From 9c5b2b0d409304c2e3c1f4d1c9bb4958e1d46f8f Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Wed, 13 Sep 2017 10:03:31 -0400 Subject: drm/amdgpu: Pulling old prepare and submit for flip back This is needed to ensure every single DC commit builds. Reverting this again when it's no longer needed by DC. This reverts commit 98da65d5e32583d89a1b1c760293b601816a98d3. Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 138 ++++++++++++++++++++++------ drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 15 +++ 2 files changed, 124 insertions(+), 29 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index 6ad243293a78..e23b89cc6636 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -138,11 +138,52 @@ static void amdgpu_unpin_work_func(struct work_struct *__work) kfree(work); } -int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc, - struct drm_framebuffer *fb, - struct drm_pending_vblank_event *event, - uint32_t page_flip_flags, uint32_t target, - struct drm_modeset_acquire_ctx *ctx) + +static void amdgpu_flip_work_cleanup(struct amdgpu_flip_work *work) +{ + int i; + + amdgpu_bo_unref(&work->old_abo); + dma_fence_put(work->excl); + for (i = 0; i < work->shared_count; ++i) + dma_fence_put(work->shared[i]); + kfree(work->shared); + kfree(work); +} + +static void amdgpu_flip_cleanup_unreserve(struct amdgpu_flip_work *work, + struct amdgpu_bo *new_abo) +{ + amdgpu_bo_unreserve(new_abo); + amdgpu_flip_work_cleanup(work); +} + +static void amdgpu_flip_cleanup_unpin(struct amdgpu_flip_work *work, + struct amdgpu_bo *new_abo) +{ + if (unlikely(amdgpu_bo_unpin(new_abo) != 0)) + DRM_ERROR("failed to unpin new abo in error path\n"); + amdgpu_flip_cleanup_unreserve(work, new_abo); +} + +void amdgpu_crtc_cleanup_flip_ctx(struct amdgpu_flip_work *work, + struct amdgpu_bo *new_abo) +{ + if (unlikely(amdgpu_bo_reserve(new_abo, true) != 0)) { + DRM_ERROR("failed to reserve new abo in error path\n"); + amdgpu_flip_work_cleanup(work); + return; + } + amdgpu_flip_cleanup_unpin(work, new_abo); +} + +int amdgpu_crtc_prepare_flip(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + struct drm_pending_vblank_event *event, + uint32_t page_flip_flags, + uint32_t target, + struct amdgpu_flip_work **work_p, + struct amdgpu_bo **new_abo_p) { struct drm_device *dev = crtc->dev; struct amdgpu_device *adev = dev->dev_private; @@ -155,7 +196,7 @@ int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc, unsigned long flags; u64 tiling_flags; u64 base; - int i, r; + int r; work = kzalloc(sizeof *work, GFP_KERNEL); if (work == NULL) @@ -216,41 +257,80 @@ int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc, spin_unlock_irqrestore(&crtc->dev->event_lock, flags); r = -EBUSY; goto pflip_cleanup; + } + spin_unlock_irqrestore(&crtc->dev->event_lock, flags); + + *work_p = work; + *new_abo_p = new_abo; + + return 0; + +pflip_cleanup: + amdgpu_crtc_cleanup_flip_ctx(work, new_abo); + return r; + +unpin: + amdgpu_flip_cleanup_unpin(work, new_abo); + return r; + +unreserve: + amdgpu_flip_cleanup_unreserve(work, new_abo); + return r; +cleanup: + amdgpu_flip_work_cleanup(work); + return r; + +} + +void amdgpu_crtc_submit_flip(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + struct amdgpu_flip_work *work, + struct amdgpu_bo *new_abo) +{ + unsigned long flags; + struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); + + spin_lock_irqsave(&crtc->dev->event_lock, flags); amdgpu_crtc->pflip_status = AMDGPU_FLIP_PENDING; amdgpu_crtc->pflip_works = work; - - DRM_DEBUG_DRIVER("crtc:%d[%p], pflip_stat:AMDGPU_FLIP_PENDING, work: %p,\n", - amdgpu_crtc->crtc_id, amdgpu_crtc, work); /* update crtc fb */ crtc->primary->fb = fb; spin_unlock_irqrestore(&crtc->dev->event_lock, flags); + + DRM_DEBUG_DRIVER( + "crtc:%d[%p], pflip_stat:AMDGPU_FLIP_PENDING, work: %p,\n", + amdgpu_crtc->crtc_id, amdgpu_crtc, work); + amdgpu_flip_work_func(&work->flip_work.work); - return 0; +} -pflip_cleanup: - if (unlikely(amdgpu_bo_reserve(new_abo, false) != 0)) { - DRM_ERROR("failed to reserve new abo in error path\n"); - goto cleanup; - } -unpin: - if (unlikely(amdgpu_bo_unpin(new_abo) != 0)) { - DRM_ERROR("failed to unpin new abo in error path\n"); - } -unreserve: - amdgpu_bo_unreserve(new_abo); +int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + struct drm_pending_vblank_event *event, + uint32_t page_flip_flags, + uint32_t target, + struct drm_modeset_acquire_ctx *ctx) +{ + struct amdgpu_bo *new_abo; + struct amdgpu_flip_work *work; + int r; -cleanup: - amdgpu_bo_unref(&work->old_abo); - dma_fence_put(work->excl); - for (i = 0; i < work->shared_count; ++i) - dma_fence_put(work->shared[i]); - kfree(work->shared); - kfree(work); + r = amdgpu_crtc_prepare_flip(crtc, + fb, + event, + page_flip_flags, + target, + &work, + &new_abo); + if (r) + return r; - return r; + amdgpu_crtc_submit_flip(crtc, fb, work, new_abo); + + return 0; } int amdgpu_crtc_set_config(struct drm_mode_set *set, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index 2af2678ddaf6..109a3833c3a8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -587,6 +587,21 @@ int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc, struct drm_pending_vblank_event *event, uint32_t page_flip_flags, uint32_t target, struct drm_modeset_acquire_ctx *ctx); +void amdgpu_crtc_cleanup_flip_ctx(struct amdgpu_flip_work *work, + struct amdgpu_bo *new_abo); +int amdgpu_crtc_prepare_flip(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + struct drm_pending_vblank_event *event, + uint32_t page_flip_flags, + uint32_t target, + struct amdgpu_flip_work **work, + struct amdgpu_bo **new_abo); + +void amdgpu_crtc_submit_flip(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + struct amdgpu_flip_work *work, + struct amdgpu_bo *new_abo); + extern const struct drm_mode_config_funcs amdgpu_mode_funcs; #endif -- cgit From 4562236b3bc0a28aeb6ee93b2d8a849a4c4e1c7c Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 12 Sep 2017 15:58:20 -0400 Subject: drm/amd/dc: Add dc display driver (v2) Supported DCE versions: 8.0, 10.0, 11.0, 11.2 v2: rebase against 4.11 Signed-off-by: Harry Wentland Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/Kconfig | 1 + drivers/gpu/drm/amd/amdgpu/Makefile | 17 +- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 15 + drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 93 +- drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 4 + drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c | 5 - drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c | 29 +- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 85 +- drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 2 +- drivers/gpu/drm/amd/amdgpu/cik.c | 9 + drivers/gpu/drm/amd/amdgpu/vi.c | 21 + drivers/gpu/drm/amd/display/Kconfig | 28 + drivers/gpu/drm/amd/display/Makefile | 22 + drivers/gpu/drm/amd/display/amdgpu_dm/Makefile | 17 + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 1564 ++++++++ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 171 + .../drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 484 +++ .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c | 829 ++++ .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h | 122 + .../amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 443 ++ .../amd/display/amdgpu_dm/amdgpu_dm_mst_types.h | 36 + .../drm/amd/display/amdgpu_dm/amdgpu_dm_services.c | 463 +++ .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 3150 +++++++++++++++ .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.h | 101 + drivers/gpu/drm/amd/display/dc/Makefile | 28 + drivers/gpu/drm/amd/display/dc/basics/Makefile | 11 + drivers/gpu/drm/amd/display/dc/basics/conversion.c | 223 ++ drivers/gpu/drm/amd/display/dc/basics/conversion.h | 51 + drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c | 691 ++++ drivers/gpu/drm/amd/display/dc/basics/fixpt32_32.c | 221 + .../gpu/drm/amd/display/dc/basics/grph_object_id.c | 134 + .../gpu/drm/amd/display/dc/basics/log_helpers.c | 100 + drivers/gpu/drm/amd/display/dc/basics/logger.c | 457 +++ drivers/gpu/drm/amd/display/dc/basics/logger.h | 67 + .../drm/amd/display/dc/basics/register_logger.c | 197 + .../gpu/drm/amd/display/dc/basics/signal_types.c | 116 + drivers/gpu/drm/amd/display/dc/basics/vector.c | 307 ++ drivers/gpu/drm/amd/display/dc/bios/Makefile | 24 + drivers/gpu/drm/amd/display/dc/bios/bios_parser.c | 4220 ++++++++++++++++++++ drivers/gpu/drm/amd/display/dc/bios/bios_parser.h | 33 + .../drm/amd/display/dc/bios/bios_parser_helper.c | 82 + .../drm/amd/display/dc/bios/bios_parser_helper.h | 40 + .../amd/display/dc/bios/bios_parser_interface.c | 50 + .../display/dc/bios/bios_parser_types_internal.h | 72 + .../gpu/drm/amd/display/dc/bios/command_table.c | 2609 ++++++++++++ .../gpu/drm/amd/display/dc/bios/command_table.h | 112 + .../drm/amd/display/dc/bios/command_table_helper.c | 288 ++ .../drm/amd/display/dc/bios/command_table_helper.h | 90 + .../dc/bios/dce110/command_table_helper_dce110.c | 364 ++ .../dc/bios/dce110/command_table_helper_dce110.h | 34 + .../dc/bios/dce112/command_table_helper_dce112.c | 418 ++ .../dc/bios/dce112/command_table_helper_dce112.h | 34 + .../dc/bios/dce80/command_table_helper_dce80.c | 354 ++ .../dc/bios/dce80/command_table_helper_dce80.h | 33 + drivers/gpu/drm/amd/display/dc/calcs/Makefile | 10 + .../gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c | 3108 ++++++++++++++ drivers/gpu/drm/amd/display/dc/calcs/bw_fixed.c | 299 ++ drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c | 1382 +++++++ drivers/gpu/drm/amd/display/dc/core/dc.c | 1846 +++++++++ drivers/gpu/drm/amd/display/dc/core/dc_debug.c | 270 ++ .../gpu/drm/amd/display/dc/core/dc_hw_sequencer.c | 93 + drivers/gpu/drm/amd/display/dc/core/dc_link.c | 1899 +++++++++ drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c | 1098 +++++ drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 2462 ++++++++++++ drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 222 + drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 1934 +++++++++ drivers/gpu/drm/amd/display/dc/core/dc_sink.c | 113 + drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 141 + drivers/gpu/drm/amd/display/dc/core/dc_surface.c | 213 + drivers/gpu/drm/amd/display/dc/core/dc_target.c | 334 ++ drivers/gpu/drm/amd/display/dc/dc.h | 780 ++++ drivers/gpu/drm/amd/display/dc/dc_bios_types.h | 224 ++ drivers/gpu/drm/amd/display/dc/dc_ddc_types.h | 115 + drivers/gpu/drm/amd/display/dc/dc_dp_types.h | 105 + drivers/gpu/drm/amd/display/dc/dc_helper.c | 144 + drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 588 +++ drivers/gpu/drm/amd/display/dc/dc_types.h | 493 +++ drivers/gpu/drm/amd/display/dc/dce/Makefile | 14 + drivers/gpu/drm/amd/display/dc/dce/dce_audio.c | 920 +++++ drivers/gpu/drm/amd/display/dc/dce/dce_audio.h | 145 + .../gpu/drm/amd/display/dc/dce/dce_clock_source.c | 1264 ++++++ .../gpu/drm/amd/display/dc/dce/dce_clock_source.h | 109 + drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c | 195 + drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h | 250 ++ .../gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 2176 ++++++++++ .../gpu/drm/amd/display/dc/dce/dce_link_encoder.h | 363 ++ drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c | 384 ++ drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h | 217 + .../gpu/drm/amd/display/dc/dce/dce_scl_filters.c | 501 +++ .../drm/amd/display/dc/dce/dce_stream_encoder.c | 1302 ++++++ .../drm/amd/display/dc/dce/dce_stream_encoder.h | 564 +++ drivers/gpu/drm/amd/display/dc/dce/dce_transform.c | 1002 +++++ drivers/gpu/drm/amd/display/dc/dce/dce_transform.h | 313 ++ drivers/gpu/drm/amd/display/dc/dce100/Makefile | 23 + .../amd/display/dc/dce100/dce100_hw_sequencer.c | 140 + .../amd/display/dc/dce100/dce100_hw_sequencer.h | 36 + .../drm/amd/display/dc/dce100/dce100_resource.c | 1085 +++++ .../drm/amd/display/dc/dce100/dce100_resource.h | 19 + drivers/gpu/drm/amd/display/dc/dce110/Makefile | 15 + .../drm/amd/display/dc/dce110/dce110_compressor.c | 859 ++++ .../drm/amd/display/dc/dce110/dce110_compressor.h | 78 + .../amd/display/dc/dce110/dce110_hw_sequencer.c | 1978 +++++++++ .../amd/display/dc/dce110/dce110_hw_sequencer.h | 62 + drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.c | 62 + drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h | 76 + .../drm/amd/display/dc/dce110/dce110_ipp_cursor.c | 253 ++ .../drm/amd/display/dc/dce110/dce110_ipp_gamma.c | 303 ++ .../drm/amd/display/dc/dce110/dce110_mem_input.c | 535 +++ .../drm/amd/display/dc/dce110/dce110_mem_input.h | 131 + .../drm/amd/display/dc/dce110/dce110_mem_input_v.c | 1081 +++++ .../drm/amd/display/dc/dce110/dce110_mem_input_v.h | 94 + drivers/gpu/drm/amd/display/dc/dce110/dce110_opp.c | 77 + drivers/gpu/drm/amd/display/dc/dce110/dce110_opp.h | 149 + .../gpu/drm/amd/display/dc/dce110/dce110_opp_csc.c | 363 ++ .../drm/amd/display/dc/dce110/dce110_opp_csc_v.c | 738 ++++ .../amd/display/dc/dce110/dce110_opp_formatter.c | 627 +++ .../drm/amd/display/dc/dce110/dce110_opp_regamma.c | 537 +++ .../amd/display/dc/dce110/dce110_opp_regamma_v.c | 551 +++ .../gpu/drm/amd/display/dc/dce110/dce110_opp_v.c | 63 + .../gpu/drm/amd/display/dc/dce110/dce110_opp_v.h | 56 + .../drm/amd/display/dc/dce110/dce110_resource.c | 1413 +++++++ .../drm/amd/display/dc/dce110/dce110_resource.h | 56 + .../display/dc/dce110/dce110_timing_generator.c | 1953 +++++++++ .../display/dc/dce110/dce110_timing_generator.h | 273 ++ .../display/dc/dce110/dce110_timing_generator_v.c | 743 ++++ .../display/dc/dce110/dce110_timing_generator_v.h | 33 + .../drm/amd/display/dc/dce110/dce110_transform_v.c | 704 ++++ .../drm/amd/display/dc/dce110/dce110_transform_v.h | 37 + .../gpu/drm/amd/display/dc/dce110/dce110_types.h | 30 + drivers/gpu/drm/amd/display/dc/dce112/Makefile | 11 + .../drm/amd/display/dc/dce112/dce112_compressor.c | 859 ++++ .../drm/amd/display/dc/dce112/dce112_compressor.h | 78 + .../amd/display/dc/dce112/dce112_hw_sequencer.c | 166 + .../amd/display/dc/dce112/dce112_hw_sequencer.h | 36 + .../drm/amd/display/dc/dce112/dce112_mem_input.c | 54 + .../drm/amd/display/dc/dce112/dce112_mem_input.h | 38 + drivers/gpu/drm/amd/display/dc/dce112/dce112_opp.c | 72 + drivers/gpu/drm/amd/display/dc/dce112/dce112_opp.h | 48 + .../amd/display/dc/dce112/dce112_opp_formatter.c | 215 + .../drm/amd/display/dc/dce112/dce112_resource.c | 1418 +++++++ .../drm/amd/display/dc/dce112/dce112_resource.h | 55 + drivers/gpu/drm/amd/display/dc/dce80/Makefile | 16 + .../drm/amd/display/dc/dce80/dce80_compressor.c | 839 ++++ .../drm/amd/display/dc/dce80/dce80_compressor.h | 78 + .../drm/amd/display/dc/dce80/dce80_hw_sequencer.c | 141 + .../drm/amd/display/dc/dce80/dce80_hw_sequencer.h | 36 + drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.c | 64 + drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.h | 47 + .../gpu/drm/amd/display/dc/dce80/dce80_ipp_gamma.c | 76 + .../gpu/drm/amd/display/dc/dce80/dce80_mem_input.c | 83 + .../gpu/drm/amd/display/dc/dce80/dce80_mem_input.h | 36 + drivers/gpu/drm/amd/display/dc/dce80/dce80_opp.c | 136 + drivers/gpu/drm/amd/display/dc/dce80/dce80_opp.h | 130 + .../gpu/drm/amd/display/dc/dce80/dce80_opp_csc.c | 363 ++ .../drm/amd/display/dc/dce80/dce80_opp_formatter.c | 577 +++ .../drm/amd/display/dc/dce80/dce80_opp_regamma.c | 543 +++ .../gpu/drm/amd/display/dc/dce80/dce80_resource.c | 1063 +++++ .../gpu/drm/amd/display/dc/dce80/dce80_resource.h | 39 + .../amd/display/dc/dce80/dce80_timing_generator.c | 241 ++ .../amd/display/dc/dce80/dce80_timing_generator.h | 45 + drivers/gpu/drm/amd/display/dc/dm_helpers.h | 101 + drivers/gpu/drm/amd/display/dc/dm_services.h | 424 ++ drivers/gpu/drm/amd/display/dc/dm_services_types.h | 242 ++ drivers/gpu/drm/amd/display/dc/gpio/Makefile | 38 + .../amd/display/dc/gpio/dce110/hw_factory_dce110.c | 178 + .../amd/display/dc/gpio/dce110/hw_factory_dce110.h | 32 + .../display/dc/gpio/dce110/hw_translate_dce110.c | 387 ++ .../display/dc/gpio/dce110/hw_translate_dce110.h | 34 + .../amd/display/dc/gpio/dce80/hw_factory_dce80.c | 173 + .../amd/display/dc/gpio/dce80/hw_factory_dce80.h | 32 + .../amd/display/dc/gpio/dce80/hw_translate_dce80.c | 411 ++ .../amd/display/dc/gpio/dce80/hw_translate_dce80.h | 32 + drivers/gpu/drm/amd/display/dc/gpio/ddc_regs.h | 150 + .../display/dc/gpio/diagnostics/hw_factory_diag.c | 63 + .../display/dc/gpio/diagnostics/hw_factory_diag.h | 32 + .../dc/gpio/diagnostics/hw_translate_diag.c | 40 + .../dc/gpio/diagnostics/hw_translate_diag.h | 34 + drivers/gpu/drm/amd/display/dc/gpio/gpio_base.c | 272 ++ drivers/gpu/drm/amd/display/dc/gpio/gpio_regs.h | 45 + drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c | 592 +++ drivers/gpu/drm/amd/display/dc/gpio/gpio_service.h | 56 + drivers/gpu/drm/amd/display/dc/gpio/hpd_regs.h | 79 + drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c | 243 ++ drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.h | 46 + drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c | 93 + drivers/gpu/drm/amd/display/dc/gpio/hw_factory.h | 74 + drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.c | 205 + drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.h | 144 + drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.c | 175 + drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.h | 46 + drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c | 75 + drivers/gpu/drm/amd/display/dc/gpio/hw_translate.h | 50 + drivers/gpu/drm/amd/display/dc/gpu/Makefile | 36 + .../display/dc/gpu/dce110/display_clock_dce110.c | 1035 +++++ .../display/dc/gpu/dce110/display_clock_dce110.h | 53 + .../display/dc/gpu/dce112/display_clock_dce112.c | 964 +++++ .../display/dc/gpu/dce112/display_clock_dce112.h | 114 + .../amd/display/dc/gpu/dce80/display_clock_dce80.c | 934 +++++ .../amd/display/dc/gpu/dce80/display_clock_dce80.h | 57 + drivers/gpu/drm/amd/display/dc/gpu/display_clock.c | 217 + drivers/gpu/drm/amd/display/dc/gpu/display_clock.h | 89 + drivers/gpu/drm/amd/display/dc/gpu/divider_range.c | 127 + drivers/gpu/drm/amd/display/dc/gpu/divider_range.h | 62 + drivers/gpu/drm/amd/display/dc/i2caux/Makefile | 58 + drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.c | 567 +++ drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.h | 117 + .../amd/display/dc/i2caux/dce100/i2caux_dce100.c | 112 + .../amd/display/dc/i2caux/dce100/i2caux_dce100.h | 32 + .../display/dc/i2caux/dce110/aux_engine_dce110.c | 456 +++ .../display/dc/i2caux/dce110/aux_engine_dce110.h | 78 + .../dc/i2caux/dce110/i2c_hw_engine_dce110.c | 577 +++ .../dc/i2caux/dce110/i2c_hw_engine_dce110.h | 214 + .../dc/i2caux/dce110/i2c_sw_engine_dce110.c | 171 + .../dc/i2caux/dce110/i2c_sw_engine_dce110.h | 43 + .../amd/display/dc/i2caux/dce110/i2caux_dce110.c | 323 ++ .../amd/display/dc/i2caux/dce110/i2caux_dce110.h | 53 + .../amd/display/dc/i2caux/dce112/i2caux_dce112.c | 140 + .../amd/display/dc/i2caux/dce112/i2caux_dce112.h | 32 + .../display/dc/i2caux/dce80/i2c_hw_engine_dce80.c | 885 ++++ .../display/dc/i2caux/dce80/i2c_hw_engine_dce80.h | 54 + .../display/dc/i2caux/dce80/i2c_sw_engine_dce80.c | 184 + .../display/dc/i2caux/dce80/i2c_sw_engine_dce80.h | 43 + .../drm/amd/display/dc/i2caux/dce80/i2caux_dce80.c | 295 ++ .../drm/amd/display/dc/i2caux/dce80/i2caux_dce80.h | 38 + .../display/dc/i2caux/diagnostics/i2caux_diag.c | 108 + .../display/dc/i2caux/diagnostics/i2caux_diag.h | 32 + drivers/gpu/drm/amd/display/dc/i2caux/engine.h | 120 + .../gpu/drm/amd/display/dc/i2caux/engine_base.c | 53 + drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.c | 121 + drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.h | 113 + .../amd/display/dc/i2caux/i2c_generic_hw_engine.c | 286 ++ .../amd/display/dc/i2caux/i2c_generic_hw_engine.h | 77 + .../gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.c | 246 ++ .../gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.h | 80 + .../gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.c | 610 +++ .../gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.h | 81 + drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c | 459 +++ drivers/gpu/drm/amd/display/dc/i2caux/i2caux.h | 122 + .../gpu/drm/amd/display/dc/inc/bandwidth_calcs.h | 503 +++ drivers/gpu/drm/amd/display/dc/inc/bw_fixed.h | 63 + drivers/gpu/drm/amd/display/dc/inc/clock_source.h | 178 + drivers/gpu/drm/amd/display/dc/inc/compressor.h | 93 + drivers/gpu/drm/amd/display/dc/inc/core_dc.h | 50 + drivers/gpu/drm/amd/display/dc/inc/core_status.h | 47 + drivers/gpu/drm/amd/display/dc/inc/core_types.h | 319 ++ drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h | 145 + drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h | 60 + drivers/gpu/drm/amd/display/dc/inc/gamma_calcs.h | 19 + drivers/gpu/drm/amd/display/dc/inc/gamma_types.h | 38 + drivers/gpu/drm/amd/display/dc/inc/hw/audio.h | 62 + drivers/gpu/drm/amd/display/dc/inc/hw/gpio.h | 86 + drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h | 74 + drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h | 121 + .../gpu/drm/amd/display/dc/inc/hw/link_encoder.h | 263 ++ drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h | 106 + drivers/gpu/drm/amd/display/dc/inc/hw/opp.h | 322 ++ .../gpu/drm/amd/display/dc/inc/hw/stream_encoder.h | 121 + .../drm/amd/display/dc/inc/hw/timing_generator.h | 162 + drivers/gpu/drm/amd/display/dc/inc/hw/transform.h | 179 + drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 156 + drivers/gpu/drm/amd/display/dc/inc/link_hwss.h | 73 + drivers/gpu/drm/amd/display/dc/inc/reg_helper.h | 290 ++ drivers/gpu/drm/amd/display/dc/inc/resource.h | 164 + drivers/gpu/drm/amd/display/dc/irq/Makefile | 28 + .../amd/display/dc/irq/dce110/irq_service_dce110.c | 367 ++ .../amd/display/dc/irq/dce110/irq_service_dce110.h | 48 + .../amd/display/dc/irq/dce80/irq_service_dce80.c | 283 ++ .../amd/display/dc/irq/dce80/irq_service_dce80.h | 35 + drivers/gpu/drm/amd/display/dc/irq/irq_service.c | 163 + drivers/gpu/drm/amd/display/dc/irq/irq_service.h | 85 + drivers/gpu/drm/amd/display/dc/irq_types.h | 185 + drivers/gpu/drm/amd/display/dc/os_types.h | 61 + drivers/gpu/drm/amd/display/dc/virtual/Makefile | 9 + .../amd/display/dc/virtual/virtual_link_encoder.c | 150 + .../amd/display/dc/virtual/virtual_link_encoder.h | 34 + .../display/dc/virtual/virtual_stream_encoder.c | 132 + .../display/dc/virtual/virtual_stream_encoder.h | 39 + .../display/include/asic_capability_interface.h | 55 + .../amd/display/include/asic_capability_types.h | 116 + drivers/gpu/drm/amd/display/include/audio_types.h | 106 + .../amd/display/include/bios_parser_interface.h | 44 + .../drm/amd/display/include/bios_parser_types.h | 338 ++ drivers/gpu/drm/amd/display/include/dal_asic_id.h | 125 + .../drm/amd/display/include/dal_register_logger.h | 42 + drivers/gpu/drm/amd/display/include/dal_types.h | 44 + .../drm/amd/display/include/ddc_service_types.h | 189 + .../amd/display/include/display_clock_interface.h | 175 + drivers/gpu/drm/amd/display/include/dpcd_defs.h | 742 ++++ drivers/gpu/drm/amd/display/include/fixed31_32.h | 390 ++ drivers/gpu/drm/amd/display/include/fixed32_32.h | 83 + .../gpu/drm/amd/display/include/gpio_interface.h | 92 + .../amd/display/include/gpio_service_interface.h | 105 + drivers/gpu/drm/amd/display/include/gpio_types.h | 332 ++ .../amd/display/include/grph_object_ctrl_defs.h | 407 ++ .../gpu/drm/amd/display/include/grph_object_defs.h | 140 + .../gpu/drm/amd/display/include/grph_object_id.h | 256 ++ .../drm/amd/display/include/hw_sequencer_types.h | 105 + .../gpu/drm/amd/display/include/i2caux_interface.h | 89 + .../gpu/drm/amd/display/include/irq_interface.h | 31 + .../amd/display/include/irq_service_interface.h | 51 + .../drm/amd/display/include/link_service_types.h | 232 ++ .../gpu/drm/amd/display/include/logger_interface.h | 140 + drivers/gpu/drm/amd/display/include/logger_types.h | 95 + .../gpu/drm/amd/display/include/set_mode_types.h | 127 + drivers/gpu/drm/amd/display/include/signal_types.h | 59 + drivers/gpu/drm/amd/display/include/vector.h | 150 + drivers/gpu/drm/amd/display/modules/color/color.c | 2094 ++++++++++ .../gpu/drm/amd/display/modules/freesync/Makefile | 10 + .../drm/amd/display/modules/freesync/freesync.c | 1158 ++++++ .../gpu/drm/amd/display/modules/inc/mod_color.h | 179 + .../gpu/drm/amd/display/modules/inc/mod_freesync.h | 149 + .../gpu/drm/amd/display/modules/inc/mod_power.h | 112 + drivers/gpu/drm/amd/display/modules/power/power.c | 784 ++++ 315 files changed, 99491 insertions(+), 37 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/Kconfig create mode 100644 drivers/gpu/drm/amd/display/Makefile create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/Makefile create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h create mode 100644 drivers/gpu/drm/amd/display/dc/Makefile create mode 100644 drivers/gpu/drm/amd/display/dc/basics/Makefile create mode 100644 drivers/gpu/drm/amd/display/dc/basics/conversion.c create mode 100644 drivers/gpu/drm/amd/display/dc/basics/conversion.h create mode 100644 drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c create mode 100644 drivers/gpu/drm/amd/display/dc/basics/fixpt32_32.c create mode 100644 drivers/gpu/drm/amd/display/dc/basics/grph_object_id.c create mode 100644 drivers/gpu/drm/amd/display/dc/basics/log_helpers.c create mode 100644 drivers/gpu/drm/amd/display/dc/basics/logger.c create mode 100644 drivers/gpu/drm/amd/display/dc/basics/logger.h create mode 100644 drivers/gpu/drm/amd/display/dc/basics/register_logger.c create mode 100644 drivers/gpu/drm/amd/display/dc/basics/signal_types.c create mode 100644 drivers/gpu/drm/amd/display/dc/basics/vector.c create mode 100644 drivers/gpu/drm/amd/display/dc/bios/Makefile create mode 100644 drivers/gpu/drm/amd/display/dc/bios/bios_parser.c create mode 100644 drivers/gpu/drm/amd/display/dc/bios/bios_parser.h create mode 100644 drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.c create mode 100644 drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.h create mode 100644 drivers/gpu/drm/amd/display/dc/bios/bios_parser_interface.c create mode 100644 drivers/gpu/drm/amd/display/dc/bios/bios_parser_types_internal.h create mode 100644 drivers/gpu/drm/amd/display/dc/bios/command_table.c create mode 100644 drivers/gpu/drm/amd/display/dc/bios/command_table.h create mode 100644 drivers/gpu/drm/amd/display/dc/bios/command_table_helper.c create mode 100644 drivers/gpu/drm/amd/display/dc/bios/command_table_helper.h create mode 100644 drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.c create mode 100644 drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.h create mode 100644 drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c create mode 100644 drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.h create mode 100644 drivers/gpu/drm/amd/display/dc/bios/dce80/command_table_helper_dce80.c create mode 100644 drivers/gpu/drm/amd/display/dc/bios/dce80/command_table_helper_dce80.h create mode 100644 drivers/gpu/drm/amd/display/dc/calcs/Makefile create mode 100644 drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c create mode 100644 drivers/gpu/drm/amd/display/dc/calcs/bw_fixed.c create mode 100644 drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c create mode 100644 drivers/gpu/drm/amd/display/dc/core/dc.c create mode 100644 drivers/gpu/drm/amd/display/dc/core/dc_debug.c create mode 100644 drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c create mode 100644 drivers/gpu/drm/amd/display/dc/core/dc_link.c create mode 100644 drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c create mode 100644 drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c create mode 100644 drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c create mode 100644 drivers/gpu/drm/amd/display/dc/core/dc_resource.c create mode 100644 drivers/gpu/drm/amd/display/dc/core/dc_sink.c create mode 100644 drivers/gpu/drm/amd/display/dc/core/dc_stream.c create mode 100644 drivers/gpu/drm/amd/display/dc/core/dc_surface.c create mode 100644 drivers/gpu/drm/amd/display/dc/core/dc_target.c create mode 100644 drivers/gpu/drm/amd/display/dc/dc.h create mode 100644 drivers/gpu/drm/amd/display/dc/dc_bios_types.h create mode 100644 drivers/gpu/drm/amd/display/dc/dc_ddc_types.h create mode 100644 drivers/gpu/drm/amd/display/dc/dc_dp_types.h create mode 100644 drivers/gpu/drm/amd/display/dc/dc_helper.c create mode 100644 drivers/gpu/drm/amd/display/dc/dc_hw_types.h create mode 100644 drivers/gpu/drm/amd/display/dc/dc_types.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce/Makefile create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_audio.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_audio.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_scl_filters.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_transform.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_transform.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce100/Makefile create mode 100644 drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/Makefile create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_cursor.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_gamma.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_opp.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_opp.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_formatter.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_types.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce112/Makefile create mode 100644 drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce112/dce112_mem_input.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce112/dce112_mem_input.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce112/dce112_opp.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce112/dce112_opp.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce112/dce112_opp_formatter.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/Makefile create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp_gamma.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_opp.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_opp.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_csc.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_formatter.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_regamma.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.h create mode 100644 drivers/gpu/drm/amd/display/dc/dm_helpers.h create mode 100644 drivers/gpu/drm/amd/display/dc/dm_services.h create mode 100644 drivers/gpu/drm/amd/display/dc/dm_services_types.h create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/Makefile create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dce110/hw_factory_dce110.c create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dce110/hw_factory_dce110.h create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dce110/hw_translate_dce110.c create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dce110/hw_translate_dce110.h create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dce80/hw_factory_dce80.c create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dce80/hw_factory_dce80.h create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dce80/hw_translate_dce80.c create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dce80/hw_translate_dce80.h create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/ddc_regs.h create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/diagnostics/hw_factory_diag.c create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/diagnostics/hw_factory_diag.h create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/diagnostics/hw_translate_diag.c create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/diagnostics/hw_translate_diag.h create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/gpio_base.c create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/gpio_regs.h create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/gpio_service.h create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/hpd_regs.h create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.h create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/hw_factory.h create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.c create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.h create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.c create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.h create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/hw_translate.h create mode 100644 drivers/gpu/drm/amd/display/dc/gpu/Makefile create mode 100644 drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c create mode 100644 drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.h create mode 100644 drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c create mode 100644 drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h create mode 100644 drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c create mode 100644 drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.h create mode 100644 drivers/gpu/drm/amd/display/dc/gpu/display_clock.c create mode 100644 drivers/gpu/drm/amd/display/dc/gpu/display_clock.h create mode 100644 drivers/gpu/drm/amd/display/dc/gpu/divider_range.c create mode 100644 drivers/gpu/drm/amd/display/dc/gpu/divider_range.h create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/Makefile create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.c create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.h create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce100/i2caux_dce100.c create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce100/i2caux_dce100.h create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.h create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.c create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.h create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_sw_engine_dce110.c create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_sw_engine_dce110.h create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.c create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.h create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.c create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.h create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.c create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.h create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_sw_engine_dce80.c create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_sw_engine_dce80.h create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2caux_dce80.c create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2caux_dce80.h create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.c create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.h create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/engine.h create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/engine_base.c create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.c create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.h create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/i2c_generic_hw_engine.c create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/i2c_generic_hw_engine.h create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.c create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.h create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.c create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.h create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/i2caux.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/bandwidth_calcs.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/bw_fixed.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/clock_source.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/compressor.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/core_dc.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/core_status.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/core_types.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/gamma_calcs.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/gamma_types.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw/audio.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw/gpio.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw/opp.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw/transform.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/link_hwss.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/reg_helper.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/resource.h create mode 100644 drivers/gpu/drm/amd/display/dc/irq/Makefile create mode 100644 drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c create mode 100644 drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.h create mode 100644 drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c create mode 100644 drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.h create mode 100644 drivers/gpu/drm/amd/display/dc/irq/irq_service.c create mode 100644 drivers/gpu/drm/amd/display/dc/irq/irq_service.h create mode 100644 drivers/gpu/drm/amd/display/dc/irq_types.h create mode 100644 drivers/gpu/drm/amd/display/dc/os_types.h create mode 100644 drivers/gpu/drm/amd/display/dc/virtual/Makefile create mode 100644 drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c create mode 100644 drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.h create mode 100644 drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c create mode 100644 drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.h create mode 100644 drivers/gpu/drm/amd/display/include/asic_capability_interface.h create mode 100644 drivers/gpu/drm/amd/display/include/asic_capability_types.h create mode 100644 drivers/gpu/drm/amd/display/include/audio_types.h create mode 100644 drivers/gpu/drm/amd/display/include/bios_parser_interface.h create mode 100644 drivers/gpu/drm/amd/display/include/bios_parser_types.h create mode 100644 drivers/gpu/drm/amd/display/include/dal_asic_id.h create mode 100644 drivers/gpu/drm/amd/display/include/dal_register_logger.h create mode 100644 drivers/gpu/drm/amd/display/include/dal_types.h create mode 100644 drivers/gpu/drm/amd/display/include/ddc_service_types.h create mode 100644 drivers/gpu/drm/amd/display/include/display_clock_interface.h create mode 100644 drivers/gpu/drm/amd/display/include/dpcd_defs.h create mode 100644 drivers/gpu/drm/amd/display/include/fixed31_32.h create mode 100644 drivers/gpu/drm/amd/display/include/fixed32_32.h create mode 100644 drivers/gpu/drm/amd/display/include/gpio_interface.h create mode 100644 drivers/gpu/drm/amd/display/include/gpio_service_interface.h create mode 100644 drivers/gpu/drm/amd/display/include/gpio_types.h create mode 100644 drivers/gpu/drm/amd/display/include/grph_object_ctrl_defs.h create mode 100644 drivers/gpu/drm/amd/display/include/grph_object_defs.h create mode 100644 drivers/gpu/drm/amd/display/include/grph_object_id.h create mode 100644 drivers/gpu/drm/amd/display/include/hw_sequencer_types.h create mode 100644 drivers/gpu/drm/amd/display/include/i2caux_interface.h create mode 100644 drivers/gpu/drm/amd/display/include/irq_interface.h create mode 100644 drivers/gpu/drm/amd/display/include/irq_service_interface.h create mode 100644 drivers/gpu/drm/amd/display/include/link_service_types.h create mode 100644 drivers/gpu/drm/amd/display/include/logger_interface.h create mode 100644 drivers/gpu/drm/amd/display/include/logger_types.h create mode 100644 drivers/gpu/drm/amd/display/include/set_mode_types.h create mode 100644 drivers/gpu/drm/amd/display/include/signal_types.h create mode 100644 drivers/gpu/drm/amd/display/include/vector.h create mode 100644 drivers/gpu/drm/amd/display/modules/color/color.c create mode 100644 drivers/gpu/drm/amd/display/modules/freesync/Makefile create mode 100644 drivers/gpu/drm/amd/display/modules/freesync/freesync.c create mode 100644 drivers/gpu/drm/amd/display/modules/inc/mod_color.h create mode 100644 drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h create mode 100644 drivers/gpu/drm/amd/display/modules/inc/mod_power.h create mode 100644 drivers/gpu/drm/amd/display/modules/power/power.c (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/Kconfig b/drivers/gpu/drm/amd/amdgpu/Kconfig index 26682454a446..e8af1f5e8a79 100644 --- a/drivers/gpu/drm/amd/amdgpu/Kconfig +++ b/drivers/gpu/drm/amd/amdgpu/Kconfig @@ -41,3 +41,4 @@ config DRM_AMDGPU_GART_DEBUGFS pages. Uses more memory for housekeeping, enable only for debugging. source "drivers/gpu/drm/amd/acp/Kconfig" +source "drivers/gpu/drm/amd/display/Kconfig" diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile index 25a95c95df14..454e6efeb5cf 100644 --- a/drivers/gpu/drm/amd/amdgpu/Makefile +++ b/drivers/gpu/drm/amd/amdgpu/Makefile @@ -3,13 +3,19 @@ # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. FULL_AMD_PATH=$(src)/.. +DISPLAY_FOLDER_NAME=display +FULL_AMD_DISPLAY_PATH = $(FULL_AMD_PATH)/$(DISPLAY_FOLDER_NAME) ccflags-y := -I$(FULL_AMD_PATH)/include/asic_reg \ -I$(FULL_AMD_PATH)/include \ -I$(FULL_AMD_PATH)/amdgpu \ -I$(FULL_AMD_PATH)/scheduler \ -I$(FULL_AMD_PATH)/powerplay/inc \ - -I$(FULL_AMD_PATH)/acp/include + -I$(FULL_AMD_PATH)/acp/include \ + -I$(FULL_AMD_DISPLAY_PATH) \ + -I$(FULL_AMD_DISPLAY_PATH)/include \ + -I$(FULL_AMD_DISPLAY_PATH)/dc \ + -I$(FULL_AMD_DISPLAY_PATH)/amdgpu_dm amdgpu-y := amdgpu_drv.o @@ -132,4 +138,13 @@ include $(FULL_AMD_PATH)/powerplay/Makefile amdgpu-y += $(AMD_POWERPLAY_FILES) +ifneq ($(CONFIG_DRM_AMD_DC),) + +RELATIVE_AMD_DISPLAY_PATH = ../$(DISPLAY_FOLDER_NAME) +include $(FULL_AMD_DISPLAY_PATH)/Makefile + +amdgpu-y += $(AMD_DISPLAY_FILES) + +endif + obj-$(CONFIG_DRM_AMDGPU)+= amdgpu.o diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index ebfc267467ee..2c88dd07e1bc 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -66,6 +66,7 @@ #include "amdgpu_vce.h" #include "amdgpu_vcn.h" #include "amdgpu_mn.h" +#include "amdgpu_dm.h" #include "gpu_scheduler.h" #include "amdgpu_virt.h" @@ -101,6 +102,7 @@ extern int amdgpu_vm_fragment_size; extern int amdgpu_vm_fault_stop; extern int amdgpu_vm_debug; extern int amdgpu_vm_update_mode; +extern int amdgpu_dc; extern int amdgpu_sched_jobs; extern int amdgpu_sched_hw_submission; extern int amdgpu_no_evict; @@ -1507,6 +1509,7 @@ struct amdgpu_device { /* display */ bool enable_virtual_display; struct amdgpu_mode_info mode_info; + /* For pre-DCE11. DCE11 and later are in "struct amdgpu_device->dm" */ struct work_struct hotplug_work; struct amdgpu_irq_src crtc_irq; struct amdgpu_irq_src pageflip_irq; @@ -1563,6 +1566,9 @@ struct amdgpu_device { /* GDS */ struct amdgpu_gds gds; + /* display related functionality */ + struct amdgpu_display_manager dm; + struct amdgpu_ip_block ip_blocks[AMDGPU_MAX_IP_NUM]; int num_ip_blocks; struct mutex mn_lock; @@ -1624,6 +1630,9 @@ void amdgpu_mm_wdoorbell(struct amdgpu_device *adev, u32 index, u32 v); u64 amdgpu_mm_rdoorbell64(struct amdgpu_device *adev, u32 index); void amdgpu_mm_wdoorbell64(struct amdgpu_device *adev, u32 index, u64 v); +bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type); +bool amdgpu_device_has_dc_support(struct amdgpu_device *adev); + /* * Registers read & write functions. */ @@ -1884,5 +1893,11 @@ int amdgpu_cs_find_mapping(struct amdgpu_cs_parser *parser, uint64_t addr, struct amdgpu_bo **bo, struct amdgpu_bo_va_mapping **mapping); +#if defined(CONFIG_DRM_AMD_DC) +int amdgpu_dm_display_resume(struct amdgpu_device *adev ); +#else +static inline int amdgpu_dm_display_resume(struct amdgpu_device *adev) { return 0; } +#endif + #include "amdgpu_object.h" #endif diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 3e84ddf9e3b5..226d10f288a3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -1973,6 +1974,41 @@ static void amdgpu_device_detect_sriov_bios(struct amdgpu_device *adev) } } +bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type) +{ + switch (asic_type) { +#if defined(CONFIG_DRM_AMD_DC) + case CHIP_BONAIRE: + case CHIP_HAWAII: + case CHIP_CARRIZO: + case CHIP_STONEY: + case CHIP_POLARIS11: + case CHIP_POLARIS10: + case CHIP_TONGA: + case CHIP_FIJI: +#if defined(CONFIG_DRM_AMD_DC_PRE_VEGA) + return amdgpu_dc != 0; +#else + return amdgpu_dc > 0; +#endif +#endif + default: + return false; + } +} + +/** + * amdgpu_device_has_dc_support - check if dc is supported + * + * @adev: amdgpu_device_pointer + * + * Returns true for supported, false for not supported + */ +bool amdgpu_device_has_dc_support(struct amdgpu_device *adev) +{ + return amdgpu_device_asic_has_dc_support(adev->asic_type); +} + /** * amdgpu_device_init - initialize the driver * @@ -2168,7 +2204,8 @@ int amdgpu_device_init(struct amdgpu_device *adev, goto failed; } /* init i2c buses */ - amdgpu_atombios_i2c_init(adev); + if (!amdgpu_device_has_dc_support(adev)) + amdgpu_atombios_i2c_init(adev); } /* Fence driver */ @@ -2296,7 +2333,8 @@ void amdgpu_device_fini(struct amdgpu_device *adev) adev->accel_working = false; cancel_delayed_work_sync(&adev->late_init_work); /* free i2c buses */ - amdgpu_i2c_fini(adev); + if (!amdgpu_device_has_dc_support(adev)) + amdgpu_i2c_fini(adev); amdgpu_atombios_fini(adev); kfree(adev->bios); adev->bios = NULL; @@ -2346,12 +2384,14 @@ int amdgpu_device_suspend(struct drm_device *dev, bool suspend, bool fbcon) drm_kms_helper_poll_disable(dev); - /* turn off display hw */ - drm_modeset_lock_all(dev); - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); + if (!amdgpu_device_has_dc_support(adev)) { + /* turn off display hw */ + drm_modeset_lock_all(dev); + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); + } + drm_modeset_unlock_all(dev); } - drm_modeset_unlock_all(dev); amdgpu_amdkfd_suspend(adev); @@ -2494,13 +2534,25 @@ int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon) /* blat the mode back in */ if (fbcon) { - drm_helper_resume_force_mode(dev); - /* turn on display hw */ - drm_modeset_lock_all(dev); - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); + if (!amdgpu_device_has_dc_support(adev)) { + /* pre DCE11 */ + drm_helper_resume_force_mode(dev); + + /* turn on display hw */ + drm_modeset_lock_all(dev); + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); + } + drm_modeset_unlock_all(dev); + } else { + /* + * There is no equivalent atomic helper to turn on + * display, so we defined our own function for this, + * once suspend resume is supported by the atomic + * framework this will be reworked + */ + amdgpu_dm_display_resume(adev); } - drm_modeset_unlock_all(dev); } drm_kms_helper_poll_enable(dev); @@ -2517,7 +2569,10 @@ int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon) #ifdef CONFIG_PM dev->dev->power.disable_depth++; #endif - drm_helper_hpd_irq_event(dev); + if (!amdgpu_device_has_dc_support(adev)) + drm_helper_hpd_irq_event(dev); + else + drm_kms_helper_hotplug_event(dev); #ifdef CONFIG_PM dev->dev->power.disable_depth--; #endif @@ -2814,6 +2869,7 @@ give_up_reset: */ int amdgpu_gpu_reset(struct amdgpu_device *adev) { + struct drm_atomic_state *state = NULL; int i, r; int resched; bool need_full_reset, vram_lost = false; @@ -2827,6 +2883,9 @@ int amdgpu_gpu_reset(struct amdgpu_device *adev) /* block TTM */ resched = ttm_bo_lock_delayed_workqueue(&adev->mman.bdev); + /* store modesetting */ + if (amdgpu_device_has_dc_support(adev)) + state = drm_atomic_helper_suspend(adev->ddev); /* block scheduler */ for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { @@ -2944,7 +3003,11 @@ out: } } - drm_helper_resume_force_mode(adev->ddev); + if (amdgpu_device_has_dc_support(adev)) { + r = drm_atomic_helper_resume(adev->ddev, state); + amdgpu_dm_display_resume(adev); + } else + drm_helper_resume_force_mode(adev->ddev); ttm_bo_unlock_delayed_workqueue(&adev->mman.bdev, resched); if (r) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h index f79f9ea58b17..0d22259c6d02 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h @@ -429,7 +429,7 @@ struct amdgpu_pm { uint32_t fw_version; uint32_t pcie_gen_mask; uint32_t pcie_mlw_mask; - struct amd_pp_display_configuration pm_display_cfg;/* set by DAL */ + struct amd_pp_display_configuration pm_display_cfg;/* set by dc */ }; #define R600_SSTU_DFLT 0 diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 4f98960e47f9..13cd35b70c51 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -103,6 +103,7 @@ int amdgpu_vm_debug = 0; int amdgpu_vram_page_split = 512; int amdgpu_vm_update_mode = -1; int amdgpu_exp_hw_support = 0; +int amdgpu_dc = -1; int amdgpu_sched_jobs = 32; int amdgpu_sched_hw_submission = 2; int amdgpu_no_evict = 0; @@ -207,6 +208,9 @@ module_param_named(vram_page_split, amdgpu_vram_page_split, int, 0444); MODULE_PARM_DESC(exp_hw_support, "experimental hw support (1 = enable, 0 = disable (default))"); module_param_named(exp_hw_support, amdgpu_exp_hw_support, int, 0444); +MODULE_PARM_DESC(dc, "Display Core driver (1 = enable, 0 = disable, -1 = auto (default))"); +module_param_named(dc, amdgpu_dc, int, 0444); + MODULE_PARM_DESC(sched_jobs, "the max number of jobs supported in the sw queue (default 32)"); module_param_named(sched_jobs, amdgpu_sched_jobs, int, 0444); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c index 562930b17a6d..2484dac08050 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c @@ -42,11 +42,6 @@ this contains a helper + a amdgpu fb the helper contains a pointer to amdgpu framebuffer baseclass. */ -struct amdgpu_fbdev { - struct drm_fb_helper helper; - struct amdgpu_framebuffer rfb; - struct amdgpu_device *adev; -}; static int amdgpufb_open(struct fb_info *info, int user) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c index 538e5f27d120..47c5ce9807db 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c @@ -37,6 +37,10 @@ #include +#ifdef CONFIG_DRM_AMD_DC +#include "amdgpu_dm_irq.h" +#endif + #define AMDGPU_WAIT_IDLE_TIMEOUT 200 /* @@ -221,15 +225,6 @@ int amdgpu_irq_init(struct amdgpu_device *adev) spin_lock_init(&adev->irq.lock); - if (!adev->enable_virtual_display) - /* Disable vblank irqs aggressively for power-saving */ - adev->ddev->vblank_disable_immediate = true; - - r = drm_vblank_init(adev->ddev, adev->mode_info.num_crtc); - if (r) { - return r; - } - /* enable msi */ adev->irq.msi_enabled = false; @@ -241,7 +236,21 @@ int amdgpu_irq_init(struct amdgpu_device *adev) } } - INIT_WORK(&adev->hotplug_work, amdgpu_hotplug_work_func); + if (!amdgpu_device_has_dc_support(adev)) { + if (!adev->enable_virtual_display) + /* Disable vblank irqs aggressively for power-saving */ + /* XXX: can this be enabled for DC? */ + adev->ddev->vblank_disable_immediate = true; + + r = drm_vblank_init(adev->ddev, adev->mode_info.num_crtc); + if (r) + return r; + + /* pre DCE11 */ + INIT_WORK(&adev->hotplug_work, + amdgpu_hotplug_work_func); + } + INIT_WORK(&adev->reset_work, amdgpu_irq_reset_work_func); adev->irq.installed = true; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index 4fd06f8d9768..7b9ae1d58c72 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -1034,7 +1034,7 @@ const struct drm_ioctl_desc amdgpu_ioctls_kms[] = { DRM_IOCTL_DEF_DRV(AMDGPU_GEM_METADATA, amdgpu_gem_metadata_ioctl, DRM_AUTH|DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(AMDGPU_GEM_VA, amdgpu_gem_va_ioctl, DRM_AUTH|DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(AMDGPU_GEM_OP, amdgpu_gem_op_ioctl, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(AMDGPU_GEM_USERPTR, amdgpu_gem_userptr_ioctl, DRM_AUTH|DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(AMDGPU_GEM_USERPTR, amdgpu_gem_userptr_ioctl, DRM_AUTH|DRM_RENDER_ALLOW) }; const int amdgpu_max_kms_ioctl = ARRAY_SIZE(amdgpu_ioctls_kms); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index 109a3833c3a8..3a3adfa16ada 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -38,11 +38,15 @@ #include #include #include +#include #include #include #include #include "amdgpu_irq.h" +#include +#include "modules/inc/mod_freesync.h" + struct amdgpu_bo; struct amdgpu_device; struct amdgpu_encoder; @@ -292,6 +296,27 @@ struct amdgpu_display_funcs { uint16_t connector_object_id, struct amdgpu_hpd *hpd, struct amdgpu_router *router); + /* it is used to enter or exit into free sync mode */ + int (*notify_freesync)(struct drm_device *dev, void *data, + struct drm_file *filp); + /* it is used to allow enablement of freesync mode */ + int (*set_freesync_property)(struct drm_connector *connector, + struct drm_property *property, + uint64_t val); + + +}; + +struct amdgpu_framebuffer { + struct drm_framebuffer base; + struct drm_gem_object *obj; +}; + +struct amdgpu_fbdev { + struct drm_fb_helper helper; + struct amdgpu_framebuffer rfb; + struct list_head fbdev_list; + struct amdgpu_device *adev; }; struct amdgpu_mode_info { @@ -400,6 +425,11 @@ struct amdgpu_crtc { /* for virtual dce */ struct hrtimer vblank_timer; enum amdgpu_interrupt_state vsync_timer_enabled; + + int otg_inst; + uint32_t flip_flags; + /* After Set Mode target will be non-NULL */ + struct dc_target *target; }; struct amdgpu_encoder_atom_dig { @@ -489,6 +519,19 @@ enum amdgpu_connector_dither { AMDGPU_FMT_DITHER_ENABLE = 1, }; +struct amdgpu_dm_dp_aux { + struct drm_dp_aux aux; + uint32_t link_index; +}; + +struct amdgpu_i2c_adapter { + struct i2c_adapter base; + struct amdgpu_display_manager *dm; + uint32_t link_index; +}; + +#define TO_DM_AUX(x) container_of((x), struct amdgpu_dm_dp_aux, aux) + struct amdgpu_connector { struct drm_connector base; uint32_t connector_id; @@ -500,6 +543,14 @@ struct amdgpu_connector { /* we need to mind the EDID between detect and get modes due to analog/digital/tvencoder */ struct edid *edid; + /* number of modes generated from EDID at 'dc_sink' */ + int num_modes; + /* The 'old' sink - before an HPD. + * The 'current' sink is in dc_link->sink. */ + const struct dc_sink *dc_sink; + const struct dc_link *dc_link; + const struct dc_sink *dc_em_sink; + const struct dc_target *target; void *con_priv; bool dac_load_detect; bool detected_by_load; /* if the connection status was determined by load */ @@ -510,11 +561,39 @@ struct amdgpu_connector { enum amdgpu_connector_audio audio; enum amdgpu_connector_dither dither; unsigned pixelclock_for_modeset; + + struct drm_dp_mst_topology_mgr mst_mgr; + struct amdgpu_dm_dp_aux dm_dp_aux; + struct drm_dp_mst_port *port; + struct amdgpu_connector *mst_port; + struct amdgpu_encoder *mst_encoder; + struct semaphore mst_sem; + + /* TODO see if we can merge with ddc_bus or make a dm_connector */ + struct amdgpu_i2c_adapter *i2c; + + /* Monitor range limits */ + int min_vfreq ; + int max_vfreq ; + int pixel_clock_mhz; + + /*freesync caps*/ + struct mod_freesync_caps caps; + + struct mutex hpd_lock; + }; -struct amdgpu_framebuffer { - struct drm_framebuffer base; - struct drm_gem_object *obj; +/* TODO: start to use this struct and remove same field from base one */ +struct amdgpu_mst_connector { + struct amdgpu_connector base; + + struct drm_dp_mst_topology_mgr mst_mgr; + struct amdgpu_dm_dp_aux dm_dp_aux; + struct drm_dp_mst_port *port; + struct amdgpu_connector *mst_port; + bool is_mst_connector; + struct amdgpu_encoder *mst_encoder; }; #define ENCODER_MODE_IS_DP(em) (((em) == ATOM_ENCODER_MODE_DP) || \ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index f6ce52956e6d..375c47767ae8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c @@ -1467,7 +1467,7 @@ void amdgpu_pm_compute_clocks(struct amdgpu_device *adev) list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head) { amdgpu_crtc = to_amdgpu_crtc(crtc); - if (crtc->enabled) { + if (amdgpu_crtc->enabled) { adev->pm.dpm.new_active_crtcs |= (1 << amdgpu_crtc->crtc_id); adev->pm.dpm.new_active_crtc_count++; } diff --git a/drivers/gpu/drm/amd/amdgpu/cik.c b/drivers/gpu/drm/amd/amdgpu/cik.c index 567c4a5cf90c..af3b66f6f47c 100644 --- a/drivers/gpu/drm/amd/amdgpu/cik.c +++ b/drivers/gpu/drm/amd/amdgpu/cik.c @@ -65,6 +65,7 @@ #include "oss/oss_2_0_d.h" #include "oss/oss_2_0_sh_mask.h" +#include "amdgpu_dm.h" #include "amdgpu_amdkfd.h" #include "amdgpu_powerplay.h" #include "dce_virtual.h" @@ -1900,6 +1901,10 @@ int cik_set_ip_blocks(struct amdgpu_device *adev) amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block); if (adev->enable_virtual_display) amdgpu_ip_block_add(adev, &dce_virtual_ip_block); +#if defined(CONFIG_DRM_AMD_DC) + else if (amdgpu_device_has_dc_support(adev)) + amdgpu_ip_block_add(adev, &dm_ip_block); +#endif else amdgpu_ip_block_add(adev, &dce_v8_2_ip_block); amdgpu_ip_block_add(adev, &gfx_v7_2_ip_block); @@ -1914,6 +1919,10 @@ int cik_set_ip_blocks(struct amdgpu_device *adev) amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block); if (adev->enable_virtual_display) amdgpu_ip_block_add(adev, &dce_virtual_ip_block); +#if defined(CONFIG_DRM_AMD_DC) + else if (amdgpu_device_has_dc_support(adev)) + amdgpu_ip_block_add(adev, &dm_ip_block); +#endif else amdgpu_ip_block_add(adev, &dce_v8_5_ip_block); amdgpu_ip_block_add(adev, &gfx_v7_3_ip_block); diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c index 9ff69b90df36..2ac5b84eee20 100644 --- a/drivers/gpu/drm/amd/amdgpu/vi.c +++ b/drivers/gpu/drm/amd/amdgpu/vi.c @@ -77,6 +77,7 @@ #endif #include "dce_virtual.h" #include "mxgpu_vi.h" +#include "amdgpu_dm.h" /* * Indirect registers accessor @@ -1496,6 +1497,10 @@ int vi_set_ip_blocks(struct amdgpu_device *adev) amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block); if (adev->enable_virtual_display || amdgpu_sriov_vf(adev)) amdgpu_ip_block_add(adev, &dce_virtual_ip_block); +#if defined(CONFIG_DRM_AMD_DC) + else if (amdgpu_device_has_dc_support(adev)) + amdgpu_ip_block_add(adev, &dm_ip_block); +#endif else amdgpu_ip_block_add(adev, &dce_v10_1_ip_block); amdgpu_ip_block_add(adev, &gfx_v8_0_ip_block); @@ -1512,6 +1517,10 @@ int vi_set_ip_blocks(struct amdgpu_device *adev) amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block); if (adev->enable_virtual_display || amdgpu_sriov_vf(adev)) amdgpu_ip_block_add(adev, &dce_virtual_ip_block); +#if defined(CONFIG_DRM_AMD_DC) + else if (amdgpu_device_has_dc_support(adev)) + amdgpu_ip_block_add(adev, &dm_ip_block); +#endif else amdgpu_ip_block_add(adev, &dce_v10_0_ip_block); amdgpu_ip_block_add(adev, &gfx_v8_0_ip_block); @@ -1530,6 +1539,10 @@ int vi_set_ip_blocks(struct amdgpu_device *adev) amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block); if (adev->enable_virtual_display) amdgpu_ip_block_add(adev, &dce_virtual_ip_block); +#if defined(CONFIG_DRM_AMD_DC) + else if (amdgpu_device_has_dc_support(adev)) + amdgpu_ip_block_add(adev, &dm_ip_block); +#endif else amdgpu_ip_block_add(adev, &dce_v11_2_ip_block); amdgpu_ip_block_add(adev, &gfx_v8_0_ip_block); @@ -1544,6 +1557,10 @@ int vi_set_ip_blocks(struct amdgpu_device *adev) amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block); if (adev->enable_virtual_display) amdgpu_ip_block_add(adev, &dce_virtual_ip_block); +#if defined(CONFIG_DRM_AMD_DC) + else if (amdgpu_device_has_dc_support(adev)) + amdgpu_ip_block_add(adev, &dm_ip_block); +#endif else amdgpu_ip_block_add(adev, &dce_v11_0_ip_block); amdgpu_ip_block_add(adev, &gfx_v8_0_ip_block); @@ -1561,6 +1578,10 @@ int vi_set_ip_blocks(struct amdgpu_device *adev) amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block); if (adev->enable_virtual_display) amdgpu_ip_block_add(adev, &dce_virtual_ip_block); +#if defined(CONFIG_DRM_AMD_DC) + else if (amdgpu_device_has_dc_support(adev)) + amdgpu_ip_block_add(adev, &dm_ip_block); +#endif else amdgpu_ip_block_add(adev, &dce_v11_0_ip_block); amdgpu_ip_block_add(adev, &gfx_v8_1_ip_block); diff --git a/drivers/gpu/drm/amd/display/Kconfig b/drivers/gpu/drm/amd/display/Kconfig new file mode 100644 index 000000000000..47c8e2940a91 --- /dev/null +++ b/drivers/gpu/drm/amd/display/Kconfig @@ -0,0 +1,28 @@ +menu "Display Engine Configuration" + depends on DRM && DRM_AMDGPU + +config DRM_AMD_DC + bool "AMD DC - Enable new display engine" + default y + help + Choose this option if you want to use the new display engine + support for AMDGPU. This adds required support for Vega and + Raven ASICs. + +config DRM_AMD_DC_PRE_VEGA + bool "DC support for Polaris and older ASICs" + default n + help + Choose this option to enable the new DC support for older asics + by default. This includes Polaris, Carrizo, Tonga, Bonaire, + and Hawaii. + +config DEBUG_KERNEL_DC + bool "Enable kgdb break in DC" + depends on DRM_AMD_DC + help + Choose this option + if you want to hit + kdgb_break in assert. + +endmenu diff --git a/drivers/gpu/drm/amd/display/Makefile b/drivers/gpu/drm/amd/display/Makefile new file mode 100644 index 000000000000..8ba37dd9cf7f --- /dev/null +++ b/drivers/gpu/drm/amd/display/Makefile @@ -0,0 +1,22 @@ +# +# Makefile for the DAL (Display Abstract Layer), which is a sub-component +# of the AMDGPU drm driver. +# It provides the HW control for display related functionalities. + +AMDDALPATH = $(RELATIVE_AMD_DISPLAY_PATH) + +subdir-ccflags-y += -I$(AMDDALPATH)/ -I$(AMDDALPATH)/include + +subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/inc/ +subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/inc/hw +subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/inc +subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/freesync + +#TODO: remove when Timing Sync feature is complete +subdir-ccflags-y += -DBUILD_FEATURE_TIMING_SYNC=0 + +DAL_LIBS = amdgpu_dm dc modules/freesync + +AMD_DAL = $(addsuffix /Makefile, $(addprefix $(FULL_AMD_DISPLAY_PATH)/,$(DAL_LIBS))) + +include $(AMD_DAL) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile b/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile new file mode 100644 index 000000000000..698b1d4f83f5 --- /dev/null +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile @@ -0,0 +1,17 @@ +# +# Makefile for the 'dm' sub-component of DAL. +# It provides the control and status of dm blocks. + + + +AMDGPUDM = amdgpu_dm_types.o amdgpu_dm.o amdgpu_dm_irq.o amdgpu_dm_mst_types.o + +ifneq ($(CONFIG_DRM_AMD_DC),) +AMDGPUDM += amdgpu_dm_services.o amdgpu_dm_helpers.o +endif + +subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc + +AMDGPU_DM = $(addprefix $(AMDDALPATH)/amdgpu_dm/,$(AMDGPUDM)) + +AMD_DISPLAY_FILES += $(AMDGPU_DM) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c new file mode 100644 index 000000000000..ae4ba7777839 --- /dev/null +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -0,0 +1,1564 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services_types.h" +#include "dc.h" + +#include "vid.h" +#include "amdgpu.h" +#include "atom.h" +#include "amdgpu_dm.h" +#include "amdgpu_dm_types.h" + +#include "amd_shared.h" +#include "amdgpu_dm_irq.h" +#include "dm_helpers.h" + +#include "ivsrcid/ivsrcid_vislands30.h" + +#include +#include +#include + +#include +#include +#include + +#include "modules/inc/mod_freesync.h" + +/* Debug facilities */ +#define AMDGPU_DM_NOT_IMPL(fmt, ...) \ + DRM_INFO("DM_NOT_IMPL: " fmt, ##__VA_ARGS__) + +/* + * dm_vblank_get_counter + * + * @brief + * Get counter for number of vertical blanks + * + * @param + * struct amdgpu_device *adev - [in] desired amdgpu device + * int disp_idx - [in] which CRTC to get the counter from + * + * @return + * Counter for vertical blanks + */ +static u32 dm_vblank_get_counter(struct amdgpu_device *adev, int crtc) +{ + if (crtc >= adev->mode_info.num_crtc) + return 0; + else { + struct amdgpu_crtc *acrtc = adev->mode_info.crtcs[crtc]; + + if (NULL == acrtc->target) { + DRM_ERROR("dc_target is NULL for crtc '%d'!\n", crtc); + return 0; + } + + return dc_target_get_vblank_counter(acrtc->target); + } +} + +static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc, + u32 *vbl, u32 *position) +{ + if ((crtc < 0) || (crtc >= adev->mode_info.num_crtc)) + return -EINVAL; + else { + struct amdgpu_crtc *acrtc = adev->mode_info.crtcs[crtc]; + + if (NULL == acrtc->target) { + DRM_ERROR("dc_target is NULL for crtc '%d'!\n", crtc); + return 0; + } + + return dc_target_get_scanoutpos(acrtc->target, vbl, position); + } + + return 0; +} + +static bool dm_is_idle(void *handle) +{ + /* XXX todo */ + return true; +} + +static int dm_wait_for_idle(void *handle) +{ + /* XXX todo */ + return 0; +} + +static bool dm_check_soft_reset(void *handle) +{ + return false; +} + +static int dm_soft_reset(void *handle) +{ + /* XXX todo */ + return 0; +} + +static struct amdgpu_crtc *get_crtc_by_otg_inst( + struct amdgpu_device *adev, + int otg_inst) +{ + struct drm_device *dev = adev->ddev; + struct drm_crtc *crtc; + struct amdgpu_crtc *amdgpu_crtc; + + /* + * following if is check inherited from both functions where this one is + * used now. Need to be checked why it could happen. + */ + if (otg_inst == -1) { + WARN_ON(1); + return adev->mode_info.crtcs[0]; + } + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + amdgpu_crtc = to_amdgpu_crtc(crtc); + + if (amdgpu_crtc->otg_inst == otg_inst) + return amdgpu_crtc; + } + + return NULL; +} + +static void dm_pflip_high_irq(void *interrupt_params) +{ + struct amdgpu_flip_work *works; + struct amdgpu_crtc *amdgpu_crtc; + struct common_irq_params *irq_params = interrupt_params; + struct amdgpu_device *adev = irq_params->adev; + unsigned long flags; + + amdgpu_crtc = get_crtc_by_otg_inst(adev, irq_params->irq_src - IRQ_TYPE_PFLIP); + + /* IRQ could occur when in initial stage */ + /*TODO work and BO cleanup */ + if (amdgpu_crtc == NULL) { + DRM_DEBUG_DRIVER("CRTC is null, returning.\n"); + return; + } + + spin_lock_irqsave(&adev->ddev->event_lock, flags); + works = amdgpu_crtc->pflip_works; + + if (amdgpu_crtc->pflip_status != AMDGPU_FLIP_SUBMITTED){ + DRM_DEBUG_DRIVER("amdgpu_crtc->pflip_status = %d !=AMDGPU_FLIP_SUBMITTED(%d) on crtc:%d[%p] \n", + amdgpu_crtc->pflip_status, + AMDGPU_FLIP_SUBMITTED, + amdgpu_crtc->crtc_id, + amdgpu_crtc); + spin_unlock_irqrestore(&adev->ddev->event_lock, flags); + return; + } + + /* page flip completed. clean up */ + amdgpu_crtc->pflip_status = AMDGPU_FLIP_NONE; + amdgpu_crtc->pflip_works = NULL; + + /* wakeup usersapce */ + if (works->event) + drm_crtc_send_vblank_event(&amdgpu_crtc->base, + works->event); + + spin_unlock_irqrestore(&adev->ddev->event_lock, flags); + + DRM_DEBUG_DRIVER("%s - crtc :%d[%p], pflip_stat:AMDGPU_FLIP_NONE, work: %p,\n", + __func__, amdgpu_crtc->crtc_id, amdgpu_crtc, works); + + drm_crtc_vblank_put(&amdgpu_crtc->base); + schedule_work(&works->unpin_work); +} + +static void dm_crtc_high_irq(void *interrupt_params) +{ + struct common_irq_params *irq_params = interrupt_params; + struct amdgpu_device *adev = irq_params->adev; + uint8_t crtc_index = 0; + struct amdgpu_crtc *acrtc; + + acrtc = get_crtc_by_otg_inst(adev, irq_params->irq_src - IRQ_TYPE_VUPDATE); + + if (acrtc) + crtc_index = acrtc->crtc_id; + + drm_handle_vblank(adev->ddev, crtc_index); +} + +static int dm_set_clockgating_state(void *handle, + enum amd_clockgating_state state) +{ + return 0; +} + +static int dm_set_powergating_state(void *handle, + enum amd_powergating_state state) +{ + return 0; +} + +/* Prototypes of private functions */ +static int dm_early_init(void* handle); + +static void hotplug_notify_work_func(struct work_struct *work) +{ + struct amdgpu_display_manager *dm = container_of(work, struct amdgpu_display_manager, mst_hotplug_work); + struct drm_device *dev = dm->ddev; + + drm_kms_helper_hotplug_event(dev); +} + +/* Init display KMS + * + * Returns 0 on success + */ +int amdgpu_dm_init(struct amdgpu_device *adev) +{ + struct dc_init_data init_data; + adev->dm.ddev = adev->ddev; + adev->dm.adev = adev; + + DRM_INFO("DAL is enabled\n"); + /* Zero all the fields */ + memset(&init_data, 0, sizeof(init_data)); + + /* initialize DAL's lock (for SYNC context use) */ + spin_lock_init(&adev->dm.dal_lock); + + /* initialize DAL's mutex */ + mutex_init(&adev->dm.dal_mutex); + + if(amdgpu_dm_irq_init(adev)) { + DRM_ERROR("amdgpu: failed to initialize DM IRQ support.\n"); + goto error; + } + + init_data.asic_id.chip_family = adev->family; + + init_data.asic_id.pci_revision_id = adev->rev_id; + init_data.asic_id.hw_internal_rev = adev->external_rev_id; + + init_data.asic_id.vram_width = adev->mc.vram_width; + /* TODO: initialize init_data.asic_id.vram_type here!!!! */ + init_data.asic_id.atombios_base_address = + adev->mode_info.atom_context->bios; + + init_data.driver = adev; + + adev->dm.cgs_device = amdgpu_cgs_create_device(adev); + + if (!adev->dm.cgs_device) { + DRM_ERROR("amdgpu: failed to create cgs device.\n"); + goto error; + } + + init_data.cgs_device = adev->dm.cgs_device; + + adev->dm.dal = NULL; + + init_data.dce_environment = DCE_ENV_PRODUCTION_DRV; + + /* Display Core create. */ + adev->dm.dc = dc_create(&init_data); + + if (!adev->dm.dc) + DRM_INFO("Display Core failed to initialize!\n"); + + INIT_WORK(&adev->dm.mst_hotplug_work, hotplug_notify_work_func); + + adev->dm.freesync_module = mod_freesync_create(adev->dm.dc); + if (!adev->dm.freesync_module) { + DRM_ERROR( + "amdgpu: failed to initialize freesync_module.\n"); + } else + DRM_INFO("amdgpu: freesync_module init done %p.\n", + adev->dm.freesync_module); + + if (amdgpu_dm_initialize_drm_device(adev)) { + DRM_ERROR( + "amdgpu: failed to initialize sw for display support.\n"); + goto error; + } + + /* Update the actual used number of crtc */ + adev->mode_info.num_crtc = adev->dm.display_indexes_num; + + /* TODO: Add_display_info? */ + + /* TODO use dynamic cursor width */ + adev->ddev->mode_config.cursor_width = 128; + adev->ddev->mode_config.cursor_height = 128; + + if (drm_vblank_init(adev->ddev, adev->dm.display_indexes_num)) { + DRM_ERROR( + "amdgpu: failed to initialize sw for display support.\n"); + goto error; + } + + DRM_INFO("KMS initialized.\n"); + + return 0; +error: + amdgpu_dm_fini(adev); + + return -1; +} + +void amdgpu_dm_fini(struct amdgpu_device *adev) +{ + amdgpu_dm_destroy_drm_device(&adev->dm); + /* + * TODO: pageflip, vlank interrupt + * + * amdgpu_dm_irq_fini(adev); + */ + + if (adev->dm.cgs_device) { + amdgpu_cgs_destroy_device(adev->dm.cgs_device); + adev->dm.cgs_device = NULL; + } + if (adev->dm.freesync_module) { + mod_freesync_destroy(adev->dm.freesync_module); + adev->dm.freesync_module = NULL; + } + /* DC Destroy TODO: Replace destroy DAL */ + { + dc_destroy(&adev->dm.dc); + } + return; +} + +/* moved from amdgpu_dm_kms.c */ +void amdgpu_dm_destroy() +{ +} + +static int dm_sw_init(void *handle) +{ + return 0; +} + +static int dm_sw_fini(void *handle) +{ + return 0; +} + +static void detect_link_for_all_connectors(struct drm_device *dev) +{ + struct amdgpu_connector *aconnector; + struct drm_connector *connector; + + drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + aconnector = to_amdgpu_connector(connector); + if (aconnector->dc_link->type == dc_connection_mst_branch) { + DRM_INFO("DM_MST: starting TM on aconnector: %p [id: %d]\n", + aconnector, aconnector->base.base.id); + + if (drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_mgr, true) < 0) { + DRM_ERROR("DM_MST: Failed to start MST\n"); + ((struct dc_link *)aconnector->dc_link)->type = dc_connection_single; + } + } + } + + drm_modeset_unlock(&dev->mode_config.connection_mutex); +} + +static void s3_handle_mst(struct drm_device *dev, bool suspend) +{ + struct amdgpu_connector *aconnector; + struct drm_connector *connector; + + drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + aconnector = to_amdgpu_connector(connector); + if (aconnector->dc_link->type == dc_connection_mst_branch && + !aconnector->mst_port) { + + if (suspend) + drm_dp_mst_topology_mgr_suspend(&aconnector->mst_mgr); + else + drm_dp_mst_topology_mgr_resume(&aconnector->mst_mgr); + } + } + + drm_modeset_unlock(&dev->mode_config.connection_mutex); +} + +static int dm_hw_init(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + /* Create DAL display manager */ + amdgpu_dm_init(adev); + + amdgpu_dm_hpd_init(adev); + + detect_link_for_all_connectors(adev->ddev); + + return 0; +} + +static int dm_hw_fini(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + amdgpu_dm_hpd_fini(adev); + + amdgpu_dm_irq_fini(adev); + + return 0; +} + +static int dm_suspend(void *handle) +{ + struct amdgpu_device *adev = handle; + struct amdgpu_display_manager *dm = &adev->dm; + int ret = 0; + struct drm_crtc *crtc; + + s3_handle_mst(adev->ddev, true); + + /* flash all pending vblank events and turn interrupt off + * before disabling CRTCs. They will be enabled back in + * dm_display_resume + */ + drm_modeset_lock_all(adev->ddev); + list_for_each_entry(crtc, &adev->ddev->mode_config.crtc_list, head) { + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + if (acrtc->target) + drm_crtc_vblank_off(crtc); + } + drm_modeset_unlock_all(adev->ddev); + + amdgpu_dm_irq_suspend(adev); + + dc_set_power_state( + dm->dc, + DC_ACPI_CM_POWER_STATE_D3, + DC_VIDEO_POWER_SUSPEND); + + return ret; +} + +struct amdgpu_connector *amdgpu_dm_find_first_crct_matching_connector( + struct drm_atomic_state *state, + struct drm_crtc *crtc, + bool from_state_var) +{ + uint32_t i; + struct drm_connector_state *conn_state; + struct drm_connector *connector; + struct drm_crtc *crtc_from_state; + + for_each_connector_in_state( + state, + connector, + conn_state, + i) { + crtc_from_state = + from_state_var ? + conn_state->crtc : + connector->state->crtc; + + if (crtc_from_state == crtc) + return to_amdgpu_connector(connector); + } + + return NULL; +} + +static int dm_display_resume(struct drm_device *ddev) +{ + int ret = 0; + struct drm_connector *connector; + + struct drm_atomic_state *state = drm_atomic_state_alloc(ddev); + struct drm_plane *plane; + struct drm_crtc *crtc; + struct amdgpu_connector *aconnector; + struct drm_connector_state *conn_state; + + if (!state) + return ENOMEM; + + state->acquire_ctx = ddev->mode_config.acquire_ctx; + + /* Construct an atomic state to restore previous display setting */ + + /* + * Attach connectors to drm_atomic_state + * Should be done in the first place in order to make connectors + * available in state during crtc state processing. It is used for + * making decision if crtc should be disabled in case sink got + * disconnected. + * + * Connectors state crtc with NULL dc_sink should be cleared, because it + * will fail validation during commit + */ + list_for_each_entry(connector, &ddev->mode_config.connector_list, head) { + aconnector = to_amdgpu_connector(connector); + conn_state = drm_atomic_get_connector_state(state, connector); + + ret = PTR_ERR_OR_ZERO(conn_state); + if (ret) + goto err; + } + + /* Attach crtcs to drm_atomic_state*/ + list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head) { + struct drm_crtc_state *crtc_state = + drm_atomic_get_crtc_state(state, crtc); + + ret = PTR_ERR_OR_ZERO(crtc_state); + if (ret) + goto err; + + /* force a restore */ + crtc_state->mode_changed = true; + } + + + /* Attach planes to drm_atomic_state */ + list_for_each_entry(plane, &ddev->mode_config.plane_list, head) { + + struct drm_crtc *crtc; + struct drm_gem_object *obj; + struct drm_framebuffer *fb; + struct amdgpu_framebuffer *afb; + struct amdgpu_bo *rbo; + int r; + struct drm_plane_state *plane_state = drm_atomic_get_plane_state(state, plane); + + ret = PTR_ERR_OR_ZERO(plane_state); + if (ret) + goto err; + + crtc = plane_state->crtc; + fb = plane_state->fb; + + if (!crtc || !crtc->state || !crtc->state->active) + continue; + + if (!fb) { + DRM_DEBUG_KMS("No FB bound\n"); + return 0; + } + + /* + * Pin back the front buffers, cursor buffer was already pinned + * back in amdgpu_resume_kms + */ + + afb = to_amdgpu_framebuffer(fb); + + obj = afb->obj; + rbo = gem_to_amdgpu_bo(obj); + r = amdgpu_bo_reserve(rbo, false); + if (unlikely(r != 0)) + return r; + + r = amdgpu_bo_pin(rbo, AMDGPU_GEM_DOMAIN_VRAM, NULL); + + amdgpu_bo_unreserve(rbo); + + if (unlikely(r != 0)) { + DRM_ERROR("Failed to pin framebuffer\n"); + return r; + } + + } + + + /* Call commit internally with the state we just constructed */ + ret = drm_atomic_commit(state); + if (!ret) + return 0; + +err: + DRM_ERROR("Restoring old state failed with %i\n", ret); + drm_atomic_state_put(state); + + return ret; +} + +static int dm_resume(void *handle) +{ + struct amdgpu_device *adev = handle; + struct amdgpu_display_manager *dm = &adev->dm; + + /* power on hardware */ + dc_set_power_state( + dm->dc, + DC_ACPI_CM_POWER_STATE_D0, + DC_VIDEO_POWER_ON); + + return 0; +} + +int amdgpu_dm_display_resume(struct amdgpu_device *adev ) +{ + struct drm_device *ddev = adev->ddev; + struct amdgpu_display_manager *dm = &adev->dm; + struct amdgpu_connector *aconnector; + struct drm_connector *connector; + int ret = 0; + struct drm_crtc *crtc; + + /* program HPD filter */ + dc_resume(dm->dc); + + /* On resume we need to rewrite the MSTM control bits to enamble MST*/ + s3_handle_mst(ddev, false); + + /* + * early enable HPD Rx IRQ, should be done before set mode as short + * pulse interrupts are used for MST + */ + amdgpu_dm_irq_resume_early(adev); + + drm_modeset_lock_all(ddev); + list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head) { + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + if (acrtc->target) + drm_crtc_vblank_on(crtc); + } + drm_modeset_unlock_all(ddev); + + /* Do detection*/ + list_for_each_entry(connector, + &ddev->mode_config.connector_list, head) { + aconnector = to_amdgpu_connector(connector); + + /* + * this is the case when traversing through already created + * MST connectors, should be skipped + */ + if (aconnector->mst_port) + continue; + + dc_link_detect(aconnector->dc_link, false); + aconnector->dc_sink = NULL; + amdgpu_dm_update_connector_after_detect(aconnector); + } + + drm_modeset_lock_all(ddev); + ret = dm_display_resume(ddev); + drm_modeset_unlock_all(ddev); + + amdgpu_dm_irq_resume(adev); + + return ret; +} + +static const struct amd_ip_funcs amdgpu_dm_funcs = { + .name = "dm", + .early_init = dm_early_init, + .late_init = NULL, + .sw_init = dm_sw_init, + .sw_fini = dm_sw_fini, + .hw_init = dm_hw_init, + .hw_fini = dm_hw_fini, + .suspend = dm_suspend, + .resume = dm_resume, + .is_idle = dm_is_idle, + .wait_for_idle = dm_wait_for_idle, + .check_soft_reset = dm_check_soft_reset, + .soft_reset = dm_soft_reset, + .set_clockgating_state = dm_set_clockgating_state, + .set_powergating_state = dm_set_powergating_state, +}; + +const struct amdgpu_ip_block_version dm_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_DCE, + .major = 1, + .minor = 0, + .rev = 0, + .funcs = &amdgpu_dm_funcs, +}; + +/* TODO: it is temporary non-const, should fixed later */ +static struct drm_mode_config_funcs amdgpu_dm_mode_funcs = { + .atomic_check = amdgpu_dm_atomic_check, + .atomic_commit = amdgpu_dm_atomic_commit +}; + +void amdgpu_dm_update_connector_after_detect( + struct amdgpu_connector *aconnector) +{ + struct drm_connector *connector = &aconnector->base; + struct drm_device *dev = connector->dev; + const struct dc_sink *sink; + + /* MST handled by drm_mst framework */ + if (aconnector->mst_mgr.mst_state == true) + return; + + + sink = aconnector->dc_link->local_sink; + + /* Edid mgmt connector gets first update only in mode_valid hook and then + * the connector sink is set to either fake or physical sink depends on link status. + * don't do it here if u are during boot + */ + if (aconnector->base.force != DRM_FORCE_UNSPECIFIED + && aconnector->dc_em_sink) { + + /* For S3 resume with headless use eml_sink to fake target + * because on resume connecotr->sink is set ti NULL + */ + mutex_lock(&dev->mode_config.mutex); + + if (sink) { + if (aconnector->dc_sink) + amdgpu_dm_remove_sink_from_freesync_module( + connector); + aconnector->dc_sink = sink; + amdgpu_dm_add_sink_to_freesync_module( + connector, aconnector->edid); + } else { + amdgpu_dm_remove_sink_from_freesync_module(connector); + if (!aconnector->dc_sink) + aconnector->dc_sink = aconnector->dc_em_sink; + } + + mutex_unlock(&dev->mode_config.mutex); + return; + } + + /* + * TODO: temporary guard to look for proper fix + * if this sink is MST sink, we should not do anything + */ + if (sink && sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT_MST) + return; + + if (aconnector->dc_sink == sink) { + /* We got a DP short pulse (Link Loss, DP CTS, etc...). + * Do nothing!! */ + DRM_INFO("DCHPD: connector_id=%d: dc_sink didn't change.\n", + aconnector->connector_id); + return; + } + + DRM_INFO("DCHPD: connector_id=%d: Old sink=%p New sink=%p\n", + aconnector->connector_id, aconnector->dc_sink, sink); + + mutex_lock(&dev->mode_config.mutex); + + /* 1. Update status of the drm connector + * 2. Send an event and let userspace tell us what to do */ + if (sink) { + /* TODO: check if we still need the S3 mode update workaround. + * If yes, put it here. */ + if (aconnector->dc_sink) + amdgpu_dm_remove_sink_from_freesync_module( + connector); + + aconnector->dc_sink = sink; + if (sink->dc_edid.length == 0) + aconnector->edid = NULL; + else { + aconnector->edid = + (struct edid *) sink->dc_edid.raw_edid; + + + drm_mode_connector_update_edid_property(connector, + aconnector->edid); + } + amdgpu_dm_add_sink_to_freesync_module(connector, aconnector->edid); + + } else { + amdgpu_dm_remove_sink_from_freesync_module(connector); + drm_mode_connector_update_edid_property(connector, NULL); + aconnector->num_modes = 0; + aconnector->dc_sink = NULL; + } + + mutex_unlock(&dev->mode_config.mutex); +} + +static void handle_hpd_irq(void *param) +{ + struct amdgpu_connector *aconnector = (struct amdgpu_connector *)param; + struct drm_connector *connector = &aconnector->base; + struct drm_device *dev = connector->dev; + + /* In case of failure or MST no need to update connector status or notify the OS + * since (for MST case) MST does this in it's own context. + */ + mutex_lock(&aconnector->hpd_lock); + if (dc_link_detect(aconnector->dc_link, false)) { + amdgpu_dm_update_connector_after_detect(aconnector); + + + drm_modeset_lock_all(dev); + dm_restore_drm_connector_state(dev, connector); + drm_modeset_unlock_all(dev); + + if (aconnector->base.force == DRM_FORCE_UNSPECIFIED) + drm_kms_helper_hotplug_event(dev); + } + mutex_unlock(&aconnector->hpd_lock); + +} + +static void dm_handle_hpd_rx_irq(struct amdgpu_connector *aconnector) +{ + uint8_t esi[DP_PSR_ERROR_STATUS - DP_SINK_COUNT_ESI] = { 0 }; + uint8_t dret; + bool new_irq_handled = false; + int dpcd_addr; + int dpcd_bytes_to_read; + + const int max_process_count = 30; + int process_count = 0; + + const struct dc_link_status *link_status = dc_link_get_status(aconnector->dc_link); + + if (link_status->dpcd_caps->dpcd_rev.raw < 0x12) { + dpcd_bytes_to_read = DP_LANE0_1_STATUS - DP_SINK_COUNT; + /* DPCD 0x200 - 0x201 for downstream IRQ */ + dpcd_addr = DP_SINK_COUNT; + } else { + dpcd_bytes_to_read = DP_PSR_ERROR_STATUS - DP_SINK_COUNT_ESI; + /* DPCD 0x2002 - 0x2005 for downstream IRQ */ + dpcd_addr = DP_SINK_COUNT_ESI; + } + + dret = drm_dp_dpcd_read( + &aconnector->dm_dp_aux.aux, + dpcd_addr, + esi, + dpcd_bytes_to_read); + + while (dret == dpcd_bytes_to_read && + process_count < max_process_count) { + uint8_t retry; + dret = 0; + + process_count++; + + DRM_DEBUG_KMS("ESI %02x %02x %02x\n", esi[0], esi[1], esi[2]); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 3, 0) + /* handle HPD short pulse irq */ + if (aconnector->mst_mgr.mst_state) + drm_dp_mst_hpd_irq( + &aconnector->mst_mgr, + esi, + &new_irq_handled); +#endif + + if (new_irq_handled) { + /* ACK at DPCD to notify down stream */ + const int ack_dpcd_bytes_to_write = + dpcd_bytes_to_read - 1; + + for (retry = 0; retry < 3; retry++) { + uint8_t wret; + + wret = drm_dp_dpcd_write( + &aconnector->dm_dp_aux.aux, + dpcd_addr + 1, + &esi[1], + ack_dpcd_bytes_to_write); + if (wret == ack_dpcd_bytes_to_write) + break; + } + + /* check if there is new irq to be handle */ + dret = drm_dp_dpcd_read( + &aconnector->dm_dp_aux.aux, + dpcd_addr, + esi, + dpcd_bytes_to_read); + + new_irq_handled = false; + } else + break; + } + + if (process_count == max_process_count) + DRM_DEBUG_KMS("Loop exceeded max iterations\n"); +} + +static void handle_hpd_rx_irq(void *param) +{ + struct amdgpu_connector *aconnector = (struct amdgpu_connector *)param; + struct drm_connector *connector = &aconnector->base; + struct drm_device *dev = connector->dev; + const struct dc_link *dc_link = aconnector->dc_link; + bool is_mst_root_connector = aconnector->mst_mgr.mst_state; + + /* TODO:Temporary add mutex to protect hpd interrupt not have a gpio + * conflict, after implement i2c helper, this mutex should be + * retired. + */ + if (aconnector->dc_link->type != dc_connection_mst_branch) + mutex_lock(&aconnector->hpd_lock); + + if (dc_link_handle_hpd_rx_irq(aconnector->dc_link) && + !is_mst_root_connector) { + /* Downstream Port status changed. */ + if (dc_link_detect(aconnector->dc_link, false)) { + amdgpu_dm_update_connector_after_detect(aconnector); + + + drm_modeset_lock_all(dev); + dm_restore_drm_connector_state(dev, connector); + drm_modeset_unlock_all(dev); + + drm_kms_helper_hotplug_event(dev); + } + } + if ((dc_link->cur_link_settings.lane_count != LANE_COUNT_UNKNOWN) || + (dc_link->type == dc_connection_mst_branch)) + dm_handle_hpd_rx_irq(aconnector); + + if (aconnector->dc_link->type != dc_connection_mst_branch) + mutex_unlock(&aconnector->hpd_lock); +} + +static void register_hpd_handlers(struct amdgpu_device *adev) +{ + struct drm_device *dev = adev->ddev; + struct drm_connector *connector; + struct amdgpu_connector *aconnector; + const struct dc_link *dc_link; + struct dc_interrupt_params int_params = {0}; + + int_params.requested_polarity = INTERRUPT_POLARITY_DEFAULT; + int_params.current_polarity = INTERRUPT_POLARITY_DEFAULT; + + list_for_each_entry(connector, + &dev->mode_config.connector_list, head) { + + aconnector = to_amdgpu_connector(connector); + dc_link = aconnector->dc_link; + + if (DC_IRQ_SOURCE_INVALID != dc_link->irq_source_hpd) { + int_params.int_context = INTERRUPT_LOW_IRQ_CONTEXT; + int_params.irq_source = dc_link->irq_source_hpd; + + amdgpu_dm_irq_register_interrupt(adev, &int_params, + handle_hpd_irq, + (void *) aconnector); + } + + if (DC_IRQ_SOURCE_INVALID != dc_link->irq_source_hpd_rx) { + + /* Also register for DP short pulse (hpd_rx). */ + int_params.int_context = INTERRUPT_LOW_IRQ_CONTEXT; + int_params.irq_source = dc_link->irq_source_hpd_rx; + + amdgpu_dm_irq_register_interrupt(adev, &int_params, + handle_hpd_rx_irq, + (void *) aconnector); + } + } +} + +/* Register IRQ sources and initialize IRQ callbacks */ +static int dce110_register_irq_handlers(struct amdgpu_device *adev) +{ + struct dc *dc = adev->dm.dc; + struct common_irq_params *c_irq_params; + struct dc_interrupt_params int_params = {0}; + int r; + int i; + + int_params.requested_polarity = INTERRUPT_POLARITY_DEFAULT; + int_params.current_polarity = INTERRUPT_POLARITY_DEFAULT; + + /* Actions of amdgpu_irq_add_id(): + * 1. Register a set() function with base driver. + * Base driver will call set() function to enable/disable an + * interrupt in DC hardware. + * 2. Register amdgpu_dm_irq_handler(). + * Base driver will call amdgpu_dm_irq_handler() for ALL interrupts + * coming from DC hardware. + * amdgpu_dm_irq_handler() will re-direct the interrupt to DC + * for acknowledging and handling. */ + + for (i = VISLANDS30_IV_SRCID_D1_V_UPDATE_INT; + i <= VISLANDS30_IV_SRCID_D6_V_UPDATE_INT; i += 2) { + r = amdgpu_irq_add_id(adev, AMDGPU_IH_CLIENTID_LEGACY, i, &adev->crtc_irq); + if (r) { + DRM_ERROR("Failed to add crtc irq id!\n"); + return r; + } + + int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT; + int_params.irq_source = + dc_interrupt_to_irq_source(dc, i, 0); + + c_irq_params = &adev->dm.vupdate_params[int_params.irq_source - DC_IRQ_SOURCE_VUPDATE1]; + + c_irq_params->adev = adev; + c_irq_params->irq_src = int_params.irq_source; + + amdgpu_dm_irq_register_interrupt(adev, &int_params, + dm_crtc_high_irq, c_irq_params); + } + + for (i = VISLANDS30_IV_SRCID_D1_GRPH_PFLIP; + i <= VISLANDS30_IV_SRCID_D6_GRPH_PFLIP; i += 2) { + r = amdgpu_irq_add_id(adev, AMDGPU_IH_CLIENTID_LEGACY, i, &adev->pageflip_irq); + if (r) { + DRM_ERROR("Failed to add page flip irq id!\n"); + return r; + } + + int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT; + int_params.irq_source = + dc_interrupt_to_irq_source(dc, i, 0); + + c_irq_params = &adev->dm.pflip_params[int_params.irq_source - DC_IRQ_SOURCE_PFLIP_FIRST]; + + c_irq_params->adev = adev; + c_irq_params->irq_src = int_params.irq_source; + + amdgpu_dm_irq_register_interrupt(adev, &int_params, + dm_pflip_high_irq, c_irq_params); + + } + + /* HPD */ + r = amdgpu_irq_add_id(adev, AMDGPU_IH_CLIENTID_LEGACY, VISLANDS30_IV_SRCID_HOTPLUG_DETECT_A, + &adev->hpd_irq); + if (r) { + DRM_ERROR("Failed to add hpd irq id!\n"); + return r; + } + + register_hpd_handlers(adev); + + return 0; +} + +static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev) +{ + int r; + + adev->mode_info.mode_config_initialized = true; + + amdgpu_dm_mode_funcs.fb_create = + amdgpu_mode_funcs.fb_create; + amdgpu_dm_mode_funcs.output_poll_changed = + amdgpu_mode_funcs.output_poll_changed; + + adev->ddev->mode_config.funcs = (void *)&amdgpu_dm_mode_funcs; + + adev->ddev->mode_config.max_width = 16384; + adev->ddev->mode_config.max_height = 16384; + + adev->ddev->mode_config.preferred_depth = 24; + adev->ddev->mode_config.prefer_shadow = 1; + /* indicate support of immediate flip */ + adev->ddev->mode_config.async_page_flip = true; + + adev->ddev->mode_config.fb_base = adev->mc.aper_base; + + r = amdgpu_modeset_create_props(adev); + if (r) + return r; + + return 0; +} + +#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\ + defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) + +static int amdgpu_dm_backlight_update_status(struct backlight_device *bd) +{ + struct amdgpu_display_manager *dm = bl_get_data(bd); + + if (dc_link_set_backlight_level(dm->backlight_link, + bd->props.brightness, 0, 0)) + return 0; + else + return 1; +} + +static int amdgpu_dm_backlight_get_brightness(struct backlight_device *bd) +{ + return bd->props.brightness; +} + +static const struct backlight_ops amdgpu_dm_backlight_ops = { + .get_brightness = amdgpu_dm_backlight_get_brightness, + .update_status = amdgpu_dm_backlight_update_status, +}; + +void amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm) +{ + char bl_name[16]; + struct backlight_properties props = { 0 }; + + props.max_brightness = AMDGPU_MAX_BL_LEVEL; + props.type = BACKLIGHT_RAW; + + snprintf(bl_name, sizeof(bl_name), "amdgpu_bl%d", + dm->adev->ddev->primary->index); + + dm->backlight_dev = backlight_device_register(bl_name, + dm->adev->ddev->dev, + dm, + &amdgpu_dm_backlight_ops, + &props); + + if (NULL == dm->backlight_dev) + DRM_ERROR("DM: Backlight registration failed!\n"); + else + DRM_INFO("DM: Registered Backlight device: %s\n", bl_name); +} + +#endif + +/* In this architecture, the association + * connector -> encoder -> crtc + * id not really requried. The crtc and connector will hold the + * display_index as an abstraction to use with DAL component + * + * Returns 0 on success + */ +int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) +{ + struct amdgpu_display_manager *dm = &adev->dm; + uint32_t i; + struct amdgpu_connector *aconnector; + struct amdgpu_encoder *aencoder; + struct amdgpu_crtc *acrtc; + uint32_t link_cnt; + + link_cnt = dm->dc->caps.max_links; + + if (amdgpu_dm_mode_config_init(dm->adev)) { + DRM_ERROR("DM: Failed to initialize mode config\n"); + return -1; + } + + for (i = 0; i < dm->dc->caps.max_targets; i++) { + acrtc = kzalloc(sizeof(struct amdgpu_crtc), GFP_KERNEL); + if (!acrtc) + goto fail; + + if (amdgpu_dm_crtc_init( + dm, + acrtc, + i)) { + DRM_ERROR("KMS: Failed to initialize crtc\n"); + kfree(acrtc); + goto fail; + } + } + + dm->display_indexes_num = dm->dc->caps.max_targets; + + /* loops over all connectors on the board */ + for (i = 0; i < link_cnt; i++) { + + if (i > AMDGPU_DM_MAX_DISPLAY_INDEX) { + DRM_ERROR( + "KMS: Cannot support more than %d display indexes\n", + AMDGPU_DM_MAX_DISPLAY_INDEX); + continue; + } + + aconnector = kzalloc(sizeof(*aconnector), GFP_KERNEL); + if (!aconnector) + goto fail; + + aencoder = kzalloc(sizeof(*aencoder), GFP_KERNEL); + if (!aencoder) { + goto fail_free_connector; + } + + if (amdgpu_dm_encoder_init(dm->ddev, aencoder, i)) { + DRM_ERROR("KMS: Failed to initialize encoder\n"); + goto fail_free_encoder; + } + + if (amdgpu_dm_connector_init(dm, aconnector, i, aencoder)) { + DRM_ERROR("KMS: Failed to initialize connector\n"); + goto fail_free_connector; + } + + if (dc_link_detect(dc_get_link_at_index(dm->dc, i), true)) + amdgpu_dm_update_connector_after_detect(aconnector); + } + + /* Software is initialized. Now we can register interrupt handlers. */ + switch (adev->asic_type) { + case CHIP_BONAIRE: + case CHIP_HAWAII: + case CHIP_TONGA: + case CHIP_FIJI: + case CHIP_CARRIZO: + case CHIP_STONEY: + case CHIP_POLARIS11: + case CHIP_POLARIS10: + if (dce110_register_irq_handlers(dm->adev)) { + DRM_ERROR("DM: Failed to initialize IRQ\n"); + return -1; + } + break; + default: + DRM_ERROR("Usupported ASIC type: 0x%X\n", adev->asic_type); + return -1; + } + + drm_mode_config_reset(dm->ddev); + + return 0; +fail_free_encoder: + kfree(aencoder); +fail_free_connector: + kfree(aconnector); +fail: + return -1; +} + +void amdgpu_dm_destroy_drm_device(struct amdgpu_display_manager *dm) +{ + drm_mode_config_cleanup(dm->ddev); + return; +} + +/****************************************************************************** + * amdgpu_display_funcs functions + *****************************************************************************/ + +/** + * dm_bandwidth_update - program display watermarks + * + * @adev: amdgpu_device pointer + * + * Calculate and program the display watermarks and line buffer allocation. + */ +static void dm_bandwidth_update(struct amdgpu_device *adev) +{ + AMDGPU_DM_NOT_IMPL("%s\n", __func__); +} + +static void dm_set_backlight_level(struct amdgpu_encoder *amdgpu_encoder, + u8 level) +{ + /* TODO: translate amdgpu_encoder to display_index and call DAL */ + AMDGPU_DM_NOT_IMPL("%s\n", __func__); +} + +static u8 dm_get_backlight_level(struct amdgpu_encoder *amdgpu_encoder) +{ + /* TODO: translate amdgpu_encoder to display_index and call DAL */ + AMDGPU_DM_NOT_IMPL("%s\n", __func__); + return 0; +} + +/****************************************************************************** + * Page Flip functions + ******************************************************************************/ + +/** + * dm_page_flip - called by amdgpu_flip_work_func(), which is triggered + * via DRM IOCTL, by user mode. + * + * @adev: amdgpu_device pointer + * @crtc_id: crtc to cleanup pageflip on + * @crtc_base: new address of the crtc (GPU MC address) + * + * Does the actual pageflip (surface address update). + */ +static void dm_page_flip(struct amdgpu_device *adev, + int crtc_id, u64 crtc_base, bool async) +{ + struct amdgpu_crtc *acrtc; + struct dc_target *target; + struct dc_flip_addrs addr = { {0} }; + + /* + * TODO risk of concurrency issues + * + * This should guarded by the dal_mutex but we can't do this since the + * caller uses a spin_lock on event_lock. + * + * If we wait on the dal_mutex a second page flip interrupt might come, + * spin on the event_lock, disabling interrupts while it does so. At + * this point the core can no longer be pre-empted and return to the + * thread that waited on the dal_mutex and we're deadlocked. + * + * With multiple cores the same essentially happens but might just take + * a little longer to lock up all cores. + * + * The reason we should lock on dal_mutex is so that we can be sure + * nobody messes with acrtc->target after we read and check its value. + * + * We might be able to fix our concurrency issues with a work queue + * where we schedule all work items (mode_set, page_flip, etc.) and + * execute them one by one. Care needs to be taken to still deal with + * any potential concurrency issues arising from interrupt calls. + */ + + acrtc = adev->mode_info.crtcs[crtc_id]; + target = acrtc->target; + + /* + * Received a page flip call after the display has been reset. + * Just return in this case. Everything should be clean-up on reset. + */ + + if (!target) { + WARN_ON(1); + return; + } + + addr.address.grph.addr.low_part = lower_32_bits(crtc_base); + addr.address.grph.addr.high_part = upper_32_bits(crtc_base); + addr.flip_immediate = async; + + DRM_DEBUG_DRIVER("%s Flipping to hi: 0x%x, low: 0x%x \n", + __func__, + addr.address.grph.addr.high_part, + addr.address.grph.addr.low_part); + + dc_flip_surface_addrs( + adev->dm.dc, + dc_target_get_status(target)->surfaces, + &addr, 1); +} + +static int amdgpu_notify_freesync(struct drm_device *dev, void *data, + struct drm_file *filp) +{ + struct mod_freesync_params freesync_params; + uint8_t num_targets; + uint8_t i; + struct dc_target *target; + + struct amdgpu_device *adev = dev->dev_private; + int r = 0; + + /* Get freesync enable flag from DRM */ + + num_targets = dc_get_current_target_count(adev->dm.dc); + + for (i = 0; i < num_targets; i++) { + + target = dc_get_target_at_index(adev->dm.dc, i); + + mod_freesync_update_state(adev->dm.freesync_module, + target->streams, + target->stream_count, + &freesync_params); + } + + return r; +} + +#ifdef CONFIG_DRM_AMDGPU_CIK +static const struct amdgpu_display_funcs dm_dce_v8_0_display_funcs = { + .bandwidth_update = dm_bandwidth_update, /* called unconditionally */ + .vblank_get_counter = dm_vblank_get_counter,/* called unconditionally */ + .vblank_wait = NULL, + .backlight_set_level = + dm_set_backlight_level,/* called unconditionally */ + .backlight_get_level = + dm_get_backlight_level,/* called unconditionally */ + .hpd_sense = NULL,/* called unconditionally */ + .hpd_set_polarity = NULL, /* called unconditionally */ + .hpd_get_gpio_reg = NULL, /* VBIOS parsing. DAL does it. */ + .page_flip = dm_page_flip, /* called unconditionally */ + .page_flip_get_scanoutpos = + dm_crtc_get_scanoutpos,/* called unconditionally */ + .add_encoder = NULL, /* VBIOS parsing. DAL does it. */ + .add_connector = NULL, /* VBIOS parsing. DAL does it. */ + .notify_freesync = amdgpu_notify_freesync, +}; +#endif + +static const struct amdgpu_display_funcs dm_dce_v10_0_display_funcs = { + .bandwidth_update = dm_bandwidth_update, /* called unconditionally */ + .vblank_get_counter = dm_vblank_get_counter,/* called unconditionally */ + .vblank_wait = NULL, + .backlight_set_level = + dm_set_backlight_level,/* called unconditionally */ + .backlight_get_level = + dm_get_backlight_level,/* called unconditionally */ + .hpd_sense = NULL,/* called unconditionally */ + .hpd_set_polarity = NULL, /* called unconditionally */ + .hpd_get_gpio_reg = NULL, /* VBIOS parsing. DAL does it. */ + .page_flip = dm_page_flip, /* called unconditionally */ + .page_flip_get_scanoutpos = + dm_crtc_get_scanoutpos,/* called unconditionally */ + .add_encoder = NULL, /* VBIOS parsing. DAL does it. */ + .add_connector = NULL, /* VBIOS parsing. DAL does it. */ + .notify_freesync = amdgpu_notify_freesync, + +}; + +static const struct amdgpu_display_funcs dm_dce_v11_0_display_funcs = { + .bandwidth_update = dm_bandwidth_update, /* called unconditionally */ + .vblank_get_counter = dm_vblank_get_counter,/* called unconditionally */ + .vblank_wait = NULL, + .backlight_set_level = + dm_set_backlight_level,/* called unconditionally */ + .backlight_get_level = + dm_get_backlight_level,/* called unconditionally */ + .hpd_sense = NULL,/* called unconditionally */ + .hpd_set_polarity = NULL, /* called unconditionally */ + .hpd_get_gpio_reg = NULL, /* VBIOS parsing. DAL does it. */ + .page_flip = dm_page_flip, /* called unconditionally */ + .page_flip_get_scanoutpos = + dm_crtc_get_scanoutpos,/* called unconditionally */ + .add_encoder = NULL, /* VBIOS parsing. DAL does it. */ + .add_connector = NULL, /* VBIOS parsing. DAL does it. */ + .notify_freesync = amdgpu_notify_freesync, + +}; + +#if defined(CONFIG_DEBUG_KERNEL_DC) + +static ssize_t s3_debug_store( + struct device *device, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + int ret; + int s3_state; + struct pci_dev *pdev = to_pci_dev(device); + struct drm_device *drm_dev = pci_get_drvdata(pdev); + struct amdgpu_device *adev = drm_dev->dev_private; + + ret = kstrtoint(buf, 0, &s3_state); + + if (ret == 0) { + if (s3_state) { + dm_resume(adev); + amdgpu_dm_display_resume(adev); + drm_kms_helper_hotplug_event(adev->ddev); + } else + dm_suspend(adev); + } + + return ret == 0 ? count : 0; +} + +DEVICE_ATTR_WO(s3_debug); + +#endif + +static int dm_early_init(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + amdgpu_dm_set_irq_funcs(adev); + + switch (adev->asic_type) { + case CHIP_BONAIRE: + case CHIP_HAWAII: + adev->mode_info.num_crtc = 6; + adev->mode_info.num_hpd = 6; + adev->mode_info.num_dig = 6; +#ifdef CONFIG_DRM_AMDGPU_CIK + if (adev->mode_info.funcs == NULL) + adev->mode_info.funcs = &dm_dce_v8_0_display_funcs; +#endif + break; + case CHIP_FIJI: + case CHIP_TONGA: + adev->mode_info.num_crtc = 6; + adev->mode_info.num_hpd = 6; + adev->mode_info.num_dig = 7; + if (adev->mode_info.funcs == NULL) + adev->mode_info.funcs = &dm_dce_v10_0_display_funcs; + break; + case CHIP_CARRIZO: + adev->mode_info.num_crtc = 3; + adev->mode_info.num_hpd = 6; + adev->mode_info.num_dig = 9; + if (adev->mode_info.funcs == NULL) + adev->mode_info.funcs = &dm_dce_v11_0_display_funcs; + break; + case CHIP_STONEY: + adev->mode_info.num_crtc = 2; + adev->mode_info.num_hpd = 6; + adev->mode_info.num_dig = 9; + if (adev->mode_info.funcs == NULL) + adev->mode_info.funcs = &dm_dce_v11_0_display_funcs; + break; + case CHIP_POLARIS11: + adev->mode_info.num_crtc = 5; + adev->mode_info.num_hpd = 5; + adev->mode_info.num_dig = 5; + if (adev->mode_info.funcs == NULL) + adev->mode_info.funcs = &dm_dce_v11_0_display_funcs; + break; + case CHIP_POLARIS10: + adev->mode_info.num_crtc = 6; + adev->mode_info.num_hpd = 6; + adev->mode_info.num_dig = 6; + if (adev->mode_info.funcs == NULL) + adev->mode_info.funcs = &dm_dce_v11_0_display_funcs; + break; + default: + DRM_ERROR("Usupported ASIC type: 0x%X\n", adev->asic_type); + return -EINVAL; + } + + /* Note: Do NOT change adev->audio_endpt_rreg and + * adev->audio_endpt_wreg because they are initialised in + * amdgpu_device_init() */ +#if defined(CONFIG_DEBUG_KERNEL_DC) + device_create_file( + adev->ddev->dev, + &dev_attr_s3_debug); +#endif + + return 0; +} + +bool amdgpu_dm_acquire_dal_lock(struct amdgpu_display_manager *dm) +{ + /* TODO */ + return true; +} + +bool amdgpu_dm_release_dal_lock(struct amdgpu_display_manager *dm) +{ + /* TODO */ + return true; +} + + diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h new file mode 100644 index 000000000000..1b54566f5da1 --- /dev/null +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -0,0 +1,171 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __AMDGPU_DM_H__ +#define __AMDGPU_DM_H__ + +/* +#include "linux/switch.h" +*/ + +/* + * This file contains the definition for amdgpu_display_manager + * and its API for amdgpu driver's use. + * This component provides all the display related functionality + * and this is the only component that calls DAL API. + * The API contained here intended for amdgpu driver use. + * The API that is called directly from KMS framework is located + * in amdgpu_dm_kms.h file + */ + +#define AMDGPU_DM_MAX_DISPLAY_INDEX 31 +/* +#include "include/amdgpu_dal_power_if.h" +#include "amdgpu_dm_irq.h" +*/ + +#include "irq_types.h" +#include "signal_types.h" + +/* Forward declarations */ +struct amdgpu_device; +struct drm_device; +struct amdgpu_dm_irq_handler_data; + +struct amdgpu_dm_prev_state { + struct drm_framebuffer *fb; + int32_t x; + int32_t y; + struct drm_display_mode mode; +}; + +struct common_irq_params { + struct amdgpu_device *adev; + enum dc_irq_source irq_src; +}; + +struct irq_list_head { + struct list_head head; + /* In case this interrupt needs post-processing, 'work' will be queued*/ + struct work_struct work; +}; + +struct amdgpu_display_manager { + struct dal *dal; + struct dc *dc; + struct cgs_device *cgs_device; + /* lock to be used when DAL is called from SYNC IRQ context */ + spinlock_t dal_lock; + + struct amdgpu_device *adev; /*AMD base driver*/ + struct drm_device *ddev; /*DRM base driver*/ + u16 display_indexes_num; + + struct amdgpu_dm_prev_state prev_state; + + /* + * 'irq_source_handler_table' holds a list of handlers + * per (DAL) IRQ source. + * + * Each IRQ source may need to be handled at different contexts. + * By 'context' we mean, for example: + * - The ISR context, which is the direct interrupt handler. + * - The 'deferred' context - this is the post-processing of the + * interrupt, but at a lower priority. + * + * Note that handlers are called in the same order as they were + * registered (FIFO). + */ + struct irq_list_head irq_handler_list_low_tab[DAL_IRQ_SOURCES_NUMBER]; + struct list_head irq_handler_list_high_tab[DAL_IRQ_SOURCES_NUMBER]; + + struct common_irq_params + pflip_params[DC_IRQ_SOURCE_PFLIP_LAST - DC_IRQ_SOURCE_PFLIP_FIRST + 1]; + + struct common_irq_params + vupdate_params[DC_IRQ_SOURCE_VUPDATE6 - DC_IRQ_SOURCE_VUPDATE1 + 1]; + + /* this spin lock synchronizes access to 'irq_handler_list_table' */ + spinlock_t irq_handler_list_table_lock; + + /* Timer-related data. */ + struct list_head timer_handler_list; + struct workqueue_struct *timer_workqueue; + + /* Use dal_mutex for any activity which is NOT syncronized by + * DRM mode setting locks. + * For example: amdgpu_dm_hpd_low_irq() calls into DAL *without* + * DRM mode setting locks being acquired. This is where dal_mutex + * is acquired before calling into DAL. */ + struct mutex dal_mutex; + + struct backlight_device *backlight_dev; + + const struct dc_link *backlight_link; + + struct work_struct mst_hotplug_work; + + struct mod_freesync *freesync_module; +}; + +/* basic init/fini API */ +int amdgpu_dm_init(struct amdgpu_device *adev); + +void amdgpu_dm_fini(struct amdgpu_device *adev); + +void amdgpu_dm_destroy(void); + +/* initializes drm_device display related structures, based on the information + * provided by DAL. The drm strcutures are: drm_crtc, drm_connector, + * drm_encoder, drm_mode_config + * + * Returns 0 on success + */ +int amdgpu_dm_initialize_drm_device( + struct amdgpu_device *adev); + +/* removes and deallocates the drm structures, created by the above function */ +void amdgpu_dm_destroy_drm_device( + struct amdgpu_display_manager *dm); + +/* Locking/Mutex */ +bool amdgpu_dm_acquire_dal_lock(struct amdgpu_display_manager *dm); + +bool amdgpu_dm_release_dal_lock(struct amdgpu_display_manager *dm); + +/* Register "Backlight device" accessible by user-mode. */ +void amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm); + +extern const struct amdgpu_ip_block_version dm_ip_block; + +void amdgpu_dm_update_connector_after_detect( + struct amdgpu_connector *aconnector); + +struct amdgpu_connector *amdgpu_dm_find_first_crct_matching_connector( + struct drm_atomic_state *state, + struct drm_crtc *crtc, + bool from_state_var); + +#endif /* __AMDGPU_DM_H__ */ diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c new file mode 100644 index 000000000000..d4e01b51f949 --- /dev/null +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -0,0 +1,484 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "dm_services.h" +#include "amdgpu.h" +#include "dc.h" +#include "amdgpu_dm.h" +#include "amdgpu_dm_irq.h" +#include "amdgpu_dm_types.h" + +#include "dm_helpers.h" + +/* dm_helpers_parse_edid_caps + * + * Parse edid caps + * + * @edid: [in] pointer to edid + * edid_caps: [in] pointer to edid caps + * @return + * void + * */ +enum dc_edid_status dm_helpers_parse_edid_caps( + struct dc_context *ctx, + const struct dc_edid *edid, + struct dc_edid_caps *edid_caps) +{ + struct edid *edid_buf = (struct edid *) edid->raw_edid; + struct cea_sad *sads; + int sad_count = -1; + int sadb_count = -1; + int i = 0; + int j = 0; + uint8_t *sadb = NULL; + + enum dc_edid_status result = EDID_OK; + + if (!edid_caps || !edid) + return EDID_BAD_INPUT; + + if (!drm_edid_is_valid(edid_buf)) + result = EDID_BAD_CHECKSUM; + + edid_caps->manufacturer_id = (uint16_t) edid_buf->mfg_id[0] | + ((uint16_t) edid_buf->mfg_id[1])<<8; + edid_caps->product_id = (uint16_t) edid_buf->prod_code[0] | + ((uint16_t) edid_buf->prod_code[1])<<8; + edid_caps->serial_number = edid_buf->serial; + edid_caps->manufacture_week = edid_buf->mfg_week; + edid_caps->manufacture_year = edid_buf->mfg_year; + + /* One of the four detailed_timings stores the monitor name. It's + * stored in an array of length 13. */ + for (i = 0; i < 4; i++) { + if (edid_buf->detailed_timings[i].data.other_data.type == 0xfc) { + while (j < 13 && edid_buf->detailed_timings[i].data.other_data.data.str.str[j]) { + if (edid_buf->detailed_timings[i].data.other_data.data.str.str[j] == '\n') + break; + + edid_caps->display_name[j] = + edid_buf->detailed_timings[i].data.other_data.data.str.str[j]; + j++; + } + } + } + + edid_caps->edid_hdmi = drm_detect_hdmi_monitor( + (struct edid *) edid->raw_edid); + + sad_count = drm_edid_to_sad((struct edid *) edid->raw_edid, &sads); + if (sad_count <= 0) { + DRM_INFO("SADs count is: %d, don't need to read it\n", + sad_count); + return result; + } + + edid_caps->audio_mode_count = sad_count < DC_MAX_AUDIO_DESC_COUNT ? sad_count : DC_MAX_AUDIO_DESC_COUNT; + for (i = 0; i < edid_caps->audio_mode_count; ++i) { + struct cea_sad *sad = &sads[i]; + + edid_caps->audio_modes[i].format_code = sad->format; + edid_caps->audio_modes[i].channel_count = sad->channels; + edid_caps->audio_modes[i].sample_rate = sad->freq; + edid_caps->audio_modes[i].sample_size = sad->byte2; + } + + sadb_count = drm_edid_to_speaker_allocation((struct edid *) edid->raw_edid, &sadb); + + if (sadb_count < 0) { + DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sadb_count); + sadb_count = 0; + } + + if (sadb_count) + edid_caps->speaker_flags = sadb[0]; + else + edid_caps->speaker_flags = DEFAULT_SPEAKER_LOCATION; + + kfree(sads); + kfree(sadb); + + return result; +} + +static struct amdgpu_connector *get_connector_for_sink( + struct drm_device *dev, + const struct dc_sink *sink) +{ + struct drm_connector *connector; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + if (aconnector->dc_sink == sink) + return aconnector; + } + + return NULL; +} + +static struct amdgpu_connector *get_connector_for_link( + struct drm_device *dev, + const struct dc_link *link) +{ + struct drm_connector *connector; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + if (aconnector->dc_link == link) + return aconnector; + } + + return NULL; +} + +static void get_payload_table( + struct amdgpu_connector *aconnector, + struct dp_mst_stream_allocation_table *proposed_table) +{ + int i; + struct drm_dp_mst_topology_mgr *mst_mgr = + &aconnector->mst_port->mst_mgr; + + mutex_lock(&mst_mgr->payload_lock); + + proposed_table->stream_count = 0; + + /* number of active streams */ + for (i = 0; i < mst_mgr->max_payloads; i++) { + if (mst_mgr->payloads[i].num_slots == 0) + break; /* end of vcp_id table */ + + ASSERT(mst_mgr->payloads[i].payload_state != + DP_PAYLOAD_DELETE_LOCAL); + + if (mst_mgr->payloads[i].payload_state == DP_PAYLOAD_LOCAL || + mst_mgr->payloads[i].payload_state == + DP_PAYLOAD_REMOTE) { + + struct dp_mst_stream_allocation *sa = + &proposed_table->stream_allocations[ + proposed_table->stream_count]; + + sa->slot_count = mst_mgr->payloads[i].num_slots; + sa->vcp_id = mst_mgr->proposed_vcpis[i]->vcpi; + proposed_table->stream_count++; + } + } + + mutex_unlock(&mst_mgr->payload_lock); +} + +/* + * Writes payload allocation table in immediate downstream device. + */ +bool dm_helpers_dp_mst_write_payload_allocation_table( + struct dc_context *ctx, + const struct dc_stream *stream, + struct dp_mst_stream_allocation_table *proposed_table, + bool enable) +{ + struct amdgpu_device *adev = ctx->driver_context; + struct drm_device *dev = adev->ddev; + struct amdgpu_connector *aconnector; + struct drm_dp_mst_topology_mgr *mst_mgr; + struct drm_dp_mst_port *mst_port; + int slots = 0; + bool ret; + int clock; + int bpp = 0; + int pbn = 0; + + aconnector = get_connector_for_sink(dev, stream->sink); + + if (!aconnector || !aconnector->mst_port) + return false; + + mst_mgr = &aconnector->mst_port->mst_mgr; + + if (!mst_mgr->mst_state) + return false; + + mst_port = aconnector->port; + + if (enable) { + clock = stream->timing.pix_clk_khz; + + switch (stream->timing.display_color_depth) { + + case COLOR_DEPTH_666: + bpp = 6; + break; + case COLOR_DEPTH_888: + bpp = 8; + break; + case COLOR_DEPTH_101010: + bpp = 10; + break; + case COLOR_DEPTH_121212: + bpp = 12; + break; + case COLOR_DEPTH_141414: + bpp = 14; + break; + case COLOR_DEPTH_161616: + bpp = 16; + break; + default: + ASSERT(bpp != 0); + break; + } + + bpp = bpp * 3; + + /* TODO need to know link rate */ + + pbn = drm_dp_calc_pbn_mode(clock, bpp); + + slots = drm_dp_find_vcpi_slots(mst_mgr, pbn); + ret = drm_dp_mst_allocate_vcpi(mst_mgr, mst_port, pbn, slots); + + if (!ret) + return false; + + } else { + drm_dp_mst_reset_vcpi_slots(mst_mgr, mst_port); + } + + ret = drm_dp_update_payload_part1(mst_mgr); + + /* mst_mgr->->payloads are VC payload notify MST branch using DPCD or + * AUX message. The sequence is slot 1-63 allocated sequence for each + * stream. AMD ASIC stream slot allocation should follow the same + * sequence. copy DRM MST allocation to dc */ + + get_payload_table(aconnector, proposed_table); + + if (ret) + return false; + + return true; +} + +/* + * Polls for ACT (allocation change trigger) handled and sends + * ALLOCATE_PAYLOAD message. + */ +bool dm_helpers_dp_mst_poll_for_allocation_change_trigger( + struct dc_context *ctx, + const struct dc_stream *stream) +{ + struct amdgpu_device *adev = ctx->driver_context; + struct drm_device *dev = adev->ddev; + struct amdgpu_connector *aconnector; + struct drm_dp_mst_topology_mgr *mst_mgr; + int ret; + + aconnector = get_connector_for_sink(dev, stream->sink); + + if (!aconnector || !aconnector->mst_port) + return false; + + mst_mgr = &aconnector->mst_port->mst_mgr; + + if (!mst_mgr->mst_state) + return false; + + ret = drm_dp_check_act_status(mst_mgr); + + if (ret) + return false; + + return true; +} + +bool dm_helpers_dp_mst_send_payload_allocation( + struct dc_context *ctx, + const struct dc_stream *stream, + bool enable) +{ + struct amdgpu_device *adev = ctx->driver_context; + struct drm_device *dev = adev->ddev; + struct amdgpu_connector *aconnector; + struct drm_dp_mst_topology_mgr *mst_mgr; + struct drm_dp_mst_port *mst_port; + int ret; + + aconnector = get_connector_for_sink(dev, stream->sink); + + if (!aconnector || !aconnector->mst_port) + return false; + + mst_port = aconnector->port; + + mst_mgr = &aconnector->mst_port->mst_mgr; + + if (!mst_mgr->mst_state) + return false; + + ret = drm_dp_update_payload_part2(mst_mgr); + + if (ret) + return false; + + if (!enable) + drm_dp_mst_deallocate_vcpi(mst_mgr, mst_port); + + return true; +} + +bool dm_helpers_dp_mst_start_top_mgr( + struct dc_context *ctx, + const struct dc_link *link, + bool boot) +{ + struct amdgpu_device *adev = ctx->driver_context; + struct drm_device *dev = adev->ddev; + struct amdgpu_connector *aconnector = get_connector_for_link(dev, link); + + if (!aconnector) { + DRM_ERROR("Failed to found connector for link!"); + return false; + } + + if (boot) { + DRM_INFO("DM_MST: Differing MST start on aconnector: %p [id: %d]\n", + aconnector, aconnector->base.base.id); + return true; + } + + DRM_INFO("DM_MST: starting TM on aconnector: %p [id: %d]\n", + aconnector, aconnector->base.base.id); + + return (drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_mgr, true) == 0); +} + +void dm_helpers_dp_mst_stop_top_mgr( + struct dc_context *ctx, + const struct dc_link *link) +{ + struct amdgpu_device *adev = ctx->driver_context; + struct drm_device *dev = adev->ddev; + struct amdgpu_connector *aconnector = get_connector_for_link(dev, link); + + if (!aconnector) { + DRM_ERROR("Failed to found connector for link!"); + return; + } + + DRM_INFO("DM_MST: stopping TM on aconnector: %p [id: %d]\n", + aconnector, aconnector->base.base.id); + + if (aconnector->mst_mgr.mst_state == true) + drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_mgr, false); +} + +bool dm_helpers_dp_read_dpcd( + struct dc_context *ctx, + const struct dc_link *link, + uint32_t address, + uint8_t *data, + uint32_t size) +{ + + struct amdgpu_device *adev = ctx->driver_context; + struct drm_device *dev = adev->ddev; + struct amdgpu_connector *aconnector = get_connector_for_link(dev, link); + + if (!aconnector) { + DRM_ERROR("Failed to found connector for link!"); + return false; + } + + return drm_dp_dpcd_read(&aconnector->dm_dp_aux.aux, address, + data, size) > 0; +} + +bool dm_helpers_dp_write_dpcd( + struct dc_context *ctx, + const struct dc_link *link, + uint32_t address, + const uint8_t *data, + uint32_t size) +{ + + struct amdgpu_device *adev = ctx->driver_context; + struct drm_device *dev = adev->ddev; + struct amdgpu_connector *aconnector = get_connector_for_link(dev, link); + + if (!aconnector) { + DRM_ERROR("Failed to found connector for link!"); + return false; + } + + return drm_dp_dpcd_write(&aconnector->dm_dp_aux.aux, + address, (uint8_t *)data, size) > 0; +} + +bool dm_helpers_submit_i2c( + struct dc_context *ctx, + const struct dc_link *link, + struct i2c_command *cmd) +{ + struct amdgpu_device *adev = ctx->driver_context; + struct drm_device *dev = adev->ddev; + struct amdgpu_connector *aconnector = get_connector_for_link(dev, link); + struct i2c_msg *msgs; + int i = 0; + int num = cmd->number_of_payloads; + bool result; + + if (!aconnector) { + DRM_ERROR("Failed to found connector for link!"); + return false; + } + + msgs = kzalloc(num * sizeof(struct i2c_msg), GFP_KERNEL); + + if (!msgs) + return false; + + for (i = 0; i < num; i++) { + msgs[i].flags = cmd->payloads[i].write ? I2C_M_RD : 0; + msgs[i].addr = cmd->payloads[i].address; + msgs[i].len = cmd->payloads[i].length; + msgs[i].buf = cmd->payloads[i].data; + } + + result = i2c_transfer(&aconnector->i2c->base, msgs, num) == num; + + kfree(msgs); + + return result; +} diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c new file mode 100644 index 000000000000..20e074971bff --- /dev/null +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c @@ -0,0 +1,829 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include + +#include "dm_services_types.h" +#include "dc.h" + +#include "amdgpu.h" +#include "amdgpu_dm.h" +#include "amdgpu_dm_irq.h" + +/****************************************************************************** + * Private declarations. + *****************************************************************************/ + +struct handler_common_data { + struct list_head list; + interrupt_handler handler; + void *handler_arg; + + /* DM which this handler belongs to */ + struct amdgpu_display_manager *dm; +}; + +struct amdgpu_dm_irq_handler_data { + struct handler_common_data hcd; + /* DAL irq source which registered for this interrupt. */ + enum dc_irq_source irq_source; +}; + +struct amdgpu_dm_timer_handler_data { + struct handler_common_data hcd; + struct delayed_work d_work; +}; + +#define DM_IRQ_TABLE_LOCK(adev, flags) \ + spin_lock_irqsave(&adev->dm.irq_handler_list_table_lock, flags) + +#define DM_IRQ_TABLE_UNLOCK(adev, flags) \ + spin_unlock_irqrestore(&adev->dm.irq_handler_list_table_lock, flags) + +/****************************************************************************** + * Private functions. + *****************************************************************************/ + +static void init_handler_common_data( + struct handler_common_data *hcd, + void (*ih)(void *), + void *args, + struct amdgpu_display_manager *dm) +{ + hcd->handler = ih; + hcd->handler_arg = args; + hcd->dm = dm; +} + +/** + * dm_irq_work_func - Handle an IRQ outside of the interrupt handler proper. + * + * @work: work struct + */ +static void dm_irq_work_func(struct work_struct *work) +{ + struct list_head *entry; + struct irq_list_head *irq_list_head = + container_of(work, struct irq_list_head, work); + struct list_head *handler_list = &irq_list_head->head; + struct amdgpu_dm_irq_handler_data *handler_data; + + list_for_each(entry, handler_list) { + handler_data = + list_entry( + entry, + struct amdgpu_dm_irq_handler_data, + hcd.list); + + DRM_DEBUG_KMS("DM_IRQ: work_func: for dal_src=%d\n", + handler_data->irq_source); + + DRM_DEBUG_KMS("DM_IRQ: schedule_work: for dal_src=%d\n", + handler_data->irq_source); + + handler_data->hcd.handler(handler_data->hcd.handler_arg); + } + + /* Call a DAL subcomponent which registered for interrupt notification + * at INTERRUPT_LOW_IRQ_CONTEXT. + * (The most common use is HPD interrupt) */ +} + +/** + * Remove a handler and return a pointer to hander list from which the + * handler was removed. + */ +static struct list_head *remove_irq_handler( + struct amdgpu_device *adev, + void *ih, + const struct dc_interrupt_params *int_params) +{ + struct list_head *hnd_list; + struct list_head *entry, *tmp; + struct amdgpu_dm_irq_handler_data *handler; + unsigned long irq_table_flags; + bool handler_removed = false; + enum dc_irq_source irq_source; + + DM_IRQ_TABLE_LOCK(adev, irq_table_flags); + + irq_source = int_params->irq_source; + + switch (int_params->int_context) { + case INTERRUPT_HIGH_IRQ_CONTEXT: + hnd_list = &adev->dm.irq_handler_list_high_tab[irq_source]; + break; + case INTERRUPT_LOW_IRQ_CONTEXT: + default: + hnd_list = &adev->dm.irq_handler_list_low_tab[irq_source].head; + break; + } + + list_for_each_safe(entry, tmp, hnd_list) { + + handler = list_entry(entry, struct amdgpu_dm_irq_handler_data, + hcd.list); + + if (ih == handler) { + /* Found our handler. Remove it from the list. */ + list_del(&handler->hcd.list); + handler_removed = true; + break; + } + } + + DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags); + + if (handler_removed == false) { + /* Not necessarily an error - caller may not + * know the context. */ + return NULL; + } + + kfree(handler); + + DRM_DEBUG_KMS( + "DM_IRQ: removed irq handler: %p for: dal_src=%d, irq context=%d\n", + ih, int_params->irq_source, int_params->int_context); + + return hnd_list; +} + +/* If 'handler_in == NULL' then remove ALL handlers. */ +static void remove_timer_handler( + struct amdgpu_device *adev, + struct amdgpu_dm_timer_handler_data *handler_in) +{ + struct amdgpu_dm_timer_handler_data *handler_temp; + struct list_head *handler_list; + struct list_head *entry, *tmp; + unsigned long irq_table_flags; + bool handler_removed = false; + + DM_IRQ_TABLE_LOCK(adev, irq_table_flags); + + handler_list = &adev->dm.timer_handler_list; + + list_for_each_safe(entry, tmp, handler_list) { + /* Note that list_for_each_safe() guarantees that + * handler_temp is NOT null. */ + handler_temp = list_entry(entry, + struct amdgpu_dm_timer_handler_data, hcd.list); + + if (handler_in == NULL || handler_in == handler_temp) { + list_del(&handler_temp->hcd.list); + DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags); + + DRM_DEBUG_KMS("DM_IRQ: removing timer handler: %p\n", + handler_temp); + + if (handler_in == NULL) { + /* Since it is still in the queue, it must + * be cancelled. */ + cancel_delayed_work_sync(&handler_temp->d_work); + } + + kfree(handler_temp); + handler_removed = true; + + DM_IRQ_TABLE_LOCK(adev, irq_table_flags); + } + + if (handler_in == NULL) { + /* Remove ALL handlers. */ + continue; + } + + if (handler_in == handler_temp) { + /* Remove a SPECIFIC handler. + * Found our handler - we can stop here. */ + break; + } + } + + DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags); + + if (handler_in != NULL && handler_removed == false) { + DRM_ERROR("DM_IRQ: handler: %p is not in the list!\n", + handler_in); + } +} + +/** + * dm_timer_work_func - Handle a timer. + * + * @work: work struct + */ +static void dm_timer_work_func( + struct work_struct *work) +{ + struct amdgpu_dm_timer_handler_data *handler_data = + container_of(work, struct amdgpu_dm_timer_handler_data, + d_work.work); + + DRM_DEBUG_KMS("DM_IRQ: work_func: handler_data=%p\n", handler_data); + + /* Call a DAL subcomponent which registered for timer notification. */ + handler_data->hcd.handler(handler_data->hcd.handler_arg); + + /* We support only "single shot" timers. That means we must delete + * the handler after it was called. */ + remove_timer_handler(handler_data->hcd.dm->adev, handler_data); +} + +static bool validate_irq_registration_params( + struct dc_interrupt_params *int_params, + void (*ih)(void *)) +{ + if (NULL == int_params || NULL == ih) { + DRM_ERROR("DM_IRQ: invalid input!\n"); + return false; + } + + if (int_params->int_context >= INTERRUPT_CONTEXT_NUMBER) { + DRM_ERROR("DM_IRQ: invalid context: %d!\n", + int_params->int_context); + return false; + } + + if (!DAL_VALID_IRQ_SRC_NUM(int_params->irq_source)) { + DRM_ERROR("DM_IRQ: invalid irq_source: %d!\n", + int_params->irq_source); + return false; + } + + return true; +} + +static bool validate_irq_unregistration_params( + enum dc_irq_source irq_source, + irq_handler_idx handler_idx) +{ + if (DAL_INVALID_IRQ_HANDLER_IDX == handler_idx) { + DRM_ERROR("DM_IRQ: invalid handler_idx==NULL!\n"); + return false; + } + + if (!DAL_VALID_IRQ_SRC_NUM(irq_source)) { + DRM_ERROR("DM_IRQ: invalid irq_source:%d!\n", irq_source); + return false; + } + + return true; +} +/****************************************************************************** + * Public functions. + * + * Note: caller is responsible for input validation. + *****************************************************************************/ + +void *amdgpu_dm_irq_register_interrupt( + struct amdgpu_device *adev, + struct dc_interrupt_params *int_params, + void (*ih)(void *), + void *handler_args) +{ + struct list_head *hnd_list; + struct amdgpu_dm_irq_handler_data *handler_data; + unsigned long irq_table_flags; + enum dc_irq_source irq_source; + + if (false == validate_irq_registration_params(int_params, ih)) + return DAL_INVALID_IRQ_HANDLER_IDX; + + handler_data = kzalloc(sizeof(*handler_data), GFP_KERNEL); + if (!handler_data) { + DRM_ERROR("DM_IRQ: failed to allocate irq handler!\n"); + return DAL_INVALID_IRQ_HANDLER_IDX; + } + + memset(handler_data, 0, sizeof(*handler_data)); + + init_handler_common_data(&handler_data->hcd, ih, handler_args, + &adev->dm); + + irq_source = int_params->irq_source; + + handler_data->irq_source = irq_source; + + /* Lock the list, add the handler. */ + DM_IRQ_TABLE_LOCK(adev, irq_table_flags); + + switch (int_params->int_context) { + case INTERRUPT_HIGH_IRQ_CONTEXT: + hnd_list = &adev->dm.irq_handler_list_high_tab[irq_source]; + break; + case INTERRUPT_LOW_IRQ_CONTEXT: + default: + hnd_list = &adev->dm.irq_handler_list_low_tab[irq_source].head; + break; + } + + list_add_tail(&handler_data->hcd.list, hnd_list); + + DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags); + + /* This pointer will be stored by code which requested interrupt + * registration. + * The same pointer will be needed in order to unregister the + * interrupt. */ + + DRM_DEBUG_KMS( + "DM_IRQ: added irq handler: %p for: dal_src=%d, irq context=%d\n", + handler_data, + irq_source, + int_params->int_context); + + return handler_data; +} + +void amdgpu_dm_irq_unregister_interrupt( + struct amdgpu_device *adev, + enum dc_irq_source irq_source, + void *ih) +{ + struct list_head *handler_list; + struct dc_interrupt_params int_params; + int i; + + if (false == validate_irq_unregistration_params(irq_source, ih)) + return; + + memset(&int_params, 0, sizeof(int_params)); + + int_params.irq_source = irq_source; + + for (i = 0; i < INTERRUPT_CONTEXT_NUMBER; i++) { + + int_params.int_context = i; + + handler_list = remove_irq_handler(adev, ih, &int_params); + + if (handler_list != NULL) + break; + } + + if (handler_list == NULL) { + /* If we got here, it means we searched all irq contexts + * for this irq source, but the handler was not found. */ + DRM_ERROR( + "DM_IRQ: failed to find irq handler:%p for irq_source:%d!\n", + ih, irq_source); + } +} + +int amdgpu_dm_irq_init( + struct amdgpu_device *adev) +{ + int src; + struct irq_list_head *lh; + + DRM_DEBUG_KMS("DM_IRQ\n"); + + spin_lock_init(&adev->dm.irq_handler_list_table_lock); + + for (src = 0; src < DAL_IRQ_SOURCES_NUMBER; src++) { + /* low context handler list init */ + lh = &adev->dm.irq_handler_list_low_tab[src]; + INIT_LIST_HEAD(&lh->head); + INIT_WORK(&lh->work, dm_irq_work_func); + + /* high context handler init */ + INIT_LIST_HEAD(&adev->dm.irq_handler_list_high_tab[src]); + } + + INIT_LIST_HEAD(&adev->dm.timer_handler_list); + + /* allocate and initialize the workqueue for DM timer */ + adev->dm.timer_workqueue = create_singlethread_workqueue( + "dm_timer_queue"); + if (adev->dm.timer_workqueue == NULL) { + DRM_ERROR("DM_IRQ: unable to create timer queue!\n"); + return -1; + } + + return 0; +} + +void amdgpu_dm_irq_register_timer( + struct amdgpu_device *adev, + struct dc_timer_interrupt_params *int_params, + interrupt_handler ih, + void *args) +{ + unsigned long jf_delay; + struct list_head *handler_list; + struct amdgpu_dm_timer_handler_data *handler_data; + unsigned long irq_table_flags; + + handler_data = kzalloc(sizeof(*handler_data), GFP_KERNEL); + if (!handler_data) { + DRM_ERROR("DM_IRQ: failed to allocate timer handler!\n"); + return; + } + + memset(handler_data, 0, sizeof(*handler_data)); + + init_handler_common_data(&handler_data->hcd, ih, args, &adev->dm); + + INIT_DELAYED_WORK(&handler_data->d_work, dm_timer_work_func); + + /* Lock the list, add the handler. */ + DM_IRQ_TABLE_LOCK(adev, irq_table_flags); + + handler_list = &adev->dm.timer_handler_list; + + list_add_tail(&handler_data->hcd.list, handler_list); + + DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags); + + jf_delay = usecs_to_jiffies(int_params->micro_sec_interval); + + queue_delayed_work(adev->dm.timer_workqueue, &handler_data->d_work, + jf_delay); + + DRM_DEBUG_KMS("DM_IRQ: added handler:%p with micro_sec_interval=%u\n", + handler_data, int_params->micro_sec_interval); + return; +} + +/* DM IRQ and timer resource release */ +void amdgpu_dm_irq_fini( + struct amdgpu_device *adev) +{ + int src; + struct irq_list_head *lh; + DRM_DEBUG_KMS("DM_IRQ: releasing resources.\n"); + + for (src = 0; src < DAL_IRQ_SOURCES_NUMBER; src++) { + + /* The handler was removed from the table, + * it means it is safe to flush all the 'work' + * (because no code can schedule a new one). */ + lh = &adev->dm.irq_handler_list_low_tab[src]; + flush_work(&lh->work); + } + + /* Cancel ALL timers and release handlers (if any). */ + remove_timer_handler(adev, NULL); + /* Release the queue itself. */ + destroy_workqueue(adev->dm.timer_workqueue); +} + +int amdgpu_dm_irq_suspend( + struct amdgpu_device *adev) +{ + int src; + struct list_head *hnd_list_h; + struct list_head *hnd_list_l; + unsigned long irq_table_flags; + + DM_IRQ_TABLE_LOCK(adev, irq_table_flags); + + DRM_DEBUG_KMS("DM_IRQ: suspend\n"); + + /* disable HW interrupt */ + for (src = DC_IRQ_SOURCE_HPD1; src < DAL_IRQ_SOURCES_NUMBER; src++) { + hnd_list_l = &adev->dm.irq_handler_list_low_tab[src].head; + hnd_list_h = &adev->dm.irq_handler_list_high_tab[src]; + if (!list_empty(hnd_list_l) || !list_empty(hnd_list_h)) + dc_interrupt_set(adev->dm.dc, src, false); + + DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags); + flush_work(&adev->dm.irq_handler_list_low_tab[src].work); + + DM_IRQ_TABLE_LOCK(adev, irq_table_flags); + } + + DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags); + return 0; +} + +int amdgpu_dm_irq_resume_early(struct amdgpu_device *adev) +{ + int src; + struct list_head *hnd_list_h, *hnd_list_l; + unsigned long irq_table_flags; + + DM_IRQ_TABLE_LOCK(adev, irq_table_flags); + + DRM_DEBUG_KMS("DM_IRQ: early resume\n"); + + /* re-enable short pulse interrupts HW interrupt */ + for (src = DC_IRQ_SOURCE_HPD1RX; src < DC_IRQ_SOURCE_HPD6RX + 1; src++) { + hnd_list_l = &adev->dm.irq_handler_list_low_tab[src].head; + hnd_list_h = &adev->dm.irq_handler_list_high_tab[src]; + if (!list_empty(hnd_list_l) || !list_empty(hnd_list_h)) + dc_interrupt_set(adev->dm.dc, src, true); + } + + DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags); + + return 0; +} + +int amdgpu_dm_irq_resume(struct amdgpu_device *adev) +{ + int src; + struct list_head *hnd_list_h, *hnd_list_l; + unsigned long irq_table_flags; + + DM_IRQ_TABLE_LOCK(adev, irq_table_flags); + + DRM_DEBUG_KMS("DM_IRQ: resume\n"); + + /* re-enable HW interrupt */ + for (src = DC_IRQ_SOURCE_HPD1; src < DAL_IRQ_SOURCES_NUMBER; src++) { + hnd_list_l = &adev->dm.irq_handler_list_low_tab[src].head; + hnd_list_h = &adev->dm.irq_handler_list_high_tab[src]; + if (!list_empty(hnd_list_l) || !list_empty(hnd_list_h)) + dc_interrupt_set(adev->dm.dc, src, true); + } + + DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags); + return 0; +} + +/** + * amdgpu_dm_irq_schedule_work - schedule all work items registered for the + * "irq_source". + */ +static void amdgpu_dm_irq_schedule_work( + struct amdgpu_device *adev, + enum dc_irq_source irq_source) +{ + unsigned long irq_table_flags; + struct work_struct *work = NULL; + + DM_IRQ_TABLE_LOCK(adev, irq_table_flags); + + if (!list_empty(&adev->dm.irq_handler_list_low_tab[irq_source].head)) + work = &adev->dm.irq_handler_list_low_tab[irq_source].work; + + DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags); + + if (work) { + if (!schedule_work(work)) + DRM_INFO("amdgpu_dm_irq_schedule_work FAILED src %d\n", + irq_source); + } + +} + +/** amdgpu_dm_irq_immediate_work + * Callback high irq work immediately, don't send to work queue + */ +static void amdgpu_dm_irq_immediate_work( + struct amdgpu_device *adev, + enum dc_irq_source irq_source) +{ + struct amdgpu_dm_irq_handler_data *handler_data; + struct list_head *entry; + unsigned long irq_table_flags; + + DM_IRQ_TABLE_LOCK(adev, irq_table_flags); + + list_for_each( + entry, + &adev->dm.irq_handler_list_high_tab[irq_source]) { + + handler_data = + list_entry( + entry, + struct amdgpu_dm_irq_handler_data, + hcd.list); + + /* Call a subcomponent which registered for immediate + * interrupt notification */ + handler_data->hcd.handler(handler_data->hcd.handler_arg); + } + + DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags); +} + +/* + * amdgpu_dm_irq_handler + * + * Generic IRQ handler, calls all registered high irq work immediately, and + * schedules work for low irq + */ +int amdgpu_dm_irq_handler( + struct amdgpu_device *adev, + struct amdgpu_irq_src *source, + struct amdgpu_iv_entry *entry) +{ + + enum dc_irq_source src = + dc_interrupt_to_irq_source( + adev->dm.dc, + entry->src_id, + entry->src_data[0]); + + dc_interrupt_ack(adev->dm.dc, src); + + /* Call high irq work immediately */ + amdgpu_dm_irq_immediate_work(adev, src); + /*Schedule low_irq work */ + amdgpu_dm_irq_schedule_work(adev, src); + + return 0; +} + +static enum dc_irq_source amdgpu_dm_hpd_to_dal_irq_source(unsigned type) +{ + switch (type) { + case AMDGPU_HPD_1: + return DC_IRQ_SOURCE_HPD1; + case AMDGPU_HPD_2: + return DC_IRQ_SOURCE_HPD2; + case AMDGPU_HPD_3: + return DC_IRQ_SOURCE_HPD3; + case AMDGPU_HPD_4: + return DC_IRQ_SOURCE_HPD4; + case AMDGPU_HPD_5: + return DC_IRQ_SOURCE_HPD5; + case AMDGPU_HPD_6: + return DC_IRQ_SOURCE_HPD6; + default: + return DC_IRQ_SOURCE_INVALID; + } +} + +static int amdgpu_dm_set_hpd_irq_state(struct amdgpu_device *adev, + struct amdgpu_irq_src *source, + unsigned type, + enum amdgpu_interrupt_state state) +{ + enum dc_irq_source src = amdgpu_dm_hpd_to_dal_irq_source(type); + bool st = (state == AMDGPU_IRQ_STATE_ENABLE); + + dc_interrupt_set(adev->dm.dc, src, st); + return 0; +} + +static inline int dm_irq_state( + struct amdgpu_device *adev, + struct amdgpu_irq_src *source, + unsigned crtc_id, + enum amdgpu_interrupt_state state, + const enum irq_type dal_irq_type, + const char *func) +{ + bool st; + enum dc_irq_source irq_source; + + struct amdgpu_crtc *acrtc = adev->mode_info.crtcs[crtc_id]; + + if (!acrtc) { + DRM_ERROR( + "%s: crtc is NULL at id :%d\n", + func, + crtc_id); + return 0; + } + + irq_source = dal_irq_type + acrtc->otg_inst; + + st = (state == AMDGPU_IRQ_STATE_ENABLE); + + dc_interrupt_set(adev->dm.dc, irq_source, st); + return 0; +} + +static int amdgpu_dm_set_pflip_irq_state(struct amdgpu_device *adev, + struct amdgpu_irq_src *source, + unsigned crtc_id, + enum amdgpu_interrupt_state state) +{ + return dm_irq_state( + adev, + source, + crtc_id, + state, + IRQ_TYPE_PFLIP, + __func__); +} + +static int amdgpu_dm_set_crtc_irq_state(struct amdgpu_device *adev, + struct amdgpu_irq_src *source, + unsigned crtc_id, + enum amdgpu_interrupt_state state) +{ + return dm_irq_state( + adev, + source, + crtc_id, + state, + IRQ_TYPE_VUPDATE, + __func__); +} + +static const struct amdgpu_irq_src_funcs dm_crtc_irq_funcs = { + .set = amdgpu_dm_set_crtc_irq_state, + .process = amdgpu_dm_irq_handler, +}; + +static const struct amdgpu_irq_src_funcs dm_pageflip_irq_funcs = { + .set = amdgpu_dm_set_pflip_irq_state, + .process = amdgpu_dm_irq_handler, +}; + +static const struct amdgpu_irq_src_funcs dm_hpd_irq_funcs = { + .set = amdgpu_dm_set_hpd_irq_state, + .process = amdgpu_dm_irq_handler, +}; + +void amdgpu_dm_set_irq_funcs(struct amdgpu_device *adev) +{ + adev->crtc_irq.num_types = AMDGPU_CRTC_IRQ_LAST; + adev->crtc_irq.funcs = &dm_crtc_irq_funcs; + + adev->pageflip_irq.num_types = AMDGPU_PAGEFLIP_IRQ_LAST; + adev->pageflip_irq.funcs = &dm_pageflip_irq_funcs; + + adev->hpd_irq.num_types = AMDGPU_HPD_LAST; + adev->hpd_irq.funcs = &dm_hpd_irq_funcs; +} + +/* + * amdgpu_dm_hpd_init - hpd setup callback. + * + * @adev: amdgpu_device pointer + * + * Setup the hpd pins used by the card (evergreen+). + * Enable the pin, set the polarity, and enable the hpd interrupts. + */ +void amdgpu_dm_hpd_init(struct amdgpu_device *adev) +{ + struct drm_device *dev = adev->ddev; + struct drm_connector *connector; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + struct amdgpu_connector *amdgpu_connector = + to_amdgpu_connector(connector); + + const struct dc_link *dc_link = amdgpu_connector->dc_link; + + if (DC_IRQ_SOURCE_INVALID != dc_link->irq_source_hpd) { + dc_interrupt_set(adev->dm.dc, + dc_link->irq_source_hpd, + true); + } + + if (DC_IRQ_SOURCE_INVALID != dc_link->irq_source_hpd_rx) { + dc_interrupt_set(adev->dm.dc, + dc_link->irq_source_hpd_rx, + true); + } + } +} + +/** + * amdgpu_dm_hpd_fini - hpd tear down callback. + * + * @adev: amdgpu_device pointer + * + * Tear down the hpd pins used by the card (evergreen+). + * Disable the hpd interrupts. + */ +void amdgpu_dm_hpd_fini(struct amdgpu_device *adev) +{ + struct drm_device *dev = adev->ddev; + struct drm_connector *connector; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + struct amdgpu_connector *amdgpu_connector = + to_amdgpu_connector(connector); + const struct dc_link *dc_link = amdgpu_connector->dc_link; + + dc_interrupt_set(adev->dm.dc, dc_link->irq_source_hpd, false); + + if (DC_IRQ_SOURCE_INVALID != dc_link->irq_source_hpd_rx) { + dc_interrupt_set(adev->dm.dc, + dc_link->irq_source_hpd_rx, + false); + } + } +} diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h new file mode 100644 index 000000000000..9339861c8897 --- /dev/null +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h @@ -0,0 +1,122 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef __AMDGPU_DM_IRQ_H__ +#define __AMDGPU_DM_IRQ_H__ + +#include "irq_types.h" /* DAL irq definitions */ + +/* + * Display Manager IRQ-related interfaces (for use by DAL). + */ + +/** + * amdgpu_dm_irq_init - Initialize internal structures of 'amdgpu_dm_irq'. + * + * This function should be called exactly once - during DM initialization. + * + * Returns: + * 0 - success + * non-zero - error + */ +int amdgpu_dm_irq_init( + struct amdgpu_device *adev); + +/** + * amdgpu_dm_irq_fini - deallocate internal structures of 'amdgpu_dm_irq'. + * + * This function should be called exactly once - during DM destruction. + * + */ +void amdgpu_dm_irq_fini( + struct amdgpu_device *adev); + +/** + * amdgpu_dm_irq_register_interrupt - register irq handler for Display block. + * + * @adev: AMD DRM device + * @int_params: parameters for the irq + * @ih: pointer to the irq hander function + * @handler_args: arguments which will be passed to ih + * + * Returns: + * IRQ Handler Index on success. + * NULL on failure. + * + * Cannot be called from an interrupt handler. + */ +void *amdgpu_dm_irq_register_interrupt( + struct amdgpu_device *adev, + struct dc_interrupt_params *int_params, + void (*ih)(void *), + void *handler_args); + +/** + * amdgpu_dm_irq_unregister_interrupt - unregister handler which was registered + * by amdgpu_dm_irq_register_interrupt(). + * + * @adev: AMD DRM device. + * @ih_index: irq handler index which was returned by + * amdgpu_dm_irq_register_interrupt + */ +void amdgpu_dm_irq_unregister_interrupt( + struct amdgpu_device *adev, + enum dc_irq_source irq_source, + void *ih_index); + +void amdgpu_dm_irq_register_timer( + struct amdgpu_device *adev, + struct dc_timer_interrupt_params *int_params, + interrupt_handler ih, + void *args); + +/** + * amdgpu_dm_irq_handler + * Generic IRQ handler, calls all registered high irq work immediately, and + * schedules work for low irq + */ +int amdgpu_dm_irq_handler( + struct amdgpu_device *adev, + struct amdgpu_irq_src *source, + struct amdgpu_iv_entry *entry); + +void amdgpu_dm_set_irq_funcs(struct amdgpu_device *adev); + +void amdgpu_dm_hpd_init(struct amdgpu_device *adev); +void amdgpu_dm_hpd_fini(struct amdgpu_device *adev); + +/** + * amdgpu_dm_irq_suspend - disable ASIC interrupt during suspend. + * + */ +int amdgpu_dm_irq_suspend(struct amdgpu_device *adev); + +/** + * amdgpu_dm_irq_resume_early - enable HPDRX ASIC interrupts during resume. + * amdgpu_dm_irq_resume - enable ASIC interrupt during resume. + * + */ +int amdgpu_dm_irq_resume_early(struct amdgpu_device *adev); +int amdgpu_dm_irq_resume(struct amdgpu_device *adev); + +#endif /* __AMDGPU_DM_IRQ_H__ */ diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c new file mode 100644 index 000000000000..e4d94d4c215d --- /dev/null +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -0,0 +1,443 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include +#include +#include "dm_services.h" +#include "amdgpu.h" +#include "amdgpu_dm_types.h" +#include "amdgpu_dm_mst_types.h" + +#include "dc.h" +#include "dm_helpers.h" + +/* #define TRACE_DPCD */ + +#ifdef TRACE_DPCD +#define SIDE_BAND_MSG(address) (address >= DP_SIDEBAND_MSG_DOWN_REQ_BASE && address < DP_SINK_COUNT_ESI) + +static inline char *side_band_msg_type_to_str(uint32_t address) +{ + static char str[10] = {0}; + + if (address < DP_SIDEBAND_MSG_UP_REP_BASE) + strcpy(str, "DOWN_REQ"); + else if (address < DP_SIDEBAND_MSG_DOWN_REP_BASE) + strcpy(str, "UP_REP"); + else if (address < DP_SIDEBAND_MSG_UP_REQ_BASE) + strcpy(str, "DOWN_REP"); + else + strcpy(str, "UP_REQ"); + + return str; +} + +void log_dpcd(uint8_t type, + uint32_t address, + uint8_t *data, + uint32_t size, + bool res) +{ + DRM_DEBUG_KMS("Op: %s, addr: %04x, SideBand Msg: %s, Op res: %s\n", + (type == DP_AUX_NATIVE_READ) || + (type == DP_AUX_I2C_READ) ? + "Read" : "Write", + address, + SIDE_BAND_MSG(address) ? + side_band_msg_type_to_str(address) : "Nop", + res ? "OK" : "Fail"); + + if (res) { + print_hex_dump(KERN_INFO, "Body: ", DUMP_PREFIX_NONE, 16, 1, data, size, false); + } +} +#endif + +static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) +{ + struct pci_dev *pdev = to_pci_dev(aux->dev); + struct drm_device *drm_dev = pci_get_drvdata(pdev); + struct amdgpu_device *adev = drm_dev->dev_private; + struct dc *dc = adev->dm.dc; + bool res; + + switch (msg->request) { + case DP_AUX_NATIVE_READ: + res = dc_read_dpcd( + dc, + TO_DM_AUX(aux)->link_index, + msg->address, + msg->buffer, + msg->size); + break; + case DP_AUX_NATIVE_WRITE: + res = dc_write_dpcd( + dc, + TO_DM_AUX(aux)->link_index, + msg->address, + msg->buffer, + msg->size); + break; + default: + return 0; + } + +#ifdef TRACE_DPCD + log_dpcd(msg->request, + msg->address, + msg->buffer, + msg->size, + res); +#endif + + return msg->size; +} + +static enum drm_connector_status +dm_dp_mst_detect(struct drm_connector *connector, bool force) +{ + struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + struct amdgpu_connector *master = aconnector->mst_port; + + enum drm_connector_status status = + drm_dp_mst_detect_port( + connector, + &master->mst_mgr, + aconnector->port); + + /* + * we do not want to make this connector connected until we have edid on + * it + */ + if (status == connector_status_connected && + !aconnector->port->cached_edid) + status = connector_status_disconnected; + + return status; +} + +static void +dm_dp_mst_connector_destroy(struct drm_connector *connector) +{ + struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); + struct amdgpu_encoder *amdgpu_encoder = amdgpu_connector->mst_encoder; + + drm_encoder_cleanup(&amdgpu_encoder->base); + kfree(amdgpu_encoder); + drm_connector_cleanup(connector); + kfree(amdgpu_connector); +} + +static const struct drm_connector_funcs dm_dp_mst_connector_funcs = { + .detect = dm_dp_mst_detect, + .fill_modes = drm_helper_probe_single_connector_modes, + .destroy = dm_dp_mst_connector_destroy, + .reset = amdgpu_dm_connector_funcs_reset, + .atomic_duplicate_state = amdgpu_dm_connector_atomic_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, + .atomic_set_property = amdgpu_dm_connector_atomic_set_property +}; + +static int dm_dp_mst_get_modes(struct drm_connector *connector) +{ + struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + int ret = 0; + + ret = drm_add_edid_modes(&aconnector->base, aconnector->edid); + + drm_edid_to_eld(&aconnector->base, aconnector->edid); + + return ret; +} + +static struct drm_encoder *dm_mst_best_encoder(struct drm_connector *connector) +{ + struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); + + return &amdgpu_connector->mst_encoder->base; +} + +static const struct drm_connector_helper_funcs dm_dp_mst_connector_helper_funcs = { + .get_modes = dm_dp_mst_get_modes, + .mode_valid = amdgpu_dm_connector_mode_valid, + .best_encoder = dm_mst_best_encoder, +}; + +static struct amdgpu_encoder * +dm_dp_create_fake_mst_encoder(struct amdgpu_connector *connector) +{ + struct drm_device *dev = connector->base.dev; + struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_encoder *amdgpu_encoder; + struct drm_encoder *encoder; + const struct drm_connector_helper_funcs *connector_funcs = + connector->base.helper_private; + struct drm_encoder *enc_master = + connector_funcs->best_encoder(&connector->base); + + DRM_DEBUG_KMS("enc master is %p\n", enc_master); + amdgpu_encoder = kzalloc(sizeof(*amdgpu_encoder), GFP_KERNEL); + if (!amdgpu_encoder) + return NULL; + + encoder = &amdgpu_encoder->base; + encoder->possible_crtcs = amdgpu_dm_get_encoder_crtc_mask(adev); + + drm_encoder_init( + dev, + &amdgpu_encoder->base, + NULL, + DRM_MODE_ENCODER_DPMST, + NULL); + + drm_encoder_helper_add(encoder, &amdgpu_dm_encoder_helper_funcs); + + return amdgpu_encoder; +} + +static struct drm_connector *dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr, + struct drm_dp_mst_port *port, + const char *pathprop) +{ + struct amdgpu_connector *master = container_of(mgr, struct amdgpu_connector, mst_mgr); + struct drm_device *dev = master->base.dev; + struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_connector *aconnector; + struct drm_connector *connector; + + drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + aconnector = to_amdgpu_connector(connector); + if (aconnector->mst_port == master + && !aconnector->port) { + DRM_INFO("DM_MST: reusing connector: %p [id: %d] [master: %p]\n", + aconnector, connector->base.id, aconnector->mst_port); + + aconnector->port = port; + drm_mode_connector_set_path_property(connector, pathprop); + + drm_modeset_unlock(&dev->mode_config.connection_mutex); + return &aconnector->base; + } + } + drm_modeset_unlock(&dev->mode_config.connection_mutex); + + aconnector = kzalloc(sizeof(*aconnector), GFP_KERNEL); + if (!aconnector) + return NULL; + + connector = &aconnector->base; + aconnector->port = port; + aconnector->mst_port = master; + + if (drm_connector_init( + dev, + connector, + &dm_dp_mst_connector_funcs, + DRM_MODE_CONNECTOR_DisplayPort)) { + kfree(aconnector); + return NULL; + } + drm_connector_helper_add(connector, &dm_dp_mst_connector_helper_funcs); + + amdgpu_dm_connector_init_helper( + &adev->dm, + aconnector, + DRM_MODE_CONNECTOR_DisplayPort, + master->dc_link, + master->connector_id); + + aconnector->mst_encoder = dm_dp_create_fake_mst_encoder(master); + + /* + * TODO: understand why this one is needed + */ + drm_object_attach_property( + &connector->base, + dev->mode_config.path_property, + 0); + drm_object_attach_property( + &connector->base, + dev->mode_config.tile_property, + 0); + + drm_mode_connector_set_path_property(connector, pathprop); + + /* + * Initialize connector state before adding the connectror to drm and + * framebuffer lists + */ + amdgpu_dm_connector_funcs_reset(connector); + + DRM_INFO("DM_MST: added connector: %p [id: %d] [master: %p]\n", + aconnector, connector->base.id, aconnector->mst_port); + + DRM_DEBUG_KMS(":%d\n", connector->base.id); + + return connector; +} + +static void dm_dp_destroy_mst_connector( + struct drm_dp_mst_topology_mgr *mgr, + struct drm_connector *connector) +{ + struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + + DRM_INFO("DM_MST: Disabling connector: %p [id: %d] [master: %p]\n", + aconnector, connector->base.id, aconnector->mst_port); + + aconnector->port = NULL; + if (aconnector->dc_sink) { + amdgpu_dm_remove_sink_from_freesync_module(connector); + dc_link_remove_remote_sink(aconnector->dc_link, aconnector->dc_sink); + dc_sink_release(aconnector->dc_sink); + aconnector->dc_sink = NULL; + } + if (aconnector->edid) { + kfree(aconnector->edid); + aconnector->edid = NULL; + } + + drm_mode_connector_update_edid_property( + &aconnector->base, + NULL); +} + +static void dm_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr) +{ + struct amdgpu_connector *master = container_of(mgr, struct amdgpu_connector, mst_mgr); + struct drm_device *dev = master->base.dev; + struct amdgpu_device *adev = dev->dev_private; + struct drm_connector *connector; + struct amdgpu_connector *aconnector; + struct edid *edid; + + drm_modeset_lock_all(dev); + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + aconnector = to_amdgpu_connector(connector); + if (aconnector->port && + aconnector->port->pdt != DP_PEER_DEVICE_NONE && + aconnector->port->pdt != DP_PEER_DEVICE_MST_BRANCHING && + !aconnector->dc_sink) { + /* + * This is plug in case, where port has been created but + * sink hasn't been created yet + */ + if (!aconnector->edid) { + struct dc_sink_init_data init_params = { + .link = aconnector->dc_link, + .sink_signal = SIGNAL_TYPE_DISPLAY_PORT_MST}; + edid = drm_dp_mst_get_edid(connector, &aconnector->mst_port->mst_mgr, aconnector->port); + + if (!edid) { + drm_mode_connector_update_edid_property( + &aconnector->base, + NULL); + continue; + } + + aconnector->edid = edid; + + aconnector->dc_sink = dc_link_add_remote_sink( + aconnector->dc_link, + (uint8_t *)edid, + (edid->extensions + 1) * EDID_LENGTH, + &init_params); + if (aconnector->dc_sink) + amdgpu_dm_add_sink_to_freesync_module( + connector, + edid); + + dm_restore_drm_connector_state(connector->dev, connector); + } else + edid = aconnector->edid; + + DRM_DEBUG_KMS("edid retrieved %p\n", edid); + + drm_mode_connector_update_edid_property( + &aconnector->base, + aconnector->edid); + } + } + drm_modeset_unlock_all(dev); + + schedule_work(&adev->dm.mst_hotplug_work); +} + +static void dm_dp_mst_register_connector(struct drm_connector *connector) +{ + struct drm_device *dev = connector->dev; + struct amdgpu_device *adev = dev->dev_private; + int i; + + drm_modeset_lock_all(dev); + if (adev->mode_info.rfbdev) { + /*Do not add if already registered in past*/ + for (i = 0; i < adev->mode_info.rfbdev->helper.connector_count; i++) { + if (adev->mode_info.rfbdev->helper.connector_info[i]->connector + == connector) { + drm_modeset_unlock_all(dev); + return; + } + } + + drm_fb_helper_add_one_connector(&adev->mode_info.rfbdev->helper, connector); + } + else + DRM_ERROR("adev->mode_info.rfbdev is NULL\n"); + + drm_modeset_unlock_all(dev); + + drm_connector_register(connector); + +} + +static const struct drm_dp_mst_topology_cbs dm_mst_cbs = { + .add_connector = dm_dp_add_mst_connector, + .destroy_connector = dm_dp_destroy_mst_connector, + .hotplug = dm_dp_mst_hotplug, + .register_connector = dm_dp_mst_register_connector +}; + +void amdgpu_dm_initialize_mst_connector( + struct amdgpu_display_manager *dm, + struct amdgpu_connector *aconnector) +{ + aconnector->dm_dp_aux.aux.name = "dmdc"; + aconnector->dm_dp_aux.aux.dev = dm->adev->dev; + aconnector->dm_dp_aux.aux.transfer = dm_dp_aux_transfer; + aconnector->dm_dp_aux.link_index = aconnector->connector_id; + + drm_dp_aux_register(&aconnector->dm_dp_aux.aux); + aconnector->mst_mgr.cbs = &dm_mst_cbs; + drm_dp_mst_topology_mgr_init( + &aconnector->mst_mgr, + dm->adev->ddev, + &aconnector->dm_dp_aux.aux, + 16, + 4, + aconnector->connector_id); +} + diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h new file mode 100644 index 000000000000..6130d62ac65c --- /dev/null +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h @@ -0,0 +1,36 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_AMDGPU_DM_MST_TYPES_H__ +#define __DAL_AMDGPU_DM_MST_TYPES_H__ + +struct amdgpu_display_manager; +struct amdgpu_connector; + +void amdgpu_dm_initialize_mst_connector( + struct amdgpu_display_manager *dm, + struct amdgpu_connector *aconnector); + +#endif diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c new file mode 100644 index 000000000000..9d5125951acd --- /dev/null +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c @@ -0,0 +1,463 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include +#include + +#include +#include +#include +#include "dm_services.h" +#include "amdgpu.h" +#include "amdgpu_dm.h" +#include "amdgpu_dm_irq.h" +#include "amdgpu_dm_types.h" +#include "amdgpu_pm.h" + +#define dm_alloc(size) kzalloc(size, GFP_KERNEL) +#define dm_realloc(ptr, size) krealloc(ptr, size, GFP_KERNEL) +#define dm_free(ptr) kfree(ptr) + +/****************************************************************************** + * IRQ Interfaces. + *****************************************************************************/ + +void dal_register_timer_interrupt( + struct dc_context *ctx, + struct dc_timer_interrupt_params *int_params, + interrupt_handler ih, + void *args) +{ + struct amdgpu_device *adev = ctx->driver_context; + + if (!adev || !int_params) { + DRM_ERROR("DM_IRQ: invalid input!\n"); + return; + } + + if (int_params->int_context != INTERRUPT_LOW_IRQ_CONTEXT) { + /* only low irq ctx is supported. */ + DRM_ERROR("DM_IRQ: invalid context: %d!\n", + int_params->int_context); + return; + } + + amdgpu_dm_irq_register_timer(adev, int_params, ih, args); +} + +void dal_isr_acquire_lock(struct dc_context *ctx) +{ + /*TODO*/ +} + +void dal_isr_release_lock(struct dc_context *ctx) +{ + /*TODO*/ +} + +/****************************************************************************** + * End-of-IRQ Interfaces. + *****************************************************************************/ + +bool dm_get_platform_info(struct dc_context *ctx, + struct platform_info_params *params) +{ + /*TODO*/ + return false; +} + +bool dm_write_persistent_data(struct dc_context *ctx, + const struct dc_sink *sink, + const char *module_name, + const char *key_name, + void *params, + unsigned int size, + struct persistent_data_flag *flag) +{ + /*TODO implement*/ + return false; +} + +bool dm_read_persistent_data(struct dc_context *ctx, + const struct dc_sink *sink, + const char *module_name, + const char *key_name, + void *params, + unsigned int size, + struct persistent_data_flag *flag) +{ + /*TODO implement*/ + return false; +} + +void dm_delay_in_microseconds(struct dc_context *ctx, + unsigned int microSeconds) +{ + /*TODO implement*/ + return; +} + +/**** power component interfaces ****/ + +bool dm_pp_pre_dce_clock_change( + struct dc_context *ctx, + struct dm_pp_gpu_clock_range *requested_state, + struct dm_pp_gpu_clock_range *actual_state) +{ + /*TODO*/ + return false; +} + +bool dm_pp_apply_safe_state( + const struct dc_context *ctx) +{ + struct amdgpu_device *adev = ctx->driver_context; + + if (adev->pm.dpm_enabled) { + /* TODO: Does this require PreModeChange event to PPLIB? */ + } + + return true; +} + +bool dm_pp_apply_display_requirements( + const struct dc_context *ctx, + const struct dm_pp_display_configuration *pp_display_cfg) +{ + struct amdgpu_device *adev = ctx->driver_context; + + if (adev->pm.dpm_enabled) { + + memset(&adev->pm.pm_display_cfg, 0, + sizeof(adev->pm.pm_display_cfg)); + + adev->pm.pm_display_cfg.cpu_cc6_disable = + pp_display_cfg->cpu_cc6_disable; + + adev->pm.pm_display_cfg.cpu_pstate_disable = + pp_display_cfg->cpu_pstate_disable; + + adev->pm.pm_display_cfg.cpu_pstate_separation_time = + pp_display_cfg->cpu_pstate_separation_time; + + adev->pm.pm_display_cfg.nb_pstate_switch_disable = + pp_display_cfg->nb_pstate_switch_disable; + + adev->pm.pm_display_cfg.num_display = + pp_display_cfg->display_count; + adev->pm.pm_display_cfg.num_path_including_non_display = + pp_display_cfg->display_count; + + adev->pm.pm_display_cfg.min_core_set_clock = + pp_display_cfg->min_engine_clock_khz/10; + adev->pm.pm_display_cfg.min_core_set_clock_in_sr = + pp_display_cfg->min_engine_clock_deep_sleep_khz/10; + adev->pm.pm_display_cfg.min_mem_set_clock = + pp_display_cfg->min_memory_clock_khz/10; + + adev->pm.pm_display_cfg.multi_monitor_in_sync = + pp_display_cfg->all_displays_in_sync; + adev->pm.pm_display_cfg.min_vblank_time = + pp_display_cfg->avail_mclk_switch_time_us; + + adev->pm.pm_display_cfg.display_clk = + pp_display_cfg->disp_clk_khz/10; + + adev->pm.pm_display_cfg.dce_tolerable_mclk_in_active_latency = + pp_display_cfg->avail_mclk_switch_time_in_disp_active_us; + + adev->pm.pm_display_cfg.crtc_index = pp_display_cfg->crtc_index; + adev->pm.pm_display_cfg.line_time_in_us = + pp_display_cfg->line_time_in_us; + + adev->pm.pm_display_cfg.vrefresh = pp_display_cfg->disp_configs[0].v_refresh; + adev->pm.pm_display_cfg.crossfire_display_index = -1; + adev->pm.pm_display_cfg.min_bus_bandwidth = 0; + + /* TODO: complete implementation of + * amd_powerplay_display_configuration_change(). + * Follow example of: + * PHM_StoreDALConfigurationData - powerplay\hwmgr\hardwaremanager.c + * PP_IRI_DisplayConfigurationChange - powerplay\eventmgr\iri.c */ + amd_powerplay_display_configuration_change( + adev->powerplay.pp_handle, + &adev->pm.pm_display_cfg); + + /* TODO: replace by a separate call to 'apply display cfg'? */ + amdgpu_pm_compute_clocks(adev); + } + + return true; +} + +bool dc_service_get_system_clocks_range( + const struct dc_context *ctx, + struct dm_pp_gpu_clock_range *sys_clks) +{ + struct amdgpu_device *adev = ctx->driver_context; + + /* Default values, in case PPLib is not compiled-in. */ + sys_clks->mclk.max_khz = 800000; + sys_clks->mclk.min_khz = 800000; + + sys_clks->sclk.max_khz = 600000; + sys_clks->sclk.min_khz = 300000; + + if (adev->pm.dpm_enabled) { + sys_clks->mclk.max_khz = amdgpu_dpm_get_mclk(adev, false); + sys_clks->mclk.min_khz = amdgpu_dpm_get_mclk(adev, true); + + sys_clks->sclk.max_khz = amdgpu_dpm_get_sclk(adev, false); + sys_clks->sclk.min_khz = amdgpu_dpm_get_sclk(adev, true); + } + + return true; +} + +static void get_default_clock_levels( + enum dm_pp_clock_type clk_type, + struct dm_pp_clock_levels *clks) +{ + uint32_t disp_clks_in_khz[6] = { + 300000, 400000, 496560, 626090, 685720, 757900 }; + uint32_t sclks_in_khz[6] = { + 300000, 360000, 423530, 514290, 626090, 720000 }; + uint32_t mclks_in_khz[2] = { 333000, 800000 }; + + switch (clk_type) { + case DM_PP_CLOCK_TYPE_DISPLAY_CLK: + clks->num_levels = 6; + memmove(clks->clocks_in_khz, disp_clks_in_khz, + sizeof(disp_clks_in_khz)); + break; + case DM_PP_CLOCK_TYPE_ENGINE_CLK: + clks->num_levels = 6; + memmove(clks->clocks_in_khz, sclks_in_khz, + sizeof(sclks_in_khz)); + break; + case DM_PP_CLOCK_TYPE_MEMORY_CLK: + clks->num_levels = 2; + memmove(clks->clocks_in_khz, mclks_in_khz, + sizeof(mclks_in_khz)); + break; + default: + clks->num_levels = 0; + break; + } +} + +static enum amd_pp_clock_type dc_to_pp_clock_type( + enum dm_pp_clock_type dm_pp_clk_type) +{ + enum amd_pp_clock_type amd_pp_clk_type = 0; + + switch (dm_pp_clk_type) { + case DM_PP_CLOCK_TYPE_DISPLAY_CLK: + amd_pp_clk_type = amd_pp_disp_clock; + break; + case DM_PP_CLOCK_TYPE_ENGINE_CLK: + amd_pp_clk_type = amd_pp_sys_clock; + break; + case DM_PP_CLOCK_TYPE_MEMORY_CLK: + amd_pp_clk_type = amd_pp_mem_clock; + break; + default: + DRM_ERROR("DM_PPLIB: invalid clock type: %d!\n", + dm_pp_clk_type); + break; + } + + return amd_pp_clk_type; +} + +static void pp_to_dc_clock_levels( + const struct amd_pp_clocks *pp_clks, + struct dm_pp_clock_levels *dc_clks, + enum dm_pp_clock_type dc_clk_type) +{ + uint32_t i; + + if (pp_clks->count > DM_PP_MAX_CLOCK_LEVELS) { + DRM_INFO("DM_PPLIB: Warning: %s clock: number of levels %d exceeds maximum of %d!\n", + DC_DECODE_PP_CLOCK_TYPE(dc_clk_type), + pp_clks->count, + DM_PP_MAX_CLOCK_LEVELS); + + dc_clks->num_levels = DM_PP_MAX_CLOCK_LEVELS; + } else + dc_clks->num_levels = pp_clks->count; + + DRM_INFO("DM_PPLIB: values for %s clock\n", + DC_DECODE_PP_CLOCK_TYPE(dc_clk_type)); + + for (i = 0; i < dc_clks->num_levels; i++) { + DRM_INFO("DM_PPLIB:\t %d\n", pp_clks->clock[i]); + /* translate 10kHz to kHz */ + dc_clks->clocks_in_khz[i] = pp_clks->clock[i] * 10; + } +} + +bool dm_pp_get_clock_levels_by_type( + const struct dc_context *ctx, + enum dm_pp_clock_type clk_type, + struct dm_pp_clock_levels *dc_clks) +{ + struct amdgpu_device *adev = ctx->driver_context; + void *pp_handle = adev->powerplay.pp_handle; + struct amd_pp_clocks pp_clks = { 0 }; + struct amd_pp_simple_clock_info validation_clks = { 0 }; + uint32_t i; + + if (amd_powerplay_get_clock_by_type(pp_handle, + dc_to_pp_clock_type(clk_type), &pp_clks)) { + /* Error in pplib. Provide default values. */ + get_default_clock_levels(clk_type, dc_clks); + return true; + } + + pp_to_dc_clock_levels(&pp_clks, dc_clks, clk_type); + + if (amd_powerplay_get_display_mode_validation_clocks(pp_handle, + &validation_clks)) { + /* Error in pplib. Provide default values. */ + DRM_INFO("DM_PPLIB: Warning: using default validation clocks!\n"); + validation_clks.engine_max_clock = 72000; + validation_clks.memory_max_clock = 80000; + validation_clks.level = 0; + } + + DRM_INFO("DM_PPLIB: Validation clocks:\n"); + DRM_INFO("DM_PPLIB: engine_max_clock: %d\n", + validation_clks.engine_max_clock); + DRM_INFO("DM_PPLIB: memory_max_clock: %d\n", + validation_clks.memory_max_clock); + DRM_INFO("DM_PPLIB: level : %d\n", + validation_clks.level); + + /* Translate 10 kHz to kHz. */ + validation_clks.engine_max_clock *= 10; + validation_clks.memory_max_clock *= 10; + + /* Determine the highest non-boosted level from the Validation Clocks */ + if (clk_type == DM_PP_CLOCK_TYPE_ENGINE_CLK) { + for (i = 0; i < dc_clks->num_levels; i++) { + if (dc_clks->clocks_in_khz[i] > validation_clks.engine_max_clock) { + /* This clock is higher the validation clock. + * Than means the previous one is the highest + * non-boosted one. */ + DRM_INFO("DM_PPLIB: reducing engine clock level from %d to %d\n", + dc_clks->num_levels, i + 1); + dc_clks->num_levels = i; + break; + } + } + } else if (clk_type == DM_PP_CLOCK_TYPE_MEMORY_CLK) { + for (i = 0; i < dc_clks->num_levels; i++) { + if (dc_clks->clocks_in_khz[i] > validation_clks.memory_max_clock) { + DRM_INFO("DM_PPLIB: reducing memory clock level from %d to %d\n", + dc_clks->num_levels, i + 1); + dc_clks->num_levels = i; + break; + } + } + } + + return true; +} + +bool dm_pp_get_clock_levels_by_type_with_latency( + const struct dc_context *ctx, + enum dm_pp_clock_type clk_type, + struct dm_pp_clock_levels_with_latency *clk_level_info) +{ + /* TODO: to be implemented */ + return false; +} + +bool dm_pp_get_clock_levels_by_type_with_voltage( + const struct dc_context *ctx, + enum dm_pp_clock_type clk_type, + struct dm_pp_clock_levels_with_voltage *clk_level_info) +{ + /* TODO: to be implemented */ + return false; +} + +bool dm_pp_notify_wm_clock_changes( + const struct dc_context *ctx, + struct dm_pp_wm_sets_with_clock_ranges *wm_with_clock_ranges) +{ + /* TODO: to be implemented */ + return false; +} + +bool dm_pp_apply_power_level_change_request( + const struct dc_context *ctx, + struct dm_pp_power_level_change_request *level_change_req) +{ + /* TODO: to be implemented */ + return false; +} + +bool dm_pp_apply_clock_for_voltage_request( + const struct dc_context *ctx, + struct dm_pp_clock_for_voltage_req *clock_for_voltage_req) +{ + /* TODO: to be implemented */ + return false; +} + +bool dm_pp_get_static_clocks( + const struct dc_context *ctx, + struct dm_pp_static_clock_info *static_clk_info) +{ + /* TODO: to be implemented */ + return false; +} + +/**** end of power component interfaces ****/ + +/* Calls to notification */ + +void dal_notify_setmode_complete(struct dc_context *ctx, + uint32_t h_total, + uint32_t v_total, + uint32_t h_active, + uint32_t v_active, + uint32_t pix_clk_in_khz) +{ + /*TODO*/ +} +/* End of calls to notification */ + +long dm_get_pid(void) +{ + return current->pid; +} + +long dm_get_tgid(void) +{ + return current->tgid; +} diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c new file mode 100644 index 000000000000..c073f4558cf4 --- /dev/null +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -0,0 +1,3150 @@ +/* + * Copyright 2012-13 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include "amdgpu.h" +#include "amdgpu_pm.h" +#include "dm_services_types.h" + +// We need to #undef FRAME_SIZE and DEPRECATED because they conflict +// with ptrace-abi.h's #define's of them. +#undef FRAME_SIZE +#undef DEPRECATED + +#include "dc.h" + +#include "amdgpu_dm_types.h" +#include "amdgpu_dm_mst_types.h" + +#include "modules/inc/mod_freesync.h" + +struct dm_connector_state { + struct drm_connector_state base; + + enum amdgpu_rmx_type scaling; + uint8_t underscan_vborder; + uint8_t underscan_hborder; + bool underscan_enable; +}; + +#define to_dm_connector_state(x)\ + container_of((x), struct dm_connector_state, base) + + +void amdgpu_dm_encoder_destroy(struct drm_encoder *encoder) +{ + drm_encoder_cleanup(encoder); + kfree(encoder); +} + +static const struct drm_encoder_funcs amdgpu_dm_encoder_funcs = { + .destroy = amdgpu_dm_encoder_destroy, +}; + +static void dm_set_cursor( + struct amdgpu_crtc *amdgpu_crtc, + uint64_t gpu_addr, + uint32_t width, + uint32_t height) +{ + struct dc_cursor_attributes attributes; + amdgpu_crtc->cursor_width = width; + amdgpu_crtc->cursor_height = height; + + attributes.address.high_part = upper_32_bits(gpu_addr); + attributes.address.low_part = lower_32_bits(gpu_addr); + attributes.width = width; + attributes.height = height; + attributes.x_hot = 0; + attributes.y_hot = 0; + attributes.color_format = CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA; + attributes.rotation_angle = 0; + attributes.attribute_flags.value = 0; + + if (!dc_target_set_cursor_attributes( + amdgpu_crtc->target, + &attributes)) { + DRM_ERROR("DC failed to set cursor attributes\n"); + } +} + +static int dm_crtc_unpin_cursor_bo_old( + struct amdgpu_crtc *amdgpu_crtc) +{ + struct amdgpu_bo *robj; + int ret = 0; + + if (NULL != amdgpu_crtc && NULL != amdgpu_crtc->cursor_bo) { + robj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo); + + ret = amdgpu_bo_reserve(robj, false); + + if (likely(ret == 0)) { + ret = amdgpu_bo_unpin(robj); + + if (unlikely(ret != 0)) { + DRM_ERROR( + "%s: unpin failed (ret=%d), bo %p\n", + __func__, + ret, + amdgpu_crtc->cursor_bo); + } + + amdgpu_bo_unreserve(robj); + } else { + DRM_ERROR( + "%s: reserve failed (ret=%d), bo %p\n", + __func__, + ret, + amdgpu_crtc->cursor_bo); + } + + drm_gem_object_unreference_unlocked(amdgpu_crtc->cursor_bo); + amdgpu_crtc->cursor_bo = NULL; + } + + return ret; +} + +static int dm_crtc_pin_cursor_bo_new( + struct drm_crtc *crtc, + struct drm_file *file_priv, + uint32_t handle, + struct amdgpu_bo **ret_obj) +{ + struct amdgpu_crtc *amdgpu_crtc; + struct amdgpu_bo *robj; + struct drm_gem_object *obj; + int ret = -EINVAL; + + if (NULL != crtc) { + struct drm_device *dev = crtc->dev; + struct amdgpu_device *adev = dev->dev_private; + uint64_t gpu_addr; + + amdgpu_crtc = to_amdgpu_crtc(crtc); + + obj = drm_gem_object_lookup(file_priv, handle); + + if (!obj) { + DRM_ERROR( + "Cannot find cursor object %x for crtc %d\n", + handle, + amdgpu_crtc->crtc_id); + goto release; + } + robj = gem_to_amdgpu_bo(obj); + + ret = amdgpu_bo_reserve(robj, false); + + if (unlikely(ret != 0)) { + drm_gem_object_unreference_unlocked(obj); + DRM_ERROR("dm_crtc_pin_cursor_bo_new ret %x, handle %x\n", + ret, handle); + goto release; + } + + ret = amdgpu_bo_pin_restricted(robj, AMDGPU_GEM_DOMAIN_VRAM, 0, + adev->mc.visible_vram_size, + &gpu_addr); + + if (ret == 0) { + amdgpu_crtc->cursor_addr = gpu_addr; + *ret_obj = robj; + } + amdgpu_bo_unreserve(robj); + if (ret) + drm_gem_object_unreference_unlocked(obj); + + } +release: + + return ret; +} + +static int dm_crtc_cursor_set( + struct drm_crtc *crtc, + struct drm_file *file_priv, + uint32_t handle, + uint32_t width, + uint32_t height) +{ + struct amdgpu_bo *new_cursor_bo; + struct dc_cursor_position position; + + int ret; + + struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); + + ret = EINVAL; + new_cursor_bo = NULL; + + DRM_DEBUG_KMS( + "%s: crtc_id=%d with handle %d and size %d to %d, bo_object %p\n", + __func__, + amdgpu_crtc->crtc_id, + handle, + width, + height, + amdgpu_crtc->cursor_bo); + + if (!handle) { + /* turn off cursor */ + position.enable = false; + position.x = 0; + position.y = 0; + position.hot_spot_enable = false; + + if (amdgpu_crtc->target) { + /*set cursor visible false*/ + dc_target_set_cursor_position( + amdgpu_crtc->target, + &position); + } + /*unpin old cursor buffer and update cache*/ + ret = dm_crtc_unpin_cursor_bo_old(amdgpu_crtc); + goto release; + + } + + if ((width > amdgpu_crtc->max_cursor_width) || + (height > amdgpu_crtc->max_cursor_height)) { + DRM_ERROR( + "%s: bad cursor width or height %d x %d\n", + __func__, + width, + height); + goto release; + } + /*try to pin new cursor bo*/ + ret = dm_crtc_pin_cursor_bo_new(crtc, file_priv, handle, &new_cursor_bo); + /*if map not successful then return an error*/ + if (ret) + goto release; + + /*program new cursor bo to hardware*/ + dm_set_cursor(amdgpu_crtc, amdgpu_crtc->cursor_addr, width, height); + + /*un map old, not used anymore cursor bo , + * return memory and mapping back */ + dm_crtc_unpin_cursor_bo_old(amdgpu_crtc); + + /*assign new cursor bo to our internal cache*/ + amdgpu_crtc->cursor_bo = &new_cursor_bo->gem_base; + +release: + return ret; + +} + +static int dm_crtc_cursor_move(struct drm_crtc *crtc, + int x, int y) +{ + struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); + int xorigin = 0, yorigin = 0; + struct dc_cursor_position position; + + /* avivo cursor are offset into the total surface */ + x += crtc->primary->state->src_x >> 16; + y += crtc->primary->state->src_y >> 16; + + /* + * TODO: for cursor debugging unguard the following + */ +#if 0 + DRM_DEBUG_KMS( + "%s: x %d y %d c->x %d c->y %d\n", + __func__, + x, + y, + crtc->x, + crtc->y); +#endif + + if (x < 0) { + xorigin = min(-x, amdgpu_crtc->max_cursor_width - 1); + x = 0; + } + if (y < 0) { + yorigin = min(-y, amdgpu_crtc->max_cursor_height - 1); + y = 0; + } + + position.enable = true; + position.x = x; + position.y = y; + + position.hot_spot_enable = true; + position.x_hotspot = xorigin; + position.y_hotspot = yorigin; + + if (amdgpu_crtc->target) { + if (!dc_target_set_cursor_position( + amdgpu_crtc->target, + &position)) { + DRM_ERROR("DC failed to set cursor position\n"); + return -EINVAL; + } + } + + return 0; +} + +static void dm_crtc_cursor_reset(struct drm_crtc *crtc) +{ + struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); + + DRM_DEBUG_KMS( + "%s: with cursor_bo %p\n", + __func__, + amdgpu_crtc->cursor_bo); + + if (amdgpu_crtc->cursor_bo && amdgpu_crtc->target) { + dm_set_cursor( + amdgpu_crtc, + amdgpu_crtc->cursor_addr, + amdgpu_crtc->cursor_width, + amdgpu_crtc->cursor_height); + } +} +static bool fill_rects_from_plane_state( + const struct drm_plane_state *state, + struct dc_surface *surface) +{ + surface->src_rect.x = state->src_x >> 16; + surface->src_rect.y = state->src_y >> 16; + /*we ignore for now mantissa and do not to deal with floating pixels :(*/ + surface->src_rect.width = state->src_w >> 16; + + if (surface->src_rect.width == 0) + return false; + + surface->src_rect.height = state->src_h >> 16; + if (surface->src_rect.height == 0) + return false; + + surface->dst_rect.x = state->crtc_x; + surface->dst_rect.y = state->crtc_y; + + if (state->crtc_w == 0) + return false; + + surface->dst_rect.width = state->crtc_w; + + if (state->crtc_h == 0) + return false; + + surface->dst_rect.height = state->crtc_h; + + surface->clip_rect = surface->dst_rect; + + switch (state->rotation & DRM_MODE_ROTATE_MASK) { + case DRM_MODE_ROTATE_0: + surface->rotation = ROTATION_ANGLE_0; + break; + case DRM_MODE_ROTATE_90: + surface->rotation = ROTATION_ANGLE_90; + break; + case DRM_MODE_ROTATE_180: + surface->rotation = ROTATION_ANGLE_180; + break; + case DRM_MODE_ROTATE_270: + surface->rotation = ROTATION_ANGLE_270; + break; + default: + surface->rotation = ROTATION_ANGLE_0; + break; + } + + return true; +} +static bool get_fb_info( + const struct amdgpu_framebuffer *amdgpu_fb, + uint64_t *tiling_flags, + uint64_t *fb_location) +{ + struct amdgpu_bo *rbo = gem_to_amdgpu_bo(amdgpu_fb->obj); + int r = amdgpu_bo_reserve(rbo, false); + if (unlikely(r != 0)){ + DRM_ERROR("Unable to reserve buffer\n"); + return false; + } + + if (fb_location) + *fb_location = amdgpu_bo_gpu_offset(rbo); + + if (tiling_flags) + amdgpu_bo_get_tiling_flags(rbo, tiling_flags); + + amdgpu_bo_unreserve(rbo); + + return true; +} +static void fill_plane_attributes_from_fb( + struct dc_surface *surface, + const struct amdgpu_framebuffer *amdgpu_fb, bool addReq) +{ + uint64_t tiling_flags; + uint64_t fb_location = 0; + const struct drm_framebuffer *fb = &amdgpu_fb->base; + struct drm_format_name_buf format_name; + + get_fb_info( + amdgpu_fb, + &tiling_flags, + addReq == true ? &fb_location:NULL); + + surface->address.type = PLN_ADDR_TYPE_GRAPHICS; + surface->address.grph.addr.low_part = lower_32_bits(fb_location); + surface->address.grph.addr.high_part = upper_32_bits(fb_location); + + switch (fb->format->format) { + case DRM_FORMAT_C8: + surface->format = SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS; + break; + case DRM_FORMAT_RGB565: + surface->format = SURFACE_PIXEL_FORMAT_GRPH_RGB565; + break; + case DRM_FORMAT_XRGB8888: + case DRM_FORMAT_ARGB8888: + surface->format = SURFACE_PIXEL_FORMAT_GRPH_ARGB8888; + break; + case DRM_FORMAT_XRGB2101010: + case DRM_FORMAT_ARGB2101010: + surface->format = SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010; + break; + case DRM_FORMAT_XBGR2101010: + case DRM_FORMAT_ABGR2101010: + surface->format = SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010; + break; + default: + DRM_ERROR("Unsupported screen format %s\n", + drm_get_format_name(fb->format->format, &format_name)); + return; + } + + memset(&surface->tiling_info, 0, sizeof(surface->tiling_info)); + + if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE) == DC_ARRAY_2D_TILED_THIN1) + { + unsigned bankw, bankh, mtaspect, tile_split, num_banks; + + bankw = AMDGPU_TILING_GET(tiling_flags, BANK_WIDTH); + bankh = AMDGPU_TILING_GET(tiling_flags, BANK_HEIGHT); + mtaspect = AMDGPU_TILING_GET(tiling_flags, MACRO_TILE_ASPECT); + tile_split = AMDGPU_TILING_GET(tiling_flags, TILE_SPLIT); + num_banks = AMDGPU_TILING_GET(tiling_flags, NUM_BANKS); + + /* XXX fix me for VI */ + surface->tiling_info.gfx8.num_banks = num_banks; + surface->tiling_info.gfx8.array_mode = + DC_ARRAY_2D_TILED_THIN1; + surface->tiling_info.gfx8.tile_split = tile_split; + surface->tiling_info.gfx8.bank_width = bankw; + surface->tiling_info.gfx8.bank_height = bankh; + surface->tiling_info.gfx8.tile_aspect = mtaspect; + surface->tiling_info.gfx8.tile_mode = + DC_ADDR_SURF_MICRO_TILING_DISPLAY; + } else if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE) + == DC_ARRAY_1D_TILED_THIN1) { + surface->tiling_info.gfx8.array_mode = DC_ARRAY_1D_TILED_THIN1; + } + + surface->tiling_info.gfx8.pipe_config = + AMDGPU_TILING_GET(tiling_flags, PIPE_CONFIG); + + surface->plane_size.grph.surface_size.x = 0; + surface->plane_size.grph.surface_size.y = 0; + surface->plane_size.grph.surface_size.width = fb->width; + surface->plane_size.grph.surface_size.height = fb->height; + surface->plane_size.grph.surface_pitch = + fb->pitches[0] / fb->format->cpp[0]; + + surface->visible = true; + surface->scaling_quality.h_taps_c = 0; + surface->scaling_quality.v_taps_c = 0; + + /* TODO: unhardcode */ + surface->color_space = COLOR_SPACE_SRGB; + /* is this needed? is surface zeroed at allocation? */ + surface->scaling_quality.h_taps = 0; + surface->scaling_quality.v_taps = 0; + surface->stereo_format = PLANE_STEREO_FORMAT_NONE; + +} + +#define NUM_OF_RAW_GAMMA_RAMP_RGB_256 256 + +static void fill_gamma_from_crtc( + const struct drm_crtc *crtc, + struct dc_surface *dc_surface) +{ + int i; + struct dc_gamma *gamma; + struct drm_crtc_state *state = crtc->state; + struct drm_color_lut *lut = (struct drm_color_lut *) state->gamma_lut->data; + + gamma = dc_create_gamma(); + + if (gamma == NULL) + return; + + for (i = 0; i < NUM_OF_RAW_GAMMA_RAMP_RGB_256; i++) { + gamma->gamma_ramp_rgb256x3x16.red[i] = lut[i].red; + gamma->gamma_ramp_rgb256x3x16.green[i] = lut[i].green; + gamma->gamma_ramp_rgb256x3x16.blue[i] = lut[i].blue; + } + + gamma->type = GAMMA_RAMP_RBG256X3X16; + gamma->size = sizeof(gamma->gamma_ramp_rgb256x3x16); + + dc_surface->gamma_correction = gamma; +} + +static void fill_plane_attributes( + struct dc_surface *surface, + struct drm_plane_state *state, bool addrReq) +{ + const struct amdgpu_framebuffer *amdgpu_fb = + to_amdgpu_framebuffer(state->fb); + const struct drm_crtc *crtc = state->crtc; + + fill_rects_from_plane_state(state, surface); + fill_plane_attributes_from_fb( + surface, + amdgpu_fb, + addrReq); + + /* In case of gamma set, update gamma value */ + if (state->crtc->state->gamma_lut) { + fill_gamma_from_crtc(crtc, surface); + } +} + +/*****************************************************************************/ + +struct amdgpu_connector *aconnector_from_drm_crtc_id( + const struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct drm_connector *connector; + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + struct amdgpu_connector *aconnector; + + list_for_each_entry(connector, + &dev->mode_config.connector_list, head) { + + aconnector = to_amdgpu_connector(connector); + + if (aconnector->base.state->crtc != &acrtc->base) + continue; + + /* Found the connector */ + return aconnector; + } + + /* If we get here, not found. */ + return NULL; +} + +static void update_stream_scaling_settings( + const struct drm_display_mode *mode, + const struct dm_connector_state *dm_state, + const struct dc_stream *stream) +{ + struct amdgpu_device *adev = dm_state->base.crtc->dev->dev_private; + enum amdgpu_rmx_type rmx_type; + + struct rect src = { 0 }; /* viewport in target space*/ + struct rect dst = { 0 }; /* stream addressable area */ + + /* Full screen scaling by default */ + src.width = mode->hdisplay; + src.height = mode->vdisplay; + dst.width = stream->timing.h_addressable; + dst.height = stream->timing.v_addressable; + + rmx_type = dm_state->scaling; + if (rmx_type == RMX_ASPECT || rmx_type == RMX_OFF) { + if (src.width * dst.height < + src.height * dst.width) { + /* height needs less upscaling/more downscaling */ + dst.width = src.width * + dst.height / src.height; + } else { + /* width needs less upscaling/more downscaling */ + dst.height = src.height * + dst.width / src.width; + } + } else if (rmx_type == RMX_CENTER) { + dst = src; + } + + dst.x = (stream->timing.h_addressable - dst.width) / 2; + dst.y = (stream->timing.v_addressable - dst.height) / 2; + + if (dm_state->underscan_enable) { + dst.x += dm_state->underscan_hborder / 2; + dst.y += dm_state->underscan_vborder / 2; + dst.width -= dm_state->underscan_hborder; + dst.height -= dm_state->underscan_vborder; + } + + adev->dm.dc->stream_funcs.stream_update_scaling(adev->dm.dc, stream, &src, &dst); + + DRM_DEBUG_KMS("Destination Rectangle x:%d y:%d width:%d height:%d\n", + dst.x, dst.y, dst.width, dst.height); + +} + +static void dm_dc_surface_commit( + struct dc *dc, + struct drm_crtc *crtc) +{ + struct dc_surface *dc_surface; + const struct dc_surface *dc_surfaces[1]; + const struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + struct dc_target *dc_target = acrtc->target; + + if (!dc_target) { + dm_error( + "%s: Failed to obtain target on crtc (%d)!\n", + __func__, + acrtc->crtc_id); + goto fail; + } + + dc_surface = dc_create_surface(dc); + + if (!dc_surface) { + dm_error( + "%s: Failed to create a surface!\n", + __func__); + goto fail; + } + + /* Surface programming */ + fill_plane_attributes(dc_surface, crtc->primary->state, true); + + dc_surfaces[0] = dc_surface; + + if (false == dc_commit_surfaces_to_target( + dc, + dc_surfaces, + 1, + dc_target)) { + dm_error( + "%s: Failed to attach surface!\n", + __func__); + } + + dc_surface_release(dc_surface); +fail: + return; +} + +static enum dc_color_depth convert_color_depth_from_display_info( + const struct drm_connector *connector) +{ + uint32_t bpc = connector->display_info.bpc; + + /* Limited color depth to 8bit + * TODO: Still need to handle deep color*/ + if (bpc > 8) + bpc = 8; + + switch (bpc) { + case 0: + /* Temporary Work around, DRM don't parse color depth for + * EDID revision before 1.4 + * TODO: Fix edid parsing + */ + return COLOR_DEPTH_888; + case 6: + return COLOR_DEPTH_666; + case 8: + return COLOR_DEPTH_888; + case 10: + return COLOR_DEPTH_101010; + case 12: + return COLOR_DEPTH_121212; + case 14: + return COLOR_DEPTH_141414; + case 16: + return COLOR_DEPTH_161616; + default: + return COLOR_DEPTH_UNDEFINED; + } +} + +static enum dc_aspect_ratio get_aspect_ratio( + const struct drm_display_mode *mode_in) +{ + int32_t width = mode_in->crtc_hdisplay * 9; + int32_t height = mode_in->crtc_vdisplay * 16; + if ((width - height) < 10 && (width - height) > -10) + return ASPECT_RATIO_16_9; + else + return ASPECT_RATIO_4_3; +} + +static enum dc_color_space get_output_color_space( + const struct dc_crtc_timing *dc_crtc_timing) +{ + enum dc_color_space color_space = COLOR_SPACE_SRGB; + + switch (dc_crtc_timing->pixel_encoding) { + case PIXEL_ENCODING_YCBCR422: + case PIXEL_ENCODING_YCBCR444: + case PIXEL_ENCODING_YCBCR420: + { + /* + * 27030khz is the separation point between HDTV and SDTV + * according to HDMI spec, we use YCbCr709 and YCbCr601 + * respectively + */ + if (dc_crtc_timing->pix_clk_khz > 27030) { + if (dc_crtc_timing->flags.Y_ONLY) + color_space = + COLOR_SPACE_YCBCR709_LIMITED; + else + color_space = COLOR_SPACE_YCBCR709; + } else { + if (dc_crtc_timing->flags.Y_ONLY) + color_space = + COLOR_SPACE_YCBCR601_LIMITED; + else + color_space = COLOR_SPACE_YCBCR601; + } + + } + break; + case PIXEL_ENCODING_RGB: + color_space = COLOR_SPACE_SRGB; + break; + + default: + WARN_ON(1); + break; + } + + return color_space; +} + +/*****************************************************************************/ + +static void fill_stream_properties_from_drm_display_mode( + struct dc_stream *stream, + const struct drm_display_mode *mode_in, + const struct drm_connector *connector) +{ + struct dc_crtc_timing *timing_out = &stream->timing; + memset(timing_out, 0, sizeof(struct dc_crtc_timing)); + + timing_out->h_border_left = 0; + timing_out->h_border_right = 0; + timing_out->v_border_top = 0; + timing_out->v_border_bottom = 0; + /* TODO: un-hardcode */ + + if ((connector->display_info.color_formats & DRM_COLOR_FORMAT_YCRCB444) + && stream->sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A) + timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR444; + else + timing_out->pixel_encoding = PIXEL_ENCODING_RGB; + + timing_out->timing_3d_format = TIMING_3D_FORMAT_NONE; + timing_out->display_color_depth = convert_color_depth_from_display_info( + connector); + timing_out->scan_type = SCANNING_TYPE_NODATA; + timing_out->hdmi_vic = 0; + timing_out->vic = drm_match_cea_mode(mode_in); + + timing_out->h_addressable = mode_in->crtc_hdisplay; + timing_out->h_total = mode_in->crtc_htotal; + timing_out->h_sync_width = + mode_in->crtc_hsync_end - mode_in->crtc_hsync_start; + timing_out->h_front_porch = + mode_in->crtc_hsync_start - mode_in->crtc_hdisplay; + timing_out->v_total = mode_in->crtc_vtotal; + timing_out->v_addressable = mode_in->crtc_vdisplay; + timing_out->v_front_porch = + mode_in->crtc_vsync_start - mode_in->crtc_vdisplay; + timing_out->v_sync_width = + mode_in->crtc_vsync_end - mode_in->crtc_vsync_start; + timing_out->pix_clk_khz = mode_in->crtc_clock; + timing_out->aspect_ratio = get_aspect_ratio(mode_in); + if (mode_in->flags & DRM_MODE_FLAG_PHSYNC) + timing_out->flags.HSYNC_POSITIVE_POLARITY = 1; + if (mode_in->flags & DRM_MODE_FLAG_PVSYNC) + timing_out->flags.VSYNC_POSITIVE_POLARITY = 1; + + stream->output_color_space = get_output_color_space(timing_out); + +} + +static void fill_audio_info( + struct audio_info *audio_info, + const struct drm_connector *drm_connector, + const struct dc_sink *dc_sink) +{ + int i = 0; + int cea_revision = 0; + const struct dc_edid_caps *edid_caps = &dc_sink->edid_caps; + + audio_info->manufacture_id = edid_caps->manufacturer_id; + audio_info->product_id = edid_caps->product_id; + + cea_revision = drm_connector->display_info.cea_rev; + + while (i < AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS && + edid_caps->display_name[i]) { + audio_info->display_name[i] = edid_caps->display_name[i]; + i++; + } + + if(cea_revision >= 3) { + audio_info->mode_count = edid_caps->audio_mode_count; + + for (i = 0; i < audio_info->mode_count; ++i) { + audio_info->modes[i].format_code = + (enum audio_format_code) + (edid_caps->audio_modes[i].format_code); + audio_info->modes[i].channel_count = + edid_caps->audio_modes[i].channel_count; + audio_info->modes[i].sample_rates.all = + edid_caps->audio_modes[i].sample_rate; + audio_info->modes[i].sample_size = + edid_caps->audio_modes[i].sample_size; + } + } + + audio_info->flags.all = edid_caps->speaker_flags; + + /* TODO: We only check for the progressive mode, check for interlace mode too */ + if(drm_connector->latency_present[0]) { + audio_info->video_latency = drm_connector->video_latency[0]; + audio_info->audio_latency = drm_connector->audio_latency[0]; + } + + /* TODO: For DP, video and audio latency should be calculated from DPCD caps */ + +} + +static void copy_crtc_timing_for_drm_display_mode( + const struct drm_display_mode *src_mode, + struct drm_display_mode *dst_mode) +{ + dst_mode->crtc_hdisplay = src_mode->crtc_hdisplay; + dst_mode->crtc_vdisplay = src_mode->crtc_vdisplay; + dst_mode->crtc_clock = src_mode->crtc_clock; + dst_mode->crtc_hblank_start = src_mode->crtc_hblank_start; + dst_mode->crtc_hblank_end = src_mode->crtc_hblank_end; + dst_mode->crtc_hsync_start= src_mode->crtc_hsync_start; + dst_mode->crtc_hsync_end = src_mode->crtc_hsync_end; + dst_mode->crtc_htotal = src_mode->crtc_htotal; + dst_mode->crtc_hskew = src_mode->crtc_hskew; + dst_mode->crtc_vblank_start = src_mode->crtc_vblank_start;; + dst_mode->crtc_vblank_end = src_mode->crtc_vblank_end;; + dst_mode->crtc_vsync_start = src_mode->crtc_vsync_start;; + dst_mode->crtc_vsync_end = src_mode->crtc_vsync_end;; + dst_mode->crtc_vtotal = src_mode->crtc_vtotal;; +} + +static void decide_crtc_timing_for_drm_display_mode( + struct drm_display_mode *drm_mode, + const struct drm_display_mode *native_mode, + bool scale_enabled) +{ + if (scale_enabled) { + copy_crtc_timing_for_drm_display_mode(native_mode, drm_mode); + } else if (native_mode->clock == drm_mode->clock && + native_mode->htotal == drm_mode->htotal && + native_mode->vtotal == drm_mode->vtotal) { + copy_crtc_timing_for_drm_display_mode(native_mode, drm_mode); + } else { + /* no scaling nor amdgpu inserted, no need to patch */ + } +} + +static struct dc_target *create_target_for_sink( + const struct amdgpu_connector *aconnector, + const struct drm_display_mode *drm_mode, + const struct dm_connector_state *dm_state) +{ + struct drm_display_mode *preferred_mode = NULL; + const struct drm_connector *drm_connector; + struct dc_target *target = NULL; + struct dc_stream *stream; + struct drm_display_mode mode = *drm_mode; + bool native_mode_found = false; + + if (NULL == aconnector) { + DRM_ERROR("aconnector is NULL!\n"); + goto drm_connector_null; + } + + if (NULL == dm_state) { + DRM_ERROR("dm_state is NULL!\n"); + goto dm_state_null; + } + + drm_connector = &aconnector->base; + stream = dc_create_stream_for_sink(aconnector->dc_sink); + + if (NULL == stream) { + DRM_ERROR("Failed to create stream for sink!\n"); + goto stream_create_fail; + } + + list_for_each_entry(preferred_mode, &aconnector->base.modes, head) { + /* Search for preferred mode */ + if (preferred_mode->type & DRM_MODE_TYPE_PREFERRED) { + native_mode_found = true; + break; + } + } + if (!native_mode_found) + preferred_mode = list_first_entry_or_null( + &aconnector->base.modes, + struct drm_display_mode, + head); + + if (NULL == preferred_mode) { + /* This may not be an error, the use case is when we we have no + * usermode calls to reset and set mode upon hotplug. In this + * case, we call set mode ourselves to restore the previous mode + * and the modelist may not be filled in in time. + */ + DRM_INFO("No preferred mode found\n"); + } else { + decide_crtc_timing_for_drm_display_mode( + &mode, preferred_mode, + dm_state->scaling != RMX_OFF); + } + + fill_stream_properties_from_drm_display_mode(stream, + &mode, &aconnector->base); + update_stream_scaling_settings(&mode, dm_state, stream); + + fill_audio_info( + &stream->audio_info, + drm_connector, + aconnector->dc_sink); + + target = dc_create_target_for_streams(&stream, 1); + dc_stream_release(stream); + + if (NULL == target) { + DRM_ERROR("Failed to create target with streams!\n"); + goto target_create_fail; + } + +dm_state_null: +drm_connector_null: +target_create_fail: +stream_create_fail: + return target; +} + +void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc) +{ + drm_crtc_cleanup(crtc); + kfree(crtc); +} + +/* Implemented only the options currently availible for the driver */ +static const struct drm_crtc_funcs amdgpu_dm_crtc_funcs = { + .reset = drm_atomic_helper_crtc_reset, + .cursor_set = dm_crtc_cursor_set, + .cursor_move = dm_crtc_cursor_move, + .destroy = amdgpu_dm_crtc_destroy, + .gamma_set = drm_atomic_helper_legacy_gamma_set, + .set_config = drm_atomic_helper_set_config, + .page_flip = drm_atomic_helper_page_flip, + .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, +}; + +static enum drm_connector_status +amdgpu_dm_connector_detect(struct drm_connector *connector, bool force) +{ + bool connected; + struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + + /* Notes: + * 1. This interface is NOT called in context of HPD irq. + * 2. This interface *is called* in context of user-mode ioctl. Which + * makes it a bad place for *any* MST-related activit. */ + + if (aconnector->base.force == DRM_FORCE_UNSPECIFIED) + connected = (aconnector->dc_sink != NULL); + else + connected = (aconnector->base.force == DRM_FORCE_ON); + + return (connected ? connector_status_connected : + connector_status_disconnected); +} + +int amdgpu_dm_connector_atomic_set_property( + struct drm_connector *connector, + struct drm_connector_state *connector_state, + struct drm_property *property, + uint64_t val) +{ + struct drm_device *dev = connector->dev; + struct amdgpu_device *adev = dev->dev_private; + struct dm_connector_state *dm_old_state = + to_dm_connector_state(connector->state); + struct dm_connector_state *dm_new_state = + to_dm_connector_state(connector_state); + + struct drm_crtc_state *new_crtc_state; + struct drm_crtc *crtc; + int i; + int ret = -EINVAL; + + if (property == dev->mode_config.scaling_mode_property) { + enum amdgpu_rmx_type rmx_type; + + switch (val) { + case DRM_MODE_SCALE_CENTER: + rmx_type = RMX_CENTER; + break; + case DRM_MODE_SCALE_ASPECT: + rmx_type = RMX_ASPECT; + break; + case DRM_MODE_SCALE_FULLSCREEN: + rmx_type = RMX_FULL; + break; + case DRM_MODE_SCALE_NONE: + default: + rmx_type = RMX_OFF; + break; + } + + if (dm_old_state->scaling == rmx_type) + return 0; + + dm_new_state->scaling = rmx_type; + ret = 0; + } else if (property == adev->mode_info.underscan_hborder_property) { + dm_new_state->underscan_hborder = val; + ret = 0; + } else if (property == adev->mode_info.underscan_vborder_property) { + dm_new_state->underscan_vborder = val; + ret = 0; + } else if (property == adev->mode_info.underscan_property) { + dm_new_state->underscan_enable = val; + ret = 0; + } + + for_each_crtc_in_state( + connector_state->state, + crtc, + new_crtc_state, + i) { + + if (crtc == connector_state->crtc) { + struct drm_plane_state *plane_state; + + /* + * Bit of magic done here. We need to ensure + * that planes get update after mode is set. + * So, we need to add primary plane to state, + * and this way atomic_update would be called + * for it + */ + plane_state = + drm_atomic_get_plane_state( + connector_state->state, + crtc->primary); + + if (!plane_state) + return -EINVAL; + } + } + + return ret; +} + +void amdgpu_dm_connector_destroy(struct drm_connector *connector) +{ + struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + const struct dc_link *link = aconnector->dc_link; + struct amdgpu_device *adev = connector->dev->dev_private; + struct amdgpu_display_manager *dm = &adev->dm; +#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\ + defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) + + if (link->connector_signal & (SIGNAL_TYPE_EDP | SIGNAL_TYPE_LVDS)) { + amdgpu_dm_register_backlight_device(dm); + + if (dm->backlight_dev) { + backlight_device_unregister(dm->backlight_dev); + dm->backlight_dev = NULL; + } + + } +#endif + drm_connector_unregister(connector); + drm_connector_cleanup(connector); + kfree(connector); +} + +void amdgpu_dm_connector_funcs_reset(struct drm_connector *connector) +{ + struct dm_connector_state *state = + to_dm_connector_state(connector->state); + + kfree(state); + + state = kzalloc(sizeof(*state), GFP_KERNEL); + + if (state) { + state->scaling = RMX_OFF; + state->underscan_enable = false; + state->underscan_hborder = 0; + state->underscan_vborder = 0; + + connector->state = &state->base; + connector->state->connector = connector; + } +} + +struct drm_connector_state *amdgpu_dm_connector_atomic_duplicate_state( + struct drm_connector *connector) +{ + struct dm_connector_state *state = + to_dm_connector_state(connector->state); + + struct dm_connector_state *new_state = + kmemdup(state, sizeof(*state), GFP_KERNEL); + + if (new_state) { + __drm_atomic_helper_connector_duplicate_state(connector, + &new_state->base); + return &new_state->base; + } + + return NULL; +} + +static const struct drm_connector_funcs amdgpu_dm_connector_funcs = { + .reset = amdgpu_dm_connector_funcs_reset, + .detect = amdgpu_dm_connector_detect, + .fill_modes = drm_helper_probe_single_connector_modes, + .destroy = amdgpu_dm_connector_destroy, + .atomic_duplicate_state = amdgpu_dm_connector_atomic_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, + .atomic_set_property = amdgpu_dm_connector_atomic_set_property +}; + +static struct drm_encoder *best_encoder(struct drm_connector *connector) +{ + int enc_id = connector->encoder_ids[0]; + struct drm_mode_object *obj; + struct drm_encoder *encoder; + + DRM_DEBUG_KMS("Finding the best encoder\n"); + + /* pick the encoder ids */ + if (enc_id) { + obj = drm_mode_object_find(connector->dev, enc_id, DRM_MODE_OBJECT_ENCODER); + if (!obj) { + DRM_ERROR("Couldn't find a matching encoder for our connector\n"); + return NULL; + } + encoder = obj_to_encoder(obj); + return encoder; + } + DRM_ERROR("No encoder id\n"); + return NULL; +} + +static int get_modes(struct drm_connector *connector) +{ + return amdgpu_dm_connector_get_modes(connector); +} + +static void create_eml_sink(struct amdgpu_connector *aconnector) +{ + struct dc_sink_init_data init_params = { + .link = aconnector->dc_link, + .sink_signal = SIGNAL_TYPE_VIRTUAL + }; + struct edid *edid = (struct edid *) aconnector->base.edid_blob_ptr->data; + + if (!aconnector->base.edid_blob_ptr || + !aconnector->base.edid_blob_ptr->data) { + DRM_ERROR("No EDID firmware found on connector: %s ,forcing to OFF!\n", + aconnector->base.name); + + aconnector->base.force = DRM_FORCE_OFF; + aconnector->base.override_edid = false; + return; + } + + aconnector->edid = edid; + + aconnector->dc_em_sink = dc_link_add_remote_sink( + aconnector->dc_link, + (uint8_t *)edid, + (edid->extensions + 1) * EDID_LENGTH, + &init_params); + + if (aconnector->base.force + == DRM_FORCE_ON) + aconnector->dc_sink = aconnector->dc_link->local_sink ? + aconnector->dc_link->local_sink : + aconnector->dc_em_sink; +} + +static void handle_edid_mgmt(struct amdgpu_connector *aconnector) +{ + struct dc_link *link = (struct dc_link *)aconnector->dc_link; + + /* In case of headless boot with force on for DP managed connector + * Those settings have to be != 0 to get initial modeset + */ + if (link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT) { + link->verified_link_cap.lane_count = LANE_COUNT_FOUR; + link->verified_link_cap.link_rate = LINK_RATE_HIGH2; + } + + + aconnector->base.override_edid = true; + create_eml_sink(aconnector); +} + +int amdgpu_dm_connector_mode_valid( + struct drm_connector *connector, + struct drm_display_mode *mode) +{ + int result = MODE_ERROR; + const struct dc_sink *dc_sink; + struct amdgpu_device *adev = connector->dev->dev_private; + struct dc_validation_set val_set = { 0 }; + /* TODO: Unhardcode stream count */ + struct dc_stream *streams[1]; + struct dc_target *target; + struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + + if ((mode->flags & DRM_MODE_FLAG_INTERLACE) || + (mode->flags & DRM_MODE_FLAG_DBLSCAN)) + return result; + + /* Only run this the first time mode_valid is called to initilialize + * EDID mgmt + */ + if (aconnector->base.force != DRM_FORCE_UNSPECIFIED && + !aconnector->dc_em_sink) + handle_edid_mgmt(aconnector); + + dc_sink = to_amdgpu_connector(connector)->dc_sink; + + if (NULL == dc_sink) { + DRM_ERROR("dc_sink is NULL!\n"); + goto stream_create_fail; + } + + streams[0] = dc_create_stream_for_sink(dc_sink); + + if (NULL == streams[0]) { + DRM_ERROR("Failed to create stream for sink!\n"); + goto stream_create_fail; + } + + drm_mode_set_crtcinfo(mode, 0); + fill_stream_properties_from_drm_display_mode(streams[0], mode, connector); + + target = dc_create_target_for_streams(streams, 1); + val_set.target = target; + + if (NULL == val_set.target) { + DRM_ERROR("Failed to create target with stream!\n"); + goto target_create_fail; + } + + val_set.surface_count = 0; + streams[0]->src.width = mode->hdisplay; + streams[0]->src.height = mode->vdisplay; + streams[0]->dst = streams[0]->src; + + if (dc_validate_resources(adev->dm.dc, &val_set, 1)) + result = MODE_OK; + + dc_target_release(target); +target_create_fail: + dc_stream_release(streams[0]); +stream_create_fail: + /* TODO: error handling*/ + return result; +} + +static const struct drm_connector_helper_funcs +amdgpu_dm_connector_helper_funcs = { + /* + * If hotplug a second bigger display in FB Con mode, bigger resolution + * modes will be filtered by drm_mode_validate_size(), and those modes + * is missing after user start lightdm. So we need to renew modes list. + * in get_modes call back, not just return the modes count + */ + .get_modes = get_modes, + .mode_valid = amdgpu_dm_connector_mode_valid, + .best_encoder = best_encoder +}; + +static void dm_crtc_helper_disable(struct drm_crtc *crtc) +{ +} + +static int dm_crtc_helper_atomic_check( + struct drm_crtc *crtc, + struct drm_crtc_state *state) +{ + return 0; +} + +static bool dm_crtc_helper_mode_fixup( + struct drm_crtc *crtc, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + return true; +} + +static const struct drm_crtc_helper_funcs amdgpu_dm_crtc_helper_funcs = { + .disable = dm_crtc_helper_disable, + .atomic_check = dm_crtc_helper_atomic_check, + .mode_fixup = dm_crtc_helper_mode_fixup +}; + +static void dm_encoder_helper_disable(struct drm_encoder *encoder) +{ + +} + +static int dm_encoder_helper_atomic_check( + struct drm_encoder *encoder, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) +{ + return 0; +} + +const struct drm_encoder_helper_funcs amdgpu_dm_encoder_helper_funcs = { + .disable = dm_encoder_helper_disable, + .atomic_check = dm_encoder_helper_atomic_check +}; + +static const struct drm_plane_funcs dm_plane_funcs = { + .reset = drm_atomic_helper_plane_reset, + .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_plane_destroy_state +}; + +static void clear_unrelated_fields(struct drm_plane_state *state) +{ + state->crtc = NULL; + state->fb = NULL; + state->state = NULL; + state->fence = NULL; +} + +static bool page_flip_needed( + const struct drm_plane_state *new_state, + const struct drm_plane_state *old_state, + struct drm_pending_vblank_event *event, + bool commit_surface_required) +{ + struct drm_plane_state old_state_tmp; + struct drm_plane_state new_state_tmp; + + struct amdgpu_framebuffer *amdgpu_fb_old; + struct amdgpu_framebuffer *amdgpu_fb_new; + struct amdgpu_crtc *acrtc_new; + + uint64_t old_tiling_flags; + uint64_t new_tiling_flags; + + bool page_flip_required; + + if (!old_state) + return false; + + if (!old_state->fb) + return false; + + if (!new_state) + return false; + + if (!new_state->fb) + return false; + + old_state_tmp = *old_state; + new_state_tmp = *new_state; + + if (!event) + return false; + + amdgpu_fb_old = to_amdgpu_framebuffer(old_state->fb); + amdgpu_fb_new = to_amdgpu_framebuffer(new_state->fb); + + if (!get_fb_info(amdgpu_fb_old, &old_tiling_flags, NULL)) + return false; + + if (!get_fb_info(amdgpu_fb_new, &new_tiling_flags, NULL)) + return false; + + if (commit_surface_required == true && + old_tiling_flags != new_tiling_flags) + return false; + + clear_unrelated_fields(&old_state_tmp); + clear_unrelated_fields(&new_state_tmp); + + page_flip_required = memcmp(&old_state_tmp, + &new_state_tmp, + sizeof(old_state_tmp)) == 0 ? true:false; + if (new_state->crtc && page_flip_required == false) { + acrtc_new = to_amdgpu_crtc(new_state->crtc); + if (acrtc_new->flip_flags & DRM_MODE_PAGE_FLIP_ASYNC) + page_flip_required = true; + } + return page_flip_required; +} + +static int dm_plane_helper_prepare_fb( + struct drm_plane *plane, + struct drm_plane_state *new_state) +{ + struct amdgpu_framebuffer *afb; + struct drm_gem_object *obj; + struct amdgpu_bo *rbo; + int r; + + if (!new_state->fb) { + DRM_DEBUG_KMS("No FB bound\n"); + return 0; + } + + afb = to_amdgpu_framebuffer(new_state->fb); + + obj = afb->obj; + rbo = gem_to_amdgpu_bo(obj); + r = amdgpu_bo_reserve(rbo, false); + if (unlikely(r != 0)) + return r; + + r = amdgpu_bo_pin(rbo, AMDGPU_GEM_DOMAIN_VRAM, NULL); + + amdgpu_bo_unreserve(rbo); + + if (unlikely(r != 0)) { + DRM_ERROR("Failed to pin framebuffer\n"); + return r; + } + + return 0; +} + +static void dm_plane_helper_cleanup_fb( + struct drm_plane *plane, + struct drm_plane_state *old_state) +{ + struct amdgpu_bo *rbo; + struct amdgpu_framebuffer *afb; + int r; + + if (!old_state->fb) + return; + + afb = to_amdgpu_framebuffer(old_state->fb); + rbo = gem_to_amdgpu_bo(afb->obj); + r = amdgpu_bo_reserve(rbo, false); + if (unlikely(r)) { + DRM_ERROR("failed to reserve rbo before unpin\n"); + return; + } else { + amdgpu_bo_unpin(rbo); + amdgpu_bo_unreserve(rbo); + } +} + +int dm_create_validation_set_for_target(struct drm_connector *connector, + struct drm_display_mode *mode, struct dc_validation_set *val_set) +{ + int result = MODE_ERROR; + const struct dc_sink *dc_sink = + to_amdgpu_connector(connector)->dc_sink; + /* TODO: Unhardcode stream count */ + struct dc_stream *streams[1]; + struct dc_target *target; + + if ((mode->flags & DRM_MODE_FLAG_INTERLACE) || + (mode->flags & DRM_MODE_FLAG_DBLSCAN)) + return result; + + if (NULL == dc_sink) { + DRM_ERROR("dc_sink is NULL!\n"); + return result; + } + + streams[0] = dc_create_stream_for_sink(dc_sink); + + if (NULL == streams[0]) { + DRM_ERROR("Failed to create stream for sink!\n"); + return result; + } + + drm_mode_set_crtcinfo(mode, 0); + + fill_stream_properties_from_drm_display_mode(streams[0], mode, connector); + + target = dc_create_target_for_streams(streams, 1); + val_set->target = target; + + if (NULL == val_set->target) { + DRM_ERROR("Failed to create target with stream!\n"); + goto fail; + } + + streams[0]->src.width = mode->hdisplay; + streams[0]->src.height = mode->vdisplay; + streams[0]->dst = streams[0]->src; + + return MODE_OK; + +fail: + dc_stream_release(streams[0]); + return result; + +} + +static const struct drm_plane_helper_funcs dm_plane_helper_funcs = { + .prepare_fb = dm_plane_helper_prepare_fb, + .cleanup_fb = dm_plane_helper_cleanup_fb, +}; + +/* + * TODO: these are currently initialized to rgb formats only. + * For future use cases we should either initialize them dynamically based on + * plane capabilities, or initialize this array to all formats, so internal drm + * check will succeed, and let DC to implement proper check + */ +static uint32_t rgb_formats[] = { + DRM_FORMAT_XRGB4444, + DRM_FORMAT_ARGB4444, + DRM_FORMAT_RGBA4444, + DRM_FORMAT_ARGB1555, + DRM_FORMAT_RGB565, + DRM_FORMAT_RGB888, + DRM_FORMAT_XRGB8888, + DRM_FORMAT_ARGB8888, + DRM_FORMAT_RGBA8888, + DRM_FORMAT_XRGB2101010, + DRM_FORMAT_XBGR2101010, + DRM_FORMAT_ARGB2101010, + DRM_FORMAT_ABGR2101010, +}; + +int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, + struct amdgpu_crtc *acrtc, + uint32_t crtc_index) +{ + int res = -ENOMEM; + + struct drm_plane *primary_plane = + kzalloc(sizeof(*primary_plane), GFP_KERNEL); + + if (!primary_plane) + goto fail_plane; + + primary_plane->format_default = true; + + res = drm_universal_plane_init( + dm->adev->ddev, + primary_plane, + 0, + &dm_plane_funcs, + rgb_formats, + ARRAY_SIZE(rgb_formats), + NULL, + DRM_PLANE_TYPE_PRIMARY, NULL); + + primary_plane->crtc = &acrtc->base; + + drm_plane_helper_add(primary_plane, &dm_plane_helper_funcs); + + res = drm_crtc_init_with_planes( + dm->ddev, + &acrtc->base, + primary_plane, + NULL, + &amdgpu_dm_crtc_funcs, NULL); + + if (res) + goto fail; + + drm_crtc_helper_add(&acrtc->base, &amdgpu_dm_crtc_helper_funcs); + + acrtc->max_cursor_width = 128; + acrtc->max_cursor_height = 128; + + acrtc->crtc_id = crtc_index; + acrtc->base.enabled = false; + + dm->adev->mode_info.crtcs[crtc_index] = acrtc; + drm_mode_crtc_set_gamma_size(&acrtc->base, 256); + + return 0; +fail: + kfree(primary_plane); +fail_plane: + acrtc->crtc_id = -1; + return res; +} + +static int to_drm_connector_type(enum signal_type st) +{ + switch (st) { + case SIGNAL_TYPE_HDMI_TYPE_A: + return DRM_MODE_CONNECTOR_HDMIA; + case SIGNAL_TYPE_EDP: + return DRM_MODE_CONNECTOR_eDP; + case SIGNAL_TYPE_RGB: + return DRM_MODE_CONNECTOR_VGA; + case SIGNAL_TYPE_DISPLAY_PORT: + case SIGNAL_TYPE_DISPLAY_PORT_MST: + return DRM_MODE_CONNECTOR_DisplayPort; + case SIGNAL_TYPE_DVI_DUAL_LINK: + case SIGNAL_TYPE_DVI_SINGLE_LINK: + return DRM_MODE_CONNECTOR_DVID; + case SIGNAL_TYPE_VIRTUAL: + return DRM_MODE_CONNECTOR_VIRTUAL; + + default: + return DRM_MODE_CONNECTOR_Unknown; + } +} + +static void amdgpu_dm_get_native_mode(struct drm_connector *connector) +{ + const struct drm_connector_helper_funcs *helper = + connector->helper_private; + struct drm_encoder *encoder; + struct amdgpu_encoder *amdgpu_encoder; + + encoder = helper->best_encoder(connector); + + if (encoder == NULL) + return; + + amdgpu_encoder = to_amdgpu_encoder(encoder); + + amdgpu_encoder->native_mode.clock = 0; + + if (!list_empty(&connector->probed_modes)) { + struct drm_display_mode *preferred_mode = NULL; + list_for_each_entry(preferred_mode, + &connector->probed_modes, + head) { + if (preferred_mode->type & DRM_MODE_TYPE_PREFERRED) { + amdgpu_encoder->native_mode = *preferred_mode; + } + break; + } + + } +} + +static struct drm_display_mode *amdgpu_dm_create_common_mode( + struct drm_encoder *encoder, char *name, + int hdisplay, int vdisplay) +{ + struct drm_device *dev = encoder->dev; + struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); + struct drm_display_mode *mode = NULL; + struct drm_display_mode *native_mode = &amdgpu_encoder->native_mode; + + mode = drm_mode_duplicate(dev, native_mode); + + if(mode == NULL) + return NULL; + + mode->hdisplay = hdisplay; + mode->vdisplay = vdisplay; + mode->type &= ~DRM_MODE_TYPE_PREFERRED; + strncpy(mode->name, name, DRM_DISPLAY_MODE_LEN); + + return mode; + +} + +static void amdgpu_dm_connector_add_common_modes(struct drm_encoder *encoder, + struct drm_connector *connector) +{ + struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); + struct drm_display_mode *mode = NULL; + struct drm_display_mode *native_mode = &amdgpu_encoder->native_mode; + struct amdgpu_connector *amdgpu_connector = + to_amdgpu_connector(connector); + int i; + int n; + struct mode_size { + char name[DRM_DISPLAY_MODE_LEN]; + int w; + int h; + }common_modes[] = { + { "640x480", 640, 480}, + { "800x600", 800, 600}, + { "1024x768", 1024, 768}, + { "1280x720", 1280, 720}, + { "1280x800", 1280, 800}, + {"1280x1024", 1280, 1024}, + { "1440x900", 1440, 900}, + {"1680x1050", 1680, 1050}, + {"1600x1200", 1600, 1200}, + {"1920x1080", 1920, 1080}, + {"1920x1200", 1920, 1200} + }; + + n = sizeof(common_modes) / sizeof(common_modes[0]); + + for (i = 0; i < n; i++) { + struct drm_display_mode *curmode = NULL; + bool mode_existed = false; + + if (common_modes[i].w > native_mode->hdisplay || + common_modes[i].h > native_mode->vdisplay || + (common_modes[i].w == native_mode->hdisplay && + common_modes[i].h == native_mode->vdisplay)) + continue; + + list_for_each_entry(curmode, &connector->probed_modes, head) { + if (common_modes[i].w == curmode->hdisplay && + common_modes[i].h == curmode->vdisplay) { + mode_existed = true; + break; + } + } + + if (mode_existed) + continue; + + mode = amdgpu_dm_create_common_mode(encoder, + common_modes[i].name, common_modes[i].w, + common_modes[i].h); + drm_mode_probed_add(connector, mode); + amdgpu_connector->num_modes++; + } +} + +static void amdgpu_dm_connector_ddc_get_modes( + struct drm_connector *connector, + struct edid *edid) +{ + struct amdgpu_connector *amdgpu_connector = + to_amdgpu_connector(connector); + + if (edid) { + /* empty probed_modes */ + INIT_LIST_HEAD(&connector->probed_modes); + amdgpu_connector->num_modes = + drm_add_edid_modes(connector, edid); + + drm_edid_to_eld(connector, edid); + + amdgpu_dm_get_native_mode(connector); + } else + amdgpu_connector->num_modes = 0; +} + +int amdgpu_dm_connector_get_modes(struct drm_connector *connector) +{ + const struct drm_connector_helper_funcs *helper = + connector->helper_private; + struct amdgpu_connector *amdgpu_connector = + to_amdgpu_connector(connector); + struct drm_encoder *encoder; + struct edid *edid = amdgpu_connector->edid; + + encoder = helper->best_encoder(connector); + + amdgpu_dm_connector_ddc_get_modes(connector, edid); + amdgpu_dm_connector_add_common_modes(encoder, connector); + return amdgpu_connector->num_modes; +} + +void amdgpu_dm_connector_init_helper( + struct amdgpu_display_manager *dm, + struct amdgpu_connector *aconnector, + int connector_type, + const struct dc_link *link, + int link_index) +{ + struct amdgpu_device *adev = dm->ddev->dev_private; + + aconnector->connector_id = link_index; + aconnector->dc_link = link; + aconnector->base.interlace_allowed = true; + aconnector->base.doublescan_allowed = true; + aconnector->base.dpms = DRM_MODE_DPMS_OFF; + aconnector->hpd.hpd = AMDGPU_HPD_NONE; /* not used */ + + mutex_init(&aconnector->hpd_lock); + + /*configure suport HPD hot plug connector_>polled default value is 0 + * which means HPD hot plug not supported*/ + switch (connector_type) { + case DRM_MODE_CONNECTOR_HDMIA: + aconnector->base.polled = DRM_CONNECTOR_POLL_HPD; + break; + case DRM_MODE_CONNECTOR_DisplayPort: + aconnector->base.polled = DRM_CONNECTOR_POLL_HPD; + break; + case DRM_MODE_CONNECTOR_DVID: + aconnector->base.polled = DRM_CONNECTOR_POLL_HPD; + break; + default: + break; + } + + drm_object_attach_property(&aconnector->base.base, + dm->ddev->mode_config.scaling_mode_property, + DRM_MODE_SCALE_NONE); + + drm_object_attach_property(&aconnector->base.base, + adev->mode_info.underscan_property, + UNDERSCAN_OFF); + drm_object_attach_property(&aconnector->base.base, + adev->mode_info.underscan_hborder_property, + 0); + drm_object_attach_property(&aconnector->base.base, + adev->mode_info.underscan_vborder_property, + 0); + +} + +int amdgpu_dm_i2c_xfer(struct i2c_adapter *i2c_adap, + struct i2c_msg *msgs, int num) +{ + struct amdgpu_i2c_adapter *i2c = i2c_get_adapdata(i2c_adap); + struct i2c_command cmd; + int i; + int result = -EIO; + + cmd.payloads = kzalloc(num * sizeof(struct i2c_payload), GFP_KERNEL); + + if (!cmd.payloads) + return result; + + cmd.number_of_payloads = num; + cmd.engine = I2C_COMMAND_ENGINE_DEFAULT; + cmd.speed = 100; + + for (i = 0; i < num; i++) { + cmd.payloads[i].write = (msgs[i].flags & I2C_M_RD); + cmd.payloads[i].address = msgs[i].addr; + cmd.payloads[i].length = msgs[i].len; + cmd.payloads[i].data = msgs[i].buf; + } + + if (dc_submit_i2c(i2c->dm->dc, i2c->link_index, &cmd)) + result = num; + + kfree(cmd.payloads); + + return result; +} + +u32 amdgpu_dm_i2c_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + +static const struct i2c_algorithm amdgpu_dm_i2c_algo = { + .master_xfer = amdgpu_dm_i2c_xfer, + .functionality = amdgpu_dm_i2c_func, +}; + +struct amdgpu_i2c_adapter *create_i2c(unsigned int link_index, struct amdgpu_display_manager *dm, int *res) +{ + struct amdgpu_i2c_adapter *i2c; + + i2c = kzalloc(sizeof (struct amdgpu_i2c_adapter), GFP_KERNEL); + i2c->dm = dm; + i2c->base.owner = THIS_MODULE; + i2c->base.class = I2C_CLASS_DDC; + i2c->base.dev.parent = &dm->adev->pdev->dev; + i2c->base.algo = &amdgpu_dm_i2c_algo; + snprintf(i2c->base.name, sizeof (i2c->base.name), "AMDGPU DM i2c hw bus %d", link_index); + i2c->link_index = link_index; + i2c_set_adapdata(&i2c->base, i2c); + + return i2c; +} + +/* Note: this function assumes that dc_link_detect() was called for the + * dc_link which will be represented by this aconnector. */ +int amdgpu_dm_connector_init( + struct amdgpu_display_manager *dm, + struct amdgpu_connector *aconnector, + uint32_t link_index, + struct amdgpu_encoder *aencoder) +{ + int res = 0; + int connector_type; + struct dc *dc = dm->dc; + const struct dc_link *link = dc_get_link_at_index(dc, link_index); + struct amdgpu_i2c_adapter *i2c; + + DRM_DEBUG_KMS("%s()\n", __func__); + + i2c = create_i2c(link->link_index, dm, &res); + aconnector->i2c = i2c; + res = i2c_add_adapter(&i2c->base); + + if (res) { + DRM_ERROR("Failed to register hw i2c %d\n", link->link_index); + goto out_free; + } + + connector_type = to_drm_connector_type(link->connector_signal); + + res = drm_connector_init( + dm->ddev, + &aconnector->base, + &amdgpu_dm_connector_funcs, + connector_type); + + if (res) { + DRM_ERROR("connector_init failed\n"); + aconnector->connector_id = -1; + goto out_free; + } + + drm_connector_helper_add( + &aconnector->base, + &amdgpu_dm_connector_helper_funcs); + + amdgpu_dm_connector_init_helper( + dm, + aconnector, + connector_type, + link, + link_index); + + drm_mode_connector_attach_encoder( + &aconnector->base, &aencoder->base); + + drm_connector_register(&aconnector->base); + + if (connector_type == DRM_MODE_CONNECTOR_DisplayPort + || connector_type == DRM_MODE_CONNECTOR_eDP) + amdgpu_dm_initialize_mst_connector(dm, aconnector); + +#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\ + defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) + + /* NOTE: this currently will create backlight device even if a panel + * is not connected to the eDP/LVDS connector. + * + * This is less than ideal but we don't have sink information at this + * stage since detection happens after. We can't do detection earlier + * since MST detection needs connectors to be created first. + */ + if (link->connector_signal & (SIGNAL_TYPE_EDP | SIGNAL_TYPE_LVDS)) { + /* Event if registration failed, we should continue with + * DM initialization because not having a backlight control + * is better then a black screen. */ + amdgpu_dm_register_backlight_device(dm); + + if (dm->backlight_dev) + dm->backlight_link = link; + } +#endif + +out_free: + if (res) { + kfree(i2c); + aconnector->i2c = NULL; + } + return res; +} + +int amdgpu_dm_get_encoder_crtc_mask(struct amdgpu_device *adev) +{ + switch (adev->mode_info.num_crtc) { + case 1: + return 0x1; + case 2: + return 0x3; + case 3: + return 0x7; + case 4: + return 0xf; + case 5: + return 0x1f; + case 6: + default: + return 0x3f; + } +} + +int amdgpu_dm_encoder_init( + struct drm_device *dev, + struct amdgpu_encoder *aencoder, + uint32_t link_index) +{ + struct amdgpu_device *adev = dev->dev_private; + + int res = drm_encoder_init(dev, + &aencoder->base, + &amdgpu_dm_encoder_funcs, + DRM_MODE_ENCODER_TMDS, + NULL); + + aencoder->base.possible_crtcs = amdgpu_dm_get_encoder_crtc_mask(adev); + + if (!res) + aencoder->encoder_id = link_index; + else + aencoder->encoder_id = -1; + + drm_encoder_helper_add(&aencoder->base, &amdgpu_dm_encoder_helper_funcs); + + return res; +} + +enum dm_commit_action { + DM_COMMIT_ACTION_NOTHING, + DM_COMMIT_ACTION_RESET, + DM_COMMIT_ACTION_DPMS_ON, + DM_COMMIT_ACTION_DPMS_OFF, + DM_COMMIT_ACTION_SET +}; + +static enum dm_commit_action get_dm_commit_action(struct drm_crtc_state *state) +{ + /* mode changed means either actually mode changed or enabled changed */ + /* active changed means dpms changed */ + + DRM_DEBUG_KMS("crtc_state_flags: enable:%d, active:%d, planes_changed:%d, mode_changed:%d,active_changed:%d,connectors_changed:%d\n", + state->enable, + state->active, + state->planes_changed, + state->mode_changed, + state->active_changed, + state->connectors_changed); + + if (state->mode_changed) { + /* if it is got disabled - call reset mode */ + if (!state->enable) + return DM_COMMIT_ACTION_RESET; + + if (state->active) + return DM_COMMIT_ACTION_SET; + else + return DM_COMMIT_ACTION_RESET; + } else { + /* ! mode_changed */ + + /* if it is remain disable - skip it */ + if (!state->enable) + return DM_COMMIT_ACTION_NOTHING; + + if (state->active && state->connectors_changed) + return DM_COMMIT_ACTION_SET; + + if (state->active_changed) { + if (state->active) { + return DM_COMMIT_ACTION_DPMS_ON; + } else { + return DM_COMMIT_ACTION_DPMS_OFF; + } + } else { + /* ! active_changed */ + return DM_COMMIT_ACTION_NOTHING; + } + } +} + + +typedef bool (*predicate)(struct amdgpu_crtc *acrtc); + +static void wait_while_pflip_status(struct amdgpu_device *adev, + struct amdgpu_crtc *acrtc, predicate f) { + int count = 0; + while (f(acrtc)) { + /* Spin Wait*/ + msleep(1); + count++; + if (count == 1000) { + DRM_ERROR("%s - crtc:%d[%p], pflip_stat:%d, probable hang!\n", + __func__, acrtc->crtc_id, + acrtc, + acrtc->pflip_status); + + /* we do not expect to hit this case except on Polaris with PHY PLL + * 1. DP to HDMI passive dongle connected + * 2. unplug (headless) + * 3. plug in DP + * 3a. on plug in, DP will try verify link by training, and training + * would disable PHY PLL which HDMI rely on to drive TG + * 3b. this will cause flip interrupt cannot be generated, and we + * exit when timeout expired. however we do not have code to clean + * up flip, flip clean up will happen when the address is written + * with the restore mode change + */ + WARN_ON(1); + break; + } + } + + DRM_DEBUG_DRIVER("%s - Finished waiting for:%d msec, crtc:%d[%p], pflip_stat:%d \n", + __func__, + count, + acrtc->crtc_id, + acrtc, + acrtc->pflip_status); +} + +static bool pflip_in_progress_predicate(struct amdgpu_crtc *acrtc) +{ + return acrtc->pflip_status != AMDGPU_FLIP_NONE; +} + +static void manage_dm_interrupts( + struct amdgpu_device *adev, + struct amdgpu_crtc *acrtc, + bool enable) +{ + /* + * this is not correct translation but will work as soon as VBLANK + * constant is the same as PFLIP + */ + int irq_type = + amdgpu_crtc_idx_to_irq_type( + adev, + acrtc->crtc_id); + + if (enable) { + drm_crtc_vblank_on(&acrtc->base); + amdgpu_irq_get( + adev, + &adev->pageflip_irq, + irq_type); + } else { + wait_while_pflip_status(adev, acrtc, + pflip_in_progress_predicate); + + amdgpu_irq_put( + adev, + &adev->pageflip_irq, + irq_type); + drm_crtc_vblank_off(&acrtc->base); + } +} + + +static bool pflip_pending_predicate(struct amdgpu_crtc *acrtc) +{ + return acrtc->pflip_status == AMDGPU_FLIP_PENDING; +} + +static bool is_scaling_state_different( + const struct dm_connector_state *dm_state, + const struct dm_connector_state *old_dm_state) +{ + if (dm_state->scaling != old_dm_state->scaling) + return true; + if (!dm_state->underscan_enable && old_dm_state->underscan_enable) { + if (old_dm_state->underscan_hborder != 0 && old_dm_state->underscan_vborder != 0) + return true; + } else if (dm_state->underscan_enable && !old_dm_state->underscan_enable) { + if (dm_state->underscan_hborder != 0 && dm_state->underscan_vborder != 0) + return true; + } else if (dm_state->underscan_hborder != old_dm_state->underscan_hborder + || dm_state->underscan_vborder != old_dm_state->underscan_vborder) + return true; + return false; +} + +static void remove_target(struct amdgpu_device *adev, struct amdgpu_crtc *acrtc) +{ + int i; + + /* + * we evade vblanks and pflips on crtc that + * should be changed + */ + manage_dm_interrupts(adev, acrtc, false); + /* this is the update mode case */ + if (adev->dm.freesync_module) + for (i = 0; i < acrtc->target->stream_count; i++) + mod_freesync_remove_stream( + adev->dm.freesync_module, + acrtc->target->streams[i]); + dc_target_release(acrtc->target); + acrtc->target = NULL; + acrtc->otg_inst = -1; + acrtc->enabled = false; +} + +int amdgpu_dm_atomic_commit( + struct drm_device *dev, + struct drm_atomic_state *state, + bool async) +{ + struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_display_manager *dm = &adev->dm; + struct drm_plane *plane; + struct drm_plane_state *new_plane_state; + struct drm_plane_state *old_plane_state; + uint32_t i, j; + int32_t ret = 0; + uint32_t commit_targets_count = 0; + uint32_t new_crtcs_count = 0; + uint32_t flip_crtcs_count = 0; + struct drm_crtc *crtc; + struct drm_crtc_state *old_crtc_state; + + struct dc_target *commit_targets[MAX_TARGETS]; + struct amdgpu_crtc *new_crtcs[MAX_TARGETS]; + struct dc_target *new_target; + struct drm_crtc *flip_crtcs[MAX_TARGETS]; + struct amdgpu_flip_work *work[MAX_TARGETS] = {0}; + struct amdgpu_bo *new_abo[MAX_TARGETS] = {0}; + + /* In this step all new fb would be pinned */ + + /* + * TODO: Revisit when we support true asynchronous commit. + * Right now we receive async commit only from pageflip, in which case + * we should not pin/unpin the fb here, it should be done in + * amdgpu_crtc_flip and from the vblank irq handler. + */ + if (!async) { + ret = drm_atomic_helper_prepare_planes(dev, state); + if (ret) + return ret; + } + + /* Page flip if needed */ + for_each_plane_in_state(state, plane, new_plane_state, i) { + struct drm_plane_state *old_plane_state = plane->state; + struct drm_crtc *crtc = new_plane_state->crtc; + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + struct drm_framebuffer *fb = new_plane_state->fb; + struct drm_crtc_state *crtc_state; + + if (!fb || !crtc) + continue; + + crtc_state = drm_atomic_get_crtc_state(state, crtc); + + if (!crtc_state->planes_changed || !crtc_state->active) + continue; + + if (page_flip_needed( + new_plane_state, + old_plane_state, + crtc_state->event, + false)) { + ret = amdgpu_crtc_prepare_flip(crtc, + fb, + crtc_state->event, + acrtc->flip_flags, + drm_crtc_vblank_count(crtc), + &work[flip_crtcs_count], + &new_abo[flip_crtcs_count]); + + if (ret) { + /* According to atomic_commit hook API, EINVAL is not allowed */ + if (unlikely(ret == -EINVAL)) + ret = -ENOMEM; + + DRM_ERROR("Atomic commit: Flip for crtc id %d: [%p], " + "failed, errno = %d\n", + acrtc->crtc_id, + acrtc, + ret); + /* cleanup all flip configurations which + * succeeded in this commit + */ + for (i = 0; i < flip_crtcs_count; i++) + amdgpu_crtc_cleanup_flip_ctx( + work[i], + new_abo[i]); + + return ret; + } + + flip_crtcs[flip_crtcs_count] = crtc; + flip_crtcs_count++; + } + } + + /* + * This is the point of no return - everything below never fails except + * when the hw goes bonghits. Which means we can commit the new state on + * the software side now. + */ + + drm_atomic_helper_swap_state(state, true); + + /* + * From this point state become old state really. New state is + * initialized to appropriate objects and could be accessed from there + */ + + /* + * there is no fences usage yet in state. We can skip the following line + * wait_for_fences(dev, state); + */ + + drm_atomic_helper_update_legacy_modeset_state(dev, state); + + /* update changed items */ + for_each_crtc_in_state(state, crtc, old_crtc_state, i) { + struct amdgpu_crtc *acrtc; + struct amdgpu_connector *aconnector = NULL; + enum dm_commit_action action; + struct drm_crtc_state *new_state = crtc->state; + + acrtc = to_amdgpu_crtc(crtc); + + aconnector = + amdgpu_dm_find_first_crct_matching_connector( + state, + crtc, + false); + + /* handles headless hotplug case, updating new_state and + * aconnector as needed + */ + + action = get_dm_commit_action(new_state); + + switch (action) { + case DM_COMMIT_ACTION_DPMS_ON: + case DM_COMMIT_ACTION_SET: { + struct dm_connector_state *dm_state = NULL; + new_target = NULL; + + if (aconnector) + dm_state = to_dm_connector_state(aconnector->base.state); + + new_target = create_target_for_sink( + aconnector, + &crtc->state->mode, + dm_state); + + DRM_INFO("Atomic commit: SET crtc id %d: [%p]\n", acrtc->crtc_id, acrtc); + + if (!new_target) { + /* + * this could happen because of issues with + * userspace notifications delivery. + * In this case userspace tries to set mode on + * display which is disconnect in fact. + * dc_sink in NULL in this case on aconnector. + * We expect reset mode will come soon. + * + * This can also happen when unplug is done + * during resume sequence ended + * + * In this case, we want to pretend we still + * have a sink to keep the pipe running so that + * hw state is consistent with the sw state + */ + DRM_DEBUG_KMS("%s: Failed to create new target for crtc %d\n", + __func__, acrtc->base.base.id); + break; + } + + if (acrtc->target) + remove_target(adev, acrtc); + + /* + * this loop saves set mode crtcs + * we needed to enable vblanks once all + * resources acquired in dc after dc_commit_targets + */ + new_crtcs[new_crtcs_count] = acrtc; + new_crtcs_count++; + + acrtc->target = new_target; + acrtc->enabled = true; + acrtc->hw_mode = crtc->state->mode; + crtc->hwmode = crtc->state->mode; + + break; + } + + case DM_COMMIT_ACTION_NOTHING: { + struct dm_connector_state *dm_state = NULL; + + if (!aconnector) + break; + + dm_state = to_dm_connector_state(aconnector->base.state); + + /* Scaling update */ + update_stream_scaling_settings( + &crtc->state->mode, + dm_state, + acrtc->target->streams[0]); + + break; + } + case DM_COMMIT_ACTION_DPMS_OFF: + case DM_COMMIT_ACTION_RESET: + DRM_INFO("Atomic commit: RESET. crtc id %d:[%p]\n", acrtc->crtc_id, acrtc); + /* i.e. reset mode */ + if (acrtc->target) + remove_target(adev, acrtc); + break; + } /* switch() */ + } /* for_each_crtc_in_state() */ + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + + if (acrtc->target) { + commit_targets[commit_targets_count] = acrtc->target; + ++commit_targets_count; + } + } + + /* + * Add streams after required streams from new and replaced targets + * are removed from freesync module + */ + if (adev->dm.freesync_module) { + for (i = 0; i < new_crtcs_count; i++) { + struct amdgpu_connector *aconnector = NULL; + new_target = new_crtcs[i]->target; + aconnector = + amdgpu_dm_find_first_crct_matching_connector( + state, + &new_crtcs[i]->base, + false); + if (!aconnector) { + DRM_INFO( + "Atomic commit: Failed to find connector for acrtc id:%d " + "skipping freesync init\n", + new_crtcs[i]->crtc_id); + continue; + } + + for (j = 0; j < new_target->stream_count; j++) + mod_freesync_add_stream( + adev->dm.freesync_module, + new_target->streams[j], &aconnector->caps); + } + } + + /* DC is optimized not to do anything if 'targets' didn't change. */ + dc_commit_targets(dm->dc, commit_targets, commit_targets_count); + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + + if (acrtc->target != NULL) + acrtc->otg_inst = + dc_target_get_status(acrtc->target)->primary_otg_inst; + } + + /* update planes when needed */ + for_each_plane_in_state(state, plane, old_plane_state, i) { + struct drm_plane_state *plane_state = plane->state; + struct drm_crtc *crtc = plane_state->crtc; + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + struct drm_framebuffer *fb = plane_state->fb; + struct drm_connector *connector; + struct dm_connector_state *dm_state = NULL; + enum dm_commit_action action; + + if (!fb || !crtc || !crtc->state->active) + continue; + + action = get_dm_commit_action(crtc->state); + + /* Surfaces are created under two scenarios: + * 1. This commit is not a page flip. + * 2. This commit is a page flip, and targets are created. + */ + if (!page_flip_needed( + plane_state, + old_plane_state, + crtc->state->event, true) || + action == DM_COMMIT_ACTION_DPMS_ON || + action == DM_COMMIT_ACTION_SET) { + list_for_each_entry(connector, + &dev->mode_config.connector_list, head) { + if (connector->state->crtc == crtc) { + dm_state = to_dm_connector_state( + connector->state); + break; + } + } + + /* + * This situation happens in the following case: + * we are about to get set mode for connector who's only + * possible crtc (in encoder crtc mask) is used by + * another connector, that is why it will try to + * re-assing crtcs in order to make configuration + * supported. For our implementation we need to make all + * encoders support all crtcs, then this issue will + * never arise again. But to guard code from this issue + * check is left. + * + * Also it should be needed when used with actual + * drm_atomic_commit ioctl in future + */ + if (!dm_state) + continue; + + /* + * if flip is pending (ie, still waiting for fence to return + * before address is submitted) here, we cannot commit_surface + * as commit_surface will pre-maturely write out the future + * address. wait until flip is submitted before proceeding. + */ + wait_while_pflip_status(adev, acrtc, pflip_pending_predicate); + + dm_dc_surface_commit(dm->dc, crtc); + } + } + + for (i = 0; i < new_crtcs_count; i++) { + /* + * loop to enable interrupts on newly arrived crtc + */ + struct amdgpu_crtc *acrtc = new_crtcs[i]; + + if (adev->dm.freesync_module) { + for (j = 0; j < acrtc->target->stream_count; j++) + mod_freesync_notify_mode_change( + adev->dm.freesync_module, + acrtc->target->streams, + acrtc->target->stream_count); + } + + manage_dm_interrupts(adev, acrtc, true); + dm_crtc_cursor_reset(&acrtc->base); + + } + + /* Do actual flip */ + flip_crtcs_count = 0; + for_each_plane_in_state(state, plane, old_plane_state, i) { + struct drm_plane_state *plane_state = plane->state; + struct drm_crtc *crtc = plane_state->crtc; + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + struct drm_framebuffer *fb = plane_state->fb; + + if (!fb || !crtc || !crtc->state->planes_changed || + !crtc->state->active) + continue; + + if (page_flip_needed( + plane_state, + old_plane_state, + crtc->state->event, + false)) { + amdgpu_crtc_submit_flip( + crtc, + fb, + work[flip_crtcs_count], + new_abo[i]); + flip_crtcs_count++; + /*clean up the flags for next usage*/ + acrtc->flip_flags = 0; + } + } + + /* In this state all old framebuffers would be unpinned */ + + /* TODO: Revisit when we support true asynchronous commit.*/ + if (!async) + drm_atomic_helper_cleanup_planes(dev, state); + + drm_atomic_state_put(state); + + return ret; +} +/* + * This functions handle all cases when set mode does not come upon hotplug. + * This include when the same display is unplugged then plugged back into the + * same port and when we are running without usermode desktop manager supprot + */ +void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector *connector) +{ + struct drm_crtc *crtc; + struct amdgpu_device *adev = dev->dev_private; + struct dc *dc = adev->dm.dc; + struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + struct amdgpu_crtc *disconnected_acrtc; + const struct dc_sink *sink; + struct dc_target *commit_targets[6]; + struct dc_target *current_target; + uint32_t commit_targets_count = 0; + int i; + + if (!aconnector->dc_sink || !connector->state || !connector->encoder) + return; + + disconnected_acrtc = to_amdgpu_crtc(connector->encoder->crtc); + + if (!disconnected_acrtc || !disconnected_acrtc->target) + return; + + sink = disconnected_acrtc->target->streams[0]->sink; + + /* + * If the previous sink is not released and different from the current, + * we deduce we are in a state where we can not rely on usermode call + * to turn on the display, so we do it here + */ + if (sink != aconnector->dc_sink) { + struct dm_connector_state *dm_state = + to_dm_connector_state(aconnector->base.state); + + struct dc_target *new_target = + create_target_for_sink( + aconnector, + &disconnected_acrtc->base.state->mode, + dm_state); + + DRM_INFO("Headless hotplug, restoring connector state\n"); + /* + * we evade vblanks and pflips on crtc that + * should be changed + */ + manage_dm_interrupts(adev, disconnected_acrtc, false); + /* this is the update mode case */ + + current_target = disconnected_acrtc->target; + + disconnected_acrtc->target = new_target; + disconnected_acrtc->enabled = true; + disconnected_acrtc->hw_mode = disconnected_acrtc->base.state->mode; + + commit_targets_count = 0; + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + + if (acrtc->target) { + commit_targets[commit_targets_count] = acrtc->target; + ++commit_targets_count; + } + } + + /* DC is optimized not to do anything if 'targets' didn't change. */ + if (!dc_commit_targets(dc, commit_targets, + commit_targets_count)) { + DRM_INFO("Failed to restore connector state!\n"); + dc_target_release(disconnected_acrtc->target); + disconnected_acrtc->target = current_target; + manage_dm_interrupts(adev, disconnected_acrtc, true); + return; + } + + if (adev->dm.freesync_module) { + + for (i = 0; i < current_target->stream_count; i++) + mod_freesync_remove_stream( + adev->dm.freesync_module, + current_target->streams[i]); + + for (i = 0; i < new_target->stream_count; i++) + mod_freesync_add_stream( + adev->dm.freesync_module, + new_target->streams[i], + &aconnector->caps); + } + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + + if (acrtc->target != NULL) { + acrtc->otg_inst = + dc_target_get_status(acrtc->target)->primary_otg_inst; + } + } + + dc_target_release(current_target); + + dm_dc_surface_commit(dc, &disconnected_acrtc->base); + + manage_dm_interrupts(adev, disconnected_acrtc, true); + dm_crtc_cursor_reset(&disconnected_acrtc->base); + + } +} + +static uint32_t add_val_sets_surface( + struct dc_validation_set *val_sets, + uint32_t set_count, + const struct dc_target *target, + const struct dc_surface *surface) +{ + uint32_t i = 0; + + while (i < set_count) { + if (val_sets[i].target == target) + break; + ++i; + } + + val_sets[i].surfaces[val_sets[i].surface_count] = surface; + val_sets[i].surface_count++; + + return val_sets[i].surface_count; +} + +static uint32_t update_in_val_sets_target( + struct dc_validation_set *val_sets, + struct drm_crtc **crtcs, + uint32_t set_count, + const struct dc_target *old_target, + const struct dc_target *new_target, + struct drm_crtc *crtc) +{ + uint32_t i = 0; + + while (i < set_count) { + if (val_sets[i].target == old_target) + break; + ++i; + } + + val_sets[i].target = new_target; + crtcs[i] = crtc; + + if (i == set_count) { + /* nothing found. add new one to the end */ + return set_count + 1; + } + + return set_count; +} + +static uint32_t remove_from_val_sets( + struct dc_validation_set *val_sets, + uint32_t set_count, + const struct dc_target *target) +{ + int i; + + for (i = 0; i < set_count; i++) + if (val_sets[i].target == target) + break; + + if (i == set_count) { + /* nothing found */ + return set_count; + } + + set_count--; + + for (; i < set_count; i++) { + val_sets[i] = val_sets[i + 1]; + } + + return set_count; +} + +int amdgpu_dm_atomic_check(struct drm_device *dev, + struct drm_atomic_state *state) +{ + struct drm_crtc *crtc; + struct drm_crtc_state *crtc_state; + struct drm_plane *plane; + struct drm_plane_state *plane_state; + int i, j; + int ret; + int set_count; + int new_target_count; + struct dc_validation_set set[MAX_TARGETS] = {{ 0 }}; + struct dc_target *new_targets[MAX_TARGETS] = { 0 }; + struct drm_crtc *crtc_set[MAX_TARGETS] = { 0 }; + struct amdgpu_device *adev = dev->dev_private; + struct dc *dc = adev->dm.dc; + bool need_to_validate = false; + + ret = drm_atomic_helper_check(dev, state); + + if (ret) { + DRM_ERROR("Atomic state validation failed with error :%d !\n", + ret); + return ret; + } + + ret = -EINVAL; + + /* copy existing configuration */ + new_target_count = 0; + set_count = 0; + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + + if (acrtc->target) { + set[set_count].target = acrtc->target; + crtc_set[set_count] = crtc; + ++set_count; + } + } + + /* update changed items */ + for_each_crtc_in_state(state, crtc, crtc_state, i) { + struct amdgpu_crtc *acrtc = NULL; + struct amdgpu_connector *aconnector = NULL; + enum dm_commit_action action; + + acrtc = to_amdgpu_crtc(crtc); + + aconnector = amdgpu_dm_find_first_crct_matching_connector(state, crtc, true); + + action = get_dm_commit_action(crtc_state); + + switch (action) { + case DM_COMMIT_ACTION_DPMS_ON: + case DM_COMMIT_ACTION_SET: { + struct dc_target *new_target = NULL; + struct drm_connector_state *conn_state = NULL; + struct dm_connector_state *dm_state = NULL; + + if (aconnector) { + conn_state = drm_atomic_get_connector_state(state, &aconnector->base); + if (IS_ERR(conn_state)) + return ret; + dm_state = to_dm_connector_state(conn_state); + } + + new_target = create_target_for_sink(aconnector, &crtc_state->mode, dm_state); + + /* + * we can have no target on ACTION_SET if a display + * was disconnected during S3, in this case it not and + * error, the OS will be updated after detection, and + * do the right thing on next atomic commit + */ + if (!new_target) { + DRM_DEBUG_KMS("%s: Failed to create new target for crtc %d\n", + __func__, acrtc->base.base.id); + break; + } + + new_targets[new_target_count] = new_target; + set_count = update_in_val_sets_target( + set, + crtc_set, + set_count, + acrtc->target, + new_target, + crtc); + + new_target_count++; + need_to_validate = true; + break; + } + + case DM_COMMIT_ACTION_NOTHING: { + const struct drm_connector *drm_connector = NULL; + struct drm_connector_state *conn_state = NULL; + struct dm_connector_state *dm_state = NULL; + struct dm_connector_state *old_dm_state = NULL; + struct dc_target *new_target; + + if (!aconnector) + break; + + for_each_connector_in_state( + state, drm_connector, conn_state, j) { + if (&aconnector->base == drm_connector) + break; + } + + old_dm_state = to_dm_connector_state(drm_connector->state); + dm_state = to_dm_connector_state(conn_state); + + /* Support underscan adjustment*/ + if (!is_scaling_state_different(dm_state, old_dm_state)) + break; + + new_target = create_target_for_sink(aconnector, &crtc_state->mode, dm_state); + + if (!new_target) { + DRM_ERROR("%s: Failed to create new target for crtc %d\n", + __func__, acrtc->base.base.id); + break; + } + + new_targets[new_target_count] = new_target; + set_count = update_in_val_sets_target( + set, + crtc_set, + set_count, + acrtc->target, + new_target, + crtc); + + new_target_count++; + need_to_validate = true; + + break; + } + case DM_COMMIT_ACTION_DPMS_OFF: + case DM_COMMIT_ACTION_RESET: + /* i.e. reset mode */ + if (acrtc->target) { + set_count = remove_from_val_sets( + set, + set_count, + acrtc->target); + } + break; + } + + /* + * TODO revisit when removing commit action + * and looking at atomic flags directly + */ + + /* commit needs planes right now (for gamma, eg.) */ + /* TODO rework commit to chack crtc for gamma change */ + ret = drm_atomic_add_affected_planes(state, crtc); + if (ret) + return ret; + } + + for (i = 0; i < set_count; i++) { + for_each_plane_in_state(state, plane, plane_state, j) { + struct drm_plane_state *old_plane_state = plane->state; + struct drm_crtc *crtc = plane_state->crtc; + struct drm_framebuffer *fb = plane_state->fb; + struct drm_connector *connector; + struct dm_connector_state *dm_state = NULL; + enum dm_commit_action action; + struct drm_crtc_state *crtc_state; + + + if (!fb || !crtc || crtc_set[i] != crtc || + !crtc->state->planes_changed || !crtc->state->active) + continue; + + action = get_dm_commit_action(crtc->state); + + /* Surfaces are created under two scenarios: + * 1. This commit is not a page flip. + * 2. This commit is a page flip, and targets are created. + */ + crtc_state = drm_atomic_get_crtc_state(state, crtc); + if (!page_flip_needed(plane_state, old_plane_state, + crtc_state->event, true) || + action == DM_COMMIT_ACTION_DPMS_ON || + action == DM_COMMIT_ACTION_SET) { + struct dc_surface *surface; + + list_for_each_entry(connector, + &dev->mode_config.connector_list, head) { + if (connector->state->crtc == crtc) { + dm_state = to_dm_connector_state( + connector->state); + break; + } + } + + /* + * This situation happens in the following case: + * we are about to get set mode for connector who's only + * possible crtc (in encoder crtc mask) is used by + * another connector, that is why it will try to + * re-assing crtcs in order to make configuration + * supported. For our implementation we need to make all + * encoders support all crtcs, then this issue will + * never arise again. But to guard code from this issue + * check is left. + * + * Also it should be needed when used with actual + * drm_atomic_commit ioctl in future + */ + if (!dm_state) + continue; + + surface = dc_create_surface(dc); + fill_plane_attributes( + surface, + plane_state, + false); + + add_val_sets_surface( + set, + set_count, + set[i].target, + surface); + + need_to_validate = true; + } + } + } + + if (need_to_validate == false || set_count == 0 || + dc_validate_resources(dc, set, set_count)) + ret = 0; + + for (i = 0; i < set_count; i++) { + for (j = 0; j < set[i].surface_count; j++) { + dc_surface_release(set[i].surfaces[j]); + } + } + for (i = 0; i < new_target_count; i++) + dc_target_release(new_targets[i]); + + if (ret != 0) + DRM_ERROR("Atomic check failed.\n"); + + return ret; +} + +static bool is_dp_capable_without_timing_msa( + struct dc *dc, + struct amdgpu_connector *amdgpu_connector) +{ + uint8_t dpcd_data; + bool capable = false; + if (amdgpu_connector->dc_link && + dc_read_dpcd(dc, amdgpu_connector->dc_link->link_index, + DP_DOWN_STREAM_PORT_COUNT, + &dpcd_data, sizeof(dpcd_data)) ) + capable = dpcd_data & DP_MSA_TIMING_PAR_IGNORED? true:false; + + return capable; +} +void amdgpu_dm_add_sink_to_freesync_module( + struct drm_connector *connector, + struct edid *edid) +{ + int i; + uint64_t val_capable; + bool edid_check_required; + struct detailed_timing *timing; + struct detailed_non_pixel *data; + struct detailed_data_monitor_range *range; + struct amdgpu_connector *amdgpu_connector = + to_amdgpu_connector(connector); + + struct drm_device *dev = connector->dev; + struct amdgpu_device *adev = dev->dev_private; + edid_check_required = false; + if (!amdgpu_connector->dc_sink) { + DRM_ERROR("dc_sink NULL, could not add free_sync module.\n"); + return; + } + if (!adev->dm.freesync_module) + return; + /* + * if edid non zero restrict freesync only for dp and edp + */ + if (edid) { + if (amdgpu_connector->dc_sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT + || amdgpu_connector->dc_sink->sink_signal == SIGNAL_TYPE_EDP) { + edid_check_required = is_dp_capable_without_timing_msa( + adev->dm.dc, + amdgpu_connector); + } + } + val_capable = 0; + if (edid_check_required == true && (edid->version > 1 || + (edid->version == 1 && edid->revision > 1))) { + for (i = 0; i < 4; i++) { + + timing = &edid->detailed_timings[i]; + data = &timing->data.other_data; + range = &data->data.range; + /* + * Check if monitor has continuous frequency mode + */ + if (data->type != EDID_DETAIL_MONITOR_RANGE) + continue; + /* + * Check for flag range limits only. If flag == 1 then + * no additional timing information provided. + * Default GTF, GTF Secondary curve and CVT are not + * supported + */ + if (range->flags != 1) + continue; + + amdgpu_connector->min_vfreq = range->min_vfreq; + amdgpu_connector->max_vfreq = range->max_vfreq; + amdgpu_connector->pixel_clock_mhz = + range->pixel_clock_mhz * 10; + break; + } + + if (amdgpu_connector->max_vfreq - + amdgpu_connector->min_vfreq > 10) { + amdgpu_connector->caps.supported = true; + amdgpu_connector->caps.min_refresh_in_micro_hz = + amdgpu_connector->min_vfreq * 1000000; + amdgpu_connector->caps.max_refresh_in_micro_hz = + amdgpu_connector->max_vfreq * 1000000; + val_capable = 1; + } + } + + /* + * TODO figure out how to notify user-mode or DRM of freesync caps + * once we figure out how to deal with freesync in an upstreamable + * fashion + */ + +} + +void amdgpu_dm_remove_sink_from_freesync_module( + struct drm_connector *connector) +{ + /* + * TODO fill in once we figure out how to deal with freesync in + * an upstreamable fashion + */ +} diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h new file mode 100644 index 000000000000..4f7bd3bae44e --- /dev/null +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h @@ -0,0 +1,101 @@ +/* + * Copyright 2012-13 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __AMDGPU_DM_TYPES_H__ +#define __AMDGPU_DM_TYPES_H__ + +#include + +struct amdgpu_framebuffer; +struct amdgpu_display_manager; +struct dc_validation_set; +struct dc_surface; + +/*TODO Jodan Hersen use the one in amdgpu_dm*/ +int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, + struct amdgpu_crtc *amdgpu_crtc, + uint32_t link_index); +int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm, + struct amdgpu_connector *amdgpu_connector, + uint32_t link_index, + struct amdgpu_encoder *amdgpu_encoder); +int amdgpu_dm_encoder_init( + struct drm_device *dev, + struct amdgpu_encoder *aencoder, + uint32_t link_index); + +void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc); +void amdgpu_dm_connector_destroy(struct drm_connector *connector); +void amdgpu_dm_encoder_destroy(struct drm_encoder *encoder); + +int amdgpu_dm_connector_get_modes(struct drm_connector *connector); + +int amdgpu_dm_atomic_commit( + struct drm_device *dev, + struct drm_atomic_state *state, + bool async); +int amdgpu_dm_atomic_check(struct drm_device *dev, + struct drm_atomic_state *state); + +int dm_create_validation_set_for_target( + struct drm_connector *connector, + struct drm_display_mode *mode, + struct dc_validation_set *val_set); + +void amdgpu_dm_connector_funcs_reset(struct drm_connector *connector); +struct drm_connector_state *amdgpu_dm_connector_atomic_duplicate_state( + struct drm_connector *connector); + +int amdgpu_dm_connector_atomic_set_property( + struct drm_connector *connector, + struct drm_connector_state *state, + struct drm_property *property, + uint64_t val); + +int amdgpu_dm_get_encoder_crtc_mask(struct amdgpu_device *adev); + +void amdgpu_dm_connector_init_helper( + struct amdgpu_display_manager *dm, + struct amdgpu_connector *aconnector, + int connector_type, + const struct dc_link *link, + int link_index); + +int amdgpu_dm_connector_mode_valid( + struct drm_connector *connector, + struct drm_display_mode *mode); + +void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector *connector); + +void amdgpu_dm_add_sink_to_freesync_module( + struct drm_connector *connector, + struct edid *edid); + +void amdgpu_dm_remove_sink_from_freesync_module( + struct drm_connector *connector); + +extern const struct drm_encoder_helper_funcs amdgpu_dm_encoder_helper_funcs; + +#endif /* __AMDGPU_DM_TYPES_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/Makefile b/drivers/gpu/drm/amd/display/dc/Makefile new file mode 100644 index 000000000000..5fac034093e9 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/Makefile @@ -0,0 +1,28 @@ +# +# Makefile for Display Core (dc) component. +# + +DC_LIBS = basics bios calcs dce \ +gpio gpu i2caux irq virtual + +DC_LIBS += dce112 +DC_LIBS += dce110 +DC_LIBS += dce100 +DC_LIBS += dce80 + +AMD_DC = $(addsuffix /Makefile, $(addprefix $(FULL_AMD_DISPLAY_PATH)/dc/,$(DC_LIBS))) + +include $(AMD_DC) + +DISPLAY_CORE = dc.o dc_link.o dc_resource.o dc_hw_sequencer.o dc_target.o dc_sink.o dc_stream.o \ +dc_surface.o dc_link_hwss.o dc_link_dp.o dc_link_ddc.o dc_debug.o + +AMD_DISPLAY_CORE = $(addprefix $(AMDDALPATH)/dc/core/,$(DISPLAY_CORE)) + +AMD_DM_REG_UPDATE = $(addprefix $(AMDDALPATH)/dc/,dc_helper.o) + +AMD_DISPLAY_FILES += $(AMD_DISPLAY_CORE) +AMD_DISPLAY_FILES += $(AMD_DM_REG_UPDATE) + + + diff --git a/drivers/gpu/drm/amd/display/dc/basics/Makefile b/drivers/gpu/drm/amd/display/dc/basics/Makefile new file mode 100644 index 000000000000..a263cadcc0df --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/basics/Makefile @@ -0,0 +1,11 @@ +# +# Makefile for the 'utils' sub-component of DAL. +# It provides the general basic services required by other DAL +# subcomponents. + +BASICS = conversion.o fixpt31_32.o fixpt32_32.o grph_object_id.o \ + logger.o log_helpers.o register_logger.o signal_types.o vector.o + +AMD_DAL_BASICS = $(addprefix $(AMDDALPATH)/dc/basics/,$(BASICS)) + +AMD_DISPLAY_FILES += $(AMD_DAL_BASICS) diff --git a/drivers/gpu/drm/amd/display/dc/basics/conversion.c b/drivers/gpu/drm/amd/display/dc/basics/conversion.c new file mode 100644 index 000000000000..ebe14e17cc2e --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/basics/conversion.c @@ -0,0 +1,223 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#define DIVIDER 10000 + +/* S2D13 value in [-3.00...0.9999] */ +#define S2D13_MIN (-3 * DIVIDER) +#define S2D13_MAX (3 * DIVIDER) + +uint16_t fixed_point_to_int_frac( + struct fixed31_32 arg, + uint8_t integer_bits, + uint8_t fractional_bits) +{ + int32_t numerator; + int32_t divisor = 1 << fractional_bits; + + uint16_t result; + + uint16_t d = (uint16_t)dal_fixed31_32_floor( + dal_fixed31_32_abs( + arg)); + + if (d <= (uint16_t)(1 << integer_bits) - (1 / (uint16_t)divisor)) + numerator = (uint16_t)dal_fixed31_32_floor( + dal_fixed31_32_mul_int( + arg, + divisor)); + else { + numerator = dal_fixed31_32_floor( + dal_fixed31_32_sub( + dal_fixed31_32_from_int( + 1LL << integer_bits), + dal_fixed31_32_recip( + dal_fixed31_32_from_int( + divisor)))); + } + + if (numerator >= 0) + result = (uint16_t)numerator; + else + result = (uint16_t)( + (1 << (integer_bits + fractional_bits + 1)) + numerator); + + if ((result != 0) && dal_fixed31_32_lt( + arg, dal_fixed31_32_zero)) + result |= 1 << (integer_bits + fractional_bits); + + return result; +} +/** +* convert_float_matrix +* This converts a double into HW register spec defined format S2D13. +* @param : +* @return None +*/ +void convert_float_matrix( + uint16_t *matrix, + struct fixed31_32 *flt, + uint32_t buffer_size) +{ + const struct fixed31_32 min_2_13 = + dal_fixed31_32_from_fraction(S2D13_MIN, DIVIDER); + const struct fixed31_32 max_2_13 = + dal_fixed31_32_from_fraction(S2D13_MAX, DIVIDER); + uint32_t i; + + for (i = 0; i < buffer_size; ++i) { + uint32_t reg_value = + fixed_point_to_int_frac( + dal_fixed31_32_clamp( + flt[i], + min_2_13, + max_2_13), + 2, + 13); + + matrix[i] = (uint16_t)reg_value; + } +} + +static void calculate_adjustments_common( + const struct fixed31_32 *ideal_matrix, + const struct dc_csc_adjustments *adjustments, + struct fixed31_32 *matrix) +{ + const struct fixed31_32 sin_hue = + dal_fixed31_32_sin(adjustments->hue); + const struct fixed31_32 cos_hue = + dal_fixed31_32_cos(adjustments->hue); + + const struct fixed31_32 multiplier = + dal_fixed31_32_mul( + adjustments->contrast, + adjustments->saturation); + + matrix[0] = dal_fixed31_32_mul( + ideal_matrix[0], + adjustments->contrast); + + matrix[1] = dal_fixed31_32_mul( + ideal_matrix[1], + adjustments->contrast); + + matrix[2] = dal_fixed31_32_mul( + ideal_matrix[2], + adjustments->contrast); + + matrix[4] = dal_fixed31_32_mul( + multiplier, + dal_fixed31_32_add( + dal_fixed31_32_mul( + ideal_matrix[8], + sin_hue), + dal_fixed31_32_mul( + ideal_matrix[4], + cos_hue))); + + matrix[5] = dal_fixed31_32_mul( + multiplier, + dal_fixed31_32_add( + dal_fixed31_32_mul( + ideal_matrix[9], + sin_hue), + dal_fixed31_32_mul( + ideal_matrix[5], + cos_hue))); + + matrix[6] = dal_fixed31_32_mul( + multiplier, + dal_fixed31_32_add( + dal_fixed31_32_mul( + ideal_matrix[10], + sin_hue), + dal_fixed31_32_mul( + ideal_matrix[6], + cos_hue))); + + matrix[7] = ideal_matrix[7]; + + matrix[8] = dal_fixed31_32_mul( + multiplier, + dal_fixed31_32_sub( + dal_fixed31_32_mul( + ideal_matrix[8], + cos_hue), + dal_fixed31_32_mul( + ideal_matrix[4], + sin_hue))); + + matrix[9] = dal_fixed31_32_mul( + multiplier, + dal_fixed31_32_sub( + dal_fixed31_32_mul( + ideal_matrix[9], + cos_hue), + dal_fixed31_32_mul( + ideal_matrix[5], + sin_hue))); + + matrix[10] = dal_fixed31_32_mul( + multiplier, + dal_fixed31_32_sub( + dal_fixed31_32_mul( + ideal_matrix[10], + cos_hue), + dal_fixed31_32_mul( + ideal_matrix[6], + sin_hue))); + + matrix[11] = ideal_matrix[11]; +} + +void calculate_adjustments( + const struct fixed31_32 *ideal_matrix, + const struct dc_csc_adjustments *adjustments, + struct fixed31_32 *matrix) +{ + calculate_adjustments_common(ideal_matrix, adjustments, matrix); + + matrix[3] = dal_fixed31_32_add( + ideal_matrix[3], + dal_fixed31_32_mul( + adjustments->brightness, + dal_fixed31_32_from_fraction(86, 100))); +} + +void calculate_adjustments_y_only( + const struct fixed31_32 *ideal_matrix, + const struct dc_csc_adjustments *adjustments, + struct fixed31_32 *matrix) +{ + calculate_adjustments_common(ideal_matrix, adjustments, matrix); + + matrix[3] = dal_fixed31_32_add( + ideal_matrix[3], + adjustments->brightness); +} + diff --git a/drivers/gpu/drm/amd/display/dc/basics/conversion.h b/drivers/gpu/drm/amd/display/dc/basics/conversion.h new file mode 100644 index 000000000000..18cbe41e80ff --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/basics/conversion.h @@ -0,0 +1,51 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_CONVERSION_H__ +#define __DAL_CONVERSION_H__ + +#include "include/fixed31_32.h" + +uint16_t fixed_point_to_int_frac( + struct fixed31_32 arg, + uint8_t integer_bits, + uint8_t fractional_bits); + +void convert_float_matrix( + uint16_t *matrix, + struct fixed31_32 *flt, + uint32_t buffer_size); + +void calculate_adjustments( + const struct fixed31_32 *ideal_matrix, + const struct dc_csc_adjustments *adjustments, + struct fixed31_32 *matrix); + +void calculate_adjustments_y_only( + const struct fixed31_32 *ideal_matrix, + const struct dc_csc_adjustments *adjustments, + struct fixed31_32 *matrix); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c b/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c new file mode 100644 index 000000000000..5a6e46843502 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c @@ -0,0 +1,691 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "include/fixed31_32.h" + +static inline uint64_t abs_i64( + int64_t arg) +{ + if (arg > 0) + return (uint64_t)arg; + else + return (uint64_t)(-arg); +} + +/* + * @brief + * result = dividend / divisor + * *remainder = dividend % divisor + */ +static inline uint64_t complete_integer_division_u64( + uint64_t dividend, + uint64_t divisor, + uint64_t *remainder) +{ + uint64_t result; + + ASSERT(divisor); + + result = div64_u64_rem(dividend, divisor, remainder); + + return result; +} + +#define BITS_PER_FRACTIONAL_PART \ + 32 + +#define FRACTIONAL_PART_MASK \ + ((1ULL << BITS_PER_FRACTIONAL_PART) - 1) + +#define GET_INTEGER_PART(x) \ + ((x) >> BITS_PER_FRACTIONAL_PART) + +#define GET_FRACTIONAL_PART(x) \ + (FRACTIONAL_PART_MASK & (x)) + +struct fixed31_32 dal_fixed31_32_from_fraction( + int64_t numerator, + int64_t denominator) +{ + struct fixed31_32 res; + + bool arg1_negative = numerator < 0; + bool arg2_negative = denominator < 0; + + uint64_t arg1_value = arg1_negative ? -numerator : numerator; + uint64_t arg2_value = arg2_negative ? -denominator : denominator; + + uint64_t remainder; + + /* determine integer part */ + + uint64_t res_value = complete_integer_division_u64( + arg1_value, arg2_value, &remainder); + + ASSERT(res_value <= LONG_MAX); + + /* determine fractional part */ + { + uint32_t i = BITS_PER_FRACTIONAL_PART; + + do { + remainder <<= 1; + + res_value <<= 1; + + if (remainder >= arg2_value) { + res_value |= 1; + remainder -= arg2_value; + } + } while (--i != 0); + } + + /* round up LSB */ + { + uint64_t summand = (remainder << 1) >= arg2_value; + + ASSERT(res_value <= LLONG_MAX - summand); + + res_value += summand; + } + + res.value = (int64_t)res_value; + + if (arg1_negative ^ arg2_negative) + res.value = -res.value; + + return res; +} + +struct fixed31_32 dal_fixed31_32_from_int( + int64_t arg) +{ + struct fixed31_32 res; + + ASSERT((LONG_MIN <= arg) && (arg <= LONG_MAX)); + + res.value = arg << BITS_PER_FRACTIONAL_PART; + + return res; +} + +struct fixed31_32 dal_fixed31_32_neg( + struct fixed31_32 arg) +{ + struct fixed31_32 res; + + res.value = -arg.value; + + return res; +} + +struct fixed31_32 dal_fixed31_32_abs( + struct fixed31_32 arg) +{ + if (arg.value < 0) + return dal_fixed31_32_neg(arg); + else + return arg; +} + +bool dal_fixed31_32_lt( + struct fixed31_32 arg1, + struct fixed31_32 arg2) +{ + return arg1.value < arg2.value; +} + +bool dal_fixed31_32_le( + struct fixed31_32 arg1, + struct fixed31_32 arg2) +{ + return arg1.value <= arg2.value; +} + +bool dal_fixed31_32_eq( + struct fixed31_32 arg1, + struct fixed31_32 arg2) +{ + return arg1.value == arg2.value; +} + +struct fixed31_32 dal_fixed31_32_min( + struct fixed31_32 arg1, + struct fixed31_32 arg2) +{ + if (arg1.value <= arg2.value) + return arg1; + else + return arg2; +} + +struct fixed31_32 dal_fixed31_32_max( + struct fixed31_32 arg1, + struct fixed31_32 arg2) +{ + if (arg1.value <= arg2.value) + return arg2; + else + return arg1; +} + +struct fixed31_32 dal_fixed31_32_clamp( + struct fixed31_32 arg, + struct fixed31_32 min_value, + struct fixed31_32 max_value) +{ + if (dal_fixed31_32_le(arg, min_value)) + return min_value; + else if (dal_fixed31_32_le(max_value, arg)) + return max_value; + else + return arg; +} + +struct fixed31_32 dal_fixed31_32_shl( + struct fixed31_32 arg, + uint8_t shift) +{ + struct fixed31_32 res; + + ASSERT(((arg.value >= 0) && (arg.value <= LLONG_MAX >> shift)) || + ((arg.value < 0) && (arg.value >= LLONG_MIN >> shift))); + + res.value = arg.value << shift; + + return res; +} + +struct fixed31_32 dal_fixed31_32_shr( + struct fixed31_32 arg, + uint8_t shift) +{ + struct fixed31_32 res; + + ASSERT(shift < 64); + + res.value = arg.value >> shift; + + return res; +} + +struct fixed31_32 dal_fixed31_32_add( + struct fixed31_32 arg1, + struct fixed31_32 arg2) +{ + struct fixed31_32 res; + + ASSERT(((arg1.value >= 0) && (LLONG_MAX - arg1.value >= arg2.value)) || + ((arg1.value < 0) && (LLONG_MIN - arg1.value <= arg2.value))); + + res.value = arg1.value + arg2.value; + + return res; +} + +struct fixed31_32 dal_fixed31_32_sub_int( + struct fixed31_32 arg1, + int32_t arg2) +{ + return dal_fixed31_32_sub( + arg1, + dal_fixed31_32_from_int(arg2)); +} + +struct fixed31_32 dal_fixed31_32_sub( + struct fixed31_32 arg1, + struct fixed31_32 arg2) +{ + struct fixed31_32 res; + + ASSERT(((arg2.value >= 0) && (LLONG_MIN + arg2.value <= arg1.value)) || + ((arg2.value < 0) && (LLONG_MAX + arg2.value >= arg1.value))); + + res.value = arg1.value - arg2.value; + + return res; +} + +struct fixed31_32 dal_fixed31_32_mul_int( + struct fixed31_32 arg1, + int32_t arg2) +{ + return dal_fixed31_32_mul( + arg1, + dal_fixed31_32_from_int(arg2)); +} + +struct fixed31_32 dal_fixed31_32_mul( + struct fixed31_32 arg1, + struct fixed31_32 arg2) +{ + struct fixed31_32 res; + + bool arg1_negative = arg1.value < 0; + bool arg2_negative = arg2.value < 0; + + uint64_t arg1_value = arg1_negative ? -arg1.value : arg1.value; + uint64_t arg2_value = arg2_negative ? -arg2.value : arg2.value; + + uint64_t arg1_int = GET_INTEGER_PART(arg1_value); + uint64_t arg2_int = GET_INTEGER_PART(arg2_value); + + uint64_t arg1_fra = GET_FRACTIONAL_PART(arg1_value); + uint64_t arg2_fra = GET_FRACTIONAL_PART(arg2_value); + + uint64_t tmp; + + res.value = arg1_int * arg2_int; + + ASSERT(res.value <= LONG_MAX); + + res.value <<= BITS_PER_FRACTIONAL_PART; + + tmp = arg1_int * arg2_fra; + + ASSERT(tmp <= (uint64_t)(LLONG_MAX - res.value)); + + res.value += tmp; + + tmp = arg2_int * arg1_fra; + + ASSERT(tmp <= (uint64_t)(LLONG_MAX - res.value)); + + res.value += tmp; + + tmp = arg1_fra * arg2_fra; + + tmp = (tmp >> BITS_PER_FRACTIONAL_PART) + + (tmp >= (uint64_t)dal_fixed31_32_half.value); + + ASSERT(tmp <= (uint64_t)(LLONG_MAX - res.value)); + + res.value += tmp; + + if (arg1_negative ^ arg2_negative) + res.value = -res.value; + + return res; +} + +struct fixed31_32 dal_fixed31_32_sqr( + struct fixed31_32 arg) +{ + struct fixed31_32 res; + + uint64_t arg_value = abs_i64(arg.value); + + uint64_t arg_int = GET_INTEGER_PART(arg_value); + + uint64_t arg_fra = GET_FRACTIONAL_PART(arg_value); + + uint64_t tmp; + + res.value = arg_int * arg_int; + + ASSERT(res.value <= LONG_MAX); + + res.value <<= BITS_PER_FRACTIONAL_PART; + + tmp = arg_int * arg_fra; + + ASSERT(tmp <= (uint64_t)(LLONG_MAX - res.value)); + + res.value += tmp; + + ASSERT(tmp <= (uint64_t)(LLONG_MAX - res.value)); + + res.value += tmp; + + tmp = arg_fra * arg_fra; + + tmp = (tmp >> BITS_PER_FRACTIONAL_PART) + + (tmp >= (uint64_t)dal_fixed31_32_half.value); + + ASSERT(tmp <= (uint64_t)(LLONG_MAX - res.value)); + + res.value += tmp; + + return res; +} + +struct fixed31_32 dal_fixed31_32_div_int( + struct fixed31_32 arg1, + int64_t arg2) +{ + return dal_fixed31_32_from_fraction( + arg1.value, + dal_fixed31_32_from_int(arg2).value); +} + +struct fixed31_32 dal_fixed31_32_div( + struct fixed31_32 arg1, + struct fixed31_32 arg2) +{ + return dal_fixed31_32_from_fraction( + arg1.value, + arg2.value); +} + +struct fixed31_32 dal_fixed31_32_recip( + struct fixed31_32 arg) +{ + /* + * @note + * Good idea to use Newton's method + */ + + ASSERT(arg.value); + + return dal_fixed31_32_from_fraction( + dal_fixed31_32_one.value, + arg.value); +} + +struct fixed31_32 dal_fixed31_32_sinc( + struct fixed31_32 arg) +{ + struct fixed31_32 square; + + struct fixed31_32 res = dal_fixed31_32_one; + + int32_t n = 27; + + struct fixed31_32 arg_norm = arg; + + if (dal_fixed31_32_le( + dal_fixed31_32_two_pi, + dal_fixed31_32_abs(arg))) { + arg_norm = dal_fixed31_32_sub( + arg_norm, + dal_fixed31_32_mul_int( + dal_fixed31_32_two_pi, + (int32_t)div64_s64( + arg_norm.value, + dal_fixed31_32_two_pi.value))); + } + + square = dal_fixed31_32_sqr(arg_norm); + + do { + res = dal_fixed31_32_sub( + dal_fixed31_32_one, + dal_fixed31_32_div_int( + dal_fixed31_32_mul( + square, + res), + n * (n - 1))); + + n -= 2; + } while (n > 2); + + if (arg.value != arg_norm.value) + res = dal_fixed31_32_div( + dal_fixed31_32_mul(res, arg_norm), + arg); + + return res; +} + +struct fixed31_32 dal_fixed31_32_sin( + struct fixed31_32 arg) +{ + return dal_fixed31_32_mul( + arg, + dal_fixed31_32_sinc(arg)); +} + +struct fixed31_32 dal_fixed31_32_cos( + struct fixed31_32 arg) +{ + /* TODO implement argument normalization */ + + const struct fixed31_32 square = dal_fixed31_32_sqr(arg); + + struct fixed31_32 res = dal_fixed31_32_one; + + int32_t n = 26; + + do { + res = dal_fixed31_32_sub( + dal_fixed31_32_one, + dal_fixed31_32_div_int( + dal_fixed31_32_mul( + square, + res), + n * (n - 1))); + + n -= 2; + } while (n != 0); + + return res; +} + +/* + * @brief + * result = exp(arg), + * where abs(arg) < 1 + * + * Calculated as Taylor series. + */ +static struct fixed31_32 fixed31_32_exp_from_taylor_series( + struct fixed31_32 arg) +{ + uint32_t n = 9; + + struct fixed31_32 res = dal_fixed31_32_from_fraction( + n + 2, + n + 1); + /* TODO find correct res */ + + ASSERT(dal_fixed31_32_lt(arg, dal_fixed31_32_one)); + + do + res = dal_fixed31_32_add( + dal_fixed31_32_one, + dal_fixed31_32_div_int( + dal_fixed31_32_mul( + arg, + res), + n)); + while (--n != 1); + + return dal_fixed31_32_add( + dal_fixed31_32_one, + dal_fixed31_32_mul( + arg, + res)); +} + +struct fixed31_32 dal_fixed31_32_exp( + struct fixed31_32 arg) +{ + /* + * @brief + * Main equation is: + * exp(x) = exp(r + m * ln(2)) = (1 << m) * exp(r), + * where m = round(x / ln(2)), r = x - m * ln(2) + */ + + if (dal_fixed31_32_le( + dal_fixed31_32_ln2_div_2, + dal_fixed31_32_abs(arg))) { + int32_t m = dal_fixed31_32_round( + dal_fixed31_32_div( + arg, + dal_fixed31_32_ln2)); + + struct fixed31_32 r = dal_fixed31_32_sub( + arg, + dal_fixed31_32_mul_int( + dal_fixed31_32_ln2, + m)); + + ASSERT(m != 0); + + ASSERT(dal_fixed31_32_lt( + dal_fixed31_32_abs(r), + dal_fixed31_32_one)); + + if (m > 0) + return dal_fixed31_32_shl( + fixed31_32_exp_from_taylor_series(r), + (uint8_t)m); + else + return dal_fixed31_32_div_int( + fixed31_32_exp_from_taylor_series(r), + 1LL << -m); + } else if (arg.value != 0) + return fixed31_32_exp_from_taylor_series(arg); + else + return dal_fixed31_32_one; +} + +struct fixed31_32 dal_fixed31_32_log( + struct fixed31_32 arg) +{ + struct fixed31_32 res = dal_fixed31_32_neg(dal_fixed31_32_one); + /* TODO improve 1st estimation */ + + struct fixed31_32 error; + + ASSERT(arg.value > 0); + /* TODO if arg is negative, return NaN */ + /* TODO if arg is zero, return -INF */ + + do { + struct fixed31_32 res1 = dal_fixed31_32_add( + dal_fixed31_32_sub( + res, + dal_fixed31_32_one), + dal_fixed31_32_div( + arg, + dal_fixed31_32_exp(res))); + + error = dal_fixed31_32_sub( + res, + res1); + + res = res1; + /* TODO determine max_allowed_error based on quality of exp() */ + } while (abs_i64(error.value) > 100ULL); + + return res; +} + +struct fixed31_32 dal_fixed31_32_pow( + struct fixed31_32 arg1, + struct fixed31_32 arg2) +{ + return dal_fixed31_32_exp( + dal_fixed31_32_mul( + dal_fixed31_32_log(arg1), + arg2)); +} + +int32_t dal_fixed31_32_floor( + struct fixed31_32 arg) +{ + uint64_t arg_value = abs_i64(arg.value); + + if (arg.value >= 0) + return (int32_t)GET_INTEGER_PART(arg_value); + else + return -(int32_t)GET_INTEGER_PART(arg_value); +} + +int32_t dal_fixed31_32_round( + struct fixed31_32 arg) +{ + uint64_t arg_value = abs_i64(arg.value); + + const int64_t summand = dal_fixed31_32_half.value; + + ASSERT(LLONG_MAX - (int64_t)arg_value >= summand); + + arg_value += summand; + + if (arg.value >= 0) + return (int32_t)GET_INTEGER_PART(arg_value); + else + return -(int32_t)GET_INTEGER_PART(arg_value); +} + +int32_t dal_fixed31_32_ceil( + struct fixed31_32 arg) +{ + uint64_t arg_value = abs_i64(arg.value); + + const int64_t summand = dal_fixed31_32_one.value - + dal_fixed31_32_epsilon.value; + + ASSERT(LLONG_MAX - (int64_t)arg_value >= summand); + + arg_value += summand; + + if (arg.value >= 0) + return (int32_t)GET_INTEGER_PART(arg_value); + else + return -(int32_t)GET_INTEGER_PART(arg_value); +} + +/* this function is a generic helper to translate fixed point value to + * specified integer format that will consist of integer_bits integer part and + * fractional_bits fractional part. For example it is used in + * dal_fixed31_32_u2d19 to receive 2 bits integer part and 19 bits fractional + * part in 32 bits. It is used in hw programming (scaler) + */ + +static inline uint32_t ux_dy( + int64_t value, + uint32_t integer_bits, + uint32_t fractional_bits) +{ + /* 1. create mask of integer part */ + uint32_t result = (1 << integer_bits) - 1; + /* 2. mask out fractional part */ + uint32_t fractional_part = FRACTIONAL_PART_MASK & value; + /* 3. shrink fixed point integer part to be of integer_bits width*/ + result &= GET_INTEGER_PART(value); + /* 4. make space for fractional part to be filled in after integer */ + result <<= fractional_bits; + /* 5. shrink fixed point fractional part to of fractional_bits width*/ + fractional_part >>= BITS_PER_FRACTIONAL_PART - fractional_bits; + /* 6. merge the result */ + return result | fractional_part; +} + +uint32_t dal_fixed31_32_u2d19( + struct fixed31_32 arg) +{ + return ux_dy(arg.value, 2, 19); +} + +uint32_t dal_fixed31_32_u0d19( + struct fixed31_32 arg) +{ + return ux_dy(arg.value, 0, 19); +} diff --git a/drivers/gpu/drm/amd/display/dc/basics/fixpt32_32.c b/drivers/gpu/drm/amd/display/dc/basics/fixpt32_32.c new file mode 100644 index 000000000000..911e90bb1b5c --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/basics/fixpt32_32.c @@ -0,0 +1,221 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "include/fixed32_32.h" + +static uint64_t u64_div(uint64_t n, uint64_t d) +{ + uint32_t i = 0; + uint64_t r; + uint64_t q = div64_u64_rem(n, d, &r); + + for (i = 0; i < 32; ++i) { + uint64_t sbit = q & (1ULL<<63); + + r <<= 1; + r |= sbit ? 1 : 0; + q <<= 1; + if (r >= d) { + r -= d; + q |= 1; + } + } + + if (2*r >= d) + q += 1; + return q; +} + +struct fixed32_32 dal_fixed32_32_from_fraction(uint32_t n, uint32_t d) +{ + struct fixed32_32 fx; + + fx.value = u64_div((uint64_t)n << 32, (uint64_t)d << 32); + return fx; +} + +struct fixed32_32 dal_fixed32_32_from_int(uint32_t value) +{ + struct fixed32_32 fx; + + fx.value = (uint64_t)value<<32; + return fx; +} + +struct fixed32_32 dal_fixed32_32_add( + struct fixed32_32 lhs, + struct fixed32_32 rhs) +{ + struct fixed32_32 fx = {lhs.value + rhs.value}; + + ASSERT(fx.value >= rhs.value); + return fx; +} + +struct fixed32_32 dal_fixed32_32_add_int(struct fixed32_32 lhs, uint32_t rhs) +{ + struct fixed32_32 fx = {lhs.value + ((uint64_t)rhs << 32)}; + + ASSERT(fx.value >= (uint64_t)rhs << 32); + return fx; + +} +struct fixed32_32 dal_fixed32_32_sub( + struct fixed32_32 lhs, + struct fixed32_32 rhs) +{ + struct fixed32_32 fx; + + ASSERT(lhs.value >= rhs.value); + fx.value = lhs.value - rhs.value; + return fx; +} + +struct fixed32_32 dal_fixed32_32_sub_int(struct fixed32_32 lhs, uint32_t rhs) +{ + struct fixed32_32 fx; + + ASSERT(lhs.value >= ((uint64_t)rhs<<32)); + fx.value = lhs.value - ((uint64_t)rhs<<32); + return fx; +} + +struct fixed32_32 dal_fixed32_32_mul( + struct fixed32_32 lhs, + struct fixed32_32 rhs) +{ + struct fixed32_32 fx; + uint64_t lhs_int = lhs.value>>32; + uint64_t lhs_frac = (uint32_t)lhs.value; + uint64_t rhs_int = rhs.value>>32; + uint64_t rhs_frac = (uint32_t)rhs.value; + uint64_t ahbh = lhs_int * rhs_int; + uint64_t ahbl = lhs_int * rhs_frac; + uint64_t albh = lhs_frac * rhs_int; + uint64_t albl = lhs_frac * rhs_frac; + + ASSERT((ahbh>>32) == 0); + + fx.value = (ahbh<<32) + ahbl + albh + (albl>>32); + return fx; + +} + +struct fixed32_32 dal_fixed32_32_mul_int(struct fixed32_32 lhs, uint32_t rhs) +{ + struct fixed32_32 fx; + uint64_t lhsi = (lhs.value>>32) * (uint64_t)rhs; + uint64_t lhsf; + + ASSERT((lhsi>>32) == 0); + lhsf = ((uint32_t)lhs.value) * (uint64_t)rhs; + ASSERT((lhsi<<32) + lhsf >= lhsf); + fx.value = (lhsi<<32) + lhsf; + return fx; +} + +struct fixed32_32 dal_fixed32_32_div( + struct fixed32_32 lhs, + struct fixed32_32 rhs) +{ + struct fixed32_32 fx; + + fx.value = u64_div(lhs.value, rhs.value); + return fx; +} + +struct fixed32_32 dal_fixed32_32_div_int(struct fixed32_32 lhs, uint32_t rhs) +{ + struct fixed32_32 fx; + + fx.value = u64_div(lhs.value, (uint64_t)rhs << 32); + return fx; +} + +struct fixed32_32 dal_fixed32_32_min( + struct fixed32_32 lhs, + struct fixed32_32 rhs) +{ + return (lhs.value < rhs.value) ? lhs : rhs; +} + +struct fixed32_32 dal_fixed32_32_max( + struct fixed32_32 lhs, + struct fixed32_32 rhs) +{ + return (lhs.value > rhs.value) ? lhs : rhs; +} + +bool dal_fixed32_32_gt(struct fixed32_32 lhs, struct fixed32_32 rhs) +{ + return lhs.value > rhs.value; +} +bool dal_fixed32_32_gt_int(struct fixed32_32 lhs, uint32_t rhs) +{ + return lhs.value > ((uint64_t)rhs<<32); +} + +bool dal_fixed32_32_lt(struct fixed32_32 lhs, struct fixed32_32 rhs) +{ + return lhs.value < rhs.value; +} + +bool dal_fixed32_32_le(struct fixed32_32 lhs, struct fixed32_32 rhs) +{ + return lhs.value <= rhs.value; +} + +bool dal_fixed32_32_lt_int(struct fixed32_32 lhs, uint32_t rhs) +{ + return lhs.value < ((uint64_t)rhs<<32); +} + +bool dal_fixed32_32_le_int(struct fixed32_32 lhs, uint32_t rhs) +{ + return lhs.value <= ((uint64_t)rhs<<32); +} + +uint32_t dal_fixed32_32_ceil(struct fixed32_32 v) +{ + ASSERT((uint32_t)v.value ? (v.value >> 32) + 1 >= 1 : true); + return (v.value>>32) + ((uint32_t)v.value ? 1 : 0); +} + +uint32_t dal_fixed32_32_floor(struct fixed32_32 v) +{ + return v.value>>32; +} + +uint32_t dal_fixed32_32_round(struct fixed32_32 v) +{ + ASSERT(v.value + (1ULL<<31) >= (1ULL<<31)); + return (v.value + (1ULL<<31))>>32; +} + +bool dal_fixed32_32_eq(struct fixed32_32 lhs, struct fixed32_32 rhs) +{ + return lhs.value == rhs.value; +} diff --git a/drivers/gpu/drm/amd/display/dc/basics/grph_object_id.c b/drivers/gpu/drm/amd/display/dc/basics/grph_object_id.c new file mode 100644 index 000000000000..9c80847d03a9 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/basics/grph_object_id.c @@ -0,0 +1,134 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "include/grph_object_id.h" + +bool dal_graphics_object_id_is_valid(struct graphics_object_id id) +{ + bool rc = true; + + switch (id.type) { + case OBJECT_TYPE_UNKNOWN: + rc = false; + break; + case OBJECT_TYPE_GPU: + case OBJECT_TYPE_ENGINE: + /* do NOT check for id.id == 0 */ + if (id.enum_id == ENUM_ID_UNKNOWN) + rc = false; + break; + default: + if (id.id == 0 || id.enum_id == ENUM_ID_UNKNOWN) + rc = false; + break; + } + + return rc; +} + +bool dal_graphics_object_id_is_equal( + struct graphics_object_id id1, + struct graphics_object_id id2) +{ + if (false == dal_graphics_object_id_is_valid(id1)) { + dm_output_to_console( + "%s: Warning: comparing invalid object 'id1'!\n", __func__); + return false; + } + + if (false == dal_graphics_object_id_is_valid(id2)) { + dm_output_to_console( + "%s: Warning: comparing invalid object 'id2'!\n", __func__); + return false; + } + + if (id1.id == id2.id && id1.enum_id == id2.enum_id + && id1.type == id2.type) + return true; + + return false; +} + +/* Based on internal data members memory layout */ +uint32_t dal_graphics_object_id_to_uint(struct graphics_object_id id) +{ + uint32_t object_id = 0; + + object_id = id.id + (id.enum_id << 0x8) + (id.type << 0xc); + return object_id; +} + +/* + * ******* get specific ID - internal safe cast into specific type ******* + */ + +enum controller_id dal_graphics_object_id_get_controller_id( + struct graphics_object_id id) +{ + if (id.type == OBJECT_TYPE_CONTROLLER) + return id.id; + return CONTROLLER_ID_UNDEFINED; +} + +enum clock_source_id dal_graphics_object_id_get_clock_source_id( + struct graphics_object_id id) +{ + if (id.type == OBJECT_TYPE_CLOCK_SOURCE) + return id.id; + return CLOCK_SOURCE_ID_UNDEFINED; +} + +enum encoder_id dal_graphics_object_id_get_encoder_id( + struct graphics_object_id id) +{ + if (id.type == OBJECT_TYPE_ENCODER) + return id.id; + return ENCODER_ID_UNKNOWN; +} + +enum connector_id dal_graphics_object_id_get_connector_id( + struct graphics_object_id id) +{ + if (id.type == OBJECT_TYPE_CONNECTOR) + return id.id; + return CONNECTOR_ID_UNKNOWN; +} + +enum audio_id dal_graphics_object_id_get_audio_id(struct graphics_object_id id) +{ + if (id.type == OBJECT_TYPE_AUDIO) + return id.id; + return AUDIO_ID_UNKNOWN; +} + +enum engine_id dal_graphics_object_id_get_engine_id( + struct graphics_object_id id) +{ + if (id.type == OBJECT_TYPE_ENGINE) + return id.id; + return ENGINE_ID_UNKNOWN; +} + diff --git a/drivers/gpu/drm/amd/display/dc/basics/log_helpers.c b/drivers/gpu/drm/amd/display/dc/basics/log_helpers.c new file mode 100644 index 000000000000..61f36a7f322b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/basics/log_helpers.c @@ -0,0 +1,100 @@ +/* + * Copyright 2012-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "core_types.h" +#include "logger.h" +#include "include/logger_interface.h" + +#define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0])) + +struct dc_signal_type_info { + enum signal_type type; + char name[MAX_NAME_LEN]; +}; + +static const struct dc_signal_type_info signal_type_info_tbl[] = { + {SIGNAL_TYPE_NONE, "NC"}, + {SIGNAL_TYPE_DVI_SINGLE_LINK, "DVI"}, + {SIGNAL_TYPE_DVI_DUAL_LINK, "DDVI"}, + {SIGNAL_TYPE_HDMI_TYPE_A, "HDMIA"}, + {SIGNAL_TYPE_LVDS, "LVDS"}, + {SIGNAL_TYPE_RGB, "VGA"}, + {SIGNAL_TYPE_DISPLAY_PORT, "DP"}, + {SIGNAL_TYPE_DISPLAY_PORT_MST, "MST"}, + {SIGNAL_TYPE_EDP, "eDP"}, + {SIGNAL_TYPE_WIRELESS, "Wireless"}, + {SIGNAL_TYPE_VIRTUAL, "Virtual"} +}; + +void dc_conn_log(struct dc_context *ctx, + const struct dc_link *link, + uint8_t *hex_data, + int hex_data_count, + enum dc_log_type event, + const char *msg, + ...) +{ + int i; + va_list args; + struct log_entry entry = { 0 }; + enum signal_type signal; + + if (link->local_sink) + signal = link->local_sink->sink_signal; + else + signal = link->connector_signal; + + if (link->type == dc_connection_mst_branch) + signal = SIGNAL_TYPE_DISPLAY_PORT_MST; + + dm_logger_open(ctx->logger, &entry, event); + + for (i = 0; i < NUM_ELEMENTS(signal_type_info_tbl); i++) + if (signal == signal_type_info_tbl[i].type) + break; + + dm_logger_append(&entry, "[%s][ConnIdx:%d] ", + signal_type_info_tbl[i].name, + link->link_index); + + va_start(args, msg); + entry.buf_offset += dm_log_to_buffer( + &entry.buf[entry.buf_offset], + LOG_MAX_LINE_SIZE - entry.buf_offset, + msg, args); + + if (entry.buf[strlen(entry.buf) - 1] == '\n') { + entry.buf[strlen(entry.buf) - 1] = '\0'; + entry.buf_offset--; + } + + if (hex_data) + for (i = 0; i < hex_data_count; i++) + dm_logger_append(&entry, "%2.2X ", hex_data[i]); + + dm_logger_append(&entry, "^\n"); + dm_logger_close(&entry); + va_end(args); +} diff --git a/drivers/gpu/drm/amd/display/dc/basics/logger.c b/drivers/gpu/drm/amd/display/dc/basics/logger.c new file mode 100644 index 000000000000..a5625a3badab --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/basics/logger.c @@ -0,0 +1,457 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#include "dm_services.h" +#include "include/logger_interface.h" +#include "logger.h" + + +#define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0])) + +static const struct dc_log_type_info log_type_info_tbl[] = { + {LOG_ERROR, "Error"}, + {LOG_WARNING, "Warning"}, + {LOG_DC, "DC_Interface"}, + {LOG_SURFACE, "Surface"}, + {LOG_HW_HOTPLUG, "HW_Hotplug"}, + {LOG_HW_LINK_TRAINING, "HW_LKTN"}, + {LOG_HW_SET_MODE, "HW_Mode"}, + {LOG_HW_RESUME_S3, "HW_Resume"}, + {LOG_HW_AUDIO, "HW_Audio"}, + {LOG_HW_HPD_IRQ, "HW_HPDIRQ"}, + {LOG_MST, "MST"}, + {LOG_SCALER, "Scaler"}, + {LOG_BIOS, "BIOS"}, + {LOG_BANDWIDTH_CALCS, "BWCalcs"}, + {LOG_BANDWIDTH_VALIDATION, "BWValidation"}, + {LOG_I2C_AUX, "I2C_AUX"}, + {LOG_SYNC, "Sync"}, + {LOG_BACKLIGHT, "Backlight"}, + {LOG_FEATURE_OVERRIDE, "Override"}, + {LOG_DETECTION_EDID_PARSER, "Edid"}, + {LOG_DETECTION_DP_CAPS, "DP_Caps"}, + {LOG_RESOURCE, "Resource"}, + {LOG_DML, "DML"}, + {LOG_EVENT_MODE_SET, "Mode"}, + {LOG_EVENT_DETECTION, "Detect"}, + {LOG_EVENT_LINK_TRAINING, "LKTN"}, + {LOG_EVENT_LINK_LOSS, "LinkLoss"}, + {LOG_EVENT_UNDERFLOW, "Underflow"}, + {LOG_IF_TRACE, "InterfaceTrace"} +}; + + +#define DC_DEFAULT_LOG_MASK ((1 << LOG_ERROR) | \ + (1 << LOG_WARNING) | \ + (1 << LOG_EVENT_MODE_SET) | \ + (1 << LOG_EVENT_DETECTION) | \ + (1 << LOG_EVENT_LINK_TRAINING) | \ + (1 << LOG_EVENT_LINK_LOSS) | \ + (1 << LOG_EVENT_UNDERFLOW) | \ + (1 << LOG_RESOURCE) | \ + (1 << LOG_FEATURE_OVERRIDE) | \ + (1 << LOG_DETECTION_EDID_PARSER) | \ + (1 << LOG_DC) | \ + (1 << LOG_HW_HOTPLUG) | \ + (1 << LOG_HW_SET_MODE) | \ + (1 << LOG_HW_RESUME_S3) | \ + (1 << LOG_HW_HPD_IRQ) | \ + (1 << LOG_SYNC) | \ + (1 << LOG_BANDWIDTH_VALIDATION) | \ + (1 << LOG_MST) | \ + (1 << LOG_BIOS) | \ + (1 << LOG_DETECTION_EDID_PARSER) | \ + (1 << LOG_DETECTION_DP_CAPS) | \ + (1 << LOG_BACKLIGHT)) | \ + (1 << LOG_I2C_AUX) | \ + (1 << LOG_IF_TRACE) /* | \ + (1 << LOG_SURFACE) | \ + (1 << LOG_SCALER) | \ + (1 << LOG_DML) | \ + (1 << LOG_HW_LINK_TRAINING) | \ + (1 << LOG_HW_AUDIO)| \ + (1 << LOG_BANDWIDTH_CALCS)*/ + +/* ----------- Object init and destruction ----------- */ +static bool construct(struct dc_context *ctx, struct dal_logger *logger) +{ + /* malloc buffer and init offsets */ + logger->log_buffer_size = DAL_LOGGER_BUFFER_MAX_SIZE; + logger->log_buffer = (char *)dm_alloc(logger->log_buffer_size * + sizeof(char)); + + if (!logger->log_buffer) + return false; + + /* Initialize both offsets to start of buffer (empty) */ + logger->buffer_read_offset = 0; + logger->buffer_write_offset = 0; + + logger->write_wrap_count = 0; + logger->read_wrap_count = 0; + logger->open_count = 0; + + logger->flags.bits.ENABLE_CONSOLE = 1; + logger->flags.bits.ENABLE_BUFFER = 0; + + logger->ctx = ctx; + + logger->mask = DC_DEFAULT_LOG_MASK; + + return true; +} + +static void destruct(struct dal_logger *logger) +{ + if (logger->log_buffer) { + dm_free(logger->log_buffer); + logger->log_buffer = NULL; + } +} + +struct dal_logger *dal_logger_create(struct dc_context *ctx) +{ + /* malloc struct */ + struct dal_logger *logger = dm_alloc(sizeof(struct dal_logger)); + + if (!logger) + return NULL; + if (!construct(ctx, logger)) { + dm_free(logger); + return NULL; + } + + return logger; +} + +uint32_t dal_logger_destroy(struct dal_logger **logger) +{ + if (logger == NULL || *logger == NULL) + return 1; + destruct(*logger); + dm_free(*logger); + *logger = NULL; + + return 0; +} + +/* ------------------------------------------------------------------------ */ + + +static bool dal_logger_should_log( + struct dal_logger *logger, + enum dc_log_type log_type) +{ + if (logger->mask & (1 << log_type)) + return true; + + return false; +} + +static void log_to_debug_console(struct log_entry *entry) +{ + struct dal_logger *logger = entry->logger; + + if (logger->flags.bits.ENABLE_CONSOLE == 0) + return; + + if (entry->buf_offset) { + switch (entry->type) { + case LOG_ERROR: + dm_error("%s", entry->buf); + break; + default: + dm_output_to_console("%s", entry->buf); + break; + } + } +} + +/* Print everything unread existing in log_buffer to debug console*/ +static void flush_to_debug_console(struct dal_logger *logger) +{ + int i = logger->buffer_read_offset; + char *string_start = &logger->log_buffer[i]; + + dm_output_to_console( + "---------------- FLUSHING LOG BUFFER ----------------\n"); + while (i < logger->buffer_write_offset) { + + if (logger->log_buffer[i] == '\0') { + dm_output_to_console("%s", string_start); + string_start = (char *)logger->log_buffer + i + 1; + } + i++; + } + dm_output_to_console( + "-------------- END FLUSHING LOG BUFFER --------------\n\n"); +} + +static void log_to_internal_buffer(struct log_entry *entry) +{ + + uint32_t size = entry->buf_offset; + struct dal_logger *logger = entry->logger; + + if (logger->flags.bits.ENABLE_BUFFER == 0) + return; + + if (logger->log_buffer == NULL) + return; + + if (size > 0 && size < logger->log_buffer_size) { + + int total_free_space = 0; + int space_before_wrap = 0; + + if (logger->buffer_write_offset > logger->buffer_read_offset) { + total_free_space = logger->log_buffer_size - + logger->buffer_write_offset + + logger->buffer_read_offset; + space_before_wrap = logger->log_buffer_size - + logger->buffer_write_offset; + } else if (logger->buffer_write_offset < + logger->buffer_read_offset) { + total_free_space = logger->log_buffer_size - + logger->buffer_read_offset + + logger->buffer_write_offset; + space_before_wrap = total_free_space; + } else if (logger->write_wrap_count != + logger->read_wrap_count) { + /* Buffer is completely full already */ + total_free_space = 0; + space_before_wrap = 0; + } else { + /* Buffer is empty, start writing at beginning */ + total_free_space = logger->log_buffer_size; + space_before_wrap = logger->log_buffer_size; + logger->buffer_write_offset = 0; + logger->buffer_read_offset = 0; + } + + if (space_before_wrap > size) { + /* No wrap around, copy 'size' bytes + * from 'entry->buf' to 'log_buffer' + */ + memmove(logger->log_buffer + + logger->buffer_write_offset, + entry->buf, size); + logger->buffer_write_offset += size; + + } else if (total_free_space > size) { + /* We have enough room without flushing, + * but need to wrap around */ + + int space_after_wrap = total_free_space - + space_before_wrap; + + memmove(logger->log_buffer + + logger->buffer_write_offset, + entry->buf, space_before_wrap); + memmove(logger->log_buffer, entry->buf + + space_before_wrap, space_after_wrap); + + logger->buffer_write_offset = space_after_wrap; + logger->write_wrap_count++; + + } else { + /* Not enough room remaining, we should flush + * existing logs */ + + /* Flush existing unread logs to console */ + flush_to_debug_console(logger); + + /* Start writing to beginning of buffer */ + memmove(logger->log_buffer, entry->buf, size); + logger->buffer_write_offset = size; + logger->buffer_read_offset = 0; + } + + } +} + +static void log_heading(struct log_entry *entry) +{ + int j; + + for (j = 0; j < NUM_ELEMENTS(log_type_info_tbl); j++) { + + const struct dc_log_type_info *info = &log_type_info_tbl[j]; + + if (info->type == entry->type) + dm_logger_append(entry, "[%s]\t", info->name); + } +} + +static void append_entry( + struct log_entry *entry, + char *buffer, + uint32_t buf_size) +{ + if (!entry->buf || + entry->buf_offset + buf_size > entry->max_buf_bytes + ) { + BREAK_TO_DEBUGGER(); + return; + } + + /* Todo: check if off by 1 byte due to \0 anywhere */ + memmove(entry->buf + entry->buf_offset, buffer, buf_size); + entry->buf_offset += buf_size; +} + +/* ------------------------------------------------------------------------ */ + +/* Warning: Be careful that 'msg' is null terminated and the total size is + * less than DAL_LOGGER_BUFFER_MAX_LOG_LINE_SIZE (256) including '\0' + */ +void dm_logger_write( + struct dal_logger *logger, + enum dc_log_type log_type, + const char *msg, + ...) +{ + if (logger && dal_logger_should_log(logger, log_type)) { + uint32_t size; + va_list args; + char buffer[LOG_MAX_LINE_SIZE]; + struct log_entry entry; + + va_start(args, msg); + + entry.logger = logger; + + entry.buf = buffer; + + entry.buf_offset = 0; + entry.max_buf_bytes = DAL_LOGGER_BUFFER_MAX_SIZE * sizeof(char); + + entry.type = log_type; + + log_heading(&entry); + + size = dm_log_to_buffer( + buffer, LOG_MAX_LINE_SIZE, msg, args); + + entry.buf_offset += size; + + /* --Flush log_entry buffer-- */ + /* print to kernel console */ + log_to_debug_console(&entry); + /* log internally for dsat */ + log_to_internal_buffer(&entry); + + va_end(args); + } +} + +/* Same as dm_logger_write, except without open() and close(), which must + * be done separately. + */ +void dm_logger_append( + struct log_entry *entry, + const char *msg, + ...) +{ + struct dal_logger *logger; + + if (!entry) { + BREAK_TO_DEBUGGER(); + return; + } + + logger = entry->logger; + + if (logger && logger->open_count > 0 && + dal_logger_should_log(logger, entry->type)) { + + uint32_t size; + va_list args; + char buffer[LOG_MAX_LINE_SIZE]; + + va_start(args, msg); + + size = dm_log_to_buffer( + buffer, LOG_MAX_LINE_SIZE, msg, args); + + if (size < LOG_MAX_LINE_SIZE - 1) { + append_entry(entry, buffer, size); + } else { + append_entry(entry, "LOG_ERROR, line too long\n", 27); + } + + va_end(args); + } +} + +void dm_logger_open( + struct dal_logger *logger, + struct log_entry *entry, /* out */ + enum dc_log_type log_type) +{ + if (!entry) { + BREAK_TO_DEBUGGER(); + return; + } + + entry->type = log_type; + entry->logger = logger; + + entry->buf = dm_alloc(DAL_LOGGER_BUFFER_MAX_SIZE * sizeof(char)); + + entry->buf_offset = 0; + entry->max_buf_bytes = DAL_LOGGER_BUFFER_MAX_SIZE * sizeof(char); + + logger->open_count++; + + log_heading(entry); +} + +void dm_logger_close(struct log_entry *entry) +{ + struct dal_logger *logger = entry->logger; + + if (logger && logger->open_count > 0) { + logger->open_count--; + } else { + BREAK_TO_DEBUGGER(); + goto cleanup; + } + + /* --Flush log_entry buffer-- */ + /* print to kernel console */ + log_to_debug_console(entry); + /* log internally for dsat */ + log_to_internal_buffer(entry); + + /* TODO: Write end heading */ + +cleanup: + if (entry->buf) { + dm_free(entry->buf); + entry->buf = NULL; + entry->buf_offset = 0; + entry->max_buf_bytes = 0; + } +} diff --git a/drivers/gpu/drm/amd/display/dc/basics/logger.h b/drivers/gpu/drm/amd/display/dc/basics/logger.h new file mode 100644 index 000000000000..2f7a5df4c811 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/basics/logger.h @@ -0,0 +1,67 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_LOGGER_H__ +#define __DAL_LOGGER_H__ + +/* Structure for keeping track of offsets, buffer, etc */ + +#define DAL_LOGGER_BUFFER_MAX_SIZE 2048 + +/*Connectivity log needs to output EDID, which needs at lease 256x3 bytes, + * change log line size to 896 to meet the request. + */ +#define LOG_MAX_LINE_SIZE 896 + +#include "include/logger_types.h" + +struct dal_logger { + + /* How far into the circular buffer has been read by dsat + * Read offset should never cross write offset. Write \0's to + * read data just to be sure? + */ + uint32_t buffer_read_offset; + + /* How far into the circular buffer we have written + * Write offset should never cross read offset + */ + uint32_t buffer_write_offset; + + uint32_t write_wrap_count; + uint32_t read_wrap_count; + + uint32_t open_count; + + char *log_buffer; /* Pointer to malloc'ed buffer */ + uint32_t log_buffer_size; /* Size of circular buffer */ + + uint32_t mask; /*array of masks for major elements*/ + + union logger_flags flags; + struct dc_context *ctx; +}; + +#endif /* __DAL_LOGGER_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/basics/register_logger.c b/drivers/gpu/drm/amd/display/dc/basics/register_logger.c new file mode 100644 index 000000000000..b8d57d919fe4 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/basics/register_logger.c @@ -0,0 +1,197 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "include/dal_types.h" +#include "include/logger_interface.h" +#include "logger.h" + +/****************************************************************************** + * Register Logger. + * A facility to create register R/W logs. + * Currently used for DAL Test. + *****************************************************************************/ + +/****************************************************************************** + * Private structures + *****************************************************************************/ +struct dal_reg_dump_stack_location { + const char *current_caller_func; + long current_pid; + long current_tgid; + uint32_t rw_count;/* register access counter for current function. */ +}; + +/* This the maximum number of nested calls to the 'reg_dump' facility. */ +#define DAL_REG_DUMP_STACK_MAX_SIZE 32 + +struct dal_reg_dump_stack { + int32_t stack_pointer; + struct dal_reg_dump_stack_location + stack_locations[DAL_REG_DUMP_STACK_MAX_SIZE]; + uint32_t total_rw_count; /* Total count for *all* functions. */ +}; + +static struct dal_reg_dump_stack reg_dump_stack = {0}; + +/****************************************************************************** + * Private functions + *****************************************************************************/ + +/* Check if current process is the one which requested register dump. + * The reason for the check: + * mmCRTC_STATUS_FRAME_COUNT is accessed by dal_controller_get_vblank_counter(). + * Which runs all the time when at least one display is connected. + * (Triggered by drm_mode_page_flip_ioctl()). */ +static bool is_reg_dump_process(void) +{ + uint32_t i; + + /* walk the list of our processes */ + for (i = 0; i < reg_dump_stack.stack_pointer; i++) { + struct dal_reg_dump_stack_location *stack_location + = ®_dump_stack.stack_locations[i]; + + if (stack_location->current_pid == dm_get_pid() + && stack_location->current_tgid == dm_get_tgid()) + return true; + } + + return false; +} + +static bool dal_reg_dump_stack_is_empty(void) +{ + if (reg_dump_stack.stack_pointer <= 0) + return true; + else + return false; +} + +static struct dal_reg_dump_stack_location *dal_reg_dump_stack_push(void) +{ + struct dal_reg_dump_stack_location *current_location = NULL; + + if (reg_dump_stack.stack_pointer >= DAL_REG_DUMP_STACK_MAX_SIZE) { + /* stack is full */ + dm_output_to_console("[REG_DUMP]: %s: stack is full!\n", + __func__); + } else { + current_location = + ®_dump_stack.stack_locations[reg_dump_stack.stack_pointer]; + ++reg_dump_stack.stack_pointer; + } + + return current_location; +} + +static struct dal_reg_dump_stack_location *dal_reg_dump_stack_pop(void) +{ + struct dal_reg_dump_stack_location *current_location = NULL; + + if (dal_reg_dump_stack_is_empty()) { + /* stack is empty */ + dm_output_to_console("[REG_DUMP]: %s: stack is empty!\n", + __func__); + } else { + --reg_dump_stack.stack_pointer; + current_location = + ®_dump_stack.stack_locations[reg_dump_stack.stack_pointer]; + } + + return current_location; +} + +/****************************************************************************** + * Public functions + *****************************************************************************/ + +void dal_reg_logger_push(const char *caller_func) +{ + struct dal_reg_dump_stack_location *free_stack_location; + + free_stack_location = dal_reg_dump_stack_push(); + + if (NULL == free_stack_location) + return; + + memset(free_stack_location, 0, sizeof(*free_stack_location)); + + free_stack_location->current_caller_func = caller_func; + free_stack_location->current_pid = dm_get_pid(); + free_stack_location->current_tgid = dm_get_tgid(); + + dm_output_to_console("[REG_DUMP]:%s - start (pid:%ld, tgid:%ld)\n", + caller_func, + free_stack_location->current_pid, + free_stack_location->current_tgid); +} + +void dal_reg_logger_pop(void) +{ + struct dal_reg_dump_stack_location *top_stack_location; + + top_stack_location = dal_reg_dump_stack_pop(); + + if (NULL == top_stack_location) { + dm_output_to_console("[REG_DUMP]:%s - Stack is Empty!\n", + __func__); + return; + } + + dm_output_to_console( + "[REG_DUMP]:%s - end."\ + " Reg R/W Count: Total=%d Function=%d. (pid:%ld, tgid:%ld)\n", + top_stack_location->current_caller_func, + reg_dump_stack.total_rw_count, + top_stack_location->rw_count, + dm_get_pid(), + dm_get_tgid()); + + memset(top_stack_location, 0, sizeof(*top_stack_location)); +} + +void dal_reg_logger_rw_count_increment(void) +{ + ++reg_dump_stack.total_rw_count; + + ++reg_dump_stack.stack_locations + [reg_dump_stack.stack_pointer - 1].rw_count; +} + +bool dal_reg_logger_should_dump_register(void) +{ + if (true == dal_reg_dump_stack_is_empty()) + return false; + + if (false == is_reg_dump_process()) + return false; + + return true; +} + +/****************************************************************************** + * End of File. + *****************************************************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/basics/signal_types.c b/drivers/gpu/drm/amd/display/dc/basics/signal_types.c new file mode 100644 index 000000000000..44447e07803a --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/basics/signal_types.c @@ -0,0 +1,116 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "include/signal_types.h" + +bool dc_is_hdmi_signal(enum signal_type signal) +{ + return (signal == SIGNAL_TYPE_HDMI_TYPE_A); +} + +bool dc_is_dp_sst_signal(enum signal_type signal) +{ + return (signal == SIGNAL_TYPE_DISPLAY_PORT || + signal == SIGNAL_TYPE_EDP); +} + +bool dc_is_dp_signal(enum signal_type signal) +{ + return (signal == SIGNAL_TYPE_DISPLAY_PORT || + signal == SIGNAL_TYPE_EDP || + signal == SIGNAL_TYPE_DISPLAY_PORT_MST); +} + +bool dc_is_dp_external_signal(enum signal_type signal) +{ + return (signal == SIGNAL_TYPE_DISPLAY_PORT || + signal == SIGNAL_TYPE_DISPLAY_PORT_MST); +} + +bool dc_is_analog_signal(enum signal_type signal) +{ + switch (signal) { + case SIGNAL_TYPE_RGB: + return true; + break; + default: + return false; + } +} + +bool dc_is_embedded_signal(enum signal_type signal) +{ + return (signal == SIGNAL_TYPE_EDP || signal == SIGNAL_TYPE_LVDS); +} + +bool dc_is_dvi_signal(enum signal_type signal) +{ + switch (signal) { + case SIGNAL_TYPE_DVI_SINGLE_LINK: + case SIGNAL_TYPE_DVI_DUAL_LINK: + return true; + break; + default: + return false; + } +} + +bool dc_is_dvi_single_link_signal(enum signal_type signal) +{ + return (signal == SIGNAL_TYPE_DVI_SINGLE_LINK); +} + +bool dc_is_dual_link_signal(enum signal_type signal) +{ + return (signal == SIGNAL_TYPE_DVI_DUAL_LINK); +} + +bool dc_is_audio_capable_signal(enum signal_type signal) +{ + return (signal == SIGNAL_TYPE_DISPLAY_PORT || + signal == SIGNAL_TYPE_DISPLAY_PORT_MST || + dc_is_hdmi_signal(signal) || + signal == SIGNAL_TYPE_WIRELESS); +} + +/* + * @brief + * Returns whether the signal is compatible + * with other digital encoder signal types. + * This is true for DVI, LVDS, and HDMI signal types. + */ +bool dc_is_digital_encoder_compatible_signal(enum signal_type signal) +{ + switch (signal) { + case SIGNAL_TYPE_DVI_SINGLE_LINK: + case SIGNAL_TYPE_DVI_DUAL_LINK: + case SIGNAL_TYPE_HDMI_TYPE_A: + case SIGNAL_TYPE_LVDS: + return true; + default: + return false; + } +} diff --git a/drivers/gpu/drm/amd/display/dc/basics/vector.c b/drivers/gpu/drm/amd/display/dc/basics/vector.c new file mode 100644 index 000000000000..bb72a1857160 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/basics/vector.c @@ -0,0 +1,307 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "include/vector.h" + +bool dal_vector_construct( + struct vector *vector, + struct dc_context *ctx, + uint32_t capacity, + uint32_t struct_size) +{ + vector->container = NULL; + + if (!struct_size || !capacity) { + /* Container must be non-zero size*/ + BREAK_TO_DEBUGGER(); + return false; + } + + vector->container = dm_alloc(struct_size * capacity); + if (vector->container == NULL) + return false; + vector->capacity = capacity; + vector->struct_size = struct_size; + vector->count = 0; + vector->ctx = ctx; + return true; +} + +bool dal_vector_presized_costruct( + struct vector *vector, + struct dc_context *ctx, + uint32_t count, + void *initial_value, + uint32_t struct_size) +{ + uint32_t i; + + vector->container = NULL; + + if (!struct_size || !count) { + /* Container must be non-zero size*/ + BREAK_TO_DEBUGGER(); + return false; + } + + vector->container = dm_alloc(struct_size * count); + + if (vector->container == NULL) + return false; + + /* If caller didn't supply initial value then the default + * of all zeros is expected, which is exactly what dal_alloc() + * initialises the memory to. */ + if (NULL != initial_value) { + for (i = 0; i < count; ++i) + memmove( + vector->container + i * struct_size, + initial_value, + struct_size); + } + + vector->capacity = count; + vector->struct_size = struct_size; + vector->count = count; + return true; +} + +struct vector *dal_vector_presized_create( + struct dc_context *ctx, + uint32_t size, + void *initial_value, + uint32_t struct_size) +{ + struct vector *vector = dm_alloc(sizeof(struct vector)); + + if (vector == NULL) + return NULL; + + if (dal_vector_presized_costruct( + vector, ctx, size, initial_value, struct_size)) + return vector; + + BREAK_TO_DEBUGGER(); + dm_free(vector); + return NULL; +} + +struct vector *dal_vector_create( + struct dc_context *ctx, + uint32_t capacity, + uint32_t struct_size) +{ + struct vector *vector = dm_alloc(sizeof(struct vector)); + + if (vector == NULL) + return NULL; + + if (dal_vector_construct(vector, ctx, capacity, struct_size)) + return vector; + + BREAK_TO_DEBUGGER(); + dm_free(vector); + return NULL; +} + +void dal_vector_destruct( + struct vector *vector) +{ + if (vector->container != NULL) + dm_free(vector->container); + vector->count = 0; + vector->capacity = 0; +} + +void dal_vector_destroy( + struct vector **vector) +{ + if (vector == NULL || *vector == NULL) + return; + dal_vector_destruct(*vector); + dm_free(*vector); + *vector = NULL; +} + +uint32_t dal_vector_get_count( + const struct vector *vector) +{ + return vector->count; +} + +void *dal_vector_at_index( + const struct vector *vector, + uint32_t index) +{ + if (vector->container == NULL || index >= vector->count) + return NULL; + return vector->container + (index * vector->struct_size); +} + +bool dal_vector_remove_at_index( + struct vector *vector, + uint32_t index) +{ + if (index >= vector->count) + return false; + + if (index != vector->count - 1) + memmove( + vector->container + (index * vector->struct_size), + vector->container + ((index + 1) * vector->struct_size), + (vector->count - index - 1) * vector->struct_size); + vector->count -= 1; + + return true; +} + +void dal_vector_set_at_index( + const struct vector *vector, + const void *what, + uint32_t index) +{ + void *where = dal_vector_at_index(vector, index); + + if (!where) { + BREAK_TO_DEBUGGER(); + return; + } + memmove( + where, + what, + vector->struct_size); +} + +static inline uint32_t calc_increased_capacity( + uint32_t old_capacity) +{ + return old_capacity * 2; +} + +bool dal_vector_insert_at( + struct vector *vector, + const void *what, + uint32_t position) +{ + uint8_t *insert_address; + + if (vector->count == vector->capacity) { + if (!dal_vector_reserve( + vector, + calc_increased_capacity(vector->capacity))) + return false; + } + + insert_address = vector->container + (vector->struct_size * position); + + if (vector->count && position < vector->count) + memmove( + insert_address + vector->struct_size, + insert_address, + vector->struct_size * (vector->count - position)); + + memmove( + insert_address, + what, + vector->struct_size); + + vector->count++; + + return true; +} + +bool dal_vector_append( + struct vector *vector, + const void *item) +{ + return dal_vector_insert_at(vector, item, vector->count); +} + +struct vector *dal_vector_clone( + const struct vector *vector) +{ + struct vector *vec_cloned; + uint32_t count; + + /* create new vector */ + count = dal_vector_get_count(vector); + + if (count == 0) + /* when count is 0 we still want to create clone of the vector + */ + vec_cloned = dal_vector_create( + vector->ctx, + vector->capacity, + vector->struct_size); + else + /* Call "presized create" version, independently of how the + * original vector was created. + * The owner of original vector must know how to treat the new + * vector - as "presized" or as "regular". + * But from vector point of view it doesn't matter. */ + vec_cloned = dal_vector_presized_create(vector->ctx, count, + NULL,/* no initial value */ + vector->struct_size); + + if (NULL == vec_cloned) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + /* copy vector's data */ + memmove(vec_cloned->container, vector->container, + vec_cloned->struct_size * vec_cloned->capacity); + + return vec_cloned; +} + +uint32_t dal_vector_capacity(const struct vector *vector) +{ + return vector->capacity; +} + +bool dal_vector_reserve(struct vector *vector, uint32_t capacity) +{ + void *new_container; + + if (capacity <= vector->capacity) + return true; + + new_container = dm_realloc(vector->container, capacity * vector->struct_size); + + if (new_container) { + vector->container = new_container; + vector->capacity = capacity; + return true; + } + + return false; +} + +void dal_vector_clear(struct vector *vector) +{ + vector->count = 0; +} diff --git a/drivers/gpu/drm/amd/display/dc/bios/Makefile b/drivers/gpu/drm/amd/display/dc/bios/Makefile new file mode 100644 index 000000000000..9ba677f0ff01 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/Makefile @@ -0,0 +1,24 @@ +# +# Makefile for the 'bios' sub-component of DAL. +# It provides the parsing and executing controls for atom bios image. + +BIOS = bios_parser.o bios_parser_interface.o bios_parser_helper.o command_table.o command_table_helper.o + +AMD_DAL_BIOS = $(addprefix $(AMDDALPATH)/dc/bios/,$(BIOS)) + +AMD_DISPLAY_FILES += $(AMD_DAL_BIOS) + +############################################################################### +# DCE 8x +############################################################################### +# All DCE8.x are derived from DCE8.0, so 8.0 MUST be defined if ANY of +# DCE8.x is compiled. +AMD_DISPLAY_FILES += $(AMDDALPATH)/dc/bios/dce80/command_table_helper_dce80.o + +############################################################################### +# DCE 11x +############################################################################### +AMD_DISPLAY_FILES += $(AMDDALPATH)/dc/bios/dce110/command_table_helper_dce110.o + +ccflags-y += -DLATEST_ATOM_BIOS_SUPPORT +AMD_DISPLAY_FILES += $(AMDDALPATH)/dc/bios/dce112/command_table_helper_dce112.o diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c new file mode 100644 index 000000000000..ebd2e419f8f2 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c @@ -0,0 +1,4220 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "atom.h" + +#include "dc_bios_types.h" +#include "include/gpio_service_interface.h" +#include "include/grph_object_ctrl_defs.h" +#include "include/bios_parser_interface.h" +#include "include/i2caux_interface.h" +#include "include/logger_interface.h" + +#include "command_table.h" +#include "bios_parser_helper.h" +#include "command_table_helper.h" +#include "bios_parser.h" +#include "bios_parser_types_internal.h" +#include "bios_parser_interface.h" + +/* TODO remove - only needed for default i2c speed */ +#include "dc.h" + +#define THREE_PERCENT_OF_10000 300 + +#define LAST_RECORD_TYPE 0xff + +/* GUID to validate external display connection info table (aka OPM module) */ +static const uint8_t ext_display_connection_guid[NUMBER_OF_UCHAR_FOR_GUID] = { + 0x91, 0x6E, 0x57, 0x09, + 0x3F, 0x6D, 0xD2, 0x11, + 0x39, 0x8E, 0x00, 0xA0, + 0xC9, 0x69, 0x72, 0x3B}; + +#define DATA_TABLES(table) (bp->master_data_tbl->ListOfDataTables.table) + +static enum object_type object_type_from_bios_object_id( + uint32_t bios_object_id); +static struct graphics_object_id object_id_from_bios_object_id( + uint32_t bios_object_id); +static enum object_enum_id enum_id_from_bios_object_id(uint32_t bios_object_id); +static enum encoder_id encoder_id_from_bios_object_id(uint32_t bios_object_id); +static enum connector_id connector_id_from_bios_object_id( + uint32_t bios_object_id); +static uint32_t id_from_bios_object_id(enum object_type type, + uint32_t bios_object_id); +static uint32_t gpu_id_from_bios_object_id(uint32_t bios_object_id); +static enum generic_id generic_id_from_bios_object_id(uint32_t bios_object_id); +static void get_atom_data_table_revision( + ATOM_COMMON_TABLE_HEADER *atom_data_tbl, + struct atom_data_revision *tbl_revision); +static uint32_t get_dst_number_from_object(struct bios_parser *bp, + ATOM_OBJECT *object); +static uint32_t get_src_obj_list(struct bios_parser *bp, ATOM_OBJECT *object, + uint16_t **id_list); +static uint32_t get_dest_obj_list(struct bios_parser *bp, + ATOM_OBJECT *object, uint16_t **id_list); +static ATOM_OBJECT *get_bios_object(struct bios_parser *bp, + struct graphics_object_id id); +static enum bp_result get_gpio_i2c_info(struct bios_parser *bp, + ATOM_I2C_RECORD *record, + struct graphics_object_i2c_info *info); +static ATOM_HPD_INT_RECORD *get_hpd_record(struct bios_parser *bp, + ATOM_OBJECT *object); +static struct device_id device_type_from_device_id(uint16_t device_id); +static uint32_t signal_to_ss_id(enum as_signal_type signal); +static uint32_t get_support_mask_for_device_id(struct device_id device_id); +static ATOM_ENCODER_CAP_RECORD *get_encoder_cap_record( + struct bios_parser *bp, + ATOM_OBJECT *object); + +#define BIOS_IMAGE_SIZE_OFFSET 2 +#define BIOS_IMAGE_SIZE_UNIT 512 + +/*****************************************************************************/ +static bool bios_parser_construct( + struct bios_parser *bp, + struct bp_init_data *init, + enum dce_version dce_version); + +static uint8_t bios_parser_get_connectors_number( + struct dc_bios *dcb); + +static enum bp_result bios_parser_get_embedded_panel_info( + struct dc_bios *dcb, + struct embedded_panel_info *info); + +/*****************************************************************************/ + +struct dc_bios *bios_parser_create( + struct bp_init_data *init, + enum dce_version dce_version) +{ + struct bios_parser *bp = NULL; + + bp = dm_alloc(sizeof(struct bios_parser)); + if (!bp) + return NULL; + + if (bios_parser_construct(bp, init, dce_version)) + return &bp->base; + + dm_free(bp); + BREAK_TO_DEBUGGER(); + return NULL; +} + +static void destruct(struct bios_parser *bp) +{ + if (bp->base.bios_local_image) + dm_free(bp->base.bios_local_image); + + if (bp->base.integrated_info) + dm_free(bp->base.integrated_info); +} + +static void bios_parser_destroy(struct dc_bios **dcb) +{ + struct bios_parser *bp = BP_FROM_DCB(*dcb); + + if (!bp) { + BREAK_TO_DEBUGGER(); + return; + } + + destruct(bp); + + dm_free(bp); + *dcb = NULL; +} + +static uint8_t get_number_of_objects(struct bios_parser *bp, uint32_t offset) +{ + ATOM_OBJECT_TABLE *table; + + uint32_t object_table_offset = bp->object_info_tbl_offset + offset; + + table = GET_IMAGE(ATOM_OBJECT_TABLE, object_table_offset); + + if (!table) + return 0; + else + return table->ucNumberOfObjects; +} + +static uint8_t bios_parser_get_connectors_number(struct dc_bios *dcb) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + return get_number_of_objects(bp, + le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset)); +} + +static struct graphics_object_id bios_parser_get_encoder_id( + struct dc_bios *dcb, + uint32_t i) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + struct graphics_object_id object_id = dal_graphics_object_id_init( + 0, ENUM_ID_UNKNOWN, OBJECT_TYPE_UNKNOWN); + + uint32_t encoder_table_offset = bp->object_info_tbl_offset + + le16_to_cpu(bp->object_info_tbl.v1_1->usEncoderObjectTableOffset); + + ATOM_OBJECT_TABLE *tbl = + GET_IMAGE(ATOM_OBJECT_TABLE, encoder_table_offset); + + if (tbl && tbl->ucNumberOfObjects > i) { + const uint16_t id = le16_to_cpu(tbl->asObjects[i].usObjectID); + + object_id = object_id_from_bios_object_id(id); + } + + return object_id; +} + +static struct graphics_object_id bios_parser_get_connector_id( + struct dc_bios *dcb, + uint8_t i) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + struct graphics_object_id object_id = dal_graphics_object_id_init( + 0, ENUM_ID_UNKNOWN, OBJECT_TYPE_UNKNOWN); + + uint32_t connector_table_offset = bp->object_info_tbl_offset + + le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset); + + ATOM_OBJECT_TABLE *tbl = + GET_IMAGE(ATOM_OBJECT_TABLE, connector_table_offset); + + if (tbl && tbl->ucNumberOfObjects > i) { + const uint16_t id = le16_to_cpu(tbl->asObjects[i].usObjectID); + + object_id = object_id_from_bios_object_id(id); + } + + return object_id; +} + +static uint32_t bios_parser_get_dst_number(struct dc_bios *dcb, + struct graphics_object_id id) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + ATOM_OBJECT *object = get_bios_object(bp, id); + + return get_dst_number_from_object(bp, object); +} + +static enum bp_result bios_parser_get_src_obj(struct dc_bios *dcb, + struct graphics_object_id object_id, uint32_t index, + struct graphics_object_id *src_object_id) +{ + uint32_t number; + uint16_t *id; + ATOM_OBJECT *object; + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!src_object_id) + return BP_RESULT_BADINPUT; + + object = get_bios_object(bp, object_id); + + if (!object) { + BREAK_TO_DEBUGGER(); /* Invalid object id */ + return BP_RESULT_BADINPUT; + } + + number = get_src_obj_list(bp, object, &id); + + if (number <= index) + return BP_RESULT_BADINPUT; + + *src_object_id = object_id_from_bios_object_id(id[index]); + + return BP_RESULT_OK; +} + +static enum bp_result bios_parser_get_dst_obj(struct dc_bios *dcb, + struct graphics_object_id object_id, uint32_t index, + struct graphics_object_id *dest_object_id) +{ + uint32_t number; + uint16_t *id; + ATOM_OBJECT *object; + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!dest_object_id) + return BP_RESULT_BADINPUT; + + object = get_bios_object(bp, object_id); + + number = get_dest_obj_list(bp, object, &id); + + if (number <= index) + return BP_RESULT_BADINPUT; + + *dest_object_id = object_id_from_bios_object_id(id[index]); + + return BP_RESULT_OK; +} + +static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb, + struct graphics_object_id id, + struct graphics_object_i2c_info *info) +{ + uint32_t offset; + ATOM_OBJECT *object; + ATOM_COMMON_RECORD_HEADER *header; + ATOM_I2C_RECORD *record; + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!info) + return BP_RESULT_BADINPUT; + + object = get_bios_object(bp, id); + + if (!object) + return BP_RESULT_BADINPUT; + + offset = le16_to_cpu(object->usRecordOffset) + + bp->object_info_tbl_offset; + + for (;;) { + header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset); + + if (!header) + return BP_RESULT_BADBIOSTABLE; + + if (LAST_RECORD_TYPE == header->ucRecordType || + !header->ucRecordSize) + break; + + if (ATOM_I2C_RECORD_TYPE == header->ucRecordType + && sizeof(ATOM_I2C_RECORD) <= header->ucRecordSize) { + /* get the I2C info */ + record = (ATOM_I2C_RECORD *) header; + + if (get_gpio_i2c_info(bp, record, info) == BP_RESULT_OK) + return BP_RESULT_OK; + } + + offset += header->ucRecordSize; + } + + return BP_RESULT_NORECORD; +} + +static enum bp_result get_voltage_ddc_info_v1(uint8_t *i2c_line, + ATOM_COMMON_TABLE_HEADER *header, + uint8_t *address) +{ + enum bp_result result = BP_RESULT_NORECORD; + ATOM_VOLTAGE_OBJECT_INFO *info = + (ATOM_VOLTAGE_OBJECT_INFO *) address; + + uint8_t *voltage_current_object = (uint8_t *) &info->asVoltageObj[0]; + + while ((address + le16_to_cpu(header->usStructureSize)) > voltage_current_object) { + ATOM_VOLTAGE_OBJECT *object = + (ATOM_VOLTAGE_OBJECT *) voltage_current_object; + + if ((object->ucVoltageType == SET_VOLTAGE_INIT_MODE) && + (object->ucVoltageType & + VOLTAGE_CONTROLLED_BY_I2C_MASK)) { + + *i2c_line = object->asControl.ucVoltageControlI2cLine + ^ 0x90; + result = BP_RESULT_OK; + break; + } + + voltage_current_object += object->ucSize; + } + return result; +} + +static enum bp_result get_voltage_ddc_info_v3(uint8_t *i2c_line, + uint32_t index, + ATOM_COMMON_TABLE_HEADER *header, + uint8_t *address) +{ + enum bp_result result = BP_RESULT_NORECORD; + ATOM_VOLTAGE_OBJECT_INFO_V3_1 *info = + (ATOM_VOLTAGE_OBJECT_INFO_V3_1 *) address; + + uint8_t *voltage_current_object = + (uint8_t *) (&(info->asVoltageObj[0])); + + while ((address + le16_to_cpu(header->usStructureSize)) > voltage_current_object) { + ATOM_I2C_VOLTAGE_OBJECT_V3 *object = + (ATOM_I2C_VOLTAGE_OBJECT_V3 *) voltage_current_object; + + if (object->sHeader.ucVoltageMode == + ATOM_INIT_VOLTAGE_REGULATOR) { + if (object->sHeader.ucVoltageType == index) { + *i2c_line = object->ucVoltageControlI2cLine + ^ 0x90; + result = BP_RESULT_OK; + break; + } + } + + voltage_current_object += le16_to_cpu(object->sHeader.usSize); + } + return result; +} + +static enum bp_result bios_parser_get_thermal_ddc_info( + struct dc_bios *dcb, + uint32_t i2c_channel_id, + struct graphics_object_i2c_info *info) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + ATOM_I2C_ID_CONFIG_ACCESS *config; + ATOM_I2C_RECORD record; + + if (!info) + return BP_RESULT_BADINPUT; + + config = (ATOM_I2C_ID_CONFIG_ACCESS *) &i2c_channel_id; + + record.sucI2cId.bfHW_Capable = config->sbfAccess.bfHW_Capable; + record.sucI2cId.bfI2C_LineMux = config->sbfAccess.bfI2C_LineMux; + record.sucI2cId.bfHW_EngineID = config->sbfAccess.bfHW_EngineID; + + return get_gpio_i2c_info(bp, &record, info); +} + +static enum bp_result bios_parser_get_voltage_ddc_info(struct dc_bios *dcb, + uint32_t index, + struct graphics_object_i2c_info *info) +{ + uint8_t i2c_line = 0; + enum bp_result result = BP_RESULT_NORECORD; + uint8_t *voltage_info_address; + ATOM_COMMON_TABLE_HEADER *header; + struct atom_data_revision revision = {0}; + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!DATA_TABLES(VoltageObjectInfo)) + return result; + + voltage_info_address = get_image(&bp->base, DATA_TABLES(VoltageObjectInfo), sizeof(ATOM_COMMON_TABLE_HEADER)); + + header = (ATOM_COMMON_TABLE_HEADER *) voltage_info_address; + + get_atom_data_table_revision(header, &revision); + + switch (revision.major) { + case 1: + case 2: + result = get_voltage_ddc_info_v1(&i2c_line, header, + voltage_info_address); + break; + case 3: + if (revision.minor != 1) + break; + result = get_voltage_ddc_info_v3(&i2c_line, index, header, + voltage_info_address); + break; + } + + if (result == BP_RESULT_OK) + result = bios_parser_get_thermal_ddc_info(dcb, + i2c_line, info); + + return result; +} + +/* TODO: temporary commented out to suppress 'defined but not used' warning */ +#if 0 +static enum bp_result bios_parser_get_ddc_info_for_i2c_line( + struct bios_parser *bp, + uint8_t i2c_line, struct graphics_object_i2c_info *info) +{ + uint32_t offset; + ATOM_OBJECT *object; + ATOM_OBJECT_TABLE *table; + uint32_t i; + + if (!info) + return BP_RESULT_BADINPUT; + + offset = le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset); + + offset += bp->object_info_tbl_offset; + + table = GET_IMAGE(ATOM_OBJECT_TABLE, offset); + + if (!table) + return BP_RESULT_BADBIOSTABLE; + + for (i = 0; i < table->ucNumberOfObjects; i++) { + object = &table->asObjects[i]; + + if (!object) { + BREAK_TO_DEBUGGER(); /* Invalid object id */ + return BP_RESULT_BADINPUT; + } + + offset = le16_to_cpu(object->usRecordOffset) + + bp->object_info_tbl_offset; + + for (;;) { + ATOM_COMMON_RECORD_HEADER *header = + GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset); + + if (!header) + return BP_RESULT_BADBIOSTABLE; + + offset += header->ucRecordSize; + + if (LAST_RECORD_TYPE == header->ucRecordType || + !header->ucRecordSize) + break; + + if (ATOM_I2C_RECORD_TYPE == header->ucRecordType + && sizeof(ATOM_I2C_RECORD) <= + header->ucRecordSize) { + ATOM_I2C_RECORD *record = + (ATOM_I2C_RECORD *) header; + + if (i2c_line != record->sucI2cId.bfI2C_LineMux) + continue; + + /* get the I2C info */ + if (get_gpio_i2c_info(bp, record, info) == + BP_RESULT_OK) + return BP_RESULT_OK; + } + } + } + + return BP_RESULT_NORECORD; +} +#endif + +static enum bp_result bios_parser_get_hpd_info(struct dc_bios *dcb, + struct graphics_object_id id, + struct graphics_object_hpd_info *info) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + ATOM_OBJECT *object; + ATOM_HPD_INT_RECORD *record = NULL; + + if (!info) + return BP_RESULT_BADINPUT; + + object = get_bios_object(bp, id); + + if (!object) + return BP_RESULT_BADINPUT; + + record = get_hpd_record(bp, object); + + if (record != NULL) { + info->hpd_int_gpio_uid = record->ucHPDIntGPIOID; + info->hpd_active = record->ucPlugged_PinState; + return BP_RESULT_OK; + } + + return BP_RESULT_NORECORD; +} + +static uint32_t bios_parser_get_gpio_record( + struct dc_bios *dcb, + struct graphics_object_id id, + struct bp_gpio_cntl_info *gpio_record, + uint32_t record_size) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + ATOM_COMMON_RECORD_HEADER *header = NULL; + ATOM_OBJECT_GPIO_CNTL_RECORD *record = NULL; + ATOM_OBJECT *object = get_bios_object(bp, id); + uint32_t offset; + uint32_t pins_number; + uint32_t i; + + if (!object) + return 0; + + /* Initialise offset */ + offset = le16_to_cpu(object->usRecordOffset) + + bp->object_info_tbl_offset; + + for (;;) { + /* Get record header */ + header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset); + if (!header || header->ucRecordType == LAST_RECORD_TYPE || + !header->ucRecordSize) + break; + + /* If this is gpio control record - stop. We found the record */ + if (header->ucRecordType == ATOM_OBJECT_GPIO_CNTL_RECORD_TYPE + && header->ucRecordSize + >= sizeof(ATOM_OBJECT_GPIO_CNTL_RECORD)) { + record = (ATOM_OBJECT_GPIO_CNTL_RECORD *) header; + break; + } + + /* Advance to next record */ + offset += header->ucRecordSize; + } + + /* If we did not find a record - return */ + if (!record) + return 0; + + /* Extract gpio IDs from bios record (make sure we do not exceed passed + * array size) */ + pins_number = (record->ucNumberOfPins < record_size ? + record->ucNumberOfPins : record_size); + for (i = 0; i < pins_number; i++) { + uint8_t output_state = ((record->asGpio[i].ucGPIO_PinState + & GPIO_PIN_OUTPUT_STATE_MASK) + >> GPIO_PIN_OUTPUT_STATE_SHIFT); + gpio_record[i].id = record->asGpio[i].ucGPIOID; + + switch (output_state) { + case GPIO_PIN_STATE_ACTIVE_LOW: + gpio_record[i].state = + GPIO_PIN_OUTPUT_STATE_ACTIVE_LOW; + break; + + case GPIO_PIN_STATE_ACTIVE_HIGH: + gpio_record[i].state = + GPIO_PIN_OUTPUT_STATE_ACTIVE_HIGH; + break; + + default: + BREAK_TO_DEBUGGER(); /* Invalid Pin Output State */ + break; + } + } + + return pins_number; +} + +enum bp_result bios_parser_get_device_tag_record( + struct bios_parser *bp, + ATOM_OBJECT *object, + ATOM_CONNECTOR_DEVICE_TAG_RECORD **record) +{ + ATOM_COMMON_RECORD_HEADER *header; + uint32_t offset; + + offset = le16_to_cpu(object->usRecordOffset) + + bp->object_info_tbl_offset; + + for (;;) { + header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset); + + if (!header) + return BP_RESULT_BADBIOSTABLE; + + offset += header->ucRecordSize; + + if (LAST_RECORD_TYPE == header->ucRecordType || + !header->ucRecordSize) + break; + + if (ATOM_CONNECTOR_DEVICE_TAG_RECORD_TYPE != + header->ucRecordType) + continue; + + if (sizeof(ATOM_CONNECTOR_DEVICE_TAG) > header->ucRecordSize) + continue; + + *record = (ATOM_CONNECTOR_DEVICE_TAG_RECORD *) header; + return BP_RESULT_OK; + } + + return BP_RESULT_NORECORD; +} + +static enum bp_result bios_parser_get_device_tag( + struct dc_bios *dcb, + struct graphics_object_id connector_object_id, + uint32_t device_tag_index, + struct connector_device_tag_info *info) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + ATOM_OBJECT *object; + ATOM_CONNECTOR_DEVICE_TAG_RECORD *record = NULL; + ATOM_CONNECTOR_DEVICE_TAG *device_tag; + + if (!info) + return BP_RESULT_BADINPUT; + + /* getBiosObject will return MXM object */ + object = get_bios_object(bp, connector_object_id); + + if (!object) { + BREAK_TO_DEBUGGER(); /* Invalid object id */ + return BP_RESULT_BADINPUT; + } + + if (bios_parser_get_device_tag_record(bp, object, &record) + != BP_RESULT_OK) + return BP_RESULT_NORECORD; + + if (device_tag_index >= record->ucNumberOfDevice) + return BP_RESULT_NORECORD; + + device_tag = &record->asDeviceTag[device_tag_index]; + + info->acpi_device = le32_to_cpu(device_tag->ulACPIDeviceEnum); + info->dev_id = + device_type_from_device_id(le16_to_cpu(device_tag->usDeviceID)); + + return BP_RESULT_OK; +} + +static enum bp_result get_firmware_info_v1_4( + struct bios_parser *bp, + struct firmware_info *info); +static enum bp_result get_firmware_info_v2_1( + struct bios_parser *bp, + struct firmware_info *info); +static enum bp_result get_firmware_info_v2_2( + struct bios_parser *bp, + struct firmware_info *info); + +static enum bp_result bios_parser_get_firmware_info( + struct dc_bios *dcb, + struct firmware_info *info) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + enum bp_result result = BP_RESULT_BADBIOSTABLE; + ATOM_COMMON_TABLE_HEADER *header; + struct atom_data_revision revision; + + if (info && DATA_TABLES(FirmwareInfo)) { + header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, + DATA_TABLES(FirmwareInfo)); + get_atom_data_table_revision(header, &revision); + switch (revision.major) { + case 1: + switch (revision.minor) { + case 4: + result = get_firmware_info_v1_4(bp, info); + break; + default: + break; + } + break; + + case 2: + switch (revision.minor) { + case 1: + result = get_firmware_info_v2_1(bp, info); + break; + case 2: + result = get_firmware_info_v2_2(bp, info); + break; + default: + break; + } + break; + default: + break; + } + } + + return result; +} + +static enum bp_result get_firmware_info_v1_4( + struct bios_parser *bp, + struct firmware_info *info) +{ + ATOM_FIRMWARE_INFO_V1_4 *firmware_info = + GET_IMAGE(ATOM_FIRMWARE_INFO_V1_4, + DATA_TABLES(FirmwareInfo)); + + if (!info) + return BP_RESULT_BADINPUT; + + if (!firmware_info) + return BP_RESULT_BADBIOSTABLE; + + memset(info, 0, sizeof(*info)); + + /* Pixel clock pll information. We need to convert from 10KHz units into + * KHz units */ + info->pll_info.crystal_frequency = + le16_to_cpu(firmware_info->usReferenceClock) * 10; + info->pll_info.min_input_pxl_clk_pll_frequency = + le16_to_cpu(firmware_info->usMinPixelClockPLL_Input) * 10; + info->pll_info.max_input_pxl_clk_pll_frequency = + le16_to_cpu(firmware_info->usMaxPixelClockPLL_Input) * 10; + info->pll_info.min_output_pxl_clk_pll_frequency = + le32_to_cpu(firmware_info->ulMinPixelClockPLL_Output) * 10; + info->pll_info.max_output_pxl_clk_pll_frequency = + le32_to_cpu(firmware_info->ulMaxPixelClockPLL_Output) * 10; + + if (firmware_info->usFirmwareCapability.sbfAccess.MemoryClockSS_Support) + /* Since there is no information on the SS, report conservative + * value 3% for bandwidth calculation */ + /* unit of 0.01% */ + info->feature.memory_clk_ss_percentage = THREE_PERCENT_OF_10000; + + if (firmware_info->usFirmwareCapability.sbfAccess.EngineClockSS_Support) + /* Since there is no information on the SS,report conservative + * value 3% for bandwidth calculation */ + /* unit of 0.01% */ + info->feature.engine_clk_ss_percentage = THREE_PERCENT_OF_10000; + + return BP_RESULT_OK; +} + +static enum bp_result get_ss_info_v3_1( + struct bios_parser *bp, + uint32_t id, + uint32_t index, + struct spread_spectrum_info *ss_info); + +static enum bp_result get_firmware_info_v2_1( + struct bios_parser *bp, + struct firmware_info *info) +{ + ATOM_FIRMWARE_INFO_V2_1 *firmwareInfo = + GET_IMAGE(ATOM_FIRMWARE_INFO_V2_1, DATA_TABLES(FirmwareInfo)); + struct spread_spectrum_info internalSS; + uint32_t index; + + if (!info) + return BP_RESULT_BADINPUT; + + if (!firmwareInfo) + return BP_RESULT_BADBIOSTABLE; + + memset(info, 0, sizeof(*info)); + + /* Pixel clock pll information. We need to convert from 10KHz units into + * KHz units */ + info->pll_info.crystal_frequency = + le16_to_cpu(firmwareInfo->usCoreReferenceClock) * 10; + info->pll_info.min_input_pxl_clk_pll_frequency = + le16_to_cpu(firmwareInfo->usMinPixelClockPLL_Input) * 10; + info->pll_info.max_input_pxl_clk_pll_frequency = + le16_to_cpu(firmwareInfo->usMaxPixelClockPLL_Input) * 10; + info->pll_info.min_output_pxl_clk_pll_frequency = + le32_to_cpu(firmwareInfo->ulMinPixelClockPLL_Output) * 10; + info->pll_info.max_output_pxl_clk_pll_frequency = + le32_to_cpu(firmwareInfo->ulMaxPixelClockPLL_Output) * 10; + info->default_display_engine_pll_frequency = + le32_to_cpu(firmwareInfo->ulDefaultDispEngineClkFreq) * 10; + info->external_clock_source_frequency_for_dp = + le16_to_cpu(firmwareInfo->usUniphyDPModeExtClkFreq) * 10; + info->min_allowed_bl_level = firmwareInfo->ucMinAllowedBL_Level; + + /* There should be only one entry in the SS info table for Memory Clock + */ + index = 0; + if (firmwareInfo->usFirmwareCapability.sbfAccess.MemoryClockSS_Support) + /* Since there is no information for external SS, report + * conservative value 3% for bandwidth calculation */ + /* unit of 0.01% */ + info->feature.memory_clk_ss_percentage = THREE_PERCENT_OF_10000; + else if (get_ss_info_v3_1(bp, + ASIC_INTERNAL_MEMORY_SS, index, &internalSS) == BP_RESULT_OK) { + if (internalSS.spread_spectrum_percentage) { + info->feature.memory_clk_ss_percentage = + internalSS.spread_spectrum_percentage; + if (internalSS.type.CENTER_MODE) { + /* if it is centermode, the exact SS Percentage + * will be round up of half of the percentage + * reported in the SS table */ + ++info->feature.memory_clk_ss_percentage; + info->feature.memory_clk_ss_percentage /= 2; + } + } + } + + /* There should be only one entry in the SS info table for Engine Clock + */ + index = 1; + if (firmwareInfo->usFirmwareCapability.sbfAccess.EngineClockSS_Support) + /* Since there is no information for external SS, report + * conservative value 3% for bandwidth calculation */ + /* unit of 0.01% */ + info->feature.engine_clk_ss_percentage = THREE_PERCENT_OF_10000; + else if (get_ss_info_v3_1(bp, + ASIC_INTERNAL_ENGINE_SS, index, &internalSS) == BP_RESULT_OK) { + if (internalSS.spread_spectrum_percentage) { + info->feature.engine_clk_ss_percentage = + internalSS.spread_spectrum_percentage; + if (internalSS.type.CENTER_MODE) { + /* if it is centermode, the exact SS Percentage + * will be round up of half of the percentage + * reported in the SS table */ + ++info->feature.engine_clk_ss_percentage; + info->feature.engine_clk_ss_percentage /= 2; + } + } + } + + return BP_RESULT_OK; +} + +static enum bp_result get_firmware_info_v2_2( + struct bios_parser *bp, + struct firmware_info *info) +{ + ATOM_FIRMWARE_INFO_V2_2 *firmware_info; + struct spread_spectrum_info internal_ss; + uint32_t index; + + if (!info) + return BP_RESULT_BADINPUT; + + firmware_info = GET_IMAGE(ATOM_FIRMWARE_INFO_V2_2, + DATA_TABLES(FirmwareInfo)); + + if (!firmware_info) + return BP_RESULT_BADBIOSTABLE; + + memset(info, 0, sizeof(*info)); + + /* Pixel clock pll information. We need to convert from 10KHz units into + * KHz units */ + info->pll_info.crystal_frequency = + le16_to_cpu(firmware_info->usCoreReferenceClock) * 10; + info->pll_info.min_input_pxl_clk_pll_frequency = + le16_to_cpu(firmware_info->usMinPixelClockPLL_Input) * 10; + info->pll_info.max_input_pxl_clk_pll_frequency = + le16_to_cpu(firmware_info->usMaxPixelClockPLL_Input) * 10; + info->pll_info.min_output_pxl_clk_pll_frequency = + le32_to_cpu(firmware_info->ulMinPixelClockPLL_Output) * 10; + info->pll_info.max_output_pxl_clk_pll_frequency = + le32_to_cpu(firmware_info->ulMaxPixelClockPLL_Output) * 10; + info->default_display_engine_pll_frequency = + le32_to_cpu(firmware_info->ulDefaultDispEngineClkFreq) * 10; + info->external_clock_source_frequency_for_dp = + le16_to_cpu(firmware_info->usUniphyDPModeExtClkFreq) * 10; + + /* There should be only one entry in the SS info table for Memory Clock + */ + index = 0; + if (firmware_info->usFirmwareCapability.sbfAccess.MemoryClockSS_Support) + /* Since there is no information for external SS, report + * conservative value 3% for bandwidth calculation */ + /* unit of 0.01% */ + info->feature.memory_clk_ss_percentage = THREE_PERCENT_OF_10000; + else if (get_ss_info_v3_1(bp, + ASIC_INTERNAL_MEMORY_SS, index, &internal_ss) == BP_RESULT_OK) { + if (internal_ss.spread_spectrum_percentage) { + info->feature.memory_clk_ss_percentage = + internal_ss.spread_spectrum_percentage; + if (internal_ss.type.CENTER_MODE) { + /* if it is centermode, the exact SS Percentage + * will be round up of half of the percentage + * reported in the SS table */ + ++info->feature.memory_clk_ss_percentage; + info->feature.memory_clk_ss_percentage /= 2; + } + } + } + + /* There should be only one entry in the SS info table for Engine Clock + */ + index = 1; + if (firmware_info->usFirmwareCapability.sbfAccess.EngineClockSS_Support) + /* Since there is no information for external SS, report + * conservative value 3% for bandwidth calculation */ + /* unit of 0.01% */ + info->feature.engine_clk_ss_percentage = THREE_PERCENT_OF_10000; + else if (get_ss_info_v3_1(bp, + ASIC_INTERNAL_ENGINE_SS, index, &internal_ss) == BP_RESULT_OK) { + if (internal_ss.spread_spectrum_percentage) { + info->feature.engine_clk_ss_percentage = + internal_ss.spread_spectrum_percentage; + if (internal_ss.type.CENTER_MODE) { + /* if it is centermode, the exact SS Percentage + * will be round up of half of the percentage + * reported in the SS table */ + ++info->feature.engine_clk_ss_percentage; + info->feature.engine_clk_ss_percentage /= 2; + } + } + } + + /* Remote Display */ + info->remote_display_config = firmware_info->ucRemoteDisplayConfig; + + /* Is allowed minimum BL level */ + info->min_allowed_bl_level = firmware_info->ucMinAllowedBL_Level; + /* Used starting from CI */ + info->smu_gpu_pll_output_freq = + (uint32_t) (le32_to_cpu(firmware_info->ulGPUPLL_OutputFreq) * 10); + + return BP_RESULT_OK; +} + +static enum bp_result get_ss_info_v3_1( + struct bios_parser *bp, + uint32_t id, + uint32_t index, + struct spread_spectrum_info *ss_info) +{ + ATOM_ASIC_INTERNAL_SS_INFO_V3 *ss_table_header_include; + ATOM_ASIC_SS_ASSIGNMENT_V3 *tbl; + uint32_t table_size; + uint32_t i; + uint32_t table_index = 0; + + if (!ss_info) + return BP_RESULT_BADINPUT; + + if (!DATA_TABLES(ASIC_InternalSS_Info)) + return BP_RESULT_UNSUPPORTED; + + ss_table_header_include = GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V3, + DATA_TABLES(ASIC_InternalSS_Info)); + table_size = + (le16_to_cpu(ss_table_header_include->sHeader.usStructureSize) + - sizeof(ATOM_COMMON_TABLE_HEADER)) + / sizeof(ATOM_ASIC_SS_ASSIGNMENT_V3); + + tbl = (ATOM_ASIC_SS_ASSIGNMENT_V3 *) + &ss_table_header_include->asSpreadSpectrum[0]; + + memset(ss_info, 0, sizeof(struct spread_spectrum_info)); + + for (i = 0; i < table_size; i++) { + if (tbl[i].ucClockIndication != (uint8_t) id) + continue; + + if (table_index != index) { + table_index++; + continue; + } + /* VBIOS introduced new defines for Version 3, same values as + * before, so now use these new ones for Version 3. + * Shouldn't affect field VBIOS's V3 as define values are still + * same. + * #define SS_MODE_V3_CENTRE_SPREAD_MASK 0x01 + * #define SS_MODE_V3_EXTERNAL_SS_MASK 0x02 + + * Old VBIOS defines: + * #define ATOM_SS_CENTRE_SPREAD_MODE_MASK 0x00000001 + * #define ATOM_EXTERNAL_SS_MASK 0x00000002 + */ + + if (SS_MODE_V3_EXTERNAL_SS_MASK & tbl[i].ucSpreadSpectrumMode) + ss_info->type.EXTERNAL = true; + + if (SS_MODE_V3_CENTRE_SPREAD_MASK & tbl[i].ucSpreadSpectrumMode) + ss_info->type.CENTER_MODE = true; + + /* Older VBIOS (in field) always provides SS percentage in 0.01% + * units set Divider to 100 */ + ss_info->spread_percentage_divider = 100; + + /* #define SS_MODE_V3_PERCENTAGE_DIV_BY_1000_MASK 0x10 */ + if (SS_MODE_V3_PERCENTAGE_DIV_BY_1000_MASK + & tbl[i].ucSpreadSpectrumMode) + ss_info->spread_percentage_divider = 1000; + + ss_info->type.STEP_AND_DELAY_INFO = false; + /* convert [10KHz] into [KHz] */ + ss_info->target_clock_range = + le32_to_cpu(tbl[i].ulTargetClockRange) * 10; + ss_info->spread_spectrum_percentage = + (uint32_t)le16_to_cpu(tbl[i].usSpreadSpectrumPercentage); + ss_info->spread_spectrum_range = + (uint32_t)(le16_to_cpu(tbl[i].usSpreadRateIn10Hz) * 10); + + return BP_RESULT_OK; + } + return BP_RESULT_NORECORD; +} + +static enum bp_result bios_parser_transmitter_control( + struct dc_bios *dcb, + struct bp_transmitter_control *cntl) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!bp->cmd_tbl.transmitter_control) + return BP_RESULT_FAILURE; + + return bp->cmd_tbl.transmitter_control(bp, cntl); +} + +static enum bp_result bios_parser_encoder_control( + struct dc_bios *dcb, + struct bp_encoder_control *cntl) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!bp->cmd_tbl.dig_encoder_control) + return BP_RESULT_FAILURE; + + return bp->cmd_tbl.dig_encoder_control(bp, cntl); +} + +static enum bp_result bios_parser_adjust_pixel_clock( + struct dc_bios *dcb, + struct bp_adjust_pixel_clock_parameters *bp_params) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!bp->cmd_tbl.adjust_display_pll) + return BP_RESULT_FAILURE; + + return bp->cmd_tbl.adjust_display_pll(bp, bp_params); +} + +static enum bp_result bios_parser_set_pixel_clock( + struct dc_bios *dcb, + struct bp_pixel_clock_parameters *bp_params) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!bp->cmd_tbl.set_pixel_clock) + return BP_RESULT_FAILURE; + + return bp->cmd_tbl.set_pixel_clock(bp, bp_params); +} + +static enum bp_result bios_parser_set_dce_clock( + struct dc_bios *dcb, + struct bp_set_dce_clock_parameters *bp_params) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!bp->cmd_tbl.set_dce_clock) + return BP_RESULT_FAILURE; + + return bp->cmd_tbl.set_dce_clock(bp, bp_params); +} + +static enum bp_result bios_parser_enable_spread_spectrum_on_ppll( + struct dc_bios *dcb, + struct bp_spread_spectrum_parameters *bp_params, + bool enable) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!bp->cmd_tbl.enable_spread_spectrum_on_ppll) + return BP_RESULT_FAILURE; + + return bp->cmd_tbl.enable_spread_spectrum_on_ppll( + bp, bp_params, enable); + +} + +static enum bp_result bios_parser_program_crtc_timing( + struct dc_bios *dcb, + struct bp_hw_crtc_timing_parameters *bp_params) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!bp->cmd_tbl.set_crtc_timing) + return BP_RESULT_FAILURE; + + return bp->cmd_tbl.set_crtc_timing(bp, bp_params); +} + +static enum bp_result bios_parser_program_display_engine_pll( + struct dc_bios *dcb, + struct bp_pixel_clock_parameters *bp_params) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!bp->cmd_tbl.program_clock) + return BP_RESULT_FAILURE; + + return bp->cmd_tbl.program_clock(bp, bp_params); + +} + + +static enum bp_result bios_parser_enable_crtc( + struct dc_bios *dcb, + enum controller_id id, + bool enable) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!bp->cmd_tbl.enable_crtc) + return BP_RESULT_FAILURE; + + return bp->cmd_tbl.enable_crtc(bp, id, enable); +} + +static enum bp_result bios_parser_crtc_source_select( + struct dc_bios *dcb, + struct bp_crtc_source_select *bp_params) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!bp->cmd_tbl.select_crtc_source) + return BP_RESULT_FAILURE; + + return bp->cmd_tbl.select_crtc_source(bp, bp_params); +} + +static enum bp_result bios_parser_enable_disp_power_gating( + struct dc_bios *dcb, + enum controller_id controller_id, + enum bp_pipe_control_action action) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!bp->cmd_tbl.enable_disp_power_gating) + return BP_RESULT_FAILURE; + + return bp->cmd_tbl.enable_disp_power_gating(bp, controller_id, + action); +} + +static bool bios_parser_is_device_id_supported( + struct dc_bios *dcb, + struct device_id id) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + uint32_t mask = get_support_mask_for_device_id(id); + + return (le16_to_cpu(bp->object_info_tbl.v1_1->usDeviceSupport) & mask) != 0; +} + +static enum bp_result bios_parser_crt_control( + struct dc_bios *dcb, + enum engine_id engine_id, + bool enable, + uint32_t pixel_clock) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + uint8_t standard; + + if (!bp->cmd_tbl.dac1_encoder_control && + engine_id == ENGINE_ID_DACA) + return BP_RESULT_FAILURE; + if (!bp->cmd_tbl.dac2_encoder_control && + engine_id == ENGINE_ID_DACB) + return BP_RESULT_FAILURE; + /* validate params */ + switch (engine_id) { + case ENGINE_ID_DACA: + case ENGINE_ID_DACB: + break; + default: + /* unsupported engine */ + return BP_RESULT_FAILURE; + } + + standard = ATOM_DAC1_PS2; /* == ATOM_DAC2_PS2 */ + + if (enable) { + if (engine_id == ENGINE_ID_DACA) { + bp->cmd_tbl.dac1_encoder_control(bp, enable, + pixel_clock, standard); + if (bp->cmd_tbl.dac1_output_control != NULL) + bp->cmd_tbl.dac1_output_control(bp, enable); + } else { + bp->cmd_tbl.dac2_encoder_control(bp, enable, + pixel_clock, standard); + if (bp->cmd_tbl.dac2_output_control != NULL) + bp->cmd_tbl.dac2_output_control(bp, enable); + } + } else { + if (engine_id == ENGINE_ID_DACA) { + if (bp->cmd_tbl.dac1_output_control != NULL) + bp->cmd_tbl.dac1_output_control(bp, enable); + bp->cmd_tbl.dac1_encoder_control(bp, enable, + pixel_clock, standard); + } else { + if (bp->cmd_tbl.dac2_output_control != NULL) + bp->cmd_tbl.dac2_output_control(bp, enable); + bp->cmd_tbl.dac2_encoder_control(bp, enable, + pixel_clock, standard); + } + } + + return BP_RESULT_OK; +} + +static ATOM_HPD_INT_RECORD *get_hpd_record(struct bios_parser *bp, + ATOM_OBJECT *object) +{ + ATOM_COMMON_RECORD_HEADER *header; + uint32_t offset; + + if (!object) { + BREAK_TO_DEBUGGER(); /* Invalid object */ + return NULL; + } + + offset = le16_to_cpu(object->usRecordOffset) + + bp->object_info_tbl_offset; + + for (;;) { + header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset); + + if (!header) + return NULL; + + if (LAST_RECORD_TYPE == header->ucRecordType || + !header->ucRecordSize) + break; + + if (ATOM_HPD_INT_RECORD_TYPE == header->ucRecordType + && sizeof(ATOM_HPD_INT_RECORD) <= header->ucRecordSize) + return (ATOM_HPD_INT_RECORD *) header; + + offset += header->ucRecordSize; + } + + return NULL; +} + +/** + * Get I2C information of input object id + * + * search all records to find the ATOM_I2C_RECORD_TYPE record IR + */ +static ATOM_I2C_RECORD *get_i2c_record( + struct bios_parser *bp, + ATOM_OBJECT *object) +{ + uint32_t offset; + ATOM_COMMON_RECORD_HEADER *record_header; + + if (!object) { + BREAK_TO_DEBUGGER(); + /* Invalid object */ + return NULL; + } + + offset = le16_to_cpu(object->usRecordOffset) + + bp->object_info_tbl_offset; + + for (;;) { + record_header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset); + + if (!record_header) + return NULL; + + if (LAST_RECORD_TYPE == record_header->ucRecordType || + 0 == record_header->ucRecordSize) + break; + + if (ATOM_I2C_RECORD_TYPE == record_header->ucRecordType && + sizeof(ATOM_I2C_RECORD) <= + record_header->ucRecordSize) { + return (ATOM_I2C_RECORD *)record_header; + } + + offset += record_header->ucRecordSize; + } + + return NULL; +} + +static enum bp_result get_ss_info_from_ss_info_table( + struct bios_parser *bp, + uint32_t id, + struct spread_spectrum_info *ss_info); +static enum bp_result get_ss_info_from_tbl( + struct bios_parser *bp, + uint32_t id, + struct spread_spectrum_info *ss_info); +/** + * bios_parser_get_spread_spectrum_info + * Get spread spectrum information from the ASIC_InternalSS_Info(ver 2.1 or + * ver 3.1) or SS_Info table from the VBIOS. Currently ASIC_InternalSS_Info + * ver 2.1 can co-exist with SS_Info table. Expect ASIC_InternalSS_Info ver 3.1, + * there is only one entry for each signal /ss id. However, there is + * no planning of supporting multiple spread Sprectum entry for EverGreen + * @param [in] this + * @param [in] signal, ASSignalType to be converted to info index + * @param [in] index, number of entries that match the converted info index + * @param [out] ss_info, sprectrum information structure, + * @return Bios parser result code + */ +static enum bp_result bios_parser_get_spread_spectrum_info( + struct dc_bios *dcb, + enum as_signal_type signal, + uint32_t index, + struct spread_spectrum_info *ss_info) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + enum bp_result result = BP_RESULT_UNSUPPORTED; + uint32_t clk_id_ss = 0; + ATOM_COMMON_TABLE_HEADER *header; + struct atom_data_revision tbl_revision; + + if (!ss_info) /* check for bad input */ + return BP_RESULT_BADINPUT; + /* signal translation */ + clk_id_ss = signal_to_ss_id(signal); + + if (!DATA_TABLES(ASIC_InternalSS_Info)) + if (!index) + return get_ss_info_from_ss_info_table(bp, clk_id_ss, + ss_info); + + header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, + DATA_TABLES(ASIC_InternalSS_Info)); + get_atom_data_table_revision(header, &tbl_revision); + + switch (tbl_revision.major) { + case 2: + switch (tbl_revision.minor) { + case 1: + /* there can not be more then one entry for Internal + * SS Info table version 2.1 */ + if (!index) + return get_ss_info_from_tbl(bp, clk_id_ss, + ss_info); + break; + default: + break; + } + break; + + case 3: + switch (tbl_revision.minor) { + case 1: + return get_ss_info_v3_1(bp, clk_id_ss, index, ss_info); + default: + break; + } + break; + default: + break; + } + /* there can not be more then one entry for SS Info table */ + return result; +} + +static enum bp_result get_ss_info_from_internal_ss_info_tbl_V2_1( + struct bios_parser *bp, + uint32_t id, + struct spread_spectrum_info *info); + +/** + * get_ss_info_from_table + * Get spread sprectrum information from the ASIC_InternalSS_Info Ver 2.1 or + * SS_Info table from the VBIOS + * There can not be more than 1 entry for ASIC_InternalSS_Info Ver 2.1 or + * SS_Info. + * + * @param this + * @param id, spread sprectrum info index + * @param pSSinfo, sprectrum information structure, + * @return Bios parser result code + */ +static enum bp_result get_ss_info_from_tbl( + struct bios_parser *bp, + uint32_t id, + struct spread_spectrum_info *ss_info) +{ + if (!ss_info) /* check for bad input, if ss_info is not NULL */ + return BP_RESULT_BADINPUT; + /* for SS_Info table only support DP and LVDS */ + if (id == ASIC_INTERNAL_SS_ON_DP || id == ASIC_INTERNAL_SS_ON_LVDS) + return get_ss_info_from_ss_info_table(bp, id, ss_info); + else + return get_ss_info_from_internal_ss_info_tbl_V2_1(bp, id, + ss_info); +} + +/** + * get_ss_info_from_internal_ss_info_tbl_V2_1 + * Get spread sprectrum information from the ASIC_InternalSS_Info table Ver 2.1 + * from the VBIOS + * There will not be multiple entry for Ver 2.1 + * + * @param id, spread sprectrum info index + * @param pSSinfo, sprectrum information structure, + * @return Bios parser result code + */ +static enum bp_result get_ss_info_from_internal_ss_info_tbl_V2_1( + struct bios_parser *bp, + uint32_t id, + struct spread_spectrum_info *info) +{ + enum bp_result result = BP_RESULT_UNSUPPORTED; + ATOM_ASIC_INTERNAL_SS_INFO_V2 *header; + ATOM_ASIC_SS_ASSIGNMENT_V2 *tbl; + uint32_t tbl_size, i; + + if (!DATA_TABLES(ASIC_InternalSS_Info)) + return result; + + header = GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V2, + DATA_TABLES(ASIC_InternalSS_Info)); + + memset(info, 0, sizeof(struct spread_spectrum_info)); + + tbl_size = (le16_to_cpu(header->sHeader.usStructureSize) + - sizeof(ATOM_COMMON_TABLE_HEADER)) + / sizeof(ATOM_ASIC_SS_ASSIGNMENT_V2); + + tbl = (ATOM_ASIC_SS_ASSIGNMENT_V2 *) + &(header->asSpreadSpectrum[0]); + for (i = 0; i < tbl_size; i++) { + result = BP_RESULT_NORECORD; + + if (tbl[i].ucClockIndication != (uint8_t)id) + continue; + + if (ATOM_EXTERNAL_SS_MASK + & tbl[i].ucSpreadSpectrumMode) { + info->type.EXTERNAL = true; + } + if (ATOM_SS_CENTRE_SPREAD_MODE_MASK + & tbl[i].ucSpreadSpectrumMode) { + info->type.CENTER_MODE = true; + } + info->type.STEP_AND_DELAY_INFO = false; + /* convert [10KHz] into [KHz] */ + info->target_clock_range = + le32_to_cpu(tbl[i].ulTargetClockRange) * 10; + info->spread_spectrum_percentage = + (uint32_t)le16_to_cpu(tbl[i].usSpreadSpectrumPercentage); + info->spread_spectrum_range = + (uint32_t)(le16_to_cpu(tbl[i].usSpreadRateIn10Hz) * 10); + result = BP_RESULT_OK; + break; + } + + return result; + +} + +/** + * get_ss_info_from_ss_info_table + * Get spread sprectrum information from the SS_Info table from the VBIOS + * if the pointer to info is NULL, indicate the caller what to know the number + * of entries that matches the id + * for, the SS_Info table, there should not be more than 1 entry match. + * + * @param [in] id, spread sprectrum id + * @param [out] pSSinfo, sprectrum information structure, + * @return Bios parser result code + */ +static enum bp_result get_ss_info_from_ss_info_table( + struct bios_parser *bp, + uint32_t id, + struct spread_spectrum_info *ss_info) +{ + enum bp_result result = BP_RESULT_UNSUPPORTED; + ATOM_SPREAD_SPECTRUM_INFO *tbl; + ATOM_COMMON_TABLE_HEADER *header; + uint32_t table_size; + uint32_t i; + uint32_t id_local = SS_ID_UNKNOWN; + struct atom_data_revision revision; + + /* exist of the SS_Info table */ + /* check for bad input, pSSinfo can not be NULL */ + if (!DATA_TABLES(SS_Info) || !ss_info) + return result; + + header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, DATA_TABLES(SS_Info)); + get_atom_data_table_revision(header, &revision); + + tbl = GET_IMAGE(ATOM_SPREAD_SPECTRUM_INFO, DATA_TABLES(SS_Info)); + + if (1 != revision.major || 2 > revision.minor) + return result; + + /* have to convert from Internal_SS format to SS_Info format */ + switch (id) { + case ASIC_INTERNAL_SS_ON_DP: + id_local = SS_ID_DP1; + break; + case ASIC_INTERNAL_SS_ON_LVDS: + { + struct embedded_panel_info panel_info; + + if (bios_parser_get_embedded_panel_info(&bp->base, &panel_info) + == BP_RESULT_OK) + id_local = panel_info.ss_id; + break; + } + default: + break; + } + + if (id_local == SS_ID_UNKNOWN) + return result; + + table_size = (le16_to_cpu(tbl->sHeader.usStructureSize) - + sizeof(ATOM_COMMON_TABLE_HEADER)) / + sizeof(ATOM_SPREAD_SPECTRUM_ASSIGNMENT); + + for (i = 0; i < table_size; i++) { + if (id_local != (uint32_t)tbl->asSS_Info[i].ucSS_Id) + continue; + + memset(ss_info, 0, sizeof(struct spread_spectrum_info)); + + if (ATOM_EXTERNAL_SS_MASK & + tbl->asSS_Info[i].ucSpreadSpectrumType) + ss_info->type.EXTERNAL = true; + + if (ATOM_SS_CENTRE_SPREAD_MODE_MASK & + tbl->asSS_Info[i].ucSpreadSpectrumType) + ss_info->type.CENTER_MODE = true; + + ss_info->type.STEP_AND_DELAY_INFO = true; + ss_info->spread_spectrum_percentage = + (uint32_t)le16_to_cpu(tbl->asSS_Info[i].usSpreadSpectrumPercentage); + ss_info->step_and_delay_info.step = tbl->asSS_Info[i].ucSS_Step; + ss_info->step_and_delay_info.delay = + tbl->asSS_Info[i].ucSS_Delay; + ss_info->step_and_delay_info.recommended_ref_div = + tbl->asSS_Info[i].ucRecommendedRef_Div; + ss_info->spread_spectrum_range = + (uint32_t)tbl->asSS_Info[i].ucSS_Range * 10000; + + /* there will be only one entry for each display type in SS_info + * table */ + result = BP_RESULT_OK; + break; + } + + return result; +} +static enum bp_result get_embedded_panel_info_v1_2( + struct bios_parser *bp, + struct embedded_panel_info *info); +static enum bp_result get_embedded_panel_info_v1_3( + struct bios_parser *bp, + struct embedded_panel_info *info); + +static enum bp_result bios_parser_get_embedded_panel_info( + struct dc_bios *dcb, + struct embedded_panel_info *info) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + ATOM_COMMON_TABLE_HEADER *hdr; + + if (!DATA_TABLES(LCD_Info)) + return BP_RESULT_FAILURE; + + hdr = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, DATA_TABLES(LCD_Info)); + + if (!hdr) + return BP_RESULT_BADBIOSTABLE; + + switch (hdr->ucTableFormatRevision) { + case 1: + switch (hdr->ucTableContentRevision) { + case 0: + case 1: + case 2: + return get_embedded_panel_info_v1_2(bp, info); + case 3: + return get_embedded_panel_info_v1_3(bp, info); + default: + break; + } + default: + break; + } + + return BP_RESULT_FAILURE; +} + +static enum bp_result get_embedded_panel_info_v1_2( + struct bios_parser *bp, + struct embedded_panel_info *info) +{ + ATOM_LVDS_INFO_V12 *lvds; + + if (!info) + return BP_RESULT_BADINPUT; + + if (!DATA_TABLES(LVDS_Info)) + return BP_RESULT_UNSUPPORTED; + + lvds = + GET_IMAGE(ATOM_LVDS_INFO_V12, DATA_TABLES(LVDS_Info)); + + if (!lvds) + return BP_RESULT_BADBIOSTABLE; + + if (1 != lvds->sHeader.ucTableFormatRevision + || 2 > lvds->sHeader.ucTableContentRevision) + return BP_RESULT_UNSUPPORTED; + + memset(info, 0, sizeof(struct embedded_panel_info)); + + /* We need to convert from 10KHz units into KHz units*/ + info->lcd_timing.pixel_clk = + le16_to_cpu(lvds->sLCDTiming.usPixClk) * 10; + /* usHActive does not include borders, according to VBIOS team*/ + info->lcd_timing.horizontal_addressable = + le16_to_cpu(lvds->sLCDTiming.usHActive); + /* usHBlanking_Time includes borders, so we should really be subtracting + * borders duing this translation, but LVDS generally*/ + /* doesn't have borders, so we should be okay leaving this as is for + * now. May need to revisit if we ever have LVDS with borders*/ + info->lcd_timing.horizontal_blanking_time = + le16_to_cpu(lvds->sLCDTiming.usHBlanking_Time); + /* usVActive does not include borders, according to VBIOS team*/ + info->lcd_timing.vertical_addressable = + le16_to_cpu(lvds->sLCDTiming.usVActive); + /* usVBlanking_Time includes borders, so we should really be subtracting + * borders duing this translation, but LVDS generally*/ + /* doesn't have borders, so we should be okay leaving this as is for + * now. May need to revisit if we ever have LVDS with borders*/ + info->lcd_timing.vertical_blanking_time = + le16_to_cpu(lvds->sLCDTiming.usVBlanking_Time); + info->lcd_timing.horizontal_sync_offset = + le16_to_cpu(lvds->sLCDTiming.usHSyncOffset); + info->lcd_timing.horizontal_sync_width = + le16_to_cpu(lvds->sLCDTiming.usHSyncWidth); + info->lcd_timing.vertical_sync_offset = + le16_to_cpu(lvds->sLCDTiming.usVSyncOffset); + info->lcd_timing.vertical_sync_width = + le16_to_cpu(lvds->sLCDTiming.usVSyncWidth); + info->lcd_timing.horizontal_border = lvds->sLCDTiming.ucHBorder; + info->lcd_timing.vertical_border = lvds->sLCDTiming.ucVBorder; + info->lcd_timing.misc_info.HORIZONTAL_CUT_OFF = + lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HorizontalCutOff; + info->lcd_timing.misc_info.H_SYNC_POLARITY = + ~(uint32_t) + lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HSyncPolarity; + info->lcd_timing.misc_info.V_SYNC_POLARITY = + ~(uint32_t) + lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VSyncPolarity; + info->lcd_timing.misc_info.VERTICAL_CUT_OFF = + lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VerticalCutOff; + info->lcd_timing.misc_info.H_REPLICATION_BY2 = + lvds->sLCDTiming.susModeMiscInfo.sbfAccess.H_ReplicationBy2; + info->lcd_timing.misc_info.V_REPLICATION_BY2 = + lvds->sLCDTiming.susModeMiscInfo.sbfAccess.V_ReplicationBy2; + info->lcd_timing.misc_info.COMPOSITE_SYNC = + lvds->sLCDTiming.susModeMiscInfo.sbfAccess.CompositeSync; + info->lcd_timing.misc_info.INTERLACE = + lvds->sLCDTiming.susModeMiscInfo.sbfAccess.Interlace; + info->lcd_timing.misc_info.DOUBLE_CLOCK = + lvds->sLCDTiming.susModeMiscInfo.sbfAccess.DoubleClock; + info->ss_id = lvds->ucSS_Id; + + { + uint8_t rr = le16_to_cpu(lvds->usSupportedRefreshRate); + /* Get minimum supported refresh rate*/ + if (SUPPORTED_LCD_REFRESHRATE_30Hz & rr) + info->supported_rr.REFRESH_RATE_30HZ = 1; + else if (SUPPORTED_LCD_REFRESHRATE_40Hz & rr) + info->supported_rr.REFRESH_RATE_40HZ = 1; + else if (SUPPORTED_LCD_REFRESHRATE_48Hz & rr) + info->supported_rr.REFRESH_RATE_48HZ = 1; + else if (SUPPORTED_LCD_REFRESHRATE_50Hz & rr) + info->supported_rr.REFRESH_RATE_50HZ = 1; + else if (SUPPORTED_LCD_REFRESHRATE_60Hz & rr) + info->supported_rr.REFRESH_RATE_60HZ = 1; + } + + /*Drr panel support can be reported by VBIOS*/ + if (LCDPANEL_CAP_DRR_SUPPORTED + & lvds->ucLCDPanel_SpecialHandlingCap) + info->drr_enabled = 1; + + if (ATOM_PANEL_MISC_DUAL & lvds->ucLVDS_Misc) + info->lcd_timing.misc_info.DOUBLE_CLOCK = true; + + if (ATOM_PANEL_MISC_888RGB & lvds->ucLVDS_Misc) + info->lcd_timing.misc_info.RGB888 = true; + + info->lcd_timing.misc_info.GREY_LEVEL = + (uint32_t) (ATOM_PANEL_MISC_GREY_LEVEL & + lvds->ucLVDS_Misc) >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT; + + if (ATOM_PANEL_MISC_SPATIAL & lvds->ucLVDS_Misc) + info->lcd_timing.misc_info.SPATIAL = true; + + if (ATOM_PANEL_MISC_TEMPORAL & lvds->ucLVDS_Misc) + info->lcd_timing.misc_info.TEMPORAL = true; + + if (ATOM_PANEL_MISC_API_ENABLED & lvds->ucLVDS_Misc) + info->lcd_timing.misc_info.API_ENABLED = true; + + return BP_RESULT_OK; +} + +static enum bp_result get_embedded_panel_info_v1_3( + struct bios_parser *bp, + struct embedded_panel_info *info) +{ + ATOM_LCD_INFO_V13 *lvds; + + if (!info) + return BP_RESULT_BADINPUT; + + if (!DATA_TABLES(LCD_Info)) + return BP_RESULT_UNSUPPORTED; + + lvds = GET_IMAGE(ATOM_LCD_INFO_V13, DATA_TABLES(LCD_Info)); + + if (!lvds) + return BP_RESULT_BADBIOSTABLE; + + if (!((1 == lvds->sHeader.ucTableFormatRevision) + && (3 <= lvds->sHeader.ucTableContentRevision))) + return BP_RESULT_UNSUPPORTED; + + memset(info, 0, sizeof(struct embedded_panel_info)); + + /* We need to convert from 10KHz units into KHz units */ + info->lcd_timing.pixel_clk = + le16_to_cpu(lvds->sLCDTiming.usPixClk) * 10; + /* usHActive does not include borders, according to VBIOS team */ + info->lcd_timing.horizontal_addressable = + le16_to_cpu(lvds->sLCDTiming.usHActive); + /* usHBlanking_Time includes borders, so we should really be subtracting + * borders duing this translation, but LVDS generally*/ + /* doesn't have borders, so we should be okay leaving this as is for + * now. May need to revisit if we ever have LVDS with borders*/ + info->lcd_timing.horizontal_blanking_time = + le16_to_cpu(lvds->sLCDTiming.usHBlanking_Time); + /* usVActive does not include borders, according to VBIOS team*/ + info->lcd_timing.vertical_addressable = + le16_to_cpu(lvds->sLCDTiming.usVActive); + /* usVBlanking_Time includes borders, so we should really be subtracting + * borders duing this translation, but LVDS generally*/ + /* doesn't have borders, so we should be okay leaving this as is for + * now. May need to revisit if we ever have LVDS with borders*/ + info->lcd_timing.vertical_blanking_time = + le16_to_cpu(lvds->sLCDTiming.usVBlanking_Time); + info->lcd_timing.horizontal_sync_offset = + le16_to_cpu(lvds->sLCDTiming.usHSyncOffset); + info->lcd_timing.horizontal_sync_width = + le16_to_cpu(lvds->sLCDTiming.usHSyncWidth); + info->lcd_timing.vertical_sync_offset = + le16_to_cpu(lvds->sLCDTiming.usVSyncOffset); + info->lcd_timing.vertical_sync_width = + le16_to_cpu(lvds->sLCDTiming.usVSyncWidth); + info->lcd_timing.horizontal_border = lvds->sLCDTiming.ucHBorder; + info->lcd_timing.vertical_border = lvds->sLCDTiming.ucVBorder; + info->lcd_timing.misc_info.HORIZONTAL_CUT_OFF = + lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HorizontalCutOff; + info->lcd_timing.misc_info.H_SYNC_POLARITY = + ~(uint32_t) + lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HSyncPolarity; + info->lcd_timing.misc_info.V_SYNC_POLARITY = + ~(uint32_t) + lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VSyncPolarity; + info->lcd_timing.misc_info.VERTICAL_CUT_OFF = + lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VerticalCutOff; + info->lcd_timing.misc_info.H_REPLICATION_BY2 = + lvds->sLCDTiming.susModeMiscInfo.sbfAccess.H_ReplicationBy2; + info->lcd_timing.misc_info.V_REPLICATION_BY2 = + lvds->sLCDTiming.susModeMiscInfo.sbfAccess.V_ReplicationBy2; + info->lcd_timing.misc_info.COMPOSITE_SYNC = + lvds->sLCDTiming.susModeMiscInfo.sbfAccess.CompositeSync; + info->lcd_timing.misc_info.INTERLACE = + lvds->sLCDTiming.susModeMiscInfo.sbfAccess.Interlace; + info->lcd_timing.misc_info.DOUBLE_CLOCK = + lvds->sLCDTiming.susModeMiscInfo.sbfAccess.DoubleClock; + info->ss_id = lvds->ucSS_Id; + + /* Drr panel support can be reported by VBIOS*/ + if (LCDPANEL_CAP_V13_DRR_SUPPORTED + & lvds->ucLCDPanel_SpecialHandlingCap) + info->drr_enabled = 1; + + /* Get supported refresh rate*/ + if (info->drr_enabled == 1) { + uint8_t min_rr = + lvds->sRefreshRateSupport.ucMinRefreshRateForDRR; + uint8_t rr = lvds->sRefreshRateSupport.ucSupportedRefreshRate; + + if (min_rr != 0) { + if (SUPPORTED_LCD_REFRESHRATE_30Hz & min_rr) + info->supported_rr.REFRESH_RATE_30HZ = 1; + else if (SUPPORTED_LCD_REFRESHRATE_40Hz & min_rr) + info->supported_rr.REFRESH_RATE_40HZ = 1; + else if (SUPPORTED_LCD_REFRESHRATE_48Hz & min_rr) + info->supported_rr.REFRESH_RATE_48HZ = 1; + else if (SUPPORTED_LCD_REFRESHRATE_50Hz & min_rr) + info->supported_rr.REFRESH_RATE_50HZ = 1; + else if (SUPPORTED_LCD_REFRESHRATE_60Hz & min_rr) + info->supported_rr.REFRESH_RATE_60HZ = 1; + } else { + if (SUPPORTED_LCD_REFRESHRATE_30Hz & rr) + info->supported_rr.REFRESH_RATE_30HZ = 1; + else if (SUPPORTED_LCD_REFRESHRATE_40Hz & rr) + info->supported_rr.REFRESH_RATE_40HZ = 1; + else if (SUPPORTED_LCD_REFRESHRATE_48Hz & rr) + info->supported_rr.REFRESH_RATE_48HZ = 1; + else if (SUPPORTED_LCD_REFRESHRATE_50Hz & rr) + info->supported_rr.REFRESH_RATE_50HZ = 1; + else if (SUPPORTED_LCD_REFRESHRATE_60Hz & rr) + info->supported_rr.REFRESH_RATE_60HZ = 1; + } + } + + if (ATOM_PANEL_MISC_V13_DUAL & lvds->ucLCD_Misc) + info->lcd_timing.misc_info.DOUBLE_CLOCK = true; + + if (ATOM_PANEL_MISC_V13_8BIT_PER_COLOR & lvds->ucLCD_Misc) + info->lcd_timing.misc_info.RGB888 = true; + + info->lcd_timing.misc_info.GREY_LEVEL = + (uint32_t) (ATOM_PANEL_MISC_V13_GREY_LEVEL & + lvds->ucLCD_Misc) >> ATOM_PANEL_MISC_V13_GREY_LEVEL_SHIFT; + + return BP_RESULT_OK; +} + +/** + * bios_parser_get_encoder_cap_info + * + * @brief + * Get encoder capability information of input object id + * + * @param object_id, Object id + * @param object_id, encoder cap information structure + * + * @return Bios parser result code + * + */ +static enum bp_result bios_parser_get_encoder_cap_info( + struct dc_bios *dcb, + struct graphics_object_id object_id, + struct bp_encoder_cap_info *info) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + ATOM_OBJECT *object; + ATOM_ENCODER_CAP_RECORD *record = NULL; + + if (!info) + return BP_RESULT_BADINPUT; + + object = get_bios_object(bp, object_id); + + if (!object) + return BP_RESULT_BADINPUT; + + record = get_encoder_cap_record(bp, object); + if (!record) + return BP_RESULT_NORECORD; + + info->DP_HBR2_CAP = record->usHBR2Cap; + info->DP_HBR2_EN = record->usHBR2En; + return BP_RESULT_OK; +} + +/** + * get_encoder_cap_record + * + * @brief + * Get encoder cap record for the object + * + * @param object, ATOM object + * + * @return atom encoder cap record + * + * @note + * search all records to find the ATOM_ENCODER_CAP_RECORD record + */ +static ATOM_ENCODER_CAP_RECORD *get_encoder_cap_record( + struct bios_parser *bp, + ATOM_OBJECT *object) +{ + ATOM_COMMON_RECORD_HEADER *header; + uint32_t offset; + + if (!object) { + BREAK_TO_DEBUGGER(); /* Invalid object */ + return NULL; + } + + offset = le16_to_cpu(object->usRecordOffset) + + bp->object_info_tbl_offset; + + for (;;) { + header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset); + + if (!header) + return NULL; + + offset += header->ucRecordSize; + + if (LAST_RECORD_TYPE == header->ucRecordType || + !header->ucRecordSize) + break; + + if (ATOM_ENCODER_CAP_RECORD_TYPE != header->ucRecordType) + continue; + + if (sizeof(ATOM_ENCODER_CAP_RECORD) <= header->ucRecordSize) + return (ATOM_ENCODER_CAP_RECORD *)header; + } + + return NULL; +} + +static uint32_t get_ss_entry_number( + struct bios_parser *bp, + uint32_t id); +static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_v2_1( + struct bios_parser *bp, + uint32_t id); +static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_V3_1( + struct bios_parser *bp, + uint32_t id); +static uint32_t get_ss_entry_number_from_ss_info_tbl( + struct bios_parser *bp, + uint32_t id); + +/** + * BiosParserObject::GetNumberofSpreadSpectrumEntry + * Get Number of SpreadSpectrum Entry from the ASIC_InternalSS_Info table from + * the VBIOS that match the SSid (to be converted from signal) + * + * @param[in] signal, ASSignalType to be converted to SSid + * @return number of SS Entry that match the signal + */ +static uint32_t bios_parser_get_ss_entry_number( + struct dc_bios *dcb, + enum as_signal_type signal) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + uint32_t ss_id = 0; + ATOM_COMMON_TABLE_HEADER *header; + struct atom_data_revision revision; + + ss_id = signal_to_ss_id(signal); + + if (!DATA_TABLES(ASIC_InternalSS_Info)) + return get_ss_entry_number_from_ss_info_tbl(bp, ss_id); + + header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, + DATA_TABLES(ASIC_InternalSS_Info)); + get_atom_data_table_revision(header, &revision); + + switch (revision.major) { + case 2: + switch (revision.minor) { + case 1: + return get_ss_entry_number(bp, ss_id); + default: + break; + } + break; + case 3: + switch (revision.minor) { + case 1: + return + get_ss_entry_number_from_internal_ss_info_tbl_V3_1( + bp, ss_id); + default: + break; + } + break; + default: + break; + } + + return 0; +} + +/** + * get_ss_entry_number_from_ss_info_tbl + * Get Number of spread spectrum entry from the SS_Info table from the VBIOS. + * + * @note There can only be one entry for each id for SS_Info Table + * + * @param [in] id, spread spectrum id + * @return number of SS Entry that match the id + */ +static uint32_t get_ss_entry_number_from_ss_info_tbl( + struct bios_parser *bp, + uint32_t id) +{ + ATOM_SPREAD_SPECTRUM_INFO *tbl; + ATOM_COMMON_TABLE_HEADER *header; + uint32_t table_size; + uint32_t i; + uint32_t number = 0; + uint32_t id_local = SS_ID_UNKNOWN; + struct atom_data_revision revision; + + /* SS_Info table exist */ + if (!DATA_TABLES(SS_Info)) + return number; + + header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, + DATA_TABLES(SS_Info)); + get_atom_data_table_revision(header, &revision); + + tbl = GET_IMAGE(ATOM_SPREAD_SPECTRUM_INFO, + DATA_TABLES(SS_Info)); + + if (1 != revision.major || 2 > revision.minor) + return number; + + /* have to convert from Internal_SS format to SS_Info format */ + switch (id) { + case ASIC_INTERNAL_SS_ON_DP: + id_local = SS_ID_DP1; + break; + case ASIC_INTERNAL_SS_ON_LVDS: { + struct embedded_panel_info panel_info; + + if (bios_parser_get_embedded_panel_info(&bp->base, &panel_info) + == BP_RESULT_OK) + id_local = panel_info.ss_id; + break; + } + default: + break; + } + + if (id_local == SS_ID_UNKNOWN) + return number; + + table_size = (le16_to_cpu(tbl->sHeader.usStructureSize) - + sizeof(ATOM_COMMON_TABLE_HEADER)) / + sizeof(ATOM_SPREAD_SPECTRUM_ASSIGNMENT); + + for (i = 0; i < table_size; i++) + if (id_local == (uint32_t)tbl->asSS_Info[i].ucSS_Id) { + number = 1; + break; + } + + return number; +} + +/** + * get_ss_entry_number + * Get spread sprectrum information from the ASIC_InternalSS_Info Ver 2.1 or + * SS_Info table from the VBIOS + * There can not be more than 1 entry for ASIC_InternalSS_Info Ver 2.1 or + * SS_Info. + * + * @param id, spread sprectrum info index + * @return Bios parser result code + */ +static uint32_t get_ss_entry_number(struct bios_parser *bp, uint32_t id) +{ + if (id == ASIC_INTERNAL_SS_ON_DP || id == ASIC_INTERNAL_SS_ON_LVDS) + return get_ss_entry_number_from_ss_info_tbl(bp, id); + + return get_ss_entry_number_from_internal_ss_info_tbl_v2_1(bp, id); +} + +/** + * get_ss_entry_number_from_internal_ss_info_tbl_v2_1 + * Get NUmber of spread sprectrum entry from the ASIC_InternalSS_Info table + * Ver 2.1 from the VBIOS + * There will not be multiple entry for Ver 2.1 + * + * @param id, spread sprectrum info index + * @return number of SS Entry that match the id + */ +static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_v2_1( + struct bios_parser *bp, + uint32_t id) +{ + ATOM_ASIC_INTERNAL_SS_INFO_V2 *header_include; + ATOM_ASIC_SS_ASSIGNMENT_V2 *tbl; + uint32_t size; + uint32_t i; + + if (!DATA_TABLES(ASIC_InternalSS_Info)) + return 0; + + header_include = GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V2, + DATA_TABLES(ASIC_InternalSS_Info)); + + size = (le16_to_cpu(header_include->sHeader.usStructureSize) + - sizeof(ATOM_COMMON_TABLE_HEADER)) + / sizeof(ATOM_ASIC_SS_ASSIGNMENT_V2); + + tbl = (ATOM_ASIC_SS_ASSIGNMENT_V2 *) + &header_include->asSpreadSpectrum[0]; + for (i = 0; i < size; i++) + if (tbl[i].ucClockIndication == (uint8_t)id) + return 1; + + return 0; +} +/** + * get_ss_entry_number_from_internal_ss_info_table_V3_1 + * Get Number of SpreadSpectrum Entry from the ASIC_InternalSS_Info table of + * the VBIOS that matches id + * + * @param[in] id, spread sprectrum id + * @return number of SS Entry that match the id + */ +static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_V3_1( + struct bios_parser *bp, + uint32_t id) +{ + uint32_t number = 0; + ATOM_ASIC_INTERNAL_SS_INFO_V3 *header_include; + ATOM_ASIC_SS_ASSIGNMENT_V3 *tbl; + uint32_t size; + uint32_t i; + + if (!DATA_TABLES(ASIC_InternalSS_Info)) + return number; + + header_include = GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V3, + DATA_TABLES(ASIC_InternalSS_Info)); + size = (le16_to_cpu(header_include->sHeader.usStructureSize) - + sizeof(ATOM_COMMON_TABLE_HEADER)) / + sizeof(ATOM_ASIC_SS_ASSIGNMENT_V3); + + tbl = (ATOM_ASIC_SS_ASSIGNMENT_V3 *) + &header_include->asSpreadSpectrum[0]; + + for (i = 0; i < size; i++) + if (tbl[i].ucClockIndication == (uint8_t)id) + number++; + + return number; +} + +/** + * bios_parser_get_gpio_pin_info + * Get GpioPin information of input gpio id + * + * @param gpio_id, GPIO ID + * @param info, GpioPin information structure + * @return Bios parser result code + * @note + * to get the GPIO PIN INFO, we need: + * 1. get the GPIO_ID from other object table, see GetHPDInfo() + * 2. in DATA_TABLE.GPIO_Pin_LUT, search all records, to get the registerA + * offset/mask + */ +static enum bp_result bios_parser_get_gpio_pin_info( + struct dc_bios *dcb, + uint32_t gpio_id, + struct gpio_pin_info *info) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + ATOM_GPIO_PIN_LUT *header; + uint32_t count = 0; + uint32_t i = 0; + + if (!DATA_TABLES(GPIO_Pin_LUT)) + return BP_RESULT_BADBIOSTABLE; + + header = GET_IMAGE(ATOM_GPIO_PIN_LUT, DATA_TABLES(GPIO_Pin_LUT)); + if (!header) + return BP_RESULT_BADBIOSTABLE; + + if (sizeof(ATOM_COMMON_TABLE_HEADER) + sizeof(ATOM_GPIO_PIN_LUT) + > le16_to_cpu(header->sHeader.usStructureSize)) + return BP_RESULT_BADBIOSTABLE; + + if (1 != header->sHeader.ucTableContentRevision) + return BP_RESULT_UNSUPPORTED; + + count = (le16_to_cpu(header->sHeader.usStructureSize) + - sizeof(ATOM_COMMON_TABLE_HEADER)) + / sizeof(ATOM_GPIO_PIN_ASSIGNMENT); + for (i = 0; i < count; ++i) { + if (header->asGPIO_Pin[i].ucGPIO_ID != gpio_id) + continue; + + info->offset = + (uint32_t) le16_to_cpu(header->asGPIO_Pin[i].usGpioPin_AIndex); + info->offset_y = info->offset + 2; + info->offset_en = info->offset + 1; + info->offset_mask = info->offset - 1; + + info->mask = (uint32_t) (1 << + header->asGPIO_Pin[i].ucGpioPinBitShift); + info->mask_y = info->mask + 2; + info->mask_en = info->mask + 1; + info->mask_mask = info->mask - 1; + + return BP_RESULT_OK; + } + + return BP_RESULT_NORECORD; +} + +static enum bp_result get_gpio_i2c_info(struct bios_parser *bp, + ATOM_I2C_RECORD *record, + struct graphics_object_i2c_info *info) +{ + ATOM_GPIO_I2C_INFO *header; + uint32_t count = 0; + + if (!info) + return BP_RESULT_BADINPUT; + + /* get the GPIO_I2C info */ + if (!DATA_TABLES(GPIO_I2C_Info)) + return BP_RESULT_BADBIOSTABLE; + + header = GET_IMAGE(ATOM_GPIO_I2C_INFO, DATA_TABLES(GPIO_I2C_Info)); + if (!header) + return BP_RESULT_BADBIOSTABLE; + + if (sizeof(ATOM_COMMON_TABLE_HEADER) + sizeof(ATOM_GPIO_I2C_ASSIGMENT) + > le16_to_cpu(header->sHeader.usStructureSize)) + return BP_RESULT_BADBIOSTABLE; + + if (1 != header->sHeader.ucTableContentRevision) + return BP_RESULT_UNSUPPORTED; + + /* get data count */ + count = (le16_to_cpu(header->sHeader.usStructureSize) + - sizeof(ATOM_COMMON_TABLE_HEADER)) + / sizeof(ATOM_GPIO_I2C_ASSIGMENT); + if (count < record->sucI2cId.bfI2C_LineMux) + return BP_RESULT_BADBIOSTABLE; + + /* get the GPIO_I2C_INFO */ + info->i2c_hw_assist = record->sucI2cId.bfHW_Capable; + info->i2c_line = record->sucI2cId.bfI2C_LineMux; + info->i2c_engine_id = record->sucI2cId.bfHW_EngineID; + info->i2c_slave_address = record->ucI2CAddr; + + info->gpio_info.clk_mask_register_index = + le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkMaskRegisterIndex); + info->gpio_info.clk_en_register_index = + le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkEnRegisterIndex); + info->gpio_info.clk_y_register_index = + le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkY_RegisterIndex); + info->gpio_info.clk_a_register_index = + le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkA_RegisterIndex); + info->gpio_info.data_mask_register_index = + le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataMaskRegisterIndex); + info->gpio_info.data_en_register_index = + le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataEnRegisterIndex); + info->gpio_info.data_y_register_index = + le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataY_RegisterIndex); + info->gpio_info.data_a_register_index = + le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataA_RegisterIndex); + + info->gpio_info.clk_mask_shift = + header->asGPIO_Info[info->i2c_line].ucClkMaskShift; + info->gpio_info.clk_en_shift = + header->asGPIO_Info[info->i2c_line].ucClkEnShift; + info->gpio_info.clk_y_shift = + header->asGPIO_Info[info->i2c_line].ucClkY_Shift; + info->gpio_info.clk_a_shift = + header->asGPIO_Info[info->i2c_line].ucClkA_Shift; + info->gpio_info.data_mask_shift = + header->asGPIO_Info[info->i2c_line].ucDataMaskShift; + info->gpio_info.data_en_shift = + header->asGPIO_Info[info->i2c_line].ucDataEnShift; + info->gpio_info.data_y_shift = + header->asGPIO_Info[info->i2c_line].ucDataY_Shift; + info->gpio_info.data_a_shift = + header->asGPIO_Info[info->i2c_line].ucDataA_Shift; + + return BP_RESULT_OK; +} + +static ATOM_OBJECT *get_bios_object(struct bios_parser *bp, + struct graphics_object_id id) +{ + uint32_t offset; + ATOM_OBJECT_TABLE *tbl; + uint32_t i; + + switch (id.type) { + case OBJECT_TYPE_ENCODER: + offset = le16_to_cpu(bp->object_info_tbl.v1_1->usEncoderObjectTableOffset); + break; + + case OBJECT_TYPE_CONNECTOR: + offset = le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset); + break; + + case OBJECT_TYPE_ROUTER: + offset = le16_to_cpu(bp->object_info_tbl.v1_1->usRouterObjectTableOffset); + break; + + case OBJECT_TYPE_GENERIC: + if (bp->object_info_tbl.revision.minor < 3) + return NULL; + offset = le16_to_cpu(bp->object_info_tbl.v1_3->usMiscObjectTableOffset); + break; + + default: + return NULL; + } + + offset += bp->object_info_tbl_offset; + + tbl = GET_IMAGE(ATOM_OBJECT_TABLE, offset); + if (!tbl) + return NULL; + + for (i = 0; i < tbl->ucNumberOfObjects; i++) + if (dal_graphics_object_id_is_equal(id, + object_id_from_bios_object_id( + le16_to_cpu(tbl->asObjects[i].usObjectID)))) + return &tbl->asObjects[i]; + + return NULL; +} + +static uint32_t get_dest_obj_list(struct bios_parser *bp, + ATOM_OBJECT *object, uint16_t **id_list) +{ + uint32_t offset; + uint8_t *number; + + if (!object) { + BREAK_TO_DEBUGGER(); /* Invalid object id */ + return 0; + } + + offset = le16_to_cpu(object->usSrcDstTableOffset) + + bp->object_info_tbl_offset; + + number = GET_IMAGE(uint8_t, offset); + if (!number) + return 0; + + offset += sizeof(uint8_t); + offset += sizeof(uint16_t) * (*number); + + number = GET_IMAGE(uint8_t, offset); + if ((!number) || (!*number)) + return 0; + + offset += sizeof(uint8_t); + *id_list = (uint16_t *)get_image(&bp->base, offset, *number * sizeof(uint16_t)); + + if (!*id_list) + return 0; + + return *number; +} + +static uint32_t get_src_obj_list(struct bios_parser *bp, ATOM_OBJECT *object, + uint16_t **id_list) +{ + uint32_t offset; + uint8_t *number; + + if (!object) { + BREAK_TO_DEBUGGER(); /* Invalid object id */ + return 0; + } + + offset = le16_to_cpu(object->usSrcDstTableOffset) + + bp->object_info_tbl_offset; + + number = GET_IMAGE(uint8_t, offset); + if (!number) + return 0; + + offset += sizeof(uint8_t); + *id_list = (uint16_t *)get_image(&bp->base, offset, *number * sizeof(uint16_t)); + + if (!*id_list) + return 0; + + return *number; +} + +static uint32_t get_dst_number_from_object(struct bios_parser *bp, + ATOM_OBJECT *object) +{ + uint32_t offset; + uint8_t *number; + + if (!object) { + BREAK_TO_DEBUGGER(); /* Invalid encoder object id*/ + return 0; + } + + offset = le16_to_cpu(object->usSrcDstTableOffset) + + bp->object_info_tbl_offset; + + number = GET_IMAGE(uint8_t, offset); + if (!number) + return 0; + + offset += sizeof(uint8_t); + offset += sizeof(uint16_t) * (*number); + + number = GET_IMAGE(uint8_t, offset); + + if (!number) + return 0; + + return *number; +} + + +static struct graphics_object_id object_id_from_bios_object_id( + uint32_t bios_object_id) +{ + enum object_type type; + enum object_enum_id enum_id; + struct graphics_object_id go_id = { 0 }; + + type = object_type_from_bios_object_id(bios_object_id); + + if (OBJECT_TYPE_UNKNOWN == type) + return go_id; + + enum_id = enum_id_from_bios_object_id(bios_object_id); + + if (ENUM_ID_UNKNOWN == enum_id) + return go_id; + + go_id = dal_graphics_object_id_init( + id_from_bios_object_id(type, bios_object_id), enum_id, type); + + return go_id; +} + +static enum object_type object_type_from_bios_object_id(uint32_t bios_object_id) +{ + uint32_t bios_object_type = (bios_object_id & OBJECT_TYPE_MASK) + >> OBJECT_TYPE_SHIFT; + enum object_type object_type; + + switch (bios_object_type) { + case GRAPH_OBJECT_TYPE_GPU: + object_type = OBJECT_TYPE_GPU; + break; + case GRAPH_OBJECT_TYPE_ENCODER: + object_type = OBJECT_TYPE_ENCODER; + break; + case GRAPH_OBJECT_TYPE_CONNECTOR: + object_type = OBJECT_TYPE_CONNECTOR; + break; + case GRAPH_OBJECT_TYPE_ROUTER: + object_type = OBJECT_TYPE_ROUTER; + break; + case GRAPH_OBJECT_TYPE_GENERIC: + object_type = OBJECT_TYPE_GENERIC; + break; + default: + object_type = OBJECT_TYPE_UNKNOWN; + break; + } + + return object_type; +} + +static enum object_enum_id enum_id_from_bios_object_id(uint32_t bios_object_id) +{ + uint32_t bios_enum_id = + (bios_object_id & ENUM_ID_MASK) >> ENUM_ID_SHIFT; + enum object_enum_id id; + + switch (bios_enum_id) { + case GRAPH_OBJECT_ENUM_ID1: + id = ENUM_ID_1; + break; + case GRAPH_OBJECT_ENUM_ID2: + id = ENUM_ID_2; + break; + case GRAPH_OBJECT_ENUM_ID3: + id = ENUM_ID_3; + break; + case GRAPH_OBJECT_ENUM_ID4: + id = ENUM_ID_4; + break; + case GRAPH_OBJECT_ENUM_ID5: + id = ENUM_ID_5; + break; + case GRAPH_OBJECT_ENUM_ID6: + id = ENUM_ID_6; + break; + case GRAPH_OBJECT_ENUM_ID7: + id = ENUM_ID_7; + break; + default: + id = ENUM_ID_UNKNOWN; + break; + } + + return id; +} + +static uint32_t id_from_bios_object_id(enum object_type type, + uint32_t bios_object_id) +{ + switch (type) { + case OBJECT_TYPE_GPU: + return gpu_id_from_bios_object_id(bios_object_id); + case OBJECT_TYPE_ENCODER: + return (uint32_t)encoder_id_from_bios_object_id(bios_object_id); + case OBJECT_TYPE_CONNECTOR: + return (uint32_t)connector_id_from_bios_object_id( + bios_object_id); + case OBJECT_TYPE_GENERIC: + return generic_id_from_bios_object_id(bios_object_id); + default: + return 0; + } +} + +static enum connector_id connector_id_from_bios_object_id( + uint32_t bios_object_id) +{ + uint32_t bios_connector_id = gpu_id_from_bios_object_id(bios_object_id); + + enum connector_id id; + + switch (bios_connector_id) { + case CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I: + id = CONNECTOR_ID_SINGLE_LINK_DVII; + break; + case CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I: + id = CONNECTOR_ID_DUAL_LINK_DVII; + break; + case CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D: + id = CONNECTOR_ID_SINGLE_LINK_DVID; + break; + case CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D: + id = CONNECTOR_ID_DUAL_LINK_DVID; + break; + case CONNECTOR_OBJECT_ID_VGA: + id = CONNECTOR_ID_VGA; + break; + case CONNECTOR_OBJECT_ID_HDMI_TYPE_A: + id = CONNECTOR_ID_HDMI_TYPE_A; + break; + case CONNECTOR_OBJECT_ID_LVDS: + id = CONNECTOR_ID_LVDS; + break; + case CONNECTOR_OBJECT_ID_PCIE_CONNECTOR: + id = CONNECTOR_ID_PCIE; + break; + case CONNECTOR_OBJECT_ID_HARDCODE_DVI: + id = CONNECTOR_ID_HARDCODE_DVI; + break; + case CONNECTOR_OBJECT_ID_DISPLAYPORT: + id = CONNECTOR_ID_DISPLAY_PORT; + break; + case CONNECTOR_OBJECT_ID_eDP: + id = CONNECTOR_ID_EDP; + break; + case CONNECTOR_OBJECT_ID_MXM: + id = CONNECTOR_ID_MXM; + break; + default: + id = CONNECTOR_ID_UNKNOWN; + break; + } + + return id; +} + +static enum encoder_id encoder_id_from_bios_object_id(uint32_t bios_object_id) +{ + uint32_t bios_encoder_id = gpu_id_from_bios_object_id(bios_object_id); + enum encoder_id id; + + switch (bios_encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_LVDS: + id = ENCODER_ID_INTERNAL_LVDS; + break; + case ENCODER_OBJECT_ID_INTERNAL_TMDS1: + id = ENCODER_ID_INTERNAL_TMDS1; + break; + case ENCODER_OBJECT_ID_INTERNAL_TMDS2: + id = ENCODER_ID_INTERNAL_TMDS2; + break; + case ENCODER_OBJECT_ID_INTERNAL_DAC1: + id = ENCODER_ID_INTERNAL_DAC1; + break; + case ENCODER_OBJECT_ID_INTERNAL_DAC2: + id = ENCODER_ID_INTERNAL_DAC2; + break; + case ENCODER_OBJECT_ID_INTERNAL_LVTM1: + id = ENCODER_ID_INTERNAL_LVTM1; + break; + case ENCODER_OBJECT_ID_HDMI_INTERNAL: + id = ENCODER_ID_INTERNAL_HDMI; + break; + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: + id = ENCODER_ID_INTERNAL_KLDSCP_TMDS1; + break; + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: + id = ENCODER_ID_INTERNAL_KLDSCP_DAC1; + break; + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: + id = ENCODER_ID_INTERNAL_KLDSCP_DAC2; + break; + case ENCODER_OBJECT_ID_MVPU_FPGA: + id = ENCODER_ID_EXTERNAL_MVPU_FPGA; + break; + case ENCODER_OBJECT_ID_INTERNAL_DDI: + id = ENCODER_ID_INTERNAL_DDI; + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: + id = ENCODER_ID_INTERNAL_UNIPHY; + break; + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: + id = ENCODER_ID_INTERNAL_KLDSCP_LVTMA; + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: + id = ENCODER_ID_INTERNAL_UNIPHY1; + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: + id = ENCODER_ID_INTERNAL_UNIPHY2; + break; + case ENCODER_OBJECT_ID_ALMOND: /* ENCODER_OBJECT_ID_NUTMEG */ + id = ENCODER_ID_EXTERNAL_NUTMEG; + break; + case ENCODER_OBJECT_ID_TRAVIS: + id = ENCODER_ID_EXTERNAL_TRAVIS; + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3: + id = ENCODER_ID_INTERNAL_UNIPHY3; + break; + default: + id = ENCODER_ID_UNKNOWN; + ASSERT(0); + break; + } + + return id; +} + +uint32_t gpu_id_from_bios_object_id(uint32_t bios_object_id) +{ + return (bios_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; +} + +enum generic_id generic_id_from_bios_object_id(uint32_t bios_object_id) +{ + uint32_t bios_generic_id = gpu_id_from_bios_object_id(bios_object_id); + + enum generic_id id; + + switch (bios_generic_id) { + case GENERIC_OBJECT_ID_MXM_OPM: + id = GENERIC_ID_MXM_OPM; + break; + case GENERIC_OBJECT_ID_GLSYNC: + id = GENERIC_ID_GLSYNC; + break; + case GENERIC_OBJECT_ID_STEREO_PIN: + id = GENERIC_ID_STEREO; + break; + default: + id = GENERIC_ID_UNKNOWN; + break; + } + + return id; +} + +static struct device_id device_type_from_device_id(uint16_t device_id) +{ + + struct device_id result_device_id; + + switch (device_id) { + case ATOM_DEVICE_LCD1_SUPPORT: + result_device_id.device_type = DEVICE_TYPE_LCD; + result_device_id.enum_id = 1; + break; + + case ATOM_DEVICE_LCD2_SUPPORT: + result_device_id.device_type = DEVICE_TYPE_LCD; + result_device_id.enum_id = 2; + break; + + case ATOM_DEVICE_CRT1_SUPPORT: + result_device_id.device_type = DEVICE_TYPE_CRT; + result_device_id.enum_id = 1; + break; + + case ATOM_DEVICE_CRT2_SUPPORT: + result_device_id.device_type = DEVICE_TYPE_CRT; + result_device_id.enum_id = 2; + break; + + case ATOM_DEVICE_DFP1_SUPPORT: + result_device_id.device_type = DEVICE_TYPE_DFP; + result_device_id.enum_id = 1; + break; + + case ATOM_DEVICE_DFP2_SUPPORT: + result_device_id.device_type = DEVICE_TYPE_DFP; + result_device_id.enum_id = 2; + break; + + case ATOM_DEVICE_DFP3_SUPPORT: + result_device_id.device_type = DEVICE_TYPE_DFP; + result_device_id.enum_id = 3; + break; + + case ATOM_DEVICE_DFP4_SUPPORT: + result_device_id.device_type = DEVICE_TYPE_DFP; + result_device_id.enum_id = 4; + break; + + case ATOM_DEVICE_DFP5_SUPPORT: + result_device_id.device_type = DEVICE_TYPE_DFP; + result_device_id.enum_id = 5; + break; + + case ATOM_DEVICE_DFP6_SUPPORT: + result_device_id.device_type = DEVICE_TYPE_DFP; + result_device_id.enum_id = 6; + break; + + default: + BREAK_TO_DEBUGGER(); /* Invalid device Id */ + result_device_id.device_type = DEVICE_TYPE_UNKNOWN; + result_device_id.enum_id = 0; + } + return result_device_id; +} + +static void get_atom_data_table_revision( + ATOM_COMMON_TABLE_HEADER *atom_data_tbl, + struct atom_data_revision *tbl_revision) +{ + if (!tbl_revision) + return; + + /* initialize the revision to 0 which is invalid revision */ + tbl_revision->major = 0; + tbl_revision->minor = 0; + + if (!atom_data_tbl) + return; + + tbl_revision->major = + (uint32_t) GET_DATA_TABLE_MAJOR_REVISION(atom_data_tbl); + tbl_revision->minor = + (uint32_t) GET_DATA_TABLE_MINOR_REVISION(atom_data_tbl); +} + +static uint32_t signal_to_ss_id(enum as_signal_type signal) +{ + uint32_t clk_id_ss = 0; + + switch (signal) { + case AS_SIGNAL_TYPE_DVI: + clk_id_ss = ASIC_INTERNAL_SS_ON_TMDS; + break; + case AS_SIGNAL_TYPE_HDMI: + clk_id_ss = ASIC_INTERNAL_SS_ON_HDMI; + break; + case AS_SIGNAL_TYPE_LVDS: + clk_id_ss = ASIC_INTERNAL_SS_ON_LVDS; + break; + case AS_SIGNAL_TYPE_DISPLAY_PORT: + clk_id_ss = ASIC_INTERNAL_SS_ON_DP; + break; + case AS_SIGNAL_TYPE_GPU_PLL: + clk_id_ss = ASIC_INTERNAL_GPUPLL_SS; + break; + default: + break; + } + return clk_id_ss; +} + +static uint32_t get_support_mask_for_device_id(struct device_id device_id) +{ + enum dal_device_type device_type = device_id.device_type; + uint32_t enum_id = device_id.enum_id; + + switch (device_type) { + case DEVICE_TYPE_LCD: + switch (enum_id) { + case 1: + return ATOM_DEVICE_LCD1_SUPPORT; + case 2: + return ATOM_DEVICE_LCD2_SUPPORT; + default: + break; + } + break; + case DEVICE_TYPE_CRT: + switch (enum_id) { + case 1: + return ATOM_DEVICE_CRT1_SUPPORT; + case 2: + return ATOM_DEVICE_CRT2_SUPPORT; + default: + break; + } + break; + case DEVICE_TYPE_DFP: + switch (enum_id) { + case 1: + return ATOM_DEVICE_DFP1_SUPPORT; + case 2: + return ATOM_DEVICE_DFP2_SUPPORT; + case 3: + return ATOM_DEVICE_DFP3_SUPPORT; + case 4: + return ATOM_DEVICE_DFP4_SUPPORT; + case 5: + return ATOM_DEVICE_DFP5_SUPPORT; + case 6: + return ATOM_DEVICE_DFP6_SUPPORT; + default: + break; + } + break; + case DEVICE_TYPE_CV: + switch (enum_id) { + case 1: + return ATOM_DEVICE_CV_SUPPORT; + default: + break; + } + break; + case DEVICE_TYPE_TV: + switch (enum_id) { + case 1: + return ATOM_DEVICE_TV1_SUPPORT; + default: + break; + } + break; + default: + break; + }; + + /* Unidentified device ID, return empty support mask. */ + return 0; +} + +/** + * HwContext interface for writing MM registers + */ + +static bool i2c_read( + struct bios_parser *bp, + struct graphics_object_i2c_info *i2c_info, + uint8_t *buffer, + uint32_t length) +{ + struct ddc *ddc; + uint8_t offset[2] = { 0, 0 }; + bool result = false; + struct i2c_command cmd; + struct gpio_ddc_hw_info hw_info = { + i2c_info->i2c_hw_assist, + i2c_info->i2c_line }; + + ddc = dal_gpio_create_ddc(bp->base.ctx->gpio_service, + i2c_info->gpio_info.clk_a_register_index, + (1 << i2c_info->gpio_info.clk_a_shift), &hw_info); + + if (!ddc) + return result; + + /*Using SW engine */ + cmd.engine = I2C_COMMAND_ENGINE_SW; + cmd.speed = ddc->ctx->dc->caps.i2c_speed_in_khz; + + { + struct i2c_payload payloads[] = { + { + .address = i2c_info->i2c_slave_address >> 1, + .data = offset, + .length = sizeof(offset), + .write = true + }, + { + .address = i2c_info->i2c_slave_address >> 1, + .data = buffer, + .length = length, + .write = false + } + }; + + cmd.payloads = payloads; + cmd.number_of_payloads = ARRAY_SIZE(payloads); + + /* TODO route this through drm i2c_adapter */ + result = dal_i2caux_submit_i2c_command( + ddc->ctx->i2caux, + ddc, + &cmd); + } + + dal_gpio_destroy_ddc(&ddc); + + return result; +} + +/** + * Read external display connection info table through i2c. + * validate the GUID and checksum. + * + * @return enum bp_result whether all data was sucessfully read + */ +static enum bp_result get_ext_display_connection_info( + struct bios_parser *bp, + ATOM_OBJECT *opm_object, + ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO *ext_display_connection_info_tbl) +{ + bool config_tbl_present = false; + ATOM_I2C_RECORD *i2c_record = NULL; + uint32_t i = 0; + + if (opm_object == NULL) + return BP_RESULT_BADINPUT; + + i2c_record = get_i2c_record(bp, opm_object); + + if (i2c_record != NULL) { + ATOM_GPIO_I2C_INFO *gpio_i2c_header; + struct graphics_object_i2c_info i2c_info; + + gpio_i2c_header = GET_IMAGE(ATOM_GPIO_I2C_INFO, + bp->master_data_tbl->ListOfDataTables.GPIO_I2C_Info); + + if (NULL == gpio_i2c_header) + return BP_RESULT_BADBIOSTABLE; + + if (get_gpio_i2c_info(bp, i2c_record, &i2c_info) != + BP_RESULT_OK) + return BP_RESULT_BADBIOSTABLE; + + if (i2c_read(bp, + &i2c_info, + (uint8_t *)ext_display_connection_info_tbl, + sizeof(ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO))) { + config_tbl_present = true; + } + } + + /* Validate GUID */ + if (config_tbl_present) + for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; i++) { + if (ext_display_connection_info_tbl->ucGuid[i] + != ext_display_connection_guid[i]) { + config_tbl_present = false; + break; + } + } + + /* Validate checksum */ + if (config_tbl_present) { + uint8_t check_sum = 0; + uint8_t *buf = + (uint8_t *)ext_display_connection_info_tbl; + + for (i = 0; i < sizeof(ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO); + i++) { + check_sum += buf[i]; + } + + if (check_sum != 0) + config_tbl_present = false; + } + + if (config_tbl_present) + return BP_RESULT_OK; + else + return BP_RESULT_FAILURE; +} + +/* + * Gets the first device ID in the same group as the given ID for enumerating. + * For instance, if any DFP device ID is passed, returns the device ID for DFP1. + * + * The first device ID in the same group as the passed device ID, or 0 if no + * matching device group found. + */ +static uint32_t enum_first_device_id(uint32_t dev_id) +{ + /* Return the first in the group that this ID belongs to. */ + if (dev_id & ATOM_DEVICE_CRT_SUPPORT) + return ATOM_DEVICE_CRT1_SUPPORT; + else if (dev_id & ATOM_DEVICE_DFP_SUPPORT) + return ATOM_DEVICE_DFP1_SUPPORT; + else if (dev_id & ATOM_DEVICE_LCD_SUPPORT) + return ATOM_DEVICE_LCD1_SUPPORT; + else if (dev_id & ATOM_DEVICE_TV_SUPPORT) + return ATOM_DEVICE_TV1_SUPPORT; + else if (dev_id & ATOM_DEVICE_CV_SUPPORT) + return ATOM_DEVICE_CV_SUPPORT; + + /* No group found for this device ID. */ + + dm_error("%s: incorrect input %d\n", __func__, dev_id); + /* No matching support flag for given device ID */ + return 0; +} + +/* + * Gets the next device ID in the group for a given device ID. + * + * The current device ID being enumerated on. + * + * The next device ID in the group, or 0 if no device exists. + */ +static uint32_t enum_next_dev_id(uint32_t dev_id) +{ + /* Get next device ID in the group. */ + switch (dev_id) { + case ATOM_DEVICE_CRT1_SUPPORT: + return ATOM_DEVICE_CRT2_SUPPORT; + case ATOM_DEVICE_LCD1_SUPPORT: + return ATOM_DEVICE_LCD2_SUPPORT; + case ATOM_DEVICE_DFP1_SUPPORT: + return ATOM_DEVICE_DFP2_SUPPORT; + case ATOM_DEVICE_DFP2_SUPPORT: + return ATOM_DEVICE_DFP3_SUPPORT; + case ATOM_DEVICE_DFP3_SUPPORT: + return ATOM_DEVICE_DFP4_SUPPORT; + case ATOM_DEVICE_DFP4_SUPPORT: + return ATOM_DEVICE_DFP5_SUPPORT; + case ATOM_DEVICE_DFP5_SUPPORT: + return ATOM_DEVICE_DFP6_SUPPORT; + } + + /* Done enumerating through devices. */ + return 0; +} + +/* + * Returns the new device tag record for patched BIOS object. + * + * [IN] pExtDisplayPath - External display path to copy device tag from. + * [IN] deviceSupport - Bit vector for device ID support flags. + * [OUT] pDeviceTag - Device tag structure to fill with patched data. + * + * True if a compatible device ID was found, false otherwise. + */ +static bool get_patched_device_tag( + struct bios_parser *bp, + EXT_DISPLAY_PATH *ext_display_path, + uint32_t device_support, + ATOM_CONNECTOR_DEVICE_TAG *device_tag) +{ + uint32_t dev_id; + /* Use fallback behaviour if not supported. */ + if (!bp->remap_device_tags) { + device_tag->ulACPIDeviceEnum = + cpu_to_le32((uint32_t) le16_to_cpu(ext_display_path->usDeviceACPIEnum)); + device_tag->usDeviceID = + cpu_to_le16(le16_to_cpu(ext_display_path->usDeviceTag)); + return true; + } + + /* Find the first unused in the same group. */ + dev_id = enum_first_device_id(le16_to_cpu(ext_display_path->usDeviceTag)); + while (dev_id != 0) { + /* Assign this device ID if supported. */ + if ((device_support & dev_id) != 0) { + device_tag->ulACPIDeviceEnum = + cpu_to_le32((uint32_t) le16_to_cpu(ext_display_path->usDeviceACPIEnum)); + device_tag->usDeviceID = cpu_to_le16((USHORT) dev_id); + return true; + } + + dev_id = enum_next_dev_id(dev_id); + } + + /* No compatible device ID found. */ + return false; +} + +/* + * Adds a device tag to a BIOS object's device tag record if there is + * matching device ID supported. + * + * pObject - Pointer to the BIOS object to add the device tag to. + * pExtDisplayPath - Display path to retrieve base device ID from. + * pDeviceSupport - Pointer to bit vector for supported device IDs. + */ +static void add_device_tag_from_ext_display_path( + struct bios_parser *bp, + ATOM_OBJECT *object, + EXT_DISPLAY_PATH *ext_display_path, + uint32_t *device_support) +{ + /* Get device tag record for object. */ + ATOM_CONNECTOR_DEVICE_TAG *device_tag = NULL; + ATOM_CONNECTOR_DEVICE_TAG_RECORD *device_tag_record = NULL; + enum bp_result result = + bios_parser_get_device_tag_record( + bp, object, &device_tag_record); + + if ((le16_to_cpu(ext_display_path->usDeviceTag) != CONNECTOR_OBJECT_ID_NONE) + && (result == BP_RESULT_OK)) { + uint8_t index; + + if ((device_tag_record->ucNumberOfDevice == 1) && + (le16_to_cpu(device_tag_record->asDeviceTag[0].usDeviceID) == 0)) { + /*Workaround bug in current VBIOS releases where + * ucNumberOfDevice = 1 but there is no actual device + * tag data. This w/a is temporary until the updated + * VBIOS is distributed. */ + device_tag_record->ucNumberOfDevice = + device_tag_record->ucNumberOfDevice - 1; + } + + /* Attempt to find a matching device ID. */ + index = device_tag_record->ucNumberOfDevice; + device_tag = &device_tag_record->asDeviceTag[index]; + if (get_patched_device_tag( + bp, + ext_display_path, + *device_support, + device_tag)) { + /* Update cached device support to remove assigned ID. + */ + *device_support &= ~le16_to_cpu(device_tag->usDeviceID); + device_tag_record->ucNumberOfDevice++; + } + } +} + +/* + * Read out a single EXT_DISPLAY_PATH from the external display connection info + * table. The specific entry in the table is determined by the enum_id passed + * in. + * + * EXT_DISPLAY_PATH describing a single Configuration table entry + */ + +#define INVALID_CONNECTOR 0xffff + +static EXT_DISPLAY_PATH *get_ext_display_path_entry( + ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO *config_table, + uint32_t bios_object_id) +{ + EXT_DISPLAY_PATH *ext_display_path; + uint32_t ext_display_path_index = + ((bios_object_id & ENUM_ID_MASK) >> ENUM_ID_SHIFT) - 1; + + if (ext_display_path_index >= MAX_NUMBER_OF_EXT_DISPLAY_PATH) + return NULL; + + ext_display_path = &config_table->sPath[ext_display_path_index]; + + if (le16_to_cpu(ext_display_path->usDeviceConnector) == INVALID_CONNECTOR) + ext_display_path->usDeviceConnector = cpu_to_le16(0); + + return ext_display_path; +} + +/* + * Get AUX/DDC information of input object id + * + * search all records to find the ATOM_CONNECTOR_AUXDDC_LUT_RECORD_TYPE record + * IR + */ +static ATOM_CONNECTOR_AUXDDC_LUT_RECORD *get_ext_connector_aux_ddc_lut_record( + struct bios_parser *bp, + ATOM_OBJECT *object) +{ + uint32_t offset; + ATOM_COMMON_RECORD_HEADER *header; + + if (!object) { + BREAK_TO_DEBUGGER(); + /* Invalid object */ + return NULL; + } + + offset = le16_to_cpu(object->usRecordOffset) + + bp->object_info_tbl_offset; + + for (;;) { + header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset); + + if (!header) + return NULL; + + if (LAST_RECORD_TYPE == header->ucRecordType || + 0 == header->ucRecordSize) + break; + + if (ATOM_CONNECTOR_AUXDDC_LUT_RECORD_TYPE == + header->ucRecordType && + sizeof(ATOM_CONNECTOR_AUXDDC_LUT_RECORD) <= + header->ucRecordSize) + return (ATOM_CONNECTOR_AUXDDC_LUT_RECORD *)(header); + + offset += header->ucRecordSize; + } + + return NULL; +} + +/* + * Get AUX/DDC information of input object id + * + * search all records to find the ATOM_CONNECTOR_AUXDDC_LUT_RECORD_TYPE record + * IR + */ +static ATOM_CONNECTOR_HPDPIN_LUT_RECORD *get_ext_connector_hpd_pin_lut_record( + struct bios_parser *bp, + ATOM_OBJECT *object) +{ + uint32_t offset; + ATOM_COMMON_RECORD_HEADER *header; + + if (!object) { + BREAK_TO_DEBUGGER(); + /* Invalid object */ + return NULL; + } + + offset = le16_to_cpu(object->usRecordOffset) + + bp->object_info_tbl_offset; + + for (;;) { + header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset); + + if (!header) + return NULL; + + if (LAST_RECORD_TYPE == header->ucRecordType || + 0 == header->ucRecordSize) + break; + + if (ATOM_CONNECTOR_HPDPIN_LUT_RECORD_TYPE == + header->ucRecordType && + sizeof(ATOM_CONNECTOR_HPDPIN_LUT_RECORD) <= + header->ucRecordSize) + return (ATOM_CONNECTOR_HPDPIN_LUT_RECORD *)header; + + offset += header->ucRecordSize; + } + + return NULL; +} + +/* + * Check whether we need to patch the VBIOS connector info table with + * data from an external display connection info table. This is + * necessary to support MXM boards with an OPM (output personality + * module). With these designs, the VBIOS connector info table + * specifies an MXM_CONNECTOR with a unique ID. The driver retrieves + * the external connection info table through i2c and then looks up the + * connector ID to find the real connector type (e.g. DFP1). + * + */ +static enum bp_result patch_bios_image_from_ext_display_connection_info( + struct bios_parser *bp) +{ + ATOM_OBJECT_TABLE *connector_tbl; + uint32_t connector_tbl_offset; + struct graphics_object_id object_id; + ATOM_OBJECT *object; + ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO ext_display_connection_info_tbl; + EXT_DISPLAY_PATH *ext_display_path; + ATOM_CONNECTOR_AUXDDC_LUT_RECORD *aux_ddc_lut_record = NULL; + ATOM_I2C_RECORD *i2c_record = NULL; + ATOM_CONNECTOR_HPDPIN_LUT_RECORD *hpd_pin_lut_record = NULL; + ATOM_HPD_INT_RECORD *hpd_record = NULL; + ATOM_OBJECT_TABLE *encoder_table; + uint32_t encoder_table_offset; + ATOM_OBJECT *opm_object = NULL; + uint32_t i = 0; + struct graphics_object_id opm_object_id = + dal_graphics_object_id_init( + GENERIC_ID_MXM_OPM, + ENUM_ID_1, + OBJECT_TYPE_GENERIC); + ATOM_CONNECTOR_DEVICE_TAG_RECORD *dev_tag_record; + uint32_t cached_device_support = + le16_to_cpu(bp->object_info_tbl.v1_1->usDeviceSupport); + + uint32_t dst_number; + uint16_t *dst_object_id_list; + + opm_object = get_bios_object(bp, opm_object_id); + if (!opm_object) + return BP_RESULT_UNSUPPORTED; + + memset(&ext_display_connection_info_tbl, 0, + sizeof(ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO)); + + connector_tbl_offset = bp->object_info_tbl_offset + + le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset); + connector_tbl = GET_IMAGE(ATOM_OBJECT_TABLE, connector_tbl_offset); + + /* Read Connector info table from EEPROM through i2c */ + if (get_ext_display_connection_info(bp, + opm_object, + &ext_display_connection_info_tbl) != BP_RESULT_OK) { + + dm_logger_write(bp->base.ctx->logger, LOG_BIOS, + "%s: Failed to read Connection Info Table", __func__); + return BP_RESULT_UNSUPPORTED; + } + + /* Get pointer to AUX/DDC and HPD LUTs */ + aux_ddc_lut_record = + get_ext_connector_aux_ddc_lut_record(bp, opm_object); + hpd_pin_lut_record = + get_ext_connector_hpd_pin_lut_record(bp, opm_object); + + if ((aux_ddc_lut_record == NULL) || (hpd_pin_lut_record == NULL)) + return BP_RESULT_UNSUPPORTED; + + /* Cache support bits for currently unmapped device types. */ + if (bp->remap_device_tags) { + for (i = 0; i < connector_tbl->ucNumberOfObjects; ++i) { + uint32_t j; + /* Remove support for all non-MXM connectors. */ + object = &connector_tbl->asObjects[i]; + object_id = object_id_from_bios_object_id( + le16_to_cpu(object->usObjectID)); + if ((OBJECT_TYPE_CONNECTOR != object_id.type) || + (CONNECTOR_ID_MXM == object_id.id)) + continue; + + /* Remove support for all device tags. */ + if (bios_parser_get_device_tag_record( + bp, object, &dev_tag_record) != BP_RESULT_OK) + continue; + + for (j = 0; j < dev_tag_record->ucNumberOfDevice; ++j) { + ATOM_CONNECTOR_DEVICE_TAG *device_tag = + &dev_tag_record->asDeviceTag[j]; + cached_device_support &= + ~le16_to_cpu(device_tag->usDeviceID); + } + } + } + + /* Find all MXM connector objects and patch them with connector info + * from the external display connection info table. */ + for (i = 0; i < connector_tbl->ucNumberOfObjects; i++) { + uint32_t j; + + object = &connector_tbl->asObjects[i]; + object_id = object_id_from_bios_object_id(le16_to_cpu(object->usObjectID)); + if ((OBJECT_TYPE_CONNECTOR != object_id.type) || + (CONNECTOR_ID_MXM != object_id.id)) + continue; + + /* Get the correct connection info table entry based on the enum + * id. */ + ext_display_path = get_ext_display_path_entry( + &ext_display_connection_info_tbl, + le16_to_cpu(object->usObjectID)); + if (!ext_display_path) + return BP_RESULT_FAILURE; + + /* Patch device connector ID */ + object->usObjectID = + cpu_to_le16(le16_to_cpu(ext_display_path->usDeviceConnector)); + + /* Patch device tag, ulACPIDeviceEnum. */ + add_device_tag_from_ext_display_path( + bp, + object, + ext_display_path, + &cached_device_support); + + /* Patch HPD info */ + if (ext_display_path->ucExtHPDPINLutIndex < + MAX_NUMBER_OF_EXT_HPDPIN_LUT_ENTRIES) { + hpd_record = get_hpd_record(bp, object); + if (hpd_record) { + uint8_t index = + ext_display_path->ucExtHPDPINLutIndex; + hpd_record->ucHPDIntGPIOID = + hpd_pin_lut_record->ucHPDPINMap[index]; + } else { + BREAK_TO_DEBUGGER(); + /* Invalid hpd record */ + return BP_RESULT_FAILURE; + } + } + + /* Patch I2C/AUX info */ + if (ext_display_path->ucExtHPDPINLutIndex < + MAX_NUMBER_OF_EXT_AUXDDC_LUT_ENTRIES) { + i2c_record = get_i2c_record(bp, object); + if (i2c_record) { + uint8_t index = + ext_display_path->ucExtAUXDDCLutIndex; + i2c_record->sucI2cId = + aux_ddc_lut_record->ucAUXDDCMap[index]; + } else { + BREAK_TO_DEBUGGER(); + /* Invalid I2C record */ + return BP_RESULT_FAILURE; + } + } + + /* Merge with other MXM connectors that map to the same physical + * connector. */ + for (j = i + 1; + j < connector_tbl->ucNumberOfObjects; j++) { + ATOM_OBJECT *next_object; + struct graphics_object_id next_object_id; + EXT_DISPLAY_PATH *next_ext_display_path; + + next_object = &connector_tbl->asObjects[j]; + next_object_id = object_id_from_bios_object_id( + le16_to_cpu(next_object->usObjectID)); + + if ((OBJECT_TYPE_CONNECTOR != next_object_id.type) && + (CONNECTOR_ID_MXM == next_object_id.id)) + continue; + + next_ext_display_path = get_ext_display_path_entry( + &ext_display_connection_info_tbl, + le16_to_cpu(next_object->usObjectID)); + + if (next_ext_display_path == NULL) + return BP_RESULT_FAILURE; + + /* Merge if using same connector. */ + if ((le16_to_cpu(next_ext_display_path->usDeviceConnector) == + le16_to_cpu(ext_display_path->usDeviceConnector)) && + (le16_to_cpu(ext_display_path->usDeviceConnector) != 0)) { + /* Clear duplicate connector from table. */ + next_object->usObjectID = cpu_to_le16(0); + add_device_tag_from_ext_display_path( + bp, + object, + ext_display_path, + &cached_device_support); + } + } + } + + /* Find all encoders which have an MXM object as their destination. + * Replace the MXM object with the real connector Id from the external + * display connection info table */ + + encoder_table_offset = bp->object_info_tbl_offset + + le16_to_cpu(bp->object_info_tbl.v1_1->usEncoderObjectTableOffset); + encoder_table = GET_IMAGE(ATOM_OBJECT_TABLE, encoder_table_offset); + + for (i = 0; i < encoder_table->ucNumberOfObjects; i++) { + uint32_t j; + + object = &encoder_table->asObjects[i]; + + dst_number = get_dest_obj_list(bp, object, &dst_object_id_list); + + for (j = 0; j < dst_number; j++) { + object_id = object_id_from_bios_object_id( + dst_object_id_list[j]); + + if ((OBJECT_TYPE_CONNECTOR != object_id.type) || + (CONNECTOR_ID_MXM != object_id.id)) + continue; + + /* Get the correct connection info table entry based on + * the enum id. */ + ext_display_path = + get_ext_display_path_entry( + &ext_display_connection_info_tbl, + dst_object_id_list[j]); + + if (ext_display_path == NULL) + return BP_RESULT_FAILURE; + + dst_object_id_list[j] = + le16_to_cpu(ext_display_path->usDeviceConnector); + } + } + + return BP_RESULT_OK; +} + +/* + * Check whether we need to patch the VBIOS connector info table with + * data from an external display connection info table. This is + * necessary to support MXM boards with an OPM (output personality + * module). With these designs, the VBIOS connector info table + * specifies an MXM_CONNECTOR with a unique ID. The driver retrieves + * the external connection info table through i2c and then looks up the + * connector ID to find the real connector type (e.g. DFP1). + * + */ + +static void process_ext_display_connection_info(struct bios_parser *bp) +{ + ATOM_OBJECT_TABLE *connector_tbl; + uint32_t connector_tbl_offset; + struct graphics_object_id object_id; + ATOM_OBJECT *object; + bool mxm_connector_found = false; + bool null_entry_found = false; + uint32_t i = 0; + + connector_tbl_offset = bp->object_info_tbl_offset + + le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset); + connector_tbl = GET_IMAGE(ATOM_OBJECT_TABLE, connector_tbl_offset); + + /* Look for MXM connectors to determine whether we need patch the VBIOS + * connector info table. Look for null entries to determine whether we + * need to compact connector table. */ + for (i = 0; i < connector_tbl->ucNumberOfObjects; i++) { + object = &connector_tbl->asObjects[i]; + object_id = object_id_from_bios_object_id(le16_to_cpu(object->usObjectID)); + + if ((OBJECT_TYPE_CONNECTOR == object_id.type) && + (CONNECTOR_ID_MXM == object_id.id)) { + /* Once we found MXM connector - we can break */ + mxm_connector_found = true; + break; + } else if (OBJECT_TYPE_CONNECTOR != object_id.type) { + /* We need to continue looping - to check if MXM + * connector present */ + null_entry_found = true; + } + } + + /* Patch BIOS image */ + if (mxm_connector_found || null_entry_found) { + uint32_t connectors_num = 0; + uint8_t *original_bios; + /* Step 1: Replace bios image with the new copy which will be + * patched */ + bp->base.bios_local_image = dm_alloc(bp->base.bios_size); + if (bp->base.bios_local_image == NULL) { + BREAK_TO_DEBUGGER(); + /* Failed to alloc bp->base.bios_local_image */ + return; + } + + memmove(bp->base.bios_local_image, bp->base.bios, bp->base.bios_size); + original_bios = bp->base.bios; + bp->base.bios = bp->base.bios_local_image; + connector_tbl = + GET_IMAGE(ATOM_OBJECT_TABLE, connector_tbl_offset); + + /* Step 2: (only if MXM connector found) Patch BIOS image with + * info from external module */ + if (mxm_connector_found && + patch_bios_image_from_ext_display_connection_info(bp) != + BP_RESULT_OK) { + /* Patching the bios image has failed. We will copy + * again original image provided and afterwards + * only remove null entries */ + memmove( + bp->base.bios_local_image, + original_bios, + bp->base.bios_size); + } + + /* Step 3: Compact connector table (remove null entries, valid + * entries moved to beginning) */ + for (i = 0; i < connector_tbl->ucNumberOfObjects; i++) { + object = &connector_tbl->asObjects[i]; + object_id = object_id_from_bios_object_id( + le16_to_cpu(object->usObjectID)); + + if (OBJECT_TYPE_CONNECTOR != object_id.type) + continue; + + if (i != connectors_num) { + memmove( + &connector_tbl-> + asObjects[connectors_num], + object, + sizeof(ATOM_OBJECT)); + } + ++connectors_num; + } + connector_tbl->ucNumberOfObjects = (uint8_t)connectors_num; + } +} + +static void bios_parser_post_init(struct dc_bios *dcb) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + process_ext_display_connection_info(bp); +} + +/** + * bios_parser_set_scratch_critical_state + * + * @brief + * update critical state bit in VBIOS scratch register + * + * @param + * bool - to set or reset state + */ +static void bios_parser_set_scratch_critical_state( + struct dc_bios *dcb, + bool state) +{ + bios_set_scratch_critical_state(dcb, state); +} + +/* + * get_integrated_info_v8 + * + * @brief + * Get V8 integrated BIOS information + * + * @param + * bios_parser *bp - [in]BIOS parser handler to get master data table + * integrated_info *info - [out] store and output integrated info + * + * @return + * enum bp_result - BP_RESULT_OK if information is available, + * BP_RESULT_BADBIOSTABLE otherwise. + */ +static enum bp_result get_integrated_info_v8( + struct bios_parser *bp, + struct integrated_info *info) +{ + ATOM_INTEGRATED_SYSTEM_INFO_V1_8 *info_v8; + uint32_t i; + + info_v8 = GET_IMAGE(ATOM_INTEGRATED_SYSTEM_INFO_V1_8, + bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo); + + if (info_v8 == NULL) + return BP_RESULT_BADBIOSTABLE; + info->boot_up_engine_clock = le32_to_cpu(info_v8->ulBootUpEngineClock) * 10; + info->dentist_vco_freq = le32_to_cpu(info_v8->ulDentistVCOFreq) * 10; + info->boot_up_uma_clock = le32_to_cpu(info_v8->ulBootUpUMAClock) * 10; + + for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) { + /* Convert [10KHz] into [KHz] */ + info->disp_clk_voltage[i].max_supported_clk = + le32_to_cpu(info_v8->sDISPCLK_Voltage[i]. + ulMaximumSupportedCLK) * 10; + info->disp_clk_voltage[i].voltage_index = + le32_to_cpu(info_v8->sDISPCLK_Voltage[i].ulVoltageIndex); + } + + info->boot_up_req_display_vector = + le32_to_cpu(info_v8->ulBootUpReqDisplayVector); + info->gpu_cap_info = + le32_to_cpu(info_v8->ulGPUCapInfo); + + /* + * system_config: Bit[0] = 0 : PCIE power gating disabled + * = 1 : PCIE power gating enabled + * Bit[1] = 0 : DDR-PLL shut down disabled + * = 1 : DDR-PLL shut down enabled + * Bit[2] = 0 : DDR-PLL power down disabled + * = 1 : DDR-PLL power down enabled + */ + info->system_config = le32_to_cpu(info_v8->ulSystemConfig); + info->cpu_cap_info = le32_to_cpu(info_v8->ulCPUCapInfo); + info->boot_up_nb_voltage = + le16_to_cpu(info_v8->usBootUpNBVoltage); + info->ext_disp_conn_info_offset = + le16_to_cpu(info_v8->usExtDispConnInfoOffset); + info->memory_type = info_v8->ucMemoryType; + info->ma_channel_number = info_v8->ucUMAChannelNumber; + info->gmc_restore_reset_time = + le32_to_cpu(info_v8->ulGMCRestoreResetTime); + + info->minimum_n_clk = + le32_to_cpu(info_v8->ulNbpStateNClkFreq[0]); + for (i = 1; i < 4; ++i) + info->minimum_n_clk = + info->minimum_n_clk < le32_to_cpu(info_v8->ulNbpStateNClkFreq[i]) ? + info->minimum_n_clk : le32_to_cpu(info_v8->ulNbpStateNClkFreq[i]); + + info->idle_n_clk = le32_to_cpu(info_v8->ulIdleNClk); + info->ddr_dll_power_up_time = + le32_to_cpu(info_v8->ulDDR_DLL_PowerUpTime); + info->ddr_pll_power_up_time = + le32_to_cpu(info_v8->ulDDR_PLL_PowerUpTime); + info->pcie_clk_ss_type = le16_to_cpu(info_v8->usPCIEClkSSType); + info->lvds_ss_percentage = + le16_to_cpu(info_v8->usLvdsSSPercentage); + info->lvds_sspread_rate_in_10hz = + le16_to_cpu(info_v8->usLvdsSSpreadRateIn10Hz); + info->hdmi_ss_percentage = + le16_to_cpu(info_v8->usHDMISSPercentage); + info->hdmi_sspread_rate_in_10hz = + le16_to_cpu(info_v8->usHDMISSpreadRateIn10Hz); + info->dvi_ss_percentage = + le16_to_cpu(info_v8->usDVISSPercentage); + info->dvi_sspread_rate_in_10_hz = + le16_to_cpu(info_v8->usDVISSpreadRateIn10Hz); + + info->max_lvds_pclk_freq_in_single_link = + le16_to_cpu(info_v8->usMaxLVDSPclkFreqInSingleLink); + info->lvds_misc = info_v8->ucLvdsMisc; + info->lvds_pwr_on_seq_dig_on_to_de_in_4ms = + info_v8->ucLVDSPwrOnSeqDIGONtoDE_in4Ms; + info->lvds_pwr_on_seq_de_to_vary_bl_in_4ms = + info_v8->ucLVDSPwrOnSeqDEtoVARY_BL_in4Ms; + info->lvds_pwr_on_seq_vary_bl_to_blon_in_4ms = + info_v8->ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms; + info->lvds_pwr_off_seq_vary_bl_to_de_in4ms = + info_v8->ucLVDSPwrOffSeqVARY_BLtoDE_in4Ms; + info->lvds_pwr_off_seq_de_to_dig_on_in4ms = + info_v8->ucLVDSPwrOffSeqDEtoDIGON_in4Ms; + info->lvds_pwr_off_seq_blon_to_vary_bl_in_4ms = + info_v8->ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms; + info->lvds_off_to_on_delay_in_4ms = + info_v8->ucLVDSOffToOnDelay_in4Ms; + info->lvds_bit_depth_control_val = + le32_to_cpu(info_v8->ulLCDBitDepthControlVal); + + for (i = 0; i < NUMBER_OF_AVAILABLE_SCLK; ++i) { + /* Convert [10KHz] into [KHz] */ + info->avail_s_clk[i].supported_s_clk = + le32_to_cpu(info_v8->sAvail_SCLK[i].ulSupportedSCLK) * 10; + info->avail_s_clk[i].voltage_index = + le16_to_cpu(info_v8->sAvail_SCLK[i].usVoltageIndex); + info->avail_s_clk[i].voltage_id = + le16_to_cpu(info_v8->sAvail_SCLK[i].usVoltageID); + } + + for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) { + info->ext_disp_conn_info.gu_id[i] = + info_v8->sExtDispConnInfo.ucGuid[i]; + } + + for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) { + info->ext_disp_conn_info.path[i].device_connector_id = + object_id_from_bios_object_id( + le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usDeviceConnector)); + + info->ext_disp_conn_info.path[i].ext_encoder_obj_id = + object_id_from_bios_object_id( + le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usExtEncoderObjId)); + + info->ext_disp_conn_info.path[i].device_tag = + le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usDeviceTag); + info->ext_disp_conn_info.path[i].device_acpi_enum = + le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usDeviceACPIEnum); + info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index = + info_v8->sExtDispConnInfo.sPath[i].ucExtAUXDDCLutIndex; + info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index = + info_v8->sExtDispConnInfo.sPath[i].ucExtHPDPINLutIndex; + info->ext_disp_conn_info.path[i].channel_mapping.raw = + info_v8->sExtDispConnInfo.sPath[i].ucChannelMapping; + } + info->ext_disp_conn_info.checksum = + info_v8->sExtDispConnInfo.ucChecksum; + + return BP_RESULT_OK; +} + +/* + * get_integrated_info_v8 + * + * @brief + * Get V8 integrated BIOS information + * + * @param + * bios_parser *bp - [in]BIOS parser handler to get master data table + * integrated_info *info - [out] store and output integrated info + * + * @return + * enum bp_result - BP_RESULT_OK if information is available, + * BP_RESULT_BADBIOSTABLE otherwise. + */ +static enum bp_result get_integrated_info_v9( + struct bios_parser *bp, + struct integrated_info *info) +{ + ATOM_INTEGRATED_SYSTEM_INFO_V1_9 *info_v9; + uint32_t i; + + info_v9 = GET_IMAGE(ATOM_INTEGRATED_SYSTEM_INFO_V1_9, + bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo); + + if (!info_v9) + return BP_RESULT_BADBIOSTABLE; + + info->boot_up_engine_clock = le32_to_cpu(info_v9->ulBootUpEngineClock) * 10; + info->dentist_vco_freq = le32_to_cpu(info_v9->ulDentistVCOFreq) * 10; + info->boot_up_uma_clock = le32_to_cpu(info_v9->ulBootUpUMAClock) * 10; + + for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) { + /* Convert [10KHz] into [KHz] */ + info->disp_clk_voltage[i].max_supported_clk = + le32_to_cpu(info_v9->sDISPCLK_Voltage[i].ulMaximumSupportedCLK) * 10; + info->disp_clk_voltage[i].voltage_index = + le32_to_cpu(info_v9->sDISPCLK_Voltage[i].ulVoltageIndex); + } + + info->boot_up_req_display_vector = + le32_to_cpu(info_v9->ulBootUpReqDisplayVector); + info->gpu_cap_info = le32_to_cpu(info_v9->ulGPUCapInfo); + + /* + * system_config: Bit[0] = 0 : PCIE power gating disabled + * = 1 : PCIE power gating enabled + * Bit[1] = 0 : DDR-PLL shut down disabled + * = 1 : DDR-PLL shut down enabled + * Bit[2] = 0 : DDR-PLL power down disabled + * = 1 : DDR-PLL power down enabled + */ + info->system_config = le32_to_cpu(info_v9->ulSystemConfig); + info->cpu_cap_info = le32_to_cpu(info_v9->ulCPUCapInfo); + info->boot_up_nb_voltage = le16_to_cpu(info_v9->usBootUpNBVoltage); + info->ext_disp_conn_info_offset = le16_to_cpu(info_v9->usExtDispConnInfoOffset); + info->memory_type = info_v9->ucMemoryType; + info->ma_channel_number = info_v9->ucUMAChannelNumber; + info->gmc_restore_reset_time = le32_to_cpu(info_v9->ulGMCRestoreResetTime); + + info->minimum_n_clk = le32_to_cpu(info_v9->ulNbpStateNClkFreq[0]); + for (i = 1; i < 4; ++i) + info->minimum_n_clk = + info->minimum_n_clk < le32_to_cpu(info_v9->ulNbpStateNClkFreq[i]) ? + info->minimum_n_clk : le32_to_cpu(info_v9->ulNbpStateNClkFreq[i]); + + info->idle_n_clk = le32_to_cpu(info_v9->ulIdleNClk); + info->ddr_dll_power_up_time = le32_to_cpu(info_v9->ulDDR_DLL_PowerUpTime); + info->ddr_pll_power_up_time = le32_to_cpu(info_v9->ulDDR_PLL_PowerUpTime); + info->pcie_clk_ss_type = le16_to_cpu(info_v9->usPCIEClkSSType); + info->lvds_ss_percentage = le16_to_cpu(info_v9->usLvdsSSPercentage); + info->lvds_sspread_rate_in_10hz = le16_to_cpu(info_v9->usLvdsSSpreadRateIn10Hz); + info->hdmi_ss_percentage = le16_to_cpu(info_v9->usHDMISSPercentage); + info->hdmi_sspread_rate_in_10hz = le16_to_cpu(info_v9->usHDMISSpreadRateIn10Hz); + info->dvi_ss_percentage = le16_to_cpu(info_v9->usDVISSPercentage); + info->dvi_sspread_rate_in_10_hz = le16_to_cpu(info_v9->usDVISSpreadRateIn10Hz); + + info->max_lvds_pclk_freq_in_single_link = + le16_to_cpu(info_v9->usMaxLVDSPclkFreqInSingleLink); + info->lvds_misc = info_v9->ucLvdsMisc; + info->lvds_pwr_on_seq_dig_on_to_de_in_4ms = + info_v9->ucLVDSPwrOnSeqDIGONtoDE_in4Ms; + info->lvds_pwr_on_seq_de_to_vary_bl_in_4ms = + info_v9->ucLVDSPwrOnSeqDEtoVARY_BL_in4Ms; + info->lvds_pwr_on_seq_vary_bl_to_blon_in_4ms = + info_v9->ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms; + info->lvds_pwr_off_seq_vary_bl_to_de_in4ms = + info_v9->ucLVDSPwrOffSeqVARY_BLtoDE_in4Ms; + info->lvds_pwr_off_seq_de_to_dig_on_in4ms = + info_v9->ucLVDSPwrOffSeqDEtoDIGON_in4Ms; + info->lvds_pwr_off_seq_blon_to_vary_bl_in_4ms = + info_v9->ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms; + info->lvds_off_to_on_delay_in_4ms = + info_v9->ucLVDSOffToOnDelay_in4Ms; + info->lvds_bit_depth_control_val = + le32_to_cpu(info_v9->ulLCDBitDepthControlVal); + + for (i = 0; i < NUMBER_OF_AVAILABLE_SCLK; ++i) { + /* Convert [10KHz] into [KHz] */ + info->avail_s_clk[i].supported_s_clk = + le32_to_cpu(info_v9->sAvail_SCLK[i].ulSupportedSCLK) * 10; + info->avail_s_clk[i].voltage_index = + le16_to_cpu(info_v9->sAvail_SCLK[i].usVoltageIndex); + info->avail_s_clk[i].voltage_id = + le16_to_cpu(info_v9->sAvail_SCLK[i].usVoltageID); + } + + for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) { + info->ext_disp_conn_info.gu_id[i] = + info_v9->sExtDispConnInfo.ucGuid[i]; + } + + for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) { + info->ext_disp_conn_info.path[i].device_connector_id = + object_id_from_bios_object_id( + le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usDeviceConnector)); + + info->ext_disp_conn_info.path[i].ext_encoder_obj_id = + object_id_from_bios_object_id( + le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usExtEncoderObjId)); + + info->ext_disp_conn_info.path[i].device_tag = + le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usDeviceTag); + info->ext_disp_conn_info.path[i].device_acpi_enum = + le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usDeviceACPIEnum); + info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index = + info_v9->sExtDispConnInfo.sPath[i].ucExtAUXDDCLutIndex; + info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index = + info_v9->sExtDispConnInfo.sPath[i].ucExtHPDPINLutIndex; + info->ext_disp_conn_info.path[i].channel_mapping.raw = + info_v9->sExtDispConnInfo.sPath[i].ucChannelMapping; + } + info->ext_disp_conn_info.checksum = + info_v9->sExtDispConnInfo.ucChecksum; + + return BP_RESULT_OK; +} + +/* + * construct_integrated_info + * + * @brief + * Get integrated BIOS information based on table revision + * + * @param + * bios_parser *bp - [in]BIOS parser handler to get master data table + * integrated_info *info - [out] store and output integrated info + * + * @return + * enum bp_result - BP_RESULT_OK if information is available, + * BP_RESULT_BADBIOSTABLE otherwise. + */ +static enum bp_result construct_integrated_info( + struct bios_parser *bp, + struct integrated_info *info) +{ + enum bp_result result = BP_RESULT_BADBIOSTABLE; + + ATOM_COMMON_TABLE_HEADER *header; + struct atom_data_revision revision; + + if (bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo) { + header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, + bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo); + + get_atom_data_table_revision(header, &revision); + + /* Don't need to check major revision as they are all 1 */ + switch (revision.minor) { + case 8: + result = get_integrated_info_v8(bp, info); + break; + case 9: + result = get_integrated_info_v9(bp, info); + break; + default: + return result; + + } + } + + /* Sort voltage table from low to high*/ + if (result == BP_RESULT_OK) { + struct clock_voltage_caps temp = {0, 0}; + uint32_t i; + uint32_t j; + + for (i = 1; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) { + for (j = i; j > 0; --j) { + if ( + info->disp_clk_voltage[j].max_supported_clk < + info->disp_clk_voltage[j-1].max_supported_clk) { + /* swap j and j - 1*/ + temp = info->disp_clk_voltage[j-1]; + info->disp_clk_voltage[j-1] = + info->disp_clk_voltage[j]; + info->disp_clk_voltage[j] = temp; + } + } + } + + } + + return result; +} + +static struct integrated_info *bios_parser_create_integrated_info( + struct dc_bios *dcb) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + struct integrated_info *info = NULL; + + info = dm_alloc(sizeof(struct integrated_info)); + + if (info == NULL) { + ASSERT_CRITICAL(0); + return NULL; + } + + if (construct_integrated_info(bp, info) == BP_RESULT_OK) + return info; + + dm_free(info); + + return NULL; +} + +/******************************************************************************/ + +static const struct dc_vbios_funcs vbios_funcs = { + .get_connectors_number = bios_parser_get_connectors_number, + + .get_encoder_id = bios_parser_get_encoder_id, + + .get_connector_id = bios_parser_get_connector_id, + + .get_dst_number = bios_parser_get_dst_number, + + .get_gpio_record = bios_parser_get_gpio_record, + + .get_src_obj = bios_parser_get_src_obj, + + .get_dst_obj = bios_parser_get_dst_obj, + + .get_i2c_info = bios_parser_get_i2c_info, + + .get_voltage_ddc_info = bios_parser_get_voltage_ddc_info, + + .get_thermal_ddc_info = bios_parser_get_thermal_ddc_info, + + .get_hpd_info = bios_parser_get_hpd_info, + + .get_device_tag = bios_parser_get_device_tag, + + .get_firmware_info = bios_parser_get_firmware_info, + + .get_spread_spectrum_info = bios_parser_get_spread_spectrum_info, + + .get_ss_entry_number = bios_parser_get_ss_entry_number, + + .get_embedded_panel_info = bios_parser_get_embedded_panel_info, + + .get_gpio_pin_info = bios_parser_get_gpio_pin_info, + + .get_embedded_panel_info = bios_parser_get_embedded_panel_info, + + .get_gpio_pin_info = bios_parser_get_gpio_pin_info, + + .get_encoder_cap_info = bios_parser_get_encoder_cap_info, + + /* bios scratch register communication */ + .is_accelerated_mode = bios_is_accelerated_mode, + + .set_scratch_critical_state = bios_parser_set_scratch_critical_state, + + .is_device_id_supported = bios_parser_is_device_id_supported, + + /* COMMANDS */ + .encoder_control = bios_parser_encoder_control, + + .transmitter_control = bios_parser_transmitter_control, + + .crt_control = bios_parser_crt_control, /* not used in DAL3. keep for now in case we need to support VGA on Bonaire */ + + .enable_crtc = bios_parser_enable_crtc, + + .adjust_pixel_clock = bios_parser_adjust_pixel_clock, + + .set_pixel_clock = bios_parser_set_pixel_clock, + + .set_dce_clock = bios_parser_set_dce_clock, + + .enable_spread_spectrum_on_ppll = bios_parser_enable_spread_spectrum_on_ppll, + + .program_crtc_timing = bios_parser_program_crtc_timing, /* still use. should probably retire and program directly */ + + .crtc_source_select = bios_parser_crtc_source_select, /* still use. should probably retire and program directly */ + + .program_display_engine_pll = bios_parser_program_display_engine_pll, + + .enable_disp_power_gating = bios_parser_enable_disp_power_gating, + + /* SW init and patch */ + .post_init = bios_parser_post_init, /* patch vbios table for mxm module by reading i2c */ + + .bios_parser_destroy = bios_parser_destroy, +}; + +static bool bios_parser_construct( + struct bios_parser *bp, + struct bp_init_data *init, + enum dce_version dce_version) +{ + uint16_t *rom_header_offset = NULL; + ATOM_ROM_HEADER *rom_header = NULL; + ATOM_OBJECT_HEADER *object_info_tbl; + struct atom_data_revision tbl_rev = {0}; + + if (!init) + return false; + + if (!init->bios) + return false; + + bp->base.funcs = &vbios_funcs; + bp->base.bios = init->bios; + bp->base.bios_size = bp->base.bios[BIOS_IMAGE_SIZE_OFFSET] * BIOS_IMAGE_SIZE_UNIT; + + bp->base.ctx = init->ctx; + bp->base.bios_local_image = NULL; + + rom_header_offset = + GET_IMAGE(uint16_t, OFFSET_TO_POINTER_TO_ATOM_ROM_HEADER); + + if (!rom_header_offset) + return false; + + rom_header = GET_IMAGE(ATOM_ROM_HEADER, *rom_header_offset); + + if (!rom_header) + return false; + + get_atom_data_table_revision(&rom_header->sHeader, &tbl_rev); + if (tbl_rev.major >= 2 && tbl_rev.minor >= 2) + return false; + + bp->master_data_tbl = + GET_IMAGE(ATOM_MASTER_DATA_TABLE, + rom_header->usMasterDataTableOffset); + + if (!bp->master_data_tbl) + return false; + + bp->object_info_tbl_offset = DATA_TABLES(Object_Header); + + if (!bp->object_info_tbl_offset) + return false; + + object_info_tbl = + GET_IMAGE(ATOM_OBJECT_HEADER, bp->object_info_tbl_offset); + + if (!object_info_tbl) + return false; + + get_atom_data_table_revision(&object_info_tbl->sHeader, + &bp->object_info_tbl.revision); + + if (bp->object_info_tbl.revision.major == 1 + && bp->object_info_tbl.revision.minor >= 3) { + ATOM_OBJECT_HEADER_V3 *tbl_v3; + + tbl_v3 = GET_IMAGE(ATOM_OBJECT_HEADER_V3, + bp->object_info_tbl_offset); + if (!tbl_v3) + return false; + + bp->object_info_tbl.v1_3 = tbl_v3; + } else if (bp->object_info_tbl.revision.major == 1 + && bp->object_info_tbl.revision.minor >= 1) + bp->object_info_tbl.v1_1 = object_info_tbl; + else + return false; + + dal_bios_parser_init_cmd_tbl(bp); + dal_bios_parser_init_cmd_tbl_helper(&bp->cmd_helper, dce_version); + + bp->base.integrated_info = bios_parser_create_integrated_info(&bp->base); + + return true; +} + +/******************************************************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.h b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.h new file mode 100644 index 000000000000..d6f16275048f --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.h @@ -0,0 +1,33 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_BIOS_PARSER_H__ +#define __DAL_BIOS_PARSER_H__ + +struct dc_bios *bios_parser_create( + struct bp_init_data *init, + enum dce_version dce_version); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.c new file mode 100644 index 000000000000..8e56d2f25dea --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.c @@ -0,0 +1,82 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "atom.h" + +#include "include/bios_parser_types.h" +#include "bios_parser_helper.h" +#include "command_table_helper.h" +#include "command_table.h" +#include "bios_parser_types_internal.h" + +uint8_t *get_image(struct dc_bios *bp, + uint32_t offset, + uint32_t size) +{ + if (bp->bios && offset + size < bp->bios_size) + return bp->bios + offset; + else + return NULL; +} + +#include "reg_helper.h" + +#define CTX \ + bios->ctx +#define REG(reg)\ + (bios->regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + ATOM_ ## field_name ## _SHIFT, ATOM_ ## field_name + +bool bios_is_accelerated_mode( + struct dc_bios *bios) +{ + uint32_t acc_mode; + REG_GET(BIOS_SCRATCH_6, S6_ACC_MODE, &acc_mode); + return (acc_mode == 1); +} + + +void bios_set_scratch_acc_mode_change( + struct dc_bios *bios) +{ + REG_UPDATE(BIOS_SCRATCH_6, S6_ACC_MODE, 1); +} + + +void bios_set_scratch_critical_state( + struct dc_bios *bios, + bool state) +{ + uint32_t critial_state = state ? 1 : 0; + REG_UPDATE(BIOS_SCRATCH_6, S6_CRITICAL_STATE, critial_state); +} + + + diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.h b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.h new file mode 100644 index 000000000000..a8fbb82b8c8e --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.h @@ -0,0 +1,40 @@ +/* + * Copyright 2012-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_BIOS_PARSER_HELPER_H__ +#define __DAL_BIOS_PARSER_HELPER_H__ + +struct bios_parser; + +uint8_t *get_image(struct dc_bios *bp, uint32_t offset, + uint32_t size); + +bool bios_is_accelerated_mode(struct dc_bios *bios); +void bios_set_scratch_acc_mode_change(struct dc_bios *bios); +void bios_set_scratch_critical_state(struct dc_bios *bios, bool state); + +#define GET_IMAGE(type, offset) ((type *) get_image(&bp->base, offset, sizeof(type))) + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_interface.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_interface.c new file mode 100644 index 000000000000..42272c35df2d --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_interface.c @@ -0,0 +1,50 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "include/logger_interface.h" + +#include "bios_parser_interface.h" +#include "bios_parser.h" + + +struct dc_bios *dal_bios_parser_create( + struct bp_init_data *init, + enum dce_version dce_version) +{ + struct dc_bios *bios = NULL; + + bios = bios_parser_create(init, dce_version); + + return bios; +} + +void dal_bios_parser_destroy(struct dc_bios **dcb) +{ + struct dc_bios *bios = *dcb; + + bios->funcs->bios_parser_destroy(dcb); +} + diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_types_internal.h b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_types_internal.h new file mode 100644 index 000000000000..5918923bfb93 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_types_internal.h @@ -0,0 +1,72 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_BIOS_PARSER_TYPES_BIOS_H__ +#define __DAL_BIOS_PARSER_TYPES_BIOS_H__ + +#include "dc_bios_types.h" +#include "bios_parser_helper.h" + +struct atom_data_revision { + uint32_t major; + uint32_t minor; +}; + +struct object_info_table { + struct atom_data_revision revision; + union { + ATOM_OBJECT_HEADER *v1_1; + ATOM_OBJECT_HEADER_V3 *v1_3; + }; +}; + +enum spread_spectrum_id { + SS_ID_UNKNOWN = 0, + SS_ID_DP1 = 0xf1, + SS_ID_DP2 = 0xf2, + SS_ID_LVLINK_2700MHZ = 0xf3, + SS_ID_LVLINK_1620MHZ = 0xf4 +}; + +struct bios_parser { + struct dc_bios base; + + struct object_info_table object_info_tbl; + uint32_t object_info_tbl_offset; + ATOM_MASTER_DATA_TABLE *master_data_tbl; + + const struct bios_parser_helper *bios_helper; + + const struct command_table_helper *cmd_helper; + struct cmd_tbl cmd_tbl; + + bool remap_device_tags; +}; + +/* Bios Parser from DC Bios */ +#define BP_FROM_DCB(dc_bios) \ + container_of(dc_bios, struct bios_parser, base) + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table.c b/drivers/gpu/drm/amd/display/dc/bios/command_table.c new file mode 100644 index 000000000000..51f6052eac96 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table.c @@ -0,0 +1,2609 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "atom.h" + +#include "include/bios_parser_interface.h" + +#include "command_table.h" +#include "command_table_helper.h" +#include "bios_parser_helper.h" +#include "bios_parser_types_internal.h" + +#define EXEC_BIOS_CMD_TABLE(command, params)\ + (cgs_atom_exec_cmd_table(bp->base.ctx->cgs_device, \ + GetIndexIntoMasterTable(COMMAND, command), \ + ¶ms) == 0) + +#define BIOS_CMD_TABLE_REVISION(command, frev, crev)\ + cgs_atom_get_cmd_table_revs(bp->base.ctx->cgs_device, \ + GetIndexIntoMasterTable(COMMAND, command), &frev, &crev) + +#define BIOS_CMD_TABLE_PARA_REVISION(command)\ + bios_cmd_table_para_revision(bp->base.ctx->cgs_device, \ + GetIndexIntoMasterTable(COMMAND, command)) + +static void init_dig_encoder_control(struct bios_parser *bp); +static void init_transmitter_control(struct bios_parser *bp); +static void init_set_pixel_clock(struct bios_parser *bp); +static void init_enable_spread_spectrum_on_ppll(struct bios_parser *bp); +static void init_adjust_display_pll(struct bios_parser *bp); +static void init_dac_encoder_control(struct bios_parser *bp); +static void init_dac_output_control(struct bios_parser *bp); +static void init_blank_crtc(struct bios_parser *bp); +static void init_set_crtc_timing(struct bios_parser *bp); +static void init_set_crtc_overscan(struct bios_parser *bp); +static void init_select_crtc_source(struct bios_parser *bp); +static void init_enable_crtc(struct bios_parser *bp); +static void init_enable_crtc_mem_req(struct bios_parser *bp); +static void init_compute_memore_engine_pll(struct bios_parser *bp); +static void init_external_encoder_control(struct bios_parser *bp); +static void init_enable_disp_power_gating(struct bios_parser *bp); +static void init_program_clock(struct bios_parser *bp); +static void init_set_dce_clock(struct bios_parser *bp); + +void dal_bios_parser_init_cmd_tbl(struct bios_parser *bp) +{ + init_dig_encoder_control(bp); + init_transmitter_control(bp); + init_set_pixel_clock(bp); + init_enable_spread_spectrum_on_ppll(bp); + init_adjust_display_pll(bp); + init_dac_encoder_control(bp); + init_dac_output_control(bp); + init_blank_crtc(bp); + init_set_crtc_timing(bp); + init_set_crtc_overscan(bp); + init_select_crtc_source(bp); + init_enable_crtc(bp); + init_enable_crtc_mem_req(bp); + init_program_clock(bp); + init_compute_memore_engine_pll(bp); + init_external_encoder_control(bp); + init_enable_disp_power_gating(bp); + init_set_dce_clock(bp); +} + +static uint32_t bios_cmd_table_para_revision(void *cgs_device, + uint32_t index) +{ + uint8_t frev, crev; + + if (cgs_atom_get_cmd_table_revs(cgs_device, + index, + &frev, &crev) != 0) + return 0; + return crev; +} + +/******************************************************************************* + ******************************************************************************** + ** + ** D I G E N C O D E R C O N T R O L + ** + ******************************************************************************** + *******************************************************************************/ +static enum bp_result encoder_control_digx_v3( + struct bios_parser *bp, + struct bp_encoder_control *cntl); + +static enum bp_result encoder_control_digx_v4( + struct bios_parser *bp, + struct bp_encoder_control *cntl); + +#ifdef LATEST_ATOM_BIOS_SUPPORT +static enum bp_result encoder_control_digx_v5( + struct bios_parser *bp, + struct bp_encoder_control *cntl); +#endif + +static void init_encoder_control_dig_v1(struct bios_parser *bp); + +static void init_dig_encoder_control(struct bios_parser *bp) +{ + uint32_t version = + BIOS_CMD_TABLE_PARA_REVISION(DIGxEncoderControl); + + switch (version) { + case 2: + bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v3; + break; + case 4: + bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v4; + break; + +#ifdef LATEST_ATOM_BIOS_SUPPORT + case 5: + bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v5; + break; +#endif + + default: + init_encoder_control_dig_v1(bp); + break; + } +} + +static enum bp_result encoder_control_dig_v1( + struct bios_parser *bp, + struct bp_encoder_control *cntl); +static enum bp_result encoder_control_dig1_v1( + struct bios_parser *bp, + struct bp_encoder_control *cntl); +static enum bp_result encoder_control_dig2_v1( + struct bios_parser *bp, + struct bp_encoder_control *cntl); + +static void init_encoder_control_dig_v1(struct bios_parser *bp) +{ + struct cmd_tbl *cmd_tbl = &bp->cmd_tbl; + + if (1 == BIOS_CMD_TABLE_PARA_REVISION(DIG1EncoderControl)) + cmd_tbl->encoder_control_dig1 = encoder_control_dig1_v1; + else + cmd_tbl->encoder_control_dig1 = NULL; + + if (1 == BIOS_CMD_TABLE_PARA_REVISION(DIG2EncoderControl)) + cmd_tbl->encoder_control_dig2 = encoder_control_dig2_v1; + else + cmd_tbl->encoder_control_dig2 = NULL; + + cmd_tbl->dig_encoder_control = encoder_control_dig_v1; +} + +static enum bp_result encoder_control_dig_v1( + struct bios_parser *bp, + struct bp_encoder_control *cntl) +{ + enum bp_result result = BP_RESULT_FAILURE; + struct cmd_tbl *cmd_tbl = &bp->cmd_tbl; + + if (cntl != NULL) + switch (cntl->engine_id) { + case ENGINE_ID_DIGA: + if (cmd_tbl->encoder_control_dig1 != NULL) + result = + cmd_tbl->encoder_control_dig1(bp, cntl); + break; + case ENGINE_ID_DIGB: + if (cmd_tbl->encoder_control_dig2 != NULL) + result = + cmd_tbl->encoder_control_dig2(bp, cntl); + break; + + default: + break; + } + + return result; +} + +static enum bp_result encoder_control_dig1_v1( + struct bios_parser *bp, + struct bp_encoder_control *cntl) +{ + enum bp_result result = BP_RESULT_FAILURE; + DIG_ENCODER_CONTROL_PARAMETERS_V2 params = {0}; + + bp->cmd_helper->assign_control_parameter(bp->cmd_helper, cntl, ¶ms); + + if (EXEC_BIOS_CMD_TABLE(DIG1EncoderControl, params)) + result = BP_RESULT_OK; + + return result; +} + +static enum bp_result encoder_control_dig2_v1( + struct bios_parser *bp, + struct bp_encoder_control *cntl) +{ + enum bp_result result = BP_RESULT_FAILURE; + DIG_ENCODER_CONTROL_PARAMETERS_V2 params = {0}; + + bp->cmd_helper->assign_control_parameter(bp->cmd_helper, cntl, ¶ms); + + if (EXEC_BIOS_CMD_TABLE(DIG2EncoderControl, params)) + result = BP_RESULT_OK; + + return result; +} + +static enum bp_result encoder_control_digx_v3( + struct bios_parser *bp, + struct bp_encoder_control *cntl) +{ + enum bp_result result = BP_RESULT_FAILURE; + DIG_ENCODER_CONTROL_PARAMETERS_V3 params = {0}; + + if (LANE_COUNT_FOUR < cntl->lanes_number) + params.acConfig.ucDPLinkRate = 1; /* dual link 2.7GHz */ + else + params.acConfig.ucDPLinkRate = 0; /* single link 1.62GHz */ + + params.acConfig.ucDigSel = (uint8_t)(cntl->engine_id); + + /* We need to convert from KHz units into 10KHz units */ + params.ucAction = bp->cmd_helper->encoder_action_to_atom(cntl->action); + params.usPixelClock = cpu_to_le16((uint16_t)(cntl->pixel_clock / 10)); + params.ucEncoderMode = + (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom( + cntl->signal, + cntl->enable_dp_audio); + params.ucLaneNum = (uint8_t)(cntl->lanes_number); + + if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params)) + result = BP_RESULT_OK; + + return result; +} + +static enum bp_result encoder_control_digx_v4( + struct bios_parser *bp, + struct bp_encoder_control *cntl) +{ + enum bp_result result = BP_RESULT_FAILURE; + DIG_ENCODER_CONTROL_PARAMETERS_V4 params = {0}; + + if (LANE_COUNT_FOUR < cntl->lanes_number) + params.acConfig.ucDPLinkRate = 1; /* dual link 2.7GHz */ + else + params.acConfig.ucDPLinkRate = 0; /* single link 1.62GHz */ + + params.acConfig.ucDigSel = (uint8_t)(cntl->engine_id); + + /* We need to convert from KHz units into 10KHz units */ + params.ucAction = bp->cmd_helper->encoder_action_to_atom(cntl->action); + params.usPixelClock = cpu_to_le16((uint16_t)(cntl->pixel_clock / 10)); + params.ucEncoderMode = + (uint8_t)(bp->cmd_helper->encoder_mode_bp_to_atom( + cntl->signal, + cntl->enable_dp_audio)); + params.ucLaneNum = (uint8_t)(cntl->lanes_number); + + if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params)) + result = BP_RESULT_OK; + + return result; +} + +#ifdef LATEST_ATOM_BIOS_SUPPORT +static enum bp_result encoder_control_digx_v5( + struct bios_parser *bp, + struct bp_encoder_control *cntl) +{ + enum bp_result result = BP_RESULT_FAILURE; + ENCODER_STREAM_SETUP_PARAMETERS_V5 params = {0}; + + params.ucDigId = (uint8_t)(cntl->engine_id); + params.ucAction = bp->cmd_helper->encoder_action_to_atom(cntl->action); + + params.ulPixelClock = cntl->pixel_clock / 10; + params.ucDigMode = + (uint8_t)(bp->cmd_helper->encoder_mode_bp_to_atom( + cntl->signal, + cntl->enable_dp_audio)); + params.ucLaneNum = (uint8_t)(cntl->lanes_number); + + switch (cntl->color_depth) { + case COLOR_DEPTH_888: + params.ucBitPerColor = PANEL_8BIT_PER_COLOR; + break; + case COLOR_DEPTH_101010: + params.ucBitPerColor = PANEL_10BIT_PER_COLOR; + break; + case COLOR_DEPTH_121212: + params.ucBitPerColor = PANEL_12BIT_PER_COLOR; + break; + case COLOR_DEPTH_161616: + params.ucBitPerColor = PANEL_16BIT_PER_COLOR; + break; + default: + break; + } + + if (cntl->signal == SIGNAL_TYPE_HDMI_TYPE_A) + switch (cntl->color_depth) { + case COLOR_DEPTH_101010: + params.ulPixelClock = + (params.ulPixelClock * 30) / 24; + break; + case COLOR_DEPTH_121212: + params.ulPixelClock = + (params.ulPixelClock * 36) / 24; + break; + case COLOR_DEPTH_161616: + params.ulPixelClock = + (params.ulPixelClock * 48) / 24; + break; + default: + break; + } + + if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params)) + result = BP_RESULT_OK; + + return result; +} +#endif + +/******************************************************************************* + ******************************************************************************** + ** + ** TRANSMITTER CONTROL + ** + ******************************************************************************** + *******************************************************************************/ + +static enum bp_result transmitter_control_v2( + struct bios_parser *bp, + struct bp_transmitter_control *cntl); +static enum bp_result transmitter_control_v3( + struct bios_parser *bp, + struct bp_transmitter_control *cntl); +static enum bp_result transmitter_control_v4( + struct bios_parser *bp, + struct bp_transmitter_control *cntl); +static enum bp_result transmitter_control_v1_5( + struct bios_parser *bp, + struct bp_transmitter_control *cntl); +static enum bp_result transmitter_control_v1_6( + struct bios_parser *bp, + struct bp_transmitter_control *cntl); + +static void init_transmitter_control(struct bios_parser *bp) +{ + uint8_t frev; + uint8_t crev; + + if (BIOS_CMD_TABLE_REVISION(UNIPHYTransmitterControl, + frev, crev) != 0) + BREAK_TO_DEBUGGER(); + switch (crev) { + case 2: + bp->cmd_tbl.transmitter_control = transmitter_control_v2; + break; + case 3: + bp->cmd_tbl.transmitter_control = transmitter_control_v3; + break; + case 4: + bp->cmd_tbl.transmitter_control = transmitter_control_v4; + break; + case 5: + bp->cmd_tbl.transmitter_control = transmitter_control_v1_5; + break; + case 6: + bp->cmd_tbl.transmitter_control = transmitter_control_v1_6; + break; + default: + bp->cmd_tbl.transmitter_control = NULL; + break; + } +} + +static enum bp_result transmitter_control_v2( + struct bios_parser *bp, + struct bp_transmitter_control *cntl) +{ + enum bp_result result = BP_RESULT_FAILURE; + DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 params; + enum connector_id connector_id = + dal_graphics_object_id_get_connector_id(cntl->connector_obj_id); + + memset(¶ms, 0, sizeof(params)); + + switch (cntl->transmitter) { + case TRANSMITTER_UNIPHY_A: + case TRANSMITTER_UNIPHY_B: + case TRANSMITTER_UNIPHY_C: + case TRANSMITTER_UNIPHY_D: + case TRANSMITTER_UNIPHY_E: + case TRANSMITTER_UNIPHY_F: + case TRANSMITTER_TRAVIS_LCD: + break; + default: + return BP_RESULT_BADINPUT; + } + + switch (cntl->action) { + case TRANSMITTER_CONTROL_INIT: + if ((CONNECTOR_ID_DUAL_LINK_DVII == connector_id) || + (CONNECTOR_ID_DUAL_LINK_DVID == connector_id)) + /* on INIT this bit should be set according to the + * phisycal connector + * Bit0: dual link connector flag + * =0 connector is single link connector + * =1 connector is dual link connector + */ + params.acConfig.fDualLinkConnector = 1; + + /* connector object id */ + params.usInitInfo = + cpu_to_le16((uint8_t)cntl->connector_obj_id.id); + break; + case TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS: + /* votage swing and pre-emphsis */ + params.asMode.ucLaneSel = (uint8_t)cntl->lane_select; + params.asMode.ucLaneSet = (uint8_t)cntl->lane_settings; + break; + default: + /* if dual-link */ + if (LANE_COUNT_FOUR < cntl->lanes_number) { + /* on ENABLE/DISABLE this bit should be set according to + * actual timing (number of lanes) + * Bit0: dual link connector flag + * =0 connector is single link connector + * =1 connector is dual link connector + */ + params.acConfig.fDualLinkConnector = 1; + + /* link rate, half for dual link + * We need to convert from KHz units into 20KHz units + */ + params.usPixelClock = + cpu_to_le16((uint16_t)(cntl->pixel_clock / 20)); + } else + /* link rate, half for dual link + * We need to convert from KHz units into 10KHz units + */ + params.usPixelClock = + cpu_to_le16((uint16_t)(cntl->pixel_clock / 10)); + break; + } + + /* 00 - coherent mode + * 01 - incoherent mode + */ + + params.acConfig.fCoherentMode = cntl->coherent; + + if ((TRANSMITTER_UNIPHY_B == cntl->transmitter) + || (TRANSMITTER_UNIPHY_D == cntl->transmitter) + || (TRANSMITTER_UNIPHY_F == cntl->transmitter)) + /* Bit2: Transmitter Link selection + * =0 when bit0=0, single link A/C/E, when bit0=1, + * master link A/C/E + * =1 when bit0=0, single link B/D/F, when bit0=1, + * master link B/D/F + */ + params.acConfig.ucLinkSel = 1; + + if (ENGINE_ID_DIGB == cntl->engine_id) + /* Bit3: Transmitter data source selection + * =0 DIGA is data source. + * =1 DIGB is data source. + * This bit is only useful when ucAction= ATOM_ENABLE + */ + params.acConfig.ucEncoderSel = 1; + + if (CONNECTOR_ID_DISPLAY_PORT == connector_id) + /* Bit4: DP connector flag + * =0 connector is none-DP connector + * =1 connector is DP connector + */ + params.acConfig.fDPConnector = 1; + + /* Bit[7:6]: Transmitter selection + * =0 UNIPHY_ENCODER: UNIPHYA/B + * =1 UNIPHY1_ENCODER: UNIPHYC/D + * =2 UNIPHY2_ENCODER: UNIPHYE/F + * =3 reserved + */ + params.acConfig.ucTransmitterSel = + (uint8_t)bp->cmd_helper->transmitter_bp_to_atom( + cntl->transmitter); + + params.ucAction = (uint8_t)cntl->action; + + if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params)) + result = BP_RESULT_OK; + + return result; +} + +static enum bp_result transmitter_control_v3( + struct bios_parser *bp, + struct bp_transmitter_control *cntl) +{ + enum bp_result result = BP_RESULT_FAILURE; + DIG_TRANSMITTER_CONTROL_PARAMETERS_V3 params; + uint32_t pll_id; + enum connector_id conn_id = + dal_graphics_object_id_get_connector_id(cntl->connector_obj_id); + const struct command_table_helper *cmd = bp->cmd_helper; + bool dual_link_conn = (CONNECTOR_ID_DUAL_LINK_DVII == conn_id) + || (CONNECTOR_ID_DUAL_LINK_DVID == conn_id); + + memset(¶ms, 0, sizeof(params)); + + switch (cntl->transmitter) { + case TRANSMITTER_UNIPHY_A: + case TRANSMITTER_UNIPHY_B: + case TRANSMITTER_UNIPHY_C: + case TRANSMITTER_UNIPHY_D: + case TRANSMITTER_UNIPHY_E: + case TRANSMITTER_UNIPHY_F: + case TRANSMITTER_TRAVIS_LCD: + break; + default: + return BP_RESULT_BADINPUT; + } + + if (!cmd->clock_source_id_to_atom(cntl->pll_id, &pll_id)) + return BP_RESULT_BADINPUT; + + /* fill information based on the action */ + switch (cntl->action) { + case TRANSMITTER_CONTROL_INIT: + if (dual_link_conn) { + /* on INIT this bit should be set according to the + * phisycal connector + * Bit0: dual link connector flag + * =0 connector is single link connector + * =1 connector is dual link connector + */ + params.acConfig.fDualLinkConnector = 1; + } + + /* connector object id */ + params.usInitInfo = + cpu_to_le16((uint8_t)(cntl->connector_obj_id.id)); + break; + case TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS: + /* votage swing and pre-emphsis */ + params.asMode.ucLaneSel = (uint8_t)cntl->lane_select; + params.asMode.ucLaneSet = (uint8_t)cntl->lane_settings; + break; + default: + if (dual_link_conn && cntl->multi_path) + /* on ENABLE/DISABLE this bit should be set according to + * actual timing (number of lanes) + * Bit0: dual link connector flag + * =0 connector is single link connector + * =1 connector is dual link connector + */ + params.acConfig.fDualLinkConnector = 1; + + /* if dual-link */ + if (LANE_COUNT_FOUR < cntl->lanes_number) { + /* on ENABLE/DISABLE this bit should be set according to + * actual timing (number of lanes) + * Bit0: dual link connector flag + * =0 connector is single link connector + * =1 connector is dual link connector + */ + params.acConfig.fDualLinkConnector = 1; + + /* link rate, half for dual link + * We need to convert from KHz units into 20KHz units + */ + params.usPixelClock = + cpu_to_le16((uint16_t)(cntl->pixel_clock / 20)); + } else { + /* link rate, half for dual link + * We need to convert from KHz units into 10KHz units + */ + params.usPixelClock = + cpu_to_le16((uint16_t)(cntl->pixel_clock / 10)); + } + break; + } + + /* 00 - coherent mode + * 01 - incoherent mode + */ + + params.acConfig.fCoherentMode = cntl->coherent; + + if ((TRANSMITTER_UNIPHY_B == cntl->transmitter) + || (TRANSMITTER_UNIPHY_D == cntl->transmitter) + || (TRANSMITTER_UNIPHY_F == cntl->transmitter)) + /* Bit2: Transmitter Link selection + * =0 when bit0=0, single link A/C/E, when bit0=1, + * master link A/C/E + * =1 when bit0=0, single link B/D/F, when bit0=1, + * master link B/D/F + */ + params.acConfig.ucLinkSel = 1; + + if (ENGINE_ID_DIGB == cntl->engine_id) + /* Bit3: Transmitter data source selection + * =0 DIGA is data source. + * =1 DIGB is data source. + * This bit is only useful when ucAction= ATOM_ENABLE + */ + params.acConfig.ucEncoderSel = 1; + + /* Bit[7:6]: Transmitter selection + * =0 UNIPHY_ENCODER: UNIPHYA/B + * =1 UNIPHY1_ENCODER: UNIPHYC/D + * =2 UNIPHY2_ENCODER: UNIPHYE/F + * =3 reserved + */ + params.acConfig.ucTransmitterSel = + (uint8_t)cmd->transmitter_bp_to_atom(cntl->transmitter); + + params.ucLaneNum = (uint8_t)cntl->lanes_number; + + params.acConfig.ucRefClkSource = (uint8_t)pll_id; + + params.ucAction = (uint8_t)cntl->action; + + if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params)) + result = BP_RESULT_OK; + + return result; +} + +static enum bp_result transmitter_control_v4( + struct bios_parser *bp, + struct bp_transmitter_control *cntl) +{ + enum bp_result result = BP_RESULT_FAILURE; + DIG_TRANSMITTER_CONTROL_PARAMETERS_V4 params; + uint32_t ref_clk_src_id; + enum connector_id conn_id = + dal_graphics_object_id_get_connector_id(cntl->connector_obj_id); + const struct command_table_helper *cmd = bp->cmd_helper; + + memset(¶ms, 0, sizeof(params)); + + switch (cntl->transmitter) { + case TRANSMITTER_UNIPHY_A: + case TRANSMITTER_UNIPHY_B: + case TRANSMITTER_UNIPHY_C: + case TRANSMITTER_UNIPHY_D: + case TRANSMITTER_UNIPHY_E: + case TRANSMITTER_UNIPHY_F: + case TRANSMITTER_TRAVIS_LCD: + break; + default: + return BP_RESULT_BADINPUT; + } + + if (!cmd->clock_source_id_to_ref_clk_src(cntl->pll_id, &ref_clk_src_id)) + return BP_RESULT_BADINPUT; + + switch (cntl->action) { + case TRANSMITTER_CONTROL_INIT: + { + if ((CONNECTOR_ID_DUAL_LINK_DVII == conn_id) || + (CONNECTOR_ID_DUAL_LINK_DVID == conn_id)) + /* on INIT this bit should be set according to the + * phisycal connector + * Bit0: dual link connector flag + * =0 connector is single link connector + * =1 connector is dual link connector + */ + params.acConfig.fDualLinkConnector = 1; + + /* connector object id */ + params.usInitInfo = + cpu_to_le16((uint8_t)(cntl->connector_obj_id.id)); + } + break; + case TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS: + /* votage swing and pre-emphsis */ + params.asMode.ucLaneSel = (uint8_t)(cntl->lane_select); + params.asMode.ucLaneSet = (uint8_t)(cntl->lane_settings); + break; + default: + if ((CONNECTOR_ID_DUAL_LINK_DVII == conn_id) || + (CONNECTOR_ID_DUAL_LINK_DVID == conn_id)) + /* on ENABLE/DISABLE this bit should be set according to + * actual timing (number of lanes) + * Bit0: dual link connector flag + * =0 connector is single link connector + * =1 connector is dual link connector + */ + params.acConfig.fDualLinkConnector = 1; + + /* if dual-link */ + if (LANE_COUNT_FOUR < cntl->lanes_number) + /* link rate, half for dual link + * We need to convert from KHz units into 20KHz units + */ + params.usPixelClock = + cpu_to_le16((uint16_t)(cntl->pixel_clock / 20)); + else { + /* link rate, half for dual link + * We need to convert from KHz units into 10KHz units + */ + params.usPixelClock = + cpu_to_le16((uint16_t)(cntl->pixel_clock / 10)); + } + break; + } + + /* 00 - coherent mode + * 01 - incoherent mode + */ + + params.acConfig.fCoherentMode = cntl->coherent; + + if ((TRANSMITTER_UNIPHY_B == cntl->transmitter) + || (TRANSMITTER_UNIPHY_D == cntl->transmitter) + || (TRANSMITTER_UNIPHY_F == cntl->transmitter)) + /* Bit2: Transmitter Link selection + * =0 when bit0=0, single link A/C/E, when bit0=1, + * master link A/C/E + * =1 when bit0=0, single link B/D/F, when bit0=1, + * master link B/D/F + */ + params.acConfig.ucLinkSel = 1; + + if (ENGINE_ID_DIGB == cntl->engine_id) + /* Bit3: Transmitter data source selection + * =0 DIGA is data source. + * =1 DIGB is data source. + * This bit is only useful when ucAction= ATOM_ENABLE + */ + params.acConfig.ucEncoderSel = 1; + + /* Bit[7:6]: Transmitter selection + * =0 UNIPHY_ENCODER: UNIPHYA/B + * =1 UNIPHY1_ENCODER: UNIPHYC/D + * =2 UNIPHY2_ENCODER: UNIPHYE/F + * =3 reserved + */ + params.acConfig.ucTransmitterSel = + (uint8_t)(cmd->transmitter_bp_to_atom(cntl->transmitter)); + params.ucLaneNum = (uint8_t)(cntl->lanes_number); + params.acConfig.ucRefClkSource = (uint8_t)(ref_clk_src_id); + params.ucAction = (uint8_t)(cntl->action); + + if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params)) + result = BP_RESULT_OK; + + return result; +} + +static enum bp_result transmitter_control_v1_5( + struct bios_parser *bp, + struct bp_transmitter_control *cntl) +{ + enum bp_result result = BP_RESULT_FAILURE; + const struct command_table_helper *cmd = bp->cmd_helper; + DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_5 params; + + memset(¶ms, 0, sizeof(params)); + params.ucPhyId = cmd->phy_id_to_atom(cntl->transmitter); + params.ucAction = (uint8_t)cntl->action; + params.ucLaneNum = (uint8_t)cntl->lanes_number; + params.ucConnObjId = (uint8_t)cntl->connector_obj_id.id; + + params.ucDigMode = + cmd->signal_type_to_atom_dig_mode(cntl->signal); + params.asConfig.ucPhyClkSrcId = + cmd->clock_source_id_to_atom_phy_clk_src_id(cntl->pll_id); + /* 00 - coherent mode */ + params.asConfig.ucCoherentMode = cntl->coherent; + params.asConfig.ucHPDSel = + cmd->hpd_sel_to_atom(cntl->hpd_sel); + params.ucDigEncoderSel = + cmd->dig_encoder_sel_to_atom(cntl->engine_id); + params.ucDPLaneSet = (uint8_t) cntl->lane_settings; + params.usSymClock = cpu_to_le16((uint16_t) (cntl->pixel_clock / 10)); + /* + * In SI/TN case, caller have to set usPixelClock as following: + * DP mode: usPixelClock = DP_LINK_CLOCK/10 + * (DP_LINK_CLOCK = 1.62GHz, 2.7GHz, 5.4GHz) + * DVI single link mode: usPixelClock = pixel clock + * DVI dual link mode: usPixelClock = pixel clock + * HDMI mode: usPixelClock = pixel clock * deep_color_ratio + * (=1: 8bpp, =1.25: 10bpp, =1.5:12bpp, =2: 16bpp) + * LVDS mode: usPixelClock = pixel clock + */ + + if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params)) + result = BP_RESULT_OK; + + return result; +} + +static enum bp_result transmitter_control_v1_6( + struct bios_parser *bp, + struct bp_transmitter_control *cntl) +{ + enum bp_result result = BP_RESULT_FAILURE; +#ifdef LATEST_ATOM_BIOS_SUPPORT + const struct command_table_helper *cmd = bp->cmd_helper; + DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_6 params; + + memset(¶ms, 0, sizeof(params)); + params.ucPhyId = cmd->phy_id_to_atom(cntl->transmitter); + params.ucAction = (uint8_t)cntl->action; + + if (cntl->action == TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS) + params.ucDPLaneSet = (uint8_t)cntl->lane_settings; + else + params.ucDigMode = cmd->signal_type_to_atom_dig_mode(cntl->signal); + + params.ucLaneNum = (uint8_t)cntl->lanes_number; + params.ucHPDSel = cmd->hpd_sel_to_atom(cntl->hpd_sel); + params.ucDigEncoderSel = cmd->dig_encoder_sel_to_atom(cntl->engine_id); + params.ucConnObjId = (uint8_t)cntl->connector_obj_id.id; + params.ulSymClock = cntl->pixel_clock/10; + + /* + * In SI/TN case, caller have to set usPixelClock as following: + * DP mode: usPixelClock = DP_LINK_CLOCK/10 + * (DP_LINK_CLOCK = 1.62GHz, 2.7GHz, 5.4GHz) + * DVI single link mode: usPixelClock = pixel clock + * DVI dual link mode: usPixelClock = pixel clock + * HDMI mode: usPixelClock = pixel clock * deep_color_ratio + * (=1: 8bpp, =1.25: 10bpp, =1.5:12bpp, =2: 16bpp) + * LVDS mode: usPixelClock = pixel clock + */ + switch (cntl->signal) { + case SIGNAL_TYPE_HDMI_TYPE_A: + switch (cntl->color_depth) { + case COLOR_DEPTH_101010: + params.ulSymClock = + cpu_to_le16((le16_to_cpu(params.ulSymClock) * 30) / 24); + break; + case COLOR_DEPTH_121212: + params.ulSymClock = + cpu_to_le16((le16_to_cpu(params.ulSymClock) * 36) / 24); + break; + case COLOR_DEPTH_161616: + params.ulSymClock = + cpu_to_le16((le16_to_cpu(params.ulSymClock) * 48) / 24); + break; + default: + break; + } + break; + default: + break; + } + + if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params)) + result = BP_RESULT_OK; +#endif + return result; +} + +/******************************************************************************* + ******************************************************************************** + ** + ** SET PIXEL CLOCK + ** + ******************************************************************************** + *******************************************************************************/ + +static enum bp_result set_pixel_clock_v3( + struct bios_parser *bp, + struct bp_pixel_clock_parameters *bp_params); +static enum bp_result set_pixel_clock_v5( + struct bios_parser *bp, + struct bp_pixel_clock_parameters *bp_params); +static enum bp_result set_pixel_clock_v6( + struct bios_parser *bp, + struct bp_pixel_clock_parameters *bp_params); +static enum bp_result set_pixel_clock_v7( + struct bios_parser *bp, + struct bp_pixel_clock_parameters *bp_params); + +static void init_set_pixel_clock(struct bios_parser *bp) +{ + switch (BIOS_CMD_TABLE_PARA_REVISION(SetPixelClock)) { + case 3: + bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v3; + break; + case 5: + bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v5; + break; + case 6: + bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v6; + break; + case 7: + bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v7; + break; + default: + bp->cmd_tbl.set_pixel_clock = NULL; + break; + } +} + +static enum bp_result set_pixel_clock_v3( + struct bios_parser *bp, + struct bp_pixel_clock_parameters *bp_params) +{ + enum bp_result result = BP_RESULT_FAILURE; + PIXEL_CLOCK_PARAMETERS_V3 *params; + SET_PIXEL_CLOCK_PS_ALLOCATION allocation; + + memset(&allocation, 0, sizeof(allocation)); + + if (CLOCK_SOURCE_ID_PLL1 == bp_params->pll_id) + allocation.sPCLKInput.ucPpll = ATOM_PPLL1; + else if (CLOCK_SOURCE_ID_PLL2 == bp_params->pll_id) + allocation.sPCLKInput.ucPpll = ATOM_PPLL2; + else + return BP_RESULT_BADINPUT; + + allocation.sPCLKInput.usRefDiv = + cpu_to_le16((uint16_t)bp_params->reference_divider); + allocation.sPCLKInput.usFbDiv = + cpu_to_le16((uint16_t)bp_params->feedback_divider); + allocation.sPCLKInput.ucFracFbDiv = + (uint8_t)bp_params->fractional_feedback_divider; + allocation.sPCLKInput.ucPostDiv = + (uint8_t)bp_params->pixel_clock_post_divider; + + /* We need to convert from KHz units into 10KHz units */ + allocation.sPCLKInput.usPixelClock = + cpu_to_le16((uint16_t)(bp_params->target_pixel_clock / 10)); + + params = (PIXEL_CLOCK_PARAMETERS_V3 *)&allocation.sPCLKInput; + params->ucTransmitterId = + bp->cmd_helper->encoder_id_to_atom( + dal_graphics_object_id_get_encoder_id( + bp_params->encoder_object_id)); + params->ucEncoderMode = + (uint8_t)(bp->cmd_helper->encoder_mode_bp_to_atom( + bp_params->signal_type, false)); + + if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL) + params->ucMiscInfo |= PIXEL_CLOCK_MISC_FORCE_PROG_PPLL; + + if (bp_params->flags.USE_E_CLOCK_AS_SOURCE_FOR_D_CLOCK) + params->ucMiscInfo |= PIXEL_CLOCK_MISC_USE_ENGINE_FOR_DISPCLK; + + if (CONTROLLER_ID_D1 != bp_params->controller_id) + params->ucMiscInfo |= PIXEL_CLOCK_MISC_CRTC_SEL_CRTC2; + + if (EXEC_BIOS_CMD_TABLE(SetPixelClock, allocation)) + result = BP_RESULT_OK; + + return result; +} + +#ifndef SET_PIXEL_CLOCK_PS_ALLOCATION_V5 +/* video bios did not define this: */ +typedef struct _SET_PIXEL_CLOCK_PS_ALLOCATION_V5 { + PIXEL_CLOCK_PARAMETERS_V5 sPCLKInput; + /* Caller doesn't need to init this portion */ + ENABLE_SPREAD_SPECTRUM_ON_PPLL sReserved; +} SET_PIXEL_CLOCK_PS_ALLOCATION_V5; +#endif + +#ifndef SET_PIXEL_CLOCK_PS_ALLOCATION_V6 +/* video bios did not define this: */ +typedef struct _SET_PIXEL_CLOCK_PS_ALLOCATION_V6 { + PIXEL_CLOCK_PARAMETERS_V6 sPCLKInput; + /* Caller doesn't need to init this portion */ + ENABLE_SPREAD_SPECTRUM_ON_PPLL sReserved; +} SET_PIXEL_CLOCK_PS_ALLOCATION_V6; +#endif + +static enum bp_result set_pixel_clock_v5( + struct bios_parser *bp, + struct bp_pixel_clock_parameters *bp_params) +{ + enum bp_result result = BP_RESULT_FAILURE; + SET_PIXEL_CLOCK_PS_ALLOCATION_V5 clk; + uint8_t controller_id; + uint32_t pll_id; + + memset(&clk, 0, sizeof(clk)); + + if (bp->cmd_helper->clock_source_id_to_atom(bp_params->pll_id, &pll_id) + && bp->cmd_helper->controller_id_to_atom( + bp_params->controller_id, &controller_id)) { + clk.sPCLKInput.ucCRTC = controller_id; + clk.sPCLKInput.ucPpll = (uint8_t)pll_id; + clk.sPCLKInput.ucRefDiv = + (uint8_t)(bp_params->reference_divider); + clk.sPCLKInput.usFbDiv = + cpu_to_le16((uint16_t)(bp_params->feedback_divider)); + clk.sPCLKInput.ulFbDivDecFrac = + cpu_to_le32(bp_params->fractional_feedback_divider); + clk.sPCLKInput.ucPostDiv = + (uint8_t)(bp_params->pixel_clock_post_divider); + clk.sPCLKInput.ucTransmitterID = + bp->cmd_helper->encoder_id_to_atom( + dal_graphics_object_id_get_encoder_id( + bp_params->encoder_object_id)); + clk.sPCLKInput.ucEncoderMode = + (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom( + bp_params->signal_type, false); + + /* We need to convert from KHz units into 10KHz units */ + clk.sPCLKInput.usPixelClock = + cpu_to_le16((uint16_t)(bp_params->target_pixel_clock / 10)); + + if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL) + clk.sPCLKInput.ucMiscInfo |= + PIXEL_CLOCK_MISC_FORCE_PROG_PPLL; + + if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC) + clk.sPCLKInput.ucMiscInfo |= + PIXEL_CLOCK_MISC_REF_DIV_SRC; + + /* clkV5.ucMiscInfo bit[3:2]= HDMI panel bit depth: =0: 24bpp + * =1:30bpp, =2:32bpp + * driver choose program it itself, i.e. here we program it + * to 888 by default. + */ + + if (EXEC_BIOS_CMD_TABLE(SetPixelClock, clk)) + result = BP_RESULT_OK; + } + + return result; +} + +static enum bp_result set_pixel_clock_v6( + struct bios_parser *bp, + struct bp_pixel_clock_parameters *bp_params) +{ + enum bp_result result = BP_RESULT_FAILURE; + SET_PIXEL_CLOCK_PS_ALLOCATION_V6 clk; + uint8_t controller_id; + uint32_t pll_id; + + memset(&clk, 0, sizeof(clk)); + + if (bp->cmd_helper->clock_source_id_to_atom(bp_params->pll_id, &pll_id) + && bp->cmd_helper->controller_id_to_atom( + bp_params->controller_id, &controller_id)) { + /* Note: VBIOS still wants to use ucCRTC name which is now + * 1 byte in ULONG + *typedef struct _CRTC_PIXEL_CLOCK_FREQ + *{ + * target the pixel clock to drive the CRTC timing. + * ULONG ulPixelClock:24; + * 0 means disable PPLL/DCPLL. Expanded to 24 bits comparing to + * previous version. + * ATOM_CRTC1~6, indicate the CRTC controller to + * ULONG ucCRTC:8; + * drive the pixel clock. not used for DCPLL case. + *}CRTC_PIXEL_CLOCK_FREQ; + *union + *{ + * pixel clock and CRTC id frequency + * CRTC_PIXEL_CLOCK_FREQ ulCrtcPclkFreq; + * ULONG ulDispEngClkFreq; dispclk frequency + *}; + */ + clk.sPCLKInput.ulCrtcPclkFreq.ucCRTC = controller_id; + clk.sPCLKInput.ucPpll = (uint8_t) pll_id; + clk.sPCLKInput.ucRefDiv = + (uint8_t) bp_params->reference_divider; + clk.sPCLKInput.usFbDiv = + cpu_to_le16((uint16_t) bp_params->feedback_divider); + clk.sPCLKInput.ulFbDivDecFrac = + cpu_to_le32(bp_params->fractional_feedback_divider); + clk.sPCLKInput.ucPostDiv = + (uint8_t) bp_params->pixel_clock_post_divider; + clk.sPCLKInput.ucTransmitterID = + bp->cmd_helper->encoder_id_to_atom( + dal_graphics_object_id_get_encoder_id( + bp_params->encoder_object_id)); + clk.sPCLKInput.ucEncoderMode = + (uint8_t) bp->cmd_helper->encoder_mode_bp_to_atom( + bp_params->signal_type, false); + + /* We need to convert from KHz units into 10KHz units */ + clk.sPCLKInput.ulCrtcPclkFreq.ulPixelClock = + cpu_to_le32(bp_params->target_pixel_clock / 10); + + if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL) { + clk.sPCLKInput.ucMiscInfo |= + PIXEL_CLOCK_V6_MISC_FORCE_PROG_PPLL; + } + + if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC) { + clk.sPCLKInput.ucMiscInfo |= + PIXEL_CLOCK_V6_MISC_REF_DIV_SRC; + } + + /* clkV6.ucMiscInfo bit[3:2]= HDMI panel bit depth: =0: + * 24bpp =1:30bpp, =2:32bpp + * driver choose program it itself, i.e. here we pass required + * target rate that includes deep color. + */ + + if (EXEC_BIOS_CMD_TABLE(SetPixelClock, clk)) + result = BP_RESULT_OK; + } + + return result; +} + +static enum bp_result set_pixel_clock_v7( + struct bios_parser *bp, + struct bp_pixel_clock_parameters *bp_params) +{ + enum bp_result result = BP_RESULT_FAILURE; +#ifdef LATEST_ATOM_BIOS_SUPPORT + PIXEL_CLOCK_PARAMETERS_V7 clk; + uint8_t controller_id; + uint32_t pll_id; + + memset(&clk, 0, sizeof(clk)); + + if (bp->cmd_helper->clock_source_id_to_atom(bp_params->pll_id, &pll_id) + && bp->cmd_helper->controller_id_to_atom(bp_params->controller_id, &controller_id)) { + /* Note: VBIOS still wants to use ucCRTC name which is now + * 1 byte in ULONG + *typedef struct _CRTC_PIXEL_CLOCK_FREQ + *{ + * target the pixel clock to drive the CRTC timing. + * ULONG ulPixelClock:24; + * 0 means disable PPLL/DCPLL. Expanded to 24 bits comparing to + * previous version. + * ATOM_CRTC1~6, indicate the CRTC controller to + * ULONG ucCRTC:8; + * drive the pixel clock. not used for DCPLL case. + *}CRTC_PIXEL_CLOCK_FREQ; + *union + *{ + * pixel clock and CRTC id frequency + * CRTC_PIXEL_CLOCK_FREQ ulCrtcPclkFreq; + * ULONG ulDispEngClkFreq; dispclk frequency + *}; + */ + clk.ucCRTC = controller_id; + clk.ucPpll = (uint8_t) pll_id; + clk.ucTransmitterID = bp->cmd_helper->encoder_id_to_atom(dal_graphics_object_id_get_encoder_id(bp_params->encoder_object_id)); + clk.ucEncoderMode = (uint8_t) bp->cmd_helper->encoder_mode_bp_to_atom(bp_params->signal_type, false); + + /* We need to convert from KHz units into 10KHz units */ + clk.ulPixelClock = cpu_to_le32(bp_params->target_pixel_clock * 10); + + clk.ucDeepColorRatio = (uint8_t) bp->cmd_helper->transmitter_color_depth_to_atom(bp_params->color_depth); + + if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL) + clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_FORCE_PROG_PPLL; + + if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC) + clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC; + + if (bp_params->flags.PROGRAM_PHY_PLL_ONLY) + clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_PROG_PHYPLL; + + if (bp_params->flags.SUPPORT_YUV_420) + clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_YUV420_MODE; + + if (bp_params->flags.SET_XTALIN_REF_SRC) + clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC_XTALIN; + + if (bp_params->flags.SET_GENLOCK_REF_DIV_SRC) + clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC_GENLK; + + if (bp_params->signal_type == SIGNAL_TYPE_DVI_DUAL_LINK) + clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_DVI_DUALLINK_EN; + + if (EXEC_BIOS_CMD_TABLE(SetPixelClock, clk)) + result = BP_RESULT_OK; + } +#endif + return result; +} + +/******************************************************************************* + ******************************************************************************** + ** + ** ENABLE PIXEL CLOCK SS + ** + ******************************************************************************** + *******************************************************************************/ +static enum bp_result enable_spread_spectrum_on_ppll_v1( + struct bios_parser *bp, + struct bp_spread_spectrum_parameters *bp_params, + bool enable); +static enum bp_result enable_spread_spectrum_on_ppll_v2( + struct bios_parser *bp, + struct bp_spread_spectrum_parameters *bp_params, + bool enable); +static enum bp_result enable_spread_spectrum_on_ppll_v3( + struct bios_parser *bp, + struct bp_spread_spectrum_parameters *bp_params, + bool enable); + +static void init_enable_spread_spectrum_on_ppll(struct bios_parser *bp) +{ + switch (BIOS_CMD_TABLE_PARA_REVISION(EnableSpreadSpectrumOnPPLL)) { + case 1: + bp->cmd_tbl.enable_spread_spectrum_on_ppll = + enable_spread_spectrum_on_ppll_v1; + break; + case 2: + bp->cmd_tbl.enable_spread_spectrum_on_ppll = + enable_spread_spectrum_on_ppll_v2; + break; + case 3: + bp->cmd_tbl.enable_spread_spectrum_on_ppll = + enable_spread_spectrum_on_ppll_v3; + break; + default: + bp->cmd_tbl.enable_spread_spectrum_on_ppll = NULL; + break; + } +} + +static enum bp_result enable_spread_spectrum_on_ppll_v1( + struct bios_parser *bp, + struct bp_spread_spectrum_parameters *bp_params, + bool enable) +{ + enum bp_result result = BP_RESULT_FAILURE; + ENABLE_SPREAD_SPECTRUM_ON_PPLL params; + + memset(¶ms, 0, sizeof(params)); + + if ((enable == true) && (bp_params->percentage > 0)) + params.ucEnable = ATOM_ENABLE; + else + params.ucEnable = ATOM_DISABLE; + + params.usSpreadSpectrumPercentage = + cpu_to_le16((uint16_t)bp_params->percentage); + params.ucSpreadSpectrumStep = + (uint8_t)bp_params->ver1.step; + params.ucSpreadSpectrumDelay = + (uint8_t)bp_params->ver1.delay; + /* convert back to unit of 10KHz */ + params.ucSpreadSpectrumRange = + (uint8_t)(bp_params->ver1.range / 10000); + + if (bp_params->flags.EXTERNAL_SS) + params.ucSpreadSpectrumType |= ATOM_EXTERNAL_SS_MASK; + + if (bp_params->flags.CENTER_SPREAD) + params.ucSpreadSpectrumType |= ATOM_SS_CENTRE_SPREAD_MODE; + + if (bp_params->pll_id == CLOCK_SOURCE_ID_PLL1) + params.ucPpll = ATOM_PPLL1; + else if (bp_params->pll_id == CLOCK_SOURCE_ID_PLL2) + params.ucPpll = ATOM_PPLL2; + else + BREAK_TO_DEBUGGER(); /* Unexpected PLL value!! */ + + if (EXEC_BIOS_CMD_TABLE(EnableSpreadSpectrumOnPPLL, params)) + result = BP_RESULT_OK; + + return result; +} + +static enum bp_result enable_spread_spectrum_on_ppll_v2( + struct bios_parser *bp, + struct bp_spread_spectrum_parameters *bp_params, + bool enable) +{ + enum bp_result result = BP_RESULT_FAILURE; + ENABLE_SPREAD_SPECTRUM_ON_PPLL_V2 params; + + memset(¶ms, 0, sizeof(params)); + + if (bp_params->pll_id == CLOCK_SOURCE_ID_PLL1) + params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V2_P1PLL; + else if (bp_params->pll_id == CLOCK_SOURCE_ID_PLL2) + params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V2_P2PLL; + else + BREAK_TO_DEBUGGER(); /* Unexpected PLL value!! */ + + if ((enable == true) && (bp_params->percentage > 0)) { + params.ucEnable = ATOM_ENABLE; + + params.usSpreadSpectrumPercentage = + cpu_to_le16((uint16_t)(bp_params->percentage)); + params.usSpreadSpectrumStep = + cpu_to_le16((uint16_t)(bp_params->ds.ds_frac_size)); + + if (bp_params->flags.EXTERNAL_SS) + params.ucSpreadSpectrumType |= + ATOM_PPLL_SS_TYPE_V2_EXT_SPREAD; + + if (bp_params->flags.CENTER_SPREAD) + params.ucSpreadSpectrumType |= + ATOM_PPLL_SS_TYPE_V2_CENTRE_SPREAD; + + /* Both amounts need to be left shifted first before bit + * comparison. Otherwise, the result will always be zero here + */ + params.usSpreadSpectrumAmount = cpu_to_le16((uint16_t)( + ((bp_params->ds.feedback_amount << + ATOM_PPLL_SS_AMOUNT_V2_FBDIV_SHIFT) & + ATOM_PPLL_SS_AMOUNT_V2_FBDIV_MASK) | + ((bp_params->ds.nfrac_amount << + ATOM_PPLL_SS_AMOUNT_V2_NFRAC_SHIFT) & + ATOM_PPLL_SS_AMOUNT_V2_NFRAC_MASK))); + } else + params.ucEnable = ATOM_DISABLE; + + if (EXEC_BIOS_CMD_TABLE(EnableSpreadSpectrumOnPPLL, params)) + result = BP_RESULT_OK; + + return result; +} + +static enum bp_result enable_spread_spectrum_on_ppll_v3( + struct bios_parser *bp, + struct bp_spread_spectrum_parameters *bp_params, + bool enable) +{ + enum bp_result result = BP_RESULT_FAILURE; + ENABLE_SPREAD_SPECTRUM_ON_PPLL_V3 params; + + memset(¶ms, 0, sizeof(params)); + + switch (bp_params->pll_id) { + case CLOCK_SOURCE_ID_PLL0: + /* ATOM_PPLL_SS_TYPE_V3_P0PLL; this is pixel clock only, + * not for SI display clock. + */ + params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_DCPLL; + break; + case CLOCK_SOURCE_ID_PLL1: + params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_P1PLL; + break; + + case CLOCK_SOURCE_ID_PLL2: + params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_P2PLL; + break; + + case CLOCK_SOURCE_ID_DCPLL: + params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_DCPLL; + break; + + default: + BREAK_TO_DEBUGGER(); + /* Unexpected PLL value!! */ + return result; + } + + if (enable == true) { + params.ucEnable = ATOM_ENABLE; + + params.usSpreadSpectrumAmountFrac = + cpu_to_le16((uint16_t)(bp_params->ds_frac_amount)); + params.usSpreadSpectrumStep = + cpu_to_le16((uint16_t)(bp_params->ds.ds_frac_size)); + + if (bp_params->flags.EXTERNAL_SS) + params.ucSpreadSpectrumType |= + ATOM_PPLL_SS_TYPE_V3_EXT_SPREAD; + if (bp_params->flags.CENTER_SPREAD) + params.ucSpreadSpectrumType |= + ATOM_PPLL_SS_TYPE_V3_CENTRE_SPREAD; + + /* Both amounts need to be left shifted first before bit + * comparison. Otherwise, the result will always be zero here + */ + params.usSpreadSpectrumAmount = cpu_to_le16((uint16_t)( + ((bp_params->ds.feedback_amount << + ATOM_PPLL_SS_AMOUNT_V3_FBDIV_SHIFT) & + ATOM_PPLL_SS_AMOUNT_V3_FBDIV_MASK) | + ((bp_params->ds.nfrac_amount << + ATOM_PPLL_SS_AMOUNT_V3_NFRAC_SHIFT) & + ATOM_PPLL_SS_AMOUNT_V3_NFRAC_MASK))); + } else + params.ucEnable = ATOM_DISABLE; + + if (EXEC_BIOS_CMD_TABLE(EnableSpreadSpectrumOnPPLL, params)) + result = BP_RESULT_OK; + + return result; +} + +/******************************************************************************* + ******************************************************************************** + ** + ** ADJUST DISPLAY PLL + ** + ******************************************************************************** + *******************************************************************************/ + +static enum bp_result adjust_display_pll_v2( + struct bios_parser *bp, + struct bp_adjust_pixel_clock_parameters *bp_params); +static enum bp_result adjust_display_pll_v3( + struct bios_parser *bp, + struct bp_adjust_pixel_clock_parameters *bp_params); + +static void init_adjust_display_pll(struct bios_parser *bp) +{ + switch (BIOS_CMD_TABLE_PARA_REVISION(AdjustDisplayPll)) { + case 2: + bp->cmd_tbl.adjust_display_pll = adjust_display_pll_v2; + break; + case 3: + bp->cmd_tbl.adjust_display_pll = adjust_display_pll_v3; + break; + default: + bp->cmd_tbl.adjust_display_pll = NULL; + break; + } +} + +static enum bp_result adjust_display_pll_v2( + struct bios_parser *bp, + struct bp_adjust_pixel_clock_parameters *bp_params) +{ + enum bp_result result = BP_RESULT_FAILURE; + ADJUST_DISPLAY_PLL_PS_ALLOCATION params = { 0 }; + + /* We need to convert from KHz units into 10KHz units and then convert + * output pixel clock back 10KHz-->KHz */ + uint32_t pixel_clock_10KHz_in = bp_params->pixel_clock / 10; + + params.usPixelClock = cpu_to_le16((uint16_t)(pixel_clock_10KHz_in)); + params.ucTransmitterID = + bp->cmd_helper->encoder_id_to_atom( + dal_graphics_object_id_get_encoder_id( + bp_params->encoder_object_id)); + params.ucEncodeMode = + (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom( + bp_params->signal_type, false); + return result; +} + +static enum bp_result adjust_display_pll_v3( + struct bios_parser *bp, + struct bp_adjust_pixel_clock_parameters *bp_params) +{ + enum bp_result result = BP_RESULT_FAILURE; + ADJUST_DISPLAY_PLL_PS_ALLOCATION_V3 params; + uint32_t pixel_clk_10_kHz_in = bp_params->pixel_clock / 10; + + memset(¶ms, 0, sizeof(params)); + + /* We need to convert from KHz units into 10KHz units and then convert + * output pixel clock back 10KHz-->KHz */ + params.sInput.usPixelClock = cpu_to_le16((uint16_t)pixel_clk_10_kHz_in); + params.sInput.ucTransmitterID = + bp->cmd_helper->encoder_id_to_atom( + dal_graphics_object_id_get_encoder_id( + bp_params->encoder_object_id)); + params.sInput.ucEncodeMode = + (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom( + bp_params->signal_type, false); + + if (bp_params->ss_enable == true) + params.sInput.ucDispPllConfig |= DISPPLL_CONFIG_SS_ENABLE; + + if (bp_params->signal_type == SIGNAL_TYPE_DVI_DUAL_LINK) + params.sInput.ucDispPllConfig |= DISPPLL_CONFIG_DUAL_LINK; + + if (EXEC_BIOS_CMD_TABLE(AdjustDisplayPll, params)) { + /* Convert output pixel clock back 10KHz-->KHz: multiply + * original pixel clock in KHz by ratio + * [output pxlClk/input pxlClk] */ + uint64_t pixel_clk_10_khz_out = + (uint64_t)le32_to_cpu(params.sOutput.ulDispPllFreq); + uint64_t pixel_clk = (uint64_t)bp_params->pixel_clock; + + if (pixel_clk_10_kHz_in != 0) { + bp_params->adjusted_pixel_clock = + div_u64(pixel_clk * pixel_clk_10_khz_out, + pixel_clk_10_kHz_in); + } else { + bp_params->adjusted_pixel_clock = 0; + BREAK_TO_DEBUGGER(); + } + + bp_params->reference_divider = params.sOutput.ucRefDiv; + bp_params->pixel_clock_post_divider = params.sOutput.ucPostDiv; + + result = BP_RESULT_OK; + } + + return result; +} + +/******************************************************************************* + ******************************************************************************** + ** + ** DAC ENCODER CONTROL + ** + ******************************************************************************** + *******************************************************************************/ + +static enum bp_result dac1_encoder_control_v1( + struct bios_parser *bp, + bool enable, + uint32_t pixel_clock, + uint8_t dac_standard); +static enum bp_result dac2_encoder_control_v1( + struct bios_parser *bp, + bool enable, + uint32_t pixel_clock, + uint8_t dac_standard); + +static void init_dac_encoder_control(struct bios_parser *bp) +{ + switch (BIOS_CMD_TABLE_PARA_REVISION(DAC1EncoderControl)) { + case 1: + bp->cmd_tbl.dac1_encoder_control = dac1_encoder_control_v1; + break; + default: + bp->cmd_tbl.dac1_encoder_control = NULL; + break; + } + switch (BIOS_CMD_TABLE_PARA_REVISION(DAC2EncoderControl)) { + case 1: + bp->cmd_tbl.dac2_encoder_control = dac2_encoder_control_v1; + break; + default: + bp->cmd_tbl.dac2_encoder_control = NULL; + break; + } +} + +static void dac_encoder_control_prepare_params( + DAC_ENCODER_CONTROL_PS_ALLOCATION *params, + bool enable, + uint32_t pixel_clock, + uint8_t dac_standard) +{ + params->ucDacStandard = dac_standard; + if (enable) + params->ucAction = ATOM_ENABLE; + else + params->ucAction = ATOM_DISABLE; + + /* We need to convert from KHz units into 10KHz units + * it looks as if the TvControl do not care about pixel clock + */ + params->usPixelClock = cpu_to_le16((uint16_t)(pixel_clock / 10)); +} + +static enum bp_result dac1_encoder_control_v1( + struct bios_parser *bp, + bool enable, + uint32_t pixel_clock, + uint8_t dac_standard) +{ + enum bp_result result = BP_RESULT_FAILURE; + DAC_ENCODER_CONTROL_PS_ALLOCATION params; + + dac_encoder_control_prepare_params( + ¶ms, + enable, + pixel_clock, + dac_standard); + + if (EXEC_BIOS_CMD_TABLE(DAC1EncoderControl, params)) + result = BP_RESULT_OK; + + return result; +} + +static enum bp_result dac2_encoder_control_v1( + struct bios_parser *bp, + bool enable, + uint32_t pixel_clock, + uint8_t dac_standard) +{ + enum bp_result result = BP_RESULT_FAILURE; + DAC_ENCODER_CONTROL_PS_ALLOCATION params; + + dac_encoder_control_prepare_params( + ¶ms, + enable, + pixel_clock, + dac_standard); + + if (EXEC_BIOS_CMD_TABLE(DAC2EncoderControl, params)) + result = BP_RESULT_OK; + + return result; +} + +/******************************************************************************* + ******************************************************************************** + ** + ** DAC OUTPUT CONTROL + ** + ******************************************************************************** + *******************************************************************************/ +static enum bp_result dac1_output_control_v1( + struct bios_parser *bp, + bool enable); +static enum bp_result dac2_output_control_v1( + struct bios_parser *bp, + bool enable); + +static void init_dac_output_control(struct bios_parser *bp) +{ + switch (BIOS_CMD_TABLE_PARA_REVISION(DAC1OutputControl)) { + case 1: + bp->cmd_tbl.dac1_output_control = dac1_output_control_v1; + break; + default: + bp->cmd_tbl.dac1_output_control = NULL; + break; + } + switch (BIOS_CMD_TABLE_PARA_REVISION(DAC2OutputControl)) { + case 1: + bp->cmd_tbl.dac2_output_control = dac2_output_control_v1; + break; + default: + bp->cmd_tbl.dac2_output_control = NULL; + break; + } +} + +static enum bp_result dac1_output_control_v1( + struct bios_parser *bp, bool enable) +{ + enum bp_result result = BP_RESULT_FAILURE; + DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION params; + + if (enable) + params.ucAction = ATOM_ENABLE; + else + params.ucAction = ATOM_DISABLE; + + if (EXEC_BIOS_CMD_TABLE(DAC1OutputControl, params)) + result = BP_RESULT_OK; + + return result; +} + +static enum bp_result dac2_output_control_v1( + struct bios_parser *bp, bool enable) +{ + enum bp_result result = BP_RESULT_FAILURE; + DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION params; + + if (enable) + params.ucAction = ATOM_ENABLE; + else + params.ucAction = ATOM_DISABLE; + + if (EXEC_BIOS_CMD_TABLE(DAC2OutputControl, params)) + result = BP_RESULT_OK; + + return result; +} + +/******************************************************************************* + ******************************************************************************** + ** + ** BLANK CRTC + ** + ******************************************************************************** + *******************************************************************************/ + +static enum bp_result blank_crtc_v1( + struct bios_parser *bp, + struct bp_blank_crtc_parameters *bp_params, + bool blank); + +static void init_blank_crtc(struct bios_parser *bp) +{ + switch (BIOS_CMD_TABLE_PARA_REVISION(BlankCRTC)) { + case 1: + bp->cmd_tbl.blank_crtc = blank_crtc_v1; + break; + default: + bp->cmd_tbl.blank_crtc = NULL; + break; + } +} + +static enum bp_result blank_crtc_v1( + struct bios_parser *bp, + struct bp_blank_crtc_parameters *bp_params, + bool blank) +{ + enum bp_result result = BP_RESULT_FAILURE; + BLANK_CRTC_PARAMETERS params = {0}; + uint8_t atom_controller_id; + + if (bp->cmd_helper->controller_id_to_atom(bp_params->controller_id, + &atom_controller_id)) { + params.ucCRTC = (uint8_t)atom_controller_id; + + if (blank) + params.ucBlanking = ATOM_BLANKING; + else + params.ucBlanking = ATOM_BLANKING_OFF; + params.usBlackColorRCr = + cpu_to_le16((uint16_t)bp_params->black_color_rcr); + params.usBlackColorGY = + cpu_to_le16((uint16_t)bp_params->black_color_gy); + params.usBlackColorBCb = + cpu_to_le16((uint16_t)bp_params->black_color_bcb); + + if (EXEC_BIOS_CMD_TABLE(BlankCRTC, params)) + result = BP_RESULT_OK; + } else + /* Not support more than two CRTC as current ASIC, update this + * if needed. + */ + result = BP_RESULT_BADINPUT; + + return result; +} + +/******************************************************************************* + ******************************************************************************** + ** + ** SET CRTC TIMING + ** + ******************************************************************************** + *******************************************************************************/ + +static enum bp_result set_crtc_using_dtd_timing_v3( + struct bios_parser *bp, + struct bp_hw_crtc_timing_parameters *bp_params); +static enum bp_result set_crtc_timing_v1( + struct bios_parser *bp, + struct bp_hw_crtc_timing_parameters *bp_params); + +static void init_set_crtc_timing(struct bios_parser *bp) +{ + uint32_t dtd_version = + BIOS_CMD_TABLE_PARA_REVISION(SetCRTC_UsingDTDTiming); + if (dtd_version > 2) + switch (dtd_version) { + case 3: + bp->cmd_tbl.set_crtc_timing = + set_crtc_using_dtd_timing_v3; + break; + default: + bp->cmd_tbl.set_crtc_timing = NULL; + break; + } + else + switch (BIOS_CMD_TABLE_PARA_REVISION(SetCRTC_Timing)) { + case 1: + bp->cmd_tbl.set_crtc_timing = set_crtc_timing_v1; + break; + default: + bp->cmd_tbl.set_crtc_timing = NULL; + break; + } +} + +static enum bp_result set_crtc_timing_v1( + struct bios_parser *bp, + struct bp_hw_crtc_timing_parameters *bp_params) +{ + enum bp_result result = BP_RESULT_FAILURE; + SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION params = {0}; + uint8_t atom_controller_id; + + if (bp->cmd_helper->controller_id_to_atom( + bp_params->controller_id, &atom_controller_id)) + params.ucCRTC = atom_controller_id; + + params.usH_Total = cpu_to_le16((uint16_t)(bp_params->h_total)); + params.usH_Disp = cpu_to_le16((uint16_t)(bp_params->h_addressable)); + params.usH_SyncStart = cpu_to_le16((uint16_t)(bp_params->h_sync_start)); + params.usH_SyncWidth = cpu_to_le16((uint16_t)(bp_params->h_sync_width)); + params.usV_Total = cpu_to_le16((uint16_t)(bp_params->v_total)); + params.usV_Disp = cpu_to_le16((uint16_t)(bp_params->v_addressable)); + params.usV_SyncStart = + cpu_to_le16((uint16_t)(bp_params->v_sync_start)); + params.usV_SyncWidth = + cpu_to_le16((uint16_t)(bp_params->v_sync_width)); + + /* VBIOS does not expect any value except zero into this call, for + * underscan use another entry ProgramOverscan call but when mode + * 1776x1000 with the overscan 72x44 .e.i. 1920x1080 @30 DAL2 is ok, + * but when same ,but 60 Hz there is corruption + * DAL1 does not allow the mode 1776x1000@60 + */ + params.ucOverscanRight = (uint8_t)bp_params->h_overscan_right; + params.ucOverscanLeft = (uint8_t)bp_params->h_overscan_left; + params.ucOverscanBottom = (uint8_t)bp_params->v_overscan_bottom; + params.ucOverscanTop = (uint8_t)bp_params->v_overscan_top; + + if (0 == bp_params->flags.HSYNC_POSITIVE_POLARITY) + params.susModeMiscInfo.usAccess = + cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_HSYNC_POLARITY); + + if (0 == bp_params->flags.VSYNC_POSITIVE_POLARITY) + params.susModeMiscInfo.usAccess = + cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_VSYNC_POLARITY); + + if (bp_params->flags.INTERLACE) { + params.susModeMiscInfo.usAccess = + cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_INTERLACE); + + /* original DAL code has this condition to apply tis for + * non-TV/CV only due to complex MV testing for possible + * impact + * if (pACParameters->signal != SignalType_YPbPr && + * pACParameters->signal != SignalType_Composite && + * pACParameters->signal != SignalType_SVideo) + */ + /* HW will deduct 0.5 line from 2nd feild. + * i.e. for 1080i, it is 2 lines for 1st field, 2.5 + * lines for the 2nd feild. we need input as 5 instead + * of 4, but it is 4 either from Edid data + * (spec CEA 861) or CEA timing table. + */ + params.usV_SyncStart = + cpu_to_le16((uint16_t)(bp_params->v_sync_start + 1)); + } + + if (bp_params->flags.HORZ_COUNT_BY_TWO) + params.susModeMiscInfo.usAccess = + cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_DOUBLE_CLOCK_MODE); + + if (EXEC_BIOS_CMD_TABLE(SetCRTC_Timing, params)) + result = BP_RESULT_OK; + + return result; +} + +static enum bp_result set_crtc_using_dtd_timing_v3( + struct bios_parser *bp, + struct bp_hw_crtc_timing_parameters *bp_params) +{ + enum bp_result result = BP_RESULT_FAILURE; + SET_CRTC_USING_DTD_TIMING_PARAMETERS params = {0}; + uint8_t atom_controller_id; + + if (bp->cmd_helper->controller_id_to_atom( + bp_params->controller_id, &atom_controller_id)) + params.ucCRTC = atom_controller_id; + + /* bios usH_Size wants h addressable size */ + params.usH_Size = cpu_to_le16((uint16_t)bp_params->h_addressable); + /* bios usH_Blanking_Time wants borders included in blanking */ + params.usH_Blanking_Time = + cpu_to_le16((uint16_t)(bp_params->h_total - bp_params->h_addressable)); + /* bios usV_Size wants v addressable size */ + params.usV_Size = cpu_to_le16((uint16_t)bp_params->v_addressable); + /* bios usV_Blanking_Time wants borders included in blanking */ + params.usV_Blanking_Time = + cpu_to_le16((uint16_t)(bp_params->v_total - bp_params->v_addressable)); + /* bios usHSyncOffset is the offset from the end of h addressable, + * our horizontalSyncStart is the offset from the beginning + * of h addressable */ + params.usH_SyncOffset = + cpu_to_le16((uint16_t)(bp_params->h_sync_start - bp_params->h_addressable)); + params.usH_SyncWidth = cpu_to_le16((uint16_t)bp_params->h_sync_width); + /* bios usHSyncOffset is the offset from the end of v addressable, + * our verticalSyncStart is the offset from the beginning of + * v addressable */ + params.usV_SyncOffset = + cpu_to_le16((uint16_t)(bp_params->v_sync_start - bp_params->v_addressable)); + params.usV_SyncWidth = cpu_to_le16((uint16_t)bp_params->v_sync_width); + + /* we assume that overscan from original timing does not get bigger + * than 255 + * we will program all the borders in the Set CRTC Overscan call below + */ + + if (0 == bp_params->flags.HSYNC_POSITIVE_POLARITY) + params.susModeMiscInfo.usAccess = + cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_HSYNC_POLARITY); + + if (0 == bp_params->flags.VSYNC_POSITIVE_POLARITY) + params.susModeMiscInfo.usAccess = + cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_VSYNC_POLARITY); + + if (bp_params->flags.INTERLACE) { + params.susModeMiscInfo.usAccess = + cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_INTERLACE); + + /* original DAL code has this condition to apply this + * for non-TV/CV only + * due to complex MV testing for possible impact + * if ( pACParameters->signal != SignalType_YPbPr && + * pACParameters->signal != SignalType_Composite && + * pACParameters->signal != SignalType_SVideo) + */ + { + /* HW will deduct 0.5 line from 2nd feild. + * i.e. for 1080i, it is 2 lines for 1st field, + * 2.5 lines for the 2nd feild. we need input as 5 + * instead of 4. + * but it is 4 either from Edid data (spec CEA 861) + * or CEA timing table. + */ + params.usV_SyncOffset = + cpu_to_le16(le16_to_cpu(params.usV_SyncOffset) + 1); + + } + } + + if (bp_params->flags.HORZ_COUNT_BY_TWO) + params.susModeMiscInfo.usAccess = + cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_DOUBLE_CLOCK_MODE); + + if (EXEC_BIOS_CMD_TABLE(SetCRTC_UsingDTDTiming, params)) + result = BP_RESULT_OK; + + return result; +} + +/******************************************************************************* + ******************************************************************************** + ** + ** SET CRTC OVERSCAN + ** + ******************************************************************************** + *******************************************************************************/ + +static enum bp_result set_crtc_overscan_v1( + struct bios_parser *bp, + struct bp_hw_crtc_overscan_parameters *bp_params); + +static void init_set_crtc_overscan(struct bios_parser *bp) +{ + switch (BIOS_CMD_TABLE_PARA_REVISION(SetCRTC_OverScan)) { + case 1: + bp->cmd_tbl.set_crtc_overscan = set_crtc_overscan_v1; + break; + default: + bp->cmd_tbl.set_crtc_overscan = NULL; + break; + } +} + +static enum bp_result set_crtc_overscan_v1( + struct bios_parser *bp, + struct bp_hw_crtc_overscan_parameters *bp_params) +{ + enum bp_result result = BP_RESULT_FAILURE; + SET_CRTC_OVERSCAN_PARAMETERS params = {0}; + uint8_t atom_controller_id; + + if (bp->cmd_helper->controller_id_to_atom( + bp_params->controller_id, &atom_controller_id)) + params.ucCRTC = atom_controller_id; + else + return BP_RESULT_BADINPUT; + + params.usOverscanRight = + cpu_to_le16((uint16_t)bp_params->h_overscan_right); + params.usOverscanLeft = + cpu_to_le16((uint16_t)bp_params->h_overscan_left); + params.usOverscanBottom = + cpu_to_le16((uint16_t)bp_params->v_overscan_bottom); + params.usOverscanTop = + cpu_to_le16((uint16_t)bp_params->v_overscan_top); + + if (EXEC_BIOS_CMD_TABLE(SetCRTC_OverScan, params)) + result = BP_RESULT_OK; + + return result; +} + +/******************************************************************************* + ******************************************************************************** + ** + ** SELECT CRTC SOURCE + ** + ******************************************************************************** + *******************************************************************************/ + +static enum bp_result select_crtc_source_v2( + struct bios_parser *bp, + struct bp_crtc_source_select *bp_params); +static enum bp_result select_crtc_source_v3( + struct bios_parser *bp, + struct bp_crtc_source_select *bp_params); + +static void init_select_crtc_source(struct bios_parser *bp) +{ + switch (BIOS_CMD_TABLE_PARA_REVISION(SelectCRTC_Source)) { + case 2: + bp->cmd_tbl.select_crtc_source = select_crtc_source_v2; + break; + case 3: + bp->cmd_tbl.select_crtc_source = select_crtc_source_v3; + break; + default: + bp->cmd_tbl.select_crtc_source = NULL; + break; + } +} + +static enum bp_result select_crtc_source_v2( + struct bios_parser *bp, + struct bp_crtc_source_select *bp_params) +{ + enum bp_result result = BP_RESULT_FAILURE; + SELECT_CRTC_SOURCE_PARAMETERS_V2 params; + uint8_t atom_controller_id; + uint32_t atom_engine_id; + enum signal_type s = bp_params->signal; + + memset(¶ms, 0, sizeof(params)); + + /* set controller id */ + if (bp->cmd_helper->controller_id_to_atom( + bp_params->controller_id, &atom_controller_id)) + params.ucCRTC = atom_controller_id; + else + return BP_RESULT_FAILURE; + + /* set encoder id */ + if (bp->cmd_helper->engine_bp_to_atom( + bp_params->engine_id, &atom_engine_id)) + params.ucEncoderID = (uint8_t)atom_engine_id; + else + return BP_RESULT_FAILURE; + + if (SIGNAL_TYPE_EDP == s || + (SIGNAL_TYPE_DISPLAY_PORT == s && + SIGNAL_TYPE_LVDS == bp_params->sink_signal)) + s = SIGNAL_TYPE_LVDS; + + params.ucEncodeMode = + (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom( + s, bp_params->enable_dp_audio); + + if (EXEC_BIOS_CMD_TABLE(SelectCRTC_Source, params)) + result = BP_RESULT_OK; + + return result; +} + +static enum bp_result select_crtc_source_v3( + struct bios_parser *bp, + struct bp_crtc_source_select *bp_params) +{ + bool result = BP_RESULT_FAILURE; + SELECT_CRTC_SOURCE_PARAMETERS_V3 params; + uint8_t atom_controller_id; + uint32_t atom_engine_id; + enum signal_type s = bp_params->signal; + + memset(¶ms, 0, sizeof(params)); + + if (bp->cmd_helper->controller_id_to_atom(bp_params->controller_id, + &atom_controller_id)) + params.ucCRTC = atom_controller_id; + else + return result; + + if (bp->cmd_helper->engine_bp_to_atom(bp_params->engine_id, + &atom_engine_id)) + params.ucEncoderID = (uint8_t)atom_engine_id; + else + return result; + + if (SIGNAL_TYPE_EDP == s || + (SIGNAL_TYPE_DISPLAY_PORT == s && + SIGNAL_TYPE_LVDS == bp_params->sink_signal)) + s = SIGNAL_TYPE_LVDS; + + params.ucEncodeMode = + bp->cmd_helper->encoder_mode_bp_to_atom( + s, bp_params->enable_dp_audio); + /* Needed for VBIOS Random Spatial Dithering feature */ + params.ucDstBpc = (uint8_t)(bp_params->display_output_bit_depth); + + if (EXEC_BIOS_CMD_TABLE(SelectCRTC_Source, params)) + result = BP_RESULT_OK; + + return result; +} + +/******************************************************************************* + ******************************************************************************** + ** + ** ENABLE CRTC + ** + ******************************************************************************** + *******************************************************************************/ + +static enum bp_result enable_crtc_v1( + struct bios_parser *bp, + enum controller_id controller_id, + bool enable); + +static void init_enable_crtc(struct bios_parser *bp) +{ + switch (BIOS_CMD_TABLE_PARA_REVISION(EnableCRTC)) { + case 1: + bp->cmd_tbl.enable_crtc = enable_crtc_v1; + break; + default: + bp->cmd_tbl.enable_crtc = NULL; + break; + } +} + +static enum bp_result enable_crtc_v1( + struct bios_parser *bp, + enum controller_id controller_id, + bool enable) +{ + bool result = BP_RESULT_FAILURE; + ENABLE_CRTC_PARAMETERS params = {0}; + uint8_t id; + + if (bp->cmd_helper->controller_id_to_atom(controller_id, &id)) + params.ucCRTC = id; + else + return BP_RESULT_BADINPUT; + + if (enable) + params.ucEnable = ATOM_ENABLE; + else + params.ucEnable = ATOM_DISABLE; + + if (EXEC_BIOS_CMD_TABLE(EnableCRTC, params)) + result = BP_RESULT_OK; + + return result; +} + +/******************************************************************************* + ******************************************************************************** + ** + ** ENABLE CRTC MEM REQ + ** + ******************************************************************************** + *******************************************************************************/ + +static enum bp_result enable_crtc_mem_req_v1( + struct bios_parser *bp, + enum controller_id controller_id, + bool enable); + +static void init_enable_crtc_mem_req(struct bios_parser *bp) +{ + switch (BIOS_CMD_TABLE_PARA_REVISION(EnableCRTCMemReq)) { + case 1: + bp->cmd_tbl.enable_crtc_mem_req = enable_crtc_mem_req_v1; + break; + default: + bp->cmd_tbl.enable_crtc_mem_req = NULL; + break; + } +} + +static enum bp_result enable_crtc_mem_req_v1( + struct bios_parser *bp, + enum controller_id controller_id, + bool enable) +{ + bool result = BP_RESULT_BADINPUT; + ENABLE_CRTC_PARAMETERS params = {0}; + uint8_t id; + + if (bp->cmd_helper->controller_id_to_atom(controller_id, &id)) { + params.ucCRTC = id; + + if (enable) + params.ucEnable = ATOM_ENABLE; + else + params.ucEnable = ATOM_DISABLE; + + if (EXEC_BIOS_CMD_TABLE(EnableCRTCMemReq, params)) + result = BP_RESULT_OK; + else + result = BP_RESULT_FAILURE; + } + + return result; +} + +/******************************************************************************* + ******************************************************************************** + ** + ** DISPLAY PLL + ** + ******************************************************************************** + *******************************************************************************/ + +static enum bp_result program_clock_v5( + struct bios_parser *bp, + struct bp_pixel_clock_parameters *bp_params); +static enum bp_result program_clock_v6( + struct bios_parser *bp, + struct bp_pixel_clock_parameters *bp_params); + +static void init_program_clock(struct bios_parser *bp) +{ + switch (BIOS_CMD_TABLE_PARA_REVISION(SetPixelClock)) { + case 5: + bp->cmd_tbl.program_clock = program_clock_v5; + break; + case 6: + bp->cmd_tbl.program_clock = program_clock_v6; + break; + default: + bp->cmd_tbl.program_clock = NULL; + break; + } +} + +static enum bp_result program_clock_v5( + struct bios_parser *bp, + struct bp_pixel_clock_parameters *bp_params) +{ + enum bp_result result = BP_RESULT_FAILURE; + + SET_PIXEL_CLOCK_PS_ALLOCATION_V5 params; + uint32_t atom_pll_id; + + memset(¶ms, 0, sizeof(params)); + if (!bp->cmd_helper->clock_source_id_to_atom( + bp_params->pll_id, &atom_pll_id)) { + BREAK_TO_DEBUGGER(); /* Invalid Inpute!! */ + return BP_RESULT_BADINPUT; + } + + /* We need to convert from KHz units into 10KHz units */ + params.sPCLKInput.ucPpll = (uint8_t) atom_pll_id; + params.sPCLKInput.usPixelClock = + cpu_to_le16((uint16_t) (bp_params->target_pixel_clock / 10)); + params.sPCLKInput.ucCRTC = (uint8_t) ATOM_CRTC_INVALID; + + if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC) + params.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_MISC_REF_DIV_SRC; + + if (EXEC_BIOS_CMD_TABLE(SetPixelClock, params)) + result = BP_RESULT_OK; + + return result; +} + +static enum bp_result program_clock_v6( + struct bios_parser *bp, + struct bp_pixel_clock_parameters *bp_params) +{ + enum bp_result result = BP_RESULT_FAILURE; + + SET_PIXEL_CLOCK_PS_ALLOCATION_V6 params; + uint32_t atom_pll_id; + + memset(¶ms, 0, sizeof(params)); + + if (!bp->cmd_helper->clock_source_id_to_atom( + bp_params->pll_id, &atom_pll_id)) { + BREAK_TO_DEBUGGER(); /*Invalid Input!!*/ + return BP_RESULT_BADINPUT; + } + + /* We need to convert from KHz units into 10KHz units */ + params.sPCLKInput.ucPpll = (uint8_t)atom_pll_id; + params.sPCLKInput.ulDispEngClkFreq = + cpu_to_le32(bp_params->target_pixel_clock / 10); + + if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC) + params.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_MISC_REF_DIV_SRC; + + if (EXEC_BIOS_CMD_TABLE(SetPixelClock, params)) { + /* True display clock is returned by VBIOS if DFS bypass + * is enabled. */ + bp_params->dfs_bypass_display_clock = + (uint32_t)(le32_to_cpu(params.sPCLKInput.ulDispEngClkFreq) * 10); + result = BP_RESULT_OK; + } + + return result; +} + +/******************************************************************************* + ******************************************************************************** + ** + ** COMPUTE MEMORY ENGINE PLL + ** + ******************************************************************************** + *******************************************************************************/ + +static enum bp_result compute_memore_engine_pll_v4( + struct bios_parser *bp, + struct bp_display_clock_parameters *bp_params); + +static void init_compute_memore_engine_pll(struct bios_parser *bp) +{ + switch (BIOS_CMD_TABLE_PARA_REVISION(ComputeMemoryEnginePLL)) { + case 4: + bp->cmd_tbl.compute_memore_engine_pll = + compute_memore_engine_pll_v4; + break; + default: + bp->cmd_tbl.compute_memore_engine_pll = NULL; + break; + } +} + +static enum bp_result compute_memore_engine_pll_v4( + struct bios_parser *bp, + struct bp_display_clock_parameters *bp_params) +{ + enum bp_result result = BP_RESULT_FAILURE; + COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V4 params; + + memset(¶ms, 0, sizeof(params)); + + params.ulClock = cpu_to_le32(bp_params->target_display_clock / 10); + + /* Initialize this to the target clock in case this call fails */ + bp_params->actual_display_clock = bp_params->target_display_clock; + + if (EXEC_BIOS_CMD_TABLE(ComputeMemoryEnginePLL, params)) { + /* Convert from 10KHz units back to KHz */ + bp_params->actual_display_clock = + le32_to_cpu(params.ulClock) * 10; + bp_params->actual_post_divider_id = params.ucPostDiv; + result = BP_RESULT_OK; + } + + return result; +} + +/******************************************************************************* + ******************************************************************************** + ** + ** EXTERNAL ENCODER CONTROL + ** + ******************************************************************************** + *******************************************************************************/ + +static enum bp_result external_encoder_control_v3( + struct bios_parser *bp, + struct bp_external_encoder_control *cntl); + +static void init_external_encoder_control( + struct bios_parser *bp) +{ + switch (BIOS_CMD_TABLE_PARA_REVISION(ExternalEncoderControl)) { + case 3: + bp->cmd_tbl.external_encoder_control = + external_encoder_control_v3; + break; + default: + bp->cmd_tbl.external_encoder_control = NULL; + break; + } +} + +static enum bp_result external_encoder_control_v3( + struct bios_parser *bp, + struct bp_external_encoder_control *cntl) +{ + enum bp_result result = BP_RESULT_FAILURE; + + /* we need use _PS_Alloc struct */ + EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3 params; + EXTERNAL_ENCODER_CONTROL_PARAMETERS_V3 *cntl_params; + struct graphics_object_id encoder; + bool is_input_signal_dp = false; + + memset(¶ms, 0, sizeof(params)); + + cntl_params = ¶ms.sExtEncoder; + + encoder = cntl->encoder_id; + + /* check if encoder supports external encoder control table */ + switch (dal_graphics_object_id_get_encoder_id(encoder)) { + case ENCODER_ID_EXTERNAL_NUTMEG: + case ENCODER_ID_EXTERNAL_TRAVIS: + is_input_signal_dp = true; + break; + + default: + BREAK_TO_DEBUGGER(); + return BP_RESULT_BADINPUT; + } + + /* Fill information based on the action + * + * Bit[6:4]: indicate external encoder, applied to all functions. + * =0: external encoder1, mapped to external encoder enum id1 + * =1: external encoder2, mapped to external encoder enum id2 + * + * enum ObjectEnumId + * { + * EnumId_Unknown = 0, + * EnumId_1, + * EnumId_2, + * }; + */ + cntl_params->ucConfig = (uint8_t)((encoder.enum_id - 1) << 4); + + switch (cntl->action) { + case EXTERNAL_ENCODER_CONTROL_INIT: + /* output display connector type. Only valid in encoder + * initialization */ + cntl_params->usConnectorId = + cpu_to_le16((uint16_t)cntl->connector_obj_id.id); + break; + case EXTERNAL_ENCODER_CONTROL_SETUP: + /* EXTERNAL_ENCODER_CONTROL_PARAMETERS_V3 pixel clock unit in + * 10KHz + * output display device pixel clock frequency in unit of 10KHz. + * Only valid in setup and enableoutput + */ + cntl_params->usPixelClock = + cpu_to_le16((uint16_t)(cntl->pixel_clock / 10)); + /* Indicate display output signal type drive by external + * encoder, only valid in setup and enableoutput */ + cntl_params->ucEncoderMode = + (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom( + cntl->signal, false); + + if (is_input_signal_dp) { + /* Bit[0]: indicate link rate, =1: 2.7Ghz, =0: 1.62Ghz, + * only valid in encoder setup with DP mode. */ + if (LINK_RATE_HIGH == cntl->link_rate) + cntl_params->ucConfig |= 1; + /* output color depth Indicate encoder data bpc format + * in DP mode, only valid in encoder setup in DP mode. + */ + cntl_params->ucBitPerColor = + (uint8_t)(cntl->color_depth); + } + /* Indicate how many lanes used by external encoder, only valid + * in encoder setup and enableoutput. */ + cntl_params->ucLaneNum = (uint8_t)(cntl->lanes_number); + break; + case EXTERNAL_ENCODER_CONTROL_ENABLE: + cntl_params->usPixelClock = + cpu_to_le16((uint16_t)(cntl->pixel_clock / 10)); + cntl_params->ucEncoderMode = + (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom( + cntl->signal, false); + cntl_params->ucLaneNum = (uint8_t)cntl->lanes_number; + break; + default: + break; + } + + cntl_params->ucAction = (uint8_t)cntl->action; + + if (EXEC_BIOS_CMD_TABLE(ExternalEncoderControl, params)) + result = BP_RESULT_OK; + + return result; +} + +/******************************************************************************* + ******************************************************************************** + ** + ** ENABLE DISPLAY POWER GATING + ** + ******************************************************************************** + *******************************************************************************/ + +static enum bp_result enable_disp_power_gating_v2_1( + struct bios_parser *bp, + enum controller_id crtc_id, + enum bp_pipe_control_action action); + +static void init_enable_disp_power_gating( + struct bios_parser *bp) +{ + switch (BIOS_CMD_TABLE_PARA_REVISION(EnableDispPowerGating)) { + case 1: + bp->cmd_tbl.enable_disp_power_gating = + enable_disp_power_gating_v2_1; + break; + default: + bp->cmd_tbl.enable_disp_power_gating = NULL; + break; + } +} + +static enum bp_result enable_disp_power_gating_v2_1( + struct bios_parser *bp, + enum controller_id crtc_id, + enum bp_pipe_control_action action) +{ + enum bp_result result = BP_RESULT_FAILURE; + + ENABLE_DISP_POWER_GATING_PS_ALLOCATION params = {0}; + uint8_t atom_crtc_id; + + if (bp->cmd_helper->controller_id_to_atom(crtc_id, &atom_crtc_id)) + params.ucDispPipeId = atom_crtc_id; + else + return BP_RESULT_BADINPUT; + + params.ucEnable = + bp->cmd_helper->disp_power_gating_action_to_atom(action); + + if (EXEC_BIOS_CMD_TABLE(EnableDispPowerGating, params)) + result = BP_RESULT_OK; + + return result; +} + +/******************************************************************************* + ******************************************************************************** + ** + ** SET DCE CLOCK + ** + ******************************************************************************** + *******************************************************************************/ +#ifdef LATEST_ATOM_BIOS_SUPPORT +static enum bp_result set_dce_clock_v2_1( + struct bios_parser *bp, + struct bp_set_dce_clock_parameters *bp_params); +#endif + +static void init_set_dce_clock(struct bios_parser *bp) +{ +#ifdef LATEST_ATOM_BIOS_SUPPORT + switch (BIOS_CMD_TABLE_PARA_REVISION(SetDCEClock)) { + case 1: + bp->cmd_tbl.set_dce_clock = set_dce_clock_v2_1; + break; + default: + bp->cmd_tbl.set_dce_clock = NULL; + break; + } +#endif +} + +#ifdef LATEST_ATOM_BIOS_SUPPORT +static enum bp_result set_dce_clock_v2_1( + struct bios_parser *bp, + struct bp_set_dce_clock_parameters *bp_params) +{ + enum bp_result result = BP_RESULT_FAILURE; + + SET_DCE_CLOCK_PS_ALLOCATION_V2_1 params; + uint32_t atom_pll_id; + uint32_t atom_clock_type; + const struct command_table_helper *cmd = bp->cmd_helper; + + memset(¶ms, 0, sizeof(params)); + + if (!cmd->clock_source_id_to_atom(bp_params->pll_id, &atom_pll_id) || + !cmd->dc_clock_type_to_atom(bp_params->clock_type, &atom_clock_type)) + return BP_RESULT_BADINPUT; + + params.asParam.ucDCEClkSrc = atom_pll_id; + params.asParam.ucDCEClkType = atom_clock_type; + + if (bp_params->clock_type == DCECLOCK_TYPE_DPREFCLK) { + if (bp_params->flags.USE_GENLOCK_AS_SOURCE_FOR_DPREFCLK) + params.asParam.ucDCEClkFlag |= DCE_CLOCK_FLAG_PLL_REFCLK_SRC_GENLK; + + if (bp_params->flags.USE_PCIE_AS_SOURCE_FOR_DPREFCLK) + params.asParam.ucDCEClkFlag |= DCE_CLOCK_FLAG_PLL_REFCLK_SRC_PCIE; + + if (bp_params->flags.USE_XTALIN_AS_SOURCE_FOR_DPREFCLK) + params.asParam.ucDCEClkFlag |= DCE_CLOCK_FLAG_PLL_REFCLK_SRC_XTALIN; + + if (bp_params->flags.USE_GENERICA_AS_SOURCE_FOR_DPREFCLK) + params.asParam.ucDCEClkFlag |= DCE_CLOCK_FLAG_PLL_REFCLK_SRC_GENERICA; + } + else + /* only program clock frequency if display clock is used; VBIOS will program DPREFCLK */ + /* We need to convert from KHz units into 10KHz units */ + params.asParam.ulDCEClkFreq = cpu_to_le32(bp_params->target_clock_frequency / 10); + + if (EXEC_BIOS_CMD_TABLE(SetDCEClock, params)) { + /* Convert from 10KHz units back to KHz */ + bp_params->target_clock_frequency = le32_to_cpu(params.asParam.ulDCEClkFreq) * 10; + result = BP_RESULT_OK; + } + + return result; +} +#endif diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table.h b/drivers/gpu/drm/amd/display/dc/bios/command_table.h new file mode 100644 index 000000000000..e1cd21b6e968 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table.h @@ -0,0 +1,112 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_COMMAND_TABLE_H__ +#define __DAL_COMMAND_TABLE_H__ + +struct bios_parser; +struct bp_encoder_control; + +struct cmd_tbl { + enum bp_result (*dig_encoder_control)( + struct bios_parser *bp, + struct bp_encoder_control *control); + enum bp_result (*encoder_control_dig1)( + struct bios_parser *bp, + struct bp_encoder_control *control); + enum bp_result (*encoder_control_dig2)( + struct bios_parser *bp, + struct bp_encoder_control *control); + enum bp_result (*transmitter_control)( + struct bios_parser *bp, + struct bp_transmitter_control *control); + enum bp_result (*set_pixel_clock)( + struct bios_parser *bp, + struct bp_pixel_clock_parameters *bp_params); + enum bp_result (*enable_spread_spectrum_on_ppll)( + struct bios_parser *bp, + struct bp_spread_spectrum_parameters *bp_params, + bool enable); + enum bp_result (*adjust_display_pll)( + struct bios_parser *bp, + struct bp_adjust_pixel_clock_parameters *bp_params); + enum bp_result (*dac1_encoder_control)( + struct bios_parser *bp, + bool enable, + uint32_t pixel_clock, + uint8_t dac_standard); + enum bp_result (*dac2_encoder_control)( + struct bios_parser *bp, + bool enable, + uint32_t pixel_clock, + uint8_t dac_standard); + enum bp_result (*dac1_output_control)( + struct bios_parser *bp, + bool enable); + enum bp_result (*dac2_output_control)( + struct bios_parser *bp, + bool enable); + enum bp_result (*blank_crtc)( + struct bios_parser *bp, + struct bp_blank_crtc_parameters *bp_params, + bool blank); + enum bp_result (*set_crtc_timing)( + struct bios_parser *bp, + struct bp_hw_crtc_timing_parameters *bp_params); + enum bp_result (*set_crtc_overscan)( + struct bios_parser *bp, + struct bp_hw_crtc_overscan_parameters *bp_params); + enum bp_result (*select_crtc_source)( + struct bios_parser *bp, + struct bp_crtc_source_select *bp_params); + enum bp_result (*enable_crtc)( + struct bios_parser *bp, + enum controller_id controller_id, + bool enable); + enum bp_result (*enable_crtc_mem_req)( + struct bios_parser *bp, + enum controller_id controller_id, + bool enable); + enum bp_result (*program_clock)( + struct bios_parser *bp, + struct bp_pixel_clock_parameters *bp_params); + enum bp_result (*compute_memore_engine_pll)( + struct bios_parser *bp, + struct bp_display_clock_parameters *bp_params); + enum bp_result (*external_encoder_control)( + struct bios_parser *bp, + struct bp_external_encoder_control *cntl); + enum bp_result (*enable_disp_power_gating)( + struct bios_parser *bp, + enum controller_id crtc_id, + enum bp_pipe_control_action action); + enum bp_result (*set_dce_clock)( + struct bios_parser *bp, + struct bp_set_dce_clock_parameters *bp_params); +}; + +void dal_bios_parser_init_cmd_tbl(struct bios_parser *bp); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper.c b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper.c new file mode 100644 index 000000000000..40d9a9921c45 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper.c @@ -0,0 +1,288 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "atom.h" + +#include "include/bios_parser_types.h" + +#include "command_table_helper.h" + +bool dal_bios_parser_init_cmd_tbl_helper( + const struct command_table_helper **h, + enum dce_version dce) +{ + switch (dce) { + case DCE_VERSION_8_0: + *h = dal_cmd_tbl_helper_dce80_get_table(); + return true; + + case DCE_VERSION_10_0: + *h = dal_cmd_tbl_helper_dce110_get_table(); + return true; + + case DCE_VERSION_11_0: + *h = dal_cmd_tbl_helper_dce110_get_table(); + return true; + + case DCE_VERSION_11_2: + *h = dal_cmd_tbl_helper_dce112_get_table(); + return true; + + default: + /* Unsupported DCE */ + BREAK_TO_DEBUGGER(); + return false; + } +} + +/* real implementations */ + +bool dal_cmd_table_helper_controller_id_to_atom( + enum controller_id id, + uint8_t *atom_id) +{ + if (atom_id == NULL) { + BREAK_TO_DEBUGGER(); + return false; + } + + switch (id) { + case CONTROLLER_ID_D0: + *atom_id = ATOM_CRTC1; + return true; + case CONTROLLER_ID_D1: + *atom_id = ATOM_CRTC2; + return true; + case CONTROLLER_ID_D2: + *atom_id = ATOM_CRTC3; + return true; + case CONTROLLER_ID_D3: + *atom_id = ATOM_CRTC4; + return true; + case CONTROLLER_ID_D4: + *atom_id = ATOM_CRTC5; + return true; + case CONTROLLER_ID_D5: + *atom_id = ATOM_CRTC6; + return true; + case CONTROLLER_ID_UNDERLAY0: + *atom_id = ATOM_UNDERLAY_PIPE0; + return true; + case CONTROLLER_ID_UNDEFINED: + *atom_id = ATOM_CRTC_INVALID; + return true; + default: + /* Wrong controller id */ + BREAK_TO_DEBUGGER(); + return false; + } +} + +/** +* translate_transmitter_bp_to_atom +* +* @brief +* Translate the Transmitter to the corresponding ATOM BIOS value +* +* @param +* input transmitter +* output digitalTransmitter +* // =00: Digital Transmitter1 ( UNIPHY linkAB ) +* // =01: Digital Transmitter2 ( UNIPHY linkCD ) +* // =02: Digital Transmitter3 ( UNIPHY linkEF ) +*/ +uint8_t dal_cmd_table_helper_transmitter_bp_to_atom( + enum transmitter t) +{ + switch (t) { + case TRANSMITTER_UNIPHY_A: + case TRANSMITTER_UNIPHY_B: + case TRANSMITTER_TRAVIS_LCD: + return 0; + case TRANSMITTER_UNIPHY_C: + case TRANSMITTER_UNIPHY_D: + return 1; + case TRANSMITTER_UNIPHY_E: + case TRANSMITTER_UNIPHY_F: + return 2; + default: + /* Invalid Transmitter Type! */ + BREAK_TO_DEBUGGER(); + return 0; + } +} + +uint32_t dal_cmd_table_helper_encoder_mode_bp_to_atom( + enum signal_type s, + bool enable_dp_audio) +{ + switch (s) { + case SIGNAL_TYPE_DVI_SINGLE_LINK: + case SIGNAL_TYPE_DVI_DUAL_LINK: + return ATOM_ENCODER_MODE_DVI; + case SIGNAL_TYPE_HDMI_TYPE_A: + return ATOM_ENCODER_MODE_HDMI; + case SIGNAL_TYPE_LVDS: + return ATOM_ENCODER_MODE_LVDS; + case SIGNAL_TYPE_EDP: + case SIGNAL_TYPE_DISPLAY_PORT_MST: + case SIGNAL_TYPE_DISPLAY_PORT: + case SIGNAL_TYPE_VIRTUAL: + if (enable_dp_audio) + return ATOM_ENCODER_MODE_DP_AUDIO; + else + return ATOM_ENCODER_MODE_DP; + case SIGNAL_TYPE_RGB: + return ATOM_ENCODER_MODE_CRT; + default: + return ATOM_ENCODER_MODE_CRT; + } +} + +void dal_cmd_table_helper_assign_control_parameter( + const struct command_table_helper *h, + struct bp_encoder_control *control, + DIG_ENCODER_CONTROL_PARAMETERS_V2 *ctrl_param) +{ + /* there are three transmitter blocks, each one has two links 4-lanes + * each, A+B, C+D, E+F, Uniphy A, C and E are enumerated as link 0 in + * each transmitter block B, D and F as link 1, third transmitter block + * has non splitable links (UniphyE and UniphyF can not be configured + * separately to drive two different streams) + */ + if ((control->transmitter == TRANSMITTER_UNIPHY_B) || + (control->transmitter == TRANSMITTER_UNIPHY_D) || + (control->transmitter == TRANSMITTER_UNIPHY_F)) { + /* Bit2: Link Select + * =0: PHY linkA/C/E + * =1: PHY linkB/D/F + */ + ctrl_param->acConfig.ucLinkSel = 1; + } + + /* Bit[4:3]: Transmitter Selection + * =00: Digital Transmitter1 ( UNIPHY linkAB ) + * =01: Digital Transmitter2 ( UNIPHY linkCD ) + * =02: Digital Transmitter3 ( UNIPHY linkEF ) + * =03: Reserved + */ + ctrl_param->acConfig.ucTransmitterSel = + (uint8_t)(h->transmitter_bp_to_atom(control->transmitter)); + + /* We need to convert from KHz units into 10KHz units */ + ctrl_param->ucAction = h->encoder_action_to_atom(control->action); + ctrl_param->usPixelClock = cpu_to_le16((uint16_t)(control->pixel_clock / 10)); + ctrl_param->ucEncoderMode = + (uint8_t)(h->encoder_mode_bp_to_atom( + control->signal, control->enable_dp_audio)); + ctrl_param->ucLaneNum = (uint8_t)(control->lanes_number); +} + +bool dal_cmd_table_helper_clock_source_id_to_ref_clk_src( + enum clock_source_id id, + uint32_t *ref_clk_src_id) +{ + if (ref_clk_src_id == NULL) { + BREAK_TO_DEBUGGER(); + return false; + } + + switch (id) { + case CLOCK_SOURCE_ID_PLL1: + *ref_clk_src_id = ENCODER_REFCLK_SRC_P1PLL; + return true; + case CLOCK_SOURCE_ID_PLL2: + *ref_clk_src_id = ENCODER_REFCLK_SRC_P2PLL; + return true; + case CLOCK_SOURCE_ID_DCPLL: + *ref_clk_src_id = ENCODER_REFCLK_SRC_DCPLL; + return true; + case CLOCK_SOURCE_ID_EXTERNAL: + *ref_clk_src_id = ENCODER_REFCLK_SRC_EXTCLK; + return true; + case CLOCK_SOURCE_ID_UNDEFINED: + *ref_clk_src_id = ENCODER_REFCLK_SRC_INVALID; + return true; + default: + /* Unsupported clock source id */ + BREAK_TO_DEBUGGER(); + return false; + } +} + +uint8_t dal_cmd_table_helper_encoder_id_to_atom( + enum encoder_id id) +{ + switch (id) { + case ENCODER_ID_INTERNAL_LVDS: + return ENCODER_OBJECT_ID_INTERNAL_LVDS; + case ENCODER_ID_INTERNAL_TMDS1: + return ENCODER_OBJECT_ID_INTERNAL_TMDS1; + case ENCODER_ID_INTERNAL_TMDS2: + return ENCODER_OBJECT_ID_INTERNAL_TMDS2; + case ENCODER_ID_INTERNAL_DAC1: + return ENCODER_OBJECT_ID_INTERNAL_DAC1; + case ENCODER_ID_INTERNAL_DAC2: + return ENCODER_OBJECT_ID_INTERNAL_DAC2; + case ENCODER_ID_INTERNAL_LVTM1: + return ENCODER_OBJECT_ID_INTERNAL_LVTM1; + case ENCODER_ID_INTERNAL_HDMI: + return ENCODER_OBJECT_ID_HDMI_INTERNAL; + case ENCODER_ID_EXTERNAL_TRAVIS: + return ENCODER_OBJECT_ID_TRAVIS; + case ENCODER_ID_EXTERNAL_NUTMEG: + return ENCODER_OBJECT_ID_NUTMEG; + case ENCODER_ID_INTERNAL_KLDSCP_TMDS1: + return ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1; + case ENCODER_ID_INTERNAL_KLDSCP_DAC1: + return ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1; + case ENCODER_ID_INTERNAL_KLDSCP_DAC2: + return ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2; + case ENCODER_ID_EXTERNAL_MVPU_FPGA: + return ENCODER_OBJECT_ID_MVPU_FPGA; + case ENCODER_ID_INTERNAL_DDI: + return ENCODER_OBJECT_ID_INTERNAL_DDI; + case ENCODER_ID_INTERNAL_UNIPHY: + return ENCODER_OBJECT_ID_INTERNAL_UNIPHY; + case ENCODER_ID_INTERNAL_KLDSCP_LVTMA: + return ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA; + case ENCODER_ID_INTERNAL_UNIPHY1: + return ENCODER_OBJECT_ID_INTERNAL_UNIPHY1; + case ENCODER_ID_INTERNAL_UNIPHY2: + return ENCODER_OBJECT_ID_INTERNAL_UNIPHY2; + case ENCODER_ID_INTERNAL_UNIPHY3: + return ENCODER_OBJECT_ID_INTERNAL_UNIPHY3; + case ENCODER_ID_INTERNAL_WIRELESS: + return ENCODER_OBJECT_ID_INTERNAL_VCE; + case ENCODER_ID_UNKNOWN: + return ENCODER_OBJECT_ID_NONE; + default: + /* Invalid encoder id */ + BREAK_TO_DEBUGGER(); + return ENCODER_OBJECT_ID_NONE; + } +} diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper.h b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper.h new file mode 100644 index 000000000000..1fab634b66be --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper.h @@ -0,0 +1,90 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_COMMAND_TABLE_HELPER_H__ +#define __DAL_COMMAND_TABLE_HELPER_H__ + +#include "dce80/command_table_helper_dce80.h" +#include "dce110/command_table_helper_dce110.h" +#include "dce112/command_table_helper_dce112.h" + +struct command_table_helper { + bool (*controller_id_to_atom)(enum controller_id id, uint8_t *atom_id); + uint8_t (*encoder_action_to_atom)( + enum bp_encoder_control_action action); + uint32_t (*encoder_mode_bp_to_atom)(enum signal_type s, + bool enable_dp_audio); + bool (*engine_bp_to_atom)(enum engine_id engine_id, + uint32_t *atom_engine_id); + void (*assign_control_parameter)( + const struct command_table_helper *h, + struct bp_encoder_control *control, + DIG_ENCODER_CONTROL_PARAMETERS_V2 *ctrl_param); + bool (*clock_source_id_to_atom)(enum clock_source_id id, + uint32_t *atom_pll_id); + bool (*clock_source_id_to_ref_clk_src)( + enum clock_source_id id, + uint32_t *ref_clk_src_id); + uint8_t (*transmitter_bp_to_atom)(enum transmitter t); + uint8_t (*encoder_id_to_atom)(enum encoder_id id); + uint8_t (*clock_source_id_to_atom_phy_clk_src_id)( + enum clock_source_id id); + uint8_t (*signal_type_to_atom_dig_mode)(enum signal_type s); + uint8_t (*hpd_sel_to_atom)(enum hpd_source_id id); + uint8_t (*dig_encoder_sel_to_atom)(enum engine_id engine_id); + uint8_t (*phy_id_to_atom)(enum transmitter t); + uint8_t (*disp_power_gating_action_to_atom)( + enum bp_pipe_control_action action); + bool (*dc_clock_type_to_atom)(enum bp_dce_clock_type id, + uint32_t *atom_clock_type); + uint8_t (*transmitter_color_depth_to_atom)(enum transmitter_color_depth id); +}; + +bool dal_bios_parser_init_cmd_tbl_helper(const struct command_table_helper **h, + enum dce_version dce); + +bool dal_cmd_table_helper_controller_id_to_atom( + enum controller_id id, + uint8_t *atom_id); + +uint32_t dal_cmd_table_helper_encoder_mode_bp_to_atom( + enum signal_type s, + bool enable_dp_audio); + +void dal_cmd_table_helper_assign_control_parameter( + const struct command_table_helper *h, + struct bp_encoder_control *control, +DIG_ENCODER_CONTROL_PARAMETERS_V2 *ctrl_param); + +bool dal_cmd_table_helper_clock_source_id_to_ref_clk_src( + enum clock_source_id id, + uint32_t *ref_clk_src_id); + +uint8_t dal_cmd_table_helper_transmitter_bp_to_atom( + enum transmitter t); + +uint8_t dal_cmd_table_helper_encoder_id_to_atom( + enum encoder_id id); +#endif diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.c b/drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.c new file mode 100644 index 000000000000..dff82dd11721 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.c @@ -0,0 +1,364 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "atom.h" + +#include "include/bios_parser_types.h" + +#include "../command_table_helper.h" + +static uint8_t phy_id_to_atom(enum transmitter t) +{ + uint8_t atom_phy_id; + + switch (t) { + case TRANSMITTER_UNIPHY_A: + atom_phy_id = ATOM_PHY_ID_UNIPHYA; + break; + case TRANSMITTER_UNIPHY_B: + atom_phy_id = ATOM_PHY_ID_UNIPHYB; + break; + case TRANSMITTER_UNIPHY_C: + atom_phy_id = ATOM_PHY_ID_UNIPHYC; + break; + case TRANSMITTER_UNIPHY_D: + atom_phy_id = ATOM_PHY_ID_UNIPHYD; + break; + case TRANSMITTER_UNIPHY_E: + atom_phy_id = ATOM_PHY_ID_UNIPHYE; + break; + case TRANSMITTER_UNIPHY_F: + atom_phy_id = ATOM_PHY_ID_UNIPHYF; + break; + case TRANSMITTER_UNIPHY_G: + atom_phy_id = ATOM_PHY_ID_UNIPHYG; + break; + default: + atom_phy_id = ATOM_PHY_ID_UNIPHYA; + break; + } + return atom_phy_id; +} + +static uint8_t signal_type_to_atom_dig_mode(enum signal_type s) +{ + uint8_t atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DP; + + switch (s) { + case SIGNAL_TYPE_DISPLAY_PORT: + case SIGNAL_TYPE_EDP: + atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DP; + break; + case SIGNAL_TYPE_LVDS: + atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_LVDS; + break; + case SIGNAL_TYPE_DVI_SINGLE_LINK: + case SIGNAL_TYPE_DVI_DUAL_LINK: + atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DVI; + break; + case SIGNAL_TYPE_HDMI_TYPE_A: + atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_HDMI; + break; + case SIGNAL_TYPE_DISPLAY_PORT_MST: + atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DP_MST; + break; + default: + atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DVI; + break; + } + + return atom_dig_mode; +} + +static uint8_t clock_source_id_to_atom_phy_clk_src_id( + enum clock_source_id id) +{ + uint8_t atom_phy_clk_src_id = 0; + + switch (id) { + case CLOCK_SOURCE_ID_PLL0: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P0PLL; + break; + case CLOCK_SOURCE_ID_PLL1: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL; + break; + case CLOCK_SOURCE_ID_PLL2: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P2PLL; + break; + case CLOCK_SOURCE_ID_EXTERNAL: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_REFCLK_SRC_EXT; + break; + default: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL; + break; + } + + return atom_phy_clk_src_id >> 2; +} + +static uint8_t hpd_sel_to_atom(enum hpd_source_id id) +{ + uint8_t atom_hpd_sel = 0; + + switch (id) { + case HPD_SOURCEID1: + atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD1_SEL; + break; + case HPD_SOURCEID2: + atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD2_SEL; + break; + case HPD_SOURCEID3: + atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD3_SEL; + break; + case HPD_SOURCEID4: + atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD4_SEL; + break; + case HPD_SOURCEID5: + atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD5_SEL; + break; + case HPD_SOURCEID6: + atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD6_SEL; + break; + case HPD_SOURCEID_UNKNOWN: + default: + atom_hpd_sel = 0; + break; + } + return atom_hpd_sel >> 4; +} + +static uint8_t dig_encoder_sel_to_atom(enum engine_id id) +{ + uint8_t atom_dig_encoder_sel = 0; + + switch (id) { + case ENGINE_ID_DIGA: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGA_SEL; + break; + case ENGINE_ID_DIGB: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGB_SEL; + break; + case ENGINE_ID_DIGC: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGC_SEL; + break; + case ENGINE_ID_DIGD: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGD_SEL; + break; + case ENGINE_ID_DIGE: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGE_SEL; + break; + case ENGINE_ID_DIGF: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGF_SEL; + break; + case ENGINE_ID_DIGG: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGG_SEL; + break; + case ENGINE_ID_UNKNOWN: + /* No DIG_FRONT is associated to DIG_BACKEND */ + atom_dig_encoder_sel = 0; + break; + default: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGA_SEL; + break; + } + + return atom_dig_encoder_sel; +} + +static bool clock_source_id_to_atom( + enum clock_source_id id, + uint32_t *atom_pll_id) +{ + bool result = true; + + if (atom_pll_id != NULL) + switch (id) { + case CLOCK_SOURCE_ID_PLL0: + *atom_pll_id = ATOM_PPLL0; + break; + case CLOCK_SOURCE_ID_PLL1: + *atom_pll_id = ATOM_PPLL1; + break; + case CLOCK_SOURCE_ID_PLL2: + *atom_pll_id = ATOM_PPLL2; + break; + case CLOCK_SOURCE_ID_EXTERNAL: + *atom_pll_id = ATOM_PPLL_INVALID; + break; + case CLOCK_SOURCE_ID_DFS: + *atom_pll_id = ATOM_EXT_PLL1; + break; + case CLOCK_SOURCE_ID_VCE: + /* for VCE encoding, + * we need to pass in ATOM_PPLL_INVALID + */ + *atom_pll_id = ATOM_PPLL_INVALID; + break; + case CLOCK_SOURCE_ID_DP_DTO: + /* When programming DP DTO PLL ID should be invalid */ + *atom_pll_id = ATOM_PPLL_INVALID; + break; + case CLOCK_SOURCE_ID_UNDEFINED: + /* Should not happen */ + *atom_pll_id = ATOM_PPLL_INVALID; + result = false; + break; + default: + result = false; + break; + } + + return result; +} + +static bool engine_bp_to_atom(enum engine_id id, uint32_t *atom_engine_id) +{ + bool result = false; + + if (atom_engine_id != NULL) + switch (id) { + case ENGINE_ID_DIGA: + *atom_engine_id = ASIC_INT_DIG1_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGB: + *atom_engine_id = ASIC_INT_DIG2_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGC: + *atom_engine_id = ASIC_INT_DIG3_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGD: + *atom_engine_id = ASIC_INT_DIG4_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGE: + *atom_engine_id = ASIC_INT_DIG5_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGF: + *atom_engine_id = ASIC_INT_DIG6_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGG: + *atom_engine_id = ASIC_INT_DIG7_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DACA: + *atom_engine_id = ASIC_INT_DAC1_ENCODER_ID; + result = true; + break; + default: + break; + } + + return result; +} + +static uint8_t encoder_action_to_atom(enum bp_encoder_control_action action) +{ + uint8_t atom_action = 0; + + switch (action) { + case ENCODER_CONTROL_ENABLE: + atom_action = ATOM_ENABLE; + break; + case ENCODER_CONTROL_DISABLE: + atom_action = ATOM_DISABLE; + break; + case ENCODER_CONTROL_SETUP: + atom_action = ATOM_ENCODER_CMD_SETUP; + break; + case ENCODER_CONTROL_INIT: + atom_action = ATOM_ENCODER_INIT; + break; + default: + BREAK_TO_DEBUGGER(); /* Unhandle action in driver.!! */ + break; + } + + return atom_action; +} + +static uint8_t disp_power_gating_action_to_atom( + enum bp_pipe_control_action action) +{ + uint8_t atom_pipe_action = 0; + + switch (action) { + case ASIC_PIPE_DISABLE: + atom_pipe_action = ATOM_DISABLE; + break; + case ASIC_PIPE_ENABLE: + atom_pipe_action = ATOM_ENABLE; + break; + case ASIC_PIPE_INIT: + atom_pipe_action = ATOM_INIT; + break; + default: + ASSERT_CRITICAL(false); /* Unhandle action in driver! */ + break; + } + + return atom_pipe_action; +} + +/* function table */ +static const struct command_table_helper command_table_helper_funcs = { + .controller_id_to_atom = dal_cmd_table_helper_controller_id_to_atom, + .encoder_action_to_atom = encoder_action_to_atom, + .engine_bp_to_atom = engine_bp_to_atom, + .clock_source_id_to_atom = clock_source_id_to_atom, + .clock_source_id_to_atom_phy_clk_src_id = + clock_source_id_to_atom_phy_clk_src_id, + .signal_type_to_atom_dig_mode = signal_type_to_atom_dig_mode, + .hpd_sel_to_atom = hpd_sel_to_atom, + .dig_encoder_sel_to_atom = dig_encoder_sel_to_atom, + .phy_id_to_atom = phy_id_to_atom, + .disp_power_gating_action_to_atom = disp_power_gating_action_to_atom, + .assign_control_parameter = NULL, + .clock_source_id_to_ref_clk_src = NULL, + .transmitter_bp_to_atom = NULL, + .encoder_id_to_atom = dal_cmd_table_helper_encoder_id_to_atom, + .encoder_mode_bp_to_atom = dal_cmd_table_helper_encoder_mode_bp_to_atom, +}; + +/* + * dal_cmd_tbl_helper_dce110_get_table + * + * @brief + * Initialize command table helper functions + * + * @param + * const struct command_table_helper **h - [out] struct of functions + * + */ +const struct command_table_helper *dal_cmd_tbl_helper_dce110_get_table() +{ + return &command_table_helper_funcs; +} diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.h b/drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.h new file mode 100644 index 000000000000..eb60c2ead992 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.h @@ -0,0 +1,34 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_COMMAND_TABLE_HELPER_DCE110_H__ +#define __DAL_COMMAND_TABLE_HELPER_DCE110_H__ + +struct command_table_helper; + +/* Initialize command table helper functions */ +const struct command_table_helper *dal_cmd_tbl_helper_dce110_get_table(void); + +#endif /* __DAL_COMMAND_TABLE_HELPER_DCE110_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c new file mode 100644 index 000000000000..8b72aa588b86 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c @@ -0,0 +1,418 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "atom.h" + +#include "include/bios_parser_types.h" + +#include "../command_table_helper.h" + +static uint8_t phy_id_to_atom(enum transmitter t) +{ + uint8_t atom_phy_id; + + switch (t) { + case TRANSMITTER_UNIPHY_A: + atom_phy_id = ATOM_PHY_ID_UNIPHYA; + break; + case TRANSMITTER_UNIPHY_B: + atom_phy_id = ATOM_PHY_ID_UNIPHYB; + break; + case TRANSMITTER_UNIPHY_C: + atom_phy_id = ATOM_PHY_ID_UNIPHYC; + break; + case TRANSMITTER_UNIPHY_D: + atom_phy_id = ATOM_PHY_ID_UNIPHYD; + break; + case TRANSMITTER_UNIPHY_E: + atom_phy_id = ATOM_PHY_ID_UNIPHYE; + break; + case TRANSMITTER_UNIPHY_F: + atom_phy_id = ATOM_PHY_ID_UNIPHYF; + break; + case TRANSMITTER_UNIPHY_G: + atom_phy_id = ATOM_PHY_ID_UNIPHYG; + break; + default: + atom_phy_id = ATOM_PHY_ID_UNIPHYA; + break; + } + return atom_phy_id; +} + +static uint8_t signal_type_to_atom_dig_mode(enum signal_type s) +{ + uint8_t atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_DP; + + switch (s) { + case SIGNAL_TYPE_DISPLAY_PORT: + case SIGNAL_TYPE_EDP: + atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_DP; + break; + case SIGNAL_TYPE_DVI_SINGLE_LINK: + case SIGNAL_TYPE_DVI_DUAL_LINK: + atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_DVI; + break; + case SIGNAL_TYPE_HDMI_TYPE_A: + atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_HDMI; + break; + case SIGNAL_TYPE_DISPLAY_PORT_MST: + atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_DP_MST; + break; + default: + atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_DVI; + break; + } + + return atom_dig_mode; +} + +static uint8_t clock_source_id_to_atom_phy_clk_src_id( + enum clock_source_id id) +{ + uint8_t atom_phy_clk_src_id = 0; + + switch (id) { + case CLOCK_SOURCE_ID_PLL0: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P0PLL; + break; + case CLOCK_SOURCE_ID_PLL1: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL; + break; + case CLOCK_SOURCE_ID_PLL2: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P2PLL; + break; + case CLOCK_SOURCE_ID_EXTERNAL: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_REFCLK_SRC_EXT; + break; + default: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL; + break; + } + + return atom_phy_clk_src_id >> 2; +} + +static uint8_t hpd_sel_to_atom(enum hpd_source_id id) +{ + uint8_t atom_hpd_sel = 0; + + switch (id) { + case HPD_SOURCEID1: + atom_hpd_sel = ATOM_TRANSMITTER_V6_HPD1_SEL; + break; + case HPD_SOURCEID2: + atom_hpd_sel = ATOM_TRANSMITTER_V6_HPD2_SEL; + break; + case HPD_SOURCEID3: + atom_hpd_sel = ATOM_TRANSMITTER_V6_HPD3_SEL; + break; + case HPD_SOURCEID4: + atom_hpd_sel = ATOM_TRANSMITTER_V6_HPD4_SEL; + break; + case HPD_SOURCEID5: + atom_hpd_sel = ATOM_TRANSMITTER_V6_HPD5_SEL; + break; + case HPD_SOURCEID6: + atom_hpd_sel = ATOM_TRANSMITTER_V6_HPD6_SEL; + break; + case HPD_SOURCEID_UNKNOWN: + default: + atom_hpd_sel = 0; + break; + } + return atom_hpd_sel; +} + +static uint8_t dig_encoder_sel_to_atom(enum engine_id id) +{ + uint8_t atom_dig_encoder_sel = 0; + + switch (id) { + case ENGINE_ID_DIGA: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGA_SEL; + break; + case ENGINE_ID_DIGB: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGB_SEL; + break; + case ENGINE_ID_DIGC: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGC_SEL; + break; + case ENGINE_ID_DIGD: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGD_SEL; + break; + case ENGINE_ID_DIGE: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGE_SEL; + break; + case ENGINE_ID_DIGF: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGF_SEL; + break; + case ENGINE_ID_DIGG: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGG_SEL; + break; + case ENGINE_ID_UNKNOWN: + /* No DIG_FRONT is associated to DIG_BACKEND */ + atom_dig_encoder_sel = 0; + break; + default: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGA_SEL; + break; + } + + return atom_dig_encoder_sel; +} + +static bool clock_source_id_to_atom( + enum clock_source_id id, + uint32_t *atom_pll_id) +{ + bool result = true; + + if (atom_pll_id != NULL) + switch (id) { + case CLOCK_SOURCE_COMBO_PHY_PLL0: + *atom_pll_id = ATOM_COMBOPHY_PLL0; + break; + case CLOCK_SOURCE_COMBO_PHY_PLL1: + *atom_pll_id = ATOM_COMBOPHY_PLL1; + break; + case CLOCK_SOURCE_COMBO_PHY_PLL2: + *atom_pll_id = ATOM_COMBOPHY_PLL2; + break; + case CLOCK_SOURCE_COMBO_PHY_PLL3: + *atom_pll_id = ATOM_COMBOPHY_PLL3; + break; + case CLOCK_SOURCE_COMBO_PHY_PLL4: + *atom_pll_id = ATOM_COMBOPHY_PLL4; + break; + case CLOCK_SOURCE_COMBO_PHY_PLL5: + *atom_pll_id = ATOM_COMBOPHY_PLL5; + break; + case CLOCK_SOURCE_COMBO_DISPLAY_PLL0: + *atom_pll_id = ATOM_PPLL0; + break; + case CLOCK_SOURCE_ID_DFS: + *atom_pll_id = ATOM_GCK_DFS; + break; + case CLOCK_SOURCE_ID_VCE: + *atom_pll_id = ATOM_DP_DTO; + break; + case CLOCK_SOURCE_ID_DP_DTO: + *atom_pll_id = ATOM_DP_DTO; + break; + case CLOCK_SOURCE_ID_UNDEFINED: + /* Should not happen */ + *atom_pll_id = ATOM_PPLL_INVALID; + result = false; + break; + default: + result = false; + break; + } + + return result; +} + +static bool engine_bp_to_atom(enum engine_id id, uint32_t *atom_engine_id) +{ + bool result = false; + + if (atom_engine_id != NULL) + switch (id) { + case ENGINE_ID_DIGA: + *atom_engine_id = ASIC_INT_DIG1_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGB: + *atom_engine_id = ASIC_INT_DIG2_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGC: + *atom_engine_id = ASIC_INT_DIG3_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGD: + *atom_engine_id = ASIC_INT_DIG4_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGE: + *atom_engine_id = ASIC_INT_DIG5_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGF: + *atom_engine_id = ASIC_INT_DIG6_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGG: + *atom_engine_id = ASIC_INT_DIG7_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DACA: + *atom_engine_id = ASIC_INT_DAC1_ENCODER_ID; + result = true; + break; + default: + break; + } + + return result; +} + +static uint8_t encoder_action_to_atom(enum bp_encoder_control_action action) +{ + uint8_t atom_action = 0; + + switch (action) { + case ENCODER_CONTROL_ENABLE: + atom_action = ATOM_ENABLE; + break; + case ENCODER_CONTROL_DISABLE: + atom_action = ATOM_DISABLE; + break; + case ENCODER_CONTROL_SETUP: + atom_action = ATOM_ENCODER_CMD_STREAM_SETUP; + break; + case ENCODER_CONTROL_INIT: + atom_action = ATOM_ENCODER_INIT; + break; + default: + BREAK_TO_DEBUGGER(); /* Unhandle action in driver.!! */ + break; + } + + return atom_action; +} + +static uint8_t disp_power_gating_action_to_atom( + enum bp_pipe_control_action action) +{ + uint8_t atom_pipe_action = 0; + + switch (action) { + case ASIC_PIPE_DISABLE: + atom_pipe_action = ATOM_DISABLE; + break; + case ASIC_PIPE_ENABLE: + atom_pipe_action = ATOM_ENABLE; + break; + case ASIC_PIPE_INIT: + atom_pipe_action = ATOM_INIT; + break; + default: + ASSERT_CRITICAL(false); /* Unhandle action in driver! */ + break; + } + + return atom_pipe_action; +} + +static bool dc_clock_type_to_atom( + enum bp_dce_clock_type id, + uint32_t *atom_clock_type) +{ + bool retCode = true; + + if (atom_clock_type != NULL) { + switch (id) { + case DCECLOCK_TYPE_DISPLAY_CLOCK: + *atom_clock_type = DCE_CLOCK_TYPE_DISPCLK; + break; + + case DCECLOCK_TYPE_DPREFCLK: + *atom_clock_type = DCE_CLOCK_TYPE_DPREFCLK; + break; + + default: + ASSERT_CRITICAL(false); /* Unhandle action in driver! */ + break; + } + } + + return retCode; +} + +static uint8_t transmitter_color_depth_to_atom(enum transmitter_color_depth id) +{ + uint8_t atomColorDepth = 0; + + switch (id) { + case TRANSMITTER_COLOR_DEPTH_24: + atomColorDepth = PIXEL_CLOCK_V7_DEEPCOLOR_RATIO_DIS; + break; + case TRANSMITTER_COLOR_DEPTH_30: + atomColorDepth = PIXEL_CLOCK_V7_DEEPCOLOR_RATIO_5_4; + break; + case TRANSMITTER_COLOR_DEPTH_36: + atomColorDepth = PIXEL_CLOCK_V7_DEEPCOLOR_RATIO_3_2; + break; + case TRANSMITTER_COLOR_DEPTH_48: + atomColorDepth = PIXEL_CLOCK_V7_DEEPCOLOR_RATIO_2_1; + break; + default: + ASSERT_CRITICAL(false); /* Unhandle action in driver! */ + break; + } + + return atomColorDepth; +} + +/* function table */ +static const struct command_table_helper command_table_helper_funcs = { + .controller_id_to_atom = dal_cmd_table_helper_controller_id_to_atom, + .encoder_action_to_atom = encoder_action_to_atom, + .engine_bp_to_atom = engine_bp_to_atom, + .clock_source_id_to_atom = clock_source_id_to_atom, + .clock_source_id_to_atom_phy_clk_src_id = + clock_source_id_to_atom_phy_clk_src_id, + .signal_type_to_atom_dig_mode = signal_type_to_atom_dig_mode, + .hpd_sel_to_atom = hpd_sel_to_atom, + .dig_encoder_sel_to_atom = dig_encoder_sel_to_atom, + .phy_id_to_atom = phy_id_to_atom, + .disp_power_gating_action_to_atom = disp_power_gating_action_to_atom, + .assign_control_parameter = NULL, + .clock_source_id_to_ref_clk_src = NULL, + .transmitter_bp_to_atom = NULL, + .encoder_id_to_atom = dal_cmd_table_helper_encoder_id_to_atom, + .encoder_mode_bp_to_atom = dal_cmd_table_helper_encoder_mode_bp_to_atom, + .dc_clock_type_to_atom = dc_clock_type_to_atom, + .transmitter_color_depth_to_atom = transmitter_color_depth_to_atom, +}; + +/* + * dal_cmd_tbl_helper_dce110_get_table + * + * @brief + * Initialize command table helper functions + * + * @param + * const struct command_table_helper **h - [out] struct of functions + * + */ +const struct command_table_helper *dal_cmd_tbl_helper_dce112_get_table() +{ + return &command_table_helper_funcs; +} diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.h b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.h new file mode 100644 index 000000000000..dc3660951355 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.h @@ -0,0 +1,34 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_COMMAND_TABLE_HELPER_DCE112_H__ +#define __DAL_COMMAND_TABLE_HELPER_DCE112_H__ + +struct command_table_helper; + +/* Initialize command table helper functions */ +const struct command_table_helper *dal_cmd_tbl_helper_dce112_get_table(void); + +#endif /* __DAL_COMMAND_TABLE_HELPER_DCE110_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce80/command_table_helper_dce80.c b/drivers/gpu/drm/amd/display/dc/bios/dce80/command_table_helper_dce80.c new file mode 100644 index 000000000000..295e16ef3f73 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/dce80/command_table_helper_dce80.c @@ -0,0 +1,354 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "atom.h" + +#include "include/grph_object_id.h" +#include "include/grph_object_defs.h" +#include "include/bios_parser_types.h" + +#include "../command_table_helper.h" + +static uint8_t encoder_action_to_atom(enum bp_encoder_control_action action) +{ + uint8_t atom_action = 0; + + switch (action) { + case ENCODER_CONTROL_ENABLE: + atom_action = ATOM_ENABLE; + break; + case ENCODER_CONTROL_DISABLE: + atom_action = ATOM_DISABLE; + break; + case ENCODER_CONTROL_SETUP: + atom_action = ATOM_ENCODER_CMD_SETUP; + break; + case ENCODER_CONTROL_INIT: + atom_action = ATOM_ENCODER_INIT; + break; + default: + BREAK_TO_DEBUGGER(); /* Unhandle action in driver.!! */ + break; + } + + return atom_action; +} + +static bool engine_bp_to_atom(enum engine_id id, uint32_t *atom_engine_id) +{ + bool result = false; + + if (atom_engine_id != NULL) + switch (id) { + case ENGINE_ID_DIGA: + *atom_engine_id = ASIC_INT_DIG1_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGB: + *atom_engine_id = ASIC_INT_DIG2_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGC: + *atom_engine_id = ASIC_INT_DIG3_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGD: + *atom_engine_id = ASIC_INT_DIG4_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGE: + *atom_engine_id = ASIC_INT_DIG5_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGF: + *atom_engine_id = ASIC_INT_DIG6_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGG: + *atom_engine_id = ASIC_INT_DIG7_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DACA: + *atom_engine_id = ASIC_INT_DAC1_ENCODER_ID; + result = true; + break; + default: + break; + } + + return result; +} + +static bool clock_source_id_to_atom( + enum clock_source_id id, + uint32_t *atom_pll_id) +{ + bool result = true; + + if (atom_pll_id != NULL) + switch (id) { + case CLOCK_SOURCE_ID_PLL0: + *atom_pll_id = ATOM_PPLL0; + break; + case CLOCK_SOURCE_ID_PLL1: + *atom_pll_id = ATOM_PPLL1; + break; + case CLOCK_SOURCE_ID_PLL2: + *atom_pll_id = ATOM_PPLL2; + break; + case CLOCK_SOURCE_ID_EXTERNAL: + *atom_pll_id = ATOM_PPLL_INVALID; + break; + case CLOCK_SOURCE_ID_DFS: + *atom_pll_id = ATOM_EXT_PLL1; + break; + case CLOCK_SOURCE_ID_VCE: + /* for VCE encoding, + * we need to pass in ATOM_PPLL_INVALID + */ + *atom_pll_id = ATOM_PPLL_INVALID; + break; + case CLOCK_SOURCE_ID_DP_DTO: + /* When programming DP DTO PLL ID should be invalid */ + *atom_pll_id = ATOM_PPLL_INVALID; + break; + case CLOCK_SOURCE_ID_UNDEFINED: + BREAK_TO_DEBUGGER(); /* check when this will happen! */ + *atom_pll_id = ATOM_PPLL_INVALID; + result = false; + break; + default: + result = false; + break; + } + + return result; +} + +static uint8_t clock_source_id_to_atom_phy_clk_src_id( + enum clock_source_id id) +{ + uint8_t atom_phy_clk_src_id = 0; + + switch (id) { + case CLOCK_SOURCE_ID_PLL0: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P0PLL; + break; + case CLOCK_SOURCE_ID_PLL1: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL; + break; + case CLOCK_SOURCE_ID_PLL2: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P2PLL; + break; + case CLOCK_SOURCE_ID_EXTERNAL: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_REFCLK_SRC_EXT; + break; + default: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL; + break; + } + + return atom_phy_clk_src_id >> 2; +} + +static uint8_t signal_type_to_atom_dig_mode(enum signal_type s) +{ + uint8_t atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DP; + + switch (s) { + case SIGNAL_TYPE_DISPLAY_PORT: + case SIGNAL_TYPE_EDP: + atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DP; + break; + case SIGNAL_TYPE_LVDS: + atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_LVDS; + break; + case SIGNAL_TYPE_DVI_SINGLE_LINK: + case SIGNAL_TYPE_DVI_DUAL_LINK: + atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DVI; + break; + case SIGNAL_TYPE_HDMI_TYPE_A: + atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_HDMI; + break; + case SIGNAL_TYPE_DISPLAY_PORT_MST: + atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DP_MST; + break; + default: + atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DVI; + break; + } + + return atom_dig_mode; +} + +static uint8_t hpd_sel_to_atom(enum hpd_source_id id) +{ + uint8_t atom_hpd_sel = 0; + + switch (id) { + case HPD_SOURCEID1: + atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD1_SEL; + break; + case HPD_SOURCEID2: + atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD2_SEL; + break; + case HPD_SOURCEID3: + atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD3_SEL; + break; + case HPD_SOURCEID4: + atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD4_SEL; + break; + case HPD_SOURCEID5: + atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD5_SEL; + break; + case HPD_SOURCEID6: + atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD6_SEL; + break; + case HPD_SOURCEID_UNKNOWN: + default: + atom_hpd_sel = 0; + break; + } + return atom_hpd_sel >> 4; +} + +static uint8_t dig_encoder_sel_to_atom(enum engine_id id) +{ + uint8_t atom_dig_encoder_sel = 0; + + switch (id) { + case ENGINE_ID_DIGA: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGA_SEL; + break; + case ENGINE_ID_DIGB: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGB_SEL; + break; + case ENGINE_ID_DIGC: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGC_SEL; + break; + case ENGINE_ID_DIGD: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGD_SEL; + break; + case ENGINE_ID_DIGE: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGE_SEL; + break; + case ENGINE_ID_DIGF: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGF_SEL; + break; + case ENGINE_ID_DIGG: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGG_SEL; + break; + default: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGA_SEL; + break; + } + + return atom_dig_encoder_sel; +} + +static uint8_t phy_id_to_atom(enum transmitter t) +{ + uint8_t atom_phy_id; + + switch (t) { + case TRANSMITTER_UNIPHY_A: + atom_phy_id = ATOM_PHY_ID_UNIPHYA; + break; + case TRANSMITTER_UNIPHY_B: + atom_phy_id = ATOM_PHY_ID_UNIPHYB; + break; + case TRANSMITTER_UNIPHY_C: + atom_phy_id = ATOM_PHY_ID_UNIPHYC; + break; + case TRANSMITTER_UNIPHY_D: + atom_phy_id = ATOM_PHY_ID_UNIPHYD; + break; + case TRANSMITTER_UNIPHY_E: + atom_phy_id = ATOM_PHY_ID_UNIPHYE; + break; + case TRANSMITTER_UNIPHY_F: + atom_phy_id = ATOM_PHY_ID_UNIPHYF; + break; + case TRANSMITTER_UNIPHY_G: + atom_phy_id = ATOM_PHY_ID_UNIPHYG; + break; + default: + atom_phy_id = ATOM_PHY_ID_UNIPHYA; + break; + } + return atom_phy_id; +} + +static uint8_t disp_power_gating_action_to_atom( + enum bp_pipe_control_action action) +{ + uint8_t atom_pipe_action = 0; + + switch (action) { + case ASIC_PIPE_DISABLE: + atom_pipe_action = ATOM_DISABLE; + break; + case ASIC_PIPE_ENABLE: + atom_pipe_action = ATOM_ENABLE; + break; + case ASIC_PIPE_INIT: + atom_pipe_action = ATOM_INIT; + break; + default: + BREAK_TO_DEBUGGER(); /* Unhandle action in driver! */ + break; + } + + return atom_pipe_action; +} + +static const struct command_table_helper command_table_helper_funcs = { + .controller_id_to_atom = dal_cmd_table_helper_controller_id_to_atom, + .encoder_action_to_atom = encoder_action_to_atom, + .engine_bp_to_atom = engine_bp_to_atom, + .clock_source_id_to_atom = clock_source_id_to_atom, + .clock_source_id_to_atom_phy_clk_src_id = + clock_source_id_to_atom_phy_clk_src_id, + .signal_type_to_atom_dig_mode = signal_type_to_atom_dig_mode, + .hpd_sel_to_atom = hpd_sel_to_atom, + .dig_encoder_sel_to_atom = dig_encoder_sel_to_atom, + .phy_id_to_atom = phy_id_to_atom, + .disp_power_gating_action_to_atom = disp_power_gating_action_to_atom, + .assign_control_parameter = + dal_cmd_table_helper_assign_control_parameter, + .clock_source_id_to_ref_clk_src = + dal_cmd_table_helper_clock_source_id_to_ref_clk_src, + .transmitter_bp_to_atom = dal_cmd_table_helper_transmitter_bp_to_atom, + .encoder_id_to_atom = dal_cmd_table_helper_encoder_id_to_atom, + .encoder_mode_bp_to_atom = + dal_cmd_table_helper_encoder_mode_bp_to_atom, +}; + +const struct command_table_helper *dal_cmd_tbl_helper_dce80_get_table() +{ + return &command_table_helper_funcs; +} diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce80/command_table_helper_dce80.h b/drivers/gpu/drm/amd/display/dc/bios/dce80/command_table_helper_dce80.h new file mode 100644 index 000000000000..e675c359e306 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/dce80/command_table_helper_dce80.h @@ -0,0 +1,33 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_COMMAND_TABLE_HELPER_DCE80_H__ +#define __DAL_COMMAND_TABLE_HELPER_DCE80_H__ + +struct command_table_helper; + +const struct command_table_helper *dal_cmd_tbl_helper_dce80_get_table(void); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/calcs/Makefile b/drivers/gpu/drm/amd/display/dc/calcs/Makefile new file mode 100644 index 000000000000..4001933e7808 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/calcs/Makefile @@ -0,0 +1,10 @@ +# +# Makefile for the 'calcs' sub-component of DAL. +# It calculates Bandwidth and Watermarks values for HW programming +# + +BW_CALCS = bandwidth_calcs.o bw_fixed.o gamma_calcs.o + +AMD_DAL_BW_CALCS = $(addprefix $(AMDDALPATH)/dc/calcs/,$(BW_CALCS)) + +AMD_DISPLAY_FILES += $(AMD_DAL_BW_CALCS) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c new file mode 100644 index 000000000000..0b2bb3992f1a --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c @@ -0,0 +1,3108 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "bandwidth_calcs.h" +#include "dc.h" +#include "core_types.h" + +/******************************************************************************* + * Private Functions + ******************************************************************************/ + +static void calculate_bandwidth( + const struct bw_calcs_dceip *dceip, + const struct bw_calcs_vbios *vbios, + struct bw_calcs_data *data) + +{ + const int32_t pixels_per_chunk = 512; + const int32_t high = 2; + const int32_t mid = 1; + const int32_t low = 0; + const uint32_t s_low = 0; + const uint32_t s_mid1 = 1; + const uint32_t s_mid2 = 2; + const uint32_t s_mid3 = 3; + const uint32_t s_mid4 = 4; + const uint32_t s_mid5 = 5; + const uint32_t s_mid6 = 6; + const uint32_t s_high = 7; + const uint32_t bus_efficiency = 1; + const uint32_t dmif_chunk_buff_margin = 1; + + uint32_t max_chunks_fbc_mode; + int32_t num_cursor_lines; + + int32_t i, j, k; + struct bw_fixed yclk[3]; + struct bw_fixed sclk[8]; + bool d0_underlay_enable; + bool d1_underlay_enable; + bool fbc_enabled; + bool lpt_enabled; + enum bw_defines sclk_message; + enum bw_defines yclk_message; + enum bw_defines v_filter_init_mode[maximum_number_of_surfaces]; + enum bw_defines tiling_mode[maximum_number_of_surfaces]; + enum bw_defines surface_type[maximum_number_of_surfaces]; + enum bw_defines voltage; + enum bw_defines pipe_check; + enum bw_defines hsr_check; + enum bw_defines vsr_check; + enum bw_defines lb_size_check; + enum bw_defines fbc_check; + enum bw_defines rotation_check; + enum bw_defines mode_check; + enum bw_defines nbp_state_change_enable_blank; + /*initialize variables*/ + int32_t number_of_displays_enabled = 0; + int32_t number_of_displays_enabled_with_margin = 0; + int32_t number_of_aligned_displays_with_no_margin = 0; + + yclk[low] = vbios->low_yclk; + yclk[mid] = vbios->mid_yclk; + yclk[high] = vbios->high_yclk; + sclk[s_low] = vbios->low_sclk; + sclk[s_mid1] = vbios->mid1_sclk; + sclk[s_mid2] = vbios->mid2_sclk; + sclk[s_mid3] = vbios->mid3_sclk; + sclk[s_mid4] = vbios->mid4_sclk; + sclk[s_mid5] = vbios->mid5_sclk; + sclk[s_mid6] = vbios->mid6_sclk; + sclk[s_high] = vbios->high_sclk; + /*''''''''''''''''''*/ + /* surface assignment:*/ + /* 0: d0 underlay or underlay luma*/ + /* 1: d0 underlay chroma*/ + /* 2: d1 underlay or underlay luma*/ + /* 3: d1 underlay chroma*/ + /* 4: d0 graphics*/ + /* 5: d1 graphics*/ + /* 6: d2 graphics*/ + /* 7: d3 graphics, same mode as d2*/ + /* 8: d4 graphics, same mode as d2*/ + /* 9: d5 graphics, same mode as d2*/ + /* ...*/ + /* maximum_number_of_surfaces-2: d1 display_write_back420 luma*/ + /* maximum_number_of_surfaces-1: d1 display_write_back420 chroma*/ + /* underlay luma and chroma surface parameters from spreadsheet*/ + + + + + if (data->d0_underlay_mode == bw_def_none) { d0_underlay_enable = 0; } + else { + d0_underlay_enable = 1; + } + if (data->d1_underlay_mode == bw_def_none) { d1_underlay_enable = 0; } + else { + d1_underlay_enable = 1; + } + data->number_of_underlay_surfaces = d0_underlay_enable + d1_underlay_enable; + switch (data->underlay_surface_type) { + case bw_def_420: + surface_type[0] = bw_def_underlay420_luma; + surface_type[2] = bw_def_underlay420_luma; + data->bytes_per_pixel[0] = 1; + data->bytes_per_pixel[2] = 1; + surface_type[1] = bw_def_underlay420_chroma; + surface_type[3] = bw_def_underlay420_chroma; + data->bytes_per_pixel[1] = 2; + data->bytes_per_pixel[3] = 2; + data->lb_size_per_component[0] = dceip->underlay420_luma_lb_size_per_component; + data->lb_size_per_component[1] = dceip->underlay420_chroma_lb_size_per_component; + data->lb_size_per_component[2] = dceip->underlay420_luma_lb_size_per_component; + data->lb_size_per_component[3] = dceip->underlay420_chroma_lb_size_per_component; + break; + case bw_def_422: + surface_type[0] = bw_def_underlay422; + surface_type[2] = bw_def_underlay422; + data->bytes_per_pixel[0] = 2; + data->bytes_per_pixel[2] = 2; + data->lb_size_per_component[0] = dceip->underlay422_lb_size_per_component; + data->lb_size_per_component[2] = dceip->underlay422_lb_size_per_component; + break; + default: + surface_type[0] = bw_def_underlay444; + surface_type[2] = bw_def_underlay444; + data->bytes_per_pixel[0] = 4; + data->bytes_per_pixel[2] = 4; + data->lb_size_per_component[0] = dceip->lb_size_per_component444; + data->lb_size_per_component[2] = dceip->lb_size_per_component444; + break; + } + if (d0_underlay_enable) { + switch (data->underlay_surface_type) { + case bw_def_420: + data->enable[0] = 1; + data->enable[1] = 1; + break; + default: + data->enable[0] = 1; + data->enable[1] = 0; + break; + } + } + else { + data->enable[0] = 0; + data->enable[1] = 0; + } + if (d1_underlay_enable) { + switch (data->underlay_surface_type) { + case bw_def_420: + data->enable[2] = 1; + data->enable[3] = 1; + break; + default: + data->enable[2] = 1; + data->enable[3] = 0; + break; + } + } + else { + data->enable[2] = 0; + data->enable[3] = 0; + } + data->use_alpha[0] = 0; + data->use_alpha[1] = 0; + data->use_alpha[2] = 0; + data->use_alpha[3] = 0; + data->scatter_gather_enable_for_pipe[0] = vbios->scatter_gather_enable; + data->scatter_gather_enable_for_pipe[1] = vbios->scatter_gather_enable; + data->scatter_gather_enable_for_pipe[2] = vbios->scatter_gather_enable; + data->scatter_gather_enable_for_pipe[3] = vbios->scatter_gather_enable; + /*underlay0 same and graphics display pipe0*/ + data->interlace_mode[0] = data->interlace_mode[4]; + data->interlace_mode[1] = data->interlace_mode[4]; + /*underlay1 same and graphics display pipe1*/ + data->interlace_mode[2] = data->interlace_mode[5]; + data->interlace_mode[3] = data->interlace_mode[5]; + /*underlay0 same and graphics display pipe0*/ + data->h_total[0] = data->h_total[4]; + data->v_total[0] = data->v_total[4]; + data->h_total[1] = data->h_total[4]; + data->v_total[1] = data->v_total[4]; + /*underlay1 same and graphics display pipe1*/ + data->h_total[2] = data->h_total[5]; + data->v_total[2] = data->v_total[5]; + data->h_total[3] = data->h_total[5]; + data->v_total[3] = data->v_total[5]; + /*underlay0 same and graphics display pipe0*/ + data->pixel_rate[0] = data->pixel_rate[4]; + data->pixel_rate[1] = data->pixel_rate[4]; + /*underlay1 same and graphics display pipe1*/ + data->pixel_rate[2] = data->pixel_rate[5]; + data->pixel_rate[3] = data->pixel_rate[5]; + if ((data->underlay_tiling_mode == bw_def_array_linear_general || data->underlay_tiling_mode == bw_def_array_linear_aligned)) { + tiling_mode[0] = bw_def_linear; + tiling_mode[1] = bw_def_linear; + tiling_mode[2] = bw_def_linear; + tiling_mode[3] = bw_def_linear; + } + else { + tiling_mode[0] = bw_def_landscape; + tiling_mode[1] = bw_def_landscape; + tiling_mode[2] = bw_def_landscape; + tiling_mode[3] = bw_def_landscape; + } + data->lb_bpc[0] = data->underlay_lb_bpc; + data->lb_bpc[1] = data->underlay_lb_bpc; + data->lb_bpc[2] = data->underlay_lb_bpc; + data->lb_bpc[3] = data->underlay_lb_bpc; + data->compression_rate[0] = bw_int_to_fixed(1); + data->compression_rate[1] = bw_int_to_fixed(1); + data->compression_rate[2] = bw_int_to_fixed(1); + data->compression_rate[3] = bw_int_to_fixed(1); + data->access_one_channel_only[0] = 0; + data->access_one_channel_only[1] = 0; + data->access_one_channel_only[2] = 0; + data->access_one_channel_only[3] = 0; + data->cursor_width_pixels[0] = bw_int_to_fixed(0); + data->cursor_width_pixels[1] = bw_int_to_fixed(0); + data->cursor_width_pixels[2] = bw_int_to_fixed(0); + data->cursor_width_pixels[3] = bw_int_to_fixed(0); + /* graphics surface parameters from spreadsheet*/ + fbc_enabled = 0; + lpt_enabled = 0; + for (i = 4; i <= maximum_number_of_surfaces - 3; i++) { + if (i < data->number_of_displays + 4) { + if (i == 4 && data->d0_underlay_mode == bw_def_underlay_only) { + data->enable[i] = 0; + data->use_alpha[i] = 0; + } + else if (i == 4 && data->d0_underlay_mode == bw_def_blend) { + data->enable[i] = 1; + data->use_alpha[i] = 1; + } + else if (i == 4) { + data->enable[i] = 1; + data->use_alpha[i] = 0; + } + else if (i == 5 && data->d1_underlay_mode == bw_def_underlay_only) { + data->enable[i] = 0; + data->use_alpha[i] = 0; + } + else if (i == 5 && data->d1_underlay_mode == bw_def_blend) { + data->enable[i] = 1; + data->use_alpha[i] = 1; + } + else { + data->enable[i] = 1; + data->use_alpha[i] = 0; + } + } + else { + data->enable[i] = 0; + data->use_alpha[i] = 0; + } + data->scatter_gather_enable_for_pipe[i] = vbios->scatter_gather_enable; + surface_type[i] = bw_def_graphics; + data->lb_size_per_component[i] = dceip->lb_size_per_component444; + if (data->graphics_tiling_mode == bw_def_array_linear_general || data->graphics_tiling_mode == bw_def_array_linear_aligned) { + tiling_mode[i] = bw_def_linear; + } + else { + tiling_mode[i] = bw_def_tiled; + } + data->lb_bpc[i] = data->graphics_lb_bpc; + if ((data->fbc_en[i] == 1 && (dceip->argb_compression_support || data->d0_underlay_mode != bw_def_blended))) { + data->compression_rate[i] = bw_int_to_fixed(vbios->average_compression_rate); + data->access_one_channel_only[i] = data->lpt_en[i]; + } + else { + data->compression_rate[i] = bw_int_to_fixed(1); + data->access_one_channel_only[i] = 0; + } + if (data->fbc_en[i] == 1) { + fbc_enabled = 1; + if (data->lpt_en[i] == 1) { + lpt_enabled = 1; + } + } + data->cursor_width_pixels[i] = bw_int_to_fixed(vbios->cursor_width); + } + /* display_write_back420*/ + data->scatter_gather_enable_for_pipe[maximum_number_of_surfaces - 2] = 0; + data->scatter_gather_enable_for_pipe[maximum_number_of_surfaces - 1] = 0; + if (data->d1_display_write_back_dwb_enable == 1) { + data->enable[maximum_number_of_surfaces - 2] = 1; + data->enable[maximum_number_of_surfaces - 1] = 1; + } + else { + data->enable[maximum_number_of_surfaces - 2] = 0; + data->enable[maximum_number_of_surfaces - 1] = 0; + } + surface_type[maximum_number_of_surfaces - 2] = bw_def_display_write_back420_luma; + surface_type[maximum_number_of_surfaces - 1] = bw_def_display_write_back420_chroma; + data->lb_size_per_component[maximum_number_of_surfaces - 2] = dceip->underlay420_luma_lb_size_per_component; + data->lb_size_per_component[maximum_number_of_surfaces - 1] = dceip->underlay420_chroma_lb_size_per_component; + data->bytes_per_pixel[maximum_number_of_surfaces - 2] = 1; + data->bytes_per_pixel[maximum_number_of_surfaces - 1] = 2; + data->interlace_mode[maximum_number_of_surfaces - 2] = data->interlace_mode[5]; + data->interlace_mode[maximum_number_of_surfaces - 1] = data->interlace_mode[5]; + data->h_taps[maximum_number_of_surfaces - 2] = bw_int_to_fixed(1); + data->h_taps[maximum_number_of_surfaces - 1] = bw_int_to_fixed(1); + data->v_taps[maximum_number_of_surfaces - 2] = bw_int_to_fixed(1); + data->v_taps[maximum_number_of_surfaces - 1] = bw_int_to_fixed(1); + data->rotation_angle[maximum_number_of_surfaces - 2] = bw_int_to_fixed(0); + data->rotation_angle[maximum_number_of_surfaces - 1] = bw_int_to_fixed(0); + tiling_mode[maximum_number_of_surfaces - 2] = bw_def_linear; + tiling_mode[maximum_number_of_surfaces - 1] = bw_def_linear; + data->lb_bpc[maximum_number_of_surfaces - 2] = 8; + data->lb_bpc[maximum_number_of_surfaces - 1] = 8; + data->compression_rate[maximum_number_of_surfaces - 2] = bw_int_to_fixed(1); + data->compression_rate[maximum_number_of_surfaces - 1] = bw_int_to_fixed(1); + data->access_one_channel_only[maximum_number_of_surfaces - 2] = 0; + data->access_one_channel_only[maximum_number_of_surfaces - 1] = 0; + /*assume display pipe1 has dwb enabled*/ + data->h_total[maximum_number_of_surfaces - 2] = data->h_total[5]; + data->h_total[maximum_number_of_surfaces - 1] = data->h_total[5]; + data->v_total[maximum_number_of_surfaces - 2] = data->v_total[5]; + data->v_total[maximum_number_of_surfaces - 1] = data->v_total[5]; + data->pixel_rate[maximum_number_of_surfaces - 2] = data->pixel_rate[5]; + data->pixel_rate[maximum_number_of_surfaces - 1] = data->pixel_rate[5]; + data->src_width[maximum_number_of_surfaces - 2] = data->src_width[5]; + data->src_width[maximum_number_of_surfaces - 1] = data->src_width[5]; + data->src_height[maximum_number_of_surfaces - 2] = data->src_height[5]; + data->src_height[maximum_number_of_surfaces - 1] = data->src_height[5]; + data->pitch_in_pixels[maximum_number_of_surfaces - 2] = data->src_width[5]; + data->pitch_in_pixels[maximum_number_of_surfaces - 1] = data->src_width[5]; + data->h_scale_ratio[maximum_number_of_surfaces - 2] = bw_int_to_fixed(1); + data->h_scale_ratio[maximum_number_of_surfaces - 1] = bw_int_to_fixed(1); + data->v_scale_ratio[maximum_number_of_surfaces - 2] = bw_int_to_fixed(1); + data->v_scale_ratio[maximum_number_of_surfaces - 1] = bw_int_to_fixed(1); + data->stereo_mode[maximum_number_of_surfaces - 2] = bw_def_mono; + data->stereo_mode[maximum_number_of_surfaces - 1] = bw_def_mono; + data->cursor_width_pixels[maximum_number_of_surfaces - 2] = bw_int_to_fixed(0); + data->cursor_width_pixels[maximum_number_of_surfaces - 1] = bw_int_to_fixed(0); + data->use_alpha[maximum_number_of_surfaces - 2] = 0; + data->use_alpha[maximum_number_of_surfaces - 1] = 0; + /*mode check calculations:*/ + /* mode within dce ip capabilities*/ + /* fbc*/ + /* hsr*/ + /* vsr*/ + /* lb size*/ + /*effective scaling source and ratios:*/ + /*for graphics, non-stereo, non-interlace surfaces when the size of the source and destination are the same, only one tap is used*/ + /*420 chroma has half the width, height, horizontal and vertical scaling ratios than luma*/ + /*rotating a graphic or underlay surface swaps the width, height, horizontal and vertical scaling ratios*/ + /*in top-bottom stereo mode there is 2:1 vertical downscaling for each eye*/ + /*in side-by-side stereo mode there is 2:1 horizontal downscaling for each eye*/ + /*in interlace mode there is 2:1 vertical downscaling for each field*/ + /*in panning or bezel adjustment mode the source width has an extra 128 pixels*/ + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if (bw_equ(data->h_scale_ratio[i], bw_int_to_fixed(1)) && bw_equ(data->v_scale_ratio[i], bw_int_to_fixed(1)) && surface_type[i] == bw_def_graphics && data->stereo_mode[i] == bw_def_mono && data->interlace_mode[i] == 0) { + data->h_taps[i] = bw_int_to_fixed(1); + data->v_taps[i] = bw_int_to_fixed(1); + } + if (surface_type[i] == bw_def_display_write_back420_chroma || surface_type[i] == bw_def_underlay420_chroma) { + data->pitch_in_pixels_after_surface_type[i] = bw_div(data->pitch_in_pixels[i], bw_int_to_fixed(2)); + data->src_width_after_surface_type = bw_div(data->src_width[i], bw_int_to_fixed(2)); + data->src_height_after_surface_type = bw_div(data->src_height[i], bw_int_to_fixed(2)); + data->hsr_after_surface_type = bw_div(data->h_scale_ratio[i], bw_int_to_fixed(2)); + data->vsr_after_surface_type = bw_div(data->v_scale_ratio[i], bw_int_to_fixed(2)); + } + else { + data->pitch_in_pixels_after_surface_type[i] = data->pitch_in_pixels[i]; + data->src_width_after_surface_type = data->src_width[i]; + data->src_height_after_surface_type = data->src_height[i]; + data->hsr_after_surface_type = data->h_scale_ratio[i]; + data->vsr_after_surface_type = data->v_scale_ratio[i]; + } + if ((bw_equ(data->rotation_angle[i], bw_int_to_fixed(90)) || bw_equ(data->rotation_angle[i], bw_int_to_fixed(270))) && surface_type[i] != bw_def_display_write_back420_luma && surface_type[i] != bw_def_display_write_back420_chroma) { + data->src_width_after_rotation = data->src_height_after_surface_type; + data->src_height_after_rotation = data->src_width_after_surface_type; + data->hsr_after_rotation = data->vsr_after_surface_type; + data->vsr_after_rotation = data->hsr_after_surface_type; + } + else { + data->src_width_after_rotation = data->src_width_after_surface_type; + data->src_height_after_rotation = data->src_height_after_surface_type; + data->hsr_after_rotation = data->hsr_after_surface_type; + data->vsr_after_rotation = data->vsr_after_surface_type; + } + switch (data->stereo_mode[i]) { + case bw_def_top_bottom: + data->source_width_pixels[i] = data->src_width_after_rotation; + data->source_height_pixels = bw_mul(bw_int_to_fixed(2), data->src_height_after_rotation); + data->hsr_after_stereo = data->hsr_after_rotation; + data->vsr_after_stereo = bw_mul(bw_int_to_fixed(1), data->vsr_after_rotation); + break; + case bw_def_side_by_side: + data->source_width_pixels[i] = bw_mul(bw_int_to_fixed(2), data->src_width_after_rotation); + data->source_height_pixels = data->src_height_after_rotation; + data->hsr_after_stereo = bw_mul(bw_int_to_fixed(1), data->hsr_after_rotation); + data->vsr_after_stereo = data->vsr_after_rotation; + break; + default: + data->source_width_pixels[i] = data->src_width_after_rotation; + data->source_height_pixels = data->src_height_after_rotation; + data->hsr_after_stereo = data->hsr_after_rotation; + data->vsr_after_stereo = data->vsr_after_rotation; + break; + } + data->hsr[i] = data->hsr_after_stereo; + if (data->interlace_mode[i]) { + data->vsr[i] = bw_mul(data->vsr_after_stereo, bw_int_to_fixed(2)); + } + else { + data->vsr[i] = data->vsr_after_stereo; + } + if (data->panning_and_bezel_adjustment != bw_def_none) { + data->source_width_rounded_up_to_chunks[i] = bw_add(bw_floor2(bw_sub(data->source_width_pixels[i], bw_int_to_fixed(1)), bw_int_to_fixed(128)), bw_int_to_fixed(256)); + } + else { + data->source_width_rounded_up_to_chunks[i] = bw_ceil2(data->source_width_pixels[i], bw_int_to_fixed(128)); + } + data->source_height_rounded_up_to_chunks[i] = data->source_height_pixels; + } + } + /*mode support checks:*/ + /*the number of graphics and underlay pipes is limited by the ip support*/ + /*maximum horizontal and vertical scale ratio is 4, and should not exceed the number of taps*/ + /*for downscaling with the pre-downscaler, the horizontal scale ratio must be more than the ceiling of one quarter of the number of taps*/ + /*the pre-downscaler reduces the line buffer source by the horizontal scale ratio*/ + /*the number of lines in the line buffer has to exceed the number of vertical taps*/ + /*the size of the line in the line buffer is the product of the source width and the bits per component, rounded up to a multiple of 48*/ + /*the size of the line in the line buffer in the case of 10 bit per component is the product of the source width rounded up to multiple of 8 and 30.023438 / 3, rounded up to a multiple of 48*/ + /*the size of the line in the line buffer in the case of 8 bit per component is the product of the source width rounded up to multiple of 8 and 30.023438 / 3, rounded up to a multiple of 48*/ + /*frame buffer compression is not supported with stereo mode, rotation, or non- 888 formats*/ + /*rotation is not supported with linear of stereo modes*/ + if (dceip->number_of_graphics_pipes >= data->number_of_displays && dceip->number_of_underlay_pipes >= data->number_of_underlay_surfaces && !(dceip->display_write_back_supported == 0 && data->d1_display_write_back_dwb_enable == 1)) { + pipe_check = bw_def_ok; + } + else { + pipe_check = bw_def_notok; + } + hsr_check = bw_def_ok; + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if (bw_neq(data->hsr[i], bw_int_to_fixed(1))) { + if (bw_mtn(data->hsr[i], bw_int_to_fixed(4))) { + hsr_check = bw_def_hsr_mtn_4; + } + else { + if (bw_mtn(data->hsr[i], data->h_taps[i])) { + hsr_check = bw_def_hsr_mtn_h_taps; + } + else { + if (dceip->pre_downscaler_enabled == 1 && bw_mtn(data->hsr[i], bw_int_to_fixed(1)) && bw_leq(data->hsr[i], bw_ceil2(bw_div(data->h_taps[i], bw_int_to_fixed(4)), bw_int_to_fixed(1)))) { + hsr_check = bw_def_ceiling__h_taps_div_4___meq_hsr; + } + } + } + } + } + } + vsr_check = bw_def_ok; + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if (bw_neq(data->vsr[i], bw_int_to_fixed(1))) { + if (bw_mtn(data->vsr[i], bw_int_to_fixed(4))) { + vsr_check = bw_def_vsr_mtn_4; + } + else { + if (bw_mtn(data->vsr[i], data->v_taps[i])) { + vsr_check = bw_def_vsr_mtn_v_taps; + } + } + } + } + } + lb_size_check = bw_def_ok; + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if ((dceip->pre_downscaler_enabled && bw_mtn(data->hsr[i], bw_int_to_fixed(1)))) { + data->source_width_in_lb = bw_div(data->source_width_pixels[i], data->hsr[i]); + } + else { + data->source_width_in_lb = data->source_width_pixels[i]; + } + switch (data->lb_bpc[i]) { + case 8: + data->lb_line_pitch = bw_ceil2(bw_mul(bw_div(bw_frc_to_fixed(2401171875, 100000000), bw_int_to_fixed(3)), bw_ceil2(data->source_width_in_lb, bw_int_to_fixed(8))), bw_int_to_fixed(48)); + break; + case 10: + data->lb_line_pitch = bw_ceil2(bw_mul(bw_div(bw_frc_to_fixed(300234375, 10000000), bw_int_to_fixed(3)), bw_ceil2(data->source_width_in_lb, bw_int_to_fixed(8))), bw_int_to_fixed(48)); + break; + default: + data->lb_line_pitch = bw_ceil2(bw_mul(bw_int_to_fixed(data->lb_bpc[i]), data->source_width_in_lb), bw_int_to_fixed(48)); + break; + } + data->lb_partitions[i] = bw_floor2(bw_div(data->lb_size_per_component[i], data->lb_line_pitch), bw_int_to_fixed(1)); + /*clamp the partitions to the maxium number supported by the lb*/ + if ((surface_type[i] != bw_def_graphics || dceip->graphics_lb_nodownscaling_multi_line_prefetching == 1)) { + data->lb_partitions_max[i] = bw_int_to_fixed(10); + } + else { + data->lb_partitions_max[i] = bw_int_to_fixed(7); + } + data->lb_partitions[i] = bw_min2(data->lb_partitions_max[i], data->lb_partitions[i]); + if (bw_mtn(bw_add(data->v_taps[i], bw_int_to_fixed(1)), data->lb_partitions[i])) { + lb_size_check = bw_def_notok; + } + } + } + fbc_check = bw_def_ok; + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i] && data->fbc_en[i] == 1 && (bw_equ(data->rotation_angle[i], bw_int_to_fixed(90)) || bw_equ(data->rotation_angle[i], bw_int_to_fixed(270)) || data->stereo_mode[i] != bw_def_mono || data->bytes_per_pixel[i] != 4)) { + fbc_check = bw_def_invalid_rotation_or_bpp_or_stereo; + } + } + rotation_check = bw_def_ok; + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if ((bw_equ(data->rotation_angle[i], bw_int_to_fixed(90)) || bw_equ(data->rotation_angle[i], bw_int_to_fixed(270))) && (tiling_mode[i] == bw_def_linear || data->stereo_mode[i] != bw_def_mono)) { + rotation_check = bw_def_invalid_linear_or_stereo_mode; + } + } + } + if (pipe_check == bw_def_ok && hsr_check == bw_def_ok && vsr_check == bw_def_ok && lb_size_check == bw_def_ok && fbc_check == bw_def_ok && rotation_check == bw_def_ok) { + mode_check = bw_def_ok; + } + else { + mode_check = bw_def_notok; + } + /*number of memory channels for write-back client*/ + data->number_of_dram_wrchannels = vbios->number_of_dram_channels; + data->number_of_dram_channels = vbios->number_of_dram_channels; + /*modify number of memory channels if lpt mode is enabled*/ + /* low power tiling mode register*/ + /* 0 = use channel 0*/ + /* 1 = use channel 0 and 1*/ + /* 2 = use channel 0,1,2,3*/ + if ((fbc_enabled == 1 && lpt_enabled == 1)) { + data->dram_efficiency = bw_int_to_fixed(1); + if (dceip->low_power_tiling_mode == 0) { + data->number_of_dram_channels = 1; + } + else if (dceip->low_power_tiling_mode == 1) { + data->number_of_dram_channels = 2; + } + else if (dceip->low_power_tiling_mode == 2) { + data->number_of_dram_channels = 4; + } + else { + data->number_of_dram_channels = 1; + } + } + else { + data->dram_efficiency = bw_frc_to_fixed(8, 10); + } + /*memory request size and latency hiding:*/ + /*request size is normally 64 byte, 2-line interleaved, with full latency hiding*/ + /*the display write-back requests are single line*/ + /*for tiled graphics surfaces, or undelay surfaces with width higher than the maximum size for full efficiency, request size is 32 byte in 8 and 16 bpp or if the rotation is orthogonal to the tiling grain. only half is useful of the bytes in the request size in 8 bpp or in 32 bpp if the rotation is orthogonal to the tiling grain.*/ + /*for undelay surfaces with width lower than the maximum size for full efficiency, requests are 4-line interleaved in 16bpp if the rotation is parallel to the tiling grain, and 8-line interleaved with 4-line latency hiding in 8bpp or if the rotation is orthogonal to the tiling grain.*/ + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if ((bw_equ(data->rotation_angle[i], bw_int_to_fixed(90)) || bw_equ(data->rotation_angle[i], bw_int_to_fixed(270)))) { + if ((i < 4)) { + /*underlay portrait tiling mode is not supported*/ + data->orthogonal_rotation[i] = 1; + } + else { + /*graphics portrait tiling mode*/ + if ((data->graphics_micro_tile_mode == bw_def_rotated_micro_tiling)) { + data->orthogonal_rotation[i] = 0; + } + else { + data->orthogonal_rotation[i] = 1; + } + } + } + else { + if ((i < 4)) { + /*underlay landscape tiling mode is only supported*/ + if ((data->underlay_micro_tile_mode == bw_def_display_micro_tiling)) { + data->orthogonal_rotation[i] = 0; + } + else { + data->orthogonal_rotation[i] = 1; + } + } + else { + /*graphics landscape tiling mode*/ + if ((data->graphics_micro_tile_mode == bw_def_display_micro_tiling)) { + data->orthogonal_rotation[i] = 0; + } + else { + data->orthogonal_rotation[i] = 1; + } + } + } + if (bw_equ(data->rotation_angle[i], bw_int_to_fixed(90)) || bw_equ(data->rotation_angle[i], bw_int_to_fixed(270))) { + data->underlay_maximum_source_efficient_for_tiling = dceip->underlay_maximum_height_efficient_for_tiling; + } + else { + data->underlay_maximum_source_efficient_for_tiling = dceip->underlay_maximum_width_efficient_for_tiling; + } + if (surface_type[i] == bw_def_display_write_back420_luma || surface_type[i] == bw_def_display_write_back420_chroma) { + data->bytes_per_request[i] = bw_int_to_fixed(64); + data->useful_bytes_per_request[i] = bw_int_to_fixed(64); + data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(1); + data->latency_hiding_lines[i] = bw_int_to_fixed(1); + } + else if (tiling_mode[i] == bw_def_linear) { + data->bytes_per_request[i] = bw_int_to_fixed(64); + data->useful_bytes_per_request[i] = bw_int_to_fixed(64); + data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(2); + data->latency_hiding_lines[i] = bw_int_to_fixed(2); + } + else { + if (surface_type[i] == bw_def_graphics || (bw_mtn(data->source_width_rounded_up_to_chunks[i], bw_ceil2(data->underlay_maximum_source_efficient_for_tiling, bw_int_to_fixed(256))))) { + switch (data->bytes_per_pixel[i]) { + case 8: + data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(2); + data->latency_hiding_lines[i] = bw_int_to_fixed(2); + if (data->orthogonal_rotation[i]) { + data->bytes_per_request[i] = bw_int_to_fixed(32); + data->useful_bytes_per_request[i] = bw_int_to_fixed(32); + } + else { + data->bytes_per_request[i] = bw_int_to_fixed(64); + data->useful_bytes_per_request[i] = bw_int_to_fixed(64); + } + break; + case 4: + if (data->orthogonal_rotation[i]) { + data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(2); + data->latency_hiding_lines[i] = bw_int_to_fixed(2); + data->bytes_per_request[i] = bw_int_to_fixed(32); + data->useful_bytes_per_request[i] = bw_int_to_fixed(16); + } + else { + data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(2); + data->latency_hiding_lines[i] = bw_int_to_fixed(2); + data->bytes_per_request[i] = bw_int_to_fixed(64); + data->useful_bytes_per_request[i] = bw_int_to_fixed(64); + } + break; + case 2: + data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(2); + data->latency_hiding_lines[i] = bw_int_to_fixed(2); + data->bytes_per_request[i] = bw_int_to_fixed(32); + data->useful_bytes_per_request[i] = bw_int_to_fixed(32); + break; + default: + data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(2); + data->latency_hiding_lines[i] = bw_int_to_fixed(2); + data->bytes_per_request[i] = bw_int_to_fixed(32); + data->useful_bytes_per_request[i] = bw_int_to_fixed(16); + break; + } + } + else { + data->bytes_per_request[i] = bw_int_to_fixed(64); + data->useful_bytes_per_request[i] = bw_int_to_fixed(64); + if (data->orthogonal_rotation[i]) { + data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(8); + data->latency_hiding_lines[i] = bw_int_to_fixed(4); + } + else { + switch (data->bytes_per_pixel[i]) { + case 4: + data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(2); + data->latency_hiding_lines[i] = bw_int_to_fixed(2); + break; + case 2: + data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(4); + data->latency_hiding_lines[i] = bw_int_to_fixed(4); + break; + default: + data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(8); + data->latency_hiding_lines[i] = bw_int_to_fixed(4); + break; + } + } + } + } + } + } + /*requested peak bandwidth:*/ + /*the peak request-per-second bandwidth is the product of the maximum source lines in per line out in the beginning*/ + /*and in the middle of the frame, the ratio of the source width to the line time, the ratio of line interleaving*/ + /*in memory to lines of latency hiding, and the ratio of bytes per pixel to useful bytes per request.*/ + /**/ + /*if the dmif data buffer size holds more than vta_ps worth of source lines, then only vsr is used.*/ + /*the peak bandwidth is the peak request-per-second bandwidth times the request size.*/ + /**/ + /*the line buffer lines in per line out in the beginning of the frame is the vertical filter initialization value*/ + /*rounded up to even and divided by the line times for initialization, which is normally three.*/ + /*the line buffer lines in per line out in the middle of the frame is at least one, or the vertical scale ratio,*/ + /*rounded up to line pairs if not doing line buffer prefetching.*/ + /**/ + /*the non-prefetching rounding up of the vertical scale ratio can also be done up to 1 (for a 0,2 pattern), 4/3 (for a 0,2,2 pattern),*/ + /*6/4 (for a 0,2,2,2 pattern), or 3 (for a 2,4 pattern).*/ + /**/ + /*the scaler vertical filter initialization value is calculated by the hardware as the floor of the average of the*/ + /*vertical scale ratio and the number of vertical taps increased by one. add one more for possible odd line*/ + /*panning/bezel adjustment mode.*/ + /**/ + /*for the bottom interlace field an extra 50% of the vertical scale ratio is considered for this calculation.*/ + /*in top-bottom stereo mode software has to set the filter initialization value manually and explicitly limit it to 4.*/ + /*furthermore, there is only one line time for initialization.*/ + /**/ + /*line buffer prefetching is done when the number of lines in the line buffer exceeds the number of taps plus*/ + /*the ceiling of the vertical scale ratio.*/ + /**/ + /*multi-line buffer prefetching is only done in the graphics pipe when the scaler is disabled or when upscaling and the vsr <= 0.8.'*/ + /**/ + /*the horizontal blank and chunk granularity factor is indirectly used indicate the interval of time required to transfer the source pixels.*/ + /*the denominator of this term represents the total number of destination output pixels required for the input source pixels.*/ + /*it applies when the lines in per line out is not 2 or 4. it does not apply when there is a line buffer between the scl and blnd.*/ + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + data->v_filter_init[i] = bw_floor2(bw_div((bw_add(bw_add(bw_add(bw_int_to_fixed(1), data->v_taps[i]), data->vsr[i]), bw_mul(bw_mul(bw_int_to_fixed(data->interlace_mode[i]), bw_frc_to_fixed(5, 10)), data->vsr[i]))), bw_int_to_fixed(2)), bw_int_to_fixed(1)); + if (data->panning_and_bezel_adjustment == bw_def_any_lines) { + data->v_filter_init[i] = bw_add(data->v_filter_init[i], bw_int_to_fixed(1)); + } + if (data->stereo_mode[i] == bw_def_top_bottom) { + v_filter_init_mode[i] = bw_def_manual; + data->v_filter_init[i] = bw_min2(data->v_filter_init[i], bw_int_to_fixed(4)); + } + else { + v_filter_init_mode[i] = bw_def_auto; + } + if (data->stereo_mode[i] == bw_def_top_bottom) { + data->num_lines_at_frame_start = bw_int_to_fixed(1); + } + else { + data->num_lines_at_frame_start = bw_int_to_fixed(3); + } + if ((bw_mtn(data->vsr[i], bw_int_to_fixed(1)) && surface_type[i] == bw_def_graphics) || data->panning_and_bezel_adjustment == bw_def_any_lines) { + data->line_buffer_prefetch[i] = 0; + } + else if ((((dceip->underlay_downscale_prefetch_enabled == 1 && surface_type[i] != bw_def_graphics) || surface_type[i] == bw_def_graphics) && (bw_mtn(data->lb_partitions[i], bw_add(data->v_taps[i], bw_ceil2(data->vsr[i], bw_int_to_fixed(1))))))) { + data->line_buffer_prefetch[i] = 1; + } + else { + data->line_buffer_prefetch[i] = 0; + } + data->lb_lines_in_per_line_out_in_beginning_of_frame[i] = bw_div(bw_ceil2(data->v_filter_init[i], bw_int_to_fixed(dceip->lines_interleaved_into_lb)), data->num_lines_at_frame_start); + if (data->line_buffer_prefetch[i] == 1) { + data->lb_lines_in_per_line_out_in_middle_of_frame[i] = bw_max2(bw_int_to_fixed(1), data->vsr[i]); + } + else if (bw_leq(data->vsr[i], bw_int_to_fixed(1))) { + data->lb_lines_in_per_line_out_in_middle_of_frame[i] = bw_int_to_fixed(1); + } + else if (bw_leq(data->vsr[i], bw_int_to_fixed(4 / 3))) { + data->lb_lines_in_per_line_out_in_middle_of_frame[i] = bw_div(bw_int_to_fixed(4), bw_int_to_fixed(3)); + } + else if (bw_leq(data->vsr[i], bw_int_to_fixed(6 / 4))) { + data->lb_lines_in_per_line_out_in_middle_of_frame[i] = bw_div(bw_int_to_fixed(6), bw_int_to_fixed(4)); + } + else if (bw_leq(data->vsr[i], bw_int_to_fixed(2))) { + data->lb_lines_in_per_line_out_in_middle_of_frame[i] = bw_int_to_fixed(2); + } + else if (bw_leq(data->vsr[i], bw_int_to_fixed(3))) { + data->lb_lines_in_per_line_out_in_middle_of_frame[i] = bw_int_to_fixed(3); + } + else { + data->lb_lines_in_per_line_out_in_middle_of_frame[i] = bw_int_to_fixed(4); + } + if (data->line_buffer_prefetch[i] == 1 || bw_equ(data->lb_lines_in_per_line_out_in_middle_of_frame[i], bw_int_to_fixed(2)) || bw_equ(data->lb_lines_in_per_line_out_in_middle_of_frame[i], bw_int_to_fixed(4))) { + data->horizontal_blank_and_chunk_granularity_factor[i] = bw_int_to_fixed(1); + } + else { + data->horizontal_blank_and_chunk_granularity_factor[i] = bw_div(data->h_total[i], (bw_div((bw_add(data->h_total[i], bw_div((bw_sub(data->source_width_pixels[i], bw_int_to_fixed(dceip->chunk_width))), data->hsr[i]))), bw_int_to_fixed(2)))); + } + data->request_bandwidth[i] = bw_div(bw_mul(bw_div(bw_mul(bw_div(bw_mul(bw_max2(data->lb_lines_in_per_line_out_in_beginning_of_frame[i], data->lb_lines_in_per_line_out_in_middle_of_frame[i]), data->source_width_rounded_up_to_chunks[i]), (bw_div(data->h_total[i], data->pixel_rate[i]))), bw_int_to_fixed(data->bytes_per_pixel[i])), data->useful_bytes_per_request[i]), data->lines_interleaved_in_mem_access[i]), data->latency_hiding_lines[i]); + data->display_bandwidth[i] = bw_mul(data->request_bandwidth[i], data->bytes_per_request[i]); + } + } + /*outstanding chunk request limit*/ + /*if underlay buffer sharing is enabled, the data buffer size for underlay in 422 or 444 is the sum of the luma and chroma data buffer sizes.*/ + /*underlay buffer sharing mode is only permitted in orthogonal rotation modes.*/ + /**/ + /*if there is only one display enabled, the dmif data buffer size for the graphics surface is increased by concatenating the adjacent buffers.*/ + /**/ + /*the memory chunk size in bytes is 1024 for the writeback, and 256 times the memory line interleaving and the bytes per pixel for graphics*/ + /*and underlay.*/ + /**/ + /*the pipe chunk size uses 2 for line interleaving, except for the write back, in which case it is 1.*/ + /*graphics and underlay data buffer size is adjusted (limited) using the outstanding chunk request limit if there is more than one*/ + /*display enabled or if the dmif request buffer is not large enough for the total data buffer size.*/ + /*the outstanding chunk request limit is the ceiling of the adjusted data buffer size divided by the chunk size in bytes*/ + /*the adjusted data buffer size is the product of the display bandwidth and the minimum effective data buffer size in terms of time,*/ + /*rounded up to the chunk size in bytes, but should not exceed the original data buffer size*/ + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if ((dceip->dmif_pipe_en_fbc_chunk_tracker + 3 == i && fbc_enabled == 0 && tiling_mode[i] != bw_def_linear)) { + data->max_chunks_non_fbc_mode[i] = 128 - dmif_chunk_buff_margin; + } + else { + data->max_chunks_non_fbc_mode[i] = 16 - dmif_chunk_buff_margin; + } + } + if (data->fbc_en[i] == 1) { + max_chunks_fbc_mode = 128 - dmif_chunk_buff_margin; + } + } + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + switch (surface_type[i]) { + case bw_def_display_write_back420_luma: + data->data_buffer_size[i] = bw_int_to_fixed(dceip->display_write_back420_luma_mcifwr_buffer_size); + break; + case bw_def_display_write_back420_chroma: + data->data_buffer_size[i] = bw_int_to_fixed(dceip->display_write_back420_chroma_mcifwr_buffer_size); + break; + case bw_def_underlay420_luma: + data->data_buffer_size[i] = bw_int_to_fixed(dceip->underlay_luma_dmif_size); + break; + case bw_def_underlay420_chroma: + data->data_buffer_size[i] = bw_div(bw_int_to_fixed(dceip->underlay_chroma_dmif_size), bw_int_to_fixed(2)); + break; + case bw_def_underlay422:case bw_def_underlay444: + if (data->orthogonal_rotation[i] == 0) { + data->data_buffer_size[i] = bw_int_to_fixed(dceip->underlay_luma_dmif_size); + } + else { + data->data_buffer_size[i] = bw_add(bw_int_to_fixed(dceip->underlay_luma_dmif_size), bw_int_to_fixed(dceip->underlay_chroma_dmif_size)); + } + break; + default: + if (data->fbc_en[i] == 1) { + /*data_buffer_size(i) = max_dmif_buffer_allocated * graphics_dmif_size*/ + if (data->number_of_displays == 1) { + data->data_buffer_size[i] = bw_min2(bw_mul(bw_mul(bw_int_to_fixed(max_chunks_fbc_mode), bw_int_to_fixed(pixels_per_chunk)), bw_int_to_fixed(data->bytes_per_pixel[i])), bw_mul(bw_int_to_fixed(dceip->max_dmif_buffer_allocated), bw_int_to_fixed(dceip->graphics_dmif_size))); + } + else { + data->data_buffer_size[i] = bw_min2(bw_mul(bw_mul(bw_int_to_fixed(max_chunks_fbc_mode), bw_int_to_fixed(pixels_per_chunk)), bw_int_to_fixed(data->bytes_per_pixel[i])), bw_int_to_fixed(dceip->graphics_dmif_size)); + } + } + else { + /*the effective dmif buffer size in non-fbc mode is limited by the 16 entry chunk tracker*/ + if (data->number_of_displays == 1) { + data->data_buffer_size[i] = bw_min2(bw_mul(bw_mul(bw_int_to_fixed(data->max_chunks_non_fbc_mode[i]), bw_int_to_fixed(pixels_per_chunk)), bw_int_to_fixed(data->bytes_per_pixel[i])), bw_mul(bw_int_to_fixed(dceip->max_dmif_buffer_allocated), bw_int_to_fixed(dceip->graphics_dmif_size))); + } + else { + data->data_buffer_size[i] = bw_min2(bw_mul(bw_mul(bw_int_to_fixed(data->max_chunks_non_fbc_mode[i]), bw_int_to_fixed(pixels_per_chunk)), bw_int_to_fixed(data->bytes_per_pixel[i])), bw_int_to_fixed(dceip->graphics_dmif_size)); + } + } + break; + } + if (surface_type[i] == bw_def_display_write_back420_luma || surface_type[i] == bw_def_display_write_back420_chroma) { + data->memory_chunk_size_in_bytes[i] = bw_int_to_fixed(1024); + data->pipe_chunk_size_in_bytes[i] = bw_int_to_fixed(1024); + } + else { + data->memory_chunk_size_in_bytes[i] = bw_mul(bw_mul(bw_int_to_fixed(dceip->chunk_width), data->lines_interleaved_in_mem_access[i]), bw_int_to_fixed(data->bytes_per_pixel[i])); + data->pipe_chunk_size_in_bytes[i] = bw_mul(bw_mul(bw_int_to_fixed(dceip->chunk_width), bw_int_to_fixed(dceip->lines_interleaved_into_lb)), bw_int_to_fixed(data->bytes_per_pixel[i])); + } + } + } + data->min_dmif_size_in_time = bw_int_to_fixed(9999); + data->min_mcifwr_size_in_time = bw_int_to_fixed(9999); + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if (surface_type[i] != bw_def_display_write_back420_luma && surface_type[i] != bw_def_display_write_back420_chroma) { + if (bw_ltn(bw_div(bw_div(bw_mul(data->data_buffer_size[i], data->bytes_per_request[i]), data->useful_bytes_per_request[i]), data->display_bandwidth[i]), data->min_dmif_size_in_time)) { + data->min_dmif_size_in_time = bw_div(bw_div(bw_mul(data->data_buffer_size[i], data->bytes_per_request[i]), data->useful_bytes_per_request[i]), data->display_bandwidth[i]); + } + } + else { + if (bw_ltn(bw_div(bw_div(bw_mul(data->data_buffer_size[i], data->bytes_per_request[i]), data->useful_bytes_per_request[i]), data->display_bandwidth[i]), data->min_mcifwr_size_in_time)) { + data->min_mcifwr_size_in_time = bw_div(bw_div(bw_mul(data->data_buffer_size[i], data->bytes_per_request[i]), data->useful_bytes_per_request[i]), data->display_bandwidth[i]); + } + } + } + } + data->total_requests_for_dmif_size = bw_int_to_fixed(0); + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i] && surface_type[i] != bw_def_display_write_back420_luma && surface_type[i] != bw_def_display_write_back420_chroma) { + data->total_requests_for_dmif_size = bw_add(data->total_requests_for_dmif_size, bw_div(data->data_buffer_size[i], data->useful_bytes_per_request[i])); + } + } + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if (surface_type[i] != bw_def_display_write_back420_luma && surface_type[i] != bw_def_display_write_back420_chroma && dceip->limit_excessive_outstanding_dmif_requests && (data->number_of_displays > 1 || bw_mtn(data->total_requests_for_dmif_size, dceip->dmif_request_buffer_size))) { + data->adjusted_data_buffer_size[i] = bw_min2(data->data_buffer_size[i], bw_ceil2(bw_mul(data->min_dmif_size_in_time, data->display_bandwidth[i]), data->memory_chunk_size_in_bytes[i])); + } + else { + data->adjusted_data_buffer_size[i] = data->data_buffer_size[i]; + } + } + } + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if ((data->number_of_displays == 1 && data->number_of_underlay_surfaces == 0)) { + /*set maximum chunk limit if only one graphic pipe is enabled*/ + data->outstanding_chunk_request_limit[i] = bw_int_to_fixed(127); + } + else { + data->outstanding_chunk_request_limit[i] = bw_ceil2(bw_div(data->adjusted_data_buffer_size[i], data->pipe_chunk_size_in_bytes[i]), bw_int_to_fixed(1)); + /*clamp maximum chunk limit in the graphic display pipe*/ + if ((i >= 4)) { + data->outstanding_chunk_request_limit[i] = bw_max2(bw_int_to_fixed(127), data->outstanding_chunk_request_limit[i]); + } + } + } + } + /*outstanding pte request limit*/ + /*in tiling mode with no rotation the sg pte requests are 8 useful pt_es, the sg row height is the page height and the sg page width x height is 64x64 for 8bpp, 64x32 for 16 bpp, 32x32 for 32 bpp*/ + /*in tiling mode with rotation the sg pte requests are only one useful pte, and the sg row height is also the page height, but the sg page width and height are swapped*/ + /*in linear mode the pte requests are 8 useful pt_es, the sg page width is 4096 divided by the bytes per pixel, the sg page height is 1, but there is just one row whose height is the lines of pte prefetching*/ + /*the outstanding pte request limit is obtained by multiplying the outstanding chunk request limit by the peak pte request to eviction limiting ratio, rounding up to integer, multiplying by the pte requests per chunk, and rounding up to integer again*/ + /*if not using peak pte request to eviction limiting, the outstanding pte request limit is the pte requests in the vblank*/ + /*the pte requests in the vblank is the product of the number of pte request rows times the number of pte requests in a row*/ + /*the number of pte requests in a row is the quotient of the source width divided by 256, multiplied by the pte requests per chunk, rounded up to even, multiplied by the scatter-gather row height and divided by the scatter-gather page height*/ + /*the pte requests per chunk is 256 divided by the scatter-gather page width and the useful pt_es per pte request*/ + if (data->number_of_displays > 1 || (bw_neq(data->rotation_angle[4], bw_int_to_fixed(0)) && bw_neq(data->rotation_angle[4], bw_int_to_fixed(180)))) { + data->peak_pte_request_to_eviction_ratio_limiting = dceip->peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display; + } + else { + data->peak_pte_request_to_eviction_ratio_limiting = dceip->peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation; + } + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i] && data->scatter_gather_enable_for_pipe[i] == 1) { + if (tiling_mode[i] == bw_def_linear) { + data->useful_pte_per_pte_request = bw_int_to_fixed(8); + data->scatter_gather_page_width[i] = bw_div(bw_int_to_fixed(4096), bw_int_to_fixed(data->bytes_per_pixel[i])); + data->scatter_gather_page_height[i] = bw_int_to_fixed(1); + data->scatter_gather_pte_request_rows = bw_int_to_fixed(1); + data->scatter_gather_row_height = bw_int_to_fixed(dceip->scatter_gather_lines_of_pte_prefetching_in_linear_mode); + } + else if (bw_equ(data->rotation_angle[i], bw_int_to_fixed(0)) || bw_equ(data->rotation_angle[i], bw_int_to_fixed(180))) { + data->useful_pte_per_pte_request = bw_int_to_fixed(8); + switch (data->bytes_per_pixel[i]) { + case 4: + data->scatter_gather_page_width[i] = bw_int_to_fixed(32); + data->scatter_gather_page_height[i] = bw_int_to_fixed(32); + break; + case 2: + data->scatter_gather_page_width[i] = bw_int_to_fixed(64); + data->scatter_gather_page_height[i] = bw_int_to_fixed(32); + break; + default: + data->scatter_gather_page_width[i] = bw_int_to_fixed(64); + data->scatter_gather_page_height[i] = bw_int_to_fixed(64); + break; + } + data->scatter_gather_pte_request_rows = bw_int_to_fixed(dceip->scatter_gather_pte_request_rows_in_tiling_mode); + data->scatter_gather_row_height = data->scatter_gather_page_height[i]; + } + else { + data->useful_pte_per_pte_request = bw_int_to_fixed(1); + switch (data->bytes_per_pixel[i]) { + case 4: + data->scatter_gather_page_width[i] = bw_int_to_fixed(32); + data->scatter_gather_page_height[i] = bw_int_to_fixed(32); + break; + case 2: + data->scatter_gather_page_width[i] = bw_int_to_fixed(32); + data->scatter_gather_page_height[i] = bw_int_to_fixed(64); + break; + default: + data->scatter_gather_page_width[i] = bw_int_to_fixed(64); + data->scatter_gather_page_height[i] = bw_int_to_fixed(64); + break; + } + data->scatter_gather_pte_request_rows = bw_int_to_fixed(dceip->scatter_gather_pte_request_rows_in_tiling_mode); + data->scatter_gather_row_height = data->scatter_gather_page_height[i]; + } + data->pte_request_per_chunk[i] = bw_div(bw_div(bw_int_to_fixed(dceip->chunk_width), data->scatter_gather_page_width[i]), data->useful_pte_per_pte_request); + data->scatter_gather_pte_requests_in_row[i] = bw_div(bw_mul(bw_ceil2(bw_mul(bw_div(data->source_width_rounded_up_to_chunks[i], bw_int_to_fixed(dceip->chunk_width)), data->pte_request_per_chunk[i]), bw_int_to_fixed(1)), data->scatter_gather_row_height), data->scatter_gather_page_height[i]); + data->scatter_gather_pte_requests_in_vblank = bw_mul(data->scatter_gather_pte_request_rows, data->scatter_gather_pte_requests_in_row[i]); + if (bw_equ(data->peak_pte_request_to_eviction_ratio_limiting, bw_int_to_fixed(0))) { + data->scatter_gather_pte_request_limit[i] = data->scatter_gather_pte_requests_in_vblank; + } + else { + data->scatter_gather_pte_request_limit[i] = bw_max2(dceip->minimum_outstanding_pte_request_limit, bw_min2(data->scatter_gather_pte_requests_in_vblank, bw_ceil2(bw_mul(bw_mul(bw_div(bw_ceil2(data->adjusted_data_buffer_size[i], data->memory_chunk_size_in_bytes[i]), data->memory_chunk_size_in_bytes[i]), data->pte_request_per_chunk[i]), data->peak_pte_request_to_eviction_ratio_limiting), bw_int_to_fixed(1)))); + } + } + } + /*pitch padding recommended for efficiency in linear mode*/ + /*in linear mode graphics or underlay with scatter gather, a pitch that is a multiple of the channel interleave (256 bytes) times the channel-bank rotation is not efficient*/ + /*if that is the case it is recommended to pad the pitch by at least 256 pixels*/ + data->inefficient_linear_pitch_in_bytes = bw_mul(bw_mul(bw_int_to_fixed(256), bw_int_to_fixed(vbios->number_of_dram_banks)), bw_int_to_fixed(data->number_of_dram_channels)); + + /*pixel transfer time*/ + /*the dmif and mcifwr yclk(pclk) required is the one that allows the transfer of all pipe's data buffer size in memory in the time for data transfer*/ + /*for dmif, pte and cursor requests have to be included.*/ + /*the dram data requirement is doubled when the data request size in bytes is less than the dram channel width times the burst size (8)*/ + /*the dram data requirement is also multiplied by the number of channels in the case of low power tiling*/ + /*the page close-open time is determined by trc and the number of page close-opens*/ + /*in tiled mode graphics or underlay with scatter-gather enabled the bytes per page close-open is the product of the memory line interleave times the maximum of the scatter-gather page width and the product of the tile width (8 pixels) times the number of channels times the number of banks.*/ + /*in linear mode graphics or underlay with scatter-gather enabled and inefficient pitch, the bytes per page close-open is the line request alternation slice, because different lines are in completely different 4k address bases.*/ + /*otherwise, the bytes page close-open is the chunk size because that is the arbitration slice.*/ + /*pte requests are grouped by pte requests per chunk if that is more than 1. each group costs a page close-open time for dmif reads*/ + /*cursor requests outstanding are limited to a group of two source lines. each group costs a page close-open time for dmif reads*/ + /*the display reads and writes time for data transfer is the minimum data or cursor buffer size in time minus the mc urgent latency*/ + /*the mc urgent latency is experienced more than one time if the number of dmif requests in the data buffer exceeds the request buffer size plus the request slots reserved for dmif in the dram channel arbiter queues*/ + /*the dispclk required is the maximum for all surfaces of the maximum of the source pixels for first output pixel times the throughput factor, divided by the pixels per dispclk, and divided by the minimum latency hiding minus the dram speed/p-state change latency minus the burst time, and the source pixels for last output pixel, times the throughput factor, divided by the pixels per dispclk, and divided by the minimum latency hiding minus the dram speed/p-state change latency minus the burst time, plus the active time.*/ + /*the data burst time is the maximum of the total page close-open time, total dmif/mcifwr buffer size in memory divided by the dram bandwidth, and the total dmif/mcifwr buffer size in memory divided by the 32 byte sclk data bus bandwidth, each multiplied by its efficiency.*/ + /*the source line transfer time is the maximum for all surfaces of the maximum of the burst time plus the urgent latency times the floor of the data required divided by the buffer size for the fist pixel, and the burst time plus the urgent latency times the floor of the data required divided by the buffer size for the last pixel plus the active time.*/ + /*the source pixels for the first output pixel is 512 if the scaler vertical filter initialization value is greater than 2, and it is 4 times the source width if it is greater than 4.*/ + /*the source pixels for the last output pixel is the source width times the scaler vertical filter initialization value rounded up to even*/ + /*the source data for these pixels is the number of pixels times the bytes per pixel times the bytes per request divided by the useful bytes per request.*/ + data->cursor_total_data = bw_int_to_fixed(0); + data->cursor_total_request_groups = bw_int_to_fixed(0); + data->scatter_gather_total_pte_requests = bw_int_to_fixed(0); + data->scatter_gather_total_pte_request_groups = bw_int_to_fixed(0); + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + data->cursor_total_data = bw_add(data->cursor_total_data, bw_mul(bw_mul(bw_int_to_fixed(2), data->cursor_width_pixels[i]), bw_int_to_fixed(4))); + if (dceip->large_cursor == 1) { + data->cursor_total_request_groups = bw_add(data->cursor_total_request_groups, bw_int_to_fixed((dceip->cursor_max_outstanding_group_num + 1))); + } + else { + data->cursor_total_request_groups = bw_add(data->cursor_total_request_groups, bw_ceil2(bw_div(data->cursor_width_pixels[i], dceip->cursor_chunk_width), bw_int_to_fixed(1))); + } + if (data->scatter_gather_enable_for_pipe[i]) { + data->scatter_gather_total_pte_requests = bw_add(data->scatter_gather_total_pte_requests, data->scatter_gather_pte_request_limit[i]); + data->scatter_gather_total_pte_request_groups = bw_add(data->scatter_gather_total_pte_request_groups, bw_ceil2(bw_div(data->scatter_gather_pte_request_limit[i], bw_ceil2(data->pte_request_per_chunk[i], bw_int_to_fixed(1))), bw_int_to_fixed(1))); + } + } + } + data->tile_width_in_pixels = bw_int_to_fixed(8); + data->dmif_total_number_of_data_request_page_close_open = bw_int_to_fixed(0); + data->mcifwr_total_number_of_data_request_page_close_open = bw_int_to_fixed(0); + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if (data->scatter_gather_enable_for_pipe[i] == 1 && tiling_mode[i] != bw_def_linear) { + data->bytes_per_page_close_open = bw_mul(data->lines_interleaved_in_mem_access[i], bw_max2(bw_mul(bw_mul(bw_mul(bw_int_to_fixed(data->bytes_per_pixel[i]), data->tile_width_in_pixels), bw_int_to_fixed(vbios->number_of_dram_banks)), bw_int_to_fixed(data->number_of_dram_channels)), bw_mul(bw_int_to_fixed(data->bytes_per_pixel[i]), data->scatter_gather_page_width[i]))); + } + else if (data->scatter_gather_enable_for_pipe[i] == 1 && tiling_mode[i] == bw_def_linear && bw_equ(bw_mod((bw_mul(data->pitch_in_pixels_after_surface_type[i], bw_int_to_fixed(data->bytes_per_pixel[i]))), data->inefficient_linear_pitch_in_bytes), bw_int_to_fixed(0))) { + data->bytes_per_page_close_open = dceip->linear_mode_line_request_alternation_slice; + } + else { + data->bytes_per_page_close_open = data->memory_chunk_size_in_bytes[i]; + } + if (surface_type[i] != bw_def_display_write_back420_luma && surface_type[i] != bw_def_display_write_back420_chroma) { + data->dmif_total_number_of_data_request_page_close_open = bw_add(data->dmif_total_number_of_data_request_page_close_open, bw_div(bw_ceil2(data->adjusted_data_buffer_size[i], data->memory_chunk_size_in_bytes[i]), data->bytes_per_page_close_open)); + } + else { + data->mcifwr_total_number_of_data_request_page_close_open = bw_add(data->mcifwr_total_number_of_data_request_page_close_open, bw_div(bw_ceil2(data->adjusted_data_buffer_size[i], data->memory_chunk_size_in_bytes[i]), data->bytes_per_page_close_open)); + } + } + } + data->dmif_total_page_close_open_time = bw_div(bw_mul((bw_add(bw_add(data->dmif_total_number_of_data_request_page_close_open, data->scatter_gather_total_pte_request_groups), data->cursor_total_request_groups)), vbios->trc), bw_int_to_fixed(1000)); + data->mcifwr_total_page_close_open_time = bw_div(bw_mul(data->mcifwr_total_number_of_data_request_page_close_open, vbios->trc), bw_int_to_fixed(1000)); + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + data->adjusted_data_buffer_size_in_memory[i] = bw_div(bw_mul(data->adjusted_data_buffer_size[i], data->bytes_per_request[i]), data->useful_bytes_per_request[i]); + } + } + data->total_requests_for_adjusted_dmif_size = bw_int_to_fixed(0); + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if (surface_type[i] != bw_def_display_write_back420_luma && surface_type[i] != bw_def_display_write_back420_chroma) { + data->total_requests_for_adjusted_dmif_size = bw_add(data->total_requests_for_adjusted_dmif_size, bw_div(data->adjusted_data_buffer_size[i], data->useful_bytes_per_request[i])); + } + } + } + data->total_dmifmc_urgent_trips = bw_ceil2(bw_div(data->total_requests_for_adjusted_dmif_size, (bw_add(dceip->dmif_request_buffer_size, bw_int_to_fixed(vbios->number_of_request_slots_gmc_reserves_for_dmif_per_channel * data->number_of_dram_channels)))), bw_int_to_fixed(1)); + data->total_dmifmc_urgent_latency = bw_mul(vbios->dmifmc_urgent_latency, data->total_dmifmc_urgent_trips); + data->total_display_reads_required_data = bw_int_to_fixed(0); + data->total_display_reads_required_dram_access_data = bw_int_to_fixed(0); + data->total_display_writes_required_data = bw_int_to_fixed(0); + data->total_display_writes_required_dram_access_data = bw_int_to_fixed(0); + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if (surface_type[i] != bw_def_display_write_back420_luma && surface_type[i] != bw_def_display_write_back420_chroma) { + data->display_reads_required_data = data->adjusted_data_buffer_size_in_memory[i]; + /*for hbm memories, each channel is split into 2 pseudo-channels that are each 64 bits in width. each*/ + /*pseudo-channel may be read independently of one another.*/ + /*the read burst length (bl) for hbm memories is 4, so each read command will access 32 bytes of data.*/ + /*the 64 or 32 byte sized data is stored in one pseudo-channel.*/ + /*it will take 4 memclk cycles or 8 yclk cycles to fetch 64 bytes of data from the hbm memory (2 read commands).*/ + /*it will take 2 memclk cycles or 4 yclk cycles to fetch 32 bytes of data from the hbm memory (1 read command).*/ + /*for gddr5/ddr4 memories, there is additional overhead if the size of the request is smaller than 64 bytes.*/ + /*the read burst length (bl) for gddr5/ddr4 memories is 8, regardless of the size of the data request.*/ + /*therefore it will require 8 cycles to fetch 64 or 32 bytes of data from the memory.*/ + /*the memory efficiency will be 50% for the 32 byte sized data.*/ + if (vbios->memory_type == bw_def_hbm) { + data->display_reads_required_dram_access_data = data->adjusted_data_buffer_size_in_memory[i]; + } + else { + data->display_reads_required_dram_access_data = bw_mul(data->adjusted_data_buffer_size_in_memory[i], bw_ceil2(bw_div(bw_int_to_fixed((8 * vbios->dram_channel_width_in_bits / 8)), data->bytes_per_request[i]), bw_int_to_fixed(1))); + } + data->total_display_reads_required_data = bw_add(data->total_display_reads_required_data, data->display_reads_required_data); + data->total_display_reads_required_dram_access_data = bw_add(data->total_display_reads_required_dram_access_data, data->display_reads_required_dram_access_data); + } + else { + data->total_display_writes_required_data = bw_add(data->total_display_writes_required_data, data->adjusted_data_buffer_size_in_memory[i]); + data->total_display_writes_required_dram_access_data = bw_add(data->total_display_writes_required_dram_access_data, bw_mul(data->adjusted_data_buffer_size_in_memory[i], bw_ceil2(bw_div(bw_int_to_fixed(vbios->dram_channel_width_in_bits), data->bytes_per_request[i]), bw_int_to_fixed(1)))); + } + } + } + data->total_display_reads_required_data = bw_add(bw_add(data->total_display_reads_required_data, data->cursor_total_data), bw_mul(data->scatter_gather_total_pte_requests, bw_int_to_fixed(64))); + data->total_display_reads_required_dram_access_data = bw_add(bw_add(data->total_display_reads_required_dram_access_data, data->cursor_total_data), bw_mul(data->scatter_gather_total_pte_requests, bw_int_to_fixed(64))); + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if (bw_mtn(data->v_filter_init[i], bw_int_to_fixed(4))) { + data->src_pixels_for_first_output_pixel[i] = bw_mul(bw_int_to_fixed(4), data->source_width_rounded_up_to_chunks[i]); + } + else { + if (bw_mtn(data->v_filter_init[i], bw_int_to_fixed(2))) { + data->src_pixels_for_first_output_pixel[i] = bw_int_to_fixed(512); + } + else { + data->src_pixels_for_first_output_pixel[i] = bw_int_to_fixed(0); + } + } + data->src_data_for_first_output_pixel[i] = bw_div(bw_mul(bw_mul(data->src_pixels_for_first_output_pixel[i], bw_int_to_fixed(data->bytes_per_pixel[i])), data->bytes_per_request[i]), data->useful_bytes_per_request[i]); + data->src_pixels_for_last_output_pixel[i] = bw_mul(data->source_width_rounded_up_to_chunks[i], bw_max2(bw_ceil2(data->v_filter_init[i], bw_int_to_fixed(dceip->lines_interleaved_into_lb)), bw_mul(bw_ceil2(data->vsr[i], bw_int_to_fixed(dceip->lines_interleaved_into_lb)), data->horizontal_blank_and_chunk_granularity_factor[i]))); + data->src_data_for_last_output_pixel[i] = bw_div(bw_mul(bw_mul(bw_mul(data->source_width_rounded_up_to_chunks[i], bw_max2(bw_ceil2(data->v_filter_init[i], bw_int_to_fixed(dceip->lines_interleaved_into_lb)), data->lines_interleaved_in_mem_access[i])), bw_int_to_fixed(data->bytes_per_pixel[i])), data->bytes_per_request[i]), data->useful_bytes_per_request[i]); + data->active_time[i] = bw_div(bw_div(data->source_width_rounded_up_to_chunks[i], data->hsr[i]), data->pixel_rate[i]); + } + } + for (i = 0; i <= 2; i++) { + for (j = 0; j <= 7; j++) { + data->dmif_burst_time[i][j] = bw_max3(data->dmif_total_page_close_open_time, bw_div(data->total_display_reads_required_dram_access_data, (bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[i]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels)))), bw_div(data->total_display_reads_required_data, (bw_mul(bw_mul(sclk[j], vbios->data_return_bus_width), bw_int_to_fixed(bus_efficiency))))); + if (data->d1_display_write_back_dwb_enable == 1) { + data->mcifwr_burst_time[i][j] = bw_max3(data->mcifwr_total_page_close_open_time, bw_div(data->total_display_writes_required_dram_access_data, (bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[i]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_wrchannels)))), bw_div(data->total_display_writes_required_data, (bw_mul(bw_mul(sclk[j], vbios->data_return_bus_width), bw_int_to_fixed(bus_efficiency))))); + } + } + } + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + for (j = 0; j <= 2; j++) { + for (k = 0; k <= 7; k++) { + if (data->enable[i]) { + if (surface_type[i] != bw_def_display_write_back420_luma && surface_type[i] != bw_def_display_write_back420_chroma) { + /*time to transfer data from the dmif buffer to the lb. since the mc to dmif transfer time overlaps*/ + /*with the dmif to lb transfer time, only time to transfer the last chunk is considered.*/ + data->dmif_buffer_transfer_time[i] = bw_mul(data->source_width_rounded_up_to_chunks[i], (bw_div(dceip->lb_write_pixels_per_dispclk, (bw_div(vbios->low_voltage_max_dispclk, dceip->display_pipe_throughput_factor))))); + data->line_source_transfer_time[i][j][k] = bw_max2(bw_mul((bw_add(data->total_dmifmc_urgent_latency, data->dmif_burst_time[j][k])), bw_floor2(bw_div(data->src_data_for_first_output_pixel[i], data->adjusted_data_buffer_size_in_memory[i]), bw_int_to_fixed(1))), bw_sub(bw_add(bw_mul((bw_add(data->total_dmifmc_urgent_latency, data->dmif_burst_time[j][k])), bw_floor2(bw_div(data->src_data_for_last_output_pixel[i], data->adjusted_data_buffer_size_in_memory[i]), bw_int_to_fixed(1))), data->dmif_buffer_transfer_time[i]), data->active_time[i])); + /*during an mclk switch the requests from the dce ip are stored in the gmc/arb. these requests should be serviced immediately*/ + /*after the mclk switch sequence and not incur an urgent latency penalty. it is assumed that the gmc/arb can hold up to 256 requests*/ + /*per memory channel. if the dce ip is urgent after the mclk switch sequence, all pending requests and subsequent requests should be*/ + /*immediately serviced without a gap in the urgent requests.*/ + /*the latency incurred would be the time to issue the requests and return the data for the first or last output pixel.*/ + if (surface_type[i] == bw_def_graphics) { + switch (data->lb_bpc[i]) { + case 6: + data->v_scaler_efficiency = dceip->graphics_vscaler_efficiency6_bit_per_component; + break; + case 8: + data->v_scaler_efficiency = dceip->graphics_vscaler_efficiency8_bit_per_component; + break; + case 10: + data->v_scaler_efficiency = dceip->graphics_vscaler_efficiency10_bit_per_component; + break; + default: + data->v_scaler_efficiency = dceip->graphics_vscaler_efficiency12_bit_per_component; + break; + } + if (data->use_alpha[i] == 1) { + data->v_scaler_efficiency = bw_min2(data->v_scaler_efficiency, dceip->alpha_vscaler_efficiency); + } + } + else { + switch (data->lb_bpc[i]) { + case 6: + data->v_scaler_efficiency = dceip->underlay_vscaler_efficiency6_bit_per_component; + break; + case 8: + data->v_scaler_efficiency = dceip->underlay_vscaler_efficiency8_bit_per_component; + break; + case 10: + data->v_scaler_efficiency = dceip->underlay_vscaler_efficiency10_bit_per_component; + break; + default: + data->v_scaler_efficiency = bw_int_to_fixed(3); + break; + } + } + if (dceip->pre_downscaler_enabled && bw_mtn(data->hsr[i], bw_int_to_fixed(1))) { + data->scaler_limits_factor = bw_max2(bw_div(data->v_taps[i], data->v_scaler_efficiency), bw_div(data->source_width_rounded_up_to_chunks[i], data->h_total[i])); + } + else { + data->scaler_limits_factor = bw_max3(bw_int_to_fixed(1), bw_ceil2(bw_div(data->h_taps[i], bw_int_to_fixed(4)), bw_int_to_fixed(1)), bw_mul(data->hsr[i], bw_max2(bw_div(data->v_taps[i], data->v_scaler_efficiency), bw_int_to_fixed(1)))); + } + data->dram_speed_change_line_source_transfer_time[i][j][k] = bw_mul(bw_int_to_fixed(2), bw_max2((bw_add((bw_div(data->src_data_for_first_output_pixel[i], bw_min2(bw_mul(data->bytes_per_request[i], sclk[k]), bw_div(bw_mul(bw_mul(data->bytes_per_request[i], data->pixel_rate[i]), data->scaler_limits_factor), bw_int_to_fixed(2))))), (bw_mul(data->dmif_burst_time[j][k], bw_floor2(bw_div(data->src_data_for_first_output_pixel[i], data->adjusted_data_buffer_size_in_memory[i]), bw_int_to_fixed(1)))))), (bw_add((bw_div(data->src_data_for_last_output_pixel[i], bw_min2(bw_mul(data->bytes_per_request[i], sclk[k]), bw_div(bw_mul(bw_mul(data->bytes_per_request[i], data->pixel_rate[i]), data->scaler_limits_factor), bw_int_to_fixed(2))))), (bw_sub(bw_mul(data->dmif_burst_time[j][k], bw_floor2(bw_div(data->src_data_for_last_output_pixel[i], data->adjusted_data_buffer_size_in_memory[i]), bw_int_to_fixed(1))), data->active_time[i])))))); + } + else { + data->line_source_transfer_time[i][j][k] = bw_max2(bw_mul((bw_add(vbios->mcifwrmc_urgent_latency, data->mcifwr_burst_time[j][k])), bw_floor2(bw_div(data->src_data_for_first_output_pixel[i], data->adjusted_data_buffer_size_in_memory[i]), bw_int_to_fixed(1))), bw_sub(bw_mul((bw_add(vbios->mcifwrmc_urgent_latency, data->mcifwr_burst_time[j][k])), bw_floor2(bw_div(data->src_data_for_last_output_pixel[i], data->adjusted_data_buffer_size_in_memory[i]), bw_int_to_fixed(1))), data->active_time[i])); + /*during an mclk switch the requests from the dce ip are stored in the gmc/arb. these requests should be serviced immediately*/ + /*after the mclk switch sequence and not incur an urgent latency penalty. it is assumed that the gmc/arb can hold up to 256 requests*/ + /*per memory channel. if the dce ip is urgent after the mclk switch sequence, all pending requests and subsequent requests should be*/ + /*immediately serviced without a gap in the urgent requests.*/ + /*the latency incurred would be the time to issue the requests and return the data for the first or last output pixel.*/ + data->dram_speed_change_line_source_transfer_time[i][j][k] = bw_max2((bw_add((bw_div(data->src_data_for_first_output_pixel[i], bw_min2(bw_mul(data->bytes_per_request[i], sclk[k]), bw_div(bw_mul(data->bytes_per_request[i], vbios->low_voltage_max_dispclk), bw_int_to_fixed(2))))), (bw_mul(data->mcifwr_burst_time[j][k], bw_floor2(bw_div(data->src_data_for_first_output_pixel[i], data->adjusted_data_buffer_size_in_memory[i]), bw_int_to_fixed(1)))))), (bw_add((bw_div(data->src_data_for_last_output_pixel[i], bw_min2(bw_mul(data->bytes_per_request[i], sclk[k]), bw_div(bw_mul(data->bytes_per_request[i], vbios->low_voltage_max_dispclk), bw_int_to_fixed(2))))), (bw_sub(bw_mul(data->mcifwr_burst_time[j][k], bw_floor2(bw_div(data->src_data_for_last_output_pixel[i], data->adjusted_data_buffer_size_in_memory[i]), bw_int_to_fixed(1))), data->active_time[i]))))); + } + } + } + } + } + /*cpu c-state and p-state change enable*/ + /*for cpu p-state change to be possible for a yclk(pclk) and sclk level the dispclk required has to be enough for the blackout duration*/ + /*for cpu c-state change to be possible for a yclk(pclk) and sclk level the dispclk required has to be enough for the blackout duration and recovery*/ + /*condition for the blackout duration:*/ + /* minimum latency hiding > blackout duration + dmif burst time + line source transfer time*/ + /*condition for the blackout recovery:*/ + /* recovery time > dmif burst time + 2 * urgent latency*/ + /* recovery time > (display bw * blackout duration + (2 * urgent latency + dmif burst time)*dispclk - dmif size )*/ + /* / (dispclk - display bw)*/ + /*the minimum latency hiding is the minimum for all pipes of one screen line time, plus one more line time if doing lb prefetch, plus the dmif data buffer size equivalent in time, minus the urgent latency.*/ + /*the minimum latency hiding is further limited by the cursor. the cursor latency hiding is the number of lines of the cursor buffer, minus one if the downscaling is less than two, or minus three if it is more*/ + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if ((bw_equ(dceip->stutter_and_dram_clock_state_change_gated_before_cursor, bw_int_to_fixed(0)) && bw_mtn(data->cursor_width_pixels[i], bw_int_to_fixed(0)))) { + if (bw_ltn(data->vsr[i], bw_int_to_fixed(2))) { + data->cursor_latency_hiding[i] = bw_div(bw_div(bw_mul((bw_sub(dceip->cursor_dcp_buffer_lines, bw_int_to_fixed(1))), data->h_total[i]), data->vsr[i]), data->pixel_rate[i]); + } + else { + data->cursor_latency_hiding[i] = bw_div(bw_div(bw_mul((bw_sub(dceip->cursor_dcp_buffer_lines, bw_int_to_fixed(3))), data->h_total[i]), data->vsr[i]), data->pixel_rate[i]); + } + } + else { + data->cursor_latency_hiding[i] = bw_int_to_fixed(9999); + } + } + } + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if (dceip->graphics_lb_nodownscaling_multi_line_prefetching == 1 && (bw_equ(data->vsr[i], bw_int_to_fixed(1)) || (bw_leq(data->vsr[i], bw_frc_to_fixed(8, 10)) && bw_leq(data->v_taps[i], bw_int_to_fixed(2)) && data->lb_bpc[i] == 8)) && surface_type[i] == bw_def_graphics) { + data->minimum_latency_hiding[i] = bw_sub(bw_div(bw_mul((bw_div((bw_add(bw_sub(data->lb_partitions[i], bw_int_to_fixed(1)), bw_div(bw_div(data->data_buffer_size[i], bw_int_to_fixed(data->bytes_per_pixel[i])), data->source_width_pixels[i]))), data->vsr[i])), data->h_total[i]), data->pixel_rate[i]), data->total_dmifmc_urgent_latency); + } + else { + data->minimum_latency_hiding[i] = bw_sub(bw_div(bw_mul((bw_div((bw_add(bw_int_to_fixed(1 + data->line_buffer_prefetch[i]), bw_div(bw_div(data->data_buffer_size[i], bw_int_to_fixed(data->bytes_per_pixel[i])), data->source_width_pixels[i]))), data->vsr[i])), data->h_total[i]), data->pixel_rate[i]), data->total_dmifmc_urgent_latency); + } + data->minimum_latency_hiding_with_cursor[i] = bw_min2(data->minimum_latency_hiding[i], data->cursor_latency_hiding[i]); + } + } + for (i = 0; i <= 2; i++) { + for (j = 0; j <= 7; j++) { + data->blackout_duration_margin[i][j] = bw_int_to_fixed(9999); + data->dispclk_required_for_blackout_duration[i][j] = bw_int_to_fixed(0); + data->dispclk_required_for_blackout_recovery[i][j] = bw_int_to_fixed(0); + for (k = 0; k <= maximum_number_of_surfaces - 1; k++) { + if (data->enable[k] && bw_mtn(vbios->blackout_duration, bw_int_to_fixed(0))) { + if (surface_type[k] != bw_def_display_write_back420_luma && surface_type[k] != bw_def_display_write_back420_chroma) { + data->blackout_duration_margin[i][j] = bw_min2(data->blackout_duration_margin[i][j], bw_sub(bw_sub(bw_sub(data->minimum_latency_hiding_with_cursor[k], vbios->blackout_duration), data->dmif_burst_time[i][j]), data->line_source_transfer_time[k][i][j])); + data->dispclk_required_for_blackout_duration[i][j] = bw_max3(data->dispclk_required_for_blackout_duration[i][j], bw_div(bw_div(bw_mul(data->src_pixels_for_first_output_pixel[k], dceip->display_pipe_throughput_factor), dceip->lb_write_pixels_per_dispclk), (bw_sub(bw_sub(data->minimum_latency_hiding_with_cursor[k], vbios->blackout_duration), data->dmif_burst_time[i][j]))), bw_div(bw_div(bw_mul(data->src_pixels_for_last_output_pixel[k], dceip->display_pipe_throughput_factor), dceip->lb_write_pixels_per_dispclk), (bw_add(bw_sub(bw_sub(data->minimum_latency_hiding_with_cursor[k], vbios->blackout_duration), data->dmif_burst_time[i][j]), data->active_time[k])))); + if (bw_leq(vbios->maximum_blackout_recovery_time, bw_add(bw_mul(bw_int_to_fixed(2), data->total_dmifmc_urgent_latency), data->dmif_burst_time[i][j]))) { + data->dispclk_required_for_blackout_recovery[i][j] = bw_int_to_fixed(9999); + } + else if (bw_ltn(data->adjusted_data_buffer_size[k], bw_mul(bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]), (bw_add(vbios->blackout_duration, bw_add(bw_mul(bw_int_to_fixed(2), data->total_dmifmc_urgent_latency), data->dmif_burst_time[i][j])))))) { + data->dispclk_required_for_blackout_recovery[i][j] = bw_max2(data->dispclk_required_for_blackout_recovery[i][j], bw_div(bw_mul(bw_div(bw_div((bw_sub(bw_mul(bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]), (bw_add(vbios->blackout_duration, vbios->maximum_blackout_recovery_time))), data->adjusted_data_buffer_size[k])), bw_int_to_fixed(data->bytes_per_pixel[k])), (bw_sub(vbios->maximum_blackout_recovery_time, bw_sub(bw_mul(bw_int_to_fixed(2), data->total_dmifmc_urgent_latency), data->dmif_burst_time[i][j])))), data->latency_hiding_lines[k]), data->lines_interleaved_in_mem_access[k])); + } + } + else { + data->blackout_duration_margin[i][j] = bw_min2(data->blackout_duration_margin[i][j], bw_sub(bw_sub(bw_sub(bw_sub(data->minimum_latency_hiding_with_cursor[k], vbios->blackout_duration), data->dmif_burst_time[i][j]), data->mcifwr_burst_time[i][j]), data->line_source_transfer_time[k][i][j])); + data->dispclk_required_for_blackout_duration[i][j] = bw_max3(data->dispclk_required_for_blackout_duration[i][j], bw_div(bw_div(bw_mul(data->src_pixels_for_first_output_pixel[k], dceip->display_pipe_throughput_factor), dceip->lb_write_pixels_per_dispclk), (bw_sub(bw_sub(bw_sub(data->minimum_latency_hiding_with_cursor[k], vbios->blackout_duration), data->dmif_burst_time[i][j]), data->mcifwr_burst_time[i][j]))), bw_div(bw_div(bw_mul(data->src_pixels_for_last_output_pixel[k], dceip->display_pipe_throughput_factor), dceip->lb_write_pixels_per_dispclk), (bw_add(bw_sub(bw_sub(bw_sub(data->minimum_latency_hiding_with_cursor[k], vbios->blackout_duration), data->dmif_burst_time[i][j]), data->mcifwr_burst_time[i][j]), data->active_time[k])))); + if (bw_ltn(vbios->maximum_blackout_recovery_time, bw_add(bw_add(bw_mul(bw_int_to_fixed(2), vbios->mcifwrmc_urgent_latency), data->dmif_burst_time[i][j]), data->mcifwr_burst_time[i][j]))) { + data->dispclk_required_for_blackout_recovery[i][j] = bw_int_to_fixed(9999); + } + else if (bw_ltn(data->adjusted_data_buffer_size[k], bw_mul(bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]), (bw_add(vbios->blackout_duration, bw_add(bw_mul(bw_int_to_fixed(2), data->total_dmifmc_urgent_latency), data->dmif_burst_time[i][j])))))) { + data->dispclk_required_for_blackout_recovery[i][j] = bw_max2(data->dispclk_required_for_blackout_recovery[i][j], bw_div(bw_mul(bw_div(bw_div((bw_sub(bw_mul(bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]), (bw_add(vbios->blackout_duration, vbios->maximum_blackout_recovery_time))), data->adjusted_data_buffer_size[k])), bw_int_to_fixed(data->bytes_per_pixel[k])), (bw_sub(vbios->maximum_blackout_recovery_time, (bw_add(bw_mul(bw_int_to_fixed(2), data->total_dmifmc_urgent_latency), data->dmif_burst_time[i][j]))))), data->latency_hiding_lines[k]), data->lines_interleaved_in_mem_access[k])); + } + } + } + } + } + } + if (bw_mtn(data->blackout_duration_margin[high][s_high], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[high][s_high], vbios->high_voltage_max_dispclk)) { + data->cpup_state_change_enable = bw_def_yes; + if (bw_ltn(data->dispclk_required_for_blackout_recovery[high][s_high], vbios->high_voltage_max_dispclk)) { + data->cpuc_state_change_enable = bw_def_yes; + } + else { + data->cpuc_state_change_enable = bw_def_no; + } + } + else { + data->cpup_state_change_enable = bw_def_no; + data->cpuc_state_change_enable = bw_def_no; + } + /*nb p-state change enable*/ + /*for dram speed/p-state change to be possible for a yclk(pclk) and sclk level there has to be positive margin and the dispclk required has to be*/ + /*below the maximum.*/ + /*the dram speed/p-state change margin is the minimum for all surfaces of the maximum latency hiding minus the dram speed/p-state change latency,*/ + /*minus the dmif burst time, minus the source line transfer time*/ + /*the maximum latency hiding is the minimum latency hiding plus one source line used for de-tiling in the line buffer, plus half the urgent latency*/ + /*if stutter and dram clock state change are gated before cursor then the cursor latency hiding does not limit stutter or dram clock state change*/ + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if ((dceip->graphics_lb_nodownscaling_multi_line_prefetching == 1)) { + data->maximum_latency_hiding[i] = bw_add(data->minimum_latency_hiding[i], bw_mul(bw_frc_to_fixed(8, 10), data->total_dmifmc_urgent_latency)); + } + else { + /*maximum_latency_hiding(i) = minimum_latency_hiding(i) + 1 / vsr(i) * h_total(i) / pixel_rate(i) + 0.5 * total_dmifmc_urgent_latency*/ + data->maximum_latency_hiding[i] = bw_add(data->minimum_latency_hiding[i], bw_mul(bw_frc_to_fixed(8, 10), data->total_dmifmc_urgent_latency)); + } + data->maximum_latency_hiding_with_cursor[i] = bw_min2(data->maximum_latency_hiding[i], data->cursor_latency_hiding[i]); + } + } + /*initialize variables*/ + number_of_displays_enabled = 0; + number_of_displays_enabled_with_margin = 0; + for (k = 0; k < maximum_number_of_surfaces; k++) { + if (data->enable[k]) { + number_of_displays_enabled = number_of_displays_enabled + 1; + } + } + data->display_pstate_change_enable[maximum_number_of_surfaces - 1] = 0; + for (i = 0; i <= 2; i++) { + for (j = 0; j <= 7; j++) { + data->min_dram_speed_change_margin[i][j] = bw_int_to_fixed(9999); + data->dram_speed_change_margin = bw_int_to_fixed(9999); + data->dispclk_required_for_dram_speed_change[i][j] = bw_int_to_fixed(0); + data->num_displays_with_margin[i][j] = 0; + for (k = 0; k <= maximum_number_of_surfaces - 1; k++) { + if (data->enable[k]) { + if (surface_type[k] != bw_def_display_write_back420_luma && surface_type[k] != bw_def_display_write_back420_chroma) { + data->dram_speed_change_margin = bw_sub(bw_sub(bw_sub(data->maximum_latency_hiding_with_cursor[k], vbios->nbp_state_change_latency), data->dmif_burst_time[i][j]), data->dram_speed_change_line_source_transfer_time[k][i][j]); + if ((bw_mtn(data->dram_speed_change_margin, bw_int_to_fixed(0)) && bw_ltn(data->dram_speed_change_margin, bw_int_to_fixed(9999)))) { + /*determine the minimum dram clock change margin for each set of clock frequencies*/ + data->min_dram_speed_change_margin[i][j] = bw_min2(data->min_dram_speed_change_margin[i][j], data->dram_speed_change_margin); + /*compute the maximum clock frequuency required for the dram clock change at each set of clock frequencies*/ + data->dispclk_required_for_dram_speed_change[i][j] = bw_max3(data->dispclk_required_for_dram_speed_change[i][j], bw_div(bw_div(bw_mul(data->src_pixels_for_first_output_pixel[k], dceip->display_pipe_throughput_factor), dceip->lb_write_pixels_per_dispclk), (bw_sub(bw_sub(bw_sub(data->maximum_latency_hiding_with_cursor[k], vbios->nbp_state_change_latency), data->dmif_burst_time[i][j]), data->dram_speed_change_line_source_transfer_time[k][i][j]))), bw_div(bw_div(bw_mul(data->src_pixels_for_last_output_pixel[k], dceip->display_pipe_throughput_factor), dceip->lb_write_pixels_per_dispclk), (bw_add(bw_sub(bw_sub(bw_sub(data->maximum_latency_hiding_with_cursor[k], vbios->nbp_state_change_latency), data->dmif_burst_time[i][j]), data->dram_speed_change_line_source_transfer_time[k][i][j]), data->active_time[k])))); + if ((bw_ltn(data->dispclk_required_for_dram_speed_change[i][j], vbios->high_voltage_max_dispclk))) { + data->display_pstate_change_enable[k] = 1; + data->num_displays_with_margin[i][j] = data->num_displays_with_margin[i][j] + 1; + } + } + } + else { + data->dram_speed_change_margin = bw_sub(bw_sub(bw_sub(bw_sub(data->maximum_latency_hiding_with_cursor[k], vbios->nbp_state_change_latency), data->dmif_burst_time[i][j]), data->mcifwr_burst_time[i][j]), data->dram_speed_change_line_source_transfer_time[k][i][j]); + if ((bw_mtn(data->dram_speed_change_margin, bw_int_to_fixed(0)) && bw_ltn(data->dram_speed_change_margin, bw_int_to_fixed(9999)))) { + /*determine the minimum dram clock change margin for each display pipe*/ + data->min_dram_speed_change_margin[i][j] = bw_min2(data->min_dram_speed_change_margin[i][j], data->dram_speed_change_margin); + /*compute the maximum clock frequuency required for the dram clock change at each set of clock frequencies*/ + data->dispclk_required_for_dram_speed_change[i][j] = bw_max3(data->dispclk_required_for_dram_speed_change[i][j], bw_div(bw_div(bw_mul(data->src_pixels_for_first_output_pixel[k], dceip->display_pipe_throughput_factor), dceip->lb_write_pixels_per_dispclk), (bw_sub(bw_sub(bw_sub(bw_sub(data->maximum_latency_hiding_with_cursor[k], vbios->nbp_state_change_latency), data->dmif_burst_time[i][j]), data->dram_speed_change_line_source_transfer_time[k][i][j]), data->mcifwr_burst_time[i][j]))), bw_div(bw_div(bw_mul(data->src_pixels_for_last_output_pixel[k], dceip->display_pipe_throughput_factor), dceip->lb_write_pixels_per_dispclk), (bw_add(bw_sub(bw_sub(bw_sub(bw_sub(data->maximum_latency_hiding_with_cursor[k], vbios->nbp_state_change_latency), data->dmif_burst_time[i][j]), data->dram_speed_change_line_source_transfer_time[k][i][j]), data->mcifwr_burst_time[i][j]), data->active_time[k])))); + if ((bw_ltn(data->dispclk_required_for_dram_speed_change[i][j], vbios->high_voltage_max_dispclk))) { + data->display_pstate_change_enable[k] = 1; + data->num_displays_with_margin[i][j] = data->num_displays_with_margin[i][j] + 1; + } + } + } + } + } + } + } + /*determine the number of displays with margin to switch in the v_active region*/ + for (k = 0; k <= maximum_number_of_surfaces - 1; k++) { + if ((data->enable[k] == 1 && data->display_pstate_change_enable[k] == 1)) { + number_of_displays_enabled_with_margin = number_of_displays_enabled_with_margin + 1; + } + } + /*determine the number of displays that don't have any dram clock change margin, but*/ + /*have the same resolution. these displays can switch in a common vblank region if*/ + /*their frames are aligned.*/ + data->min_vblank_dram_speed_change_margin = bw_int_to_fixed(9999); + for (k = 0; k <= maximum_number_of_surfaces - 1; k++) { + if (data->enable[k]) { + if (surface_type[k] != bw_def_display_write_back420_luma && surface_type[k] != bw_def_display_write_back420_chroma) { + data->v_blank_dram_speed_change_margin[k] = bw_sub(bw_sub(bw_sub(bw_div(bw_mul((bw_sub(data->v_total[k], bw_sub(bw_div(data->src_height[k], data->v_scale_ratio[k]), bw_int_to_fixed(4)))), data->h_total[k]), data->pixel_rate[k]), vbios->nbp_state_change_latency), data->dmif_burst_time[low][s_low]), data->dram_speed_change_line_source_transfer_time[k][low][s_low]); + data->min_vblank_dram_speed_change_margin = bw_min2(data->min_vblank_dram_speed_change_margin, data->v_blank_dram_speed_change_margin[k]); + } + else { + data->v_blank_dram_speed_change_margin[k] = bw_sub(bw_sub(bw_sub(bw_sub(bw_div(bw_mul((bw_sub(data->v_total[k], bw_sub(bw_div(data->src_height[k], data->v_scale_ratio[k]), bw_int_to_fixed(4)))), data->h_total[k]), data->pixel_rate[k]), vbios->nbp_state_change_latency), data->dmif_burst_time[low][s_low]), data->mcifwr_burst_time[low][s_low]), data->dram_speed_change_line_source_transfer_time[k][low][s_low]); + data->min_vblank_dram_speed_change_margin = bw_min2(data->min_vblank_dram_speed_change_margin, data->v_blank_dram_speed_change_margin[k]); + } + } + } + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + data->displays_with_same_mode[i] = bw_int_to_fixed(0); + if (data->enable[i] == 1 && data->display_pstate_change_enable[i] == 0 && bw_mtn(data->v_blank_dram_speed_change_margin[i], bw_int_to_fixed(0))) { + for (j = 0; j <= maximum_number_of_surfaces - 1; j++) { + if ((data->enable[j] == 1 && bw_equ(data->source_width_rounded_up_to_chunks[i], data->source_width_rounded_up_to_chunks[j]) && bw_equ(data->source_height_rounded_up_to_chunks[i], data->source_height_rounded_up_to_chunks[j]) && bw_equ(data->vsr[i], data->vsr[j]) && bw_equ(data->hsr[i], data->hsr[j]) && bw_equ(data->pixel_rate[i], data->pixel_rate[j]))) { + data->displays_with_same_mode[i] = bw_add(data->displays_with_same_mode[i], bw_int_to_fixed(1)); + } + } + } + } + /*compute the maximum number of aligned displays with no margin*/ + number_of_aligned_displays_with_no_margin = 0; + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + number_of_aligned_displays_with_no_margin = bw_fixed_to_int(bw_max2(bw_int_to_fixed(number_of_aligned_displays_with_no_margin), data->displays_with_same_mode[i])); + } + /*dram clock change is possible, if all displays have positive margin except for one display or a group of*/ + /*aligned displays with the same timing.*/ + /*the display(s) with the negative margin can be switched in the v_blank region while the other*/ + /*displays are in v_blank or v_active.*/ + if ((number_of_displays_enabled_with_margin + number_of_aligned_displays_with_no_margin == number_of_displays_enabled && bw_mtn(data->min_dram_speed_change_margin[high][s_high], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[high][s_high], bw_int_to_fixed(9999)) && bw_ltn(data->dispclk_required_for_dram_speed_change[high][s_high], vbios->high_voltage_max_dispclk))) { + data->nbp_state_change_enable = bw_def_yes; + } + else { + data->nbp_state_change_enable = bw_def_no; + } + /*dram clock change is possible only in vblank if all displays are aligned and have no margin*/ + if ((number_of_aligned_displays_with_no_margin == number_of_displays_enabled)) { + nbp_state_change_enable_blank = bw_def_yes; + } + else { + nbp_state_change_enable_blank = bw_def_no; + } + /*required yclk(pclk)*/ + /*yclk requirement only makes sense if the dmif and mcifwr data total page close-open time is less than the time for data transfer and the total pte requests fit in the scatter-gather saw queque size*/ + /*if that is the case, the yclk requirement is the maximum of the ones required by dmif and mcifwr, and the high/low yclk(pclk) is chosen accordingly*/ + /*high yclk(pclk) has to be selected when dram speed/p-state change is not possible.*/ + data->min_cursor_memory_interface_buffer_size_in_time = bw_int_to_fixed(9999); + /* number of cursor lines stored in the cursor data return buffer*/ + num_cursor_lines = 0; + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if (bw_mtn(data->cursor_width_pixels[i], bw_int_to_fixed(0))) { + /*compute number of cursor lines stored in data return buffer*/ + if (bw_leq(data->cursor_width_pixels[i], bw_int_to_fixed(64)) && dceip->large_cursor == 1) { + num_cursor_lines = 4; + } + else { + num_cursor_lines = 2; + } + data->min_cursor_memory_interface_buffer_size_in_time = bw_min2(data->min_cursor_memory_interface_buffer_size_in_time, bw_div(bw_mul(bw_div(bw_int_to_fixed(num_cursor_lines), data->vsr[i]), data->h_total[i]), data->pixel_rate[i])); + } + } + } + /*compute minimum time to read one chunk from the dmif buffer*/ + if ((number_of_displays_enabled > 2)) { + data->chunk_request_delay = 0; + } + else { + data->chunk_request_delay = bw_fixed_to_int(bw_div(bw_int_to_fixed(512), vbios->high_voltage_max_dispclk)); + } + data->min_read_buffer_size_in_time = bw_min2(data->min_cursor_memory_interface_buffer_size_in_time, data->min_dmif_size_in_time); + data->display_reads_time_for_data_transfer = bw_sub(bw_sub(data->min_read_buffer_size_in_time, data->total_dmifmc_urgent_latency), bw_int_to_fixed(data->chunk_request_delay)); + data->display_writes_time_for_data_transfer = bw_sub(data->min_mcifwr_size_in_time, vbios->mcifwrmc_urgent_latency); + data->dmif_required_dram_bandwidth = bw_div(data->total_display_reads_required_dram_access_data, data->display_reads_time_for_data_transfer); + data->mcifwr_required_dram_bandwidth = bw_div(data->total_display_writes_required_dram_access_data, data->display_writes_time_for_data_transfer); + data->required_dmifmc_urgent_latency_for_page_close_open = bw_div((bw_sub(data->min_read_buffer_size_in_time, data->dmif_total_page_close_open_time)), data->total_dmifmc_urgent_trips); + data->required_mcifmcwr_urgent_latency = bw_sub(data->min_mcifwr_size_in_time, data->mcifwr_total_page_close_open_time); + if (bw_mtn(data->scatter_gather_total_pte_requests, dceip->maximum_total_outstanding_pte_requests_allowed_by_saw)) { + data->required_dram_bandwidth_gbyte_per_second = bw_int_to_fixed(9999); + yclk_message = bw_def_exceeded_allowed_outstanding_pte_req_queue_size; + data->y_clk_level = high; + data->dram_bandwidth = bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[high]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels)); + } + else if (bw_mtn(vbios->dmifmc_urgent_latency, data->required_dmifmc_urgent_latency_for_page_close_open) || bw_mtn(vbios->mcifwrmc_urgent_latency, data->required_mcifmcwr_urgent_latency)) { + data->required_dram_bandwidth_gbyte_per_second = bw_int_to_fixed(9999); + yclk_message = bw_def_exceeded_allowed_page_close_open; + data->y_clk_level = high; + data->dram_bandwidth = bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[high]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels)); + } + else { + data->required_dram_bandwidth_gbyte_per_second = bw_div(bw_max2(data->dmif_required_dram_bandwidth, data->mcifwr_required_dram_bandwidth), bw_int_to_fixed(1000)); + if (bw_ltn(bw_mul(data->required_dram_bandwidth_gbyte_per_second, bw_int_to_fixed(1000)), bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[low]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels))) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[low][s_high], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[low][s_high], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[low][s_high], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[low][s_high], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[low][s_high], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[low][s_high], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[low][s_high], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[low][s_high], vbios->high_voltage_max_dispclk) && data->num_displays_with_margin[low][s_high] == number_of_displays_enabled_with_margin))) { + yclk_message = bw_fixed_to_int(vbios->low_yclk); + data->y_clk_level = low; + data->dram_bandwidth = bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[low]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels)); + } + else if (bw_ltn(bw_mul(data->required_dram_bandwidth_gbyte_per_second, bw_int_to_fixed(1000)), bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[mid]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels))) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[mid][s_high], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[mid][s_high], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[mid][s_high], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[mid][s_high], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[mid][s_high], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[mid][s_high], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[mid][s_high], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[mid][s_high], vbios->high_voltage_max_dispclk) && data->num_displays_with_margin[mid][s_high] == number_of_displays_enabled_with_margin))) { + yclk_message = bw_fixed_to_int(vbios->mid_yclk); + data->y_clk_level = mid; + data->dram_bandwidth = bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[mid]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels)); + } + else if (bw_ltn(bw_mul(data->required_dram_bandwidth_gbyte_per_second, bw_int_to_fixed(1000)), bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[high]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels)))) { + yclk_message = bw_fixed_to_int(vbios->high_yclk); + data->y_clk_level = high; + data->dram_bandwidth = bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[high]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels)); + } + else { + yclk_message = bw_def_exceeded_allowed_maximum_bw; + data->y_clk_level = high; + data->dram_bandwidth = bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[high]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels)); + } + } + /*required sclk*/ + /*sclk requirement only makes sense if the total pte requests fit in the scatter-gather saw queque size*/ + /*if that is the case, the sclk requirement is the maximum of the ones required by dmif and mcifwr, and the high/mid/low sclk is chosen accordingly, unless that choice results in foresaking dram speed/nb p-state change.*/ + /*the dmif and mcifwr sclk required is the one that allows the transfer of all pipe's data buffer size through the sclk bus in the time for data transfer*/ + /*for dmif, pte and cursor requests have to be included.*/ + data->dmif_required_sclk = bw_div(bw_div(data->total_display_reads_required_data, data->display_reads_time_for_data_transfer), (bw_mul(vbios->data_return_bus_width, bw_int_to_fixed(bus_efficiency)))); + data->mcifwr_required_sclk = bw_div(bw_div(data->total_display_writes_required_data, data->display_writes_time_for_data_transfer), (bw_mul(vbios->data_return_bus_width, bw_int_to_fixed(bus_efficiency)))); + if (bw_mtn(data->scatter_gather_total_pte_requests, dceip->maximum_total_outstanding_pte_requests_allowed_by_saw)) { + data->required_sclk = bw_int_to_fixed(9999); + sclk_message = bw_def_exceeded_allowed_outstanding_pte_req_queue_size; + data->sclk_level = s_high; + } + else if (bw_mtn(vbios->dmifmc_urgent_latency, data->required_dmifmc_urgent_latency_for_page_close_open) || bw_mtn(vbios->mcifwrmc_urgent_latency, data->required_mcifmcwr_urgent_latency)) { + data->required_sclk = bw_int_to_fixed(9999); + sclk_message = bw_def_exceeded_allowed_page_close_open; + data->sclk_level = s_high; + } + else { + data->required_sclk = bw_max2(data->dmif_required_sclk, data->mcifwr_required_sclk); + if (bw_ltn(data->required_sclk, sclk[s_low]) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_low], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_low], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_low], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_low], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[data->y_clk_level][s_low], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[data->y_clk_level][s_low], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[data->y_clk_level][s_low], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[data->y_clk_level][s_low], vbios->low_voltage_max_dispclk) && data->num_displays_with_margin[data->y_clk_level][s_low] == number_of_displays_enabled_with_margin))) { + sclk_message = bw_def_low; + data->sclk_level = s_low; + data->required_sclk = vbios->low_sclk; + } + else if (bw_ltn(data->required_sclk, sclk[s_mid1]) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid1], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid1], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid1], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid1], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[data->y_clk_level][s_mid1], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid1], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid1], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[data->y_clk_level][s_mid1], vbios->mid_voltage_max_dispclk) && data->num_displays_with_margin[data->y_clk_level][s_mid1] == number_of_displays_enabled_with_margin))) { + sclk_message = bw_def_mid; + data->sclk_level = s_mid1; + data->required_sclk = vbios->mid1_sclk; + } + else if (bw_ltn(data->required_sclk, sclk[s_mid2]) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid2], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid2], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid2], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid2], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[data->y_clk_level][s_mid2], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid2], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid2], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[data->y_clk_level][s_mid2], vbios->mid_voltage_max_dispclk) && data->num_displays_with_margin[data->y_clk_level][s_mid2] == number_of_displays_enabled_with_margin))) { + sclk_message = bw_def_mid; + data->sclk_level = s_mid2; + data->required_sclk = vbios->mid2_sclk; + } + else if (bw_ltn(data->required_sclk, sclk[s_mid3]) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid3], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid3], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid3], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid3], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[data->y_clk_level][s_mid3], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid3], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid3], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[data->y_clk_level][s_mid3], vbios->mid_voltage_max_dispclk) && data->num_displays_with_margin[data->y_clk_level][s_mid3] == number_of_displays_enabled_with_margin))) { + sclk_message = bw_def_mid; + data->sclk_level = s_mid3; + data->required_sclk = vbios->mid3_sclk; + } + else if (bw_ltn(data->required_sclk, sclk[s_mid4]) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid4], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid4], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid4], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid4], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[data->y_clk_level][s_mid4], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid4], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid4], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[data->y_clk_level][s_mid4], vbios->mid_voltage_max_dispclk) && data->num_displays_with_margin[data->y_clk_level][s_mid4] == number_of_displays_enabled_with_margin))) { + sclk_message = bw_def_mid; + data->sclk_level = s_mid4; + data->required_sclk = vbios->mid4_sclk; + } + else if (bw_ltn(data->required_sclk, sclk[s_mid5]) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid5], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid5], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid5], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid5], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[data->y_clk_level][s_mid5], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid5], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid5], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[data->y_clk_level][s_mid5], vbios->mid_voltage_max_dispclk) && data->num_displays_with_margin[data->y_clk_level][s_mid5] == number_of_displays_enabled_with_margin))) { + sclk_message = bw_def_mid; + data->sclk_level = s_mid5; + data->required_sclk = vbios->mid5_sclk; + } + else if (bw_ltn(data->required_sclk, sclk[s_mid6]) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid6], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid6], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid6], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid6], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[data->y_clk_level][s_mid6], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid6], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid6], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[data->y_clk_level][s_mid6], vbios->high_voltage_max_dispclk) && data->num_displays_with_margin[data->y_clk_level][s_mid6] == number_of_displays_enabled_with_margin))) { + sclk_message = bw_def_mid; + data->sclk_level = s_mid6; + data->required_sclk = vbios->mid6_sclk; + } + else if (bw_ltn(data->required_sclk, sclk[s_high])) { + sclk_message = bw_def_high; + data->sclk_level = s_high; + data->required_sclk = vbios->high_sclk; + } + else { + sclk_message = bw_def_exceeded_allowed_maximum_sclk; + data->sclk_level = s_high; + /*required_sclk = high_sclk*/ + } + } + /*dispclk*/ + /*if dispclk is set to the maximum, ramping is not required. dispclk required without ramping is less than the dispclk required with ramping.*/ + /*if dispclk required without ramping is more than the maximum dispclk, that is the dispclk required, and the mode is not supported*/ + /*if that does not happen, but dispclk required with ramping is more than the maximum dispclk, dispclk required is just the maximum dispclk*/ + /*if that does not happen either, dispclk required is the dispclk required with ramping.*/ + /*dispclk required without ramping is the maximum of the one required for display pipe pixel throughput, for scaler throughput, for total read request thrrougput and for dram/np p-state change if enabled.*/ + /*the display pipe pixel throughput is the maximum of lines in per line out in the beginning of the frame and lines in per line out in the middle of the frame multiplied by the horizontal blank and chunk granularity factor, altogether multiplied by the ratio of the source width to the line time, divided by the line buffer pixels per dispclk throughput, and multiplied by the display pipe throughput factor.*/ + /*the horizontal blank and chunk granularity factor is the ratio of the line time divided by the line time minus half the horizontal blank and chunk time. it applies when the lines in per line out is not 2 or 4.*/ + /*the dispclk required for scaler throughput is the product of the pixel rate and the scaling limits factor.*/ + /*the dispclk required for total read request throughput is the product of the peak request-per-second bandwidth and the dispclk cycles per request, divided by the request efficiency.*/ + /*for the dispclk required with ramping, instead of multiplying just the pipe throughput by the display pipe throughput factor, we multiply the scaler and pipe throughput by the ramping factor.*/ + /*the scaling limits factor is the product of the horizontal scale ratio, and the ratio of the vertical taps divided by the scaler efficiency clamped to at least 1.*/ + /*the scaling limits factor itself it also clamped to at least 1*/ + /*if doing downscaling with the pre-downscaler enabled, the horizontal scale ratio should not be considered above (use "1")*/ + data->downspread_factor = bw_add(bw_int_to_fixed(1), bw_div(vbios->down_spread_percentage, bw_int_to_fixed(100))); + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if (surface_type[i] == bw_def_graphics) { + switch (data->lb_bpc[i]) { + case 6: + data->v_scaler_efficiency = dceip->graphics_vscaler_efficiency6_bit_per_component; + break; + case 8: + data->v_scaler_efficiency = dceip->graphics_vscaler_efficiency8_bit_per_component; + break; + case 10: + data->v_scaler_efficiency = dceip->graphics_vscaler_efficiency10_bit_per_component; + break; + default: + data->v_scaler_efficiency = dceip->graphics_vscaler_efficiency12_bit_per_component; + break; + } + if (data->use_alpha[i] == 1) { + data->v_scaler_efficiency = bw_min2(data->v_scaler_efficiency, dceip->alpha_vscaler_efficiency); + } + } + else { + switch (data->lb_bpc[i]) { + case 6: + data->v_scaler_efficiency = dceip->underlay_vscaler_efficiency6_bit_per_component; + break; + case 8: + data->v_scaler_efficiency = dceip->underlay_vscaler_efficiency8_bit_per_component; + break; + case 10: + data->v_scaler_efficiency = dceip->underlay_vscaler_efficiency10_bit_per_component; + break; + default: + data->v_scaler_efficiency = dceip->underlay_vscaler_efficiency12_bit_per_component; + break; + } + } + if (dceip->pre_downscaler_enabled && bw_mtn(data->hsr[i], bw_int_to_fixed(1))) { + data->scaler_limits_factor = bw_max2(bw_div(data->v_taps[i], data->v_scaler_efficiency), bw_div(data->source_width_rounded_up_to_chunks[i], data->h_total[i])); + } + else { + data->scaler_limits_factor = bw_max3(bw_int_to_fixed(1), bw_ceil2(bw_div(data->h_taps[i], bw_int_to_fixed(4)), bw_int_to_fixed(1)), bw_mul(data->hsr[i], bw_max2(bw_div(data->v_taps[i], data->v_scaler_efficiency), bw_int_to_fixed(1)))); + } + data->display_pipe_pixel_throughput = bw_div(bw_div(bw_mul(bw_max2(data->lb_lines_in_per_line_out_in_beginning_of_frame[i], bw_mul(data->lb_lines_in_per_line_out_in_middle_of_frame[i], data->horizontal_blank_and_chunk_granularity_factor[i])), data->source_width_rounded_up_to_chunks[i]), (bw_div(data->h_total[i], data->pixel_rate[i]))), dceip->lb_write_pixels_per_dispclk); + data->dispclk_required_without_ramping[i] = bw_mul(data->downspread_factor, bw_max2(bw_mul(data->pixel_rate[i], data->scaler_limits_factor), bw_mul(dceip->display_pipe_throughput_factor, data->display_pipe_pixel_throughput))); + data->dispclk_required_with_ramping[i] = bw_mul(dceip->dispclk_ramping_factor, bw_max2(bw_mul(data->pixel_rate[i], data->scaler_limits_factor), data->display_pipe_pixel_throughput)); + } + } + data->total_dispclk_required_with_ramping = bw_int_to_fixed(0); + data->total_dispclk_required_without_ramping = bw_int_to_fixed(0); + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if (bw_ltn(data->total_dispclk_required_with_ramping, data->dispclk_required_with_ramping[i])) { + data->total_dispclk_required_with_ramping = data->dispclk_required_with_ramping[i]; + } + if (bw_ltn(data->total_dispclk_required_without_ramping, data->dispclk_required_without_ramping[i])) { + data->total_dispclk_required_without_ramping = data->dispclk_required_without_ramping[i]; + } + } + } + data->total_read_request_bandwidth = bw_int_to_fixed(0); + data->total_write_request_bandwidth = bw_int_to_fixed(0); + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if (surface_type[i] != bw_def_display_write_back420_luma && surface_type[i] != bw_def_display_write_back420_chroma) { + data->total_read_request_bandwidth = bw_add(data->total_read_request_bandwidth, data->request_bandwidth[i]); + } + else { + data->total_write_request_bandwidth = bw_add(data->total_write_request_bandwidth, data->request_bandwidth[i]); + } + } + } + data->dispclk_required_for_total_read_request_bandwidth = bw_div(bw_mul(data->total_read_request_bandwidth, dceip->dispclk_per_request), dceip->request_efficiency); + data->total_dispclk_required_with_ramping_with_request_bandwidth = bw_max2(data->total_dispclk_required_with_ramping, data->dispclk_required_for_total_read_request_bandwidth); + data->total_dispclk_required_without_ramping_with_request_bandwidth = bw_max2(data->total_dispclk_required_without_ramping, data->dispclk_required_for_total_read_request_bandwidth); + if (data->cpuc_state_change_enable == bw_def_yes) { + data->total_dispclk_required_with_ramping_with_request_bandwidth = bw_max3(data->total_dispclk_required_with_ramping_with_request_bandwidth, data->dispclk_required_for_blackout_duration[data->y_clk_level][data->sclk_level], data->dispclk_required_for_blackout_recovery[data->y_clk_level][data->sclk_level]); + data->total_dispclk_required_without_ramping_with_request_bandwidth = bw_max3(data->total_dispclk_required_without_ramping_with_request_bandwidth, data->dispclk_required_for_blackout_duration[data->y_clk_level][data->sclk_level], data->dispclk_required_for_blackout_recovery[data->y_clk_level][data->sclk_level]); + } + if (data->cpup_state_change_enable == bw_def_yes) { + data->total_dispclk_required_with_ramping_with_request_bandwidth = bw_max2(data->total_dispclk_required_with_ramping_with_request_bandwidth, data->dispclk_required_for_blackout_duration[data->y_clk_level][data->sclk_level]); + data->total_dispclk_required_without_ramping_with_request_bandwidth = bw_max2(data->total_dispclk_required_without_ramping_with_request_bandwidth, data->dispclk_required_for_blackout_duration[data->y_clk_level][data->sclk_level]); + } + if (data->nbp_state_change_enable == bw_def_yes) { + data->total_dispclk_required_with_ramping_with_request_bandwidth = bw_max2(data->total_dispclk_required_with_ramping_with_request_bandwidth, data->dispclk_required_for_dram_speed_change[data->y_clk_level][data->sclk_level]); + data->total_dispclk_required_without_ramping_with_request_bandwidth = bw_max2(data->total_dispclk_required_without_ramping_with_request_bandwidth, data->dispclk_required_for_dram_speed_change[data->y_clk_level][data->sclk_level]); + } + if (bw_ltn(data->total_dispclk_required_with_ramping_with_request_bandwidth, vbios->high_voltage_max_dispclk)) { + data->dispclk = data->total_dispclk_required_with_ramping_with_request_bandwidth; + } + else if (bw_ltn(data->total_dispclk_required_without_ramping_with_request_bandwidth, vbios->high_voltage_max_dispclk)) { + data->dispclk = vbios->high_voltage_max_dispclk; + } + else { + data->dispclk = data->total_dispclk_required_without_ramping_with_request_bandwidth; + } + /* required core voltage*/ + /* the core voltage required is low if sclk, yclk(pclk)and dispclk are within the low limits*/ + /* otherwise, the core voltage required is medium if yclk (pclk) is within the low limit and sclk and dispclk are within the medium limit*/ + /* otherwise, the core voltage required is high if the three clocks are within the high limits*/ + /* otherwise, or if the mode is not supported, core voltage requirement is not applicable*/ + if (pipe_check == bw_def_notok) { + voltage = bw_def_na; + } + else if (mode_check == bw_def_notok) { + voltage = bw_def_notok; + } + else if (bw_equ(bw_int_to_fixed(yclk_message), vbios->low_yclk) && sclk_message == bw_def_low && bw_ltn(data->dispclk, vbios->low_voltage_max_dispclk)) { + voltage = bw_def_0_72; + } + else if ((bw_equ(bw_int_to_fixed(yclk_message), vbios->low_yclk) || bw_equ(bw_int_to_fixed(yclk_message), vbios->mid_yclk)) && (sclk_message == bw_def_low || sclk_message == bw_def_mid) && bw_ltn(data->dispclk, vbios->mid_voltage_max_dispclk)) { + voltage = bw_def_0_8; + } + else if ((bw_equ(bw_int_to_fixed(yclk_message), vbios->low_yclk) || bw_equ(bw_int_to_fixed(yclk_message), vbios->mid_yclk) || bw_equ(bw_int_to_fixed(yclk_message), vbios->high_yclk)) && (sclk_message == bw_def_low || sclk_message == bw_def_mid || sclk_message == bw_def_high) && bw_leq(data->dispclk, vbios->high_voltage_max_dispclk)) { + if ((data->nbp_state_change_enable == bw_def_no && nbp_state_change_enable_blank == bw_def_no)) { + voltage = bw_def_high_no_nbp_state_change; + } + else { + voltage = bw_def_0_9; + } + } + else { + voltage = bw_def_notok; + } + if (voltage == bw_def_0_72) { + data->max_phyclk = vbios->low_voltage_max_phyclk; + } + else if (voltage == bw_def_0_8) { + data->max_phyclk = vbios->mid_voltage_max_phyclk; + } + else { + data->max_phyclk = vbios->high_voltage_max_phyclk; + } + /*required blackout recovery time*/ + data->blackout_recovery_time = bw_int_to_fixed(0); + for (k = 0; k <= maximum_number_of_surfaces - 1; k++) { + if (data->enable[k] && bw_mtn(vbios->blackout_duration, bw_int_to_fixed(0)) && data->cpup_state_change_enable == bw_def_yes) { + if (surface_type[k] != bw_def_display_write_back420_luma && surface_type[k] != bw_def_display_write_back420_chroma) { + data->blackout_recovery_time = bw_max2(data->blackout_recovery_time, bw_add(bw_mul(bw_int_to_fixed(2), data->total_dmifmc_urgent_latency), data->dmif_burst_time[data->y_clk_level][data->sclk_level])); + if (bw_ltn(data->adjusted_data_buffer_size[k], bw_mul(bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]), (bw_add(vbios->blackout_duration, bw_add(bw_mul(bw_int_to_fixed(2), data->total_dmifmc_urgent_latency), data->dmif_burst_time[data->y_clk_level][data->sclk_level])))))) { + data->blackout_recovery_time = bw_max2(data->blackout_recovery_time, bw_div((bw_add(bw_mul(bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]), vbios->blackout_duration), bw_sub(bw_div(bw_mul(bw_mul(bw_mul((bw_add(bw_mul(bw_int_to_fixed(2), data->total_dmifmc_urgent_latency), data->dmif_burst_time[data->y_clk_level][data->sclk_level])), data->dispclk), bw_int_to_fixed(data->bytes_per_pixel[k])), data->lines_interleaved_in_mem_access[k]), data->latency_hiding_lines[k]), data->adjusted_data_buffer_size[k]))), (bw_sub(bw_div(bw_mul(bw_mul(data->dispclk, bw_int_to_fixed(data->bytes_per_pixel[k])), data->lines_interleaved_in_mem_access[k]), data->latency_hiding_lines[k]), bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]))))); + } + } + else { + data->blackout_recovery_time = bw_max2(data->blackout_recovery_time, bw_add(bw_mul(bw_int_to_fixed(2), vbios->mcifwrmc_urgent_latency), data->mcifwr_burst_time[data->y_clk_level][data->sclk_level])); + if (bw_ltn(data->adjusted_data_buffer_size[k], bw_mul(bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]), (bw_add(vbios->blackout_duration, bw_add(bw_mul(bw_int_to_fixed(2), vbios->mcifwrmc_urgent_latency), data->mcifwr_burst_time[data->y_clk_level][data->sclk_level])))))) { + data->blackout_recovery_time = bw_max2(data->blackout_recovery_time, bw_div((bw_add(bw_mul(bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]), vbios->blackout_duration), bw_sub(bw_div(bw_mul(bw_mul(bw_mul((bw_add(bw_add(bw_mul(bw_int_to_fixed(2), vbios->mcifwrmc_urgent_latency), data->dmif_burst_time[i][j]), data->mcifwr_burst_time[data->y_clk_level][data->sclk_level])), data->dispclk), bw_int_to_fixed(data->bytes_per_pixel[k])), data->lines_interleaved_in_mem_access[k]), data->latency_hiding_lines[k]), data->adjusted_data_buffer_size[k]))), (bw_sub(bw_div(bw_mul(bw_mul(data->dispclk, bw_int_to_fixed(data->bytes_per_pixel[k])), data->lines_interleaved_in_mem_access[k]), data->latency_hiding_lines[k]), bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]))))); + } + } + } + } + /*sclk deep sleep*/ + /*during self-refresh, sclk can be reduced to dispclk divided by the minimum pixels in the data fifo entry, with 15% margin, but shoudl not be set to less than the request bandwidth.*/ + /*the data fifo entry is 16 pixels for the writeback, 64 bytes/bytes_per_pixel for the graphics, 16 pixels for the parallel rotation underlay,*/ + /*and 16 bytes/bytes_per_pixel for the orthogonal rotation underlay.*/ + /*in parallel mode (underlay pipe), the data read from the dmifv buffer is variable and based on the pixel depth (8bbp - 16 bytes, 16 bpp - 32 bytes, 32 bpp - 64 bytes)*/ + /*in orthogonal mode (underlay pipe), the data read from the dmifv buffer is fixed at 16 bytes.*/ + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if (surface_type[i] == bw_def_display_write_back420_luma || surface_type[i] == bw_def_display_write_back420_chroma) { + data->pixels_per_data_fifo_entry[i] = bw_int_to_fixed(16); + } + else if (surface_type[i] == bw_def_graphics) { + data->pixels_per_data_fifo_entry[i] = bw_div(bw_int_to_fixed(64), bw_int_to_fixed(data->bytes_per_pixel[i])); + } + else if (data->orthogonal_rotation[i] == 0) { + data->pixels_per_data_fifo_entry[i] = bw_int_to_fixed(16); + } + else { + data->pixels_per_data_fifo_entry[i] = bw_div(bw_int_to_fixed(16), bw_int_to_fixed(data->bytes_per_pixel[i])); + } + } + } + data->min_pixels_per_data_fifo_entry = bw_int_to_fixed(9999); + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if (bw_mtn(data->min_pixels_per_data_fifo_entry, data->pixels_per_data_fifo_entry[i])) { + data->min_pixels_per_data_fifo_entry = data->pixels_per_data_fifo_entry[i]; + } + } + } + data->sclk_deep_sleep = bw_max2(bw_div(bw_mul(data->dispclk, bw_frc_to_fixed(115, 100)), data->min_pixels_per_data_fifo_entry), data->total_read_request_bandwidth); + /*urgent, stutter and nb-p_state watermark*/ + /*the urgent watermark is the maximum of the urgent trip time plus the pixel transfer time, the urgent trip times to get data for the first pixel, and the urgent trip times to get data for the last pixel.*/ + /*the stutter exit watermark is the self refresh exit time plus the maximum of the data burst time plus the pixel transfer time, the data burst times to get data for the first pixel, and the data burst times to get data for the last pixel. it does not apply to the writeback.*/ + /*the nb p-state change watermark is the dram speed/p-state change time plus the maximum of the data burst time plus the pixel transfer time, the data burst times to get data for the first pixel, and the data burst times to get data for the last pixel.*/ + /*the pixel transfer time is the maximum of the time to transfer the source pixels required for the first output pixel, and the time to transfer the pixels for the last output pixel minus the active line time.*/ + /*blackout_duration is added to the urgent watermark*/ + data->chunk_request_time = bw_int_to_fixed(0); + data->cursor_request_time = bw_int_to_fixed(0); + /*compute total time to request one chunk from each active display pipe*/ + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + data->chunk_request_time = bw_add(data->chunk_request_time, (bw_div((bw_div(bw_int_to_fixed(pixels_per_chunk * data->bytes_per_pixel[i]), data->useful_bytes_per_request[i])), bw_min2(sclk[data->sclk_level], bw_div(data->dispclk, bw_int_to_fixed(2)))))); + } + } + /*compute total time to request cursor data*/ + data->cursor_request_time = (bw_div(data->cursor_total_data, (bw_mul(bw_int_to_fixed(32), sclk[data->sclk_level])))); + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + data->line_source_pixels_transfer_time = bw_max2(bw_div(bw_div(data->src_pixels_for_first_output_pixel[i], dceip->lb_write_pixels_per_dispclk), (bw_div(data->dispclk, dceip->display_pipe_throughput_factor))), bw_sub(bw_div(bw_div(data->src_pixels_for_last_output_pixel[i], dceip->lb_write_pixels_per_dispclk), (bw_div(data->dispclk, dceip->display_pipe_throughput_factor))), data->active_time[i])); + if (surface_type[i] != bw_def_display_write_back420_luma && surface_type[i] != bw_def_display_write_back420_chroma) { + data->urgent_watermark[i] = bw_add(bw_add(bw_add(bw_add(bw_add(data->total_dmifmc_urgent_latency, data->dmif_burst_time[data->y_clk_level][data->sclk_level]), bw_max2(data->line_source_pixels_transfer_time, data->line_source_transfer_time[i][data->y_clk_level][data->sclk_level])), vbios->blackout_duration), data->chunk_request_time), data->cursor_request_time); + data->stutter_exit_watermark[i] = bw_add(bw_sub(vbios->stutter_self_refresh_exit_latency, data->total_dmifmc_urgent_latency), data->urgent_watermark[i]); + data->stutter_entry_watermark[i] = bw_add(bw_sub(bw_add(vbios->stutter_self_refresh_exit_latency, vbios->stutter_self_refresh_entry_latency), data->total_dmifmc_urgent_latency), data->urgent_watermark[i]); + /*unconditionally remove black out time from the nb p_state watermark*/ + if ((data->display_pstate_change_enable[i] == 1)) { + data->nbp_state_change_watermark[i] = bw_add(bw_add(vbios->nbp_state_change_latency, data->dmif_burst_time[data->y_clk_level][data->sclk_level]), bw_max2(data->line_source_pixels_transfer_time, data->dram_speed_change_line_source_transfer_time[i][data->y_clk_level][data->sclk_level])); + } + else { + /*maximize the watermark to force the switch in the vb_lank region of the frame*/ + data->nbp_state_change_watermark[i] = bw_int_to_fixed(131000); + } + } + else { + data->urgent_watermark[i] = bw_add(bw_add(bw_add(bw_add(bw_add(vbios->mcifwrmc_urgent_latency, data->mcifwr_burst_time[data->y_clk_level][data->sclk_level]), bw_max2(data->line_source_pixels_transfer_time, data->line_source_transfer_time[i][data->y_clk_level][data->sclk_level])), vbios->blackout_duration), data->chunk_request_time), data->cursor_request_time); + data->stutter_exit_watermark[i] = bw_int_to_fixed(0); + data->stutter_entry_watermark[i] = bw_int_to_fixed(0); + if ((data->display_pstate_change_enable[i] == 1)) { + data->nbp_state_change_watermark[i] = bw_add(bw_add(vbios->nbp_state_change_latency, data->mcifwr_burst_time[data->y_clk_level][data->sclk_level]), bw_max2(data->line_source_pixels_transfer_time, data->dram_speed_change_line_source_transfer_time[i][data->y_clk_level][data->sclk_level])); + } + else { + /*maximize the watermark to force the switch in the vb_lank region of the frame*/ + data->nbp_state_change_watermark[i] = bw_int_to_fixed(131000); + } + } + } + } + /*stutter mode enable*/ + /*in the multi-display case the stutter exit or entry watermark cannot exceed the minimum latency hiding capabilities of the*/ + /*display pipe.*/ + data->stutter_mode_enable = data->cpuc_state_change_enable; + if (data->number_of_displays > 1) { + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if ((bw_mtn(data->stutter_exit_watermark[i], data->minimum_latency_hiding[i]) || bw_mtn(data->stutter_entry_watermark[i], data->minimum_latency_hiding[i]))) { + data->stutter_mode_enable = bw_def_no; + } + } + } + } + /*performance metrics*/ + /* display read access efficiency (%)*/ + /* display write back access efficiency (%)*/ + /* stutter efficiency (%)*/ + /* extra underlay pitch recommended for efficiency (pixels)*/ + /* immediate flip time (us)*/ + /* latency for other clients due to urgent display read (us)*/ + /* latency for other clients due to urgent display write (us)*/ + /* average bandwidth consumed by display (no compression) (gb/s)*/ + /* required dram bandwidth (gb/s)*/ + /* required sclk (m_hz)*/ + /* required rd urgent latency (us)*/ + /* nb p-state change margin (us)*/ + /*dmif and mcifwr dram access efficiency*/ + /*is the ratio between the ideal dram access time (which is the data buffer size in memory divided by the dram bandwidth), and the actual time which is the total page close-open time. but it cannot exceed the dram efficiency provided by the memory subsystem*/ + data->dmifdram_access_efficiency = bw_min2(bw_div(bw_div(data->total_display_reads_required_dram_access_data, data->dram_bandwidth), data->dmif_total_page_close_open_time), bw_int_to_fixed(1)); + if (bw_mtn(data->total_display_writes_required_dram_access_data, bw_int_to_fixed(0))) { + data->mcifwrdram_access_efficiency = bw_min2(bw_div(bw_div(data->total_display_writes_required_dram_access_data, data->dram_bandwidth), data->mcifwr_total_page_close_open_time), bw_int_to_fixed(1)); + } + else { + data->mcifwrdram_access_efficiency = bw_int_to_fixed(0); + } + /*average bandwidth*/ + /*the average bandwidth with no compression is the vertical active time is the source width times the bytes per pixel divided by the line time, multiplied by the vertical scale ratio and the ratio of bytes per request divided by the useful bytes per request.*/ + /*the average bandwidth with compression is the same, divided by the compression ratio*/ + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + data->average_bandwidth_no_compression[i] = bw_div(bw_mul(bw_mul(bw_div(bw_mul(data->source_width_rounded_up_to_chunks[i], bw_int_to_fixed(data->bytes_per_pixel[i])), (bw_div(data->h_total[i], data->pixel_rate[i]))), data->vsr[i]), data->bytes_per_request[i]), data->useful_bytes_per_request[i]); + data->average_bandwidth[i] = bw_div(data->average_bandwidth_no_compression[i], data->compression_rate[i]); + } + } + data->total_average_bandwidth_no_compression = bw_int_to_fixed(0); + data->total_average_bandwidth = bw_int_to_fixed(0); + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + data->total_average_bandwidth_no_compression = bw_add(data->total_average_bandwidth_no_compression, data->average_bandwidth_no_compression[i]); + data->total_average_bandwidth = bw_add(data->total_average_bandwidth, data->average_bandwidth[i]); + } + } + /*stutter efficiency*/ + /*the stutter efficiency is the frame-average time in self-refresh divided by the frame-average stutter cycle duration. only applies if the display write-back is not enabled.*/ + /*the frame-average stutter cycle used is the minimum for all pipes of the frame-average data buffer size in time, times the compression rate*/ + /*the frame-average time in self-refresh is the stutter cycle minus the self refresh exit latency and the burst time*/ + /*the stutter cycle is the dmif buffer size reduced by the excess of the stutter exit watermark over the lb size in time.*/ + /*the burst time is the data needed during the stutter cycle divided by the available bandwidth*/ + /*compute the time read all the data from the dmif buffer to the lb (dram refresh period)*/ + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + data->stutter_refresh_duration[i] = bw_sub(bw_mul(bw_div(bw_div(bw_mul(bw_div(bw_div(data->adjusted_data_buffer_size[i], bw_int_to_fixed(data->bytes_per_pixel[i])), data->source_width_rounded_up_to_chunks[i]), data->h_total[i]), data->vsr[i]), data->pixel_rate[i]), data->compression_rate[i]), bw_max2(bw_int_to_fixed(0), bw_sub(data->stutter_exit_watermark[i], bw_div(bw_mul((bw_sub(data->lb_partitions[i], bw_int_to_fixed(1))), data->h_total[i]), data->pixel_rate[i])))); + data->stutter_dmif_buffer_size[i] = bw_div(bw_mul(bw_mul(bw_div(bw_mul(bw_mul(data->stutter_refresh_duration[i], bw_int_to_fixed(data->bytes_per_pixel[i])), data->source_width_rounded_up_to_chunks[i]), data->h_total[i]), data->vsr[i]), data->pixel_rate[i]), data->compression_rate[i]); + } + } + data->min_stutter_refresh_duration = bw_int_to_fixed(9999); + data->total_stutter_dmif_buffer_size = 0; + data->total_bytes_requested = 0; + data->min_stutter_dmif_buffer_size = 9999; + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if (bw_mtn(data->min_stutter_refresh_duration, data->stutter_refresh_duration[i])) { + data->min_stutter_refresh_duration = data->stutter_refresh_duration[i]; + data->total_bytes_requested = bw_fixed_to_int(bw_add(bw_int_to_fixed(data->total_bytes_requested), (bw_mul(bw_mul(data->source_height_rounded_up_to_chunks[i], data->source_width_rounded_up_to_chunks[i]), bw_int_to_fixed(data->bytes_per_pixel[i]))))); + data->min_stutter_dmif_buffer_size = bw_fixed_to_int(data->stutter_dmif_buffer_size[i]); + } + data->total_stutter_dmif_buffer_size = bw_fixed_to_int(bw_add(data->stutter_dmif_buffer_size[i], bw_int_to_fixed(data->total_stutter_dmif_buffer_size))); + } + } + data->stutter_burst_time = bw_div(bw_int_to_fixed(data->total_stutter_dmif_buffer_size), bw_min2(bw_mul(data->dram_bandwidth, data->dmifdram_access_efficiency), bw_mul(sclk[data->sclk_level], bw_int_to_fixed(32)))); + data->num_stutter_bursts = data->total_bytes_requested / data->min_stutter_dmif_buffer_size; + data->total_stutter_cycle_duration = bw_add(bw_add(data->min_stutter_refresh_duration, vbios->stutter_self_refresh_exit_latency), data->stutter_burst_time); + data->time_in_self_refresh = data->min_stutter_refresh_duration; + if (data->d1_display_write_back_dwb_enable == 1) { + data->stutter_efficiency = bw_int_to_fixed(0); + } + else if (bw_ltn(data->time_in_self_refresh, bw_int_to_fixed(0))) { + data->stutter_efficiency = bw_int_to_fixed(0); + } + else { + /*compute stutter efficiency assuming 60 hz refresh rate*/ + data->stutter_efficiency = bw_max2(bw_int_to_fixed(0), bw_mul((bw_sub(bw_int_to_fixed(1), (bw_div(bw_mul((bw_add(vbios->stutter_self_refresh_exit_latency, data->stutter_burst_time)), bw_int_to_fixed(data->num_stutter_bursts)), bw_frc_to_fixed(166666667, 10000))))), bw_int_to_fixed(100))); + } + /*immediate flip time*/ + /*if scatter gather is enabled, the immediate flip takes a number of urgent memory trips equivalent to the pte requests in a row divided by the pte request limit.*/ + /*otherwise, it may take just one urgenr memory trip*/ + data->worst_number_of_trips_to_memory = bw_int_to_fixed(1); + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i] && data->scatter_gather_enable_for_pipe[i] == 1) { + data->number_of_trips_to_memory_for_getting_apte_row[i] = bw_ceil2(bw_div(data->scatter_gather_pte_requests_in_row[i], data->scatter_gather_pte_request_limit[i]), bw_int_to_fixed(1)); + if (bw_ltn(data->worst_number_of_trips_to_memory, data->number_of_trips_to_memory_for_getting_apte_row[i])) { + data->worst_number_of_trips_to_memory = data->number_of_trips_to_memory_for_getting_apte_row[i]; + } + } + } + data->immediate_flip_time = bw_mul(data->worst_number_of_trips_to_memory, data->total_dmifmc_urgent_latency); + /*worst latency for other clients*/ + /*it is the urgent latency plus the urgent burst time*/ + data->latency_for_non_dmif_clients = bw_add(data->total_dmifmc_urgent_latency, data->dmif_burst_time[data->y_clk_level][data->sclk_level]); + if (data->d1_display_write_back_dwb_enable == 1) { + data->latency_for_non_mcifwr_clients = bw_add(vbios->mcifwrmc_urgent_latency, dceip->mcifwr_all_surfaces_burst_time); + } + else { + data->latency_for_non_mcifwr_clients = bw_int_to_fixed(0); + } + /*dmif mc urgent latency suppported in high sclk and yclk*/ + data->dmifmc_urgent_latency_supported_in_high_sclk_and_yclk = bw_div((bw_sub(data->min_read_buffer_size_in_time, data->dmif_burst_time[high][s_high])), data->total_dmifmc_urgent_trips); + /*dram speed/p-state change margin*/ + /*in the multi-display case the nb p-state change watermark cannot exceed the average lb size plus the dmif size or the cursor dcp buffer size*/ + data->v_blank_nbp_state_dram_speed_change_latency_supported = bw_int_to_fixed(99999); + data->nbp_state_dram_speed_change_latency_supported = bw_int_to_fixed(99999); + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + data->nbp_state_dram_speed_change_latency_supported = bw_min2(data->nbp_state_dram_speed_change_latency_supported, bw_add(bw_sub(data->maximum_latency_hiding_with_cursor[i], data->nbp_state_change_watermark[i]), vbios->nbp_state_change_latency)); + data->v_blank_nbp_state_dram_speed_change_latency_supported = bw_min2(data->v_blank_nbp_state_dram_speed_change_latency_supported, bw_add(bw_sub(bw_div(bw_mul((bw_sub(data->v_total[i], bw_sub(bw_div(data->src_height[i], data->v_scale_ratio[i]), bw_int_to_fixed(4)))), data->h_total[i]), data->pixel_rate[i]), data->nbp_state_change_watermark[i]), vbios->nbp_state_change_latency)); + } + } + /*sclk required vs urgent latency*/ + for (i = 1; i <= 5; i++) { + data->display_reads_time_for_data_transfer_and_urgent_latency = bw_sub(data->min_read_buffer_size_in_time, bw_mul(data->total_dmifmc_urgent_trips, bw_int_to_fixed(i))); + if (pipe_check == bw_def_ok && (bw_mtn(data->display_reads_time_for_data_transfer_and_urgent_latency, data->dmif_total_page_close_open_time))) { + data->dmif_required_sclk_for_urgent_latency[i] = bw_div(bw_div(data->total_display_reads_required_data, data->display_reads_time_for_data_transfer_and_urgent_latency), (bw_mul(vbios->data_return_bus_width, bw_int_to_fixed(bus_efficiency)))); + } + else { + data->dmif_required_sclk_for_urgent_latency[i] = bw_int_to_fixed(bw_def_na); + } + } + /*output link bit per pixel supported*/ + for (k = 0; k <= maximum_number_of_surfaces - 1; k++) { + data->output_bpphdmi[k] = bw_def_na; + data->output_bppdp4_lane_hbr[k] = bw_def_na; + data->output_bppdp4_lane_hbr2[k] = bw_def_na; + data->output_bppdp4_lane_hbr3[k] = bw_def_na; + if (data->enable[k]) { + data->output_bpphdmi[k] = bw_fixed_to_int(bw_mul(bw_div(bw_min2(bw_int_to_fixed(600), data->max_phyclk), data->pixel_rate[k]), bw_int_to_fixed(24))); + if (bw_meq(data->max_phyclk, bw_int_to_fixed(270))) { + data->output_bppdp4_lane_hbr[k] = bw_fixed_to_int(bw_mul(bw_div(bw_mul(bw_int_to_fixed(270), bw_int_to_fixed(4)), data->pixel_rate[k]), bw_int_to_fixed(8))); + } + if (bw_meq(data->max_phyclk, bw_int_to_fixed(540))) { + data->output_bppdp4_lane_hbr2[k] = bw_fixed_to_int(bw_mul(bw_div(bw_mul(bw_int_to_fixed(540), bw_int_to_fixed(4)), data->pixel_rate[k]), bw_int_to_fixed(8))); + } + if (bw_meq(data->max_phyclk, bw_int_to_fixed(810))) { + data->output_bppdp4_lane_hbr3[k] = bw_fixed_to_int(bw_mul(bw_div(bw_mul(bw_int_to_fixed(810), bw_int_to_fixed(4)), data->pixel_rate[k]), bw_int_to_fixed(8))); + } + } + } +} + +/******************************************************************************* + * Public functions + ******************************************************************************/ +void bw_calcs_init(struct bw_calcs_dceip *bw_dceip, + struct bw_calcs_vbios *bw_vbios, + enum bw_calcs_version version) +{ + struct bw_calcs_dceip dceip = { 0 }; + struct bw_calcs_vbios vbios = { 0 }; + + dceip.version = version; + + switch (version) { + case BW_CALCS_VERSION_CARRIZO: + vbios.memory_type = bw_def_gddr5; + vbios.dram_channel_width_in_bits = 64; + vbios.number_of_dram_channels = 2; + vbios.number_of_dram_banks = 8; + vbios.high_yclk = bw_int_to_fixed(1600); + vbios.mid_yclk = bw_int_to_fixed(1600); + vbios.low_yclk = bw_frc_to_fixed(66666, 100); + vbios.low_sclk = bw_int_to_fixed(200); + vbios.mid1_sclk = bw_int_to_fixed(300); + vbios.mid2_sclk = bw_int_to_fixed(300); + vbios.mid3_sclk = bw_int_to_fixed(300); + vbios.mid4_sclk = bw_int_to_fixed(300); + vbios.mid5_sclk = bw_int_to_fixed(300); + vbios.mid6_sclk = bw_int_to_fixed(300); + vbios.high_sclk = bw_frc_to_fixed(62609, 100); + vbios.low_voltage_max_dispclk = bw_int_to_fixed(352); + vbios.mid_voltage_max_dispclk = bw_int_to_fixed(467); + vbios.high_voltage_max_dispclk = bw_int_to_fixed(643); + vbios.low_voltage_max_phyclk = bw_int_to_fixed(540); + vbios.mid_voltage_max_phyclk = bw_int_to_fixed(810); + vbios.high_voltage_max_phyclk = bw_int_to_fixed(810); + vbios.data_return_bus_width = bw_int_to_fixed(32); + vbios.trc = bw_int_to_fixed(50); + vbios.dmifmc_urgent_latency = bw_int_to_fixed(4); + vbios.stutter_self_refresh_exit_latency = bw_frc_to_fixed(153, 10); + vbios.stutter_self_refresh_entry_latency = bw_int_to_fixed(0); + vbios.nbp_state_change_latency = bw_frc_to_fixed(19649, 1000); + vbios.mcifwrmc_urgent_latency = bw_int_to_fixed(10); + vbios.scatter_gather_enable = true; + vbios.down_spread_percentage = bw_frc_to_fixed(5, 10); + vbios.cursor_width = 32; + vbios.average_compression_rate = 4; + vbios.number_of_request_slots_gmc_reserves_for_dmif_per_channel = 256; + vbios.blackout_duration = bw_int_to_fixed(18); /* us */ + vbios.maximum_blackout_recovery_time = bw_int_to_fixed(20); + + dceip.large_cursor = false; + dceip.dmif_request_buffer_size = bw_int_to_fixed(768); + dceip.dmif_pipe_en_fbc_chunk_tracker = false; + dceip.cursor_max_outstanding_group_num = 1; + dceip.lines_interleaved_into_lb = 2; + dceip.chunk_width = 256; + dceip.number_of_graphics_pipes = 3; + dceip.number_of_underlay_pipes = 1; + dceip.low_power_tiling_mode = 0; + dceip.display_write_back_supported = false; + dceip.argb_compression_support = false; + dceip.underlay_vscaler_efficiency6_bit_per_component = + bw_frc_to_fixed(35556, 10000); + dceip.underlay_vscaler_efficiency8_bit_per_component = + bw_frc_to_fixed(34286, 10000); + dceip.underlay_vscaler_efficiency10_bit_per_component = + bw_frc_to_fixed(32, 10); + dceip.underlay_vscaler_efficiency12_bit_per_component = + bw_int_to_fixed(3); + dceip.graphics_vscaler_efficiency6_bit_per_component = + bw_frc_to_fixed(35, 10); + dceip.graphics_vscaler_efficiency8_bit_per_component = + bw_frc_to_fixed(34286, 10000); + dceip.graphics_vscaler_efficiency10_bit_per_component = + bw_frc_to_fixed(32, 10); + dceip.graphics_vscaler_efficiency12_bit_per_component = + bw_int_to_fixed(3); + dceip.alpha_vscaler_efficiency = bw_int_to_fixed(3); + dceip.max_dmif_buffer_allocated = 2; + dceip.graphics_dmif_size = 12288; + dceip.underlay_luma_dmif_size = 19456; + dceip.underlay_chroma_dmif_size = 23552; + dceip.pre_downscaler_enabled = true; + dceip.underlay_downscale_prefetch_enabled = true; + dceip.lb_write_pixels_per_dispclk = bw_int_to_fixed(1); + dceip.lb_size_per_component444 = bw_int_to_fixed(82176); + dceip.graphics_lb_nodownscaling_multi_line_prefetching = false; + dceip.stutter_and_dram_clock_state_change_gated_before_cursor = + bw_int_to_fixed(0); + dceip.underlay420_luma_lb_size_per_component = bw_int_to_fixed( + 82176); + dceip.underlay420_chroma_lb_size_per_component = + bw_int_to_fixed(164352); + dceip.underlay422_lb_size_per_component = bw_int_to_fixed( + 82176); + dceip.cursor_chunk_width = bw_int_to_fixed(64); + dceip.cursor_dcp_buffer_lines = bw_int_to_fixed(4); + dceip.underlay_maximum_width_efficient_for_tiling = + bw_int_to_fixed(1920); + dceip.underlay_maximum_height_efficient_for_tiling = + bw_int_to_fixed(1080); + dceip.peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display = + bw_frc_to_fixed(3, 10); + dceip.peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation = + bw_int_to_fixed(25); + dceip.minimum_outstanding_pte_request_limit = bw_int_to_fixed( + 2); + dceip.maximum_total_outstanding_pte_requests_allowed_by_saw = + bw_int_to_fixed(128); + dceip.limit_excessive_outstanding_dmif_requests = true; + dceip.linear_mode_line_request_alternation_slice = + bw_int_to_fixed(64); + dceip.scatter_gather_lines_of_pte_prefetching_in_linear_mode = + 32; + dceip.display_write_back420_luma_mcifwr_buffer_size = 12288; + dceip.display_write_back420_chroma_mcifwr_buffer_size = 8192; + dceip.request_efficiency = bw_frc_to_fixed(8, 10); + dceip.dispclk_per_request = bw_int_to_fixed(2); + dceip.dispclk_ramping_factor = bw_frc_to_fixed(105, 100); + dceip.display_pipe_throughput_factor = bw_frc_to_fixed(105, 100); + dceip.scatter_gather_pte_request_rows_in_tiling_mode = 2; + dceip.mcifwr_all_surfaces_burst_time = bw_int_to_fixed(0); /* todo: this is a bug*/ + break; + case BW_CALCS_VERSION_POLARIS10: + vbios.memory_type = bw_def_gddr5; + vbios.dram_channel_width_in_bits = 32; + vbios.number_of_dram_channels = 8; + vbios.number_of_dram_banks = 8; + vbios.high_yclk = bw_int_to_fixed(6000); + vbios.mid_yclk = bw_int_to_fixed(3200); + vbios.low_yclk = bw_int_to_fixed(1000); + vbios.low_sclk = bw_int_to_fixed(300); + vbios.mid1_sclk = bw_int_to_fixed(400); + vbios.mid2_sclk = bw_int_to_fixed(500); + vbios.mid3_sclk = bw_int_to_fixed(600); + vbios.mid4_sclk = bw_int_to_fixed(700); + vbios.mid5_sclk = bw_int_to_fixed(800); + vbios.mid6_sclk = bw_int_to_fixed(974); + vbios.high_sclk = bw_int_to_fixed(1154); + vbios.low_voltage_max_dispclk = bw_int_to_fixed(459); + vbios.mid_voltage_max_dispclk = bw_int_to_fixed(654); + vbios.high_voltage_max_dispclk = bw_int_to_fixed(1108); + vbios.low_voltage_max_phyclk = bw_int_to_fixed(540); + vbios.mid_voltage_max_phyclk = bw_int_to_fixed(810); + vbios.high_voltage_max_phyclk = bw_int_to_fixed(810); + vbios.data_return_bus_width = bw_int_to_fixed(32); + vbios.trc = bw_int_to_fixed(48); + vbios.dmifmc_urgent_latency = bw_int_to_fixed(3); + vbios.stutter_self_refresh_exit_latency = bw_int_to_fixed(5); + vbios.stutter_self_refresh_entry_latency = bw_int_to_fixed(0); + vbios.nbp_state_change_latency = bw_int_to_fixed(45); + vbios.mcifwrmc_urgent_latency = bw_int_to_fixed(10); + vbios.scatter_gather_enable = true; + vbios.down_spread_percentage = bw_frc_to_fixed(5, 10); + vbios.cursor_width = 32; + vbios.average_compression_rate = 4; + vbios.number_of_request_slots_gmc_reserves_for_dmif_per_channel = 256; + vbios.blackout_duration = bw_int_to_fixed(0); /* us */ + vbios.maximum_blackout_recovery_time = bw_int_to_fixed(0); + + dceip.large_cursor = false; + dceip.dmif_request_buffer_size = bw_int_to_fixed(768); + dceip.dmif_pipe_en_fbc_chunk_tracker = false; + dceip.cursor_max_outstanding_group_num = 1; + dceip.lines_interleaved_into_lb = 2; + dceip.chunk_width = 256; + dceip.number_of_graphics_pipes = 6; + dceip.number_of_underlay_pipes = 0; + dceip.low_power_tiling_mode = 0; + dceip.display_write_back_supported = false; + dceip.argb_compression_support = true; + dceip.underlay_vscaler_efficiency6_bit_per_component = + bw_frc_to_fixed(35556, 10000); + dceip.underlay_vscaler_efficiency8_bit_per_component = + bw_frc_to_fixed(34286, 10000); + dceip.underlay_vscaler_efficiency10_bit_per_component = + bw_frc_to_fixed(32, 10); + dceip.underlay_vscaler_efficiency12_bit_per_component = + bw_int_to_fixed(3); + dceip.graphics_vscaler_efficiency6_bit_per_component = + bw_frc_to_fixed(35, 10); + dceip.graphics_vscaler_efficiency8_bit_per_component = + bw_frc_to_fixed(34286, 10000); + dceip.graphics_vscaler_efficiency10_bit_per_component = + bw_frc_to_fixed(32, 10); + dceip.graphics_vscaler_efficiency12_bit_per_component = + bw_int_to_fixed(3); + dceip.alpha_vscaler_efficiency = bw_int_to_fixed(3); + dceip.max_dmif_buffer_allocated = 4; + dceip.graphics_dmif_size = 12288; + dceip.underlay_luma_dmif_size = 19456; + dceip.underlay_chroma_dmif_size = 23552; + dceip.pre_downscaler_enabled = true; + dceip.underlay_downscale_prefetch_enabled = true; + dceip.lb_write_pixels_per_dispclk = bw_int_to_fixed(1); + dceip.lb_size_per_component444 = bw_int_to_fixed(245952); + dceip.graphics_lb_nodownscaling_multi_line_prefetching = true; + dceip.stutter_and_dram_clock_state_change_gated_before_cursor = + bw_int_to_fixed(1); + dceip.underlay420_luma_lb_size_per_component = bw_int_to_fixed( + 82176); + dceip.underlay420_chroma_lb_size_per_component = + bw_int_to_fixed(164352); + dceip.underlay422_lb_size_per_component = bw_int_to_fixed( + 82176); + dceip.cursor_chunk_width = bw_int_to_fixed(64); + dceip.cursor_dcp_buffer_lines = bw_int_to_fixed(4); + dceip.underlay_maximum_width_efficient_for_tiling = + bw_int_to_fixed(1920); + dceip.underlay_maximum_height_efficient_for_tiling = + bw_int_to_fixed(1080); + dceip.peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display = + bw_frc_to_fixed(3, 10); + dceip.peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation = + bw_int_to_fixed(25); + dceip.minimum_outstanding_pte_request_limit = bw_int_to_fixed( + 2); + dceip.maximum_total_outstanding_pte_requests_allowed_by_saw = + bw_int_to_fixed(128); + dceip.limit_excessive_outstanding_dmif_requests = true; + dceip.linear_mode_line_request_alternation_slice = + bw_int_to_fixed(64); + dceip.scatter_gather_lines_of_pte_prefetching_in_linear_mode = + 32; + dceip.display_write_back420_luma_mcifwr_buffer_size = 12288; + dceip.display_write_back420_chroma_mcifwr_buffer_size = 8192; + dceip.request_efficiency = bw_frc_to_fixed(8, 10); + dceip.dispclk_per_request = bw_int_to_fixed(2); + dceip.dispclk_ramping_factor = bw_frc_to_fixed(105, 100); + dceip.display_pipe_throughput_factor = bw_frc_to_fixed(105, 100); + dceip.scatter_gather_pte_request_rows_in_tiling_mode = 2; + dceip.mcifwr_all_surfaces_burst_time = bw_int_to_fixed(0); + break; + case BW_CALCS_VERSION_POLARIS11: + vbios.memory_type = bw_def_gddr5; + vbios.dram_channel_width_in_bits = 32; + vbios.number_of_dram_channels = 4; + vbios.number_of_dram_banks = 8; + vbios.high_yclk = bw_int_to_fixed(6000); + vbios.mid_yclk = bw_int_to_fixed(3200); + vbios.low_yclk = bw_int_to_fixed(1000); + vbios.low_sclk = bw_int_to_fixed(300); + vbios.mid1_sclk = bw_int_to_fixed(400); + vbios.mid2_sclk = bw_int_to_fixed(500); + vbios.mid3_sclk = bw_int_to_fixed(600); + vbios.mid4_sclk = bw_int_to_fixed(700); + vbios.mid5_sclk = bw_int_to_fixed(800); + vbios.mid6_sclk = bw_int_to_fixed(974); + vbios.high_sclk = bw_int_to_fixed(1154); + vbios.low_voltage_max_dispclk = bw_int_to_fixed(459); + vbios.mid_voltage_max_dispclk = bw_int_to_fixed(654); + vbios.high_voltage_max_dispclk = bw_int_to_fixed(1108); + vbios.low_voltage_max_phyclk = bw_int_to_fixed(540); + vbios.mid_voltage_max_phyclk = bw_int_to_fixed(810); + vbios.high_voltage_max_phyclk = bw_int_to_fixed(810); + vbios.data_return_bus_width = bw_int_to_fixed(32); + vbios.trc = bw_int_to_fixed(48); + vbios.dmifmc_urgent_latency = bw_int_to_fixed(3); + vbios.stutter_self_refresh_exit_latency = bw_int_to_fixed(5); + vbios.stutter_self_refresh_entry_latency = bw_int_to_fixed(0); + vbios.nbp_state_change_latency = bw_int_to_fixed(45); + vbios.mcifwrmc_urgent_latency = bw_int_to_fixed(10); + vbios.scatter_gather_enable = true; + vbios.down_spread_percentage = bw_frc_to_fixed(5, 10); + vbios.cursor_width = 32; + vbios.average_compression_rate = 4; + vbios.number_of_request_slots_gmc_reserves_for_dmif_per_channel = 256; + vbios.blackout_duration = bw_int_to_fixed(0); /* us */ + vbios.maximum_blackout_recovery_time = bw_int_to_fixed(0); + + dceip.large_cursor = false; + dceip.dmif_request_buffer_size = bw_int_to_fixed(768); + dceip.dmif_pipe_en_fbc_chunk_tracker = false; + dceip.cursor_max_outstanding_group_num = 1; + dceip.lines_interleaved_into_lb = 2; + dceip.chunk_width = 256; + dceip.number_of_graphics_pipes = 5; + dceip.number_of_underlay_pipes = 0; + dceip.low_power_tiling_mode = 0; + dceip.display_write_back_supported = false; + dceip.argb_compression_support = true; + dceip.underlay_vscaler_efficiency6_bit_per_component = + bw_frc_to_fixed(35556, 10000); + dceip.underlay_vscaler_efficiency8_bit_per_component = + bw_frc_to_fixed(34286, 10000); + dceip.underlay_vscaler_efficiency10_bit_per_component = + bw_frc_to_fixed(32, 10); + dceip.underlay_vscaler_efficiency12_bit_per_component = + bw_int_to_fixed(3); + dceip.graphics_vscaler_efficiency6_bit_per_component = + bw_frc_to_fixed(35, 10); + dceip.graphics_vscaler_efficiency8_bit_per_component = + bw_frc_to_fixed(34286, 10000); + dceip.graphics_vscaler_efficiency10_bit_per_component = + bw_frc_to_fixed(32, 10); + dceip.graphics_vscaler_efficiency12_bit_per_component = + bw_int_to_fixed(3); + dceip.alpha_vscaler_efficiency = bw_int_to_fixed(3); + dceip.max_dmif_buffer_allocated = 4; + dceip.graphics_dmif_size = 12288; + dceip.underlay_luma_dmif_size = 19456; + dceip.underlay_chroma_dmif_size = 23552; + dceip.pre_downscaler_enabled = true; + dceip.underlay_downscale_prefetch_enabled = true; + dceip.lb_write_pixels_per_dispclk = bw_int_to_fixed(1); + dceip.lb_size_per_component444 = bw_int_to_fixed(245952); + dceip.graphics_lb_nodownscaling_multi_line_prefetching = true; + dceip.stutter_and_dram_clock_state_change_gated_before_cursor = + bw_int_to_fixed(1); + dceip.underlay420_luma_lb_size_per_component = bw_int_to_fixed( + 82176); + dceip.underlay420_chroma_lb_size_per_component = + bw_int_to_fixed(164352); + dceip.underlay422_lb_size_per_component = bw_int_to_fixed( + 82176); + dceip.cursor_chunk_width = bw_int_to_fixed(64); + dceip.cursor_dcp_buffer_lines = bw_int_to_fixed(4); + dceip.underlay_maximum_width_efficient_for_tiling = + bw_int_to_fixed(1920); + dceip.underlay_maximum_height_efficient_for_tiling = + bw_int_to_fixed(1080); + dceip.peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display = + bw_frc_to_fixed(3, 10); + dceip.peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation = + bw_int_to_fixed(25); + dceip.minimum_outstanding_pte_request_limit = bw_int_to_fixed( + 2); + dceip.maximum_total_outstanding_pte_requests_allowed_by_saw = + bw_int_to_fixed(128); + dceip.limit_excessive_outstanding_dmif_requests = true; + dceip.linear_mode_line_request_alternation_slice = + bw_int_to_fixed(64); + dceip.scatter_gather_lines_of_pte_prefetching_in_linear_mode = + 32; + dceip.display_write_back420_luma_mcifwr_buffer_size = 12288; + dceip.display_write_back420_chroma_mcifwr_buffer_size = 8192; + dceip.request_efficiency = bw_frc_to_fixed(8, 10); + dceip.dispclk_per_request = bw_int_to_fixed(2); + dceip.dispclk_ramping_factor = bw_frc_to_fixed(105, 100); + dceip.display_pipe_throughput_factor = bw_frc_to_fixed(105, 100); + dceip.scatter_gather_pte_request_rows_in_tiling_mode = 2; + dceip.mcifwr_all_surfaces_burst_time = bw_int_to_fixed(0); + break; + case BW_CALCS_VERSION_STONEY: + vbios.memory_type = bw_def_gddr5; + vbios.dram_channel_width_in_bits = 64; + vbios.number_of_dram_channels = 1; + vbios.number_of_dram_banks = 8; + vbios.high_yclk = bw_int_to_fixed(1866); + vbios.mid_yclk = bw_int_to_fixed(1866); + vbios.low_yclk = bw_int_to_fixed(1333); + vbios.low_sclk = bw_int_to_fixed(200); + vbios.mid1_sclk = bw_int_to_fixed(600); + vbios.mid2_sclk = bw_int_to_fixed(600); + vbios.mid3_sclk = bw_int_to_fixed(600); + vbios.mid4_sclk = bw_int_to_fixed(600); + vbios.mid5_sclk = bw_int_to_fixed(600); + vbios.mid6_sclk = bw_int_to_fixed(600); + vbios.high_sclk = bw_int_to_fixed(800); + vbios.low_voltage_max_dispclk = bw_int_to_fixed(352); + vbios.mid_voltage_max_dispclk = bw_int_to_fixed(467); + vbios.high_voltage_max_dispclk = bw_int_to_fixed(643); + vbios.low_voltage_max_phyclk = bw_int_to_fixed(540); + vbios.mid_voltage_max_phyclk = bw_int_to_fixed(810); + vbios.high_voltage_max_phyclk = bw_int_to_fixed(810); + vbios.data_return_bus_width = bw_int_to_fixed(32); + vbios.trc = bw_int_to_fixed(50); + vbios.dmifmc_urgent_latency = bw_int_to_fixed(4); + vbios.stutter_self_refresh_exit_latency = bw_frc_to_fixed(158, 10); + vbios.stutter_self_refresh_entry_latency = bw_int_to_fixed(0); + vbios.nbp_state_change_latency = bw_frc_to_fixed(2008, 100); + vbios.mcifwrmc_urgent_latency = bw_int_to_fixed(10); + vbios.scatter_gather_enable = true; + vbios.down_spread_percentage = bw_frc_to_fixed(5, 10); + vbios.cursor_width = 32; + vbios.average_compression_rate = 4; + vbios.number_of_request_slots_gmc_reserves_for_dmif_per_channel = 256; + vbios.blackout_duration = bw_int_to_fixed(18); /* us */ + vbios.maximum_blackout_recovery_time = bw_int_to_fixed(20); + + dceip.large_cursor = false; + dceip.dmif_request_buffer_size = bw_int_to_fixed(768); + dceip.dmif_pipe_en_fbc_chunk_tracker = false; + dceip.cursor_max_outstanding_group_num = 1; + dceip.lines_interleaved_into_lb = 2; + dceip.chunk_width = 256; + dceip.number_of_graphics_pipes = 2; + dceip.number_of_underlay_pipes = 1; + dceip.low_power_tiling_mode = 0; + dceip.display_write_back_supported = false; + dceip.argb_compression_support = true; + dceip.underlay_vscaler_efficiency6_bit_per_component = + bw_frc_to_fixed(35556, 10000); + dceip.underlay_vscaler_efficiency8_bit_per_component = + bw_frc_to_fixed(34286, 10000); + dceip.underlay_vscaler_efficiency10_bit_per_component = + bw_frc_to_fixed(32, 10); + dceip.underlay_vscaler_efficiency12_bit_per_component = + bw_int_to_fixed(3); + dceip.graphics_vscaler_efficiency6_bit_per_component = + bw_frc_to_fixed(35, 10); + dceip.graphics_vscaler_efficiency8_bit_per_component = + bw_frc_to_fixed(34286, 10000); + dceip.graphics_vscaler_efficiency10_bit_per_component = + bw_frc_to_fixed(32, 10); + dceip.graphics_vscaler_efficiency12_bit_per_component = + bw_int_to_fixed(3); + dceip.alpha_vscaler_efficiency = bw_int_to_fixed(3); + dceip.max_dmif_buffer_allocated = 2; + dceip.graphics_dmif_size = 12288; + dceip.underlay_luma_dmif_size = 19456; + dceip.underlay_chroma_dmif_size = 23552; + dceip.pre_downscaler_enabled = true; + dceip.underlay_downscale_prefetch_enabled = true; + dceip.lb_write_pixels_per_dispclk = bw_int_to_fixed(1); + dceip.lb_size_per_component444 = bw_int_to_fixed(82176); + dceip.graphics_lb_nodownscaling_multi_line_prefetching = false; + dceip.stutter_and_dram_clock_state_change_gated_before_cursor = + bw_int_to_fixed(0); + dceip.underlay420_luma_lb_size_per_component = bw_int_to_fixed( + 82176); + dceip.underlay420_chroma_lb_size_per_component = + bw_int_to_fixed(164352); + dceip.underlay422_lb_size_per_component = bw_int_to_fixed( + 82176); + dceip.cursor_chunk_width = bw_int_to_fixed(64); + dceip.cursor_dcp_buffer_lines = bw_int_to_fixed(4); + dceip.underlay_maximum_width_efficient_for_tiling = + bw_int_to_fixed(1920); + dceip.underlay_maximum_height_efficient_for_tiling = + bw_int_to_fixed(1080); + dceip.peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display = + bw_frc_to_fixed(3, 10); + dceip.peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation = + bw_int_to_fixed(25); + dceip.minimum_outstanding_pte_request_limit = bw_int_to_fixed( + 2); + dceip.maximum_total_outstanding_pte_requests_allowed_by_saw = + bw_int_to_fixed(128); + dceip.limit_excessive_outstanding_dmif_requests = true; + dceip.linear_mode_line_request_alternation_slice = + bw_int_to_fixed(64); + dceip.scatter_gather_lines_of_pte_prefetching_in_linear_mode = + 32; + dceip.display_write_back420_luma_mcifwr_buffer_size = 12288; + dceip.display_write_back420_chroma_mcifwr_buffer_size = 8192; + dceip.request_efficiency = bw_frc_to_fixed(8, 10); + dceip.dispclk_per_request = bw_int_to_fixed(2); + dceip.dispclk_ramping_factor = bw_frc_to_fixed(105, 100); + dceip.display_pipe_throughput_factor = bw_frc_to_fixed(105, 100); + dceip.scatter_gather_pte_request_rows_in_tiling_mode = 2; + dceip.mcifwr_all_surfaces_burst_time = bw_int_to_fixed(0); + break; + default: + break; + } + *bw_dceip = dceip; + *bw_vbios = vbios; + +} + +/** + * Compare calculated (required) clocks against the clocks available at + * maximum voltage (max Performance Level). + */ +static bool is_display_configuration_supported( + const struct bw_calcs_vbios *vbios, + const struct bw_calcs_output *calcs_output) +{ + uint32_t int_max_clk; + + int_max_clk = bw_fixed_to_int(vbios->high_voltage_max_dispclk); + int_max_clk *= 1000; /* MHz to kHz */ + if (calcs_output->dispclk_khz > int_max_clk) + return false; + + int_max_clk = bw_fixed_to_int(vbios->high_sclk); + int_max_clk *= 1000; /* MHz to kHz */ + if (calcs_output->required_sclk > int_max_clk) + return false; + + return true; +} + +static void populate_initial_data( + const struct pipe_ctx pipe[], int pipe_count, struct bw_calcs_data *data) +{ + int i, j; + int num_displays = 0; + + data->underlay_surface_type = bw_def_420; + data->panning_and_bezel_adjustment = bw_def_none; + data->graphics_lb_bpc = 10; + data->underlay_lb_bpc = 8; + data->underlay_tiling_mode = bw_def_tiled; + data->graphics_tiling_mode = bw_def_tiled; + data->underlay_micro_tile_mode = bw_def_display_micro_tiling; + data->graphics_micro_tile_mode = bw_def_display_micro_tiling; + + /* Pipes with underlay first */ + for (i = 0; i < pipe_count; i++) { + if (!pipe[i].stream || !pipe[i].bottom_pipe) + continue; + + ASSERT(pipe[i].surface); + + if (num_displays == 0) { + if (!pipe[i].surface->public.visible) + data->d0_underlay_mode = bw_def_underlay_only; + else + data->d0_underlay_mode = bw_def_blend; + } else { + if (!pipe[i].surface->public.visible) + data->d1_underlay_mode = bw_def_underlay_only; + else + data->d1_underlay_mode = bw_def_blend; + } + + data->fbc_en[num_displays + 4] = false; + data->lpt_en[num_displays + 4] = false; + data->h_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->public.timing.h_total); + data->v_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->public.timing.v_total); + data->pixel_rate[num_displays + 4] = bw_frc_to_fixed(pipe[i].stream->public.timing.pix_clk_khz, 1000); + data->src_width[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.viewport.width); + data->pitch_in_pixels[num_displays + 4] = bw_int_to_fixed(pipe[i].surface->public.plane_size.grph.surface_pitch); + data->src_height[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.viewport.height); + data->h_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.taps.h_taps); + data->v_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.taps.v_taps); + data->h_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].scl_data.ratios.horz.value); + data->v_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].scl_data.ratios.vert.value); + switch (pipe[i].surface->public.rotation) { + case ROTATION_ANGLE_0: + data->rotation_angle[num_displays + 4] = bw_int_to_fixed(0); + break; + case ROTATION_ANGLE_90: + data->rotation_angle[num_displays + 4] = bw_int_to_fixed(90); + break; + case ROTATION_ANGLE_180: + data->rotation_angle[num_displays + 4] = bw_int_to_fixed(180); + break; + case ROTATION_ANGLE_270: + data->rotation_angle[num_displays + 4] = bw_int_to_fixed(270); + break; + default: + break; + } + switch (pipe[i].surface->public.format) { + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: + case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: + case SURFACE_PIXEL_FORMAT_GRPH_RGB565: + data->bytes_per_pixel[num_displays + 4] = 2; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: + case SURFACE_PIXEL_FORMAT_GRPH_BGRA8888: + case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: + data->bytes_per_pixel[num_displays + 4] = 4; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: + data->bytes_per_pixel[num_displays + 4] = 8; + break; + default: + data->bytes_per_pixel[num_displays + 4] = 4; + break; + } + data->interlace_mode[num_displays + 4] = false; + data->stereo_mode[num_displays + 4] = bw_def_mono; + + + for (j = 0; j < 2; j++) { + data->fbc_en[num_displays * 2 + j] = false; + data->lpt_en[num_displays * 2 + j] = false; + + data->src_height[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->scl_data.viewport.height); + data->src_width[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->scl_data.viewport.width); + data->pitch_in_pixels[num_displays * 2 + j] = bw_int_to_fixed( + pipe[i].bottom_pipe->surface->public.plane_size.grph.surface_pitch); + data->h_taps[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->scl_data.taps.h_taps); + data->v_taps[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->scl_data.taps.v_taps); + data->h_scale_ratio[num_displays * 2 + j] = fixed31_32_to_bw_fixed( + pipe[i].bottom_pipe->scl_data.ratios.horz.value); + data->v_scale_ratio[num_displays * 2 + j] = fixed31_32_to_bw_fixed( + pipe[i].bottom_pipe->scl_data.ratios.vert.value); + switch (pipe[i].bottom_pipe->surface->public.rotation) { + case ROTATION_ANGLE_0: + data->rotation_angle[num_displays * 2 + j] = bw_int_to_fixed(0); + break; + case ROTATION_ANGLE_90: + data->rotation_angle[num_displays * 2 + j] = bw_int_to_fixed(90); + break; + case ROTATION_ANGLE_180: + data->rotation_angle[num_displays * 2 + j] = bw_int_to_fixed(180); + break; + case ROTATION_ANGLE_270: + data->rotation_angle[num_displays * 2 + j] = bw_int_to_fixed(270); + break; + default: + break; + } + data->stereo_mode[num_displays * 2 + j] = bw_def_mono; + } + + num_displays++; + } + + /* Pipes without underlay after */ + for (i = 0; i < pipe_count; i++) { + if (!pipe[i].stream || pipe[i].bottom_pipe) + continue; + + + data->fbc_en[num_displays + 4] = false; + data->lpt_en[num_displays + 4] = false; + data->h_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->public.timing.h_total); + data->v_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->public.timing.v_total); + data->pixel_rate[num_displays + 4] = bw_frc_to_fixed(pipe[i].stream->public.timing.pix_clk_khz, 1000); + if (pipe[i].surface) { + data->src_width[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.viewport.width); + data->pitch_in_pixels[num_displays + 4] = bw_int_to_fixed(pipe[i].surface->public.plane_size.grph.surface_pitch); + data->src_height[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.viewport.height); + data->h_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.taps.h_taps); + data->v_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.taps.v_taps); + data->h_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].scl_data.ratios.horz.value); + data->v_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].scl_data.ratios.vert.value); + switch (pipe[i].surface->public.rotation) { + case ROTATION_ANGLE_0: + data->rotation_angle[num_displays + 4] = bw_int_to_fixed(0); + break; + case ROTATION_ANGLE_90: + data->rotation_angle[num_displays + 4] = bw_int_to_fixed(90); + break; + case ROTATION_ANGLE_180: + data->rotation_angle[num_displays + 4] = bw_int_to_fixed(180); + break; + case ROTATION_ANGLE_270: + data->rotation_angle[num_displays + 4] = bw_int_to_fixed(270); + break; + default: + break; + } + switch (pipe[i].surface->public.format) { + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: + case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: + case SURFACE_PIXEL_FORMAT_GRPH_RGB565: + data->bytes_per_pixel[num_displays + 4] = 2; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: + case SURFACE_PIXEL_FORMAT_GRPH_BGRA8888: + case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: + data->bytes_per_pixel[num_displays + 4] = 4; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: + data->bytes_per_pixel[num_displays + 4] = 8; + break; + default: + data->bytes_per_pixel[num_displays + 4] = 4; + break; + } + } else { + data->src_width[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->public.timing.h_addressable); + data->pitch_in_pixels[num_displays + 4] = data->src_width[num_displays + 4]; + data->src_height[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->public.timing.v_addressable); + data->h_taps[num_displays + 4] = bw_int_to_fixed(1); + data->v_taps[num_displays + 4] = bw_int_to_fixed(1); + data->h_scale_ratio[num_displays + 4] = bw_int_to_fixed(1); + data->v_scale_ratio[num_displays + 4] = bw_int_to_fixed(1); + data->rotation_angle[num_displays + 4] = bw_int_to_fixed(0); + data->bytes_per_pixel[num_displays + 4] = 4; + } + + data->interlace_mode[num_displays + 4] = false; + data->stereo_mode[num_displays + 4] = bw_def_mono; + num_displays++; + } + + data->number_of_displays = num_displays; +} + +/** + * Return: + * true - Display(s) configuration supported. + * In this case 'calcs_output' contains data for HW programming + * false - Display(s) configuration not supported (not enough bandwidth). + */ + +bool bw_calcs(struct dc_context *ctx, + const struct bw_calcs_dceip *dceip, + const struct bw_calcs_vbios *vbios, + const struct pipe_ctx pipe[], + int pipe_count, + struct bw_calcs_output *calcs_output) +{ + struct bw_calcs_data *data = dm_alloc(sizeof(struct bw_calcs_data)); + + populate_initial_data(pipe, pipe_count, data); + + /*TODO: this should be taken out calcs output and assigned during timing sync for pplib use*/ + calcs_output->all_displays_in_sync = false; + + if (data->number_of_displays != 0) { + uint8_t yclk_lvl, sclk_lvl; + struct bw_fixed high_sclk = vbios->high_sclk; + struct bw_fixed mid1_sclk = vbios->mid1_sclk; + struct bw_fixed mid2_sclk = vbios->mid2_sclk; + struct bw_fixed mid3_sclk = vbios->mid3_sclk; + struct bw_fixed mid4_sclk = vbios->mid4_sclk; + struct bw_fixed mid5_sclk = vbios->mid5_sclk; + struct bw_fixed mid6_sclk = vbios->mid6_sclk; + struct bw_fixed low_sclk = vbios->low_sclk; + struct bw_fixed high_yclk = vbios->high_yclk; + struct bw_fixed mid_yclk = vbios->mid_yclk; + struct bw_fixed low_yclk = vbios->low_yclk; + + calculate_bandwidth(dceip, vbios, data); + + yclk_lvl = data->y_clk_level; + sclk_lvl = data->sclk_level; + + calcs_output->nbp_state_change_enable = + data->nbp_state_change_enable; + calcs_output->cpuc_state_change_enable = + data->cpuc_state_change_enable; + calcs_output->cpup_state_change_enable = + data->cpup_state_change_enable; + calcs_output->stutter_mode_enable = + data->stutter_mode_enable; + calcs_output->dispclk_khz = + bw_fixed_to_int(bw_mul(data->dispclk, + bw_int_to_fixed(1000))); + calcs_output->blackout_recovery_time_us = + bw_fixed_to_int(data->blackout_recovery_time); + calcs_output->required_sclk = + bw_fixed_to_int(bw_mul(data->required_sclk, + bw_int_to_fixed(1000))); + calcs_output->required_sclk_deep_sleep = + bw_fixed_to_int(bw_mul(data->sclk_deep_sleep, + bw_int_to_fixed(1000))); + if (yclk_lvl == 0) + calcs_output->required_yclk = bw_fixed_to_int( + bw_mul(low_yclk, bw_int_to_fixed(1000))); + else if (yclk_lvl == 1) + calcs_output->required_yclk = bw_fixed_to_int( + bw_mul(mid_yclk, bw_int_to_fixed(1000))); + else + calcs_output->required_yclk = bw_fixed_to_int( + bw_mul(high_yclk, bw_int_to_fixed(1000))); + + /* units: nanosecond, 16bit storage. */ + + calcs_output->nbp_state_change_wm_ns[0].a_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[4], bw_int_to_fixed(1000))); + calcs_output->nbp_state_change_wm_ns[1].a_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[5], bw_int_to_fixed(1000))); + calcs_output->nbp_state_change_wm_ns[2].a_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[6], bw_int_to_fixed(1000))); + + if (ctx->dc->caps.max_slave_planes) { + calcs_output->nbp_state_change_wm_ns[3].a_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[0], bw_int_to_fixed(1000))); + calcs_output->nbp_state_change_wm_ns[4].a_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[1], bw_int_to_fixed(1000))); + } else { + calcs_output->nbp_state_change_wm_ns[3].a_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[7], bw_int_to_fixed(1000))); + calcs_output->nbp_state_change_wm_ns[4].a_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[8], bw_int_to_fixed(1000))); + } + calcs_output->nbp_state_change_wm_ns[5].a_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[9], bw_int_to_fixed(1000))); + + + + calcs_output->stutter_exit_wm_ns[0].a_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[4], bw_int_to_fixed(1000))); + calcs_output->stutter_exit_wm_ns[1].a_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[5], bw_int_to_fixed(1000))); + calcs_output->stutter_exit_wm_ns[2].a_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[6], bw_int_to_fixed(1000))); + if (ctx->dc->caps.max_slave_planes) { + calcs_output->stutter_exit_wm_ns[3].a_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[0], bw_int_to_fixed(1000))); + calcs_output->stutter_exit_wm_ns[4].a_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[1], bw_int_to_fixed(1000))); + } else { + calcs_output->stutter_exit_wm_ns[3].a_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[7], bw_int_to_fixed(1000))); + calcs_output->stutter_exit_wm_ns[4].a_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[8], bw_int_to_fixed(1000))); + } + calcs_output->stutter_exit_wm_ns[5].a_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[9], bw_int_to_fixed(1000))); + + + + calcs_output->urgent_wm_ns[0].a_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[4], bw_int_to_fixed(1000))); + calcs_output->urgent_wm_ns[1].a_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[5], bw_int_to_fixed(1000))); + calcs_output->urgent_wm_ns[2].a_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[6], bw_int_to_fixed(1000))); + if (ctx->dc->caps.max_slave_planes) { + calcs_output->urgent_wm_ns[3].a_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[0], bw_int_to_fixed(1000))); + calcs_output->urgent_wm_ns[4].a_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[1], bw_int_to_fixed(1000))); + } else { + calcs_output->urgent_wm_ns[3].a_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[7], bw_int_to_fixed(1000))); + calcs_output->urgent_wm_ns[4].a_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[8], bw_int_to_fixed(1000))); + } + calcs_output->urgent_wm_ns[5].a_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[9], bw_int_to_fixed(1000))); + + if (dceip->version != BW_CALCS_VERSION_CARRIZO) { + ((struct bw_calcs_vbios *)vbios)->low_sclk = mid3_sclk; + ((struct bw_calcs_vbios *)vbios)->mid1_sclk = mid3_sclk; + ((struct bw_calcs_vbios *)vbios)->mid2_sclk = mid3_sclk; + calculate_bandwidth(dceip, vbios, data); + + calcs_output->nbp_state_change_wm_ns[0].b_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[4],bw_int_to_fixed(1000))); + calcs_output->nbp_state_change_wm_ns[1].b_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[5], bw_int_to_fixed(1000))); + calcs_output->nbp_state_change_wm_ns[2].b_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[6], bw_int_to_fixed(1000))); + + if (ctx->dc->caps.max_slave_planes) { + calcs_output->nbp_state_change_wm_ns[3].b_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[0], bw_int_to_fixed(1000))); + calcs_output->nbp_state_change_wm_ns[4].b_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[1], bw_int_to_fixed(1000))); + } else { + calcs_output->nbp_state_change_wm_ns[3].b_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[7], bw_int_to_fixed(1000))); + calcs_output->nbp_state_change_wm_ns[4].b_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[8], bw_int_to_fixed(1000))); + } + calcs_output->nbp_state_change_wm_ns[5].b_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[9], bw_int_to_fixed(1000))); + + + + calcs_output->stutter_exit_wm_ns[0].b_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[4], bw_int_to_fixed(1000))); + calcs_output->stutter_exit_wm_ns[1].b_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[5], bw_int_to_fixed(1000))); + calcs_output->stutter_exit_wm_ns[2].b_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[6], bw_int_to_fixed(1000))); + if (ctx->dc->caps.max_slave_planes) { + calcs_output->stutter_exit_wm_ns[3].b_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[0], bw_int_to_fixed(1000))); + calcs_output->stutter_exit_wm_ns[4].b_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[1], bw_int_to_fixed(1000))); + } else { + calcs_output->stutter_exit_wm_ns[3].b_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[7], bw_int_to_fixed(1000))); + calcs_output->stutter_exit_wm_ns[4].b_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[8], bw_int_to_fixed(1000))); + } + calcs_output->stutter_exit_wm_ns[5].b_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[9], bw_int_to_fixed(1000))); + + + + calcs_output->urgent_wm_ns[0].b_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[4], bw_int_to_fixed(1000))); + calcs_output->urgent_wm_ns[1].b_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[5], bw_int_to_fixed(1000))); + calcs_output->urgent_wm_ns[2].b_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[6], bw_int_to_fixed(1000))); + if (ctx->dc->caps.max_slave_planes) { + calcs_output->urgent_wm_ns[3].b_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[0], bw_int_to_fixed(1000))); + calcs_output->urgent_wm_ns[4].b_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[1], bw_int_to_fixed(1000))); + } else { + calcs_output->urgent_wm_ns[3].b_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[7], bw_int_to_fixed(1000))); + calcs_output->urgent_wm_ns[4].b_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[8], bw_int_to_fixed(1000))); + } + calcs_output->urgent_wm_ns[5].b_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[9], bw_int_to_fixed(1000))); + + ((struct bw_calcs_vbios *)vbios)->low_sclk = low_sclk; + ((struct bw_calcs_vbios *)vbios)->mid1_sclk = mid1_sclk; + ((struct bw_calcs_vbios *)vbios)->mid2_sclk = mid2_sclk; + ((struct bw_calcs_vbios *)vbios)->low_yclk = mid_yclk; + calculate_bandwidth(dceip, vbios, data); + + calcs_output->nbp_state_change_wm_ns[0].c_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[4], bw_int_to_fixed(1000))); + calcs_output->nbp_state_change_wm_ns[1].c_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[5], bw_int_to_fixed(1000))); + calcs_output->nbp_state_change_wm_ns[2].c_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[6], bw_int_to_fixed(1000))); + if (ctx->dc->caps.max_slave_planes) { + calcs_output->nbp_state_change_wm_ns[3].c_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[0], bw_int_to_fixed(1000))); + calcs_output->nbp_state_change_wm_ns[4].c_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[1], bw_int_to_fixed(1000))); + } else { + calcs_output->nbp_state_change_wm_ns[3].c_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[7], bw_int_to_fixed(1000))); + calcs_output->nbp_state_change_wm_ns[4].c_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[8], bw_int_to_fixed(1000))); + } + calcs_output->nbp_state_change_wm_ns[5].c_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[9], bw_int_to_fixed(1000))); + + + calcs_output->stutter_exit_wm_ns[0].c_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[4], bw_int_to_fixed(1000))); + calcs_output->stutter_exit_wm_ns[1].c_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[5], bw_int_to_fixed(1000))); + calcs_output->stutter_exit_wm_ns[2].c_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[6], bw_int_to_fixed(1000))); + if (ctx->dc->caps.max_slave_planes) { + calcs_output->stutter_exit_wm_ns[3].c_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[0], bw_int_to_fixed(1000))); + calcs_output->stutter_exit_wm_ns[4].c_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[1], bw_int_to_fixed(1000))); + } else { + calcs_output->stutter_exit_wm_ns[3].c_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[7], bw_int_to_fixed(1000))); + calcs_output->stutter_exit_wm_ns[4].c_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[8], bw_int_to_fixed(1000))); + } + calcs_output->stutter_exit_wm_ns[5].c_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[9], bw_int_to_fixed(1000))); + + calcs_output->urgent_wm_ns[0].c_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[4], bw_int_to_fixed(1000))); + calcs_output->urgent_wm_ns[1].c_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[5], bw_int_to_fixed(1000))); + calcs_output->urgent_wm_ns[2].c_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[6], bw_int_to_fixed(1000))); + if (ctx->dc->caps.max_slave_planes) { + calcs_output->urgent_wm_ns[3].c_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[0], bw_int_to_fixed(1000))); + calcs_output->urgent_wm_ns[4].c_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[1], bw_int_to_fixed(1000))); + } else { + calcs_output->urgent_wm_ns[3].c_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[7], bw_int_to_fixed(1000))); + calcs_output->urgent_wm_ns[4].c_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[8], bw_int_to_fixed(1000))); + } + calcs_output->urgent_wm_ns[5].c_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[9], bw_int_to_fixed(1000))); + } + + if (dceip->version == BW_CALCS_VERSION_CARRIZO) { + ((struct bw_calcs_vbios *)vbios)->low_yclk = high_yclk; + ((struct bw_calcs_vbios *)vbios)->mid_yclk = high_yclk; + ((struct bw_calcs_vbios *)vbios)->low_sclk = high_sclk; + ((struct bw_calcs_vbios *)vbios)->mid1_sclk = high_sclk; + ((struct bw_calcs_vbios *)vbios)->mid2_sclk = high_sclk; + ((struct bw_calcs_vbios *)vbios)->mid3_sclk = high_sclk; + ((struct bw_calcs_vbios *)vbios)->mid4_sclk = high_sclk; + ((struct bw_calcs_vbios *)vbios)->mid5_sclk = high_sclk; + ((struct bw_calcs_vbios *)vbios)->mid6_sclk = high_sclk; + } else { + ((struct bw_calcs_vbios *)vbios)->low_yclk = mid_yclk; + ((struct bw_calcs_vbios *)vbios)->low_sclk = mid3_sclk; + ((struct bw_calcs_vbios *)vbios)->mid1_sclk = mid3_sclk; + ((struct bw_calcs_vbios *)vbios)->mid2_sclk = mid3_sclk; + } + + calculate_bandwidth(dceip, vbios, data); + + calcs_output->nbp_state_change_wm_ns[0].d_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[4], bw_int_to_fixed(1000))); + calcs_output->nbp_state_change_wm_ns[1].d_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[5], bw_int_to_fixed(1000))); + calcs_output->nbp_state_change_wm_ns[2].d_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[6], bw_int_to_fixed(1000))); + if (ctx->dc->caps.max_slave_planes) { + calcs_output->nbp_state_change_wm_ns[3].d_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[0], bw_int_to_fixed(1000))); + calcs_output->nbp_state_change_wm_ns[4].d_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[1], bw_int_to_fixed(1000))); + } else { + calcs_output->nbp_state_change_wm_ns[3].d_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[7], bw_int_to_fixed(1000))); + calcs_output->nbp_state_change_wm_ns[4].d_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[8], bw_int_to_fixed(1000))); + } + calcs_output->nbp_state_change_wm_ns[5].d_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[9], bw_int_to_fixed(1000))); + + calcs_output->stutter_exit_wm_ns[0].d_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[4], bw_int_to_fixed(1000))); + calcs_output->stutter_exit_wm_ns[1].d_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[5], bw_int_to_fixed(1000))); + calcs_output->stutter_exit_wm_ns[2].d_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[6], bw_int_to_fixed(1000))); + if (ctx->dc->caps.max_slave_planes) { + calcs_output->stutter_exit_wm_ns[3].d_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[0], bw_int_to_fixed(1000))); + calcs_output->stutter_exit_wm_ns[4].d_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[1], bw_int_to_fixed(1000))); + } else { + calcs_output->stutter_exit_wm_ns[3].d_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[7], bw_int_to_fixed(1000))); + calcs_output->stutter_exit_wm_ns[4].d_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[8], bw_int_to_fixed(1000))); + } + calcs_output->stutter_exit_wm_ns[5].d_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[9], bw_int_to_fixed(1000))); + + + calcs_output->urgent_wm_ns[0].d_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[4], bw_int_to_fixed(1000))); + calcs_output->urgent_wm_ns[1].d_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[5], bw_int_to_fixed(1000))); + calcs_output->urgent_wm_ns[2].d_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[6], bw_int_to_fixed(1000))); + if (ctx->dc->caps.max_slave_planes) { + calcs_output->urgent_wm_ns[3].d_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[0], bw_int_to_fixed(1000))); + calcs_output->urgent_wm_ns[4].d_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[1], bw_int_to_fixed(1000))); + } else { + calcs_output->urgent_wm_ns[3].d_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[7], bw_int_to_fixed(1000))); + calcs_output->urgent_wm_ns[4].d_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[8], bw_int_to_fixed(1000))); + } + calcs_output->urgent_wm_ns[5].d_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[9], bw_int_to_fixed(1000))); + + ((struct bw_calcs_vbios *)vbios)->low_yclk = low_yclk; + ((struct bw_calcs_vbios *)vbios)->mid_yclk = mid_yclk; + ((struct bw_calcs_vbios *)vbios)->low_sclk = low_sclk; + ((struct bw_calcs_vbios *)vbios)->mid1_sclk = mid1_sclk; + ((struct bw_calcs_vbios *)vbios)->mid2_sclk = mid2_sclk; + ((struct bw_calcs_vbios *)vbios)->mid3_sclk = mid3_sclk; + ((struct bw_calcs_vbios *)vbios)->mid4_sclk = mid4_sclk; + ((struct bw_calcs_vbios *)vbios)->mid5_sclk = mid5_sclk; + ((struct bw_calcs_vbios *)vbios)->mid6_sclk = mid6_sclk; + ((struct bw_calcs_vbios *)vbios)->high_sclk = high_sclk; + } else { + calcs_output->nbp_state_change_enable = true; + calcs_output->cpuc_state_change_enable = true; + calcs_output->cpup_state_change_enable = true; + calcs_output->stutter_mode_enable = true; + calcs_output->dispclk_khz = 0; + calcs_output->required_sclk = 0; + } + + dm_free(data); + + return is_display_configuration_supported(vbios, calcs_output); +} diff --git a/drivers/gpu/drm/amd/display/dc/calcs/bw_fixed.c b/drivers/gpu/drm/amd/display/dc/calcs/bw_fixed.c new file mode 100644 index 000000000000..fbf2adcc5ff8 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/calcs/bw_fixed.c @@ -0,0 +1,299 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#include "dm_services.h" +#include "bw_fixed.h" + +#define BITS_PER_FRACTIONAL_PART 24 + +#define MIN_I32 \ + (int64_t)(-(1LL << (63 - BITS_PER_FRACTIONAL_PART))) + +#define MAX_I32 \ + (int64_t)((1ULL << (63 - BITS_PER_FRACTIONAL_PART)) - 1) + +#define MIN_I64 \ + (int64_t)(-(1LL << 63)) + +#define MAX_I64 \ + (int64_t)((1ULL << 63) - 1) + +#define FRACTIONAL_PART_MASK \ + ((1ULL << BITS_PER_FRACTIONAL_PART) - 1) + +#define GET_INTEGER_PART(x) \ + ((x) >> BITS_PER_FRACTIONAL_PART) + +#define GET_FRACTIONAL_PART(x) \ + (FRACTIONAL_PART_MASK & (x)) + +static uint64_t abs_i64(int64_t arg) +{ + if (arg >= 0) + return (uint64_t)(arg); + else + return (uint64_t)(-arg); +} + +struct bw_fixed bw_min3(struct bw_fixed v1, struct bw_fixed v2, struct bw_fixed v3) +{ + return bw_min2(bw_min2(v1, v2), v3); +} + +struct bw_fixed bw_max3(struct bw_fixed v1, struct bw_fixed v2, struct bw_fixed v3) +{ + return bw_max2(bw_max2(v1, v2), v3); +} + +struct bw_fixed bw_int_to_fixed(int64_t value) +{ + struct bw_fixed res; + ASSERT(value < MAX_I32 && value > MIN_I32); + res.value = value << BITS_PER_FRACTIONAL_PART; + return res; +} + +int32_t bw_fixed_to_int(struct bw_fixed value) +{ + return GET_INTEGER_PART(value.value); +} + +struct bw_fixed bw_frc_to_fixed(int64_t numerator, int64_t denominator) +{ + struct bw_fixed res; + bool arg1_negative = numerator < 0; + bool arg2_negative = denominator < 0; + uint64_t arg1_value; + uint64_t arg2_value; + uint64_t remainder; + + /* determine integer part */ + uint64_t res_value; + + ASSERT(denominator != 0); + + arg1_value = abs_i64(numerator); + arg2_value = abs_i64(denominator); + res_value = div64_u64_rem(arg1_value, arg2_value, &remainder); + + ASSERT(res_value <= MAX_I32); + + /* determine fractional part */ + { + uint32_t i = BITS_PER_FRACTIONAL_PART; + + do + { + remainder <<= 1; + + res_value <<= 1; + + if (remainder >= arg2_value) + { + res_value |= 1; + remainder -= arg2_value; + } + } while (--i != 0); + } + + /* round up LSB */ + { + uint64_t summand = (remainder << 1) >= arg2_value; + + ASSERT(res_value <= MAX_I64 - summand); + + res_value += summand; + } + + res.value = (int64_t)(res_value); + + if (arg1_negative ^ arg2_negative) + res.value = -res.value; + return res; +} + +struct bw_fixed bw_min2(const struct bw_fixed arg1, const struct bw_fixed arg2) +{ + return (arg1.value <= arg2.value) ? arg1 : arg2; +} + +struct bw_fixed bw_max2(const struct bw_fixed arg1, const struct bw_fixed arg2) +{ + return (arg2.value <= arg1.value) ? arg1 : arg2; +} + +struct bw_fixed bw_floor2( + const struct bw_fixed arg, + const struct bw_fixed significance) +{ + struct bw_fixed result; + int64_t multiplicand; + + multiplicand = div64_s64(arg.value, abs_i64(significance.value)); + result.value = abs_i64(significance.value) * multiplicand; + ASSERT(abs_i64(result.value) <= abs_i64(arg.value)); + return result; +} + +struct bw_fixed bw_ceil2( + const struct bw_fixed arg, + const struct bw_fixed significance) +{ + struct bw_fixed result; + int64_t multiplicand; + + multiplicand = div64_s64(arg.value, abs_i64(significance.value)); + result.value = abs_i64(significance.value) * multiplicand; + if (abs_i64(result.value) < abs_i64(arg.value)) { + if (arg.value < 0) + result.value -= abs_i64(significance.value); + else + result.value += abs_i64(significance.value); + } + return result; +} + +struct bw_fixed bw_add(const struct bw_fixed arg1, const struct bw_fixed arg2) +{ + struct bw_fixed res; + + res.value = arg1.value + arg2.value; + + return res; +} + +struct bw_fixed bw_sub(const struct bw_fixed arg1, const struct bw_fixed arg2) +{ + struct bw_fixed res; + + res.value = arg1.value - arg2.value; + + return res; +} + +struct bw_fixed bw_mul(const struct bw_fixed arg1, const struct bw_fixed arg2) +{ + struct bw_fixed res; + + bool arg1_negative = arg1.value < 0; + bool arg2_negative = arg2.value < 0; + + uint64_t arg1_value = abs_i64(arg1.value); + uint64_t arg2_value = abs_i64(arg2.value); + + uint64_t arg1_int = GET_INTEGER_PART(arg1_value); + uint64_t arg2_int = GET_INTEGER_PART(arg2_value); + + uint64_t arg1_fra = GET_FRACTIONAL_PART(arg1_value); + uint64_t arg2_fra = GET_FRACTIONAL_PART(arg2_value); + + uint64_t tmp; + + res.value = arg1_int * arg2_int; + + ASSERT(res.value <= MAX_I32); + + res.value <<= BITS_PER_FRACTIONAL_PART; + + tmp = arg1_int * arg2_fra; + + ASSERT(tmp <= (uint64_t)(MAX_I64 - res.value)); + + res.value += tmp; + + tmp = arg2_int * arg1_fra; + + ASSERT(tmp <= (uint64_t)(MAX_I64 - res.value)); + + res.value += tmp; + + tmp = arg1_fra * arg2_fra; + + tmp = (tmp >> BITS_PER_FRACTIONAL_PART) + + (tmp >= (uint64_t)(bw_frc_to_fixed(1, 2).value)); + + ASSERT(tmp <= (uint64_t)(MAX_I64 - res.value)); + + res.value += tmp; + + if (arg1_negative ^ arg2_negative) + res.value = -res.value; + return res; +} + +struct bw_fixed bw_div(const struct bw_fixed arg1, const struct bw_fixed arg2) +{ + struct bw_fixed res = bw_frc_to_fixed(arg1.value, arg2.value); + return res; +} + +struct bw_fixed bw_mod(const struct bw_fixed arg1, const struct bw_fixed arg2) +{ + struct bw_fixed res; + div64_u64_rem(arg1.value, arg2.value, &res.value); + return res; +} +struct bw_fixed fixed31_32_to_bw_fixed(int64_t raw) +{ + struct bw_fixed result = { 0 }; + + if (raw < 0) { + raw = -raw; + result.value = -(raw >> (32 - BITS_PER_FRACTIONAL_PART)); + } else { + result.value = raw >> (32 - BITS_PER_FRACTIONAL_PART); + } + + return result; +} + +bool bw_equ(const struct bw_fixed arg1, const struct bw_fixed arg2) +{ + return arg1.value == arg2.value; +} + +bool bw_neq(const struct bw_fixed arg1, const struct bw_fixed arg2) +{ + return arg1.value != arg2.value; +} + +bool bw_leq(const struct bw_fixed arg1, const struct bw_fixed arg2) +{ + return arg1.value <= arg2.value; +} + +bool bw_meq(const struct bw_fixed arg1, const struct bw_fixed arg2) +{ + return arg1.value >= arg2.value; +} + +bool bw_ltn(const struct bw_fixed arg1, const struct bw_fixed arg2) +{ + return arg1.value < arg2.value; +} + +bool bw_mtn(const struct bw_fixed arg1, const struct bw_fixed arg2) +{ + return arg1.value > arg2.value; +} diff --git a/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c new file mode 100644 index 000000000000..854796aa0c71 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c @@ -0,0 +1,1382 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "gamma_calcs.h" + +struct curve_config { + uint32_t offset; + int8_t segments[16]; + int8_t begin; +}; + +static bool build_custom_float( + struct fixed31_32 value, + const struct custom_float_format *format, + bool *negative, + uint32_t *mantissa, + uint32_t *exponenta) +{ + uint32_t exp_offset = (1 << (format->exponenta_bits - 1)) - 1; + + const struct fixed31_32 mantissa_constant_plus_max_fraction = + dal_fixed31_32_from_fraction( + (1LL << (format->mantissa_bits + 1)) - 1, + 1LL << format->mantissa_bits); + + struct fixed31_32 mantiss; + + if (dal_fixed31_32_eq( + value, + dal_fixed31_32_zero)) { + *negative = false; + *mantissa = 0; + *exponenta = 0; + return true; + } + + if (dal_fixed31_32_lt( + value, + dal_fixed31_32_zero)) { + *negative = format->sign; + value = dal_fixed31_32_neg(value); + } else { + *negative = false; + } + + if (dal_fixed31_32_lt( + value, + dal_fixed31_32_one)) { + uint32_t i = 1; + + do { + value = dal_fixed31_32_shl(value, 1); + ++i; + } while (dal_fixed31_32_lt( + value, + dal_fixed31_32_one)); + + --i; + + if (exp_offset <= i) { + *mantissa = 0; + *exponenta = 0; + return true; + } + + *exponenta = exp_offset - i; + } else if (dal_fixed31_32_le( + mantissa_constant_plus_max_fraction, + value)) { + uint32_t i = 1; + + do { + value = dal_fixed31_32_shr(value, 1); + ++i; + } while (dal_fixed31_32_lt( + mantissa_constant_plus_max_fraction, + value)); + + *exponenta = exp_offset + i - 1; + } else { + *exponenta = exp_offset; + } + + mantiss = dal_fixed31_32_sub( + value, + dal_fixed31_32_one); + + if (dal_fixed31_32_lt( + mantiss, + dal_fixed31_32_zero) || + dal_fixed31_32_lt( + dal_fixed31_32_one, + mantiss)) + mantiss = dal_fixed31_32_zero; + else + mantiss = dal_fixed31_32_shl( + mantiss, + format->mantissa_bits); + + *mantissa = dal_fixed31_32_floor(mantiss); + + return true; +} + +static bool setup_custom_float( + const struct custom_float_format *format, + bool negative, + uint32_t mantissa, + uint32_t exponenta, + uint32_t *result) +{ + uint32_t i = 0; + uint32_t j = 0; + + uint32_t value = 0; + + /* verification code: + * once calculation is ok we can remove it + */ + + const uint32_t mantissa_mask = + (1 << (format->mantissa_bits + 1)) - 1; + + const uint32_t exponenta_mask = + (1 << (format->exponenta_bits + 1)) - 1; + + if (mantissa & ~mantissa_mask) { + BREAK_TO_DEBUGGER(); + mantissa = mantissa_mask; + } + + if (exponenta & ~exponenta_mask) { + BREAK_TO_DEBUGGER(); + exponenta = exponenta_mask; + } + + /* end of verification code */ + + while (i < format->mantissa_bits) { + uint32_t mask = 1 << i; + + if (mantissa & mask) + value |= mask; + + ++i; + } + + while (j < format->exponenta_bits) { + uint32_t mask = 1 << j; + + if (exponenta & mask) + value |= mask << i; + + ++j; + } + + if (negative && format->sign) + value |= 1 << (i + j); + + *result = value; + + return true; +} + +static bool convert_to_custom_float_format_ex( + struct fixed31_32 value, + const struct custom_float_format *format, + struct custom_float_value *result) +{ + return build_custom_float( + value, format, + &result->negative, &result->mantissa, &result->exponenta) && + setup_custom_float( + format, result->negative, result->mantissa, result->exponenta, + &result->value); +} + +static bool round_custom_float_6_12( + struct hw_x_point *x) +{ + struct custom_float_format fmt; + + struct custom_float_value value; + + fmt.exponenta_bits = 6; + fmt.mantissa_bits = 12; + fmt.sign = true; + + if (!convert_to_custom_float_format_ex( + x->x, &fmt, &value)) + return false; + + x->adjusted_x = x->x; + + if (value.mantissa) { + BREAK_TO_DEBUGGER(); + + return false; + } + + return true; +} + +static bool build_hw_curve_configuration( + const struct curve_config *curve_config, + struct gamma_curve *gamma_curve, + struct curve_points *curve_points, + struct hw_x_point *points, + uint32_t *number_of_points) +{ + const int8_t max_regions_number = ARRAY_SIZE(curve_config->segments); + + int8_t i; + + uint8_t segments_calculation[8] = { 0 }; + + struct fixed31_32 region1 = dal_fixed31_32_zero; + struct fixed31_32 region2; + struct fixed31_32 increment; + + uint32_t index = 0; + uint32_t segments = 0; + uint32_t max_number; + + bool result = false; + + if (!number_of_points) { + BREAK_TO_DEBUGGER(); + return false; + } + + max_number = *number_of_points; + + i = 0; + + while (i != max_regions_number) { + gamma_curve[i].offset = 0; + gamma_curve[i].segments_num = 0; + + ++i; + } + + i = 0; + + while (i != max_regions_number) { + /* number should go in uninterruptible sequence */ + if (curve_config->segments[i] == -1) + break; + + ASSERT(curve_config->segments[i] >= 0); + + segments += (1 << curve_config->segments[i]); + + ++i; + } + + if (segments > max_number) { + BREAK_TO_DEBUGGER(); + } else { + int32_t divisor; + uint32_t offset = 0; + int8_t begin = curve_config->begin; + int32_t region_number = 0; + + i = begin; + + while ((index < max_number) && + (region_number < max_regions_number) && + (i <= 1)) { + int32_t j = 0; + + segments = curve_config->segments[region_number]; + divisor = 1 << segments; + + if (segments == -1) { + if (i > 0) { + region1 = dal_fixed31_32_shl( + dal_fixed31_32_one, + i - 1); + region2 = dal_fixed31_32_shl( + dal_fixed31_32_one, + i); + } else { + region1 = dal_fixed31_32_shr( + dal_fixed31_32_one, + -(i - 1)); + region2 = dal_fixed31_32_shr( + dal_fixed31_32_one, + -i); + } + + break; + } + + if (i > -1) { + region1 = dal_fixed31_32_shl( + dal_fixed31_32_one, + i); + region2 = dal_fixed31_32_shl( + dal_fixed31_32_one, + i + 1); + } else { + region1 = dal_fixed31_32_shr( + dal_fixed31_32_one, + -i); + region2 = dal_fixed31_32_shr( + dal_fixed31_32_one, + -(i + 1)); + } + + gamma_curve[region_number].offset = offset; + gamma_curve[region_number].segments_num = segments; + + offset += divisor; + + ++segments_calculation[segments]; + + increment = dal_fixed31_32_div_int( + dal_fixed31_32_sub( + region2, + region1), + divisor); + + points[index].x = region1; + + round_custom_float_6_12(points + index); + + ++index; + ++region_number; + + while ((index < max_number) && (j < divisor - 1)) { + region1 = dal_fixed31_32_add( + region1, + increment); + + points[index].x = region1; + points[index].adjusted_x = region1; + + ++index; + ++j; + } + + ++i; + } + + points[index].x = region1; + + round_custom_float_6_12(points + index); + + *number_of_points = index; + + result = true; + } + + curve_points[0].x = points[0].adjusted_x; + curve_points[0].offset = dal_fixed31_32_zero; + + curve_points[1].x = points[index - 1].adjusted_x; + curve_points[1].offset = dal_fixed31_32_zero; + + curve_points[2].x = points[index].adjusted_x; + curve_points[2].offset = dal_fixed31_32_zero; + + return result; +} + +static bool setup_distribution_points( + struct gamma_curve *arr_curve_points, + struct curve_points *arr_points, + uint32_t *hw_points_num, + struct hw_x_point *coordinates_x) +{ + struct curve_config cfg; + + cfg.offset = 0; + cfg.segments[0] = 3; + cfg.segments[1] = 4; + cfg.segments[2] = 4; + cfg.segments[3] = 4; + cfg.segments[4] = 4; + cfg.segments[5] = 4; + cfg.segments[6] = 4; + cfg.segments[7] = 4; + cfg.segments[8] = 5; + cfg.segments[9] = 5; + cfg.segments[10] = 0; + cfg.segments[11] = -1; + cfg.segments[12] = -1; + cfg.segments[13] = -1; + cfg.segments[14] = -1; + cfg.segments[15] = -1; + + cfg.begin = -10; + + if (!build_hw_curve_configuration( + &cfg, arr_curve_points, + arr_points, + coordinates_x, hw_points_num)) { + ASSERT_CRITICAL(false); + return false; + } + return true; +} + +struct dividers { + struct fixed31_32 divider1; + struct fixed31_32 divider2; + struct fixed31_32 divider3; +}; + +static void build_regamma_coefficients(struct gamma_coefficients *coefficients) +{ + /* sRGB should apply 2.4 */ + static const int32_t numerator01[3] = { 31308, 31308, 31308 }; + static const int32_t numerator02[3] = { 12920, 12920, 12920 }; + static const int32_t numerator03[3] = { 55, 55, 55 }; + static const int32_t numerator04[3] = { 55, 55, 55 }; + static const int32_t numerator05[3] = { 2400, 2400, 2400 }; + + const int32_t *numerator1; + const int32_t *numerator2; + const int32_t *numerator3; + const int32_t *numerator4; + const int32_t *numerator5; + + uint32_t i = 0; + + numerator1 = numerator01; + numerator2 = numerator02; + numerator3 = numerator03; + numerator4 = numerator04; + numerator5 = numerator05; + + do { + coefficients->a0[i] = dal_fixed31_32_from_fraction( + numerator1[i], 10000000); + coefficients->a1[i] = dal_fixed31_32_from_fraction( + numerator2[i], 1000); + coefficients->a2[i] = dal_fixed31_32_from_fraction( + numerator3[i], 1000); + coefficients->a3[i] = dal_fixed31_32_from_fraction( + numerator4[i], 1000); + coefficients->user_gamma[i] = dal_fixed31_32_from_fraction( + numerator5[i], 1000); + + ++i; + } while (i != ARRAY_SIZE(coefficients->a0)); +} + +static struct fixed31_32 translate_from_linear_space( + struct fixed31_32 arg, + struct fixed31_32 a0, + struct fixed31_32 a1, + struct fixed31_32 a2, + struct fixed31_32 a3, + struct fixed31_32 gamma) +{ + const struct fixed31_32 one = dal_fixed31_32_from_int(1); + + if (dal_fixed31_32_le(arg, dal_fixed31_32_neg(a0))) + return dal_fixed31_32_sub( + a2, + dal_fixed31_32_mul( + dal_fixed31_32_add( + one, + a3), + dal_fixed31_32_pow( + dal_fixed31_32_neg(arg), + dal_fixed31_32_recip(gamma)))); + else if (dal_fixed31_32_le(a0, arg)) + return dal_fixed31_32_sub( + dal_fixed31_32_mul( + dal_fixed31_32_add( + one, + a3), + dal_fixed31_32_pow( + arg, + dal_fixed31_32_recip(gamma))), + a2); + else + return dal_fixed31_32_mul( + arg, + a1); +} + +static inline struct fixed31_32 translate_from_linear_space_ex( + struct fixed31_32 arg, + struct gamma_coefficients *coeff, + uint32_t color_index) +{ + return translate_from_linear_space( + arg, + coeff->a0[color_index], + coeff->a1[color_index], + coeff->a2[color_index], + coeff->a3[color_index], + coeff->user_gamma[color_index]); +} + +static bool find_software_points( + const struct gamma_pixel *axis_x_256, + struct fixed31_32 hw_point, + enum channel_name channel, + uint32_t *index_to_start, + uint32_t *index_left, + uint32_t *index_right, + enum hw_point_position *pos) +{ + const uint32_t max_number = RGB_256X3X16 + 3; + + struct fixed31_32 left, right; + + uint32_t i = *index_to_start; + + while (i < max_number) { + if (channel == CHANNEL_NAME_RED) { + left = axis_x_256[i].r; + + if (i < max_number - 1) + right = axis_x_256[i + 1].r; + else + right = axis_x_256[max_number - 1].r; + } else if (channel == CHANNEL_NAME_GREEN) { + left = axis_x_256[i].g; + + if (i < max_number - 1) + right = axis_x_256[i + 1].g; + else + right = axis_x_256[max_number - 1].g; + } else { + left = axis_x_256[i].b; + + if (i < max_number - 1) + right = axis_x_256[i + 1].b; + else + right = axis_x_256[max_number - 1].b; + } + + if (dal_fixed31_32_le(left, hw_point) && + dal_fixed31_32_le(hw_point, right)) { + *index_to_start = i; + *index_left = i; + + if (i < max_number - 1) + *index_right = i + 1; + else + *index_right = max_number - 1; + + *pos = HW_POINT_POSITION_MIDDLE; + + return true; + } else if ((i == *index_to_start) && + dal_fixed31_32_le(hw_point, left)) { + *index_to_start = i; + *index_left = i; + *index_right = i; + + *pos = HW_POINT_POSITION_LEFT; + + return true; + } else if ((i == max_number - 1) && + dal_fixed31_32_le(right, hw_point)) { + *index_to_start = i; + *index_left = i; + *index_right = i; + + *pos = HW_POINT_POSITION_RIGHT; + + return true; + } + + ++i; + } + + return false; +} + +static bool build_custom_gamma_mapping_coefficients_worker( + struct pixel_gamma_point *coeff, + const struct hw_x_point *coordinates_x, + const struct gamma_pixel *axis_x_256, + enum channel_name channel, + uint32_t number_of_points, + enum surface_pixel_format pixel_format) +{ + uint32_t i = 0; + + while (i <= number_of_points) { + struct fixed31_32 coord_x; + + uint32_t index_to_start = 0; + uint32_t index_left = 0; + uint32_t index_right = 0; + + enum hw_point_position hw_pos; + + struct gamma_point *point; + + struct fixed31_32 left_pos; + struct fixed31_32 right_pos; + + /* + * TODO: confirm enum in surface_pixel_format + * if (pixel_format == PIXEL_FORMAT_FP16) + *coord_x = coordinates_x[i].adjusted_x; + *else + */ + if (channel == CHANNEL_NAME_RED) + coord_x = coordinates_x[i].regamma_y_red; + else if (channel == CHANNEL_NAME_GREEN) + coord_x = coordinates_x[i].regamma_y_green; + else + coord_x = coordinates_x[i].regamma_y_blue; + + if (!find_software_points( + axis_x_256, coord_x, channel, + &index_to_start, &index_left, &index_right, &hw_pos)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (index_left >= RGB_256X3X16 + 3) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (index_right >= RGB_256X3X16 + 3) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (channel == CHANNEL_NAME_RED) { + point = &coeff[i].r; + + left_pos = axis_x_256[index_left].r; + right_pos = axis_x_256[index_right].r; + } else if (channel == CHANNEL_NAME_GREEN) { + point = &coeff[i].g; + + left_pos = axis_x_256[index_left].g; + right_pos = axis_x_256[index_right].g; + } else { + point = &coeff[i].b; + + left_pos = axis_x_256[index_left].b; + right_pos = axis_x_256[index_right].b; + } + + if (hw_pos == HW_POINT_POSITION_MIDDLE) + point->coeff = dal_fixed31_32_div( + dal_fixed31_32_sub( + coord_x, + left_pos), + dal_fixed31_32_sub( + right_pos, + left_pos)); + else if (hw_pos == HW_POINT_POSITION_LEFT) + point->coeff = dal_fixed31_32_zero; + else if (hw_pos == HW_POINT_POSITION_RIGHT) + point->coeff = dal_fixed31_32_from_int(2); + else { + BREAK_TO_DEBUGGER(); + return false; + } + + point->left_index = index_left; + point->right_index = index_right; + point->pos = hw_pos; + + ++i; + } + + return true; +} + +static inline bool build_oem_custom_gamma_mapping_coefficients( + struct pixel_gamma_point *coeff128_oem, + const struct hw_x_point *coordinates_x, + const struct gamma_pixel *axis_x_256, + uint32_t number_of_points, + enum surface_pixel_format pixel_format) +{ + int i; + + for (i = 0; i < 3; i++) { + if (!build_custom_gamma_mapping_coefficients_worker( + coeff128_oem, coordinates_x, axis_x_256, i, + number_of_points, pixel_format)) + return false; + } + return true; +} + +static struct fixed31_32 calculate_mapped_value( + struct pwl_float_data *rgb, + const struct pixel_gamma_point *coeff, + enum channel_name channel, + uint32_t max_index) +{ + const struct gamma_point *point; + + struct fixed31_32 result; + + if (channel == CHANNEL_NAME_RED) + point = &coeff->r; + else if (channel == CHANNEL_NAME_GREEN) + point = &coeff->g; + else + point = &coeff->b; + + if ((point->left_index < 0) || (point->left_index > max_index)) { + BREAK_TO_DEBUGGER(); + return dal_fixed31_32_zero; + } + + if ((point->right_index < 0) || (point->right_index > max_index)) { + BREAK_TO_DEBUGGER(); + return dal_fixed31_32_zero; + } + + if (point->pos == HW_POINT_POSITION_MIDDLE) + if (channel == CHANNEL_NAME_RED) + result = dal_fixed31_32_add( + dal_fixed31_32_mul( + point->coeff, + dal_fixed31_32_sub( + rgb[point->right_index].r, + rgb[point->left_index].r)), + rgb[point->left_index].r); + else if (channel == CHANNEL_NAME_GREEN) + result = dal_fixed31_32_add( + dal_fixed31_32_mul( + point->coeff, + dal_fixed31_32_sub( + rgb[point->right_index].g, + rgb[point->left_index].g)), + rgb[point->left_index].g); + else + result = dal_fixed31_32_add( + dal_fixed31_32_mul( + point->coeff, + dal_fixed31_32_sub( + rgb[point->right_index].b, + rgb[point->left_index].b)), + rgb[point->left_index].b); + else if (point->pos == HW_POINT_POSITION_LEFT) { + BREAK_TO_DEBUGGER(); + result = dal_fixed31_32_zero; + } else { + BREAK_TO_DEBUGGER(); + result = dal_fixed31_32_one; + } + + return result; +} + +static inline struct fixed31_32 calculate_oem_mapped_value( + struct pwl_float_data *rgb_oem, + const struct pixel_gamma_point *coeff, + uint32_t index, + enum channel_name channel, + uint32_t max_index) +{ + return calculate_mapped_value( + rgb_oem, + coeff + index, + channel, + max_index); +} + +static void build_regamma_curve(struct pwl_float_data_ex *rgb_regamma, + struct pwl_float_data *rgb_oem, + struct pixel_gamma_point *coeff128_oem, + const struct core_gamma *ramp, + const struct core_surface *surface, + uint32_t hw_points_num, + const struct hw_x_point *coordinate_x, + const struct gamma_pixel *axis_x, + struct dividers dividers) +{ + uint32_t i; + + struct gamma_coefficients coeff; + struct pwl_float_data_ex *rgb = rgb_regamma; + const struct hw_x_point *coord_x = coordinate_x; + + build_regamma_coefficients(&coeff); + + /* Use opp110->regamma.coordinates_x to retrieve + * coordinates chosen base on given user curve (future task). + * The x values are exponentially distributed and currently + * it is hard-coded, the user curve shape is ignored. + * The future task is to recalculate opp110- + * regamma.coordinates_x based on input/user curve, + * translation from 256/1025 to 128 pwl points. + */ + + i = 0; + + while (i != hw_points_num + 1) { + rgb->r = translate_from_linear_space_ex( + coord_x->adjusted_x, &coeff, 0); + rgb->g = translate_from_linear_space_ex( + coord_x->adjusted_x, &coeff, 1); + rgb->b = translate_from_linear_space_ex( + coord_x->adjusted_x, &coeff, 2); + + ++coord_x; + ++rgb; + ++i; + } +} + +static bool scale_gamma(struct pwl_float_data *pwl_rgb, + const struct core_gamma *ramp, + struct dividers dividers) +{ + const struct dc_gamma_ramp_rgb256x3x16 *gamma; + const uint16_t max_driver = 0xFFFF; + const uint16_t max_os = 0xFF00; + uint16_t scaler = max_os; + uint32_t i; + struct pwl_float_data *rgb = pwl_rgb; + struct pwl_float_data *rgb_last = rgb + RGB_256X3X16 - 1; + + if (ramp->public.type == GAMMA_RAMP_RBG256X3X16) + gamma = &ramp->public.gamma_ramp_rgb256x3x16; + else + return false; /* invalid option */ + + i = 0; + + do { + if ((gamma->red[i] > max_os) || + (gamma->green[i] > max_os) || + (gamma->blue[i] > max_os)) { + scaler = max_driver; + break; + } + ++i; + } while (i != RGB_256X3X16); + + i = 0; + + do { + rgb->r = dal_fixed31_32_from_fraction( + gamma->red[i], scaler); + rgb->g = dal_fixed31_32_from_fraction( + gamma->green[i], scaler); + rgb->b = dal_fixed31_32_from_fraction( + gamma->blue[i], scaler); + + ++rgb; + ++i; + } while (i != RGB_256X3X16); + + rgb->r = dal_fixed31_32_mul(rgb_last->r, + dividers.divider1); + rgb->g = dal_fixed31_32_mul(rgb_last->g, + dividers.divider1); + rgb->b = dal_fixed31_32_mul(rgb_last->b, + dividers.divider1); + + ++rgb; + + rgb->r = dal_fixed31_32_mul(rgb_last->r, + dividers.divider2); + rgb->g = dal_fixed31_32_mul(rgb_last->g, + dividers.divider2); + rgb->b = dal_fixed31_32_mul(rgb_last->b, + dividers.divider2); + + ++rgb; + + rgb->r = dal_fixed31_32_mul(rgb_last->r, + dividers.divider3); + rgb->g = dal_fixed31_32_mul(rgb_last->g, + dividers.divider3); + rgb->b = dal_fixed31_32_mul(rgb_last->b, + dividers.divider3); + + return true; +} + +static void build_evenly_distributed_points( + struct gamma_pixel *points, + uint32_t numberof_points, + struct fixed31_32 max_value, + struct dividers dividers) +{ + struct gamma_pixel *p = points; + struct gamma_pixel *p_last = p + numberof_points - 1; + + uint32_t i = 0; + + do { + struct fixed31_32 value = dal_fixed31_32_div_int( + dal_fixed31_32_mul_int(max_value, i), + numberof_points - 1); + + p->r = value; + p->g = value; + p->b = value; + + ++p; + ++i; + } while (i != numberof_points); + + p->r = dal_fixed31_32_div(p_last->r, dividers.divider1); + p->g = dal_fixed31_32_div(p_last->g, dividers.divider1); + p->b = dal_fixed31_32_div(p_last->b, dividers.divider1); + + ++p; + + p->r = dal_fixed31_32_div(p_last->r, dividers.divider2); + p->g = dal_fixed31_32_div(p_last->g, dividers.divider2); + p->b = dal_fixed31_32_div(p_last->b, dividers.divider2); + + ++p; + + p->r = dal_fixed31_32_div(p_last->r, dividers.divider3); + p->g = dal_fixed31_32_div(p_last->g, dividers.divider3); + p->b = dal_fixed31_32_div(p_last->b, dividers.divider3); +} + +static inline void copy_rgb_regamma_to_coordinates_x( + struct hw_x_point *coordinates_x, + uint32_t hw_points_num, + const struct pwl_float_data_ex *rgb_ex) +{ + struct hw_x_point *coords = coordinates_x; + uint32_t i = 0; + const struct pwl_float_data_ex *rgb_regamma = rgb_ex; + + while (i <= hw_points_num) { + coords->regamma_y_red = rgb_regamma->r; + coords->regamma_y_green = rgb_regamma->g; + coords->regamma_y_blue = rgb_regamma->b; + + ++coords; + ++rgb_regamma; + ++i; + } +} + +static bool calculate_interpolated_hardware_curve( + struct pwl_result_data *rgb, + struct pixel_gamma_point *coeff128, + struct pwl_float_data *rgb_user, + const struct hw_x_point *coordinates_x, + const struct gamma_pixel *axis_x_256, + uint32_t number_of_points, + enum surface_pixel_format pixel_format) +{ + + const struct pixel_gamma_point *coeff; + struct pixel_gamma_point *coeff_128 = coeff128; + uint32_t max_entries = 3 - 1; + struct pwl_result_data *rgb_resulted = rgb; + + uint32_t i = 0; + + if (!build_oem_custom_gamma_mapping_coefficients( + coeff_128, coordinates_x, axis_x_256, + number_of_points, + pixel_format)) + return false; + + coeff = coeff128; + max_entries += RGB_256X3X16; + + /* TODO: float point case */ + + while (i <= number_of_points) { + rgb_resulted->red = calculate_mapped_value( + rgb_user, coeff, CHANNEL_NAME_RED, max_entries); + rgb_resulted->green = calculate_mapped_value( + rgb_user, coeff, CHANNEL_NAME_GREEN, max_entries); + rgb_resulted->blue = calculate_mapped_value( + rgb_user, coeff, CHANNEL_NAME_BLUE, max_entries); + + ++coeff; + ++rgb_resulted; + ++i; + } + + return true; +} + +static bool map_regamma_hw_to_x_user( + struct pixel_gamma_point *coeff128, + struct pwl_float_data *rgb_oem, + struct pwl_result_data *rgb_resulted, + struct pwl_float_data *rgb_user, + struct hw_x_point *coords_x, + const struct gamma_pixel *axis_x, + const struct dc_gamma *gamma, + const struct pwl_float_data_ex *rgb_regamma, + struct dividers dividers, + uint32_t hw_points_num, + const struct core_surface *surface) +{ + /* setup to spare calculated ideal regamma values */ + + struct pixel_gamma_point *coeff = coeff128; + + struct hw_x_point *coords = coords_x; + + copy_rgb_regamma_to_coordinates_x(coords, hw_points_num, rgb_regamma); + + return calculate_interpolated_hardware_curve( + rgb_resulted, coeff, rgb_user, coords, axis_x, + hw_points_num, surface->public.format); +} + +static void build_new_custom_resulted_curve( + struct pwl_result_data *rgb_resulted, + uint32_t hw_points_num) +{ + struct pwl_result_data *rgb = rgb_resulted; + struct pwl_result_data *rgb_plus_1 = rgb + 1; + + uint32_t i; + + i = 0; + + while (i != hw_points_num + 1) { + rgb->red = dal_fixed31_32_clamp( + rgb->red, dal_fixed31_32_zero, + dal_fixed31_32_one); + rgb->green = dal_fixed31_32_clamp( + rgb->green, dal_fixed31_32_zero, + dal_fixed31_32_one); + rgb->blue = dal_fixed31_32_clamp( + rgb->blue, dal_fixed31_32_zero, + dal_fixed31_32_one); + + ++rgb; + ++i; + } + + rgb = rgb_resulted; + + i = 1; + + while (i != hw_points_num + 1) { + if (dal_fixed31_32_lt(rgb_plus_1->red, rgb->red)) + rgb_plus_1->red = rgb->red; + if (dal_fixed31_32_lt(rgb_plus_1->green, rgb->green)) + rgb_plus_1->green = rgb->green; + if (dal_fixed31_32_lt(rgb_plus_1->blue, rgb->blue)) + rgb_plus_1->blue = rgb->blue; + + rgb->delta_red = dal_fixed31_32_sub( + rgb_plus_1->red, + rgb->red); + rgb->delta_green = dal_fixed31_32_sub( + rgb_plus_1->green, + rgb->green); + rgb->delta_blue = dal_fixed31_32_sub( + rgb_plus_1->blue, + rgb->blue); + + ++rgb_plus_1; + ++rgb; + ++i; + } +} + +static void rebuild_curve_configuration_magic( + struct curve_points *arr_points, + struct pwl_result_data *rgb_resulted, + const struct hw_x_point *coordinates_x, + uint32_t hw_points_num) +{ + const struct fixed31_32 magic_number = + dal_fixed31_32_from_fraction(249, 1000); + + struct fixed31_32 y_r; + struct fixed31_32 y_g; + struct fixed31_32 y_b; + + struct fixed31_32 y1_min; + struct fixed31_32 y2_max; + struct fixed31_32 y3_max; + + y_r = rgb_resulted[0].red; + y_g = rgb_resulted[0].green; + y_b = rgb_resulted[0].blue; + + y1_min = dal_fixed31_32_min(y_r, dal_fixed31_32_min(y_g, y_b)); + + arr_points[0].x = coordinates_x[0].adjusted_x; + arr_points[0].y = y1_min; + arr_points[0].slope = dal_fixed31_32_div( + arr_points[0].y, + arr_points[0].x); + + arr_points[1].x = dal_fixed31_32_add( + coordinates_x[hw_points_num - 1].adjusted_x, + magic_number); + + arr_points[2].x = arr_points[1].x; + + y_r = rgb_resulted[hw_points_num - 1].red; + y_g = rgb_resulted[hw_points_num - 1].green; + y_b = rgb_resulted[hw_points_num - 1].blue; + + y2_max = dal_fixed31_32_max(y_r, dal_fixed31_32_max(y_g, y_b)); + + arr_points[1].y = y2_max; + + y_r = rgb_resulted[hw_points_num].red; + y_g = rgb_resulted[hw_points_num].green; + y_b = rgb_resulted[hw_points_num].blue; + + y3_max = dal_fixed31_32_max(y_r, dal_fixed31_32_max(y_g, y_b)); + + arr_points[2].y = y3_max; + + arr_points[2].slope = dal_fixed31_32_one; +} + +static bool convert_to_custom_float_format( + struct fixed31_32 value, + const struct custom_float_format *format, + uint32_t *result) +{ + uint32_t mantissa; + uint32_t exponenta; + bool negative; + + return build_custom_float( + value, format, &negative, &mantissa, &exponenta) && + setup_custom_float( + format, negative, mantissa, exponenta, result); +} + +static bool convert_to_custom_float( + struct pwl_result_data *rgb_resulted, + struct curve_points *arr_points, + uint32_t hw_points_num) +{ + struct custom_float_format fmt; + + struct pwl_result_data *rgb = rgb_resulted; + + uint32_t i = 0; + + fmt.exponenta_bits = 6; + fmt.mantissa_bits = 12; + fmt.sign = true; + + if (!convert_to_custom_float_format( + arr_points[0].x, + &fmt, + &arr_points[0].custom_float_x)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + arr_points[0].offset, + &fmt, + &arr_points[0].custom_float_offset)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + arr_points[0].slope, + &fmt, + &arr_points[0].custom_float_slope)) { + BREAK_TO_DEBUGGER(); + return false; + } + + fmt.mantissa_bits = 10; + fmt.sign = false; + + if (!convert_to_custom_float_format( + arr_points[1].x, + &fmt, + &arr_points[1].custom_float_x)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + arr_points[1].y, + &fmt, + &arr_points[1].custom_float_y)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + arr_points[2].slope, + &fmt, + &arr_points[2].custom_float_slope)) { + BREAK_TO_DEBUGGER(); + return false; + } + + fmt.mantissa_bits = 12; + fmt.sign = true; + + while (i != hw_points_num) { + if (!convert_to_custom_float_format( + rgb->red, + &fmt, + &rgb->red_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + rgb->green, + &fmt, + &rgb->green_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + rgb->blue, + &fmt, + &rgb->blue_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + rgb->delta_red, + &fmt, + &rgb->delta_red_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + rgb->delta_green, + &fmt, + &rgb->delta_green_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + rgb->delta_blue, + &fmt, + &rgb->delta_blue_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + ++rgb; + ++i; + } + + return true; +} + +bool calculate_regamma_params(struct pwl_params *params, + const struct core_gamma *ramp, + const struct core_surface *surface) +{ + struct gamma_curve *arr_curve_points = params->arr_curve_points; + struct curve_points *arr_points = params->arr_points; + struct pwl_result_data *rgb_resulted = params->rgb_resulted; + struct dividers dividers; + + struct hw_x_point *coordinates_x = NULL; + struct pwl_float_data *rgb_user = NULL ; + struct pwl_float_data_ex *rgb_regamma = NULL; + struct pwl_float_data *rgb_oem = NULL; + struct gamma_pixel *axix_x_256 = NULL; + struct pixel_gamma_point *coeff128_oem = NULL; + struct pixel_gamma_point *coeff128 = NULL; + + + bool ret = false; + + coordinates_x = dm_alloc(sizeof(*coordinates_x)*(256 + 3)); + if (!coordinates_x) + goto coordinates_x_alloc_fail; + rgb_user = dm_alloc(sizeof(*rgb_user) * (FLOAT_GAMMA_RAMP_MAX + 3)); + if (!rgb_user) + goto rgb_user_alloc_fail; + rgb_regamma = dm_alloc(sizeof(*rgb_regamma) * (256 + 3)); + if (!rgb_regamma) + goto rgb_regamma_alloc_fail; + rgb_oem = dm_alloc(sizeof(*rgb_oem) * (FLOAT_GAMMA_RAMP_MAX + 3)); + if (!rgb_oem) + goto rgb_oem_alloc_fail; + axix_x_256 = dm_alloc(sizeof(*axix_x_256) * (256 + 3)); + if (!axix_x_256) + goto axix_x_256_alloc_fail; + coeff128_oem = dm_alloc(sizeof(*coeff128_oem) * (256 + 3)); + if (!coeff128_oem) + goto coeff128_oem_alloc_fail; + coeff128 = dm_alloc(sizeof(*coeff128) * (256 + 3)); + if (!coeff128) + goto coeff128_alloc_fail; + + dividers.divider1 = dal_fixed31_32_from_fraction(3, 2); + dividers.divider2 = dal_fixed31_32_from_int(2); + dividers.divider3 = dal_fixed31_32_from_fraction(5, 2); + + build_evenly_distributed_points( + axix_x_256, + 256, + dal_fixed31_32_one, + dividers); + + scale_gamma(rgb_user, ramp, dividers); + + setup_distribution_points(arr_curve_points, arr_points, + ¶ms->hw_points_num, coordinates_x); + + build_regamma_curve(rgb_regamma, rgb_oem, coeff128_oem, + ramp, surface, params->hw_points_num, + coordinates_x, axix_x_256, dividers); + + map_regamma_hw_to_x_user(coeff128, rgb_oem, rgb_resulted, rgb_user, + coordinates_x, axix_x_256, &ramp->public, rgb_regamma, + dividers, params->hw_points_num, surface); + + build_new_custom_resulted_curve(rgb_resulted, params->hw_points_num); + + rebuild_curve_configuration_magic( + arr_points, + rgb_resulted, + coordinates_x, + params->hw_points_num); + + convert_to_custom_float(rgb_resulted, arr_points, + params->hw_points_num); + + ret = true; + + dm_free(coeff128); +coeff128_alloc_fail: + dm_free(coeff128_oem); +coeff128_oem_alloc_fail: + dm_free(axix_x_256); +axix_x_256_alloc_fail: + dm_free(rgb_oem); +rgb_oem_alloc_fail: + dm_free(rgb_regamma); +rgb_regamma_alloc_fail: + dm_free(rgb_user); +rgb_user_alloc_fail: + dm_free(coordinates_x); +coordinates_x_alloc_fail: + return ret; + +} + diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c new file mode 100644 index 000000000000..f7638f84421b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -0,0 +1,1846 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + */ + +#include "dm_services.h" + +#include "dc.h" + +#include "core_status.h" +#include "core_types.h" +#include "hw_sequencer.h" + +#include "resource.h" + +#include "clock_source.h" +#include "dc_bios_types.h" + +#include "bandwidth_calcs.h" +#include "bios_parser_interface.h" +#include "include/irq_service_interface.h" +#include "transform.h" +#include "timing_generator.h" +#include "virtual/virtual_link_encoder.h" + +#include "link_hwss.h" +#include "link_encoder.h" + +#include "dc_link_ddc.h" +#include "dm_helpers.h" +#include "mem_input.h" + +/******************************************************************************* + * Private structures + ******************************************************************************/ + +struct dc_target_sync_report { + uint32_t h_count; + uint32_t v_count; +}; + +/******************************************************************************* + * Private functions + ******************************************************************************/ +static void destroy_links(struct core_dc *dc) +{ + uint32_t i; + + for (i = 0; i < dc->link_count; i++) { + if (NULL != dc->links[i]) + link_destroy(&dc->links[i]); + } +} + +static bool create_links( + struct core_dc *dc, + uint32_t num_virtual_links) +{ + int i; + int connectors_num; + struct dc_bios *bios = dc->ctx->dc_bios; + + dc->link_count = 0; + + connectors_num = bios->funcs->get_connectors_number(bios); + + if (connectors_num > ENUM_ID_COUNT) { + dm_error( + "DC: Number of connectors %d exceeds maximum of %d!\n", + connectors_num, + ENUM_ID_COUNT); + return false; + } + + if (connectors_num == 0 && num_virtual_links == 0) { + dm_error("DC: Number of connectors is zero!\n"); + } + + dm_output_to_console( + "DC: %s: connectors_num: physical:%d, virtual:%d\n", + __func__, + connectors_num, + num_virtual_links); + + for (i = 0; i < connectors_num; i++) { + struct link_init_data link_init_params = {0}; + struct core_link *link; + + link_init_params.ctx = dc->ctx; + link_init_params.connector_index = i; + link_init_params.link_index = dc->link_count; + link_init_params.dc = dc; + link = link_create(&link_init_params); + + if (link) { + dc->links[dc->link_count] = link; + link->dc = dc; + ++dc->link_count; + } else { + dm_error("DC: failed to create link!\n"); + } + } + + for (i = 0; i < num_virtual_links; i++) { + struct core_link *link = dm_alloc(sizeof(*link)); + struct encoder_init_data enc_init = {0}; + + if (link == NULL) { + BREAK_TO_DEBUGGER(); + goto failed_alloc; + } + + link->ctx = dc->ctx; + link->dc = dc; + link->public.connector_signal = SIGNAL_TYPE_VIRTUAL; + link->link_id.type = OBJECT_TYPE_CONNECTOR; + link->link_id.id = CONNECTOR_ID_VIRTUAL; + link->link_id.enum_id = ENUM_ID_1; + link->link_enc = dm_alloc(sizeof(*link->link_enc)); + + enc_init.ctx = dc->ctx; + enc_init.channel = CHANNEL_ID_UNKNOWN; + enc_init.hpd_source = HPD_SOURCEID_UNKNOWN; + enc_init.transmitter = TRANSMITTER_UNKNOWN; + enc_init.connector = link->link_id; + enc_init.encoder.type = OBJECT_TYPE_ENCODER; + enc_init.encoder.id = ENCODER_ID_INTERNAL_VIRTUAL; + enc_init.encoder.enum_id = ENUM_ID_1; + virtual_link_encoder_construct(link->link_enc, &enc_init); + + link->public.link_index = dc->link_count; + dc->links[dc->link_count] = link; + dc->link_count++; + } + + return true; + +failed_alloc: + return false; +} + +static bool stream_adjust_vmin_vmax(struct dc *dc, + const struct dc_stream **stream, int num_streams, + int vmin, int vmax) +{ + /* TODO: Support multiple streams */ + struct core_dc *core_dc = DC_TO_CORE(dc); + struct core_stream *core_stream = DC_STREAM_TO_CORE(stream[0]); + int i = 0; + bool ret = false; + struct pipe_ctx *pipes; + unsigned int underlay_idx = core_dc->res_pool->underlay_pipe_index; + + for (i = 0; i < MAX_PIPES; i++) { + if (core_dc->current_context->res_ctx.pipe_ctx[i].stream == core_stream + && i != underlay_idx) { + + pipes = &core_dc->current_context->res_ctx.pipe_ctx[i]; + core_dc->hwss.set_drr(&pipes, 1, vmin, vmax); + + /* build and update the info frame */ + resource_build_info_frame(pipes); + core_dc->hwss.update_info_frame(pipes); + + ret = true; + } + } + + return ret; +} + + +static bool set_gamut_remap(struct dc *dc, + const struct dc_stream **stream, int num_streams) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + struct core_stream *core_stream = DC_STREAM_TO_CORE(stream[0]); + int i = 0; + bool ret = false; + struct pipe_ctx *pipes; + + for (i = 0; i < MAX_PIPES; i++) { + if (core_dc->current_context->res_ctx.pipe_ctx[i].stream + == core_stream) { + + pipes = &core_dc->current_context->res_ctx.pipe_ctx[i]; + core_dc->hwss.set_plane_config(core_dc, pipes, + &core_dc->current_context->res_ctx); + ret = true; + } + } + + return ret; +} + +/* This function is not expected to fail, proper implementation of + * validation will prevent this from ever being called for unsupported + * configurations. + */ +static void stream_update_scaling( + const struct dc *dc, + const struct dc_stream *dc_stream, + const struct rect *src, + const struct rect *dst) +{ + struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); + struct core_dc *core_dc = DC_TO_CORE(dc); + struct validate_context *cur_ctx = core_dc->current_context; + int i, j; + + if (src) + stream->public.src = *src; + + if (dst) + stream->public.dst = *dst; + + for (i = 0; i < cur_ctx->target_count; i++) { + struct core_target *target = cur_ctx->targets[i]; + struct dc_target_status *status = &cur_ctx->target_status[i]; + + for (j = 0; j < target->public.stream_count; j++) { + if (target->public.streams[j] != dc_stream) + continue; + + if (status->surface_count) + if (!dc_commit_surfaces_to_target( + &core_dc->public, + status->surfaces, + status->surface_count, + &target->public)) + /* Need to debug validation */ + BREAK_TO_DEBUGGER(); + + return; + } + } +} + +static bool set_backlight(struct dc *dc, unsigned int backlight_level, + unsigned int frame_ramp, const struct dc_stream *stream) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + int i; + + if (stream->sink->sink_signal == SIGNAL_TYPE_EDP) { + for (i = 0; i < core_dc->link_count; i++) + dc_link_set_backlight_level(&core_dc->links[i]->public, + backlight_level, frame_ramp, stream); + } + + return true; + +} + +static bool init_dmcu_backlight_settings(struct dc *dc) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + int i; + + for (i = 0; i < core_dc->link_count; i++) + dc_link_init_dmcu_backlight_settings + (&core_dc->links[i]->public); + + return true; +} + + +static bool set_abm_level(struct dc *dc, unsigned int abm_level) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + int i; + + for (i = 0; i < core_dc->link_count; i++) + dc_link_set_abm_level(&core_dc->links[i]->public, + abm_level); + + return true; +} + +static bool set_psr_enable(struct dc *dc, bool enable) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + int i; + + for (i = 0; i < core_dc->link_count; i++) + dc_link_set_psr_enable(&core_dc->links[i]->public, + enable); + + return true; +} + + +static bool setup_psr(struct dc *dc, const struct dc_stream *stream) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + struct core_stream *core_stream = DC_STREAM_TO_CORE(stream); + struct pipe_ctx *pipes; + int i; + unsigned int underlay_idx = core_dc->res_pool->underlay_pipe_index; + + for (i = 0; i < core_dc->link_count; i++) { + if (core_stream->sink->link == core_dc->links[i]) + dc_link_setup_psr(&core_dc->links[i]->public, + stream); + } + + for (i = 0; i < MAX_PIPES; i++) { + if (core_dc->current_context->res_ctx.pipe_ctx[i].stream + == core_stream && i != underlay_idx) { + pipes = &core_dc->current_context->res_ctx.pipe_ctx[i]; + core_dc->hwss.set_static_screen_control(&pipes, 1, + 0x182); + } + } + + return true; +} + +static void set_drive_settings(struct dc *dc, + struct link_training_settings *lt_settings) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + int i; + + for (i = 0; i < core_dc->link_count; i++) + dc_link_dp_set_drive_settings(&core_dc->links[i]->public, + lt_settings); +} + +static void perform_link_training(struct dc *dc, + struct dc_link_settings *link_setting, + bool skip_video_pattern) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + int i; + + for (i = 0; i < core_dc->link_count; i++) + dc_link_dp_perform_link_training( + &core_dc->links[i]->public, + link_setting, + skip_video_pattern); +} + +static void set_preferred_link_settings(struct dc *dc, + struct dc_link_settings *link_setting) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + int i; + + for (i = 0; i < core_dc->link_count; i++) { + core_dc->links[i]->public.verified_link_cap.lane_count = + link_setting->lane_count; + core_dc->links[i]->public.verified_link_cap.link_rate = + link_setting->link_rate; + } +} + +static void enable_hpd(const struct dc_link *link) +{ + dc_link_dp_enable_hpd(link); +} + +static void disable_hpd(const struct dc_link *link) +{ + dc_link_dp_disable_hpd(link); +} + + +static void set_test_pattern( + const struct dc_link *link, + enum dp_test_pattern test_pattern, + const struct link_training_settings *p_link_settings, + const unsigned char *p_custom_pattern, + unsigned int cust_pattern_size) +{ + if (link != NULL) + dc_link_dp_set_test_pattern( + link, + test_pattern, + p_link_settings, + p_custom_pattern, + cust_pattern_size); +} + +static void allocate_dc_stream_funcs(struct core_dc *core_dc) +{ + core_dc->public.stream_funcs.stream_update_scaling = stream_update_scaling; + if (core_dc->hwss.set_drr != NULL) { + core_dc->public.stream_funcs.adjust_vmin_vmax = + stream_adjust_vmin_vmax; + } + + core_dc->public.stream_funcs.set_gamut_remap = + set_gamut_remap; + + core_dc->public.stream_funcs.set_backlight = + set_backlight; + + core_dc->public.stream_funcs.init_dmcu_backlight_settings = + init_dmcu_backlight_settings; + + core_dc->public.stream_funcs.set_abm_level = + set_abm_level; + + core_dc->public.stream_funcs.set_psr_enable = + set_psr_enable; + + core_dc->public.stream_funcs.setup_psr = + setup_psr; + + core_dc->public.link_funcs.set_drive_settings = + set_drive_settings; + + core_dc->public.link_funcs.perform_link_training = + perform_link_training; + + core_dc->public.link_funcs.set_preferred_link_settings = + set_preferred_link_settings; + + core_dc->public.link_funcs.enable_hpd = + enable_hpd; + + core_dc->public.link_funcs.disable_hpd = + disable_hpd; + + core_dc->public.link_funcs.set_test_pattern = + set_test_pattern; +} + +static void destruct(struct core_dc *dc) +{ + resource_validate_ctx_destruct(dc->current_context); + + dm_free(dc->temp_flip_context); + dc->temp_flip_context = NULL; + + destroy_links(dc); + + dc_destroy_resource_pool(dc); + + if (dc->ctx->gpio_service) + dal_gpio_service_destroy(&dc->ctx->gpio_service); + + if (dc->ctx->i2caux) + dal_i2caux_destroy(&dc->ctx->i2caux); + + if (dc->ctx->created_bios) + dal_bios_parser_destroy(&dc->ctx->dc_bios); + + if (dc->ctx->logger) + dal_logger_destroy(&dc->ctx->logger); + + dm_free(dc->current_context); + dc->current_context = NULL; + + dm_free(dc->ctx); + dc->ctx = NULL; +} + +static bool construct(struct core_dc *dc, + const struct dc_init_data *init_params) +{ + struct dal_logger *logger; + struct dc_context *dc_ctx = dm_alloc(sizeof(*dc_ctx)); + enum dce_version dc_version = DCE_VERSION_UNKNOWN; + + if (!dc_ctx) { + dm_error("%s: failed to create ctx\n", __func__); + goto ctx_fail; + } + + dc->current_context = dm_alloc(sizeof(*dc->current_context)); + dc->temp_flip_context = dm_alloc(sizeof(*dc->temp_flip_context)); + + if (!dc->current_context || !dc->temp_flip_context) { + dm_error("%s: failed to create validate ctx\n", __func__); + goto val_ctx_fail; + } + + dc_ctx->cgs_device = init_params->cgs_device; + dc_ctx->driver_context = init_params->driver; + dc_ctx->dc = &dc->public; + dc_ctx->asic_id = init_params->asic_id; + + /* Create logger */ + logger = dal_logger_create(dc_ctx); + + if (!logger) { + /* can *not* call logger. call base driver 'print error' */ + dm_error("%s: failed to create Logger!\n", __func__); + goto logger_fail; + } + dc_ctx->logger = logger; + dc->ctx = dc_ctx; + dc->ctx->dce_environment = init_params->dce_environment; + + dc_version = resource_parse_asic_id(init_params->asic_id); + dc->ctx->dce_version = dc_version; + + /* Resource should construct all asic specific resources. + * This should be the only place where we need to parse the asic id + */ + if (init_params->vbios_override) + dc_ctx->dc_bios = init_params->vbios_override; + else { + /* Create BIOS parser */ + struct bp_init_data bp_init_data; + bp_init_data.ctx = dc_ctx; + bp_init_data.bios = init_params->asic_id.atombios_base_address; + + dc_ctx->dc_bios = dal_bios_parser_create( + &bp_init_data, dc_version); + + if (!dc_ctx->dc_bios) { + ASSERT_CRITICAL(false); + goto bios_fail; + } + + dc_ctx->created_bios = true; + } + + /* Create I2C AUX */ + dc_ctx->i2caux = dal_i2caux_create(dc_ctx); + + if (!dc_ctx->i2caux) { + ASSERT_CRITICAL(false); + goto failed_to_create_i2caux; + } + + /* Create GPIO service */ + dc_ctx->gpio_service = dal_gpio_service_create( + dc_version, + dc_ctx->dce_environment, + dc_ctx); + + if (!dc_ctx->gpio_service) { + ASSERT_CRITICAL(false); + goto gpio_fail; + } + + dc->res_pool = dc_create_resource_pool( + dc, + init_params->num_virtual_links, + dc_version, + init_params->asic_id); + if (!dc->res_pool) + goto create_resource_fail; + + if (!create_links(dc, init_params->num_virtual_links)) + goto create_links_fail; + + allocate_dc_stream_funcs(dc); + + return true; + + /**** error handling here ****/ +create_links_fail: +create_resource_fail: +gpio_fail: +failed_to_create_i2caux: +bios_fail: +logger_fail: +val_ctx_fail: +ctx_fail: + destruct(dc); + return false; +} + +/* +void ProgramPixelDurationV(unsigned int pixelClockInKHz ) +{ + fixed31_32 pixel_duration = Fixed31_32(100000000, pixelClockInKHz) * 10; + unsigned int pixDurationInPico = round(pixel_duration); + + DPG_PIPE_ARBITRATION_CONTROL1 arb_control; + + arb_control.u32All = ReadReg (mmDPGV0_PIPE_ARBITRATION_CONTROL1); + arb_control.bits.PIXEL_DURATION = pixDurationInPico; + WriteReg (mmDPGV0_PIPE_ARBITRATION_CONTROL1, arb_control.u32All); + + arb_control.u32All = ReadReg (mmDPGV1_PIPE_ARBITRATION_CONTROL1); + arb_control.bits.PIXEL_DURATION = pixDurationInPico; + WriteReg (mmDPGV1_PIPE_ARBITRATION_CONTROL1, arb_control.u32All); + + WriteReg (mmDPGV0_PIPE_ARBITRATION_CONTROL2, 0x4000800); + WriteReg (mmDPGV0_REPEATER_PROGRAM, 0x11); + + WriteReg (mmDPGV1_PIPE_ARBITRATION_CONTROL2, 0x4000800); + WriteReg (mmDPGV1_REPEATER_PROGRAM, 0x11); +} +*/ + +/******************************************************************************* + * Public functions + ******************************************************************************/ + +struct dc *dc_create(const struct dc_init_data *init_params) + { + struct core_dc *core_dc = dm_alloc(sizeof(*core_dc)); + unsigned int full_pipe_count; + + if (NULL == core_dc) + goto alloc_fail; + + if (false == construct(core_dc, init_params)) + goto construct_fail; + + /*TODO: separate HW and SW initialization*/ + core_dc->hwss.init_hw(core_dc); + + full_pipe_count = core_dc->res_pool->pipe_count; + if (core_dc->res_pool->underlay_pipe_index >= 0) + full_pipe_count--; + core_dc->public.caps.max_targets = dm_min( + full_pipe_count, + core_dc->res_pool->stream_enc_count); + + core_dc->public.caps.max_links = core_dc->link_count; + core_dc->public.caps.max_audios = core_dc->res_pool->audio_count; + + core_dc->public.config = init_params->flags; + + dm_logger_write(core_dc->ctx->logger, LOG_DC, + "Display Core initialized\n"); + + + /* TODO: missing feature to be enabled */ + core_dc->public.debug.disable_dfs_bypass = true; + + return &core_dc->public; + +construct_fail: + dm_free(core_dc); + +alloc_fail: + return NULL; +} + +void dc_destroy(struct dc **dc) +{ + struct core_dc *core_dc = DC_TO_CORE(*dc); + destruct(core_dc); + dm_free(core_dc); + *dc = NULL; +} + +static bool is_validation_required( + const struct core_dc *dc, + const struct dc_validation_set set[], + int set_count) +{ + const struct validate_context *context = dc->current_context; + int i, j; + + if (context->target_count != set_count) + return true; + + for (i = 0; i < set_count; i++) { + + if (set[i].surface_count != context->target_status[i].surface_count) + return true; + if (!is_target_unchanged(DC_TARGET_TO_CORE(set[i].target), context->targets[i])) + return true; + + for (j = 0; j < set[i].surface_count; j++) { + struct dc_surface temp_surf = { 0 }; + + temp_surf = *context->target_status[i].surfaces[j]; + temp_surf.clip_rect = set[i].surfaces[j]->clip_rect; + temp_surf.dst_rect.x = set[i].surfaces[j]->dst_rect.x; + temp_surf.dst_rect.y = set[i].surfaces[j]->dst_rect.y; + + if (memcmp(&temp_surf, set[i].surfaces[j], sizeof(temp_surf)) != 0) + return true; + } + } + + return false; +} + +bool dc_validate_resources( + const struct dc *dc, + const struct dc_validation_set set[], + uint8_t set_count) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + enum dc_status result = DC_ERROR_UNEXPECTED; + struct validate_context *context; + + if (!is_validation_required(core_dc, set, set_count)) + return true; + + context = dm_alloc(sizeof(struct validate_context)); + if(context == NULL) + goto context_alloc_fail; + + result = core_dc->res_pool->funcs->validate_with_context( + core_dc, set, set_count, context); + + resource_validate_ctx_destruct(context); + dm_free(context); + +context_alloc_fail: + if (result != DC_OK) { + dm_logger_write(core_dc->ctx->logger, LOG_WARNING, + "%s:resource validation failed, dc_status:%d\n", + __func__, + result); + } + + return (result == DC_OK); + +} + +bool dc_validate_guaranteed( + const struct dc *dc, + const struct dc_target *dc_target) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + enum dc_status result = DC_ERROR_UNEXPECTED; + struct validate_context *context; + + context = dm_alloc(sizeof(struct validate_context)); + if (context == NULL) + goto context_alloc_fail; + + result = core_dc->res_pool->funcs->validate_guaranteed( + core_dc, dc_target, context); + + resource_validate_ctx_destruct(context); + dm_free(context); + +context_alloc_fail: + if (result != DC_OK) { + dm_logger_write(core_dc->ctx->logger, LOG_WARNING, + "%s:guaranteed validation failed, dc_status:%d\n", + __func__, + result); + } + + return (result == DC_OK); +} + +static void program_timing_sync( + struct core_dc *core_dc, + struct validate_context *ctx) +{ + int i, j; + int group_index = 0; + int pipe_count = ctx->res_ctx.pool->pipe_count; + struct pipe_ctx *unsynced_pipes[MAX_PIPES] = { NULL }; + + for (i = 0; i < pipe_count; i++) { + if (!ctx->res_ctx.pipe_ctx[i].stream || ctx->res_ctx.pipe_ctx[i].top_pipe) + continue; + + unsynced_pipes[i] = &ctx->res_ctx.pipe_ctx[i]; + } + + for (i = 0; i < pipe_count; i++) { + int group_size = 1; + struct pipe_ctx *pipe_set[MAX_PIPES]; + + if (!unsynced_pipes[i]) + continue; + + pipe_set[0] = unsynced_pipes[i]; + unsynced_pipes[i] = NULL; + + /* Add tg to the set, search rest of the tg's for ones with + * same timing, add all tgs with same timing to the group + */ + for (j = i + 1; j < pipe_count; j++) { + if (!unsynced_pipes[j]) + continue; + + if (resource_are_streams_timing_synchronizable( + unsynced_pipes[j]->stream, + pipe_set[0]->stream)) { + pipe_set[group_size] = unsynced_pipes[j]; + unsynced_pipes[j] = NULL; + group_size++; + } + } + + /* set first unblanked pipe as master */ + for (j = 0; j < group_size; j++) { + struct pipe_ctx *temp; + + if (!pipe_set[j]->tg->funcs->is_blanked(pipe_set[j]->tg)) { + if (j == 0) + break; + + temp = pipe_set[0]; + pipe_set[0] = pipe_set[j]; + pipe_set[j] = temp; + break; + } + } + + /* remove any other unblanked pipes as they have already been synced */ + for (j = j + 1; j < group_size; j++) { + if (!pipe_set[j]->tg->funcs->is_blanked(pipe_set[j]->tg)) { + group_size--; + pipe_set[j] = pipe_set[group_size]; + j--; + } + } + + if (group_size > 1) { + core_dc->hwss.enable_timing_synchronization( + core_dc, group_index, group_size, pipe_set); + group_index++; + } + } +} + +static bool targets_changed( + struct core_dc *dc, + struct dc_target *targets[], + uint8_t target_count) +{ + uint8_t i; + + if (target_count != dc->current_context->target_count) + return true; + + for (i = 0; i < dc->current_context->target_count; i++) { + if (&dc->current_context->targets[i]->public != targets[i]) + return true; + } + + return false; +} + +static void fill_display_configs( + const struct validate_context *context, + struct dm_pp_display_configuration *pp_display_cfg) +{ + uint8_t i, j, k; + uint8_t num_cfgs = 0; + + for (i = 0; i < context->target_count; i++) { + const struct core_target *target = context->targets[i]; + + for (j = 0; j < target->public.stream_count; j++) { + const struct core_stream *stream = + DC_STREAM_TO_CORE(target->public.streams[j]); + struct dm_pp_single_disp_config *cfg = + &pp_display_cfg->disp_configs[num_cfgs]; + const struct pipe_ctx *pipe_ctx = NULL; + + for (k = 0; k < MAX_PIPES; k++) + if (stream == + context->res_ctx.pipe_ctx[k].stream) { + pipe_ctx = &context->res_ctx.pipe_ctx[k]; + break; + } + + ASSERT(pipe_ctx != NULL); + + num_cfgs++; + cfg->signal = pipe_ctx->stream->signal; + cfg->pipe_idx = pipe_ctx->pipe_idx; + cfg->src_height = stream->public.src.height; + cfg->src_width = stream->public.src.width; + cfg->ddi_channel_mapping = + stream->sink->link->ddi_channel_mapping.raw; + cfg->transmitter = + stream->sink->link->link_enc->transmitter; + cfg->link_settings.lane_count = stream->sink->link->public.cur_link_settings.lane_count; + cfg->link_settings.link_rate = stream->sink->link->public.cur_link_settings.link_rate; + cfg->link_settings.link_spread = stream->sink->link->public.cur_link_settings.link_spread; + cfg->sym_clock = stream->phy_pix_clk; + /* Round v_refresh*/ + cfg->v_refresh = stream->public.timing.pix_clk_khz * 1000; + cfg->v_refresh /= stream->public.timing.h_total; + cfg->v_refresh = (cfg->v_refresh + stream->public.timing.v_total / 2) + / stream->public.timing.v_total; + } + } + pp_display_cfg->display_count = num_cfgs; +} + +static uint32_t get_min_vblank_time_us(const struct validate_context *context) +{ + uint8_t i, j; + uint32_t min_vertical_blank_time = -1; + + for (i = 0; i < context->target_count; i++) { + const struct core_target *target = context->targets[i]; + + for (j = 0; j < target->public.stream_count; j++) { + const struct dc_stream *stream = + target->public.streams[j]; + uint32_t vertical_blank_in_pixels = 0; + uint32_t vertical_blank_time = 0; + + vertical_blank_in_pixels = stream->timing.h_total * + (stream->timing.v_total + - stream->timing.v_addressable); + vertical_blank_time = vertical_blank_in_pixels + * 1000 / stream->timing.pix_clk_khz; + if (min_vertical_blank_time > vertical_blank_time) + min_vertical_blank_time = vertical_blank_time; + } + } + return min_vertical_blank_time; +} + +static int determine_sclk_from_bounding_box( + const struct core_dc *dc, + int required_sclk) +{ + int i; + + /* + * Some asics do not give us sclk levels, so we just report the actual + * required sclk + */ + if (dc->sclk_lvls.num_levels == 0) + return required_sclk; + + for (i = 0; i < dc->sclk_lvls.num_levels; i++) { + if (dc->sclk_lvls.clocks_in_khz[i] >= required_sclk) + return dc->sclk_lvls.clocks_in_khz[i]; + } + /* + * even maximum level could not satisfy requirement, this + * is unexpected at this stage, should have been caught at + * validation time + */ + ASSERT(0); + return dc->sclk_lvls.clocks_in_khz[dc->sclk_lvls.num_levels - 1]; +} + +void pplib_apply_display_requirements( + struct core_dc *dc, + const struct validate_context *context, + struct dm_pp_display_configuration *pp_display_cfg) +{ + pp_display_cfg->all_displays_in_sync = + context->bw_results.all_displays_in_sync; + pp_display_cfg->nb_pstate_switch_disable = + context->bw_results.nbp_state_change_enable == false; + pp_display_cfg->cpu_cc6_disable = + context->bw_results.cpuc_state_change_enable == false; + pp_display_cfg->cpu_pstate_disable = + context->bw_results.cpup_state_change_enable == false; + pp_display_cfg->cpu_pstate_separation_time = + context->bw_results.blackout_recovery_time_us; + + pp_display_cfg->min_memory_clock_khz = context->bw_results.required_yclk + / MEMORY_TYPE_MULTIPLIER; + + pp_display_cfg->min_engine_clock_khz = determine_sclk_from_bounding_box( + dc, + context->bw_results.required_sclk); + + pp_display_cfg->min_engine_clock_deep_sleep_khz + = context->bw_results.required_sclk_deep_sleep; + + pp_display_cfg->avail_mclk_switch_time_us = + get_min_vblank_time_us(context); + /* TODO: dce11.2*/ + pp_display_cfg->avail_mclk_switch_time_in_disp_active_us = 0; + + pp_display_cfg->disp_clk_khz = context->bw_results.dispclk_khz; + + fill_display_configs(context, pp_display_cfg); + + /* TODO: is this still applicable?*/ + if (pp_display_cfg->display_count == 1) { + const struct dc_crtc_timing *timing = + &context->targets[0]->public.streams[0]->timing; + + pp_display_cfg->crtc_index = + pp_display_cfg->disp_configs[0].pipe_idx; + pp_display_cfg->line_time_in_us = timing->h_total * 1000 + / timing->pix_clk_khz; + } + + if (memcmp(&dc->prev_display_config, pp_display_cfg, sizeof( + struct dm_pp_display_configuration)) != 0) + dm_pp_apply_display_requirements(dc->ctx, pp_display_cfg); + + dc->prev_display_config = *pp_display_cfg; + +} + +bool dc_commit_targets( + struct dc *dc, + struct dc_target *targets[], + uint8_t target_count) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc_bios *dcb = core_dc->ctx->dc_bios; + enum dc_status result = DC_ERROR_UNEXPECTED; + struct validate_context *context; + struct dc_validation_set set[MAX_TARGETS]; + int i, j, k; + + if (false == targets_changed(core_dc, targets, target_count)) + return DC_OK; + + dm_logger_write(core_dc->ctx->logger, LOG_DC, + "%s: %d targets\n", + __func__, + target_count); + + for (i = 0; i < target_count; i++) { + struct dc_target *target = targets[i]; + + dc_target_log(target, + core_dc->ctx->logger, + LOG_DC); + + set[i].target = targets[i]; + set[i].surface_count = 0; + + } + + context = dm_alloc(sizeof(struct validate_context)); + if (context == NULL) + goto context_alloc_fail; + + result = core_dc->res_pool->funcs->validate_with_context(core_dc, set, target_count, context); + if (result != DC_OK){ + dm_logger_write(core_dc->ctx->logger, LOG_ERROR, + "%s: Context validation failed! dc_status:%d\n", + __func__, + result); + BREAK_TO_DEBUGGER(); + resource_validate_ctx_destruct(context); + goto fail; + } + + if (!dcb->funcs->is_accelerated_mode(dcb)) { + core_dc->hwss.enable_accelerated_mode(core_dc); + } + + if (result == DC_OK) { + result = core_dc->hwss.apply_ctx_to_hw(core_dc, context); + } + + program_timing_sync(core_dc, context); + + for (i = 0; i < context->target_count; i++) { + struct dc_target *dc_target = &context->targets[i]->public; + struct core_sink *sink = DC_SINK_TO_CORE(dc_target->streams[0]->sink); + + for (j = 0; j < context->target_status[i].surface_count; j++) { + const struct dc_surface *dc_surface = + context->target_status[i].surfaces[j]; + + for (k = 0; k < context->res_ctx.pool->pipe_count; k++) { + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[k]; + + if (dc_surface != &pipe->surface->public + || !dc_surface->visible) + continue; + + pipe->tg->funcs->set_blank(pipe->tg, false); + } + } + + CONN_MSG_MODE(sink->link, "{%dx%d, %dx%d@%dKhz}", + dc_target->streams[0]->timing.h_addressable, + dc_target->streams[0]->timing.v_addressable, + dc_target->streams[0]->timing.h_total, + dc_target->streams[0]->timing.v_total, + dc_target->streams[0]->timing.pix_clk_khz); + } + + pplib_apply_display_requirements(core_dc, + context, &context->pp_display_cfg); + + resource_validate_ctx_destruct(core_dc->current_context); + + dm_free(core_dc->current_context); + core_dc->current_context = context; + + return (result == DC_OK); + +fail: + dm_free(context); + +context_alloc_fail: + return (result == DC_OK); +} + +bool dc_pre_update_surfaces_to_target( + struct dc *dc, + const struct dc_surface *const *new_surfaces, + uint8_t new_surface_count, + struct dc_target *dc_target) +{ + int i, j; + struct core_dc *core_dc = DC_TO_CORE(dc); + uint32_t prev_disp_clk = core_dc->current_context->bw_results.dispclk_khz; + struct core_target *target = DC_TARGET_TO_CORE(dc_target); + struct dc_target_status *target_status = NULL; + struct validate_context *context; + struct validate_context *temp_context; + bool ret = true; + + pre_surface_trace(dc, new_surfaces, new_surface_count); + + if (core_dc->current_context->target_count == 0) + return false; + + /* Cannot commit surface to a target that is not commited */ + for (i = 0; i < core_dc->current_context->target_count; i++) + if (target == core_dc->current_context->targets[i]) + break; + + if (i == core_dc->current_context->target_count) + return false; + + target_status = &core_dc->current_context->target_status[i]; + + if (new_surface_count == target_status->surface_count) { + bool skip_pre = true; + + for (i = 0; i < target_status->surface_count; i++) { + struct dc_surface temp_surf = { 0 }; + + temp_surf = *target_status->surfaces[i]; + temp_surf.clip_rect = new_surfaces[i]->clip_rect; + temp_surf.dst_rect.x = new_surfaces[i]->dst_rect.x; + temp_surf.dst_rect.y = new_surfaces[i]->dst_rect.y; + + if (memcmp(&temp_surf, new_surfaces[i], sizeof(temp_surf)) != 0) { + skip_pre = false; + break; + } + } + + if (skip_pre) + return true; + } + + context = dm_alloc(sizeof(struct validate_context)); + + if (!context) { + dm_error("%s: failed to create validate ctx\n", __func__); + ret = false; + goto val_ctx_fail; + } + + resource_validate_ctx_copy_construct(core_dc->current_context, context); + + dm_logger_write(core_dc->ctx->logger, LOG_DC, + "%s: commit %d surfaces to target 0x%x\n", + __func__, + new_surface_count, + dc_target); + + if (!resource_attach_surfaces_to_context( + new_surfaces, new_surface_count, dc_target, context)) { + BREAK_TO_DEBUGGER(); + ret = false; + goto unexpected_fail; + } + + for (i = 0; i < new_surface_count; i++) + for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { + if (context->res_ctx.pipe_ctx[j].surface != + DC_SURFACE_TO_CORE(new_surfaces[i])) + continue; + + resource_build_scaling_params( + new_surfaces[i], &context->res_ctx.pipe_ctx[j]); + + if (dc->debug.surface_visual_confirm) { + context->res_ctx.pipe_ctx[j].scl_data.recout.height -= 2; + context->res_ctx.pipe_ctx[j].scl_data.recout.width -= 2; + } + } + + if (core_dc->res_pool->funcs->validate_bandwidth(core_dc, context) != DC_OK) { + BREAK_TO_DEBUGGER(); + ret = false; + goto unexpected_fail; + } + + if (core_dc->res_pool->funcs->apply_clk_constraints) { + temp_context = core_dc->res_pool->funcs->apply_clk_constraints( + core_dc, + context); + if (!temp_context) { + dm_error("%s:failed apply clk constraints\n", __func__); + ret = false; + goto unexpected_fail; + } + resource_validate_ctx_destruct(context); + dm_free(context); + context = temp_context; + } + + if (prev_disp_clk < context->bw_results.dispclk_khz) { + pplib_apply_display_requirements(core_dc, context, + &context->pp_display_cfg); + core_dc->hwss.set_display_clock(context); + core_dc->current_context->bw_results.dispclk_khz = + context->bw_results.dispclk_khz; + } + + for (i = 0; i < new_surface_count; i++) + for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { + if (context->res_ctx.pipe_ctx[j].surface != + DC_SURFACE_TO_CORE(new_surfaces[i])) + continue; + + core_dc->hwss.prepare_pipe_for_context( + core_dc, + &context->res_ctx.pipe_ctx[j], + context); + + if (!new_surfaces[i]->visible) + context->res_ctx.pipe_ctx[j].tg->funcs->set_blank( + context->res_ctx.pipe_ctx[j].tg, true); + } + +unexpected_fail: + resource_validate_ctx_destruct(context); + dm_free(context); +val_ctx_fail: + + return ret; +} + +bool dc_post_update_surfaces_to_target(struct dc *dc) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + int i; + + post_surface_trace(dc); + + for (i = 0; i < core_dc->current_context->res_ctx.pool->pipe_count; i++) + if (core_dc->current_context->res_ctx.pipe_ctx[i].stream == NULL) + core_dc->hwss.power_down_front_end( + core_dc, &core_dc->current_context->res_ctx.pipe_ctx[i]); + + if (core_dc->res_pool->funcs->validate_bandwidth(core_dc, core_dc->current_context) + != DC_OK) { + BREAK_TO_DEBUGGER(); + return false; + } + + core_dc->hwss.set_bandwidth(core_dc); + + pplib_apply_display_requirements( + core_dc, core_dc->current_context, &core_dc->current_context->pp_display_cfg); + + return true; +} + +bool dc_commit_surfaces_to_target( + struct dc *dc, + const struct dc_surface **new_surfaces, + uint8_t new_surface_count, + struct dc_target *dc_target) +{ + struct dc_surface_update updates[MAX_SURFACES] = { 0 }; + struct dc_flip_addrs flip_addr[MAX_SURFACES] = { 0 }; + struct dc_plane_info plane_info[MAX_SURFACES] = { 0 }; + struct dc_scaling_info scaling_info[MAX_SURFACES] = { 0 }; + int i; + + if (!dc_pre_update_surfaces_to_target( + dc, new_surfaces, new_surface_count, dc_target)) + return false; + + for (i = 0; i < new_surface_count; i++) { + updates[i].surface = new_surfaces[i]; + updates[i].gamma = (struct dc_gamma *)new_surfaces[i]->gamma_correction; + + flip_addr[i].address = new_surfaces[i]->address; + flip_addr[i].flip_immediate = new_surfaces[i]->flip_immediate; + plane_info[i].color_space = new_surfaces[i]->color_space; + plane_info[i].format = new_surfaces[i]->format; + plane_info[i].plane_size = new_surfaces[i]->plane_size; + plane_info[i].rotation = new_surfaces[i]->rotation; + plane_info[i].horizontal_mirror = new_surfaces[i]->horizontal_mirror; + plane_info[i].stereo_format = new_surfaces[i]->stereo_format; + plane_info[i].tiling_info = new_surfaces[i]->tiling_info; + plane_info[i].visible = new_surfaces[i]->visible; + scaling_info[i].scaling_quality = new_surfaces[i]->scaling_quality; + scaling_info[i].src_rect = new_surfaces[i]->src_rect; + scaling_info[i].dst_rect = new_surfaces[i]->dst_rect; + scaling_info[i].clip_rect = new_surfaces[i]->clip_rect; + + updates[i].flip_addr = &flip_addr[i]; + updates[i].plane_info = &plane_info[i]; + updates[i].scaling_info = &scaling_info[i]; + } + dc_update_surfaces_for_target(dc, updates, new_surface_count, dc_target); + + return dc_post_update_surfaces_to_target(dc); +} + +void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *updates, + int surface_count, struct dc_target *dc_target) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + struct validate_context *context = core_dc->temp_flip_context; + int i, j; + bool is_new_pipe_surface[MAX_SURFACES]; + const struct dc_surface *new_surfaces[MAX_SURFACES] = { 0 }; + + update_surface_trace(dc, updates, surface_count); + + *context = *core_dc->current_context; + + for (i = 0; i < context->res_ctx.pool->pipe_count; i++) { + struct pipe_ctx *cur_pipe = &context->res_ctx.pipe_ctx[i]; + + if (cur_pipe->top_pipe) + cur_pipe->top_pipe = + &context->res_ctx.pipe_ctx[cur_pipe->top_pipe->pipe_idx]; + + if (cur_pipe->bottom_pipe) + cur_pipe->bottom_pipe = + &context->res_ctx.pipe_ctx[cur_pipe->bottom_pipe->pipe_idx]; + } + + for (j = 0; j < MAX_SURFACES; j++) + is_new_pipe_surface[j] = true; + + for (i = 0 ; i < surface_count; i++) { + struct core_surface *surface = DC_SURFACE_TO_CORE(updates[i].surface); + + new_surfaces[i] = updates[i].surface; + for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; + + if (surface == pipe_ctx->surface) + is_new_pipe_surface[i] = false; + } + } + + if (dc_target) { + struct core_target *target = DC_TARGET_TO_CORE(dc_target); + + if (core_dc->current_context->target_count == 0) + return; + + /* Cannot commit surface to a target that is not commited */ + for (i = 0; i < core_dc->current_context->target_count; i++) + if (target == core_dc->current_context->targets[i]) + break; + if (i == core_dc->current_context->target_count) + return; + + if (!resource_attach_surfaces_to_context( + new_surfaces, surface_count, dc_target, context)) { + BREAK_TO_DEBUGGER(); + return; + } + } + + for (i = 0; i < surface_count; i++) { + struct core_surface *surface = DC_SURFACE_TO_CORE(updates[i].surface); + + for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; + + if (pipe_ctx->surface != surface) + continue; + + if (updates[i].flip_addr) { + surface->public.address = updates[i].flip_addr->address; + surface->public.flip_immediate = + updates[i].flip_addr->flip_immediate; + } + + if (updates[i].plane_info || updates[i].scaling_info + || is_new_pipe_surface[j]) { + + if (updates[i].plane_info) { + surface->public.color_space = + updates[i].plane_info->color_space; + surface->public.format = + updates[i].plane_info->format; + surface->public.plane_size = + updates[i].plane_info->plane_size; + surface->public.rotation = + updates[i].plane_info->rotation; + surface->public.horizontal_mirror = + updates[i].plane_info->horizontal_mirror; + surface->public.stereo_format = + updates[i].plane_info->stereo_format; + surface->public.tiling_info = + updates[i].plane_info->tiling_info; + surface->public.visible = + updates[i].plane_info->visible; + } + + if (updates[i].scaling_info) { + surface->public.scaling_quality = + updates[i].scaling_info->scaling_quality; + surface->public.dst_rect = + updates[i].scaling_info->dst_rect; + surface->public.src_rect = + updates[i].scaling_info->src_rect; + surface->public.clip_rect = + updates[i].scaling_info->clip_rect; + } + + resource_build_scaling_params(updates[i].surface, pipe_ctx); + if (dc->debug.surface_visual_confirm) { + pipe_ctx->scl_data.recout.height -= 2; + pipe_ctx->scl_data.recout.width -= 2; + } + } + } + } + + for (i = 0; i < surface_count; i++) { + struct core_surface *surface = DC_SURFACE_TO_CORE(updates[i].surface); + bool apply_ctx = false; + + for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; + + if (pipe_ctx->surface != surface) + continue; + + if (updates[i].flip_addr) { + core_dc->hwss.pipe_control_lock( + core_dc->hwseq, + pipe_ctx->pipe_idx, + PIPE_LOCK_CONTROL_SURFACE, + true); + core_dc->hwss.update_plane_addr(core_dc, pipe_ctx); + } + + if (updates[i].plane_info || updates[i].scaling_info + || is_new_pipe_surface[j]) { + + apply_ctx = true; + + if (!pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) { + core_dc->hwss.pipe_control_lock( + core_dc->hwseq, + pipe_ctx->pipe_idx, + PIPE_LOCK_CONTROL_SURFACE | + PIPE_LOCK_CONTROL_GRAPHICS | + PIPE_LOCK_CONTROL_SCL | + PIPE_LOCK_CONTROL_BLENDER | + PIPE_LOCK_CONTROL_MODE, + true); + } + } + + if (updates[i].gamma) + core_dc->hwss.prepare_pipe_for_context( + core_dc, pipe_ctx, context); + } + if (apply_ctx) + core_dc->hwss.apply_ctx_for_surface(core_dc, surface, context); + } + + for (i = context->res_ctx.pool->pipe_count - 1; i >= 0; i--) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + + for (j = 0; j < surface_count; j++) { + if (updates[j].surface == &pipe_ctx->surface->public) { + if (!pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) { + core_dc->hwss.pipe_control_lock( + core_dc->hwseq, + pipe_ctx->pipe_idx, + PIPE_LOCK_CONTROL_GRAPHICS | + PIPE_LOCK_CONTROL_SCL | + PIPE_LOCK_CONTROL_BLENDER | + PIPE_LOCK_CONTROL_SURFACE, + false); + } + break; + } + } + } + + core_dc->temp_flip_context = core_dc->current_context; + core_dc->current_context = context; +} + +uint8_t dc_get_current_target_count(const struct dc *dc) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + return core_dc->current_context->target_count; +} + +struct dc_target *dc_get_target_at_index(const struct dc *dc, uint8_t i) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + if (i < core_dc->current_context->target_count) + return &(core_dc->current_context->targets[i]->public); + return NULL; +} + +const struct dc_link *dc_get_link_at_index(const struct dc *dc, uint32_t link_index) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + return &core_dc->links[link_index]->public; +} + +const struct graphics_object_id dc_get_link_id_at_index( + struct dc *dc, uint32_t link_index) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + return core_dc->links[link_index]->link_id; +} + +const struct ddc_service *dc_get_ddc_at_index( + struct dc *dc, uint32_t link_index) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + return core_dc->links[link_index]->ddc; +} + +enum dc_irq_source dc_get_hpd_irq_source_at_index( + struct dc *dc, uint32_t link_index) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + return core_dc->links[link_index]->public.irq_source_hpd; +} + +const struct audio **dc_get_audios(struct dc *dc) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + return (const struct audio **)core_dc->res_pool->audios; +} + +void dc_flip_surface_addrs( + struct dc *dc, + const struct dc_surface *const surfaces[], + struct dc_flip_addrs flip_addrs[], + uint32_t count) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + int i, j; + + for (i = 0; i < count; i++) { + struct core_surface *surface = DC_SURFACE_TO_CORE(surfaces[i]); + + surface->public.address = flip_addrs[i].address; + surface->public.flip_immediate = flip_addrs[i].flip_immediate; + + for (j = 0; j < core_dc->res_pool->pipe_count; j++) { + struct pipe_ctx *pipe_ctx = &core_dc->current_context->res_ctx.pipe_ctx[j]; + + if (pipe_ctx->surface != surface) + continue; + + core_dc->hwss.update_plane_addr(core_dc, pipe_ctx); + } + } +} + +enum dc_irq_source dc_interrupt_to_irq_source( + struct dc *dc, + uint32_t src_id, + uint32_t ext_id) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + return dal_irq_service_to_irq_source(core_dc->res_pool->irqs, src_id, ext_id); +} + +void dc_interrupt_set(const struct dc *dc, enum dc_irq_source src, bool enable) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + dal_irq_service_set(core_dc->res_pool->irqs, src, enable); +} + +void dc_interrupt_ack(struct dc *dc, enum dc_irq_source src) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + dal_irq_service_ack(core_dc->res_pool->irqs, src); +} + +void dc_set_power_state( + struct dc *dc, + enum dc_acpi_cm_power_state power_state, + enum dc_video_power_state video_power_state) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + + core_dc->previous_power_state = core_dc->current_power_state; + core_dc->current_power_state = video_power_state; + + switch (power_state) { + case DC_ACPI_CM_POWER_STATE_D0: + core_dc->hwss.init_hw(core_dc); + break; + default: + /* NULL means "reset/release all DC targets" */ + dc_commit_targets(dc, NULL, 0); + + core_dc->hwss.power_down(core_dc); + + /* Zero out the current context so that on resume we start with + * clean state, and dc hw programming optimizations will not + * cause any trouble. + */ + memset(core_dc->current_context, 0, + sizeof(*core_dc->current_context)); + + core_dc->current_context->res_ctx.pool = core_dc->res_pool; + + break; + } + +} + +void dc_resume(const struct dc *dc) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + + uint32_t i; + + for (i = 0; i < core_dc->link_count; i++) + core_link_resume(core_dc->links[i]); +} + +bool dc_read_dpcd( + struct dc *dc, + uint32_t link_index, + uint32_t address, + uint8_t *data, + uint32_t size) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + + struct core_link *link = core_dc->links[link_index]; + enum ddc_result r = dal_ddc_service_read_dpcd_data( + link->ddc, + address, + data, + size); + return r == DDC_RESULT_SUCESSFULL; +} + +bool dc_write_dpcd( + struct dc *dc, + uint32_t link_index, + uint32_t address, + const uint8_t *data, + uint32_t size) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + + struct core_link *link = core_dc->links[link_index]; + + enum ddc_result r = dal_ddc_service_write_dpcd_data( + link->ddc, + address, + data, + size); + return r == DDC_RESULT_SUCESSFULL; +} + +bool dc_submit_i2c( + struct dc *dc, + uint32_t link_index, + struct i2c_command *cmd) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + + struct core_link *link = core_dc->links[link_index]; + struct ddc_service *ddc = link->ddc; + + return dal_i2caux_submit_i2c_command( + ddc->ctx->i2caux, + ddc->ddc_pin, + cmd); +} + +static bool link_add_remote_sink_helper(struct core_link *core_link, struct dc_sink *sink) +{ + struct dc_link *dc_link = &core_link->public; + + if (dc_link->sink_count >= MAX_SINKS_PER_LINK) { + BREAK_TO_DEBUGGER(); + return false; + } + + dc_sink_retain(sink); + + dc_link->remote_sinks[dc_link->sink_count] = sink; + dc_link->sink_count++; + + return true; +} + +struct dc_sink *dc_link_add_remote_sink( + const struct dc_link *link, + const uint8_t *edid, + int len, + struct dc_sink_init_data *init_data) +{ + struct dc_sink *dc_sink; + enum dc_edid_status edid_status; + struct core_link *core_link = DC_LINK_TO_LINK(link); + + if (len > MAX_EDID_BUFFER_SIZE) { + dm_error("Max EDID buffer size breached!\n"); + return NULL; + } + + if (!init_data) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + if (!init_data->link) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dc_sink = dc_sink_create(init_data); + + if (!dc_sink) + return NULL; + + memmove(dc_sink->dc_edid.raw_edid, edid, len); + dc_sink->dc_edid.length = len; + + if (!link_add_remote_sink_helper( + core_link, + dc_sink)) + goto fail_add_sink; + + edid_status = dm_helpers_parse_edid_caps( + core_link->ctx, + &dc_sink->dc_edid, + &dc_sink->edid_caps); + + if (edid_status != EDID_OK) + goto fail; + + return dc_sink; +fail: + dc_link_remove_remote_sink(link, dc_sink); +fail_add_sink: + dc_sink_release(dc_sink); + return NULL; +} + +void dc_link_set_sink(const struct dc_link *link, struct dc_sink *sink) +{ + struct core_link *core_link = DC_LINK_TO_LINK(link); + struct dc_link *dc_link = &core_link->public; + + dc_link->local_sink = sink; + + if (sink == NULL) { + dc_link->type = dc_connection_none; + } else { + dc_link->type = dc_connection_single; + } +} + +void dc_link_remove_remote_sink(const struct dc_link *link, const struct dc_sink *sink) +{ + int i; + struct core_link *core_link = DC_LINK_TO_LINK(link); + struct dc_link *dc_link = &core_link->public; + + if (!link->sink_count) { + BREAK_TO_DEBUGGER(); + return; + } + + for (i = 0; i < dc_link->sink_count; i++) { + if (dc_link->remote_sinks[i] == sink) { + dc_sink_release(sink); + dc_link->remote_sinks[i] = NULL; + + /* shrink array to remove empty place */ + while (i < dc_link->sink_count - 1) { + dc_link->remote_sinks[i] = dc_link->remote_sinks[i+1]; + i++; + } + + dc_link->sink_count--; + return; + } + } +} + +const struct dc_stream_status *dc_stream_get_status( + const struct dc_stream *dc_stream) +{ + struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); + + return &stream->status; +} + +bool dc_init_dchub(struct dc *dc, struct dchub_init_data *dh_data) +{ + int i; + struct core_dc *core_dc = DC_TO_CORE(dc); + struct mem_input *mi = NULL; + + for (i = 0; i < core_dc->res_pool->pipe_count; i++) { + if (core_dc->res_pool->mis[i] != NULL) { + mi = core_dc->res_pool->mis[i]; + break; + } + } + if (mi == NULL) { + dm_error("no mem_input!\n"); + return false; + } + + if (mi->funcs->mem_input_update_dchub) + mi->funcs->mem_input_update_dchub(mi, dh_data); + else + ASSERT(mi->funcs->mem_input_update_dchub); + + + return true; + +} + diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c new file mode 100644 index 000000000000..8ca0f1e0369a --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c @@ -0,0 +1,270 @@ +/* + * dc_debug.c + * + * Created on: Nov 3, 2016 + * Author: yonsun + */ + +#include "dm_services.h" + +#include "dc.h" + +#include "core_status.h" +#include "core_types.h" +#include "hw_sequencer.h" + +#include "resource.h" + +#define SURFACE_TRACE(...) do {\ + if (dc->debug.surface_trace) \ + dm_logger_write(logger, \ + LOG_IF_TRACE, \ + ##__VA_ARGS__); \ +} while (0) + +void pre_surface_trace( + const struct dc *dc, + const struct dc_surface *const *surfaces, + int surface_count) +{ + int i; + struct core_dc *core_dc = DC_TO_CORE(dc); + struct dal_logger *logger = core_dc->ctx->logger; + + for (i = 0; i < surface_count; i++) { + const struct dc_surface *surface = surfaces[i]; + + SURFACE_TRACE("Surface %d:\n", i); + + SURFACE_TRACE( + "surface->visible = %d;\n" + "surface->flip_immediate = %d;\n" + "surface->address.type = %d;\n" + "surface->address.grph.addr.quad_part = 0x%X;\n" + "surface->address.grph.meta_addr.quad_part = 0x%X;\n" + "surface->scaling_quality.h_taps = %d;\n" + "surface->scaling_quality.v_taps = %d;\n" + "surface->scaling_quality.h_taps_c = %d;\n" + "surface->scaling_quality.v_taps_c = %d;\n", + surface->visible, + surface->flip_immediate, + surface->address.type, + surface->address.grph.addr.quad_part, + surface->address.grph.meta_addr.quad_part, + surface->scaling_quality.h_taps, + surface->scaling_quality.v_taps, + surface->scaling_quality.h_taps_c, + surface->scaling_quality.v_taps_c); + + SURFACE_TRACE( + "surface->src_rect.x = %d;\n" + "surface->src_rect.y = %d;\n" + "surface->src_rect.width = %d;\n" + "surface->src_rect.height = %d;\n" + "surface->dst_rect.x = %d;\n" + "surface->dst_rect.y = %d;\n" + "surface->dst_rect.width = %d;\n" + "surface->dst_rect.height = %d;\n" + "surface->clip_rect.x = %d;\n" + "surface->clip_rect.y = %d;\n" + "surface->clip_rect.width = %d;\n" + "surface->clip_rect.height = %d;\n", + surface->src_rect.x, + surface->src_rect.y, + surface->src_rect.width, + surface->src_rect.height, + surface->dst_rect.x, + surface->dst_rect.y, + surface->dst_rect.width, + surface->dst_rect.height, + surface->clip_rect.x, + surface->clip_rect.y, + surface->clip_rect.width, + surface->clip_rect.height); + + SURFACE_TRACE( + "surface->plane_size.grph.surface_size.x = %d;\n" + "surface->plane_size.grph.surface_size.y = %d;\n" + "surface->plane_size.grph.surface_size.width = %d;\n" + "surface->plane_size.grph.surface_size.height = %d;\n" + "surface->plane_size.grph.surface_pitch = %d;\n" + "surface->plane_size.grph.meta_pitch = %d;\n", + surface->plane_size.grph.surface_size.x, + surface->plane_size.grph.surface_size.y, + surface->plane_size.grph.surface_size.width, + surface->plane_size.grph.surface_size.height, + surface->plane_size.grph.surface_pitch, + surface->plane_size.grph.meta_pitch); + + + SURFACE_TRACE( + "surface->tiling_info.gfx8.num_banks = %d;\n" + "surface->tiling_info.gfx8.bank_width = %d;\n" + "surface->tiling_info.gfx8.bank_width_c = %d;\n" + "surface->tiling_info.gfx8.bank_height = %d;\n" + "surface->tiling_info.gfx8.bank_height_c = %d;\n" + "surface->tiling_info.gfx8.tile_aspect = %d;\n" + "surface->tiling_info.gfx8.tile_aspect_c = %d;\n" + "surface->tiling_info.gfx8.tile_split = %d;\n" + "surface->tiling_info.gfx8.tile_split_c = %d;\n" + "surface->tiling_info.gfx8.tile_mode = %d;\n" + "surface->tiling_info.gfx8.tile_mode_c = %d;\n", + surface->tiling_info.gfx8.num_banks, + surface->tiling_info.gfx8.bank_width, + surface->tiling_info.gfx8.bank_width_c, + surface->tiling_info.gfx8.bank_height, + surface->tiling_info.gfx8.bank_height_c, + surface->tiling_info.gfx8.tile_aspect, + surface->tiling_info.gfx8.tile_aspect_c, + surface->tiling_info.gfx8.tile_split, + surface->tiling_info.gfx8.tile_split_c, + surface->tiling_info.gfx8.tile_mode, + surface->tiling_info.gfx8.tile_mode_c); + + SURFACE_TRACE( + "surface->tiling_info.gfx8.pipe_config = %d;\n" + "surface->tiling_info.gfx8.array_mode = %d;\n" + "surface->color_space = %d;\n" + "surface->dcc.enable = %d;\n" + "surface->format = %d;\n" + "surface->rotation = %d;\n" + "surface->stereo_format = %d;\n", + surface->tiling_info.gfx8.pipe_config, + surface->tiling_info.gfx8.array_mode, + surface->color_space, + surface->dcc.enable, + surface->format, + surface->rotation, + surface->stereo_format); + SURFACE_TRACE("\n"); + } + SURFACE_TRACE("\n"); +} + +void update_surface_trace( + const struct dc *dc, + const struct dc_surface_update *updates, + int surface_count) +{ + int i; + struct core_dc *core_dc = DC_TO_CORE(dc); + struct dal_logger *logger = core_dc->ctx->logger; + + for (i = 0; i < surface_count; i++) { + const struct dc_surface_update *update = &updates[i]; + + SURFACE_TRACE("Update %d\n", i); + if (update->flip_addr) { + SURFACE_TRACE("flip_addr->address.type = %d;\n" + "flip_addr->address.grph.addr.quad_part = 0x%X;\n" + "flip_addr->address.grph.meta_addr.quad_part = 0x%X;\n" + "flip_addr->flip_immediate = %d;\n", + update->flip_addr->address.type, + update->flip_addr->address.grph.addr.quad_part, + update->flip_addr->address.grph.meta_addr.quad_part, + update->flip_addr->flip_immediate); + } + + if (update->plane_info) { + SURFACE_TRACE( + "plane_info->color_space = %d;\n" + "plane_info->format = %d;\n" + "plane_info->plane_size.grph.meta_pitch = %d;\n" + "plane_info->plane_size.grph.surface_pitch = %d;\n" + "plane_info->plane_size.grph.surface_size.height = %d;\n" + "plane_info->plane_size.grph.surface_size.width = %d;\n" + "plane_info->plane_size.grph.surface_size.x = %d;\n" + "plane_info->plane_size.grph.surface_size.y = %d;\n" + "plane_info->rotation = %d;\n", + update->plane_info->color_space, + update->plane_info->format, + update->plane_info->plane_size.grph.meta_pitch, + update->plane_info->plane_size.grph.surface_pitch, + update->plane_info->plane_size.grph.surface_size.height, + update->plane_info->plane_size.grph.surface_size.width, + update->plane_info->plane_size.grph.surface_size.x, + update->plane_info->plane_size.grph.surface_size.y, + update->plane_info->rotation, + update->plane_info->stereo_format); + + SURFACE_TRACE( + "plane_info->tiling_info.gfx8.num_banks = %d;\n" + "plane_info->tiling_info.gfx8.bank_width = %d;\n" + "plane_info->tiling_info.gfx8.bank_width_c = %d;\n" + "plane_info->tiling_info.gfx8.bank_height = %d;\n" + "plane_info->tiling_info.gfx8.bank_height_c = %d;\n" + "plane_info->tiling_info.gfx8.tile_aspect = %d;\n" + "plane_info->tiling_info.gfx8.tile_aspect_c = %d;\n" + "plane_info->tiling_info.gfx8.tile_split = %d;\n" + "plane_info->tiling_info.gfx8.tile_split_c = %d;\n" + "plane_info->tiling_info.gfx8.tile_mode = %d;\n" + "plane_info->tiling_info.gfx8.tile_mode_c = %d;\n", + update->plane_info->tiling_info.gfx8.num_banks, + update->plane_info->tiling_info.gfx8.bank_width, + update->plane_info->tiling_info.gfx8.bank_width_c, + update->plane_info->tiling_info.gfx8.bank_height, + update->plane_info->tiling_info.gfx8.bank_height_c, + update->plane_info->tiling_info.gfx8.tile_aspect, + update->plane_info->tiling_info.gfx8.tile_aspect_c, + update->plane_info->tiling_info.gfx8.tile_split, + update->plane_info->tiling_info.gfx8.tile_split_c, + update->plane_info->tiling_info.gfx8.tile_mode, + update->plane_info->tiling_info.gfx8.tile_mode_c); + + SURFACE_TRACE( + "plane_info->tiling_info.gfx8.pipe_config = %d;\n" + "plane_info->tiling_info.gfx8.array_mode = %d;\n" + "plane_info->visible = %d;\n", + update->plane_info->tiling_info.gfx8.pipe_config, + update->plane_info->tiling_info.gfx8.array_mode, + update->plane_info->visible); + } + + if (update->scaling_info) { + SURFACE_TRACE( + "scaling_info->src_rect.x = %d;\n" + "scaling_info->src_rect.y = %d;\n" + "scaling_info->src_rect.width = %d;\n" + "scaling_info->src_rect.height = %d;\n" + "scaling_info->dst_rect.x = %d;\n" + "scaling_info->dst_rect.y = %d;\n" + "scaling_info->dst_rect.width = %d;\n" + "scaling_info->dst_rect.height = %d;\n" + "scaling_info->clip_rect.x = %d;\n" + "scaling_info->clip_rect.y = %d;\n" + "scaling_info->clip_rect.width = %d;\n" + "scaling_info->clip_rect.height = %d;\n" + "scaling_info->scaling_quality.h_taps = %d;\n" + "scaling_info->scaling_quality.v_taps = %d;\n" + "scaling_info->scaling_quality.h_taps_c = %d;\n" + "scaling_info->scaling_quality.v_taps_c = %d;\n", + update->scaling_info->src_rect.x, + update->scaling_info->src_rect.y, + update->scaling_info->src_rect.width, + update->scaling_info->src_rect.height, + update->scaling_info->dst_rect.x, + update->scaling_info->dst_rect.y, + update->scaling_info->dst_rect.width, + update->scaling_info->dst_rect.height, + update->scaling_info->clip_rect.x, + update->scaling_info->clip_rect.y, + update->scaling_info->clip_rect.width, + update->scaling_info->clip_rect.height, + update->scaling_info->scaling_quality.h_taps, + update->scaling_info->scaling_quality.v_taps, + update->scaling_info->scaling_quality.h_taps_c, + update->scaling_info->scaling_quality.v_taps_c); + } + SURFACE_TRACE("\n"); + } + SURFACE_TRACE("\n"); +} + +void post_surface_trace(const struct dc *dc) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + struct dal_logger *logger = core_dc->ctx->logger; + + SURFACE_TRACE("post surface process.\n"); + +} diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c new file mode 100644 index 000000000000..d5cffa51ca96 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c @@ -0,0 +1,93 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "core_types.h" +#include "core_dc.h" +#include "timing_generator.h" +#include "hw_sequencer.h" + +/* used as index in array of black_color_format */ +enum black_color_format { + BLACK_COLOR_FORMAT_RGB_FULLRANGE = 0, + BLACK_COLOR_FORMAT_RGB_LIMITED, + BLACK_COLOR_FORMAT_YUV_TV, + BLACK_COLOR_FORMAT_YUV_CV, + BLACK_COLOR_FORMAT_YUV_SUPER_AA, + BLACK_COLOR_FORMAT_DEBUG, +}; + +static const struct tg_color black_color_format[] = { + /* BlackColorFormat_RGB_FullRange */ + {0, 0, 0}, + /* BlackColorFormat_RGB_Limited */ + {0x40, 0x40, 0x40}, + /* BlackColorFormat_YUV_TV */ + {0x200, 0x40, 0x200}, + /* BlackColorFormat_YUV_CV */ + {0x1f4, 0x40, 0x1f4}, + /* BlackColorFormat_YUV_SuperAA */ + {0x1a2, 0x20, 0x1a2}, + /* visual confirm debug */ + {0xff, 0xff, 0}, +}; + +void color_space_to_black_color( + const struct core_dc *dc, + enum dc_color_space colorspace, + struct tg_color *black_color) +{ + if (dc->public.debug.surface_visual_confirm) { + *black_color = + black_color_format[BLACK_COLOR_FORMAT_DEBUG]; + return; + } + + switch (colorspace) { + case COLOR_SPACE_YPBPR601: + *black_color = black_color_format[BLACK_COLOR_FORMAT_YUV_TV]; + break; + + case COLOR_SPACE_YPBPR709: + case COLOR_SPACE_YCBCR601: + case COLOR_SPACE_YCBCR709: + case COLOR_SPACE_YCBCR601_LIMITED: + case COLOR_SPACE_YCBCR709_LIMITED: + *black_color = black_color_format[BLACK_COLOR_FORMAT_YUV_CV]; + break; + + case COLOR_SPACE_SRGB_LIMITED: + *black_color = + black_color_format[BLACK_COLOR_FORMAT_RGB_LIMITED]; + break; + + default: + /* fefault is sRGB black (full range). */ + *black_color = + black_color_format[BLACK_COLOR_FORMAT_RGB_FULLRANGE]; + /* default is sRGB black 0. */ + break; + } +} diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c new file mode 100644 index 000000000000..70a25546de1e --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -0,0 +1,1899 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "dm_helpers.h" +#include "dc.h" +#include "core_dc.h" +#include "grph_object_id.h" +#include "gpio_service_interface.h" +#include "core_status.h" +#include "dc_link_dp.h" +#include "dc_link_ddc.h" +#include "link_hwss.h" +#include "stream_encoder.h" +#include "link_encoder.h" +#include "hw_sequencer.h" +#include "resource.h" +#include "fixed31_32.h" +#include "include/asic_capability_interface.h" + +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_enum.h" +#include "dce/dce_11_0_sh_mask.h" + +#ifndef mmDMCU_STATUS__UC_IN_RESET__SHIFT +#define mmDMCU_STATUS__UC_IN_RESET__SHIFT 0x0 +#endif + +#ifndef mmDMCU_STATUS__UC_IN_RESET_MASK +#define mmDMCU_STATUS__UC_IN_RESET_MASK 0x00000001L +#endif + +#define LINK_INFO(...) \ + dm_logger_write(dc_ctx->logger, LOG_HW_HOTPLUG, \ + __VA_ARGS__) + +/******************************************************************************* + * Private structures + ******************************************************************************/ + +enum { + LINK_RATE_REF_FREQ_IN_MHZ = 27, + PEAK_FACTOR_X1000 = 1006 +}; + +/******************************************************************************* + * Private functions + ******************************************************************************/ +static void destruct(struct core_link *link) +{ + int i; + + if (link->ddc) + dal_ddc_service_destroy(&link->ddc); + + if(link->link_enc) + link->link_enc->funcs->destroy(&link->link_enc); + + if (link->public.local_sink) + dc_sink_release(link->public.local_sink); + + for (i = 0; i < link->public.sink_count; ++i) + dc_sink_release(link->public.remote_sinks[i]); +} + +static struct gpio *get_hpd_gpio(const struct core_link *link) +{ + enum bp_result bp_result; + struct dc_bios *dcb = link->ctx->dc_bios; + struct graphics_object_hpd_info hpd_info; + struct gpio_pin_info pin_info; + + if (dcb->funcs->get_hpd_info(dcb, link->link_id, &hpd_info) != BP_RESULT_OK) + return NULL; + + bp_result = dcb->funcs->get_gpio_pin_info(dcb, + hpd_info.hpd_int_gpio_uid, &pin_info); + + if (bp_result != BP_RESULT_OK) { + ASSERT(bp_result == BP_RESULT_NORECORD); + return NULL; + } + + return dal_gpio_service_create_irq( + link->ctx->gpio_service, + pin_info.offset, + pin_info.mask); +} + +/* + * Function: program_hpd_filter + * + * @brief + * Programs HPD filter on associated HPD line + * + * @param [in] delay_on_connect_in_ms: Connect filter timeout + * @param [in] delay_on_disconnect_in_ms: Disconnect filter timeout + * + * @return + * true on success, false otherwise + */ +static bool program_hpd_filter( + const struct core_link *link) +{ + bool result = false; + + struct gpio *hpd; + + int delay_on_connect_in_ms = 0; + int delay_on_disconnect_in_ms = 0; + + /* Verify feature is supported */ + switch (link->public.connector_signal) { + case SIGNAL_TYPE_DVI_SINGLE_LINK: + case SIGNAL_TYPE_DVI_DUAL_LINK: + case SIGNAL_TYPE_HDMI_TYPE_A: + /* Program hpd filter */ + delay_on_connect_in_ms = 500; + delay_on_disconnect_in_ms = 100; + break; + case SIGNAL_TYPE_DISPLAY_PORT: + case SIGNAL_TYPE_DISPLAY_PORT_MST: + /* Program hpd filter to allow DP signal to settle */ + /* 500: not able to detect MST <-> SST switch as HPD is low for + * only 100ms on DELL U2413 + * 0: some passive dongle still show aux mode instead of i2c + * 20-50:not enough to hide bouncing HPD with passive dongle. + * also see intermittent i2c read issues. + */ + delay_on_connect_in_ms = 80; + delay_on_disconnect_in_ms = 0; + break; + case SIGNAL_TYPE_LVDS: + case SIGNAL_TYPE_EDP: + default: + /* Don't program hpd filter */ + return false; + } + + /* Obtain HPD handle */ + hpd = get_hpd_gpio(link); + + if (!hpd) + return result; + + /* Setup HPD filtering */ + if (dal_gpio_open(hpd, GPIO_MODE_INTERRUPT) == GPIO_RESULT_OK) { + struct gpio_hpd_config config; + + config.delay_on_connect = delay_on_connect_in_ms; + config.delay_on_disconnect = delay_on_disconnect_in_ms; + + dal_irq_setup_hpd_filter(hpd, &config); + + dal_gpio_close(hpd); + + result = true; + } else { + ASSERT_CRITICAL(false); + } + + /* Release HPD handle */ + dal_gpio_destroy_irq(&hpd); + + return result; +} + +static bool detect_sink(struct core_link *link, enum dc_connection_type *type) +{ + uint32_t is_hpd_high = 0; + struct gpio *hpd_pin; + + /* todo: may need to lock gpio access */ + hpd_pin = get_hpd_gpio(link); + if (hpd_pin == NULL) + goto hpd_gpio_failure; + + dal_gpio_open(hpd_pin, GPIO_MODE_INTERRUPT); + dal_gpio_get_value(hpd_pin, &is_hpd_high); + dal_gpio_close(hpd_pin); + dal_gpio_destroy_irq(&hpd_pin); + + if (is_hpd_high) { + *type = dc_connection_single; + /* TODO: need to do the actual detection */ + } else { + *type = dc_connection_none; + } + + return true; + +hpd_gpio_failure: + return false; +} + +enum ddc_transaction_type get_ddc_transaction_type( + enum signal_type sink_signal) +{ + enum ddc_transaction_type transaction_type = DDC_TRANSACTION_TYPE_NONE; + + switch (sink_signal) { + case SIGNAL_TYPE_DVI_SINGLE_LINK: + case SIGNAL_TYPE_DVI_DUAL_LINK: + case SIGNAL_TYPE_HDMI_TYPE_A: + case SIGNAL_TYPE_LVDS: + case SIGNAL_TYPE_RGB: + transaction_type = DDC_TRANSACTION_TYPE_I2C; + break; + + case SIGNAL_TYPE_DISPLAY_PORT: + case SIGNAL_TYPE_EDP: + transaction_type = DDC_TRANSACTION_TYPE_I2C_OVER_AUX; + break; + + case SIGNAL_TYPE_DISPLAY_PORT_MST: + /* MST does not use I2COverAux, but there is the + * SPECIAL use case for "immediate dwnstrm device + * access" (EPR#370830). */ + transaction_type = DDC_TRANSACTION_TYPE_I2C_OVER_AUX; + break; + + default: + break; + } + + return transaction_type; +} + +static enum signal_type get_basic_signal_type( + struct graphics_object_id encoder, + struct graphics_object_id downstream) +{ + if (downstream.type == OBJECT_TYPE_CONNECTOR) { + switch (downstream.id) { + case CONNECTOR_ID_SINGLE_LINK_DVII: + switch (encoder.id) { + case ENCODER_ID_INTERNAL_DAC1: + case ENCODER_ID_INTERNAL_KLDSCP_DAC1: + case ENCODER_ID_INTERNAL_DAC2: + case ENCODER_ID_INTERNAL_KLDSCP_DAC2: + return SIGNAL_TYPE_RGB; + default: + return SIGNAL_TYPE_DVI_SINGLE_LINK; + } + break; + case CONNECTOR_ID_DUAL_LINK_DVII: + { + switch (encoder.id) { + case ENCODER_ID_INTERNAL_DAC1: + case ENCODER_ID_INTERNAL_KLDSCP_DAC1: + case ENCODER_ID_INTERNAL_DAC2: + case ENCODER_ID_INTERNAL_KLDSCP_DAC2: + return SIGNAL_TYPE_RGB; + default: + return SIGNAL_TYPE_DVI_DUAL_LINK; + } + } + break; + case CONNECTOR_ID_SINGLE_LINK_DVID: + return SIGNAL_TYPE_DVI_SINGLE_LINK; + case CONNECTOR_ID_DUAL_LINK_DVID: + return SIGNAL_TYPE_DVI_DUAL_LINK; + case CONNECTOR_ID_VGA: + return SIGNAL_TYPE_RGB; + case CONNECTOR_ID_HDMI_TYPE_A: + return SIGNAL_TYPE_HDMI_TYPE_A; + case CONNECTOR_ID_LVDS: + return SIGNAL_TYPE_LVDS; + case CONNECTOR_ID_DISPLAY_PORT: + return SIGNAL_TYPE_DISPLAY_PORT; + case CONNECTOR_ID_EDP: + return SIGNAL_TYPE_EDP; + default: + return SIGNAL_TYPE_NONE; + } + } else if (downstream.type == OBJECT_TYPE_ENCODER) { + switch (downstream.id) { + case ENCODER_ID_EXTERNAL_NUTMEG: + case ENCODER_ID_EXTERNAL_TRAVIS: + return SIGNAL_TYPE_DISPLAY_PORT; + default: + return SIGNAL_TYPE_NONE; + } + } + + return SIGNAL_TYPE_NONE; +} + +/* + * @brief + * Check whether there is a dongle on DP connector + */ +static bool is_dp_sink_present(struct core_link *link) +{ + enum gpio_result gpio_result; + uint32_t clock_pin = 0; + uint32_t data_pin = 0; + + struct ddc *ddc; + + enum connector_id connector_id = + dal_graphics_object_id_get_connector_id(link->link_id); + + bool present = + ((connector_id == CONNECTOR_ID_DISPLAY_PORT) || + (connector_id == CONNECTOR_ID_EDP)); + + ddc = dal_ddc_service_get_ddc_pin(link->ddc); + + if (!ddc) { + BREAK_TO_DEBUGGER(); + return present; + } + + /* Open GPIO and set it to I2C mode */ + /* Note: this GpioMode_Input will be converted + * to GpioConfigType_I2cAuxDualMode in GPIO component, + * which indicates we need additional delay */ + + if (GPIO_RESULT_OK != dal_ddc_open( + ddc, GPIO_MODE_INPUT, GPIO_DDC_CONFIG_TYPE_MODE_I2C)) { + dal_gpio_destroy_ddc(&ddc); + + return present; + } + + /* Read GPIO: DP sink is present if both clock and data pins are zero */ + /* [anaumov] in DAL2, there was no check for GPIO failure */ + + gpio_result = dal_gpio_get_value(ddc->pin_clock, &clock_pin); + ASSERT(gpio_result == GPIO_RESULT_OK); + + if (gpio_result == GPIO_RESULT_OK) + if (link->link_enc->features.flags.bits. + DP_SINK_DETECT_POLL_DATA_PIN) + gpio_result = dal_gpio_get_value(ddc->pin_data, &data_pin); + + present = (gpio_result == GPIO_RESULT_OK) && !(clock_pin || data_pin); + + dal_ddc_close(ddc); + + return present; +} + +/* + * @brief + * Detect output sink type + */ +static enum signal_type link_detect_sink(struct core_link *link) +{ + enum signal_type result = get_basic_signal_type( + link->link_enc->id, link->link_id); + + /* Internal digital encoder will detect only dongles + * that require digital signal */ + + /* Detection mechanism is different + * for different native connectors. + * LVDS connector supports only LVDS signal; + * PCIE is a bus slot, the actual connector needs to be detected first; + * eDP connector supports only eDP signal; + * HDMI should check straps for audio */ + + /* PCIE detects the actual connector on add-on board */ + + if (link->link_id.id == CONNECTOR_ID_PCIE) { + /* ZAZTODO implement PCIE add-on card detection */ + } + + switch (link->link_id.id) { + case CONNECTOR_ID_HDMI_TYPE_A: { + /* check audio support: + * if native HDMI is not supported, switch to DVI */ + struct audio_support *aud_support = &link->dc->res_pool->audio_support; + + if (!aud_support->hdmi_audio_native) + if (link->link_id.id == CONNECTOR_ID_HDMI_TYPE_A) + result = SIGNAL_TYPE_DVI_SINGLE_LINK; + } + break; + case CONNECTOR_ID_DISPLAY_PORT: { + + /* Check whether DP signal detected: if not - + * we assume signal is DVI; it could be corrected + * to HDMI after dongle detection */ + if (!is_dp_sink_present(link)) + result = SIGNAL_TYPE_DVI_SINGLE_LINK; + } + break; + default: + break; + } + + return result; +} + +static enum signal_type decide_signal_from_strap_and_dongle_type( + enum display_dongle_type dongle_type, + struct audio_support *audio_support) +{ + enum signal_type signal = SIGNAL_TYPE_NONE; + + switch (dongle_type) { + case DISPLAY_DONGLE_DP_HDMI_DONGLE: + if (audio_support->hdmi_audio_on_dongle) + signal = SIGNAL_TYPE_HDMI_TYPE_A; + else + signal = SIGNAL_TYPE_DVI_SINGLE_LINK; + break; + case DISPLAY_DONGLE_DP_DVI_DONGLE: + signal = SIGNAL_TYPE_DVI_SINGLE_LINK; + break; + case DISPLAY_DONGLE_DP_HDMI_MISMATCHED_DONGLE: + if (audio_support->hdmi_audio_native) + signal = SIGNAL_TYPE_HDMI_TYPE_A; + else + signal = SIGNAL_TYPE_DVI_SINGLE_LINK; + break; + default: + signal = SIGNAL_TYPE_NONE; + break; + } + + return signal; +} + +static enum signal_type dp_passive_dongle_detection( + struct ddc_service *ddc, + struct display_sink_capability *sink_cap, + struct audio_support *audio_support) +{ + dal_ddc_service_i2c_query_dp_dual_mode_adaptor( + ddc, sink_cap); + return decide_signal_from_strap_and_dongle_type( + sink_cap->dongle_type, + audio_support); +} + +static void link_disconnect_sink(struct core_link *link) +{ + if (link->public.local_sink) { + dc_sink_release(link->public.local_sink); + link->public.local_sink = NULL; + } + + link->dpcd_sink_count = 0; +} + +static enum dc_edid_status read_edid( + struct core_link *link, + struct core_sink *sink) +{ + uint32_t edid_retry = 3; + enum dc_edid_status edid_status; + + /* some dongles read edid incorrectly the first time, + * do check sum and retry to make sure read correct edid. + */ + do { + sink->public.dc_edid.length = + dal_ddc_service_edid_query(link->ddc); + + if (0 == sink->public.dc_edid.length) + return EDID_NO_RESPONSE; + + dal_ddc_service_get_edid_buf(link->ddc, + sink->public.dc_edid.raw_edid); + edid_status = dm_helpers_parse_edid_caps( + sink->ctx, + &sink->public.dc_edid, + &sink->public.edid_caps); + --edid_retry; + if (edid_status == EDID_BAD_CHECKSUM) + dm_logger_write(link->ctx->logger, LOG_WARNING, + "Bad EDID checksum, retry remain: %d\n", + edid_retry); + } while (edid_status == EDID_BAD_CHECKSUM && edid_retry > 0); + + return edid_status; +} + +static void detect_dp( + struct core_link *link, + struct display_sink_capability *sink_caps, + bool *converter_disable_audio, + struct audio_support *audio_support, + bool boot) +{ + sink_caps->signal = link_detect_sink(link); + sink_caps->transaction_type = + get_ddc_transaction_type(sink_caps->signal); + + if (sink_caps->transaction_type == DDC_TRANSACTION_TYPE_I2C_OVER_AUX) { + sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT; + detect_dp_sink_caps(link); + + /* DP active dongles */ + if (is_dp_active_dongle(link)) { + link->public.type = dc_connection_active_dongle; + if (!link->dpcd_caps.sink_count.bits.SINK_COUNT) { + /* + * active dongle unplug processing for short irq + */ + link_disconnect_sink(link); + return; + } + + if (link->dpcd_caps.dongle_type != + DISPLAY_DONGLE_DP_HDMI_CONVERTER) { + *converter_disable_audio = true; + } + } + if (is_mst_supported(link)) { + sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT_MST; + + /* + * This call will initiate MST topology discovery. Which + * will detect MST ports and add new DRM connector DRM + * framework. Then read EDID via remote i2c over aux. In + * the end, will notify DRM detect result and save EDID + * into DRM framework. + * + * .detect is called by .fill_modes. + * .fill_modes is called by user mode ioctl + * DRM_IOCTL_MODE_GETCONNECTOR. + * + * .get_modes is called by .fill_modes. + * + * call .get_modes, AMDGPU DM implementation will create + * new dc_sink and add to dc_link. For long HPD plug + * in/out, MST has its own handle. + * + * Therefore, just after dc_create, link->sink is not + * created for MST until user mode app calls + * DRM_IOCTL_MODE_GETCONNECTOR. + * + * Need check ->sink usages in case ->sink = NULL + * TODO: s3 resume check + */ + + if (dm_helpers_dp_mst_start_top_mgr( + link->ctx, + &link->public, boot)) { + link->public.type = dc_connection_mst_branch; + } else { + /* MST not supported */ + sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT; + } + } + } else { + /* DP passive dongles */ + sink_caps->signal = dp_passive_dongle_detection(link->ddc, + sink_caps, + audio_support); + } +} + +bool dc_link_detect(const struct dc_link *dc_link, bool boot) +{ + struct core_link *link = DC_LINK_TO_LINK(dc_link); + struct dc_sink_init_data sink_init_data = { 0 }; + struct display_sink_capability sink_caps = { 0 }; + uint8_t i; + bool converter_disable_audio = false; + struct audio_support *aud_support = &link->dc->res_pool->audio_support; + enum dc_edid_status edid_status; + struct dc_context *dc_ctx = link->ctx; + struct dc_sink *dc_sink; + struct core_sink *sink = NULL; + enum dc_connection_type new_connection_type = dc_connection_none; + + if (link->public.connector_signal == SIGNAL_TYPE_VIRTUAL) + return false; + + if (false == detect_sink(link, &new_connection_type)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (link->public.connector_signal == SIGNAL_TYPE_EDP && + link->public.local_sink) + return true; + + link_disconnect_sink(link); + + if (new_connection_type != dc_connection_none) { + link->public.type = new_connection_type; + + /* From Disconnected-to-Connected. */ + switch (link->public.connector_signal) { + case SIGNAL_TYPE_HDMI_TYPE_A: { + sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C; + if (aud_support->hdmi_audio_native) + sink_caps.signal = SIGNAL_TYPE_HDMI_TYPE_A; + else + sink_caps.signal = SIGNAL_TYPE_DVI_SINGLE_LINK; + break; + } + + case SIGNAL_TYPE_DVI_SINGLE_LINK: { + sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C; + sink_caps.signal = SIGNAL_TYPE_DVI_SINGLE_LINK; + break; + } + + case SIGNAL_TYPE_DVI_DUAL_LINK: { + sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C; + sink_caps.signal = SIGNAL_TYPE_DVI_DUAL_LINK; + break; + } + + case SIGNAL_TYPE_EDP: { + detect_dp_sink_caps(link); + sink_caps.transaction_type = + DDC_TRANSACTION_TYPE_I2C_OVER_AUX; + sink_caps.signal = SIGNAL_TYPE_EDP; + break; + } + + case SIGNAL_TYPE_DISPLAY_PORT: { + detect_dp( + link, + &sink_caps, + &converter_disable_audio, + aud_support, boot); + + /* Active dongle downstream unplug */ + if (link->public.type == dc_connection_active_dongle + && link->dpcd_caps.sink_count. + bits.SINK_COUNT == 0) + return true; + + if (link->public.type == dc_connection_mst_branch) { + LINK_INFO("link=%d, mst branch is now Connected\n", + link->public.link_index); + return false; + } + + break; + } + + default: + DC_ERROR("Invalid connector type! signal:%d\n", + link->public.connector_signal); + return false; + } /* switch() */ + + if (link->dpcd_caps.sink_count.bits.SINK_COUNT) + link->dpcd_sink_count = link->dpcd_caps.sink_count. + bits.SINK_COUNT; + else + link->dpcd_sink_count = 1; + + dal_ddc_service_set_transaction_type( + link->ddc, + sink_caps.transaction_type); + + sink_init_data.link = &link->public; + sink_init_data.sink_signal = sink_caps.signal; + sink_init_data.dongle_max_pix_clk = + sink_caps.max_hdmi_pixel_clock; + sink_init_data.converter_disable_audio = + converter_disable_audio; + + dc_sink = dc_sink_create(&sink_init_data); + if (!dc_sink) { + DC_ERROR("Failed to create sink!\n"); + return false; + } + + sink = DC_SINK_TO_CORE(dc_sink); + link->public.local_sink = &sink->public; + + edid_status = read_edid(link, sink); + + switch (edid_status) { + case EDID_BAD_CHECKSUM: + dm_logger_write(link->ctx->logger, LOG_ERROR, + "EDID checksum invalid.\n"); + break; + case EDID_NO_RESPONSE: + dm_logger_write(link->ctx->logger, LOG_ERROR, + "No EDID read.\n"); + return false; + + default: + break; + } + + /* HDMI-DVI Dongle */ + if (dc_sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A && + !dc_sink->edid_caps.edid_hdmi) + dc_sink->sink_signal = SIGNAL_TYPE_DVI_SINGLE_LINK; + + /* Connectivity log: detection */ + for (i = 0; i < sink->public.dc_edid.length / EDID_BLOCK_SIZE; i++) { + CONN_DATA_DETECT(link, + &sink->public.dc_edid.raw_edid[i * EDID_BLOCK_SIZE], + EDID_BLOCK_SIZE, + "%s: [Block %d] ", sink->public.edid_caps.display_name, i); + } + + dm_logger_write(link->ctx->logger, LOG_DETECTION_EDID_PARSER, + "%s: " + "manufacturer_id = %X, " + "product_id = %X, " + "serial_number = %X, " + "manufacture_week = %d, " + "manufacture_year = %d, " + "display_name = %s, " + "speaker_flag = %d, " + "audio_mode_count = %d\n", + __func__, + sink->public.edid_caps.manufacturer_id, + sink->public.edid_caps.product_id, + sink->public.edid_caps.serial_number, + sink->public.edid_caps.manufacture_week, + sink->public.edid_caps.manufacture_year, + sink->public.edid_caps.display_name, + sink->public.edid_caps.speaker_flags, + sink->public.edid_caps.audio_mode_count); + + for (i = 0; i < sink->public.edid_caps.audio_mode_count; i++) { + dm_logger_write(link->ctx->logger, LOG_DETECTION_EDID_PARSER, + "%s: mode number = %d, " + "format_code = %d, " + "channel_count = %d, " + "sample_rate = %d, " + "sample_size = %d\n", + __func__, + i, + sink->public.edid_caps.audio_modes[i].format_code, + sink->public.edid_caps.audio_modes[i].channel_count, + sink->public.edid_caps.audio_modes[i].sample_rate, + sink->public.edid_caps.audio_modes[i].sample_size); + } + + } else { + /* From Connected-to-Disconnected. */ + if (link->public.type == dc_connection_mst_branch) { + LINK_INFO("link=%d, mst branch is now Disconnected\n", + link->public.link_index); + dm_helpers_dp_mst_stop_top_mgr(link->ctx, &link->public); + + link->mst_stream_alloc_table.stream_count = 0; + memset(link->mst_stream_alloc_table.stream_allocations, 0, sizeof(link->mst_stream_alloc_table.stream_allocations)); + } + + link->public.type = dc_connection_none; + sink_caps.signal = SIGNAL_TYPE_NONE; + } + + LINK_INFO("link=%d, dc_sink_in=%p is now %s\n", + link->public.link_index, &sink->public, + (sink_caps.signal == SIGNAL_TYPE_NONE ? + "Disconnected":"Connected")); + + return true; +} + +static enum hpd_source_id get_hpd_line( + struct core_link *link) +{ + struct gpio *hpd; + enum hpd_source_id hpd_id = HPD_SOURCEID_UNKNOWN; + + hpd = get_hpd_gpio(link); + + if (hpd) { + switch (dal_irq_get_source(hpd)) { + case DC_IRQ_SOURCE_HPD1: + hpd_id = HPD_SOURCEID1; + break; + case DC_IRQ_SOURCE_HPD2: + hpd_id = HPD_SOURCEID2; + break; + case DC_IRQ_SOURCE_HPD3: + hpd_id = HPD_SOURCEID3; + break; + case DC_IRQ_SOURCE_HPD4: + hpd_id = HPD_SOURCEID4; + break; + case DC_IRQ_SOURCE_HPD5: + hpd_id = HPD_SOURCEID5; + break; + case DC_IRQ_SOURCE_HPD6: + hpd_id = HPD_SOURCEID6; + break; + default: + BREAK_TO_DEBUGGER(); + break; + } + + dal_gpio_destroy_irq(&hpd); + } + + return hpd_id; +} + +static enum channel_id get_ddc_line(struct core_link *link) +{ + struct ddc *ddc; + enum channel_id channel = CHANNEL_ID_UNKNOWN; + + ddc = dal_ddc_service_get_ddc_pin(link->ddc); + + if (ddc) { + switch (dal_ddc_get_line(ddc)) { + case GPIO_DDC_LINE_DDC1: + channel = CHANNEL_ID_DDC1; + break; + case GPIO_DDC_LINE_DDC2: + channel = CHANNEL_ID_DDC2; + break; + case GPIO_DDC_LINE_DDC3: + channel = CHANNEL_ID_DDC3; + break; + case GPIO_DDC_LINE_DDC4: + channel = CHANNEL_ID_DDC4; + break; + case GPIO_DDC_LINE_DDC5: + channel = CHANNEL_ID_DDC5; + break; + case GPIO_DDC_LINE_DDC6: + channel = CHANNEL_ID_DDC6; + break; + case GPIO_DDC_LINE_DDC_VGA: + channel = CHANNEL_ID_DDC_VGA; + break; + case GPIO_DDC_LINE_I2C_PAD: + channel = CHANNEL_ID_I2C_PAD; + break; + default: + BREAK_TO_DEBUGGER(); + break; + } + } + + return channel; +} + +static enum transmitter translate_encoder_to_transmitter( + struct graphics_object_id encoder) +{ + switch (encoder.id) { + case ENCODER_ID_INTERNAL_UNIPHY: + switch (encoder.enum_id) { + case ENUM_ID_1: + return TRANSMITTER_UNIPHY_A; + case ENUM_ID_2: + return TRANSMITTER_UNIPHY_B; + default: + return TRANSMITTER_UNKNOWN; + } + break; + case ENCODER_ID_INTERNAL_UNIPHY1: + switch (encoder.enum_id) { + case ENUM_ID_1: + return TRANSMITTER_UNIPHY_C; + case ENUM_ID_2: + return TRANSMITTER_UNIPHY_D; + default: + return TRANSMITTER_UNKNOWN; + } + break; + case ENCODER_ID_INTERNAL_UNIPHY2: + switch (encoder.enum_id) { + case ENUM_ID_1: + return TRANSMITTER_UNIPHY_E; + case ENUM_ID_2: + return TRANSMITTER_UNIPHY_F; + default: + return TRANSMITTER_UNKNOWN; + } + break; + case ENCODER_ID_INTERNAL_UNIPHY3: + switch (encoder.enum_id) { + case ENUM_ID_1: + return TRANSMITTER_UNIPHY_G; + default: + return TRANSMITTER_UNKNOWN; + } + break; + case ENCODER_ID_EXTERNAL_NUTMEG: + switch (encoder.enum_id) { + case ENUM_ID_1: + return TRANSMITTER_NUTMEG_CRT; + default: + return TRANSMITTER_UNKNOWN; + } + break; + case ENCODER_ID_EXTERNAL_TRAVIS: + switch (encoder.enum_id) { + case ENUM_ID_1: + return TRANSMITTER_TRAVIS_CRT; + case ENUM_ID_2: + return TRANSMITTER_TRAVIS_LCD; + default: + return TRANSMITTER_UNKNOWN; + } + break; + default: + return TRANSMITTER_UNKNOWN; + } +} + +static bool construct( + struct core_link *link, + const struct link_init_data *init_params) +{ + uint8_t i; + struct gpio *hpd_gpio = NULL; + struct ddc_service_init_data ddc_service_init_data = { 0 }; + struct dc_context *dc_ctx = init_params->ctx; + struct encoder_init_data enc_init_data = { 0 }; + struct integrated_info info = {{{ 0 }}}; + struct dc_bios *bios = init_params->dc->ctx->dc_bios; + const struct dc_vbios_funcs *bp_funcs = bios->funcs; + + link->public.irq_source_hpd = DC_IRQ_SOURCE_INVALID; + link->public.irq_source_hpd_rx = DC_IRQ_SOURCE_INVALID; + + link->link_status.dpcd_caps = &link->dpcd_caps; + + link->dc = init_params->dc; + link->ctx = dc_ctx; + link->public.link_index = init_params->link_index; + + link->link_id = bios->funcs->get_connector_id(bios, init_params->connector_index); + + if (link->link_id.type != OBJECT_TYPE_CONNECTOR) { + dm_error("%s: Invalid Connector ObjectID from Adapter Service for connector index:%d!\n", + __func__, init_params->connector_index); + goto create_fail; + } + + hpd_gpio = get_hpd_gpio(link); + + if (hpd_gpio != NULL) + link->public.irq_source_hpd = dal_irq_get_source(hpd_gpio); + + switch (link->link_id.id) { + case CONNECTOR_ID_HDMI_TYPE_A: + link->public.connector_signal = SIGNAL_TYPE_HDMI_TYPE_A; + + break; + case CONNECTOR_ID_SINGLE_LINK_DVID: + case CONNECTOR_ID_SINGLE_LINK_DVII: + link->public.connector_signal = SIGNAL_TYPE_DVI_SINGLE_LINK; + break; + case CONNECTOR_ID_DUAL_LINK_DVID: + case CONNECTOR_ID_DUAL_LINK_DVII: + link->public.connector_signal = SIGNAL_TYPE_DVI_DUAL_LINK; + break; + case CONNECTOR_ID_DISPLAY_PORT: + link->public.connector_signal = SIGNAL_TYPE_DISPLAY_PORT; + + if (hpd_gpio != NULL) + link->public.irq_source_hpd_rx = + dal_irq_get_rx_source(hpd_gpio); + + break; + case CONNECTOR_ID_EDP: + link->public.connector_signal = SIGNAL_TYPE_EDP; + + if (hpd_gpio != NULL) { + link->public.irq_source_hpd = DC_IRQ_SOURCE_INVALID; + link->public.irq_source_hpd_rx = + dal_irq_get_rx_source(hpd_gpio); + } + break; + default: + dm_logger_write(dc_ctx->logger, LOG_WARNING, + "Unsupported Connector type:%d!\n", link->link_id.id); + goto create_fail; + } + + if (hpd_gpio != NULL) { + dal_gpio_destroy_irq(&hpd_gpio); + hpd_gpio = NULL; + } + + /* TODO: #DAL3 Implement id to str function.*/ + LINK_INFO("Connector[%d] description:" + "signal %d\n", + init_params->connector_index, + link->public.connector_signal); + + ddc_service_init_data.ctx = link->ctx; + ddc_service_init_data.id = link->link_id; + ddc_service_init_data.link = link; + link->ddc = dal_ddc_service_create(&ddc_service_init_data); + + if (NULL == link->ddc) { + DC_ERROR("Failed to create ddc_service!\n"); + goto ddc_create_fail; + } + + link->public.ddc_hw_inst = + dal_ddc_get_line( + dal_ddc_service_get_ddc_pin(link->ddc)); + + enc_init_data.ctx = dc_ctx; + bp_funcs->get_src_obj(dc_ctx->dc_bios, link->link_id, 0, &enc_init_data.encoder); + enc_init_data.connector = link->link_id; + enc_init_data.channel = get_ddc_line(link); + enc_init_data.hpd_source = get_hpd_line(link); + enc_init_data.transmitter = + translate_encoder_to_transmitter(enc_init_data.encoder); + link->link_enc = link->dc->res_pool->funcs->link_enc_create( + &enc_init_data); + + if( link->link_enc == NULL) { + DC_ERROR("Failed to create link encoder!\n"); + goto link_enc_create_fail; + } + + link->public.link_enc_hw_inst = link->link_enc->transmitter; + + for (i = 0; i < 4; i++) { + if (BP_RESULT_OK != + bp_funcs->get_device_tag(dc_ctx->dc_bios, link->link_id, i, &link->device_tag)) { + DC_ERROR("Failed to find device tag!\n"); + goto device_tag_fail; + } + + /* Look for device tag that matches connector signal, + * CRT for rgb, LCD for other supported signal tyes + */ + if (!bp_funcs->is_device_id_supported(dc_ctx->dc_bios, link->device_tag.dev_id)) + continue; + if (link->device_tag.dev_id.device_type == DEVICE_TYPE_CRT + && link->public.connector_signal != SIGNAL_TYPE_RGB) + continue; + if (link->device_tag.dev_id.device_type == DEVICE_TYPE_LCD + && link->public.connector_signal == SIGNAL_TYPE_RGB) + continue; + if (link->device_tag.dev_id.device_type == DEVICE_TYPE_WIRELESS + && link->public.connector_signal != SIGNAL_TYPE_WIRELESS) + continue; + break; + } + + if (bios->integrated_info) + info = *bios->integrated_info; + + /* Look for channel mapping corresponding to connector and device tag */ + for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; i++) { + struct external_display_path *path = + &info.ext_disp_conn_info.path[i]; + if (path->device_connector_id.enum_id == link->link_id.enum_id + && path->device_connector_id.id == link->link_id.id + && path->device_connector_id.type == link->link_id.type + && path->device_acpi_enum + == link->device_tag.acpi_device) { + link->ddi_channel_mapping = path->channel_mapping; + break; + } + } + + /* + * TODO check if GPIO programmed correctly + * + * If GPIO isn't programmed correctly HPD might not rise or drain + * fast enough, leading to bounces. + */ + program_hpd_filter(link); + + return true; +device_tag_fail: + link->link_enc->funcs->destroy(&link->link_enc); +link_enc_create_fail: + dal_ddc_service_destroy(&link->ddc); +ddc_create_fail: +create_fail: + + if (hpd_gpio != NULL) { + dal_gpio_destroy_irq(&hpd_gpio); + } + + return false; +} + +/******************************************************************************* + * Public functions + ******************************************************************************/ +struct core_link *link_create(const struct link_init_data *init_params) +{ + struct core_link *link = + dm_alloc(sizeof(*link)); + + if (NULL == link) + goto alloc_fail; + + if (false == construct(link, init_params)) + goto construct_fail; + + return link; + +construct_fail: + dm_free(link); + +alloc_fail: + return NULL; +} + +void link_destroy(struct core_link **link) +{ + destruct(*link); + dm_free(*link); + *link = NULL; +} + +static void dpcd_configure_panel_mode( + struct core_link *link, + enum dp_panel_mode panel_mode) +{ + union dpcd_edp_config edp_config_set; + bool panel_mode_edp = false; + + memset(&edp_config_set, '\0', sizeof(union dpcd_edp_config)); + + if (DP_PANEL_MODE_DEFAULT != panel_mode) { + + switch (panel_mode) { + case DP_PANEL_MODE_EDP: + case DP_PANEL_MODE_SPECIAL: + panel_mode_edp = true; + break; + + default: + break; + } + + /*set edp panel mode in receiver*/ + core_link_read_dpcd( + link, + DPCD_ADDRESS_EDP_CONFIG_SET, + &edp_config_set.raw, + sizeof(edp_config_set.raw)); + + if (edp_config_set.bits.PANEL_MODE_EDP + != panel_mode_edp) { + enum ddc_result result = DDC_RESULT_UNKNOWN; + + edp_config_set.bits.PANEL_MODE_EDP = + panel_mode_edp; + result = core_link_write_dpcd( + link, + DPCD_ADDRESS_EDP_CONFIG_SET, + &edp_config_set.raw, + sizeof(edp_config_set.raw)); + + ASSERT(result == DDC_RESULT_SUCESSFULL); + } + } + dm_logger_write(link->ctx->logger, LOG_DETECTION_DP_CAPS, + "Link: %d eDP panel mode supported: %d " + "eDP panel mode enabled: %d \n", + link->public.link_index, + link->dpcd_caps.panel_mode_edp, + panel_mode_edp); +} + +static void enable_stream_features(struct pipe_ctx *pipe_ctx) +{ + struct core_stream *stream = pipe_ctx->stream; + struct core_link *link = stream->sink->link; + union down_spread_ctrl downspread; + + core_link_read_dpcd(link, DPCD_ADDRESS_DOWNSPREAD_CNTL, + &downspread.raw, sizeof(downspread)); + + downspread.bits.IGNORE_MSA_TIMING_PARAM = + (stream->public.ignore_msa_timing_param) ? 1 : 0; + + core_link_write_dpcd(link, DPCD_ADDRESS_DOWNSPREAD_CNTL, + &downspread.raw, sizeof(downspread)); +} + +static enum dc_status enable_link_dp(struct pipe_ctx *pipe_ctx) +{ + struct core_stream *stream = pipe_ctx->stream; + enum dc_status status; + bool skip_video_pattern; + struct core_link *link = stream->sink->link; + struct dc_link_settings link_settings = {0}; + enum dp_panel_mode panel_mode; + enum clocks_state cur_min_clock_state; + enum dc_link_rate max_link_rate = LINK_RATE_HIGH2; + + /* get link settings for video mode timing */ + decide_link_settings(stream, &link_settings); + + /* raise clock state for HBR3 if required. Confirmed with HW DCE/DPCS + * logic for HBR3 still needs Nominal (0.8V) on VDDC rail + */ + if (link->link_enc->features.flags.bits.IS_HBR3_CAPABLE) + max_link_rate = LINK_RATE_HIGH3; + + if (link_settings.link_rate == max_link_rate) { + cur_min_clock_state = CLOCKS_STATE_INVALID; + + if (dal_display_clock_get_min_clocks_state( + pipe_ctx->dis_clk, &cur_min_clock_state)) { + if (cur_min_clock_state < CLOCKS_STATE_NOMINAL) + dal_display_clock_set_min_clocks_state( + pipe_ctx->dis_clk, + CLOCKS_STATE_NOMINAL); + } else { + } + } + + dp_enable_link_phy( + link, + pipe_ctx->stream->signal, + pipe_ctx->clock_source->id, + &link_settings); + + panel_mode = dp_get_panel_mode(link); + dpcd_configure_panel_mode(link, panel_mode); + + skip_video_pattern = true; + + if (link_settings.link_rate == LINK_RATE_LOW) + skip_video_pattern = false; + + if (perform_link_training_with_retries( + link, + &link_settings, + skip_video_pattern, + LINK_TRAINING_ATTEMPTS)) { + link->public.cur_link_settings = link_settings; + status = DC_OK; + } + else + status = DC_ERROR_UNEXPECTED; + + enable_stream_features(pipe_ctx); + + return status; +} + +static enum dc_status enable_link_dp_mst(struct pipe_ctx *pipe_ctx) +{ + struct core_link *link = pipe_ctx->stream->sink->link; + + /* sink signal type after MST branch is MST. Multiple MST sinks + * share one link. Link DP PHY is enable or training only once. + */ + if (link->public.cur_link_settings.lane_count != LANE_COUNT_UNKNOWN) + return DC_OK; + + return enable_link_dp(pipe_ctx); +} + +static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) +{ + struct core_stream *stream = pipe_ctx->stream; + struct core_link *link = stream->sink->link; + + if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) + dal_ddc_service_write_scdc_data( + stream->sink->link->ddc, + stream->phy_pix_clk, + stream->public.timing.flags.LTE_340MCSC_SCRAMBLE); + + memset(&stream->sink->link->public.cur_link_settings, 0, + sizeof(struct dc_link_settings)); + + link->link_enc->funcs->enable_tmds_output( + link->link_enc, + pipe_ctx->clock_source->id, + stream->public.timing.display_color_depth, + pipe_ctx->stream->signal == SIGNAL_TYPE_HDMI_TYPE_A, + pipe_ctx->stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK, + stream->phy_pix_clk); + + if (pipe_ctx->stream->signal == SIGNAL_TYPE_HDMI_TYPE_A) + dal_ddc_service_read_scdc_data(link->ddc); +} + +/****************************enable_link***********************************/ +static enum dc_status enable_link(struct pipe_ctx *pipe_ctx) +{ + enum dc_status status = DC_ERROR_UNEXPECTED; + switch (pipe_ctx->stream->signal) { + case SIGNAL_TYPE_DISPLAY_PORT: + case SIGNAL_TYPE_EDP: + status = enable_link_dp(pipe_ctx); + break; + case SIGNAL_TYPE_DISPLAY_PORT_MST: + status = enable_link_dp_mst(pipe_ctx); + msleep(200); + break; + case SIGNAL_TYPE_DVI_SINGLE_LINK: + case SIGNAL_TYPE_DVI_DUAL_LINK: + case SIGNAL_TYPE_HDMI_TYPE_A: + enable_link_hdmi(pipe_ctx); + status = DC_OK; + break; + case SIGNAL_TYPE_VIRTUAL: + status = DC_OK; + break; + default: + break; + } + + if (pipe_ctx->audio && status == DC_OK) { + /* notify audio driver for audio modes of monitor */ + pipe_ctx->audio->funcs->az_enable(pipe_ctx->audio); + + /* un-mute audio */ + /* TODO: audio should be per stream rather than per link */ + pipe_ctx->stream_enc->funcs->audio_mute_control( + pipe_ctx->stream_enc, false); + } + + return status; +} + +static void disable_link(struct core_link *link, enum signal_type signal) +{ + /* + * TODO: implement call for dp_set_hw_test_pattern + * it is needed for compliance testing + */ + + /* here we need to specify that encoder output settings + * need to be calculated as for the set mode, + * it will lead to querying dynamic link capabilities + * which should be done before enable output */ + + if (dc_is_dp_signal(signal)) { + /* SST DP, eDP */ + if (dc_is_dp_sst_signal(signal)) + dp_disable_link_phy(link, signal); + else + dp_disable_link_phy_mst(link, signal); + } else + link->link_enc->funcs->disable_output(link->link_enc, signal); +} + +enum dc_status dc_link_validate_mode_timing( + const struct core_stream *stream, + struct core_link *link, + const struct dc_crtc_timing *timing) +{ + uint32_t max_pix_clk = stream->sink->dongle_max_pix_clk; + + /* A hack to avoid failing any modes for EDID override feature on + * topology change such as lower quality cable for DP or different dongle + */ + if (link->public.remote_sinks[0]) + return DC_OK; + + if (0 != max_pix_clk && timing->pix_clk_khz > max_pix_clk) + return DC_EXCEED_DONGLE_MAX_CLK; + + switch (stream->signal) { + case SIGNAL_TYPE_EDP: + case SIGNAL_TYPE_DISPLAY_PORT: + if (!dp_validate_mode_timing( + link, + timing)) + return DC_NO_DP_LINK_BANDWIDTH; + break; + + default: + break; + } + + return DC_OK; +} + + +bool dc_link_set_backlight_level(const struct dc_link *dc_link, uint32_t level, + uint32_t frame_ramp, const struct dc_stream *stream) +{ + struct core_link *link = DC_LINK_TO_CORE(dc_link); + struct dc_context *ctx = link->ctx; + struct core_dc *core_dc = DC_TO_CORE(ctx->dc); + struct core_stream *core_stream = DC_STREAM_TO_CORE(stream); + unsigned int controller_id = 0; + int i; + uint32_t dmcu_status; + + dm_logger_write(ctx->logger, LOG_BACKLIGHT, + "New Backlight level: %d (0x%X)\n", level, level); + + dmcu_status = dm_read_reg(ctx, mmDMCU_STATUS); + + /* If DMCU is in reset state, DMCU is uninitialized */ + if (get_reg_field_value(dmcu_status, mmDMCU_STATUS, UC_IN_RESET)) { + link->link_enc->funcs->set_lcd_backlight_level(link->link_enc, + level); + } else { + for (i = 0; i < MAX_PIPES; i++) { + if (core_dc->current_context->res_ctx.pipe_ctx[i].stream + == core_stream) + /* dmcu -1 for all controller id values, + * therefore +1 here + */ + controller_id = core_dc->current_context->res_ctx. + pipe_ctx[i].tg->inst + 1; + } + + link->link_enc->funcs->set_dmcu_backlight_level + (link->link_enc, level, + frame_ramp, controller_id); + } + return true; +} + + +bool dc_link_init_dmcu_backlight_settings(const struct dc_link *dc_link) +{ + struct core_link *link = DC_LINK_TO_CORE(dc_link); + + if (link->link_enc->funcs->init_dmcu_backlight_settings != NULL) + link->link_enc->funcs-> + init_dmcu_backlight_settings(link->link_enc); + + return true; +} + +bool dc_link_set_abm_level(const struct dc_link *dc_link, uint32_t level) +{ + struct core_link *link = DC_LINK_TO_CORE(dc_link); + struct dc_context *ctx = link->ctx; + + dm_logger_write(ctx->logger, LOG_BACKLIGHT, + "New abm level: %d (0x%X)\n", level, level); + + link->link_enc->funcs->set_dmcu_abm_level(link->link_enc, level); + return true; +} + +bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable) +{ + struct core_link *link = DC_LINK_TO_CORE(dc_link); + + if (dc_link != NULL && dc_link->psr_caps.psr_version > 0) + link->link_enc->funcs->set_dmcu_psr_enable(link->link_enc, + enable); + return true; +} + +bool dc_link_setup_psr(const struct dc_link *dc_link, + const struct dc_stream *stream) +{ + + struct core_link *link = DC_LINK_TO_CORE(dc_link); + struct dc_context *ctx = link->ctx; + struct core_dc *core_dc = DC_TO_CORE(ctx->dc); + struct core_stream *core_stream = DC_STREAM_TO_CORE(stream); + struct psr_dmcu_context psr_context = {0}; + int i; + + psr_context.controllerId = CONTROLLER_ID_UNDEFINED; + + + if (dc_link != NULL && dc_link->psr_caps.psr_version > 0) { + /* updateSinkPsrDpcdConfig*/ + union dpcd_psr_configuration psr_configuration; + + memset(&psr_configuration, 0, sizeof(psr_configuration)); + + psr_configuration.bits.ENABLE = 1; + psr_configuration.bits.CRC_VERIFICATION = 1; + psr_configuration.bits.FRAME_CAPTURE_INDICATION = + dc_link->psr_caps.psr_frame_capture_indication_req; + + /* Check for PSR v2*/ + if (dc_link->psr_caps.psr_version == 0x2) { + /* For PSR v2 selective update. + * Indicates whether sink should start capturing + * immediately following active scan line, + * or starting with the 2nd active scan line. + */ + psr_configuration.bits.LINE_CAPTURE_INDICATION = 0; + /*For PSR v2, determines whether Sink should generate + * IRQ_HPD when CRC mismatch is detected. + */ + psr_configuration.bits.IRQ_HPD_WITH_CRC_ERROR = 1; + } + dal_ddc_service_write_dpcd_data( + link->ddc, + 368, + &psr_configuration.raw, + sizeof(psr_configuration.raw)); + + psr_context.channel = link->ddc->ddc_pin->hw_info.ddc_channel; + if (psr_context.channel == 0) + psr_context.channel = 1; + psr_context.transmitterId = link->link_enc->transmitter; + psr_context.engineId = link->link_enc->preferred_engine; + + for (i = 0; i < MAX_PIPES; i++) { + if (core_dc->current_context->res_ctx.pipe_ctx[i].stream + == core_stream) { + /* dmcu -1 for all controller id values, + * therefore +1 here + */ + psr_context.controllerId = + core_dc->current_context->res_ctx. + pipe_ctx[i].tg->inst + 1; + break; + } + } + + /* Hardcoded for now. Can be Pcie or Uniphy (or Unknown)*/ + psr_context.phyType = PHY_TYPE_UNIPHY; + /*PhyId is associated with the transmitter id*/ + psr_context.smuPhyId = link->link_enc->transmitter; + + psr_context.crtcTimingVerticalTotal = stream->timing.v_total; + psr_context.vsyncRateHz = div64_u64(div64_u64((stream-> + timing.pix_clk_khz * 1000), + stream->timing.v_total), + stream->timing.h_total); + + psr_context.psrSupportedDisplayConfig = + (dc_link->psr_caps.psr_version > 0) ? true : false; + psr_context.psrExitLinkTrainingRequired = + dc_link->psr_caps.psr_exit_link_training_required; + psr_context.sdpTransmitLineNumDeadline = + dc_link->psr_caps.psr_sdp_transmit_line_num_deadline; + psr_context.psrFrameCaptureIndicationReq = + dc_link->psr_caps.psr_frame_capture_indication_req; + + psr_context.skipPsrWaitForPllLock = 0; /* only = 1 in KV */ + + psr_context.numberOfControllers = + link->dc->res_pool->res_cap->num_timing_generator; + + psr_context.rfb_update_auto_en = true; + + /* 2 frames before enter PSR. */ + psr_context.timehyst_frames = 2; + /* half a frame + * (units in 100 lines, i.e. a value of 1 represents 100 lines) + */ + psr_context.hyst_lines = stream->timing.v_total / 2 / 100; + psr_context.aux_repeats = 10; + + psr_context.psr_level.u32all = 0; + + /* SMU will perform additional powerdown sequence. + * For unsupported ASICs, set psr_level flag to skip PSR + * static screen notification to SMU. + * (Always set for DAL2, did not check ASIC) + */ + psr_context.psr_level.bits.SKIP_SMU_NOTIFICATION = 1; + + /* Controls additional delay after remote frame capture before + * continuing power down, default = 0 + */ + psr_context.frame_delay = 0; + + link->link_enc->funcs->setup_dmcu_psr + (link->link_enc, &psr_context); + return true; + } else + return false; + +} + +const struct dc_link_status *dc_link_get_status(const struct dc_link *dc_link) +{ + struct core_link *link = DC_LINK_TO_CORE(dc_link); + + return &link->link_status; +} + +void core_link_resume(struct core_link *link) +{ + if (link->public.connector_signal != SIGNAL_TYPE_VIRTUAL) + program_hpd_filter(link); +} + +static struct fixed31_32 get_pbn_per_slot(struct core_stream *stream) +{ + struct dc_link_settings *link_settings = + &stream->sink->link->public.cur_link_settings; + uint32_t link_rate_in_mbps = + link_settings->link_rate * LINK_RATE_REF_FREQ_IN_MHZ; + struct fixed31_32 mbps = dal_fixed31_32_from_int( + link_rate_in_mbps * link_settings->lane_count); + + return dal_fixed31_32_div_int(mbps, 54); +} + +static int get_color_depth(enum dc_color_depth color_depth) +{ + switch (color_depth) { + case COLOR_DEPTH_666: return 6; + case COLOR_DEPTH_888: return 8; + case COLOR_DEPTH_101010: return 10; + case COLOR_DEPTH_121212: return 12; + case COLOR_DEPTH_141414: return 14; + case COLOR_DEPTH_161616: return 16; + default: return 0; + } +} + +static struct fixed31_32 get_pbn_from_timing(struct pipe_ctx *pipe_ctx) +{ + uint32_t bpc; + uint64_t kbps; + struct fixed31_32 peak_kbps; + uint32_t numerator; + uint32_t denominator; + + bpc = get_color_depth(pipe_ctx->pix_clk_params.color_depth); + kbps = pipe_ctx->pix_clk_params.requested_pix_clk * bpc * 3; + + /* + * margin 5300ppm + 300ppm ~ 0.6% as per spec, factor is 1.006 + * The unit of 54/64Mbytes/sec is an arbitrary unit chosen based on + * common multiplier to render an integer PBN for all link rate/lane + * counts combinations + * calculate + * peak_kbps *= (1006/1000) + * peak_kbps *= (64/54) + * peak_kbps *= 8 convert to bytes + */ + + numerator = 64 * PEAK_FACTOR_X1000; + denominator = 54 * 8 * 1000 * 1000; + kbps *= numerator; + peak_kbps = dal_fixed31_32_from_fraction(kbps, denominator); + + return peak_kbps; +} + +static void update_mst_stream_alloc_table( + struct core_link *link, + struct stream_encoder *stream_enc, + const struct dp_mst_stream_allocation_table *proposed_table) +{ + struct link_mst_stream_allocation work_table[MAX_CONTROLLER_NUM] = { + { 0 } }; + struct link_mst_stream_allocation *dc_alloc; + + int i; + int j; + + /* if DRM proposed_table has more than one new payload */ + ASSERT(proposed_table->stream_count - + link->mst_stream_alloc_table.stream_count < 2); + + /* copy proposed_table to core_link, add stream encoder */ + for (i = 0; i < proposed_table->stream_count; i++) { + + for (j = 0; j < link->mst_stream_alloc_table.stream_count; j++) { + dc_alloc = + &link->mst_stream_alloc_table.stream_allocations[j]; + + if (dc_alloc->vcp_id == + proposed_table->stream_allocations[i].vcp_id) { + + work_table[i] = *dc_alloc; + break; /* exit j loop */ + } + } + + /* new vcp_id */ + if (j == link->mst_stream_alloc_table.stream_count) { + work_table[i].vcp_id = + proposed_table->stream_allocations[i].vcp_id; + work_table[i].slot_count = + proposed_table->stream_allocations[i].slot_count; + work_table[i].stream_enc = stream_enc; + } + } + + /* update link->mst_stream_alloc_table with work_table */ + link->mst_stream_alloc_table.stream_count = + proposed_table->stream_count; + for (i = 0; i < MAX_CONTROLLER_NUM; i++) + link->mst_stream_alloc_table.stream_allocations[i] = + work_table[i]; +} + +/* convert link_mst_stream_alloc_table to dm dp_mst_stream_alloc_table + * because stream_encoder is not exposed to dm + */ +static enum dc_status allocate_mst_payload(struct pipe_ctx *pipe_ctx) +{ + struct core_stream *stream = pipe_ctx->stream; + struct core_link *link = stream->sink->link; + struct link_encoder *link_encoder = link->link_enc; + struct stream_encoder *stream_encoder = pipe_ctx->stream_enc; + struct dp_mst_stream_allocation_table proposed_table = {0}; + struct fixed31_32 avg_time_slots_per_mtp; + struct fixed31_32 pbn; + struct fixed31_32 pbn_per_slot; + uint8_t i; + + /* enable_link_dp_mst already check link->enabled_stream_count + * and stream is in link->stream[]. This is called during set mode, + * stream_enc is available. + */ + + /* get calculate VC payload for stream: stream_alloc */ + if (dm_helpers_dp_mst_write_payload_allocation_table( + stream->ctx, + &stream->public, + &proposed_table, + true)) { + update_mst_stream_alloc_table( + link, pipe_ctx->stream_enc, &proposed_table); + } + else + dm_logger_write(link->ctx->logger, LOG_WARNING, + "Failed to update" + "MST allocation table for" + "pipe idx:%d\n", + pipe_ctx->pipe_idx); + + dm_logger_write(link->ctx->logger, LOG_MST, + "%s " + "stream_count: %d: \n ", + __func__, + link->mst_stream_alloc_table.stream_count); + + for (i = 0; i < MAX_CONTROLLER_NUM; i++) { + dm_logger_write(link->ctx->logger, LOG_MST, + "stream_enc[%d]: 0x%x " + "stream[%d].vcp_id: %d " + "stream[%d].slot_count: %d\n", + i, + link->mst_stream_alloc_table.stream_allocations[i].stream_enc, + i, + link->mst_stream_alloc_table.stream_allocations[i].vcp_id, + i, + link->mst_stream_alloc_table.stream_allocations[i].slot_count); + } + + ASSERT(proposed_table.stream_count > 0); + + /* program DP source TX for payload */ + link_encoder->funcs->update_mst_stream_allocation_table( + link_encoder, + &link->mst_stream_alloc_table); + + /* send down message */ + dm_helpers_dp_mst_poll_for_allocation_change_trigger( + stream->ctx, + &stream->public); + + dm_helpers_dp_mst_send_payload_allocation( + stream->ctx, + &stream->public, + true); + + /* slot X.Y for only current stream */ + pbn_per_slot = get_pbn_per_slot(stream); + pbn = get_pbn_from_timing(pipe_ctx); + avg_time_slots_per_mtp = dal_fixed31_32_div(pbn, pbn_per_slot); + + stream_encoder->funcs->set_mst_bandwidth( + stream_encoder, + avg_time_slots_per_mtp); + + return DC_OK; + +} + +static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx) +{ + struct core_stream *stream = pipe_ctx->stream; + struct core_link *link = stream->sink->link; + struct link_encoder *link_encoder = link->link_enc; + struct stream_encoder *stream_encoder = pipe_ctx->stream_enc; + struct dp_mst_stream_allocation_table proposed_table = {0}; + struct fixed31_32 avg_time_slots_per_mtp = dal_fixed31_32_from_int(0); + uint8_t i; + bool mst_mode = (link->public.type == dc_connection_mst_branch); + + /* deallocate_mst_payload is called before disable link. When mode or + * disable/enable monitor, new stream is created which is not in link + * stream[] yet. For this, payload is not allocated yet, so de-alloc + * should not done. For new mode set, map_resources will get engine + * for new stream, so stream_enc->id should be validated until here. + */ + + /* slot X.Y */ + stream_encoder->funcs->set_mst_bandwidth( + stream_encoder, + avg_time_slots_per_mtp); + + /* TODO: which component is responsible for remove payload table? */ + if (mst_mode) { + if (dm_helpers_dp_mst_write_payload_allocation_table( + stream->ctx, + &stream->public, + &proposed_table, + false)) { + + update_mst_stream_alloc_table( + link, pipe_ctx->stream_enc, &proposed_table); + } + else { + dm_logger_write(link->ctx->logger, LOG_WARNING, + "Failed to update" + "MST allocation table for" + "pipe idx:%d\n", + pipe_ctx->pipe_idx); + } + } + + dm_logger_write(link->ctx->logger, LOG_MST, + "%s" + "stream_count: %d: ", + __func__, + link->mst_stream_alloc_table.stream_count); + + for (i = 0; i < MAX_CONTROLLER_NUM; i++) { + dm_logger_write(link->ctx->logger, LOG_MST, + "stream_enc[%d]: 0x%x " + "stream[%d].vcp_id: %d " + "stream[%d].slot_count: %d\n", + i, + link->mst_stream_alloc_table.stream_allocations[i].stream_enc, + i, + link->mst_stream_alloc_table.stream_allocations[i].vcp_id, + i, + link->mst_stream_alloc_table.stream_allocations[i].slot_count); + } + + link_encoder->funcs->update_mst_stream_allocation_table( + link_encoder, + &link->mst_stream_alloc_table); + + if (mst_mode) { + dm_helpers_dp_mst_poll_for_allocation_change_trigger( + stream->ctx, + &stream->public); + + dm_helpers_dp_mst_send_payload_allocation( + stream->ctx, + &stream->public, + false); + } + + return DC_OK; +} + +void core_link_enable_stream(struct pipe_ctx *pipe_ctx) +{ + struct core_dc *core_dc = DC_TO_CORE(pipe_ctx->stream->ctx->dc); + + if (DC_OK != enable_link(pipe_ctx)) { + BREAK_TO_DEBUGGER(); + return; + } + + core_dc->hwss.enable_stream(pipe_ctx); + + if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) + allocate_mst_payload(pipe_ctx); +} + +void core_link_disable_stream(struct pipe_ctx *pipe_ctx) +{ + struct core_dc *core_dc = DC_TO_CORE(pipe_ctx->stream->ctx->dc); + + if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) + deallocate_mst_payload(pipe_ctx); + + core_dc->hwss.disable_stream(pipe_ctx); + + disable_link(pipe_ctx->stream->sink->link, pipe_ctx->stream->signal); +} + diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c new file mode 100644 index 000000000000..6379ccfdb06e --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c @@ -0,0 +1,1098 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "dm_helpers.h" +#include "gpio_service_interface.h" +#include "include/ddc_service_types.h" +#include "include/grph_object_id.h" +#include "include/dpcd_defs.h" +#include "include/logger_interface.h" +#include "include/vector.h" +#include "core_types.h" +#include "dc_link_ddc.h" + +#define AUX_POWER_UP_WA_DELAY 500 +#define I2C_OVER_AUX_DEFER_WA_DELAY 70 + +/* CV smart dongle slave address for retrieving supported HDTV modes*/ +#define CV_SMART_DONGLE_ADDRESS 0x20 +/* DVI-HDMI dongle slave address for retrieving dongle signature*/ +#define DVI_HDMI_DONGLE_ADDRESS 0x68 +static const int8_t dvi_hdmi_dongle_signature_str[] = "6140063500G"; +struct dvi_hdmi_dongle_signature_data { + int8_t vendor[3];/* "AMD" */ + uint8_t version[2]; + uint8_t size; + int8_t id[11];/* "6140063500G"*/ +}; +/* DP-HDMI dongle slave address for retrieving dongle signature*/ +#define DP_HDMI_DONGLE_ADDRESS 0x40 +static const uint8_t dp_hdmi_dongle_signature_str[] = "DP-HDMI ADAPTOR"; +#define DP_HDMI_DONGLE_SIGNATURE_EOT 0x04 + +struct dp_hdmi_dongle_signature_data { + int8_t id[15];/* "DP-HDMI ADAPTOR"*/ + uint8_t eot;/* end of transmition '\x4' */ +}; + +/* Address range from 0x00 to 0x1F.*/ +#define DP_ADAPTOR_TYPE2_SIZE 0x20 +#define DP_ADAPTOR_TYPE2_REG_ID 0x10 +#define DP_ADAPTOR_TYPE2_REG_MAX_TMDS_CLK 0x1D +/* Identifies adaptor as Dual-mode adaptor */ +#define DP_ADAPTOR_TYPE2_ID 0xA0 +/* MHz*/ +#define DP_ADAPTOR_TYPE2_MAX_TMDS_CLK 600 +/* MHz*/ +#define DP_ADAPTOR_TYPE2_MIN_TMDS_CLK 25 +/* kHZ*/ +#define DP_ADAPTOR_DVI_MAX_TMDS_CLK 165000 +/* kHZ*/ +#define DP_ADAPTOR_HDMI_SAFE_MAX_TMDS_CLK 165000 + +#define DDC_I2C_COMMAND_ENGINE I2C_COMMAND_ENGINE_SW + +enum edid_read_result { + EDID_READ_RESULT_EDID_MATCH = 0, + EDID_READ_RESULT_EDID_MISMATCH, + EDID_READ_RESULT_CHECKSUM_READ_ERR, + EDID_READ_RESULT_VENDOR_READ_ERR +}; + +/* SCDC Address defines (HDMI 2.0)*/ +#define HDMI_SCDC_WRITE_UPDATE_0_ARRAY 3 +#define HDMI_SCDC_ADDRESS 0x54 +#define HDMI_SCDC_SINK_VERSION 0x01 +#define HDMI_SCDC_SOURCE_VERSION 0x02 +#define HDMI_SCDC_UPDATE_0 0x10 +#define HDMI_SCDC_TMDS_CONFIG 0x20 +#define HDMI_SCDC_SCRAMBLER_STATUS 0x21 +#define HDMI_SCDC_CONFIG_0 0x30 +#define HDMI_SCDC_STATUS_FLAGS 0x40 +#define HDMI_SCDC_ERR_DETECT 0x50 +#define HDMI_SCDC_TEST_CONFIG 0xC0 + +union hdmi_scdc_update_read_data { + uint8_t byte[2]; + struct { + uint8_t STATUS_UPDATE:1; + uint8_t CED_UPDATE:1; + uint8_t RR_TEST:1; + uint8_t RESERVED:5; + uint8_t RESERVED2:8; + } fields; +}; + +union hdmi_scdc_status_flags_data { + uint8_t byte[2]; + struct { + uint8_t CLOCK_DETECTED:1; + uint8_t CH0_LOCKED:1; + uint8_t CH1_LOCKED:1; + uint8_t CH2_LOCKED:1; + uint8_t RESERVED:4; + uint8_t RESERVED2:8; + } fields; +}; + +union hdmi_scdc_ced_data { + uint8_t byte[7]; + struct { + uint8_t CH0_8LOW:8; + uint8_t CH0_7HIGH:7; + uint8_t CH0_VALID:1; + uint8_t CH1_8LOW:8; + uint8_t CH1_7HIGH:7; + uint8_t CH1_VALID:1; + uint8_t CH2_8LOW:8; + uint8_t CH2_7HIGH:7; + uint8_t CH2_VALID:1; + uint8_t CHECKSUM:8; + } fields; +}; + +union hdmi_scdc_test_config_Data { + uint8_t byte; + struct { + uint8_t TEST_READ_REQUEST_DELAY:7; + uint8_t TEST_READ_REQUEST: 1; + } fields; +}; + +struct i2c_payloads { + struct vector payloads; +}; + +struct aux_payloads { + struct vector payloads; +}; + +struct i2c_payloads *dal_ddc_i2c_payloads_create(struct dc_context *ctx, uint32_t count) +{ + struct i2c_payloads *payloads; + + payloads = dm_alloc(sizeof(struct i2c_payloads)); + + if (!payloads) + return NULL; + + if (dal_vector_construct( + &payloads->payloads, ctx, count, sizeof(struct i2c_payload))) + return payloads; + + dm_free(payloads); + return NULL; + +} + +struct i2c_payload *dal_ddc_i2c_payloads_get(struct i2c_payloads *p) +{ + return (struct i2c_payload *)p->payloads.container; +} + +uint32_t dal_ddc_i2c_payloads_get_count(struct i2c_payloads *p) +{ + return p->payloads.count; +} + +void dal_ddc_i2c_payloads_destroy(struct i2c_payloads **p) +{ + if (!p || !*p) + return; + dal_vector_destruct(&(*p)->payloads); + dm_free(*p); + *p = NULL; + +} + +struct aux_payloads *dal_ddc_aux_payloads_create(struct dc_context *ctx, uint32_t count) +{ + struct aux_payloads *payloads; + + payloads = dm_alloc(sizeof(struct aux_payloads)); + + if (!payloads) + return NULL; + + if (dal_vector_construct( + &payloads->payloads, ctx, count, sizeof(struct aux_payloads))) + return payloads; + + dm_free(payloads); + return NULL; +} + +struct aux_payload *dal_ddc_aux_payloads_get(struct aux_payloads *p) +{ + return (struct aux_payload *)p->payloads.container; +} + +uint32_t dal_ddc_aux_payloads_get_count(struct aux_payloads *p) +{ + return p->payloads.count; +} + +void dal_ddc_aux_payloads_destroy(struct aux_payloads **p) +{ + if (!p || !*p) + return; + + dal_vector_destruct(&(*p)->payloads); + dm_free(*p); + *p = NULL; +} + +#define DDC_MIN(a, b) (((a) < (b)) ? (a) : (b)) + +void dal_ddc_i2c_payloads_add( + struct i2c_payloads *payloads, + uint32_t address, + uint32_t len, + uint8_t *data, + bool write) +{ + uint32_t payload_size = EDID_SEGMENT_SIZE; + uint32_t pos; + + for (pos = 0; pos < len; pos += payload_size) { + struct i2c_payload payload = { + .write = write, + .address = address, + .length = DDC_MIN(payload_size, len - pos), + .data = data + pos }; + dal_vector_append(&payloads->payloads, &payload); + } + +} + +void dal_ddc_aux_payloads_add( + struct aux_payloads *payloads, + uint32_t address, + uint32_t len, + uint8_t *data, + bool write) +{ + uint32_t payload_size = DEFAULT_AUX_MAX_DATA_SIZE; + uint32_t pos; + + for (pos = 0; pos < len; pos += payload_size) { + struct aux_payload payload = { + .i2c_over_aux = true, + .write = write, + .address = address, + .length = DDC_MIN(payload_size, len - pos), + .data = data + pos }; + dal_vector_append(&payloads->payloads, &payload); + } +} + +static bool construct( + struct ddc_service *ddc_service, + struct ddc_service_init_data *init_data) +{ + enum connector_id connector_id = + dal_graphics_object_id_get_connector_id(init_data->id); + + struct gpio_service *gpio_service = init_data->ctx->gpio_service; + struct graphics_object_i2c_info i2c_info; + struct gpio_ddc_hw_info hw_info; + struct dc_bios *dcb = init_data->ctx->dc_bios; + + ddc_service->link = init_data->link; + ddc_service->ctx = init_data->ctx; + + if (BP_RESULT_OK != dcb->funcs->get_i2c_info(dcb, init_data->id, &i2c_info)) { + ddc_service->ddc_pin = NULL; + } else { + hw_info.ddc_channel = i2c_info.i2c_line; + hw_info.hw_supported = i2c_info.i2c_hw_assist; + + ddc_service->ddc_pin = dal_gpio_create_ddc( + gpio_service, + i2c_info.gpio_info.clk_a_register_index, + 1 << i2c_info.gpio_info.clk_a_shift, + &hw_info); + } + + ddc_service->flags.EDID_QUERY_DONE_ONCE = false; + ddc_service->flags.FORCE_READ_REPEATED_START = false; + ddc_service->flags.EDID_STRESS_READ = false; + + ddc_service->flags.IS_INTERNAL_DISPLAY = + connector_id == CONNECTOR_ID_EDP || + connector_id == CONNECTOR_ID_LVDS; + + ddc_service->wa.raw = 0; + return true; +} + +struct ddc_service *dal_ddc_service_create( + struct ddc_service_init_data *init_data) +{ + struct ddc_service *ddc_service; + + ddc_service = dm_alloc(sizeof(struct ddc_service)); + + if (!ddc_service) + return NULL; + + if (construct(ddc_service, init_data)) + return ddc_service; + + dm_free(ddc_service); + return NULL; +} + +static void destruct(struct ddc_service *ddc) +{ + if (ddc->ddc_pin) + dal_gpio_destroy_ddc(&ddc->ddc_pin); +} + +void dal_ddc_service_destroy(struct ddc_service **ddc) +{ + if (!ddc || !*ddc) { + BREAK_TO_DEBUGGER(); + return; + } + destruct(*ddc); + dm_free(*ddc); + *ddc = NULL; +} + +enum ddc_service_type dal_ddc_service_get_type(struct ddc_service *ddc) +{ + return DDC_SERVICE_TYPE_CONNECTOR; +} + +void dal_ddc_service_set_transaction_type( + struct ddc_service *ddc, + enum ddc_transaction_type type) +{ + ddc->transaction_type = type; +} + +bool dal_ddc_service_is_in_aux_transaction_mode(struct ddc_service *ddc) +{ + switch (ddc->transaction_type) { + case DDC_TRANSACTION_TYPE_I2C_OVER_AUX: + case DDC_TRANSACTION_TYPE_I2C_OVER_AUX_WITH_DEFER: + case DDC_TRANSACTION_TYPE_I2C_OVER_AUX_RETRY_DEFER: + return true; + default: + break; + } + return false; +} + +void ddc_service_set_dongle_type(struct ddc_service *ddc, + enum display_dongle_type dongle_type) +{ + ddc->dongle_type = dongle_type; +} + +static uint32_t defer_delay_converter_wa( + struct ddc_service *ddc, + uint32_t defer_delay) +{ + struct core_link *link = ddc->link; + + if (link->dpcd_caps.branch_dev_id == DP_BRANCH_DEVICE_ID_4 && + !memcmp(link->dpcd_caps.branch_dev_name, + DP_DVI_CONVERTER_ID_4, + sizeof(link->dpcd_caps.branch_dev_name))) + return defer_delay > I2C_OVER_AUX_DEFER_WA_DELAY ? + defer_delay : I2C_OVER_AUX_DEFER_WA_DELAY; + + return defer_delay; +} + +#define DP_TRANSLATOR_DELAY 5 + +static uint32_t get_defer_delay(struct ddc_service *ddc) +{ + uint32_t defer_delay = 0; + + switch (ddc->transaction_type) { + case DDC_TRANSACTION_TYPE_I2C_OVER_AUX: + if ((DISPLAY_DONGLE_DP_VGA_CONVERTER == ddc->dongle_type) || + (DISPLAY_DONGLE_DP_DVI_CONVERTER == ddc->dongle_type) || + (DISPLAY_DONGLE_DP_HDMI_CONVERTER == + ddc->dongle_type)) { + + defer_delay = DP_TRANSLATOR_DELAY; + + defer_delay = + defer_delay_converter_wa(ddc, defer_delay); + + } else /*sink has a delay different from an Active Converter*/ + defer_delay = 0; + break; + case DDC_TRANSACTION_TYPE_I2C_OVER_AUX_WITH_DEFER: + defer_delay = DP_TRANSLATOR_DELAY; + break; + default: + break; + } + return defer_delay; +} + +static bool i2c_read( + struct ddc_service *ddc, + uint32_t address, + uint8_t *buffer, + uint32_t len) +{ + uint8_t offs_data = 0; + struct i2c_payload payloads[2] = { + { + .write = true, + .address = address, + .length = 1, + .data = &offs_data }, + { + .write = false, + .address = address, + .length = len, + .data = buffer } }; + + struct i2c_command command = { + .payloads = payloads, + .number_of_payloads = 2, + .engine = DDC_I2C_COMMAND_ENGINE, + .speed = ddc->ctx->dc->caps.i2c_speed_in_khz }; + + return dm_helpers_submit_i2c( + ddc->ctx, + &ddc->link->public, + &command); +} + +static uint8_t aux_read_edid_block( + struct ddc_service *ddc, + uint8_t address, + uint8_t index, + uint8_t *buf) +{ + struct aux_command cmd = { + .payloads = NULL, + .number_of_payloads = 0, + .defer_delay = get_defer_delay(ddc), + .max_defer_write_retry = 0 }; + + uint8_t retrieved = 0; + uint8_t base_offset = + (index % DDC_EDID_BLOCKS_PER_SEGMENT) * DDC_EDID_BLOCK_SIZE; + uint8_t segment = index / DDC_EDID_BLOCKS_PER_SEGMENT; + + for (retrieved = 0; retrieved < DDC_EDID_BLOCK_SIZE; + retrieved += DEFAULT_AUX_MAX_DATA_SIZE) { + + uint8_t offset = base_offset + retrieved; + + struct aux_payload payloads[3] = { + { + .i2c_over_aux = true, + .write = true, + .address = DDC_EDID_SEGMENT_ADDRESS, + .length = 1, + .data = &segment }, + { + .i2c_over_aux = true, + .write = true, + .address = address, + .length = 1, + .data = &offset }, + { + .i2c_over_aux = true, + .write = false, + .address = address, + .length = DEFAULT_AUX_MAX_DATA_SIZE, + .data = &buf[retrieved] } }; + + if (segment == 0) { + cmd.payloads = &payloads[1]; + cmd.number_of_payloads = 2; + } else { + cmd.payloads = payloads; + cmd.number_of_payloads = 3; + } + + if (!dal_i2caux_submit_aux_command( + ddc->ctx->i2caux, + ddc->ddc_pin, + &cmd)) + /* cannot read, break*/ + break; + } + + /* Reset segment to 0. Needed by some panels */ + if (0 != segment) { + struct aux_payload payloads[1] = { { + .i2c_over_aux = true, + .write = true, + .address = DDC_EDID_SEGMENT_ADDRESS, + .length = 1, + .data = &segment } }; + bool result = false; + + segment = 0; + + cmd.number_of_payloads = ARRAY_SIZE(payloads); + cmd.payloads = payloads; + + result = dal_i2caux_submit_aux_command( + ddc->ctx->i2caux, + ddc->ddc_pin, + &cmd); + + if (false == result) + dm_logger_write( + ddc->ctx->logger, LOG_ERROR, + "%s: Writing of EDID Segment (0x30) failed!\n", + __func__); + } + + return retrieved; +} + +static uint8_t i2c_read_edid_block( + struct ddc_service *ddc, + uint8_t address, + uint8_t index, + uint8_t *buf) +{ + bool ret = false; + uint8_t offset = (index % DDC_EDID_BLOCKS_PER_SEGMENT) * + DDC_EDID_BLOCK_SIZE; + uint8_t segment = index / DDC_EDID_BLOCKS_PER_SEGMENT; + + struct i2c_command cmd = { + .payloads = NULL, + .number_of_payloads = 0, + .engine = DDC_I2C_COMMAND_ENGINE, + .speed = ddc->ctx->dc->caps.i2c_speed_in_khz }; + + struct i2c_payload payloads[3] = { + { + .write = true, + .address = DDC_EDID_SEGMENT_ADDRESS, + .length = 1, + .data = &segment }, + { + .write = true, + .address = address, + .length = 1, + .data = &offset }, + { + .write = false, + .address = address, + .length = DDC_EDID_BLOCK_SIZE, + .data = buf } }; +/* + * Some I2C engines don't handle stop/start between write-offset and read-data + * commands properly. For those displays, we have to force the newer E-DDC + * behavior of repeated-start which can be enabled by runtime parameter. */ +/* Originally implemented for OnLive using NXP receiver chip */ + + if (index == 0 && !ddc->flags.FORCE_READ_REPEATED_START) { + /* base block, use use DDC2B, submit as 2 commands */ + cmd.payloads = &payloads[1]; + cmd.number_of_payloads = 1; + + if (dm_helpers_submit_i2c( + ddc->ctx, + &ddc->link->public, + &cmd)) { + + cmd.payloads = &payloads[2]; + cmd.number_of_payloads = 1; + + ret = dm_helpers_submit_i2c( + ddc->ctx, + &ddc->link->public, + &cmd); + } + + } else { + /* + * extension block use E-DDC, submit as 1 command + * or if repeated-start is forced by runtime parameter + */ + if (segment != 0) { + /* include segment offset in command*/ + cmd.payloads = payloads; + cmd.number_of_payloads = 3; + } else { + /* we are reading first segment, + * segment offset is not required */ + cmd.payloads = &payloads[1]; + cmd.number_of_payloads = 2; + } + + ret = dm_helpers_submit_i2c( + ddc->ctx, + &ddc->link->public, + &cmd); + } + + return ret ? DDC_EDID_BLOCK_SIZE : 0; +} + +static uint32_t query_edid_block( + struct ddc_service *ddc, + uint8_t address, + uint8_t index, + uint8_t *buf, + uint32_t size) +{ + uint32_t size_retrieved = 0; + + if (size < DDC_EDID_BLOCK_SIZE) + return 0; + + if (dal_ddc_service_is_in_aux_transaction_mode(ddc)) { + size_retrieved = + aux_read_edid_block(ddc, address, index, buf); + } else { + size_retrieved = + i2c_read_edid_block(ddc, address, index, buf); + } + + return size_retrieved; +} + +#define DDC_DPCD_EDID_CHECKSUM_WRITE_ADDRESS 0x261 +#define DDC_TEST_ACK_ADDRESS 0x260 +#define DDC_DPCD_EDID_TEST_ACK 0x04 +#define DDC_DPCD_EDID_TEST_MASK 0x04 +#define DDC_DPCD_TEST_REQUEST_ADDRESS 0x218 + +/* AG TODO GO throug DM callback here like for DPCD */ + +static void write_dp_edid_checksum( + struct ddc_service *ddc, + uint8_t checksum) +{ + uint8_t dpcd_data; + + dal_ddc_service_read_dpcd_data( + ddc, + DDC_DPCD_TEST_REQUEST_ADDRESS, + &dpcd_data, + 1); + + if (dpcd_data & DDC_DPCD_EDID_TEST_MASK) { + + dal_ddc_service_write_dpcd_data( + ddc, + DDC_DPCD_EDID_CHECKSUM_WRITE_ADDRESS, + &checksum, + 1); + + dpcd_data = DDC_DPCD_EDID_TEST_ACK; + + dal_ddc_service_write_dpcd_data( + ddc, + DDC_TEST_ACK_ADDRESS, + &dpcd_data, + 1); + } +} + +uint32_t dal_ddc_service_edid_query(struct ddc_service *ddc) +{ + uint32_t bytes_read = 0; + uint32_t ext_cnt = 0; + + uint8_t address; + uint32_t i; + + for (address = DDC_EDID_ADDRESS_START; + address <= DDC_EDID_ADDRESS_END; ++address) { + + bytes_read = query_edid_block( + ddc, + address, + 0, + ddc->edid_buf, + sizeof(ddc->edid_buf) - bytes_read); + + if (bytes_read != DDC_EDID_BLOCK_SIZE) + continue; + + /* get the number of ext blocks*/ + ext_cnt = ddc->edid_buf[DDC_EDID_EXT_COUNT_OFFSET]; + + /* EDID 2.0, need to read 1 more block because EDID2.0 is + * 256 byte in size*/ + if (ddc->edid_buf[DDC_EDID_20_SIGNATURE_OFFSET] == + DDC_EDID_20_SIGNATURE) + ext_cnt = 1; + + for (i = 0; i < ext_cnt; i++) { + /* read additional ext blocks accordingly */ + bytes_read += query_edid_block( + ddc, + address, + i+1, + &ddc->edid_buf[bytes_read], + sizeof(ddc->edid_buf) - bytes_read); + } + + /*this is special code path for DP compliance*/ + if (DDC_TRANSACTION_TYPE_I2C_OVER_AUX == ddc->transaction_type) + write_dp_edid_checksum( + ddc, + ddc->edid_buf[(ext_cnt * DDC_EDID_BLOCK_SIZE) + + DDC_EDID1X_CHECKSUM_OFFSET]); + + /*remembers the address where we fetch the EDID from + * for later signature check use */ + ddc->address = address; + + break;/* already read edid, done*/ + } + + ddc->edid_buf_len = bytes_read; + return bytes_read; +} + +uint32_t dal_ddc_service_get_edid_buf_len(struct ddc_service *ddc) +{ + return ddc->edid_buf_len; +} + +void dal_ddc_service_get_edid_buf(struct ddc_service *ddc, uint8_t *edid_buf) +{ + memmove(edid_buf, + ddc->edid_buf, ddc->edid_buf_len); +} + +void dal_ddc_service_i2c_query_dp_dual_mode_adaptor( + struct ddc_service *ddc, + struct display_sink_capability *sink_cap) +{ + uint8_t i; + bool is_valid_hdmi_signature; + enum display_dongle_type *dongle = &sink_cap->dongle_type; + uint8_t type2_dongle_buf[DP_ADAPTOR_TYPE2_SIZE]; + bool is_type2_dongle = false; + struct dp_hdmi_dongle_signature_data *dongle_signature; + + /* Assume we have no valid DP passive dongle connected */ + *dongle = DISPLAY_DONGLE_NONE; + sink_cap->max_hdmi_pixel_clock = DP_ADAPTOR_HDMI_SAFE_MAX_TMDS_CLK; + + /* Read DP-HDMI dongle I2c (no response interpreted as DP-DVI dongle)*/ + if (!i2c_read( + ddc, + DP_HDMI_DONGLE_ADDRESS, + type2_dongle_buf, + sizeof(type2_dongle_buf))) { + *dongle = DISPLAY_DONGLE_DP_DVI_DONGLE; + sink_cap->max_hdmi_pixel_clock = DP_ADAPTOR_DVI_MAX_TMDS_CLK; + + CONN_DATA_DETECT(ddc->link, type2_dongle_buf, sizeof(type2_dongle_buf), + "DP-DVI passive dongle %dMhz: ", + DP_ADAPTOR_DVI_MAX_TMDS_CLK / 1000); + return; + } + + /* Check if Type 2 dongle.*/ + if (type2_dongle_buf[DP_ADAPTOR_TYPE2_REG_ID] == DP_ADAPTOR_TYPE2_ID) + is_type2_dongle = true; + + dongle_signature = + (struct dp_hdmi_dongle_signature_data *)type2_dongle_buf; + + is_valid_hdmi_signature = true; + + /* Check EOT */ + if (dongle_signature->eot != DP_HDMI_DONGLE_SIGNATURE_EOT) { + is_valid_hdmi_signature = false; + } + + /* Check signature */ + for (i = 0; i < sizeof(dongle_signature->id); ++i) { + /* If its not the right signature, + * skip mismatch in subversion byte.*/ + if (dongle_signature->id[i] != + dp_hdmi_dongle_signature_str[i] && i != 3) { + + if (is_type2_dongle) { + is_valid_hdmi_signature = false; + break; + } + + } + } + + if (is_type2_dongle) { + uint32_t max_tmds_clk = + type2_dongle_buf[DP_ADAPTOR_TYPE2_REG_MAX_TMDS_CLK]; + + max_tmds_clk = max_tmds_clk * 2 + max_tmds_clk / 2; + + if (0 == max_tmds_clk || + max_tmds_clk < DP_ADAPTOR_TYPE2_MIN_TMDS_CLK || + max_tmds_clk > DP_ADAPTOR_TYPE2_MAX_TMDS_CLK) { + *dongle = DISPLAY_DONGLE_DP_DVI_DONGLE; + + CONN_DATA_DETECT(ddc->link, type2_dongle_buf, + sizeof(type2_dongle_buf), + "DP-DVI passive dongle %dMhz: ", + DP_ADAPTOR_DVI_MAX_TMDS_CLK / 1000); + } else { + if (is_valid_hdmi_signature == true) { + *dongle = DISPLAY_DONGLE_DP_HDMI_DONGLE; + + CONN_DATA_DETECT(ddc->link, type2_dongle_buf, + sizeof(type2_dongle_buf), + "Type 2 DP-HDMI passive dongle %dMhz: ", + max_tmds_clk); + } else { + *dongle = DISPLAY_DONGLE_DP_HDMI_MISMATCHED_DONGLE; + + CONN_DATA_DETECT(ddc->link, type2_dongle_buf, + sizeof(type2_dongle_buf), + "Type 2 DP-HDMI passive dongle (no signature) %dMhz: ", + max_tmds_clk); + + } + + /* Multiply by 1000 to convert to kHz. */ + sink_cap->max_hdmi_pixel_clock = + max_tmds_clk * 1000; + } + + } else { + if (is_valid_hdmi_signature == true) { + *dongle = DISPLAY_DONGLE_DP_HDMI_DONGLE; + + CONN_DATA_DETECT(ddc->link, type2_dongle_buf, + sizeof(type2_dongle_buf), + "Type 1 DP-HDMI passive dongle %dMhz: ", + sink_cap->max_hdmi_pixel_clock / 1000); + } else { + *dongle = DISPLAY_DONGLE_DP_HDMI_MISMATCHED_DONGLE; + + CONN_DATA_DETECT(ddc->link, type2_dongle_buf, + sizeof(type2_dongle_buf), + "Type 1 DP-HDMI passive dongle (no signature) %dMhz: ", + sink_cap->max_hdmi_pixel_clock / 1000); + } + } + + return; +} + +enum { + DP_SINK_CAP_SIZE = + DPCD_ADDRESS_EDP_CONFIG_CAP - DPCD_ADDRESS_DPCD_REV + 1 +}; + +bool dal_ddc_service_query_ddc_data( + struct ddc_service *ddc, + uint32_t address, + uint8_t *write_buf, + uint32_t write_size, + uint8_t *read_buf, + uint32_t read_size) +{ + bool ret; + uint32_t payload_size = + dal_ddc_service_is_in_aux_transaction_mode(ddc) ? + DEFAULT_AUX_MAX_DATA_SIZE : EDID_SEGMENT_SIZE; + + uint32_t write_payloads = + (write_size + payload_size - 1) / payload_size; + + uint32_t read_payloads = + (read_size + payload_size - 1) / payload_size; + + uint32_t payloads_num = write_payloads + read_payloads; + + if (write_size > EDID_SEGMENT_SIZE || read_size > EDID_SEGMENT_SIZE) + return false; + + /*TODO: len of payload data for i2c and aux is uint8!!!!, + * but we want to read 256 over i2c!!!!*/ + if (dal_ddc_service_is_in_aux_transaction_mode(ddc)) { + + struct aux_payloads *payloads = + dal_ddc_aux_payloads_create(ddc->ctx, payloads_num); + + struct aux_command command = { + .payloads = dal_ddc_aux_payloads_get(payloads), + .number_of_payloads = 0, + .defer_delay = get_defer_delay(ddc), + .max_defer_write_retry = 0 }; + + dal_ddc_aux_payloads_add( + payloads, address, write_size, write_buf, true); + + dal_ddc_aux_payloads_add( + payloads, address, read_size, read_buf, false); + + command.number_of_payloads = + dal_ddc_aux_payloads_get_count(payloads); + + ret = dal_i2caux_submit_aux_command( + ddc->ctx->i2caux, + ddc->ddc_pin, + &command); + + dal_ddc_aux_payloads_destroy(&payloads); + + } else { + struct i2c_payloads *payloads = + dal_ddc_i2c_payloads_create(ddc->ctx, payloads_num); + + struct i2c_command command = { + .payloads = dal_ddc_i2c_payloads_get(payloads), + .number_of_payloads = 0, + .engine = DDC_I2C_COMMAND_ENGINE, + .speed = ddc->ctx->dc->caps.i2c_speed_in_khz }; + + dal_ddc_i2c_payloads_add( + payloads, address, write_size, write_buf, true); + + dal_ddc_i2c_payloads_add( + payloads, address, read_size, read_buf, false); + + command.number_of_payloads = + dal_ddc_i2c_payloads_get_count(payloads); + + ret = dm_helpers_submit_i2c( + ddc->ctx, + &ddc->link->public, + &command); + + dal_ddc_i2c_payloads_destroy(&payloads); + } + + return ret; +} + +enum ddc_result dal_ddc_service_read_dpcd_data( + struct ddc_service *ddc, + uint32_t address, + uint8_t *data, + uint32_t len) +{ + struct aux_payload read_payload = { + .i2c_over_aux = false, + .write = false, + .address = address, + .length = len, + .data = data, + }; + struct aux_command command = { + .payloads = &read_payload, + .number_of_payloads = 1, + .defer_delay = 0, + .max_defer_write_retry = 0, + }; + + if (len > DEFAULT_AUX_MAX_DATA_SIZE) { + BREAK_TO_DEBUGGER(); + return DDC_RESULT_FAILED_INVALID_OPERATION; + } + + if (dal_i2caux_submit_aux_command( + ddc->ctx->i2caux, + ddc->ddc_pin, + &command)) + return DDC_RESULT_SUCESSFULL; + + return DDC_RESULT_FAILED_OPERATION; +} + +enum ddc_result dal_ddc_service_write_dpcd_data( + struct ddc_service *ddc, + uint32_t address, + const uint8_t *data, + uint32_t len) +{ + struct aux_payload write_payload = { + .i2c_over_aux = false, + .write = true, + .address = address, + .length = len, + .data = (uint8_t *)data, + }; + struct aux_command command = { + .payloads = &write_payload, + .number_of_payloads = 1, + .defer_delay = 0, + .max_defer_write_retry = 0, + }; + + if (len > DEFAULT_AUX_MAX_DATA_SIZE) { + BREAK_TO_DEBUGGER(); + return DDC_RESULT_FAILED_INVALID_OPERATION; + } + + if (dal_i2caux_submit_aux_command( + ddc->ctx->i2caux, + ddc->ddc_pin, + &command)) + return DDC_RESULT_SUCESSFULL; + + return DDC_RESULT_FAILED_OPERATION; +} + +/*test only function*/ +void dal_ddc_service_set_ddc_pin( + struct ddc_service *ddc_service, + struct ddc *ddc) +{ + ddc_service->ddc_pin = ddc; +} + +struct ddc *dal_ddc_service_get_ddc_pin(struct ddc_service *ddc_service) +{ + return ddc_service->ddc_pin; +} + +void dal_ddc_service_write_scdc_data(struct ddc_service *ddc_service, + uint32_t pix_clk, + bool lte_340_scramble) +{ + bool over_340_mhz = pix_clk > 340000 ? 1 : 0; + uint8_t slave_address = HDMI_SCDC_ADDRESS; + uint8_t offset = HDMI_SCDC_SINK_VERSION; + uint8_t sink_version = 0; + uint8_t write_buffer[2] = {0}; + /*Lower than 340 Scramble bit from SCDC caps*/ + + dal_ddc_service_query_ddc_data(ddc_service, slave_address, &offset, + sizeof(offset), &sink_version, sizeof(sink_version)); + if (sink_version == 1) { + /*Source Version = 1*/ + write_buffer[0] = HDMI_SCDC_SOURCE_VERSION; + write_buffer[1] = 1; + dal_ddc_service_query_ddc_data(ddc_service, slave_address, + write_buffer, sizeof(write_buffer), NULL, 0); + /*Read Request from SCDC caps*/ + } + write_buffer[0] = HDMI_SCDC_TMDS_CONFIG; + + if (over_340_mhz) { + write_buffer[1] = 3; + } else if (lte_340_scramble) { + write_buffer[1] = 1; + } else { + write_buffer[1] = 0; + } + dal_ddc_service_query_ddc_data(ddc_service, slave_address, write_buffer, + sizeof(write_buffer), NULL, 0); +} + +void dal_ddc_service_read_scdc_data(struct ddc_service *ddc_service) +{ + uint8_t slave_address = HDMI_SCDC_ADDRESS; + uint8_t offset = HDMI_SCDC_TMDS_CONFIG; + uint8_t tmds_config = 0; + + dal_ddc_service_query_ddc_data(ddc_service, slave_address, &offset, + sizeof(offset), &tmds_config, sizeof(tmds_config)); + if (tmds_config & 0x1) { + union hdmi_scdc_status_flags_data status_data = { {0} }; + uint8_t scramble_status = 0; + + offset = HDMI_SCDC_SCRAMBLER_STATUS; + dal_ddc_service_query_ddc_data(ddc_service, slave_address, + &offset, sizeof(offset), &scramble_status, + sizeof(scramble_status)); + offset = HDMI_SCDC_STATUS_FLAGS; + dal_ddc_service_query_ddc_data(ddc_service, slave_address, + &offset, sizeof(offset), status_data.byte, + sizeof(status_data.byte)); + } +} + 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 new file mode 100644 index 000000000000..2585ec332e58 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -0,0 +1,2462 @@ +/* Copyright 2015 Advanced Micro Devices, Inc. */ +#include "dm_services.h" +#include "dc.h" +#include "dc_link_dp.h" +#include "dm_helpers.h" + +#include "inc/core_types.h" +#include "link_hwss.h" +#include "dc_link_ddc.h" +#include "core_status.h" +#include "dpcd_defs.h" + +#include "core_dc.h" + +/* maximum pre emphasis level allowed for each voltage swing level*/ +static const enum dc_pre_emphasis voltage_swing_to_pre_emphasis[] = { + PRE_EMPHASIS_LEVEL3, + PRE_EMPHASIS_LEVEL2, + PRE_EMPHASIS_LEVEL1, + PRE_EMPHASIS_DISABLED }; + +enum { + POST_LT_ADJ_REQ_LIMIT = 6, + POST_LT_ADJ_REQ_TIMEOUT = 200 +}; + +enum { + LINK_TRAINING_MAX_RETRY_COUNT = 5, + /* to avoid infinite loop where-in the receiver + * switches between different VS + */ + LINK_TRAINING_MAX_CR_RETRY = 100 +}; + +static const struct dc_link_settings link_training_fallback_table[] = { +/* 4320 Mbytes/sec*/ +{ LANE_COUNT_FOUR, LINK_RATE_HIGH3, LINK_SPREAD_DISABLED }, +/* 2160 Mbytes/sec*/ +{ LANE_COUNT_FOUR, LINK_RATE_HIGH2, LINK_SPREAD_DISABLED }, +/* 1080 Mbytes/sec*/ +{ LANE_COUNT_FOUR, LINK_RATE_HIGH, LINK_SPREAD_DISABLED }, +/* 648 Mbytes/sec*/ +{ LANE_COUNT_FOUR, LINK_RATE_LOW, LINK_SPREAD_DISABLED }, +/* 2160 Mbytes/sec*/ +{ LANE_COUNT_TWO, LINK_RATE_HIGH3, LINK_SPREAD_DISABLED }, +/* 1080 Mbytes/sec*/ +{ LANE_COUNT_TWO, LINK_RATE_HIGH2, LINK_SPREAD_DISABLED }, +/* 540 Mbytes/sec*/ +{ LANE_COUNT_TWO, LINK_RATE_HIGH, LINK_SPREAD_DISABLED }, +/* 324 Mbytes/sec*/ +{ LANE_COUNT_TWO, LINK_RATE_LOW, LINK_SPREAD_DISABLED }, +/* 1080 Mbytes/sec*/ +{ LANE_COUNT_ONE, LINK_RATE_HIGH3, LINK_SPREAD_DISABLED }, +/* 540 Mbytes/sec*/ +{ LANE_COUNT_ONE, LINK_RATE_HIGH2, LINK_SPREAD_DISABLED }, +/* 270 Mbytes/sec*/ +{ LANE_COUNT_ONE, LINK_RATE_HIGH, LINK_SPREAD_DISABLED }, +/* 162 Mbytes/sec*/ +{ LANE_COUNT_ONE, LINK_RATE_LOW, LINK_SPREAD_DISABLED } }; + +static void wait_for_training_aux_rd_interval( + struct core_link* link, + uint32_t default_wait_in_micro_secs) +{ + union training_aux_rd_interval training_rd_interval; + + /* overwrite the delay if rev > 1.1*/ + if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) { + /* DP 1.2 or later - retrieve delay through + * "DPCD_ADDR_TRAINING_AUX_RD_INTERVAL" register */ + core_link_read_dpcd( + link, + DPCD_ADDRESS_TRAINING_AUX_RD_INTERVAL, + (uint8_t *)&training_rd_interval, + sizeof(training_rd_interval)); + + if (training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL) + default_wait_in_micro_secs = + training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL * 4000; + } + + udelay(default_wait_in_micro_secs); + + dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING, + "%s:\n wait = %d\n", + __func__, + default_wait_in_micro_secs); +} + +static void dpcd_set_training_pattern( + struct core_link* link, + union dpcd_training_pattern dpcd_pattern) +{ + core_link_write_dpcd( + link, + DPCD_ADDRESS_TRAINING_PATTERN_SET, + &dpcd_pattern.raw, + 1); + + dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING, + "%s\n %x pattern = %x\n", + __func__, + DPCD_ADDRESS_TRAINING_PATTERN_SET, + dpcd_pattern.v1_4.TRAINING_PATTERN_SET); +} + +static void dpcd_set_link_settings( + struct core_link* link, + const struct link_training_settings *lt_settings) +{ + uint8_t rate = (uint8_t) + (lt_settings->link_settings.link_rate); + + union down_spread_ctrl downspread = {{0}}; + union lane_count_set lane_count_set = {{0}}; + uint8_t link_set_buffer[2]; + + downspread.raw = (uint8_t) + (lt_settings->link_settings.link_spread); + + lane_count_set.bits.LANE_COUNT_SET = + lt_settings->link_settings.lane_count; + + lane_count_set.bits.ENHANCED_FRAMING = 1; + + lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED = + link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED; + + link_set_buffer[0] = rate; + link_set_buffer[1] = lane_count_set.raw; + + core_link_write_dpcd(link, DPCD_ADDRESS_LINK_BW_SET, + link_set_buffer, 2); + core_link_write_dpcd(link, DPCD_ADDRESS_DOWNSPREAD_CNTL, + &downspread.raw, sizeof(downspread)); + + dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING, + "%s\n %x rate = %x\n %x lane = %x\n %x spread = %x\n", + __func__, + DPCD_ADDRESS_LINK_BW_SET, + lt_settings->link_settings.link_rate, + DPCD_ADDRESS_LANE_COUNT_SET, + lt_settings->link_settings.lane_count, + DPCD_ADDRESS_DOWNSPREAD_CNTL, + lt_settings->link_settings.link_spread); + +} + +static enum dpcd_training_patterns + hw_training_pattern_to_dpcd_training_pattern( + struct core_link* link, + enum hw_dp_training_pattern pattern) +{ + enum dpcd_training_patterns dpcd_tr_pattern = + DPCD_TRAINING_PATTERN_VIDEOIDLE; + + switch (pattern) { + case HW_DP_TRAINING_PATTERN_1: + dpcd_tr_pattern = DPCD_TRAINING_PATTERN_1; + break; + case HW_DP_TRAINING_PATTERN_2: + dpcd_tr_pattern = DPCD_TRAINING_PATTERN_2; + break; + case HW_DP_TRAINING_PATTERN_3: + dpcd_tr_pattern = DPCD_TRAINING_PATTERN_3; + break; + case HW_DP_TRAINING_PATTERN_4: + dpcd_tr_pattern = DPCD_TRAINING_PATTERN_4; + break; + default: + ASSERT(0); + dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING, + "%s: Invalid HW Training pattern: %d\n", + __func__, pattern); + break; + } + + return dpcd_tr_pattern; + +} + +static void dpcd_set_lt_pattern_and_lane_settings( + struct core_link* link, + const struct link_training_settings *lt_settings, + enum hw_dp_training_pattern pattern) +{ + union dpcd_training_lane dpcd_lane[LANE_COUNT_DP_MAX] = {{{0}}}; + const uint32_t dpcd_base_lt_offset = + DPCD_ADDRESS_TRAINING_PATTERN_SET; + uint8_t dpcd_lt_buffer[5] = {0}; + union dpcd_training_pattern dpcd_pattern = {{0}}; + uint32_t lane; + uint32_t size_in_bytes; + bool edp_workaround = false; /* TODO link_prop.INTERNAL */ + + /***************************************************************** + * DpcdAddress_TrainingPatternSet + *****************************************************************/ + dpcd_pattern.v1_4.TRAINING_PATTERN_SET = + hw_training_pattern_to_dpcd_training_pattern(link, pattern); + + dpcd_lt_buffer[DPCD_ADDRESS_TRAINING_PATTERN_SET - dpcd_base_lt_offset] + = dpcd_pattern.raw; + + dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING, + "%s\n %x pattern = %x\n", + __func__, + DPCD_ADDRESS_TRAINING_PATTERN_SET, + dpcd_pattern.v1_4.TRAINING_PATTERN_SET); + + /***************************************************************** + * DpcdAddress_Lane0Set -> DpcdAddress_Lane3Set + *****************************************************************/ + for (lane = 0; lane < + (uint32_t)(lt_settings->link_settings.lane_count); lane++) { + + dpcd_lane[lane].bits.VOLTAGE_SWING_SET = + (uint8_t)(lt_settings->lane_settings[lane].VOLTAGE_SWING); + dpcd_lane[lane].bits.PRE_EMPHASIS_SET = + (uint8_t)(lt_settings->lane_settings[lane].PRE_EMPHASIS); + + dpcd_lane[lane].bits.MAX_SWING_REACHED = + (lt_settings->lane_settings[lane].VOLTAGE_SWING == + VOLTAGE_SWING_MAX_LEVEL ? 1 : 0); + dpcd_lane[lane].bits.MAX_PRE_EMPHASIS_REACHED = + (lt_settings->lane_settings[lane].PRE_EMPHASIS == + PRE_EMPHASIS_MAX_LEVEL ? 1 : 0); + } + + /* concatinate everything into one buffer*/ + + size_in_bytes = lt_settings->link_settings.lane_count * sizeof(dpcd_lane[0]); + + // 0x00103 - 0x00102 + memmove( + &dpcd_lt_buffer[DPCD_ADDRESS_LANE0_SET - dpcd_base_lt_offset], + dpcd_lane, + size_in_bytes); + + dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING, + "%s:\n %x VS set = %x PE set = %x \ + max VS Reached = %x max PE Reached = %x\n", + __func__, + DPCD_ADDRESS_LANE0_SET, + dpcd_lane[0].bits.VOLTAGE_SWING_SET, + dpcd_lane[0].bits.PRE_EMPHASIS_SET, + dpcd_lane[0].bits.MAX_SWING_REACHED, + dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED); + + if (edp_workaround) { + /* for eDP write in 2 parts because the 5-byte burst is + * causing issues on some eDP panels (EPR#366724) + */ + core_link_write_dpcd( + link, + DPCD_ADDRESS_TRAINING_PATTERN_SET, + &dpcd_pattern.raw, + sizeof(dpcd_pattern.raw) ); + + core_link_write_dpcd( + link, + DPCD_ADDRESS_LANE0_SET, + (uint8_t *)(dpcd_lane), + size_in_bytes); + + } else + /* write it all in (1 + number-of-lanes)-byte burst*/ + core_link_write_dpcd( + link, + dpcd_base_lt_offset, + dpcd_lt_buffer, + size_in_bytes + sizeof(dpcd_pattern.raw) ); + + link->public.cur_lane_setting = lt_settings->lane_settings[0]; +} + +static bool is_cr_done(enum dc_lane_count ln_count, + union lane_status *dpcd_lane_status) +{ + bool done = true; + uint32_t lane; + /*LANEx_CR_DONE bits All 1's?*/ + for (lane = 0; lane < (uint32_t)(ln_count); lane++) { + if (!dpcd_lane_status[lane].bits.CR_DONE_0) + done = false; + } + return done; + +} + +static bool is_ch_eq_done(enum dc_lane_count ln_count, + union lane_status *dpcd_lane_status, + union lane_align_status_updated *lane_status_updated) +{ + bool done = true; + uint32_t lane; + if (!lane_status_updated->bits.INTERLANE_ALIGN_DONE) + done = false; + else { + for (lane = 0; lane < (uint32_t)(ln_count); lane++) { + if (!dpcd_lane_status[lane].bits.SYMBOL_LOCKED_0 || + !dpcd_lane_status[lane].bits.CHANNEL_EQ_DONE_0) + done = false; + } + } + return done; + +} + +static void update_drive_settings( + struct link_training_settings *dest, + struct link_training_settings src) +{ + uint32_t lane; + for (lane = 0; lane < src.link_settings.lane_count; lane++) { + dest->lane_settings[lane].VOLTAGE_SWING = + src.lane_settings[lane].VOLTAGE_SWING; + dest->lane_settings[lane].PRE_EMPHASIS = + src.lane_settings[lane].PRE_EMPHASIS; + dest->lane_settings[lane].POST_CURSOR2 = + src.lane_settings[lane].POST_CURSOR2; + } +} + +static uint8_t get_nibble_at_index(const uint8_t *buf, + uint32_t index) +{ + uint8_t nibble; + nibble = buf[index / 2]; + + if (index % 2) + nibble >>= 4; + else + nibble &= 0x0F; + + return nibble; +} + +static enum dc_pre_emphasis get_max_pre_emphasis_for_voltage_swing( + enum dc_voltage_swing voltage) +{ + enum dc_pre_emphasis pre_emphasis; + pre_emphasis = PRE_EMPHASIS_MAX_LEVEL; + + if (voltage <= VOLTAGE_SWING_MAX_LEVEL) + pre_emphasis = voltage_swing_to_pre_emphasis[voltage]; + + return pre_emphasis; + +} + +static void find_max_drive_settings( + const struct link_training_settings *link_training_setting, + struct link_training_settings *max_lt_setting) +{ + uint32_t lane; + struct dc_lane_settings max_requested; + + max_requested.VOLTAGE_SWING = + link_training_setting-> + lane_settings[0].VOLTAGE_SWING; + max_requested.PRE_EMPHASIS = + link_training_setting-> + lane_settings[0].PRE_EMPHASIS; + /*max_requested.postCursor2 = + * link_training_setting->laneSettings[0].postCursor2;*/ + + /* Determine what the maximum of the requested settings are*/ + for (lane = 1; lane < link_training_setting->link_settings.lane_count; + lane++) { + if (link_training_setting->lane_settings[lane].VOLTAGE_SWING > + max_requested.VOLTAGE_SWING) + + max_requested.VOLTAGE_SWING = + link_training_setting-> + lane_settings[lane].VOLTAGE_SWING; + + if (link_training_setting->lane_settings[lane].PRE_EMPHASIS > + max_requested.PRE_EMPHASIS) + max_requested.PRE_EMPHASIS = + link_training_setting-> + lane_settings[lane].PRE_EMPHASIS; + + /* + if (link_training_setting->laneSettings[lane].postCursor2 > + max_requested.postCursor2) + { + max_requested.postCursor2 = + link_training_setting->laneSettings[lane].postCursor2; + } + */ + } + + /* make sure the requested settings are + * not higher than maximum settings*/ + if (max_requested.VOLTAGE_SWING > VOLTAGE_SWING_MAX_LEVEL) + max_requested.VOLTAGE_SWING = VOLTAGE_SWING_MAX_LEVEL; + + if (max_requested.PRE_EMPHASIS > PRE_EMPHASIS_MAX_LEVEL) + max_requested.PRE_EMPHASIS = PRE_EMPHASIS_MAX_LEVEL; + /* + if (max_requested.postCursor2 > PostCursor2_MaxLevel) + max_requested.postCursor2 = PostCursor2_MaxLevel; + */ + + /* make sure the pre-emphasis matches the voltage swing*/ + if (max_requested.PRE_EMPHASIS > + get_max_pre_emphasis_for_voltage_swing( + max_requested.VOLTAGE_SWING)) + max_requested.PRE_EMPHASIS = + get_max_pre_emphasis_for_voltage_swing( + max_requested.VOLTAGE_SWING); + + /* + * Post Cursor2 levels are completely independent from + * pre-emphasis (Post Cursor1) levels. But Post Cursor2 levels + * can only be applied to each allowable combination of voltage + * swing and pre-emphasis levels */ + /* if ( max_requested.postCursor2 > + * getMaxPostCursor2ForVoltageSwing(max_requested.voltageSwing)) + * max_requested.postCursor2 = + * getMaxPostCursor2ForVoltageSwing(max_requested.voltageSwing); + */ + + max_lt_setting->link_settings.link_rate = + link_training_setting->link_settings.link_rate; + max_lt_setting->link_settings.lane_count = + link_training_setting->link_settings.lane_count; + max_lt_setting->link_settings.link_spread = + link_training_setting->link_settings.link_spread; + + for (lane = 0; lane < + link_training_setting->link_settings.lane_count; + lane++) { + max_lt_setting->lane_settings[lane].VOLTAGE_SWING = + max_requested.VOLTAGE_SWING; + max_lt_setting->lane_settings[lane].PRE_EMPHASIS = + max_requested.PRE_EMPHASIS; + /*max_lt_setting->laneSettings[lane].postCursor2 = + * max_requested.postCursor2; + */ + } + +} + +static void get_lane_status_and_drive_settings( + struct core_link* link, + const struct link_training_settings *link_training_setting, + union lane_status *ln_status, + union lane_align_status_updated *ln_status_updated, + struct link_training_settings *req_settings) +{ + uint8_t dpcd_buf[6] = {0}; + union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {{{0}}}; + struct link_training_settings request_settings = {{0}}; + uint32_t lane; + + memset(req_settings, '\0', sizeof(struct link_training_settings)); + + core_link_read_dpcd( + link, + DPCD_ADDRESS_LANE_01_STATUS, + (uint8_t *)(dpcd_buf), + sizeof(dpcd_buf)); + + for (lane = 0; lane < + (uint32_t)(link_training_setting->link_settings.lane_count); + lane++) { + + ln_status[lane].raw = + get_nibble_at_index(&dpcd_buf[0], lane); + dpcd_lane_adjust[lane].raw = + get_nibble_at_index(&dpcd_buf[4], lane); + } + + ln_status_updated->raw = dpcd_buf[2]; + + dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING, + "%s:\n%x Lane01Status = %x\n %x Lane23Status = %x\n ", + __func__, + DPCD_ADDRESS_LANE_01_STATUS, dpcd_buf[0], + DPCD_ADDRESS_LANE_23_STATUS, dpcd_buf[1]); + + dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING, + "%s:\n %x Lane01AdjustRequest = %x\n %x Lane23AdjustRequest = %x\n", + __func__, + DPCD_ADDRESS_ADJUST_REQUEST_LANE0_1, + dpcd_buf[4], + DPCD_ADDRESS_ADJUST_REQUEST_LANE2_3, + dpcd_buf[5]); + + /*copy to req_settings*/ + request_settings.link_settings.lane_count = + link_training_setting->link_settings.lane_count; + request_settings.link_settings.link_rate = + link_training_setting->link_settings.link_rate; + request_settings.link_settings.link_spread = + link_training_setting->link_settings.link_spread; + + for (lane = 0; lane < + (uint32_t)(link_training_setting->link_settings.lane_count); + lane++) { + + request_settings.lane_settings[lane].VOLTAGE_SWING = + (enum dc_voltage_swing)(dpcd_lane_adjust[lane].bits. + VOLTAGE_SWING_LANE); + request_settings.lane_settings[lane].PRE_EMPHASIS = + (enum dc_pre_emphasis)(dpcd_lane_adjust[lane].bits. + PRE_EMPHASIS_LANE); + } + + /*Note: for postcursor2, read adjusted + * postcursor2 settings from*/ + /*DpcdAddress_AdjustRequestPostCursor2 = + *0x020C (not implemented yet)*/ + + /* we find the maximum of the requested settings across all lanes*/ + /* and set this maximum for all lanes*/ + find_max_drive_settings(&request_settings, req_settings); + + /* if post cursor 2 is needed in the future, + * read DpcdAddress_AdjustRequestPostCursor2 = 0x020C + */ + +} + +static void dpcd_set_lane_settings( + struct core_link* link, + const struct link_training_settings *link_training_setting) +{ + union dpcd_training_lane dpcd_lane[LANE_COUNT_DP_MAX] = {{{0}}}; + uint32_t lane; + + for (lane = 0; lane < + (uint32_t)(link_training_setting-> + link_settings.lane_count); + lane++) { + dpcd_lane[lane].bits.VOLTAGE_SWING_SET = + (uint8_t)(link_training_setting-> + lane_settings[lane].VOLTAGE_SWING); + dpcd_lane[lane].bits.PRE_EMPHASIS_SET = + (uint8_t)(link_training_setting-> + lane_settings[lane].PRE_EMPHASIS); + dpcd_lane[lane].bits.MAX_SWING_REACHED = + (link_training_setting-> + lane_settings[lane].VOLTAGE_SWING == + VOLTAGE_SWING_MAX_LEVEL ? 1 : 0); + dpcd_lane[lane].bits.MAX_PRE_EMPHASIS_REACHED = + (link_training_setting-> + lane_settings[lane].PRE_EMPHASIS == + PRE_EMPHASIS_MAX_LEVEL ? 1 : 0); + } + + core_link_write_dpcd(link, + DPCD_ADDRESS_LANE0_SET, + (uint8_t *)(dpcd_lane), + link_training_setting->link_settings.lane_count); + + /* + if (LTSettings.link.rate == LinkRate_High2) + { + DpcdTrainingLaneSet2 dpcd_lane2[lane_count_DPMax] = {0}; + for ( uint32_t lane = 0; + lane < lane_count_DPMax; lane++) + { + dpcd_lane2[lane].bits.post_cursor2_set = + static_cast( + LTSettings.laneSettings[lane].postCursor2); + dpcd_lane2[lane].bits.max_post_cursor2_reached = 0; + } + m_pDpcdAccessSrv->WriteDpcdData( + DpcdAddress_Lane0Set2, + reinterpret_cast(dpcd_lane2), + LTSettings.link.lanes); + } + */ + + dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING, + "%s\n %x VS set = %x PE set = %x \ + max VS Reached = %x max PE Reached = %x\n", + __func__, + DPCD_ADDRESS_LANE0_SET, + dpcd_lane[0].bits.VOLTAGE_SWING_SET, + dpcd_lane[0].bits.PRE_EMPHASIS_SET, + dpcd_lane[0].bits.MAX_SWING_REACHED, + dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED); + + link->public.cur_lane_setting = link_training_setting->lane_settings[0]; + +} + +static bool is_max_vs_reached( + const struct link_training_settings *lt_settings) +{ + uint32_t lane; + for (lane = 0; lane < + (uint32_t)(lt_settings->link_settings.lane_count); + lane++) { + if (lt_settings->lane_settings[lane].VOLTAGE_SWING + == VOLTAGE_SWING_MAX_LEVEL) + return true; + } + return false; + +} + +void dc_link_dp_set_drive_settings( + struct dc_link *link, + struct link_training_settings *lt_settings) +{ + struct core_link *core_link = DC_LINK_TO_CORE(link); + /* program ASIC PHY settings*/ + dp_set_hw_lane_settings(core_link, lt_settings); + + /* Notify DP sink the PHY settings from source */ + dpcd_set_lane_settings(core_link, lt_settings); +} + +static bool perform_post_lt_adj_req_sequence( + struct core_link *link, + struct link_training_settings *lt_settings) +{ + enum dc_lane_count lane_count = + lt_settings->link_settings.lane_count; + + uint32_t adj_req_count; + uint32_t adj_req_timer; + bool req_drv_setting_changed; + uint32_t lane; + + req_drv_setting_changed = false; + for (adj_req_count = 0; adj_req_count < POST_LT_ADJ_REQ_LIMIT; + adj_req_count++) { + + req_drv_setting_changed = false; + + for (adj_req_timer = 0; + adj_req_timer < POST_LT_ADJ_REQ_TIMEOUT; + adj_req_timer++) { + + struct link_training_settings req_settings; + union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX]; + union lane_align_status_updated + dpcd_lane_status_updated; + + get_lane_status_and_drive_settings( + link, + lt_settings, + dpcd_lane_status, + &dpcd_lane_status_updated, + &req_settings); + + if (dpcd_lane_status_updated.bits. + POST_LT_ADJ_REQ_IN_PROGRESS == 0) + return true; + + if (!is_cr_done(lane_count, dpcd_lane_status)) + return false; + + if (!is_ch_eq_done( + lane_count, + dpcd_lane_status, + &dpcd_lane_status_updated)) + return false; + + for (lane = 0; lane < (uint32_t)(lane_count); lane++) { + + if (lt_settings-> + lane_settings[lane].VOLTAGE_SWING != + req_settings.lane_settings[lane]. + VOLTAGE_SWING || + lt_settings->lane_settings[lane].PRE_EMPHASIS != + req_settings.lane_settings[lane].PRE_EMPHASIS) { + + req_drv_setting_changed = true; + break; + } + } + + if (req_drv_setting_changed) { + update_drive_settings( + lt_settings,req_settings); + + dc_link_dp_set_drive_settings(&link->public, + lt_settings); + break; + } + + msleep(1); + } + + if (!req_drv_setting_changed) { + dm_logger_write(link->ctx->logger, LOG_WARNING, + "%s: Post Link Training Adjust Request Timed out\n", + __func__); + + ASSERT(0); + return true; + } + } + dm_logger_write(link->ctx->logger, LOG_WARNING, + "%s: Post Link Training Adjust Request limit reached\n", + __func__); + + ASSERT(0); + return true; + +} + +static enum hw_dp_training_pattern get_supported_tp(struct core_link *link) +{ + enum hw_dp_training_pattern highest_tp = HW_DP_TRAINING_PATTERN_2; + struct encoder_feature_support *features = &link->link_enc->features; + struct dpcd_caps *dpcd_caps = &link->dpcd_caps; + + if (features->flags.bits.IS_TPS3_CAPABLE) + highest_tp = HW_DP_TRAINING_PATTERN_3; + + if (features->flags.bits.IS_TPS4_CAPABLE) + highest_tp = HW_DP_TRAINING_PATTERN_4; + + if (dpcd_caps->max_down_spread.bits.TPS4_SUPPORTED && + highest_tp >= HW_DP_TRAINING_PATTERN_4) + return HW_DP_TRAINING_PATTERN_4; + + if (dpcd_caps->max_ln_count.bits.TPS3_SUPPORTED && + highest_tp >= HW_DP_TRAINING_PATTERN_3) + return HW_DP_TRAINING_PATTERN_3; + + return HW_DP_TRAINING_PATTERN_2; +} + +static bool perform_channel_equalization_sequence( + struct core_link *link, + struct link_training_settings *lt_settings) +{ + struct link_training_settings req_settings; + enum hw_dp_training_pattern hw_tr_pattern; + uint32_t retries_ch_eq; + enum dc_lane_count lane_count = lt_settings->link_settings.lane_count; + union lane_align_status_updated dpcd_lane_status_updated = {{0}}; + union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {{{0}}};; + + hw_tr_pattern = get_supported_tp(link); + + dp_set_hw_training_pattern(link, hw_tr_pattern); + + for (retries_ch_eq = 0; retries_ch_eq <= LINK_TRAINING_MAX_RETRY_COUNT; + retries_ch_eq++) { + + dp_set_hw_lane_settings(link, lt_settings); + + /* 2. update DPCD*/ + if (!retries_ch_eq) + /* EPR #361076 - write as a 5-byte burst, + * but only for the 1-st iteration*/ + dpcd_set_lt_pattern_and_lane_settings( + link, + lt_settings, + hw_tr_pattern); + else + dpcd_set_lane_settings(link, lt_settings); + + /* 3. wait for receiver to lock-on*/ + wait_for_training_aux_rd_interval(link, 400); + + /* 4. Read lane status and requested + * drive settings as set by the sink*/ + + get_lane_status_and_drive_settings( + link, + lt_settings, + dpcd_lane_status, + &dpcd_lane_status_updated, + &req_settings); + + /* 5. check CR done*/ + if (!is_cr_done(lane_count, dpcd_lane_status)) + return false; + + /* 6. check CHEQ done*/ + if (is_ch_eq_done(lane_count, + dpcd_lane_status, + &dpcd_lane_status_updated)) + return true; + + /* 7. update VS/PE/PC2 in lt_settings*/ + update_drive_settings(lt_settings, req_settings); + } + + return false; + +} + +static bool perform_clock_recovery_sequence( + struct core_link *link, + struct link_training_settings *lt_settings) +{ + uint32_t retries_cr; + uint32_t retry_count; + uint32_t lane; + struct link_training_settings req_settings; + enum dc_lane_count lane_count = + lt_settings->link_settings.lane_count; + enum hw_dp_training_pattern hw_tr_pattern = HW_DP_TRAINING_PATTERN_1; + union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX]; + union lane_align_status_updated dpcd_lane_status_updated; + + retries_cr = 0; + retry_count = 0; + /* initial drive setting (VS/PE/PC2)*/ + for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) { + lt_settings->lane_settings[lane].VOLTAGE_SWING = + VOLTAGE_SWING_LEVEL0; + lt_settings->lane_settings[lane].PRE_EMPHASIS = + PRE_EMPHASIS_DISABLED; + lt_settings->lane_settings[lane].POST_CURSOR2 = + POST_CURSOR2_DISABLED; + } + + dp_set_hw_training_pattern(link, hw_tr_pattern); + + /* najeeb - The synaptics MST hub can put the LT in + * infinite loop by switching the VS + */ + /* between level 0 and level 1 continuously, here + * we try for CR lock for LinkTrainingMaxCRRetry count*/ + while ((retries_cr < LINK_TRAINING_MAX_RETRY_COUNT) && + (retry_count < LINK_TRAINING_MAX_CR_RETRY)) { + + memset(&dpcd_lane_status, '\0', sizeof(dpcd_lane_status)); + memset(&dpcd_lane_status_updated, '\0', + sizeof(dpcd_lane_status_updated)); + + /* 1. call HWSS to set lane settings*/ + dp_set_hw_lane_settings( + link, + lt_settings); + + /* 2. update DPCD of the receiver*/ + if (!retries_cr) + /* EPR #361076 - write as a 5-byte burst, + * but only for the 1-st iteration.*/ + dpcd_set_lt_pattern_and_lane_settings( + link, + lt_settings, + hw_tr_pattern); + else + dpcd_set_lane_settings( + link, + lt_settings); + + /* 3. wait receiver to lock-on*/ + wait_for_training_aux_rd_interval( + link, + 100); + + /* 4. Read lane status and requested drive + * settings as set by the sink + */ + get_lane_status_and_drive_settings( + link, + lt_settings, + dpcd_lane_status, + &dpcd_lane_status_updated, + &req_settings); + + /* 5. check CR done*/ + if (is_cr_done(lane_count, dpcd_lane_status)) + return true; + + /* 6. max VS reached*/ + if (is_max_vs_reached(lt_settings)) + return false; + + /* 7. same voltage*/ + /* Note: VS same for all lanes, + * so comparing first lane is sufficient*/ + if (lt_settings->lane_settings[0].VOLTAGE_SWING == + req_settings.lane_settings[0].VOLTAGE_SWING) + retries_cr++; + else + retries_cr = 0; + + /* 8. update VS/PE/PC2 in lt_settings*/ + update_drive_settings(lt_settings, req_settings); + + retry_count++; + } + + if (retry_count >= LINK_TRAINING_MAX_CR_RETRY) { + ASSERT(0); + dm_logger_write(link->ctx->logger, LOG_ERROR, + "%s: Link Training Error, could not \ + get CR after %d tries. \ + Possibly voltage swing issue", __func__, + LINK_TRAINING_MAX_CR_RETRY); + + } + + return false; +} + +static inline bool perform_link_training_int( + struct core_link *link, + struct link_training_settings *lt_settings, + bool status) +{ + union lane_count_set lane_count_set = { {0} }; + union dpcd_training_pattern dpcd_pattern = { {0} }; + + /* 3. set training not in progress*/ + dpcd_pattern.v1_4.TRAINING_PATTERN_SET = DPCD_TRAINING_PATTERN_VIDEOIDLE; + dpcd_set_training_pattern(link, dpcd_pattern); + + /* 4. mainlink output idle pattern*/ + dp_set_hw_test_pattern(link, DP_TEST_PATTERN_VIDEO_MODE, NULL, 0); + + /* + * 5. post training adjust if required + * If the upstream DPTX and downstream DPRX both support TPS4, + * TPS4 must be used instead of POST_LT_ADJ_REQ. + */ + if (link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED != 1 && + get_supported_tp(link) == HW_DP_TRAINING_PATTERN_4) + return status; + + if (status && + perform_post_lt_adj_req_sequence(link, lt_settings) == false) + status = false; + + lane_count_set.bits.LANE_COUNT_SET = lt_settings->link_settings.lane_count; + lane_count_set.bits.ENHANCED_FRAMING = 1; + lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED = 0; + + core_link_write_dpcd( + link, + DPCD_ADDRESS_LANE_COUNT_SET, + &lane_count_set.raw, + sizeof(lane_count_set)); + + return status; +} + +bool dc_link_dp_perform_link_training( + struct dc_link *link, + const struct dc_link_settings *link_setting, + bool skip_video_pattern) +{ + struct core_link *core_link = DC_LINK_TO_CORE(link); + bool status; + + char *link_rate = "Unknown"; + struct link_training_settings lt_settings; + + status = false; + memset(<_settings, '\0', sizeof(lt_settings)); + + lt_settings.link_settings.link_rate = link_setting->link_rate; + lt_settings.link_settings.lane_count = link_setting->lane_count; + + /*@todo[vdevulap] move SS to LS, should not be handled by displaypath*/ + + /* TODO hard coded to SS for now + * lt_settings.link_settings.link_spread = + * dal_display_path_is_ss_supported( + * path_mode->display_path) ? + * LINK_SPREAD_05_DOWNSPREAD_30KHZ : + * LINK_SPREAD_DISABLED; + */ + lt_settings.link_settings.link_spread = LINK_SPREAD_05_DOWNSPREAD_30KHZ; + + /* 1. set link rate, lane count and spread*/ + dpcd_set_link_settings(core_link, <_settings); + + /* 2. perform link training (set link training done + * to false is done as well)*/ + if (perform_clock_recovery_sequence(core_link, <_settings)) { + + if (perform_channel_equalization_sequence(core_link, + <_settings)) + status = true; + } + + if (status || !skip_video_pattern) + status = perform_link_training_int(core_link, + <_settings, status); + + /* 6. print status message*/ + switch (lt_settings.link_settings.link_rate) { + + case LINK_RATE_LOW: + link_rate = "RBR"; + break; + case LINK_RATE_HIGH: + link_rate = "HBR"; + break; + case LINK_RATE_HIGH2: + link_rate = "HBR2"; + break; + case LINK_RATE_RBR2: + link_rate = "RBR2"; + break; + case LINK_RATE_HIGH3: + link_rate = "HBR3"; + break; + default: + break; + } + + /* Connectivity log: link training */ + CONN_MSG_LT(core_link, "%sx%d %s VS=%d, PE=%d", + link_rate, + lt_settings.link_settings.lane_count, + status ? "pass" : "fail", + lt_settings.lane_settings[0].VOLTAGE_SWING, + lt_settings.lane_settings[0].PRE_EMPHASIS); + + return status; +} + + +bool perform_link_training_with_retries( + struct core_link *link, + const struct dc_link_settings *link_setting, + bool skip_video_pattern, + int attempts) +{ + uint8_t j; + uint8_t delay_between_attempts = LINK_TRAINING_RETRY_DELAY; + + for (j = 0; j < attempts; ++j) { + + if (dc_link_dp_perform_link_training( + &link->public, + link_setting, + skip_video_pattern)) + return true; + + msleep(delay_between_attempts); + delay_between_attempts += LINK_TRAINING_RETRY_DELAY; + } + + return false; +} + +/*TODO add more check to see if link support request link configuration */ +static bool is_link_setting_supported( + const struct dc_link_settings *link_setting, + const struct dc_link_settings *max_link_setting) +{ + if (link_setting->lane_count > max_link_setting->lane_count || + link_setting->link_rate > max_link_setting->link_rate) + return false; + return true; +} + +static const uint32_t get_link_training_fallback_table_len( + struct core_link *link) +{ + return ARRAY_SIZE(link_training_fallback_table); +} + +static const struct dc_link_settings *get_link_training_fallback_table( + struct core_link *link, uint32_t i) +{ + return &link_training_fallback_table[i]; +} + +static bool exceeded_limit_link_setting( + const struct dc_link_settings *link_setting, + const struct dc_link_settings *limit_link_setting) +{ + return (link_setting->lane_count * link_setting->link_rate + > limit_link_setting->lane_count * limit_link_setting->link_rate ? + true : false); +} + +static struct dc_link_settings get_max_link_cap(struct core_link *link) +{ + /* Set Default link settings */ + struct dc_link_settings max_link_cap = {LANE_COUNT_FOUR, LINK_RATE_HIGH, + LINK_SPREAD_05_DOWNSPREAD_30KHZ}; + + /* Higher link settings based on feature supported */ + if (link->link_enc->features.flags.bits.IS_HBR2_CAPABLE) + max_link_cap.link_rate = LINK_RATE_HIGH2; + + if (link->link_enc->features.flags.bits.IS_HBR3_CAPABLE) + max_link_cap.link_rate = LINK_RATE_HIGH3; + + /* Lower link settings based on sink's link cap */ + if (link->public.reported_link_cap.lane_count < max_link_cap.lane_count) + max_link_cap.lane_count = + link->public.reported_link_cap.lane_count; + if (link->public.reported_link_cap.link_rate < max_link_cap.link_rate) + max_link_cap.link_rate = + link->public.reported_link_cap.link_rate; + if (link->public.reported_link_cap.link_spread < + max_link_cap.link_spread) + max_link_cap.link_spread = + link->public.reported_link_cap.link_spread; + return max_link_cap; +} + +bool dp_hbr_verify_link_cap( + struct core_link *link, + struct dc_link_settings *known_limit_link_setting) +{ + struct dc_link_settings max_link_cap = {0}; + bool success; + bool skip_link_training; + const struct dc_link_settings *cur; + bool skip_video_pattern; + uint32_t i; + struct clock_source *dp_cs; + enum clock_source_id dp_cs_id = CLOCK_SOURCE_ID_EXTERNAL; + + success = false; + skip_link_training = false; + + max_link_cap = get_max_link_cap(link); + + /* TODO implement override and monitor patch later */ + + /* try to train the link from high to low to + * find the physical link capability + */ + /* disable PHY done possible by BIOS, will be done by driver itself */ + dp_disable_link_phy(link, link->public.connector_signal); + + dp_cs = link->dc->res_pool->dp_clock_source; + + if (dp_cs) + dp_cs_id = dp_cs->id; + else { + /* + * dp clock source is not initialized for some reason. + * Should not happen, CLOCK_SOURCE_ID_EXTERNAL will be used + */ + ASSERT(dp_cs); + } + + for (i = 0; i < get_link_training_fallback_table_len(link) && + !success; i++) { + cur = get_link_training_fallback_table(link, i); + + if (known_limit_link_setting->lane_count != LANE_COUNT_UNKNOWN && + exceeded_limit_link_setting(cur, + known_limit_link_setting)) + continue; + + if (!is_link_setting_supported(cur, &max_link_cap)) + continue; + + skip_video_pattern = true; + if (cur->link_rate == LINK_RATE_LOW) + skip_video_pattern = false; + + dp_enable_link_phy( + link, + link->public.connector_signal, + dp_cs_id, + cur); + + if (skip_link_training) + success = true; + else { + success = dc_link_dp_perform_link_training( + &link->public, + cur, + skip_video_pattern); + } + + if (success) + link->public.verified_link_cap = *cur; + + /* always disable the link before trying another + * setting or before returning we'll enable it later + * based on the actual mode we're driving + */ + dp_disable_link_phy(link, link->public.connector_signal); + } + + /* Link Training failed for all Link Settings + * (Lane Count is still unknown) + */ + if (!success) { + /* If all LT fails for all settings, + * set verified = failed safe (1 lane low) + */ + link->public.verified_link_cap.lane_count = LANE_COUNT_ONE; + link->public.verified_link_cap.link_rate = LINK_RATE_LOW; + + link->public.verified_link_cap.link_spread = + LINK_SPREAD_DISABLED; + } + + link->public.max_link_setting = link->public.verified_link_cap; + + return success; +} + +static uint32_t bandwidth_in_kbps_from_timing( + const struct dc_crtc_timing *timing) +{ + uint32_t bits_per_channel = 0; + uint32_t kbps; + switch (timing->display_color_depth) { + + case COLOR_DEPTH_666: + bits_per_channel = 6; + break; + case COLOR_DEPTH_888: + bits_per_channel = 8; + break; + case COLOR_DEPTH_101010: + bits_per_channel = 10; + break; + case COLOR_DEPTH_121212: + bits_per_channel = 12; + break; + case COLOR_DEPTH_141414: + bits_per_channel = 14; + break; + case COLOR_DEPTH_161616: + bits_per_channel = 16; + break; + default: + break; + } + ASSERT(bits_per_channel != 0); + + kbps = timing->pix_clk_khz; + kbps *= bits_per_channel; + + if (timing->flags.Y_ONLY != 1) + /*Only YOnly make reduce bandwidth by 1/3 compares to RGB*/ + kbps *= 3; + + return kbps; + +} + +static uint32_t bandwidth_in_kbps_from_link_settings( + const struct dc_link_settings *link_setting) +{ + uint32_t link_rate_in_kbps = link_setting->link_rate * + LINK_RATE_REF_FREQ_IN_KHZ; + + uint32_t lane_count = link_setting->lane_count; + uint32_t kbps = link_rate_in_kbps; + kbps *= lane_count; + kbps *= 8; /* 8 bits per byte*/ + + return kbps; + +} + +bool dp_validate_mode_timing( + struct core_link *link, + const struct dc_crtc_timing *timing) +{ + uint32_t req_bw; + uint32_t max_bw; + + const struct dc_link_settings *link_setting; + + /*always DP fail safe mode*/ + if (timing->pix_clk_khz == (uint32_t)25175 && + timing->h_addressable == (uint32_t)640 && + timing->v_addressable == (uint32_t)480) + return true; + + /* We always use verified link settings */ + link_setting = &link->public.verified_link_cap; + + /* TODO: DYNAMIC_VALIDATION needs to be implemented */ + /*if (flags.DYNAMIC_VALIDATION == 1 && + link->public.verified_link_cap.lane_count != LANE_COUNT_UNKNOWN) + link_setting = &link->public.verified_link_cap; + */ + + req_bw = bandwidth_in_kbps_from_timing(timing); + max_bw = bandwidth_in_kbps_from_link_settings(link_setting); + + if (req_bw <= max_bw) { + /* remember the biggest mode here, during + * initial link training (to get + * verified_link_cap), LS sends event about + * cannot train at reported cap to upper + * layer and upper layer will re-enumerate modes. + * this is not necessary if the lower + * verified_link_cap is enough to drive + * all the modes */ + + /* TODO: DYNAMIC_VALIDATION needs to be implemented */ + /* if (flags.DYNAMIC_VALIDATION == 1) + dpsst->max_req_bw_for_verified_linkcap = dal_max( + dpsst->max_req_bw_for_verified_linkcap, req_bw); */ + return true; + } else + return false; +} + +void decide_link_settings(struct core_stream *stream, + struct dc_link_settings *link_setting) +{ + + const struct dc_link_settings *cur_ls; + struct core_link* link; + uint32_t req_bw; + uint32_t link_bw; + uint32_t i; + + req_bw = bandwidth_in_kbps_from_timing( + &stream->public.timing); + + /* if preferred is specified through AMDDP, use it, if it's enough + * to drive the mode + */ + link = stream->sink->link; + + if ((link->public.reported_link_cap.lane_count != LANE_COUNT_UNKNOWN) && + (link->public.reported_link_cap.link_rate <= + link->public.verified_link_cap.link_rate)) { + + link_bw = bandwidth_in_kbps_from_link_settings( + &link->public.reported_link_cap); + + if (req_bw < link_bw) { + *link_setting = link->public.reported_link_cap; + return; + } + } + + /* search for first suitable setting for the requested + * bandwidth + */ + for (i = 0; i < get_link_training_fallback_table_len(link); i++) { + + cur_ls = get_link_training_fallback_table(link, i); + + link_bw = + bandwidth_in_kbps_from_link_settings( + cur_ls); + + if (req_bw < link_bw) { + if (is_link_setting_supported( + cur_ls, + &link->public.max_link_setting)) { + *link_setting = *cur_ls; + return; + } + } + } + + BREAK_TO_DEBUGGER(); + ASSERT(link->public.verified_link_cap.lane_count != + LANE_COUNT_UNKNOWN); + + *link_setting = link->public.verified_link_cap; +} + +/*************************Short Pulse IRQ***************************/ + +static bool hpd_rx_irq_check_link_loss_status( + struct core_link *link, + union hpd_irq_data *hpd_irq_dpcd_data) +{ + uint8_t irq_reg_rx_power_state; + enum dc_status dpcd_result = DC_ERROR_UNEXPECTED; + union lane_status lane_status; + uint32_t lane; + bool sink_status_changed; + bool return_code; + + sink_status_changed = false; + return_code = false; + + if (link->public.cur_link_settings.lane_count == 0) + return return_code; + /*1. Check that we can handle interrupt: Not in FS DOS, + * Not in "Display Timeout" state, Link is trained. + */ + + dpcd_result = core_link_read_dpcd(link, + DPCD_ADDRESS_POWER_STATE, + &irq_reg_rx_power_state, + sizeof(irq_reg_rx_power_state)); + + if (dpcd_result != DC_OK) { + irq_reg_rx_power_state = DP_PWR_STATE_D0; + dm_logger_write(link->ctx->logger, LOG_HW_HPD_IRQ, + "%s: DPCD read failed to obtain power state.\n", + __func__); + } + + if (irq_reg_rx_power_state == DP_PWR_STATE_D0) { + + /*2. Check that Link Status changed, before re-training.*/ + + /*parse lane status*/ + for (lane = 0; + lane < link->public.cur_link_settings.lane_count; + lane++) { + + /* check status of lanes 0,1 + * changed DpcdAddress_Lane01Status (0x202)*/ + lane_status.raw = get_nibble_at_index( + &hpd_irq_dpcd_data->bytes.lane01_status.raw, + lane); + + if (!lane_status.bits.CHANNEL_EQ_DONE_0 || + !lane_status.bits.CR_DONE_0 || + !lane_status.bits.SYMBOL_LOCKED_0) { + /* if one of the channel equalization, clock + * recovery or symbol lock is dropped + * consider it as (link has been + * dropped) dp sink status has changed*/ + sink_status_changed = true; + break; + } + + } + + /* Check interlane align.*/ + if (sink_status_changed || + !hpd_irq_dpcd_data->bytes.lane_status_updated.bits. + INTERLANE_ALIGN_DONE) { + + dm_logger_write(link->ctx->logger, LOG_HW_HPD_IRQ, + "%s: Link Status changed.\n", + __func__); + + return_code = true; + } + } + + return return_code; +} + +static enum dc_status read_hpd_rx_irq_data( + struct core_link *link, + union hpd_irq_data *irq_data) +{ + /* The HW reads 16 bytes from 200h on HPD, + * but if we get an AUX_DEFER, the HW cannot retry + * and this causes the CTS tests 4.3.2.1 - 3.2.4 to + * fail, so we now explicitly read 6 bytes which is + * the req from the above mentioned test cases. + */ + return core_link_read_dpcd( + link, + DPCD_ADDRESS_SINK_COUNT, + irq_data->raw, + sizeof(union hpd_irq_data)); +} + +static bool allow_hpd_rx_irq(const struct core_link *link) +{ + /* + * Don't handle RX IRQ unless one of following is met: + * 1) The link is established (cur_link_settings != unknown) + * 2) We kicked off MST detection + * 3) We know we're dealing with an active dongle + */ + + if ((link->public.cur_link_settings.lane_count != LANE_COUNT_UNKNOWN) || + (link->public.type == dc_connection_mst_branch) || + is_dp_active_dongle(link)) + return true; + + return false; +} + +static bool handle_hpd_irq_psr_sink(const struct core_link *link) +{ + union dpcd_psr_configuration psr_configuration; + + if (link->public.psr_caps.psr_version == 0) + return false; + + dal_ddc_service_read_dpcd_data( + link->ddc, + 368 /*DpcdAddress_PSR_Enable_Cfg*/, + &psr_configuration.raw, + sizeof(psr_configuration.raw)); + + if (psr_configuration.bits.ENABLE) { + unsigned char dpcdbuf[3] = {0}; + union psr_error_status psr_error_status; + union psr_sink_psr_status psr_sink_psr_status; + + dal_ddc_service_read_dpcd_data( + link->ddc, + 0x2006 /*DpcdAddress_PSR_Error_Status*/, + (unsigned char *) dpcdbuf, + sizeof(dpcdbuf)); + + /*DPCD 2006h ERROR STATUS*/ + psr_error_status.raw = dpcdbuf[0]; + /*DPCD 2008h SINK PANEL SELF REFRESH STATUS*/ + psr_sink_psr_status.raw = dpcdbuf[2]; + + if (psr_error_status.bits.LINK_CRC_ERROR || + psr_error_status.bits.RFB_STORAGE_ERROR) { + /* Acknowledge and clear error bits */ + dal_ddc_service_write_dpcd_data( + link->ddc, + 8198 /*DpcdAddress_PSR_Error_Status*/, + &psr_error_status.raw, + sizeof(psr_error_status.raw)); + + /* PSR error, disable and re-enable PSR */ + dc_link_set_psr_enable(&link->public, false); + dc_link_set_psr_enable(&link->public, true); + + return true; + } else if (psr_sink_psr_status.bits.SINK_SELF_REFRESH_STATUS == + PSR_SINK_STATE_ACTIVE_DISPLAY_FROM_SINK_RFB){ + /* No error is detect, PSR is active. + * We should return with IRQ_HPD handled without + * checking for loss of sync since PSR would have + * powered down main link. + */ + return true; + } + } + return false; +} + +static void dp_test_send_link_training(struct core_link *link) +{ + struct dc_link_settings link_settings; + + core_link_read_dpcd( + link, + DPCD_ADDRESS_TEST_LANE_COUNT, + (unsigned char *)(&link_settings.lane_count), + 1); + core_link_read_dpcd( + link, + DPCD_ADDRESS_TEST_LINK_RATE, + (unsigned char *)(&link_settings.link_rate), + 1); + + /* Set preferred link settings */ + link->public.verified_link_cap.lane_count = link_settings.lane_count; + link->public.verified_link_cap.link_rate = link_settings.link_rate; + + dp_retrain_link(link); +} + +static void dp_test_send_phy_test_pattern(struct core_link *link) +{ + union phy_test_pattern dpcd_test_pattern; + union lane_adjust dpcd_lane_adjustment[2]; + unsigned char dpcd_post_cursor_2_adjustment = 0; + unsigned char test_80_bit_pattern[ + (DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_79_72 - + DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_7_0)+1] = {0}; + enum dp_test_pattern test_pattern; + struct dc_link_training_settings link_settings; + union lane_adjust dpcd_lane_adjust; + unsigned int lane; + struct link_training_settings link_training_settings; + int i = 0; + + dpcd_test_pattern.raw = 0; + memset(dpcd_lane_adjustment, 0, sizeof(dpcd_lane_adjustment)); + memset(&link_settings, 0, sizeof(link_settings)); + + /* get phy test pattern and pattern parameters from DP receiver */ + core_link_read_dpcd( + link, + DPCD_ADDRESS_TEST_PHY_PATTERN, + &dpcd_test_pattern.raw, + sizeof(dpcd_test_pattern)); + core_link_read_dpcd( + link, + DPCD_ADDRESS_ADJUST_REQUEST_LANE0_1, + &dpcd_lane_adjustment[0].raw, + sizeof(dpcd_lane_adjustment)); + + /*get post cursor 2 parameters + * For DP 1.1a or eariler, this DPCD register's value is 0 + * For DP 1.2 or later: + * Bits 1:0 = POST_CURSOR2_LANE0; Bits 3:2 = POST_CURSOR2_LANE1 + * Bits 5:4 = POST_CURSOR2_LANE2; Bits 7:6 = POST_CURSOR2_LANE3 + */ + core_link_read_dpcd( + link, + DPCD_ADDRESS_ADJUST_REQUEST_POST_CURSOR2, + &dpcd_post_cursor_2_adjustment, + sizeof(dpcd_post_cursor_2_adjustment)); + + /* translate request */ + switch (dpcd_test_pattern.bits.PATTERN) { + case PHY_TEST_PATTERN_D10_2: + test_pattern = DP_TEST_PATTERN_D102; + break; + case PHY_TEST_PATTERN_SYMBOL_ERROR: + test_pattern = DP_TEST_PATTERN_SYMBOL_ERROR; + break; + case PHY_TEST_PATTERN_PRBS7: + test_pattern = DP_TEST_PATTERN_PRBS7; + break; + case PHY_TEST_PATTERN_80BIT_CUSTOM: + test_pattern = DP_TEST_PATTERN_80BIT_CUSTOM; + break; + case PHY_TEST_PATTERN_HBR2_COMPLIANCE_EYE: + test_pattern = DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE; + break; + default: + test_pattern = DP_TEST_PATTERN_VIDEO_MODE; + break; + } + + if (test_pattern == DP_TEST_PATTERN_80BIT_CUSTOM) + core_link_read_dpcd( + link, + DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_7_0, + test_80_bit_pattern, + sizeof(test_80_bit_pattern)); + + /* prepare link training settings */ + link_settings.link = link->public.cur_link_settings; + + for (lane = 0; lane < + (unsigned int)(link->public.cur_link_settings.lane_count); + lane++) { + dpcd_lane_adjust.raw = + get_nibble_at_index(&dpcd_lane_adjustment[0].raw, lane); + link_settings.lane_settings[lane].VOLTAGE_SWING = + (enum dc_voltage_swing) + (dpcd_lane_adjust.bits.VOLTAGE_SWING_LANE); + link_settings.lane_settings[lane].PRE_EMPHASIS = + (enum dc_pre_emphasis) + (dpcd_lane_adjust.bits.PRE_EMPHASIS_LANE); + link_settings.lane_settings[lane].POST_CURSOR2 = + (enum dc_post_cursor2) + ((dpcd_post_cursor_2_adjustment >> (lane * 2)) & 0x03); + } + + for (i = 0; i < 4; i++) + link_training_settings.lane_settings[i] = + link_settings.lane_settings[i]; + link_training_settings.link_settings = link_settings.link; + link_training_settings.allow_invalid_msa_timing_param = false; + /*Usage: Measure DP physical lane signal + * by DP SI test equipment automatically. + * PHY test pattern request is generated by equipment via HPD interrupt. + * HPD needs to be active all the time. HPD should be active + * all the time. Do not touch it. + * forward request to DS + */ + dc_link_dp_set_test_pattern( + &link->public, + test_pattern, + &link_training_settings, + test_80_bit_pattern, + (DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_79_72 - + DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_7_0)+1); +} + +static void dp_test_send_link_test_pattern(struct core_link *link) +{ + union link_test_pattern dpcd_test_pattern; + union test_misc dpcd_test_params; + enum dp_test_pattern test_pattern; + + memset(&dpcd_test_pattern, 0, sizeof(dpcd_test_pattern)); + memset(&dpcd_test_params, 0, sizeof(dpcd_test_params)); + + /* get link test pattern and pattern parameters */ + core_link_read_dpcd( + link, + DPCD_ADDRESS_TEST_PATTERN, + &dpcd_test_pattern.raw, + sizeof(dpcd_test_pattern)); + core_link_read_dpcd( + link, + DPCD_ADDRESS_TEST_MISC1, + &dpcd_test_params.raw, + sizeof(dpcd_test_params)); + + switch (dpcd_test_pattern.bits.PATTERN) { + case LINK_TEST_PATTERN_COLOR_RAMP: + test_pattern = DP_TEST_PATTERN_COLOR_RAMP; + break; + case LINK_TEST_PATTERN_VERTICAL_BARS: + test_pattern = DP_TEST_PATTERN_VERTICAL_BARS; + break; /* black and white */ + case LINK_TEST_PATTERN_COLOR_SQUARES: + test_pattern = (dpcd_test_params.bits.DYN_RANGE == + TEST_DYN_RANGE_VESA ? + DP_TEST_PATTERN_COLOR_SQUARES : + DP_TEST_PATTERN_COLOR_SQUARES_CEA); + break; + default: + test_pattern = DP_TEST_PATTERN_VIDEO_MODE; + break; + } + + dc_link_dp_set_test_pattern( + &link->public, + test_pattern, + NULL, + NULL, + 0); +} + +static void handle_automated_test(struct core_link *link) +{ + union test_request test_request; + union test_response test_response; + + memset(&test_request, 0, sizeof(test_request)); + memset(&test_response, 0, sizeof(test_response)); + + core_link_read_dpcd( + link, + DPCD_ADDRESS_TEST_REQUEST, + &test_request.raw, + sizeof(union test_request)); + if (test_request.bits.LINK_TRAINING) { + /* ACK first to let DP RX test box monitor LT sequence */ + test_response.bits.ACK = 1; + core_link_write_dpcd( + link, + DPCD_ADDRESS_TEST_RESPONSE, + &test_response.raw, + sizeof(test_response)); + dp_test_send_link_training(link); + /* no acknowledge request is needed again */ + test_response.bits.ACK = 0; + } + if (test_request.bits.LINK_TEST_PATTRN) { + dp_test_send_link_test_pattern(link); + link->public.compliance_test_state.bits. + SET_TEST_PATTERN_PENDING = 1; + } + if (test_request.bits.PHY_TEST_PATTERN) { + dp_test_send_phy_test_pattern(link); + test_response.bits.ACK = 1; + } + if (!test_request.raw) + /* no requests, revert all test signals + * TODO: revert all test signals + */ + test_response.bits.ACK = 1; + /* send request acknowledgment */ + if (test_response.bits.ACK) + core_link_write_dpcd( + link, + DPCD_ADDRESS_TEST_RESPONSE, + &test_response.raw, + sizeof(test_response)); +} + +bool dc_link_handle_hpd_rx_irq(const struct dc_link *dc_link) +{ + struct core_link *link = DC_LINK_TO_LINK(dc_link); + union hpd_irq_data hpd_irq_dpcd_data = {{{{0}}}}; + union device_service_irq device_service_clear = {0}; + enum dc_status result = DDC_RESULT_UNKNOWN; + bool status = false; + /* For use cases related to down stream connection status change, + * PSR and device auto test, refer to function handle_sst_hpd_irq + * in DAL2.1*/ + + dm_logger_write(link->ctx->logger, LOG_HW_HPD_IRQ, + "%s: Got short pulse HPD on link %d\n", + __func__, link->public.link_index); + + /* All the "handle_hpd_irq_xxx()" methods + * should be called only after + * dal_dpsst_ls_read_hpd_irq_data + * Order of calls is important too + */ + result = read_hpd_rx_irq_data(link, &hpd_irq_dpcd_data); + + if (result != DC_OK) { + dm_logger_write(link->ctx->logger, LOG_HW_HPD_IRQ, + "%s: DPCD read failed to obtain irq data\n", + __func__); + return false; + } + + if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.AUTOMATED_TEST) { + device_service_clear.bits.AUTOMATED_TEST = 1; + core_link_write_dpcd( + link, + DPCD_ADDRESS_DEVICE_SERVICE_IRQ_VECTOR, + &device_service_clear.raw, + sizeof(device_service_clear.raw)); + device_service_clear.raw = 0; + handle_automated_test(link); + return false; + } + + if (!allow_hpd_rx_irq(link)) { + dm_logger_write(link->ctx->logger, LOG_HW_HPD_IRQ, + "%s: skipping HPD handling on %d\n", + __func__, link->public.link_index); + return false; + } + + if (handle_hpd_irq_psr_sink(link)) + /* PSR-related error was detected and handled */ + return true; + + /* If PSR-related error handled, Main link may be off, + * so do not handle as a normal sink status change interrupt. + */ + + /* check if we have MST msg and return since we poll for it */ + if (hpd_irq_dpcd_data.bytes.device_service_irq. + bits.DOWN_REP_MSG_RDY || + hpd_irq_dpcd_data.bytes.device_service_irq. + bits.UP_REQ_MSG_RDY) + return false; + + /* For now we only handle 'Downstream port status' case. + * If we got sink count changed it means + * Downstream port status changed, + * then DM should call DC to do the detection. */ + if (hpd_rx_irq_check_link_loss_status( + link, + &hpd_irq_dpcd_data)) { + /* Connectivity log: link loss */ + CONN_DATA_LINK_LOSS(link, + hpd_irq_dpcd_data.raw, + sizeof(hpd_irq_dpcd_data), + "Status: "); + + perform_link_training_with_retries(link, + &link->public.cur_link_settings, + true, LINK_TRAINING_ATTEMPTS); + + status = false; + } + + if (link->public.type == dc_connection_active_dongle && + hpd_irq_dpcd_data.bytes.sink_cnt.bits.SINK_COUNT + != link->dpcd_sink_count) + status = true; + + /* reasons for HPD RX: + * 1. Link Loss - ie Re-train the Link + * 2. MST sideband message + * 3. Automated Test - ie. Internal Commit + * 4. CP (copy protection) - (not interesting for DM???) + * 5. DRR + * 6. Downstream Port status changed + * -ie. Detect - this the only one + * which is interesting for DM because + * it must call dc_link_detect. + */ + return status; +} + +/*query dpcd for version and mst cap addresses*/ +bool is_mst_supported(struct core_link *link) +{ + bool mst = false; + enum dc_status st = DC_OK; + union dpcd_rev rev; + union mstm_cap cap; + + rev.raw = 0; + cap.raw = 0; + + st = core_link_read_dpcd(link, DPCD_ADDRESS_DPCD_REV, &rev.raw, + sizeof(rev)); + + if (st == DC_OK && rev.raw >= DPCD_REV_12) { + + st = core_link_read_dpcd(link, DPCD_ADDRESS_MSTM_CAP, + &cap.raw, sizeof(cap)); + if (st == DC_OK && cap.bits.MST_CAP == 1) + mst = true; + } + return mst; + +} + +bool is_dp_active_dongle(const struct core_link *link) +{ + enum display_dongle_type dongle_type = link->dpcd_caps.dongle_type; + + return (dongle_type == DISPLAY_DONGLE_DP_VGA_CONVERTER) || + (dongle_type == DISPLAY_DONGLE_DP_DVI_CONVERTER) || + (dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER); +} + +static void get_active_converter_info( + uint8_t data, struct core_link *link) +{ + union dp_downstream_port_present ds_port = { .byte = data }; + + /* decode converter info*/ + if (!ds_port.fields.PORT_PRESENT) { + link->dpcd_caps.dongle_type = DISPLAY_DONGLE_NONE; + ddc_service_set_dongle_type(link->ddc, + link->dpcd_caps.dongle_type); + return; + } + + switch (ds_port.fields.PORT_TYPE) { + case DOWNSTREAM_VGA: + link->dpcd_caps.dongle_type = DISPLAY_DONGLE_DP_VGA_CONVERTER; + break; + case DOWNSTREAM_DVI_HDMI: + /* At this point we don't know is it DVI or HDMI, + * assume DVI.*/ + link->dpcd_caps.dongle_type = DISPLAY_DONGLE_DP_DVI_CONVERTER; + break; + default: + link->dpcd_caps.dongle_type = DISPLAY_DONGLE_NONE; + break; + } + + if (link->dpcd_caps.dpcd_rev.raw >= DCS_DPCD_REV_11) { + uint8_t det_caps[4]; + union dwnstream_port_caps_byte0 *port_caps = + (union dwnstream_port_caps_byte0 *)det_caps; + core_link_read_dpcd(link, DPCD_ADDRESS_DWN_STRM_PORT0_CAPS, + det_caps, sizeof(det_caps)); + + switch (port_caps->bits.DWN_STRM_PORTX_TYPE) { + case DOWN_STREAM_DETAILED_VGA: + link->dpcd_caps.dongle_type = + DISPLAY_DONGLE_DP_VGA_CONVERTER; + break; + case DOWN_STREAM_DETAILED_DVI: + link->dpcd_caps.dongle_type = + DISPLAY_DONGLE_DP_DVI_CONVERTER; + break; + case DOWN_STREAM_DETAILED_HDMI: + link->dpcd_caps.dongle_type = + DISPLAY_DONGLE_DP_HDMI_CONVERTER; + + if (ds_port.fields.DETAILED_CAPS) { + + union dwnstream_port_caps_byte3_hdmi + hdmi_caps = {.raw = det_caps[3] }; + + link->dpcd_caps.is_dp_hdmi_s3d_converter = + hdmi_caps.bits.FRAME_SEQ_TO_FRAME_PACK; + } + break; + } + } + + ddc_service_set_dongle_type(link->ddc, link->dpcd_caps.dongle_type); + + { + struct dp_device_vendor_id dp_id; + + /* read IEEE branch device id */ + core_link_read_dpcd( + link, + DPCD_ADDRESS_BRANCH_DEVICE_ID_START, + (uint8_t *)&dp_id, + sizeof(dp_id)); + + link->dpcd_caps.branch_dev_id = + (dp_id.ieee_oui[0] << 16) + + (dp_id.ieee_oui[1] << 8) + + dp_id.ieee_oui[2]; + + memmove( + link->dpcd_caps.branch_dev_name, + dp_id.ieee_device_id, + sizeof(dp_id.ieee_device_id)); + } + + { + struct dp_sink_hw_fw_revision dp_hw_fw_revision; + + core_link_read_dpcd( + link, + DPCD_ADDRESS_BRANCH_REVISION_START, + (uint8_t *)&dp_hw_fw_revision, + sizeof(dp_hw_fw_revision)); + + link->dpcd_caps.branch_hw_revision = + dp_hw_fw_revision.ieee_hw_rev; + } +} + +static void dp_wa_power_up_0010FA(struct core_link *link, uint8_t *dpcd_data, + int length) +{ + int retry = 0; + union dp_downstream_port_present ds_port = { 0 }; + + if (!link->dpcd_caps.dpcd_rev.raw) { + do { + dp_receiver_power_ctrl(link, true); + core_link_read_dpcd(link, DPCD_ADDRESS_DPCD_REV, + dpcd_data, length); + link->dpcd_caps.dpcd_rev.raw = dpcd_data[ + DPCD_ADDRESS_DPCD_REV - + DPCD_ADDRESS_DPCD_REV]; + } while (retry++ < 4 && !link->dpcd_caps.dpcd_rev.raw); + } + + ds_port.byte = dpcd_data[DPCD_ADDRESS_DOWNSTREAM_PORT_PRESENT - + DPCD_ADDRESS_DPCD_REV]; + + if (link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_VGA_CONVERTER) { + switch (link->dpcd_caps.branch_dev_id) { + /* Some active dongles (DP-VGA, DP-DLDVI converters) power down + * all internal circuits including AUX communication preventing + * reading DPCD table and EDID (spec violation). + * Encoder will skip DP RX power down on disable_output to + * keep receiver powered all the time.*/ + case DP_BRANCH_DEVICE_ID_1: + case DP_BRANCH_DEVICE_ID_4: + link->wa_flags.dp_keep_receiver_powered = true; + break; + + /* TODO: May need work around for other dongles. */ + default: + link->wa_flags.dp_keep_receiver_powered = false; + break; + } + } else + link->wa_flags.dp_keep_receiver_powered = false; +} + +static void retrieve_psr_link_cap(struct core_link *link, + enum edp_revision edp_revision) +{ + if (edp_revision >= EDP_REVISION_13) { + core_link_read_dpcd(link, + DPCD_ADDRESS_PSR_SUPPORT_VER, + (uint8_t *)(&link->public.psr_caps), + sizeof(link->public.psr_caps)); + if (link->public.psr_caps.psr_version != 0) { + unsigned char psr_capability = 0; + + core_link_read_dpcd(link, + DPCD_ADDRESS_PSR_CAPABILITY, + &psr_capability, + sizeof(psr_capability)); + /* Bit 0 determines whether fast link training is + * required on PSR exit. If set to 0, link training + * is required. If set to 1, sink must lock within + * five Idle Patterns after Main Link is turned on. + */ + link->public.psr_caps.psr_exit_link_training_required + = !(psr_capability & 0x1); + + psr_capability = (psr_capability >> 1) & 0x7; + link->public.psr_caps.psr_rfb_setup_time = + 55 * (6 - psr_capability); + } + } +} + +static void retrieve_link_cap(struct core_link *link) +{ + uint8_t dpcd_data[DPCD_ADDRESS_TRAINING_AUX_RD_INTERVAL - DPCD_ADDRESS_DPCD_REV + 1]; + + union down_stream_port_count down_strm_port_count; + union edp_configuration_cap edp_config_cap; + union dp_downstream_port_present ds_port = { 0 }; + + memset(dpcd_data, '\0', sizeof(dpcd_data)); + memset(&down_strm_port_count, + '\0', sizeof(union down_stream_port_count)); + memset(&edp_config_cap, '\0', + sizeof(union edp_configuration_cap)); + + core_link_read_dpcd( + link, + DPCD_ADDRESS_DPCD_REV, + dpcd_data, + sizeof(dpcd_data)); + + link->dpcd_caps.dpcd_rev.raw = + dpcd_data[DPCD_ADDRESS_DPCD_REV - DPCD_ADDRESS_DPCD_REV]; + + { + union training_aux_rd_interval aux_rd_interval; + + aux_rd_interval.raw = + dpcd_data[DPCD_ADDRESS_TRAINING_AUX_RD_INTERVAL]; + + if (aux_rd_interval.bits.EXT_RECIEVER_CAP_FIELD_PRESENT == 1) { + core_link_read_dpcd( + link, + DPCD_ADDRESS_DP13_DPCD_REV, + dpcd_data, + sizeof(dpcd_data)); + } + } + + ds_port.byte = dpcd_data[DPCD_ADDRESS_DOWNSTREAM_PORT_PRESENT - + DPCD_ADDRESS_DPCD_REV]; + + get_active_converter_info(ds_port.byte, link); + + dp_wa_power_up_0010FA(link, dpcd_data, sizeof(dpcd_data)); + + link->dpcd_caps.allow_invalid_MSA_timing_param = + down_strm_port_count.bits.IGNORE_MSA_TIMING_PARAM; + + link->dpcd_caps.max_ln_count.raw = dpcd_data[ + DPCD_ADDRESS_MAX_LANE_COUNT - DPCD_ADDRESS_DPCD_REV]; + + link->dpcd_caps.max_down_spread.raw = dpcd_data[ + DPCD_ADDRESS_MAX_DOWNSPREAD - DPCD_ADDRESS_DPCD_REV]; + + link->public.reported_link_cap.lane_count = + link->dpcd_caps.max_ln_count.bits.MAX_LANE_COUNT; + link->public.reported_link_cap.link_rate = dpcd_data[ + DPCD_ADDRESS_MAX_LINK_RATE - DPCD_ADDRESS_DPCD_REV]; + link->public.reported_link_cap.link_spread = + link->dpcd_caps.max_down_spread.bits.MAX_DOWN_SPREAD ? + LINK_SPREAD_05_DOWNSPREAD_30KHZ : LINK_SPREAD_DISABLED; + + edp_config_cap.raw = dpcd_data[ + DPCD_ADDRESS_EDP_CONFIG_CAP - DPCD_ADDRESS_DPCD_REV]; + link->dpcd_caps.panel_mode_edp = + edp_config_cap.bits.ALT_SCRAMBLER_RESET; + + link->edp_revision = DPCD_EDP_REVISION_EDP_UNKNOWN; + + link->public.test_pattern_enabled = false; + link->public.compliance_test_state.raw = 0; + + link->public.psr_caps.psr_exit_link_training_required = false; + link->public.psr_caps.psr_frame_capture_indication_req = false; + link->public.psr_caps.psr_rfb_setup_time = 0; + link->public.psr_caps.psr_sdp_transmit_line_num_deadline = 0; + link->public.psr_caps.psr_version = 0; + + /* read sink count */ + core_link_read_dpcd(link, + DPCD_ADDRESS_SINK_COUNT, + &link->dpcd_caps.sink_count.raw, + sizeof(link->dpcd_caps.sink_count.raw)); + + /* Display control registers starting at DPCD 700h are only valid and + * enabled if this eDP config cap bit is set. */ + if (edp_config_cap.bits.DPCD_DISPLAY_CONTROL_CAPABLE) { + /* Read the Panel's eDP revision at DPCD 700h. */ + core_link_read_dpcd(link, + DPCD_ADDRESS_EDP_REV, + (uint8_t *)(&link->edp_revision), + sizeof(link->edp_revision)); + } + + /* Connectivity log: detection */ + CONN_DATA_DETECT(link, dpcd_data, sizeof(dpcd_data), "Rx Caps: "); + + /* TODO: Confirm if need retrieve_psr_link_cap */ + retrieve_psr_link_cap(link, link->edp_revision); +} + +void detect_dp_sink_caps(struct core_link *link) +{ + retrieve_link_cap(link); + + /* dc init_hw has power encoder using default + * signal for connector. For native DP, no + * need to power up encoder again. If not native + * DP, hw_init may need check signal or power up + * encoder here. + */ + + if (is_mst_supported(link)) { + link->public.verified_link_cap = link->public.reported_link_cap; + } else { + dp_hbr_verify_link_cap(link, + &link->public.reported_link_cap); + } + /* TODO save sink caps in link->sink */ +} + +void dc_link_dp_enable_hpd(const struct dc_link *link) +{ + struct core_link *core_link = DC_LINK_TO_CORE(link); + struct link_encoder *encoder = core_link->link_enc; + + if (encoder != NULL && encoder->funcs->enable_hpd != NULL) + encoder->funcs->enable_hpd(encoder); +} + +void dc_link_dp_disable_hpd(const struct dc_link *link) +{ + struct core_link *core_link = DC_LINK_TO_CORE(link); + struct link_encoder *encoder = core_link->link_enc; + + if (encoder != NULL && encoder->funcs->enable_hpd != NULL) + encoder->funcs->disable_hpd(encoder); +} + +static bool is_dp_phy_pattern(enum dp_test_pattern test_pattern) +{ + if (test_pattern == DP_TEST_PATTERN_D102 || + test_pattern == DP_TEST_PATTERN_SYMBOL_ERROR || + test_pattern == DP_TEST_PATTERN_PRBS7 || + test_pattern == DP_TEST_PATTERN_80BIT_CUSTOM || + test_pattern == DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE || + test_pattern == DP_TEST_PATTERN_TRAINING_PATTERN1 || + test_pattern == DP_TEST_PATTERN_TRAINING_PATTERN2 || + test_pattern == DP_TEST_PATTERN_TRAINING_PATTERN3 || + test_pattern == DP_TEST_PATTERN_TRAINING_PATTERN4 || + test_pattern == DP_TEST_PATTERN_VIDEO_MODE) + return true; + else + return false; +} + +static void set_crtc_test_pattern(struct core_link *link, + struct pipe_ctx *pipe_ctx, + enum dp_test_pattern test_pattern) +{ + enum controller_dp_test_pattern controller_test_pattern; + enum dc_color_depth color_depth = pipe_ctx-> + stream->public.timing.display_color_depth; + struct bit_depth_reduction_params params; + + memset(¶ms, 0, sizeof(params)); + + switch (test_pattern) { + case DP_TEST_PATTERN_COLOR_SQUARES: + controller_test_pattern = + CONTROLLER_DP_TEST_PATTERN_COLORSQUARES; + break; + case DP_TEST_PATTERN_COLOR_SQUARES_CEA: + controller_test_pattern = + CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA; + break; + case DP_TEST_PATTERN_VERTICAL_BARS: + controller_test_pattern = + CONTROLLER_DP_TEST_PATTERN_VERTICALBARS; + break; + case DP_TEST_PATTERN_HORIZONTAL_BARS: + controller_test_pattern = + CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS; + break; + case DP_TEST_PATTERN_COLOR_RAMP: + controller_test_pattern = + CONTROLLER_DP_TEST_PATTERN_COLORRAMP; + break; + default: + controller_test_pattern = + CONTROLLER_DP_TEST_PATTERN_VIDEOMODE; + break; + } + + switch (test_pattern) { + case DP_TEST_PATTERN_COLOR_SQUARES: + case DP_TEST_PATTERN_COLOR_SQUARES_CEA: + case DP_TEST_PATTERN_VERTICAL_BARS: + case DP_TEST_PATTERN_HORIZONTAL_BARS: + case DP_TEST_PATTERN_COLOR_RAMP: + { + /* disable bit depth reduction */ + pipe_ctx->stream->bit_depth_params = params; + pipe_ctx->opp->funcs-> + opp_program_bit_depth_reduction(pipe_ctx->opp, ¶ms); + + pipe_ctx->tg->funcs->set_test_pattern(pipe_ctx->tg, + controller_test_pattern, color_depth); + } + break; + case DP_TEST_PATTERN_VIDEO_MODE: + { + /* restore bitdepth reduction */ + link->dc->current_context->res_ctx.pool->funcs-> + build_bit_depth_reduction_params(pipe_ctx->stream, + ¶ms); + pipe_ctx->stream->bit_depth_params = params; + pipe_ctx->opp->funcs-> + opp_program_bit_depth_reduction(pipe_ctx->opp, ¶ms); + + pipe_ctx->tg->funcs->set_test_pattern(pipe_ctx->tg, + CONTROLLER_DP_TEST_PATTERN_VIDEOMODE, + color_depth); + } + break; + + default: + break; + } +} + +bool dc_link_dp_set_test_pattern( + const struct dc_link *link, + enum dp_test_pattern test_pattern, + const struct link_training_settings *p_link_settings, + const unsigned char *p_custom_pattern, + unsigned int cust_pattern_size) +{ + struct core_link *core_link = DC_LINK_TO_CORE(link); + struct pipe_ctx *pipes = + core_link->dc->current_context->res_ctx.pipe_ctx; + struct pipe_ctx pipe_ctx = pipes[0]; + unsigned int lane; + unsigned int i; + unsigned char link_qual_pattern[LANE_COUNT_DP_MAX] = {0}; + union dpcd_training_pattern training_pattern; + union test_response test_response; + enum dpcd_phy_test_patterns pattern; + + memset(&training_pattern, 0, sizeof(training_pattern)); + memset(&test_response, 0, sizeof(test_response)); + + for (i = 0; i < MAX_PIPES; i++) { + if (pipes[i].stream->sink->link == core_link) { + pipe_ctx = pipes[i]; + break; + } + } + + /* Reset CRTC Test Pattern if it is currently running and request + * is VideoMode Reset DP Phy Test Pattern if it is currently running + * and request is VideoMode + */ + if (core_link->public.test_pattern_enabled && test_pattern == + DP_TEST_PATTERN_VIDEO_MODE) { + /* Set CRTC Test Pattern */ + set_crtc_test_pattern(core_link, &pipe_ctx, test_pattern); + dp_set_hw_test_pattern(core_link, test_pattern, + (uint8_t *)p_custom_pattern, + (uint32_t)cust_pattern_size); + + /* Unblank Stream */ + core_link->dc->hwss.unblank_stream( + &pipe_ctx, + &core_link->public.verified_link_cap); + /* TODO:m_pHwss->MuteAudioEndpoint + * (pPathMode->pDisplayPath, false); + */ + + /* Reset Test Pattern state */ + core_link->public.test_pattern_enabled = false; + + return true; + } + + /* Check for PHY Test Patterns */ + if (is_dp_phy_pattern(test_pattern)) { + /* Set DPCD Lane Settings before running test pattern */ + if (p_link_settings != NULL) { + dp_set_hw_lane_settings(core_link, p_link_settings); + dpcd_set_lane_settings(core_link, p_link_settings); + } + + /* Blank stream if running test pattern */ + if (test_pattern != DP_TEST_PATTERN_VIDEO_MODE) { + /*TODO: + * m_pHwss-> + * MuteAudioEndpoint(pPathMode->pDisplayPath, true); + */ + /* Blank stream */ + pipes->stream_enc->funcs->dp_blank(pipe_ctx.stream_enc); + } + + dp_set_hw_test_pattern(core_link, test_pattern, + (uint8_t *)p_custom_pattern, + (uint32_t)cust_pattern_size); + + if (test_pattern != DP_TEST_PATTERN_VIDEO_MODE) { + /* Set Test Pattern state */ + core_link->public.test_pattern_enabled = true; + if (p_link_settings != NULL) + dpcd_set_link_settings(core_link, + p_link_settings); + } + + switch (test_pattern) { + case DP_TEST_PATTERN_VIDEO_MODE: + pattern = PHY_TEST_PATTERN_NONE; + break; + case DP_TEST_PATTERN_D102: + pattern = PHY_TEST_PATTERN_D10_2; + break; + case DP_TEST_PATTERN_SYMBOL_ERROR: + pattern = PHY_TEST_PATTERN_SYMBOL_ERROR; + break; + case DP_TEST_PATTERN_PRBS7: + pattern = PHY_TEST_PATTERN_PRBS7; + break; + case DP_TEST_PATTERN_80BIT_CUSTOM: + pattern = PHY_TEST_PATTERN_80BIT_CUSTOM; + break; + case DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE: + pattern = PHY_TEST_PATTERN_HBR2_COMPLIANCE_EYE; + break; + default: + return false; + } + + if (test_pattern == DP_TEST_PATTERN_VIDEO_MODE + /*TODO:&& !pPathMode->pDisplayPath->IsTargetPoweredOn()*/) + return false; + + if (core_link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) { + /* tell receiver that we are sending qualification + * pattern DP 1.2 or later - DP receiver's link quality + * pattern is set using DPCD LINK_QUAL_LANEx_SET + * register (0x10B~0x10E)\ + */ + for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) + link_qual_pattern[lane] = + (unsigned char)(pattern); + + core_link_write_dpcd(core_link, + DPCD_ADDRESS_LINK_QUAL_LANE0_SET, + link_qual_pattern, + sizeof(link_qual_pattern)); + } else if (core_link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_10 || + core_link->dpcd_caps.dpcd_rev.raw == 0) { + /* tell receiver that we are sending qualification + * pattern DP 1.1a or earlier - DP receiver's link + * quality pattern is set using + * DPCD TRAINING_PATTERN_SET -> LINK_QUAL_PATTERN_SET + * register (0x102). We will use v_1.3 when we are + * setting test pattern for DP 1.1. + */ + core_link_read_dpcd(core_link, + DPCD_ADDRESS_TRAINING_PATTERN_SET, + &training_pattern.raw, + sizeof(training_pattern)); + training_pattern.v1_3.LINK_QUAL_PATTERN_SET = pattern; + core_link_write_dpcd(core_link, + DPCD_ADDRESS_TRAINING_PATTERN_SET, + &training_pattern.raw, + sizeof(training_pattern)); + } + } else { + /* CRTC Patterns */ + set_crtc_test_pattern(core_link, &pipe_ctx, test_pattern); + /* Set Test Pattern state */ + core_link->public.test_pattern_enabled = true; + + /* If this is called because of compliance test request, + * we respond ack here. + */ + if (core_link->public.compliance_test_state.bits. + SET_TEST_PATTERN_PENDING == 1) { + core_link->public.compliance_test_state.bits. + SET_TEST_PATTERN_PENDING = 0; + test_response.bits.ACK = 1; + core_link_write_dpcd(core_link, + DPCD_ADDRESS_TEST_RESPONSE, + &test_response.raw, + sizeof(test_response)); + } + } + + return true; +} diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c new file mode 100644 index 000000000000..e89f5f176ec3 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -0,0 +1,222 @@ +/* Copyright 2015 Advanced Micro Devices, Inc. */ + + +#include "dm_services.h" +#include "dc.h" +#include "inc/core_dc.h" +#include "include/ddc_service_types.h" +#include "include/i2caux_interface.h" +#include "link_hwss.h" +#include "hw_sequencer.h" +#include "dc_link_dp.h" +#include "dc_link_ddc.h" +#include "dm_helpers.h" +#include "dce/dce_link_encoder.h" +#include "dce/dce_stream_encoder.h" + +enum dc_status core_link_read_dpcd( + struct core_link* link, + uint32_t address, + uint8_t *data, + uint32_t size) +{ + if (!dm_helpers_dp_read_dpcd(link->ctx, + &link->public, + address, data, size)) + return DC_ERROR_UNEXPECTED; + + return DC_OK; +} + +enum dc_status core_link_write_dpcd( + struct core_link* link, + uint32_t address, + const uint8_t *data, + uint32_t size) +{ + if (!dm_helpers_dp_write_dpcd(link->ctx, + &link->public, + address, data, size)) + return DC_ERROR_UNEXPECTED; + + return DC_OK; +} + +void dp_receiver_power_ctrl(struct core_link *link, bool on) +{ + uint8_t state; + + state = on ? DP_POWER_STATE_D0 : DP_POWER_STATE_D3; + + core_link_write_dpcd(link, DPCD_ADDRESS_POWER_STATE, &state, + sizeof(state)); +} + +void dp_enable_link_phy( + struct core_link *link, + enum signal_type signal, + enum clock_source_id clock_source, + const struct dc_link_settings *link_settings) +{ + struct link_encoder *link_enc = link->link_enc; + + if (dc_is_dp_sst_signal(signal)) { + if (signal == SIGNAL_TYPE_EDP) { + link_enc->funcs->power_control(link_enc, true); + link_enc->funcs->backlight_control(link_enc, true); + } + + link_enc->funcs->enable_dp_output( + link_enc, + link_settings, + clock_source); + } else { + link_enc->funcs->enable_dp_mst_output( + link_enc, + link_settings, + clock_source); + } + + dp_receiver_power_ctrl(link, true); +} + +void dp_disable_link_phy(struct core_link *link, enum signal_type signal) +{ + if (!link->wa_flags.dp_keep_receiver_powered) + dp_receiver_power_ctrl(link, false); + + if (signal == SIGNAL_TYPE_EDP) + link->link_enc->funcs->backlight_control(link->link_enc, false); + + link->link_enc->funcs->disable_output(link->link_enc, signal); + + /* Clear current link setting.*/ + memset(&link->public.cur_link_settings, 0, + sizeof(link->public.cur_link_settings)); +} + +void dp_disable_link_phy_mst(struct core_link *link, enum signal_type signal) +{ + /* MST disable link only when no stream use the link */ + if (link->mst_stream_alloc_table.stream_count > 0) + return; + + dp_disable_link_phy(link, signal); +} + +bool dp_set_hw_training_pattern( + struct core_link *link, + enum hw_dp_training_pattern pattern) +{ + enum dp_test_pattern test_pattern = DP_TEST_PATTERN_UNSUPPORTED; + + switch (pattern) { + case HW_DP_TRAINING_PATTERN_1: + test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN1; + break; + case HW_DP_TRAINING_PATTERN_2: + test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN2; + break; + case HW_DP_TRAINING_PATTERN_3: + test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN3; + break; + case HW_DP_TRAINING_PATTERN_4: + test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN4; + break; + default: + break; + } + + dp_set_hw_test_pattern(link, test_pattern, NULL, 0); + + return true; +} + +void dp_set_hw_lane_settings( + struct core_link *link, + const struct link_training_settings *link_settings) +{ + struct link_encoder *encoder = link->link_enc; + + /* call Encoder to set lane settings */ + encoder->funcs->dp_set_lane_settings(encoder, link_settings); +} + +enum dp_panel_mode dp_get_panel_mode(struct core_link *link) +{ + /* We need to explicitly check that connector + * is not DP. Some Travis_VGA get reported + * by video bios as DP. + */ + if (link->public.connector_signal != SIGNAL_TYPE_DISPLAY_PORT) { + + switch (link->dpcd_caps.branch_dev_id) { + case DP_BRANCH_DEVICE_ID_2: + if (strncmp( + link->dpcd_caps.branch_dev_name, + DP_VGA_LVDS_CONVERTER_ID_2, + sizeof( + link->dpcd_caps. + branch_dev_name)) == 0) { + return DP_PANEL_MODE_SPECIAL; + } + break; + case DP_BRANCH_DEVICE_ID_3: + if (strncmp(link->dpcd_caps.branch_dev_name, + DP_VGA_LVDS_CONVERTER_ID_3, + sizeof( + link->dpcd_caps. + branch_dev_name)) == 0) { + return DP_PANEL_MODE_SPECIAL; + } + break; + default: + break; + } + + if (link->dpcd_caps.panel_mode_edp) { + return DP_PANEL_MODE_EDP; + } + } + + return DP_PANEL_MODE_DEFAULT; +} + +void dp_set_hw_test_pattern( + struct core_link *link, + enum dp_test_pattern test_pattern, + uint8_t *custom_pattern, + uint32_t custom_pattern_size) +{ + struct encoder_set_dp_phy_pattern_param pattern_param = {0}; + struct link_encoder *encoder = link->link_enc; + + pattern_param.dp_phy_pattern = test_pattern; + pattern_param.custom_pattern = custom_pattern; + pattern_param.custom_pattern_size = custom_pattern_size; + pattern_param.dp_panel_mode = dp_get_panel_mode(link); + + encoder->funcs->dp_set_phy_pattern(encoder, &pattern_param); +} + + +void dp_retrain_link(struct core_link *link) +{ + struct pipe_ctx *pipes = link->dc->current_context->res_ctx.pipe_ctx; + unsigned int i; + + for (i = 0; i < MAX_PIPES; i++) { + if (pipes[i].stream_enc != NULL) { + dm_delay_in_microseconds(link->ctx, 100); + pipes->stream_enc->funcs->dp_blank(pipes[i].stream_enc); + link->dc->hwss.disable_stream(&pipes[i]); + dc_link_dp_perform_link_training( + &link->public, + &link->public.verified_link_cap, + true); + link->dc->hwss.enable_stream(&pipes[i]); + link->dc->hwss.unblank_stream(&pipes[i], + &link->public.verified_link_cap); + } + } +} diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c new file mode 100644 index 000000000000..bd53d27e5414 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -0,0 +1,1934 @@ +/* +* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#include "dm_services.h" + +#include "resource.h" +#include "include/irq_service_interface.h" +#include "link_encoder.h" +#include "stream_encoder.h" +#include "opp.h" +#include "timing_generator.h" +#include "transform.h" +#include "set_mode_types.h" + +#include "virtual/virtual_stream_encoder.h" + +#include "dce80/dce80_resource.h" +#include "dce100/dce100_resource.h" +#include "dce110/dce110_resource.h" +#include "dce112/dce112_resource.h" + +enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id) +{ + enum dce_version dc_version = DCE_VERSION_UNKNOWN; + switch (asic_id.chip_family) { + + case FAMILY_CI: + case FAMILY_KV: + dc_version = DCE_VERSION_8_0; + break; + case FAMILY_CZ: + dc_version = DCE_VERSION_11_0; + break; + + case FAMILY_VI: + if (ASIC_REV_IS_TONGA_P(asic_id.hw_internal_rev) || + ASIC_REV_IS_FIJI_P(asic_id.hw_internal_rev)) { + dc_version = DCE_VERSION_10_0; + break; + } + if (ASIC_REV_IS_POLARIS10_P(asic_id.hw_internal_rev) || + ASIC_REV_IS_POLARIS11_M(asic_id.hw_internal_rev)) { + dc_version = DCE_VERSION_11_2; + } + break; + default: + dc_version = DCE_VERSION_UNKNOWN; + break; + } + return dc_version; +} + +struct resource_pool *dc_create_resource_pool( + struct core_dc *dc, + int num_virtual_links, + enum dce_version dc_version, + struct hw_asic_id asic_id) +{ + + switch (dc_version) { + case DCE_VERSION_8_0: + return dce80_create_resource_pool( + num_virtual_links, dc); + case DCE_VERSION_10_0: + return dce100_create_resource_pool( + num_virtual_links, dc); + case DCE_VERSION_11_0: + return dce110_create_resource_pool( + num_virtual_links, dc, asic_id); + case DCE_VERSION_11_2: + return dce112_create_resource_pool( + num_virtual_links, dc); + default: + break; + } + + return false; +} + +void dc_destroy_resource_pool(struct core_dc *dc) +{ + if (dc) { + if (dc->res_pool) + dc->res_pool->funcs->destroy(&dc->res_pool); + + if (dc->hwseq) + dm_free(dc->hwseq); + } +} + +static void update_num_audio( + const struct resource_straps *straps, + unsigned int *num_audio, + struct audio_support *aud_support) +{ + if (straps->hdmi_disable == 0) { + aud_support->hdmi_audio_native = true; + aud_support->hdmi_audio_on_dongle = true; + aud_support->dp_audio = true; + } else { + if (straps->dc_pinstraps_audio & 0x2) { + aud_support->hdmi_audio_on_dongle = true; + aud_support->dp_audio = true; + } else { + aud_support->dp_audio = true; + } + } + + switch (straps->audio_stream_number) { + case 0: /* multi streams supported */ + break; + case 1: /* multi streams not supported */ + *num_audio = 1; + break; + default: + DC_ERR("DC: unexpected audio fuse!\n"); + }; +} + +bool resource_construct( + unsigned int num_virtual_links, + struct core_dc *dc, + struct resource_pool *pool, + const struct resource_create_funcs *create_funcs) +{ + struct dc_context *ctx = dc->ctx; + const struct resource_caps *caps = pool->res_cap; + int i; + unsigned int num_audio = caps->num_audio; + struct resource_straps straps = {0}; + + if (create_funcs->read_dce_straps) + create_funcs->read_dce_straps(dc->ctx, &straps); + + pool->audio_count = 0; + if (create_funcs->create_audio) { + /* find the total number of streams available via the + * AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT + * registers (one for each pin) starting from pin 1 + * up to the max number of audio pins. + * We stop on the first pin where + * PORT_CONNECTIVITY == 1 (as instructed by HW team). + */ + update_num_audio(&straps, &num_audio, &pool->audio_support); + for (i = 0; i < pool->pipe_count && i < num_audio; i++) { + struct audio *aud = create_funcs->create_audio(ctx, i); + + if (aud == NULL) { + DC_ERR("DC: failed to create audio!\n"); + return false; + } + + if (!aud->funcs->endpoint_valid(aud)) { + aud->funcs->destroy(&aud); + break; + } + + pool->audios[i] = aud; + pool->audio_count++; + } + } + + pool->stream_enc_count = 0; + if (create_funcs->create_stream_encoder) { + for (i = 0; i < caps->num_stream_encoder; i++) { + pool->stream_enc[i] = create_funcs->create_stream_encoder(i, ctx); + if (pool->stream_enc[i] == NULL) + DC_ERR("DC: failed to create stream_encoder!\n"); + pool->stream_enc_count++; + } + } + + for (i = 0; i < num_virtual_links; i++) { + pool->stream_enc[pool->stream_enc_count] = + virtual_stream_encoder_create( + ctx, ctx->dc_bios); + if (pool->stream_enc[pool->stream_enc_count] == NULL) { + DC_ERR("DC: failed to create stream_encoder!\n"); + return false; + } + pool->stream_enc_count++; + } + + dc->hwseq = create_funcs->create_hwseq(ctx); + + return true; +} + + +void resource_unreference_clock_source( + struct resource_context *res_ctx, + struct clock_source *clock_source) +{ + int i; + for (i = 0; i < res_ctx->pool->clk_src_count; i++) { + if (res_ctx->pool->clock_sources[i] != clock_source) + continue; + + res_ctx->clock_source_ref_count[i]--; + + if (res_ctx->clock_source_ref_count[i] == 0) + clock_source->funcs->cs_power_down(clock_source); + + break; + } + + if (res_ctx->pool->dp_clock_source == clock_source) { + res_ctx->dp_clock_source_ref_count--; + + if (res_ctx->dp_clock_source_ref_count == 0) + clock_source->funcs->cs_power_down(clock_source); + } +} + +void resource_reference_clock_source( + struct resource_context *res_ctx, + struct clock_source *clock_source) +{ + int i; + for (i = 0; i < res_ctx->pool->clk_src_count; i++) { + if (res_ctx->pool->clock_sources[i] != clock_source) + continue; + + res_ctx->clock_source_ref_count[i]++; + break; + } + + if (res_ctx->pool->dp_clock_source == clock_source) + res_ctx->dp_clock_source_ref_count++; +} + +bool resource_are_streams_timing_synchronizable( + const struct core_stream *stream1, + const struct core_stream *stream2) +{ + if (stream1->public.timing.h_total != stream2->public.timing.h_total) + return false; + + if (stream1->public.timing.v_total != stream2->public.timing.v_total) + return false; + + if (stream1->public.timing.h_addressable + != stream2->public.timing.h_addressable) + return false; + + if (stream1->public.timing.v_addressable + != stream2->public.timing.v_addressable) + return false; + + if (stream1->public.timing.pix_clk_khz + != stream2->public.timing.pix_clk_khz) + return false; + + if (stream1->phy_pix_clk != stream2->phy_pix_clk + && !dc_is_dp_signal(stream1->signal) + && !dc_is_dp_signal(stream2->signal)) + return false; + + return true; +} + +static bool is_sharable_clk_src( + const struct pipe_ctx *pipe_with_clk_src, + const struct pipe_ctx *pipe) +{ + if (pipe_with_clk_src->clock_source == NULL) + return false; + + if (pipe_with_clk_src->stream->signal == SIGNAL_TYPE_VIRTUAL) + return false; + + if (dc_is_dp_signal(pipe_with_clk_src->stream->signal)) + return false; + + if (dc_is_hdmi_signal(pipe_with_clk_src->stream->signal) + && dc_is_dvi_signal(pipe->stream->signal)) + return false; + + if (dc_is_hdmi_signal(pipe->stream->signal) + && dc_is_dvi_signal(pipe_with_clk_src->stream->signal)) + return false; + + if (!resource_are_streams_timing_synchronizable( + pipe_with_clk_src->stream, pipe->stream)) + return false; + + return true; +} + +struct clock_source *resource_find_used_clk_src_for_sharing( + struct resource_context *res_ctx, + struct pipe_ctx *pipe_ctx) +{ + int i; + + for (i = 0; i < MAX_PIPES; i++) { + if (is_sharable_clk_src(&res_ctx->pipe_ctx[i], pipe_ctx)) + return res_ctx->pipe_ctx[i].clock_source; + } + + return NULL; +} + +static enum pixel_format convert_pixel_format_to_dalsurface( + enum surface_pixel_format surface_pixel_format) +{ + enum pixel_format dal_pixel_format = PIXEL_FORMAT_UNKNOWN; + + switch (surface_pixel_format) { + case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS: + dal_pixel_format = PIXEL_FORMAT_INDEX8; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: + dal_pixel_format = PIXEL_FORMAT_RGB565; + break; + case SURFACE_PIXEL_FORMAT_GRPH_RGB565: + dal_pixel_format = PIXEL_FORMAT_RGB565; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: + dal_pixel_format = PIXEL_FORMAT_ARGB8888; + break; + case SURFACE_PIXEL_FORMAT_GRPH_BGRA8888: + dal_pixel_format = PIXEL_FORMAT_ARGB8888; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: + dal_pixel_format = PIXEL_FORMAT_ARGB2101010; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: + dal_pixel_format = PIXEL_FORMAT_ARGB2101010; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: + dal_pixel_format = PIXEL_FORMAT_ARGB2101010_XRBIAS; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: + dal_pixel_format = PIXEL_FORMAT_FP16; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: + dal_pixel_format = PIXEL_FORMAT_420BPP12; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: + dal_pixel_format = PIXEL_FORMAT_420BPP12; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: + default: + dal_pixel_format = PIXEL_FORMAT_UNKNOWN; + break; + } + return dal_pixel_format; +} + +static void rect_swap_helper(struct rect *rect) +{ + uint32_t temp = 0; + + temp = rect->height; + rect->height = rect->width; + rect->width = temp; + + temp = rect->x; + rect->x = rect->y; + rect->y = temp; +} + +static void calculate_viewport( + const struct dc_surface *surface, + struct pipe_ctx *pipe_ctx) +{ + struct rect stream_src = pipe_ctx->stream->public.src; + struct rect src = surface->src_rect; + struct rect dst = surface->dst_rect; + struct rect surface_clip = surface->clip_rect; + struct rect clip = {0}; + + + if (surface->rotation == ROTATION_ANGLE_90 || + surface->rotation == ROTATION_ANGLE_270) { + rect_swap_helper(&src); + rect_swap_helper(&dst); + rect_swap_helper(&surface_clip); + rect_swap_helper(&stream_src); + } + + /* The actual clip is an intersection between stream + * source and surface clip + */ + clip.x = stream_src.x > surface_clip.x ? + stream_src.x : surface_clip.x; + + clip.width = stream_src.x + stream_src.width < + surface_clip.x + surface_clip.width ? + stream_src.x + stream_src.width - clip.x : + surface_clip.x + surface_clip.width - clip.x ; + + clip.y = stream_src.y > surface_clip.y ? + stream_src.y : surface_clip.y; + + clip.height = stream_src.y + stream_src.height < + surface_clip.y + surface_clip.height ? + stream_src.y + stream_src.height - clip.y : + surface_clip.y + surface_clip.height - clip.y ; + + /* offset = src.ofs + (clip.ofs - dst.ofs) * scl_ratio + * num_pixels = clip.num_pix * scl_ratio + */ + pipe_ctx->scl_data.viewport.x = src.x + (clip.x - dst.x) * + src.width / dst.width; + pipe_ctx->scl_data.viewport.width = clip.width * + src.width / dst.width; + + pipe_ctx->scl_data.viewport.y = src.y + (clip.y - dst.y) * + src.height / dst.height; + pipe_ctx->scl_data.viewport.height = clip.height * + src.height / dst.height; + + /* Minimum viewport such that 420/422 chroma vp is non 0 */ + if (pipe_ctx->scl_data.viewport.width < 2) + pipe_ctx->scl_data.viewport.width = 2; + if (pipe_ctx->scl_data.viewport.height < 2) + pipe_ctx->scl_data.viewport.height = 2; +} + +static void calculate_recout( + const struct dc_surface *surface, + struct pipe_ctx *pipe_ctx) +{ + struct core_stream *stream = pipe_ctx->stream; + struct rect clip = surface->clip_rect; + + pipe_ctx->scl_data.recout.x = stream->public.dst.x; + if (stream->public.src.x < clip.x) + pipe_ctx->scl_data.recout.x += (clip.x + - stream->public.src.x) * stream->public.dst.width + / stream->public.src.width; + + pipe_ctx->scl_data.recout.width = clip.width * + stream->public.dst.width / stream->public.src.width; + if (pipe_ctx->scl_data.recout.width + pipe_ctx->scl_data.recout.x > + stream->public.dst.x + stream->public.dst.width) + pipe_ctx->scl_data.recout.width = + stream->public.dst.x + stream->public.dst.width + - pipe_ctx->scl_data.recout.x; + + pipe_ctx->scl_data.recout.y = stream->public.dst.y; + if (stream->public.src.y < clip.y) + pipe_ctx->scl_data.recout.y += (clip.y + - stream->public.src.y) * stream->public.dst.height + / stream->public.src.height; + + pipe_ctx->scl_data.recout.height = clip.height * + stream->public.dst.height / stream->public.src.height; + if (pipe_ctx->scl_data.recout.height + pipe_ctx->scl_data.recout.y > + stream->public.dst.y + stream->public.dst.height) + pipe_ctx->scl_data.recout.height = + stream->public.dst.y + stream->public.dst.height + - pipe_ctx->scl_data.recout.y; +} + +static void calculate_scaling_ratios( + const struct dc_surface *surface, + struct pipe_ctx *pipe_ctx) +{ + struct core_stream *stream = pipe_ctx->stream; + const uint32_t in_w = stream->public.src.width; + const uint32_t in_h = stream->public.src.height; + const uint32_t out_w = stream->public.dst.width; + const uint32_t out_h = stream->public.dst.height; + + pipe_ctx->scl_data.ratios.horz = dal_fixed31_32_from_fraction( + surface->src_rect.width, + surface->dst_rect.width); + pipe_ctx->scl_data.ratios.vert = dal_fixed31_32_from_fraction( + surface->src_rect.height, + surface->dst_rect.height); + + if (surface->stereo_format == PLANE_STEREO_FORMAT_SIDE_BY_SIDE) + pipe_ctx->scl_data.ratios.horz.value *= 2; + else if (surface->stereo_format == PLANE_STEREO_FORMAT_TOP_AND_BOTTOM) + pipe_ctx->scl_data.ratios.vert.value *= 2; + + pipe_ctx->scl_data.ratios.vert.value = div64_s64( + pipe_ctx->scl_data.ratios.vert.value * in_h, out_h); + pipe_ctx->scl_data.ratios.horz.value = div64_s64( + pipe_ctx->scl_data.ratios.horz.value * in_w, out_w); + + pipe_ctx->scl_data.ratios.horz_c = pipe_ctx->scl_data.ratios.horz; + pipe_ctx->scl_data.ratios.vert_c = pipe_ctx->scl_data.ratios.vert; + + if (pipe_ctx->scl_data.format == PIXEL_FORMAT_420BPP12) { + pipe_ctx->scl_data.ratios.horz_c.value /= 2; + pipe_ctx->scl_data.ratios.vert_c.value /= 2; + } +} + +bool resource_build_scaling_params( + const struct dc_surface *surface, + struct pipe_ctx *pipe_ctx) +{ + bool res; + struct dc_crtc_timing *timing = &pipe_ctx->stream->public.timing; + /* Important: scaling ratio calculation requires pixel format, + * lb depth calculation requires recout and taps require scaling ratios. + */ + pipe_ctx->scl_data.format = convert_pixel_format_to_dalsurface(surface->format); + + calculate_viewport(surface, pipe_ctx); + + if (pipe_ctx->scl_data.viewport.height < 16 || pipe_ctx->scl_data.viewport.width < 16) + return false; + + calculate_scaling_ratios(surface, pipe_ctx); + + calculate_recout(surface, pipe_ctx); + + /** + * Setting line buffer pixel depth to 24bpp yields banding + * on certain displays, such as the Sharp 4k + */ + pipe_ctx->scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; + + pipe_ctx->scl_data.h_active = timing->h_addressable; + pipe_ctx->scl_data.v_active = timing->v_addressable; + + /* Taps calculations */ + res = pipe_ctx->xfm->funcs->transform_get_optimal_number_of_taps( + pipe_ctx->xfm, &pipe_ctx->scl_data, &surface->scaling_quality); + + if (!res) { + /* Try 24 bpp linebuffer */ + pipe_ctx->scl_data.lb_params.depth = LB_PIXEL_DEPTH_24BPP; + + res = pipe_ctx->xfm->funcs->transform_get_optimal_number_of_taps( + pipe_ctx->xfm, &pipe_ctx->scl_data, &surface->scaling_quality); + } + + dm_logger_write(pipe_ctx->stream->ctx->logger, LOG_SCALER, + "%s: Viewport:\nheight:%d width:%d x:%d " + "y:%d\n dst_rect:\nheight:%d width:%d x:%d " + "y:%d\n", + __func__, + pipe_ctx->scl_data.viewport.height, + pipe_ctx->scl_data.viewport.width, + pipe_ctx->scl_data.viewport.x, + pipe_ctx->scl_data.viewport.y, + surface->dst_rect.height, + surface->dst_rect.width, + surface->dst_rect.x, + surface->dst_rect.y); + + return res; +} + + +enum dc_status resource_build_scaling_params_for_context( + const struct core_dc *dc, + struct validate_context *context) +{ + int i; + + for (i = 0; i < MAX_PIPES; i++) { + if (context->res_ctx.pipe_ctx[i].surface != NULL && + context->res_ctx.pipe_ctx[i].stream != NULL) + if (!resource_build_scaling_params( + &context->res_ctx.pipe_ctx[i].surface->public, + &context->res_ctx.pipe_ctx[i])) + return DC_FAIL_BANDWIDTH_VALIDATE; + } + + return DC_OK; +} + +static void detach_surfaces_for_target( + struct validate_context *context, + const struct dc_target *dc_target) +{ + int i; + struct core_stream *stream = DC_STREAM_TO_CORE(dc_target->streams[0]); + + for (i = 0; i < context->res_ctx.pool->pipe_count; i++) { + struct pipe_ctx *cur_pipe = &context->res_ctx.pipe_ctx[i]; + if (cur_pipe->stream == stream) { + cur_pipe->surface = NULL; + cur_pipe->top_pipe = NULL; + cur_pipe->bottom_pipe = NULL; + } + } +} + +struct pipe_ctx *find_idle_secondary_pipe(struct resource_context *res_ctx) +{ + int i; + struct pipe_ctx *secondary_pipe = NULL; + + /* + * search backwards for the second pipe to keep pipe + * assignment more consistent + */ + + for (i = res_ctx->pool->pipe_count - 1; i >= 0; i--) { + if (res_ctx->pipe_ctx[i].stream == NULL) { + secondary_pipe = &res_ctx->pipe_ctx[i]; + secondary_pipe->pipe_idx = i; + break; + } + } + + + return secondary_pipe; +} + +struct pipe_ctx *resource_get_head_pipe_for_stream( + struct resource_context *res_ctx, + const struct core_stream *stream) +{ + int i; + for (i = 0; i < res_ctx->pool->pipe_count; i++) { + if (res_ctx->pipe_ctx[i].stream == stream && + !res_ctx->pipe_ctx[i].top_pipe) { + return &res_ctx->pipe_ctx[i]; + break; + } + } + return NULL; +} + +/* + * A free_pipe for a target is defined here as a pipe with a stream that belongs + * to the target but has no surface attached yet + */ +static struct pipe_ctx *acquire_free_pipe_for_target( + struct resource_context *res_ctx, + const struct dc_target *dc_target) +{ + int i; + struct core_stream *stream = DC_STREAM_TO_CORE(dc_target->streams[0]); + + struct pipe_ctx *head_pipe = NULL; + + /* Find head pipe, which has the back end set up*/ + + head_pipe = resource_get_head_pipe_for_stream(res_ctx, stream); + + if (!head_pipe) + ASSERT(0); + + if (!head_pipe->surface) + return head_pipe; + + /* Re-use pipe already acquired for this stream if available*/ + for (i = res_ctx->pool->pipe_count - 1; i >= 0; i--) { + if (res_ctx->pipe_ctx[i].stream == stream && + !res_ctx->pipe_ctx[i].surface) { + return &res_ctx->pipe_ctx[i]; + } + } + + /* + * At this point we have no re-useable pipe for this stream and we need + * to acquire an idle one to satisfy the request + */ + + if(!res_ctx->pool->funcs->acquire_idle_pipe_for_layer) + return NULL; + + return res_ctx->pool->funcs->acquire_idle_pipe_for_layer(res_ctx, stream); + +} + +static void release_free_pipes_for_target( + struct resource_context *res_ctx, + const struct dc_target *dc_target) +{ + int i; + struct core_stream *stream = DC_STREAM_TO_CORE(dc_target->streams[0]); + + for (i = res_ctx->pool->pipe_count - 1; i >= 0; i--) { + if (res_ctx->pipe_ctx[i].stream == stream && + !res_ctx->pipe_ctx[i].surface) { + res_ctx->pipe_ctx[i].stream = NULL; + } + } +} + +bool resource_attach_surfaces_to_context( + const struct dc_surface * const *surfaces, + int surface_count, + const struct dc_target *dc_target, + struct validate_context *context) +{ + int i; + struct pipe_ctx *tail_pipe; + struct dc_target_status *target_status = NULL; + + + if (surface_count > MAX_SURFACE_NUM) { + dm_error("Surface: can not attach %d surfaces! Maximum is: %d\n", + surface_count, MAX_SURFACE_NUM); + return false; + } + + for (i = 0; i < context->target_count; i++) + if (&context->targets[i]->public == dc_target) { + target_status = &context->target_status[i]; + break; + } + if (target_status == NULL) { + dm_error("Existing target not found; failed to attach surfaces\n"); + return false; + } + + /* retain new surfaces */ + for (i = 0; i < surface_count; i++) + dc_surface_retain(surfaces[i]); + + detach_surfaces_for_target(context, dc_target); + + /* release existing surfaces*/ + for (i = 0; i < target_status->surface_count; i++) + dc_surface_release(target_status->surfaces[i]); + + for (i = surface_count; i < target_status->surface_count; i++) + target_status->surfaces[i] = NULL; + + target_status->surface_count = 0; + + if (surface_count == 0) + return true; + + tail_pipe = NULL; + for (i = 0; i < surface_count; i++) { + struct core_surface *surface = DC_SURFACE_TO_CORE(surfaces[i]); + struct pipe_ctx *free_pipe = acquire_free_pipe_for_target( + &context->res_ctx, dc_target); + + if (!free_pipe) { + target_status->surfaces[i] = NULL; + return false; + } + + free_pipe->surface = surface; + + if (tail_pipe) { + free_pipe->top_pipe = tail_pipe; + tail_pipe->bottom_pipe = free_pipe; + } + + tail_pipe = free_pipe; + } + + release_free_pipes_for_target(&context->res_ctx, dc_target); + + /* assign new surfaces*/ + for (i = 0; i < surface_count; i++) + target_status->surfaces[i] = surfaces[i]; + + target_status->surface_count = surface_count; + + return true; +} + + +static bool is_timing_changed(const struct core_stream *cur_stream, + const struct core_stream *new_stream) +{ + if (cur_stream == NULL) + return true; + + /* If sink pointer changed, it means this is a hotplug, we should do + * full hw setting. + */ + if (cur_stream->sink != new_stream->sink) + return true; + + /* If output color space is changed, need to reprogram info frames */ + if (cur_stream->public.output_color_space != + new_stream->public.output_color_space) + return true; + + return memcmp( + &cur_stream->public.timing, + &new_stream->public.timing, + sizeof(struct dc_crtc_timing)) != 0; +} + +static bool are_stream_backends_same( + const struct core_stream *stream_a, const struct core_stream *stream_b) +{ + if (stream_a == stream_b) + return true; + + if (stream_a == NULL || stream_b == NULL) + return false; + + if (is_timing_changed(stream_a, stream_b)) + return false; + + return true; +} + +bool is_target_unchanged( + const struct core_target *old_target, const struct core_target *target) +{ + int i; + + if (old_target == target) + return true; + if (old_target->public.stream_count != target->public.stream_count) + return false; + + for (i = 0; i < old_target->public.stream_count; i++) { + const struct core_stream *old_stream = DC_STREAM_TO_CORE( + old_target->public.streams[i]); + const struct core_stream *stream = DC_STREAM_TO_CORE( + target->public.streams[i]); + + if (!are_stream_backends_same(old_stream, stream)) + return false; + } + + return true; +} + +bool resource_validate_attach_surfaces( + const struct dc_validation_set set[], + int set_count, + const struct validate_context *old_context, + struct validate_context *context) +{ + int i, j; + + for (i = 0; i < set_count; i++) { + for (j = 0; j < old_context->target_count; j++) + if (is_target_unchanged( + old_context->targets[j], + context->targets[i])) { + if (!resource_attach_surfaces_to_context( + old_context->target_status[j].surfaces, + old_context->target_status[j].surface_count, + &context->targets[i]->public, + context)) + return false; + context->target_status[i] = old_context->target_status[j]; + } + if (set[i].surface_count != 0) + if (!resource_attach_surfaces_to_context( + set[i].surfaces, + set[i].surface_count, + &context->targets[i]->public, + context)) + return false; + + } + + return true; +} + +/* Maximum TMDS single link pixel clock 165MHz */ +#define TMDS_MAX_PIXEL_CLOCK_IN_KHZ 165000 + +static void set_stream_engine_in_use( + struct resource_context *res_ctx, + struct stream_encoder *stream_enc) +{ + int i; + + for (i = 0; i < res_ctx->pool->stream_enc_count; i++) { + if (res_ctx->pool->stream_enc[i] == stream_enc) + res_ctx->is_stream_enc_acquired[i] = true; + } +} + +/* TODO: release audio object */ +static void set_audio_in_use( + struct resource_context *res_ctx, + struct audio *audio) +{ + int i; + for (i = 0; i < res_ctx->pool->audio_count; i++) { + if (res_ctx->pool->audios[i] == audio) { + res_ctx->is_audio_acquired[i] = true; + } + } +} + +static int acquire_first_free_pipe( + struct resource_context *res_ctx, + struct core_stream *stream) +{ + int i; + + for (i = 0; i < res_ctx->pool->pipe_count; i++) { + if (!res_ctx->pipe_ctx[i].stream) { + struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; + + pipe_ctx->tg = res_ctx->pool->timing_generators[i]; + pipe_ctx->mi = res_ctx->pool->mis[i]; + pipe_ctx->ipp = res_ctx->pool->ipps[i]; + pipe_ctx->xfm = res_ctx->pool->transforms[i]; + pipe_ctx->opp = res_ctx->pool->opps[i]; + pipe_ctx->dis_clk = res_ctx->pool->display_clock; + pipe_ctx->pipe_idx = i; + + pipe_ctx->stream = stream; + return i; + } + } + return -1; +} + +static struct stream_encoder *find_first_free_match_stream_enc_for_link( + struct resource_context *res_ctx, + struct core_stream *stream) +{ + int i; + int j = -1; + struct core_link *link = stream->sink->link; + + for (i = 0; i < res_ctx->pool->stream_enc_count; i++) { + if (!res_ctx->is_stream_enc_acquired[i] && + res_ctx->pool->stream_enc[i]) { + /* Store first available for MST second display + * in daisy chain use case */ + j = i; + if (res_ctx->pool->stream_enc[i]->id == + link->link_enc->preferred_engine) + return res_ctx->pool->stream_enc[i]; + } + } + + /* + * below can happen in cases when stream encoder is acquired: + * 1) for second MST display in chain, so preferred engine already + * acquired; + * 2) for another link, which preferred engine already acquired by any + * MST configuration. + * + * If signal is of DP type and preferred engine not found, return last available + * + * TODO - This is just a patch up and a generic solution is + * required for non DP connectors. + */ + + if (j >= 0 && dc_is_dp_signal(stream->signal)) + return res_ctx->pool->stream_enc[j]; + + return NULL; +} + +static struct audio *find_first_free_audio(struct resource_context *res_ctx) +{ + int i; + for (i = 0; i < res_ctx->pool->audio_count; i++) { + if (res_ctx->is_audio_acquired[i] == false) { + return res_ctx->pool->audios[i]; + } + } + + return 0; +} + +static void update_stream_signal(struct core_stream *stream) +{ + const struct dc_sink *dc_sink = stream->public.sink; + + stream->signal = dc_sink->sink_signal; + /* For asic supports dual link DVI, we should adjust signal type + * based on timing pixel clock. If pixel clock more than 165Mhz, + * signal is dual link, otherwise, single link. + */ + if (dc_sink->sink_signal == SIGNAL_TYPE_DVI_SINGLE_LINK || + dc_sink->sink_signal == SIGNAL_TYPE_DVI_DUAL_LINK) { + if (stream->public.timing.pix_clk_khz > + TMDS_MAX_PIXEL_CLOCK_IN_KHZ) + stream->signal = SIGNAL_TYPE_DVI_DUAL_LINK; + else + stream->signal = SIGNAL_TYPE_DVI_SINGLE_LINK; + } +} + +bool resource_is_stream_unchanged( + const struct validate_context *old_context, struct core_stream *stream) +{ + int i, j; + + for (i = 0; i < old_context->target_count; i++) { + struct core_target *old_target = old_context->targets[i]; + + for (j = 0; j < old_target->public.stream_count; j++) { + struct core_stream *old_stream = + DC_STREAM_TO_CORE(old_target->public.streams[j]); + + if (are_stream_backends_same(old_stream, stream)) + return true; + } + } + + return false; +} + +static void copy_pipe_ctx( + const struct pipe_ctx *from_pipe_ctx, struct pipe_ctx *to_pipe_ctx) +{ + struct core_surface *surface = to_pipe_ctx->surface; + struct core_stream *stream = to_pipe_ctx->stream; + + *to_pipe_ctx = *from_pipe_ctx; + to_pipe_ctx->stream = stream; + if (surface != NULL) + to_pipe_ctx->surface = surface; +} + +static struct core_stream *find_pll_sharable_stream( + const struct core_stream *stream_needs_pll, + struct validate_context *context) +{ + int i, j; + + for (i = 0; i < context->target_count; i++) { + struct core_target *target = context->targets[i]; + + for (j = 0; j < target->public.stream_count; j++) { + struct core_stream *stream_has_pll = + DC_STREAM_TO_CORE(target->public.streams[j]); + + /* We are looking for non dp, non virtual stream */ + if (resource_are_streams_timing_synchronizable( + stream_needs_pll, stream_has_pll) + && !dc_is_dp_signal(stream_has_pll->signal) + && stream_has_pll->sink->link->public.connector_signal + != SIGNAL_TYPE_VIRTUAL) + return stream_has_pll; + } + } + + return NULL; +} + +static int get_norm_pix_clk(const struct dc_crtc_timing *timing) +{ + uint32_t pix_clk = timing->pix_clk_khz; + uint32_t normalized_pix_clk = pix_clk; + + if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) + pix_clk /= 2; + + switch (timing->display_color_depth) { + case COLOR_DEPTH_888: + normalized_pix_clk = pix_clk; + break; + case COLOR_DEPTH_101010: + normalized_pix_clk = (pix_clk * 30) / 24; + break; + case COLOR_DEPTH_121212: + normalized_pix_clk = (pix_clk * 36) / 24; + break; + case COLOR_DEPTH_161616: + normalized_pix_clk = (pix_clk * 48) / 24; + break; + default: + ASSERT(0); + break; + } + + return normalized_pix_clk; +} + +static void calculate_phy_pix_clks( + const struct core_dc *dc, + struct validate_context *context) +{ + int i, j; + + for (i = 0; i < context->target_count; i++) { + struct core_target *target = context->targets[i]; + + for (j = 0; j < target->public.stream_count; j++) { + struct core_stream *stream = + DC_STREAM_TO_CORE(target->public.streams[j]); + + update_stream_signal(stream); + + /* update actual pixel clock on all streams */ + if (dc_is_hdmi_signal(stream->signal)) + stream->phy_pix_clk = get_norm_pix_clk( + &stream->public.timing); + else + stream->phy_pix_clk = + stream->public.timing.pix_clk_khz; + } + } +} + +enum dc_status resource_map_pool_resources( + const struct core_dc *dc, + struct validate_context *context) +{ + int i, j, k; + + calculate_phy_pix_clks(dc, context); + + for (i = 0; i < context->target_count; i++) { + struct core_target *target = context->targets[i]; + + for (j = 0; j < target->public.stream_count; j++) { + struct core_stream *stream = + DC_STREAM_TO_CORE(target->public.streams[j]); + + if (!resource_is_stream_unchanged(dc->current_context, stream)) + continue; + + /* mark resources used for stream that is already active */ + for (k = 0; k < MAX_PIPES; k++) { + struct pipe_ctx *pipe_ctx = + &context->res_ctx.pipe_ctx[k]; + const struct pipe_ctx *old_pipe_ctx = + &dc->current_context->res_ctx.pipe_ctx[k]; + + if (!are_stream_backends_same(old_pipe_ctx->stream, stream)) + continue; + + pipe_ctx->stream = stream; + copy_pipe_ctx(old_pipe_ctx, pipe_ctx); + + set_stream_engine_in_use( + &context->res_ctx, + pipe_ctx->stream_enc); + + /* Switch to dp clock source only if there is + * no non dp stream that shares the same timing + * with the dp stream. + */ + if (dc_is_dp_signal(pipe_ctx->stream->signal) && + !find_pll_sharable_stream(stream, context)) + pipe_ctx->clock_source = + context->res_ctx.pool->dp_clock_source; + + resource_reference_clock_source( + &context->res_ctx, + pipe_ctx->clock_source); + + set_audio_in_use(&context->res_ctx, + pipe_ctx->audio); + } + } + } + + for (i = 0; i < context->target_count; i++) { + struct core_target *target = context->targets[i]; + + for (j = 0; j < target->public.stream_count; j++) { + struct core_stream *stream = + DC_STREAM_TO_CORE(target->public.streams[j]); + struct pipe_ctx *pipe_ctx = NULL; + int pipe_idx = -1; + + if (resource_is_stream_unchanged(dc->current_context, stream)) + continue; + /* acquire new resources */ + pipe_idx = acquire_first_free_pipe( + &context->res_ctx, stream); + if (pipe_idx < 0) + return DC_NO_CONTROLLER_RESOURCE; + + + pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx]; + + pipe_ctx->stream_enc = + find_first_free_match_stream_enc_for_link( + &context->res_ctx, stream); + + if (!pipe_ctx->stream_enc) + return DC_NO_STREAM_ENG_RESOURCE; + + set_stream_engine_in_use( + &context->res_ctx, + pipe_ctx->stream_enc); + + /* TODO: Add check if ASIC support and EDID audio */ + if (!stream->sink->converter_disable_audio && + dc_is_audio_capable_signal(pipe_ctx->stream->signal) && + stream->public.audio_info.mode_count) { + pipe_ctx->audio = find_first_free_audio( + &context->res_ctx); + + /* + * Audio assigned in order first come first get. + * There are asics which has number of audio + * resources less then number of pipes + */ + if (pipe_ctx->audio) + set_audio_in_use( + &context->res_ctx, + pipe_ctx->audio); + } + + if (j == 0) { + context->target_status[i].primary_otg_inst = + pipe_ctx->tg->inst; + } + } + } + + return DC_OK; +} + +/* first target in the context is used to populate the rest */ +void validate_guaranteed_copy_target( + struct validate_context *context, + int max_targets) +{ + int i; + + for (i = 1; i < max_targets; i++) { + context->targets[i] = context->targets[0]; + + copy_pipe_ctx(&context->res_ctx.pipe_ctx[0], + &context->res_ctx.pipe_ctx[i]); + context->res_ctx.pipe_ctx[i].stream = + context->res_ctx.pipe_ctx[0].stream; + + dc_target_retain(&context->targets[i]->public); + context->target_count++; + } +} + +static void translate_info_frame(const struct hw_info_frame *hw_info_frame, + struct encoder_info_frame *encoder_info_frame) +{ + memset( + encoder_info_frame, 0, sizeof(struct encoder_info_frame)); + + /* For gamut we recalc checksum */ + if (hw_info_frame->gamut_packet.valid) { + uint8_t chk_sum = 0; + uint8_t *ptr; + uint8_t i; + + memmove( + &encoder_info_frame->gamut, + &hw_info_frame->gamut_packet, + sizeof(struct hw_info_packet)); + + /*start of the Gamut data. */ + ptr = &encoder_info_frame->gamut.sb[3]; + + for (i = 0; i <= encoder_info_frame->gamut.sb[1]; i++) + chk_sum += ptr[i]; + + encoder_info_frame->gamut.sb[2] = (uint8_t) (0x100 - chk_sum); + } + + if (hw_info_frame->avi_info_packet.valid) { + memmove( + &encoder_info_frame->avi, + &hw_info_frame->avi_info_packet, + sizeof(struct hw_info_packet)); + } + + if (hw_info_frame->vendor_info_packet.valid) { + memmove( + &encoder_info_frame->vendor, + &hw_info_frame->vendor_info_packet, + sizeof(struct hw_info_packet)); + } + + if (hw_info_frame->spd_packet.valid) { + memmove( + &encoder_info_frame->spd, + &hw_info_frame->spd_packet, + sizeof(struct hw_info_packet)); + } + + if (hw_info_frame->vsc_packet.valid) { + memmove( + &encoder_info_frame->vsc, + &hw_info_frame->vsc_packet, + sizeof(struct hw_info_packet)); + } +} + +static void set_avi_info_frame( + struct hw_info_packet *info_packet, + struct pipe_ctx *pipe_ctx) +{ + struct core_stream *stream = pipe_ctx->stream; + enum dc_color_space color_space = COLOR_SPACE_UNKNOWN; + struct info_frame info_frame = { {0} }; + uint32_t pixel_encoding = 0; + enum scanning_type scan_type = SCANNING_TYPE_NODATA; + enum dc_aspect_ratio aspect = ASPECT_RATIO_NO_DATA; + bool itc = false; + uint8_t cn0_cn1 = 0; + uint8_t *check_sum = NULL; + uint8_t byte_index = 0; + + if (info_packet == NULL) + return; + + color_space = pipe_ctx->stream->public.output_color_space; + + /* Initialize header */ + info_frame.avi_info_packet.info_packet_hdmi.bits.header. + info_frame_type = INFO_FRAME_AVI; + /* InfoFrameVersion_3 is defined by CEA861F (Section 6.4), but shall + * not be used in HDMI 2.0 (Section 10.1) */ + info_frame.avi_info_packet.info_packet_hdmi.bits.header.version = + INFO_FRAME_VERSION_2; + info_frame.avi_info_packet.info_packet_hdmi.bits.header.length = + INFO_FRAME_SIZE_AVI; + + /* + * IDO-defined (Y2,Y1,Y0 = 1,1,1) shall not be used by devices built + * according to HDMI 2.0 spec (Section 10.1) + */ + + switch (stream->public.timing.pixel_encoding) { + case PIXEL_ENCODING_YCBCR422: + pixel_encoding = 1; + break; + + case PIXEL_ENCODING_YCBCR444: + pixel_encoding = 2; + break; + case PIXEL_ENCODING_YCBCR420: + pixel_encoding = 3; + break; + + case PIXEL_ENCODING_RGB: + default: + pixel_encoding = 0; + } + + /* Y0_Y1_Y2 : The pixel encoding */ + /* H14b AVI InfoFrame has extension on Y-field from 2 bits to 3 bits */ + info_frame.avi_info_packet.info_packet_hdmi.bits.Y0_Y1_Y2 = + pixel_encoding; + + /* A0 = 1 Active Format Information valid */ + info_frame.avi_info_packet.info_packet_hdmi.bits.A0 = + ACTIVE_FORMAT_VALID; + + /* B0, B1 = 3; Bar info data is valid */ + info_frame.avi_info_packet.info_packet_hdmi.bits.B0_B1 = + BAR_INFO_BOTH_VALID; + + info_frame.avi_info_packet.info_packet_hdmi.bits.SC0_SC1 = + PICTURE_SCALING_UNIFORM; + + /* S0, S1 : Underscan / Overscan */ + /* TODO: un-hardcode scan type */ + scan_type = SCANNING_TYPE_UNDERSCAN; + info_frame.avi_info_packet.info_packet_hdmi.bits.S0_S1 = scan_type; + + /* C0, C1 : Colorimetry */ + if (color_space == COLOR_SPACE_YCBCR709) + info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 = + COLORIMETRY_ITU709; + else if (color_space == COLOR_SPACE_YCBCR601) + info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 = + COLORIMETRY_ITU601; + else + info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 = + COLORIMETRY_NO_DATA; + + /* TODO: un-hardcode aspect ratio */ + aspect = stream->public.timing.aspect_ratio; + + switch (aspect) { + case ASPECT_RATIO_4_3: + case ASPECT_RATIO_16_9: + info_frame.avi_info_packet.info_packet_hdmi.bits.M0_M1 = aspect; + break; + + case ASPECT_RATIO_NO_DATA: + case ASPECT_RATIO_64_27: + case ASPECT_RATIO_256_135: + default: + info_frame.avi_info_packet.info_packet_hdmi.bits.M0_M1 = 0; + } + + /* Active Format Aspect ratio - same as Picture Aspect Ratio. */ + info_frame.avi_info_packet.info_packet_hdmi.bits.R0_R3 = + ACTIVE_FORMAT_ASPECT_RATIO_SAME_AS_PICTURE; + + /* TODO: un-hardcode cn0_cn1 and itc */ + cn0_cn1 = 0; + itc = false; + + if (itc) { + info_frame.avi_info_packet.info_packet_hdmi.bits.ITC = 1; + info_frame.avi_info_packet.info_packet_hdmi.bits.CN0_CN1 = + cn0_cn1; + } + + /* TODO : We should handle YCC quantization */ + /* but we do not have matrix calculation */ + if (color_space == COLOR_SPACE_SRGB) { + info_frame.avi_info_packet.info_packet_hdmi.bits.Q0_Q1 = + RGB_QUANTIZATION_FULL_RANGE; + info_frame.avi_info_packet.info_packet_hdmi.bits.YQ0_YQ1 = + YYC_QUANTIZATION_FULL_RANGE; + } else if (color_space == COLOR_SPACE_SRGB_LIMITED) { + info_frame.avi_info_packet.info_packet_hdmi.bits.Q0_Q1 = + RGB_QUANTIZATION_LIMITED_RANGE; + info_frame.avi_info_packet.info_packet_hdmi.bits.YQ0_YQ1 = + YYC_QUANTIZATION_LIMITED_RANGE; + } else { + info_frame.avi_info_packet.info_packet_hdmi.bits.Q0_Q1 = + RGB_QUANTIZATION_DEFAULT_RANGE; + info_frame.avi_info_packet.info_packet_hdmi.bits.YQ0_YQ1 = + YYC_QUANTIZATION_LIMITED_RANGE; + } + + info_frame.avi_info_packet.info_packet_hdmi.bits.VIC0_VIC7 = + stream->public.timing.vic; + + /* pixel repetition + * PR0 - PR3 start from 0 whereas pHwPathMode->mode.timing.flags.pixel + * repetition start from 1 */ + info_frame.avi_info_packet.info_packet_hdmi.bits.PR0_PR3 = 0; + + /* Bar Info + * barTop: Line Number of End of Top Bar. + * barBottom: Line Number of Start of Bottom Bar. + * barLeft: Pixel Number of End of Left Bar. + * barRight: Pixel Number of Start of Right Bar. */ + info_frame.avi_info_packet.info_packet_hdmi.bits.bar_top = + stream->public.timing.v_border_top; + info_frame.avi_info_packet.info_packet_hdmi.bits.bar_bottom = + (stream->public.timing.v_border_top + - stream->public.timing.v_border_bottom + 1); + info_frame.avi_info_packet.info_packet_hdmi.bits.bar_left = + stream->public.timing.h_border_left; + info_frame.avi_info_packet.info_packet_hdmi.bits.bar_right = + (stream->public.timing.h_total + - stream->public.timing.h_border_right + 1); + + /* check_sum - Calculate AFMT_AVI_INFO0 ~ AFMT_AVI_INFO3 */ + check_sum = + &info_frame. + avi_info_packet.info_packet_hdmi.packet_raw_data.sb[0]; + *check_sum = INFO_FRAME_AVI + INFO_FRAME_SIZE_AVI + + INFO_FRAME_VERSION_2; + + for (byte_index = 1; byte_index <= INFO_FRAME_SIZE_AVI; byte_index++) + *check_sum += info_frame.avi_info_packet.info_packet_hdmi. + packet_raw_data.sb[byte_index]; + + /* one byte complement */ + *check_sum = (uint8_t) (0x100 - *check_sum); + + /* Store in hw_path_mode */ + info_packet->hb0 = + info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.hb0; + info_packet->hb1 = + info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.hb1; + info_packet->hb2 = + info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.hb2; + + for (byte_index = 0; byte_index < sizeof(info_packet->sb); byte_index++) + info_packet->sb[byte_index] = info_frame.avi_info_packet. + info_packet_hdmi.packet_raw_data.sb[byte_index]; + + info_packet->valid = true; +} + +static void set_vendor_info_packet(struct core_stream *stream, + struct hw_info_packet *info_packet) +{ + uint32_t length = 0; + bool hdmi_vic_mode = false; + uint8_t checksum = 0; + uint32_t i = 0; + enum dc_timing_3d_format format; + + ASSERT_CRITICAL(stream != NULL); + ASSERT_CRITICAL(info_packet != NULL); + + format = stream->public.timing.timing_3d_format; + + /* Can be different depending on packet content */ + length = 5; + + if (stream->public.timing.hdmi_vic != 0 + && stream->public.timing.h_total >= 3840 + && stream->public.timing.v_total >= 2160) + hdmi_vic_mode = true; + + /* According to HDMI 1.4a CTS, VSIF should be sent + * for both 3D stereo and HDMI VIC modes. + * For all other modes, there is no VSIF sent. */ + + if (format == TIMING_3D_FORMAT_NONE && !hdmi_vic_mode) + return; + + /* 24bit IEEE Registration identifier (0x000c03). LSB first. */ + info_packet->sb[1] = 0x03; + info_packet->sb[2] = 0x0C; + info_packet->sb[3] = 0x00; + + /*PB4: 5 lower bytes = 0 (reserved). 3 higher bits = HDMI_Video_Format. + * The value for HDMI_Video_Format are: + * 0x0 (0b000) - No additional HDMI video format is presented in this + * packet + * 0x1 (0b001) - Extended resolution format present. 1 byte of HDMI_VIC + * parameter follows + * 0x2 (0b010) - 3D format indication present. 3D_Structure and + * potentially 3D_Ext_Data follows + * 0x3..0x7 (0b011..0b111) - reserved for future use */ + if (format != TIMING_3D_FORMAT_NONE) + info_packet->sb[4] = (2 << 5); + else if (hdmi_vic_mode) + info_packet->sb[4] = (1 << 5); + + /* PB5: If PB4 claims 3D timing (HDMI_Video_Format = 0x2): + * 4 lower bites = 0 (reserved). 4 higher bits = 3D_Structure. + * The value for 3D_Structure are: + * 0x0 - Frame Packing + * 0x1 - Field Alternative + * 0x2 - Line Alternative + * 0x3 - Side-by-Side (full) + * 0x4 - L + depth + * 0x5 - L + depth + graphics + graphics-depth + * 0x6 - Top-and-Bottom + * 0x7 - Reserved for future use + * 0x8 - Side-by-Side (Half) + * 0x9..0xE - Reserved for future use + * 0xF - Not used */ + switch (format) { + case TIMING_3D_FORMAT_HW_FRAME_PACKING: + case TIMING_3D_FORMAT_SW_FRAME_PACKING: + info_packet->sb[5] = (0x0 << 4); + break; + + case TIMING_3D_FORMAT_SIDE_BY_SIDE: + case TIMING_3D_FORMAT_SBS_SW_PACKED: + info_packet->sb[5] = (0x8 << 4); + length = 6; + break; + + case TIMING_3D_FORMAT_TOP_AND_BOTTOM: + case TIMING_3D_FORMAT_TB_SW_PACKED: + info_packet->sb[5] = (0x6 << 4); + break; + + default: + break; + } + + /*PB5: If PB4 is set to 0x1 (extended resolution format) + * fill PB5 with the correct HDMI VIC code */ + if (hdmi_vic_mode) + info_packet->sb[5] = stream->public.timing.hdmi_vic; + + /* Header */ + info_packet->hb0 = 0x81; /* VSIF packet type. */ + info_packet->hb1 = 0x01; /* Version */ + + /* 4 lower bits = Length, 4 higher bits = 0 (reserved) */ + info_packet->hb2 = (uint8_t) (length); + + /* Calculate checksum */ + checksum = 0; + checksum += info_packet->hb0; + checksum += info_packet->hb1; + checksum += info_packet->hb2; + + for (i = 1; i <= length; i++) + checksum += info_packet->sb[i]; + + info_packet->sb[0] = (uint8_t) (0x100 - checksum); + + info_packet->valid = true; +} + +static void set_spd_info_packet(struct core_stream *stream, + struct hw_info_packet *info_packet) +{ + /* SPD info packet for FreeSync */ + + unsigned char checksum = 0; + unsigned int idx, payload_size = 0; + + /* Check if Freesync is supported. Return if false. If true, + * set the corresponding bit in the info packet + */ + if (stream->public.freesync_ctx.supported == false) + return; + + if (dc_is_hdmi_signal(stream->signal)) { + + /* HEADER */ + + /* HB0 = Packet Type = 0x83 (Source Product + * Descriptor InfoFrame) + */ + info_packet->hb0 = 0x83; + + /* HB1 = Version = 0x01 */ + info_packet->hb1 = 0x01; + + /* HB2 = [Bits 7:5 = 0] [Bits 4:0 = Length = 0x08] */ + info_packet->hb2 = 0x08; + + payload_size = 0x08; + + } else if (dc_is_dp_signal(stream->signal)) { + + /* HEADER */ + + /* HB0 = Secondary-data Packet ID = 0 - Only non-zero + * when used to associate audio related info packets + */ + info_packet->hb0 = 0x00; + + /* HB1 = Packet Type = 0x83 (Source Product + * Descriptor InfoFrame) + */ + info_packet->hb1 = 0x83; + + /* HB2 = [Bits 7:0 = Least significant eight bits - + * For INFOFRAME, the value must be 1Bh] + */ + info_packet->hb2 = 0x1B; + + /* HB3 = [Bits 7:2 = INFOFRAME SDP Version Number = 0x1] + * [Bits 1:0 = Most significant two bits = 0x00] + */ + info_packet->hb3 = 0x04; + + payload_size = 0x1B; + } + + /* PB1 = 0x1A (24bit AMD IEEE OUI (0x00001A) - Byte 0) */ + info_packet->sb[1] = 0x1A; + + /* PB2 = 0x00 (24bit AMD IEEE OUI (0x00001A) - Byte 1) */ + info_packet->sb[2] = 0x00; + + /* PB3 = 0x00 (24bit AMD IEEE OUI (0x00001A) - Byte 2) */ + info_packet->sb[3] = 0x00; + + /* PB4 = Reserved */ + info_packet->sb[4] = 0x00; + + /* PB5 = Reserved */ + info_packet->sb[5] = 0x00; + + /* PB6 = [Bits 7:3 = Reserved] */ + info_packet->sb[6] = 0x00; + + if (stream->public.freesync_ctx.supported == true) + /* PB6 = [Bit 0 = FreeSync Supported] */ + info_packet->sb[6] |= 0x01; + + if (stream->public.freesync_ctx.enabled == true) + /* PB6 = [Bit 1 = FreeSync Enabled] */ + info_packet->sb[6] |= 0x02; + + if (stream->public.freesync_ctx.active == true) + /* PB6 = [Bit 2 = FreeSync Active] */ + info_packet->sb[6] |= 0x04; + + /* PB7 = FreeSync Minimum refresh rate (Hz) */ + info_packet->sb[7] = (unsigned char) (stream->public.freesync_ctx. + min_refresh_in_micro_hz / 1000000); + + /* PB8 = FreeSync Maximum refresh rate (Hz) + * + * Note: We do not use the maximum capable refresh rate + * of the panel, because we should never go above the field + * rate of the mode timing set. + */ + info_packet->sb[8] = (unsigned char) (stream->public.freesync_ctx. + nominal_refresh_in_micro_hz / 1000000); + + /* PB9 - PB27 = Reserved */ + for (idx = 9; idx <= 27; idx++) + info_packet->sb[idx] = 0x00; + + /* Calculate checksum */ + checksum += info_packet->hb0; + checksum += info_packet->hb1; + checksum += info_packet->hb2; + checksum += info_packet->hb3; + + for (idx = 1; idx <= payload_size; idx++) + checksum += info_packet->sb[idx]; + + /* PB0 = Checksum (one byte complement) */ + info_packet->sb[0] = (unsigned char) (0x100 - checksum); + + info_packet->valid = true; +} + +static void set_vsc_info_packet(struct core_stream *stream, + struct hw_info_packet *info_packet) +{ + unsigned int vscPacketRevision = 0; + unsigned int i; + + if (stream->sink->link->public.psr_caps.psr_version != 0) { + vscPacketRevision = 2; + } + + /* VSC packet not needed based on the features + * supported by this DP display + */ + if (vscPacketRevision == 0) + return; + + if (vscPacketRevision == 0x2) { + /* Secondary-data Packet ID = 0*/ + info_packet->hb0 = 0x00; + /* 07h - Packet Type Value indicating Video + * Stream Configuration packet + */ + info_packet->hb1 = 0x07; + /* 02h = VSC SDP supporting 3D stereo and PSR + * (applies to eDP v1.3 or higher). + */ + info_packet->hb2 = 0x02; + /* 08h = VSC packet supporting 3D stereo + PSR + * (HB2 = 02h). + */ + info_packet->hb3 = 0x08; + + for (i = 0; i < 28; i++) + info_packet->sb[i] = 0; + + info_packet->valid = true; + } + + /*TODO: stereo 3D support and extend pixel encoding colorimetry*/ +} + +void resource_validate_ctx_destruct(struct validate_context *context) +{ + int i, j; + + for (i = 0; i < context->target_count; i++) { + for (j = 0; j < context->target_status[i].surface_count; j++) + dc_surface_release( + context->target_status[i].surfaces[j]); + + context->target_status[i].surface_count = 0; + dc_target_release(&context->targets[i]->public); + } +} + +/* + * Copy src_ctx into dst_ctx and retain all surfaces and targets referenced + * by the src_ctx + */ +void resource_validate_ctx_copy_construct( + const struct validate_context *src_ctx, + struct validate_context *dst_ctx) +{ + int i, j; + + *dst_ctx = *src_ctx; + + for (i = 0; i < dst_ctx->res_ctx.pool->pipe_count; i++) { + struct pipe_ctx *cur_pipe = &dst_ctx->res_ctx.pipe_ctx[i]; + + if (cur_pipe->top_pipe) + cur_pipe->top_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->top_pipe->pipe_idx]; + + if (cur_pipe->bottom_pipe) + cur_pipe->bottom_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->bottom_pipe->pipe_idx]; + + } + + for (i = 0; i < dst_ctx->target_count; i++) { + dc_target_retain(&dst_ctx->targets[i]->public); + for (j = 0; j < dst_ctx->target_status[i].surface_count; j++) + dc_surface_retain( + dst_ctx->target_status[i].surfaces[j]); + } +} + +struct clock_source *dc_resource_find_first_free_pll( + struct resource_context *res_ctx) +{ + int i; + + for (i = 0; i < res_ctx->pool->clk_src_count; ++i) { + if (res_ctx->clock_source_ref_count[i] == 0) + return res_ctx->pool->clock_sources[i]; + } + + return NULL; +} + +void resource_build_info_frame(struct pipe_ctx *pipe_ctx) +{ + enum signal_type signal = SIGNAL_TYPE_NONE; + struct hw_info_frame info_frame = { { 0 } }; + + /* default all packets to invalid */ + info_frame.avi_info_packet.valid = false; + info_frame.gamut_packet.valid = false; + info_frame.vendor_info_packet.valid = false; + info_frame.spd_packet.valid = false; + info_frame.vsc_packet.valid = false; + + signal = pipe_ctx->stream->signal; + + /* HDMi and DP have different info packets*/ + if (dc_is_hdmi_signal(signal)) { + set_avi_info_frame( + &info_frame.avi_info_packet, pipe_ctx); + set_vendor_info_packet( + pipe_ctx->stream, &info_frame.vendor_info_packet); + set_spd_info_packet(pipe_ctx->stream, &info_frame.spd_packet); + } + + else if (dc_is_dp_signal(signal)) + set_vsc_info_packet(pipe_ctx->stream, &info_frame.vsc_packet); + set_spd_info_packet(pipe_ctx->stream, &info_frame.spd_packet); + + translate_info_frame(&info_frame, + &pipe_ctx->encoder_info_frame); +} + +enum dc_status resource_map_clock_resources( + const struct core_dc *dc, + struct validate_context *context) +{ + int i, j, k; + + /* acquire new resources */ + for (i = 0; i < context->target_count; i++) { + struct core_target *target = context->targets[i]; + + for (j = 0; j < target->public.stream_count; j++) { + struct core_stream *stream = + DC_STREAM_TO_CORE(target->public.streams[j]); + + if (resource_is_stream_unchanged(dc->current_context, stream)) + continue; + + for (k = 0; k < MAX_PIPES; k++) { + struct pipe_ctx *pipe_ctx = + &context->res_ctx.pipe_ctx[k]; + + if (context->res_ctx.pipe_ctx[k].stream != stream) + continue; + + if (dc_is_dp_signal(pipe_ctx->stream->signal) + || pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL) + pipe_ctx->clock_source = + context->res_ctx.pool->dp_clock_source; + else { + pipe_ctx->clock_source = NULL; + + if (!dc->public.config.disable_disp_pll_sharing) + resource_find_used_clk_src_for_sharing( + &context->res_ctx, + pipe_ctx); + + if (pipe_ctx->clock_source == NULL) + pipe_ctx->clock_source = + dc_resource_find_first_free_pll(&context->res_ctx); + } + + if (pipe_ctx->clock_source == NULL) + return DC_NO_CLOCK_SOURCE_RESOURCE; + + resource_reference_clock_source( + &context->res_ctx, + pipe_ctx->clock_source); + + /* only one cs per stream regardless of mpo */ + break; + } + } + } + + return DC_OK; +} + +/* + * Note: We need to disable output if clock sources change, + * since bios does optimization and doesn't apply if changing + * PHY when not already disabled. + */ +bool pipe_need_reprogram( + struct pipe_ctx *pipe_ctx_old, + struct pipe_ctx *pipe_ctx) +{ + if (pipe_ctx_old->stream->sink != pipe_ctx->stream->sink) + return true; + + if (pipe_ctx_old->stream->signal != pipe_ctx->stream->signal) + return true; + + if (pipe_ctx_old->audio != pipe_ctx->audio) + return true; + + if (pipe_ctx_old->clock_source != pipe_ctx->clock_source + && pipe_ctx_old->stream != pipe_ctx->stream) + return true; + + if (pipe_ctx_old->stream_enc != pipe_ctx->stream_enc) + return true; + + if (is_timing_changed(pipe_ctx_old->stream, pipe_ctx->stream)) + return true; + + + return false; +} diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_sink.c b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c new file mode 100644 index 000000000000..67ae799b6f4f --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c @@ -0,0 +1,113 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "dm_helpers.h" +#include "core_types.h" + +/******************************************************************************* + * Private definitions + ******************************************************************************/ + +struct sink { + struct core_sink protected; + int ref_count; +}; + +#define DC_SINK_TO_SINK(dc_sink) \ + container_of(dc_sink, struct sink, protected.public) + +/******************************************************************************* + * Private functions + ******************************************************************************/ + +static void destruct(struct sink *sink) +{ + +} + +static bool construct(struct sink *sink, const struct dc_sink_init_data *init_params) +{ + + struct core_link *core_link = DC_LINK_TO_LINK(init_params->link); + + sink->protected.public.sink_signal = init_params->sink_signal; + sink->protected.link = core_link; + sink->protected.ctx = core_link->ctx; + sink->protected.dongle_max_pix_clk = init_params->dongle_max_pix_clk; + sink->protected.converter_disable_audio = + init_params->converter_disable_audio; + + return true; +} + +/******************************************************************************* + * Public functions + ******************************************************************************/ + +void dc_sink_retain(const struct dc_sink *dc_sink) +{ + struct sink *sink = DC_SINK_TO_SINK(dc_sink); + + ++sink->ref_count; +} + +void dc_sink_release(const struct dc_sink *dc_sink) +{ + struct sink *sink = DC_SINK_TO_SINK(dc_sink); + + --sink->ref_count; + + if (sink->ref_count == 0) { + destruct(sink); + dm_free(sink); + } +} + +struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params) +{ + struct sink *sink = dm_alloc(sizeof(*sink)); + + if (NULL == sink) + goto alloc_fail; + + if (false == construct(sink, init_params)) + goto construct_fail; + + /* TODO should we move this outside to where the assignment actually happens? */ + dc_sink_retain(&sink->protected.public); + + return &sink->protected.public; + +construct_fail: + dm_free(sink); + +alloc_fail: + return NULL; +} + +/******************************************************************************* + * Protected functions - visible only inside of DC (not visible in DM) + ******************************************************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c new file mode 100644 index 000000000000..8d6aa607e1f5 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -0,0 +1,141 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "dc.h" +#include "core_types.h" +#include "resource.h" + +/******************************************************************************* + * Private definitions + ******************************************************************************/ + +struct stream { + struct core_stream protected; + int ref_count; +}; + +#define DC_STREAM_TO_STREAM(dc_stream) container_of(dc_stream, struct stream, protected.public) + +/******************************************************************************* + * Private functions + ******************************************************************************/ + +static bool construct(struct core_stream *stream, + const struct dc_sink *dc_sink_data) +{ + uint32_t i = 0; + + stream->sink = DC_SINK_TO_CORE(dc_sink_data); + stream->ctx = stream->sink->ctx; + stream->public.sink = dc_sink_data; + + dc_sink_retain(dc_sink_data); + + /* Copy audio modes */ + /* TODO - Remove this translation */ + for (i = 0; i < (dc_sink_data->edid_caps.audio_mode_count); i++) + { + stream->public.audio_info.modes[i].channel_count = dc_sink_data->edid_caps.audio_modes[i].channel_count; + stream->public.audio_info.modes[i].format_code = dc_sink_data->edid_caps.audio_modes[i].format_code; + stream->public.audio_info.modes[i].sample_rates.all = dc_sink_data->edid_caps.audio_modes[i].sample_rate; + stream->public.audio_info.modes[i].sample_size = dc_sink_data->edid_caps.audio_modes[i].sample_size; + } + stream->public.audio_info.mode_count = dc_sink_data->edid_caps.audio_mode_count; + stream->public.audio_info.audio_latency = dc_sink_data->edid_caps.audio_latency; + stream->public.audio_info.video_latency = dc_sink_data->edid_caps.video_latency; + memmove( + stream->public.audio_info.display_name, + dc_sink_data->edid_caps.display_name, + AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS); + stream->public.audio_info.manufacture_id = dc_sink_data->edid_caps.manufacturer_id; + stream->public.audio_info.product_id = dc_sink_data->edid_caps.product_id; + stream->public.audio_info.flags.all = dc_sink_data->edid_caps.speaker_flags; + + /* TODO - Unhardcode port_id */ + stream->public.audio_info.port_id[0] = 0x5558859e; + stream->public.audio_info.port_id[1] = 0xd989449; + + /* EDID CAP translation for HDMI 2.0 */ + stream->public.timing.flags.LTE_340MCSC_SCRAMBLE = dc_sink_data->edid_caps.lte_340mcsc_scramble; + + stream->status.link = &stream->sink->link->public; + + return true; +} + +static void destruct(struct core_stream *stream) +{ + dc_sink_release(&stream->sink->public); +} + +void dc_stream_retain(const struct dc_stream *dc_stream) +{ + struct stream *stream = DC_STREAM_TO_STREAM(dc_stream); + stream->ref_count++; +} + +void dc_stream_release(const struct dc_stream *public) +{ + struct stream *stream = DC_STREAM_TO_STREAM(public); + struct core_stream *protected = DC_STREAM_TO_CORE(public); + + if (public != NULL) { + stream->ref_count--; + + if (stream->ref_count == 0) { + destruct(protected); + dm_free(stream); + } + } +} + +struct dc_stream *dc_create_stream_for_sink( + const struct dc_sink *dc_sink) +{ + struct core_sink *sink = DC_SINK_TO_CORE(dc_sink); + struct stream *stream; + + if (sink == NULL) + goto alloc_fail; + + stream = dm_alloc(sizeof(struct stream)); + + if (NULL == stream) + goto alloc_fail; + + if (false == construct(&stream->protected, dc_sink)) + goto construct_fail; + + dc_stream_retain(&stream->protected.public); + + return &stream->protected.public; + +construct_fail: + dm_free(stream); + +alloc_fail: + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c new file mode 100644 index 000000000000..b89d3b5d0ba0 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -0,0 +1,213 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +/* DC interface (public) */ +#include "dm_services.h" +#include "dc.h" + +/* DC core (private) */ +#include "core_dc.h" +#include "transform.h" + +/******************************************************************************* + * Private structures + ******************************************************************************/ +struct surface { + struct core_surface protected; + enum dc_irq_source irq_source; + int ref_count; +}; + +struct gamma { + struct core_gamma protected; + int ref_count; +}; + +#define DC_SURFACE_TO_SURFACE(dc_surface) container_of(dc_surface, struct surface, protected.public) +#define CORE_SURFACE_TO_SURFACE(core_surface) container_of(core_surface, struct surface, protected) + +#define DC_GAMMA_TO_GAMMA(dc_gamma) \ + container_of(dc_gamma, struct gamma, protected.public) +#define CORE_GAMMA_TO_GAMMA(core_gamma) \ + container_of(core_gamma, struct gamma, protected) + +/******************************************************************************* + * Private functions + ******************************************************************************/ +static bool construct(struct dc_context *ctx, struct surface *surface) +{ + surface->protected.ctx = ctx; + return true; +} + +static void destruct(struct surface *surface) +{ + +} + +/******************************************************************************* + * Public functions + ******************************************************************************/ +void enable_surface_flip_reporting(struct dc_surface *dc_surface, + uint32_t controller_id) +{ + struct surface *surface = DC_SURFACE_TO_SURFACE(dc_surface); + surface->irq_source = controller_id + DC_IRQ_SOURCE_PFLIP1 - 1; + /*register_flip_interrupt(surface);*/ +} + +struct dc_surface *dc_create_surface(const struct dc *dc) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + + struct surface *surface = dm_alloc(sizeof(*surface)); + + if (NULL == surface) + goto alloc_fail; + + if (false == construct(core_dc->ctx, surface)) + goto construct_fail; + + dc_surface_retain(&surface->protected.public); + + return &surface->protected.public; + +construct_fail: + dm_free(surface); + +alloc_fail: + return NULL; +} + +const struct dc_surface_status *dc_surface_get_status( + const struct dc_surface *dc_surface) +{ + struct dc_surface_status *surface_status; + struct core_surface *core_surface; + struct core_dc *core_dc; + int i; + + if (dc_surface == NULL) + return NULL; + + core_surface = DC_SURFACE_TO_CORE(dc_surface); + + if (core_surface == NULL || core_surface->ctx == NULL) + return NULL; + + surface_status = &core_surface->status; + + if (core_surface->ctx == NULL || core_surface->ctx->dc == NULL) + return NULL; + + core_dc = DC_TO_CORE(core_surface->ctx->dc); + + + if (core_dc->current_context == NULL) + return NULL; + + for (i = 0; i < core_dc->current_context->res_ctx.pool->pipe_count; + i++) { + struct pipe_ctx *pipe_ctx = + &core_dc->current_context->res_ctx.pipe_ctx[i]; + + if (pipe_ctx->surface != + DC_SURFACE_TO_CORE(dc_surface)) + continue; + + core_dc->hwss.update_pending_status(pipe_ctx); + } + + return surface_status; +} + +void dc_surface_retain(const struct dc_surface *dc_surface) +{ + struct surface *surface = DC_SURFACE_TO_SURFACE(dc_surface); + + ++surface->ref_count; +} + +void dc_surface_release(const struct dc_surface *dc_surface) +{ + struct surface *surface = DC_SURFACE_TO_SURFACE(dc_surface); + + --surface->ref_count; + + if (surface->ref_count == 0) { + destruct(surface); + dm_free(surface); + } +} + +static bool construct_gamma(struct gamma *gamma) +{ + return true; +} + +static void destruct_gamma(struct gamma *gamma) +{ + +} + +void dc_gamma_retain(const struct dc_gamma *dc_gamma) +{ + struct gamma *gamma = DC_GAMMA_TO_GAMMA(dc_gamma); + + ++gamma->ref_count; +} + +void dc_gamma_release(const struct dc_gamma *dc_gamma) +{ + struct gamma *gamma = DC_GAMMA_TO_GAMMA(dc_gamma); + --gamma->ref_count; + + if (gamma->ref_count == 0) { + destruct_gamma(gamma); + dm_free(gamma); + } +} + +struct dc_gamma *dc_create_gamma() +{ + struct gamma *gamma = dm_alloc(sizeof(*gamma)); + + if (gamma == NULL) + goto alloc_fail; + + if (false == construct_gamma(gamma)) + goto construct_fail; + + dc_gamma_retain(&gamma->protected.public); + + return &gamma->protected.public; + +construct_fail: + dm_free(gamma); + +alloc_fail: + return NULL; +} + diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_target.c b/drivers/gpu/drm/amd/display/dc/core/dc_target.c new file mode 100644 index 000000000000..48eb7b0e0350 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/core/dc_target.c @@ -0,0 +1,334 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "core_types.h" +#include "hw_sequencer.h" +#include "resource.h" +#include "ipp.h" +#include "timing_generator.h" + +struct target { + struct core_target protected; + int ref_count; +}; + +#define DC_TARGET_TO_TARGET(dc_target) \ + container_of(dc_target, struct target, protected.public) +#define CORE_TARGET_TO_TARGET(core_target) \ + container_of(core_target, struct target, protected) + +static void construct( + struct core_target *target, + struct dc_context *ctx, + struct dc_stream *dc_streams[], + uint8_t stream_count) +{ + uint8_t i; + for (i = 0; i < stream_count; i++) { + target->public.streams[i] = dc_streams[i]; + dc_stream_retain(dc_streams[i]); + } + + target->ctx = ctx; + target->public.stream_count = stream_count; +} + +static void destruct(struct core_target *core_target) +{ + int i; + + for (i = 0; i < core_target->public.stream_count; i++) { + dc_stream_release( + (struct dc_stream *)core_target->public.streams[i]); + core_target->public.streams[i] = NULL; + } +} + +void dc_target_retain(const struct dc_target *dc_target) +{ + struct target *target = DC_TARGET_TO_TARGET(dc_target); + + target->ref_count++; +} + +void dc_target_release(const struct dc_target *dc_target) +{ + struct target *target = DC_TARGET_TO_TARGET(dc_target); + struct core_target *protected = DC_TARGET_TO_CORE(dc_target); + + ASSERT(target->ref_count > 0); + target->ref_count--; + if (target->ref_count == 0) { + destruct(protected); + dm_free(target); + } +} + +const struct dc_target_status *dc_target_get_status( + const struct dc_target* dc_target) +{ + uint8_t i; + struct core_target* target = DC_TARGET_TO_CORE(dc_target); + struct core_dc *dc = DC_TO_CORE(target->ctx->dc); + + for (i = 0; i < dc->current_context->target_count; i++) + if (target == dc->current_context->targets[i]) + return &dc->current_context->target_status[i]; + + return NULL; +} + +struct dc_target *dc_create_target_for_streams( + struct dc_stream *dc_streams[], + uint8_t stream_count) +{ + struct core_stream *stream; + struct target *target; + + if (0 == stream_count) + goto target_alloc_fail; + + stream = DC_STREAM_TO_CORE(dc_streams[0]); + + target = dm_alloc(sizeof(struct target)); + + if (NULL == target) + goto target_alloc_fail; + + construct(&target->protected, stream->ctx, dc_streams, stream_count); + + dc_target_retain(&target->protected.public); + + return &target->protected.public; + +target_alloc_fail: + return NULL; +} + +bool dc_target_is_connected_to_sink( + const struct dc_target * dc_target, + const struct dc_sink *dc_sink) +{ + struct core_target *target = DC_TARGET_TO_CORE(dc_target); + uint8_t i; + for (i = 0; i < target->public.stream_count; i++) { + if (target->public.streams[i]->sink == dc_sink) + return true; + } + return false; +} + +/** + * Update the cursor attributes and set cursor surface address + */ +bool dc_target_set_cursor_attributes( + struct dc_target *dc_target, + const struct dc_cursor_attributes *attributes) +{ + uint8_t i, j; + struct core_target *target; + struct core_dc *core_dc; + struct resource_context *res_ctx; + + if (NULL == dc_target) { + dm_error("DC: dc_target is NULL!\n"); + return false; + + } + if (NULL == attributes) { + dm_error("DC: attributes is NULL!\n"); + return false; + + } + + target = DC_TARGET_TO_CORE(dc_target); + core_dc = DC_TO_CORE(target->ctx->dc); + res_ctx = &core_dc->current_context->res_ctx; + + for (i = 0; i < target->public.stream_count; i++) { + for (j = 0; j < MAX_PIPES; j++) { + struct input_pixel_processor *ipp = + res_ctx->pipe_ctx[j].ipp; + + if (res_ctx->pipe_ctx[j].stream != + DC_STREAM_TO_CORE(target->public.streams[i])) + continue; + + /* As of writing of this code cursor is on the top + * plane so we only need to set it on first pipe we + * find. May need to make this code dce specific later. + */ + if (ipp->funcs->ipp_cursor_set_attributes( + ipp, attributes)) + return true; + } + } + + return false; +} + +bool dc_target_set_cursor_position( + struct dc_target *dc_target, + const struct dc_cursor_position *position) +{ + uint8_t i, j; + struct core_target *target; + struct core_dc *core_dc; + struct resource_context *res_ctx; + + if (NULL == dc_target) { + dm_error("DC: dc_target is NULL!\n"); + return false; + } + + if (NULL == position) { + dm_error("DC: cursor position is NULL!\n"); + return false; + } + + target = DC_TARGET_TO_CORE(dc_target); + core_dc = DC_TO_CORE(target->ctx->dc); + res_ctx = &core_dc->current_context->res_ctx; + + for (i = 0; i < target->public.stream_count; i++) { + for (j = 0; j < MAX_PIPES; j++) { + struct input_pixel_processor *ipp = + res_ctx->pipe_ctx[j].ipp; + + if (res_ctx->pipe_ctx[j].stream != + DC_STREAM_TO_CORE(target->public.streams[i])) + continue; + + /* As of writing of this code cursor is on the top + * plane so we only need to set it on first pipe we + * find. May need to make this code dce specific later. + */ + ipp->funcs->ipp_cursor_set_position(ipp, position); + return true; + } + } + + return false; +} + +uint32_t dc_target_get_vblank_counter(const struct dc_target *dc_target) +{ + uint8_t i, j; + struct core_target *target = DC_TARGET_TO_CORE(dc_target); + struct core_dc *core_dc = DC_TO_CORE(target->ctx->dc); + struct resource_context *res_ctx = + &core_dc->current_context->res_ctx; + + for (i = 0; i < target->public.stream_count; i++) { + for (j = 0; j < MAX_PIPES; j++) { + struct timing_generator *tg = res_ctx->pipe_ctx[j].tg; + + if (res_ctx->pipe_ctx[j].stream != + DC_STREAM_TO_CORE(target->public.streams[i])) + continue; + + return tg->funcs->get_frame_count(tg); + } + } + + return 0; +} + +uint32_t dc_target_get_scanoutpos( + const struct dc_target *dc_target, + uint32_t *vbl, + uint32_t *position) +{ + uint8_t i, j; + struct core_target *target = DC_TARGET_TO_CORE(dc_target); + struct core_dc *core_dc = DC_TO_CORE(target->ctx->dc); + struct resource_context *res_ctx = + &core_dc->current_context->res_ctx; + + for (i = 0; i < target->public.stream_count; i++) { + for (j = 0; j < MAX_PIPES; j++) { + struct timing_generator *tg = res_ctx->pipe_ctx[j].tg; + + if (res_ctx->pipe_ctx[j].stream != + DC_STREAM_TO_CORE(target->public.streams[i])) + continue; + + return tg->funcs->get_scanoutpos(tg, vbl, position); + } + } + + return 0; +} + +void dc_target_log( + const struct dc_target *dc_target, + struct dal_logger *dm_logger, + enum dc_log_type log_type) +{ + int i; + + const struct core_target *core_target = + CONST_DC_TARGET_TO_CORE(dc_target); + + dm_logger_write(dm_logger, + log_type, + "core_target 0x%x: stream_count=%d\n", + core_target, + core_target->public.stream_count); + + for (i = 0; i < core_target->public.stream_count; i++) { + const struct core_stream *core_stream = + DC_STREAM_TO_CORE(core_target->public.streams[i]); + + dm_logger_write(dm_logger, + log_type, + "core_stream 0x%x: src: %d, %d, %d, %d; dst: %d, %d, %d, %d;\n", + core_stream, + core_stream->public.src.x, + core_stream->public.src.y, + core_stream->public.src.width, + core_stream->public.src.height, + core_stream->public.dst.x, + core_stream->public.dst.y, + core_stream->public.dst.width, + core_stream->public.dst.height); + dm_logger_write(dm_logger, + log_type, + "\tpix_clk_khz: %d, h_total: %d, v_total: %d\n", + core_stream->public.timing.pix_clk_khz, + core_stream->public.timing.h_total, + core_stream->public.timing.v_total); + dm_logger_write(dm_logger, + log_type, + "\tsink name: %s, serial: %d\n", + core_stream->sink->public.edid_caps.display_name, + core_stream->sink->public.edid_caps.serial_number); + dm_logger_write(dm_logger, + log_type, + "\tlink: %d\n", + core_stream->sink->link->public.link_index); + } +} diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h new file mode 100644 index 000000000000..5575484323b3 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -0,0 +1,780 @@ +/* + * Copyright 2012-14 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef DC_INTERFACE_H_ +#define DC_INTERFACE_H_ + +#include "dc_types.h" +#include "dpcd_defs.h" +#include "grph_object_defs.h" +#include "logger_types.h" +#include "gpio_types.h" +#include "link_service_types.h" + +#define MAX_TARGETS 6 +#define MAX_SURFACES 6 +#define MAX_SINKS_PER_LINK 4 + +/******************************************************************************* + * Display Core Interfaces + ******************************************************************************/ + +struct dc_caps { + uint32_t max_targets; + uint32_t max_links; + uint32_t max_audios; + uint32_t max_slave_planes; + uint32_t max_downscale_ratio; + uint32_t i2c_speed_in_khz; +}; + + +struct dc_dcc_surface_param { + enum surface_pixel_format format; + struct dc_size surface_size; + enum dc_scan_direction scan; +}; + +struct dc_dcc_setting { + unsigned int max_compressed_blk_size; + unsigned int max_uncompressed_blk_size; + bool independent_64b_blks; +}; + +struct dc_surface_dcc_cap { + bool capable; + bool const_color_support; + + union { + struct { + struct dc_dcc_setting rgb; + } grph; + + struct { + struct dc_dcc_setting luma; + struct dc_dcc_setting chroma; + } video; + }; +}; + +/* Forward declaration*/ +struct dc; +struct dc_surface; +struct validate_context; + +struct dc_cap_funcs { + int i; +}; + +struct dc_stream_funcs { + bool (*adjust_vmin_vmax)(struct dc *dc, + const struct dc_stream **stream, + int num_streams, + int vmin, + int vmax); + + void (*stream_update_scaling)(const struct dc *dc, + const struct dc_stream *dc_stream, + const struct rect *src, + const struct rect *dst); + bool (*set_gamut_remap)(struct dc *dc, + const struct dc_stream **stream, int num_streams); + bool (*set_backlight)(struct dc *dc, unsigned int backlight_level, + unsigned int frame_ramp, const struct dc_stream *stream); + bool (*init_dmcu_backlight_settings)(struct dc *dc); + bool (*set_abm_level)(struct dc *dc, unsigned int abm_level); + bool (*set_psr_enable)(struct dc *dc, bool enable); + bool (*setup_psr)(struct dc *dc, const struct dc_stream *stream); +}; + +struct link_training_settings; + +struct dc_link_funcs { + void (*set_drive_settings)(struct dc *dc, + struct link_training_settings *lt_settings); + void (*perform_link_training)(struct dc *dc, + struct dc_link_settings *link_setting, + bool skip_video_pattern); + void (*set_preferred_link_settings)(struct dc *dc, + struct dc_link_settings *link_setting); + void (*enable_hpd)(const struct dc_link *link); + void (*disable_hpd)(const struct dc_link *link); + void (*set_test_pattern)( + const struct dc_link *link, + enum dp_test_pattern test_pattern, + const struct link_training_settings *p_link_settings, + const unsigned char *p_custom_pattern, + unsigned int cust_pattern_size); +}; + +/* Structure to hold configuration flags set by dm at dc creation. */ +struct dc_config { + bool gpu_vm_support; + bool disable_disp_pll_sharing; +}; + +struct dc_debug { + bool surface_visual_confirm; + bool max_disp_clk; + bool target_trace; + bool surface_trace; + bool validation_trace; + bool disable_stutter; + bool disable_dcc; + bool disable_dfs_bypass; + bool disable_power_gate; + bool disable_clock_gate; +}; + +struct dc { + struct dc_caps caps; + struct dc_cap_funcs cap_funcs; + struct dc_stream_funcs stream_funcs; + struct dc_link_funcs link_funcs; + struct dc_config config; + struct dc_debug debug; +}; + +enum frame_buffer_mode { + FRAME_BUFFER_MODE_LOCAL_ONLY = 0, + FRAME_BUFFER_MODE_ZFB_ONLY, + FRAME_BUFFER_MODE_MIXED_ZFB_AND_LOCAL, +} ; + +struct dchub_init_data { + bool dchub_initialzied; + bool dchub_info_valid; + int64_t zfb_phys_addr_base; + int64_t zfb_mc_base_addr; + uint64_t zfb_size_in_byte; + enum frame_buffer_mode fb_mode; +}; + +struct dc_init_data { + struct hw_asic_id asic_id; + void *driver; /* ctx */ + struct cgs_device *cgs_device; + + int num_virtual_links; + /* + * If 'vbios_override' not NULL, it will be called instead + * of the real VBIOS. Intended use is Diagnostics on FPGA. + */ + struct dc_bios *vbios_override; + enum dce_environment dce_environment; + + struct dc_config flags; +}; + +struct dc *dc_create(const struct dc_init_data *init_params); + +void dc_destroy(struct dc **dc); + +bool dc_init_dchub(struct dc *dc, struct dchub_init_data *dh_data); + +/******************************************************************************* + * Surface Interfaces + ******************************************************************************/ + +enum { + RGB_256X3X16 = 256, + FLOAT_GAMMA_RAMP_MAX = 1025 +}; + +enum dc_gamma_ramp_type { + GAMMA_RAMP_RBG256X3X16, + GAMMA_RAMP_FLOAT, +}; + +struct float_rgb { + struct fixed32_32 red; + struct fixed32_32 green; + struct fixed32_32 blue; +}; + +struct dc_gamma_ramp_float { + struct float_rgb scale; + struct float_rgb offset; + struct float_rgb gamma_curve[FLOAT_GAMMA_RAMP_MAX]; +}; + +struct dc_gamma_ramp_rgb256x3x16 { + uint16_t red[RGB_256X3X16]; + uint16_t green[RGB_256X3X16]; + uint16_t blue[RGB_256X3X16]; +}; + +struct dc_gamma { + enum dc_gamma_ramp_type type; + union { + struct dc_gamma_ramp_rgb256x3x16 gamma_ramp_rgb256x3x16; + struct dc_gamma_ramp_float gamma_ramp_float; + }; + uint32_t size; +}; + +struct dc_surface { + bool visible; + bool flip_immediate; + struct dc_plane_address address; + + struct scaling_taps scaling_quality; + struct rect src_rect; + struct rect dst_rect; + struct rect clip_rect; + + union plane_size plane_size; + union dc_tiling_info tiling_info; + struct dc_plane_dcc_param dcc; + enum dc_color_space color_space; + + enum surface_pixel_format format; + enum dc_rotation_angle rotation; + bool horizontal_mirror; + enum plane_stereo_format stereo_format; + + const struct dc_gamma *gamma_correction; +}; + +struct dc_plane_info { + union plane_size plane_size; + union dc_tiling_info tiling_info; + enum surface_pixel_format format; + enum dc_rotation_angle rotation; + bool horizontal_mirror; + enum plane_stereo_format stereo_format; + enum dc_color_space color_space; /*todo: wrong place, fits in scaling info*/ + bool visible; +}; + +struct dc_scaling_info { + struct rect src_rect; + struct rect dst_rect; + struct rect clip_rect; + struct scaling_taps scaling_quality; +}; + +struct dc_surface_update { + const struct dc_surface *surface; + + /* isr safe update parameters. null means no updates */ + struct dc_flip_addrs *flip_addr; + struct dc_plane_info *plane_info; + struct dc_scaling_info *scaling_info; + /* following updates require alloc/sleep/spin that is not isr safe, + * null means no updates + */ + struct dc_gamma *gamma; + + +}; +/* + * This structure is filled in by dc_surface_get_status and contains + * the last requested address and the currently active address so the called + * can determine if there are any outstanding flips + */ +struct dc_surface_status { + struct dc_plane_address requested_address; + struct dc_plane_address current_address; + bool is_flip_pending; +}; + +/* + * Create a new surface with default parameters; + */ +struct dc_surface *dc_create_surface(const struct dc *dc); +const struct dc_surface_status *dc_surface_get_status( + const struct dc_surface *dc_surface); + +void dc_surface_retain(const struct dc_surface *dc_surface); +void dc_surface_release(const struct dc_surface *dc_surface); + +void dc_gamma_release(const struct dc_gamma *dc_gamma); +struct dc_gamma *dc_create_gamma(void); + +/* + * This structure holds a surface address. There could be multiple addresses + * in cases such as Stereo 3D, Planar YUV, etc. Other per-flip attributes such + * as frame durations and DCC format can also be set. + */ +struct dc_flip_addrs { + struct dc_plane_address address; + bool flip_immediate; + /* TODO: DCC format info */ + /* TODO: add flip duration for FreeSync */ +}; + +/* + * Optimized flip address update function. + * + * After this call: + * Surface addresses and flip attributes are programmed. + * Surface flip occur at next configured time (h_sync or v_sync flip) + */ +void dc_flip_surface_addrs(struct dc *dc, + const struct dc_surface *const surfaces[], + struct dc_flip_addrs flip_addrs[], + uint32_t count); + +/* + * Set up surface attributes and associate to a target + * The surfaces parameter is an absolute set of all surface active for the target. + * If no surfaces are provided, the target will be blanked; no memory read. + * Any flip related attribute changes must be done through this interface. + * + * After this call: + * Surfaces attributes are programmed and configured to be composed into target. + * This does not trigger a flip. No surface address is programmed. + */ + +bool dc_commit_surfaces_to_target( + struct dc *dc, + const struct dc_surface **dc_surfaces, + uint8_t surface_count, + struct dc_target *dc_target); + +bool dc_pre_update_surfaces_to_target( + struct dc *dc, + const struct dc_surface *const *new_surfaces, + uint8_t new_surface_count, + struct dc_target *dc_target); + +bool dc_post_update_surfaces_to_target( + struct dc *dc); + +void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *updates, + int surface_count, struct dc_target *dc_target); + +/******************************************************************************* + * Target Interfaces + ******************************************************************************/ +#define MAX_STREAM_NUM 1 + +struct dc_target { + uint8_t stream_count; + const struct dc_stream *streams[MAX_STREAM_NUM]; +}; + +/* + * Target status is returned from dc_target_get_status in order to get the + * the IRQ source, current frame counter and currently attached surfaces. + */ +struct dc_target_status { + int primary_otg_inst; + int cur_frame_count; + int surface_count; + const struct dc_surface *surfaces[MAX_SURFACE_NUM]; +}; + +struct dc_target *dc_create_target_for_streams( + struct dc_stream *dc_streams[], + uint8_t stream_count); + +/* + * Get the current target status. + */ +const struct dc_target_status *dc_target_get_status( + const struct dc_target* dc_target); + +void dc_target_retain(const struct dc_target *dc_target); +void dc_target_release(const struct dc_target *dc_target); +void dc_target_log( + const struct dc_target *dc_target, + struct dal_logger *dc_logger, + enum dc_log_type log_type); + +uint8_t dc_get_current_target_count(const struct dc *dc); +struct dc_target *dc_get_target_at_index(const struct dc *dc, uint8_t i); + +bool dc_target_is_connected_to_sink( + const struct dc_target *dc_target, + const struct dc_sink *dc_sink); + +uint32_t dc_target_get_vblank_counter(const struct dc_target *dc_target); + +/* TODO: Return parsed values rather than direct register read + * This has a dependency on the caller (amdgpu_get_crtc_scanoutpos) + * being refactored properly to be dce-specific + */ +uint32_t dc_target_get_scanoutpos( + const struct dc_target *dc_target, + uint32_t *vbl, + uint32_t *position); + +/* + * Structure to store surface/target associations for validation + */ +struct dc_validation_set { + const struct dc_target *target; + const struct dc_surface *surfaces[MAX_SURFACES]; + uint8_t surface_count; +}; + +/* + * This function takes a set of resources and checks that they are cofunctional. + * + * After this call: + * No hardware is programmed for call. Only validation is done. + */ +bool dc_validate_resources( + const struct dc *dc, + const struct dc_validation_set set[], + uint8_t set_count); + +/* + * This function takes a target and checks if it is guaranteed to be supported. + * Guaranteed means that MAX_COFUNC*target is supported. + * + * After this call: + * No hardware is programmed for call. Only validation is done. + */ + +bool dc_validate_guaranteed( + const struct dc *dc, + const struct dc_target *dc_target); + +/* + * Set up streams and links associated to targets to drive sinks + * The targets parameter is an absolute set of all active targets. + * + * After this call: + * Phy, Encoder, Timing Generator are programmed and enabled. + * New targets are enabled with blank stream; no memory read. + */ +bool dc_commit_targets( + struct dc *dc, + struct dc_target *targets[], + uint8_t target_count); + +/******************************************************************************* + * Stream Interfaces + ******************************************************************************/ +struct dc_stream { + const struct dc_sink *sink; + struct dc_crtc_timing timing; + + enum dc_color_space output_color_space; + + struct rect src; /* viewport in target space*/ + struct rect dst; /* stream addressable area */ + + struct audio_info audio_info; + + bool ignore_msa_timing_param; + + struct freesync_context freesync_ctx; + + /* TODO: dithering */ + /* TODO: transfer function (CSC/regamma/gamut remap) */ + struct colorspace_transform gamut_remap_matrix; + struct csc_transform csc_color_matrix; + /* TODO: custom INFO packets */ + /* TODO: ABM info (DMCU) */ + /* TODO: PSR info */ + /* TODO: CEA VIC */ +}; + +/** + * Create a new default stream for the requested sink + */ +struct dc_stream *dc_create_stream_for_sink(const struct dc_sink *dc_sink); + +void dc_stream_retain(const struct dc_stream *dc_stream); +void dc_stream_release(const struct dc_stream *dc_stream); + +struct dc_stream_status { + /* + * link this stream passes through + */ + const struct dc_link *link; +}; + +const struct dc_stream_status *dc_stream_get_status( + const struct dc_stream *dc_stream); + +/******************************************************************************* + * Link Interfaces + ******************************************************************************/ + +/* + * A link contains one or more sinks and their connected status. + * The currently active signal type (HDMI, DP-SST, DP-MST) is also reported. + */ +struct dc_link { + const struct dc_sink *remote_sinks[MAX_SINKS_PER_LINK]; + unsigned int sink_count; + const struct dc_sink *local_sink; + unsigned int link_index; + enum dc_connection_type type; + enum signal_type connector_signal; + enum dc_irq_source irq_source_hpd; + enum dc_irq_source irq_source_hpd_rx;/* aka DP Short Pulse */ + /* caps is the same as reported_link_cap. link_traing use + * reported_link_cap. Will clean up. TODO + */ + struct dc_link_settings reported_link_cap; + struct dc_link_settings verified_link_cap; + struct dc_link_settings max_link_setting; + struct dc_link_settings cur_link_settings; + struct dc_lane_settings cur_lane_setting; + + uint8_t ddc_hw_inst; + uint8_t link_enc_hw_inst; + + struct psr_caps psr_caps; + bool test_pattern_enabled; + union compliance_test_state compliance_test_state; +}; + +struct dpcd_caps { + union dpcd_rev dpcd_rev; + union max_lane_count max_ln_count; + union max_down_spread max_down_spread; + + /* dongle type (DP converter, CV smart dongle) */ + enum display_dongle_type dongle_type; + /* Dongle's downstream count. */ + union sink_count sink_count; + /* If dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER, + indicates 'Frame Sequential-to-lllFrame Pack' conversion capability.*/ + bool is_dp_hdmi_s3d_converter; + + bool allow_invalid_MSA_timing_param; + bool panel_mode_edp; + uint32_t sink_dev_id; + uint32_t branch_dev_id; + int8_t branch_dev_name[6]; + int8_t branch_hw_revision; +}; + +struct dc_link_status { + struct dpcd_caps *dpcd_caps; +}; + +const struct dc_link_status *dc_link_get_status(const struct dc_link *dc_link); + +/* + * Return an enumerated dc_link. dc_link order is constant and determined at + * boot time. They cannot be created or destroyed. + * Use dc_get_caps() to get number of links. + */ +const struct dc_link *dc_get_link_at_index(const struct dc *dc, uint32_t link_index); + +/* Return id of physical connector represented by a dc_link at link_index.*/ +const struct graphics_object_id dc_get_link_id_at_index( + struct dc *dc, uint32_t link_index); + +/* Set backlight level of an embedded panel (eDP, LVDS). */ +bool dc_link_set_backlight_level(const struct dc_link *dc_link, uint32_t level, + uint32_t frame_ramp, const struct dc_stream *stream); + +bool dc_link_init_dmcu_backlight_settings(const struct dc_link *dc_link); + +bool dc_link_set_abm_level(const struct dc_link *dc_link, uint32_t level); + +bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable); + +bool dc_link_setup_psr(const struct dc_link *dc_link, + const struct dc_stream *stream); + +/* Request DC to detect if there is a Panel connected. + * boot - If this call is during initial boot. + * Return false for any type of detection failure or MST detection + * true otherwise. True meaning further action is required (status update + * and OS notification). + */ +bool dc_link_detect(const struct dc_link *dc_link, bool boot); + +/* Notify DC about DP RX Interrupt (aka Short Pulse Interrupt). + * Return: + * true - Downstream port status changed. DM should call DC to do the + * detection. + * false - no change in Downstream port status. No further action required + * from DM. */ +bool dc_link_handle_hpd_rx_irq(const struct dc_link *dc_link); + +struct dc_sink_init_data; + +struct dc_sink *dc_link_add_remote_sink( + const struct dc_link *dc_link, + const uint8_t *edid, + int len, + struct dc_sink_init_data *init_data); + +void dc_link_remove_remote_sink( + const struct dc_link *link, + const struct dc_sink *sink); + +/* Used by diagnostics for virtual link at the moment */ +void dc_link_set_sink(const struct dc_link *link, struct dc_sink *sink); + +void dc_link_dp_set_drive_settings( + struct dc_link *link, + struct link_training_settings *lt_settings); + +bool dc_link_dp_perform_link_training( + struct dc_link *link, + const struct dc_link_settings *link_setting, + bool skip_video_pattern); + +void dc_link_dp_enable_hpd(const struct dc_link *link); + +void dc_link_dp_disable_hpd(const struct dc_link *link); + +bool dc_link_dp_set_test_pattern( + const struct dc_link *link, + enum dp_test_pattern test_pattern, + const struct link_training_settings *p_link_settings, + const unsigned char *p_custom_pattern, + unsigned int cust_pattern_size); + +/******************************************************************************* + * Sink Interfaces - A sink corresponds to a display output device + ******************************************************************************/ + +/* + * The sink structure contains EDID and other display device properties + */ +struct dc_sink { + enum signal_type sink_signal; + struct dc_edid dc_edid; /* raw edid */ + struct dc_edid_caps edid_caps; /* parse display caps */ +}; + +void dc_sink_retain(const struct dc_sink *sink); +void dc_sink_release(const struct dc_sink *sink); + +const struct audio **dc_get_audios(struct dc *dc); + +struct dc_sink_init_data { + enum signal_type sink_signal; + const struct dc_link *link; + uint32_t dongle_max_pix_clk; + bool converter_disable_audio; +}; + +struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params); + +/******************************************************************************* + * Cursor interfaces - To manages the cursor within a target + ******************************************************************************/ +/* TODO: Deprecated once we switch to dc_set_cursor_position */ +bool dc_target_set_cursor_attributes( + struct dc_target *dc_target, + const struct dc_cursor_attributes *attributes); + +bool dc_target_set_cursor_position( + struct dc_target *dc_target, + const struct dc_cursor_position *position); + +/* Newer interfaces */ +struct dc_cursor { + struct dc_plane_address address; + struct dc_cursor_attributes attributes; +}; + +/* + * Create a new cursor with default values for a given target. + */ +struct dc_cursor *dc_create_cursor_for_target( + const struct dc *dc, + struct dc_target *dc_target); + +/** + * Commit cursor attribute changes such as pixel format and dimensions and + * surface address. + * + * After this call: + * Cursor address and format is programmed to the new values. + * Cursor position is unmodified. + */ +bool dc_commit_cursor( + const struct dc *dc, + struct dc_cursor *cursor); + +/* + * Optimized cursor position update + * + * After this call: + * Cursor position will be programmed as well as enable/disable bit. + */ +bool dc_set_cursor_position( + const struct dc *dc, + struct dc_cursor *cursor, + struct dc_cursor_position *pos); + +/******************************************************************************* + * Interrupt interfaces + ******************************************************************************/ +enum dc_irq_source dc_interrupt_to_irq_source( + struct dc *dc, + uint32_t src_id, + uint32_t ext_id); +void dc_interrupt_set(const struct dc *dc, enum dc_irq_source src, bool enable); +void dc_interrupt_ack(struct dc *dc, enum dc_irq_source src); +enum dc_irq_source dc_get_hpd_irq_source_at_index( + struct dc *dc, uint32_t link_index); + +/******************************************************************************* + * Power Interfaces + ******************************************************************************/ + +void dc_set_power_state( + struct dc *dc, + enum dc_acpi_cm_power_state power_state, + enum dc_video_power_state video_power_state); +void dc_resume(const struct dc *dc); + +/******************************************************************************* + * DDC Interfaces + ******************************************************************************/ + +const struct ddc_service *dc_get_ddc_at_index( + struct dc *dc, uint32_t link_index); + +/* + * DPCD access interfaces + */ + +bool dc_read_dpcd( + struct dc *dc, + uint32_t link_index, + uint32_t address, + uint8_t *data, + uint32_t size); + +bool dc_write_dpcd( + struct dc *dc, + uint32_t link_index, + uint32_t address, + const uint8_t *data, + uint32_t size); + +bool dc_submit_i2c( + struct dc *dc, + uint32_t link_index, + struct i2c_command *cmd); + +#endif /* DC_INTERFACE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dc_bios_types.h b/drivers/gpu/drm/amd/display/dc/dc_bios_types.h new file mode 100644 index 000000000000..790c5bd51cb9 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dc_bios_types.h @@ -0,0 +1,224 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef DC_BIOS_TYPES_H +#define DC_BIOS_TYPES_H + +/****************************************************************************** + * Interface file for VBIOS implementations. + * + * The default implementation is inside DC. + * Display Manager (which instantiates DC) has the option to supply it's own + * (external to DC) implementation of VBIOS, which will be called by DC, using + * this interface. + * (The intended use is Diagnostics, but other uses may appear.) + *****************************************************************************/ + +#include "include/bios_parser_types.h" + +struct dc_vbios_funcs { + uint8_t (*get_connectors_number)(struct dc_bios *bios); + + struct graphics_object_id (*get_encoder_id)( + struct dc_bios *bios, + uint32_t i); + struct graphics_object_id (*get_connector_id)( + struct dc_bios *bios, + uint8_t connector_index); + uint32_t (*get_dst_number)( + struct dc_bios *bios, + struct graphics_object_id id); + + uint32_t (*get_gpio_record)( + struct dc_bios *dcb, + struct graphics_object_id id, + struct bp_gpio_cntl_info *gpio_record, + uint32_t record_size); + + enum bp_result (*get_src_obj)( + struct dc_bios *bios, + struct graphics_object_id object_id, uint32_t index, + struct graphics_object_id *src_object_id); + enum bp_result (*get_dst_obj)( + struct dc_bios *bios, + struct graphics_object_id object_id, uint32_t index, + struct graphics_object_id *dest_object_id); + + enum bp_result (*get_i2c_info)( + struct dc_bios *dcb, + struct graphics_object_id id, + struct graphics_object_i2c_info *info); + + enum bp_result (*get_voltage_ddc_info)( + struct dc_bios *bios, + uint32_t index, + struct graphics_object_i2c_info *info); + enum bp_result (*get_thermal_ddc_info)( + struct dc_bios *bios, + uint32_t i2c_channel_id, + struct graphics_object_i2c_info *info); + enum bp_result (*get_hpd_info)( + struct dc_bios *bios, + struct graphics_object_id id, + struct graphics_object_hpd_info *info); + enum bp_result (*get_device_tag)( + struct dc_bios *bios, + struct graphics_object_id connector_object_id, + uint32_t device_tag_index, + struct connector_device_tag_info *info); + enum bp_result (*get_firmware_info)( + struct dc_bios *bios, + struct firmware_info *info); + enum bp_result (*get_spread_spectrum_info)( + struct dc_bios *bios, + enum as_signal_type signal, + uint32_t index, + struct spread_spectrum_info *ss_info); + uint32_t (*get_ss_entry_number)( + struct dc_bios *bios, + enum as_signal_type signal); + enum bp_result (*get_embedded_panel_info)( + struct dc_bios *bios, + struct embedded_panel_info *info); + enum bp_result (*get_gpio_pin_info)( + struct dc_bios *bios, + uint32_t gpio_id, + struct gpio_pin_info *info); + enum bp_result (*get_encoder_cap_info)( + struct dc_bios *bios, + struct graphics_object_id object_id, + struct bp_encoder_cap_info *info); + + bool (*is_lid_status_changed)( + struct dc_bios *bios); + bool (*is_display_config_changed)( + struct dc_bios *bios); + bool (*is_accelerated_mode)( + struct dc_bios *bios); + void (*get_bios_event_info)( + struct dc_bios *bios, + struct bios_event_info *info); + void (*update_requested_backlight_level)( + struct dc_bios *bios, + uint32_t backlight_8bit); + uint32_t (*get_requested_backlight_level)( + struct dc_bios *bios); + void (*take_backlight_control)( + struct dc_bios *bios, + bool cntl); + + bool (*is_active_display)( + struct dc_bios *bios, + enum signal_type signal, + const struct connector_device_tag_info *device_tag); + enum controller_id (*get_embedded_display_controller_id)( + struct dc_bios *bios); + uint32_t (*get_embedded_display_refresh_rate)( + struct dc_bios *bios); + + void (*set_scratch_critical_state)( + struct dc_bios *bios, + bool state); + bool (*is_device_id_supported)( + struct dc_bios *bios, + struct device_id id); + + /* COMMANDS */ + + enum bp_result (*encoder_control)( + struct dc_bios *bios, + struct bp_encoder_control *cntl); + enum bp_result (*transmitter_control)( + struct dc_bios *bios, + struct bp_transmitter_control *cntl); + enum bp_result (*crt_control)( + struct dc_bios *bios, + enum engine_id engine_id, + bool enable, + uint32_t pixel_clock); + enum bp_result (*enable_crtc)( + struct dc_bios *bios, + enum controller_id id, + bool enable); + enum bp_result (*adjust_pixel_clock)( + struct dc_bios *bios, + struct bp_adjust_pixel_clock_parameters *bp_params); + enum bp_result (*set_pixel_clock)( + struct dc_bios *bios, + struct bp_pixel_clock_parameters *bp_params); + enum bp_result (*set_dce_clock)( + struct dc_bios *bios, + struct bp_set_dce_clock_parameters *bp_params); + unsigned int (*get_smu_clock_info)( + struct dc_bios *bios); + enum bp_result (*enable_spread_spectrum_on_ppll)( + struct dc_bios *bios, + struct bp_spread_spectrum_parameters *bp_params, + bool enable); + enum bp_result (*program_crtc_timing)( + struct dc_bios *bios, + struct bp_hw_crtc_timing_parameters *bp_params); + + enum bp_result (*crtc_source_select)( + struct dc_bios *bios, + struct bp_crtc_source_select *bp_params); + enum bp_result (*program_display_engine_pll)( + struct dc_bios *bios, + struct bp_pixel_clock_parameters *bp_params); + + enum signal_type (*dac_load_detect)( + struct dc_bios *bios, + struct graphics_object_id encoder, + struct graphics_object_id connector, + enum signal_type display_signal); + + enum bp_result (*enable_disp_power_gating)( + struct dc_bios *bios, + enum controller_id controller_id, + enum bp_pipe_control_action action); + + void (*post_init)(struct dc_bios *bios); + + void (*bios_parser_destroy)(struct dc_bios **dcb); +}; + +struct bios_registers { + uint32_t BIOS_SCRATCH_6; +}; + +struct dc_bios { + const struct dc_vbios_funcs *funcs; + + uint8_t *bios; + uint32_t bios_size; + + uint8_t *bios_local_image; + + struct dc_context *ctx; + const struct bios_registers *regs; + struct integrated_info *integrated_info; +}; + +#endif /* DC_BIOS_TYPES_H */ diff --git a/drivers/gpu/drm/amd/display/dc/dc_ddc_types.h b/drivers/gpu/drm/amd/display/dc/dc_ddc_types.h new file mode 100644 index 000000000000..b143fe88f49f --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dc_ddc_types.h @@ -0,0 +1,115 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef DC_DDC_TYPES_H_ +#define DC_DDC_TYPES_H_ + +struct i2c_payload { + bool write; + uint8_t address; + uint32_t length; + uint8_t *data; +}; + +enum i2c_command_engine { + I2C_COMMAND_ENGINE_DEFAULT, + I2C_COMMAND_ENGINE_SW, + I2C_COMMAND_ENGINE_HW +}; + +struct i2c_command { + struct i2c_payload *payloads; + uint8_t number_of_payloads; + + enum i2c_command_engine engine; + + /* expressed in KHz + * zero means "use default value" */ + uint32_t speed; +}; + +struct gpio_ddc_hw_info { + bool hw_supported; + uint32_t ddc_channel; +}; + +struct ddc { + struct gpio *pin_data; + struct gpio *pin_clock; + struct gpio_ddc_hw_info hw_info; + struct dc_context *ctx; +}; + +union ddc_wa { + struct { + uint32_t DP_SKIP_POWER_OFF:1; + uint32_t DP_AUX_POWER_UP_WA_DELAY:1; + } bits; + uint32_t raw; +}; + +struct ddc_flags { + uint8_t EDID_QUERY_DONE_ONCE:1; + uint8_t IS_INTERNAL_DISPLAY:1; + uint8_t FORCE_READ_REPEATED_START:1; + uint8_t EDID_STRESS_READ:1; + +}; + +enum ddc_transaction_type { + DDC_TRANSACTION_TYPE_NONE = 0, + DDC_TRANSACTION_TYPE_I2C, + DDC_TRANSACTION_TYPE_I2C_OVER_AUX, + DDC_TRANSACTION_TYPE_I2C_OVER_AUX_WITH_DEFER, + DDC_TRANSACTION_TYPE_I2C_OVER_AUX_RETRY_DEFER +}; + +enum display_dongle_type { + DISPLAY_DONGLE_NONE = 0, + /* Active converter types*/ + DISPLAY_DONGLE_DP_VGA_CONVERTER, + DISPLAY_DONGLE_DP_DVI_CONVERTER, + DISPLAY_DONGLE_DP_HDMI_CONVERTER, + /* DP-HDMI/DVI passive dongles (Type 1 and Type 2)*/ + DISPLAY_DONGLE_DP_DVI_DONGLE, + DISPLAY_DONGLE_DP_HDMI_DONGLE, + /* Other types of dongle*/ + DISPLAY_DONGLE_DP_HDMI_MISMATCHED_DONGLE, +}; + +struct ddc_service { + struct ddc *ddc_pin; + struct ddc_flags flags; + union ddc_wa wa; + enum ddc_transaction_type transaction_type; + enum display_dongle_type dongle_type; + struct dc_context *ctx; + struct core_link *link; + + uint32_t address; + uint32_t edid_buf_len; + uint8_t edid_buf[MAX_EDID_BUFFER_SIZE]; +}; + +#endif /* DC_DDC_TYPES_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h new file mode 100644 index 000000000000..befc4985fe54 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h @@ -0,0 +1,105 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef DC_DP_TYPES_H +#define DC_DP_TYPES_H + +enum dc_lane_count { + LANE_COUNT_UNKNOWN = 0, + LANE_COUNT_ONE = 1, + LANE_COUNT_TWO = 2, + LANE_COUNT_FOUR = 4, + LANE_COUNT_EIGHT = 8, + LANE_COUNT_DP_MAX = LANE_COUNT_FOUR +}; + +/* This is actually a reference clock (27MHz) multiplier + * 162MBps bandwidth for 1.62GHz like rate, + * 270MBps for 2.70GHz, + * 324MBps for 3.24Ghz, + * 540MBps for 5.40GHz + * 810MBps for 8.10GHz + */ +enum dc_link_rate { + LINK_RATE_UNKNOWN = 0, + LINK_RATE_LOW = 0x06, + LINK_RATE_HIGH = 0x0A, + LINK_RATE_RBR2 = 0x0C, + LINK_RATE_HIGH2 = 0x14, + LINK_RATE_HIGH3 = 0x1E +}; + +enum dc_link_spread { + LINK_SPREAD_DISABLED = 0x00, + /* 0.5 % downspread 30 kHz */ + LINK_SPREAD_05_DOWNSPREAD_30KHZ = 0x10, + /* 0.5 % downspread 33 kHz */ + LINK_SPREAD_05_DOWNSPREAD_33KHZ = 0x11 +}; + +enum dc_voltage_swing { + VOLTAGE_SWING_LEVEL0 = 0, /* direct HW translation! */ + VOLTAGE_SWING_LEVEL1, + VOLTAGE_SWING_LEVEL2, + VOLTAGE_SWING_LEVEL3, + VOLTAGE_SWING_MAX_LEVEL = VOLTAGE_SWING_LEVEL3 +}; + +enum dc_pre_emphasis { + PRE_EMPHASIS_DISABLED = 0, /* direct HW translation! */ + PRE_EMPHASIS_LEVEL1, + PRE_EMPHASIS_LEVEL2, + PRE_EMPHASIS_LEVEL3, + PRE_EMPHASIS_MAX_LEVEL = PRE_EMPHASIS_LEVEL3 +}; +/* Post Cursor 2 is optional for transmitter + * and it applies only to the main link operating at HBR2 + */ +enum dc_post_cursor2 { + POST_CURSOR2_DISABLED = 0, /* direct HW translation! */ + POST_CURSOR2_LEVEL1, + POST_CURSOR2_LEVEL2, + POST_CURSOR2_LEVEL3, + POST_CURSOR2_MAX_LEVEL = POST_CURSOR2_LEVEL3, +}; + +struct dc_link_settings { + enum dc_lane_count lane_count; + enum dc_link_rate link_rate; + enum dc_link_spread link_spread; +}; + +struct dc_lane_settings { + enum dc_voltage_swing VOLTAGE_SWING; + enum dc_pre_emphasis PRE_EMPHASIS; + enum dc_post_cursor2 POST_CURSOR2; +}; + +struct dc_link_training_settings { + struct dc_link_settings link; + struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]; +}; + +#endif /* DC_DP_TYPES_H */ diff --git a/drivers/gpu/drm/amd/display/dc/dc_helper.c b/drivers/gpu/drm/amd/display/dc/dc_helper.c new file mode 100644 index 000000000000..3a80b0c08ae4 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dc_helper.c @@ -0,0 +1,144 @@ +/* + * dc_helper.c + * + * Created on: Aug 30, 2016 + * Author: agrodzov + */ +#include "dm_services.h" +#include + +uint32_t generic_reg_update_ex(const struct dc_context *ctx, + uint32_t addr, uint32_t reg_val, int n, + uint8_t shift1, uint32_t mask1, uint32_t field_value1, + ...) +{ + uint32_t shift, mask, field_value; + int i = 1; + + va_list ap; + va_start(ap, field_value1); + + reg_val = set_reg_field_value_ex(reg_val, field_value1, mask1, shift1); + + while (i < n) { + shift = va_arg(ap, uint32_t); + mask = va_arg(ap, uint32_t); + field_value = va_arg(ap, uint32_t); + + reg_val = set_reg_field_value_ex(reg_val, field_value, mask, shift); + i++; + } + + dm_write_reg(ctx, addr, reg_val); + va_end(ap); + + return reg_val; +} + +uint32_t generic_reg_get(const struct dc_context *ctx, uint32_t addr, + uint8_t shift, uint32_t mask, uint32_t *field_value) +{ + uint32_t reg_val = dm_read_reg(ctx, addr); + *field_value = get_reg_field_value_ex(reg_val, mask, shift); + return reg_val; +} + +uint32_t generic_reg_get2(const struct dc_context *ctx, uint32_t addr, + uint8_t shift1, uint32_t mask1, uint32_t *field_value1, + uint8_t shift2, uint32_t mask2, uint32_t *field_value2) +{ + uint32_t reg_val = dm_read_reg(ctx, addr); + *field_value1 = get_reg_field_value_ex(reg_val, mask1, shift1); + *field_value2 = get_reg_field_value_ex(reg_val, mask2, shift2); + return reg_val; +} + +uint32_t generic_reg_get3(const struct dc_context *ctx, uint32_t addr, + uint8_t shift1, uint32_t mask1, uint32_t *field_value1, + uint8_t shift2, uint32_t mask2, uint32_t *field_value2, + uint8_t shift3, uint32_t mask3, uint32_t *field_value3) +{ + uint32_t reg_val = dm_read_reg(ctx, addr); + *field_value1 = get_reg_field_value_ex(reg_val, mask1, shift1); + *field_value2 = get_reg_field_value_ex(reg_val, mask2, shift2); + *field_value3 = get_reg_field_value_ex(reg_val, mask3, shift3); + return reg_val; +} + +uint32_t generic_reg_get5(const struct dc_context *ctx, uint32_t addr, + uint8_t shift1, uint32_t mask1, uint32_t *field_value1, + uint8_t shift2, uint32_t mask2, uint32_t *field_value2, + uint8_t shift3, uint32_t mask3, uint32_t *field_value3, + uint8_t shift4, uint32_t mask4, uint32_t *field_value4, + uint8_t shift5, uint32_t mask5, uint32_t *field_value5) +{ + uint32_t reg_val = dm_read_reg(ctx, addr); + *field_value1 = get_reg_field_value_ex(reg_val, mask1, shift1); + *field_value2 = get_reg_field_value_ex(reg_val, mask2, shift2); + *field_value3 = get_reg_field_value_ex(reg_val, mask3, shift3); + *field_value4 = get_reg_field_value_ex(reg_val, mask4, shift4); + *field_value5 = get_reg_field_value_ex(reg_val, mask5, shift5); + return reg_val; +} + +/* note: va version of this is pretty bad idea, since there is a output parameter pass by pointer + * compiler won't be able to check for size match and is prone to stack corruption type of bugs + +uint32_t generic_reg_get(const struct dc_context *ctx, + uint32_t addr, int n, ...) +{ + uint32_t shift, mask; + uint32_t *field_value; + uint32_t reg_val; + int i = 0; + + reg_val = dm_read_reg(ctx, addr); + + va_list ap; + va_start(ap, n); + + while (i < n) { + shift = va_arg(ap, uint32_t); + mask = va_arg(ap, uint32_t); + field_value = va_arg(ap, uint32_t *); + + *field_value = get_reg_field_value_ex(reg_val, mask, shift); + i++; + } + + va_end(ap); + + return reg_val; +} +*/ + +uint32_t generic_reg_wait(const struct dc_context *ctx, + uint32_t addr, uint32_t shift, uint32_t mask, uint32_t condition_value, + unsigned int delay_between_poll_us, unsigned int time_out_num_tries, + const char *func_name) +{ + uint32_t field_value; + uint32_t reg_val; + int i; + + for (i = 0; i <= time_out_num_tries; i++) { + if (i) { + if (0 < delay_between_poll_us && delay_between_poll_us < 1000) + udelay(delay_between_poll_us); + + if (delay_between_poll_us > 1000) + msleep(delay_between_poll_us/1000); + } + + reg_val = dm_read_reg(ctx, addr); + + field_value = get_reg_field_value_ex(reg_val, mask, shift); + + if (field_value == condition_value) + return reg_val; + } + + DC_ERR("REG_WAIT timeout %dus * %d tries - %s", + delay_between_poll_us, time_out_num_tries, func_name); + return reg_val; +} diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h new file mode 100644 index 000000000000..5605a5c96da7 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -0,0 +1,588 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef DC_HW_TYPES_H +#define DC_HW_TYPES_H + +#include "os_types.h" + +/****************************************************************************** + * Data types for Virtual HW Layer of DAL3. + * (see DAL3 design documents for HW Layer definition) + * + * The intended uses are: + * 1. Generation pseudocode sequences for HW programming. + * 2. Implementation of real HW programming by HW Sequencer of DAL3. + * + * Note: do *not* add any types which are *not* used for HW programming - this + * will ensure separation of Logic layer from HW layer. + ******************************************************************************/ + +union large_integer { + struct { + uint32_t low_part; + int32_t high_part; + }; + + struct { + uint32_t low_part; + int32_t high_part; + } u; + + int64_t quad_part; +}; + +#define PHYSICAL_ADDRESS_LOC union large_integer + +enum dc_plane_addr_type { + PLN_ADDR_TYPE_GRAPHICS = 0, + PLN_ADDR_TYPE_GRPH_STEREO, + PLN_ADDR_TYPE_VIDEO_PROGRESSIVE, +}; + +struct dc_plane_address { + enum dc_plane_addr_type type; + union { + struct{ + PHYSICAL_ADDRESS_LOC addr; + PHYSICAL_ADDRESS_LOC meta_addr; + union large_integer dcc_const_color; + } grph; + + /*stereo*/ + struct { + PHYSICAL_ADDRESS_LOC left_addr; + PHYSICAL_ADDRESS_LOC left_meta_addr; + union large_integer left_dcc_const_color; + + PHYSICAL_ADDRESS_LOC right_addr; + PHYSICAL_ADDRESS_LOC right_meta_addr; + union large_integer right_dcc_const_color; + + } grph_stereo; + + /*video progressive*/ + struct { + PHYSICAL_ADDRESS_LOC luma_addr; + PHYSICAL_ADDRESS_LOC luma_meta_addr; + union large_integer luma_dcc_const_color; + + PHYSICAL_ADDRESS_LOC chroma_addr; + PHYSICAL_ADDRESS_LOC chroma_meta_addr; + union large_integer chroma_dcc_const_color; + } video_progressive; + }; +}; + +struct dc_size { + uint32_t width; + uint32_t height; +}; + +struct rect { + int x; + int y; + uint32_t width; + uint32_t height; +}; + +union plane_size { + /* Grph or Video will be selected + * based on format above: + * Use Video structure if + * format >= DalPixelFormat_VideoBegin + * else use Grph structure + */ + struct { + struct rect surface_size; + /* Graphic surface pitch in pixels. + * In LINEAR_GENERAL mode, pitch + * is 32 pixel aligned. + */ + uint32_t surface_pitch; + + uint32_t meta_pitch; + } grph; + + struct { + struct rect luma_size; + /* Graphic surface pitch in pixels. + * In LINEAR_GENERAL mode, pitch is + * 32 pixel aligned. + */ + uint32_t luma_pitch; + uint32_t meta_luma_pitch; + + struct rect chroma_size; + /* Graphic surface pitch in pixels. + * In LINEAR_GENERAL mode, pitch is + * 32 pixel aligned. + */ + uint32_t chroma_pitch; + uint32_t meta_chroma_pitch; + } video; +}; + +struct dc_plane_dcc_param { + bool enable; + + union { + struct { + uint32_t meta_pitch; + bool independent_64b_blks; + } grph; + + struct { + uint32_t meta_pitch_l; + bool independent_64b_blks_l; + + uint32_t meta_pitch_c; + bool independent_64b_blks_c; + } video; + }; +}; + +/*Displayable pixel format in fb*/ +enum surface_pixel_format { + SURFACE_PIXEL_FORMAT_GRPH_BEGIN = 0, + /*TOBE REMOVED paletta 256 colors*/ + SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS = + SURFACE_PIXEL_FORMAT_GRPH_BEGIN, + /*16 bpp*/ + SURFACE_PIXEL_FORMAT_GRPH_ARGB1555, + /*16 bpp*/ + SURFACE_PIXEL_FORMAT_GRPH_RGB565, + /*32 bpp*/ + SURFACE_PIXEL_FORMAT_GRPH_ARGB8888, + /*32 bpp swaped*/ + SURFACE_PIXEL_FORMAT_GRPH_BGRA8888, + + SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010, + /*swaped*/ + SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010, + /*TOBE REMOVED swaped, XR_BIAS has no differance + * for pixel layout than previous and we can + * delete this after discusion*/ + SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS, + /*64 bpp */ + SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616, + /*float*/ + SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F, + /*swaped & float*/ + SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F, + /*grow graphics here if necessary */ + + SURFACE_PIXEL_FORMAT_VIDEO_BEGIN, + SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr = + SURFACE_PIXEL_FORMAT_VIDEO_BEGIN, + SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb, + SURFACE_PIXEL_FORMAT_INVALID + + /*grow 444 video here if necessary */ +}; + +/* Pixel format */ +enum pixel_format { + /*graph*/ + PIXEL_FORMAT_UNINITIALIZED, + PIXEL_FORMAT_INDEX8, + PIXEL_FORMAT_RGB565, + PIXEL_FORMAT_ARGB8888, + PIXEL_FORMAT_ARGB2101010, + PIXEL_FORMAT_ARGB2101010_XRBIAS, + PIXEL_FORMAT_FP16, + /*video*/ + PIXEL_FORMAT_420BPP12, + /*end of pixel format definition*/ + PIXEL_FORMAT_INVALID, + + PIXEL_FORMAT_GRPH_BEGIN = PIXEL_FORMAT_INDEX8, + PIXEL_FORMAT_GRPH_END = PIXEL_FORMAT_FP16, + PIXEL_FORMAT_VIDEO_BEGIN = PIXEL_FORMAT_420BPP12, + PIXEL_FORMAT_VIDEO_END = PIXEL_FORMAT_420BPP12, + PIXEL_FORMAT_UNKNOWN +}; + +enum tile_split_values { + DC_DISPLAY_MICRO_TILING = 0x0, + DC_THIN_MICRO_TILING = 0x1, + DC_DEPTH_MICRO_TILING = 0x2, + DC_ROTATED_MICRO_TILING = 0x3, +}; + +/* TODO: These values come from hardware spec. We need to readdress this + * if they ever change. + */ +enum array_mode_values { + DC_ARRAY_LINEAR_GENERAL = 0, + DC_ARRAY_LINEAR_ALLIGNED, + DC_ARRAY_1D_TILED_THIN1, + DC_ARRAY_1D_TILED_THICK, + DC_ARRAY_2D_TILED_THIN1, + DC_ARRAY_PRT_TILED_THIN1, + DC_ARRAY_PRT_2D_TILED_THIN1, + DC_ARRAY_2D_TILED_THICK, + DC_ARRAY_2D_TILED_X_THICK, + DC_ARRAY_PRT_TILED_THICK, + DC_ARRAY_PRT_2D_TILED_THICK, + DC_ARRAY_PRT_3D_TILED_THIN1, + DC_ARRAY_3D_TILED_THIN1, + DC_ARRAY_3D_TILED_THICK, + DC_ARRAY_3D_TILED_X_THICK, + DC_ARRAY_PRT_3D_TILED_THICK, +}; + +enum tile_mode_values { + DC_ADDR_SURF_MICRO_TILING_DISPLAY = 0x0, + DC_ADDR_SURF_MICRO_TILING_NON_DISPLAY = 0x1, +}; + +union dc_tiling_info { + + struct { + /* Specifies the number of memory banks for tiling + * purposes. + * Only applies to 2D and 3D tiling modes. + * POSSIBLE VALUES: 2,4,8,16 + */ + unsigned int num_banks; + /* Specifies the number of tiles in the x direction + * to be incorporated into the same bank. + * Only applies to 2D and 3D tiling modes. + * POSSIBLE VALUES: 1,2,4,8 + */ + unsigned int bank_width; + unsigned int bank_width_c; + /* Specifies the number of tiles in the y direction to + * be incorporated into the same bank. + * Only applies to 2D and 3D tiling modes. + * POSSIBLE VALUES: 1,2,4,8 + */ + unsigned int bank_height; + unsigned int bank_height_c; + /* Specifies the macro tile aspect ratio. Only applies + * to 2D and 3D tiling modes. + */ + unsigned int tile_aspect; + unsigned int tile_aspect_c; + /* Specifies the number of bytes that will be stored + * contiguously for each tile. + * If the tile data requires more storage than this + * amount, it is split into multiple slices. + * This field must not be larger than + * GB_ADDR_CONFIG.DRAM_ROW_SIZE. + * Only applies to 2D and 3D tiling modes. + * For color render targets, TILE_SPLIT >= 256B. + */ + enum tile_split_values tile_split; + enum tile_split_values tile_split_c; + /* Specifies the addressing within a tile. + * 0x0 - DISPLAY_MICRO_TILING + * 0x1 - THIN_MICRO_TILING + * 0x2 - DEPTH_MICRO_TILING + * 0x3 - ROTATED_MICRO_TILING + */ + enum tile_mode_values tile_mode; + enum tile_mode_values tile_mode_c; + /* Specifies the number of pipes and how they are + * interleaved in the surface. + * Refer to memory addressing document for complete + * details and constraints. + */ + unsigned int pipe_config; + /* Specifies the tiling mode of the surface. + * THIN tiles use an 8x8x1 tile size. + * THICK tiles use an 8x8x4 tile size. + * 2D tiling modes rotate banks for successive Z slices + * 3D tiling modes rotate pipes and banks for Z slices + * Refer to memory addressing document for complete + * details and constraints. + */ + enum array_mode_values array_mode; + } gfx8; + +}; + +/* Rotation angle */ +enum dc_rotation_angle { + ROTATION_ANGLE_0 = 0, + ROTATION_ANGLE_90, + ROTATION_ANGLE_180, + ROTATION_ANGLE_270, + ROTATION_ANGLE_COUNT +}; + +enum dc_scan_direction { + SCAN_DIRECTION_UNKNOWN = 0, + SCAN_DIRECTION_HORIZONTAL = 1, /* 0, 180 rotation */ + SCAN_DIRECTION_VERTICAL = 2, /* 90, 270 rotation */ +}; + +struct dc_cursor_position { + uint32_t x; + uint32_t y; + + uint32_t x_hotspot; + uint32_t y_hotspot; + + /* + * This parameter indicates whether HW cursor should be enabled + */ + bool enable; + + /* + * This parameter indicates whether cursor hot spot should be + * programmed + */ + bool hot_spot_enable; +}; + +/* IPP related types */ + +/* Used by both ipp amd opp functions*/ +/* TODO: to be consolidated with enum color_space */ + +/* + * This enum is for programming CURSOR_MODE register field. What this register + * should be programmed to depends on OS requested cursor shape flags and what + * we stored in the cursor surface. + */ +enum dc_cursor_color_format { + CURSOR_MODE_MONO, + CURSOR_MODE_COLOR_1BIT_AND, + CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA, + CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA +}; + +/* + * This is all the parameters required by DAL in order to update the cursor + * attributes, including the new cursor image surface address, size, hotspot + * location, color format, etc. + */ + +union dc_cursor_attribute_flags { + struct { + uint32_t ENABLE_MAGNIFICATION:1; + uint32_t INVERSE_TRANSPARENT_CLAMPING:1; + uint32_t HORIZONTAL_MIRROR:1; + uint32_t VERTICAL_MIRROR:1; + uint32_t INVERT_PIXEL_DATA:1; + uint32_t ZERO_EXPANSION:1; + uint32_t MIN_MAX_INVERT:1; + uint32_t RESERVED:25; + } bits; + uint32_t value; +}; + +struct dc_cursor_attributes { + PHYSICAL_ADDRESS_LOC address; + + /* Width and height should correspond to cursor surface width x heigh */ + uint32_t width; + uint32_t height; + uint32_t x_hot; + uint32_t y_hot; + + enum dc_cursor_color_format color_format; + + /* In case we support HW Cursor rotation in the future */ + enum dc_rotation_angle rotation_angle; + + union dc_cursor_attribute_flags attribute_flags; +}; + +/* OPP */ + +enum dc_color_space { + COLOR_SPACE_UNKNOWN, + COLOR_SPACE_SRGB, + COLOR_SPACE_SRGB_LIMITED, + COLOR_SPACE_YPBPR601, + COLOR_SPACE_YPBPR709, + COLOR_SPACE_YCBCR601, + COLOR_SPACE_YCBCR709, + COLOR_SPACE_YCBCR601_LIMITED, + COLOR_SPACE_YCBCR709_LIMITED +}; + +enum dc_quantization_range { + QUANTIZATION_RANGE_UNKNOWN, + QUANTIZATION_RANGE_FULL, + QUANTIZATION_RANGE_LIMITED +}; + +/* XFM */ + +/* used in struct dc_surface */ +struct scaling_taps { + uint32_t v_taps; + uint32_t h_taps; + uint32_t v_taps_c; + uint32_t h_taps_c; +}; + +enum dc_timing_standard { + TIMING_STANDARD_UNDEFINED, + TIMING_STANDARD_DMT, + TIMING_STANDARD_GTF, + TIMING_STANDARD_CVT, + TIMING_STANDARD_CVT_RB, + TIMING_STANDARD_CEA770, + TIMING_STANDARD_CEA861, + TIMING_STANDARD_HDMI, + TIMING_STANDARD_TV_NTSC, + TIMING_STANDARD_TV_NTSC_J, + TIMING_STANDARD_TV_PAL, + TIMING_STANDARD_TV_PAL_M, + TIMING_STANDARD_TV_PAL_CN, + TIMING_STANDARD_TV_SECAM, + TIMING_STANDARD_EXPLICIT, + /*!< For explicit timings from EDID, VBIOS, etc.*/ + TIMING_STANDARD_USER_OVERRIDE, + /*!< For mode timing override by user*/ + TIMING_STANDARD_MAX +}; + +enum dc_timing_3d_format { + TIMING_3D_FORMAT_NONE, + TIMING_3D_FORMAT_FRAME_ALTERNATE, /* No stereosync at all*/ + TIMING_3D_FORMAT_INBAND_FA, /* Inband Frame Alternate (DVI/DP)*/ + TIMING_3D_FORMAT_DP_HDMI_INBAND_FA, /* Inband FA to HDMI Frame Pack*/ + /* for active DP-HDMI dongle*/ + TIMING_3D_FORMAT_SIDEBAND_FA, /* Sideband Frame Alternate (eDP)*/ + TIMING_3D_FORMAT_HW_FRAME_PACKING, + TIMING_3D_FORMAT_SW_FRAME_PACKING, + TIMING_3D_FORMAT_ROW_INTERLEAVE, + TIMING_3D_FORMAT_COLUMN_INTERLEAVE, + TIMING_3D_FORMAT_PIXEL_INTERLEAVE, + TIMING_3D_FORMAT_SIDE_BY_SIDE, + TIMING_3D_FORMAT_TOP_AND_BOTTOM, + TIMING_3D_FORMAT_SBS_SW_PACKED, + /* Side-by-side, packed by application/driver into 2D frame*/ + TIMING_3D_FORMAT_TB_SW_PACKED, + /* Top-and-bottom, packed by application/driver into 2D frame*/ + + TIMING_3D_FORMAT_MAX, +}; + +enum dc_color_depth { + COLOR_DEPTH_UNDEFINED, + COLOR_DEPTH_666, + COLOR_DEPTH_888, + COLOR_DEPTH_101010, + COLOR_DEPTH_121212, + COLOR_DEPTH_141414, + COLOR_DEPTH_161616, + COLOR_DEPTH_COUNT +}; + +enum dc_pixel_encoding { + PIXEL_ENCODING_UNDEFINED, + PIXEL_ENCODING_RGB, + PIXEL_ENCODING_YCBCR422, + PIXEL_ENCODING_YCBCR444, + PIXEL_ENCODING_YCBCR420, + PIXEL_ENCODING_COUNT +}; + +enum dc_aspect_ratio { + ASPECT_RATIO_NO_DATA, + ASPECT_RATIO_4_3, + ASPECT_RATIO_16_9, + ASPECT_RATIO_64_27, + ASPECT_RATIO_256_135, + ASPECT_RATIO_FUTURE +}; + +enum scanning_type { + SCANNING_TYPE_NODATA = 0, + SCANNING_TYPE_OVERSCAN, + SCANNING_TYPE_UNDERSCAN, + SCANNING_TYPE_FUTURE, + SCANNING_TYPE_UNDEFINED +}; + +struct dc_crtc_timing_flags { + uint32_t INTERLACE :1; + uint32_t HSYNC_POSITIVE_POLARITY :1; /* when set to 1, + it is positive polarity --reversed with dal1 or video bios define*/ + uint32_t VSYNC_POSITIVE_POLARITY :1; /* when set to 1, + it is positive polarity --reversed with dal1 or video bios define*/ + + uint32_t HORZ_COUNT_BY_TWO:1; + + uint32_t EXCLUSIVE_3D :1; /* if this bit set, + timing can be driven in 3D format only + and there is no corresponding 2D timing*/ + uint32_t RIGHT_EYE_3D_POLARITY :1; /* 1 - means right eye polarity + (right eye = '1', left eye = '0') */ + uint32_t SUB_SAMPLE_3D :1; /* 1 - means left/right images subsampled + when mixed into 3D image. 0 - means summation (3D timing is doubled)*/ + uint32_t USE_IN_3D_VIEW_ONLY :1; /* Do not use this timing in 2D View, + because corresponding 2D timing also present in the list*/ + uint32_t STEREO_3D_PREFERENCE :1; /* Means this is 2D timing + and we want to match priority of corresponding 3D timing*/ + uint32_t Y_ONLY :1; + + uint32_t YCBCR420 :1; /* TODO: shouldn't need this flag, should be a separate pixel format */ + uint32_t DTD_COUNTER :5; /* values 1 to 16 */ + + /* HDMI 2.0 - Support scrambling for TMDS character + * rates less than or equal to 340Mcsc */ + uint32_t LTE_340MCSC_SCRAMBLE:1; + +}; + +struct dc_crtc_timing { + + uint32_t h_total; + uint32_t h_border_left; + uint32_t h_addressable; + uint32_t h_border_right; + uint32_t h_front_porch; + uint32_t h_sync_width; + + uint32_t v_total; + uint32_t v_border_top; + uint32_t v_addressable; + uint32_t v_border_bottom; + uint32_t v_front_porch; + uint32_t v_sync_width; + + uint32_t pix_clk_khz; + + uint32_t vic; + uint32_t hdmi_vic; + enum dc_timing_3d_format timing_3d_format; + enum dc_color_depth display_color_depth; + enum dc_pixel_encoding pixel_encoding; + enum dc_aspect_ratio aspect_ratio; + enum scanning_type scan_type; + + struct dc_crtc_timing_flags flags; +}; + +#endif /* DC_HW_TYPES_H */ + diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h new file mode 100644 index 000000000000..ae9fcca121e6 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -0,0 +1,493 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef DC_TYPES_H_ +#define DC_TYPES_H_ + +#include "fixed32_32.h" +#include "fixed31_32.h" +#include "irq_types.h" +#include "dc_dp_types.h" +#include "dc_hw_types.h" +#include "dal_types.h" + +/* forward declarations */ +struct dc_surface; +struct dc_target; +struct dc_stream; +struct dc_link; +struct dc_sink; +struct dal; + +/******************************** + * Environment definitions + ********************************/ +enum dce_environment { + DCE_ENV_PRODUCTION_DRV = 0, + /* Emulation on FPGA, in "Maximus" System. + * This environment enforces that *only* DC registers accessed. + * (access to non-DC registers will hang FPGA) */ + DCE_ENV_FPGA_MAXIMUS, + /* Emulation on real HW or on FPGA. Used by Diagnostics, enforces + * requirements of Diagnostics team. */ + DCE_ENV_DIAG +}; + +/* Note: use these macro definitions instead of direct comparison! */ +#define IS_FPGA_MAXIMUS_DC(dce_environment) \ + (dce_environment == DCE_ENV_FPGA_MAXIMUS) + +#define IS_DIAG_DC(dce_environment) \ + (IS_FPGA_MAXIMUS_DC(dce_environment) || (dce_environment == DCE_ENV_DIAG)) + +struct hw_asic_id { + uint32_t chip_id; + uint32_t chip_family; + uint32_t pci_revision_id; + uint32_t hw_internal_rev; + uint32_t vram_type; + uint32_t vram_width; + uint32_t feature_flags; + uint32_t fake_paths_num; + void *atombios_base_address; +}; + +struct dc_context { + struct dc *dc; + + void *driver_context; /* e.g. amdgpu_device */ + + struct dal_logger *logger; + void *cgs_device; + + enum dce_environment dce_environment; + struct hw_asic_id asic_id; + + /* todo: below should probably move to dc. to facilitate removal + * of AS we will store these here + */ + enum dce_version dce_version; + struct dc_bios *dc_bios; + bool created_bios; + struct gpio_service *gpio_service; + struct i2caux *i2caux; +}; + + +#define MAX_EDID_BUFFER_SIZE 512 +#define EDID_BLOCK_SIZE 128 +#define MAX_SURFACE_NUM 2 +#define NUM_PIXEL_FORMATS 10 + +#include "dc_ddc_types.h" + +enum tiling_mode { + TILING_MODE_INVALID, + TILING_MODE_LINEAR, + TILING_MODE_TILED, + TILING_MODE_COUNT +}; + +enum view_3d_format { + VIEW_3D_FORMAT_NONE = 0, + VIEW_3D_FORMAT_FRAME_SEQUENTIAL, + VIEW_3D_FORMAT_SIDE_BY_SIDE, + VIEW_3D_FORMAT_TOP_AND_BOTTOM, + VIEW_3D_FORMAT_COUNT, + VIEW_3D_FORMAT_FIRST = VIEW_3D_FORMAT_FRAME_SEQUENTIAL +}; + +enum plane_stereo_format { + PLANE_STEREO_FORMAT_NONE = 0, + PLANE_STEREO_FORMAT_SIDE_BY_SIDE = 1, + PLANE_STEREO_FORMAT_TOP_AND_BOTTOM = 2, + PLANE_STEREO_FORMAT_FRAME_ALTERNATE = 3, + PLANE_STEREO_FORMAT_ROW_INTERLEAVED = 5, + PLANE_STEREO_FORMAT_COLUMN_INTERLEAVED = 6, + PLANE_STEREO_FORMAT_CHECKER_BOARD = 7 +}; + +/* TODO: Find way to calculate number of bits + * Please increase if pixel_format enum increases + * num from PIXEL_FORMAT_INDEX8 to PIXEL_FORMAT_444BPP32 + */ + +enum dc_edid_connector_type { + EDID_CONNECTOR_UNKNOWN = 0, + EDID_CONNECTOR_ANALOG = 1, + EDID_CONNECTOR_DIGITAL = 10, + EDID_CONNECTOR_DVI = 11, + EDID_CONNECTOR_HDMIA = 12, + EDID_CONNECTOR_MDDI = 14, + EDID_CONNECTOR_DISPLAYPORT = 15 +}; + +enum dc_edid_status { + EDID_OK, + EDID_BAD_INPUT, + EDID_NO_RESPONSE, + EDID_BAD_CHECKSUM, +}; + +/* audio capability from EDID*/ +struct dc_cea_audio_mode { + uint8_t format_code; /* ucData[0] [6:3]*/ + uint8_t channel_count; /* ucData[0] [2:0]*/ + uint8_t sample_rate; /* ucData[1]*/ + union { + uint8_t sample_size; /* for LPCM*/ + /* for Audio Formats 2-8 (Max bit rate divided by 8 kHz)*/ + uint8_t max_bit_rate; + uint8_t audio_codec_vendor_specific; /* for Audio Formats 9-15*/ + }; +}; + +struct dc_edid { + uint32_t length; + uint8_t raw_edid[MAX_EDID_BUFFER_SIZE]; +}; + +/* When speaker location data block is not available, DEFAULT_SPEAKER_LOCATION + * is used. In this case we assume speaker location are: front left, front + * right and front center. */ +#define DEFAULT_SPEAKER_LOCATION 5 + +#define DC_MAX_AUDIO_DESC_COUNT 16 + +#define AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS 20 + +struct dc_edid_caps { + /* sink identification */ + uint16_t manufacturer_id; + uint16_t product_id; + uint32_t serial_number; + uint8_t manufacture_week; + uint8_t manufacture_year; + uint8_t display_name[AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS]; + + /* audio caps */ + uint8_t speaker_flags; + uint32_t audio_mode_count; + struct dc_cea_audio_mode audio_modes[DC_MAX_AUDIO_DESC_COUNT]; + uint32_t audio_latency; + uint32_t video_latency; + + /*HDMI 2.0 caps*/ + bool lte_340mcsc_scramble; + + bool edid_hdmi; +}; + +struct view { + uint32_t width; + uint32_t height; +}; + +struct dc_mode_flags { + /* note: part of refresh rate flag*/ + uint32_t INTERLACE :1; + /* native display timing*/ + uint32_t NATIVE :1; + /* preferred is the recommended mode, one per display */ + uint32_t PREFERRED :1; + /* true if this mode should use reduced blanking timings + *_not_ related to the Reduced Blanking adjustment*/ + uint32_t REDUCED_BLANKING :1; + /* note: part of refreshrate flag*/ + uint32_t VIDEO_OPTIMIZED_RATE :1; + /* should be reported to upper layers as mode_flags*/ + uint32_t PACKED_PIXEL_FORMAT :1; + /*< preferred view*/ + uint32_t PREFERRED_VIEW :1; + /* this timing should be used only in tiled mode*/ + uint32_t TILED_MODE :1; + uint32_t DSE_MODE :1; + /* Refresh rate divider when Miracast sink is using a + different rate than the output display device + Must be zero for wired displays and non-zero for + Miracast displays*/ + uint32_t MIRACAST_REFRESH_DIVIDER; +}; + + +enum dc_timing_source { + TIMING_SOURCE_UNDEFINED, + + /* explicitly specifed by user, most important*/ + TIMING_SOURCE_USER_FORCED, + TIMING_SOURCE_USER_OVERRIDE, + TIMING_SOURCE_CUSTOM, + TIMING_SOURCE_EXPLICIT, + + /* explicitly specified by the display device, more important*/ + TIMING_SOURCE_EDID_CEA_SVD_3D, + TIMING_SOURCE_EDID_CEA_SVD_PREFERRED, + TIMING_SOURCE_EDID_CEA_SVD_420, + TIMING_SOURCE_EDID_DETAILED, + TIMING_SOURCE_EDID_ESTABLISHED, + TIMING_SOURCE_EDID_STANDARD, + TIMING_SOURCE_EDID_CEA_SVD, + TIMING_SOURCE_EDID_CVT_3BYTE, + TIMING_SOURCE_EDID_4BYTE, + TIMING_SOURCE_VBIOS, + TIMING_SOURCE_CV, + TIMING_SOURCE_TV, + TIMING_SOURCE_HDMI_VIC, + + /* implicitly specified by display device, still safe but less important*/ + TIMING_SOURCE_DEFAULT, + + /* only used for custom base modes */ + TIMING_SOURCE_CUSTOM_BASE, + + /* these timing might not work, least important*/ + TIMING_SOURCE_RANGELIMIT, + TIMING_SOURCE_OS_FORCED, + TIMING_SOURCE_IMPLICIT, + + /* only used by default mode list*/ + TIMING_SOURCE_BASICMODE, + + TIMING_SOURCE_COUNT +}; + +enum dc_timing_support_method { + TIMING_SUPPORT_METHOD_UNDEFINED, + TIMING_SUPPORT_METHOD_EXPLICIT, + TIMING_SUPPORT_METHOD_IMPLICIT, + TIMING_SUPPORT_METHOD_NATIVE +}; + +struct dc_mode_info { + uint32_t pixel_width; + uint32_t pixel_height; + uint32_t field_rate; + /* Vertical refresh rate for progressive modes. + * Field rate for interlaced modes.*/ + + enum dc_timing_standard timing_standard; + enum dc_timing_source timing_source; + struct dc_mode_flags flags; +}; + +enum dc_power_state { + DC_POWER_STATE_ON = 1, + DC_POWER_STATE_STANDBY, + DC_POWER_STATE_SUSPEND, + DC_POWER_STATE_OFF +}; + +/* DC PowerStates */ +enum dc_video_power_state { + DC_VIDEO_POWER_UNSPECIFIED = 0, + DC_VIDEO_POWER_ON = 1, + DC_VIDEO_POWER_STANDBY, + DC_VIDEO_POWER_SUSPEND, + DC_VIDEO_POWER_OFF, + DC_VIDEO_POWER_HIBERNATE, + DC_VIDEO_POWER_SHUTDOWN, + DC_VIDEO_POWER_ULPS, /* BACO or Ultra-Light-Power-State */ + DC_VIDEO_POWER_AFTER_RESET, + DC_VIDEO_POWER_MAXIMUM +}; + +enum dc_acpi_cm_power_state { + DC_ACPI_CM_POWER_STATE_D0 = 1, + DC_ACPI_CM_POWER_STATE_D1 = 2, + DC_ACPI_CM_POWER_STATE_D2 = 4, + DC_ACPI_CM_POWER_STATE_D3 = 8 +}; + +enum dc_connection_type { + dc_connection_none, + dc_connection_single, + dc_connection_mst_branch, + dc_connection_active_dongle +}; + +struct dc_csc_adjustments { + struct fixed31_32 contrast; + struct fixed31_32 saturation; + struct fixed31_32 brightness; + struct fixed31_32 hue; +}; + +enum { + MAX_LANES = 2, + MAX_COFUNC_PATH = 6, + LAYER_INDEX_PRIMARY = -1, +}; + +/* Scaling format */ +enum scaling_transformation { + SCALING_TRANSFORMATION_UNINITIALIZED, + SCALING_TRANSFORMATION_IDENTITY = 0x0001, + SCALING_TRANSFORMATION_CENTER_TIMING = 0x0002, + SCALING_TRANSFORMATION_FULL_SCREEN_SCALE = 0x0004, + SCALING_TRANSFORMATION_PRESERVE_ASPECT_RATIO_SCALE = 0x0008, + SCALING_TRANSFORMATION_DAL_DECIDE = 0x0010, + SCALING_TRANSFORMATION_INVALID = 0x80000000, + + /* Flag the first and last */ + SCALING_TRANSFORMATION_BEGING = SCALING_TRANSFORMATION_IDENTITY, + SCALING_TRANSFORMATION_END = + SCALING_TRANSFORMATION_PRESERVE_ASPECT_RATIO_SCALE +}; + +/* audio*/ + +union audio_sample_rates { + struct sample_rates { + uint8_t RATE_32:1; + uint8_t RATE_44_1:1; + uint8_t RATE_48:1; + uint8_t RATE_88_2:1; + uint8_t RATE_96:1; + uint8_t RATE_176_4:1; + uint8_t RATE_192:1; + } rate; + + uint8_t all; +}; + +struct audio_speaker_flags { + uint32_t FL_FR:1; + uint32_t LFE:1; + uint32_t FC:1; + uint32_t RL_RR:1; + uint32_t RC:1; + uint32_t FLC_FRC:1; + uint32_t RLC_RRC:1; + uint32_t SUPPORT_AI:1; +}; + +struct audio_speaker_info { + uint32_t ALLSPEAKERS:7; + uint32_t SUPPORT_AI:1; +}; + + +struct audio_info_flags { + + union { + + struct audio_speaker_flags speaker_flags; + struct audio_speaker_info info; + + uint8_t all; + }; +}; + +enum audio_format_code { + AUDIO_FORMAT_CODE_FIRST = 1, + AUDIO_FORMAT_CODE_LINEARPCM = AUDIO_FORMAT_CODE_FIRST, + + AUDIO_FORMAT_CODE_AC3, + /*Layers 1 & 2 */ + AUDIO_FORMAT_CODE_MPEG1, + /*MPEG1 Layer 3 */ + AUDIO_FORMAT_CODE_MP3, + /*multichannel */ + AUDIO_FORMAT_CODE_MPEG2, + AUDIO_FORMAT_CODE_AAC, + AUDIO_FORMAT_CODE_DTS, + AUDIO_FORMAT_CODE_ATRAC, + AUDIO_FORMAT_CODE_1BITAUDIO, + AUDIO_FORMAT_CODE_DOLBYDIGITALPLUS, + AUDIO_FORMAT_CODE_DTS_HD, + AUDIO_FORMAT_CODE_MAT_MLP, + AUDIO_FORMAT_CODE_DST, + AUDIO_FORMAT_CODE_WMAPRO, + AUDIO_FORMAT_CODE_LAST, + AUDIO_FORMAT_CODE_COUNT = + AUDIO_FORMAT_CODE_LAST - AUDIO_FORMAT_CODE_FIRST +}; + +struct audio_mode { + /* ucData[0] [6:3] */ + enum audio_format_code format_code; + /* ucData[0] [2:0] */ + uint8_t channel_count; + /* ucData[1] */ + union audio_sample_rates sample_rates; + union { + /* for LPCM */ + uint8_t sample_size; + /* for Audio Formats 2-8 (Max bit rate divided by 8 kHz) */ + uint8_t max_bit_rate; + /* for Audio Formats 9-15 */ + uint8_t vendor_specific; + }; +}; + +struct audio_info { + struct audio_info_flags flags; + uint32_t video_latency; + uint32_t audio_latency; + uint32_t display_index; + uint8_t display_name[AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS]; + uint32_t manufacture_id; + uint32_t product_id; + /* PortID used for ContainerID when defined */ + uint32_t port_id[2]; + uint32_t mode_count; + /* this field must be last in this struct */ + struct audio_mode modes[DC_MAX_AUDIO_DESC_COUNT]; +}; + +struct freesync_context { + bool supported; + bool enabled; + bool active; + + unsigned int min_refresh_in_micro_hz; + unsigned int nominal_refresh_in_micro_hz; +}; + +struct colorspace_transform { + struct fixed31_32 matrix[12]; + bool enable_remap; +}; + +struct csc_transform { + uint16_t matrix[12]; + bool enable_adjustment; +}; + +struct psr_caps { + /* These parameters are from PSR capabilities reported by Sink DPCD */ + unsigned char psr_version; + unsigned int psr_rfb_setup_time; + bool psr_exit_link_training_required; + + /* These parameters are calculated in Driver, + * based on display timing and Sink capabilities. + * If VBLANK region is too small and Sink takes a long time + * to set up RFB, it may take an extra frame to enter PSR state. + */ + bool psr_frame_capture_indication_req; + unsigned int psr_sdp_transmit_line_num_deadline; +}; + +#endif /* DC_TYPES_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce/Makefile b/drivers/gpu/drm/amd/display/dc/dce/Makefile new file mode 100644 index 000000000000..bfca38170329 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/Makefile @@ -0,0 +1,14 @@ +# +# Makefile for common 'dce' logic +# HW object file under this folder follow similar pattern for HW programming +# - register offset and/or shift + mask stored in the dec_hw struct +# - register programming through common macros that look up register +# offset/shift/mask stored in dce_hw struct + +DCE = dce_audio.o dce_stream_encoder.o dce_link_encoder.o dce_hwseq.o \ +dce_mem_input.o dce_clock_source.o dce_scl_filters.o dce_transform.o + + +AMD_DAL_DCE = $(addprefix $(AMDDALPATH)/dc/dce/,$(DCE)) + +AMD_DISPLAY_FILES += $(AMD_DAL_DCE) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c new file mode 100644 index 000000000000..dc44053e8575 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c @@ -0,0 +1,920 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "reg_helper.h" +#include "dce_audio.h" +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" + +#define DCE_AUD(audio)\ + container_of(audio, struct dce_audio, base) + +#define CTX \ + aud->base.ctx +#define REG(reg)\ + (aud->regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + aud->shifts->field_name, aud->masks->field_name + +#define IX_REG(reg)\ + ix ## reg + +#define AZ_REG_READ(reg_name) \ + read_indirect_azalia_reg(audio, IX_REG(reg_name)) + +#define AZ_REG_WRITE(reg_name, value) \ + write_indirect_azalia_reg(audio, IX_REG(reg_name), value) + +static void write_indirect_azalia_reg(struct audio *audio, + uint32_t reg_index, + uint32_t reg_data) +{ + struct dce_audio *aud = DCE_AUD(audio); + + /* AZALIA_F0_CODEC_ENDPOINT_INDEX endpoint index */ + REG_SET(AZALIA_F0_CODEC_ENDPOINT_INDEX, 0, + AZALIA_ENDPOINT_REG_INDEX, reg_index); + + /* AZALIA_F0_CODEC_ENDPOINT_DATA endpoint data */ + REG_SET(AZALIA_F0_CODEC_ENDPOINT_DATA, 0, + AZALIA_ENDPOINT_REG_DATA, reg_data); + + dm_logger_write(CTX->logger, LOG_HW_AUDIO, + "AUDIO:write_indirect_azalia_reg: index: %u data: %u\n", + reg_index, reg_data); +} + +static uint32_t read_indirect_azalia_reg(struct audio *audio, uint32_t reg_index) +{ + struct dce_audio *aud = DCE_AUD(audio); + + uint32_t value = 0; + + /* AZALIA_F0_CODEC_ENDPOINT_INDEX endpoint index */ + REG_SET(AZALIA_F0_CODEC_ENDPOINT_INDEX, 0, + AZALIA_ENDPOINT_REG_INDEX, reg_index); + + /* AZALIA_F0_CODEC_ENDPOINT_DATA endpoint data */ + value = REG_READ(AZALIA_F0_CODEC_ENDPOINT_DATA); + + dm_logger_write(CTX->logger, LOG_HW_AUDIO, + "AUDIO:read_indirect_azalia_reg: index: %u data: %u\n", + reg_index, value); + + return value; +} + +static bool is_audio_format_supported( + const struct audio_info *audio_info, + enum audio_format_code audio_format_code, + uint32_t *format_index) +{ + uint32_t index; + uint32_t max_channe_index = 0; + bool found = false; + + if (audio_info == NULL) + return found; + + /* pass through whole array */ + for (index = 0; index < audio_info->mode_count; index++) { + if (audio_info->modes[index].format_code == audio_format_code) { + if (found) { + /* format has multiply entries, choose one with + * highst number of channels */ + if (audio_info->modes[index].channel_count > + audio_info->modes[max_channe_index].channel_count) { + max_channe_index = index; + } + } else { + /* format found, save it's index */ + found = true; + max_channe_index = index; + } + } + } + + /* return index */ + if (found && format_index != NULL) + *format_index = max_channe_index; + + return found; +} + +/*For HDMI, calculate if specified sample rates can fit into a given timing */ +static void check_audio_bandwidth_hdmi( + const struct audio_crtc_info *crtc_info, + uint32_t channel_count, + union audio_sample_rates *sample_rates) +{ + uint32_t samples; + uint32_t h_blank; + bool limit_freq_to_48_khz = false; + bool limit_freq_to_88_2_khz = false; + bool limit_freq_to_96_khz = false; + bool limit_freq_to_174_4_khz = false; + + /* For two channels supported return whatever sink support,unmodified*/ + if (channel_count > 2) { + + /* Based on HDMI spec 1.3 Table 7.5 */ + if ((crtc_info->requested_pixel_clock <= 27000) && + (crtc_info->v_active <= 576) && + !(crtc_info->interlaced) && + !(crtc_info->pixel_repetition == 2 || + crtc_info->pixel_repetition == 4)) { + limit_freq_to_48_khz = true; + + } else if ((crtc_info->requested_pixel_clock <= 27000) && + (crtc_info->v_active <= 576) && + (crtc_info->interlaced) && + (crtc_info->pixel_repetition == 2)) { + limit_freq_to_88_2_khz = true; + + } else if ((crtc_info->requested_pixel_clock <= 54000) && + (crtc_info->v_active <= 576) && + !(crtc_info->interlaced)) { + limit_freq_to_174_4_khz = true; + } + } + + /* Also do some calculation for the available Audio Bandwidth for the + * 8 ch (i.e. for the Layout 1 => ch > 2) + */ + h_blank = crtc_info->h_total - crtc_info->h_active; + + if (crtc_info->pixel_repetition) + h_blank *= crtc_info->pixel_repetition; + + /*based on HDMI spec 1.3 Table 7.5 */ + h_blank -= 58; + /*for Control Period */ + h_blank -= 16; + + samples = h_blank * 10; + /* Number of Audio Packets (multiplied by 10) per Line (for 8 ch number + * of Audio samples per line multiplied by 10 - Layout 1) + */ + samples /= 32; + samples *= crtc_info->v_active; + /*Number of samples multiplied by 10, per second */ + samples *= crtc_info->refresh_rate; + /*Number of Audio samples per second */ + samples /= 10; + + /* @todo do it after deep color is implemented + * 8xx - deep color bandwidth scaling + * Extra bandwidth is avaliable in deep color b/c link runs faster than + * pixel rate. This has the effect of allowing more tmds characters to + * be transmitted during blank + */ + + switch (crtc_info->color_depth) { + case COLOR_DEPTH_888: + samples *= 4; + break; + case COLOR_DEPTH_101010: + samples *= 5; + break; + case COLOR_DEPTH_121212: + samples *= 6; + break; + default: + samples *= 4; + break; + } + + samples /= 4; + + /*check limitation*/ + if (samples < 88200) + limit_freq_to_48_khz = true; + else if (samples < 96000) + limit_freq_to_88_2_khz = true; + else if (samples < 176400) + limit_freq_to_96_khz = true; + else if (samples < 192000) + limit_freq_to_174_4_khz = true; + + if (sample_rates != NULL) { + /* limit frequencies */ + if (limit_freq_to_174_4_khz) + sample_rates->rate.RATE_192 = 0; + + if (limit_freq_to_96_khz) { + sample_rates->rate.RATE_192 = 0; + sample_rates->rate.RATE_176_4 = 0; + } + if (limit_freq_to_88_2_khz) { + sample_rates->rate.RATE_192 = 0; + sample_rates->rate.RATE_176_4 = 0; + sample_rates->rate.RATE_96 = 0; + } + if (limit_freq_to_48_khz) { + sample_rates->rate.RATE_192 = 0; + sample_rates->rate.RATE_176_4 = 0; + sample_rates->rate.RATE_96 = 0; + sample_rates->rate.RATE_88_2 = 0; + } + } +} + +/*For DP SST, calculate if specified sample rates can fit into a given timing */ +static void check_audio_bandwidth_dpsst( + const struct audio_crtc_info *crtc_info, + uint32_t channel_count, + union audio_sample_rates *sample_rates) +{ + /* do nothing */ +} + +/*For DP MST, calculate if specified sample rates can fit into a given timing */ +static void check_audio_bandwidth_dpmst( + const struct audio_crtc_info *crtc_info, + uint32_t channel_count, + union audio_sample_rates *sample_rates) +{ + /* do nothing */ +} + +static void check_audio_bandwidth( + const struct audio_crtc_info *crtc_info, + uint32_t channel_count, + enum signal_type signal, + union audio_sample_rates *sample_rates) +{ + switch (signal) { + case SIGNAL_TYPE_HDMI_TYPE_A: + check_audio_bandwidth_hdmi( + crtc_info, channel_count, sample_rates); + break; + case SIGNAL_TYPE_EDP: + case SIGNAL_TYPE_DISPLAY_PORT: + check_audio_bandwidth_dpsst( + crtc_info, channel_count, sample_rates); + break; + case SIGNAL_TYPE_DISPLAY_PORT_MST: + check_audio_bandwidth_dpmst( + crtc_info, channel_count, sample_rates); + break; + default: + break; + } +} + +/* expose/not expose HBR capability to Audio driver */ +static void set_high_bit_rate_capable( + struct audio *audio, + bool capable) +{ + uint32_t value = 0; + + /* set high bit rate audio capable*/ + value = AZ_REG_READ(AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_HBR); + + set_reg_field_value(value, capable, + AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_HBR, + HBR_CAPABLE); + + AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_HBR, value); +} + +/* set video latency in in ms/2+1 */ +static void set_video_latency( + struct audio *audio, + int latency_in_ms) +{ + uint32_t value = 0; + + if ((latency_in_ms < 0) || (latency_in_ms > 255)) + return; + + value = AZ_REG_READ(AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC); + + set_reg_field_value(value, latency_in_ms, + AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC, + VIDEO_LIPSYNC); + + AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC, + value); +} + +/* set audio latency in in ms/2+1 */ +static void set_audio_latency( + struct audio *audio, + int latency_in_ms) +{ + uint32_t value = 0; + + if (latency_in_ms < 0) + latency_in_ms = 0; + + if (latency_in_ms > 255) + latency_in_ms = 255; + + value = AZ_REG_READ(AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC); + + set_reg_field_value(value, latency_in_ms, + AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC, + AUDIO_LIPSYNC); + + AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC, + value); +} + +void dce_aud_az_enable(struct audio *audio) +{ + uint32_t value = AZ_REG_READ(AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL); + + if (get_reg_field_value(value, + AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL, + AUDIO_ENABLED) != 1) + set_reg_field_value(value, 1, + AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL, + AUDIO_ENABLED); + + AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL, value); +} + +void dce_aud_az_disable(struct audio *audio) +{ + uint32_t value; + + value = AZ_REG_READ(AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL); + + set_reg_field_value(value, 0, + AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL, + AUDIO_ENABLED); + + AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL, value); +} + +void dce_aud_az_configure( + struct audio *audio, + enum signal_type signal, + const struct audio_crtc_info *crtc_info, + const struct audio_info *audio_info) +{ + struct dce_audio *aud = DCE_AUD(audio); + + uint32_t speakers = audio_info->flags.info.ALLSPEAKERS; + uint32_t value; + uint32_t field = 0; + enum audio_format_code audio_format_code; + uint32_t format_index; + uint32_t index; + bool is_ac3_supported = false; + union audio_sample_rates sample_rate; + uint32_t strlen = 0; + + /* Speaker Allocation */ + /* + uint32_t value; + uint32_t field = 0;*/ + value = AZ_REG_READ(AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER); + + set_reg_field_value(value, + speakers, + AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, + SPEAKER_ALLOCATION); + + /* LFE_PLAYBACK_LEVEL = LFEPBL + * LFEPBL = 0 : Unknown or refer to other information + * LFEPBL = 1 : 0dB playback + * LFEPBL = 2 : +10dB playback + * LFE_BL = 3 : Reserved + */ + set_reg_field_value(value, + 0, + AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, + LFE_PLAYBACK_LEVEL); + /* todo: according to reg spec LFE_PLAYBACK_LEVEL is read only. + * why are we writing to it? DCE8 does not write this */ + + + set_reg_field_value(value, + 0, + AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, + HDMI_CONNECTION); + + set_reg_field_value(value, + 0, + AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, + DP_CONNECTION); + + field = get_reg_field_value(value, + AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, + EXTRA_CONNECTION_INFO); + + field &= ~0x1; + + set_reg_field_value(value, + field, + AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, + EXTRA_CONNECTION_INFO); + + /* set audio for output signal */ + switch (signal) { + case SIGNAL_TYPE_HDMI_TYPE_A: + set_reg_field_value(value, + 1, + AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, + HDMI_CONNECTION); + + break; + + case SIGNAL_TYPE_EDP: + case SIGNAL_TYPE_DISPLAY_PORT: + case SIGNAL_TYPE_DISPLAY_PORT_MST: + set_reg_field_value(value, + 1, + AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, + DP_CONNECTION); + break; + default: + BREAK_TO_DEBUGGER(); + break; + } + + AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, value); + + /* Audio Descriptors */ + /* pass through all formats */ + for (format_index = 0; format_index < AUDIO_FORMAT_CODE_COUNT; + format_index++) { + audio_format_code = + (AUDIO_FORMAT_CODE_FIRST + format_index); + + /* those are unsupported, skip programming */ + if (audio_format_code == AUDIO_FORMAT_CODE_1BITAUDIO || + audio_format_code == AUDIO_FORMAT_CODE_DST) + continue; + + value = 0; + + /* check if supported */ + if (is_audio_format_supported( + audio_info, audio_format_code, &index)) { + const struct audio_mode *audio_mode = + &audio_info->modes[index]; + union audio_sample_rates sample_rates = + audio_mode->sample_rates; + uint8_t byte2 = audio_mode->max_bit_rate; + + /* adjust specific properties */ + switch (audio_format_code) { + case AUDIO_FORMAT_CODE_LINEARPCM: { + check_audio_bandwidth( + crtc_info, + audio_mode->channel_count, + signal, + &sample_rates); + + byte2 = audio_mode->sample_size; + + set_reg_field_value(value, + sample_rates.all, + AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0, + SUPPORTED_FREQUENCIES_STEREO); + } + break; + case AUDIO_FORMAT_CODE_AC3: + is_ac3_supported = true; + break; + case AUDIO_FORMAT_CODE_DOLBYDIGITALPLUS: + case AUDIO_FORMAT_CODE_DTS_HD: + case AUDIO_FORMAT_CODE_MAT_MLP: + case AUDIO_FORMAT_CODE_DST: + case AUDIO_FORMAT_CODE_WMAPRO: + byte2 = audio_mode->vendor_specific; + break; + default: + break; + } + + /* fill audio format data */ + set_reg_field_value(value, + audio_mode->channel_count - 1, + AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0, + MAX_CHANNELS); + + set_reg_field_value(value, + sample_rates.all, + AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0, + SUPPORTED_FREQUENCIES); + + set_reg_field_value(value, + byte2, + AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0, + DESCRIPTOR_BYTE_2); + } /* if */ + + AZ_REG_WRITE( + AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0 + format_index, + value); + } /* for */ + + if (is_ac3_supported) + /* todo: this reg global. why program global register? */ + REG_WRITE(AZALIA_F0_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS, + 0x05); + + /* check for 192khz/8-Ch support for HBR requirements */ + sample_rate.all = 0; + sample_rate.rate.RATE_192 = 1; + + check_audio_bandwidth( + crtc_info, + 8, + signal, + &sample_rate); + + set_high_bit_rate_capable(audio, sample_rate.rate.RATE_192); + + /* Audio and Video Lipsync */ + set_video_latency(audio, audio_info->video_latency); + set_audio_latency(audio, audio_info->audio_latency); + + value = 0; + set_reg_field_value(value, audio_info->manufacture_id, + AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO0, + MANUFACTURER_ID); + + set_reg_field_value(value, audio_info->product_id, + AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO0, + PRODUCT_ID); + + AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO0, + value); + + value = 0; + + /*get display name string length */ + while (audio_info->display_name[strlen++] != '\0') { + if (strlen >= + MAX_HW_AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS) + break; + } + set_reg_field_value(value, strlen, + AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO1, + SINK_DESCRIPTION_LEN); + + AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO1, + value); + + /* + *write the port ID: + *PORT_ID0 = display index + *PORT_ID1 = 16bit BDF + *(format MSB->LSB: 8bit Bus, 5bit Device, 3bit Function) + */ + + value = 0; + + set_reg_field_value(value, audio_info->port_id[0], + AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO2, + PORT_ID0); + + AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO2, value); + + value = 0; + set_reg_field_value(value, audio_info->port_id[1], + AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO3, + PORT_ID1); + + AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO3, value); + + /*write the 18 char monitor string */ + + value = 0; + set_reg_field_value(value, audio_info->display_name[0], + AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4, + DESCRIPTION0); + + set_reg_field_value(value, audio_info->display_name[1], + AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4, + DESCRIPTION1); + + set_reg_field_value(value, audio_info->display_name[2], + AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4, + DESCRIPTION2); + + set_reg_field_value(value, audio_info->display_name[3], + AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4, + DESCRIPTION3); + + AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4, value); + + value = 0; + set_reg_field_value(value, audio_info->display_name[4], + AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5, + DESCRIPTION4); + + set_reg_field_value(value, audio_info->display_name[5], + AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5, + DESCRIPTION5); + + set_reg_field_value(value, audio_info->display_name[6], + AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5, + DESCRIPTION6); + + set_reg_field_value(value, audio_info->display_name[7], + AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5, + DESCRIPTION7); + + AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5, value); + + value = 0; + set_reg_field_value(value, audio_info->display_name[8], + AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6, + DESCRIPTION8); + + set_reg_field_value(value, audio_info->display_name[9], + AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6, + DESCRIPTION9); + + set_reg_field_value(value, audio_info->display_name[10], + AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6, + DESCRIPTION10); + + set_reg_field_value(value, audio_info->display_name[11], + AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6, + DESCRIPTION11); + + AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6, value); + + value = 0; + set_reg_field_value(value, audio_info->display_name[12], + AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7, + DESCRIPTION12); + + set_reg_field_value(value, audio_info->display_name[13], + AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7, + DESCRIPTION13); + + set_reg_field_value(value, audio_info->display_name[14], + AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7, + DESCRIPTION14); + + set_reg_field_value(value, audio_info->display_name[15], + AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7, + DESCRIPTION15); + + AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7, value); + + value = 0; + set_reg_field_value(value, audio_info->display_name[16], + AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO8, + DESCRIPTION16); + + set_reg_field_value(value, audio_info->display_name[17], + AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO8, + DESCRIPTION17); + + AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO8, value); +} + +/* +* todo: wall clk related functionality probably belong to clock_src. +*/ + +/* search pixel clock value for Azalia HDMI Audio */ +static bool get_azalia_clock_info_hdmi( + uint32_t crtc_pixel_clock_in_khz, + uint32_t actual_pixel_clock_in_khz, + struct azalia_clock_info *azalia_clock_info) +{ + if (azalia_clock_info == NULL) + return false; + + /* audio_dto_phase= 24 * 10,000; + * 24MHz in [100Hz] units */ + azalia_clock_info->audio_dto_phase = + 24 * 10000; + + /* audio_dto_module = PCLKFrequency * 10,000; + * [khz] -> [100Hz] */ + azalia_clock_info->audio_dto_module = + actual_pixel_clock_in_khz * 10; + + return true; +} + +static bool get_azalia_clock_info_dp( + uint32_t requested_pixel_clock_in_khz, + const struct audio_pll_info *pll_info, + struct azalia_clock_info *azalia_clock_info) +{ + if (pll_info == NULL || azalia_clock_info == NULL) + return false; + + /* Reported dpDtoSourceClockInkhz value for + * DCE8 already adjusted for SS, do not need any + * adjustment here anymore + */ + + /*audio_dto_phase = 24 * 10,000; + * 24MHz in [100Hz] units */ + azalia_clock_info->audio_dto_phase = 24 * 10000; + + /*audio_dto_module = dpDtoSourceClockInkhz * 10,000; + * [khz] ->[100Hz] */ + azalia_clock_info->audio_dto_module = + pll_info->dp_dto_source_clock_in_khz * 10; + + return true; +} + +void dce_aud_wall_dto_setup( + struct audio *audio, + enum signal_type signal, + const struct audio_crtc_info *crtc_info, + const struct audio_pll_info *pll_info) +{ + struct dce_audio *aud = DCE_AUD(audio); + + struct azalia_clock_info clock_info = { 0 }; + + if (dc_is_hdmi_signal(signal)) { + uint32_t src_sel; + + /*DTO0 Programming goal: + -generate 24MHz, 128*Fs from 24MHz + -use DTO0 when an active HDMI port is connected + (optionally a DP is connected) */ + + /* calculate DTO settings */ + get_azalia_clock_info_hdmi( + crtc_info->requested_pixel_clock, + crtc_info->calculated_pixel_clock, + &clock_info); + + /* On TN/SI, Program DTO source select and DTO select before + programming DTO modulo and DTO phase. These bits must be + programmed first, otherwise there will be no HDMI audio at boot + up. This is a HW sequence change (different from old ASICs). + Caution when changing this programming sequence. + + HDMI enabled, using DTO0 + program master CRTC for DTO0 */ + src_sel = pll_info->dto_source - DTO_SOURCE_ID0; + REG_UPDATE_2(DCCG_AUDIO_DTO_SOURCE, + DCCG_AUDIO_DTO0_SOURCE_SEL, src_sel, + DCCG_AUDIO_DTO_SEL, 0); + + /* module */ + REG_UPDATE(DCCG_AUDIO_DTO0_MODULE, + DCCG_AUDIO_DTO0_MODULE, clock_info.audio_dto_module); + + /* phase */ + REG_UPDATE(DCCG_AUDIO_DTO0_PHASE, + DCCG_AUDIO_DTO0_PHASE, clock_info.audio_dto_phase); + } else { + /*DTO1 Programming goal: + -generate 24MHz, 512*Fs, 128*Fs from 24MHz + -default is to used DTO1, and switch to DTO0 when an audio + master HDMI port is connected + -use as default for DP + + calculate DTO settings */ + get_azalia_clock_info_dp( + crtc_info->requested_pixel_clock, + pll_info, + &clock_info); + + /* Program DTO select before programming DTO modulo and DTO + phase. default to use DTO1 */ + + REG_UPDATE(DCCG_AUDIO_DTO_SOURCE, + DCCG_AUDIO_DTO_SEL, 1); + + REG_UPDATE(DCCG_AUDIO_DTO_SOURCE, + DCCG_AUDIO_DTO_SEL, 1); + /* DCCG_AUDIO_DTO2_USE_512FBR_DTO, 1) + * Select 512fs for DP TODO: web register definition + * does not match register header file + * DCE11 version it's commented out while DCE8 it's set to 1 + */ + + /* module */ + REG_UPDATE(DCCG_AUDIO_DTO1_MODULE, + DCCG_AUDIO_DTO1_MODULE, clock_info.audio_dto_module); + + /* phase */ + REG_UPDATE(DCCG_AUDIO_DTO1_PHASE, + DCCG_AUDIO_DTO1_PHASE, clock_info.audio_dto_phase); + + /* DAL2 code separate DCCG_AUDIO_DTO_SEL and + DCCG_AUDIO_DTO2_USE_512FBR_DTO programming into two different + location. merge together should not hurt */ + /*value.bits.DCCG_AUDIO_DTO2_USE_512FBR_DTO = 1; + dal_write_reg(mmDCCG_AUDIO_DTO_SOURCE, value);*/ + } +} + +bool dce_aud_endpoint_valid( + struct audio *audio) +{ + uint32_t value; + uint32_t port_connectivity; + + value = AZ_REG_READ( + AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT); + + port_connectivity = get_reg_field_value(value, + AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT, + PORT_CONNECTIVITY); + + return !(port_connectivity == 1); +} + +/* initialize HW state */ +void dce_aud_hw_init( + struct audio *audio) +{ + struct dce_audio *aud = DCE_AUD(audio); + + /* we only need to program the following registers once, so we only do + it for the inst 0*/ + if (audio->inst != 0) + return; + + /* Suport R5 - 32khz + * Suport R6 - 44.1khz + * Suport R7 - 48khz + */ + REG_UPDATE(AZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES, + AUDIO_RATE_CAPABILITIES, 0x70); + + /*Keep alive bit to verify HW block in BU. */ + REG_UPDATE_2(AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES, + CLKSTOP, 1, + EPSS, 1); +} + +static const struct audio_funcs funcs = { + .endpoint_valid = dce_aud_endpoint_valid, + .hw_init = dce_aud_hw_init, + .wall_dto_setup = dce_aud_wall_dto_setup, + .az_enable = dce_aud_az_enable, + .az_disable = dce_aud_az_disable, + .az_configure = dce_aud_az_configure, + .destroy = dce_aud_destroy, +}; + +void dce_aud_destroy(struct audio **audio) +{ + dm_free(*audio); + *audio = NULL; +} + +struct audio *dce_audio_create( + struct dc_context *ctx, + unsigned int inst, + const struct dce_audio_registers *reg, + const struct dce_audio_shift *shifts, + const struct dce_aduio_mask *masks + ) +{ + struct dce_audio *audio = dm_alloc(sizeof(*audio)); + + if (audio == NULL) { + ASSERT_CRITICAL(audio); + return NULL; + } + + audio->base.ctx = ctx; + audio->base.inst = inst; + audio->base.funcs = &funcs; + + audio->regs = reg; + audio->shifts = shifts; + audio->masks = masks; + + return &audio->base; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.h b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.h new file mode 100644 index 000000000000..bf97cd8c8221 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.h @@ -0,0 +1,145 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef __DAL_AUDIO_DCE_110_H__ +#define __DAL_AUDIO_DCE_110_H__ + +#include "audio.h" + +#define AUD_COMMON_REG_LIST(id)\ + SRI(AZALIA_F0_CODEC_ENDPOINT_INDEX, AZF0ENDPOINT, id),\ + SRI(AZALIA_F0_CODEC_ENDPOINT_DATA, AZF0ENDPOINT, id),\ + SR(AZALIA_F0_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS),\ + SR(AZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES),\ + SR(AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES),\ + SR(DCCG_AUDIO_DTO_SOURCE),\ + SR(DCCG_AUDIO_DTO0_MODULE),\ + SR(DCCG_AUDIO_DTO0_PHASE),\ + SR(DCCG_AUDIO_DTO1_MODULE),\ + SR(DCCG_AUDIO_DTO1_PHASE) + + + /* set field name */ +#define SF(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + + +#define AUD_COMMON_MASK_SH_LIST_BASE(mask_sh)\ + SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO0_SOURCE_SEL, mask_sh),\ + SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO_SEL, mask_sh),\ + SF(DCCG_AUDIO_DTO0_MODULE, DCCG_AUDIO_DTO0_MODULE, mask_sh),\ + SF(DCCG_AUDIO_DTO0_PHASE, DCCG_AUDIO_DTO0_PHASE, mask_sh),\ + SF(DCCG_AUDIO_DTO0_MODULE, DCCG_AUDIO_DTO0_MODULE, mask_sh),\ + SF(DCCG_AUDIO_DTO0_PHASE, DCCG_AUDIO_DTO0_PHASE, mask_sh),\ + SF(AZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES, AUDIO_RATE_CAPABILITIES, mask_sh),\ + SF(AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES, CLKSTOP, mask_sh),\ + SF(AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES, EPSS, mask_sh) + +#define AUD_COMMON_MASK_SH_LIST(mask_sh)\ + AUD_COMMON_MASK_SH_LIST_BASE(mask_sh),\ + SF(AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\ + SF(AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh) + + +struct dce_audio_registers { + uint32_t AZALIA_F0_CODEC_ENDPOINT_INDEX; + uint32_t AZALIA_F0_CODEC_ENDPOINT_DATA; + + uint32_t AZALIA_F0_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS; + uint32_t AZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES; + uint32_t AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES; + + uint32_t DCCG_AUDIO_DTO_SOURCE; + uint32_t DCCG_AUDIO_DTO0_MODULE; + uint32_t DCCG_AUDIO_DTO0_PHASE; + uint32_t DCCG_AUDIO_DTO1_MODULE; + uint32_t DCCG_AUDIO_DTO1_PHASE; + + uint32_t AUDIO_RATE_CAPABILITIES; +}; + +struct dce_audio_shift { + uint8_t AZALIA_ENDPOINT_REG_INDEX; + uint8_t AZALIA_ENDPOINT_REG_DATA; + + uint8_t AUDIO_RATE_CAPABILITIES; + uint8_t CLKSTOP; + uint8_t EPSS; + + uint8_t DCCG_AUDIO_DTO0_SOURCE_SEL; + uint8_t DCCG_AUDIO_DTO_SEL; + uint8_t DCCG_AUDIO_DTO0_MODULE; + uint8_t DCCG_AUDIO_DTO0_PHASE; + uint8_t DCCG_AUDIO_DTO1_MODULE; + uint8_t DCCG_AUDIO_DTO1_PHASE; +}; + +struct dce_aduio_mask { + uint32_t AZALIA_ENDPOINT_REG_INDEX; + uint32_t AZALIA_ENDPOINT_REG_DATA; + + uint32_t AUDIO_RATE_CAPABILITIES; + uint32_t CLKSTOP; + uint32_t EPSS; + + uint32_t DCCG_AUDIO_DTO0_SOURCE_SEL; + uint32_t DCCG_AUDIO_DTO_SEL; + uint32_t DCCG_AUDIO_DTO0_MODULE; + uint32_t DCCG_AUDIO_DTO0_PHASE; + uint32_t DCCG_AUDIO_DTO1_MODULE; + uint32_t DCCG_AUDIO_DTO1_PHASE; +}; + +struct dce_audio { + struct audio base; + const struct dce_audio_registers *regs; + const struct dce_audio_shift *shifts; + const struct dce_aduio_mask *masks; +}; + +struct audio *dce_audio_create( + struct dc_context *ctx, + unsigned int inst, + const struct dce_audio_registers *reg, + const struct dce_audio_shift *shifts, + const struct dce_aduio_mask *masks); + +void dce_aud_destroy(struct audio **audio); + +void dce_aud_hw_init(struct audio *audio); + +void dce_aud_az_enable(struct audio *audio); +void dce_aud_az_disable(struct audio *audio); + +void dce_aud_az_configure(struct audio *audio, + enum signal_type signal, + const struct audio_crtc_info *crtc_info, + const struct audio_info *audio_info); + +void dce_aud_wall_dto_setup(struct audio *audio, + enum signal_type signal, + const struct audio_crtc_info *crtc_info, + const struct audio_pll_info *pll_info); + +#endif /*__DAL_AUDIO_DCE_110_H__*/ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c new file mode 100644 index 000000000000..80ac5d9efa71 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -0,0 +1,1264 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + + +#include "dc_types.h" +#include "core_types.h" + +#include "include/grph_object_id.h" +#include "include/logger_interface.h" + +#include "dce_clock_source.h" + +#include "reg_helper.h" + +#define REG(reg)\ + (clk_src->regs->reg) + +#define CTX \ + clk_src->base.ctx + +#undef FN +#define FN(reg_name, field_name) \ + clk_src->cs_shift->field_name, clk_src->cs_mask->field_name + +#define FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM 6 +#define CALC_PLL_CLK_SRC_ERR_TOLERANCE 1 +#define MAX_PLL_CALC_ERROR 0xFFFFFFFF + +static const struct spread_spectrum_data *get_ss_data_entry( + struct dce110_clk_src *clk_src, + enum signal_type signal, + uint32_t pix_clk_khz) +{ + + uint32_t entrys_num; + uint32_t i; + struct spread_spectrum_data *ss_parm = NULL; + struct spread_spectrum_data *ret = NULL; + + switch (signal) { + case SIGNAL_TYPE_DVI_SINGLE_LINK: + case SIGNAL_TYPE_DVI_DUAL_LINK: + ss_parm = clk_src->dvi_ss_params; + entrys_num = clk_src->dvi_ss_params_cnt; + break; + + case SIGNAL_TYPE_HDMI_TYPE_A: + ss_parm = clk_src->hdmi_ss_params; + entrys_num = clk_src->hdmi_ss_params_cnt; + break; + + case SIGNAL_TYPE_DISPLAY_PORT: + case SIGNAL_TYPE_DISPLAY_PORT_MST: + case SIGNAL_TYPE_EDP: + case SIGNAL_TYPE_VIRTUAL: + ss_parm = clk_src->dp_ss_params; + entrys_num = clk_src->dp_ss_params_cnt; + break; + + default: + ss_parm = NULL; + entrys_num = 0; + break; + } + + if (ss_parm == NULL) + return ret; + + for (i = 0; i < entrys_num; ++i, ++ss_parm) { + if (ss_parm->freq_range_khz >= pix_clk_khz) { + ret = ss_parm; + break; + } + } + + return ret; +} + +/** +* Function: calculate_fb_and_fractional_fb_divider +* +* * DESCRIPTION: Calculates feedback and fractional feedback dividers values +* +*PARAMETERS: +* targetPixelClock Desired frequency in 10 KHz +* ref_divider Reference divider (already known) +* postDivider Post Divider (already known) +* feedback_divider_param Pointer where to store +* calculated feedback divider value +* fract_feedback_divider_param Pointer where to store +* calculated fract feedback divider value +* +*RETURNS: +* It fills the locations pointed by feedback_divider_param +* and fract_feedback_divider_param +* It returns - true if feedback divider not 0 +* - false should never happen) +*/ +static bool calculate_fb_and_fractional_fb_divider( + struct calc_pll_clock_source *calc_pll_cs, + uint32_t target_pix_clk_khz, + uint32_t ref_divider, + uint32_t post_divider, + uint32_t *feedback_divider_param, + uint32_t *fract_feedback_divider_param) +{ + uint64_t feedback_divider; + + feedback_divider = + (uint64_t)(target_pix_clk_khz * ref_divider * post_divider); + feedback_divider *= 10; + /* additional factor, since we divide by 10 afterwards */ + feedback_divider *= (uint64_t)(calc_pll_cs->fract_fb_divider_factor); + feedback_divider = div_u64(feedback_divider, calc_pll_cs->ref_freq_khz); + +/*Round to the number of precision + * The following code replace the old code (ullfeedbackDivider + 5)/10 + * for example if the difference between the number + * of fractional feedback decimal point and the fractional FB Divider precision + * is 2 then the equation becomes (ullfeedbackDivider + 5*100) / (10*100))*/ + + feedback_divider += (uint64_t) + (5 * calc_pll_cs->fract_fb_divider_precision_factor); + feedback_divider = + div_u64(feedback_divider, + calc_pll_cs->fract_fb_divider_precision_factor * 10); + feedback_divider *= (uint64_t) + (calc_pll_cs->fract_fb_divider_precision_factor); + + *feedback_divider_param = + div_u64_rem( + feedback_divider, + calc_pll_cs->fract_fb_divider_factor, + fract_feedback_divider_param); + + if (*feedback_divider_param != 0) + return true; + return false; +} + +/** +*calc_fb_divider_checking_tolerance +* +*DESCRIPTION: Calculates Feedback and Fractional Feedback divider values +* for passed Reference and Post divider, checking for tolerance. +*PARAMETERS: +* pll_settings Pointer to structure +* ref_divider Reference divider (already known) +* postDivider Post Divider (already known) +* tolerance Tolerance for Calculated Pixel Clock to be within +* +*RETURNS: +* It fills the PLLSettings structure with PLL Dividers values +* if calculated values are within required tolerance +* It returns - true if eror is within tolerance +* - false if eror is not within tolerance +*/ +static bool calc_fb_divider_checking_tolerance( + struct calc_pll_clock_source *calc_pll_cs, + struct pll_settings *pll_settings, + uint32_t ref_divider, + uint32_t post_divider, + uint32_t tolerance) +{ + uint32_t feedback_divider; + uint32_t fract_feedback_divider; + uint32_t actual_calculated_clock_khz; + uint32_t abs_err; + uint64_t actual_calc_clk_khz; + + calculate_fb_and_fractional_fb_divider( + calc_pll_cs, + pll_settings->adjusted_pix_clk, + ref_divider, + post_divider, + &feedback_divider, + &fract_feedback_divider); + + /*Actual calculated value*/ + actual_calc_clk_khz = (uint64_t)(feedback_divider * + calc_pll_cs->fract_fb_divider_factor) + + fract_feedback_divider; + actual_calc_clk_khz *= calc_pll_cs->ref_freq_khz; + actual_calc_clk_khz = + div_u64(actual_calc_clk_khz, + ref_divider * post_divider * + calc_pll_cs->fract_fb_divider_factor); + + actual_calculated_clock_khz = (uint32_t)(actual_calc_clk_khz); + + abs_err = (actual_calculated_clock_khz > + pll_settings->adjusted_pix_clk) + ? actual_calculated_clock_khz - + pll_settings->adjusted_pix_clk + : pll_settings->adjusted_pix_clk - + actual_calculated_clock_khz; + + if (abs_err <= tolerance) { + /*found good values*/ + pll_settings->reference_freq = calc_pll_cs->ref_freq_khz; + pll_settings->reference_divider = ref_divider; + pll_settings->feedback_divider = feedback_divider; + pll_settings->fract_feedback_divider = fract_feedback_divider; + pll_settings->pix_clk_post_divider = post_divider; + pll_settings->calculated_pix_clk = + actual_calculated_clock_khz; + pll_settings->vco_freq = + actual_calculated_clock_khz * post_divider; + return true; + } + return false; +} + +static bool calc_pll_dividers_in_range( + struct calc_pll_clock_source *calc_pll_cs, + struct pll_settings *pll_settings, + uint32_t min_ref_divider, + uint32_t max_ref_divider, + uint32_t min_post_divider, + uint32_t max_post_divider, + uint32_t err_tolerance) +{ + uint32_t ref_divider; + uint32_t post_divider; + uint32_t tolerance; + +/* This is err_tolerance / 10000 = 0.0025 - acceptable error of 0.25% + * This is errorTolerance / 10000 = 0.0001 - acceptable error of 0.01%*/ + tolerance = (pll_settings->adjusted_pix_clk * err_tolerance) / + 10000; + if (tolerance < CALC_PLL_CLK_SRC_ERR_TOLERANCE) + tolerance = CALC_PLL_CLK_SRC_ERR_TOLERANCE; + + for ( + post_divider = max_post_divider; + post_divider >= min_post_divider; + --post_divider) { + for ( + ref_divider = min_ref_divider; + ref_divider <= max_ref_divider; + ++ref_divider) { + if (calc_fb_divider_checking_tolerance( + calc_pll_cs, + pll_settings, + ref_divider, + post_divider, + tolerance)) { + return true; + } + } + } + + return false; +} + +static uint32_t calculate_pixel_clock_pll_dividers( + struct calc_pll_clock_source *calc_pll_cs, + struct pll_settings *pll_settings) +{ + uint32_t err_tolerance; + uint32_t min_post_divider; + uint32_t max_post_divider; + uint32_t min_ref_divider; + uint32_t max_ref_divider; + + if (pll_settings->adjusted_pix_clk == 0) { + dm_logger_write(calc_pll_cs->ctx->logger, LOG_ERROR, + "%s Bad requested pixel clock", __func__); + return MAX_PLL_CALC_ERROR; + } + +/* 1) Find Post divider ranges */ + if (pll_settings->pix_clk_post_divider) { + min_post_divider = pll_settings->pix_clk_post_divider; + max_post_divider = pll_settings->pix_clk_post_divider; + } else { + min_post_divider = calc_pll_cs->min_pix_clock_pll_post_divider; + if (min_post_divider * pll_settings->adjusted_pix_clk < + calc_pll_cs->min_vco_khz) { + min_post_divider = calc_pll_cs->min_vco_khz / + pll_settings->adjusted_pix_clk; + if ((min_post_divider * + pll_settings->adjusted_pix_clk) < + calc_pll_cs->min_vco_khz) + min_post_divider++; + } + + max_post_divider = calc_pll_cs->max_pix_clock_pll_post_divider; + if (max_post_divider * pll_settings->adjusted_pix_clk + > calc_pll_cs->max_vco_khz) + max_post_divider = calc_pll_cs->max_vco_khz / + pll_settings->adjusted_pix_clk; + } + +/* 2) Find Reference divider ranges + * When SS is enabled, or for Display Port even without SS, + * pll_settings->referenceDivider is not zero. + * So calculate PPLL FB and fractional FB divider + * using the passed reference divider*/ + + if (pll_settings->reference_divider) { + min_ref_divider = pll_settings->reference_divider; + max_ref_divider = pll_settings->reference_divider; + } else { + min_ref_divider = ((calc_pll_cs->ref_freq_khz + / calc_pll_cs->max_pll_input_freq_khz) + > calc_pll_cs->min_pll_ref_divider) + ? calc_pll_cs->ref_freq_khz + / calc_pll_cs->max_pll_input_freq_khz + : calc_pll_cs->min_pll_ref_divider; + + max_ref_divider = ((calc_pll_cs->ref_freq_khz + / calc_pll_cs->min_pll_input_freq_khz) + < calc_pll_cs->max_pll_ref_divider) + ? calc_pll_cs->ref_freq_khz / + calc_pll_cs->min_pll_input_freq_khz + : calc_pll_cs->max_pll_ref_divider; + } + +/* If some parameters are invalid we could have scenario when "min">"max" + * which produced endless loop later. + * We should investigate why we get the wrong parameters. + * But to follow the similar logic when "adjustedPixelClock" is set to be 0 + * it is better to return here than cause system hang/watchdog timeout later. + * ## SVS Wed 15 Jul 2009 */ + + if (min_post_divider > max_post_divider) { + dm_logger_write(calc_pll_cs->ctx->logger, LOG_ERROR, + "%s Post divider range is invalid", __func__); + return MAX_PLL_CALC_ERROR; + } + + if (min_ref_divider > max_ref_divider) { + dm_logger_write(calc_pll_cs->ctx->logger, LOG_ERROR, + "%s Reference divider range is invalid", __func__); + return MAX_PLL_CALC_ERROR; + } + +/* 3) Try to find PLL dividers given ranges + * starting with minimal error tolerance. + * Increase error tolerance until PLL dividers found*/ + err_tolerance = MAX_PLL_CALC_ERROR; + + while (!calc_pll_dividers_in_range( + calc_pll_cs, + pll_settings, + min_ref_divider, + max_ref_divider, + min_post_divider, + max_post_divider, + err_tolerance)) + err_tolerance += (err_tolerance > 10) + ? (err_tolerance / 10) + : 1; + + return err_tolerance; +} + +static bool pll_adjust_pix_clk( + struct dce110_clk_src *clk_src, + struct pixel_clk_params *pix_clk_params, + struct pll_settings *pll_settings) +{ + uint32_t actual_pix_clk_khz = 0; + uint32_t requested_clk_khz = 0; + struct bp_adjust_pixel_clock_parameters bp_adjust_pixel_clock_params = { + 0 }; + enum bp_result bp_result; + + switch (pix_clk_params->signal_type) { + case SIGNAL_TYPE_HDMI_TYPE_A: { + requested_clk_khz = pix_clk_params->requested_pix_clk; + + switch (pix_clk_params->color_depth) { + case COLOR_DEPTH_101010: + requested_clk_khz = (requested_clk_khz * 5) >> 2; + break; /* x1.25*/ + case COLOR_DEPTH_121212: + requested_clk_khz = (requested_clk_khz * 6) >> 2; + break; /* x1.5*/ + case COLOR_DEPTH_161616: + requested_clk_khz = requested_clk_khz * 2; + break; /* x2.0*/ + default: + break; + } + + actual_pix_clk_khz = requested_clk_khz; + } + break; + + case SIGNAL_TYPE_DISPLAY_PORT: + case SIGNAL_TYPE_DISPLAY_PORT_MST: + case SIGNAL_TYPE_EDP: + requested_clk_khz = pix_clk_params->requested_sym_clk; + actual_pix_clk_khz = pix_clk_params->requested_pix_clk; + break; + + default: + requested_clk_khz = pix_clk_params->requested_pix_clk; + actual_pix_clk_khz = pix_clk_params->requested_pix_clk; + break; + } + + bp_adjust_pixel_clock_params.pixel_clock = requested_clk_khz; + bp_adjust_pixel_clock_params. + encoder_object_id = pix_clk_params->encoder_object_id; + bp_adjust_pixel_clock_params.signal_type = pix_clk_params->signal_type; + bp_adjust_pixel_clock_params. + ss_enable = pix_clk_params->flags.ENABLE_SS; + bp_result = clk_src->bios->funcs->adjust_pixel_clock( + clk_src->bios, &bp_adjust_pixel_clock_params); + if (bp_result == BP_RESULT_OK) { + pll_settings->actual_pix_clk = actual_pix_clk_khz; + pll_settings->adjusted_pix_clk = + bp_adjust_pixel_clock_params.adjusted_pixel_clock; + pll_settings->reference_divider = + bp_adjust_pixel_clock_params.reference_divider; + pll_settings->pix_clk_post_divider = + bp_adjust_pixel_clock_params.pixel_clock_post_divider; + + return true; + } + + return false; +} + +/** + * Calculate PLL Dividers for given Clock Value. + * First will call VBIOS Adjust Exec table to check if requested Pixel clock + * will be Adjusted based on usage. + * Then it will calculate PLL Dividers for this Adjusted clock using preferred + * method (Maximum VCO frequency). + * + * \return + * Calculation error in units of 0.01% + */ + +static uint32_t dce110_get_pix_clk_dividers_helper ( + struct dce110_clk_src *clk_src, + struct pll_settings *pll_settings, + struct pixel_clk_params *pix_clk_params) +{ + uint32_t addr = 0; + uint32_t value = 0; + uint32_t field = 0; + uint32_t pll_calc_error = MAX_PLL_CALC_ERROR; + + /* Check if reference clock is external (not pcie/xtalin) + * HW Dce80 spec: + * 00 - PCIE_REFCLK, 01 - XTALIN, 02 - GENERICA, 03 - GENERICB + * 04 - HSYNCA, 05 - GENLK_CLK, 06 - PCIE_REFCLK, 07 - DVOCLK0 */ + value = REG_READ(PLL_CNTL); + REG_GET(PLL_CNTL, PLL_REF_DIV_SRC, &field); + pll_settings->use_external_clk = (field > 1); + + /* VBIOS by default enables DP SS (spread on IDCLK) for DCE 8.0 always + * (we do not care any more from SI for some older DP Sink which + * does not report SS support, no known issues) */ + if ((pix_clk_params->flags.ENABLE_SS) || + (dc_is_dp_signal(pix_clk_params->signal_type))) { + + const struct spread_spectrum_data *ss_data = get_ss_data_entry( + clk_src, + pix_clk_params->signal_type, + pll_settings->adjusted_pix_clk); + + if (NULL != ss_data) + pll_settings->ss_percentage = ss_data->percentage; + } + + /* Check VBIOS AdjustPixelClock Exec table */ + if (!pll_adjust_pix_clk(clk_src, pix_clk_params, pll_settings)) { + /* Should never happen, ASSERT and fill up values to be able + * to continue. */ + dm_logger_write(clk_src->base.ctx->logger, LOG_ERROR, + "%s: Failed to adjust pixel clock!!", __func__); + pll_settings->actual_pix_clk = + pix_clk_params->requested_pix_clk; + pll_settings->adjusted_pix_clk = + pix_clk_params->requested_pix_clk; + + if (dc_is_dp_signal(pix_clk_params->signal_type)) + pll_settings->adjusted_pix_clk = 100000; + } + + /* Calculate Dividers */ + if (pix_clk_params->signal_type == SIGNAL_TYPE_HDMI_TYPE_A) + /*Calculate Dividers by HDMI object, no SS case or SS case */ + pll_calc_error = + calculate_pixel_clock_pll_dividers( + &clk_src->calc_pll_hdmi, + pll_settings); + else + /*Calculate Dividers by default object, no SS case or SS case */ + pll_calc_error = + calculate_pixel_clock_pll_dividers( + &clk_src->calc_pll, + pll_settings); + + return pll_calc_error; +} + +static void dce112_get_pix_clk_dividers_helper ( + struct dce110_clk_src *clk_src, + struct pll_settings *pll_settings, + struct pixel_clk_params *pix_clk_params) +{ + uint32_t actualPixelClockInKHz; + + actualPixelClockInKHz = pix_clk_params->requested_pix_clk; + /* Calculate Dividers */ + if (pix_clk_params->signal_type == SIGNAL_TYPE_HDMI_TYPE_A) { + switch (pix_clk_params->color_depth) { + case COLOR_DEPTH_101010: + actualPixelClockInKHz = (actualPixelClockInKHz * 5) >> 2; + break; + case COLOR_DEPTH_121212: + actualPixelClockInKHz = (actualPixelClockInKHz * 6) >> 2; + break; + case COLOR_DEPTH_161616: + actualPixelClockInKHz = actualPixelClockInKHz * 2; + break; + default: + break; + } + } + pll_settings->actual_pix_clk = actualPixelClockInKHz; + pll_settings->adjusted_pix_clk = actualPixelClockInKHz; + pll_settings->calculated_pix_clk = pix_clk_params->requested_pix_clk; +} + +static uint32_t dce110_get_pix_clk_dividers( + struct clock_source *cs, + struct pixel_clk_params *pix_clk_params, + struct pll_settings *pll_settings) +{ + struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(cs); + uint32_t pll_calc_error = MAX_PLL_CALC_ERROR; + + if (pix_clk_params == NULL || pll_settings == NULL + || pix_clk_params->requested_pix_clk == 0) { + dm_logger_write(clk_src->base.ctx->logger, LOG_ERROR, + "%s: Invalid parameters!!\n", __func__); + return pll_calc_error; + } + + memset(pll_settings, 0, sizeof(*pll_settings)); + + if (cs->id == CLOCK_SOURCE_ID_DP_DTO || + cs->id == CLOCK_SOURCE_ID_EXTERNAL) { + pll_settings->adjusted_pix_clk = clk_src->ext_clk_khz; + pll_settings->calculated_pix_clk = clk_src->ext_clk_khz; + pll_settings->actual_pix_clk = + pix_clk_params->requested_pix_clk; + return 0; + } + + switch (cs->ctx->dce_version) { + case DCE_VERSION_8_0: + case DCE_VERSION_10_0: + case DCE_VERSION_11_0: + pll_calc_error = + dce110_get_pix_clk_dividers_helper(clk_src, + pll_settings, pix_clk_params); + break; + case DCE_VERSION_11_2: + dce112_get_pix_clk_dividers_helper(clk_src, + pll_settings, pix_clk_params); + break; + default: + break; + } + + return pll_calc_error; +} + +static bool disable_spread_spectrum(struct dce110_clk_src *clk_src) +{ + enum bp_result result; + struct bp_spread_spectrum_parameters bp_ss_params = {0}; + + bp_ss_params.pll_id = clk_src->base.id; + + /*Call ASICControl to process ATOMBIOS Exec table*/ + result = clk_src->bios->funcs->enable_spread_spectrum_on_ppll( + clk_src->bios, + &bp_ss_params, + false); + + return result == BP_RESULT_OK; +} + +static bool calculate_ss( + const struct pll_settings *pll_settings, + const struct spread_spectrum_data *ss_data, + struct delta_sigma_data *ds_data) +{ + struct fixed32_32 fb_div; + struct fixed32_32 ss_amount; + struct fixed32_32 ss_nslip_amount; + struct fixed32_32 ss_ds_frac_amount; + struct fixed32_32 ss_step_size; + struct fixed32_32 modulation_time; + + if (ds_data == NULL) + return false; + if (ss_data == NULL) + return false; + if (ss_data->percentage == 0) + return false; + if (pll_settings == NULL) + return false; + + memset(ds_data, 0, sizeof(struct delta_sigma_data)); + + /* compute SS_AMOUNT_FBDIV & SS_AMOUNT_NFRAC_SLIP & SS_AMOUNT_DSFRAC*/ + /* 6 decimal point support in fractional feedback divider */ + fb_div = dal_fixed32_32_from_fraction( + pll_settings->fract_feedback_divider, 1000000); + fb_div = dal_fixed32_32_add_int(fb_div, pll_settings->feedback_divider); + + ds_data->ds_frac_amount = 0; + /*spreadSpectrumPercentage is in the unit of .01%, + * so have to divided by 100 * 100*/ + ss_amount = dal_fixed32_32_mul( + fb_div, dal_fixed32_32_from_fraction(ss_data->percentage, + 100 * ss_data->percentage_divider)); + ds_data->feedback_amount = dal_fixed32_32_floor(ss_amount); + + ss_nslip_amount = dal_fixed32_32_sub(ss_amount, + dal_fixed32_32_from_int(ds_data->feedback_amount)); + ss_nslip_amount = dal_fixed32_32_mul_int(ss_nslip_amount, 10); + ds_data->nfrac_amount = dal_fixed32_32_floor(ss_nslip_amount); + + ss_ds_frac_amount = dal_fixed32_32_sub(ss_nslip_amount, + dal_fixed32_32_from_int(ds_data->nfrac_amount)); + ss_ds_frac_amount = dal_fixed32_32_mul_int(ss_ds_frac_amount, 65536); + ds_data->ds_frac_amount = dal_fixed32_32_floor(ss_ds_frac_amount); + + /* compute SS_STEP_SIZE_DSFRAC */ + modulation_time = dal_fixed32_32_from_fraction( + pll_settings->reference_freq * 1000, + pll_settings->reference_divider * ss_data->modulation_freq_hz); + + if (ss_data->flags.CENTER_SPREAD) + modulation_time = dal_fixed32_32_div_int(modulation_time, 4); + else + modulation_time = dal_fixed32_32_div_int(modulation_time, 2); + + ss_step_size = dal_fixed32_32_div(ss_amount, modulation_time); + /* SS_STEP_SIZE_DSFRAC_DEC = Int(SS_STEP_SIZE * 2 ^ 16 * 10)*/ + ss_step_size = dal_fixed32_32_mul_int(ss_step_size, 65536 * 10); + ds_data->ds_frac_size = dal_fixed32_32_floor(ss_step_size); + + return true; +} + +static bool enable_spread_spectrum( + struct dce110_clk_src *clk_src, + enum signal_type signal, struct pll_settings *pll_settings) +{ + struct bp_spread_spectrum_parameters bp_params = {0}; + struct delta_sigma_data d_s_data; + const struct spread_spectrum_data *ss_data = NULL; + + ss_data = get_ss_data_entry( + clk_src, + signal, + pll_settings->calculated_pix_clk); + +/* Pixel clock PLL has been programmed to generate desired pixel clock, + * now enable SS on pixel clock */ +/* TODO is it OK to return true not doing anything ??*/ + if (ss_data != NULL && pll_settings->ss_percentage != 0) { + if (calculate_ss(pll_settings, ss_data, &d_s_data)) { + bp_params.ds.feedback_amount = + d_s_data.feedback_amount; + bp_params.ds.nfrac_amount = + d_s_data.nfrac_amount; + bp_params.ds.ds_frac_size = d_s_data.ds_frac_size; + bp_params.ds_frac_amount = + d_s_data.ds_frac_amount; + bp_params.flags.DS_TYPE = 1; + bp_params.pll_id = clk_src->base.id; + bp_params.percentage = ss_data->percentage; + if (ss_data->flags.CENTER_SPREAD) + bp_params.flags.CENTER_SPREAD = 1; + if (ss_data->flags.EXTERNAL_SS) + bp_params.flags.EXTERNAL_SS = 1; + + if (BP_RESULT_OK != + clk_src->bios->funcs-> + enable_spread_spectrum_on_ppll( + clk_src->bios, + &bp_params, + true)) + return false; + } else + return false; + } + return true; +} + +static void dce110_program_pixel_clk_resync( + struct dce110_clk_src *clk_src, + enum signal_type signal_type, + enum dc_color_depth colordepth) +{ + uint32_t value = 0; + + REG_UPDATE(RESYNC_CNTL, + DCCG_DEEP_COLOR_CNTL1, 0); + /* + 24 bit mode: TMDS clock = 1.0 x pixel clock (1:1) + 30 bit mode: TMDS clock = 1.25 x pixel clock (5:4) + 36 bit mode: TMDS clock = 1.5 x pixel clock (3:2) + 48 bit mode: TMDS clock = 2 x pixel clock (2:1) + */ + if (signal_type != SIGNAL_TYPE_HDMI_TYPE_A) + return; + + switch (colordepth) { + case COLOR_DEPTH_888: + REG_UPDATE(RESYNC_CNTL, + DCCG_DEEP_COLOR_CNTL1, 0); + break; + case COLOR_DEPTH_101010: + REG_UPDATE(RESYNC_CNTL, + DCCG_DEEP_COLOR_CNTL1, 1); + break; + case COLOR_DEPTH_121212: + REG_UPDATE(RESYNC_CNTL, + DCCG_DEEP_COLOR_CNTL1, 2); + break; + case COLOR_DEPTH_161616: + REG_UPDATE(RESYNC_CNTL, + DCCG_DEEP_COLOR_CNTL1, 3); + break; + default: + break; + } +} + +static void dce112_program_pixel_clk_resync( + struct dce110_clk_src *clk_src, + enum signal_type signal_type, + enum dc_color_depth colordepth, + bool enable_ycbcr420) +{ + uint32_t value = 0; + + REG_UPDATE(PIXCLK_RESYNC_CNTL, + PHYPLLA_DCCG_DEEP_COLOR_CNTL, 0); + /* + 24 bit mode: TMDS clock = 1.0 x pixel clock (1:1) + 30 bit mode: TMDS clock = 1.25 x pixel clock (5:4) + 36 bit mode: TMDS clock = 1.5 x pixel clock (3:2) + 48 bit mode: TMDS clock = 2 x pixel clock (2:1) + */ + if (signal_type != SIGNAL_TYPE_HDMI_TYPE_A) + return; + + switch (colordepth) { + case COLOR_DEPTH_888: + REG_UPDATE_2(PIXCLK_RESYNC_CNTL, + PHYPLLA_DCCG_DEEP_COLOR_CNTL, 0, + PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE, enable_ycbcr420); + break; + case COLOR_DEPTH_101010: + REG_UPDATE_2(PIXCLK_RESYNC_CNTL, + PHYPLLA_DCCG_DEEP_COLOR_CNTL, 1, + PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE, enable_ycbcr420); + break; + case COLOR_DEPTH_121212: + REG_UPDATE_2(PIXCLK_RESYNC_CNTL, + PHYPLLA_DCCG_DEEP_COLOR_CNTL, 2, + PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE, enable_ycbcr420); + break; + case COLOR_DEPTH_161616: + REG_UPDATE_2(PIXCLK_RESYNC_CNTL, + PHYPLLA_DCCG_DEEP_COLOR_CNTL, 3, + PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE, enable_ycbcr420); + break; + default: + break; + } +} + +static bool dce110_program_pix_clk( + struct clock_source *clk_src, + struct pixel_clk_params *pix_clk_params, + struct pll_settings *pll_settings) +{ + struct dce110_clk_src *dce110_clk_src = TO_DCE110_CLK_SRC(clk_src); + struct bp_pixel_clock_parameters bp_pc_params = {0}; + + /* First disable SS + * ATOMBIOS will enable by default SS on PLL for DP, + * do not disable it here + */ + if (clk_src->id != CLOCK_SOURCE_ID_EXTERNAL && + !dc_is_dp_signal(pix_clk_params->signal_type) && + clk_src->ctx->dce_version <= DCE_VERSION_11_0) + disable_spread_spectrum(dce110_clk_src); + + /*ATOMBIOS expects pixel rate adjusted by deep color ratio)*/ + bp_pc_params.controller_id = pix_clk_params->controller_id; + bp_pc_params.pll_id = clk_src->id; + bp_pc_params.target_pixel_clock = pll_settings->actual_pix_clk; + bp_pc_params.encoder_object_id = pix_clk_params->encoder_object_id; + bp_pc_params.signal_type = pix_clk_params->signal_type; + + switch (clk_src->ctx->dce_version) { + case DCE_VERSION_11_2: + if (clk_src->id != CLOCK_SOURCE_ID_DP_DTO) { + bp_pc_params.flags.SET_GENLOCK_REF_DIV_SRC = + pll_settings->use_external_clk; + bp_pc_params.flags.SET_XTALIN_REF_SRC = + !pll_settings->use_external_clk; + if (pix_clk_params->flags.SUPPORT_YCBCR420) { + bp_pc_params.target_pixel_clock = pll_settings->actual_pix_clk / 2; + bp_pc_params.flags.SUPPORT_YUV_420 = 1; + } + } + if (dce110_clk_src->bios->funcs->set_pixel_clock( + dce110_clk_src->bios, &bp_pc_params) != BP_RESULT_OK) + return false; + /* Resync deep color DTO */ + if (clk_src->id != CLOCK_SOURCE_ID_DP_DTO) + dce112_program_pixel_clk_resync(dce110_clk_src, + pix_clk_params->signal_type, + pix_clk_params->color_depth, + pix_clk_params->flags.SUPPORT_YCBCR420); + break; + case DCE_VERSION_8_0: + case DCE_VERSION_10_0: + case DCE_VERSION_11_0: + bp_pc_params.reference_divider = pll_settings->reference_divider; + bp_pc_params.feedback_divider = pll_settings->feedback_divider; + bp_pc_params.fractional_feedback_divider = + pll_settings->fract_feedback_divider; + bp_pc_params.pixel_clock_post_divider = + pll_settings->pix_clk_post_divider; + bp_pc_params.flags.SET_EXTERNAL_REF_DIV_SRC = + pll_settings->use_external_clk; + + if (dce110_clk_src->bios->funcs->set_pixel_clock( + dce110_clk_src->bios, &bp_pc_params) != BP_RESULT_OK) + return false; + /* Enable SS + * ATOMBIOS will enable by default SS for DP on PLL ( DP ID clock), + * based on HW display PLL team, SS control settings should be programmed + * during PLL Reset, but they do not have effect + * until SS_EN is asserted.*/ + if (clk_src->id != CLOCK_SOURCE_ID_EXTERNAL + && pix_clk_params->flags.ENABLE_SS && !dc_is_dp_signal( + pix_clk_params->signal_type)) { + + if (!enable_spread_spectrum(dce110_clk_src, + pix_clk_params->signal_type, + pll_settings)) + return false; + /* Resync deep color DTO */ + dce110_program_pixel_clk_resync(dce110_clk_src, + pix_clk_params->signal_type, + pix_clk_params->color_depth); + } + break; + default: + break; + } + + return true; +} + +static bool dce110_clock_source_power_down( + struct clock_source *clk_src) +{ + struct dce110_clk_src *dce110_clk_src = TO_DCE110_CLK_SRC(clk_src); + enum bp_result bp_result; + struct bp_pixel_clock_parameters bp_pixel_clock_params = {0}; + + if (clk_src->dp_clk_src) + return true; + + /* If Pixel Clock is 0 it means Power Down Pll*/ + bp_pixel_clock_params.controller_id = CONTROLLER_ID_UNDEFINED; + bp_pixel_clock_params.pll_id = clk_src->id; + bp_pixel_clock_params.flags.FORCE_PROGRAMMING_OF_PLL = 1; + + /*Call ASICControl to process ATOMBIOS Exec table*/ + bp_result = dce110_clk_src->bios->funcs->set_pixel_clock( + dce110_clk_src->bios, + &bp_pixel_clock_params); + + return bp_result == BP_RESULT_OK; +} + +/*****************************************/ +/* Constructor */ +/*****************************************/ +static const struct clock_source_funcs dce110_clk_src_funcs = { + .cs_power_down = dce110_clock_source_power_down, + .program_pix_clk = dce110_program_pix_clk, + .get_pix_clk_dividers = dce110_get_pix_clk_dividers +}; + +static void get_ss_info_from_atombios( + struct dce110_clk_src *clk_src, + enum as_signal_type as_signal, + struct spread_spectrum_data *spread_spectrum_data[], + uint32_t *ss_entries_num) +{ + enum bp_result bp_result = BP_RESULT_FAILURE; + struct spread_spectrum_info *ss_info; + struct spread_spectrum_data *ss_data; + struct spread_spectrum_info *ss_info_cur; + struct spread_spectrum_data *ss_data_cur; + uint32_t i; + + if (ss_entries_num == NULL) { + dm_logger_write(clk_src->base.ctx->logger, LOG_SYNC, + "Invalid entry !!!\n"); + return; + } + if (spread_spectrum_data == NULL) { + dm_logger_write(clk_src->base.ctx->logger, LOG_SYNC, + "Invalid array pointer!!!\n"); + return; + } + + spread_spectrum_data[0] = NULL; + *ss_entries_num = 0; + + *ss_entries_num = clk_src->bios->funcs->get_ss_entry_number( + clk_src->bios, + as_signal); + + if (*ss_entries_num == 0) + return; + + ss_info = dm_alloc(sizeof(struct spread_spectrum_info) * (*ss_entries_num)); + ss_info_cur = ss_info; + if (ss_info == NULL) + return; + + ss_data = dm_alloc(sizeof(struct spread_spectrum_data) * (*ss_entries_num)); + if (ss_data == NULL) + goto out_free_info; + + for (i = 0, ss_info_cur = ss_info; + i < (*ss_entries_num); + ++i, ++ss_info_cur) { + + bp_result = clk_src->bios->funcs->get_spread_spectrum_info( + clk_src->bios, + as_signal, + i, + ss_info_cur); + + if (bp_result != BP_RESULT_OK) + goto out_free_data; + } + + for (i = 0, ss_info_cur = ss_info, ss_data_cur = ss_data; + i < (*ss_entries_num); + ++i, ++ss_info_cur, ++ss_data_cur) { + + if (ss_info_cur->type.STEP_AND_DELAY_INFO != false) { + dm_logger_write(clk_src->base.ctx->logger, LOG_SYNC, + "Invalid ATOMBIOS SS Table!!!\n"); + goto out_free_data; + } + + /* for HDMI check SS percentage, + * if it is > 6 (0.06%), the ATOMBIOS table info is invalid*/ + if (as_signal == AS_SIGNAL_TYPE_HDMI + && ss_info_cur->spread_spectrum_percentage > 6){ + /* invalid input, do nothing */ + dm_logger_write(clk_src->base.ctx->logger, LOG_SYNC, + "Invalid SS percentage "); + dm_logger_write(clk_src->base.ctx->logger, LOG_SYNC, + "for HDMI in ATOMBIOS info Table!!!\n"); + continue; + } + if (ss_info_cur->spread_percentage_divider == 1000) { + /* Keep previous precision from ATOMBIOS for these + * in case new precision set by ATOMBIOS for these + * (otherwise all code in DCE specific classes + * for all previous ASICs would need + * to be updated for SS calculations, + * Audio SS compensation and DP DTO SS compensation + * which assumes fixed SS percentage Divider = 100)*/ + ss_info_cur->spread_spectrum_percentage /= 10; + ss_info_cur->spread_percentage_divider = 100; + } + + ss_data_cur->freq_range_khz = ss_info_cur->target_clock_range; + ss_data_cur->percentage = + ss_info_cur->spread_spectrum_percentage; + ss_data_cur->percentage_divider = + ss_info_cur->spread_percentage_divider; + ss_data_cur->modulation_freq_hz = + ss_info_cur->spread_spectrum_range; + + if (ss_info_cur->type.CENTER_MODE) + ss_data_cur->flags.CENTER_SPREAD = 1; + + if (ss_info_cur->type.EXTERNAL) + ss_data_cur->flags.EXTERNAL_SS = 1; + + } + + *spread_spectrum_data = ss_data; + dm_free(ss_info); + return; + +out_free_data: + dm_free(ss_data); + *ss_entries_num = 0; +out_free_info: + dm_free(ss_info); +} + +static void ss_info_from_atombios_create( + struct dce110_clk_src *clk_src) +{ + get_ss_info_from_atombios( + clk_src, + AS_SIGNAL_TYPE_DISPLAY_PORT, + &clk_src->dp_ss_params, + &clk_src->dp_ss_params_cnt); + get_ss_info_from_atombios( + clk_src, + AS_SIGNAL_TYPE_HDMI, + &clk_src->hdmi_ss_params, + &clk_src->hdmi_ss_params_cnt); + get_ss_info_from_atombios( + clk_src, + AS_SIGNAL_TYPE_DVI, + &clk_src->dvi_ss_params, + &clk_src->dvi_ss_params_cnt); +} + +static bool calc_pll_max_vco_construct( + struct calc_pll_clock_source *calc_pll_cs, + struct calc_pll_clock_source_init_data *init_data) +{ + uint32_t i; + struct firmware_info fw_info = { { 0 } }; + if (calc_pll_cs == NULL || + init_data == NULL || + init_data->bp == NULL) + return false; + + if (init_data->bp->funcs->get_firmware_info( + init_data->bp, + &fw_info) != BP_RESULT_OK) + return false; + + calc_pll_cs->ctx = init_data->ctx; + calc_pll_cs->ref_freq_khz = fw_info.pll_info.crystal_frequency; + calc_pll_cs->min_vco_khz = + fw_info.pll_info.min_output_pxl_clk_pll_frequency; + calc_pll_cs->max_vco_khz = + fw_info.pll_info.max_output_pxl_clk_pll_frequency; + + if (init_data->max_override_input_pxl_clk_pll_freq_khz != 0) + calc_pll_cs->max_pll_input_freq_khz = + init_data->max_override_input_pxl_clk_pll_freq_khz; + else + calc_pll_cs->max_pll_input_freq_khz = + fw_info.pll_info.max_input_pxl_clk_pll_frequency; + + if (init_data->min_override_input_pxl_clk_pll_freq_khz != 0) + calc_pll_cs->min_pll_input_freq_khz = + init_data->min_override_input_pxl_clk_pll_freq_khz; + else + calc_pll_cs->min_pll_input_freq_khz = + fw_info.pll_info.min_input_pxl_clk_pll_frequency; + + calc_pll_cs->min_pix_clock_pll_post_divider = + init_data->min_pix_clk_pll_post_divider; + calc_pll_cs->max_pix_clock_pll_post_divider = + init_data->max_pix_clk_pll_post_divider; + calc_pll_cs->min_pll_ref_divider = + init_data->min_pll_ref_divider; + calc_pll_cs->max_pll_ref_divider = + init_data->max_pll_ref_divider; + + if (init_data->num_fract_fb_divider_decimal_point == 0 || + init_data->num_fract_fb_divider_decimal_point_precision > + init_data->num_fract_fb_divider_decimal_point) { + dm_logger_write(calc_pll_cs->ctx->logger, LOG_ERROR, + "The dec point num or precision is incorrect!"); + return false; + } + if (init_data->num_fract_fb_divider_decimal_point_precision == 0) { + dm_logger_write(calc_pll_cs->ctx->logger, LOG_ERROR, + "Incorrect fract feedback divider precision num!"); + return false; + } + + calc_pll_cs->fract_fb_divider_decimal_points_num = + init_data->num_fract_fb_divider_decimal_point; + calc_pll_cs->fract_fb_divider_precision = + init_data->num_fract_fb_divider_decimal_point_precision; + calc_pll_cs->fract_fb_divider_factor = 1; + for (i = 0; i < calc_pll_cs->fract_fb_divider_decimal_points_num; ++i) + calc_pll_cs->fract_fb_divider_factor *= 10; + + calc_pll_cs->fract_fb_divider_precision_factor = 1; + for ( + i = 0; + i < (calc_pll_cs->fract_fb_divider_decimal_points_num - + calc_pll_cs->fract_fb_divider_precision); + ++i) + calc_pll_cs->fract_fb_divider_precision_factor *= 10; + + return true; +} + +bool dce110_clk_src_construct( + struct dce110_clk_src *clk_src, + struct dc_context *ctx, + struct dc_bios *bios, + enum clock_source_id id, + const struct dce110_clk_src_regs *regs, + const struct dce110_clk_src_shift *cs_shift, + const struct dce110_clk_src_mask *cs_mask) +{ + struct firmware_info fw_info = { { 0 } }; + struct calc_pll_clock_source_init_data calc_pll_cs_init_data_hdmi; + struct calc_pll_clock_source_init_data calc_pll_cs_init_data; + + clk_src->base.ctx = ctx; + clk_src->bios = bios; + clk_src->base.id = id; + clk_src->base.funcs = &dce110_clk_src_funcs; + + clk_src->regs = regs; + clk_src->cs_shift = cs_shift; + clk_src->cs_mask = cs_mask; + + if (clk_src->bios->funcs->get_firmware_info( + clk_src->bios, &fw_info) != BP_RESULT_OK) { + ASSERT_CRITICAL(false); + goto unexpected_failure; + } + + clk_src->ext_clk_khz = + fw_info.external_clock_source_frequency_for_dp; + + switch (clk_src->base.ctx->dce_version) { + case DCE_VERSION_8_0: + case DCE_VERSION_10_0: + case DCE_VERSION_11_0: + + /* structure normally used with PLL ranges from ATOMBIOS; DS on by default */ + calc_pll_cs_init_data.bp = bios; + calc_pll_cs_init_data.min_pix_clk_pll_post_divider = 1; + calc_pll_cs_init_data.max_pix_clk_pll_post_divider = + clk_src->cs_mask->PLL_POST_DIV_PIXCLK; + calc_pll_cs_init_data.min_pll_ref_divider = 1; + calc_pll_cs_init_data.max_pll_ref_divider = clk_src->cs_mask->PLL_REF_DIV; + /* when 0 use minInputPxlClkPLLFrequencyInKHz from firmwareInfo*/ + calc_pll_cs_init_data.min_override_input_pxl_clk_pll_freq_khz = 0; + /* when 0 use maxInputPxlClkPLLFrequencyInKHz from firmwareInfo*/ + calc_pll_cs_init_data.max_override_input_pxl_clk_pll_freq_khz = 0; + /*numberOfFractFBDividerDecimalPoints*/ + calc_pll_cs_init_data.num_fract_fb_divider_decimal_point = + FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM; + /*number of decimal point to round off for fractional feedback divider value*/ + calc_pll_cs_init_data.num_fract_fb_divider_decimal_point_precision = + FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM; + calc_pll_cs_init_data.ctx = ctx; + + /*structure for HDMI, no SS or SS% <= 0.06% for 27 MHz Ref clock */ + calc_pll_cs_init_data_hdmi.bp = bios; + calc_pll_cs_init_data_hdmi.min_pix_clk_pll_post_divider = 1; + calc_pll_cs_init_data_hdmi.max_pix_clk_pll_post_divider = + clk_src->cs_mask->PLL_POST_DIV_PIXCLK; + calc_pll_cs_init_data_hdmi.min_pll_ref_divider = 1; + calc_pll_cs_init_data_hdmi.max_pll_ref_divider = clk_src->cs_mask->PLL_REF_DIV; + /* when 0 use minInputPxlClkPLLFrequencyInKHz from firmwareInfo*/ + calc_pll_cs_init_data_hdmi.min_override_input_pxl_clk_pll_freq_khz = 13500; + /* when 0 use maxInputPxlClkPLLFrequencyInKHz from firmwareInfo*/ + calc_pll_cs_init_data_hdmi.max_override_input_pxl_clk_pll_freq_khz = 27000; + /*numberOfFractFBDividerDecimalPoints*/ + calc_pll_cs_init_data_hdmi.num_fract_fb_divider_decimal_point = + FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM; + /*number of decimal point to round off for fractional feedback divider value*/ + calc_pll_cs_init_data_hdmi.num_fract_fb_divider_decimal_point_precision = + FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM; + calc_pll_cs_init_data_hdmi.ctx = ctx; + + clk_src->ref_freq_khz = fw_info.pll_info.crystal_frequency; + + if (clk_src->base.id == CLOCK_SOURCE_ID_EXTERNAL) + return true; + + /* PLL only from here on */ + ss_info_from_atombios_create(clk_src); + + if (!calc_pll_max_vco_construct( + &clk_src->calc_pll, + &calc_pll_cs_init_data)) { + ASSERT_CRITICAL(false); + goto unexpected_failure; + } + + if (clk_src->ref_freq_khz == 48000) { + calc_pll_cs_init_data_hdmi. + min_override_input_pxl_clk_pll_freq_khz = 24000; + calc_pll_cs_init_data_hdmi. + max_override_input_pxl_clk_pll_freq_khz = 48000; + } else if (clk_src->ref_freq_khz == 100000) { + calc_pll_cs_init_data_hdmi. + min_override_input_pxl_clk_pll_freq_khz = 25000; + calc_pll_cs_init_data_hdmi. + max_override_input_pxl_clk_pll_freq_khz = 50000; + } + + if (!calc_pll_max_vco_construct( + &clk_src->calc_pll_hdmi, &calc_pll_cs_init_data_hdmi)) { + ASSERT_CRITICAL(false); + goto unexpected_failure; + } + break; + default: + break; + } + + return true; + +unexpected_failure: + return false; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h new file mode 100644 index 000000000000..067e4ac0e67a --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h @@ -0,0 +1,109 @@ +/* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_CLOCK_SOURCE_DCE_H__ +#define __DC_CLOCK_SOURCE_DCE_H__ + +#include "../inc/clock_source.h" + +#define TO_DCE110_CLK_SRC(clk_src)\ + container_of(clk_src, struct dce110_clk_src, base) + +#define CS_COMMON_REG_LIST_DCE_100_110(id) \ + SRI(RESYNC_CNTL, PIXCLK, id), \ + SRI(PLL_CNTL, BPHYC_PLL, id) + +#define CS_COMMON_REG_LIST_DCE_80(id) \ + SRI(RESYNC_CNTL, PIXCLK, id), \ + SRI(PLL_CNTL, DCCG_PLL, id) + +#define CS_COMMON_REG_LIST_DCE_112(id) \ + SRI(PIXCLK_RESYNC_CNTL, PHYPLL, id) + +#define CS_SF(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define CS_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh)\ + CS_SF(PLL_CNTL, PLL_REF_DIV_SRC, mask_sh),\ + CS_SF(PIXCLK1_RESYNC_CNTL, DCCG_DEEP_COLOR_CNTL1, mask_sh),\ + CS_SF(PLL_POST_DIV, PLL_POST_DIV_PIXCLK, mask_sh),\ + CS_SF(PLL_REF_DIV, PLL_REF_DIV, mask_sh),\ + +#define CS_COMMON_MASK_SH_LIST_DCE_112(mask_sh)\ + CS_SF(PHYPLLA_PIXCLK_RESYNC_CNTL, PHYPLLA_DCCG_DEEP_COLOR_CNTL, mask_sh),\ + CS_SF(PHYPLLA_PIXCLK_RESYNC_CNTL, PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE, mask_sh),\ + +#define CS_REG_FIELD_LIST(type) \ + type PLL_REF_DIV_SRC; \ + type DCCG_DEEP_COLOR_CNTL1; \ + type PHYPLLA_DCCG_DEEP_COLOR_CNTL; \ + type PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE; \ + type PLL_POST_DIV_PIXCLK; \ + type PLL_REF_DIV; \ + +struct dce110_clk_src_shift { + CS_REG_FIELD_LIST(uint8_t) +}; + +struct dce110_clk_src_mask{ + CS_REG_FIELD_LIST(uint32_t) +}; + +struct dce110_clk_src_regs { + uint32_t RESYNC_CNTL; + uint32_t PIXCLK_RESYNC_CNTL; + uint32_t PLL_CNTL; +}; + +struct dce110_clk_src { + struct clock_source base; + const struct dce110_clk_src_regs *regs; + const struct dce110_clk_src_mask *cs_mask; + const struct dce110_clk_src_shift *cs_shift; + struct dc_bios *bios; + + struct spread_spectrum_data *dp_ss_params; + uint32_t dp_ss_params_cnt; + struct spread_spectrum_data *hdmi_ss_params; + uint32_t hdmi_ss_params_cnt; + struct spread_spectrum_data *dvi_ss_params; + uint32_t dvi_ss_params_cnt; + + uint32_t ext_clk_khz; + uint32_t ref_freq_khz; + + struct calc_pll_clock_source calc_pll; + struct calc_pll_clock_source calc_pll_hdmi; +}; + +bool dce110_clk_src_construct( + struct dce110_clk_src *clk_src, + struct dc_context *ctx, + struct dc_bios *bios, + enum clock_source_id, + const struct dce110_clk_src_regs *regs, + const struct dce110_clk_src_shift *cs_shift, + const struct dce110_clk_src_mask *cs_mask); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c new file mode 100644 index 000000000000..dd1cf5e6e949 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c @@ -0,0 +1,195 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dce_hwseq.h" +#include "reg_helper.h" +#include "hw_sequencer.h" + +#define CTX \ + hws->ctx +#define REG(reg)\ + hws->regs->reg + +#undef FN +#define FN(reg_name, field_name) \ + hws->shifts->field_name, hws->masks->field_name + +void dce_enable_fe_clock(struct dce_hwseq *hws, + unsigned int fe_inst, bool enable) +{ + REG_UPDATE(DCFE_CLOCK_CONTROL[fe_inst], + DCFE_CLOCK_ENABLE, enable); +} + +void dce_pipe_control_lock(struct dce_hwseq *hws, + unsigned int blnd_inst, + enum pipe_lock_control control_mask, + bool lock) +{ + uint32_t lock_val = lock ? 1 : 0; + uint32_t dcp_grph, scl, dcp_grph_surf, blnd, update_lock_mode; + + uint32_t val = REG_GET_5(BLND_V_UPDATE_LOCK[blnd_inst], + BLND_DCP_GRPH_V_UPDATE_LOCK, &dcp_grph, + BLND_SCL_V_UPDATE_LOCK, &scl, + BLND_DCP_GRPH_SURF_V_UPDATE_LOCK, &dcp_grph_surf, + BLND_BLND_V_UPDATE_LOCK, &blnd, + BLND_V_UPDATE_LOCK_MODE, &update_lock_mode); + + if (control_mask & PIPE_LOCK_CONTROL_GRAPHICS) + dcp_grph = lock_val; + + if (control_mask & PIPE_LOCK_CONTROL_SCL) + scl = lock_val; + + if (control_mask & PIPE_LOCK_CONTROL_SURFACE) + dcp_grph_surf = lock_val; + + if (control_mask & PIPE_LOCK_CONTROL_BLENDER) + blnd = lock_val; + + if (control_mask & PIPE_LOCK_CONTROL_MODE) + update_lock_mode = lock_val; + + REG_SET_5(BLND_V_UPDATE_LOCK[blnd_inst], val, + BLND_DCP_GRPH_V_UPDATE_LOCK, dcp_grph, + BLND_SCL_V_UPDATE_LOCK, scl, + BLND_DCP_GRPH_SURF_V_UPDATE_LOCK, dcp_grph_surf, + BLND_BLND_V_UPDATE_LOCK, blnd, + BLND_V_UPDATE_LOCK_MODE, update_lock_mode); + + if (hws->wa.blnd_crtc_trigger) + if (!lock && (control_mask & PIPE_LOCK_CONTROL_BLENDER)) { + uint32_t value = REG_READ(CRTC_H_BLANK_START_END[blnd_inst]); + REG_WRITE(CRTC_H_BLANK_START_END[blnd_inst], value); + } +} + +void dce_set_blender_mode(struct dce_hwseq *hws, + unsigned int blnd_inst, + enum blnd_mode mode) +{ + uint32_t feedthrough = 1; + uint32_t blnd_mode = 0; + uint32_t multiplied_mode = 0; + uint32_t alpha_mode = 2; + + switch (mode) { + case BLND_MODE_OTHER_PIPE: + feedthrough = 0; + blnd_mode = 1; + alpha_mode = 0; + break; + case BLND_MODE_BLENDING: + feedthrough = 0; + blnd_mode = 2; + alpha_mode = 0; + multiplied_mode = 1; + break; + case BLND_MODE_CURRENT_PIPE: + default: + if (REG(BLND_CONTROL[blnd_inst]) == REG(BLNDV_CONTROL) || + blnd_inst == 0) + feedthrough = 0; + break; + } + + REG_UPDATE_4(BLND_CONTROL[blnd_inst], + BLND_FEEDTHROUGH_EN, feedthrough, + BLND_ALPHA_MODE, alpha_mode, + BLND_MODE, blnd_mode, + BLND_MULTIPLIED_MODE, multiplied_mode); +} + + +static void dce_disable_sram_shut_down(struct dce_hwseq *hws) +{ + if (REG(DC_MEM_GLOBAL_PWR_REQ_CNTL)) + REG_UPDATE(DC_MEM_GLOBAL_PWR_REQ_CNTL, + DC_MEM_GLOBAL_PWR_REQ_DIS, 1); +} + +static void dce_underlay_clock_enable(struct dce_hwseq *hws) +{ + /* todo: why do we need this at boot? is dce_enable_fe_clock enough? */ + if (REG(DCFEV_CLOCK_CONTROL)) + REG_UPDATE(DCFEV_CLOCK_CONTROL, + DCFEV_CLOCK_ENABLE, 1); +} + +static void enable_hw_base_light_sleep(void) +{ + /* TODO: implement */ +} + +static void disable_sw_manual_control_light_sleep(void) +{ + /* TODO: implement */ +} + +void dce_clock_gating_power_up(struct dce_hwseq *hws, + bool enable) +{ + if (enable) { + enable_hw_base_light_sleep(); + disable_sw_manual_control_light_sleep(); + } else { + dce_disable_sram_shut_down(hws); + dce_underlay_clock_enable(hws); + } +} + +void dce_crtc_switch_to_clk_src(struct dce_hwseq *hws, + struct clock_source *clk_src, + unsigned int tg_inst) +{ + if (clk_src->id == CLOCK_SOURCE_ID_DP_DTO) { + REG_UPDATE(PIXEL_RATE_CNTL[tg_inst], + DP_DTO0_ENABLE, 1); + + } else if (clk_src->id >= CLOCK_SOURCE_COMBO_PHY_PLL0) { + uint32_t rate_source = clk_src->id - CLOCK_SOURCE_COMBO_PHY_PLL0; + + REG_UPDATE_2(PHYPLL_PIXEL_RATE_CNTL[tg_inst], + PHYPLL_PIXEL_RATE_SOURCE, rate_source, + PIXEL_RATE_PLL_SOURCE, 0); + + REG_UPDATE(PIXEL_RATE_CNTL[tg_inst], + DP_DTO0_ENABLE, 0); + + } else if (clk_src->id <= CLOCK_SOURCE_ID_PLL2) { + uint32_t rate_source = clk_src->id - CLOCK_SOURCE_ID_PLL0; + + REG_UPDATE_2(PIXEL_RATE_CNTL[tg_inst], + PIXEL_RATE_SOURCE, rate_source, + DP_DTO0_ENABLE, 0); + + if (REG(PHYPLL_PIXEL_RATE_CNTL[tg_inst])) + REG_UPDATE(PHYPLL_PIXEL_RATE_CNTL[tg_inst], + PIXEL_RATE_PLL_SOURCE, 1); + } else { + DC_ERR("unknown clock source"); + } +} diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h new file mode 100644 index 000000000000..4af8d560a7ee --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -0,0 +1,250 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef __DCE_HWSEQ_H__ +#define __DCE_HWSEQ_H__ + +#include "hw_sequencer.h" + +#define HWSEQ_DCEF_REG_LIST_DCE8() \ + .DCFE_CLOCK_CONTROL[0] = mmCRTC0_CRTC_DCFE_CLOCK_CONTROL, \ + .DCFE_CLOCK_CONTROL[1] = mmCRTC1_CRTC_DCFE_CLOCK_CONTROL, \ + .DCFE_CLOCK_CONTROL[2] = mmCRTC2_CRTC_DCFE_CLOCK_CONTROL, \ + .DCFE_CLOCK_CONTROL[3] = mmCRTC3_CRTC_DCFE_CLOCK_CONTROL, \ + .DCFE_CLOCK_CONTROL[4] = mmCRTC4_CRTC_DCFE_CLOCK_CONTROL, \ + .DCFE_CLOCK_CONTROL[5] = mmCRTC5_CRTC_DCFE_CLOCK_CONTROL + +#define HWSEQ_DCEF_REG_LIST() \ + SRII(DCFE_CLOCK_CONTROL, DCFE, 0), \ + SRII(DCFE_CLOCK_CONTROL, DCFE, 1), \ + SRII(DCFE_CLOCK_CONTROL, DCFE, 2), \ + SRII(DCFE_CLOCK_CONTROL, DCFE, 3), \ + SRII(DCFE_CLOCK_CONTROL, DCFE, 4), \ + SRII(DCFE_CLOCK_CONTROL, DCFE, 5), \ + SR(DC_MEM_GLOBAL_PWR_REQ_CNTL) + +#define HWSEQ_BLND_REG_LIST() \ + SRII(BLND_V_UPDATE_LOCK, BLND, 0), \ + SRII(BLND_V_UPDATE_LOCK, BLND, 1), \ + SRII(BLND_V_UPDATE_LOCK, BLND, 2), \ + SRII(BLND_V_UPDATE_LOCK, BLND, 3), \ + SRII(BLND_V_UPDATE_LOCK, BLND, 4), \ + SRII(BLND_V_UPDATE_LOCK, BLND, 5), \ + SRII(BLND_CONTROL, BLND, 0), \ + SRII(BLND_CONTROL, BLND, 1), \ + SRII(BLND_CONTROL, BLND, 2), \ + SRII(BLND_CONTROL, BLND, 3), \ + SRII(BLND_CONTROL, BLND, 4), \ + SRII(BLND_CONTROL, BLND, 5) + +#define HWSEQ_PIXEL_RATE_REG_LIST(blk) \ + SRII(PIXEL_RATE_CNTL, blk, 0), \ + SRII(PIXEL_RATE_CNTL, blk, 1), \ + SRII(PIXEL_RATE_CNTL, blk, 2), \ + SRII(PIXEL_RATE_CNTL, blk, 3), \ + SRII(PIXEL_RATE_CNTL, blk, 4), \ + SRII(PIXEL_RATE_CNTL, blk, 5) + +#define HWSEQ_PHYPLL_REG_LIST(blk) \ + SRII(PHYPLL_PIXEL_RATE_CNTL, blk, 0), \ + SRII(PHYPLL_PIXEL_RATE_CNTL, blk, 1), \ + SRII(PHYPLL_PIXEL_RATE_CNTL, blk, 2), \ + SRII(PHYPLL_PIXEL_RATE_CNTL, blk, 3), \ + SRII(PHYPLL_PIXEL_RATE_CNTL, blk, 4), \ + SRII(PHYPLL_PIXEL_RATE_CNTL, blk, 5) + +#define HWSEQ_DCE11_REG_LIST_BASE() \ + SR(DC_MEM_GLOBAL_PWR_REQ_CNTL), \ + SR(DCFEV_CLOCK_CONTROL), \ + SRII(DCFE_CLOCK_CONTROL, DCFE, 0), \ + SRII(DCFE_CLOCK_CONTROL, DCFE, 1), \ + SRII(CRTC_H_BLANK_START_END, CRTC, 0),\ + SRII(CRTC_H_BLANK_START_END, CRTC, 1),\ + SRII(BLND_V_UPDATE_LOCK, BLND, 0),\ + SRII(BLND_V_UPDATE_LOCK, BLND, 1),\ + SRII(BLND_CONTROL, BLND, 0),\ + SRII(BLND_CONTROL, BLND, 1),\ + SR(BLNDV_CONTROL),\ + HWSEQ_PIXEL_RATE_REG_LIST(CRTC) + +#define HWSEQ_DCE8_REG_LIST() \ + HWSEQ_DCEF_REG_LIST_DCE8(), \ + HWSEQ_BLND_REG_LIST(), \ + HWSEQ_PIXEL_RATE_REG_LIST(CRTC) + +#define HWSEQ_DCE10_REG_LIST() \ + HWSEQ_DCEF_REG_LIST(), \ + HWSEQ_BLND_REG_LIST(), \ + HWSEQ_PIXEL_RATE_REG_LIST(CRTC) + +#define HWSEQ_ST_REG_LIST() \ + HWSEQ_DCE11_REG_LIST_BASE(), \ + .DCFE_CLOCK_CONTROL[2] = mmDCFEV_CLOCK_CONTROL, \ + .CRTC_H_BLANK_START_END[2] = mmCRTCV_H_BLANK_START_END, \ + .BLND_V_UPDATE_LOCK[2] = mmBLNDV_V_UPDATE_LOCK, \ + .BLND_CONTROL[2] = mmBLNDV_CONTROL, + +#define HWSEQ_CZ_REG_LIST() \ + HWSEQ_DCE11_REG_LIST_BASE(), \ + SRII(DCFE_CLOCK_CONTROL, DCFE, 2), \ + SRII(CRTC_H_BLANK_START_END, CRTC, 2), \ + SRII(BLND_V_UPDATE_LOCK, BLND, 2), \ + SRII(BLND_CONTROL, BLND, 2), \ + .DCFE_CLOCK_CONTROL[3] = mmDCFEV_CLOCK_CONTROL, \ + .CRTC_H_BLANK_START_END[3] = mmCRTCV_H_BLANK_START_END, \ + .BLND_V_UPDATE_LOCK[3] = mmBLNDV_V_UPDATE_LOCK, \ + .BLND_CONTROL[3] = mmBLNDV_CONTROL + +#define HWSEQ_DCE112_REG_LIST() \ + HWSEQ_DCE10_REG_LIST(), \ + HWSEQ_PIXEL_RATE_REG_LIST(CRTC), \ + HWSEQ_PHYPLL_REG_LIST(CRTC) + +struct dce_hwseq_registers { + uint32_t DCFE_CLOCK_CONTROL[6]; + uint32_t DCFEV_CLOCK_CONTROL; + uint32_t DC_MEM_GLOBAL_PWR_REQ_CNTL; + uint32_t BLND_V_UPDATE_LOCK[6]; + uint32_t BLND_CONTROL[6]; + uint32_t BLNDV_CONTROL; + + uint32_t CRTC_H_BLANK_START_END[6]; + uint32_t PIXEL_RATE_CNTL[6]; + uint32_t PHYPLL_PIXEL_RATE_CNTL[6]; +}; + /* set field name */ +#define HWS_SF(blk_name, reg_name, field_name, post_fix)\ + .field_name = blk_name ## reg_name ## __ ## field_name ## post_fix + +#define HWS_SF1(blk_name, reg_name, field_name, post_fix)\ + .field_name = blk_name ## reg_name ## __ ## blk_name ## field_name ## post_fix + + +#define HWSEQ_DCEF_MASK_SH_LIST(mask_sh, blk)\ + HWS_SF(blk, CLOCK_CONTROL, DCFE_CLOCK_ENABLE, mask_sh),\ + SF(DC_MEM_GLOBAL_PWR_REQ_CNTL, DC_MEM_GLOBAL_PWR_REQ_DIS, mask_sh) + +#define HWSEQ_BLND_MASK_SH_LIST(mask_sh, blk)\ + HWS_SF(blk, V_UPDATE_LOCK, BLND_DCP_GRPH_V_UPDATE_LOCK, mask_sh),\ + HWS_SF(blk, V_UPDATE_LOCK, BLND_SCL_V_UPDATE_LOCK, mask_sh),\ + HWS_SF(blk, V_UPDATE_LOCK, BLND_DCP_GRPH_SURF_V_UPDATE_LOCK, mask_sh),\ + HWS_SF(blk, V_UPDATE_LOCK, BLND_BLND_V_UPDATE_LOCK, mask_sh),\ + HWS_SF(blk, V_UPDATE_LOCK, BLND_V_UPDATE_LOCK_MODE, mask_sh),\ + HWS_SF(blk, CONTROL, BLND_FEEDTHROUGH_EN, mask_sh),\ + HWS_SF(blk, CONTROL, BLND_ALPHA_MODE, mask_sh),\ + HWS_SF(blk, CONTROL, BLND_MODE, mask_sh),\ + HWS_SF(blk, CONTROL, BLND_MULTIPLIED_MODE, mask_sh) + +#define HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, blk)\ + HWS_SF1(blk, PIXEL_RATE_CNTL, PIXEL_RATE_SOURCE, mask_sh),\ + HWS_SF(blk, PIXEL_RATE_CNTL, DP_DTO0_ENABLE, mask_sh) + +#define HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, blk)\ + HWS_SF1(blk, PHYPLL_PIXEL_RATE_CNTL, PHYPLL_PIXEL_RATE_SOURCE, mask_sh),\ + HWS_SF1(blk, PHYPLL_PIXEL_RATE_CNTL, PIXEL_RATE_PLL_SOURCE, mask_sh) + +#define HWSEQ_DCE8_MASK_SH_LIST(mask_sh)\ + .DCFE_CLOCK_ENABLE = CRTC_DCFE_CLOCK_CONTROL__CRTC_DCFE_CLOCK_ENABLE ## mask_sh, \ + HWS_SF(BLND_, V_UPDATE_LOCK, BLND_DCP_GRPH_V_UPDATE_LOCK, mask_sh),\ + HWS_SF(BLND_, V_UPDATE_LOCK, BLND_SCL_V_UPDATE_LOCK, mask_sh),\ + HWS_SF(BLND_, V_UPDATE_LOCK, BLND_DCP_GRPH_SURF_V_UPDATE_LOCK, mask_sh),\ + HWS_SF(BLND_, CONTROL, BLND_MODE, mask_sh),\ + HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_) + +#define HWSEQ_DCE10_MASK_SH_LIST(mask_sh)\ + HWSEQ_DCEF_MASK_SH_LIST(mask_sh, DCFE_),\ + HWSEQ_BLND_MASK_SH_LIST(mask_sh, BLND_),\ + HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_) + +#define HWSEQ_DCE11_MASK_SH_LIST(mask_sh)\ + HWSEQ_DCE10_MASK_SH_LIST(mask_sh),\ + SF(DCFEV_CLOCK_CONTROL, DCFEV_CLOCK_ENABLE, mask_sh),\ + HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_) + +#define HWSEQ_DCE112_MASK_SH_LIST(mask_sh)\ + HWSEQ_DCE10_MASK_SH_LIST(mask_sh),\ + HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, CRTC0_) + +#define HWSEQ_REG_FIED_LIST(type) \ + type DCFE_CLOCK_ENABLE; \ + type DCFEV_CLOCK_ENABLE; \ + type DC_MEM_GLOBAL_PWR_REQ_DIS; \ + type BLND_DCP_GRPH_V_UPDATE_LOCK; \ + type BLND_SCL_V_UPDATE_LOCK; \ + type BLND_DCP_GRPH_SURF_V_UPDATE_LOCK; \ + type BLND_BLND_V_UPDATE_LOCK; \ + type BLND_V_UPDATE_LOCK_MODE; \ + type BLND_FEEDTHROUGH_EN; \ + type BLND_ALPHA_MODE; \ + type BLND_MODE; \ + type BLND_MULTIPLIED_MODE; \ + type DP_DTO0_ENABLE; \ + type PIXEL_RATE_SOURCE; \ + type PHYPLL_PIXEL_RATE_SOURCE; \ + type PIXEL_RATE_PLL_SOURCE; \ + +struct dce_hwseq_shift { + HWSEQ_REG_FIED_LIST(uint8_t) +}; + +struct dce_hwseq_mask { + HWSEQ_REG_FIED_LIST(uint32_t) +}; + +struct dce_hwseq_wa { + bool blnd_crtc_trigger; +}; + +struct dce_hwseq { + struct dc_context *ctx; + const struct dce_hwseq_registers *regs; + const struct dce_hwseq_shift *shifts; + const struct dce_hwseq_mask *masks; + struct dce_hwseq_wa wa; +}; + +enum blnd_mode { + BLND_MODE_CURRENT_PIPE = 0,/* Data from current pipe only */ + BLND_MODE_OTHER_PIPE, /* Data from other pipe only */ + BLND_MODE_BLENDING,/* Alpha blending - blend 'current' and 'other' */ +}; + +void dce_enable_fe_clock(struct dce_hwseq *hwss, + unsigned int inst, bool enable); + +void dce_pipe_control_lock(struct dce_hwseq *hws, + unsigned int blnd_inst, + enum pipe_lock_control control_mask, + bool lock); + +void dce_set_blender_mode(struct dce_hwseq *hws, + unsigned int blnd_inst, enum blnd_mode mode); + +void dce_clock_gating_power_up(struct dce_hwseq *hws, + bool enable); + +void dce_crtc_switch_to_clk_src(struct dce_hwseq *hws, + struct clock_source *clk_src, + unsigned int tg_inst); +#endif /*__DCE_HWSEQ_H__*/ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c new file mode 100644 index 000000000000..86e55d028cbf --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -0,0 +1,2176 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "reg_helper.h" + +#include "core_types.h" +#include "link_encoder.h" +#include "dce_link_encoder.h" +#include "stream_encoder.h" +#include "i2caux_interface.h" +#include "dc_bios_types.h" + +#include "gpio_service_interface.h" + +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" +#include "dce/dce_11_0_enum.h" + +#ifndef ATOM_S2_CURRENT_BL_LEVEL_MASK +#define ATOM_S2_CURRENT_BL_LEVEL_MASK 0x0000FF00L +#define ATOM_S2_VRI_BRIGHT_ENABLE 0x20000000L +#endif + +#ifndef ATOM_S2_CURRENT_BL_LEVEL_SHIFT +#define ATOM_S2_CURRENT_BL_LEVEL_SHIFT 8 +#endif + +#ifndef HPD0_DC_HPD_CONTROL__DC_HPD_EN_MASK +#define HPD0_DC_HPD_CONTROL__DC_HPD_EN_MASK 0x10000000L +#endif + +#ifndef HPD0_DC_HPD_CONTROL__DC_HPD_EN__SHIFT +#define HPD0_DC_HPD_CONTROL__DC_HPD_EN__SHIFT 0x1c +#endif + +#define CTX \ + enc110->base.ctx + +#define REG(reg)\ + (enc110->link_regs->reg) + +#define AUX_REG(reg)\ + (enc110->aux_regs->reg) + +#define HPD_REG(reg)\ + (enc110->hpd_regs->reg) + +/* For current ASICs pixel clock - 600MHz */ +#define MAX_ENCODER_CLK 600000 + +#define DCE11_UNIPHY_MAX_PIXEL_CLK_IN_KHZ 594000 + +#define DEFAULT_AUX_MAX_DATA_SIZE 16 +#define AUX_MAX_DEFER_WRITE_RETRY 20 +/* + * @brief + * Trigger Source Select + * ASIC-dependent, actual values for register programming + */ +#define DCE110_DIG_FE_SOURCE_SELECT_INVALID 0x0 +#define DCE110_DIG_FE_SOURCE_SELECT_DIGA 0x1 +#define DCE110_DIG_FE_SOURCE_SELECT_DIGB 0x2 +#define DCE110_DIG_FE_SOURCE_SELECT_DIGC 0x4 +#define DCE110_DIG_FE_SOURCE_SELECT_DIGD 0x08 +#define DCE110_DIG_FE_SOURCE_SELECT_DIGE 0x10 +#define DCE110_DIG_FE_SOURCE_SELECT_DIGF 0x20 + +/* all values are in milliseconds */ +/* For eDP, after power-up/power/down, + * 300/500 msec max. delay from LCDVCC to black video generation */ +#define PANEL_POWER_UP_TIMEOUT 300 +#define PANEL_POWER_DOWN_TIMEOUT 500 +#define HPD_CHECK_INTERVAL 10 + +/* Minimum pixel clock, in KHz. For TMDS signal is 25.00 MHz */ +#define TMDS_MIN_PIXEL_CLOCK 25000 +/* Maximum pixel clock, in KHz. For TMDS signal is 165.00 MHz */ +#define TMDS_MAX_PIXEL_CLOCK 165000 +/* For current ASICs pixel clock - 600MHz */ +#define MAX_ENCODER_CLOCK 600000 + +/* Set the ABM Pipe */ +#define MCP_ABM_PIPE_SET 0x66 +/* Set the ABM level */ +#define MCP_ABM_LEVEL_SET 0x65 +/* Set backlight level */ +#define MCP_BL_SET 0x67 + +/* PSR related commands */ +#define PSR_ENABLE 0x20 +#define PSR_EXIT 0x21 +#define PSR_SET 0x23 + +/*TODO: Used for psr wakeup for set backlight level*/ +static unsigned int psr_crtc_offset; + +/* registers setting needs to be save and restored used at InitBacklight */ +static struct dce110_abm_backlight_registers stored_backlight_registers; + +enum { + DP_MST_UPDATE_MAX_RETRY = 50 +}; + +#define DIG_REG(reg)\ + (reg + enc110->offsets.dig) + +#define DP_REG(reg)\ + (reg + enc110->offsets.dp) + +static const struct link_encoder_funcs dce110_lnk_enc_funcs = { + .validate_output_with_stream = + dce110_link_encoder_validate_output_with_stream, + .hw_init = dce110_link_encoder_hw_init, + .setup = dce110_link_encoder_setup, + .enable_tmds_output = dce110_link_encoder_enable_tmds_output, + .enable_dp_output = dce110_link_encoder_enable_dp_output, + .enable_dp_mst_output = dce110_link_encoder_enable_dp_mst_output, + .disable_output = dce110_link_encoder_disable_output, + .dp_set_lane_settings = dce110_link_encoder_dp_set_lane_settings, + .dp_set_phy_pattern = dce110_link_encoder_dp_set_phy_pattern, + .update_mst_stream_allocation_table = + dce110_link_encoder_update_mst_stream_allocation_table, + .set_lcd_backlight_level = dce110_link_encoder_set_lcd_backlight_level, + .set_dmcu_backlight_level = + dce110_link_encoder_set_dmcu_backlight_level, + .init_dmcu_backlight_settings = + dce110_link_encoder_init_dmcu_backlight_settings, + .set_dmcu_abm_level = dce110_link_encoder_set_dmcu_abm_level, + .set_dmcu_psr_enable = dce110_link_encoder_set_dmcu_psr_enable, + .setup_dmcu_psr = dce110_link_encoder_setup_dmcu_psr, + .backlight_control = dce110_link_encoder_edp_backlight_control, + .power_control = dce110_link_encoder_edp_power_control, + .connect_dig_be_to_fe = dce110_link_encoder_connect_dig_be_to_fe, + .enable_hpd = dce110_link_encoder_enable_hpd, + .disable_hpd = dce110_link_encoder_disable_hpd, + .destroy = dce110_link_encoder_destroy +}; + + +static enum bp_result link_transmitter_control( + struct dce110_link_encoder *enc110, + struct bp_transmitter_control *cntl) +{ + enum bp_result result; + struct dc_bios *bp = enc110->base.ctx->dc_bios; + + result = bp->funcs->transmitter_control(bp, cntl); + + return result; +} + +static void enable_phy_bypass_mode( + struct dce110_link_encoder *enc110, + bool enable) +{ + /* This register resides in DP back end block; + * transmitter is used for the offset */ + + REG_UPDATE(DP_DPHY_CNTL, DPHY_BYPASS, enable); + +} + +static void disable_prbs_symbols( + struct dce110_link_encoder *enc110, + bool disable) +{ + /* This register resides in DP back end block; + * transmitter is used for the offset */ + + REG_UPDATE_4(DP_DPHY_CNTL, + DPHY_ATEST_SEL_LANE0, disable, + DPHY_ATEST_SEL_LANE1, disable, + DPHY_ATEST_SEL_LANE2, disable, + DPHY_ATEST_SEL_LANE3, disable); +} + +static void disable_prbs_mode( + struct dce110_link_encoder *enc110) +{ + /* This register resides in DP back end block; + * transmitter is used for the offset */ + + REG_UPDATE(DP_DPHY_PRBS_CNTL, DPHY_PRBS_EN, 0); +} + +static void program_pattern_symbols( + struct dce110_link_encoder *enc110, + uint16_t pattern_symbols[8]) +{ + /* This register resides in DP back end block; + * transmitter is used for the offset */ + + REG_SET_3(DP_DPHY_SYM0, 0, + DPHY_SYM1, pattern_symbols[0], + DPHY_SYM2, pattern_symbols[1], + DPHY_SYM3, pattern_symbols[2]); + + /* This register resides in DP back end block; + * transmitter is used for the offset */ + + REG_SET_3(DP_DPHY_SYM1, 0, + DPHY_SYM4, pattern_symbols[3], + DPHY_SYM5, pattern_symbols[4], + DPHY_SYM6, pattern_symbols[5]); + + /* This register resides in DP back end block; + * transmitter is used for the offset */ + + REG_SET_2(DP_DPHY_SYM2, 0, + DPHY_SYM7, pattern_symbols[6], + DPHY_SYM8, pattern_symbols[7]); +} + +static void set_dp_phy_pattern_d102( + struct dce110_link_encoder *enc110) +{ + /* Disable PHY Bypass mode to setup the test pattern */ + enable_phy_bypass_mode(enc110, false); + + /* For 10-bit PRBS or debug symbols + * please use the following sequence: */ + + /* Enable debug symbols on the lanes */ + + disable_prbs_symbols(enc110, true); + + /* Disable PRBS mode, + * make sure DPHY_PRBS_CNTL.DPHY_PRBS_EN=0 */ + + disable_prbs_mode(enc110); + + /* Program debug symbols to be output */ + { + uint16_t pattern_symbols[8] = { + 0x2AA, 0x2AA, 0x2AA, 0x2AA, + 0x2AA, 0x2AA, 0x2AA, 0x2AA + }; + + program_pattern_symbols(enc110, pattern_symbols); + } + + /* Enable phy bypass mode to enable the test pattern */ + + enable_phy_bypass_mode(enc110, true); +} + +static void set_link_training_complete( + struct dce110_link_encoder *enc110, + bool complete) +{ + /* This register resides in DP back end block; + * transmitter is used for the offset */ + + REG_UPDATE(DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE, complete); + +} + +void dce110_link_encoder_set_dp_phy_pattern_training_pattern( + struct link_encoder *enc, + uint32_t index) +{ + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + /* Write Training Pattern */ + + REG_WRITE(DP_DPHY_TRAINING_PATTERN_SEL, index); + + /* Set HW Register Training Complete to false */ + + set_link_training_complete(enc110, false); + + /* Disable PHY Bypass mode to output Training Pattern */ + + enable_phy_bypass_mode(enc110, false); + + /* Disable PRBS mode, + * make sure DPHY_PRBS_CNTL.DPHY_PRBS_EN=0 */ + + disable_prbs_mode(enc110); +} + +static void set_dp_phy_pattern_symbol_error( + struct dce110_link_encoder *enc110) +{ + /* Disable PHY Bypass mode to setup the test pattern */ + uint32_t value = 0x0; + + enable_phy_bypass_mode(enc110, false); + + /* program correct panel mode*/ + { + ASSERT(REG(DP_DPHY_INTERNAL_CTRL)); + /*DCE 120 does not have this reg*/ + + REG_WRITE(DP_DPHY_INTERNAL_CTRL, value); + } + + /* A PRBS23 pattern is used for most DP electrical measurements. */ + + /* Enable PRBS symbols on the lanes */ + + disable_prbs_symbols(enc110, false); + + /* For PRBS23 Set bit DPHY_PRBS_SEL=1 and Set bit DPHY_PRBS_EN=1 */ + { + REG_UPDATE_2(DP_DPHY_PRBS_CNTL, + DPHY_PRBS_SEL, 1, + DPHY_PRBS_EN, 1); + } + + /* Enable phy bypass mode to enable the test pattern */ + + enable_phy_bypass_mode(enc110, true); +} + +static void set_dp_phy_pattern_prbs7( + struct dce110_link_encoder *enc110) +{ + /* Disable PHY Bypass mode to setup the test pattern */ + + enable_phy_bypass_mode(enc110, false); + + /* A PRBS7 pattern is used for most DP electrical measurements. */ + + /* Enable PRBS symbols on the lanes */ + + disable_prbs_symbols(enc110, false); + + /* For PRBS7 Set bit DPHY_PRBS_SEL=0 and Set bit DPHY_PRBS_EN=1 */ + { + REG_UPDATE_2(DP_DPHY_PRBS_CNTL, + DPHY_PRBS_SEL, 0, + DPHY_PRBS_EN, 1); + } + + /* Enable phy bypass mode to enable the test pattern */ + + enable_phy_bypass_mode(enc110, true); +} + +static void set_dp_phy_pattern_80bit_custom( + struct dce110_link_encoder *enc110, + const uint8_t *pattern) +{ + /* Disable PHY Bypass mode to setup the test pattern */ + enable_phy_bypass_mode(enc110, false); + + /* Enable debug symbols on the lanes */ + + disable_prbs_symbols(enc110, true); + + /* Enable PHY bypass mode to enable the test pattern */ + /* TODO is it really needed ? */ + + enable_phy_bypass_mode(enc110, true); + + /* Program 80 bit custom pattern */ + { + uint16_t pattern_symbols[8]; + + pattern_symbols[0] = + ((pattern[1] & 0x03) << 8) | pattern[0]; + pattern_symbols[1] = + ((pattern[2] & 0x0f) << 6) | ((pattern[1] >> 2) & 0x3f); + pattern_symbols[2] = + ((pattern[3] & 0x3f) << 4) | ((pattern[2] >> 4) & 0x0f); + pattern_symbols[3] = + (pattern[4] << 2) | ((pattern[3] >> 6) & 0x03); + pattern_symbols[4] = + ((pattern[6] & 0x03) << 8) | pattern[5]; + pattern_symbols[5] = + ((pattern[7] & 0x0f) << 6) | ((pattern[6] >> 2) & 0x3f); + pattern_symbols[6] = + ((pattern[8] & 0x3f) << 4) | ((pattern[7] >> 4) & 0x0f); + pattern_symbols[7] = + (pattern[9] << 2) | ((pattern[8] >> 6) & 0x03); + + program_pattern_symbols(enc110, pattern_symbols); + } + + /* Enable phy bypass mode to enable the test pattern */ + + enable_phy_bypass_mode(enc110, true); +} + +static void set_dp_phy_pattern_hbr2_compliance( + struct dce110_link_encoder *enc110) +{ + + /* previously there is a register DP_HBR2_EYE_PATTERN + * that is enabled to get the pattern. + * But it does not work with the latest spec change, + * so we are programming the following registers manually. + * + * The following settings have been confirmed + * by Nick Chorney and Sandra Liu */ + + /* Disable PHY Bypass mode to setup the test pattern */ + + enable_phy_bypass_mode(enc110, false); + + /* Setup DIG encoder in DP SST mode */ + + enc110->base.funcs->setup(&enc110->base, SIGNAL_TYPE_DISPLAY_PORT); + + /* program correct panel mode*/ + { + ASSERT(REG(DP_DPHY_INTERNAL_CTRL)); + + REG_WRITE(DP_DPHY_INTERNAL_CTRL, 0x0); + } + + /* no vbid after BS (SR) + * DP_LINK_FRAMING_CNTL changed history Sandra Liu + * 11000260 / 11000104 / 110000FC */ + + /* TODO DP_LINK_FRAMING_CNTL should always use hardware default value + * output except output hbr2_compliance pattern for physical PHY + * measurement. This is not normal usage case. SW should reset this + * register to hardware default value after end use of HBR2 eye + */ + BREAK_TO_DEBUGGER(); + /* TODO: do we still need this, find out at compliance test + addr = mmDP_LINK_FRAMING_CNTL + fe_addr_offset; + + value = dal_read_reg(ctx, addr); + + set_reg_field_value(value, 0xFC, + DP_LINK_FRAMING_CNTL, DP_IDLE_BS_INTERVAL); + set_reg_field_value(value, 1, + DP_LINK_FRAMING_CNTL, DP_VBID_DISABLE); + set_reg_field_value(value, 1, + DP_LINK_FRAMING_CNTL, DP_VID_ENHANCED_FRAME_MODE); + + dal_write_reg(ctx, addr, value); + */ + /* swap every BS with SR */ + + REG_UPDATE(DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_BS_COUNT, 0); + + /*TODO add support for this test pattern + * support_dp_hbr2_eye_pattern + */ + + /* set link training complete */ + set_link_training_complete(enc110, true); + /* do not enable video stream */ + + REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, 0); + + /* Disable PHY Bypass mode to setup the test pattern */ + + enable_phy_bypass_mode(enc110, false); +} + +static void set_dp_phy_pattern_passthrough_mode( + struct dce110_link_encoder *enc110, + enum dp_panel_mode panel_mode) +{ + uint32_t value; + + /* program correct panel mode */ + { + ASSERT(REG(DP_DPHY_INTERNAL_CTRL)); + value = REG_READ(DP_DPHY_INTERNAL_CTRL); + + switch (panel_mode) { + case DP_PANEL_MODE_EDP: + value = 0x1; + break; + case DP_PANEL_MODE_SPECIAL: + value = 0x11; + break; + default: + value = 0x0; + break; + } + + REG_WRITE(DP_DPHY_INTERNAL_CTRL, value); + } + + REG_UPDATE(DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_BS_COUNT, 0x1FF); + + /* set link training complete */ + + set_link_training_complete(enc110, true); + + /* Disable PHY Bypass mode to setup the test pattern */ + + enable_phy_bypass_mode(enc110, false); + + /* Disable PRBS mode, + * make sure DPHY_PRBS_CNTL.DPHY_PRBS_EN=0 */ + + disable_prbs_mode(enc110); +} + +/* return value is bit-vector */ +static uint8_t get_frontend_source( + enum engine_id engine) +{ + switch (engine) { + case ENGINE_ID_DIGA: + return DCE110_DIG_FE_SOURCE_SELECT_DIGA; + case ENGINE_ID_DIGB: + return DCE110_DIG_FE_SOURCE_SELECT_DIGB; + case ENGINE_ID_DIGC: + return DCE110_DIG_FE_SOURCE_SELECT_DIGC; + case ENGINE_ID_DIGD: + return DCE110_DIG_FE_SOURCE_SELECT_DIGD; + case ENGINE_ID_DIGE: + return DCE110_DIG_FE_SOURCE_SELECT_DIGE; + case ENGINE_ID_DIGF: + return DCE110_DIG_FE_SOURCE_SELECT_DIGF; + default: + ASSERT_CRITICAL(false); + return DCE110_DIG_FE_SOURCE_SELECT_INVALID; + } +} + +static void configure_encoder( + struct dce110_link_encoder *enc110, + const struct dc_link_settings *link_settings) +{ + /* set number of lanes */ + + REG_SET(DP_CONFIG, 0, + DP_UDI_LANES, link_settings->lane_count - LANE_COUNT_ONE); + + /* setup scrambler */ + REG_UPDATE(DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_ADVANCE, 1); +} + +static bool is_panel_powered_on(struct dce110_link_encoder *enc110) +{ + bool ret; + uint32_t value; + + REG_GET(LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, &value); + ret = value; + + return ret == 1; +} + + +/* TODO duplicate of dc_link.c version */ +static struct gpio *get_hpd_gpio(const struct link_encoder *enc) +{ + enum bp_result bp_result; + struct dc_bios *dcb = enc->ctx->dc_bios; + struct graphics_object_hpd_info hpd_info; + struct gpio_pin_info pin_info; + + if (dcb->funcs->get_hpd_info(dcb, enc->connector, &hpd_info) != BP_RESULT_OK) + return NULL; + + bp_result = dcb->funcs->get_gpio_pin_info(dcb, + hpd_info.hpd_int_gpio_uid, &pin_info); + + if (bp_result != BP_RESULT_OK) { + ASSERT(bp_result == BP_RESULT_NORECORD); + return NULL; + } + + return dal_gpio_service_create_irq( + enc->ctx->gpio_service, + pin_info.offset, + pin_info.mask); +} + +/* + * @brief + * eDP only. + */ +static void link_encoder_edp_wait_for_hpd_ready( + struct dce110_link_encoder *enc110, + bool power_up) +{ + struct dc_context *ctx = enc110->base.ctx; + struct graphics_object_id connector = enc110->base.connector; + struct gpio *hpd; + bool edp_hpd_high = false; + uint32_t time_elapsed = 0; + uint32_t timeout = power_up ? + PANEL_POWER_UP_TIMEOUT : PANEL_POWER_DOWN_TIMEOUT; + + if (dal_graphics_object_id_get_connector_id(connector) != + CONNECTOR_ID_EDP) { + BREAK_TO_DEBUGGER(); + return; + } + + if (!power_up) + /* from KV, we will not HPD low after turning off VCC - + * instead, we will check the SW timer in power_up(). */ + return; + + /* when we power on/off the eDP panel, + * we need to wait until SENSE bit is high/low */ + + /* obtain HPD */ + /* TODO what to do with this? */ + hpd = get_hpd_gpio(&enc110->base); + + if (!hpd) { + BREAK_TO_DEBUGGER(); + return; + } + + dal_gpio_open(hpd, GPIO_MODE_INTERRUPT); + + /* wait until timeout or panel detected */ + + do { + uint32_t detected = 0; + + dal_gpio_get_value(hpd, &detected); + + if (!(detected ^ power_up)) { + edp_hpd_high = true; + break; + } + + msleep(HPD_CHECK_INTERVAL); + + time_elapsed += HPD_CHECK_INTERVAL; + } while (time_elapsed < timeout); + + dal_gpio_close(hpd); + + dal_gpio_destroy_irq(&hpd); + + if (false == edp_hpd_high) { + dm_logger_write(ctx->logger, LOG_ERROR, + "%s: wait timed out!\n", __func__); + } +} + +/* + * @brief + * eDP only. Control the power of the eDP panel. + */ +void dce110_link_encoder_edp_power_control( + struct link_encoder *enc, + bool power_up) +{ + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + struct dc_context *ctx = enc110->base.ctx; + struct bp_transmitter_control cntl = { 0 }; + enum bp_result bp_result; + + if (dal_graphics_object_id_get_connector_id(enc110->base.connector) != + CONNECTOR_ID_EDP) { + BREAK_TO_DEBUGGER(); + return; + } + + if ((power_up && !is_panel_powered_on(enc110)) || + (!power_up && is_panel_powered_on(enc110))) { + + /* Send VBIOS command to prompt eDP panel power */ + + dm_logger_write(ctx->logger, LOG_HW_RESUME_S3, + "%s: Panel Power action: %s\n", + __func__, (power_up ? "On":"Off")); + + cntl.action = power_up ? + TRANSMITTER_CONTROL_POWER_ON : + TRANSMITTER_CONTROL_POWER_OFF; + cntl.transmitter = enc110->base.transmitter; + cntl.connector_obj_id = enc110->base.connector; + cntl.coherent = false; + cntl.lanes_number = LANE_COUNT_FOUR; + cntl.hpd_sel = enc110->base.hpd_source; + + bp_result = link_transmitter_control(enc110, &cntl); + + if (BP_RESULT_OK != bp_result) { + + dm_logger_write(ctx->logger, LOG_ERROR, + "%s: Panel Power bp_result: %d\n", + __func__, bp_result); + } + } else { + dm_logger_write(ctx->logger, LOG_HW_RESUME_S3, + "%s: Skipping Panel Power action: %s\n", + __func__, (power_up ? "On":"Off")); + } + + link_encoder_edp_wait_for_hpd_ready(enc110, true); +} + +static void aux_initialize( + struct dce110_link_encoder *enc110) +{ + struct dc_context *ctx = enc110->base.ctx; + enum hpd_source_id hpd_source = enc110->base.hpd_source; + uint32_t addr = AUX_REG(AUX_CONTROL); + uint32_t value = dm_read_reg(ctx, addr); + + set_reg_field_value(value, hpd_source, AUX_CONTROL, AUX_HPD_SEL); + set_reg_field_value(value, 0, AUX_CONTROL, AUX_LS_READ_EN); + dm_write_reg(ctx, addr, value); + + addr = AUX_REG(AUX_DPHY_RX_CONTROL0); + value = dm_read_reg(ctx, addr); + + /* 1/4 window (the maximum allowed) */ + set_reg_field_value(value, 1, + AUX_DPHY_RX_CONTROL0, AUX_RX_RECEIVE_WINDOW); + dm_write_reg(ctx, addr, value); + +} + +/*todo: cloned in stream enc, fix*/ +static bool is_panel_backlight_on(struct dce110_link_encoder *enc110) +{ + uint32_t value; + + REG_GET(LVTMA_PWRSEQ_CNTL, LVTMA_BLON, &value); + + return value; +} + +/*todo: cloned in stream enc, fix*/ +/* + * @brief + * eDP only. Control the backlight of the eDP panel + */ +void dce110_link_encoder_edp_backlight_control( + struct link_encoder *enc, + bool enable) +{ + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + struct dc_context *ctx = enc110->base.ctx; + struct bp_transmitter_control cntl = { 0 }; + + if (dal_graphics_object_id_get_connector_id(enc110->base.connector) + != CONNECTOR_ID_EDP) { + BREAK_TO_DEBUGGER(); + return; + } + + if (enable && is_panel_backlight_on(enc110)) { + dm_logger_write(ctx->logger, LOG_HW_RESUME_S3, + "%s: panel already powered up. Do nothing.\n", + __func__); + return; + } + + if (!enable && !is_panel_powered_on(enc110)) { + dm_logger_write(ctx->logger, LOG_HW_RESUME_S3, + "%s: panel already powered down. Do nothing.\n", + __func__); + return; + } + + /* Send VBIOS command to control eDP panel backlight */ + + dm_logger_write(ctx->logger, LOG_HW_RESUME_S3, + "%s: backlight action: %s\n", + __func__, (enable ? "On":"Off")); + + cntl.action = enable ? + TRANSMITTER_CONTROL_BACKLIGHT_ON : + TRANSMITTER_CONTROL_BACKLIGHT_OFF; + /*cntl.engine_id = ctx->engine;*/ + cntl.transmitter = enc110->base.transmitter; + cntl.connector_obj_id = enc110->base.connector; + /*todo: unhardcode*/ + cntl.lanes_number = LANE_COUNT_FOUR; + cntl.hpd_sel = enc110->base.hpd_source; + + /* For eDP, the following delays might need to be considered + * after link training completed: + * idle period - min. accounts for required BS-Idle pattern, + * max. allows for source frame synchronization); + * 50 msec max. delay from valid video data from source + * to video on dislpay or backlight enable. + * + * Disable the delay for now. + * Enable it in the future if necessary. + */ + /* dc_service_sleep_in_milliseconds(50); */ + link_transmitter_control(enc110, &cntl); +} + +static bool is_dig_enabled(const struct dce110_link_encoder *enc110) +{ + uint32_t value; + + REG_GET(DIG_BE_EN_CNTL, DIG_ENABLE, &value); + return value; +} + +static void link_encoder_disable(struct dce110_link_encoder *enc110) +{ + /* reset training pattern */ + REG_SET(DP_DPHY_TRAINING_PATTERN_SEL, 0, + DPHY_TRAINING_PATTERN_SEL, 0); + + /* reset training complete */ + REG_UPDATE(DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE, 0); + + /* reset panel mode */ + ASSERT(REG(DP_DPHY_INTERNAL_CTRL)); + REG_WRITE(DP_DPHY_INTERNAL_CTRL, 0); +} + +static void hpd_initialize( + struct dce110_link_encoder *enc110) +{ + /* Associate HPD with DIG_BE */ + enum hpd_source_id hpd_source = enc110->base.hpd_source; + + REG_UPDATE(DIG_BE_CNTL, DIG_HPD_SELECT, hpd_source); +} + +bool dce110_link_encoder_validate_dvi_output( + const struct dce110_link_encoder *enc110, + enum signal_type connector_signal, + enum signal_type signal, + const struct dc_crtc_timing *crtc_timing) +{ + uint32_t max_pixel_clock = TMDS_MAX_PIXEL_CLOCK; + + if (enc110->base.features.max_pixel_clock < TMDS_MAX_PIXEL_CLOCK) + max_pixel_clock = enc110->base.features.max_pixel_clock; + + if (signal == SIGNAL_TYPE_DVI_DUAL_LINK) + max_pixel_clock <<= 1; + + /* This handles the case of HDMI downgrade to DVI we don't want to + * we don't want to cap the pixel clock if the DDI is not DVI. + */ + if (connector_signal != SIGNAL_TYPE_DVI_DUAL_LINK && + connector_signal != SIGNAL_TYPE_DVI_SINGLE_LINK) + max_pixel_clock = enc110->base.features.max_pixel_clock; + + /* DVI only support RGB pixel encoding */ + if (crtc_timing->pixel_encoding != PIXEL_ENCODING_RGB) + return false; + + if (crtc_timing->pix_clk_khz < TMDS_MIN_PIXEL_CLOCK) + return false; + + if (crtc_timing->pix_clk_khz > max_pixel_clock) + return false; + + /* DVI supports 6/8bpp single-link and 10/16bpp dual-link */ + switch (crtc_timing->display_color_depth) { + case COLOR_DEPTH_666: + case COLOR_DEPTH_888: + break; + case COLOR_DEPTH_101010: + case COLOR_DEPTH_161616: + if (signal != SIGNAL_TYPE_DVI_DUAL_LINK) + return false; + break; + default: + return false; + } + + return true; +} + +static bool dce110_link_encoder_validate_hdmi_output( + const struct dce110_link_encoder *enc110, + const struct dc_crtc_timing *crtc_timing, + int adjusted_pix_clk_khz) +{ + enum dc_color_depth max_deep_color = + enc110->base.features.max_hdmi_deep_color; + + if (max_deep_color > enc110->base.features.max_deep_color) + max_deep_color = enc110->base.features.max_deep_color; + + if (max_deep_color < crtc_timing->display_color_depth) + return false; + + if (adjusted_pix_clk_khz < TMDS_MIN_PIXEL_CLOCK) + return false; + + if ((adjusted_pix_clk_khz == 0) || + (adjusted_pix_clk_khz > enc110->base.features.max_hdmi_pixel_clock) || + (adjusted_pix_clk_khz > enc110->base.features.max_pixel_clock)) + return false; + + /* DCE11 HW does not support 420 */ + if (!enc110->base.features.ycbcr420_supported && + crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) + return false; + + return true; +} + +bool dce110_link_encoder_validate_rgb_output( + const struct dce110_link_encoder *enc110, + const struct dc_crtc_timing *crtc_timing) +{ + if (crtc_timing->pix_clk_khz > enc110->base.features.max_pixel_clock) + return false; + + if (crtc_timing->pixel_encoding != PIXEL_ENCODING_RGB) + return false; + + return true; +} + +bool dce110_link_encoder_validate_dp_output( + const struct dce110_link_encoder *enc110, + const struct dc_crtc_timing *crtc_timing) +{ + /* default RGB only */ + if (crtc_timing->pixel_encoding == PIXEL_ENCODING_RGB) + return true; + + if (enc110->base.features.flags.bits.IS_YCBCR_CAPABLE) + return true; + + /* for DCE 8.x or later DP Y-only feature, + * we need ASIC cap + FeatureSupportDPYonly, not support 666 */ + if (crtc_timing->flags.Y_ONLY && + enc110->base.features.flags.bits.IS_YCBCR_CAPABLE && + crtc_timing->display_color_depth != COLOR_DEPTH_666) + return true; + + return false; +} + +bool dce110_link_encoder_validate_wireless_output( + const struct dce110_link_encoder *enc110, + const struct dc_crtc_timing *crtc_timing) +{ + if (crtc_timing->pix_clk_khz > enc110->base.features.max_pixel_clock) + return false; + + /* Wireless only supports YCbCr444 */ + if (crtc_timing->pixel_encoding == + PIXEL_ENCODING_YCBCR444) + return true; + + return false; +} + +bool dce110_link_encoder_construct( + struct dce110_link_encoder *enc110, + const struct encoder_init_data *init_data, + const struct dce110_link_enc_registers *link_regs, + const struct dce110_link_enc_aux_registers *aux_regs, + const struct dce110_link_enc_hpd_registers *hpd_regs) +{ + enc110->base.funcs = &dce110_lnk_enc_funcs; + enc110->base.ctx = init_data->ctx; + enc110->base.id = init_data->encoder; + + enc110->base.hpd_source = init_data->hpd_source; + enc110->base.connector = init_data->connector; + enc110->base.input_signals = SIGNAL_TYPE_ALL; + + enc110->base.preferred_engine = ENGINE_ID_UNKNOWN; + + enc110->base.features.flags.raw = 0; + + enc110->base.transmitter = init_data->transmitter; + + enc110->base.features.flags.bits.IS_AUDIO_CAPABLE = true; + + enc110->base.features.max_pixel_clock = + MAX_ENCODER_CLK; + + enc110->base.features.max_deep_color = COLOR_DEPTH_121212; + enc110->base.features.max_hdmi_deep_color = COLOR_DEPTH_121212; + + /* set the flag to indicate whether driver poll the I2C data pin + * while doing the DP sink detect + */ + +/* if (dal_adapter_service_is_feature_supported(as, + FEATURE_DP_SINK_DETECT_POLL_DATA_PIN)) + enc110->base.features.flags.bits. + DP_SINK_DETECT_POLL_DATA_PIN = true;*/ + + enc110->base.output_signals = + SIGNAL_TYPE_DVI_SINGLE_LINK | + SIGNAL_TYPE_DVI_DUAL_LINK | + SIGNAL_TYPE_LVDS | + SIGNAL_TYPE_DISPLAY_PORT | + SIGNAL_TYPE_DISPLAY_PORT_MST | + SIGNAL_TYPE_EDP | + SIGNAL_TYPE_HDMI_TYPE_A; + + /* For DCE 8.0 and 8.1, by design, UNIPHY is hardwired to DIG_BE. + * SW always assign DIG_FE 1:1 mapped to DIG_FE for non-MST UNIPHY. + * SW assign DIG_FE to non-MST UNIPHY first and MST last. So prefer + * DIG is per UNIPHY and used by SST DP, eDP, HDMI, DVI and LVDS. + * Prefer DIG assignment is decided by board design. + * For DCE 8.0, there are only max 6 UNIPHYs, we assume board design + * and VBIOS will filter out 7 UNIPHY for DCE 8.0. + * By this, adding DIGG should not hurt DCE 8.0. + * This will let DCE 8.1 share DCE 8.0 as much as possible + */ + + enc110->link_regs = link_regs; + enc110->aux_regs = aux_regs; + enc110->hpd_regs = hpd_regs; + + switch (enc110->base.transmitter) { + case TRANSMITTER_UNIPHY_A: + enc110->base.preferred_engine = ENGINE_ID_DIGA; + break; + case TRANSMITTER_UNIPHY_B: + enc110->base.preferred_engine = ENGINE_ID_DIGB; + break; + case TRANSMITTER_UNIPHY_C: + enc110->base.preferred_engine = ENGINE_ID_DIGC; + break; + case TRANSMITTER_UNIPHY_D: + enc110->base.preferred_engine = ENGINE_ID_DIGD; + break; + case TRANSMITTER_UNIPHY_E: + enc110->base.preferred_engine = ENGINE_ID_DIGE; + break; + case TRANSMITTER_UNIPHY_F: + enc110->base.preferred_engine = ENGINE_ID_DIGF; + break; + default: + ASSERT_CRITICAL(false); + enc110->base.preferred_engine = ENGINE_ID_UNKNOWN; + } + + dm_logger_write(init_data->ctx->logger, LOG_I2C_AUX, + "Using channel: %s [%d]\n", + DECODE_CHANNEL_ID(init_data->channel), + init_data->channel); + + /* Override features with DCE-specific values */ + { + struct bp_encoder_cap_info bp_cap_info = {0}; + const struct dc_vbios_funcs *bp_funcs = enc110->base.ctx->dc_bios->funcs; + + if (BP_RESULT_OK == bp_funcs->get_encoder_cap_info( + enc110->base.ctx->dc_bios, enc110->base.id, + &bp_cap_info)) + enc110->base.features.flags.bits.IS_HBR2_CAPABLE = + bp_cap_info.DP_HBR2_CAP; + } + /* test pattern 3 support */ + enc110->base.features.flags.bits.IS_TPS3_CAPABLE = true; + + enc110->base.features.flags.bits.IS_Y_ONLY_CAPABLE = false; + /* + dal_adapter_service_is_feature_supported(as, + FEATURE_SUPPORT_DP_Y_ONLY); +*/ + enc110->base.features.flags.bits.IS_YCBCR_CAPABLE = true; + /* + dal_adapter_service_is_feature_supported(as, + FEATURE_SUPPORT_DP_YUV); + */ + return true; +} + +bool dce110_link_encoder_validate_output_with_stream( + struct link_encoder *enc, + struct pipe_ctx *pipe_ctx) +{ + struct core_stream *stream = pipe_ctx->stream; + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + bool is_valid; + + switch (pipe_ctx->stream->signal) { + case SIGNAL_TYPE_DVI_SINGLE_LINK: + case SIGNAL_TYPE_DVI_DUAL_LINK: + is_valid = dce110_link_encoder_validate_dvi_output( + enc110, + stream->sink->link->public.connector_signal, + pipe_ctx->stream->signal, + &stream->public.timing); + break; + case SIGNAL_TYPE_HDMI_TYPE_A: + is_valid = dce110_link_encoder_validate_hdmi_output( + enc110, + &stream->public.timing, + stream->phy_pix_clk); + break; + case SIGNAL_TYPE_RGB: + is_valid = dce110_link_encoder_validate_rgb_output( + enc110, &stream->public.timing); + break; + case SIGNAL_TYPE_DISPLAY_PORT: + case SIGNAL_TYPE_DISPLAY_PORT_MST: + case SIGNAL_TYPE_EDP: + is_valid = dce110_link_encoder_validate_dp_output( + enc110, &stream->public.timing); + break; + case SIGNAL_TYPE_WIRELESS: + is_valid = dce110_link_encoder_validate_wireless_output( + enc110, &stream->public.timing); + break; + default: + is_valid = true; + break; + } + + return is_valid; +} + +void dce110_link_encoder_hw_init( + struct link_encoder *enc) +{ + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + struct dc_context *ctx = enc110->base.ctx; + struct bp_transmitter_control cntl = { 0 }; + enum bp_result result; + + cntl.action = TRANSMITTER_CONTROL_INIT; + cntl.engine_id = ENGINE_ID_UNKNOWN; + cntl.transmitter = enc110->base.transmitter; + cntl.connector_obj_id = enc110->base.connector; + cntl.lanes_number = LANE_COUNT_FOUR; + cntl.coherent = false; + cntl.hpd_sel = enc110->base.hpd_source; + + result = link_transmitter_control(enc110, &cntl); + + if (result != BP_RESULT_OK) { + dm_logger_write(ctx->logger, LOG_ERROR, + "%s: Failed to execute VBIOS command table!\n", + __func__); + BREAK_TO_DEBUGGER(); + return; + } + + if (enc110->base.connector.id == CONNECTOR_ID_LVDS) { + cntl.action = TRANSMITTER_CONTROL_BACKLIGHT_BRIGHTNESS; + + result = link_transmitter_control(enc110, &cntl); + + ASSERT(result == BP_RESULT_OK); + + } else if (enc110->base.connector.id == CONNECTOR_ID_EDP) { + enc->funcs->power_control(&enc110->base, true); + } + aux_initialize(enc110); + + /* reinitialize HPD. + * hpd_initialize() will pass DIG_FE id to HW context. + * All other routine within HW context will use fe_engine_offset + * as DIG_FE id even caller pass DIG_FE id. + * So this routine must be called first. */ + hpd_initialize(enc110); +} + +void dce110_link_encoder_destroy(struct link_encoder **enc) +{ + dm_free(TO_DCE110_LINK_ENC(*enc)); + *enc = NULL; +} + +void dce110_link_encoder_setup( + struct link_encoder *enc, + enum signal_type signal) +{ + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + + switch (signal) { + case SIGNAL_TYPE_EDP: + case SIGNAL_TYPE_DISPLAY_PORT: + /* DP SST */ + REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 0); + break; + case SIGNAL_TYPE_LVDS: + /* LVDS */ + REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 1); + break; + case SIGNAL_TYPE_DVI_SINGLE_LINK: + case SIGNAL_TYPE_DVI_DUAL_LINK: + /* TMDS-DVI */ + REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 2); + break; + case SIGNAL_TYPE_HDMI_TYPE_A: + /* TMDS-HDMI */ + REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 3); + break; + case SIGNAL_TYPE_DISPLAY_PORT_MST: + /* DP MST */ + REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 5); + break; + default: + ASSERT_CRITICAL(false); + /* invalid mode ! */ + break; + } + +} + +/* TODO: still need depth or just pass in adjusted pixel clock? */ +void dce110_link_encoder_enable_tmds_output( + struct link_encoder *enc, + enum clock_source_id clock_source, + enum dc_color_depth color_depth, + bool hdmi, + bool dual_link, + uint32_t pixel_clock) +{ + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + struct dc_context *ctx = enc110->base.ctx; + struct bp_transmitter_control cntl = { 0 }; + enum bp_result result; + + /* Enable the PHY */ + + cntl.action = TRANSMITTER_CONTROL_ENABLE; + cntl.engine_id = ENGINE_ID_UNKNOWN; + cntl.transmitter = enc110->base.transmitter; + cntl.pll_id = clock_source; + if (hdmi) { + cntl.signal = SIGNAL_TYPE_HDMI_TYPE_A; + cntl.lanes_number = 4; + } else if (dual_link) { + cntl.signal = SIGNAL_TYPE_DVI_DUAL_LINK; + cntl.lanes_number = 8; + } else { + cntl.signal = SIGNAL_TYPE_DVI_SINGLE_LINK; + cntl.lanes_number = 4; + } + cntl.hpd_sel = enc110->base.hpd_source; + + cntl.pixel_clock = pixel_clock; + cntl.color_depth = color_depth; + + result = link_transmitter_control(enc110, &cntl); + + if (result != BP_RESULT_OK) { + dm_logger_write(ctx->logger, LOG_ERROR, + "%s: Failed to execute VBIOS command table!\n", + __func__); + BREAK_TO_DEBUGGER(); + } +} + +/* enables DP PHY output */ +void dce110_link_encoder_enable_dp_output( + struct link_encoder *enc, + const struct dc_link_settings *link_settings, + enum clock_source_id clock_source) +{ + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + struct dc_context *ctx = enc110->base.ctx; + struct bp_transmitter_control cntl = { 0 }; + enum bp_result result; + + /* Enable the PHY */ + + /* number_of_lanes is used for pixel clock adjust, + * but it's not passed to asic_control. + * We need to set number of lanes manually. + */ + configure_encoder(enc110, link_settings); + + cntl.action = TRANSMITTER_CONTROL_ENABLE; + cntl.engine_id = ENGINE_ID_UNKNOWN; + cntl.transmitter = enc110->base.transmitter; + cntl.pll_id = clock_source; + cntl.signal = SIGNAL_TYPE_DISPLAY_PORT; + cntl.lanes_number = link_settings->lane_count; + cntl.hpd_sel = enc110->base.hpd_source; + cntl.pixel_clock = link_settings->link_rate + * LINK_RATE_REF_FREQ_IN_KHZ; + /* TODO: check if undefined works */ + cntl.color_depth = COLOR_DEPTH_UNDEFINED; + + result = link_transmitter_control(enc110, &cntl); + + if (result != BP_RESULT_OK) { + dm_logger_write(ctx->logger, LOG_ERROR, + "%s: Failed to execute VBIOS command table!\n", + __func__); + BREAK_TO_DEBUGGER(); + } +} + +/* enables DP PHY output in MST mode */ +void dce110_link_encoder_enable_dp_mst_output( + struct link_encoder *enc, + const struct dc_link_settings *link_settings, + enum clock_source_id clock_source) +{ + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + struct dc_context *ctx = enc110->base.ctx; + struct bp_transmitter_control cntl = { 0 }; + enum bp_result result; + + /* Enable the PHY */ + + /* number_of_lanes is used for pixel clock adjust, + * but it's not passed to asic_control. + * We need to set number of lanes manually. + */ + configure_encoder(enc110, link_settings); + + cntl.action = TRANSMITTER_CONTROL_ENABLE; + cntl.engine_id = ENGINE_ID_UNKNOWN; + cntl.transmitter = enc110->base.transmitter; + cntl.pll_id = clock_source; + cntl.signal = SIGNAL_TYPE_DISPLAY_PORT_MST; + cntl.lanes_number = link_settings->lane_count; + cntl.hpd_sel = enc110->base.hpd_source; + cntl.pixel_clock = link_settings->link_rate + * LINK_RATE_REF_FREQ_IN_KHZ; + /* TODO: check if undefined works */ + cntl.color_depth = COLOR_DEPTH_UNDEFINED; + + result = link_transmitter_control(enc110, &cntl); + + if (result != BP_RESULT_OK) { + dm_logger_write(ctx->logger, LOG_ERROR, + "%s: Failed to execute VBIOS command table!\n", + __func__); + BREAK_TO_DEBUGGER(); + } +} +/* + * @brief + * Disable transmitter and its encoder + */ +void dce110_link_encoder_disable_output( + struct link_encoder *enc, + enum signal_type signal) +{ + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + struct dc_context *ctx = enc110->base.ctx; + struct bp_transmitter_control cntl = { 0 }; + enum bp_result result; + + if (!is_dig_enabled(enc110)) { + /* OF_SKIP_POWER_DOWN_INACTIVE_ENCODER */ + return; + } + /* Power-down RX and disable GPU PHY should be paired. + * Disabling PHY without powering down RX may cause + * symbol lock loss, on which we will get DP Sink interrupt. */ + + /* There is a case for the DP active dongles + * where we want to disable the PHY but keep RX powered, + * for those we need to ignore DP Sink interrupt + * by checking lane count that has been set + * on the last do_enable_output(). */ + + /* disable transmitter */ + cntl.action = TRANSMITTER_CONTROL_DISABLE; + cntl.transmitter = enc110->base.transmitter; + cntl.hpd_sel = enc110->base.hpd_source; + cntl.signal = signal; + cntl.connector_obj_id = enc110->base.connector; + + result = link_transmitter_control(enc110, &cntl); + + if (result != BP_RESULT_OK) { + dm_logger_write(ctx->logger, LOG_ERROR, + "%s: Failed to execute VBIOS command table!\n", + __func__); + BREAK_TO_DEBUGGER(); + return; + } + + /* disable encoder */ + if (dc_is_dp_signal(signal)) + link_encoder_disable(enc110); + + if (enc110->base.connector.id == CONNECTOR_ID_EDP) { + /* power down eDP panel */ + /* TODO: Power control cause regression, we should implement + * it properly, for now just comment it. + * + * link_encoder_edp_wait_for_hpd_ready( + link_enc, + link_enc->connector, + false); + + * link_encoder_edp_power_control( + link_enc, false); */ + } +} + +void dce110_link_encoder_dp_set_lane_settings( + struct link_encoder *enc, + const struct link_training_settings *link_settings) +{ + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + union dpcd_training_lane_set training_lane_set = { { 0 } }; + int32_t lane = 0; + struct bp_transmitter_control cntl = { 0 }; + + if (!link_settings) { + BREAK_TO_DEBUGGER(); + return; + } + + cntl.action = TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS; + cntl.transmitter = enc110->base.transmitter; + cntl.connector_obj_id = enc110->base.connector; + cntl.lanes_number = link_settings->link_settings.lane_count; + cntl.hpd_sel = enc110->base.hpd_source; + cntl.pixel_clock = link_settings->link_settings.link_rate * + LINK_RATE_REF_FREQ_IN_KHZ; + + for (lane = 0; lane < link_settings->link_settings.lane_count; ++lane) { + /* translate lane settings */ + + training_lane_set.bits.VOLTAGE_SWING_SET = + link_settings->lane_settings[lane].VOLTAGE_SWING; + training_lane_set.bits.PRE_EMPHASIS_SET = + link_settings->lane_settings[lane].PRE_EMPHASIS; + + /* post cursor 2 setting only applies to HBR2 link rate */ + if (link_settings->link_settings.link_rate == LINK_RATE_HIGH2) { + /* this is passed to VBIOS + * to program post cursor 2 level */ + + training_lane_set.bits.POST_CURSOR2_SET = + link_settings->lane_settings[lane].POST_CURSOR2; + } + + cntl.lane_select = lane; + cntl.lane_settings = training_lane_set.raw; + + /* call VBIOS table to set voltage swing and pre-emphasis */ + link_transmitter_control(enc110, &cntl); + } +} + +/* set DP PHY test and training patterns */ +void dce110_link_encoder_dp_set_phy_pattern( + struct link_encoder *enc, + const struct encoder_set_dp_phy_pattern_param *param) +{ + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + + switch (param->dp_phy_pattern) { + case DP_TEST_PATTERN_TRAINING_PATTERN1: + dce110_link_encoder_set_dp_phy_pattern_training_pattern(enc, 0); + break; + case DP_TEST_PATTERN_TRAINING_PATTERN2: + dce110_link_encoder_set_dp_phy_pattern_training_pattern(enc, 1); + break; + case DP_TEST_PATTERN_TRAINING_PATTERN3: + dce110_link_encoder_set_dp_phy_pattern_training_pattern(enc, 2); + break; + case DP_TEST_PATTERN_D102: + set_dp_phy_pattern_d102(enc110); + break; + case DP_TEST_PATTERN_SYMBOL_ERROR: + set_dp_phy_pattern_symbol_error(enc110); + break; + case DP_TEST_PATTERN_PRBS7: + set_dp_phy_pattern_prbs7(enc110); + break; + case DP_TEST_PATTERN_80BIT_CUSTOM: + set_dp_phy_pattern_80bit_custom( + enc110, param->custom_pattern); + break; + case DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE: + set_dp_phy_pattern_hbr2_compliance(enc110); + break; + case DP_TEST_PATTERN_VIDEO_MODE: { + set_dp_phy_pattern_passthrough_mode( + enc110, param->dp_panel_mode); + break; + } + + default: + /* invalid phy pattern */ + ASSERT_CRITICAL(false); + break; + } +} + +static void fill_stream_allocation_row_info( + const struct link_mst_stream_allocation *stream_allocation, + uint32_t *src, + uint32_t *slots) +{ + const struct stream_encoder *stream_enc = stream_allocation->stream_enc; + + if (stream_enc) { + *src = stream_enc->id; + *slots = stream_allocation->slot_count; + } else { + *src = 0; + *slots = 0; + } +} + +/* programs DP MST VC payload allocation */ +void dce110_link_encoder_update_mst_stream_allocation_table( + struct link_encoder *enc, + const struct link_mst_stream_allocation_table *table) +{ + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + uint32_t value0 = 0; + uint32_t value1 = 0; + uint32_t value2 = 0; + uint32_t slots = 0; + uint32_t src = 0; + uint32_t retries = 0; + + /* For CZ, there are only 3 pipes. So Virtual channel is up 3.*/ + + /* --- Set MSE Stream Attribute - + * Setup VC Payload Table on Tx Side, + * Issue allocation change trigger + * to commit payload on both tx and rx side */ + + /* we should clean-up table each time */ + + if (table->stream_count >= 1) { + fill_stream_allocation_row_info( + &table->stream_allocations[0], + &src, + &slots); + } else { + src = 0; + slots = 0; + } + + REG_UPDATE_2(DP_MSE_SAT0, + DP_MSE_SAT_SRC0, src, + DP_MSE_SAT_SLOT_COUNT0, slots); + + if (table->stream_count >= 2) { + fill_stream_allocation_row_info( + &table->stream_allocations[1], + &src, + &slots); + } else { + src = 0; + slots = 0; + } + + REG_UPDATE_2(DP_MSE_SAT0, + DP_MSE_SAT_SRC1, src, + DP_MSE_SAT_SLOT_COUNT1, slots); + + if (table->stream_count >= 3) { + fill_stream_allocation_row_info( + &table->stream_allocations[2], + &src, + &slots); + } else { + src = 0; + slots = 0; + } + + REG_UPDATE_2(DP_MSE_SAT1, + DP_MSE_SAT_SRC2, src, + DP_MSE_SAT_SLOT_COUNT2, slots); + + if (table->stream_count >= 4) { + fill_stream_allocation_row_info( + &table->stream_allocations[3], + &src, + &slots); + } else { + src = 0; + slots = 0; + } + + REG_UPDATE_2(DP_MSE_SAT1, + DP_MSE_SAT_SRC3, src, + DP_MSE_SAT_SLOT_COUNT3, slots); + + /* --- wait for transaction finish */ + + /* send allocation change trigger (ACT) ? + * this step first sends the ACT, + * then double buffers the SAT into the hardware + * making the new allocation active on the DP MST mode link */ + + + /* DP_MSE_SAT_UPDATE: + * 0 - No Action + * 1 - Update SAT with trigger + * 2 - Update SAT without trigger */ + + REG_UPDATE(DP_MSE_SAT_UPDATE, + DP_MSE_SAT_UPDATE, 1); + + /* wait for update to complete + * (i.e. DP_MSE_SAT_UPDATE field is reset to 0) + * then wait for the transmission + * of at least 16 MTP headers on immediate local link. + * i.e. DP_MSE_16_MTP_KEEPOUT field (read only) is reset to 0 + * a value of 1 indicates that DP MST mode + * is in the 16 MTP keepout region after a VC has been added. + * MST stream bandwidth (VC rate) can be configured + * after this bit is cleared */ + + do { + udelay(10); + + value0 = REG_READ(DP_MSE_SAT_UPDATE); + + REG_GET(DP_MSE_SAT_UPDATE, + DP_MSE_SAT_UPDATE, &value1); + + REG_GET(DP_MSE_SAT_UPDATE, + DP_MSE_16_MTP_KEEPOUT, &value2); + + /* bit field DP_MSE_SAT_UPDATE is set to 1 already */ + if (!value1 && !value2) + break; + ++retries; + } while (retries < DP_MST_UPDATE_MAX_RETRY); +} + +void dce110_link_encoder_set_lcd_backlight_level( + struct link_encoder *enc, + uint32_t level) +{ + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + + const uint32_t backlight_update_pending_max_retry = 1000; + + uint32_t backlight_lock; + + uint32_t i; + uint32_t backlight_24bit; + uint32_t backlight_17bit; + uint32_t backlight_16bit; + uint32_t masked_pwm_period; + uint8_t rounding_bit; + uint8_t bit_count; + uint64_t active_duty_cycle; + uint32_t pwm_period_bitcnt; + + backlight_lock = REG_READ(BL_PWM_GRP1_REG_LOCK); + + /* + * 1. Convert 8-bit value to 17 bit U1.16 format + * (1 integer, 16 fractional bits) + */ + + /* 1.1 multiply 8 bit value by 0x10101 to get a 24 bit value, + * effectively multiplying value by 256/255 + * eg. for a level of 0xEF, backlight_24bit = 0xEF * 0x10101 = 0xEFEFEF + */ + backlight_24bit = level * 0x10101; + + /* 1.2 The upper 16 bits of the 24 bit value is the fraction, lower 8 + * used for rounding, take most significant bit of fraction for + * rounding, e.g. for 0xEFEFEF, rounding bit is 1 + */ + rounding_bit = (backlight_24bit >> 7) & 1; + + /* 1.3 Add the upper 16 bits of the 24 bit value with the rounding bit + * resulting in a 17 bit value e.g. 0xEFF0 = (0xEFEFEF >> 8) + 1 + */ + backlight_17bit = (backlight_24bit >> 8) + rounding_bit; + + /* + * 2. Find 16 bit backlight active duty cycle, where 0 <= backlight + * active duty cycle <= backlight period + */ + + /* 2.1 Apply bitmask for backlight period value based on value of BITCNT + */ + { + REG_GET(BL_PWM_PERIOD_CNTL, + BL_PWM_PERIOD_BITCNT, &pwm_period_bitcnt); + + if (pwm_period_bitcnt == 0) + bit_count = 16; + else + bit_count = pwm_period_bitcnt; + } + + /* e.g. maskedPwmPeriod = 0x24 when bitCount is 6 */ + masked_pwm_period = + REG_GET(BL_PWM_PERIOD_CNTL, + BL_PWM_PERIOD, &masked_pwm_period) + & ((1 << bit_count) - 1); + + /* 2.2 Calculate integer active duty cycle required upper 16 bits + * contain integer component, lower 16 bits contain fractional component + * of active duty cycle e.g. 0x21BDC0 = 0xEFF0 * 0x24 + */ + active_duty_cycle = backlight_17bit * masked_pwm_period; + + /* 2.3 Calculate 16 bit active duty cycle from integer and fractional + * components shift by bitCount then mask 16 bits and add rounding bit + * from MSB of fraction e.g. 0x86F7 = ((0x21BDC0 >> 6) & 0xFFF) + 0 + */ + backlight_16bit = active_duty_cycle >> bit_count; + backlight_16bit &= 0xFFFF; + backlight_16bit += (active_duty_cycle >> (bit_count - 1)) & 0x1; + + REG_UPDATE(BL_PWM_CNTL, + BL_ACTIVE_INT_FRAC_CNT, backlight_16bit); + + /* + * 3. Program register with updated value + */ + + /* 3.1 Lock group 2 backlight registers */ + + REG_UPDATE(BL_PWM_GRP1_REG_LOCK, + BL_PWM_GRP1_IGNORE_MASTER_LOCK_EN, 1); + + REG_UPDATE(BL_PWM_GRP1_REG_LOCK, + BL_PWM_GRP1_REG_LOCK, 1); + + /* 3.3 Unlock group 2 backlight registers */ + REG_UPDATE(BL_PWM_GRP1_REG_LOCK, + BL_PWM_GRP1_REG_LOCK, 0); + + /* 5.4.4 Wait for pending bit to be cleared */ + for (i = 0; i < backlight_update_pending_max_retry; ++i) { + REG_GET(BL_PWM_GRP1_REG_LOCK, + BL_PWM_GRP1_REG_UPDATE_PENDING, &backlight_lock); + if (!backlight_lock) + break; + + udelay(10); + } +} + +void dce110_link_encoder_set_dmcu_backlight_level( + struct link_encoder *enc, + uint32_t level, + uint32_t frame_ramp, + uint32_t controller_id) +{ + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + struct dc_context *ctx = enc110->base.ctx; + unsigned int dmcu_max_retry_on_wait_reg_ready = 801; + unsigned int dmcu_wait_reg_ready_interval = 100; + unsigned int backlight_17bit = level * 0x10101; + unsigned char temp_uchar = + (unsigned char)(((backlight_17bit & 0x80) >> 7) & 1); + unsigned int regValue; + uint32_t rampingBoundary = 0xFFFF; + uint32_t s2; + + backlight_17bit = (backlight_17bit >> 8) + temp_uchar; + + /* set ramping boundary */ + REG_WRITE(MASTER_COMM_DATA_REG1, rampingBoundary); + + /* setDMCUParam_Pipe */ + REG_UPDATE_2(MASTER_COMM_CMD_REG, + MASTER_COMM_CMD_REG_BYTE0, MCP_ABM_PIPE_SET, + MASTER_COMM_CMD_REG_BYTE1, controller_id); + + /* notifyDMCUMsg */ + REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); + + /* waitDMCUReadyForCmd */ + do { + dm_delay_in_microseconds(ctx, dmcu_wait_reg_ready_interval); + regValue = REG_READ(MASTER_COMM_CNTL_REG); + dmcu_max_retry_on_wait_reg_ready--; + } while + /* expected value is 0, loop while not 0*/ + ((MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK & regValue) && + dmcu_max_retry_on_wait_reg_ready > 0); + + /* setDMCUParam_BL */ + REG_UPDATE(BL1_PWM_USER_LEVEL, BL1_PWM_USER_LEVEL, backlight_17bit); + + /* write ramp */ + REG_WRITE(MASTER_COMM_DATA_REG1, frame_ramp); + + /* setDMCUParam_Cmd */ + REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, MCP_BL_SET); + + /* notifyDMCUMsg */ + REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); + + /* UpdateRequestedBacklightLevel */ + s2 = REG_READ(BIOS_SCRATCH_2); + + s2 &= ~ATOM_S2_CURRENT_BL_LEVEL_MASK; + level &= (ATOM_S2_CURRENT_BL_LEVEL_MASK >> + ATOM_S2_CURRENT_BL_LEVEL_SHIFT); + s2 |= (level << ATOM_S2_CURRENT_BL_LEVEL_SHIFT); + + REG_WRITE(BIOS_SCRATCH_2, s2); +} + +void dce110_link_encoder_init_dmcu_backlight_settings( + struct link_encoder *enc) +{ + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + uint32_t bl_pwm_cntl; + uint32_t pwmCntl; + uint32_t pwmCntl2; + uint32_t periodCntl; + uint32_t s2; + uint32_t value; + + bl_pwm_cntl = REG_READ(BL_PWM_CNTL); + + /* It must not be 0, so we have to restore them + * Bios bug w/a - period resets to zero, + * restoring to cache values which is always correct + */ + REG_GET(BL_PWM_CNTL, + BL_ACTIVE_INT_FRAC_CNT, &value); + if (value == 0 || bl_pwm_cntl == 1) { + if (stored_backlight_registers.vBL_PWM_CNTL != 0) { + pwmCntl = stored_backlight_registers.vBL_PWM_CNTL; + REG_WRITE(BL_PWM_CNTL, pwmCntl); + + pwmCntl2 = stored_backlight_registers.vBL_PWM_CNTL2; + REG_WRITE(BL_PWM_CNTL2, pwmCntl2); + + periodCntl = + stored_backlight_registers.vBL_PWM_PERIOD_CNTL; + REG_WRITE(BL_PWM_PERIOD_CNTL, periodCntl); + + REG_UPDATE(LVTMA_PWRSEQ_REF_DIV, + BL_PWM_REF_DIV, + stored_backlight_registers. + vLVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV); + } + } else { + stored_backlight_registers.vBL_PWM_CNTL = + REG_READ(BL_PWM_CNTL); + stored_backlight_registers.vBL_PWM_CNTL2 = + REG_READ(BL_PWM_CNTL2); + stored_backlight_registers.vBL_PWM_PERIOD_CNTL = + REG_READ(BL_PWM_PERIOD_CNTL); + + REG_GET(LVTMA_PWRSEQ_REF_DIV, BL_PWM_REF_DIV, + &stored_backlight_registers. + vLVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV); + } + + /* Have driver take backlight control + * TakeBacklightControl(true) + */ + s2 = REG_READ(BIOS_SCRATCH_2); + s2 |= ATOM_S2_VRI_BRIGHT_ENABLE; + REG_WRITE(BIOS_SCRATCH_2, s2); + + /* Enable the backlight output */ + REG_UPDATE(BL_PWM_CNTL, BL_PWM_EN, 1); + +} + +void dce110_link_encoder_set_dmcu_abm_level( + struct link_encoder *enc, uint32_t level) +{ + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + struct dc_context *ctx = enc110->base.ctx; + + unsigned int dmcu_max_retry_on_wait_reg_ready = 801; + unsigned int dmcu_wait_reg_ready_interval = 100; + unsigned int regValue; + + /* waitDMCUReadyForCmd */ + do { + dm_delay_in_microseconds(ctx, dmcu_wait_reg_ready_interval); + regValue = REG_READ(MASTER_COMM_CNTL_REG); + dmcu_max_retry_on_wait_reg_ready--; + } while + /* expected value is 0, loop while not 0*/ + ((MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK & regValue) && + dmcu_max_retry_on_wait_reg_ready > 0); + + /* setDMCUParam_ABMLevel */ + REG_UPDATE_2(MASTER_COMM_CMD_REG, + MASTER_COMM_CMD_REG_BYTE0, MCP_ABM_LEVEL_SET, + MASTER_COMM_CMD_REG_BYTE2, level); + + /* notifyDMCUMsg */ + REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); +} + +static void get_dmcu_psr_state(struct link_encoder *enc, uint32_t *psr_state) +{ + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + struct dc_context *ctx = enc110->base.ctx; + + uint32_t count = 0; + uint32_t psrStateOffset = 0xf0; + uint32_t value; + + /* Enable write access to IRAM */ + REG_UPDATE(DMCU_RAM_ACCESS_CTRL, IRAM_HOST_ACCESS_EN, 1); + + do { + dm_delay_in_microseconds(ctx, 2); + REG_GET(DCI_MEM_PWR_STATUS, + DMCU_IRAM_MEM_PWR_STATE, &value); + } while + (value != 0 && count++ < 10); + + /* Write address to IRAM_RD_ADDR in DMCU_IRAM_RD_CTRL */ + REG_WRITE(DMCU_IRAM_RD_CTRL, psrStateOffset); + + /* Read data from IRAM_RD_DATA in DMCU_IRAM_RD_DATA*/ + *psr_state = REG_READ(DMCU_IRAM_RD_DATA); + + /* Disable write access to IRAM after finished using IRAM + * in order to allow dynamic sleep state + */ + REG_UPDATE(DMCU_RAM_ACCESS_CTRL, IRAM_HOST_ACCESS_EN, 0); +} + +void dce110_link_encoder_set_dmcu_psr_enable(struct link_encoder *enc, + bool enable) +{ + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + struct dc_context *ctx = enc110->base.ctx; + + unsigned int dmcu_max_retry_on_wait_reg_ready = 801; + unsigned int dmcu_wait_reg_ready_interval = 100; + + unsigned int regValue; + + unsigned int retryCount; + uint32_t psr_state = 0; + + /* waitDMCUReadyForCmd */ + do { + dm_delay_in_microseconds(ctx, dmcu_wait_reg_ready_interval); + regValue = REG_READ(MASTER_COMM_CNTL_REG); + dmcu_max_retry_on_wait_reg_ready--; + } while + /* expected value is 0, loop while not 0*/ + ((MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK & regValue) && + dmcu_max_retry_on_wait_reg_ready > 0); + + /* setDMCUParam_Cmd */ + if (enable) + REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, PSR_ENABLE); + else + REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, PSR_EXIT); + + /* notifyDMCUMsg */ + REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); + + for (retryCount = 0; retryCount <= 100; retryCount++) { + get_dmcu_psr_state(enc, &psr_state); + if (enable) { + if (psr_state != 0) + break; + } else { + if (psr_state == 0) + break; + } + dm_delay_in_microseconds(ctx, 10); + } +} + +void dce110_link_encoder_setup_dmcu_psr(struct link_encoder *enc, + struct psr_dmcu_context *psr_context) +{ + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + struct dc_context *ctx = enc110->base.ctx; + + unsigned int dmcu_max_retry_on_wait_reg_ready = 801; + unsigned int dmcu_wait_reg_ready_interval = 100; + unsigned int regValue; + + union dce110_dmcu_psr_config_data_reg1 masterCmdData1; + union dce110_dmcu_psr_config_data_reg2 masterCmdData2; + union dce110_dmcu_psr_config_data_reg3 masterCmdData3; + + if (psr_context->psrExitLinkTrainingRequired) + REG_UPDATE(DP_DPHY_FAST_TRAINING, DPHY_RX_FAST_TRAINING_CAPABLE, 1); + else { + REG_UPDATE(DP_DPHY_FAST_TRAINING, DPHY_RX_FAST_TRAINING_CAPABLE, 0); + /*In DCE 11, we are able to pre-program a Force SR register + * to be able to trigger SR symbol after 5 idle patterns + * transmitted. Upon PSR Exit, DMCU can trigger + * DPHY_LOAD_BS_COUNT_START = 1. Upon writing 1 to + * DPHY_LOAD_BS_COUNT_START and the internal counter + * reaches DPHY_LOAD_BS_COUNT, the next BS symbol will be + * replaced by SR symbol once. + */ + + REG_UPDATE(DP_DPHY_BS_SR_SWAP_CNTL, DPHY_LOAD_BS_COUNT, 0x5); + } + + /* Enable static screen interrupts for PSR supported display */ + /* Disable the interrupt coming from other displays. */ + REG_UPDATE_4(DMCU_INTERRUPT_TO_UC_EN_MASK, + STATIC_SCREEN1_INT_TO_UC_EN, 0, + STATIC_SCREEN2_INT_TO_UC_EN, 0, + STATIC_SCREEN3_INT_TO_UC_EN, 0, + STATIC_SCREEN4_INT_TO_UC_EN, 0); + + switch (psr_context->controllerId) { + /* Driver uses case 1 for unconfigured */ + case 1: + psr_crtc_offset = mmCRTC0_CRTC_STATIC_SCREEN_CONTROL - + mmCRTC0_CRTC_STATIC_SCREEN_CONTROL; + + REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK, + STATIC_SCREEN1_INT_TO_UC_EN, 1); + break; + case 2: + psr_crtc_offset = mmCRTC1_CRTC_STATIC_SCREEN_CONTROL - + mmCRTC0_CRTC_STATIC_SCREEN_CONTROL; + + REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK, + STATIC_SCREEN2_INT_TO_UC_EN, 1); + break; + case 3: + psr_crtc_offset = mmCRTC2_CRTC_STATIC_SCREEN_CONTROL - + mmCRTC0_CRTC_STATIC_SCREEN_CONTROL; + + REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK, + STATIC_SCREEN3_INT_TO_UC_EN, 1); + break; + case 4: + psr_crtc_offset = mmCRTC3_CRTC_STATIC_SCREEN_CONTROL - + mmCRTC0_CRTC_STATIC_SCREEN_CONTROL; + + REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK, + STATIC_SCREEN4_INT_TO_UC_EN, 1); + break; + case 5: + psr_crtc_offset = mmCRTC4_CRTC_STATIC_SCREEN_CONTROL - + mmCRTC0_CRTC_STATIC_SCREEN_CONTROL; + /* CZ/NL only has 4 CRTC!! + * really valid. + * There is no interrupt enable mask for these instances. + */ + break; + case 6: + psr_crtc_offset = mmCRTC5_CRTC_STATIC_SCREEN_CONTROL - + mmCRTC0_CRTC_STATIC_SCREEN_CONTROL; + /* CZ/NL only has 4 CRTC!! + * These are here because they are defined in HW regspec, + * but not really valid. There is no interrupt enable mask + * for these instances. + */ + break; + default: + psr_crtc_offset = mmCRTC0_CRTC_STATIC_SCREEN_CONTROL - + mmCRTC0_CRTC_STATIC_SCREEN_CONTROL; + + REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK, + STATIC_SCREEN1_INT_TO_UC_EN, 1); + break; + } + + REG_UPDATE_2(DP_SEC_CNTL1, + DP_SEC_GSP0_LINE_NUM, psr_context->sdpTransmitLineNumDeadline, + DP_SEC_GSP0_PRIORITY, 1); + + if (psr_context->psr_level.bits.SKIP_SMU_NOTIFICATION) { + REG_UPDATE(SMU_INTERRUPT_CONTROL, DC_SMU_INT_ENABLE, 1); + } + + /* waitDMCUReadyForCmd */ + do { + dm_delay_in_microseconds(ctx, dmcu_wait_reg_ready_interval); + regValue = REG_READ(MASTER_COMM_CNTL_REG); + dmcu_max_retry_on_wait_reg_ready--; + } while + /* expected value is 0, loop while not 0*/ + ((MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK & regValue) && + dmcu_max_retry_on_wait_reg_ready > 0); + + /* setDMCUParam_PSRHostConfigData */ + masterCmdData1.u32All = 0; + masterCmdData1.bits.timehyst_frames = psr_context->timehyst_frames; + masterCmdData1.bits.hyst_lines = psr_context->hyst_lines; + masterCmdData1.bits.rfb_update_auto_en = + psr_context->rfb_update_auto_en; + masterCmdData1.bits.dp_port_num = psr_context->transmitterId; + masterCmdData1.bits.dcp_sel = psr_context->controllerId; + masterCmdData1.bits.phy_type = psr_context->phyType; + masterCmdData1.bits.frame_cap_ind = + psr_context->psrFrameCaptureIndicationReq; + masterCmdData1.bits.aux_chan = psr_context->channel; + masterCmdData1.bits.aux_repeat = psr_context->aux_repeats; + dm_write_reg(ctx, REG(MASTER_COMM_DATA_REG1), + masterCmdData1.u32All); + + masterCmdData2.u32All = 0; + masterCmdData2.bits.dig_fe = psr_context->engineId; + masterCmdData2.bits.dig_be = psr_context->transmitterId; + masterCmdData2.bits.skip_wait_for_pll_lock = + psr_context->skipPsrWaitForPllLock; + masterCmdData2.bits.frame_delay = psr_context->frame_delay; + masterCmdData2.bits.smu_phy_id = psr_context->smuPhyId; + masterCmdData2.bits.num_of_controllers = + psr_context->numberOfControllers; + dm_write_reg(ctx, REG(MASTER_COMM_DATA_REG2), + masterCmdData2.u32All); + + masterCmdData3.u32All = 0; + masterCmdData3.bits.psr_level = psr_context->psr_level.u32all; + dm_write_reg(ctx, REG(MASTER_COMM_DATA_REG3), + masterCmdData3.u32All); + + /* setDMCUParam_Cmd */ + REG_UPDATE(MASTER_COMM_CMD_REG, + MASTER_COMM_CMD_REG_BYTE0, PSR_SET); + + /* notifyDMCUMsg */ + REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); +} + +void dce110_link_encoder_connect_dig_be_to_fe( + struct link_encoder *enc, + enum engine_id engine, + bool connect) +{ + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + uint32_t field; + + if (engine != ENGINE_ID_UNKNOWN) { + + REG_GET(DIG_BE_CNTL, DIG_FE_SOURCE_SELECT, &field); + + if (connect) + field |= get_frontend_source(engine); + else + field &= ~get_frontend_source(engine); + + REG_UPDATE(DIG_BE_CNTL, DIG_FE_SOURCE_SELECT, field); + } +} + +void dce110_link_encoder_enable_hpd(struct link_encoder *enc) +{ + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + struct dc_context *ctx = enc110->base.ctx; + uint32_t addr = HPD_REG(DC_HPD_CONTROL); + uint32_t hpd_enable = 0; + uint32_t value = dm_read_reg(ctx, addr); + + get_reg_field_value(hpd_enable, DC_HPD_CONTROL, DC_HPD_EN); + + if (hpd_enable == 0) + set_reg_field_value(value, 1, DC_HPD_CONTROL, DC_HPD_EN); +} + +void dce110_link_encoder_disable_hpd(struct link_encoder *enc) +{ + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + struct dc_context *ctx = enc110->base.ctx; + uint32_t addr = HPD_REG(DC_HPD_CONTROL); + uint32_t value = dm_read_reg(ctx, addr); + + set_reg_field_value(value, 0, DC_HPD_CONTROL, DC_HPD_EN); +} diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h new file mode 100644 index 000000000000..1635b239402f --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h @@ -0,0 +1,363 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_LINK_ENCODER__DCE110_H__ +#define __DC_LINK_ENCODER__DCE110_H__ + +#include "link_encoder.h" + +#define TO_DCE110_LINK_ENC(link_encoder)\ + container_of(link_encoder, struct dce110_link_encoder, base) + +#define AUX_REG_LIST(id)\ + SRI(AUX_CONTROL, DP_AUX, id), \ + SRI(AUX_DPHY_RX_CONTROL0, DP_AUX, id) + +#define HPD_REG_LIST(id)\ + SRI(DC_HPD_CONTROL, HPD, id) + +#define LE_COMMON_REG_LIST_BASE(id) \ + SR(BL_PWM_CNTL), \ + SR(BL_PWM_GRP1_REG_LOCK), \ + SR(BL_PWM_PERIOD_CNTL), \ + SR(LVTMA_PWRSEQ_CNTL), \ + SR(LVTMA_PWRSEQ_STATE), \ + SR(BL_PWM_CNTL2), \ + SR(LVTMA_PWRSEQ_REF_DIV), \ + SR(MASTER_COMM_DATA_REG1), \ + SR(MASTER_COMM_DATA_REG2), \ + SR(MASTER_COMM_DATA_REG3), \ + SR(MASTER_COMM_CMD_REG), \ + SR(MASTER_COMM_CNTL_REG), \ + SR(DMCU_RAM_ACCESS_CTRL), \ + SR(DMCU_IRAM_RD_CTRL), \ + SR(DMCU_IRAM_RD_DATA), \ + SR(DMCU_INTERRUPT_TO_UC_EN_MASK), \ + SR(SMU_INTERRUPT_CONTROL), \ + SRI(DIG_BE_CNTL, DIG, id), \ + SRI(DIG_BE_EN_CNTL, DIG, id), \ + SRI(DP_CONFIG, DP, id), \ + SRI(DP_DPHY_CNTL, DP, id), \ + SRI(DP_DPHY_PRBS_CNTL, DP, id), \ + SRI(DP_DPHY_SCRAM_CNTL, DP, id),\ + SRI(DP_DPHY_SYM0, DP, id), \ + SRI(DP_DPHY_SYM1, DP, id), \ + SRI(DP_DPHY_SYM2, DP, id), \ + SRI(DP_DPHY_TRAINING_PATTERN_SEL, DP, id), \ + SRI(DP_LINK_CNTL, DP, id), \ + SRI(DP_LINK_FRAMING_CNTL, DP, id), \ + SRI(DP_MSE_SAT0, DP, id), \ + SRI(DP_MSE_SAT1, DP, id), \ + SRI(DP_MSE_SAT2, DP, id), \ + SRI(DP_MSE_SAT_UPDATE, DP, id), \ + SRI(DP_SEC_CNTL, DP, id), \ + SRI(DP_VID_STREAM_CNTL, DP, id), \ + SRI(DP_DPHY_FAST_TRAINING, DP, id), \ + SRI(DP_SEC_CNTL1, DP, id) + + #define LE_COMMON_REG_LIST(id)\ + LE_COMMON_REG_LIST_BASE(id), \ + SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ + SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ + SR(BIOS_SCRATCH_2), \ + SR(BL1_PWM_USER_LEVEL), \ + SR(DCI_MEM_PWR_STATUS) + + #define LE_DCE110_REG_LIST(id)\ + LE_COMMON_REG_LIST_BASE(id), \ + SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ + SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ + SR(BIOS_SCRATCH_2), \ + SR(BL1_PWM_USER_LEVEL), \ + SR(DCI_MEM_PWR_STATUS) + + #define LE_DCE80_REG_LIST(id)\ + SR(BIOS_SCRATCH_2), \ + SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ + SR(BL1_PWM_USER_LEVEL), \ + LE_COMMON_REG_LIST_BASE(id) + + +struct dce110_link_enc_aux_registers { + uint32_t AUX_CONTROL; + uint32_t AUX_DPHY_RX_CONTROL0; +}; + +struct dce110_link_enc_hpd_registers { + uint32_t DC_HPD_CONTROL; +}; + +struct dce110_link_enc_registers { + /* BL registers */ + uint32_t BL_PWM_CNTL; + uint32_t BL_PWM_GRP1_REG_LOCK; + uint32_t BL_PWM_PERIOD_CNTL; + uint32_t LVTMA_PWRSEQ_CNTL; + uint32_t LVTMA_PWRSEQ_STATE; + uint32_t BL_PWM_CNTL2; + uint32_t LVTMA_PWRSEQ_REF_DIV; + + /* DMCU registers */ + uint32_t BL1_PWM_USER_LEVEL; + uint32_t ABM0_BL1_PWM_USER_LEVEL; + uint32_t MASTER_COMM_DATA_REG1; + uint32_t MASTER_COMM_DATA_REG2; + uint32_t MASTER_COMM_DATA_REG3; + uint32_t MASTER_COMM_CMD_REG; + uint32_t MASTER_COMM_CNTL_REG; + uint32_t BIOS_SCRATCH_2; + uint32_t DMCU_RAM_ACCESS_CTRL; + uint32_t DCI_MEM_PWR_STATUS; + uint32_t DMU_MEM_PWR_CNTL; + uint32_t DMCU_IRAM_RD_CTRL; + uint32_t DMCU_IRAM_RD_DATA; + uint32_t DMCU_INTERRUPT_TO_UC_EN_MASK; + uint32_t SMU_INTERRUPT_CONTROL; + + + /* Common DP registers */ + uint32_t DIG_BE_CNTL; + uint32_t DIG_BE_EN_CNTL; + uint32_t DP_CONFIG; + uint32_t DP_DPHY_CNTL; + uint32_t DP_DPHY_INTERNAL_CTRL; + uint32_t DP_DPHY_PRBS_CNTL; + uint32_t DP_DPHY_SCRAM_CNTL; + uint32_t DP_DPHY_SYM0; + uint32_t DP_DPHY_SYM1; + uint32_t DP_DPHY_SYM2; + uint32_t DP_DPHY_TRAINING_PATTERN_SEL; + uint32_t DP_LINK_CNTL; + uint32_t DP_LINK_FRAMING_CNTL; + uint32_t DP_MSE_SAT0; + uint32_t DP_MSE_SAT1; + uint32_t DP_MSE_SAT2; + uint32_t DP_MSE_SAT_UPDATE; + uint32_t DP_SEC_CNTL; + uint32_t DP_VID_STREAM_CNTL; + uint32_t DP_DPHY_FAST_TRAINING; + uint32_t DP_DPHY_BS_SR_SWAP_CNTL; + uint32_t DP_SEC_CNTL1; +}; + +struct dce110_link_encoder { + struct link_encoder base; + const struct dce110_link_enc_registers *link_regs; + const struct dce110_link_enc_aux_registers *aux_regs; + const struct dce110_link_enc_hpd_registers *hpd_regs; +}; + +/******************************************************************* +* MASTER_COMM_DATA_REG1 Bit position Data +* 7:0 hyst_frames[7:0] +* 14:8 hyst_lines[6:0] +* 15 RFB_UPDATE_AUTO_EN +* 18:16 phy_num[2:0] +* 21:19 dcp_sel[2:0] +* 22 phy_type +* 23 frame_cap_ind +* 26:24 aux_chan[2:0] +* 30:27 aux_repeat[3:0] +* 31:31 reserved[31:31] +*******************************************************************/ +union dce110_dmcu_psr_config_data_reg1 { + struct { + unsigned int timehyst_frames:8; /*[7:0]*/ + unsigned int hyst_lines:7; /*[14:8]*/ + unsigned int rfb_update_auto_en:1; /*[15:15]*/ + unsigned int dp_port_num:3; /*[18:16]*/ + unsigned int dcp_sel:3; /*[21:19]*/ + unsigned int phy_type:1; /*[22:22]*/ + unsigned int frame_cap_ind:1; /*[23:23]*/ + unsigned int aux_chan:3; /*[26:24]*/ + unsigned int aux_repeat:4; /*[30:27]*/ + unsigned int reserved:1; /*[31:31]*/ + } bits; + unsigned int u32All; +}; + +/******************************************************************* +* MASTER_COMM_DATA_REG2 +*******************************************************************/ +union dce110_dmcu_psr_config_data_reg2 { + struct { + unsigned int dig_fe:3; /*[2:0]*/ + unsigned int dig_be:3; /*[5:3]*/ + unsigned int skip_wait_for_pll_lock:1; /*[6:6]*/ + unsigned int reserved:9; /*[15:7]*/ + unsigned int frame_delay:8; /*[23:16]*/ + unsigned int smu_phy_id:4; /*[27:24]*/ + unsigned int num_of_controllers:4; /*[31:28]*/ + } bits; + unsigned int u32All; +}; + +/******************************************************************* +* MASTER_COMM_DATA_REG3 +*******************************************************************/ +union dce110_dmcu_psr_config_data_reg3 { + struct { + unsigned int psr_level:16; /*[15:0]*/ + unsigned int link_rate:4; /*[19:16]*/ + unsigned int reserved:12; /*[31:20]*/ + } bits; + unsigned int u32All; +}; + +struct dce110_abm_backlight_registers { + unsigned int vBL_PWM_CNTL; + unsigned int vBL_PWM_CNTL2; + unsigned int vBL_PWM_PERIOD_CNTL; + unsigned int vLVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV; +}; + +bool dce110_link_encoder_construct( + struct dce110_link_encoder *enc110, + const struct encoder_init_data *init_data, + const struct dce110_link_enc_registers *link_regs, + const struct dce110_link_enc_aux_registers *aux_regs, + const struct dce110_link_enc_hpd_registers *hpd_regs); + +bool dce110_link_encoder_validate_dvi_output( + const struct dce110_link_encoder *enc110, + enum signal_type connector_signal, + enum signal_type signal, + const struct dc_crtc_timing *crtc_timing); + +bool dce110_link_encoder_validate_rgb_output( + const struct dce110_link_encoder *enc110, + const struct dc_crtc_timing *crtc_timing); + +bool dce110_link_encoder_validate_dp_output( + const struct dce110_link_encoder *enc110, + const struct dc_crtc_timing *crtc_timing); + +bool dce110_link_encoder_validate_wireless_output( + const struct dce110_link_encoder *enc110, + const struct dc_crtc_timing *crtc_timing); + +bool dce110_link_encoder_validate_output_with_stream( + struct link_encoder *enc, + struct pipe_ctx *pipe_ctx); + +/****************** HW programming ************************/ + +/* initialize HW */ /* why do we initialze aux in here? */ +void dce110_link_encoder_hw_init(struct link_encoder *enc); + +void dce110_link_encoder_destroy(struct link_encoder **enc); + +/* program DIG_MODE in DIG_BE */ +/* TODO can this be combined with enable_output? */ +void dce110_link_encoder_setup( + struct link_encoder *enc, + enum signal_type signal); + +/* enables TMDS PHY output */ +/* TODO: still need depth or just pass in adjusted pixel clock? */ +void dce110_link_encoder_enable_tmds_output( + struct link_encoder *enc, + enum clock_source_id clock_source, + enum dc_color_depth color_depth, + bool hdmi, + bool dual_link, + uint32_t pixel_clock); + +/* enables DP PHY output */ +void dce110_link_encoder_enable_dp_output( + struct link_encoder *enc, + const struct dc_link_settings *link_settings, + enum clock_source_id clock_source); + +/* enables DP PHY output in MST mode */ +void dce110_link_encoder_enable_dp_mst_output( + struct link_encoder *enc, + const struct dc_link_settings *link_settings, + enum clock_source_id clock_source); + +/* disable PHY output */ +void dce110_link_encoder_disable_output( + struct link_encoder *link_enc, + enum signal_type signal); + +/* set DP lane settings */ +void dce110_link_encoder_dp_set_lane_settings( + struct link_encoder *enc, + const struct link_training_settings *link_settings); + +void dce110_link_encoder_dp_set_phy_pattern( + struct link_encoder *enc, + const struct encoder_set_dp_phy_pattern_param *param); + +/* programs DP MST VC payload allocation */ +void dce110_link_encoder_update_mst_stream_allocation_table( + struct link_encoder *enc, + const struct link_mst_stream_allocation_table *table); + +void dce110_link_encoder_set_lcd_backlight_level( + struct link_encoder *enc, + uint32_t level); + +void dce110_link_encoder_set_dmcu_backlight_level( + struct link_encoder *enc, + uint32_t level, + uint32_t frame_ramp, + uint32_t controller_id); + +void dce110_link_encoder_init_dmcu_backlight_settings( + struct link_encoder *enc); + +void dce110_link_encoder_set_dmcu_abm_level( + struct link_encoder *enc, + uint32_t level); + +void dce110_link_encoder_set_dmcu_psr_enable( + struct link_encoder *enc, bool enable); + +void dce110_link_encoder_setup_dmcu_psr(struct link_encoder *enc, + struct psr_dmcu_context *psr_context); + +void dce110_link_encoder_edp_backlight_control( + struct link_encoder *enc, + bool enable); + +void dce110_link_encoder_edp_power_control( + struct link_encoder *enc, + bool power_up); + +void dce110_link_encoder_connect_dig_be_to_fe( + struct link_encoder *enc, + enum engine_id engine, + bool connect); + +void dce110_link_encoder_set_dp_phy_pattern_training_pattern( + struct link_encoder *enc, + uint32_t index); + +void dce110_link_encoder_enable_hpd(struct link_encoder *enc); + +void dce110_link_encoder_disable_hpd(struct link_encoder *enc); + +#endif /* __DC_LINK_ENCODER__DCE110_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c new file mode 100644 index 000000000000..654731cccdcd --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c @@ -0,0 +1,384 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "mem_input.h" +#include "reg_helper.h" + +#define CTX \ + mi->ctx +#define REG(reg)\ + mi->regs->reg + +#undef FN +#define FN(reg_name, field_name) \ + mi->shifts->field_name, mi->masks->field_name + + +static void program_urgency_watermark(struct mem_input *mi, + uint32_t wm_select, + uint32_t urgency_low_wm, + uint32_t urgency_high_wm) +{ + REG_UPDATE(DPG_WATERMARK_MASK_CONTROL, + URGENCY_WATERMARK_MASK, wm_select); + + REG_SET_2(DPG_PIPE_URGENCY_CONTROL, 0, + URGENCY_LOW_WATERMARK, urgency_low_wm, + URGENCY_HIGH_WATERMARK, urgency_high_wm); +} + +static void program_nbp_watermark(struct mem_input *mi, + uint32_t wm_select, + uint32_t nbp_wm) +{ + if (REG(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL)) { + REG_UPDATE(DPG_WATERMARK_MASK_CONTROL, + NB_PSTATE_CHANGE_WATERMARK_MASK, wm_select); + + REG_UPDATE_3(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_ENABLE, 1, + NB_PSTATE_CHANGE_URGENT_DURING_REQUEST, 1, + NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST, 1); + + REG_UPDATE(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_WATERMARK, nbp_wm); + } +} + +static void program_stutter_watermark(struct mem_input *mi, + uint32_t wm_select, + uint32_t stutter_mark) +{ + REG_UPDATE(DPG_WATERMARK_MASK_CONTROL, + STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK, wm_select); + + REG_UPDATE(DPG_PIPE_STUTTER_CONTROL, + STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark); +} + +void dce_mem_input_program_display_marks(struct mem_input *mi, + struct bw_watermarks nbp, + struct bw_watermarks stutter, + struct bw_watermarks urgent, + uint32_t total_dest_line_time_ns) +{ + uint32_t stutter_en = mi->ctx->dc->debug.disable_stutter ? 0 : 1; + + program_urgency_watermark(mi, 0, /* set a */ + urgent.a_mark, total_dest_line_time_ns); + program_urgency_watermark(mi, 1, /* set b */ + urgent.b_mark, total_dest_line_time_ns); + program_urgency_watermark(mi, 2, /* set c */ + urgent.c_mark, total_dest_line_time_ns); + program_urgency_watermark(mi, 3, /* set d */ + urgent.d_mark, total_dest_line_time_ns); + + REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL, + STUTTER_ENABLE, stutter_en, + STUTTER_IGNORE_FBC, 1); + program_nbp_watermark(mi, 0, nbp.a_mark); /* set a */ + program_nbp_watermark(mi, 1, nbp.b_mark); /* set b */ + program_nbp_watermark(mi, 2, nbp.c_mark); /* set c */ + program_nbp_watermark(mi, 3, nbp.d_mark); /* set d */ + + program_stutter_watermark(mi, 0, stutter.a_mark); /* set a */ + program_stutter_watermark(mi, 1, stutter.b_mark); /* set b */ + program_stutter_watermark(mi, 2, stutter.c_mark); /* set c */ + program_stutter_watermark(mi, 3, stutter.d_mark); /* set d */ +} + +static void program_tiling(struct mem_input *mi, + const union dc_tiling_info *info) +{ + if (mi->masks->GRPH_ARRAY_MODE) { /* GFX8 */ + REG_UPDATE_9(GRPH_CONTROL, + GRPH_NUM_BANKS, info->gfx8.num_banks, + GRPH_BANK_WIDTH, info->gfx8.bank_width, + GRPH_BANK_HEIGHT, info->gfx8.bank_height, + GRPH_MACRO_TILE_ASPECT, info->gfx8.tile_aspect, + GRPH_TILE_SPLIT, info->gfx8.tile_split, + GRPH_MICRO_TILE_MODE, info->gfx8.tile_mode, + GRPH_PIPE_CONFIG, info->gfx8.pipe_config, + GRPH_ARRAY_MODE, info->gfx8.array_mode, + GRPH_COLOR_EXPANSION_MODE, 1); + /* 01 - DCP_GRPH_COLOR_EXPANSION_MODE_ZEXP: zero expansion for YCbCr */ + /* + GRPH_Z, 0); + */ + } +} + + +static void program_size_and_rotation( + struct mem_input *mi, + enum dc_rotation_angle rotation, + const union plane_size *plane_size) +{ + const struct rect *in_rect = &plane_size->grph.surface_size; + struct rect hw_rect = plane_size->grph.surface_size; + const uint32_t rotation_angles[ROTATION_ANGLE_COUNT] = { + [ROTATION_ANGLE_0] = 0, + [ROTATION_ANGLE_90] = 1, + [ROTATION_ANGLE_180] = 2, + [ROTATION_ANGLE_270] = 3, + }; + + if (rotation == ROTATION_ANGLE_90 || rotation == ROTATION_ANGLE_270) { + hw_rect.x = in_rect->y; + hw_rect.y = in_rect->x; + + hw_rect.height = in_rect->width; + hw_rect.width = in_rect->height; + } + + REG_SET(GRPH_X_START, 0, + GRPH_X_START, hw_rect.x); + + REG_SET(GRPH_Y_START, 0, + GRPH_Y_START, hw_rect.y); + + REG_SET(GRPH_X_END, 0, + GRPH_X_END, hw_rect.width); + + REG_SET(GRPH_Y_END, 0, + GRPH_Y_END, hw_rect.height); + + REG_SET(GRPH_PITCH, 0, + GRPH_PITCH, plane_size->grph.surface_pitch); + + REG_SET(HW_ROTATION, 0, + GRPH_ROTATION_ANGLE, rotation_angles[rotation]); +} + +static void program_grph_pixel_format( + struct mem_input *mi, + enum surface_pixel_format format) +{ + uint32_t red_xbar = 0, blue_xbar = 0; /* no swap */ + uint32_t grph_depth, grph_format; + uint32_t sign = 0, floating = 0; + + if (format == SURFACE_PIXEL_FORMAT_GRPH_BGRA8888 || + /*todo: doesn't look like we handle BGRA here, + * should problem swap endian*/ + format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010 || + format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS || + format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F) { + /* ABGR formats */ + red_xbar = 2; + blue_xbar = 2; + } + + REG_SET_2(GRPH_SWAP_CNTL, 0, + GRPH_RED_CROSSBAR, red_xbar, + GRPH_BLUE_CROSSBAR, blue_xbar); + + switch (format) { + case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS: + grph_depth = 0; + grph_format = 0; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: + grph_depth = 1; + grph_format = 0; + break; + case SURFACE_PIXEL_FORMAT_GRPH_RGB565: + grph_depth = 1; + grph_format = 1; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: + case SURFACE_PIXEL_FORMAT_GRPH_BGRA8888: + grph_depth = 2; + grph_format = 0; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: + grph_depth = 2; + grph_format = 1; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: + sign = 1; + floating = 1; + /* no break */ + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: /* shouldn't this get float too? */ + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: + grph_depth = 3; + grph_format = 0; + break; + default: + DC_ERR("unsupported grph pixel format"); + break; + } + + REG_UPDATE_2(GRPH_CONTROL, + GRPH_DEPTH, grph_depth, + GRPH_FORMAT, grph_format); + + REG_UPDATE_4(PRESCALE_GRPH_CONTROL, + GRPH_PRESCALE_SELECT, floating, + GRPH_PRESCALE_R_SIGN, sign, + GRPH_PRESCALE_G_SIGN, sign, + GRPH_PRESCALE_B_SIGN, sign); +} + +bool dce_mem_input_program_surface_config(struct mem_input *mi, + enum surface_pixel_format format, + union dc_tiling_info *tiling_info, + union plane_size *plane_size, + enum dc_rotation_angle rotation, + struct dc_plane_dcc_param *dcc, + bool horizontal_mirror) +{ + REG_UPDATE(GRPH_ENABLE, GRPH_ENABLE, 1); + + program_tiling(mi, tiling_info); + program_size_and_rotation(mi, rotation, plane_size); + + if (format >= SURFACE_PIXEL_FORMAT_GRPH_BEGIN && + format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) + program_grph_pixel_format(mi, format); + + return true; +} + +static uint32_t get_dmif_switch_time_us( + uint32_t h_total, + uint32_t v_total, + uint32_t pix_clk_khz) +{ + uint32_t frame_time; + uint32_t pixels_per_second; + uint32_t pixels_per_frame; + uint32_t refresh_rate; + const uint32_t us_in_sec = 1000000; + const uint32_t min_single_frame_time_us = 30000; + /*return double of frame time*/ + const uint32_t single_frame_time_multiplier = 2; + + if (!h_total || v_total || !pix_clk_khz) + return single_frame_time_multiplier * min_single_frame_time_us; + + /*TODO: should we use pixel format normalized pixel clock here?*/ + pixels_per_second = pix_clk_khz * 1000; + pixels_per_frame = h_total * v_total; + + if (!pixels_per_second || !pixels_per_frame) { + /* avoid division by zero */ + ASSERT(pixels_per_frame); + ASSERT(pixels_per_second); + return single_frame_time_multiplier * min_single_frame_time_us; + } + + refresh_rate = pixels_per_second / pixels_per_frame; + + if (!refresh_rate) { + /* avoid division by zero*/ + ASSERT(refresh_rate); + return single_frame_time_multiplier * min_single_frame_time_us; + } + + frame_time = us_in_sec / refresh_rate; + + if (frame_time < min_single_frame_time_us) + frame_time = min_single_frame_time_us; + + frame_time *= single_frame_time_multiplier; + + return frame_time; +} + +void dce_mem_input_allocate_dmif(struct mem_input *mi, + uint32_t h_total, + uint32_t v_total, + uint32_t pix_clk_khz, + uint32_t total_stream_num) +{ + const uint32_t retry_delay = 10; + uint32_t retry_count = get_dmif_switch_time_us( + h_total, + v_total, + pix_clk_khz) / retry_delay; + + uint32_t pix_dur; + uint32_t buffers_allocated; + uint32_t dmif_buffer_control; + + dmif_buffer_control = REG_GET(DMIF_BUFFER_CONTROL, + DMIF_BUFFERS_ALLOCATED, &buffers_allocated); + + if (buffers_allocated == 2) + return; + + REG_SET(DMIF_BUFFER_CONTROL, dmif_buffer_control, + DMIF_BUFFERS_ALLOCATED, 2); + + REG_WAIT(DMIF_BUFFER_CONTROL, + DMIF_BUFFERS_ALLOCATION_COMPLETED, 1, + retry_delay, retry_count); + + if (pix_clk_khz != 0) { + pix_dur = 1000000000ULL / pix_clk_khz; + + REG_UPDATE(DPG_PIPE_ARBITRATION_CONTROL1, + PIXEL_DURATION, pix_dur); + } + + if (mi->wa.single_head_rdreq_dmif_limit) { + uint32_t eanble = (total_stream_num > 1) ? 0 : + mi->wa.single_head_rdreq_dmif_limit; + + REG_UPDATE(MC_HUB_RDREQ_DMIF_LIMIT, + ENABLE, eanble); + } +} + +void dce_mem_input_free_dmif(struct mem_input *mi, + uint32_t total_stream_num) +{ + uint32_t buffers_allocated; + uint32_t dmif_buffer_control; + + dmif_buffer_control = REG_GET(DMIF_BUFFER_CONTROL, + DMIF_BUFFERS_ALLOCATED, &buffers_allocated); + + if (buffers_allocated == 0) + return; + + REG_SET(DMIF_BUFFER_CONTROL, dmif_buffer_control, + DMIF_BUFFERS_ALLOCATED, 0); + + REG_WAIT(DMIF_BUFFER_CONTROL, + DMIF_BUFFERS_ALLOCATION_COMPLETED, 1, + 10, 0xBB8); + + if (mi->wa.single_head_rdreq_dmif_limit) { + uint32_t eanble = (total_stream_num > 1) ? 0 : + mi->wa.single_head_rdreq_dmif_limit; + + REG_UPDATE(MC_HUB_RDREQ_DMIF_LIMIT, + ENABLE, eanble); + } +} diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h new file mode 100644 index 000000000000..d5930a925fcb --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h @@ -0,0 +1,217 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef __DCE_MEM_INPUT_H__ +#define __DCE_MEM_INPUT_H__ + +#define MI_DCE_BASE_REG_LIST(id)\ + SRI(GRPH_ENABLE, DCP, id),\ + SRI(GRPH_CONTROL, DCP, id),\ + SRI(GRPH_X_START, DCP, id),\ + SRI(GRPH_Y_START, DCP, id),\ + SRI(GRPH_X_END, DCP, id),\ + SRI(GRPH_Y_END, DCP, id),\ + SRI(GRPH_PITCH, DCP, id),\ + SRI(HW_ROTATION, DCP, id),\ + SRI(GRPH_SWAP_CNTL, DCP, id),\ + SRI(PRESCALE_GRPH_CONTROL, DCP, id),\ + SRI(DPG_PIPE_ARBITRATION_CONTROL1, DMIF_PG, id),\ + SRI(DPG_WATERMARK_MASK_CONTROL, DMIF_PG, id),\ + SRI(DPG_PIPE_URGENCY_CONTROL, DMIF_PG, id),\ + SRI(DPG_PIPE_STUTTER_CONTROL, DMIF_PG, id),\ + SRI(DMIF_BUFFER_CONTROL, PIPE, id) + +#define MI_REG_LIST(id)\ + MI_DCE_BASE_REG_LIST(id),\ + SRI(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, DMIF_PG, id) + +struct dce_mem_input_registers { + /* DCP */ + uint32_t GRPH_ENABLE; + uint32_t GRPH_CONTROL; + uint32_t GRPH_X_START; + uint32_t GRPH_Y_START; + uint32_t GRPH_X_END; + uint32_t GRPH_Y_END; + uint32_t GRPH_PITCH; + uint32_t HW_ROTATION; + uint32_t GRPH_SWAP_CNTL; + uint32_t PRESCALE_GRPH_CONTROL; + /* DMIF_PG */ + uint32_t DPG_PIPE_ARBITRATION_CONTROL1; + uint32_t DPG_WATERMARK_MASK_CONTROL; + uint32_t DPG_PIPE_URGENCY_CONTROL; + uint32_t DPG_PIPE_NB_PSTATE_CHANGE_CONTROL; + uint32_t DPG_PIPE_LOW_POWER_CONTROL; + uint32_t DPG_PIPE_STUTTER_CONTROL; + uint32_t DPG_PIPE_STUTTER_CONTROL2; + /* DCI */ + uint32_t DMIF_BUFFER_CONTROL; + /* MC_HUB */ + uint32_t MC_HUB_RDREQ_DMIF_LIMIT; +}; + +/* Set_Filed_for_Block */ +#define SFB(blk_name, reg_name, field_name, post_fix)\ + .field_name = blk_name ## reg_name ## __ ## field_name ## post_fix + +#define MI_GFX8_TILE_MASK_SH_LIST(mask_sh, blk)\ + SFB(blk, GRPH_CONTROL, GRPH_BANK_HEIGHT, mask_sh),\ + SFB(blk, GRPH_CONTROL, GRPH_MACRO_TILE_ASPECT, mask_sh),\ + SFB(blk, GRPH_CONTROL, GRPH_TILE_SPLIT, mask_sh),\ + SFB(blk, GRPH_CONTROL, GRPH_MICRO_TILE_MODE, mask_sh),\ + SFB(blk, GRPH_CONTROL, GRPH_PIPE_CONFIG, mask_sh),\ + SFB(blk, GRPH_CONTROL, GRPH_ARRAY_MODE, mask_sh),\ + SFB(blk, GRPH_CONTROL, GRPH_COLOR_EXPANSION_MODE, mask_sh) + +#define MI_DCP_MASK_SH_LIST(mask_sh, blk)\ + SFB(blk, GRPH_ENABLE, GRPH_ENABLE, mask_sh),\ + SFB(blk, GRPH_CONTROL, GRPH_DEPTH, mask_sh),\ + SFB(blk, GRPH_CONTROL, GRPH_FORMAT, mask_sh),\ + SFB(blk, GRPH_CONTROL, GRPH_NUM_BANKS, mask_sh),\ + SFB(blk, GRPH_X_START, GRPH_X_START, mask_sh),\ + SFB(blk, GRPH_Y_START, GRPH_Y_START, mask_sh),\ + SFB(blk, GRPH_X_END, GRPH_X_END, mask_sh),\ + SFB(blk, GRPH_Y_END, GRPH_Y_END, mask_sh),\ + SFB(blk, GRPH_PITCH, GRPH_PITCH, mask_sh),\ + SFB(blk, HW_ROTATION, GRPH_ROTATION_ANGLE, mask_sh),\ + SFB(blk, GRPH_SWAP_CNTL, GRPH_RED_CROSSBAR, mask_sh),\ + SFB(blk, GRPH_SWAP_CNTL, GRPH_BLUE_CROSSBAR, mask_sh),\ + SFB(blk, PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_SELECT, mask_sh),\ + SFB(blk, PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_R_SIGN, mask_sh),\ + SFB(blk, PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_G_SIGN, mask_sh),\ + SFB(blk, PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_B_SIGN, mask_sh) + +#define MI_DMIF_PG_MASK_SH_LIST(mask_sh, blk)\ + SFB(blk, DPG_PIPE_ARBITRATION_CONTROL1, PIXEL_DURATION, mask_sh),\ + SFB(blk, DPG_WATERMARK_MASK_CONTROL, URGENCY_WATERMARK_MASK, mask_sh),\ + SFB(blk, DPG_WATERMARK_MASK_CONTROL, STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK, mask_sh),\ + SFB(blk, DPG_PIPE_URGENCY_CONTROL, URGENCY_LOW_WATERMARK, mask_sh),\ + SFB(blk, DPG_PIPE_URGENCY_CONTROL, URGENCY_HIGH_WATERMARK, mask_sh),\ + SFB(blk, DPG_PIPE_STUTTER_CONTROL, STUTTER_ENABLE, mask_sh),\ + SFB(blk, DPG_PIPE_STUTTER_CONTROL, STUTTER_IGNORE_FBC, mask_sh),\ + SF(PIPE0_DMIF_BUFFER_CONTROL, DMIF_BUFFERS_ALLOCATED, mask_sh),\ + SF(PIPE0_DMIF_BUFFER_CONTROL, DMIF_BUFFERS_ALLOCATION_COMPLETED, mask_sh) + +#define MI_DMIF_PG_MASK_SH_DCE(mask_sh, blk)\ + SFB(blk, DPG_PIPE_STUTTER_CONTROL, STUTTER_EXIT_SELF_REFRESH_WATERMARK, mask_sh),\ + SFB(blk, DPG_WATERMARK_MASK_CONTROL, NB_PSTATE_CHANGE_WATERMARK_MASK, mask_sh),\ + SFB(blk, DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, NB_PSTATE_CHANGE_ENABLE, mask_sh),\ + SFB(blk, DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, NB_PSTATE_CHANGE_URGENT_DURING_REQUEST, mask_sh),\ + SFB(blk, DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST, mask_sh),\ + SFB(blk, DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, NB_PSTATE_CHANGE_WATERMARK, mask_sh) + +#define MI_DCE_MASK_SH_LIST(mask_sh)\ + MI_DCP_MASK_SH_LIST(mask_sh,),\ + MI_DMIF_PG_MASK_SH_LIST(mask_sh,),\ + MI_DMIF_PG_MASK_SH_DCE(mask_sh,),\ + MI_GFX8_TILE_MASK_SH_LIST(mask_sh,) + +#define MI_REG_FIELD_LIST(type) \ + type GRPH_ENABLE; \ + type GRPH_X_START; \ + type GRPH_Y_START; \ + type GRPH_X_END; \ + type GRPH_Y_END; \ + type GRPH_PITCH; \ + type GRPH_ROTATION_ANGLE; \ + type GRPH_RED_CROSSBAR; \ + type GRPH_BLUE_CROSSBAR; \ + type GRPH_PRESCALE_SELECT; \ + type GRPH_PRESCALE_R_SIGN; \ + type GRPH_PRESCALE_G_SIGN; \ + type GRPH_PRESCALE_B_SIGN; \ + type GRPH_DEPTH; \ + type GRPH_FORMAT; \ + type GRPH_NUM_BANKS; \ + type GRPH_BANK_WIDTH;\ + type GRPH_BANK_HEIGHT;\ + type GRPH_MACRO_TILE_ASPECT;\ + type GRPH_TILE_SPLIT;\ + type GRPH_MICRO_TILE_MODE;\ + type GRPH_PIPE_CONFIG;\ + type GRPH_ARRAY_MODE;\ + type GRPH_COLOR_EXPANSION_MODE;\ + type GRPH_SW_MODE; \ + type GRPH_NUM_SHADER_ENGINES; \ + type GRPH_NUM_PIPES; \ + type PIXEL_DURATION; \ + type URGENCY_WATERMARK_MASK; \ + type PSTATE_CHANGE_WATERMARK_MASK; \ + type NB_PSTATE_CHANGE_WATERMARK_MASK; \ + type STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK; \ + type URGENCY_LOW_WATERMARK; \ + type URGENCY_HIGH_WATERMARK; \ + type NB_PSTATE_CHANGE_ENABLE; \ + type NB_PSTATE_CHANGE_URGENT_DURING_REQUEST; \ + type NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST; \ + type NB_PSTATE_CHANGE_WATERMARK; \ + type PSTATE_CHANGE_ENABLE; \ + type PSTATE_CHANGE_URGENT_DURING_REQUEST; \ + type PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST; \ + type PSTATE_CHANGE_WATERMARK; \ + type STUTTER_ENABLE; \ + type STUTTER_IGNORE_FBC; \ + type STUTTER_EXIT_SELF_REFRESH_WATERMARK; \ + type DMIF_BUFFERS_ALLOCATED; \ + type DMIF_BUFFERS_ALLOCATION_COMPLETED; \ + type ENABLE; /* MC_HUB_RDREQ_DMIF_LIMIT */\ + +struct dce_mem_input_shift { + MI_REG_FIELD_LIST(uint8_t) +}; + +struct dce_mem_input_mask { + MI_REG_FIELD_LIST(uint32_t) +}; + +struct dce_mem_input_wa { + uint8_t single_head_rdreq_dmif_limit; +}; + +struct mem_input; +bool dce_mem_input_program_surface_config(struct mem_input *mi, + enum surface_pixel_format format, + union dc_tiling_info *tiling_info, + union plane_size *plane_size, + enum dc_rotation_angle rotation, + struct dc_plane_dcc_param *dcc, + bool horizontal_mirror); + +void dce_mem_input_allocate_dmif(struct mem_input *mi, + uint32_t h_total, + uint32_t v_total, + uint32_t pix_clk_khz, + uint32_t total_stream_num); + +void dce_mem_input_free_dmif(struct mem_input *mi, + uint32_t total_stream_num); + +void dce_mem_input_program_display_marks(struct mem_input *mi, + struct bw_watermarks nbp, + struct bw_watermarks stutter, + struct bw_watermarks urgent, + uint32_t total_dest_line_time_ns); + +#endif /*__DCE_MEM_INPUT_H__*/ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_scl_filters.c b/drivers/gpu/drm/amd/display/dc/dce/dce_scl_filters.c new file mode 100644 index 000000000000..3aab86781be2 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_scl_filters.c @@ -0,0 +1,501 @@ +/* + * Copyright 2012-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "transform.h" + +const uint16_t filter_2tap_16p[18] = { + 4096, 0, + 3840, 256, + 3584, 512, + 3328, 768, + 3072, 1024, + 2816, 1280, + 2560, 1536, + 2304, 1792, + 2048, 2048 +}; + +const uint16_t filter_3tap_16p_upscale[27] = { + 2048, 2048, 0, + 1708, 2424, 16348, + 1372, 2796, 16308, + 1056, 3148, 16272, + 768, 3464, 16244, + 512, 3728, 16236, + 296, 3928, 16252, + 124, 4052, 16296, + 0, 4096, 0 +}; + +const uint16_t filter_3tap_16p_117[27] = { + 2048, 2048, 0, + 1824, 2276, 16376, + 1600, 2496, 16380, + 1376, 2700, 16, + 1156, 2880, 52, + 948, 3032, 108, + 756, 3144, 192, + 580, 3212, 296, + 428, 3236, 428 +}; + +const uint16_t filter_3tap_16p_150[27] = { + 2048, 2048, 0, + 1872, 2184, 36, + 1692, 2308, 88, + 1516, 2420, 156, + 1340, 2516, 236, + 1168, 2592, 328, + 1004, 2648, 440, + 844, 2684, 560, + 696, 2696, 696 +}; + +const uint16_t filter_3tap_16p_183[27] = { + 2048, 2048, 0, + 1892, 2104, 92, + 1744, 2152, 196, + 1592, 2196, 300, + 1448, 2232, 412, + 1304, 2256, 528, + 1168, 2276, 648, + 1032, 2288, 772, + 900, 2292, 900 +}; + +const uint16_t filter_4tap_16p_upscale[36] = { + 0, 4096, 0, 0, + 16240, 4056, 180, 16380, + 16136, 3952, 404, 16364, + 16072, 3780, 664, 16344, + 16040, 3556, 952, 16312, + 16036, 3284, 1268, 16272, + 16052, 2980, 1604, 16224, + 16084, 2648, 1952, 16176, + 16128, 2304, 2304, 16128 +}; + +const uint16_t filter_4tap_16p_117[36] = { + 428, 3236, 428, 0, + 276, 3232, 604, 16364, + 148, 3184, 800, 16340, + 44, 3104, 1016, 16312, + 16344, 2984, 1244, 16284, + 16284, 2832, 1488, 16256, + 16244, 2648, 1732, 16236, + 16220, 2440, 1976, 16220, + 16212, 2216, 2216, 16212 +}; + +const uint16_t filter_4tap_16p_150[36] = { + 696, 2700, 696, 0, + 560, 2700, 848, 16364, + 436, 2676, 1008, 16348, + 328, 2628, 1180, 16336, + 232, 2556, 1356, 16328, + 152, 2460, 1536, 16328, + 84, 2344, 1716, 16332, + 28, 2208, 1888, 16348, + 16376, 2052, 2052, 16376 +}; + +const uint16_t filter_4tap_16p_183[36] = { + 940, 2208, 940, 0, + 832, 2200, 1052, 4, + 728, 2180, 1164, 16, + 628, 2148, 1280, 36, + 536, 2100, 1392, 60, + 448, 2044, 1504, 92, + 368, 1976, 1612, 132, + 296, 1900, 1716, 176, + 232, 1812, 1812, 232 +}; + +const uint16_t filter_2tap_64p[66] = { + 4096, 0, + 4032, 64, + 3968, 128, + 3904, 192, + 3840, 256, + 3776, 320, + 3712, 384, + 3648, 448, + 3584, 512, + 3520, 576, + 3456, 640, + 3392, 704, + 3328, 768, + 3264, 832, + 3200, 896, + 3136, 960, + 3072, 1024, + 3008, 1088, + 2944, 1152, + 2880, 1216, + 2816, 1280, + 2752, 1344, + 2688, 1408, + 2624, 1472, + 2560, 1536, + 2496, 1600, + 2432, 1664, + 2368, 1728, + 2304, 1792, + 2240, 1856, + 2176, 1920, + 2112, 1984, + 2048, 2048 }; + +const uint16_t filter_3tap_64p_upscale[99] = { + 2048, 2048, 0, + 1960, 2140, 16376, + 1876, 2236, 16364, + 1792, 2328, 16356, + 1708, 2424, 16348, + 1620, 2516, 16336, + 1540, 2612, 16328, + 1456, 2704, 16316, + 1372, 2796, 16308, + 1292, 2884, 16296, + 1212, 2976, 16288, + 1136, 3060, 16280, + 1056, 3148, 16272, + 984, 3228, 16264, + 908, 3312, 16256, + 836, 3388, 16248, + 768, 3464, 16244, + 700, 3536, 16240, + 636, 3604, 16236, + 572, 3668, 16236, + 512, 3728, 16236, + 456, 3784, 16236, + 400, 3836, 16240, + 348, 3884, 16244, + 296, 3928, 16252, + 252, 3964, 16260, + 204, 4000, 16268, + 164, 4028, 16284, + 124, 4052, 16296, + 88, 4072, 16316, + 56, 4084, 16336, + 24, 4092, 16356, + 0, 4096, 0 +}; + +const uint16_t filter_3tap_64p_117[99] = { + 2048, 2048, 0, + 1992, 2104, 16380, + 1936, 2160, 16380, + 1880, 2220, 16376, + 1824, 2276, 16376, + 1768, 2332, 16376, + 1712, 2388, 16376, + 1656, 2444, 16376, + 1600, 2496, 16380, + 1544, 2548, 0, + 1488, 2600, 4, + 1432, 2652, 8, + 1376, 2700, 16, + 1320, 2748, 20, + 1264, 2796, 32, + 1212, 2840, 40, + 1156, 2880, 52, + 1104, 2920, 64, + 1052, 2960, 80, + 1000, 2996, 92, + 948, 3032, 108, + 900, 3060, 128, + 852, 3092, 148, + 804, 3120, 168, + 756, 3144, 192, + 712, 3164, 216, + 668, 3184, 240, + 624, 3200, 268, + 580, 3212, 296, + 540, 3220, 328, + 500, 3228, 360, + 464, 3232, 392, + 428, 3236, 428 +}; + +const uint16_t filter_3tap_64p_150[99] = { + 2048, 2048, 0, + 2004, 2080, 8, + 1960, 2116, 16, + 1916, 2148, 28, + 1872, 2184, 36, + 1824, 2216, 48, + 1780, 2248, 60, + 1736, 2280, 76, + 1692, 2308, 88, + 1648, 2336, 104, + 1604, 2368, 120, + 1560, 2392, 136, + 1516, 2420, 156, + 1472, 2444, 172, + 1428, 2472, 192, + 1384, 2492, 212, + 1340, 2516, 236, + 1296, 2536, 256, + 1252, 2556, 280, + 1212, 2576, 304, + 1168, 2592, 328, + 1124, 2608, 356, + 1084, 2624, 384, + 1044, 2636, 412, + 1004, 2648, 440, + 964, 2660, 468, + 924, 2668, 500, + 884, 2676, 528, + 844, 2684, 560, + 808, 2688, 596, + 768, 2692, 628, + 732, 2696, 664, + 696, 2696, 696 +}; + +const uint16_t filter_3tap_64p_183[99] = { + 2048, 2048, 0, + 2008, 2060, 20, + 1968, 2076, 44, + 1932, 2088, 68, + 1892, 2104, 92, + 1856, 2116, 120, + 1816, 2128, 144, + 1780, 2140, 168, + 1744, 2152, 196, + 1704, 2164, 220, + 1668, 2176, 248, + 1632, 2188, 272, + 1592, 2196, 300, + 1556, 2204, 328, + 1520, 2216, 356, + 1484, 2224, 384, + 1448, 2232, 412, + 1412, 2240, 440, + 1376, 2244, 468, + 1340, 2252, 496, + 1304, 2256, 528, + 1272, 2264, 556, + 1236, 2268, 584, + 1200, 2272, 616, + 1168, 2276, 648, + 1132, 2280, 676, + 1100, 2284, 708, + 1064, 2288, 740, + 1032, 2288, 772, + 996, 2292, 800, + 964, 2292, 832, + 932, 2292, 868, + 900, 2292, 900 +}; + +const uint16_t filter_4tap_64p_upscale[132] = { + 0, 4096, 0, 0, + 16344, 4092, 40, 0, + 16308, 4084, 84, 16380, + 16272, 4072, 132, 16380, + 16240, 4056, 180, 16380, + 16212, 4036, 232, 16376, + 16184, 4012, 288, 16372, + 16160, 3984, 344, 16368, + 16136, 3952, 404, 16364, + 16116, 3916, 464, 16360, + 16100, 3872, 528, 16356, + 16084, 3828, 596, 16348, + 16072, 3780, 664, 16344, + 16060, 3728, 732, 16336, + 16052, 3676, 804, 16328, + 16044, 3616, 876, 16320, + 16040, 3556, 952, 16312, + 16036, 3492, 1028, 16300, + 16032, 3424, 1108, 16292, + 16032, 3356, 1188, 16280, + 16036, 3284, 1268, 16272, + 16036, 3212, 1352, 16260, + 16040, 3136, 1436, 16248, + 16044, 3056, 1520, 16236, + 16052, 2980, 1604, 16224, + 16060, 2896, 1688, 16212, + 16064, 2816, 1776, 16200, + 16076, 2732, 1864, 16188, + 16084, 2648, 1952, 16176, + 16092, 2564, 2040, 16164, + 16104, 2476, 2128, 16152, + 16116, 2388, 2216, 16140, + 16128, 2304, 2304, 16128 }; + +const uint16_t filter_4tap_64p_117[132] = { + 420, 3248, 420, 0, + 380, 3248, 464, 16380, + 344, 3248, 508, 16372, + 308, 3248, 552, 16368, + 272, 3240, 596, 16364, + 236, 3236, 644, 16356, + 204, 3224, 692, 16352, + 172, 3212, 744, 16344, + 144, 3196, 796, 16340, + 116, 3180, 848, 16332, + 88, 3160, 900, 16324, + 60, 3136, 956, 16320, + 36, 3112, 1012, 16312, + 16, 3084, 1068, 16304, + 16380, 3056, 1124, 16296, + 16360, 3024, 1184, 16292, + 16340, 2992, 1244, 16284, + 16324, 2956, 1304, 16276, + 16308, 2920, 1364, 16268, + 16292, 2880, 1424, 16264, + 16280, 2836, 1484, 16256, + 16268, 2792, 1548, 16252, + 16256, 2748, 1608, 16244, + 16248, 2700, 1668, 16240, + 16240, 2652, 1732, 16232, + 16232, 2604, 1792, 16228, + 16228, 2552, 1856, 16224, + 16220, 2500, 1916, 16220, + 16216, 2444, 1980, 16216, + 16216, 2388, 2040, 16216, + 16212, 2332, 2100, 16212, + 16212, 2276, 2160, 16212, + 16212, 2220, 2220, 16212 }; + +const uint16_t filter_4tap_64p_150[132] = { + 696, 2700, 696, 0, + 660, 2704, 732, 16380, + 628, 2704, 768, 16376, + 596, 2704, 804, 16372, + 564, 2700, 844, 16364, + 532, 2696, 884, 16360, + 500, 2692, 924, 16356, + 472, 2684, 964, 16352, + 440, 2676, 1004, 16352, + 412, 2668, 1044, 16348, + 384, 2656, 1088, 16344, + 360, 2644, 1128, 16340, + 332, 2632, 1172, 16336, + 308, 2616, 1216, 16336, + 284, 2600, 1260, 16332, + 260, 2580, 1304, 16332, + 236, 2560, 1348, 16328, + 216, 2540, 1392, 16328, + 196, 2516, 1436, 16328, + 176, 2492, 1480, 16324, + 156, 2468, 1524, 16324, + 136, 2440, 1568, 16328, + 120, 2412, 1612, 16328, + 104, 2384, 1656, 16328, + 88, 2352, 1700, 16332, + 72, 2324, 1744, 16332, + 60, 2288, 1788, 16336, + 48, 2256, 1828, 16340, + 36, 2220, 1872, 16344, + 24, 2184, 1912, 16352, + 12, 2148, 1952, 16356, + 4, 2112, 1996, 16364, + 16380, 2072, 2036, 16372 }; + +const uint16_t filter_4tap_64p_183[132] = { + 944, 2204, 944, 0, + 916, 2204, 972, 0, + 888, 2200, 996, 0, + 860, 2200, 1024, 4, + 832, 2196, 1052, 4, + 808, 2192, 1080, 8, + 780, 2188, 1108, 12, + 756, 2180, 1140, 12, + 728, 2176, 1168, 16, + 704, 2168, 1196, 20, + 680, 2160, 1224, 24, + 656, 2152, 1252, 28, + 632, 2144, 1280, 36, + 608, 2132, 1308, 40, + 584, 2120, 1336, 48, + 560, 2112, 1364, 52, + 536, 2096, 1392, 60, + 516, 2084, 1420, 68, + 492, 2072, 1448, 76, + 472, 2056, 1476, 84, + 452, 2040, 1504, 92, + 428, 2024, 1532, 100, + 408, 2008, 1560, 112, + 392, 1992, 1584, 120, + 372, 1972, 1612, 132, + 352, 1956, 1636, 144, + 336, 1936, 1664, 156, + 316, 1916, 1688, 168, + 300, 1896, 1712, 180, + 284, 1876, 1736, 192, + 268, 1852, 1760, 208, + 252, 1832, 1784, 220, + 236, 1808, 1808, 236 }; + +const uint16_t *get_filter_3tap_16p(struct fixed31_32 ratio) +{ + if (ratio.value < dal_fixed31_32_one.value) + return filter_3tap_16p_upscale; + else if (ratio.value < dal_fixed31_32_from_fraction(4, 3).value) + return filter_3tap_16p_117; + else if (ratio.value < dal_fixed31_32_from_fraction(5, 3).value) + return filter_3tap_16p_150; + else + return filter_3tap_16p_183; +} + +const uint16_t *get_filter_3tap_64p(struct fixed31_32 ratio) +{ + if (ratio.value < dal_fixed31_32_one.value) + return filter_3tap_64p_upscale; + else if (ratio.value < dal_fixed31_32_from_fraction(4, 3).value) + return filter_3tap_64p_117; + else if (ratio.value < dal_fixed31_32_from_fraction(5, 3).value) + return filter_3tap_64p_150; + else + return filter_3tap_64p_183; +} + +const uint16_t *get_filter_4tap_16p(struct fixed31_32 ratio) +{ + if (ratio.value < dal_fixed31_32_one.value) + return filter_4tap_16p_upscale; + else if (ratio.value < dal_fixed31_32_from_fraction(4, 3).value) + return filter_4tap_16p_117; + else if (ratio.value < dal_fixed31_32_from_fraction(5, 3).value) + return filter_4tap_16p_150; + else + return filter_4tap_16p_183; +} + +const uint16_t *get_filter_4tap_64p(struct fixed31_32 ratio) +{ + if (ratio.value < dal_fixed31_32_one.value) + return filter_4tap_64p_upscale; + else if (ratio.value < dal_fixed31_32_from_fraction(4, 3).value) + return filter_4tap_64p_117; + else if (ratio.value < dal_fixed31_32_from_fraction(5, 3).value) + return filter_4tap_64p_150; + else + return filter_4tap_64p_183; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c new file mode 100644 index 000000000000..842182ce93a8 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c @@ -0,0 +1,1302 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dc_bios_types.h" +#include "dce_stream_encoder.h" +#include "reg_helper.h" + +enum DP_PIXEL_ENCODING { +DP_PIXEL_ENCODING_RGB444 = 0x00000000, +DP_PIXEL_ENCODING_YCBCR422 = 0x00000001, +DP_PIXEL_ENCODING_YCBCR444 = 0x00000002, +DP_PIXEL_ENCODING_RGB_WIDE_GAMUT = 0x00000003, +DP_PIXEL_ENCODING_Y_ONLY = 0x00000004, +DP_PIXEL_ENCODING_YCBCR420 = 0x00000005, +DP_PIXEL_ENCODING_RESERVED = 0x00000006, +}; + + +enum DP_COMPONENT_DEPTH { +DP_COMPONENT_DEPTH_6BPC = 0x00000000, +DP_COMPONENT_DEPTH_8BPC = 0x00000001, +DP_COMPONENT_DEPTH_10BPC = 0x00000002, +DP_COMPONENT_DEPTH_12BPC = 0x00000003, +DP_COMPONENT_DEPTH_16BPC = 0x00000004, +DP_COMPONENT_DEPTH_RESERVED = 0x00000005, +}; + + +#define REG(reg)\ + (enc110->regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + enc110->se_shift->field_name, enc110->se_mask->field_name + +#define VBI_LINE_0 0 +#define DP_BLANK_MAX_RETRY 20 +#define HDMI_CLOCK_CHANNEL_RATE_MORE_340M 340000 + +#ifndef TMDS_CNTL__TMDS_PIXEL_ENCODING_MASK + #define TMDS_CNTL__TMDS_PIXEL_ENCODING_MASK 0x00000010L + #define TMDS_CNTL__TMDS_COLOR_FORMAT_MASK 0x00000300L + #define TMDS_CNTL__TMDS_PIXEL_ENCODING__SHIFT 0x00000004 + #define TMDS_CNTL__TMDS_COLOR_FORMAT__SHIFT 0x00000008 +#endif + +enum { + DP_MST_UPDATE_MAX_RETRY = 50 +}; + +#define DCE110_SE(audio)\ + container_of(audio, struct dce110_stream_encoder, base) + +#define CTX \ + enc110->base.ctx + +static void dce110_update_generic_info_packet( + struct dce110_stream_encoder *enc110, + uint32_t packet_index, + const struct encoder_info_packet *info_packet) +{ + uint32_t regval; + /* TODOFPGA Figure out a proper number for max_retries polling for lock + * use 50 for now. + */ + uint32_t max_retries = 50; + + if (REG(AFMT_VBI_PACKET_CONTROL1)) { + if (packet_index >= 8) + ASSERT(0); + + /* poll dig_update_lock is not locked -> asic internal signal + * assume otg master lock will unlock it + */ + REG_WAIT(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_LOCK_STATUS, + 1, 10, max_retries); + + /* check if HW reading GSP memory */ + REG_WAIT(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT, + 1, 10, max_retries); + + /* HW does is not reading GSP memory not reading too long -> + * something wrong. clear GPS memory access and notify? + * hw SW is writing to GSP memory + */ + REG_UPDATE(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT_CLR, 1); + } + /* choose which generic packet to use */ + { + regval = REG_READ(AFMT_VBI_PACKET_CONTROL); + REG_UPDATE(AFMT_VBI_PACKET_CONTROL, + AFMT_GENERIC_INDEX, packet_index); + } + + /* write generic packet header + * (4th byte is for GENERIC0 only) */ + { + REG_SET_4(AFMT_GENERIC_HDR, 0, + AFMT_GENERIC_HB0, info_packet->hb0, + AFMT_GENERIC_HB1, info_packet->hb1, + AFMT_GENERIC_HB2, info_packet->hb2, + AFMT_GENERIC_HB3, info_packet->hb3); + } + + /* write generic packet contents + * (we never use last 4 bytes) + * there are 8 (0-7) mmDIG0_AFMT_GENERIC0_x registers */ + { + const uint32_t *content = + (const uint32_t *) &info_packet->sb[0]; + + REG_WRITE(AFMT_GENERIC_0, *content++); + REG_WRITE(AFMT_GENERIC_1, *content++); + REG_WRITE(AFMT_GENERIC_2, *content++); + REG_WRITE(AFMT_GENERIC_3, *content++); + REG_WRITE(AFMT_GENERIC_4, *content++); + REG_WRITE(AFMT_GENERIC_5, *content++); + REG_WRITE(AFMT_GENERIC_6, *content); + REG_WRITE(AFMT_GENERIC_7, 0); + } + + if (!REG(AFMT_VBI_PACKET_CONTROL1)) { + /* force double-buffered packet update */ + REG_UPDATE_2(AFMT_VBI_PACKET_CONTROL, + AFMT_GENERIC0_UPDATE, (packet_index == 0), + AFMT_GENERIC2_UPDATE, (packet_index == 2)); + } +} + +static void dce110_update_hdmi_info_packet( + struct dce110_stream_encoder *enc110, + uint32_t packet_index, + const struct encoder_info_packet *info_packet) +{ + struct dc_context *ctx = enc110->base.ctx; + uint32_t cont, send, line; + + if (info_packet->valid) { + dce110_update_generic_info_packet( + enc110, + packet_index, + info_packet); + + /* enable transmission of packet(s) - + * packet transmission begins on the next frame */ + cont = 1; + /* send packet(s) every frame */ + send = 1; + /* select line number to send packets on */ + line = 2; + } else { + cont = 0; + send = 0; + line = 0; + } + + /* choose which generic packet control to use */ + switch (packet_index) { + case 0: + REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL0, + HDMI_GENERIC0_CONT, cont, + HDMI_GENERIC0_SEND, send, + HDMI_GENERIC0_LINE, line); + break; + case 1: + REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL0, + HDMI_GENERIC1_CONT, cont, + HDMI_GENERIC1_SEND, send, + HDMI_GENERIC1_LINE, line); + break; + case 2: + REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL1, + HDMI_GENERIC0_CONT, cont, + HDMI_GENERIC0_SEND, send, + HDMI_GENERIC0_LINE, line); + break; + case 3: + REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL1, + HDMI_GENERIC1_CONT, cont, + HDMI_GENERIC1_SEND, send, + HDMI_GENERIC1_LINE, line); + break; + default: + /* invalid HW packet index */ + dm_logger_write( + ctx->logger, LOG_WARNING, + "Invalid HW packet index: %s()\n", + __func__); + return; + } +} + +/* setup stream encoder in dp mode */ +static void dce110_stream_encoder_dp_set_stream_attribute( + struct stream_encoder *enc, + struct dc_crtc_timing *crtc_timing, + enum dc_color_space output_color_space) +{ + + struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); + + /* set pixel encoding */ + switch (crtc_timing->pixel_encoding) { + case PIXEL_ENCODING_YCBCR422: + REG_UPDATE(DP_PIXEL_FORMAT, DP_PIXEL_ENCODING, + DP_PIXEL_ENCODING_YCBCR422); + break; + case PIXEL_ENCODING_YCBCR444: + REG_UPDATE(DP_PIXEL_FORMAT, DP_PIXEL_ENCODING, + DP_PIXEL_ENCODING_YCBCR444); + + if (crtc_timing->flags.Y_ONLY) + if (crtc_timing->display_color_depth != COLOR_DEPTH_666) + /* HW testing only, no use case yet. + * Color depth of Y-only could be + * 8, 10, 12, 16 bits */ + REG_UPDATE(DP_PIXEL_FORMAT, DP_PIXEL_ENCODING, + DP_PIXEL_ENCODING_Y_ONLY); + /* Note: DP_MSA_MISC1 bit 7 is the indicator + * of Y-only mode. + * This bit is set in HW if register + * DP_PIXEL_ENCODING is programmed to 0x4 */ + break; + case PIXEL_ENCODING_YCBCR420: + REG_UPDATE(DP_PIXEL_FORMAT, DP_PIXEL_ENCODING, + DP_PIXEL_ENCODING_YCBCR420); + if (enc110->se_mask->DP_VID_M_DOUBLE_VALUE_EN) + REG_UPDATE(DP_VID_TIMING, DP_VID_M_DOUBLE_VALUE_EN, 1); + + break; + default: + REG_UPDATE(DP_PIXEL_FORMAT, DP_PIXEL_ENCODING, + DP_PIXEL_ENCODING_RGB444); + break; + } + + /* set color depth */ + + switch (crtc_timing->display_color_depth) { + case COLOR_DEPTH_666: + REG_UPDATE(DP_PIXEL_FORMAT, DP_COMPONENT_DEPTH, + 0); + break; + case COLOR_DEPTH_888: + REG_UPDATE(DP_PIXEL_FORMAT, DP_COMPONENT_DEPTH, + DP_COMPONENT_DEPTH_8BPC); + break; + case COLOR_DEPTH_101010: + REG_UPDATE(DP_PIXEL_FORMAT, DP_COMPONENT_DEPTH, + DP_COMPONENT_DEPTH_10BPC); + + break; + case COLOR_DEPTH_121212: + REG_UPDATE(DP_PIXEL_FORMAT, DP_COMPONENT_DEPTH, + DP_COMPONENT_DEPTH_12BPC); + break; + default: + REG_UPDATE(DP_PIXEL_FORMAT, DP_COMPONENT_DEPTH, + DP_COMPONENT_DEPTH_6BPC); + break; + } + + /* set dynamic range and YCbCr range */ + if (enc110->se_mask->DP_DYN_RANGE && enc110->se_mask->DP_YCBCR_RANGE) + REG_UPDATE_2( + DP_PIXEL_FORMAT, + DP_DYN_RANGE, 0, + DP_YCBCR_RANGE, 0); + +} + +static void dce110_stream_encoder_set_stream_attribute_helper( + struct dce110_stream_encoder *enc110, + struct dc_crtc_timing *crtc_timing) +{ + if (enc110->regs->TMDS_CNTL) { + switch (crtc_timing->pixel_encoding) { + case PIXEL_ENCODING_YCBCR422: + REG_UPDATE(TMDS_CNTL, TMDS_PIXEL_ENCODING, 1); + break; + default: + REG_UPDATE(TMDS_CNTL, TMDS_PIXEL_ENCODING, 0); + break; + } + REG_UPDATE(TMDS_CNTL, TMDS_COLOR_FORMAT, 0); + } else if (enc110->regs->DIG_FE_CNTL) { + switch (crtc_timing->pixel_encoding) { + case PIXEL_ENCODING_YCBCR422: + REG_UPDATE(DIG_FE_CNTL, TMDS_PIXEL_ENCODING, 1); + break; + default: + REG_UPDATE(DIG_FE_CNTL, TMDS_PIXEL_ENCODING, 0); + break; + } + REG_UPDATE(DIG_FE_CNTL, TMDS_COLOR_FORMAT, 0); + } + +} + +/* setup stream encoder in hdmi mode */ +static void dce110_stream_encoder_hdmi_set_stream_attribute( + struct stream_encoder *enc, + struct dc_crtc_timing *crtc_timing, + int actual_pix_clk_khz, + bool enable_audio) +{ + struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); + struct bp_encoder_control cntl = {0}; + + cntl.action = ENCODER_CONTROL_SETUP; + cntl.engine_id = enc110->base.id; + cntl.signal = SIGNAL_TYPE_HDMI_TYPE_A; + cntl.enable_dp_audio = enable_audio; + cntl.pixel_clock = actual_pix_clk_khz; + cntl.lanes_number = LANE_COUNT_FOUR; + + if (enc110->base.bp->funcs->encoder_control( + enc110->base.bp, &cntl) != BP_RESULT_OK) + return; + + dce110_stream_encoder_set_stream_attribute_helper(enc110, crtc_timing); + + /* setup HDMI engine */ + if (!enc110->se_mask->HDMI_DATA_SCRAMBLE_EN) { + REG_UPDATE_3(HDMI_CONTROL, + HDMI_PACKET_GEN_VERSION, 1, + HDMI_KEEPOUT_MODE, 1, + HDMI_DEEP_COLOR_ENABLE, 0); + } else if (enc110->regs->DIG_FE_CNTL) { + REG_UPDATE_5(HDMI_CONTROL, + HDMI_PACKET_GEN_VERSION, 1, + HDMI_KEEPOUT_MODE, 1, + HDMI_DEEP_COLOR_ENABLE, 0, + HDMI_DATA_SCRAMBLE_EN, 0, + HDMI_CLOCK_CHANNEL_RATE, 0); + } + + switch (crtc_timing->display_color_depth) { + case COLOR_DEPTH_888: + REG_UPDATE(HDMI_CONTROL, HDMI_DEEP_COLOR_DEPTH, 0); + break; + case COLOR_DEPTH_101010: + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DEEP_COLOR_DEPTH, 1, + HDMI_DEEP_COLOR_ENABLE, 1); + break; + case COLOR_DEPTH_121212: + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DEEP_COLOR_DEPTH, 2, + HDMI_DEEP_COLOR_ENABLE, 1); + break; + case COLOR_DEPTH_161616: + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DEEP_COLOR_DEPTH, 3, + HDMI_DEEP_COLOR_ENABLE, 1); + break; + default: + break; + } + + if (enc110->se_mask->HDMI_DATA_SCRAMBLE_EN) { + if (actual_pix_clk_khz >= HDMI_CLOCK_CHANNEL_RATE_MORE_340M) { + /* enable HDMI data scrambler + * HDMI_CLOCK_CHANNEL_RATE_MORE_340M + * Clock channel frequency is 1/4 of character rate. + */ + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DATA_SCRAMBLE_EN, 1, + HDMI_CLOCK_CHANNEL_RATE, 1); + } else if (crtc_timing->flags.LTE_340MCSC_SCRAMBLE) { + + /* TODO: New feature for DCE11, still need to implement */ + + /* enable HDMI data scrambler + * HDMI_CLOCK_CHANNEL_FREQ_EQUAL_TO_CHAR_RATE + * Clock channel frequency is the same + * as character rate + */ + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DATA_SCRAMBLE_EN, 1, + HDMI_CLOCK_CHANNEL_RATE, 0); + } + } + + REG_UPDATE_3(HDMI_VBI_PACKET_CONTROL, + HDMI_GC_CONT, 1, + HDMI_GC_SEND, 1, + HDMI_NULL_SEND, 1); + + /* following belongs to audio */ + REG_UPDATE(HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_SEND, 1); + + REG_UPDATE(AFMT_INFOFRAME_CONTROL0, AFMT_AUDIO_INFO_UPDATE, 1); + + REG_UPDATE(HDMI_INFOFRAME_CONTROL1, HDMI_AUDIO_INFO_LINE, + VBI_LINE_0 + 2); + + REG_UPDATE(HDMI_GC, HDMI_GC_AVMUTE, 0); + +} + +/* setup stream encoder in dvi mode */ +static void dce110_stream_encoder_dvi_set_stream_attribute( + struct stream_encoder *enc, + struct dc_crtc_timing *crtc_timing, + bool is_dual_link) +{ + struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); + struct bp_encoder_control cntl = {0}; + + cntl.action = ENCODER_CONTROL_SETUP; + cntl.engine_id = enc110->base.id; + cntl.signal = is_dual_link ? + SIGNAL_TYPE_DVI_DUAL_LINK : SIGNAL_TYPE_DVI_SINGLE_LINK; + cntl.enable_dp_audio = false; + cntl.pixel_clock = crtc_timing->pix_clk_khz; + cntl.lanes_number = (is_dual_link) ? LANE_COUNT_EIGHT : LANE_COUNT_FOUR; + + if (enc110->base.bp->funcs->encoder_control( + enc110->base.bp, &cntl) != BP_RESULT_OK) + return; + + ASSERT(crtc_timing->pixel_encoding == PIXEL_ENCODING_RGB); + ASSERT(crtc_timing->display_color_depth == COLOR_DEPTH_888); + dce110_stream_encoder_set_stream_attribute_helper(enc110, crtc_timing); +} + +static void dce110_stream_encoder_set_mst_bandwidth( + struct stream_encoder *enc, + struct fixed31_32 avg_time_slots_per_mtp) +{ + struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); + uint32_t x = dal_fixed31_32_floor( + avg_time_slots_per_mtp); + uint32_t y = dal_fixed31_32_ceil( + dal_fixed31_32_shl( + dal_fixed31_32_sub_int( + avg_time_slots_per_mtp, + x), + 26)); + + { + REG_SET_2(DP_MSE_RATE_CNTL, 0, + DP_MSE_RATE_X, x, + DP_MSE_RATE_Y, y); + } + + /* wait for update to be completed on the link */ + /* i.e. DP_MSE_RATE_UPDATE_PENDING field (read only) */ + /* is reset to 0 (not pending) */ + REG_WAIT(DP_MSE_RATE_UPDATE, DP_MSE_RATE_UPDATE_PENDING, + 0, + 10, DP_MST_UPDATE_MAX_RETRY); +} + +static void dce110_stream_encoder_update_hdmi_info_packets( + struct stream_encoder *enc, + const struct encoder_info_frame *info_frame) +{ + struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); + + if (enc110->se_mask->HDMI_AVI_INFO_CONT && + enc110->se_mask->HDMI_AVI_INFO_SEND) { + + if (info_frame->avi.valid) { + const uint32_t *content = + (const uint32_t *) &info_frame->avi.sb[0]; + + REG_WRITE(AFMT_AVI_INFO0, content[0]); + + REG_WRITE(AFMT_AVI_INFO1, content[1]); + + REG_WRITE(AFMT_AVI_INFO2, content[2]); + + REG_WRITE(AFMT_AVI_INFO3, content[3]); + + REG_UPDATE(AFMT_AVI_INFO3, AFMT_AVI_INFO_VERSION, + info_frame->avi.hb1); + + REG_UPDATE_2(HDMI_INFOFRAME_CONTROL0, + HDMI_AVI_INFO_SEND, 1, + HDMI_AVI_INFO_CONT, 1); + + REG_UPDATE(HDMI_INFOFRAME_CONTROL1, HDMI_AVI_INFO_LINE, + VBI_LINE_0 + 2); + + } else { + REG_UPDATE_2(HDMI_INFOFRAME_CONTROL0, + HDMI_AVI_INFO_SEND, 0, + HDMI_AVI_INFO_CONT, 0); + } + } + + if (enc110->se_mask->HDMI_AVI_INFO_CONT && + enc110->se_mask->HDMI_AVI_INFO_SEND) { + dce110_update_hdmi_info_packet(enc110, 0, &info_frame->vendor); + dce110_update_hdmi_info_packet(enc110, 1, &info_frame->gamut); + dce110_update_hdmi_info_packet(enc110, 2, &info_frame->spd); + } + +} + +static void dce110_stream_encoder_stop_hdmi_info_packets( + struct stream_encoder *enc) +{ + struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); + + /* stop generic packets 0 & 1 on HDMI */ + REG_SET_6(HDMI_GENERIC_PACKET_CONTROL0, 0, + HDMI_GENERIC1_CONT, 0, + HDMI_GENERIC1_LINE, 0, + HDMI_GENERIC1_SEND, 0, + HDMI_GENERIC0_CONT, 0, + HDMI_GENERIC0_LINE, 0, + HDMI_GENERIC0_SEND, 0); + + /* stop generic packets 2 & 3 on HDMI */ + REG_SET_6(HDMI_GENERIC_PACKET_CONTROL1, 0, + HDMI_GENERIC0_CONT, 0, + HDMI_GENERIC0_LINE, 0, + HDMI_GENERIC0_SEND, 0, + HDMI_GENERIC1_CONT, 0, + HDMI_GENERIC1_LINE, 0, + HDMI_GENERIC1_SEND, 0); + +} + +static void dce110_stream_encoder_update_dp_info_packets( + struct stream_encoder *enc, + const struct encoder_info_frame *info_frame) +{ + struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); + uint32_t value = REG_READ(DP_SEC_CNTL); + + if (info_frame->vsc.valid) + dce110_update_generic_info_packet( + enc110, + 0, /* packetIndex */ + &info_frame->vsc); + + /* enable/disable transmission of packet(s). + * If enabled, packet transmission begins on the next frame + */ + REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP0_ENABLE, info_frame->vsc.valid); + + /* This bit is the master enable bit. + * When enabling secondary stream engine, + * this master bit must also be set. + * This register shared with audio info frame. + * Therefore we need to enable master bit + * if at least on of the fields is not 0 + */ + if (value) + REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1); +} + +static void dce110_stream_encoder_stop_dp_info_packets( + struct stream_encoder *enc) +{ + /* stop generic packets on DP */ + struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); + uint32_t value = REG_READ(DP_SEC_CNTL); + + if (enc110->se_mask->DP_SEC_AVI_ENABLE) { + REG_SET_7(DP_SEC_CNTL, 0, + DP_SEC_GSP0_ENABLE, 0, + DP_SEC_GSP1_ENABLE, 0, + DP_SEC_GSP2_ENABLE, 0, + DP_SEC_GSP3_ENABLE, 0, + DP_SEC_AVI_ENABLE, 0, + DP_SEC_MPG_ENABLE, 0, + DP_SEC_STREAM_ENABLE, 0); + } + + /* this register shared with audio info frame. + * therefore we need to keep master enabled + * if at least one of the fields is not 0 */ + + if (value) + REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1); + +} + +static void dce110_stream_encoder_dp_blank( + struct stream_encoder *enc) +{ + struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); + uint32_t retries = 0; + uint32_t max_retries = DP_BLANK_MAX_RETRY * 10; + + /* Note: For CZ, we are changing driver default to disable + * stream deferred to next VBLANK. If results are positive, we + * will make the same change to all DCE versions. There are a + * handful of panels that cannot handle disable stream at + * HBLANK and will result in a white line flash across the + * screen on stream disable. */ + + /* Specify the video stream disable point + * (2 = start of the next vertical blank) */ + REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_DIS_DEFER, 2); + /* Larger delay to wait until VBLANK - use max retry of + * 10us*3000=30ms. This covers 16.6ms of typical 60 Hz mode + + * a little more because we may not trust delay accuracy. + */ + max_retries = DP_BLANK_MAX_RETRY * 150; + + /* disable DP stream */ + REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, 0); + + /* the encoder stops sending the video stream + * at the start of the vertical blanking. + * Poll for DP_VID_STREAM_STATUS == 0 + */ + + REG_WAIT(DP_VID_STREAM_CNTL, DP_VID_STREAM_STATUS, + 1, + 10, max_retries); + + ASSERT(retries <= max_retries); + + /* Tell the DP encoder to ignore timing from CRTC, must be done after + * the polling. If we set DP_STEER_FIFO_RESET before DP stream blank is + * complete, stream status will be stuck in video stream enabled state, + * i.e. DP_VID_STREAM_STATUS stuck at 1. + */ + + REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, true); +} + +/* output video stream to link encoder */ +static void dce110_stream_encoder_dp_unblank( + struct stream_encoder *enc, + const struct encoder_unblank_param *param) +{ + struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); + + if (param->link_settings.link_rate != LINK_RATE_UNKNOWN) { + uint32_t n_vid = 0x8000; + uint32_t m_vid; + + /* M / N = Fstream / Flink + * m_vid / n_vid = pixel rate / link rate + */ + + uint64_t m_vid_l = n_vid; + + m_vid_l *= param->crtc_timing.pixel_clock; + m_vid_l = div_u64(m_vid_l, + param->link_settings.link_rate + * LINK_RATE_REF_FREQ_IN_KHZ); + + m_vid = (uint32_t) m_vid_l; + + /* enable auto measurement */ + + REG_UPDATE(DP_VID_TIMING, DP_VID_M_N_GEN_EN, 0); + + /* auto measurement need 1 full 0x8000 symbol cycle to kick in, + * therefore program initial value for Mvid and Nvid + */ + + REG_UPDATE(DP_VID_N, DP_VID_N, n_vid); + + REG_UPDATE(DP_VID_M, DP_VID_M, m_vid); + + REG_UPDATE(DP_VID_TIMING, DP_VID_M_N_GEN_EN, 1); + } + + /* set DIG_START to 0x1 to resync FIFO */ + + REG_UPDATE(DIG_FE_CNTL, DIG_START, 1); + + /* switch DP encoder to CRTC data */ + + REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, 0); + + /* wait 100us for DIG/DP logic to prime + * (i.e. a few video lines) + */ + udelay(100); + + /* the hardware would start sending video at the start of the next DP + * frame (i.e. rising edge of the vblank). + * NOTE: We used to program DP_VID_STREAM_DIS_DEFER = 2 here, but this + * register has no effect on enable transition! HW always guarantees + * VID_STREAM enable at start of next frame, and this is not + * programmable + */ + + REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, true); +} + + +#define DP_SEC_AUD_N__DP_SEC_AUD_N__DEFAULT 0x8000 +#define DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUTO_CALC 1 + +#include "include/audio_types.h" + +/** +* speakersToChannels +* +* @brief +* translate speakers to channels +* +* FL - Front Left +* FR - Front Right +* RL - Rear Left +* RR - Rear Right +* RC - Rear Center +* FC - Front Center +* FLC - Front Left Center +* FRC - Front Right Center +* RLC - Rear Left Center +* RRC - Rear Right Center +* LFE - Low Freq Effect +* +* FC +* FLC FRC +* FL FR +* +* LFE +* () +* +* +* RL RR +* RLC RRC +* RC +* +* ch 8 7 6 5 4 3 2 1 +* 0b00000011 - - - - - - FR FL +* 0b00000111 - - - - - LFE FR FL +* 0b00001011 - - - - FC - FR FL +* 0b00001111 - - - - FC LFE FR FL +* 0b00010011 - - - RC - - FR FL +* 0b00010111 - - - RC - LFE FR FL +* 0b00011011 - - - RC FC - FR FL +* 0b00011111 - - - RC FC LFE FR FL +* 0b00110011 - - RR RL - - FR FL +* 0b00110111 - - RR RL - LFE FR FL +* 0b00111011 - - RR RL FC - FR FL +* 0b00111111 - - RR RL FC LFE FR FL +* 0b01110011 - RC RR RL - - FR FL +* 0b01110111 - RC RR RL - LFE FR FL +* 0b01111011 - RC RR RL FC - FR FL +* 0b01111111 - RC RR RL FC LFE FR FL +* 0b11110011 RRC RLC RR RL - - FR FL +* 0b11110111 RRC RLC RR RL - LFE FR FL +* 0b11111011 RRC RLC RR RL FC - FR FL +* 0b11111111 RRC RLC RR RL FC LFE FR FL +* 0b11000011 FRC FLC - - - - FR FL +* 0b11000111 FRC FLC - - - LFE FR FL +* 0b11001011 FRC FLC - - FC - FR FL +* 0b11001111 FRC FLC - - FC LFE FR FL +* 0b11010011 FRC FLC - RC - - FR FL +* 0b11010111 FRC FLC - RC - LFE FR FL +* 0b11011011 FRC FLC - RC FC - FR FL +* 0b11011111 FRC FLC - RC FC LFE FR FL +* 0b11110011 FRC FLC RR RL - - FR FL +* 0b11110111 FRC FLC RR RL - LFE FR FL +* 0b11111011 FRC FLC RR RL FC - FR FL +* 0b11111111 FRC FLC RR RL FC LFE FR FL +* +* @param +* speakers - speaker information as it comes from CEA audio block +*/ +/* translate speakers to channels */ + +union audio_cea_channels { + uint8_t all; + struct audio_cea_channels_bits { + uint32_t FL:1; + uint32_t FR:1; + uint32_t LFE:1; + uint32_t FC:1; + uint32_t RL_RC:1; + uint32_t RR:1; + uint32_t RC_RLC_FLC:1; + uint32_t RRC_FRC:1; + } channels; +}; + +struct audio_clock_info { + /* pixel clock frequency*/ + uint32_t pixel_clock_in_10khz; + /* N - 32KHz audio */ + uint32_t n_32khz; + /* CTS - 32KHz audio*/ + uint32_t cts_32khz; + uint32_t n_44khz; + uint32_t cts_44khz; + uint32_t n_48khz; + uint32_t cts_48khz; +}; + +/* 25.2MHz/1.001*/ +/* 25.2MHz/1.001*/ +/* 25.2MHz*/ +/* 27MHz */ +/* 27MHz*1.001*/ +/* 27MHz*1.001*/ +/* 54MHz*/ +/* 54MHz*1.001*/ +/* 74.25MHz/1.001*/ +/* 74.25MHz*/ +/* 148.5MHz/1.001*/ +/* 148.5MHz*/ + +static const struct audio_clock_info audio_clock_info_table[12] = { + {2517, 4576, 28125, 7007, 31250, 6864, 28125}, + {2518, 4576, 28125, 7007, 31250, 6864, 28125}, + {2520, 4096, 25200, 6272, 28000, 6144, 25200}, + {2700, 4096, 27000, 6272, 30000, 6144, 27000}, + {2702, 4096, 27027, 6272, 30030, 6144, 27027}, + {2703, 4096, 27027, 6272, 30030, 6144, 27027}, + {5400, 4096, 54000, 6272, 60000, 6144, 54000}, + {5405, 4096, 54054, 6272, 60060, 6144, 54054}, + {7417, 11648, 210937, 17836, 234375, 11648, 140625}, + {7425, 4096, 74250, 6272, 82500, 6144, 74250}, + {14835, 11648, 421875, 8918, 234375, 5824, 140625}, + {14850, 4096, 148500, 6272, 165000, 6144, 148500} +}; + +static const struct audio_clock_info audio_clock_info_table_36bpc[12] = { + {2517, 9152, 84375, 7007, 48875, 9152, 56250}, + {2518, 9152, 84375, 7007, 48875, 9152, 56250}, + {2520, 4096, 37800, 6272, 42000, 6144, 37800}, + {2700, 4096, 40500, 6272, 45000, 6144, 40500}, + {2702, 8192, 81081, 6272, 45045, 8192, 54054}, + {2703, 8192, 81081, 6272, 45045, 8192, 54054}, + {5400, 4096, 81000, 6272, 90000, 6144, 81000}, + {5405, 4096, 81081, 6272, 90090, 6144, 81081}, + {7417, 11648, 316406, 17836, 351562, 11648, 210937}, + {7425, 4096, 111375, 6272, 123750, 6144, 111375}, + {14835, 11648, 632812, 17836, 703125, 11648, 421875}, + {14850, 4096, 222750, 6272, 247500, 6144, 222750} +}; + +static const struct audio_clock_info audio_clock_info_table_48bpc[12] = { + {2517, 4576, 56250, 7007, 62500, 6864, 56250}, + {2518, 4576, 56250, 7007, 62500, 6864, 56250}, + {2520, 4096, 50400, 6272, 56000, 6144, 50400}, + {2700, 4096, 54000, 6272, 60000, 6144, 54000}, + {2702, 4096, 54054, 6267, 60060, 8192, 54054}, + {2703, 4096, 54054, 6272, 60060, 8192, 54054}, + {5400, 4096, 108000, 6272, 120000, 6144, 108000}, + {5405, 4096, 108108, 6272, 120120, 6144, 108108}, + {7417, 11648, 421875, 17836, 468750, 11648, 281250}, + {7425, 4096, 148500, 6272, 165000, 6144, 148500}, + {14835, 11648, 843750, 8918, 468750, 11648, 281250}, + {14850, 4096, 297000, 6272, 330000, 6144, 297000} +}; + +union audio_cea_channels speakers_to_channels( + struct audio_speaker_flags speaker_flags) +{ + union audio_cea_channels cea_channels = {0}; + + /* these are one to one */ + cea_channels.channels.FL = speaker_flags.FL_FR; + cea_channels.channels.FR = speaker_flags.FL_FR; + cea_channels.channels.LFE = speaker_flags.LFE; + cea_channels.channels.FC = speaker_flags.FC; + + /* if Rear Left and Right exist move RC speaker to channel 7 + * otherwise to channel 5 + */ + if (speaker_flags.RL_RR) { + cea_channels.channels.RL_RC = speaker_flags.RL_RR; + cea_channels.channels.RR = speaker_flags.RL_RR; + cea_channels.channels.RC_RLC_FLC = speaker_flags.RC; + } else { + cea_channels.channels.RL_RC = speaker_flags.RC; + } + + /* FRONT Left Right Center and REAR Left Right Center are exclusive */ + if (speaker_flags.FLC_FRC) { + cea_channels.channels.RC_RLC_FLC = speaker_flags.FLC_FRC; + cea_channels.channels.RRC_FRC = speaker_flags.FLC_FRC; + } else { + cea_channels.channels.RC_RLC_FLC = speaker_flags.RLC_RRC; + cea_channels.channels.RRC_FRC = speaker_flags.RLC_RRC; + } + + return cea_channels; +} + +uint32_t calc_max_audio_packets_per_line( + const struct audio_crtc_info *crtc_info) +{ + uint32_t max_packets_per_line; + + max_packets_per_line = + crtc_info->h_total - crtc_info->h_active; + + if (crtc_info->pixel_repetition) + max_packets_per_line *= crtc_info->pixel_repetition; + + /* for other hdmi features */ + max_packets_per_line -= 58; + /* for Control Period */ + max_packets_per_line -= 16; + /* Number of Audio Packets per Line */ + max_packets_per_line /= 32; + + return max_packets_per_line; +} + +bool get_audio_clock_info( + enum dc_color_depth color_depth, + uint32_t crtc_pixel_clock_in_khz, + uint32_t actual_pixel_clock_in_khz, + struct audio_clock_info *audio_clock_info) +{ + const struct audio_clock_info *clock_info; + uint32_t index; + uint32_t crtc_pixel_clock_in_10khz = crtc_pixel_clock_in_khz / 10; + uint32_t audio_array_size; + + if (audio_clock_info == NULL) + return false; /* should not happen */ + + switch (color_depth) { + case COLOR_DEPTH_161616: + clock_info = audio_clock_info_table_48bpc; + audio_array_size = ARRAY_SIZE( + audio_clock_info_table_48bpc); + break; + case COLOR_DEPTH_121212: + clock_info = audio_clock_info_table_36bpc; + audio_array_size = ARRAY_SIZE( + audio_clock_info_table_36bpc); + break; + default: + clock_info = audio_clock_info_table; + audio_array_size = ARRAY_SIZE( + audio_clock_info_table); + break; + } + + if (clock_info != NULL) { + /* search for exact pixel clock in table */ + for (index = 0; index < audio_array_size; index++) { + if (clock_info[index].pixel_clock_in_10khz > + crtc_pixel_clock_in_10khz) + break; /* not match */ + else if (clock_info[index].pixel_clock_in_10khz == + crtc_pixel_clock_in_10khz) { + /* match found */ + *audio_clock_info = clock_info[index]; + return true; + } + } + } + + /* not found */ + if (actual_pixel_clock_in_khz == 0) + actual_pixel_clock_in_khz = crtc_pixel_clock_in_khz; + + /* See HDMI spec the table entry under + * pixel clock of "Other". */ + audio_clock_info->pixel_clock_in_10khz = + actual_pixel_clock_in_khz / 10; + audio_clock_info->cts_32khz = actual_pixel_clock_in_khz; + audio_clock_info->cts_44khz = actual_pixel_clock_in_khz; + audio_clock_info->cts_48khz = actual_pixel_clock_in_khz; + + audio_clock_info->n_32khz = 4096; + audio_clock_info->n_44khz = 6272; + audio_clock_info->n_48khz = 6144; + + return true; +} + +static void dce110_se_audio_setup( + struct stream_encoder *enc, + unsigned int az_inst, + struct audio_info *audio_info) +{ + struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); + + uint32_t speakers = 0; + uint32_t channels = 0; + + ASSERT(audio_info); + if (audio_info == NULL) + /* This should not happen.it does so we don't get BSOD*/ + return; + + speakers = audio_info->flags.info.ALLSPEAKERS; + channels = speakers_to_channels(audio_info->flags.speaker_flags).all; + + /* setup the audio stream source select (audio -> dig mapping) */ + REG_SET(AFMT_AUDIO_SRC_CONTROL, 0, AFMT_AUDIO_SRC_SELECT, az_inst); + + /* Channel allocation */ + REG_UPDATE(AFMT_AUDIO_PACKET_CONTROL2, AFMT_AUDIO_CHANNEL_ENABLE, channels); +} + +static void dce110_se_setup_hdmi_audio( + struct stream_encoder *enc, + const struct audio_crtc_info *crtc_info) +{ + struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); + + struct audio_clock_info audio_clock_info = {0}; + uint32_t max_packets_per_line; + + /* For now still do calculation, although this field is ignored when + above HDMI_PACKET_GEN_VERSION set to 1 */ + max_packets_per_line = calc_max_audio_packets_per_line(crtc_info); + + /* HDMI_AUDIO_PACKET_CONTROL */ + REG_UPDATE_2(HDMI_AUDIO_PACKET_CONTROL, + HDMI_AUDIO_PACKETS_PER_LINE, max_packets_per_line, + HDMI_AUDIO_DELAY_EN, 1); + + /* AFMT_AUDIO_PACKET_CONTROL */ + REG_UPDATE(AFMT_AUDIO_PACKET_CONTROL, AFMT_60958_CS_UPDATE, 1); + + /* AFMT_AUDIO_PACKET_CONTROL2 */ + REG_UPDATE_2(AFMT_AUDIO_PACKET_CONTROL2, + AFMT_AUDIO_LAYOUT_OVRD, 0, + AFMT_60958_OSF_OVRD, 0); + + /* HDMI_ACR_PACKET_CONTROL */ + REG_UPDATE_3(HDMI_ACR_PACKET_CONTROL, + HDMI_ACR_AUTO_SEND, 1, + HDMI_ACR_SOURCE, 0, + HDMI_ACR_AUDIO_PRIORITY, 0); + + /* Program audio clock sample/regeneration parameters */ + if (get_audio_clock_info( + crtc_info->color_depth, + crtc_info->requested_pixel_clock, + crtc_info->calculated_pixel_clock, + &audio_clock_info)) { + + /* HDMI_ACR_32_0__HDMI_ACR_CTS_32_MASK */ + REG_UPDATE(HDMI_ACR_32_0, HDMI_ACR_CTS_32, audio_clock_info.cts_32khz); + + /* HDMI_ACR_32_1__HDMI_ACR_N_32_MASK */ + REG_UPDATE(HDMI_ACR_32_1, HDMI_ACR_N_32, audio_clock_info.n_32khz); + + /* HDMI_ACR_44_0__HDMI_ACR_CTS_44_MASK */ + REG_UPDATE(HDMI_ACR_44_0, HDMI_ACR_CTS_44, audio_clock_info.cts_44khz); + + /* HDMI_ACR_44_1__HDMI_ACR_N_44_MASK */ + REG_UPDATE(HDMI_ACR_44_1, HDMI_ACR_N_44, audio_clock_info.n_44khz); + + /* HDMI_ACR_48_0__HDMI_ACR_CTS_48_MASK */ + REG_UPDATE(HDMI_ACR_48_0, HDMI_ACR_CTS_48, audio_clock_info.cts_48khz); + + /* HDMI_ACR_48_1__HDMI_ACR_N_48_MASK */ + REG_UPDATE(HDMI_ACR_48_1, HDMI_ACR_N_48, audio_clock_info.n_48khz); + + /* Video driver cannot know in advance which sample rate will + be used by HD Audio driver + HDMI_ACR_PACKET_CONTROL__HDMI_ACR_N_MULTIPLE field is + programmed below in interruppt callback */ + } /* if */ + + /* AFMT_60958_0__AFMT_60958_CS_CHANNEL_NUMBER_L_MASK & + AFMT_60958_0__AFMT_60958_CS_CLOCK_ACCURACY_MASK */ + REG_UPDATE_2(AFMT_60958_0, + AFMT_60958_CS_CHANNEL_NUMBER_L, 1, + AFMT_60958_CS_CLOCK_ACCURACY, 0); + + /* AFMT_60958_1 AFMT_60958_CS_CHALNNEL_NUMBER_R */ + REG_UPDATE(AFMT_60958_1, AFMT_60958_CS_CHANNEL_NUMBER_R, 2); + + /*AFMT_60958_2 now keep this settings until + * Programming guide comes out*/ + REG_UPDATE_6(AFMT_60958_2, + AFMT_60958_CS_CHANNEL_NUMBER_2, 3, + AFMT_60958_CS_CHANNEL_NUMBER_3, 4, + AFMT_60958_CS_CHANNEL_NUMBER_4, 5, + AFMT_60958_CS_CHANNEL_NUMBER_5, 6, + AFMT_60958_CS_CHANNEL_NUMBER_6, 7, + AFMT_60958_CS_CHANNEL_NUMBER_7, 8); +} + +static void dce110_se_setup_dp_audio( + struct stream_encoder *enc) +{ + struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); + + /* --- DP Audio packet configurations --- */ + + /* ATP Configuration */ + REG_SET(DP_SEC_AUD_N, 0, + DP_SEC_AUD_N, DP_SEC_AUD_N__DP_SEC_AUD_N__DEFAULT); + + /* Async/auto-calc timestamp mode */ + REG_SET(DP_SEC_TIMESTAMP, 0, DP_SEC_TIMESTAMP_MODE, + DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUTO_CALC); + + /* --- The following are the registers + * copied from the SetupHDMI --- */ + + /* AFMT_AUDIO_PACKET_CONTROL */ + REG_UPDATE(AFMT_AUDIO_PACKET_CONTROL, AFMT_60958_CS_UPDATE, 1); + + /* AFMT_AUDIO_PACKET_CONTROL2 */ + /* Program the ATP and AIP next */ + REG_UPDATE_2(AFMT_AUDIO_PACKET_CONTROL2, + AFMT_AUDIO_LAYOUT_OVRD, 0, + AFMT_60958_OSF_OVRD, 0); + + /* AFMT_INFOFRAME_CONTROL0 */ + REG_UPDATE(AFMT_INFOFRAME_CONTROL0, AFMT_AUDIO_INFO_UPDATE, 1); + + /* AFMT_60958_0__AFMT_60958_CS_CLOCK_ACCURACY_MASK */ + REG_UPDATE(AFMT_60958_0, AFMT_60958_CS_CLOCK_ACCURACY, 0); +} + +static void dce110_se_enable_audio_clock( + struct stream_encoder *enc, + bool enable) +{ + struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); + + if (REG(AFMT_CNTL) == 0) + return; /* DCE8/10 does not have this register */ + + REG_UPDATE(AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, !!enable); + + /* wait for AFMT clock to turn on, + * expectation: this should complete in 1-2 reads + * + * REG_WAIT(AFMT_CNTL, AFMT_AUDIO_CLOCK_ON, !!enable, 1, 10); + * + * TODO: wait for clock_on does not work well. May need HW + * program sequence. But audio seems work normally even without wait + * for clock_on status change + */ +} + +static void dce110_se_enable_dp_audio( + struct stream_encoder *enc) +{ + struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); + + /* Enable Audio packets */ + REG_UPDATE(DP_SEC_CNTL, DP_SEC_ASP_ENABLE, 1); + + /* Program the ATP and AIP next */ + REG_UPDATE_2(DP_SEC_CNTL, + DP_SEC_ATP_ENABLE, 1, + DP_SEC_AIP_ENABLE, 1); + + /* Program STREAM_ENABLE after all the other enables. */ + REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1); +} + +static void dce110_se_disable_dp_audio( + struct stream_encoder *enc) +{ + struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); + uint32_t value = REG_READ(DP_SEC_CNTL); + + /* Disable Audio packets */ + REG_UPDATE_5(DP_SEC_CNTL, + DP_SEC_ASP_ENABLE, 0, + DP_SEC_ATP_ENABLE, 0, + DP_SEC_AIP_ENABLE, 0, + DP_SEC_ACM_ENABLE, 0, + DP_SEC_STREAM_ENABLE, 0); + + /* This register shared with encoder info frame. Therefore we need to + keep master enabled if at least on of the fields is not 0 */ + if (value != 0) + REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1); + +} + +void dce110_se_audio_mute_control( + struct stream_encoder *enc, + bool mute) +{ + struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); + + REG_UPDATE(AFMT_AUDIO_PACKET_CONTROL, AFMT_AUDIO_SAMPLE_SEND, !mute); +} + +void dce110_se_dp_audio_setup( + struct stream_encoder *enc, + unsigned int az_inst, + struct audio_info *info) +{ + dce110_se_audio_setup(enc, az_inst, info); +} + +void dce110_se_dp_audio_enable( + struct stream_encoder *enc) +{ + dce110_se_enable_audio_clock(enc, true); + dce110_se_setup_dp_audio(enc); + dce110_se_enable_dp_audio(enc); +} + +void dce110_se_dp_audio_disable( + struct stream_encoder *enc) +{ + dce110_se_disable_dp_audio(enc); + dce110_se_enable_audio_clock(enc, false); +} + +void dce110_se_hdmi_audio_setup( + struct stream_encoder *enc, + unsigned int az_inst, + struct audio_info *info, + struct audio_crtc_info *audio_crtc_info) +{ + dce110_se_enable_audio_clock(enc, true); + dce110_se_setup_hdmi_audio(enc, audio_crtc_info); + dce110_se_audio_setup(enc, az_inst, info); +} + +void dce110_se_hdmi_audio_disable( + struct stream_encoder *enc) +{ + dce110_se_enable_audio_clock(enc, false); +} + +static const struct stream_encoder_funcs dce110_str_enc_funcs = { + .dp_set_stream_attribute = + dce110_stream_encoder_dp_set_stream_attribute, + .hdmi_set_stream_attribute = + dce110_stream_encoder_hdmi_set_stream_attribute, + .dvi_set_stream_attribute = + dce110_stream_encoder_dvi_set_stream_attribute, + .set_mst_bandwidth = + dce110_stream_encoder_set_mst_bandwidth, + .update_hdmi_info_packets = + dce110_stream_encoder_update_hdmi_info_packets, + .stop_hdmi_info_packets = + dce110_stream_encoder_stop_hdmi_info_packets, + .update_dp_info_packets = + dce110_stream_encoder_update_dp_info_packets, + .stop_dp_info_packets = + dce110_stream_encoder_stop_dp_info_packets, + .dp_blank = + dce110_stream_encoder_dp_blank, + .dp_unblank = + dce110_stream_encoder_dp_unblank, + + .audio_mute_control = dce110_se_audio_mute_control, + + .dp_audio_setup = dce110_se_dp_audio_setup, + .dp_audio_enable = dce110_se_dp_audio_enable, + .dp_audio_disable = dce110_se_dp_audio_disable, + + .hdmi_audio_setup = dce110_se_hdmi_audio_setup, + .hdmi_audio_disable = dce110_se_hdmi_audio_disable, +}; + +bool dce110_stream_encoder_construct( + struct dce110_stream_encoder *enc110, + struct dc_context *ctx, + struct dc_bios *bp, + enum engine_id eng_id, + const struct dce110_stream_enc_registers *regs, + const struct dce_stream_encoder_shift *se_shift, + const struct dce_stream_encoder_mask *se_mask) +{ + if (!enc110) + return false; + if (!bp) + return false; + + enc110->base.funcs = &dce110_str_enc_funcs; + enc110->base.ctx = ctx; + enc110->base.id = eng_id; + enc110->base.bp = bp; + enc110->regs = regs; + enc110->se_shift = se_shift; + enc110->se_mask = se_mask; + + return true; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h new file mode 100644 index 000000000000..458a37000956 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h @@ -0,0 +1,564 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_STREAM_ENCODER_DCE110_H__ +#define __DC_STREAM_ENCODER_DCE110_H__ + +#include "stream_encoder.h" + +#define DCE110STRENC_FROM_STRENC(stream_encoder)\ + container_of(stream_encoder, struct dce110_stream_encoder, base) + +#ifndef TMDS_CNTL__TMDS_PIXEL_ENCODING_MASK + #define TMDS_CNTL__TMDS_PIXEL_ENCODING_MASK 0x00000010L + #define TMDS_CNTL__TMDS_COLOR_FORMAT_MASK 0x00000300L + #define TMDS_CNTL__TMDS_PIXEL_ENCODING__SHIFT 0x00000004 + #define TMDS_CNTL__TMDS_COLOR_FORMAT__SHIFT 0x00000008 +#endif + + +#define SE_COMMON_REG_LIST_DCE_BASE(id) \ + SE_COMMON_REG_LIST_BASE(id),\ + SRI(AFMT_AVI_INFO0, DIG, id), \ + SRI(AFMT_AVI_INFO1, DIG, id), \ + SRI(AFMT_AVI_INFO2, DIG, id), \ + SRI(AFMT_AVI_INFO3, DIG, id) + +#define SE_COMMON_REG_LIST_BASE(id) \ + SRI(AFMT_GENERIC_0, DIG, id), \ + SRI(AFMT_GENERIC_1, DIG, id), \ + SRI(AFMT_GENERIC_2, DIG, id), \ + SRI(AFMT_GENERIC_3, DIG, id), \ + SRI(AFMT_GENERIC_4, DIG, id), \ + SRI(AFMT_GENERIC_5, DIG, id), \ + SRI(AFMT_GENERIC_6, DIG, id), \ + SRI(AFMT_GENERIC_7, DIG, id), \ + SRI(AFMT_GENERIC_HDR, DIG, id), \ + SRI(AFMT_INFOFRAME_CONTROL0, DIG, id), \ + SRI(AFMT_VBI_PACKET_CONTROL, DIG, id), \ + SRI(AFMT_AUDIO_PACKET_CONTROL, DIG, id), \ + SRI(AFMT_AUDIO_PACKET_CONTROL2, DIG, id), \ + SRI(AFMT_AUDIO_SRC_CONTROL, DIG, id), \ + SRI(AFMT_60958_0, DIG, id), \ + SRI(AFMT_60958_1, DIG, id), \ + SRI(AFMT_60958_2, DIG, id), \ + SRI(DIG_FE_CNTL, DIG, id), \ + SRI(HDMI_CONTROL, DIG, id), \ + SRI(HDMI_GC, DIG, id), \ + SRI(HDMI_GENERIC_PACKET_CONTROL0, DIG, id), \ + SRI(HDMI_GENERIC_PACKET_CONTROL1, DIG, id), \ + SRI(HDMI_INFOFRAME_CONTROL0, DIG, id), \ + SRI(HDMI_INFOFRAME_CONTROL1, DIG, id), \ + SRI(HDMI_VBI_PACKET_CONTROL, DIG, id), \ + SRI(HDMI_AUDIO_PACKET_CONTROL, DIG, id),\ + SRI(HDMI_ACR_PACKET_CONTROL, DIG, id),\ + SRI(HDMI_ACR_32_0, DIG, id),\ + SRI(HDMI_ACR_32_1, DIG, id),\ + SRI(HDMI_ACR_44_0, DIG, id),\ + SRI(HDMI_ACR_44_1, DIG, id),\ + SRI(HDMI_ACR_48_0, DIG, id),\ + SRI(HDMI_ACR_48_1, DIG, id),\ + SRI(TMDS_CNTL, DIG, id), \ + SRI(DP_MSE_RATE_CNTL, DP, id), \ + SRI(DP_MSE_RATE_UPDATE, DP, id), \ + SRI(DP_PIXEL_FORMAT, DP, id), \ + SRI(DP_SEC_CNTL, DP, id), \ + SRI(DP_STEER_FIFO, DP, id), \ + SRI(DP_VID_M, DP, id), \ + SRI(DP_VID_N, DP, id), \ + SRI(DP_VID_STREAM_CNTL, DP, id), \ + SRI(DP_VID_TIMING, DP, id), \ + SRI(DP_SEC_AUD_N, DP, id), \ + SRI(DP_SEC_TIMESTAMP, DP, id) + +#define SE_COMMON_REG_LIST(id)\ + SE_COMMON_REG_LIST_DCE_BASE(id), \ + SRI(AFMT_CNTL, DIG, id) + +#define SE_SF(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define SE_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh)\ + SE_SF(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_INDEX, mask_sh),\ + SE_SF(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC0_UPDATE, mask_sh),\ + SE_SF(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC2_UPDATE, mask_sh),\ + SE_SF(AFMT_GENERIC_HDR, AFMT_GENERIC_HB0, mask_sh),\ + SE_SF(AFMT_GENERIC_HDR, AFMT_GENERIC_HB1, mask_sh),\ + SE_SF(AFMT_GENERIC_HDR, AFMT_GENERIC_HB2, mask_sh),\ + SE_SF(AFMT_GENERIC_HDR, AFMT_GENERIC_HB3, mask_sh),\ + SE_SF(HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_CONT, mask_sh),\ + SE_SF(HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_SEND, mask_sh),\ + SE_SF(HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_LINE, mask_sh),\ + SE_SF(HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_CONT, mask_sh),\ + SE_SF(HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_SEND, mask_sh),\ + SE_SF(HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_LINE, mask_sh),\ + SE_SF(DP_PIXEL_FORMAT, DP_PIXEL_ENCODING, mask_sh),\ + SE_SF(DP_PIXEL_FORMAT, DP_COMPONENT_DEPTH, mask_sh),\ + SE_SF(DP_PIXEL_FORMAT, DP_DYN_RANGE, mask_sh),\ + SE_SF(DP_PIXEL_FORMAT, DP_YCBCR_RANGE, mask_sh),\ + SE_SF(HDMI_CONTROL, HDMI_PACKET_GEN_VERSION, mask_sh),\ + SE_SF(HDMI_CONTROL, HDMI_KEEPOUT_MODE, mask_sh),\ + SE_SF(HDMI_CONTROL, HDMI_DEEP_COLOR_ENABLE, mask_sh),\ + SE_SF(HDMI_CONTROL, HDMI_DEEP_COLOR_DEPTH, mask_sh),\ + SE_SF(HDMI_VBI_PACKET_CONTROL, HDMI_GC_CONT, mask_sh),\ + SE_SF(HDMI_VBI_PACKET_CONTROL, HDMI_GC_SEND, mask_sh),\ + SE_SF(HDMI_VBI_PACKET_CONTROL, HDMI_NULL_SEND, mask_sh),\ + SE_SF(HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_SEND, mask_sh),\ + SE_SF(AFMT_INFOFRAME_CONTROL0, AFMT_AUDIO_INFO_UPDATE, mask_sh),\ + SE_SF(HDMI_INFOFRAME_CONTROL1, HDMI_AUDIO_INFO_LINE, mask_sh),\ + SE_SF(HDMI_GC, HDMI_GC_AVMUTE, mask_sh),\ + SE_SF(DP_MSE_RATE_CNTL, DP_MSE_RATE_X, mask_sh),\ + SE_SF(DP_MSE_RATE_CNTL, DP_MSE_RATE_Y, mask_sh),\ + SE_SF(DP_MSE_RATE_UPDATE, DP_MSE_RATE_UPDATE_PENDING, mask_sh),\ + SE_SF(AFMT_AVI_INFO3, AFMT_AVI_INFO_VERSION, mask_sh),\ + SE_SF(HDMI_INFOFRAME_CONTROL0, HDMI_AVI_INFO_SEND, mask_sh),\ + SE_SF(HDMI_INFOFRAME_CONTROL0, HDMI_AVI_INFO_CONT, mask_sh),\ + SE_SF(HDMI_INFOFRAME_CONTROL1, HDMI_AVI_INFO_LINE, mask_sh),\ + SE_SF(DP_SEC_CNTL, DP_SEC_GSP0_ENABLE, mask_sh),\ + SE_SF(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, mask_sh),\ + SE_SF(DP_SEC_CNTL, DP_SEC_GSP1_ENABLE, mask_sh),\ + SE_SF(DP_SEC_CNTL, DP_SEC_GSP2_ENABLE, mask_sh),\ + SE_SF(DP_SEC_CNTL, DP_SEC_GSP3_ENABLE, mask_sh),\ + SE_SF(DP_SEC_CNTL, DP_SEC_AVI_ENABLE, mask_sh),\ + SE_SF(DP_SEC_CNTL, DP_SEC_MPG_ENABLE, mask_sh),\ + SE_SF(DP_VID_STREAM_CNTL, DP_VID_STREAM_DIS_DEFER, mask_sh),\ + SE_SF(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, mask_sh),\ + SE_SF(DP_VID_STREAM_CNTL, DP_VID_STREAM_STATUS, mask_sh),\ + SE_SF(DP_STEER_FIFO, DP_STEER_FIFO_RESET, mask_sh),\ + SE_SF(DP_VID_TIMING, DP_VID_M_N_GEN_EN, mask_sh),\ + SE_SF(DP_VID_N, DP_VID_N, mask_sh),\ + SE_SF(DP_VID_M, DP_VID_M, mask_sh),\ + SE_SF(DIG_FE_CNTL, DIG_START, mask_sh),\ + SE_SF(AFMT_AUDIO_SRC_CONTROL, AFMT_AUDIO_SRC_SELECT, mask_sh),\ + SE_SF(AFMT_AUDIO_PACKET_CONTROL2, AFMT_AUDIO_CHANNEL_ENABLE, mask_sh),\ + SE_SF(HDMI_AUDIO_PACKET_CONTROL, HDMI_AUDIO_PACKETS_PER_LINE, mask_sh),\ + SE_SF(HDMI_AUDIO_PACKET_CONTROL, HDMI_AUDIO_DELAY_EN, mask_sh),\ + SE_SF(AFMT_AUDIO_PACKET_CONTROL, AFMT_60958_CS_UPDATE, mask_sh),\ + SE_SF(AFMT_AUDIO_PACKET_CONTROL2, AFMT_AUDIO_LAYOUT_OVRD, mask_sh),\ + SE_SF(AFMT_AUDIO_PACKET_CONTROL2, AFMT_60958_OSF_OVRD, mask_sh),\ + SE_SF(HDMI_ACR_PACKET_CONTROL, HDMI_ACR_AUTO_SEND, mask_sh),\ + SE_SF(HDMI_ACR_PACKET_CONTROL, HDMI_ACR_SOURCE, mask_sh),\ + SE_SF(HDMI_ACR_PACKET_CONTROL, HDMI_ACR_AUDIO_PRIORITY, mask_sh),\ + SE_SF(HDMI_ACR_32_0, HDMI_ACR_CTS_32, mask_sh),\ + SE_SF(HDMI_ACR_32_1, HDMI_ACR_N_32, mask_sh),\ + SE_SF(HDMI_ACR_44_0, HDMI_ACR_CTS_44, mask_sh),\ + SE_SF(HDMI_ACR_44_1, HDMI_ACR_N_44, mask_sh),\ + SE_SF(HDMI_ACR_48_0, HDMI_ACR_CTS_48, mask_sh),\ + SE_SF(HDMI_ACR_48_1, HDMI_ACR_N_48, mask_sh),\ + SE_SF(AFMT_60958_0, AFMT_60958_CS_CHANNEL_NUMBER_L, mask_sh),\ + SE_SF(AFMT_60958_0, AFMT_60958_CS_CLOCK_ACCURACY, mask_sh),\ + SE_SF(AFMT_60958_1, AFMT_60958_CS_CHANNEL_NUMBER_R, mask_sh),\ + SE_SF(AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_2, mask_sh),\ + SE_SF(AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_3, mask_sh),\ + SE_SF(AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_4, mask_sh),\ + SE_SF(AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_5, mask_sh),\ + SE_SF(AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_6, mask_sh),\ + SE_SF(AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_7, mask_sh),\ + SE_SF(DP_SEC_AUD_N, DP_SEC_AUD_N, mask_sh),\ + SE_SF(DP_SEC_TIMESTAMP, DP_SEC_TIMESTAMP_MODE, mask_sh),\ + SE_SF(DP_SEC_CNTL, DP_SEC_ASP_ENABLE, mask_sh),\ + SE_SF(DP_SEC_CNTL, DP_SEC_ATP_ENABLE, mask_sh),\ + SE_SF(DP_SEC_CNTL, DP_SEC_AIP_ENABLE, mask_sh),\ + SE_SF(DP_SEC_CNTL, DP_SEC_ACM_ENABLE, mask_sh),\ + SE_SF(AFMT_AUDIO_PACKET_CONTROL, AFMT_AUDIO_SAMPLE_SEND, mask_sh) + +#define SE_COMMON_MASK_SH_LIST_DCE_COMMON(mask_sh)\ + SE_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh) + +#define SE_COMMON_MASK_SH_LIST_DCE80_100(mask_sh)\ + SE_COMMON_MASK_SH_LIST_DCE_COMMON(mask_sh),\ + SE_SF(TMDS_CNTL, TMDS_PIXEL_ENCODING, mask_sh),\ + SE_SF(TMDS_CNTL, TMDS_COLOR_FORMAT, mask_sh) + +#define SE_COMMON_MASK_SH_LIST_DCE110(mask_sh)\ + SE_COMMON_MASK_SH_LIST_DCE_COMMON(mask_sh),\ + SE_SF(AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, mask_sh),\ + SE_SF(HDMI_CONTROL, HDMI_CLOCK_CHANNEL_RATE, mask_sh),\ + SE_SF(HDMI_CONTROL, HDMI_DATA_SCRAMBLE_EN, mask_sh),\ + SE_SF(DIG_FE_CNTL, TMDS_PIXEL_ENCODING, mask_sh),\ + SE_SF(DIG_FE_CNTL, TMDS_COLOR_FORMAT, mask_sh) + +#define SE_COMMON_MASK_SH_LIST_DCE112(mask_sh)\ + SE_COMMON_MASK_SH_LIST_DCE_COMMON(mask_sh),\ + SE_SF(AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, mask_sh),\ + SE_SF(HDMI_CONTROL, HDMI_CLOCK_CHANNEL_RATE, mask_sh),\ + SE_SF(HDMI_CONTROL, HDMI_DATA_SCRAMBLE_EN, mask_sh),\ + SE_SF(DIG_FE_CNTL, TMDS_PIXEL_ENCODING, mask_sh),\ + SE_SF(DIG_FE_CNTL, TMDS_COLOR_FORMAT, mask_sh),\ + SE_SF(DP_VID_TIMING, DP_VID_M_DOUBLE_VALUE_EN, mask_sh) + +struct dce_stream_encoder_shift { + uint8_t AFMT_GENERIC_INDEX; + uint8_t AFMT_GENERIC0_UPDATE; + uint8_t AFMT_GENERIC2_UPDATE; + uint8_t AFMT_GENERIC_HB0; + uint8_t AFMT_GENERIC_HB1; + uint8_t AFMT_GENERIC_HB2; + uint8_t AFMT_GENERIC_HB3; + uint8_t AFMT_GENERIC_LOCK_STATUS; + uint8_t AFMT_GENERIC_CONFLICT; + uint8_t AFMT_GENERIC_CONFLICT_CLR; + uint8_t AFMT_GENERIC0_FRAME_UPDATE_PENDING; + uint8_t AFMT_GENERIC1_FRAME_UPDATE_PENDING; + uint8_t AFMT_GENERIC2_FRAME_UPDATE_PENDING; + uint8_t AFMT_GENERIC3_FRAME_UPDATE_PENDING; + uint8_t AFMT_GENERIC4_FRAME_UPDATE_PENDING; + uint8_t AFMT_GENERIC5_FRAME_UPDATE_PENDING; + uint8_t AFMT_GENERIC6_FRAME_UPDATE_PENDING; + uint8_t AFMT_GENERIC7_FRAME_UPDATE_PENDING; + uint8_t AFMT_GENERIC0_FRAME_UPDATE; + uint8_t AFMT_GENERIC1_FRAME_UPDATE; + uint8_t AFMT_GENERIC2_FRAME_UPDATE; + uint8_t AFMT_GENERIC3_FRAME_UPDATE; + uint8_t AFMT_GENERIC4_FRAME_UPDATE; + uint8_t AFMT_GENERIC5_FRAME_UPDATE; + uint8_t AFMT_GENERIC6_FRAME_UPDATE; + uint8_t AFMT_GENERIC7_FRAME_UPDATE; + uint8_t HDMI_GENERIC0_CONT; + uint8_t HDMI_GENERIC0_SEND; + uint8_t HDMI_GENERIC0_LINE; + uint8_t HDMI_GENERIC1_CONT; + uint8_t HDMI_GENERIC1_SEND; + uint8_t HDMI_GENERIC1_LINE; + uint8_t DP_PIXEL_ENCODING; + uint8_t DP_COMPONENT_DEPTH; + uint8_t DP_DYN_RANGE; + uint8_t DP_YCBCR_RANGE; + uint8_t HDMI_PACKET_GEN_VERSION; + uint8_t HDMI_KEEPOUT_MODE; + uint8_t HDMI_DEEP_COLOR_ENABLE; + uint8_t HDMI_CLOCK_CHANNEL_RATE; + uint8_t HDMI_DEEP_COLOR_DEPTH; + uint8_t HDMI_GC_CONT; + uint8_t HDMI_GC_SEND; + uint8_t HDMI_NULL_SEND; + uint8_t HDMI_DATA_SCRAMBLE_EN; + uint8_t HDMI_AUDIO_INFO_SEND; + uint8_t AFMT_AUDIO_INFO_UPDATE; + uint8_t HDMI_AUDIO_INFO_LINE; + uint8_t HDMI_GC_AVMUTE; + uint8_t DP_MSE_RATE_X; + uint8_t DP_MSE_RATE_Y; + uint8_t DP_MSE_RATE_UPDATE_PENDING; + uint8_t AFMT_AVI_INFO_VERSION; + uint8_t HDMI_AVI_INFO_SEND; + uint8_t HDMI_AVI_INFO_CONT; + uint8_t HDMI_AVI_INFO_LINE; + uint8_t DP_SEC_GSP0_ENABLE; + uint8_t DP_SEC_STREAM_ENABLE; + uint8_t DP_SEC_GSP1_ENABLE; + uint8_t DP_SEC_GSP2_ENABLE; + uint8_t DP_SEC_GSP3_ENABLE; + uint8_t DP_SEC_GSP4_ENABLE; + uint8_t DP_SEC_GSP5_ENABLE; + uint8_t DP_SEC_GSP6_ENABLE; + uint8_t DP_SEC_GSP7_ENABLE; + uint8_t DP_SEC_AVI_ENABLE; + uint8_t DP_SEC_MPG_ENABLE; + uint8_t DP_VID_STREAM_DIS_DEFER; + uint8_t DP_VID_STREAM_ENABLE; + uint8_t DP_VID_STREAM_STATUS; + uint8_t DP_STEER_FIFO_RESET; + uint8_t DP_VID_M_N_GEN_EN; + uint8_t DP_VID_N; + uint8_t DP_VID_M; + uint8_t DIG_START; + uint8_t AFMT_AUDIO_SRC_SELECT; + uint8_t AFMT_AUDIO_CHANNEL_ENABLE; + uint8_t HDMI_AUDIO_PACKETS_PER_LINE; + uint8_t HDMI_AUDIO_DELAY_EN; + uint8_t AFMT_60958_CS_UPDATE; + uint8_t AFMT_AUDIO_LAYOUT_OVRD; + uint8_t AFMT_60958_OSF_OVRD; + uint8_t HDMI_ACR_AUTO_SEND; + uint8_t HDMI_ACR_SOURCE; + uint8_t HDMI_ACR_AUDIO_PRIORITY; + uint8_t HDMI_ACR_CTS_32; + uint8_t HDMI_ACR_N_32; + uint8_t HDMI_ACR_CTS_44; + uint8_t HDMI_ACR_N_44; + uint8_t HDMI_ACR_CTS_48; + uint8_t HDMI_ACR_N_48; + uint8_t AFMT_60958_CS_CHANNEL_NUMBER_L; + uint8_t AFMT_60958_CS_CLOCK_ACCURACY; + uint8_t AFMT_60958_CS_CHANNEL_NUMBER_R; + uint8_t AFMT_60958_CS_CHANNEL_NUMBER_2; + uint8_t AFMT_60958_CS_CHANNEL_NUMBER_3; + uint8_t AFMT_60958_CS_CHANNEL_NUMBER_4; + uint8_t AFMT_60958_CS_CHANNEL_NUMBER_5; + uint8_t AFMT_60958_CS_CHANNEL_NUMBER_6; + uint8_t AFMT_60958_CS_CHANNEL_NUMBER_7; + uint8_t DP_SEC_AUD_N; + uint8_t DP_SEC_TIMESTAMP_MODE; + uint8_t DP_SEC_ASP_ENABLE; + uint8_t DP_SEC_ATP_ENABLE; + uint8_t DP_SEC_AIP_ENABLE; + uint8_t DP_SEC_ACM_ENABLE; + uint8_t AFMT_AUDIO_SAMPLE_SEND; + uint8_t AFMT_AUDIO_CLOCK_EN; + uint8_t TMDS_PIXEL_ENCODING; + uint8_t TMDS_COLOR_FORMAT; + uint8_t DP_DB_DISABLE; + uint8_t DP_MSA_MISC0; + uint8_t DP_MSA_HTOTAL; + uint8_t DP_MSA_VTOTAL; + uint8_t DP_MSA_HSTART; + uint8_t DP_MSA_VSTART; + uint8_t DP_MSA_HSYNCWIDTH; + uint8_t DP_MSA_HSYNCPOLARITY; + uint8_t DP_MSA_VSYNCWIDTH; + uint8_t DP_MSA_VSYNCPOLARITY; + uint8_t DP_MSA_HWIDTH; + uint8_t DP_MSA_VHEIGHT; + uint8_t HDMI_DB_DISABLE; + uint8_t DP_VID_N_MUL; + uint8_t DP_VID_M_DOUBLE_VALUE_EN; +}; + +struct dce_stream_encoder_mask { + uint32_t AFMT_GENERIC_INDEX; + uint32_t AFMT_GENERIC0_UPDATE; + uint32_t AFMT_GENERIC2_UPDATE; + uint32_t AFMT_GENERIC_HB0; + uint32_t AFMT_GENERIC_HB1; + uint32_t AFMT_GENERIC_HB2; + uint32_t AFMT_GENERIC_HB3; + uint32_t AFMT_GENERIC_LOCK_STATUS; + uint32_t AFMT_GENERIC_CONFLICT; + uint32_t AFMT_GENERIC_CONFLICT_CLR; + uint32_t AFMT_GENERIC0_FRAME_UPDATE_PENDING; + uint32_t AFMT_GENERIC1_FRAME_UPDATE_PENDING; + uint32_t AFMT_GENERIC2_FRAME_UPDATE_PENDING; + uint32_t AFMT_GENERIC3_FRAME_UPDATE_PENDING; + uint32_t AFMT_GENERIC4_FRAME_UPDATE_PENDING; + uint32_t AFMT_GENERIC5_FRAME_UPDATE_PENDING; + uint32_t AFMT_GENERIC6_FRAME_UPDATE_PENDING; + uint32_t AFMT_GENERIC7_FRAME_UPDATE_PENDING; + uint32_t AFMT_GENERIC0_FRAME_UPDATE; + uint32_t AFMT_GENERIC1_FRAME_UPDATE; + uint32_t AFMT_GENERIC2_FRAME_UPDATE; + uint32_t AFMT_GENERIC3_FRAME_UPDATE; + uint32_t AFMT_GENERIC4_FRAME_UPDATE; + uint32_t AFMT_GENERIC5_FRAME_UPDATE; + uint32_t AFMT_GENERIC6_FRAME_UPDATE; + uint32_t AFMT_GENERIC7_FRAME_UPDATE; + uint32_t HDMI_GENERIC0_CONT; + uint32_t HDMI_GENERIC0_SEND; + uint32_t HDMI_GENERIC0_LINE; + uint32_t HDMI_GENERIC1_CONT; + uint32_t HDMI_GENERIC1_SEND; + uint32_t HDMI_GENERIC1_LINE; + uint32_t DP_PIXEL_ENCODING; + uint32_t DP_COMPONENT_DEPTH; + uint32_t DP_DYN_RANGE; + uint32_t DP_YCBCR_RANGE; + uint32_t HDMI_PACKET_GEN_VERSION; + uint32_t HDMI_KEEPOUT_MODE; + uint32_t HDMI_DEEP_COLOR_ENABLE; + uint32_t HDMI_CLOCK_CHANNEL_RATE; + uint32_t HDMI_DEEP_COLOR_DEPTH; + uint32_t HDMI_GC_CONT; + uint32_t HDMI_GC_SEND; + uint32_t HDMI_NULL_SEND; + uint32_t HDMI_DATA_SCRAMBLE_EN; + uint32_t HDMI_AUDIO_INFO_SEND; + uint32_t AFMT_AUDIO_INFO_UPDATE; + uint32_t HDMI_AUDIO_INFO_LINE; + uint32_t HDMI_GC_AVMUTE; + uint32_t DP_MSE_RATE_X; + uint32_t DP_MSE_RATE_Y; + uint32_t DP_MSE_RATE_UPDATE_PENDING; + uint32_t AFMT_AVI_INFO_VERSION; + uint32_t HDMI_AVI_INFO_SEND; + uint32_t HDMI_AVI_INFO_CONT; + uint32_t HDMI_AVI_INFO_LINE; + uint32_t DP_SEC_GSP0_ENABLE; + uint32_t DP_SEC_STREAM_ENABLE; + uint32_t DP_SEC_GSP1_ENABLE; + uint32_t DP_SEC_GSP2_ENABLE; + uint32_t DP_SEC_GSP3_ENABLE; + uint32_t DP_SEC_GSP4_ENABLE; + uint32_t DP_SEC_GSP5_ENABLE; + uint32_t DP_SEC_GSP6_ENABLE; + uint32_t DP_SEC_GSP7_ENABLE; + uint32_t DP_SEC_AVI_ENABLE; + uint32_t DP_SEC_MPG_ENABLE; + uint32_t DP_VID_STREAM_DIS_DEFER; + uint32_t DP_VID_STREAM_ENABLE; + uint32_t DP_VID_STREAM_STATUS; + uint32_t DP_STEER_FIFO_RESET; + uint32_t DP_VID_M_N_GEN_EN; + uint32_t DP_VID_N; + uint32_t DP_VID_M; + uint32_t DIG_START; + uint32_t AFMT_AUDIO_SRC_SELECT; + uint32_t AFMT_AUDIO_CHANNEL_ENABLE; + uint32_t HDMI_AUDIO_PACKETS_PER_LINE; + uint32_t HDMI_AUDIO_DELAY_EN; + uint32_t AFMT_60958_CS_UPDATE; + uint32_t AFMT_AUDIO_LAYOUT_OVRD; + uint32_t AFMT_60958_OSF_OVRD; + uint32_t HDMI_ACR_AUTO_SEND; + uint32_t HDMI_ACR_SOURCE; + uint32_t HDMI_ACR_AUDIO_PRIORITY; + uint32_t HDMI_ACR_CTS_32; + uint32_t HDMI_ACR_N_32; + uint32_t HDMI_ACR_CTS_44; + uint32_t HDMI_ACR_N_44; + uint32_t HDMI_ACR_CTS_48; + uint32_t HDMI_ACR_N_48; + uint32_t AFMT_60958_CS_CHANNEL_NUMBER_L; + uint32_t AFMT_60958_CS_CLOCK_ACCURACY; + uint32_t AFMT_60958_CS_CHANNEL_NUMBER_R; + uint32_t AFMT_60958_CS_CHANNEL_NUMBER_2; + uint32_t AFMT_60958_CS_CHANNEL_NUMBER_3; + uint32_t AFMT_60958_CS_CHANNEL_NUMBER_4; + uint32_t AFMT_60958_CS_CHANNEL_NUMBER_5; + uint32_t AFMT_60958_CS_CHANNEL_NUMBER_6; + uint32_t AFMT_60958_CS_CHANNEL_NUMBER_7; + uint32_t DP_SEC_AUD_N; + uint32_t DP_SEC_TIMESTAMP_MODE; + uint32_t DP_SEC_ASP_ENABLE; + uint32_t DP_SEC_ATP_ENABLE; + uint32_t DP_SEC_AIP_ENABLE; + uint32_t DP_SEC_ACM_ENABLE; + uint32_t AFMT_AUDIO_SAMPLE_SEND; + uint32_t AFMT_AUDIO_CLOCK_EN; + uint32_t TMDS_PIXEL_ENCODING; + uint32_t TMDS_COLOR_FORMAT; + uint32_t DP_DB_DISABLE; + uint32_t DP_MSA_MISC0; + uint32_t DP_MSA_HTOTAL; + uint32_t DP_MSA_VTOTAL; + uint32_t DP_MSA_HSTART; + uint32_t DP_MSA_VSTART; + uint32_t DP_MSA_HSYNCWIDTH; + uint32_t DP_MSA_HSYNCPOLARITY; + uint32_t DP_MSA_VSYNCWIDTH; + uint32_t DP_MSA_VSYNCPOLARITY; + uint32_t DP_MSA_HWIDTH; + uint32_t DP_MSA_VHEIGHT; + uint32_t HDMI_DB_DISABLE; + uint32_t DP_VID_N_MUL; + uint32_t DP_VID_M_DOUBLE_VALUE_EN; +}; + +struct dce110_stream_enc_registers { + uint32_t AFMT_CNTL; + uint32_t AFMT_AVI_INFO0; + uint32_t AFMT_AVI_INFO1; + uint32_t AFMT_AVI_INFO2; + uint32_t AFMT_AVI_INFO3; + uint32_t AFMT_GENERIC_0; + uint32_t AFMT_GENERIC_1; + uint32_t AFMT_GENERIC_2; + uint32_t AFMT_GENERIC_3; + uint32_t AFMT_GENERIC_4; + uint32_t AFMT_GENERIC_5; + uint32_t AFMT_GENERIC_6; + uint32_t AFMT_GENERIC_7; + uint32_t AFMT_GENERIC_HDR; + uint32_t AFMT_INFOFRAME_CONTROL0; + uint32_t AFMT_VBI_PACKET_CONTROL; + uint32_t AFMT_VBI_PACKET_CONTROL1; + uint32_t AFMT_AUDIO_PACKET_CONTROL; + uint32_t AFMT_AUDIO_PACKET_CONTROL2; + uint32_t AFMT_AUDIO_SRC_CONTROL; + uint32_t AFMT_60958_0; + uint32_t AFMT_60958_1; + uint32_t AFMT_60958_2; + uint32_t DIG_FE_CNTL; + uint32_t DP_MSE_RATE_CNTL; + uint32_t DP_MSE_RATE_UPDATE; + uint32_t DP_PIXEL_FORMAT; + uint32_t DP_SEC_CNTL; + uint32_t DP_STEER_FIFO; + uint32_t DP_VID_M; + uint32_t DP_VID_N; + uint32_t DP_VID_STREAM_CNTL; + uint32_t DP_VID_TIMING; + uint32_t DP_SEC_AUD_N; + uint32_t DP_SEC_TIMESTAMP; + uint32_t HDMI_CONTROL; + uint32_t HDMI_GC; + uint32_t HDMI_GENERIC_PACKET_CONTROL0; + uint32_t HDMI_GENERIC_PACKET_CONTROL1; + uint32_t HDMI_GENERIC_PACKET_CONTROL2; + uint32_t HDMI_GENERIC_PACKET_CONTROL3; + uint32_t HDMI_INFOFRAME_CONTROL0; + uint32_t HDMI_INFOFRAME_CONTROL1; + uint32_t HDMI_VBI_PACKET_CONTROL; + uint32_t HDMI_AUDIO_PACKET_CONTROL; + uint32_t HDMI_ACR_PACKET_CONTROL; + uint32_t HDMI_ACR_32_0; + uint32_t HDMI_ACR_32_1; + uint32_t HDMI_ACR_44_0; + uint32_t HDMI_ACR_44_1; + uint32_t HDMI_ACR_48_0; + uint32_t HDMI_ACR_48_1; + uint32_t TMDS_CNTL; +}; + +struct dce110_stream_encoder { + struct stream_encoder base; + const struct dce110_stream_enc_registers *regs; + const struct dce_stream_encoder_shift *se_shift; + const struct dce_stream_encoder_mask *se_mask; +}; + +bool dce110_stream_encoder_construct( + struct dce110_stream_encoder *enc110, + struct dc_context *ctx, + struct dc_bios *bp, + enum engine_id eng_id, + const struct dce110_stream_enc_registers *regs, + const struct dce_stream_encoder_shift *se_shift, + const struct dce_stream_encoder_mask *se_mask); + + +void dce110_se_audio_mute_control( + struct stream_encoder *enc, bool mute); + +void dce110_se_dp_audio_setup( + struct stream_encoder *enc, + unsigned int az_inst, + struct audio_info *info); + +void dce110_se_dp_audio_enable( + struct stream_encoder *enc); + +void dce110_se_dp_audio_disable( + struct stream_encoder *enc); + +void dce110_se_hdmi_audio_setup( + struct stream_encoder *enc, + unsigned int az_inst, + struct audio_info *info, + struct audio_crtc_info *audio_crtc_info); + +void dce110_se_hdmi_audio_disable( + struct stream_encoder *enc); + +#endif /* __DC_STREAM_ENCODER_DCE110_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c new file mode 100644 index 000000000000..f47b6617f662 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c @@ -0,0 +1,1002 @@ +/* + * Copyright 2012-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dce_transform.h" +#include "reg_helper.h" +#include "opp.h" +#include "basics/conversion.h" + +#define REG(reg) \ + (xfm_dce->regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + xfm_dce->xfm_shift->field_name, xfm_dce->xfm_mask->field_name + +#define CTX \ + xfm_dce->base.ctx + +#define IDENTITY_RATIO(ratio) (dal_fixed31_32_u2d19(ratio) == (1 << 19)) +#define GAMUT_MATRIX_SIZE 12 +#define SCL_PHASES 16 + +enum dcp_out_trunc_round_mode { + DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE, + DCP_OUT_TRUNC_ROUND_MODE_ROUND +}; + +enum dcp_out_trunc_round_depth { + DCP_OUT_TRUNC_ROUND_DEPTH_14BIT, + DCP_OUT_TRUNC_ROUND_DEPTH_13BIT, + DCP_OUT_TRUNC_ROUND_DEPTH_12BIT, + DCP_OUT_TRUNC_ROUND_DEPTH_11BIT, + DCP_OUT_TRUNC_ROUND_DEPTH_10BIT, + DCP_OUT_TRUNC_ROUND_DEPTH_9BIT, + DCP_OUT_TRUNC_ROUND_DEPTH_8BIT +}; + +/* defines the various methods of bit reduction available for use */ +enum dcp_bit_depth_reduction_mode { + DCP_BIT_DEPTH_REDUCTION_MODE_DITHER, + DCP_BIT_DEPTH_REDUCTION_MODE_ROUND, + DCP_BIT_DEPTH_REDUCTION_MODE_TRUNCATE, + DCP_BIT_DEPTH_REDUCTION_MODE_DISABLED, + DCP_BIT_DEPTH_REDUCTION_MODE_INVALID +}; + +enum dcp_spatial_dither_mode { + DCP_SPATIAL_DITHER_MODE_AAAA, + DCP_SPATIAL_DITHER_MODE_A_AA_A, + DCP_SPATIAL_DITHER_MODE_AABBAABB, + DCP_SPATIAL_DITHER_MODE_AABBCCAABBCC, + DCP_SPATIAL_DITHER_MODE_INVALID +}; + +enum dcp_spatial_dither_depth { + DCP_SPATIAL_DITHER_DEPTH_30BPP, + DCP_SPATIAL_DITHER_DEPTH_24BPP +}; + +static bool setup_scaling_configuration( + struct dce_transform *xfm_dce, + const struct scaler_data *data) +{ + struct dc_context *ctx = xfm_dce->base.ctx; + + if (data->taps.h_taps + data->taps.v_taps <= 2) { + /* Set bypass */ + REG_UPDATE_2(SCL_MODE, SCL_MODE, 0, SCL_PSCL_EN, 0); + return false; + } + + REG_SET_2(SCL_TAP_CONTROL, 0, + SCL_H_NUM_OF_TAPS, data->taps.h_taps - 1, + SCL_V_NUM_OF_TAPS, data->taps.v_taps - 1); + + if (data->format <= PIXEL_FORMAT_GRPH_END) + REG_UPDATE_2(SCL_MODE, SCL_MODE, 1, SCL_PSCL_EN, 1); + else + REG_UPDATE_2(SCL_MODE, SCL_MODE, 2, SCL_PSCL_EN, 1); + + /* 1 - Replace out of bound pixels with edge */ + REG_SET(SCL_CONTROL, 0, SCL_BOUNDARY_MODE, 1); + + return true; +} + +static void program_overscan( + struct dce_transform *xfm_dce, + const struct scaler_data *data) +{ + int overscan_right = data->h_active + - data->recout.x - data->recout.width; + int overscan_bottom = data->v_active + - data->recout.y - data->recout.height; + + if (overscan_right < 0) { + BREAK_TO_DEBUGGER(); + overscan_right = 0; + } + if (overscan_bottom < 0) { + BREAK_TO_DEBUGGER(); + overscan_bottom = 0; + } + + REG_SET_2(EXT_OVERSCAN_LEFT_RIGHT, 0, + EXT_OVERSCAN_LEFT, data->recout.x, + EXT_OVERSCAN_RIGHT, overscan_right); + REG_SET_2(EXT_OVERSCAN_TOP_BOTTOM, 0, + EXT_OVERSCAN_TOP, data->recout.y, + EXT_OVERSCAN_BOTTOM, overscan_bottom); +} + +static void program_multi_taps_filter( + struct dce_transform *xfm_dce, + int taps, + const uint16_t *coeffs, + enum ram_filter_type filter_type) +{ + int phase, pair; + int array_idx = 0; + int taps_pairs = (taps + 1) / 2; + int phases_to_program = SCL_PHASES / 2 + 1; + + uint32_t power_ctl = 0; + + if (!coeffs) + return; + + /*We need to disable power gating on coeff memory to do programming*/ + if (REG(DCFE_MEM_PWR_CTRL)) { + power_ctl = REG_READ(DCFE_MEM_PWR_CTRL); + REG_SET(DCFE_MEM_PWR_CTRL, power_ctl, SCL_COEFF_MEM_PWR_DIS, 1); + + REG_WAIT(DCFE_MEM_PWR_STATUS, SCL_COEFF_MEM_PWR_STATE, 0, 1, 10); + } + for (phase = 0; phase < phases_to_program; phase++) { + /*we always program N/2 + 1 phases, total phases N, but N/2-1 are just mirror + phase 0 is unique and phase N/2 is unique if N is even*/ + for (pair = 0; pair < taps_pairs; pair++) { + uint16_t odd_coeff = 0; + uint16_t even_coeff = coeffs[array_idx]; + + REG_SET_3(SCL_COEF_RAM_SELECT, 0, + SCL_C_RAM_FILTER_TYPE, filter_type, + SCL_C_RAM_PHASE, phase, + SCL_C_RAM_TAP_PAIR_IDX, pair); + + if (taps % 2 && pair == taps_pairs - 1) + array_idx++; + else { + odd_coeff = coeffs[array_idx + 1]; + array_idx += 2; + } + + REG_SET_4(SCL_COEF_RAM_TAP_DATA, 0, + SCL_C_RAM_EVEN_TAP_COEF_EN, 1, + SCL_C_RAM_EVEN_TAP_COEF, even_coeff, + SCL_C_RAM_ODD_TAP_COEF_EN, 1, + SCL_C_RAM_ODD_TAP_COEF, odd_coeff); + } + } + + /*We need to restore power gating on coeff memory to initial state*/ + if (REG(DCFE_MEM_PWR_CTRL)) + REG_WRITE(DCFE_MEM_PWR_CTRL, power_ctl); +} + +static void program_viewport( + struct dce_transform *xfm_dce, + const struct rect *view_port) +{ + REG_SET_2(VIEWPORT_START, 0, + VIEWPORT_X_START, view_port->x, + VIEWPORT_Y_START, view_port->y); + + REG_SET_2(VIEWPORT_SIZE, 0, + VIEWPORT_HEIGHT, view_port->height, + VIEWPORT_WIDTH, view_port->width); + + /* TODO: add stereo support */ +} + +static void calculate_inits( + struct dce_transform *xfm_dce, + const struct scaler_data *data, + struct scl_ratios_inits *inits) +{ + struct fixed31_32 h_init; + struct fixed31_32 v_init; + + inits->h_int_scale_ratio = + dal_fixed31_32_u2d19(data->ratios.horz) << 5; + inits->v_int_scale_ratio = + dal_fixed31_32_u2d19(data->ratios.vert) << 5; + + h_init = + dal_fixed31_32_div_int( + dal_fixed31_32_add( + data->ratios.horz, + dal_fixed31_32_from_int(data->taps.h_taps + 1)), + 2); + inits->h_init.integer = dal_fixed31_32_floor(h_init); + inits->h_init.fraction = dal_fixed31_32_u0d19(h_init) << 5; + + v_init = + dal_fixed31_32_div_int( + dal_fixed31_32_add( + data->ratios.vert, + dal_fixed31_32_from_int(data->taps.v_taps + 1)), + 2); + inits->v_init.integer = dal_fixed31_32_floor(v_init); + inits->v_init.fraction = dal_fixed31_32_u0d19(v_init) << 5; +} + +static void program_scl_ratios_inits( + struct dce_transform *xfm_dce, + struct scl_ratios_inits *inits) +{ + + REG_SET(SCL_HORZ_FILTER_SCALE_RATIO, 0, + SCL_H_SCALE_RATIO, inits->h_int_scale_ratio); + + REG_SET(SCL_VERT_FILTER_SCALE_RATIO, 0, + SCL_V_SCALE_RATIO, inits->v_int_scale_ratio); + + REG_SET_2(SCL_HORZ_FILTER_INIT, 0, + SCL_H_INIT_INT, inits->h_init.integer, + SCL_H_INIT_FRAC, inits->h_init.fraction); + + REG_SET_2(SCL_VERT_FILTER_INIT, 0, + SCL_V_INIT_INT, inits->v_init.integer, + SCL_V_INIT_FRAC, inits->v_init.fraction); + + REG_WRITE(SCL_AUTOMATIC_MODE_CONTROL, 0); +} + +static const uint16_t *get_filter_coeffs_16p(int taps, struct fixed31_32 ratio) +{ + if (taps == 4) + return get_filter_4tap_16p(ratio); + else if (taps == 3) + return get_filter_3tap_16p(ratio); + else if (taps == 2) + return filter_2tap_16p; + else if (taps == 1) + return NULL; + else { + /* should never happen, bug */ + BREAK_TO_DEBUGGER(); + return NULL; + } +} + +static void dce_transform_set_scaler( + struct transform *xfm, + const struct scaler_data *data) +{ + struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); + bool is_scaling_required; + bool filter_updated = false; + const uint16_t *coeffs_v, *coeffs_h; + + /*Use all three pieces of memory always*/ + REG_SET_2(LB_MEMORY_CTRL, 0, + LB_MEMORY_CONFIG, 0, + LB_MEMORY_SIZE, xfm_dce->lb_memory_size); + + /* 1. Program overscan */ + program_overscan(xfm_dce, data); + + /* 2. Program taps and configuration */ + is_scaling_required = setup_scaling_configuration(xfm_dce, data); + + if (is_scaling_required) { + /* 3. Calculate and program ratio, filter initialization */ + struct scl_ratios_inits inits = { 0 }; + + calculate_inits(xfm_dce, data, &inits); + + program_scl_ratios_inits(xfm_dce, &inits); + + coeffs_v = get_filter_coeffs_16p(data->taps.v_taps, data->ratios.vert); + coeffs_h = get_filter_coeffs_16p(data->taps.h_taps, data->ratios.horz); + + if (coeffs_v != xfm_dce->filter_v || coeffs_h != xfm_dce->filter_h) { + /* 4. Program vertical filters */ + if (xfm_dce->filter_v == NULL) + REG_SET(SCL_VERT_FILTER_CONTROL, 0, + SCL_V_2TAP_HARDCODE_COEF_EN, 0); + program_multi_taps_filter( + xfm_dce, + data->taps.v_taps, + coeffs_v, + FILTER_TYPE_RGB_Y_VERTICAL); + program_multi_taps_filter( + xfm_dce, + data->taps.v_taps, + coeffs_v, + FILTER_TYPE_ALPHA_VERTICAL); + + /* 5. Program horizontal filters */ + if (xfm_dce->filter_h == NULL) + REG_SET(SCL_HORZ_FILTER_CONTROL, 0, + SCL_H_2TAP_HARDCODE_COEF_EN, 0); + program_multi_taps_filter( + xfm_dce, + data->taps.h_taps, + coeffs_h, + FILTER_TYPE_RGB_Y_HORIZONTAL); + program_multi_taps_filter( + xfm_dce, + data->taps.h_taps, + coeffs_h, + FILTER_TYPE_ALPHA_HORIZONTAL); + + xfm_dce->filter_v = coeffs_v; + xfm_dce->filter_h = coeffs_h; + filter_updated = true; + } + } + + /* 6. Program the viewport */ + program_viewport(xfm_dce, &data->viewport); + + /* 7. Set bit to flip to new coefficient memory */ + if (filter_updated) + REG_UPDATE(SCL_UPDATE, SCL_COEF_UPDATE_COMPLETE, 1); + + REG_UPDATE(LB_DATA_FORMAT, ALPHA_EN, data->lb_params.alpha_en); +} + +/***************************************************************************** + * set_clamp + * + * @param depth : bit depth to set the clamp to (should match denorm) + * + * @brief + * Programs clamp according to panel bit depth. + * + *******************************************************************************/ +static void set_clamp( + struct dce_transform *xfm_dce, + enum dc_color_depth depth) +{ + int clamp_max = 0; + + /* At the clamp block the data will be MSB aligned, so we set the max + * clamp accordingly. + * For example, the max value for 6 bits MSB aligned (14 bit bus) would + * be "11 1111 0000 0000" in binary, so 0x3F00. + */ + switch (depth) { + case COLOR_DEPTH_666: + /* 6bit MSB aligned on 14 bit bus '11 1111 0000 0000' */ + clamp_max = 0x3F00; + break; + case COLOR_DEPTH_888: + /* 8bit MSB aligned on 14 bit bus '11 1111 1100 0000' */ + clamp_max = 0x3FC0; + break; + case COLOR_DEPTH_101010: + /* 10bit MSB aligned on 14 bit bus '11 1111 1111 1100' */ + clamp_max = 0x3FFC; + break; + case COLOR_DEPTH_121212: + /* 12bit MSB aligned on 14 bit bus '11 1111 1111 1111' */ + clamp_max = 0x3FFF; + break; + default: + clamp_max = 0x3FC0; + BREAK_TO_DEBUGGER(); /* Invalid clamp bit depth */ + } + REG_SET_2(OUT_CLAMP_CONTROL_B_CB, 0, + OUT_CLAMP_MIN_B_CB, 0, + OUT_CLAMP_MAX_B_CB, clamp_max); + + REG_SET_2(OUT_CLAMP_CONTROL_G_Y, 0, + OUT_CLAMP_MIN_G_Y, 0, + OUT_CLAMP_MAX_G_Y, clamp_max); + + REG_SET_2(OUT_CLAMP_CONTROL_R_CR, 0, + OUT_CLAMP_MIN_R_CR, 0, + OUT_CLAMP_MAX_R_CR, clamp_max); +} + +/******************************************************************************* + * set_round + * + * @brief + * Programs Round/Truncate + * + * @param [in] mode :round or truncate + * @param [in] depth :bit depth to round/truncate to + OUT_ROUND_TRUNC_MODE 3:0 0xA Output data round or truncate mode + POSSIBLE VALUES: + 00 - truncate to u0.12 + 01 - truncate to u0.11 + 02 - truncate to u0.10 + 03 - truncate to u0.9 + 04 - truncate to u0.8 + 05 - reserved + 06 - truncate to u0.14 + 07 - truncate to u0.13 set_reg_field_value( + value, + clamp_max, + OUT_CLAMP_CONTROL_R_CR, + OUT_CLAMP_MAX_R_CR); + 08 - round to u0.12 + 09 - round to u0.11 + 10 - round to u0.10 + 11 - round to u0.9 + 12 - round to u0.8 + 13 - reserved + 14 - round to u0.14 + 15 - round to u0.13 + + ******************************************************************************/ +static void set_round( + struct dce_transform *xfm_dce, + enum dcp_out_trunc_round_mode mode, + enum dcp_out_trunc_round_depth depth) +{ + int depth_bits = 0; + int mode_bit = 0; + + /* set up bit depth */ + switch (depth) { + case DCP_OUT_TRUNC_ROUND_DEPTH_14BIT: + depth_bits = 6; + break; + case DCP_OUT_TRUNC_ROUND_DEPTH_13BIT: + depth_bits = 7; + break; + case DCP_OUT_TRUNC_ROUND_DEPTH_12BIT: + depth_bits = 0; + break; + case DCP_OUT_TRUNC_ROUND_DEPTH_11BIT: + depth_bits = 1; + break; + case DCP_OUT_TRUNC_ROUND_DEPTH_10BIT: + depth_bits = 2; + break; + case DCP_OUT_TRUNC_ROUND_DEPTH_9BIT: + depth_bits = 3; + break; + case DCP_OUT_TRUNC_ROUND_DEPTH_8BIT: + depth_bits = 4; + break; + default: + depth_bits = 4; + BREAK_TO_DEBUGGER(); /* Invalid dcp_out_trunc_round_depth */ + } + + /* set up round or truncate */ + switch (mode) { + case DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE: + mode_bit = 0; + break; + case DCP_OUT_TRUNC_ROUND_MODE_ROUND: + mode_bit = 1; + break; + default: + BREAK_TO_DEBUGGER(); /* Invalid dcp_out_trunc_round_mode */ + } + + depth_bits |= mode_bit << 3; + + REG_SET(OUT_ROUND_CONTROL, 0, OUT_ROUND_TRUNC_MODE, depth_bits); +} + +/***************************************************************************** + * set_dither + * + * @brief + * Programs Dither + * + * @param [in] dither_enable : enable dither + * @param [in] dither_mode : dither mode to set + * @param [in] dither_depth : bit depth to dither to + * @param [in] frame_random_enable : enable frame random + * @param [in] rgb_random_enable : enable rgb random + * @param [in] highpass_random_enable : enable highpass random + * + ******************************************************************************/ + +static void set_dither( + struct dce_transform *xfm_dce, + bool dither_enable, + enum dcp_spatial_dither_mode dither_mode, + enum dcp_spatial_dither_depth dither_depth, + bool frame_random_enable, + bool rgb_random_enable, + bool highpass_random_enable) +{ + int dither_depth_bits = 0; + int dither_mode_bits = 0; + + switch (dither_mode) { + case DCP_SPATIAL_DITHER_MODE_AAAA: + dither_mode_bits = 0; + break; + case DCP_SPATIAL_DITHER_MODE_A_AA_A: + dither_mode_bits = 1; + break; + case DCP_SPATIAL_DITHER_MODE_AABBAABB: + dither_mode_bits = 2; + break; + case DCP_SPATIAL_DITHER_MODE_AABBCCAABBCC: + dither_mode_bits = 3; + break; + default: + /* Invalid dcp_spatial_dither_mode */ + BREAK_TO_DEBUGGER(); + } + + switch (dither_depth) { + case DCP_SPATIAL_DITHER_DEPTH_30BPP: + dither_depth_bits = 0; + break; + case DCP_SPATIAL_DITHER_DEPTH_24BPP: + dither_depth_bits = 1; + break; + default: + /* Invalid dcp_spatial_dither_depth */ + BREAK_TO_DEBUGGER(); + } + + /* write the register */ + REG_SET_6(DCP_SPATIAL_DITHER_CNTL, 0, + DCP_SPATIAL_DITHER_EN, dither_enable, + DCP_SPATIAL_DITHER_MODE, dither_mode_bits, + DCP_SPATIAL_DITHER_DEPTH, dither_depth_bits, + DCP_FRAME_RANDOM_ENABLE, frame_random_enable, + DCP_RGB_RANDOM_ENABLE, rgb_random_enable, + DCP_HIGHPASS_RANDOM_ENABLE, highpass_random_enable); +} + +/***************************************************************************** + * dce_transform_bit_depth_reduction_program + * + * @brief + * Programs the DCP bit depth reduction registers (Clamp, Round/Truncate, + * Dither) for dce + * + * @param depth : bit depth to set the clamp to (should match denorm) + * + ******************************************************************************/ +static void program_bit_depth_reduction( + struct dce_transform *xfm_dce, + enum dc_color_depth depth, + const struct bit_depth_reduction_params *bit_depth_params) +{ + enum dcp_bit_depth_reduction_mode depth_reduction_mode; + enum dcp_spatial_dither_mode spatial_dither_mode; + bool frame_random_enable; + bool rgb_random_enable; + bool highpass_random_enable; + + ASSERT(depth < COLOR_DEPTH_121212); /* Invalid clamp bit depth */ + + if (bit_depth_params->flags.SPATIAL_DITHER_ENABLED) { + depth_reduction_mode = DCP_BIT_DEPTH_REDUCTION_MODE_DITHER; + frame_random_enable = true; + rgb_random_enable = true; + highpass_random_enable = true; + + } else { + depth_reduction_mode = DCP_BIT_DEPTH_REDUCTION_MODE_DISABLED; + frame_random_enable = false; + rgb_random_enable = false; + highpass_random_enable = false; + } + + spatial_dither_mode = DCP_SPATIAL_DITHER_MODE_A_AA_A; + + set_clamp(xfm_dce, depth); + + switch (depth_reduction_mode) { + case DCP_BIT_DEPTH_REDUCTION_MODE_DITHER: + /* Spatial Dither: Set round/truncate to bypass (12bit), + * enable Dither (30bpp) */ + set_round(xfm_dce, + DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE, + DCP_OUT_TRUNC_ROUND_DEPTH_12BIT); + + set_dither(xfm_dce, true, spatial_dither_mode, + DCP_SPATIAL_DITHER_DEPTH_30BPP, frame_random_enable, + rgb_random_enable, highpass_random_enable); + break; + case DCP_BIT_DEPTH_REDUCTION_MODE_ROUND: + /* Round: Enable round (10bit), disable Dither */ + set_round(xfm_dce, + DCP_OUT_TRUNC_ROUND_MODE_ROUND, + DCP_OUT_TRUNC_ROUND_DEPTH_10BIT); + + set_dither(xfm_dce, false, spatial_dither_mode, + DCP_SPATIAL_DITHER_DEPTH_30BPP, frame_random_enable, + rgb_random_enable, highpass_random_enable); + break; + case DCP_BIT_DEPTH_REDUCTION_MODE_TRUNCATE: /* Truncate */ + /* Truncate: Enable truncate (10bit), disable Dither */ + set_round(xfm_dce, + DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE, + DCP_OUT_TRUNC_ROUND_DEPTH_10BIT); + + set_dither(xfm_dce, false, spatial_dither_mode, + DCP_SPATIAL_DITHER_DEPTH_30BPP, frame_random_enable, + rgb_random_enable, highpass_random_enable); + break; + + case DCP_BIT_DEPTH_REDUCTION_MODE_DISABLED: /* Disabled */ + /* Truncate: Set round/truncate to bypass (12bit), + * disable Dither */ + set_round(xfm_dce, + DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE, + DCP_OUT_TRUNC_ROUND_DEPTH_12BIT); + + set_dither(xfm_dce, false, spatial_dither_mode, + DCP_SPATIAL_DITHER_DEPTH_30BPP, frame_random_enable, + rgb_random_enable, highpass_random_enable); + break; + default: + /* Invalid DCP Depth reduction mode */ + BREAK_TO_DEBUGGER(); + break; + } +} + +static int dce_transform_get_max_num_of_supported_lines( + struct dce_transform *xfm_dce, + enum lb_pixel_depth depth, + int pixel_width) +{ + int pixels_per_entries = 0; + int max_pixels_supports = 0; + + ASSERT(pixel_width); + + /* Find number of pixels that can fit into a single LB entry and + * take floor of the value since we cannot store a single pixel + * across multiple entries. */ + switch (depth) { + case LB_PIXEL_DEPTH_18BPP: + pixels_per_entries = xfm_dce->lb_bits_per_entry / 18; + break; + + case LB_PIXEL_DEPTH_24BPP: + pixels_per_entries = xfm_dce->lb_bits_per_entry / 24; + break; + + case LB_PIXEL_DEPTH_30BPP: + pixels_per_entries = xfm_dce->lb_bits_per_entry / 30; + break; + + case LB_PIXEL_DEPTH_36BPP: + pixels_per_entries = xfm_dce->lb_bits_per_entry / 36; + break; + + default: + dm_logger_write(xfm_dce->base.ctx->logger, LOG_WARNING, + "%s: Invalid LB pixel depth", + __func__); + BREAK_TO_DEBUGGER(); + break; + } + + ASSERT(pixels_per_entries); + + max_pixels_supports = + pixels_per_entries * + xfm_dce->lb_memory_size; + + return (max_pixels_supports / pixel_width); +} + +static void set_denormalization( + struct dce_transform *xfm_dce, + enum dc_color_depth depth) +{ + int denorm_mode = 0; + + switch (depth) { + case COLOR_DEPTH_666: + /* 63/64 for 6 bit output color depth */ + denorm_mode = 1; + break; + case COLOR_DEPTH_888: + /* Unity for 8 bit output color depth + * because prescale is disabled by default */ + denorm_mode = 0; + break; + case COLOR_DEPTH_101010: + /* 1023/1024 for 10 bit output color depth */ + denorm_mode = 3; + break; + case COLOR_DEPTH_121212: + /* 4095/4096 for 12 bit output color depth */ + denorm_mode = 5; + break; + case COLOR_DEPTH_141414: + case COLOR_DEPTH_161616: + default: + /* not valid used case! */ + break; + } + + REG_SET(DENORM_CONTROL, 0, DENORM_MODE, denorm_mode); +} + +static void dce_transform_set_pixel_storage_depth( + struct transform *xfm, + enum lb_pixel_depth depth, + const struct bit_depth_reduction_params *bit_depth_params) +{ + struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); + int pixel_depth, expan_mode; + enum dc_color_depth color_depth; + + switch (depth) { + case LB_PIXEL_DEPTH_18BPP: + color_depth = COLOR_DEPTH_666; + pixel_depth = 2; + expan_mode = 1; + break; + case LB_PIXEL_DEPTH_24BPP: + color_depth = COLOR_DEPTH_888; + pixel_depth = 1; + expan_mode = 1; + break; + case LB_PIXEL_DEPTH_30BPP: + color_depth = COLOR_DEPTH_101010; + pixel_depth = 0; + expan_mode = 1; + break; + case LB_PIXEL_DEPTH_36BPP: + color_depth = COLOR_DEPTH_121212; + pixel_depth = 3; + expan_mode = 0; + break; + default: + color_depth = COLOR_DEPTH_101010; + pixel_depth = 0; + expan_mode = 1; + BREAK_TO_DEBUGGER(); + break; + } + + set_denormalization(xfm_dce, color_depth); + program_bit_depth_reduction(xfm_dce, color_depth, bit_depth_params); + + REG_UPDATE_2(LB_DATA_FORMAT, + PIXEL_DEPTH, pixel_depth, + PIXEL_EXPAN_MODE, expan_mode); + + if (!(xfm_dce->lb_pixel_depth_supported & depth)) { + /*we should use unsupported capabilities + * unless it is required by w/a*/ + dm_logger_write(xfm->ctx->logger, LOG_WARNING, + "%s: Capability not supported", + __func__); + } +} + +static void program_gamut_remap( + struct dce_transform *xfm_dce, + const uint16_t *reg_val) +{ + if (reg_val) { + REG_SET_2(GAMUT_REMAP_C11_C12, 0, + GAMUT_REMAP_C11, reg_val[0], + GAMUT_REMAP_C12, reg_val[1]); + REG_SET_2(GAMUT_REMAP_C13_C14, 0, + GAMUT_REMAP_C13, reg_val[2], + GAMUT_REMAP_C14, reg_val[3]); + REG_SET_2(GAMUT_REMAP_C21_C22, 0, + GAMUT_REMAP_C21, reg_val[4], + GAMUT_REMAP_C22, reg_val[5]); + REG_SET_2(GAMUT_REMAP_C23_C24, 0, + GAMUT_REMAP_C23, reg_val[6], + GAMUT_REMAP_C24, reg_val[7]); + REG_SET_2(GAMUT_REMAP_C31_C32, 0, + GAMUT_REMAP_C31, reg_val[8], + GAMUT_REMAP_C32, reg_val[9]); + REG_SET_2(GAMUT_REMAP_C33_C34, 0, + GAMUT_REMAP_C33, reg_val[10], + GAMUT_REMAP_C34, reg_val[11]); + + REG_SET(GAMUT_REMAP_CONTROL, 0, GRPH_GAMUT_REMAP_MODE, 1); + } else + REG_SET(GAMUT_REMAP_CONTROL, 0, GRPH_GAMUT_REMAP_MODE, 0); + +} + +/** + ***************************************************************************** + * Function: dal_transform_wide_gamut_set_gamut_remap + * + * @param [in] const struct xfm_grph_csc_adjustment *adjust + * + * @return + * void + * + * @note calculate and apply color temperature adjustment to in Rgb color space + * + * @see + * + ***************************************************************************** + */ +static void dce_transform_set_gamut_remap( + struct transform *xfm, + const struct xfm_grph_csc_adjustment *adjust) +{ + struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); + + if (adjust->gamut_adjust_type != GRAPHICS_GAMUT_ADJUST_TYPE_SW) + /* Bypass if type is bypass or hw */ + program_gamut_remap(xfm_dce, NULL); + else { + struct fixed31_32 arr_matrix[GAMUT_MATRIX_SIZE]; + uint16_t arr_reg_val[GAMUT_MATRIX_SIZE]; + + arr_matrix[0] = adjust->temperature_matrix[0]; + arr_matrix[1] = adjust->temperature_matrix[1]; + arr_matrix[2] = adjust->temperature_matrix[2]; + arr_matrix[3] = dal_fixed31_32_zero; + + arr_matrix[4] = adjust->temperature_matrix[3]; + arr_matrix[5] = adjust->temperature_matrix[4]; + arr_matrix[6] = adjust->temperature_matrix[5]; + arr_matrix[7] = dal_fixed31_32_zero; + + arr_matrix[8] = adjust->temperature_matrix[6]; + arr_matrix[9] = adjust->temperature_matrix[7]; + arr_matrix[10] = adjust->temperature_matrix[8]; + arr_matrix[11] = dal_fixed31_32_zero; + + convert_float_matrix( + arr_reg_val, arr_matrix, GAMUT_MATRIX_SIZE); + + program_gamut_remap(xfm_dce, arr_reg_val); + } +} + +static uint32_t decide_taps(struct fixed31_32 ratio, uint32_t in_taps, bool chroma) +{ + uint32_t taps; + + if (IDENTITY_RATIO(ratio)) { + return 1; + } else if (in_taps != 0) { + taps = in_taps; + } else { + taps = 4; + } + + if (chroma) { + taps /= 2; + if (taps < 2) + taps = 2; + } + + return taps; +} + + +bool dce_transform_get_optimal_number_of_taps( + struct transform *xfm, + struct scaler_data *scl_data, + const struct scaling_taps *in_taps) +{ + struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); + int pixel_width = scl_data->viewport.width; + int max_num_of_lines; + + if (xfm_dce->prescaler_on && + (scl_data->viewport.width > scl_data->recout.width)) + pixel_width = scl_data->recout.width; + + max_num_of_lines = dce_transform_get_max_num_of_supported_lines( + xfm_dce, + scl_data->lb_params.depth, + pixel_width); + + /* Fail if in_taps are impossible */ + if (in_taps->v_taps >= max_num_of_lines) + return false; + + /* + * Set taps according to this policy (in this order) + * - Use 1 for no scaling + * - Use input taps + * - Use 4 and reduce as required by line buffer size + * - Decide chroma taps if chroma is scaled + * + * Ignore input chroma taps. Decide based on non-chroma + */ + scl_data->taps.h_taps = decide_taps(scl_data->ratios.horz, in_taps->h_taps, false); + scl_data->taps.v_taps = decide_taps(scl_data->ratios.vert, in_taps->v_taps, false); + scl_data->taps.h_taps_c = decide_taps(scl_data->ratios.horz_c, in_taps->h_taps, true); + scl_data->taps.v_taps_c = decide_taps(scl_data->ratios.vert_c, in_taps->v_taps, true); + + if (!IDENTITY_RATIO(scl_data->ratios.vert)) { + /* reduce v_taps if needed but ensure we have at least two */ + if (in_taps->v_taps == 0 + && max_num_of_lines <= scl_data->taps.v_taps + && scl_data->taps.v_taps > 1) { + scl_data->taps.v_taps = max_num_of_lines - 1; + } + + if (scl_data->taps.v_taps <= 1) + return false; + } + + if (!IDENTITY_RATIO(scl_data->ratios.vert_c)) { + /* reduce chroma v_taps if needed but ensure we have at least two */ + if (max_num_of_lines <= scl_data->taps.v_taps_c && scl_data->taps.v_taps_c > 1) { + scl_data->taps.v_taps_c = max_num_of_lines - 1; + } + + if (scl_data->taps.v_taps_c <= 1) + return false; + } + + /* we've got valid taps */ + return true; +} + +static void dce_transform_reset(struct transform *xfm) +{ + struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); + + xfm_dce->filter_h = NULL; + xfm_dce->filter_v = NULL; +} + + +static const struct transform_funcs dce_transform_funcs = { + .transform_reset = dce_transform_reset, + .transform_set_scaler = + dce_transform_set_scaler, + .transform_set_gamut_remap = + dce_transform_set_gamut_remap, + .transform_set_pixel_storage_depth = + dce_transform_set_pixel_storage_depth, + .transform_get_optimal_number_of_taps = + dce_transform_get_optimal_number_of_taps +}; + +/*****************************************/ +/* Constructor, Destructor */ +/*****************************************/ + +bool dce_transform_construct( + struct dce_transform *xfm_dce, + struct dc_context *ctx, + uint32_t inst, + const struct dce_transform_registers *regs, + const struct dce_transform_shift *xfm_shift, + const struct dce_transform_mask *xfm_mask) +{ + xfm_dce->base.ctx = ctx; + + xfm_dce->base.inst = inst; + xfm_dce->base.funcs = &dce_transform_funcs; + + xfm_dce->regs = regs; + xfm_dce->xfm_shift = xfm_shift; + xfm_dce->xfm_mask = xfm_mask; + + xfm_dce->prescaler_on = true; + xfm_dce->lb_pixel_depth_supported = + LB_PIXEL_DEPTH_18BPP | + LB_PIXEL_DEPTH_24BPP | + LB_PIXEL_DEPTH_30BPP; + + xfm_dce->lb_bits_per_entry = LB_BITS_PER_ENTRY; + xfm_dce->lb_memory_size = LB_TOTAL_NUMBER_OF_ENTRIES; /*0x6B0*/ + + return true; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h new file mode 100644 index 000000000000..897645e2889f --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h @@ -0,0 +1,313 @@ +/* + * Copyright 2012-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef _DCE_DCE_TRANSFORM_H_ +#define _DCE_DCE_TRANSFORM_H_ + + +#include "transform.h" + +#define TO_DCE_TRANSFORM(transform)\ + container_of(transform, struct dce_transform, base) + +#define LB_TOTAL_NUMBER_OF_ENTRIES 1712 +#define LB_BITS_PER_ENTRY 144 + +#define XFM_COMMON_REG_LIST_DCE_BASE(id) \ + SRI(LB_DATA_FORMAT, LB, id), \ + SRI(GAMUT_REMAP_CONTROL, DCP, id), \ + SRI(GAMUT_REMAP_C11_C12, DCP, id), \ + SRI(GAMUT_REMAP_C13_C14, DCP, id), \ + SRI(GAMUT_REMAP_C21_C22, DCP, id), \ + SRI(GAMUT_REMAP_C23_C24, DCP, id), \ + SRI(GAMUT_REMAP_C31_C32, DCP, id), \ + SRI(GAMUT_REMAP_C33_C34, DCP, id), \ + SRI(DENORM_CONTROL, DCP, id), \ + SRI(DCP_SPATIAL_DITHER_CNTL, DCP, id), \ + SRI(OUT_ROUND_CONTROL, DCP, id), \ + SRI(OUT_CLAMP_CONTROL_R_CR, DCP, id), \ + SRI(OUT_CLAMP_CONTROL_G_Y, DCP, id), \ + SRI(OUT_CLAMP_CONTROL_B_CB, DCP, id), \ + SRI(SCL_MODE, SCL, id), \ + SRI(SCL_TAP_CONTROL, SCL, id), \ + SRI(SCL_CONTROL, SCL, id), \ + SRI(EXT_OVERSCAN_LEFT_RIGHT, SCL, id), \ + SRI(EXT_OVERSCAN_TOP_BOTTOM, SCL, id), \ + SRI(SCL_VERT_FILTER_CONTROL, SCL, id), \ + SRI(SCL_HORZ_FILTER_CONTROL, SCL, id), \ + SRI(SCL_COEF_RAM_SELECT, SCL, id), \ + SRI(SCL_COEF_RAM_TAP_DATA, SCL, id), \ + SRI(VIEWPORT_START, SCL, id), \ + SRI(VIEWPORT_SIZE, SCL, id), \ + SRI(SCL_HORZ_FILTER_SCALE_RATIO, SCL, id), \ + SRI(SCL_VERT_FILTER_SCALE_RATIO, SCL, id), \ + SRI(SCL_HORZ_FILTER_INIT, SCL, id), \ + SRI(SCL_VERT_FILTER_INIT, SCL, id), \ + SRI(SCL_AUTOMATIC_MODE_CONTROL, SCL, id), \ + SRI(LB_MEMORY_CTRL, LB, id), \ + SRI(SCL_UPDATE, SCL, id) + +#define XFM_COMMON_REG_LIST_DCE100(id) \ + XFM_COMMON_REG_LIST_DCE_BASE(id), \ + SRI(DCFE_MEM_PWR_CTRL, CRTC, id), \ + SRI(DCFE_MEM_PWR_STATUS, CRTC, id) + +#define XFM_COMMON_REG_LIST_DCE110(id) \ + XFM_COMMON_REG_LIST_DCE_BASE(id), \ + SRI(DCFE_MEM_PWR_CTRL, DCFE, id), \ + SRI(DCFE_MEM_PWR_STATUS, DCFE, id) + +#define XFM_SF(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define XFM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh) \ + XFM_SF(OUT_CLAMP_CONTROL_B_CB, OUT_CLAMP_MIN_B_CB, mask_sh), \ + XFM_SF(OUT_CLAMP_CONTROL_B_CB, OUT_CLAMP_MAX_B_CB, mask_sh), \ + XFM_SF(OUT_CLAMP_CONTROL_G_Y, OUT_CLAMP_MIN_G_Y, mask_sh), \ + XFM_SF(OUT_CLAMP_CONTROL_G_Y, OUT_CLAMP_MAX_G_Y, mask_sh), \ + XFM_SF(OUT_CLAMP_CONTROL_R_CR, OUT_CLAMP_MIN_R_CR, mask_sh), \ + XFM_SF(OUT_CLAMP_CONTROL_R_CR, OUT_CLAMP_MAX_R_CR, mask_sh), \ + XFM_SF(OUT_ROUND_CONTROL, OUT_ROUND_TRUNC_MODE, mask_sh), \ + XFM_SF(DCP_SPATIAL_DITHER_CNTL, DCP_SPATIAL_DITHER_EN, mask_sh), \ + XFM_SF(DCP_SPATIAL_DITHER_CNTL, DCP_SPATIAL_DITHER_MODE, mask_sh), \ + XFM_SF(DCP_SPATIAL_DITHER_CNTL, DCP_SPATIAL_DITHER_DEPTH, mask_sh), \ + XFM_SF(DCP_SPATIAL_DITHER_CNTL, DCP_FRAME_RANDOM_ENABLE, mask_sh), \ + XFM_SF(DCP_SPATIAL_DITHER_CNTL, DCP_RGB_RANDOM_ENABLE, mask_sh), \ + XFM_SF(DCP_SPATIAL_DITHER_CNTL, DCP_HIGHPASS_RANDOM_ENABLE, mask_sh), \ + XFM_SF(DENORM_CONTROL, DENORM_MODE, mask_sh), \ + XFM_SF(LB_DATA_FORMAT, PIXEL_DEPTH, mask_sh), \ + XFM_SF(LB_DATA_FORMAT, PIXEL_EXPAN_MODE, mask_sh), \ + XFM_SF(GAMUT_REMAP_C11_C12, GAMUT_REMAP_C11, mask_sh), \ + XFM_SF(GAMUT_REMAP_C11_C12, GAMUT_REMAP_C12, mask_sh), \ + XFM_SF(GAMUT_REMAP_C13_C14, GAMUT_REMAP_C13, mask_sh), \ + XFM_SF(GAMUT_REMAP_C13_C14, GAMUT_REMAP_C14, mask_sh), \ + XFM_SF(GAMUT_REMAP_C21_C22, GAMUT_REMAP_C21, mask_sh), \ + XFM_SF(GAMUT_REMAP_C21_C22, GAMUT_REMAP_C22, mask_sh), \ + XFM_SF(GAMUT_REMAP_C23_C24, GAMUT_REMAP_C23, mask_sh), \ + XFM_SF(GAMUT_REMAP_C23_C24, GAMUT_REMAP_C24, mask_sh), \ + XFM_SF(GAMUT_REMAP_C31_C32, GAMUT_REMAP_C31, mask_sh), \ + XFM_SF(GAMUT_REMAP_C31_C32, GAMUT_REMAP_C32, mask_sh), \ + XFM_SF(GAMUT_REMAP_C33_C34, GAMUT_REMAP_C33, mask_sh), \ + XFM_SF(GAMUT_REMAP_C33_C34, GAMUT_REMAP_C34, mask_sh), \ + XFM_SF(GAMUT_REMAP_CONTROL, GRPH_GAMUT_REMAP_MODE, mask_sh), \ + XFM_SF(SCL_MODE, SCL_MODE, mask_sh), \ + XFM_SF(SCL_TAP_CONTROL, SCL_H_NUM_OF_TAPS, mask_sh), \ + XFM_SF(SCL_TAP_CONTROL, SCL_V_NUM_OF_TAPS, mask_sh), \ + XFM_SF(SCL_CONTROL, SCL_BOUNDARY_MODE, mask_sh), \ + XFM_SF(EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_LEFT, mask_sh), \ + XFM_SF(EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_RIGHT, mask_sh), \ + XFM_SF(EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_TOP, mask_sh), \ + XFM_SF(EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_BOTTOM, mask_sh), \ + XFM_SF(SCL_COEF_RAM_SELECT, SCL_C_RAM_FILTER_TYPE, mask_sh), \ + XFM_SF(SCL_COEF_RAM_SELECT, SCL_C_RAM_PHASE, mask_sh), \ + XFM_SF(SCL_COEF_RAM_SELECT, SCL_C_RAM_TAP_PAIR_IDX, mask_sh), \ + XFM_SF(SCL_COEF_RAM_TAP_DATA, SCL_C_RAM_EVEN_TAP_COEF_EN, mask_sh), \ + XFM_SF(SCL_COEF_RAM_TAP_DATA, SCL_C_RAM_EVEN_TAP_COEF, mask_sh), \ + XFM_SF(SCL_COEF_RAM_TAP_DATA, SCL_C_RAM_ODD_TAP_COEF_EN, mask_sh), \ + XFM_SF(SCL_COEF_RAM_TAP_DATA, SCL_C_RAM_ODD_TAP_COEF, mask_sh), \ + XFM_SF(VIEWPORT_START, VIEWPORT_X_START, mask_sh), \ + XFM_SF(VIEWPORT_START, VIEWPORT_Y_START, mask_sh), \ + XFM_SF(VIEWPORT_SIZE, VIEWPORT_HEIGHT, mask_sh), \ + XFM_SF(VIEWPORT_SIZE, VIEWPORT_WIDTH, mask_sh), \ + XFM_SF(SCL_HORZ_FILTER_SCALE_RATIO, SCL_H_SCALE_RATIO, mask_sh), \ + XFM_SF(SCL_VERT_FILTER_SCALE_RATIO, SCL_V_SCALE_RATIO, mask_sh), \ + XFM_SF(SCL_HORZ_FILTER_INIT, SCL_H_INIT_INT, mask_sh), \ + XFM_SF(SCL_HORZ_FILTER_INIT, SCL_H_INIT_FRAC, mask_sh), \ + XFM_SF(SCL_VERT_FILTER_INIT, SCL_V_INIT_INT, mask_sh), \ + XFM_SF(SCL_VERT_FILTER_INIT, SCL_V_INIT_FRAC, mask_sh), \ + XFM_SF(LB_MEMORY_CTRL, LB_MEMORY_CONFIG, mask_sh), \ + XFM_SF(LB_MEMORY_CTRL, LB_MEMORY_SIZE, mask_sh), \ + XFM_SF(SCL_VERT_FILTER_CONTROL, SCL_V_2TAP_HARDCODE_COEF_EN, mask_sh), \ + XFM_SF(SCL_HORZ_FILTER_CONTROL, SCL_H_2TAP_HARDCODE_COEF_EN, mask_sh), \ + XFM_SF(SCL_UPDATE, SCL_COEF_UPDATE_COMPLETE, mask_sh), \ + XFM_SF(LB_DATA_FORMAT, ALPHA_EN, mask_sh) + +#define XFM_COMMON_MASK_SH_LIST_DCE110(mask_sh) \ + XFM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh), \ + XFM_SF(DCFE_MEM_PWR_CTRL, SCL_COEFF_MEM_PWR_DIS, mask_sh), \ + XFM_SF(DCFE_MEM_PWR_STATUS, SCL_COEFF_MEM_PWR_STATE, mask_sh), \ + XFM_SF(SCL_MODE, SCL_PSCL_EN, mask_sh) + +#define XFM_REG_FIELD_LIST(type) \ + type OUT_CLAMP_MIN_B_CB; \ + type OUT_CLAMP_MAX_B_CB; \ + type OUT_CLAMP_MIN_G_Y; \ + type OUT_CLAMP_MAX_G_Y; \ + type OUT_CLAMP_MIN_R_CR; \ + type OUT_CLAMP_MAX_R_CR; \ + type OUT_ROUND_TRUNC_MODE; \ + type DCP_SPATIAL_DITHER_EN; \ + type DCP_SPATIAL_DITHER_MODE; \ + type DCP_SPATIAL_DITHER_DEPTH; \ + type DCP_FRAME_RANDOM_ENABLE; \ + type DCP_RGB_RANDOM_ENABLE; \ + type DCP_HIGHPASS_RANDOM_ENABLE; \ + type DENORM_MODE; \ + type PIXEL_DEPTH; \ + type PIXEL_EXPAN_MODE; \ + type GAMUT_REMAP_C11; \ + type GAMUT_REMAP_C12; \ + type GAMUT_REMAP_C13; \ + type GAMUT_REMAP_C14; \ + type GAMUT_REMAP_C21; \ + type GAMUT_REMAP_C22; \ + type GAMUT_REMAP_C23; \ + type GAMUT_REMAP_C24; \ + type GAMUT_REMAP_C31; \ + type GAMUT_REMAP_C32; \ + type GAMUT_REMAP_C33; \ + type GAMUT_REMAP_C34; \ + type GRPH_GAMUT_REMAP_MODE; \ + type SCL_MODE; \ + type SCL_PSCL_EN; \ + type SCL_H_NUM_OF_TAPS; \ + type SCL_V_NUM_OF_TAPS; \ + type SCL_BOUNDARY_MODE; \ + type EXT_OVERSCAN_LEFT; \ + type EXT_OVERSCAN_RIGHT; \ + type EXT_OVERSCAN_TOP; \ + type EXT_OVERSCAN_BOTTOM; \ + type SCL_COEFF_MEM_PWR_DIS; \ + type SCL_COEFF_MEM_PWR_STATE; \ + type SCL_C_RAM_FILTER_TYPE; \ + type SCL_C_RAM_PHASE; \ + type SCL_C_RAM_TAP_PAIR_IDX; \ + type SCL_C_RAM_EVEN_TAP_COEF_EN; \ + type SCL_C_RAM_EVEN_TAP_COEF; \ + type SCL_C_RAM_ODD_TAP_COEF_EN; \ + type SCL_C_RAM_ODD_TAP_COEF; \ + type VIEWPORT_X_START; \ + type VIEWPORT_Y_START; \ + type VIEWPORT_HEIGHT; \ + type VIEWPORT_WIDTH; \ + type SCL_H_SCALE_RATIO; \ + type SCL_V_SCALE_RATIO; \ + type SCL_H_INIT_INT; \ + type SCL_H_INIT_FRAC; \ + type SCL_V_INIT_INT; \ + type SCL_V_INIT_FRAC; \ + type LB_MEMORY_CONFIG; \ + type LB_MEMORY_SIZE; \ + type SCL_V_2TAP_HARDCODE_COEF_EN; \ + type SCL_H_2TAP_HARDCODE_COEF_EN; \ + type SCL_COEF_UPDATE_COMPLETE; \ + type ALPHA_EN + +struct dce_transform_shift { + XFM_REG_FIELD_LIST(uint8_t); +}; + +struct dce_transform_mask { + XFM_REG_FIELD_LIST(uint32_t); +}; + +struct dce_transform_registers { + uint32_t LB_DATA_FORMAT; + uint32_t GAMUT_REMAP_CONTROL; + uint32_t GAMUT_REMAP_C11_C12; + uint32_t GAMUT_REMAP_C13_C14; + uint32_t GAMUT_REMAP_C21_C22; + uint32_t GAMUT_REMAP_C23_C24; + uint32_t GAMUT_REMAP_C31_C32; + uint32_t GAMUT_REMAP_C33_C34; + uint32_t DENORM_CONTROL; + uint32_t DCP_SPATIAL_DITHER_CNTL; + uint32_t OUT_ROUND_CONTROL; + uint32_t OUT_CLAMP_CONTROL_R_CR; + uint32_t OUT_CLAMP_CONTROL_G_Y; + uint32_t OUT_CLAMP_CONTROL_B_CB; + uint32_t SCL_MODE; + uint32_t SCL_TAP_CONTROL; + uint32_t SCL_CONTROL; + uint32_t EXT_OVERSCAN_LEFT_RIGHT; + uint32_t EXT_OVERSCAN_TOP_BOTTOM; + uint32_t SCL_VERT_FILTER_CONTROL; + uint32_t SCL_HORZ_FILTER_CONTROL; + uint32_t DCFE_MEM_PWR_CTRL; + uint32_t DCFE_MEM_PWR_STATUS; + uint32_t SCL_COEF_RAM_SELECT; + uint32_t SCL_COEF_RAM_TAP_DATA; + uint32_t VIEWPORT_START; + uint32_t VIEWPORT_SIZE; + uint32_t SCL_HORZ_FILTER_SCALE_RATIO; + uint32_t SCL_VERT_FILTER_SCALE_RATIO; + uint32_t SCL_HORZ_FILTER_INIT; + uint32_t SCL_VERT_FILTER_INIT; + uint32_t SCL_AUTOMATIC_MODE_CONTROL; + uint32_t LB_MEMORY_CTRL; + uint32_t SCL_UPDATE; +}; + +struct init_int_and_frac { + uint32_t integer; + uint32_t fraction; +}; + +struct scl_ratios_inits { + uint32_t h_int_scale_ratio; + uint32_t v_int_scale_ratio; + struct init_int_and_frac h_init; + struct init_int_and_frac v_init; +}; + +enum ram_filter_type { + FILTER_TYPE_RGB_Y_VERTICAL = 0, /* 0 - RGB/Y Vertical filter */ + FILTER_TYPE_CBCR_VERTICAL = 1, /* 1 - CbCr Vertical filter */ + FILTER_TYPE_RGB_Y_HORIZONTAL = 2, /* 1 - RGB/Y Horizontal filter */ + FILTER_TYPE_CBCR_HORIZONTAL = 3, /* 3 - CbCr Horizontal filter */ + FILTER_TYPE_ALPHA_VERTICAL = 4, /* 4 - Alpha Vertical filter. */ + FILTER_TYPE_ALPHA_HORIZONTAL = 5, /* 5 - Alpha Horizontal filter. */ +}; + +struct dce_transform { + struct transform base; + const struct dce_transform_registers *regs; + const struct dce_transform_shift *xfm_shift; + const struct dce_transform_mask *xfm_mask; + + const uint16_t *filter_v; + const uint16_t *filter_h; + const uint16_t *filter_v_c; + const uint16_t *filter_h_c; + int lb_pixel_depth_supported; + int lb_memory_size; + int lb_bits_per_entry; + bool prescaler_on; +}; + +bool dce_transform_construct(struct dce_transform *xfm110, + struct dc_context *ctx, + uint32_t inst, + const struct dce_transform_registers *regs, + const struct dce_transform_shift *xfm_shift, + const struct dce_transform_mask *xfm_mask); + +bool dce_transform_get_optimal_number_of_taps( + struct transform *xfm, + struct scaler_data *scl_data, + const struct scaling_taps *in_taps); + + +#endif /* _DCE_DCE_TRANSFORM_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce100/Makefile b/drivers/gpu/drm/amd/display/dc/dce100/Makefile new file mode 100644 index 000000000000..ea40870624b3 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce100/Makefile @@ -0,0 +1,23 @@ +# +# Makefile for the 'controller' sub-component of DAL. +# It provides the control and status of HW CRTC block. + +DCE100 = dce100_resource.o dce100_hw_sequencer.o + +AMD_DAL_DCE100 = $(addprefix $(AMDDALPATH)/dc/dce100/,$(DCE100)) + +AMD_DISPLAY_FILES += $(AMD_DAL_DCE100) + + +############################################################################### +# DCE 10x +############################################################################### +ifdef 0#CONFIG_DRM_AMD_DC_DCE11_0 +TG_DCE100 = dce100_resource.o + +AMD_DAL_TG_DCE100 = $(addprefix \ + $(AMDDALPATH)/dc/dce100/,$(TG_DCE100)) + +AMD_DISPLAY_FILES += $(AMD_DAL_TG_DCE100) +endif + diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c new file mode 100644 index 000000000000..e2fe024e1182 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c @@ -0,0 +1,140 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#include "dm_services.h" +#include "dc.h" +#include "core_dc.h" +#include "core_types.h" +#include "hw_sequencer.h" +#include "dce100_hw_sequencer.h" +#include "dce110/dce110_hw_sequencer.h" + +/* include DCE10 register header files */ +#include "dce/dce_10_0_d.h" +#include "dce/dce_10_0_sh_mask.h" + +struct dce100_hw_seq_reg_offsets { + uint32_t blnd; + uint32_t crtc; +}; + +static const struct dce100_hw_seq_reg_offsets reg_offsets[] = { +{ + .crtc = (mmCRTC0_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), +}, +{ + .crtc = (mmCRTC1_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), +}, +{ + .crtc = (mmCRTC2_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), +}, +{ + .crtc = (mmCRTC3_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), +}, +{ + .crtc = (mmCRTC4_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), +}, +{ + .crtc = (mmCRTC5_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), +} +}; + +#define HW_REG_CRTC(reg, id)\ + (reg + reg_offsets[id].crtc) + +/******************************************************************************* + * Private definitions + ******************************************************************************/ +/***************************PIPE_CONTROL***********************************/ + +static bool dce100_enable_display_power_gating( + struct core_dc *dc, + uint8_t controller_id, + struct dc_bios *dcb, + enum pipe_gating_control power_gating) +{ + enum bp_result bp_result = BP_RESULT_OK; + enum bp_pipe_control_action cntl; + struct dc_context *ctx = dc->ctx; + + if (power_gating == PIPE_GATING_CONTROL_INIT) + cntl = ASIC_PIPE_INIT; + else if (power_gating == PIPE_GATING_CONTROL_ENABLE) + cntl = ASIC_PIPE_ENABLE; + else + cntl = ASIC_PIPE_DISABLE; + + if (!(power_gating == PIPE_GATING_CONTROL_INIT && controller_id != 0)){ + + bp_result = dcb->funcs->enable_disp_power_gating( + dcb, controller_id + 1, cntl); + + /* Revert MASTER_UPDATE_MODE to 0 because bios sets it 2 + * by default when command table is called + */ + dm_write_reg(ctx, + HW_REG_CRTC(mmMASTER_UPDATE_MODE, controller_id), + 0); + } + + if (bp_result == BP_RESULT_OK) + return true; + else + return false; +} + +static void set_display_mark_for_pipe_if_needed(struct core_dc *dc, + struct pipe_ctx *pipe_ctx, + struct validate_context *context) +{ + /* Do nothing until we have proper bandwitdth calcs */ +} + +static void set_displaymarks( + const struct core_dc *dc, struct validate_context *context) +{ + /* Do nothing until we have proper bandwitdth calcs */ +} + +static void set_bandwidth(struct core_dc *dc) +{ + /* Do nothing until we have proper bandwitdth calcs */ +} + + +/**************************************************************************/ + +bool dce100_hw_sequencer_construct(struct core_dc *dc) +{ + dce110_hw_sequencer_construct(dc); + + /* TODO: dce80 is empty implementation at the moment*/ + dc->hwss.enable_display_power_gating = dce100_enable_display_power_gating; + dc->hwss.set_displaymarks = set_displaymarks; + dc->hwss.increase_watermarks_for_pipe = set_display_mark_for_pipe_if_needed; + dc->hwss.set_bandwidth = set_bandwidth; + + return true; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h new file mode 100644 index 000000000000..cf497ea605c8 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h @@ -0,0 +1,36 @@ +/* +* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_HWSS_DCE100_H__ +#define __DC_HWSS_DCE100_H__ + +#include "core_types.h" + +struct core_dc; + +bool dce100_hw_sequencer_construct(struct core_dc *dc); + +#endif /* __DC_HWSS_DCE100_H__ */ + diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c new file mode 100644 index 000000000000..16595dc875a1 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -0,0 +1,1085 @@ +/* +* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#include "dm_services.h" + +#include "link_encoder.h" +#include "stream_encoder.h" + +#include "resource.h" +#include "include/irq_service_interface.h" +#include "../virtual/virtual_stream_encoder.h" +#include "dce110/dce110_resource.h" +#include "dce110/dce110_timing_generator.h" +#include "irq/dce110/irq_service_dce110.h" +#include "dce/dce_link_encoder.h" +#include "dce/dce_stream_encoder.h" +#include "dce110/dce110_mem_input.h" +#include "dce110/dce110_mem_input_v.h" +#include "dce110/dce110_ipp.h" +#include "dce/dce_transform.h" +#include "dce110/dce110_opp.h" +#include "dce/dce_clock_source.h" +#include "dce/dce_audio.h" +#include "dce/dce_hwseq.h" +#include "dce100/dce100_hw_sequencer.h" + +#include "reg_helper.h" + +#include "dce/dce_10_0_d.h" +#include "dce/dce_10_0_sh_mask.h" + +#ifndef mmMC_HUB_RDREQ_DMIF_LIMIT +#include "gmc/gmc_8_2_d.h" +#include "gmc/gmc_8_2_sh_mask.h" +#endif + +#ifndef mmDP_DPHY_INTERNAL_CTRL + #define mmDP_DPHY_INTERNAL_CTRL 0x4aa7 + #define mmDP0_DP_DPHY_INTERNAL_CTRL 0x4aa7 + #define mmDP1_DP_DPHY_INTERNAL_CTRL 0x4ba7 + #define mmDP2_DP_DPHY_INTERNAL_CTRL 0x4ca7 + #define mmDP3_DP_DPHY_INTERNAL_CTRL 0x4da7 + #define mmDP4_DP_DPHY_INTERNAL_CTRL 0x4ea7 + #define mmDP5_DP_DPHY_INTERNAL_CTRL 0x4fa7 + #define mmDP6_DP_DPHY_INTERNAL_CTRL 0x54a7 + #define mmDP7_DP_DPHY_INTERNAL_CTRL 0x56a7 + #define mmDP8_DP_DPHY_INTERNAL_CTRL 0x57a7 +#endif + +#ifndef mmBIOS_SCRATCH_2 + #define mmBIOS_SCRATCH_2 0x05CB + #define mmBIOS_SCRATCH_6 0x05CF +#endif + +#ifndef mmDP_DPHY_BS_SR_SWAP_CNTL + #define mmDP_DPHY_BS_SR_SWAP_CNTL 0x4ADC + #define mmDP0_DP_DPHY_BS_SR_SWAP_CNTL 0x4ADC + #define mmDP1_DP_DPHY_BS_SR_SWAP_CNTL 0x4BDC + #define mmDP2_DP_DPHY_BS_SR_SWAP_CNTL 0x4CDC + #define mmDP3_DP_DPHY_BS_SR_SWAP_CNTL 0x4DDC + #define mmDP4_DP_DPHY_BS_SR_SWAP_CNTL 0x4EDC + #define mmDP5_DP_DPHY_BS_SR_SWAP_CNTL 0x4FDC + #define mmDP6_DP_DPHY_BS_SR_SWAP_CNTL 0x54DC +#endif + +#ifndef mmDP_DPHY_FAST_TRAINING + #define mmDP_DPHY_FAST_TRAINING 0x4ABC + #define mmDP0_DP_DPHY_FAST_TRAINING 0x4ABC + #define mmDP1_DP_DPHY_FAST_TRAINING 0x4BBC + #define mmDP2_DP_DPHY_FAST_TRAINING 0x4CBC + #define mmDP3_DP_DPHY_FAST_TRAINING 0x4DBC + #define mmDP4_DP_DPHY_FAST_TRAINING 0x4EBC + #define mmDP5_DP_DPHY_FAST_TRAINING 0x4FBC + #define mmDP6_DP_DPHY_FAST_TRAINING 0x54BC +#endif + +static const struct dce110_timing_generator_offsets dce100_tg_offsets[] = { + { + .crtc = (mmCRTC0_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL), + }, + { + .crtc = (mmCRTC1_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL), + }, + { + .crtc = (mmCRTC2_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL), + }, + { + .crtc = (mmCRTC3_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL), + }, + { + .crtc = (mmCRTC4_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL), + }, + { + .crtc = (mmCRTC5_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL), + } +}; + +static const struct dce110_mem_input_reg_offsets dce100_mi_reg_offsets[] = { + { + .dcp = (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE0_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + }, + { + .dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG1_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE1_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + }, + { + .dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG2_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE2_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + }, + { + .dcp = (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG3_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE3_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + }, + { + .dcp = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG4_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE4_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + }, + { + .dcp = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG5_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE5_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + } +}; + + +static const struct dce110_ipp_reg_offsets dce100_ipp_reg_offsets[] = { +{ + .dcp_offset = (mmDCP0_CUR_CONTROL - mmCUR_CONTROL), +}, +{ + .dcp_offset = (mmDCP1_CUR_CONTROL - mmCUR_CONTROL), +}, +{ + .dcp_offset = (mmDCP2_CUR_CONTROL - mmCUR_CONTROL), +}, +{ + .dcp_offset = (mmDCP3_CUR_CONTROL - mmCUR_CONTROL), +}, +{ + .dcp_offset = (mmDCP4_CUR_CONTROL - mmCUR_CONTROL), +}, +{ + .dcp_offset = (mmDCP5_CUR_CONTROL - mmCUR_CONTROL), +} +}; + + + +/* set register offset */ +#define SR(reg_name)\ + .reg_name = mm ## reg_name + +/* set register offset with instance */ +#define SRI(reg_name, block, id)\ + .reg_name = mm ## block ## id ## _ ## reg_name + + +#define transform_regs(id)\ +[id] = {\ + XFM_COMMON_REG_LIST_DCE100(id)\ +} + +static const struct dce_transform_registers xfm_regs[] = { + transform_regs(0), + transform_regs(1), + transform_regs(2), + transform_regs(3), + transform_regs(4), + transform_regs(5) +}; + +static const struct dce_transform_shift xfm_shift = { + XFM_COMMON_MASK_SH_LIST_DCE110(__SHIFT) +}; + +static const struct dce_transform_mask xfm_mask = { + XFM_COMMON_MASK_SH_LIST_DCE110(_MASK) +}; + +#define aux_regs(id)\ +[id] = {\ + AUX_REG_LIST(id)\ +} + +static const struct dce110_link_enc_aux_registers link_enc_aux_regs[] = { + aux_regs(0), + aux_regs(1), + aux_regs(2), + aux_regs(3), + aux_regs(4), + aux_regs(5) +}; + +#define hpd_regs(id)\ +[id] = {\ + HPD_REG_LIST(id)\ +} + +static const struct dce110_link_enc_hpd_registers link_enc_hpd_regs[] = { + hpd_regs(0), + hpd_regs(1), + hpd_regs(2), + hpd_regs(3), + hpd_regs(4), + hpd_regs(5) +}; + +#define link_regs(id)\ +[id] = {\ + LE_DCE110_REG_LIST(id)\ +} + +static const struct dce110_link_enc_registers link_enc_regs[] = { + link_regs(0), + link_regs(1), + link_regs(2), + link_regs(3), + link_regs(4), + link_regs(5), + link_regs(6), +}; + +#define stream_enc_regs(id)\ +[id] = {\ + SE_COMMON_REG_LIST_DCE_BASE(id),\ + .AFMT_CNTL = 0,\ +} + +static const struct dce110_stream_enc_registers stream_enc_regs[] = { + stream_enc_regs(0), + stream_enc_regs(1), + stream_enc_regs(2), + stream_enc_regs(3), + stream_enc_regs(4), + stream_enc_regs(5), + stream_enc_regs(6) +}; + +static const struct dce_stream_encoder_shift se_shift = { + SE_COMMON_MASK_SH_LIST_DCE80_100(__SHIFT) +}; + +static const struct dce_stream_encoder_mask se_mask = { + SE_COMMON_MASK_SH_LIST_DCE80_100(_MASK) +}; + +#define audio_regs(id)\ +[id] = {\ + AUD_COMMON_REG_LIST(id)\ +} + +static const struct dce_audio_registers audio_regs[] = { + audio_regs(0), + audio_regs(1), + audio_regs(2), + audio_regs(3), + audio_regs(4), + audio_regs(5), + audio_regs(6), +}; + +static const struct dce_audio_shift audio_shift = { + AUD_COMMON_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_aduio_mask audio_mask = { + AUD_COMMON_MASK_SH_LIST(_MASK) +}; + +#define clk_src_regs(id)\ +[id] = {\ + CS_COMMON_REG_LIST_DCE_100_110(id),\ +} + +static const struct dce110_clk_src_regs clk_src_regs[] = { + clk_src_regs(0), + clk_src_regs(1), + clk_src_regs(2) +}; + +static const struct dce110_clk_src_shift cs_shift = { + CS_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) +}; + +static const struct dce110_clk_src_mask cs_mask = { + CS_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) +}; + + + +#define DCFE_MEM_PWR_CTRL_REG_BASE 0x1b03 + +static const struct dce110_opp_reg_offsets dce100_opp_reg_offsets[] = { +{ + .fmt_offset = (mmFMT0_FMT_CONTROL - mmFMT_CONTROL), + .dcfe_offset = (mmCRTC0_DCFE_MEM_PWR_CTRL - DCFE_MEM_PWR_CTRL_REG_BASE), + .dcp_offset = (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL), +}, +{ .fmt_offset = (mmFMT1_FMT_CONTROL - mmFMT0_FMT_CONTROL), + .dcfe_offset = (mmCRTC1_DCFE_MEM_PWR_CTRL - DCFE_MEM_PWR_CTRL_REG_BASE), + .dcp_offset = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ .fmt_offset = (mmFMT2_FMT_CONTROL - mmFMT0_FMT_CONTROL), + .dcfe_offset = (mmCRTC2_DCFE_MEM_PWR_CTRL - DCFE_MEM_PWR_CTRL_REG_BASE), + .dcp_offset = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ + .fmt_offset = (mmFMT3_FMT_CONTROL - mmFMT0_FMT_CONTROL), + .dcfe_offset = (mmCRTC3_DCFE_MEM_PWR_CTRL - DCFE_MEM_PWR_CTRL_REG_BASE), + .dcp_offset = (mmDCP3_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ .fmt_offset = (mmFMT4_FMT_CONTROL - mmFMT0_FMT_CONTROL), + .dcfe_offset = (mmCRTC4_DCFE_MEM_PWR_CTRL - DCFE_MEM_PWR_CTRL_REG_BASE), + .dcp_offset = (mmDCP4_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ .fmt_offset = (mmFMT5_FMT_CONTROL - mmFMT0_FMT_CONTROL), + .dcfe_offset = (mmCRTC5_DCFE_MEM_PWR_CTRL - DCFE_MEM_PWR_CTRL_REG_BASE), + .dcp_offset = (mmDCP5_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +} +}; + +static const struct bios_registers bios_regs = { + .BIOS_SCRATCH_6 = mmBIOS_SCRATCH_6 +}; + +static const struct resource_caps res_cap = { + .num_timing_generator = 6, + .num_audio = 6, + .num_stream_encoder = 6, + .num_pll = 3 +}; + +#define CTX ctx +#define REG(reg) mm ## reg + +#ifndef mmCC_DC_HDMI_STRAPS +#define mmCC_DC_HDMI_STRAPS 0x1918 +#define CC_DC_HDMI_STRAPS__HDMI_DISABLE_MASK 0x40 +#define CC_DC_HDMI_STRAPS__HDMI_DISABLE__SHIFT 0x6 +#define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER_MASK 0x700 +#define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER__SHIFT 0x8 +#endif + +static void read_dce_straps( + struct dc_context *ctx, + struct resource_straps *straps) +{ + REG_GET_2(CC_DC_HDMI_STRAPS, + HDMI_DISABLE, &straps->hdmi_disable, + AUDIO_STREAM_NUMBER, &straps->audio_stream_number); + + REG_GET(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO, &straps->dc_pinstraps_audio); +} + +static struct audio *create_audio( + struct dc_context *ctx, unsigned int inst) +{ + return dce_audio_create(ctx, inst, + &audio_regs[inst], &audio_shift, &audio_mask); +} + +static struct timing_generator *dce100_timing_generator_create( + struct dc_context *ctx, + uint32_t instance, + const struct dce110_timing_generator_offsets *offsets) +{ + struct dce110_timing_generator *tg110 = + dm_alloc(sizeof(struct dce110_timing_generator)); + + if (!tg110) + return NULL; + + if (dce110_timing_generator_construct(tg110, ctx, instance, + offsets)) + return &tg110->base; + + BREAK_TO_DEBUGGER(); + dm_free(tg110); + return NULL; +} + +static struct stream_encoder *dce100_stream_encoder_create( + enum engine_id eng_id, + struct dc_context *ctx) +{ + struct dce110_stream_encoder *enc110 = + dm_alloc(sizeof(struct dce110_stream_encoder)); + + if (!enc110) + return NULL; + + if (dce110_stream_encoder_construct( + enc110, ctx, ctx->dc_bios, eng_id, + &stream_enc_regs[eng_id], &se_shift, &se_mask)) + return &enc110->base; + + BREAK_TO_DEBUGGER(); + dm_free(enc110); + return NULL; +} + +#define SRII(reg_name, block, id)\ + .reg_name[id] = mm ## block ## id ## _ ## reg_name + +static const struct dce_hwseq_registers hwseq_reg = { + HWSEQ_DCE10_REG_LIST() +}; + +static const struct dce_hwseq_shift hwseq_shift = { + HWSEQ_DCE10_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_hwseq_mask hwseq_mask = { + HWSEQ_DCE10_MASK_SH_LIST(_MASK) +}; + +static struct dce_hwseq *dce100_hwseq_create( + struct dc_context *ctx) +{ + struct dce_hwseq *hws = dm_alloc(sizeof(struct dce_hwseq)); + + if (hws) { + hws->ctx = ctx; + hws->regs = &hwseq_reg; + hws->shifts = &hwseq_shift; + hws->masks = &hwseq_mask; + } + return hws; +} + +static const struct resource_create_funcs res_create_funcs = { + .read_dce_straps = read_dce_straps, + .create_audio = create_audio, + .create_stream_encoder = dce100_stream_encoder_create, + .create_hwseq = dce100_hwseq_create, +}; + +#define mi_inst_regs(id) { \ + MI_REG_LIST(id), \ + .MC_HUB_RDREQ_DMIF_LIMIT = mmMC_HUB_RDREQ_DMIF_LIMIT \ +} +static const struct dce_mem_input_registers mi_regs[] = { + mi_inst_regs(0), + mi_inst_regs(1), + mi_inst_regs(2), + mi_inst_regs(3), + mi_inst_regs(4), + mi_inst_regs(5), +}; + +static const struct dce_mem_input_shift mi_shifts = { + MI_DCE_MASK_SH_LIST(__SHIFT), + .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE__SHIFT +}; + +static const struct dce_mem_input_mask mi_masks = { + MI_DCE_MASK_SH_LIST(_MASK), + .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE_MASK +}; + +static struct mem_input *dce100_mem_input_create( + struct dc_context *ctx, + uint32_t inst, + const struct dce110_mem_input_reg_offsets *offset) +{ + struct dce110_mem_input *mem_input110 = + dm_alloc(sizeof(struct dce110_mem_input)); + + if (!mem_input110) + return NULL; + + if (dce110_mem_input_construct(mem_input110, ctx, inst, offset)) { + struct mem_input *mi = &mem_input110->base; + + mi->regs = &mi_regs[inst]; + mi->shifts = &mi_shifts; + mi->masks = &mi_masks; + mi->wa.single_head_rdreq_dmif_limit = 2; + return mi; + } + + BREAK_TO_DEBUGGER(); + dm_free(mem_input110); + return NULL; +} + +static void dce100_transform_destroy(struct transform **xfm) +{ + dm_free(TO_DCE_TRANSFORM(*xfm)); + *xfm = NULL; +} + +static struct transform *dce100_transform_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dce_transform *transform = + dm_alloc(sizeof(struct dce_transform)); + + if (!transform) + return NULL; + + if (dce_transform_construct(transform, ctx, inst, + &xfm_regs[inst], &xfm_shift, &xfm_mask)) { + return &transform->base; + } + + BREAK_TO_DEBUGGER(); + dm_free(transform); + return NULL; +} + +static struct input_pixel_processor *dce100_ipp_create( + struct dc_context *ctx, + uint32_t inst, + const struct dce110_ipp_reg_offsets *offsets) +{ + struct dce110_ipp *ipp = + dm_alloc(sizeof(struct dce110_ipp)); + + if (!ipp) + return NULL; + + if (dce110_ipp_construct(ipp, ctx, inst, offsets)) + return &ipp->base; + + BREAK_TO_DEBUGGER(); + dm_free(ipp); + return NULL; +} + +struct link_encoder *dce100_link_encoder_create( + const struct encoder_init_data *enc_init_data) +{ + struct dce110_link_encoder *enc110 = + dm_alloc(sizeof(struct dce110_link_encoder)); + + if (!enc110) + return NULL; + + if (dce110_link_encoder_construct( + enc110, + enc_init_data, + &link_enc_regs[enc_init_data->transmitter], + &link_enc_aux_regs[enc_init_data->channel - 1], + &link_enc_hpd_regs[enc_init_data->hpd_source])) { + + enc110->base.features.ycbcr420_supported = false; + enc110->base.features.max_hdmi_pixel_clock = 300000; + return &enc110->base; + } + + BREAK_TO_DEBUGGER(); + dm_free(enc110); + return NULL; +} + +struct output_pixel_processor *dce100_opp_create( + struct dc_context *ctx, + uint32_t inst, + const struct dce110_opp_reg_offsets *offset) +{ + struct dce110_opp *opp = + dm_alloc(sizeof(struct dce110_opp)); + + if (!opp) + return NULL; + + if (dce110_opp_construct(opp, + ctx, inst, offset)) + return &opp->base; + + BREAK_TO_DEBUGGER(); + dm_free(opp); + return NULL; +} + +void dce100_opp_destroy(struct output_pixel_processor **opp) +{ + struct dce110_opp *dce110_opp; + + if (!opp || !*opp) + return; + + dce110_opp = FROM_DCE11_OPP(*opp); + + dm_free(dce110_opp->regamma.coeff128_dx); + dm_free(dce110_opp->regamma.coeff128_oem); + dm_free(dce110_opp->regamma.coeff128); + dm_free(dce110_opp->regamma.axis_x_1025); + dm_free(dce110_opp->regamma.axis_x_256); + dm_free(dce110_opp->regamma.coordinates_x); + dm_free(dce110_opp->regamma.rgb_regamma); + dm_free(dce110_opp->regamma.rgb_resulted); + dm_free(dce110_opp->regamma.rgb_oem); + dm_free(dce110_opp->regamma.rgb_user); + dm_free(dce110_opp); + + *opp = NULL; +} + +struct clock_source *dce100_clock_source_create( + struct dc_context *ctx, + struct dc_bios *bios, + enum clock_source_id id, + const struct dce110_clk_src_regs *regs, + bool dp_clk_src) +{ + struct dce110_clk_src *clk_src = + dm_alloc(sizeof(struct dce110_clk_src)); + + if (!clk_src) + return NULL; + + if (dce110_clk_src_construct(clk_src, ctx, bios, id, + regs, &cs_shift, &cs_mask)) { + clk_src->base.dp_clk_src = dp_clk_src; + return &clk_src->base; + } + + BREAK_TO_DEBUGGER(); + return NULL; +} + +void dce100_clock_source_destroy(struct clock_source **clk_src) +{ + dm_free(TO_DCE110_CLK_SRC(*clk_src)); + *clk_src = NULL; +} + +static void destruct(struct dce110_resource_pool *pool) +{ + unsigned int i; + + for (i = 0; i < pool->base.pipe_count; i++) { + if (pool->base.opps[i] != NULL) + dce100_opp_destroy(&pool->base.opps[i]); + + if (pool->base.transforms[i] != NULL) + dce100_transform_destroy(&pool->base.transforms[i]); + + if (pool->base.ipps[i] != NULL) + dce110_ipp_destroy(&pool->base.ipps[i]); + + if (pool->base.mis[i] != NULL) { + dm_free(TO_DCE110_MEM_INPUT(pool->base.mis[i])); + pool->base.mis[i] = NULL; + } + + if (pool->base.timing_generators[i] != NULL) { + dm_free(DCE110TG_FROM_TG(pool->base.timing_generators[i])); + pool->base.timing_generators[i] = NULL; + } + } + + for (i = 0; i < pool->base.stream_enc_count; i++) { + if (pool->base.stream_enc[i] != NULL) + dm_free(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); + } + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] != NULL) + dce100_clock_source_destroy(&pool->base.clock_sources[i]); + } + + if (pool->base.dp_clock_source != NULL) + dce100_clock_source_destroy(&pool->base.dp_clock_source); + + for (i = 0; i < pool->base.audio_count; i++) { + if (pool->base.audios[i] != NULL) + dce_aud_destroy(&pool->base.audios[i]); + } + + if (pool->base.display_clock != NULL) + dal_display_clock_destroy(&pool->base.display_clock); + + if (pool->base.irqs != NULL) + dal_irq_service_destroy(&pool->base.irqs); +} + +static enum dc_status validate_mapped_resource( + const struct core_dc *dc, + struct validate_context *context) +{ + enum dc_status status = DC_OK; + uint8_t i, j, k; + + for (i = 0; i < context->target_count; i++) { + struct core_target *target = context->targets[i]; + + for (j = 0; j < target->public.stream_count; j++) { + struct core_stream *stream = + DC_STREAM_TO_CORE(target->public.streams[j]); + struct core_link *link = stream->sink->link; + + if (resource_is_stream_unchanged(dc->current_context, stream)) + continue; + + for (k = 0; k < MAX_PIPES; k++) { + struct pipe_ctx *pipe_ctx = + &context->res_ctx.pipe_ctx[k]; + + if (context->res_ctx.pipe_ctx[k].stream != stream) + continue; + + if (!pipe_ctx->tg->funcs->validate_timing( + pipe_ctx->tg, &stream->public.timing)) + return DC_FAIL_CONTROLLER_VALIDATE; + + status = dce110_resource_build_pipe_hw_param(pipe_ctx); + + if (status != DC_OK) + return status; + + if (!link->link_enc->funcs->validate_output_with_stream( + link->link_enc, + pipe_ctx)) + return DC_FAIL_ENC_VALIDATE; + + /* TODO: validate audio ASIC caps, encoder */ + status = dc_link_validate_mode_timing(stream, + link, + &stream->public.timing); + + if (status != DC_OK) + return status; + + resource_build_info_frame(pipe_ctx); + + /* do not need to validate non root pipes */ + break; + } + } + } + + return DC_OK; +} + +enum dc_status dce100_validate_bandwidth( + const struct core_dc *dc, + struct validate_context *context) +{ + /* TODO implement when needed but for now hardcode max value*/ + context->bw_results.dispclk_khz = 681000; + + return DC_OK; +} + +static bool dce100_validate_surface_sets( + const struct dc_validation_set set[], + int set_count) +{ + int i; + + for (i = 0; i < set_count; i++) { + if (set[i].surface_count == 0) + continue; + + if (set[i].surface_count > 1) + return false; + + if (set[i].surfaces[0]->clip_rect.width + != set[i].target->streams[0]->src.width + || set[i].surfaces[0]->clip_rect.height + != set[i].target->streams[0]->src.height) + return false; + if (set[i].surfaces[0]->format + >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) + return false; + } + + return true; +} + +enum dc_status dce100_validate_with_context( + const struct core_dc *dc, + const struct dc_validation_set set[], + int set_count, + struct validate_context *context) +{ + struct dc_context *dc_ctx = dc->ctx; + enum dc_status result = DC_ERROR_UNEXPECTED; + int i; + + if (!dce100_validate_surface_sets(set, set_count)) + return DC_FAIL_SURFACE_VALIDATE; + + context->res_ctx.pool = dc->res_pool; + + for (i = 0; i < set_count; i++) { + context->targets[i] = DC_TARGET_TO_CORE(set[i].target); + dc_target_retain(&context->targets[i]->public); + context->target_count++; + } + + result = resource_map_pool_resources(dc, context); + + if (result == DC_OK) + result = resource_map_clock_resources(dc, context); + + if (!resource_validate_attach_surfaces( + set, set_count, dc->current_context, context)) { + DC_ERROR("Failed to attach surface to target!\n"); + return DC_FAIL_ATTACH_SURFACES; + } + + if (result == DC_OK) + result = validate_mapped_resource(dc, context); + + if (result == DC_OK) + result = resource_build_scaling_params_for_context(dc, context); + + if (result == DC_OK) + result = dce100_validate_bandwidth(dc, context); + + return result; +} + +enum dc_status dce100_validate_guaranteed( + const struct core_dc *dc, + const struct dc_target *dc_target, + struct validate_context *context) +{ + enum dc_status result = DC_ERROR_UNEXPECTED; + + context->res_ctx.pool = dc->res_pool; + + context->targets[0] = DC_TARGET_TO_CORE(dc_target); + dc_target_retain(&context->targets[0]->public); + context->target_count++; + + result = resource_map_pool_resources(dc, context); + + if (result == DC_OK) + result = resource_map_clock_resources(dc, context); + + if (result == DC_OK) + result = validate_mapped_resource(dc, context); + + if (result == DC_OK) { + validate_guaranteed_copy_target( + context, dc->public.caps.max_targets); + result = resource_build_scaling_params_for_context(dc, context); + } + + if (result == DC_OK) + result = dce100_validate_bandwidth(dc, context); + + return result; +} + +static void dce100_destroy_resource_pool(struct resource_pool **pool) +{ + struct dce110_resource_pool *dce110_pool = TO_DCE110_RES_POOL(*pool); + + destruct(dce110_pool); + dm_free(dce110_pool); + *pool = NULL; +} + +static const struct resource_funcs dce100_res_pool_funcs = { + .destroy = dce100_destroy_resource_pool, + .link_enc_create = dce100_link_encoder_create, + .validate_with_context = dce100_validate_with_context, + .validate_guaranteed = dce100_validate_guaranteed, + .validate_bandwidth = dce100_validate_bandwidth +}; + +static bool construct( + uint8_t num_virtual_links, + struct core_dc *dc, + struct dce110_resource_pool *pool) +{ + unsigned int i; + struct dc_context *ctx = dc->ctx; + struct firmware_info info; + struct dc_bios *bp; + struct dm_pp_static_clock_info static_clk_info = {0}; + + ctx->dc_bios->regs = &bios_regs; + + pool->base.res_cap = &res_cap; + pool->base.funcs = &dce100_res_pool_funcs; + pool->base.underlay_pipe_index = -1; + + bp = ctx->dc_bios; + + if ((bp->funcs->get_firmware_info(bp, &info) == BP_RESULT_OK) && + info.external_clock_source_frequency_for_dp != 0) { + pool->base.dp_clock_source = + dce100_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true); + + pool->base.clock_sources[0] = + dce100_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], false); + pool->base.clock_sources[1] = + dce100_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false); + pool->base.clock_sources[2] = + dce100_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false); + pool->base.clk_src_count = 3; + + } else { + pool->base.dp_clock_source = + dce100_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], true); + + pool->base.clock_sources[0] = + dce100_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false); + pool->base.clock_sources[1] = + dce100_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false); + pool->base.clk_src_count = 2; + } + + if (pool->base.dp_clock_source == NULL) { + dm_error("DC: failed to create dp clock source!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] == NULL) { + dm_error("DC: failed to create clock sources!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + } + + pool->base.display_clock = dal_display_clock_dce110_create(ctx); + if (pool->base.display_clock == NULL) { + dm_error("DC: failed to create display clock!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + + /* get static clock information for PPLIB or firmware, save + * max_clock_state + */ + if (dm_pp_get_static_clocks(ctx, &static_clk_info)) { + enum clocks_state max_clocks_state = + dce110_resource_convert_clock_state_pp_to_dc( + static_clk_info.max_clocks_state); + + dal_display_clock_store_max_clocks_state( + pool->base.display_clock, max_clocks_state); + } + { + struct irq_service_init_data init_data; + init_data.ctx = dc->ctx; + pool->base.irqs = dal_irq_service_dce110_create(&init_data); + if (!pool->base.irqs) + goto res_create_fail; + } + + /************************************************* + * Resource + asic cap harcoding * + *************************************************/ + pool->base.underlay_pipe_index = -1; + pool->base.pipe_count = res_cap.num_timing_generator; + dc->public.caps.max_downscale_ratio = 200; + dc->public.caps.i2c_speed_in_khz = 40; + + for (i = 0; i < pool->base.pipe_count; i++) { + pool->base.timing_generators[i] = + dce100_timing_generator_create( + ctx, + i, + &dce100_tg_offsets[i]); + if (pool->base.timing_generators[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create tg!\n"); + goto res_create_fail; + } + + pool->base.mis[i] = dce100_mem_input_create(ctx, i, + &dce100_mi_reg_offsets[i]); + if (pool->base.mis[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create memory input!\n"); + goto res_create_fail; + } + + pool->base.ipps[i] = dce100_ipp_create(ctx, i, + &dce100_ipp_reg_offsets[i]); + if (pool->base.ipps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create input pixel processor!\n"); + goto res_create_fail; + } + + pool->base.transforms[i] = dce100_transform_create(ctx, i); + if (pool->base.transforms[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create transform!\n"); + goto res_create_fail; + } + + pool->base.opps[i] = dce100_opp_create(ctx, i, &dce100_opp_reg_offsets[i]); + if (pool->base.opps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create output pixel processor!\n"); + goto res_create_fail; + } + } + + if (!resource_construct(num_virtual_links, dc, &pool->base, + &res_create_funcs)) + goto res_create_fail; + + /* Create hardware sequencer */ + if (!dce100_hw_sequencer_construct(dc)) + goto res_create_fail; + + return true; + +res_create_fail: + destruct(pool); + + return false; +} + +struct resource_pool *dce100_create_resource_pool( + uint8_t num_virtual_links, + struct core_dc *dc) +{ + struct dce110_resource_pool *pool = + dm_alloc(sizeof(struct dce110_resource_pool)); + + if (!pool) + return NULL; + + if (construct(num_virtual_links, dc, pool)) + return &pool->base; + + BREAK_TO_DEBUGGER(); + return NULL; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h new file mode 100644 index 000000000000..bfd7518c94c9 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h @@ -0,0 +1,19 @@ +/* + * dce100_resource.h + * + * Created on: 2016-01-20 + * Author: qyang + */ + +#ifndef DCE100_RESOURCE_H_ +#define DCE100_RESOURCE_H_ + +struct core_dc; +struct resource_pool; +struct dc_validation_set; + +struct resource_pool *dce100_create_resource_pool( + uint8_t num_virtual_links, + struct core_dc *dc); + +#endif /* DCE100_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/Makefile b/drivers/gpu/drm/amd/display/dc/dce110/Makefile new file mode 100644 index 000000000000..cd7a9095fa06 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/Makefile @@ -0,0 +1,15 @@ +# +# Makefile for the 'controller' sub-component of DAL. +# It provides the control and status of HW CRTC block. + +DCE110 = dce110_ipp.o dce110_ipp_cursor.o \ +dce110_ipp_gamma.o dce110_opp.o dce110_opp_csc.o \ +dce110_timing_generator.o dce110_opp_formatter.o dce110_opp_regamma.o \ +dce110_compressor.o dce110_mem_input.o dce110_hw_sequencer.o \ +dce110_resource.o \ +dce110_opp_regamma_v.o dce110_opp_csc_v.o dce110_timing_generator_v.o \ +dce110_mem_input_v.o dce110_opp_v.o dce110_transform_v.o + +AMD_DAL_DCE110 = $(addprefix $(AMDDALPATH)/dc/dce110/,$(DCE110)) + +AMD_DISPLAY_FILES += $(AMD_DAL_DCE110) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c new file mode 100644 index 000000000000..518150a414e2 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c @@ -0,0 +1,859 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" +#include "gmc/gmc_8_2_sh_mask.h" +#include "gmc/gmc_8_2_d.h" + +#include "include/logger_interface.h" + +#include "dce110_compressor.h" + +#define DCP_REG(reg)\ + (reg + cp110->offsets.dcp_offset) +#define DMIF_REG(reg)\ + (reg + cp110->offsets.dmif_offset) + +static const struct dce110_compressor_reg_offsets reg_offsets[] = { +{ + .dcp_offset = (mmDCP0_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), + .dmif_offset = + (mmDMIF_PG0_DPG_PIPE_DPM_CONTROL + - mmDMIF_PG0_DPG_PIPE_DPM_CONTROL), +}, +{ + .dcp_offset = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), + .dmif_offset = + (mmDMIF_PG1_DPG_PIPE_DPM_CONTROL + - mmDMIF_PG0_DPG_PIPE_DPM_CONTROL), +}, +{ + .dcp_offset = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), + .dmif_offset = + (mmDMIF_PG2_DPG_PIPE_DPM_CONTROL + - mmDMIF_PG0_DPG_PIPE_DPM_CONTROL), +} +}; + +static const uint32_t dce11_one_lpt_channel_max_resolution = 2560 * 1600; + +enum fbc_idle_force { + /* Bit 0 - Display registers updated */ + FBC_IDLE_FORCE_DISPLAY_REGISTER_UPDATE = 0x00000001, + + /* Bit 2 - FBC_GRPH_COMP_EN register updated */ + FBC_IDLE_FORCE_GRPH_COMP_EN = 0x00000002, + /* Bit 3 - FBC_SRC_SEL register updated */ + FBC_IDLE_FORCE_SRC_SEL_CHANGE = 0x00000004, + /* Bit 4 - FBC_MIN_COMPRESSION register updated */ + FBC_IDLE_FORCE_MIN_COMPRESSION_CHANGE = 0x00000008, + /* Bit 5 - FBC_ALPHA_COMP_EN register updated */ + FBC_IDLE_FORCE_ALPHA_COMP_EN = 0x00000010, + /* Bit 6 - FBC_ZERO_ALPHA_CHUNK_SKIP_EN register updated */ + FBC_IDLE_FORCE_ZERO_ALPHA_CHUNK_SKIP_EN = 0x00000020, + /* Bit 7 - FBC_FORCE_COPY_TO_COMP_BUF register updated */ + FBC_IDLE_FORCE_FORCE_COPY_TO_COMP_BUF = 0x00000040, + + /* Bit 24 - Memory write to region 0 defined by MC registers. */ + FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION0 = 0x01000000, + /* Bit 25 - Memory write to region 1 defined by MC registers */ + FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION1 = 0x02000000, + /* Bit 26 - Memory write to region 2 defined by MC registers */ + FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION2 = 0x04000000, + /* Bit 27 - Memory write to region 3 defined by MC registers. */ + FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION3 = 0x08000000, + + /* Bit 28 - Memory write from any client other than MCIF */ + FBC_IDLE_FORCE_MEMORY_WRITE_OTHER_THAN_MCIF = 0x10000000, + /* Bit 29 - CG statics screen signal is inactive */ + FBC_IDLE_FORCE_CG_STATIC_SCREEN_IS_INACTIVE = 0x20000000, +}; + +static uint32_t lpt_size_alignment(struct dce110_compressor *cp110) +{ + /*LPT_ALIGNMENT (in bytes) = ROW_SIZE * #BANKS * # DRAM CHANNELS. */ + return cp110->base.raw_size * cp110->base.banks_num * + cp110->base.dram_channels_num; +} + +static uint32_t lpt_memory_control_config(struct dce110_compressor *cp110, + uint32_t lpt_control) +{ + /*LPT MC Config */ + if (cp110->base.options.bits.LPT_MC_CONFIG == 1) { + /* POSSIBLE VALUES for LPT NUM_PIPES (DRAM CHANNELS): + * 00 - 1 CHANNEL + * 01 - 2 CHANNELS + * 02 - 4 OR 6 CHANNELS + * (Only for discrete GPU, N/A for CZ) + * 03 - 8 OR 12 CHANNELS + * (Only for discrete GPU, N/A for CZ) */ + switch (cp110->base.dram_channels_num) { + case 2: + set_reg_field_value( + lpt_control, + 1, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_NUM_PIPES); + break; + case 1: + set_reg_field_value( + lpt_control, + 0, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_NUM_PIPES); + break; + default: + dm_logger_write( + cp110->base.ctx->logger, LOG_WARNING, + "%s: Invalid LPT NUM_PIPES!!!", + __func__); + break; + } + + /* The mapping for LPT NUM_BANKS is in + * GRPH_CONTROL.GRPH_NUM_BANKS register field + * Specifies the number of memory banks for tiling + * purposes. Only applies to 2D and 3D tiling modes. + * POSSIBLE VALUES: + * 00 - DCP_GRPH_NUM_BANKS_2BANK: ADDR_SURF_2_BANK + * 01 - DCP_GRPH_NUM_BANKS_4BANK: ADDR_SURF_4_BANK + * 02 - DCP_GRPH_NUM_BANKS_8BANK: ADDR_SURF_8_BANK + * 03 - DCP_GRPH_NUM_BANKS_16BANK: ADDR_SURF_16_BANK */ + switch (cp110->base.banks_num) { + case 16: + set_reg_field_value( + lpt_control, + 3, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_NUM_BANKS); + break; + case 8: + set_reg_field_value( + lpt_control, + 2, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_NUM_BANKS); + break; + case 4: + set_reg_field_value( + lpt_control, + 1, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_NUM_BANKS); + break; + case 2: + set_reg_field_value( + lpt_control, + 0, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_NUM_BANKS); + break; + default: + dm_logger_write( + cp110->base.ctx->logger, LOG_WARNING, + "%s: Invalid LPT NUM_BANKS!!!", + __func__); + break; + } + + /* The mapping is in DMIF_ADDR_CALC. + * ADDR_CONFIG_PIPE_INTERLEAVE_SIZE register field for + * Carrizo specifies the memory interleave per pipe. + * It effectively specifies the location of pipe bits in + * the memory address. + * POSSIBLE VALUES: + * 00 - ADDR_CONFIG_PIPE_INTERLEAVE_256B: 256 byte + * interleave + * 01 - ADDR_CONFIG_PIPE_INTERLEAVE_512B: 512 byte + * interleave + */ + switch (cp110->base.channel_interleave_size) { + case 256: /*256B */ + set_reg_field_value( + lpt_control, + 0, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_PIPE_INTERLEAVE_SIZE); + break; + case 512: /*512B */ + set_reg_field_value( + lpt_control, + 1, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_PIPE_INTERLEAVE_SIZE); + break; + default: + dm_logger_write( + cp110->base.ctx->logger, LOG_WARNING, + "%s: Invalid LPT INTERLEAVE_SIZE!!!", + __func__); + break; + } + + /* The mapping for LOW_POWER_TILING_ROW_SIZE is in + * DMIF_ADDR_CALC.ADDR_CONFIG_ROW_SIZE register field + * for Carrizo. Specifies the size of dram row in bytes. + * This should match up with NOOFCOLS field in + * MC_ARB_RAMCFG (ROW_SIZE = 4 * 2 ^^ columns). + * This register DMIF_ADDR_CALC is not used by the + * hardware as it is only used for addrlib assertions. + * POSSIBLE VALUES: + * 00 - ADDR_CONFIG_1KB_ROW: Treat 1KB as DRAM row + * boundary + * 01 - ADDR_CONFIG_2KB_ROW: Treat 2KB as DRAM row + * boundary + * 02 - ADDR_CONFIG_4KB_ROW: Treat 4KB as DRAM row + * boundary */ + switch (cp110->base.raw_size) { + case 4096: /*4 KB */ + set_reg_field_value( + lpt_control, + 2, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_ROW_SIZE); + break; + case 2048: + set_reg_field_value( + lpt_control, + 1, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_ROW_SIZE); + break; + case 1024: + set_reg_field_value( + lpt_control, + 0, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_ROW_SIZE); + break; + default: + dm_logger_write( + cp110->base.ctx->logger, LOG_WARNING, + "%s: Invalid LPT ROW_SIZE!!!", + __func__); + break; + } + } else { + dm_logger_write( + cp110->base.ctx->logger, LOG_WARNING, + "%s: LPT MC Configuration is not provided", + __func__); + } + + return lpt_control; +} + +static bool is_source_bigger_than_epanel_size( + struct dce110_compressor *cp110, + uint32_t source_view_width, + uint32_t source_view_height) +{ + if (cp110->base.embedded_panel_h_size != 0 && + cp110->base.embedded_panel_v_size != 0 && + ((source_view_width * source_view_height) > + (cp110->base.embedded_panel_h_size * + cp110->base.embedded_panel_v_size))) + return true; + + return false; +} + +static uint32_t align_to_chunks_number_per_line( + struct dce110_compressor *cp110, + uint32_t pixels) +{ + return 256 * ((pixels + 255) / 256); +} + +static void wait_for_fbc_state_changed( + struct dce110_compressor *cp110, + bool enabled) +{ + uint8_t counter = 0; + uint32_t addr = mmFBC_STATUS; + uint32_t value; + + while (counter < 10) { + value = dm_read_reg(cp110->base.ctx, addr); + if (get_reg_field_value( + value, + FBC_STATUS, + FBC_ENABLE_STATUS) == enabled) + break; + udelay(10); + counter++; + } + + if (counter == 10) { + dm_logger_write( + cp110->base.ctx->logger, LOG_WARNING, + "%s: wait counter exceeded, changes to HW not applied", + __func__); + } +} + +void dce110_compressor_power_up_fbc(struct compressor *compressor) +{ + uint32_t value; + uint32_t addr; + + addr = mmFBC_CNTL; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value(value, 0, FBC_CNTL, FBC_GRPH_COMP_EN); + set_reg_field_value(value, 1, FBC_CNTL, FBC_EN); + set_reg_field_value(value, 2, FBC_CNTL, FBC_COHERENCY_MODE); + if (compressor->options.bits.CLK_GATING_DISABLED == 1) { + /* HW needs to do power measurement comparison. */ + set_reg_field_value( + value, + 0, + FBC_CNTL, + FBC_COMP_CLK_GATE_EN); + } + dm_write_reg(compressor->ctx, addr, value); + + addr = mmFBC_COMP_MODE; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value(value, 1, FBC_COMP_MODE, FBC_RLE_EN); + set_reg_field_value(value, 1, FBC_COMP_MODE, FBC_DPCM4_RGB_EN); + set_reg_field_value(value, 1, FBC_COMP_MODE, FBC_IND_EN); + dm_write_reg(compressor->ctx, addr, value); + + addr = mmFBC_COMP_CNTL; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value(value, 1, FBC_COMP_CNTL, FBC_DEPTH_RGB08_EN); + dm_write_reg(compressor->ctx, addr, value); + /*FBC_MIN_COMPRESSION 0 ==> 2:1 */ + /* 1 ==> 4:1 */ + /* 2 ==> 8:1 */ + /* 0xF ==> 1:1 */ + set_reg_field_value(value, 0xF, FBC_COMP_CNTL, FBC_MIN_COMPRESSION); + dm_write_reg(compressor->ctx, addr, value); + compressor->min_compress_ratio = FBC_COMPRESS_RATIO_1TO1; + + value = 0; + dm_write_reg(compressor->ctx, mmFBC_IND_LUT0, value); + + value = 0xFFFFFF; + dm_write_reg(compressor->ctx, mmFBC_IND_LUT1, value); +} + +void dce110_compressor_enable_fbc( + struct compressor *compressor, + uint32_t paths_num, + struct compr_addr_and_pitch_params *params) +{ + struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor); + + if (compressor->options.bits.FBC_SUPPORT && + (compressor->options.bits.DUMMY_BACKEND == 0) && + (!dce110_compressor_is_fbc_enabled_in_hw(compressor, NULL)) && + (!is_source_bigger_than_epanel_size( + cp110, + params->source_view_width, + params->source_view_height))) { + + uint32_t addr; + uint32_t value; + + /* Before enabling FBC first need to enable LPT if applicable + * LPT state should always be changed (enable/disable) while FBC + * is disabled */ + if (compressor->options.bits.LPT_SUPPORT && (paths_num < 2) && + (params->source_view_width * + params->source_view_height <= + dce11_one_lpt_channel_max_resolution)) { + dce110_compressor_enable_lpt(compressor); + } + + addr = mmFBC_CNTL; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value(value, 1, FBC_CNTL, FBC_GRPH_COMP_EN); + set_reg_field_value( + value, + params->inst, + FBC_CNTL, FBC_SRC_SEL); + dm_write_reg(compressor->ctx, addr, value); + + /* Keep track of enum controller_id FBC is attached to */ + compressor->is_enabled = true; + compressor->attached_inst = params->inst; + cp110->offsets = reg_offsets[params->inst - 1]; + + /*Toggle it as there is bug in HW */ + set_reg_field_value(value, 0, FBC_CNTL, FBC_GRPH_COMP_EN); + dm_write_reg(compressor->ctx, addr, value); + set_reg_field_value(value, 1, FBC_CNTL, FBC_GRPH_COMP_EN); + dm_write_reg(compressor->ctx, addr, value); + + wait_for_fbc_state_changed(cp110, true); + } +} + +void dce110_compressor_disable_fbc(struct compressor *compressor) +{ + struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor); + + if (compressor->options.bits.FBC_SUPPORT && + dce110_compressor_is_fbc_enabled_in_hw(compressor, NULL)) { + uint32_t reg_data; + /* Turn off compression */ + reg_data = dm_read_reg(compressor->ctx, mmFBC_CNTL); + set_reg_field_value(reg_data, 0, FBC_CNTL, FBC_GRPH_COMP_EN); + dm_write_reg(compressor->ctx, mmFBC_CNTL, reg_data); + + /* Reset enum controller_id to undefined */ + compressor->attached_inst = 0; + compressor->is_enabled = false; + + /* Whenever disabling FBC make sure LPT is disabled if LPT + * supported */ + if (compressor->options.bits.LPT_SUPPORT) + dce110_compressor_disable_lpt(compressor); + + wait_for_fbc_state_changed(cp110, false); + } +} + +bool dce110_compressor_is_fbc_enabled_in_hw( + struct compressor *compressor, + uint32_t *inst) +{ + /* Check the hardware register */ + uint32_t value; + + value = dm_read_reg(compressor->ctx, mmFBC_STATUS); + if (get_reg_field_value(value, FBC_STATUS, FBC_ENABLE_STATUS)) { + if (inst != NULL) + *inst = compressor->attached_inst; + return true; + } + + value = dm_read_reg(compressor->ctx, mmFBC_MISC); + if (get_reg_field_value(value, FBC_MISC, FBC_STOP_ON_HFLIP_EVENT)) { + value = dm_read_reg(compressor->ctx, mmFBC_CNTL); + + if (get_reg_field_value(value, FBC_CNTL, FBC_GRPH_COMP_EN)) { + if (inst != NULL) + *inst = + compressor->attached_inst; + return true; + } + } + return false; +} + +bool dce110_compressor_is_lpt_enabled_in_hw(struct compressor *compressor) +{ + /* Check the hardware register */ + uint32_t value = dm_read_reg(compressor->ctx, + mmLOW_POWER_TILING_CONTROL); + + return get_reg_field_value( + value, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_ENABLE); +} + +void dce110_compressor_program_compressed_surface_address_and_pitch( + struct compressor *compressor, + struct compr_addr_and_pitch_params *params) +{ + struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor); + uint32_t value = 0; + uint32_t fbc_pitch = 0; + uint32_t compressed_surf_address_low_part = + compressor->compr_surface_address.addr.low_part; + + /* Clear content first. */ + dm_write_reg( + compressor->ctx, + DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS_HIGH), + 0); + dm_write_reg(compressor->ctx, + DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS), 0); + + if (compressor->options.bits.LPT_SUPPORT) { + uint32_t lpt_alignment = lpt_size_alignment(cp110); + + if (lpt_alignment != 0) { + compressed_surf_address_low_part = + ((compressed_surf_address_low_part + + (lpt_alignment - 1)) / lpt_alignment) + * lpt_alignment; + } + } + + /* Write address, HIGH has to be first. */ + dm_write_reg(compressor->ctx, + DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS_HIGH), + compressor->compr_surface_address.addr.high_part); + dm_write_reg(compressor->ctx, + DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS), + compressed_surf_address_low_part); + + fbc_pitch = align_to_chunks_number_per_line( + cp110, + params->source_view_width); + + if (compressor->min_compress_ratio == FBC_COMPRESS_RATIO_1TO1) + fbc_pitch = fbc_pitch / 8; + else + dm_logger_write( + compressor->ctx->logger, LOG_WARNING, + "%s: Unexpected DCE11 compression ratio", + __func__); + + /* Clear content first. */ + dm_write_reg(compressor->ctx, DCP_REG(mmGRPH_COMPRESS_PITCH), 0); + + /* Write FBC Pitch. */ + set_reg_field_value( + value, + fbc_pitch, + GRPH_COMPRESS_PITCH, + GRPH_COMPRESS_PITCH); + dm_write_reg(compressor->ctx, DCP_REG(mmGRPH_COMPRESS_PITCH), value); + +} + +void dce110_compressor_disable_lpt(struct compressor *compressor) +{ + struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor); + uint32_t value; + uint32_t addr; + uint32_t inx; + + /* Disable all pipes LPT Stutter */ + for (inx = 0; inx < 3; inx++) { + value = + dm_read_reg( + compressor->ctx, + DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH)); + set_reg_field_value( + value, + 0, + DPG_PIPE_STUTTER_CONTROL_NONLPTCH, + STUTTER_ENABLE_NONLPTCH); + dm_write_reg( + compressor->ctx, + DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH), + value); + } + /* Disable Underlay pipe LPT Stutter */ + addr = mmDPGV0_PIPE_STUTTER_CONTROL_NONLPTCH; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value( + value, + 0, + DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH, + STUTTER_ENABLE_NONLPTCH); + dm_write_reg(compressor->ctx, addr, value); + + /* Disable LPT */ + addr = mmLOW_POWER_TILING_CONTROL; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value( + value, + 0, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_ENABLE); + dm_write_reg(compressor->ctx, addr, value); + + /* Clear selection of Channel(s) containing Compressed Surface */ + addr = mmGMCON_LPT_TARGET; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value( + value, + 0xFFFFFFFF, + GMCON_LPT_TARGET, + STCTRL_LPT_TARGET); + dm_write_reg(compressor->ctx, mmGMCON_LPT_TARGET, value); +} + +void dce110_compressor_enable_lpt(struct compressor *compressor) +{ + struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor); + uint32_t value; + uint32_t addr; + uint32_t value_control; + uint32_t channels; + + /* Enable LPT Stutter from Display pipe */ + value = dm_read_reg(compressor->ctx, + DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH)); + set_reg_field_value( + value, + 1, + DPG_PIPE_STUTTER_CONTROL_NONLPTCH, + STUTTER_ENABLE_NONLPTCH); + dm_write_reg(compressor->ctx, + DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH), value); + + /* Enable Underlay pipe LPT Stutter */ + addr = mmDPGV0_PIPE_STUTTER_CONTROL_NONLPTCH; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value( + value, + 1, + DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH, + STUTTER_ENABLE_NONLPTCH); + dm_write_reg(compressor->ctx, addr, value); + + /* Selection of Channel(s) containing Compressed Surface: 0xfffffff + * will disable LPT. + * STCTRL_LPT_TARGETn corresponds to channel n. */ + addr = mmLOW_POWER_TILING_CONTROL; + value_control = dm_read_reg(compressor->ctx, addr); + channels = get_reg_field_value(value_control, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_MODE); + + addr = mmGMCON_LPT_TARGET; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value( + value, + channels + 1, /* not mentioned in programming guide, + but follow DCE8.1 */ + GMCON_LPT_TARGET, + STCTRL_LPT_TARGET); + dm_write_reg(compressor->ctx, addr, value); + + /* Enable LPT */ + addr = mmLOW_POWER_TILING_CONTROL; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value( + value, + 1, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_ENABLE); + dm_write_reg(compressor->ctx, addr, value); +} + +void dce110_compressor_program_lpt_control( + struct compressor *compressor, + struct compr_addr_and_pitch_params *params) +{ + struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor); + uint32_t rows_per_channel; + uint32_t lpt_alignment; + uint32_t source_view_width; + uint32_t source_view_height; + uint32_t lpt_control = 0; + + if (!compressor->options.bits.LPT_SUPPORT) + return; + + lpt_control = dm_read_reg(compressor->ctx, + mmLOW_POWER_TILING_CONTROL); + + /* POSSIBLE VALUES for Low Power Tiling Mode: + * 00 - Use channel 0 + * 01 - Use Channel 0 and 1 + * 02 - Use Channel 0,1,2,3 + * 03 - reserved */ + switch (compressor->lpt_channels_num) { + /* case 2: + * Use Channel 0 & 1 / Not used for DCE 11 */ + case 1: + /*Use Channel 0 for LPT for DCE 11 */ + set_reg_field_value( + lpt_control, + 0, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_MODE); + break; + default: + dm_logger_write( + compressor->ctx->logger, LOG_WARNING, + "%s: Invalid selected DRAM channels for LPT!!!", + __func__); + break; + } + + lpt_control = lpt_memory_control_config(cp110, lpt_control); + + /* Program LOW_POWER_TILING_ROWS_PER_CHAN field which depends on + * FBC compressed surface pitch. + * LOW_POWER_TILING_ROWS_PER_CHAN = Roundup ((Surface Height * + * Surface Pitch) / (Row Size * Number of Channels * + * Number of Banks)). */ + rows_per_channel = 0; + lpt_alignment = lpt_size_alignment(cp110); + source_view_width = + align_to_chunks_number_per_line( + cp110, + params->source_view_width); + source_view_height = (params->source_view_height + 1) & (~0x1); + + if (lpt_alignment != 0) { + rows_per_channel = source_view_width * source_view_height * 4; + rows_per_channel = + (rows_per_channel % lpt_alignment) ? + (rows_per_channel / lpt_alignment + 1) : + rows_per_channel / lpt_alignment; + } + + set_reg_field_value( + lpt_control, + rows_per_channel, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_ROWS_PER_CHAN); + + dm_write_reg(compressor->ctx, + mmLOW_POWER_TILING_CONTROL, lpt_control); +} + +/* + * DCE 11 Frame Buffer Compression Implementation + */ + +void dce110_compressor_set_fbc_invalidation_triggers( + struct compressor *compressor, + uint32_t fbc_trigger) +{ + /* Disable region hit event, FBC_MEMORY_REGION_MASK = 0 (bits 16-19) + * for DCE 11 regions cannot be used - does not work with S/G + */ + uint32_t addr = mmFBC_CLIENT_REGION_MASK; + uint32_t value = dm_read_reg(compressor->ctx, addr); + + set_reg_field_value( + value, + 0, + FBC_CLIENT_REGION_MASK, + FBC_MEMORY_REGION_MASK); + dm_write_reg(compressor->ctx, addr, value); + + /* Setup events when to clear all CSM entries (effectively marking + * current compressed data invalid) + * For DCE 11 CSM metadata 11111 means - "Not Compressed" + * Used as the initial value of the metadata sent to the compressor + * after invalidation, to indicate that the compressor should attempt + * to compress all chunks on the current pass. Also used when the chunk + * is not successfully written to memory. + * When this CSM value is detected, FBC reads from the uncompressed + * buffer. Set events according to passed in value, these events are + * valid for DCE11: + * - bit 0 - display register updated + * - bit 28 - memory write from any client except from MCIF + * - bit 29 - CG static screen signal is inactive + * In addition, DCE11.1 also needs to set new DCE11.1 specific events + * that are used to trigger invalidation on certain register changes, + * for example enabling of Alpha Compression may trigger invalidation of + * FBC once bit is set. These events are as follows: + * - Bit 2 - FBC_GRPH_COMP_EN register updated + * - Bit 3 - FBC_SRC_SEL register updated + * - Bit 4 - FBC_MIN_COMPRESSION register updated + * - Bit 5 - FBC_ALPHA_COMP_EN register updated + * - Bit 6 - FBC_ZERO_ALPHA_CHUNK_SKIP_EN register updated + * - Bit 7 - FBC_FORCE_COPY_TO_COMP_BUF register updated + */ + addr = mmFBC_IDLE_FORCE_CLEAR_MASK; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value( + value, + fbc_trigger | + FBC_IDLE_FORCE_GRPH_COMP_EN | + FBC_IDLE_FORCE_SRC_SEL_CHANGE | + FBC_IDLE_FORCE_MIN_COMPRESSION_CHANGE | + FBC_IDLE_FORCE_ALPHA_COMP_EN | + FBC_IDLE_FORCE_ZERO_ALPHA_CHUNK_SKIP_EN | + FBC_IDLE_FORCE_FORCE_COPY_TO_COMP_BUF, + FBC_IDLE_FORCE_CLEAR_MASK, + FBC_IDLE_FORCE_CLEAR_MASK); + dm_write_reg(compressor->ctx, addr, value); +} + +bool dce110_compressor_construct(struct dce110_compressor *compressor, + struct dc_context *ctx) +{ + struct dc_bios *bp = ctx->dc_bios; + struct embedded_panel_info panel_info; + + compressor->base.options.bits.FBC_SUPPORT = true; + compressor->base.options.bits.LPT_SUPPORT = true; + /* For DCE 11 always use one DRAM channel for LPT */ + compressor->base.lpt_channels_num = 1; + compressor->base.options.bits.DUMMY_BACKEND = false; + + /* Check if this system has more than 1 DRAM channel; if only 1 then LPT + * should not be supported */ + if (compressor->base.memory_bus_width == 64) + compressor->base.options.bits.LPT_SUPPORT = false; + + compressor->base.options.bits.CLK_GATING_DISABLED = false; + + compressor->base.ctx = ctx; + compressor->base.embedded_panel_h_size = 0; + compressor->base.embedded_panel_v_size = 0; + compressor->base.memory_bus_width = ctx->asic_id.vram_width; + compressor->base.allocated_size = 0; + compressor->base.preferred_requested_size = 0; + compressor->base.min_compress_ratio = FBC_COMPRESS_RATIO_INVALID; + compressor->base.options.raw = 0; + compressor->base.banks_num = 0; + compressor->base.raw_size = 0; + compressor->base.channel_interleave_size = 0; + compressor->base.dram_channels_num = 0; + compressor->base.lpt_channels_num = 0; + compressor->base.attached_inst = 0; + compressor->base.is_enabled = false; + + if (BP_RESULT_OK == + bp->funcs->get_embedded_panel_info(bp, &panel_info)) { + compressor->base.embedded_panel_h_size = + panel_info.lcd_timing.horizontal_addressable; + compressor->base.embedded_panel_v_size = + panel_info.lcd_timing.vertical_addressable; + } + return true; +} + +struct compressor *dce110_compressor_create(struct dc_context *ctx) +{ + struct dce110_compressor *cp110 = + dm_alloc(sizeof(struct dce110_compressor)); + + if (!cp110) + return NULL; + + if (dce110_compressor_construct(cp110, ctx)) + return &cp110->base; + + BREAK_TO_DEBUGGER(); + dm_free(cp110); + return NULL; +} + +void dce110_compressor_destroy(struct compressor **compressor) +{ + dm_free(TO_DCE110_COMPRESSOR(*compressor)); + *compressor = NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.h new file mode 100644 index 000000000000..22af5be51581 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.h @@ -0,0 +1,78 @@ +/* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_COMPRESSOR_DCE110_H__ +#define __DC_COMPRESSOR_DCE110_H__ + +#include "../inc/compressor.h" + +#define TO_DCE110_COMPRESSOR(compressor)\ + container_of(compressor, struct dce110_compressor, base) + +struct dce110_compressor_reg_offsets { + uint32_t dcp_offset; + uint32_t dmif_offset; +}; + +struct dce110_compressor { + struct compressor base; + struct dce110_compressor_reg_offsets offsets; +}; + +struct compressor *dce110_compressor_create(struct dc_context *ctx); + +bool dce110_compressor_construct(struct dce110_compressor *cp110, + struct dc_context *ctx); + +void dce110_compressor_destroy(struct compressor **cp); + +/* FBC RELATED */ +void dce110_compressor_power_up_fbc(struct compressor *cp); + +void dce110_compressor_enable_fbc(struct compressor *cp, uint32_t paths_num, + struct compr_addr_and_pitch_params *params); + +void dce110_compressor_disable_fbc(struct compressor *cp); + +void dce110_compressor_set_fbc_invalidation_triggers(struct compressor *cp, + uint32_t fbc_trigger); + +void dce110_compressor_program_compressed_surface_address_and_pitch( + struct compressor *cp, + struct compr_addr_and_pitch_params *params); + +bool dce110_compressor_is_fbc_enabled_in_hw(struct compressor *cp, + uint32_t *fbc_mapped_crtc_id); + +/* LPT RELATED */ +void dce110_compressor_enable_lpt(struct compressor *cp); + +void dce110_compressor_disable_lpt(struct compressor *cp); + +void dce110_compressor_program_lpt_control(struct compressor *cp, + struct compr_addr_and_pitch_params *params); + +bool dce110_compressor_is_lpt_enabled_in_hw(struct compressor *cp); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c new file mode 100644 index 000000000000..1a682996b531 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -0,0 +1,1978 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#include "dm_services.h" +#include "dc.h" +#include "dc_bios_types.h" +#include "core_types.h" +#include "core_status.h" +#include "resource.h" +#include "hw_sequencer.h" +#include "dm_helpers.h" +#include "dce110_hw_sequencer.h" +#include "dce110_timing_generator.h" + +#include "bios/bios_parser_helper.h" +#include "timing_generator.h" +#include "mem_input.h" +#include "opp.h" +#include "ipp.h" +#include "transform.h" +#include "stream_encoder.h" +#include "link_encoder.h" +#include "clock_source.h" +#include "gamma_calcs.h" +#include "audio.h" +#include "dce/dce_hwseq.h" + +/* include DCE11 register header files */ +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" + +struct dce110_hw_seq_reg_offsets { + uint32_t crtc; +}; + +static const struct dce110_hw_seq_reg_offsets reg_offsets[] = { +{ + .crtc = (mmCRTC0_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), +}, +{ + .crtc = (mmCRTC1_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), +}, +{ + .crtc = (mmCRTC2_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), +}, +{ + .crtc = (mmCRTCV_GSL_CONTROL - mmCRTC_GSL_CONTROL), +} +}; + +#define HW_REG_BLND(reg, id)\ + (reg + reg_offsets[id].blnd) + +#define HW_REG_CRTC(reg, id)\ + (reg + reg_offsets[id].crtc) + +#define MAX_WATERMARK 0xFFFF +#define SAFE_NBP_MARK 0x7FFF + +/******************************************************************************* + * Private definitions + ******************************************************************************/ +/***************************PIPE_CONTROL***********************************/ +static void dce110_init_pte(struct dc_context *ctx) +{ + uint32_t addr; + uint32_t value = 0; + uint32_t chunk_int = 0; + uint32_t chunk_mul = 0; + + addr = mmUNP_DVMM_PTE_CONTROL; + value = dm_read_reg(ctx, addr); + + set_reg_field_value( + value, + 0, + DVMM_PTE_CONTROL, + DVMM_USE_SINGLE_PTE); + + set_reg_field_value( + value, + 1, + DVMM_PTE_CONTROL, + DVMM_PTE_BUFFER_MODE0); + + set_reg_field_value( + value, + 1, + DVMM_PTE_CONTROL, + DVMM_PTE_BUFFER_MODE1); + + dm_write_reg(ctx, addr, value); + + addr = mmDVMM_PTE_REQ; + value = dm_read_reg(ctx, addr); + + chunk_int = get_reg_field_value( + value, + DVMM_PTE_REQ, + HFLIP_PTEREQ_PER_CHUNK_INT); + + chunk_mul = get_reg_field_value( + value, + DVMM_PTE_REQ, + HFLIP_PTEREQ_PER_CHUNK_MULTIPLIER); + + if (chunk_int != 0x4 || chunk_mul != 0x4) { + + set_reg_field_value( + value, + 255, + DVMM_PTE_REQ, + MAX_PTEREQ_TO_ISSUE); + + set_reg_field_value( + value, + 4, + DVMM_PTE_REQ, + HFLIP_PTEREQ_PER_CHUNK_INT); + + set_reg_field_value( + value, + 4, + DVMM_PTE_REQ, + HFLIP_PTEREQ_PER_CHUNK_MULTIPLIER); + + dm_write_reg(ctx, addr, value); + } +} +/**************************************************************************/ + +static void enable_display_pipe_clock_gating( + struct dc_context *ctx, + bool clock_gating) +{ + /*TODO*/ +} + +static bool dce110_enable_display_power_gating( + struct core_dc *dc, + uint8_t controller_id, + struct dc_bios *dcb, + enum pipe_gating_control power_gating) +{ + enum bp_result bp_result = BP_RESULT_OK; + enum bp_pipe_control_action cntl; + struct dc_context *ctx = dc->ctx; + unsigned int underlay_idx = dc->res_pool->underlay_pipe_index; + + if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment)) + return true; + + if (power_gating == PIPE_GATING_CONTROL_INIT) + cntl = ASIC_PIPE_INIT; + else if (power_gating == PIPE_GATING_CONTROL_ENABLE) + cntl = ASIC_PIPE_ENABLE; + else + cntl = ASIC_PIPE_DISABLE; + + if (controller_id == underlay_idx) + controller_id = CONTROLLER_ID_UNDERLAY0 - 1; + + if (power_gating != PIPE_GATING_CONTROL_INIT || controller_id == 0){ + + bp_result = dcb->funcs->enable_disp_power_gating( + dcb, controller_id + 1, cntl); + + /* Revert MASTER_UPDATE_MODE to 0 because bios sets it 2 + * by default when command table is called + * + * Bios parser accepts controller_id = 6 as indicative of + * underlay pipe in dce110. But we do not support more + * than 3. + */ + if (controller_id < CONTROLLER_ID_MAX - 1) + dm_write_reg(ctx, + HW_REG_CRTC(mmCRTC_MASTER_UPDATE_MODE, controller_id), + 0); + } + + if (power_gating != PIPE_GATING_CONTROL_ENABLE) + dce110_init_pte(ctx); + + if (bp_result == BP_RESULT_OK) + return true; + else + return false; +} + +static void build_prescale_params(struct ipp_prescale_params *prescale_params, + const struct core_surface *surface) +{ + prescale_params->mode = IPP_PRESCALE_MODE_FIXED_UNSIGNED; + + switch (surface->public.format) { + case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: + case SURFACE_PIXEL_FORMAT_GRPH_BGRA8888: + prescale_params->scale = 0x2020; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: + prescale_params->scale = 0x2008; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: + prescale_params->scale = 0x2000; + break; + default: + ASSERT(false); + } +} + +static bool set_gamma_ramp( + struct input_pixel_processor *ipp, + struct output_pixel_processor *opp, + const struct core_gamma *ramp, + const struct core_surface *surface) +{ + struct ipp_prescale_params prescale_params = { 0 }; + struct pwl_params *regamma_params; + bool result = false; + + regamma_params = dm_alloc(sizeof(struct pwl_params)); + if (regamma_params == NULL) + goto regamma_alloc_fail; + + regamma_params->hw_points_num = GAMMA_HW_POINTS_NUM; + + opp->funcs->opp_power_on_regamma_lut(opp, true); + + if (ipp) { + build_prescale_params(&prescale_params, surface); + ipp->funcs->ipp_program_prescale(ipp, &prescale_params); + } + + if (ramp && calculate_regamma_params(regamma_params, ramp, surface)) { + + opp->funcs->opp_program_regamma_pwl(opp, regamma_params); + if (ipp) + ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_HW_sRGB); + opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_USER); + } else { + if (ipp) + ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS); + opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_BYPASS); + } + + opp->funcs->opp_power_on_regamma_lut(opp, false); + + result = true; + + dm_free(regamma_params); + +regamma_alloc_fail: + return result; +} + +static enum dc_status bios_parser_crtc_source_select( + struct pipe_ctx *pipe_ctx) +{ + struct dc_bios *dcb; + /* call VBIOS table to set CRTC source for the HW + * encoder block + * note: video bios clears all FMT setting here. */ + struct bp_crtc_source_select crtc_source_select = {0}; + const struct core_sink *sink = pipe_ctx->stream->sink; + + crtc_source_select.engine_id = pipe_ctx->stream_enc->id; + crtc_source_select.controller_id = pipe_ctx->pipe_idx + 1; + /*TODO: Need to un-hardcode color depth, dp_audio and account for + * the case where signal and sink signal is different (translator + * encoder)*/ + crtc_source_select.signal = pipe_ctx->stream->signal; + crtc_source_select.enable_dp_audio = false; + crtc_source_select.sink_signal = pipe_ctx->stream->signal; + crtc_source_select.display_output_bit_depth = PANEL_8BIT_COLOR; + + dcb = sink->ctx->dc_bios; + + if (BP_RESULT_OK != dcb->funcs->crtc_source_select( + dcb, + &crtc_source_select)) { + return DC_ERROR_UNEXPECTED; + } + + return DC_OK; +} + +void dce110_update_info_frame(struct pipe_ctx *pipe_ctx) +{ + if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) + pipe_ctx->stream_enc->funcs->update_hdmi_info_packets( + pipe_ctx->stream_enc, + &pipe_ctx->encoder_info_frame); + else if (dc_is_dp_signal(pipe_ctx->stream->signal)) + pipe_ctx->stream_enc->funcs->update_dp_info_packets( + pipe_ctx->stream_enc, + &pipe_ctx->encoder_info_frame); +} + +void dce110_enable_stream(struct pipe_ctx *pipe_ctx) +{ + enum dc_lane_count lane_count = + pipe_ctx->stream->sink->link->public.cur_link_settings.lane_count; + + struct dc_crtc_timing *timing = &pipe_ctx->stream->public.timing; + struct core_link *link = pipe_ctx->stream->sink->link; + + /* 1. update AVI info frame (HDMI, DP) + * we always need to update info frame + */ + uint32_t active_total_with_borders; + uint32_t early_control = 0; + struct timing_generator *tg = pipe_ctx->tg; + + /* TODOFPGA may change to hwss.update_info_frame */ + dce110_update_info_frame(pipe_ctx); + /* enable early control to avoid corruption on DP monitor*/ + active_total_with_borders = + timing->h_addressable + + timing->h_border_left + + timing->h_border_right; + + if (lane_count != 0) + early_control = active_total_with_borders % lane_count; + + if (early_control == 0) + early_control = lane_count; + + tg->funcs->set_early_control(tg, early_control); + + /* enable audio only within mode set */ + if (pipe_ctx->audio != NULL) { + if (dc_is_dp_signal(pipe_ctx->stream->signal)) + pipe_ctx->stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_enc); + } + + /* For MST, there are multiply stream go to only one link. + * connect DIG back_end to front_end while enable_stream and + * disconnect them during disable_stream + * BY this, it is logic clean to separate stream and link */ + link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc, + pipe_ctx->stream_enc->id, true); + +} + +void dce110_disable_stream(struct pipe_ctx *pipe_ctx) +{ + struct core_stream *stream = pipe_ctx->stream; + struct core_link *link = stream->sink->link; + + if (pipe_ctx->audio) { + pipe_ctx->audio->funcs->az_disable(pipe_ctx->audio); + + if (dc_is_dp_signal(pipe_ctx->stream->signal)) + pipe_ctx->stream_enc->funcs->dp_audio_disable( + pipe_ctx->stream_enc); + else + pipe_ctx->stream_enc->funcs->hdmi_audio_disable( + pipe_ctx->stream_enc); + + pipe_ctx->audio = NULL; + + /* TODO: notify audio driver for if audio modes list changed + * add audio mode list change flag */ + /* dal_audio_disable_azalia_audio_jack_presence(stream->audio, + * stream->stream_engine_id); + */ + } + + if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) + pipe_ctx->stream_enc->funcs->stop_hdmi_info_packets( + pipe_ctx->stream_enc); + + if (dc_is_dp_signal(pipe_ctx->stream->signal)) + pipe_ctx->stream_enc->funcs->stop_dp_info_packets( + pipe_ctx->stream_enc); + + pipe_ctx->stream_enc->funcs->audio_mute_control( + pipe_ctx->stream_enc, true); + + + /* blank at encoder level */ + if (dc_is_dp_signal(pipe_ctx->stream->signal)) + pipe_ctx->stream_enc->funcs->dp_blank(pipe_ctx->stream_enc); + + link->link_enc->funcs->connect_dig_be_to_fe( + link->link_enc, + pipe_ctx->stream_enc->id, + false); + +} + +void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, + struct dc_link_settings *link_settings) +{ + struct encoder_unblank_param params = { { 0 } }; + + /* only 3 items below are used by unblank */ + params.crtc_timing.pixel_clock = + pipe_ctx->stream->public.timing.pix_clk_khz; + params.link_settings.link_rate = link_settings->link_rate; + pipe_ctx->stream_enc->funcs->dp_unblank(pipe_ctx->stream_enc, ¶ms); +} + +static enum audio_dto_source translate_to_dto_source(enum controller_id crtc_id) +{ + switch (crtc_id) { + case CONTROLLER_ID_D0: + return DTO_SOURCE_ID0; + case CONTROLLER_ID_D1: + return DTO_SOURCE_ID1; + case CONTROLLER_ID_D2: + return DTO_SOURCE_ID2; + case CONTROLLER_ID_D3: + return DTO_SOURCE_ID3; + case CONTROLLER_ID_D4: + return DTO_SOURCE_ID4; + case CONTROLLER_ID_D5: + return DTO_SOURCE_ID5; + default: + return DTO_SOURCE_UNKNOWN; + } +} + +static void build_audio_output( + const struct pipe_ctx *pipe_ctx, + struct audio_output *audio_output) +{ + const struct core_stream *stream = pipe_ctx->stream; + audio_output->engine_id = pipe_ctx->stream_enc->id; + + audio_output->signal = pipe_ctx->stream->signal; + + /* audio_crtc_info */ + + audio_output->crtc_info.h_total = + stream->public.timing.h_total; + + /* + * Audio packets are sent during actual CRTC blank physical signal, we + * need to specify actual active signal portion + */ + audio_output->crtc_info.h_active = + stream->public.timing.h_addressable + + stream->public.timing.h_border_left + + stream->public.timing.h_border_right; + + audio_output->crtc_info.v_active = + stream->public.timing.v_addressable + + stream->public.timing.v_border_top + + stream->public.timing.v_border_bottom; + + audio_output->crtc_info.pixel_repetition = 1; + + audio_output->crtc_info.interlaced = + stream->public.timing.flags.INTERLACE; + + audio_output->crtc_info.refresh_rate = + (stream->public.timing.pix_clk_khz*1000)/ + (stream->public.timing.h_total*stream->public.timing.v_total); + + audio_output->crtc_info.color_depth = + stream->public.timing.display_color_depth; + + audio_output->crtc_info.requested_pixel_clock = + pipe_ctx->pix_clk_params.requested_pix_clk; + + /* + * TODO - Investigate why calculated pixel clk has to be + * requested pixel clk + */ + audio_output->crtc_info.calculated_pixel_clock = + pipe_ctx->pix_clk_params.requested_pix_clk; + + if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT || + pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { + audio_output->pll_info.dp_dto_source_clock_in_khz = + dal_display_clock_get_dp_ref_clk_frequency( + pipe_ctx->dis_clk); + } + + audio_output->pll_info.feed_back_divider = + pipe_ctx->pll_settings.feedback_divider; + + audio_output->pll_info.dto_source = + translate_to_dto_source( + pipe_ctx->pipe_idx + 1); + + /* TODO hard code to enable for now. Need get from stream */ + audio_output->pll_info.ss_enabled = true; + + audio_output->pll_info.ss_percentage = + pipe_ctx->pll_settings.ss_percentage; +} + +static void get_surface_visual_confirm_color(const struct pipe_ctx *pipe_ctx, + struct tg_color *color) +{ + uint32_t color_value = MAX_TG_COLOR_VALUE * (4 - pipe_ctx->pipe_idx) / 4; + + switch (pipe_ctx->scl_data.format) { + case PIXEL_FORMAT_ARGB8888: + /* set boarder color to red */ + color->color_r_cr = color_value; + break; + + case PIXEL_FORMAT_ARGB2101010: + /* set boarder color to blue */ + color->color_b_cb = color_value; + break; + case PIXEL_FORMAT_420BPP12: + /* set boarder color to green */ + color->color_g_y = color_value; + break; + case PIXEL_FORMAT_FP16: + /* set boarder color to white */ + color->color_r_cr = color_value; + color->color_b_cb = color_value; + color->color_g_y = color_value; + break; + default: + break; + } +} + +static void program_scaler(const struct core_dc *dc, + const struct pipe_ctx *pipe_ctx) +{ + struct tg_color color = {0}; + + if (dc->public.debug.surface_visual_confirm) + get_surface_visual_confirm_color(pipe_ctx, &color); + else + color_space_to_black_color(dc, + pipe_ctx->stream->public.output_color_space, + &color); + + pipe_ctx->xfm->funcs->transform_set_pixel_storage_depth( + pipe_ctx->xfm, + pipe_ctx->scl_data.lb_params.depth, + &pipe_ctx->stream->bit_depth_params); + + if (pipe_ctx->tg->funcs->set_overscan_blank_color) + pipe_ctx->tg->funcs->set_overscan_blank_color( + pipe_ctx->tg, + &color); + + pipe_ctx->xfm->funcs->transform_set_scaler(pipe_ctx->xfm, + &pipe_ctx->scl_data); +} + +static enum dc_status prog_pixclk_crtc_otg( + struct pipe_ctx *pipe_ctx, + struct validate_context *context, + struct core_dc *dc) +{ + struct core_stream *stream = pipe_ctx->stream; + struct pipe_ctx *pipe_ctx_old = &dc->current_context->res_ctx. + pipe_ctx[pipe_ctx->pipe_idx]; + struct tg_color black_color = {0}; + + if (!pipe_ctx_old->stream) { + + /* program blank color */ + color_space_to_black_color(dc, + stream->public.output_color_space, &black_color); + pipe_ctx->tg->funcs->set_blank_color( + pipe_ctx->tg, + &black_color); + /* + * Must blank CRTC after disabling power gating and before any + * programming, otherwise CRTC will be hung in bad state + */ + pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, true); + + if (false == pipe_ctx->clock_source->funcs->program_pix_clk( + pipe_ctx->clock_source, + &pipe_ctx->pix_clk_params, + &pipe_ctx->pll_settings)) { + BREAK_TO_DEBUGGER(); + return DC_ERROR_UNEXPECTED; + } + + pipe_ctx->tg->funcs->program_timing( + pipe_ctx->tg, + &stream->public.timing, + true); + } + + if (!pipe_ctx_old->stream) { + if (false == pipe_ctx->tg->funcs->enable_crtc( + pipe_ctx->tg)) { + BREAK_TO_DEBUGGER(); + return DC_ERROR_UNEXPECTED; + } + } + + return DC_OK; +} + +static enum dc_status apply_single_controller_ctx_to_hw( + struct pipe_ctx *pipe_ctx, + struct validate_context *context, + struct core_dc *dc) +{ + struct core_stream *stream = pipe_ctx->stream; + struct pipe_ctx *pipe_ctx_old = &dc->current_context->res_ctx. + pipe_ctx[pipe_ctx->pipe_idx]; + + /* */ + dc->hwss.prog_pixclk_crtc_otg(pipe_ctx, context, dc); + + pipe_ctx->opp->funcs->opp_set_dyn_expansion( + pipe_ctx->opp, + COLOR_SPACE_YCBCR601, + stream->public.timing.display_color_depth, + pipe_ctx->stream->signal); + + pipe_ctx->opp->funcs->opp_program_fmt( + pipe_ctx->opp, + &stream->bit_depth_params, + &stream->clamping); + + /* FPGA does not program backend */ + if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) + return DC_OK; + + /* TODO: move to stream encoder */ + if (pipe_ctx->stream->signal != SIGNAL_TYPE_VIRTUAL) + if (DC_OK != bios_parser_crtc_source_select(pipe_ctx)) { + BREAK_TO_DEBUGGER(); + return DC_ERROR_UNEXPECTED; + } + + if (pipe_ctx->stream->signal != SIGNAL_TYPE_VIRTUAL) + stream->sink->link->link_enc->funcs->setup( + stream->sink->link->link_enc, + pipe_ctx->stream->signal); + + if (dc_is_dp_signal(pipe_ctx->stream->signal)) + pipe_ctx->stream_enc->funcs->dp_set_stream_attribute( + pipe_ctx->stream_enc, + &stream->public.timing, + stream->public.output_color_space); + + if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) + pipe_ctx->stream_enc->funcs->hdmi_set_stream_attribute( + pipe_ctx->stream_enc, + &stream->public.timing, + stream->phy_pix_clk, + pipe_ctx->audio != NULL); + + if (dc_is_dvi_signal(pipe_ctx->stream->signal)) + pipe_ctx->stream_enc->funcs->dvi_set_stream_attribute( + pipe_ctx->stream_enc, + &stream->public.timing, + (pipe_ctx->stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK) ? + true : false); + + if (!pipe_ctx_old->stream) { + core_link_enable_stream(pipe_ctx); + + if (dc_is_dp_signal(pipe_ctx->stream->signal)) + dce110_unblank_stream(pipe_ctx, + &stream->sink->link->public.cur_link_settings); + } + + pipe_ctx->scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; + /* program_scaler and allocate_mem_input are not new asic */ + if (!pipe_ctx_old || memcmp(&pipe_ctx_old->scl_data, + &pipe_ctx->scl_data, + sizeof(struct scaler_data)) != 0) + program_scaler(dc, pipe_ctx); + + /* mst support - use total stream count */ + pipe_ctx->mi->funcs->allocate_mem_input( + pipe_ctx->mi, + stream->public.timing.h_total, + stream->public.timing.v_total, + stream->public.timing.pix_clk_khz, + context->target_count); + + return DC_OK; +} + +/******************************************************************************/ + +static void power_down_encoders(struct core_dc *dc) +{ + int i; + + for (i = 0; i < dc->link_count; i++) { + dc->links[i]->link_enc->funcs->disable_output( + dc->links[i]->link_enc, SIGNAL_TYPE_NONE); + } +} + +static void power_down_controllers(struct core_dc *dc) +{ + int i; + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + dc->res_pool->timing_generators[i]->funcs->disable_crtc( + dc->res_pool->timing_generators[i]); + } +} + +static void power_down_clock_sources(struct core_dc *dc) +{ + int i; + + if (dc->res_pool->dp_clock_source->funcs->cs_power_down( + dc->res_pool->dp_clock_source) == false) + dm_error("Failed to power down pll! (dp clk src)\n"); + + for (i = 0; i < dc->res_pool->clk_src_count; i++) { + if (dc->res_pool->clock_sources[i]->funcs->cs_power_down( + dc->res_pool->clock_sources[i]) == false) + dm_error("Failed to power down pll! (clk src index=%d)\n", i); + } +} + +static void power_down_all_hw_blocks(struct core_dc *dc) +{ + power_down_encoders(dc); + + power_down_controllers(dc); + + power_down_clock_sources(dc); +} + +static void disable_vga_and_power_gate_all_controllers( + struct core_dc *dc) +{ + int i; + struct timing_generator *tg; + struct dc_context *ctx = dc->ctx; + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + tg = dc->res_pool->timing_generators[i]; + + tg->funcs->disable_vga(tg); + + /* Enable CLOCK gating for each pipe BEFORE controller + * powergating. */ + enable_display_pipe_clock_gating(ctx, + true); + + dc->hwss.power_down_front_end( + dc, &dc->current_context->res_ctx.pipe_ctx[i]); + } +} + +/** + * When ASIC goes from VBIOS/VGA mode to driver/accelerated mode we need: + * 1. Power down all DC HW blocks + * 2. Disable VGA engine on all controllers + * 3. Enable power gating for controller + * 4. Set acc_mode_change bit (VBIOS will clear this bit when going to FSDOS) + */ +void dce110_enable_accelerated_mode(struct core_dc *dc) +{ + power_down_all_hw_blocks(dc); + + disable_vga_and_power_gate_all_controllers(dc); + bios_set_scratch_acc_mode_change(dc->ctx->dc_bios); +} + +/** + * Call display_engine_clock_dce80 to perform the Dclk programming. + */ +void dce110_set_display_clock(struct validate_context *context) +{ + /* Program the display engine clock. + * Check DFS bypass mode support or not. DFSbypass feature is only when + * BIOS GPU info table reports support. */ + + if (/*dal_adapter_service_is_dfs_bypass_enabled()*/ false) { + /*TODO: set_display_clock_dfs_bypass( + hws, + path_set, + context->res_ctx.pool->display_clock, + context->res_ctx.min_clocks.min_dclk_khz);*/ + } else { + /* + * TODO: need to either port work around from DAL2 function + * getActualRequiredDisplayClock or program displayclock without + * calling vbios. Currently temporily work + * around by increasing the displclk by 15 percent + */ + dal_display_clock_set_clock( + context->res_ctx.pool->display_clock, + context->bw_results.dispclk_khz * 115 / 100); + } + + + /* TODO: When changing display engine clock, DMCU WaitLoop must be + * reconfigured in order to maintain the same delays within DMCU + * programming sequences. */ +} + +static uint32_t compute_pstate_blackout_duration( + struct bw_fixed blackout_duration, + const struct core_stream *stream) +{ + uint32_t total_dest_line_time_ns; + uint32_t pstate_blackout_duration_ns; + + pstate_blackout_duration_ns = 1000 * blackout_duration.value >> 24; + + total_dest_line_time_ns = 1000000UL * + stream->public.timing.h_total / + stream->public.timing.pix_clk_khz + + pstate_blackout_duration_ns; + + return total_dest_line_time_ns; +} + +/* get the index of the pipe_ctx if there were no gaps in the pipe_ctx array*/ +int get_bw_result_idx( + struct resource_context *res_ctx, + int pipe_idx) +{ + int i, collapsed_idx; + + if (res_ctx->pipe_ctx[pipe_idx].top_pipe) + return 3; + + collapsed_idx = 0; + for (i = 0; i < pipe_idx; i++) { + if (res_ctx->pipe_ctx[i].stream) + collapsed_idx++; + } + + return collapsed_idx; +} + +static bool is_watermark_set_a_greater( + const struct bw_watermarks *set_a, + const struct bw_watermarks *set_b) +{ + if (set_a->a_mark > set_b->a_mark + || set_a->b_mark > set_b->b_mark + || set_a->c_mark > set_b->c_mark + || set_a->d_mark > set_b->d_mark) + return true; + return false; +} + +static bool did_watermarks_increase( + struct pipe_ctx *pipe_ctx, + struct validate_context *context, + struct validate_context *old_context) +{ + int collapsed_pipe_idx = get_bw_result_idx(&context->res_ctx, + pipe_ctx->pipe_idx); + int old_collapsed_pipe_idx = get_bw_result_idx(&old_context->res_ctx, + pipe_ctx->pipe_idx); + struct pipe_ctx *old_pipe_ctx = &old_context->res_ctx.pipe_ctx[pipe_ctx->pipe_idx]; + + if (!old_pipe_ctx->stream) + return true; + + if (is_watermark_set_a_greater( + &context->bw_results.nbp_state_change_wm_ns[collapsed_pipe_idx], + &old_context->bw_results.nbp_state_change_wm_ns[old_collapsed_pipe_idx])) + return true; + if (is_watermark_set_a_greater( + &context->bw_results.stutter_exit_wm_ns[collapsed_pipe_idx], + &old_context->bw_results.stutter_exit_wm_ns[old_collapsed_pipe_idx])) + return true; + if (is_watermark_set_a_greater( + &context->bw_results.urgent_wm_ns[collapsed_pipe_idx], + &old_context->bw_results.urgent_wm_ns[old_collapsed_pipe_idx])) + return true; + + return false; +} + +static void program_wm_for_pipe(struct core_dc *dc, + struct pipe_ctx *pipe_ctx, + struct validate_context *context) +{ + int total_dest_line_time_ns = compute_pstate_blackout_duration( + dc->bw_vbios.blackout_duration, + pipe_ctx->stream); + int bw_result_idx = get_bw_result_idx(&context->res_ctx, + pipe_ctx->pipe_idx); + + pipe_ctx->mi->funcs->mem_input_program_display_marks( + pipe_ctx->mi, + context->bw_results.nbp_state_change_wm_ns[bw_result_idx], + context->bw_results.stutter_exit_wm_ns[bw_result_idx], + context->bw_results.urgent_wm_ns[bw_result_idx], + total_dest_line_time_ns); + + if (pipe_ctx->top_pipe) + pipe_ctx->mi->funcs->mem_input_program_chroma_display_marks( + pipe_ctx->mi, + context->bw_results.nbp_state_change_wm_ns[bw_result_idx + 1], + context->bw_results.stutter_exit_wm_ns[bw_result_idx + 1], + context->bw_results.urgent_wm_ns[bw_result_idx + 1], + total_dest_line_time_ns); +} + +void dce110_set_displaymarks( + const struct core_dc *dc, + struct validate_context *context) +{ + uint8_t i, num_pipes; + unsigned int underlay_idx = dc->res_pool->underlay_pipe_index; + + for (i = 0, num_pipes = 0; i < MAX_PIPES; i++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + uint32_t total_dest_line_time_ns; + + if (pipe_ctx->stream == NULL) + continue; + + total_dest_line_time_ns = compute_pstate_blackout_duration( + dc->bw_vbios.blackout_duration, pipe_ctx->stream); + pipe_ctx->mi->funcs->mem_input_program_display_marks( + pipe_ctx->mi, + context->bw_results.nbp_state_change_wm_ns[num_pipes], + context->bw_results.stutter_exit_wm_ns[num_pipes], + context->bw_results.urgent_wm_ns[num_pipes], + total_dest_line_time_ns); + if (i == underlay_idx) { + num_pipes++; + pipe_ctx->mi->funcs->mem_input_program_chroma_display_marks( + pipe_ctx->mi, + context->bw_results.nbp_state_change_wm_ns[num_pipes], + context->bw_results.stutter_exit_wm_ns[num_pipes], + context->bw_results.urgent_wm_ns[num_pipes], + total_dest_line_time_ns); + } + num_pipes++; + } +} + +static void set_safe_displaymarks(struct resource_context *res_ctx) +{ + int i; + int underlay_idx = res_ctx->pool->underlay_pipe_index; + struct bw_watermarks max_marks = { + MAX_WATERMARK, MAX_WATERMARK, MAX_WATERMARK, MAX_WATERMARK }; + struct bw_watermarks nbp_marks = { + SAFE_NBP_MARK, SAFE_NBP_MARK, SAFE_NBP_MARK, SAFE_NBP_MARK }; + + for (i = 0; i < MAX_PIPES; i++) { + if (res_ctx->pipe_ctx[i].stream == NULL) + continue; + + res_ctx->pipe_ctx[i].mi->funcs->mem_input_program_display_marks( + res_ctx->pipe_ctx[i].mi, + nbp_marks, + max_marks, + max_marks, + MAX_WATERMARK); + if (i == underlay_idx) + res_ctx->pipe_ctx[i].mi->funcs->mem_input_program_chroma_display_marks( + res_ctx->pipe_ctx[i].mi, + nbp_marks, + max_marks, + max_marks, + MAX_WATERMARK); + } +} + +static void switch_dp_clock_sources( + const struct core_dc *dc, + struct resource_context *res_ctx) +{ + uint8_t i; + for (i = 0; i < MAX_PIPES; i++) { + struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; + + if (pipe_ctx->stream == NULL || pipe_ctx->top_pipe) + continue; + + if (dc_is_dp_signal(pipe_ctx->stream->signal)) { + struct clock_source *clk_src = + resource_find_used_clk_src_for_sharing( + res_ctx, pipe_ctx); + + if (clk_src && + clk_src != pipe_ctx->clock_source) { + resource_unreference_clock_source( + res_ctx, pipe_ctx->clock_source); + pipe_ctx->clock_source = clk_src; + resource_reference_clock_source(res_ctx, clk_src); + + dce_crtc_switch_to_clk_src(dc->hwseq, clk_src, i); + } + } + } +} + +/******************************************************************************* + * Public functions + ******************************************************************************/ + +static void reset_single_pipe_hw_ctx( + const struct core_dc *dc, + struct pipe_ctx *pipe_ctx, + struct validate_context *context) +{ + core_link_disable_stream(pipe_ctx); + if (!pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, true)) { + dm_error("DC: failed to blank crtc!\n"); + BREAK_TO_DEBUGGER(); + } + pipe_ctx->tg->funcs->disable_crtc(pipe_ctx->tg); + pipe_ctx->mi->funcs->free_mem_input( + pipe_ctx->mi, context->target_count); + resource_unreference_clock_source( + &context->res_ctx, pipe_ctx->clock_source); + + dc->hwss.power_down_front_end((struct core_dc *)dc, pipe_ctx); + + pipe_ctx->stream = NULL; +} + +static void set_drr(struct pipe_ctx **pipe_ctx, + int num_pipes, int vmin, int vmax) +{ + int i = 0; + struct drr_params params = {0}; + + params.vertical_total_max = vmax; + params.vertical_total_min = vmin; + + /* TODO: If multiple pipes are to be supported, you need + * some GSL stuff + */ + + for (i = 0; i < num_pipes; i++) { + pipe_ctx[i]->tg->funcs->set_drr(pipe_ctx[i]->tg, ¶ms); + } +} + +static void set_static_screen_control(struct pipe_ctx **pipe_ctx, + int num_pipes, int value) +{ + unsigned int i; + + for (i = 0; i < num_pipes; i++) + pipe_ctx[i]->tg->funcs-> + set_static_screen_control(pipe_ctx[i]->tg, value); +} + +/* unit: in_khz before mode set, get pixel clock from context. ASIC register + * may not be programmed yet. + * TODO: after mode set, pre_mode_set = false, + * may read PLL register to get pixel clock + */ +static uint32_t get_max_pixel_clock_for_all_paths( + struct core_dc *dc, + struct validate_context *context, + bool pre_mode_set) +{ + uint32_t max_pix_clk = 0; + int i; + + if (!pre_mode_set) { + /* TODO: read ASIC register to get pixel clock */ + ASSERT(0); + } + + for (i = 0; i < MAX_PIPES; i++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + + if (pipe_ctx->stream == NULL) + continue; + + /* do not check under lay */ + if (pipe_ctx->top_pipe) + continue; + + if (pipe_ctx->pix_clk_params.requested_pix_clk > max_pix_clk) + max_pix_clk = + pipe_ctx->pix_clk_params.requested_pix_clk; + } + + if (max_pix_clk == 0) + ASSERT(0); + + return max_pix_clk; +} + +/* + * Find clock state based on clock requested. if clock value is 0, simply + * set clock state as requested without finding clock state by clock value + */ +static void apply_min_clocks( + struct core_dc *dc, + struct validate_context *context, + enum clocks_state *clocks_state, + bool pre_mode_set) +{ + struct state_dependent_clocks req_clocks = {0}; + struct pipe_ctx *pipe_ctx; + int i; + + for (i = 0; i < MAX_PIPES; i++) { + pipe_ctx = &context->res_ctx.pipe_ctx[i]; + if (pipe_ctx->dis_clk != NULL) + break; + } + + if (!pre_mode_set) { + /* set clock_state without verification */ + if (dal_display_clock_set_min_clocks_state( + pipe_ctx->dis_clk, *clocks_state)) + return; + + /* TODOFPGA */ + } + + /* get the required state based on state dependent clocks: + * display clock and pixel clock + */ + req_clocks.display_clk_khz = context->bw_results.dispclk_khz; + + req_clocks.pixel_clk_khz = get_max_pixel_clock_for_all_paths( + dc, context, true); + + if (dal_display_clock_get_required_clocks_state( + pipe_ctx->dis_clk, &req_clocks, clocks_state)) { + dal_display_clock_set_min_clocks_state( + pipe_ctx->dis_clk, *clocks_state); + } else { + } +} + +static enum dc_status apply_ctx_to_hw_fpga( + struct core_dc *dc, + struct validate_context *context) +{ + enum dc_status status = DC_ERROR_UNEXPECTED; + int i; + + for (i = 0; i < context->res_ctx.pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx_old = + &dc->current_context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + + if (pipe_ctx->stream == NULL) + continue; + + if (pipe_ctx->stream == pipe_ctx_old->stream) + continue; + + status = apply_single_controller_ctx_to_hw( + pipe_ctx, + context, + dc); + + if (status != DC_OK) + return status; + } + + return DC_OK; +} + +static void reset_hw_ctx_wrap( + struct core_dc *dc, + struct validate_context *context) +{ + int i; + + /* Reset old context */ + /* look up the targets that have been removed since last commit */ + for (i = 0; i < context->res_ctx.pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx_old = + &dc->current_context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + + /* Note: We need to disable output if clock sources change, + * since bios does optimization and doesn't apply if changing + * PHY when not already disabled. + */ + + /* Skip underlay pipe since it will be handled in commit surface*/ + if (!pipe_ctx_old->stream || pipe_ctx_old->top_pipe) + continue; + + if (!pipe_ctx->stream || + pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) + reset_single_pipe_hw_ctx( + dc, pipe_ctx_old, dc->current_context); + } +} + +/*TODO: const validate_context*/ +enum dc_status dce110_apply_ctx_to_hw( + struct core_dc *dc, + struct validate_context *context) +{ + struct dc_bios *dcb = dc->ctx->dc_bios; + enum dc_status status; + int i; + bool programmed_audio_dto = false; + enum clocks_state clocks_state = CLOCKS_STATE_INVALID; + + /* Reset old context */ + /* look up the targets that have been removed since last commit */ + dc->hwss.reset_hw_ctx_wrap(dc, context); + + /* Skip applying if no targets */ + if (context->target_count <= 0) + return DC_OK; + + if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { + apply_ctx_to_hw_fpga(dc, context); + return DC_OK; + } + + /* Apply new context */ + dcb->funcs->set_scratch_critical_state(dcb, true); + + /* below is for real asic only */ + for (i = 0; i < context->res_ctx.pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx_old = + &dc->current_context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + + if (pipe_ctx->stream == NULL || pipe_ctx->top_pipe) + continue; + + if (pipe_ctx->stream == pipe_ctx_old->stream) { + if (pipe_ctx_old->clock_source != pipe_ctx->clock_source) + dce_crtc_switch_to_clk_src(dc->hwseq, + pipe_ctx->clock_source, i); + continue; + } + + dc->hwss.enable_display_power_gating( + dc, i, dc->ctx->dc_bios, + PIPE_GATING_CONTROL_DISABLE); + } + + set_safe_displaymarks(&context->res_ctx); + /*TODO: when pplib works*/ + apply_min_clocks(dc, context, &clocks_state, true); + + if (context->bw_results.dispclk_khz + > dc->current_context->bw_results.dispclk_khz) + dc->hwss.set_display_clock(context); + + for (i = 0; i < context->res_ctx.pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx_old = + &dc->current_context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + + if (pipe_ctx->stream == NULL) + continue; + + if (pipe_ctx->stream == pipe_ctx_old->stream) + continue; + + if (pipe_ctx->top_pipe) + continue; + + if (context->res_ctx.pipe_ctx[i].audio != NULL) { + /* Setup audio rate clock source */ + /* Issue: + * Audio lag happened on DP monitor when unplug a HDMI monitor + * + * Cause: + * In case of DP and HDMI connected or HDMI only, DCCG_AUDIO_DTO_SEL + * is set to either dto0 or dto1, audio should work fine. + * In case of DP connected only, DCCG_AUDIO_DTO_SEL should be dto1, + * set to dto0 will cause audio lag. + * + * Solution: + * Not optimized audio wall dto setup. When mode set, iterate pipe_ctx, + * find first available pipe with audio, setup audio wall DTO per topology + * instead of per pipe. + */ + struct audio_output audio_output; + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + + build_audio_output(pipe_ctx, &audio_output); + + if (dc_is_dp_signal(pipe_ctx->stream->signal)) + pipe_ctx->stream_enc->funcs->dp_audio_setup( + pipe_ctx->stream_enc, + pipe_ctx->audio->inst, + &pipe_ctx->stream->public.audio_info); + else + pipe_ctx->stream_enc->funcs->hdmi_audio_setup( + pipe_ctx->stream_enc, + pipe_ctx->audio->inst, + &pipe_ctx->stream->public.audio_info, + &audio_output.crtc_info); + + pipe_ctx->audio->funcs->az_configure( + pipe_ctx->audio, + pipe_ctx->stream->signal, + &audio_output.crtc_info, + &pipe_ctx->stream->public.audio_info); + + if (!programmed_audio_dto) { + pipe_ctx->audio->funcs->wall_dto_setup( + pipe_ctx->audio, + pipe_ctx->stream->signal, + &audio_output.crtc_info, + &audio_output.pll_info); + programmed_audio_dto = true; + } + } + + status = apply_single_controller_ctx_to_hw( + pipe_ctx, + context, + dc); + + if (DC_OK != status) + return status; + } + + dc->hwss.set_displaymarks(dc, context); + + /* to save power */ + apply_min_clocks(dc, context, &clocks_state, false); + + dcb->funcs->set_scratch_critical_state(dcb, false); + + switch_dp_clock_sources(dc, &context->res_ctx); + + return DC_OK; +} + +/******************************************************************************* + * Front End programming + ******************************************************************************/ +static void set_default_colors(struct pipe_ctx *pipe_ctx) +{ + struct default_adjustment default_adjust = { 0 }; + + default_adjust.force_hw_default = false; + if (pipe_ctx->surface == NULL) + default_adjust.in_color_space = COLOR_SPACE_SRGB; + else + default_adjust.in_color_space = + pipe_ctx->surface->public.color_space; + if (pipe_ctx->stream == NULL) + default_adjust.out_color_space = COLOR_SPACE_SRGB; + else + default_adjust.out_color_space = + pipe_ctx->stream->public.output_color_space; + default_adjust.csc_adjust_type = GRAPHICS_CSC_ADJUST_TYPE_SW; + default_adjust.surface_pixel_format = pipe_ctx->scl_data.format; + + /* display color depth */ + default_adjust.color_depth = + pipe_ctx->stream->public.timing.display_color_depth; + + /* Lb color depth */ + default_adjust.lb_color_depth = pipe_ctx->scl_data.lb_params.depth; + + pipe_ctx->opp->funcs->opp_set_csc_default( + pipe_ctx->opp, &default_adjust); +} + +static void program_blender(const struct core_dc *dc, + struct pipe_ctx *pipe_ctx) +{ + enum blnd_mode blender_mode = BLND_MODE_CURRENT_PIPE; + + if (pipe_ctx->bottom_pipe) { + if (pipe_ctx->bottom_pipe->surface->public.visible) { + if (pipe_ctx->surface->public.visible) + blender_mode = BLND_MODE_BLENDING; + else + blender_mode = BLND_MODE_OTHER_PIPE; + } + } + dce_set_blender_mode(dc->hwseq, pipe_ctx->pipe_idx, blender_mode); +} + +/** + * TODO REMOVE, USE UPDATE INSTEAD + */ +static void set_plane_config( + const struct core_dc *dc, + struct pipe_ctx *pipe_ctx, + struct resource_context *res_ctx) +{ + struct mem_input *mi = pipe_ctx->mi; + struct core_surface *surface = pipe_ctx->surface; + struct xfm_grph_csc_adjustment adjust; + struct out_csc_color_matrix tbl_entry; + unsigned int i; + + memset(&adjust, 0, sizeof(adjust)); + memset(&tbl_entry, 0, sizeof(tbl_entry)); + adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS; + + dce_enable_fe_clock(dc->hwseq, pipe_ctx->pipe_idx, true); + + set_default_colors(pipe_ctx); + if (pipe_ctx->stream->public.csc_color_matrix.enable_adjustment + == true) { + tbl_entry.color_space = + pipe_ctx->stream->public.output_color_space; + + for (i = 0; i < 12; i++) + tbl_entry.regval[i] = + pipe_ctx->stream->public.csc_color_matrix.matrix[i]; + + pipe_ctx->opp->funcs->opp_set_csc_adjustment + (pipe_ctx->opp, &tbl_entry); + } + + if (pipe_ctx->stream->public.gamut_remap_matrix.enable_remap == true) { + adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW; + adjust.temperature_matrix[0] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[0]; + adjust.temperature_matrix[1] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[1]; + adjust.temperature_matrix[2] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[2]; + adjust.temperature_matrix[3] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[4]; + adjust.temperature_matrix[4] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[5]; + adjust.temperature_matrix[5] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[6]; + adjust.temperature_matrix[6] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[8]; + adjust.temperature_matrix[7] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[9]; + adjust.temperature_matrix[8] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[10]; + } + + pipe_ctx->xfm->funcs->transform_set_gamut_remap(pipe_ctx->xfm, &adjust); + + pipe_ctx->scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; + program_scaler(dc, pipe_ctx); + + program_blender(dc, pipe_ctx); + + mi->funcs->mem_input_program_surface_config( + mi, + surface->public.format, + &surface->public.tiling_info, + &surface->public.plane_size, + surface->public.rotation, + NULL, + false); + + if (dc->public.config.gpu_vm_support) + mi->funcs->mem_input_program_pte_vm( + pipe_ctx->mi, + surface->public.format, + &surface->public.tiling_info, + surface->public.rotation); +} + +static void update_plane_addr(const struct core_dc *dc, + struct pipe_ctx *pipe_ctx) +{ + struct core_surface *surface = pipe_ctx->surface; + + if (surface == NULL) + return; + + pipe_ctx->mi->funcs->mem_input_program_surface_flip_and_addr( + pipe_ctx->mi, + &surface->public.address, + surface->public.flip_immediate); + + surface->status.requested_address = surface->public.address; + + if (surface->public.visible) + pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, false); +} + +void dce110_update_pending_status(struct pipe_ctx *pipe_ctx) +{ + struct core_surface *surface = pipe_ctx->surface; + + if (surface == NULL) + return; + + surface->status.is_flip_pending = + pipe_ctx->mi->funcs->mem_input_is_flip_pending( + pipe_ctx->mi); + + if (surface->status.is_flip_pending && !surface->public.visible) + pipe_ctx->mi->current_address = pipe_ctx->mi->request_address; + + surface->status.current_address = pipe_ctx->mi->current_address; +} + +void dce110_power_down(struct core_dc *dc) +{ + power_down_all_hw_blocks(dc); + disable_vga_and_power_gate_all_controllers(dc); +} + +static bool wait_for_reset_trigger_to_occur( + struct dc_context *dc_ctx, + struct timing_generator *tg) +{ + bool rc = false; + + /* To avoid endless loop we wait at most + * frames_to_wait_on_triggered_reset frames for the reset to occur. */ + const uint32_t frames_to_wait_on_triggered_reset = 10; + uint32_t i; + + for (i = 0; i < frames_to_wait_on_triggered_reset; i++) { + + if (!tg->funcs->is_counter_moving(tg)) { + DC_ERROR("TG counter is not moving!\n"); + break; + } + + if (tg->funcs->did_triggered_reset_occur(tg)) { + rc = true; + /* usually occurs at i=1 */ + DC_SYNC_INFO("GSL: reset occurred at wait count: %d\n", + i); + break; + } + + /* Wait for one frame. */ + tg->funcs->wait_for_state(tg, CRTC_STATE_VACTIVE); + tg->funcs->wait_for_state(tg, CRTC_STATE_VBLANK); + } + + if (false == rc) + DC_ERROR("GSL: Timeout on reset trigger!\n"); + + return rc; +} + +/* Enable timing synchronization for a group of Timing Generators. */ +static void dce110_enable_timing_synchronization( + struct core_dc *dc, + int group_index, + int group_size, + struct pipe_ctx *grouped_pipes[]) +{ + struct dc_context *dc_ctx = dc->ctx; + struct dcp_gsl_params gsl_params = { 0 }; + int i; + + DC_SYNC_INFO("GSL: Setting-up...\n"); + + /* Designate a single TG in the group as a master. + * Since HW doesn't care which one, we always assign + * the 1st one in the group. */ + gsl_params.gsl_group = 0; + gsl_params.gsl_master = grouped_pipes[0]->tg->inst; + + for (i = 0; i < group_size; i++) + grouped_pipes[i]->tg->funcs->setup_global_swap_lock( + grouped_pipes[i]->tg, &gsl_params); + + /* Reset slave controllers on master VSync */ + DC_SYNC_INFO("GSL: enabling trigger-reset\n"); + + for (i = 1 /* skip the master */; i < group_size; i++) + grouped_pipes[i]->tg->funcs->enable_reset_trigger( + grouped_pipes[i]->tg, gsl_params.gsl_group); + + + + for (i = 1 /* skip the master */; i < group_size; i++) { + DC_SYNC_INFO("GSL: waiting for reset to occur.\n"); + wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[i]->tg); + /* Regardless of success of the wait above, remove the reset or + * the driver will start timing out on Display requests. */ + DC_SYNC_INFO("GSL: disabling trigger-reset.\n"); + grouped_pipes[i]->tg->funcs->disable_reset_trigger(grouped_pipes[i]->tg); + } + + + /* GSL Vblank synchronization is a one time sync mechanism, assumption + * is that the sync'ed displays will not drift out of sync over time*/ + DC_SYNC_INFO("GSL: Restoring register states.\n"); + for (i = 0; i < group_size; i++) + grouped_pipes[i]->tg->funcs->tear_down_global_swap_lock(grouped_pipes[i]->tg); + + DC_SYNC_INFO("GSL: Set-up complete.\n"); +} + +static void init_hw(struct core_dc *dc) +{ + int i; + struct dc_bios *bp; + struct transform *xfm; + + bp = dc->ctx->dc_bios; + for (i = 0; i < dc->res_pool->pipe_count; i++) { + xfm = dc->res_pool->transforms[i]; + xfm->funcs->transform_reset(xfm); + + dc->hwss.enable_display_power_gating( + dc, i, bp, + PIPE_GATING_CONTROL_INIT); + dc->hwss.enable_display_power_gating( + dc, i, bp, + PIPE_GATING_CONTROL_DISABLE); + dc->hwss.enable_display_pipe_clock_gating( + dc->ctx, + true); + } + + dce_clock_gating_power_up(dc->hwseq, false);; + /***************************************/ + + for (i = 0; i < dc->link_count; i++) { + /****************************************/ + /* Power up AND update implementation according to the + * required signal (which may be different from the + * default signal on connector). */ + struct core_link *link = dc->links[i]; + link->link_enc->funcs->hw_init(link->link_enc); + } + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct timing_generator *tg = dc->res_pool->timing_generators[i]; + + tg->funcs->disable_vga(tg); + + /* Blank controller using driver code instead of + * command table. */ + tg->funcs->set_blank(tg, true); + } + + for (i = 0; i < dc->res_pool->audio_count; i++) { + struct audio *audio = dc->res_pool->audios[i]; + audio->funcs->hw_init(audio); + } +} + +/* TODO: move this to apply_ctx_tohw some how?*/ +static void dce110_power_on_pipe_if_needed( + struct core_dc *dc, + struct pipe_ctx *pipe_ctx, + struct validate_context *context) +{ + struct pipe_ctx *old_pipe_ctx = &dc->current_context->res_ctx.pipe_ctx[pipe_ctx->pipe_idx]; + struct dc_bios *dcb = dc->ctx->dc_bios; + struct tg_color black_color = {0}; + + if (!old_pipe_ctx->stream && pipe_ctx->stream) { + dc->hwss.enable_display_power_gating( + dc, + pipe_ctx->pipe_idx, + dcb, PIPE_GATING_CONTROL_DISABLE); + + /* + * This is for powering on underlay, so crtc does not + * need to be enabled + */ + + pipe_ctx->tg->funcs->program_timing(pipe_ctx->tg, + &pipe_ctx->stream->public.timing, + false); + + pipe_ctx->tg->funcs->enable_advanced_request( + pipe_ctx->tg, + true, + &pipe_ctx->stream->public.timing); + + pipe_ctx->mi->funcs->allocate_mem_input(pipe_ctx->mi, + pipe_ctx->stream->public.timing.h_total, + pipe_ctx->stream->public.timing.v_total, + pipe_ctx->stream->public.timing.pix_clk_khz, + context->target_count); + + /* TODO unhardcode*/ + color_space_to_black_color(dc, + COLOR_SPACE_YCBCR601, &black_color); + pipe_ctx->tg->funcs->set_blank_color( + pipe_ctx->tg, + &black_color); + } +} + +static void dce110_increase_watermarks_for_pipe( + struct core_dc *dc, + struct pipe_ctx *pipe_ctx, + struct validate_context *context) +{ + if (did_watermarks_increase(pipe_ctx, context, dc->current_context)) + program_wm_for_pipe(dc, pipe_ctx, context); +} + +static void dce110_set_bandwidth(struct core_dc *dc) +{ + int i; + + for (i = 0; i < dc->current_context->res_ctx.pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &dc->current_context->res_ctx.pipe_ctx[i]; + + if (!pipe_ctx->stream) + continue; + + program_wm_for_pipe(dc, pipe_ctx, dc->current_context); + } + + dc->hwss.set_display_clock(dc->current_context); +} + +static void dce110_program_front_end_for_pipe( + struct core_dc *dc, struct pipe_ctx *pipe_ctx) +{ + struct mem_input *mi = pipe_ctx->mi; + struct pipe_ctx *old_pipe = NULL; + struct core_surface *surface = pipe_ctx->surface; + struct xfm_grph_csc_adjustment adjust; + struct out_csc_color_matrix tbl_entry; + unsigned int i; + + memset(&tbl_entry, 0, sizeof(tbl_entry)); + + if (dc->current_context) + old_pipe = &dc->current_context->res_ctx.pipe_ctx[pipe_ctx->pipe_idx]; + + memset(&adjust, 0, sizeof(adjust)); + adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS; + + dce_enable_fe_clock(dc->hwseq, pipe_ctx->pipe_idx, true); + + set_default_colors(pipe_ctx); + if (pipe_ctx->stream->public.csc_color_matrix.enable_adjustment + == true) { + tbl_entry.color_space = + pipe_ctx->stream->public.output_color_space; + + for (i = 0; i < 12; i++) + tbl_entry.regval[i] = + pipe_ctx->stream->public.csc_color_matrix.matrix[i]; + + pipe_ctx->opp->funcs->opp_set_csc_adjustment + (pipe_ctx->opp, &tbl_entry); + } + + if (pipe_ctx->stream->public.gamut_remap_matrix.enable_remap == true) { + adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW; + adjust.temperature_matrix[0] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[0]; + adjust.temperature_matrix[1] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[1]; + adjust.temperature_matrix[2] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[2]; + adjust.temperature_matrix[3] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[4]; + adjust.temperature_matrix[4] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[5]; + adjust.temperature_matrix[5] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[6]; + adjust.temperature_matrix[6] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[8]; + adjust.temperature_matrix[7] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[9]; + adjust.temperature_matrix[8] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[10]; + } + + pipe_ctx->xfm->funcs->transform_set_gamut_remap(pipe_ctx->xfm, &adjust); + + pipe_ctx->scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; + if (old_pipe && memcmp(&old_pipe->scl_data, + &pipe_ctx->scl_data, + sizeof(struct scaler_data)) != 0) + program_scaler(dc, pipe_ctx); + + mi->funcs->mem_input_program_surface_config( + mi, + surface->public.format, + &surface->public.tiling_info, + &surface->public.plane_size, + surface->public.rotation, + false, + false); + + if (dc->public.config.gpu_vm_support) + mi->funcs->mem_input_program_pte_vm( + pipe_ctx->mi, + surface->public.format, + &surface->public.tiling_info, + surface->public.rotation); + + dm_logger_write(dc->ctx->logger, LOG_SURFACE, + "Pipe:%d 0x%x: addr hi:0x%x, " + "addr low:0x%x, " + "src: %d, %d, %d," + " %d; dst: %d, %d, %d, %d;" + "clip: %d, %d, %d, %d\n", + pipe_ctx->pipe_idx, + pipe_ctx->surface, + pipe_ctx->surface->public.address.grph.addr.high_part, + pipe_ctx->surface->public.address.grph.addr.low_part, + pipe_ctx->surface->public.src_rect.x, + pipe_ctx->surface->public.src_rect.y, + pipe_ctx->surface->public.src_rect.width, + pipe_ctx->surface->public.src_rect.height, + pipe_ctx->surface->public.dst_rect.x, + pipe_ctx->surface->public.dst_rect.y, + pipe_ctx->surface->public.dst_rect.width, + pipe_ctx->surface->public.dst_rect.height, + pipe_ctx->surface->public.clip_rect.x, + pipe_ctx->surface->public.clip_rect.y, + pipe_ctx->surface->public.clip_rect.width, + pipe_ctx->surface->public.clip_rect.height); + + dm_logger_write(dc->ctx->logger, LOG_SURFACE, + "Pipe %d: width, height, x, y\n" + "viewport:%d, %d, %d, %d\n" + "recout: %d, %d, %d, %d\n", + pipe_ctx->pipe_idx, + pipe_ctx->scl_data.viewport.width, + pipe_ctx->scl_data.viewport.height, + pipe_ctx->scl_data.viewport.x, + pipe_ctx->scl_data.viewport.y, + pipe_ctx->scl_data.recout.width, + pipe_ctx->scl_data.recout.height, + pipe_ctx->scl_data.recout.x, + pipe_ctx->scl_data.recout.y); +} + + + +static void dce110_prepare_pipe_for_surface_commit( + struct core_dc *dc, + struct pipe_ctx *pipe_ctx, + struct validate_context *context) { + struct core_gamma *gamma = NULL; + + dc->hwss.increase_watermarks_for_pipe(dc, pipe_ctx, context); + + if (pipe_ctx->surface->public.gamma_correction) + gamma = DC_GAMMA_TO_CORE( + pipe_ctx->surface->public.gamma_correction); + + dc->hwss.set_gamma_correction( + pipe_ctx->ipp, + pipe_ctx->opp, + gamma, pipe_ctx->surface); +} + +static void dce110_prepare_pipe_for_context( + struct core_dc *dc, + struct pipe_ctx *pipe_ctx, + struct validate_context *context) +{ + dce110_power_on_pipe_if_needed(dc, pipe_ctx, context); + dce110_prepare_pipe_for_surface_commit(dc, pipe_ctx, context); +} + +static void dce110_apply_ctx_for_surface( + struct core_dc *dc, + struct core_surface *surface, + struct validate_context *context) +{ + int i; + + /* TODO remove when removing the surface reset workaroud*/ + if (!surface) + return; + + for (i = 0; i < context->res_ctx.pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + + if (pipe_ctx->surface != surface) + continue; + + dce110_program_front_end_for_pipe(dc, pipe_ctx); + program_blender(dc, pipe_ctx); + + } + +} + +static void dce110_power_down_fe(struct core_dc *dc, struct pipe_ctx *pipe) +{ + int i; + + for (i = 0; i < dc->res_pool->pipe_count; i++) + if (&dc->current_context->res_ctx.pipe_ctx[i] == pipe) + break; + + if (i == dc->res_pool->pipe_count) + return; + + dc->hwss.enable_display_power_gating( + dc, i, dc->ctx->dc_bios, PIPE_GATING_CONTROL_ENABLE); + if (pipe->xfm) + pipe->xfm->funcs->transform_reset(pipe->xfm); + memset(&pipe->scl_data, 0, sizeof(struct scaler_data)); +} + +static const struct hw_sequencer_funcs dce110_funcs = { + .init_hw = init_hw, + .apply_ctx_to_hw = dce110_apply_ctx_to_hw, + .prepare_pipe_for_context = dce110_prepare_pipe_for_context, + .apply_ctx_for_surface = dce110_apply_ctx_for_surface, + .set_plane_config = set_plane_config, + .update_plane_addr = update_plane_addr, + .update_pending_status = dce110_update_pending_status, + .set_gamma_correction = set_gamma_ramp, + .power_down = dce110_power_down, + .enable_accelerated_mode = dce110_enable_accelerated_mode, + .enable_timing_synchronization = dce110_enable_timing_synchronization, + .update_info_frame = dce110_update_info_frame, + .enable_stream = dce110_enable_stream, + .disable_stream = dce110_disable_stream, + .unblank_stream = dce110_unblank_stream, + .enable_display_pipe_clock_gating = enable_display_pipe_clock_gating, + .enable_display_power_gating = dce110_enable_display_power_gating, + .power_down_front_end = dce110_power_down_fe, + .pipe_control_lock = dce_pipe_control_lock, + .set_display_clock = dce110_set_display_clock, + .set_displaymarks = dce110_set_displaymarks, + .increase_watermarks_for_pipe = dce110_increase_watermarks_for_pipe, + .set_bandwidth = dce110_set_bandwidth, + .set_drr = set_drr, + .set_static_screen_control = set_static_screen_control, + .reset_hw_ctx_wrap = reset_hw_ctx_wrap, + .prog_pixclk_crtc_otg = prog_pixclk_crtc_otg, +}; + +bool dce110_hw_sequencer_construct(struct core_dc *dc) +{ + dc->hwss = dce110_funcs; + + return true; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h new file mode 100644 index 000000000000..a6b4d0d2429f --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h @@ -0,0 +1,62 @@ +/* +* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_HWSS_DCE110_H__ +#define __DC_HWSS_DCE110_H__ + +#include "core_types.h" + +#define GAMMA_HW_POINTS_NUM 256 +struct core_dc; + +bool dce110_hw_sequencer_construct(struct core_dc *dc); + +enum dc_status dce110_apply_ctx_to_hw( + struct core_dc *dc, + struct validate_context *context); + +void dce110_set_display_clock(struct validate_context *context); + +void dce110_set_displaymarks( + const struct core_dc *dc, + struct validate_context *context); + +void dce110_enable_stream(struct pipe_ctx *pipe_ctx); + +void dce110_disable_stream(struct pipe_ctx *pipe_ctx); + +void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, + struct dc_link_settings *link_settings); + +void dce110_update_info_frame(struct pipe_ctx *pipe_ctx); + +void dce110_enable_accelerated_mode(struct core_dc *dc); + +void dce110_power_down(struct core_dc *dc); + +void dce110_update_pending_status(struct pipe_ctx *pipe_ctx); + +#endif /* __DC_HWSS_DCE110_H__ */ + diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.c new file mode 100644 index 000000000000..dd69f6060bb9 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.c @@ -0,0 +1,62 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "include/logger_interface.h" + +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" + +#include "dce110_ipp.h" + +static const struct ipp_funcs funcs = { + .ipp_cursor_set_attributes = dce110_ipp_cursor_set_attributes, + .ipp_cursor_set_position = dce110_ipp_cursor_set_position, + .ipp_program_prescale = dce110_ipp_program_prescale, + .ipp_set_degamma = dce110_ipp_set_degamma, +}; + +bool dce110_ipp_construct( + struct dce110_ipp* ipp, + struct dc_context *ctx, + uint32_t inst, + const struct dce110_ipp_reg_offsets *offset) +{ + ipp->base.ctx = ctx; + + ipp->base.inst = inst; + + ipp->offsets = *offset; + + ipp->base.funcs = &funcs; + + return true; +} + +void dce110_ipp_destroy(struct input_pixel_processor **ipp) +{ + dm_free(TO_DCE110_IPP(*ipp)); + *ipp = NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h new file mode 100644 index 000000000000..60eebdecfa10 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h @@ -0,0 +1,76 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_IPP_DCE110_H__ +#define __DC_IPP_DCE110_H__ + +#include "ipp.h" + +struct gamma_parameters; +struct dev_c_lut; + +#define TO_DCE110_IPP(input_pixel_processor)\ + container_of(input_pixel_processor, struct dce110_ipp, base) + +struct dce110_ipp_reg_offsets { + uint32_t dcp_offset; +}; + +struct dce110_ipp { + struct input_pixel_processor base; + struct dce110_ipp_reg_offsets offsets; +}; + +bool dce110_ipp_construct( + struct dce110_ipp* ipp, + struct dc_context *ctx, + enum controller_id id, + const struct dce110_ipp_reg_offsets *offset); + +void dce110_ipp_destroy(struct input_pixel_processor **ipp); + +/* CURSOR RELATED */ +void dce110_ipp_cursor_set_position( + struct input_pixel_processor *ipp, + const struct dc_cursor_position *position); + +bool dce110_ipp_cursor_set_attributes( + struct input_pixel_processor *ipp, + const struct dc_cursor_attributes *attributes); + +/* DEGAMMA RELATED */ +bool dce110_ipp_set_degamma( + struct input_pixel_processor *ipp, + enum ipp_degamma_mode mode); + +void dce110_ipp_program_prescale( + struct input_pixel_processor *ipp, + struct ipp_prescale_params *params); +/* + * Helper functions to be resused in other ASICs + */ +void dce110_helper_select_lut(struct dce110_ipp *ipp110); + +#endif /*__DC_IPP_DCE110_H__*/ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_cursor.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_cursor.c new file mode 100644 index 000000000000..95f6ca3ba5df --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_cursor.c @@ -0,0 +1,253 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "include/logger_interface.h" + +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" + +#include "dce110_ipp.h" + +#define CURSOR_COLOR_BLACK 0x00000000 +#define CURSOR_COLOR_WHITE 0xFFFFFFFF + +#define DCP_REG(reg)\ + (reg + ipp110->offsets.dcp_offset) + +static void enable( + struct dce110_ipp *ipp110, + bool enable); + +static void lock( + struct dce110_ipp *ipp110, + bool enable); + +static void program_position( + struct dce110_ipp *ipp110, + uint32_t x, + uint32_t y); + +static bool program_control( + struct dce110_ipp *ipp110, + enum dc_cursor_color_format color_format, + bool enable_magnification, + bool inverse_transparent_clamping); + +static void program_hotspot( + struct dce110_ipp *ipp110, + uint32_t x, + uint32_t y); + +static void program_size( + struct dce110_ipp *ipp110, + uint32_t width, + uint32_t height); + +static void program_address( + struct dce110_ipp *ipp110, + PHYSICAL_ADDRESS_LOC address); + +void dce110_ipp_cursor_set_position( + struct input_pixel_processor *ipp, + const struct dc_cursor_position *position) +{ + struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); + + /* lock cursor registers */ + lock(ipp110, true); + + /* Flag passed in structure differentiates cursor enable/disable. */ + /* Update if it differs from cached state. */ + enable(ipp110, position->enable); + + program_position(ipp110, position->x, position->y); + + if (position->hot_spot_enable) + program_hotspot( + ipp110, + position->x_hotspot, + position->y_hotspot); + + /* unlock cursor registers */ + lock(ipp110, false); +} + +bool dce110_ipp_cursor_set_attributes( + struct input_pixel_processor *ipp, + const struct dc_cursor_attributes *attributes) +{ + struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); + /* Lock cursor registers */ + lock(ipp110, true); + + /* Program cursor control */ + program_control( + ipp110, + attributes->color_format, + attributes->attribute_flags.bits.ENABLE_MAGNIFICATION, + attributes->attribute_flags.bits.INVERSE_TRANSPARENT_CLAMPING); + + /* Program hot spot coordinates */ + program_hotspot(ipp110, attributes->x_hot, attributes->y_hot); + + /* + * Program cursor size -- NOTE: HW spec specifies that HW register + * stores size as (height - 1, width - 1) + */ + program_size(ipp110, attributes->width-1, attributes->height-1); + + /* Program cursor surface address */ + program_address(ipp110, attributes->address); + + /* Unlock Cursor registers. */ + lock(ipp110, false); + + return true; +} + +static void enable( + struct dce110_ipp *ipp110, bool enable) +{ + uint32_t value = 0; + uint32_t addr = DCP_REG(mmCUR_CONTROL); + + value = dm_read_reg(ipp110->base.ctx, addr); + set_reg_field_value(value, enable, CUR_CONTROL, CURSOR_EN); + dm_write_reg(ipp110->base.ctx, addr, value); +} + +static void lock( + struct dce110_ipp *ipp110, bool lock) +{ + uint32_t value = 0; + uint32_t addr = DCP_REG(mmCUR_UPDATE); + + value = dm_read_reg(ipp110->base.ctx, addr); + set_reg_field_value(value, lock, CUR_UPDATE, CURSOR_UPDATE_LOCK); + dm_write_reg(ipp110->base.ctx, addr, value); +} + +static void program_position( + struct dce110_ipp *ipp110, + uint32_t x, + uint32_t y) +{ + uint32_t value = 0; + uint32_t addr = DCP_REG(mmCUR_POSITION); + + value = dm_read_reg(ipp110->base.ctx, addr); + set_reg_field_value(value, x, CUR_POSITION, CURSOR_X_POSITION); + set_reg_field_value(value, y, CUR_POSITION, CURSOR_Y_POSITION); + dm_write_reg(ipp110->base.ctx, addr, value); +} + +static bool program_control( + struct dce110_ipp *ipp110, + enum dc_cursor_color_format color_format, + bool enable_magnification, + bool inverse_transparent_clamping) +{ + uint32_t value = 0; + uint32_t addr = DCP_REG(mmCUR_CONTROL); + uint32_t mode = 0; + + switch (color_format) { + case CURSOR_MODE_MONO: + mode = 0; + break; + case CURSOR_MODE_COLOR_1BIT_AND: + mode = 1; + break; + case CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA: + mode = 2; + break; + case CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA: + mode = 3; + break; + default: + return false; + } + + set_reg_field_value(value, mode, CUR_CONTROL, CURSOR_MODE); + set_reg_field_value(value, enable_magnification, + CUR_CONTROL, CURSOR_2X_MAGNIFY); + set_reg_field_value(value, inverse_transparent_clamping, + CUR_CONTROL, CUR_INV_TRANS_CLAMP); + dm_write_reg(ipp110->base.ctx, addr, value); + + if (color_format == CURSOR_MODE_MONO) { + addr = DCP_REG(mmCUR_COLOR1); + dm_write_reg(ipp110->base.ctx, addr, CURSOR_COLOR_BLACK); + addr = DCP_REG(mmCUR_COLOR2); + dm_write_reg(ipp110->base.ctx, addr, CURSOR_COLOR_WHITE); + } + return true; +} + +static void program_hotspot( + struct dce110_ipp *ipp110, + uint32_t x, + uint32_t y) +{ + uint32_t value = 0; + uint32_t addr = DCP_REG(mmCUR_HOT_SPOT); + + value = dm_read_reg(ipp110->base.ctx, addr); + set_reg_field_value(value, x, CUR_HOT_SPOT, CURSOR_HOT_SPOT_X); + set_reg_field_value(value, y, CUR_HOT_SPOT, CURSOR_HOT_SPOT_Y); + dm_write_reg(ipp110->base.ctx, addr, value); +} + +static void program_size( + struct dce110_ipp *ipp110, + uint32_t width, + uint32_t height) +{ + uint32_t value = 0; + uint32_t addr = DCP_REG(mmCUR_SIZE); + + value = dm_read_reg(ipp110->base.ctx, addr); + set_reg_field_value(value, width, CUR_SIZE, CURSOR_WIDTH); + set_reg_field_value(value, height, CUR_SIZE, CURSOR_HEIGHT); + dm_write_reg(ipp110->base.ctx, addr, value); +} + +static void program_address( + struct dce110_ipp *ipp110, + PHYSICAL_ADDRESS_LOC address) +{ + uint32_t addr = DCP_REG(mmCUR_SURFACE_ADDRESS_HIGH); + /* SURFACE_ADDRESS_HIGH: Higher order bits (39:32) of hardware cursor + * surface base address in byte. It is 4K byte aligned. + * The correct way to program cursor surface address is to first write + * to CUR_SURFACE_ADDRESS_HIGH, and then write to CUR_SURFACE_ADDRESS */ + + dm_write_reg(ipp110->base.ctx, addr, address.high_part); + + addr = DCP_REG(mmCUR_SURFACE_ADDRESS); + dm_write_reg(ipp110->base.ctx, addr, address.low_part); +} + diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_gamma.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_gamma.c new file mode 100644 index 000000000000..79a6a6dd72fc --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_gamma.c @@ -0,0 +1,303 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "include/logger_interface.h" +#include "include/fixed31_32.h" +#include "basics/conversion.h" + +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" + +#include "dce110_ipp.h" +#include "gamma_types.h" + +#define DCP_REG(reg)\ + (reg + ipp110->offsets.dcp_offset) + +enum { + MAX_INPUT_LUT_ENTRY = 256 +}; + +/*PROTOTYPE DECLARATIONS*/ +static void set_lut_inc( + struct dce110_ipp *ipp110, + uint8_t inc, + bool is_float, + bool is_signed); + +bool dce110_ipp_set_degamma( + struct input_pixel_processor *ipp, + enum ipp_degamma_mode mode) +{ + struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); + + uint32_t value = 0; + + uint32_t degamma_type = (mode == IPP_DEGAMMA_MODE_HW_sRGB) ? 1 : 0; + + ASSERT(mode == IPP_DEGAMMA_MODE_BYPASS || + mode == IPP_DEGAMMA_MODE_HW_sRGB); + + set_reg_field_value( + value, + degamma_type, + DEGAMMA_CONTROL, + GRPH_DEGAMMA_MODE); + + set_reg_field_value( + value, + degamma_type, + DEGAMMA_CONTROL, + CURSOR_DEGAMMA_MODE); + + set_reg_field_value( + value, + degamma_type, + DEGAMMA_CONTROL, + CURSOR2_DEGAMMA_MODE); + + dm_write_reg(ipp110->base.ctx, DCP_REG(mmDEGAMMA_CONTROL), value); + + return true; +} + +void dce110_ipp_program_prescale( + struct input_pixel_processor *ipp, + struct ipp_prescale_params *params) +{ + struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); + + uint32_t prescale_control = 0; + uint32_t prescale_value = 0; + uint32_t legacy_lut_control = 0; + + prescale_control = dm_read_reg(ipp110->base.ctx, + DCP_REG(mmPRESCALE_GRPH_CONTROL)); + + if (params->mode != IPP_PRESCALE_MODE_BYPASS) { + + set_reg_field_value( + prescale_control, + 0, + PRESCALE_GRPH_CONTROL, + GRPH_PRESCALE_BYPASS); + + /* + * If prescale is in use, then legacy lut should + * be bypassed + */ + legacy_lut_control = dm_read_reg(ipp110->base.ctx, + DCP_REG(mmINPUT_GAMMA_CONTROL)); + + set_reg_field_value( + legacy_lut_control, + 1, + INPUT_GAMMA_CONTROL, + GRPH_INPUT_GAMMA_MODE); + + dm_write_reg(ipp110->base.ctx, + DCP_REG(mmINPUT_GAMMA_CONTROL), + legacy_lut_control); + } else { + set_reg_field_value( + prescale_control, + 1, + PRESCALE_GRPH_CONTROL, + GRPH_PRESCALE_BYPASS); + } + + set_reg_field_value( + prescale_value, + params->scale, + PRESCALE_VALUES_GRPH_R, + GRPH_PRESCALE_SCALE_R); + + set_reg_field_value( + prescale_value, + params->bias, + PRESCALE_VALUES_GRPH_R, + GRPH_PRESCALE_BIAS_R); + + dm_write_reg(ipp110->base.ctx, + DCP_REG(mmPRESCALE_GRPH_CONTROL), + prescale_control); + + dm_write_reg(ipp110->base.ctx, + DCP_REG(mmPRESCALE_VALUES_GRPH_R), + prescale_value); + + dm_write_reg(ipp110->base.ctx, + DCP_REG(mmPRESCALE_VALUES_GRPH_G), + prescale_value); + + dm_write_reg(ipp110->base.ctx, + DCP_REG(mmPRESCALE_VALUES_GRPH_B), + prescale_value); +} + +static void set_lut_inc( + struct dce110_ipp *ipp110, + uint8_t inc, + bool is_float, + bool is_signed) +{ + const uint32_t addr = DCP_REG(mmDC_LUT_CONTROL); + + uint32_t value = dm_read_reg(ipp110->base.ctx, addr); + + set_reg_field_value( + value, + inc, + DC_LUT_CONTROL, + DC_LUT_INC_R); + + set_reg_field_value( + value, + inc, + DC_LUT_CONTROL, + DC_LUT_INC_G); + + set_reg_field_value( + value, + inc, + DC_LUT_CONTROL, + DC_LUT_INC_B); + + set_reg_field_value( + value, + is_float, + DC_LUT_CONTROL, + DC_LUT_DATA_R_FLOAT_POINT_EN); + + set_reg_field_value( + value, + is_float, + DC_LUT_CONTROL, + DC_LUT_DATA_G_FLOAT_POINT_EN); + + set_reg_field_value( + value, + is_float, + DC_LUT_CONTROL, + DC_LUT_DATA_B_FLOAT_POINT_EN); + + set_reg_field_value( + value, + is_signed, + DC_LUT_CONTROL, + DC_LUT_DATA_R_SIGNED_EN); + + set_reg_field_value( + value, + is_signed, + DC_LUT_CONTROL, + DC_LUT_DATA_G_SIGNED_EN); + + set_reg_field_value( + value, + is_signed, + DC_LUT_CONTROL, + DC_LUT_DATA_B_SIGNED_EN); + + dm_write_reg(ipp110->base.ctx, addr, value); +} + +void dce110_helper_select_lut(struct dce110_ipp *ipp110) +{ + uint32_t value = 0; + + set_lut_inc(ipp110, 0, false, false); + + { + const uint32_t addr = DCP_REG(mmDC_LUT_WRITE_EN_MASK); + + value = dm_read_reg(ipp110->base.ctx, addr); + + /* enable all */ + set_reg_field_value( + value, + 0x7, + DC_LUT_WRITE_EN_MASK, + DC_LUT_WRITE_EN_MASK); + + dm_write_reg(ipp110->base.ctx, addr, value); + } + + { + const uint32_t addr = DCP_REG(mmDC_LUT_RW_MODE); + + value = dm_read_reg(ipp110->base.ctx, addr); + + set_reg_field_value( + value, + 0, + DC_LUT_RW_MODE, + DC_LUT_RW_MODE); + + dm_write_reg(ipp110->base.ctx, addr, value); + } + + { + const uint32_t addr = DCP_REG(mmDC_LUT_CONTROL); + + value = dm_read_reg(ipp110->base.ctx, addr); + + /* 00 - new u0.12 */ + set_reg_field_value( + value, + 3, + DC_LUT_CONTROL, + DC_LUT_DATA_R_FORMAT); + + set_reg_field_value( + value, + 3, + DC_LUT_CONTROL, + DC_LUT_DATA_G_FORMAT); + + set_reg_field_value( + value, + 3, + DC_LUT_CONTROL, + DC_LUT_DATA_B_FORMAT); + + dm_write_reg(ipp110->base.ctx, addr, value); + } + + { + const uint32_t addr = DCP_REG(mmDC_LUT_RW_INDEX); + + value = dm_read_reg(ipp110->base.ctx, addr); + + set_reg_field_value( + value, + 0, + DC_LUT_RW_INDEX, + DC_LUT_RW_INDEX); + + dm_write_reg(ipp110->base.ctx, addr, value); + } +} diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c new file mode 100644 index 000000000000..c0a68c6f585e --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c @@ -0,0 +1,535 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#include "dm_services.h" + +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" +/* TODO: this needs to be looked at, used by Stella's workaround*/ +#include "gmc/gmc_8_2_d.h" +#include "gmc/gmc_8_2_sh_mask.h" + +#include "include/logger_interface.h" + +#include "dce110_mem_input.h" + +#define DCP_REG(reg) (reg + mem_input110->offsets.dcp) +#define DMIF_REG(reg) (reg + mem_input110->offsets.dmif) +#define PIPE_REG(reg) (reg + mem_input110->offsets.pipe) + +static void program_sec_addr( + struct dce110_mem_input *mem_input110, + PHYSICAL_ADDRESS_LOC address) +{ + uint32_t value = 0; + uint32_t temp; + + /*high register MUST be programmed first*/ + temp = address.high_part & + GRPH_SECONDARY_SURFACE_ADDRESS_HIGH__GRPH_SECONDARY_SURFACE_ADDRESS_HIGH_MASK; + set_reg_field_value(value, temp, + GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, + GRPH_SECONDARY_SURFACE_ADDRESS_HIGH); + dm_write_reg(mem_input110->base.ctx, + DCP_REG(mmGRPH_SECONDARY_SURFACE_ADDRESS_HIGH), value); + + value = 0; + temp = address.low_part >> + GRPH_SECONDARY_SURFACE_ADDRESS__GRPH_SECONDARY_SURFACE_ADDRESS__SHIFT; + set_reg_field_value(value, temp, + GRPH_SECONDARY_SURFACE_ADDRESS, + GRPH_SECONDARY_SURFACE_ADDRESS); + dm_write_reg(mem_input110->base.ctx, + DCP_REG(mmGRPH_SECONDARY_SURFACE_ADDRESS), value); +} + +static void program_pri_addr( + struct dce110_mem_input *mem_input110, + PHYSICAL_ADDRESS_LOC address) +{ + uint32_t value = 0; + uint32_t temp; + + /*high register MUST be programmed first*/ + temp = address.high_part & + GRPH_PRIMARY_SURFACE_ADDRESS_HIGH__GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_MASK; + set_reg_field_value(value, temp, + GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, + GRPH_PRIMARY_SURFACE_ADDRESS_HIGH); + dm_write_reg(mem_input110->base.ctx, + DCP_REG(mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH), value); + + value = 0; + temp = address.low_part >> + GRPH_PRIMARY_SURFACE_ADDRESS__GRPH_PRIMARY_SURFACE_ADDRESS__SHIFT; + set_reg_field_value(value, temp, + GRPH_PRIMARY_SURFACE_ADDRESS, + GRPH_PRIMARY_SURFACE_ADDRESS); + dm_write_reg(mem_input110->base.ctx, + DCP_REG(mmGRPH_PRIMARY_SURFACE_ADDRESS), value); +} + +bool dce110_mem_input_is_flip_pending(struct mem_input *mem_input) +{ + struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input); + uint32_t value; + + value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmGRPH_UPDATE)); + + if (get_reg_field_value(value, GRPH_UPDATE, + GRPH_SURFACE_UPDATE_PENDING)) + return true; + + mem_input->current_address = mem_input->request_address; + return false; +} + +bool dce110_mem_input_program_surface_flip_and_addr( + struct mem_input *mem_input, + const struct dc_plane_address *address, + bool flip_immediate) +{ + struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input); + + uint32_t value = 0; + + value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmGRPH_FLIP_CONTROL)); + if (flip_immediate) { + set_reg_field_value(value, 1, GRPH_FLIP_CONTROL, GRPH_SURFACE_UPDATE_IMMEDIATE_EN); + set_reg_field_value(value, 1, GRPH_FLIP_CONTROL, GRPH_SURFACE_UPDATE_H_RETRACE_EN); + } else { + set_reg_field_value(value, 0, GRPH_FLIP_CONTROL, GRPH_SURFACE_UPDATE_IMMEDIATE_EN); + set_reg_field_value(value, 0, GRPH_FLIP_CONTROL, GRPH_SURFACE_UPDATE_H_RETRACE_EN); + } + dm_write_reg(mem_input110->base.ctx, DCP_REG(mmGRPH_FLIP_CONTROL), value); + + switch (address->type) { + case PLN_ADDR_TYPE_GRAPHICS: + if (address->grph.addr.quad_part == 0) + break; + program_pri_addr(mem_input110, address->grph.addr); + break; + case PLN_ADDR_TYPE_GRPH_STEREO: + if (address->grph_stereo.left_addr.quad_part == 0 + || address->grph_stereo.right_addr.quad_part == 0) + break; + program_pri_addr(mem_input110, address->grph_stereo.left_addr); + program_sec_addr(mem_input110, address->grph_stereo.right_addr); + break; + default: + /* not supported */ + BREAK_TO_DEBUGGER(); + break; + } + + mem_input->request_address = *address; + if (flip_immediate) + mem_input->current_address = *address; + + return true; +} + +/* Scatter Gather param tables */ +static const unsigned int dvmm_Hw_Setting_2DTiling[4][9] = { + { 8, 64, 64, 8, 8, 1, 4, 0, 0}, + { 16, 64, 32, 8, 16, 1, 8, 0, 0}, + { 32, 32, 32, 16, 16, 1, 8, 0, 0}, + { 64, 8, 32, 16, 16, 1, 8, 0, 0}, /* fake */ +}; + +static const unsigned int dvmm_Hw_Setting_1DTiling[4][9] = { + { 8, 512, 8, 1, 0, 1, 0, 0, 0}, /* 0 for invalid */ + { 16, 256, 8, 2, 0, 1, 0, 0, 0}, + { 32, 128, 8, 4, 0, 1, 0, 0, 0}, + { 64, 64, 8, 4, 0, 1, 0, 0, 0}, /* fake */ +}; + +static const unsigned int dvmm_Hw_Setting_Linear[4][9] = { + { 8, 4096, 1, 8, 0, 1, 0, 0, 0}, + { 16, 2048, 1, 8, 0, 1, 0, 0, 0}, + { 32, 1024, 1, 8, 0, 1, 0, 0, 0}, + { 64, 512, 1, 8, 0, 1, 0, 0, 0}, /* new for 64bpp from HW */ +}; + +/* Helper to get table entry from surface info */ +static const unsigned int *get_dvmm_hw_setting( + union dc_tiling_info *tiling_info, + enum surface_pixel_format format) +{ + enum bits_per_pixel { + bpp_8 = 0, + bpp_16, + bpp_32, + bpp_64 + } bpp; + + if (format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616) + bpp = bpp_64; + else if (format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB8888) + bpp = bpp_32; + else if (format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB1555) + bpp = bpp_16; + else + bpp = bpp_8; + + switch (tiling_info->gfx8.array_mode) { + case DC_ARRAY_1D_TILED_THIN1: + case DC_ARRAY_1D_TILED_THICK: + case DC_ARRAY_PRT_TILED_THIN1: + return dvmm_Hw_Setting_1DTiling[bpp]; + case DC_ARRAY_2D_TILED_THIN1: + case DC_ARRAY_2D_TILED_THICK: + case DC_ARRAY_2D_TILED_X_THICK: + case DC_ARRAY_PRT_2D_TILED_THIN1: + case DC_ARRAY_PRT_2D_TILED_THICK: + return dvmm_Hw_Setting_2DTiling[bpp]; + case DC_ARRAY_LINEAR_GENERAL: + case DC_ARRAY_LINEAR_ALLIGNED: + return dvmm_Hw_Setting_Linear[bpp]; + default: + return dvmm_Hw_Setting_2DTiling[bpp]; + } +} + +bool dce110_mem_input_program_pte_vm( + struct mem_input *mem_input, + enum surface_pixel_format format, + union dc_tiling_info *tiling_info, + enum dc_rotation_angle rotation) +{ + struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input); + const unsigned int *pte = get_dvmm_hw_setting(tiling_info, format); + + unsigned int page_width = 0; + unsigned int page_height = 0; + unsigned int temp_page_width = pte[1]; + unsigned int temp_page_height = pte[2]; + unsigned int min_pte_before_flip = 0; + uint32_t value = 0; + + while ((temp_page_width >>= 1) != 0) + page_width++; + while ((temp_page_height >>= 1) != 0) + page_height++; + + switch (rotation) { + case ROTATION_ANGLE_90: + case ROTATION_ANGLE_270: + min_pte_before_flip = pte[4]; + break; + default: + min_pte_before_flip = pte[3]; + break; + } + + value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmGRPH_PIPE_OUTSTANDING_REQUEST_LIMIT)); + set_reg_field_value(value, 0xff, GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT, GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT); + dm_write_reg(mem_input110->base.ctx, DCP_REG(mmGRPH_PIPE_OUTSTANDING_REQUEST_LIMIT), value); + + value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmDVMM_PTE_CONTROL)); + set_reg_field_value(value, page_width, DVMM_PTE_CONTROL, DVMM_PAGE_WIDTH); + set_reg_field_value(value, page_height, DVMM_PTE_CONTROL, DVMM_PAGE_HEIGHT); + set_reg_field_value(value, min_pte_before_flip, DVMM_PTE_CONTROL, DVMM_MIN_PTE_BEFORE_FLIP); + dm_write_reg(mem_input110->base.ctx, DCP_REG(mmDVMM_PTE_CONTROL), value); + + value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmDVMM_PTE_ARB_CONTROL)); + set_reg_field_value(value, pte[5], DVMM_PTE_ARB_CONTROL, DVMM_PTE_REQ_PER_CHUNK); + set_reg_field_value(value, 0xff, DVMM_PTE_ARB_CONTROL, DVMM_MAX_PTE_REQ_OUTSTANDING); + dm_write_reg(mem_input110->base.ctx, DCP_REG(mmDVMM_PTE_ARB_CONTROL), value); + + return true; +} + +static void program_urgency_watermark( + const struct dc_context *ctx, + const uint32_t offset, + struct bw_watermarks marks_low, + uint32_t total_dest_line_time_ns) +{ + /* register value */ + uint32_t urgency_cntl = 0; + uint32_t wm_mask_cntl = 0; + + uint32_t urgency_addr = offset + mmDPG_PIPE_URGENCY_CONTROL; + uint32_t wm_addr = offset + mmDPG_WATERMARK_MASK_CONTROL; + + /*Write mask to enable reading/writing of watermark set A*/ + wm_mask_cntl = dm_read_reg(ctx, wm_addr); + set_reg_field_value(wm_mask_cntl, + 1, + DPG_WATERMARK_MASK_CONTROL, + URGENCY_WATERMARK_MASK); + dm_write_reg(ctx, wm_addr, wm_mask_cntl); + + urgency_cntl = dm_read_reg(ctx, urgency_addr); + + set_reg_field_value( + urgency_cntl, + marks_low.d_mark, + DPG_PIPE_URGENCY_CONTROL, + URGENCY_LOW_WATERMARK); + + set_reg_field_value( + urgency_cntl, + total_dest_line_time_ns, + DPG_PIPE_URGENCY_CONTROL, + URGENCY_HIGH_WATERMARK); + dm_write_reg(ctx, urgency_addr, urgency_cntl); + + /*Write mask to enable reading/writing of watermark set B*/ + wm_mask_cntl = dm_read_reg(ctx, wm_addr); + set_reg_field_value(wm_mask_cntl, + 2, + DPG_WATERMARK_MASK_CONTROL, + URGENCY_WATERMARK_MASK); + dm_write_reg(ctx, wm_addr, wm_mask_cntl); + + urgency_cntl = dm_read_reg(ctx, urgency_addr); + + set_reg_field_value(urgency_cntl, + marks_low.a_mark, + DPG_PIPE_URGENCY_CONTROL, + URGENCY_LOW_WATERMARK); + + set_reg_field_value(urgency_cntl, + total_dest_line_time_ns, + DPG_PIPE_URGENCY_CONTROL, + URGENCY_HIGH_WATERMARK); + dm_write_reg(ctx, urgency_addr, urgency_cntl); +} + +static void program_stutter_watermark( + const struct dc_context *ctx, + const uint32_t offset, + struct bw_watermarks marks) +{ + /* register value */ + uint32_t stutter_cntl = 0; + uint32_t wm_mask_cntl = 0; + + uint32_t stutter_addr = offset + mmDPG_PIPE_STUTTER_CONTROL; + uint32_t wm_addr = offset + mmDPG_WATERMARK_MASK_CONTROL; + + /*Write mask to enable reading/writing of watermark set A*/ + + wm_mask_cntl = dm_read_reg(ctx, wm_addr); + set_reg_field_value(wm_mask_cntl, + 1, + DPG_WATERMARK_MASK_CONTROL, + STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK); + dm_write_reg(ctx, wm_addr, wm_mask_cntl); + + stutter_cntl = dm_read_reg(ctx, stutter_addr); + + if (ctx->dc->debug.disable_stutter) { + set_reg_field_value(stutter_cntl, + 0, + DPG_PIPE_STUTTER_CONTROL, + STUTTER_ENABLE); + } else { + set_reg_field_value(stutter_cntl, + 1, + DPG_PIPE_STUTTER_CONTROL, + STUTTER_ENABLE); + } + + set_reg_field_value(stutter_cntl, + 1, + DPG_PIPE_STUTTER_CONTROL, + STUTTER_IGNORE_FBC); + + /*Write watermark set A*/ + set_reg_field_value(stutter_cntl, + marks.d_mark, + DPG_PIPE_STUTTER_CONTROL, + STUTTER_EXIT_SELF_REFRESH_WATERMARK); + dm_write_reg(ctx, stutter_addr, stutter_cntl); + + /*Write mask to enable reading/writing of watermark set B*/ + wm_mask_cntl = dm_read_reg(ctx, wm_addr); + set_reg_field_value(wm_mask_cntl, + 2, + DPG_WATERMARK_MASK_CONTROL, + STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK); + dm_write_reg(ctx, wm_addr, wm_mask_cntl); + + stutter_cntl = dm_read_reg(ctx, stutter_addr); + + /*Write watermark set B*/ + set_reg_field_value(stutter_cntl, + marks.a_mark, + DPG_PIPE_STUTTER_CONTROL, + STUTTER_EXIT_SELF_REFRESH_WATERMARK); + dm_write_reg(ctx, stutter_addr, stutter_cntl); +} + +static void program_nbp_watermark( + const struct dc_context *ctx, + const uint32_t offset, + struct bw_watermarks marks) +{ + uint32_t value; + uint32_t addr; + /* Write mask to enable reading/writing of watermark set A */ + addr = offset + mmDPG_WATERMARK_MASK_CONTROL; + value = dm_read_reg(ctx, addr); + set_reg_field_value( + value, + 1, + DPG_WATERMARK_MASK_CONTROL, + NB_PSTATE_CHANGE_WATERMARK_MASK); + dm_write_reg(ctx, addr, value); + + addr = offset + mmDPG_PIPE_NB_PSTATE_CHANGE_CONTROL; + value = dm_read_reg(ctx, addr); + set_reg_field_value( + value, + 1, + DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_ENABLE); + set_reg_field_value( + value, + 1, + DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_URGENT_DURING_REQUEST); + set_reg_field_value( + value, + 1, + DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST); + dm_write_reg(ctx, addr, value); + + /* Write watermark set A */ + value = dm_read_reg(ctx, addr); + set_reg_field_value( + value, + marks.d_mark, + DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_WATERMARK); + dm_write_reg(ctx, addr, value); + + /* Write mask to enable reading/writing of watermark set B */ + addr = offset + mmDPG_WATERMARK_MASK_CONTROL; + value = dm_read_reg(ctx, addr); + set_reg_field_value( + value, + 2, + DPG_WATERMARK_MASK_CONTROL, + NB_PSTATE_CHANGE_WATERMARK_MASK); + dm_write_reg(ctx, addr, value); + + addr = offset + mmDPG_PIPE_NB_PSTATE_CHANGE_CONTROL; + value = dm_read_reg(ctx, addr); + set_reg_field_value( + value, + 1, + DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_ENABLE); + set_reg_field_value( + value, + 1, + DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_URGENT_DURING_REQUEST); + set_reg_field_value( + value, + 1, + DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST); + dm_write_reg(ctx, addr, value); + + /* Write watermark set B */ + value = dm_read_reg(ctx, addr); + set_reg_field_value( + value, + marks.a_mark, + DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_WATERMARK); + dm_write_reg(ctx, addr, value); +} + +void dce110_mem_input_program_display_marks( + struct mem_input *mem_input, + struct bw_watermarks nbp, + struct bw_watermarks stutter, + struct bw_watermarks urgent, + uint32_t total_dest_line_time_ns) +{ + struct dce110_mem_input *bm_dce110 = TO_DCE110_MEM_INPUT(mem_input); + + program_urgency_watermark( + mem_input->ctx, + bm_dce110->offsets.dmif, + urgent, + total_dest_line_time_ns); + + program_nbp_watermark( + mem_input->ctx, + bm_dce110->offsets.dmif, + nbp); + + program_stutter_watermark( + mem_input->ctx, + bm_dce110->offsets.dmif, + stutter); +} + +static struct mem_input_funcs dce110_mem_input_funcs = { + .mem_input_program_display_marks = + dce110_mem_input_program_display_marks, + .allocate_mem_input = dce_mem_input_allocate_dmif, + .free_mem_input = dce_mem_input_free_dmif, + .mem_input_program_surface_flip_and_addr = + dce110_mem_input_program_surface_flip_and_addr, + .mem_input_program_pte_vm = + dce110_mem_input_program_pte_vm, + .mem_input_program_surface_config = + dce_mem_input_program_surface_config, + .mem_input_is_flip_pending = + dce110_mem_input_is_flip_pending, + .mem_input_update_dchub = NULL +}; +/*****************************************/ +/* Constructor, Destructor */ +/*****************************************/ + +bool dce110_mem_input_construct( + struct dce110_mem_input *mem_input110, + struct dc_context *ctx, + uint32_t inst, + const struct dce110_mem_input_reg_offsets *offsets) +{ + /* supported stutter method + * STUTTER_MODE_ENHANCED + * STUTTER_MODE_QUAD_DMIF_BUFFER + * STUTTER_MODE_WATERMARK_NBP_STATE + */ + mem_input110->base.funcs = &dce110_mem_input_funcs; + mem_input110->base.ctx = ctx; + + mem_input110->base.inst = inst; + + mem_input110->offsets = *offsets; + + return true; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.h new file mode 100644 index 000000000000..83b2df93ce49 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.h @@ -0,0 +1,131 @@ +/* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_MEM_INPUT_DCE110_H__ +#define __DC_MEM_INPUT_DCE110_H__ + +#include "mem_input.h" + +#define TO_DCE110_MEM_INPUT(mi)\ + container_of(mi, struct dce110_mem_input, base) + +struct dce110_mem_input_reg_offsets { + uint32_t dcp; + uint32_t dmif; + uint32_t pipe; +}; + +struct dce110_mem_input { + struct mem_input base; + struct dce110_mem_input_reg_offsets offsets; +}; + +bool dce110_mem_input_construct( + struct dce110_mem_input *mem_input110, + struct dc_context *ctx, + uint32_t inst, + const struct dce110_mem_input_reg_offsets *offsets); + +/* + * dce110_mem_input_program_display_marks + * + * This function will program nbp stutter and urgency watermarks to minimum + * allowable values + */ +void dce110_mem_input_program_display_marks( + struct mem_input *mem_input, + struct bw_watermarks nbp, + struct bw_watermarks stutter, + struct bw_watermarks urgent, + uint32_t total_dest_line_time_ns); + +/* + * dce110_allocate_mem_input + * + * This function will allocate a dmif buffer and program required + * pixel duration for pipe + */ +void dce110_allocate_mem_input( + struct mem_input *mem_input, + uint32_t h_total,/* for current stream */ + uint32_t v_total,/* for current stream */ + uint32_t pix_clk_khz,/* for current stream */ + uint32_t total_stream_num); + +/* + * dce110_free_mem_input + * + * This function will deallocate a dmif buffer from pipe + */ +void dce110_free_mem_input( + struct mem_input *mem_input, + uint32_t total_stream_num); + +/* + * dce110_mem_input_program_surface_flip_and_addr + * + * This function programs hsync/vsync mode and surface address + */ +bool dce110_mem_input_program_surface_flip_and_addr( + struct mem_input *mem_input, + const struct dc_plane_address *address, + bool flip_immediate); + +/* + * dce110_mem_input_program_surface_config + * + * This function will program surface tiling, size, rotation and pixel format + * to corresponding dcp registers. + */ +bool dce110_mem_input_program_surface_config( + struct mem_input *mem_input, + enum surface_pixel_format format, + union dc_tiling_info *tiling_info, + union plane_size *plane_size, + enum dc_rotation_angle rotation, + struct dc_plane_dcc_param *dcc, + bool horizontal_mirror); + +/* + * dce110_mem_input_program_pte_vm + * + * This function will program pte vm registers. + */ +bool dce110_mem_input_program_pte_vm( + struct mem_input *mem_input, + enum surface_pixel_format format, + union dc_tiling_info *tiling_info, + enum dc_rotation_angle rotation); + +/* + * dce110_mem_input_is_flip_pending + * + * This function will wait until the surface update-pending bit is cleared. + * This is necessary when a flip immediate call is requested as we shouldn't + * return until the flip has actually occurred. + */ +bool dce110_mem_input_is_flip_pending( + struct mem_input *mem_input); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c new file mode 100644 index 000000000000..f0310bab4030 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c @@ -0,0 +1,1081 @@ +/* + * Copyright 2012-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#include "dm_services.h" + +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" +/* TODO: this needs to be looked at, used by Stella's workaround*/ +#include "gmc/gmc_8_2_d.h" +#include "gmc/gmc_8_2_sh_mask.h" + +#include "include/logger_interface.h" +#include "inc/bandwidth_calcs.h" + +#include "dce110_mem_input.h" + +#define DCP_REG(reg) (reg + mem_input110->offsets.dcp) +/*#define DMIF_REG(reg) (reg + mem_input110->offsets.dmif)*/ +/*#define PIPE_REG(reg) (reg + mem_input110->offsets.pipe)*/ + +static const struct dce110_mem_input_reg_offsets dce110_mi_v_reg_offsets[] = { + { + .dcp = 0, + .dmif = 0, + .pipe = 0, + } +}; + +static void set_flip_control( + struct dce110_mem_input *mem_input110, + bool immediate) +{ + uint32_t value = 0; + + value = dm_read_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_FLIP_CONTROL)); + + set_reg_field_value(value, 1, + UNP_FLIP_CONTROL, + GRPH_SURFACE_UPDATE_PENDING_MODE); + + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_FLIP_CONTROL), + value); +} + +/* chroma part */ +static void program_pri_addr_c( + struct dce110_mem_input *mem_input110, + PHYSICAL_ADDRESS_LOC address) +{ + uint32_t value = 0; + uint32_t temp = 0; + /*high register MUST be programmed first*/ + temp = address.high_part & +UNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C__GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C_MASK; + + set_reg_field_value(value, temp, + UNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C, + GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C); + + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C), + value); + + temp = 0; + value = 0; + temp = address.low_part >> + UNP_GRPH_PRIMARY_SURFACE_ADDRESS_C__GRPH_PRIMARY_SURFACE_ADDRESS_C__SHIFT; + + set_reg_field_value(value, temp, + UNP_GRPH_PRIMARY_SURFACE_ADDRESS_C, + GRPH_PRIMARY_SURFACE_ADDRESS_C); + + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_C), + value); +} + +/* luma part */ +static void program_pri_addr_l( + struct dce110_mem_input *mem_input110, + PHYSICAL_ADDRESS_LOC address) +{ + uint32_t value = 0; + uint32_t temp = 0; + + /*high register MUST be programmed first*/ + temp = address.high_part & +UNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L__GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L_MASK; + + set_reg_field_value(value, temp, + UNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L, + GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L); + + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L), + value); + + temp = 0; + value = 0; + temp = address.low_part >> + UNP_GRPH_PRIMARY_SURFACE_ADDRESS_L__GRPH_PRIMARY_SURFACE_ADDRESS_L__SHIFT; + + set_reg_field_value(value, temp, + UNP_GRPH_PRIMARY_SURFACE_ADDRESS_L, + GRPH_PRIMARY_SURFACE_ADDRESS_L); + + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_L), + value); +} + +static void program_addr( + struct dce110_mem_input *mem_input110, + const struct dc_plane_address *addr) +{ + switch (addr->type) { + case PLN_ADDR_TYPE_GRAPHICS: + program_pri_addr_l( + mem_input110, + addr->grph.addr); + break; + case PLN_ADDR_TYPE_VIDEO_PROGRESSIVE: + program_pri_addr_l( + mem_input110, + addr->video_progressive.luma_addr); + program_pri_addr_c( + mem_input110, + addr->video_progressive.chroma_addr); + break; + default: + /* not supported */ + BREAK_TO_DEBUGGER(); + } +} + +static void enable(struct dce110_mem_input *mem_input110) +{ + uint32_t value = 0; + + value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmUNP_GRPH_ENABLE)); + set_reg_field_value(value, 1, UNP_GRPH_ENABLE, GRPH_ENABLE); + dm_write_reg(mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_ENABLE), + value); +} + +static void program_tiling( + struct dce110_mem_input *mem_input110, + const union dc_tiling_info *info, + const enum surface_pixel_format pixel_format) +{ + uint32_t value = 0; + + set_reg_field_value(value, info->gfx8.num_banks, + UNP_GRPH_CONTROL, GRPH_NUM_BANKS); + + set_reg_field_value(value, info->gfx8.bank_width, + UNP_GRPH_CONTROL, GRPH_BANK_WIDTH_L); + + set_reg_field_value(value, info->gfx8.bank_height, + UNP_GRPH_CONTROL, GRPH_BANK_HEIGHT_L); + + set_reg_field_value(value, info->gfx8.tile_aspect, + UNP_GRPH_CONTROL, GRPH_MACRO_TILE_ASPECT_L); + + set_reg_field_value(value, info->gfx8.tile_split, + UNP_GRPH_CONTROL, GRPH_TILE_SPLIT_L); + + set_reg_field_value(value, info->gfx8.tile_mode, + UNP_GRPH_CONTROL, GRPH_MICRO_TILE_MODE_L); + + set_reg_field_value(value, info->gfx8.pipe_config, + UNP_GRPH_CONTROL, GRPH_PIPE_CONFIG); + + set_reg_field_value(value, info->gfx8.array_mode, + UNP_GRPH_CONTROL, GRPH_ARRAY_MODE); + + set_reg_field_value(value, 1, + UNP_GRPH_CONTROL, GRPH_COLOR_EXPANSION_MODE); + + set_reg_field_value(value, 0, + UNP_GRPH_CONTROL, GRPH_Z); + + dm_write_reg( + mem_input110->base.ctx, + mmUNP_GRPH_CONTROL, + value); + + value = 0; + + set_reg_field_value(value, info->gfx8.bank_width_c, + UNP_GRPH_CONTROL_C, GRPH_BANK_WIDTH_C); + + set_reg_field_value(value, info->gfx8.bank_height_c, + UNP_GRPH_CONTROL_C, GRPH_BANK_HEIGHT_C); + + set_reg_field_value(value, info->gfx8.tile_aspect_c, + UNP_GRPH_CONTROL_C, GRPH_MACRO_TILE_ASPECT_C); + + set_reg_field_value(value, info->gfx8.tile_split_c, + UNP_GRPH_CONTROL_C, GRPH_TILE_SPLIT_C); + + set_reg_field_value(value, info->gfx8.tile_mode_c, + UNP_GRPH_CONTROL_C, GRPH_MICRO_TILE_MODE_C); + + dm_write_reg( + mem_input110->base.ctx, + mmUNP_GRPH_CONTROL_C, + value); +} + +static void program_size_and_rotation( + struct dce110_mem_input *mem_input110, + enum dc_rotation_angle rotation, + const union plane_size *plane_size) +{ + uint32_t value = 0; + union plane_size local_size = *plane_size; + + if (rotation == ROTATION_ANGLE_90 || + rotation == ROTATION_ANGLE_270) { + + uint32_t swap; + swap = local_size.video.luma_size.x; + local_size.video.luma_size.x = + local_size.video.luma_size.y; + local_size.video.luma_size.y = swap; + + swap = local_size.video.luma_size.width; + local_size.video.luma_size.width = + local_size.video.luma_size.height; + local_size.video.luma_size.height = swap; + + swap = local_size.video.chroma_size.x; + local_size.video.chroma_size.x = + local_size.video.chroma_size.y; + local_size.video.chroma_size.y = swap; + + swap = local_size.video.chroma_size.width; + local_size.video.chroma_size.width = + local_size.video.chroma_size.height; + local_size.video.chroma_size.height = swap; + } + + value = 0; + set_reg_field_value(value, local_size.video.luma_pitch, + UNP_GRPH_PITCH_L, GRPH_PITCH_L); + + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_PITCH_L), + value); + + value = 0; + set_reg_field_value(value, local_size.video.chroma_pitch, + UNP_GRPH_PITCH_C, GRPH_PITCH_C); + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_PITCH_C), + value); + + value = 0; + set_reg_field_value(value, 0, + UNP_GRPH_X_START_L, GRPH_X_START_L); + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_X_START_L), + value); + + value = 0; + set_reg_field_value(value, 0, + UNP_GRPH_X_START_C, GRPH_X_START_C); + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_X_START_C), + value); + + value = 0; + set_reg_field_value(value, 0, + UNP_GRPH_Y_START_L, GRPH_Y_START_L); + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_Y_START_L), + value); + + value = 0; + set_reg_field_value(value, 0, + UNP_GRPH_Y_START_C, GRPH_Y_START_C); + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_Y_START_C), + value); + + value = 0; + set_reg_field_value(value, local_size.video.luma_size.x + + local_size.video.luma_size.width, + UNP_GRPH_X_END_L, GRPH_X_END_L); + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_X_END_L), + value); + + value = 0; + set_reg_field_value(value, local_size.video.chroma_size.x + + local_size.video.chroma_size.width, + UNP_GRPH_X_END_C, GRPH_X_END_C); + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_X_END_C), + value); + + value = 0; + set_reg_field_value(value, local_size.video.luma_size.y + + local_size.video.luma_size.height, + UNP_GRPH_Y_END_L, GRPH_Y_END_L); + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_Y_END_L), + value); + + value = 0; + set_reg_field_value(value, local_size.video.chroma_size.y + + local_size.video.chroma_size.height, + UNP_GRPH_Y_END_C, GRPH_Y_END_C); + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_Y_END_C), + value); + + value = 0; + switch (rotation) { + case ROTATION_ANGLE_90: + set_reg_field_value(value, 3, + UNP_HW_ROTATION, ROTATION_ANGLE); + break; + case ROTATION_ANGLE_180: + set_reg_field_value(value, 2, + UNP_HW_ROTATION, ROTATION_ANGLE); + break; + case ROTATION_ANGLE_270: + set_reg_field_value(value, 1, + UNP_HW_ROTATION, ROTATION_ANGLE); + break; + default: + set_reg_field_value(value, 0, + UNP_HW_ROTATION, ROTATION_ANGLE); + break; + } + + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_HW_ROTATION), + value); +} + +static void program_pixel_format( + struct dce110_mem_input *mem_input110, + enum surface_pixel_format format) +{ + if (format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) { + uint32_t value; + uint8_t grph_depth; + uint8_t grph_format; + + value = dm_read_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_CONTROL)); + + switch (format) { + case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS: + grph_depth = 0; + grph_format = 0; + break; + case SURFACE_PIXEL_FORMAT_GRPH_RGB565: + grph_depth = 1; + grph_format = 1; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: + case SURFACE_PIXEL_FORMAT_GRPH_BGRA8888: + grph_depth = 2; + grph_format = 0; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: + grph_depth = 2; + grph_format = 1; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: + grph_depth = 3; + grph_format = 0; + break; + default: + grph_depth = 2; + grph_format = 0; + break; + } + + set_reg_field_value( + value, + grph_depth, + UNP_GRPH_CONTROL, + GRPH_DEPTH); + set_reg_field_value( + value, + grph_format, + UNP_GRPH_CONTROL, + GRPH_FORMAT); + + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_CONTROL), + value); + + value = dm_read_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_CONTROL_EXP)); + + /* VIDEO FORMAT 0 */ + set_reg_field_value( + value, + 0, + UNP_GRPH_CONTROL_EXP, + VIDEO_FORMAT); + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_CONTROL_EXP), + value); + + } else { + /* Video 422 and 420 needs UNP_GRPH_CONTROL_EXP programmed */ + uint32_t value; + uint8_t video_format; + + value = dm_read_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_CONTROL_EXP)); + + switch (format) { + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: + video_format = 2; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: + video_format = 3; + break; + default: + video_format = 0; + break; + } + + set_reg_field_value( + value, + video_format, + UNP_GRPH_CONTROL_EXP, + VIDEO_FORMAT); + + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_CONTROL_EXP), + value); + } +} + +bool dce110_mem_input_v_is_surface_pending(struct mem_input *mem_input) +{ + struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input); + uint32_t value; + + value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmUNP_GRPH_UPDATE)); + + if (get_reg_field_value(value, UNP_GRPH_UPDATE, + GRPH_SURFACE_UPDATE_PENDING)) + return true; + + mem_input->current_address = mem_input->request_address; + return false; +} + +bool dce110_mem_input_v_program_surface_flip_and_addr( + struct mem_input *mem_input, + const struct dc_plane_address *address, + bool flip_immediate) +{ + struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input); + + set_flip_control(mem_input110, flip_immediate); + program_addr(mem_input110, + address); + + mem_input->request_address = *address; + + return true; +} + +/* Scatter Gather param tables */ +static const unsigned int dvmm_Hw_Setting_2DTiling[4][9] = { + { 8, 64, 64, 8, 8, 1, 4, 0, 0}, + { 16, 64, 32, 8, 16, 1, 8, 0, 0}, + { 32, 32, 32, 16, 16, 1, 8, 0, 0}, + { 64, 8, 32, 16, 16, 1, 8, 0, 0}, /* fake */ +}; + +static const unsigned int dvmm_Hw_Setting_1DTiling[4][9] = { + { 8, 512, 8, 1, 0, 1, 0, 0, 0}, /* 0 for invalid */ + { 16, 256, 8, 2, 0, 1, 0, 0, 0}, + { 32, 128, 8, 4, 0, 1, 0, 0, 0}, + { 64, 64, 8, 4, 0, 1, 0, 0, 0}, /* fake */ +}; + +static const unsigned int dvmm_Hw_Setting_Linear[4][9] = { + { 8, 4096, 1, 8, 0, 1, 0, 0, 0}, + { 16, 2048, 1, 8, 0, 1, 0, 0, 0}, + { 32, 1024, 1, 8, 0, 1, 0, 0, 0}, + { 64, 512, 1, 8, 0, 1, 0, 0, 0}, /* new for 64bpp from HW */ +}; + +/* Helper to get table entry from surface info */ +static const unsigned int *get_dvmm_hw_setting( + union dc_tiling_info *tiling_info, + enum surface_pixel_format format, + bool chroma) +{ + enum bits_per_pixel { + bpp_8 = 0, + bpp_16, + bpp_32, + bpp_64 + } bpp; + + if (format >= SURFACE_PIXEL_FORMAT_INVALID) + bpp = bpp_32; + else if (format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) + bpp = chroma ? bpp_16 : bpp_8; + else + bpp = bpp_8; + + switch (tiling_info->gfx8.array_mode) { + case DC_ARRAY_1D_TILED_THIN1: + case DC_ARRAY_1D_TILED_THICK: + case DC_ARRAY_PRT_TILED_THIN1: + return dvmm_Hw_Setting_1DTiling[bpp]; + case DC_ARRAY_2D_TILED_THIN1: + case DC_ARRAY_2D_TILED_THICK: + case DC_ARRAY_2D_TILED_X_THICK: + case DC_ARRAY_PRT_2D_TILED_THIN1: + case DC_ARRAY_PRT_2D_TILED_THICK: + return dvmm_Hw_Setting_2DTiling[bpp]; + case DC_ARRAY_LINEAR_GENERAL: + case DC_ARRAY_LINEAR_ALLIGNED: + return dvmm_Hw_Setting_Linear[bpp]; + default: + return dvmm_Hw_Setting_2DTiling[bpp]; + } +} + +bool dce110_mem_input_v_program_pte_vm( + struct mem_input *mem_input, + enum surface_pixel_format format, + union dc_tiling_info *tiling_info, + enum dc_rotation_angle rotation) +{ + struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input); + const unsigned int *pte = get_dvmm_hw_setting(tiling_info, format, false); + const unsigned int *pte_chroma = get_dvmm_hw_setting(tiling_info, format, true); + + unsigned int page_width = 0; + unsigned int page_height = 0; + unsigned int page_width_chroma = 0; + unsigned int page_height_chroma = 0; + unsigned int temp_page_width = pte[1]; + unsigned int temp_page_height = pte[2]; + unsigned int min_pte_before_flip = 0; + unsigned int min_pte_before_flip_chroma = 0; + uint32_t value = 0; + + while ((temp_page_width >>= 1) != 0) + page_width++; + while ((temp_page_height >>= 1) != 0) + page_height++; + + temp_page_width = pte_chroma[1]; + temp_page_height = pte_chroma[2]; + while ((temp_page_width >>= 1) != 0) + page_width_chroma++; + while ((temp_page_height >>= 1) != 0) + page_height_chroma++; + + switch (rotation) { + case ROTATION_ANGLE_90: + case ROTATION_ANGLE_270: + min_pte_before_flip = pte[4]; + min_pte_before_flip_chroma = pte_chroma[4]; + break; + default: + min_pte_before_flip = pte[3]; + min_pte_before_flip_chroma = pte_chroma[3]; + break; + } + + value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmUNP_PIPE_OUTSTANDING_REQUEST_LIMIT)); + /* TODO: un-hardcode requestlimit */ + set_reg_field_value(value, 0xff, UNP_PIPE_OUTSTANDING_REQUEST_LIMIT, UNP_PIPE_OUTSTANDING_REQUEST_LIMIT_L); + set_reg_field_value(value, 0xff, UNP_PIPE_OUTSTANDING_REQUEST_LIMIT, UNP_PIPE_OUTSTANDING_REQUEST_LIMIT_C); + dm_write_reg(mem_input110->base.ctx, DCP_REG(mmUNP_PIPE_OUTSTANDING_REQUEST_LIMIT), value); + + value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmUNP_DVMM_PTE_CONTROL)); + set_reg_field_value(value, page_width, UNP_DVMM_PTE_CONTROL, DVMM_PAGE_WIDTH); + set_reg_field_value(value, page_height, UNP_DVMM_PTE_CONTROL, DVMM_PAGE_HEIGHT); + set_reg_field_value(value, min_pte_before_flip, UNP_DVMM_PTE_CONTROL, DVMM_MIN_PTE_BEFORE_FLIP); + dm_write_reg(mem_input110->base.ctx, DCP_REG(mmUNP_DVMM_PTE_CONTROL), value); + + value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmUNP_DVMM_PTE_ARB_CONTROL)); + set_reg_field_value(value, pte[5], UNP_DVMM_PTE_ARB_CONTROL, DVMM_PTE_REQ_PER_CHUNK); + set_reg_field_value(value, 0xff, UNP_DVMM_PTE_ARB_CONTROL, DVMM_MAX_PTE_REQ_OUTSTANDING); + dm_write_reg(mem_input110->base.ctx, DCP_REG(mmUNP_DVMM_PTE_ARB_CONTROL), value); + + value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmUNP_DVMM_PTE_CONTROL_C)); + set_reg_field_value(value, page_width_chroma, UNP_DVMM_PTE_CONTROL_C, DVMM_PAGE_WIDTH_C); + set_reg_field_value(value, page_height_chroma, UNP_DVMM_PTE_CONTROL_C, DVMM_PAGE_HEIGHT_C); + set_reg_field_value(value, min_pte_before_flip_chroma, UNP_DVMM_PTE_CONTROL_C, DVMM_MIN_PTE_BEFORE_FLIP_C); + dm_write_reg(mem_input110->base.ctx, DCP_REG(mmUNP_DVMM_PTE_CONTROL_C), value); + + value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmUNP_DVMM_PTE_ARB_CONTROL_C)); + set_reg_field_value(value, pte_chroma[5], UNP_DVMM_PTE_ARB_CONTROL_C, DVMM_PTE_REQ_PER_CHUNK_C); + set_reg_field_value(value, 0xff, UNP_DVMM_PTE_ARB_CONTROL_C, DVMM_MAX_PTE_REQ_OUTSTANDING_C); + dm_write_reg(mem_input110->base.ctx, DCP_REG(mmUNP_DVMM_PTE_ARB_CONTROL_C), value); + + return true; +} + +bool dce110_mem_input_v_program_surface_config( + struct mem_input *mem_input, + enum surface_pixel_format format, + union dc_tiling_info *tiling_info, + union plane_size *plane_size, + enum dc_rotation_angle rotation, + struct dc_plane_dcc_param *dcc, + bool horizotal_mirror) +{ + struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input); + + enable(mem_input110); + program_tiling(mem_input110, tiling_info, format); + program_size_and_rotation(mem_input110, rotation, plane_size); + program_pixel_format(mem_input110, format); + + return true; +} + +static void program_urgency_watermark( + const struct dc_context *ctx, + const uint32_t urgency_addr, + const uint32_t wm_addr, + struct bw_watermarks marks_low, + uint32_t total_dest_line_time_ns) +{ + /* register value */ + uint32_t urgency_cntl = 0; + uint32_t wm_mask_cntl = 0; + + /*Write mask to enable reading/writing of watermark set A*/ + wm_mask_cntl = dm_read_reg(ctx, wm_addr); + set_reg_field_value(wm_mask_cntl, + 1, + DPGV0_WATERMARK_MASK_CONTROL, + URGENCY_WATERMARK_MASK); + dm_write_reg(ctx, wm_addr, wm_mask_cntl); + + urgency_cntl = dm_read_reg(ctx, urgency_addr); + + set_reg_field_value( + urgency_cntl, + marks_low.a_mark, + DPGV0_PIPE_URGENCY_CONTROL, + URGENCY_LOW_WATERMARK); + + set_reg_field_value( + urgency_cntl, + total_dest_line_time_ns, + DPGV0_PIPE_URGENCY_CONTROL, + URGENCY_HIGH_WATERMARK); + dm_write_reg(ctx, urgency_addr, urgency_cntl); + + /*Write mask to enable reading/writing of watermark set B*/ + wm_mask_cntl = dm_read_reg(ctx, wm_addr); + set_reg_field_value(wm_mask_cntl, + 2, + DPGV0_WATERMARK_MASK_CONTROL, + URGENCY_WATERMARK_MASK); + dm_write_reg(ctx, wm_addr, wm_mask_cntl); + + urgency_cntl = dm_read_reg(ctx, urgency_addr); + + set_reg_field_value(urgency_cntl, + marks_low.b_mark, + DPGV0_PIPE_URGENCY_CONTROL, + URGENCY_LOW_WATERMARK); + + set_reg_field_value(urgency_cntl, + total_dest_line_time_ns, + DPGV0_PIPE_URGENCY_CONTROL, + URGENCY_HIGH_WATERMARK); + + dm_write_reg(ctx, urgency_addr, urgency_cntl); +} + +static void program_urgency_watermark_l( + const struct dc_context *ctx, + struct bw_watermarks marks_low, + uint32_t total_dest_line_time_ns) +{ + program_urgency_watermark( + ctx, + mmDPGV0_PIPE_URGENCY_CONTROL, + mmDPGV0_WATERMARK_MASK_CONTROL, + marks_low, + total_dest_line_time_ns); +} + +static void program_urgency_watermark_c( + const struct dc_context *ctx, + struct bw_watermarks marks_low, + uint32_t total_dest_line_time_ns) +{ + program_urgency_watermark( + ctx, + mmDPGV1_PIPE_URGENCY_CONTROL, + mmDPGV1_WATERMARK_MASK_CONTROL, + marks_low, + total_dest_line_time_ns); +} + +static void program_stutter_watermark( + const struct dc_context *ctx, + const uint32_t stutter_addr, + const uint32_t wm_addr, + struct bw_watermarks marks) +{ + /* register value */ + uint32_t stutter_cntl = 0; + uint32_t wm_mask_cntl = 0; + + /*Write mask to enable reading/writing of watermark set A*/ + + wm_mask_cntl = dm_read_reg(ctx, wm_addr); + set_reg_field_value(wm_mask_cntl, + 1, + DPGV0_WATERMARK_MASK_CONTROL, + STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK); + dm_write_reg(ctx, wm_addr, wm_mask_cntl); + + stutter_cntl = dm_read_reg(ctx, stutter_addr); + + if (ctx->dc->debug.disable_stutter) { + set_reg_field_value(stutter_cntl, + 0, + DPGV0_PIPE_STUTTER_CONTROL, + STUTTER_ENABLE); + } else { + set_reg_field_value(stutter_cntl, + 1, + DPGV0_PIPE_STUTTER_CONTROL, + STUTTER_ENABLE); + } + + set_reg_field_value(stutter_cntl, + 1, + DPGV0_PIPE_STUTTER_CONTROL, + STUTTER_IGNORE_FBC); + + /*Write watermark set A*/ + set_reg_field_value(stutter_cntl, + marks.a_mark, + DPGV0_PIPE_STUTTER_CONTROL, + STUTTER_EXIT_SELF_REFRESH_WATERMARK); + dm_write_reg(ctx, stutter_addr, stutter_cntl); + + /*Write mask to enable reading/writing of watermark set B*/ + wm_mask_cntl = dm_read_reg(ctx, wm_addr); + set_reg_field_value(wm_mask_cntl, + 2, + DPGV0_WATERMARK_MASK_CONTROL, + STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK); + dm_write_reg(ctx, wm_addr, wm_mask_cntl); + + stutter_cntl = dm_read_reg(ctx, stutter_addr); + /*Write watermark set B*/ + set_reg_field_value(stutter_cntl, + marks.b_mark, + DPGV0_PIPE_STUTTER_CONTROL, + STUTTER_EXIT_SELF_REFRESH_WATERMARK); + dm_write_reg(ctx, stutter_addr, stutter_cntl); +} + +static void program_stutter_watermark_l( + const struct dc_context *ctx, + struct bw_watermarks marks) +{ + program_stutter_watermark(ctx, + mmDPGV0_PIPE_STUTTER_CONTROL, + mmDPGV0_WATERMARK_MASK_CONTROL, + marks); +} + +static void program_stutter_watermark_c( + const struct dc_context *ctx, + struct bw_watermarks marks) +{ + program_stutter_watermark(ctx, + mmDPGV1_PIPE_STUTTER_CONTROL, + mmDPGV1_WATERMARK_MASK_CONTROL, + marks); +} + +static void program_nbp_watermark( + const struct dc_context *ctx, + const uint32_t wm_mask_ctrl_addr, + const uint32_t nbp_pstate_ctrl_addr, + struct bw_watermarks marks) +{ + uint32_t value; + + /* Write mask to enable reading/writing of watermark set A */ + + value = dm_read_reg(ctx, wm_mask_ctrl_addr); + + set_reg_field_value( + value, + 1, + DPGV0_WATERMARK_MASK_CONTROL, + NB_PSTATE_CHANGE_WATERMARK_MASK); + dm_write_reg(ctx, wm_mask_ctrl_addr, value); + + value = dm_read_reg(ctx, nbp_pstate_ctrl_addr); + + set_reg_field_value( + value, + 1, + DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_ENABLE); + set_reg_field_value( + value, + 1, + DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_URGENT_DURING_REQUEST); + set_reg_field_value( + value, + 1, + DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST); + dm_write_reg(ctx, nbp_pstate_ctrl_addr, value); + + /* Write watermark set A */ + value = dm_read_reg(ctx, nbp_pstate_ctrl_addr); + set_reg_field_value( + value, + marks.a_mark, + DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_WATERMARK); + dm_write_reg(ctx, nbp_pstate_ctrl_addr, value); + + /* Write mask to enable reading/writing of watermark set B */ + value = dm_read_reg(ctx, wm_mask_ctrl_addr); + set_reg_field_value( + value, + 2, + DPGV0_WATERMARK_MASK_CONTROL, + NB_PSTATE_CHANGE_WATERMARK_MASK); + dm_write_reg(ctx, wm_mask_ctrl_addr, value); + + value = dm_read_reg(ctx, nbp_pstate_ctrl_addr); + set_reg_field_value( + value, + 1, + DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_ENABLE); + set_reg_field_value( + value, + 1, + DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_URGENT_DURING_REQUEST); + set_reg_field_value( + value, + 1, + DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST); + dm_write_reg(ctx, nbp_pstate_ctrl_addr, value); + + /* Write watermark set B */ + value = dm_read_reg(ctx, nbp_pstate_ctrl_addr); + set_reg_field_value( + value, + marks.b_mark, + DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_WATERMARK); + dm_write_reg(ctx, nbp_pstate_ctrl_addr, value); +} + +static void program_nbp_watermark_l( + const struct dc_context *ctx, + struct bw_watermarks marks) +{ + program_nbp_watermark(ctx, + mmDPGV0_WATERMARK_MASK_CONTROL, + mmDPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL, + marks); +} + +static void program_nbp_watermark_c( + const struct dc_context *ctx, + struct bw_watermarks marks) +{ + program_nbp_watermark(ctx, + mmDPGV1_WATERMARK_MASK_CONTROL, + mmDPGV1_PIPE_NB_PSTATE_CHANGE_CONTROL, + marks); +} + +void dce110_mem_input_v_program_display_marks( + struct mem_input *mem_input, + struct bw_watermarks nbp, + struct bw_watermarks stutter, + struct bw_watermarks urgent, + uint32_t total_dest_line_time_ns) +{ + program_urgency_watermark_l( + mem_input->ctx, + urgent, + total_dest_line_time_ns); + + program_nbp_watermark_l( + mem_input->ctx, + nbp); + + program_stutter_watermark_l( + mem_input->ctx, + stutter); + +} + +void dce110_mem_input_program_chroma_display_marks( + struct mem_input *mem_input, + struct bw_watermarks nbp, + struct bw_watermarks stutter, + struct bw_watermarks urgent, + uint32_t total_dest_line_time_ns) +{ + program_urgency_watermark_c( + mem_input->ctx, + urgent, + total_dest_line_time_ns); + + program_nbp_watermark_c( + mem_input->ctx, + nbp); + + program_stutter_watermark_c( + mem_input->ctx, + stutter); +} + +void dce110_allocate_mem_input_v( + struct mem_input *mi, + uint32_t h_total,/* for current stream */ + uint32_t v_total,/* for current stream */ + uint32_t pix_clk_khz,/* for current stream */ + uint32_t total_stream_num) +{ + uint32_t addr; + uint32_t value; + uint32_t pix_dur; + if (pix_clk_khz != 0) { + addr = mmDPGV0_PIPE_ARBITRATION_CONTROL1; + value = dm_read_reg(mi->ctx, addr); + pix_dur = 1000000000ULL / pix_clk_khz; + set_reg_field_value( + value, + pix_dur, + DPGV0_PIPE_ARBITRATION_CONTROL1, + PIXEL_DURATION); + dm_write_reg(mi->ctx, addr, value); + + addr = mmDPGV1_PIPE_ARBITRATION_CONTROL1; + value = dm_read_reg(mi->ctx, addr); + pix_dur = 1000000000ULL / pix_clk_khz; + set_reg_field_value( + value, + pix_dur, + DPGV1_PIPE_ARBITRATION_CONTROL1, + PIXEL_DURATION); + dm_write_reg(mi->ctx, addr, value); + + addr = mmDPGV0_PIPE_ARBITRATION_CONTROL2; + value = 0x4000800; + dm_write_reg(mi->ctx, addr, value); + + addr = mmDPGV1_PIPE_ARBITRATION_CONTROL2; + value = 0x4000800; + dm_write_reg(mi->ctx, addr, value); + } + +} + +void dce110_free_mem_input_v( + struct mem_input *mi, + uint32_t total_stream_num) +{ +} + +static struct mem_input_funcs dce110_mem_input_v_funcs = { + .mem_input_program_display_marks = + dce110_mem_input_v_program_display_marks, + .mem_input_program_chroma_display_marks = + dce110_mem_input_program_chroma_display_marks, + .allocate_mem_input = dce110_allocate_mem_input_v, + .free_mem_input = dce110_free_mem_input_v, + .mem_input_program_surface_flip_and_addr = + dce110_mem_input_v_program_surface_flip_and_addr, + .mem_input_program_pte_vm = + dce110_mem_input_v_program_pte_vm, + .mem_input_program_surface_config = + dce110_mem_input_v_program_surface_config, + .mem_input_is_flip_pending = + dce110_mem_input_v_is_surface_pending +}; +/*****************************************/ +/* Constructor, Destructor */ +/*****************************************/ + +bool dce110_mem_input_v_construct( + struct dce110_mem_input *mem_input110, + struct dc_context *ctx) +{ + mem_input110->base.funcs = &dce110_mem_input_v_funcs; + mem_input110->base.ctx = ctx; + + mem_input110->base.inst = 0; + + mem_input110->offsets = dce110_mi_v_reg_offsets[0]; + + return true; +} + +#if 0 +void dce110_mem_input_v_destroy(struct mem_input **mem_input) +{ + dm_free(TO_DCE110_MEM_INPUT(*mem_input)); + *mem_input = NULL; +} +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.h new file mode 100644 index 000000000000..5b1796ccefc0 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.h @@ -0,0 +1,94 @@ +/* Copyright 2012-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_MEM_INPUT_V_DCE110_H__ +#define __DC_MEM_INPUT_V_DCE110_H__ + +#include "mem_input.h" +#include "dce110_mem_input.h" + +bool dce110_mem_input_v_construct( + struct dce110_mem_input *mem_input110, + struct dc_context *ctx); + +/* + * This function will program nbp stutter and urgency watermarks to minimum + * allowable values + */ +void dce110_mem_input_v_program_display_marks( + struct mem_input *mem_input, + struct bw_watermarks nbp, + struct bw_watermarks stutter, + struct bw_watermarks urgent, + uint32_t total_dest_line_time_ns); + +/* + * This function will allocate a dmif buffer and program required + * pixel duration for pipe + */ +void dce110_allocate_mem_v_input( + struct mem_input *mem_input, + uint32_t h_total,/* for current stream */ + uint32_t v_total,/* for current stream */ + uint32_t pix_clk_khz,/* for current stream */ + uint32_t total_stream_num); + +/* + * This function will deallocate a dmif buffer from pipe + */ +void dce110_free_mem_v_input( + struct mem_input *mem_input, + uint32_t total_stream_num); + +/* + * This function programs hsync/vsync mode and surface address + */ +bool dce110_mem_input_v_program_surface_flip_and_addr( + struct mem_input *mem_input, + const struct dc_plane_address *address, + bool flip_immediate); + +/* + * dce110_mem_input_v_program_scatter_gather + * + * This function will program scatter gather registers. + */ +bool dce110_mem_input_v_program_pte_vm( + struct mem_input *mem_input, + enum surface_pixel_format format, + union dc_tiling_info *tiling_info, + enum dc_rotation_angle rotation); + +/* + * This function will program surface tiling, size, rotation and pixel format + * to corresponding dcp registers. + */ +bool dce110_mem_input_v_program_surface_config( + struct mem_input *mem_input, + enum surface_pixel_format format, + union dc_tiling_info *tiling_info, + union plane_size *plane_size, + enum dc_rotation_angle rotation); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp.c new file mode 100644 index 000000000000..698ec2f55d0f --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp.c @@ -0,0 +1,77 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* include DCE11 register header files */ +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" + +#include "dce110_opp.h" + +#include "gamma_types.h" + +enum { + MAX_LUT_ENTRY = 256, + MAX_NUMBER_OF_ENTRIES = 256 +}; + +/*****************************************/ +/* Constructor, Destructor */ +/*****************************************/ + +static const struct opp_funcs funcs = { + .opp_power_on_regamma_lut = dce110_opp_power_on_regamma_lut, + .opp_set_csc_adjustment = dce110_opp_set_csc_adjustment, + .opp_set_csc_default = dce110_opp_set_csc_default, + .opp_set_dyn_expansion = dce110_opp_set_dyn_expansion, + .opp_program_regamma_pwl = dce110_opp_program_regamma_pwl, + .opp_set_regamma_mode = dce110_opp_set_regamma_mode, + .opp_destroy = dce110_opp_destroy, + .opp_program_fmt = dce110_opp_program_fmt, +}; + +bool dce110_opp_construct(struct dce110_opp *opp110, + struct dc_context *ctx, + uint32_t inst, + const struct dce110_opp_reg_offsets *offsets) +{ + opp110->base.funcs = &funcs; + + opp110->base.ctx = ctx; + + opp110->base.inst = inst; + + opp110->offsets = *offsets; + + return true; +} + +void dce110_opp_destroy(struct output_pixel_processor **opp) +{ + dm_free(FROM_DCE11_OPP(*opp)); + *opp = NULL; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp.h new file mode 100644 index 000000000000..2fbb2415cc97 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp.h @@ -0,0 +1,149 @@ +/* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_OPP_DCE110_H__ +#define __DC_OPP_DCE110_H__ + +#include "dc_types.h" +#include "opp.h" +#include "core_types.h" + +#include "gamma_types.h" /* decprecated */ + +struct gamma_parameters; + +#define FROM_DCE11_OPP(opp)\ + container_of(opp, struct dce110_opp, base) + +enum dce110_opp_reg_type { + DCE110_OPP_REG_DCP = 0, + DCE110_OPP_REG_DCFE, + DCE110_OPP_REG_FMT, + + DCE110_OPP_REG_MAX +}; + +struct dce110_regamma { + struct gamma_curve arr_curve_points[16]; + struct curve_points arr_points[3]; + uint32_t hw_points_num; + struct hw_x_point *coordinates_x; + struct pwl_result_data *rgb_resulted; + + /* re-gamma curve */ + struct pwl_float_data_ex *rgb_regamma; + /* coeff used to map user evenly distributed points + * to our hardware points (predefined) for gamma 256 */ + struct pixel_gamma_point *coeff128; + struct pixel_gamma_point *coeff128_oem; + /* coeff used to map user evenly distributed points + * to our hardware points (predefined) for gamma 1025 */ + struct pixel_gamma_point *coeff128_dx; + /* evenly distributed points, gamma 256 software points 0-255 */ + struct gamma_pixel *axis_x_256; + /* evenly distributed points, gamma 1025 software points 0-1025 */ + struct gamma_pixel *axis_x_1025; + /* OEM supplied gamma for regamma LUT */ + struct pwl_float_data *rgb_oem; + /* user supplied gamma */ + struct pwl_float_data *rgb_user; + uint32_t extra_points; + bool use_half_points; + struct fixed31_32 x_max1; + struct fixed31_32 x_max2; + struct fixed31_32 x_min; + struct fixed31_32 divider1; + struct fixed31_32 divider2; + struct fixed31_32 divider3; +}; + +/* OPP RELATED */ +#define TO_DCE110_OPP(opp)\ + container_of(opp, struct dce110_opp, base) + +struct dce110_opp_reg_offsets { + uint32_t fmt_offset; + uint32_t fmt_mem_offset; + uint32_t dcp_offset; + uint32_t dcfe_offset; +}; + +struct dce110_opp { + struct output_pixel_processor base; + struct dce110_opp_reg_offsets offsets; + struct dce110_regamma regamma; +}; + +bool dce110_opp_construct(struct dce110_opp *opp110, + struct dc_context *ctx, + uint32_t inst, + const struct dce110_opp_reg_offsets *offsets); + +void dce110_opp_destroy(struct output_pixel_processor **opp); + +/* REGAMMA RELATED */ +void dce110_opp_power_on_regamma_lut( + struct output_pixel_processor *opp, + bool power_on); + +bool dce110_opp_program_regamma_pwl( + struct output_pixel_processor *opp, + const struct pwl_params *params); + +void dce110_opp_set_regamma_mode(struct output_pixel_processor *opp, + enum opp_regamma mode); + +void dce110_opp_set_csc_adjustment( + struct output_pixel_processor *opp, + const struct out_csc_color_matrix *tbl_entry); + +void dce110_opp_set_csc_default( + struct output_pixel_processor *opp, + const struct default_adjustment *default_adjust); + +/* FORMATTER RELATED */ +void dce110_opp_program_bit_depth_reduction( + struct output_pixel_processor *opp, + const struct bit_depth_reduction_params *params); + +void dce110_opp_program_clamping_and_pixel_encoding( + struct output_pixel_processor *opp, + const struct clamping_and_pixel_encoding_params *params); + +void dce110_opp_set_dyn_expansion( + struct output_pixel_processor *opp, + enum dc_color_space color_sp, + enum dc_color_depth color_dpth, + enum signal_type signal); + +void dce110_opp_program_fmt( + struct output_pixel_processor *opp, + struct bit_depth_reduction_params *fmt_bit_depth, + struct clamping_and_pixel_encoding_params *clamping); + +void dce110_opp_set_clamping( + struct dce110_opp *opp110, + const struct clamping_and_pixel_encoding_params *params); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc.c new file mode 100644 index 000000000000..b46db202ddbb --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc.c @@ -0,0 +1,363 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "dce110_opp.h" +#include "basics/conversion.h" + +/* include DCE11 register header files */ +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" + +#define DCP_REG(reg)\ + (reg + opp110->offsets.dcp_offset) + +enum { + OUTPUT_CSC_MATRIX_SIZE = 12 +}; + +static const struct out_csc_color_matrix global_color_matrix[] = { +{ COLOR_SPACE_SRGB, + { 0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} }, +{ COLOR_SPACE_SRGB_LIMITED, + { 0x1B60, 0, 0, 0x200, 0, 0x1B60, 0, 0x200, 0, 0, 0x1B60, 0x200} }, +{ COLOR_SPACE_YCBCR601, + { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x82F, 0x1012, 0x31F, 0x200, 0xFB47, + 0xF6B9, 0xE00, 0x1000} }, +{ COLOR_SPACE_YCBCR709, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x5D2, 0x1394, 0x1FA, + 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} }, +/* TODO: correct values below */ +{ COLOR_SPACE_YCBCR601_LIMITED, { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x991, + 0x12C9, 0x3A6, 0x200, 0xFB47, 0xF6B9, 0xE00, 0x1000} }, +{ COLOR_SPACE_YCBCR709_LIMITED, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x6CE, 0x16E3, + 0x24F, 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} } +}; + +enum csc_color_mode { + /* 00 - BITS2:0 Bypass */ + CSC_COLOR_MODE_GRAPHICS_BYPASS, + /* 01 - hard coded coefficient TV RGB */ + CSC_COLOR_MODE_GRAPHICS_PREDEFINED, + /* 04 - programmable OUTPUT CSC coefficient */ + CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC, +}; + +static void program_color_matrix( + struct dce110_opp *opp110, + const struct out_csc_color_matrix *tbl_entry, + enum grph_color_adjust_option options) +{ + struct dc_context *ctx = opp110->base.ctx; + { + uint32_t value = 0; + uint32_t addr = DCP_REG(mmOUTPUT_CSC_C11_C12); + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[0], + OUTPUT_CSC_C11_C12, + OUTPUT_CSC_C11); + + set_reg_field_value( + value, + tbl_entry->regval[1], + OUTPUT_CSC_C11_C12, + OUTPUT_CSC_C12); + + dm_write_reg(ctx, addr, value); + } + { + uint32_t value = 0; + uint32_t addr = DCP_REG(mmOUTPUT_CSC_C13_C14); + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[2], + OUTPUT_CSC_C13_C14, + OUTPUT_CSC_C13); + /* fixed S0.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[3], + OUTPUT_CSC_C13_C14, + OUTPUT_CSC_C14); + + dm_write_reg(ctx, addr, value); + } + { + uint32_t value = 0; + uint32_t addr = DCP_REG(mmOUTPUT_CSC_C21_C22); + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[4], + OUTPUT_CSC_C21_C22, + OUTPUT_CSC_C21); + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[5], + OUTPUT_CSC_C21_C22, + OUTPUT_CSC_C22); + + dm_write_reg(ctx, addr, value); + } + { + uint32_t value = 0; + uint32_t addr = DCP_REG(mmOUTPUT_CSC_C23_C24); + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[6], + OUTPUT_CSC_C23_C24, + OUTPUT_CSC_C23); + /* fixed S0.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[7], + OUTPUT_CSC_C23_C24, + OUTPUT_CSC_C24); + + dm_write_reg(ctx, addr, value); + } + { + uint32_t value = 0; + uint32_t addr = DCP_REG(mmOUTPUT_CSC_C31_C32); + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[8], + OUTPUT_CSC_C31_C32, + OUTPUT_CSC_C31); + /* fixed S0.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[9], + OUTPUT_CSC_C31_C32, + OUTPUT_CSC_C32); + + dm_write_reg(ctx, addr, value); + } + { + uint32_t value = 0; + uint32_t addr = DCP_REG(mmOUTPUT_CSC_C33_C34); + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[10], + OUTPUT_CSC_C33_C34, + OUTPUT_CSC_C33); + /* fixed S0.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[11], + OUTPUT_CSC_C33_C34, + OUTPUT_CSC_C34); + + dm_write_reg(ctx, addr, value); + } +} + +static bool configure_graphics_mode( + struct dce110_opp *opp110, + enum csc_color_mode config, + enum graphics_csc_adjust_type csc_adjust_type, + enum dc_color_space color_space) +{ + struct dc_context *ctx = opp110->base.ctx; + uint32_t addr = DCP_REG(mmOUTPUT_CSC_CONTROL); + uint32_t value = dm_read_reg(ctx, addr); + + set_reg_field_value( + value, + 0, + OUTPUT_CSC_CONTROL, + OUTPUT_CSC_GRPH_MODE); + + if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_SW) { + if (config == CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC) { + set_reg_field_value( + value, + 4, + OUTPUT_CSC_CONTROL, + OUTPUT_CSC_GRPH_MODE); + } else { + + switch (color_space) { + case COLOR_SPACE_SRGB: + /* by pass */ + set_reg_field_value( + value, + 0, + OUTPUT_CSC_CONTROL, + OUTPUT_CSC_GRPH_MODE); + break; + case COLOR_SPACE_SRGB_LIMITED: + /* TV RGB */ + set_reg_field_value( + value, + 1, + OUTPUT_CSC_CONTROL, + OUTPUT_CSC_GRPH_MODE); + break; + case COLOR_SPACE_YCBCR601: + case COLOR_SPACE_YPBPR601: + case COLOR_SPACE_YCBCR601_LIMITED: + /* YCbCr601 */ + set_reg_field_value( + value, + 2, + OUTPUT_CSC_CONTROL, + OUTPUT_CSC_GRPH_MODE); + break; + case COLOR_SPACE_YCBCR709: + case COLOR_SPACE_YPBPR709: + case COLOR_SPACE_YCBCR709_LIMITED: + /* YCbCr709 */ + set_reg_field_value( + value, + 3, + OUTPUT_CSC_CONTROL, + OUTPUT_CSC_GRPH_MODE); + break; + default: + return false; + } + } + } else if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_HW) { + switch (color_space) { + case COLOR_SPACE_SRGB: + /* by pass */ + set_reg_field_value( + value, + 0, + OUTPUT_CSC_CONTROL, + OUTPUT_CSC_GRPH_MODE); + break; + case COLOR_SPACE_SRGB_LIMITED: + /* TV RGB */ + set_reg_field_value( + value, + 1, + OUTPUT_CSC_CONTROL, + OUTPUT_CSC_GRPH_MODE); + break; + case COLOR_SPACE_YCBCR601: + case COLOR_SPACE_YPBPR601: + case COLOR_SPACE_YCBCR601_LIMITED: + /* YCbCr601 */ + set_reg_field_value( + value, + 2, + OUTPUT_CSC_CONTROL, + OUTPUT_CSC_GRPH_MODE); + break; + case COLOR_SPACE_YCBCR709: + case COLOR_SPACE_YPBPR709: + case COLOR_SPACE_YCBCR709_LIMITED: + /* YCbCr709 */ + set_reg_field_value( + value, + 3, + OUTPUT_CSC_CONTROL, + OUTPUT_CSC_GRPH_MODE); + break; + default: + return false; + } + + } else + /* by pass */ + set_reg_field_value( + value, + 0, + OUTPUT_CSC_CONTROL, + OUTPUT_CSC_GRPH_MODE); + + addr = DCP_REG(mmOUTPUT_CSC_CONTROL); + dm_write_reg(ctx, addr, value); + + return true; +} + +void dce110_opp_set_csc_adjustment( + struct output_pixel_processor *opp, + const struct out_csc_color_matrix *tbl_entry) +{ + struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + enum csc_color_mode config = + CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; + + program_color_matrix( + opp110, tbl_entry, GRAPHICS_CSC_ADJUST_TYPE_SW); + + /* We did everything ,now program DxOUTPUT_CSC_CONTROL */ + configure_graphics_mode(opp110, config, GRAPHICS_CSC_ADJUST_TYPE_SW, + tbl_entry->color_space); +} + +void dce110_opp_set_csc_default( + struct output_pixel_processor *opp, + const struct default_adjustment *default_adjust) +{ + struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + enum csc_color_mode config = + CSC_COLOR_MODE_GRAPHICS_PREDEFINED; + + if (default_adjust->force_hw_default == false) { + const struct out_csc_color_matrix *elm; + /* currently parameter not in use */ + enum grph_color_adjust_option option = + GRPH_COLOR_MATRIX_HW_DEFAULT; + uint32_t i; + /* + * HW default false we program locally defined matrix + * HW default true we use predefined hw matrix and we + * do not need to program matrix + * OEM wants the HW default via runtime parameter. + */ + option = GRPH_COLOR_MATRIX_SW; + + for (i = 0; i < ARRAY_SIZE(global_color_matrix); ++i) { + elm = &global_color_matrix[i]; + if (elm->color_space != default_adjust->out_color_space) + continue; + /* program the matrix with default values from this + * file */ + program_color_matrix(opp110, elm, option); + config = CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; + break; + } + } + + /* configure the what we programmed : + * 1. Default values from this file + * 2. Use hardware default from ROM_A and we do not need to program + * matrix */ + + configure_graphics_mode(opp110, config, + default_adjust->csc_adjust_type, + default_adjust->out_color_space); +} diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c new file mode 100644 index 000000000000..975466f6e424 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c @@ -0,0 +1,738 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "dce110_opp.h" +#include "basics/conversion.h" + +/* include DCE11 register header files */ +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" +#include "dce/dce_11_0_enum.h" + +enum { + OUTPUT_CSC_MATRIX_SIZE = 12 +}; + +/* constrast:0 - 2.0, default 1.0 */ +#define UNDERLAY_CONTRAST_DEFAULT 100 +#define UNDERLAY_CONTRAST_MAX 200 +#define UNDERLAY_CONTRAST_MIN 0 +#define UNDERLAY_CONTRAST_STEP 1 +#define UNDERLAY_CONTRAST_DIVIDER 100 + +/* Saturation: 0 - 2.0; default 1.0 */ +#define UNDERLAY_SATURATION_DEFAULT 100 /*1.00*/ +#define UNDERLAY_SATURATION_MIN 0 +#define UNDERLAY_SATURATION_MAX 200 /* 2.00 */ +#define UNDERLAY_SATURATION_STEP 1 /* 0.01 */ +/*actual max overlay saturation + * value = UNDERLAY_SATURATION_MAX /UNDERLAY_SATURATION_DIVIDER + */ + +/* Hue */ +#define UNDERLAY_HUE_DEFAULT 0 +#define UNDERLAY_HUE_MIN -300 +#define UNDERLAY_HUE_MAX 300 +#define UNDERLAY_HUE_STEP 5 +#define UNDERLAY_HUE_DIVIDER 10 /* HW range: -30 ~ +30 */ +#define UNDERLAY_SATURATION_DIVIDER 100 + +/* Brightness: in DAL usually -.25 ~ .25. + * In MMD is -100 to +100 in 16-235 range; which when scaled to full range is + * ~-116 to +116. When normalized this is about 0.4566. + * With 100 divider this becomes 46, but we may use another for better precision + * The ideal one is 100/219 ((100/255)*(255/219)), + * i.e. min/max = +-100, divider = 219 + * default 0.0 + */ +#define UNDERLAY_BRIGHTNESS_DEFAULT 0 +#define UNDERLAY_BRIGHTNESS_MIN -46 /* ~116/255 */ +#define UNDERLAY_BRIGHTNESS_MAX 46 +#define UNDERLAY_BRIGHTNESS_STEP 1 /* .01 */ +#define UNDERLAY_BRIGHTNESS_DIVIDER 100 + +static const struct out_csc_color_matrix global_color_matrix[] = { +{ COLOR_SPACE_SRGB, + { 0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} }, +{ COLOR_SPACE_SRGB_LIMITED, + { 0x1B60, 0, 0, 0x200, 0, 0x1B60, 0, 0x200, 0, 0, 0x1B60, 0x200} }, +{ COLOR_SPACE_YCBCR601, + { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x82F, 0x1012, 0x31F, 0x200, 0xFB47, + 0xF6B9, 0xE00, 0x1000} }, +{ COLOR_SPACE_YCBCR709, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x5D2, 0x1394, 0x1FA, + 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} }, +/* TODO: correct values below */ +{ COLOR_SPACE_YCBCR601_LIMITED, { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x991, + 0x12C9, 0x3A6, 0x200, 0xFB47, 0xF6B9, 0xE00, 0x1000} }, +{ COLOR_SPACE_YCBCR709_LIMITED, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x6CE, 0x16E3, + 0x24F, 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} } +}; + +enum csc_color_mode { + /* 00 - BITS2:0 Bypass */ + CSC_COLOR_MODE_GRAPHICS_BYPASS, + /* 01 - hard coded coefficient TV RGB */ + CSC_COLOR_MODE_GRAPHICS_PREDEFINED, + /* 04 - programmable OUTPUT CSC coefficient */ + CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC, +}; + +static void program_color_matrix_v( + struct dce110_opp *opp110, + const struct out_csc_color_matrix *tbl_entry, + enum grph_color_adjust_option options) +{ + struct dc_context *ctx = opp110->base.ctx; + uint32_t cntl_value = dm_read_reg(ctx, mmCOL_MAN_OUTPUT_CSC_CONTROL); + bool use_set_a = (get_reg_field_value(cntl_value, + COL_MAN_OUTPUT_CSC_CONTROL, + OUTPUT_CSC_MODE) != 4); + + set_reg_field_value( + cntl_value, + 0, + COL_MAN_OUTPUT_CSC_CONTROL, + OUTPUT_CSC_MODE); + + if (use_set_a) { + { + uint32_t value = 0; + uint32_t addr = mmOUTPUT_CSC_C11_C12_A; + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[0], + OUTPUT_CSC_C11_C12_A, + OUTPUT_CSC_C11_A); + + set_reg_field_value( + value, + tbl_entry->regval[1], + OUTPUT_CSC_C11_C12_A, + OUTPUT_CSC_C12_A); + + dm_write_reg(ctx, addr, value); + } + { + uint32_t value = 0; + uint32_t addr = mmOUTPUT_CSC_C13_C14_A; + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[2], + OUTPUT_CSC_C13_C14_A, + OUTPUT_CSC_C13_A); + /* fixed S0.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[3], + OUTPUT_CSC_C13_C14_A, + OUTPUT_CSC_C14_A); + + dm_write_reg(ctx, addr, value); + } + { + uint32_t value = 0; + uint32_t addr = mmOUTPUT_CSC_C21_C22_A; + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[4], + OUTPUT_CSC_C21_C22_A, + OUTPUT_CSC_C21_A); + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[5], + OUTPUT_CSC_C21_C22_A, + OUTPUT_CSC_C22_A); + + dm_write_reg(ctx, addr, value); + } + { + uint32_t value = 0; + uint32_t addr = mmOUTPUT_CSC_C23_C24_A; + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[6], + OUTPUT_CSC_C23_C24_A, + OUTPUT_CSC_C23_A); + /* fixed S0.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[7], + OUTPUT_CSC_C23_C24_A, + OUTPUT_CSC_C24_A); + + dm_write_reg(ctx, addr, value); + } + { + uint32_t value = 0; + uint32_t addr = mmOUTPUT_CSC_C31_C32_A; + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[8], + OUTPUT_CSC_C31_C32_A, + OUTPUT_CSC_C31_A); + /* fixed S0.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[9], + OUTPUT_CSC_C31_C32_A, + OUTPUT_CSC_C32_A); + + dm_write_reg(ctx, addr, value); + } + { + uint32_t value = 0; + uint32_t addr = mmOUTPUT_CSC_C33_C34_A; + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[10], + OUTPUT_CSC_C33_C34_A, + OUTPUT_CSC_C33_A); + /* fixed S0.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[11], + OUTPUT_CSC_C33_C34_A, + OUTPUT_CSC_C34_A); + + dm_write_reg(ctx, addr, value); + } + set_reg_field_value( + cntl_value, + 4, + COL_MAN_OUTPUT_CSC_CONTROL, + OUTPUT_CSC_MODE); + } else { + { + uint32_t value = 0; + uint32_t addr = mmOUTPUT_CSC_C11_C12_B; + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[0], + OUTPUT_CSC_C11_C12_B, + OUTPUT_CSC_C11_B); + + set_reg_field_value( + value, + tbl_entry->regval[1], + OUTPUT_CSC_C11_C12_B, + OUTPUT_CSC_C12_B); + + dm_write_reg(ctx, addr, value); + } + { + uint32_t value = 0; + uint32_t addr = mmOUTPUT_CSC_C13_C14_B; + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[2], + OUTPUT_CSC_C13_C14_B, + OUTPUT_CSC_C13_B); + /* fixed S0.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[3], + OUTPUT_CSC_C13_C14_B, + OUTPUT_CSC_C14_B); + + dm_write_reg(ctx, addr, value); + } + { + uint32_t value = 0; + uint32_t addr = mmOUTPUT_CSC_C21_C22_B; + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[4], + OUTPUT_CSC_C21_C22_B, + OUTPUT_CSC_C21_B); + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[5], + OUTPUT_CSC_C21_C22_B, + OUTPUT_CSC_C22_B); + + dm_write_reg(ctx, addr, value); + } + { + uint32_t value = 0; + uint32_t addr = mmOUTPUT_CSC_C23_C24_B; + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[6], + OUTPUT_CSC_C23_C24_B, + OUTPUT_CSC_C23_B); + /* fixed S0.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[7], + OUTPUT_CSC_C23_C24_B, + OUTPUT_CSC_C24_B); + + dm_write_reg(ctx, addr, value); + } + { + uint32_t value = 0; + uint32_t addr = mmOUTPUT_CSC_C31_C32_B; + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[8], + OUTPUT_CSC_C31_C32_B, + OUTPUT_CSC_C31_B); + /* fixed S0.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[9], + OUTPUT_CSC_C31_C32_B, + OUTPUT_CSC_C32_B); + + dm_write_reg(ctx, addr, value); + } + { + uint32_t value = 0; + uint32_t addr = mmOUTPUT_CSC_C33_C34_B; + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[10], + OUTPUT_CSC_C33_C34_B, + OUTPUT_CSC_C33_B); + /* fixed S0.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[11], + OUTPUT_CSC_C33_C34_B, + OUTPUT_CSC_C34_B); + + dm_write_reg(ctx, addr, value); + } + set_reg_field_value( + cntl_value, + 5, + COL_MAN_OUTPUT_CSC_CONTROL, + OUTPUT_CSC_MODE); + } + + dm_write_reg(ctx, mmCOL_MAN_OUTPUT_CSC_CONTROL, cntl_value); +} + +static bool configure_graphics_mode_v( + struct dce110_opp *opp110, + enum csc_color_mode config, + enum graphics_csc_adjust_type csc_adjust_type, + enum dc_color_space color_space) +{ + struct dc_context *ctx = opp110->base.ctx; + uint32_t addr = mmCOL_MAN_OUTPUT_CSC_CONTROL; + uint32_t value = dm_read_reg(ctx, addr); + + set_reg_field_value( + value, + 0, + COL_MAN_OUTPUT_CSC_CONTROL, + OUTPUT_CSC_MODE); + + if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_SW) { + if (config == CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC) + return true; + + switch (color_space) { + case COLOR_SPACE_SRGB: + /* by pass */ + set_reg_field_value( + value, + 0, + COL_MAN_OUTPUT_CSC_CONTROL, + OUTPUT_CSC_MODE); + break; + case COLOR_SPACE_SRGB_LIMITED: + /* not supported for underlay on CZ */ + return false; + + case COLOR_SPACE_YCBCR601: + case COLOR_SPACE_YPBPR601: + case COLOR_SPACE_YCBCR601_LIMITED: + /* YCbCr601 */ + set_reg_field_value( + value, + 2, + COL_MAN_OUTPUT_CSC_CONTROL, + OUTPUT_CSC_MODE); + break; + case COLOR_SPACE_YCBCR709: + case COLOR_SPACE_YPBPR709: + case COLOR_SPACE_YCBCR709_LIMITED: + /* YCbCr709 */ + set_reg_field_value( + value, + 3, + COL_MAN_OUTPUT_CSC_CONTROL, + OUTPUT_CSC_MODE); + break; + default: + return false; + } + + } else if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_HW) { + switch (color_space) { + case COLOR_SPACE_SRGB: + /* by pass */ + set_reg_field_value( + value, + 0, + COL_MAN_OUTPUT_CSC_CONTROL, + OUTPUT_CSC_MODE); + break; + case COLOR_SPACE_SRGB_LIMITED: + /* not supported for underlay on CZ */ + return false; + case COLOR_SPACE_YCBCR601: + case COLOR_SPACE_YPBPR601: + case COLOR_SPACE_YCBCR601_LIMITED: + /* YCbCr601 */ + set_reg_field_value( + value, + 2, + COL_MAN_OUTPUT_CSC_CONTROL, + OUTPUT_CSC_MODE); + break; + case COLOR_SPACE_YCBCR709: + case COLOR_SPACE_YPBPR709: + case COLOR_SPACE_YCBCR709_LIMITED: + /* YCbCr709 */ + set_reg_field_value( + value, + 3, + COL_MAN_OUTPUT_CSC_CONTROL, + OUTPUT_CSC_MODE); + break; + default: + return false; + } + + } else + /* by pass */ + set_reg_field_value( + value, + 0, + COL_MAN_OUTPUT_CSC_CONTROL, + OUTPUT_CSC_MODE); + + addr = mmCOL_MAN_OUTPUT_CSC_CONTROL; + dm_write_reg(ctx, addr, value); + + return true; +} + +/*TODO: color depth is not correct when this is called*/ +static void set_Denormalization(struct output_pixel_processor *opp, + enum dc_color_depth color_depth) +{ + uint32_t value = dm_read_reg(opp->ctx, mmDENORM_CLAMP_CONTROL); + + switch (color_depth) { + case COLOR_DEPTH_888: + /* 255/256 for 8 bit output color depth */ + set_reg_field_value( + value, + 1, + DENORM_CLAMP_CONTROL, + DENORM_MODE); + break; + case COLOR_DEPTH_101010: + /* 1023/1024 for 10 bit output color depth */ + set_reg_field_value( + value, + 2, + DENORM_CLAMP_CONTROL, + DENORM_MODE); + break; + case COLOR_DEPTH_121212: + /* 4095/4096 for 12 bit output color depth */ + set_reg_field_value( + value, + 3, + DENORM_CLAMP_CONTROL, + DENORM_MODE); + break; + default: + /* not valid case */ + break; + } + + set_reg_field_value( + value, + 1, + DENORM_CLAMP_CONTROL, + DENORM_10BIT_OUT); + + dm_write_reg(opp->ctx, mmDENORM_CLAMP_CONTROL, value); +} + +struct input_csc_matrix { + enum dc_color_space color_space; + uint32_t regval[12]; +}; + +static const struct input_csc_matrix input_csc_matrix[] = { + {COLOR_SPACE_SRGB, +/*1_1 1_2 1_3 1_4 2_1 2_2 2_3 2_4 3_1 3_2 3_3 3_4 */ + {0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} }, + {COLOR_SPACE_SRGB_LIMITED, + {0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} }, + {COLOR_SPACE_YCBCR601, + {0x2cdd, 0x2000, 0x0, 0xe991, 0xe926, 0x2000, 0xf4fd, 0x10ef, + 0x0, 0x2000, 0x38b4, 0xe3a6} }, + {COLOR_SPACE_YCBCR601_LIMITED, + {0x3353, 0x2568, 0x0, 0xe400, 0xe5dc, 0x2568, 0xf367, 0x1108, + 0x0, 0x2568, 0x40de, 0xdd3a} }, + {COLOR_SPACE_YCBCR709, + {0x3265, 0x2000, 0, 0xe6ce, 0xf105, 0x2000, 0xfa01, 0xa7d, 0, + 0x2000, 0x3b61, 0xe24f} }, + {COLOR_SPACE_YCBCR709_LIMITED, + {0x39a6, 0x2568, 0, 0xe0d6, 0xeedd, 0x2568, 0xf925, 0x9a8, 0, + 0x2568, 0x43ee, 0xdbb2} } +}; + +static void program_input_csc( + struct output_pixel_processor *opp, enum dc_color_space color_space) +{ + int arr_size = sizeof(input_csc_matrix)/sizeof(struct input_csc_matrix); + struct dc_context *ctx = opp->ctx; + const uint32_t *regval = NULL; + bool use_set_a; + uint32_t value; + int i; + + for (i = 0; i < arr_size; i++) + if (input_csc_matrix[i].color_space == color_space) { + regval = input_csc_matrix[i].regval; + break; + } + if (regval == NULL) { + BREAK_TO_DEBUGGER(); + return; + } + + /* + * 1 == set A, the logic is 'if currently we're not using set A, + * then use set A, otherwise use set B' + */ + value = dm_read_reg(ctx, mmCOL_MAN_INPUT_CSC_CONTROL); + use_set_a = get_reg_field_value( + value, COL_MAN_INPUT_CSC_CONTROL, INPUT_CSC_MODE) != 1; + + if (use_set_a) { + /* fixed S2.13 format */ + value = 0; + set_reg_field_value( + value, regval[0], INPUT_CSC_C11_C12_A, INPUT_CSC_C11_A); + set_reg_field_value( + value, regval[1], INPUT_CSC_C11_C12_A, INPUT_CSC_C12_A); + dm_write_reg(ctx, mmINPUT_CSC_C11_C12_A, value); + + value = 0; + set_reg_field_value( + value, regval[2], INPUT_CSC_C13_C14_A, INPUT_CSC_C13_A); + set_reg_field_value( + value, regval[3], INPUT_CSC_C13_C14_A, INPUT_CSC_C14_A); + dm_write_reg(ctx, mmINPUT_CSC_C13_C14_A, value); + + value = 0; + set_reg_field_value( + value, regval[4], INPUT_CSC_C21_C22_A, INPUT_CSC_C21_A); + set_reg_field_value( + value, regval[5], INPUT_CSC_C21_C22_A, INPUT_CSC_C22_A); + dm_write_reg(ctx, mmINPUT_CSC_C21_C22_A, value); + + value = 0; + set_reg_field_value( + value, regval[6], INPUT_CSC_C23_C24_A, INPUT_CSC_C23_A); + set_reg_field_value( + value, regval[7], INPUT_CSC_C23_C24_A, INPUT_CSC_C24_A); + dm_write_reg(ctx, mmINPUT_CSC_C23_C24_A, value); + + value = 0; + set_reg_field_value( + value, regval[8], INPUT_CSC_C31_C32_A, INPUT_CSC_C31_A); + set_reg_field_value( + value, regval[9], INPUT_CSC_C31_C32_A, INPUT_CSC_C32_A); + dm_write_reg(ctx, mmINPUT_CSC_C31_C32_A, value); + + value = 0; + set_reg_field_value( + value, regval[10], INPUT_CSC_C33_C34_A, INPUT_CSC_C33_A); + set_reg_field_value( + value, regval[11], INPUT_CSC_C33_C34_A, INPUT_CSC_C34_A); + dm_write_reg(ctx, mmINPUT_CSC_C33_C34_A, value); + } else { + /* fixed S2.13 format */ + value = 0; + set_reg_field_value( + value, regval[0], INPUT_CSC_C11_C12_B, INPUT_CSC_C11_B); + set_reg_field_value( + value, regval[1], INPUT_CSC_C11_C12_B, INPUT_CSC_C12_B); + dm_write_reg(ctx, mmINPUT_CSC_C11_C12_B, value); + + value = 0; + set_reg_field_value( + value, regval[2], INPUT_CSC_C13_C14_B, INPUT_CSC_C13_B); + set_reg_field_value( + value, regval[3], INPUT_CSC_C13_C14_B, INPUT_CSC_C14_B); + dm_write_reg(ctx, mmINPUT_CSC_C13_C14_B, value); + + value = 0; + set_reg_field_value( + value, regval[4], INPUT_CSC_C21_C22_B, INPUT_CSC_C21_B); + set_reg_field_value( + value, regval[5], INPUT_CSC_C21_C22_B, INPUT_CSC_C22_B); + dm_write_reg(ctx, mmINPUT_CSC_C21_C22_B, value); + + value = 0; + set_reg_field_value( + value, regval[6], INPUT_CSC_C23_C24_B, INPUT_CSC_C23_B); + set_reg_field_value( + value, regval[7], INPUT_CSC_C23_C24_B, INPUT_CSC_C24_B); + dm_write_reg(ctx, mmINPUT_CSC_C23_C24_B, value); + + value = 0; + set_reg_field_value( + value, regval[8], INPUT_CSC_C31_C32_B, INPUT_CSC_C31_B); + set_reg_field_value( + value, regval[9], INPUT_CSC_C31_C32_B, INPUT_CSC_C32_B); + dm_write_reg(ctx, mmINPUT_CSC_C31_C32_B, value); + + value = 0; + set_reg_field_value( + value, regval[10], INPUT_CSC_C33_C34_B, INPUT_CSC_C33_B); + set_reg_field_value( + value, regval[11], INPUT_CSC_C33_C34_B, INPUT_CSC_C34_B); + dm_write_reg(ctx, mmINPUT_CSC_C33_C34_B, value); + } + + /* KK: leave INPUT_CSC_CONVERSION_MODE at default */ + value = 0; + /* + * select 8.4 input type instead of default 12.0. From the discussion + * with HW team, this format depends on the UNP surface format, so for + * 8-bit we should select 8.4 (4 bits truncated). For 10 it should be + * 10.2. For Carrizo we only support 8-bit surfaces on underlay pipe + * so we can always keep this at 8.4 (input_type=2). If the later asics + * start supporting 10+ bits, we will have a problem: surface + * programming including UNP_GRPH* is being done in DalISR after this, + * so either we pass surface format to here, or move this logic to ISR + */ + + set_reg_field_value( + value, 2, COL_MAN_INPUT_CSC_CONTROL, INPUT_CSC_INPUT_TYPE); + set_reg_field_value( + value, + use_set_a ? 1 : 2, + COL_MAN_INPUT_CSC_CONTROL, + INPUT_CSC_MODE); + + dm_write_reg(ctx, mmCOL_MAN_INPUT_CSC_CONTROL, value); +} + +void dce110_opp_v_set_csc_default( + struct output_pixel_processor *opp, + const struct default_adjustment *default_adjust) +{ + struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + enum csc_color_mode config = + CSC_COLOR_MODE_GRAPHICS_PREDEFINED; + + if (default_adjust->force_hw_default == false) { + const struct out_csc_color_matrix *elm; + /* currently parameter not in use */ + enum grph_color_adjust_option option = + GRPH_COLOR_MATRIX_HW_DEFAULT; + uint32_t i; + /* + * HW default false we program locally defined matrix + * HW default true we use predefined hw matrix and we + * do not need to program matrix + * OEM wants the HW default via runtime parameter. + */ + option = GRPH_COLOR_MATRIX_SW; + + for (i = 0; i < ARRAY_SIZE(global_color_matrix); ++i) { + elm = &global_color_matrix[i]; + if (elm->color_space != default_adjust->out_color_space) + continue; + /* program the matrix with default values from this + * file + */ + program_color_matrix_v(opp110, elm, option); + config = CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; + break; + } + } + + program_input_csc(opp, default_adjust->in_color_space); + + /* configure the what we programmed : + * 1. Default values from this file + * 2. Use hardware default from ROM_A and we do not need to program + * matrix + */ + + configure_graphics_mode_v(opp110, config, + default_adjust->csc_adjust_type, + default_adjust->out_color_space); + + set_Denormalization(opp, default_adjust->color_depth); +} + +void dce110_opp_v_set_csc_adjustment( + struct output_pixel_processor *opp, + const struct out_csc_color_matrix *tbl_entry) +{ + struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + enum csc_color_mode config = + CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; + + program_color_matrix_v( + opp110, tbl_entry, GRAPHICS_CSC_ADJUST_TYPE_SW); + + /* We did everything ,now program DxOUTPUT_CSC_CONTROL */ + configure_graphics_mode_v(opp110, config, GRAPHICS_CSC_ADJUST_TYPE_SW, + tbl_entry->color_space); + + /*TODO: Check if denormalization is needed*/ + /*set_Denormalization(opp, adjust->color_depth);*/ +} diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_formatter.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_formatter.c new file mode 100644 index 000000000000..eac20775c23f --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_formatter.c @@ -0,0 +1,627 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" + +#include "dce110_opp.h" + +#define FMT_REG(reg)\ + (reg + opp110->offsets.fmt_offset) +/** + * set_truncation + * 1) set truncation depth: 0 for 18 bpp or 1 for 24 bpp + * 2) enable truncation + * 3) HW remove 12bit FMT support for DCE11 power saving reason. + */ +static void set_truncation( + struct dce110_opp *opp110, + const struct bit_depth_reduction_params *params) +{ + uint32_t value = 0; + uint32_t addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL); + + /*Disable truncation*/ + value = dm_read_reg(opp110->base.ctx, addr); + set_reg_field_value(value, 0, + FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN); + set_reg_field_value(value, 0, + FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_DEPTH); + set_reg_field_value(value, 0, + FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_MODE); + + dm_write_reg(opp110->base.ctx, addr, value); + + /* no 10bpc trunc on DCE11*/ + if (params->flags.TRUNCATE_ENABLED == 0 || + params->flags.TRUNCATE_DEPTH == 2) + return; + + /*Set truncation depth and Enable truncation*/ + set_reg_field_value(value, 1, + FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN); + set_reg_field_value(value, params->flags.TRUNCATE_MODE, + FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_MODE); + set_reg_field_value(value, params->flags.TRUNCATE_DEPTH, + FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_DEPTH); + + dm_write_reg(opp110->base.ctx, addr, value); + +} + +/** + * set_spatial_dither + * 1) set spatial dithering mode: pattern of seed + * 2) set spatical dithering depth: 0 for 18bpp or 1 for 24bpp + * 3) set random seed + * 4) set random mode + * lfsr is reset every frame or not reset + * RGB dithering method + * 0: RGB data are all dithered with x^28+x^3+1 + * 1: R data is dithered with x^28+x^3+1 + * G data is dithered with x^28+X^9+1 + * B data is dithered with x^28+x^13+1 + * enable high pass filter or not + * 5) enable spatical dithering + */ +static void set_spatial_dither( + struct dce110_opp *opp110, + const struct bit_depth_reduction_params *params) +{ + uint32_t addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL); + uint32_t depth_cntl_value = 0; + uint32_t fmt_cntl_value = 0; + uint32_t dither_r_value = 0; + uint32_t dither_g_value = 0; + uint32_t dither_b_value = 0; + + /*Disable spatial (random) dithering*/ + depth_cntl_value = dm_read_reg(opp110->base.ctx, addr); + set_reg_field_value(depth_cntl_value, 0, + FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_EN); + set_reg_field_value(depth_cntl_value, 0, + FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_MODE); + set_reg_field_value(depth_cntl_value, 0, + FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_DEPTH); + set_reg_field_value(depth_cntl_value, 0, + FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_EN); + set_reg_field_value(depth_cntl_value, 0, + FMT_BIT_DEPTH_CONTROL, FMT_HIGHPASS_RANDOM_ENABLE); + set_reg_field_value(depth_cntl_value, 0, + FMT_BIT_DEPTH_CONTROL, FMT_FRAME_RANDOM_ENABLE); + set_reg_field_value(depth_cntl_value, 0, + FMT_BIT_DEPTH_CONTROL, FMT_RGB_RANDOM_ENABLE); + + dm_write_reg(opp110->base.ctx, addr, depth_cntl_value); + + /* no 10bpc on DCE11*/ + if (params->flags.SPATIAL_DITHER_ENABLED == 0 || + params->flags.SPATIAL_DITHER_DEPTH == 2) + return; + + addr = FMT_REG(mmFMT_CONTROL); + fmt_cntl_value = dm_read_reg(opp110->base.ctx, addr); + /* only use FRAME_COUNTER_MAX if frameRandom == 1*/ + if (params->flags.FRAME_RANDOM == 1) { + if (params->flags.SPATIAL_DITHER_DEPTH == 0 || + params->flags.SPATIAL_DITHER_DEPTH == 1) { + set_reg_field_value(fmt_cntl_value, 15, + FMT_CONTROL, + FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX); + set_reg_field_value(fmt_cntl_value, 2, + FMT_CONTROL, + FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP); + } else if (params->flags.SPATIAL_DITHER_DEPTH == 2) { + set_reg_field_value(fmt_cntl_value, 3, + FMT_CONTROL, + FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX); + set_reg_field_value(fmt_cntl_value, 1, + FMT_CONTROL, + FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP); + } else + return; + } else { + set_reg_field_value(fmt_cntl_value, 0, + FMT_CONTROL, + FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX); + set_reg_field_value(fmt_cntl_value, 0, + FMT_CONTROL, + FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP); + } + + dm_write_reg(opp110->base.ctx, addr, fmt_cntl_value); + + /*Set seed for random values for + * spatial dithering for R,G,B channels*/ + addr = FMT_REG(mmFMT_DITHER_RAND_R_SEED); + set_reg_field_value(dither_r_value, params->r_seed_value, + FMT_DITHER_RAND_R_SEED, + FMT_RAND_R_SEED); + dm_write_reg(opp110->base.ctx, addr, dither_r_value); + + addr = FMT_REG(mmFMT_DITHER_RAND_G_SEED); + set_reg_field_value(dither_g_value, + params->g_seed_value, + FMT_DITHER_RAND_G_SEED, + FMT_RAND_G_SEED); + dm_write_reg(opp110->base.ctx, addr, dither_g_value); + + addr = FMT_REG(mmFMT_DITHER_RAND_B_SEED); + set_reg_field_value(dither_b_value, params->b_seed_value, + FMT_DITHER_RAND_B_SEED, + FMT_RAND_B_SEED); + dm_write_reg(opp110->base.ctx, addr, dither_b_value); + + /* FMT_OFFSET_R_Cr 31:16 0x0 Setting the zero + * offset for the R/Cr channel, lower 4LSB + * is forced to zeros. Typically set to 0 + * RGB and 0x80000 YCbCr. + */ + /* FMT_OFFSET_G_Y 31:16 0x0 Setting the zero + * offset for the G/Y channel, lower 4LSB is + * forced to zeros. Typically set to 0 RGB + * and 0x80000 YCbCr. + */ + /* FMT_OFFSET_B_Cb 31:16 0x0 Setting the zero + * offset for the B/Cb channel, lower 4LSB is + * forced to zeros. Typically set to 0 RGB and + * 0x80000 YCbCr. + */ + + /*Set spatial dithering bit depth*/ + set_reg_field_value(depth_cntl_value, + params->flags.SPATIAL_DITHER_DEPTH, + FMT_BIT_DEPTH_CONTROL, + FMT_SPATIAL_DITHER_DEPTH); + + /* Set spatial dithering mode + * (default is Seed patterrn AAAA...) + */ + set_reg_field_value(depth_cntl_value, + params->flags.SPATIAL_DITHER_MODE, + FMT_BIT_DEPTH_CONTROL, + FMT_SPATIAL_DITHER_MODE); + + /*Reset only at startup*/ + set_reg_field_value(depth_cntl_value, + params->flags.FRAME_RANDOM, + FMT_BIT_DEPTH_CONTROL, + FMT_FRAME_RANDOM_ENABLE); + + /*Set RGB data dithered with x^28+x^3+1*/ + set_reg_field_value(depth_cntl_value, + params->flags.RGB_RANDOM, + FMT_BIT_DEPTH_CONTROL, + FMT_RGB_RANDOM_ENABLE); + + /*Disable High pass filter*/ + set_reg_field_value(depth_cntl_value, + params->flags.HIGHPASS_RANDOM, + FMT_BIT_DEPTH_CONTROL, + FMT_HIGHPASS_RANDOM_ENABLE); + + /*Enable spatial dithering*/ + set_reg_field_value(depth_cntl_value, + 1, + FMT_BIT_DEPTH_CONTROL, + FMT_SPATIAL_DITHER_EN); + + addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL); + dm_write_reg(opp110->base.ctx, addr, depth_cntl_value); + +} + +/** + * SetTemporalDither (Frame Modulation) + * 1) set temporal dither depth + * 2) select pattern: from hard-coded pattern or programmable pattern + * 3) select optimized strips for BGR or RGB LCD sub-pixel + * 4) set s matrix + * 5) set t matrix + * 6) set grey level for 0.25, 0.5, 0.75 + * 7) enable temporal dithering + */ +static void set_temporal_dither( + struct dce110_opp *opp110, + const struct bit_depth_reduction_params *params) +{ + uint32_t addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL); + uint32_t value; + + /*Disable temporal (frame modulation) dithering first*/ + value = dm_read_reg(opp110->base.ctx, addr); + + set_reg_field_value(value, + 0, + FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_DITHER_EN); + + set_reg_field_value(value, + 0, + FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_DITHER_RESET); + set_reg_field_value(value, + 0, + FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_DITHER_OFFSET); + set_reg_field_value(value, + 0, + FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_DITHER_DEPTH); + set_reg_field_value(value, + 0, + FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_LEVEL); + set_reg_field_value(value, + 0, + FMT_BIT_DEPTH_CONTROL, + FMT_25FRC_SEL); + + set_reg_field_value(value, + 0, + FMT_BIT_DEPTH_CONTROL, + FMT_50FRC_SEL); + + set_reg_field_value(value, + 0, + FMT_BIT_DEPTH_CONTROL, + FMT_75FRC_SEL); + + dm_write_reg(opp110->base.ctx, addr, value); + + /* no 10bpc dither on DCE11*/ + if (params->flags.FRAME_MODULATION_ENABLED == 0 || + params->flags.FRAME_MODULATION_DEPTH == 2) + return; + + /* Set temporal dithering depth*/ + set_reg_field_value(value, + params->flags.FRAME_MODULATION_DEPTH, + FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_DITHER_DEPTH); + + set_reg_field_value(value, + 0, + FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_DITHER_RESET); + + set_reg_field_value(value, + 0, + FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_DITHER_OFFSET); + + /*Select legacy pattern based on FRC and Temporal level*/ + addr = FMT_REG(mmFMT_TEMPORAL_DITHER_PATTERN_CONTROL); + dm_write_reg(opp110->base.ctx, addr, 0); + /*Set s matrix*/ + addr = FMT_REG( + mmFMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX); + dm_write_reg(opp110->base.ctx, addr, 0); + /*Set t matrix*/ + addr = FMT_REG( + mmFMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX); + dm_write_reg(opp110->base.ctx, addr, 0); + + /*Select patterns for 0.25, 0.5 and 0.75 grey level*/ + set_reg_field_value(value, + params->flags.TEMPORAL_LEVEL, + FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_LEVEL); + + set_reg_field_value(value, + params->flags.FRC25, + FMT_BIT_DEPTH_CONTROL, + FMT_25FRC_SEL); + + set_reg_field_value(value, + params->flags.FRC50, + FMT_BIT_DEPTH_CONTROL, + FMT_50FRC_SEL); + + set_reg_field_value(value, + params->flags.FRC75, + FMT_BIT_DEPTH_CONTROL, + FMT_75FRC_SEL); + + /*Enable bit reduction by temporal (frame modulation) dithering*/ + set_reg_field_value(value, + 1, + FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_DITHER_EN); + + addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL); + dm_write_reg(opp110->base.ctx, addr, value); + +} + +/** + * Set Clamping + * 1) Set clamping format based on bpc - 0 for 6bpc (No clamping) + * 1 for 8 bpc + * 2 for 10 bpc + * 3 for 12 bpc + * 7 for programable + * 2) Enable clamp if Limited range requested + */ +void dce110_opp_set_clamping( + struct dce110_opp *opp110, + const struct clamping_and_pixel_encoding_params *params) +{ + uint32_t clamp_cntl_value = 0; + uint32_t red_clamp_value = 0; + uint32_t green_clamp_value = 0; + uint32_t blue_clamp_value = 0; + uint32_t addr = FMT_REG(mmFMT_CLAMP_CNTL); + + clamp_cntl_value = dm_read_reg(opp110->base.ctx, addr); + + set_reg_field_value(clamp_cntl_value, + 0, + FMT_CLAMP_CNTL, + FMT_CLAMP_DATA_EN); + + set_reg_field_value(clamp_cntl_value, + 0, + FMT_CLAMP_CNTL, + FMT_CLAMP_COLOR_FORMAT); + + switch (params->clamping_level) { + case CLAMPING_FULL_RANGE: + break; + + case CLAMPING_LIMITED_RANGE_8BPC: + set_reg_field_value(clamp_cntl_value, + 1, + FMT_CLAMP_CNTL, + FMT_CLAMP_DATA_EN); + + set_reg_field_value(clamp_cntl_value, + 1, + FMT_CLAMP_CNTL, + FMT_CLAMP_COLOR_FORMAT); + + break; + + case CLAMPING_LIMITED_RANGE_10BPC: + set_reg_field_value(clamp_cntl_value, + 1, + FMT_CLAMP_CNTL, + FMT_CLAMP_DATA_EN); + + set_reg_field_value(clamp_cntl_value, + 2, + FMT_CLAMP_CNTL, + FMT_CLAMP_COLOR_FORMAT); + + break; + case CLAMPING_LIMITED_RANGE_12BPC: + set_reg_field_value(clamp_cntl_value, + 1, + FMT_CLAMP_CNTL, + FMT_CLAMP_DATA_EN); + + set_reg_field_value(clamp_cntl_value, + 3, + FMT_CLAMP_CNTL, + FMT_CLAMP_COLOR_FORMAT); + + break; + case CLAMPING_LIMITED_RANGE_PROGRAMMABLE: + set_reg_field_value(clamp_cntl_value, + 1, + FMT_CLAMP_CNTL, + FMT_CLAMP_DATA_EN); + + set_reg_field_value(clamp_cntl_value, + 7, + FMT_CLAMP_CNTL, + FMT_CLAMP_COLOR_FORMAT); + + /*set the defaults*/ + set_reg_field_value(red_clamp_value, + 0x10, + FMT_CLAMP_COMPONENT_R, + FMT_CLAMP_LOWER_R); + + set_reg_field_value(red_clamp_value, + 0xFEF, + FMT_CLAMP_COMPONENT_R, + FMT_CLAMP_UPPER_R); + + addr = FMT_REG(mmFMT_CLAMP_COMPONENT_R); + dm_write_reg(opp110->base.ctx, addr, red_clamp_value); + + set_reg_field_value(green_clamp_value, + 0x10, + FMT_CLAMP_COMPONENT_G, + FMT_CLAMP_LOWER_G); + + set_reg_field_value(green_clamp_value, + 0xFEF, + FMT_CLAMP_COMPONENT_G, + FMT_CLAMP_UPPER_G); + + addr = FMT_REG(mmFMT_CLAMP_COMPONENT_G); + dm_write_reg(opp110->base.ctx, addr, green_clamp_value); + + set_reg_field_value(blue_clamp_value, + 0x10, + FMT_CLAMP_COMPONENT_B, + FMT_CLAMP_LOWER_B); + + set_reg_field_value(blue_clamp_value, + 0xFEF, + FMT_CLAMP_COMPONENT_B, + FMT_CLAMP_UPPER_B); + + addr = FMT_REG(mmFMT_CLAMP_COMPONENT_B); + dm_write_reg(opp110->base.ctx, addr, blue_clamp_value); + + break; + + default: + break; + } + + addr = FMT_REG(mmFMT_CLAMP_CNTL); + /*Set clamp control*/ + dm_write_reg(opp110->base.ctx, addr, clamp_cntl_value); + +} + +/** + * set_pixel_encoding + * + * Set Pixel Encoding + * 0: RGB 4:4:4 or YCbCr 4:4:4 or YOnly + * 1: YCbCr 4:2:2 + */ +static void set_pixel_encoding( + struct dce110_opp *opp110, + const struct clamping_and_pixel_encoding_params *params) +{ + uint32_t fmt_cntl_value; + uint32_t addr = FMT_REG(mmFMT_CONTROL); + + /*RGB 4:4:4 or YCbCr 4:4:4 - 0; YCbCr 4:2:2 -1.*/ + fmt_cntl_value = dm_read_reg(opp110->base.ctx, addr); + + set_reg_field_value(fmt_cntl_value, + 0, + FMT_CONTROL, + FMT_PIXEL_ENCODING); + + if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) { + set_reg_field_value(fmt_cntl_value, + 1, + FMT_CONTROL, + FMT_PIXEL_ENCODING); + + /*00 - Pixels drop mode ,01 - Pixels average mode*/ + set_reg_field_value(fmt_cntl_value, + 0, + FMT_CONTROL, + FMT_SUBSAMPLING_MODE); + + /*00 - Cb before Cr ,01 - Cr before Cb*/ + set_reg_field_value(fmt_cntl_value, + 0, + FMT_CONTROL, + FMT_SUBSAMPLING_ORDER); + } + dm_write_reg(opp110->base.ctx, addr, fmt_cntl_value); + +} + +void dce110_opp_program_bit_depth_reduction( + struct output_pixel_processor *opp, + const struct bit_depth_reduction_params *params) +{ + struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + + set_truncation(opp110, params); + set_spatial_dither(opp110, params); + set_temporal_dither(opp110, params); +} + +void dce110_opp_program_clamping_and_pixel_encoding( + struct output_pixel_processor *opp, + const struct clamping_and_pixel_encoding_params *params) +{ + struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + + dce110_opp_set_clamping(opp110, params); + set_pixel_encoding(opp110, params); +} + +void dce110_opp_set_dyn_expansion( + struct output_pixel_processor *opp, + enum dc_color_space color_sp, + enum dc_color_depth color_dpth, + enum signal_type signal) +{ + struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + uint32_t value; + bool enable_dyn_exp = false; + uint32_t addr = FMT_REG(mmFMT_DYNAMIC_EXP_CNTL); + + value = dm_read_reg(opp->ctx, addr); + + set_reg_field_value(value, 0, + FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN); + set_reg_field_value(value, 0, + FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE); + + /* From HW programming guide: + FMT_DYNAMIC_EXP_EN = 0 for limited RGB or YCbCr output + FMT_DYNAMIC_EXP_EN = 1 for RGB full range only*/ + if (color_sp == COLOR_SPACE_SRGB) + enable_dyn_exp = true; + + /*00 - 10-bit -> 12-bit dynamic expansion*/ + /*01 - 8-bit -> 12-bit dynamic expansion*/ + if (signal == SIGNAL_TYPE_HDMI_TYPE_A) { + switch (color_dpth) { + case COLOR_DEPTH_888: + set_reg_field_value(value, enable_dyn_exp ? 1:0, + FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN); + set_reg_field_value(value, 1, + FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE); + break; + case COLOR_DEPTH_101010: + set_reg_field_value(value, enable_dyn_exp ? 1:0, + FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN); + set_reg_field_value(value, 0, + FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE); + break; + case COLOR_DEPTH_121212: + break; + default: + break; + } + } + + dm_write_reg(opp->ctx, addr, value); +} + +void dce110_opp_program_fmt( + struct output_pixel_processor *opp, + struct bit_depth_reduction_params *fmt_bit_depth, + struct clamping_and_pixel_encoding_params *clamping) +{ + /* dithering is affected by , hence should be + * programmed afterwards */ + dce110_opp_program_bit_depth_reduction( + opp, + fmt_bit_depth); + + dce110_opp_program_clamping_and_pixel_encoding( + opp, + clamping); + + return; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma.c new file mode 100644 index 000000000000..62051abcfe2f --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma.c @@ -0,0 +1,537 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* include DCE11 register header files */ +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" + +#include "dce110_opp.h" +#include "gamma_types.h" + +#define DCP_REG(reg)\ + (reg + opp110->offsets.dcp_offset) + +#define DCFE_REG(reg)\ + (reg + opp110->offsets.dcfe_offset) + +enum { + MAX_PWL_ENTRY = 128, + MAX_REGIONS_NUMBER = 16 + +}; + +/* + ***************************************************************************** + * Function: regamma_config_regions_and_segments + * + * build regamma curve by using predefined hw points + * uses interface parameters ,like EDID coeff. + * + * @param : parameters interface parameters + * @return void + * + * @note + * + * @see + * + ***************************************************************************** + */ +static void regamma_config_regions_and_segments( + struct dce110_opp *opp110, + const struct pwl_params *params) +{ + const struct gamma_curve *curve; + uint32_t value = 0; + + { + set_reg_field_value( + value, + params->arr_points[0].custom_float_x, + REGAMMA_CNTLA_START_CNTL, + REGAMMA_CNTLA_EXP_REGION_START); + + set_reg_field_value( + value, + 0, + REGAMMA_CNTLA_START_CNTL, + REGAMMA_CNTLA_EXP_REGION_START_SEGMENT); + + dm_write_reg(opp110->base.ctx, + DCP_REG(mmREGAMMA_CNTLA_START_CNTL), + value); + } + { + value = 0; + set_reg_field_value( + value, + params->arr_points[0].custom_float_slope, + REGAMMA_CNTLA_SLOPE_CNTL, + REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE); + + dm_write_reg(opp110->base.ctx, + DCP_REG(mmREGAMMA_CNTLA_SLOPE_CNTL), value); + } + { + value = 0; + set_reg_field_value( + value, + params->arr_points[1].custom_float_x, + REGAMMA_CNTLA_END_CNTL1, + REGAMMA_CNTLA_EXP_REGION_END); + + dm_write_reg(opp110->base.ctx, + DCP_REG(mmREGAMMA_CNTLA_END_CNTL1), value); + } + { + value = 0; + set_reg_field_value( + value, + params->arr_points[2].custom_float_slope, + REGAMMA_CNTLA_END_CNTL2, + REGAMMA_CNTLA_EXP_REGION_END_BASE); + + set_reg_field_value( + value, + params->arr_points[1].custom_float_y, + REGAMMA_CNTLA_END_CNTL2, + REGAMMA_CNTLA_EXP_REGION_END_SLOPE); + + dm_write_reg(opp110->base.ctx, + DCP_REG(mmREGAMMA_CNTLA_END_CNTL2), value); + } + + curve = params->arr_curve_points; + + { + value = 0; + set_reg_field_value( + value, + curve[0].offset, + REGAMMA_CNTLA_REGION_0_1, + REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET); + + set_reg_field_value( + value, + curve[0].segments_num, + REGAMMA_CNTLA_REGION_0_1, + REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS); + + set_reg_field_value( + value, + curve[1].offset, + REGAMMA_CNTLA_REGION_0_1, + REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET); + + set_reg_field_value( + value, + curve[1].segments_num, + REGAMMA_CNTLA_REGION_0_1, + REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS); + + dm_write_reg( + opp110->base.ctx, + DCP_REG(mmREGAMMA_CNTLA_REGION_0_1), + value); + } + + curve += 2; + { + value = 0; + set_reg_field_value( + value, + curve[0].offset, + REGAMMA_CNTLA_REGION_2_3, + REGAMMA_CNTLA_EXP_REGION2_LUT_OFFSET); + + set_reg_field_value( + value, + curve[0].segments_num, + REGAMMA_CNTLA_REGION_2_3, + REGAMMA_CNTLA_EXP_REGION2_NUM_SEGMENTS); + + set_reg_field_value( + value, + curve[1].offset, + REGAMMA_CNTLA_REGION_2_3, + REGAMMA_CNTLA_EXP_REGION3_LUT_OFFSET); + + set_reg_field_value( + value, + curve[1].segments_num, + REGAMMA_CNTLA_REGION_2_3, + REGAMMA_CNTLA_EXP_REGION3_NUM_SEGMENTS); + + dm_write_reg(opp110->base.ctx, + DCP_REG(mmREGAMMA_CNTLA_REGION_2_3), + value); + } + + curve += 2; + { + value = 0; + set_reg_field_value( + value, + curve[0].offset, + REGAMMA_CNTLA_REGION_4_5, + REGAMMA_CNTLA_EXP_REGION4_LUT_OFFSET); + + set_reg_field_value( + value, + curve[0].segments_num, + REGAMMA_CNTLA_REGION_4_5, + REGAMMA_CNTLA_EXP_REGION4_NUM_SEGMENTS); + + set_reg_field_value( + value, + curve[1].offset, + REGAMMA_CNTLA_REGION_4_5, + REGAMMA_CNTLA_EXP_REGION5_LUT_OFFSET); + + set_reg_field_value( + value, + curve[1].segments_num, + REGAMMA_CNTLA_REGION_4_5, + REGAMMA_CNTLA_EXP_REGION5_NUM_SEGMENTS); + + dm_write_reg(opp110->base.ctx, + DCP_REG(mmREGAMMA_CNTLA_REGION_4_5), + value); + } + + curve += 2; + { + value = 0; + set_reg_field_value( + value, + curve[0].offset, + REGAMMA_CNTLA_REGION_6_7, + REGAMMA_CNTLA_EXP_REGION6_LUT_OFFSET); + + set_reg_field_value( + value, + curve[0].segments_num, + REGAMMA_CNTLA_REGION_6_7, + REGAMMA_CNTLA_EXP_REGION6_NUM_SEGMENTS); + + set_reg_field_value( + value, + curve[1].offset, + REGAMMA_CNTLA_REGION_6_7, + REGAMMA_CNTLA_EXP_REGION7_LUT_OFFSET); + + set_reg_field_value( + value, + curve[1].segments_num, + REGAMMA_CNTLA_REGION_6_7, + REGAMMA_CNTLA_EXP_REGION7_NUM_SEGMENTS); + + dm_write_reg(opp110->base.ctx, + DCP_REG(mmREGAMMA_CNTLA_REGION_6_7), + value); + } + + curve += 2; + { + value = 0; + set_reg_field_value( + value, + curve[0].offset, + REGAMMA_CNTLA_REGION_8_9, + REGAMMA_CNTLA_EXP_REGION8_LUT_OFFSET); + + set_reg_field_value( + value, + curve[0].segments_num, + REGAMMA_CNTLA_REGION_8_9, + REGAMMA_CNTLA_EXP_REGION8_NUM_SEGMENTS); + + set_reg_field_value( + value, + curve[1].offset, + REGAMMA_CNTLA_REGION_8_9, + REGAMMA_CNTLA_EXP_REGION9_LUT_OFFSET); + + set_reg_field_value( + value, + curve[1].segments_num, + REGAMMA_CNTLA_REGION_8_9, + REGAMMA_CNTLA_EXP_REGION9_NUM_SEGMENTS); + + dm_write_reg(opp110->base.ctx, + DCP_REG(mmREGAMMA_CNTLA_REGION_8_9), + value); + } + + curve += 2; + { + value = 0; + set_reg_field_value( + value, + curve[0].offset, + REGAMMA_CNTLA_REGION_10_11, + REGAMMA_CNTLA_EXP_REGION10_LUT_OFFSET); + + set_reg_field_value( + value, + curve[0].segments_num, + REGAMMA_CNTLA_REGION_10_11, + REGAMMA_CNTLA_EXP_REGION10_NUM_SEGMENTS); + + set_reg_field_value( + value, + curve[1].offset, + REGAMMA_CNTLA_REGION_10_11, + REGAMMA_CNTLA_EXP_REGION11_LUT_OFFSET); + + set_reg_field_value( + value, + curve[1].segments_num, + REGAMMA_CNTLA_REGION_10_11, + REGAMMA_CNTLA_EXP_REGION11_NUM_SEGMENTS); + + dm_write_reg(opp110->base.ctx, + DCP_REG(mmREGAMMA_CNTLA_REGION_10_11), + value); + } + + curve += 2; + { + value = 0; + set_reg_field_value( + value, + curve[0].offset, + REGAMMA_CNTLA_REGION_12_13, + REGAMMA_CNTLA_EXP_REGION12_LUT_OFFSET); + + set_reg_field_value( + value, + curve[0].segments_num, + REGAMMA_CNTLA_REGION_12_13, + REGAMMA_CNTLA_EXP_REGION12_NUM_SEGMENTS); + + set_reg_field_value( + value, + curve[1].offset, + REGAMMA_CNTLA_REGION_12_13, + REGAMMA_CNTLA_EXP_REGION13_LUT_OFFSET); + + set_reg_field_value( + value, + curve[1].segments_num, + REGAMMA_CNTLA_REGION_12_13, + REGAMMA_CNTLA_EXP_REGION13_NUM_SEGMENTS); + + dm_write_reg(opp110->base.ctx, + DCP_REG(mmREGAMMA_CNTLA_REGION_12_13), + value); + } + + curve += 2; + { + value = 0; + set_reg_field_value( + value, + curve[0].offset, + REGAMMA_CNTLA_REGION_14_15, + REGAMMA_CNTLA_EXP_REGION14_LUT_OFFSET); + + set_reg_field_value( + value, + curve[0].segments_num, + REGAMMA_CNTLA_REGION_14_15, + REGAMMA_CNTLA_EXP_REGION14_NUM_SEGMENTS); + + set_reg_field_value( + value, + curve[1].offset, + REGAMMA_CNTLA_REGION_14_15, + REGAMMA_CNTLA_EXP_REGION15_LUT_OFFSET); + + set_reg_field_value( + value, + curve[1].segments_num, + REGAMMA_CNTLA_REGION_14_15, + REGAMMA_CNTLA_EXP_REGION15_NUM_SEGMENTS); + + dm_write_reg(opp110->base.ctx, + DCP_REG(mmREGAMMA_CNTLA_REGION_14_15), + value); + } +} + +static void program_pwl( + struct dce110_opp *opp110, + const struct pwl_params *params) +{ + uint32_t value; + + { + uint8_t max_tries = 10; + uint8_t counter = 0; + + /* Power on LUT memory */ + value = dm_read_reg(opp110->base.ctx, + DCFE_REG(mmDCFE_MEM_PWR_CTRL)); + + set_reg_field_value( + value, + 1, + DCFE_MEM_PWR_CTRL, + DCP_REGAMMA_MEM_PWR_DIS); + + dm_write_reg(opp110->base.ctx, + DCFE_REG(mmDCFE_MEM_PWR_CTRL), value); + + while (counter < max_tries) { + value = + dm_read_reg( + opp110->base.ctx, + DCFE_REG(mmDCFE_MEM_PWR_STATUS)); + + if (get_reg_field_value( + value, + DCFE_MEM_PWR_STATUS, + DCP_REGAMMA_MEM_PWR_STATE) == 0) + break; + + ++counter; + } + + if (counter == max_tries) { + dm_logger_write(opp110->base.ctx->logger, LOG_WARNING, + "%s: regamma lut was not powered on " + "in a timely manner," + " programming still proceeds\n", + __func__); + } + } + + value = 0; + + set_reg_field_value( + value, + 7, + REGAMMA_LUT_WRITE_EN_MASK, + REGAMMA_LUT_WRITE_EN_MASK); + + dm_write_reg(opp110->base.ctx, + DCP_REG(mmREGAMMA_LUT_WRITE_EN_MASK), value); + dm_write_reg(opp110->base.ctx, + DCP_REG(mmREGAMMA_LUT_INDEX), 0); + + /* Program REGAMMA_LUT_DATA */ + { + const uint32_t addr = DCP_REG(mmREGAMMA_LUT_DATA); + + uint32_t i = 0; + + const struct pwl_result_data *rgb = params->rgb_resulted; + + while (i != params->hw_points_num) { + dm_write_reg(opp110->base.ctx, addr, rgb->red_reg); + dm_write_reg(opp110->base.ctx, addr, rgb->green_reg); + dm_write_reg(opp110->base.ctx, addr, rgb->blue_reg); + + dm_write_reg(opp110->base.ctx, addr, + rgb->delta_red_reg); + dm_write_reg(opp110->base.ctx, addr, + rgb->delta_green_reg); + dm_write_reg(opp110->base.ctx, addr, + rgb->delta_blue_reg); + + ++rgb; + ++i; + } + } + + /* we are done with DCP LUT memory; re-enable low power mode */ + value = dm_read_reg(opp110->base.ctx, DCFE_REG(mmDCFE_MEM_PWR_CTRL)); + + set_reg_field_value( + value, + 0, + DCFE_MEM_PWR_CTRL, + DCP_REGAMMA_MEM_PWR_DIS); + + dm_write_reg(opp110->base.ctx, DCFE_REG(mmDCFE_MEM_PWR_CTRL), value); +} + +bool dce110_opp_program_regamma_pwl( + struct output_pixel_processor *opp, + const struct pwl_params *params) +{ + struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + + /* Setup regions */ + regamma_config_regions_and_segments(opp110, params); + + /* Program PWL */ + program_pwl(opp110, params); + + return true; +} + +void dce110_opp_power_on_regamma_lut( + struct output_pixel_processor *opp, + bool power_on) +{ + struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + + uint32_t value = + dm_read_reg(opp->ctx, DCFE_REG(mmDCFE_MEM_PWR_CTRL)); + + set_reg_field_value( + value, + power_on, + DCFE_MEM_PWR_CTRL, + DCP_REGAMMA_MEM_PWR_DIS); + + set_reg_field_value( + value, + power_on, + DCFE_MEM_PWR_CTRL, + DCP_LUT_MEM_PWR_DIS); + + dm_write_reg(opp->ctx, DCFE_REG(mmDCFE_MEM_PWR_CTRL), value); +} + +void dce110_opp_set_regamma_mode(struct output_pixel_processor *opp, + enum opp_regamma mode) +{ + struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + uint32_t value = dm_read_reg(opp110->base.ctx, + DCP_REG(mmREGAMMA_CONTROL)); + + set_reg_field_value( + value, + mode, + REGAMMA_CONTROL, + GRPH_REGAMMA_MODE); + + dm_write_reg(opp110->base.ctx, DCP_REG(mmREGAMMA_CONTROL), + value); +} diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c new file mode 100644 index 000000000000..3b3a9175b2c3 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c @@ -0,0 +1,551 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* include DCE11 register header files */ +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" + +#include "dce110_opp.h" +#include "gamma_types.h" + +static void power_on_lut(struct output_pixel_processor *opp, + bool power_on, bool inputgamma, bool regamma) +{ + uint32_t value = dm_read_reg(opp->ctx, mmDCFEV_MEM_PWR_CTRL); + int i; + + if (power_on) { + if (inputgamma) + set_reg_field_value( + value, + 1, + DCFEV_MEM_PWR_CTRL, + COL_MAN_INPUT_GAMMA_MEM_PWR_DIS); + if (regamma) + set_reg_field_value( + value, + 1, + DCFEV_MEM_PWR_CTRL, + COL_MAN_GAMMA_CORR_MEM_PWR_DIS); + } else { + if (inputgamma) + set_reg_field_value( + value, + 0, + DCFEV_MEM_PWR_CTRL, + COL_MAN_INPUT_GAMMA_MEM_PWR_DIS); + if (regamma) + set_reg_field_value( + value, + 0, + DCFEV_MEM_PWR_CTRL, + COL_MAN_GAMMA_CORR_MEM_PWR_DIS); + } + + dm_write_reg(opp->ctx, mmDCFEV_MEM_PWR_CTRL, value); + + for (i = 0; i < 3; i++) { + value = dm_read_reg(opp->ctx, mmDCFEV_MEM_PWR_CTRL); + if (get_reg_field_value(value, + DCFEV_MEM_PWR_CTRL, + COL_MAN_INPUT_GAMMA_MEM_PWR_DIS) && + get_reg_field_value(value, + DCFEV_MEM_PWR_CTRL, + COL_MAN_GAMMA_CORR_MEM_PWR_DIS)) + break; + + udelay(2); + } +} + +static void set_bypass_input_gamma(struct dce110_opp *opp110) +{ + uint32_t value; + + value = dm_read_reg(opp110->base.ctx, + mmCOL_MAN_INPUT_GAMMA_CONTROL1); + + set_reg_field_value( + value, + 0, + COL_MAN_INPUT_GAMMA_CONTROL1, + INPUT_GAMMA_MODE); + + dm_write_reg(opp110->base.ctx, + mmCOL_MAN_INPUT_GAMMA_CONTROL1, value); +} + +static void configure_regamma_mode(struct dce110_opp *opp110, uint32_t mode) +{ + uint32_t value = 0; + + set_reg_field_value( + value, + mode, + GAMMA_CORR_CONTROL, + GAMMA_CORR_MODE); + + dm_write_reg(opp110->base.ctx, mmGAMMA_CORR_CONTROL, 0); +} + +/* + ***************************************************************************** + * Function: regamma_config_regions_and_segments + * + * build regamma curve by using predefined hw points + * uses interface parameters ,like EDID coeff. + * + * @param : parameters interface parameters + * @return void + * + * @note + * + * @see + * + ***************************************************************************** + */ +static void regamma_config_regions_and_segments( + struct dce110_opp *opp110, const struct pwl_params *params) +{ + const struct gamma_curve *curve; + uint32_t value = 0; + + { + set_reg_field_value( + value, + params->arr_points[0].custom_float_x, + GAMMA_CORR_CNTLA_START_CNTL, + GAMMA_CORR_CNTLA_EXP_REGION_START); + + set_reg_field_value( + value, + 0, + GAMMA_CORR_CNTLA_START_CNTL, + GAMMA_CORR_CNTLA_EXP_REGION_START_SEGMENT); + + dm_write_reg(opp110->base.ctx, mmGAMMA_CORR_CNTLA_START_CNTL, + value); + } + { + value = 0; + set_reg_field_value( + value, + params->arr_points[0].custom_float_slope, + GAMMA_CORR_CNTLA_SLOPE_CNTL, + GAMMA_CORR_CNTLA_EXP_REGION_LINEAR_SLOPE); + + dm_write_reg(opp110->base.ctx, + mmGAMMA_CORR_CNTLA_SLOPE_CNTL, value); + } + { + value = 0; + set_reg_field_value( + value, + params->arr_points[1].custom_float_x, + GAMMA_CORR_CNTLA_END_CNTL1, + GAMMA_CORR_CNTLA_EXP_REGION_END); + + dm_write_reg(opp110->base.ctx, + mmGAMMA_CORR_CNTLA_END_CNTL1, value); + } + { + value = 0; + set_reg_field_value( + value, + params->arr_points[2].custom_float_slope, + GAMMA_CORR_CNTLA_END_CNTL2, + GAMMA_CORR_CNTLA_EXP_REGION_END_BASE); + + set_reg_field_value( + value, + params->arr_points[1].custom_float_y, + GAMMA_CORR_CNTLA_END_CNTL2, + GAMMA_CORR_CNTLA_EXP_REGION_END_SLOPE); + + dm_write_reg(opp110->base.ctx, + mmGAMMA_CORR_CNTLA_END_CNTL2, value); + } + + curve = params->arr_curve_points; + + { + value = 0; + set_reg_field_value( + value, + curve[0].offset, + GAMMA_CORR_CNTLA_REGION_0_1, + GAMMA_CORR_CNTLA_EXP_REGION0_LUT_OFFSET); + + set_reg_field_value( + value, + curve[0].segments_num, + GAMMA_CORR_CNTLA_REGION_0_1, + GAMMA_CORR_CNTLA_EXP_REGION0_NUM_SEGMENTS); + + set_reg_field_value( + value, + curve[1].offset, + GAMMA_CORR_CNTLA_REGION_0_1, + GAMMA_CORR_CNTLA_EXP_REGION1_LUT_OFFSET); + + set_reg_field_value( + value, + curve[1].segments_num, + GAMMA_CORR_CNTLA_REGION_0_1, + GAMMA_CORR_CNTLA_EXP_REGION1_NUM_SEGMENTS); + + dm_write_reg( + opp110->base.ctx, + mmGAMMA_CORR_CNTLA_REGION_0_1, + value); + } + + curve += 2; + { + value = 0; + set_reg_field_value( + value, + curve[0].offset, + GAMMA_CORR_CNTLA_REGION_2_3, + GAMMA_CORR_CNTLA_EXP_REGION2_LUT_OFFSET); + + set_reg_field_value( + value, + curve[0].segments_num, + GAMMA_CORR_CNTLA_REGION_2_3, + GAMMA_CORR_CNTLA_EXP_REGION2_NUM_SEGMENTS); + + set_reg_field_value( + value, + curve[1].offset, + GAMMA_CORR_CNTLA_REGION_2_3, + GAMMA_CORR_CNTLA_EXP_REGION3_LUT_OFFSET); + + set_reg_field_value( + value, + curve[1].segments_num, + GAMMA_CORR_CNTLA_REGION_2_3, + GAMMA_CORR_CNTLA_EXP_REGION3_NUM_SEGMENTS); + + dm_write_reg(opp110->base.ctx, + mmGAMMA_CORR_CNTLA_REGION_2_3, + value); + } + + curve += 2; + { + value = 0; + set_reg_field_value( + value, + curve[0].offset, + GAMMA_CORR_CNTLA_REGION_4_5, + GAMMA_CORR_CNTLA_EXP_REGION4_LUT_OFFSET); + + set_reg_field_value( + value, + curve[0].segments_num, + GAMMA_CORR_CNTLA_REGION_4_5, + GAMMA_CORR_CNTLA_EXP_REGION4_NUM_SEGMENTS); + + set_reg_field_value( + value, + curve[1].offset, + GAMMA_CORR_CNTLA_REGION_4_5, + GAMMA_CORR_CNTLA_EXP_REGION5_LUT_OFFSET); + + set_reg_field_value( + value, + curve[1].segments_num, + GAMMA_CORR_CNTLA_REGION_4_5, + GAMMA_CORR_CNTLA_EXP_REGION5_NUM_SEGMENTS); + + dm_write_reg(opp110->base.ctx, + mmGAMMA_CORR_CNTLA_REGION_4_5, + value); + } + + curve += 2; + { + value = 0; + set_reg_field_value( + value, + curve[0].offset, + GAMMA_CORR_CNTLA_REGION_6_7, + GAMMA_CORR_CNTLA_EXP_REGION6_LUT_OFFSET); + + set_reg_field_value( + value, + curve[0].segments_num, + GAMMA_CORR_CNTLA_REGION_6_7, + GAMMA_CORR_CNTLA_EXP_REGION6_NUM_SEGMENTS); + + set_reg_field_value( + value, + curve[1].offset, + GAMMA_CORR_CNTLA_REGION_6_7, + GAMMA_CORR_CNTLA_EXP_REGION7_LUT_OFFSET); + + set_reg_field_value( + value, + curve[1].segments_num, + GAMMA_CORR_CNTLA_REGION_6_7, + GAMMA_CORR_CNTLA_EXP_REGION7_NUM_SEGMENTS); + + dm_write_reg(opp110->base.ctx, + mmGAMMA_CORR_CNTLA_REGION_6_7, + value); + } + + curve += 2; + { + value = 0; + set_reg_field_value( + value, + curve[0].offset, + GAMMA_CORR_CNTLA_REGION_8_9, + GAMMA_CORR_CNTLA_EXP_REGION8_LUT_OFFSET); + + set_reg_field_value( + value, + curve[0].segments_num, + GAMMA_CORR_CNTLA_REGION_8_9, + GAMMA_CORR_CNTLA_EXP_REGION8_NUM_SEGMENTS); + + set_reg_field_value( + value, + curve[1].offset, + GAMMA_CORR_CNTLA_REGION_8_9, + GAMMA_CORR_CNTLA_EXP_REGION9_LUT_OFFSET); + + set_reg_field_value( + value, + curve[1].segments_num, + GAMMA_CORR_CNTLA_REGION_8_9, + GAMMA_CORR_CNTLA_EXP_REGION9_NUM_SEGMENTS); + + dm_write_reg(opp110->base.ctx, + mmGAMMA_CORR_CNTLA_REGION_8_9, + value); + } + + curve += 2; + { + value = 0; + set_reg_field_value( + value, + curve[0].offset, + GAMMA_CORR_CNTLA_REGION_10_11, + GAMMA_CORR_CNTLA_EXP_REGION10_LUT_OFFSET); + + set_reg_field_value( + value, + curve[0].segments_num, + GAMMA_CORR_CNTLA_REGION_10_11, + GAMMA_CORR_CNTLA_EXP_REGION10_NUM_SEGMENTS); + + set_reg_field_value( + value, + curve[1].offset, + GAMMA_CORR_CNTLA_REGION_10_11, + GAMMA_CORR_CNTLA_EXP_REGION11_LUT_OFFSET); + + set_reg_field_value( + value, + curve[1].segments_num, + GAMMA_CORR_CNTLA_REGION_10_11, + GAMMA_CORR_CNTLA_EXP_REGION11_NUM_SEGMENTS); + + dm_write_reg(opp110->base.ctx, + mmGAMMA_CORR_CNTLA_REGION_10_11, + value); + } + + curve += 2; + { + value = 0; + set_reg_field_value( + value, + curve[0].offset, + GAMMA_CORR_CNTLA_REGION_12_13, + GAMMA_CORR_CNTLA_EXP_REGION12_LUT_OFFSET); + + set_reg_field_value( + value, + curve[0].segments_num, + GAMMA_CORR_CNTLA_REGION_12_13, + GAMMA_CORR_CNTLA_EXP_REGION12_NUM_SEGMENTS); + + set_reg_field_value( + value, + curve[1].offset, + GAMMA_CORR_CNTLA_REGION_12_13, + GAMMA_CORR_CNTLA_EXP_REGION13_LUT_OFFSET); + + set_reg_field_value( + value, + curve[1].segments_num, + GAMMA_CORR_CNTLA_REGION_12_13, + GAMMA_CORR_CNTLA_EXP_REGION13_NUM_SEGMENTS); + + dm_write_reg(opp110->base.ctx, + mmGAMMA_CORR_CNTLA_REGION_12_13, + value); + } + + curve += 2; + { + value = 0; + set_reg_field_value( + value, + curve[0].offset, + GAMMA_CORR_CNTLA_REGION_14_15, + GAMMA_CORR_CNTLA_EXP_REGION14_LUT_OFFSET); + + set_reg_field_value( + value, + curve[0].segments_num, + GAMMA_CORR_CNTLA_REGION_14_15, + GAMMA_CORR_CNTLA_EXP_REGION14_NUM_SEGMENTS); + + set_reg_field_value( + value, + curve[1].offset, + GAMMA_CORR_CNTLA_REGION_14_15, + GAMMA_CORR_CNTLA_EXP_REGION15_LUT_OFFSET); + + set_reg_field_value( + value, + curve[1].segments_num, + GAMMA_CORR_CNTLA_REGION_14_15, + GAMMA_CORR_CNTLA_EXP_REGION15_NUM_SEGMENTS); + + dm_write_reg(opp110->base.ctx, + mmGAMMA_CORR_CNTLA_REGION_14_15, + value); + } +} + +static void program_pwl(struct dce110_opp *opp110, + const struct pwl_params *params) +{ + uint32_t value = 0; + + set_reg_field_value( + value, + 7, + GAMMA_CORR_LUT_WRITE_EN_MASK, + GAMMA_CORR_LUT_WRITE_EN_MASK); + + dm_write_reg(opp110->base.ctx, + mmGAMMA_CORR_LUT_WRITE_EN_MASK, value); + + dm_write_reg(opp110->base.ctx, + mmGAMMA_CORR_LUT_INDEX, 0); + + /* Program REGAMMA_LUT_DATA */ + { + const uint32_t addr = mmGAMMA_CORR_LUT_DATA; + uint32_t i = 0; + const struct pwl_result_data *rgb = + params->rgb_resulted; + + while (i != params->hw_points_num) { + dm_write_reg(opp110->base.ctx, addr, rgb->red_reg); + dm_write_reg(opp110->base.ctx, addr, rgb->green_reg); + dm_write_reg(opp110->base.ctx, addr, rgb->blue_reg); + + dm_write_reg(opp110->base.ctx, addr, + rgb->delta_red_reg); + dm_write_reg(opp110->base.ctx, addr, + rgb->delta_green_reg); + dm_write_reg(opp110->base.ctx, addr, + rgb->delta_blue_reg); + + ++rgb; + ++i; + } + } +} + +bool dce110_opp_program_regamma_pwl_v( + struct output_pixel_processor *opp, + const struct pwl_params *params) +{ + struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + + /* Setup regions */ + regamma_config_regions_and_segments(opp110, params); + + set_bypass_input_gamma(opp110); + + /* Power on gamma LUT memory */ + power_on_lut(opp, true, false, true); + + /* Program PWL */ + program_pwl(opp110, params); + + /* program regamma config */ + configure_regamma_mode(opp110, 1); + + /* Power return to auto back */ + power_on_lut(opp, false, false, true); + + return true; +} + +void dce110_opp_power_on_regamma_lut_v( + struct output_pixel_processor *opp, + bool power_on) +{ + uint32_t value = dm_read_reg(opp->ctx, mmDCFEV_MEM_PWR_CTRL); + + set_reg_field_value( + value, + 0, + DCFEV_MEM_PWR_CTRL, + COL_MAN_GAMMA_CORR_MEM_PWR_FORCE); + + set_reg_field_value( + value, + power_on, + DCFEV_MEM_PWR_CTRL, + COL_MAN_GAMMA_CORR_MEM_PWR_DIS); + + set_reg_field_value( + value, + 0, + DCFEV_MEM_PWR_CTRL, + COL_MAN_INPUT_GAMMA_MEM_PWR_FORCE); + + set_reg_field_value( + value, + power_on, + DCFEV_MEM_PWR_CTRL, + COL_MAN_INPUT_GAMMA_MEM_PWR_DIS); + + dm_write_reg(opp->ctx, mmDCFEV_MEM_PWR_CTRL, value); +} diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c new file mode 100644 index 000000000000..4b32397529ec --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c @@ -0,0 +1,63 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* include DCE11 register header files */ +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" + +#include "dce110_opp.h" +#include "dce110_opp_v.h" + +#include "gamma_types.h" + +/*****************************************/ +/* Constructor, Destructor */ +/*****************************************/ + +static const struct opp_funcs funcs = { + .opp_power_on_regamma_lut = dce110_opp_power_on_regamma_lut_v, + .opp_program_regamma_pwl = dce110_opp_program_regamma_pwl_v, + .opp_set_csc_default = dce110_opp_v_set_csc_default, + .opp_set_csc_adjustment = dce110_opp_v_set_csc_adjustment, + .opp_set_dyn_expansion = dce110_opp_set_dyn_expansion, + .opp_set_regamma_mode = dce110_opp_set_regamma_mode, + .opp_destroy = dce110_opp_destroy, + .opp_program_fmt = dce110_opp_program_fmt, + .opp_program_bit_depth_reduction = + dce110_opp_program_bit_depth_reduction +}; + +bool dce110_opp_v_construct(struct dce110_opp *opp110, + struct dc_context *ctx) +{ + opp110->base.funcs = &funcs; + + opp110->base.ctx = ctx; + + return true; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h new file mode 100644 index 000000000000..dcdbf86fccc1 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h @@ -0,0 +1,56 @@ +/* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_OPP_DCE110_V_H__ +#define __DC_OPP_DCE110_V_H__ + +#include "dc_types.h" +#include "opp.h" +#include "core_types.h" + +#include "gamma_types.h" /* decprecated */ + +struct gamma_parameters; + +bool dce110_opp_v_construct(struct dce110_opp *opp110, + struct dc_context *ctx); + +/* underlay callbacks */ +void dce110_opp_v_set_csc_default( + struct output_pixel_processor *opp, + const struct default_adjustment *default_adjust); + +void dce110_opp_v_set_csc_adjustment( + struct output_pixel_processor *opp, + const struct out_csc_color_matrix *tbl_entry); + +bool dce110_opp_program_regamma_pwl_v( + struct output_pixel_processor *opp, + const struct pwl_params *params); + +void dce110_opp_power_on_regamma_lut_v( + struct output_pixel_processor *opp, + bool power_on); + +#endif /* __DC_OPP_DCE110_V_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c new file mode 100644 index 000000000000..959467fa421e --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -0,0 +1,1413 @@ +/* +* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "link_encoder.h" +#include "stream_encoder.h" + +#include "resource.h" +#include "dce110/dce110_resource.h" + +#include "include/irq_service_interface.h" +#include "dce/dce_audio.h" +#include "dce110/dce110_timing_generator.h" +#include "irq/dce110/irq_service_dce110.h" +#include "dce110/dce110_timing_generator_v.h" +#include "dce/dce_link_encoder.h" +#include "dce/dce_stream_encoder.h" +#include "dce110/dce110_mem_input.h" +#include "dce110/dce110_mem_input_v.h" +#include "dce110/dce110_ipp.h" +#include "dce/dce_transform.h" +#include "dce110/dce110_transform_v.h" +#include "dce110/dce110_opp.h" +#include "dce110/dce110_opp_v.h" +#include "dce/dce_clock_source.h" +#include "dce/dce_hwseq.h" +#include "dce110/dce110_hw_sequencer.h" + +#include "reg_helper.h" + +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" + +#ifndef mmMC_HUB_RDREQ_DMIF_LIMIT +#include "gmc/gmc_8_2_d.h" +#include "gmc/gmc_8_2_sh_mask.h" +#endif + +#ifndef mmDP_DPHY_INTERNAL_CTRL + #define mmDP_DPHY_INTERNAL_CTRL 0x4aa7 + #define mmDP0_DP_DPHY_INTERNAL_CTRL 0x4aa7 + #define mmDP1_DP_DPHY_INTERNAL_CTRL 0x4ba7 + #define mmDP2_DP_DPHY_INTERNAL_CTRL 0x4ca7 + #define mmDP3_DP_DPHY_INTERNAL_CTRL 0x4da7 + #define mmDP4_DP_DPHY_INTERNAL_CTRL 0x4ea7 + #define mmDP5_DP_DPHY_INTERNAL_CTRL 0x4fa7 + #define mmDP6_DP_DPHY_INTERNAL_CTRL 0x54a7 + #define mmDP7_DP_DPHY_INTERNAL_CTRL 0x56a7 + #define mmDP8_DP_DPHY_INTERNAL_CTRL 0x57a7 +#endif + +#ifndef mmBIOS_SCRATCH_2 + #define mmBIOS_SCRATCH_2 0x05CB + #define mmBIOS_SCRATCH_6 0x05CF +#endif + +#ifndef mmDP_DPHY_BS_SR_SWAP_CNTL + #define mmDP_DPHY_BS_SR_SWAP_CNTL 0x4ADC + #define mmDP0_DP_DPHY_BS_SR_SWAP_CNTL 0x4ADC + #define mmDP1_DP_DPHY_BS_SR_SWAP_CNTL 0x4BDC + #define mmDP2_DP_DPHY_BS_SR_SWAP_CNTL 0x4CDC + #define mmDP3_DP_DPHY_BS_SR_SWAP_CNTL 0x4DDC + #define mmDP4_DP_DPHY_BS_SR_SWAP_CNTL 0x4EDC + #define mmDP5_DP_DPHY_BS_SR_SWAP_CNTL 0x4FDC + #define mmDP6_DP_DPHY_BS_SR_SWAP_CNTL 0x54DC +#endif + +#ifndef mmDP_DPHY_FAST_TRAINING + #define mmDP_DPHY_FAST_TRAINING 0x4ABC + #define mmDP0_DP_DPHY_FAST_TRAINING 0x4ABC + #define mmDP1_DP_DPHY_FAST_TRAINING 0x4BBC + #define mmDP2_DP_DPHY_FAST_TRAINING 0x4CBC + #define mmDP3_DP_DPHY_FAST_TRAINING 0x4DBC + #define mmDP4_DP_DPHY_FAST_TRAINING 0x4EBC + #define mmDP5_DP_DPHY_FAST_TRAINING 0x4FBC + #define mmDP6_DP_DPHY_FAST_TRAINING 0x54BC +#endif + +#ifndef DPHY_RX_FAST_TRAINING_CAPABLE + #define DPHY_RX_FAST_TRAINING_CAPABLE 0x1 +#endif + +static const struct dce110_timing_generator_offsets dce110_tg_offsets[] = { + { + .crtc = (mmCRTC0_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL), + }, + { + .crtc = (mmCRTC1_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL), + }, + { + .crtc = (mmCRTC2_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL), + }, + { + .crtc = (mmCRTC3_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL), + }, + { + .crtc = (mmCRTC4_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL), + }, + { + .crtc = (mmCRTC5_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL), + } +}; + +static const struct dce110_mem_input_reg_offsets dce110_mi_reg_offsets[] = { + { + .dcp = (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE0_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + }, + { + .dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG1_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE1_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + }, + { + .dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG2_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE2_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + } +}; + + +static const struct dce110_ipp_reg_offsets dce110_ipp_reg_offsets[] = { +{ + .dcp_offset = (mmDCP0_CUR_CONTROL - mmCUR_CONTROL), +}, +{ + .dcp_offset = (mmDCP1_CUR_CONTROL - mmCUR_CONTROL), +}, +{ + .dcp_offset = (mmDCP2_CUR_CONTROL - mmCUR_CONTROL), +}, +{ + .dcp_offset = (mmDCP3_CUR_CONTROL - mmCUR_CONTROL), +}, +{ + .dcp_offset = (mmDCP4_CUR_CONTROL - mmCUR_CONTROL), +}, +{ + .dcp_offset = (mmDCP5_CUR_CONTROL - mmCUR_CONTROL), +} +}; + + + + +/* set register offset */ +#define SR(reg_name)\ + .reg_name = mm ## reg_name + +/* set register offset with instance */ +#define SRI(reg_name, block, id)\ + .reg_name = mm ## block ## id ## _ ## reg_name + + +#define transform_regs(id)\ +[id] = {\ + XFM_COMMON_REG_LIST_DCE110(id)\ +} + +static const struct dce_transform_registers xfm_regs[] = { + transform_regs(0), + transform_regs(1), + transform_regs(2) +}; + +static const struct dce_transform_shift xfm_shift = { + XFM_COMMON_MASK_SH_LIST_DCE110(__SHIFT) +}; + +static const struct dce_transform_mask xfm_mask = { + XFM_COMMON_MASK_SH_LIST_DCE110(_MASK) +}; + +#define aux_regs(id)\ +[id] = {\ + AUX_REG_LIST(id)\ +} + +static const struct dce110_link_enc_aux_registers link_enc_aux_regs[] = { + aux_regs(0), + aux_regs(1), + aux_regs(2), + aux_regs(3), + aux_regs(4), + aux_regs(5) +}; + +#define hpd_regs(id)\ +[id] = {\ + HPD_REG_LIST(id)\ +} + +static const struct dce110_link_enc_hpd_registers link_enc_hpd_regs[] = { + hpd_regs(0), + hpd_regs(1), + hpd_regs(2), + hpd_regs(3), + hpd_regs(4), + hpd_regs(5) +}; + + +#define link_regs(id)\ +[id] = {\ + LE_DCE110_REG_LIST(id)\ +} + +static const struct dce110_link_enc_registers link_enc_regs[] = { + link_regs(0), + link_regs(1), + link_regs(2), + link_regs(3), + link_regs(4), + link_regs(5), + link_regs(6), +}; + +#define stream_enc_regs(id)\ +[id] = {\ + SE_COMMON_REG_LIST(id),\ + .TMDS_CNTL = 0,\ +} + +static const struct dce110_stream_enc_registers stream_enc_regs[] = { + stream_enc_regs(0), + stream_enc_regs(1), + stream_enc_regs(2) +}; + +static const struct dce_stream_encoder_shift se_shift = { + SE_COMMON_MASK_SH_LIST_DCE110(__SHIFT) +}; + +static const struct dce_stream_encoder_mask se_mask = { + SE_COMMON_MASK_SH_LIST_DCE110(_MASK) +}; + +#define audio_regs(id)\ +[id] = {\ + AUD_COMMON_REG_LIST(id)\ +} + +static const struct dce_audio_registers audio_regs[] = { + audio_regs(0), + audio_regs(1), + audio_regs(2), + audio_regs(3), + audio_regs(4), + audio_regs(5), + audio_regs(6), +}; + +static const struct dce_audio_shift audio_shift = { + AUD_COMMON_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_aduio_mask audio_mask = { + AUD_COMMON_MASK_SH_LIST(_MASK) +}; + +/* AG TBD Needs to be reduced back to 3 pipes once dce10 hw sequencer implemented. */ +static const struct dce110_opp_reg_offsets dce110_opp_reg_offsets[] = { +{ + .fmt_offset = (mmFMT0_FMT_CONTROL - mmFMT0_FMT_CONTROL), + .dcfe_offset = (mmDCFE0_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), + .dcp_offset = (mmDCP0_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ .fmt_offset = (mmFMT1_FMT_CONTROL - mmFMT0_FMT_CONTROL), + .dcfe_offset = (mmDCFE1_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), + .dcp_offset = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ .fmt_offset = (mmFMT2_FMT_CONTROL - mmFMT0_FMT_CONTROL), + .dcfe_offset = (mmDCFE2_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), + .dcp_offset = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ + .fmt_offset = (mmFMT3_FMT_CONTROL - mmFMT0_FMT_CONTROL), + .dcfe_offset = (mmDCFE3_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), + .dcp_offset = (mmDCP3_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ .fmt_offset = (mmFMT4_FMT_CONTROL - mmFMT0_FMT_CONTROL), + .dcfe_offset = (mmDCFE4_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), + .dcp_offset = (mmDCP4_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ .fmt_offset = (mmFMT5_FMT_CONTROL - mmFMT0_FMT_CONTROL), + .dcfe_offset = (mmDCFE5_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), + .dcp_offset = (mmDCP5_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +} +}; + +#define clk_src_regs(id)\ +[id] = {\ + CS_COMMON_REG_LIST_DCE_100_110(id),\ +} + +static const struct dce110_clk_src_regs clk_src_regs[] = { + clk_src_regs(0), + clk_src_regs(1), + clk_src_regs(2) +}; + +static const struct dce110_clk_src_shift cs_shift = { + CS_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) +}; + +static const struct dce110_clk_src_mask cs_mask = { + CS_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) +}; + +static const struct bios_registers bios_regs = { + .BIOS_SCRATCH_6 = mmBIOS_SCRATCH_6 +}; + +static const struct resource_caps carrizo_resource_cap = { + .num_timing_generator = 3, + .num_video_plane = 1, + .num_audio = 3, + .num_stream_encoder = 3, + .num_pll = 2, +}; + +static const struct resource_caps stoney_resource_cap = { + .num_timing_generator = 2, + .num_video_plane = 1, + .num_audio = 3, + .num_stream_encoder = 3, + .num_pll = 2, +}; + +#define CTX ctx +#define REG(reg) mm ## reg + +#ifndef mmCC_DC_HDMI_STRAPS +#define mmCC_DC_HDMI_STRAPS 0x4819 +#define CC_DC_HDMI_STRAPS__HDMI_DISABLE_MASK 0x40 +#define CC_DC_HDMI_STRAPS__HDMI_DISABLE__SHIFT 0x6 +#define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER_MASK 0x700 +#define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER__SHIFT 0x8 +#endif + +static void read_dce_straps( + struct dc_context *ctx, + struct resource_straps *straps) +{ + REG_GET_2(CC_DC_HDMI_STRAPS, + HDMI_DISABLE, &straps->hdmi_disable, + AUDIO_STREAM_NUMBER, &straps->audio_stream_number); + + REG_GET(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO, &straps->dc_pinstraps_audio); +} + +static struct audio *create_audio( + struct dc_context *ctx, unsigned int inst) +{ + return dce_audio_create(ctx, inst, + &audio_regs[inst], &audio_shift, &audio_mask); +} + +static struct timing_generator *dce110_timing_generator_create( + struct dc_context *ctx, + uint32_t instance, + const struct dce110_timing_generator_offsets *offsets) +{ + struct dce110_timing_generator *tg110 = + dm_alloc(sizeof(struct dce110_timing_generator)); + + if (!tg110) + return NULL; + + if (dce110_timing_generator_construct(tg110, ctx, instance, offsets)) + return &tg110->base; + + BREAK_TO_DEBUGGER(); + dm_free(tg110); + return NULL; +} + +static struct stream_encoder *dce110_stream_encoder_create( + enum engine_id eng_id, + struct dc_context *ctx) +{ + struct dce110_stream_encoder *enc110 = + dm_alloc(sizeof(struct dce110_stream_encoder)); + + if (!enc110) + return NULL; + + if (dce110_stream_encoder_construct( + enc110, ctx, ctx->dc_bios, eng_id, + &stream_enc_regs[eng_id], &se_shift, &se_mask)) + return &enc110->base; + + BREAK_TO_DEBUGGER(); + dm_free(enc110); + return NULL; +} + +#define SRII(reg_name, block, id)\ + .reg_name[id] = mm ## block ## id ## _ ## reg_name + +static const struct dce_hwseq_registers hwseq_stoney_reg = { + HWSEQ_ST_REG_LIST() +}; + +static const struct dce_hwseq_registers hwseq_cz_reg = { + HWSEQ_CZ_REG_LIST() +}; + +static const struct dce_hwseq_shift hwseq_shift = { + HWSEQ_DCE11_MASK_SH_LIST(__SHIFT), +}; + +static const struct dce_hwseq_mask hwseq_mask = { + HWSEQ_DCE11_MASK_SH_LIST(_MASK), +}; + +static struct dce_hwseq *dce110_hwseq_create( + struct dc_context *ctx) +{ + struct dce_hwseq *hws = dm_alloc(sizeof(struct dce_hwseq)); + + if (hws) { + hws->ctx = ctx; + hws->regs = ASIC_REV_IS_STONEY(ctx->asic_id.hw_internal_rev) ? + &hwseq_stoney_reg : &hwseq_cz_reg; + hws->shifts = &hwseq_shift; + hws->masks = &hwseq_mask; + hws->wa.blnd_crtc_trigger = true; + } + return hws; +} + +static const struct resource_create_funcs res_create_funcs = { + .read_dce_straps = read_dce_straps, + .create_audio = create_audio, + .create_stream_encoder = dce110_stream_encoder_create, + .create_hwseq = dce110_hwseq_create, +}; + +#define mi_inst_regs(id) { \ + MI_REG_LIST(id), \ + .MC_HUB_RDREQ_DMIF_LIMIT = mmMC_HUB_RDREQ_DMIF_LIMIT \ +} +static const struct dce_mem_input_registers mi_regs[] = { + mi_inst_regs(0), + mi_inst_regs(1), + mi_inst_regs(2), +}; + +static const struct dce_mem_input_shift mi_shifts = { + MI_DCE_MASK_SH_LIST(__SHIFT), + .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE__SHIFT +}; + +static const struct dce_mem_input_mask mi_masks = { + MI_DCE_MASK_SH_LIST(_MASK), + .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE_MASK +}; + +static struct mem_input *dce110_mem_input_create( + struct dc_context *ctx, + uint32_t inst, + const struct dce110_mem_input_reg_offsets *offset) +{ + struct dce110_mem_input *mem_input110 = + dm_alloc(sizeof(struct dce110_mem_input)); + + if (!mem_input110) + return NULL; + + if (dce110_mem_input_construct(mem_input110, ctx, inst, offset)) { + struct mem_input *mi = &mem_input110->base; + + mi->regs = &mi_regs[inst]; + mi->shifts = &mi_shifts; + mi->masks = &mi_masks; + mi->wa.single_head_rdreq_dmif_limit = 3; + return mi; + } + + BREAK_TO_DEBUGGER(); + dm_free(mem_input110); + return NULL; +} + +static void dce110_transform_destroy(struct transform **xfm) +{ + dm_free(TO_DCE_TRANSFORM(*xfm)); + *xfm = NULL; +} + +static struct transform *dce110_transform_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dce_transform *transform = + dm_alloc(sizeof(struct dce_transform)); + + if (!transform) + return NULL; + + if (dce_transform_construct(transform, ctx, inst, + &xfm_regs[inst], &xfm_shift, &xfm_mask)) + return &transform->base; + + BREAK_TO_DEBUGGER(); + dm_free(transform); + return NULL; +} + +static struct input_pixel_processor *dce110_ipp_create( + struct dc_context *ctx, + uint32_t inst, + const struct dce110_ipp_reg_offsets *offsets) +{ + struct dce110_ipp *ipp = + dm_alloc(sizeof(struct dce110_ipp)); + + if (!ipp) + return NULL; + + if (dce110_ipp_construct(ipp, ctx, inst, offsets)) + return &ipp->base; + + BREAK_TO_DEBUGGER(); + dm_free(ipp); + return NULL; +} + +struct link_encoder *dce110_link_encoder_create( + const struct encoder_init_data *enc_init_data) +{ + struct dce110_link_encoder *enc110 = + dm_alloc(sizeof(struct dce110_link_encoder)); + + if (!enc110) + return NULL; + + if (dce110_link_encoder_construct( + enc110, + enc_init_data, + &link_enc_regs[enc_init_data->transmitter], + &link_enc_aux_regs[enc_init_data->channel - 1], + &link_enc_hpd_regs[enc_init_data->hpd_source])) { + + enc110->base.features.ycbcr420_supported = false; + enc110->base.features.max_hdmi_pixel_clock = 594000; + return &enc110->base; + } + + BREAK_TO_DEBUGGER(); + dm_free(enc110); + return NULL; +} + +static struct output_pixel_processor *dce110_opp_create( + struct dc_context *ctx, + uint32_t inst, + const struct dce110_opp_reg_offsets *offsets) +{ + struct dce110_opp *opp = + dm_alloc(sizeof(struct dce110_opp)); + + if (!opp) + return NULL; + + if (dce110_opp_construct(opp, + ctx, inst, offsets)) + return &opp->base; + + BREAK_TO_DEBUGGER(); + dm_free(opp); + return NULL; +} + +struct clock_source *dce110_clock_source_create( + struct dc_context *ctx, + struct dc_bios *bios, + enum clock_source_id id, + const struct dce110_clk_src_regs *regs, + bool dp_clk_src) +{ + struct dce110_clk_src *clk_src = + dm_alloc(sizeof(struct dce110_clk_src)); + + if (!clk_src) + return NULL; + + if (dce110_clk_src_construct(clk_src, ctx, bios, id, + regs, &cs_shift, &cs_mask)) { + clk_src->base.dp_clk_src = dp_clk_src; + return &clk_src->base; + } + + BREAK_TO_DEBUGGER(); + return NULL; +} + +void dce110_clock_source_destroy(struct clock_source **clk_src) +{ + struct dce110_clk_src *dce110_clk_src; + + if (!clk_src) + return; + + dce110_clk_src = TO_DCE110_CLK_SRC(*clk_src); + + if (dce110_clk_src->dp_ss_params) + dm_free(dce110_clk_src->dp_ss_params); + + if (dce110_clk_src->hdmi_ss_params) + dm_free(dce110_clk_src->hdmi_ss_params); + + if (dce110_clk_src->dvi_ss_params) + dm_free(dce110_clk_src->dvi_ss_params); + + dm_free(dce110_clk_src); + *clk_src = NULL; +} + +static void destruct(struct dce110_resource_pool *pool) +{ + unsigned int i; + + for (i = 0; i < pool->base.pipe_count; i++) { + if (pool->base.opps[i] != NULL) + dce110_opp_destroy(&pool->base.opps[i]); + + if (pool->base.transforms[i] != NULL) + dce110_transform_destroy(&pool->base.transforms[i]); + + if (pool->base.ipps[i] != NULL) + dce110_ipp_destroy(&pool->base.ipps[i]); + + if (pool->base.mis[i] != NULL) { + dm_free(TO_DCE110_MEM_INPUT(pool->base.mis[i])); + pool->base.mis[i] = NULL; + } + + if (pool->base.timing_generators[i] != NULL) { + dm_free(DCE110TG_FROM_TG(pool->base.timing_generators[i])); + pool->base.timing_generators[i] = NULL; + } + } + + for (i = 0; i < pool->base.stream_enc_count; i++) { + if (pool->base.stream_enc[i] != NULL) + dm_free(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); + } + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] != NULL) { + dce110_clock_source_destroy(&pool->base.clock_sources[i]); + } + } + + if (pool->base.dp_clock_source != NULL) + dce110_clock_source_destroy(&pool->base.dp_clock_source); + + for (i = 0; i < pool->base.audio_count; i++) { + if (pool->base.audios[i] != NULL) { + dce_aud_destroy(&pool->base.audios[i]); + } + } + + if (pool->base.display_clock != NULL) { + dal_display_clock_destroy(&pool->base.display_clock); + } + + if (pool->base.irqs != NULL) { + dal_irq_service_destroy(&pool->base.irqs); + } +} + + +static void get_pixel_clock_parameters( + const struct pipe_ctx *pipe_ctx, + struct pixel_clk_params *pixel_clk_params) +{ + const struct core_stream *stream = pipe_ctx->stream; + + /*TODO: is this halved for YCbCr 420? in that case we might want to move + * the pixel clock normalization for hdmi up to here instead of doing it + * in pll_adjust_pix_clk + */ + pixel_clk_params->requested_pix_clk = stream->public.timing.pix_clk_khz; + pixel_clk_params->encoder_object_id = stream->sink->link->link_enc->id; + pixel_clk_params->signal_type = pipe_ctx->stream->signal; + pixel_clk_params->controller_id = pipe_ctx->pipe_idx + 1; + /* TODO: un-hardcode*/ + pixel_clk_params->requested_sym_clk = LINK_RATE_LOW * + LINK_RATE_REF_FREQ_IN_KHZ; + pixel_clk_params->flags.ENABLE_SS = 0; + pixel_clk_params->color_depth = + stream->public.timing.display_color_depth; + pixel_clk_params->flags.DISPLAY_BLANKED = 1; + pixel_clk_params->flags.SUPPORT_YCBCR420 = (stream->public.timing.pixel_encoding == + PIXEL_ENCODING_YCBCR420); +} + +void dce110_resource_build_bit_depth_reduction_params( + const struct core_stream *stream, + struct bit_depth_reduction_params *fmt_bit_depth) +{ + memset(fmt_bit_depth, 0, sizeof(*fmt_bit_depth)); + + /*TODO: Need to un-hardcode, refer to function with same name + * in dal2 hw_sequencer*/ + + fmt_bit_depth->flags.TRUNCATE_ENABLED = 0; + fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 0; + fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 0; + + /* Diagnostics need consistent CRC of the image, that means + * dithering should not be enabled for Diagnostics. */ + if (IS_DIAG_DC(stream->ctx->dce_environment) == false) { + switch (stream->public.timing.display_color_depth) { + case COLOR_DEPTH_666: + fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; + fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 0; + break; + case COLOR_DEPTH_888: + fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; + fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 1; + break; + case COLOR_DEPTH_101010: + fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; + fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 2; + break; + default: + break; + } + fmt_bit_depth->flags.RGB_RANDOM = 1; + fmt_bit_depth->flags.HIGHPASS_RANDOM = 1; + fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; + fmt_bit_depth->flags.TRUNCATE_DEPTH = 2; + } + + return; +} + +enum dc_status dce110_resource_build_pipe_hw_param(struct pipe_ctx *pipe_ctx) +{ + get_pixel_clock_parameters(pipe_ctx, &pipe_ctx->pix_clk_params); + pipe_ctx->clock_source->funcs->get_pix_clk_dividers( + pipe_ctx->clock_source, + &pipe_ctx->pix_clk_params, + &pipe_ctx->pll_settings); + dce110_resource_build_bit_depth_reduction_params(pipe_ctx->stream, + &pipe_ctx->stream->bit_depth_params); + pipe_ctx->stream->clamping.pixel_encoding = pipe_ctx->stream->public.timing.pixel_encoding; + + return DC_OK; +} + +static bool is_surface_pixel_format_supported(struct pipe_ctx *pipe_ctx, unsigned int underlay_idx) +{ + if (pipe_ctx->pipe_idx != underlay_idx) + return true; + if (!pipe_ctx->surface) + return false; + if (pipe_ctx->surface->public.format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) + return false; + return true; +} + +static enum dc_status validate_mapped_resource( + const struct core_dc *dc, + struct validate_context *context) +{ + enum dc_status status = DC_OK; + uint8_t i, j, k; + + for (i = 0; i < context->target_count; i++) { + struct core_target *target = context->targets[i]; + + for (j = 0; j < target->public.stream_count; j++) { + struct core_stream *stream = + DC_STREAM_TO_CORE(target->public.streams[j]); + struct core_link *link = stream->sink->link; + + if (resource_is_stream_unchanged(dc->current_context, stream)) + continue; + + for (k = 0; k < MAX_PIPES; k++) { + struct pipe_ctx *pipe_ctx = + &context->res_ctx.pipe_ctx[k]; + + if (context->res_ctx.pipe_ctx[k].stream != stream) + continue; + + if (!is_surface_pixel_format_supported(pipe_ctx, + context->res_ctx.pool->underlay_pipe_index)) + return DC_SURFACE_PIXEL_FORMAT_UNSUPPORTED; + + if (!pipe_ctx->tg->funcs->validate_timing( + pipe_ctx->tg, &stream->public.timing)) + return DC_FAIL_CONTROLLER_VALIDATE; + + status = dce110_resource_build_pipe_hw_param(pipe_ctx); + + if (status != DC_OK) + return status; + + if (!link->link_enc->funcs->validate_output_with_stream( + link->link_enc, + pipe_ctx)) + return DC_FAIL_ENC_VALIDATE; + + /* TODO: validate audio ASIC caps, encoder */ + + status = dc_link_validate_mode_timing(stream, + link, + &stream->public.timing); + + if (status != DC_OK) + return status; + + resource_build_info_frame(pipe_ctx); + + /* do not need to validate non root pipes */ + break; + } + } + } + + return DC_OK; +} + +enum dc_status dce110_validate_bandwidth( + const struct core_dc *dc, + struct validate_context *context) +{ + enum dc_status result = DC_ERROR_UNEXPECTED; + + dm_logger_write( + dc->ctx->logger, LOG_BANDWIDTH_CALCS, + "%s: start", + __func__); + + if (!bw_calcs( + dc->ctx, + &dc->bw_dceip, + &dc->bw_vbios, + context->res_ctx.pipe_ctx, + context->res_ctx.pool->pipe_count, + &context->bw_results)) + result = DC_FAIL_BANDWIDTH_VALIDATE; + else + result = DC_OK; + + if (result == DC_FAIL_BANDWIDTH_VALIDATE) + dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_VALIDATION, + "%s: %dx%d@%d Bandwidth validation failed!\n", + __func__, + context->targets[0]->public.streams[0]->timing.h_addressable, + context->targets[0]->public.streams[0]->timing.v_addressable, + context->targets[0]->public.streams[0]->timing.pix_clk_khz); + + if (memcmp(&dc->current_context->bw_results, + &context->bw_results, sizeof(context->bw_results))) { + struct log_entry log_entry; + dm_logger_open( + dc->ctx->logger, + &log_entry, + LOG_BANDWIDTH_CALCS); + dm_logger_append(&log_entry, "%s: finish,\n" + "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n" + "stutMark_b: %d stutMark_a: %d\n", + __func__, + context->bw_results.nbp_state_change_wm_ns[0].b_mark, + context->bw_results.nbp_state_change_wm_ns[0].a_mark, + context->bw_results.urgent_wm_ns[0].b_mark, + context->bw_results.urgent_wm_ns[0].a_mark, + context->bw_results.stutter_exit_wm_ns[0].b_mark, + context->bw_results.stutter_exit_wm_ns[0].a_mark); + dm_logger_append(&log_entry, + "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n" + "stutMark_b: %d stutMark_a: %d\n", + context->bw_results.nbp_state_change_wm_ns[1].b_mark, + context->bw_results.nbp_state_change_wm_ns[1].a_mark, + context->bw_results.urgent_wm_ns[1].b_mark, + context->bw_results.urgent_wm_ns[1].a_mark, + context->bw_results.stutter_exit_wm_ns[1].b_mark, + context->bw_results.stutter_exit_wm_ns[1].a_mark); + dm_logger_append(&log_entry, + "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n" + "stutMark_b: %d stutMark_a: %d stutter_mode_enable: %d\n", + context->bw_results.nbp_state_change_wm_ns[2].b_mark, + context->bw_results.nbp_state_change_wm_ns[2].a_mark, + context->bw_results.urgent_wm_ns[2].b_mark, + context->bw_results.urgent_wm_ns[2].a_mark, + context->bw_results.stutter_exit_wm_ns[2].b_mark, + context->bw_results.stutter_exit_wm_ns[2].a_mark, + context->bw_results.stutter_mode_enable); + dm_logger_append(&log_entry, + "cstate: %d pstate: %d nbpstate: %d sync: %d dispclk: %d\n" + "sclk: %d sclk_sleep: %d yclk: %d blackout_recovery_time_us: %d\n", + context->bw_results.cpuc_state_change_enable, + context->bw_results.cpup_state_change_enable, + context->bw_results.nbp_state_change_enable, + context->bw_results.all_displays_in_sync, + context->bw_results.dispclk_khz, + context->bw_results.required_sclk, + context->bw_results.required_sclk_deep_sleep, + context->bw_results.required_yclk, + context->bw_results.blackout_recovery_time_us); + dm_logger_close(&log_entry); + } + return result; +} + +static bool dce110_validate_surface_sets( + const struct dc_validation_set set[], + int set_count) +{ + int i; + + for (i = 0; i < set_count; i++) { + if (set[i].surface_count == 0) + continue; + + if (set[i].surface_count > 2) + return false; + + if (set[i].surfaces[0]->src_rect.width + != set[i].target->streams[0]->src.width + || set[i].surfaces[0]->src_rect.height + != set[i].target->streams[0]->src.height) + return false; + if (set[i].surfaces[0]->format + >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) + return false; + + if (set[i].surface_count == 2) { + if (set[i].surfaces[1]->format + < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) + return false; + if (set[i].surfaces[1]->src_rect.width > 1920 + || set[i].surfaces[1]->src_rect.height > 1080) + return false; + + if (set[i].target->streams[0]->timing.pixel_encoding != PIXEL_ENCODING_RGB) + return false; + } + } + + return true; +} + +enum dc_status dce110_validate_with_context( + const struct core_dc *dc, + const struct dc_validation_set set[], + int set_count, + struct validate_context *context) +{ + struct dc_context *dc_ctx = dc->ctx; + enum dc_status result = DC_ERROR_UNEXPECTED; + int i; + + if (!dce110_validate_surface_sets(set, set_count)) + return DC_FAIL_SURFACE_VALIDATE; + + context->res_ctx.pool = dc->res_pool; + + for (i = 0; i < set_count; i++) { + context->targets[i] = DC_TARGET_TO_CORE(set[i].target); + dc_target_retain(&context->targets[i]->public); + context->target_count++; + } + + result = resource_map_pool_resources(dc, context); + + if (result == DC_OK) + result = resource_map_clock_resources(dc, context); + + if (!resource_validate_attach_surfaces( + set, set_count, dc->current_context, context)) { + DC_ERROR("Failed to attach surface to target!\n"); + return DC_FAIL_ATTACH_SURFACES; + } + + if (result == DC_OK) + result = validate_mapped_resource(dc, context); + + if (result == DC_OK) + result = resource_build_scaling_params_for_context(dc, context); + + if (result == DC_OK) + result = dce110_validate_bandwidth(dc, context); + + return result; +} + +enum dc_status dce110_validate_guaranteed( + const struct core_dc *dc, + const struct dc_target *dc_target, + struct validate_context *context) +{ + enum dc_status result = DC_ERROR_UNEXPECTED; + + context->res_ctx.pool = dc->res_pool; + + context->targets[0] = DC_TARGET_TO_CORE(dc_target); + dc_target_retain(&context->targets[0]->public); + context->target_count++; + + result = resource_map_pool_resources(dc, context); + + if (result == DC_OK) + result = resource_map_clock_resources(dc, context); + + if (result == DC_OK) + result = validate_mapped_resource(dc, context); + + if (result == DC_OK) { + validate_guaranteed_copy_target( + context, dc->public.caps.max_targets); + result = resource_build_scaling_params_for_context(dc, context); + } + + if (result == DC_OK) + result = dce110_validate_bandwidth(dc, context); + + return result; +} + +static struct pipe_ctx *dce110_acquire_idle_pipe_for_layer( + struct resource_context *res_ctx, + struct core_stream *stream) +{ + unsigned int underlay_idx = res_ctx->pool->underlay_pipe_index; + struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[underlay_idx]; + + if (res_ctx->pipe_ctx[underlay_idx].stream) { + return NULL; + } + + pipe_ctx->tg = res_ctx->pool->timing_generators[underlay_idx]; + pipe_ctx->mi = res_ctx->pool->mis[underlay_idx]; + /*pipe_ctx->ipp = res_ctx->pool->ipps[underlay_idx];*/ + pipe_ctx->xfm = res_ctx->pool->transforms[underlay_idx]; + pipe_ctx->opp = res_ctx->pool->opps[underlay_idx]; + pipe_ctx->dis_clk = res_ctx->pool->display_clock; + pipe_ctx->pipe_idx = underlay_idx; + + pipe_ctx->stream = stream; + + return pipe_ctx; + +} + +static void dce110_destroy_resource_pool(struct resource_pool **pool) +{ + struct dce110_resource_pool *dce110_pool = TO_DCE110_RES_POOL(*pool); + + destruct(dce110_pool); + dm_free(dce110_pool); + *pool = NULL; +} + + +static const struct resource_funcs dce110_res_pool_funcs = { + .destroy = dce110_destroy_resource_pool, + .link_enc_create = dce110_link_encoder_create, + .validate_with_context = dce110_validate_with_context, + .validate_guaranteed = dce110_validate_guaranteed, + .validate_bandwidth = dce110_validate_bandwidth, + .acquire_idle_pipe_for_layer = dce110_acquire_idle_pipe_for_layer, + .build_bit_depth_reduction_params = + dce110_resource_build_bit_depth_reduction_params +}; + +static void underlay_create(struct dc_context *ctx, struct resource_pool *pool) +{ + struct dce110_timing_generator *dce110_tgv = dm_alloc(sizeof (*dce110_tgv)); + struct dce_transform *dce110_xfmv = dm_alloc(sizeof (*dce110_xfmv)); + struct dce110_mem_input *dce110_miv = dm_alloc(sizeof (*dce110_miv)); + struct dce110_opp *dce110_oppv = dm_alloc(sizeof (*dce110_oppv)); + + dce110_opp_v_construct(dce110_oppv, ctx); + dce110_timing_generator_v_construct(dce110_tgv, ctx); + dce110_mem_input_v_construct(dce110_miv, ctx); + dce110_transform_v_construct(dce110_xfmv, ctx); + + pool->opps[pool->pipe_count] = &dce110_oppv->base; + pool->timing_generators[pool->pipe_count] = &dce110_tgv->base; + pool->mis[pool->pipe_count] = &dce110_miv->base; + pool->transforms[pool->pipe_count] = &dce110_xfmv->base; + pool->pipe_count++; + + /* update the public caps to indicate an underlay is available */ + ctx->dc->caps.max_slave_planes = 1; + ctx->dc->caps.max_slave_planes = 1; +} + +static void bw_calcs_data_update_from_pplib(struct core_dc *dc) +{ + struct dm_pp_clock_levels clks = {0}; + + /*do system clock*/ + dm_pp_get_clock_levels_by_type( + dc->ctx, + DM_PP_CLOCK_TYPE_ENGINE_CLK, + &clks); + /* convert all the clock fro kHz to fix point mHz */ + dc->bw_vbios.high_sclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels-1], 1000); + dc->bw_vbios.mid1_sclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels/8], 1000); + dc->bw_vbios.mid2_sclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels*2/8], 1000); + dc->bw_vbios.mid3_sclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels*3/8], 1000); + dc->bw_vbios.mid4_sclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels*4/8], 1000); + dc->bw_vbios.mid5_sclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels*5/8], 1000); + dc->bw_vbios.mid6_sclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels*6/8], 1000); + dc->bw_vbios.low_sclk = bw_frc_to_fixed( + clks.clocks_in_khz[0], 1000); + dc->sclk_lvls = clks; + + /*do display clock*/ + dm_pp_get_clock_levels_by_type( + dc->ctx, + DM_PP_CLOCK_TYPE_DISPLAY_CLK, + &clks); + dc->bw_vbios.high_voltage_max_dispclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels-1], 1000); + dc->bw_vbios.mid_voltage_max_dispclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels>>1], 1000); + dc->bw_vbios.low_voltage_max_dispclk = bw_frc_to_fixed( + clks.clocks_in_khz[0], 1000); + + /*do memory clock*/ + dm_pp_get_clock_levels_by_type( + dc->ctx, + DM_PP_CLOCK_TYPE_MEMORY_CLK, + &clks); + + dc->bw_vbios.low_yclk = bw_frc_to_fixed( + clks.clocks_in_khz[0] * MEMORY_TYPE_MULTIPLIER, 1000); + dc->bw_vbios.mid_yclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels>>1] * MEMORY_TYPE_MULTIPLIER, + 1000); + dc->bw_vbios.high_yclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels-1] * MEMORY_TYPE_MULTIPLIER, + 1000); +} + +enum clocks_state dce110_resource_convert_clock_state_pp_to_dc( + enum dm_pp_clocks_state pp_clock_state) +{ + enum clocks_state dc_clocks_state = CLOCKS_STATE_INVALID; + + switch (pp_clock_state) { + case DM_PP_CLOCKS_STATE_INVALID: + dc_clocks_state = CLOCKS_STATE_INVALID; + break; + case DM_PP_CLOCKS_STATE_ULTRA_LOW: + dc_clocks_state = CLOCKS_STATE_ULTRA_LOW; + break; + case DM_PP_CLOCKS_STATE_LOW: + dc_clocks_state = CLOCKS_STATE_LOW; + break; + case DM_PP_CLOCKS_STATE_NOMINAL: + dc_clocks_state = CLOCKS_STATE_NOMINAL; + break; + case DM_PP_CLOCKS_STATE_PERFORMANCE: + dc_clocks_state = CLOCKS_STATE_PERFORMANCE; + break; + case DM_PP_CLOCKS_DPM_STATE_LEVEL_4: + dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_4; + break; + case DM_PP_CLOCKS_DPM_STATE_LEVEL_5: + dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_5; + break; + case DM_PP_CLOCKS_DPM_STATE_LEVEL_6: + dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_6; + break; + case DM_PP_CLOCKS_DPM_STATE_LEVEL_7: + dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_7; + break; + default: + dc_clocks_state = CLOCKS_STATE_INVALID; + break; + } + + return dc_clocks_state; +} + +const struct resource_caps *dce110_resource_cap( + struct hw_asic_id *asic_id) +{ + if (ASIC_REV_IS_STONEY(asic_id->hw_internal_rev)) + return &stoney_resource_cap; + else + return &carrizo_resource_cap; +} + +static bool construct( + uint8_t num_virtual_links, + struct core_dc *dc, + struct dce110_resource_pool *pool, + struct hw_asic_id asic_id) +{ + unsigned int i; + struct dc_context *ctx = dc->ctx; + struct firmware_info info; + struct dc_bios *bp; + struct dm_pp_static_clock_info static_clk_info = {0}; + + ctx->dc_bios->regs = &bios_regs; + + pool->base.res_cap = dce110_resource_cap(&ctx->asic_id); + pool->base.funcs = &dce110_res_pool_funcs; + + /************************************************* + * Resource + asic cap harcoding * + *************************************************/ + + pool->base.pipe_count = pool->base.res_cap->num_timing_generator; + pool->base.underlay_pipe_index = pool->base.pipe_count; + + dc->public.caps.max_downscale_ratio = 150; + dc->public.caps.i2c_speed_in_khz = 100; + + /************************************************* + * Create resources * + *************************************************/ + + bp = ctx->dc_bios; + + if ((bp->funcs->get_firmware_info(bp, &info) == BP_RESULT_OK) && + info.external_clock_source_frequency_for_dp != 0) { + pool->base.dp_clock_source = + dce110_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true); + + pool->base.clock_sources[0] = + dce110_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, + &clk_src_regs[0], false); + pool->base.clock_sources[1] = + dce110_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, + &clk_src_regs[1], false); + + pool->base.clk_src_count = 2; + + /* TODO: find out if CZ support 3 PLLs */ + } + + if (pool->base.dp_clock_source == NULL) { + dm_error("DC: failed to create dp clock source!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] == NULL) { + dm_error("DC: failed to create clock sources!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + } + + pool->base.display_clock = dal_display_clock_dce110_create(ctx); + if (pool->base.display_clock == NULL) { + dm_error("DC: failed to create display clock!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + /* get static clock information for PPLIB or firmware, save + * max_clock_state + */ + if (dm_pp_get_static_clocks(ctx, &static_clk_info)) { + enum clocks_state max_clocks_state = + dce110_resource_convert_clock_state_pp_to_dc( + static_clk_info.max_clocks_state); + + dal_display_clock_store_max_clocks_state( + pool->base.display_clock, max_clocks_state); + } + + { + struct irq_service_init_data init_data; + init_data.ctx = dc->ctx; + pool->base.irqs = dal_irq_service_dce110_create(&init_data); + if (!pool->base.irqs) + goto res_create_fail; + } + + for (i = 0; i < pool->base.pipe_count; i++) { + pool->base.timing_generators[i] = dce110_timing_generator_create( + ctx, i, &dce110_tg_offsets[i]); + if (pool->base.timing_generators[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create tg!\n"); + goto res_create_fail; + } + + pool->base.mis[i] = dce110_mem_input_create(ctx, i, + &dce110_mi_reg_offsets[i]); + if (pool->base.mis[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create memory input!\n"); + goto res_create_fail; + } + + pool->base.ipps[i] = dce110_ipp_create(ctx, i, &dce110_ipp_reg_offsets[i]); + if (pool->base.ipps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create input pixel processor!\n"); + goto res_create_fail; + } + + pool->base.transforms[i] = dce110_transform_create(ctx, i); + if (pool->base.transforms[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create transform!\n"); + goto res_create_fail; + } + + pool->base.opps[i] = dce110_opp_create(ctx, i, &dce110_opp_reg_offsets[i]); + if (pool->base.opps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create output pixel processor!\n"); + goto res_create_fail; + } + } + + underlay_create(ctx, &pool->base); + + if (!resource_construct(num_virtual_links, dc, &pool->base, + &res_create_funcs)) + goto res_create_fail; + + /* Create hardware sequencer */ + if (!dce110_hw_sequencer_construct(dc)) + goto res_create_fail; + + if (ASIC_REV_IS_STONEY(ctx->asic_id.hw_internal_rev)) + bw_calcs_init(&dc->bw_dceip, &dc->bw_vbios, BW_CALCS_VERSION_STONEY); + else + bw_calcs_init(&dc->bw_dceip, &dc->bw_vbios, BW_CALCS_VERSION_CARRIZO); + + bw_calcs_data_update_from_pplib(dc); + + return true; + +res_create_fail: + destruct(pool); + return false; +} + +struct resource_pool *dce110_create_resource_pool( + uint8_t num_virtual_links, + struct core_dc *dc, + struct hw_asic_id asic_id) +{ + struct dce110_resource_pool *pool = + dm_alloc(sizeof(struct dce110_resource_pool)); + + if (!pool) + return NULL; + + if (construct(num_virtual_links, dc, pool, asic_id)) + return &pool->base; + + BREAK_TO_DEBUGGER(); + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.h new file mode 100644 index 000000000000..535623aa0052 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.h @@ -0,0 +1,56 @@ +/* +* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_RESOURCE_DCE110_H__ +#define __DC_RESOURCE_DCE110_H__ + +#include "core_types.h" + +struct core_dc; +struct resource_pool; + +#define TO_DCE110_RES_POOL(pool)\ + container_of(pool, struct dce110_resource_pool, base) + +struct dce110_resource_pool { + struct resource_pool base; +}; + +enum dc_status dce110_resource_build_pipe_hw_param(struct pipe_ctx *pipe_ctx); + +enum clocks_state dce110_resource_convert_clock_state_pp_to_dc( + enum dm_pp_clocks_state pp_clock_state); + +void dce110_resource_build_bit_depth_reduction_params( + const struct core_stream *stream, + struct bit_depth_reduction_params *fmt_bit_depth); + +struct resource_pool *dce110_create_resource_pool( + uint8_t num_virtual_links, + struct core_dc *dc, + struct hw_asic_id asic_id); + +#endif /* __DC_RESOURCE_DCE110_H__ */ + diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c new file mode 100644 index 000000000000..b1c97125f6fb --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c @@ -0,0 +1,1953 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* include DCE11 register header files */ +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" + +#include "dc_types.h" +#include "dc_bios_types.h" +#include "dc.h" + +#include "include/grph_object_id.h" +#include "include/logger_interface.h" +#include "dce110_timing_generator.h" + +#include "timing_generator.h" + + +#define NUMBER_OF_FRAME_TO_WAIT_ON_TRIGGERED_RESET 10 + +#define MAX_H_TOTAL (CRTC_H_TOTAL__CRTC_H_TOTAL_MASK + 1) +#define MAX_V_TOTAL (CRTC_V_TOTAL__CRTC_V_TOTAL_MASKhw + 1) + +#define CRTC_REG(reg) (reg + tg110->offsets.crtc) +#define DCP_REG(reg) (reg + tg110->offsets.dcp) + +/* Flowing register offsets are same in files of + * dce/dce_11_0_d.h + * dce/vi_polaris10_p/vi_polaris10_d.h + * + * So we can create dce110 timing generator to use it. + */ + + +/* +* apply_front_porch_workaround +* +* This is a workaround for a bug that has existed since R5xx and has not been +* fixed keep Front porch at minimum 2 for Interlaced mode or 1 for progressive. +*/ +static void dce110_timing_generator_apply_front_porch_workaround( + struct timing_generator *tg, + struct dc_crtc_timing *timing) +{ + if (timing->flags.INTERLACE == 1) { + if (timing->v_front_porch < 2) + timing->v_front_porch = 2; + } else { + if (timing->v_front_porch < 1) + timing->v_front_porch = 1; + } +} + +/** + ***************************************************************************** + * Function: is_in_vertical_blank + * + * @brief + * check the current status of CRTC to check if we are in Vertical Blank + * regioneased" state + * + * @return + * true if currently in blank region, false otherwise + * + ***************************************************************************** + */ +static bool dce110_timing_generator_is_in_vertical_blank( + struct timing_generator *tg) +{ + uint32_t addr = 0; + uint32_t value = 0; + uint32_t field = 0; + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + addr = CRTC_REG(mmCRTC_STATUS); + value = dm_read_reg(tg->ctx, addr); + field = get_reg_field_value(value, CRTC_STATUS, CRTC_V_BLANK); + return field == 1; +} + +void dce110_timing_generator_set_early_control( + struct timing_generator *tg, + uint32_t early_cntl) +{ + uint32_t regval; + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t address = CRTC_REG(mmCRTC_CONTROL); + + regval = dm_read_reg(tg->ctx, address); + set_reg_field_value(regval, early_cntl, + CRTC_CONTROL, CRTC_HBLANK_EARLY_CONTROL); + dm_write_reg(tg->ctx, address, regval); +} + +/** + * Enable CRTC + * Enable CRTC - call ASIC Control Object to enable Timing generator. + */ +bool dce110_timing_generator_enable_crtc(struct timing_generator *tg) +{ + enum bp_result result; + + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t value = 0; + + /* + * 3 is used to make sure V_UPDATE occurs at the beginning of the first + * line of vertical front porch + */ + set_reg_field_value( + value, + 0, + CRTC_MASTER_UPDATE_MODE, + MASTER_UPDATE_MODE); + + dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_MASTER_UPDATE_MODE), value); + + /* TODO: may want this on to catch underflow */ + value = 0; + dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_MASTER_UPDATE_LOCK), value); + + result = tg->bp->funcs->enable_crtc(tg->bp, tg110->controller_id, true); + + return result == BP_RESULT_OK; +} + +void dce110_timing_generator_program_blank_color( + struct timing_generator *tg, + const struct tg_color *black_color) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t addr = CRTC_REG(mmCRTC_BLACK_COLOR); + uint32_t value = dm_read_reg(tg->ctx, addr); + + set_reg_field_value( + value, + black_color->color_b_cb, + CRTC_BLACK_COLOR, + CRTC_BLACK_COLOR_B_CB); + set_reg_field_value( + value, + black_color->color_g_y, + CRTC_BLACK_COLOR, + CRTC_BLACK_COLOR_G_Y); + set_reg_field_value( + value, + black_color->color_r_cr, + CRTC_BLACK_COLOR, + CRTC_BLACK_COLOR_R_CR); + + dm_write_reg(tg->ctx, addr, value); +} + +/** + ***************************************************************************** + * Function: disable_stereo + * + * @brief + * Disables active stereo on controller + * Frame Packing need to be disabled in vBlank or when CRTC not running + ***************************************************************************** + */ +#if 0 +@TODOSTEREO +static void disable_stereo(struct timing_generator *tg) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t addr = CRTC_REG(mmCRTC_3D_STRUCTURE_CONTROL); + uint32_t value = 0; + uint32_t test = 0; + uint32_t field = 0; + uint32_t struc_en = 0; + uint32_t struc_stereo_sel_ovr = 0; + + value = dm_read_reg(tg->ctx, addr); + struc_en = get_reg_field_value( + value, + CRTC_3D_STRUCTURE_CONTROL, + CRTC_3D_STRUCTURE_EN); + + struc_stereo_sel_ovr = get_reg_field_value( + value, + CRTC_3D_STRUCTURE_CONTROL, + CRTC_3D_STRUCTURE_STEREO_SEL_OVR); + + /* + * When disabling Frame Packing in 2 step mode, we need to program both + * registers at the same frame + * Programming it in the beginning of VActive makes sure we are ok + */ + + if (struc_en != 0 && struc_stereo_sel_ovr == 0) { + tg->funcs->wait_for_vblank(tg); + tg->funcs->wait_for_vactive(tg); + } + + value = 0; + dm_write_reg(tg->ctx, addr, value); + + addr = tg->regs[IDX_CRTC_STEREO_CONTROL]; + dm_write_reg(tg->ctx, addr, value); +} +#endif + +/** + * disable_crtc - call ASIC Control Object to disable Timing generator. + */ +bool dce110_timing_generator_disable_crtc(struct timing_generator *tg) +{ + enum bp_result result; + + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + result = tg->bp->funcs->enable_crtc(tg->bp, tg110->controller_id, false); + + /* Need to make sure stereo is disabled according to the DCE5.0 spec */ + + /* + * @TODOSTEREO call this when adding stereo support + * tg->funcs->disable_stereo(tg); + */ + + return result == BP_RESULT_OK; +} + +/** +* program_horz_count_by_2 +* Programs DxCRTC_HORZ_COUNT_BY2_EN - 1 for DVI 30bpp mode, 0 otherwise +* +*/ +static void program_horz_count_by_2( + struct timing_generator *tg, + const struct dc_crtc_timing *timing) +{ + uint32_t regval; + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + regval = dm_read_reg(tg->ctx, + CRTC_REG(mmCRTC_COUNT_CONTROL)); + + set_reg_field_value(regval, 0, CRTC_COUNT_CONTROL, + CRTC_HORZ_COUNT_BY2_EN); + + if (timing->flags.HORZ_COUNT_BY_TWO) + set_reg_field_value(regval, 1, CRTC_COUNT_CONTROL, + CRTC_HORZ_COUNT_BY2_EN); + + dm_write_reg(tg->ctx, + CRTC_REG(mmCRTC_COUNT_CONTROL), regval); +} + +/** + * program_timing_generator + * Program CRTC Timing Registers - DxCRTC_H_*, DxCRTC_V_*, Pixel repetition. + * Call ASIC Control Object to program Timings. + */ +bool dce110_timing_generator_program_timing_generator( + struct timing_generator *tg, + const struct dc_crtc_timing *dc_crtc_timing) +{ + enum bp_result result; + struct bp_hw_crtc_timing_parameters bp_params; + struct dc_crtc_timing patched_crtc_timing; + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + uint32_t vsync_offset = dc_crtc_timing->v_border_bottom + + dc_crtc_timing->v_front_porch; + uint32_t v_sync_start =dc_crtc_timing->v_addressable + vsync_offset; + + uint32_t hsync_offset = dc_crtc_timing->h_border_right + + dc_crtc_timing->h_front_porch; + uint32_t h_sync_start = dc_crtc_timing->h_addressable + hsync_offset; + + memset(&bp_params, 0, sizeof(struct bp_hw_crtc_timing_parameters)); + + /* Due to an asic bug we need to apply the Front Porch workaround prior + * to programming the timing. + */ + + patched_crtc_timing = *dc_crtc_timing; + + dce110_timing_generator_apply_front_porch_workaround(tg, &patched_crtc_timing); + + bp_params.controller_id = tg110->controller_id; + + bp_params.h_total = patched_crtc_timing.h_total; + bp_params.h_addressable = + patched_crtc_timing.h_addressable; + bp_params.v_total = patched_crtc_timing.v_total; + bp_params.v_addressable = patched_crtc_timing.v_addressable; + + bp_params.h_sync_start = h_sync_start; + bp_params.h_sync_width = patched_crtc_timing.h_sync_width; + bp_params.v_sync_start = v_sync_start; + bp_params.v_sync_width = patched_crtc_timing.v_sync_width; + + /* Set overscan */ + bp_params.h_overscan_left = + patched_crtc_timing.h_border_left; + bp_params.h_overscan_right = + patched_crtc_timing.h_border_right; + bp_params.v_overscan_top = patched_crtc_timing.v_border_top; + bp_params.v_overscan_bottom = + patched_crtc_timing.v_border_bottom; + + /* Set flags */ + if (patched_crtc_timing.flags.HSYNC_POSITIVE_POLARITY == 1) + bp_params.flags.HSYNC_POSITIVE_POLARITY = 1; + + if (patched_crtc_timing.flags.VSYNC_POSITIVE_POLARITY == 1) + bp_params.flags.VSYNC_POSITIVE_POLARITY = 1; + + if (patched_crtc_timing.flags.INTERLACE == 1) + bp_params.flags.INTERLACE = 1; + + if (patched_crtc_timing.flags.HORZ_COUNT_BY_TWO == 1) + bp_params.flags.HORZ_COUNT_BY_TWO = 1; + + result = tg->bp->funcs->program_crtc_timing(tg->bp, &bp_params); + + program_horz_count_by_2(tg, &patched_crtc_timing); + + tg110->base.funcs->enable_advanced_request(tg, true, &patched_crtc_timing); + + /* Enable stereo - only when we need to pack 3D frame. Other types + * of stereo handled in explicit call */ + + return result == BP_RESULT_OK; +} + +/** + ***************************************************************************** + * Function: set_drr + * + * @brief + * Program dynamic refresh rate registers m_DxCRTC_V_TOTAL_*. + * + * @param [in] pHwCrtcTiming: point to H + * wCrtcTiming struct + ***************************************************************************** + */ +void dce110_timing_generator_set_drr( + struct timing_generator *tg, + const struct drr_params *params) +{ + /* register values */ + uint32_t v_total_min = 0; + uint32_t v_total_max = 0; + uint32_t v_total_cntl = 0; + uint32_t static_screen_cntl = 0; + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + uint32_t addr = 0; + + addr = CRTC_REG(mmCRTC_V_TOTAL_MIN); + v_total_min = dm_read_reg(tg->ctx, addr); + + addr = CRTC_REG(mmCRTC_V_TOTAL_MAX); + v_total_max = dm_read_reg(tg->ctx, addr); + + addr = CRTC_REG(mmCRTC_V_TOTAL_CONTROL); + v_total_cntl = dm_read_reg(tg->ctx, addr); + + addr = CRTC_REG(mmCRTC_STATIC_SCREEN_CONTROL); + static_screen_cntl = dm_read_reg(tg->ctx, addr); + + if (params != NULL && + params->vertical_total_max > 0 && + params->vertical_total_min > 0) { + + set_reg_field_value(v_total_max, + params->vertical_total_max - 1, + CRTC_V_TOTAL_MAX, + CRTC_V_TOTAL_MAX); + + set_reg_field_value(v_total_min, + params->vertical_total_min - 1, + CRTC_V_TOTAL_MIN, + CRTC_V_TOTAL_MIN); + + set_reg_field_value(v_total_cntl, + 1, + CRTC_V_TOTAL_CONTROL, + CRTC_V_TOTAL_MIN_SEL); + + set_reg_field_value(v_total_cntl, + 1, + CRTC_V_TOTAL_CONTROL, + CRTC_V_TOTAL_MAX_SEL); + + set_reg_field_value(v_total_cntl, + 0, + CRTC_V_TOTAL_CONTROL, + CRTC_FORCE_LOCK_ON_EVENT); + set_reg_field_value(v_total_cntl, + 0, + CRTC_V_TOTAL_CONTROL, + CRTC_FORCE_LOCK_TO_MASTER_VSYNC); + + set_reg_field_value(v_total_cntl, + 0, + CRTC_V_TOTAL_CONTROL, + CRTC_SET_V_TOTAL_MIN_MASK_EN); + + set_reg_field_value(v_total_cntl, + 0, + CRTC_V_TOTAL_CONTROL, + CRTC_SET_V_TOTAL_MIN_MASK); + + set_reg_field_value(static_screen_cntl, + 0x180, + CRTC_STATIC_SCREEN_CONTROL, + CRTC_STATIC_SCREEN_EVENT_MASK); + } else { + set_reg_field_value(v_total_cntl, + 0, + CRTC_V_TOTAL_CONTROL, + CRTC_SET_V_TOTAL_MIN_MASK); + set_reg_field_value(static_screen_cntl, + 0, + CRTC_STATIC_SCREEN_CONTROL, + CRTC_STATIC_SCREEN_EVENT_MASK); + set_reg_field_value(v_total_min, + 0, + CRTC_V_TOTAL_MIN, + CRTC_V_TOTAL_MIN); + set_reg_field_value(v_total_max, + 0, + CRTC_V_TOTAL_MAX, + CRTC_V_TOTAL_MAX); + set_reg_field_value(v_total_cntl, + 0, + CRTC_V_TOTAL_CONTROL, + CRTC_V_TOTAL_MIN_SEL); + set_reg_field_value(v_total_cntl, + 0, + CRTC_V_TOTAL_CONTROL, + CRTC_V_TOTAL_MAX_SEL); + set_reg_field_value(v_total_cntl, + 0, + CRTC_V_TOTAL_CONTROL, + CRTC_FORCE_LOCK_ON_EVENT); + set_reg_field_value(v_total_cntl, + 0, + CRTC_V_TOTAL_CONTROL, + CRTC_FORCE_LOCK_TO_MASTER_VSYNC); + } + + addr = CRTC_REG(mmCRTC_V_TOTAL_MIN); + dm_write_reg(tg->ctx, addr, v_total_min); + + addr = CRTC_REG(mmCRTC_V_TOTAL_MAX); + dm_write_reg(tg->ctx, addr, v_total_max); + + addr = CRTC_REG(mmCRTC_V_TOTAL_CONTROL); + dm_write_reg(tg->ctx, addr, v_total_cntl); + + addr = CRTC_REG(mmCRTC_STATIC_SCREEN_CONTROL); + dm_write_reg(tg->ctx, addr, static_screen_cntl); +} + +void dce110_timing_generator_set_static_screen_control( + struct timing_generator *tg, + uint32_t value) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t static_screen_cntl = 0; + uint32_t addr = 0; + + addr = CRTC_REG(mmCRTC_STATIC_SCREEN_CONTROL); + static_screen_cntl = dm_read_reg(tg->ctx, addr); + + set_reg_field_value(static_screen_cntl, + value, + CRTC_STATIC_SCREEN_CONTROL, + CRTC_STATIC_SCREEN_EVENT_MASK); + + set_reg_field_value(static_screen_cntl, + 2, + CRTC_STATIC_SCREEN_CONTROL, + CRTC_STATIC_SCREEN_FRAME_COUNT); + + dm_write_reg(tg->ctx, addr, static_screen_cntl); +} + +/* + * get_vblank_counter + * + * @brief + * Get counter for vertical blanks. use register CRTC_STATUS_FRAME_COUNT which + * holds the counter of frames. + * + * @param + * struct timing_generator *tg - [in] timing generator which controls the + * desired CRTC + * + * @return + * Counter of frames, which should equal to number of vblanks. + */ +uint32_t dce110_timing_generator_get_vblank_counter(struct timing_generator *tg) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t addr = CRTC_REG(mmCRTC_STATUS_FRAME_COUNT); + uint32_t value = dm_read_reg(tg->ctx, addr); + uint32_t field = get_reg_field_value( + value, CRTC_STATUS_FRAME_COUNT, CRTC_FRAME_COUNT); + + return field; +} + +/** + ***************************************************************************** + * Function: dce110_get_crtc_positions + * + * @brief + * Returns CRTC vertical/horizontal counters + * + * @param [out] v_position, h_position + ***************************************************************************** + */ + +void dce110_timing_generator_get_crtc_positions( + struct timing_generator *tg, + int32_t *h_position, + int32_t *v_position) +{ + uint32_t value; + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_STATUS_POSITION)); + + *h_position = get_reg_field_value( + value, + CRTC_STATUS_POSITION, + CRTC_HORZ_COUNT); + + *v_position = get_reg_field_value( + value, + CRTC_STATUS_POSITION, + CRTC_VERT_COUNT); +} + +/** + ***************************************************************************** + * Function: get_crtc_scanoutpos + * + * @brief + * Returns CRTC vertical/horizontal counters + * + * @param [out] vpos, hpos + ***************************************************************************** + */ +uint32_t dce110_timing_generator_get_crtc_scanoutpos( + struct timing_generator *tg, + uint32_t *vbl, + uint32_t *position) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + /* TODO 1: Update the implementation once caller is updated + * WARNING!! This function is returning the whole register value + * because the caller is expecting it instead of proper vertical and + * horizontal position. This should be a temporary implementation + * until the caller is updated. */ + + /* TODO 2: re-use dce110_timing_generator_get_crtc_positions() */ + + *vbl = dm_read_reg(tg->ctx, + CRTC_REG(mmCRTC_V_BLANK_START_END)); + + *position = dm_read_reg(tg->ctx, + CRTC_REG(mmCRTC_STATUS_POSITION)); + + /* @TODO: return value should indicate if current + * crtc is inside vblank*/ + return 0; +} + +/* TODO: is it safe to assume that mask/shift of Primary and Underlay + * are the same? + * For example: today CRTC_H_TOTAL == CRTCV_H_TOTAL but is it always + * guaranteed? */ +void dce110_timing_generator_program_blanking( + struct timing_generator *tg, + const struct dc_crtc_timing *timing) +{ + uint32_t vsync_offset = timing->v_border_bottom + + timing->v_front_porch; + uint32_t v_sync_start =timing->v_addressable + vsync_offset; + + uint32_t hsync_offset = timing->h_border_right + + timing->h_front_porch; + uint32_t h_sync_start = timing->h_addressable + hsync_offset; + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + struct dc_context *ctx = tg->ctx; + uint32_t value = 0; + uint32_t addr = 0; + uint32_t tmp = 0; + + addr = CRTC_REG(mmCRTC_H_TOTAL); + value = dm_read_reg(ctx, addr); + set_reg_field_value( + value, + timing->h_total - 1, + CRTC_H_TOTAL, + CRTC_H_TOTAL); + dm_write_reg(ctx, addr, value); + + addr = CRTC_REG(mmCRTC_V_TOTAL); + value = dm_read_reg(ctx, addr); + set_reg_field_value( + value, + timing->v_total - 1, + CRTC_V_TOTAL, + CRTC_V_TOTAL); + dm_write_reg(ctx, addr, value); + + addr = CRTC_REG(mmCRTC_H_BLANK_START_END); + value = dm_read_reg(ctx, addr); + + tmp = timing->h_total - + (h_sync_start + timing->h_border_left); + + set_reg_field_value( + value, + tmp, + CRTC_H_BLANK_START_END, + CRTC_H_BLANK_END); + + tmp = tmp + timing->h_addressable + + timing->h_border_left + timing->h_border_right; + + set_reg_field_value( + value, + tmp, + CRTC_H_BLANK_START_END, + CRTC_H_BLANK_START); + + dm_write_reg(ctx, addr, value); + + addr = CRTC_REG(mmCRTC_V_BLANK_START_END); + value = dm_read_reg(ctx, addr); + + tmp = timing->v_total - (v_sync_start + timing->v_border_top); + + set_reg_field_value( + value, + tmp, + CRTC_V_BLANK_START_END, + CRTC_V_BLANK_END); + + tmp = tmp + timing->v_addressable + timing->v_border_top + + timing->v_border_bottom; + + set_reg_field_value( + value, + tmp, + CRTC_V_BLANK_START_END, + CRTC_V_BLANK_START); + + dm_write_reg(ctx, addr, value); +} + +void dce110_timing_generator_set_test_pattern( + struct timing_generator *tg, + /* TODO: replace 'controller_dp_test_pattern' by 'test_pattern_mode' + * because this is not DP-specific (which is probably somewhere in DP + * encoder) */ + enum controller_dp_test_pattern test_pattern, + enum dc_color_depth color_depth) +{ + struct dc_context *ctx = tg->ctx; + uint32_t value; + uint32_t addr; + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + enum test_pattern_color_format bit_depth; + enum test_pattern_dyn_range dyn_range; + enum test_pattern_mode mode; + /* color ramp generator mixes 16-bits color */ + uint32_t src_bpc = 16; + /* requested bpc */ + uint32_t dst_bpc; + uint32_t index; + /* RGB values of the color bars. + * Produce two RGB colors: RGB0 - white (all Fs) + * and RGB1 - black (all 0s) + * (three RGB components for two colors) + */ + uint16_t src_color[6] = {0xFFFF, 0xFFFF, 0xFFFF, 0x0000, + 0x0000, 0x0000}; + /* dest color (converted to the specified color format) */ + uint16_t dst_color[6]; + uint32_t inc_base; + + /* translate to bit depth */ + switch (color_depth) { + case COLOR_DEPTH_666: + bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_6; + break; + case COLOR_DEPTH_888: + bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8; + break; + case COLOR_DEPTH_101010: + bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_10; + break; + case COLOR_DEPTH_121212: + bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_12; + break; + default: + bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8; + break; + } + + switch (test_pattern) { + case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES: + case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA: + { + dyn_range = (test_pattern == + CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA ? + TEST_PATTERN_DYN_RANGE_CEA : + TEST_PATTERN_DYN_RANGE_VESA); + mode = TEST_PATTERN_MODE_COLORSQUARES_RGB; + value = 0; + addr = CRTC_REG(mmCRTC_TEST_PATTERN_PARAMETERS); + + set_reg_field_value( + value, + 6, + CRTC_TEST_PATTERN_PARAMETERS, + CRTC_TEST_PATTERN_VRES); + set_reg_field_value( + value, + 6, + CRTC_TEST_PATTERN_PARAMETERS, + CRTC_TEST_PATTERN_HRES); + + dm_write_reg(ctx, addr, value); + + addr = CRTC_REG(mmCRTC_TEST_PATTERN_CONTROL); + value = 0; + + set_reg_field_value( + value, + 1, + CRTC_TEST_PATTERN_CONTROL, + CRTC_TEST_PATTERN_EN); + + set_reg_field_value( + value, + mode, + CRTC_TEST_PATTERN_CONTROL, + CRTC_TEST_PATTERN_MODE); + + set_reg_field_value( + value, + dyn_range, + CRTC_TEST_PATTERN_CONTROL, + CRTC_TEST_PATTERN_DYNAMIC_RANGE); + set_reg_field_value( + value, + bit_depth, + CRTC_TEST_PATTERN_CONTROL, + CRTC_TEST_PATTERN_COLOR_FORMAT); + dm_write_reg(ctx, addr, value); + } + break; + + case CONTROLLER_DP_TEST_PATTERN_VERTICALBARS: + case CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS: + { + mode = (test_pattern == + CONTROLLER_DP_TEST_PATTERN_VERTICALBARS ? + TEST_PATTERN_MODE_VERTICALBARS : + TEST_PATTERN_MODE_HORIZONTALBARS); + + switch (bit_depth) { + case TEST_PATTERN_COLOR_FORMAT_BPC_6: + dst_bpc = 6; + break; + case TEST_PATTERN_COLOR_FORMAT_BPC_8: + dst_bpc = 8; + break; + case TEST_PATTERN_COLOR_FORMAT_BPC_10: + dst_bpc = 10; + break; + default: + dst_bpc = 8; + break; + } + + /* adjust color to the required colorFormat */ + for (index = 0; index < 6; index++) { + /* dst = 2^dstBpc * src / 2^srcBpc = src >> + * (srcBpc - dstBpc); + */ + dst_color[index] = + src_color[index] >> (src_bpc - dst_bpc); + /* CRTC_TEST_PATTERN_DATA has 16 bits, + * lowest 6 are hardwired to ZERO + * color bits should be left aligned aligned to MSB + * XXXXXXXXXX000000 for 10 bit, + * XXXXXXXX00000000 for 8 bit and XXXXXX0000000000 for 6 + */ + dst_color[index] <<= (16 - dst_bpc); + } + + value = 0; + addr = CRTC_REG(mmCRTC_TEST_PATTERN_PARAMETERS); + dm_write_reg(ctx, addr, value); + + /* We have to write the mask before data, similar to pipeline. + * For example, for 8 bpc, if we want RGB0 to be magenta, + * and RGB1 to be cyan, + * we need to make 7 writes: + * MASK DATA + * 000001 00000000 00000000 set mask to R0 + * 000010 11111111 00000000 R0 255, 0xFF00, set mask to G0 + * 000100 00000000 00000000 G0 0, 0x0000, set mask to B0 + * 001000 11111111 00000000 B0 255, 0xFF00, set mask to R1 + * 010000 00000000 00000000 R1 0, 0x0000, set mask to G1 + * 100000 11111111 00000000 G1 255, 0xFF00, set mask to B1 + * 100000 11111111 00000000 B1 255, 0xFF00 + * + * we will make a loop of 6 in which we prepare the mask, + * then write, then prepare the color for next write. + * first iteration will write mask only, + * but each next iteration color prepared in + * previous iteration will be written within new mask, + * the last component will written separately, + * mask is not changing between 6th and 7th write + * and color will be prepared by last iteration + */ + + /* write color, color values mask in CRTC_TEST_PATTERN_MASK + * is B1, G1, R1, B0, G0, R0 + */ + value = 0; + addr = CRTC_REG(mmCRTC_TEST_PATTERN_COLOR); + for (index = 0; index < 6; index++) { + /* prepare color mask, first write PATTERN_DATA + * will have all zeros + */ + set_reg_field_value( + value, + (1 << index), + CRTC_TEST_PATTERN_COLOR, + CRTC_TEST_PATTERN_MASK); + /* write color component */ + dm_write_reg(ctx, addr, value); + /* prepare next color component, + * will be written in the next iteration + */ + set_reg_field_value( + value, + dst_color[index], + CRTC_TEST_PATTERN_COLOR, + CRTC_TEST_PATTERN_DATA); + } + /* write last color component, + * it's been already prepared in the loop + */ + dm_write_reg(ctx, addr, value); + + /* enable test pattern */ + addr = CRTC_REG(mmCRTC_TEST_PATTERN_CONTROL); + value = 0; + + set_reg_field_value( + value, + 1, + CRTC_TEST_PATTERN_CONTROL, + CRTC_TEST_PATTERN_EN); + + set_reg_field_value( + value, + mode, + CRTC_TEST_PATTERN_CONTROL, + CRTC_TEST_PATTERN_MODE); + + set_reg_field_value( + value, + 0, + CRTC_TEST_PATTERN_CONTROL, + CRTC_TEST_PATTERN_DYNAMIC_RANGE); + + set_reg_field_value( + value, + bit_depth, + CRTC_TEST_PATTERN_CONTROL, + CRTC_TEST_PATTERN_COLOR_FORMAT); + + dm_write_reg(ctx, addr, value); + } + break; + + case CONTROLLER_DP_TEST_PATTERN_COLORRAMP: + { + mode = (bit_depth == + TEST_PATTERN_COLOR_FORMAT_BPC_10 ? + TEST_PATTERN_MODE_DUALRAMP_RGB : + TEST_PATTERN_MODE_SINGLERAMP_RGB); + + switch (bit_depth) { + case TEST_PATTERN_COLOR_FORMAT_BPC_6: + dst_bpc = 6; + break; + case TEST_PATTERN_COLOR_FORMAT_BPC_8: + dst_bpc = 8; + break; + case TEST_PATTERN_COLOR_FORMAT_BPC_10: + dst_bpc = 10; + break; + default: + dst_bpc = 8; + break; + } + + /* increment for the first ramp for one color gradation + * 1 gradation for 6-bit color is 2^10 + * gradations in 16-bit color + */ + inc_base = (src_bpc - dst_bpc); + + value = 0; + addr = CRTC_REG(mmCRTC_TEST_PATTERN_PARAMETERS); + + switch (bit_depth) { + case TEST_PATTERN_COLOR_FORMAT_BPC_6: + { + set_reg_field_value( + value, + inc_base, + CRTC_TEST_PATTERN_PARAMETERS, + CRTC_TEST_PATTERN_INC0); + set_reg_field_value( + value, + 0, + CRTC_TEST_PATTERN_PARAMETERS, + CRTC_TEST_PATTERN_INC1); + set_reg_field_value( + value, + 6, + CRTC_TEST_PATTERN_PARAMETERS, + CRTC_TEST_PATTERN_HRES); + set_reg_field_value( + value, + 6, + CRTC_TEST_PATTERN_PARAMETERS, + CRTC_TEST_PATTERN_VRES); + set_reg_field_value( + value, + 0, + CRTC_TEST_PATTERN_PARAMETERS, + CRTC_TEST_PATTERN_RAMP0_OFFSET); + } + break; + case TEST_PATTERN_COLOR_FORMAT_BPC_8: + { + set_reg_field_value( + value, + inc_base, + CRTC_TEST_PATTERN_PARAMETERS, + CRTC_TEST_PATTERN_INC0); + set_reg_field_value( + value, + 0, + CRTC_TEST_PATTERN_PARAMETERS, + CRTC_TEST_PATTERN_INC1); + set_reg_field_value( + value, + 8, + CRTC_TEST_PATTERN_PARAMETERS, + CRTC_TEST_PATTERN_HRES); + set_reg_field_value( + value, + 6, + CRTC_TEST_PATTERN_PARAMETERS, + CRTC_TEST_PATTERN_VRES); + set_reg_field_value( + value, + 0, + CRTC_TEST_PATTERN_PARAMETERS, + CRTC_TEST_PATTERN_RAMP0_OFFSET); + } + break; + case TEST_PATTERN_COLOR_FORMAT_BPC_10: + { + set_reg_field_value( + value, + inc_base, + CRTC_TEST_PATTERN_PARAMETERS, + CRTC_TEST_PATTERN_INC0); + set_reg_field_value( + value, + inc_base + 2, + CRTC_TEST_PATTERN_PARAMETERS, + CRTC_TEST_PATTERN_INC1); + set_reg_field_value( + value, + 8, + CRTC_TEST_PATTERN_PARAMETERS, + CRTC_TEST_PATTERN_HRES); + set_reg_field_value( + value, + 5, + CRTC_TEST_PATTERN_PARAMETERS, + CRTC_TEST_PATTERN_VRES); + set_reg_field_value( + value, + 384 << 6, + CRTC_TEST_PATTERN_PARAMETERS, + CRTC_TEST_PATTERN_RAMP0_OFFSET); + } + break; + default: + break; + } + dm_write_reg(ctx, addr, value); + + value = 0; + addr = CRTC_REG(mmCRTC_TEST_PATTERN_COLOR); + dm_write_reg(ctx, addr, value); + + /* enable test pattern */ + addr = CRTC_REG(mmCRTC_TEST_PATTERN_CONTROL); + value = 0; + + set_reg_field_value( + value, + 1, + CRTC_TEST_PATTERN_CONTROL, + CRTC_TEST_PATTERN_EN); + + set_reg_field_value( + value, + mode, + CRTC_TEST_PATTERN_CONTROL, + CRTC_TEST_PATTERN_MODE); + + set_reg_field_value( + value, + 0, + CRTC_TEST_PATTERN_CONTROL, + CRTC_TEST_PATTERN_DYNAMIC_RANGE); + /* add color depth translation here */ + set_reg_field_value( + value, + bit_depth, + CRTC_TEST_PATTERN_CONTROL, + CRTC_TEST_PATTERN_COLOR_FORMAT); + + dm_write_reg(ctx, addr, value); + } + break; + case CONTROLLER_DP_TEST_PATTERN_VIDEOMODE: + { + value = 0; + dm_write_reg(ctx, CRTC_REG(mmCRTC_TEST_PATTERN_CONTROL), value); + dm_write_reg(ctx, CRTC_REG(mmCRTC_TEST_PATTERN_COLOR), value); + dm_write_reg(ctx, CRTC_REG(mmCRTC_TEST_PATTERN_PARAMETERS), + value); + } + break; + default: + break; + } +} + +/** +* dce110_timing_generator_validate_timing +* The timing generators support a maximum display size of is 8192 x 8192 pixels, +* including both active display and blanking periods. Check H Total and V Total. +*/ +bool dce110_timing_generator_validate_timing( + struct timing_generator *tg, + const struct dc_crtc_timing *timing, + enum signal_type signal) +{ + uint32_t h_blank; + uint32_t h_back_porch; + uint32_t hsync_offset = timing->h_border_right + + timing->h_front_porch; + uint32_t h_sync_start = timing->h_addressable + hsync_offset; + + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + ASSERT(timing != NULL); + + if (!timing) + return false; + + /* Check maximum number of pixels supported by Timing Generator + * (Currently will never fail, in order to fail needs display which + * needs more than 8192 horizontal and + * more than 8192 vertical total pixels) + */ + if (timing->h_total > tg110->max_h_total || + timing->v_total > tg110->max_v_total) + return false; + + h_blank = (timing->h_total - timing->h_addressable - + timing->h_border_right - + timing->h_border_left); + + if (h_blank < tg110->min_h_blank) + return false; + + if (timing->h_front_porch < tg110->min_h_front_porch) + return false; + + h_back_porch = h_blank - (h_sync_start - + timing->h_addressable - + timing->h_border_right - + timing->h_sync_width); + + if (h_back_porch < tg110->min_h_back_porch) + return false; + + return true; +} + +/** +* Wait till we are at the beginning of VBlank. +*/ +void dce110_timing_generator_wait_for_vblank(struct timing_generator *tg) +{ + /* We want to catch beginning of VBlank here, so if the first try are + * in VBlank, we might be very close to Active, in this case wait for + * another frame + */ + while (dce110_timing_generator_is_in_vertical_blank(tg)) { + if (!dce110_timing_generator_is_counter_moving(tg)) { + /* error - no point to wait if counter is not moving */ + break; + } + } + + while (!dce110_timing_generator_is_in_vertical_blank(tg)) { + if (!dce110_timing_generator_is_counter_moving(tg)) { + /* error - no point to wait if counter is not moving */ + break; + } + } +} + +/** +* Wait till we are in VActive (anywhere in VActive) +*/ +void dce110_timing_generator_wait_for_vactive(struct timing_generator *tg) +{ + while (dce110_timing_generator_is_in_vertical_blank(tg)) { + if (!dce110_timing_generator_is_counter_moving(tg)) { + /* error - no point to wait if counter is not moving */ + break; + } + } +} + +/** + ***************************************************************************** + * Function: dce110_timing_generator_setup_global_swap_lock + * + * @brief + * Setups Global Swap Lock group for current pipe + * Pipe can join or leave GSL group, become a TimingServer or TimingClient + * + * @param [in] gsl_params: setup data + ***************************************************************************** + */ + +void dce110_timing_generator_setup_global_swap_lock( + struct timing_generator *tg, + const struct dcp_gsl_params *gsl_params) +{ + uint32_t value; + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t address = DCP_REG(mmDCP_GSL_CONTROL); + uint32_t check_point = FLIP_READY_BACK_LOOKUP; + + value = dm_read_reg(tg->ctx, address); + + /* This pipe will belong to GSL Group zero. */ + set_reg_field_value(value, + 1, + DCP_GSL_CONTROL, + DCP_GSL0_EN); + + set_reg_field_value(value, + gsl_params->gsl_master == tg->inst, + DCP_GSL_CONTROL, + DCP_GSL_MASTER_EN); + + set_reg_field_value(value, + HFLIP_READY_DELAY, + DCP_GSL_CONTROL, + DCP_GSL_HSYNC_FLIP_FORCE_DELAY); + + /* Keep signal low (pending high) during 6 lines. + * Also defines minimum interval before re-checking signal. */ + set_reg_field_value(value, + HFLIP_CHECK_DELAY, + DCP_GSL_CONTROL, + DCP_GSL_HSYNC_FLIP_CHECK_DELAY); + + + { + uint32_t value_crtc_vtotal; + + value_crtc_vtotal = dm_read_reg(tg->ctx, + CRTC_REG(mmCRTC_V_TOTAL)); + + set_reg_field_value(value, + 0,/* DCP_GSL_PURPOSE_SURFACE_FLIP */ + DCP_GSL_CONTROL, + DCP_GSL_SYNC_SOURCE); + + /* Checkpoint relative to end of frame */ + check_point = get_reg_field_value(value_crtc_vtotal, + CRTC_V_TOTAL, + CRTC_V_TOTAL); + + dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_GSL_WINDOW), 0); + } + + set_reg_field_value(value, + 1, + DCP_GSL_CONTROL, + DCP_GSL_DELAY_SURFACE_UPDATE_PENDING); + + dm_write_reg(tg->ctx, address, value); + + /********************************************************************/ + address = CRTC_REG(mmCRTC_GSL_CONTROL); + + value = 0; + set_reg_field_value(value, + check_point - FLIP_READY_BACK_LOOKUP, + CRTC_GSL_CONTROL, + CRTC_GSL_CHECK_LINE_NUM); + + set_reg_field_value(value, + VFLIP_READY_DELAY, + CRTC_GSL_CONTROL, + CRTC_GSL_FORCE_DELAY); + + dm_write_reg(tg->ctx, address, value); +} + +void dce110_timing_generator_tear_down_global_swap_lock( + struct timing_generator *tg) +{ + /* Clear all the register writes done by + * dce110_timing_generator_setup_global_swap_lock + */ + + uint32_t value; + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t address = DCP_REG(mmDCP_GSL_CONTROL); + + value = 0; + + /* This pipe will belong to GSL Group zero. */ + /* Settig HW default values from reg specs */ + set_reg_field_value(value, + 0, + DCP_GSL_CONTROL, + DCP_GSL0_EN); + + set_reg_field_value(value, + 0, + DCP_GSL_CONTROL, + DCP_GSL_MASTER_EN); + + set_reg_field_value(value, + 0x2, + DCP_GSL_CONTROL, + DCP_GSL_HSYNC_FLIP_FORCE_DELAY); + + set_reg_field_value(value, + 0x6, + DCP_GSL_CONTROL, + DCP_GSL_HSYNC_FLIP_CHECK_DELAY); + + /* Restore DCP_GSL_PURPOSE_SURFACE_FLIP */ + { + uint32_t value_crtc_vtotal; + + value_crtc_vtotal = dm_read_reg(tg->ctx, + CRTC_REG(mmCRTC_V_TOTAL)); + + set_reg_field_value(value, + 0, + DCP_GSL_CONTROL, + DCP_GSL_SYNC_SOURCE); + } + + set_reg_field_value(value, + 0, + DCP_GSL_CONTROL, + DCP_GSL_DELAY_SURFACE_UPDATE_PENDING); + + dm_write_reg(tg->ctx, address, value); + + /********************************************************************/ + address = CRTC_REG(mmCRTC_GSL_CONTROL); + + value = 0; + set_reg_field_value(value, + 0, + CRTC_GSL_CONTROL, + CRTC_GSL_CHECK_LINE_NUM); + + set_reg_field_value(value, + 0x2, + CRTC_GSL_CONTROL, + CRTC_GSL_FORCE_DELAY); + + dm_write_reg(tg->ctx, address, value); +} +/** + ***************************************************************************** + * Function: is_counter_moving + * + * @brief + * check if the timing generator is currently going + * + * @return + * true if currently going, false if currently paused or stopped. + * + ***************************************************************************** + */ +bool dce110_timing_generator_is_counter_moving(struct timing_generator *tg) +{ + uint32_t h1 = 0; + uint32_t h2 = 0; + uint32_t v1 = 0; + uint32_t v2 = 0; + + tg->funcs->get_position(tg, &h1, &v1); + tg->funcs->get_position(tg, &h2, &v2); + + if (h1 == h2 && v1 == v2) + return false; + else + return true; +} + +void dce110_timing_generator_enable_advanced_request( + struct timing_generator *tg, + bool enable, + const struct dc_crtc_timing *timing) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t addr = CRTC_REG(mmCRTC_START_LINE_CONTROL); + uint32_t value = dm_read_reg(tg->ctx, addr); + + if (enable) { + set_reg_field_value( + value, + 0, + CRTC_START_LINE_CONTROL, + CRTC_LEGACY_REQUESTOR_EN); + } else { + set_reg_field_value( + value, + 1, + CRTC_START_LINE_CONTROL, + CRTC_LEGACY_REQUESTOR_EN); + } + + if ((timing->v_sync_width + timing->v_front_porch) <= 3) { + set_reg_field_value( + value, + 3, + CRTC_START_LINE_CONTROL, + CRTC_ADVANCED_START_LINE_POSITION); + set_reg_field_value( + value, + 0, + CRTC_START_LINE_CONTROL, + CRTC_PREFETCH_EN); + } else { + set_reg_field_value( + value, + 4, + CRTC_START_LINE_CONTROL, + CRTC_ADVANCED_START_LINE_POSITION); + set_reg_field_value( + value, + 1, + CRTC_START_LINE_CONTROL, + CRTC_PREFETCH_EN); + } + + set_reg_field_value( + value, + 1, + CRTC_START_LINE_CONTROL, + CRTC_PROGRESSIVE_START_LINE_EARLY); + + set_reg_field_value( + value, + 1, + CRTC_START_LINE_CONTROL, + CRTC_INTERLACE_START_LINE_EARLY); + + dm_write_reg(tg->ctx, addr, value); +} + +/*TODO: Figure out if we need this function. */ +void dce110_timing_generator_set_lock_master(struct timing_generator *tg, + bool lock) +{ + struct dc_context *ctx = tg->ctx; + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t addr = CRTC_REG(mmCRTC_MASTER_UPDATE_LOCK); + uint32_t value = dm_read_reg(ctx, addr); + + set_reg_field_value( + value, + lock ? 1 : 0, + CRTC_MASTER_UPDATE_LOCK, + MASTER_UPDATE_LOCK); + + dm_write_reg(ctx, addr, value); +} + +void dce110_timing_generator_enable_reset_trigger( + struct timing_generator *tg, + int source_tg_inst) +{ + uint32_t value; + uint32_t rising_edge = 0; + uint32_t falling_edge = 0; + enum trigger_source_select trig_src_select = TRIGGER_SOURCE_SELECT_LOGIC_ZERO; + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + /* Setup trigger edge */ + { + uint32_t pol_value = dm_read_reg(tg->ctx, + CRTC_REG(mmCRTC_V_SYNC_A_CNTL)); + + /* Register spec has reversed definition: + * 0 for positive, 1 for negative */ + if (get_reg_field_value(pol_value, + CRTC_V_SYNC_A_CNTL, + CRTC_V_SYNC_A_POL) == 0) { + rising_edge = 1; + } else { + falling_edge = 1; + } + } + + value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL)); + + trig_src_select = TRIGGER_SOURCE_SELECT_GSL_GROUP0; + + set_reg_field_value(value, + trig_src_select, + CRTC_TRIGB_CNTL, + CRTC_TRIGB_SOURCE_SELECT); + + set_reg_field_value(value, + TRIGGER_POLARITY_SELECT_LOGIC_ZERO, + CRTC_TRIGB_CNTL, + CRTC_TRIGB_POLARITY_SELECT); + + set_reg_field_value(value, + rising_edge, + CRTC_TRIGB_CNTL, + CRTC_TRIGB_RISING_EDGE_DETECT_CNTL); + + set_reg_field_value(value, + falling_edge, + CRTC_TRIGB_CNTL, + CRTC_TRIGB_FALLING_EDGE_DETECT_CNTL); + + set_reg_field_value(value, + 0, /* send every signal */ + CRTC_TRIGB_CNTL, + CRTC_TRIGB_FREQUENCY_SELECT); + + set_reg_field_value(value, + 0, /* no delay */ + CRTC_TRIGB_CNTL, + CRTC_TRIGB_DELAY); + + set_reg_field_value(value, + 1, /* clear trigger status */ + CRTC_TRIGB_CNTL, + CRTC_TRIGB_CLEAR); + + dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL), value); + + /**************************************************************/ + + value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL)); + + set_reg_field_value(value, + 2, /* force H count to H_TOTAL and V count to V_TOTAL */ + CRTC_FORCE_COUNT_NOW_CNTL, + CRTC_FORCE_COUNT_NOW_MODE); + + set_reg_field_value(value, + 1, /* TriggerB - we never use TriggerA */ + CRTC_FORCE_COUNT_NOW_CNTL, + CRTC_FORCE_COUNT_NOW_TRIG_SEL); + + set_reg_field_value(value, + 1, /* clear trigger status */ + CRTC_FORCE_COUNT_NOW_CNTL, + CRTC_FORCE_COUNT_NOW_CLEAR); + + dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL), value); +} + +void dce110_timing_generator_disable_reset_trigger( + struct timing_generator *tg) +{ + uint32_t value; + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL)); + + set_reg_field_value(value, + 0, /* force counter now mode is disabled */ + CRTC_FORCE_COUNT_NOW_CNTL, + CRTC_FORCE_COUNT_NOW_MODE); + + set_reg_field_value(value, + 1, /* clear trigger status */ + CRTC_FORCE_COUNT_NOW_CNTL, + CRTC_FORCE_COUNT_NOW_CLEAR); + + dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL), value); + + /********************************************************************/ + value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL)); + + set_reg_field_value(value, + TRIGGER_SOURCE_SELECT_LOGIC_ZERO, + CRTC_TRIGB_CNTL, + CRTC_TRIGB_SOURCE_SELECT); + + set_reg_field_value(value, + TRIGGER_POLARITY_SELECT_LOGIC_ZERO, + CRTC_TRIGB_CNTL, + CRTC_TRIGB_POLARITY_SELECT); + + set_reg_field_value(value, + 1, /* clear trigger status */ + CRTC_TRIGB_CNTL, + CRTC_TRIGB_CLEAR); + + dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL), value); +} + +/** + ***************************************************************************** + * @brief + * Checks whether CRTC triggered reset occurred + * + * @return + * true if triggered reset occurred, false otherwise + ***************************************************************************** + */ +bool dce110_timing_generator_did_triggered_reset_occur( + struct timing_generator *tg) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t value = dm_read_reg(tg->ctx, + CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL)); + + return get_reg_field_value(value, + CRTC_FORCE_COUNT_NOW_CNTL, + CRTC_FORCE_COUNT_NOW_OCCURRED) != 0; +} + +/** + * dce110_timing_generator_disable_vga + * Turn OFF VGA Mode and Timing - DxVGA_CONTROL + * VGA Mode and VGA Timing is used by VBIOS on CRT Monitors; + */ +void dce110_timing_generator_disable_vga( + struct timing_generator *tg) +{ + uint32_t addr = 0; + uint32_t value = 0; + + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + switch (tg110->controller_id) { + case CONTROLLER_ID_D0: + addr = mmD1VGA_CONTROL; + break; + case CONTROLLER_ID_D1: + addr = mmD2VGA_CONTROL; + break; + case CONTROLLER_ID_D2: + addr = mmD3VGA_CONTROL; + break; + case CONTROLLER_ID_D3: + addr = mmD4VGA_CONTROL; + break; + case CONTROLLER_ID_D4: + addr = mmD5VGA_CONTROL; + break; + case CONTROLLER_ID_D5: + addr = mmD6VGA_CONTROL; + break; + default: + break; + } + value = dm_read_reg(tg->ctx, addr); + + set_reg_field_value(value, 0, D1VGA_CONTROL, D1VGA_MODE_ENABLE); + set_reg_field_value(value, 0, D1VGA_CONTROL, D1VGA_TIMING_SELECT); + set_reg_field_value( + value, 0, D1VGA_CONTROL, D1VGA_SYNC_POLARITY_SELECT); + set_reg_field_value(value, 0, D1VGA_CONTROL, D1VGA_OVERSCAN_COLOR_EN); + + dm_write_reg(tg->ctx, addr, value); +} + +/** +* set_overscan_color_black +* +* @param :black_color is one of the color space +* :this routine will set overscan black color according to the color space. +* @return none +*/ + +void dce110_timing_generator_set_overscan_color_black( + struct timing_generator *tg, + const struct tg_color *color) +{ + struct dc_context *ctx = tg->ctx; + uint32_t addr; + uint32_t value = 0; + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + set_reg_field_value( + value, + color->color_b_cb, + CRTC_OVERSCAN_COLOR, + CRTC_OVERSCAN_COLOR_BLUE); + + set_reg_field_value( + value, + color->color_r_cr, + CRTC_OVERSCAN_COLOR, + CRTC_OVERSCAN_COLOR_RED); + + set_reg_field_value( + value, + color->color_g_y, + CRTC_OVERSCAN_COLOR, + CRTC_OVERSCAN_COLOR_GREEN); + + addr = CRTC_REG(mmCRTC_OVERSCAN_COLOR); + dm_write_reg(ctx, addr, value); + addr = CRTC_REG(mmCRTC_BLACK_COLOR); + dm_write_reg(ctx, addr, value); + /* This is desirable to have a constant DAC output voltage during the + * blank time that is higher than the 0 volt reference level that the + * DAC outputs when the NBLANK signal + * is asserted low, such as for output to an analog TV. */ + addr = CRTC_REG(mmCRTC_BLANK_DATA_COLOR); + dm_write_reg(ctx, addr, value); + + /* TO DO we have to program EXT registers and we need to know LB DATA + * format because it is used when more 10 , i.e. 12 bits per color + * + * m_mmDxCRTC_OVERSCAN_COLOR_EXT + * m_mmDxCRTC_BLACK_COLOR_EXT + * m_mmDxCRTC_BLANK_DATA_COLOR_EXT + */ + +} + +void dce110_tg_program_blank_color(struct timing_generator *tg, + const struct tg_color *black_color) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t addr = CRTC_REG(mmCRTC_BLACK_COLOR); + uint32_t value = dm_read_reg(tg->ctx, addr); + + set_reg_field_value( + value, + black_color->color_b_cb, + CRTC_BLACK_COLOR, + CRTC_BLACK_COLOR_B_CB); + set_reg_field_value( + value, + black_color->color_g_y, + CRTC_BLACK_COLOR, + CRTC_BLACK_COLOR_G_Y); + set_reg_field_value( + value, + black_color->color_r_cr, + CRTC_BLACK_COLOR, + CRTC_BLACK_COLOR_R_CR); + + dm_write_reg(tg->ctx, addr, value); + + addr = CRTC_REG(mmCRTC_BLANK_DATA_COLOR); + dm_write_reg(tg->ctx, addr, value); +} + +void dce110_tg_set_overscan_color(struct timing_generator *tg, + const struct tg_color *overscan_color) +{ + struct dc_context *ctx = tg->ctx; + uint32_t value = 0; + uint32_t addr; + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + set_reg_field_value( + value, + overscan_color->color_b_cb, + CRTC_OVERSCAN_COLOR, + CRTC_OVERSCAN_COLOR_BLUE); + + set_reg_field_value( + value, + overscan_color->color_g_y, + CRTC_OVERSCAN_COLOR, + CRTC_OVERSCAN_COLOR_GREEN); + + set_reg_field_value( + value, + overscan_color->color_r_cr, + CRTC_OVERSCAN_COLOR, + CRTC_OVERSCAN_COLOR_RED); + + addr = CRTC_REG(mmCRTC_OVERSCAN_COLOR); + dm_write_reg(ctx, addr, value); +} + +void dce110_tg_get_position(struct timing_generator *tg, + struct crtc_position *position) +{ + int32_t h_position; + int32_t v_position; + + dce110_timing_generator_get_crtc_positions(tg, &h_position, &v_position); + + position->horizontal_count = (uint32_t)h_position; + position->vertical_count = (uint32_t)v_position; +} + +void dce110_tg_program_timing(struct timing_generator *tg, + const struct dc_crtc_timing *timing, + bool use_vbios) +{ + if (use_vbios) + dce110_timing_generator_program_timing_generator(tg, timing); + else + dce110_timing_generator_program_blanking(tg, timing); +} + +bool dce110_tg_is_blanked(struct timing_generator *tg) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_BLANK_CONTROL)); + + if (get_reg_field_value( + value, + CRTC_BLANK_CONTROL, + CRTC_BLANK_DATA_EN) == 1 && + get_reg_field_value( + value, + CRTC_BLANK_CONTROL, + CRTC_CURRENT_BLANK_STATE) == 1) + return true; + return false; +} + +bool dce110_tg_set_blank(struct timing_generator *tg, + bool enable_blanking) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t value = 0; + + set_reg_field_value( + value, + 1, + CRTC_DOUBLE_BUFFER_CONTROL, + CRTC_BLANK_DATA_DOUBLE_BUFFER_EN); + + dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_DOUBLE_BUFFER_CONTROL), value); + value = 0; + + if (enable_blanking) { + int counter; + + set_reg_field_value( + value, + 1, + CRTC_BLANK_CONTROL, + CRTC_BLANK_DATA_EN); + + dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_BLANK_CONTROL), value); + + for (counter = 0; counter < 100; counter++) { + value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_BLANK_CONTROL)); + + if (get_reg_field_value( + value, + CRTC_BLANK_CONTROL, + CRTC_BLANK_DATA_EN) == 1 && + get_reg_field_value( + value, + CRTC_BLANK_CONTROL, + CRTC_CURRENT_BLANK_STATE) == 1) + break; + + msleep(1); + } + + if (counter == 100) { + dm_logger_write(tg->ctx->logger, LOG_ERROR, + "timing generator %d blank timing out.\n", + tg110->controller_id); + return false; + } + } else + dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_BLANK_CONTROL), 0); + + return true; +} + +bool dce110_tg_validate_timing(struct timing_generator *tg, + const struct dc_crtc_timing *timing) +{ + return dce110_timing_generator_validate_timing(tg, timing, SIGNAL_TYPE_NONE); +} + +void dce110_tg_wait_for_state(struct timing_generator *tg, + enum crtc_state state) +{ + switch (state) { + case CRTC_STATE_VBLANK: + dce110_timing_generator_wait_for_vblank(tg); + break; + + case CRTC_STATE_VACTIVE: + dce110_timing_generator_wait_for_vactive(tg); + break; + + default: + break; + } +} + +void dce110_tg_set_colors(struct timing_generator *tg, + const struct tg_color *blank_color, + const struct tg_color *overscan_color) +{ + if (blank_color != NULL) + dce110_tg_program_blank_color(tg, blank_color); + if (overscan_color != NULL) + dce110_tg_set_overscan_color(tg, overscan_color); +} + +static const struct timing_generator_funcs dce110_tg_funcs = { + .validate_timing = dce110_tg_validate_timing, + .program_timing = dce110_tg_program_timing, + .enable_crtc = dce110_timing_generator_enable_crtc, + .disable_crtc = dce110_timing_generator_disable_crtc, + .is_counter_moving = dce110_timing_generator_is_counter_moving, + .get_position = dce110_timing_generator_get_crtc_positions, + .get_frame_count = dce110_timing_generator_get_vblank_counter, + .get_scanoutpos = dce110_timing_generator_get_crtc_scanoutpos, + .set_early_control = dce110_timing_generator_set_early_control, + .wait_for_state = dce110_tg_wait_for_state, + .set_blank = dce110_tg_set_blank, + .is_blanked = dce110_tg_is_blanked, + .set_colors = dce110_tg_set_colors, + .set_overscan_blank_color = + dce110_timing_generator_set_overscan_color_black, + .set_blank_color = dce110_timing_generator_program_blank_color, + .disable_vga = dce110_timing_generator_disable_vga, + .did_triggered_reset_occur = + dce110_timing_generator_did_triggered_reset_occur, + .setup_global_swap_lock = + dce110_timing_generator_setup_global_swap_lock, + .enable_reset_trigger = dce110_timing_generator_enable_reset_trigger, + .disable_reset_trigger = dce110_timing_generator_disable_reset_trigger, + .tear_down_global_swap_lock = + dce110_timing_generator_tear_down_global_swap_lock, + .enable_advanced_request = + dce110_timing_generator_enable_advanced_request, + .set_drr = + dce110_timing_generator_set_drr, + .set_static_screen_control = + dce110_timing_generator_set_static_screen_control, + .set_test_pattern = dce110_timing_generator_set_test_pattern + +}; + +bool dce110_timing_generator_construct( + struct dce110_timing_generator *tg110, + struct dc_context *ctx, + uint32_t instance, + const struct dce110_timing_generator_offsets *offsets) +{ + if (!tg110) + return false; + + tg110->controller_id = CONTROLLER_ID_D0 + instance; + tg110->base.inst = instance; + + tg110->offsets = *offsets; + + tg110->base.funcs = &dce110_tg_funcs; + + tg110->base.ctx = ctx; + tg110->base.bp = ctx->dc_bios; + + tg110->max_h_total = CRTC_H_TOTAL__CRTC_H_TOTAL_MASK + 1; + tg110->max_v_total = CRTC_V_TOTAL__CRTC_V_TOTAL_MASK + 1; + + tg110->min_h_blank = 56; + tg110->min_h_front_porch = 4; + tg110->min_h_back_porch = 4; + + return true; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h new file mode 100644 index 000000000000..39906502ad5c --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h @@ -0,0 +1,273 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_TIMING_GENERATOR_DCE110_H__ +#define __DC_TIMING_GENERATOR_DCE110_H__ + +#include "timing_generator.h" +#include "../include/grph_object_id.h" +#include "../include/hw_sequencer_types.h" + +/* GSL Sync related values */ + +/* In VSync mode, after 4 units of time, master pipe will generate + * flip_ready signal */ +#define VFLIP_READY_DELAY 4 +/* In HSync mode, after 2 units of time, master pipe will generate + * flip_ready signal */ +#define HFLIP_READY_DELAY 2 +/* 6 lines delay between forcing flip and checking all pipes ready */ +#define HFLIP_CHECK_DELAY 6 +/* 3 lines before end of frame */ +#define FLIP_READY_BACK_LOOKUP 3 + +/* Trigger Source Select - ASIC-defendant, actual values for the + * register programming */ +enum trigger_source_select { + TRIGGER_SOURCE_SELECT_LOGIC_ZERO = 0, + TRIGGER_SOURCE_SELECT_CRTC_VSYNCA = 1, + TRIGGER_SOURCE_SELECT_CRTC_HSYNCA = 2, + TRIGGER_SOURCE_SELECT_CRTC_VSYNCB = 3, + TRIGGER_SOURCE_SELECT_CRTC_HSYNCB = 4, + TRIGGER_SOURCE_SELECT_GENERICF = 5, + TRIGGER_SOURCE_SELECT_GENERICE = 6, + TRIGGER_SOURCE_SELECT_VSYNCA = 7, + TRIGGER_SOURCE_SELECT_HSYNCA = 8, + TRIGGER_SOURCE_SELECT_VSYNCB = 9, + TRIGGER_SOURCE_SELECT_HSYNCB = 10, + TRIGGER_SOURCE_SELECT_HPD1 = 11, + TRIGGER_SOURCE_SELECT_HPD2 = 12, + TRIGGER_SOURCE_SELECT_GENERICD = 13, + TRIGGER_SOURCE_SELECT_GENERICC = 14, + TRIGGER_SOURCE_SELECT_VIDEO_CAPTURE = 15, + TRIGGER_SOURCE_SELECT_GSL_GROUP0 = 16, + TRIGGER_SOURCE_SELECT_GSL_GROUP1 = 17, + TRIGGER_SOURCE_SELECT_GSL_GROUP2 = 18, + TRIGGER_SOURCE_SELECT_BLONY = 19, + TRIGGER_SOURCE_SELECT_GENERICA = 20, + TRIGGER_SOURCE_SELECT_GENERICB = 21, + TRIGGER_SOURCE_SELECT_GSL_ALLOW_FLIP = 22, + TRIGGER_SOURCE_SELECT_MANUAL_TRIGGER = 23 +}; + +/* Trigger Source Select - ASIC-dependant, actual values for the + * register programming */ +enum trigger_polarity_select { + TRIGGER_POLARITY_SELECT_LOGIC_ZERO = 0, + TRIGGER_POLARITY_SELECT_CRTC = 1, + TRIGGER_POLARITY_SELECT_GENERICA = 2, + TRIGGER_POLARITY_SELECT_GENERICB = 3, + TRIGGER_POLARITY_SELECT_HSYNCA = 4, + TRIGGER_POLARITY_SELECT_HSYNCB = 5, + TRIGGER_POLARITY_SELECT_VIDEO_CAPTURE = 6, + TRIGGER_POLARITY_SELECT_GENERICC = 7 +}; + + +struct dce110_timing_generator_offsets { + int32_t crtc; + int32_t dcp; + + /* DCE80 use only */ + int32_t dmif; +}; + +struct dce110_timing_generator { + struct timing_generator base; + struct dce110_timing_generator_offsets offsets; + struct dce110_timing_generator_offsets derived_offsets; + + enum controller_id controller_id; + + uint32_t max_h_total; + uint32_t max_v_total; + + uint32_t min_h_blank; + uint32_t min_h_front_porch; + uint32_t min_h_back_porch; + + uint32_t min_h_sync_width; + uint32_t min_v_sync_width; + uint32_t min_v_blank; + +}; + +#define DCE110TG_FROM_TG(tg)\ + container_of(tg, struct dce110_timing_generator, base) + +bool dce110_timing_generator_construct( + struct dce110_timing_generator *tg, + struct dc_context *ctx, + uint32_t instance, + const struct dce110_timing_generator_offsets *offsets); + +/* determine if given timing can be supported by TG */ +bool dce110_timing_generator_validate_timing( + struct timing_generator *tg, + const struct dc_crtc_timing *timing, + enum signal_type signal); + +/******** HW programming ************/ + +/* Program timing generator with given timing */ +bool dce110_timing_generator_program_timing_generator( + struct timing_generator *tg, + const struct dc_crtc_timing *dc_crtc_timing); + +/* Disable/Enable Timing Generator */ +bool dce110_timing_generator_enable_crtc(struct timing_generator *tg); +bool dce110_timing_generator_disable_crtc(struct timing_generator *tg); + +void dce110_timing_generator_set_early_control( + struct timing_generator *tg, + uint32_t early_cntl); + +/**************** TG current status ******************/ + +/* return the current frame counter. Used by Linux kernel DRM */ +uint32_t dce110_timing_generator_get_vblank_counter( + struct timing_generator *tg); + +/* Get current H and V position */ +void dce110_timing_generator_get_crtc_positions( + struct timing_generator *tg, + int32_t *h_position, + int32_t *v_position); + +/* return true if TG counter is moving. false if TG is stopped */ +bool dce110_timing_generator_is_counter_moving(struct timing_generator *tg); + +/* wait until TG is in beginning of vertical blank region */ +void dce110_timing_generator_wait_for_vblank(struct timing_generator *tg); + +/* wait until TG is in beginning of active region */ +void dce110_timing_generator_wait_for_vactive(struct timing_generator *tg); + +/*********** Timing Generator Synchronization routines ****/ + +/* Setups Global Swap Lock group, TimingServer or TimingClient*/ +void dce110_timing_generator_setup_global_swap_lock( + struct timing_generator *tg, + const struct dcp_gsl_params *gsl_params); + +/* Clear all the register writes done by setup_global_swap_lock */ +void dce110_timing_generator_tear_down_global_swap_lock( + struct timing_generator *tg); + +/* Reset slave controllers on master VSync */ +void dce110_timing_generator_enable_reset_trigger( + struct timing_generator *tg, + int source); + +/* disabling trigger-reset */ +void dce110_timing_generator_disable_reset_trigger( + struct timing_generator *tg); + +/* Checks whether CRTC triggered reset occurred */ +bool dce110_timing_generator_did_triggered_reset_occur( + struct timing_generator *tg); + +/******** Stuff to move to other virtual HW objects *****************/ +/* Move to enable accelerated mode */ +void dce110_timing_generator_disable_vga(struct timing_generator *tg); +/* TODO: Should we move it to transform */ +/* Fully program CRTC timing in timing generator */ +void dce110_timing_generator_program_blanking( + struct timing_generator *tg, + const struct dc_crtc_timing *timing); + +/* TODO: Should we move it to opp? */ +/* Combine with below and move YUV/RGB color conversion to SW layer */ +void dce110_timing_generator_program_blank_color( + struct timing_generator *tg, + const struct tg_color *black_color); +/* Combine with above and move YUV/RGB color conversion to SW layer */ +void dce110_timing_generator_set_overscan_color_black( + struct timing_generator *tg, + const struct tg_color *color); +void dce110_timing_generator_color_space_to_black_color( + enum dc_color_space colorspace, + struct tg_color *black_color); +/*************** End-of-move ********************/ + +/* Not called yet */ +void dce110_timing_generator_set_test_pattern( + struct timing_generator *tg, + /* TODO: replace 'controller_dp_test_pattern' by 'test_pattern_mode' + * because this is not DP-specific (which is probably somewhere in DP + * encoder) */ + enum controller_dp_test_pattern test_pattern, + enum dc_color_depth color_depth); + +void dce110_timing_generator_set_drr( + struct timing_generator *tg, + const struct drr_params *params); + +void dce110_timing_generator_set_static_screen_control( + struct timing_generator *tg, + uint32_t value); + +uint32_t dce110_timing_generator_get_crtc_scanoutpos( + struct timing_generator *tg, + uint32_t *vbl, + uint32_t *position); + +void dce110_timing_generator_enable_advanced_request( + struct timing_generator *tg, + bool enable, + const struct dc_crtc_timing *timing); + +void dce110_timing_generator_set_lock_master(struct timing_generator *tg, + bool lock); + +void dce110_tg_program_blank_color(struct timing_generator *tg, + const struct tg_color *black_color); + +void dce110_tg_set_overscan_color(struct timing_generator *tg, + const struct tg_color *overscan_color); + +void dce110_tg_get_position(struct timing_generator *tg, + struct crtc_position *position); + +void dce110_tg_program_timing(struct timing_generator *tg, + const struct dc_crtc_timing *timing, + bool use_vbios); + +bool dce110_tg_is_blanked(struct timing_generator *tg); + +bool dce110_tg_set_blank(struct timing_generator *tg, + bool enable_blanking); + +bool dce110_tg_validate_timing(struct timing_generator *tg, + const struct dc_crtc_timing *timing); + +void dce110_tg_wait_for_state(struct timing_generator *tg, + enum crtc_state state); + +void dce110_tg_set_colors(struct timing_generator *tg, + const struct tg_color *blank_color, + const struct tg_color *overscan_color); + +#endif /* __DC_TIMING_GENERATOR_DCE110_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c new file mode 100644 index 000000000000..3bf3179e07c5 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c @@ -0,0 +1,743 @@ +#include "dm_services.h" + +/* include DCE11 register header files */ +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" + +#include "dc_types.h" +#include "dc_bios_types.h" +#include "dc.h" + +#include "include/grph_object_id.h" +#include "include/logger_interface.h" +#include "dce110_timing_generator.h" +#include "dce110_timing_generator_v.h" + +#include "timing_generator.h" + +/** ******************************************************************************** + * + * DCE11 Timing Generator Implementation + * + **********************************************************************************/ + +/** +* Enable CRTCV +*/ + +static bool dce110_timing_generator_v_enable_crtc(struct timing_generator *tg) +{ +/* +* Set MASTER_UPDATE_MODE to 0 +* This is needed for DRR, and also suggested to be default value by Syed. +*/ + + uint32_t value; + + value = 0; + set_reg_field_value(value, 0, + CRTCV_MASTER_UPDATE_MODE, MASTER_UPDATE_MODE); + dm_write_reg(tg->ctx, + mmCRTCV_MASTER_UPDATE_MODE, value); + + /* TODO: may want this on for looking for underflow */ + value = 0; + dm_write_reg(tg->ctx, mmCRTCV_MASTER_UPDATE_MODE, value); + + value = 0; + set_reg_field_value(value, 1, + CRTCV_MASTER_EN, CRTC_MASTER_EN); + dm_write_reg(tg->ctx, + mmCRTCV_MASTER_EN, value); + + return true; +} + +static bool dce110_timing_generator_v_disable_crtc(struct timing_generator *tg) +{ + uint32_t value; + + value = dm_read_reg(tg->ctx, + mmCRTCV_CONTROL); + set_reg_field_value(value, 0, + CRTCV_CONTROL, CRTC_DISABLE_POINT_CNTL); + set_reg_field_value(value, 0, + CRTCV_CONTROL, CRTC_MASTER_EN); + dm_write_reg(tg->ctx, + mmCRTCV_CONTROL, value); + /* + * TODO: call this when adding stereo support + * tg->funcs->disable_stereo(tg); + */ + return true; +} + +static bool dce110_timing_generator_v_blank_crtc(struct timing_generator *tg) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t addr = mmCRTCV_BLANK_CONTROL; + uint32_t value = dm_read_reg(tg->ctx, addr); + uint8_t counter = 100; + + set_reg_field_value( + value, + 1, + CRTCV_BLANK_CONTROL, + CRTC_BLANK_DATA_EN); + + set_reg_field_value( + value, + 0, + CRTCV_BLANK_CONTROL, + CRTC_BLANK_DE_MODE); + + dm_write_reg(tg->ctx, addr, value); + + while (counter > 0) { + value = dm_read_reg(tg->ctx, addr); + + if (get_reg_field_value( + value, + CRTCV_BLANK_CONTROL, + CRTC_BLANK_DATA_EN) == 1 && + get_reg_field_value( + value, + CRTCV_BLANK_CONTROL, + CRTC_CURRENT_BLANK_STATE) == 1) + break; + + msleep(1); + counter--; + } + + if (!counter) { + dm_logger_write(tg->ctx->logger, LOG_ERROR, + "timing generator %d blank timing out.\n", + tg110->controller_id); + return false; + } + + return true; +} + +static bool dce110_timing_generator_v_unblank_crtc(struct timing_generator *tg) +{ + uint32_t addr = mmCRTCV_BLANK_CONTROL; + uint32_t value = dm_read_reg(tg->ctx, addr); + + set_reg_field_value( + value, + 0, + CRTCV_BLANK_CONTROL, + CRTC_BLANK_DATA_EN); + + set_reg_field_value( + value, + 0, + CRTCV_BLANK_CONTROL, + CRTC_BLANK_DE_MODE); + + dm_write_reg(tg->ctx, addr, value); + + return true; +} + +static bool dce110_timing_generator_v_is_in_vertical_blank( + struct timing_generator *tg) +{ + uint32_t addr = 0; + uint32_t value = 0; + uint32_t field = 0; + + addr = mmCRTCV_STATUS; + value = dm_read_reg(tg->ctx, addr); + field = get_reg_field_value(value, CRTCV_STATUS, CRTC_V_BLANK); + return field == 1; +} + +static bool dce110_timing_generator_v_is_counter_moving(struct timing_generator *tg) +{ + uint32_t value; + uint32_t h1 = 0; + uint32_t h2 = 0; + uint32_t v1 = 0; + uint32_t v2 = 0; + + value = dm_read_reg(tg->ctx, mmCRTCV_STATUS_POSITION); + + h1 = get_reg_field_value( + value, + CRTCV_STATUS_POSITION, + CRTC_HORZ_COUNT); + + v1 = get_reg_field_value( + value, + CRTCV_STATUS_POSITION, + CRTC_VERT_COUNT); + + value = dm_read_reg(tg->ctx, mmCRTCV_STATUS_POSITION); + + h2 = get_reg_field_value( + value, + CRTCV_STATUS_POSITION, + CRTC_HORZ_COUNT); + + v2 = get_reg_field_value( + value, + CRTCV_STATUS_POSITION, + CRTC_VERT_COUNT); + + if (h1 == h2 && v1 == v2) + return false; + else + return true; +} + +static void dce110_timing_generator_v_wait_for_vblank(struct timing_generator *tg) +{ + /* We want to catch beginning of VBlank here, so if the first try are + * in VBlank, we might be very close to Active, in this case wait for + * another frame + */ + while (dce110_timing_generator_v_is_in_vertical_blank(tg)) { + if (!dce110_timing_generator_v_is_counter_moving(tg)) { + /* error - no point to wait if counter is not moving */ + break; + } + } + + while (!dce110_timing_generator_v_is_in_vertical_blank(tg)) { + if (!dce110_timing_generator_v_is_counter_moving(tg)) { + /* error - no point to wait if counter is not moving */ + break; + } + } +} + +/** +* Wait till we are in VActive (anywhere in VActive) +*/ +static void dce110_timing_generator_v_wait_for_vactive(struct timing_generator *tg) +{ + while (dce110_timing_generator_v_is_in_vertical_blank(tg)) { + if (!dce110_timing_generator_v_is_counter_moving(tg)) { + /* error - no point to wait if counter is not moving */ + break; + } + } +} + +static void dce110_timing_generator_v_wait_for_state(struct timing_generator *tg, + enum crtc_state state) +{ + switch (state) { + case CRTC_STATE_VBLANK: + dce110_timing_generator_v_wait_for_vblank(tg); + break; + + case CRTC_STATE_VACTIVE: + dce110_timing_generator_v_wait_for_vactive(tg); + break; + + default: + break; + } +} + +static void dce110_timing_generator_v_program_blanking( + struct timing_generator *tg, + const struct dc_crtc_timing *timing) +{ + uint32_t vsync_offset = timing->v_border_bottom + + timing->v_front_porch; + uint32_t v_sync_start = timing->v_addressable + vsync_offset; + + uint32_t hsync_offset = timing->h_border_right + + timing->h_front_porch; + uint32_t h_sync_start = timing->h_addressable + hsync_offset; + + struct dc_context *ctx = tg->ctx; + uint32_t value = 0; + uint32_t addr = 0; + uint32_t tmp = 0; + + addr = mmCRTCV_H_TOTAL; + value = dm_read_reg(ctx, addr); + set_reg_field_value( + value, + timing->h_total - 1, + CRTCV_H_TOTAL, + CRTC_H_TOTAL); + dm_write_reg(ctx, addr, value); + + addr = mmCRTCV_V_TOTAL; + value = dm_read_reg(ctx, addr); + set_reg_field_value( + value, + timing->v_total - 1, + CRTCV_V_TOTAL, + CRTC_V_TOTAL); + dm_write_reg(ctx, addr, value); + + addr = mmCRTCV_H_BLANK_START_END; + value = dm_read_reg(ctx, addr); + + tmp = timing->h_total - + (h_sync_start + timing->h_border_left); + + set_reg_field_value( + value, + tmp, + CRTCV_H_BLANK_START_END, + CRTC_H_BLANK_END); + + tmp = tmp + timing->h_addressable + + timing->h_border_left + timing->h_border_right; + + set_reg_field_value( + value, + tmp, + CRTCV_H_BLANK_START_END, + CRTC_H_BLANK_START); + + dm_write_reg(ctx, addr, value); + + addr = mmCRTCV_V_BLANK_START_END; + value = dm_read_reg(ctx, addr); + + tmp = timing->v_total - (v_sync_start + timing->v_border_top); + + set_reg_field_value( + value, + tmp, + CRTCV_V_BLANK_START_END, + CRTC_V_BLANK_END); + + tmp = tmp + timing->v_addressable + timing->v_border_top + + timing->v_border_bottom; + + set_reg_field_value( + value, + tmp, + CRTCV_V_BLANK_START_END, + CRTC_V_BLANK_START); + + dm_write_reg(ctx, addr, value); + + addr = mmCRTCV_H_SYNC_A; + value = 0; + set_reg_field_value( + value, + timing->h_sync_width, + CRTCV_H_SYNC_A, + CRTC_H_SYNC_A_END); + dm_write_reg(ctx, addr, value); + + addr = mmCRTCV_H_SYNC_A_CNTL; + value = dm_read_reg(ctx, addr); + if (timing->flags.HSYNC_POSITIVE_POLARITY) { + set_reg_field_value( + value, + 0, + CRTCV_H_SYNC_A_CNTL, + CRTC_H_SYNC_A_POL); + } else { + set_reg_field_value( + value, + 1, + CRTCV_H_SYNC_A_CNTL, + CRTC_H_SYNC_A_POL); + } + dm_write_reg(ctx, addr, value); + + addr = mmCRTCV_V_SYNC_A; + value = 0; + set_reg_field_value( + value, + timing->v_sync_width, + CRTCV_V_SYNC_A, + CRTC_V_SYNC_A_END); + dm_write_reg(ctx, addr, value); + + addr = mmCRTCV_V_SYNC_A_CNTL; + value = dm_read_reg(ctx, addr); + if (timing->flags.VSYNC_POSITIVE_POLARITY) { + set_reg_field_value( + value, + 0, + CRTCV_V_SYNC_A_CNTL, + CRTC_V_SYNC_A_POL); + } else { + set_reg_field_value( + value, + 1, + CRTCV_V_SYNC_A_CNTL, + CRTC_V_SYNC_A_POL); + } + dm_write_reg(ctx, addr, value); + + addr = mmCRTCV_INTERLACE_CONTROL; + value = dm_read_reg(ctx, addr); + set_reg_field_value( + value, + timing->flags.INTERLACE, + CRTCV_INTERLACE_CONTROL, + CRTC_INTERLACE_ENABLE); + dm_write_reg(ctx, addr, value); +} + +static void dce110_timing_generator_v_enable_advanced_request( + struct timing_generator *tg, + bool enable, + const struct dc_crtc_timing *timing) +{ + uint32_t addr = mmCRTCV_START_LINE_CONTROL; + uint32_t value = dm_read_reg(tg->ctx, addr); + + if (enable) { + if ((timing->v_sync_width + timing->v_front_porch) <= 3) { + set_reg_field_value( + value, + 3, + CRTCV_START_LINE_CONTROL, + CRTC_ADVANCED_START_LINE_POSITION); + } else { + set_reg_field_value( + value, + 4, + CRTCV_START_LINE_CONTROL, + CRTC_ADVANCED_START_LINE_POSITION); + } + set_reg_field_value( + value, + 0, + CRTCV_START_LINE_CONTROL, + CRTC_LEGACY_REQUESTOR_EN); + } else { + set_reg_field_value( + value, + 2, + CRTCV_START_LINE_CONTROL, + CRTC_ADVANCED_START_LINE_POSITION); + set_reg_field_value( + value, + 1, + CRTCV_START_LINE_CONTROL, + CRTC_LEGACY_REQUESTOR_EN); + } + + dm_write_reg(tg->ctx, addr, value); +} + +static bool dce110_timing_generator_v_set_blank(struct timing_generator *tg, + bool enable_blanking) +{ + if (enable_blanking) + return dce110_timing_generator_v_blank_crtc(tg); + else + return dce110_timing_generator_v_unblank_crtc(tg); +} + +static void dce110_timing_generator_v_program_timing(struct timing_generator *tg, + const struct dc_crtc_timing *timing, + bool use_vbios) +{ + if (use_vbios) + dce110_timing_generator_program_timing_generator(tg, timing); + else + dce110_timing_generator_v_program_blanking(tg, timing); +} + +static void dce110_timing_generator_v_program_blank_color( + struct timing_generator *tg, + const struct tg_color *black_color) +{ + uint32_t addr = mmCRTCV_BLACK_COLOR; + uint32_t value = dm_read_reg(tg->ctx, addr); + + set_reg_field_value( + value, + black_color->color_b_cb, + CRTCV_BLACK_COLOR, + CRTC_BLACK_COLOR_B_CB); + set_reg_field_value( + value, + black_color->color_g_y, + CRTCV_BLACK_COLOR, + CRTC_BLACK_COLOR_G_Y); + set_reg_field_value( + value, + black_color->color_r_cr, + CRTCV_BLACK_COLOR, + CRTC_BLACK_COLOR_R_CR); + + dm_write_reg(tg->ctx, addr, value); +} + +static void dce110_timing_generator_v_set_overscan_color_black( + struct timing_generator *tg, + const struct tg_color *color) +{ + struct dc_context *ctx = tg->ctx; + uint32_t addr; + uint32_t value = 0; + + set_reg_field_value( + value, + color->color_b_cb, + CRTC_OVERSCAN_COLOR, + CRTC_OVERSCAN_COLOR_BLUE); + + set_reg_field_value( + value, + color->color_r_cr, + CRTC_OVERSCAN_COLOR, + CRTC_OVERSCAN_COLOR_RED); + + set_reg_field_value( + value, + color->color_g_y, + CRTC_OVERSCAN_COLOR, + CRTC_OVERSCAN_COLOR_GREEN); + + addr = mmCRTCV_OVERSCAN_COLOR; + dm_write_reg(ctx, addr, value); + addr = mmCRTCV_BLACK_COLOR; + dm_write_reg(ctx, addr, value); + /* This is desirable to have a constant DAC output voltage during the + * blank time that is higher than the 0 volt reference level that the + * DAC outputs when the NBLANK signal + * is asserted low, such as for output to an analog TV. */ + addr = mmCRTCV_BLANK_DATA_COLOR; + dm_write_reg(ctx, addr, value); + + /* TO DO we have to program EXT registers and we need to know LB DATA + * format because it is used when more 10 , i.e. 12 bits per color + * + * m_mmDxCRTC_OVERSCAN_COLOR_EXT + * m_mmDxCRTC_BLACK_COLOR_EXT + * m_mmDxCRTC_BLANK_DATA_COLOR_EXT + */ +} + +static void dce110_tg_v_program_blank_color(struct timing_generator *tg, + const struct tg_color *black_color) +{ + uint32_t addr = mmCRTCV_BLACK_COLOR; + uint32_t value = dm_read_reg(tg->ctx, addr); + + set_reg_field_value( + value, + black_color->color_b_cb, + CRTCV_BLACK_COLOR, + CRTC_BLACK_COLOR_B_CB); + set_reg_field_value( + value, + black_color->color_g_y, + CRTCV_BLACK_COLOR, + CRTC_BLACK_COLOR_G_Y); + set_reg_field_value( + value, + black_color->color_r_cr, + CRTCV_BLACK_COLOR, + CRTC_BLACK_COLOR_R_CR); + + dm_write_reg(tg->ctx, addr, value); + + addr = mmCRTCV_BLANK_DATA_COLOR; + dm_write_reg(tg->ctx, addr, value); +} + +static void dce110_timing_generator_v_set_overscan_color(struct timing_generator *tg, + const struct tg_color *overscan_color) +{ + struct dc_context *ctx = tg->ctx; + uint32_t value = 0; + uint32_t addr; + + set_reg_field_value( + value, + overscan_color->color_b_cb, + CRTCV_OVERSCAN_COLOR, + CRTC_OVERSCAN_COLOR_BLUE); + + set_reg_field_value( + value, + overscan_color->color_g_y, + CRTCV_OVERSCAN_COLOR, + CRTC_OVERSCAN_COLOR_GREEN); + + set_reg_field_value( + value, + overscan_color->color_r_cr, + CRTCV_OVERSCAN_COLOR, + CRTC_OVERSCAN_COLOR_RED); + + addr = mmCRTCV_OVERSCAN_COLOR; + dm_write_reg(ctx, addr, value); +} + +static void dce110_timing_generator_v_set_colors(struct timing_generator *tg, + const struct tg_color *blank_color, + const struct tg_color *overscan_color) +{ + if (blank_color != NULL) + dce110_tg_v_program_blank_color(tg, blank_color); + if (overscan_color != NULL) + dce110_timing_generator_v_set_overscan_color(tg, overscan_color); +} + +static void dce110_timing_generator_v_set_early_control( + struct timing_generator *tg, + uint32_t early_cntl) +{ + uint32_t regval; + uint32_t address = mmCRTC_CONTROL; + + regval = dm_read_reg(tg->ctx, address); + set_reg_field_value(regval, early_cntl, + CRTCV_CONTROL, CRTC_HBLANK_EARLY_CONTROL); + dm_write_reg(tg->ctx, address, regval); +} + +static void dce110_timing_generator_v_get_crtc_positions( + struct timing_generator *tg, + int32_t *h_position, + int32_t *v_position) +{ + uint32_t value; + + value = dm_read_reg(tg->ctx, mmCRTCV_STATUS_POSITION); + + *h_position = get_reg_field_value( + value, + CRTCV_STATUS_POSITION, + CRTC_HORZ_COUNT); + + *v_position = get_reg_field_value( + value, + CRTCV_STATUS_POSITION, + CRTC_VERT_COUNT); +} + +static uint32_t dce110_timing_generator_v_get_vblank_counter(struct timing_generator *tg) +{ + uint32_t addr = mmCRTCV_STATUS_FRAME_COUNT; + uint32_t value = dm_read_reg(tg->ctx, addr); + uint32_t field = get_reg_field_value( + value, CRTCV_STATUS_FRAME_COUNT, CRTC_FRAME_COUNT); + + return field; +} + +static bool dce110_timing_generator_v_did_triggered_reset_occur( + struct timing_generator *tg) +{ + dm_logger_write(tg->ctx->logger, LOG_ERROR, + "Timing Sync not supported on underlay pipe\n"); + return false; +} + +static void dce110_timing_generator_v_setup_global_swap_lock( + struct timing_generator *tg, + const struct dcp_gsl_params *gsl_params) +{ + dm_logger_write(tg->ctx->logger, LOG_ERROR, + "Timing Sync not supported on underlay pipe\n"); + return; +} + +static void dce110_timing_generator_v_enable_reset_trigger( + struct timing_generator *tg, + int source_tg_inst) +{ + dm_logger_write(tg->ctx->logger, LOG_ERROR, + "Timing Sync not supported on underlay pipe\n"); + return; +} + +static void dce110_timing_generator_v_disable_reset_trigger( + struct timing_generator *tg) +{ + dm_logger_write(tg->ctx->logger, LOG_ERROR, + "Timing Sync not supported on underlay pipe\n"); + return; +} + +static void dce110_timing_generator_v_tear_down_global_swap_lock( + struct timing_generator *tg) +{ + dm_logger_write(tg->ctx->logger, LOG_ERROR, + "Timing Sync not supported on underlay pipe\n"); + return; +} + +static void dce110_timing_generator_v_disable_vga( + struct timing_generator *tg) +{ + return; +} + +static bool dce110_tg_v_is_blanked(struct timing_generator *tg) +{ + /* Signal comes from the primary pipe, underlay is never blanked. */ + return false; +} + +/** ******************************************************************************************** + * + * DCE11 Timing Generator Constructor / Destructor + * + *********************************************************************************************/ +static const struct timing_generator_funcs dce110_tg_v_funcs = { + .validate_timing = dce110_tg_validate_timing, + .program_timing = dce110_timing_generator_v_program_timing, + .enable_crtc = dce110_timing_generator_v_enable_crtc, + .disable_crtc = dce110_timing_generator_v_disable_crtc, + .is_counter_moving = dce110_timing_generator_v_is_counter_moving, + .get_position = dce110_timing_generator_v_get_crtc_positions, + .get_frame_count = dce110_timing_generator_v_get_vblank_counter, + .set_early_control = dce110_timing_generator_v_set_early_control, + .wait_for_state = dce110_timing_generator_v_wait_for_state, + .set_blank = dce110_timing_generator_v_set_blank, + .is_blanked = dce110_tg_v_is_blanked, + .set_colors = dce110_timing_generator_v_set_colors, + .set_overscan_blank_color = + dce110_timing_generator_v_set_overscan_color_black, + .set_blank_color = dce110_timing_generator_v_program_blank_color, + .disable_vga = dce110_timing_generator_v_disable_vga, + .did_triggered_reset_occur = + dce110_timing_generator_v_did_triggered_reset_occur, + .setup_global_swap_lock = + dce110_timing_generator_v_setup_global_swap_lock, + .enable_reset_trigger = dce110_timing_generator_v_enable_reset_trigger, + .disable_reset_trigger = dce110_timing_generator_v_disable_reset_trigger, + .tear_down_global_swap_lock = + dce110_timing_generator_v_tear_down_global_swap_lock, + .enable_advanced_request = + dce110_timing_generator_v_enable_advanced_request +}; + +bool dce110_timing_generator_v_construct( + struct dce110_timing_generator *tg110, + struct dc_context *ctx) +{ + if (!tg110) + return false; + + tg110->controller_id = CONTROLLER_ID_UNDERLAY0; + + tg110->base.funcs = &dce110_tg_v_funcs; + + tg110->base.ctx = ctx; + tg110->base.bp = ctx->dc_bios; + + tg110->max_h_total = CRTC_H_TOTAL__CRTC_H_TOTAL_MASK + 1; + tg110->max_v_total = CRTC_V_TOTAL__CRTC_V_TOTAL_MASK + 1; + + tg110->min_h_blank = 56; + tg110->min_h_front_porch = 4; + tg110->min_h_back_porch = 4; + + return true; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.h new file mode 100644 index 000000000000..7e49ca8e26ad --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.h @@ -0,0 +1,33 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_TIMING_GENERATOR_V_DCE110_H__ +#define __DC_TIMING_GENERATOR_V_DCE110_H__ + +bool dce110_timing_generator_v_construct( + struct dce110_timing_generator *tg110, + struct dc_context *ctx); + +#endif /* __DC_TIMING_GENERATOR_V_DCE110_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c new file mode 100644 index 000000000000..7d8cf7a58f46 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c @@ -0,0 +1,704 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dce110_transform_v.h" +#include "dm_services.h" +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" + +#define SCLV_PHASES 64 + +struct sclv_ratios_inits { + uint32_t h_int_scale_ratio_luma; + uint32_t h_int_scale_ratio_chroma; + uint32_t v_int_scale_ratio_luma; + uint32_t v_int_scale_ratio_chroma; + struct init_int_and_frac h_init_luma; + struct init_int_and_frac h_init_chroma; + struct init_int_and_frac v_init_luma; + struct init_int_and_frac v_init_chroma; +}; + +static void calculate_viewport( + const struct scaler_data *scl_data, + struct rect *luma_viewport, + struct rect *chroma_viewport) +{ + /*Do not set chroma vp for rgb444 pixel format*/ + luma_viewport->x = scl_data->viewport.x - scl_data->viewport.x % 2; + luma_viewport->y = scl_data->viewport.y - scl_data->viewport.y % 2; + luma_viewport->width = + scl_data->viewport.width - scl_data->viewport.width % 2; + luma_viewport->height = + scl_data->viewport.height - scl_data->viewport.height % 2; + chroma_viewport->x = luma_viewport->x; + chroma_viewport->y = luma_viewport->y; + chroma_viewport->height = luma_viewport->height; + chroma_viewport->width = luma_viewport->width; + + if (scl_data->format == PIXEL_FORMAT_420BPP12) { + luma_viewport->height += luma_viewport->height % 2; + luma_viewport->width += luma_viewport->width % 2; + /*for 420 video chroma is 1/4 the area of luma, scaled + *vertically and horizontally + */ + chroma_viewport->x = luma_viewport->x / 2; + chroma_viewport->y = luma_viewport->y / 2; + chroma_viewport->height = luma_viewport->height / 2; + chroma_viewport->width = luma_viewport->width / 2; + } +} + +static void program_viewport( + struct dce_transform *xfm_dce, + struct rect *luma_view_port, + struct rect *chroma_view_port) +{ + struct dc_context *ctx = xfm_dce->base.ctx; + uint32_t value = 0; + uint32_t addr = 0; + + if (luma_view_port->width != 0 && luma_view_port->height != 0) { + addr = mmSCLV_VIEWPORT_START; + value = 0; + set_reg_field_value( + value, + luma_view_port->x, + SCLV_VIEWPORT_START, + VIEWPORT_X_START); + set_reg_field_value( + value, + luma_view_port->y, + SCLV_VIEWPORT_START, + VIEWPORT_Y_START); + dm_write_reg(ctx, addr, value); + + addr = mmSCLV_VIEWPORT_SIZE; + value = 0; + set_reg_field_value( + value, + luma_view_port->height, + SCLV_VIEWPORT_SIZE, + VIEWPORT_HEIGHT); + set_reg_field_value( + value, + luma_view_port->width, + SCLV_VIEWPORT_SIZE, + VIEWPORT_WIDTH); + dm_write_reg(ctx, addr, value); + } + + if (chroma_view_port->width != 0 && chroma_view_port->height != 0) { + addr = mmSCLV_VIEWPORT_START_C; + value = 0; + set_reg_field_value( + value, + chroma_view_port->x, + SCLV_VIEWPORT_START_C, + VIEWPORT_X_START_C); + set_reg_field_value( + value, + chroma_view_port->y, + SCLV_VIEWPORT_START_C, + VIEWPORT_Y_START_C); + dm_write_reg(ctx, addr, value); + + addr = mmSCLV_VIEWPORT_SIZE_C; + value = 0; + set_reg_field_value( + value, + chroma_view_port->height, + SCLV_VIEWPORT_SIZE_C, + VIEWPORT_HEIGHT_C); + set_reg_field_value( + value, + chroma_view_port->width, + SCLV_VIEWPORT_SIZE_C, + VIEWPORT_WIDTH_C); + dm_write_reg(ctx, addr, value); + } +} + +/* + * Function: + * void setup_scaling_configuration + * + * Purpose: setup scaling mode : bypass, RGb, YCbCr and nummber of taps + * Input: data + * + * Output: + * void + */ +static bool setup_scaling_configuration( + struct dce_transform *xfm_dce, + const struct scaler_data *data) +{ + bool is_scaling_needed = false; + struct dc_context *ctx = xfm_dce->base.ctx; + uint32_t value = 0; + + set_reg_field_value(value, data->taps.h_taps - 1, + SCLV_TAP_CONTROL, SCL_H_NUM_OF_TAPS); + set_reg_field_value(value, data->taps.v_taps - 1, + SCLV_TAP_CONTROL, SCL_V_NUM_OF_TAPS); + set_reg_field_value(value, data->taps.h_taps_c - 1, + SCLV_TAP_CONTROL, SCL_H_NUM_OF_TAPS_C); + set_reg_field_value(value, data->taps.v_taps_c - 1, + SCLV_TAP_CONTROL, SCL_V_NUM_OF_TAPS_C); + dm_write_reg(ctx, mmSCLV_TAP_CONTROL, value); + + value = 0; + if (data->taps.h_taps + data->taps.v_taps > 2) { + set_reg_field_value(value, 1, SCLV_MODE, SCL_MODE); + set_reg_field_value(value, 1, SCLV_MODE, SCL_PSCL_EN); + is_scaling_needed = true; + } else { + set_reg_field_value(value, 0, SCLV_MODE, SCL_MODE); + set_reg_field_value(value, 0, SCLV_MODE, SCL_PSCL_EN); + } + + if (data->taps.h_taps_c + data->taps.v_taps_c > 2) { + set_reg_field_value(value, 1, SCLV_MODE, SCL_MODE_C); + set_reg_field_value(value, 1, SCLV_MODE, SCL_PSCL_EN_C); + is_scaling_needed = true; + } else if (data->format != PIXEL_FORMAT_420BPP12) { + set_reg_field_value( + value, + get_reg_field_value(value, SCLV_MODE, SCL_MODE), + SCLV_MODE, + SCL_MODE_C); + set_reg_field_value( + value, + get_reg_field_value(value, SCLV_MODE, SCL_PSCL_EN), + SCLV_MODE, + SCL_PSCL_EN_C); + } else { + set_reg_field_value(value, 0, SCLV_MODE, SCL_MODE_C); + set_reg_field_value(value, 0, SCLV_MODE, SCL_PSCL_EN_C); + } + dm_write_reg(ctx, mmSCLV_MODE, value); + + value = 0; + /* + * 0 - Replaced out of bound pixels with black pixel + * (or any other required color) + * 1 - Replaced out of bound pixels with the edge pixel + */ + set_reg_field_value(value, 1, SCLV_CONTROL, SCL_BOUNDARY_MODE); + dm_write_reg(ctx, mmSCLV_CONTROL, value); + + return is_scaling_needed; +} + +/** +* Function: +* void program_overscan +* +* Purpose: Programs overscan border +* Input: overscan +* +* Output: + void +*/ +static void program_overscan( + struct dce_transform *xfm_dce, + const struct scaler_data *data) +{ + uint32_t overscan_left_right = 0; + uint32_t overscan_top_bottom = 0; + + int overscan_right = data->h_active - data->recout.x - data->recout.width; + int overscan_bottom = data->v_active - data->recout.y - data->recout.height; + + if (overscan_right < 0) { + BREAK_TO_DEBUGGER(); + overscan_right = 0; + } + if (overscan_bottom < 0) { + BREAK_TO_DEBUGGER(); + overscan_bottom = 0; + } + + set_reg_field_value(overscan_left_right, data->recout.x, + EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_LEFT); + + set_reg_field_value(overscan_left_right, overscan_right, + EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_RIGHT); + + set_reg_field_value(overscan_top_bottom, data->recout.y, + EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_TOP); + + set_reg_field_value(overscan_top_bottom, overscan_bottom, + EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_BOTTOM); + + dm_write_reg(xfm_dce->base.ctx, + mmSCLV_EXT_OVERSCAN_LEFT_RIGHT, + overscan_left_right); + + dm_write_reg(xfm_dce->base.ctx, + mmSCLV_EXT_OVERSCAN_TOP_BOTTOM, + overscan_top_bottom); +} + +static void set_coeff_update_complete( + struct dce_transform *xfm_dce) +{ + uint32_t value; + + value = dm_read_reg(xfm_dce->base.ctx, mmSCLV_UPDATE); + set_reg_field_value(value, 1, SCLV_UPDATE, SCL_COEF_UPDATE_COMPLETE); + dm_write_reg(xfm_dce->base.ctx, mmSCLV_UPDATE, value); +} + +static void program_multi_taps_filter( + struct dce_transform *xfm_dce, + int taps, + const uint16_t *coeffs, + enum ram_filter_type filter_type) +{ + struct dc_context *ctx = xfm_dce->base.ctx; + int i, phase, pair; + int array_idx = 0; + int taps_pairs = (taps + 1) / 2; + int phases_to_program = SCLV_PHASES / 2 + 1; + + uint32_t select = 0; + uint32_t power_ctl, power_ctl_off; + + if (!coeffs) + return; + + /*We need to disable power gating on coeff memory to do programming*/ + power_ctl = dm_read_reg(ctx, mmDCFEV_MEM_PWR_CTRL); + power_ctl_off = power_ctl; + set_reg_field_value(power_ctl_off, 1, DCFEV_MEM_PWR_CTRL, SCLV_COEFF_MEM_PWR_DIS); + dm_write_reg(ctx, mmDCFEV_MEM_PWR_CTRL, power_ctl_off); + + /*Wait to disable gating:*/ + for (i = 0; i < 10; i++) { + if (get_reg_field_value( + dm_read_reg(ctx, mmDCFEV_MEM_PWR_STATUS), + DCFEV_MEM_PWR_STATUS, + SCLV_COEFF_MEM_PWR_STATE) == 0) + break; + + udelay(1); + } + + set_reg_field_value(select, filter_type, SCLV_COEF_RAM_SELECT, SCL_C_RAM_FILTER_TYPE); + + for (phase = 0; phase < phases_to_program; phase++) { + /*we always program N/2 + 1 phases, total phases N, but N/2-1 are just mirror + phase 0 is unique and phase N/2 is unique if N is even*/ + set_reg_field_value(select, phase, SCLV_COEF_RAM_SELECT, SCL_C_RAM_PHASE); + for (pair = 0; pair < taps_pairs; pair++) { + uint32_t data = 0; + + set_reg_field_value(select, pair, + SCLV_COEF_RAM_SELECT, SCL_C_RAM_TAP_PAIR_IDX); + + dm_write_reg(ctx, mmSCLV_COEF_RAM_SELECT, select); + + set_reg_field_value( + data, 1, + SCLV_COEF_RAM_TAP_DATA, + SCL_C_RAM_EVEN_TAP_COEF_EN); + set_reg_field_value( + data, coeffs[array_idx], + SCLV_COEF_RAM_TAP_DATA, + SCL_C_RAM_EVEN_TAP_COEF); + + if (taps % 2 && pair == taps_pairs - 1) { + set_reg_field_value( + data, 0, + SCLV_COEF_RAM_TAP_DATA, + SCL_C_RAM_ODD_TAP_COEF_EN); + array_idx++; + } else { + set_reg_field_value( + data, 1, + SCLV_COEF_RAM_TAP_DATA, + SCL_C_RAM_ODD_TAP_COEF_EN); + set_reg_field_value( + data, coeffs[array_idx + 1], + SCLV_COEF_RAM_TAP_DATA, + SCL_C_RAM_ODD_TAP_COEF); + + array_idx += 2; + } + + dm_write_reg(ctx, mmSCLV_COEF_RAM_TAP_DATA, data); + } + } + + /*We need to restore power gating on coeff memory to initial state*/ + dm_write_reg(ctx, mmDCFEV_MEM_PWR_CTRL, power_ctl); +} + +static void calculate_inits( + struct dce_transform *xfm_dce, + const struct scaler_data *data, + struct sclv_ratios_inits *inits, + struct rect *luma_viewport, + struct rect *chroma_viewport) +{ + inits->h_int_scale_ratio_luma = + dal_fixed31_32_u2d19(data->ratios.horz) << 5; + inits->v_int_scale_ratio_luma = + dal_fixed31_32_u2d19(data->ratios.vert) << 5; + inits->h_int_scale_ratio_chroma = + dal_fixed31_32_u2d19(data->ratios.horz_c) << 5; + inits->v_int_scale_ratio_chroma = + dal_fixed31_32_u2d19(data->ratios.vert_c) << 5; + + inits->h_init_luma.integer = 1; + inits->v_init_luma.integer = 1; + inits->h_init_chroma.integer = 1; + inits->v_init_chroma.integer = 1; +} + +static void program_scl_ratios_inits( + struct dce_transform *xfm_dce, + struct sclv_ratios_inits *inits) +{ + struct dc_context *ctx = xfm_dce->base.ctx; + uint32_t addr = mmSCLV_HORZ_FILTER_SCALE_RATIO; + uint32_t value = 0; + + set_reg_field_value( + value, + inits->h_int_scale_ratio_luma, + SCLV_HORZ_FILTER_SCALE_RATIO, + SCL_H_SCALE_RATIO); + dm_write_reg(ctx, addr, value); + + addr = mmSCLV_VERT_FILTER_SCALE_RATIO; + value = 0; + set_reg_field_value( + value, + inits->v_int_scale_ratio_luma, + SCLV_VERT_FILTER_SCALE_RATIO, + SCL_V_SCALE_RATIO); + dm_write_reg(ctx, addr, value); + + addr = mmSCLV_HORZ_FILTER_SCALE_RATIO_C; + value = 0; + set_reg_field_value( + value, + inits->h_int_scale_ratio_chroma, + SCLV_HORZ_FILTER_SCALE_RATIO_C, + SCL_H_SCALE_RATIO_C); + dm_write_reg(ctx, addr, value); + + addr = mmSCLV_VERT_FILTER_SCALE_RATIO_C; + value = 0; + set_reg_field_value( + value, + inits->v_int_scale_ratio_chroma, + SCLV_VERT_FILTER_SCALE_RATIO_C, + SCL_V_SCALE_RATIO_C); + dm_write_reg(ctx, addr, value); + + addr = mmSCLV_HORZ_FILTER_INIT; + value = 0; + set_reg_field_value( + value, + inits->h_init_luma.fraction, + SCLV_HORZ_FILTER_INIT, + SCL_H_INIT_FRAC); + set_reg_field_value( + value, + inits->h_init_luma.integer, + SCLV_HORZ_FILTER_INIT, + SCL_H_INIT_INT); + dm_write_reg(ctx, addr, value); + + addr = mmSCLV_VERT_FILTER_INIT; + value = 0; + set_reg_field_value( + value, + inits->v_init_luma.fraction, + SCLV_VERT_FILTER_INIT, + SCL_V_INIT_FRAC); + set_reg_field_value( + value, + inits->v_init_luma.integer, + SCLV_VERT_FILTER_INIT, + SCL_V_INIT_INT); + dm_write_reg(ctx, addr, value); + + addr = mmSCLV_HORZ_FILTER_INIT_C; + value = 0; + set_reg_field_value( + value, + inits->h_init_chroma.fraction, + SCLV_HORZ_FILTER_INIT_C, + SCL_H_INIT_FRAC_C); + set_reg_field_value( + value, + inits->h_init_chroma.integer, + SCLV_HORZ_FILTER_INIT_C, + SCL_H_INIT_INT_C); + dm_write_reg(ctx, addr, value); + + addr = mmSCLV_VERT_FILTER_INIT_C; + value = 0; + set_reg_field_value( + value, + inits->v_init_chroma.fraction, + SCLV_VERT_FILTER_INIT_C, + SCL_V_INIT_FRAC_C); + set_reg_field_value( + value, + inits->v_init_chroma.integer, + SCLV_VERT_FILTER_INIT_C, + SCL_V_INIT_INT_C); + dm_write_reg(ctx, addr, value); +} + +static const uint16_t *get_filter_coeffs_64p(int taps, struct fixed31_32 ratio) +{ + if (taps == 4) + return get_filter_4tap_64p(ratio); + else if (taps == 2) + return filter_2tap_64p; + else if (taps == 1) + return NULL; + else { + /* should never happen, bug */ + BREAK_TO_DEBUGGER(); + return NULL; + } +} + +static bool dce110_xfmv_power_up_line_buffer(struct transform *xfm) +{ + struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); + uint32_t value; + + value = dm_read_reg(xfm_dce->base.ctx, mmLBV_MEMORY_CTRL); + + /*Use all three pieces of memory always*/ + set_reg_field_value(value, 0, LBV_MEMORY_CTRL, LB_MEMORY_CONFIG); + /*hard coded number DCE11 1712(0x6B0) Partitions: 720/960/1712*/ + set_reg_field_value(value, xfm_dce->lb_memory_size, LBV_MEMORY_CTRL, + LB_MEMORY_SIZE); + + dm_write_reg(xfm_dce->base.ctx, mmLBV_MEMORY_CTRL, value); + + return true; +} + +static void dce110_xfmv_set_scaler( + struct transform *xfm, + const struct scaler_data *data) +{ + struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); + bool is_scaling_required = false; + bool filter_updated = false; + const uint16_t *coeffs_v, *coeffs_h, *coeffs_h_c, *coeffs_v_c; + struct rect luma_viewport = {0}; + struct rect chroma_viewport = {0}; + + dce110_xfmv_power_up_line_buffer(xfm); + /* 1. Calculate viewport, viewport programming should happen after init + * calculations as they may require an adjustment in the viewport. + */ + + calculate_viewport(data, &luma_viewport, &chroma_viewport); + + /* 2. Program overscan */ + program_overscan(xfm_dce, data); + + /* 3. Program taps and configuration */ + is_scaling_required = setup_scaling_configuration(xfm_dce, data); + + if (is_scaling_required) { + /* 4. Calculate and program ratio, filter initialization */ + + struct sclv_ratios_inits inits = { 0 }; + + calculate_inits( + xfm_dce, + data, + &inits, + &luma_viewport, + &chroma_viewport); + + program_scl_ratios_inits(xfm_dce, &inits); + + coeffs_v = get_filter_coeffs_64p(data->taps.v_taps, data->ratios.vert); + coeffs_h = get_filter_coeffs_64p(data->taps.h_taps, data->ratios.horz); + coeffs_v_c = get_filter_coeffs_64p(data->taps.v_taps_c, data->ratios.vert_c); + coeffs_h_c = get_filter_coeffs_64p(data->taps.h_taps_c, data->ratios.horz_c); + + if (coeffs_v != xfm_dce->filter_v + || coeffs_v_c != xfm_dce->filter_v_c + || coeffs_h != xfm_dce->filter_h + || coeffs_h_c != xfm_dce->filter_h_c) { + /* 5. Program vertical filters */ + program_multi_taps_filter( + xfm_dce, + data->taps.v_taps, + coeffs_v, + FILTER_TYPE_RGB_Y_VERTICAL); + program_multi_taps_filter( + xfm_dce, + data->taps.v_taps_c, + coeffs_v_c, + FILTER_TYPE_CBCR_VERTICAL); + + /* 6. Program horizontal filters */ + program_multi_taps_filter( + xfm_dce, + data->taps.h_taps, + coeffs_h, + FILTER_TYPE_RGB_Y_HORIZONTAL); + program_multi_taps_filter( + xfm_dce, + data->taps.h_taps_c, + coeffs_h_c, + FILTER_TYPE_CBCR_HORIZONTAL); + + xfm_dce->filter_v = coeffs_v; + xfm_dce->filter_v_c = coeffs_v_c; + xfm_dce->filter_h = coeffs_h; + xfm_dce->filter_h_c = coeffs_h_c; + filter_updated = true; + } + } + + /* 7. Program the viewport */ + program_viewport(xfm_dce, &luma_viewport, &chroma_viewport); + + /* 8. Set bit to flip to new coefficient memory */ + if (filter_updated) + set_coeff_update_complete(xfm_dce); +} + +static void dce110_xfmv_reset(struct transform *xfm) +{ + struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); + + xfm_dce->filter_h = NULL; + xfm_dce->filter_v = NULL; + xfm_dce->filter_h_c = NULL; + xfm_dce->filter_v_c = NULL; +} + +static void dce110_xfmv_set_gamut_remap( + struct transform *xfm, + const struct xfm_grph_csc_adjustment *adjust) +{ + /* DO NOTHING*/ +} + +static void dce110_xfmv_set_pixel_storage_depth( + struct transform *xfm, + enum lb_pixel_depth depth, + const struct bit_depth_reduction_params *bit_depth_params) +{ + struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); + int pixel_depth, expan_mode; + uint32_t reg_data = 0; + + switch (depth) { + case LB_PIXEL_DEPTH_18BPP: + pixel_depth = 2; + expan_mode = 1; + break; + case LB_PIXEL_DEPTH_24BPP: + pixel_depth = 1; + expan_mode = 1; + break; + case LB_PIXEL_DEPTH_30BPP: + pixel_depth = 0; + expan_mode = 1; + break; + case LB_PIXEL_DEPTH_36BPP: + pixel_depth = 3; + expan_mode = 0; + break; + default: + BREAK_TO_DEBUGGER(); + break; + } + + set_reg_field_value( + reg_data, + expan_mode, + LBV_DATA_FORMAT, + PIXEL_EXPAN_MODE); + + set_reg_field_value( + reg_data, + pixel_depth, + LBV_DATA_FORMAT, + PIXEL_DEPTH); + + dm_write_reg(xfm->ctx, mmLBV_DATA_FORMAT, reg_data); + + if (!(xfm_dce->lb_pixel_depth_supported & depth)) { + /*we should use unsupported capabilities + * unless it is required by w/a*/ + dm_logger_write(xfm->ctx->logger, LOG_WARNING, + "%s: Capability not supported", + __func__); + } +} + +static const struct transform_funcs dce110_xfmv_funcs = { + .transform_reset = dce110_xfmv_reset, + .transform_set_scaler = dce110_xfmv_set_scaler, + .transform_set_gamut_remap = + dce110_xfmv_set_gamut_remap, + .transform_set_pixel_storage_depth = + dce110_xfmv_set_pixel_storage_depth, + .transform_get_optimal_number_of_taps = + dce_transform_get_optimal_number_of_taps +}; +/*****************************************/ +/* Constructor, Destructor */ +/*****************************************/ + +bool dce110_transform_v_construct( + struct dce_transform *xfm_dce, + struct dc_context *ctx) +{ + xfm_dce->base.ctx = ctx; + + xfm_dce->base.funcs = &dce110_xfmv_funcs; + + xfm_dce->lb_pixel_depth_supported = + LB_PIXEL_DEPTH_18BPP | + LB_PIXEL_DEPTH_24BPP | + LB_PIXEL_DEPTH_30BPP; + + xfm_dce->prescaler_on = true; + xfm_dce->lb_bits_per_entry = LB_BITS_PER_ENTRY; + xfm_dce->lb_memory_size = LB_TOTAL_NUMBER_OF_ENTRIES; /*0x6B0*/ + + return true; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.h new file mode 100644 index 000000000000..267af34db3e5 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.h @@ -0,0 +1,37 @@ +/* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_TRANSFORM_V_DCE110_H__ +#define __DAL_TRANSFORM_V_DCE110_H__ + +#include "../dce/dce_transform.h" + +#define LB_TOTAL_NUMBER_OF_ENTRIES 1712 +#define LB_BITS_PER_ENTRY 144 + +bool dce110_transform_v_construct( + struct dce_transform *xfm110, + struct dc_context *ctx); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_types.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_types.h new file mode 100644 index 000000000000..55f52382ddfb --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_types.h @@ -0,0 +1,30 @@ +/* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef _DCE110_TYPES_H_ +#define __DCE110_TYPES_H_ + +#define GAMMA_SEGMENTS_NUM 16 + +#endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_DCE110_DCE110_TYPES_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce112/Makefile b/drivers/gpu/drm/amd/display/dc/dce112/Makefile new file mode 100644 index 000000000000..34fba0730bed --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce112/Makefile @@ -0,0 +1,11 @@ +# +# Makefile for the 'controller' sub-component of DAL. +# It provides the control and status of HW CRTC block. + +DCE112 = dce112_compressor.o dce112_hw_sequencer.o \ +dce112_resource.o dce112_mem_input.o dce112_opp_formatter.o \ +dce112_opp.o + +AMD_DAL_DCE112 = $(addprefix $(AMDDALPATH)/dc/dce112/,$(DCE112)) + +AMD_DISPLAY_FILES += $(AMD_DAL_DCE112) diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c new file mode 100644 index 000000000000..22a5aba073ca --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c @@ -0,0 +1,859 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "dce/dce_11_2_d.h" +#include "dce/dce_11_2_sh_mask.h" +#include "gmc/gmc_8_1_sh_mask.h" +#include "gmc/gmc_8_1_d.h" + +#include "include/logger_interface.h" + +#include "dce112_compressor.h" + +#define DCP_REG(reg)\ + (reg + cp110->offsets.dcp_offset) +#define DMIF_REG(reg)\ + (reg + cp110->offsets.dmif_offset) + +static const struct dce112_compressor_reg_offsets reg_offsets[] = { +{ + .dcp_offset = (mmDCP0_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), + .dmif_offset = + (mmDMIF_PG0_DPG_PIPE_DPM_CONTROL + - mmDMIF_PG0_DPG_PIPE_DPM_CONTROL), +}, +{ + .dcp_offset = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), + .dmif_offset = + (mmDMIF_PG1_DPG_PIPE_DPM_CONTROL + - mmDMIF_PG0_DPG_PIPE_DPM_CONTROL), +}, +{ + .dcp_offset = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), + .dmif_offset = + (mmDMIF_PG2_DPG_PIPE_DPM_CONTROL + - mmDMIF_PG0_DPG_PIPE_DPM_CONTROL), +} +}; + +static const uint32_t dce11_one_lpt_channel_max_resolution = 2560 * 1600; + +enum fbc_idle_force { + /* Bit 0 - Display registers updated */ + FBC_IDLE_FORCE_DISPLAY_REGISTER_UPDATE = 0x00000001, + + /* Bit 2 - FBC_GRPH_COMP_EN register updated */ + FBC_IDLE_FORCE_GRPH_COMP_EN = 0x00000002, + /* Bit 3 - FBC_SRC_SEL register updated */ + FBC_IDLE_FORCE_SRC_SEL_CHANGE = 0x00000004, + /* Bit 4 - FBC_MIN_COMPRESSION register updated */ + FBC_IDLE_FORCE_MIN_COMPRESSION_CHANGE = 0x00000008, + /* Bit 5 - FBC_ALPHA_COMP_EN register updated */ + FBC_IDLE_FORCE_ALPHA_COMP_EN = 0x00000010, + /* Bit 6 - FBC_ZERO_ALPHA_CHUNK_SKIP_EN register updated */ + FBC_IDLE_FORCE_ZERO_ALPHA_CHUNK_SKIP_EN = 0x00000020, + /* Bit 7 - FBC_FORCE_COPY_TO_COMP_BUF register updated */ + FBC_IDLE_FORCE_FORCE_COPY_TO_COMP_BUF = 0x00000040, + + /* Bit 24 - Memory write to region 0 defined by MC registers. */ + FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION0 = 0x01000000, + /* Bit 25 - Memory write to region 1 defined by MC registers */ + FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION1 = 0x02000000, + /* Bit 26 - Memory write to region 2 defined by MC registers */ + FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION2 = 0x04000000, + /* Bit 27 - Memory write to region 3 defined by MC registers. */ + FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION3 = 0x08000000, + + /* Bit 28 - Memory write from any client other than MCIF */ + FBC_IDLE_FORCE_MEMORY_WRITE_OTHER_THAN_MCIF = 0x10000000, + /* Bit 29 - CG statics screen signal is inactive */ + FBC_IDLE_FORCE_CG_STATIC_SCREEN_IS_INACTIVE = 0x20000000, +}; + +static uint32_t lpt_size_alignment(struct dce112_compressor *cp110) +{ + /*LPT_ALIGNMENT (in bytes) = ROW_SIZE * #BANKS * # DRAM CHANNELS. */ + return cp110->base.raw_size * cp110->base.banks_num * + cp110->base.dram_channels_num; +} + +static uint32_t lpt_memory_control_config(struct dce112_compressor *cp110, + uint32_t lpt_control) +{ + /*LPT MC Config */ + if (cp110->base.options.bits.LPT_MC_CONFIG == 1) { + /* POSSIBLE VALUES for LPT NUM_PIPES (DRAM CHANNELS): + * 00 - 1 CHANNEL + * 01 - 2 CHANNELS + * 02 - 4 OR 6 CHANNELS + * (Only for discrete GPU, N/A for CZ) + * 03 - 8 OR 12 CHANNELS + * (Only for discrete GPU, N/A for CZ) */ + switch (cp110->base.dram_channels_num) { + case 2: + set_reg_field_value( + lpt_control, + 1, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_NUM_PIPES); + break; + case 1: + set_reg_field_value( + lpt_control, + 0, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_NUM_PIPES); + break; + default: + dm_logger_write( + cp110->base.ctx->logger, LOG_WARNING, + "%s: Invalid LPT NUM_PIPES!!!", + __func__); + break; + } + + /* The mapping for LPT NUM_BANKS is in + * GRPH_CONTROL.GRPH_NUM_BANKS register field + * Specifies the number of memory banks for tiling + * purposes. Only applies to 2D and 3D tiling modes. + * POSSIBLE VALUES: + * 00 - DCP_GRPH_NUM_BANKS_2BANK: ADDR_SURF_2_BANK + * 01 - DCP_GRPH_NUM_BANKS_4BANK: ADDR_SURF_4_BANK + * 02 - DCP_GRPH_NUM_BANKS_8BANK: ADDR_SURF_8_BANK + * 03 - DCP_GRPH_NUM_BANKS_16BANK: ADDR_SURF_16_BANK */ + switch (cp110->base.banks_num) { + case 16: + set_reg_field_value( + lpt_control, + 3, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_NUM_BANKS); + break; + case 8: + set_reg_field_value( + lpt_control, + 2, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_NUM_BANKS); + break; + case 4: + set_reg_field_value( + lpt_control, + 1, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_NUM_BANKS); + break; + case 2: + set_reg_field_value( + lpt_control, + 0, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_NUM_BANKS); + break; + default: + dm_logger_write( + cp110->base.ctx->logger, LOG_WARNING, + "%s: Invalid LPT NUM_BANKS!!!", + __func__); + break; + } + + /* The mapping is in DMIF_ADDR_CALC. + * ADDR_CONFIG_PIPE_INTERLEAVE_SIZE register field for + * Carrizo specifies the memory interleave per pipe. + * It effectively specifies the location of pipe bits in + * the memory address. + * POSSIBLE VALUES: + * 00 - ADDR_CONFIG_PIPE_INTERLEAVE_256B: 256 byte + * interleave + * 01 - ADDR_CONFIG_PIPE_INTERLEAVE_512B: 512 byte + * interleave + */ + switch (cp110->base.channel_interleave_size) { + case 256: /*256B */ + set_reg_field_value( + lpt_control, + 0, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_PIPE_INTERLEAVE_SIZE); + break; + case 512: /*512B */ + set_reg_field_value( + lpt_control, + 1, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_PIPE_INTERLEAVE_SIZE); + break; + default: + dm_logger_write( + cp110->base.ctx->logger, LOG_WARNING, + "%s: Invalid LPT INTERLEAVE_SIZE!!!", + __func__); + break; + } + + /* The mapping for LOW_POWER_TILING_ROW_SIZE is in + * DMIF_ADDR_CALC.ADDR_CONFIG_ROW_SIZE register field + * for Carrizo. Specifies the size of dram row in bytes. + * This should match up with NOOFCOLS field in + * MC_ARB_RAMCFG (ROW_SIZE = 4 * 2 ^^ columns). + * This register DMIF_ADDR_CALC is not used by the + * hardware as it is only used for addrlib assertions. + * POSSIBLE VALUES: + * 00 - ADDR_CONFIG_1KB_ROW: Treat 1KB as DRAM row + * boundary + * 01 - ADDR_CONFIG_2KB_ROW: Treat 2KB as DRAM row + * boundary + * 02 - ADDR_CONFIG_4KB_ROW: Treat 4KB as DRAM row + * boundary */ + switch (cp110->base.raw_size) { + case 4096: /*4 KB */ + set_reg_field_value( + lpt_control, + 2, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_ROW_SIZE); + break; + case 2048: + set_reg_field_value( + lpt_control, + 1, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_ROW_SIZE); + break; + case 1024: + set_reg_field_value( + lpt_control, + 0, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_ROW_SIZE); + break; + default: + dm_logger_write( + cp110->base.ctx->logger, LOG_WARNING, + "%s: Invalid LPT ROW_SIZE!!!", + __func__); + break; + } + } else { + dm_logger_write( + cp110->base.ctx->logger, LOG_WARNING, + "%s: LPT MC Configuration is not provided", + __func__); + } + + return lpt_control; +} + +static bool is_source_bigger_than_epanel_size( + struct dce112_compressor *cp110, + uint32_t source_view_width, + uint32_t source_view_height) +{ + if (cp110->base.embedded_panel_h_size != 0 && + cp110->base.embedded_panel_v_size != 0 && + ((source_view_width * source_view_height) > + (cp110->base.embedded_panel_h_size * + cp110->base.embedded_panel_v_size))) + return true; + + return false; +} + +static uint32_t align_to_chunks_number_per_line( + struct dce112_compressor *cp110, + uint32_t pixels) +{ + return 256 * ((pixels + 255) / 256); +} + +static void wait_for_fbc_state_changed( + struct dce112_compressor *cp110, + bool enabled) +{ + uint8_t counter = 0; + uint32_t addr = mmFBC_STATUS; + uint32_t value; + + while (counter < 10) { + value = dm_read_reg(cp110->base.ctx, addr); + if (get_reg_field_value( + value, + FBC_STATUS, + FBC_ENABLE_STATUS) == enabled) + break; + udelay(10); + counter++; + } + + if (counter == 10) { + dm_logger_write( + cp110->base.ctx->logger, LOG_WARNING, + "%s: wait counter exceeded, changes to HW not applied", + __func__); + } +} + +void dce112_compressor_power_up_fbc(struct compressor *compressor) +{ + uint32_t value; + uint32_t addr; + + addr = mmFBC_CNTL; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value(value, 0, FBC_CNTL, FBC_GRPH_COMP_EN); + set_reg_field_value(value, 1, FBC_CNTL, FBC_EN); + set_reg_field_value(value, 2, FBC_CNTL, FBC_COHERENCY_MODE); + if (compressor->options.bits.CLK_GATING_DISABLED == 1) { + /* HW needs to do power measurement comparison. */ + set_reg_field_value( + value, + 0, + FBC_CNTL, + FBC_COMP_CLK_GATE_EN); + } + dm_write_reg(compressor->ctx, addr, value); + + addr = mmFBC_COMP_MODE; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value(value, 1, FBC_COMP_MODE, FBC_RLE_EN); + set_reg_field_value(value, 1, FBC_COMP_MODE, FBC_DPCM4_RGB_EN); + set_reg_field_value(value, 1, FBC_COMP_MODE, FBC_IND_EN); + dm_write_reg(compressor->ctx, addr, value); + + addr = mmFBC_COMP_CNTL; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value(value, 1, FBC_COMP_CNTL, FBC_DEPTH_RGB08_EN); + dm_write_reg(compressor->ctx, addr, value); + /*FBC_MIN_COMPRESSION 0 ==> 2:1 */ + /* 1 ==> 4:1 */ + /* 2 ==> 8:1 */ + /* 0xF ==> 1:1 */ + set_reg_field_value(value, 0xF, FBC_COMP_CNTL, FBC_MIN_COMPRESSION); + dm_write_reg(compressor->ctx, addr, value); + compressor->min_compress_ratio = FBC_COMPRESS_RATIO_1TO1; + + value = 0; + dm_write_reg(compressor->ctx, mmFBC_IND_LUT0, value); + + value = 0xFFFFFF; + dm_write_reg(compressor->ctx, mmFBC_IND_LUT1, value); +} + +void dce112_compressor_enable_fbc( + struct compressor *compressor, + uint32_t paths_num, + struct compr_addr_and_pitch_params *params) +{ + struct dce112_compressor *cp110 = TO_DCE112_COMPRESSOR(compressor); + + if (compressor->options.bits.FBC_SUPPORT && + (compressor->options.bits.DUMMY_BACKEND == 0) && + (!dce112_compressor_is_fbc_enabled_in_hw(compressor, NULL)) && + (!is_source_bigger_than_epanel_size( + cp110, + params->source_view_width, + params->source_view_height))) { + + uint32_t addr; + uint32_t value; + + /* Before enabling FBC first need to enable LPT if applicable + * LPT state should always be changed (enable/disable) while FBC + * is disabled */ + if (compressor->options.bits.LPT_SUPPORT && (paths_num < 2) && + (params->source_view_width * + params->source_view_height <= + dce11_one_lpt_channel_max_resolution)) { + dce112_compressor_enable_lpt(compressor); + } + + addr = mmFBC_CNTL; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value(value, 1, FBC_CNTL, FBC_GRPH_COMP_EN); + set_reg_field_value( + value, + params->inst, + FBC_CNTL, FBC_SRC_SEL); + dm_write_reg(compressor->ctx, addr, value); + + /* Keep track of enum controller_id FBC is attached to */ + compressor->is_enabled = true; + compressor->attached_inst = params->inst; + cp110->offsets = reg_offsets[params->inst - 1]; + + /*Toggle it as there is bug in HW */ + set_reg_field_value(value, 0, FBC_CNTL, FBC_GRPH_COMP_EN); + dm_write_reg(compressor->ctx, addr, value); + set_reg_field_value(value, 1, FBC_CNTL, FBC_GRPH_COMP_EN); + dm_write_reg(compressor->ctx, addr, value); + + wait_for_fbc_state_changed(cp110, true); + } +} + +void dce112_compressor_disable_fbc(struct compressor *compressor) +{ + struct dce112_compressor *cp110 = TO_DCE112_COMPRESSOR(compressor); + + if (compressor->options.bits.FBC_SUPPORT && + dce112_compressor_is_fbc_enabled_in_hw(compressor, NULL)) { + uint32_t reg_data; + /* Turn off compression */ + reg_data = dm_read_reg(compressor->ctx, mmFBC_CNTL); + set_reg_field_value(reg_data, 0, FBC_CNTL, FBC_GRPH_COMP_EN); + dm_write_reg(compressor->ctx, mmFBC_CNTL, reg_data); + + /* Reset enum controller_id to undefined */ + compressor->attached_inst = 0; + compressor->is_enabled = false; + + /* Whenever disabling FBC make sure LPT is disabled if LPT + * supported */ + if (compressor->options.bits.LPT_SUPPORT) + dce112_compressor_disable_lpt(compressor); + + wait_for_fbc_state_changed(cp110, false); + } +} + +bool dce112_compressor_is_fbc_enabled_in_hw( + struct compressor *compressor, + uint32_t *inst) +{ + /* Check the hardware register */ + uint32_t value; + + value = dm_read_reg(compressor->ctx, mmFBC_STATUS); + if (get_reg_field_value(value, FBC_STATUS, FBC_ENABLE_STATUS)) { + if (inst != NULL) + *inst = compressor->attached_inst; + return true; + } + + value = dm_read_reg(compressor->ctx, mmFBC_MISC); + if (get_reg_field_value(value, FBC_MISC, FBC_STOP_ON_HFLIP_EVENT)) { + value = dm_read_reg(compressor->ctx, mmFBC_CNTL); + + if (get_reg_field_value(value, FBC_CNTL, FBC_GRPH_COMP_EN)) { + if (inst != NULL) + *inst = + compressor->attached_inst; + return true; + } + } + return false; +} + +bool dce112_compressor_is_lpt_enabled_in_hw(struct compressor *compressor) +{ + /* Check the hardware register */ + uint32_t value = dm_read_reg(compressor->ctx, + mmLOW_POWER_TILING_CONTROL); + + return get_reg_field_value( + value, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_ENABLE); +} + +void dce112_compressor_program_compressed_surface_address_and_pitch( + struct compressor *compressor, + struct compr_addr_and_pitch_params *params) +{ + struct dce112_compressor *cp110 = TO_DCE112_COMPRESSOR(compressor); + uint32_t value = 0; + uint32_t fbc_pitch = 0; + uint32_t compressed_surf_address_low_part = + compressor->compr_surface_address.addr.low_part; + + /* Clear content first. */ + dm_write_reg( + compressor->ctx, + DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS_HIGH), + 0); + dm_write_reg(compressor->ctx, + DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS), 0); + + if (compressor->options.bits.LPT_SUPPORT) { + uint32_t lpt_alignment = lpt_size_alignment(cp110); + + if (lpt_alignment != 0) { + compressed_surf_address_low_part = + ((compressed_surf_address_low_part + + (lpt_alignment - 1)) / lpt_alignment) + * lpt_alignment; + } + } + + /* Write address, HIGH has to be first. */ + dm_write_reg(compressor->ctx, + DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS_HIGH), + compressor->compr_surface_address.addr.high_part); + dm_write_reg(compressor->ctx, + DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS), + compressed_surf_address_low_part); + + fbc_pitch = align_to_chunks_number_per_line( + cp110, + params->source_view_width); + + if (compressor->min_compress_ratio == FBC_COMPRESS_RATIO_1TO1) + fbc_pitch = fbc_pitch / 8; + else + dm_logger_write( + compressor->ctx->logger, LOG_WARNING, + "%s: Unexpected DCE11 compression ratio", + __func__); + + /* Clear content first. */ + dm_write_reg(compressor->ctx, DCP_REG(mmGRPH_COMPRESS_PITCH), 0); + + /* Write FBC Pitch. */ + set_reg_field_value( + value, + fbc_pitch, + GRPH_COMPRESS_PITCH, + GRPH_COMPRESS_PITCH); + dm_write_reg(compressor->ctx, DCP_REG(mmGRPH_COMPRESS_PITCH), value); + +} + +void dce112_compressor_disable_lpt(struct compressor *compressor) +{ + struct dce112_compressor *cp110 = TO_DCE112_COMPRESSOR(compressor); + uint32_t value; + uint32_t addr; + uint32_t inx; + + /* Disable all pipes LPT Stutter */ + for (inx = 0; inx < 3; inx++) { + value = + dm_read_reg( + compressor->ctx, + DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH)); + set_reg_field_value( + value, + 0, + DPG_PIPE_STUTTER_CONTROL_NONLPTCH, + STUTTER_ENABLE_NONLPTCH); + dm_write_reg( + compressor->ctx, + DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH), + value); + } + /* Disable Underlay pipe LPT Stutter */ + addr = mmDPGV0_PIPE_STUTTER_CONTROL_NONLPTCH; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value( + value, + 0, + DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH, + STUTTER_ENABLE_NONLPTCH); + dm_write_reg(compressor->ctx, addr, value); + + /* Disable LPT */ + addr = mmLOW_POWER_TILING_CONTROL; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value( + value, + 0, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_ENABLE); + dm_write_reg(compressor->ctx, addr, value); + + /* Clear selection of Channel(s) containing Compressed Surface */ + addr = mmGMCON_LPT_TARGET; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value( + value, + 0xFFFFFFFF, + GMCON_LPT_TARGET, + STCTRL_LPT_TARGET); + dm_write_reg(compressor->ctx, mmGMCON_LPT_TARGET, value); +} + +void dce112_compressor_enable_lpt(struct compressor *compressor) +{ + struct dce112_compressor *cp110 = TO_DCE112_COMPRESSOR(compressor); + uint32_t value; + uint32_t addr; + uint32_t value_control; + uint32_t channels; + + /* Enable LPT Stutter from Display pipe */ + value = dm_read_reg(compressor->ctx, + DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH)); + set_reg_field_value( + value, + 1, + DPG_PIPE_STUTTER_CONTROL_NONLPTCH, + STUTTER_ENABLE_NONLPTCH); + dm_write_reg(compressor->ctx, + DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH), value); + + /* Enable Underlay pipe LPT Stutter */ + addr = mmDPGV0_PIPE_STUTTER_CONTROL_NONLPTCH; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value( + value, + 1, + DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH, + STUTTER_ENABLE_NONLPTCH); + dm_write_reg(compressor->ctx, addr, value); + + /* Selection of Channel(s) containing Compressed Surface: 0xfffffff + * will disable LPT. + * STCTRL_LPT_TARGETn corresponds to channel n. */ + addr = mmLOW_POWER_TILING_CONTROL; + value_control = dm_read_reg(compressor->ctx, addr); + channels = get_reg_field_value(value_control, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_MODE); + + addr = mmGMCON_LPT_TARGET; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value( + value, + channels + 1, /* not mentioned in programming guide, + but follow DCE8.1 */ + GMCON_LPT_TARGET, + STCTRL_LPT_TARGET); + dm_write_reg(compressor->ctx, addr, value); + + /* Enable LPT */ + addr = mmLOW_POWER_TILING_CONTROL; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value( + value, + 1, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_ENABLE); + dm_write_reg(compressor->ctx, addr, value); +} + +void dce112_compressor_program_lpt_control( + struct compressor *compressor, + struct compr_addr_and_pitch_params *params) +{ + struct dce112_compressor *cp110 = TO_DCE112_COMPRESSOR(compressor); + uint32_t rows_per_channel; + uint32_t lpt_alignment; + uint32_t source_view_width; + uint32_t source_view_height; + uint32_t lpt_control = 0; + + if (!compressor->options.bits.LPT_SUPPORT) + return; + + lpt_control = dm_read_reg(compressor->ctx, + mmLOW_POWER_TILING_CONTROL); + + /* POSSIBLE VALUES for Low Power Tiling Mode: + * 00 - Use channel 0 + * 01 - Use Channel 0 and 1 + * 02 - Use Channel 0,1,2,3 + * 03 - reserved */ + switch (compressor->lpt_channels_num) { + /* case 2: + * Use Channel 0 & 1 / Not used for DCE 11 */ + case 1: + /*Use Channel 0 for LPT for DCE 11 */ + set_reg_field_value( + lpt_control, + 0, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_MODE); + break; + default: + dm_logger_write( + compressor->ctx->logger, LOG_WARNING, + "%s: Invalid selected DRAM channels for LPT!!!", + __func__); + break; + } + + lpt_control = lpt_memory_control_config(cp110, lpt_control); + + /* Program LOW_POWER_TILING_ROWS_PER_CHAN field which depends on + * FBC compressed surface pitch. + * LOW_POWER_TILING_ROWS_PER_CHAN = Roundup ((Surface Height * + * Surface Pitch) / (Row Size * Number of Channels * + * Number of Banks)). */ + rows_per_channel = 0; + lpt_alignment = lpt_size_alignment(cp110); + source_view_width = + align_to_chunks_number_per_line( + cp110, + params->source_view_width); + source_view_height = (params->source_view_height + 1) & (~0x1); + + if (lpt_alignment != 0) { + rows_per_channel = source_view_width * source_view_height * 4; + rows_per_channel = + (rows_per_channel % lpt_alignment) ? + (rows_per_channel / lpt_alignment + 1) : + rows_per_channel / lpt_alignment; + } + + set_reg_field_value( + lpt_control, + rows_per_channel, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_ROWS_PER_CHAN); + + dm_write_reg(compressor->ctx, + mmLOW_POWER_TILING_CONTROL, lpt_control); +} + +/* + * DCE 11 Frame Buffer Compression Implementation + */ + +void dce112_compressor_set_fbc_invalidation_triggers( + struct compressor *compressor, + uint32_t fbc_trigger) +{ + /* Disable region hit event, FBC_MEMORY_REGION_MASK = 0 (bits 16-19) + * for DCE 11 regions cannot be used - does not work with S/G + */ + uint32_t addr = mmFBC_CLIENT_REGION_MASK; + uint32_t value = dm_read_reg(compressor->ctx, addr); + + set_reg_field_value( + value, + 0, + FBC_CLIENT_REGION_MASK, + FBC_MEMORY_REGION_MASK); + dm_write_reg(compressor->ctx, addr, value); + + /* Setup events when to clear all CSM entries (effectively marking + * current compressed data invalid) + * For DCE 11 CSM metadata 11111 means - "Not Compressed" + * Used as the initial value of the metadata sent to the compressor + * after invalidation, to indicate that the compressor should attempt + * to compress all chunks on the current pass. Also used when the chunk + * is not successfully written to memory. + * When this CSM value is detected, FBC reads from the uncompressed + * buffer. Set events according to passed in value, these events are + * valid for DCE11: + * - bit 0 - display register updated + * - bit 28 - memory write from any client except from MCIF + * - bit 29 - CG static screen signal is inactive + * In addition, DCE11.1 also needs to set new DCE11.1 specific events + * that are used to trigger invalidation on certain register changes, + * for example enabling of Alpha Compression may trigger invalidation of + * FBC once bit is set. These events are as follows: + * - Bit 2 - FBC_GRPH_COMP_EN register updated + * - Bit 3 - FBC_SRC_SEL register updated + * - Bit 4 - FBC_MIN_COMPRESSION register updated + * - Bit 5 - FBC_ALPHA_COMP_EN register updated + * - Bit 6 - FBC_ZERO_ALPHA_CHUNK_SKIP_EN register updated + * - Bit 7 - FBC_FORCE_COPY_TO_COMP_BUF register updated + */ + addr = mmFBC_IDLE_FORCE_CLEAR_MASK; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value( + value, + fbc_trigger | + FBC_IDLE_FORCE_GRPH_COMP_EN | + FBC_IDLE_FORCE_SRC_SEL_CHANGE | + FBC_IDLE_FORCE_MIN_COMPRESSION_CHANGE | + FBC_IDLE_FORCE_ALPHA_COMP_EN | + FBC_IDLE_FORCE_ZERO_ALPHA_CHUNK_SKIP_EN | + FBC_IDLE_FORCE_FORCE_COPY_TO_COMP_BUF, + FBC_IDLE_FORCE_CLEAR_MASK, + FBC_IDLE_FORCE_CLEAR_MASK); + dm_write_reg(compressor->ctx, addr, value); +} + +bool dce112_compressor_construct(struct dce112_compressor *compressor, + struct dc_context *ctx) +{ + struct dc_bios *bp = ctx->dc_bios; + struct embedded_panel_info panel_info; + + compressor->base.options.bits.FBC_SUPPORT = true; + compressor->base.options.bits.LPT_SUPPORT = true; + /* For DCE 11 always use one DRAM channel for LPT */ + compressor->base.lpt_channels_num = 1; + compressor->base.options.bits.DUMMY_BACKEND = false; + + /* Check if this system has more than 1 DRAM channel; if only 1 then LPT + * should not be supported */ + if (compressor->base.memory_bus_width == 64) + compressor->base.options.bits.LPT_SUPPORT = false; + + compressor->base.options.bits.CLK_GATING_DISABLED = false; + + compressor->base.ctx = ctx; + compressor->base.embedded_panel_h_size = 0; + compressor->base.embedded_panel_v_size = 0; + compressor->base.memory_bus_width = ctx->asic_id.vram_width; + compressor->base.allocated_size = 0; + compressor->base.preferred_requested_size = 0; + compressor->base.min_compress_ratio = FBC_COMPRESS_RATIO_INVALID; + compressor->base.options.raw = 0; + compressor->base.banks_num = 0; + compressor->base.raw_size = 0; + compressor->base.channel_interleave_size = 0; + compressor->base.dram_channels_num = 0; + compressor->base.lpt_channels_num = 0; + compressor->base.attached_inst = 0; + compressor->base.is_enabled = false; + + if (BP_RESULT_OK == + bp->funcs->get_embedded_panel_info(bp, &panel_info)) { + compressor->base.embedded_panel_h_size = + panel_info.lcd_timing.horizontal_addressable; + compressor->base.embedded_panel_v_size = + panel_info.lcd_timing.vertical_addressable; + } + return true; +} + +struct compressor *dce112_compressor_create(struct dc_context *ctx) +{ + struct dce112_compressor *cp110 = + dm_alloc(sizeof(struct dce112_compressor)); + + if (!cp110) + return NULL; + + if (dce112_compressor_construct(cp110, ctx)) + return &cp110->base; + + BREAK_TO_DEBUGGER(); + dm_free(cp110); + return NULL; +} + +void dce112_compressor_destroy(struct compressor **compressor) +{ + dm_free(TO_DCE112_COMPRESSOR(*compressor)); + *compressor = NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.h b/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.h new file mode 100644 index 000000000000..106506387270 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.h @@ -0,0 +1,78 @@ +/* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_COMPRESSOR_DCE112_H__ +#define __DC_COMPRESSOR_DCE112_H__ + +#include "../inc/compressor.h" + +#define TO_DCE112_COMPRESSOR(compressor)\ + container_of(compressor, struct dce112_compressor, base) + +struct dce112_compressor_reg_offsets { + uint32_t dcp_offset; + uint32_t dmif_offset; +}; + +struct dce112_compressor { + struct compressor base; + struct dce112_compressor_reg_offsets offsets; +}; + +struct compressor *dce112_compressor_create(struct dc_context *ctx); + +bool dce112_compressor_construct(struct dce112_compressor *cp110, + struct dc_context *ctx); + +void dce112_compressor_destroy(struct compressor **cp); + +/* FBC RELATED */ +void dce112_compressor_power_up_fbc(struct compressor *cp); + +void dce112_compressor_enable_fbc(struct compressor *cp, uint32_t paths_num, + struct compr_addr_and_pitch_params *params); + +void dce112_compressor_disable_fbc(struct compressor *cp); + +void dce112_compressor_set_fbc_invalidation_triggers(struct compressor *cp, + uint32_t fbc_trigger); + +void dce112_compressor_program_compressed_surface_address_and_pitch( + struct compressor *cp, + struct compr_addr_and_pitch_params *params); + +bool dce112_compressor_is_fbc_enabled_in_hw(struct compressor *cp, + uint32_t *fbc_mapped_crtc_id); + +/* LPT RELATED */ +void dce112_compressor_enable_lpt(struct compressor *cp); + +void dce112_compressor_disable_lpt(struct compressor *cp); + +void dce112_compressor_program_lpt_control(struct compressor *cp, + struct compr_addr_and_pitch_params *params); + +bool dce112_compressor_is_lpt_enabled_in_hw(struct compressor *cp); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.c new file mode 100644 index 000000000000..204f613467b7 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.c @@ -0,0 +1,166 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "dc.h" +#include "core_dc.h" +#include "core_types.h" +#include "dce112_hw_sequencer.h" + +#include "dce110/dce110_hw_sequencer.h" + +/* include DCE11.2 register header files */ +#include "dce/dce_11_2_d.h" +#include "dce/dce_11_2_sh_mask.h" + +struct dce112_hw_seq_reg_offsets { + uint32_t crtc; +}; + + +static const struct dce112_hw_seq_reg_offsets reg_offsets[] = { +{ + .crtc = (mmCRTC0_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), +}, +{ + .crtc = (mmCRTC1_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), +}, +{ + .crtc = (mmCRTC2_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), +}, +{ + .crtc = (mmCRTC3_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), +}, +{ + .crtc = (mmCRTC4_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), +}, +{ + .crtc = (mmCRTC5_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), +} +}; +#define HW_REG_CRTC(reg, id)\ + (reg + reg_offsets[id].crtc) + +/******************************************************************************* + * Private definitions + ******************************************************************************/ + +static void dce112_init_pte(struct dc_context *ctx) +{ + uint32_t addr; + uint32_t value = 0; + uint32_t chunk_int = 0; + uint32_t chunk_mul = 0; + + addr = mmDVMM_PTE_REQ; + value = dm_read_reg(ctx, addr); + + chunk_int = get_reg_field_value( + value, + DVMM_PTE_REQ, + HFLIP_PTEREQ_PER_CHUNK_INT); + + chunk_mul = get_reg_field_value( + value, + DVMM_PTE_REQ, + HFLIP_PTEREQ_PER_CHUNK_MULTIPLIER); + + if (chunk_int != 0x4 || chunk_mul != 0x4) { + + set_reg_field_value( + value, + 255, + DVMM_PTE_REQ, + MAX_PTEREQ_TO_ISSUE); + + set_reg_field_value( + value, + 4, + DVMM_PTE_REQ, + HFLIP_PTEREQ_PER_CHUNK_INT); + + set_reg_field_value( + value, + 4, + DVMM_PTE_REQ, + HFLIP_PTEREQ_PER_CHUNK_MULTIPLIER); + + dm_write_reg(ctx, addr, value); + } +} + +static bool dce112_enable_display_power_gating( + struct core_dc *dc, + uint8_t controller_id, + struct dc_bios *dcb, + enum pipe_gating_control power_gating) +{ + enum bp_result bp_result = BP_RESULT_OK; + enum bp_pipe_control_action cntl; + struct dc_context *ctx = dc->ctx; + + if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment)) + return true; + + if (power_gating == PIPE_GATING_CONTROL_INIT) + cntl = ASIC_PIPE_INIT; + else if (power_gating == PIPE_GATING_CONTROL_ENABLE) + cntl = ASIC_PIPE_ENABLE; + else + cntl = ASIC_PIPE_DISABLE; + + if (power_gating != PIPE_GATING_CONTROL_INIT || controller_id == 0){ + + bp_result = dcb->funcs->enable_disp_power_gating( + dcb, controller_id + 1, cntl); + + /* Revert MASTER_UPDATE_MODE to 0 because bios sets it 2 + * by default when command table is called + */ + dm_write_reg(ctx, + HW_REG_CRTC(mmCRTC_MASTER_UPDATE_MODE, controller_id), + 0); + } + + if (power_gating != PIPE_GATING_CONTROL_ENABLE) + dce112_init_pte(ctx); + + if (bp_result == BP_RESULT_OK) + return true; + else + return false; +} + +bool dce112_hw_sequencer_construct(struct core_dc *dc) +{ + /* All registers used by dce11.2 match those in dce11 in offset and + * structure + */ + dce110_hw_sequencer_construct(dc); + dc->hwss.enable_display_power_gating = dce112_enable_display_power_gating; + + return true; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.h new file mode 100644 index 000000000000..d96c582da45c --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.h @@ -0,0 +1,36 @@ +/* +* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_HWSS_DCE112_H__ +#define __DC_HWSS_DCE112_H__ + +#include "core_types.h" + +struct core_dc; + +bool dce112_hw_sequencer_construct(struct core_dc *dc); + +#endif /* __DC_HWSS_DCE112_H__ */ + diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_mem_input.c new file mode 100644 index 000000000000..c29007dafe21 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_mem_input.c @@ -0,0 +1,54 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#include "dm_services.h" +#include "dce112_mem_input.h" + + +#include "dce/dce_11_2_d.h" +#include "dce/dce_11_2_sh_mask.h" + + +#define DCP_REG(reg) (reg + mem_input110->offsets.dcp) +#define DMIF_REG(reg) (reg + mem_input110->offsets.dmif) +#define PIPE_REG(reg) (reg + mem_input110->offsets.pipe) + +/*****************************************/ +/* Constructor, Destructor */ +/*****************************************/ + +bool dce112_mem_input_construct( + struct dce110_mem_input *mem_input110, + struct dc_context *ctx, + uint32_t inst, + const struct dce110_mem_input_reg_offsets *offsets) +{ + if (!dce110_mem_input_construct(mem_input110, ctx, inst, offsets)) + return false; + + mem_input110->base.funcs->mem_input_program_display_marks = + dce_mem_input_program_display_marks; + + return true; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce112/dce112_mem_input.h new file mode 100644 index 000000000000..de2aaf0f9a8e --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_mem_input.h @@ -0,0 +1,38 @@ +/* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_MEM_INPUT_DCE112_H__ +#define __DC_MEM_INPUT_DCE112_H__ + +#include "mem_input.h" +#include "dce110/dce110_mem_input.h" + +bool dce112_mem_input_construct( + struct dce110_mem_input *mem_input110, + struct dc_context *ctx, + uint32_t inst, + const struct dce110_mem_input_reg_offsets *offsets); + + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_opp.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_opp.c new file mode 100644 index 000000000000..23c2d1086b3b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_opp.c @@ -0,0 +1,72 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* include DCE11 register header files */ +#include "dce/dce_11_2_d.h" +#include "dce/dce_11_2_sh_mask.h" + +#include "dce112_opp.h" + +#include "gamma_types.h" + +enum { + MAX_LUT_ENTRY = 256, + MAX_NUMBER_OF_ENTRIES = 256 +}; + +/*****************************************/ +/* Constructor, Destructor */ +/*****************************************/ + +static struct opp_funcs funcs = { + .opp_power_on_regamma_lut = dce110_opp_power_on_regamma_lut, + .opp_set_csc_adjustment = dce110_opp_set_csc_adjustment, + .opp_set_csc_default = dce110_opp_set_csc_default, + .opp_set_dyn_expansion = dce110_opp_set_dyn_expansion, + .opp_program_regamma_pwl = dce110_opp_program_regamma_pwl, + .opp_set_regamma_mode = dce110_opp_set_regamma_mode, + .opp_destroy = dce110_opp_destroy, + .opp_program_fmt = dce112_opp_program_fmt, + .opp_program_bit_depth_reduction = + dce110_opp_program_bit_depth_reduction +}; + +bool dce112_opp_construct(struct dce110_opp *opp110, + struct dc_context *ctx, + uint32_t inst, + const struct dce110_opp_reg_offsets *offsets) +{ + opp110->base.funcs = &funcs; + + opp110->base.ctx = ctx; + + opp110->base.inst = inst; + + opp110->offsets = *offsets; + + return true; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_opp.h b/drivers/gpu/drm/amd/display/dc/dce112/dce112_opp.h new file mode 100644 index 000000000000..9443b87776c6 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_opp.h @@ -0,0 +1,48 @@ +/* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_OPP_DCE112_H__ +#define __DC_OPP_DCE112_H__ + +#include "dc_types.h" +#include "opp.h" +#include "../dce110/dce110_opp.h" +#include "core_types.h" + +void dce112_opp_program_clamping_and_pixel_encoding( + struct output_pixel_processor *opp, + const struct clamping_and_pixel_encoding_params *params); + +void dce112_opp_program_fmt( + struct output_pixel_processor *opp, + struct bit_depth_reduction_params *fmt_bit_depth, + struct clamping_and_pixel_encoding_params *clamping); + +bool dce112_opp_construct(struct dce110_opp *opp110, + struct dc_context *ctx, + uint32_t inst, + const struct dce110_opp_reg_offsets *offsets); + + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_opp_formatter.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_opp_formatter.c new file mode 100644 index 000000000000..2d9072138834 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_opp_formatter.c @@ -0,0 +1,215 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "dce/dce_11_2_d.h" +#include "dce/dce_11_2_sh_mask.h" + +#include "dce112_opp.h" + +#define FMT_REG(reg)\ + (reg + opp110->offsets.fmt_offset) +#define FMT_MEM_REG(reg)\ + (reg + opp110->offsets.fmt_mem_offset) + +/** + * Set Clamping + * 1) Set clamping format based on bpc - 0 for 6bpc (No clamping) + * 1 for 8 bpc + * 2 for 10 bpc + * 3 for 12 bpc + * 7 for programable + * 2) Enable clamp if Limited range requested + */ + +/** + * set_pixel_encoding + * + * Set Pixel Encoding + * 0: RGB 4:4:4 or YCbCr 4:4:4 or YOnly + * 1: YCbCr 4:2:2 + * 2: YCbCr 4:2:0 + */ +static void set_pixel_encoding( + struct dce110_opp *opp110, + const struct clamping_and_pixel_encoding_params *params) +{ + uint32_t fmt_cntl_value; + uint32_t addr = FMT_REG(mmFMT_CONTROL); + + /*RGB 4:4:4 or YCbCr 4:4:4 - 0; YCbCr 4:2:2 -1.*/ + fmt_cntl_value = dm_read_reg(opp110->base.ctx, addr); + + set_reg_field_value(fmt_cntl_value, + 0, + FMT_CONTROL, + FMT_PIXEL_ENCODING); + + /*00 - Pixels drop mode HW default*/ + set_reg_field_value(fmt_cntl_value, + 0, + FMT_CONTROL, + FMT_SUBSAMPLING_MODE); + + /* By default no bypass*/ + set_reg_field_value(fmt_cntl_value, + 0, + FMT_CONTROL, + FMT_CBCR_BIT_REDUCTION_BYPASS); + + if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) { + set_reg_field_value(fmt_cntl_value, + 1, + FMT_CONTROL, + FMT_PIXEL_ENCODING); + + /*00 - Cb before Cr ,01 - Cr before Cb*/ + set_reg_field_value(fmt_cntl_value, + 0, + FMT_CONTROL, + FMT_SUBSAMPLING_ORDER); + } + + if (params->pixel_encoding == PIXEL_ENCODING_YCBCR420) { + set_reg_field_value(fmt_cntl_value, + 2, + FMT_CONTROL, + FMT_PIXEL_ENCODING); + + /* 02 - Subsampling mode, 3 taps*/ + set_reg_field_value(fmt_cntl_value, + 2, + FMT_CONTROL, + FMT_SUBSAMPLING_MODE); + + /* 00 - Enable CbCr bit reduction bypass to preserve precision*/ + set_reg_field_value(fmt_cntl_value, + 1, + FMT_CONTROL, + FMT_CBCR_BIT_REDUCTION_BYPASS); + } + dm_write_reg(opp110->base.ctx, addr, fmt_cntl_value); + +} + +void dce112_opp_program_clamping_and_pixel_encoding( + struct output_pixel_processor *opp, + const struct clamping_and_pixel_encoding_params *params) +{ + struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + + dce110_opp_set_clamping(opp110, params); + set_pixel_encoding(opp110, params); +} + +static void program_formatter_420_memory(struct output_pixel_processor *opp) +{ + struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + uint32_t fmt_cntl_value; + uint32_t fmt_mem_cntl_value; + uint32_t fmt_cntl_addr = FMT_REG(mmFMT_CONTROL); + uint32_t fmt_mem_cntl_addr = FMT_MEM_REG(mmFMT_MEMORY0_CONTROL); + + fmt_mem_cntl_value = dm_read_reg(opp110->base.ctx, fmt_mem_cntl_addr); + fmt_cntl_value = dm_read_reg(opp110->base.ctx, fmt_cntl_addr); + /* Program source select*/ + /* Use HW default source select for FMT_MEMORYx_CONTROL */ + /* Use that value for FMT_SRC_SELECT as well*/ + set_reg_field_value(fmt_cntl_value, + get_reg_field_value(fmt_mem_cntl_value, FMT_MEMORY0_CONTROL, FMT420_MEM0_SOURCE_SEL), + FMT_CONTROL, + FMT_SRC_SELECT); + dm_write_reg(opp110->base.ctx, fmt_cntl_addr, fmt_cntl_value); + + /* Turn on the memory */ + set_reg_field_value(fmt_mem_cntl_value, + 0, + FMT_MEMORY0_CONTROL, + FMT420_MEM0_PWR_FORCE); + dm_write_reg(opp110->base.ctx, fmt_mem_cntl_addr, fmt_mem_cntl_value); +} + +static void program_formatter_reset_dig_resync_fifo(struct output_pixel_processor *opp) +{ + struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + uint32_t value; + uint32_t addr = FMT_REG(mmFMT_CONTROL); + uint8_t counter = 10; + + + value = dm_read_reg(opp110->base.ctx, addr); + + /* clear previous phase lock status*/ + set_reg_field_value(value, + 1, + FMT_CONTROL, + FMT_420_PIXEL_PHASE_LOCKED_CLEAR); + dm_write_reg(opp110->base.ctx, addr, value); + + /* poll until FMT_420_PIXEL_PHASE_LOCKED become 1*/ + while (counter > 0) { + value = dm_read_reg(opp110->base.ctx, addr); + + if (get_reg_field_value( + value, + FMT_CONTROL, + FMT_420_PIXEL_PHASE_LOCKED) == 1) + break; + + msleep(10); + counter--; + } + + if (counter == 0) + dm_logger_write(opp->ctx->logger, LOG_ERROR, + "%s:opp program formattter reset dig resync info time out.\n", + __func__); +} + +void dce112_opp_program_fmt( + struct output_pixel_processor *opp, + struct bit_depth_reduction_params *fmt_bit_depth, + struct clamping_and_pixel_encoding_params *clamping) +{ + /* dithering is affected by , hence should be + * programmed afterwards */ + + if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420) + program_formatter_420_memory(opp); + + dce110_opp_program_bit_depth_reduction( + opp, + fmt_bit_depth); + + dce112_opp_program_clamping_and_pixel_encoding( + opp, + clamping); + + if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420) + program_formatter_reset_dig_resync_fifo(opp); + + return; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c new file mode 100644 index 000000000000..bfb2c3fcd2cb --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -0,0 +1,1418 @@ +/* +* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "link_encoder.h" +#include "stream_encoder.h" + +#include "resource.h" +#include "include/irq_service_interface.h" +#include "dce110/dce110_resource.h" +#include "dce110/dce110_timing_generator.h" +#include "dce112/dce112_mem_input.h" + +#include "irq/dce110/irq_service_dce110.h" +#include "dce/dce_transform.h" +#include "dce/dce_link_encoder.h" +#include "dce/dce_stream_encoder.h" +#include "dce/dce_audio.h" +#include "dce112/dce112_opp.h" +#include "dce110/dce110_ipp.h" +#include "dce/dce_clock_source.h" + +#include "dce/dce_hwseq.h" +#include "dce112/dce112_hw_sequencer.h" + +#include "reg_helper.h" + +#include "dce/dce_11_2_d.h" +#include "dce/dce_11_2_sh_mask.h" + +#ifndef mmDP_DPHY_INTERNAL_CTRL + #define mmDP_DPHY_INTERNAL_CTRL 0x4aa7 + #define mmDP0_DP_DPHY_INTERNAL_CTRL 0x4aa7 + #define mmDP1_DP_DPHY_INTERNAL_CTRL 0x4ba7 + #define mmDP2_DP_DPHY_INTERNAL_CTRL 0x4ca7 + #define mmDP3_DP_DPHY_INTERNAL_CTRL 0x4da7 + #define mmDP4_DP_DPHY_INTERNAL_CTRL 0x4ea7 + #define mmDP5_DP_DPHY_INTERNAL_CTRL 0x4fa7 + #define mmDP6_DP_DPHY_INTERNAL_CTRL 0x54a7 + #define mmDP7_DP_DPHY_INTERNAL_CTRL 0x56a7 + #define mmDP8_DP_DPHY_INTERNAL_CTRL 0x57a7 +#endif + +#ifndef mmBIOS_SCRATCH_2 + #define mmBIOS_SCRATCH_2 0x05CB + #define mmBIOS_SCRATCH_6 0x05CF +#endif + +#ifndef mmDP_DPHY_BS_SR_SWAP_CNTL + #define mmDP_DPHY_BS_SR_SWAP_CNTL 0x4ADC + #define mmDP0_DP_DPHY_BS_SR_SWAP_CNTL 0x4ADC + #define mmDP1_DP_DPHY_BS_SR_SWAP_CNTL 0x4BDC + #define mmDP2_DP_DPHY_BS_SR_SWAP_CNTL 0x4CDC + #define mmDP3_DP_DPHY_BS_SR_SWAP_CNTL 0x4DDC + #define mmDP4_DP_DPHY_BS_SR_SWAP_CNTL 0x4EDC + #define mmDP5_DP_DPHY_BS_SR_SWAP_CNTL 0x4FDC + #define mmDP6_DP_DPHY_BS_SR_SWAP_CNTL 0x54DC +#endif + +#ifndef mmDP_DPHY_FAST_TRAINING + #define mmDP_DPHY_FAST_TRAINING 0x4ABC + #define mmDP0_DP_DPHY_FAST_TRAINING 0x4ABC + #define mmDP1_DP_DPHY_FAST_TRAINING 0x4BBC + #define mmDP2_DP_DPHY_FAST_TRAINING 0x4CBC + #define mmDP3_DP_DPHY_FAST_TRAINING 0x4DBC + #define mmDP4_DP_DPHY_FAST_TRAINING 0x4EBC + #define mmDP5_DP_DPHY_FAST_TRAINING 0x4FBC + #define mmDP6_DP_DPHY_FAST_TRAINING 0x54BC +#endif + +enum dce112_clk_src_array_id { + DCE112_CLK_SRC_PLL0, + DCE112_CLK_SRC_PLL1, + DCE112_CLK_SRC_PLL2, + DCE112_CLK_SRC_PLL3, + DCE112_CLK_SRC_PLL4, + DCE112_CLK_SRC_PLL5, + + DCE112_CLK_SRC_TOTAL +}; + +static const struct dce110_timing_generator_offsets dce112_tg_offsets[] = { + { + .crtc = (mmCRTC0_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL), + }, + { + .crtc = (mmCRTC1_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL), + }, + { + .crtc = (mmCRTC2_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL), + }, + { + .crtc = (mmCRTC3_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL), + }, + { + .crtc = (mmCRTC4_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL), + }, + { + .crtc = (mmCRTC5_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL), + } +}; + +static const struct dce110_mem_input_reg_offsets dce112_mi_reg_offsets[] = { + { + .dcp = (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE0_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + }, + { + .dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG1_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE1_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + }, + { + .dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG2_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE2_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + }, + { + .dcp = (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG3_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE3_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + }, + { + .dcp = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG4_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE4_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + }, + { + .dcp = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG5_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE5_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + } +}; + +static const struct dce110_ipp_reg_offsets ipp_reg_offsets[] = { +{ + .dcp_offset = (mmDCP0_CUR_CONTROL - mmCUR_CONTROL), +}, +{ + .dcp_offset = (mmDCP1_CUR_CONTROL - mmCUR_CONTROL), +}, +{ + .dcp_offset = (mmDCP2_CUR_CONTROL - mmCUR_CONTROL), +}, +{ + .dcp_offset = (mmDCP3_CUR_CONTROL - mmCUR_CONTROL), +}, +{ + .dcp_offset = (mmDCP4_CUR_CONTROL - mmCUR_CONTROL), +}, +{ + .dcp_offset = (mmDCP5_CUR_CONTROL - mmCUR_CONTROL), +} +}; + + +/* set register offset */ +#define SR(reg_name)\ + .reg_name = mm ## reg_name + +/* set register offset with instance */ +#define SRI(reg_name, block, id)\ + .reg_name = mm ## block ## id ## _ ## reg_name + +#define transform_regs(id)\ +[id] = {\ + XFM_COMMON_REG_LIST_DCE110(id)\ +} + +static const struct dce_transform_registers xfm_regs[] = { + transform_regs(0), + transform_regs(1), + transform_regs(2), + transform_regs(3), + transform_regs(4), + transform_regs(5) +}; + +static const struct dce_transform_shift xfm_shift = { + XFM_COMMON_MASK_SH_LIST_DCE110(__SHIFT) +}; + +static const struct dce_transform_mask xfm_mask = { + XFM_COMMON_MASK_SH_LIST_DCE110(_MASK) +}; + +#define aux_regs(id)\ +[id] = {\ + AUX_REG_LIST(id)\ +} + +static const struct dce110_link_enc_aux_registers link_enc_aux_regs[] = { + aux_regs(0), + aux_regs(1), + aux_regs(2), + aux_regs(3), + aux_regs(4), + aux_regs(5) +}; + +#define hpd_regs(id)\ +[id] = {\ + HPD_REG_LIST(id)\ +} + +static const struct dce110_link_enc_hpd_registers link_enc_hpd_regs[] = { + hpd_regs(0), + hpd_regs(1), + hpd_regs(2), + hpd_regs(3), + hpd_regs(4), + hpd_regs(5) +}; + +#define link_regs(id)\ +[id] = {\ + LE_DCE110_REG_LIST(id)\ +} + +static const struct dce110_link_enc_registers link_enc_regs[] = { + link_regs(0), + link_regs(1), + link_regs(2), + link_regs(3), + link_regs(4), + link_regs(5), + link_regs(6), +}; + +#define stream_enc_regs(id)\ +[id] = {\ + SE_COMMON_REG_LIST(id),\ + .TMDS_CNTL = 0,\ +} + +static const struct dce110_stream_enc_registers stream_enc_regs[] = { + stream_enc_regs(0), + stream_enc_regs(1), + stream_enc_regs(2), + stream_enc_regs(3), + stream_enc_regs(4), + stream_enc_regs(5) +}; + +static const struct dce_stream_encoder_shift se_shift = { + SE_COMMON_MASK_SH_LIST_DCE112(__SHIFT) +}; + +static const struct dce_stream_encoder_mask se_mask = { + SE_COMMON_MASK_SH_LIST_DCE112(_MASK) +}; + +#define audio_regs(id)\ +[id] = {\ + AUD_COMMON_REG_LIST(id)\ +} + +static const struct dce_audio_registers audio_regs[] = { + audio_regs(0), + audio_regs(1), + audio_regs(2), + audio_regs(3), + audio_regs(4), + audio_regs(5) +}; + +static const struct dce_audio_shift audio_shift = { + AUD_COMMON_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_aduio_mask audio_mask = { + AUD_COMMON_MASK_SH_LIST(_MASK) +}; + + +static const struct dce110_opp_reg_offsets dce112_opp_reg_offsets[] = { +{ + .fmt_offset = (mmFMT0_FMT_CONTROL - mmFMT0_FMT_CONTROL), + .fmt_mem_offset = (mmFMT_MEMORY0_CONTROL - mmFMT_MEMORY0_CONTROL), + .dcfe_offset = (mmDCFE0_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), + .dcp_offset = (mmDCP0_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ .fmt_offset = (mmFMT1_FMT_CONTROL - mmFMT0_FMT_CONTROL), + .fmt_mem_offset = (mmFMT_MEMORY1_CONTROL - mmFMT_MEMORY0_CONTROL), + .dcfe_offset = (mmDCFE1_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), + .dcp_offset = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ .fmt_offset = (mmFMT2_FMT_CONTROL - mmFMT0_FMT_CONTROL), + .fmt_mem_offset = (mmFMT_MEMORY2_CONTROL - mmFMT_MEMORY0_CONTROL), + .dcfe_offset = (mmDCFE2_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), + .dcp_offset = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ + .fmt_offset = (mmFMT3_FMT_CONTROL - mmFMT0_FMT_CONTROL), + .fmt_mem_offset = (mmFMT_MEMORY3_CONTROL - mmFMT_MEMORY0_CONTROL), + .dcfe_offset = (mmDCFE3_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), + .dcp_offset = (mmDCP3_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ .fmt_offset = (mmFMT4_FMT_CONTROL - mmFMT0_FMT_CONTROL), + .fmt_mem_offset = (mmFMT_MEMORY4_CONTROL - mmFMT_MEMORY0_CONTROL), + .dcfe_offset = (mmDCFE4_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), + .dcp_offset = (mmDCP4_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ .fmt_offset = (mmFMT5_FMT_CONTROL - mmFMT0_FMT_CONTROL), + .fmt_mem_offset = (mmFMT_MEMORY5_CONTROL - mmFMT_MEMORY0_CONTROL), + .dcfe_offset = (mmDCFE5_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), + .dcp_offset = (mmDCP5_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +} +}; + +#define clk_src_regs(index, id)\ +[index] = {\ + CS_COMMON_REG_LIST_DCE_112(id),\ +} + +static const struct dce110_clk_src_regs clk_src_regs[] = { + clk_src_regs(0, A), + clk_src_regs(1, B), + clk_src_regs(2, C), + clk_src_regs(3, D), + clk_src_regs(4, E), + clk_src_regs(5, F) +}; + +static const struct dce110_clk_src_shift cs_shift = { + CS_COMMON_MASK_SH_LIST_DCE_112(__SHIFT) +}; + +static const struct dce110_clk_src_mask cs_mask = { + CS_COMMON_MASK_SH_LIST_DCE_112(_MASK) +}; + +static const struct bios_registers bios_regs = { + .BIOS_SCRATCH_6 = mmBIOS_SCRATCH_6 +}; + +static const struct resource_caps polaris_10_resource_cap = { + .num_timing_generator = 6, + .num_audio = 6, + .num_stream_encoder = 6, + .num_pll = 8, /* why 8? 6 combo PHY PLL + 2 regular PLLs? */ +}; + +static const struct resource_caps polaris_11_resource_cap = { + .num_timing_generator = 5, + .num_audio = 5, + .num_stream_encoder = 5, + .num_pll = 8, /* why 8? 6 combo PHY PLL + 2 regular PLLs? */ +}; + +#define CTX ctx +#define REG(reg) mm ## reg + +#ifndef mmCC_DC_HDMI_STRAPS +#define mmCC_DC_HDMI_STRAPS 0x4819 +#define CC_DC_HDMI_STRAPS__HDMI_DISABLE_MASK 0x40 +#define CC_DC_HDMI_STRAPS__HDMI_DISABLE__SHIFT 0x6 +#define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER_MASK 0x700 +#define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER__SHIFT 0x8 +#endif + +static void read_dce_straps( + struct dc_context *ctx, + struct resource_straps *straps) +{ + REG_GET_2(CC_DC_HDMI_STRAPS, + HDMI_DISABLE, &straps->hdmi_disable, + AUDIO_STREAM_NUMBER, &straps->audio_stream_number); + + REG_GET(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO, &straps->dc_pinstraps_audio); +} + +static struct audio *create_audio( + struct dc_context *ctx, unsigned int inst) +{ + return dce_audio_create(ctx, inst, + &audio_regs[inst], &audio_shift, &audio_mask); +} + + +static struct timing_generator *dce112_timing_generator_create( + struct dc_context *ctx, + uint32_t instance, + const struct dce110_timing_generator_offsets *offsets) +{ + struct dce110_timing_generator *tg110 = + dm_alloc(sizeof(struct dce110_timing_generator)); + + if (!tg110) + return NULL; + + if (dce110_timing_generator_construct(tg110, ctx, instance, offsets)) + return &tg110->base; + + BREAK_TO_DEBUGGER(); + dm_free(tg110); + return NULL; +} + +static struct stream_encoder *dce112_stream_encoder_create( + enum engine_id eng_id, + struct dc_context *ctx) +{ + struct dce110_stream_encoder *enc110 = + dm_alloc(sizeof(struct dce110_stream_encoder)); + + if (!enc110) + return NULL; + + if (dce110_stream_encoder_construct( + enc110, ctx, ctx->dc_bios, eng_id, + &stream_enc_regs[eng_id], &se_shift, &se_mask)) + return &enc110->base; + + BREAK_TO_DEBUGGER(); + dm_free(enc110); + return NULL; +} + +#define SRII(reg_name, block, id)\ + .reg_name[id] = mm ## block ## id ## _ ## reg_name + +static const struct dce_hwseq_registers hwseq_reg = { + HWSEQ_DCE112_REG_LIST() +}; + +static const struct dce_hwseq_shift hwseq_shift = { + HWSEQ_DCE112_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_hwseq_mask hwseq_mask = { + HWSEQ_DCE112_MASK_SH_LIST(_MASK) +}; + +static struct dce_hwseq *dce112_hwseq_create( + struct dc_context *ctx) +{ + struct dce_hwseq *hws = dm_alloc(sizeof(struct dce_hwseq)); + + if (hws) { + hws->ctx = ctx; + hws->regs = &hwseq_reg; + hws->shifts = &hwseq_shift; + hws->masks = &hwseq_mask; + } + return hws; +} + +static const struct resource_create_funcs res_create_funcs = { + .read_dce_straps = read_dce_straps, + .create_audio = create_audio, + .create_stream_encoder = dce112_stream_encoder_create, + .create_hwseq = dce112_hwseq_create, +}; + +#define mi_inst_regs(id) { MI_REG_LIST(id) } +static const struct dce_mem_input_registers mi_regs[] = { + mi_inst_regs(0), + mi_inst_regs(1), + mi_inst_regs(2), + mi_inst_regs(3), + mi_inst_regs(4), + mi_inst_regs(5), +}; + +static const struct dce_mem_input_shift mi_shifts = { + MI_DCE_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_mem_input_mask mi_masks = { + MI_DCE_MASK_SH_LIST(_MASK) +}; + +static struct mem_input *dce112_mem_input_create( + struct dc_context *ctx, + uint32_t inst, + const struct dce110_mem_input_reg_offsets *offset) +{ + struct dce110_mem_input *mem_input110 = + dm_alloc(sizeof(struct dce110_mem_input)); + + if (!mem_input110) + return NULL; + + if (dce112_mem_input_construct(mem_input110, ctx, inst, offset)) { + struct mem_input *mi = &mem_input110->base; + + mi->regs = &mi_regs[inst]; + mi->shifts = &mi_shifts; + mi->masks = &mi_masks; + return mi; + } + + BREAK_TO_DEBUGGER(); + dm_free(mem_input110); + return NULL; +} + +static void dce112_transform_destroy(struct transform **xfm) +{ + dm_free(TO_DCE_TRANSFORM(*xfm)); + *xfm = NULL; +} + +static struct transform *dce112_transform_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dce_transform *transform = + dm_alloc(sizeof(struct dce_transform)); + + if (!transform) + return NULL; + + if (dce_transform_construct(transform, ctx, inst, + &xfm_regs[inst], &xfm_shift, &xfm_mask)) { + transform->lb_memory_size = 0x1404; /*5124*/ + return &transform->base; + } + + BREAK_TO_DEBUGGER(); + dm_free(transform); + return NULL; +} +struct link_encoder *dce112_link_encoder_create( + const struct encoder_init_data *enc_init_data) +{ + struct dce110_link_encoder *enc110 = + dm_alloc(sizeof(struct dce110_link_encoder)); + + if (!enc110) + return NULL; + + if (dce110_link_encoder_construct( + enc110, + enc_init_data, + &link_enc_regs[enc_init_data->transmitter], + &link_enc_aux_regs[enc_init_data->channel - 1], + &link_enc_hpd_regs[enc_init_data->hpd_source])) { + + enc110->base.features.ycbcr420_supported = false; + enc110->base.features.max_hdmi_pixel_clock = 600000; + return &enc110->base; + } + + BREAK_TO_DEBUGGER(); + dm_free(enc110); + return NULL; +} + +struct input_pixel_processor *dce112_ipp_create( + struct dc_context *ctx, + uint32_t inst, + const struct dce110_ipp_reg_offsets *offset) +{ + struct dce110_ipp *ipp = + dm_alloc(sizeof(struct dce110_ipp)); + + if (!ipp) + return NULL; + + if (dce110_ipp_construct(ipp, ctx, inst, offset)) + return &ipp->base; + + BREAK_TO_DEBUGGER(); + dm_free(ipp); + return NULL; +} + +void dce112_ipp_destroy(struct input_pixel_processor **ipp) +{ + dm_free(TO_DCE110_IPP(*ipp)); + *ipp = NULL; +} + +struct output_pixel_processor *dce112_opp_create( + struct dc_context *ctx, + uint32_t inst, + const struct dce110_opp_reg_offsets *offset) +{ + struct dce110_opp *opp = + dm_alloc(sizeof(struct dce110_opp)); + + if (!opp) + return NULL; + + if (dce112_opp_construct(opp, + ctx, inst, offset)) + return &opp->base; + + BREAK_TO_DEBUGGER(); + dm_free(opp); + return NULL; +} + +void dce112_opp_destroy(struct output_pixel_processor **opp) +{ + struct dce110_opp *dce110_opp; + + if (!opp || !*opp) + return; + + dce110_opp = FROM_DCE11_OPP(*opp); + + dm_free(dce110_opp->regamma.coeff128_dx); + dm_free(dce110_opp->regamma.coeff128_oem); + dm_free(dce110_opp->regamma.coeff128); + dm_free(dce110_opp->regamma.axis_x_1025); + dm_free(dce110_opp->regamma.axis_x_256); + dm_free(dce110_opp->regamma.coordinates_x); + dm_free(dce110_opp->regamma.rgb_regamma); + dm_free(dce110_opp->regamma.rgb_resulted); + dm_free(dce110_opp->regamma.rgb_oem); + dm_free(dce110_opp->regamma.rgb_user); + + dm_free(dce110_opp); + *opp = NULL; +} + +struct clock_source *dce112_clock_source_create( + struct dc_context *ctx, + struct dc_bios *bios, + enum clock_source_id id, + const struct dce110_clk_src_regs *regs, + bool dp_clk_src) +{ + struct dce110_clk_src *clk_src = + dm_alloc(sizeof(struct dce110_clk_src)); + + if (!clk_src) + return NULL; + + if (dce110_clk_src_construct(clk_src, ctx, bios, id, + regs, &cs_shift, &cs_mask)) { + clk_src->base.dp_clk_src = dp_clk_src; + return &clk_src->base; + } + + BREAK_TO_DEBUGGER(); + return NULL; +} + +void dce112_clock_source_destroy(struct clock_source **clk_src) +{ + dm_free(TO_DCE110_CLK_SRC(*clk_src)); + *clk_src = NULL; +} + +static void destruct(struct dce110_resource_pool *pool) +{ + unsigned int i; + + for (i = 0; i < pool->base.pipe_count; i++) { + if (pool->base.opps[i] != NULL) + dce112_opp_destroy(&pool->base.opps[i]); + + if (pool->base.transforms[i] != NULL) + dce112_transform_destroy(&pool->base.transforms[i]); + + if (pool->base.ipps[i] != NULL) + dce112_ipp_destroy(&pool->base.ipps[i]); + + if (pool->base.mis[i] != NULL) { + dm_free(TO_DCE110_MEM_INPUT(pool->base.mis[i])); + pool->base.mis[i] = NULL; + } + + if (pool->base.timing_generators[i] != NULL) { + dm_free(DCE110TG_FROM_TG(pool->base.timing_generators[i])); + pool->base.timing_generators[i] = NULL; + } + } + + for (i = 0; i < pool->base.stream_enc_count; i++) { + if (pool->base.stream_enc[i] != NULL) + dm_free(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); + } + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] != NULL) { + dce112_clock_source_destroy(&pool->base.clock_sources[i]); + } + } + + if (pool->base.dp_clock_source != NULL) + dce112_clock_source_destroy(&pool->base.dp_clock_source); + + for (i = 0; i < pool->base.audio_count; i++) { + if (pool->base.audios[i] != NULL) { + dce_aud_destroy(&pool->base.audios[i]); + } + } + + if (pool->base.display_clock != NULL) { + dal_display_clock_destroy(&pool->base.display_clock); + } + + if (pool->base.irqs != NULL) { + dal_irq_service_destroy(&pool->base.irqs); + } +} + +static struct clock_source *find_matching_pll(struct resource_context *res_ctx, + const struct core_stream *const stream) +{ + switch (stream->sink->link->link_enc->transmitter) { + case TRANSMITTER_UNIPHY_A: + return res_ctx->pool->clock_sources[DCE112_CLK_SRC_PLL0]; + case TRANSMITTER_UNIPHY_B: + return res_ctx->pool->clock_sources[DCE112_CLK_SRC_PLL1]; + case TRANSMITTER_UNIPHY_C: + return res_ctx->pool->clock_sources[DCE112_CLK_SRC_PLL2]; + case TRANSMITTER_UNIPHY_D: + return res_ctx->pool->clock_sources[DCE112_CLK_SRC_PLL3]; + case TRANSMITTER_UNIPHY_E: + return res_ctx->pool->clock_sources[DCE112_CLK_SRC_PLL4]; + case TRANSMITTER_UNIPHY_F: + return res_ctx->pool->clock_sources[DCE112_CLK_SRC_PLL5]; + default: + return NULL; + }; + + return 0; +} + +static enum dc_status validate_mapped_resource( + const struct core_dc *dc, + struct validate_context *context) +{ + enum dc_status status = DC_OK; + uint8_t i, j, k; + + for (i = 0; i < context->target_count; i++) { + struct core_target *target = context->targets[i]; + + for (j = 0; j < target->public.stream_count; j++) { + struct core_stream *stream = + DC_STREAM_TO_CORE(target->public.streams[j]); + struct core_link *link = stream->sink->link; + + if (resource_is_stream_unchanged(dc->current_context, stream)) + continue; + + for (k = 0; k < MAX_PIPES; k++) { + struct pipe_ctx *pipe_ctx = + &context->res_ctx.pipe_ctx[k]; + + if (context->res_ctx.pipe_ctx[k].stream != stream) + continue; + + if (!pipe_ctx->tg->funcs->validate_timing( + pipe_ctx->tg, &stream->public.timing)) + return DC_FAIL_CONTROLLER_VALIDATE; + + status = dce110_resource_build_pipe_hw_param(pipe_ctx); + + if (status != DC_OK) + return status; + + if (!link->link_enc->funcs->validate_output_with_stream( + link->link_enc, + pipe_ctx)) + return DC_FAIL_ENC_VALIDATE; + + /* TODO: validate audio ASIC caps, encoder */ + + status = dc_link_validate_mode_timing(stream, + link, + &stream->public.timing); + + if (status != DC_OK) + return status; + + resource_build_info_frame(pipe_ctx); + + /* do not need to validate non root pipes */ + break; + } + } + } + + return DC_OK; +} + +enum dc_status dce112_validate_bandwidth( + const struct core_dc *dc, + struct validate_context *context) +{ + enum dc_status result = DC_ERROR_UNEXPECTED; + + dm_logger_write( + dc->ctx->logger, LOG_BANDWIDTH_CALCS, + "%s: start", + __func__); + + if (!bw_calcs( + dc->ctx, + &dc->bw_dceip, + &dc->bw_vbios, + context->res_ctx.pipe_ctx, + context->res_ctx.pool->pipe_count, + &context->bw_results)) + result = DC_FAIL_BANDWIDTH_VALIDATE; + else + result = DC_OK; + + if (result == DC_FAIL_BANDWIDTH_VALIDATE) + dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_VALIDATION, + "%s: Bandwidth validation failed!", + __func__); + + if (memcmp(&dc->current_context->bw_results, + &context->bw_results, sizeof(context->bw_results))) { + struct log_entry log_entry; + dm_logger_open( + dc->ctx->logger, + &log_entry, + LOG_BANDWIDTH_CALCS); + dm_logger_append(&log_entry, "%s: finish,\n" + "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n" + "stutMark_b: %d stutMark_a: %d\n", + __func__, + context->bw_results.nbp_state_change_wm_ns[0].b_mark, + context->bw_results.nbp_state_change_wm_ns[0].a_mark, + context->bw_results.urgent_wm_ns[0].b_mark, + context->bw_results.urgent_wm_ns[0].a_mark, + context->bw_results.stutter_exit_wm_ns[0].b_mark, + context->bw_results.stutter_exit_wm_ns[0].a_mark); + dm_logger_append(&log_entry, + "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n" + "stutMark_b: %d stutMark_a: %d\n", + context->bw_results.nbp_state_change_wm_ns[1].b_mark, + context->bw_results.nbp_state_change_wm_ns[1].a_mark, + context->bw_results.urgent_wm_ns[1].b_mark, + context->bw_results.urgent_wm_ns[1].a_mark, + context->bw_results.stutter_exit_wm_ns[1].b_mark, + context->bw_results.stutter_exit_wm_ns[1].a_mark); + dm_logger_append(&log_entry, + "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n" + "stutMark_b: %d stutMark_a: %d stutter_mode_enable: %d\n", + context->bw_results.nbp_state_change_wm_ns[2].b_mark, + context->bw_results.nbp_state_change_wm_ns[2].a_mark, + context->bw_results.urgent_wm_ns[2].b_mark, + context->bw_results.urgent_wm_ns[2].a_mark, + context->bw_results.stutter_exit_wm_ns[2].b_mark, + context->bw_results.stutter_exit_wm_ns[2].a_mark, + context->bw_results.stutter_mode_enable); + dm_logger_append(&log_entry, + "cstate: %d pstate: %d nbpstate: %d sync: %d dispclk: %d\n" + "sclk: %d sclk_sleep: %d yclk: %d blackout_recovery_time_us: %d\n", + context->bw_results.cpuc_state_change_enable, + context->bw_results.cpup_state_change_enable, + context->bw_results.nbp_state_change_enable, + context->bw_results.all_displays_in_sync, + context->bw_results.dispclk_khz, + context->bw_results.required_sclk, + context->bw_results.required_sclk_deep_sleep, + context->bw_results.required_yclk, + context->bw_results.blackout_recovery_time_us); + dm_logger_close(&log_entry); + } + return result; +} + +enum dc_status resource_map_phy_clock_resources( + const struct core_dc *dc, + struct validate_context *context) +{ + uint8_t i, j, k; + + /* acquire new resources */ + for (i = 0; i < context->target_count; i++) { + struct core_target *target = context->targets[i]; + + for (j = 0; j < target->public.stream_count; j++) { + struct core_stream *stream = + DC_STREAM_TO_CORE(target->public.streams[j]); + + if (resource_is_stream_unchanged(dc->current_context, stream)) + continue; + + for (k = 0; k < MAX_PIPES; k++) { + struct pipe_ctx *pipe_ctx = + &context->res_ctx.pipe_ctx[k]; + + if (context->res_ctx.pipe_ctx[k].stream != stream) + continue; + + if (dc_is_dp_signal(pipe_ctx->stream->signal) + || pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL) + pipe_ctx->clock_source = + context->res_ctx.pool->dp_clock_source; + else + pipe_ctx->clock_source = + find_matching_pll(&context->res_ctx, + stream); + + if (pipe_ctx->clock_source == NULL) + return DC_NO_CLOCK_SOURCE_RESOURCE; + + resource_reference_clock_source( + &context->res_ctx, + pipe_ctx->clock_source); + + /* only one cs per stream regardless of mpo */ + break; + } + } + } + + return DC_OK; +} + +static bool dce112_validate_surface_sets( + const struct dc_validation_set set[], + int set_count) +{ + int i; + + for (i = 0; i < set_count; i++) { + if (set[i].surface_count == 0) + continue; + + if (set[i].surface_count > 1) + return false; + + if (set[i].surfaces[0]->clip_rect.width + != set[i].target->streams[0]->src.width + || set[i].surfaces[0]->clip_rect.height + != set[i].target->streams[0]->src.height) + return false; + if (set[i].surfaces[0]->format + >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) + return false; + } + + return true; +} + +enum dc_status dce112_validate_with_context( + const struct core_dc *dc, + const struct dc_validation_set set[], + int set_count, + struct validate_context *context) +{ + struct dc_context *dc_ctx = dc->ctx; + enum dc_status result = DC_ERROR_UNEXPECTED; + int i; + + if (!dce112_validate_surface_sets(set, set_count)) + return DC_FAIL_SURFACE_VALIDATE; + + context->res_ctx.pool = dc->res_pool; + + for (i = 0; i < set_count; i++) { + context->targets[i] = DC_TARGET_TO_CORE(set[i].target); + dc_target_retain(&context->targets[i]->public); + context->target_count++; + } + + result = resource_map_pool_resources(dc, context); + + if (result == DC_OK) + result = resource_map_phy_clock_resources(dc, context); + + if (!resource_validate_attach_surfaces( + set, set_count, dc->current_context, context)) { + DC_ERROR("Failed to attach surface to target!\n"); + return DC_FAIL_ATTACH_SURFACES; + } + + if (result == DC_OK) + result = validate_mapped_resource(dc, context); + + if (result == DC_OK) + result = resource_build_scaling_params_for_context(dc, context); + + if (result == DC_OK) + result = dce112_validate_bandwidth(dc, context); + + return result; +} + +enum dc_status dce112_validate_guaranteed( + const struct core_dc *dc, + const struct dc_target *dc_target, + struct validate_context *context) +{ + enum dc_status result = DC_ERROR_UNEXPECTED; + + context->res_ctx.pool = dc->res_pool; + + context->targets[0] = DC_TARGET_TO_CORE(dc_target); + dc_target_retain(&context->targets[0]->public); + context->target_count++; + + result = resource_map_pool_resources(dc, context); + + if (result == DC_OK) + result = resource_map_phy_clock_resources(dc, context); + + if (result == DC_OK) + result = validate_mapped_resource(dc, context); + + if (result == DC_OK) { + validate_guaranteed_copy_target( + context, dc->public.caps.max_targets); + result = resource_build_scaling_params_for_context(dc, context); + } + + if (result == DC_OK) + result = dce112_validate_bandwidth(dc, context); + + return result; +} + +static void dce112_destroy_resource_pool(struct resource_pool **pool) +{ + struct dce110_resource_pool *dce110_pool = TO_DCE110_RES_POOL(*pool); + + destruct(dce110_pool); + dm_free(dce110_pool); + *pool = NULL; +} + +static const struct resource_funcs dce112_res_pool_funcs = { + .destroy = dce112_destroy_resource_pool, + .link_enc_create = dce112_link_encoder_create, + .validate_with_context = dce112_validate_with_context, + .validate_guaranteed = dce112_validate_guaranteed, + .validate_bandwidth = dce112_validate_bandwidth +}; + +static void bw_calcs_data_update_from_pplib(struct core_dc *dc) +{ + struct dm_pp_clock_levels_with_latency eng_clks = {0}; + struct dm_pp_clock_levels_with_latency mem_clks = {0}; + struct dm_pp_wm_sets_with_clock_ranges clk_ranges = {0}; + struct dm_pp_clock_levels clks = {0}; + + /*do system clock TODO PPLIB: after PPLIB implement, + * then remove old way + */ + if (!dm_pp_get_clock_levels_by_type_with_latency( + dc->ctx, + DM_PP_CLOCK_TYPE_ENGINE_CLK, + &eng_clks)) { + + /* This is only for temporary */ + dm_pp_get_clock_levels_by_type( + dc->ctx, + DM_PP_CLOCK_TYPE_ENGINE_CLK, + &clks); + /* convert all the clock fro kHz to fix point mHz */ + dc->bw_vbios.high_sclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels-1], 1000); + dc->bw_vbios.mid1_sclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels/8], 1000); + dc->bw_vbios.mid2_sclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels*2/8], 1000); + dc->bw_vbios.mid3_sclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels*3/8], 1000); + dc->bw_vbios.mid4_sclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels*4/8], 1000); + dc->bw_vbios.mid5_sclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels*5/8], 1000); + dc->bw_vbios.mid6_sclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels*6/8], 1000); + dc->bw_vbios.low_sclk = bw_frc_to_fixed( + clks.clocks_in_khz[0], 1000); + + /*do memory clock*/ + dm_pp_get_clock_levels_by_type( + dc->ctx, + DM_PP_CLOCK_TYPE_MEMORY_CLK, + &clks); + + dc->bw_vbios.low_yclk = bw_frc_to_fixed( + clks.clocks_in_khz[0] * MEMORY_TYPE_MULTIPLIER, 1000); + dc->bw_vbios.mid_yclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels>>1] * MEMORY_TYPE_MULTIPLIER, + 1000); + dc->bw_vbios.high_yclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels-1] * MEMORY_TYPE_MULTIPLIER, + 1000); + + return; + } + + /* convert all the clock fro kHz to fix point mHz TODO: wloop data */ + dc->bw_vbios.high_sclk = bw_frc_to_fixed( + eng_clks.data[eng_clks.num_levels-1].clocks_in_khz, 1000); + dc->bw_vbios.mid1_sclk = bw_frc_to_fixed( + eng_clks.data[eng_clks.num_levels/8].clocks_in_khz, 1000); + dc->bw_vbios.mid2_sclk = bw_frc_to_fixed( + eng_clks.data[eng_clks.num_levels*2/8].clocks_in_khz, 1000); + dc->bw_vbios.mid3_sclk = bw_frc_to_fixed( + eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz, 1000); + dc->bw_vbios.mid4_sclk = bw_frc_to_fixed( + eng_clks.data[eng_clks.num_levels*4/8].clocks_in_khz, 1000); + dc->bw_vbios.mid5_sclk = bw_frc_to_fixed( + eng_clks.data[eng_clks.num_levels*5/8].clocks_in_khz, 1000); + dc->bw_vbios.mid6_sclk = bw_frc_to_fixed( + eng_clks.data[eng_clks.num_levels*6/8].clocks_in_khz, 1000); + dc->bw_vbios.low_sclk = bw_frc_to_fixed( + eng_clks.data[0].clocks_in_khz, 1000); + + /*do memory clock*/ + dm_pp_get_clock_levels_by_type_with_latency( + dc->ctx, + DM_PP_CLOCK_TYPE_MEMORY_CLK, + &mem_clks); + + /* we don't need to call PPLIB for validation clock since they + * also give us the highest sclk and highest mclk (UMA clock). + * ALSO always convert UMA clock (from PPLIB) to YCLK (HW formula): + * YCLK = UMACLK*m_memoryTypeMultiplier + */ + dc->bw_vbios.low_yclk = bw_frc_to_fixed( + mem_clks.data[0].clocks_in_khz * MEMORY_TYPE_MULTIPLIER, 1000); + dc->bw_vbios.mid_yclk = bw_frc_to_fixed( + mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz * MEMORY_TYPE_MULTIPLIER, + 1000); + dc->bw_vbios.high_yclk = bw_frc_to_fixed( + mem_clks.data[mem_clks.num_levels-1].clocks_in_khz * MEMORY_TYPE_MULTIPLIER, + 1000); + + /* Now notify PPLib/SMU about which Watermarks sets they should select + * depending on DPM state they are in. And update BW MGR GFX Engine and + * Memory clock member variables for Watermarks calculations for each + * Watermark Set + */ + clk_ranges.num_wm_sets = 4; + clk_ranges.wm_clk_ranges[0].wm_set_id = WM_SET_A; + clk_ranges.wm_clk_ranges[0].wm_min_eng_clk_in_khz = + eng_clks.data[0].clocks_in_khz; + clk_ranges.wm_clk_ranges[0].wm_max_eng_clk_in_khz = + eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz - 1; + clk_ranges.wm_clk_ranges[0].wm_min_memg_clk_in_khz = + mem_clks.data[0].clocks_in_khz; + clk_ranges.wm_clk_ranges[0].wm_max_mem_clk_in_khz = + mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz - 1; + + clk_ranges.wm_clk_ranges[1].wm_set_id = WM_SET_B; + clk_ranges.wm_clk_ranges[1].wm_min_eng_clk_in_khz = + eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz; + /* 5 GHz instead of data[7].clockInKHz to cover Overdrive */ + clk_ranges.wm_clk_ranges[1].wm_max_eng_clk_in_khz = 5000000; + clk_ranges.wm_clk_ranges[1].wm_min_memg_clk_in_khz = + mem_clks.data[0].clocks_in_khz; + clk_ranges.wm_clk_ranges[1].wm_max_mem_clk_in_khz = + mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz - 1; + + clk_ranges.wm_clk_ranges[2].wm_set_id = WM_SET_C; + clk_ranges.wm_clk_ranges[2].wm_min_eng_clk_in_khz = + eng_clks.data[0].clocks_in_khz; + clk_ranges.wm_clk_ranges[2].wm_max_eng_clk_in_khz = + eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz - 1; + clk_ranges.wm_clk_ranges[2].wm_min_memg_clk_in_khz = + mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz; + /* 5 GHz instead of data[2].clockInKHz to cover Overdrive */ + clk_ranges.wm_clk_ranges[2].wm_max_mem_clk_in_khz = 5000000; + + clk_ranges.wm_clk_ranges[3].wm_set_id = WM_SET_D; + clk_ranges.wm_clk_ranges[3].wm_min_eng_clk_in_khz = + eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz; + /* 5 GHz instead of data[7].clockInKHz to cover Overdrive */ + clk_ranges.wm_clk_ranges[3].wm_max_eng_clk_in_khz = 5000000; + clk_ranges.wm_clk_ranges[3].wm_min_memg_clk_in_khz = + mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz; + /* 5 GHz instead of data[2].clockInKHz to cover Overdrive */ + clk_ranges.wm_clk_ranges[3].wm_max_mem_clk_in_khz = 5000000; + + /* Notify PP Lib/SMU which Watermarks to use for which clock ranges */ + dm_pp_notify_wm_clock_changes(dc->ctx, &clk_ranges); +} + +const struct resource_caps *dce112_resource_cap( + struct hw_asic_id *asic_id) +{ + if (ASIC_REV_IS_POLARIS11_M(asic_id->hw_internal_rev)) + return &polaris_11_resource_cap; + else + return &polaris_10_resource_cap; +} + +static bool construct( + uint8_t num_virtual_links, + struct core_dc *dc, + struct dce110_resource_pool *pool) +{ + unsigned int i; + struct dc_context *ctx = dc->ctx; + struct dm_pp_static_clock_info static_clk_info = {0}; + + ctx->dc_bios->regs = &bios_regs; + + pool->base.res_cap = dce112_resource_cap(&ctx->asic_id); + pool->base.funcs = &dce112_res_pool_funcs; + + /************************************************* + * Resource + asic cap harcoding * + *************************************************/ + pool->base.underlay_pipe_index = -1; + pool->base.pipe_count = pool->base.res_cap->num_timing_generator; + dc->public.caps.max_downscale_ratio = 200; + dc->public.caps.i2c_speed_in_khz = 100; + + /************************************************* + * Create resources * + *************************************************/ + + pool->base.clock_sources[DCE112_CLK_SRC_PLL0] = + dce112_clock_source_create( + ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL0, + &clk_src_regs[0], false); + pool->base.clock_sources[DCE112_CLK_SRC_PLL1] = + dce112_clock_source_create( + ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL1, + &clk_src_regs[1], false); + pool->base.clock_sources[DCE112_CLK_SRC_PLL2] = + dce112_clock_source_create( + ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL2, + &clk_src_regs[2], false); + pool->base.clock_sources[DCE112_CLK_SRC_PLL3] = + dce112_clock_source_create( + ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL3, + &clk_src_regs[3], false); + pool->base.clock_sources[DCE112_CLK_SRC_PLL4] = + dce112_clock_source_create( + ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL4, + &clk_src_regs[4], false); + pool->base.clock_sources[DCE112_CLK_SRC_PLL5] = + dce112_clock_source_create( + ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL5, + &clk_src_regs[5], false); + pool->base.clk_src_count = DCE112_CLK_SRC_TOTAL; + + pool->base.dp_clock_source = dce112_clock_source_create( + ctx, ctx->dc_bios, + CLOCK_SOURCE_ID_DP_DTO, &clk_src_regs[0], true); + + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] == NULL) { + dm_error("DC: failed to create clock sources!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + } + + pool->base.display_clock = dal_display_clock_dce112_create( + ctx); + + if (pool->base.display_clock == NULL) { + dm_error("DC: failed to create display clock!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + + /* get static clock information for PPLIB or firmware, save + * max_clock_state + */ + if (dm_pp_get_static_clocks(ctx, &static_clk_info)) { + enum clocks_state max_clocks_state = + dce110_resource_convert_clock_state_pp_to_dc( + static_clk_info.max_clocks_state); + + dal_display_clock_store_max_clocks_state( + pool->base.display_clock, max_clocks_state); + } + + { + struct irq_service_init_data init_data; + init_data.ctx = dc->ctx; + pool->base.irqs = dal_irq_service_dce110_create(&init_data); + if (!pool->base.irqs) + goto res_create_fail; + } + + for (i = 0; i < pool->base.pipe_count; i++) { + pool->base.timing_generators[i] = + dce112_timing_generator_create( + ctx, + i, + &dce112_tg_offsets[i]); + if (pool->base.timing_generators[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create tg!\n"); + goto res_create_fail; + } + + pool->base.mis[i] = dce112_mem_input_create( + ctx, + i, + &dce112_mi_reg_offsets[i]); + if (pool->base.mis[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create memory input!\n"); + goto res_create_fail; + } + + pool->base.ipps[i] = dce112_ipp_create( + ctx, + i, + &ipp_reg_offsets[i]); + if (pool->base.ipps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create input pixel processor!\n"); + goto res_create_fail; + } + + pool->base.transforms[i] = dce112_transform_create(ctx, i); + if (pool->base.transforms[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create transform!\n"); + goto res_create_fail; + } + + pool->base.opps[i] = dce112_opp_create( + ctx, + i, + &dce112_opp_reg_offsets[i]); + if (pool->base.opps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create output pixel processor!\n"); + goto res_create_fail; + } + } + + if (!resource_construct(num_virtual_links, dc, &pool->base, + &res_create_funcs)) + goto res_create_fail; + + /* Create hardware sequencer */ + if (!dce112_hw_sequencer_construct(dc)) + goto res_create_fail; + + bw_calcs_init(&dc->bw_dceip, &dc->bw_vbios, BW_CALCS_VERSION_POLARIS11); + + bw_calcs_data_update_from_pplib(dc); + + return true; + +res_create_fail: + destruct(pool); + return false; +} + +struct resource_pool *dce112_create_resource_pool( + uint8_t num_virtual_links, + struct core_dc *dc) +{ + struct dce110_resource_pool *pool = + dm_alloc(sizeof(struct dce110_resource_pool)); + + if (!pool) + return NULL; + + if (construct(num_virtual_links, dc, pool)) + return &pool->base; + + BREAK_TO_DEBUGGER(); + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h new file mode 100644 index 000000000000..f21eb57857d4 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h @@ -0,0 +1,55 @@ +/* +* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_RESOURCE_DCE112_H__ +#define __DC_RESOURCE_DCE112_H__ + +#include "core_types.h" + +struct core_dc; +struct resource_pool; + +struct resource_pool *dce112_create_resource_pool( + uint8_t num_virtual_links, + struct core_dc *dc); + +enum dc_status dce112_validate_with_context( + const struct core_dc *dc, + const struct dc_validation_set set[], + int set_count, + struct validate_context *context); + +enum dc_status dce112_validate_guaranteed( + const struct core_dc *dc, + const struct dc_target *dc_target, + struct validate_context *context); + +enum dc_status dce112_validate_bandwidth( + const struct core_dc *dc, + struct validate_context *context); + + +#endif /* __DC_RESOURCE_DCE112_H__ */ + diff --git a/drivers/gpu/drm/amd/display/dc/dce80/Makefile b/drivers/gpu/drm/amd/display/dc/dce80/Makefile new file mode 100644 index 000000000000..9979b8441a8d --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce80/Makefile @@ -0,0 +1,16 @@ +# +# Makefile for the 'controller' sub-component of DAL. +# It provides the control and status of HW CRTC block. + +DCE80 = dce80_ipp.o dce80_ipp_gamma.o dce80_opp.o \ + dce80_opp_formatter.o dce80_opp_regamma.o \ + dce80_timing_generator.o dce80_opp_csc.o\ + dce80_compressor.o dce80_mem_input.o dce80_hw_sequencer.o \ + dce80_resource.o + +AMD_DAL_DCE80 = $(addprefix $(AMDDALPATH)/dc/dce80/,$(DCE80)) + +AMD_DISPLAY_FILES += $(AMD_DAL_DCE80) + + + diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.c new file mode 100644 index 000000000000..eeedb7c4fe53 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.c @@ -0,0 +1,839 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "dce/dce_8_0_d.h" +#include "dce/dce_8_0_sh_mask.h" +#include "gmc/gmc_7_1_sh_mask.h" +#include "gmc/gmc_7_1_d.h" + +#include "include/logger_interface.h" +#include "dce80_compressor.h" + +#define DCP_REG(reg)\ + (reg + cp80->offsets.dcp_offset) +#define DMIF_REG(reg)\ + (reg + cp80->offsets.dmif_offset) + +static const struct dce80_compressor_reg_offsets reg_offsets[] = { +{ + .dcp_offset = (mmDCP0_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), + .dmif_offset = (mmDMIF_PG0_DPG_PIPE_DPM_CONTROL + - mmDMIF_PG0_DPG_PIPE_DPM_CONTROL), +}, +{ + .dcp_offset = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), + .dmif_offset = (mmDMIF_PG1_DPG_PIPE_DPM_CONTROL + - mmDMIF_PG0_DPG_PIPE_DPM_CONTROL), +}, +{ + .dcp_offset = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), + .dmif_offset = (mmDMIF_PG2_DPG_PIPE_DPM_CONTROL + - mmDMIF_PG0_DPG_PIPE_DPM_CONTROL), +}, +{ + .dcp_offset = (mmDCP3_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), + .dmif_offset = (mmDMIF_PG3_DPG_PIPE_DPM_CONTROL + - mmDMIF_PG0_DPG_PIPE_DPM_CONTROL), +}, +{ + .dcp_offset = (mmDCP4_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), + .dmif_offset = (mmDMIF_PG4_DPG_PIPE_DPM_CONTROL + - mmDMIF_PG0_DPG_PIPE_DPM_CONTROL), +}, +{ + .dcp_offset = (mmDCP5_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), + .dmif_offset = (mmDMIF_PG5_DPG_PIPE_DPM_CONTROL + - mmDMIF_PG0_DPG_PIPE_DPM_CONTROL), +} +}; + +static const uint32_t dce8_one_lpt_channel_max_resolution = 2048 * 1200; + +enum fbc_idle_force { + /* Bit 0 - Display registers updated */ + FBC_IDLE_FORCE_DISPLAY_REGISTER_UPDATE = 0x00000001, + + /* Bit 2 - FBC_GRPH_COMP_EN register updated */ + FBC_IDLE_FORCE_GRPH_COMP_EN = 0x00000002, + /* Bit 3 - FBC_SRC_SEL register updated */ + FBC_IDLE_FORCE_SRC_SEL_CHANGE = 0x00000004, + /* Bit 4 - FBC_MIN_COMPRESSION register updated */ + FBC_IDLE_FORCE_MIN_COMPRESSION_CHANGE = 0x00000008, + /* Bit 5 - FBC_ALPHA_COMP_EN register updated */ + FBC_IDLE_FORCE_ALPHA_COMP_EN = 0x00000010, + /* Bit 6 - FBC_ZERO_ALPHA_CHUNK_SKIP_EN register updated */ + FBC_IDLE_FORCE_ZERO_ALPHA_CHUNK_SKIP_EN = 0x00000020, + /* Bit 7 - FBC_FORCE_COPY_TO_COMP_BUF register updated */ + FBC_IDLE_FORCE_FORCE_COPY_TO_COMP_BUF = 0x00000040, + + /* Bit 24 - Memory write to region 0 defined by MC registers. */ + FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION0 = 0x01000000, + /* Bit 25 - Memory write to region 1 defined by MC registers */ + FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION1 = 0x02000000, + /* Bit 26 - Memory write to region 2 defined by MC registers */ + FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION2 = 0x04000000, + /* Bit 27 - Memory write to region 3 defined by MC registers. */ + FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION3 = 0x08000000, + + /* Bit 28 - Memory write from any client other than MCIF */ + FBC_IDLE_FORCE_MEMORY_WRITE_OTHER_THAN_MCIF = 0x10000000, + /* Bit 29 - CG statics screen signal is inactive */ + FBC_IDLE_FORCE_CG_STATIC_SCREEN_IS_INACTIVE = 0x20000000, +}; + +static uint32_t lpt_size_alignment(struct dce80_compressor *cp80) +{ + /*LPT_ALIGNMENT (in bytes) = ROW_SIZE * #BANKS * # DRAM CHANNELS. */ + return cp80->base.raw_size * cp80->base.banks_num * + cp80->base.dram_channels_num; +} + +static uint32_t lpt_memory_control_config(struct dce80_compressor *cp80, + uint32_t lpt_control) +{ + /*LPT MC Config */ + if (cp80->base.options.bits.LPT_MC_CONFIG == 1) { + /* POSSIBLE VALUES for LPT NUM_PIPES (DRAM CHANNELS): + * 00 - 1 CHANNEL + * 01 - 2 CHANNELS + * 02 - 4 OR 6 CHANNELS + * (Only for discrete GPU, N/A for CZ) + * 03 - 8 OR 12 CHANNELS + * (Only for discrete GPU, N/A for CZ) */ + switch (cp80->base.dram_channels_num) { + case 2: + set_reg_field_value( + lpt_control, + 1, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_NUM_PIPES); + break; + case 1: + set_reg_field_value( + lpt_control, + 0, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_NUM_PIPES); + break; + default: + dm_logger_write( + cp80->base.ctx->logger, LOG_WARNING, + "%s: Invalid LPT NUM_PIPES!!!", + __func__); + break; + } + + /* The mapping for LPT NUM_BANKS is in + * GRPH_CONTROL.GRPH_NUM_BANKS register field + * Specifies the number of memory banks for tiling + * purposes. Only applies to 2D and 3D tiling modes. + * POSSIBLE VALUES: + * 00 - DCP_GRPH_NUM_BANKS_2BANK: ADDR_SURF_2_BANK + * 01 - DCP_GRPH_NUM_BANKS_4BANK: ADDR_SURF_4_BANK + * 02 - DCP_GRPH_NUM_BANKS_8BANK: ADDR_SURF_8_BANK + * 03 - DCP_GRPH_NUM_BANKS_16BANK: ADDR_SURF_16_BANK */ + switch (cp80->base.banks_num) { + case 16: + set_reg_field_value( + lpt_control, + 3, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_NUM_BANKS); + break; + case 8: + set_reg_field_value( + lpt_control, + 2, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_NUM_BANKS); + break; + case 4: + set_reg_field_value( + lpt_control, + 1, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_NUM_BANKS); + break; + case 2: + set_reg_field_value( + lpt_control, + 0, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_NUM_BANKS); + break; + default: + dm_logger_write( + cp80->base.ctx->logger, LOG_WARNING, + "%s: Invalid LPT NUM_BANKS!!!", + __func__); + break; + } + + /* The mapping is in DMIF_ADDR_CALC. + * ADDR_CONFIG_PIPE_INTERLEAVE_SIZE register field for + * Carrizo specifies the memory interleave per pipe. + * It effectively specifies the location of pipe bits in + * the memory address. + * POSSIBLE VALUES: + * 00 - ADDR_CONFIG_PIPE_INTERLEAVE_256B: 256 byte + * interleave + * 01 - ADDR_CONFIG_PIPE_INTERLEAVE_512B: 512 byte + * interleave + */ + switch (cp80->base.channel_interleave_size) { + case 256: /*256B */ + set_reg_field_value( + lpt_control, + 0, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_PIPE_INTERLEAVE_SIZE); + break; + case 512: /*512B */ + set_reg_field_value( + lpt_control, + 1, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_PIPE_INTERLEAVE_SIZE); + break; + default: + dm_logger_write( + cp80->base.ctx->logger, LOG_WARNING, + "%s: Invalid LPT INTERLEAVE_SIZE!!!", + __func__); + break; + } + + /* The mapping for LOW_POWER_TILING_ROW_SIZE is in + * DMIF_ADDR_CALC.ADDR_CONFIG_ROW_SIZE register field + * for Carrizo. Specifies the size of dram row in bytes. + * This should match up with NOOFCOLS field in + * MC_ARB_RAMCFG (ROW_SIZE = 4 * 2 ^^ columns). + * This register DMIF_ADDR_CALC is not used by the + * hardware as it is only used for addrlib assertions. + * POSSIBLE VALUES: + * 00 - ADDR_CONFIG_1KB_ROW: Treat 1KB as DRAM row + * boundary + * 01 - ADDR_CONFIG_2KB_ROW: Treat 2KB as DRAM row + * boundary + * 02 - ADDR_CONFIG_4KB_ROW: Treat 4KB as DRAM row + * boundary */ + switch (cp80->base.raw_size) { + case 4096: /*4 KB */ + set_reg_field_value( + lpt_control, + 2, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_ROW_SIZE); + break; + case 2048: + set_reg_field_value( + lpt_control, + 1, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_ROW_SIZE); + break; + case 1024: + set_reg_field_value( + lpt_control, + 0, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_ROW_SIZE); + break; + default: + dm_logger_write( + cp80->base.ctx->logger, LOG_WARNING, + "%s: Invalid LPT ROW_SIZE!!!", + __func__); + break; + } + } else { + dm_logger_write( + cp80->base.ctx->logger, LOG_WARNING, + "%s: LPT MC Configuration is not provided", + __func__); + } + + return lpt_control; +} + +static bool is_source_bigger_than_epanel_size( + struct dce80_compressor *cp80, + uint32_t source_view_width, + uint32_t source_view_height) +{ + if (cp80->base.embedded_panel_h_size != 0 && + cp80->base.embedded_panel_v_size != 0 && + ((source_view_width * source_view_height) > + (cp80->base.embedded_panel_h_size * + cp80->base.embedded_panel_v_size))) + return true; + + return false; +} + +static uint32_t align_to_chunks_number_per_line( + struct dce80_compressor *cp80, + uint32_t pixels) +{ + return 256 * ((pixels + 255) / 256); +} + +static void wait_for_fbc_state_changed( + struct dce80_compressor *cp80, + bool enabled) +{ + uint8_t counter = 0; + uint32_t addr = mmFBC_STATUS; + uint32_t value; + + while (counter < 10) { + value = dm_read_reg(cp80->base.ctx, addr); + if (get_reg_field_value( + value, + FBC_STATUS, + FBC_ENABLE_STATUS) == enabled) + break; + udelay(10); + counter++; + } + + if (counter == 10) { + dm_logger_write( + cp80->base.ctx->logger, LOG_WARNING, + "%s: wait counter exceeded, changes to HW not applied", + __func__); + } +} + +void dce80_compressor_power_up_fbc(struct compressor *compressor) +{ + uint32_t value; + uint32_t addr; + + addr = mmFBC_CNTL; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value(value, 0, FBC_CNTL, FBC_GRPH_COMP_EN); + set_reg_field_value(value, 1, FBC_CNTL, FBC_EN); + set_reg_field_value(value, 2, FBC_CNTL, FBC_COHERENCY_MODE); + dm_write_reg(compressor->ctx, addr, value); + + addr = mmFBC_COMP_MODE; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value(value, 1, FBC_COMP_MODE, FBC_RLE_EN); + set_reg_field_value(value, 1, FBC_COMP_MODE, FBC_DPCM4_RGB_EN); + set_reg_field_value(value, 1, FBC_COMP_MODE, FBC_IND_EN); + dm_write_reg(compressor->ctx, addr, value); + + addr = mmFBC_COMP_CNTL; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value(value, 1, FBC_COMP_CNTL, FBC_DEPTH_RGB08_EN); + dm_write_reg(compressor->ctx, addr, value); + /*FBC_MIN_COMPRESSION 0 ==> 2:1 */ + /* 1 ==> 4:1 */ + /* 2 ==> 8:1 */ + /* 0xF ==> 1:1 */ + set_reg_field_value(value, 0xF, FBC_COMP_CNTL, FBC_MIN_COMPRESSION); + dm_write_reg(compressor->ctx, addr, value); + compressor->min_compress_ratio = FBC_COMPRESS_RATIO_1TO1; + + value = 0; + dm_write_reg(compressor->ctx, mmFBC_IND_LUT0, value); + + value = 0xFFFFFF; + dm_write_reg(compressor->ctx, mmFBC_IND_LUT1, value); +} + +void dce80_compressor_enable_fbc( + struct compressor *compressor, + uint32_t paths_num, + struct compr_addr_and_pitch_params *params) +{ + struct dce80_compressor *cp80 = TO_DCE80_COMPRESSOR(compressor); + + if (compressor->options.bits.FBC_SUPPORT && + (compressor->options.bits.DUMMY_BACKEND == 0) && + (!dce80_compressor_is_fbc_enabled_in_hw(compressor, NULL)) && + (!is_source_bigger_than_epanel_size( + cp80, + params->source_view_width, + params->source_view_height))) { + + uint32_t addr; + uint32_t value; + + /* Before enabling FBC first need to enable LPT if applicable + * LPT state should always be changed (enable/disable) while FBC + * is disabled */ + if (compressor->options.bits.LPT_SUPPORT && (paths_num < 2) && + (params->source_view_width * + params->source_view_height <= + dce8_one_lpt_channel_max_resolution)) { + dce80_compressor_enable_lpt(compressor); + } + + addr = mmFBC_CNTL; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value(value, 1, FBC_CNTL, FBC_GRPH_COMP_EN); + set_reg_field_value( + value, + params->inst, + FBC_CNTL, FBC_SRC_SEL); + dm_write_reg(compressor->ctx, addr, value); + + /* Keep track of enum controller_id FBC is attached to */ + compressor->is_enabled = true; + compressor->attached_inst = params->inst; + cp80->offsets = reg_offsets[params->inst - 1]; + + /*Toggle it as there is bug in HW */ + set_reg_field_value(value, 0, FBC_CNTL, FBC_GRPH_COMP_EN); + dm_write_reg(compressor->ctx, addr, value); + set_reg_field_value(value, 1, FBC_CNTL, FBC_GRPH_COMP_EN); + dm_write_reg(compressor->ctx, addr, value); + + wait_for_fbc_state_changed(cp80, true); + } +} + +void dce80_compressor_disable_fbc(struct compressor *compressor) +{ + struct dce80_compressor *cp80 = TO_DCE80_COMPRESSOR(compressor); + + if (compressor->options.bits.FBC_SUPPORT && + dce80_compressor_is_fbc_enabled_in_hw(compressor, NULL)) { + uint32_t reg_data; + /* Turn off compression */ + reg_data = dm_read_reg(compressor->ctx, mmFBC_CNTL); + set_reg_field_value(reg_data, 0, FBC_CNTL, FBC_GRPH_COMP_EN); + dm_write_reg(compressor->ctx, mmFBC_CNTL, reg_data); + + /* Reset enum controller_id to undefined */ + compressor->attached_inst = 0; + compressor->is_enabled = false; + + /* Whenever disabling FBC make sure LPT is disabled if LPT + * supported */ + if (compressor->options.bits.LPT_SUPPORT) + dce80_compressor_disable_lpt(compressor); + + wait_for_fbc_state_changed(cp80, false); + } +} + +bool dce80_compressor_is_fbc_enabled_in_hw( + struct compressor *compressor, + uint32_t *inst) +{ + /* Check the hardware register */ + uint32_t value; + + value = dm_read_reg(compressor->ctx, mmFBC_STATUS); + if (get_reg_field_value(value, FBC_STATUS, FBC_ENABLE_STATUS)) { + if (inst != NULL) + *inst = compressor->attached_inst; + return true; + } + + value = dm_read_reg(compressor->ctx, mmFBC_CNTL); + if (get_reg_field_value(value, FBC_CNTL, FBC_GRPH_COMP_EN)) { + if (inst != NULL) + *inst = compressor->attached_inst; + return true; + } + + return false; +} + +bool dce80_compressor_is_lpt_enabled_in_hw(struct compressor *compressor) +{ + /* Check the hardware register */ + uint32_t value = dm_read_reg(compressor->ctx, + mmLOW_POWER_TILING_CONTROL); + + return get_reg_field_value( + value, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_ENABLE); +} + +void dce80_compressor_program_compressed_surface_address_and_pitch( + struct compressor *compressor, + struct compr_addr_and_pitch_params *params) +{ + struct dce80_compressor *cp80 = TO_DCE80_COMPRESSOR(compressor); + uint32_t value = 0; + uint32_t fbc_pitch = 0; + uint32_t compressed_surf_address_low_part = + compressor->compr_surface_address.addr.low_part; + + /* Clear content first. */ + dm_write_reg( + compressor->ctx, + DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS_HIGH), + 0); + dm_write_reg(compressor->ctx, + DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS), 0); + + if (compressor->options.bits.LPT_SUPPORT) { + uint32_t lpt_alignment = lpt_size_alignment(cp80); + + if (lpt_alignment != 0) { + compressed_surf_address_low_part = + ((compressed_surf_address_low_part + + (lpt_alignment - 1)) / lpt_alignment) + * lpt_alignment; + } + } + + /* Write address, HIGH has to be first. */ + dm_write_reg(compressor->ctx, + DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS_HIGH), + compressor->compr_surface_address.addr.high_part); + dm_write_reg(compressor->ctx, + DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS), + compressed_surf_address_low_part); + + fbc_pitch = align_to_chunks_number_per_line( + cp80, + params->source_view_width); + + if (compressor->min_compress_ratio == FBC_COMPRESS_RATIO_1TO1) + fbc_pitch = fbc_pitch / 8; + else + dm_logger_write( + compressor->ctx->logger, LOG_WARNING, + "%s: Unexpected DCE8 compression ratio", + __func__); + + /* Clear content first. */ + dm_write_reg(compressor->ctx, DCP_REG(mmGRPH_COMPRESS_PITCH), 0); + + /* Write FBC Pitch. */ + set_reg_field_value( + value, + fbc_pitch, + GRPH_COMPRESS_PITCH, + GRPH_COMPRESS_PITCH); + dm_write_reg(compressor->ctx, DCP_REG(mmGRPH_COMPRESS_PITCH), value); + +} + +void dce80_compressor_disable_lpt(struct compressor *compressor) +{ + struct dce80_compressor *cp80 = TO_DCE80_COMPRESSOR(compressor); + uint32_t value; + uint32_t addr; + uint32_t inx; + + /* Disable all pipes LPT Stutter */ + for (inx = 0; inx < 3; inx++) { + value = + dm_read_reg( + compressor->ctx, + DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH)); + set_reg_field_value( + value, + 0, + DPG_PIPE_STUTTER_CONTROL_NONLPTCH, + STUTTER_ENABLE_NONLPTCH); + dm_write_reg( + compressor->ctx, + DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH), + value); + } + + /* Disable LPT */ + addr = mmLOW_POWER_TILING_CONTROL; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value( + value, + 0, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_ENABLE); + dm_write_reg(compressor->ctx, addr, value); + + /* Clear selection of Channel(s) containing Compressed Surface */ + addr = mmGMCON_LPT_TARGET; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value( + value, + 0xFFFFFFFF, + GMCON_LPT_TARGET, + STCTRL_LPT_TARGET); + dm_write_reg(compressor->ctx, mmGMCON_LPT_TARGET, value); +} + +void dce80_compressor_enable_lpt(struct compressor *compressor) +{ + struct dce80_compressor *cp80 = TO_DCE80_COMPRESSOR(compressor); + uint32_t value; + uint32_t addr; + uint32_t value_control; + uint32_t channels; + + /* Enable LPT Stutter from Display pipe */ + value = dm_read_reg(compressor->ctx, + DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH)); + set_reg_field_value( + value, + 1, + DPG_PIPE_STUTTER_CONTROL_NONLPTCH, + STUTTER_ENABLE_NONLPTCH); + dm_write_reg(compressor->ctx, + DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH), value); + + /* Selection of Channel(s) containing Compressed Surface: 0xfffffff + * will disable LPT. + * STCTRL_LPT_TARGETn corresponds to channel n. */ + addr = mmLOW_POWER_TILING_CONTROL; + value_control = dm_read_reg(compressor->ctx, addr); + channels = get_reg_field_value(value_control, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_MODE); + + addr = mmGMCON_LPT_TARGET; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value( + value, + channels + 1, /* not mentioned in programming guide, + but follow DCE8.1 */ + GMCON_LPT_TARGET, + STCTRL_LPT_TARGET); + dm_write_reg(compressor->ctx, addr, value); + + /* Enable LPT */ + addr = mmLOW_POWER_TILING_CONTROL; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value( + value, + 1, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_ENABLE); + dm_write_reg(compressor->ctx, addr, value); +} + +void dce80_compressor_program_lpt_control( + struct compressor *compressor, + struct compr_addr_and_pitch_params *params) +{ + struct dce80_compressor *cp80 = TO_DCE80_COMPRESSOR(compressor); + uint32_t rows_per_channel; + uint32_t lpt_alignment; + uint32_t source_view_width; + uint32_t source_view_height; + uint32_t lpt_control = 0; + + if (!compressor->options.bits.LPT_SUPPORT) + return; + + lpt_control = dm_read_reg(compressor->ctx, + mmLOW_POWER_TILING_CONTROL); + + /* POSSIBLE VALUES for Low Power Tiling Mode: + * 00 - Use channel 0 + * 01 - Use Channel 0 and 1 + * 02 - Use Channel 0,1,2,3 + * 03 - reserved */ + switch (compressor->lpt_channels_num) { + /* case 2: + * Use Channel 0 & 1 / Not used for DCE 11 */ + case 1: + /*Use Channel 0 for LPT for DCE 11 */ + set_reg_field_value( + lpt_control, + 0, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_MODE); + break; + default: + dm_logger_write( + compressor->ctx->logger, LOG_WARNING, + "%s: Invalid selected DRAM channels for LPT!!!", + __func__); + break; + } + + lpt_control = lpt_memory_control_config(cp80, lpt_control); + + /* Program LOW_POWER_TILING_ROWS_PER_CHAN field which depends on + * FBC compressed surface pitch. + * LOW_POWER_TILING_ROWS_PER_CHAN = Roundup ((Surface Height * + * Surface Pitch) / (Row Size * Number of Channels * + * Number of Banks)). */ + rows_per_channel = 0; + lpt_alignment = lpt_size_alignment(cp80); + source_view_width = + align_to_chunks_number_per_line( + cp80, + params->source_view_width); + source_view_height = (params->source_view_height + 1) & (~0x1); + + if (lpt_alignment != 0) { + rows_per_channel = source_view_width * source_view_height * 4; + rows_per_channel = + (rows_per_channel % lpt_alignment) ? + (rows_per_channel / lpt_alignment + 1) : + rows_per_channel / lpt_alignment; + } + + set_reg_field_value( + lpt_control, + rows_per_channel, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_ROWS_PER_CHAN); + + dm_write_reg(compressor->ctx, + mmLOW_POWER_TILING_CONTROL, lpt_control); +} + +/* + * DCE 11 Frame Buffer Compression Implementation + */ + +void dce80_compressor_set_fbc_invalidation_triggers( + struct compressor *compressor, + uint32_t fbc_trigger) +{ + /* Disable region hit event, FBC_MEMORY_REGION_MASK = 0 (bits 16-19) + * for DCE 11 regions cannot be used - does not work with S/G + */ + uint32_t addr = mmFBC_CLIENT_REGION_MASK; + uint32_t value = dm_read_reg(compressor->ctx, addr); + + set_reg_field_value( + value, + 0, + FBC_CLIENT_REGION_MASK, + FBC_MEMORY_REGION_MASK); + dm_write_reg(compressor->ctx, addr, value); + + /* Setup events when to clear all CSM entries (effectively marking + * current compressed data invalid) + * For DCE 11 CSM metadata 11111 means - "Not Compressed" + * Used as the initial value of the metadata sent to the compressor + * after invalidation, to indicate that the compressor should attempt + * to compress all chunks on the current pass. Also used when the chunk + * is not successfully written to memory. + * When this CSM value is detected, FBC reads from the uncompressed + * buffer. Set events according to passed in value, these events are + * valid for DCE8: + * - bit 0 - display register updated + * - bit 28 - memory write from any client except from MCIF + * - bit 29 - CG static screen signal is inactive + * In addition, DCE8.1 also needs to set new DCE8.1 specific events + * that are used to trigger invalidation on certain register changes, + * for example enabling of Alpha Compression may trigger invalidation of + * FBC once bit is set. These events are as follows: + * - Bit 2 - FBC_GRPH_COMP_EN register updated + * - Bit 3 - FBC_SRC_SEL register updated + * - Bit 4 - FBC_MIN_COMPRESSION register updated + * - Bit 5 - FBC_ALPHA_COMP_EN register updated + * - Bit 6 - FBC_ZERO_ALPHA_CHUNK_SKIP_EN register updated + * - Bit 7 - FBC_FORCE_COPY_TO_COMP_BUF register updated + */ + addr = mmFBC_IDLE_FORCE_CLEAR_MASK; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value( + value, + fbc_trigger | + FBC_IDLE_FORCE_GRPH_COMP_EN | + FBC_IDLE_FORCE_SRC_SEL_CHANGE | + FBC_IDLE_FORCE_MIN_COMPRESSION_CHANGE | + FBC_IDLE_FORCE_ALPHA_COMP_EN | + FBC_IDLE_FORCE_ZERO_ALPHA_CHUNK_SKIP_EN | + FBC_IDLE_FORCE_FORCE_COPY_TO_COMP_BUF, + FBC_IDLE_FORCE_CLEAR_MASK, + FBC_IDLE_FORCE_CLEAR_MASK); + dm_write_reg(compressor->ctx, addr, value); +} + +bool dce80_compressor_construct(struct dce80_compressor *compressor, + struct dc_context *ctx) +{ + struct dc_bios *bp = ctx->dc_bios; + struct embedded_panel_info panel_info; + + compressor->base.options.bits.FBC_SUPPORT = true; + compressor->base.options.bits.LPT_SUPPORT = true; + /* For DCE 11 always use one DRAM channel for LPT */ + compressor->base.lpt_channels_num = 1; + compressor->base.options.bits.DUMMY_BACKEND = false; + + /* Check if this system has more than 1 DRAM channel; if only 1 then LPT + * should not be supported */ + if (compressor->base.memory_bus_width == 64) + compressor->base.options.bits.LPT_SUPPORT = false; + + compressor->base.options.bits.CLK_GATING_DISABLED = false; + + compressor->base.ctx = ctx; + compressor->base.embedded_panel_h_size = 0; + compressor->base.embedded_panel_v_size = 0; + compressor->base.memory_bus_width = ctx->asic_id.vram_width; + compressor->base.allocated_size = 0; + compressor->base.preferred_requested_size = 0; + compressor->base.min_compress_ratio = FBC_COMPRESS_RATIO_INVALID; + compressor->base.options.raw = 0; + compressor->base.banks_num = 0; + compressor->base.raw_size = 0; + compressor->base.channel_interleave_size = 0; + compressor->base.dram_channels_num = 0; + compressor->base.lpt_channels_num = 0; + compressor->base.attached_inst = 0; + compressor->base.is_enabled = false; + + if (BP_RESULT_OK == + bp->funcs->get_embedded_panel_info(bp, &panel_info)) { + compressor->base.embedded_panel_h_size = + panel_info.lcd_timing.horizontal_addressable; + compressor->base.embedded_panel_v_size = + panel_info.lcd_timing.vertical_addressable; + } + return true; +} + +struct compressor *dce80_compressor_create(struct dc_context *ctx) +{ + struct dce80_compressor *cp80 = + dm_alloc(sizeof(struct dce80_compressor)); + + if (!cp80) + return NULL; + + if (dce80_compressor_construct(cp80, ctx)) + return &cp80->base; + + BREAK_TO_DEBUGGER(); + dm_free(cp80); + return NULL; +} + +void dce80_compressor_destroy(struct compressor **compressor) +{ + dm_free(TO_DCE80_COMPRESSOR(*compressor)); + *compressor = NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.h b/drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.h new file mode 100644 index 000000000000..01290969ff92 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.h @@ -0,0 +1,78 @@ +/* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_COMPRESSOR_DCE80_H__ +#define __DC_COMPRESSOR_DCE80_H__ + +#include "../inc/compressor.h" + +#define TO_DCE80_COMPRESSOR(compressor)\ + container_of(compressor, struct dce80_compressor, base) + +struct dce80_compressor_reg_offsets { + uint32_t dcp_offset; + uint32_t dmif_offset; +}; + +struct dce80_compressor { + struct compressor base; + struct dce80_compressor_reg_offsets offsets; +}; + +struct compressor *dce80_compressor_create(struct dc_context *ctx); + +bool dce80_compressor_construct(struct dce80_compressor *cp80, + struct dc_context *ctx); + +void dce80_compressor_destroy(struct compressor **cp); + +/* FBC RELATED */ +void dce80_compressor_power_up_fbc(struct compressor *cp); + +void dce80_compressor_enable_fbc(struct compressor *cp, uint32_t paths_num, + struct compr_addr_and_pitch_params *params); + +void dce80_compressor_disable_fbc(struct compressor *cp); + +void dce80_compressor_set_fbc_invalidation_triggers(struct compressor *cp, + uint32_t fbc_trigger); + +void dce80_compressor_program_compressed_surface_address_and_pitch( + struct compressor *cp, + struct compr_addr_and_pitch_params *params); + +bool dce80_compressor_is_fbc_enabled_in_hw(struct compressor *cp, + uint32_t *fbc_mapped_crtc_id); + +/* LPT RELATED */ +void dce80_compressor_enable_lpt(struct compressor *cp); + +void dce80_compressor_disable_lpt(struct compressor *cp); + +void dce80_compressor_program_lpt_control(struct compressor *cp, + struct compr_addr_and_pitch_params *params); + +bool dce80_compressor_is_lpt_enabled_in_hw(struct compressor *cp); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c new file mode 100644 index 000000000000..c7a2b768bcd1 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c @@ -0,0 +1,141 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "dc.h" +#include "core_dc.h" +#include "core_types.h" +#include "dce80_hw_sequencer.h" + +#include "dce/dce_hwseq.h" +#include "dce110/dce110_hw_sequencer.h" + +/* include DCE8 register header files */ +#include "dce/dce_8_0_d.h" +#include "dce/dce_8_0_sh_mask.h" + +struct dce80_hw_seq_reg_offsets { + uint32_t crtc; +}; + +static const struct dce80_hw_seq_reg_offsets reg_offsets[] = { +{ + .crtc = (mmCRTC0_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), +}, +{ + .crtc = (mmCRTC1_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), +}, +{ + .crtc = (mmCRTC2_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), +}, +{ + .crtc = (mmCRTC3_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), +}, +{ + .crtc = (mmCRTC4_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), +}, +{ + .crtc = (mmCRTC5_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), +} +}; + +#define HW_REG_CRTC(reg, id)\ + (reg + reg_offsets[id].crtc) + +/******************************************************************************* + * Private definitions + ******************************************************************************/ + +/***************************PIPE_CONTROL***********************************/ + +static bool dce80_enable_display_power_gating( + struct core_dc *dc, + uint8_t controller_id, + struct dc_bios *dcb, + enum pipe_gating_control power_gating) +{ + enum bp_result bp_result = BP_RESULT_OK; + enum bp_pipe_control_action cntl; + struct dc_context *ctx = dc->ctx; + + if (power_gating == PIPE_GATING_CONTROL_INIT) + cntl = ASIC_PIPE_INIT; + else if (power_gating == PIPE_GATING_CONTROL_ENABLE) + cntl = ASIC_PIPE_ENABLE; + else + cntl = ASIC_PIPE_DISABLE; + + if (!(power_gating == PIPE_GATING_CONTROL_INIT && controller_id != 0)){ + + bp_result = dcb->funcs->enable_disp_power_gating( + dcb, controller_id + 1, cntl); + + /* Revert MASTER_UPDATE_MODE to 0 because bios sets it 2 + * by default when command table is called + */ + dm_write_reg(ctx, + HW_REG_CRTC(mmMASTER_UPDATE_MODE, controller_id), + 0); + } + + if (bp_result == BP_RESULT_OK) + return true; + else + return false; +} + + +static void set_display_mark_for_pipe_if_needed(struct core_dc *dc, + struct pipe_ctx *pipe_ctx, + struct validate_context *context) +{ + /* Do nothing until we have proper bandwitdth calcs */ +} + +static void set_displaymarks( + const struct core_dc *dc, struct validate_context *context) +{ + /* Do nothing until we have proper bandwitdth calcs */ +} + +static void set_bandwidth(struct core_dc *dc) +{ + /* Do nothing until we have proper bandwitdth calcs */ +} + + +bool dce80_hw_sequencer_construct(struct core_dc *dc) +{ + dce110_hw_sequencer_construct(dc); + + dc->hwss.enable_display_power_gating = dce80_enable_display_power_gating; + dc->hwss.pipe_control_lock = dce_pipe_control_lock; + dc->hwss.set_displaymarks = set_displaymarks; + dc->hwss.increase_watermarks_for_pipe = set_display_mark_for_pipe_if_needed; + dc->hwss.set_bandwidth = set_bandwidth; + + return true; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.h new file mode 100644 index 000000000000..7cc203f433d3 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.h @@ -0,0 +1,36 @@ +/* +* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_HWSS_DCE80_H__ +#define __DC_HWSS_DCE80_H__ + +#include "core_types.h" + +struct core_dc; + +bool dce80_hw_sequencer_construct(struct core_dc *dc); + +#endif /* __DC_HWSS_DCE80_H__ */ + diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.c new file mode 100644 index 000000000000..86826c229d39 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.c @@ -0,0 +1,64 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "include/logger_interface.h" + +#include "dce/dce_8_0_d.h" +#include "dce/dce_8_0_sh_mask.h" + +#include "dce80_ipp.h" + +#include "dce110/dce110_ipp.h" + +static const struct ipp_funcs funcs = { + .ipp_cursor_set_attributes = dce110_ipp_cursor_set_attributes, + .ipp_cursor_set_position = dce110_ipp_cursor_set_position, + .ipp_program_prescale = dce110_ipp_program_prescale, + .ipp_set_degamma = dce110_ipp_set_degamma, +}; + +bool dce80_ipp_construct( + struct dce110_ipp *ipp, + struct dc_context *ctx, + uint32_t inst, + const struct dce110_ipp_reg_offsets *offset) +{ + ipp->base.ctx = ctx; + + ipp->base.inst = inst; + + ipp->offsets = *offset; + + ipp->base.funcs = &funcs; + + return true; +} + +void dce80_ipp_destroy(struct input_pixel_processor **ipp) +{ + dm_free(TO_DCE80_IPP(*ipp)); + *ipp = NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.h b/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.h new file mode 100644 index 000000000000..d350138e5feb --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.h @@ -0,0 +1,47 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_IPP_DCE80_H__ +#define __DC_IPP_DCE80_H__ + +#include "ipp.h" + +#define TO_DCE80_IPP(input_pixel_processor)\ + container_of(input_pixel_processor, struct dce110_ipp, base) + +struct dce110_ipp; +struct dce110_ipp_reg_offsets; +struct gamma_parameters; +struct dev_c_lut; + +bool dce80_ipp_construct( + struct dce110_ipp *ipp, + struct dc_context *ctx, + uint32_t inst, + const struct dce110_ipp_reg_offsets *offset); + +void dce80_ipp_destroy(struct input_pixel_processor **ipp); + +#endif /*__DC_IPP_DCE80_H__*/ diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp_gamma.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp_gamma.c new file mode 100644 index 000000000000..eacb14e40d52 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp_gamma.c @@ -0,0 +1,76 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "include/logger_interface.h" +#include "include/fixed31_32.h" +#include "basics/conversion.h" + +#include "dce/dce_8_0_d.h" +#include "dce/dce_8_0_sh_mask.h" + +#include "dce80_ipp.h" +#include "dce110/dce110_ipp.h" +#include "gamma_types.h" + +#define DCP_REG(reg)\ + (reg + ipp80->offsets.dcp_offset) + +enum { + MAX_INPUT_LUT_ENTRY = 256 +}; + +/*PROTOTYPE DECLARATIONS*/ + +static void set_legacy_input_gamma_mode( + struct dce110_ipp *ipp80, + bool is_legacy); + +void dce80_ipp_set_legacy_input_gamma_mode( + struct input_pixel_processor *ipp, + bool is_legacy) +{ + struct dce110_ipp *ipp80 = TO_DCE80_IPP(ipp); + + set_legacy_input_gamma_mode(ipp80, is_legacy); +} + +static void set_legacy_input_gamma_mode( + struct dce110_ipp *ipp80, + bool is_legacy) +{ + const uint32_t addr = DCP_REG(mmINPUT_GAMMA_CONTROL); + uint32_t value = dm_read_reg(ipp80->base.ctx, addr); + + set_reg_field_value( + value, + !is_legacy, + INPUT_GAMMA_CONTROL, + GRPH_INPUT_GAMMA_MODE); + + dm_write_reg(ipp80->base.ctx, addr, value); +} + diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c new file mode 100644 index 000000000000..ebb8df3cdf4a --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c @@ -0,0 +1,83 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#include "dm_services.h" + +#include "dce/dce_8_0_d.h" +#include "dce/dce_8_0_sh_mask.h" +/* TODO: this needs to be looked at, used by Stella's workaround*/ +#include "gmc/gmc_7_1_d.h" +#include "gmc/gmc_7_1_sh_mask.h" + +#include "include/logger_interface.h" +#include "inc/bandwidth_calcs.h" + +#include "../dce110/dce110_mem_input.h" +#include "dce80_mem_input.h" + +#define MAX_WATERMARK 0xFFFF +#define SAFE_NBP_MARK 0x7FFF + +#define DCP_REG(reg) (reg + mem_input80->offsets.dcp) +#define DMIF_REG(reg) (reg + mem_input80->offsets.dmif) +#define PIPE_REG(reg) (reg + mem_input80->offsets.pipe) + +static struct mem_input_funcs dce80_mem_input_funcs = { + .mem_input_program_display_marks = + dce110_mem_input_program_display_marks, + .allocate_mem_input = dce_mem_input_allocate_dmif, + .free_mem_input = dce_mem_input_free_dmif, + .mem_input_program_surface_flip_and_addr = + dce110_mem_input_program_surface_flip_and_addr, + .mem_input_program_surface_config = + dce_mem_input_program_surface_config, + .mem_input_is_flip_pending = + dce110_mem_input_is_flip_pending, + .mem_input_update_dchub = NULL +}; + +/*****************************************/ +/* Constructor, Destructor */ +/*****************************************/ + +bool dce80_mem_input_construct( + struct dce110_mem_input *mem_input80, + struct dc_context *ctx, + uint32_t inst, + const struct dce110_mem_input_reg_offsets *offsets) +{ + /* supported stutter method + * STUTTER_MODE_ENHANCED + * STUTTER_MODE_QUAD_DMIF_BUFFER + */ + mem_input80->base.funcs = &dce80_mem_input_funcs; + mem_input80->base.ctx = ctx; + + mem_input80->base.inst = inst; + + mem_input80->offsets = *offsets; + + return true; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.h new file mode 100644 index 000000000000..357b9e2e9f1e --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.h @@ -0,0 +1,36 @@ +/* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_MEM_INPUT_DCE80_H__ +#define __DC_MEM_INPUT_DCE80_H__ + +#include "mem_input.h" + +bool dce80_mem_input_construct( + struct dce110_mem_input *mem_input80, + struct dc_context *ctx, + uint32_t inst, + const struct dce110_mem_input_reg_offsets *offsets); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp.c new file mode 100644 index 000000000000..b69e8a5d844d --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp.c @@ -0,0 +1,136 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* include DCE8 register header files */ +#include "dce/dce_8_0_d.h" +#include "dce/dce_8_0_sh_mask.h" + +#include "dce80_opp.h" + +#define FROM_OPP(opp)\ + container_of(opp, struct dce80_opp, base) + +enum { + MAX_LUT_ENTRY = 256, + MAX_NUMBER_OF_ENTRIES = 256 +}; + +static const struct dce80_opp_reg_offsets reg_offsets[] = { +{ + .fmt_offset = (mmFMT0_FMT_CONTROL - mmFMT0_FMT_CONTROL), + .crtc_offset = (mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL - + mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL), + .dcp_offset = (mmDCP0_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ .fmt_offset = (mmFMT1_FMT_CONTROL - mmFMT0_FMT_CONTROL), + .crtc_offset = (mmCRTC1_DCFE_MEM_LIGHT_SLEEP_CNTL - + mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL), + .dcp_offset = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ .fmt_offset = (mmFMT2_FMT_CONTROL - mmFMT0_FMT_CONTROL), + .crtc_offset = (mmCRTC2_DCFE_MEM_LIGHT_SLEEP_CNTL - + mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL), + .dcp_offset = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ + .fmt_offset = (mmFMT3_FMT_CONTROL - mmFMT0_FMT_CONTROL), + .crtc_offset = (mmCRTC3_DCFE_MEM_LIGHT_SLEEP_CNTL - + mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL), + .dcp_offset = (mmDCP3_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ + .fmt_offset = (mmFMT4_FMT_CONTROL - mmFMT0_FMT_CONTROL), + .crtc_offset = (mmCRTC4_DCFE_MEM_LIGHT_SLEEP_CNTL - + mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL), + .dcp_offset = (mmDCP4_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ + .fmt_offset = (mmFMT5_FMT_CONTROL - mmFMT0_FMT_CONTROL), + .crtc_offset = (mmCRTC5_DCFE_MEM_LIGHT_SLEEP_CNTL - + mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL), + .dcp_offset = (mmDCP5_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +} +}; + +static const struct opp_funcs funcs = { + .opp_power_on_regamma_lut = dce80_opp_power_on_regamma_lut, + .opp_set_csc_adjustment = dce80_opp_set_csc_adjustment, + .opp_set_csc_default = dce80_opp_set_csc_default, + .opp_set_dyn_expansion = dce80_opp_set_dyn_expansion, + .opp_program_regamma_pwl = dce80_opp_program_regamma_pwl, + .opp_set_regamma_mode = dce80_opp_set_regamma_mode, + .opp_destroy = dce80_opp_destroy, + .opp_program_fmt = dce110_opp_program_fmt, +}; + +/*****************************************/ +/* Constructor, Destructor */ +/*****************************************/ + +bool dce80_opp_construct(struct dce80_opp *opp80, + struct dc_context *ctx, + uint32_t inst) +{ + if (inst >= ARRAY_SIZE(reg_offsets)) + return false; + + opp80->base.funcs = &funcs; + + opp80->base.ctx = ctx; + + opp80->base.inst = inst; + + opp80->offsets = reg_offsets[inst]; + + return true; +} + +void dce80_opp_destroy(struct output_pixel_processor **opp) +{ + dm_free(FROM_OPP(*opp)); + *opp = NULL; +} + +struct output_pixel_processor *dce80_opp_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dce80_opp *opp = + dm_alloc(sizeof(struct dce80_opp)); + + if (!opp) + return NULL; + + if (dce80_opp_construct(opp, + ctx, inst)) + return &opp->base; + + BREAK_TO_DEBUGGER(); + dm_free(opp); + return NULL; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp.h b/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp.h new file mode 100644 index 000000000000..965cce37f7e3 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp.h @@ -0,0 +1,130 @@ +/* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_OPP_DCE80_H__ +#define __DC_OPP_DCE80_H__ + +#include "dc_types.h" +#include "opp.h" +#include "gamma_types.h" +#include "../dce110/dce110_opp.h" + +struct gamma_parameters; + +struct dce80_regamma { + struct gamma_curve arr_curve_points[16]; + struct curve_points arr_points[3]; + uint32_t hw_points_num; + struct hw_x_point *coordinates_x; + struct pwl_result_data *rgb_resulted; + + /* re-gamma curve */ + struct pwl_float_data_ex *rgb_regamma; + /* coeff used to map user evenly distributed points + * to our hardware points (predefined) for gamma 256 */ + struct pixel_gamma_point *coeff128; + struct pixel_gamma_point *coeff128_oem; + /* coeff used to map user evenly distributed points + * to our hardware points (predefined) for gamma 1025 */ + struct pixel_gamma_point *coeff128_dx; + /* evenly distributed points, gamma 256 software points 0-255 */ + struct gamma_pixel *axis_x_256; + /* evenly distributed points, gamma 1025 software points 0-1025 */ + struct gamma_pixel *axis_x_1025; + /* OEM supplied gamma for regamma LUT */ + struct pwl_float_data *rgb_oem; + /* user supplied gamma */ + struct pwl_float_data *rgb_user; + uint32_t extra_points; + bool use_half_points; + struct fixed31_32 x_max1; + struct fixed31_32 x_max2; + struct fixed31_32 x_min; + struct fixed31_32 divider1; + struct fixed31_32 divider2; + struct fixed31_32 divider3; +}; + +/* OPP RELATED */ +#define TO_DCE80_OPP(opp)\ + container_of(opp, struct dce80_opp, base) + +struct dce80_opp_reg_offsets { + uint32_t fmt_offset; + uint32_t dcp_offset; + uint32_t crtc_offset; +}; + +struct dce80_opp { + struct output_pixel_processor base; + struct dce80_opp_reg_offsets offsets; + struct dce80_regamma regamma; +}; + +bool dce80_opp_construct(struct dce80_opp *opp80, + struct dc_context *ctx, + uint32_t inst); + +void dce80_opp_destroy(struct output_pixel_processor **opp); + +struct output_pixel_processor *dce80_opp_create( + struct dc_context *ctx, + uint32_t inst); + +/* REGAMMA RELATED */ +void dce80_opp_power_on_regamma_lut( + struct output_pixel_processor *opp, + bool power_on); + +bool dce80_opp_program_regamma_pwl( + struct output_pixel_processor *opp, + const struct pwl_params *pamras); + +void dce80_opp_set_regamma_mode(struct output_pixel_processor *opp, + enum opp_regamma mode); + +void dce80_opp_set_csc_adjustment( + struct output_pixel_processor *opp, + const struct out_csc_color_matrix *tbl_entry); + +void dce80_opp_set_csc_default( + struct output_pixel_processor *opp, + const struct default_adjustment *default_adjust); + +/* FORMATTER RELATED */ +void dce80_opp_program_bit_depth_reduction( + struct output_pixel_processor *opp, + const struct bit_depth_reduction_params *params); + +void dce80_opp_program_clamping_and_pixel_encoding( + struct output_pixel_processor *opp, + const struct clamping_and_pixel_encoding_params *params); + +void dce80_opp_set_dyn_expansion( + struct output_pixel_processor *opp, + enum dc_color_space color_sp, + enum dc_color_depth color_dpth, + enum signal_type signal); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_csc.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_csc.c new file mode 100644 index 000000000000..bdb9e0a77982 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_csc.c @@ -0,0 +1,363 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "dce80_opp.h" +#include "basics/conversion.h" + +/* include DCE8 register header files */ +#include "dce/dce_8_0_d.h" +#include "dce/dce_8_0_sh_mask.h" + +#define DCP_REG(reg)\ + (reg + opp80->offsets.dcp_offset) + +enum { + OUTPUT_CSC_MATRIX_SIZE = 12 +}; + +static const struct out_csc_color_matrix global_color_matrix[] = { +{ COLOR_SPACE_SRGB, + { 0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} }, +{ COLOR_SPACE_SRGB_LIMITED, + { 0x1B60, 0, 0, 0x200, 0, 0x1B60, 0, 0x200, 0, 0, 0x1B60, 0x200} }, +{ COLOR_SPACE_YCBCR601, + { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x82F, 0x1012, 0x31F, 0x200, 0xFB47, + 0xF6B9, 0xE00, 0x1000} }, +{ COLOR_SPACE_YCBCR709, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x5D2, 0x1394, 0x1FA, + 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} }, +/* TODO: correct values below */ +{ COLOR_SPACE_YCBCR601_LIMITED, { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x991, + 0x12C9, 0x3A6, 0x200, 0xFB47, 0xF6B9, 0xE00, 0x1000} }, +{ COLOR_SPACE_YCBCR709_LIMITED, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x6CE, 0x16E3, + 0x24F, 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} } +}; + +enum csc_color_mode { + /* 00 - BITS2:0 Bypass */ + CSC_COLOR_MODE_GRAPHICS_BYPASS, + /* 01 - hard coded coefficient TV RGB */ + CSC_COLOR_MODE_GRAPHICS_PREDEFINED, + /* 04 - programmable OUTPUT CSC coefficient */ + CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC, +}; + +static void program_color_matrix( + struct dce80_opp *opp80, + const struct out_csc_color_matrix *tbl_entry, + enum grph_color_adjust_option options) +{ + struct dc_context *ctx = opp80->base.ctx; + { + uint32_t value = 0; + uint32_t addr = DCP_REG(mmOUTPUT_CSC_C11_C12); + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[0], + OUTPUT_CSC_C11_C12, + OUTPUT_CSC_C11); + + set_reg_field_value( + value, + tbl_entry->regval[1], + OUTPUT_CSC_C11_C12, + OUTPUT_CSC_C12); + + dm_write_reg(ctx, addr, value); + } + { + uint32_t value = 0; + uint32_t addr = DCP_REG(mmOUTPUT_CSC_C13_C14); + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[2], + OUTPUT_CSC_C13_C14, + OUTPUT_CSC_C13); + /* fixed S0.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[3], + OUTPUT_CSC_C13_C14, + OUTPUT_CSC_C14); + + dm_write_reg(ctx, addr, value); + } + { + uint32_t value = 0; + uint32_t addr = DCP_REG(mmOUTPUT_CSC_C21_C22); + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[4], + OUTPUT_CSC_C21_C22, + OUTPUT_CSC_C21); + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[5], + OUTPUT_CSC_C21_C22, + OUTPUT_CSC_C22); + + dm_write_reg(ctx, addr, value); + } + { + uint32_t value = 0; + uint32_t addr = DCP_REG(mmOUTPUT_CSC_C23_C24); + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[6], + OUTPUT_CSC_C23_C24, + OUTPUT_CSC_C23); + /* fixed S0.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[7], + OUTPUT_CSC_C23_C24, + OUTPUT_CSC_C24); + + dm_write_reg(ctx, addr, value); + } + { + uint32_t value = 0; + uint32_t addr = DCP_REG(mmOUTPUT_CSC_C31_C32); + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[8], + OUTPUT_CSC_C31_C32, + OUTPUT_CSC_C31); + /* fixed S0.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[9], + OUTPUT_CSC_C31_C32, + OUTPUT_CSC_C32); + + dm_write_reg(ctx, addr, value); + } + { + uint32_t value = 0; + uint32_t addr = DCP_REG(mmOUTPUT_CSC_C33_C34); + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[10], + OUTPUT_CSC_C33_C34, + OUTPUT_CSC_C33); + /* fixed S0.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[11], + OUTPUT_CSC_C33_C34, + OUTPUT_CSC_C34); + + dm_write_reg(ctx, addr, value); + } +} + +static bool configure_graphics_mode( + struct dce80_opp *opp80, + enum csc_color_mode config, + enum graphics_csc_adjust_type csc_adjust_type, + enum dc_color_space color_space) +{ + struct dc_context *ctx = opp80->base.ctx; + uint32_t addr = DCP_REG(mmOUTPUT_CSC_CONTROL); + uint32_t value = dm_read_reg(ctx, addr); + + set_reg_field_value( + value, + 0, + OUTPUT_CSC_CONTROL, + OUTPUT_CSC_GRPH_MODE); + + if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_SW) { + if (config == CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC) { + set_reg_field_value( + value, + 4, + OUTPUT_CSC_CONTROL, + OUTPUT_CSC_GRPH_MODE); + } else { + + switch (color_space) { + case COLOR_SPACE_SRGB: + /* by pass */ + set_reg_field_value( + value, + 0, + OUTPUT_CSC_CONTROL, + OUTPUT_CSC_GRPH_MODE); + break; + case COLOR_SPACE_SRGB_LIMITED: + /* TV RGB */ + set_reg_field_value( + value, + 1, + OUTPUT_CSC_CONTROL, + OUTPUT_CSC_GRPH_MODE); + break; + case COLOR_SPACE_YCBCR601: + case COLOR_SPACE_YPBPR601: + case COLOR_SPACE_YCBCR601_LIMITED: + /* YCbCr601 */ + set_reg_field_value( + value, + 2, + OUTPUT_CSC_CONTROL, + OUTPUT_CSC_GRPH_MODE); + break; + case COLOR_SPACE_YCBCR709: + case COLOR_SPACE_YPBPR709: + case COLOR_SPACE_YCBCR709_LIMITED: + /* YCbCr709 */ + set_reg_field_value( + value, + 3, + OUTPUT_CSC_CONTROL, + OUTPUT_CSC_GRPH_MODE); + break; + default: + return false; + } + } + } else if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_HW) { + switch (color_space) { + case COLOR_SPACE_SRGB: + /* by pass */ + set_reg_field_value( + value, + 0, + OUTPUT_CSC_CONTROL, + OUTPUT_CSC_GRPH_MODE); + break; + case COLOR_SPACE_SRGB_LIMITED: + /* TV RGB */ + set_reg_field_value( + value, + 1, + OUTPUT_CSC_CONTROL, + OUTPUT_CSC_GRPH_MODE); + break; + case COLOR_SPACE_YCBCR601: + case COLOR_SPACE_YPBPR601: + case COLOR_SPACE_YCBCR601_LIMITED: + /* YCbCr601 */ + set_reg_field_value( + value, + 2, + OUTPUT_CSC_CONTROL, + OUTPUT_CSC_GRPH_MODE); + break; + case COLOR_SPACE_YCBCR709: + case COLOR_SPACE_YPBPR709: + case COLOR_SPACE_YCBCR709_LIMITED: + /* YCbCr709 */ + set_reg_field_value( + value, + 3, + OUTPUT_CSC_CONTROL, + OUTPUT_CSC_GRPH_MODE); + break; + default: + return false; + } + + } else + /* by pass */ + set_reg_field_value( + value, + 0, + OUTPUT_CSC_CONTROL, + OUTPUT_CSC_GRPH_MODE); + + addr = DCP_REG(mmOUTPUT_CSC_CONTROL); + dm_write_reg(ctx, addr, value); + + return true; +} + +void dce80_opp_set_csc_adjustment( + struct output_pixel_processor *opp, + const struct out_csc_color_matrix *tbl_entry) +{ + struct dce80_opp *opp80 = TO_DCE80_OPP(opp); + enum csc_color_mode config = + CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; + + program_color_matrix(opp80, tbl_entry, GRAPHICS_CSC_ADJUST_TYPE_SW); + + /* We did everything ,now program DxOUTPUT_CSC_CONTROL */ + configure_graphics_mode(opp80, config, GRAPHICS_CSC_ADJUST_TYPE_SW, + tbl_entry->color_space); +} + +void dce80_opp_set_csc_default( + struct output_pixel_processor *opp, + const struct default_adjustment *default_adjust) +{ + struct dce80_opp *opp80 = TO_DCE80_OPP(opp); + enum csc_color_mode config = + CSC_COLOR_MODE_GRAPHICS_PREDEFINED; + + if (default_adjust->force_hw_default == false) { + const struct out_csc_color_matrix *elm; + /* currently parameter not in use */ + enum grph_color_adjust_option option = + GRPH_COLOR_MATRIX_HW_DEFAULT; + uint32_t i; + /* + * HW default false we program locally defined matrix + * HW default true we use predefined hw matrix and we + * do not need to program matrix + * OEM wants the HW default via runtime parameter. + */ + option = GRPH_COLOR_MATRIX_SW; + + for (i = 0; i < ARRAY_SIZE(global_color_matrix); ++i) { + elm = &global_color_matrix[i]; + if (elm->color_space != default_adjust->out_color_space) + continue; + /* program the matrix with default values from this + * file */ + program_color_matrix(opp80, elm, option); + config = CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; + break; + } + } + + /* configure the what we programmed : + * 1. Default values from this file + * 2. Use hardware default from ROM_A and we do not need to program + * matrix */ + + configure_graphics_mode(opp80, config, + default_adjust->csc_adjust_type, + default_adjust->out_color_space); +} diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_formatter.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_formatter.c new file mode 100644 index 000000000000..433296a4ed12 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_formatter.c @@ -0,0 +1,577 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "dce/dce_8_0_d.h" +#include "dce/dce_8_0_sh_mask.h" + +#include "dce80_opp.h" + +#define FMT_REG(reg)\ + (reg + opp80->offsets.fmt_offset) + +/** + * set_truncation + * 1) set truncation depth: 0 for 18 bpp or 1 for 24 bpp + * 2) enable truncation + * 3) HW remove 12bit FMT support for DCE8 power saving reason. + */ +static void set_truncation( + struct dce80_opp *opp80, + const struct bit_depth_reduction_params *params) +{ + uint32_t value = 0; + uint32_t addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL); + + /*Disable truncation*/ + value = dm_read_reg(opp80->base.ctx, addr); + set_reg_field_value(value, 0, + FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN); + set_reg_field_value(value, 0, + FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_DEPTH); + set_reg_field_value(value, 0, + FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_MODE); + + dm_write_reg(opp80->base.ctx, addr, value); + + /* no 10bpc trunc on DCE8*/ + if (params->flags.TRUNCATE_ENABLED == 0 || + params->flags.TRUNCATE_DEPTH == 2) + return; + + /*Set truncation depth and Enable truncation*/ + set_reg_field_value(value, 1, + FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN); + set_reg_field_value(value, params->flags.TRUNCATE_MODE, + FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_MODE); + set_reg_field_value(value, params->flags.TRUNCATE_DEPTH, + FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_DEPTH); + + dm_write_reg(opp80->base.ctx, addr, value); + +} + +/** + * set_spatial_dither + * 1) set spatial dithering mode: pattern of seed + * 2) set spatical dithering depth: 0 for 18bpp or 1 for 24bpp + * 3) set random seed + * 4) set random mode + * lfsr is reset every frame or not reset + * RGB dithering method + * 0: RGB data are all dithered with x^28+x^3+1 + * 1: R data is dithered with x^28+x^3+1 + * G data is dithered with x^28+X^9+1 + * B data is dithered with x^28+x^13+1 + * enable high pass filter or not + * 5) enable spatical dithering + */ +static void set_spatial_dither( + struct dce80_opp *opp80, + const struct bit_depth_reduction_params *params) +{ + uint32_t addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL); + uint32_t depth_cntl_value = 0; + uint32_t dither_r_value = 0; + uint32_t dither_g_value = 0; + uint32_t dither_b_value = 0; + + /*Disable spatial (random) dithering*/ + depth_cntl_value = dm_read_reg(opp80->base.ctx, addr); + set_reg_field_value(depth_cntl_value, 0, + FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_EN); + set_reg_field_value(depth_cntl_value, 0, + FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_MODE); + set_reg_field_value(depth_cntl_value, 0, + FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_DEPTH); + set_reg_field_value(depth_cntl_value, 0, + FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_EN); + set_reg_field_value(depth_cntl_value, 0, + FMT_BIT_DEPTH_CONTROL, FMT_HIGHPASS_RANDOM_ENABLE); + set_reg_field_value(depth_cntl_value, 0, + FMT_BIT_DEPTH_CONTROL, FMT_FRAME_RANDOM_ENABLE); + set_reg_field_value(depth_cntl_value, 0, + FMT_BIT_DEPTH_CONTROL, FMT_RGB_RANDOM_ENABLE); + + dm_write_reg(opp80->base.ctx, addr, depth_cntl_value); + + /* no 10bpc on DCE8*/ + if (params->flags.SPATIAL_DITHER_ENABLED == 0 || + params->flags.SPATIAL_DITHER_DEPTH == 2) + return; + + /*Set seed for random values for + * spatial dithering for R,G,B channels*/ + addr = FMT_REG(mmFMT_DITHER_RAND_R_SEED); + set_reg_field_value(dither_r_value, params->r_seed_value, + FMT_DITHER_RAND_R_SEED, + FMT_RAND_R_SEED); + dm_write_reg(opp80->base.ctx, addr, dither_r_value); + + addr = FMT_REG(mmFMT_DITHER_RAND_G_SEED); + set_reg_field_value(dither_g_value, + params->g_seed_value, + FMT_DITHER_RAND_G_SEED, + FMT_RAND_G_SEED); + dm_write_reg(opp80->base.ctx, addr, dither_g_value); + + addr = FMT_REG(mmFMT_DITHER_RAND_B_SEED); + set_reg_field_value(dither_b_value, params->b_seed_value, + FMT_DITHER_RAND_B_SEED, + FMT_RAND_B_SEED); + dm_write_reg(opp80->base.ctx, addr, dither_b_value); + + /* FMT_OFFSET_R_Cr 31:16 0x0 Setting the zero + * offset for the R/Cr channel, lower 4LSB + * is forced to zeros. Typically set to 0 + * RGB and 0x80000 YCbCr. + */ + /* FMT_OFFSET_G_Y 31:16 0x0 Setting the zero + * offset for the G/Y channel, lower 4LSB is + * forced to zeros. Typically set to 0 RGB + * and 0x80000 YCbCr. + */ + /* FMT_OFFSET_B_Cb 31:16 0x0 Setting the zero + * offset for the B/Cb channel, lower 4LSB is + * forced to zeros. Typically set to 0 RGB and + * 0x80000 YCbCr. + */ + + /*Set spatial dithering bit depth*/ + set_reg_field_value(depth_cntl_value, + params->flags.SPATIAL_DITHER_DEPTH, + FMT_BIT_DEPTH_CONTROL, + FMT_SPATIAL_DITHER_DEPTH); + + /* Set spatial dithering mode + * (default is Seed patterrn AAAA...) + */ + set_reg_field_value(depth_cntl_value, + params->flags.SPATIAL_DITHER_MODE, + FMT_BIT_DEPTH_CONTROL, + FMT_SPATIAL_DITHER_MODE); + + /*Reset only at startup*/ + set_reg_field_value(depth_cntl_value, + params->flags.FRAME_RANDOM, + FMT_BIT_DEPTH_CONTROL, + FMT_FRAME_RANDOM_ENABLE); + + /*Set RGB data dithered with x^28+x^3+1*/ + set_reg_field_value(depth_cntl_value, + params->flags.RGB_RANDOM, + FMT_BIT_DEPTH_CONTROL, + FMT_RGB_RANDOM_ENABLE); + + /*Disable High pass filter*/ + set_reg_field_value(depth_cntl_value, + params->flags.HIGHPASS_RANDOM, + FMT_BIT_DEPTH_CONTROL, + FMT_HIGHPASS_RANDOM_ENABLE); + + /*Enable spatial dithering*/ + set_reg_field_value(depth_cntl_value, + 1, + FMT_BIT_DEPTH_CONTROL, + FMT_SPATIAL_DITHER_EN); + + addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL); + dm_write_reg(opp80->base.ctx, addr, depth_cntl_value); + +} + +/** + * SetTemporalDither (Frame Modulation) + * 1) set temporal dither depth + * 2) select pattern: from hard-coded pattern or programmable pattern + * 3) select optimized strips for BGR or RGB LCD sub-pixel + * 4) set s matrix + * 5) set t matrix + * 6) set grey level for 0.25, 0.5, 0.75 + * 7) enable temporal dithering + */ +static void set_temporal_dither( + struct dce80_opp *opp80, + const struct bit_depth_reduction_params *params) +{ + uint32_t addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL); + uint32_t value; + + /*Disable temporal (frame modulation) dithering first*/ + value = dm_read_reg(opp80->base.ctx, addr); + + set_reg_field_value(value, + 0, + FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_DITHER_EN); + + set_reg_field_value(value, + 0, + FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_DITHER_RESET); + set_reg_field_value(value, + 0, + FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_DITHER_OFFSET); + set_reg_field_value(value, + 0, + FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_DITHER_DEPTH); + set_reg_field_value(value, + 0, + FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_LEVEL); + set_reg_field_value(value, + 0, + FMT_BIT_DEPTH_CONTROL, + FMT_25FRC_SEL); + + set_reg_field_value(value, + 0, + FMT_BIT_DEPTH_CONTROL, + FMT_50FRC_SEL); + + set_reg_field_value(value, + 0, + FMT_BIT_DEPTH_CONTROL, + FMT_75FRC_SEL); + + dm_write_reg(opp80->base.ctx, addr, value); + + /* no 10bpc dither on DCE8*/ + if (params->flags.FRAME_MODULATION_ENABLED == 0 || + params->flags.FRAME_MODULATION_DEPTH == 2) + return; + + /* Set temporal dithering depth*/ + set_reg_field_value(value, + params->flags.FRAME_MODULATION_DEPTH, + FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_DITHER_DEPTH); + + set_reg_field_value(value, + 0, + FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_DITHER_RESET); + + set_reg_field_value(value, + 0, + FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_DITHER_OFFSET); + + /*Select legacy pattern based on FRC and Temporal level*/ + addr = FMT_REG(mmFMT_TEMPORAL_DITHER_PATTERN_CONTROL); + dm_write_reg(opp80->base.ctx, addr, 0); + /*Set s matrix*/ + addr = FMT_REG( + mmFMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX); + dm_write_reg(opp80->base.ctx, addr, 0); + /*Set t matrix*/ + addr = FMT_REG( + mmFMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX); + dm_write_reg(opp80->base.ctx, addr, 0); + + /*Select patterns for 0.25, 0.5 and 0.75 grey level*/ + set_reg_field_value(value, + params->flags.TEMPORAL_LEVEL, + FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_LEVEL); + + set_reg_field_value(value, + params->flags.FRC25, + FMT_BIT_DEPTH_CONTROL, + FMT_25FRC_SEL); + + set_reg_field_value(value, + params->flags.FRC50, + FMT_BIT_DEPTH_CONTROL, + FMT_50FRC_SEL); + + set_reg_field_value(value, + params->flags.FRC75, + FMT_BIT_DEPTH_CONTROL, + FMT_75FRC_SEL); + + /*Enable bit reduction by temporal (frame modulation) dithering*/ + set_reg_field_value(value, + 1, + FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_DITHER_EN); + + addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL); + dm_write_reg(opp80->base.ctx, addr, value); + +} + +/** + * Set Clamping + * 1) Set clamping format based on bpc - 0 for 6bpc (No clamping) + * 1 for 8 bpc + * 2 for 10 bpc + * 3 for 12 bpc + * 7 for programable + * 2) Enable clamp if Limited range requested + */ +static void set_clamping( + struct dce80_opp *opp80, + const struct clamping_and_pixel_encoding_params *params) +{ + uint32_t clamp_cntl_value = 0; + uint32_t red_clamp_value = 0; + uint32_t green_clamp_value = 0; + uint32_t blue_clamp_value = 0; + uint32_t addr = FMT_REG(mmFMT_CLAMP_CNTL); + + clamp_cntl_value = dm_read_reg(opp80->base.ctx, addr); + + set_reg_field_value(clamp_cntl_value, + 0, + FMT_CLAMP_CNTL, + FMT_CLAMP_DATA_EN); + + set_reg_field_value(clamp_cntl_value, + 0, + FMT_CLAMP_CNTL, + FMT_CLAMP_COLOR_FORMAT); + + switch (params->clamping_level) { + case CLAMPING_FULL_RANGE: + break; + + case CLAMPING_LIMITED_RANGE_8BPC: + set_reg_field_value(clamp_cntl_value, + 1, + FMT_CLAMP_CNTL, + FMT_CLAMP_DATA_EN); + + set_reg_field_value(clamp_cntl_value, + 1, + FMT_CLAMP_CNTL, + FMT_CLAMP_COLOR_FORMAT); + + break; + + case CLAMPING_LIMITED_RANGE_10BPC: + set_reg_field_value(clamp_cntl_value, + 1, + FMT_CLAMP_CNTL, + FMT_CLAMP_DATA_EN); + + set_reg_field_value(clamp_cntl_value, + 2, + FMT_CLAMP_CNTL, + FMT_CLAMP_COLOR_FORMAT); + + break; + case CLAMPING_LIMITED_RANGE_12BPC: + set_reg_field_value(clamp_cntl_value, + 1, + FMT_CLAMP_CNTL, + FMT_CLAMP_DATA_EN); + + set_reg_field_value(clamp_cntl_value, + 3, + FMT_CLAMP_CNTL, + FMT_CLAMP_COLOR_FORMAT); + + break; + case CLAMPING_LIMITED_RANGE_PROGRAMMABLE: + set_reg_field_value(clamp_cntl_value, + 1, + FMT_CLAMP_CNTL, + FMT_CLAMP_DATA_EN); + + set_reg_field_value(clamp_cntl_value, + 7, + FMT_CLAMP_CNTL, + FMT_CLAMP_COLOR_FORMAT); + + /*set the defaults*/ + set_reg_field_value(red_clamp_value, + 0x10, + FMT_CLAMP_COMPONENT_R, + FMT_CLAMP_LOWER_R); + + set_reg_field_value(red_clamp_value, + 0xFEF, + FMT_CLAMP_COMPONENT_R, + FMT_CLAMP_UPPER_R); + + addr = FMT_REG(mmFMT_CLAMP_COMPONENT_R); + dm_write_reg(opp80->base.ctx, addr, red_clamp_value); + + set_reg_field_value(green_clamp_value, + 0x10, + FMT_CLAMP_COMPONENT_G, + FMT_CLAMP_LOWER_G); + + set_reg_field_value(green_clamp_value, + 0xFEF, + FMT_CLAMP_COMPONENT_G, + FMT_CLAMP_UPPER_G); + + addr = FMT_REG(mmFMT_CLAMP_COMPONENT_G); + dm_write_reg(opp80->base.ctx, addr, green_clamp_value); + + set_reg_field_value(blue_clamp_value, + 0x10, + FMT_CLAMP_COMPONENT_B, + FMT_CLAMP_LOWER_B); + + set_reg_field_value(blue_clamp_value, + 0xFEF, + FMT_CLAMP_COMPONENT_B, + FMT_CLAMP_UPPER_B); + + addr = FMT_REG(mmFMT_CLAMP_COMPONENT_B); + dm_write_reg(opp80->base.ctx, addr, blue_clamp_value); + + break; + + default: + break; + } + + addr = FMT_REG(mmFMT_CLAMP_CNTL); + /*Set clamp control*/ + dm_write_reg(opp80->base.ctx, addr, clamp_cntl_value); + +} + +/** + * set_pixel_encoding + * + * Set Pixel Encoding + * 0: RGB 4:4:4 or YCbCr 4:4:4 or YOnly + * 1: YCbCr 4:2:2 + */ +static void set_pixel_encoding( + struct dce80_opp *opp80, + const struct clamping_and_pixel_encoding_params *params) +{ + uint32_t fmt_cntl_value; + uint32_t addr = FMT_REG(mmFMT_CONTROL); + + /*RGB 4:4:4 or YCbCr 4:4:4 - 0; YCbCr 4:2:2 -1.*/ + fmt_cntl_value = dm_read_reg(opp80->base.ctx, addr); + + set_reg_field_value(fmt_cntl_value, + 0, + FMT_CONTROL, + FMT_PIXEL_ENCODING); + + if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) { + set_reg_field_value(fmt_cntl_value, + 1, + FMT_CONTROL, + FMT_PIXEL_ENCODING); + + /*00 - Pixels drop mode ,01 - Pixels average mode*/ + set_reg_field_value(fmt_cntl_value, + 0, + FMT_CONTROL, + FMT_SUBSAMPLING_MODE); + + /*00 - Cb before Cr ,01 - Cr before Cb*/ + set_reg_field_value(fmt_cntl_value, + 0, + FMT_CONTROL, + FMT_SUBSAMPLING_ORDER); + } + dm_write_reg(opp80->base.ctx, addr, fmt_cntl_value); + +} + +void dce80_opp_program_bit_depth_reduction( + struct output_pixel_processor *opp, + const struct bit_depth_reduction_params *params) +{ + struct dce80_opp *opp80 = TO_DCE80_OPP(opp); + + set_truncation(opp80, params); + set_spatial_dither(opp80, params); + set_temporal_dither(opp80, params); +} + +void dce80_opp_program_clamping_and_pixel_encoding( + struct output_pixel_processor *opp, + const struct clamping_and_pixel_encoding_params *params) +{ + struct dce80_opp *opp80 = TO_DCE80_OPP(opp); + + set_clamping(opp80, params); + set_pixel_encoding(opp80, params); +} + +void dce80_opp_set_dyn_expansion( + struct output_pixel_processor *opp, + enum dc_color_space color_sp, + enum dc_color_depth color_dpth, + enum signal_type signal) +{ + struct dce80_opp *opp80 = TO_DCE80_OPP(opp); + uint32_t value; + bool enable_dyn_exp = false; + uint32_t addr = FMT_REG(mmFMT_DYNAMIC_EXP_CNTL); + + value = dm_read_reg(opp->ctx, addr); + + set_reg_field_value(value, 0, + FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN); + set_reg_field_value(value, 0, + FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE); + + /* From HW programming guide: + FMT_DYNAMIC_EXP_EN = 0 for limited RGB or YCbCr output + FMT_DYNAMIC_EXP_EN = 1 for RGB full range only*/ + if (color_sp == COLOR_SPACE_SRGB) + enable_dyn_exp = true; + + /*00 - 10-bit -> 12-bit dynamic expansion*/ + /*01 - 8-bit -> 12-bit dynamic expansion*/ + if (signal == SIGNAL_TYPE_HDMI_TYPE_A) { + switch (color_dpth) { + case COLOR_DEPTH_888: + set_reg_field_value(value, enable_dyn_exp ? 1:0, + FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN); + set_reg_field_value(value, 1, + FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE); + break; + case COLOR_DEPTH_101010: + set_reg_field_value(value, enable_dyn_exp ? 1:0, + FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN); + set_reg_field_value(value, 0, + FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE); + break; + case COLOR_DEPTH_121212: + break; + default: + break; + } + } + + dm_write_reg(opp->ctx, addr, value); +} diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_regamma.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_regamma.c new file mode 100644 index 000000000000..648e3ef35d91 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_regamma.c @@ -0,0 +1,543 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* include DCE8 register header files */ +#include "dce/dce_8_0_d.h" +#include "dce/dce_8_0_sh_mask.h" + +#include "dce80_opp.h" +#include "gamma_types.h" + +#define DCP_REG(reg)\ + (reg + opp80->offsets.dcp_offset) + +#define DCFE_REG(reg)\ + (reg + opp80->offsets.crtc_offset) + +enum { + MAX_PWL_ENTRY = 128, + MAX_REGIONS_NUMBER = 16 + +}; + +struct curve_config { + uint32_t offset; + int8_t segments[MAX_REGIONS_NUMBER]; + int8_t begin; +}; + +/* + ***************************************************************************** + * Function: regamma_config_regions_and_segments + * + * build regamma curve by using predefined hw points + * uses interface parameters ,like EDID coeff. + * + * @param : parameters interface parameters + * @return void + * + * @note + * + * @see + * + ***************************************************************************** + */ +static void regamma_config_regions_and_segments( + struct dce80_opp *opp80, const struct pwl_params *params) +{ + const struct gamma_curve *curve; + uint32_t value = 0; + + { + set_reg_field_value( + value, + params->arr_points[0].custom_float_x, + REGAMMA_CNTLA_START_CNTL, + REGAMMA_CNTLA_EXP_REGION_START); + + set_reg_field_value( + value, + 0, + REGAMMA_CNTLA_START_CNTL, + REGAMMA_CNTLA_EXP_REGION_START_SEGMENT); + + dm_write_reg(opp80->base.ctx, + DCP_REG(mmREGAMMA_CNTLA_START_CNTL), + value); + } + { + value = 0; + set_reg_field_value( + value, + params->arr_points[0].custom_float_slope, + REGAMMA_CNTLA_SLOPE_CNTL, + REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE); + + dm_write_reg(opp80->base.ctx, + DCP_REG(mmREGAMMA_CNTLA_SLOPE_CNTL), value); + } + { + value = 0; + set_reg_field_value( + value, + params->arr_points[1].custom_float_x, + REGAMMA_CNTLA_END_CNTL1, + REGAMMA_CNTLA_EXP_REGION_END); + + dm_write_reg(opp80->base.ctx, + DCP_REG(mmREGAMMA_CNTLA_END_CNTL1), value); + } + { + value = 0; + set_reg_field_value( + value, + params->arr_points[2].custom_float_slope, + REGAMMA_CNTLA_END_CNTL2, + REGAMMA_CNTLA_EXP_REGION_END_BASE); + + set_reg_field_value( + value, + params->arr_points[1].custom_float_y, + REGAMMA_CNTLA_END_CNTL2, + REGAMMA_CNTLA_EXP_REGION_END_SLOPE); + + dm_write_reg(opp80->base.ctx, + DCP_REG(mmREGAMMA_CNTLA_END_CNTL2), value); + } + + curve = params->arr_curve_points; + + { + value = 0; + set_reg_field_value( + value, + curve[0].offset, + REGAMMA_CNTLA_REGION_0_1, + REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET); + + set_reg_field_value( + value, + curve[0].segments_num, + REGAMMA_CNTLA_REGION_0_1, + REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS); + + set_reg_field_value( + value, + curve[1].offset, + REGAMMA_CNTLA_REGION_0_1, + REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET); + + set_reg_field_value( + value, + curve[1].segments_num, + REGAMMA_CNTLA_REGION_0_1, + REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS); + + dm_write_reg( + opp80->base.ctx, + DCP_REG(mmREGAMMA_CNTLA_REGION_0_1), + value); + } + + curve += 2; + { + value = 0; + set_reg_field_value( + value, + curve[0].offset, + REGAMMA_CNTLA_REGION_2_3, + REGAMMA_CNTLA_EXP_REGION2_LUT_OFFSET); + + set_reg_field_value( + value, + curve[0].segments_num, + REGAMMA_CNTLA_REGION_2_3, + REGAMMA_CNTLA_EXP_REGION2_NUM_SEGMENTS); + + set_reg_field_value( + value, + curve[1].offset, + REGAMMA_CNTLA_REGION_2_3, + REGAMMA_CNTLA_EXP_REGION3_LUT_OFFSET); + + set_reg_field_value( + value, + curve[1].segments_num, + REGAMMA_CNTLA_REGION_2_3, + REGAMMA_CNTLA_EXP_REGION3_NUM_SEGMENTS); + + dm_write_reg(opp80->base.ctx, + DCP_REG(mmREGAMMA_CNTLA_REGION_2_3), + value); + } + + curve += 2; + { + value = 0; + set_reg_field_value( + value, + curve[0].offset, + REGAMMA_CNTLA_REGION_4_5, + REGAMMA_CNTLA_EXP_REGION4_LUT_OFFSET); + + set_reg_field_value( + value, + curve[0].segments_num, + REGAMMA_CNTLA_REGION_4_5, + REGAMMA_CNTLA_EXP_REGION4_NUM_SEGMENTS); + + set_reg_field_value( + value, + curve[1].offset, + REGAMMA_CNTLA_REGION_4_5, + REGAMMA_CNTLA_EXP_REGION5_LUT_OFFSET); + + set_reg_field_value( + value, + curve[1].segments_num, + REGAMMA_CNTLA_REGION_4_5, + REGAMMA_CNTLA_EXP_REGION5_NUM_SEGMENTS); + + dm_write_reg(opp80->base.ctx, + DCP_REG(mmREGAMMA_CNTLA_REGION_4_5), + value); + } + + curve += 2; + { + value = 0; + set_reg_field_value( + value, + curve[0].offset, + REGAMMA_CNTLA_REGION_6_7, + REGAMMA_CNTLA_EXP_REGION6_LUT_OFFSET); + + set_reg_field_value( + value, + curve[0].segments_num, + REGAMMA_CNTLA_REGION_6_7, + REGAMMA_CNTLA_EXP_REGION6_NUM_SEGMENTS); + + set_reg_field_value( + value, + curve[1].offset, + REGAMMA_CNTLA_REGION_6_7, + REGAMMA_CNTLA_EXP_REGION7_LUT_OFFSET); + + set_reg_field_value( + value, + curve[1].segments_num, + REGAMMA_CNTLA_REGION_6_7, + REGAMMA_CNTLA_EXP_REGION7_NUM_SEGMENTS); + + dm_write_reg(opp80->base.ctx, + DCP_REG(mmREGAMMA_CNTLA_REGION_6_7), + value); + } + + curve += 2; + { + value = 0; + set_reg_field_value( + value, + curve[0].offset, + REGAMMA_CNTLA_REGION_8_9, + REGAMMA_CNTLA_EXP_REGION8_LUT_OFFSET); + + set_reg_field_value( + value, + curve[0].segments_num, + REGAMMA_CNTLA_REGION_8_9, + REGAMMA_CNTLA_EXP_REGION8_NUM_SEGMENTS); + + set_reg_field_value( + value, + curve[1].offset, + REGAMMA_CNTLA_REGION_8_9, + REGAMMA_CNTLA_EXP_REGION9_LUT_OFFSET); + + set_reg_field_value( + value, + curve[1].segments_num, + REGAMMA_CNTLA_REGION_8_9, + REGAMMA_CNTLA_EXP_REGION9_NUM_SEGMENTS); + + dm_write_reg(opp80->base.ctx, + DCP_REG(mmREGAMMA_CNTLA_REGION_8_9), + value); + } + + curve += 2; + { + value = 0; + set_reg_field_value( + value, + curve[0].offset, + REGAMMA_CNTLA_REGION_10_11, + REGAMMA_CNTLA_EXP_REGION10_LUT_OFFSET); + + set_reg_field_value( + value, + curve[0].segments_num, + REGAMMA_CNTLA_REGION_10_11, + REGAMMA_CNTLA_EXP_REGION10_NUM_SEGMENTS); + + set_reg_field_value( + value, + curve[1].offset, + REGAMMA_CNTLA_REGION_10_11, + REGAMMA_CNTLA_EXP_REGION11_LUT_OFFSET); + + set_reg_field_value( + value, + curve[1].segments_num, + REGAMMA_CNTLA_REGION_10_11, + REGAMMA_CNTLA_EXP_REGION11_NUM_SEGMENTS); + + dm_write_reg(opp80->base.ctx, + DCP_REG(mmREGAMMA_CNTLA_REGION_10_11), + value); + } + + curve += 2; + { + value = 0; + set_reg_field_value( + value, + curve[0].offset, + REGAMMA_CNTLA_REGION_12_13, + REGAMMA_CNTLA_EXP_REGION12_LUT_OFFSET); + + set_reg_field_value( + value, + curve[0].segments_num, + REGAMMA_CNTLA_REGION_12_13, + REGAMMA_CNTLA_EXP_REGION12_NUM_SEGMENTS); + + set_reg_field_value( + value, + curve[1].offset, + REGAMMA_CNTLA_REGION_12_13, + REGAMMA_CNTLA_EXP_REGION13_LUT_OFFSET); + + set_reg_field_value( + value, + curve[1].segments_num, + REGAMMA_CNTLA_REGION_12_13, + REGAMMA_CNTLA_EXP_REGION13_NUM_SEGMENTS); + + dm_write_reg(opp80->base.ctx, + DCP_REG(mmREGAMMA_CNTLA_REGION_12_13), + value); + } + + curve += 2; + { + value = 0; + set_reg_field_value( + value, + curve[0].offset, + REGAMMA_CNTLA_REGION_14_15, + REGAMMA_CNTLA_EXP_REGION14_LUT_OFFSET); + + set_reg_field_value( + value, + curve[0].segments_num, + REGAMMA_CNTLA_REGION_14_15, + REGAMMA_CNTLA_EXP_REGION14_NUM_SEGMENTS); + + set_reg_field_value( + value, + curve[1].offset, + REGAMMA_CNTLA_REGION_14_15, + REGAMMA_CNTLA_EXP_REGION15_LUT_OFFSET); + + set_reg_field_value( + value, + curve[1].segments_num, + REGAMMA_CNTLA_REGION_14_15, + REGAMMA_CNTLA_EXP_REGION15_NUM_SEGMENTS); + + dm_write_reg(opp80->base.ctx, + DCP_REG(mmREGAMMA_CNTLA_REGION_14_15), + value); + } +} + +static void program_pwl( + struct dce80_opp *opp80, + const struct pwl_params *params) +{ + uint32_t value; + + { + uint8_t max_tries = 10; + uint8_t counter = 0; + + /* Power on LUT memory */ + value = dm_read_reg(opp80->base.ctx, + DCFE_REG(mmDCFE_MEM_LIGHT_SLEEP_CNTL)); + + set_reg_field_value( + value, + 1, + DCFE_MEM_LIGHT_SLEEP_CNTL, + REGAMMA_LUT_LIGHT_SLEEP_DIS); + + dm_write_reg(opp80->base.ctx, + DCFE_REG(mmDCFE_MEM_LIGHT_SLEEP_CNTL), value); + + while (counter < max_tries) { + value = + dm_read_reg( + opp80->base.ctx, + DCFE_REG(mmDCFE_MEM_LIGHT_SLEEP_CNTL)); + + if (get_reg_field_value( + value, + DCFE_MEM_LIGHT_SLEEP_CNTL, + REGAMMA_LUT_MEM_PWR_STATE) == 0) + break; + + ++counter; + } + + if (counter == max_tries) { + dm_logger_write(opp80->base.ctx->logger, LOG_WARNING, + "%s: regamma lut was not powered on " + "in a timely manner," + " programming still proceeds\n", + __func__); + } + } + + value = 0; + + set_reg_field_value( + value, + 7, + REGAMMA_LUT_WRITE_EN_MASK, + REGAMMA_LUT_WRITE_EN_MASK); + + dm_write_reg(opp80->base.ctx, + DCP_REG(mmREGAMMA_LUT_WRITE_EN_MASK), value); + dm_write_reg(opp80->base.ctx, + DCP_REG(mmREGAMMA_LUT_INDEX), 0); + + /* Program REGAMMA_LUT_DATA */ + { + const uint32_t addr = DCP_REG(mmREGAMMA_LUT_DATA); + + uint32_t i = 0; + + const struct pwl_result_data *rgb = + params->rgb_resulted; + + while (i != params->hw_points_num) { + dm_write_reg(opp80->base.ctx, addr, rgb->red_reg); + dm_write_reg(opp80->base.ctx, addr, rgb->green_reg); + dm_write_reg(opp80->base.ctx, addr, rgb->blue_reg); + + dm_write_reg(opp80->base.ctx, addr, + rgb->delta_red_reg); + dm_write_reg(opp80->base.ctx, addr, + rgb->delta_green_reg); + dm_write_reg(opp80->base.ctx, addr, + rgb->delta_blue_reg); + + ++rgb; + ++i; + } + } + + /* we are done with DCP LUT memory; re-enable low power mode */ + value = dm_read_reg(opp80->base.ctx, + DCFE_REG(mmDCFE_MEM_LIGHT_SLEEP_CNTL)); + + set_reg_field_value( + value, + 0, + DCFE_MEM_LIGHT_SLEEP_CNTL, + REGAMMA_LUT_LIGHT_SLEEP_DIS); + + dm_write_reg(opp80->base.ctx, DCFE_REG(mmDCFE_MEM_LIGHT_SLEEP_CNTL), + value); +} + +void dce80_opp_power_on_regamma_lut( + struct output_pixel_processor *opp, + bool power_on) +{ + struct dce80_opp *opp80 = TO_DCE80_OPP(opp); + + uint32_t value = + dm_read_reg(opp->ctx, DCFE_REG(mmDCFE_MEM_LIGHT_SLEEP_CNTL)); + + set_reg_field_value( + value, + power_on, + DCFE_MEM_LIGHT_SLEEP_CNTL, + REGAMMA_LUT_LIGHT_SLEEP_DIS); + + set_reg_field_value( + value, + power_on, + DCFE_MEM_LIGHT_SLEEP_CNTL, + DCP_LUT_LIGHT_SLEEP_DIS); + + dm_write_reg(opp->ctx, DCFE_REG(mmDCFE_MEM_LIGHT_SLEEP_CNTL), value); +} + +bool dce80_opp_program_regamma_pwl( + struct output_pixel_processor *opp, + const struct pwl_params *params) +{ + + struct dce80_opp *opp80 = TO_DCE80_OPP(opp); + + regamma_config_regions_and_segments(opp80, params); + + program_pwl(opp80, params); + + return true; +} + +void dce80_opp_set_regamma_mode(struct output_pixel_processor *opp, + enum opp_regamma mode) +{ + struct dce80_opp *opp80 = TO_DCE80_OPP(opp); + uint32_t value = dm_read_reg(opp80->base.ctx, + DCP_REG(mmREGAMMA_CONTROL)); + + set_reg_field_value( + value, + mode, + REGAMMA_CONTROL, + GRPH_REGAMMA_MODE); + + dm_write_reg(opp80->base.ctx, DCP_REG(mmREGAMMA_CONTROL), value); +} diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c new file mode 100644 index 000000000000..06720407b6fc --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -0,0 +1,1063 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dce/dce_8_0_d.h" +#include "dce/dce_8_0_sh_mask.h" + +#include "dm_services.h" + +#include "link_encoder.h" +#include "stream_encoder.h" + +#include "resource.h" +#include "include/irq_service_interface.h" +#include "irq/dce80/irq_service_dce80.h" +#include "dce110/dce110_timing_generator.h" +#include "dce110/dce110_mem_input.h" +#include "dce110/dce110_resource.h" +#include "dce80/dce80_timing_generator.h" +#include "dce/dce_link_encoder.h" +#include "dce/dce_stream_encoder.h" +#include "dce80/dce80_mem_input.h" +#include "dce80/dce80_ipp.h" +#include "dce/dce_transform.h" +#include "dce80/dce80_opp.h" +#include "dce110/dce110_ipp.h" +#include "dce/dce_clock_source.h" +#include "dce/dce_audio.h" +#include "dce/dce_hwseq.h" +#include "dce80/dce80_hw_sequencer.h" + +#include "reg_helper.h" + +/* TODO remove this include */ + +#ifndef mmMC_HUB_RDREQ_DMIF_LIMIT +#include "gmc/gmc_7_1_d.h" +#include "gmc/gmc_7_1_sh_mask.h" +#endif + +#ifndef mmDP_DPHY_INTERNAL_CTRL +#define mmDP_DPHY_INTERNAL_CTRL 0x1CDE +#define mmDP0_DP_DPHY_INTERNAL_CTRL 0x1CDE +#define mmDP1_DP_DPHY_INTERNAL_CTRL 0x1FDE +#define mmDP2_DP_DPHY_INTERNAL_CTRL 0x42DE +#define mmDP3_DP_DPHY_INTERNAL_CTRL 0x45DE +#define mmDP4_DP_DPHY_INTERNAL_CTRL 0x48DE +#define mmDP5_DP_DPHY_INTERNAL_CTRL 0x4BDE +#define mmDP6_DP_DPHY_INTERNAL_CTRL 0x4EDE +#endif + + +#ifndef mmBIOS_SCRATCH_2 + #define mmBIOS_SCRATCH_2 0x05CB + #define mmBIOS_SCRATCH_6 0x05CF +#endif + +#ifndef mmDP_DPHY_FAST_TRAINING + #define mmDP_DPHY_FAST_TRAINING 0x1CCE + #define mmDP0_DP_DPHY_FAST_TRAINING 0x1CCE + #define mmDP1_DP_DPHY_FAST_TRAINING 0x1FCE + #define mmDP2_DP_DPHY_FAST_TRAINING 0x42CE + #define mmDP3_DP_DPHY_FAST_TRAINING 0x45CE + #define mmDP4_DP_DPHY_FAST_TRAINING 0x48CE + #define mmDP5_DP_DPHY_FAST_TRAINING 0x4BCE + #define mmDP6_DP_DPHY_FAST_TRAINING 0x4ECE +#endif + + +#ifndef mmHPD_DC_HPD_CONTROL + #define mmHPD_DC_HPD_CONTROL 0x189A + #define mmHPD0_DC_HPD_CONTROL 0x189A + #define mmHPD1_DC_HPD_CONTROL 0x18A2 + #define mmHPD2_DC_HPD_CONTROL 0x18AA + #define mmHPD3_DC_HPD_CONTROL 0x18B2 + #define mmHPD4_DC_HPD_CONTROL 0x18BA + #define mmHPD5_DC_HPD_CONTROL 0x18C2 +#endif + +#define DCE11_DIG_FE_CNTL 0x4a00 +#define DCE11_DIG_BE_CNTL 0x4a47 +#define DCE11_DP_SEC 0x4ac3 + +static const struct dce110_timing_generator_offsets dce80_tg_offsets[] = { + { + .crtc = (mmCRTC0_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmGRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + }, + { + .crtc = (mmCRTC1_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG1_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + }, + { + .crtc = (mmCRTC2_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG2_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + }, + { + .crtc = (mmCRTC3_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG3_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + }, + { + .crtc = (mmCRTC4_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG4_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + }, + { + .crtc = (mmCRTC5_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG5_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + } +}; + +static const struct dce110_mem_input_reg_offsets dce80_mi_reg_offsets[] = { + { + .dcp = (mmGRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE0_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + }, + { + .dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG1_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE1_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + }, + { + .dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG2_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE2_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + }, + { + .dcp = (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG3_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE3_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + }, + { + .dcp = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG4_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE4_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + }, + { + .dcp = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG5_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE5_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + } +}; + +static const struct dce110_ipp_reg_offsets ipp_reg_offsets[] = { +{ + .dcp_offset = (mmDCP0_CUR_CONTROL - mmDCP0_CUR_CONTROL), +}, +{ + .dcp_offset = (mmDCP1_CUR_CONTROL - mmDCP0_CUR_CONTROL), +}, +{ + .dcp_offset = (mmDCP2_CUR_CONTROL - mmDCP0_CUR_CONTROL), +}, +{ + .dcp_offset = (mmDCP3_CUR_CONTROL - mmDCP0_CUR_CONTROL), +}, +{ + .dcp_offset = (mmDCP4_CUR_CONTROL - mmDCP0_CUR_CONTROL), +}, +{ + .dcp_offset = (mmDCP5_CUR_CONTROL - mmDCP0_CUR_CONTROL), +} +}; + +/* set register offset */ +#define SR(reg_name)\ + .reg_name = mm ## reg_name + +/* set register offset with instance */ +#define SRI(reg_name, block, id)\ + .reg_name = mm ## block ## id ## _ ## reg_name + +#define transform_regs(id)\ +[id] = {\ + XFM_COMMON_REG_LIST_DCE_BASE(id)\ +} + +static const struct dce_transform_registers xfm_regs[] = { + transform_regs(0), + transform_regs(1), + transform_regs(2), + transform_regs(3), + transform_regs(4), + transform_regs(5) +}; + +static const struct dce_transform_shift xfm_shift = { + XFM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) +}; + +static const struct dce_transform_mask xfm_mask = { + XFM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) +}; + +#define aux_regs(id)\ +[id] = {\ + AUX_REG_LIST(id)\ +} + +static const struct dce110_link_enc_aux_registers link_enc_aux_regs[] = { + aux_regs(0), + aux_regs(1), + aux_regs(2), + aux_regs(3), + aux_regs(4), + aux_regs(5) +}; + +#define hpd_regs(id)\ +[id] = {\ + HPD_REG_LIST(id)\ +} + +static const struct dce110_link_enc_hpd_registers link_enc_hpd_regs[] = { + hpd_regs(0), + hpd_regs(1), + hpd_regs(2), + hpd_regs(3), + hpd_regs(4), + hpd_regs(5) +}; + +#define link_regs(id)\ +[id] = {\ + LE_DCE80_REG_LIST(id)\ +} + +static const struct dce110_link_enc_registers link_enc_regs[] = { + link_regs(0), + link_regs(1), + link_regs(2), + link_regs(3), + link_regs(4), + link_regs(5), + link_regs(6), +}; + +#define stream_enc_regs(id)\ +[id] = {\ + SE_COMMON_REG_LIST_DCE_BASE(id),\ + .AFMT_CNTL = 0,\ +} + +static const struct dce110_stream_enc_registers stream_enc_regs[] = { + stream_enc_regs(0), + stream_enc_regs(1), + stream_enc_regs(2), + stream_enc_regs(3), + stream_enc_regs(4), + stream_enc_regs(5) +}; + +static const struct dce_stream_encoder_shift se_shift = { + SE_COMMON_MASK_SH_LIST_DCE80_100(__SHIFT) +}; + +static const struct dce_stream_encoder_mask se_mask = { + SE_COMMON_MASK_SH_LIST_DCE80_100(_MASK) +}; + +#define audio_regs(id)\ +[id] = {\ + AUD_COMMON_REG_LIST(id)\ +} + +static const struct dce_audio_registers audio_regs[] = { + audio_regs(0), + audio_regs(1), + audio_regs(2), + audio_regs(3), + audio_regs(4), + audio_regs(5), + audio_regs(6), +}; + +static const struct dce_audio_shift audio_shift = { + AUD_COMMON_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_aduio_mask audio_mask = { + AUD_COMMON_MASK_SH_LIST(_MASK) +}; + +#define clk_src_regs(id)\ +[id] = {\ + CS_COMMON_REG_LIST_DCE_80(id),\ +} + + +static const struct dce110_clk_src_regs clk_src_regs[] = { + clk_src_regs(0), + clk_src_regs(1), + clk_src_regs(2) +}; + +static const struct dce110_clk_src_shift cs_shift = { + CS_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) +}; + +static const struct dce110_clk_src_mask cs_mask = { + CS_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) +}; + +static const struct bios_registers bios_regs = { + .BIOS_SCRATCH_6 = mmBIOS_SCRATCH_6 +}; + +static const struct resource_caps res_cap = { + .num_timing_generator = 6, + .num_audio = 6, + .num_stream_encoder = 6, + .num_pll = 3, +}; + +#define CTX ctx +#define REG(reg) mm ## reg + +#ifndef mmCC_DC_HDMI_STRAPS +#define mmCC_DC_HDMI_STRAPS 0x1918 +#define CC_DC_HDMI_STRAPS__HDMI_DISABLE_MASK 0x40 +#define CC_DC_HDMI_STRAPS__HDMI_DISABLE__SHIFT 0x6 +#define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER_MASK 0x700 +#define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER__SHIFT 0x8 +#endif + +static void read_dce_straps( + struct dc_context *ctx, + struct resource_straps *straps) +{ + REG_GET_2(CC_DC_HDMI_STRAPS, + HDMI_DISABLE, &straps->hdmi_disable, + AUDIO_STREAM_NUMBER, &straps->audio_stream_number); + + REG_GET(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO, &straps->dc_pinstraps_audio); +} + +static struct audio *create_audio( + struct dc_context *ctx, unsigned int inst) +{ + return dce_audio_create(ctx, inst, + &audio_regs[inst], &audio_shift, &audio_mask); +} + +static struct timing_generator *dce80_timing_generator_create( + struct dc_context *ctx, + uint32_t instance, + const struct dce110_timing_generator_offsets *offsets) +{ + struct dce110_timing_generator *tg110 = + dm_alloc(sizeof(struct dce110_timing_generator)); + + if (!tg110) + return NULL; + + if (dce80_timing_generator_construct(tg110, ctx, instance, offsets)) + return &tg110->base; + + BREAK_TO_DEBUGGER(); + dm_free(tg110); + return NULL; +} + +static struct stream_encoder *dce80_stream_encoder_create( + enum engine_id eng_id, + struct dc_context *ctx) +{ + struct dce110_stream_encoder *enc110 = + dm_alloc(sizeof(struct dce110_stream_encoder)); + + if (!enc110) + return NULL; + + if (dce110_stream_encoder_construct( + enc110, ctx, ctx->dc_bios, eng_id, + &stream_enc_regs[eng_id], &se_shift, &se_mask)) + return &enc110->base; + + BREAK_TO_DEBUGGER(); + dm_free(enc110); + return NULL; +} + +#define SRII(reg_name, block, id)\ + .reg_name[id] = mm ## block ## id ## _ ## reg_name + +static const struct dce_hwseq_registers hwseq_reg = { + HWSEQ_DCE8_REG_LIST() +}; + +static const struct dce_hwseq_shift hwseq_shift = { + HWSEQ_DCE8_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_hwseq_mask hwseq_mask = { + HWSEQ_DCE8_MASK_SH_LIST(_MASK) +}; + +static struct dce_hwseq *dce80_hwseq_create( + struct dc_context *ctx) +{ + struct dce_hwseq *hws = dm_alloc(sizeof(struct dce_hwseq)); + + if (hws) { + hws->ctx = ctx; + hws->regs = &hwseq_reg; + hws->shifts = &hwseq_shift; + hws->masks = &hwseq_mask; + } + return hws; +} + +static const struct resource_create_funcs res_create_funcs = { + .read_dce_straps = read_dce_straps, + .create_audio = create_audio, + .create_stream_encoder = dce80_stream_encoder_create, + .create_hwseq = dce80_hwseq_create, +}; + +#define mi_inst_regs(id) { \ + MI_REG_LIST(id), \ + .MC_HUB_RDREQ_DMIF_LIMIT = mmMC_HUB_RDREQ_DMIF_LIMIT \ +} +static const struct dce_mem_input_registers mi_regs[] = { + mi_inst_regs(0), + mi_inst_regs(1), + mi_inst_regs(2), + mi_inst_regs(3), + mi_inst_regs(4), + mi_inst_regs(5), +}; + +static const struct dce_mem_input_shift mi_shifts = { + MI_DCE_MASK_SH_LIST(__SHIFT), + .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE__SHIFT +}; + +static const struct dce_mem_input_mask mi_masks = { + MI_DCE_MASK_SH_LIST(_MASK), + .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE_MASK +}; + +static struct mem_input *dce80_mem_input_create( + struct dc_context *ctx, + uint32_t inst, + const struct dce110_mem_input_reg_offsets *offsets) +{ + struct dce110_mem_input *mem_input80 = + dm_alloc(sizeof(struct dce110_mem_input)); + + if (!mem_input80) + return NULL; + + if (dce80_mem_input_construct(mem_input80, ctx, inst, offsets)) { + struct mem_input *mi = &mem_input80->base; + + mi->regs = &mi_regs[inst]; + mi->shifts = &mi_shifts; + mi->masks = &mi_masks; + mi->wa.single_head_rdreq_dmif_limit = 2; + return mi; + } + + BREAK_TO_DEBUGGER(); + dm_free(mem_input80); + return NULL; +} + +static void dce80_transform_destroy(struct transform **xfm) +{ + dm_free(TO_DCE_TRANSFORM(*xfm)); + *xfm = NULL; +} + +static struct transform *dce80_transform_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dce_transform *transform = + dm_alloc(sizeof(struct dce_transform)); + + if (!transform) + return NULL; + + if (dce_transform_construct(transform, ctx, inst, + &xfm_regs[inst], &xfm_shift, &xfm_mask)) { + transform->prescaler_on = false; + return &transform->base; + } + + BREAK_TO_DEBUGGER(); + dm_free(transform); + return NULL; +} + +static struct input_pixel_processor *dce80_ipp_create( + struct dc_context *ctx, + uint32_t inst, + const struct dce110_ipp_reg_offsets *offset) +{ + struct dce110_ipp *ipp = + dm_alloc(sizeof(struct dce110_ipp)); + + if (!ipp) + return NULL; + + if (dce80_ipp_construct(ipp, ctx, inst, offset)) + return &ipp->base; + + BREAK_TO_DEBUGGER(); + dm_free(ipp); + return NULL; +} + +struct link_encoder *dce80_link_encoder_create( + const struct encoder_init_data *enc_init_data) +{ + struct dce110_link_encoder *enc110 = + dm_alloc(sizeof(struct dce110_link_encoder)); + + if (!enc110) + return NULL; + + if (dce110_link_encoder_construct( + enc110, + enc_init_data, + &link_enc_regs[enc_init_data->transmitter], + &link_enc_aux_regs[enc_init_data->channel - 1], + &link_enc_hpd_regs[enc_init_data->hpd_source])) { + + enc110->base.features.ycbcr420_supported = false; + enc110->base.features.max_hdmi_pixel_clock = 297000; + return &enc110->base; + } + + BREAK_TO_DEBUGGER(); + dm_free(enc110); + return NULL; +} + +struct clock_source *dce80_clock_source_create( + struct dc_context *ctx, + struct dc_bios *bios, + enum clock_source_id id, + const struct dce110_clk_src_regs *regs, + bool dp_clk_src) +{ + struct dce110_clk_src *clk_src = + dm_alloc(sizeof(struct dce110_clk_src)); + + if (!clk_src) + return NULL; + + if (dce110_clk_src_construct(clk_src, ctx, bios, id, + regs, &cs_shift, &cs_mask)) { + clk_src->base.dp_clk_src = dp_clk_src; + return &clk_src->base; + } + + BREAK_TO_DEBUGGER(); + return NULL; +} + +void dce80_clock_source_destroy(struct clock_source **clk_src) +{ + dm_free(TO_DCE110_CLK_SRC(*clk_src)); + *clk_src = NULL; +} + +static void destruct(struct dce110_resource_pool *pool) +{ + unsigned int i; + + for (i = 0; i < pool->base.pipe_count; i++) { + if (pool->base.opps[i] != NULL) + dce80_opp_destroy(&pool->base.opps[i]); + + if (pool->base.transforms[i] != NULL) + dce80_transform_destroy(&pool->base.transforms[i]); + + if (pool->base.ipps[i] != NULL) + dce80_ipp_destroy(&pool->base.ipps[i]); + + if (pool->base.mis[i] != NULL) { + dm_free(TO_DCE110_MEM_INPUT(pool->base.mis[i])); + pool->base.mis[i] = NULL; + } + + if (pool->base.timing_generators[i] != NULL) { + dm_free(DCE110TG_FROM_TG(pool->base.timing_generators[i])); + pool->base.timing_generators[i] = NULL; + } + } + + for (i = 0; i < pool->base.stream_enc_count; i++) { + if (pool->base.stream_enc[i] != NULL) + dm_free(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); + } + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] != NULL) { + dce80_clock_source_destroy(&pool->base.clock_sources[i]); + } + } + + if (pool->base.dp_clock_source != NULL) + dce80_clock_source_destroy(&pool->base.dp_clock_source); + + for (i = 0; i < pool->base.audio_count; i++) { + if (pool->base.audios[i] != NULL) { + dce_aud_destroy(&pool->base.audios[i]); + } + } + + if (pool->base.display_clock != NULL) { + dal_display_clock_destroy(&pool->base.display_clock); + } + + if (pool->base.irqs != NULL) { + dal_irq_service_destroy(&pool->base.irqs); + } +} + +static enum dc_status validate_mapped_resource( + const struct core_dc *dc, + struct validate_context *context) +{ + enum dc_status status = DC_OK; + uint8_t i, j, k; + + for (i = 0; i < context->target_count; i++) { + struct core_target *target = context->targets[i]; + + for (j = 0; j < target->public.stream_count; j++) { + struct core_stream *stream = + DC_STREAM_TO_CORE(target->public.streams[j]); + struct core_link *link = stream->sink->link; + + if (resource_is_stream_unchanged(dc->current_context, stream)) + continue; + + for (k = 0; k < MAX_PIPES; k++) { + struct pipe_ctx *pipe_ctx = + &context->res_ctx.pipe_ctx[k]; + + if (context->res_ctx.pipe_ctx[k].stream != stream) + continue; + + if (!pipe_ctx->tg->funcs->validate_timing( + pipe_ctx->tg, &stream->public.timing)) + return DC_FAIL_CONTROLLER_VALIDATE; + + status = dce110_resource_build_pipe_hw_param(pipe_ctx); + + if (status != DC_OK) + return status; + + if (!link->link_enc->funcs->validate_output_with_stream( + link->link_enc, + pipe_ctx)) + return DC_FAIL_ENC_VALIDATE; + + /* TODO: validate audio ASIC caps, encoder */ + + status = dc_link_validate_mode_timing(stream, + link, + &stream->public.timing); + + if (status != DC_OK) + return status; + + resource_build_info_frame(pipe_ctx); + + /* do not need to validate non root pipes */ + break; + } + } + } + + return DC_OK; +} + +enum dc_status dce80_validate_bandwidth( + const struct core_dc *dc, + struct validate_context *context) +{ + /* TODO implement when needed but for now hardcode max value*/ + context->bw_results.dispclk_khz = 681000; + context->bw_results.required_yclk = 250000 * MEMORY_TYPE_MULTIPLIER; + + return DC_OK; +} + +static bool dce80_validate_surface_sets( + const struct dc_validation_set set[], + int set_count) +{ + int i; + + for (i = 0; i < set_count; i++) { + if (set[i].surface_count == 0) + continue; + + if (set[i].surface_count > 1) + return false; + + if (set[i].surfaces[0]->clip_rect.width + != set[i].target->streams[0]->src.width + || set[i].surfaces[0]->clip_rect.height + != set[i].target->streams[0]->src.height) + return false; + if (set[i].surfaces[0]->format + >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) + return false; + } + + return true; +} + +enum dc_status dce80_validate_with_context( + const struct core_dc *dc, + const struct dc_validation_set set[], + int set_count, + struct validate_context *context) +{ + struct dc_context *dc_ctx = dc->ctx; + enum dc_status result = DC_ERROR_UNEXPECTED; + int i; + + if (!dce80_validate_surface_sets(set, set_count)) + return DC_FAIL_SURFACE_VALIDATE; + + context->res_ctx.pool = dc->res_pool; + + for (i = 0; i < set_count; i++) { + context->targets[i] = DC_TARGET_TO_CORE(set[i].target); + dc_target_retain(&context->targets[i]->public); + context->target_count++; + } + + result = resource_map_pool_resources(dc, context); + + if (result == DC_OK) + result = resource_map_clock_resources(dc, context); + + if (!resource_validate_attach_surfaces( + set, set_count, dc->current_context, context)) { + DC_ERROR("Failed to attach surface to target!\n"); + return DC_FAIL_ATTACH_SURFACES; + } + + if (result == DC_OK) + result = validate_mapped_resource(dc, context); + + if (result == DC_OK) + result = resource_build_scaling_params_for_context(dc, context); + + if (result == DC_OK) + result = dce80_validate_bandwidth(dc, context); + + return result; +} + +enum dc_status dce80_validate_guaranteed( + const struct core_dc *dc, + const struct dc_target *dc_target, + struct validate_context *context) +{ + enum dc_status result = DC_ERROR_UNEXPECTED; + + context->res_ctx.pool = dc->res_pool; + + context->targets[0] = DC_TARGET_TO_CORE(dc_target); + dc_target_retain(&context->targets[0]->public); + context->target_count++; + + result = resource_map_pool_resources(dc, context); + + if (result == DC_OK) + result = resource_map_clock_resources(dc, context); + + if (result == DC_OK) + result = validate_mapped_resource(dc, context); + + if (result == DC_OK) { + validate_guaranteed_copy_target( + context, dc->public.caps.max_targets); + result = resource_build_scaling_params_for_context(dc, context); + } + + if (result == DC_OK) + result = dce80_validate_bandwidth(dc, context); + + return result; +} + +static void dce80_destroy_resource_pool(struct resource_pool **pool) +{ + struct dce110_resource_pool *dce110_pool = TO_DCE110_RES_POOL(*pool); + + destruct(dce110_pool); + dm_free(dce110_pool); + *pool = NULL; +} + +static const struct resource_funcs dce80_res_pool_funcs = { + .destroy = dce80_destroy_resource_pool, + .link_enc_create = dce80_link_encoder_create, + .validate_with_context = dce80_validate_with_context, + .validate_guaranteed = dce80_validate_guaranteed, + .validate_bandwidth = dce80_validate_bandwidth +}; + +static enum clocks_state dce80_resource_convert_clock_state_pp_to_dc( + enum dm_pp_clocks_state pp_clock_state) +{ + enum clocks_state dc_clocks_state = CLOCKS_STATE_INVALID; + + switch (pp_clock_state) { + case DM_PP_CLOCKS_STATE_INVALID: + dc_clocks_state = CLOCKS_STATE_INVALID; + break; + case DM_PP_CLOCKS_STATE_ULTRA_LOW: + dc_clocks_state = CLOCKS_STATE_ULTRA_LOW; + break; + case DM_PP_CLOCKS_STATE_LOW: + dc_clocks_state = CLOCKS_STATE_LOW; + break; + case DM_PP_CLOCKS_STATE_NOMINAL: + dc_clocks_state = CLOCKS_STATE_NOMINAL; + break; + case DM_PP_CLOCKS_STATE_PERFORMANCE: + dc_clocks_state = CLOCKS_STATE_PERFORMANCE; + break; + case DM_PP_CLOCKS_DPM_STATE_LEVEL_4: + dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_4; + break; + case DM_PP_CLOCKS_DPM_STATE_LEVEL_5: + dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_5; + break; + case DM_PP_CLOCKS_DPM_STATE_LEVEL_6: + dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_6; + break; + case DM_PP_CLOCKS_DPM_STATE_LEVEL_7: + dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_7; + break; + default: + dc_clocks_state = CLOCKS_STATE_INVALID; + break; + } + + return dc_clocks_state; +} + +static bool construct( + uint8_t num_virtual_links, + struct core_dc *dc, + struct dce110_resource_pool *pool) +{ + unsigned int i; + struct dc_context *ctx = dc->ctx; + struct firmware_info info; + struct dc_bios *bp; + struct dm_pp_static_clock_info static_clk_info = {0}; + + ctx->dc_bios->regs = &bios_regs; + + pool->base.res_cap = &res_cap; + pool->base.funcs = &dce80_res_pool_funcs; + + + /************************************************* + * Resource + asic cap harcoding * + *************************************************/ + pool->base.underlay_pipe_index = -1; + pool->base.pipe_count = res_cap.num_timing_generator; + dc->public.caps.max_downscale_ratio = 200; + dc->public.caps.i2c_speed_in_khz = 40; + + /************************************************* + * Create resources * + *************************************************/ + + bp = ctx->dc_bios; + + if ((bp->funcs->get_firmware_info(bp, &info) == BP_RESULT_OK) && + info.external_clock_source_frequency_for_dp != 0) { + pool->base.dp_clock_source = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true); + + pool->base.clock_sources[0] = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], false); + pool->base.clock_sources[1] = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false); + pool->base.clock_sources[2] = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false); + pool->base.clk_src_count = 3; + + } else { + pool->base.dp_clock_source = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], true); + + pool->base.clock_sources[0] = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false); + pool->base.clock_sources[1] = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false); + pool->base.clk_src_count = 2; + } + + if (pool->base.dp_clock_source == NULL) { + dm_error("DC: failed to create dp clock source!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] == NULL) { + dm_error("DC: failed to create clock sources!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + } + + pool->base.display_clock = dal_display_clock_dce80_create(ctx); + if (pool->base.display_clock == NULL) { + dm_error("DC: failed to create display clock!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + + if (dm_pp_get_static_clocks(ctx, &static_clk_info)) { + enum clocks_state max_clocks_state = + dce80_resource_convert_clock_state_pp_to_dc( + static_clk_info.max_clocks_state); + + dal_display_clock_store_max_clocks_state( + pool->base.display_clock, max_clocks_state); + } + + { + struct irq_service_init_data init_data; + init_data.ctx = dc->ctx; + pool->base.irqs = dal_irq_service_dce80_create(&init_data); + if (!pool->base.irqs) + goto res_create_fail; + } + + for (i = 0; i < pool->base.pipe_count; i++) { + pool->base.timing_generators[i] = dce80_timing_generator_create( + ctx, i, &dce80_tg_offsets[i]); + if (pool->base.timing_generators[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create tg!\n"); + goto res_create_fail; + } + + pool->base.mis[i] = dce80_mem_input_create(ctx, i, + &dce80_mi_reg_offsets[i]); + if (pool->base.mis[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create memory input!\n"); + goto res_create_fail; + } + + pool->base.ipps[i] = dce80_ipp_create(ctx, i, &ipp_reg_offsets[i]); + if (pool->base.ipps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create input pixel processor!\n"); + goto res_create_fail; + } + + pool->base.transforms[i] = dce80_transform_create(ctx, i); + if (pool->base.transforms[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create transform!\n"); + goto res_create_fail; + } + + pool->base.opps[i] = dce80_opp_create(ctx, i); + if (pool->base.opps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create output pixel processor!\n"); + goto res_create_fail; + } + } + + if (!resource_construct(num_virtual_links, dc, &pool->base, + &res_create_funcs)) + goto res_create_fail; + + /* Create hardware sequencer */ + if (!dce80_hw_sequencer_construct(dc)) + goto res_create_fail; + + return true; + +res_create_fail: + destruct(pool); + return false; +} + +struct resource_pool *dce80_create_resource_pool( + uint8_t num_virtual_links, + struct core_dc *dc) +{ + struct dce110_resource_pool *pool = + dm_alloc(sizeof(struct dce110_resource_pool)); + + if (!pool) + return NULL; + + if (construct(num_virtual_links, dc, pool)) + return &pool->base; + + BREAK_TO_DEBUGGER(); + return NULL; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.h b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.h new file mode 100644 index 000000000000..2a0cdccddeaf --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.h @@ -0,0 +1,39 @@ +/* +* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_RESOURCE_DCE80_H__ +#define __DC_RESOURCE_DCE80_H__ + +#include "core_types.h" + +struct core_dc; +struct resource_pool; + +struct resource_pool *dce80_create_resource_pool( + uint8_t num_virtual_links, + struct core_dc *dc); + +#endif /* __DC_RESOURCE_DCE80_H__ */ + diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c new file mode 100644 index 000000000000..e8fae0a7eeb4 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c @@ -0,0 +1,241 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* include DCE8 register header files */ +#include "dce/dce_8_0_d.h" +#include "dce/dce_8_0_sh_mask.h" + +#include "dc_types.h" + +#include "include/grph_object_id.h" +#include "include/logger_interface.h" +#include "../dce110/dce110_timing_generator.h" +#include "dce80_timing_generator.h" + +#include "timing_generator.h" + +enum black_color_format { + BLACK_COLOR_FORMAT_RGB_FULLRANGE = 0, /* used as index in array */ + BLACK_COLOR_FORMAT_RGB_LIMITED, + BLACK_COLOR_FORMAT_YUV_TV, + BLACK_COLOR_FORMAT_YUV_CV, + BLACK_COLOR_FORMAT_YUV_SUPER_AA, + + BLACK_COLOR_FORMAT_COUNT +}; + +static const struct dce110_timing_generator_offsets reg_offsets[] = { +{ + .crtc = (mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL - mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL), + .dcp = (mmDCP0_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ + .crtc = (mmCRTC1_DCFE_MEM_LIGHT_SLEEP_CNTL - mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL), + .dcp = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ + .crtc = (mmCRTC2_DCFE_MEM_LIGHT_SLEEP_CNTL - mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL), + .dcp = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ + .crtc = (mmCRTC3_DCFE_MEM_LIGHT_SLEEP_CNTL - mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL), + .dcp = (mmDCP3_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ + .crtc = (mmCRTC4_DCFE_MEM_LIGHT_SLEEP_CNTL - mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL), + .dcp = (mmDCP4_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ + .crtc = (mmCRTC5_DCFE_MEM_LIGHT_SLEEP_CNTL - mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL), + .dcp = (mmDCP5_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +} +}; + +#define NUMBER_OF_FRAME_TO_WAIT_ON_TRIGGERED_RESET 10 + +#define MAX_H_TOTAL (CRTC_H_TOTAL__CRTC_H_TOTAL_MASK + 1) +#define MAX_V_TOTAL (CRTC_V_TOTAL__CRTC_V_TOTAL_MASKhw + 1) + +#define CRTC_REG(reg) (reg + tg110->offsets.crtc) +#define DCP_REG(reg) (reg + tg110->offsets.dcp) +#define DMIF_REG(reg) (reg + tg110->offsets.dmif) + +void program_pix_dur(struct timing_generator *tg, uint32_t pix_clk_khz) +{ + uint64_t pix_dur; + uint32_t addr = mmDMIF_PG0_DPG_PIPE_ARBITRATION_CONTROL1 + + DCE110TG_FROM_TG(tg)->offsets.dmif; + uint32_t value = dm_read_reg(tg->ctx, addr); + + if (pix_clk_khz == 0) + return; + + pix_dur = 1000000000 / pix_clk_khz; + + set_reg_field_value( + value, + pix_dur, + DPG_PIPE_ARBITRATION_CONTROL1, + PIXEL_DURATION); + + dm_write_reg(tg->ctx, addr, value); +} + +static void program_timing(struct timing_generator *tg, + const struct dc_crtc_timing *timing, + bool use_vbios) +{ + if (!use_vbios) + program_pix_dur(tg, timing->pix_clk_khz); + + dce110_tg_program_timing(tg, timing, use_vbios); +} + +static const struct timing_generator_funcs dce80_tg_funcs = { + .validate_timing = dce110_tg_validate_timing, + .program_timing = program_timing, + .enable_crtc = dce110_timing_generator_enable_crtc, + .disable_crtc = dce110_timing_generator_disable_crtc, + .is_counter_moving = dce110_timing_generator_is_counter_moving, + .get_position = dce110_timing_generator_get_crtc_positions, + .get_frame_count = dce110_timing_generator_get_vblank_counter, + .get_scanoutpos = dce110_timing_generator_get_crtc_scanoutpos, + .set_early_control = dce110_timing_generator_set_early_control, + .wait_for_state = dce110_tg_wait_for_state, + .set_blank = dce110_tg_set_blank, + .is_blanked = dce110_tg_is_blanked, + .set_colors = dce110_tg_set_colors, + .set_overscan_blank_color = + dce110_timing_generator_set_overscan_color_black, + .set_blank_color = dce110_timing_generator_program_blank_color, + .disable_vga = dce110_timing_generator_disable_vga, + .did_triggered_reset_occur = + dce110_timing_generator_did_triggered_reset_occur, + .setup_global_swap_lock = + dce110_timing_generator_setup_global_swap_lock, + .enable_reset_trigger = dce110_timing_generator_enable_reset_trigger, + .disable_reset_trigger = dce110_timing_generator_disable_reset_trigger, + .tear_down_global_swap_lock = + dce110_timing_generator_tear_down_global_swap_lock, + + /* DCE8.0 overrides */ + .enable_advanced_request = + dce80_timing_generator_enable_advanced_request, + .set_drr = + dce110_timing_generator_set_drr, +}; + +bool dce80_timing_generator_construct( + struct dce110_timing_generator *tg110, + struct dc_context *ctx, + uint32_t instance, + const struct dce110_timing_generator_offsets *offsets) +{ + if (!tg110) + return false; + + tg110->controller_id = CONTROLLER_ID_D0 + instance; + tg110->base.inst = instance; + tg110->offsets = *offsets; + tg110->derived_offsets = reg_offsets[instance]; + + tg110->base.funcs = &dce80_tg_funcs; + + tg110->base.ctx = ctx; + tg110->base.bp = ctx->dc_bios; + + tg110->max_h_total = CRTC_H_TOTAL__CRTC_H_TOTAL_MASK + 1; + tg110->max_v_total = CRTC_V_TOTAL__CRTC_V_TOTAL_MASK + 1; + + tg110->min_h_blank = 56; + tg110->min_h_front_porch = 4; + tg110->min_h_back_porch = 4; + + return true; +} + +void dce80_timing_generator_enable_advanced_request( + struct timing_generator *tg, + bool enable, + const struct dc_crtc_timing *timing) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t addr = CRTC_REG(mmCRTC_START_LINE_CONTROL); + uint32_t value = dm_read_reg(tg->ctx, addr); + + if (enable) { + set_reg_field_value( + value, + 0, + CRTC_START_LINE_CONTROL, + CRTC_LEGACY_REQUESTOR_EN); + } else { + set_reg_field_value( + value, + 1, + CRTC_START_LINE_CONTROL, + CRTC_LEGACY_REQUESTOR_EN); + } + + if ((timing->v_sync_width + timing->v_front_porch) <= 3) { + set_reg_field_value( + value, + 3, + CRTC_START_LINE_CONTROL, + CRTC_ADVANCED_START_LINE_POSITION); + set_reg_field_value( + value, + 0, + CRTC_START_LINE_CONTROL, + CRTC_PREFETCH_EN); + } else { + set_reg_field_value( + value, + 4, + CRTC_START_LINE_CONTROL, + CRTC_ADVANCED_START_LINE_POSITION); + set_reg_field_value( + value, + 1, + CRTC_START_LINE_CONTROL, + CRTC_PREFETCH_EN); + } + + set_reg_field_value( + value, + 1, + CRTC_START_LINE_CONTROL, + CRTC_PROGRESSIVE_START_LINE_EARLY); + + set_reg_field_value( + value, + 1, + CRTC_START_LINE_CONTROL, + CRTC_INTERLACE_START_LINE_EARLY); + + dm_write_reg(tg->ctx, addr, value); +} diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.h new file mode 100644 index 000000000000..6e4722a970d7 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.h @@ -0,0 +1,45 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_TIMING_GENERATOR_DCE80_H__ +#define __DC_TIMING_GENERATOR_DCE80_H__ + +#include "timing_generator.h" +#include "../include/grph_object_id.h" + +/* DCE8.0 implementation inherits from DCE11.0 */ +bool dce80_timing_generator_construct( + struct dce110_timing_generator *tg, + struct dc_context *ctx, + uint32_t instance, + const struct dce110_timing_generator_offsets *offsets); + +/******** HW programming ************/ +void dce80_timing_generator_enable_advanced_request( + struct timing_generator *tg, + bool enable, + const struct dc_crtc_timing *timing); + +#endif /* __DC_TIMING_GENERATOR_DCE80_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dm_helpers.h b/drivers/gpu/drm/amd/display/dc/dm_helpers.h new file mode 100644 index 000000000000..d6c52d31f0f0 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dm_helpers.h @@ -0,0 +1,101 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +/** + * This file defines helper functions provided by the Display Manager to + * Display Core. + */ +#ifndef __DM_HELPERS__ +#define __DM_HELPERS__ + +#include "dc_types.h" +#include "dc.h" + +struct dp_mst_stream_allocation_table; + +enum dc_edid_status dm_helpers_parse_edid_caps( + struct dc_context *ctx, + const struct dc_edid *edid, + struct dc_edid_caps *edid_caps); + +/* + * Writes payload allocation table in immediate downstream device. + */ +bool dm_helpers_dp_mst_write_payload_allocation_table( + struct dc_context *ctx, + const struct dc_stream *stream, + struct dp_mst_stream_allocation_table *proposed_table, + bool enable); + +/* + * Polls for ACT (allocation change trigger) handled and + */ +bool dm_helpers_dp_mst_poll_for_allocation_change_trigger( + struct dc_context *ctx, + const struct dc_stream *stream); +/* + * Sends ALLOCATE_PAYLOAD message. + */ +bool dm_helpers_dp_mst_send_payload_allocation( + struct dc_context *ctx, + const struct dc_stream *stream, + bool enable); + +bool dm_helpers_dp_mst_start_top_mgr( + struct dc_context *ctx, + const struct dc_link *link, + bool boot); + +void dm_helpers_dp_mst_stop_top_mgr( + struct dc_context *ctx, + const struct dc_link *link); + +/** + * OS specific aux read callback. + */ +bool dm_helpers_dp_read_dpcd( + struct dc_context *ctx, + const struct dc_link *link, + uint32_t address, + uint8_t *data, + uint32_t size); + +/** + * OS specific aux write callback. + */ +bool dm_helpers_dp_write_dpcd( + struct dc_context *ctx, + const struct dc_link *link, + uint32_t address, + const uint8_t *data, + uint32_t size); + +bool dm_helpers_submit_i2c( + struct dc_context *ctx, + const struct dc_link *link, + struct i2c_command *cmd); + + +#endif /* __DM_HELPERS__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dm_services.h b/drivers/gpu/drm/amd/display/dc/dm_services.h new file mode 100644 index 000000000000..7a3f10354830 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dm_services.h @@ -0,0 +1,424 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +/** + * This file defines external dependencies of Display Core. + */ + +#ifndef __DM_SERVICES_H__ + +#define __DM_SERVICES_H__ + +/* TODO: remove when DC is complete. */ +#include "dm_services_types.h" +#include "logger_interface.h" +#include "link_service_types.h" + +#undef DEPRECATED + +/* + * + * general debug capabilities + * + */ +#if defined(CONFIG_DEBUG_KERNEL) || defined(CONFIG_DEBUG_DRIVER) + +#if defined(CONFIG_HAVE_KGDB) || defined(CONFIG_KGDB) +#define ASSERT_CRITICAL(expr) do { \ + if (WARN_ON(!(expr))) { \ + kgdb_breakpoint(); \ + } \ +} while (0) +#else +#define ASSERT_CRITICAL(expr) do { \ + if (WARN_ON(!(expr))) { \ + ; \ + } \ +} while (0) +#endif + +#if defined(CONFIG_DEBUG_KERNEL_DC) +#define ASSERT(expr) ASSERT_CRITICAL(expr) + +#else +#define ASSERT(expr) WARN_ON(!(expr)) +#endif + +#define BREAK_TO_DEBUGGER() ASSERT(0) + +#endif /* CONFIG_DEBUG_KERNEL || CONFIG_DEBUG_DRIVER */ + +#define DC_ERR(...) do { \ + dm_error(__VA_ARGS__); \ + BREAK_TO_DEBUGGER(); \ +} while (0) + +#define dm_alloc(size) kzalloc(size, GFP_KERNEL) +#define dm_realloc(ptr, size) krealloc(ptr, size, GFP_KERNEL) +#define dm_free(ptr) kfree(ptr) + +irq_handler_idx dm_register_interrupt( + struct dc_context *ctx, + struct dc_interrupt_params *int_params, + interrupt_handler ih, + void *handler_args); + + +/* + * + * GPU registers access + * + */ + +#define dm_read_reg(ctx, address) \ + dm_read_reg_func(ctx, address, __func__) + +static inline uint32_t dm_read_reg_func( + const struct dc_context *ctx, + uint32_t address, + const char *func_name) +{ + uint32_t value; + + if (address == 0) { + DC_ERR("invalid register read. address = 0"); + return 0; + } + + value = cgs_read_register(ctx->cgs_device, address); + +#if defined(__DAL_REGISTER_LOGGER__) + if (true == dal_reg_logger_should_dump_register()) { + dal_reg_logger_rw_count_increment(); + DRM_INFO("%s DC_READ_REG: 0x%x 0x%x\n", func_name, address, value); + } +#endif + return value; +} + +#define dm_write_reg(ctx, address, value) \ + dm_write_reg_func(ctx, address, value, __func__) + +static inline void dm_write_reg_func( + const struct dc_context *ctx, + uint32_t address, + uint32_t value, + const char *func_name) +{ +#if defined(__DAL_REGISTER_LOGGER__) + if (true == dal_reg_logger_should_dump_register()) { + dal_reg_logger_rw_count_increment(); + DRM_INFO("%s DC_WRITE_REG: 0x%x 0x%x\n", func_name, address, value); + } +#endif + + if (address == 0) { + DC_ERR("invalid register write. address = 0"); + return; + } + cgs_write_register(ctx->cgs_device, address, value); +} + +static inline uint32_t dm_read_index_reg( + const struct dc_context *ctx, + enum cgs_ind_reg addr_space, + uint32_t index) +{ + return cgs_read_ind_register(ctx->cgs_device, addr_space, index); +} + +static inline void dm_write_index_reg( + const struct dc_context *ctx, + enum cgs_ind_reg addr_space, + uint32_t index, + uint32_t value) +{ + cgs_write_ind_register(ctx->cgs_device, addr_space, index, value); +} + +static inline uint32_t get_reg_field_value_ex( + uint32_t reg_value, + uint32_t mask, + uint8_t shift) +{ + return (mask & reg_value) >> shift; +} + +#define get_reg_field_value(reg_value, reg_name, reg_field)\ + get_reg_field_value_ex(\ + (reg_value),\ + reg_name ## __ ## reg_field ## _MASK,\ + reg_name ## __ ## reg_field ## __SHIFT) + +static inline uint32_t set_reg_field_value_ex( + uint32_t reg_value, + uint32_t value, + uint32_t mask, + uint8_t shift) +{ + return (reg_value & ~mask) | (mask & (value << shift)); +} + +#define set_reg_field_value(reg_value, value, reg_name, reg_field)\ + (reg_value) = set_reg_field_value_ex(\ + (reg_value),\ + (value),\ + reg_name ## __ ## reg_field ## _MASK,\ + reg_name ## __ ## reg_field ## __SHIFT) + +uint32_t generic_reg_update_ex(const struct dc_context *ctx, + uint32_t addr, uint32_t reg_val, int n, + uint8_t shift1, uint32_t mask1, uint32_t field_value1, ...); + +#define FD(reg_field) reg_field ## __SHIFT, \ + reg_field ## _MASK + +/* + * return number of poll before condition is met + * return 0 if condition is not meet after specified time out tries + */ +unsigned int generic_reg_wait(const struct dc_context *ctx, + uint32_t addr, uint32_t mask, uint32_t shift, uint32_t condition_value, + unsigned int delay_between_poll_us, unsigned int time_out_num_tries, + const char *func_name); + +/************************************** + * Power Play (PP) interfaces + **************************************/ + +/* DAL calls this function to notify PP about clocks it needs for the Mode Set. + * This is done *before* it changes DCE clock. + * + * If required clock is higher than current, then PP will increase the voltage. + * + * If required clock is lower than current, then PP will defer reduction of + * voltage until the call to dc_service_pp_post_dce_clock_change(). + * + * \input - Contains clocks needed for Mode Set. + * + * \output - Contains clocks adjusted by PP which DAL should use for Mode Set. + * Valid only if function returns zero. + * + * \returns true - call is successful + * false - call failed + */ +bool dm_pp_pre_dce_clock_change( + struct dc_context *ctx, + struct dm_pp_gpu_clock_range *requested_state, + struct dm_pp_gpu_clock_range *actual_state); + +/* The returned clocks range are 'static' system clocks which will be used for + * mode validation purposes. + * + * \returns true - call is successful + * false - call failed + */ +bool dc_service_get_system_clocks_range( + const struct dc_context *ctx, + struct dm_pp_gpu_clock_range *sys_clks); + +/* Gets valid clocks levels from pplib + * + * input: clk_type - display clk / sclk / mem clk + * + * output: array of valid clock levels for given type in ascending order, + * with invalid levels filtered out + * + */ +bool dm_pp_get_clock_levels_by_type( + const struct dc_context *ctx, + enum dm_pp_clock_type clk_type, + struct dm_pp_clock_levels *clk_level_info); + +bool dm_pp_get_clock_levels_by_type_with_latency( + const struct dc_context *ctx, + enum dm_pp_clock_type clk_type, + struct dm_pp_clock_levels_with_latency *clk_level_info); + +bool dm_pp_get_clock_levels_by_type_with_voltage( + const struct dc_context *ctx, + enum dm_pp_clock_type clk_type, + struct dm_pp_clock_levels_with_voltage *clk_level_info); + +bool dm_pp_notify_wm_clock_changes( + const struct dc_context *ctx, + struct dm_pp_wm_sets_with_clock_ranges *wm_with_clock_ranges); + +/* DAL calls this function to notify PP about completion of Mode Set. + * For PP it means that current DCE clocks are those which were returned + * by dc_service_pp_pre_dce_clock_change(), in the 'output' parameter. + * + * If the clocks are higher than before, then PP does nothing. + * + * If the clocks are lower than before, then PP reduces the voltage. + * + * \returns true - call is successful + * false - call failed + */ +bool dm_pp_apply_display_requirements( + const struct dc_context *ctx, + const struct dm_pp_display_configuration *pp_display_cfg); + +bool dm_pp_apply_power_level_change_request( + const struct dc_context *ctx, + struct dm_pp_power_level_change_request *level_change_req); + +bool dm_pp_apply_clock_for_voltage_request( + const struct dc_context *ctx, + struct dm_pp_clock_for_voltage_req *clock_for_voltage_req); + +bool dm_pp_get_static_clocks( + const struct dc_context *ctx, + struct dm_pp_static_clock_info *static_clk_info); + +/****** end of PP interfaces ******/ + +enum platform_method { + PM_GET_AVAILABLE_METHODS = 1 << 0, + PM_GET_LID_STATE = 1 << 1, + PM_GET_EXTENDED_BRIGHNESS_CAPS = 1 << 2 +}; + +struct platform_info_params { + enum platform_method method; + void *data; +}; + +struct platform_info_brightness_caps { + uint8_t ac_level_percentage; + uint8_t dc_level_percentage; +}; + +struct platform_info_ext_brightness_caps { + struct platform_info_brightness_caps basic_caps; + struct data_point { + uint8_t luminance; + uint8_t signal_level; + } data_points[99]; + + uint8_t data_points_num; + uint8_t min_input_signal; + uint8_t max_input_signal; +}; + +bool dm_get_platform_info( + struct dc_context *ctx, + struct platform_info_params *params); + +struct persistent_data_flag { + bool save_per_link; + bool save_per_edid; +}; + +/* Call to write data in registry editor for persistent data storage. + * + * \inputs sink - identify edid/link for registry folder creation + * module name - identify folders for registry + * key name - identify keys within folders for registry + * params - value to write in defined folder/key + * size - size of the input params + * flag - determine whether to save by link or edid + * + * \returns true - call is successful + * false - call failed + * + * sink module key + * ----------------------------------------------------------------------------- + * NULL NULL NULL - failure + * NULL NULL - - create key with param value + * under base folder + * NULL - NULL - create module folder under base folder + * - NULL NULL - failure + * NULL - - - create key under module folder + * with no edid/link identification + * - NULL - - create key with param value + * under base folder + * - - NULL - create module folder under base folder + * - - - - create key under module folder + * with edid/link identification + */ +bool dm_write_persistent_data(struct dc_context *ctx, + const struct dc_sink *sink, + const char *module_name, + const char *key_name, + void *params, + unsigned int size, + struct persistent_data_flag *flag); + + +/* Call to read data in registry editor for persistent data storage. + * + * \inputs sink - identify edid/link for registry folder creation + * module name - identify folders for registry + * key name - identify keys within folders for registry + * size - size of the output params + * flag - determine whether it was save by link or edid + * + * \returns params - value read from defined folder/key + * true - call is successful + * false - call failed + * + * sink module key + * ----------------------------------------------------------------------------- + * NULL NULL NULL - failure + * NULL NULL - - read key under base folder + * NULL - NULL - failure + * - NULL NULL - failure + * NULL - - - read key under module folder + * with no edid/link identification + * - NULL - - read key under base folder + * - - NULL - failure + * - - - - read key under module folder + * with edid/link identification + */ +bool dm_read_persistent_data(struct dc_context *ctx, + const struct dc_sink *sink, + const char *module_name, + const char *key_name, + void *params, + unsigned int size, + struct persistent_data_flag *flag); + +void dm_delay_in_microseconds + (struct dc_context *ctx, unsigned int microSeconds); + +bool dm_query_extended_brightness_caps + (struct dc_context *ctx, enum dm_acpi_display_type display, + struct dm_acpi_atif_backlight_caps *pCaps); + +bool dm_dmcu_set_pipe(struct dc_context *ctx, unsigned int controller_id); + +/* + * + * print-out services + * + */ +#define dm_log_to_buffer(buffer, size, fmt, args)\ + vsnprintf(buffer, size, fmt, args) + +long dm_get_pid(void); +long dm_get_tgid(void); + +#endif /* __DM_SERVICES_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dm_services_types.h b/drivers/gpu/drm/amd/display/dc/dm_services_types.h new file mode 100644 index 000000000000..44bad17fa318 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dm_services_types.h @@ -0,0 +1,242 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DM_SERVICES_TYPES_H__ +#define __DM_SERVICES_TYPES_H__ + +#include "os_types.h" +#include "dc_types.h" + +struct dm_pp_clock_range { + int min_khz; + int max_khz; +}; + +enum dm_pp_clocks_state { + DM_PP_CLOCKS_STATE_INVALID, + DM_PP_CLOCKS_STATE_ULTRA_LOW, + DM_PP_CLOCKS_STATE_LOW, + DM_PP_CLOCKS_STATE_NOMINAL, + DM_PP_CLOCKS_STATE_PERFORMANCE, + + /* Starting from DCE11, Max 8 levels of DPM state supported. */ + DM_PP_CLOCKS_DPM_STATE_LEVEL_INVALID = DM_PP_CLOCKS_STATE_INVALID, + DM_PP_CLOCKS_DPM_STATE_LEVEL_0 = DM_PP_CLOCKS_STATE_ULTRA_LOW, + DM_PP_CLOCKS_DPM_STATE_LEVEL_1 = DM_PP_CLOCKS_STATE_LOW, + DM_PP_CLOCKS_DPM_STATE_LEVEL_2 = DM_PP_CLOCKS_STATE_NOMINAL, + /* to be backward compatible */ + DM_PP_CLOCKS_DPM_STATE_LEVEL_3 = DM_PP_CLOCKS_STATE_PERFORMANCE, + DM_PP_CLOCKS_DPM_STATE_LEVEL_4 = DM_PP_CLOCKS_DPM_STATE_LEVEL_3 + 1, + DM_PP_CLOCKS_DPM_STATE_LEVEL_5 = DM_PP_CLOCKS_DPM_STATE_LEVEL_4 + 1, + DM_PP_CLOCKS_DPM_STATE_LEVEL_6 = DM_PP_CLOCKS_DPM_STATE_LEVEL_5 + 1, + DM_PP_CLOCKS_DPM_STATE_LEVEL_7 = DM_PP_CLOCKS_DPM_STATE_LEVEL_6 + 1, +}; + +struct dm_pp_gpu_clock_range { + enum dm_pp_clocks_state clock_state; + struct dm_pp_clock_range sclk; + struct dm_pp_clock_range mclk; + struct dm_pp_clock_range eclk; + struct dm_pp_clock_range dclk; +}; + +enum dm_pp_clock_type { + DM_PP_CLOCK_TYPE_DISPLAY_CLK = 1, + DM_PP_CLOCK_TYPE_ENGINE_CLK, /* System clock */ + DM_PP_CLOCK_TYPE_MEMORY_CLK, + DM_PP_CLOCK_TYPE_DCFCLK, + DM_PP_CLOCK_TYPE_SOCCLK, + DM_PP_CLOCK_TYPE_PIXELCLK, + DM_PP_CLOCK_TYPE_DISPLAYPHYCLK +}; + +#define DC_DECODE_PP_CLOCK_TYPE(clk_type) \ + (clk_type) == DM_PP_CLOCK_TYPE_DISPLAY_CLK ? "Display" : \ + (clk_type) == DM_PP_CLOCK_TYPE_ENGINE_CLK ? "Engine" : \ + (clk_type) == DM_PP_CLOCK_TYPE_MEMORY_CLK ? "Memory" : "Invalid" + +#define DM_PP_MAX_CLOCK_LEVELS 8 + +struct dm_pp_clock_levels { + uint32_t num_levels; + uint32_t clocks_in_khz[DM_PP_MAX_CLOCK_LEVELS]; +}; + +struct dm_pp_clock_with_latency { + uint32_t clocks_in_khz; + uint32_t latency_in_us; +}; + +struct dm_pp_clock_levels_with_latency { + uint32_t num_levels; + struct dm_pp_clock_with_latency data[DM_PP_MAX_CLOCK_LEVELS]; +}; + +struct dm_pp_clock_with_voltage { + uint32_t clocks_in_khz; + uint32_t voltage_in_mv; +}; + +struct dm_pp_clock_levels_with_voltage { + uint32_t num_levels; + struct dm_pp_clock_with_voltage data[DM_PP_MAX_CLOCK_LEVELS]; +}; + +struct dm_pp_single_disp_config { + enum signal_type signal; + uint8_t transmitter; + uint8_t ddi_channel_mapping; + uint8_t pipe_idx; + uint32_t src_height; + uint32_t src_width; + uint32_t v_refresh; + uint32_t sym_clock; /* HDMI only */ + struct dc_link_settings link_settings; /* DP only */ +}; + +#define MAX_WM_SETS 4 + +enum dm_pp_wm_set_id { + WM_SET_A = 0, + WM_SET_B, + WM_SET_C, + WM_SET_D, + WM_SET_INVALID = 0xffff, +}; + +struct dm_pp_clock_range_for_wm_set { + enum dm_pp_wm_set_id wm_set_id; + uint32_t wm_min_eng_clk_in_khz; + uint32_t wm_max_eng_clk_in_khz; + uint32_t wm_min_memg_clk_in_khz; + uint32_t wm_max_mem_clk_in_khz; +}; + +struct dm_pp_wm_sets_with_clock_ranges { + uint32_t num_wm_sets; + struct dm_pp_clock_range_for_wm_set wm_clk_ranges[MAX_WM_SETS]; +}; + +#define MAX_DISPLAY_CONFIGS 6 + +struct dm_pp_display_configuration { + bool nb_pstate_switch_disable;/* controls NB PState switch */ + bool cpu_cc6_disable; /* controls CPU CState switch ( on or off) */ + bool cpu_pstate_disable; + uint32_t cpu_pstate_separation_time; + + uint32_t min_memory_clock_khz; + uint32_t min_engine_clock_khz; + uint32_t min_engine_clock_deep_sleep_khz; + + uint32_t avail_mclk_switch_time_us; + uint32_t avail_mclk_switch_time_in_disp_active_us; + + uint32_t disp_clk_khz; + + bool all_displays_in_sync; + + uint8_t display_count; + struct dm_pp_single_disp_config disp_configs[MAX_DISPLAY_CONFIGS]; + + /*Controller Index of primary display - used in MCLK SMC switching hang + * SW Workaround*/ + uint8_t crtc_index; + /*htotal*1000/pixelclk - used in MCLK SMC switching hang SW Workaround*/ + uint32_t line_time_in_us; +}; + +struct dm_bl_data_point { + /* Brightness level in percentage */ + uint8_t luminance; + /* Brightness level as effective value in range 0-255, + * corresponding to above percentage + */ + uint8_t signalLevel; +}; + +/* Total size of the structure should not exceed 256 bytes */ +struct dm_acpi_atif_backlight_caps { + + + uint16_t size; /* Bytes 0-1 (2 bytes) */ + uint16_t flags; /* Byted 2-3 (2 bytes) */ + uint8_t errorCode; /* Byte 4 */ + uint8_t acLevelPercentage; /* Byte 5 */ + uint8_t dcLevelPercentage; /* Byte 6 */ + uint8_t minInputSignal; /* Byte 7 */ + uint8_t maxInputSignal; /* Byte 8 */ + uint8_t numOfDataPoints; /* Byte 9 */ + struct dm_bl_data_point dataPoints[99]; /* Bytes 10-207 (198 bytes)*/ +}; + +enum dm_acpi_display_type { + AcpiDisplayType_LCD1 = 0, + AcpiDisplayType_CRT1 = 1, + AcpiDisplayType_DFP1 = 3, + AcpiDisplayType_CRT2 = 4, + AcpiDisplayType_LCD2 = 5, + AcpiDisplayType_DFP2 = 7, + AcpiDisplayType_DFP3 = 9, + AcpiDisplayType_DFP4 = 10, + AcpiDisplayType_DFP5 = 11, + AcpiDisplayType_DFP6 = 12 +}; + +enum dm_pp_power_level { + DM_PP_POWER_LEVEL_INVALID, + DM_PP_POWER_LEVEL_ULTRA_LOW, + DM_PP_POWER_LEVEL_LOW, + DM_PP_POWER_LEVEL_NOMINAL, + DM_PP_POWER_LEVEL_PERFORMANCE, + + DM_PP_POWER_LEVEL_0 = DM_PP_POWER_LEVEL_ULTRA_LOW, + DM_PP_POWER_LEVEL_1 = DM_PP_POWER_LEVEL_LOW, + DM_PP_POWER_LEVEL_2 = DM_PP_POWER_LEVEL_NOMINAL, + DM_PP_POWER_LEVEL_3 = DM_PP_POWER_LEVEL_PERFORMANCE, + DM_PP_POWER_LEVEL_4 = DM_PP_CLOCKS_DPM_STATE_LEVEL_3 + 1, + DM_PP_POWER_LEVEL_5 = DM_PP_CLOCKS_DPM_STATE_LEVEL_4 + 1, + DM_PP_POWER_LEVEL_6 = DM_PP_CLOCKS_DPM_STATE_LEVEL_5 + 1, + DM_PP_POWER_LEVEL_7 = DM_PP_CLOCKS_DPM_STATE_LEVEL_6 + 1, +}; + +struct dm_pp_power_level_change_request { + enum dm_pp_power_level power_level; +}; + +struct dm_pp_clock_for_voltage_req { + enum dm_pp_clock_type clk_type; + uint32_t clocks_in_khz; +}; + +struct dm_pp_static_clock_info { + uint32_t max_sclk_khz; + uint32_t max_mclk_khz; + + /* max possible display block clocks state */ + enum dm_pp_clocks_state max_clocks_state; +}; + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/gpio/Makefile b/drivers/gpu/drm/amd/display/dc/gpio/Makefile new file mode 100644 index 000000000000..a15c257fd2fa --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/Makefile @@ -0,0 +1,38 @@ +# +# Makefile for the 'gpio' sub-component of DAL. +# It provides the control and status of HW GPIO pins. + +GPIO = gpio_base.o gpio_service.o hw_factory.o \ + hw_gpio.o hw_hpd.o hw_ddc.o hw_translate.o + +AMD_DAL_GPIO = $(addprefix $(AMDDALPATH)/dc/gpio/,$(GPIO)) + +AMD_DISPLAY_FILES += $(AMD_DAL_GPIO) + +############################################################################### +# DCE 8x +############################################################################### +# all DCE8.x are derived from DCE8.0 +GPIO_DCE80 = hw_translate_dce80.o hw_factory_dce80.o + +AMD_DAL_GPIO_DCE80 = $(addprefix $(AMDDALPATH)/dc/gpio/dce80/,$(GPIO_DCE80)) + +AMD_DISPLAY_FILES += $(AMD_DAL_GPIO_DCE80) + +############################################################################### +# DCE 11x +############################################################################### +GPIO_DCE110 = hw_translate_dce110.o hw_factory_dce110.o + +AMD_DAL_GPIO_DCE110 = $(addprefix $(AMDDALPATH)/dc/gpio/dce110/,$(GPIO_DCE110)) + +AMD_DISPLAY_FILES += $(AMD_DAL_GPIO_DCE110) + +############################################################################### +# Diagnostics on FPGA +############################################################################### +GPIO_DIAG_FPGA = hw_translate_diag.o hw_factory_diag.o + +AMD_DAL_GPIO_DIAG_FPGA = $(addprefix $(AMDDALPATH)/dc/gpio/diagnostics/,$(GPIO_DIAG_FPGA)) + +AMD_DISPLAY_FILES += $(AMD_DAL_GPIO_DIAG_FPGA) diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dce110/hw_factory_dce110.c b/drivers/gpu/drm/amd/display/dc/gpio/dce110/hw_factory_dce110.c new file mode 100644 index 000000000000..20d81bca119c --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/dce110/hw_factory_dce110.c @@ -0,0 +1,178 @@ +/* + * Copyright 2013-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "include/gpio_types.h" +#include "../hw_factory.h" + +#include "hw_factory_dce110.h" + +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" + +/* set field name */ +#define SF_HPD(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define REG(reg_name)\ + mm ## reg_name + +#define REGI(reg_name, block, id)\ + mm ## block ## id ## _ ## reg_name + +#include "../hw_gpio.h" +#include "../hw_ddc.h" +#include "../hw_hpd.h" + +#include "reg_helper.h" +#include "../hpd_regs.h" + +#define hpd_regs(id) \ +{\ + HPD_REG_LIST(id)\ +} + +static const struct hpd_registers hpd_regs[] = { + hpd_regs(0), + hpd_regs(1), + hpd_regs(2), + hpd_regs(3), + hpd_regs(4), + hpd_regs(5) +}; + +static const struct hpd_sh_mask hpd_shift = { + HPD_MASK_SH_LIST(__SHIFT) +}; + +static const struct hpd_sh_mask hpd_mask = { + HPD_MASK_SH_LIST(_MASK) +}; + +#include "../ddc_regs.h" + + /* set field name */ +#define SF_DDC(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +static const struct ddc_registers ddc_data_regs[] = { + ddc_data_regs(1), + ddc_data_regs(2), + ddc_data_regs(3), + ddc_data_regs(4), + ddc_data_regs(5), + ddc_data_regs(6), + ddc_vga_data_regs, + ddc_i2c_data_regs +}; + +static const struct ddc_registers ddc_clk_regs[] = { + ddc_clk_regs(1), + ddc_clk_regs(2), + ddc_clk_regs(3), + ddc_clk_regs(4), + ddc_clk_regs(5), + ddc_clk_regs(6), + ddc_vga_clk_regs, + ddc_i2c_clk_regs +}; + +static const struct ddc_sh_mask ddc_shift = { + DDC_MASK_SH_LIST(__SHIFT) +}; + +static const struct ddc_sh_mask ddc_mask = { + DDC_MASK_SH_LIST(_MASK) +}; + +static void define_ddc_registers( + struct hw_gpio_pin *pin, + uint32_t en) +{ + struct hw_ddc *ddc = HW_DDC_FROM_BASE(pin); + + switch (pin->id) { + case GPIO_ID_DDC_DATA: + ddc->regs = &ddc_data_regs[en]; + ddc->base.regs = &ddc_data_regs[en].gpio; + break; + case GPIO_ID_DDC_CLOCK: + ddc->regs = &ddc_clk_regs[en]; + ddc->base.regs = &ddc_clk_regs[en].gpio; + break; + default: + ASSERT_CRITICAL(false); + return; + } + + ddc->shifts = &ddc_shift; + ddc->masks = &ddc_mask; + +} + +static void define_hpd_registers(struct hw_gpio_pin *pin, uint32_t en) +{ + struct hw_hpd *hpd = HW_HPD_FROM_BASE(pin); + + hpd->regs = &hpd_regs[en]; + hpd->shifts = &hpd_shift; + hpd->masks = &hpd_mask; + hpd->base.regs = &hpd_regs[en].gpio; +} + +static const struct hw_factory_funcs funcs = { + .create_ddc_data = dal_hw_ddc_create, + .create_ddc_clock = dal_hw_ddc_create, + .create_generic = NULL, + .create_hpd = dal_hw_hpd_create, + .create_sync = NULL, + .create_gsl = NULL, + .define_hpd_registers = define_hpd_registers, + .define_ddc_registers = define_ddc_registers +}; + +/* + * dal_hw_factory_dce110_init + * + * @brief + * Initialize HW factory function pointers and pin info + * + * @param + * struct hw_factory *factory - [out] struct of function pointers + */ +void dal_hw_factory_dce110_init(struct hw_factory *factory) +{ + /*TODO check ASIC CAPs*/ + factory->number_of_pins[GPIO_ID_DDC_DATA] = 8; + factory->number_of_pins[GPIO_ID_DDC_CLOCK] = 8; + factory->number_of_pins[GPIO_ID_GENERIC] = 7; + factory->number_of_pins[GPIO_ID_HPD] = 6; + factory->number_of_pins[GPIO_ID_GPIO_PAD] = 31; + factory->number_of_pins[GPIO_ID_VIP_PAD] = 0; + factory->number_of_pins[GPIO_ID_SYNC] = 2; + factory->number_of_pins[GPIO_ID_GSL] = 4; + + factory->funcs = &funcs; +} diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dce110/hw_factory_dce110.h b/drivers/gpu/drm/amd/display/dc/gpio/dce110/hw_factory_dce110.h new file mode 100644 index 000000000000..ecf06ed0d587 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/dce110/hw_factory_dce110.h @@ -0,0 +1,32 @@ +/* + * Copyright 2013-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_HW_FACTORY_DCE110_H__ +#define __DAL_HW_FACTORY_DCE110_H__ + +/* Initialize HW factory function pointers and pin info */ +void dal_hw_factory_dce110_init(struct hw_factory *factory); + +#endif /* __DAL_HW_FACTORY_DCE110_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dce110/hw_translate_dce110.c b/drivers/gpu/drm/amd/display/dc/gpio/dce110/hw_translate_dce110.c new file mode 100644 index 000000000000..ac4cddbba815 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/dce110/hw_translate_dce110.c @@ -0,0 +1,387 @@ +/* + * Copyright 2013-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +/* + * Pre-requisites: headers required by header of this unit + */ + +#include "dm_services.h" +#include "include/gpio_types.h" +#include "../hw_translate.h" + +#include "hw_translate_dce110.h" + +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" + +static bool offset_to_id( + uint32_t offset, + uint32_t mask, + enum gpio_id *id, + uint32_t *en) +{ + switch (offset) { + /* GENERIC */ + case mmDC_GPIO_GENERIC_A: + *id = GPIO_ID_GENERIC; + switch (mask) { + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICA_A_MASK: + *en = GPIO_GENERIC_A; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICB_A_MASK: + *en = GPIO_GENERIC_B; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICC_A_MASK: + *en = GPIO_GENERIC_C; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICD_A_MASK: + *en = GPIO_GENERIC_D; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICE_A_MASK: + *en = GPIO_GENERIC_E; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICF_A_MASK: + *en = GPIO_GENERIC_F; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICG_A_MASK: + *en = GPIO_GENERIC_G; + return true; + default: + ASSERT_CRITICAL(false); + return false; + } + break; + /* HPD */ + case mmDC_GPIO_HPD_A: + *id = GPIO_ID_HPD; + switch (mask) { + case DC_GPIO_HPD_A__DC_GPIO_HPD1_A_MASK: + *en = GPIO_HPD_1; + return true; + case DC_GPIO_HPD_A__DC_GPIO_HPD2_A_MASK: + *en = GPIO_HPD_2; + return true; + case DC_GPIO_HPD_A__DC_GPIO_HPD3_A_MASK: + *en = GPIO_HPD_3; + return true; + case DC_GPIO_HPD_A__DC_GPIO_HPD4_A_MASK: + *en = GPIO_HPD_4; + return true; + case DC_GPIO_HPD_A__DC_GPIO_HPD5_A_MASK: + *en = GPIO_HPD_5; + return true; + case DC_GPIO_HPD_A__DC_GPIO_HPD6_A_MASK: + *en = GPIO_HPD_6; + return true; + default: + ASSERT_CRITICAL(false); + return false; + } + break; + /* SYNCA */ + case mmDC_GPIO_SYNCA_A: + *id = GPIO_ID_SYNC; + switch (mask) { + case DC_GPIO_SYNCA_A__DC_GPIO_HSYNCA_A_MASK: + *en = GPIO_SYNC_HSYNC_A; + return true; + case DC_GPIO_SYNCA_A__DC_GPIO_VSYNCA_A_MASK: + *en = GPIO_SYNC_VSYNC_A; + return true; + default: + ASSERT_CRITICAL(false); + return false; + } + break; + /* mmDC_GPIO_GENLK_MASK */ + case mmDC_GPIO_GENLK_A: + *id = GPIO_ID_GSL; + switch (mask) { + case DC_GPIO_GENLK_A__DC_GPIO_GENLK_CLK_A_MASK: + *en = GPIO_GSL_GENLOCK_CLOCK; + return true; + case DC_GPIO_GENLK_A__DC_GPIO_GENLK_VSYNC_A_MASK: + *en = GPIO_GSL_GENLOCK_VSYNC; + return true; + case DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_A_A_MASK: + *en = GPIO_GSL_SWAPLOCK_A; + return true; + case DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_B_A_MASK: + *en = GPIO_GSL_SWAPLOCK_B; + return true; + default: + ASSERT_CRITICAL(false); + return false; + } + break; + /* DDC */ + /* we don't care about the GPIO_ID for DDC + * in DdcHandle it will use GPIO_ID_DDC_DATA/GPIO_ID_DDC_CLOCK + * directly in the create method */ + case mmDC_GPIO_DDC1_A: + *en = GPIO_DDC_LINE_DDC1; + return true; + case mmDC_GPIO_DDC2_A: + *en = GPIO_DDC_LINE_DDC2; + return true; + case mmDC_GPIO_DDC3_A: + *en = GPIO_DDC_LINE_DDC3; + return true; + case mmDC_GPIO_DDC4_A: + *en = GPIO_DDC_LINE_DDC4; + return true; + case mmDC_GPIO_DDC5_A: + *en = GPIO_DDC_LINE_DDC5; + return true; + case mmDC_GPIO_DDC6_A: + *en = GPIO_DDC_LINE_DDC6; + return true; + case mmDC_GPIO_DDCVGA_A: + *en = GPIO_DDC_LINE_DDC_VGA; + return true; + /* GPIO_I2CPAD */ + case mmDC_GPIO_I2CPAD_A: + *en = GPIO_DDC_LINE_I2C_PAD; + return true; + /* Not implemented */ + case mmDC_GPIO_PWRSEQ_A: + case mmDC_GPIO_PAD_STRENGTH_1: + case mmDC_GPIO_PAD_STRENGTH_2: + case mmDC_GPIO_DEBUG: + return false; + /* UNEXPECTED */ + default: + ASSERT_CRITICAL(false); + return false; + } +} + +static bool id_to_offset( + enum gpio_id id, + uint32_t en, + struct gpio_pin_info *info) +{ + bool result = true; + + switch (id) { + case GPIO_ID_DDC_DATA: + info->mask = DC_GPIO_DDC6_A__DC_GPIO_DDC6DATA_A_MASK; + switch (en) { + case GPIO_DDC_LINE_DDC1: + info->offset = mmDC_GPIO_DDC1_A; + break; + case GPIO_DDC_LINE_DDC2: + info->offset = mmDC_GPIO_DDC2_A; + break; + case GPIO_DDC_LINE_DDC3: + info->offset = mmDC_GPIO_DDC3_A; + break; + case GPIO_DDC_LINE_DDC4: + info->offset = mmDC_GPIO_DDC4_A; + break; + case GPIO_DDC_LINE_DDC5: + info->offset = mmDC_GPIO_DDC5_A; + break; + case GPIO_DDC_LINE_DDC6: + info->offset = mmDC_GPIO_DDC6_A; + break; + case GPIO_DDC_LINE_DDC_VGA: + info->offset = mmDC_GPIO_DDCVGA_A; + break; + case GPIO_DDC_LINE_I2C_PAD: + info->offset = mmDC_GPIO_I2CPAD_A; + break; + default: + ASSERT_CRITICAL(false); + result = false; + } + break; + case GPIO_ID_DDC_CLOCK: + info->mask = DC_GPIO_DDC6_A__DC_GPIO_DDC6CLK_A_MASK; + switch (en) { + case GPIO_DDC_LINE_DDC1: + info->offset = mmDC_GPIO_DDC1_A; + break; + case GPIO_DDC_LINE_DDC2: + info->offset = mmDC_GPIO_DDC2_A; + break; + case GPIO_DDC_LINE_DDC3: + info->offset = mmDC_GPIO_DDC3_A; + break; + case GPIO_DDC_LINE_DDC4: + info->offset = mmDC_GPIO_DDC4_A; + break; + case GPIO_DDC_LINE_DDC5: + info->offset = mmDC_GPIO_DDC5_A; + break; + case GPIO_DDC_LINE_DDC6: + info->offset = mmDC_GPIO_DDC6_A; + break; + case GPIO_DDC_LINE_DDC_VGA: + info->offset = mmDC_GPIO_DDCVGA_A; + break; + case GPIO_DDC_LINE_I2C_PAD: + info->offset = mmDC_GPIO_I2CPAD_A; + break; + default: + ASSERT_CRITICAL(false); + result = false; + } + break; + case GPIO_ID_GENERIC: + info->offset = mmDC_GPIO_GENERIC_A; + switch (en) { + case GPIO_GENERIC_A: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICA_A_MASK; + break; + case GPIO_GENERIC_B: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICB_A_MASK; + break; + case GPIO_GENERIC_C: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICC_A_MASK; + break; + case GPIO_GENERIC_D: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICD_A_MASK; + break; + case GPIO_GENERIC_E: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICE_A_MASK; + break; + case GPIO_GENERIC_F: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICF_A_MASK; + break; + case GPIO_GENERIC_G: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICG_A_MASK; + break; + default: + ASSERT_CRITICAL(false); + result = false; + } + break; + case GPIO_ID_HPD: + info->offset = mmDC_GPIO_HPD_A; + switch (en) { + case GPIO_HPD_1: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD1_A_MASK; + break; + case GPIO_HPD_2: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD2_A_MASK; + break; + case GPIO_HPD_3: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD3_A_MASK; + break; + case GPIO_HPD_4: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD4_A_MASK; + break; + case GPIO_HPD_5: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD5_A_MASK; + break; + case GPIO_HPD_6: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD6_A_MASK; + break; + default: + ASSERT_CRITICAL(false); + result = false; + } + break; + case GPIO_ID_SYNC: + switch (en) { + case GPIO_SYNC_HSYNC_A: + info->offset = mmDC_GPIO_SYNCA_A; + info->mask = DC_GPIO_SYNCA_A__DC_GPIO_HSYNCA_A_MASK; + break; + case GPIO_SYNC_VSYNC_A: + info->offset = mmDC_GPIO_SYNCA_A; + info->mask = DC_GPIO_SYNCA_A__DC_GPIO_VSYNCA_A_MASK; + break; + case GPIO_SYNC_HSYNC_B: + case GPIO_SYNC_VSYNC_B: + default: + ASSERT_CRITICAL(false); + result = false; + } + break; + case GPIO_ID_GSL: + switch (en) { + case GPIO_GSL_GENLOCK_CLOCK: + info->offset = mmDC_GPIO_GENLK_A; + info->mask = DC_GPIO_GENLK_A__DC_GPIO_GENLK_CLK_A_MASK; + break; + case GPIO_GSL_GENLOCK_VSYNC: + info->offset = mmDC_GPIO_GENLK_A; + info->mask = + DC_GPIO_GENLK_A__DC_GPIO_GENLK_VSYNC_A_MASK; + break; + case GPIO_GSL_SWAPLOCK_A: + info->offset = mmDC_GPIO_GENLK_A; + info->mask = DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_A_A_MASK; + break; + case GPIO_GSL_SWAPLOCK_B: + info->offset = mmDC_GPIO_GENLK_A; + info->mask = DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_B_A_MASK; + break; + default: + ASSERT_CRITICAL(false); + result = false; + } + break; + case GPIO_ID_VIP_PAD: + default: + ASSERT_CRITICAL(false); + result = false; + } + + if (result) { + info->offset_y = info->offset + 2; + info->offset_en = info->offset + 1; + info->offset_mask = info->offset - 1; + + info->mask_y = info->mask; + info->mask_en = info->mask; + info->mask_mask = info->mask; + } + + return result; +} + +/* function table */ +static const struct hw_translate_funcs funcs = { + .offset_to_id = offset_to_id, + .id_to_offset = id_to_offset, +}; + +/* + * dal_hw_translate_dce110_init + * + * @brief + * Initialize Hw translate function pointers. + * + * @param + * struct hw_translate *tr - [out] struct of function pointers + * + */ +void dal_hw_translate_dce110_init(struct hw_translate *tr) +{ + tr->funcs = &funcs; +} diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dce110/hw_translate_dce110.h b/drivers/gpu/drm/amd/display/dc/gpio/dce110/hw_translate_dce110.h new file mode 100644 index 000000000000..4d16e09853c8 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/dce110/hw_translate_dce110.h @@ -0,0 +1,34 @@ +/* + * Copyright 2013-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_HW_TRANSLATE_DCE110_H__ +#define __DAL_HW_TRANSLATE_DCE110_H__ + +struct hw_translate; + +/* Initialize Hw translate function pointers */ +void dal_hw_translate_dce110_init(struct hw_translate *tr); + +#endif /* __DAL_HW_TRANSLATE_DCE110_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dce80/hw_factory_dce80.c b/drivers/gpu/drm/amd/display/dc/gpio/dce80/hw_factory_dce80.c new file mode 100644 index 000000000000..48b67866377e --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/dce80/hw_factory_dce80.c @@ -0,0 +1,173 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "include/gpio_types.h" +#include "../hw_factory.h" + +#include "hw_factory_dce80.h" + +#include "../hw_gpio.h" +#include "../hw_ddc.h" +#include "../hw_hpd.h" + +#include "dce/dce_8_0_d.h" +#include "dce/dce_8_0_sh_mask.h" + +#define REG(reg_name)\ + mm ## reg_name + +#include "reg_helper.h" +#include "../hpd_regs.h" + +#define HPD_REG_LIST_DCE8(id) \ + HPD_GPIO_REG_LIST(id), \ + .int_status = mmDC_HPD ## id ## _INT_STATUS,\ + .toggle_filt_cntl = mmDC_HPD ## id ## _TOGGLE_FILT_CNTL + +#define HPD_MASK_SH_LIST_DCE8(mask_sh) \ + .DC_HPD_SENSE_DELAYED = DC_HPD1_INT_STATUS__DC_HPD1_SENSE_DELAYED ## mask_sh,\ + .DC_HPD_SENSE = DC_HPD1_INT_STATUS__DC_HPD1_SENSE ## mask_sh,\ + .DC_HPD_CONNECT_INT_DELAY = DC_HPD1_TOGGLE_FILT_CNTL__DC_HPD1_CONNECT_INT_DELAY ## mask_sh,\ + .DC_HPD_DISCONNECT_INT_DELAY = DC_HPD1_TOGGLE_FILT_CNTL__DC_HPD1_DISCONNECT_INT_DELAY ## mask_sh + +#define hpd_regs(id) \ +{\ + HPD_REG_LIST_DCE8(id)\ +} + +static const struct hpd_registers hpd_regs[] = { + hpd_regs(1), + hpd_regs(2), + hpd_regs(3), + hpd_regs(4), + hpd_regs(5), + hpd_regs(6) +}; + +static const struct hpd_sh_mask hpd_shift = { + HPD_MASK_SH_LIST_DCE8(__SHIFT) +}; + +static const struct hpd_sh_mask hpd_mask = { + HPD_MASK_SH_LIST_DCE8(_MASK) +}; + +#include "../ddc_regs.h" + + /* set field name */ +#define SF_DDC(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +static const struct ddc_registers ddc_data_regs[] = { + ddc_data_regs(1), + ddc_data_regs(2), + ddc_data_regs(3), + ddc_data_regs(4), + ddc_data_regs(5), + ddc_data_regs(6), + ddc_vga_data_regs, + ddc_i2c_data_regs +}; + +static const struct ddc_registers ddc_clk_regs[] = { + ddc_clk_regs(1), + ddc_clk_regs(2), + ddc_clk_regs(3), + ddc_clk_regs(4), + ddc_clk_regs(5), + ddc_clk_regs(6), + ddc_vga_clk_regs, + ddc_i2c_clk_regs +}; + +static const struct ddc_sh_mask ddc_shift = { + DDC_MASK_SH_LIST(__SHIFT) +}; + +static const struct ddc_sh_mask ddc_mask = { + DDC_MASK_SH_LIST(_MASK) +}; + +static void define_ddc_registers( + struct hw_gpio_pin *pin, + uint32_t en) +{ + struct hw_ddc *ddc = HW_DDC_FROM_BASE(pin); + + switch (pin->id) { + case GPIO_ID_DDC_DATA: + ddc->regs = &ddc_data_regs[en]; + ddc->base.regs = &ddc_data_regs[en].gpio; + break; + case GPIO_ID_DDC_CLOCK: + ddc->regs = &ddc_clk_regs[en]; + ddc->base.regs = &ddc_clk_regs[en].gpio; + break; + default: + ASSERT_CRITICAL(false); + return; + } + + ddc->shifts = &ddc_shift; + ddc->masks = &ddc_mask; + +} + +static void define_hpd_registers(struct hw_gpio_pin *pin, uint32_t en) +{ + struct hw_hpd *hpd = HW_HPD_FROM_BASE(pin); + + hpd->regs = &hpd_regs[en]; + hpd->shifts = &hpd_shift; + hpd->masks = &hpd_mask; + hpd->base.regs = &hpd_regs[en].gpio; +} + +static const struct hw_factory_funcs funcs = { + .create_ddc_data = dal_hw_ddc_create, + .create_ddc_clock = dal_hw_ddc_create, + .create_generic = NULL, + .create_hpd = dal_hw_hpd_create, + .create_sync = NULL, + .create_gsl = NULL, + .define_hpd_registers = define_hpd_registers, + .define_ddc_registers = define_ddc_registers +}; + +void dal_hw_factory_dce80_init( + struct hw_factory *factory) +{ + factory->number_of_pins[GPIO_ID_DDC_DATA] = 8; + factory->number_of_pins[GPIO_ID_DDC_CLOCK] = 8; + factory->number_of_pins[GPIO_ID_GENERIC] = 7; + factory->number_of_pins[GPIO_ID_HPD] = 6; + factory->number_of_pins[GPIO_ID_GPIO_PAD] = 31; + factory->number_of_pins[GPIO_ID_VIP_PAD] = 0; + factory->number_of_pins[GPIO_ID_SYNC] = 2; + factory->number_of_pins[GPIO_ID_GSL] = 4; + + factory->funcs = &funcs; +} diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dce80/hw_factory_dce80.h b/drivers/gpu/drm/amd/display/dc/gpio/dce80/hw_factory_dce80.h new file mode 100644 index 000000000000..e78a8b36f35a --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/dce80/hw_factory_dce80.h @@ -0,0 +1,32 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_HW_FACTORY_DCE80_H__ +#define __DAL_HW_FACTORY_DCE80_H__ + +void dal_hw_factory_dce80_init( + struct hw_factory *factory); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dce80/hw_translate_dce80.c b/drivers/gpu/drm/amd/display/dc/gpio/dce80/hw_translate_dce80.c new file mode 100644 index 000000000000..fabb9da504be --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/dce80/hw_translate_dce80.c @@ -0,0 +1,411 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* + * Pre-requisites: headers required by header of this unit + */ +#include "include/gpio_types.h" +#include "../hw_translate.h" + +#include "hw_translate_dce80.h" + +#include "dce/dce_8_0_d.h" +#include "dce/dce_8_0_sh_mask.h" +#include "smu/smu_7_0_1_d.h" + +/* + * @brief + * Returns index of first bit (starting with LSB) which is set + */ +static uint32_t index_from_vector( + uint32_t vector) +{ + uint32_t result = 0; + uint32_t mask = 1; + + do { + if (vector == mask) + return result; + + ++result; + mask <<= 1; + } while (mask); + + BREAK_TO_DEBUGGER(); + + return GPIO_ENUM_UNKNOWN; +} + +static bool offset_to_id( + uint32_t offset, + uint32_t mask, + enum gpio_id *id, + uint32_t *en) +{ + switch (offset) { + /* GENERIC */ + case mmDC_GPIO_GENERIC_A: + *id = GPIO_ID_GENERIC; + switch (mask) { + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICA_A_MASK: + *en = GPIO_GENERIC_A; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICB_A_MASK: + *en = GPIO_GENERIC_B; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICC_A_MASK: + *en = GPIO_GENERIC_C; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICD_A_MASK: + *en = GPIO_GENERIC_D; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICE_A_MASK: + *en = GPIO_GENERIC_E; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICF_A_MASK: + *en = GPIO_GENERIC_F; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICG_A_MASK: + *en = GPIO_GENERIC_G; + return true; + default: + BREAK_TO_DEBUGGER(); + return false; + } + break; + /* HPD */ + case mmDC_GPIO_HPD_A: + *id = GPIO_ID_HPD; + switch (mask) { + case DC_GPIO_HPD_A__DC_GPIO_HPD1_A_MASK: + *en = GPIO_HPD_1; + return true; + case DC_GPIO_HPD_A__DC_GPIO_HPD2_A_MASK: + *en = GPIO_HPD_2; + return true; + case DC_GPIO_HPD_A__DC_GPIO_HPD3_A_MASK: + *en = GPIO_HPD_3; + return true; + case DC_GPIO_HPD_A__DC_GPIO_HPD4_A_MASK: + *en = GPIO_HPD_4; + return true; + case DC_GPIO_HPD_A__DC_GPIO_HPD5_A_MASK: + *en = GPIO_HPD_5; + return true; + case DC_GPIO_HPD_A__DC_GPIO_HPD6_A_MASK: + *en = GPIO_HPD_6; + return true; + default: + BREAK_TO_DEBUGGER(); + return false; + } + break; + /* SYNCA */ + case mmDC_GPIO_SYNCA_A: + *id = GPIO_ID_SYNC; + switch (mask) { + case DC_GPIO_SYNCA_A__DC_GPIO_HSYNCA_A_MASK: + *en = GPIO_SYNC_HSYNC_A; + return true; + case DC_GPIO_SYNCA_A__DC_GPIO_VSYNCA_A_MASK: + *en = GPIO_SYNC_VSYNC_A; + return true; + default: + BREAK_TO_DEBUGGER(); + return false; + } + break; + /* mmDC_GPIO_GENLK_MASK */ + case mmDC_GPIO_GENLK_A: + *id = GPIO_ID_GSL; + switch (mask) { + case DC_GPIO_GENLK_A__DC_GPIO_GENLK_CLK_A_MASK: + *en = GPIO_GSL_GENLOCK_CLOCK; + return true; + case DC_GPIO_GENLK_A__DC_GPIO_GENLK_VSYNC_A_MASK: + *en = GPIO_GSL_GENLOCK_VSYNC; + return true; + case DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_A_A_MASK: + *en = GPIO_GSL_SWAPLOCK_A; + return true; + case DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_B_A_MASK: + *en = GPIO_GSL_SWAPLOCK_B; + return true; + default: + BREAK_TO_DEBUGGER(); + return false; + } + break; + /* GPIOPAD */ + case mmGPIOPAD_A: + *id = GPIO_ID_GPIO_PAD; + *en = index_from_vector(mask); + return (*en <= GPIO_GPIO_PAD_MAX); + /* DDC */ + /* we don't care about the GPIO_ID for DDC + * in DdcHandle it will use GPIO_ID_DDC_DATA/GPIO_ID_DDC_CLOCK + * directly in the create method */ + case mmDC_GPIO_DDC1_A: + *en = GPIO_DDC_LINE_DDC1; + return true; + case mmDC_GPIO_DDC2_A: + *en = GPIO_DDC_LINE_DDC2; + return true; + case mmDC_GPIO_DDC3_A: + *en = GPIO_DDC_LINE_DDC3; + return true; + case mmDC_GPIO_DDC4_A: + *en = GPIO_DDC_LINE_DDC4; + return true; + case mmDC_GPIO_DDC5_A: + *en = GPIO_DDC_LINE_DDC5; + return true; + case mmDC_GPIO_DDC6_A: + *en = GPIO_DDC_LINE_DDC6; + return true; + case mmDC_GPIO_DDCVGA_A: + *en = GPIO_DDC_LINE_DDC_VGA; + return true; + /* GPIO_I2CPAD */ + case mmDC_GPIO_I2CPAD_A: + *en = GPIO_DDC_LINE_I2C_PAD; + return true; + /* Not implemented */ + case mmDC_GPIO_PWRSEQ_A: + case mmDC_GPIO_PAD_STRENGTH_1: + case mmDC_GPIO_PAD_STRENGTH_2: + case mmDC_GPIO_DEBUG: + return false; + /* UNEXPECTED */ + default: + BREAK_TO_DEBUGGER(); + return false; + } +} + +static bool id_to_offset( + enum gpio_id id, + uint32_t en, + struct gpio_pin_info *info) +{ + bool result = true; + + switch (id) { + case GPIO_ID_DDC_DATA: + info->mask = DC_GPIO_DDC6_A__DC_GPIO_DDC6DATA_A_MASK; + switch (en) { + case GPIO_DDC_LINE_DDC1: + info->offset = mmDC_GPIO_DDC1_A; + break; + case GPIO_DDC_LINE_DDC2: + info->offset = mmDC_GPIO_DDC2_A; + break; + case GPIO_DDC_LINE_DDC3: + info->offset = mmDC_GPIO_DDC3_A; + break; + case GPIO_DDC_LINE_DDC4: + info->offset = mmDC_GPIO_DDC4_A; + break; + case GPIO_DDC_LINE_DDC5: + info->offset = mmDC_GPIO_DDC5_A; + break; + case GPIO_DDC_LINE_DDC6: + info->offset = mmDC_GPIO_DDC6_A; + break; + case GPIO_DDC_LINE_DDC_VGA: + info->offset = mmDC_GPIO_DDCVGA_A; + break; + case GPIO_DDC_LINE_I2C_PAD: + info->offset = mmDC_GPIO_I2CPAD_A; + break; + default: + BREAK_TO_DEBUGGER(); + result = false; + } + break; + case GPIO_ID_DDC_CLOCK: + info->mask = DC_GPIO_DDC6_A__DC_GPIO_DDC6CLK_A_MASK; + switch (en) { + case GPIO_DDC_LINE_DDC1: + info->offset = mmDC_GPIO_DDC1_A; + break; + case GPIO_DDC_LINE_DDC2: + info->offset = mmDC_GPIO_DDC2_A; + break; + case GPIO_DDC_LINE_DDC3: + info->offset = mmDC_GPIO_DDC3_A; + break; + case GPIO_DDC_LINE_DDC4: + info->offset = mmDC_GPIO_DDC4_A; + break; + case GPIO_DDC_LINE_DDC5: + info->offset = mmDC_GPIO_DDC5_A; + break; + case GPIO_DDC_LINE_DDC6: + info->offset = mmDC_GPIO_DDC6_A; + break; + case GPIO_DDC_LINE_DDC_VGA: + info->offset = mmDC_GPIO_DDCVGA_A; + break; + case GPIO_DDC_LINE_I2C_PAD: + info->offset = mmDC_GPIO_I2CPAD_A; + break; + default: + BREAK_TO_DEBUGGER(); + result = false; + } + break; + case GPIO_ID_GENERIC: + info->offset = mmDC_GPIO_GENERIC_A; + switch (en) { + case GPIO_GENERIC_A: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICA_A_MASK; + break; + case GPIO_GENERIC_B: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICB_A_MASK; + break; + case GPIO_GENERIC_C: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICC_A_MASK; + break; + case GPIO_GENERIC_D: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICD_A_MASK; + break; + case GPIO_GENERIC_E: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICE_A_MASK; + break; + case GPIO_GENERIC_F: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICF_A_MASK; + break; + case GPIO_GENERIC_G: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICG_A_MASK; + break; + default: + BREAK_TO_DEBUGGER(); + result = false; + } + break; + case GPIO_ID_HPD: + info->offset = mmDC_GPIO_HPD_A; + switch (en) { + case GPIO_HPD_1: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD1_A_MASK; + break; + case GPIO_HPD_2: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD2_A_MASK; + break; + case GPIO_HPD_3: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD3_A_MASK; + break; + case GPIO_HPD_4: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD4_A_MASK; + break; + case GPIO_HPD_5: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD5_A_MASK; + break; + case GPIO_HPD_6: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD6_A_MASK; + break; + default: + BREAK_TO_DEBUGGER(); + result = false; + } + break; + case GPIO_ID_SYNC: + switch (en) { + case GPIO_SYNC_HSYNC_A: + info->offset = mmDC_GPIO_SYNCA_A; + info->mask = DC_GPIO_SYNCA_A__DC_GPIO_HSYNCA_A_MASK; + break; + case GPIO_SYNC_VSYNC_A: + info->offset = mmDC_GPIO_SYNCA_A; + info->mask = DC_GPIO_SYNCA_A__DC_GPIO_VSYNCA_A_MASK; + break; + case GPIO_SYNC_HSYNC_B: + case GPIO_SYNC_VSYNC_B: + default: + BREAK_TO_DEBUGGER(); + result = false; + } + break; + case GPIO_ID_GSL: + switch (en) { + case GPIO_GSL_GENLOCK_CLOCK: + info->offset = mmDC_GPIO_GENLK_A; + info->mask = DC_GPIO_GENLK_A__DC_GPIO_GENLK_CLK_A_MASK; + break; + case GPIO_GSL_GENLOCK_VSYNC: + info->offset = mmDC_GPIO_GENLK_A; + info->mask = + DC_GPIO_GENLK_A__DC_GPIO_GENLK_VSYNC_A_MASK; + break; + case GPIO_GSL_SWAPLOCK_A: + info->offset = mmDC_GPIO_GENLK_A; + info->mask = DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_A_A_MASK; + break; + case GPIO_GSL_SWAPLOCK_B: + info->offset = mmDC_GPIO_GENLK_A; + info->mask = DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_B_A_MASK; + break; + default: + BREAK_TO_DEBUGGER(); + result = false; + } + break; + case GPIO_ID_GPIO_PAD: + info->offset = mmGPIOPAD_A; + info->mask = (1 << en); + result = (info->mask <= GPIO_GPIO_PAD_MAX); + break; + case GPIO_ID_VIP_PAD: + default: + BREAK_TO_DEBUGGER(); + result = false; + } + + if (result) { + info->offset_y = info->offset + 2; + info->offset_en = info->offset + 1; + info->offset_mask = info->offset - 1; + + info->mask_y = info->mask; + info->mask_en = info->mask; + info->mask_mask = info->mask; + } + + return result; +} + +static const struct hw_translate_funcs funcs = { + .offset_to_id = offset_to_id, + .id_to_offset = id_to_offset, +}; + +void dal_hw_translate_dce80_init( + struct hw_translate *translate) +{ + translate->funcs = &funcs; +} diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dce80/hw_translate_dce80.h b/drivers/gpu/drm/amd/display/dc/gpio/dce80/hw_translate_dce80.h new file mode 100644 index 000000000000..374f2f3282a1 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/dce80/hw_translate_dce80.h @@ -0,0 +1,32 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_HW_TRANSLATE_DCE80_H__ +#define __DAL_HW_TRANSLATE_DCE80_H__ + +void dal_hw_translate_dce80_init( + struct hw_translate *tr); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/gpio/ddc_regs.h b/drivers/gpu/drm/amd/display/dc/gpio/ddc_regs.h new file mode 100644 index 000000000000..9c4a56c738c0 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/ddc_regs.h @@ -0,0 +1,150 @@ +/* + * Copyright 2012-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef DRIVERS_GPU_DRM_AMD_DC_DEV_DC_GPIO_DDC_REGS_H_ +#define DRIVERS_GPU_DRM_AMD_DC_DEV_DC_GPIO_DDC_REGS_H_ + +#include "gpio_regs.h" + +/****************************** new register headers */ +/*** following in header */ + +#define DDC_GPIO_REG_LIST_ENTRY(type,cd,id) \ + .type ## _reg = REG(DC_GPIO_DDC ## id ## _ ## type),\ + .type ## _mask = DC_GPIO_DDC ## id ## _ ## type ## __DC_GPIO_DDC ## id ## cd ## _ ## type ## _MASK,\ + .type ## _shift = DC_GPIO_DDC ## id ## _ ## type ## __DC_GPIO_DDC ## id ## cd ## _ ## type ## __SHIFT + +#define DDC_GPIO_REG_LIST(cd,id) \ + {\ + DDC_GPIO_REG_LIST_ENTRY(MASK,cd,id),\ + DDC_GPIO_REG_LIST_ENTRY(A,cd,id),\ + DDC_GPIO_REG_LIST_ENTRY(EN,cd,id),\ + DDC_GPIO_REG_LIST_ENTRY(Y,cd,id)\ + } + +#define DDC_REG_LIST(cd,id) \ + DDC_GPIO_REG_LIST(cd,id),\ + .ddc_setup = REG(DC_I2C_DDC ## id ## _SETUP) + +#define DDC_GPIO_VGA_REG_LIST_ENTRY(type,cd)\ + .type ## _reg = REG(DC_GPIO_DDCVGA_ ## type),\ + .type ## _mask = DC_GPIO_DDCVGA_ ## type ## __DC_GPIO_DDCVGA ## cd ## _ ## type ## _MASK,\ + .type ## _shift = DC_GPIO_DDCVGA_ ## type ## __DC_GPIO_DDCVGA ## cd ## _ ## type ## __SHIFT + +#define DDC_GPIO_VGA_REG_LIST(cd) \ + {\ + DDC_GPIO_VGA_REG_LIST_ENTRY(MASK,cd),\ + DDC_GPIO_VGA_REG_LIST_ENTRY(A,cd),\ + DDC_GPIO_VGA_REG_LIST_ENTRY(EN,cd),\ + DDC_GPIO_VGA_REG_LIST_ENTRY(Y,cd)\ + } + +#define DDC_VGA_REG_LIST(cd) \ + DDC_GPIO_VGA_REG_LIST(cd),\ + .ddc_setup = mmDC_I2C_DDCVGA_SETUP + +#define DDC_GPIO_I2C_REG_LIST_ENTRY(type,cd) \ + .type ## _reg = REG(DC_GPIO_I2CPAD_ ## type),\ + .type ## _mask = DC_GPIO_I2CPAD_ ## type ## __DC_GPIO_ ## cd ## _ ## type ## _MASK,\ + .type ## _shift = DC_GPIO_I2CPAD_ ## type ## __DC_GPIO_ ## cd ## _ ## type ## __SHIFT + +#define DDC_GPIO_I2C_REG_LIST(cd) \ + {\ + DDC_GPIO_I2C_REG_LIST_ENTRY(MASK,cd),\ + DDC_GPIO_I2C_REG_LIST_ENTRY(A,cd),\ + DDC_GPIO_I2C_REG_LIST_ENTRY(EN,cd),\ + DDC_GPIO_I2C_REG_LIST_ENTRY(Y,cd)\ + } + +#define DDC_I2C_REG_LIST(cd) \ + DDC_GPIO_I2C_REG_LIST(cd),\ + .ddc_setup = 0 + +#define DDC_MASK_SH_LIST(mask_sh) \ + SF_DDC(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_ENABLE, mask_sh),\ + SF_DDC(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_EDID_DETECT_ENABLE, mask_sh),\ + SF_DDC(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_EDID_DETECT_MODE, mask_sh),\ + SF_DDC(DC_GPIO_DDC1_MASK, DC_GPIO_DDC1DATA_PD_EN, mask_sh),\ + SF_DDC(DC_GPIO_DDC1_MASK, DC_GPIO_DDC1CLK_PD_EN, mask_sh),\ + SF_DDC(DC_GPIO_DDC1_MASK, AUX_PAD1_MODE, mask_sh),\ + SF_DDC(DC_GPIO_I2CPAD_MASK, DC_GPIO_SDA_PD_DIS, mask_sh),\ + SF_DDC(DC_GPIO_I2CPAD_MASK, DC_GPIO_SCL_PD_DIS, mask_sh) + + +struct ddc_registers { + struct gpio_registers gpio; + uint32_t ddc_setup; +}; + +struct ddc_sh_mask { + /* i2c_dd_setup */ + uint32_t DC_I2C_DDC1_ENABLE; + uint32_t DC_I2C_DDC1_EDID_DETECT_ENABLE; + uint32_t DC_I2C_DDC1_EDID_DETECT_MODE; + /* ddc1_mask */ + uint32_t DC_GPIO_DDC1DATA_PD_EN; + uint32_t DC_GPIO_DDC1CLK_PD_EN; + uint32_t AUX_PAD1_MODE; + /* i2cpad_mask */ + uint32_t DC_GPIO_SDA_PD_DIS; + uint32_t DC_GPIO_SCL_PD_DIS; +}; + + + +/*** following in dc_resource */ + +#define ddc_data_regs(id) \ +{\ + DDC_REG_LIST(DATA,id)\ +} + +#define ddc_clk_regs(id) \ +{\ + DDC_REG_LIST(CLK,id)\ +} + +#define ddc_vga_data_regs \ +{\ + DDC_VGA_REG_LIST(DATA)\ +} + +#define ddc_vga_clk_regs \ +{\ + DDC_VGA_REG_LIST(CLK)\ +} + +#define ddc_i2c_data_regs \ +{\ + DDC_I2C_REG_LIST(SDA)\ +} + +#define ddc_i2c_clk_regs \ +{\ + DDC_I2C_REG_LIST(SCL)\ +} + + +#endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_GPIO_DDC_REGS_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/gpio/diagnostics/hw_factory_diag.c b/drivers/gpu/drm/amd/display/dc/gpio/diagnostics/hw_factory_diag.c new file mode 100644 index 000000000000..26695b963c58 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/diagnostics/hw_factory_diag.c @@ -0,0 +1,63 @@ +/* + * Copyright 2013-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +/* + * Pre-requisites: headers required by header of this unit + */ + +#include "dm_services.h" +#include "include/gpio_types.h" +#include "../hw_factory.h" + +/* + * Header of this unit + */ + +#include "../hw_gpio.h" +#include "../hw_ddc.h" +#include "../hw_hpd.h" + +/* function table */ +static const struct hw_factory_funcs funcs = { + .create_ddc_data = NULL, + .create_ddc_clock = NULL, + .create_generic = NULL, + .create_hpd = NULL, + .create_sync = NULL, + .create_gsl = NULL, +}; + +void dal_hw_factory_diag_fpga_init(struct hw_factory *factory) +{ + factory->number_of_pins[GPIO_ID_DDC_DATA] = 8; + factory->number_of_pins[GPIO_ID_DDC_CLOCK] = 8; + factory->number_of_pins[GPIO_ID_GENERIC] = 7; + factory->number_of_pins[GPIO_ID_HPD] = 6; + factory->number_of_pins[GPIO_ID_GPIO_PAD] = 31; + factory->number_of_pins[GPIO_ID_VIP_PAD] = 0; + factory->number_of_pins[GPIO_ID_SYNC] = 2; + factory->number_of_pins[GPIO_ID_GSL] = 4; + factory->funcs = &funcs; +} diff --git a/drivers/gpu/drm/amd/display/dc/gpio/diagnostics/hw_factory_diag.h b/drivers/gpu/drm/amd/display/dc/gpio/diagnostics/hw_factory_diag.h new file mode 100644 index 000000000000..8a74f6adb8ee --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/diagnostics/hw_factory_diag.h @@ -0,0 +1,32 @@ +/* + * Copyright 2013-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_HW_FACTORY_DIAG_FPGA_H__ +#define __DAL_HW_FACTORY_DIAG_FPGA_H__ + +/* Initialize HW factory function pointers and pin info */ +void dal_hw_factory_diag_fpga_init(struct hw_factory *factory); + +#endif /* __DAL_HW_FACTORY_DIAG_FPGA_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/gpio/diagnostics/hw_translate_diag.c b/drivers/gpu/drm/amd/display/dc/gpio/diagnostics/hw_translate_diag.c new file mode 100644 index 000000000000..bf9068846927 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/diagnostics/hw_translate_diag.c @@ -0,0 +1,40 @@ +/* + * Copyright 2013-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "include/gpio_types.h" + +#include "../hw_translate.h" + +/* function table */ +static const struct hw_translate_funcs funcs = { + .offset_to_id = NULL, + .id_to_offset = NULL, +}; + +void dal_hw_translate_diag_fpga_init(struct hw_translate *tr) +{ + tr->funcs = &funcs; +} diff --git a/drivers/gpu/drm/amd/display/dc/gpio/diagnostics/hw_translate_diag.h b/drivers/gpu/drm/amd/display/dc/gpio/diagnostics/hw_translate_diag.h new file mode 100644 index 000000000000..4f053241fe96 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/diagnostics/hw_translate_diag.h @@ -0,0 +1,34 @@ +/* + * Copyright 2013-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_HW_TRANSLATE_DIAG_FPGA_H__ +#define __DAL_HW_TRANSLATE_DIAG_FPGA_H__ + +struct hw_translate; + +/* Initialize Hw translate function pointers */ +void dal_hw_translate_diag_fpga_init(struct hw_translate *tr); + +#endif /* __DAL_HW_TRANSLATE_DIAG_FPGA_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/gpio/gpio_base.c b/drivers/gpu/drm/amd/display/dc/gpio/gpio_base.c new file mode 100644 index 000000000000..d42eb3de2ea4 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/gpio_base.c @@ -0,0 +1,272 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +/* + * Pre-requisites: headers required by header of this unit + */ + +#include "dm_services.h" + +#include "include/gpio_interface.h" +#include "include/gpio_service_interface.h" +#include "hw_gpio.h" +#include "hw_translate.h" +#include "hw_factory.h" +#include "gpio_service.h" + +/* + * Post-requisites: headers required by this unit + */ + +/* + * This unit + */ + +/* + * @brief + * Public API + */ + +enum gpio_result dal_gpio_open( + struct gpio *gpio, + enum gpio_mode mode) +{ + return dal_gpio_open_ex(gpio, mode); +} + +enum gpio_result dal_gpio_open_ex( + struct gpio *gpio, + enum gpio_mode mode) +{ + if (gpio->pin) { + ASSERT_CRITICAL(false); + return GPIO_RESULT_ALREADY_OPENED; + } + + gpio->mode = mode; + + return dal_gpio_service_open( + gpio->service, gpio->id, gpio->en, mode, &gpio->pin); +} + +enum gpio_result dal_gpio_get_value( + const struct gpio *gpio, + uint32_t *value) +{ + if (!gpio->pin) { + BREAK_TO_DEBUGGER(); + return GPIO_RESULT_NULL_HANDLE; + } + + return gpio->pin->funcs->get_value(gpio->pin, value); +} + +enum gpio_result dal_gpio_set_value( + const struct gpio *gpio, + uint32_t value) +{ + if (!gpio->pin) { + BREAK_TO_DEBUGGER(); + return GPIO_RESULT_NULL_HANDLE; + } + + return gpio->pin->funcs->set_value(gpio->pin, value); +} + +enum gpio_mode dal_gpio_get_mode( + const struct gpio *gpio) +{ + return gpio->mode; +} + +enum gpio_result dal_gpio_change_mode( + struct gpio *gpio, + enum gpio_mode mode) +{ + if (!gpio->pin) { + BREAK_TO_DEBUGGER(); + return GPIO_RESULT_NULL_HANDLE; + } + + return gpio->pin->funcs->change_mode(gpio->pin, mode); +} + +enum gpio_id dal_gpio_get_id( + const struct gpio *gpio) +{ + return gpio->id; +} + +uint32_t dal_gpio_get_enum( + const struct gpio *gpio) +{ + return gpio->en; +} + +enum gpio_result dal_gpio_set_config( + struct gpio *gpio, + const struct gpio_config_data *config_data) +{ + if (!gpio->pin) { + BREAK_TO_DEBUGGER(); + return GPIO_RESULT_NULL_HANDLE; + } + + return gpio->pin->funcs->set_config(gpio->pin, config_data); +} + +enum gpio_result dal_gpio_get_pin_info( + const struct gpio *gpio, + struct gpio_pin_info *pin_info) +{ + return gpio->service->translate.funcs->id_to_offset( + gpio->id, gpio->en, pin_info) ? + GPIO_RESULT_OK : GPIO_RESULT_INVALID_DATA; +} + +enum sync_source dal_gpio_get_sync_source( + const struct gpio *gpio) +{ + switch (gpio->id) { + case GPIO_ID_GENERIC: + switch (gpio->en) { + case GPIO_GENERIC_A: + return SYNC_SOURCE_IO_GENERIC_A; + case GPIO_GENERIC_B: + return SYNC_SOURCE_IO_GENERIC_B; + case GPIO_GENERIC_C: + return SYNC_SOURCE_IO_GENERIC_C; + case GPIO_GENERIC_D: + return SYNC_SOURCE_IO_GENERIC_D; + case GPIO_GENERIC_E: + return SYNC_SOURCE_IO_GENERIC_E; + case GPIO_GENERIC_F: + return SYNC_SOURCE_IO_GENERIC_F; + default: + return SYNC_SOURCE_NONE; + } + break; + case GPIO_ID_SYNC: + switch (gpio->en) { + case GPIO_SYNC_HSYNC_A: + return SYNC_SOURCE_IO_HSYNC_A; + case GPIO_SYNC_VSYNC_A: + return SYNC_SOURCE_IO_VSYNC_A; + case GPIO_SYNC_HSYNC_B: + return SYNC_SOURCE_IO_HSYNC_B; + case GPIO_SYNC_VSYNC_B: + return SYNC_SOURCE_IO_VSYNC_B; + default: + return SYNC_SOURCE_NONE; + } + break; + case GPIO_ID_HPD: + switch (gpio->en) { + case GPIO_HPD_1: + return SYNC_SOURCE_IO_HPD1; + case GPIO_HPD_2: + return SYNC_SOURCE_IO_HPD2; + default: + return SYNC_SOURCE_NONE; + } + break; + case GPIO_ID_GSL: + switch (gpio->en) { + case GPIO_GSL_GENLOCK_CLOCK: + return SYNC_SOURCE_GSL_IO_GENLOCK_CLOCK; + case GPIO_GSL_GENLOCK_VSYNC: + return SYNC_SOURCE_GSL_IO_GENLOCK_VSYNC; + case GPIO_GSL_SWAPLOCK_A: + return SYNC_SOURCE_GSL_IO_SWAPLOCK_A; + case GPIO_GSL_SWAPLOCK_B: + return SYNC_SOURCE_GSL_IO_SWAPLOCK_B; + default: + return SYNC_SOURCE_NONE; + } + break; + default: + return SYNC_SOURCE_NONE; + } +} + +enum gpio_pin_output_state dal_gpio_get_output_state( + const struct gpio *gpio) +{ + return gpio->output_state; +} + +void dal_gpio_close( + struct gpio *gpio) +{ + if (!gpio) + return; + + dal_gpio_service_close(gpio->service, &gpio->pin); + + gpio->mode = GPIO_MODE_UNKNOWN; +} + +/* + * @brief + * Creation and destruction + */ + +struct gpio *dal_gpio_create( + struct gpio_service *service, + enum gpio_id id, + uint32_t en, + enum gpio_pin_output_state output_state) +{ + struct gpio *gpio = dm_alloc(sizeof(struct gpio)); + + if (!gpio) { + ASSERT_CRITICAL(false); + return NULL; + } + + gpio->service = service; + gpio->pin = NULL; + gpio->id = id; + gpio->en = en; + gpio->mode = GPIO_MODE_UNKNOWN; + gpio->output_state = output_state; + + return gpio; +} + +void dal_gpio_destroy( + struct gpio **gpio) +{ + if (!gpio || !*gpio) { + ASSERT_CRITICAL(false); + return; + } + + dal_gpio_close(*gpio); + + dm_free(*gpio); + + *gpio = NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/gpio/gpio_regs.h b/drivers/gpu/drm/amd/display/dc/gpio/gpio_regs.h new file mode 100644 index 000000000000..5c5925299f8d --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/gpio_regs.h @@ -0,0 +1,45 @@ +/* + * Copyright 2012-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef DRIVERS_GPU_DRM_AMD_DC_DEV_DC_GPIO_GPIO_REGS_H_ +#define DRIVERS_GPU_DRM_AMD_DC_DEV_DC_GPIO_GPIO_REGS_H_ + +struct gpio_registers { + uint32_t MASK_reg; + uint32_t MASK_mask; + uint32_t MASK_shift; + uint32_t A_reg; + uint32_t A_mask; + uint32_t A_shift; + uint32_t EN_reg; + uint32_t EN_mask; + uint32_t EN_shift; + uint32_t Y_reg; + uint32_t Y_mask; + uint32_t Y_shift; +}; + + +#endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_GPIO_GPIO_REGS_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c b/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c new file mode 100644 index 000000000000..eeb1cd0f75a6 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c @@ -0,0 +1,592 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +/* + * Pre-requisites: headers required by header of this unit + */ + +#include "dm_services.h" +#include "include/gpio_interface.h" +#include "include/gpio_service_interface.h" +#include "hw_translate.h" +#include "hw_factory.h" + +/* + * Header of this unit + */ + +#include "gpio_service.h" + +/* + * Post-requisites: headers required by this unit + */ + +#include "hw_gpio.h" + +/* + * @brief + * Public API. + */ + +struct gpio_service *dal_gpio_service_create( + enum dce_version dce_version_major, + enum dce_version dce_version_minor, + struct dc_context *ctx) +{ + struct gpio_service *service; + + uint32_t index_of_id; + + service = dm_alloc(sizeof(struct gpio_service)); + + if (!service) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + if (!dal_hw_translate_init(&service->translate, dce_version_major, + dce_version_minor)) { + BREAK_TO_DEBUGGER(); + goto failure_1; + } + + if (!dal_hw_factory_init(&service->factory, dce_version_major, + dce_version_minor)) { + BREAK_TO_DEBUGGER(); + goto failure_1; + } + + /* allocate and initialize business storage */ + { + const uint32_t bits_per_uint = sizeof(uint32_t) << 3; + + index_of_id = 0; + service->ctx = ctx; + + do { + uint32_t number_of_bits = + service->factory.number_of_pins[index_of_id]; + + uint32_t number_of_uints = + (number_of_bits + bits_per_uint - 1) / + bits_per_uint; + + uint32_t *slot; + + if (number_of_bits) { + uint32_t index_of_uint = 0; + + slot = dm_alloc(number_of_uints * sizeof(uint32_t)); + + if (!slot) { + BREAK_TO_DEBUGGER(); + goto failure_2; + } + + do { + slot[index_of_uint] = 0; + + ++index_of_uint; + } while (index_of_uint < number_of_uints); + } else + slot = NULL; + + service->busyness[index_of_id] = slot; + + ++index_of_id; + } while (index_of_id < GPIO_ID_COUNT); + } + + return service; + +failure_2: + while (index_of_id) { + uint32_t *slot; + + --index_of_id; + + slot = service->busyness[index_of_id]; + + if (slot) + dm_free(slot); + }; + +failure_1: + dm_free(service); + + return NULL; +} + +struct gpio *dal_gpio_service_create_irq( + struct gpio_service *service, + uint32_t offset, + uint32_t mask) +{ + enum gpio_id id; + uint32_t en; + + if (!service->translate.funcs->offset_to_id(offset, mask, &id, &en)) { + ASSERT_CRITICAL(false); + return NULL; + } + + return dal_gpio_create_irq(service, id, en); +} + +void dal_gpio_service_destroy( + struct gpio_service **ptr) +{ + if (!ptr || !*ptr) { + BREAK_TO_DEBUGGER(); + return; + } + + /* free business storage */ + { + uint32_t index_of_id = 0; + + do { + uint32_t *slot = (*ptr)->busyness[index_of_id]; + + if (slot) + dm_free(slot); + + ++index_of_id; + } while (index_of_id < GPIO_ID_COUNT); + } + + dm_free(*ptr); + + *ptr = NULL; +} + +/* + * @brief + * Private API. + */ + +static bool is_pin_busy( + const struct gpio_service *service, + enum gpio_id id, + uint32_t en) +{ + const uint32_t bits_per_uint = sizeof(uint32_t) << 3; + + const uint32_t *slot = service->busyness[id] + (en / bits_per_uint); + + return 0 != (*slot & (1 << (en % bits_per_uint))); +} + +static void set_pin_busy( + struct gpio_service *service, + enum gpio_id id, + uint32_t en) +{ + const uint32_t bits_per_uint = sizeof(uint32_t) << 3; + + service->busyness[id][en / bits_per_uint] |= + (1 << (en % bits_per_uint)); +} + +static void set_pin_free( + struct gpio_service *service, + enum gpio_id id, + uint32_t en) +{ + const uint32_t bits_per_uint = sizeof(uint32_t) << 3; + + service->busyness[id][en / bits_per_uint] &= + ~(1 << (en % bits_per_uint)); +} + +enum gpio_result dal_gpio_service_open( + struct gpio_service *service, + enum gpio_id id, + uint32_t en, + enum gpio_mode mode, + struct hw_gpio_pin **ptr) +{ + struct hw_gpio_pin *pin; + + if (!service->busyness[id]) { + ASSERT_CRITICAL(false); + return GPIO_RESULT_OPEN_FAILED; + } + + if (is_pin_busy(service, id, en)) { + ASSERT_CRITICAL(false); + return GPIO_RESULT_DEVICE_BUSY; + } + + switch (id) { + case GPIO_ID_DDC_DATA: + pin = service->factory.funcs->create_ddc_data( + service->ctx, id, en); + service->factory.funcs->define_ddc_registers(pin, en); + break; + case GPIO_ID_DDC_CLOCK: + pin = service->factory.funcs->create_ddc_clock( + service->ctx, id, en); + service->factory.funcs->define_ddc_registers(pin, en); + break; + case GPIO_ID_GENERIC: + pin = service->factory.funcs->create_generic( + service->ctx, id, en); + break; + case GPIO_ID_HPD: + pin = service->factory.funcs->create_hpd( + service->ctx, id, en); + service->factory.funcs->define_hpd_registers(pin, en); + break; + case GPIO_ID_SYNC: + pin = service->factory.funcs->create_sync( + service->ctx, id, en); + break; + case GPIO_ID_GSL: + pin = service->factory.funcs->create_gsl( + service->ctx, id, en); + break; + default: + ASSERT_CRITICAL(false); + return GPIO_RESULT_NON_SPECIFIC_ERROR; + } + + if (!pin) { + ASSERT_CRITICAL(false); + return GPIO_RESULT_NON_SPECIFIC_ERROR; + } + + if (!pin->funcs->open(pin, mode)) { + ASSERT_CRITICAL(false); + dal_gpio_service_close(service, &pin); + return GPIO_RESULT_OPEN_FAILED; + } + + set_pin_busy(service, id, en); + *ptr = pin; + return GPIO_RESULT_OK; +} + +void dal_gpio_service_close( + struct gpio_service *service, + struct hw_gpio_pin **ptr) +{ + struct hw_gpio_pin *pin; + + if (!ptr) { + ASSERT_CRITICAL(false); + return; + } + + pin = *ptr; + + if (pin) { + set_pin_free(service, pin->id, pin->en); + + pin->funcs->close(pin); + + pin->funcs->destroy(ptr); + } +} + + +enum dc_irq_source dal_irq_get_source( + const struct gpio *irq) +{ + enum gpio_id id = dal_gpio_get_id(irq); + + switch (id) { + case GPIO_ID_HPD: + return (enum dc_irq_source)(DC_IRQ_SOURCE_HPD1 + + dal_gpio_get_enum(irq)); + case GPIO_ID_GPIO_PAD: + return (enum dc_irq_source)(DC_IRQ_SOURCE_GPIOPAD0 + + dal_gpio_get_enum(irq)); + default: + return DC_IRQ_SOURCE_INVALID; + } +} + +enum dc_irq_source dal_irq_get_rx_source( + const struct gpio *irq) +{ + enum gpio_id id = dal_gpio_get_id(irq); + + switch (id) { + case GPIO_ID_HPD: + return (enum dc_irq_source)(DC_IRQ_SOURCE_HPD1RX + + dal_gpio_get_enum(irq)); + default: + return DC_IRQ_SOURCE_INVALID; + } +} + +enum gpio_result dal_irq_setup_hpd_filter( + struct gpio *irq, + struct gpio_hpd_config *config) +{ + struct gpio_config_data config_data; + + if (!config) + return GPIO_RESULT_INVALID_DATA; + + config_data.type = GPIO_CONFIG_TYPE_HPD; + config_data.config.hpd = *config; + + return dal_gpio_set_config(irq, &config_data); +} + +/* + * @brief + * Creation and destruction + */ + +struct gpio *dal_gpio_create_irq( + struct gpio_service *service, + enum gpio_id id, + uint32_t en) +{ + struct gpio *irq; + + switch (id) { + case GPIO_ID_HPD: + case GPIO_ID_GPIO_PAD: + break; + default: + ASSERT_CRITICAL(false); + return NULL; + } + + irq = dal_gpio_create( + service, id, en, GPIO_PIN_OUTPUT_STATE_DEFAULT); + + if (irq) + return irq; + + ASSERT_CRITICAL(false); + return NULL; +} + +void dal_gpio_destroy_irq( + struct gpio **irq) +{ + if (!irq || !*irq) { + ASSERT_CRITICAL(false); + return; + } + + dal_gpio_close(*irq); + dal_gpio_destroy(irq); + dm_free(*irq); + + *irq = NULL; +} + +struct ddc *dal_gpio_create_ddc( + struct gpio_service *service, + uint32_t offset, + uint32_t mask, + struct gpio_ddc_hw_info *info) +{ + enum gpio_id id; + uint32_t en; + struct ddc *ddc; + + if (!service->translate.funcs->offset_to_id(offset, mask, &id, &en)) + return NULL; + + ddc = dm_alloc(sizeof(struct ddc)); + + if (!ddc) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + ddc->pin_data = dal_gpio_create( + service, GPIO_ID_DDC_DATA, en, GPIO_PIN_OUTPUT_STATE_DEFAULT); + + if (!ddc->pin_data) { + BREAK_TO_DEBUGGER(); + goto failure_1; + } + + ddc->pin_clock = dal_gpio_create( + service, GPIO_ID_DDC_CLOCK, en, GPIO_PIN_OUTPUT_STATE_DEFAULT); + + if (!ddc->pin_clock) { + BREAK_TO_DEBUGGER(); + goto failure_2; + } + + ddc->hw_info = *info; + + ddc->ctx = service->ctx; + + return ddc; + +failure_2: + dal_gpio_destroy(&ddc->pin_data); + +failure_1: + dm_free(ddc); + + return NULL; +} + +void dal_gpio_destroy_ddc( + struct ddc **ddc) +{ + if (!ddc || !*ddc) { + BREAK_TO_DEBUGGER(); + return; + } + + dal_ddc_close(*ddc); + dal_gpio_destroy(&(*ddc)->pin_data); + dal_gpio_destroy(&(*ddc)->pin_clock); + dm_free(*ddc); + + *ddc = NULL; +} + +enum gpio_result dal_ddc_open( + struct ddc *ddc, + enum gpio_mode mode, + enum gpio_ddc_config_type config_type) +{ + enum gpio_result result; + + struct gpio_config_data config_data; + struct hw_gpio *hw_data; + struct hw_gpio *hw_clock; + + result = dal_gpio_open_ex(ddc->pin_data, mode); + + if (result != GPIO_RESULT_OK) { + BREAK_TO_DEBUGGER(); + return result; + } + + result = dal_gpio_open_ex(ddc->pin_clock, mode); + + if (result != GPIO_RESULT_OK) { + BREAK_TO_DEBUGGER(); + goto failure; + } + + /* DDC clock and data pins should belong + * to the same DDC block id, + * we use the data pin to set the pad mode. */ + + if (mode == GPIO_MODE_INPUT) + /* this is from detect_sink_type, + * we need extra delay there */ + config_data.type = GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE; + else + config_data.type = GPIO_CONFIG_TYPE_DDC; + + config_data.config.ddc.type = config_type; + + hw_data = FROM_HW_GPIO_PIN(ddc->pin_data->pin); + hw_clock = FROM_HW_GPIO_PIN(ddc->pin_clock->pin); + + config_data.config.ddc.data_en_bit_present = hw_data->store.en != 0; + config_data.config.ddc.clock_en_bit_present = hw_clock->store.en != 0; + + result = dal_gpio_set_config(ddc->pin_data, &config_data); + + if (result == GPIO_RESULT_OK) + return result; + + BREAK_TO_DEBUGGER(); + + dal_gpio_close(ddc->pin_clock); + +failure: + dal_gpio_close(ddc->pin_data); + + return result; +} + +enum gpio_result dal_ddc_change_mode( + struct ddc *ddc, + enum gpio_mode mode) +{ + enum gpio_result result; + + enum gpio_mode original_mode = + dal_gpio_get_mode(ddc->pin_data); + + result = dal_gpio_change_mode(ddc->pin_data, mode); + + /* [anaumov] DAL2 code returns GPIO_RESULT_NON_SPECIFIC_ERROR + * in case of failures; + * set_mode() is so that, in case of failure, + * we must explicitly set original mode */ + + if (result != GPIO_RESULT_OK) + goto failure; + + result = dal_gpio_change_mode(ddc->pin_clock, mode); + + if (result == GPIO_RESULT_OK) + return result; + + dal_gpio_change_mode(ddc->pin_clock, original_mode); + +failure: + dal_gpio_change_mode(ddc->pin_data, original_mode); + + return result; +} + +enum gpio_ddc_line dal_ddc_get_line( + const struct ddc *ddc) +{ + return (enum gpio_ddc_line)dal_gpio_get_enum(ddc->pin_data); +} + +enum gpio_result dal_ddc_set_config( + struct ddc *ddc, + enum gpio_ddc_config_type config_type) +{ + struct gpio_config_data config_data; + + config_data.type = GPIO_CONFIG_TYPE_DDC; + + config_data.config.ddc.type = config_type; + config_data.config.ddc.data_en_bit_present = false; + config_data.config.ddc.clock_en_bit_present = false; + + return dal_gpio_set_config(ddc->pin_data, &config_data); +} + +void dal_ddc_close( + struct ddc *ddc) +{ + dal_gpio_close(ddc->pin_clock); + dal_gpio_close(ddc->pin_data); +} + diff --git a/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.h b/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.h new file mode 100644 index 000000000000..c7f3081f59cc --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.h @@ -0,0 +1,56 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_GPIO_SERVICE_H__ +#define __DAL_GPIO_SERVICE_H__ + +struct hw_translate; +struct hw_factory; + +struct gpio_service { + struct dc_context *ctx; + struct hw_translate translate; + struct hw_factory factory; + /* + * @brief + * Business storage. + * For each member of 'enum gpio_id', + * store array of bits (packed into uint32_t slots), + * index individual bit by 'en' value */ + uint32_t *busyness[GPIO_ID_COUNT]; +}; + +enum gpio_result dal_gpio_service_open( + struct gpio_service *service, + enum gpio_id id, + uint32_t en, + enum gpio_mode mode, + struct hw_gpio_pin **ptr); + +void dal_gpio_service_close( + struct gpio_service *service, + struct hw_gpio_pin **ptr); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hpd_regs.h b/drivers/gpu/drm/amd/display/dc/gpio/hpd_regs.h new file mode 100644 index 000000000000..dcfdd71b2304 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/hpd_regs.h @@ -0,0 +1,79 @@ +/* + * Copyright 2012-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef DRIVERS_GPU_DRM_AMD_DC_DEV_DC_GPIO_HPD_REGS_H_ +#define DRIVERS_GPU_DRM_AMD_DC_DEV_DC_GPIO_HPD_REGS_H_ + +#include "gpio_regs.h" + +#define ONE_MORE_0 1 +#define ONE_MORE_1 2 +#define ONE_MORE_2 3 +#define ONE_MORE_3 4 +#define ONE_MORE_4 5 +#define ONE_MORE_5 6 + + +#define HPD_GPIO_REG_LIST_ENTRY(type,cd,id) \ + .type ## _reg = REG(DC_GPIO_HPD_## type),\ + .type ## _mask = DC_GPIO_HPD_ ## type ## __DC_GPIO_HPD ## id ## _ ## type ## _MASK,\ + .type ## _shift = DC_GPIO_HPD_ ## type ## __DC_GPIO_HPD ## id ## _ ## type ## __SHIFT + +#define HPD_GPIO_REG_LIST(id) \ + {\ + HPD_GPIO_REG_LIST_ENTRY(MASK,cd,id),\ + HPD_GPIO_REG_LIST_ENTRY(A,cd,id),\ + HPD_GPIO_REG_LIST_ENTRY(EN,cd,id),\ + HPD_GPIO_REG_LIST_ENTRY(Y,cd,id)\ + } + +#define HPD_REG_LIST(id) \ + HPD_GPIO_REG_LIST(ONE_MORE_ ## id), \ + .int_status = REGI(DC_HPD_INT_STATUS, HPD, id),\ + .toggle_filt_cntl = REGI(DC_HPD_TOGGLE_FILT_CNTL, HPD, id) + + #define HPD_MASK_SH_LIST(mask_sh) \ + SF_HPD(DC_HPD_INT_STATUS, DC_HPD_SENSE_DELAYED, mask_sh),\ + SF_HPD(DC_HPD_INT_STATUS, DC_HPD_SENSE, mask_sh),\ + SF_HPD(DC_HPD_TOGGLE_FILT_CNTL, DC_HPD_CONNECT_INT_DELAY, mask_sh),\ + SF_HPD(DC_HPD_TOGGLE_FILT_CNTL, DC_HPD_DISCONNECT_INT_DELAY, mask_sh) + +struct hpd_registers { + struct gpio_registers gpio; + uint32_t int_status; + uint32_t toggle_filt_cntl; +}; + +struct hpd_sh_mask { + /* int_status */ + uint32_t DC_HPD_SENSE_DELAYED; + uint32_t DC_HPD_SENSE; + /* toggle_filt_cntl */ + uint32_t DC_HPD_CONNECT_INT_DELAY; + uint32_t DC_HPD_DISCONNECT_INT_DELAY; +}; + + +#endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_GPIO_HPD_REGS_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c new file mode 100644 index 000000000000..47e0f8f24a86 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c @@ -0,0 +1,243 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "include/gpio_types.h" +#include "hw_gpio.h" +#include "hw_ddc.h" + +#include "reg_helper.h" +#include "gpio_regs.h" + + +#undef FN +#define FN(reg_name, field_name) \ + ddc->shifts->field_name, ddc->masks->field_name + +#define CTX \ + ddc->base.base.ctx +#define REG(reg)\ + (ddc->regs->reg) + +static void destruct( + struct hw_ddc *pin) +{ + dal_hw_gpio_destruct(&pin->base); +} + +static void destroy( + struct hw_gpio_pin **ptr) +{ + struct hw_ddc *pin = HW_DDC_FROM_BASE(*ptr); + + destruct(pin); + + dm_free(pin); + + *ptr = NULL; +} + +static enum gpio_result set_config( + struct hw_gpio_pin *ptr, + const struct gpio_config_data *config_data) +{ + struct hw_ddc *ddc = HW_DDC_FROM_BASE(ptr); + struct hw_gpio *hw_gpio = NULL; + uint32_t regval; + uint32_t ddc_data_pd_en = 0; + uint32_t ddc_clk_pd_en = 0; + uint32_t aux_pad_mode = 0; + + hw_gpio = &ddc->base; + + if (hw_gpio == NULL) { + ASSERT_CRITICAL(false); + return GPIO_RESULT_NULL_HANDLE; + } + + regval = REG_GET_3(gpio.MASK_reg, + DC_GPIO_DDC1DATA_PD_EN, &ddc_data_pd_en, + DC_GPIO_DDC1CLK_PD_EN, &ddc_clk_pd_en, + AUX_PAD1_MODE, &aux_pad_mode); + + switch (config_data->config.ddc.type) { + case GPIO_DDC_CONFIG_TYPE_MODE_I2C: + /* On plug-in, there is a transient level on the pad + * which must be discharged through the internal pull-down. + * Enable internal pull-down, 2.5msec discharge time + * is required for detection of AUX mode */ + if (hw_gpio->base.en != GPIO_DDC_LINE_VIP_PAD) { + if (!ddc_data_pd_en || !ddc_clk_pd_en) { + + REG_SET_2(gpio.MASK_reg, regval, + DC_GPIO_DDC1DATA_PD_EN, 1, + DC_GPIO_DDC1CLK_PD_EN, 1); + + if (config_data->type == + GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE) + msleep(3); + } + } else { + uint32_t reg2; + uint32_t sda_pd_dis = 0; + uint32_t scl_pd_dis = 0; + + reg2 = REG_GET_2(gpio.MASK_reg, + DC_GPIO_SDA_PD_DIS, &sda_pd_dis, + DC_GPIO_SCL_PD_DIS, &scl_pd_dis); + + if (sda_pd_dis) { + REG_SET(gpio.MASK_reg, regval, + DC_GPIO_SDA_PD_DIS, 0); + + if (config_data->type == + GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE) + msleep(3); + } + + if (!scl_pd_dis) { + REG_SET(gpio.MASK_reg, regval, + DC_GPIO_SCL_PD_DIS, 1); + + if (config_data->type == + GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE) + msleep(3); + } + } + + if (aux_pad_mode) { + /* let pins to get de-asserted + * before setting pad to I2C mode */ + if (config_data->config.ddc.data_en_bit_present || + config_data->config.ddc.clock_en_bit_present) + /* [anaumov] in DAL2, there was + * dc_service_delay_in_microseconds(2000); */ + msleep(2); + + /* set the I2C pad mode */ + /* read the register again, + * some bits may have been changed */ + REG_UPDATE(gpio.MASK_reg, + AUX_PAD1_MODE, 0); + } + + return GPIO_RESULT_OK; + case GPIO_DDC_CONFIG_TYPE_MODE_AUX: + /* set the AUX pad mode */ + if (!aux_pad_mode) { + REG_SET(gpio.MASK_reg, regval, + AUX_PAD1_MODE, 1); + } + + return GPIO_RESULT_OK; + case GPIO_DDC_CONFIG_TYPE_POLL_FOR_CONNECT: + if ((hw_gpio->base.en >= GPIO_DDC_LINE_DDC1) && + (hw_gpio->base.en <= GPIO_DDC_LINE_DDC_VGA)) { + REG_UPDATE_3(ddc_setup, + DC_I2C_DDC1_ENABLE, 1, + DC_I2C_DDC1_EDID_DETECT_ENABLE, 1, + DC_I2C_DDC1_EDID_DETECT_MODE, 0); + return GPIO_RESULT_OK; + } + break; + case GPIO_DDC_CONFIG_TYPE_POLL_FOR_DISCONNECT: + if ((hw_gpio->base.en >= GPIO_DDC_LINE_DDC1) && + (hw_gpio->base.en <= GPIO_DDC_LINE_DDC_VGA)) { + REG_UPDATE_3(ddc_setup, + DC_I2C_DDC1_ENABLE, 1, + DC_I2C_DDC1_EDID_DETECT_ENABLE, 1, + DC_I2C_DDC1_EDID_DETECT_MODE, 1); + return GPIO_RESULT_OK; + } + break; + case GPIO_DDC_CONFIG_TYPE_DISABLE_POLLING: + if ((hw_gpio->base.en >= GPIO_DDC_LINE_DDC1) && + (hw_gpio->base.en <= GPIO_DDC_LINE_DDC_VGA)) { + REG_UPDATE_2(ddc_setup, + DC_I2C_DDC1_ENABLE, 0, + DC_I2C_DDC1_EDID_DETECT_ENABLE, 0); + return GPIO_RESULT_OK; + } + break; + } + + BREAK_TO_DEBUGGER(); + + return GPIO_RESULT_NON_SPECIFIC_ERROR; +} + +static const struct hw_gpio_pin_funcs funcs = { + .destroy = destroy, + .open = dal_hw_gpio_open, + .get_value = dal_hw_gpio_get_value, + .set_value = dal_hw_gpio_set_value, + .set_config = set_config, + .change_mode = dal_hw_gpio_change_mode, + .close = dal_hw_gpio_close, +}; + +static bool construct( + struct hw_ddc *ddc, + enum gpio_id id, + uint32_t en, + struct dc_context *ctx) +{ + if ((en < GPIO_DDC_LINE_MIN) || (en > GPIO_DDC_LINE_MAX)) { + ASSERT_CRITICAL(false); + return false; + } + + if (!dal_hw_gpio_construct(&ddc->base, id, en, ctx)) { + ASSERT_CRITICAL(false); + return false; + } + + ddc->base.base.funcs = &funcs; + + return true; +} + +struct hw_gpio_pin *dal_hw_ddc_create( + struct dc_context *ctx, + enum gpio_id id, + uint32_t en) +{ + struct hw_ddc *pin = dm_alloc(sizeof(struct hw_ddc)); + + if (!pin) { + ASSERT_CRITICAL(false); + return NULL; + } + + if (construct(pin, id, en, ctx)) + return &pin->base.base; + + ASSERT_CRITICAL(false); + + dm_free(pin); + + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.h b/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.h new file mode 100644 index 000000000000..9690e2a885d7 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.h @@ -0,0 +1,46 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_HW_DDC_H__ +#define __DAL_HW_DDC_H__ + +#include "ddc_regs.h" + +struct hw_ddc { + struct hw_gpio base; + const struct ddc_registers *regs; + const struct ddc_sh_mask *shifts; + const struct ddc_sh_mask *masks; +}; + +#define HW_DDC_FROM_BASE(hw_gpio) \ + container_of((HW_GPIO_FROM_BASE(hw_gpio)), struct hw_ddc, base) + +struct hw_gpio_pin *dal_hw_ddc_create( + struct dc_context *ctx, + enum gpio_id id, + uint32_t en); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c new file mode 100644 index 000000000000..f1a6fa7391c6 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c @@ -0,0 +1,93 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* + * Pre-requisites: headers required by header of this unit + */ +#include "include/gpio_types.h" + +/* + * Header of this unit + */ + +#include "hw_factory.h" + +/* + * Post-requisites: headers required by this unit + */ + +#include "dce80/hw_factory_dce80.h" + +#include "dce110/hw_factory_dce110.h" + +#include "diagnostics/hw_factory_diag.h" + +/* + * This unit + */ + +bool dal_hw_factory_init( + struct hw_factory *factory, + enum dce_version dce_version, + enum dce_environment dce_environment) +{ + if (IS_FPGA_MAXIMUS_DC(dce_environment)) { + dal_hw_factory_diag_fpga_init(factory); + return true; + } + + switch (dce_version) { + case DCE_VERSION_8_0: + dal_hw_factory_dce80_init(factory); + return true; + + case DCE_VERSION_10_0: + dal_hw_factory_dce110_init(factory); + return true; + case DCE_VERSION_11_0: + case DCE_VERSION_11_2: + dal_hw_factory_dce110_init(factory); + return true; + default: + ASSERT_CRITICAL(false); + return false; + } +} + +void dal_hw_factory_destroy( + struct dc_context *ctx, + struct hw_factory **factory) +{ + if (!factory || !*factory) { + BREAK_TO_DEBUGGER(); + return; + } + + dm_free(*factory); + + *factory = NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.h b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.h new file mode 100644 index 000000000000..6e4dd3521935 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.h @@ -0,0 +1,74 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_HW_FACTORY_H__ +#define __DAL_HW_FACTORY_H__ + +struct hw_gpio_pin; +struct hw_hpd; + +struct hw_factory { + uint32_t number_of_pins[GPIO_ID_COUNT]; + + const struct hw_factory_funcs { + struct hw_gpio_pin *(*create_ddc_data)( + struct dc_context *ctx, + enum gpio_id id, + uint32_t en); + struct hw_gpio_pin *(*create_ddc_clock)( + struct dc_context *ctx, + enum gpio_id id, + uint32_t en); + struct hw_gpio_pin *(*create_generic)( + struct dc_context *ctx, + enum gpio_id id, + uint32_t en); + struct hw_gpio_pin *(*create_hpd)( + struct dc_context *ctx, + enum gpio_id id, + uint32_t en); + struct hw_gpio_pin *(*create_sync)( + struct dc_context *ctx, + enum gpio_id id, + uint32_t en); + struct hw_gpio_pin *(*create_gsl)( + struct dc_context *ctx, + enum gpio_id id, + uint32_t en); + void (*define_hpd_registers)( + struct hw_gpio_pin *pin, + uint32_t en); + void (*define_ddc_registers)( + struct hw_gpio_pin *pin, + uint32_t en); + } *funcs; +}; + +bool dal_hw_factory_init( + struct hw_factory *factory, + enum dce_version dce_version, + enum dce_environment dce_environment); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.c new file mode 100644 index 000000000000..4cdcdfb73e5c --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.c @@ -0,0 +1,205 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "include/gpio_types.h" +#include "hw_gpio.h" + +#include "reg_helper.h" +#include "gpio_regs.h" + +#undef FN +#define FN(reg_name, field_name) \ + gpio->regs->field_name ## _shift, gpio->regs->field_name ## _mask + +#define CTX \ + gpio->base.ctx +#define REG(reg)\ + (gpio->regs->reg) + +static void store_registers( + struct hw_gpio *gpio) +{ + REG_GET(MASK_reg, MASK, &gpio->store.mask); + REG_GET(A_reg, A, &gpio->store.a); + REG_GET(EN_reg, EN, &gpio->store.en); + /* TODO store GPIO_MUX_CONTROL if we ever use it */ +} + +static void restore_registers( + struct hw_gpio *gpio) +{ + REG_UPDATE(MASK_reg, MASK, gpio->store.mask); + REG_UPDATE(A_reg, A, gpio->store.a); + REG_UPDATE(EN_reg, EN, gpio->store.en); + /* TODO restore GPIO_MUX_CONTROL if we ever use it */ +} + +bool dal_hw_gpio_open( + struct hw_gpio_pin *ptr, + enum gpio_mode mode) +{ + struct hw_gpio *pin = FROM_HW_GPIO_PIN(ptr); + + store_registers(pin); + + ptr->opened = (dal_hw_gpio_config_mode(pin, mode) == GPIO_RESULT_OK); + + return ptr->opened; +} + +enum gpio_result dal_hw_gpio_get_value( + const struct hw_gpio_pin *ptr, + uint32_t *value) +{ + const struct hw_gpio *gpio = FROM_HW_GPIO_PIN(ptr); + + enum gpio_result result = GPIO_RESULT_OK; + + switch (ptr->mode) { + case GPIO_MODE_INPUT: + case GPIO_MODE_OUTPUT: + case GPIO_MODE_HARDWARE: + case GPIO_MODE_FAST_OUTPUT: + REG_GET(Y_reg, Y, value); + break; + default: + result = GPIO_RESULT_NON_SPECIFIC_ERROR; + } + + return result; +} + +enum gpio_result dal_hw_gpio_set_value( + const struct hw_gpio_pin *ptr, + uint32_t value) +{ + struct hw_gpio *gpio = FROM_HW_GPIO_PIN(ptr); + + /* This is the public interface + * where the input comes from client, not shifted yet + * (because client does not know the shifts). */ + + switch (ptr->mode) { + case GPIO_MODE_OUTPUT: + REG_UPDATE(A_reg, A, value); + return GPIO_RESULT_OK; + case GPIO_MODE_FAST_OUTPUT: + /* We use (EN) to faster switch (used in DDC GPIO). + * So (A) is grounded, output is driven by (EN = 0) + * to pull the line down (output == 0) and (EN=1) + * then output is tri-state */ + REG_UPDATE(EN_reg, EN, ~value); + return GPIO_RESULT_OK; + default: + return GPIO_RESULT_NON_SPECIFIC_ERROR; + } +} + +enum gpio_result dal_hw_gpio_change_mode( + struct hw_gpio_pin *ptr, + enum gpio_mode mode) +{ + struct hw_gpio *pin = FROM_HW_GPIO_PIN(ptr); + + return dal_hw_gpio_config_mode(pin, mode); +} + +void dal_hw_gpio_close( + struct hw_gpio_pin *ptr) +{ + struct hw_gpio *pin = FROM_HW_GPIO_PIN(ptr); + + restore_registers(pin); + + ptr->mode = GPIO_MODE_UNKNOWN; + ptr->opened = false; +} + +enum gpio_result dal_hw_gpio_config_mode( + struct hw_gpio *gpio, + enum gpio_mode mode) +{ + gpio->base.mode = mode; + + switch (mode) { + case GPIO_MODE_INPUT: + /* turn off output enable, act as input pin; + * program the pin as GPIO, mask out signal driven by HW */ + REG_UPDATE(EN_reg, EN, 0); + REG_UPDATE(MASK_reg, MASK, 1); + return GPIO_RESULT_OK; + case GPIO_MODE_OUTPUT: + /* turn on output enable, act as output pin; + * program the pin as GPIO, mask out signal driven by HW */ + REG_UPDATE(A_reg, A, 0); + REG_UPDATE(MASK_reg, MASK, 1); + return GPIO_RESULT_OK; + case GPIO_MODE_FAST_OUTPUT: + /* grounding the A register then use the EN register bit + * will have faster effect on the rise time */ + REG_UPDATE(A_reg, A, 0); + REG_UPDATE(MASK_reg, MASK, 1); + return GPIO_RESULT_OK; + case GPIO_MODE_HARDWARE: + /* program the pin as tri-state, pin is driven by HW */ + REG_UPDATE(MASK_reg, MASK, 0); + return GPIO_RESULT_OK; + case GPIO_MODE_INTERRUPT: + /* Interrupt mode supported only by HPD (IrqGpio) pins. */ + REG_UPDATE(MASK_reg, MASK, 0); + return GPIO_RESULT_OK; + default: + return GPIO_RESULT_NON_SPECIFIC_ERROR; + } +} + +bool dal_hw_gpio_construct( + struct hw_gpio *pin, + enum gpio_id id, + uint32_t en, + struct dc_context *ctx) +{ + pin->base.ctx = ctx; + pin->base.id = id; + pin->base.en = en; + pin->base.mode = GPIO_MODE_UNKNOWN; + pin->base.opened = false; + + pin->store.mask = 0; + pin->store.a = 0; + pin->store.en = 0; + pin->store.mux = 0; + + pin->mux_supported = false; + + return true; +} + +void dal_hw_gpio_destruct( + struct hw_gpio *pin) +{ + ASSERT(!pin->base.opened); +} diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.h b/drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.h new file mode 100644 index 000000000000..fb41ee2be958 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.h @@ -0,0 +1,144 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_HW_GPIO_H__ +#define __DAL_HW_GPIO_H__ + +#include "gpio_regs.h" + +#define FROM_HW_GPIO_PIN(ptr) \ + container_of((ptr), struct hw_gpio, base) + +struct addr_mask { + uint32_t addr; + uint32_t mask; +}; + +struct hw_gpio_pin { + const struct hw_gpio_pin_funcs *funcs; + enum gpio_id id; + uint32_t en; + enum gpio_mode mode; + bool opened; + struct dc_context *ctx; +}; + +struct hw_gpio_pin_funcs { + void (*destroy)( + struct hw_gpio_pin **ptr); + bool (*open)( + struct hw_gpio_pin *pin, + enum gpio_mode mode); + enum gpio_result (*get_value)( + const struct hw_gpio_pin *pin, + uint32_t *value); + enum gpio_result (*set_value)( + const struct hw_gpio_pin *pin, + uint32_t value); + enum gpio_result (*set_config)( + struct hw_gpio_pin *pin, + const struct gpio_config_data *config_data); + enum gpio_result (*change_mode)( + struct hw_gpio_pin *pin, + enum gpio_mode mode); + void (*close)( + struct hw_gpio_pin *pin); +}; + + +struct hw_gpio; + +/* Register indices are represented by member variables + * and are to be filled in by constructors of derived classes. + * These members permit the use of common code + * for programming registers, where the sequence is the same + * but register sets are different. + * Some GPIOs have HW mux which allows to choose + * what is the source of the signal in HW mode */ + +struct hw_gpio_pin_reg { + struct addr_mask DC_GPIO_DATA_MASK; + struct addr_mask DC_GPIO_DATA_A; + struct addr_mask DC_GPIO_DATA_EN; + struct addr_mask DC_GPIO_DATA_Y; +}; + +struct hw_gpio_mux_reg { + struct addr_mask GPIO_MUX_CONTROL; + struct addr_mask GPIO_MUX_STEREO_SEL; +}; + +struct hw_gpio { + struct hw_gpio_pin base; + + /* variables to save register value */ + struct { + uint32_t mask; + uint32_t a; + uint32_t en; + uint32_t mux; + } store; + + /* GPIO MUX support */ + bool mux_supported; + const struct gpio_registers *regs; +}; + +#define HW_GPIO_FROM_BASE(hw_gpio_pin) \ + container_of((hw_gpio_pin), struct hw_gpio, base) + +bool dal_hw_gpio_construct( + struct hw_gpio *pin, + enum gpio_id id, + uint32_t en, + struct dc_context *ctx); + +bool dal_hw_gpio_open( + struct hw_gpio_pin *pin, + enum gpio_mode mode); + +enum gpio_result dal_hw_gpio_get_value( + const struct hw_gpio_pin *pin, + uint32_t *value); + +enum gpio_result dal_hw_gpio_config_mode( + struct hw_gpio *pin, + enum gpio_mode mode); + +void dal_hw_gpio_destruct( + struct hw_gpio *pin); + +enum gpio_result dal_hw_gpio_set_value( + const struct hw_gpio_pin *ptr, + uint32_t value); + +enum gpio_result dal_hw_gpio_change_mode( + struct hw_gpio_pin *ptr, + enum gpio_mode mode); + +void dal_hw_gpio_close( + struct hw_gpio_pin *ptr); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.c new file mode 100644 index 000000000000..9634e8841d90 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.c @@ -0,0 +1,175 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "include/gpio_types.h" +#include "hw_gpio.h" +#include "hw_hpd.h" + +#include "reg_helper.h" +#include "hpd_regs.h" + +#undef FN +#define FN(reg_name, field_name) \ + hpd->shifts->field_name, hpd->masks->field_name + +#define CTX \ + hpd->base.base.ctx +#define REG(reg)\ + (hpd->regs->reg) + +static bool dal_hw_hpd_construct( + struct hw_hpd *pin, + enum gpio_id id, + uint32_t en, + struct dc_context *ctx) +{ + if (!dal_hw_gpio_construct(&pin->base, id, en, ctx)) + return false; + return true; +} + +static void dal_hw_hpd_destruct( + struct hw_hpd *pin) +{ + dal_hw_gpio_destruct(&pin->base); +} + + +static void destruct( + struct hw_hpd *hpd) +{ + dal_hw_hpd_destruct(hpd); +} + +static void destroy( + struct hw_gpio_pin **ptr) +{ + struct hw_hpd *hpd = HW_HPD_FROM_BASE(*ptr); + + destruct(hpd); + + dm_free(hpd); + + *ptr = NULL; +} + +static enum gpio_result get_value( + const struct hw_gpio_pin *ptr, + uint32_t *value) +{ + struct hw_hpd *hpd = HW_HPD_FROM_BASE(ptr); + uint32_t hpd_delayed = 0; + + /* in Interrupt mode we ask for SENSE bit */ + + if (ptr->mode == GPIO_MODE_INTERRUPT) { + + REG_GET(int_status, + DC_HPD_SENSE_DELAYED, &hpd_delayed); + + *value = hpd_delayed; + return GPIO_RESULT_OK; + } + + /* in any other modes, operate as normal GPIO */ + + return dal_hw_gpio_get_value(ptr, value); +} + +static enum gpio_result set_config( + struct hw_gpio_pin *ptr, + const struct gpio_config_data *config_data) +{ + struct hw_hpd *hpd = HW_HPD_FROM_BASE(ptr); + + if (!config_data) + return GPIO_RESULT_INVALID_DATA; + + REG_UPDATE_2(toggle_filt_cntl, + DC_HPD_CONNECT_INT_DELAY, config_data->config.hpd.delay_on_connect / 10, + DC_HPD_DISCONNECT_INT_DELAY, config_data->config.hpd.delay_on_disconnect / 10); + + return GPIO_RESULT_OK; +} + +static const struct hw_gpio_pin_funcs funcs = { + .destroy = destroy, + .open = dal_hw_gpio_open, + .get_value = get_value, + .set_value = dal_hw_gpio_set_value, + .set_config = set_config, + .change_mode = dal_hw_gpio_change_mode, + .close = dal_hw_gpio_close, +}; + +static bool construct( + struct hw_hpd *hpd, + enum gpio_id id, + uint32_t en, + struct dc_context *ctx) +{ + if (id != GPIO_ID_HPD) { + ASSERT_CRITICAL(false); + return false; + } + + if ((en < GPIO_HPD_MIN) || (en > GPIO_HPD_MAX)) { + ASSERT_CRITICAL(false); + return false; + } + + if (!dal_hw_hpd_construct(hpd, id, en, ctx)) { + ASSERT_CRITICAL(false); + return false; + } + + hpd->base.base.funcs = &funcs; + + return true; +} + +struct hw_gpio_pin *dal_hw_hpd_create( + struct dc_context *ctx, + enum gpio_id id, + uint32_t en) +{ + struct hw_hpd *hpd = dm_alloc(sizeof(struct hw_hpd)); + + if (!hpd) { + ASSERT_CRITICAL(false); + return NULL; + } + + if (construct(hpd, id, en, ctx)) + return &hpd->base.base; + + ASSERT_CRITICAL(false); + + dm_free(hpd); + + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.h b/drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.h new file mode 100644 index 000000000000..4ab7a208f781 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.h @@ -0,0 +1,46 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_HW_HPD_H__ +#define __DAL_HW_HPD_H__ + +#include "hpd_regs.h" + +struct hw_hpd { + struct hw_gpio base; + const struct hpd_registers *regs; + const struct hpd_sh_mask *shifts; + const struct hpd_sh_mask *masks; +}; + +#define HW_HPD_FROM_BASE(hw_gpio) \ + container_of((HW_GPIO_FROM_BASE(hw_gpio)), struct hw_hpd, base) + +struct hw_gpio_pin *dal_hw_hpd_create( + struct dc_context *ctx, + enum gpio_id id, + uint32_t en); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c new file mode 100644 index 000000000000..23e097fa5ace --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c @@ -0,0 +1,75 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* + * Pre-requisites: headers required by header of this unit + */ +#include "include/gpio_types.h" + +/* + * Header of this unit + */ + +#include "hw_translate.h" + +/* + * Post-requisites: headers required by this unit + */ + +#include "dce80/hw_translate_dce80.h" +#include "dce110/hw_translate_dce110.h" + +#include "diagnostics/hw_translate_diag.h" + +/* + * This unit + */ + +bool dal_hw_translate_init( + struct hw_translate *translate, + enum dce_version dce_version, + enum dce_environment dce_environment) +{ + if (IS_FPGA_MAXIMUS_DC(dce_environment)) { + dal_hw_translate_diag_fpga_init(translate); + return true; + } + + switch (dce_version) { + case DCE_VERSION_8_0: + dal_hw_translate_dce80_init(translate); + return true; + case DCE_VERSION_10_0: + case DCE_VERSION_11_0: + case DCE_VERSION_11_2: + dal_hw_translate_dce110_init(translate); + return true; + default: + BREAK_TO_DEBUGGER(); + return false; + } +} diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.h b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.h new file mode 100644 index 000000000000..3a7d89ca1605 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.h @@ -0,0 +1,50 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_HW_TRANSLATE_H__ +#define __DAL_HW_TRANSLATE_H__ + +struct hw_translate_funcs { + bool (*offset_to_id)( + uint32_t offset, + uint32_t mask, + enum gpio_id *id, + uint32_t *en); + bool (*id_to_offset)( + enum gpio_id id, + uint32_t en, + struct gpio_pin_info *info); +}; + +struct hw_translate { + const struct hw_translate_funcs *funcs; +}; + +bool dal_hw_translate_init( + struct hw_translate *translate, + enum dce_version dce_version, + enum dce_environment dce_environment); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/gpu/Makefile b/drivers/gpu/drm/amd/display/dc/gpu/Makefile new file mode 100644 index 000000000000..fd17af1ce88e --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpu/Makefile @@ -0,0 +1,36 @@ +# +# Makefile for the 'gpu' sub-component of DAL. +# It provides the control and status of HW adapter resources, +# that are global for the ASIC and sharable between pipes. + +GPU = display_clock.o divider_range.o + +AMD_DAL_GPU = $(addprefix $(AMDDALPATH)/dc/gpu/,$(GPU)) + +AMD_DISPLAY_FILES += $(AMD_DAL_GPU) + +############################################################################### +# DCE 80 family +############################################################################### +GPU_DCE80 = display_clock_dce80.o + +AMD_DAL_GPU_DCE80 = $(addprefix $(AMDDALPATH)/dc/gpu/dce80/,$(GPU_DCE80)) + +AMD_DISPLAY_FILES += $(AMD_DAL_GPU_DCE80) + + +############################################################################### +# DCE 110 family +############################################################################### +GPU_DCE110 = display_clock_dce110.o + +AMD_DAL_GPU_DCE110 = $(addprefix $(AMDDALPATH)/dc/gpu/dce110/,$(GPU_DCE110)) + +AMD_DISPLAY_FILES += $(AMD_DAL_GPU_DCE110) + +GPU_DCE112 = display_clock_dce112.o + +AMD_DAL_GPU_DCE112 = $(addprefix $(AMDDALPATH)/dc/gpu/dce112/,$(GPU_DCE112)) + +AMD_DISPLAY_FILES += $(AMD_DAL_GPU_DCE110) $(AMD_DAL_GPU_DCE112) + diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c b/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c new file mode 100644 index 000000000000..1bc39f12b6a1 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c @@ -0,0 +1,1035 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" + +#include "include/bios_parser_interface.h" +#include "include/fixed32_32.h" +#include "include/logger_interface.h" + +#include "../divider_range.h" + +#include "display_clock_dce110.h" +#include "dc.h" + +#define FROM_DISPLAY_CLOCK(base) \ + container_of(base, struct display_clock_dce110, disp_clk_base) + +#define PSR_SET_WAITLOOP 0x31 + +static struct state_dependent_clocks max_clks_by_state[] = { +/*ClocksStateInvalid - should not be used*/ +{ .display_clk_khz = 0, .pixel_clk_khz = 0 }, +/*ClocksStateUltraLow - currently by HW design team not supposed to be used*/ +{ .display_clk_khz = 352000, .pixel_clk_khz = 330000 }, +/*ClocksStateLow*/ +{ .display_clk_khz = 352000, .pixel_clk_khz = 330000 }, +/*ClocksStateNominal*/ +{ .display_clk_khz = 467000, .pixel_clk_khz = 400000 }, +/*ClocksStatePerformance*/ +{ .display_clk_khz = 643000, .pixel_clk_khz = 400000 } }; + +/* Starting point for each divider range.*/ +enum divider_range_start { + DIVIDER_RANGE_01_START = 200, /* 2.00*/ + DIVIDER_RANGE_02_START = 1600, /* 16.00*/ + DIVIDER_RANGE_03_START = 3200, /* 32.00*/ + DIVIDER_RANGE_SCALE_FACTOR = 100 /* Results are scaled up by 100.*/ +}; + +/* Array identifiers and count for the divider ranges.*/ +enum divider_range_count { + DIVIDER_RANGE_01 = 0, + DIVIDER_RANGE_02, + DIVIDER_RANGE_03, + DIVIDER_RANGE_MAX /* == 3*/ +}; + +/* Ranges for divider identifiers (Divider ID or DID) + mmDENTIST_DISPCLK_CNTL.DENTIST_DISPCLK_WDIVIDER*/ +enum divider_id_register_setting { + DIVIDER_RANGE_01_BASE_DIVIDER_ID = 0X08, + DIVIDER_RANGE_02_BASE_DIVIDER_ID = 0X40, + DIVIDER_RANGE_03_BASE_DIVIDER_ID = 0X60, + DIVIDER_RANGE_MAX_DIVIDER_ID = 0X80 +}; + +/* Step size between each divider within a range. + Incrementing the DENTIST_DISPCLK_WDIVIDER by one + will increment the divider by this much.*/ +enum divider_range_step_size { + DIVIDER_RANGE_01_STEP_SIZE = 25, /* 0.25*/ + DIVIDER_RANGE_02_STEP_SIZE = 50, /* 0.50*/ + DIVIDER_RANGE_03_STEP_SIZE = 100 /* 1.00 */ +}; + +union dce110_dmcu_psr_config_data_wait_loop_reg1 { + struct { + unsigned int waitLoop:16; /* [15:0] */ + unsigned int reserved:16; /* [31:16] */ + } bits; + unsigned int u32All; +}; + +static struct divider_range divider_ranges[DIVIDER_RANGE_MAX]; + +#define DCE110_DFS_BYPASS_THRESHOLD_KHZ 400000 +/***************************************************************************** + * static functions + *****************************************************************************/ + +/* + * store_max_clocks_state + * + * @brief + * Cache the clock state + * + * @param + * struct display_clock *base - [out] cach the state in this structure + * enum clocks_state max_clocks_state - [in] state to be stored + */ +static void store_max_clocks_state( + struct display_clock *base, + enum clocks_state max_clocks_state) +{ + struct display_clock_dce110 *dc = DCLCK110_FROM_BASE(base); + + switch (max_clocks_state) { + case CLOCKS_STATE_LOW: + case CLOCKS_STATE_NOMINAL: + case CLOCKS_STATE_PERFORMANCE: + case CLOCKS_STATE_ULTRA_LOW: + dc->max_clks_state = max_clocks_state; + break; + + case CLOCKS_STATE_INVALID: + default: + /*Invalid Clocks State!*/ + ASSERT_CRITICAL(false); + break; + } +} + +static enum clocks_state get_min_clocks_state(struct display_clock *base) +{ + return base->cur_min_clks_state; +} + +static bool set_min_clocks_state( + struct display_clock *base, + enum clocks_state clocks_state) +{ + struct display_clock_dce110 *dc = DCLCK110_FROM_BASE(base); + struct dm_pp_power_level_change_request level_change_req = { + DM_PP_POWER_LEVEL_INVALID}; + + if (clocks_state > dc->max_clks_state) { + /*Requested state exceeds max supported state.*/ + dm_logger_write(base->ctx->logger, LOG_WARNING, + "Requested state exceeds max supported state"); + return false; + } else if (clocks_state == base->cur_min_clks_state) { + /*if we're trying to set the same state, we can just return + * since nothing needs to be done*/ + return true; + } + + switch (clocks_state) { + case CLOCKS_STATE_ULTRA_LOW: + level_change_req.power_level = DM_PP_POWER_LEVEL_ULTRA_LOW; + break; + case CLOCKS_STATE_LOW: + level_change_req.power_level = DM_PP_POWER_LEVEL_LOW; + break; + case CLOCKS_STATE_NOMINAL: + level_change_req.power_level = DM_PP_POWER_LEVEL_NOMINAL; + break; + case CLOCKS_STATE_PERFORMANCE: + level_change_req.power_level = DM_PP_POWER_LEVEL_PERFORMANCE; + break; + case CLOCKS_STATE_INVALID: + default: + dm_logger_write(base->ctx->logger, LOG_WARNING, + "Requested state invalid state"); + return false; + } + + /* get max clock state from PPLIB */ + if (dm_pp_apply_power_level_change_request( + base->ctx, &level_change_req)) + base->cur_min_clks_state = clocks_state; + + return true; +} + +static uint32_t get_dp_ref_clk_frequency(struct display_clock *dc) +{ + uint32_t dispclk_cntl_value; + uint32_t dp_ref_clk_cntl_value; + uint32_t dp_ref_clk_cntl_src_sel_value; + uint32_t dp_ref_clk_khz = 600000; + uint32_t target_div = INVALID_DIVIDER; + struct display_clock_dce110 *disp_clk = FROM_DISPLAY_CLOCK(dc); + + /* ASSERT DP Reference Clock source is from DFS*/ + dp_ref_clk_cntl_value = dm_read_reg(dc->ctx, + mmDPREFCLK_CNTL); + + dp_ref_clk_cntl_src_sel_value = + get_reg_field_value( + dp_ref_clk_cntl_value, + DPREFCLK_CNTL, DPREFCLK_SRC_SEL); + + ASSERT(dp_ref_clk_cntl_src_sel_value == 0); + + /* Read the mmDENTIST_DISPCLK_CNTL to get the currently + * programmed DID DENTIST_DPREFCLK_WDIVIDER*/ + dispclk_cntl_value = dm_read_reg(dc->ctx, + mmDENTIST_DISPCLK_CNTL); + + /* Convert DENTIST_DPREFCLK_WDIVIDERto actual divider*/ + target_div = dal_divider_range_get_divider( + divider_ranges, + DIVIDER_RANGE_MAX, + get_reg_field_value(dispclk_cntl_value, + DENTIST_DISPCLK_CNTL, + DENTIST_DPREFCLK_WDIVIDER)); + + if (target_div != INVALID_DIVIDER) { + /* Calculate the current DFS clock, in kHz.*/ + dp_ref_clk_khz = (DIVIDER_RANGE_SCALE_FACTOR + * disp_clk->dentist_vco_freq_khz) / target_div; + } + + /* SW will adjust DP REF Clock average value for all purposes + * (DP DTO / DP Audio DTO and DP GTC) + if clock is spread for all cases: + -if SS enabled on DP Ref clock and HW de-spreading enabled with SW + calculations for DS_INCR/DS_MODULO (this is planned to be default case) + -if SS enabled on DP Ref clock and HW de-spreading enabled with HW + calculations (not planned to be used, but average clock should still + be valid) + -if SS enabled on DP Ref clock and HW de-spreading disabled + (should not be case with CIK) then SW should program all rates + generated according to average value (case as with previous ASICs) + */ + if ((disp_clk->ss_on_gpu_pll) && (disp_clk->gpu_pll_ss_divider != 0)) { + struct fixed32_32 ss_percentage = dal_fixed32_32_div_int( + dal_fixed32_32_from_fraction( + disp_clk->gpu_pll_ss_percentage, + disp_clk->gpu_pll_ss_divider), 200); + struct fixed32_32 adj_dp_ref_clk_khz; + + ss_percentage = dal_fixed32_32_sub(dal_fixed32_32_one, + ss_percentage); + adj_dp_ref_clk_khz = + dal_fixed32_32_mul_int( + ss_percentage, + dp_ref_clk_khz); + dp_ref_clk_khz = dal_fixed32_32_floor(adj_dp_ref_clk_khz); + } + + return dp_ref_clk_khz; +} + +static void destroy(struct display_clock **base) +{ + struct display_clock_dce110 *dc110; + + dc110 = DCLCK110_FROM_BASE(*base); + + dm_free(dc110); + + *base = NULL; +} + +static uint32_t get_validation_clock(struct display_clock *dc) +{ + uint32_t clk = 0; + struct display_clock_dce110 *disp_clk = DCLCK110_FROM_BASE(dc); + + switch (disp_clk->max_clks_state) { + case CLOCKS_STATE_ULTRA_LOW: + /*Currently not supported, it has 0 in table entry*/ + case CLOCKS_STATE_LOW: + clk = max_clks_by_state[CLOCKS_STATE_LOW]. + display_clk_khz; + break; + + case CLOCKS_STATE_NOMINAL: + clk = max_clks_by_state[CLOCKS_STATE_NOMINAL]. + display_clk_khz; + break; + + case CLOCKS_STATE_PERFORMANCE: + clk = max_clks_by_state[CLOCKS_STATE_PERFORMANCE]. + display_clk_khz; + break; + + case CLOCKS_STATE_INVALID: + default: + /*Invalid Clocks State*/ + dm_logger_write(dc->ctx->logger, LOG_WARNING, + "Invalid clock state"); + /* just return the display engine clock for + * lowest supported state*/ + clk = max_clks_by_state[CLOCKS_STATE_LOW]. + display_clk_khz; + break; + } + return clk; +} + +static struct fixed32_32 get_deep_color_factor(struct min_clock_params *params) +{ + /* DeepColorFactor = IF (HDMI = True, bpp / 24, 1)*/ + struct fixed32_32 deep_color_factor = dal_fixed32_32_from_int(1); + + if (params->signal_type != SIGNAL_TYPE_HDMI_TYPE_A) + return deep_color_factor; + + switch (params->deep_color_depth) { + case COLOR_DEPTH_101010: + /*deep color ratio for 30bpp is 30/24 = 1.25*/ + deep_color_factor = dal_fixed32_32_from_fraction(30, 24); + break; + + case COLOR_DEPTH_121212: + /* deep color ratio for 36bpp is 36/24 = 1.5*/ + deep_color_factor = dal_fixed32_32_from_fraction(36, 24); + break; + + case COLOR_DEPTH_161616: + /* deep color ratio for 48bpp is 48/24 = 2.0 */ + deep_color_factor = dal_fixed32_32_from_fraction(48, 24); + break; + default: + break; + } + return deep_color_factor; +} + +static struct fixed32_32 get_scaler_efficiency( + struct dc_context *ctx, + struct min_clock_params *params) +{ + struct fixed32_32 scaler_efficiency = dal_fixed32_32_from_int(3); + + if (params->scaler_efficiency == V_SCALER_EFFICIENCY_LB18BPP) { + scaler_efficiency = + dal_fixed32_32_add( + dal_fixed32_32_from_fraction(35555, 10000), + dal_fixed32_32_from_fraction( + 55556, + 100000 * 10000)); + } else if (params->scaler_efficiency == V_SCALER_EFFICIENCY_LB24BPP) { + scaler_efficiency = + dal_fixed32_32_add( + dal_fixed32_32_from_fraction(34285, 10000), + dal_fixed32_32_from_fraction( + 71429, + 100000 * 10000)); + } else if (params->scaler_efficiency == V_SCALER_EFFICIENCY_LB30BPP) + scaler_efficiency = dal_fixed32_32_from_fraction(32, 10); + + return scaler_efficiency; +} + +static struct fixed32_32 get_lb_lines_in_per_line_out( + struct min_clock_params *params, + struct fixed32_32 v_scale_ratio) +{ + struct fixed32_32 two = dal_fixed32_32_from_int(2); + struct fixed32_32 four = dal_fixed32_32_from_int(4); + struct fixed32_32 f4_to_3 = dal_fixed32_32_from_fraction(4, 3); + struct fixed32_32 f6_to_4 = dal_fixed32_32_from_fraction(6, 4); + + if (params->line_buffer_prefetch_enabled) + return dal_fixed32_32_max(v_scale_ratio, dal_fixed32_32_one); + else if (dal_fixed32_32_le(v_scale_ratio, dal_fixed32_32_one)) + return dal_fixed32_32_one; + else if (dal_fixed32_32_le(v_scale_ratio, f4_to_3)) + return f4_to_3; + else if (dal_fixed32_32_le(v_scale_ratio, f6_to_4)) + return f6_to_4; + else if (dal_fixed32_32_le(v_scale_ratio, two)) + return two; + else if (dal_fixed32_32_le(v_scale_ratio, dal_fixed32_32_from_int(3))) + return four; + else + return dal_fixed32_32_zero; +} + +static uint32_t get_actual_required_display_clk( + struct display_clock_dce110 *disp_clk, + uint32_t target_clk_khz) +{ + uint32_t disp_clk_khz = target_clk_khz; + uint32_t div = INVALID_DIVIDER; + uint32_t did = INVALID_DID; + uint32_t scaled_vco = + disp_clk->dentist_vco_freq_khz * DIVIDER_RANGE_SCALE_FACTOR; + + ASSERT_CRITICAL(!!disp_clk_khz); + + if (disp_clk_khz) + div = scaled_vco / disp_clk_khz; + + did = dal_divider_range_get_did(divider_ranges, DIVIDER_RANGE_MAX, div); + + if (did != INVALID_DID) { + div = dal_divider_range_get_divider( + divider_ranges, DIVIDER_RANGE_MAX, did); + + if ((div != INVALID_DIVIDER) && + (did > DIVIDER_RANGE_01_BASE_DIVIDER_ID)) + if (disp_clk_khz > (scaled_vco / div)) + div = dal_divider_range_get_divider( + divider_ranges, DIVIDER_RANGE_MAX, + did - 1); + + if (div != INVALID_DIVIDER) + disp_clk_khz = scaled_vco / div; + + } + /* We need to add 10KHz to this value because the accuracy in VBIOS is + in 10KHz units. So we need to always round the last digit up in order + to reach the next div level.*/ + return disp_clk_khz + 10; +} + +static uint32_t calc_single_display_min_clks( + struct display_clock *base, + struct min_clock_params *params, + bool set_clk) +{ + struct fixed32_32 h_scale_ratio = dal_fixed32_32_one; + struct fixed32_32 v_scale_ratio = dal_fixed32_32_one; + uint32_t pix_clk_khz = 0; + uint32_t lb_source_width = 0; + struct fixed32_32 deep_color_factor; + struct fixed32_32 scaler_efficiency; + struct fixed32_32 v_filter_init; + uint32_t v_filter_init_trunc; + uint32_t num_lines_at_frame_start = 3; + struct fixed32_32 v_filter_init_ceil; + struct fixed32_32 lines_per_lines_out_at_frame_start; + struct fixed32_32 lb_lines_in_per_line_out; /* in middle of the frame*/ + uint32_t src_wdth_rnd_to_chunks; + struct fixed32_32 scaling_coeff; + struct fixed32_32 h_blank_granularity_factor = + dal_fixed32_32_one; + struct fixed32_32 fx_disp_clk_mhz; + struct fixed32_32 line_time; + struct fixed32_32 disp_pipe_pix_throughput; + struct fixed32_32 fx_alt_disp_clk_mhz; + uint32_t disp_clk_khz; + uint32_t alt_disp_clk_khz; + struct display_clock_dce110 *disp_clk_110 = DCLCK110_FROM_BASE(base); + uint32_t max_clk_khz = get_validation_clock(base); + bool panning_allowed = false; /* TODO: receive this value from AS */ + + if (params == NULL) { + dm_logger_write(base->ctx->logger, LOG_WARNING, + "Invalid input parameter in %s", + __func__); + return 0; + } + + deep_color_factor = get_deep_color_factor(params); + scaler_efficiency = get_scaler_efficiency(base->ctx, params); + pix_clk_khz = params->requested_pixel_clock; + lb_source_width = params->source_view.width; + + if (0 != params->dest_view.height && 0 != params->dest_view.width) { + + h_scale_ratio = dal_fixed32_32_from_fraction( + params->source_view.width, + params->dest_view.width); + v_scale_ratio = dal_fixed32_32_from_fraction( + params->source_view.height, + params->dest_view.height); + } else { + dm_logger_write(base->ctx->logger, LOG_WARNING, + "Destination height or width is 0!\n"); + } + + v_filter_init = + dal_fixed32_32_add( + v_scale_ratio, + dal_fixed32_32_add_int( + dal_fixed32_32_div_int( + dal_fixed32_32_mul_int( + v_scale_ratio, + params->timing_info.INTERLACED), + 2), + params->scaling_info.v_taps + 1)); + v_filter_init = dal_fixed32_32_div_int(v_filter_init, 2); + + v_filter_init_trunc = dal_fixed32_32_floor(v_filter_init); + + v_filter_init_ceil = dal_fixed32_32_from_fraction( + v_filter_init_trunc, 2); + v_filter_init_ceil = dal_fixed32_32_from_int( + dal_fixed32_32_ceil(v_filter_init_ceil)); + v_filter_init_ceil = dal_fixed32_32_mul_int(v_filter_init_ceil, 2); + + lines_per_lines_out_at_frame_start = + dal_fixed32_32_div_int(v_filter_init_ceil, + num_lines_at_frame_start); + lb_lines_in_per_line_out = + get_lb_lines_in_per_line_out(params, v_scale_ratio); + + if (panning_allowed) + src_wdth_rnd_to_chunks = + ((lb_source_width - 1) / 128) * 128 + 256; + else + src_wdth_rnd_to_chunks = + ((lb_source_width + 127) / 128) * 128; + + scaling_coeff = + dal_fixed32_32_div( + dal_fixed32_32_from_int(params->scaling_info.v_taps), + scaler_efficiency); + + if (dal_fixed32_32_le(h_scale_ratio, dal_fixed32_32_one)) + scaling_coeff = dal_fixed32_32_max( + dal_fixed32_32_from_int( + dal_fixed32_32_ceil( + dal_fixed32_32_from_fraction( + params->scaling_info.h_taps, + 4))), + dal_fixed32_32_max( + dal_fixed32_32_mul( + scaling_coeff, + h_scale_ratio), + dal_fixed32_32_one)); + + if (!params->line_buffer_prefetch_enabled && + dal_fixed32_32_floor(lb_lines_in_per_line_out) != 2 && + dal_fixed32_32_floor(lb_lines_in_per_line_out) != 4) { + uint32_t line_total_pixel = + params->timing_info.h_total + lb_source_width - 256; + h_blank_granularity_factor = dal_fixed32_32_div( + dal_fixed32_32_from_int(params->timing_info.h_total), + dal_fixed32_32_div( + dal_fixed32_32_from_fraction( + line_total_pixel, 2), + h_scale_ratio)); + } + + /* Calculate display clock with ramping. Ramping factor is 1.1*/ + fx_disp_clk_mhz = + dal_fixed32_32_div_int( + dal_fixed32_32_mul_int(scaling_coeff, 11), + 10); + line_time = dal_fixed32_32_from_fraction( + params->timing_info.h_total * 1000, pix_clk_khz); + + disp_pipe_pix_throughput = dal_fixed32_32_mul( + lb_lines_in_per_line_out, h_blank_granularity_factor); + disp_pipe_pix_throughput = dal_fixed32_32_max( + disp_pipe_pix_throughput, + lines_per_lines_out_at_frame_start); + disp_pipe_pix_throughput = dal_fixed32_32_div(dal_fixed32_32_mul_int( + disp_pipe_pix_throughput, src_wdth_rnd_to_chunks), + line_time); + + if (0 != params->timing_info.h_total) { + fx_disp_clk_mhz = + dal_fixed32_32_max( + dal_fixed32_32_div_int( + dal_fixed32_32_mul_int( + scaling_coeff, pix_clk_khz), + 1000), + disp_pipe_pix_throughput); + fx_disp_clk_mhz = + dal_fixed32_32_mul( + fx_disp_clk_mhz, + dal_fixed32_32_from_fraction(11, 10)); + } + + fx_disp_clk_mhz = dal_fixed32_32_max(fx_disp_clk_mhz, + dal_fixed32_32_mul(deep_color_factor, + dal_fixed32_32_from_fraction(11, 10))); + + /* Calculate display clock without ramping */ + fx_alt_disp_clk_mhz = scaling_coeff; + + if (0 != params->timing_info.h_total) { + fx_alt_disp_clk_mhz = dal_fixed32_32_max( + dal_fixed32_32_div_int(dal_fixed32_32_mul_int( + scaling_coeff, pix_clk_khz), + 1000), + dal_fixed32_32_div_int(dal_fixed32_32_mul_int( + disp_pipe_pix_throughput, 105), + 100)); + } + + if (set_clk && disp_clk_110->ss_on_gpu_pll && + disp_clk_110->gpu_pll_ss_divider) + fx_alt_disp_clk_mhz = dal_fixed32_32_mul(fx_alt_disp_clk_mhz, + dal_fixed32_32_add_int( + dal_fixed32_32_div_int( + dal_fixed32_32_div_int( + dal_fixed32_32_from_fraction( + disp_clk_110->gpu_pll_ss_percentage, + disp_clk_110->gpu_pll_ss_divider), 100), + 2), + 1)); + + /* convert to integer */ + disp_clk_khz = dal_fixed32_32_round( + dal_fixed32_32_mul_int(fx_disp_clk_mhz, 1000)); + alt_disp_clk_khz = dal_fixed32_32_round( + dal_fixed32_32_mul_int(fx_alt_disp_clk_mhz, 1000)); + + if ((disp_clk_khz > max_clk_khz) && (alt_disp_clk_khz <= max_clk_khz)) + disp_clk_khz = alt_disp_clk_khz; + + if (set_clk) { /* only compensate clock if we are going to set it.*/ + disp_clk_khz = get_actual_required_display_clk( + disp_clk_110, disp_clk_khz); + } + + disp_clk_khz = disp_clk_khz > max_clk_khz ? max_clk_khz : disp_clk_khz; + + return disp_clk_khz; +} + +static uint32_t calculate_min_clock( + struct display_clock *base, + uint32_t path_num, + struct min_clock_params *params) +{ + uint32_t i; + uint32_t validation_clk_khz = + get_validation_clock(base); + uint32_t min_clk_khz = validation_clk_khz; + uint32_t max_clk_khz = 0; + struct display_clock_dce110 *dc = DCLCK110_FROM_BASE(base); + + if (dc->use_max_disp_clk) + return min_clk_khz; + + if (params != NULL) { + uint32_t disp_clk_khz = 0; + + for (i = 0; i < path_num; ++i) { + + disp_clk_khz = calc_single_display_min_clks( + base, params, true); + + /* update the max required clock found*/ + if (disp_clk_khz > max_clk_khz) + max_clk_khz = disp_clk_khz; + + params++; + } + } + + min_clk_khz = max_clk_khz; + + if (min_clk_khz > validation_clk_khz) + min_clk_khz = validation_clk_khz; + else if (min_clk_khz < base->min_display_clk_threshold_khz) + min_clk_khz = base->min_display_clk_threshold_khz; + + if (dc->use_max_disp_clk) + min_clk_khz = get_validation_clock(base); + + return min_clk_khz; +} + +static bool display_clock_integrated_info_construct( + struct display_clock_dce110 *disp_clk) +{ + struct dc_debug *debug = &disp_clk->disp_clk_base.ctx->dc->debug; + struct dc_bios *bp = disp_clk->disp_clk_base.ctx->dc_bios; + struct integrated_info info; + struct firmware_info fw_info; + uint32_t i; + struct display_clock *base = &disp_clk->disp_clk_base; + + memset(&info, 0, sizeof(struct integrated_info)); + memset(&fw_info, 0, sizeof(struct firmware_info)); + + if (bp->integrated_info) + info = *bp->integrated_info; + + disp_clk->dentist_vco_freq_khz = info.dentist_vco_freq; + if (disp_clk->dentist_vco_freq_khz == 0) { + bp->funcs->get_firmware_info(bp, &fw_info); + disp_clk->dentist_vco_freq_khz = + fw_info.smu_gpu_pll_output_freq; + if (disp_clk->dentist_vco_freq_khz == 0) + disp_clk->dentist_vco_freq_khz = 3600000; + } + + base->min_display_clk_threshold_khz = + disp_clk->dentist_vco_freq_khz / 64; + + if (bp->integrated_info == NULL) + return false; + + /*update the maximum display clock for each power state*/ + for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) { + enum clocks_state clk_state = CLOCKS_STATE_INVALID; + + switch (i) { + case 0: + clk_state = CLOCKS_STATE_ULTRA_LOW; + break; + + case 1: + clk_state = CLOCKS_STATE_LOW; + break; + + case 2: + clk_state = CLOCKS_STATE_NOMINAL; + break; + + case 3: + clk_state = CLOCKS_STATE_PERFORMANCE; + break; + + default: + clk_state = CLOCKS_STATE_INVALID; + break; + } + + /*Do not allow bad VBIOS/SBIOS to override with invalid values, + * check for > 100MHz*/ + if (info.disp_clk_voltage[i].max_supported_clk >= 100000) { + max_clks_by_state[clk_state].display_clk_khz = + info.disp_clk_voltage[i].max_supported_clk; + } + } + + disp_clk->dfs_bypass_enabled = false; + if (!debug->disable_dfs_bypass) + if (bp->integrated_info->gpu_cap_info & DFS_BYPASS_ENABLE) + disp_clk->dfs_bypass_enabled = true; + + disp_clk->use_max_disp_clk = debug->max_disp_clk; + + return true; +} + +static uint32_t get_clock(struct display_clock *dc) +{ + uint32_t disp_clock = get_validation_clock(dc); + uint32_t target_div = INVALID_DIVIDER; + uint32_t addr = mmDENTIST_DISPCLK_CNTL; + uint32_t value = 0; + uint32_t field = 0; + struct display_clock_dce110 *disp_clk = DCLCK110_FROM_BASE(dc); + + if (disp_clk->dfs_bypass_enabled && disp_clk->dfs_bypass_disp_clk) + return disp_clk->dfs_bypass_disp_clk; + + /* Read the mmDENTIST_DISPCLK_CNTL to get the currently programmed + DID DENTIST_DISPCLK_WDIVIDER.*/ + value = dm_read_reg(dc->ctx, addr); + field = get_reg_field_value( + value, DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER); + + /* Convert DENTIST_DISPCLK_WDIVIDER to actual divider*/ + target_div = dal_divider_range_get_divider( + divider_ranges, + DIVIDER_RANGE_MAX, + field); + + if (target_div != INVALID_DIVIDER) + /* Calculate the current DFS clock in KHz. + Should be okay up to 42.9 THz before overflowing.*/ + disp_clock = (DIVIDER_RANGE_SCALE_FACTOR + * disp_clk->dentist_vco_freq_khz) / target_div; + return disp_clock; +} + +static enum clocks_state get_required_clocks_state( + struct display_clock *dc, + struct state_dependent_clocks *req_clocks) +{ + int32_t i; + struct display_clock_dce110 *disp_clk = DCLCK110_FROM_BASE(dc); + enum clocks_state low_req_clk = disp_clk->max_clks_state; + + if (!req_clocks) { + /* NULL pointer*/ + dm_logger_write(dc->ctx->logger, LOG_WARNING, + "%s: Invalid parameter", + __func__); + return CLOCKS_STATE_INVALID; + } + + /* Iterate from highest supported to lowest valid state, and update + * lowest RequiredState with the lowest state that satisfies + * all required clocks + */ + for (i = disp_clk->max_clks_state; i >= CLOCKS_STATE_ULTRA_LOW; --i) { + if ((req_clocks->display_clk_khz <= + max_clks_by_state[i].display_clk_khz) && + (req_clocks->pixel_clk_khz <= + max_clks_by_state[i].pixel_clk_khz)) + low_req_clk = i; + } + return low_req_clk; +} + +static void psr_wait_loop(struct dc_context *ctx, unsigned int display_clk_khz) +{ + unsigned int dmcu_max_retry_on_wait_reg_ready = 801; + unsigned int dmcu_wait_reg_ready_interval = 100; + unsigned int regValue; + uint32_t masterCmd; + uint32_t masterComCntl; + union dce110_dmcu_psr_config_data_wait_loop_reg1 masterCmdData1; + + /* waitDMCUReadyForCmd */ + do { + dm_delay_in_microseconds(ctx, dmcu_wait_reg_ready_interval); + regValue = dm_read_reg(ctx, mmMASTER_COMM_CNTL_REG); + dmcu_max_retry_on_wait_reg_ready--; + } while + /* expected value is 0, loop while not 0*/ + ((MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK & regValue) && + dmcu_max_retry_on_wait_reg_ready > 0); + + masterCmdData1.u32All = 0; + masterCmdData1.bits.waitLoop = display_clk_khz / 1000 / 7; + dm_write_reg(ctx, mmMASTER_COMM_DATA_REG1, masterCmdData1.u32All); + + /* setDMCUParam_Cmd */ + masterCmd = dm_read_reg(ctx, mmMASTER_COMM_CMD_REG); + set_reg_field_value( + masterCmd, + PSR_SET_WAITLOOP, + MASTER_COMM_CMD_REG, + MASTER_COMM_CMD_REG_BYTE0); + + dm_write_reg(ctx, mmMASTER_COMM_CMD_REG, masterCmd); + + /* notifyDMCUMsg */ + masterComCntl = dm_read_reg(ctx, mmMASTER_COMM_CNTL_REG); + set_reg_field_value( + masterComCntl, + 1, + MASTER_COMM_CNTL_REG, + MASTER_COMM_INTERRUPT); + dm_write_reg(ctx, mmMASTER_COMM_CNTL_REG, masterComCntl); +} + +static void set_clock( + struct display_clock *base, + uint32_t requested_clk_khz) +{ + struct bp_pixel_clock_parameters pxl_clk_params; + struct display_clock_dce110 *dc = DCLCK110_FROM_BASE(base); + struct dc_bios *bp = base->ctx->dc_bios; + + /* Prepare to program display clock*/ + memset(&pxl_clk_params, 0, sizeof(pxl_clk_params)); + + /* Make sure requested clock isn't lower than minimum threshold*/ + if (requested_clk_khz > 0) + requested_clk_khz = dm_max(requested_clk_khz, + base->min_display_clk_threshold_khz); + + pxl_clk_params.target_pixel_clock = requested_clk_khz; + pxl_clk_params.pll_id = base->id; + + bp->funcs->program_display_engine_pll(bp, &pxl_clk_params); + + if (dc->dfs_bypass_enabled) { + + /* Cache the fixed display clock*/ + dc->dfs_bypass_disp_clk = + pxl_clk_params.dfs_bypass_display_clock; + } + + /* from power down, we need mark the clock state as ClocksStateNominal + * from HWReset, so when resume we will call pplib voltage regulator.*/ + if (requested_clk_khz == 0) + base->cur_min_clks_state = CLOCKS_STATE_NOMINAL; + + psr_wait_loop(base->ctx, requested_clk_khz); +} + +static void set_clock_state( + struct display_clock *dc, + struct display_clock_state clk_state) +{ + struct display_clock_dce110 *disp_clk = DCLCK110_FROM_BASE(dc); + + disp_clk->clock_state = clk_state; +} + +static struct display_clock_state get_clock_state( + struct display_clock *dc) +{ + struct display_clock_dce110 *disp_clk = DCLCK110_FROM_BASE(dc); + + return disp_clk->clock_state; +} + +static uint32_t get_dfs_bypass_threshold(struct display_clock *dc) +{ + return DCE110_DFS_BYPASS_THRESHOLD_KHZ; +} + +static const struct display_clock_funcs funcs = { + .destroy = destroy, + .calculate_min_clock = calculate_min_clock, + .get_clock = get_clock, + .get_clock_state = get_clock_state, + .get_dfs_bypass_threshold = get_dfs_bypass_threshold, + .get_dp_ref_clk_frequency = get_dp_ref_clk_frequency, + .get_min_clocks_state = get_min_clocks_state, + .get_required_clocks_state = get_required_clocks_state, + .get_validation_clock = get_validation_clock, + .set_clock = set_clock, + .set_clock_state = set_clock_state, + .set_dp_ref_clock_source = NULL, + .set_min_clocks_state = set_min_clocks_state, + .store_max_clocks_state = store_max_clocks_state, + .validate = NULL, +}; + +static bool dal_display_clock_dce110_construct( + struct display_clock_dce110 *dc110, + struct dc_context *ctx) +{ + struct display_clock *dc_base = &dc110->disp_clk_base; + struct dc_bios *bp = ctx->dc_bios; + + if (!dal_display_clock_construct_base(dc_base, ctx)) + return false; + + dc_base->funcs = &funcs; + + dc110->dfs_bypass_disp_clk = 0; + + if (!display_clock_integrated_info_construct(dc110)) + dm_logger_write(dc_base->ctx->logger, LOG_WARNING, + "Cannot obtain VBIOS integrated info\n"); + + dc110->gpu_pll_ss_percentage = 0; + dc110->gpu_pll_ss_divider = 1000; + dc110->ss_on_gpu_pll = false; + + dc_base->id = CLOCK_SOURCE_ID_DFS; +/* Initially set max clocks state to nominal. This should be updated by + * via a pplib call to DAL IRI eventually calling a + * DisplayEngineClock_Dce110::StoreMaxClocksState(). This call will come in + * on PPLIB init. This is from DCE5x. in case HW wants to use mixed method.*/ + dc110->max_clks_state = CLOCKS_STATE_NOMINAL; + + dal_divider_range_construct( + ÷r_ranges[DIVIDER_RANGE_01], + DIVIDER_RANGE_01_START, + DIVIDER_RANGE_01_STEP_SIZE, + DIVIDER_RANGE_01_BASE_DIVIDER_ID, + DIVIDER_RANGE_02_BASE_DIVIDER_ID); + dal_divider_range_construct( + ÷r_ranges[DIVIDER_RANGE_02], + DIVIDER_RANGE_02_START, + DIVIDER_RANGE_02_STEP_SIZE, + DIVIDER_RANGE_02_BASE_DIVIDER_ID, + DIVIDER_RANGE_03_BASE_DIVIDER_ID); + dal_divider_range_construct( + ÷r_ranges[DIVIDER_RANGE_03], + DIVIDER_RANGE_03_START, + DIVIDER_RANGE_03_STEP_SIZE, + DIVIDER_RANGE_03_BASE_DIVIDER_ID, + DIVIDER_RANGE_MAX_DIVIDER_ID); + + { + uint32_t ss_info_num = + bp->funcs->get_ss_entry_number(bp, + AS_SIGNAL_TYPE_GPU_PLL); + + if (ss_info_num) { + struct spread_spectrum_info info; + enum bp_result result; + + memset(&info, 0, sizeof(info)); + + result = bp->funcs->get_spread_spectrum_info(bp, + AS_SIGNAL_TYPE_GPU_PLL, + 0, + &info); + + /* Based on VBIOS, VBIOS will keep entry for GPU PLL SS + * even if SS not enabled and in that case + * SSInfo.spreadSpectrumPercentage !=0 would be sign + * that SS is enabled + */ + if (result == BP_RESULT_OK && + info.spread_spectrum_percentage != 0) { + dc110->ss_on_gpu_pll = true; + dc110->gpu_pll_ss_divider = + info.spread_percentage_divider; + + if (info.type.CENTER_MODE == 0) { + /* Currently for DP Reference clock we + * need only SS percentage for + * downspread */ + dc110->gpu_pll_ss_percentage = + info.spread_spectrum_percentage; + } + } + + } + } + + return true; +} + +/***************************************************************************** + * public functions + *****************************************************************************/ + +struct display_clock *dal_display_clock_dce110_create( + struct dc_context *ctx) +{ + struct display_clock_dce110 *dc110; + + dc110 = dm_alloc(sizeof(struct display_clock_dce110)); + + if (dc110 == NULL) + return NULL; + + if (dal_display_clock_dce110_construct(dc110, ctx)) + return &dc110->disp_clk_base; + + dm_free(dc110); + + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.h b/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.h new file mode 100644 index 000000000000..0cdc7b52a09f --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.h @@ -0,0 +1,53 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef __DAL_DISPLAY_CLOCK_DCE110_H__ +#define __DAL_DISPLAY_CLOCK_DCE110_H__ + +#include "gpu/display_clock.h" + +struct display_clock_dce110 { + struct display_clock disp_clk_base; + /* Max display block clocks state*/ + enum clocks_state max_clks_state; + bool use_max_disp_clk; + uint32_t dentist_vco_freq_khz; + /* Cache the status of DFS-bypass feature*/ + bool dfs_bypass_enabled; + /* GPU PLL SS percentage (if down-spread enabled) */ + uint32_t gpu_pll_ss_percentage; + /* GPU PLL SS percentage Divider (100 or 1000) */ + uint32_t gpu_pll_ss_divider; + /* Flag for Enabled SS on GPU PLL */ + bool ss_on_gpu_pll; + /* Cache the display clock returned by VBIOS if DFS-bypass is enabled. + * This is basically "Crystal Frequency In KHz" (XTALIN) frequency */ + uint32_t dfs_bypass_disp_clk; + struct display_clock_state clock_state; +}; + +#define DCLCK110_FROM_BASE(dc_base) \ + container_of(dc_base, struct display_clock_dce110, disp_clk_base) + +#endif /* __DAL_DISPLAY_CLOCK_DCE110_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c new file mode 100644 index 000000000000..9b7c9755e316 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c @@ -0,0 +1,964 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "dce/dce_11_2_d.h" +#include "dce/dce_11_2_sh_mask.h" + +#include "include/bios_parser_interface.h" +#include "include/fixed32_32.h" +#include "include/logger_interface.h" + +#include "../divider_range.h" + +#include "display_clock_dce112.h" + +#define FROM_DISPLAY_CLOCK(base) \ + container_of(base, struct display_clock_dce112, disp_clk_base) + +static struct state_dependent_clocks max_clks_by_state[] = { +/*ClocksStateInvalid - should not be used*/ +{ .display_clk_khz = 0, .pixel_clk_khz = 0 }, +/*ClocksStateUltraLow - currently by HW design team not supposed to be used*/ +{ .display_clk_khz = 389189, .pixel_clk_khz = 346672 }, +/*ClocksStateLow*/ +{ .display_clk_khz = 459000, .pixel_clk_khz = 400000 }, +/*ClocksStateNominal*/ +{ .display_clk_khz = 667000, .pixel_clk_khz = 600000 }, +/*ClocksStatePerformance*/ +{ .display_clk_khz = 1132000, .pixel_clk_khz = 600000 } }; + +/* Ranges for divider identifiers (Divider ID or DID) + mmDENTIST_DISPCLK_CNTL.DENTIST_DISPCLK_WDIVIDER*/ +enum divider_id_register_setting { + DIVIDER_RANGE_01_BASE_DIVIDER_ID = 0X08, + DIVIDER_RANGE_02_BASE_DIVIDER_ID = 0X40, + DIVIDER_RANGE_03_BASE_DIVIDER_ID = 0X60, + DIVIDER_RANGE_MAX_DIVIDER_ID = 0X80 +}; + +/* Step size between each divider within a range. + Incrementing the DENTIST_DISPCLK_WDIVIDER by one + will increment the divider by this much.*/ +enum divider_range_step_size { + DIVIDER_RANGE_01_STEP_SIZE = 25, /* 0.25*/ + DIVIDER_RANGE_02_STEP_SIZE = 50, /* 0.50*/ + DIVIDER_RANGE_03_STEP_SIZE = 100 /* 1.00 */ +}; + +static struct divider_range divider_ranges[DIVIDER_RANGE_MAX]; + +#define dce112_DFS_BYPASS_THRESHOLD_KHZ 400000 +/***************************************************************************** + * static functions + *****************************************************************************/ + +/* + * store_max_clocks_state + * + * @brief + * Cache the clock state + * + * @param + * struct display_clock *base - [out] cach the state in this structure + * enum clocks_state max_clocks_state - [in] state to be stored + */ +void dispclk_dce112_store_max_clocks_state( + struct display_clock *base, + enum clocks_state max_clocks_state) +{ + struct display_clock_dce112 *dc = DCLCK112_FROM_BASE(base); + + switch (max_clocks_state) { + case CLOCKS_STATE_LOW: + case CLOCKS_STATE_NOMINAL: + case CLOCKS_STATE_PERFORMANCE: + case CLOCKS_STATE_ULTRA_LOW: + dc->max_clks_state = max_clocks_state; + break; + + case CLOCKS_STATE_INVALID: + default: + /*Invalid Clocks State!*/ + ASSERT_CRITICAL(false); + break; + } +} + +enum clocks_state dispclk_dce112_get_min_clocks_state( + struct display_clock *base) +{ + return base->cur_min_clks_state; +} + +bool dispclk_dce112_set_min_clocks_state( + struct display_clock *base, + enum clocks_state clocks_state) +{ + struct display_clock_dce112 *dc = DCLCK112_FROM_BASE(base); + struct dm_pp_power_level_change_request level_change_req = { + DM_PP_POWER_LEVEL_INVALID}; + + if (clocks_state > dc->max_clks_state) { + /*Requested state exceeds max supported state.*/ + dm_logger_write(base->ctx->logger, LOG_WARNING, + "Requested state exceeds max supported state"); + return false; + } else if (clocks_state == base->cur_min_clks_state) { + /*if we're trying to set the same state, we can just return + * since nothing needs to be done*/ + return true; + } + + switch (clocks_state) { + case CLOCKS_STATE_ULTRA_LOW: + level_change_req.power_level = DM_PP_POWER_LEVEL_ULTRA_LOW; + break; + case CLOCKS_STATE_LOW: + level_change_req.power_level = DM_PP_POWER_LEVEL_LOW; + break; + case CLOCKS_STATE_NOMINAL: + level_change_req.power_level = DM_PP_POWER_LEVEL_NOMINAL; + break; + case CLOCKS_STATE_PERFORMANCE: + level_change_req.power_level = DM_PP_POWER_LEVEL_PERFORMANCE; + break; + case CLOCKS_STATE_INVALID: + default: + dm_logger_write(base->ctx->logger, LOG_WARNING, + "Requested state invalid state"); + return false; + } + + /* get max clock state from PPLIB */ + if (dm_pp_apply_power_level_change_request( + base->ctx, &level_change_req)) + base->cur_min_clks_state = clocks_state; + + return true; +} + +static uint32_t get_dp_ref_clk_frequency(struct display_clock *dc) +{ + uint32_t dispclk_cntl_value; + uint32_t dp_ref_clk_cntl_value; + uint32_t dp_ref_clk_cntl_src_sel_value; + uint32_t dp_ref_clk_khz = 600000; + uint32_t target_div = INVALID_DIVIDER; + struct display_clock_dce112 *disp_clk = FROM_DISPLAY_CLOCK(dc); + + /* ASSERT DP Reference Clock source is from DFS*/ + dp_ref_clk_cntl_value = dm_read_reg(dc->ctx, + mmDPREFCLK_CNTL); + + dp_ref_clk_cntl_src_sel_value = + get_reg_field_value( + dp_ref_clk_cntl_value, + DPREFCLK_CNTL, DPREFCLK_SRC_SEL); + + ASSERT(dp_ref_clk_cntl_src_sel_value == 0); + + /* Read the mmDENTIST_DISPCLK_CNTL to get the currently + * programmed DID DENTIST_DPREFCLK_WDIVIDER*/ + dispclk_cntl_value = dm_read_reg(dc->ctx, + mmDENTIST_DISPCLK_CNTL); + + /* Convert DENTIST_DPREFCLK_WDIVIDERto actual divider*/ + target_div = dal_divider_range_get_divider( + divider_ranges, + DIVIDER_RANGE_MAX, + get_reg_field_value(dispclk_cntl_value, + DENTIST_DISPCLK_CNTL, + DENTIST_DPREFCLK_WDIVIDER)); + + if (target_div != INVALID_DIVIDER) { + /* Calculate the current DFS clock, in kHz.*/ + dp_ref_clk_khz = (DIVIDER_RANGE_SCALE_FACTOR + * disp_clk->dentist_vco_freq_khz) / target_div; + } + + /* SW will adjust DP REF Clock average value for all purposes + * (DP DTO / DP Audio DTO and DP GTC) + if clock is spread for all cases: + -if SS enabled on DP Ref clock and HW de-spreading enabled with SW + calculations for DS_INCR/DS_MODULO (this is planned to be default case) + -if SS enabled on DP Ref clock and HW de-spreading enabled with HW + calculations (not planned to be used, but average clock should still + be valid) + -if SS enabled on DP Ref clock and HW de-spreading disabled + (should not be case with CIK) then SW should program all rates + generated according to average value (case as with previous ASICs) + */ + if ((disp_clk->ss_on_gpu_pll) && (disp_clk->gpu_pll_ss_divider != 0)) { + struct fixed32_32 ss_percentage = dal_fixed32_32_div_int( + dal_fixed32_32_from_fraction( + disp_clk->gpu_pll_ss_percentage, + disp_clk->gpu_pll_ss_divider), 200); + struct fixed32_32 adj_dp_ref_clk_khz; + + ss_percentage = dal_fixed32_32_sub(dal_fixed32_32_one, + ss_percentage); + adj_dp_ref_clk_khz = + dal_fixed32_32_mul_int( + ss_percentage, + dp_ref_clk_khz); + dp_ref_clk_khz = dal_fixed32_32_floor(adj_dp_ref_clk_khz); + } + + return dp_ref_clk_khz; +} + +void dispclk_dce112_destroy(struct display_clock **base) +{ + struct display_clock_dce112 *dc112; + + dc112 = DCLCK112_FROM_BASE(*base); + + dm_free(dc112); + + *base = NULL; +} + +uint32_t dispclk_dce112_get_validation_clock(struct display_clock *dc) +{ + uint32_t clk = 0; + struct display_clock_dce112 *disp_clk = DCLCK112_FROM_BASE(dc); + + switch (disp_clk->max_clks_state) { + case CLOCKS_STATE_ULTRA_LOW: + clk = (disp_clk->max_clks_by_state + CLOCKS_STATE_ULTRA_LOW)-> + display_clk_khz; + + case CLOCKS_STATE_LOW: + clk = (disp_clk->max_clks_by_state + CLOCKS_STATE_LOW)-> + display_clk_khz; + break; + + case CLOCKS_STATE_NOMINAL: + clk = (disp_clk->max_clks_by_state + CLOCKS_STATE_NOMINAL)-> + display_clk_khz; + break; + + case CLOCKS_STATE_PERFORMANCE: + clk = (disp_clk->max_clks_by_state + CLOCKS_STATE_PERFORMANCE)-> + display_clk_khz; + break; + + case CLOCKS_STATE_INVALID: + default: + /*Invalid Clocks State*/ + dm_logger_write(dc->ctx->logger, LOG_WARNING, + "Invalid clock state"); + /* just return the display engine clock for + * lowest supported state*/ + clk = (disp_clk->max_clks_by_state + CLOCKS_STATE_LOW)-> + display_clk_khz; + break; + } + return clk; +} + +static struct fixed32_32 get_deep_color_factor(struct min_clock_params *params) +{ + /* DeepColorFactor = IF (HDMI = True, bpp / 24, 1)*/ + struct fixed32_32 deep_color_factor = dal_fixed32_32_from_int(1); + + if (params->signal_type != SIGNAL_TYPE_HDMI_TYPE_A) + return deep_color_factor; + + switch (params->deep_color_depth) { + case COLOR_DEPTH_101010: + /*deep color ratio for 30bpp is 30/24 = 1.25*/ + deep_color_factor = dal_fixed32_32_from_fraction(30, 24); + break; + + case COLOR_DEPTH_121212: + /* deep color ratio for 36bpp is 36/24 = 1.5*/ + deep_color_factor = dal_fixed32_32_from_fraction(36, 24); + break; + + case COLOR_DEPTH_161616: + /* deep color ratio for 48bpp is 48/24 = 2.0 */ + deep_color_factor = dal_fixed32_32_from_fraction(48, 24); + break; + default: + break; + } + return deep_color_factor; +} + +static struct fixed32_32 get_scaler_efficiency( + struct dc_context *ctx, + struct min_clock_params *params) +{ + struct fixed32_32 scaler_efficiency = dal_fixed32_32_from_int(3); + + if (params->scaler_efficiency == V_SCALER_EFFICIENCY_LB18BPP) { + scaler_efficiency = + dal_fixed32_32_add( + dal_fixed32_32_from_fraction(35555, 10000), + dal_fixed32_32_from_fraction( + 55556, + 100000 * 10000)); + } else if (params->scaler_efficiency == V_SCALER_EFFICIENCY_LB24BPP) { + scaler_efficiency = + dal_fixed32_32_add( + dal_fixed32_32_from_fraction(34285, 10000), + dal_fixed32_32_from_fraction( + 71429, + 100000 * 10000)); + } else if (params->scaler_efficiency == V_SCALER_EFFICIENCY_LB30BPP) + scaler_efficiency = dal_fixed32_32_from_fraction(32, 10); + + return scaler_efficiency; +} + +static struct fixed32_32 get_lb_lines_in_per_line_out( + struct min_clock_params *params, + struct fixed32_32 v_scale_ratio) +{ + struct fixed32_32 two = dal_fixed32_32_from_int(2); + struct fixed32_32 four = dal_fixed32_32_from_int(4); + struct fixed32_32 f4_to_3 = dal_fixed32_32_from_fraction(4, 3); + struct fixed32_32 f6_to_4 = dal_fixed32_32_from_fraction(6, 4); + + if (params->line_buffer_prefetch_enabled) + return dal_fixed32_32_max(v_scale_ratio, dal_fixed32_32_one); + else if (dal_fixed32_32_le(v_scale_ratio, dal_fixed32_32_one)) + return dal_fixed32_32_one; + else if (dal_fixed32_32_le(v_scale_ratio, f4_to_3)) + return f4_to_3; + else if (dal_fixed32_32_le(v_scale_ratio, f6_to_4)) + return f6_to_4; + else if (dal_fixed32_32_le(v_scale_ratio, two)) + return two; + else if (dal_fixed32_32_le(v_scale_ratio, dal_fixed32_32_from_int(3))) + return four; + else + return dal_fixed32_32_zero; +} + +static uint32_t get_actual_required_display_clk( + struct display_clock_dce112 *disp_clk, + uint32_t target_clk_khz) +{ + uint32_t disp_clk_khz = target_clk_khz; + uint32_t div = INVALID_DIVIDER; + uint32_t did = INVALID_DID; + uint32_t scaled_vco = + disp_clk->dentist_vco_freq_khz * DIVIDER_RANGE_SCALE_FACTOR; + + ASSERT_CRITICAL(!!disp_clk_khz); + + if (disp_clk_khz) + div = scaled_vco / disp_clk_khz; + + did = dal_divider_range_get_did(divider_ranges, DIVIDER_RANGE_MAX, div); + + if (did != INVALID_DID) { + div = dal_divider_range_get_divider( + divider_ranges, DIVIDER_RANGE_MAX, did); + + if ((div != INVALID_DIVIDER) && + (did > DIVIDER_RANGE_01_BASE_DIVIDER_ID)) + if (disp_clk_khz > (scaled_vco / div)) + div = dal_divider_range_get_divider( + divider_ranges, DIVIDER_RANGE_MAX, + did - 1); + + if (div != INVALID_DIVIDER) + disp_clk_khz = scaled_vco / div; + + } + /* We need to add 10KHz to this value because the accuracy in VBIOS is + in 10KHz units. So we need to always round the last digit up in order + to reach the next div level.*/ + return disp_clk_khz + 10; +} + +static uint32_t calc_single_display_min_clks( + struct display_clock *base, + struct min_clock_params *params, + bool set_clk) +{ + struct fixed32_32 h_scale_ratio = dal_fixed32_32_one; + struct fixed32_32 v_scale_ratio = dal_fixed32_32_one; + uint32_t pix_clk_khz = 0; + uint32_t lb_source_width = 0; + struct fixed32_32 deep_color_factor; + struct fixed32_32 scaler_efficiency; + struct fixed32_32 v_filter_init; + uint32_t v_filter_init_trunc; + uint32_t num_lines_at_frame_start = 3; + struct fixed32_32 v_filter_init_ceil; + struct fixed32_32 lines_per_lines_out_at_frame_start; + struct fixed32_32 lb_lines_in_per_line_out; /* in middle of the frame*/ + uint32_t src_wdth_rnd_to_chunks; + struct fixed32_32 scaling_coeff; + struct fixed32_32 h_blank_granularity_factor = + dal_fixed32_32_one; + struct fixed32_32 fx_disp_clk_mhz; + struct fixed32_32 line_time; + struct fixed32_32 disp_pipe_pix_throughput; + struct fixed32_32 fx_alt_disp_clk_mhz; + uint32_t disp_clk_khz; + uint32_t alt_disp_clk_khz; + struct display_clock_dce112 *disp_clk_110 = DCLCK112_FROM_BASE(base); + uint32_t max_clk_khz = dispclk_dce112_get_validation_clock(base); + bool panning_allowed = false; /* TODO: receive this value from AS */ + + if (params == NULL) { + dm_logger_write(base->ctx->logger, LOG_WARNING, + "Invalid input parameter in %s", + __func__); + return 0; + } + + deep_color_factor = get_deep_color_factor(params); + scaler_efficiency = get_scaler_efficiency(base->ctx, params); + pix_clk_khz = params->requested_pixel_clock; + lb_source_width = params->source_view.width; + + if (0 != params->dest_view.height && 0 != params->dest_view.width) { + + h_scale_ratio = dal_fixed32_32_from_fraction( + params->source_view.width, + params->dest_view.width); + v_scale_ratio = dal_fixed32_32_from_fraction( + params->source_view.height, + params->dest_view.height); + } else { + dm_logger_write(base->ctx->logger, LOG_WARNING, + "Destination height or width is 0!\n"); + } + + v_filter_init = + dal_fixed32_32_add( + v_scale_ratio, + dal_fixed32_32_add_int( + dal_fixed32_32_div_int( + dal_fixed32_32_mul_int( + v_scale_ratio, + params->timing_info.INTERLACED), + 2), + params->scaling_info.v_taps + 1)); + v_filter_init = dal_fixed32_32_div_int(v_filter_init, 2); + + v_filter_init_trunc = dal_fixed32_32_floor(v_filter_init); + + v_filter_init_ceil = dal_fixed32_32_from_fraction( + v_filter_init_trunc, 2); + v_filter_init_ceil = dal_fixed32_32_from_int( + dal_fixed32_32_ceil(v_filter_init_ceil)); + v_filter_init_ceil = dal_fixed32_32_mul_int(v_filter_init_ceil, 2); + + lines_per_lines_out_at_frame_start = + dal_fixed32_32_div_int(v_filter_init_ceil, + num_lines_at_frame_start); + lb_lines_in_per_line_out = + get_lb_lines_in_per_line_out(params, v_scale_ratio); + + if (panning_allowed) + src_wdth_rnd_to_chunks = + ((lb_source_width - 1) / 128) * 128 + 256; + else + src_wdth_rnd_to_chunks = + ((lb_source_width + 127) / 128) * 128; + + scaling_coeff = + dal_fixed32_32_div( + dal_fixed32_32_from_int(params->scaling_info.v_taps), + scaler_efficiency); + + if (dal_fixed32_32_le(h_scale_ratio, dal_fixed32_32_one)) + scaling_coeff = dal_fixed32_32_max( + dal_fixed32_32_from_int( + dal_fixed32_32_ceil( + dal_fixed32_32_from_fraction( + params->scaling_info.h_taps, + 4))), + dal_fixed32_32_max( + dal_fixed32_32_mul( + scaling_coeff, + h_scale_ratio), + dal_fixed32_32_one)); + + if (!params->line_buffer_prefetch_enabled && + dal_fixed32_32_floor(lb_lines_in_per_line_out) != 2 && + dal_fixed32_32_floor(lb_lines_in_per_line_out) != 4) { + uint32_t line_total_pixel = + params->timing_info.h_total + lb_source_width - 256; + h_blank_granularity_factor = dal_fixed32_32_div( + dal_fixed32_32_from_int(params->timing_info.h_total), + dal_fixed32_32_div( + dal_fixed32_32_from_fraction( + line_total_pixel, 2), + h_scale_ratio)); + } + + /* Calculate display clock with ramping. Ramping factor is 1.1*/ + fx_disp_clk_mhz = + dal_fixed32_32_div_int( + dal_fixed32_32_mul_int(scaling_coeff, 11), + 10); + line_time = dal_fixed32_32_from_fraction( + params->timing_info.h_total * 1000, pix_clk_khz); + + disp_pipe_pix_throughput = dal_fixed32_32_mul( + lb_lines_in_per_line_out, h_blank_granularity_factor); + disp_pipe_pix_throughput = dal_fixed32_32_max( + disp_pipe_pix_throughput, + lines_per_lines_out_at_frame_start); + disp_pipe_pix_throughput = dal_fixed32_32_div(dal_fixed32_32_mul_int( + disp_pipe_pix_throughput, src_wdth_rnd_to_chunks), + line_time); + + if (0 != params->timing_info.h_total) { + fx_disp_clk_mhz = + dal_fixed32_32_max( + dal_fixed32_32_div_int( + dal_fixed32_32_mul_int( + scaling_coeff, pix_clk_khz), + 1000), + disp_pipe_pix_throughput); + fx_disp_clk_mhz = + dal_fixed32_32_mul( + fx_disp_clk_mhz, + dal_fixed32_32_from_fraction(11, 10)); + } + + fx_disp_clk_mhz = dal_fixed32_32_max(fx_disp_clk_mhz, + dal_fixed32_32_mul(deep_color_factor, + dal_fixed32_32_from_fraction(11, 10))); + + /* Calculate display clock without ramping */ + fx_alt_disp_clk_mhz = scaling_coeff; + + if (0 != params->timing_info.h_total) { + fx_alt_disp_clk_mhz = dal_fixed32_32_max( + dal_fixed32_32_div_int(dal_fixed32_32_mul_int( + scaling_coeff, pix_clk_khz), + 1000), + dal_fixed32_32_div_int(dal_fixed32_32_mul_int( + disp_pipe_pix_throughput, 105), + 100)); + } + + if (set_clk && disp_clk_110->ss_on_gpu_pll && + disp_clk_110->gpu_pll_ss_divider) + fx_alt_disp_clk_mhz = dal_fixed32_32_mul(fx_alt_disp_clk_mhz, + dal_fixed32_32_add_int( + dal_fixed32_32_div_int( + dal_fixed32_32_div_int( + dal_fixed32_32_from_fraction( + disp_clk_110->gpu_pll_ss_percentage, + disp_clk_110->gpu_pll_ss_divider), 100), + 2), + 1)); + + /* convert to integer */ + disp_clk_khz = dal_fixed32_32_round( + dal_fixed32_32_mul_int(fx_disp_clk_mhz, 1000)); + alt_disp_clk_khz = dal_fixed32_32_round( + dal_fixed32_32_mul_int(fx_alt_disp_clk_mhz, 1000)); + + if ((disp_clk_khz > max_clk_khz) && (alt_disp_clk_khz <= max_clk_khz)) + disp_clk_khz = alt_disp_clk_khz; + + if (set_clk) { /* only compensate clock if we are going to set it.*/ + disp_clk_khz = get_actual_required_display_clk( + disp_clk_110, disp_clk_khz); + } + + disp_clk_khz = disp_clk_khz > max_clk_khz ? max_clk_khz : disp_clk_khz; + + return disp_clk_khz; +} + +uint32_t dispclk_dce112_calculate_min_clock( + struct display_clock *base, + uint32_t path_num, + struct min_clock_params *params) +{ + uint32_t i; + uint32_t validation_clk_khz = + dispclk_dce112_get_validation_clock(base); + uint32_t min_clk_khz = validation_clk_khz; + uint32_t max_clk_khz = 0; + struct display_clock_dce112 *dc = DCLCK112_FROM_BASE(base); + + if (dc->use_max_disp_clk) + return min_clk_khz; + + if (params != NULL) { + uint32_t disp_clk_khz = 0; + + for (i = 0; i < path_num; ++i) { + + disp_clk_khz = calc_single_display_min_clks( + base, params, true); + + /* update the max required clock found*/ + if (disp_clk_khz > max_clk_khz) + max_clk_khz = disp_clk_khz; + + params++; + } + } + + min_clk_khz = max_clk_khz; + + if (min_clk_khz > validation_clk_khz) + min_clk_khz = validation_clk_khz; + else if (min_clk_khz < base->min_display_clk_threshold_khz) + min_clk_khz = base->min_display_clk_threshold_khz; + + if (dc->use_max_disp_clk) + min_clk_khz = dispclk_dce112_get_validation_clock(base); + + return min_clk_khz; +} + +static bool display_clock_integrated_info_construct( + struct display_clock_dce112 *disp_clk) +{ + struct integrated_info info; + uint32_t i; + struct display_clock *base = &disp_clk->disp_clk_base; + + memset(&info, 0, sizeof(struct integrated_info)); + + disp_clk->dentist_vco_freq_khz = info.dentist_vco_freq; + if (disp_clk->dentist_vco_freq_khz == 0) + disp_clk->dentist_vco_freq_khz = 3600000; + + disp_clk->crystal_freq_khz = 100000; + + base->min_display_clk_threshold_khz = + disp_clk->dentist_vco_freq_khz / 64; + + /*update the maximum display clock for each power state*/ + for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) { + enum clocks_state clk_state = CLOCKS_STATE_INVALID; + + switch (i) { + case 0: + clk_state = CLOCKS_STATE_ULTRA_LOW; + break; + + case 1: + clk_state = CLOCKS_STATE_LOW; + break; + + case 2: + clk_state = CLOCKS_STATE_NOMINAL; + break; + + case 3: + clk_state = CLOCKS_STATE_PERFORMANCE; + break; + + default: + clk_state = CLOCKS_STATE_INVALID; + break; + } + + /*Do not allow bad VBIOS/SBIOS to override with invalid values, + * check for > 100MHz*/ + if (info.disp_clk_voltage[i].max_supported_clk >= 100000) { + (disp_clk->max_clks_by_state + clk_state)-> + display_clk_khz = + info.disp_clk_voltage[i].max_supported_clk; + } + } + + return true; +} + +static uint32_t get_clock(struct display_clock *dc) +{ + uint32_t disp_clock = dispclk_dce112_get_validation_clock(dc); + uint32_t target_div = INVALID_DIVIDER; + uint32_t addr = mmDENTIST_DISPCLK_CNTL; + uint32_t value = 0; + uint32_t field = 0; + struct display_clock_dce112 *disp_clk = DCLCK112_FROM_BASE(dc); + + /* Read the mmDENTIST_DISPCLK_CNTL to get the currently programmed + DID DENTIST_DISPCLK_WDIVIDER.*/ + value = dm_read_reg(dc->ctx, addr); + field = get_reg_field_value( + value, DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER); + + /* Convert DENTIST_DISPCLK_WDIVIDER to actual divider*/ + target_div = dal_divider_range_get_divider( + divider_ranges, + DIVIDER_RANGE_MAX, + field); + + if (target_div != INVALID_DIVIDER) + /* Calculate the current DFS clock in KHz. + Should be okay up to 42.9 THz before overflowing.*/ + disp_clock = (DIVIDER_RANGE_SCALE_FACTOR + * disp_clk->dentist_vco_freq_khz) / target_div; + return disp_clock; +} + +enum clocks_state dispclk_dce112_get_required_clocks_state( + struct display_clock *dc, + struct state_dependent_clocks *req_clocks) +{ + int32_t i; + struct display_clock_dce112 *disp_clk = DCLCK112_FROM_BASE(dc); + enum clocks_state low_req_clk = disp_clk->max_clks_state; + + if (!req_clocks) { + /* NULL pointer*/ + dm_logger_write(dc->ctx->logger, LOG_WARNING, + "%s: Invalid parameter", + __func__); + return CLOCKS_STATE_INVALID; + } + + /* Iterate from highest supported to lowest valid state, and update + * lowest RequiredState with the lowest state that satisfies + * all required clocks + */ + for (i = disp_clk->max_clks_state; i >= CLOCKS_STATE_ULTRA_LOW; --i) { + if ((req_clocks->display_clk_khz <= + (disp_clk->max_clks_by_state + i)-> + display_clk_khz) && + (req_clocks->pixel_clk_khz <= + (disp_clk->max_clks_by_state + i)-> + pixel_clk_khz)) + low_req_clk = i; + } + return low_req_clk; +} + +void dispclk_dce112_set_clock( + struct display_clock *base, + uint32_t requested_clk_khz) +{ + struct bp_set_dce_clock_parameters dce_clk_params; + struct display_clock_dce112 *dc = DCLCK112_FROM_BASE(base); + struct dc_bios *bp = base->ctx->dc_bios; + + /* Prepare to program display clock*/ + memset(&dce_clk_params, 0, sizeof(dce_clk_params)); + + /* Make sure requested clock isn't lower than minimum threshold*/ + if (requested_clk_khz > 0) + requested_clk_khz = dm_max(requested_clk_khz, + base->min_display_clk_threshold_khz); + + dce_clk_params.target_clock_frequency = requested_clk_khz; + dce_clk_params.pll_id = dc->disp_clk_base.id; + dce_clk_params.clock_type = DCECLOCK_TYPE_DISPLAY_CLOCK; + + bp->funcs->set_dce_clock(bp, &dce_clk_params); + + /* from power down, we need mark the clock state as ClocksStateNominal + * from HWReset, so when resume we will call pplib voltage regulator.*/ + if (requested_clk_khz == 0) + base->cur_min_clks_state = CLOCKS_STATE_NOMINAL; + + /*Program DP ref Clock*/ + /*VBIOS will determine DPREFCLK frequency, so we don't set it*/ + dce_clk_params.target_clock_frequency = 0; + dce_clk_params.clock_type = DCECLOCK_TYPE_DPREFCLK; + dce_clk_params.flags.USE_GENLOCK_AS_SOURCE_FOR_DPREFCLK = + (dce_clk_params.pll_id == + CLOCK_SOURCE_COMBO_DISPLAY_PLL0); + + bp->funcs->set_dce_clock(bp, &dce_clk_params); +} + +void dispclk_dce112_set_clock_state( + struct display_clock *dc, + struct display_clock_state clk_state) +{ + struct display_clock_dce112 *disp_clk = DCLCK112_FROM_BASE(dc); + + disp_clk->clock_state = clk_state; +} + +struct display_clock_state dispclk_dce112_get_clock_state( + struct display_clock *dc) +{ + struct display_clock_dce112 *disp_clk = DCLCK112_FROM_BASE(dc); + + return disp_clk->clock_state; +} + +uint32_t dispclk_dce112_get_dfs_bypass_threshold( + struct display_clock *dc) +{ + return dce112_DFS_BYPASS_THRESHOLD_KHZ; +} + +static const struct display_clock_funcs funcs = { + .destroy = dispclk_dce112_destroy, + .calculate_min_clock = dispclk_dce112_calculate_min_clock, + .get_clock = get_clock, + .get_clock_state = dispclk_dce112_get_clock_state, + .get_dfs_bypass_threshold = dispclk_dce112_get_dfs_bypass_threshold, + .get_dp_ref_clk_frequency = get_dp_ref_clk_frequency, + .get_min_clocks_state = dispclk_dce112_get_min_clocks_state, + .get_required_clocks_state = dispclk_dce112_get_required_clocks_state, + .get_validation_clock = dispclk_dce112_get_validation_clock, + .set_clock = dispclk_dce112_set_clock, + .set_clock_state = dispclk_dce112_set_clock_state, + .set_dp_ref_clock_source = NULL, + .set_min_clocks_state = dispclk_dce112_set_min_clocks_state, + .store_max_clocks_state = dispclk_dce112_store_max_clocks_state, + .validate = NULL, +}; + +bool dal_display_clock_dce112_construct( + struct display_clock_dce112 *dc112, + struct dc_context *ctx) +{ + struct display_clock *dc_base = &dc112->disp_clk_base; + + /*if (NULL == as) + return false;*/ + + if (!dal_display_clock_construct_base(dc_base, ctx)) + return false; + + dc_base->funcs = &funcs; + + dc112->dfs_bypass_disp_clk = 0; + + if (!display_clock_integrated_info_construct(dc112)) + dm_logger_write(dc_base->ctx->logger, LOG_WARNING, + "Cannot obtain VBIOS integrated info\n"); + + dc112->gpu_pll_ss_percentage = 0; + dc112->gpu_pll_ss_divider = 1000; + dc112->ss_on_gpu_pll = false; + + dc_base->id = CLOCK_SOURCE_ID_DFS; +/* Initially set max clocks state to nominal. This should be updated by + * via a pplib call to DAL IRI eventually calling a + * DisplayEngineClock_dce112::StoreMaxClocksState(). This call will come in + * on PPLIB init. This is from DCE5x. in case HW wants to use mixed method.*/ + dc112->max_clks_state = CLOCKS_STATE_NOMINAL; + + dc112->disp_clk_base.min_display_clk_threshold_khz = + dc112->crystal_freq_khz; + + if (dc112->disp_clk_base.min_display_clk_threshold_khz < + (dc112->dentist_vco_freq_khz / 62)) + dc112->disp_clk_base.min_display_clk_threshold_khz = + (dc112->dentist_vco_freq_khz / 62); + + dal_divider_range_construct( + ÷r_ranges[DIVIDER_RANGE_01], + DIVIDER_RANGE_01_START, + DIVIDER_RANGE_01_STEP_SIZE, + DIVIDER_RANGE_01_BASE_DIVIDER_ID, + DIVIDER_RANGE_02_BASE_DIVIDER_ID); + dal_divider_range_construct( + ÷r_ranges[DIVIDER_RANGE_02], + DIVIDER_RANGE_02_START, + DIVIDER_RANGE_02_STEP_SIZE, + DIVIDER_RANGE_02_BASE_DIVIDER_ID, + DIVIDER_RANGE_03_BASE_DIVIDER_ID); + dal_divider_range_construct( + ÷r_ranges[DIVIDER_RANGE_03], + DIVIDER_RANGE_03_START, + DIVIDER_RANGE_03_STEP_SIZE, + DIVIDER_RANGE_03_BASE_DIVIDER_ID, + DIVIDER_RANGE_MAX_DIVIDER_ID); + + { + uint32_t ss_info_num = + ctx->dc_bios->funcs-> + get_ss_entry_number(ctx->dc_bios, AS_SIGNAL_TYPE_GPU_PLL); + + if (ss_info_num) { + struct spread_spectrum_info info; + bool result; + + memset(&info, 0, sizeof(info)); + + result = + (BP_RESULT_OK == ctx->dc_bios->funcs-> + get_spread_spectrum_info(ctx->dc_bios, + AS_SIGNAL_TYPE_GPU_PLL, 0, &info)) ? true : false; + + + /* Based on VBIOS, VBIOS will keep entry for GPU PLL SS + * even if SS not enabled and in that case + * SSInfo.spreadSpectrumPercentage !=0 would be sign + * that SS is enabled + */ + if (result && info.spread_spectrum_percentage != 0) { + dc112->ss_on_gpu_pll = true; + dc112->gpu_pll_ss_divider = + info.spread_percentage_divider; + + if (info.type.CENTER_MODE == 0) { + /* Currently for DP Reference clock we + * need only SS percentage for + * downspread */ + dc112->gpu_pll_ss_percentage = + info.spread_spectrum_percentage; + } + } + + } + } + + dc112->use_max_disp_clk = true; + dc112->max_clks_by_state = max_clks_by_state; + + return true; +} + +/***************************************************************************** + * public functions + *****************************************************************************/ + +struct display_clock *dal_display_clock_dce112_create( + struct dc_context *ctx) +{ + struct display_clock_dce112 *dc112; + + dc112 = dm_alloc(sizeof(struct display_clock_dce112)); + + if (dc112 == NULL) + return NULL; + + if (dal_display_clock_dce112_construct(dc112, ctx)) + return &dc112->disp_clk_base; + + dm_free(dc112); + + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h new file mode 100644 index 000000000000..937e17929b7c --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h @@ -0,0 +1,114 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef __DAL_DISPLAY_CLOCK_DCE112_H__ +#define __DAL_DISPLAY_CLOCK_DCE112_H__ + +#include "gpu/display_clock.h" + +struct display_clock_dce112 { + struct display_clock disp_clk_base; + /* Max display block clocks state*/ + enum clocks_state max_clks_state; + bool use_max_disp_clk; + uint32_t crystal_freq_khz; + uint32_t dentist_vco_freq_khz; + /* Cache the status of DFS-bypass feature*/ + bool dfs_bypass_enabled; + /* GPU PLL SS percentage (if down-spread enabled) */ + uint32_t gpu_pll_ss_percentage; + /* GPU PLL SS percentage Divider (100 or 1000) */ + uint32_t gpu_pll_ss_divider; + /* Flag for Enabled SS on GPU PLL */ + bool ss_on_gpu_pll; + /* Cache the display clock returned by VBIOS if DFS-bypass is enabled. + * This is basically "Crystal Frequency In KHz" (XTALIN) frequency */ + uint32_t dfs_bypass_disp_clk; + struct display_clock_state clock_state; + struct state_dependent_clocks *max_clks_by_state; + +}; + +#define DCLCK112_FROM_BASE(dc_base) \ + container_of(dc_base, struct display_clock_dce112, disp_clk_base) + +/* Array identifiers and count for the divider ranges.*/ +enum divider_range_count { + DIVIDER_RANGE_01 = 0, + DIVIDER_RANGE_02, + DIVIDER_RANGE_03, + DIVIDER_RANGE_MAX /* == 3*/ +}; + +/* Starting point for each divider range.*/ +enum divider_range_start { + DIVIDER_RANGE_01_START = 200, /* 2.00*/ + DIVIDER_RANGE_02_START = 1600, /* 16.00*/ + DIVIDER_RANGE_03_START = 3200, /* 32.00*/ + DIVIDER_RANGE_SCALE_FACTOR = 100 /* Results are scaled up by 100.*/ +}; + +bool dal_display_clock_dce112_construct( + struct display_clock_dce112 *dc112, + struct dc_context *ctx); + +void dispclk_dce112_destroy(struct display_clock **base); + +uint32_t dispclk_dce112_calculate_min_clock( + struct display_clock *base, + uint32_t path_num, + struct min_clock_params *params); + +struct display_clock_state dispclk_dce112_get_clock_state( + struct display_clock *dc); + +uint32_t dispclk_dce112_get_dfs_bypass_threshold( + struct display_clock *dc); + +enum clocks_state dispclk_dce112_get_min_clocks_state( + struct display_clock *base); + +enum clocks_state dispclk_dce112_get_required_clocks_state( + struct display_clock *dc, + struct state_dependent_clocks *req_clocks); + +uint32_t dispclk_dce112_get_validation_clock(struct display_clock *dc); + +void dispclk_dce112_set_clock( + struct display_clock *base, + uint32_t requested_clk_khz); + +void dispclk_dce112_set_clock_state( + struct display_clock *dc, + struct display_clock_state clk_state); + +bool dispclk_dce112_set_min_clocks_state( + struct display_clock *base, + enum clocks_state clocks_state); + +void dispclk_dce112_store_max_clocks_state( + struct display_clock *base, + enum clocks_state max_clocks_state); + +#endif /* __DAL_DISPLAY_CLOCK_DCE112_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c b/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c new file mode 100644 index 000000000000..eedcfd6232fc --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c @@ -0,0 +1,934 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "dce/dce_8_0_d.h" +#include "dce/dce_8_0_sh_mask.h" + +#include "include/bios_parser_interface.h" +#include "include/fixed32_32.h" +#include "include/logger_interface.h" + +#include "../divider_range.h" +#include "display_clock_dce80.h" +#include "dc.h" + +#define DCE80_DFS_BYPASS_THRESHOLD_KHZ 100000 + +/* Max clock values for each state indexed by "enum clocks_state": */ +static struct state_dependent_clocks max_clks_by_state[] = { +/* ClocksStateInvalid - should not be used */ +{ .display_clk_khz = 0, .pixel_clk_khz = 0 }, +/* ClocksStateUltraLow - not expected to be used for DCE 8.0 */ +{ .display_clk_khz = 0, .pixel_clk_khz = 0 }, +/* ClocksStateLow */ +{ .display_clk_khz = 352000, .pixel_clk_khz = 330000}, +/* ClocksStateNominal */ +{ .display_clk_khz = 600000, .pixel_clk_khz = 400000 }, +/* ClocksStatePerformance */ +{ .display_clk_khz = 600000, .pixel_clk_khz = 400000 } }; + +/* Starting point for each divider range.*/ +enum divider_range_start { + DIVIDER_RANGE_01_START = 200, /* 2.00*/ + DIVIDER_RANGE_02_START = 1600, /* 16.00*/ + DIVIDER_RANGE_03_START = 3200, /* 32.00*/ + DIVIDER_RANGE_SCALE_FACTOR = 100 /* Results are scaled up by 100.*/ +}; + +/* Ranges for divider identifiers (Divider ID or DID) + mmDENTIST_DISPCLK_CNTL.DENTIST_DISPCLK_WDIVIDER*/ +enum divider_id_register_setting { + DIVIDER_RANGE_01_BASE_DIVIDER_ID = 0X08, + DIVIDER_RANGE_02_BASE_DIVIDER_ID = 0X40, + DIVIDER_RANGE_03_BASE_DIVIDER_ID = 0X60, + DIVIDER_RANGE_MAX_DIVIDER_ID = 0X80 +}; + +/* Step size between each divider within a range. + Incrementing the DENTIST_DISPCLK_WDIVIDER by one + will increment the divider by this much.*/ +enum divider_range_step_size { + DIVIDER_RANGE_01_STEP_SIZE = 25, /* 0.25*/ + DIVIDER_RANGE_02_STEP_SIZE = 50, /* 0.50*/ + DIVIDER_RANGE_03_STEP_SIZE = 100 /* 1.00 */ +}; + +/* Array identifiers and count for the divider ranges.*/ +enum divider_range_count { + DIVIDER_RANGE_01 = 0, + DIVIDER_RANGE_02, + DIVIDER_RANGE_03, + DIVIDER_RANGE_MAX /* == 3*/ +}; + +static struct divider_range divider_ranges[DIVIDER_RANGE_MAX]; + +#define FROM_DISPLAY_CLOCK(base) \ + container_of(base, struct display_clock_dce80, disp_clk) + +static struct fixed32_32 get_deep_color_factor(struct min_clock_params *params) +{ + /* DeepColorFactor = IF (HDMI = True, bpp / 24, 1)*/ + struct fixed32_32 deep_color_factor = dal_fixed32_32_from_int(1); + + if (params->signal_type != SIGNAL_TYPE_HDMI_TYPE_A) + return deep_color_factor; + + switch (params->deep_color_depth) { + case COLOR_DEPTH_101010: + /*deep color ratio for 30bpp is 30/24 = 1.25*/ + deep_color_factor = dal_fixed32_32_from_fraction(30, 24); + break; + + case COLOR_DEPTH_121212: + /* deep color ratio for 36bpp is 36/24 = 1.5*/ + deep_color_factor = dal_fixed32_32_from_fraction(36, 24); + break; + + case COLOR_DEPTH_161616: + /* deep color ratio for 48bpp is 48/24 = 2.0 */ + deep_color_factor = dal_fixed32_32_from_fraction(48, 24); + break; + default: + break; + } + return deep_color_factor; +} + +static uint32_t get_scaler_efficiency(struct min_clock_params *params) +{ + uint32_t scaler_efficiency = 3; + + switch (params->scaler_efficiency) { + case V_SCALER_EFFICIENCY_LB18BPP: + case V_SCALER_EFFICIENCY_LB24BPP: + scaler_efficiency = 4; + break; + + case V_SCALER_EFFICIENCY_LB30BPP: + case V_SCALER_EFFICIENCY_LB36BPP: + scaler_efficiency = 3; + break; + + default: + break; + } + + return scaler_efficiency; +} + +static uint32_t get_actual_required_display_clk( + struct display_clock_dce80 *disp_clk, + uint32_t target_clk_khz) +{ + uint32_t disp_clk_khz = target_clk_khz; + uint32_t div = INVALID_DIVIDER; + uint32_t did = INVALID_DID; + uint32_t scaled_vco = + disp_clk->dentist_vco_freq_khz * DIVIDER_RANGE_SCALE_FACTOR; + + ASSERT(disp_clk_khz); + + if (disp_clk_khz) + div = scaled_vco / disp_clk_khz; + + did = dal_divider_range_get_did(divider_ranges, DIVIDER_RANGE_MAX, div); + + if (did != INVALID_DID) { + div = dal_divider_range_get_divider( + divider_ranges, DIVIDER_RANGE_MAX, did); + + if ((div != INVALID_DIVIDER) && + (did > DIVIDER_RANGE_01_BASE_DIVIDER_ID)) + if (disp_clk_khz > (scaled_vco / div)) + div = dal_divider_range_get_divider( + divider_ranges, DIVIDER_RANGE_MAX, + did - 1); + + if (div != INVALID_DIVIDER) + disp_clk_khz = scaled_vco / div; + + } + /* We need to add 10KHz to this value because the accuracy in VBIOS is + in 10KHz units. So we need to always round the last digit up in order + to reach the next div level.*/ + return disp_clk_khz + 10; +} + +static uint32_t get_validation_clock(struct display_clock *dc) +{ + uint32_t clk = 0; + struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc); + + switch (disp_clk->max_clks_state) { + case CLOCKS_STATE_ULTRA_LOW: + /*Currently not supported, it has 0 in table entry*/ + case CLOCKS_STATE_LOW: + clk = max_clks_by_state[CLOCKS_STATE_LOW]. + display_clk_khz; + break; + + case CLOCKS_STATE_NOMINAL: + clk = max_clks_by_state[CLOCKS_STATE_NOMINAL]. + display_clk_khz; + break; + + case CLOCKS_STATE_PERFORMANCE: + clk = max_clks_by_state[CLOCKS_STATE_PERFORMANCE]. + display_clk_khz; + break; + + case CLOCKS_STATE_INVALID: + default: + /*Invalid Clocks State*/ + BREAK_TO_DEBUGGER(); + /* just return the display engine clock for + * lowest supported state*/ + clk = max_clks_by_state[CLOCKS_STATE_LOW]. + display_clk_khz; + break; + } + return clk; +} + +static uint32_t calc_single_display_min_clks( + struct display_clock *base, + struct min_clock_params *params, + bool set_clk) +{ + struct fixed32_32 h_scale = dal_fixed32_32_from_int(1); + struct fixed32_32 v_scale = dal_fixed32_32_from_int(1); + uint32_t pix_clk_khz = params->requested_pixel_clock; + uint32_t line_total = params->timing_info.h_total; + uint32_t max_clk_khz = get_validation_clock(base); + struct fixed32_32 deep_color_factor = get_deep_color_factor(params); + uint32_t scaler_efficiency = get_scaler_efficiency(params); + struct fixed32_32 v_filter_init; + uint32_t v_filter_init_trunc; + struct fixed32_32 v_filter_init_ceil; + struct fixed32_32 src_lines_per_dst_line; + uint32_t src_wdth_rnd_to_chunks; + struct fixed32_32 scaling_coeff; + struct fixed32_32 fx_disp_clk_khz; + struct fixed32_32 fx_alt_disp_clk_khz; + uint32_t disp_clk_khz; + uint32_t alt_disp_clk_khz; + struct display_clock_dce80 *dc = FROM_DISPLAY_CLOCK(base); + + if (0 != params->dest_view.height && 0 != params->dest_view.width) { + + h_scale = dal_fixed32_32_from_fraction( + params->source_view.width, + params->dest_view.width); + v_scale = dal_fixed32_32_from_fraction( + params->source_view.height, + params->dest_view.height); + } + + v_filter_init = dal_fixed32_32_from_fraction( + params->scaling_info.v_taps, 2u); + v_filter_init = dal_fixed32_32_add(v_filter_init, + dal_fixed32_32_div_int(v_scale, 2)); + v_filter_init = dal_fixed32_32_add(v_filter_init, + dal_fixed32_32_from_fraction(15, 10)); + + v_filter_init_trunc = dal_fixed32_32_floor(v_filter_init); + + v_filter_init_ceil = dal_fixed32_32_from_fraction( + v_filter_init_trunc, 2); + v_filter_init_ceil = dal_fixed32_32_from_int( + dal_fixed32_32_ceil(v_filter_init_ceil)); + v_filter_init_ceil = dal_fixed32_32_mul_int(v_filter_init_ceil, 2); + v_filter_init_ceil = dal_fixed32_32_div_int(v_filter_init_ceil, 3); + v_filter_init_ceil = dal_fixed32_32_from_int( + dal_fixed32_32_ceil(v_filter_init_ceil)); + + src_lines_per_dst_line = dal_fixed32_32_max( + dal_fixed32_32_from_int(dal_fixed32_32_ceil(v_scale)), + v_filter_init_ceil); + + src_wdth_rnd_to_chunks = + ((params->source_view.width - 1) / 128) * 128 + 256; + + scaling_coeff = dal_fixed32_32_max( + dal_fixed32_32_from_fraction(params->scaling_info.h_taps, 4), + dal_fixed32_32_mul( + dal_fixed32_32_from_fraction( + params->scaling_info.v_taps, + scaler_efficiency), + h_scale)); + + scaling_coeff = dal_fixed32_32_max(scaling_coeff, h_scale); + + fx_disp_clk_khz = dal_fixed32_32_mul( + scaling_coeff, dal_fixed32_32_from_fraction(11, 10)); + if (0 != line_total) { + struct fixed32_32 d_clk = dal_fixed32_32_mul_int( + src_lines_per_dst_line, src_wdth_rnd_to_chunks); + d_clk = dal_fixed32_32_div_int(d_clk, line_total); + d_clk = dal_fixed32_32_mul(d_clk, + dal_fixed32_32_from_fraction(11, 10)); + fx_disp_clk_khz = dal_fixed32_32_max(fx_disp_clk_khz, d_clk); + } + + fx_disp_clk_khz = dal_fixed32_32_max(fx_disp_clk_khz, + dal_fixed32_32_mul(deep_color_factor, + dal_fixed32_32_from_fraction(11, 10))); + + fx_disp_clk_khz = dal_fixed32_32_mul_int(fx_disp_clk_khz, pix_clk_khz); + fx_disp_clk_khz = dal_fixed32_32_mul(fx_disp_clk_khz, + dal_fixed32_32_from_fraction(1005, 1000)); + + fx_alt_disp_clk_khz = scaling_coeff; + + if (0 != line_total) { + struct fixed32_32 d_clk = dal_fixed32_32_mul_int( + src_lines_per_dst_line, src_wdth_rnd_to_chunks); + d_clk = dal_fixed32_32_div_int(d_clk, line_total); + d_clk = dal_fixed32_32_mul(d_clk, + dal_fixed32_32_from_fraction(105, 100)); + fx_alt_disp_clk_khz = dal_fixed32_32_max( + fx_alt_disp_clk_khz, d_clk); + } + fx_alt_disp_clk_khz = dal_fixed32_32_max( + fx_alt_disp_clk_khz, fx_alt_disp_clk_khz); + + fx_alt_disp_clk_khz = dal_fixed32_32_mul_int( + fx_alt_disp_clk_khz, pix_clk_khz); + + /* convert to integer*/ + disp_clk_khz = dal_fixed32_32_floor(fx_disp_clk_khz); + alt_disp_clk_khz = dal_fixed32_32_floor(fx_alt_disp_clk_khz); + + if (set_clk) { /* only compensate clock if we are going to set it.*/ + disp_clk_khz = get_actual_required_display_clk( + dc, disp_clk_khz); + alt_disp_clk_khz = get_actual_required_display_clk( + dc, alt_disp_clk_khz); + } + + if ((disp_clk_khz > max_clk_khz) && (alt_disp_clk_khz <= max_clk_khz)) + disp_clk_khz = alt_disp_clk_khz; + + return disp_clk_khz; + +} + +static uint32_t calc_cursor_bw_for_min_clks(struct min_clock_params *params) +{ + + struct fixed32_32 v_scale = dal_fixed32_32_from_int(1); + struct fixed32_32 v_filter_ceiling; + struct fixed32_32 src_lines_per_dst_line; + struct fixed32_32 cursor_bw; + + /* DCE8 Mode Support and Mode Set Architecture Specification Rev 1.3 + 6.3.3 Cursor data Throughput requirement on DISPCLK + The MCIF to DCP cursor data return throughput is one pixel per DISPCLK + shared among the display heads. + If (Total Cursor Bandwidth in pixels for All heads> DISPCLK) + The mode is not supported + Cursor Bandwidth in Pixels = Cursor Width * + (SourceLinesPerDestinationLine / Line Time) + Assuming that Cursor Width = 128 + */ + /*In the hardware doc they mention an Interlace Factor + It is not used here because we have already used it when + calculating destination view*/ + if (0 != params->dest_view.height) + v_scale = dal_fixed32_32_from_fraction( + params->source_view.height, + params->dest_view.height); + + { + /*Do: Vertical Filter Init = 0.5 + VTAPS/2 + VSR/2 * Interlace Factor*/ + /*Interlace Factor is included in verticalScaleRatio*/ + struct fixed32_32 v_filter = dal_fixed32_32_add( + dal_fixed32_32_from_fraction(params->scaling_info.v_taps, 2), + dal_fixed32_32_div_int(v_scale, 2)); + /*Do : Ceiling (Vertical Filter Init, 2)/3 )*/ + v_filter_ceiling = dal_fixed32_32_div_int(v_filter, 2); + v_filter_ceiling = dal_fixed32_32_mul_int( + dal_fixed32_32_from_int(dal_fixed32_32_ceil(v_filter_ceiling)), + 2); + v_filter_ceiling = dal_fixed32_32_div_int(v_filter_ceiling, 3); + } + /*Do : MAX( CeilCeiling (VSR), Ceiling (Vertical Filter Init, 2)/3 )*/ + /*Do : SourceLinesPerDestinationLine = + * MAX( Ceiling (VSR), Ceiling (Vertical Filter Init, 2)/3 )*/ + src_lines_per_dst_line = dal_fixed32_32_max(v_scale, v_filter_ceiling); + + if ((params->requested_pixel_clock != 0) && + (params->timing_info.h_total != 0)) { + /* pixelClock is in units of KHz. Calc lineTime in us*/ + struct fixed32_32 inv_line_time = dal_fixed32_32_from_fraction( + params->requested_pixel_clock, + params->timing_info.h_total); + cursor_bw = dal_fixed32_32_mul( + dal_fixed32_32_mul_int(inv_line_time, 128), + src_lines_per_dst_line); + } + + /* convert to integer*/ + return dal_fixed32_32_floor(cursor_bw); +} + +static bool validate( + struct display_clock *dc, + struct min_clock_params *params) +{ + uint32_t max_clk_khz = get_validation_clock(dc); + uint32_t req_clk_khz; + + if (params == NULL) + return false; + + req_clk_khz = calc_single_display_min_clks(dc, params, false); + + return (req_clk_khz <= max_clk_khz); +} + +static uint32_t calculate_min_clock( + struct display_clock *dc, + uint32_t path_num, + struct min_clock_params *params) +{ + uint32_t i; + uint32_t validation_clk_khz = get_validation_clock(dc); + uint32_t min_clk_khz = validation_clk_khz; + uint32_t max_clk_khz = 0; + uint32_t total_cursor_bw = 0; + struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc); + + if (disp_clk->use_max_disp_clk) + return min_clk_khz; + + if (params != NULL) { + uint32_t disp_clk_khz = 0; + + for (i = 0; i < path_num; ++i) { + disp_clk_khz = calc_single_display_min_clks( + dc, params, true); + + /* update the max required clock found*/ + if (disp_clk_khz > max_clk_khz) + max_clk_khz = disp_clk_khz; + + disp_clk_khz = calc_cursor_bw_for_min_clks(params); + + total_cursor_bw += disp_clk_khz; + + params++; + + } + } + + max_clk_khz = (total_cursor_bw > max_clk_khz) ? total_cursor_bw : + max_clk_khz; + + min_clk_khz = max_clk_khz; + + /*"Cursor data Throughput requirement on DISPCLK is now a factor, + * need to change the code */ + ASSERT(total_cursor_bw < validation_clk_khz); + + if (min_clk_khz > validation_clk_khz) + min_clk_khz = validation_clk_khz; + else if (min_clk_khz < dc->min_display_clk_threshold_khz) + min_clk_khz = dc->min_display_clk_threshold_khz; + + return min_clk_khz; +} + +static void set_clock( + struct display_clock *dc, + uint32_t requested_clk_khz) +{ + struct bp_pixel_clock_parameters pxl_clk_params; + struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc); + struct dc_bios *bp = dc->ctx->dc_bios; + + /* Prepare to program display clock*/ + memset(&pxl_clk_params, 0, sizeof(pxl_clk_params)); + + pxl_clk_params.target_pixel_clock = requested_clk_khz; + pxl_clk_params.pll_id = dc->id; + + bp->funcs->program_display_engine_pll(bp, &pxl_clk_params); + + if (disp_clk->dfs_bypass_enabled) { + + /* Cache the fixed display clock*/ + disp_clk->dfs_bypass_disp_clk = + pxl_clk_params.dfs_bypass_display_clock; + } + + /* from power down, we need mark the clock state as ClocksStateNominal + * from HWReset, so when resume we will call pplib voltage regulator.*/ + if (requested_clk_khz == 0) + disp_clk->cur_min_clks_state = CLOCKS_STATE_NOMINAL; +} + +static uint32_t get_clock(struct display_clock *dc) +{ + uint32_t disp_clock = get_validation_clock(dc); + uint32_t target_div = INVALID_DIVIDER; + uint32_t addr = mmDENTIST_DISPCLK_CNTL; + uint32_t value = 0; + uint32_t field = 0; + struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc); + + if (disp_clk->dfs_bypass_enabled && disp_clk->dfs_bypass_disp_clk) + return disp_clk->dfs_bypass_disp_clk; + + /* Read the mmDENTIST_DISPCLK_CNTL to get the currently programmed + DID DENTIST_DISPCLK_WDIVIDER.*/ + value = dm_read_reg(dc->ctx, addr); + field = get_reg_field_value( + value, DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER); + + /* Convert DENTIST_DISPCLK_WDIVIDER to actual divider*/ + target_div = dal_divider_range_get_divider( + divider_ranges, + DIVIDER_RANGE_MAX, + field); + + if (target_div != INVALID_DIVIDER) + /* Calculate the current DFS clock in KHz. + Should be okay up to 42.9 THz before overflowing.*/ + disp_clock = (DIVIDER_RANGE_SCALE_FACTOR + * disp_clk->dentist_vco_freq_khz) / target_div; + return disp_clock; +} + +static void set_clock_state( + struct display_clock *dc, + struct display_clock_state clk_state) +{ + struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc); + + disp_clk->clock_state = clk_state; +} +static struct display_clock_state get_clock_state( + struct display_clock *dc) +{ + struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc); + + return disp_clk->clock_state; +} + +static enum clocks_state get_min_clocks_state(struct display_clock *dc) +{ + struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc); + + return disp_clk->cur_min_clks_state; +} + +static enum clocks_state get_required_clocks_state + (struct display_clock *dc, + struct state_dependent_clocks *req_clocks) +{ + int32_t i; + struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc); + enum clocks_state low_req_clk = disp_clk->max_clks_state; + + if (!req_clocks) { + /* NULL pointer*/ + BREAK_TO_DEBUGGER(); + return CLOCKS_STATE_INVALID; + } + + /* Iterate from highest supported to lowest valid state, and update + * lowest RequiredState with the lowest state that satisfies + * all required clocks + */ + for (i = disp_clk->max_clks_state; i >= CLOCKS_STATE_ULTRA_LOW; --i) { + if ((req_clocks->display_clk_khz <= + max_clks_by_state[i].display_clk_khz) && + (req_clocks->pixel_clk_khz <= + max_clks_by_state[i].pixel_clk_khz)) + low_req_clk = i; + } + return low_req_clk; +} + +static bool set_min_clocks_state( + struct display_clock *dc, + enum clocks_state clocks_state) +{ + struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc); + + struct dm_pp_power_level_change_request level_change_req = { + DM_PP_POWER_LEVEL_INVALID}; + + if (clocks_state > disp_clk->max_clks_state) { + /*Requested state exceeds max supported state.*/ + dm_logger_write(dc->ctx->logger, LOG_WARNING, + "Requested state exceeds max supported state"); + return false; + } else if (clocks_state == dc->cur_min_clks_state) { + /*if we're trying to set the same state, we can just return + * since nothing needs to be done*/ + return true; + } + + switch (clocks_state) { + case CLOCKS_STATE_ULTRA_LOW: + level_change_req.power_level = DM_PP_POWER_LEVEL_ULTRA_LOW; + break; + case CLOCKS_STATE_LOW: + level_change_req.power_level = DM_PP_POWER_LEVEL_LOW; + break; + case CLOCKS_STATE_NOMINAL: + level_change_req.power_level = DM_PP_POWER_LEVEL_NOMINAL; + break; + case CLOCKS_STATE_PERFORMANCE: + level_change_req.power_level = DM_PP_POWER_LEVEL_PERFORMANCE; + break; + case CLOCKS_STATE_INVALID: + default: + dm_logger_write(dc->ctx->logger, LOG_WARNING, + "Requested state invalid state"); + return false; + } + + /* get max clock state from PPLIB */ + if (dm_pp_apply_power_level_change_request(dc->ctx, &level_change_req)) + dc->cur_min_clks_state = clocks_state; + + return true; +} + +static uint32_t get_dp_ref_clk_frequency(struct display_clock *dc) +{ + uint32_t dispclk_cntl_value; + uint32_t dp_ref_clk_cntl_value; + uint32_t dp_ref_clk_cntl_src_sel_value; + uint32_t dp_ref_clk_khz = 600000; + uint32_t target_div = INVALID_DIVIDER; + struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc); + + /* ASSERT DP Reference Clock source is from DFS*/ + dp_ref_clk_cntl_value = dm_read_reg(dc->ctx, + mmDPREFCLK_CNTL); + + dp_ref_clk_cntl_src_sel_value = + get_reg_field_value( + dp_ref_clk_cntl_value, + DPREFCLK_CNTL, DPREFCLK_SRC_SEL); + + ASSERT(dp_ref_clk_cntl_src_sel_value == 0); + + /* Read the mmDENTIST_DISPCLK_CNTL to get the currently + * programmed DID DENTIST_DPREFCLK_WDIVIDER*/ + dispclk_cntl_value = dm_read_reg(dc->ctx, + mmDENTIST_DISPCLK_CNTL); + + /* Convert DENTIST_DPREFCLK_WDIVIDERto actual divider*/ + target_div = dal_divider_range_get_divider( + divider_ranges, + DIVIDER_RANGE_MAX, + get_reg_field_value(dispclk_cntl_value, + DENTIST_DISPCLK_CNTL, + DENTIST_DPREFCLK_WDIVIDER)); + + if (target_div != INVALID_DIVIDER) { + /* Calculate the current DFS clock, in kHz.*/ + dp_ref_clk_khz = (DIVIDER_RANGE_SCALE_FACTOR + * disp_clk->dentist_vco_freq_khz) / target_div; + } + + /* SW will adjust DP REF Clock average value for all purposes + * (DP DTO / DP Audio DTO and DP GTC) + if clock is spread for all cases: + -if SS enabled on DP Ref clock and HW de-spreading enabled with SW + calculations for DS_INCR/DS_MODULO (this is planned to be default case) + -if SS enabled on DP Ref clock and HW de-spreading enabled with HW + calculations (not planned to be used, but average clock should still + be valid) + -if SS enabled on DP Ref clock and HW de-spreading disabled + (should not be case with CIK) then SW should program all rates + generated according to average value (case as with previous ASICs) + */ + if ((disp_clk->ss_on_gpu_pll) && (disp_clk->gpu_pll_ss_divider != 0)) { + struct fixed32_32 ss_percentage = dal_fixed32_32_div_int( + dal_fixed32_32_from_fraction( + disp_clk->gpu_pll_ss_percentage, + disp_clk->gpu_pll_ss_divider), 200); + struct fixed32_32 adj_dp_ref_clk_khz; + + ss_percentage = dal_fixed32_32_sub(dal_fixed32_32_one, + ss_percentage); + adj_dp_ref_clk_khz = + dal_fixed32_32_mul_int( + ss_percentage, + dp_ref_clk_khz); + dp_ref_clk_khz = dal_fixed32_32_floor(adj_dp_ref_clk_khz); + } + + return dp_ref_clk_khz; +} + +static void store_max_clocks_state( + struct display_clock *dc, + enum clocks_state max_clocks_state) +{ + struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc); + + switch (max_clocks_state) { + case CLOCKS_STATE_LOW: + case CLOCKS_STATE_NOMINAL: + case CLOCKS_STATE_PERFORMANCE: + case CLOCKS_STATE_ULTRA_LOW: + disp_clk->max_clks_state = max_clocks_state; + break; + + case CLOCKS_STATE_INVALID: + default: + /*Invalid Clocks State!*/ + BREAK_TO_DEBUGGER(); + break; + } +} + +static void display_clock_ss_construct( + struct display_clock_dce80 *disp_clk) +{ + struct dc_bios *bp = disp_clk->disp_clk.ctx->dc_bios; + uint32_t ss_entry_num = bp->funcs->get_ss_entry_number(bp, + AS_SIGNAL_TYPE_GPU_PLL); + + /*Read SS Info from VBIOS SS Info table for DP Reference Clock spread.*/ + if (ss_entry_num > 0) {/* Should be only one entry */ + struct spread_spectrum_info ss_info; + enum bp_result res; + + memset(&ss_info, 0, sizeof(struct spread_spectrum_info)); + + res = bp->funcs->get_spread_spectrum_info(bp, + AS_SIGNAL_TYPE_GPU_PLL, 0, &ss_info); + + /* Based on VBIOS, VBIOS will keep entry for GPU PLL SS even if + * SS not enabled and in that case + * SSInfo.spreadSpectrumPercentage !=0 would be + * sign that SS is enabled*/ + if (res == BP_RESULT_OK && ss_info.spread_spectrum_percentage != 0) { + disp_clk->ss_on_gpu_pll = true; + disp_clk->gpu_pll_ss_divider = + ss_info.spread_percentage_divider; + if (ss_info.type.CENTER_MODE == 0) + /* Currently we need only SS + * percentage for down-spread*/ + disp_clk->gpu_pll_ss_percentage = + ss_info.spread_spectrum_percentage; + } + } +} + +static bool display_clock_integrated_info_construct( + struct display_clock_dce80 *disp_clk) +{ + struct dc_debug *debug = &disp_clk->disp_clk.ctx->dc->debug; + struct dc_bios *bp = disp_clk->disp_clk.ctx->dc_bios; + struct integrated_info info = { { { 0 } } }; + struct firmware_info fw_info = { { 0 } }; + uint32_t i; + + if (bp->integrated_info) + info = *bp->integrated_info; + + disp_clk->dentist_vco_freq_khz = info.dentist_vco_freq; + if (disp_clk->dentist_vco_freq_khz == 0) { + bp->funcs->get_firmware_info(bp, &fw_info); + disp_clk->dentist_vco_freq_khz = + fw_info.smu_gpu_pll_output_freq; + if (disp_clk->dentist_vco_freq_khz == 0) + disp_clk->dentist_vco_freq_khz = 3600000; + } + disp_clk->disp_clk.min_display_clk_threshold_khz = + disp_clk->dentist_vco_freq_khz / 64; + + /* TODO: initialise disp_clk->dfs_bypass_disp_clk */ + + /*update the maximum display clock for each power state*/ + for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) { + enum clocks_state clk_state = CLOCKS_STATE_INVALID; + + switch (i) { + case 0: + clk_state = CLOCKS_STATE_ULTRA_LOW; + break; + + case 1: + clk_state = CLOCKS_STATE_LOW; + break; + + case 2: + clk_state = CLOCKS_STATE_NOMINAL; + break; + + case 3: + clk_state = CLOCKS_STATE_PERFORMANCE; + break; + + default: + clk_state = CLOCKS_STATE_INVALID; + break; + } + + /*Do not allow bad VBIOS/SBIOS to override with invalid values, + * check for > 100MHz*/ + if (info.disp_clk_voltage[i].max_supported_clk >= 100000) { + max_clks_by_state[clk_state].display_clk_khz = + info.disp_clk_voltage[i].max_supported_clk; + } + } + + disp_clk->dfs_bypass_enabled = false; + if (!debug->disable_dfs_bypass) + if (bp->integrated_info->gpu_cap_info & DFS_BYPASS_ENABLE) + disp_clk->dfs_bypass_enabled = true; + + disp_clk->use_max_disp_clk = debug->max_disp_clk; + + return true; +} + +static uint32_t get_dfs_bypass_threshold(struct display_clock *dc) +{ + return DCE80_DFS_BYPASS_THRESHOLD_KHZ; +} + +static void destroy(struct display_clock **dc) +{ + struct display_clock_dce80 *disp_clk; + + disp_clk = FROM_DISPLAY_CLOCK(*dc); + dm_free(disp_clk); + *dc = NULL; +} + +static const struct display_clock_funcs funcs = { + .calculate_min_clock = calculate_min_clock, + .destroy = destroy, + .get_clock = get_clock, + .get_clock_state = get_clock_state, + .get_dfs_bypass_threshold = get_dfs_bypass_threshold, + .get_dp_ref_clk_frequency = get_dp_ref_clk_frequency, + .get_min_clocks_state = get_min_clocks_state, + .get_required_clocks_state = get_required_clocks_state, + .get_validation_clock = get_validation_clock, + .set_clock = set_clock, + .set_clock_state = set_clock_state, + .set_dp_ref_clock_source = + dal_display_clock_base_set_dp_ref_clock_source, + .set_min_clocks_state = set_min_clocks_state, + .store_max_clocks_state = store_max_clocks_state, + .validate = validate, +}; + +static bool display_clock_construct( + struct dc_context *ctx, + struct display_clock_dce80 *disp_clk) +{ + struct display_clock *dc_base = &disp_clk->disp_clk; + + if (!dal_display_clock_construct_base(dc_base, ctx)) + return false; + + dc_base->funcs = &funcs; + /* + * set_dp_ref_clock_source + * set_clock_state + * get_clock_state + * get_dfs_bypass_threshold + */ + + disp_clk->gpu_pll_ss_percentage = 0; + disp_clk->gpu_pll_ss_divider = 1000; + disp_clk->ss_on_gpu_pll = false; + disp_clk->dfs_bypass_enabled = false; + disp_clk->dfs_bypass_disp_clk = 0; + disp_clk->use_max_disp_clk = true;/* false will hang the system! */ + + disp_clk->disp_clk.id = CLOCK_SOURCE_ID_DFS; +/* Initially set max clocks state to nominal. This should be updated by + * via a pplib call to DAL IRI eventually calling a + * DisplayEngineClock_Dce50::StoreMaxClocksState(). This call will come in + * on PPLIB init. This is from DCE5x. in case HW wants to use mixed method.*/ + disp_clk->max_clks_state = CLOCKS_STATE_NOMINAL; +/* Initially set current min clocks state to invalid since we + * cannot make any assumption about PPLIB's initial state. This will be updated + * by HWSS via SetMinClocksState() on first mode set prior to programming + * state dependent clocks.*/ + disp_clk->cur_min_clks_state = CLOCKS_STATE_INVALID; + + display_clock_ss_construct(disp_clk); + + if (!display_clock_integrated_info_construct(disp_clk)) { + dm_logger_write(dc_base->ctx->logger, LOG_WARNING, + "Cannot obtain VBIOS integrated info"); + } + + dal_divider_range_construct( + ÷r_ranges[DIVIDER_RANGE_01], + DIVIDER_RANGE_01_START, + DIVIDER_RANGE_01_STEP_SIZE, + DIVIDER_RANGE_01_BASE_DIVIDER_ID, + DIVIDER_RANGE_02_BASE_DIVIDER_ID); + dal_divider_range_construct( + ÷r_ranges[DIVIDER_RANGE_02], + DIVIDER_RANGE_02_START, + DIVIDER_RANGE_02_STEP_SIZE, + DIVIDER_RANGE_02_BASE_DIVIDER_ID, + DIVIDER_RANGE_03_BASE_DIVIDER_ID); + dal_divider_range_construct( + ÷r_ranges[DIVIDER_RANGE_03], + DIVIDER_RANGE_03_START, + DIVIDER_RANGE_03_STEP_SIZE, + DIVIDER_RANGE_03_BASE_DIVIDER_ID, + DIVIDER_RANGE_MAX_DIVIDER_ID); + return true; +} + +struct display_clock *dal_display_clock_dce80_create( + struct dc_context *ctx) +{ + struct display_clock_dce80 *disp_clk; + + disp_clk = dm_alloc(sizeof(struct display_clock_dce80)); + + if (disp_clk == NULL) + return NULL; + + if (display_clock_construct(ctx, disp_clk)) + return &disp_clk->disp_clk; + + dm_free(disp_clk); + return NULL; +} + diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.h b/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.h new file mode 100644 index 000000000000..944dd0380413 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.h @@ -0,0 +1,57 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef __DAL_DISPLAY_CLOCK_DCE80_H__ +#define __DAL_DISPLAY_CLOCK_DCE80_H__ + +#include "gpu/display_clock.h" + +struct display_clock_dce80 { + struct display_clock disp_clk; + /* DFS input - GPUPLL VCO frequency - from VBIOS Firmware info. */ + uint32_t dentist_vco_freq_khz; + /* GPU PLL SS percentage (if down-spread enabled)*/ + uint32_t gpu_pll_ss_percentage; + /* GPU PLL SS percentage Divider (100 or 1000)*/ + uint32_t gpu_pll_ss_divider; + /* Flag for Enabled SS on GPU PLL*/ + bool ss_on_gpu_pll; + /* Max display block clocks state*/ + enum clocks_state max_clks_state; + /* Current minimum display block clocks state*/ + enum clocks_state cur_min_clks_state; + /* DFS-bypass feature variable + Cache the status of DFS-bypass feature*/ + bool dfs_bypass_enabled; + /* Cache the display clock returned by VBIOS if DFS-bypass is enabled. + * This is basically "Crystal Frequency In KHz" (XTALIN) frequency */ + uint32_t dfs_bypass_disp_clk; + bool use_max_disp_clk; + struct display_clock_state clock_state; +}; + +struct display_clock *dal_display_clock_dce80_create( + struct dc_context *ctx); + +#endif /* __DAL_DISPLAY_CLOCK_DCE80_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/gpu/display_clock.c b/drivers/gpu/drm/amd/display/dc/gpu/display_clock.c new file mode 100644 index 000000000000..bcc0a5132600 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpu/display_clock.c @@ -0,0 +1,217 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "display_clock.h" + +void dal_display_clock_base_set_dp_ref_clock_source( + struct display_clock *disp_clk, + enum clock_source_id clk_src) +{/*must be implemented in derived*/ + +} + +void dal_display_clock_base_set_clock_state(struct display_clock *disp_clk, + struct display_clock_state clk_state) +{ + /*Implemented only in DCE81*/ +} +struct display_clock_state dal_display_clock_base_get_clock_state( + struct display_clock *disp_clk) +{ + /*Implemented only in DCE81*/ + struct display_clock_state state = {0}; + return state; +} +uint32_t dal_display_clock_base_get_dfs_bypass_threshold( + struct display_clock *disp_clk) +{ + /*Implemented only in DCE81*/ + return 0; +} + +bool dal_display_clock_construct_base( + struct display_clock *base, + struct dc_context *ctx) +{ + base->ctx = ctx; + base->id = CLOCK_SOURCE_ID_DCPLL; + base->min_display_clk_threshold_khz = 0; + +/* Initially set current min clocks state to invalid since we + * cannot make any assumption about PPLIB's initial state. This will be updated + * by HWSS via SetMinClocksState() on first mode set prior to programming + * state dependent clocks.*/ + base->cur_min_clks_state = CLOCKS_STATE_INVALID; + + return true; +} + +void dal_display_clock_destroy(struct display_clock **disp_clk) +{ + if (!disp_clk || !*disp_clk) { + BREAK_TO_DEBUGGER(); + return; + } + + (*disp_clk)->funcs->destroy(disp_clk); + + *disp_clk = NULL; +} + +bool dal_display_clock_validate( + struct display_clock *disp_clk, + struct min_clock_params *params) +{ + return disp_clk->funcs->validate(disp_clk, params); +} + +uint32_t dal_display_clock_calculate_min_clock( + struct display_clock *disp_clk, + uint32_t path_num, + struct min_clock_params *params) +{ + return disp_clk->funcs->calculate_min_clock(disp_clk, path_num, params); +} + +uint32_t dal_display_clock_get_validation_clock(struct display_clock *disp_clk) +{ + return disp_clk->funcs->get_validation_clock(disp_clk); +} + +void dal_display_clock_set_clock( + struct display_clock *disp_clk, + uint32_t requested_clock_khz) +{ + disp_clk->funcs->set_clock(disp_clk, requested_clock_khz); +} + +uint32_t dal_display_clock_get_clock(struct display_clock *disp_clk) +{ + return disp_clk->funcs->get_clock(disp_clk); +} + +bool dal_display_clock_get_min_clocks_state( + struct display_clock *disp_clk, + enum clocks_state *clocks_state) +{ + if (!disp_clk->funcs->get_min_clocks_state) + return false; + + *clocks_state = disp_clk->funcs->get_min_clocks_state(disp_clk); + return true; +} + +bool dal_display_clock_get_required_clocks_state( + struct display_clock *disp_clk, + struct state_dependent_clocks *req_clocks, + enum clocks_state *clocks_state) +{ + if (!disp_clk->funcs->get_required_clocks_state) + return false; + + *clocks_state = disp_clk->funcs->get_required_clocks_state( + disp_clk, req_clocks); + return true; +} + +bool dal_display_clock_set_min_clocks_state( + struct display_clock *disp_clk, + enum clocks_state clocks_state) +{ + if (!disp_clk->funcs->set_min_clocks_state) + return false; + + disp_clk->funcs->set_min_clocks_state(disp_clk, clocks_state); + return true; +} + +uint32_t dal_display_clock_get_dp_ref_clk_frequency( + struct display_clock *disp_clk) +{ + return disp_clk->funcs->get_dp_ref_clk_frequency(disp_clk); +} + +/*the second parameter of "switchreferenceclock" is + * a dummy argument for all pre dce 6.0 versions*/ + +void dal_display_clock_switch_reference_clock( + struct display_clock *disp_clk, + bool use_external_ref_clk, + uint32_t requested_clk_khz) +{ + /* TODO: requires Asic Control*/ + /* + struct ac_pixel_clk_params params; + struct asic_control *ac = + dal_adapter_service_get_asic_control(disp_clk->as); + dc_service_memset(¶ms, 0, sizeof(struct ac_pixel_clk_params)); + + params.tgt_pixel_clk_khz = requested_clk_khz; + params.flags.SET_EXTERNAL_REF_DIV_SRC = use_external_ref_clk; + params.pll_id = disp_clk->id; + dal_asic_control_program_display_engine_pll(ac, ¶ms); + */ +} + +void dal_display_clock_set_dp_ref_clock_source( + struct display_clock *disp_clk, + enum clock_source_id clk_src) +{ + disp_clk->funcs->set_dp_ref_clock_source(disp_clk, clk_src); +} + +void dal_display_clock_store_max_clocks_state( + struct display_clock *disp_clk, + enum clocks_state max_clocks_state) +{ + disp_clk->funcs->store_max_clocks_state(disp_clk, max_clocks_state); +} + +void dal_display_clock_set_clock_state( + struct display_clock *disp_clk, + struct display_clock_state clk_state) +{ + disp_clk->funcs->set_clock_state(disp_clk, clk_state); +} + +struct display_clock_state dal_display_clock_get_clock_state( + struct display_clock *disp_clk) +{ + return disp_clk->funcs->get_clock_state(disp_clk); +} + +uint32_t dal_display_clock_get_dfs_bypass_threshold( + struct display_clock *disp_clk) +{ + return disp_clk->funcs->get_dfs_bypass_threshold(disp_clk); +} + +void dal_display_clock_invalid_clock_state( + struct display_clock *disp_clk) +{ + disp_clk->cur_min_clks_state = CLOCKS_STATE_INVALID; +} + diff --git a/drivers/gpu/drm/amd/display/dc/gpu/display_clock.h b/drivers/gpu/drm/amd/display/dc/gpu/display_clock.h new file mode 100644 index 000000000000..663580d18a09 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpu/display_clock.h @@ -0,0 +1,89 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_DISPLAY_CLOCK_H__ +#define __DAL_DISPLAY_CLOCK_H__ + +#include "include/display_clock_interface.h" + +struct display_clock_funcs { + void (*destroy)(struct display_clock **to_destroy); + bool (*validate)(struct display_clock *disp_clk, + struct min_clock_params *params); + uint32_t (*calculate_min_clock)(struct display_clock *disp_clk, + uint32_t path_num, struct min_clock_params *params); + uint32_t (*get_validation_clock)(struct display_clock *disp_clk); + void (*set_clock)(struct display_clock *disp_clk, + uint32_t requested_clock_khz); + uint32_t (*get_clock)(struct display_clock *disp_clk); + enum clocks_state (*get_min_clocks_state)( + struct display_clock *disp_clk); + enum clocks_state (*get_required_clocks_state)( + struct display_clock *disp_clk, + struct state_dependent_clocks *req_clocks); + bool (*set_min_clocks_state)(struct display_clock *disp_clk, + enum clocks_state clocks_state); + uint32_t (*get_dp_ref_clk_frequency)(struct display_clock *disp_clk); + void (*set_dp_ref_clock_source)(struct display_clock *disp_clk, + enum clock_source_id clk_src); + void (*store_max_clocks_state)(struct display_clock *disp_clk, + enum clocks_state max_clocks_state); + void (*set_clock_state)(struct display_clock *disp_clk, + struct display_clock_state clk_state); + struct display_clock_state (*get_clock_state)( + struct display_clock *disp_clk); + uint32_t (*get_dfs_bypass_threshold)(struct display_clock *disp_clk); + +}; + +struct display_clock { + struct dc_context *ctx; + const struct display_clock_funcs *funcs; + uint32_t min_display_clk_threshold_khz; + enum clock_source_id id; + + enum clocks_state cur_min_clks_state; +}; +void dal_display_clock_base_set_dp_ref_clock_source( + struct display_clock *disp_clk, + enum clock_source_id clk_src); +struct display_clock_state dal_display_clock_base_get_clock_state( + struct display_clock *disp_clk); +uint32_t dal_display_clock_base_get_dfs_bypass_threshold( + struct display_clock *disp_clk); +void dal_display_clock_base_set_clock_state(struct display_clock *disp_clk, + struct display_clock_state clk_state); +bool dal_display_clock_construct_base( + struct display_clock *base, + struct dc_context *ctx); + +uint32_t dal_display_clock_get_validation_clock(struct display_clock *disp_clk); + +void dal_display_clock_store_max_clocks_state( + struct display_clock *disp_clk, + enum clocks_state max_clocks_state); + + +#endif /* __DAL_DISPLAY_CLOCK_H__*/ diff --git a/drivers/gpu/drm/amd/display/dc/gpu/divider_range.c b/drivers/gpu/drm/amd/display/dc/gpu/divider_range.c new file mode 100644 index 000000000000..59d44004411b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpu/divider_range.c @@ -0,0 +1,127 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#include "dm_services.h" +#include "divider_range.h" + +bool dal_divider_range_construct( + struct divider_range *div_range, + uint32_t range_start, + uint32_t range_step, + uint32_t did_min, + uint32_t did_max) +{ + div_range->div_range_start = range_start; + div_range->div_range_step = range_step; + div_range->did_min = did_min; + div_range->did_max = did_max; + + if (div_range->div_range_step == 0) { + div_range->div_range_step = 1; + /*div_range_step cannot be zero*/ + BREAK_TO_DEBUGGER(); + } + /* Calculate this based on the other inputs.*/ + /* See DividerRange.h for explanation of */ + /* the relationship between divider id (DID) and a divider.*/ + /* Number of Divider IDs = (Maximum Divider ID - Minimum Divider ID)*/ + /* Maximum divider identified in this range = + * (Number of Divider IDs)*Step size between dividers + * + The start of this range.*/ + div_range->div_range_end = (did_max - did_min) * range_step + + range_start; + return true; +} + +static uint32_t dal_divider_range_calc_divider( + struct divider_range *div_range, + uint32_t did) +{ + /* Is this DID within our range?*/ + if ((did < div_range->did_min) || (did >= div_range->did_max)) + return INVALID_DIVIDER; + + return ((did - div_range->did_min) * div_range->div_range_step) + + div_range->div_range_start; + +} + +static uint32_t dal_divider_range_calc_did( + struct divider_range *div_range, + uint32_t div) +{ + uint32_t did; + /* Check before dividing.*/ + if (div_range->div_range_step == 0) { + div_range->div_range_step = 1; + /*div_range_step cannot be zero*/ + BREAK_TO_DEBUGGER(); + } + /* Is this divider within our range?*/ + if ((div < div_range->div_range_start) + || (div >= div_range->div_range_end)) + return INVALID_DID; +/* did = (divider - range_start + (range_step-1)) / range_step) + did_min*/ + did = div - div_range->div_range_start; + did += div_range->div_range_step - 1; + did /= div_range->div_range_step; + did += div_range->did_min; + return did; +} + +uint32_t dal_divider_range_get_divider( + struct divider_range *div_range, + uint32_t ranges_num, + uint32_t did) +{ + uint32_t div = INVALID_DIVIDER; + uint32_t i; + + for (i = 0; i < ranges_num; i++) { + /* Calculate divider with given divider ID*/ + div = dal_divider_range_calc_divider(&div_range[i], did); + /* Found a valid return divider*/ + if (div != INVALID_DIVIDER) + break; + } + return div; +} +uint32_t dal_divider_range_get_did( + struct divider_range *div_range, + uint32_t ranges_num, + uint32_t divider) +{ + uint32_t did = INVALID_DID; + uint32_t i; + + for (i = 0; i < ranges_num; i++) { + /* CalcDid returns InvalidDid if a divider ID isn't found*/ + did = dal_divider_range_calc_did(&div_range[i], divider); + /* Found a valid return did*/ + if (did != INVALID_DID) + break; + } + return did; +} + diff --git a/drivers/gpu/drm/amd/display/dc/gpu/divider_range.h b/drivers/gpu/drm/amd/display/dc/gpu/divider_range.h new file mode 100644 index 000000000000..e53522f652cc --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpu/divider_range.h @@ -0,0 +1,62 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_DIVIDER_RANGE_H__ +#define __DAL_DIVIDER_RANGE_H__ + +enum divider_error_types { + INVALID_DID = 0, + INVALID_DIVIDER = 1 +}; + +struct divider_range { + uint32_t div_range_start; + /* The end of this range of dividers.*/ + uint32_t div_range_end; + /* The distance between each divider in this range.*/ + uint32_t div_range_step; + /* The divider id for the lowest divider.*/ + uint32_t did_min; + /* The divider id for the highest divider.*/ + uint32_t did_max; +}; + +bool dal_divider_range_construct( + struct divider_range *div_range, + uint32_t range_start, + uint32_t range_step, + uint32_t did_min, + uint32_t did_max); + +uint32_t dal_divider_range_get_divider( + struct divider_range *div_range, + uint32_t ranges_num, + uint32_t did); +uint32_t dal_divider_range_get_did( + struct divider_range *div_range, + uint32_t ranges_num, + uint32_t divider); + +#endif /* __DAL_DIVIDER_RANGE_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/Makefile b/drivers/gpu/drm/amd/display/dc/i2caux/Makefile new file mode 100644 index 000000000000..83dfc437aae4 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/Makefile @@ -0,0 +1,58 @@ +# +# Makefile for the 'i2c' sub-component of DAL. +# It provides the control and status of HW i2c engine of the adapter. + +I2CAUX = aux_engine.o engine_base.o i2caux.o i2c_engine.o \ + i2c_generic_hw_engine.o i2c_hw_engine.o i2c_sw_engine.o + +AMD_DAL_I2CAUX = $(addprefix $(AMDDALPATH)/dc/i2caux/,$(I2CAUX)) + +AMD_DISPLAY_FILES += $(AMD_DAL_I2CAUX) + +############################################################################### +# DCE 8x family +############################################################################### +I2CAUX_DCE80 = i2caux_dce80.o i2c_hw_engine_dce80.o \ + i2c_sw_engine_dce80.o + +AMD_DAL_I2CAUX_DCE80 = $(addprefix $(AMDDALPATH)/dc/i2caux/dce80/,$(I2CAUX_DCE80)) + +AMD_DISPLAY_FILES += $(AMD_DAL_I2CAUX_DCE80) + +############################################################################### +# DCE 100 family +############################################################################### +I2CAUX_DCE100 = i2caux_dce100.o + +AMD_DAL_I2CAUX_DCE100 = $(addprefix $(AMDDALPATH)/dc/i2caux/dce100/,$(I2CAUX_DCE100)) + +AMD_DISPLAY_FILES += $(AMD_DAL_I2CAUX_DCE100) + +############################################################################### +# DCE 110 family +############################################################################### +I2CAUX_DCE110 = i2caux_dce110.o i2c_sw_engine_dce110.o i2c_hw_engine_dce110.o \ + aux_engine_dce110.o + +AMD_DAL_I2CAUX_DCE110 = $(addprefix $(AMDDALPATH)/dc/i2caux/dce110/,$(I2CAUX_DCE110)) + +AMD_DISPLAY_FILES += $(AMD_DAL_I2CAUX_DCE110) + +############################################################################### +# DCE 112 family +############################################################################### +I2CAUX_DCE112 = i2caux_dce112.o + +AMD_DAL_I2CAUX_DCE112 = $(addprefix $(AMDDALPATH)/dc/i2caux/dce112/,$(I2CAUX_DCE112)) + +AMD_DISPLAY_FILES += $(AMD_DAL_I2CAUX_DCE112) + +############################################################################### +# Diagnostics on FPGA +############################################################################### +I2CAUX_DIAG = i2caux_diag.o + +AMD_DAL_I2CAUX_DIAG = $(addprefix $(AMDDALPATH)/dc/i2caux/diagnostics/,$(I2CAUX_DIAG)) + +AMD_DISPLAY_FILES += $(AMD_DAL_I2CAUX_DIAG) + diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.c b/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.c new file mode 100644 index 000000000000..667660f3fa26 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.c @@ -0,0 +1,567 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* + * Pre-requisites: headers required by header of this unit + */ +#include "include/i2caux_interface.h" +#include "engine.h" + +/* + * Header of this unit + */ + +#include "aux_engine.h" + +/* + * Post-requisites: headers required by this unit + */ + +#include "include/link_service_types.h" + +/* + * This unit + */ + +enum { + AUX_INVALID_REPLY_RETRY_COUNTER = 1, + AUX_TIMED_OUT_RETRY_COUNTER = 2, + AUX_DEFER_RETRY_COUNTER = 6 +}; + +#define FROM_ENGINE(ptr) \ + container_of((ptr), struct aux_engine, base) + +enum i2caux_engine_type dal_aux_engine_get_engine_type( + const struct engine *engine) +{ + return I2CAUX_ENGINE_TYPE_AUX; +} + +bool dal_aux_engine_acquire( + struct engine *engine, + struct ddc *ddc) +{ + struct aux_engine *aux_engine = FROM_ENGINE(engine); + + enum gpio_result result; + + result = dal_ddc_open(ddc, GPIO_MODE_HARDWARE, + GPIO_DDC_CONFIG_TYPE_MODE_AUX); + + if (result != GPIO_RESULT_OK) + return false; + + if (!aux_engine->funcs->acquire_engine(aux_engine)) { + dal_ddc_close(ddc); + return false; + } + + engine->ddc = ddc; + + return true; +} + +struct read_command_context { + uint8_t *buffer; + uint32_t current_read_length; + uint32_t offset; + enum i2caux_transaction_status status; + + struct aux_request_transaction_data request; + struct aux_reply_transaction_data reply; + + uint8_t returned_byte; + + uint32_t timed_out_retry_aux; + uint32_t invalid_reply_retry_aux; + uint32_t defer_retry_aux; + uint32_t defer_retry_i2c; + uint32_t invalid_reply_retry_aux_on_ack; + + bool transaction_complete; + bool operation_succeeded; +}; + +static void process_read_reply( + struct aux_engine *engine, + struct read_command_context *ctx) +{ + engine->funcs->process_channel_reply(engine, &ctx->reply); + + switch (ctx->reply.status) { + case AUX_TRANSACTION_REPLY_AUX_ACK: + ctx->defer_retry_aux = 0; + if (ctx->returned_byte > ctx->current_read_length) { + ctx->status = + I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR; + ctx->operation_succeeded = false; + } else if (ctx->returned_byte < ctx->current_read_length) { + ctx->current_read_length -= ctx->returned_byte; + + ctx->offset += ctx->returned_byte; + + ++ctx->invalid_reply_retry_aux_on_ack; + + if (ctx->invalid_reply_retry_aux_on_ack > + AUX_INVALID_REPLY_RETRY_COUNTER) { + ctx->status = + I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR; + ctx->operation_succeeded = false; + } + } else { + ctx->status = I2CAUX_TRANSACTION_STATUS_SUCCEEDED; + ctx->transaction_complete = true; + ctx->operation_succeeded = true; + } + break; + case AUX_TRANSACTION_REPLY_AUX_NACK: + ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_NACK; + ctx->operation_succeeded = false; + break; + case AUX_TRANSACTION_REPLY_AUX_DEFER: + ++ctx->defer_retry_aux; + + if (ctx->defer_retry_aux > AUX_DEFER_RETRY_COUNTER) { + ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; + ctx->operation_succeeded = false; + } + break; + case AUX_TRANSACTION_REPLY_I2C_DEFER: + ctx->defer_retry_aux = 0; + + ++ctx->defer_retry_i2c; + + if (ctx->defer_retry_i2c > AUX_DEFER_RETRY_COUNTER) { + ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; + ctx->operation_succeeded = false; + } + break; + default: + ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN; + ctx->operation_succeeded = false; + } +} + +static void process_read_request( + struct aux_engine *engine, + struct read_command_context *ctx) +{ + enum aux_channel_operation_result operation_result; + + engine->funcs->submit_channel_request(engine, &ctx->request); + + operation_result = engine->funcs->get_channel_status( + engine, &ctx->returned_byte); + + switch (operation_result) { + case AUX_CHANNEL_OPERATION_SUCCEEDED: + if (ctx->returned_byte > ctx->current_read_length) { + ctx->status = + I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR; + ctx->operation_succeeded = false; + } else { + ctx->timed_out_retry_aux = 0; + ctx->invalid_reply_retry_aux = 0; + + ctx->reply.length = ctx->returned_byte; + ctx->reply.data = ctx->buffer; + + process_read_reply(engine, ctx); + } + break; + case AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY: + ++ctx->invalid_reply_retry_aux; + + if (ctx->invalid_reply_retry_aux > + AUX_INVALID_REPLY_RETRY_COUNTER) { + ctx->status = + I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR; + ctx->operation_succeeded = false; + } else + udelay(400); + break; + case AUX_CHANNEL_OPERATION_FAILED_TIMEOUT: + ++ctx->timed_out_retry_aux; + + if (ctx->timed_out_retry_aux > AUX_TIMED_OUT_RETRY_COUNTER) { + ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; + ctx->operation_succeeded = false; + } else { + /* DP 1.2a, table 2-58: + * "S3: AUX Request CMD PENDING: + * retry 3 times, with 400usec wait on each" + * The HW timeout is set to 550usec, + * so we should not wait here */ + } + break; + default: + ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN; + ctx->operation_succeeded = false; + } +} + +static bool read_command( + struct aux_engine *engine, + struct i2caux_transaction_request *request, + bool middle_of_transaction) +{ + struct read_command_context ctx; + + ctx.buffer = request->payload.data; + ctx.current_read_length = request->payload.length; + ctx.offset = 0; + ctx.timed_out_retry_aux = 0; + ctx.invalid_reply_retry_aux = 0; + ctx.defer_retry_aux = 0; + ctx.defer_retry_i2c = 0; + ctx.invalid_reply_retry_aux_on_ack = 0; + ctx.transaction_complete = false; + ctx.operation_succeeded = true; + + if (request->payload.address_space == + I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD) { + ctx.request.type = AUX_TRANSACTION_TYPE_DP; + ctx.request.action = I2CAUX_TRANSACTION_ACTION_DP_READ; + ctx.request.address = request->payload.address; + } else if (request->payload.address_space == + I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C) { + ctx.request.type = AUX_TRANSACTION_TYPE_I2C; + ctx.request.action = middle_of_transaction ? + I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT : + I2CAUX_TRANSACTION_ACTION_I2C_READ; + ctx.request.address = request->payload.address >> 1; + } else { + /* in DAL2, there was no return in such case */ + BREAK_TO_DEBUGGER(); + return false; + } + + ctx.request.delay = 0; + + do { + memset(ctx.buffer + ctx.offset, 0, ctx.current_read_length); + + ctx.request.data = ctx.buffer + ctx.offset; + ctx.request.length = ctx.current_read_length; + + process_read_request(engine, &ctx); + + request->status = ctx.status; + + if (ctx.operation_succeeded && !ctx.transaction_complete) + if (ctx.request.type == AUX_TRANSACTION_TYPE_I2C) + msleep(engine->delay); + } while (ctx.operation_succeeded && !ctx.transaction_complete); + + return ctx.operation_succeeded; +} + +struct write_command_context { + bool mot; + + uint8_t *buffer; + uint32_t current_write_length; + enum i2caux_transaction_status status; + + struct aux_request_transaction_data request; + struct aux_reply_transaction_data reply; + + uint8_t returned_byte; + + uint32_t timed_out_retry_aux; + uint32_t invalid_reply_retry_aux; + uint32_t defer_retry_aux; + uint32_t defer_retry_i2c; + uint32_t max_defer_retry; + uint32_t ack_m_retry; + + uint8_t reply_data[DEFAULT_AUX_MAX_DATA_SIZE]; + + bool transaction_complete; + bool operation_succeeded; +}; + +static void process_write_reply( + struct aux_engine *engine, + struct write_command_context *ctx) +{ + engine->funcs->process_channel_reply(engine, &ctx->reply); + + switch (ctx->reply.status) { + case AUX_TRANSACTION_REPLY_AUX_ACK: + ctx->operation_succeeded = true; + + if (ctx->returned_byte) { + ctx->request.action = ctx->mot ? + I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST_MOT : + I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST; + + ctx->current_write_length = 0; + + ++ctx->ack_m_retry; + + if (ctx->ack_m_retry > AUX_DEFER_RETRY_COUNTER) { + ctx->status = + I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; + ctx->operation_succeeded = false; + } else + udelay(300); + } else { + ctx->status = I2CAUX_TRANSACTION_STATUS_SUCCEEDED; + ctx->defer_retry_aux = 0; + ctx->ack_m_retry = 0; + ctx->transaction_complete = true; + } + break; + case AUX_TRANSACTION_REPLY_AUX_NACK: + ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_NACK; + ctx->operation_succeeded = false; + break; + case AUX_TRANSACTION_REPLY_AUX_DEFER: + ++ctx->defer_retry_aux; + + if (ctx->defer_retry_aux > ctx->max_defer_retry) { + ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; + ctx->operation_succeeded = false; + } + break; + case AUX_TRANSACTION_REPLY_I2C_DEFER: + ctx->defer_retry_aux = 0; + ctx->current_write_length = 0; + + ctx->request.action = ctx->mot ? + I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST_MOT : + I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST; + + ++ctx->defer_retry_i2c; + + if (ctx->defer_retry_i2c > ctx->max_defer_retry) { + ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; + ctx->operation_succeeded = false; + } + break; + default: + ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN; + ctx->operation_succeeded = false; + } +} + +static void process_write_request( + struct aux_engine *engine, + struct write_command_context *ctx) +{ + enum aux_channel_operation_result operation_result; + + engine->funcs->submit_channel_request(engine, &ctx->request); + + operation_result = engine->funcs->get_channel_status( + engine, &ctx->returned_byte); + + switch (operation_result) { + case AUX_CHANNEL_OPERATION_SUCCEEDED: + ctx->timed_out_retry_aux = 0; + ctx->invalid_reply_retry_aux = 0; + + ctx->reply.length = ctx->returned_byte; + ctx->reply.data = ctx->reply_data; + + process_write_reply(engine, ctx); + break; + case AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY: + ++ctx->invalid_reply_retry_aux; + + if (ctx->invalid_reply_retry_aux > + AUX_INVALID_REPLY_RETRY_COUNTER) { + ctx->status = + I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR; + ctx->operation_succeeded = false; + } else + udelay(400); + break; + case AUX_CHANNEL_OPERATION_FAILED_TIMEOUT: + ++ctx->timed_out_retry_aux; + + if (ctx->timed_out_retry_aux > AUX_TIMED_OUT_RETRY_COUNTER) { + ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; + ctx->operation_succeeded = false; + } else { + /* DP 1.2a, table 2-58: + * "S3: AUX Request CMD PENDING: + * retry 3 times, with 400usec wait on each" + * The HW timeout is set to 550usec, + * so we should not wait here */ + } + break; + default: + ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN; + ctx->operation_succeeded = false; + } +} + +static bool write_command( + struct aux_engine *engine, + struct i2caux_transaction_request *request, + bool middle_of_transaction) +{ + struct write_command_context ctx; + + ctx.mot = middle_of_transaction; + ctx.buffer = request->payload.data; + ctx.current_write_length = request->payload.length; + ctx.timed_out_retry_aux = 0; + ctx.invalid_reply_retry_aux = 0; + ctx.defer_retry_aux = 0; + ctx.defer_retry_i2c = 0; + ctx.ack_m_retry = 0; + ctx.transaction_complete = false; + ctx.operation_succeeded = true; + + if (request->payload.address_space == + I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD) { + ctx.request.type = AUX_TRANSACTION_TYPE_DP; + ctx.request.action = I2CAUX_TRANSACTION_ACTION_DP_WRITE; + ctx.request.address = request->payload.address; + } else if (request->payload.address_space == + I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C) { + ctx.request.type = AUX_TRANSACTION_TYPE_I2C; + ctx.request.action = middle_of_transaction ? + I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT : + I2CAUX_TRANSACTION_ACTION_I2C_WRITE; + ctx.request.address = request->payload.address >> 1; + } else { + /* in DAL2, there was no return in such case */ + BREAK_TO_DEBUGGER(); + return false; + } + + ctx.request.delay = 0; + + ctx.max_defer_retry = + (engine->max_defer_write_retry > AUX_DEFER_RETRY_COUNTER) ? + engine->max_defer_write_retry : AUX_DEFER_RETRY_COUNTER; + + do { + ctx.request.data = ctx.buffer; + ctx.request.length = ctx.current_write_length; + + process_write_request(engine, &ctx); + + request->status = ctx.status; + + if (ctx.operation_succeeded && !ctx.transaction_complete) + if (ctx.request.type == AUX_TRANSACTION_TYPE_I2C) + msleep(engine->delay); + } while (ctx.operation_succeeded && !ctx.transaction_complete); + + return ctx.operation_succeeded; +} + +static bool end_of_transaction_command( + struct aux_engine *engine, + struct i2caux_transaction_request *request) +{ + struct i2caux_transaction_request dummy_request; + uint8_t dummy_data; + + /* [tcheng] We only need to send the stop (read with MOT = 0) + * for I2C-over-Aux, not native AUX */ + + if (request->payload.address_space != + I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C) + return false; + + dummy_request.operation = request->operation; + dummy_request.payload.address_space = request->payload.address_space; + dummy_request.payload.address = request->payload.address; + + /* + * Add a dummy byte due to some receiver quirk + * where one byte is sent along with MOT = 0. + * Ideally this should be 0. + */ + + dummy_request.payload.length = 0; + dummy_request.payload.data = &dummy_data; + + if (request->operation == I2CAUX_TRANSACTION_READ) + return read_command(engine, &dummy_request, false); + else + return write_command(engine, &dummy_request, false); + + /* according Syed, it does not need now DoDummyMOT */ +} + +bool dal_aux_engine_submit_request( + struct engine *engine, + struct i2caux_transaction_request *request, + bool middle_of_transaction) +{ + struct aux_engine *aux_engine = FROM_ENGINE(engine); + + bool result; + bool mot_used = true; + + switch (request->operation) { + case I2CAUX_TRANSACTION_READ: + result = read_command(aux_engine, request, mot_used); + break; + case I2CAUX_TRANSACTION_WRITE: + result = write_command(aux_engine, request, mot_used); + break; + default: + result = false; + } + + /* [tcheng] + * need to send stop for the last transaction to free up the AUX + * if the above command fails, this would be the last transaction */ + + if (!middle_of_transaction || !result) + end_of_transaction_command(aux_engine, request); + + /* mask AUX interrupt */ + + return result; +} + +bool dal_aux_engine_construct( + struct aux_engine *engine, + struct dc_context *ctx) +{ + if (!dal_i2caux_construct_engine(&engine->base, ctx)) + return false; + engine->delay = 0; + engine->max_defer_write_retry = 0; + return true; +} + +void dal_aux_engine_destruct( + struct aux_engine *engine) +{ + dal_i2caux_destruct_engine(&engine->base); +} diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.h b/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.h new file mode 100644 index 000000000000..b5d6c79eb029 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.h @@ -0,0 +1,117 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_AUX_ENGINE_H__ +#define __DAL_AUX_ENGINE_H__ + +enum aux_transaction_type { + AUX_TRANSACTION_TYPE_DP, + AUX_TRANSACTION_TYPE_I2C +}; + +struct aux_request_transaction_data { + enum aux_transaction_type type; + enum i2caux_transaction_action action; + /* 20-bit AUX channel transaction address */ + uint32_t address; + /* delay, in 100-microsecond units */ + uint8_t delay; + uint32_t length; + uint8_t *data; +}; + +enum aux_transaction_reply { + AUX_TRANSACTION_REPLY_AUX_ACK = 0x00, + AUX_TRANSACTION_REPLY_AUX_NACK = 0x01, + AUX_TRANSACTION_REPLY_AUX_DEFER = 0x02, + + AUX_TRANSACTION_REPLY_I2C_ACK = 0x00, + AUX_TRANSACTION_REPLY_I2C_NACK = 0x10, + AUX_TRANSACTION_REPLY_I2C_DEFER = 0x20, + + AUX_TRANSACTION_REPLY_INVALID = 0xFF +}; + +struct aux_reply_transaction_data { + enum aux_transaction_reply status; + uint32_t length; + uint8_t *data; +}; + +enum aux_channel_operation_result { + AUX_CHANNEL_OPERATION_SUCCEEDED, + AUX_CHANNEL_OPERATION_FAILED_REASON_UNKNOWN, + AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY, + AUX_CHANNEL_OPERATION_FAILED_TIMEOUT +}; + +struct aux_engine; + +struct aux_engine_funcs { + void (*destroy)( + struct aux_engine **ptr); + bool (*acquire_engine)( + struct aux_engine *engine); + void (*configure)( + struct aux_engine *engine, + union aux_config cfg); + void (*submit_channel_request)( + struct aux_engine *engine, + struct aux_request_transaction_data *request); + void (*process_channel_reply)( + struct aux_engine *engine, + struct aux_reply_transaction_data *reply); + enum aux_channel_operation_result (*get_channel_status)( + struct aux_engine *engine, + uint8_t *returned_bytes); +}; + +struct aux_engine { + struct engine base; + const struct aux_engine_funcs *funcs; + /* following values are expressed in milliseconds */ + uint32_t delay; + uint32_t max_defer_write_retry; + + bool acquire_reset; +}; + +bool dal_aux_engine_construct( + struct aux_engine *engine, + struct dc_context *ctx); + +void dal_aux_engine_destruct( + struct aux_engine *engine); +bool dal_aux_engine_submit_request( + struct engine *ptr, + struct i2caux_transaction_request *request, + bool middle_of_transaction); +bool dal_aux_engine_acquire( + struct engine *ptr, + struct ddc *ddc); +enum i2caux_engine_type dal_aux_engine_get_engine_type( + const struct engine *engine); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce100/i2caux_dce100.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce100/i2caux_dce100.c new file mode 100644 index 000000000000..0712cafb4c42 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce100/i2caux_dce100.c @@ -0,0 +1,112 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "include/i2caux_interface.h" +#include "../i2caux.h" +#include "../engine.h" +#include "../i2c_engine.h" +#include "../i2c_sw_engine.h" +#include "../i2c_hw_engine.h" + +#include "../dce110/aux_engine_dce110.h" +#include "../dce110/i2c_hw_engine_dce110.h" +#include "../dce110/i2caux_dce110.h" + +#include "dce/dce_10_0_d.h" +#include "dce/dce_10_0_sh_mask.h" + +/* set register offset */ +#define SR(reg_name)\ + .reg_name = mm ## reg_name + +/* set register offset with instance */ +#define SRI(reg_name, block, id)\ + .reg_name = mm ## block ## id ## _ ## reg_name + +#define aux_regs(id)\ +[id] = {\ + AUX_COMMON_REG_LIST(id), \ + .AUX_RESET_MASK = 0 \ +} + +#define hw_engine_regs(id)\ +{\ + I2C_HW_ENGINE_COMMON_REG_LIST(id) \ +} + +static const struct dce110_aux_registers dce100_aux_regs[] = { + aux_regs(0), + aux_regs(1), + aux_regs(2), + aux_regs(3), + aux_regs(4), + aux_regs(5), +}; + +static const struct dce110_i2c_hw_engine_registers dce100_hw_engine_regs[] = { + hw_engine_regs(1), + hw_engine_regs(2), + hw_engine_regs(3), + hw_engine_regs(4), + hw_engine_regs(5), + hw_engine_regs(6) +}; + +static const struct dce110_i2c_hw_engine_shift i2c_shift = { + I2C_COMMON_MASK_SH_LIST_DCE100(__SHIFT) +}; + +static const struct dce110_i2c_hw_engine_mask i2c_mask = { + I2C_COMMON_MASK_SH_LIST_DCE100(_MASK) +}; + +struct i2caux *dal_i2caux_dce100_create( + struct dc_context *ctx) +{ + struct i2caux_dce110 *i2caux_dce110 = + dm_alloc(sizeof(struct i2caux_dce110)); + + if (!i2caux_dce110) { + ASSERT_CRITICAL(false); + return NULL; + } + + if (dal_i2caux_dce110_construct( + i2caux_dce110, + ctx, + dce100_aux_regs, + dce100_hw_engine_regs, + &i2c_shift, + &i2c_mask)) + return &i2caux_dce110->base; + + ASSERT_CRITICAL(false); + + dm_free(i2caux_dce110); + + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce100/i2caux_dce100.h b/drivers/gpu/drm/amd/display/dc/i2caux/dce100/i2caux_dce100.h new file mode 100644 index 000000000000..2b508d3e0ef4 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce100/i2caux_dce100.h @@ -0,0 +1,32 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_I2C_AUX_DCE100_H__ +#define __DAL_I2C_AUX_DCE100_H__ + +struct i2caux *dal_i2caux_dce100_create( + struct dc_context *ctx); + +#endif /* __DAL_I2C_AUX_DCE100_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c new file mode 100644 index 000000000000..f49fd1ad3807 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c @@ -0,0 +1,456 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* + * Pre-requisites: headers required by header of this unit + */ +#include "include/i2caux_interface.h" +#include "../engine.h" +#include "../aux_engine.h" + +/* + * Header of this unit + */ + +#include "aux_engine_dce110.h" + +/* + * Post-requisites: headers required by this unit + */ +#include "dce/dce_11_0_sh_mask.h" + +#define CTX \ + aux110->base.base.ctx +#define REG(reg_name)\ + (aux110->regs->reg_name) +#include "reg_helper.h" + +/* + * This unit + */ + +/* + * @brief + * Cast 'struct aux_engine *' + * to 'struct aux_engine_dce110 *' + */ +#define FROM_AUX_ENGINE(ptr) \ + container_of((ptr), struct aux_engine_dce110, base) + +/* + * @brief + * Cast 'struct engine *' + * to 'struct aux_engine_dce110 *' + */ +#define FROM_ENGINE(ptr) \ + FROM_AUX_ENGINE(container_of((ptr), struct aux_engine, base)) + +static void release_engine( + struct engine *engine) +{ + struct aux_engine_dce110 *aux110 = FROM_ENGINE(engine); + + REG_UPDATE(AUX_ARB_CONTROL, AUX_SW_DONE_USING_AUX_REG, 1); +} + +static void destruct( + struct aux_engine_dce110 *engine); + +static void destroy( + struct aux_engine **aux_engine) +{ + struct aux_engine_dce110 *engine = FROM_AUX_ENGINE(*aux_engine); + + destruct(engine); + + dm_free(engine); + + *aux_engine = NULL; +} + +#define SW_CAN_ACCESS_AUX 1 + +static bool acquire_engine( + struct aux_engine *engine) +{ + struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); + + /* enable AUX before request SW to access AUX */ + uint32_t value = REG_READ(AUX_CONTROL); + uint32_t field = get_reg_field_value(value, + AUX_CONTROL, + AUX_EN); + + if (field == 0) { + set_reg_field_value( + value, + 1, + AUX_CONTROL, + AUX_EN); + + if (REG(AUX_RESET_MASK)) { + /*DP_AUX block as part of the enable sequence*/ + set_reg_field_value( + value, + 1, + AUX_CONTROL, + AUX_RESET); + } + + REG_WRITE(AUX_CONTROL, value); + + if (REG(AUX_RESET_MASK)) { + /*poll HW to make sure reset it done*/ + + REG_WAIT(AUX_CONTROL, AUX_RESET_DONE, 1, + 1, 11); + + set_reg_field_value( + value, + 0, + AUX_CONTROL, + AUX_RESET); + + REG_WRITE(AUX_CONTROL, value); + + REG_WAIT(AUX_CONTROL, AUX_RESET_DONE, 0, + 1, 11); + } + } /*if (field)*/ + + /* request SW to access AUX */ + REG_UPDATE(AUX_ARB_CONTROL, AUX_SW_USE_AUX_REG_REQ, 1); + + value = REG_READ(AUX_ARB_CONTROL); + field = get_reg_field_value( + value, + AUX_ARB_CONTROL, + AUX_REG_RW_CNTL_STATUS); + + return (field == SW_CAN_ACCESS_AUX); +} + +#define COMPOSE_AUX_SW_DATA_16_20(command, address) \ + ((command) | ((0xF0000 & (address)) >> 16)) + +#define COMPOSE_AUX_SW_DATA_8_15(address) \ + ((0xFF00 & (address)) >> 8) + +#define COMPOSE_AUX_SW_DATA_0_7(address) \ + (0xFF & (address)) + +static void submit_channel_request( + struct aux_engine *engine, + struct aux_request_transaction_data *request) +{ + struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); + uint32_t value; + uint32_t length; + + bool is_write = + ((request->type == AUX_TRANSACTION_TYPE_DP) && + (request->action == I2CAUX_TRANSACTION_ACTION_DP_WRITE)) || + ((request->type == AUX_TRANSACTION_TYPE_I2C) && + ((request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE) || + (request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT))); + + /* clear_aux_error */ + REG_UPDATE_SEQ(AUXN_IMPCAL, AUXN_CALOUT_ERROR_AK, + 1, + 0); + + REG_UPDATE_SEQ(AUXP_IMPCAL, AUXP_CALOUT_ERROR_AK, + 1, + 0); + + /* force_default_calibrate */ + REG_UPDATE_1BY1_2(AUXN_IMPCAL, + AUXN_IMPCAL_ENABLE, 1, + AUXN_IMPCAL_OVERRIDE_ENABLE, 0); + + /* bug? why AUXN update EN and OVERRIDE_EN 1 by 1 while AUX P toggles OVERRIDE? */ + + REG_UPDATE_SEQ(AUXP_IMPCAL, AUXP_IMPCAL_OVERRIDE_ENABLE, + 1, + 0); + + /* set the delay and the number of bytes to write */ + + /* The length include + * the 4 bit header and the 20 bit address + * (that is 3 byte). + * If the requested length is non zero this means + * an addition byte specifying the length is required. */ + + length = request->length ? 4 : 3; + if (is_write) + length += request->length; + + REG_UPDATE_2(AUX_SW_CONTROL, + AUX_SW_START_DELAY, request->delay, + AUX_SW_WR_BYTES, length); + + /* program action and address and payload data (if 'is_write') */ + value = REG_UPDATE_4(AUX_SW_DATA, + AUX_SW_INDEX, 0, + AUX_SW_DATA_RW, 0, + AUX_SW_AUTOINCREMENT_DISABLE, 1, + AUX_SW_DATA, COMPOSE_AUX_SW_DATA_16_20(request->action, request->address)); + + value = REG_SET_2(AUX_SW_DATA, value, + AUX_SW_AUTOINCREMENT_DISABLE, 0, + AUX_SW_DATA, COMPOSE_AUX_SW_DATA_8_15(request->address)); + + value = REG_SET(AUX_SW_DATA, value, + AUX_SW_DATA, COMPOSE_AUX_SW_DATA_0_7(request->address)); + + if (request->length) { + value = REG_SET(AUX_SW_DATA, value, + AUX_SW_DATA, request->length - 1); + } + + if (is_write) { + /* Load the HW buffer with the Data to be sent. + * This is relevant for write operation. + * For read, the data recived data will be + * processed in process_channel_reply(). */ + uint32_t i = 0; + + while (i < request->length) { + value = REG_SET(AUX_SW_DATA, value, + AUX_SW_DATA, request->data[i]); + + ++i; + } + } + + REG_UPDATE(AUX_INTERRUPT_CONTROL, AUX_SW_DONE_ACK, 1); + REG_WAIT(AUX_SW_STATUS, AUX_SW_DONE, 0, + 10, aux110->timeout_period/10); + REG_UPDATE(AUX_SW_CONTROL, AUX_SW_GO, 1); +} + +static void process_channel_reply( + struct aux_engine *engine, + struct aux_reply_transaction_data *reply) +{ + struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); + + /* Need to do a read to get the number of bytes to process + * Alternatively, this information can be passed - + * but that causes coupling which isn't good either. */ + + uint32_t bytes_replied; + uint32_t value; + + value = REG_GET(AUX_SW_STATUS, + AUX_SW_REPLY_BYTE_COUNT, &bytes_replied); + + if (bytes_replied) { + uint32_t reply_result; + + REG_UPDATE_1BY1_3(AUX_SW_DATA, + AUX_SW_INDEX, 0, + AUX_SW_AUTOINCREMENT_DISABLE, 1, + AUX_SW_DATA_RW, 1); + + REG_GET(AUX_SW_DATA, + AUX_SW_DATA, &reply_result); + + reply_result = reply_result >> 4; + + switch (reply_result) { + case 0: /* ACK */ { + uint32_t i = 0; + + /* first byte was already used + * to get the command status */ + --bytes_replied; + + while (i < bytes_replied) { + uint32_t aux_sw_data_val; + + REG_GET(AUX_SW_DATA, + AUX_SW_DATA, &aux_sw_data_val); + + reply->data[i] = aux_sw_data_val; + ++i; + } + + reply->status = AUX_TRANSACTION_REPLY_AUX_ACK; + } + break; + case 1: /* NACK */ + reply->status = AUX_TRANSACTION_REPLY_AUX_NACK; + break; + case 2: /* DEFER */ + reply->status = AUX_TRANSACTION_REPLY_AUX_DEFER; + break; + case 4: /* AUX ACK / I2C NACK */ + reply->status = AUX_TRANSACTION_REPLY_I2C_NACK; + break; + case 8: /* AUX ACK / I2C DEFER */ + reply->status = AUX_TRANSACTION_REPLY_I2C_DEFER; + break; + default: + reply->status = AUX_TRANSACTION_REPLY_INVALID; + } + } else { + /* Need to handle an error case... + * hopefully, upper layer function won't call this function + * if the number of bytes in the reply was 0 + * because there was surely an error that was asserted + * that should have been handled + * for hot plug case, this could happens*/ + if (!(value & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) + ASSERT_CRITICAL(false); + } +} + +static enum aux_channel_operation_result get_channel_status( + struct aux_engine *engine, + uint8_t *returned_bytes) +{ + struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); + + uint32_t value; + + if (returned_bytes == NULL) { + /*caller pass NULL pointer*/ + ASSERT_CRITICAL(false); + return AUX_CHANNEL_OPERATION_FAILED_REASON_UNKNOWN; + } + *returned_bytes = 0; + + /* poll to make sure that SW_DONE is asserted */ + value = REG_WAIT(AUX_SW_STATUS, AUX_SW_DONE, 1, + 10, aux110->timeout_period/10); + + /* Note that the following bits are set in 'status.bits' + * during CTS 4.2.1.2: + * AUX_SW_RX_MIN_COUNT_VIOL, AUX_SW_RX_INVALID_STOP, + * AUX_SW_RX_RECV_NO_DET, AUX_SW_RX_RECV_INVALID_H. + * + * AUX_SW_RX_MIN_COUNT_VIOL is an internal, + * HW debugging bit and should be ignored. */ + if (value & AUX_SW_STATUS__AUX_SW_DONE_MASK) { + if ((value & AUX_SW_STATUS__AUX_SW_RX_TIMEOUT_STATE_MASK) || + (value & AUX_SW_STATUS__AUX_SW_RX_TIMEOUT_MASK)) + return AUX_CHANNEL_OPERATION_FAILED_TIMEOUT; + + else if ((value & AUX_SW_STATUS__AUX_SW_RX_INVALID_STOP_MASK) || + (value & AUX_SW_STATUS__AUX_SW_RX_RECV_NO_DET_MASK) || + (value & + AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_H_MASK) || + (value & AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_L_MASK)) + return AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY; + + *returned_bytes = get_reg_field_value(value, + AUX_SW_STATUS, + AUX_SW_REPLY_BYTE_COUNT); + + if (*returned_bytes == 0) + return + AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY; + else { + *returned_bytes -= 1; + return AUX_CHANNEL_OPERATION_SUCCEEDED; + } + } else { + /*time_elapsed >= aux_engine->timeout_period */ + if (!(value & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) + ASSERT_CRITICAL(false); + + return AUX_CHANNEL_OPERATION_FAILED_TIMEOUT; + } +} + +static const struct aux_engine_funcs aux_engine_funcs = { + .destroy = destroy, + .acquire_engine = acquire_engine, + .submit_channel_request = submit_channel_request, + .process_channel_reply = process_channel_reply, + .get_channel_status = get_channel_status, +}; + +static const struct engine_funcs engine_funcs = { + .release_engine = release_engine, + .submit_request = dal_aux_engine_submit_request, + .get_engine_type = dal_aux_engine_get_engine_type, + .acquire = dal_aux_engine_acquire, +}; + +static bool construct( + struct aux_engine_dce110 *engine, + const struct aux_engine_dce110_init_data *aux_init_data) +{ + if (!dal_aux_engine_construct( + &engine->base, aux_init_data->ctx)) { + ASSERT_CRITICAL(false); + return false; + } + engine->base.base.funcs = &engine_funcs; + engine->base.funcs = &aux_engine_funcs; + + engine->timeout_period = aux_init_data->timeout_period; + engine->regs = aux_init_data->regs; + + return true; +} + +static void destruct( + struct aux_engine_dce110 *engine) +{ + dal_aux_engine_destruct(&engine->base); +} + +struct aux_engine *dal_aux_engine_dce110_create( + const struct aux_engine_dce110_init_data *aux_init_data) +{ + struct aux_engine_dce110 *engine; + + if (!aux_init_data) { + ASSERT_CRITICAL(false); + return NULL; + } + + engine = dm_alloc(sizeof(*engine)); + + if (!engine) { + ASSERT_CRITICAL(false); + return NULL; + } + + if (construct(engine, aux_init_data)) + return &engine->base; + + ASSERT_CRITICAL(false); + + dm_free(engine); + + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.h b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.h new file mode 100644 index 000000000000..85ee82162590 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.h @@ -0,0 +1,78 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_AUX_ENGINE_DCE110_H__ +#define __DAL_AUX_ENGINE_DCE110_H__ + +#include "../aux_engine.h" + +#define AUX_COMMON_REG_LIST(id)\ + SRI(AUX_CONTROL, DP_AUX, id), \ + SRI(AUX_ARB_CONTROL, DP_AUX, id), \ + SRI(AUX_SW_DATA, DP_AUX, id), \ + SRI(AUX_SW_CONTROL, DP_AUX, id), \ + SRI(AUX_INTERRUPT_CONTROL, DP_AUX, id), \ + SRI(AUX_SW_STATUS, DP_AUX, id), \ + SR(AUXN_IMPCAL), \ + SR(AUXP_IMPCAL) + +struct dce110_aux_registers { + uint32_t AUX_CONTROL; + uint32_t AUX_ARB_CONTROL; + uint32_t AUX_SW_DATA; + uint32_t AUX_SW_CONTROL; + uint32_t AUX_INTERRUPT_CONTROL; + uint32_t AUX_SW_STATUS; + uint32_t AUXN_IMPCAL; + uint32_t AUXP_IMPCAL; + + uint32_t AUX_RESET_MASK; +}; + +struct aux_engine_dce110 { + struct aux_engine base; + const struct dce110_aux_registers *regs; + struct { + uint32_t aux_control; + uint32_t aux_arb_control; + uint32_t aux_sw_data; + uint32_t aux_sw_control; + uint32_t aux_interrupt_control; + uint32_t aux_sw_status; + } addr; + uint32_t timeout_period; +}; + +struct aux_engine_dce110_init_data { + uint32_t engine_id; + uint32_t timeout_period; + struct dc_context *ctx; + const struct dce110_aux_registers *regs; +}; + +struct aux_engine *dal_aux_engine_dce110_create( + const struct aux_engine_dce110_init_data *aux_init_data); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.c new file mode 100644 index 000000000000..80d06ad78e07 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.c @@ -0,0 +1,577 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "include/logger_interface.h" +/* + * Pre-requisites: headers required by header of this unit + */ + +#include "include/i2caux_interface.h" +#include "../engine.h" +#include "../i2c_engine.h" +#include "../i2c_hw_engine.h" +#include "../i2c_generic_hw_engine.h" +/* + * Header of this unit + */ + +#include "i2c_hw_engine_dce110.h" + +/* + * Post-requisites: headers required by this unit + */ +#include "reg_helper.h" + +/* + * This unit + */ + +enum dc_i2c_status { + DC_I2C_STATUS__DC_I2C_STATUS_IDLE, + DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_SW, + DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_HW +}; + +enum dc_i2c_arbitration { + DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_NORMAL, + DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_HIGH +}; + +enum { + /* No timeout in HW + * (timeout implemented in SW by querying status) */ + I2C_SETUP_TIME_LIMIT = 255, + I2C_HW_BUFFER_SIZE = 538 +}; + +/* + * @brief + * Cast pointer to 'struct i2c_hw_engine *' + * to pointer 'struct i2c_hw_engine_dce110 *' + */ +#define FROM_I2C_HW_ENGINE(ptr) \ + container_of((ptr), struct i2c_hw_engine_dce110, base) +/* + * @brief + * Cast pointer to 'struct i2c_engine *' + * to pointer to 'struct i2c_hw_engine_dce110 *' + */ +#define FROM_I2C_ENGINE(ptr) \ + FROM_I2C_HW_ENGINE(container_of((ptr), struct i2c_hw_engine, base)) + +/* + * @brief + * Cast pointer to 'struct engine *' + * to 'pointer to struct i2c_hw_engine_dce110 *' + */ +#define FROM_ENGINE(ptr) \ + FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base)) + +#define CTX \ + hw_engine->base.base.base.ctx + +#define REG(reg_name)\ + (hw_engine->regs->reg_name) + +#undef FN +#define FN(reg_name, field_name) \ + hw_engine->i2c_shift->field_name, hw_engine->i2c_mask->field_name + +#include "reg_helper.h" + +static void disable_i2c_hw_engine( + struct i2c_hw_engine_dce110 *hw_engine) +{ + REG_UPDATE_N(SETUP, 1, FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_ENABLE), 0); +} + +static void release_engine( + struct engine *engine) +{ + struct i2c_hw_engine_dce110 *hw_engine = FROM_ENGINE(engine); + + struct i2c_engine *base = NULL; + bool safe_to_reset; + + base = &hw_engine->base.base; + + /* Restore original HW engine speed */ + + base->funcs->set_speed(base, hw_engine->base.original_speed); + + /* Release I2C */ + REG_UPDATE(DC_I2C_ARBITRATION, DC_I2C_SW_DONE_USING_I2C_REG, 1); + + /* Reset HW engine */ + { + uint32_t i2c_sw_status = 0; + REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status); + /* if used by SW, safe to reset */ + safe_to_reset = (i2c_sw_status == 1); + } + + if (safe_to_reset) + REG_UPDATE_2( + DC_I2C_CONTROL, + DC_I2C_SOFT_RESET, 1, + DC_I2C_SW_STATUS_RESET, 1); + else + REG_UPDATE(DC_I2C_CONTROL, DC_I2C_SW_STATUS_RESET, 1); + + /* HW I2c engine - clock gating feature */ + if (!hw_engine->engine_keep_power_up_count) + disable_i2c_hw_engine(hw_engine); +} + +static bool setup_engine( + struct i2c_engine *i2c_engine) +{ + struct i2c_hw_engine_dce110 *hw_engine = FROM_I2C_ENGINE(i2c_engine); + + /* Program pin select */ + REG_UPDATE_6( + DC_I2C_CONTROL, + DC_I2C_GO, 0, + DC_I2C_SOFT_RESET, 0, + DC_I2C_SEND_RESET, 0, + DC_I2C_SW_STATUS_RESET, 1, + DC_I2C_TRANSACTION_COUNT, 0, + DC_I2C_DDC_SELECT, hw_engine->engine_id); + + /* Program time limit */ + REG_UPDATE_N( + SETUP, 2, + FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_TIME_LIMIT), I2C_SETUP_TIME_LIMIT, + FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_ENABLE), 1); + + /* Program HW priority + * set to High - interrupt software I2C at any time + * Enable restart of SW I2C that was interrupted by HW + * disable queuing of software while I2C is in use by HW */ + REG_UPDATE_2( + DC_I2C_ARBITRATION, + DC_I2C_NO_QUEUED_SW_GO, 0, + DC_I2C_SW_PRIORITY, DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_NORMAL); + + return true; +} + +static uint32_t get_speed( + const struct i2c_engine *i2c_engine) +{ + const struct i2c_hw_engine_dce110 *hw_engine = FROM_I2C_ENGINE(i2c_engine); + uint32_t pre_scale = 0; + + REG_GET(SPEED, DC_I2C_DDC1_PRESCALE, &pre_scale); + + /* [anaumov] it seems following is unnecessary */ + /*ASSERT(value.bits.DC_I2C_DDC1_PRESCALE);*/ + return pre_scale ? + hw_engine->reference_frequency / pre_scale : + hw_engine->base.default_speed; +} + +static void set_speed( + struct i2c_engine *i2c_engine, + uint32_t speed) +{ + struct i2c_hw_engine_dce110 *hw_engine = FROM_I2C_ENGINE(i2c_engine); + + if (speed) { + if (hw_engine->i2c_mask->DC_I2C_DDC1_START_STOP_TIMING_CNTL) + REG_UPDATE_N( + SPEED, 3, + FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_PRESCALE), hw_engine->reference_frequency / speed, + FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_THRESHOLD), 2, + FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_START_STOP_TIMING_CNTL), speed > 50 ? 2:1); + else + REG_UPDATE_N( + SPEED, 2, + FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_PRESCALE), hw_engine->reference_frequency / speed, + FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_THRESHOLD), 2); + } +} + +static inline void reset_hw_engine(struct engine *engine) +{ + struct i2c_hw_engine_dce110 *hw_engine = FROM_ENGINE(engine); + + REG_UPDATE_2( + DC_I2C_CONTROL, + DC_I2C_SW_STATUS_RESET, 1, + DC_I2C_SW_STATUS_RESET, 1); +} + +static bool is_hw_busy(struct engine *engine) +{ + struct i2c_hw_engine_dce110 *hw_engine = FROM_ENGINE(engine); + uint32_t i2c_sw_status = 0; + + REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status); + if (i2c_sw_status == DC_I2C_STATUS__DC_I2C_STATUS_IDLE) + return false; + + reset_hw_engine(engine); + + REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status); + return i2c_sw_status != DC_I2C_STATUS__DC_I2C_STATUS_IDLE; +} + + +#define STOP_TRANS_PREDICAT \ + ((hw_engine->transaction_count == 3) || \ + (request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE) || \ + (request->action & I2CAUX_TRANSACTION_ACTION_I2C_READ)) + +#define SET_I2C_TRANSACTION(id) \ + do { \ + REG_UPDATE_N(DC_I2C_TRANSACTION##id, 5, \ + FN(DC_I2C_TRANSACTION0, DC_I2C_STOP_ON_NACK0), 1, \ + FN(DC_I2C_TRANSACTION0, DC_I2C_START0), 1, \ + FN(DC_I2C_TRANSACTION0, DC_I2C_STOP0), STOP_TRANS_PREDICAT ? 1:0, \ + FN(DC_I2C_TRANSACTION0, DC_I2C_RW0), (0 != (request->action & I2CAUX_TRANSACTION_ACTION_I2C_READ)), \ + FN(DC_I2C_TRANSACTION0, DC_I2C_COUNT0), length); \ + if (STOP_TRANS_PREDICAT) \ + last_transaction = true; \ + } while (false) + + +static bool process_transaction( + struct i2c_hw_engine_dce110 *hw_engine, + struct i2c_request_transaction_data *request) +{ + uint32_t length = request->length; + uint8_t *buffer = request->data; + uint32_t value = 0; + + bool last_transaction = false; + + struct dc_context *ctx = NULL; + + ctx = hw_engine->base.base.base.ctx; + + + + switch (hw_engine->transaction_count) { + case 0: + SET_I2C_TRANSACTION(0); + break; + case 1: + SET_I2C_TRANSACTION(1); + break; + case 2: + SET_I2C_TRANSACTION(2); + break; + case 3: + SET_I2C_TRANSACTION(3); + break; + default: + /* TODO Warning ? */ + break; + } + + + /* Write the I2C address and I2C data + * into the hardware circular buffer, one byte per entry. + * As an example, the 7-bit I2C slave address for CRT monitor + * for reading DDC/EDID information is 0b1010001. + * For an I2C send operation, the LSB must be programmed to 0; + * for I2C receive operation, the LSB must be programmed to 1. */ + if (hw_engine->transaction_count == 0) { + value = REG_SET_4(DC_I2C_DATA, 0, + DC_I2C_DATA_RW, false, + DC_I2C_DATA, request->address, + DC_I2C_INDEX, 0, + DC_I2C_INDEX_WRITE, 1); + hw_engine->buffer_used_write = 0; + } else + value = REG_SET_2(DC_I2C_DATA, 0, + DC_I2C_DATA_RW, false, + DC_I2C_DATA, request->address); + + hw_engine->buffer_used_write++; + + if (!(request->action & I2CAUX_TRANSACTION_ACTION_I2C_READ)) { + while (length) { + REG_SET_2(DC_I2C_DATA, value, + DC_I2C_INDEX_WRITE, 0, + DC_I2C_DATA, *buffer++); + hw_engine->buffer_used_write++; + --length; + } + } + + ++hw_engine->transaction_count; + hw_engine->buffer_used_bytes += length + 1; + + return last_transaction; +} + +static void execute_transaction( + struct i2c_hw_engine_dce110 *hw_engine) +{ + REG_UPDATE_N(SETUP, 5, + FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_DATA_DRIVE_EN), 0, + FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_CLK_DRIVE_EN), 0, + FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_DATA_DRIVE_SEL), 0, + FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_INTRA_TRANSACTION_DELAY), 0, + FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_INTRA_BYTE_DELAY), 0); + + + REG_UPDATE_5(DC_I2C_CONTROL, + DC_I2C_SOFT_RESET, 0, + DC_I2C_SW_STATUS_RESET, 0, + DC_I2C_SEND_RESET, 0, + DC_I2C_GO, 0, + DC_I2C_TRANSACTION_COUNT, hw_engine->transaction_count - 1); + + /* start I2C transfer */ + REG_UPDATE(DC_I2C_CONTROL, DC_I2C_GO, 1); + + /* all transactions were executed and HW buffer became empty + * (even though it actually happens when status becomes DONE) */ + hw_engine->transaction_count = 0; + hw_engine->buffer_used_bytes = 0; +} + +static void submit_channel_request( + struct i2c_engine *engine, + struct i2c_request_transaction_data *request) +{ + request->status = I2C_CHANNEL_OPERATION_SUCCEEDED; + + if (!process_transaction(FROM_I2C_ENGINE(engine), request)) + return; + + if (is_hw_busy(&engine->base)) { + request->status = I2C_CHANNEL_OPERATION_ENGINE_BUSY; + return; + } + + execute_transaction(FROM_I2C_ENGINE(engine)); +} + +static void process_channel_reply( + struct i2c_engine *engine, + struct i2c_reply_transaction_data *reply) +{ + uint32_t length = reply->length; + uint8_t *buffer = reply->data; + + struct i2c_hw_engine_dce110 *hw_engine = + FROM_I2C_ENGINE(engine); + + + REG_SET_3(DC_I2C_DATA, 0, + DC_I2C_INDEX, hw_engine->buffer_used_write, + DC_I2C_DATA_RW, 1, + DC_I2C_INDEX_WRITE, 1); + + while (length) { + /* after reading the status, + * if the I2C operation executed successfully + * (i.e. DC_I2C_STATUS_DONE = 1) then the I2C controller + * should read data bytes from I2C circular data buffer */ + + uint32_t i2c_data; + + REG_GET(DC_I2C_DATA, DC_I2C_DATA, &i2c_data); + *buffer++ = i2c_data; + + --length; + } +} + +static enum i2c_channel_operation_result get_channel_status( + struct i2c_engine *i2c_engine, + uint8_t *returned_bytes) +{ + uint32_t i2c_sw_status = 0; + struct i2c_hw_engine_dce110 *hw_engine = FROM_I2C_ENGINE(i2c_engine); + uint32_t value = + REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status); + + if (i2c_sw_status == DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_SW) + return I2C_CHANNEL_OPERATION_ENGINE_BUSY; + else if (value & hw_engine->i2c_mask->DC_I2C_SW_STOPPED_ON_NACK) + return I2C_CHANNEL_OPERATION_NO_RESPONSE; + else if (value & hw_engine->i2c_mask->DC_I2C_SW_TIMEOUT) + return I2C_CHANNEL_OPERATION_TIMEOUT; + else if (value & hw_engine->i2c_mask->DC_I2C_SW_ABORTED) + return I2C_CHANNEL_OPERATION_FAILED; + else if (value & hw_engine->i2c_mask->DC_I2C_SW_DONE) + return I2C_CHANNEL_OPERATION_SUCCEEDED; + + /* + * this is the case when HW used for communication, I2C_SW_STATUS + * could be zero + */ + return I2C_CHANNEL_OPERATION_SUCCEEDED; +} + +static uint32_t get_hw_buffer_available_size( + const struct i2c_hw_engine *engine) +{ + return I2C_HW_BUFFER_SIZE - + FROM_I2C_HW_ENGINE(engine)->buffer_used_bytes; +} + +static uint32_t get_transaction_timeout( + const struct i2c_hw_engine *engine, + uint32_t length) +{ + uint32_t speed = engine->base.funcs->get_speed(&engine->base); + + uint32_t period_timeout; + uint32_t num_of_clock_stretches; + + if (!speed) + return 0; + + period_timeout = (1000 * TRANSACTION_TIMEOUT_IN_I2C_CLOCKS) / speed; + + num_of_clock_stretches = 1 + (length << 3) + 1; + num_of_clock_stretches += + (FROM_I2C_HW_ENGINE(engine)->buffer_used_bytes << 3) + + (FROM_I2C_HW_ENGINE(engine)->transaction_count << 1); + + return period_timeout * num_of_clock_stretches; +} + +static void destroy( + struct i2c_engine **i2c_engine) +{ + struct i2c_hw_engine_dce110 *engine_dce110 = + FROM_I2C_ENGINE(*i2c_engine); + + dal_i2c_hw_engine_destruct(&engine_dce110->base); + + dm_free(engine_dce110); + + *i2c_engine = NULL; +} + +static const struct i2c_engine_funcs i2c_engine_funcs = { + .destroy = destroy, + .get_speed = get_speed, + .set_speed = set_speed, + .setup_engine = setup_engine, + .submit_channel_request = submit_channel_request, + .process_channel_reply = process_channel_reply, + .get_channel_status = get_channel_status, + .acquire_engine = dal_i2c_hw_engine_acquire_engine, +}; + +static const struct engine_funcs engine_funcs = { + .release_engine = release_engine, + .get_engine_type = dal_i2c_hw_engine_get_engine_type, + .acquire = dal_i2c_engine_acquire, + .submit_request = dal_i2c_hw_engine_submit_request, +}; + +static const struct i2c_hw_engine_funcs i2c_hw_engine_funcs = { + .get_hw_buffer_available_size = get_hw_buffer_available_size, + .get_transaction_timeout = get_transaction_timeout, + .wait_on_operation_result = dal_i2c_hw_engine_wait_on_operation_result, +}; + +bool i2c_hw_engine_dce110_construct( + struct i2c_hw_engine_dce110 *hw_engine, + const struct i2c_hw_engine_dce110_create_arg *arg) +{ + uint32_t xtal_ref_div = 0; + + if (!arg->reference_frequency) + return false; + + if (!dal_i2c_hw_engine_construct(&hw_engine->base, arg->ctx)) + return false; + + hw_engine->base.base.base.funcs = &engine_funcs; + hw_engine->base.base.funcs = &i2c_engine_funcs; + hw_engine->base.funcs = &i2c_hw_engine_funcs; + hw_engine->base.default_speed = arg->default_speed; + + hw_engine->regs = arg->regs; + hw_engine->i2c_shift = arg->i2c_shift; + hw_engine->i2c_mask = arg->i2c_mask; + + hw_engine->engine_id = arg->engine_id; + + hw_engine->buffer_used_bytes = 0; + hw_engine->transaction_count = 0; + hw_engine->engine_keep_power_up_count = 1; + + + REG_GET(MICROSECOND_TIME_BASE_DIV, XTAL_REF_DIV, &xtal_ref_div); + + if (xtal_ref_div == 0) { + dm_logger_write( + hw_engine->base.base.base.ctx->logger, LOG_WARNING, + "Invalid base timer divider\n", + __func__); + xtal_ref_div = 2; + } + + /*Calculating Reference Clock by divding original frequency by + * XTAL_REF_DIV. + * At upper level, uint32_t reference_frequency = + * dal_i2caux_get_reference_clock(as) >> 1 + * which already divided by 2. So we need x2 to get original + * reference clock from ppll_info + */ + hw_engine->reference_frequency = + (arg->reference_frequency * 2) / xtal_ref_div; + + return true; +} + +struct i2c_engine *dal_i2c_hw_engine_dce110_create( + const struct i2c_hw_engine_dce110_create_arg *arg) +{ + struct i2c_hw_engine_dce110 *engine_dce10; + + if (!arg) { + ASSERT_CRITICAL(false); + return NULL; + } + + engine_dce10 = dm_alloc(sizeof(struct i2c_hw_engine_dce110)); + + if (!engine_dce10) { + ASSERT_CRITICAL(false); + return NULL; + } + + if (i2c_hw_engine_dce110_construct(engine_dce10, arg)) + return &engine_dce10->base.base; + + ASSERT_CRITICAL(false); + + dm_free(engine_dce10); + + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.h b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.h new file mode 100644 index 000000000000..c573c6459ec6 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.h @@ -0,0 +1,214 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_I2C_HW_ENGINE_DCE110_H__ +#define __DAL_I2C_HW_ENGINE_DCE110_H__ + +#define I2C_HW_ENGINE_COMMON_REG_LIST(id)\ + SRI(SETUP, DC_I2C_DDC, id),\ + SRI(SPEED, DC_I2C_DDC, id),\ + SR(DC_I2C_ARBITRATION),\ + SR(DC_I2C_CONTROL),\ + SR(DC_I2C_SW_STATUS),\ + SR(DC_I2C_TRANSACTION0),\ + SR(DC_I2C_TRANSACTION1),\ + SR(DC_I2C_TRANSACTION2),\ + SR(DC_I2C_TRANSACTION3),\ + SR(DC_I2C_DATA),\ + SR(MICROSECOND_TIME_BASE_DIV) + +#define I2C_SF(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define I2C_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh)\ + I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_ENABLE, mask_sh),\ + I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_TIME_LIMIT, mask_sh),\ + I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_DATA_DRIVE_EN, mask_sh),\ + I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_CLK_DRIVE_EN, mask_sh),\ + I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_DATA_DRIVE_SEL, mask_sh),\ + I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_INTRA_TRANSACTION_DELAY, mask_sh),\ + I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_INTRA_BYTE_DELAY, mask_sh),\ + I2C_SF(DC_I2C_ARBITRATION, DC_I2C_SW_DONE_USING_I2C_REG, mask_sh),\ + I2C_SF(DC_I2C_ARBITRATION, DC_I2C_NO_QUEUED_SW_GO, mask_sh),\ + I2C_SF(DC_I2C_ARBITRATION, DC_I2C_SW_PRIORITY, mask_sh),\ + I2C_SF(DC_I2C_CONTROL, DC_I2C_SOFT_RESET, mask_sh),\ + I2C_SF(DC_I2C_CONTROL, DC_I2C_SW_STATUS_RESET, mask_sh),\ + I2C_SF(DC_I2C_CONTROL, DC_I2C_GO, mask_sh),\ + I2C_SF(DC_I2C_CONTROL, DC_I2C_SEND_RESET, mask_sh),\ + I2C_SF(DC_I2C_CONTROL, DC_I2C_TRANSACTION_COUNT, mask_sh),\ + I2C_SF(DC_I2C_CONTROL, DC_I2C_DDC_SELECT, mask_sh),\ + I2C_SF(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_PRESCALE, mask_sh),\ + I2C_SF(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_THRESHOLD, mask_sh),\ + I2C_SF(DC_I2C_SW_STATUS, DC_I2C_SW_STOPPED_ON_NACK, mask_sh),\ + I2C_SF(DC_I2C_SW_STATUS, DC_I2C_SW_TIMEOUT, mask_sh),\ + I2C_SF(DC_I2C_SW_STATUS, DC_I2C_SW_ABORTED, mask_sh),\ + I2C_SF(DC_I2C_SW_STATUS, DC_I2C_SW_DONE, mask_sh),\ + I2C_SF(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, mask_sh),\ + I2C_SF(DC_I2C_TRANSACTION0, DC_I2C_STOP_ON_NACK0, mask_sh),\ + I2C_SF(DC_I2C_TRANSACTION0, DC_I2C_START0, mask_sh),\ + I2C_SF(DC_I2C_TRANSACTION0, DC_I2C_RW0, mask_sh),\ + I2C_SF(DC_I2C_TRANSACTION0, DC_I2C_STOP0, mask_sh),\ + I2C_SF(DC_I2C_TRANSACTION0, DC_I2C_COUNT0, mask_sh),\ + I2C_SF(DC_I2C_DATA, DC_I2C_DATA_RW, mask_sh),\ + I2C_SF(DC_I2C_DATA, DC_I2C_DATA, mask_sh),\ + I2C_SF(DC_I2C_DATA, DC_I2C_INDEX, mask_sh),\ + I2C_SF(DC_I2C_DATA, DC_I2C_INDEX_WRITE, mask_sh),\ + I2C_SF(MICROSECOND_TIME_BASE_DIV, XTAL_REF_DIV, mask_sh) + +#define I2C_COMMON_MASK_SH_LIST_DCE100(mask_sh)\ + I2C_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh) + +#define I2C_COMMON_MASK_SH_LIST_DCE110(mask_sh)\ + I2C_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh),\ + I2C_SF(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_START_STOP_TIMING_CNTL, mask_sh) + +struct dce110_i2c_hw_engine_shift { + uint8_t DC_I2C_DDC1_ENABLE; + uint8_t DC_I2C_DDC1_TIME_LIMIT; + uint8_t DC_I2C_DDC1_DATA_DRIVE_EN; + uint8_t DC_I2C_DDC1_CLK_DRIVE_EN; + uint8_t DC_I2C_DDC1_DATA_DRIVE_SEL; + uint8_t DC_I2C_DDC1_INTRA_TRANSACTION_DELAY; + uint8_t DC_I2C_DDC1_INTRA_BYTE_DELAY; + uint8_t DC_I2C_SW_DONE_USING_I2C_REG; + uint8_t DC_I2C_NO_QUEUED_SW_GO; + uint8_t DC_I2C_SW_PRIORITY; + uint8_t DC_I2C_SOFT_RESET; + uint8_t DC_I2C_SW_STATUS_RESET; + uint8_t DC_I2C_GO; + uint8_t DC_I2C_SEND_RESET; + uint8_t DC_I2C_TRANSACTION_COUNT; + uint8_t DC_I2C_DDC_SELECT; + uint8_t DC_I2C_DDC1_PRESCALE; + uint8_t DC_I2C_DDC1_THRESHOLD; + uint8_t DC_I2C_DDC1_START_STOP_TIMING_CNTL; + uint8_t DC_I2C_SW_STOPPED_ON_NACK; + uint8_t DC_I2C_SW_TIMEOUT; + uint8_t DC_I2C_SW_ABORTED; + uint8_t DC_I2C_SW_DONE; + uint8_t DC_I2C_SW_STATUS; + uint8_t DC_I2C_STOP_ON_NACK0; + uint8_t DC_I2C_START0; + uint8_t DC_I2C_RW0; + uint8_t DC_I2C_STOP0; + uint8_t DC_I2C_COUNT0; + uint8_t DC_I2C_DATA_RW; + uint8_t DC_I2C_DATA; + uint8_t DC_I2C_INDEX; + uint8_t DC_I2C_INDEX_WRITE; + uint8_t XTAL_REF_DIV; +}; + +struct dce110_i2c_hw_engine_mask { + uint32_t DC_I2C_DDC1_ENABLE; + uint32_t DC_I2C_DDC1_TIME_LIMIT; + uint32_t DC_I2C_DDC1_DATA_DRIVE_EN; + uint32_t DC_I2C_DDC1_CLK_DRIVE_EN; + uint32_t DC_I2C_DDC1_DATA_DRIVE_SEL; + uint32_t DC_I2C_DDC1_INTRA_TRANSACTION_DELAY; + uint32_t DC_I2C_DDC1_INTRA_BYTE_DELAY; + uint32_t DC_I2C_SW_DONE_USING_I2C_REG; + uint32_t DC_I2C_NO_QUEUED_SW_GO; + uint32_t DC_I2C_SW_PRIORITY; + uint32_t DC_I2C_SOFT_RESET; + uint32_t DC_I2C_SW_STATUS_RESET; + uint32_t DC_I2C_GO; + uint32_t DC_I2C_SEND_RESET; + uint32_t DC_I2C_TRANSACTION_COUNT; + uint32_t DC_I2C_DDC_SELECT; + uint32_t DC_I2C_DDC1_PRESCALE; + uint32_t DC_I2C_DDC1_THRESHOLD; + uint32_t DC_I2C_DDC1_START_STOP_TIMING_CNTL; + uint32_t DC_I2C_SW_STOPPED_ON_NACK; + uint32_t DC_I2C_SW_TIMEOUT; + uint32_t DC_I2C_SW_ABORTED; + uint32_t DC_I2C_SW_DONE; + uint32_t DC_I2C_SW_STATUS; + uint32_t DC_I2C_STOP_ON_NACK0; + uint32_t DC_I2C_START0; + uint32_t DC_I2C_RW0; + uint32_t DC_I2C_STOP0; + uint32_t DC_I2C_COUNT0; + uint32_t DC_I2C_DATA_RW; + uint32_t DC_I2C_DATA; + uint32_t DC_I2C_INDEX; + uint32_t DC_I2C_INDEX_WRITE; + uint32_t XTAL_REF_DIV; +}; + +struct dce110_i2c_hw_engine_registers { + uint32_t SETUP; + uint32_t SPEED; + uint32_t DC_I2C_ARBITRATION; + uint32_t DC_I2C_CONTROL; + uint32_t DC_I2C_SW_STATUS; + uint32_t DC_I2C_TRANSACTION0; + uint32_t DC_I2C_TRANSACTION1; + uint32_t DC_I2C_TRANSACTION2; + uint32_t DC_I2C_TRANSACTION3; + uint32_t DC_I2C_DATA; + uint32_t MICROSECOND_TIME_BASE_DIV; +}; + +struct i2c_hw_engine_dce110 { + struct i2c_hw_engine base; + const struct dce110_i2c_hw_engine_registers *regs; + const struct dce110_i2c_hw_engine_shift *i2c_shift; + const struct dce110_i2c_hw_engine_mask *i2c_mask; + struct { + uint32_t DC_I2C_DDCX_SETUP; + uint32_t DC_I2C_DDCX_SPEED; + } addr; + uint32_t engine_id; + /* expressed in kilohertz */ + uint32_t reference_frequency; + /* number of bytes currently used in HW buffer */ + uint32_t buffer_used_bytes; + /* number of bytes used for write transaction in HW buffer + * - this will be used as the index to read from*/ + uint32_t buffer_used_write; + /* number of pending transactions (before GO) */ + uint32_t transaction_count; + uint32_t engine_keep_power_up_count; +}; + +struct i2c_hw_engine_dce110_create_arg { + uint32_t engine_id; + uint32_t reference_frequency; + uint32_t default_speed; + struct dc_context *ctx; + const struct dce110_i2c_hw_engine_registers *regs; + const struct dce110_i2c_hw_engine_shift *i2c_shift; + const struct dce110_i2c_hw_engine_mask *i2c_mask; +}; + +struct i2c_engine *dal_i2c_hw_engine_dce110_create( + const struct i2c_hw_engine_dce110_create_arg *arg); + +bool i2c_hw_engine_dce110_construct( + struct i2c_hw_engine_dce110 *engine_dce110, + const struct i2c_hw_engine_dce110_create_arg *arg); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_sw_engine_dce110.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_sw_engine_dce110.c new file mode 100644 index 000000000000..996813d9165f --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_sw_engine_dce110.c @@ -0,0 +1,171 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* + * Pre-requisites: headers required by header of this unit + */ +#include "include/i2caux_interface.h" +#include "../engine.h" +#include "../i2c_engine.h" +#include "../i2c_sw_engine.h" + +/* + * Header of this unit + */ + +#include "i2c_sw_engine_dce110.h" + +/* + * Post-requisites: headers required by this unit + */ + +/* + * This unit + */ + +/* + * @brief + * Cast 'struct i2c_sw_engine *' + * to 'struct i2c_sw_engine_dce110 *' + */ +#define FROM_I2C_SW_ENGINE(ptr) \ + container_of((ptr), struct i2c_sw_engine_dce110, base) +/* + * @brief + * Cast 'struct i2c_engine *' + * to 'struct i2c_sw_engine_dce80 *' + */ +#define FROM_I2C_ENGINE(ptr) \ + FROM_I2C_SW_ENGINE(container_of((ptr), struct i2c_sw_engine, base)) + +/* + * @brief + * Cast 'struct engine *' + * to 'struct i2c_sw_engine_dce80 *' + */ +#define FROM_ENGINE(ptr) \ + FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base)) + +static void release_engine( + struct engine *engine) +{ +} + +static void destruct( + struct i2c_sw_engine_dce110 *engine) +{ + dal_i2c_sw_engine_destruct(&engine->base); +} + +static void destroy( + struct i2c_engine **engine) +{ + struct i2c_sw_engine_dce110 *sw_engine = FROM_I2C_ENGINE(*engine); + + destruct(sw_engine); + + dm_free(sw_engine); + + *engine = NULL; +} + +static bool acquire_engine( + struct i2c_engine *engine, + struct ddc *ddc_handle) +{ + return dal_i2caux_i2c_sw_engine_acquire_engine(engine, ddc_handle); +} + +static const struct i2c_engine_funcs i2c_engine_funcs = { + .acquire_engine = acquire_engine, + .destroy = destroy, + .get_speed = dal_i2c_sw_engine_get_speed, + .set_speed = dal_i2c_sw_engine_set_speed, + .setup_engine = dal_i2c_engine_setup_i2c_engine, + .submit_channel_request = dal_i2c_sw_engine_submit_channel_request, + .process_channel_reply = dal_i2c_engine_process_channel_reply, + .get_channel_status = dal_i2c_sw_engine_get_channel_status, +}; + +static const struct engine_funcs engine_funcs = { + .release_engine = release_engine, + .get_engine_type = dal_i2c_sw_engine_get_engine_type, + .acquire = dal_i2c_engine_acquire, + .submit_request = dal_i2c_sw_engine_submit_request, +}; + +static bool construct( + struct i2c_sw_engine_dce110 *engine_dce110, + const struct i2c_sw_engine_dce110_create_arg *arg_dce110) +{ + struct i2c_sw_engine_create_arg arg_base; + + arg_base.ctx = arg_dce110->ctx; + arg_base.default_speed = arg_dce110->default_speed; + + if (!dal_i2c_sw_engine_construct( + &engine_dce110->base, &arg_base)) { + ASSERT_CRITICAL(false); + return false; + } + + /*struct engine struct engine_funcs*/ + engine_dce110->base.base.base.funcs = &engine_funcs; + /*struct i2c_engine struct i2c_engine_funcs*/ + engine_dce110->base.base.funcs = &i2c_engine_funcs; + engine_dce110->base.default_speed = arg_dce110->default_speed; + engine_dce110->engine_id = arg_dce110->engine_id; + + return true; +} + +struct i2c_engine *dal_i2c_sw_engine_dce110_create( + const struct i2c_sw_engine_dce110_create_arg *arg) +{ + struct i2c_sw_engine_dce110 *engine_dce110; + + if (!arg) { + ASSERT_CRITICAL(false); + return NULL; + } + + engine_dce110 = dm_alloc(sizeof(struct i2c_sw_engine_dce110)); + + if (!engine_dce110) { + ASSERT_CRITICAL(false); + return NULL; + } + + if (construct(engine_dce110, arg)) + return &engine_dce110->base.base; + + ASSERT_CRITICAL(false); + + dm_free(engine_dce110); + + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_sw_engine_dce110.h b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_sw_engine_dce110.h new file mode 100644 index 000000000000..c48c61f540a8 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_sw_engine_dce110.h @@ -0,0 +1,43 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_I2C_SW_ENGINE_DCE110_H__ +#define __DAL_I2C_SW_ENGINE_DCE110_H__ + +struct i2c_sw_engine_dce110 { + struct i2c_sw_engine base; + uint32_t engine_id; +}; + +struct i2c_sw_engine_dce110_create_arg { + uint32_t engine_id; + uint32_t default_speed; + struct dc_context *ctx; +}; + +struct i2c_engine *dal_i2c_sw_engine_dce110_create( + const struct i2c_sw_engine_dce110_create_arg *arg); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.c new file mode 100644 index 000000000000..1c00ed0010d9 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.c @@ -0,0 +1,323 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* + * Pre-requisites: headers required by header of this unit + */ +#include "include/i2caux_interface.h" +#include "../i2caux.h" +#include "../engine.h" +#include "../i2c_engine.h" +#include "../i2c_sw_engine.h" +#include "../i2c_hw_engine.h" + +/* + * Header of this unit + */ +#include "i2caux_dce110.h" + +#include "i2c_sw_engine_dce110.h" +#include "i2c_hw_engine_dce110.h" +#include "aux_engine_dce110.h" + +/* + * Post-requisites: headers required by this unit + */ + +/* + * This unit + */ +/*cast pointer to struct i2caux TO pointer to struct i2caux_dce110*/ +#define FROM_I2C_AUX(ptr) \ + container_of((ptr), struct i2caux_dce110, base) + +static void destruct( + struct i2caux_dce110 *i2caux_dce110) +{ + dal_i2caux_destruct(&i2caux_dce110->base); +} + +static void destroy( + struct i2caux **i2c_engine) +{ + struct i2caux_dce110 *i2caux_dce110 = FROM_I2C_AUX(*i2c_engine); + + destruct(i2caux_dce110); + + dm_free(i2caux_dce110); + + *i2c_engine = NULL; +} + +static struct i2c_engine *acquire_i2c_hw_engine( + struct i2caux *i2caux, + struct ddc *ddc) +{ + struct i2caux_dce110 *i2caux_dce110 = FROM_I2C_AUX(i2caux); + + struct i2c_engine *engine = NULL; + /* generic hw engine is not used for EDID read + * It may be needed for external i2c device, like thermal chip, + * TODO will be implemented when needed. + * check dce80 bool non_generic for generic hw engine; + */ + + if (!ddc) + return NULL; + + if (ddc->hw_info.hw_supported) { + enum gpio_ddc_line line = dal_ddc_get_line(ddc); + + if (line < GPIO_DDC_LINE_COUNT) + engine = i2caux->i2c_hw_engines[line]; + } + + if (!engine) + return NULL; + + if (!i2caux_dce110->i2c_hw_buffer_in_use && + engine->base.funcs->acquire(&engine->base, ddc)) { + i2caux_dce110->i2c_hw_buffer_in_use = true; + return engine; + } + + return NULL; +} + +static void release_engine( + struct i2caux *i2caux, + struct engine *engine) +{ + struct i2caux_dce110 *i2caux_dce110 = FROM_I2C_AUX(i2caux); + + if (engine->funcs->get_engine_type(engine) == + I2CAUX_ENGINE_TYPE_I2C_DDC_HW) + i2caux_dce110->i2c_hw_buffer_in_use = false; + + dal_i2caux_release_engine(i2caux, engine); +} + +static const enum gpio_ddc_line hw_ddc_lines[] = { + GPIO_DDC_LINE_DDC1, + GPIO_DDC_LINE_DDC2, + GPIO_DDC_LINE_DDC3, + GPIO_DDC_LINE_DDC4, + GPIO_DDC_LINE_DDC5, + GPIO_DDC_LINE_DDC6, +}; + +static const enum gpio_ddc_line hw_aux_lines[] = { + GPIO_DDC_LINE_DDC1, + GPIO_DDC_LINE_DDC2, + GPIO_DDC_LINE_DDC3, + GPIO_DDC_LINE_DDC4, + GPIO_DDC_LINE_DDC5, + GPIO_DDC_LINE_DDC6, +}; + +/* function table */ +static const struct i2caux_funcs i2caux_funcs = { + .destroy = destroy, + .acquire_i2c_hw_engine = acquire_i2c_hw_engine, + .release_engine = release_engine, + .acquire_i2c_sw_engine = dal_i2caux_acquire_i2c_sw_engine, + .acquire_aux_engine = dal_i2caux_acquire_aux_engine, +}; + +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" + +/* set register offset */ +#define SR(reg_name)\ + .reg_name = mm ## reg_name + +/* set register offset with instance */ +#define SRI(reg_name, block, id)\ + .reg_name = mm ## block ## id ## _ ## reg_name + +#define aux_regs(id)\ +[id] = {\ + AUX_COMMON_REG_LIST(id), \ + .AUX_RESET_MASK = AUX_CONTROL__AUX_RESET_MASK \ +} + +#define hw_engine_regs(id)\ +{\ + I2C_HW_ENGINE_COMMON_REG_LIST(id) \ +} + +static const struct dce110_aux_registers dce110_aux_regs[] = { + aux_regs(0), + aux_regs(1), + aux_regs(2), + aux_regs(3), + aux_regs(4), + aux_regs(5) +}; + +static const struct dce110_i2c_hw_engine_registers i2c_hw_engine_regs[] = { + hw_engine_regs(1), + hw_engine_regs(2), + hw_engine_regs(3), + hw_engine_regs(4), + hw_engine_regs(5), + hw_engine_regs(6) +}; + +static const struct dce110_i2c_hw_engine_shift i2c_shift = { + I2C_COMMON_MASK_SH_LIST_DCE110(__SHIFT) +}; + +static const struct dce110_i2c_hw_engine_mask i2c_mask = { + I2C_COMMON_MASK_SH_LIST_DCE110(_MASK) +}; + +bool dal_i2caux_dce110_construct( + struct i2caux_dce110 *i2caux_dce110, + struct dc_context *ctx, + const struct dce110_aux_registers aux_regs[], + const struct dce110_i2c_hw_engine_registers i2c_hw_engine_regs[], + const struct dce110_i2c_hw_engine_shift *i2c_shift, + const struct dce110_i2c_hw_engine_mask *i2c_mask) +{ + uint32_t i = 0; + uint32_t reference_frequency = 0; + bool use_i2c_sw_engine = false; + struct i2caux *base = NULL; + /*TODO: For CZ bring up, if dal_i2caux_get_reference_clock + * does not return 48KHz, we need hard coded for 48Khz. + * Some BIOS setting incorrect cause this + * For production, we always get value from BIOS*/ + reference_frequency = + dal_i2caux_get_reference_clock(ctx->dc_bios) >> 1; + + base = &i2caux_dce110->base; + + if (!dal_i2caux_construct(base, ctx)) { + ASSERT_CRITICAL(false); + return false; + } + + i2caux_dce110->base.funcs = &i2caux_funcs; + i2caux_dce110->i2c_hw_buffer_in_use = false; + /* Create I2C engines (DDC lines per connector) + * different I2C/AUX usage cases, DDC, Generic GPIO, AUX. + */ + do { + enum gpio_ddc_line line_id = hw_ddc_lines[i]; + + struct i2c_hw_engine_dce110_create_arg hw_arg_dce110; + + if (use_i2c_sw_engine) { + struct i2c_sw_engine_dce110_create_arg sw_arg; + + sw_arg.engine_id = i; + sw_arg.default_speed = base->default_i2c_sw_speed; + sw_arg.ctx = ctx; + base->i2c_sw_engines[line_id] = + dal_i2c_sw_engine_dce110_create(&sw_arg); + } + + hw_arg_dce110.engine_id = i; + hw_arg_dce110.reference_frequency = reference_frequency; + hw_arg_dce110.default_speed = base->default_i2c_hw_speed; + hw_arg_dce110.ctx = ctx; + hw_arg_dce110.regs = &i2c_hw_engine_regs[i]; + hw_arg_dce110.i2c_shift = i2c_shift; + hw_arg_dce110.i2c_mask = i2c_mask; + + base->i2c_hw_engines[line_id] = + dal_i2c_hw_engine_dce110_create(&hw_arg_dce110); + + ++i; + } while (i < ARRAY_SIZE(hw_ddc_lines)); + + /* Create AUX engines for all lines which has assisted HW AUX + * 'i' (loop counter) used as DDC/AUX engine_id */ + + i = 0; + + do { + enum gpio_ddc_line line_id = hw_aux_lines[i]; + + struct aux_engine_dce110_init_data aux_init_data; + + aux_init_data.engine_id = i; + aux_init_data.timeout_period = base->aux_timeout_period; + aux_init_data.ctx = ctx; + aux_init_data.regs = &aux_regs[i]; + + base->aux_engines[line_id] = + dal_aux_engine_dce110_create(&aux_init_data); + + ++i; + } while (i < ARRAY_SIZE(hw_aux_lines)); + + /*TODO Generic I2C SW and HW*/ + + return true; +} + +/* + * dal_i2caux_dce110_create + * + * @brief + * public interface to allocate memory for DCE11 I2CAUX + * + * @param + * struct adapter_service *as - [in] + * struct dc_context *ctx - [in] + * + * @return + * pointer to the base struct of DCE11 I2CAUX + */ +struct i2caux *dal_i2caux_dce110_create( + struct dc_context *ctx) +{ + struct i2caux_dce110 *i2caux_dce110 = + dm_alloc(sizeof(struct i2caux_dce110)); + + if (!i2caux_dce110) { + ASSERT_CRITICAL(false); + return NULL; + } + + if (dal_i2caux_dce110_construct( + i2caux_dce110, + ctx, + dce110_aux_regs, + i2c_hw_engine_regs, + &i2c_shift, + &i2c_mask)) + return &i2caux_dce110->base; + + ASSERT_CRITICAL(false); + + dm_free(i2caux_dce110); + + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.h b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.h new file mode 100644 index 000000000000..fd1cc23c3d70 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.h @@ -0,0 +1,53 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_I2C_AUX_DCE110_H__ +#define __DAL_I2C_AUX_DCE110_H__ + +#include "../i2caux.h" + +struct i2caux_dce110 { + struct i2caux base; + /* indicate the I2C HW circular buffer is in use */ + bool i2c_hw_buffer_in_use; +}; + +struct dce110_aux_registers; +struct dce110_i2c_hw_engine_registers; +struct dce110_i2c_hw_engine_shift; +struct dce110_i2c_hw_engine_mask; + +struct i2caux *dal_i2caux_dce110_create( + struct dc_context *ctx); + +bool dal_i2caux_dce110_construct( + struct i2caux_dce110 *i2caux_dce110, + struct dc_context *ctx, + const struct dce110_aux_registers *aux_regs, + const struct dce110_i2c_hw_engine_registers *i2c_hw_engine_regs, + const struct dce110_i2c_hw_engine_shift *i2c_shift, + const struct dce110_i2c_hw_engine_mask *i2c_mask); + +#endif /* __DAL_I2C_AUX_DCE110_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.c new file mode 100644 index 000000000000..d74f3f15d600 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.c @@ -0,0 +1,140 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "include/i2caux_interface.h" +#include "../i2caux.h" +#include "../engine.h" +#include "../i2c_engine.h" +#include "../i2c_sw_engine.h" +#include "../i2c_hw_engine.h" + +#include "../dce110/i2caux_dce110.h" +#include "i2caux_dce112.h" + +#include "../dce110/aux_engine_dce110.h" + +#include "../dce110/i2c_hw_engine_dce110.h" + +#include "dce/dce_11_2_d.h" +#include "dce/dce_11_2_sh_mask.h" + +/* set register offset */ +#define SR(reg_name)\ + .reg_name = mm ## reg_name + +/* set register offset with instance */ +#define SRI(reg_name, block, id)\ + .reg_name = mm ## block ## id ## _ ## reg_name + +#define aux_regs(id)\ +[id] = {\ + AUX_COMMON_REG_LIST(id), \ + .AUX_RESET_MASK = AUX_CONTROL__AUX_RESET_MASK \ +} + +#define hw_engine_regs(id)\ +{\ + I2C_HW_ENGINE_COMMON_REG_LIST(id) \ +} + +static const struct dce110_aux_registers dce112_aux_regs[] = { + aux_regs(0), + aux_regs(1), + aux_regs(2), + aux_regs(3), + aux_regs(4), + aux_regs(5), +}; + +static const struct dce110_i2c_hw_engine_registers dce112_hw_engine_regs[] = { + hw_engine_regs(1), + hw_engine_regs(2), + hw_engine_regs(3), + hw_engine_regs(4), + hw_engine_regs(5), + hw_engine_regs(6) +}; + +static const struct dce110_i2c_hw_engine_shift i2c_shift = { + I2C_COMMON_MASK_SH_LIST_DCE110(__SHIFT) +}; + +static const struct dce110_i2c_hw_engine_mask i2c_mask = { + I2C_COMMON_MASK_SH_LIST_DCE110(_MASK) +}; + +static bool construct( + struct i2caux_dce110 *i2caux_dce110, + struct dc_context *ctx) +{ + if (!dal_i2caux_dce110_construct( + i2caux_dce110, + ctx, + dce112_aux_regs, + dce112_hw_engine_regs, + &i2c_shift, + &i2c_mask)) { + ASSERT_CRITICAL(false); + return false; + } + + return true; +} + +/* + * dal_i2caux_dce110_create + * + * @brief + * public interface to allocate memory for DCE11 I2CAUX + * + * @param + * struct adapter_service *as - [in] + * struct dc_context *ctx - [in] + * + * @return + * pointer to the base struct of DCE11 I2CAUX + */ +struct i2caux *dal_i2caux_dce112_create( + struct dc_context *ctx) +{ + struct i2caux_dce110 *i2caux_dce110 = + dm_alloc(sizeof(struct i2caux_dce110)); + + if (!i2caux_dce110) { + ASSERT_CRITICAL(false); + return NULL; + } + + if (construct(i2caux_dce110, ctx)) + return &i2caux_dce110->base; + + ASSERT_CRITICAL(false); + + dm_free(i2caux_dce110); + + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.h b/drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.h new file mode 100644 index 000000000000..8d35453c25b6 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.h @@ -0,0 +1,32 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_I2C_AUX_DCE112_H__ +#define __DAL_I2C_AUX_DCE112_H__ + +struct i2caux *dal_i2caux_dce112_create( + struct dc_context *ctx); + +#endif /* __DAL_I2C_AUX_DCE112_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.c new file mode 100644 index 000000000000..423c38ac880c --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.c @@ -0,0 +1,885 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* + * Pre-requisites: headers required by header of this unit + */ +#include "include/i2caux_interface.h" +#include "../engine.h" +#include "../i2c_engine.h" +#include "../i2c_hw_engine.h" +#include "../i2c_generic_hw_engine.h" +/* + * Header of this unit + */ + +#include "i2c_hw_engine_dce80.h" + +/* + * Post-requisites: headers required by this unit + */ + +#include "dce/dce_8_0_d.h" +#include "dce/dce_8_0_sh_mask.h" +/* + * This unit + */ + +enum dc_i2c_status { + DC_I2C_STATUS__DC_I2C_STATUS_IDLE, + DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_SW, + DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_HW +}; + +enum dc_i2c_arbitration { + DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_NORMAL, + DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_HIGH +}; + +enum { + /* No timeout in HW + * (timeout implemented in SW by querying status) */ + I2C_SETUP_TIME_LIMIT = 255, + I2C_HW_BUFFER_SIZE = 144 +}; + +/* + * @brief + * Cast 'struct i2c_hw_engine *' + * to 'struct i2c_hw_engine_dce80 *' + */ +#define FROM_I2C_HW_ENGINE(ptr) \ + container_of((ptr), struct i2c_hw_engine_dce80, base) + +/* + * @brief + * Cast pointer to 'struct i2c_engine *' + * to pointer to 'struct i2c_hw_engine_dce80 *' + */ +#define FROM_I2C_ENGINE(ptr) \ + FROM_I2C_HW_ENGINE(container_of((ptr), struct i2c_hw_engine, base)) + +/* + * @brief + * Cast pointer to 'struct engine *' + * to 'pointer to struct i2c_hw_engine_dce80 *' + */ +#define FROM_ENGINE(ptr) \ + FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base)) + +static void disable_i2c_hw_engine( + struct i2c_hw_engine_dce80 *engine) +{ + const uint32_t addr = engine->addr.DC_I2C_DDCX_SETUP; + uint32_t value = 0; + + struct dc_context *ctx = NULL; + + ctx = engine->base.base.base.ctx; + + value = dm_read_reg(ctx, addr); + + set_reg_field_value( + value, + 0, + DC_I2C_DDC1_SETUP, + DC_I2C_DDC1_ENABLE); + + dm_write_reg(ctx, addr, value); +} + +static void release_engine( + struct engine *engine) +{ + struct i2c_hw_engine_dce80 *hw_engine = FROM_ENGINE(engine); + + struct i2c_engine *base = NULL; + bool safe_to_reset; + uint32_t value = 0; + + base = &hw_engine->base.base; + + /* Restore original HW engine speed */ + + base->funcs->set_speed(base, hw_engine->base.original_speed); + + /* Release I2C */ + { + value = dm_read_reg(engine->ctx, mmDC_I2C_ARBITRATION); + + set_reg_field_value( + value, + 1, + DC_I2C_ARBITRATION, + DC_I2C_SW_DONE_USING_I2C_REG); + + dm_write_reg(engine->ctx, mmDC_I2C_ARBITRATION, value); + } + + /* Reset HW engine */ + { + uint32_t i2c_sw_status = 0; + + value = dm_read_reg(engine->ctx, mmDC_I2C_SW_STATUS); + + i2c_sw_status = get_reg_field_value( + value, + DC_I2C_SW_STATUS, + DC_I2C_SW_STATUS); + /* if used by SW, safe to reset */ + safe_to_reset = (i2c_sw_status == 1); + } + { + value = dm_read_reg(engine->ctx, mmDC_I2C_CONTROL); + + if (safe_to_reset) + set_reg_field_value( + value, + 1, + DC_I2C_CONTROL, + DC_I2C_SOFT_RESET); + + set_reg_field_value( + value, + 1, + DC_I2C_CONTROL, + DC_I2C_SW_STATUS_RESET); + + dm_write_reg(engine->ctx, mmDC_I2C_CONTROL, value); + } + + /* HW I2c engine - clock gating feature */ + if (!hw_engine->engine_keep_power_up_count) + disable_i2c_hw_engine(hw_engine); +} + +static void destruct( + struct i2c_hw_engine_dce80 *engine) +{ + dal_i2c_hw_engine_destruct(&engine->base); +} + +static void destroy( + struct i2c_engine **i2c_engine) +{ + struct i2c_hw_engine_dce80 *engine = FROM_I2C_ENGINE(*i2c_engine); + + destruct(engine); + + dm_free(engine); + + *i2c_engine = NULL; +} + +static bool setup_engine( + struct i2c_engine *i2c_engine) +{ + uint32_t value = 0; + struct i2c_hw_engine_dce80 *engine = FROM_I2C_ENGINE(i2c_engine); + + /* Program pin select */ + { + const uint32_t addr = mmDC_I2C_CONTROL; + + value = dm_read_reg(i2c_engine->base.ctx, addr); + + set_reg_field_value( + value, + 0, + DC_I2C_CONTROL, + DC_I2C_GO); + + set_reg_field_value( + value, + 0, + DC_I2C_CONTROL, + DC_I2C_SOFT_RESET); + + set_reg_field_value( + value, + 0, + DC_I2C_CONTROL, + DC_I2C_SEND_RESET); + + set_reg_field_value( + value, + 0, + DC_I2C_CONTROL, + DC_I2C_SW_STATUS_RESET); + + set_reg_field_value( + value, + 0, + DC_I2C_CONTROL, + DC_I2C_TRANSACTION_COUNT); + + set_reg_field_value( + value, + engine->engine_id, + DC_I2C_CONTROL, + DC_I2C_DDC_SELECT); + + dm_write_reg(i2c_engine->base.ctx, addr, value); + } + + /* Program time limit */ + { + const uint32_t addr = engine->addr.DC_I2C_DDCX_SETUP; + + value = dm_read_reg(i2c_engine->base.ctx, addr); + + set_reg_field_value( + value, + I2C_SETUP_TIME_LIMIT, + DC_I2C_DDC1_SETUP, + DC_I2C_DDC1_TIME_LIMIT); + + set_reg_field_value( + value, + 1, + DC_I2C_DDC1_SETUP, + DC_I2C_DDC1_ENABLE); + + dm_write_reg(i2c_engine->base.ctx, addr, value); + } + + /* Program HW priority + * set to High - interrupt software I2C at any time + * Enable restart of SW I2C that was interrupted by HW + * disable queuing of software while I2C is in use by HW */ + { + value = dm_read_reg(i2c_engine->base.ctx, + mmDC_I2C_ARBITRATION); + + set_reg_field_value( + value, + 0, + DC_I2C_ARBITRATION, + DC_I2C_NO_QUEUED_SW_GO); + + set_reg_field_value( + value, + DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_NORMAL, + DC_I2C_ARBITRATION, + DC_I2C_SW_PRIORITY); + + dm_write_reg(i2c_engine->base.ctx, + mmDC_I2C_ARBITRATION, value); + } + + return true; +} + +static uint32_t get_speed( + const struct i2c_engine *i2c_engine) +{ + const struct i2c_hw_engine_dce80 *engine = FROM_I2C_ENGINE(i2c_engine); + + const uint32_t addr = engine->addr.DC_I2C_DDCX_SPEED; + + uint32_t pre_scale = 0; + + uint32_t value = dm_read_reg(i2c_engine->base.ctx, addr); + + pre_scale = get_reg_field_value( + value, + DC_I2C_DDC1_SPEED, + DC_I2C_DDC1_PRESCALE); + + /* [anaumov] it seems following is unnecessary */ + /*ASSERT(value.bits.DC_I2C_DDC1_PRESCALE);*/ + + return pre_scale ? + engine->reference_frequency / pre_scale : + engine->base.default_speed; +} + +static void set_speed( + struct i2c_engine *i2c_engine, + uint32_t speed) +{ + struct i2c_hw_engine_dce80 *engine = FROM_I2C_ENGINE(i2c_engine); + + if (speed) { + const uint32_t addr = engine->addr.DC_I2C_DDCX_SPEED; + + uint32_t value = dm_read_reg(i2c_engine->base.ctx, addr); + + set_reg_field_value( + value, + engine->reference_frequency / speed, + DC_I2C_DDC1_SPEED, + DC_I2C_DDC1_PRESCALE); + + set_reg_field_value( + value, + 2, + DC_I2C_DDC1_SPEED, + DC_I2C_DDC1_THRESHOLD); + + dm_write_reg(i2c_engine->base.ctx, addr, value); + } +} + +static inline void reset_hw_engine(struct engine *engine) +{ + uint32_t value = dm_read_reg(engine->ctx, mmDC_I2C_CONTROL); + + set_reg_field_value( + value, + 1, + DC_I2C_CONTROL, + DC_I2C_SOFT_RESET); + + set_reg_field_value( + value, + 1, + DC_I2C_CONTROL, + DC_I2C_SW_STATUS_RESET); + + dm_write_reg(engine->ctx, mmDC_I2C_CONTROL, value); +} + +static bool is_hw_busy(struct engine *engine) +{ + uint32_t i2c_sw_status = 0; + + uint32_t value = dm_read_reg(engine->ctx, mmDC_I2C_SW_STATUS); + + i2c_sw_status = get_reg_field_value( + value, + DC_I2C_SW_STATUS, + DC_I2C_SW_STATUS); + + if (i2c_sw_status == DC_I2C_STATUS__DC_I2C_STATUS_IDLE) + return false; + + reset_hw_engine(engine); + + value = dm_read_reg(engine->ctx, mmDC_I2C_SW_STATUS); + + i2c_sw_status = get_reg_field_value( + value, + DC_I2C_SW_STATUS, + DC_I2C_SW_STATUS); + + return i2c_sw_status != DC_I2C_STATUS__DC_I2C_STATUS_IDLE; +} + +/* + * @brief + * DC_GPIO_DDC MM register offsets + */ +static const uint32_t transaction_addr[] = { + mmDC_I2C_TRANSACTION0, + mmDC_I2C_TRANSACTION1, + mmDC_I2C_TRANSACTION2, + mmDC_I2C_TRANSACTION3 +}; + +static bool process_transaction( + struct i2c_hw_engine_dce80 *engine, + struct i2c_request_transaction_data *request) +{ + uint32_t length = request->length; + uint8_t *buffer = request->data; + + bool last_transaction = false; + uint32_t value = 0; + + struct dc_context *ctx = NULL; + + ctx = engine->base.base.base.ctx; + + { + const uint32_t addr = + transaction_addr[engine->transaction_count]; + + value = dm_read_reg(ctx, addr); + + set_reg_field_value( + value, + 1, + DC_I2C_TRANSACTION0, + DC_I2C_STOP_ON_NACK0); + + set_reg_field_value( + value, + 1, + DC_I2C_TRANSACTION0, + DC_I2C_START0); + + if ((engine->transaction_count == 3) || + (request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE) || + (request->action & I2CAUX_TRANSACTION_ACTION_I2C_READ)) { + + set_reg_field_value( + value, + 1, + DC_I2C_TRANSACTION0, + DC_I2C_STOP0); + + last_transaction = true; + } else + set_reg_field_value( + value, + 0, + DC_I2C_TRANSACTION0, + DC_I2C_STOP0); + + set_reg_field_value( + value, + (0 != (request->action & + I2CAUX_TRANSACTION_ACTION_I2C_READ)), + DC_I2C_TRANSACTION0, + DC_I2C_RW0); + + set_reg_field_value( + value, + length, + DC_I2C_TRANSACTION0, + DC_I2C_COUNT0); + + dm_write_reg(ctx, addr, value); + } + + /* Write the I2C address and I2C data + * into the hardware circular buffer, one byte per entry. + * As an example, the 7-bit I2C slave address for CRT monitor + * for reading DDC/EDID information is 0b1010001. + * For an I2C send operation, the LSB must be programmed to 0; + * for I2C receive operation, the LSB must be programmed to 1. */ + + { + value = 0; + + set_reg_field_value( + value, + false, + DC_I2C_DATA, + DC_I2C_DATA_RW); + + set_reg_field_value( + value, + request->address, + DC_I2C_DATA, + DC_I2C_DATA); + + if (engine->transaction_count == 0) { + set_reg_field_value( + value, + 0, + DC_I2C_DATA, + DC_I2C_INDEX); + + /*enable index write*/ + set_reg_field_value( + value, + 1, + DC_I2C_DATA, + DC_I2C_INDEX_WRITE); + } + + dm_write_reg(ctx, mmDC_I2C_DATA, value); + + if (!(request->action & I2CAUX_TRANSACTION_ACTION_I2C_READ)) { + + set_reg_field_value( + value, + 0, + DC_I2C_DATA, + DC_I2C_INDEX_WRITE); + + while (length) { + + set_reg_field_value( + value, + *buffer++, + DC_I2C_DATA, + DC_I2C_DATA); + + dm_write_reg(ctx, mmDC_I2C_DATA, value); + --length; + } + } + } + + ++engine->transaction_count; + engine->buffer_used_bytes += length + 1; + + return last_transaction; +} + +static void execute_transaction( + struct i2c_hw_engine_dce80 *engine) +{ + uint32_t value = 0; + struct dc_context *ctx = NULL; + + ctx = engine->base.base.base.ctx; + + { + const uint32_t addr = engine->addr.DC_I2C_DDCX_SETUP; + + value = dm_read_reg(ctx, addr); + + set_reg_field_value( + value, + 0, + DC_I2C_DDC1_SETUP, + DC_I2C_DDC1_DATA_DRIVE_EN); + + set_reg_field_value( + value, + 0, + DC_I2C_DDC1_SETUP, + DC_I2C_DDC1_CLK_DRIVE_EN); + + set_reg_field_value( + value, + 0, + DC_I2C_DDC1_SETUP, + DC_I2C_DDC1_DATA_DRIVE_SEL); + + set_reg_field_value( + value, + 0, + DC_I2C_DDC1_SETUP, + DC_I2C_DDC1_INTRA_TRANSACTION_DELAY); + + set_reg_field_value( + value, + 0, + DC_I2C_DDC1_SETUP, + DC_I2C_DDC1_INTRA_BYTE_DELAY); + + dm_write_reg(ctx, addr, value); + } + + { + const uint32_t addr = mmDC_I2C_CONTROL; + + value = dm_read_reg(ctx, addr); + + set_reg_field_value( + value, + 0, + DC_I2C_CONTROL, + DC_I2C_SOFT_RESET); + + set_reg_field_value( + value, + 0, + DC_I2C_CONTROL, + DC_I2C_SW_STATUS_RESET); + + set_reg_field_value( + value, + 0, + DC_I2C_CONTROL, + DC_I2C_SEND_RESET); + + set_reg_field_value( + value, + 0, + DC_I2C_CONTROL, + DC_I2C_GO); + + set_reg_field_value( + value, + engine->transaction_count - 1, + DC_I2C_CONTROL, + DC_I2C_TRANSACTION_COUNT); + + dm_write_reg(ctx, addr, value); + } + + /* start I2C transfer */ + { + const uint32_t addr = mmDC_I2C_CONTROL; + + value = dm_read_reg(ctx, addr); + + set_reg_field_value( + value, + 1, + DC_I2C_CONTROL, + DC_I2C_GO); + + dm_write_reg(ctx, addr, value); + } + + /* all transactions were executed and HW buffer became empty + * (even though it actually happens when status becomes DONE) */ + engine->transaction_count = 0; + engine->buffer_used_bytes = 0; +} + +static void submit_channel_request( + struct i2c_engine *engine, + struct i2c_request_transaction_data *request) +{ + request->status = I2C_CHANNEL_OPERATION_SUCCEEDED; + + if (!process_transaction(FROM_I2C_ENGINE(engine), request)) + return; + + if (is_hw_busy(&engine->base)) { + request->status = I2C_CHANNEL_OPERATION_ENGINE_BUSY; + return; + } + + execute_transaction(FROM_I2C_ENGINE(engine)); +} + +static void process_channel_reply( + struct i2c_engine *engine, + struct i2c_reply_transaction_data *reply) +{ + uint32_t length = reply->length; + uint8_t *buffer = reply->data; + + uint32_t value = 0; + + /*set index*/ + set_reg_field_value( + value, + length - 1, + DC_I2C_DATA, + DC_I2C_INDEX); + + set_reg_field_value( + value, + 1, + DC_I2C_DATA, + DC_I2C_DATA_RW); + + set_reg_field_value( + value, + 1, + DC_I2C_DATA, + DC_I2C_INDEX_WRITE); + + dm_write_reg(engine->base.ctx, mmDC_I2C_DATA, value); + + while (length) { + /* after reading the status, + * if the I2C operation executed successfully + * (i.e. DC_I2C_STATUS_DONE = 1) then the I2C controller + * should read data bytes from I2C circular data buffer */ + + value = dm_read_reg(engine->base.ctx, mmDC_I2C_DATA); + + *buffer++ = get_reg_field_value( + value, + DC_I2C_DATA, + DC_I2C_DATA); + + --length; + } +} + +static enum i2c_channel_operation_result get_channel_status( + struct i2c_engine *engine, + uint8_t *returned_bytes) +{ + uint32_t i2c_sw_status = 0; + uint32_t value = dm_read_reg(engine->base.ctx, mmDC_I2C_SW_STATUS); + + i2c_sw_status = get_reg_field_value( + value, + DC_I2C_SW_STATUS, + DC_I2C_SW_STATUS); + + if (i2c_sw_status == DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_SW) + return I2C_CHANNEL_OPERATION_ENGINE_BUSY; + else if (value & DC_I2C_SW_STATUS__DC_I2C_SW_STOPPED_ON_NACK_MASK) + return I2C_CHANNEL_OPERATION_NO_RESPONSE; + else if (value & DC_I2C_SW_STATUS__DC_I2C_SW_TIMEOUT_MASK) + return I2C_CHANNEL_OPERATION_TIMEOUT; + else if (value & DC_I2C_SW_STATUS__DC_I2C_SW_ABORTED_MASK) + return I2C_CHANNEL_OPERATION_FAILED; + else if (value & DC_I2C_SW_STATUS__DC_I2C_SW_DONE_MASK) + return I2C_CHANNEL_OPERATION_SUCCEEDED; + + /* + * this is the case when HW used for communication, I2C_SW_STATUS + * could be zero + */ + return I2C_CHANNEL_OPERATION_SUCCEEDED; +} + +static uint32_t get_hw_buffer_available_size( + const struct i2c_hw_engine *engine) +{ + return I2C_HW_BUFFER_SIZE - + FROM_I2C_HW_ENGINE(engine)->buffer_used_bytes; +} + +static uint32_t get_transaction_timeout( + const struct i2c_hw_engine *engine, + uint32_t length) +{ + uint32_t speed = engine->base.funcs->get_speed(&engine->base); + + uint32_t period_timeout; + uint32_t num_of_clock_stretches; + + if (!speed) + return 0; + + period_timeout = (1000 * TRANSACTION_TIMEOUT_IN_I2C_CLOCKS) / speed; + + num_of_clock_stretches = 1 + (length << 3) + 1; + num_of_clock_stretches += + (FROM_I2C_HW_ENGINE(engine)->buffer_used_bytes << 3) + + (FROM_I2C_HW_ENGINE(engine)->transaction_count << 1); + + return period_timeout * num_of_clock_stretches; +} + +/* + * @brief + * DC_I2C_DDC1_SETUP MM register offsets + * + * @note + * The indices of this offset array are DDC engine IDs + */ +static const int32_t ddc_setup_offset[] = { + + mmDC_I2C_DDC1_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 1 */ + mmDC_I2C_DDC2_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 2 */ + mmDC_I2C_DDC3_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 3 */ + mmDC_I2C_DDC4_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 4 */ + mmDC_I2C_DDC5_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 5 */ + mmDC_I2C_DDC6_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 6 */ + mmDC_I2C_DDCVGA_SETUP - mmDC_I2C_DDC1_SETUP /* DDC Engine 7 */ +}; + +/* + * @brief + * DC_I2C_DDC1_SPEED MM register offsets + * + * @note + * The indices of this offset array are DDC engine IDs + */ +static const int32_t ddc_speed_offset[] = { + mmDC_I2C_DDC1_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 1 */ + mmDC_I2C_DDC2_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 2 */ + mmDC_I2C_DDC3_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 3 */ + mmDC_I2C_DDC4_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 4 */ + mmDC_I2C_DDC5_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 5 */ + mmDC_I2C_DDC6_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 6 */ + mmDC_I2C_DDCVGA_SPEED - mmDC_I2C_DDC1_SPEED /* DDC Engine 7 */ +}; + +static const struct i2c_engine_funcs i2c_engine_funcs = { + .destroy = destroy, + .get_speed = get_speed, + .set_speed = set_speed, + .setup_engine = setup_engine, + .submit_channel_request = submit_channel_request, + .process_channel_reply = process_channel_reply, + .get_channel_status = get_channel_status, + .acquire_engine = dal_i2c_hw_engine_acquire_engine, +}; + +static const struct engine_funcs engine_funcs = { + .release_engine = release_engine, + .get_engine_type = dal_i2c_hw_engine_get_engine_type, + .acquire = dal_i2c_engine_acquire, + .submit_request = dal_i2c_hw_engine_submit_request, +}; + +static const struct i2c_hw_engine_funcs i2c_hw_engine_funcs = { + .get_hw_buffer_available_size = + get_hw_buffer_available_size, + .get_transaction_timeout = + get_transaction_timeout, + .wait_on_operation_result = + dal_i2c_hw_engine_wait_on_operation_result, +}; + +static bool construct( + struct i2c_hw_engine_dce80 *engine, + const struct i2c_hw_engine_dce80_create_arg *arg) +{ + if (arg->engine_id >= sizeof(ddc_setup_offset) / sizeof(int32_t)) + return false; + if (arg->engine_id >= sizeof(ddc_speed_offset) / sizeof(int32_t)) + return false; + + if (!arg->reference_frequency) + return false; + + if (!dal_i2c_hw_engine_construct(&engine->base, arg->ctx)) + return false; + + engine->base.base.base.funcs = &engine_funcs; + engine->base.base.funcs = &i2c_engine_funcs; + engine->base.funcs = &i2c_hw_engine_funcs; + engine->base.default_speed = arg->default_speed; + engine->addr.DC_I2C_DDCX_SETUP = + mmDC_I2C_DDC1_SETUP + ddc_setup_offset[arg->engine_id]; + engine->addr.DC_I2C_DDCX_SPEED = + mmDC_I2C_DDC1_SPEED + ddc_speed_offset[arg->engine_id]; + + engine->engine_id = arg->engine_id; + engine->reference_frequency = arg->reference_frequency; + engine->buffer_used_bytes = 0; + engine->transaction_count = 0; + engine->engine_keep_power_up_count = 1; + + return true; +} + +struct i2c_engine *dal_i2c_hw_engine_dce80_create( + const struct i2c_hw_engine_dce80_create_arg *arg) +{ + struct i2c_hw_engine_dce80 *engine; + + if (!arg) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + engine = dm_alloc(sizeof(struct i2c_hw_engine_dce80)); + + if (!engine) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + if (construct(engine, arg)) + return &engine->base.base; + + BREAK_TO_DEBUGGER(); + + dm_free(engine); + + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.h b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.h new file mode 100644 index 000000000000..5c6116fb5479 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.h @@ -0,0 +1,54 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_I2C_HW_ENGINE_DCE80_H__ +#define __DAL_I2C_HW_ENGINE_DCE80_H__ + +struct i2c_hw_engine_dce80 { + struct i2c_hw_engine base; + struct { + uint32_t DC_I2C_DDCX_SETUP; + uint32_t DC_I2C_DDCX_SPEED; + } addr; + uint32_t engine_id; + /* expressed in kilohertz */ + uint32_t reference_frequency; + /* number of bytes currently used in HW buffer */ + uint32_t buffer_used_bytes; + /* number of pending transactions (before GO) */ + uint32_t transaction_count; + uint32_t engine_keep_power_up_count; +}; + +struct i2c_hw_engine_dce80_create_arg { + uint32_t engine_id; + uint32_t reference_frequency; + uint32_t default_speed; + struct dc_context *ctx; +}; + +struct i2c_engine *dal_i2c_hw_engine_dce80_create( + const struct i2c_hw_engine_dce80_create_arg *arg); +#endif diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_sw_engine_dce80.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_sw_engine_dce80.c new file mode 100644 index 000000000000..804a3266c578 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_sw_engine_dce80.c @@ -0,0 +1,184 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* + * Pre-requisites: headers required by header of this unit + */ +#include "include/i2caux_interface.h" +#include "../engine.h" +#include "../i2c_engine.h" +#include "../i2c_sw_engine.h" + +/* + * Header of this unit + */ + +#include "i2c_sw_engine_dce80.h" + +/* + * Post-requisites: headers required by this unit + */ + +#include "dce/dce_8_0_d.h" +#include "dce/dce_8_0_sh_mask.h" + +/* + * This unit + */ + +static const uint32_t ddc_hw_status_addr[] = { + mmDC_I2C_DDC1_HW_STATUS, + mmDC_I2C_DDC2_HW_STATUS, + mmDC_I2C_DDC3_HW_STATUS, + mmDC_I2C_DDC4_HW_STATUS, + mmDC_I2C_DDC5_HW_STATUS, + mmDC_I2C_DDC6_HW_STATUS, + mmDC_I2C_DDCVGA_HW_STATUS +}; + +/* + * @brief + * Cast 'struct i2c_sw_engine *' + * to 'struct i2c_sw_engine_dce80 *' + */ +#define FROM_I2C_SW_ENGINE(ptr) \ + container_of((ptr), struct i2c_sw_engine_dce80, base) + +/* + * @brief + * Cast 'struct i2c_engine *' + * to 'struct i2c_sw_engine_dce80 *' + */ +#define FROM_I2C_ENGINE(ptr) \ + FROM_I2C_SW_ENGINE(container_of((ptr), struct i2c_sw_engine, base)) + +/* + * @brief + * Cast 'struct engine *' + * to 'struct i2c_sw_engine_dce80 *' + */ +#define FROM_ENGINE(ptr) \ + FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base)) + +static void release_engine( + struct engine *engine) +{ + +} + +static void destruct( + struct i2c_sw_engine_dce80 *engine) +{ + dal_i2c_sw_engine_destruct(&engine->base); +} + +static void destroy( + struct i2c_engine **engine) +{ + struct i2c_sw_engine_dce80 *sw_engine = FROM_I2C_ENGINE(*engine); + + destruct(sw_engine); + + dm_free(sw_engine); + + *engine = NULL; +} + +static bool acquire_engine( + struct i2c_engine *engine, + struct ddc *ddc_handle) +{ + return dal_i2caux_i2c_sw_engine_acquire_engine(engine, ddc_handle); +} + +static const struct i2c_engine_funcs i2c_engine_funcs = { + .acquire_engine = acquire_engine, + .destroy = destroy, + .get_speed = dal_i2c_sw_engine_get_speed, + .set_speed = dal_i2c_sw_engine_set_speed, + .setup_engine = dal_i2c_engine_setup_i2c_engine, + .submit_channel_request = dal_i2c_sw_engine_submit_channel_request, + .process_channel_reply = dal_i2c_engine_process_channel_reply, + .get_channel_status = dal_i2c_sw_engine_get_channel_status, +}; + +static const struct engine_funcs engine_funcs = { + .release_engine = release_engine, + .get_engine_type = dal_i2c_sw_engine_get_engine_type, + .acquire = dal_i2c_engine_acquire, + .submit_request = dal_i2c_sw_engine_submit_request, +}; + +static bool construct( + struct i2c_sw_engine_dce80 *engine, + const struct i2c_sw_engine_dce80_create_arg *arg) +{ + struct i2c_sw_engine_create_arg arg_base; + + arg_base.ctx = arg->ctx; + arg_base.default_speed = arg->default_speed; + + if (!dal_i2c_sw_engine_construct(&engine->base, &arg_base)) { + BREAK_TO_DEBUGGER(); + return false; + } + + engine->base.base.base.funcs = &engine_funcs; + engine->base.base.funcs = &i2c_engine_funcs; + engine->base.default_speed = arg->default_speed; + engine->engine_id = arg->engine_id; + + return true; +} + +struct i2c_engine *dal_i2c_sw_engine_dce80_create( + const struct i2c_sw_engine_dce80_create_arg *arg) +{ + struct i2c_sw_engine_dce80 *engine; + + if (!arg) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + engine = dm_alloc(sizeof(struct i2c_sw_engine_dce80)); + + if (!engine) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + if (construct(engine, arg)) + return &engine->base.base; + + BREAK_TO_DEBUGGER(); + + dm_free(engine); + + return NULL; +} + diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_sw_engine_dce80.h b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_sw_engine_dce80.h new file mode 100644 index 000000000000..26355c088746 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_sw_engine_dce80.h @@ -0,0 +1,43 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_I2C_SW_ENGINE_DCE80_H__ +#define __DAL_I2C_SW_ENGINE_DCE80_H__ + +struct i2c_sw_engine_dce80 { + struct i2c_sw_engine base; + uint32_t engine_id; +}; + +struct i2c_sw_engine_dce80_create_arg { + uint32_t engine_id; + uint32_t default_speed; + struct dc_context *ctx; +}; + +struct i2c_engine *dal_i2c_sw_engine_dce80_create( + const struct i2c_sw_engine_dce80_create_arg *arg); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2caux_dce80.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2caux_dce80.c new file mode 100644 index 000000000000..5e71450c44e0 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2caux_dce80.c @@ -0,0 +1,295 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* + * Pre-requisites: headers required by header of this unit + */ +#include "include/i2caux_interface.h" +#include "../i2caux.h" + +/* + * Header of this unit + */ + +#include "i2caux_dce80.h" + +/* + * Post-requisites: headers required by this unit + */ + +#include "../engine.h" +#include "../i2c_engine.h" +#include "../i2c_sw_engine.h" +#include "i2c_sw_engine_dce80.h" +#include "../i2c_hw_engine.h" +#include "i2c_hw_engine_dce80.h" +#include "../i2c_generic_hw_engine.h" +#include "../aux_engine.h" + + +#include "../dce110/aux_engine_dce110.h" +#include "../dce110/i2caux_dce110.h" + +#include "dce/dce_8_0_d.h" +#include "dce/dce_8_0_sh_mask.h" + + +/* set register offset */ +#define SR(reg_name)\ + .reg_name = mm ## reg_name + +/* set register offset with instance */ +#define SRI(reg_name, block, id)\ + .reg_name = mm ## block ## id ## _ ## reg_name + +#define aux_regs(id)\ +[id] = {\ + AUX_COMMON_REG_LIST(id), \ + .AUX_RESET_MASK = 0 \ +} + +static const struct dce110_aux_registers dce80_aux_regs[] = { + aux_regs(0), + aux_regs(1), + aux_regs(2), + aux_regs(3), + aux_regs(4), + aux_regs(5) +}; + +/* + * This unit + */ + +#define FROM_I2C_AUX(ptr) \ + container_of((ptr), struct i2caux_dce80, base) + +static void destruct( + struct i2caux_dce80 *i2caux_dce80) +{ + dal_i2caux_destruct(&i2caux_dce80->base); +} + +static void destroy( + struct i2caux **i2c_engine) +{ + struct i2caux_dce80 *i2caux_dce80 = FROM_I2C_AUX(*i2c_engine); + + destruct(i2caux_dce80); + + dm_free(i2caux_dce80); + + *i2c_engine = NULL; +} + +static struct i2c_engine *acquire_i2c_hw_engine( + struct i2caux *i2caux, + struct ddc *ddc) +{ + struct i2caux_dce80 *i2caux_dce80 = FROM_I2C_AUX(i2caux); + + struct i2c_engine *engine = NULL; + bool non_generic; + + if (!ddc) + return NULL; + + if (ddc->hw_info.hw_supported) { + enum gpio_ddc_line line = dal_ddc_get_line(ddc); + + if (line < GPIO_DDC_LINE_COUNT) { + non_generic = true; + engine = i2caux->i2c_hw_engines[line]; + } + } + + if (!engine) { + non_generic = false; + engine = i2caux->i2c_generic_hw_engine; + } + + if (!engine) + return NULL; + + if (non_generic) { + if (!i2caux_dce80->i2c_hw_buffer_in_use && + engine->base.funcs->acquire(&engine->base, ddc)) { + i2caux_dce80->i2c_hw_buffer_in_use = true; + return engine; + } + } else { + if (engine->base.funcs->acquire(&engine->base, ddc)) + return engine; + } + + return NULL; +} + +static void release_engine( + struct i2caux *i2caux, + struct engine *engine) +{ + if (engine->funcs->get_engine_type(engine) == + I2CAUX_ENGINE_TYPE_I2C_DDC_HW) + FROM_I2C_AUX(i2caux)->i2c_hw_buffer_in_use = false; + + dal_i2caux_release_engine(i2caux, engine); +} + +static const enum gpio_ddc_line hw_ddc_lines[] = { + GPIO_DDC_LINE_DDC1, + GPIO_DDC_LINE_DDC2, + GPIO_DDC_LINE_DDC3, + GPIO_DDC_LINE_DDC4, + GPIO_DDC_LINE_DDC5, + GPIO_DDC_LINE_DDC6, + GPIO_DDC_LINE_DDC_VGA +}; + +static const enum gpio_ddc_line hw_aux_lines[] = { + GPIO_DDC_LINE_DDC1, + GPIO_DDC_LINE_DDC2, + GPIO_DDC_LINE_DDC3, + GPIO_DDC_LINE_DDC4, + GPIO_DDC_LINE_DDC5, + GPIO_DDC_LINE_DDC6 +}; + +static const struct i2caux_funcs i2caux_funcs = { + .destroy = destroy, + .acquire_i2c_hw_engine = acquire_i2c_hw_engine, + .release_engine = release_engine, + .acquire_i2c_sw_engine = dal_i2caux_acquire_i2c_sw_engine, + .acquire_aux_engine = dal_i2caux_acquire_aux_engine, +}; + +static bool construct( + struct i2caux_dce80 *i2caux_dce80, + struct dc_context *ctx) +{ + /* Entire family have I2C engine reference clock frequency + * changed from XTALIN (27) to XTALIN/2 (13.5) */ + + struct i2caux *base = &i2caux_dce80->base; + + uint32_t reference_frequency = + dal_i2caux_get_reference_clock(ctx->dc_bios) >> 1; + + /*bool use_i2c_sw_engine = dal_adapter_service_is_feature_supported(as, + FEATURE_RESTORE_USAGE_I2C_SW_ENGINE);*/ + + /* Use SWI2C for dce8 currently, sicne we have bug with hwi2c */ + bool use_i2c_sw_engine = true; + + uint32_t i; + + if (!dal_i2caux_construct(base, ctx)) { + BREAK_TO_DEBUGGER(); + return false; + } + + i2caux_dce80->base.funcs = &i2caux_funcs; + i2caux_dce80->i2c_hw_buffer_in_use = false; + + /* Create I2C HW engines (HW + SW pairs) + * for all lines which has assisted HW DDC + * 'i' (loop counter) used as DDC/AUX engine_id */ + + i = 0; + + do { + enum gpio_ddc_line line_id = hw_ddc_lines[i]; + + struct i2c_hw_engine_dce80_create_arg hw_arg; + + if (use_i2c_sw_engine) { + struct i2c_sw_engine_dce80_create_arg sw_arg; + + sw_arg.engine_id = i; + sw_arg.default_speed = base->default_i2c_sw_speed; + sw_arg.ctx = ctx; + base->i2c_sw_engines[line_id] = + dal_i2c_sw_engine_dce80_create(&sw_arg); + } + + hw_arg.engine_id = i; + hw_arg.reference_frequency = reference_frequency; + hw_arg.default_speed = base->default_i2c_hw_speed; + hw_arg.ctx = ctx; + + base->i2c_hw_engines[line_id] = + dal_i2c_hw_engine_dce80_create(&hw_arg); + + ++i; + } while (i < ARRAY_SIZE(hw_ddc_lines)); + + /* Create AUX engines for all lines which has assisted HW AUX + * 'i' (loop counter) used as DDC/AUX engine_id */ + + i = 0; + + do { + enum gpio_ddc_line line_id = hw_aux_lines[i]; + + struct aux_engine_dce110_init_data arg; + + arg.engine_id = i; + arg.timeout_period = base->aux_timeout_period; + arg.ctx = ctx; + arg.regs = &dce80_aux_regs[i]; + + base->aux_engines[line_id] = + dal_aux_engine_dce110_create(&arg); + + ++i; + } while (i < ARRAY_SIZE(hw_aux_lines)); + + /* TODO Generic I2C SW and HW */ + + return true; +} + +struct i2caux *dal_i2caux_dce80_create( + struct dc_context *ctx) +{ + struct i2caux_dce80 *i2caux_dce80 = + dm_alloc(sizeof(struct i2caux_dce80)); + + if (!i2caux_dce80) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + if (construct(i2caux_dce80, ctx)) + return &i2caux_dce80->base; + + BREAK_TO_DEBUGGER(); + + dm_free(i2caux_dce80); + + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2caux_dce80.h b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2caux_dce80.h new file mode 100644 index 000000000000..21908629e973 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2caux_dce80.h @@ -0,0 +1,38 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_I2C_AUX_DCE80_H__ +#define __DAL_I2C_AUX_DCE80_H__ + +struct i2caux_dce80 { + struct i2caux base; + /* indicate the I2C HW circular buffer is in use */ + bool i2c_hw_buffer_in_use; +}; + +struct i2caux *dal_i2caux_dce80_create( + struct dc_context *ctx); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.c b/drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.c new file mode 100644 index 000000000000..029bf735036c --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.c @@ -0,0 +1,108 @@ +/* + * Copyright 2012-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* + * Pre-requisites: headers required by header of this unit + */ +#include "include/i2caux_interface.h" +#include "../i2caux.h" +#include "../engine.h" +#include "../i2c_engine.h" +#include "../i2c_sw_engine.h" +#include "../i2c_hw_engine.h" + +/* + * Header of this unit + */ +#include "i2caux_diag.h" + +/* + * Post-requisites: headers required by this unit + */ + +/* + * This unit + */ + +static void destruct( + struct i2caux *i2caux) +{ + dal_i2caux_destruct(i2caux); +} + +static void destroy( + struct i2caux **i2c_engine) +{ + destruct(*i2c_engine); + + dm_free(*i2c_engine); + + *i2c_engine = NULL; +} + +/* function table */ +static const struct i2caux_funcs i2caux_funcs = { + .destroy = destroy, + .acquire_i2c_hw_engine = NULL, + .release_engine = NULL, + .acquire_i2c_sw_engine = NULL, + .acquire_aux_engine = NULL, +}; + +static bool construct( + struct i2caux *i2caux, + struct dc_context *ctx) +{ + if (!dal_i2caux_construct(i2caux, ctx)) { + ASSERT_CRITICAL(false); + return false; + } + + i2caux->funcs = &i2caux_funcs; + + return true; +} + +struct i2caux *dal_i2caux_diag_fpga_create( + struct dc_context *ctx) +{ + struct i2caux *i2caux = dm_alloc(sizeof(struct i2caux)); + + if (!i2caux) { + ASSERT_CRITICAL(false); + return NULL; + } + + if (construct(i2caux, ctx)) + return i2caux; + + ASSERT_CRITICAL(false); + + dm_free(i2caux); + + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.h b/drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.h new file mode 100644 index 000000000000..a83eeb748283 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.h @@ -0,0 +1,32 @@ +/* + * Copyright 2012-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_I2C_AUX_DIAG_FPGA_H__ +#define __DAL_I2C_AUX_DIAG_FPGA_H__ + +struct i2caux *dal_i2caux_diag_fpga_create( + struct dc_context *ctx); + +#endif /* __DAL_I2C_AUX_DIAG_FPGA_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/engine.h b/drivers/gpu/drm/amd/display/dc/i2caux/engine.h new file mode 100644 index 000000000000..76fe2df3c2f8 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/engine.h @@ -0,0 +1,120 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_ENGINE_H__ +#define __DAL_ENGINE_H__ + +enum i2caux_transaction_operation { + I2CAUX_TRANSACTION_READ, + I2CAUX_TRANSACTION_WRITE +}; + +enum i2caux_transaction_address_space { + I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C = 1, + I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD +}; + +struct i2caux_transaction_payload { + enum i2caux_transaction_address_space address_space; + uint32_t address; + uint32_t length; + uint8_t *data; +}; + +enum i2caux_transaction_status { + I2CAUX_TRANSACTION_STATUS_UNKNOWN = (-1L), + I2CAUX_TRANSACTION_STATUS_SUCCEEDED, + I2CAUX_TRANSACTION_STATUS_FAILED_CHANNEL_BUSY, + I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT, + I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR, + I2CAUX_TRANSACTION_STATUS_FAILED_NACK, + I2CAUX_TRANSACTION_STATUS_FAILED_INCOMPLETE, + I2CAUX_TRANSACTION_STATUS_FAILED_OPERATION, + I2CAUX_TRANSACTION_STATUS_FAILED_INVALID_OPERATION, + I2CAUX_TRANSACTION_STATUS_FAILED_BUFFER_OVERFLOW +}; + +struct i2caux_transaction_request { + enum i2caux_transaction_operation operation; + struct i2caux_transaction_payload payload; + enum i2caux_transaction_status status; +}; + +enum i2caux_engine_type { + I2CAUX_ENGINE_TYPE_UNKNOWN = (-1L), + I2CAUX_ENGINE_TYPE_AUX, + I2CAUX_ENGINE_TYPE_I2C_DDC_HW, + I2CAUX_ENGINE_TYPE_I2C_GENERIC_HW, + I2CAUX_ENGINE_TYPE_I2C_SW +}; + +enum i2c_default_speed { + I2CAUX_DEFAULT_I2C_HW_SPEED = 50, + I2CAUX_DEFAULT_I2C_SW_SPEED = 50 +}; + +enum i2caux_transaction_action { + I2CAUX_TRANSACTION_ACTION_I2C_WRITE = 0x00, + I2CAUX_TRANSACTION_ACTION_I2C_READ = 0x10, + I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST = 0x20, + + I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT = 0x40, + I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT = 0x50, + I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST_MOT = 0x60, + + I2CAUX_TRANSACTION_ACTION_DP_WRITE = 0x80, + I2CAUX_TRANSACTION_ACTION_DP_READ = 0x90 +}; + +struct engine; + +struct engine_funcs { + enum i2caux_engine_type (*get_engine_type)( + const struct engine *engine); + bool (*acquire)( + struct engine *engine, + struct ddc *ddc); + bool (*submit_request)( + struct engine *engine, + struct i2caux_transaction_request *request, + bool middle_of_transaction); + void (*release_engine)( + struct engine *engine); +}; + +struct engine { + const struct engine_funcs *funcs; + struct ddc *ddc; + struct dc_context *ctx; +}; + +bool dal_i2caux_construct_engine( + struct engine *engine, + struct dc_context *ctx); + +void dal_i2caux_destruct_engine( + struct engine *engine); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/engine_base.c b/drivers/gpu/drm/amd/display/dc/i2caux/engine_base.c new file mode 100644 index 000000000000..09da81379491 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/engine_base.c @@ -0,0 +1,53 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* + * Pre-requisites: headers required by header of this unit + */ +#include "include/i2caux_interface.h" + +/* + * Header of this unit + */ + +#include "engine.h" + +bool dal_i2caux_construct_engine( + struct engine *engine, + struct dc_context *ctx) +{ + engine->ddc = NULL; + engine->ctx = ctx; + return true; +} + +void dal_i2caux_destruct_engine( + struct engine *engine) +{ + /* nothing to do */ +} + diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.c new file mode 100644 index 000000000000..144f51dc4523 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.c @@ -0,0 +1,121 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* + * Pre-requisites: headers required by header of this unit + */ +#include "include/i2caux_interface.h" +#include "engine.h" + +/* + * Header of this unit + */ + +#include "i2c_engine.h" + +/* + * Post-requisites: headers required by this unit + */ + +/* + * This unit + */ + +#define FROM_ENGINE(ptr) \ + container_of((ptr), struct i2c_engine, base) + +bool dal_i2c_engine_acquire( + struct engine *engine, + struct ddc *ddc_handle) +{ + struct i2c_engine *i2c_engine = FROM_ENGINE(engine); + + uint32_t counter = 0; + bool result; + + do { + result = i2c_engine->funcs->acquire_engine( + i2c_engine, ddc_handle); + + if (result) + break; + + /* i2c_engine is busy by VBios, lets wait and retry */ + + udelay(10); + + ++counter; + } while (counter < 2); + + if (result) { + if (!i2c_engine->funcs->setup_engine(i2c_engine)) { + engine->funcs->release_engine(engine); + result = false; + } + } + + return result; +} + +bool dal_i2c_engine_setup_i2c_engine( + struct i2c_engine *engine) +{ + /* Derivative classes do not have to override this */ + + return true; +} + +void dal_i2c_engine_submit_channel_request( + struct i2c_engine *engine, + struct i2c_request_transaction_data *request) +{ + +} + +void dal_i2c_engine_process_channel_reply( + struct i2c_engine *engine, + struct i2c_reply_transaction_data *reply) +{ + +} + +bool dal_i2c_engine_construct( + struct i2c_engine *engine, + struct dc_context *ctx) +{ + if (!dal_i2caux_construct_engine(&engine->base, ctx)) + return false; + + engine->timeout_delay = 0; + return true; +} + +void dal_i2c_engine_destruct( + struct i2c_engine *engine) +{ + dal_i2caux_destruct_engine(&engine->base); +} diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.h b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.h new file mode 100644 index 000000000000..ce2c51ddea02 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.h @@ -0,0 +1,113 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_I2C_ENGINE_H__ +#define __DAL_I2C_ENGINE_H__ + +enum i2c_channel_operation_result { + I2C_CHANNEL_OPERATION_SUCCEEDED, + I2C_CHANNEL_OPERATION_FAILED, + I2C_CHANNEL_OPERATION_NOT_GRANTED, + I2C_CHANNEL_OPERATION_IS_BUSY, + I2C_CHANNEL_OPERATION_NO_HANDLE_PROVIDED, + I2C_CHANNEL_OPERATION_CHANNEL_IN_USE, + I2C_CHANNEL_OPERATION_CHANNEL_CLIENT_MAX_ALLOWED, + I2C_CHANNEL_OPERATION_ENGINE_BUSY, + I2C_CHANNEL_OPERATION_TIMEOUT, + I2C_CHANNEL_OPERATION_NO_RESPONSE, + I2C_CHANNEL_OPERATION_HW_REQUEST_I2C_BUS, + I2C_CHANNEL_OPERATION_WRONG_PARAMETER, + I2C_CHANNEL_OPERATION_OUT_NB_OF_RETRIES, + I2C_CHANNEL_OPERATION_NOT_STARTED +}; + +struct i2c_request_transaction_data { + enum i2caux_transaction_action action; + enum i2c_channel_operation_result status; + uint8_t address; + uint32_t length; + uint8_t *data; +}; + +struct i2c_reply_transaction_data { + uint32_t length; + uint8_t *data; +}; + +struct i2c_engine; + +struct i2c_engine_funcs { + void (*destroy)( + struct i2c_engine **ptr); + uint32_t (*get_speed)( + const struct i2c_engine *engine); + void (*set_speed)( + struct i2c_engine *engine, + uint32_t speed); + bool (*acquire_engine)( + struct i2c_engine *engine, + struct ddc *ddc); + bool (*setup_engine)( + struct i2c_engine *engine); + void (*submit_channel_request)( + struct i2c_engine *engine, + struct i2c_request_transaction_data *request); + void (*process_channel_reply)( + struct i2c_engine *engine, + struct i2c_reply_transaction_data *reply); + enum i2c_channel_operation_result (*get_channel_status)( + struct i2c_engine *engine, + uint8_t *returned_bytes); +}; + +struct i2c_engine { + struct engine base; + const struct i2c_engine_funcs *funcs; + uint32_t timeout_delay; +}; + +bool dal_i2c_engine_construct( + struct i2c_engine *engine, + struct dc_context *ctx); + +void dal_i2c_engine_destruct( + struct i2c_engine *engine); + +bool dal_i2c_engine_setup_i2c_engine( + struct i2c_engine *engine); + +void dal_i2c_engine_submit_channel_request( + struct i2c_engine *engine, + struct i2c_request_transaction_data *request); + +void dal_i2c_engine_process_channel_reply( + struct i2c_engine *engine, + struct i2c_reply_transaction_data *reply); + +bool dal_i2c_engine_acquire( + struct engine *ptr, + struct ddc *ddc_handle); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_generic_hw_engine.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_generic_hw_engine.c new file mode 100644 index 000000000000..521c4ec98632 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_generic_hw_engine.c @@ -0,0 +1,286 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* + * Pre-requisites: headers required by header of this unit + */ +#include "include/i2caux_interface.h" +#include "engine.h" +#include "i2c_engine.h" +#include "i2c_hw_engine.h" + +/* + * Header of this unit + */ + +#include "i2c_generic_hw_engine.h" + +/* + * Post-requisites: headers required by this unit + */ + +/* + * This unit + */ + +/* + * @brief + * Cast 'struct i2c_hw_engine *' + * to 'struct i2c_generic_hw_engine *' + */ +#define FROM_I2C_HW_ENGINE(ptr) \ + container_of((ptr), struct i2c_generic_hw_engine, base) + +/* + * @brief + * Cast 'struct i2c_engine *' + * to 'struct i2c_generic_hw_engine *' + */ +#define FROM_I2C_ENGINE(ptr) \ + FROM_I2C_HW_ENGINE(container_of((ptr), struct i2c_hw_engine, base)) + +/* + * @brief + * Cast 'struct engine *' + * to 'struct i2c_generic_hw_engine *' + */ +#define FROM_ENGINE(ptr) \ + FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base)) + +enum i2caux_engine_type dal_i2c_generic_hw_engine_get_engine_type( + const struct engine *engine) +{ + return I2CAUX_ENGINE_TYPE_I2C_GENERIC_HW; +} + +/* + * @brief + * Single transaction handling. + * Since transaction may be bigger than HW buffer size, + * it divides transaction to sub-transactions + * and uses batch transaction feature of the engine. + */ +bool dal_i2c_generic_hw_engine_submit_request( + struct engine *engine, + struct i2caux_transaction_request *i2caux_request, + bool middle_of_transaction) +{ + struct i2c_generic_hw_engine *hw_engine = FROM_ENGINE(engine); + + struct i2c_hw_engine *base = &hw_engine->base; + + uint32_t max_payload_size = + base->funcs->get_hw_buffer_available_size(base); + + bool initial_stop_bit = !middle_of_transaction; + + struct i2c_generic_transaction_attributes attributes; + + enum i2c_channel_operation_result operation_result = + I2C_CHANNEL_OPERATION_FAILED; + + bool result = false; + + /* setup transaction initial properties */ + + uint8_t address = i2caux_request->payload.address; + uint8_t *current_payload = i2caux_request->payload.data; + uint32_t remaining_payload_size = i2caux_request->payload.length; + + bool first_iteration = true; + + if (i2caux_request->operation == I2CAUX_TRANSACTION_READ) + attributes.action = I2CAUX_TRANSACTION_ACTION_I2C_READ; + else if (i2caux_request->operation == I2CAUX_TRANSACTION_WRITE) + attributes.action = I2CAUX_TRANSACTION_ACTION_I2C_WRITE; + else { + i2caux_request->status = + I2CAUX_TRANSACTION_STATUS_FAILED_INVALID_OPERATION; + return false; + } + + /* Do batch transaction. + * Divide read/write data into payloads which fit HW buffer size. + * 1. Single transaction: + * start_bit = 1, stop_bit depends on session state, ack_on_read = 0; + * 2. Start of batch transaction: + * start_bit = 1, stop_bit = 0, ack_on_read = 1; + * 3. Middle of batch transaction: + * start_bit = 0, stop_bit = 0, ack_on_read = 1; + * 4. End of batch transaction: + * start_bit = 0, stop_bit depends on session state, ack_on_read = 0. + * Session stop bit is set if 'middle_of_transaction' = 0. */ + + while (remaining_payload_size) { + uint32_t current_transaction_size; + uint32_t current_payload_size; + + bool last_iteration; + bool stop_bit; + + /* Calculate current transaction size and payload size. + * Transaction size = total number of bytes in transaction, + * including slave's address; + * Payload size = number of data bytes in transaction. */ + + if (first_iteration) { + /* In the first sub-transaction we send slave's address + * thus we need to reserve one byte for it */ + current_transaction_size = + (remaining_payload_size > max_payload_size - 1) ? + max_payload_size : + remaining_payload_size + 1; + + current_payload_size = current_transaction_size - 1; + } else { + /* Second and further sub-transactions will have + * entire buffer reserved for data */ + current_transaction_size = + (remaining_payload_size > max_payload_size) ? + max_payload_size : + remaining_payload_size; + + current_payload_size = current_transaction_size; + } + + last_iteration = + (remaining_payload_size == current_payload_size); + + stop_bit = last_iteration ? initial_stop_bit : false; + + /* write slave device address */ + + if (first_iteration) + hw_engine->funcs->write_address(hw_engine, address); + + /* write current portion of data, if requested */ + + if (i2caux_request->operation == I2CAUX_TRANSACTION_WRITE) + hw_engine->funcs->write_data( + hw_engine, + current_payload, + current_payload_size); + + /* execute transaction */ + + attributes.start_bit = first_iteration; + attributes.stop_bit = stop_bit; + attributes.last_read = last_iteration; + attributes.transaction_size = current_transaction_size; + + hw_engine->funcs->execute_transaction(hw_engine, &attributes); + + /* wait until transaction is processed; if it fails - quit */ + + operation_result = base->funcs->wait_on_operation_result( + base, + base->funcs->get_transaction_timeout( + base, current_transaction_size), + I2C_CHANNEL_OPERATION_ENGINE_BUSY); + + if (operation_result != I2C_CHANNEL_OPERATION_SUCCEEDED) + break; + + /* read current portion of data, if requested */ + + /* the read offset should be 1 for first sub-transaction, + * and 0 for any next one */ + + if (i2caux_request->operation == I2CAUX_TRANSACTION_READ) + hw_engine->funcs->read_data(hw_engine, current_payload, + current_payload_size, first_iteration ? 1 : 0); + + /* update loop variables */ + + first_iteration = false; + current_payload += current_payload_size; + remaining_payload_size -= current_payload_size; + } + + /* update transaction status */ + + switch (operation_result) { + case I2C_CHANNEL_OPERATION_SUCCEEDED: + i2caux_request->status = + I2CAUX_TRANSACTION_STATUS_SUCCEEDED; + result = true; + break; + case I2C_CHANNEL_OPERATION_NO_RESPONSE: + i2caux_request->status = + I2CAUX_TRANSACTION_STATUS_FAILED_NACK; + break; + case I2C_CHANNEL_OPERATION_TIMEOUT: + i2caux_request->status = + I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; + break; + case I2C_CHANNEL_OPERATION_FAILED: + i2caux_request->status = + I2CAUX_TRANSACTION_STATUS_FAILED_INCOMPLETE; + break; + default: + i2caux_request->status = + I2CAUX_TRANSACTION_STATUS_FAILED_OPERATION; + } + + return result; +} + +/* + * @brief + * Returns number of microseconds to wait until timeout to be considered + */ +uint32_t dal_i2c_generic_hw_engine_get_transaction_timeout( + const struct i2c_hw_engine *engine, + uint32_t length) +{ + const struct i2c_engine *base = &engine->base; + + uint32_t speed = base->funcs->get_speed(base); + + if (!speed) + return 0; + + /* total timeout = period_timeout * (start + data bits count + stop) */ + + return ((1000 * TRANSACTION_TIMEOUT_IN_I2C_CLOCKS) / speed) * + (1 + (length << 3) + 1); +} + +bool dal_i2c_generic_hw_engine_construct( + struct i2c_generic_hw_engine *engine, + struct dc_context *ctx) +{ + if (!dal_i2c_hw_engine_construct(&engine->base, ctx)) + return false; + return true; +} + +void dal_i2c_generic_hw_engine_destruct( + struct i2c_generic_hw_engine *engine) +{ + dal_i2c_hw_engine_destruct(&engine->base); +} diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_generic_hw_engine.h b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_generic_hw_engine.h new file mode 100644 index 000000000000..083bb0dee9a1 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_generic_hw_engine.h @@ -0,0 +1,77 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_I2C_GENERIC_HW_ENGINE_H__ +#define __DAL_I2C_GENERIC_HW_ENGINE_H__ + +struct i2c_generic_transaction_attributes { + enum i2caux_transaction_action action; + uint32_t transaction_size; + bool start_bit; + bool stop_bit; + bool last_read; +}; + +struct i2c_generic_hw_engine; + +struct i2c_generic_hw_engine_funcs { + void (*write_address)( + struct i2c_generic_hw_engine *engine, + uint8_t address); + void (*write_data)( + struct i2c_generic_hw_engine *engine, + const uint8_t *buffer, + uint32_t length); + void (*read_data)( + struct i2c_generic_hw_engine *engine, + uint8_t *buffer, + uint32_t length, + uint32_t offset); + void (*execute_transaction)( + struct i2c_generic_hw_engine *engine, + struct i2c_generic_transaction_attributes *attributes); +}; + +struct i2c_generic_hw_engine { + struct i2c_hw_engine base; + const struct i2c_generic_hw_engine_funcs *funcs; +}; + +bool dal_i2c_generic_hw_engine_construct( + struct i2c_generic_hw_engine *engine, + struct dc_context *ctx); + +void dal_i2c_generic_hw_engine_destruct( + struct i2c_generic_hw_engine *engine); +enum i2caux_engine_type dal_i2c_generic_hw_engine_get_engine_type( + const struct engine *engine); +bool dal_i2c_generic_hw_engine_submit_request( + struct engine *ptr, + struct i2caux_transaction_request *i2caux_request, + bool middle_of_transaction); +uint32_t dal_i2c_generic_hw_engine_get_transaction_timeout( + const struct i2c_hw_engine *engine, + uint32_t length); +#endif diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.c new file mode 100644 index 000000000000..00a8f07a74e9 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.c @@ -0,0 +1,246 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* + * Pre-requisites: headers required by header of this unit + */ +#include "include/i2caux_interface.h" +#include "engine.h" +#include "i2c_engine.h" + +/* + * Header of this unit + */ + +#include "i2c_hw_engine.h" + +/* + * Post-requisites: headers required by this unit + */ + +/* + * This unit + */ + +/* + * @brief + * Cast 'struct i2c_engine *' + * to 'struct i2c_hw_engine *' + */ +#define FROM_I2C_ENGINE(ptr) \ + container_of((ptr), struct i2c_hw_engine, base) + +/* + * @brief + * Cast 'struct engine *' + * to 'struct i2c_hw_engine *' + */ +#define FROM_ENGINE(ptr) \ + FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base)) + +enum i2caux_engine_type dal_i2c_hw_engine_get_engine_type( + const struct engine *engine) +{ + return I2CAUX_ENGINE_TYPE_I2C_DDC_HW; +} + +bool dal_i2c_hw_engine_submit_request( + struct engine *engine, + struct i2caux_transaction_request *i2caux_request, + bool middle_of_transaction) +{ + struct i2c_hw_engine *hw_engine = FROM_ENGINE(engine); + + struct i2c_request_transaction_data request; + + uint32_t transaction_timeout; + + enum i2c_channel_operation_result operation_result; + + bool result = false; + + /* We need following: + * transaction length will not exceed + * the number of free bytes in HW buffer (minus one for address)*/ + + if (i2caux_request->payload.length >= + hw_engine->funcs->get_hw_buffer_available_size(hw_engine)) { + i2caux_request->status = + I2CAUX_TRANSACTION_STATUS_FAILED_BUFFER_OVERFLOW; + return false; + } + + if (i2caux_request->operation == I2CAUX_TRANSACTION_READ) + request.action = middle_of_transaction ? + I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT : + I2CAUX_TRANSACTION_ACTION_I2C_READ; + else if (i2caux_request->operation == I2CAUX_TRANSACTION_WRITE) + request.action = middle_of_transaction ? + I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT : + I2CAUX_TRANSACTION_ACTION_I2C_WRITE; + else { + i2caux_request->status = + I2CAUX_TRANSACTION_STATUS_FAILED_INVALID_OPERATION; + /* [anaumov] in DAL2, there was no "return false" */ + return false; + } + + request.address = (uint8_t)i2caux_request->payload.address; + request.length = i2caux_request->payload.length; + request.data = i2caux_request->payload.data; + + /* obtain timeout value before submitting request */ + + transaction_timeout = hw_engine->funcs->get_transaction_timeout( + hw_engine, i2caux_request->payload.length + 1); + + hw_engine->base.funcs->submit_channel_request( + &hw_engine->base, &request); + + if ((request.status == I2C_CHANNEL_OPERATION_FAILED) || + (request.status == I2C_CHANNEL_OPERATION_ENGINE_BUSY)) { + i2caux_request->status = + I2CAUX_TRANSACTION_STATUS_FAILED_CHANNEL_BUSY; + return false; + } + + /* wait until transaction proceed */ + + operation_result = hw_engine->funcs->wait_on_operation_result( + hw_engine, + transaction_timeout, + I2C_CHANNEL_OPERATION_ENGINE_BUSY); + + /* update transaction status */ + + switch (operation_result) { + case I2C_CHANNEL_OPERATION_SUCCEEDED: + i2caux_request->status = + I2CAUX_TRANSACTION_STATUS_SUCCEEDED; + result = true; + break; + case I2C_CHANNEL_OPERATION_NO_RESPONSE: + i2caux_request->status = + I2CAUX_TRANSACTION_STATUS_FAILED_NACK; + break; + case I2C_CHANNEL_OPERATION_TIMEOUT: + i2caux_request->status = + I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; + break; + case I2C_CHANNEL_OPERATION_FAILED: + i2caux_request->status = + I2CAUX_TRANSACTION_STATUS_FAILED_INCOMPLETE; + break; + default: + i2caux_request->status = + I2CAUX_TRANSACTION_STATUS_FAILED_OPERATION; + } + + if (result && (i2caux_request->operation == I2CAUX_TRANSACTION_READ)) { + struct i2c_reply_transaction_data reply; + + reply.data = i2caux_request->payload.data; + reply.length = i2caux_request->payload.length; + + hw_engine->base.funcs-> + process_channel_reply(&hw_engine->base, &reply); + } + + return result; +} + +bool dal_i2c_hw_engine_acquire_engine( + struct i2c_engine *engine, + struct ddc *ddc) +{ + enum gpio_result result; + uint32_t current_speed; + + result = dal_ddc_open(ddc, GPIO_MODE_HARDWARE, + GPIO_DDC_CONFIG_TYPE_MODE_I2C); + + if (result != GPIO_RESULT_OK) + return false; + + engine->base.ddc = ddc; + + current_speed = engine->funcs->get_speed(engine); + + if (current_speed) + FROM_I2C_ENGINE(engine)->original_speed = current_speed; + + return true; +} +/* + * @brief + * Queries in a loop for current engine status + * until retrieved status matches 'expected_result', or timeout occurs. + * Timeout given in microseconds + * and the status query frequency is also one per microsecond. + */ +enum i2c_channel_operation_result dal_i2c_hw_engine_wait_on_operation_result( + struct i2c_hw_engine *engine, + uint32_t timeout, + enum i2c_channel_operation_result expected_result) +{ + enum i2c_channel_operation_result result; + uint32_t i = 0; + + if (!timeout) + return I2C_CHANNEL_OPERATION_SUCCEEDED; + + do { + result = engine->base.funcs->get_channel_status( + &engine->base, NULL); + + if (result != expected_result) + break; + + udelay(1); + + ++i; + } while (i < timeout); + + return result; +} + +bool dal_i2c_hw_engine_construct( + struct i2c_hw_engine *engine, + struct dc_context *ctx) +{ + if (!dal_i2c_engine_construct(&engine->base, ctx)) + return false; + engine->original_speed = I2CAUX_DEFAULT_I2C_HW_SPEED; + engine->default_speed = I2CAUX_DEFAULT_I2C_HW_SPEED; + return true; +} + +void dal_i2c_hw_engine_destruct( + struct i2c_hw_engine *engine) +{ + dal_i2c_engine_destruct(&engine->base); +} diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.h b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.h new file mode 100644 index 000000000000..f2df1749820e --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.h @@ -0,0 +1,80 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_I2C_HW_ENGINE_H__ +#define __DAL_I2C_HW_ENGINE_H__ + +enum { + TRANSACTION_TIMEOUT_IN_I2C_CLOCKS = 32 +}; + +struct i2c_hw_engine; + +struct i2c_hw_engine_funcs { + uint32_t (*get_hw_buffer_available_size)( + const struct i2c_hw_engine *engine); + enum i2c_channel_operation_result (*wait_on_operation_result)( + struct i2c_hw_engine *engine, + uint32_t timeout, + enum i2c_channel_operation_result expected_result); + uint32_t (*get_transaction_timeout)( + const struct i2c_hw_engine *engine, + uint32_t length); +}; + +struct i2c_hw_engine { + struct i2c_engine base; + const struct i2c_hw_engine_funcs *funcs; + + /* Values below are in kilohertz */ + uint32_t original_speed; + uint32_t default_speed; +}; + +bool dal_i2c_hw_engine_construct( + struct i2c_hw_engine *engine, + struct dc_context *ctx); + +void dal_i2c_hw_engine_destruct( + struct i2c_hw_engine *engine); + +enum i2c_channel_operation_result dal_i2c_hw_engine_wait_on_operation_result( + struct i2c_hw_engine *engine, + uint32_t timeout, + enum i2c_channel_operation_result expected_result); + +bool dal_i2c_hw_engine_acquire_engine( + struct i2c_engine *engine, + struct ddc *ddc); + +bool dal_i2c_hw_engine_submit_request( + struct engine *ptr, + struct i2caux_transaction_request *i2caux_request, + bool middle_of_transaction); + +enum i2caux_engine_type dal_i2c_hw_engine_get_engine_type( + const struct engine *engine); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.c new file mode 100644 index 000000000000..95bc4457d44b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.c @@ -0,0 +1,610 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* + * Pre-requisites: headers required by header of this unit + */ +#include "include/i2caux_interface.h" +#include "engine.h" +#include "i2c_engine.h" + +/* + * Header of this unit + */ + +#include "i2c_sw_engine.h" + +/* + * Post-requisites: headers required by this unit + */ + +/* + * This unit + */ + +#define SCL false +#define SDA true + +static inline bool read_bit_from_ddc( + struct ddc *ddc, + bool data_nor_clock) +{ + uint32_t value = 0; + + if (data_nor_clock) + dal_gpio_get_value(ddc->pin_data, &value); + else + dal_gpio_get_value(ddc->pin_clock, &value); + + return (value != 0); +} + +static inline void write_bit_to_ddc( + struct ddc *ddc, + bool data_nor_clock, + bool bit) +{ + uint32_t value = bit ? 1 : 0; + + if (data_nor_clock) + dal_gpio_set_value(ddc->pin_data, value); + else + dal_gpio_set_value(ddc->pin_clock, value); +} + +static bool wait_for_scl_high( + struct dc_context *ctx, + struct ddc *ddc, + uint16_t clock_delay_div_4) +{ + uint32_t scl_retry = 0; + uint32_t scl_retry_max = I2C_SW_TIMEOUT_DELAY / clock_delay_div_4; + + udelay(clock_delay_div_4); + + /* 3 milliseconds delay + * to wake up some displays from "low power" state. + */ + + do { + if (read_bit_from_ddc(ddc, SCL)) + return true; + + udelay(clock_delay_div_4); + + ++scl_retry; + } while (scl_retry <= scl_retry_max); + + return false; +} + +static bool start_sync( + struct dc_context *ctx, + struct ddc *ddc_handle, + uint16_t clock_delay_div_4) +{ + uint32_t retry = 0; + + /* The I2C communications start signal is: + * the SDA going low from high, while the SCL is high. */ + + write_bit_to_ddc(ddc_handle, SCL, true); + + udelay(clock_delay_div_4); + + do { + write_bit_to_ddc(ddc_handle, SDA, true); + + if (!read_bit_from_ddc(ddc_handle, SDA)) { + ++retry; + continue; + } + + udelay(clock_delay_div_4); + + write_bit_to_ddc(ddc_handle, SCL, true); + + if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4)) + break; + + write_bit_to_ddc(ddc_handle, SDA, false); + + udelay(clock_delay_div_4); + + write_bit_to_ddc(ddc_handle, SCL, false); + + udelay(clock_delay_div_4); + + return true; + } while (retry <= I2C_SW_RETRIES); + + return false; +} + +static bool stop_sync( + struct dc_context *ctx, + struct ddc *ddc_handle, + uint16_t clock_delay_div_4) +{ + uint32_t retry = 0; + + /* The I2C communications stop signal is: + * the SDA going high from low, while the SCL is high. */ + + write_bit_to_ddc(ddc_handle, SCL, false); + + udelay(clock_delay_div_4); + + write_bit_to_ddc(ddc_handle, SDA, false); + + udelay(clock_delay_div_4); + + write_bit_to_ddc(ddc_handle, SCL, true); + + if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4)) + return false; + + write_bit_to_ddc(ddc_handle, SDA, true); + + do { + udelay(clock_delay_div_4); + + if (read_bit_from_ddc(ddc_handle, SDA)) + return true; + + ++retry; + } while (retry <= 2); + + return false; +} + +static bool write_byte( + struct dc_context *ctx, + struct ddc *ddc_handle, + uint16_t clock_delay_div_4, + uint8_t byte) +{ + int32_t shift = 7; + bool ack; + + /* bits are transmitted serially, starting from MSB */ + + do { + udelay(clock_delay_div_4); + + write_bit_to_ddc(ddc_handle, SDA, (byte >> shift) & 1); + + udelay(clock_delay_div_4); + + write_bit_to_ddc(ddc_handle, SCL, true); + + if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4)) + return false; + + write_bit_to_ddc(ddc_handle, SCL, false); + + --shift; + } while (shift >= 0); + + /* The display sends ACK by preventing the SDA from going high + * after the SCL pulse we use to send our last data bit. + * If the SDA goes high after that bit, it's a NACK */ + + udelay(clock_delay_div_4); + + write_bit_to_ddc(ddc_handle, SDA, true); + + udelay(clock_delay_div_4); + + write_bit_to_ddc(ddc_handle, SCL, true); + + if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4)) + return false; + + /* read ACK bit */ + + ack = !read_bit_from_ddc(ddc_handle, SDA); + + udelay(clock_delay_div_4 << 1); + + write_bit_to_ddc(ddc_handle, SCL, false); + + udelay(clock_delay_div_4 << 1); + + return ack; +} + +static bool read_byte( + struct dc_context *ctx, + struct ddc *ddc_handle, + uint16_t clock_delay_div_4, + uint8_t *byte, + bool more) +{ + int32_t shift = 7; + + uint8_t data = 0; + + /* The data bits are read from MSB to LSB; + * bit is read while SCL is high */ + + do { + write_bit_to_ddc(ddc_handle, SCL, true); + + if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4)) + return false; + + if (read_bit_from_ddc(ddc_handle, SDA)) + data |= (1 << shift); + + write_bit_to_ddc(ddc_handle, SCL, false); + + udelay(clock_delay_div_4 << 1); + + --shift; + } while (shift >= 0); + + /* read only whole byte */ + + *byte = data; + + udelay(clock_delay_div_4); + + /* send the acknowledge bit: + * SDA low means ACK, SDA high means NACK */ + + write_bit_to_ddc(ddc_handle, SDA, !more); + + udelay(clock_delay_div_4); + + write_bit_to_ddc(ddc_handle, SCL, true); + + if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4)) + return false; + + write_bit_to_ddc(ddc_handle, SCL, false); + + udelay(clock_delay_div_4); + + write_bit_to_ddc(ddc_handle, SDA, true); + + udelay(clock_delay_div_4); + + return true; +} + +static bool i2c_write( + struct dc_context *ctx, + struct ddc *ddc_handle, + uint16_t clock_delay_div_4, + uint8_t address, + uint32_t length, + const uint8_t *data) +{ + uint32_t i = 0; + + if (!write_byte(ctx, ddc_handle, clock_delay_div_4, address)) + return false; + + while (i < length) { + if (!write_byte(ctx, ddc_handle, clock_delay_div_4, data[i])) + return false; + ++i; + } + + return true; +} + +static bool i2c_read( + struct dc_context *ctx, + struct ddc *ddc_handle, + uint16_t clock_delay_div_4, + uint8_t address, + uint32_t length, + uint8_t *data) +{ + uint32_t i = 0; + + if (!write_byte(ctx, ddc_handle, clock_delay_div_4, address)) + return false; + + while (i < length) { + if (!read_byte(ctx, ddc_handle, clock_delay_div_4, data + i, + i < length - 1)) + return false; + ++i; + } + + return true; +} + +/* + * @brief + * Cast 'struct i2c_engine *' + * to 'struct i2c_sw_engine *' + */ +#define FROM_I2C_ENGINE(ptr) \ + container_of((ptr), struct i2c_sw_engine, base) + +/* + * @brief + * Cast 'struct engine *' + * to 'struct i2c_sw_engine *' + */ +#define FROM_ENGINE(ptr) \ + FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base)) + +enum i2caux_engine_type dal_i2c_sw_engine_get_engine_type( + const struct engine *engine) +{ + return I2CAUX_ENGINE_TYPE_I2C_SW; +} + +bool dal_i2c_sw_engine_submit_request( + struct engine *engine, + struct i2caux_transaction_request *i2caux_request, + bool middle_of_transaction) +{ + struct i2c_sw_engine *sw_engine = FROM_ENGINE(engine); + + struct i2c_engine *base = &sw_engine->base; + + struct i2c_request_transaction_data request; + bool operation_succeeded = false; + + if (i2caux_request->operation == I2CAUX_TRANSACTION_READ) + request.action = middle_of_transaction ? + I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT : + I2CAUX_TRANSACTION_ACTION_I2C_READ; + else if (i2caux_request->operation == I2CAUX_TRANSACTION_WRITE) + request.action = middle_of_transaction ? + I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT : + I2CAUX_TRANSACTION_ACTION_I2C_WRITE; + else { + i2caux_request->status = + I2CAUX_TRANSACTION_STATUS_FAILED_INVALID_OPERATION; + /* in DAL2, there was no "return false" */ + return false; + } + + request.address = (uint8_t)i2caux_request->payload.address; + request.length = i2caux_request->payload.length; + request.data = i2caux_request->payload.data; + + base->funcs->submit_channel_request(base, &request); + + if ((request.status == I2C_CHANNEL_OPERATION_ENGINE_BUSY) || + (request.status == I2C_CHANNEL_OPERATION_FAILED)) + i2caux_request->status = + I2CAUX_TRANSACTION_STATUS_FAILED_CHANNEL_BUSY; + else { + enum i2c_channel_operation_result operation_result; + + do { + operation_result = + base->funcs->get_channel_status(base, NULL); + + switch (operation_result) { + case I2C_CHANNEL_OPERATION_SUCCEEDED: + i2caux_request->status = + I2CAUX_TRANSACTION_STATUS_SUCCEEDED; + operation_succeeded = true; + break; + case I2C_CHANNEL_OPERATION_NO_RESPONSE: + i2caux_request->status = + I2CAUX_TRANSACTION_STATUS_FAILED_NACK; + break; + case I2C_CHANNEL_OPERATION_TIMEOUT: + i2caux_request->status = + I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; + break; + case I2C_CHANNEL_OPERATION_FAILED: + i2caux_request->status = + I2CAUX_TRANSACTION_STATUS_FAILED_INCOMPLETE; + break; + default: + i2caux_request->status = + I2CAUX_TRANSACTION_STATUS_FAILED_OPERATION; + break; + } + } while (operation_result == I2C_CHANNEL_OPERATION_ENGINE_BUSY); + } + + return operation_succeeded; +} + +uint32_t dal_i2c_sw_engine_get_speed( + const struct i2c_engine *engine) +{ + return FROM_I2C_ENGINE(engine)->speed; +} + +void dal_i2c_sw_engine_set_speed( + struct i2c_engine *engine, + uint32_t speed) +{ + struct i2c_sw_engine *sw_engine = FROM_I2C_ENGINE(engine); + + ASSERT(speed); + + sw_engine->speed = speed ? speed : I2CAUX_DEFAULT_I2C_SW_SPEED; + + sw_engine->clock_delay = 1000 / sw_engine->speed; + + if (sw_engine->clock_delay < 12) + sw_engine->clock_delay = 12; +} + +bool dal_i2caux_i2c_sw_engine_acquire_engine( + struct i2c_engine *engine, + struct ddc *ddc) +{ + enum gpio_result result; + + result = dal_ddc_open(ddc, GPIO_MODE_FAST_OUTPUT, + GPIO_DDC_CONFIG_TYPE_MODE_I2C); + + if (result != GPIO_RESULT_OK) + return false; + + engine->base.ddc = ddc; + + return true; +} + +void dal_i2c_sw_engine_submit_channel_request( + struct i2c_engine *engine, + struct i2c_request_transaction_data *req) +{ + struct i2c_sw_engine *sw_engine = FROM_I2C_ENGINE(engine); + + struct ddc *ddc = engine->base.ddc; + uint16_t clock_delay_div_4 = sw_engine->clock_delay >> 2; + + /* send sync (start / repeated start) */ + + bool result = start_sync(engine->base.ctx, ddc, clock_delay_div_4); + + /* process payload */ + + if (result) { + switch (req->action) { + case I2CAUX_TRANSACTION_ACTION_I2C_WRITE: + case I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT: + result = i2c_write(engine->base.ctx, ddc, clock_delay_div_4, + req->address, req->length, req->data); + break; + case I2CAUX_TRANSACTION_ACTION_I2C_READ: + case I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT: + result = i2c_read(engine->base.ctx, ddc, clock_delay_div_4, + req->address, req->length, req->data); + break; + default: + result = false; + break; + } + } + + /* send stop if not 'mot' or operation failed */ + + if (!result || + (req->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE) || + (req->action == I2CAUX_TRANSACTION_ACTION_I2C_READ)) + if (!stop_sync(engine->base.ctx, ddc, clock_delay_div_4)) + result = false; + + req->status = result ? + I2C_CHANNEL_OPERATION_SUCCEEDED : + I2C_CHANNEL_OPERATION_FAILED; +} + +enum i2c_channel_operation_result dal_i2c_sw_engine_get_channel_status( + struct i2c_engine *engine, + uint8_t *returned_bytes) +{ + /* No arbitration with VBIOS is performed since DCE 6.0 */ + return I2C_CHANNEL_OPERATION_SUCCEEDED; +} + +void dal_i2c_sw_engine_destruct( + struct i2c_sw_engine *engine) +{ + dal_i2c_engine_destruct(&engine->base); +} + +static void destroy( + struct i2c_engine **ptr) +{ + dal_i2c_sw_engine_destruct(FROM_I2C_ENGINE(*ptr)); + + dm_free(*ptr); + *ptr = NULL; +} + +static const struct i2c_engine_funcs i2c_engine_funcs = { + .acquire_engine = dal_i2caux_i2c_sw_engine_acquire_engine, + .destroy = destroy, + .get_speed = dal_i2c_sw_engine_get_speed, + .set_speed = dal_i2c_sw_engine_set_speed, + .setup_engine = dal_i2c_engine_setup_i2c_engine, + .submit_channel_request = dal_i2c_sw_engine_submit_channel_request, + .process_channel_reply = dal_i2c_engine_process_channel_reply, + .get_channel_status = dal_i2c_sw_engine_get_channel_status, +}; + +static void release_engine( + struct engine *engine) +{ + +} + +static const struct engine_funcs engine_funcs = { + .release_engine = release_engine, + .get_engine_type = dal_i2c_sw_engine_get_engine_type, + .acquire = dal_i2c_engine_acquire, + .submit_request = dal_i2c_sw_engine_submit_request, +}; + +bool dal_i2c_sw_engine_construct( + struct i2c_sw_engine *engine, + const struct i2c_sw_engine_create_arg *arg) +{ + if (!dal_i2c_engine_construct(&engine->base, arg->ctx)) + return false; + + dal_i2c_sw_engine_set_speed(&engine->base, arg->default_speed); + engine->base.funcs = &i2c_engine_funcs; + engine->base.base.funcs = &engine_funcs; + return true; +} + +struct i2c_engine *dal_i2c_sw_engine_create( + const struct i2c_sw_engine_create_arg *arg) +{ + struct i2c_sw_engine *engine; + + if (!arg) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + engine = dm_alloc(sizeof(struct i2c_sw_engine)); + + if (!engine) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + if (dal_i2c_sw_engine_construct(engine, arg)) + return &engine->base; + + BREAK_TO_DEBUGGER(); + + dm_free(engine); + + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.h b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.h new file mode 100644 index 000000000000..e0cb4c3d483d --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.h @@ -0,0 +1,81 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_I2C_SW_ENGINE_H__ +#define __DAL_I2C_SW_ENGINE_H__ + +enum { + I2C_SW_RETRIES = 10, + I2C_SW_SCL_READ_RETRIES = 128, + /* following value is in microseconds */ + I2C_SW_TIMEOUT_DELAY = 3000 +}; + +struct i2c_sw_engine; + +struct i2c_sw_engine { + struct i2c_engine base; + uint32_t clock_delay; + /* Values below are in KHz */ + uint32_t speed; + uint32_t default_speed; +}; + +struct i2c_sw_engine_create_arg { + uint32_t default_speed; + struct dc_context *ctx; +}; + +bool dal_i2c_sw_engine_construct( + struct i2c_sw_engine *engine, + const struct i2c_sw_engine_create_arg *arg); + +bool dal_i2caux_i2c_sw_engine_acquire_engine( + struct i2c_engine *engine, + struct ddc *ddc_handle); + +void dal_i2c_sw_engine_destruct( + struct i2c_sw_engine *engine); + +struct i2c_engine *dal_i2c_sw_engine_create( + const struct i2c_sw_engine_create_arg *arg); +enum i2caux_engine_type dal_i2c_sw_engine_get_engine_type( + const struct engine *engine); +bool dal_i2c_sw_engine_submit_request( + struct engine *ptr, + struct i2caux_transaction_request *i2caux_request, + bool middle_of_transaction); +uint32_t dal_i2c_sw_engine_get_speed( + const struct i2c_engine *engine); +void dal_i2c_sw_engine_set_speed( + struct i2c_engine *ptr, + uint32_t speed); +void dal_i2c_sw_engine_submit_channel_request( + struct i2c_engine *ptr, + struct i2c_request_transaction_data *req); +enum i2c_channel_operation_result dal_i2c_sw_engine_get_channel_status( + struct i2c_engine *engine, + uint8_t *returned_bytes); +#endif diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c new file mode 100644 index 000000000000..5391655af23a --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c @@ -0,0 +1,459 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* + * Pre-requisites: headers required by header of this unit + */ +#include "include/i2caux_interface.h" +#include "dc_bios_types.h" + +/* + * Header of this unit + */ + +#include "i2caux.h" + +/* + * Post-requisites: headers required by this unit + */ + +#include "engine.h" +#include "i2c_engine.h" +#include "aux_engine.h" + +/* + * This unit + */ + +#include "dce80/i2caux_dce80.h" + +#include "dce100/i2caux_dce100.h" + +#include "dce110/i2caux_dce110.h" + +#include "dce112/i2caux_dce112.h" + +#include "diagnostics/i2caux_diag.h" + +/* + * @brief + * Plain API, available publicly + */ + +struct i2caux *dal_i2caux_create( + struct dc_context *ctx) +{ + if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment)) { + return dal_i2caux_diag_fpga_create(ctx); + } + + switch (ctx->dce_version) { + case DCE_VERSION_8_0: + return dal_i2caux_dce80_create(ctx); + case DCE_VERSION_11_2: + return dal_i2caux_dce112_create(ctx); + case DCE_VERSION_11_0: + return dal_i2caux_dce110_create(ctx); + case DCE_VERSION_10_0: + return dal_i2caux_dce100_create(ctx); + default: + BREAK_TO_DEBUGGER(); + return NULL; + } +} + +bool dal_i2caux_submit_i2c_command( + struct i2caux *i2caux, + struct ddc *ddc, + struct i2c_command *cmd) +{ + struct i2c_engine *engine; + uint8_t index_of_payload = 0; + bool result; + + if (!ddc) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!cmd) { + BREAK_TO_DEBUGGER(); + return false; + } + + /* + * default will be SW, however there is a feature flag in adapter + * service that determines whether SW i2c_engine will be available or + * not, if sw i2c is not available we will fallback to hw. This feature + * flag is set to not creating sw i2c engine for every dce except dce80 + * currently + */ + switch (cmd->engine) { + case I2C_COMMAND_ENGINE_DEFAULT: + case I2C_COMMAND_ENGINE_SW: + /* try to acquire SW engine first, + * acquire HW engine if SW engine not available */ + engine = i2caux->funcs->acquire_i2c_sw_engine(i2caux, ddc); + + if (!engine) + engine = i2caux->funcs->acquire_i2c_hw_engine( + i2caux, ddc); + break; + case I2C_COMMAND_ENGINE_HW: + default: + /* try to acquire HW engine first, + * acquire SW engine if HW engine not available */ + engine = i2caux->funcs->acquire_i2c_hw_engine(i2caux, ddc); + + if (!engine) + engine = i2caux->funcs->acquire_i2c_sw_engine( + i2caux, ddc); + } + + if (!engine) + return false; + + engine->funcs->set_speed(engine, cmd->speed); + + result = true; + + while (index_of_payload < cmd->number_of_payloads) { + bool mot = (index_of_payload != cmd->number_of_payloads - 1); + + struct i2c_payload *payload = cmd->payloads + index_of_payload; + + struct i2caux_transaction_request request = { 0 }; + + request.operation = payload->write ? + I2CAUX_TRANSACTION_WRITE : + I2CAUX_TRANSACTION_READ; + + request.payload.address_space = + I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C; + request.payload.address = (payload->address << 1) | + !payload->write; + request.payload.length = payload->length; + request.payload.data = payload->data; + + if (!engine->base.funcs->submit_request( + &engine->base, &request, mot)) { + result = false; + break; + } + + ++index_of_payload; + } + + i2caux->funcs->release_engine(i2caux, &engine->base); + + return result; +} + +bool dal_i2caux_submit_aux_command( + struct i2caux *i2caux, + struct ddc *ddc, + struct aux_command *cmd) +{ + struct aux_engine *engine; + uint8_t index_of_payload = 0; + bool result; + + if (!ddc) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!cmd) { + BREAK_TO_DEBUGGER(); + return false; + } + + engine = i2caux->funcs->acquire_aux_engine(i2caux, ddc); + + if (!engine) + return false; + + engine->delay = cmd->defer_delay; + engine->max_defer_write_retry = cmd->max_defer_write_retry; + + result = true; + + while (index_of_payload < cmd->number_of_payloads) { + bool mot = (index_of_payload != cmd->number_of_payloads - 1); + + struct aux_payload *payload = cmd->payloads + index_of_payload; + + struct i2caux_transaction_request request = { 0 }; + + request.operation = payload->write ? + I2CAUX_TRANSACTION_WRITE : + I2CAUX_TRANSACTION_READ; + + if (payload->i2c_over_aux) { + request.payload.address_space = + I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C; + + request.payload.address = (payload->address << 1) | + !payload->write; + } else { + request.payload.address_space = + I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD; + + request.payload.address = payload->address; + } + + request.payload.length = payload->length; + request.payload.data = payload->data; + + if (!engine->base.funcs->submit_request( + &engine->base, &request, mot)) { + result = false; + break; + } + + ++index_of_payload; + } + + i2caux->funcs->release_engine(i2caux, &engine->base); + + return result; +} + +static bool get_hw_supported_ddc_line( + struct ddc *ddc, + enum gpio_ddc_line *line) +{ + enum gpio_ddc_line line_found; + + if (!ddc) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!ddc->hw_info.hw_supported) + return false; + + line_found = dal_ddc_get_line(ddc); + + if (line_found >= GPIO_DDC_LINE_COUNT) + return false; + + *line = line_found; + + return true; +} + +void dal_i2caux_configure_aux( + struct i2caux *i2caux, + struct ddc *ddc, + union aux_config cfg) +{ + struct aux_engine *engine = + i2caux->funcs->acquire_aux_engine(i2caux, ddc); + + if (!engine) + return; + + engine->funcs->configure(engine, cfg); + + i2caux->funcs->release_engine(i2caux, &engine->base); +} + +void dal_i2caux_destroy( + struct i2caux **i2caux) +{ + if (!i2caux || !*i2caux) { + BREAK_TO_DEBUGGER(); + return; + } + + (*i2caux)->funcs->destroy(i2caux); + + *i2caux = NULL; +} + +/* + * @brief + * An utility function used by 'struct i2caux' and its descendants + */ + +uint32_t dal_i2caux_get_reference_clock( + struct dc_bios *bios) +{ + struct firmware_info info = { { 0 } }; + + if (bios->funcs->get_firmware_info(bios, &info) != BP_RESULT_OK) + return 0; + + return info.pll_info.crystal_frequency; +} + +/* + * @brief + * i2caux + */ + +enum { + /* following are expressed in KHz */ + DEFAULT_I2C_SW_SPEED = 50, + DEFAULT_I2C_HW_SPEED = 50, + + /* This is the timeout as defined in DP 1.2a, + * 2.3.4 "Detailed uPacket TX AUX CH State Description". */ + AUX_TIMEOUT_PERIOD = 400, + + /* Ideally, the SW timeout should be just above 550usec + * which is programmed in HW. + * But the SW timeout of 600usec is not reliable, + * because on some systems, delay_in_microseconds() + * returns faster than it should. + * EPR #379763: by trial-and-error on different systems, + * 700usec is the minimum reliable SW timeout for polling + * the AUX_SW_STATUS.AUX_SW_DONE bit. + * This timeout expires *only* when there is + * AUX Error or AUX Timeout conditions - not during normal operation. + * During normal operation, AUX_SW_STATUS.AUX_SW_DONE bit is set + * at most within ~240usec. That means, + * increasing this timeout will not affect normal operation, + * and we'll timeout after + * SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD = 1600usec. + * This timeout is especially important for + * resume from S3 and CTS. */ + SW_AUX_TIMEOUT_PERIOD_MULTIPLIER = 4 +}; + +struct i2c_engine *dal_i2caux_acquire_i2c_sw_engine( + struct i2caux *i2caux, + struct ddc *ddc) +{ + enum gpio_ddc_line line; + struct i2c_engine *engine = NULL; + + if (get_hw_supported_ddc_line(ddc, &line)) + engine = i2caux->i2c_sw_engines[line]; + + if (!engine) + engine = i2caux->i2c_generic_sw_engine; + + if (!engine) + return NULL; + + if (!engine->base.funcs->acquire(&engine->base, ddc)) + return NULL; + + return engine; +} + +struct aux_engine *dal_i2caux_acquire_aux_engine( + struct i2caux *i2caux, + struct ddc *ddc) +{ + enum gpio_ddc_line line; + struct aux_engine *engine; + + if (!get_hw_supported_ddc_line(ddc, &line)) + return NULL; + + engine = i2caux->aux_engines[line]; + + if (!engine) + return NULL; + + if (!engine->base.funcs->acquire(&engine->base, ddc)) + return NULL; + + return engine; +} + +void dal_i2caux_release_engine( + struct i2caux *i2caux, + struct engine *engine) +{ + engine->funcs->release_engine(engine); + + dal_ddc_close(engine->ddc); + + engine->ddc = NULL; +} + +bool dal_i2caux_construct( + struct i2caux *i2caux, + struct dc_context *ctx) +{ + uint32_t i = 0; + + i2caux->ctx = ctx; + do { + i2caux->i2c_sw_engines[i] = NULL; + i2caux->i2c_hw_engines[i] = NULL; + i2caux->aux_engines[i] = NULL; + + ++i; + } while (i < GPIO_DDC_LINE_COUNT); + + i2caux->i2c_generic_sw_engine = NULL; + i2caux->i2c_generic_hw_engine = NULL; + + i2caux->aux_timeout_period = + SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD; + + i2caux->default_i2c_sw_speed = DEFAULT_I2C_SW_SPEED; + i2caux->default_i2c_hw_speed = DEFAULT_I2C_HW_SPEED; + + return true; +} + +void dal_i2caux_destruct( + struct i2caux *i2caux) +{ + uint32_t i = 0; + + if (i2caux->i2c_generic_hw_engine) + i2caux->i2c_generic_hw_engine->funcs->destroy( + &i2caux->i2c_generic_hw_engine); + + if (i2caux->i2c_generic_sw_engine) + i2caux->i2c_generic_sw_engine->funcs->destroy( + &i2caux->i2c_generic_sw_engine); + + do { + if (i2caux->aux_engines[i]) + i2caux->aux_engines[i]->funcs->destroy( + &i2caux->aux_engines[i]); + + if (i2caux->i2c_hw_engines[i]) + i2caux->i2c_hw_engines[i]->funcs->destroy( + &i2caux->i2c_hw_engines[i]); + + if (i2caux->i2c_sw_engines[i]) + i2caux->i2c_sw_engines[i]->funcs->destroy( + &i2caux->i2c_sw_engines[i]); + + ++i; + } while (i < GPIO_DDC_LINE_COUNT); +} + diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.h b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.h new file mode 100644 index 000000000000..bc20de3da1c4 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.h @@ -0,0 +1,122 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_I2C_AUX_H__ +#define __DAL_I2C_AUX_H__ + +uint32_t dal_i2caux_get_reference_clock( + struct dc_bios *bios); + +struct i2caux; + +struct engine; + +struct i2caux_funcs { + void (*destroy)(struct i2caux **ptr); + struct i2c_engine * (*acquire_i2c_sw_engine)( + struct i2caux *i2caux, + struct ddc *ddc); + struct i2c_engine * (*acquire_i2c_hw_engine)( + struct i2caux *i2caux, + struct ddc *ddc); + struct aux_engine * (*acquire_aux_engine)( + struct i2caux *i2caux, + struct ddc *ddc); + void (*release_engine)( + struct i2caux *i2caux, + struct engine *engine); +}; + +struct i2c_engine; +struct aux_engine; + +struct i2caux { + struct dc_context *ctx; + const struct i2caux_funcs *funcs; + /* On ASIC we have certain amount of lines with HW DDC engine + * (4, 6, or maybe more in the future). + * For every such line, we create separate HW DDC engine + * (since we have these engines in HW) and separate SW DDC engine + * (to allow concurrent use of few lines). + * In similar way we have AUX engines. */ + + /* I2C SW engines, per DDC line. + * Only lines with HW DDC support will be initialized */ + struct i2c_engine *i2c_sw_engines[GPIO_DDC_LINE_COUNT]; + + /* I2C HW engines, per DDC line. + * Only lines with HW DDC support will be initialized */ + struct i2c_engine *i2c_hw_engines[GPIO_DDC_LINE_COUNT]; + + /* AUX engines, per DDC line. + * Only lines with HW AUX support will be initialized */ + struct aux_engine *aux_engines[GPIO_DDC_LINE_COUNT]; + + /* For all other lines, we can use + * single instance of generic I2C HW engine + * (since in HW, there is single instance of it) + * or single instance of generic I2C SW engine. + * AUX is not supported for other lines. */ + + /* General-purpose I2C SW engine. + * Can be assigned dynamically to any line per transaction */ + struct i2c_engine *i2c_generic_sw_engine; + + /* General-purpose I2C generic HW engine. + * Can be assigned dynamically to almost any line per transaction */ + struct i2c_engine *i2c_generic_hw_engine; + + /* [anaumov] in DAL2, there is a Mutex */ + + uint32_t aux_timeout_period; + + /* expressed in KHz */ + uint32_t default_i2c_sw_speed; + uint32_t default_i2c_hw_speed; +}; + +bool dal_i2caux_construct( + struct i2caux *i2caux, + struct dc_context *ctx); + +void dal_i2caux_release_engine( + struct i2caux *i2caux, + struct engine *engine); + +void dal_i2caux_destruct( + struct i2caux *i2caux); + +void dal_i2caux_destroy( + struct i2caux **ptr); + +struct i2c_engine *dal_i2caux_acquire_i2c_sw_engine( + struct i2caux *i2caux, + struct ddc *ddc); + +struct aux_engine *dal_i2caux_acquire_aux_engine( + struct i2caux *i2caux, + struct ddc *ddc); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/bandwidth_calcs.h b/drivers/gpu/drm/amd/display/dc/inc/bandwidth_calcs.h new file mode 100644 index 000000000000..f9b871b6199b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/bandwidth_calcs.h @@ -0,0 +1,503 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +/** + * Bandwidth and Watermark calculations interface. + * (Refer to "DCEx_mode_support.xlsm" from Perforce.) + */ +#ifndef __BANDWIDTH_CALCS_H__ +#define __BANDWIDTH_CALCS_H__ + +#include "bw_fixed.h" + +struct pipe_ctx; + +enum bw_calcs_version { + BW_CALCS_VERSION_INVALID, + BW_CALCS_VERSION_CARRIZO, + BW_CALCS_VERSION_POLARIS10, + BW_CALCS_VERSION_POLARIS11, + BW_CALCS_VERSION_STONEY, +}; + +/******************************************************************************* + * There are three types of input into Calculations: + * 1. per-DCE static values - these are "hardcoded" properties of the DCEIP + * 2. board-level values - these are generally coming from VBIOS parser + * 3. mode/configuration values - depending Mode, Scaling number of Displays etc. + ******************************************************************************/ + +enum bw_defines { + //Common + bw_def_no = 0, + bw_def_none = 0, + bw_def_yes = 1, + bw_def_ok = 1, + bw_def_high = 2, + bw_def_mid = 1, + bw_def_low = 0, + + //Internal + bw_defs_start = 255, + bw_def_underlay422, + bw_def_underlay420_luma, + bw_def_underlay420_chroma, + bw_def_underlay444, + bw_def_graphics, + bw_def_display_write_back420_luma, + bw_def_display_write_back420_chroma, + bw_def_portrait, + bw_def_hsr_mtn_4, + bw_def_hsr_mtn_h_taps, + bw_def_ceiling__h_taps_div_4___meq_hsr, + bw_def_invalid_linear_or_stereo_mode, + bw_def_invalid_rotation_or_bpp_or_stereo, + bw_def_vsr_mtn_v_taps, + bw_def_vsr_mtn_4, + bw_def_auto, + bw_def_manual, + bw_def_exceeded_allowed_maximum_sclk, + bw_def_exceeded_allowed_page_close_open, + bw_def_exceeded_allowed_outstanding_pte_req_queue_size, + bw_def_exceeded_allowed_maximum_bw, + bw_def_landscape, + + //Panning and bezel + bw_def_any_lines, + + //Underlay mode + bw_def_underlay_only, + bw_def_blended, + bw_def_blend, + + //Stereo mode + bw_def_mono, + bw_def_side_by_side, + bw_def_top_bottom, + + //Underlay surface type + bw_def_420, + bw_def_422, + bw_def_444, + + //Tiling mode + bw_def_linear, + bw_def_tiled, + bw_def_array_linear_general, + bw_def_array_linear_aligned, + bw_def_rotated_micro_tiling, + bw_def_display_micro_tiling, + + //Memory type + bw_def_gddr5, + bw_def_hbm, + + //Voltage + bw_def_high_no_nbp_state_change, + bw_def_0_72, + bw_def_0_8, + bw_def_0_9, + + bw_def_notok = -1, + bw_def_na = -1 +}; + +struct bw_calcs_dceip { + enum bw_calcs_version version; + bool large_cursor; + uint32_t cursor_max_outstanding_group_num; + bool dmif_pipe_en_fbc_chunk_tracker; + struct bw_fixed dmif_request_buffer_size; + uint32_t lines_interleaved_into_lb; + uint32_t low_power_tiling_mode; + uint32_t chunk_width; + uint32_t number_of_graphics_pipes; + uint32_t number_of_underlay_pipes; + bool display_write_back_supported; + bool argb_compression_support; + struct bw_fixed underlay_vscaler_efficiency6_bit_per_component; + struct bw_fixed underlay_vscaler_efficiency8_bit_per_component; + struct bw_fixed underlay_vscaler_efficiency10_bit_per_component; + struct bw_fixed underlay_vscaler_efficiency12_bit_per_component; + struct bw_fixed graphics_vscaler_efficiency6_bit_per_component; + struct bw_fixed graphics_vscaler_efficiency8_bit_per_component; + struct bw_fixed graphics_vscaler_efficiency10_bit_per_component; + struct bw_fixed graphics_vscaler_efficiency12_bit_per_component; + struct bw_fixed alpha_vscaler_efficiency; + uint32_t max_dmif_buffer_allocated; + uint32_t graphics_dmif_size; + uint32_t underlay_luma_dmif_size; + uint32_t underlay_chroma_dmif_size; + bool pre_downscaler_enabled; + bool underlay_downscale_prefetch_enabled; + struct bw_fixed lb_write_pixels_per_dispclk; + struct bw_fixed lb_size_per_component444; + bool graphics_lb_nodownscaling_multi_line_prefetching; + struct bw_fixed stutter_and_dram_clock_state_change_gated_before_cursor; + struct bw_fixed underlay420_luma_lb_size_per_component; + struct bw_fixed underlay420_chroma_lb_size_per_component; + struct bw_fixed underlay422_lb_size_per_component; + struct bw_fixed cursor_chunk_width; + struct bw_fixed cursor_dcp_buffer_lines; + struct bw_fixed underlay_maximum_width_efficient_for_tiling; + struct bw_fixed underlay_maximum_height_efficient_for_tiling; + struct bw_fixed peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display; + struct bw_fixed peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation; + struct bw_fixed minimum_outstanding_pte_request_limit; + struct bw_fixed maximum_total_outstanding_pte_requests_allowed_by_saw; + bool limit_excessive_outstanding_dmif_requests; + struct bw_fixed linear_mode_line_request_alternation_slice; + uint32_t scatter_gather_lines_of_pte_prefetching_in_linear_mode; + uint32_t display_write_back420_luma_mcifwr_buffer_size; + uint32_t display_write_back420_chroma_mcifwr_buffer_size; + struct bw_fixed request_efficiency; + struct bw_fixed dispclk_per_request; + struct bw_fixed dispclk_ramping_factor; + struct bw_fixed display_pipe_throughput_factor; + uint32_t scatter_gather_pte_request_rows_in_tiling_mode; + struct bw_fixed mcifwr_all_surfaces_burst_time; +}; + +struct bw_calcs_vbios { + enum bw_defines memory_type; + uint32_t dram_channel_width_in_bits; + uint32_t number_of_dram_channels; + uint32_t number_of_dram_banks; + struct bw_fixed low_yclk; /*m_hz*/ + struct bw_fixed mid_yclk; /*m_hz*/ + struct bw_fixed high_yclk; /*m_hz*/ + struct bw_fixed low_sclk; /*m_hz*/ + struct bw_fixed mid1_sclk; /*m_hz*/ + struct bw_fixed mid2_sclk; /*m_hz*/ + struct bw_fixed mid3_sclk; /*m_hz*/ + struct bw_fixed mid4_sclk; /*m_hz*/ + struct bw_fixed mid5_sclk; /*m_hz*/ + struct bw_fixed mid6_sclk; /*m_hz*/ + struct bw_fixed high_sclk; /*m_hz*/ + struct bw_fixed low_voltage_max_dispclk; /*m_hz*/ + struct bw_fixed mid_voltage_max_dispclk; /*m_hz*/ + struct bw_fixed high_voltage_max_dispclk; /*m_hz*/ + struct bw_fixed low_voltage_max_phyclk; + struct bw_fixed mid_voltage_max_phyclk; + struct bw_fixed high_voltage_max_phyclk; + struct bw_fixed data_return_bus_width; + struct bw_fixed trc; + struct bw_fixed dmifmc_urgent_latency; + struct bw_fixed stutter_self_refresh_exit_latency; + struct bw_fixed stutter_self_refresh_entry_latency; + struct bw_fixed nbp_state_change_latency; + struct bw_fixed mcifwrmc_urgent_latency; + bool scatter_gather_enable; + struct bw_fixed down_spread_percentage; + uint32_t cursor_width; + uint32_t average_compression_rate; + uint32_t number_of_request_slots_gmc_reserves_for_dmif_per_channel; + struct bw_fixed blackout_duration; + struct bw_fixed maximum_blackout_recovery_time; +}; + +/******************************************************************************* + * Temporary data structure(s). + ******************************************************************************/ +#define maximum_number_of_surfaces 12 +/*Units : MHz, us */ + +struct bw_calcs_data { + /* data for all displays */ + uint32_t number_of_displays; + enum bw_defines underlay_surface_type; + enum bw_defines panning_and_bezel_adjustment; + enum bw_defines graphics_tiling_mode; + uint32_t graphics_lb_bpc; + uint32_t underlay_lb_bpc; + enum bw_defines underlay_tiling_mode; + enum bw_defines d0_underlay_mode; + bool d1_display_write_back_dwb_enable; + enum bw_defines d1_underlay_mode; + + bool cpup_state_change_enable; + bool cpuc_state_change_enable; + bool nbp_state_change_enable; + bool stutter_mode_enable; + uint32_t y_clk_level; + uint32_t sclk_level; + uint32_t number_of_underlay_surfaces; + uint32_t number_of_dram_wrchannels; + uint32_t chunk_request_delay; + uint32_t number_of_dram_channels; + enum bw_defines underlay_micro_tile_mode; + enum bw_defines graphics_micro_tile_mode; + struct bw_fixed max_phyclk; + struct bw_fixed dram_efficiency; + struct bw_fixed src_width_after_surface_type; + struct bw_fixed src_height_after_surface_type; + struct bw_fixed hsr_after_surface_type; + struct bw_fixed vsr_after_surface_type; + struct bw_fixed src_width_after_rotation; + struct bw_fixed src_height_after_rotation; + struct bw_fixed hsr_after_rotation; + struct bw_fixed vsr_after_rotation; + struct bw_fixed source_height_pixels; + struct bw_fixed hsr_after_stereo; + struct bw_fixed vsr_after_stereo; + struct bw_fixed source_width_in_lb; + struct bw_fixed lb_line_pitch; + struct bw_fixed underlay_maximum_source_efficient_for_tiling; + struct bw_fixed num_lines_at_frame_start; + struct bw_fixed min_dmif_size_in_time; + struct bw_fixed min_mcifwr_size_in_time; + struct bw_fixed total_requests_for_dmif_size; + struct bw_fixed peak_pte_request_to_eviction_ratio_limiting; + struct bw_fixed useful_pte_per_pte_request; + struct bw_fixed scatter_gather_pte_request_rows; + struct bw_fixed scatter_gather_row_height; + struct bw_fixed scatter_gather_pte_requests_in_vblank; + struct bw_fixed inefficient_linear_pitch_in_bytes; + struct bw_fixed cursor_total_data; + struct bw_fixed cursor_total_request_groups; + struct bw_fixed scatter_gather_total_pte_requests; + struct bw_fixed scatter_gather_total_pte_request_groups; + struct bw_fixed tile_width_in_pixels; + struct bw_fixed dmif_total_number_of_data_request_page_close_open; + struct bw_fixed mcifwr_total_number_of_data_request_page_close_open; + struct bw_fixed bytes_per_page_close_open; + struct bw_fixed mcifwr_total_page_close_open_time; + struct bw_fixed total_requests_for_adjusted_dmif_size; + struct bw_fixed total_dmifmc_urgent_trips; + struct bw_fixed total_dmifmc_urgent_latency; + struct bw_fixed total_display_reads_required_data; + struct bw_fixed total_display_reads_required_dram_access_data; + struct bw_fixed total_display_writes_required_data; + struct bw_fixed total_display_writes_required_dram_access_data; + struct bw_fixed display_reads_required_data; + struct bw_fixed display_reads_required_dram_access_data; + struct bw_fixed dmif_total_page_close_open_time; + struct bw_fixed min_cursor_memory_interface_buffer_size_in_time; + struct bw_fixed min_read_buffer_size_in_time; + struct bw_fixed display_reads_time_for_data_transfer; + struct bw_fixed display_writes_time_for_data_transfer; + struct bw_fixed dmif_required_dram_bandwidth; + struct bw_fixed mcifwr_required_dram_bandwidth; + struct bw_fixed required_dmifmc_urgent_latency_for_page_close_open; + struct bw_fixed required_mcifmcwr_urgent_latency; + struct bw_fixed required_dram_bandwidth_gbyte_per_second; + struct bw_fixed dram_bandwidth; + struct bw_fixed dmif_required_sclk; + struct bw_fixed mcifwr_required_sclk; + struct bw_fixed required_sclk; + struct bw_fixed downspread_factor; + struct bw_fixed v_scaler_efficiency; + struct bw_fixed scaler_limits_factor; + struct bw_fixed display_pipe_pixel_throughput; + struct bw_fixed total_dispclk_required_with_ramping; + struct bw_fixed total_dispclk_required_without_ramping; + struct bw_fixed total_read_request_bandwidth; + struct bw_fixed total_write_request_bandwidth; + struct bw_fixed dispclk_required_for_total_read_request_bandwidth; + struct bw_fixed total_dispclk_required_with_ramping_with_request_bandwidth; + struct bw_fixed total_dispclk_required_without_ramping_with_request_bandwidth; + struct bw_fixed dispclk; + struct bw_fixed blackout_recovery_time; + struct bw_fixed min_pixels_per_data_fifo_entry; + struct bw_fixed sclk_deep_sleep; + struct bw_fixed chunk_request_time; + struct bw_fixed cursor_request_time; + struct bw_fixed line_source_pixels_transfer_time; + struct bw_fixed dmifdram_access_efficiency; + struct bw_fixed mcifwrdram_access_efficiency; + struct bw_fixed total_average_bandwidth_no_compression; + struct bw_fixed total_average_bandwidth; + struct bw_fixed total_stutter_cycle_duration; + struct bw_fixed stutter_burst_time; + struct bw_fixed time_in_self_refresh; + struct bw_fixed stutter_efficiency; + struct bw_fixed worst_number_of_trips_to_memory; + struct bw_fixed immediate_flip_time; + struct bw_fixed latency_for_non_dmif_clients; + struct bw_fixed latency_for_non_mcifwr_clients; + struct bw_fixed dmifmc_urgent_latency_supported_in_high_sclk_and_yclk; + struct bw_fixed nbp_state_dram_speed_change_margin; + struct bw_fixed display_reads_time_for_data_transfer_and_urgent_latency; + struct bw_fixed dram_speed_change_margin; + struct bw_fixed min_vblank_dram_speed_change_margin; + struct bw_fixed min_stutter_refresh_duration; + uint32_t total_stutter_dmif_buffer_size; + uint32_t total_bytes_requested; + uint32_t min_stutter_dmif_buffer_size; + uint32_t num_stutter_bursts; + struct bw_fixed v_blank_nbp_state_dram_speed_change_latency_supported; + struct bw_fixed nbp_state_dram_speed_change_latency_supported; + bool fbc_en[maximum_number_of_surfaces]; + bool lpt_en[maximum_number_of_surfaces]; + bool displays_match_flag[maximum_number_of_surfaces]; + bool use_alpha[maximum_number_of_surfaces]; + bool orthogonal_rotation[maximum_number_of_surfaces]; + bool enable[maximum_number_of_surfaces]; + bool access_one_channel_only[maximum_number_of_surfaces]; + bool scatter_gather_enable_for_pipe[maximum_number_of_surfaces]; + bool interlace_mode[maximum_number_of_surfaces]; + bool display_pstate_change_enable[maximum_number_of_surfaces]; + bool line_buffer_prefetch[maximum_number_of_surfaces]; + uint32_t bytes_per_pixel[maximum_number_of_surfaces]; + uint32_t max_chunks_non_fbc_mode[maximum_number_of_surfaces]; + uint32_t lb_bpc[maximum_number_of_surfaces]; + uint32_t output_bpphdmi[maximum_number_of_surfaces]; + uint32_t output_bppdp4_lane_hbr[maximum_number_of_surfaces]; + uint32_t output_bppdp4_lane_hbr2[maximum_number_of_surfaces]; + uint32_t output_bppdp4_lane_hbr3[maximum_number_of_surfaces]; + enum bw_defines stereo_mode[maximum_number_of_surfaces]; + struct bw_fixed dmif_buffer_transfer_time[maximum_number_of_surfaces]; + struct bw_fixed displays_with_same_mode[maximum_number_of_surfaces]; + struct bw_fixed stutter_dmif_buffer_size[maximum_number_of_surfaces]; + struct bw_fixed stutter_refresh_duration[maximum_number_of_surfaces]; + struct bw_fixed stutter_exit_watermark[maximum_number_of_surfaces]; + struct bw_fixed stutter_entry_watermark[maximum_number_of_surfaces]; + struct bw_fixed h_total[maximum_number_of_surfaces]; + struct bw_fixed v_total[maximum_number_of_surfaces]; + struct bw_fixed pixel_rate[maximum_number_of_surfaces]; + struct bw_fixed src_width[maximum_number_of_surfaces]; + struct bw_fixed pitch_in_pixels[maximum_number_of_surfaces]; + struct bw_fixed pitch_in_pixels_after_surface_type[maximum_number_of_surfaces]; + struct bw_fixed src_height[maximum_number_of_surfaces]; + struct bw_fixed scale_ratio[maximum_number_of_surfaces]; + struct bw_fixed h_taps[maximum_number_of_surfaces]; + struct bw_fixed v_taps[maximum_number_of_surfaces]; + struct bw_fixed h_scale_ratio[maximum_number_of_surfaces]; + struct bw_fixed v_scale_ratio[maximum_number_of_surfaces]; + struct bw_fixed rotation_angle[maximum_number_of_surfaces]; + struct bw_fixed compression_rate[maximum_number_of_surfaces]; + struct bw_fixed hsr[maximum_number_of_surfaces]; + struct bw_fixed vsr[maximum_number_of_surfaces]; + struct bw_fixed source_width_rounded_up_to_chunks[maximum_number_of_surfaces]; + struct bw_fixed source_width_pixels[maximum_number_of_surfaces]; + struct bw_fixed source_height_rounded_up_to_chunks[maximum_number_of_surfaces]; + struct bw_fixed display_bandwidth[maximum_number_of_surfaces]; + struct bw_fixed request_bandwidth[maximum_number_of_surfaces]; + struct bw_fixed bytes_per_request[maximum_number_of_surfaces]; + struct bw_fixed useful_bytes_per_request[maximum_number_of_surfaces]; + struct bw_fixed lines_interleaved_in_mem_access[maximum_number_of_surfaces]; + struct bw_fixed latency_hiding_lines[maximum_number_of_surfaces]; + struct bw_fixed lb_partitions[maximum_number_of_surfaces]; + struct bw_fixed lb_partitions_max[maximum_number_of_surfaces]; + struct bw_fixed dispclk_required_with_ramping[maximum_number_of_surfaces]; + struct bw_fixed dispclk_required_without_ramping[maximum_number_of_surfaces]; + struct bw_fixed data_buffer_size[maximum_number_of_surfaces]; + struct bw_fixed outstanding_chunk_request_limit[maximum_number_of_surfaces]; + struct bw_fixed urgent_watermark[maximum_number_of_surfaces]; + struct bw_fixed nbp_state_change_watermark[maximum_number_of_surfaces]; + struct bw_fixed v_filter_init[maximum_number_of_surfaces]; + struct bw_fixed stutter_cycle_duration[maximum_number_of_surfaces]; + struct bw_fixed average_bandwidth[maximum_number_of_surfaces]; + struct bw_fixed average_bandwidth_no_compression[maximum_number_of_surfaces]; + struct bw_fixed scatter_gather_pte_request_limit[maximum_number_of_surfaces]; + struct bw_fixed lb_size_per_component[maximum_number_of_surfaces]; + struct bw_fixed memory_chunk_size_in_bytes[maximum_number_of_surfaces]; + struct bw_fixed pipe_chunk_size_in_bytes[maximum_number_of_surfaces]; + struct bw_fixed number_of_trips_to_memory_for_getting_apte_row[maximum_number_of_surfaces]; + struct bw_fixed adjusted_data_buffer_size[maximum_number_of_surfaces]; + struct bw_fixed adjusted_data_buffer_size_in_memory[maximum_number_of_surfaces]; + struct bw_fixed pixels_per_data_fifo_entry[maximum_number_of_surfaces]; + struct bw_fixed scatter_gather_pte_requests_in_row[maximum_number_of_surfaces]; + struct bw_fixed pte_request_per_chunk[maximum_number_of_surfaces]; + struct bw_fixed scatter_gather_page_width[maximum_number_of_surfaces]; + struct bw_fixed scatter_gather_page_height[maximum_number_of_surfaces]; + struct bw_fixed lb_lines_in_per_line_out_in_beginning_of_frame[maximum_number_of_surfaces]; + struct bw_fixed lb_lines_in_per_line_out_in_middle_of_frame[maximum_number_of_surfaces]; + struct bw_fixed cursor_width_pixels[maximum_number_of_surfaces]; + struct bw_fixed minimum_latency_hiding[maximum_number_of_surfaces]; + struct bw_fixed maximum_latency_hiding[maximum_number_of_surfaces]; + struct bw_fixed minimum_latency_hiding_with_cursor[maximum_number_of_surfaces]; + struct bw_fixed maximum_latency_hiding_with_cursor[maximum_number_of_surfaces]; + struct bw_fixed src_pixels_for_first_output_pixel[maximum_number_of_surfaces]; + struct bw_fixed src_pixels_for_last_output_pixel[maximum_number_of_surfaces]; + struct bw_fixed src_data_for_first_output_pixel[maximum_number_of_surfaces]; + struct bw_fixed src_data_for_last_output_pixel[maximum_number_of_surfaces]; + struct bw_fixed active_time[maximum_number_of_surfaces]; + struct bw_fixed horizontal_blank_and_chunk_granularity_factor[maximum_number_of_surfaces]; + struct bw_fixed cursor_latency_hiding[maximum_number_of_surfaces]; + struct bw_fixed v_blank_dram_speed_change_margin[maximum_number_of_surfaces]; + uint32_t num_displays_with_margin[3][8]; + struct bw_fixed dmif_burst_time[3][8]; + struct bw_fixed mcifwr_burst_time[3][8]; + struct bw_fixed line_source_transfer_time[maximum_number_of_surfaces][3][8]; + struct bw_fixed dram_speed_change_line_source_transfer_time[maximum_number_of_surfaces][3][8]; + struct bw_fixed min_dram_speed_change_margin[3][8]; + struct bw_fixed dispclk_required_for_dram_speed_change[3][8]; + struct bw_fixed blackout_duration_margin[3][8]; + struct bw_fixed dispclk_required_for_blackout_duration[3][8]; + struct bw_fixed dispclk_required_for_blackout_recovery[3][8]; + struct bw_fixed dmif_required_sclk_for_urgent_latency[6]; +}; + +/******************************************************************************* + * Output data structures. + ******************************************************************************/ +struct bw_watermarks { + uint32_t a_mark; + uint32_t b_mark; + uint32_t c_mark; + uint32_t d_mark; +}; + +struct bw_calcs_output { + bool cpuc_state_change_enable; + bool cpup_state_change_enable; + bool stutter_mode_enable; + bool nbp_state_change_enable; + bool all_displays_in_sync; + struct bw_watermarks urgent_wm_ns[6]; + struct bw_watermarks stutter_exit_wm_ns[6]; + struct bw_watermarks nbp_state_change_wm_ns[6]; + uint32_t required_sclk; + uint32_t required_sclk_deep_sleep; + uint32_t required_yclk; + uint32_t dispclk_khz; + int blackout_recovery_time_us; +}; + +/** + * Initialize structures with data which will NOT change at runtime. + */ +void bw_calcs_init( + struct bw_calcs_dceip *bw_dceip, + struct bw_calcs_vbios *bw_vbios, + enum bw_calcs_version version); + +/** + * Return: + * true - Display(s) configuration supported. + * In this case 'calcs_output' contains data for HW programming + * false - Display(s) configuration not supported (not enough bandwidth). + */ +bool bw_calcs( + struct dc_context *ctx, + const struct bw_calcs_dceip *dceip, + const struct bw_calcs_vbios *vbios, + const struct pipe_ctx *pipe, + int pipe_count, + struct bw_calcs_output *calcs_output); + +#endif /* __BANDWIDTH_CALCS_H__ */ + diff --git a/drivers/gpu/drm/amd/display/dc/inc/bw_fixed.h b/drivers/gpu/drm/amd/display/dc/inc/bw_fixed.h new file mode 100644 index 000000000000..b31d07a57c31 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/bw_fixed.h @@ -0,0 +1,63 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef BW_FIXED_H_ +#define BW_FIXED_H_ + +struct bw_fixed { + int64_t value; +}; + +struct bw_fixed bw_min3(struct bw_fixed v1, struct bw_fixed v2, struct bw_fixed v3); + +struct bw_fixed bw_max3(struct bw_fixed v1, struct bw_fixed v2, struct bw_fixed v3); + +struct bw_fixed bw_int_to_fixed(int64_t value); + +int32_t bw_fixed_to_int(struct bw_fixed value); + +struct bw_fixed bw_frc_to_fixed(int64_t num, int64_t denum); + +struct bw_fixed fixed31_32_to_bw_fixed(int64_t raw); + +struct bw_fixed bw_add(const struct bw_fixed arg1, const struct bw_fixed arg2); +struct bw_fixed bw_sub(const struct bw_fixed arg1, const struct bw_fixed arg2); +struct bw_fixed bw_mul(const struct bw_fixed arg1, const struct bw_fixed arg2); +struct bw_fixed bw_div(const struct bw_fixed arg1, const struct bw_fixed arg2); +struct bw_fixed bw_mod(const struct bw_fixed arg1, const struct bw_fixed arg2); + +struct bw_fixed bw_min2(const struct bw_fixed arg1, const struct bw_fixed arg2); +struct bw_fixed bw_max2(const struct bw_fixed arg1, const struct bw_fixed arg2); +struct bw_fixed bw_floor2(const struct bw_fixed arg, const struct bw_fixed significance); +struct bw_fixed bw_ceil2(const struct bw_fixed arg, const struct bw_fixed significance); + +bool bw_equ(const struct bw_fixed arg1, const struct bw_fixed arg2); +bool bw_neq(const struct bw_fixed arg1, const struct bw_fixed arg2); +bool bw_leq(const struct bw_fixed arg1, const struct bw_fixed arg2); +bool bw_meq(const struct bw_fixed arg1, const struct bw_fixed arg2); +bool bw_ltn(const struct bw_fixed arg1, const struct bw_fixed arg2); +bool bw_mtn(const struct bw_fixed arg1, const struct bw_fixed arg2); + +#endif //BW_FIXED_H_ diff --git a/drivers/gpu/drm/amd/display/dc/inc/clock_source.h b/drivers/gpu/drm/amd/display/dc/inc/clock_source.h new file mode 100644 index 000000000000..c91c7815ec6e --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/clock_source.h @@ -0,0 +1,178 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_CLOCK_SOURCE_H__ +#define __DC_CLOCK_SOURCE_H__ + +#include "dc_types.h" +#include "include/grph_object_id.h" +#include "include/bios_parser_types.h" + +struct clock_source; + +struct spread_spectrum_data { + uint32_t percentage; /*> In unit of 0.01% or 0.001%*/ + uint32_t percentage_divider; /*> 100 or 1000 */ + uint32_t freq_range_khz; + uint32_t modulation_freq_hz; + + struct spread_spectrum_flags flags; +}; + +struct delta_sigma_data { + uint32_t feedback_amount; + uint32_t nfrac_amount; + uint32_t ds_frac_size; + uint32_t ds_frac_amount; +}; + +/** + * Pixel Clock Parameters structure + * These parameters are required as input + * when calculating Pixel Clock Dividers for requested Pixel Clock + */ +struct pixel_clk_flags { + uint32_t ENABLE_SS:1; + uint32_t DISPLAY_BLANKED:1; + uint32_t PROGRAM_PIXEL_CLOCK:1; + uint32_t PROGRAM_ID_CLOCK:1; + uint32_t SUPPORT_YCBCR420:1; +}; + +/** + * Display Port HW De spread of Reference Clock related Parameters structure + * Store it once at boot for later usage + */ +struct csdp_ref_clk_ds_params { + bool hw_dso_n_dp_ref_clk; +/* Flag for HW De Spread enabled (if enabled SS on DP Reference Clock)*/ + uint32_t avg_dp_ref_clk_khz; +/* Average DP Reference clock (in KHz)*/ + uint32_t ss_percentage_on_dp_ref_clk; +/* DP Reference clock SS percentage + * (not to be mixed with DP IDCLK SS from PLL Settings)*/ + uint32_t ss_percentage_divider; +/* DP Reference clock SS percentage divider */ +}; + +struct pixel_clk_params { + uint32_t requested_pix_clk; /* in KHz */ +/*> Requested Pixel Clock + * (based on Video Timing standard used for requested mode)*/ + uint32_t requested_sym_clk; /* in KHz */ +/*> Requested Sym Clock (relevant only for display port)*/ + uint32_t dp_ref_clk; /* in KHz */ +/*> DP reference clock - calculated only for DP signal for specific cases*/ + struct graphics_object_id encoder_object_id; +/*> Encoder object Id - needed by VBIOS Exec table*/ + enum signal_type signal_type; +/*> signalType -> Encoder Mode - needed by VBIOS Exec table*/ + enum controller_id controller_id; +/*> ControllerId - which controller using this PLL*/ + enum dc_color_depth color_depth; + struct csdp_ref_clk_ds_params de_spread_params; +/*> de-spread info, relevant only for on-the-fly tune-up pixel rate*/ + + struct pixel_clk_flags flags; +}; + +/** + * Pixel Clock Dividers structure with desired Pixel Clock + * (adjusted after VBIOS exec table), + * with actually calculated Clock and reference Crystal frequency + */ +struct pll_settings { + uint32_t actual_pix_clk; + uint32_t adjusted_pix_clk; + uint32_t calculated_pix_clk; + uint32_t vco_freq; + uint32_t reference_freq; + uint32_t reference_divider; + uint32_t feedback_divider; + uint32_t fract_feedback_divider; + uint32_t pix_clk_post_divider; + uint32_t ss_percentage; + bool use_external_clk; +}; + +struct calc_pll_clock_source_init_data { + struct dc_bios *bp; + uint32_t min_pix_clk_pll_post_divider; + uint32_t max_pix_clk_pll_post_divider; + uint32_t min_pll_ref_divider; + uint32_t max_pll_ref_divider; + uint32_t min_override_input_pxl_clk_pll_freq_khz; +/* if not 0, override the firmware info */ + + uint32_t max_override_input_pxl_clk_pll_freq_khz; +/* if not 0, override the firmware info */ + + uint32_t num_fract_fb_divider_decimal_point; +/* number of decimal point for fractional feedback divider value */ + + uint32_t num_fract_fb_divider_decimal_point_precision; +/* number of decimal point to round off for fractional feedback divider value*/ + struct dc_context *ctx; + +}; + +struct calc_pll_clock_source { + uint32_t ref_freq_khz; + uint32_t min_pix_clock_pll_post_divider; + uint32_t max_pix_clock_pll_post_divider; + uint32_t min_pll_ref_divider; + uint32_t max_pll_ref_divider; + + uint32_t max_vco_khz; + uint32_t min_vco_khz; + uint32_t min_pll_input_freq_khz; + uint32_t max_pll_input_freq_khz; + + uint32_t fract_fb_divider_decimal_points_num; + uint32_t fract_fb_divider_factor; + uint32_t fract_fb_divider_precision; + uint32_t fract_fb_divider_precision_factor; + struct dc_context *ctx; +}; + +struct clock_source_funcs { + bool (*cs_power_down)( + struct clock_source *); + bool (*program_pix_clk)(struct clock_source *, + struct pixel_clk_params *, struct pll_settings *); + uint32_t (*get_pix_clk_dividers)( + struct clock_source *, + struct pixel_clk_params *, + struct pll_settings *); +}; + +struct clock_source { + const struct clock_source_funcs *funcs; + struct dc_context *ctx; + enum clock_source_id id; + bool dp_clk_src; +}; + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/compressor.h b/drivers/gpu/drm/amd/display/dc/inc/compressor.h new file mode 100644 index 000000000000..af292596b101 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/compressor.h @@ -0,0 +1,93 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_COMPRESSOR_H__ +#define __DAL_COMPRESSOR_H__ + +#include "include/grph_object_id.h" +#include "bios_parser_interface.h" + +enum fbc_compress_ratio { + FBC_COMPRESS_RATIO_INVALID = 0, + FBC_COMPRESS_RATIO_1TO1 = 1, + FBC_COMPRESS_RATIO_2TO1 = 2, + FBC_COMPRESS_RATIO_4TO1 = 4, + FBC_COMPRESS_RATIO_8TO1 = 8, +}; + +union fbc_physical_address { + struct { + uint32_t low_part; + int32_t high_part; + } addr; +}; + +struct compr_addr_and_pitch_params { + uint32_t inst; + uint32_t source_view_width; + uint32_t source_view_height; +}; + +enum fbc_hw_max_resolution_supported { + FBC_MAX_X = 3840, + FBC_MAX_Y = 2400 +}; + +struct compressor { + struct dc_context *ctx; + uint32_t attached_inst; + bool is_enabled; + + union { + uint32_t raw; + struct { + uint32_t FBC_SUPPORT:1; + uint32_t FB_POOL:1; + uint32_t DYNAMIC_ALLOC:1; + uint32_t LPT_SUPPORT:1; + uint32_t LPT_MC_CONFIG:1; + uint32_t DUMMY_BACKEND:1; + uint32_t CLK_GATING_DISABLED:1; + + } bits; + } options; + + union fbc_physical_address compr_surface_address; + + uint32_t embedded_panel_h_size; + uint32_t embedded_panel_v_size; + uint32_t memory_bus_width; + uint32_t banks_num; + uint32_t raw_size; + uint32_t channel_interleave_size; + uint32_t dram_channels_num; + + uint32_t allocated_size; + uint32_t preferred_requested_size; + uint32_t lpt_channels_num; + enum fbc_compress_ratio min_compress_ratio; +}; + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_dc.h b/drivers/gpu/drm/amd/display/dc/inc/core_dc.h new file mode 100644 index 000000000000..7d6dc8ea75ab --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/core_dc.h @@ -0,0 +1,50 @@ +/* + * core_dc.h + * + * Created on: Nov 13, 2015 + * Author: yonsun + */ + +#ifndef __CORE_DC_H__ +#define __CORE_DC_H__ + +#include "core_types.h" +#include "hw_sequencer.h" + +#define DC_TO_CORE(dc)\ + container_of(dc, struct core_dc, public) + +struct core_dc { + struct dc public; + struct dc_context *ctx; + + uint8_t link_count; + struct core_link *links[MAX_PIPES * 2]; + + /* TODO: determine max number of targets*/ + struct validate_context *current_context; + struct validate_context *temp_flip_context; + struct resource_pool *res_pool; + + /*Power State*/ + enum dc_video_power_state previous_power_state; + enum dc_video_power_state current_power_state; + + /* Display Engine Clock levels */ + struct dm_pp_clock_levels sclk_lvls; + + /* Inputs into BW and WM calculations. */ + struct bw_calcs_dceip bw_dceip; + struct bw_calcs_vbios bw_vbios; + + /* HW functions */ + struct hw_sequencer_funcs hwss; + struct dce_hwseq *hwseq; + + /* temp store of dm_pp_display_configuration + * to compare to see if display config changed + */ + struct dm_pp_display_configuration prev_display_config; +}; + +#endif /* __CORE_DC_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_status.h b/drivers/gpu/drm/amd/display/dc/inc/core_status.h new file mode 100644 index 000000000000..32a2cc712000 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/core_status.h @@ -0,0 +1,47 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef _CORE_STATUS_H_ +#define _CORE_STATUS_H_ + +enum dc_status { + DC_OK = 1, + + DC_NO_CONTROLLER_RESOURCE, + DC_NO_STREAM_ENG_RESOURCE, + DC_NO_CLOCK_SOURCE_RESOURCE, + DC_FAIL_CONTROLLER_VALIDATE, + DC_FAIL_ENC_VALIDATE, + DC_FAIL_ATTACH_SURFACES, + DC_FAIL_SURFACE_VALIDATE, + DC_NO_DP_LINK_BANDWIDTH, + DC_EXCEED_DONGLE_MAX_CLK, + DC_SURFACE_PIXEL_FORMAT_UNSUPPORTED, + DC_FAIL_BANDWIDTH_VALIDATE, /* BW and Watermark validation */ + + DC_ERROR_UNEXPECTED = -1 +}; + +#endif /* _CORE_STATUS_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h new file mode 100644 index 000000000000..f2eb8945d5c4 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -0,0 +1,319 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef _CORE_TYPES_H_ +#define _CORE_TYPES_H_ + +#include "dc.h" +#include "bandwidth_calcs.h" +#include "ddc_service_types.h" +#include "dc_bios_types.h" + +struct core_stream; +/********* core_target *************/ + +#define CONST_DC_TARGET_TO_CORE(dc_target) \ + container_of(dc_target, const struct core_target, public) +#define DC_TARGET_TO_CORE(dc_target) \ + container_of(dc_target, struct core_target, public) + +#define MAX_PIPES 6 +#define MAX_CLOCK_SOURCES 7 + +struct core_target { + struct dc_target public; + + struct dc_context *ctx; +}; + +/********* core_surface **********/ +#define DC_SURFACE_TO_CORE(dc_surface) \ + container_of(dc_surface, struct core_surface, public) + +#define DC_GAMMA_TO_CORE(dc_gamma) \ + container_of(dc_gamma, struct core_gamma, public) + +struct core_surface { + struct dc_surface public; + struct dc_surface_status status; + struct dc_context *ctx; +}; + +struct core_gamma { + struct dc_gamma public; + struct dc_context *ctx; +}; + +void enable_surface_flip_reporting(struct dc_surface *dc_surface, + uint32_t controller_id); + +/********* core_stream ************/ +#include "grph_object_id.h" +#include "link_encoder.h" +#include "stream_encoder.h" +#include "clock_source.h" +#include "audio.h" +#include "hw_sequencer_types.h" +#include "opp.h" + +#define DC_STREAM_TO_CORE(dc_stream) container_of( \ + dc_stream, struct core_stream, public) + +struct core_stream { + struct dc_stream public; + + /* field internal to DC */ + struct dc_context *ctx; + const struct core_sink *sink; + + /* used by DCP and FMT */ + struct bit_depth_reduction_params bit_depth_params; + struct clamping_and_pixel_encoding_params clamping; + + int phy_pix_clk; + enum signal_type signal; + + struct dc_stream_status status; +}; + +/************ core_sink *****************/ + +#define DC_SINK_TO_CORE(dc_sink) \ + container_of(dc_sink, struct core_sink, public) + +struct core_sink { + /** The public, read-only (for DM) area of sink. **/ + struct dc_sink public; + /** End-of-public area. **/ + + /** The 'protected' area - read/write access, for use only inside DC **/ + /* not used for now */ + struct core_link *link; + struct dc_context *ctx; + uint32_t dongle_max_pix_clk; + bool converter_disable_audio; +}; + +/************ link *****************/ +#define DC_LINK_TO_CORE(dc_link) container_of(dc_link, struct core_link, public) + +struct link_init_data { + const struct core_dc *dc; + struct dc_context *ctx; /* TODO: remove 'dal' when DC is complete. */ + uint32_t connector_index; /* this will be mapped to the HPD pins */ + uint32_t link_index; /* this is mapped to DAL display_index + TODO: remove it when DC is complete. */ +}; + +/* DP MST stream allocation (payload bandwidth number) */ +struct link_mst_stream_allocation { + /* DIG front */ + const struct stream_encoder *stream_enc; + /* associate DRM payload table with DC stream encoder */ + uint8_t vcp_id; + /* number of slots required for the DP stream in transport packet */ + uint8_t slot_count; +}; + +/* DP MST stream allocation table */ +struct link_mst_stream_allocation_table { + /* number of DP video streams */ + int stream_count; + /* array of stream allocations */ + struct link_mst_stream_allocation + stream_allocations[MAX_CONTROLLER_NUM]; +}; + +struct core_link { + struct dc_link public; + const struct core_dc *dc; + + struct dc_context *ctx; /* TODO: AUTO remove 'dal' when DC is complete*/ + + struct link_encoder *link_enc; + struct ddc_service *ddc; + struct graphics_object_id link_id; + union ddi_channel_mapping ddi_channel_mapping; + struct connector_device_tag_info device_tag; + struct dpcd_caps dpcd_caps; + unsigned int dpcd_sink_count; + + enum edp_revision edp_revision; + + /* MST record stream using this link */ + struct link_flags { + bool dp_keep_receiver_powered; + } wa_flags; + struct link_mst_stream_allocation_table mst_stream_alloc_table; + + struct dc_link_status link_status; +}; + +#define DC_LINK_TO_LINK(dc_link) container_of(dc_link, struct core_link, public) + +struct core_link *link_create(const struct link_init_data *init_params); +void link_destroy(struct core_link **link); + +enum dc_status dc_link_validate_mode_timing( + const struct core_stream *stream, + struct core_link *link, + const struct dc_crtc_timing *timing); + +void core_link_resume(struct core_link *link); + +void core_link_enable_stream(struct pipe_ctx *pipe_ctx); + +void core_link_disable_stream(struct pipe_ctx *pipe_ctx); + +/********** DAL Core*********************/ +#include "display_clock_interface.h" +#include "transform.h" + +struct resource_pool; +struct validate_context; +struct resource_context; + +struct resource_funcs { + void (*destroy)(struct resource_pool **pool); + struct link_encoder *(*link_enc_create)( + const struct encoder_init_data *init); + enum dc_status (*validate_with_context)( + const struct core_dc *dc, + const struct dc_validation_set set[], + int set_count, + struct validate_context *context); + + enum dc_status (*validate_guaranteed)( + const struct core_dc *dc, + const struct dc_target *dc_target, + struct validate_context *context); + + enum dc_status (*validate_bandwidth)( + const struct core_dc *dc, + struct validate_context *context); + + struct validate_context *(*apply_clk_constraints)( + const struct core_dc *dc, + struct validate_context *context); + + struct pipe_ctx *(*acquire_idle_pipe_for_layer)( + struct resource_context *res_ctx, + struct core_stream *stream); + + void (*build_bit_depth_reduction_params)( + const struct core_stream *stream, + struct bit_depth_reduction_params *fmt_bit_depth); +}; + +struct audio_support{ + bool dp_audio; + bool hdmi_audio_on_dongle; + bool hdmi_audio_native; +}; + +struct resource_pool { + struct mem_input *mis[MAX_PIPES]; + struct input_pixel_processor *ipps[MAX_PIPES]; + struct transform *transforms[MAX_PIPES]; + struct output_pixel_processor *opps[MAX_PIPES]; + struct timing_generator *timing_generators[MAX_PIPES]; + struct stream_encoder *stream_enc[MAX_PIPES * 2]; + + unsigned int pipe_count; + unsigned int underlay_pipe_index; + unsigned int stream_enc_count; + + /* + * reserved clock source for DP + */ + struct clock_source *dp_clock_source; + + struct clock_source *clock_sources[MAX_CLOCK_SOURCES]; + unsigned int clk_src_count; + + struct audio *audios[MAX_PIPES]; + unsigned int audio_count; + struct audio_support audio_support; + + struct display_clock *display_clock; + struct irq_service *irqs; + + const struct resource_funcs *funcs; + const struct resource_caps *res_cap; +}; + +struct pipe_ctx { + struct core_surface *surface; + struct core_stream *stream; + + struct mem_input *mi; + struct input_pixel_processor *ipp; + struct transform *xfm; + struct output_pixel_processor *opp; + struct timing_generator *tg; + + struct scaler_data scl_data; + + struct stream_encoder *stream_enc; + struct display_clock *dis_clk; + struct clock_source *clock_source; + + struct audio *audio; + + struct pixel_clk_params pix_clk_params; + struct pll_settings pll_settings; + + /*fmt*/ + struct encoder_info_frame encoder_info_frame; + + uint8_t pipe_idx; + + struct pipe_ctx *top_pipe; + struct pipe_ctx *bottom_pipe; +}; + +struct resource_context { + const struct resource_pool *pool; + struct pipe_ctx pipe_ctx[MAX_PIPES]; + bool is_stream_enc_acquired[MAX_PIPES * 2]; + bool is_audio_acquired[MAX_PIPES]; + uint8_t clock_source_ref_count[MAX_CLOCK_SOURCES]; + uint8_t dp_clock_source_ref_count; + }; + +struct validate_context { + struct core_target *targets[MAX_PIPES]; + struct dc_target_status target_status[MAX_PIPES]; + uint8_t target_count; + + struct resource_context res_ctx; + + /* The output from BW and WM calculations. */ + struct bw_calcs_output bw_results; + /* Note: this is a big structure, do *not* put on stack! */ + struct dm_pp_display_configuration pp_display_cfg; +}; + +#endif /* _CORE_TYPES_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h new file mode 100644 index 000000000000..830fc3d039c9 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h @@ -0,0 +1,145 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_DDC_SERVICE_H__ +#define __DAL_DDC_SERVICE_H__ + +#include "include/ddc_service_types.h" +#include "include/i2caux_interface.h" + +#define EDID_SEGMENT_SIZE 256 + +struct ddc_service; +struct graphics_object_id; +enum ddc_result; +struct av_sync_data; +struct dp_receiver_id_info; + +struct i2c_payloads; +struct aux_payloads; + +struct i2c_payloads *dal_ddc_i2c_payloads_create(struct dc_context *ctx, uint32_t count); +struct i2c_payload *dal_ddc_i2c_payloads_get(struct i2c_payloads *p); +uint32_t dal_ddc_i2c_payloads_get_count(struct i2c_payloads *p); +void dal_ddc_i2c_payloads_destroy(struct i2c_payloads **p); + +struct aux_payloads *dal_ddc_aux_payloads_create(struct dc_context *ctx, uint32_t count); +struct aux_payload *dal_ddc_aux_payloads_get(struct aux_payloads *p); +uint32_t dal_ddc_aux_payloads_get_count(struct aux_payloads *p); +void dal_ddc_aux_payloads_destroy(struct aux_payloads **p); + +void dal_ddc_i2c_payloads_add( + struct i2c_payloads *payloads, + uint32_t address, + uint32_t len, + uint8_t *data, + bool write); + +void dal_ddc_aux_payloads_add( + struct aux_payloads *payloads, + uint32_t address, + uint32_t len, + uint8_t *data, + bool write); + +struct ddc_service_init_data { + struct graphics_object_id id; + struct dc_context *ctx; + struct core_link *link; +}; + +struct ddc_service *dal_ddc_service_create( + struct ddc_service_init_data *ddc_init_data); + +void dal_ddc_service_destroy(struct ddc_service **ddc); + +enum ddc_service_type dal_ddc_service_get_type(struct ddc_service *ddc); + +void dal_ddc_service_set_transaction_type( + struct ddc_service *ddc, + enum ddc_transaction_type type); + +bool dal_ddc_service_is_in_aux_transaction_mode(struct ddc_service *ddc); + +uint32_t dal_ddc_service_edid_query(struct ddc_service *ddc); + +uint32_t dal_ddc_service_get_edid_buf_len(struct ddc_service *ddc); + +void dal_ddc_service_get_edid_buf(struct ddc_service *ddc, uint8_t *edid_buf); + +void dal_ddc_service_i2c_query_dp_dual_mode_adaptor( + struct ddc_service *ddc, + struct display_sink_capability *sink_cap); + +bool dal_ddc_service_query_ddc_data( + struct ddc_service *ddc, + uint32_t address, + uint8_t *write_buf, + uint32_t write_size, + uint8_t *read_buf, + uint32_t read_size); + +enum ddc_result dal_ddc_service_read_dpcd_data( + struct ddc_service *ddc, + uint32_t address, + uint8_t *data, + uint32_t len); + +enum ddc_result dal_ddc_service_write_dpcd_data( + struct ddc_service *ddc, + uint32_t address, + const uint8_t *data, + uint32_t len); + +void dal_ddc_service_write_scdc_data( + struct ddc_service *ddc_service, + uint32_t pix_clk, + bool lte_340_scramble); + +void dal_ddc_service_read_scdc_data( + struct ddc_service *ddc_service); + +void ddc_service_set_dongle_type(struct ddc_service *ddc, + enum display_dongle_type dongle_type); + +void dal_ddc_service_set_ddc_pin( + struct ddc_service *ddc_service, + struct ddc *ddc); + +struct ddc *dal_ddc_service_get_ddc_pin(struct ddc_service *ddc_service); + +enum ddc_result dal_ddc_service_read_dpcd_data( + struct ddc_service *ddc, + uint32_t address, + uint8_t *data, + uint32_t len); +enum ddc_result dal_ddc_service_write_dpcd_data( + struct ddc_service *ddc, + uint32_t address, + const uint8_t *data, + uint32_t len); + +#endif /* __DAL_DDC_SERVICE_H__ */ + diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h new file mode 100644 index 000000000000..b0cf8e00059c --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h @@ -0,0 +1,60 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_LINK_DP_H__ +#define __DC_LINK_DP_H__ + +#define LINK_TRAINING_ATTEMPTS 4 +#define LINK_TRAINING_RETRY_DELAY 50 /* ms */ + +struct core_link; +struct core_stream; +struct dc_link_settings; + +bool dp_hbr_verify_link_cap( + struct core_link *link, + struct dc_link_settings *known_limit_link_setting); + +bool dp_validate_mode_timing( + struct core_link *link, + const struct dc_crtc_timing *timing); + +void decide_link_settings( + struct core_stream *stream, + struct dc_link_settings *link_setting); + +bool perform_link_training_with_retries( + struct core_link *link, + const struct dc_link_settings *link_setting, + bool skip_video_pattern, + int attempts); + +bool is_mst_supported(struct core_link *link); + +void detect_dp_sink_caps(struct core_link *link); + +bool is_dp_active_dongle(const struct core_link *link); + +#endif /* __DC_LINK_DP_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/gamma_calcs.h b/drivers/gpu/drm/amd/display/dc/inc/gamma_calcs.h new file mode 100644 index 000000000000..e2c63fd4fe92 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/gamma_calcs.h @@ -0,0 +1,19 @@ +/* + * gamma_calcs.h + * + * Created on: Feb 9, 2016 + * Author: yonsun + */ + +#ifndef DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_GAMMA_CALCS_H_ +#define DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_GAMMA_CALCS_H_ + +#include "opp.h" +#include "core_types.h" +#include "dc.h" + +bool calculate_regamma_params(struct pwl_params *params, + const struct core_gamma *ramp, + const struct core_surface *surface); + +#endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_GAMMA_CALCS_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/gamma_types.h b/drivers/gpu/drm/amd/display/dc/inc/gamma_types.h new file mode 100644 index 000000000000..7948d2cc0715 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/gamma_types.h @@ -0,0 +1,38 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef GAMMA_TYPES_H_ + +#define GAMMA_TYPES_H_ + +#include "dc_types.h" + +/* TODO: Used in IPP and OPP */ + +struct dev_c_lut16 { + uint16_t red; + uint16_t green; + uint16_t blue; +}; +#endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/audio.h b/drivers/gpu/drm/amd/display/dc/inc/hw/audio.h new file mode 100644 index 000000000000..925204f49717 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/audio.h @@ -0,0 +1,62 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_AUDIO_H__ +#define __DAL_AUDIO_H__ + +#include "audio_types.h" + +struct audio; + +struct audio_funcs { + + bool (*endpoint_valid)(struct audio *audio); + + void (*hw_init)(struct audio *audio); + + void (*az_enable)(struct audio *audio); + + void (*az_disable)(struct audio *audio); + + void (*az_configure)(struct audio *audio, + enum signal_type signal, + const struct audio_crtc_info *crtc_info, + const struct audio_info *audio_info); + + void (*wall_dto_setup)(struct audio *audio, + enum signal_type signal, + const struct audio_crtc_info *crtc_info, + const struct audio_pll_info *pll_info); + + void (*destroy)(struct audio **audio); +}; + +struct audio { + const struct audio_funcs *funcs; + struct dc_context *ctx; + unsigned int inst; +}; + +#endif /* __DAL_AUDIO__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/gpio.h b/drivers/gpu/drm/amd/display/dc/inc/hw/gpio.h new file mode 100644 index 000000000000..90d0148430fb --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/gpio.h @@ -0,0 +1,86 @@ +/* + * Copyright 2012-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_GPIO_H__ +#define __DAL_GPIO_H__ + +#include "gpio_types.h" + +struct gpio { + struct gpio_service *service; + struct hw_gpio_pin *pin; + enum gpio_id id; + uint32_t en; + enum gpio_mode mode; + /* when GPIO comes from VBIOS, it has defined output state */ + enum gpio_pin_output_state output_state; +}; + +#if 0 +struct gpio_funcs { + + struct hw_gpio_pin *(*create_ddc_data)( + struct dc_context *ctx, + enum gpio_id id, + uint32_t en); + struct hw_gpio_pin *(*create_ddc_clock)( + struct dc_context *ctx, + enum gpio_id id, + uint32_t en); + struct hw_gpio_pin *(*create_generic)( + struct dc_context *ctx, + enum gpio_id id, + uint32_t en); + struct hw_gpio_pin *(*create_hpd)( + struct dc_context *ctx, + enum gpio_id id, + uint32_t en); + struct hw_gpio_pin *(*create_gpio_pad)( + struct dc_context *ctx, + enum gpio_id id, + uint32_t en); + struct hw_gpio_pin *(*create_sync)( + struct dc_context *ctx, + enum gpio_id id, + uint32_t en); + struct hw_gpio_pin *(*create_gsl)( + struct dc_context *ctx, + enum gpio_id id, + uint32_t en); + + /* HW translation */ + bool (*offset_to_id)( + uint32_t offset, + uint32_t mask, + enum gpio_id *id, + uint32_t *en); + bool (*id_to_offset)( + enum gpio_id id, + uint32_t en, + struct gpio_pin_info *info); +}; +#endif + +#endif /* __DAL_GPIO__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h new file mode 100644 index 000000000000..3b0e616f7066 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h @@ -0,0 +1,74 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_HW_SHARED_H__ +#define __DAL_HW_SHARED_H__ + +/****************************************************************************** + * Data types shared between different Virtual HW blocks + ******************************************************************************/ +struct gamma_curve { + uint32_t offset; + uint32_t segments_num; +}; + +struct curve_points { + struct fixed31_32 x; + struct fixed31_32 y; + struct fixed31_32 offset; + struct fixed31_32 slope; + + uint32_t custom_float_x; + uint32_t custom_float_y; + uint32_t custom_float_offset; + uint32_t custom_float_slope; +}; + +struct pwl_result_data { + struct fixed31_32 red; + struct fixed31_32 green; + struct fixed31_32 blue; + + struct fixed31_32 delta_red; + struct fixed31_32 delta_green; + struct fixed31_32 delta_blue; + + uint32_t red_reg; + uint32_t green_reg; + uint32_t blue_reg; + + uint32_t delta_red_reg; + uint32_t delta_green_reg; + uint32_t delta_blue_reg; +}; + +struct pwl_params { + uint32_t *data; + struct gamma_curve arr_curve_points[16]; + struct curve_points arr_points[3]; + struct pwl_result_data rgb_resulted[256 + 3]; + uint32_t hw_points_num; +}; +#endif /* __DAL_HW_SHARED_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h new file mode 100644 index 000000000000..7e5f3e02a719 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h @@ -0,0 +1,121 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_IPP_H__ +#define __DAL_IPP_H__ + +#include "hw_shared.h" + +#define MAXTRIX_COEFFICIENTS_NUMBER 12 +#define MAXTRIX_COEFFICIENTS_WRAP_NUMBER (MAXTRIX_COEFFICIENTS_NUMBER + 4) +#define MAX_OVL_MATRIX_COUNT 12 + +/* IPP RELATED */ +struct input_pixel_processor { + struct dc_context *ctx; + uint32_t inst; + const struct ipp_funcs *funcs; +}; + +enum ipp_prescale_mode { + IPP_PRESCALE_MODE_BYPASS, + IPP_PRESCALE_MODE_FIXED_SIGNED, + IPP_PRESCALE_MODE_FLOAT_SIGNED, + IPP_PRESCALE_MODE_FIXED_UNSIGNED, + IPP_PRESCALE_MODE_FLOAT_UNSIGNED +}; + +struct ipp_prescale_params { + enum ipp_prescale_mode mode; + uint16_t bias; + uint16_t scale; +}; + +enum ipp_degamma_mode { + IPP_DEGAMMA_MODE_BYPASS, + IPP_DEGAMMA_MODE_HW_sRGB, + IPP_DEGAMMA_MODE_HW_xvYCC, + IPP_DEGAMMA_MODE_USER_PWL +}; + +enum ovl_color_space { + OVL_COLOR_SPACE_UNKNOWN = 0, + OVL_COLOR_SPACE_RGB, + OVL_COLOR_SPACE_YUV601, + OVL_COLOR_SPACE_YUV709 +}; + +enum expansion_mode { + EXPANSION_MODE_DYNAMIC, + EXPANSION_MODE_ZERO +}; + +enum ipp_output_format { + IPP_OUTPUT_FORMAT_12_BIT_FIX, + IPP_OUTPUT_FORMAT_16_BIT_BYPASS, + IPP_OUTPUT_FORMAT_FLOAT +}; + +struct ipp_funcs { + + /*** cursor ***/ + void (*ipp_cursor_set_position)( + struct input_pixel_processor *ipp, + const struct dc_cursor_position *position); + + bool (*ipp_cursor_set_attributes)( + struct input_pixel_processor *ipp, + const struct dc_cursor_attributes *attributes); + + /*** setup input pixel processing ***/ + + /* put the entire pixel processor to bypass */ + void (*ipp_full_bypass)( + struct input_pixel_processor *ipp); + + /* setup ipp to expand/convert input to pixel processor internal format */ + void (*ipp_setup)( + struct input_pixel_processor *ipp, + enum surface_pixel_format input_format, + enum expansion_mode mode, + enum ipp_output_format output_format); + + /* DCE function to setup IPP. TODO: see if we can consolidate to setup */ + void (*ipp_program_prescale)( + struct input_pixel_processor *ipp, + struct ipp_prescale_params *params); + + /*** DEGAMMA RELATED ***/ + bool (*ipp_set_degamma)( + struct input_pixel_processor *ipp, + enum ipp_degamma_mode mode); + + bool (*ipp_program_degamma_pwl)( + struct input_pixel_processor *ipp, + const struct pwl_params *params); + +}; + +#endif /* __DAL_IPP_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h new file mode 100644 index 000000000000..77f8aa410898 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h @@ -0,0 +1,263 @@ +/* + * link_encoder.h + * + * Created on: Oct 6, 2015 + * Author: yonsun + */ + +#ifndef LINK_ENCODER_H_ +#define LINK_ENCODER_H_ + +#include "grph_object_defs.h" +#include "signal_types.h" +#include "dc_types.h" + +struct dc_context; +struct encoder_set_dp_phy_pattern_param; +struct link_mst_stream_allocation_table; +struct dc_link_settings; +struct link_training_settings; +struct core_stream; +struct pipe_ctx; + +struct encoder_init_data { + enum channel_id channel; + struct graphics_object_id connector; + enum hpd_source_id hpd_source; + /* TODO: in DAL2, here was pointer to EventManagerInterface */ + struct graphics_object_id encoder; + struct dc_context *ctx; + enum transmitter transmitter; +}; + +struct encoder_feature_support { + union { + struct { + /* 1 - external encoder; 0 - internal encoder */ + uint32_t EXTERNAL_ENCODER:1; + uint32_t ANALOG_ENCODER:1; + uint32_t STEREO_SYNC:1; + /* check the DDC data pin + * when performing DP Sink detection */ + uint32_t DP_SINK_DETECT_POLL_DATA_PIN:1; + /* CPLIB authentication + * for external DP chip supported */ + uint32_t CPLIB_DP_AUTHENTICATION:1; + uint32_t IS_HBR2_CAPABLE:1; + uint32_t IS_HBR3_CAPABLE:1; + uint32_t IS_HBR2_VALIDATED:1; + uint32_t IS_TPS3_CAPABLE:1; + uint32_t IS_TPS4_CAPABLE:1; + uint32_t IS_AUDIO_CAPABLE:1; + uint32_t IS_VCE_SUPPORTED:1; + uint32_t IS_CONVERTER:1; + uint32_t IS_Y_ONLY_CAPABLE:1; + uint32_t IS_YCBCR_CAPABLE:1; + } bits; + uint32_t raw; + } flags; + /* maximum supported deep color depth */ + enum dc_color_depth max_deep_color; + enum dc_color_depth max_hdmi_deep_color; + /* maximum supported clock */ + unsigned int max_pixel_clock; + unsigned int max_hdmi_pixel_clock; + bool ycbcr420_supported; +}; + +enum physical_phy_id { + PHYLD_0, + PHYLD_1, + PHYLD_2, + PHYLD_3, + PHYLD_4, + PHYLD_5, + PHYLD_6, + PHYLD_7, + PHYLD_8, + PHYLD_9, + PHYLD_COUNT, + PHYLD_UNKNOWN = (-1L) +}; + +enum phy_type { + PHY_TYPE_UNKNOWN = 1, + PHY_TYPE_PCIE_PHY = 2, + PHY_TYPE_UNIPHY = 3, +}; + +union dmcu_psr_level { + struct { + unsigned int SKIP_CRC:1; + unsigned int SKIP_DP_VID_STREAM_DISABLE:1; + unsigned int SKIP_PHY_POWER_DOWN:1; + unsigned int SKIP_AUX_ACK_CHECK:1; + unsigned int SKIP_CRTC_DISABLE:1; + unsigned int SKIP_AUX_RFB_CAPTURE_CHECK:1; + unsigned int SKIP_SMU_NOTIFICATION:1; + unsigned int SKIP_AUTO_STATE_ADVANCE:1; + unsigned int DISABLE_PSR_ENTRY_ABORT:1; + unsigned int RESERVED:23; + } bits; + unsigned int u32all; +}; + +union dpcd_psr_configuration { + struct { + unsigned char ENABLE : 1; + unsigned char TRANSMITTER_ACTIVE_IN_PSR : 1; + unsigned char CRC_VERIFICATION : 1; + unsigned char FRAME_CAPTURE_INDICATION : 1; + /* For eDP 1.4, PSR v2*/ + unsigned char LINE_CAPTURE_INDICATION : 1; + /* For eDP 1.4, PSR v2*/ + unsigned char IRQ_HPD_WITH_CRC_ERROR : 1; + unsigned char RESERVED : 2; + } bits; + unsigned char raw; +}; + +union psr_error_status { + struct { + unsigned char LINK_CRC_ERROR :1; + unsigned char RFB_STORAGE_ERROR :1; + unsigned char RESERVED :6; + } bits; + unsigned char raw; +}; + +union psr_sink_psr_status { + struct { + unsigned char SINK_SELF_REFRESH_STATUS :3; + unsigned char RESERVED :5; + } bits; + unsigned char raw; +}; + +struct psr_dmcu_context { + /* ddc line */ + enum channel_id channel; + /* Transmitter id */ + enum transmitter transmitterId; + /* Engine Id is used for Dig Be source select */ + enum engine_id engineId; + /* Controller Id used for Dig Fe source select */ + enum controller_id controllerId; + /* Pcie or Uniphy */ + enum phy_type phyType; + /* Physical PHY Id used by SMU interpretation */ + enum physical_phy_id smuPhyId; + /* Vertical total pixels from crtc timing. + * This is used for static screen detection. + * ie. If we want to detect half a frame, + * we use this to determine the hyst lines. + */ + unsigned int crtcTimingVerticalTotal; + /* PSR supported from panel capabilities and + * current display configuration + */ + bool psrSupportedDisplayConfig; + /* Whether fast link training is supported by the panel */ + bool psrExitLinkTrainingRequired; + /* If RFB setup time is greater than the total VBLANK time, + * it is not possible for the sink to capture the video frame + * in the same frame the SDP is sent. In this case, + * the frame capture indication bit should be set and an extra + * static frame should be transmitted to the sink. + */ + bool psrFrameCaptureIndicationReq; + /* Set the last possible line SDP may be transmitted without violating + * the RFB setup time or entering the active video frame. + */ + unsigned int sdpTransmitLineNumDeadline; + /* The VSync rate in Hz used to calculate the + * step size for smooth brightness feature + */ + unsigned int vsyncRateHz; + unsigned int skipPsrWaitForPllLock; + unsigned int numberOfControllers; + /* Unused, for future use. To indicate that first changed frame from + * state3 shouldn't result in psr_inactive, but rather to perform + * an automatic single frame rfb_update. + */ + bool rfb_update_auto_en; + /* Number of frame before entering static screen */ + unsigned int timehyst_frames; + /* Partial frames before entering static screen */ + unsigned int hyst_lines; + /* # of repeated AUX transaction attempts to make before + * indicating failure to the driver + */ + unsigned int aux_repeats; + /* Controls hw blocks to power down during PSR active state */ + union dmcu_psr_level psr_level; + /* Controls additional delay after remote frame capture before + * continuing powerd own + */ + unsigned int frame_delay; +}; + + +struct link_encoder { + const struct link_encoder_funcs *funcs; + int32_t aux_channel_offset; + struct dc_context *ctx; + struct graphics_object_id id; + struct graphics_object_id connector; + uint32_t input_signals; + uint32_t output_signals; + enum engine_id preferred_engine; + struct encoder_feature_support features; + enum transmitter transmitter; + enum hpd_source_id hpd_source; +}; + +struct link_encoder_funcs { + bool (*validate_output_with_stream)( + struct link_encoder *enc, struct pipe_ctx *pipe_ctx); + void (*hw_init)(struct link_encoder *enc); + void (*setup)(struct link_encoder *enc, + enum signal_type signal); + void (*enable_tmds_output)(struct link_encoder *enc, + enum clock_source_id clock_source, + enum dc_color_depth color_depth, + bool hdmi, + bool dual_link, + uint32_t pixel_clock); + void (*enable_dp_output)(struct link_encoder *enc, + const struct dc_link_settings *link_settings, + enum clock_source_id clock_source); + void (*enable_dp_mst_output)(struct link_encoder *enc, + const struct dc_link_settings *link_settings, + enum clock_source_id clock_source); + void (*disable_output)(struct link_encoder *link_enc, + enum signal_type signal); + void (*dp_set_lane_settings)(struct link_encoder *enc, + const struct link_training_settings *link_settings); + void (*dp_set_phy_pattern)(struct link_encoder *enc, + const struct encoder_set_dp_phy_pattern_param *para); + void (*update_mst_stream_allocation_table)( + struct link_encoder *enc, + const struct link_mst_stream_allocation_table *table); + void (*set_lcd_backlight_level) (struct link_encoder *enc, + uint32_t level); + void (*set_dmcu_backlight_level)(struct link_encoder *enc, + uint32_t level, uint32_t frame_ramp, uint32_t controller_id); + void (*init_dmcu_backlight_settings)(struct link_encoder *enc); + void (*set_dmcu_abm_level)(struct link_encoder *enc, uint32_t level); + void (*set_dmcu_psr_enable)(struct link_encoder *enc, bool enable); + void (*setup_dmcu_psr)(struct link_encoder *enc, + struct psr_dmcu_context *psr_context); + void (*backlight_control) (struct link_encoder *enc, + bool enable); + void (*power_control) (struct link_encoder *enc, + bool power_up); + void (*connect_dig_be_to_fe)(struct link_encoder *enc, + enum engine_id engine, + bool connect); + void (*enable_hpd)(struct link_encoder *enc); + void (*disable_hpd)(struct link_encoder *enc); + void (*destroy)(struct link_encoder **enc); +}; + +#endif /* LINK_ENCODER_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h new file mode 100644 index 000000000000..78dab74edc2d --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h @@ -0,0 +1,106 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef __DAL_MEM_INPUT_H__ +#define __DAL_MEM_INPUT_H__ + +#include "dc.h" +#include "include/grph_object_id.h" +#include "inc/bandwidth_calcs.h" + +#include "dce/dce_mem_input.h" /* temporary */ + +struct stutter_modes { + bool enhanced; + bool quad_dmif_buffer; + bool watermark_nb_pstate; +}; + +struct mem_input { + struct mem_input_funcs *funcs; + struct dc_context *ctx; + struct dc_plane_address request_address; + struct dc_plane_address current_address; + uint32_t inst; + struct stutter_modes stutter_mode; + + const struct dce_mem_input_registers *regs; + const struct dce_mem_input_shift *shifts; + const struct dce_mem_input_mask *masks; + struct dce_mem_input_wa wa; +}; + +struct mem_input_funcs { + void (*mem_input_program_display_marks)( + struct mem_input *mem_input, + struct bw_watermarks nbp, + struct bw_watermarks stutter, + struct bw_watermarks urgent, + uint32_t total_dest_line_time_ns); + + void (*mem_input_program_chroma_display_marks)( + struct mem_input *mem_input, + struct bw_watermarks nbp, + struct bw_watermarks stutter, + struct bw_watermarks urgent, + uint32_t total_dest_line_time_ns); + + void (*allocate_mem_input)( + struct mem_input *mem_input, + uint32_t h_total,/* for current target */ + uint32_t v_total,/* for current target */ + uint32_t pix_clk_khz,/* for current target */ + uint32_t total_streams_num); + + void (*free_mem_input)( + struct mem_input *mem_input, + uint32_t paths_num); + + bool (*mem_input_program_surface_flip_and_addr)( + struct mem_input *mem_input, + const struct dc_plane_address *address, + bool flip_immediate); + + bool (*mem_input_program_pte_vm)( + struct mem_input *mem_input, + enum surface_pixel_format format, + union dc_tiling_info *tiling_info, + enum dc_rotation_angle rotation); + + bool (*mem_input_program_surface_config)( + struct mem_input *mem_input, + enum surface_pixel_format format, + union dc_tiling_info *tiling_info, + union plane_size *plane_size, + enum dc_rotation_angle rotation, + struct dc_plane_dcc_param *dcc, + bool horizontal_mirror); + + bool (*mem_input_is_flip_pending)(struct mem_input *mem_input); + + void (*mem_input_update_dchub)(struct mem_input *mem_input, + struct dchub_init_data *dh_data); +}; + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h new file mode 100644 index 000000000000..e615997be20e --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h @@ -0,0 +1,322 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_OPP_H__ +#define __DAL_OPP_H__ + +#include "hw_shared.h" +#include "transform.h" + +struct fixed31_32; +struct gamma_parameters; + +/* TODO: Need cleanup */ +enum clamping_range { + CLAMPING_FULL_RANGE = 0, /* No Clamping */ + CLAMPING_LIMITED_RANGE_8BPC, /* 8 bpc: Clamping 1 to FE */ + CLAMPING_LIMITED_RANGE_10BPC, /* 10 bpc: Clamping 4 to 3FB */ + CLAMPING_LIMITED_RANGE_12BPC, /* 12 bpc: Clamping 10 to FEF */ + /* Use programmable clampping value on FMT_CLAMP_COMPONENT_R/G/B. */ + CLAMPING_LIMITED_RANGE_PROGRAMMABLE +}; + +struct clamping_and_pixel_encoding_params { + enum dc_pixel_encoding pixel_encoding; /* Pixel Encoding */ + enum clamping_range clamping_level; /* Clamping identifier */ + enum dc_color_depth c_depth; /* Deep color use. */ +}; + +struct bit_depth_reduction_params { + struct { + /* truncate/round */ + /* trunc/round enabled*/ + uint32_t TRUNCATE_ENABLED:1; + /* 2 bits: 0=6 bpc, 1=8 bpc, 2 = 10bpc*/ + uint32_t TRUNCATE_DEPTH:2; + /* truncate or round*/ + uint32_t TRUNCATE_MODE:1; + + /* spatial dither */ + /* Spatial Bit Depth Reduction enabled*/ + uint32_t SPATIAL_DITHER_ENABLED:1; + /* 2 bits: 0=6 bpc, 1 = 8 bpc, 2 = 10bpc*/ + uint32_t SPATIAL_DITHER_DEPTH:2; + /* 0-3 to select patterns*/ + uint32_t SPATIAL_DITHER_MODE:2; + /* Enable RGB random dithering*/ + uint32_t RGB_RANDOM:1; + /* Enable Frame random dithering*/ + uint32_t FRAME_RANDOM:1; + /* Enable HighPass random dithering*/ + uint32_t HIGHPASS_RANDOM:1; + + /* temporal dither*/ + /* frame modulation enabled*/ + uint32_t FRAME_MODULATION_ENABLED:1; + /* same as for trunc/spatial*/ + uint32_t FRAME_MODULATION_DEPTH:2; + /* 2/4 gray levels*/ + uint32_t TEMPORAL_LEVEL:1; + uint32_t FRC25:2; + uint32_t FRC50:2; + uint32_t FRC75:2; + } flags; + + uint32_t r_seed_value; + uint32_t b_seed_value; + uint32_t g_seed_value; +}; + +enum wide_gamut_regamma_mode { + /* 0x0 - BITS2:0 Bypass */ + WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_BYPASS, + /* 0x1 - Fixed curve sRGB 2.4 */ + WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_SRGB24, + /* 0x2 - Fixed curve xvYCC 2.22 */ + WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_XYYCC22, + /* 0x3 - Programmable control A */ + WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_MATRIX_A, + /* 0x4 - Programmable control B */ + WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_MATRIX_B, + /* 0x0 - BITS6:4 Bypass */ + WIDE_GAMUT_REGAMMA_MODE_OVL_BYPASS, + /* 0x1 - Fixed curve sRGB 2.4 */ + WIDE_GAMUT_REGAMMA_MODE_OVL_SRGB24, + /* 0x2 - Fixed curve xvYCC 2.22 */ + WIDE_GAMUT_REGAMMA_MODE_OVL_XYYCC22, + /* 0x3 - Programmable control A */ + WIDE_GAMUT_REGAMMA_MODE_OVL_MATRIX_A, + /* 0x4 - Programmable control B */ + WIDE_GAMUT_REGAMMA_MODE_OVL_MATRIX_B +}; + +struct gamma_pixel { + struct fixed31_32 r; + struct fixed31_32 g; + struct fixed31_32 b; +}; + +enum channel_name { + CHANNEL_NAME_RED, + CHANNEL_NAME_GREEN, + CHANNEL_NAME_BLUE +}; + +struct custom_float_format { + uint32_t mantissa_bits; + uint32_t exponenta_bits; + bool sign; +}; + +struct custom_float_value { + uint32_t mantissa; + uint32_t exponenta; + uint32_t value; + bool negative; +}; + +struct hw_x_point { + uint32_t custom_float_x; + uint32_t custom_float_x_adjusted; + struct fixed31_32 x; + struct fixed31_32 adjusted_x; + struct fixed31_32 regamma_y_red; + struct fixed31_32 regamma_y_green; + struct fixed31_32 regamma_y_blue; + +}; + +struct pwl_float_data_ex { + struct fixed31_32 r; + struct fixed31_32 g; + struct fixed31_32 b; + struct fixed31_32 delta_r; + struct fixed31_32 delta_g; + struct fixed31_32 delta_b; +}; + +enum hw_point_position { + /* hw point sits between left and right sw points */ + HW_POINT_POSITION_MIDDLE, + /* hw point lays left from left (smaller) sw point */ + HW_POINT_POSITION_LEFT, + /* hw point lays stays from right (bigger) sw point */ + HW_POINT_POSITION_RIGHT +}; + +struct gamma_point { + int32_t left_index; + int32_t right_index; + enum hw_point_position pos; + struct fixed31_32 coeff; +}; + +struct pixel_gamma_point { + struct gamma_point r; + struct gamma_point g; + struct gamma_point b; +}; + +struct gamma_coefficients { + struct fixed31_32 a0[3]; + struct fixed31_32 a1[3]; + struct fixed31_32 a2[3]; + struct fixed31_32 a3[3]; + struct fixed31_32 user_gamma[3]; + struct fixed31_32 user_contrast; + struct fixed31_32 user_brightness; +}; + +struct pwl_float_data { + struct fixed31_32 r; + struct fixed31_32 g; + struct fixed31_32 b; +}; + +enum opp_regamma { + OPP_REGAMMA_BYPASS = 0, + OPP_REGAMMA_SRGB, + OPP_REGAMMA_3_6, + OPP_REGAMMA_USER, +}; + +struct output_pixel_processor { + struct dc_context *ctx; + uint32_t inst; + const struct opp_funcs *funcs; +}; + +enum fmt_stereo_action { + FMT_STEREO_ACTION_ENABLE = 0, + FMT_STEREO_ACTION_DISABLE, + FMT_STEREO_ACTION_UPDATE_POLARITY +}; + +enum graphics_csc_adjust_type { + GRAPHICS_CSC_ADJUST_TYPE_BYPASS = 0, + GRAPHICS_CSC_ADJUST_TYPE_HW, /* without adjustments */ + GRAPHICS_CSC_ADJUST_TYPE_SW /*use adjustments */ +}; + +struct default_adjustment { + enum lb_pixel_depth lb_color_depth; + enum dc_color_space out_color_space; + enum dc_color_space in_color_space; + enum dc_color_depth color_depth; + enum pixel_format surface_pixel_format; + enum graphics_csc_adjust_type csc_adjust_type; + bool force_hw_default; +}; + +enum grph_color_adjust_option { + GRPH_COLOR_MATRIX_HW_DEFAULT = 1, + GRPH_COLOR_MATRIX_SW +}; + +struct opp_grph_csc_adjustment { + enum grph_color_adjust_option color_adjust_option; + enum dc_color_space c_space; + enum dc_color_depth color_depth; /* clean up to uint32_t */ + enum graphics_csc_adjust_type csc_adjust_type; + int32_t adjust_divider; + int32_t grph_cont; + int32_t grph_sat; + int32_t grph_bright; + int32_t grph_hue; +}; + +struct out_csc_color_matrix { + enum dc_color_space color_space; + uint16_t regval[12]; +}; + +/* Underlay related types */ + +struct hw_adjustment_range { + int32_t hw_default; + int32_t min; + int32_t max; + int32_t step; + uint32_t divider; /* (actually HW range is min/divider; divider !=0) */ +}; + +enum ovl_csc_adjust_item { + OVERLAY_BRIGHTNESS = 0, + OVERLAY_GAMMA, + OVERLAY_CONTRAST, + OVERLAY_SATURATION, + OVERLAY_HUE, + OVERLAY_ALPHA, + OVERLAY_ALPHA_PER_PIX, + OVERLAY_COLOR_TEMPERATURE +}; + +struct opp_funcs { + void (*opp_power_on_regamma_lut)( + struct output_pixel_processor *opp, + bool power_on); + + bool (*opp_program_regamma_pwl)( + struct output_pixel_processor *opp, + const struct pwl_params *params); + + void (*opp_set_regamma_mode)(struct output_pixel_processor *opp, + enum opp_regamma mode); + + void (*opp_set_csc_adjustment)( + struct output_pixel_processor *opp, + const struct out_csc_color_matrix *tbl_entry); + + void (*opp_set_csc_default)( + struct output_pixel_processor *opp, + const struct default_adjustment *default_adjust); + + /* FORMATTER RELATED */ + + void (*opp_program_fmt)( + struct output_pixel_processor *opp, + struct bit_depth_reduction_params *fmt_bit_depth, + struct clamping_and_pixel_encoding_params *clamping); + + void (*opp_set_dyn_expansion)( + struct output_pixel_processor *opp, + enum dc_color_space color_sp, + enum dc_color_depth color_dpth, + enum signal_type signal); + + void (*opp_program_bit_depth_reduction)( + struct output_pixel_processor *opp, + const struct bit_depth_reduction_params *params); + + /* underlay related */ + void (*opp_get_underlay_adjustment_range)( + struct output_pixel_processor *opp, + enum ovl_csc_adjust_item overlay_adjust_item, + struct hw_adjustment_range *range); + + void (*opp_destroy)(struct output_pixel_processor **opp); +}; + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h new file mode 100644 index 000000000000..9caf2b365420 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h @@ -0,0 +1,121 @@ +/* + * stream_encoder.h + * + */ + +#ifndef STREAM_ENCODER_H_ +#define STREAM_ENCODER_H_ + +#include "include/hw_sequencer_types.h" +#include "audio_types.h" + +struct dc_bios; +struct dc_context; +struct dc_crtc_timing; + +struct encoder_info_packet { + bool valid; + uint8_t hb0; + uint8_t hb1; + uint8_t hb2; + uint8_t hb3; + uint8_t sb[28]; +}; + +struct encoder_info_frame { + /* auxiliary video information */ + struct encoder_info_packet avi; + struct encoder_info_packet gamut; + struct encoder_info_packet vendor; + /* source product description */ + struct encoder_info_packet spd; + /* video stream configuration */ + struct encoder_info_packet vsc; +}; + +struct encoder_unblank_param { + struct hw_crtc_timing crtc_timing; + struct dc_link_settings link_settings; +}; + +struct encoder_set_dp_phy_pattern_param { + enum dp_test_pattern dp_phy_pattern; + const uint8_t *custom_pattern; + uint32_t custom_pattern_size; + enum dp_panel_mode dp_panel_mode; +}; + +struct stream_encoder { + const struct stream_encoder_funcs *funcs; + struct dc_context *ctx; + struct dc_bios *bp; + enum engine_id id; +}; + +struct stream_encoder_funcs { + void (*dp_set_stream_attribute)( + struct stream_encoder *enc, + struct dc_crtc_timing *crtc_timing, + enum dc_color_space output_color_space); + + void (*hdmi_set_stream_attribute)( + struct stream_encoder *enc, + struct dc_crtc_timing *crtc_timing, + int actual_pix_clk_khz, + bool enable_audio); + + void (*dvi_set_stream_attribute)( + struct stream_encoder *enc, + struct dc_crtc_timing *crtc_timing, + bool is_dual_link); + + void (*set_mst_bandwidth)( + struct stream_encoder *enc, + struct fixed31_32 avg_time_slots_per_mtp); + + void (*update_hdmi_info_packets)( + struct stream_encoder *enc, + const struct encoder_info_frame *info_frame); + + void (*stop_hdmi_info_packets)( + struct stream_encoder *enc); + + void (*update_dp_info_packets)( + struct stream_encoder *enc, + const struct encoder_info_frame *info_frame); + + void (*stop_dp_info_packets)( + struct stream_encoder *enc); + + void (*dp_blank)( + struct stream_encoder *enc); + + void (*dp_unblank)( + struct stream_encoder *enc, + const struct encoder_unblank_param *param); + + void (*audio_mute_control)( + struct stream_encoder *enc, bool mute); + + void (*dp_audio_setup)( + struct stream_encoder *enc, + unsigned int az_inst, + struct audio_info *info); + + void (*dp_audio_enable) ( + struct stream_encoder *enc); + + void (*dp_audio_disable) ( + struct stream_encoder *enc); + + void (*hdmi_audio_setup)( + struct stream_encoder *enc, + unsigned int az_inst, + struct audio_info *info, + struct audio_crtc_info *audio_crtc_info); + + void (*hdmi_audio_disable) ( + struct stream_encoder *enc); +}; + +#endif /* STREAM_ENCODER_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h new file mode 100644 index 000000000000..6ac609f6f89f --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h @@ -0,0 +1,162 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_TIMING_GENERATOR_TYPES_H__ +#define __DAL_TIMING_GENERATOR_TYPES_H__ + +struct dc_bios; + +/** + * These parameters are required as input when doing blanking/Unblanking +*/ +#define MAX_TG_COLOR_VALUE 0x3FF + +struct tg_color { + /* Maximum 10 bits color value */ + uint16_t color_r_cr; + uint16_t color_g_y; + uint16_t color_b_cb; +}; + +/* Contains CRTC vertical/horizontal pixel counters */ +struct crtc_position { + uint32_t vertical_count; + uint32_t horizontal_count; + uint32_t nominal_vcount; +}; + +struct dcp_gsl_params { + int gsl_group; + int gsl_master; +}; + +#define LEFT_EYE_3D_PRIMARY_SURFACE 1 +#define RIGHT_EYE_3D_PRIMARY_SURFACE 0 + +enum test_pattern_dyn_range { + TEST_PATTERN_DYN_RANGE_VESA = 0, + TEST_PATTERN_DYN_RANGE_CEA +}; + +enum test_pattern_mode { + TEST_PATTERN_MODE_COLORSQUARES_RGB = 0, + TEST_PATTERN_MODE_COLORSQUARES_YCBCR601, + TEST_PATTERN_MODE_COLORSQUARES_YCBCR709, + TEST_PATTERN_MODE_VERTICALBARS, + TEST_PATTERN_MODE_HORIZONTALBARS, + TEST_PATTERN_MODE_SINGLERAMP_RGB, + TEST_PATTERN_MODE_DUALRAMP_RGB +}; + +enum test_pattern_color_format { + TEST_PATTERN_COLOR_FORMAT_BPC_6 = 0, + TEST_PATTERN_COLOR_FORMAT_BPC_8, + TEST_PATTERN_COLOR_FORMAT_BPC_10, + TEST_PATTERN_COLOR_FORMAT_BPC_12 +}; + +enum controller_dp_test_pattern { + CONTROLLER_DP_TEST_PATTERN_D102 = 0, + CONTROLLER_DP_TEST_PATTERN_SYMBOLERROR, + CONTROLLER_DP_TEST_PATTERN_PRBS7, + CONTROLLER_DP_TEST_PATTERN_COLORSQUARES, + CONTROLLER_DP_TEST_PATTERN_VERTICALBARS, + CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS, + CONTROLLER_DP_TEST_PATTERN_COLORRAMP, + CONTROLLER_DP_TEST_PATTERN_VIDEOMODE, + CONTROLLER_DP_TEST_PATTERN_RESERVED_8, + CONTROLLER_DP_TEST_PATTERN_RESERVED_9, + CONTROLLER_DP_TEST_PATTERN_RESERVED_A, + CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA +}; + +enum crtc_state { + CRTC_STATE_VBLANK = 0, + CRTC_STATE_VACTIVE +}; + +struct timing_generator { + const struct timing_generator_funcs *funcs; + struct dc_bios *bp; + struct dc_context *ctx; + int inst; +}; + +struct dc_crtc_timing; + +struct drr_params; + +struct timing_generator_funcs { + bool (*validate_timing)(struct timing_generator *tg, + const struct dc_crtc_timing *timing); + void (*program_timing)(struct timing_generator *tg, + const struct dc_crtc_timing *timing, + bool use_vbios); + bool (*enable_crtc)(struct timing_generator *tg); + bool (*disable_crtc)(struct timing_generator *tg); + bool (*is_counter_moving)(struct timing_generator *tg); + void (*get_position)(struct timing_generator *tg, + int32_t *h_position, + int32_t *v_position); + uint32_t (*get_frame_count)(struct timing_generator *tg); + uint32_t (*get_scanoutpos)( + struct timing_generator *tg, + uint32_t *vbl, + uint32_t *position); + void (*set_early_control)(struct timing_generator *tg, + uint32_t early_cntl); + void (*wait_for_state)(struct timing_generator *tg, + enum crtc_state state); + bool (*set_blank)(struct timing_generator *tg, + bool enable_blanking); + bool (*is_blanked)(struct timing_generator *tg); + void (*set_overscan_blank_color) (struct timing_generator *tg, const struct tg_color *color); + void (*set_blank_color)(struct timing_generator *tg, const struct tg_color *color); + void (*set_colors)(struct timing_generator *tg, + const struct tg_color *blank_color, + const struct tg_color *overscan_color); + + void (*disable_vga)(struct timing_generator *tg); + bool (*did_triggered_reset_occur)(struct timing_generator *tg); + void (*setup_global_swap_lock)(struct timing_generator *tg, + const struct dcp_gsl_params *gsl_params); + void (*unlock)(struct timing_generator *tg); + void (*lock)(struct timing_generator *tg); + void (*enable_reset_trigger)(struct timing_generator *tg, int source_tg_inst); + void (*disable_reset_trigger)(struct timing_generator *tg); + void (*tear_down_global_swap_lock)(struct timing_generator *tg); + void (*enable_advanced_request)(struct timing_generator *tg, + bool enable, const struct dc_crtc_timing *timing); + void (*set_drr)(struct timing_generator *tg, const struct drr_params *params); + void (*set_static_screen_control)(struct timing_generator *tg, + uint32_t value); + void (*set_test_pattern)( + struct timing_generator *tg, + enum controller_dp_test_pattern test_pattern, + enum dc_color_depth color_depth); + +}; + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h new file mode 100644 index 000000000000..ef743b70b3e9 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h @@ -0,0 +1,179 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_TRANSFORM_H__ +#define __DAL_TRANSFORM_H__ + +#include "dc_hw_types.h" +#include "fixed31_32.h" + +#define CSC_TEMPERATURE_MATRIX_SIZE 9 + +struct bit_depth_reduction_params; + +struct transform { + const struct transform_funcs *funcs; + struct dc_context *ctx; + int inst; +}; + +/* Colorimetry */ +enum colorimetry { + COLORIMETRY_NO_DATA = 0, + COLORIMETRY_ITU601 = 1, + COLORIMETRY_ITU709 = 2, + COLORIMETRY_EXTENDED = 3 +}; + +enum active_format_info { + ACTIVE_FORMAT_NO_DATA = 0, + ACTIVE_FORMAT_VALID = 1 +}; + +/* Active format aspect ratio */ +enum active_format_aspect_ratio { + ACTIVE_FORMAT_ASPECT_RATIO_SAME_AS_PICTURE = 8, + ACTIVE_FORMAT_ASPECT_RATIO_4_3 = 9, + ACTIVE_FORMAT_ASPECT_RATIO_16_9 = 0XA, + ACTIVE_FORMAT_ASPECT_RATIO_14_9 = 0XB +}; + +enum bar_info { + BAR_INFO_NOT_VALID = 0, + BAR_INFO_VERTICAL_VALID = 1, + BAR_INFO_HORIZONTAL_VALID = 2, + BAR_INFO_BOTH_VALID = 3 +}; + +enum picture_scaling { + PICTURE_SCALING_UNIFORM = 0, + PICTURE_SCALING_HORIZONTAL = 1, + PICTURE_SCALING_VERTICAL = 2, + PICTURE_SCALING_BOTH = 3 +}; + +/* RGB quantization range */ +enum rgb_quantization_range { + RGB_QUANTIZATION_DEFAULT_RANGE = 0, + RGB_QUANTIZATION_LIMITED_RANGE = 1, + RGB_QUANTIZATION_FULL_RANGE = 2, + RGB_QUANTIZATION_RESERVED = 3 +}; + +/* YYC quantization range */ +enum yyc_quantization_range { + YYC_QUANTIZATION_LIMITED_RANGE = 0, + YYC_QUANTIZATION_FULL_RANGE = 1, + YYC_QUANTIZATION_RESERVED2 = 2, + YYC_QUANTIZATION_RESERVED3 = 3 +}; + +enum graphics_gamut_adjust_type { + GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS = 0, + GRAPHICS_GAMUT_ADJUST_TYPE_HW, /* without adjustments */ + GRAPHICS_GAMUT_ADJUST_TYPE_SW /* use adjustments */ +}; + +struct xfm_grph_csc_adjustment { + struct fixed31_32 temperature_matrix[CSC_TEMPERATURE_MATRIX_SIZE]; + enum graphics_gamut_adjust_type gamut_adjust_type; +}; + +enum lb_pixel_depth { + /* do not change the values because it is used as bit vector */ + LB_PIXEL_DEPTH_18BPP = 1, + LB_PIXEL_DEPTH_24BPP = 2, + LB_PIXEL_DEPTH_30BPP = 4, + LB_PIXEL_DEPTH_36BPP = 8 +}; + +struct overscan_info { + int left; + int right; + int top; + int bottom; +}; + +struct scaling_ratios { + struct fixed31_32 horz; + struct fixed31_32 vert; + struct fixed31_32 horz_c; + struct fixed31_32 vert_c; +}; + +struct sharpness_adj { + int horz; + int vert; +}; + +struct line_buffer_params { + bool alpha_en; + bool pixel_expan_mode; + bool interleave_en; + int dynamic_pixel_depth; + enum lb_pixel_depth depth; +}; + +struct scaler_data { + int h_active; + int v_active; + struct scaling_taps taps; + struct rect viewport; + struct rect recout; + struct scaling_ratios ratios; + struct sharpness_adj sharpness; + enum pixel_format format; + struct line_buffer_params lb_params; +}; + +struct transform_funcs { + void (*transform_reset)(struct transform *xfm); + + void (*transform_set_scaler)(struct transform *xfm, + const struct scaler_data *scl_data); + + void (*transform_set_gamut_remap)( + struct transform *xfm, + const struct xfm_grph_csc_adjustment *adjust); + + void (*transform_set_pixel_storage_depth)( + struct transform *xfm, + enum lb_pixel_depth depth, + const struct bit_depth_reduction_params *bit_depth_params); + + bool (*transform_get_optimal_number_of_taps)( + struct transform *xfm, + struct scaler_data *scl_data, + const struct scaling_taps *in_taps); +}; + +extern const uint16_t filter_2tap_16p[18]; +extern const uint16_t filter_2tap_64p[66]; +const uint16_t *get_filter_3tap_16p(struct fixed31_32 ratio); +const uint16_t *get_filter_3tap_64p(struct fixed31_32 ratio); +const uint16_t *get_filter_4tap_16p(struct fixed31_32 ratio); +const uint16_t *get_filter_4tap_64p(struct fixed31_32 ratio); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h new file mode 100644 index 000000000000..35a556dd9054 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -0,0 +1,156 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_HW_SEQUENCER_H__ +#define __DC_HW_SEQUENCER_H__ +#include "core_types.h" +#include "timing_generator.h" + +struct gamma_parameters; + +enum pipe_gating_control { + PIPE_GATING_CONTROL_DISABLE = 0, + PIPE_GATING_CONTROL_ENABLE, + PIPE_GATING_CONTROL_INIT +}; + +enum pipe_lock_control { + PIPE_LOCK_CONTROL_GRAPHICS = 1 << 0, + PIPE_LOCK_CONTROL_BLENDER = 1 << 1, + PIPE_LOCK_CONTROL_SCL = 1 << 2, + PIPE_LOCK_CONTROL_SURFACE = 1 << 3, + PIPE_LOCK_CONTROL_MODE = 1 << 4 +}; + +struct dce_hwseq; + +struct hw_sequencer_funcs { + + void (*init_hw)(struct core_dc *dc); + + enum dc_status (*apply_ctx_to_hw)( + struct core_dc *dc, struct validate_context *context); + + void (*reset_hw_ctx_wrap)( + struct core_dc *dc, struct validate_context *context); + + void (*prepare_pipe_for_context)( + struct core_dc *dc, + struct pipe_ctx *pipe_ctx, + struct validate_context *context); + + void (*apply_ctx_for_surface)( + struct core_dc *dc, + struct core_surface *surface, + struct validate_context *context); + + void (*set_plane_config)( + const struct core_dc *dc, + struct pipe_ctx *pipe_ctx, + struct resource_context *res_ctx); + + void (*update_plane_addr)( + const struct core_dc *dc, + struct pipe_ctx *pipe_ctx); + + void (*update_pending_status)( + struct pipe_ctx *pipe_ctx); + + bool (*set_gamma_correction)( + struct input_pixel_processor *ipp, + struct output_pixel_processor *opp, + const struct core_gamma *ramp, + const struct core_surface *surface); + + void (*power_down)(struct core_dc *dc); + + void (*enable_accelerated_mode)(struct core_dc *dc); + + void (*enable_timing_synchronization)( + struct core_dc *dc, + int group_index, + int group_size, + struct pipe_ctx *grouped_pipes[]); + + /* backlight control */ + void (*encoder_set_lcd_backlight_level)( + struct link_encoder *enc, uint32_t level); + + void (*enable_display_pipe_clock_gating)( + struct dc_context *ctx, + bool clock_gating); + + bool (*enable_display_power_gating)( + struct core_dc *dc, + uint8_t controller_id, + struct dc_bios *dcb, + enum pipe_gating_control power_gating); + + void (*power_down_front_end)(struct core_dc *dc, struct pipe_ctx *pipe); + void (*update_info_frame)(struct pipe_ctx *pipe_ctx); + + void (*enable_stream)(struct pipe_ctx *pipe_ctx); + + void (*disable_stream)(struct pipe_ctx *pipe_ctx); + + void (*unblank_stream)(struct pipe_ctx *pipe_ctx, + struct dc_link_settings *link_settings); + + void (*pipe_control_lock)( + struct dce_hwseq *hwseq, + unsigned int blnd_inst, + enum pipe_lock_control control_mask, + bool lock); + + void (*set_displaymarks)( + const struct core_dc *dc, + struct validate_context *context); + + void (*increase_watermarks_for_pipe)(struct core_dc *dc, + struct pipe_ctx *pipe_ctx, + struct validate_context *context); + + void (*set_display_clock)(struct validate_context *context); + + void (*set_bandwidth)(struct core_dc *dc); + + void (*set_drr)(struct pipe_ctx **pipe_ctx, int num_pipes, + int vmin, int vmax); + + void (*set_static_screen_control)(struct pipe_ctx **pipe_ctx, + int num_pipes, int value); + + enum dc_status (*prog_pixclk_crtc_otg)( + struct pipe_ctx *pipe_ctx, + struct validate_context *context, + struct core_dc *dc); +}; + +void color_space_to_black_color( + const struct core_dc *dc, + enum dc_color_space colorspace, + struct tg_color *black_color); + +#endif /* __DC_HW_SEQUENCER_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h new file mode 100644 index 000000000000..662fa30d45f7 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h @@ -0,0 +1,73 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_LINK_HWSS_H__ +#define __DC_LINK_HWSS_H__ + +#include "inc/core_status.h" + +enum dc_status core_link_read_dpcd( + struct core_link* link, + uint32_t address, + uint8_t *data, + uint32_t size); + +enum dc_status core_link_write_dpcd( + struct core_link* link, + uint32_t address, + const uint8_t *data, + uint32_t size); + +void dp_enable_link_phy( + struct core_link *link, + enum signal_type signal, + enum clock_source_id clock_source, + const struct dc_link_settings *link_settings); + +void dp_receiver_power_ctrl(struct core_link *link, bool on); + +void dp_disable_link_phy(struct core_link *link, enum signal_type signal); + +void dp_disable_link_phy_mst(struct core_link *link, enum signal_type signal); + +bool dp_set_hw_training_pattern( + struct core_link *link, + enum hw_dp_training_pattern pattern); + +void dp_set_hw_lane_settings( + struct core_link *link, + const struct link_training_settings *link_settings); + +void dp_set_hw_test_pattern( + struct core_link *link, + enum dp_test_pattern test_pattern, + uint8_t *custom_pattern, + uint32_t custom_pattern_size); + +enum dp_panel_mode dp_get_panel_mode(struct core_link *link); + +void dp_retrain_link(struct core_link *link); + +#endif /* __DC_LINK_HWSS_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h b/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h new file mode 100644 index 000000000000..159b2c519f2b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h @@ -0,0 +1,290 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + */ + +#ifndef DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_REG_HELPER_H_ +#define DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_REG_HELPER_H_ + +#include "dm_services.h" + +/* macro for register read/write + * user of macro need to define + * + * CTX ==> macro to ptr to dc_context + * eg. aud110->base.ctx + * + * REG ==> macro to location of register offset + * eg. aud110->regs->reg + */ +#define REG_READ(reg_name) \ + dm_read_reg(CTX, REG(reg_name)) + +#define REG_WRITE(reg_name, value) \ + dm_write_reg(CTX, REG(reg_name), value) + +#ifdef REG_SET +#undef REG_SET +#endif + +#ifdef REG_GET +#undef REG_GET +#endif + +/* macro to set register fields. */ +#define REG_SET_N(reg_name, n, initial_val, ...) \ + generic_reg_update_ex(CTX, \ + REG(reg_name), \ + initial_val, \ + n, __VA_ARGS__) + +#define FN(reg_name, field) \ + FD(reg_name##__##field) + +#define REG_SET(reg_name, initial_val, field, val) \ + REG_SET_N(reg_name, 1, initial_val, \ + FN(reg_name, field), val) + +#define REG_SET_2(reg, init_value, f1, v1, f2, v2) \ + REG_SET_N(reg, 2, init_value, \ + FN(reg, f1), v1,\ + FN(reg, f2), v2) + +#define REG_SET_3(reg, init_value, f1, v1, f2, v2, f3, v3) \ + REG_SET_N(reg, 3, init_value, \ + FN(reg, f1), v1,\ + FN(reg, f2), v2,\ + FN(reg, f3), v3) + +#define REG_SET_4(reg, init_value, f1, v1, f2, v2, f3, v3, f4, v4) \ + REG_SET_N(reg, 4, init_value, \ + FN(reg, f1), v1,\ + FN(reg, f2), v2,\ + FN(reg, f3), v3,\ + FN(reg, f4), v4) + +#define REG_SET_5(reg, init_value, f1, v1, f2, v2, f3, v3, f4, v4, \ + f5, v5) \ + REG_SET_N(reg, 6, init_value, \ + FN(reg, f1), v1,\ + FN(reg, f2), v2,\ + FN(reg, f3), v3,\ + FN(reg, f4), v4,\ + FN(reg, f5), v5) + +#define REG_SET_6(reg, init_value, f1, v1, f2, v2, f3, v3, f4, v4, \ + f5, v5, f6, v6) \ + REG_SET_N(reg, 6, init_value, \ + FN(reg, f1), v1,\ + FN(reg, f2), v2,\ + FN(reg, f3), v3,\ + FN(reg, f4), v4,\ + FN(reg, f5), v5,\ + FN(reg, f6), v6) + +#define REG_SET_7(reg, init_value, f1, v1, f2, v2, f3, v3, f4, v4, \ + f5, v5, f6, v6, f7, v7) \ + REG_SET_N(reg, 7, init_value, \ + FN(reg, f1), v1,\ + FN(reg, f2), v2,\ + FN(reg, f3), v3,\ + FN(reg, f4), v4,\ + FN(reg, f5), v5,\ + FN(reg, f6), v6,\ + FN(reg, f7), v7) + +#define REG_SET_10(reg, init_value, f1, v1, f2, v2, f3, v3, f4, v4, f5, \ + v5, f6, v6, f7, v7, f8, v8, f9, v9, f10, v10) \ + REG_SET_N(reg, 10, init_value, \ + FN(reg, f1), v1,\ + FN(reg, f2), v2, \ + FN(reg, f3), v3, \ + FN(reg, f4), v4, \ + FN(reg, f5), v5, \ + FN(reg, f6), v6, \ + FN(reg, f7), v7, \ + FN(reg, f8), v8, \ + FN(reg, f9), v9, \ + FN(reg, f10), v10) + +/* macro to get register fields + * read given register and fill in field value in output parameter */ +#define REG_GET(reg_name, field, val) \ + generic_reg_get(CTX, REG(reg_name), \ + FN(reg_name, field), val) + +#define REG_GET_2(reg_name, f1, v1, f2, v2) \ + generic_reg_get2(CTX, REG(reg_name), \ + FN(reg_name, f1), v1, \ + FN(reg_name, f2), v2) + +#define REG_GET_3(reg_name, f1, v1, f2, v2, f3, v3) \ + generic_reg_get3(CTX, REG(reg_name), \ + FN(reg_name, f1), v1, \ + FN(reg_name, f2), v2, \ + FN(reg_name, f3), v3) + +#define REG_GET_5(reg_name, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5) \ + generic_reg_get5(CTX, REG(reg_name), \ + FN(reg_name, f1), v1, \ + FN(reg_name, f2), v2, \ + FN(reg_name, f3), v3, \ + FN(reg_name, f4), v4, \ + FN(reg_name, f5), v5) + +/* macro to poll and wait for a register field to read back given value */ + +#define REG_WAIT(reg_name, field, val, delay, max_try) \ + generic_reg_wait(CTX, \ + REG(reg_name), FN(reg_name, field), val,\ + delay, max_try, __func__) + +/* macro to update (read, modify, write) register fields + */ +#define REG_UPDATE_N(reg_name, n, ...) \ + generic_reg_update_ex(CTX, \ + REG(reg_name), \ + REG_READ(reg_name), \ + n, __VA_ARGS__) + +#define REG_UPDATE(reg_name, field, val) \ + REG_UPDATE_N(reg_name, 1, \ + FN(reg_name, field), val) + +#define REG_UPDATE_2(reg, f1, v1, f2, v2) \ + REG_UPDATE_N(reg, 2,\ + FN(reg, f1), v1,\ + FN(reg, f2), v2) + +#define REG_UPDATE_3(reg, f1, v1, f2, v2, f3, v3) \ + REG_UPDATE_N(reg, 3, \ + FN(reg, f1), v1,\ + FN(reg, f2), v2, \ + FN(reg, f3), v3) + +#define REG_UPDATE_4(reg, f1, v1, f2, v2, f3, v3, f4, v4) \ + REG_UPDATE_N(reg, 4, \ + FN(reg, f1), v1,\ + FN(reg, f2), v2, \ + FN(reg, f3), v3, \ + FN(reg, f4), v4) + +#define REG_UPDATE_5(reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5) \ + REG_UPDATE_N(reg, 5, \ + FN(reg, f1), v1,\ + FN(reg, f2), v2, \ + FN(reg, f3), v3, \ + FN(reg, f4), v4, \ + FN(reg, f5), v5) + +#define REG_UPDATE_6(reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6) \ + REG_UPDATE_N(reg, 6, \ + FN(reg, f1), v1,\ + FN(reg, f2), v2, \ + FN(reg, f3), v3, \ + FN(reg, f4), v4, \ + FN(reg, f5), v5, \ + FN(reg, f6), v6) + +#define REG_UPDATE_7(reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7) \ + REG_UPDATE_N(reg, 7, \ + FN(reg, f1), v1,\ + FN(reg, f2), v2, \ + FN(reg, f3), v3, \ + FN(reg, f4), v4, \ + FN(reg, f5), v5, \ + FN(reg, f6), v6, \ + FN(reg, f7), v7) + +#define REG_UPDATE_8(reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8) \ + REG_UPDATE_N(reg, 8, \ + FN(reg, f1), v1,\ + FN(reg, f2), v2, \ + FN(reg, f3), v3, \ + FN(reg, f4), v4, \ + FN(reg, f5), v5, \ + FN(reg, f6), v6, \ + FN(reg, f7), v7, \ + FN(reg, f8), v8) + +#define REG_UPDATE_9(reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9) \ + REG_UPDATE_N(reg, 9, \ + FN(reg, f1), v1,\ + FN(reg, f2), v2, \ + FN(reg, f3), v3, \ + FN(reg, f4), v4, \ + FN(reg, f5), v5, \ + FN(reg, f6), v6, \ + FN(reg, f7), v7, \ + FN(reg, f8), v8, \ + FN(reg, f9), v9) + +#define REG_UPDATE_10(reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10, v10) \ + REG_UPDATE_N(reg, 10, \ + FN(reg, f1), v1,\ + FN(reg, f2), v2, \ + FN(reg, f3), v3, \ + FN(reg, f4), v4, \ + FN(reg, f5), v5, \ + FN(reg, f6), v6, \ + FN(reg, f7), v7, \ + FN(reg, f8), v8, \ + FN(reg, f9), v9, \ + FN(reg, f10), v10) + +/* macro to update a register field to specified values in given sequences. + * useful when toggling bits + */ +#define REG_UPDATE_SEQ(reg, field, value1, value2) \ +{ uint32_t val = REG_UPDATE(reg, field, value1); \ + REG_SET(reg, val, field, value2); } + +/* macro to update fields in register 1 field at a time in given order */ +#define REG_UPDATE_1BY1_2(reg, f1, v1, f2, v2) \ +{ uint32_t val = REG_UPDATE(reg, f1, v1); \ + REG_SET(reg, val, f2, v2); } + +#define REG_UPDATE_1BY1_3(reg, f1, v1, f2, v2, f3, v3) \ +{ uint32_t val = REG_UPDATE(reg, f1, v1); \ + val = REG_SET(reg, val, f2, v2); \ + REG_SET(reg, val, f3, v3); } + +uint32_t generic_reg_get(const struct dc_context *ctx, uint32_t addr, + uint8_t shift, uint32_t mask, uint32_t *field_value); + +uint32_t generic_reg_get2(const struct dc_context *ctx, uint32_t addr, + uint8_t shift1, uint32_t mask1, uint32_t *field_value1, + uint8_t shift2, uint32_t mask2, uint32_t *field_value2); + +uint32_t generic_reg_get3(const struct dc_context *ctx, uint32_t addr, + uint8_t shift1, uint32_t mask1, uint32_t *field_value1, + uint8_t shift2, uint32_t mask2, uint32_t *field_value2, + uint8_t shift3, uint32_t mask3, uint32_t *field_value3); + +uint32_t generic_reg_get5(const struct dc_context *ctx, uint32_t addr, + uint8_t shift1, uint32_t mask1, uint32_t *field_value1, + uint8_t shift2, uint32_t mask2, uint32_t *field_value2, + uint8_t shift3, uint32_t mask3, uint32_t *field_value3, + uint8_t shift4, uint32_t mask4, uint32_t *field_value4, + uint8_t shift5, uint32_t mask5, uint32_t *field_value5); + +#endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_REG_HELPER_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h new file mode 100644 index 000000000000..8dd676de6b07 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -0,0 +1,164 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + */ + +#ifndef DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_RESOURCE_H_ +#define DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_RESOURCE_H_ + +#include "core_types.h" +#include "core_status.h" +#include "core_dc.h" +#include "dal_asic_id.h" + +/* TODO unhardcode, 4 for CZ*/ +#define MEMORY_TYPE_MULTIPLIER 4 + +enum dce_version resource_parse_asic_id( + struct hw_asic_id asic_id); + +struct resource_caps { + int num_timing_generator; + int num_video_plane; + int num_audio; + int num_stream_encoder; + int num_pll; +}; + +struct resource_straps { + uint32_t hdmi_disable; + uint32_t dc_pinstraps_audio; + uint32_t audio_stream_number; +}; + +struct resource_create_funcs { + void (*read_dce_straps)( + struct dc_context *ctx, struct resource_straps *straps); + + struct audio *(*create_audio)( + struct dc_context *ctx, unsigned int inst); + + struct stream_encoder *(*create_stream_encoder)( + enum engine_id eng_id, struct dc_context *ctx); + + struct dce_hwseq *(*create_hwseq)( + struct dc_context *ctx); +}; + +bool resource_construct( + unsigned int num_virtual_links, + struct core_dc *dc, + struct resource_pool *pool, + const struct resource_create_funcs *create_funcs); + +struct resource_pool *dc_create_resource_pool( + struct core_dc *dc, + int num_virtual_links, + enum dce_version dc_version, + struct hw_asic_id asic_id); + +void dc_destroy_resource_pool(struct core_dc *dc); + +enum dc_status resource_map_pool_resources( + const struct core_dc *dc, + struct validate_context *context); + +bool resource_build_scaling_params( + const struct dc_surface *surface, + struct pipe_ctx *pipe_ctx); + +enum dc_status resource_build_scaling_params_for_context( + const struct core_dc *dc, + struct validate_context *context); + +void resource_build_info_frame(struct pipe_ctx *pipe_ctx); + +void resource_unreference_clock_source( + struct resource_context *res_ctx, + struct clock_source *clock_source); + +void resource_reference_clock_source( + struct resource_context *res_ctx, + struct clock_source *clock_source); + +bool resource_are_streams_timing_synchronizable( + const struct core_stream *stream1, + const struct core_stream *stream2); + +struct clock_source *resource_find_used_clk_src_for_sharing( + struct resource_context *res_ctx, + struct pipe_ctx *pipe_ctx); + +struct clock_source *dc_resource_find_first_free_pll( + struct resource_context *res_ctx); + +struct pipe_ctx *resource_get_head_pipe_for_stream( + struct resource_context *res_ctx, + const struct core_stream *stream); + +bool resource_attach_surfaces_to_context( + const struct dc_surface *const *surfaces, + int surface_count, + const struct dc_target *dc_target, + struct validate_context *context); + +struct pipe_ctx *find_idle_secondary_pipe(struct resource_context *res_ctx); + +bool resource_is_stream_unchanged( + const struct validate_context *old_context, struct core_stream *stream); + +bool is_target_unchanged( + const struct core_target *old_target, const struct core_target *target); +bool resource_validate_attach_surfaces( + const struct dc_validation_set set[], + int set_count, + const struct validate_context *old_context, + struct validate_context *context); + +void validate_guaranteed_copy_target( + struct validate_context *context, + int max_targets); + +void resource_validate_ctx_update_pointer_after_copy( + const struct validate_context *src_ctx, + struct validate_context *dst_ctx); + +void resource_validate_ctx_copy_construct( + const struct validate_context *src_ctx, + struct validate_context *dst_ctx); + +void resource_validate_ctx_destruct(struct validate_context *context); + +enum dc_status resource_map_clock_resources( + const struct core_dc *dc, + struct validate_context *context); + +enum dc_status resource_map_phy_clock_resources( + const struct core_dc *dc, + struct validate_context *context); + +bool pipe_need_reprogram( + struct pipe_ctx *pipe_ctx_old, + struct pipe_ctx *pipe_ctx); + + +#endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/irq/Makefile b/drivers/gpu/drm/amd/display/dc/irq/Makefile new file mode 100644 index 000000000000..02710333ce0a --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/irq/Makefile @@ -0,0 +1,28 @@ +# +# Makefile for the 'audio' sub-component of DAL. +# It provides the control and status of HW adapter resources, +# that are global for the ASIC and sharable between pipes. + +IRQ = irq_service.o + +AMD_DAL_IRQ = $(addprefix $(AMDDALPATH)/dc/irq/,$(IRQ)) + +AMD_DISPLAY_FILES += $(AMD_DAL_IRQ) + +############################################################################### +# DCE 8x +############################################################################### +IRQ_DCE80 = irq_service_dce80.o + +AMD_DAL_IRQ_DCE80 = $(addprefix $(AMDDALPATH)/dc/irq/dce80/,$(IRQ_DCE80)) + +AMD_DISPLAY_FILES += $(AMD_DAL_IRQ_DCE80) + +############################################################################### +# DCE 11x +############################################################################### +IRQ_DCE11 = irq_service_dce110.o + +AMD_DAL_IRQ_DCE11 = $(addprefix $(AMDDALPATH)/dc/irq/dce110/,$(IRQ_DCE11)) + +AMD_DISPLAY_FILES += $(AMD_DAL_IRQ_DCE11) diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c new file mode 100644 index 000000000000..f3eda1b4eebf --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c @@ -0,0 +1,367 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "include/logger_interface.h" + +#include "irq_service_dce110.h" + +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" +#include "ivsrcid/ivsrcid_vislands30.h" + +static bool hpd_ack( + struct irq_service *irq_service, + const struct irq_source_info *info) +{ + uint32_t addr = info->status_reg; + uint32_t value = dm_read_reg(irq_service->ctx, addr); + uint32_t current_status = + get_reg_field_value( + value, + DC_HPD_INT_STATUS, + DC_HPD_SENSE_DELAYED); + + dal_irq_service_ack_generic(irq_service, info); + + value = dm_read_reg(irq_service->ctx, info->enable_reg); + + set_reg_field_value( + value, + current_status ? 0 : 1, + DC_HPD_INT_CONTROL, + DC_HPD_INT_POLARITY); + + dm_write_reg(irq_service->ctx, info->enable_reg, value); + + return true; +} + +static const struct irq_source_info_funcs hpd_irq_info_funcs = { + .set = NULL, + .ack = hpd_ack +}; + +static const struct irq_source_info_funcs hpd_rx_irq_info_funcs = { + .set = NULL, + .ack = NULL +}; + +static const struct irq_source_info_funcs pflip_irq_info_funcs = { + .set = NULL, + .ack = NULL +}; + +static const struct irq_source_info_funcs vblank_irq_info_funcs = { + .set = NULL, + .ack = NULL +}; + +#define hpd_int_entry(reg_num)\ + [DC_IRQ_SOURCE_HPD1 + reg_num] = {\ + .enable_reg = mmHPD ## reg_num ## _DC_HPD_INT_CONTROL,\ + .enable_mask = DC_HPD_INT_CONTROL__DC_HPD_INT_EN_MASK,\ + .enable_value = {\ + DC_HPD_INT_CONTROL__DC_HPD_INT_EN_MASK,\ + ~DC_HPD_INT_CONTROL__DC_HPD_INT_EN_MASK\ + },\ + .ack_reg = mmHPD ## reg_num ## _DC_HPD_INT_CONTROL,\ + .ack_mask = DC_HPD_INT_CONTROL__DC_HPD_INT_ACK_MASK,\ + .ack_value = DC_HPD_INT_CONTROL__DC_HPD_INT_ACK_MASK,\ + .status_reg = mmHPD ## reg_num ## _DC_HPD_INT_STATUS,\ + .funcs = &hpd_irq_info_funcs\ + } + +#define hpd_rx_int_entry(reg_num)\ + [DC_IRQ_SOURCE_HPD1RX + reg_num] = {\ + .enable_reg = mmHPD ## reg_num ## _DC_HPD_INT_CONTROL,\ + .enable_mask = DC_HPD_INT_CONTROL__DC_HPD_RX_INT_EN_MASK,\ + .enable_value = {\ + DC_HPD_INT_CONTROL__DC_HPD_RX_INT_EN_MASK,\ + ~DC_HPD_INT_CONTROL__DC_HPD_RX_INT_EN_MASK },\ + .ack_reg = mmHPD ## reg_num ## _DC_HPD_INT_CONTROL,\ + .ack_mask = DC_HPD_INT_CONTROL__DC_HPD_RX_INT_ACK_MASK,\ + .ack_value = DC_HPD_INT_CONTROL__DC_HPD_RX_INT_ACK_MASK,\ + .status_reg = mmHPD ## reg_num ## _DC_HPD_INT_STATUS,\ + .funcs = &hpd_rx_irq_info_funcs\ + } +#define pflip_int_entry(reg_num)\ + [DC_IRQ_SOURCE_PFLIP1 + reg_num] = {\ + .enable_reg = mmDCP ## reg_num ## _GRPH_INTERRUPT_CONTROL,\ + .enable_mask =\ + GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK,\ + .enable_value = {\ + GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK,\ + ~GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK},\ + .ack_reg = mmDCP ## reg_num ## _GRPH_INTERRUPT_STATUS,\ + .ack_mask = GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_CLEAR_MASK,\ + .ack_value = GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_CLEAR_MASK,\ + .status_reg = mmDCP ## reg_num ##_GRPH_INTERRUPT_STATUS,\ + .funcs = &pflip_irq_info_funcs\ + } + +#define vupdate_int_entry(reg_num)\ + [DC_IRQ_SOURCE_VUPDATE1 + reg_num] = {\ + .enable_reg = mmCRTC ## reg_num ## _CRTC_INTERRUPT_CONTROL,\ + .enable_mask =\ + CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK,\ + .enable_value = {\ + CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK,\ + ~CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK},\ + .ack_reg = mmCRTC ## reg_num ## _CRTC_V_UPDATE_INT_STATUS,\ + .ack_mask =\ + CRTC_V_UPDATE_INT_STATUS__CRTC_V_UPDATE_INT_CLEAR_MASK,\ + .ack_value =\ + CRTC_V_UPDATE_INT_STATUS__CRTC_V_UPDATE_INT_CLEAR_MASK,\ + .funcs = &vblank_irq_info_funcs\ + } + +#define dummy_irq_entry() \ + {\ + .funcs = &dummy_irq_info_funcs\ + } + +#define i2c_int_entry(reg_num) \ + [DC_IRQ_SOURCE_I2C_DDC ## reg_num] = dummy_irq_entry() + +#define dp_sink_int_entry(reg_num) \ + [DC_IRQ_SOURCE_DPSINK ## reg_num] = dummy_irq_entry() + +#define gpio_pad_int_entry(reg_num) \ + [DC_IRQ_SOURCE_GPIOPAD ## reg_num] = dummy_irq_entry() + +#define dc_underflow_int_entry(reg_num) \ + [DC_IRQ_SOURCE_DC ## reg_num ## UNDERFLOW] = dummy_irq_entry() + +bool dal_irq_service_dummy_set( + struct irq_service *irq_service, + const struct irq_source_info *info, + bool enable) +{ + dm_logger_write( + irq_service->ctx->logger, LOG_ERROR, + "%s: called for non-implemented irq source\n", + __func__); + return false; +} + +bool dal_irq_service_dummy_ack( + struct irq_service *irq_service, + const struct irq_source_info *info) +{ + dm_logger_write( + irq_service->ctx->logger, LOG_ERROR, + "%s: called for non-implemented irq source\n", + __func__); + return false; +} + +static const struct irq_source_info_funcs dummy_irq_info_funcs = { + .set = dal_irq_service_dummy_set, + .ack = dal_irq_service_dummy_ack +}; + +static const struct irq_source_info +irq_source_info_dce110[DAL_IRQ_SOURCES_NUMBER] = { + [DC_IRQ_SOURCE_INVALID] = dummy_irq_entry(), + hpd_int_entry(0), + hpd_int_entry(1), + hpd_int_entry(2), + hpd_int_entry(3), + hpd_int_entry(4), + hpd_int_entry(5), + hpd_rx_int_entry(0), + hpd_rx_int_entry(1), + hpd_rx_int_entry(2), + hpd_rx_int_entry(3), + hpd_rx_int_entry(4), + hpd_rx_int_entry(5), + i2c_int_entry(1), + i2c_int_entry(2), + i2c_int_entry(3), + i2c_int_entry(4), + i2c_int_entry(5), + i2c_int_entry(6), + dp_sink_int_entry(1), + dp_sink_int_entry(2), + dp_sink_int_entry(3), + dp_sink_int_entry(4), + dp_sink_int_entry(5), + dp_sink_int_entry(6), + [DC_IRQ_SOURCE_TIMER] = dummy_irq_entry(), + pflip_int_entry(0), + pflip_int_entry(1), + pflip_int_entry(2), + pflip_int_entry(3), + pflip_int_entry(4), + pflip_int_entry(5), + [DC_IRQ_SOURCE_PFLIP_UNDERLAY0] = dummy_irq_entry(), + gpio_pad_int_entry(0), + gpio_pad_int_entry(1), + gpio_pad_int_entry(2), + gpio_pad_int_entry(3), + gpio_pad_int_entry(4), + gpio_pad_int_entry(5), + gpio_pad_int_entry(6), + gpio_pad_int_entry(7), + gpio_pad_int_entry(8), + gpio_pad_int_entry(9), + gpio_pad_int_entry(10), + gpio_pad_int_entry(11), + gpio_pad_int_entry(12), + gpio_pad_int_entry(13), + gpio_pad_int_entry(14), + gpio_pad_int_entry(15), + gpio_pad_int_entry(16), + gpio_pad_int_entry(17), + gpio_pad_int_entry(18), + gpio_pad_int_entry(19), + gpio_pad_int_entry(20), + gpio_pad_int_entry(21), + gpio_pad_int_entry(22), + gpio_pad_int_entry(23), + gpio_pad_int_entry(24), + gpio_pad_int_entry(25), + gpio_pad_int_entry(26), + gpio_pad_int_entry(27), + gpio_pad_int_entry(28), + gpio_pad_int_entry(29), + gpio_pad_int_entry(30), + dc_underflow_int_entry(1), + dc_underflow_int_entry(2), + dc_underflow_int_entry(3), + dc_underflow_int_entry(4), + dc_underflow_int_entry(5), + dc_underflow_int_entry(6), + [DC_IRQ_SOURCE_DMCU_SCP] = dummy_irq_entry(), + [DC_IRQ_SOURCE_VBIOS_SW] = dummy_irq_entry(), + vupdate_int_entry(0), + vupdate_int_entry(1), + vupdate_int_entry(2), + vupdate_int_entry(3), + vupdate_int_entry(4), + vupdate_int_entry(5), +}; + +enum dc_irq_source to_dal_irq_source_dce110( + struct irq_service *irq_service, + uint32_t src_id, + uint32_t ext_id) +{ + switch (src_id) { + case VISLANDS30_IV_SRCID_D1_V_UPDATE_INT: + return DC_IRQ_SOURCE_VUPDATE1; + case VISLANDS30_IV_SRCID_D2_V_UPDATE_INT: + return DC_IRQ_SOURCE_VUPDATE2; + case VISLANDS30_IV_SRCID_D3_V_UPDATE_INT: + return DC_IRQ_SOURCE_VUPDATE3; + case VISLANDS30_IV_SRCID_D4_V_UPDATE_INT: + return DC_IRQ_SOURCE_VUPDATE4; + case VISLANDS30_IV_SRCID_D5_V_UPDATE_INT: + return DC_IRQ_SOURCE_VUPDATE5; + case VISLANDS30_IV_SRCID_D6_V_UPDATE_INT: + return DC_IRQ_SOURCE_VUPDATE6; + case VISLANDS30_IV_SRCID_D1_GRPH_PFLIP: + return DC_IRQ_SOURCE_PFLIP1; + case VISLANDS30_IV_SRCID_D2_GRPH_PFLIP: + return DC_IRQ_SOURCE_PFLIP2; + case VISLANDS30_IV_SRCID_D3_GRPH_PFLIP: + return DC_IRQ_SOURCE_PFLIP3; + case VISLANDS30_IV_SRCID_D4_GRPH_PFLIP: + return DC_IRQ_SOURCE_PFLIP4; + case VISLANDS30_IV_SRCID_D5_GRPH_PFLIP: + return DC_IRQ_SOURCE_PFLIP5; + case VISLANDS30_IV_SRCID_D6_GRPH_PFLIP: + return DC_IRQ_SOURCE_PFLIP6; + + case VISLANDS30_IV_SRCID_HOTPLUG_DETECT_A: + /* generic src_id for all HPD and HPDRX interrupts */ + switch (ext_id) { + case VISLANDS30_IV_EXTID_HOTPLUG_DETECT_A: + return DC_IRQ_SOURCE_HPD1; + case VISLANDS30_IV_EXTID_HOTPLUG_DETECT_B: + return DC_IRQ_SOURCE_HPD2; + case VISLANDS30_IV_EXTID_HOTPLUG_DETECT_C: + return DC_IRQ_SOURCE_HPD3; + case VISLANDS30_IV_EXTID_HOTPLUG_DETECT_D: + return DC_IRQ_SOURCE_HPD4; + case VISLANDS30_IV_EXTID_HOTPLUG_DETECT_E: + return DC_IRQ_SOURCE_HPD5; + case VISLANDS30_IV_EXTID_HOTPLUG_DETECT_F: + return DC_IRQ_SOURCE_HPD6; + case VISLANDS30_IV_EXTID_HPD_RX_A: + return DC_IRQ_SOURCE_HPD1RX; + case VISLANDS30_IV_EXTID_HPD_RX_B: + return DC_IRQ_SOURCE_HPD2RX; + case VISLANDS30_IV_EXTID_HPD_RX_C: + return DC_IRQ_SOURCE_HPD3RX; + case VISLANDS30_IV_EXTID_HPD_RX_D: + return DC_IRQ_SOURCE_HPD4RX; + case VISLANDS30_IV_EXTID_HPD_RX_E: + return DC_IRQ_SOURCE_HPD5RX; + case VISLANDS30_IV_EXTID_HPD_RX_F: + return DC_IRQ_SOURCE_HPD6RX; + default: + return DC_IRQ_SOURCE_INVALID; + } + break; + + default: + return DC_IRQ_SOURCE_INVALID; + } +} + +static const struct irq_service_funcs irq_service_funcs_dce110 = { + .to_dal_irq_source = to_dal_irq_source_dce110 +}; + +bool construct( + struct irq_service *irq_service, + struct irq_service_init_data *init_data) +{ + if (!dal_irq_service_construct(irq_service, init_data)) + return false; + + irq_service->info = irq_source_info_dce110; + irq_service->funcs = &irq_service_funcs_dce110; + + return true; +} + +struct irq_service *dal_irq_service_dce110_create( + struct irq_service_init_data *init_data) +{ + struct irq_service *irq_service = dm_alloc(sizeof(*irq_service)); + + if (!irq_service) + return NULL; + + if (construct(irq_service, init_data)) + return irq_service; + + dm_free(irq_service); + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.h b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.h new file mode 100644 index 000000000000..a84f360c6515 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.h @@ -0,0 +1,48 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_IRQ_SERVICE_DCE110_H__ +#define __DAL_IRQ_SERVICE_DCE110_H__ + +#include "../irq_service.h" + +struct irq_service *dal_irq_service_dce110_create( + struct irq_service_init_data *init_data); + +enum dc_irq_source to_dal_irq_source_dce110( + struct irq_service *irq_service, + uint32_t src_id, + uint32_t ext_id); + +bool dal_irq_service_dummy_set( + struct irq_service *irq_service, + const struct irq_source_info *info, + bool enable); + +bool dal_irq_service_dummy_ack( + struct irq_service *irq_service, + const struct irq_source_info *info); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c b/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c new file mode 100644 index 000000000000..8b4f45389783 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c @@ -0,0 +1,283 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "include/logger_interface.h" + +#include "irq_service_dce80.h" +#include "../dce110/irq_service_dce110.h" + +#include "dce/dce_8_0_d.h" +#include "dce/dce_8_0_sh_mask.h" + +#include "ivsrcid/ivsrcid_vislands30.h" + +static bool hpd_ack( + struct irq_service *irq_service, + const struct irq_source_info *info) +{ + uint32_t addr = info->status_reg; + uint32_t value = dm_read_reg(irq_service->ctx, addr); + uint32_t current_status = + get_reg_field_value( + value, + DC_HPD1_INT_STATUS, + DC_HPD1_SENSE_DELAYED); + + dal_irq_service_ack_generic(irq_service, info); + + value = dm_read_reg(irq_service->ctx, info->enable_reg); + + set_reg_field_value( + value, + current_status ? 0 : 1, + DC_HPD1_INT_CONTROL, + DC_HPD1_INT_POLARITY); + + dm_write_reg(irq_service->ctx, info->enable_reg, value); + + return true; +} + +static const struct irq_source_info_funcs hpd_irq_info_funcs = { + .set = NULL, + .ack = hpd_ack +}; + +static const struct irq_source_info_funcs hpd_rx_irq_info_funcs = { + .set = NULL, + .ack = NULL +}; + +static const struct irq_source_info_funcs pflip_irq_info_funcs = { + .set = NULL, + .ack = NULL +}; + +static const struct irq_source_info_funcs vblank_irq_info_funcs = { + .set = NULL, + .ack = NULL +}; + + +#define hpd_int_entry(reg_num)\ + [DC_IRQ_SOURCE_INVALID + reg_num] = {\ + .enable_reg = mmDC_HPD ## reg_num ## _INT_CONTROL,\ + .enable_mask = DC_HPD1_INT_CONTROL__DC_HPD1_INT_EN_MASK,\ + .enable_value = {\ + DC_HPD1_INT_CONTROL__DC_HPD1_INT_EN_MASK,\ + ~DC_HPD1_INT_CONTROL__DC_HPD1_INT_EN_MASK\ + },\ + .ack_reg = mmDC_HPD ## reg_num ## _INT_CONTROL,\ + .ack_mask = DC_HPD1_INT_CONTROL__DC_HPD1_INT_ACK_MASK,\ + .ack_value = DC_HPD1_INT_CONTROL__DC_HPD1_INT_ACK_MASK,\ + .status_reg = mmDC_HPD ## reg_num ## _INT_STATUS,\ + .funcs = &hpd_irq_info_funcs\ + } + +#define hpd_rx_int_entry(reg_num)\ + [DC_IRQ_SOURCE_HPD6 + reg_num] = {\ + .enable_reg = mmDC_HPD ## reg_num ## _INT_CONTROL,\ + .enable_mask = DC_HPD1_INT_CONTROL__DC_HPD1_RX_INT_EN_MASK,\ + .enable_value = {\ + DC_HPD1_INT_CONTROL__DC_HPD1_RX_INT_EN_MASK,\ + ~DC_HPD1_INT_CONTROL__DC_HPD1_RX_INT_EN_MASK },\ + .ack_reg = mmDC_HPD ## reg_num ## _INT_CONTROL,\ + .ack_mask = DC_HPD1_INT_CONTROL__DC_HPD1_RX_INT_ACK_MASK,\ + .ack_value = DC_HPD1_INT_CONTROL__DC_HPD1_RX_INT_ACK_MASK,\ + .status_reg = mmDC_HPD ## reg_num ## _INT_STATUS,\ + .funcs = &hpd_rx_irq_info_funcs\ + } + +#define pflip_int_entry(reg_num)\ + [DC_IRQ_SOURCE_PFLIP1 + reg_num] = {\ + .enable_reg = mmDCP ## reg_num ## _GRPH_INTERRUPT_CONTROL,\ + .enable_mask =\ + GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK,\ + .enable_value = {\ + GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK,\ + ~GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK},\ + .ack_reg = mmDCP ## reg_num ## _GRPH_INTERRUPT_STATUS,\ + .ack_mask = GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_CLEAR_MASK,\ + .ack_value = GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_CLEAR_MASK,\ + .status_reg = mmDCP ## reg_num ##_GRPH_INTERRUPT_STATUS,\ + .funcs = &pflip_irq_info_funcs\ + } + +#define vupdate_int_entry(reg_num)\ + [DC_IRQ_SOURCE_VUPDATE1 + reg_num] = {\ + .enable_reg = mmCRTC ## reg_num ## _CRTC_INTERRUPT_CONTROL,\ + .enable_mask =\ + CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK,\ + .enable_value = {\ + CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK,\ + ~CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK},\ + .ack_reg = mmCRTC ## reg_num ## _CRTC_V_UPDATE_INT_STATUS,\ + .ack_mask =\ + CRTC_V_UPDATE_INT_STATUS__CRTC_V_UPDATE_INT_CLEAR_MASK,\ + .ack_value =\ + CRTC_V_UPDATE_INT_STATUS__CRTC_V_UPDATE_INT_CLEAR_MASK,\ + .funcs = &vblank_irq_info_funcs\ + } + +#define dummy_irq_entry() \ + {\ + .funcs = &dummy_irq_info_funcs\ + } + +#define i2c_int_entry(reg_num) \ + [DC_IRQ_SOURCE_I2C_DDC ## reg_num] = dummy_irq_entry() + +#define dp_sink_int_entry(reg_num) \ + [DC_IRQ_SOURCE_DPSINK ## reg_num] = dummy_irq_entry() + +#define gpio_pad_int_entry(reg_num) \ + [DC_IRQ_SOURCE_GPIOPAD ## reg_num] = dummy_irq_entry() + +#define dc_underflow_int_entry(reg_num) \ + [DC_IRQ_SOURCE_DC ## reg_num ## UNDERFLOW] = dummy_irq_entry() + + +static const struct irq_source_info_funcs dummy_irq_info_funcs = { + .set = dal_irq_service_dummy_set, + .ack = dal_irq_service_dummy_ack +}; + +static const struct irq_source_info +irq_source_info_dce80[DAL_IRQ_SOURCES_NUMBER] = { + [DC_IRQ_SOURCE_INVALID] = dummy_irq_entry(), + hpd_int_entry(1), + hpd_int_entry(2), + hpd_int_entry(3), + hpd_int_entry(4), + hpd_int_entry(5), + hpd_int_entry(6), + hpd_rx_int_entry(1), + hpd_rx_int_entry(2), + hpd_rx_int_entry(3), + hpd_rx_int_entry(4), + hpd_rx_int_entry(5), + hpd_rx_int_entry(6), + i2c_int_entry(1), + i2c_int_entry(2), + i2c_int_entry(3), + i2c_int_entry(4), + i2c_int_entry(5), + i2c_int_entry(6), + dp_sink_int_entry(1), + dp_sink_int_entry(2), + dp_sink_int_entry(3), + dp_sink_int_entry(4), + dp_sink_int_entry(5), + dp_sink_int_entry(6), + [DC_IRQ_SOURCE_TIMER] = dummy_irq_entry(), + pflip_int_entry(0), + pflip_int_entry(1), + pflip_int_entry(2), + pflip_int_entry(3), + pflip_int_entry(4), + pflip_int_entry(5), + [DC_IRQ_SOURCE_PFLIP_UNDERLAY0] = dummy_irq_entry(), + gpio_pad_int_entry(0), + gpio_pad_int_entry(1), + gpio_pad_int_entry(2), + gpio_pad_int_entry(3), + gpio_pad_int_entry(4), + gpio_pad_int_entry(5), + gpio_pad_int_entry(6), + gpio_pad_int_entry(7), + gpio_pad_int_entry(8), + gpio_pad_int_entry(9), + gpio_pad_int_entry(10), + gpio_pad_int_entry(11), + gpio_pad_int_entry(12), + gpio_pad_int_entry(13), + gpio_pad_int_entry(14), + gpio_pad_int_entry(15), + gpio_pad_int_entry(16), + gpio_pad_int_entry(17), + gpio_pad_int_entry(18), + gpio_pad_int_entry(19), + gpio_pad_int_entry(20), + gpio_pad_int_entry(21), + gpio_pad_int_entry(22), + gpio_pad_int_entry(23), + gpio_pad_int_entry(24), + gpio_pad_int_entry(25), + gpio_pad_int_entry(26), + gpio_pad_int_entry(27), + gpio_pad_int_entry(28), + gpio_pad_int_entry(29), + gpio_pad_int_entry(30), + dc_underflow_int_entry(1), + dc_underflow_int_entry(2), + dc_underflow_int_entry(3), + dc_underflow_int_entry(4), + dc_underflow_int_entry(5), + dc_underflow_int_entry(6), + [DC_IRQ_SOURCE_DMCU_SCP] = dummy_irq_entry(), + [DC_IRQ_SOURCE_VBIOS_SW] = dummy_irq_entry(), + vupdate_int_entry(0), + vupdate_int_entry(1), + vupdate_int_entry(2), + vupdate_int_entry(3), + vupdate_int_entry(4), + vupdate_int_entry(5), +}; + +static const struct irq_service_funcs irq_service_funcs_dce80 = { + .to_dal_irq_source = to_dal_irq_source_dce110 +}; + +static bool construct( + struct irq_service *irq_service, + struct irq_service_init_data *init_data) +{ + if (!dal_irq_service_construct(irq_service, init_data)) + return false; + + irq_service->info = irq_source_info_dce80; + irq_service->funcs = &irq_service_funcs_dce80; + + return true; +} + +struct irq_service *dal_irq_service_dce80_create( + struct irq_service_init_data *init_data) +{ + struct irq_service *irq_service = dm_alloc(sizeof(*irq_service)); + + if (!irq_service) + return NULL; + + if (construct(irq_service, init_data)) + return irq_service; + + dm_free(irq_service); + return NULL; +} + + diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.h b/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.h new file mode 100644 index 000000000000..3dd1013576ea --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.h @@ -0,0 +1,35 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_IRQ_SERVICE_DCE80_H__ +#define __DAL_IRQ_SERVICE_DCE80_H__ + +#include "../irq_service.h" + +struct irq_service *dal_irq_service_dce80_create( + struct irq_service_init_data *init_data); + +#endif + diff --git a/drivers/gpu/drm/amd/display/dc/irq/irq_service.c b/drivers/gpu/drm/amd/display/dc/irq/irq_service.c new file mode 100644 index 000000000000..fbaa2fc00ddb --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/irq/irq_service.c @@ -0,0 +1,163 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "include/irq_service_interface.h" +#include "include/logger_interface.h" + +#include "dce110/irq_service_dce110.h" + + +#include "dce80/irq_service_dce80.h" + + +#include "reg_helper.h" +#include "irq_service.h" + + + +#define CTX \ + irq_service->ctx + +bool dal_irq_service_construct( + struct irq_service *irq_service, + struct irq_service_init_data *init_data) +{ + if (!init_data || !init_data->ctx) + return false; + + irq_service->ctx = init_data->ctx; + return true; +} + +void dal_irq_service_destroy(struct irq_service **irq_service) +{ + if (!irq_service || !*irq_service) { + BREAK_TO_DEBUGGER(); + return; + } + + dm_free(*irq_service); + + *irq_service = NULL; +} + +const struct irq_source_info *find_irq_source_info( + struct irq_service *irq_service, + enum dc_irq_source source) +{ + if (source > DAL_IRQ_SOURCES_NUMBER || source < DC_IRQ_SOURCE_INVALID) + return NULL; + + return &irq_service->info[source]; +} + +void dal_irq_service_set_generic( + struct irq_service *irq_service, + const struct irq_source_info *info, + bool enable) +{ + uint32_t addr = info->enable_reg; + uint32_t value = dm_read_reg(irq_service->ctx, addr); + + value = (value & ~info->enable_mask) | + (info->enable_value[enable ? 0 : 1] & info->enable_mask); + dm_write_reg(irq_service->ctx, addr, value); +} + +bool dal_irq_service_set( + struct irq_service *irq_service, + enum dc_irq_source source, + bool enable) +{ + const struct irq_source_info *info = + find_irq_source_info(irq_service, source); + + if (!info) { + dm_logger_write( + irq_service->ctx->logger, LOG_ERROR, + "%s: cannot find irq info table entry for %d\n", + __func__, + source); + return false; + } + + dal_irq_service_ack(irq_service, source); + + if (info->funcs->set) + return info->funcs->set(irq_service, info, enable); + + dal_irq_service_set_generic(irq_service, info, enable); + + return true; +} + +void dal_irq_service_ack_generic( + struct irq_service *irq_service, + const struct irq_source_info *info) +{ + uint32_t addr = info->ack_reg; + uint32_t value = dm_read_reg(irq_service->ctx, addr); + + value = (value & ~info->ack_mask) | + (info->ack_value & info->ack_mask); + dm_write_reg(irq_service->ctx, addr, value); +} + +bool dal_irq_service_ack( + struct irq_service *irq_service, + enum dc_irq_source source) +{ + const struct irq_source_info *info = + find_irq_source_info(irq_service, source); + + if (!info) { + dm_logger_write( + irq_service->ctx->logger, LOG_ERROR, + "%s: cannot find irq info table entry for %d\n", + __func__, + source); + return false; + } + + if (info->funcs->ack) + return info->funcs->ack(irq_service, info); + + dal_irq_service_ack_generic(irq_service, info); + + return true; +} + +enum dc_irq_source dal_irq_service_to_irq_source( + struct irq_service *irq_service, + uint32_t src_id, + uint32_t ext_id) +{ + return irq_service->funcs->to_dal_irq_source( + irq_service, + src_id, + ext_id); +} diff --git a/drivers/gpu/drm/amd/display/dc/irq/irq_service.h b/drivers/gpu/drm/amd/display/dc/irq/irq_service.h new file mode 100644 index 000000000000..a2a2d6965c2f --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/irq/irq_service.h @@ -0,0 +1,85 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_IRQ_SERVICE_H__ +#define __DAL_IRQ_SERVICE_H__ + +#include "include/irq_service_interface.h" + +#include "irq_types.h" + +struct irq_service; +struct irq_source_info; + +struct irq_source_info_funcs { + bool (*set)( + struct irq_service *irq_service, + const struct irq_source_info *info, + bool enable); + bool (*ack)( + struct irq_service *irq_service, + const struct irq_source_info *info); +}; + +struct irq_source_info { + uint32_t src_id; + uint32_t ext_id; + uint32_t enable_reg; + uint32_t enable_mask; + uint32_t enable_value[2]; + uint32_t ack_reg; + uint32_t ack_mask; + uint32_t ack_value; + uint32_t status_reg; + const struct irq_source_info_funcs *funcs; +}; + +struct irq_service_funcs { + enum dc_irq_source (*to_dal_irq_source)( + struct irq_service *irq_service, + uint32_t src_id, + uint32_t ext_id); +}; + +struct irq_service { + struct dc_context *ctx; + const struct irq_source_info *info; + const struct irq_service_funcs *funcs; +}; + +bool dal_irq_service_construct( + struct irq_service *irq_service, + struct irq_service_init_data *init_data); + +void dal_irq_service_ack_generic( + struct irq_service *irq_service, + const struct irq_source_info *info); + +void dal_irq_service_set_generic( + struct irq_service *irq_service, + const struct irq_source_info *info, + bool enable); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/irq_types.h b/drivers/gpu/drm/amd/display/dc/irq_types.h new file mode 100644 index 000000000000..e4b4b99a86fc --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/irq_types.h @@ -0,0 +1,185 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_IRQ_TYPES_H__ +#define __DAL_IRQ_TYPES_H__ + +struct dc_context; + +typedef void (*interrupt_handler)(void *); + +typedef void *irq_handler_idx; +#define DAL_INVALID_IRQ_HANDLER_IDX NULL + +/* The order of the IRQ sources is important and MUST match the one's +of base driver */ +enum dc_irq_source { + /* Use as mask to specify invalid irq source */ + DC_IRQ_SOURCE_INVALID = 0, + + DC_IRQ_SOURCE_HPD1, + DC_IRQ_SOURCE_HPD2, + DC_IRQ_SOURCE_HPD3, + DC_IRQ_SOURCE_HPD4, + DC_IRQ_SOURCE_HPD5, + DC_IRQ_SOURCE_HPD6, + + DC_IRQ_SOURCE_HPD1RX, + DC_IRQ_SOURCE_HPD2RX, + DC_IRQ_SOURCE_HPD3RX, + DC_IRQ_SOURCE_HPD4RX, + DC_IRQ_SOURCE_HPD5RX, + DC_IRQ_SOURCE_HPD6RX, + + DC_IRQ_SOURCE_I2C_DDC1, + DC_IRQ_SOURCE_I2C_DDC2, + DC_IRQ_SOURCE_I2C_DDC3, + DC_IRQ_SOURCE_I2C_DDC4, + DC_IRQ_SOURCE_I2C_DDC5, + DC_IRQ_SOURCE_I2C_DDC6, + + DC_IRQ_SOURCE_DPSINK1, + DC_IRQ_SOURCE_DPSINK2, + DC_IRQ_SOURCE_DPSINK3, + DC_IRQ_SOURCE_DPSINK4, + DC_IRQ_SOURCE_DPSINK5, + DC_IRQ_SOURCE_DPSINK6, + + DC_IRQ_SOURCE_TIMER, + + DC_IRQ_SOURCE_PFLIP_FIRST, + DC_IRQ_SOURCE_PFLIP1 = DC_IRQ_SOURCE_PFLIP_FIRST, + DC_IRQ_SOURCE_PFLIP2, + DC_IRQ_SOURCE_PFLIP3, + DC_IRQ_SOURCE_PFLIP4, + DC_IRQ_SOURCE_PFLIP5, + DC_IRQ_SOURCE_PFLIP6, + DC_IRQ_SOURCE_PFLIP_UNDERLAY0, + DC_IRQ_SOURCE_PFLIP_LAST = DC_IRQ_SOURCE_PFLIP_UNDERLAY0, + + DC_IRQ_SOURCE_GPIOPAD0, + DC_IRQ_SOURCE_GPIOPAD1, + DC_IRQ_SOURCE_GPIOPAD2, + DC_IRQ_SOURCE_GPIOPAD3, + DC_IRQ_SOURCE_GPIOPAD4, + DC_IRQ_SOURCE_GPIOPAD5, + DC_IRQ_SOURCE_GPIOPAD6, + DC_IRQ_SOURCE_GPIOPAD7, + DC_IRQ_SOURCE_GPIOPAD8, + DC_IRQ_SOURCE_GPIOPAD9, + DC_IRQ_SOURCE_GPIOPAD10, + DC_IRQ_SOURCE_GPIOPAD11, + DC_IRQ_SOURCE_GPIOPAD12, + DC_IRQ_SOURCE_GPIOPAD13, + DC_IRQ_SOURCE_GPIOPAD14, + DC_IRQ_SOURCE_GPIOPAD15, + DC_IRQ_SOURCE_GPIOPAD16, + DC_IRQ_SOURCE_GPIOPAD17, + DC_IRQ_SOURCE_GPIOPAD18, + DC_IRQ_SOURCE_GPIOPAD19, + DC_IRQ_SOURCE_GPIOPAD20, + DC_IRQ_SOURCE_GPIOPAD21, + DC_IRQ_SOURCE_GPIOPAD22, + DC_IRQ_SOURCE_GPIOPAD23, + DC_IRQ_SOURCE_GPIOPAD24, + DC_IRQ_SOURCE_GPIOPAD25, + DC_IRQ_SOURCE_GPIOPAD26, + DC_IRQ_SOURCE_GPIOPAD27, + DC_IRQ_SOURCE_GPIOPAD28, + DC_IRQ_SOURCE_GPIOPAD29, + DC_IRQ_SOURCE_GPIOPAD30, + + DC_IRQ_SOURCE_DC1UNDERFLOW, + DC_IRQ_SOURCE_DC2UNDERFLOW, + DC_IRQ_SOURCE_DC3UNDERFLOW, + DC_IRQ_SOURCE_DC4UNDERFLOW, + DC_IRQ_SOURCE_DC5UNDERFLOW, + DC_IRQ_SOURCE_DC6UNDERFLOW, + + DC_IRQ_SOURCE_DMCU_SCP, + DC_IRQ_SOURCE_VBIOS_SW, + + DC_IRQ_SOURCE_VUPDATE1, + DC_IRQ_SOURCE_VUPDATE2, + DC_IRQ_SOURCE_VUPDATE3, + DC_IRQ_SOURCE_VUPDATE4, + DC_IRQ_SOURCE_VUPDATE5, + DC_IRQ_SOURCE_VUPDATE6, + + DAL_IRQ_SOURCES_NUMBER +}; + +enum irq_type +{ + IRQ_TYPE_PFLIP = DC_IRQ_SOURCE_PFLIP1, + IRQ_TYPE_VUPDATE = DC_IRQ_SOURCE_VUPDATE1, +}; + +#define DAL_VALID_IRQ_SRC_NUM(src) \ + ((src) <= DAL_IRQ_SOURCES_NUMBER && (src) > DC_IRQ_SOURCE_INVALID) + +/* Number of Page Flip IRQ Sources. */ +#define DAL_PFLIP_IRQ_SRC_NUM \ + (DC_IRQ_SOURCE_PFLIP_LAST - DC_IRQ_SOURCE_PFLIP_FIRST + 1) + +/* the number of contexts may be expanded in the future based on needs */ +enum dc_interrupt_context { + INTERRUPT_LOW_IRQ_CONTEXT = 0, + INTERRUPT_HIGH_IRQ_CONTEXT, + INTERRUPT_CONTEXT_NUMBER +}; + +enum dc_interrupt_porlarity { + INTERRUPT_POLARITY_DEFAULT = 0, + INTERRUPT_POLARITY_LOW = INTERRUPT_POLARITY_DEFAULT, + INTERRUPT_POLARITY_HIGH, + INTERRUPT_POLARITY_BOTH +}; + +#define DC_DECODE_INTERRUPT_POLARITY(int_polarity) \ + (int_polarity == INTERRUPT_POLARITY_LOW) ? "Low" : \ + (int_polarity == INTERRUPT_POLARITY_HIGH) ? "High" : \ + (int_polarity == INTERRUPT_POLARITY_BOTH) ? "Both" : "Invalid" + +struct dc_timer_interrupt_params { + uint32_t micro_sec_interval; + enum dc_interrupt_context int_context; +}; + +struct dc_interrupt_params { + /* The polarity *change* which will trigger an interrupt. + * If 'requested_polarity == INTERRUPT_POLARITY_BOTH', then + * 'current_polarity' must be initialised. */ + enum dc_interrupt_porlarity requested_polarity; + /* If 'requested_polarity == INTERRUPT_POLARITY_BOTH', + * 'current_polarity' should contain the current state, which means + * the interrupt will be triggered when state changes from what is, + * in 'current_polarity'. */ + enum dc_interrupt_porlarity current_polarity; + enum dc_irq_source irq_source; + enum dc_interrupt_context int_context; +}; + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/os_types.h b/drivers/gpu/drm/amd/display/dc/os_types.h new file mode 100644 index 000000000000..459a2741eccb --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/os_types.h @@ -0,0 +1,61 @@ +/* + * Copyright 2012-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef _OS_TYPES_H_ +#define _OS_TYPES_H_ + +#if defined __KERNEL__ + +#include +#include +#include + +#include "cgs_linux.h" + +#if defined(__BIG_ENDIAN) && !defined(BIGENDIAN_CPU) +#define BIGENDIAN_CPU +#elif defined(__LITTLE_ENDIAN) && !defined(LITTLEENDIAN_CPU) +#define LITTLEENDIAN_CPU +#endif + +#undef READ +#undef WRITE +#undef FRAME_SIZE + +#define dm_output_to_console(fmt, ...) DRM_INFO(fmt, ##__VA_ARGS__) + +#define dm_error(fmt, ...) DRM_ERROR(fmt, ##__VA_ARGS__) + +#define dm_debug(fmt, ...) DRM_DEBUG_KMS(fmt, ##__VA_ARGS__) + +#define dm_vlog(fmt, args) vprintk(fmt, args) + +#define dm_min(x, y) min(x, y) +#define dm_max(x, y) max(x, y) + +#endif + + +#endif /* _OS_TYPES_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/virtual/Makefile b/drivers/gpu/drm/amd/display/dc/virtual/Makefile new file mode 100644 index 000000000000..fc0b7318d9cc --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/virtual/Makefile @@ -0,0 +1,9 @@ +# +# Makefile for the virtual sub-component of DAL. +# It provides the control and status of HW CRTC block. + +VIRTUAL = virtual_link_encoder.o virtual_stream_encoder.o + +AMD_DAL_VIRTUAL = $(addprefix $(AMDDALPATH)/dc/virtual/,$(VIRTUAL)) + +AMD_DISPLAY_FILES += $(AMD_DAL_VIRTUAL) diff --git a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c new file mode 100644 index 000000000000..bb4433ff3b6e --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c @@ -0,0 +1,150 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "dm_services_types.h" + +#include "virtual_link_encoder.h" + +#define VIRTUAL_MAX_PIXEL_CLK_IN_KHZ 600000 + +static bool virtual_link_encoder_validate_output_with_stream( + struct link_encoder *enc, + struct pipe_ctx *pipe_ctx) { return true; } + +static void virtual_link_encoder_hw_init(struct link_encoder *enc) {} + +static void virtual_link_encoder_setup( + struct link_encoder *enc, + enum signal_type signal) {} + +static void virtual_link_encoder_enable_tmds_output( + struct link_encoder *enc, + enum clock_source_id clock_source, + enum dc_color_depth color_depth, + bool hdmi, + bool dual_link, + uint32_t pixel_clock) {} + +static void virtual_link_encoder_enable_dp_output( + struct link_encoder *enc, + const struct dc_link_settings *link_settings, + enum clock_source_id clock_source) {} + +static void virtual_link_encoder_enable_dp_mst_output( + struct link_encoder *enc, + const struct dc_link_settings *link_settings, + enum clock_source_id clock_source) {} + +static void virtual_link_encoder_disable_output( + struct link_encoder *link_enc, + enum signal_type signal) {} + +static void virtual_link_encoder_dp_set_lane_settings( + struct link_encoder *enc, + const struct link_training_settings *link_settings) {} + +static void virtual_link_encoder_dp_set_phy_pattern( + struct link_encoder *enc, + const struct encoder_set_dp_phy_pattern_param *param) {} + +static void virtual_link_encoder_update_mst_stream_allocation_table( + struct link_encoder *enc, + const struct link_mst_stream_allocation_table *table) {} + +static void virtual_link_encoder_set_lcd_backlight_level( + struct link_encoder *enc, + uint32_t level) {} + +static void virtual_link_encoder_set_dmcu_backlight_level( + struct link_encoder *enc, + uint32_t level, + uint32_t frame_ramp, + uint32_t controller_id) {} + +static void virtual_link_encoder_edp_backlight_control( + struct link_encoder *enc, + bool enable) {} + +static void virtual_link_encoder_edp_power_control( + struct link_encoder *enc, + bool power_up) {} + +static void virtual_link_encoder_connect_dig_be_to_fe( + struct link_encoder *enc, + enum engine_id engine, + bool connect) {} + +static void virtual_link_encoder_destroy(struct link_encoder **enc) +{ + dm_free(*enc); + *enc = NULL; +} + + +static const struct link_encoder_funcs virtual_lnk_enc_funcs = { + .validate_output_with_stream = + virtual_link_encoder_validate_output_with_stream, + .hw_init = virtual_link_encoder_hw_init, + .setup = virtual_link_encoder_setup, + .enable_tmds_output = virtual_link_encoder_enable_tmds_output, + .enable_dp_output = virtual_link_encoder_enable_dp_output, + .enable_dp_mst_output = virtual_link_encoder_enable_dp_mst_output, + .disable_output = virtual_link_encoder_disable_output, + .dp_set_lane_settings = virtual_link_encoder_dp_set_lane_settings, + .dp_set_phy_pattern = virtual_link_encoder_dp_set_phy_pattern, + .update_mst_stream_allocation_table = + virtual_link_encoder_update_mst_stream_allocation_table, + .set_lcd_backlight_level = virtual_link_encoder_set_lcd_backlight_level, + .set_dmcu_backlight_level = + virtual_link_encoder_set_dmcu_backlight_level, + .backlight_control = virtual_link_encoder_edp_backlight_control, + .power_control = virtual_link_encoder_edp_power_control, + .connect_dig_be_to_fe = virtual_link_encoder_connect_dig_be_to_fe, + .destroy = virtual_link_encoder_destroy +}; + +bool virtual_link_encoder_construct( + struct link_encoder *enc, const struct encoder_init_data *init_data) +{ + enc->funcs = &virtual_lnk_enc_funcs; + enc->ctx = init_data->ctx; + enc->id = init_data->encoder; + + enc->hpd_source = init_data->hpd_source; + enc->connector = init_data->connector; + + enc->transmitter = init_data->transmitter; + + enc->features.max_pixel_clock = VIRTUAL_MAX_PIXEL_CLK_IN_KHZ; + + enc->output_signals = SIGNAL_TYPE_VIRTUAL; + + enc->preferred_engine = ENGINE_ID_VIRTUAL; + + return true; +} + + diff --git a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.h b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.h new file mode 100644 index 000000000000..eb1a94fb8a9b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.h @@ -0,0 +1,34 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_VIRTUAL_LINK_ENCODER_H__ +#define __DC_VIRTUAL_LINK_ENCODER_H__ + +#include "link_encoder.h" + +bool virtual_link_encoder_construct( + struct link_encoder *enc, const struct encoder_init_data *init_data); + +#endif /* __DC_VIRTUAL_LINK_ENCODER_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c new file mode 100644 index 000000000000..8de21d9a8079 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c @@ -0,0 +1,132 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "virtual_stream_encoder.h" + +static void virtual_stream_encoder_dp_set_stream_attribute( + struct stream_encoder *enc, + struct dc_crtc_timing *crtc_timing, + enum dc_color_space output_color_space) {} + +static void virtual_stream_encoder_hdmi_set_stream_attribute( + struct stream_encoder *enc, + struct dc_crtc_timing *crtc_timing, + int actual_pix_clk_khz, + bool enable_audio) {} + +static void virtual_stream_encoder_dvi_set_stream_attribute( + struct stream_encoder *enc, + struct dc_crtc_timing *crtc_timing, + bool is_dual_link) {} + +static void virtual_stream_encoder_set_mst_bandwidth( + struct stream_encoder *enc, + struct fixed31_32 avg_time_slots_per_mtp) {} + +static void virtual_stream_encoder_update_hdmi_info_packets( + struct stream_encoder *enc, + const struct encoder_info_frame *info_frame) {} + +static void virtual_stream_encoder_stop_hdmi_info_packets( + struct stream_encoder *enc) {} + +static void virtual_stream_encoder_update_dp_info_packets( + struct stream_encoder *enc, + const struct encoder_info_frame *info_frame) {} + +static void virtual_stream_encoder_stop_dp_info_packets( + struct stream_encoder *enc) {} + +static void virtual_stream_encoder_dp_blank( + struct stream_encoder *enc) {} + +static void virtual_stream_encoder_dp_unblank( + struct stream_encoder *enc, + const struct encoder_unblank_param *param) {} + +static void virtual_audio_mute_control( + struct stream_encoder *enc, + bool mute) {} + +static const struct stream_encoder_funcs virtual_str_enc_funcs = { + .dp_set_stream_attribute = + virtual_stream_encoder_dp_set_stream_attribute, + .hdmi_set_stream_attribute = + virtual_stream_encoder_hdmi_set_stream_attribute, + .dvi_set_stream_attribute = + virtual_stream_encoder_dvi_set_stream_attribute, + .set_mst_bandwidth = + virtual_stream_encoder_set_mst_bandwidth, + .update_hdmi_info_packets = + virtual_stream_encoder_update_hdmi_info_packets, + .stop_hdmi_info_packets = + virtual_stream_encoder_stop_hdmi_info_packets, + .update_dp_info_packets = + virtual_stream_encoder_update_dp_info_packets, + .stop_dp_info_packets = + virtual_stream_encoder_stop_dp_info_packets, + .dp_blank = + virtual_stream_encoder_dp_blank, + .dp_unblank = + virtual_stream_encoder_dp_unblank, + + .audio_mute_control = virtual_audio_mute_control, +}; + +bool virtual_stream_encoder_construct( + struct stream_encoder *enc, + struct dc_context *ctx, + struct dc_bios *bp) +{ + if (!enc) + return false; + if (!bp) + return false; + + enc->funcs = &virtual_str_enc_funcs; + enc->ctx = ctx; + enc->id = ENGINE_ID_VIRTUAL; + enc->bp = bp; + + return true; +} + +struct stream_encoder *virtual_stream_encoder_create( + struct dc_context *ctx, struct dc_bios *bp) +{ + struct stream_encoder *enc = dm_alloc(sizeof(*enc)); + + if (!enc) + return NULL; + + if (virtual_stream_encoder_construct(enc, ctx, bp)) + return enc; + + BREAK_TO_DEBUGGER(); + dm_free(enc); + return NULL; +} + diff --git a/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.h new file mode 100644 index 000000000000..bf3422c66976 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.h @@ -0,0 +1,39 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_VIRTUAL_STREAM_ENCODER_H__ +#define __DC_VIRTUAL_STREAM_ENCODER_H__ + +#include "stream_encoder.h" + +struct stream_encoder *virtual_stream_encoder_create( + struct dc_context *ctx, struct dc_bios *bp); + +bool virtual_stream_encoder_construct( + struct stream_encoder *enc, + struct dc_context *ctx, + struct dc_bios *bp); + +#endif /* __DC_VIRTUAL_STREAM_ENCODER_H__ */ diff --git a/drivers/gpu/drm/amd/display/include/asic_capability_interface.h b/drivers/gpu/drm/amd/display/include/asic_capability_interface.h new file mode 100644 index 000000000000..57cc72fdc560 --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/asic_capability_interface.h @@ -0,0 +1,55 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of enc software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and enc permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_ASIC_CAPABILITY_INTERFACE_H__ +#define __DAL_ASIC_CAPABILITY_INTERFACE_H__ + +/* Include */ +#include "include/asic_capability_types.h" + +/* Forward declaration */ +struct hw_asic_id; + +/* ASIC capability */ +struct asic_capability { + struct dc_context *ctx; + struct asic_caps caps; + struct asic_stereo_3d_caps stereo_3d_caps; + struct asic_bugs bugs; + uint32_t data[ASIC_DATA_MAX_NUMBER]; +}; + +/** + * Interfaces + */ + +/* Create and initialize ASIC capability */ +struct asic_capability *dal_asic_capability_create(struct hw_asic_id *init, + struct dc_context *ctx); + +/* Destroy ASIC capability and free memory space */ +void dal_asic_capability_destroy(struct asic_capability **cap); + +#endif /* __DAL_ASIC_CAPABILITY_INTERFACE_H__ */ diff --git a/drivers/gpu/drm/amd/display/include/asic_capability_types.h b/drivers/gpu/drm/amd/display/include/asic_capability_types.h new file mode 100644 index 000000000000..c44dae043599 --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/asic_capability_types.h @@ -0,0 +1,116 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef __DAL_ASIC_CAPABILITY_TYPES_H__ +#define __DAL_ASIC_CAPABILITY_TYPES_H__ + +/* + * ASIC Capabilities + */ +struct asic_caps { + bool CONSUMER_SINGLE_SELECTED_TIMING:1; + bool UNDERSCAN_ADJUST:1; + bool DELTA_SIGMA_SUPPORT:1; + bool PANEL_SELF_REFRESH_SUPPORTED:1; + bool IS_FUSION:1; + bool DP_MST_SUPPORTED:1; + bool UNDERSCAN_FOR_HDMI_ONLY:1; + bool DVI_CLOCK_SHARE_CAPABILITY:1; + bool SUPPORT_CEA861E_FINAL:1; + bool MIRABILIS_SUPPORTED:1; + bool MIRABILIS_ENABLED_BY_DEFAULT:1; + bool DEVICE_TAG_REMAP_SUPPORTED:1; + bool HEADLESS_NO_OPM_SUPPORTED:1; + bool WIRELESS_LIMIT_TO_720P:1; + bool WIRELESS_FULL_TIMING_ADJUSTMENT:1; + bool WIRELESS_TIMING_ADJUSTMENT:1; + bool WIRELESS_COMPRESSED_AUDIO:1; + bool VCE_SUPPORTED:1; + bool HPD_CHECK_FOR_EDID:1; + bool NEED_MC_TUNING:1; + bool SKIP_PSR_WAIT_FOR_PLL_LOCK_BIT:1; + bool DFSBYPASS_DYNAMIC_SUPPORT:1; + bool SUPPORT_8BPP:1; +}; + +/* + * ASIC Stereo 3D Caps + */ +struct asic_stereo_3d_caps { + bool SUPPORTED:1; + bool DISPLAY_BASED_ON_WS:1; + bool HDMI_FRAME_PACK:1; + bool INTERLACE_FRAME_PACK:1; + bool DISPLAYPORT_FRAME_PACK:1; + bool DISPLAYPORT_FRAME_ALT:1; + bool INTERLEAVE:1; +}; + +/* + * ASIC Bugs + */ +struct asic_bugs { + bool MST_SYMBOL_MISALIGNMENT:1; + bool PSR_2X_LANE_GANGING:1; + bool LB_WA_IS_SUPPORTED:1; + bool ROM_REGISTER_ACCESS:1; + bool PSR_WA_OVERSCAN_CRC_ERROR:1; +}; + +/* + * ASIC Data + */ +enum asic_data { + ASIC_DATA_FIRST = 0, + ASIC_DATA_DCE_VERSION = ASIC_DATA_FIRST, + ASIC_DATA_DCE_VERSION_MINOR, + ASIC_DATA_LINEBUFFER_SIZE, + ASIC_DATA_DRAM_BANDWIDTH_EFFICIENCY, + ASIC_DATA_MC_LATENCY, + ASIC_DATA_MC_LATENCY_SLOW, + ASIC_DATA_MEMORYTYPE_MULTIPLIER, + ASIC_DATA_PATH_NUM_PER_DPMST_CONNECTOR, + ASIC_DATA_MAX_UNDERSCAN_PERCENTAGE, + ASIC_DATA_VIEWPORT_PIXEL_GRANULARITY, + ASIC_DATA_MIN_DISPCLK_FOR_UNDERSCAN, + ASIC_DATA_DOWNSCALE_LIMIT, + ASIC_DATA_MAX_NUMBER /* end of enum */ +}; + +/* + * ASIC Feature Flags + */ +struct asic_feature_flags { + union { + uint32_t raw; + struct { + uint32_t LEGACY_CLIENT:1; + uint32_t PACKED_PIXEL_FORMAT:1; + uint32_t WORKSTATION_STEREO:1; + uint32_t WORKSTATION:1; + } bits; + }; +}; + +#endif /* __DAL_ASIC_CAPABILITY_TYPES_H__ */ diff --git a/drivers/gpu/drm/amd/display/include/audio_types.h b/drivers/gpu/drm/amd/display/include/audio_types.h new file mode 100644 index 000000000000..6364fbc24cfe --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/audio_types.h @@ -0,0 +1,106 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __AUDIO_TYPES_H__ +#define __AUDIO_TYPES_H__ + +#include "signal_types.h" + +#define AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS 20 +#define MAX_HW_AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS 18 +#define MULTI_CHANNEL_SPLIT_NO_ASSO_INFO 0xFFFFFFFF + + +struct audio_crtc_info { + uint32_t h_total; + uint32_t h_active; + uint32_t v_active; + uint32_t pixel_repetition; + uint32_t requested_pixel_clock; /* in KHz */ + uint32_t calculated_pixel_clock; /* in KHz */ + uint32_t refresh_rate; + enum dc_color_depth color_depth; + bool interlaced; +}; +struct azalia_clock_info { + uint32_t pixel_clock_in_10khz; + uint32_t audio_dto_phase; + uint32_t audio_dto_module; + uint32_t audio_dto_wall_clock_ratio; +}; + +enum audio_dto_source { + DTO_SOURCE_UNKNOWN = 0, + DTO_SOURCE_ID0, + DTO_SOURCE_ID1, + DTO_SOURCE_ID2, + DTO_SOURCE_ID3, + DTO_SOURCE_ID4, + DTO_SOURCE_ID5 +}; + +/* PLL information required for AZALIA DTO calculation */ + +struct audio_pll_info { + uint32_t dp_dto_source_clock_in_khz; + uint32_t feed_back_divider; + enum audio_dto_source dto_source; + bool ss_enabled; + uint32_t ss_percentage; + uint32_t ss_percentage_divider; +}; + +struct audio_channel_associate_info { + union { + struct { + uint32_t ALL_CHANNEL_FL:4; + uint32_t ALL_CHANNEL_FR:4; + uint32_t ALL_CHANNEL_FC:4; + uint32_t ALL_CHANNEL_Sub:4; + uint32_t ALL_CHANNEL_SL:4; + uint32_t ALL_CHANNEL_SR:4; + uint32_t ALL_CHANNEL_BL:4; + uint32_t ALL_CHANNEL_BR:4; + } bits; + uint32_t u32all; + }; +}; + +struct audio_output { + /* Front DIG id. */ + enum engine_id engine_id; + /* encoder output signal */ + enum signal_type signal; + /* video timing */ + struct audio_crtc_info crtc_info; + /* PLL for audio */ + struct audio_pll_info pll_info; +}; + +enum audio_payload { + CHANNEL_SPLIT_MAPPINGCHANG = 0x9, +}; + +#endif /* __AUDIO_TYPES_H__ */ diff --git a/drivers/gpu/drm/amd/display/include/bios_parser_interface.h b/drivers/gpu/drm/amd/display/include/bios_parser_interface.h new file mode 100644 index 000000000000..d51101c5c6b0 --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/bios_parser_interface.h @@ -0,0 +1,44 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_BIOS_PARSER_INTERFACE_H__ +#define __DAL_BIOS_PARSER_INTERFACE_H__ + +#include "dc_bios_types.h" + +struct bios_parser; + +struct bp_init_data { + struct dc_context *ctx; + uint8_t *bios; +}; + +struct dc_bios *dal_bios_parser_create( + struct bp_init_data *init, + enum dce_version dce_version); + +void dal_bios_parser_destroy(struct dc_bios **dcb); + +#endif /* __DAL_BIOS_PARSER_INTERFACE_H__ */ diff --git a/drivers/gpu/drm/amd/display/include/bios_parser_types.h b/drivers/gpu/drm/amd/display/include/bios_parser_types.h new file mode 100644 index 000000000000..9ab9065735f7 --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/bios_parser_types.h @@ -0,0 +1,338 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_BIOS_PARSER_TYPES_H__ + +#define __DAL_BIOS_PARSER_TYPES_H__ + +#include "dm_services.h" +#include "include/signal_types.h" +#include "include/grph_object_ctrl_defs.h" +#include "include/gpio_types.h" +#include "include/link_service_types.h" + +/* TODO: include signal_types.h and remove this enum */ +enum as_signal_type { + AS_SIGNAL_TYPE_NONE = 0L, /* no signal */ + AS_SIGNAL_TYPE_DVI, + AS_SIGNAL_TYPE_HDMI, + AS_SIGNAL_TYPE_LVDS, + AS_SIGNAL_TYPE_DISPLAY_PORT, + AS_SIGNAL_TYPE_GPU_PLL, + AS_SIGNAL_TYPE_UNKNOWN +}; + +enum bp_result { + BP_RESULT_OK = 0, /* There was no error */ + BP_RESULT_BADINPUT, /*Bad input parameter */ + BP_RESULT_BADBIOSTABLE, /* Bad BIOS table */ + BP_RESULT_UNSUPPORTED, /* BIOS Table is not supported */ + BP_RESULT_NORECORD, /* Record can't be found */ + BP_RESULT_FAILURE +}; + +enum bp_encoder_control_action { + /* direct VBIOS translation! Just to simplify the translation */ + ENCODER_CONTROL_DISABLE = 0, + ENCODER_CONTROL_ENABLE, + ENCODER_CONTROL_SETUP, + ENCODER_CONTROL_INIT +}; + +enum bp_transmitter_control_action { + /* direct VBIOS translation! Just to simplify the translation */ + TRANSMITTER_CONTROL_DISABLE = 0, + TRANSMITTER_CONTROL_ENABLE, + TRANSMITTER_CONTROL_BACKLIGHT_OFF, + TRANSMITTER_CONTROL_BACKLIGHT_ON, + TRANSMITTER_CONTROL_BACKLIGHT_BRIGHTNESS, + TRANSMITTER_CONTROL_LCD_SETF_TEST_START, + TRANSMITTER_CONTROL_LCD_SELF_TEST_STOP, + TRANSMITTER_CONTROL_INIT, + TRANSMITTER_CONTROL_DEACTIVATE, + TRANSMITTER_CONTROL_ACTIAVATE, + TRANSMITTER_CONTROL_SETUP, + TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS, + /* ATOM_TRANSMITTER_ACTION_POWER_ON. This action is for eDP only + * (power up the panel) + */ + TRANSMITTER_CONTROL_POWER_ON, + /* ATOM_TRANSMITTER_ACTION_POWER_OFF. This action is for eDP only + * (power down the panel) + */ + TRANSMITTER_CONTROL_POWER_OFF +}; + +enum bp_external_encoder_control_action { + EXTERNAL_ENCODER_CONTROL_DISABLE = 0, + EXTERNAL_ENCODER_CONTROL_ENABLE = 1, + EXTERNAL_ENCODER_CONTROL_INIT = 0x7, + EXTERNAL_ENCODER_CONTROL_SETUP = 0xf, + EXTERNAL_ENCODER_CONTROL_UNBLANK = 0x10, + EXTERNAL_ENCODER_CONTROL_BLANK = 0x11, +}; + +enum bp_pipe_control_action { + ASIC_PIPE_DISABLE = 0, + ASIC_PIPE_ENABLE, + ASIC_PIPE_INIT +}; + +struct bp_encoder_control { + enum bp_encoder_control_action action; + enum engine_id engine_id; + enum transmitter transmitter; + enum signal_type signal; + enum dc_lane_count lanes_number; + enum dc_color_depth color_depth; + bool enable_dp_audio; + uint32_t pixel_clock; /* khz */ +}; + +struct bp_external_encoder_control { + enum bp_external_encoder_control_action action; + enum engine_id engine_id; + enum dc_link_rate link_rate; + enum dc_lane_count lanes_number; + enum signal_type signal; + enum dc_color_depth color_depth; + bool coherent; + struct graphics_object_id encoder_id; + struct graphics_object_id connector_obj_id; + uint32_t pixel_clock; /* in KHz */ +}; + +struct bp_crtc_source_select { + enum engine_id engine_id; + enum controller_id controller_id; + /* from GPU Tx aka asic_signal */ + enum signal_type signal; + /* sink_signal may differ from asicSignal if Translator encoder */ + enum signal_type sink_signal; + enum display_output_bit_depth display_output_bit_depth; + bool enable_dp_audio; +}; + +struct bp_transmitter_control { + enum bp_transmitter_control_action action; + enum engine_id engine_id; + enum transmitter transmitter; /* PhyId */ + enum dc_lane_count lanes_number; + enum clock_source_id pll_id; /* needed for DCE 4.0 */ + enum signal_type signal; + enum dc_color_depth color_depth; /* not used for DCE6.0 */ + enum hpd_source_id hpd_sel; /* ucHPDSel, used for DCe6.0 */ + struct graphics_object_id connector_obj_id; + /* symClock; in 10kHz, pixel clock, in HDMI deep color mode, it should + * be pixel clock * deep_color_ratio (in KHz) + */ + uint32_t pixel_clock; + uint32_t lane_select; + uint32_t lane_settings; + bool coherent; + bool multi_path; + bool single_pll_mode; +}; + +struct bp_blank_crtc_parameters { + enum controller_id controller_id; + uint32_t black_color_rcr; + uint32_t black_color_gy; + uint32_t black_color_bcb; +}; + +struct bp_hw_crtc_timing_parameters { + enum controller_id controller_id; + /* horizontal part */ + uint32_t h_total; + uint32_t h_addressable; + uint32_t h_overscan_left; + uint32_t h_overscan_right; + uint32_t h_sync_start; + uint32_t h_sync_width; + + /* vertical part */ + uint32_t v_total; + uint32_t v_addressable; + uint32_t v_overscan_top; + uint32_t v_overscan_bottom; + uint32_t v_sync_start; + uint32_t v_sync_width; + + struct timing_flags { + uint32_t INTERLACE:1; + uint32_t PIXEL_REPETITION:4; + uint32_t HSYNC_POSITIVE_POLARITY:1; + uint32_t VSYNC_POSITIVE_POLARITY:1; + uint32_t HORZ_COUNT_BY_TWO:1; + } flags; +}; + +struct bp_hw_crtc_overscan_parameters { + enum controller_id controller_id; + uint32_t h_overscan_left; + uint32_t h_overscan_right; + uint32_t v_overscan_top; + uint32_t v_overscan_bottom; +}; + +struct bp_adjust_pixel_clock_parameters { + /* Input: Signal Type - to be converted to Encoder mode */ + enum signal_type signal_type; + /* Input: Encoder object id */ + struct graphics_object_id encoder_object_id; + /* Input: Pixel Clock (requested Pixel clock based on Video timing + * standard used) in KHz + */ + uint32_t pixel_clock; + /* Output: Adjusted Pixel Clock (after VBIOS exec table) in KHz */ + uint32_t adjusted_pixel_clock; + /* Output: If non-zero, this refDiv value should be used to calculate + * other ppll params */ + uint32_t reference_divider; + /* Output: If non-zero, this postDiv value should be used to calculate + * other ppll params */ + uint32_t pixel_clock_post_divider; + /* Input: Enable spread spectrum */ + bool ss_enable; +}; + +struct bp_pixel_clock_parameters { + enum controller_id controller_id; /* (Which CRTC uses this PLL) */ + enum clock_source_id pll_id; /* Clock Source Id */ + /* signal_type -> Encoder Mode - needed by VBIOS Exec table */ + enum signal_type signal_type; + /* Adjusted Pixel Clock (after VBIOS exec table) + * that becomes Target Pixel Clock (KHz) */ + uint32_t target_pixel_clock; + /* Calculated Reference divider of Display PLL */ + uint32_t reference_divider; + /* Calculated Feedback divider of Display PLL */ + uint32_t feedback_divider; + /* Calculated Fractional Feedback divider of Display PLL */ + uint32_t fractional_feedback_divider; + /* Calculated Pixel Clock Post divider of Display PLL */ + uint32_t pixel_clock_post_divider; + struct graphics_object_id encoder_object_id; /* Encoder object id */ + /* VBIOS returns a fixed display clock when DFS-bypass feature + * is enabled (KHz) */ + uint32_t dfs_bypass_display_clock; + /* color depth to support HDMI deep color */ + enum transmitter_color_depth color_depth; + + struct program_pixel_clock_flags { + uint32_t FORCE_PROGRAMMING_OF_PLL:1; + /* Use Engine Clock as source for Display Clock when + * programming PLL */ + uint32_t USE_E_CLOCK_AS_SOURCE_FOR_D_CLOCK:1; + /* Use external reference clock (refDivSrc for PLL) */ + uint32_t SET_EXTERNAL_REF_DIV_SRC:1; + /* Force program PHY PLL only */ + uint32_t PROGRAM_PHY_PLL_ONLY:1; + /* Support for YUV420 */ + uint32_t SUPPORT_YUV_420:1; + /* Use XTALIN reference clock source */ + uint32_t SET_XTALIN_REF_SRC:1; + /* Use GENLK reference clock source */ + uint32_t SET_GENLOCK_REF_DIV_SRC:1; + } flags; +}; + +struct bp_display_clock_parameters { + uint32_t target_display_clock; /* KHz */ + /* Actual Display Clock set due to clock divider granularity KHz */ + uint32_t actual_display_clock; + /* Actual Post Divider ID used to generate the actual clock */ + uint32_t actual_post_divider_id; +}; + +enum bp_dce_clock_type { + DCECLOCK_TYPE_DISPLAY_CLOCK = 0, + DCECLOCK_TYPE_DPREFCLK = 1 +}; + +/* DCE Clock Parameters structure for SetDceClock Exec command table */ +struct bp_set_dce_clock_parameters { + enum clock_source_id pll_id; /* Clock Source Id */ + /* Display clock or DPREFCLK value */ + uint32_t target_clock_frequency; + /* Clock to set: =0: DISPCLK =1: DPREFCLK =2: PIXCLK */ + enum bp_dce_clock_type clock_type; + + struct set_dce_clock_flags { + uint32_t USE_GENERICA_AS_SOURCE_FOR_DPREFCLK:1; + /* Use XTALIN reference clock source */ + uint32_t USE_XTALIN_AS_SOURCE_FOR_DPREFCLK:1; + /* Use PCIE reference clock source */ + uint32_t USE_PCIE_AS_SOURCE_FOR_DPREFCLK:1; + /* Use GENLK reference clock source */ + uint32_t USE_GENLOCK_AS_SOURCE_FOR_DPREFCLK:1; + } flags; +}; + +struct spread_spectrum_flags { + /* 1 = Center Spread; 0 = down spread */ + uint32_t CENTER_SPREAD:1; + /* 1 = external; 0 = internal */ + uint32_t EXTERNAL_SS:1; + /* 1 = delta-sigma type parameter; 0 = ver1 */ + uint32_t DS_TYPE:1; +}; + +struct bp_spread_spectrum_parameters { + enum clock_source_id pll_id; + uint32_t percentage; + uint32_t ds_frac_amount; + + union { + struct { + uint32_t step; + uint32_t delay; + uint32_t range; /* In Hz unit */ + } ver1; + struct { + uint32_t feedback_amount; + uint32_t nfrac_amount; + uint32_t ds_frac_size; + } ds; + }; + + struct spread_spectrum_flags flags; +}; + +struct bp_encoder_cap_info { + uint32_t DP_HBR2_CAP:1; + uint32_t DP_HBR2_EN:1; + uint32_t DP_HBR3_EN:1; + uint32_t HDMI_6GB_EN:1; + uint32_t RESERVED:30; +}; + +struct bp_gpio_cntl_info { + uint32_t id; + enum gpio_pin_output_state state; +}; + +#endif /*__DAL_BIOS_PARSER_TYPES_H__ */ diff --git a/drivers/gpu/drm/amd/display/include/dal_asic_id.h b/drivers/gpu/drm/amd/display/include/dal_asic_id.h new file mode 100644 index 000000000000..119297e3bdc0 --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/dal_asic_id.h @@ -0,0 +1,125 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_ASIC_ID_H__ +#define __DAL_ASIC_ID_H__ + +/* + * ASIC internal revision ID + */ + +/* DCE80 (based on ci_id.h in Perforce) */ +#define CI_BONAIRE_M_A0 0x14 +#define CI_BONAIRE_M_A1 0x15 +#define CI_HAWAII_P_A0 0x28 + +#define CI_UNKNOWN 0xFF + +#define ASIC_REV_IS_BONAIRE_M(rev) \ + ((rev >= CI_BONAIRE_M_A0) && (rev < CI_HAWAII_P_A0)) + +#define ASIC_REV_IS_HAWAII_P(rev) \ + (rev >= CI_HAWAII_P_A0) + +/* KV1 with Spectre GFX core, 8-8-1-2 (CU-Pix-Primitive-RB) */ +#define KV_SPECTRE_A0 0x01 + +/* KV2 with Spooky GFX core, including downgraded from Spectre core, + * 3-4-1-1 (CU-Pix-Primitive-RB) */ +#define KV_SPOOKY_A0 0x41 + +/* KB with Kalindi GFX core, 2-4-1-1 (CU-Pix-Primitive-RB) */ +#define KB_KALINDI_A0 0x81 + +/* KB with Kalindi GFX core, 2-4-1-1 (CU-Pix-Primitive-RB) */ +#define KB_KALINDI_A1 0x82 + +/* BV with Kalindi GFX core, 2-4-1-1 (CU-Pix-Primitive-RB) */ +#define BV_KALINDI_A2 0x85 + +/* ML with Godavari GFX core, 2-4-1-1 (CU-Pix-Primitive-RB) */ +#define ML_GODAVARI_A0 0xA1 + +/* ML with Godavari GFX core, 2-4-1-1 (CU-Pix-Primitive-RB) */ +#define ML_GODAVARI_A1 0xA2 + +#define KV_UNKNOWN 0xFF + +#define ASIC_REV_IS_KALINDI(rev) \ + ((rev >= KB_KALINDI_A0) && (rev < KV_UNKNOWN)) + +#define ASIC_REV_IS_BHAVANI(rev) \ + ((rev >= BV_KALINDI_A2) && (rev < ML_GODAVARI_A0)) + +#define ASIC_REV_IS_GODAVARI(rev) \ + ((rev >= ML_GODAVARI_A0) && (rev < KV_UNKNOWN)) + +/* VI Family */ +/* DCE10 */ +#define VI_TONGA_P_A0 20 +#define VI_TONGA_P_A1 21 +#define VI_FIJI_P_A0 60 + +/* DCE112 */ +#define VI_POLARIS10_P_A0 80 +#define VI_POLARIS11_M_A0 90 + +#define VI_UNKNOWN 0xFF + +#define ASIC_REV_IS_TONGA_P(eChipRev) ((eChipRev >= VI_TONGA_P_A0) && \ + (eChipRev < 40)) +#define ASIC_REV_IS_FIJI_P(eChipRev) ((eChipRev >= VI_FIJI_P_A0) && \ + (eChipRev < 80)) + +#define ASIC_REV_IS_POLARIS10_P(eChipRev) ((eChipRev >= VI_POLARIS10_P_A0) && \ + (eChipRev < VI_POLARIS11_M_A0)) +#define ASIC_REV_IS_POLARIS11_M(eChipRev) (eChipRev >= VI_POLARIS11_M_A0) + +/* DCE11 */ +#define CZ_CARRIZO_A0 0x01 + +#define STONEY_A0 0x61 +#define CZ_UNKNOWN 0xFF + +#define ASIC_REV_IS_STONEY(rev) \ + ((rev >= STONEY_A0) && (rev < CZ_UNKNOWN)) + +/* + * ASIC chip ID + */ +/* DCE80 */ +#define DEVICE_ID_KALINDI_9834 0x9834 +#define DEVICE_ID_TEMASH_9839 0x9839 +#define DEVICE_ID_TEMASH_983D 0x983D + +/* Asic Family IDs for different asic family. */ +#define FAMILY_CI 120 /* Sea Islands: Hawaii (P), Bonaire (M) */ +#define FAMILY_KV 125 /* Fusion => Kaveri: Spectre, Spooky; Kabini: Kalindi */ +#define FAMILY_VI 130 /* Volcanic Islands: Iceland (V), Tonga (M) */ +#define FAMILY_CZ 135 /* Carrizo */ + +#define FAMILY_UNKNOWN 0xFF + +#endif /* __DAL_ASIC_ID_H__ */ diff --git a/drivers/gpu/drm/amd/display/include/dal_register_logger.h b/drivers/gpu/drm/amd/display/include/dal_register_logger.h new file mode 100644 index 000000000000..00dfcd70cc37 --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/dal_register_logger.h @@ -0,0 +1,42 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_REGISTER_LOGGER__ +#define __DAL_REGISTER_LOGGER__ + +/**************** + * API functions + ***************/ + +/* dal_reg_logger_push - begin Register Logging */ +void dal_reg_logger_push(const char *caller_func); +/* dal_reg_logger_pop - stop Register Logging */ +void dal_reg_logger_pop(void); + +/* for internal use of the Logger only */ +void dal_reg_logger_rw_count_increment(void); +bool dal_reg_logger_should_dump_register(void); + +#endif /* __DAL_REGISTER_LOGGER__ */ diff --git a/drivers/gpu/drm/amd/display/include/dal_types.h b/drivers/gpu/drm/amd/display/include/dal_types.h new file mode 100644 index 000000000000..ada5b19e85eb --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/dal_types.h @@ -0,0 +1,44 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_TYPES_H__ +#define __DAL_TYPES_H__ + +#include "signal_types.h" +#include "dc_types.h" + +struct dal_logger; +struct dc_bios; + +enum dce_version { + DCE_VERSION_UNKNOWN = (-1), + DCE_VERSION_8_0, + DCE_VERSION_10_0, + DCE_VERSION_11_0, + DCE_VERSION_11_2, + DCE_VERSION_MAX, +}; + +#endif /* __DAL_TYPES_H__ */ diff --git a/drivers/gpu/drm/amd/display/include/ddc_service_types.h b/drivers/gpu/drm/amd/display/include/ddc_service_types.h new file mode 100644 index 000000000000..0a6ba91e3eba --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/ddc_service_types.h @@ -0,0 +1,189 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef __DAL_DDC_SERVICE_TYPES_H__ +#define __DAL_DDC_SERVICE_TYPES_H__ + +#define DP_BRANCH_DEVICE_ID_1 0x0010FA +#define DP_BRANCH_DEVICE_ID_2 0x0022B9 +#define DP_SINK_DEVICE_ID_1 0x4CE000 +#define DP_BRANCH_DEVICE_ID_3 0x00001A +#define DP_BRANCH_DEVICE_ID_4 0x0080e1 +#define DP_BRANCH_DEVICE_ID_5 0x006037 +#define DP_SINK_DEVICE_ID_2 0x001CF8 + + +enum ddc_result { + DDC_RESULT_UNKNOWN = 0, + DDC_RESULT_SUCESSFULL, + DDC_RESULT_FAILED_CHANNEL_BUSY, + DDC_RESULT_FAILED_TIMEOUT, + DDC_RESULT_FAILED_PROTOCOL_ERROR, + DDC_RESULT_FAILED_NACK, + DDC_RESULT_FAILED_INCOMPLETE, + DDC_RESULT_FAILED_OPERATION, + DDC_RESULT_FAILED_INVALID_OPERATION, + DDC_RESULT_FAILED_BUFFER_OVERFLOW +}; + +enum ddc_service_type { + DDC_SERVICE_TYPE_CONNECTOR, + DDC_SERVICE_TYPE_DISPLAY_PORT_MST, +}; + +enum dcs_dpcd_revision { + DCS_DPCD_REV_10 = 0x10, + DCS_DPCD_REV_11 = 0x11, + DCS_DPCD_REV_12 = 0x12 +}; + +/** + * display sink capability + */ +struct display_sink_capability { + /* dongle type (DP converter, CV smart dongle) */ + enum display_dongle_type dongle_type; + + /********************************************************** + capabilities going INTO SINK DEVICE (stream capabilities) + **********************************************************/ + /* Dongle's downstream count. */ + uint32_t downstrm_sink_count; + /* Is dongle's downstream count info field (downstrm_sink_count) + * valid. */ + bool downstrm_sink_count_valid; + + /* Maximum additional audio delay in microsecond (us) */ + uint32_t additional_audio_delay; + /* Audio latency value in microsecond (us) */ + uint32_t audio_latency; + /* Interlace video latency value in microsecond (us) */ + uint32_t video_latency_interlace; + /* Progressive video latency value in microsecond (us) */ + uint32_t video_latency_progressive; + /* Dongle caps: Maximum pixel clock supported over dongle for HDMI */ + uint32_t max_hdmi_pixel_clock; + /* Dongle caps: Maximum deep color supported over dongle for HDMI */ + enum dc_color_depth max_hdmi_deep_color; + + /************************************************************ + capabilities going OUT OF SOURCE DEVICE (link capabilities) + ************************************************************/ + /* support for Spread Spectrum(SS) */ + bool ss_supported; + /* DP link settings (laneCount, linkRate, Spread) */ + uint32_t dp_link_lane_count; + uint32_t dp_link_rate; + uint32_t dp_link_spead; + + enum dcs_dpcd_revision dpcd_revision; + /* If dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER, + indicates 'Frame Sequential-to-lllFrame Pack' conversion capability.*/ + bool is_dp_hdmi_s3d_converter; + /* to check if we have queried the display capability + * for eDP panel already. */ + bool is_edp_sink_cap_valid; + + enum ddc_transaction_type transaction_type; + enum signal_type signal; +}; + +struct av_sync_data { + uint8_t av_granularity;/* DPCD 00023h */ + uint8_t aud_dec_lat1;/* DPCD 00024h */ + uint8_t aud_dec_lat2;/* DPCD 00025h */ + uint8_t aud_pp_lat1;/* DPCD 00026h */ + uint8_t aud_pp_lat2;/* DPCD 00027h */ + uint8_t vid_inter_lat;/* DPCD 00028h */ + uint8_t vid_prog_lat;/* DPCD 00029h */ + uint8_t aud_del_ins1;/* DPCD 0002Bh */ + uint8_t aud_del_ins2;/* DPCD 0002Ch */ + uint8_t aud_del_ins3;/* DPCD 0002Dh */ +}; + +/** EDID retrieval related constants, also used by MstMgr **/ + +#define DDC_EDID_SEGMENT_SIZE 256 +#define DDC_EDID_BLOCK_SIZE 128 +#define DDC_EDID_BLOCKS_PER_SEGMENT \ + (DDC_EDID_SEGMENT_SIZE / DDC_EDID_BLOCK_SIZE) + +#define DDC_EDID_EXT_COUNT_OFFSET 0x7E + +#define DDC_EDID_ADDRESS_START 0x50 +#define DDC_EDID_ADDRESS_END 0x52 +#define DDC_EDID_SEGMENT_ADDRESS 0x30 + +/* signatures for Edid 1x */ +#define DDC_EDID1X_VENDORID_SIGNATURE_OFFSET 8 +#define DDC_EDID1X_VENDORID_SIGNATURE_LEN 4 +#define DDC_EDID1X_EXT_CNT_AND_CHECKSUM_OFFSET 126 +#define DDC_EDID1X_EXT_CNT_AND_CHECKSUM_LEN 2 +#define DDC_EDID1X_CHECKSUM_OFFSET 127 +/* signatures for Edid 20*/ +#define DDC_EDID_20_SIGNATURE_OFFSET 0 +#define DDC_EDID_20_SIGNATURE 0x20 + +#define DDC_EDID20_VENDORID_SIGNATURE_OFFSET 1 +#define DDC_EDID20_VENDORID_SIGNATURE_LEN 4 +#define DDC_EDID20_CHECKSUM_OFFSET 255 +#define DDC_EDID20_CHECKSUM_LEN 1 + +/*DP to VGA converter*/ +static const uint8_t DP_VGA_CONVERTER_ID_1[] = "mVGAa"; +/*DP to Dual link DVI converter*/ +static const uint8_t DP_DVI_CONVERTER_ID_1[] = "m2DVIa"; +/*Travis*/ +static const uint8_t DP_VGA_LVDS_CONVERTER_ID_2[] = "sivarT"; +/*Nutmeg*/ +static const uint8_t DP_VGA_LVDS_CONVERTER_ID_3[] = "dnomlA"; +/*DP to VGA converter*/ +static const uint8_t DP_VGA_CONVERTER_ID_4[] = "DpVga"; +/*DP to Dual link DVI converter*/ +static const uint8_t DP_DVI_CONVERTER_ID_4[] = "m2DVIa"; +/*DP to Dual link DVI converter 2*/ +static const uint8_t DP_DVI_CONVERTER_ID_42[] = "v2DVIa"; + +static const uint8_t DP_SINK_DEV_STRING_ID2_REV0[] = "\0\0\0\0\0\0"; + +/* Identifies second generation PSR TCON from Parade: Device ID string: + * yy-xx-**-**-**-** + */ +/* xx - Hw ID high byte */ +static const uint32_t DP_SINK_DEV_STRING_ID2_REV1_HW_ID_HIGH_BYTE = + 0x06; + +/* yy - HW ID low byte, the same silicon has several package/feature flavors */ +static const uint32_t DP_SINK_DEV_STRING_ID2_REV1_HW_ID_LOW_BYTE1 = + 0x61; +static const uint32_t DP_SINK_DEV_STRING_ID2_REV1_HW_ID_LOW_BYTE2 = + 0x62; +static const uint32_t DP_SINK_DEV_STRING_ID2_REV1_HW_ID_LOW_BYTE3 = + 0x63; +static const uint32_t DP_SINK_DEV_STRING_ID2_REV1_HW_ID_LOW_BYTE4 = + 0x72; +static const uint32_t DP_SINK_DEV_STRING_ID2_REV1_HW_ID_LOW_BYTE5 = + 0x73; + +#endif /* __DAL_DDC_SERVICE_TYPES_H__ */ diff --git a/drivers/gpu/drm/amd/display/include/display_clock_interface.h b/drivers/gpu/drm/amd/display/include/display_clock_interface.h new file mode 100644 index 000000000000..2006fa21f54c --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/display_clock_interface.h @@ -0,0 +1,175 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DISPLAY_CLOCK_INTERFACE_H__ +#define __DISPLAY_CLOCK_INTERFACE_H__ + +#include "hw_sequencer_types.h" +#include "grph_object_defs.h" +#include "signal_types.h" + +/* Timing related information*/ +struct dc_timing_params { + uint32_t INTERLACED:1; + uint32_t HCOUNT_BY_TWO:1; + uint32_t PIXEL_REPETITION:4; /*< values 1 to 10 supported*/ + uint32_t PREFETCH:1; + + uint32_t h_total; + uint32_t h_addressable; + uint32_t h_sync_width; +}; + +/* Scaling related information*/ +struct dc_scaling_params { + uint32_t h_overscan_right; + uint32_t h_overscan_left; + uint32_t h_taps; + uint32_t v_taps; +}; + +/* VScalerEfficiency */ +enum v_scaler_efficiency { + V_SCALER_EFFICIENCY_LB36BPP = 0, + V_SCALER_EFFICIENCY_LB30BPP = 1, + V_SCALER_EFFICIENCY_LB24BPP = 2, + V_SCALER_EFFICIENCY_LB18BPP = 3 +}; + +/* Parameters required for minimum Engine + * and minimum Display clock calculations*/ +struct min_clock_params { + uint32_t id; + uint32_t requested_pixel_clock; /* in KHz */ + uint32_t actual_pixel_clock; /* in KHz */ + struct view source_view; + struct view dest_view; + struct dc_timing_params timing_info; + struct dc_scaling_params scaling_info; + enum signal_type signal_type; + enum dc_color_depth deep_color_depth; + enum v_scaler_efficiency scaler_efficiency; + bool line_buffer_prefetch_enabled; +}; + +/* Result of Minimum System and Display clock calculations. + * Minimum System clock and Display clock, source and path to be used + * for Display clock*/ +struct minimum_clocks_calculation_result { + uint32_t min_sclk_khz; + uint32_t min_dclk_khz; + uint32_t min_mclk_khz; + uint32_t min_deep_sleep_sclk; +}; + +/* Enumeration of all clocks states */ +enum clocks_state { + CLOCKS_STATE_INVALID = 0, + CLOCKS_STATE_ULTRA_LOW, + CLOCKS_STATE_LOW, + CLOCKS_STATE_NOMINAL, + CLOCKS_STATE_PERFORMANCE, + /* Starting from DCE11, Max 8 level DPM state supported */ + CLOCKS_DPM_STATE_LEVEL_INVALID = CLOCKS_STATE_INVALID, + CLOCKS_DPM_STATE_LEVEL_0 = CLOCKS_STATE_ULTRA_LOW, + CLOCKS_DPM_STATE_LEVEL_1 = CLOCKS_STATE_LOW, + CLOCKS_DPM_STATE_LEVEL_2 = CLOCKS_STATE_NOMINAL, + CLOCKS_DPM_STATE_LEVEL_3 = CLOCKS_STATE_PERFORMANCE, + CLOCKS_DPM_STATE_LEVEL_4 = CLOCKS_DPM_STATE_LEVEL_3 + 1, + CLOCKS_DPM_STATE_LEVEL_5 = CLOCKS_DPM_STATE_LEVEL_4 + 1, + CLOCKS_DPM_STATE_LEVEL_6 = CLOCKS_DPM_STATE_LEVEL_5 + 1, + CLOCKS_DPM_STATE_LEVEL_7 = CLOCKS_DPM_STATE_LEVEL_6 + 1, +}; + +/* Structure containing all state-dependent clocks + * (dependent on "enum clocks_state") */ +struct state_dependent_clocks { + uint32_t display_clk_khz; + uint32_t pixel_clk_khz; +}; + +struct display_clock_state { + uint32_t DFS_BYPASS_ACTIVE:1; +}; + +struct display_clock; + +struct display_clock *dal_display_clock_dce112_create( + struct dc_context *ctx); + +struct display_clock *dal_display_clock_dce110_create( + struct dc_context *ctx); + +struct display_clock *dal_display_clock_dce80_create( + struct dc_context *ctx); + +void dal_display_clock_destroy(struct display_clock **to_destroy); +bool dal_display_clock_validate( + struct display_clock *disp_clk, + struct min_clock_params *params); +uint32_t dal_display_clock_calculate_min_clock( + struct display_clock *disp_clk, + uint32_t path_num, + struct min_clock_params *params); +uint32_t dal_display_clock_get_validation_clock(struct display_clock *disp_clk); +void dal_display_clock_set_clock( + struct display_clock *disp_clk, + uint32_t requested_clock_khz); +uint32_t dal_display_clock_get_clock(struct display_clock *disp_clk); +bool dal_display_clock_get_min_clocks_state( + struct display_clock *disp_clk, + enum clocks_state *clocks_state); +bool dal_display_clock_get_required_clocks_state( + struct display_clock *disp_clk, + struct state_dependent_clocks *req_clocks, + enum clocks_state *clocks_state); +bool dal_display_clock_set_min_clocks_state( + struct display_clock *disp_clk, + enum clocks_state clocks_state); +uint32_t dal_display_clock_get_dp_ref_clk_frequency( + struct display_clock *disp_clk); +/*the second parameter of "switchreferenceclock" is + * a dummy argument for all pre dce 6.0 versions*/ +void dal_display_clock_switch_reference_clock( + struct display_clock *disp_clk, + bool use_external_ref_clk, + uint32_t requested_clock_khz); +void dal_display_clock_set_dp_ref_clock_source( + struct display_clock *disp_clk, + enum clock_source_id clk_src); +void dal_display_clock_store_max_clocks_state( + struct display_clock *disp_clk, + enum clocks_state max_clocks_state); +void dal_display_clock_set_clock_state( + struct display_clock *disp_clk, + struct display_clock_state clk_state); +struct display_clock_state dal_display_clock_get_clock_state( + struct display_clock *disp_clk); +uint32_t dal_display_clock_get_dfs_bypass_threshold( + struct display_clock *disp_clk); +void dal_display_clock_invalid_clock_state( + struct display_clock *disp_clk); + +#endif /* __DISPLAY_CLOCK_INTERFACE_H__ */ diff --git a/drivers/gpu/drm/amd/display/include/dpcd_defs.h b/drivers/gpu/drm/amd/display/include/dpcd_defs.h new file mode 100644 index 000000000000..fbb2729148df --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/dpcd_defs.h @@ -0,0 +1,742 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_DPCD_DEFS_H__ +#define __DAL_DPCD_DEFS_H__ + +enum dpcd_address { +/* addresses marked with 1.2 are only defined since DP 1.2 spec */ + + /* Reciever Capability Field */ + DPCD_ADDRESS_DPCD_REV = 0x00000, + DPCD_ADDRESS_MAX_LINK_RATE = 0x00001, + DPCD_ADDRESS_MAX_LANE_COUNT = 0x00002, + DPCD_ADDRESS_MAX_DOWNSPREAD = 0x00003, + DPCD_ADDRESS_NORP = 0x00004, + DPCD_ADDRESS_DOWNSTREAM_PORT_PRESENT = 0x00005, + DPCD_ADDRESS_MAIN_LINK_CHANNEL_CODING = 0x00006, + DPCD_ADDRESS_DOWNSTREAM_PORT_COUNT = 0x00007, + DPCD_ADDRESS_RECEIVE_PORT0_CAP0 = 0x00008, + DPCD_ADDRESS_RECEIVE_PORT0_CAP1 = 0x00009, + DPCD_ADDRESS_RECEIVE_PORT1_CAP0 = 0x0000A, + DPCD_ADDRESS_RECEIVE_PORT1_CAP1 = 0x0000B, + + DPCD_ADDRESS_I2C_SPEED_CNTL_CAP = 0x0000C,/*1.2*/ + DPCD_ADDRESS_EDP_CONFIG_CAP = 0x0000D,/*1.2*/ + DPCD_ADDRESS_TRAINING_AUX_RD_INTERVAL = 0x000E,/*1.2*/ + + DPCD_ADDRESS_MSTM_CAP = 0x00021,/*1.2*/ + + /* Audio Video Sync Data Feild */ + DPCD_ADDRESS_AV_GRANULARITY = 0x0023, + DPCD_ADDRESS_AUDIO_DECODE_LATENCY1 = 0x0024, + DPCD_ADDRESS_AUDIO_DECODE_LATENCY2 = 0x0025, + DPCD_ADDRESS_AUDIO_POSTPROCESSING_LATENCY1 = 0x0026, + DPCD_ADDRESS_AUDIO_POSTPROCESSING_LATENCY2 = 0x0027, + DPCD_ADDRESS_VIDEO_INTERLACED_LATENCY = 0x0028, + DPCD_ADDRESS_VIDEO_PROGRESSIVE_LATENCY = 0x0029, + DPCD_ADDRESS_AUDIO_DELAY_INSERT1 = 0x0002B, + DPCD_ADDRESS_AUDIO_DELAY_INSERT2 = 0x0002C, + DPCD_ADDRESS_AUDIO_DELAY_INSERT3 = 0x0002D, + + /* Audio capability */ + DPCD_ADDRESS_NUM_OF_AUDIO_ENDPOINTS = 0x00022, + + DPCD_ADDRESS_GUID_START = 0x00030,/*1.2*/ + DPCD_ADDRESS_GUID_END = 0x0003f,/*1.2*/ + + DPCD_ADDRESS_PSR_SUPPORT_VER = 0x00070, + DPCD_ADDRESS_PSR_CAPABILITY = 0x00071, + + DPCD_ADDRESS_DWN_STRM_PORT0_CAPS = 0x00080,/*1.2a*/ + + /* Link Configuration Field */ + DPCD_ADDRESS_LINK_BW_SET = 0x00100, + DPCD_ADDRESS_LANE_COUNT_SET = 0x00101, + DPCD_ADDRESS_TRAINING_PATTERN_SET = 0x00102, + DPCD_ADDRESS_LANE0_SET = 0x00103, + DPCD_ADDRESS_LANE1_SET = 0x00104, + DPCD_ADDRESS_LANE2_SET = 0x00105, + DPCD_ADDRESS_LANE3_SET = 0x00106, + DPCD_ADDRESS_DOWNSPREAD_CNTL = 0x00107, + DPCD_ADDRESS_I2C_SPEED_CNTL = 0x00109,/*1.2*/ + + DPCD_ADDRESS_EDP_CONFIG_SET = 0x0010A, + DPCD_ADDRESS_LINK_QUAL_LANE0_SET = 0x0010B, + DPCD_ADDRESS_LINK_QUAL_LANE1_SET = 0x0010C, + DPCD_ADDRESS_LINK_QUAL_LANE2_SET = 0x0010D, + DPCD_ADDRESS_LINK_QUAL_LANE3_SET = 0x0010E, + + DPCD_ADDRESS_LANE0_SET2 = 0x0010F,/*1.2*/ + DPCD_ADDRESS_LANE2_SET2 = 0x00110,/*1.2*/ + + DPCD_ADDRESS_MSTM_CNTL = 0x00111,/*1.2*/ + + DPCD_ADDRESS_PSR_ENABLE_CFG = 0x0170, + + /* Payload Table Configuration Field 1.2 */ + DPCD_ADDRESS_PAYLOAD_ALLOCATE_SET = 0x001C0, + DPCD_ADDRESS_PAYLOAD_ALLOCATE_START_TIMESLOT = 0x001C1, + DPCD_ADDRESS_PAYLOAD_ALLOCATE_TIMESLOT_COUNT = 0x001C2, + + DPCD_ADDRESS_SINK_COUNT = 0x0200, + DPCD_ADDRESS_DEVICE_SERVICE_IRQ_VECTOR = 0x0201, + + /* Link / Sink Status Field */ + DPCD_ADDRESS_LANE_01_STATUS = 0x00202, + DPCD_ADDRESS_LANE_23_STATUS = 0x00203, + DPCD_ADDRESS_LANE_ALIGN_STATUS_UPDATED = 0x0204, + DPCD_ADDRESS_SINK_STATUS = 0x0205, + + /* Adjust Request Field */ + DPCD_ADDRESS_ADJUST_REQUEST_LANE0_1 = 0x0206, + DPCD_ADDRESS_ADJUST_REQUEST_LANE2_3 = 0x0207, + DPCD_ADDRESS_ADJUST_REQUEST_POST_CURSOR2 = 0x020C, + + /* Test Request Field */ + DPCD_ADDRESS_TEST_REQUEST = 0x0218, + DPCD_ADDRESS_TEST_LINK_RATE = 0x0219, + DPCD_ADDRESS_TEST_LANE_COUNT = 0x0220, + DPCD_ADDRESS_TEST_PATTERN = 0x0221, + DPCD_ADDRESS_TEST_MISC1 = 0x0232, + + /* Phy Test Pattern Field */ + DPCD_ADDRESS_TEST_PHY_PATTERN = 0x0248, + DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_7_0 = 0x0250, + DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_15_8 = 0x0251, + DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_23_16 = 0x0252, + DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_31_24 = 0x0253, + DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_39_32 = 0x0254, + DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_47_40 = 0x0255, + DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_55_48 = 0x0256, + DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_63_56 = 0x0257, + DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_71_64 = 0x0258, + DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_79_72 = 0x0259, + + /* Test Response Field*/ + DPCD_ADDRESS_TEST_RESPONSE = 0x0260, + + /* Audio Test Pattern Field 1.2*/ + DPCD_ADDRESS_TEST_AUDIO_MODE = 0x0271, + DPCD_ADDRESS_TEST_AUDIO_PATTERN_TYPE = 0x0272, + DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_1 = 0x0273, + DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_2 = 0x0274, + DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_3 = 0x0275, + DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_4 = 0x0276, + DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_5 = 0x0277, + DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_6 = 0x0278, + DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_7 = 0x0279, + DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_8 = 0x027A, + + /* Payload Table Status Field */ + DPCD_ADDRESS_PAYLOAD_TABLE_UPDATE_STATUS = 0x002C0,/*1.2*/ + DPCD_ADDRESS_VC_PAYLOAD_ID_SLOT1 = 0x002C1,/*1.2*/ + DPCD_ADDRESS_VC_PAYLOAD_ID_SLOT63 = 0x002FF,/*1.2*/ + + /* Source Device Specific Field */ + DPCD_ADDRESS_SOURCE_DEVICE_ID_START = 0x0300, + DPCD_ADDRESS_SOURCE_DEVICE_ID_END = 0x0301, + DPCD_ADDRESS_AMD_INTERNAL_DEBUG_START = 0x030C, + DPCD_ADDRESS_AMD_INTERNAL_DEBUG_END = 0x030F, + DPCD_ADDRESS_SOURCE_SPECIFIC_TABLE_START = 0x0310, + DPCD_ADDRESS_SOURCE_SPECIFIC_TABLE_END = 0x037F, + DPCD_ADDRESS_SOURCE_RESERVED_START = 0x0380, + DPCD_ADDRESS_SOURCE_RESERVED_END = 0x03FF, + + /* Sink Device Specific Field */ + DPCD_ADDRESS_SINK_DEVICE_ID_START = 0x0400, + DPCD_ADDRESS_SINK_DEVICE_ID_END = 0x0402, + DPCD_ADDRESS_SINK_DEVICE_STR_START = 0x0403, + DPCD_ADDRESS_SINK_DEVICE_STR_END = 0x0408, + DPCD_ADDRESS_SINK_REVISION_START = 0x409, + DPCD_ADDRESS_SINK_REVISION_END = 0x40B, + + /* Branch Device Specific Field */ + DPCD_ADDRESS_BRANCH_DEVICE_ID_START = 0x0500, + DPCD_ADDRESS_BRANCH_DEVICE_ID_END = 0x0502, + DPCD_ADDRESS_BRANCH_DEVICE_STR_START = 0x0503, + DPCD_ADDRESS_BRANCH_DEVICE_STR_END = 0x0508, + DPCD_ADDRESS_BRANCH_REVISION_START = 0x0509, + DPCD_ADDRESS_BRANCH_REVISION_END = 0x050B, + + DPCD_ADDRESS_POWER_STATE = 0x0600, + + /* EDP related */ + DPCD_ADDRESS_EDP_REV = 0x0700, + DPCD_ADDRESS_EDP_CAPABILITY = 0x0701, + DPCD_ADDRESS_EDP_BACKLIGHT_ADJUST_CAP = 0x0702, + DPCD_ADDRESS_EDP_GENERAL_CAP2 = 0x0703, + + DPCD_ADDRESS_EDP_DISPLAY_CONTROL = 0x0720, + DPCD_ADDRESS_SUPPORTED_LINK_RATES = 0x00010, /* edp 1.4 */ + DPCD_ADDRESS_EDP_BACKLIGHT_SET = 0x0721, + DPCD_ADDRESS_EDP_BACKLIGHT_BRIGHTNESS_MSB = 0x0722, + DPCD_ADDRESS_EDP_BACKLIGHT_BRIGHTNESS_LSB = 0x0723, + DPCD_ADDRESS_EDP_PWMGEN_BIT_COUNT = 0x0724, + DPCD_ADDRESS_EDP_PWMGEN_BIT_COUNT_CAP_MIN = 0x0725, + DPCD_ADDRESS_EDP_PWMGEN_BIT_COUNT_CAP_MAX = 0x0726, + DPCD_ADDRESS_EDP_BACKLIGHT_CONTROL_STATUS = 0x0727, + DPCD_ADDRESS_EDP_BACKLIGHT_FREQ_SET = 0x0728, + DPCD_ADDRESS_EDP_REVERVED = 0x0729, + DPCD_ADDRESS_EDP_BACKLIGNT_FREQ_CAP_MIN_MSB = 0x072A, + DPCD_ADDRESS_EDP_BACKLIGNT_FREQ_CAP_MIN_MID = 0x072B, + DPCD_ADDRESS_EDP_BACKLIGNT_FREQ_CAP_MIN_LSB = 0x072C, + DPCD_ADDRESS_EDP_BACKLIGNT_FREQ_CAP_MAX_MSB = 0x072D, + DPCD_ADDRESS_EDP_BACKLIGNT_FREQ_CAP_MAX_MID = 0x072E, + DPCD_ADDRESS_EDP_BACKLIGNT_FREQ_CAP_MAX_LSB = 0x072F, + + DPCD_ADDRESS_EDP_DBC_MINIMUM_BRIGHTNESS_SET = 0x0732, + DPCD_ADDRESS_EDP_DBC_MAXIMUM_BRIGHTNESS_SET = 0x0733, + + /* Sideband MSG Buffers 1.2 */ + DPCD_ADDRESS_DOWN_REQ_START = 0x01000, + DPCD_ADDRESS_DOWN_REQ_END = 0x011ff, + + DPCD_ADDRESS_UP_REP_START = 0x01200, + DPCD_ADDRESS_UP_REP_END = 0x013ff, + + DPCD_ADDRESS_DOWN_REP_START = 0x01400, + DPCD_ADDRESS_DOWN_REP_END = 0x015ff, + + DPCD_ADDRESS_UP_REQ_START = 0x01600, + DPCD_ADDRESS_UP_REQ_END = 0x017ff, + + /* ESI (Event Status Indicator) Field 1.2 */ + DPCD_ADDRESS_SINK_COUNT_ESI = 0x02002, + DPCD_ADDRESS_DEVICE_IRQ_ESI0 = 0x02003, + DPCD_ADDRESS_DEVICE_IRQ_ESI1 = 0x02004, + /*@todo move dpcd_address_Lane01Status back here*/ + + DPCD_ADDRESS_PSR_ERROR_STATUS = 0x2006, + DPCD_ADDRESS_PSR_EVENT_STATUS = 0x2007, + DPCD_ADDRESS_PSR_SINK_STATUS = 0x2008, + DPCD_ADDRESS_PSR_DBG_REGISTER0 = 0x2009, + DPCD_ADDRESS_PSR_DBG_REGISTER1 = 0x200A, + + DPCD_ADDRESS_DP13_DPCD_REV = 0x2200, + DPCD_ADDRESS_DP13_MAX_LINK_RATE = 0x2201, + + /* Travis specific addresses */ + DPCD_ADDRESS_TRAVIS_SINK_DEV_SEL = 0x5f0, + DPCD_ADDRESS_TRAVIS_SINK_ACCESS_OFFSET = 0x5f1, + DPCD_ADDRESS_TRAVIS_SINK_ACCESS_REG = 0x5f2, +}; + +enum dpcd_revision { + DPCD_REV_10 = 0x10, + DPCD_REV_11 = 0x11, + DPCD_REV_12 = 0x12, + DPCD_REV_13 = 0x13, + DPCD_REV_14 = 0x14 +}; + +enum dp_pwr_state { + DP_PWR_STATE_D0 = 1,/* direct HW translation! */ + DP_PWR_STATE_D3 +}; + +/* these are the types stored at DOWNSTREAMPORT_PRESENT */ +enum dpcd_downstream_port_type { + DOWNSTREAM_DP = 0, + DOWNSTREAM_VGA, + DOWNSTREAM_DVI_HDMI, + DOWNSTREAM_NONDDC /* has no EDID (TV,CV) */ +}; + +enum dpcd_link_test_patterns { + LINK_TEST_PATTERN_NONE = 0, + LINK_TEST_PATTERN_COLOR_RAMP, + LINK_TEST_PATTERN_VERTICAL_BARS, + LINK_TEST_PATTERN_COLOR_SQUARES +}; + +enum dpcd_test_color_format { + TEST_COLOR_FORMAT_RGB = 0, + TEST_COLOR_FORMAT_YCBCR422, + TEST_COLOR_FORMAT_YCBCR444 +}; + +enum dpcd_test_bit_depth { + TEST_BIT_DEPTH_6 = 0, + TEST_BIT_DEPTH_8, + TEST_BIT_DEPTH_10, + TEST_BIT_DEPTH_12, + TEST_BIT_DEPTH_16 +}; + +/* PHY (encoder) test patterns +The order of test patterns follows DPCD register PHY_TEST_PATTERN (0x248) +*/ +enum dpcd_phy_test_patterns { + PHY_TEST_PATTERN_NONE = 0, + PHY_TEST_PATTERN_D10_2, + PHY_TEST_PATTERN_SYMBOL_ERROR, + PHY_TEST_PATTERN_PRBS7, + PHY_TEST_PATTERN_80BIT_CUSTOM,/* For DP1.2 only */ + PHY_TEST_PATTERN_HBR2_COMPLIANCE_EYE/* For DP1.2 only */ +}; + +enum dpcd_test_dyn_range { + TEST_DYN_RANGE_VESA = 0, + TEST_DYN_RANGE_CEA +}; + +enum dpcd_audio_test_pattern { + AUDIO_TEST_PATTERN_OPERATOR_DEFINED = 0,/* direct HW translation */ + AUDIO_TEST_PATTERN_SAWTOOTH +}; + +enum dpcd_audio_sampling_rate { + AUDIO_SAMPLING_RATE_32KHZ = 0,/* direct HW translation */ + AUDIO_SAMPLING_RATE_44_1KHZ, + AUDIO_SAMPLING_RATE_48KHZ, + AUDIO_SAMPLING_RATE_88_2KHZ, + AUDIO_SAMPLING_RATE_96KHZ, + AUDIO_SAMPLING_RATE_176_4KHZ, + AUDIO_SAMPLING_RATE_192KHZ +}; + +enum dpcd_audio_channels { + AUDIO_CHANNELS_1 = 0,/* direct HW translation */ + AUDIO_CHANNELS_2, + AUDIO_CHANNELS_3, + AUDIO_CHANNELS_4, + AUDIO_CHANNELS_5, + AUDIO_CHANNELS_6, + AUDIO_CHANNELS_7, + AUDIO_CHANNELS_8, + + AUDIO_CHANNELS_COUNT +}; + +enum dpcd_audio_test_pattern_periods { + DPCD_AUDIO_TEST_PATTERN_PERIOD_NOTUSED = 0,/* direct HW translation */ + DPCD_AUDIO_TEST_PATTERN_PERIOD_3, + DPCD_AUDIO_TEST_PATTERN_PERIOD_6, + DPCD_AUDIO_TEST_PATTERN_PERIOD_12, + DPCD_AUDIO_TEST_PATTERN_PERIOD_24, + DPCD_AUDIO_TEST_PATTERN_PERIOD_48, + DPCD_AUDIO_TEST_PATTERN_PERIOD_96, + DPCD_AUDIO_TEST_PATTERN_PERIOD_192, + DPCD_AUDIO_TEST_PATTERN_PERIOD_384, + DPCD_AUDIO_TEST_PATTERN_PERIOD_768, + DPCD_AUDIO_TEST_PATTERN_PERIOD_1536 +}; + +/* This enum is for programming DPCD TRAINING_PATTERN_SET */ +enum dpcd_training_patterns { + DPCD_TRAINING_PATTERN_VIDEOIDLE = 0,/* direct HW translation! */ + DPCD_TRAINING_PATTERN_1, + DPCD_TRAINING_PATTERN_2, + DPCD_TRAINING_PATTERN_3, + DPCD_TRAINING_PATTERN_4 = 7 +}; + +/* This enum is for use with PsrSinkPsrStatus.bits.sinkSelfRefreshStatus +It defines the possible PSR states. */ +enum dpcd_psr_sink_states { + PSR_SINK_STATE_INACTIVE = 0, + PSR_SINK_STATE_ACTIVE_CAPTURE_DISPLAY_ON_SOURCE_TIMING = 1, + PSR_SINK_STATE_ACTIVE_DISPLAY_FROM_SINK_RFB = 2, + PSR_SINK_STATE_ACTIVE_CAPTURE_DISPLAY_ON_SINK_TIMING = 3, + PSR_SINK_STATE_ACTIVE_CAPTURE_TIMING_RESYNC = 4, + PSR_SINK_STATE_SINK_INTERNAL_ERROR = 7, +}; + +/* This enum defines the Panel's eDP revision at DPCD 700h + * 00h = eDP v1.1 or lower + * 01h = eDP v1.2 + * 02h = eDP v1.3 (PSR support starts here) + * 03h = eDP v1.4 + * If unknown revision, treat as eDP v1.1, meaning least functionality set. + * This enum has values matched to eDP spec, thus values should not change. + */ +enum dpcd_edp_revision { + DPCD_EDP_REVISION_EDP_V1_1 = 0, + DPCD_EDP_REVISION_EDP_V1_2 = 1, + DPCD_EDP_REVISION_EDP_V1_3 = 2, + DPCD_EDP_REVISION_EDP_V1_4 = 3, + DPCD_EDP_REVISION_EDP_UNKNOWN = DPCD_EDP_REVISION_EDP_V1_1, +}; + +union dpcd_rev { + struct { + uint8_t MINOR:4; + uint8_t MAJOR:4; + } bits; + uint8_t raw; +}; + +union max_lane_count { + struct { + uint8_t MAX_LANE_COUNT:5; + uint8_t POST_LT_ADJ_REQ_SUPPORTED:1; + uint8_t TPS3_SUPPORTED:1; + uint8_t ENHANCED_FRAME_CAP:1; + } bits; + uint8_t raw; +}; + +union max_down_spread { + struct { + uint8_t MAX_DOWN_SPREAD:1; + uint8_t RESERVED:5; + uint8_t NO_AUX_HANDSHAKE_LINK_TRAINING:1; + uint8_t TPS4_SUPPORTED:1; + } bits; + uint8_t raw; +}; + +union mstm_cap { + struct { + uint8_t MST_CAP:1; + uint8_t RESERVED:7; + } bits; + uint8_t raw; +}; + +union lane_count_set { + struct { + uint8_t LANE_COUNT_SET:5; + uint8_t POST_LT_ADJ_REQ_GRANTED:1; + uint8_t RESERVED:1; + uint8_t ENHANCED_FRAMING:1; + } bits; + uint8_t raw; +}; + +union lane_status { + struct { + uint8_t CR_DONE_0:1; + uint8_t CHANNEL_EQ_DONE_0:1; + uint8_t SYMBOL_LOCKED_0:1; + uint8_t RESERVED0:1; + uint8_t CR_DONE_1:1; + uint8_t CHANNEL_EQ_DONE_1:1; + uint8_t SYMBOL_LOCKED_1:1; + uint8_t RESERVED_1:1; + } bits; + uint8_t raw; +}; + +union device_service_irq { + struct { + uint8_t REMOTE_CONTROL_CMD_PENDING:1; + uint8_t AUTOMATED_TEST:1; + uint8_t CP_IRQ:1; + uint8_t MCCS_IRQ:1; + uint8_t DOWN_REP_MSG_RDY:1; + uint8_t UP_REQ_MSG_RDY:1; + uint8_t SINK_SPECIFIC:1; + uint8_t reserved:1; + } bits; + uint8_t raw; +}; + +union sink_count { + struct { + uint8_t SINK_COUNT:6; + uint8_t CPREADY:1; + uint8_t RESERVED:1; + } bits; + uint8_t raw; +}; + +union lane_align_status_updated { + struct { + uint8_t INTERLANE_ALIGN_DONE:1; + uint8_t POST_LT_ADJ_REQ_IN_PROGRESS:1; + uint8_t RESERVED:4; + uint8_t DOWNSTREAM_PORT_STATUS_CHANGED:1; + uint8_t LINK_STATUS_UPDATED:1; + } bits; + uint8_t raw; +}; + +union lane_adjust { + struct { + uint8_t VOLTAGE_SWING_LANE:2; + uint8_t PRE_EMPHASIS_LANE:2; + uint8_t RESERVED:4; + } bits; + uint8_t raw; +}; + +union dpcd_training_pattern { + struct { + uint8_t TRAINING_PATTERN_SET:4; + uint8_t RECOVERED_CLOCK_OUT_EN:1; + uint8_t SCRAMBLING_DISABLE:1; + uint8_t SYMBOL_ERROR_COUNT_SEL:2; + } v1_4; + struct { + uint8_t TRAINING_PATTERN_SET:2; + uint8_t LINK_QUAL_PATTERN_SET:2; + uint8_t RESERVED:4; + } v1_3; + uint8_t raw; +}; + +/* Training Lane is used to configure downstream DP device's voltage swing +and pre-emphasis levels*/ +/* The DPCD addresses are from 0x103 to 0x106*/ +union dpcd_training_lane { + struct { + uint8_t VOLTAGE_SWING_SET:2; + uint8_t MAX_SWING_REACHED:1; + uint8_t PRE_EMPHASIS_SET:2; + uint8_t MAX_PRE_EMPHASIS_REACHED:1; + uint8_t RESERVED:2; + } bits; + uint8_t raw; +}; + +/* TMDS-converter related */ +union dwnstream_port_caps_byte0 { + struct { + uint8_t DWN_STRM_PORTX_TYPE:3; + uint8_t DWN_STRM_PORTX_HPD:1; + uint8_t RESERVERD:4; + } bits; + uint8_t raw; +}; + +/* these are the detailed types stored at DWN_STRM_PORTX_CAP (00080h)*/ +enum dpcd_downstream_port_detailed_type { + DOWN_STREAM_DETAILED_DP = 0, + DOWN_STREAM_DETAILED_VGA, + DOWN_STREAM_DETAILED_DVI, + DOWN_STREAM_DETAILED_HDMI, + DOWN_STREAM_DETAILED_NONDDC,/* has no EDID (TV,CV)*/ + DOWN_STREAM_DETAILED_DP_PLUS_PLUS +}; + +union dwnstream_port_caps_byte2 { + struct { + uint8_t MAX_BITS_PER_COLOR_COMPONENT:2; + uint8_t RESERVED:6; + } bits; + uint8_t raw; +}; + +union dp_downstream_port_present { + uint8_t byte; + struct { + uint8_t PORT_PRESENT:1; + uint8_t PORT_TYPE:2; + uint8_t FMT_CONVERSION:1; + uint8_t DETAILED_CAPS:1; + uint8_t RESERVED:3; + } fields; +}; + +union dwnstream_port_caps_byte3_dvi { + struct { + uint8_t RESERVED1:1; + uint8_t DUAL_LINK:1; + uint8_t HIGH_COLOR_DEPTH:1; + uint8_t RESERVED2:5; + } bits; + uint8_t raw; +}; + +union dwnstream_port_caps_byte3_hdmi { + struct { + uint8_t FRAME_SEQ_TO_FRAME_PACK:1; + uint8_t RESERVED:7; + } bits; + uint8_t raw; +}; + +/*4-byte structure for detailed capabilities of a down-stream port +(DP-to-TMDS converter).*/ + +union sink_status { + struct { + uint8_t RX_PORT0_STATUS:1; + uint8_t RX_PORT1_STATUS:1; + uint8_t RESERVED:6; + } bits; + uint8_t raw; +}; + +/*6-byte structure corresponding to 6 registers (200h-205h) +read during handling of HPD-IRQ*/ +union hpd_irq_data { + struct { + union sink_count sink_cnt;/* 200h */ + union device_service_irq device_service_irq;/* 201h */ + union lane_status lane01_status;/* 202h */ + union lane_status lane23_status;/* 203h */ + union lane_align_status_updated lane_status_updated;/* 204h */ + union sink_status sink_status; + } bytes; + uint8_t raw[6]; +}; + +union down_stream_port_count { + struct { + uint8_t DOWN_STR_PORT_COUNT:4; + uint8_t RESERVED:2; /*Bits 5:4 = RESERVED. Read all 0s.*/ + /*Bit 6 = MSA_TIMING_PAR_IGNORED + 0 = Sink device requires the MSA timing parameters + 1 = Sink device is capable of rendering incoming video + stream without MSA timing parameters*/ + uint8_t IGNORE_MSA_TIMING_PARAM:1; + /*Bit 7 = OUI Support + 0 = OUI not supported + 1 = OUI supported + (OUI and Device Identification mandatory for DP 1.2)*/ + uint8_t OUI_SUPPORT:1; + } bits; + uint8_t raw; +}; + +union down_spread_ctrl { + struct { + uint8_t RESERVED1:4;/* Bit 3:0 = RESERVED. Read all 0s*/ + /* Bits 4 = SPREAD_AMP. Spreading amplitude + 0 = Main link signal is not downspread + 1 = Main link signal is downspread <= 0.5% + with frequency in the range of 30kHz ~ 33kHz*/ + uint8_t SPREAD_AMP:1; + uint8_t RESERVED2:2;/*Bit 6:5 = RESERVED. Read all 0s*/ + /*Bit 7 = MSA_TIMING_PAR_IGNORE_EN + 0 = Source device will send valid data for the MSA Timing Params + 1 = Source device may send invalid data for these MSA Timing Params*/ + uint8_t IGNORE_MSA_TIMING_PARAM:1; + } bits; + uint8_t raw; +}; + +union dpcd_edp_config { + struct { + uint8_t PANEL_MODE_EDP:1; + uint8_t FRAMING_CHANGE_ENABLE:1; + uint8_t RESERVED:5; + uint8_t PANEL_SELF_TEST_ENABLE:1; + } bits; + uint8_t raw; +}; + +struct dp_device_vendor_id { + uint8_t ieee_oui[3];/*24-bit IEEE OUI*/ + uint8_t ieee_device_id[6];/*usually 6-byte ASCII name*/ +}; + +struct dp_sink_hw_fw_revision { + uint8_t ieee_hw_rev; + uint8_t ieee_fw_rev[2]; +}; + +/*DPCD register of DP receiver capability field bits-*/ +union edp_configuration_cap { + struct { + uint8_t ALT_SCRAMBLER_RESET:1; + uint8_t FRAMING_CHANGE:1; + uint8_t RESERVED:1; + uint8_t DPCD_DISPLAY_CONTROL_CAPABLE:1; + uint8_t RESERVED2:4; + } bits; + uint8_t raw; +}; + +union training_aux_rd_interval { + struct { + uint8_t TRAINIG_AUX_RD_INTERVAL:7; + uint8_t EXT_RECIEVER_CAP_FIELD_PRESENT:1; + } bits; + uint8_t raw; +}; + +/* Automated test structures */ +union test_request { + struct { + uint8_t LINK_TRAINING :1; + uint8_t LINK_TEST_PATTRN :1; + uint8_t EDID_REAT :1; + uint8_t PHY_TEST_PATTERN :1; + uint8_t AUDIO_TEST_PATTERN :1; + uint8_t RESERVED :1; + uint8_t TEST_STEREO_3D :1; + } bits; + uint8_t raw; +}; + +union test_response { + struct { + uint8_t ACK :1; + uint8_t NO_ACK :1; + uint8_t RESERVED :6; + } bits; + uint8_t raw; +}; + +union phy_test_pattern { + struct { + /* DpcdPhyTestPatterns. This field is 2 bits for DP1.1 + * and 3 bits for DP1.2. + */ + uint8_t PATTERN :3; + /* BY speci, bit7:2 is 0 for DP1.1. */ + uint8_t RESERVED :5; + } bits; + uint8_t raw; +}; + +/* States of Compliance Test Specification (CTS DP1.2). */ +union compliance_test_state { + struct { + unsigned char STEREO_3D_RUNNING : 1; + unsigned char SET_TEST_PATTERN_PENDING : 1; + unsigned char RESERVED : 6; + } bits; + unsigned char raw; +}; + +union link_test_pattern { + struct { + /* dpcd_link_test_patterns */ + unsigned char PATTERN :2; + unsigned char RESERVED:6; + } bits; + unsigned char raw; +}; + +union test_misc { + struct dpcd_test_misc_bits { + unsigned char SYNC_CLOCK :1; + /* dpcd_test_color_format */ + unsigned char CLR_FORMAT :2; + /* dpcd_test_dyn_range */ + unsigned char DYN_RANGE :1; + unsigned char YCBCR :1; + /* dpcd_test_bit_depth */ + unsigned char BPC :3; + } bits; + unsigned char raw; +}; + +#endif /* __DAL_DPCD_DEFS_H__ */ diff --git a/drivers/gpu/drm/amd/display/include/fixed31_32.h b/drivers/gpu/drm/amd/display/include/fixed31_32.h new file mode 100644 index 000000000000..c28de167250f --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/fixed31_32.h @@ -0,0 +1,390 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_FIXED31_32_H__ +#define __DAL_FIXED31_32_H__ + +#include "os_types.h" + +/* + * @brief + * Arithmetic operations on real numbers + * represented as fixed-point numbers. + * There are: 1 bit for sign, + * 31 bit for integer part, + * 32 bits for fractional part. + * + * @note + * Currently, overflows and underflows are asserted; + * no special result returned. + */ + +struct fixed31_32 { + int64_t value; +}; + +/* + * @brief + * Useful constants + */ + +static const struct fixed31_32 dal_fixed31_32_zero = { 0 }; +static const struct fixed31_32 dal_fixed31_32_epsilon = { 1LL }; +static const struct fixed31_32 dal_fixed31_32_half = { 0x80000000LL }; +static const struct fixed31_32 dal_fixed31_32_one = { 0x100000000LL }; + +static const struct fixed31_32 dal_fixed31_32_pi = { 13493037705LL }; +static const struct fixed31_32 dal_fixed31_32_two_pi = { 26986075409LL }; +static const struct fixed31_32 dal_fixed31_32_e = { 11674931555LL }; +static const struct fixed31_32 dal_fixed31_32_ln2 = { 2977044471LL }; +static const struct fixed31_32 dal_fixed31_32_ln2_div_2 = { 1488522236LL }; + +/* + * @brief + * Initialization routines + */ + +/* + * @brief + * result = numerator / denominator + */ +struct fixed31_32 dal_fixed31_32_from_fraction( + int64_t numerator, + int64_t denominator); + +/* + * @brief + * result = arg + */ +struct fixed31_32 dal_fixed31_32_from_int( + int64_t arg); + +/* + * @brief + * Unary operators + */ + +/* + * @brief + * result = -arg + */ +struct fixed31_32 dal_fixed31_32_neg( + struct fixed31_32 arg); + +/* + * @brief + * result = abs(arg) := (arg >= 0) ? arg : -arg + */ +struct fixed31_32 dal_fixed31_32_abs( + struct fixed31_32 arg); + +/* + * @brief + * Binary relational operators + */ + +/* + * @brief + * result = arg1 < arg2 + */ +bool dal_fixed31_32_lt( + struct fixed31_32 arg1, + struct fixed31_32 arg2); + +/* + * @brief + * result = arg1 <= arg2 + */ +bool dal_fixed31_32_le( + struct fixed31_32 arg1, + struct fixed31_32 arg2); + +/* + * @brief + * result = arg1 == arg2 + */ +bool dal_fixed31_32_eq( + struct fixed31_32 arg1, + struct fixed31_32 arg2); + +/* + * @brief + * result = min(arg1, arg2) := (arg1 <= arg2) ? arg1 : arg2 + */ +struct fixed31_32 dal_fixed31_32_min( + struct fixed31_32 arg1, + struct fixed31_32 arg2); + +/* + * @brief + * result = max(arg1, arg2) := (arg1 <= arg2) ? arg2 : arg1 + */ +struct fixed31_32 dal_fixed31_32_max( + struct fixed31_32 arg1, + struct fixed31_32 arg2); + +/* + * @brief + * | min_value, when arg <= min_value + * result = | arg, when min_value < arg < max_value + * | max_value, when arg >= max_value + */ +struct fixed31_32 dal_fixed31_32_clamp( + struct fixed31_32 arg, + struct fixed31_32 min_value, + struct fixed31_32 max_value); + +/* + * @brief + * Binary shift operators + */ + +/* + * @brief + * result = arg << shift + */ +struct fixed31_32 dal_fixed31_32_shl( + struct fixed31_32 arg, + uint8_t shift); + +/* + * @brief + * result = arg >> shift + */ +struct fixed31_32 dal_fixed31_32_shr( + struct fixed31_32 arg, + uint8_t shift); + +/* + * @brief + * Binary additive operators + */ + +/* + * @brief + * result = arg1 + arg2 + */ +struct fixed31_32 dal_fixed31_32_add( + struct fixed31_32 arg1, + struct fixed31_32 arg2); + +/* + * @brief + * result = arg1 - arg2 + */ +struct fixed31_32 dal_fixed31_32_sub_int( + struct fixed31_32 arg1, + int32_t arg2); + +/* + * @brief + * result = arg1 - arg2 + */ +struct fixed31_32 dal_fixed31_32_sub( + struct fixed31_32 arg1, + struct fixed31_32 arg2); + +/* + * @brief + * Binary multiplicative operators + */ + +/* + * @brief + * result = arg1 * arg2 + */ +struct fixed31_32 dal_fixed31_32_mul_int( + struct fixed31_32 arg1, + int32_t arg2); + +/* + * @brief + * result = arg1 * arg2 + */ +struct fixed31_32 dal_fixed31_32_mul( + struct fixed31_32 arg1, + struct fixed31_32 arg2); + +/* + * @brief + * result = square(arg) := arg * arg + */ +struct fixed31_32 dal_fixed31_32_sqr( + struct fixed31_32 arg); + +/* + * @brief + * result = arg1 / arg2 + */ +struct fixed31_32 dal_fixed31_32_div_int( + struct fixed31_32 arg1, + int64_t arg2); + +/* + * @brief + * result = arg1 / arg2 + */ +struct fixed31_32 dal_fixed31_32_div( + struct fixed31_32 arg1, + struct fixed31_32 arg2); + +/* + * @brief + * Reciprocal function + */ + +/* + * @brief + * result = reciprocal(arg) := 1 / arg + * + * @note + * No special actions taken in case argument is zero. + */ +struct fixed31_32 dal_fixed31_32_recip( + struct fixed31_32 arg); + +/* + * @brief + * Trigonometric functions + */ + +/* + * @brief + * result = sinc(arg) := sin(arg) / arg + * + * @note + * Argument specified in radians, + * internally it's normalized to [-2pi...2pi] range. + */ +struct fixed31_32 dal_fixed31_32_sinc( + struct fixed31_32 arg); + +/* + * @brief + * result = sin(arg) + * + * @note + * Argument specified in radians, + * internally it's normalized to [-2pi...2pi] range. + */ +struct fixed31_32 dal_fixed31_32_sin( + struct fixed31_32 arg); + +/* + * @brief + * result = cos(arg) + * + * @note + * Argument specified in radians + * and should be in [-2pi...2pi] range - + * passing arguments outside that range + * will cause incorrect result! + */ +struct fixed31_32 dal_fixed31_32_cos( + struct fixed31_32 arg); + +/* + * @brief + * Transcendent functions + */ + +/* + * @brief + * result = exp(arg) + * + * @note + * Currently, function is verified for abs(arg) <= 1. + */ +struct fixed31_32 dal_fixed31_32_exp( + struct fixed31_32 arg); + +/* + * @brief + * result = log(arg) + * + * @note + * Currently, abs(arg) should be less than 1. + * No normalization is done. + * Currently, no special actions taken + * in case of invalid argument(s). Take care! + */ +struct fixed31_32 dal_fixed31_32_log( + struct fixed31_32 arg); + +/* + * @brief + * Power function + */ + +/* + * @brief + * result = pow(arg1, arg2) + * + * @note + * Currently, abs(arg1) should be less than 1. Take care! + */ +struct fixed31_32 dal_fixed31_32_pow( + struct fixed31_32 arg1, + struct fixed31_32 arg2); + +/* + * @brief + * Rounding functions + */ + +/* + * @brief + * result = floor(arg) := greatest integer lower than or equal to arg + */ +int32_t dal_fixed31_32_floor( + struct fixed31_32 arg); + +/* + * @brief + * result = round(arg) := integer nearest to arg + */ +int32_t dal_fixed31_32_round( + struct fixed31_32 arg); + +/* + * @brief + * result = ceil(arg) := lowest integer greater than or equal to arg + */ +int32_t dal_fixed31_32_ceil( + struct fixed31_32 arg); + +/* the following two function are used in scaler hw programming to convert fixed + * point value to format 2 bits from integer part and 19 bits from fractional + * part. The same applies for u0d19, 0 bits from integer part and 19 bits from + * fractional + */ + +uint32_t dal_fixed31_32_u2d19( + struct fixed31_32 arg); + +uint32_t dal_fixed31_32_u0d19( + struct fixed31_32 arg); + +#endif diff --git a/drivers/gpu/drm/amd/display/include/fixed32_32.h b/drivers/gpu/drm/amd/display/include/fixed32_32.h new file mode 100644 index 000000000000..c7ddd0e435eb --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/fixed32_32.h @@ -0,0 +1,83 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + + +#ifndef __DAL_FIXED32_32_H__ +#define __DAL_FIXED32_32_H__ + +#include "os_types.h" + +struct fixed32_32 { + uint64_t value; +}; + +static const struct fixed32_32 dal_fixed32_32_zero = { 0 }; +static const struct fixed32_32 dal_fixed32_32_one = { 0x100000000LL }; +static const struct fixed32_32 dal_fixed32_32_half = { 0x80000000LL }; + +struct fixed32_32 dal_fixed32_32_from_fraction(uint32_t n, uint32_t d); +struct fixed32_32 dal_fixed32_32_from_int(uint32_t value); +struct fixed32_32 dal_fixed32_32_add( + struct fixed32_32 lhs, + struct fixed32_32 rhs); +struct fixed32_32 dal_fixed32_32_add_int( + struct fixed32_32 lhs, + uint32_t rhs); +struct fixed32_32 dal_fixed32_32_sub( + struct fixed32_32 lhs, + struct fixed32_32 rhs); +struct fixed32_32 dal_fixed32_32_sub_int( + struct fixed32_32 lhs, + uint32_t rhs); +struct fixed32_32 dal_fixed32_32_mul( + struct fixed32_32 lhs, + struct fixed32_32 rhs); +struct fixed32_32 dal_fixed32_32_mul_int( + struct fixed32_32 lhs, + uint32_t rhs); +struct fixed32_32 dal_fixed32_32_div( + struct fixed32_32 lhs, + struct fixed32_32 rhs); +struct fixed32_32 dal_fixed32_32_div_int( + struct fixed32_32 lhs, + uint32_t rhs); +struct fixed32_32 dal_fixed32_32_min( + struct fixed32_32 lhs, + struct fixed32_32 rhs); +struct fixed32_32 dal_fixed32_32_max( + struct fixed32_32 lhs, + struct fixed32_32 rhs); +bool dal_fixed32_32_gt(struct fixed32_32 lhs, struct fixed32_32 rhs); +bool dal_fixed32_32_gt_int(struct fixed32_32 lhs, uint32_t rhs); +bool dal_fixed32_32_lt(struct fixed32_32 lhs, struct fixed32_32 rhs); +bool dal_fixed32_32_lt_int(struct fixed32_32 lhs, uint32_t rhs); +bool dal_fixed32_32_le(struct fixed32_32 lhs, struct fixed32_32 rhs); +bool dal_fixed32_32_le_int(struct fixed32_32 lhs, uint32_t rhs); +bool dal_fixed32_32_eq(struct fixed32_32 lhs, struct fixed32_32 rhs); +uint32_t dal_fixed32_32_ceil(struct fixed32_32 value); +uint32_t dal_fixed32_32_floor(struct fixed32_32 value); +uint32_t dal_fixed32_32_round(struct fixed32_32 value); + +#endif diff --git a/drivers/gpu/drm/amd/display/include/gpio_interface.h b/drivers/gpu/drm/amd/display/include/gpio_interface.h new file mode 100644 index 000000000000..e4fd31024b92 --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/gpio_interface.h @@ -0,0 +1,92 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_GPIO_INTERFACE_H__ +#define __DAL_GPIO_INTERFACE_H__ + +#include "gpio_types.h" +#include "grph_object_defs.h" + +struct gpio; + +/* Open the handle for future use */ +enum gpio_result dal_gpio_open( + struct gpio *gpio, + enum gpio_mode mode); + +enum gpio_result dal_gpio_open_ex( + struct gpio *gpio, + enum gpio_mode mode); + +/* Get high or low from the pin */ +enum gpio_result dal_gpio_get_value( + const struct gpio *gpio, + uint32_t *value); + +/* Set pin high or low */ +enum gpio_result dal_gpio_set_value( + const struct gpio *gpio, + uint32_t value); + +/* Get current mode */ +enum gpio_mode dal_gpio_get_mode( + const struct gpio *gpio); + +/* Change mode of the handle */ +enum gpio_result dal_gpio_change_mode( + struct gpio *gpio, + enum gpio_mode mode); + +/* Get the GPIO id */ +enum gpio_id dal_gpio_get_id( + const struct gpio *gpio); + +/* Get the GPIO enum */ +uint32_t dal_gpio_get_enum( + const struct gpio *gpio); + +/* Set the GPIO pin configuration */ +enum gpio_result dal_gpio_set_config( + struct gpio *gpio, + const struct gpio_config_data *config_data); + +/* Obtain GPIO pin info */ +enum gpio_result dal_gpio_get_pin_info( + const struct gpio *gpio, + struct gpio_pin_info *pin_info); + +/* Obtain GPIO sync source */ +enum sync_source dal_gpio_get_sync_source( + const struct gpio *gpio); + +/* Obtain GPIO pin output state (active low or active high) */ +enum gpio_pin_output_state dal_gpio_get_output_state( + const struct gpio *gpio); + +/* Close the handle */ +void dal_gpio_close( + struct gpio *gpio); + +#endif diff --git a/drivers/gpu/drm/amd/display/include/gpio_service_interface.h b/drivers/gpu/drm/amd/display/include/gpio_service_interface.h new file mode 100644 index 000000000000..f40259bade40 --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/gpio_service_interface.h @@ -0,0 +1,105 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_GPIO_SERVICE_INTERFACE_H__ +#define __DAL_GPIO_SERVICE_INTERFACE_H__ + +#include "gpio_types.h" +#include "gpio_interface.h" +#include "hw/gpio.h" + +struct gpio_service; + +struct gpio *dal_gpio_create( + struct gpio_service *service, + enum gpio_id id, + uint32_t en, + enum gpio_pin_output_state output_state); + +void dal_gpio_destroy( + struct gpio **ptr); + +struct gpio_service *dal_gpio_service_create( + enum dce_version dce_version_major, + enum dce_version dce_version_minor, + struct dc_context *ctx); + +struct gpio *dal_gpio_service_create_irq( + struct gpio_service *service, + uint32_t offset, + uint32_t mask); + +struct ddc *dal_gpio_create_ddc( + struct gpio_service *service, + uint32_t offset, + uint32_t mask, + struct gpio_ddc_hw_info *info); + + +void dal_gpio_destroy_ddc( + struct ddc **ddc); + +void dal_gpio_service_destroy( + struct gpio_service **ptr); + +enum dc_irq_source dal_irq_get_source( + const struct gpio *irq); + +enum dc_irq_source dal_irq_get_rx_source( + const struct gpio *irq); + +enum gpio_result dal_irq_setup_hpd_filter( + struct gpio *irq, + struct gpio_hpd_config *config); + +struct gpio *dal_gpio_create_irq( + struct gpio_service *service, + enum gpio_id id, + uint32_t en); + +void dal_gpio_destroy_irq( + struct gpio **ptr); + + +enum gpio_result dal_ddc_open( + struct ddc *ddc, + enum gpio_mode mode, + enum gpio_ddc_config_type config_type); + +enum gpio_result dal_ddc_change_mode( + struct ddc *ddc, + enum gpio_mode mode); + +enum gpio_ddc_line dal_ddc_get_line( + const struct ddc *ddc); + +enum gpio_result dal_ddc_set_config( + struct ddc *ddc, + enum gpio_ddc_config_type config_type); + +void dal_ddc_close( + struct ddc *ddc); + +#endif diff --git a/drivers/gpu/drm/amd/display/include/gpio_types.h b/drivers/gpu/drm/amd/display/include/gpio_types.h new file mode 100644 index 000000000000..8dd46ed799e5 --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/gpio_types.h @@ -0,0 +1,332 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_GPIO_TYPES_H__ +#define __DAL_GPIO_TYPES_H__ + +#define BUNDLE_A_MASK 0x00FFF000L +#define BUNDLE_B_MASK 0x00000FFFL + +/* + * gpio_result + * + * @brief + * The possible return codes that the GPIO object can return. + * These return codes can be generated + * directly by the GPIO object or from the GPIOPin object. + */ +enum gpio_result { + GPIO_RESULT_OK, + GPIO_RESULT_NULL_HANDLE, + GPIO_RESULT_INVALID_DATA, + GPIO_RESULT_DEVICE_BUSY, + GPIO_RESULT_OPEN_FAILED, + GPIO_RESULT_ALREADY_OPENED, + GPIO_RESULT_NON_SPECIFIC_ERROR +}; + +/* + * @brief + * Used to identify the specific GPIO device + * + * @notes + * These constants are used as indices in a vector. + * Thus they should start from zero and be contiguous. + */ +enum gpio_id { + GPIO_ID_UNKNOWN = (-1), + GPIO_ID_DDC_DATA, + GPIO_ID_DDC_CLOCK, + GPIO_ID_GENERIC, + GPIO_ID_HPD, + GPIO_ID_GPIO_PAD, + GPIO_ID_VIP_PAD, + GPIO_ID_SYNC, + GPIO_ID_GSL, /* global swap lock */ + GPIO_ID_COUNT, + GPIO_ID_MIN = GPIO_ID_DDC_DATA, + GPIO_ID_MAX = GPIO_ID_GSL +}; + +#define GPIO_ENUM_UNKNOWN \ + 32 + +struct gpio_pin_info { + uint32_t offset; + uint32_t offset_y; + uint32_t offset_en; + uint32_t offset_mask; + + uint32_t mask; + uint32_t mask_y; + uint32_t mask_en; + uint32_t mask_mask; +}; + +enum gpio_pin_output_state { + GPIO_PIN_OUTPUT_STATE_ACTIVE_LOW, + GPIO_PIN_OUTPUT_STATE_ACTIVE_HIGH, + GPIO_PIN_OUTPUT_STATE_DEFAULT = GPIO_PIN_OUTPUT_STATE_ACTIVE_LOW +}; + +enum gpio_generic { + GPIO_GENERIC_UNKNOWN = (-1), + GPIO_GENERIC_A, + GPIO_GENERIC_B, + GPIO_GENERIC_C, + GPIO_GENERIC_D, + GPIO_GENERIC_E, + GPIO_GENERIC_F, + GPIO_GENERIC_G, + GPIO_GENERIC_COUNT, + GPIO_GENERIC_MIN = GPIO_GENERIC_A, + GPIO_GENERIC_MAX = GPIO_GENERIC_B +}; + +enum gpio_hpd { + GPIO_HPD_UNKNOWN = (-1), + GPIO_HPD_1, + GPIO_HPD_2, + GPIO_HPD_3, + GPIO_HPD_4, + GPIO_HPD_5, + GPIO_HPD_6, + GPIO_HPD_COUNT, + GPIO_HPD_MIN = GPIO_HPD_1, + GPIO_HPD_MAX = GPIO_HPD_6 +}; + +enum gpio_gpio_pad { + GPIO_GPIO_PAD_UNKNOWN = (-1), + GPIO_GPIO_PAD_0, + GPIO_GPIO_PAD_1, + GPIO_GPIO_PAD_2, + GPIO_GPIO_PAD_3, + GPIO_GPIO_PAD_4, + GPIO_GPIO_PAD_5, + GPIO_GPIO_PAD_6, + GPIO_GPIO_PAD_7, + GPIO_GPIO_PAD_8, + GPIO_GPIO_PAD_9, + GPIO_GPIO_PAD_10, + GPIO_GPIO_PAD_11, + GPIO_GPIO_PAD_12, + GPIO_GPIO_PAD_13, + GPIO_GPIO_PAD_14, + GPIO_GPIO_PAD_15, + GPIO_GPIO_PAD_16, + GPIO_GPIO_PAD_17, + GPIO_GPIO_PAD_18, + GPIO_GPIO_PAD_19, + GPIO_GPIO_PAD_20, + GPIO_GPIO_PAD_21, + GPIO_GPIO_PAD_22, + GPIO_GPIO_PAD_23, + GPIO_GPIO_PAD_24, + GPIO_GPIO_PAD_25, + GPIO_GPIO_PAD_26, + GPIO_GPIO_PAD_27, + GPIO_GPIO_PAD_28, + GPIO_GPIO_PAD_29, + GPIO_GPIO_PAD_30, + GPIO_GPIO_PAD_COUNT, + GPIO_GPIO_PAD_MIN = GPIO_GPIO_PAD_0, + GPIO_GPIO_PAD_MAX = GPIO_GPIO_PAD_30 +}; + +enum gpio_vip_pad { + GPIO_VIP_PAD_UNKNOWN = (-1), + /* following never used - + * GPIO_ID_DDC_CLOCK::GPIO_DDC_LINE_VIP_PAD defined instead */ + GPIO_VIP_PAD_SCL, + /* following never used - + * GPIO_ID_DDC_DATA::GPIO_DDC_LINE_VIP_PAD defined instead */ + GPIO_VIP_PAD_SDA, + GPIO_VIP_PAD_VHAD, + GPIO_VIP_PAD_VPHCTL, + GPIO_VIP_PAD_VIPCLK, + GPIO_VIP_PAD_VID, + GPIO_VIP_PAD_VPCLK0, + GPIO_VIP_PAD_DVALID, + GPIO_VIP_PAD_PSYNC, + GPIO_VIP_PAD_COUNT, + GPIO_VIP_PAD_MIN = GPIO_VIP_PAD_SCL, + GPIO_VIP_PAD_MAX = GPIO_VIP_PAD_PSYNC +}; + +enum gpio_sync { + GPIO_SYNC_UNKNOWN = (-1), + GPIO_SYNC_HSYNC_A, + GPIO_SYNC_VSYNC_A, + GPIO_SYNC_HSYNC_B, + GPIO_SYNC_VSYNC_B, + GPIO_SYNC_COUNT, + GPIO_SYNC_MIN = GPIO_SYNC_HSYNC_A, + GPIO_SYNC_MAX = GPIO_SYNC_VSYNC_B +}; + +enum gpio_gsl { + GPIO_GSL_UNKNOWN = (-1), + GPIO_GSL_GENLOCK_CLOCK, + GPIO_GSL_GENLOCK_VSYNC, + GPIO_GSL_SWAPLOCK_A, + GPIO_GSL_SWAPLOCK_B, + GPIO_GSL_COUNT, + GPIO_GSL_MIN = GPIO_GSL_GENLOCK_CLOCK, + GPIO_GSL_MAX = GPIO_GSL_SWAPLOCK_B +}; + +/* + * @brief + * Unique Id for DDC handle. + * Values are meaningful (used as indexes to array) + */ +enum gpio_ddc_line { + GPIO_DDC_LINE_UNKNOWN = (-1), + GPIO_DDC_LINE_DDC1, + GPIO_DDC_LINE_DDC2, + GPIO_DDC_LINE_DDC3, + GPIO_DDC_LINE_DDC4, + GPIO_DDC_LINE_DDC5, + GPIO_DDC_LINE_DDC6, + GPIO_DDC_LINE_DDC_VGA, + GPIO_DDC_LINE_VIP_PAD, + GPIO_DDC_LINE_I2C_PAD = GPIO_DDC_LINE_VIP_PAD, + GPIO_DDC_LINE_COUNT, + GPIO_DDC_LINE_MIN = GPIO_DDC_LINE_DDC1, + GPIO_DDC_LINE_MAX = GPIO_DDC_LINE_I2C_PAD +}; + +/* + * @brief + * Identifies the mode of operation to open a GPIO device. + * A GPIO device (pin) can be programmed in only one of these modes at a time. + */ +enum gpio_mode { + GPIO_MODE_UNKNOWN = (-1), + GPIO_MODE_INPUT, + GPIO_MODE_OUTPUT, + GPIO_MODE_FAST_OUTPUT, + GPIO_MODE_HARDWARE, + GPIO_MODE_INTERRUPT +}; + +/* + * @brief + * Identifies the source of the signal when GPIO is in HW mode. + * get_signal_source() will return GPIO_SYGNAL_SOURCE__UNKNOWN + * when one of the following holds: + * 1. GPIO is input GPIO + * 2. GPIO is not opened in HW mode + * 3. GPIO does not have fixed signal source + * (like DC_GenericA have mux instead fixed) + */ +enum gpio_signal_source { + GPIO_SIGNAL_SOURCE_UNKNOWN = (-1), + GPIO_SIGNAL_SOURCE_DACA_STEREO_SYNC, + GPIO_SIGNAL_SOURCE_PASS_THROUGH_STEREO_SYNC, + GPIO_SIGNAL_SOURCE_DACB_STEREO_SYNC, + GPIO_SIGNAL_SOURCE_DACA_HSYNC, + GPIO_SIGNAL_SOURCE_DACB_HSYNC, + GPIO_SIGNAL_SOURCE_DACA_VSYNC, + GPIO_SIGNAL_SOURCE_DACB_VSYNC, +}; + +enum gpio_stereo_source { + GPIO_STEREO_SOURCE_UNKNOWN = (-1), + GPIO_STEREO_SOURCE_D1, + GPIO_STEREO_SOURCE_D2, + GPIO_STEREO_SOURCE_D3, + GPIO_STEREO_SOURCE_D4, + GPIO_STEREO_SOURCE_D5, + GPIO_STEREO_SOURCE_D6 +}; + +/* + * GPIO config + */ + +enum gpio_config_type { + GPIO_CONFIG_TYPE_NONE, + GPIO_CONFIG_TYPE_DDC, + GPIO_CONFIG_TYPE_HPD, + GPIO_CONFIG_TYPE_GENERIC_MUX, + GPIO_CONFIG_TYPE_GSL_MUX, + GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE +}; + +/* DDC configuration */ + +enum gpio_ddc_config_type { + GPIO_DDC_CONFIG_TYPE_MODE_AUX, + GPIO_DDC_CONFIG_TYPE_MODE_I2C, + GPIO_DDC_CONFIG_TYPE_POLL_FOR_CONNECT, + GPIO_DDC_CONFIG_TYPE_POLL_FOR_DISCONNECT, + GPIO_DDC_CONFIG_TYPE_DISABLE_POLLING +}; + +struct gpio_ddc_config { + enum gpio_ddc_config_type type; + bool data_en_bit_present; + bool clock_en_bit_present; +}; + +/* HPD configuration */ + +struct gpio_hpd_config { + uint32_t delay_on_connect; /* milliseconds */ + uint32_t delay_on_disconnect; /* milliseconds */ +}; + +struct gpio_generic_mux_config { + bool enable_output_from_mux; + enum gpio_signal_source mux_select; + enum gpio_stereo_source stereo_select; +}; + +enum gpio_gsl_mux_config_type { + GPIO_GSL_MUX_CONFIG_TYPE_DISABLE, + GPIO_GSL_MUX_CONFIG_TYPE_TIMING_SYNC, + GPIO_GSL_MUX_CONFIG_TYPE_FLIP_SYNC +}; + +struct gpio_gsl_mux_config { + enum gpio_gsl_mux_config_type type; + /* Actually sync_source type, + * however we want to avoid inter-component includes here */ + uint32_t gsl_group; +}; + +struct gpio_config_data { + enum gpio_config_type type; + union { + struct gpio_ddc_config ddc; + struct gpio_hpd_config hpd; + struct gpio_generic_mux_config generic_mux; + struct gpio_gsl_mux_config gsl_mux; + } config; +}; + +#endif diff --git a/drivers/gpu/drm/amd/display/include/grph_object_ctrl_defs.h b/drivers/gpu/drm/amd/display/include/grph_object_ctrl_defs.h new file mode 100644 index 000000000000..9c0bf6521dd9 --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/grph_object_ctrl_defs.h @@ -0,0 +1,407 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_GRPH_OBJECT_CTRL_DEFS_H__ +#define __DAL_GRPH_OBJECT_CTRL_DEFS_H__ + +#include "grph_object_defs.h" + +/* + * ##################################################### + * ##################################################### + * + * These defines shared between asic_control/bios_parser and other + * DAL components + * + * ##################################################### + * ##################################################### + */ + +enum display_output_bit_depth { + PANEL_UNDEFINE = 0, + PANEL_6BIT_COLOR = 1, + PANEL_8BIT_COLOR = 2, + PANEL_10BIT_COLOR = 3, + PANEL_12BIT_COLOR = 4, + PANEL_16BIT_COLOR = 5, +}; + + +/* Device type as abstracted by ATOM BIOS */ +enum dal_device_type { + DEVICE_TYPE_UNKNOWN = 0, + DEVICE_TYPE_LCD, + DEVICE_TYPE_CRT, + DEVICE_TYPE_DFP, + DEVICE_TYPE_CV, + DEVICE_TYPE_TV, + DEVICE_TYPE_CF, + DEVICE_TYPE_WIRELESS +}; + +/* Device ID as abstracted by ATOM BIOS */ +struct device_id { + enum dal_device_type device_type:16; + uint32_t enum_id:16; /* 1 based enum */ +}; + +struct graphics_object_i2c_info { + struct gpio_info { + uint32_t clk_mask_register_index; + uint32_t clk_en_register_index; + uint32_t clk_y_register_index; + uint32_t clk_a_register_index; + uint32_t data_mask_register_index; + uint32_t data_en_register_index; + uint32_t data_y_register_index; + uint32_t data_a_register_index; + + uint32_t clk_mask_shift; + uint32_t clk_en_shift; + uint32_t clk_y_shift; + uint32_t clk_a_shift; + uint32_t data_mask_shift; + uint32_t data_en_shift; + uint32_t data_y_shift; + uint32_t data_a_shift; + } gpio_info; + + bool i2c_hw_assist; + uint32_t i2c_line; + uint32_t i2c_engine_id; + uint32_t i2c_slave_address; +}; + +struct graphics_object_hpd_info { + uint8_t hpd_int_gpio_uid; + uint8_t hpd_active; +}; + +struct connector_device_tag_info { + uint32_t acpi_device; + struct device_id dev_id; +}; + +struct device_timing { + struct misc_info { + uint32_t HORIZONTAL_CUT_OFF:1; + /* 0=Active High, 1=Active Low */ + uint32_t H_SYNC_POLARITY:1; + /* 0=Active High, 1=Active Low */ + uint32_t V_SYNC_POLARITY:1; + uint32_t VERTICAL_CUT_OFF:1; + uint32_t H_REPLICATION_BY2:1; + uint32_t V_REPLICATION_BY2:1; + uint32_t COMPOSITE_SYNC:1; + uint32_t INTERLACE:1; + uint32_t DOUBLE_CLOCK:1; + uint32_t RGB888:1; + uint32_t GREY_LEVEL:2; + uint32_t SPATIAL:1; + uint32_t TEMPORAL:1; + uint32_t API_ENABLED:1; + } misc_info; + + uint32_t pixel_clk; /* in KHz */ + uint32_t horizontal_addressable; + uint32_t horizontal_blanking_time; + uint32_t vertical_addressable; + uint32_t vertical_blanking_time; + uint32_t horizontal_sync_offset; + uint32_t horizontal_sync_width; + uint32_t vertical_sync_offset; + uint32_t vertical_sync_width; + uint32_t horizontal_border; + uint32_t vertical_border; +}; + +struct supported_refresh_rate { + uint32_t REFRESH_RATE_30HZ:1; + uint32_t REFRESH_RATE_40HZ:1; + uint32_t REFRESH_RATE_48HZ:1; + uint32_t REFRESH_RATE_50HZ:1; + uint32_t REFRESH_RATE_60HZ:1; +}; + +struct embedded_panel_info { + struct device_timing lcd_timing; + uint32_t ss_id; + struct supported_refresh_rate supported_rr; + uint32_t drr_enabled; + uint32_t min_drr_refresh_rate; + bool realtek_eDPToLVDS; +}; + +struct firmware_info { + struct pll_info { + uint32_t crystal_frequency; /* in KHz */ + uint32_t min_input_pxl_clk_pll_frequency; /* in KHz */ + uint32_t max_input_pxl_clk_pll_frequency; /* in KHz */ + uint32_t min_output_pxl_clk_pll_frequency; /* in KHz */ + uint32_t max_output_pxl_clk_pll_frequency; /* in KHz */ + } pll_info; + + struct firmware_feature { + uint32_t memory_clk_ss_percentage; + uint32_t engine_clk_ss_percentage; + } feature; + + uint32_t default_display_engine_pll_frequency; /* in KHz */ + uint32_t external_clock_source_frequency_for_dp; /* in KHz */ + uint32_t smu_gpu_pll_output_freq; /* in KHz */ + uint8_t min_allowed_bl_level; + uint8_t remote_display_config; + uint32_t default_memory_clk; /* in KHz */ + uint32_t default_engine_clk; /* in KHz */ + uint32_t dp_phy_ref_clk; /* in KHz - DCE12 only */ + uint32_t i2c_engine_ref_clk; /* in KHz - DCE12 only */ + + +}; + +struct step_and_delay_info { + uint32_t step; + uint32_t delay; + uint32_t recommended_ref_div; +}; + +struct spread_spectrum_info { + struct spread_spectrum_type { + bool CENTER_MODE:1; + bool EXTERNAL:1; + bool STEP_AND_DELAY_INFO:1; + } type; + + /* in unit of 0.01% (spreadPercentageDivider = 100), + otherwise in 0.001% units (spreadPercentageDivider = 1000); */ + uint32_t spread_spectrum_percentage; + uint32_t spread_percentage_divider; /* 100 or 1000 */ + uint32_t spread_spectrum_range; /* modulation freq (HZ)*/ + + union { + struct step_and_delay_info step_and_delay_info; + /* For mem/engine/uvd, Clock Out frequence (VCO ), + in unit of kHz. For TMDS/HDMI/LVDS, it is pixel clock, + for DP, it is link clock ( 270000 or 162000 ) */ + uint32_t target_clock_range; /* in KHz */ + }; + +}; + +struct graphics_object_encoder_cap_info { + uint32_t dp_hbr2_cap:1; + uint32_t dp_hbr2_validated:1; + /* + * TODO: added MST and HDMI 6G capable flags + */ + uint32_t reserved:15; +}; + +struct din_connector_info { + uint32_t gpio_id; + bool gpio_tv_active_state; +}; + +/* Invalid channel mapping */ +enum { INVALID_DDI_CHANNEL_MAPPING = 0x0 }; + +/** + * DDI PHY channel mapping reflecting XBAR setting + */ +union ddi_channel_mapping { + struct mapping { + uint8_t lane0:2; /* Mapping for lane 0 */ + uint8_t lane1:2; /* Mapping for lane 1 */ + uint8_t lane2:2; /* Mapping for lane 2 */ + uint8_t lane3:2; /* Mapping for lane 3 */ + } mapping; + uint8_t raw; +}; + +/** +* Transmitter output configuration description +*/ +struct transmitter_configuration_info { + /* DDI PHY ID for the transmitter */ + enum transmitter transmitter_phy_id; + /* DDI PHY channel mapping reflecting crossbar setting */ + union ddi_channel_mapping output_channel_mapping; +}; + +struct transmitter_configuration { + /* Configuration for the primary transmitter */ + struct transmitter_configuration_info primary_transmitter_config; + /* Secondary transmitter configuration for Dual-link DVI */ + struct transmitter_configuration_info secondary_transmitter_config; +}; + +/* These size should be sufficient to store info coming from BIOS */ +#define NUMBER_OF_UCHAR_FOR_GUID 16 +#define MAX_NUMBER_OF_EXT_DISPLAY_PATH 7 +#define NUMBER_OF_CSR_M3_ARB 10 +#define NUMBER_OF_DISP_CLK_VOLTAGE 4 +#define NUMBER_OF_AVAILABLE_SCLK 5 + +/* V6 */ +struct integrated_info { + struct clock_voltage_caps { + /* The Voltage Index indicated by FUSE, same voltage index + shared with SCLK DPM fuse table */ + uint32_t voltage_index; + /* Maximum clock supported with specified voltage index */ + uint32_t max_supported_clk; /* in KHz */ + } disp_clk_voltage[NUMBER_OF_DISP_CLK_VOLTAGE]; + + struct display_connection_info { + struct external_display_path { + /* A bit vector to show what devices are supported */ + uint32_t device_tag; + /* 16bit device ACPI id. */ + uint32_t device_acpi_enum; + /* A physical connector for displays to plug in, + using object connector definitions */ + struct graphics_object_id device_connector_id; + /* An index into external AUX/DDC channel LUT */ + uint8_t ext_aux_ddc_lut_index; + /* An index into external HPD pin LUT */ + uint8_t ext_hpd_pin_lut_index; + /* external encoder object id */ + struct graphics_object_id ext_encoder_obj_id; + /* XBAR mapping of the PHY channels */ + union ddi_channel_mapping channel_mapping; + } path[MAX_NUMBER_OF_EXT_DISPLAY_PATH]; + + uint8_t gu_id[NUMBER_OF_UCHAR_FOR_GUID]; + uint8_t checksum; + } ext_disp_conn_info; /* exiting long long time */ + + struct available_s_clk_list { + /* Maximum clock supported with specified voltage index */ + uint32_t supported_s_clk; /* in KHz */ + /* The Voltage Index indicated by FUSE for specified SCLK */ + uint32_t voltage_index; + /* The Voltage ID indicated by FUSE for specified SCLK */ + uint32_t voltage_id; + } avail_s_clk[NUMBER_OF_AVAILABLE_SCLK]; + + uint8_t memory_type; + uint8_t ma_channel_number; + uint32_t boot_up_engine_clock; /* in KHz */ + uint32_t dentist_vco_freq; /* in KHz */ + uint32_t boot_up_uma_clock; /* in KHz */ + uint32_t boot_up_req_display_vector; + uint32_t other_display_misc; + uint32_t gpu_cap_info; + uint32_t sb_mmio_base_addr; + uint32_t system_config; + uint32_t cpu_cap_info; + uint32_t max_nb_voltage; + uint32_t min_nb_voltage; + uint32_t boot_up_nb_voltage; + uint32_t ext_disp_conn_info_offset; + uint32_t csr_m3_arb_cntl_default[NUMBER_OF_CSR_M3_ARB]; + uint32_t csr_m3_arb_cntl_uvd[NUMBER_OF_CSR_M3_ARB]; + uint32_t csr_m3_arb_cntl_fs3d[NUMBER_OF_CSR_M3_ARB]; + uint32_t gmc_restore_reset_time; + uint32_t minimum_n_clk; + uint32_t idle_n_clk; + uint32_t ddr_dll_power_up_time; + uint32_t ddr_pll_power_up_time; + /* start for V6 */ + uint32_t pcie_clk_ss_type; + uint32_t lvds_ss_percentage; + uint32_t lvds_sspread_rate_in_10hz; + uint32_t hdmi_ss_percentage; + uint32_t hdmi_sspread_rate_in_10hz; + uint32_t dvi_ss_percentage; + uint32_t dvi_sspread_rate_in_10_hz; + uint32_t sclk_dpm_boost_margin; + uint32_t sclk_dpm_throttle_margin; + uint32_t sclk_dpm_tdp_limit_pg; + uint32_t sclk_dpm_tdp_limit_boost; + uint32_t boost_engine_clock; + uint32_t boost_vid_2bit; + uint32_t enable_boost; + uint32_t gnb_tdp_limit; + /* Start from V7 */ + uint32_t max_lvds_pclk_freq_in_single_link; + uint32_t lvds_misc; + uint32_t lvds_pwr_on_seq_dig_on_to_de_in_4ms; + uint32_t lvds_pwr_on_seq_de_to_vary_bl_in_4ms; + uint32_t lvds_pwr_off_seq_vary_bl_to_de_in4ms; + uint32_t lvds_pwr_off_seq_de_to_dig_on_in4ms; + uint32_t lvds_off_to_on_delay_in_4ms; + uint32_t lvds_pwr_on_seq_vary_bl_to_blon_in_4ms; + uint32_t lvds_pwr_off_seq_blon_to_vary_bl_in_4ms; + uint32_t lvds_reserved1; + uint32_t lvds_bit_depth_control_val; +}; + +/** +* Power source ids. +*/ +enum power_source { + POWER_SOURCE_AC = 0, + POWER_SOURCE_DC, + POWER_SOURCE_LIMITED_POWER, + POWER_SOURCE_LIMITED_POWER_2, + POWER_SOURCE_MAX +}; + +struct bios_event_info { + uint32_t thermal_state; + uint32_t backlight_level; + enum power_source powerSource; + bool has_thermal_state_changed; + bool has_power_source_changed; + bool has_forced_mode_changed; + bool forced_mode; + bool backlight_changed; +}; + +enum { + HDMI_PIXEL_CLOCK_IN_KHZ_297 = 297000, + TMDS_PIXEL_CLOCK_IN_KHZ_165 = 165000 +}; + +/* + * DFS-bypass flag + */ +/* Copy of SYS_INFO_GPUCAPS__ENABEL_DFS_BYPASS from atombios.h */ +enum { + DFS_BYPASS_ENABLE = 0x10 +}; + +enum { + INVALID_BACKLIGHT = -1 +}; + +struct panel_backlight_boundaries { + uint32_t min_signal_level; + uint32_t max_signal_level; +}; + + +#endif diff --git a/drivers/gpu/drm/amd/display/include/grph_object_defs.h b/drivers/gpu/drm/amd/display/include/grph_object_defs.h new file mode 100644 index 000000000000..2941b882b0b6 --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/grph_object_defs.h @@ -0,0 +1,140 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_GRPH_OBJECT_DEFS_H__ +#define __DAL_GRPH_OBJECT_DEFS_H__ + +#include "grph_object_id.h" + +/* ******************************************************************** + * ******************************************************************** + * + * These defines shared between All Graphics Objects + * + * ******************************************************************** + * ******************************************************************** + */ + +/* HPD unit id - HW direct translation */ +enum hpd_source_id { + HPD_SOURCEID1 = 0, + HPD_SOURCEID2, + HPD_SOURCEID3, + HPD_SOURCEID4, + HPD_SOURCEID5, + HPD_SOURCEID6, + + HPD_SOURCEID_COUNT, + HPD_SOURCEID_UNKNOWN +}; + +/* DDC unit id - HW direct translation */ +enum channel_id { + CHANNEL_ID_UNKNOWN = 0, + CHANNEL_ID_DDC1, + CHANNEL_ID_DDC2, + CHANNEL_ID_DDC3, + CHANNEL_ID_DDC4, + CHANNEL_ID_DDC5, + CHANNEL_ID_DDC6, + CHANNEL_ID_DDC_VGA, + CHANNEL_ID_I2C_PAD, + CHANNEL_ID_COUNT +}; + +#define DECODE_CHANNEL_ID(ch_id) \ + (ch_id) == CHANNEL_ID_DDC1 ? "CHANNEL_ID_DDC1" : \ + (ch_id) == CHANNEL_ID_DDC2 ? "CHANNEL_ID_DDC2" : \ + (ch_id) == CHANNEL_ID_DDC3 ? "CHANNEL_ID_DDC3" : \ + (ch_id) == CHANNEL_ID_DDC4 ? "CHANNEL_ID_DDC4" : \ + (ch_id) == CHANNEL_ID_DDC5 ? "CHANNEL_ID_DDC5" : \ + (ch_id) == CHANNEL_ID_DDC6 ? "CHANNEL_ID_DDC6" : \ + (ch_id) == CHANNEL_ID_DDC_VGA ? "CHANNEL_ID_DDC_VGA" : \ + (ch_id) == CHANNEL_ID_I2C_PAD ? "CHANNEL_ID_I2C_PAD" : "Invalid" + +enum transmitter { + TRANSMITTER_UNKNOWN = (-1L), + TRANSMITTER_UNIPHY_A, + TRANSMITTER_UNIPHY_B, + TRANSMITTER_UNIPHY_C, + TRANSMITTER_UNIPHY_D, + TRANSMITTER_UNIPHY_E, + TRANSMITTER_UNIPHY_F, + TRANSMITTER_NUTMEG_CRT, + TRANSMITTER_TRAVIS_CRT, + TRANSMITTER_TRAVIS_LCD, + TRANSMITTER_UNIPHY_G, + TRANSMITTER_COUNT +}; + +/* Generic source of the synchronisation input/output signal */ +/* Can be used for flow control, stereo sync, timing sync, frame sync, etc */ +enum sync_source { + SYNC_SOURCE_NONE = 0, + + /* Source based on controllers */ + SYNC_SOURCE_CONTROLLER0, + SYNC_SOURCE_CONTROLLER1, + SYNC_SOURCE_CONTROLLER2, + SYNC_SOURCE_CONTROLLER3, + SYNC_SOURCE_CONTROLLER4, + SYNC_SOURCE_CONTROLLER5, + + /* Source based on GSL group */ + SYNC_SOURCE_GSL_GROUP0, + SYNC_SOURCE_GSL_GROUP1, + SYNC_SOURCE_GSL_GROUP2, + + /* Source based on GSL IOs */ + /* These IOs normally used as GSL input/output */ + SYNC_SOURCE_GSL_IO_FIRST, + SYNC_SOURCE_GSL_IO_GENLOCK_CLOCK = SYNC_SOURCE_GSL_IO_FIRST, + SYNC_SOURCE_GSL_IO_GENLOCK_VSYNC, + SYNC_SOURCE_GSL_IO_SWAPLOCK_A, + SYNC_SOURCE_GSL_IO_SWAPLOCK_B, + SYNC_SOURCE_GSL_IO_LAST = SYNC_SOURCE_GSL_IO_SWAPLOCK_B, + + /* Source based on regular IOs */ + SYNC_SOURCE_IO_FIRST, + SYNC_SOURCE_IO_GENERIC_A = SYNC_SOURCE_IO_FIRST, + SYNC_SOURCE_IO_GENERIC_B, + SYNC_SOURCE_IO_GENERIC_C, + SYNC_SOURCE_IO_GENERIC_D, + SYNC_SOURCE_IO_GENERIC_E, + SYNC_SOURCE_IO_GENERIC_F, + SYNC_SOURCE_IO_HPD1, + SYNC_SOURCE_IO_HPD2, + SYNC_SOURCE_IO_HSYNC_A, + SYNC_SOURCE_IO_VSYNC_A, + SYNC_SOURCE_IO_HSYNC_B, + SYNC_SOURCE_IO_VSYNC_B, + SYNC_SOURCE_IO_LAST = SYNC_SOURCE_IO_VSYNC_B, + + /* Misc. flow control sources */ + SYNC_SOURCE_DUAL_GPU_PIN +}; + + +#endif diff --git a/drivers/gpu/drm/amd/display/include/grph_object_id.h b/drivers/gpu/drm/amd/display/include/grph_object_id.h new file mode 100644 index 000000000000..e4aa4ddf9d2a --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/grph_object_id.h @@ -0,0 +1,256 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_GRPH_OBJECT_ID_H__ +#define __DAL_GRPH_OBJECT_ID_H__ + +/* Types of graphics objects */ +enum object_type { + OBJECT_TYPE_UNKNOWN = 0, + + /* Direct ATOM BIOS translation */ + OBJECT_TYPE_GPU, + OBJECT_TYPE_ENCODER, + OBJECT_TYPE_CONNECTOR, + OBJECT_TYPE_ROUTER, + OBJECT_TYPE_GENERIC, + + /* Driver specific */ + OBJECT_TYPE_AUDIO, + OBJECT_TYPE_CONTROLLER, + OBJECT_TYPE_CLOCK_SOURCE, + OBJECT_TYPE_ENGINE, + + OBJECT_TYPE_COUNT +}; + +/* Enumeration inside one type of graphics objects */ +enum object_enum_id { + ENUM_ID_UNKNOWN = 0, + ENUM_ID_1, + ENUM_ID_2, + ENUM_ID_3, + ENUM_ID_4, + ENUM_ID_5, + ENUM_ID_6, + ENUM_ID_7, + + ENUM_ID_COUNT +}; + +/* Generic object ids */ +enum generic_id { + GENERIC_ID_UNKNOWN = 0, + GENERIC_ID_MXM_OPM, + GENERIC_ID_GLSYNC, + GENERIC_ID_STEREO, + + GENERIC_ID_COUNT +}; + +/* Controller object ids */ +enum controller_id { + CONTROLLER_ID_UNDEFINED = 0, + CONTROLLER_ID_D0, + CONTROLLER_ID_D1, + CONTROLLER_ID_D2, + CONTROLLER_ID_D3, + CONTROLLER_ID_D4, + CONTROLLER_ID_D5, + CONTROLLER_ID_UNDERLAY0, + CONTROLLER_ID_MAX = CONTROLLER_ID_UNDERLAY0 +}; + +#define IS_UNDERLAY_CONTROLLER(ctrlr_id) (ctrlr_id >= CONTROLLER_ID_UNDERLAY0) + +/* + * ClockSource object ids. + * We maintain the order matching (more or less) ATOM BIOS + * to improve optimized acquire + */ +enum clock_source_id { + CLOCK_SOURCE_ID_UNDEFINED = 0, + CLOCK_SOURCE_ID_PLL0, + CLOCK_SOURCE_ID_PLL1, + CLOCK_SOURCE_ID_PLL2, + CLOCK_SOURCE_ID_EXTERNAL, /* ID (Phy) ref. clk. for DP */ + CLOCK_SOURCE_ID_DCPLL, + CLOCK_SOURCE_ID_DFS, /* DENTIST */ + CLOCK_SOURCE_ID_VCE, /* VCE does not need a real PLL */ + /* Used to distinguish between programming pixel clock and ID (Phy) clock */ + CLOCK_SOURCE_ID_DP_DTO, + + CLOCK_SOURCE_COMBO_PHY_PLL0, /*combo PHY PLL defines (DC 11.2 and up)*/ + CLOCK_SOURCE_COMBO_PHY_PLL1, + CLOCK_SOURCE_COMBO_PHY_PLL2, + CLOCK_SOURCE_COMBO_PHY_PLL3, + CLOCK_SOURCE_COMBO_PHY_PLL4, + CLOCK_SOURCE_COMBO_PHY_PLL5, + CLOCK_SOURCE_COMBO_DISPLAY_PLL0 +}; + +/* Encoder object ids */ +enum encoder_id { + ENCODER_ID_UNKNOWN = 0, + + /* Radeon Class Display Hardware */ + ENCODER_ID_INTERNAL_LVDS, + ENCODER_ID_INTERNAL_TMDS1, + ENCODER_ID_INTERNAL_TMDS2, + ENCODER_ID_INTERNAL_DAC1, + ENCODER_ID_INTERNAL_DAC2, /* TV/CV DAC */ + + /* External Third Party Encoders */ + ENCODER_ID_INTERNAL_LVTM1, /* not used for Radeon */ + ENCODER_ID_INTERNAL_HDMI, + + /* Kaledisope (KLDSCP) Class Display Hardware */ + ENCODER_ID_INTERNAL_KLDSCP_TMDS1, + ENCODER_ID_INTERNAL_KLDSCP_DAC1, + ENCODER_ID_INTERNAL_KLDSCP_DAC2, /* Shared with CV/TV and CRT */ + /* External TMDS (dual link) */ + ENCODER_ID_EXTERNAL_MVPU_FPGA, /* MVPU FPGA chip */ + ENCODER_ID_INTERNAL_DDI, + ENCODER_ID_INTERNAL_UNIPHY, + ENCODER_ID_INTERNAL_KLDSCP_LVTMA, + ENCODER_ID_INTERNAL_UNIPHY1, + ENCODER_ID_INTERNAL_UNIPHY2, + ENCODER_ID_EXTERNAL_NUTMEG, + ENCODER_ID_EXTERNAL_TRAVIS, + + ENCODER_ID_INTERNAL_WIRELESS, /* Internal wireless display encoder */ + ENCODER_ID_INTERNAL_UNIPHY3, + ENCODER_ID_INTERNAL_VIRTUAL, +}; + +/* Connector object ids */ +enum connector_id { + CONNECTOR_ID_UNKNOWN = 0, + CONNECTOR_ID_SINGLE_LINK_DVII = 1, + CONNECTOR_ID_DUAL_LINK_DVII = 2, + CONNECTOR_ID_SINGLE_LINK_DVID = 3, + CONNECTOR_ID_DUAL_LINK_DVID = 4, + CONNECTOR_ID_VGA = 5, + CONNECTOR_ID_HDMI_TYPE_A = 12, + CONNECTOR_ID_LVDS = 14, + CONNECTOR_ID_PCIE = 16, + CONNECTOR_ID_HARDCODE_DVI = 18, + CONNECTOR_ID_DISPLAY_PORT = 19, + CONNECTOR_ID_EDP = 20, + CONNECTOR_ID_MXM = 21, + CONNECTOR_ID_WIRELESS = 22, + CONNECTOR_ID_MIRACAST = 23, + + CONNECTOR_ID_VIRTUAL = 100 +}; + +/* Audio object ids */ +enum audio_id { + AUDIO_ID_UNKNOWN = 0, + AUDIO_ID_INTERNAL_AZALIA +}; + +/* Engine object ids */ +enum engine_id { + ENGINE_ID_DIGA, + ENGINE_ID_DIGB, + ENGINE_ID_DIGC, + ENGINE_ID_DIGD, + ENGINE_ID_DIGE, + ENGINE_ID_DIGF, + ENGINE_ID_DIGG, + ENGINE_ID_DACA, + ENGINE_ID_DACB, + ENGINE_ID_VCE, /* wireless display pseudo-encoder */ + ENGINE_ID_VIRTUAL, + + ENGINE_ID_COUNT, + ENGINE_ID_UNKNOWN = (-1L) +}; + +enum transmitter_color_depth { + TRANSMITTER_COLOR_DEPTH_24 = 0, /* 8 bits */ + TRANSMITTER_COLOR_DEPTH_30, /* 10 bits */ + TRANSMITTER_COLOR_DEPTH_36, /* 12 bits */ + TRANSMITTER_COLOR_DEPTH_48 /* 16 bits */ +}; + +/* + ***************************************************************************** + * graphics_object_id struct + * + * graphics_object_id is a very simple struct wrapping 32bit Graphics + * Object identication + * + * This struct should stay very simple + * No dependencies at all (no includes) + * No debug messages or asserts + * No #ifndef and preprocessor directives + * No grow in space (no more data member) + ***************************************************************************** + */ + +struct graphics_object_id { + uint32_t id:8; + uint32_t enum_id:4; + uint32_t type:4; + uint32_t reserved:16; /* for padding. total size should be u32 */ +}; + +/* some simple functions for convenient graphics_object_id handle */ + +static inline struct graphics_object_id dal_graphics_object_id_init( + uint32_t id, + enum object_enum_id enum_id, + enum object_type type) +{ + struct graphics_object_id result = { + id, enum_id, type, 0 + }; + + return result; +} + +bool dal_graphics_object_id_is_valid( + struct graphics_object_id id); +bool dal_graphics_object_id_is_equal( + struct graphics_object_id id1, + struct graphics_object_id id2); +uint32_t dal_graphics_object_id_to_uint( + struct graphics_object_id id); + +enum controller_id dal_graphics_object_id_get_controller_id( + struct graphics_object_id id); +enum clock_source_id dal_graphics_object_id_get_clock_source_id( + struct graphics_object_id id); +enum encoder_id dal_graphics_object_id_get_encoder_id( + struct graphics_object_id id); +enum connector_id dal_graphics_object_id_get_connector_id( + struct graphics_object_id id); +enum audio_id dal_graphics_object_id_get_audio_id( + struct graphics_object_id id); +enum engine_id dal_graphics_object_id_get_engine_id( + struct graphics_object_id id); +#endif diff --git a/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h b/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h new file mode 100644 index 000000000000..9a78097e70f3 --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h @@ -0,0 +1,105 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_HW_SEQUENCER_TYPES_H__ +#define __DAL_HW_SEQUENCER_TYPES_H__ + +#include "signal_types.h" +#include "grph_object_defs.h" +#include "link_service_types.h" + +/* define the structure of Dynamic Refresh Mode */ +struct drr_params { + /* defines the minimum possible vertical dimension of display timing + * for CRTC as supported by the panel */ + uint32_t vertical_total_min; + /* defines the maximum possible vertical dimension of display timing + * for CRTC as supported by the panel */ + uint32_t vertical_total_max; +}; + +/* CRTC timing structure */ +struct hw_crtc_timing { + uint32_t h_total; + uint32_t h_addressable; + uint32_t h_overscan_left; + uint32_t h_overscan_right; + uint32_t h_sync_start; + uint32_t h_sync_width; + + uint32_t v_total; + uint32_t v_addressable; + uint32_t v_overscan_top; + uint32_t v_overscan_bottom; + uint32_t v_sync_start; + uint32_t v_sync_width; + + /* in KHz */ + uint32_t pixel_clock; + + struct { + uint32_t INTERLACED:1; + uint32_t DOUBLESCAN:1; + uint32_t PIXEL_REPETITION:4; /* 1...10 */ + uint32_t HSYNC_POSITIVE_POLARITY:1; + uint32_t VSYNC_POSITIVE_POLARITY:1; + /* frame should be packed for 3D + * (currently this refers to HDMI 1.4a FramePacking format */ + uint32_t HORZ_COUNT_BY_TWO:1; + uint32_t PACK_3D_FRAME:1; + /* 0 - left eye polarity, 1 - right eye polarity */ + uint32_t RIGHT_EYE_3D_POLARITY:1; + /* DVI-DL High-Color mode */ + uint32_t HIGH_COLOR_DL_MODE:1; + uint32_t Y_ONLY:1; + /* HDMI 2.0 - Support scrambling for TMDS character + * rates less than or equal to 340Mcsc */ + uint32_t LTE_340MCSC_SCRAMBLE:1; + } flags; +}; + +/* TODO hw_info_frame and hw_info_packet structures are same as in encoder + * merge it*/ +struct hw_info_packet { + bool valid; + uint8_t hb0; + uint8_t hb1; + uint8_t hb2; + uint8_t hb3; + uint8_t sb[28]; +}; + +struct hw_info_frame { + /* Auxiliary Video Information */ + struct hw_info_packet avi_info_packet; + struct hw_info_packet gamut_packet; + struct hw_info_packet vendor_info_packet; + /* Source Product Description */ + struct hw_info_packet spd_packet; + /* Video Stream Configuration */ + struct hw_info_packet vsc_packet; +}; + +#endif diff --git a/drivers/gpu/drm/amd/display/include/i2caux_interface.h b/drivers/gpu/drm/amd/display/include/i2caux_interface.h new file mode 100644 index 000000000000..d2ec04d1c592 --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/i2caux_interface.h @@ -0,0 +1,89 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_I2CAUX_INTERFACE_H__ +#define __DAL_I2CAUX_INTERFACE_H__ + +#include "gpio_service_interface.h" + + +#define DEFAULT_AUX_MAX_DATA_SIZE 16 +#define AUX_MAX_DEFER_WRITE_RETRY 20 + +struct aux_payload { + /* set following flag to read/write I2C data, + * reset it to read/write DPCD data */ + bool i2c_over_aux; + /* set following flag to write data, + * reset it to read data */ + bool write; + uint32_t address; + uint8_t length; + uint8_t *data; +}; + +struct aux_command { + struct aux_payload *payloads; + uint8_t number_of_payloads; + + /* expressed in milliseconds + * zero means "use default value" */ + uint32_t defer_delay; + + /* zero means "use default value" */ + uint32_t max_defer_write_retry; +}; + +union aux_config { + struct { + uint32_t ALLOW_AUX_WHEN_HPD_LOW:1; + } bits; + uint32_t raw; +}; + +struct i2caux; + +struct i2caux *dal_i2caux_create( + struct dc_context *ctx); + +bool dal_i2caux_submit_i2c_command( + struct i2caux *i2caux, + struct ddc *ddc, + struct i2c_command *cmd); + +bool dal_i2caux_submit_aux_command( + struct i2caux *i2caux, + struct ddc *ddc, + struct aux_command *cmd); + +void dal_i2caux_configure_aux( + struct i2caux *i2caux, + struct ddc *ddc, + union aux_config cfg); + +void dal_i2caux_destroy( + struct i2caux **ptr); + +#endif diff --git a/drivers/gpu/drm/amd/display/include/irq_interface.h b/drivers/gpu/drm/amd/display/include/irq_interface.h new file mode 100644 index 000000000000..077ded3fbedd --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/irq_interface.h @@ -0,0 +1,31 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_IRQ_INTERFACE_H__ +#define __DAL_IRQ_INTERFACE_H__ + +#include "gpio_types.h" + +#endif diff --git a/drivers/gpu/drm/amd/display/include/irq_service_interface.h b/drivers/gpu/drm/amd/display/include/irq_service_interface.h new file mode 100644 index 000000000000..d6ebed524daf --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/irq_service_interface.h @@ -0,0 +1,51 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_IRQ_SERVICE_INTERFACE_H__ +#define __DAL_IRQ_SERVICE_INTERFACE_H__ + +struct irq_service_init_data { + struct dc_context *ctx; +}; + +struct irq_service; + +void dal_irq_service_destroy(struct irq_service **irq_service); + +bool dal_irq_service_set( + struct irq_service *irq_service, + enum dc_irq_source source, + bool enable); + +bool dal_irq_service_ack( + struct irq_service *irq_service, + enum dc_irq_source source); + +enum dc_irq_source dal_irq_service_to_irq_source( + struct irq_service *irq_service, + uint32_t src_id, + uint32_t ext_id); + +#endif diff --git a/drivers/gpu/drm/amd/display/include/link_service_types.h b/drivers/gpu/drm/amd/display/include/link_service_types.h new file mode 100644 index 000000000000..06e68426d430 --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/link_service_types.h @@ -0,0 +1,232 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_LINK_SERVICE_TYPES_H__ +#define __DAL_LINK_SERVICE_TYPES_H__ + +#include "grph_object_id.h" +#include "dpcd_defs.h" +#include "dal_types.h" +#include "irq_types.h" + +/*struct mst_mgr_callback_object;*/ +struct ddc; +struct irq_manager; + +enum { + MAX_CONTROLLER_NUM = 6 +}; + +enum link_service_type { + LINK_SERVICE_TYPE_LEGACY = 0, + LINK_SERVICE_TYPE_DP_SST, + LINK_SERVICE_TYPE_DP_MST, + LINK_SERVICE_TYPE_MAX +}; + +enum dpcd_value_mask { + DPCD_VALUE_MASK_MAX_LANE_COUNT_LANE_COUNT = 0x1F, + DPCD_VALUE_MASK_MAX_LANE_COUNT_TPS3_SUPPORTED = 0x40, + DPCD_VALUE_MASK_MAX_LANE_COUNT_ENHANCED_FRAME_EN = 0x80, + DPCD_VALUE_MASK_MAX_DOWNSPREAD = 0x01, + DPCD_VALUE_MASK_LANE_ALIGN_STATUS_INTERLANE_ALIGN_DONE = 0x01 +}; + +enum dp_power_state { + DP_POWER_STATE_D0 = 1, + DP_POWER_STATE_D3 +}; + +enum dpcd_downstream_port_types { + DPCD_DOWNSTREAM_DP, + DPCD_DOWNSTREAM_VGA, + DPCD_DOWNSTREAM_DVI_HDMI, + /* has no EDID (TV, CV) */ + DPCD_DOWNSTREAM_NON_DDC +}; + +enum edp_revision { + /* eDP version 1.1 or lower */ + EDP_REVISION_11 = 0x00, + /* eDP version 1.2 */ + EDP_REVISION_12 = 0x01, + /* eDP version 1.3 */ + EDP_REVISION_13 = 0x02 +}; + +enum { + LINK_RATE_REF_FREQ_IN_KHZ = 27000 /*27MHz*/ +}; + +struct link_training_settings { + struct dc_link_settings link_settings; + struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]; + bool allow_invalid_msa_timing_param; +}; + +enum hw_dp_training_pattern { + HW_DP_TRAINING_PATTERN_1 = 0, + HW_DP_TRAINING_PATTERN_2, + HW_DP_TRAINING_PATTERN_3, + HW_DP_TRAINING_PATTERN_4 +}; + +/*TODO: Move this enum test harness*/ +/* Test patterns*/ +enum dp_test_pattern { + /* Input data is pass through Scrambler + * and 8b10b Encoder straight to output*/ + DP_TEST_PATTERN_VIDEO_MODE = 0, + /* phy test patterns*/ + DP_TEST_PATTERN_D102, + DP_TEST_PATTERN_SYMBOL_ERROR, + DP_TEST_PATTERN_PRBS7, + + DP_TEST_PATTERN_80BIT_CUSTOM, + DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE, + + /* Link Training Patterns */ + DP_TEST_PATTERN_TRAINING_PATTERN1, + DP_TEST_PATTERN_TRAINING_PATTERN2, + DP_TEST_PATTERN_TRAINING_PATTERN3, + DP_TEST_PATTERN_TRAINING_PATTERN4, + + /* link test patterns*/ + DP_TEST_PATTERN_COLOR_SQUARES, + DP_TEST_PATTERN_COLOR_SQUARES_CEA, + DP_TEST_PATTERN_VERTICAL_BARS, + DP_TEST_PATTERN_HORIZONTAL_BARS, + DP_TEST_PATTERN_COLOR_RAMP, + + /* audio test patterns*/ + DP_TEST_PATTERN_AUDIO_OPERATOR_DEFINED, + DP_TEST_PATTERN_AUDIO_SAWTOOTH, + + DP_TEST_PATTERN_UNSUPPORTED +}; + +enum dp_panel_mode { + /* not required */ + DP_PANEL_MODE_DEFAULT, + /* standard mode for eDP */ + DP_PANEL_MODE_EDP, + /* external chips specific settings */ + DP_PANEL_MODE_SPECIAL +}; + +/** + * @brief LinkServiceInitOptions to set certain bits + */ +struct link_service_init_options { + uint32_t APPLY_MISALIGNMENT_BUG_WORKAROUND:1; +}; + +/** + * @brief data required to initialize LinkService + */ +struct link_service_init_data { + /* number of displays indices which the MST Mgr would manange*/ + uint32_t num_of_displays; + enum link_service_type link_type; + /*struct mst_mgr_callback_object*topology_change_callback;*/ + /* native aux access */ + struct ddc_service *dpcd_access_srv; + /* for calling HWSS to program HW */ + struct hw_sequencer *hwss; + /* the source which to register IRQ on */ + enum dc_irq_source irq_src_hpd_rx; + enum dc_irq_source irq_src_dp_sink; + /* other init options such as SW Workarounds */ + struct link_service_init_options init_options; + uint32_t connector_enum_id; + struct graphics_object_id connector_id; + struct dc_context *ctx; + struct topology_mgr *tm; +}; + +/* DPCD_ADDR_TRAINING_LANEx_SET registers value */ +union dpcd_training_lane_set { + struct { +#if defined(LITTLEENDIAN_CPU) + uint8_t VOLTAGE_SWING_SET:2; + uint8_t MAX_SWING_REACHED:1; + uint8_t PRE_EMPHASIS_SET:2; + uint8_t MAX_PRE_EMPHASIS_REACHED:1; + /* following is reserved in DP 1.1 */ + uint8_t POST_CURSOR2_SET:2; +#elif defined(BIGENDIAN_CPU) + uint8_t POST_CURSOR2_SET:2; + uint8_t MAX_PRE_EMPHASIS_REACHED:1; + uint8_t PRE_EMPHASIS_SET:2; + uint8_t MAX_SWING_REACHED:1; + uint8_t VOLTAGE_SWING_SET:2; +#else + #error ARCH not defined! +#endif + } bits; + + uint8_t raw; +}; + +/** + * @brief represent the 16 byte + * global unique identifier + */ +struct mst_guid { + uint8_t ids[16]; +}; + +/** + * @brief represents the relative address used + * to identify a node in MST topology network + */ +struct mst_rad { + /* number of links. rad[0] up to + * rad [linkCount - 1] are valid. */ + uint32_t rad_link_count; + /* relative address. rad[0] is the + * first device connected to the source. */ + uint8_t rad[15]; + /* extra 10 bytes for underscores; for e.g.:2_1_8*/ + int8_t rad_str[25]; +}; + +/* DP MST stream allocation (payload bandwidth number) */ +struct dp_mst_stream_allocation { + uint8_t vcp_id; + /* number of slots required for the DP stream in + * transport packet */ + uint8_t slot_count; +}; + +/* DP MST stream allocation table */ +struct dp_mst_stream_allocation_table { + /* number of DP video streams */ + int stream_count; + /* array of stream allocations */ + struct dp_mst_stream_allocation stream_allocations[MAX_CONTROLLER_NUM]; +}; + +#endif /*__DAL_LINK_SERVICE_TYPES_H__*/ diff --git a/drivers/gpu/drm/amd/display/include/logger_interface.h b/drivers/gpu/drm/amd/display/include/logger_interface.h new file mode 100644 index 000000000000..b58d30de8293 --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/logger_interface.h @@ -0,0 +1,140 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_LOGGER_INTERFACE_H__ +#define __DAL_LOGGER_INTERFACE_H__ + +#include "logger_types.h" + +struct dc_context; +struct dc_link; +struct dc_surface_update; + +/* + * + * DAL logger functionality + * + */ + +struct dal_logger *dal_logger_create(struct dc_context *ctx); + +uint32_t dal_logger_destroy(struct dal_logger **logger); + +void dm_logger_write( + struct dal_logger *logger, + enum dc_log_type log_type, + const char *msg, + ...); + +void dm_logger_append( + struct log_entry *entry, + const char *msg, + ...); + +void dm_logger_open( + struct dal_logger *logger, + struct log_entry *entry, + enum dc_log_type log_type); + +void dm_logger_close(struct log_entry *entry); + +void dc_conn_log(struct dc_context *ctx, + const struct dc_link *link, + uint8_t *hex_data, + int hex_data_count, + enum dc_log_type event, + const char *msg, + ...); + +void logger_write(struct dal_logger *logger, + enum dc_log_type log_type, + const char *msg, + void *paralist); + +void pre_surface_trace( + const struct dc *dc, + const struct dc_surface *const *surfaces, + int surface_count); + +void update_surface_trace( + const struct dc *dc, + const struct dc_surface_update *updates, + int surface_count); + +void post_surface_trace(const struct dc *dc); + + +/* Any function which is empty or have incomplete implementation should be + * marked by this macro. + * Note that the message will be printed exactly once for every function + * it is used in order to avoid repeating of the same message. */ +#define DAL_LOGGER_NOT_IMPL(fmt, ...) \ +{ \ + static bool print_not_impl = true; \ +\ + if (print_not_impl == true) { \ + print_not_impl = false; \ + dm_logger_write(ctx->logger, LOG_WARNING, \ + "DAL_NOT_IMPL: " fmt, ##__VA_ARGS__); \ + } \ +} + +/****************************************************************************** + * Convenience macros to save on typing. + *****************************************************************************/ + +#define DC_ERROR(...) \ + dm_logger_write(dc_ctx->logger, LOG_ERROR, \ + __VA_ARGS__); + +#define DC_SYNC_INFO(...) \ + dm_logger_write(dc_ctx->logger, LOG_SYNC, \ + __VA_ARGS__); + + +/* Connectivity log format: + * [time stamp] [drm] [Major_minor] [connector name] message..... + * eg: + * [ 26.590965] [drm] [Conn_LKTN] [DP-1] HBRx4 pass VS=0, PE=0^ + * [ 26.881060] [drm] [Conn_Mode] [DP-1] {2560x1080, 2784x1111@185580Khz}^ + */ + +#define CONN_DATA_DETECT(link, hex_data, hex_len, ...) \ + dc_conn_log(link->ctx, &link->public, hex_data, hex_len, \ + LOG_EVENT_DETECTION, ##__VA_ARGS__) + +#define CONN_DATA_LINK_LOSS(link, hex_data, hex_len, ...) \ + dc_conn_log(link->ctx, &link->public, hex_data, hex_len, \ + LOG_EVENT_LINK_LOSS, ##__VA_ARGS__) + +#define CONN_MSG_LT(link, ...) \ + dc_conn_log(link->ctx, &link->public, NULL, 0, \ + LOG_EVENT_LINK_TRAINING, ##__VA_ARGS__) + +#define CONN_MSG_MODE(link, ...) \ + dc_conn_log(link->ctx, &link->public, NULL, 0, \ + LOG_EVENT_MODE_SET, ##__VA_ARGS__) + +#endif /* __DAL_LOGGER_INTERFACE_H__ */ diff --git a/drivers/gpu/drm/amd/display/include/logger_types.h b/drivers/gpu/drm/amd/display/include/logger_types.h new file mode 100644 index 000000000000..babd6523b105 --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/logger_types.h @@ -0,0 +1,95 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_LOGGER_TYPES_H__ +#define __DAL_LOGGER_TYPES_H__ + +#include "os_types.h" + +#define MAX_NAME_LEN 32 + +struct dal_logger; + +enum dc_log_type { + LOG_ERROR = 0, + LOG_WARNING, + LOG_DC, + LOG_SURFACE, + LOG_HW_HOTPLUG, + LOG_HW_LINK_TRAINING, + LOG_HW_SET_MODE, + LOG_HW_RESUME_S3, + LOG_HW_AUDIO, + LOG_HW_HPD_IRQ, + LOG_MST, + LOG_SCALER, + LOG_BIOS, + LOG_BANDWIDTH_CALCS, + LOG_BANDWIDTH_VALIDATION, + LOG_I2C_AUX, + LOG_SYNC, + LOG_BACKLIGHT, + LOG_FEATURE_OVERRIDE, + LOG_DETECTION_EDID_PARSER, + LOG_DETECTION_DP_CAPS, + LOG_RESOURCE, + LOG_DML, + LOG_EVENT_MODE_SET, + LOG_EVENT_DETECTION, + LOG_EVENT_LINK_TRAINING, + LOG_EVENT_LINK_LOSS, + LOG_EVENT_UNDERFLOW, + LOG_IF_TRACE, + + LOG_SECTION_TOTAL_COUNT +}; + +union logger_flags { + struct { + uint32_t ENABLE_CONSOLE:1; /* Print to console */ + uint32_t ENABLE_BUFFER:1; /* Print to buffer */ + uint32_t RESERVED:30; + } bits; + uint32_t value; +}; + +struct log_entry { + struct dal_logger *logger; + enum dc_log_type type; + + char *buf; + uint32_t buf_offset; + uint32_t max_buf_bytes; +}; + +/** +* Structure for enumerating log types +*/ +struct dc_log_type_info { + enum dc_log_type type; + char name[MAX_NAME_LEN]; +}; + +#endif /* __DAL_LOGGER_TYPES_H__ */ diff --git a/drivers/gpu/drm/amd/display/include/set_mode_types.h b/drivers/gpu/drm/amd/display/include/set_mode_types.h new file mode 100644 index 000000000000..d18210ff5b7a --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/set_mode_types.h @@ -0,0 +1,127 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_SET_MODE_TYPES_H__ +#define __DAL_SET_MODE_TYPES_H__ + +#include "dc_types.h" + +/* Info frame packet status */ +enum info_frame_flag { + INFO_PACKET_PACKET_INVALID = 0, + INFO_PACKET_PACKET_VALID = 1, + INFO_PACKET_PACKET_RESET = 2, + INFO_PACKET_PACKET_UPDATE_SCAN_TYPE = 8 +}; + +/* Info frame types */ +enum info_frame_type { + INFO_FRAME_GAMUT = 0x0A, + INFO_FRAME_VENDOR_INFO = 0x81, + INFO_FRAME_AVI = 0x82 +}; + +/* Info frame versions */ +enum info_frame_version { + INFO_FRAME_VERSION_1 = 1, + INFO_FRAME_VERSION_2 = 2, + INFO_FRAME_VERSION_3 = 3 +}; + +/* Info frame size */ +enum info_frame_size { + INFO_FRAME_SIZE_AVI = 13, + INFO_FRAME_SIZE_VENDOR = 25, + INFO_FRAME_SIZE_AUDIO = 10 +}; + +struct hdmi_info_frame_header { + uint8_t info_frame_type; + uint8_t version; + uint8_t length; +}; + +#pragma pack(push) +#pragma pack(1) + +struct info_packet_raw_data { + uint8_t hb0; + uint8_t hb1; + uint8_t hb2; + uint8_t sb[28]; /* sb0~sb27 */ +}; + +union hdmi_info_packet { + struct avi_info_frame { + struct hdmi_info_frame_header header; + + uint8_t CHECK_SUM:8; + + uint8_t S0_S1:2; + uint8_t B0_B1:2; + uint8_t A0:1; + uint8_t Y0_Y1_Y2:3; + + uint8_t R0_R3:4; + uint8_t M0_M1:2; + uint8_t C0_C1:2; + + uint8_t SC0_SC1:2; + uint8_t Q0_Q1:2; + uint8_t EC0_EC2:3; + uint8_t ITC:1; + + uint8_t VIC0_VIC7:8; + + uint8_t PR0_PR3:4; + uint8_t CN0_CN1:2; + uint8_t YQ0_YQ1:2; + + uint16_t bar_top; + uint16_t bar_bottom; + uint16_t bar_left; + uint16_t bar_right; + + uint8_t reserved[14]; + } bits; + + struct info_packet_raw_data packet_raw_data; +}; + +struct info_packet { + enum info_frame_flag flags; + union hdmi_info_packet info_packet_hdmi; +}; + +struct info_frame { + struct info_packet avi_info_packet; + struct info_packet gamut_packet; + struct info_packet vendor_info_packet; + struct info_packet spd_info_packet; +}; + +#pragma pack(pop) + +#endif /* __DAL_SET_MODE_TYPES_H__ */ diff --git a/drivers/gpu/drm/amd/display/include/signal_types.h b/drivers/gpu/drm/amd/display/include/signal_types.h new file mode 100644 index 000000000000..a50f7ed74a33 --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/signal_types.h @@ -0,0 +1,59 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_SIGNAL_TYPES_H__ +#define __DC_SIGNAL_TYPES_H__ + +enum signal_type { + SIGNAL_TYPE_NONE = 0L, /* no signal */ + SIGNAL_TYPE_DVI_SINGLE_LINK = (1 << 0), + SIGNAL_TYPE_DVI_DUAL_LINK = (1 << 1), + SIGNAL_TYPE_HDMI_TYPE_A = (1 << 2), + SIGNAL_TYPE_LVDS = (1 << 3), + SIGNAL_TYPE_RGB = (1 << 4), + SIGNAL_TYPE_DISPLAY_PORT = (1 << 5), + SIGNAL_TYPE_DISPLAY_PORT_MST = (1 << 6), + SIGNAL_TYPE_EDP = (1 << 7), + SIGNAL_TYPE_WIRELESS = (1 << 8), /* Wireless Display */ + SIGNAL_TYPE_VIRTUAL = (1 << 9), /* Virtual Display */ + + SIGNAL_TYPE_COUNT = 10, + SIGNAL_TYPE_ALL = (1 << SIGNAL_TYPE_COUNT) - 1 +}; + +/* help functions for signal types manipulation */ +bool dc_is_hdmi_signal(enum signal_type signal); +bool dc_is_dp_sst_signal(enum signal_type signal); +bool dc_is_dp_signal(enum signal_type signal); +bool dc_is_dp_external_signal(enum signal_type signal); +bool dc_is_analog_signal(enum signal_type signal); +bool dc_is_embedded_signal(enum signal_type signal); +bool dc_is_dvi_signal(enum signal_type signal); +bool dc_is_dvi_single_link_signal(enum signal_type signal); +bool dc_is_dual_link_signal(enum signal_type signal); +bool dc_is_audio_capable_signal(enum signal_type signal); +bool dc_is_digital_encoder_compatible_signal(enum signal_type signal); + +#endif diff --git a/drivers/gpu/drm/amd/display/include/vector.h b/drivers/gpu/drm/amd/display/include/vector.h new file mode 100644 index 000000000000..8233b7c22a07 --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/vector.h @@ -0,0 +1,150 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_VECTOR_H__ +#define __DAL_VECTOR_H__ + +struct vector { + uint8_t *container; + uint32_t struct_size; + uint32_t count; + uint32_t capacity; + struct dc_context *ctx; +}; + +bool dal_vector_construct( + struct vector *vector, + struct dc_context *ctx, + uint32_t capacity, + uint32_t struct_size); + +struct vector *dal_vector_create( + struct dc_context *ctx, + uint32_t capacity, + uint32_t struct_size); + +/* 'initial_value' is optional. If initial_value not supplied, + * each "structure" in the vector will contain zeros by default. */ +struct vector *dal_vector_presized_create( + struct dc_context *ctx, + uint32_t size, + void *initial_value, + uint32_t struct_size); + +void dal_vector_destruct( + struct vector *vector); + +void dal_vector_destroy( + struct vector **vector); + +uint32_t dal_vector_get_count( + const struct vector *vector); + +/* dal_vector_insert_at + * reallocate container if necessary + * then shell items at right and insert + * return if the container modified + * do not check that index belongs to container + * since the function is private and index is going to be calculated + * either with by function or as get_count+1 */ +bool dal_vector_insert_at( + struct vector *vector, + const void *what, + uint32_t position); + +bool dal_vector_append( + struct vector *vector, + const void *item); + +/* operator[] */ +void *dal_vector_at_index( + const struct vector *vector, + uint32_t index); + +void dal_vector_set_at_index( + const struct vector *vector, + const void *what, + uint32_t index); + +/* create a clone (copy) of a vector */ +struct vector *dal_vector_clone( + const struct vector *vector_other); + +/* dal_vector_remove_at_index + * Shifts elements on the right from remove position to the left, + * removing an element at position by overwrite means*/ +bool dal_vector_remove_at_index( + struct vector *vector, + uint32_t index); + +uint32_t dal_vector_capacity(const struct vector *vector); + +bool dal_vector_reserve(struct vector *vector, uint32_t capacity); + +void dal_vector_clear(struct vector *vector); + +/*************************************************************************** + * Macro definitions of TYPE-SAFE versions of vector set/get functions. + ***************************************************************************/ + +#define DAL_VECTOR_INSERT_AT(vector_type, type_t) \ + static bool vector_type##_vector_insert_at( \ + struct vector *vector, \ + type_t what, \ + uint32_t position) \ +{ \ + return dal_vector_insert_at(vector, what, position); \ +} + +#define DAL_VECTOR_APPEND(vector_type, type_t) \ + static bool vector_type##_vector_append( \ + struct vector *vector, \ + type_t item) \ +{ \ + return dal_vector_append(vector, item); \ +} + +/* Note: "type_t" is the ONLY token accepted by "checkpatch.pl" and by + * "checkcommit" as *return type*. + * For uniformity reasons "type_t" is used for all type-safe macro + * definitions here. */ +#define DAL_VECTOR_AT_INDEX(vector_type, type_t) \ + static type_t vector_type##_vector_at_index( \ + const struct vector *vector, \ + uint32_t index) \ +{ \ + return dal_vector_at_index(vector, index); \ +} + +#define DAL_VECTOR_SET_AT_INDEX(vector_type, type_t) \ + static void vector_type##_vector_set_at_index( \ + const struct vector *vector, \ + type_t what, \ + uint32_t index) \ +{ \ + dal_vector_set_at_index(vector, what, index); \ +} + +#endif /* __DAL_VECTOR_H__ */ diff --git a/drivers/gpu/drm/amd/display/modules/color/color.c b/drivers/gpu/drm/amd/display/modules/color/color.c new file mode 100644 index 000000000000..cf030b18f6a9 --- /dev/null +++ b/drivers/gpu/drm/amd/display/modules/color/color.c @@ -0,0 +1,2094 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "dc.h" +#include "mod_color.h" +#include "core_types.h" +#include "fixed31_32.h" +#include "core_dc.h" + +#define MOD_COLOR_MAX_CONCURRENT_SINKS 32 +#define DIVIDER 10000 +/* S2D13 value in [-3.00...0.9999] */ +#define S2D13_MIN (-3 * DIVIDER) +#define S2D13_MAX (3 * DIVIDER) +#define S0D13_MIN (-1 * DIVIDER) +#define S0D13_MAX (1 * DIVIDER) + +struct sink_caps { + const struct dc_sink *sink; +}; + +struct gamut_calculation_matrix { + struct fixed31_32 MTransposed[9]; + struct fixed31_32 XYZtoRGB_Custom[9]; + struct fixed31_32 XYZtoRGB_Ref[9]; + struct fixed31_32 RGBtoXYZ_Final[9]; + + struct fixed31_32 MResult[9]; + struct fixed31_32 fXYZofWhiteRef[9]; + struct fixed31_32 fXYZofRGBRef[9]; +}; + +struct gamut_src_dst_matrix { + struct fixed31_32 rgbCoeffDst[9]; + struct fixed31_32 whiteCoeffDst[3]; + struct fixed31_32 rgbCoeffSrc[9]; + struct fixed31_32 whiteCoeffSrc[3]; +}; + +struct color_state { + bool user_enable_color_temperature; + int custom_color_temperature; + struct color_space_coordinates source_gamut; + struct color_space_coordinates destination_gamut; + struct color_range contrast; + struct color_range saturation; + struct color_range brightness; + struct color_range hue; + enum dc_quantization_range preferred_quantization_range; +}; + +struct core_color { + struct mod_color public; + struct dc *dc; + int num_sinks; + struct sink_caps *caps; + struct color_state *state; +}; + +#define MOD_COLOR_TO_CORE(mod_color)\ + container_of(mod_color, struct core_color, public) + +#define COLOR_REGISTRY_NAME "color_v1" + +/*Matrix Calculation Functions*/ +/** + ***************************************************************************** + * Function: transposeMatrix + * + * @brief + * rotate the matrix 90 degrees clockwise + * rows become a columns and columns to rows + * @param [ in ] M - source matrix + * @param [ in ] Rows - num of Rows of the original matrix + * @param [ in ] Cols - num of Cols of the original matrix + * @param [ out] MTransposed - result matrix + * @return void + * + ***************************************************************************** + */ +static void transpose_matrix(const struct fixed31_32 *M, unsigned int Rows, + unsigned int Cols, struct fixed31_32 *MTransposed) +{ + unsigned int i, j; + + for (i = 0; i < Rows; i++) { + for (j = 0; j < Cols; j++) + MTransposed[(j*Rows)+i] = M[(i*Cols)+j]; + } +} + +/** + ***************************************************************************** + * Function: multiplyMatrices + * + * @brief + * multiplies produce of two matrices: M = M1[ulRows1 x ulCols1] * + * M2[ulCols1 x ulCols2]. + * + * @param [ in ] M1 - first Matrix. + * @param [ in ] M2 - second Matrix. + * @param [ in ] Rows1 - num of Rows of the first Matrix + * @param [ in ] Cols1 - num of Cols of the first Matrix/Num of Rows + * of the second Matrix + * @param [ in ] Cols2 - num of Cols of the second Matrix + * @param [out ] mResult - resulting matrix. + * @return void + * + ***************************************************************************** + */ +static void multiply_matrices(struct fixed31_32 *mResult, + const struct fixed31_32 *M1, + const struct fixed31_32 *M2, unsigned int Rows1, + unsigned int Cols1, unsigned int Cols2) +{ + unsigned int i, j, k; + + for (i = 0; i < Rows1; i++) { + for (j = 0; j < Cols2; j++) { + mResult[(i * Cols2) + j] = dal_fixed31_32_zero; + for (k = 0; k < Cols1; k++) + mResult[(i * Cols2) + j] = + dal_fixed31_32_add + (mResult[(i * Cols2) + j], + dal_fixed31_32_mul(M1[(i * Cols1) + k], + M2[(k * Cols2) + j])); + } + } +} + +/** + ***************************************************************************** + * Function: cFind3X3Det + * + * @brief + * finds determinant of given 3x3 matrix + * + * @param [ in ] m - matrix + * @return determinate whioch could not be zero + * + ***************************************************************************** + */ +static struct fixed31_32 find_3X3_det(const struct fixed31_32 *m) +{ + struct fixed31_32 det, A1, A2, A3; + + A1 = dal_fixed31_32_mul(m[0], + dal_fixed31_32_sub(dal_fixed31_32_mul(m[4], m[8]), + dal_fixed31_32_mul(m[5], m[7]))); + A2 = dal_fixed31_32_mul(m[1], + dal_fixed31_32_sub(dal_fixed31_32_mul(m[3], m[8]), + dal_fixed31_32_mul(m[5], m[6]))); + A3 = dal_fixed31_32_mul(m[2], + dal_fixed31_32_sub(dal_fixed31_32_mul(m[3], m[7]), + dal_fixed31_32_mul(m[4], m[6]))); + det = dal_fixed31_32_add(dal_fixed31_32_sub(A1, A2), A3); + return det; +} + + +/** + ***************************************************************************** + * Function: computeInverseMatrix_3x3 + * + * @brief + * builds inverse matrix + * + * @param [ in ] m - matrix + * @param [ out ] im - result matrix + * @return true if success + * + ***************************************************************************** + */ +static bool compute_inverse_matrix_3x3(const struct fixed31_32 *m, + struct fixed31_32 *im) +{ + struct fixed31_32 determinant = find_3X3_det(m); + + if (dal_fixed31_32_eq(determinant, dal_fixed31_32_zero) == false) { + im[0] = dal_fixed31_32_div(dal_fixed31_32_sub + (dal_fixed31_32_mul(m[4], m[8]), + dal_fixed31_32_mul(m[5], m[7])), determinant); + im[1] = dal_fixed31_32_neg(dal_fixed31_32_div(dal_fixed31_32_sub + (dal_fixed31_32_mul(m[1], m[8]), + dal_fixed31_32_mul(m[2], m[7])), determinant)); + im[2] = dal_fixed31_32_div(dal_fixed31_32_sub + (dal_fixed31_32_mul(m[1], m[5]), + dal_fixed31_32_mul(m[2], m[4])), determinant); + im[3] = dal_fixed31_32_neg(dal_fixed31_32_div(dal_fixed31_32_sub + (dal_fixed31_32_mul(m[3], m[8]), + dal_fixed31_32_mul(m[5], m[6])), determinant)); + im[4] = dal_fixed31_32_div(dal_fixed31_32_sub + (dal_fixed31_32_mul(m[0], m[8]), + dal_fixed31_32_mul(m[2], m[6])), determinant); + im[5] = dal_fixed31_32_neg(dal_fixed31_32_div(dal_fixed31_32_sub + (dal_fixed31_32_mul(m[0], m[5]), + dal_fixed31_32_mul(m[2], m[3])), determinant)); + im[6] = dal_fixed31_32_div(dal_fixed31_32_sub + (dal_fixed31_32_mul(m[3], m[7]), + dal_fixed31_32_mul(m[4], m[6])), determinant); + im[7] = dal_fixed31_32_neg(dal_fixed31_32_div(dal_fixed31_32_sub + (dal_fixed31_32_mul(m[0], m[7]), + dal_fixed31_32_mul(m[1], m[6])), determinant)); + im[8] = dal_fixed31_32_div(dal_fixed31_32_sub + (dal_fixed31_32_mul(m[0], m[4]), + dal_fixed31_32_mul(m[1], m[3])), determinant); + return true; + } + return false; +} + +/** + ***************************************************************************** + * Function: calculateXYZtoRGB_M3x3 + * + * @brief + * Calculates transformation matrix from XYZ coordinates to RBG + * + * @param [ in ] XYZofRGB - primaries XYZ + * @param [ in ] XYZofWhite - white point. + * @param [ out ] XYZtoRGB - RGB primires + * @return true if success + * + ***************************************************************************** + */ +static bool calculate_XYZ_to_RGB_3x3(const struct fixed31_32 *XYZofRGB, + const struct fixed31_32 *XYZofWhite, + struct fixed31_32 *XYZtoRGB) +{ + + struct fixed31_32 MInversed[9]; + struct fixed31_32 SVector[3]; + + /*1. Find Inverse matrix 3x3 of MTransposed*/ + if (!compute_inverse_matrix_3x3(XYZofRGB, MInversed)) + return false; + + /*2. Calculate vector: |Sr Sg Sb| = [MInversed] * |Wx Wy Wz|*/ + multiply_matrices(SVector, MInversed, XYZofWhite, 3, 3, 1); + + /*3. Calculate matrix XYZtoRGB 3x3*/ + XYZtoRGB[0] = dal_fixed31_32_mul(XYZofRGB[0], SVector[0]); + XYZtoRGB[1] = dal_fixed31_32_mul(XYZofRGB[1], SVector[1]); + XYZtoRGB[2] = dal_fixed31_32_mul(XYZofRGB[2], SVector[2]); + + XYZtoRGB[3] = dal_fixed31_32_mul(XYZofRGB[3], SVector[0]); + XYZtoRGB[4] = dal_fixed31_32_mul(XYZofRGB[4], SVector[1]); + XYZtoRGB[5] = dal_fixed31_32_mul(XYZofRGB[5], SVector[2]); + + XYZtoRGB[6] = dal_fixed31_32_mul(XYZofRGB[6], SVector[0]); + XYZtoRGB[7] = dal_fixed31_32_mul(XYZofRGB[7], SVector[1]); + XYZtoRGB[8] = dal_fixed31_32_mul(XYZofRGB[8], SVector[2]); + + return true; +} + +static bool gamut_to_color_matrix( + const struct fixed31_32 *pXYZofRGB,/*destination gamut*/ + const struct fixed31_32 *pXYZofWhite,/*destination of white point*/ + const struct fixed31_32 *pRefXYZofRGB,/*source gamut*/ + const struct fixed31_32 *pRefXYZofWhite,/*source of white point*/ + bool invert, + struct fixed31_32 *tempMatrix3X3) +{ + int i = 0; + struct gamut_calculation_matrix *matrix = + dm_alloc(sizeof(struct gamut_calculation_matrix)); + + struct fixed31_32 *pXYZtoRGB_Temp; + struct fixed31_32 *pXYZtoRGB_Final; + + matrix->fXYZofWhiteRef[0] = pRefXYZofWhite[0]; + matrix->fXYZofWhiteRef[1] = pRefXYZofWhite[1]; + matrix->fXYZofWhiteRef[2] = pRefXYZofWhite[2]; + + + matrix->fXYZofRGBRef[0] = pRefXYZofRGB[0]; + matrix->fXYZofRGBRef[1] = pRefXYZofRGB[1]; + matrix->fXYZofRGBRef[2] = pRefXYZofRGB[2]; + + matrix->fXYZofRGBRef[3] = pRefXYZofRGB[3]; + matrix->fXYZofRGBRef[4] = pRefXYZofRGB[4]; + matrix->fXYZofRGBRef[5] = pRefXYZofRGB[5]; + + matrix->fXYZofRGBRef[6] = pRefXYZofRGB[6]; + matrix->fXYZofRGBRef[7] = pRefXYZofRGB[7]; + matrix->fXYZofRGBRef[8] = pRefXYZofRGB[8]; + + /*default values - unity matrix*/ + while (i < 9) { + if (i == 0 || i == 4 || i == 8) + tempMatrix3X3[i] = dal_fixed31_32_one; + else + tempMatrix3X3[i] = dal_fixed31_32_zero; + i++; + } + + /*1. Decide about the order of calculation. + * bInvert == FALSE --> RGBtoXYZ_Ref * XYZtoRGB_Custom + * bInvert == TRUE --> RGBtoXYZ_Custom * XYZtoRGB_Ref */ + if (invert) { + pXYZtoRGB_Temp = matrix->XYZtoRGB_Custom; + pXYZtoRGB_Final = matrix->XYZtoRGB_Ref; + } else { + pXYZtoRGB_Temp = matrix->XYZtoRGB_Ref; + pXYZtoRGB_Final = matrix->XYZtoRGB_Custom; + } + + /*2. Calculate XYZtoRGB_Ref*/ + transpose_matrix(matrix->fXYZofRGBRef, 3, 3, matrix->MTransposed); + + if (!calculate_XYZ_to_RGB_3x3( + matrix->MTransposed, + matrix->fXYZofWhiteRef, + matrix->XYZtoRGB_Ref)) + goto function_fail; + + /*3. Calculate XYZtoRGB_Custom*/ + transpose_matrix(pXYZofRGB, 3, 3, matrix->MTransposed); + + if (!calculate_XYZ_to_RGB_3x3( + matrix->MTransposed, + pXYZofWhite, + matrix->XYZtoRGB_Custom)) + goto function_fail; + + /*4. Calculate RGBtoXYZ - + * inverse matrix 3x3 of XYZtoRGB_Ref or XYZtoRGB_Custom*/ + if (!compute_inverse_matrix_3x3(pXYZtoRGB_Temp, matrix->RGBtoXYZ_Final)) + goto function_fail; + + /*5. Calculate M(3x3) = RGBtoXYZ * XYZtoRGB*/ + multiply_matrices(matrix->MResult, matrix->RGBtoXYZ_Final, + pXYZtoRGB_Final, 3, 3, 3); + + for (i = 0; i < 9; i++) + tempMatrix3X3[i] = matrix->MResult[i]; + + dm_free(matrix); + + return true; + +function_fail: + dm_free(matrix); + return false; +} + +static bool build_gamut_remap_matrix + (struct color_space_coordinates gamut_description, + struct fixed31_32 *rgb_matrix, + struct fixed31_32 *white_point_matrix) +{ + struct fixed31_32 fixed_blueX = dal_fixed31_32_from_fraction + (gamut_description.blueX, DIVIDER); + struct fixed31_32 fixed_blueY = dal_fixed31_32_from_fraction + (gamut_description.blueY, DIVIDER); + struct fixed31_32 fixed_greenX = dal_fixed31_32_from_fraction + (gamut_description.greenX, DIVIDER); + struct fixed31_32 fixed_greenY = dal_fixed31_32_from_fraction + (gamut_description.greenY, DIVIDER); + struct fixed31_32 fixed_redX = dal_fixed31_32_from_fraction + (gamut_description.redX, DIVIDER); + struct fixed31_32 fixed_redY = dal_fixed31_32_from_fraction + (gamut_description.redY, DIVIDER); + struct fixed31_32 fixed_whiteX = dal_fixed31_32_from_fraction + (gamut_description.whiteX, DIVIDER); + struct fixed31_32 fixed_whiteY = dal_fixed31_32_from_fraction + (gamut_description.whiteY, DIVIDER); + + rgb_matrix[0] = dal_fixed31_32_div(fixed_redX, fixed_redY); + rgb_matrix[1] = dal_fixed31_32_one; + rgb_matrix[2] = dal_fixed31_32_div(dal_fixed31_32_sub + (dal_fixed31_32_sub(dal_fixed31_32_one, fixed_redX), + fixed_redY), fixed_redY); + + rgb_matrix[3] = dal_fixed31_32_div(fixed_greenX, fixed_greenY); + rgb_matrix[4] = dal_fixed31_32_one; + rgb_matrix[5] = dal_fixed31_32_div(dal_fixed31_32_sub + (dal_fixed31_32_sub(dal_fixed31_32_one, fixed_greenX), + fixed_greenY), fixed_greenY); + + rgb_matrix[6] = dal_fixed31_32_div(fixed_blueX, fixed_blueY); + rgb_matrix[7] = dal_fixed31_32_one; + rgb_matrix[8] = dal_fixed31_32_div(dal_fixed31_32_sub + (dal_fixed31_32_sub(dal_fixed31_32_one, fixed_blueX), + fixed_blueY), fixed_blueY); + + white_point_matrix[0] = dal_fixed31_32_div(fixed_whiteX, fixed_whiteY); + white_point_matrix[1] = dal_fixed31_32_one; + white_point_matrix[2] = dal_fixed31_32_div(dal_fixed31_32_sub + (dal_fixed31_32_sub(dal_fixed31_32_one, fixed_whiteX), + fixed_whiteY), fixed_whiteY); + + return true; +} + +static bool check_dc_support(const struct dc *dc) +{ + if (dc->stream_funcs.set_gamut_remap == NULL) + return false; + + return true; +} + +static uint16_t fixed_point_to_int_frac( + struct fixed31_32 arg, + uint8_t integer_bits, + uint8_t fractional_bits) +{ + int32_t numerator; + int32_t divisor = 1 << fractional_bits; + + uint16_t result; + + uint16_t d = (uint16_t)dal_fixed31_32_floor( + dal_fixed31_32_abs( + arg)); + + if (d <= (uint16_t)(1 << integer_bits) - (1 / (uint16_t)divisor)) + numerator = (uint16_t)dal_fixed31_32_floor( + dal_fixed31_32_mul_int( + arg, + divisor)); + else { + numerator = dal_fixed31_32_floor( + dal_fixed31_32_sub( + dal_fixed31_32_from_int( + 1LL << integer_bits), + dal_fixed31_32_recip( + dal_fixed31_32_from_int( + divisor)))); + } + + if (numerator >= 0) + result = (uint16_t)numerator; + else + result = (uint16_t)( + (1 << (integer_bits + fractional_bits + 1)) + numerator); + + if ((result != 0) && dal_fixed31_32_lt( + arg, dal_fixed31_32_zero)) + result |= 1 << (integer_bits + fractional_bits); + + return result; +} + +/** +* convert_float_matrix +* This converts a double into HW register spec defined format S2D13. +* @param : +* @return None +*/ + +static void convert_float_matrix_legacy( + uint16_t *matrix, + struct fixed31_32 *flt, + uint32_t buffer_size) +{ + const struct fixed31_32 min_2_13 = + dal_fixed31_32_from_fraction(S2D13_MIN, DIVIDER); + const struct fixed31_32 max_2_13 = + dal_fixed31_32_from_fraction(S2D13_MAX, DIVIDER); + uint32_t i; + + for (i = 0; i < buffer_size; ++i) { + uint32_t reg_value = + fixed_point_to_int_frac( + dal_fixed31_32_clamp( + flt[i], + min_2_13, + max_2_13), + 2, + 13); + + matrix[i] = (uint16_t)reg_value; + } +} + +static void convert_float_matrix( + uint16_t *matrix, + struct fixed31_32 *flt, + uint32_t buffer_size) +{ + const struct fixed31_32 min_0_13 = + dal_fixed31_32_from_fraction(S0D13_MIN, DIVIDER); + const struct fixed31_32 max_0_13 = + dal_fixed31_32_from_fraction(S0D13_MAX, DIVIDER); + const struct fixed31_32 min_2_13 = + dal_fixed31_32_from_fraction(S2D13_MIN, DIVIDER); + const struct fixed31_32 max_2_13 = + dal_fixed31_32_from_fraction(S2D13_MAX, DIVIDER); + uint32_t i; + uint16_t temp_matrix[12]; + + for (i = 0; i < buffer_size; ++i) { + if (i == 3 || i == 7 || i == 11) { + uint32_t reg_value = + fixed_point_to_int_frac( + dal_fixed31_32_clamp( + flt[i], + min_0_13, + max_0_13), + 2, + 13); + + temp_matrix[i] = (uint16_t)reg_value; + } else { + uint32_t reg_value = + fixed_point_to_int_frac( + dal_fixed31_32_clamp( + flt[i], + min_2_13, + max_2_13), + 2, + 13); + + temp_matrix[i] = (uint16_t)reg_value; + } + } + + matrix[4] = temp_matrix[0]; + matrix[5] = temp_matrix[1]; + matrix[6] = temp_matrix[2]; + matrix[7] = temp_matrix[3]; + + matrix[8] = temp_matrix[4]; + matrix[9] = temp_matrix[5]; + matrix[10] = temp_matrix[6]; + matrix[11] = temp_matrix[7]; + + matrix[0] = temp_matrix[8]; + matrix[1] = temp_matrix[9]; + matrix[2] = temp_matrix[10]; + matrix[3] = temp_matrix[11]; +} + +static int get_hw_value_from_sw_value(int swVal, int swMin, + int swMax, int hwMin, int hwMax) +{ + int dSW = swMax - swMin; /*software adjustment range size*/ + int dHW = hwMax - hwMin; /*hardware adjustment range size*/ + int hwVal; /*HW adjustment value*/ + + /* error case, I preserve the behavior from the predecessor + *getHwStepFromSwHwMinMaxValue (removed in Feb 2013) + *which was the FP version that only computed SCLF (i.e. dHW/dSW). + *it would return 0 in this case so + *hwVal = hwMin from the formula given in @brief + */ + if (dSW == 0) + return hwMin; + + /*it's quite often that ranges match, + *e.g. for overlay colors currently (Feb 2013) + *only brightness has a different + *HW range, and in this case no multiplication or division is needed, + *and if minimums match, no calculation at all + */ + if (dSW != dHW) { + hwVal = (swVal - swMin)*dHW/dSW + hwMin; + } else { + hwVal = swVal; + if (swMin != hwMin) + hwVal += (hwMin - swMin); + } + + return hwVal; +} + +static void initialize_fix_point_color_values( + struct core_color *core_color, + unsigned int sink_index, + struct fixed31_32 *grph_cont, + struct fixed31_32 *grph_sat, + struct fixed31_32 *grph_bright, + struct fixed31_32 *sin_grph_hue, + struct fixed31_32 *cos_grph_hue) +{ + /* Hue adjustment could be negative. -45 ~ +45 */ + struct fixed31_32 hue = + dal_fixed31_32_mul( + dal_fixed31_32_from_fraction + (get_hw_value_from_sw_value + (core_color->state[sink_index].hue.current, + core_color->state[sink_index].hue.min, + core_color->state[sink_index].hue.max, + -30, 30), 180), + dal_fixed31_32_pi); + + *sin_grph_hue = dal_fixed31_32_sin(hue); + *cos_grph_hue = dal_fixed31_32_cos(hue); + + *grph_cont = + dal_fixed31_32_from_fraction(get_hw_value_from_sw_value + (core_color->state[sink_index].contrast.current, + core_color->state[sink_index].contrast.min, + core_color->state[sink_index].contrast.max, + 50, 150), 100); + *grph_sat = + dal_fixed31_32_from_fraction(get_hw_value_from_sw_value + (core_color->state[sink_index].saturation.current, + core_color->state[sink_index].saturation.min, + core_color->state[sink_index].saturation.max, + 0, 200), 100); + *grph_bright = + dal_fixed31_32_from_fraction(get_hw_value_from_sw_value + (core_color->state[sink_index].brightness.current, + core_color->state[sink_index].brightness.min, + core_color->state[sink_index].brightness.max, + -25, 25), 100); +} + + +/* Given a specific dc_sink* this function finds its equivalent + * on the dc_sink array and returns the corresponding index + */ +static unsigned int sink_index_from_sink(struct core_color *core_color, + const struct dc_sink *sink) +{ + unsigned int index = 0; + + for (index = 0; index < core_color->num_sinks; index++) + if (core_color->caps[index].sink == sink) + return index; + + /* Could not find sink requested */ + ASSERT(false); + return index; +} + +static void calculate_rgb_matrix_legacy(struct core_color *core_color, + unsigned int sink_index, + struct fixed31_32 *rgb_matrix) +{ + const struct fixed31_32 k1 = + dal_fixed31_32_from_fraction(701000, 1000000); + const struct fixed31_32 k2 = + dal_fixed31_32_from_fraction(236568, 1000000); + const struct fixed31_32 k3 = + dal_fixed31_32_from_fraction(-587000, 1000000); + const struct fixed31_32 k4 = + dal_fixed31_32_from_fraction(464432, 1000000); + const struct fixed31_32 k5 = + dal_fixed31_32_from_fraction(-114000, 1000000); + const struct fixed31_32 k6 = + dal_fixed31_32_from_fraction(-701000, 1000000); + const struct fixed31_32 k7 = + dal_fixed31_32_from_fraction(-299000, 1000000); + const struct fixed31_32 k8 = + dal_fixed31_32_from_fraction(-292569, 1000000); + const struct fixed31_32 k9 = + dal_fixed31_32_from_fraction(413000, 1000000); + const struct fixed31_32 k10 = + dal_fixed31_32_from_fraction(-92482, 1000000); + const struct fixed31_32 k11 = + dal_fixed31_32_from_fraction(-114000, 1000000); + const struct fixed31_32 k12 = + dal_fixed31_32_from_fraction(385051, 1000000); + const struct fixed31_32 k13 = + dal_fixed31_32_from_fraction(-299000, 1000000); + const struct fixed31_32 k14 = + dal_fixed31_32_from_fraction(886000, 1000000); + const struct fixed31_32 k15 = + dal_fixed31_32_from_fraction(-587000, 1000000); + const struct fixed31_32 k16 = + dal_fixed31_32_from_fraction(-741914, 1000000); + const struct fixed31_32 k17 = + dal_fixed31_32_from_fraction(886000, 1000000); + const struct fixed31_32 k18 = + dal_fixed31_32_from_fraction(-144086, 1000000); + + const struct fixed31_32 luma_r = + dal_fixed31_32_from_fraction(299, 1000); + const struct fixed31_32 luma_g = + dal_fixed31_32_from_fraction(587, 1000); + const struct fixed31_32 luma_b = + dal_fixed31_32_from_fraction(114, 1000); + + struct fixed31_32 grph_cont; + struct fixed31_32 grph_sat; + struct fixed31_32 grph_bright; + struct fixed31_32 sin_grph_hue; + struct fixed31_32 cos_grph_hue; + + initialize_fix_point_color_values( + core_color, sink_index, &grph_cont, &grph_sat, + &grph_bright, &sin_grph_hue, &cos_grph_hue); + + /* COEF_1_1 = GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K1 +*/ + /* Sin(GrphHue) * K2))*/ + /* (Cos(GrphHue) * K1 + Sin(GrphHue) * K2)*/ + rgb_matrix[0] = + dal_fixed31_32_add( + dal_fixed31_32_mul(cos_grph_hue, k1), + dal_fixed31_32_mul(sin_grph_hue, k2)); + /* GrphSat * (Cos(GrphHue) * K1 + Sin(GrphHue) * K2 */ + rgb_matrix[0] = dal_fixed31_32_mul(grph_sat, rgb_matrix[0]); + /* (LumaR + GrphSat * (Cos(GrphHue) * K1 + Sin(GrphHue) * K2))*/ + rgb_matrix[0] = dal_fixed31_32_add(luma_r, rgb_matrix[0]); + /* GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K1 + Sin(GrphHue)**/ + /* K2))*/ + rgb_matrix[0] = dal_fixed31_32_mul(grph_cont, rgb_matrix[0]); + + /* COEF_1_2 = GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K3 +*/ + /* Sin(GrphHue) * K4))*/ + /* (Cos(GrphHue) * K3 + Sin(GrphHue) * K4)*/ + rgb_matrix[1] = + dal_fixed31_32_add( + dal_fixed31_32_mul(cos_grph_hue, k3), + dal_fixed31_32_mul(sin_grph_hue, k4)); + /* GrphSat * (Cos(GrphHue) * K3 + Sin(GrphHue) * K4)*/ + rgb_matrix[1] = dal_fixed31_32_mul(grph_sat, rgb_matrix[1]); + /* (LumaG + GrphSat * (Cos(GrphHue) * K3 + Sin(GrphHue) * K4))*/ + rgb_matrix[1] = dal_fixed31_32_add(luma_g, rgb_matrix[1]); + /* GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K3 + Sin(GrphHue)**/ + /* K4))*/ + rgb_matrix[1] = dal_fixed31_32_mul(grph_cont, rgb_matrix[1]); + + /* COEF_1_3 = GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K5 +*/ + /* Sin(GrphHue) * K6))*/ + /* (Cos(GrphHue) * K5 + Sin(GrphHue) * K6)*/ + rgb_matrix[2] = + dal_fixed31_32_add( + dal_fixed31_32_mul(cos_grph_hue, k5), + dal_fixed31_32_mul(sin_grph_hue, k6)); + /* GrphSat * (Cos(GrphHue) * K5 + Sin(GrphHue) * K6)*/ + rgb_matrix[2] = dal_fixed31_32_mul(grph_sat, rgb_matrix[2]); + /* LumaB + GrphSat * (Cos(GrphHue) * K5 + Sin(GrphHue) * K6)*/ + rgb_matrix[2] = dal_fixed31_32_add(luma_b, rgb_matrix[2]); + /* GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K5 + Sin(GrphHue)**/ + /* K6))*/ + rgb_matrix[2] = dal_fixed31_32_mul(grph_cont, rgb_matrix[2]); + + /* COEF_1_4 = GrphBright*/ + rgb_matrix[3] = grph_bright; + + /* COEF_2_1 = GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K7 +*/ + /* Sin(GrphHue) * K8))*/ + /* (Cos(GrphHue) * K7 + Sin(GrphHue) * K8)*/ + rgb_matrix[4] = + dal_fixed31_32_add( + dal_fixed31_32_mul(cos_grph_hue, k7), + dal_fixed31_32_mul(sin_grph_hue, k8)); + /* GrphSat * (Cos(GrphHue) * K7 + Sin(GrphHue) * K8)*/ + rgb_matrix[4] = dal_fixed31_32_mul(grph_sat, rgb_matrix[4]); + /* (LumaR + GrphSat * (Cos(GrphHue) * K7 + Sin(GrphHue) * K8))*/ + rgb_matrix[4] = dal_fixed31_32_add(luma_r, rgb_matrix[4]); + /* GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K7 + Sin(GrphHue)**/ + /* K8))*/ + rgb_matrix[4] = dal_fixed31_32_mul(grph_cont, rgb_matrix[4]); + + /* COEF_2_2 = GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K9 +*/ + /* Sin(GrphHue) * K10))*/ + /* (Cos(GrphHue) * K9 + Sin(GrphHue) * K10))*/ + rgb_matrix[5] = + dal_fixed31_32_add( + dal_fixed31_32_mul(cos_grph_hue, k9), + dal_fixed31_32_mul(sin_grph_hue, k10)); + /* GrphSat * (Cos(GrphHue) * K9 + Sin(GrphHue) * K10))*/ + rgb_matrix[5] = dal_fixed31_32_mul(grph_sat, rgb_matrix[5]); + /* (LumaG + GrphSat * (Cos(GrphHue) * K9 + Sin(GrphHue) * K10))*/ + rgb_matrix[5] = dal_fixed31_32_add(luma_g, rgb_matrix[5]); + /* GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K9 + Sin(GrphHue)**/ + /* K10))*/ + rgb_matrix[5] = dal_fixed31_32_mul(grph_cont, rgb_matrix[5]); + + /* COEF_2_3 = GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K11 +*/ + /* Sin(GrphHue) * K12))*/ + /* (Cos(GrphHue) * K11 + Sin(GrphHue) * K12))*/ + rgb_matrix[6] = + dal_fixed31_32_add( + dal_fixed31_32_mul(cos_grph_hue, k11), + dal_fixed31_32_mul(sin_grph_hue, k12)); + /* GrphSat * (Cos(GrphHue) * K11 + Sin(GrphHue) * K12))*/ + rgb_matrix[6] = dal_fixed31_32_mul(grph_sat, rgb_matrix[6]); + /* (LumaB + GrphSat * (Cos(GrphHue) * K11 + Sin(GrphHue) * K12))*/ + rgb_matrix[6] = dal_fixed31_32_add(luma_b, rgb_matrix[6]); + /* GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K11 + Sin(GrphHue)**/ + /* K12))*/ + rgb_matrix[6] = dal_fixed31_32_mul(grph_cont, rgb_matrix[6]); + + /* COEF_2_4 = GrphBright*/ + rgb_matrix[7] = grph_bright; + + /* COEF_3_1 = GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K13 +*/ + /* Sin(GrphHue) * K14))*/ + /* (Cos(GrphHue) * K13 + Sin(GrphHue) * K14)) */ + rgb_matrix[8] = + dal_fixed31_32_add( + dal_fixed31_32_mul(cos_grph_hue, k13), + dal_fixed31_32_mul(sin_grph_hue, k14)); + /* GrphSat * (Cos(GrphHue) * K13 + Sin(GrphHue) * K14)) */ + rgb_matrix[8] = dal_fixed31_32_mul(grph_sat, rgb_matrix[8]); + /* (LumaR + GrphSat * (Cos(GrphHue) * K13 + Sin(GrphHue) * K14)) */ + rgb_matrix[8] = dal_fixed31_32_add(luma_r, rgb_matrix[8]); + /* GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K13 + Sin(GrphHue)**/ + /* K14)) */ + rgb_matrix[8] = dal_fixed31_32_mul(grph_cont, rgb_matrix[8]); + + /* COEF_3_2 = GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K15 +*/ + /* Sin(GrphHue) * K16)) */ + /* GrphSat * (Cos(GrphHue) * K15 + Sin(GrphHue) * K16) */ + rgb_matrix[9] = + dal_fixed31_32_add( + dal_fixed31_32_mul(cos_grph_hue, k15), + dal_fixed31_32_mul(sin_grph_hue, k16)); + /* (LumaG + GrphSat * (Cos(GrphHue) * K15 + Sin(GrphHue) * K16)) */ + rgb_matrix[9] = dal_fixed31_32_mul(grph_sat, rgb_matrix[9]); + /* (LumaG + GrphSat * (Cos(GrphHue) * K15 + Sin(GrphHue) * K16)) */ + rgb_matrix[9] = dal_fixed31_32_add(luma_g, rgb_matrix[9]); + /* GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K15 + Sin(GrphHue)**/ + /* K16)) */ + rgb_matrix[9] = dal_fixed31_32_mul(grph_cont, rgb_matrix[9]); + + /* COEF_3_3 = GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K17 +*/ + /* Sin(GrphHue) * K18)) */ + /* (Cos(GrphHue) * K17 + Sin(GrphHue) * K18)) */ + rgb_matrix[10] = + dal_fixed31_32_add( + dal_fixed31_32_mul(cos_grph_hue, k17), + dal_fixed31_32_mul(sin_grph_hue, k18)); + /* GrphSat * (Cos(GrphHue) * K17 + Sin(GrphHue) * K18)) */ + rgb_matrix[10] = dal_fixed31_32_mul(grph_sat, rgb_matrix[10]); + /* (LumaB + GrphSat * (Cos(GrphHue) * K17 + Sin(GrphHue) * K18)) */ + rgb_matrix[10] = dal_fixed31_32_add(luma_b, rgb_matrix[10]); + /* GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K17 + Sin(GrphHue)**/ + /* K18)) */ + rgb_matrix[10] = dal_fixed31_32_mul(grph_cont, rgb_matrix[10]); + + /* COEF_3_4 = GrphBright */ + rgb_matrix[11] = grph_bright; +} + +static void calculate_rgb_limited_range_matrix(struct core_color *core_color, + unsigned int sink_index, struct fixed31_32 *rgb_matrix) +{ + struct fixed31_32 ideal[12]; + + static const int32_t matrix_[] = { + 85546875, 0, 0, 6250000, + 0, 85546875, 0, 6250000, + 0, 0, 85546875, 6250000 + }; + + uint32_t i = 0; + + do { + ideal[i] = dal_fixed31_32_from_fraction( + matrix_[i], + 100000000); + ++i; + } while (i != ARRAY_SIZE(matrix_)); + + + struct fixed31_32 grph_cont; + struct fixed31_32 grph_sat; + struct fixed31_32 grph_bright; + struct fixed31_32 sin_grph_hue; + struct fixed31_32 cos_grph_hue; + + initialize_fix_point_color_values( + core_color, sink_index, &grph_cont, &grph_sat, + &grph_bright, &sin_grph_hue, &cos_grph_hue); + + const struct fixed31_32 multiplier = + dal_fixed31_32_mul(grph_cont, grph_sat); + + rgb_matrix[8] = dal_fixed31_32_mul(ideal[0], grph_cont); + + rgb_matrix[9] = dal_fixed31_32_mul(ideal[1], grph_cont); + + rgb_matrix[10] = dal_fixed31_32_mul(ideal[2], grph_cont); + + rgb_matrix[11] = dal_fixed31_32_add( + ideal[3], + dal_fixed31_32_mul( + grph_bright, + dal_fixed31_32_from_fraction(86, 100))); + + rgb_matrix[0] = dal_fixed31_32_mul( + multiplier, + dal_fixed31_32_add( + dal_fixed31_32_mul( + ideal[8], + sin_grph_hue), + dal_fixed31_32_mul( + ideal[4], + cos_grph_hue))); + + rgb_matrix[1] = dal_fixed31_32_mul( + multiplier, + dal_fixed31_32_add( + dal_fixed31_32_mul( + ideal[9], + sin_grph_hue), + dal_fixed31_32_mul( + ideal[5], + cos_grph_hue))); + + rgb_matrix[2] = dal_fixed31_32_mul( + multiplier, + dal_fixed31_32_add( + dal_fixed31_32_mul( + ideal[10], + sin_grph_hue), + dal_fixed31_32_mul( + ideal[6], + cos_grph_hue))); + + rgb_matrix[3] = ideal[7]; + + rgb_matrix[4] = dal_fixed31_32_mul( + multiplier, + dal_fixed31_32_sub( + dal_fixed31_32_mul( + ideal[8], + cos_grph_hue), + dal_fixed31_32_mul( + ideal[4], + sin_grph_hue))); + + rgb_matrix[5] = dal_fixed31_32_mul( + multiplier, + dal_fixed31_32_sub( + dal_fixed31_32_mul( + ideal[9], + cos_grph_hue), + dal_fixed31_32_mul( + ideal[5], + sin_grph_hue))); + + rgb_matrix[6] = dal_fixed31_32_mul( + multiplier, + dal_fixed31_32_sub( + dal_fixed31_32_mul( + ideal[10], + cos_grph_hue), + dal_fixed31_32_mul( + ideal[6], + sin_grph_hue))); + + rgb_matrix[7] = ideal[11]; +} + +static void calculate_yuv_matrix(struct core_color *core_color, + unsigned int sink_index, + enum dc_color_space color_space, + struct fixed31_32 *yuv_matrix) +{ + struct fixed31_32 ideal[12]; + uint32_t i = 0; + + if ((color_space == COLOR_SPACE_YPBPR601) || + (color_space == COLOR_SPACE_YCBCR601) || + (color_space == COLOR_SPACE_YCBCR601_LIMITED)) { + static const int32_t matrix_[] = { + 25578516, 50216016, 9752344, 6250000, + -14764391, -28985609, 43750000, 50000000, + 43750000, -36635164, -7114836, 50000000 + }; + do { + ideal[i] = dal_fixed31_32_from_fraction( + matrix_[i], + 100000000); + ++i; + } while (i != ARRAY_SIZE(matrix_)); + } else { + static const int32_t matrix_[] = { + 18187266, 61183125, 6176484, 6250000, + -10025059, -33724941, 43750000, 50000000, + 43750000, -39738379, -4011621, 50000000 + }; + do { + ideal[i] = dal_fixed31_32_from_fraction( + matrix_[i], + 100000000); + ++i; + } while (i != ARRAY_SIZE(matrix_)); + } + + struct fixed31_32 grph_cont; + struct fixed31_32 grph_sat; + struct fixed31_32 grph_bright; + struct fixed31_32 sin_grph_hue; + struct fixed31_32 cos_grph_hue; + + initialize_fix_point_color_values( + core_color, sink_index, &grph_cont, &grph_sat, + &grph_bright, &sin_grph_hue, &cos_grph_hue); + + const struct fixed31_32 multiplier = + dal_fixed31_32_mul(grph_cont, grph_sat); + + yuv_matrix[0] = dal_fixed31_32_mul(ideal[0], grph_cont); + + yuv_matrix[1] = dal_fixed31_32_mul(ideal[1], grph_cont); + + yuv_matrix[2] = dal_fixed31_32_mul(ideal[2], grph_cont); + + yuv_matrix[4] = dal_fixed31_32_mul( + multiplier, + dal_fixed31_32_add( + dal_fixed31_32_mul( + ideal[4], + cos_grph_hue), + dal_fixed31_32_mul( + ideal[8], + sin_grph_hue))); + + yuv_matrix[5] = dal_fixed31_32_mul( + multiplier, + dal_fixed31_32_add( + dal_fixed31_32_mul( + ideal[5], + cos_grph_hue), + dal_fixed31_32_mul( + ideal[9], + sin_grph_hue))); + + yuv_matrix[6] = dal_fixed31_32_mul( + multiplier, + dal_fixed31_32_add( + dal_fixed31_32_mul( + ideal[6], + cos_grph_hue), + dal_fixed31_32_mul( + ideal[10], + sin_grph_hue))); + + yuv_matrix[7] = ideal[7]; + + yuv_matrix[8] = dal_fixed31_32_mul( + multiplier, + dal_fixed31_32_sub( + dal_fixed31_32_mul( + ideal[8], + cos_grph_hue), + dal_fixed31_32_mul( + ideal[4], + sin_grph_hue))); + + yuv_matrix[9] = dal_fixed31_32_mul( + multiplier, + dal_fixed31_32_sub( + dal_fixed31_32_mul( + ideal[9], + cos_grph_hue), + dal_fixed31_32_mul( + ideal[5], + sin_grph_hue))); + + yuv_matrix[10] = dal_fixed31_32_mul( + multiplier, + dal_fixed31_32_sub( + dal_fixed31_32_mul( + ideal[10], + cos_grph_hue), + dal_fixed31_32_mul( + ideal[6], + sin_grph_hue))); + + yuv_matrix[11] = ideal[11]; + + if ((color_space == COLOR_SPACE_YCBCR601_LIMITED) || + (color_space == COLOR_SPACE_YCBCR709_LIMITED)) { + yuv_matrix[3] = dal_fixed31_32_add(ideal[3], grph_bright); + } else { + yuv_matrix[3] = dal_fixed31_32_add( + ideal[3], + dal_fixed31_32_mul( + grph_bright, + dal_fixed31_32_from_fraction(86, 100))); + } +} + +static void calculate_csc_matrix(struct core_color *core_color, + unsigned int sink_index, + enum dc_color_space color_space, + uint16_t *csc_matrix) +{ + struct fixed31_32 fixed_csc_matrix[12]; + switch (color_space) { + case COLOR_SPACE_SRGB: + calculate_rgb_matrix_legacy + (core_color, sink_index, fixed_csc_matrix); + convert_float_matrix_legacy + (csc_matrix, fixed_csc_matrix, 12); + break; + case COLOR_SPACE_SRGB_LIMITED: + calculate_rgb_limited_range_matrix(core_color, sink_index, + fixed_csc_matrix); + convert_float_matrix(csc_matrix, fixed_csc_matrix, 12); + break; + case COLOR_SPACE_YCBCR601: + case COLOR_SPACE_YCBCR709: + case COLOR_SPACE_YCBCR601_LIMITED: + case COLOR_SPACE_YCBCR709_LIMITED: + case COLOR_SPACE_YPBPR601: + case COLOR_SPACE_YPBPR709: + calculate_yuv_matrix(core_color, sink_index, color_space, + fixed_csc_matrix); + convert_float_matrix(csc_matrix, fixed_csc_matrix, 12); + break; + default: + calculate_rgb_matrix_legacy + (core_color, sink_index, fixed_csc_matrix); + convert_float_matrix_legacy + (csc_matrix, fixed_csc_matrix, 12); + break; + } +} + +struct mod_color *mod_color_create(struct dc *dc) +{ + int i = 0; + struct core_color *core_color = + dm_alloc(sizeof(struct core_color)); + struct core_dc *core_dc = DC_TO_CORE(dc); + struct persistent_data_flag flag; + + if (core_color == NULL) + goto fail_alloc_context; + + core_color->caps = dm_alloc(sizeof(struct sink_caps) * + MOD_COLOR_MAX_CONCURRENT_SINKS); + + if (core_color->caps == NULL) + goto fail_alloc_caps; + + for (i = 0; i < MOD_COLOR_MAX_CONCURRENT_SINKS; i++) + core_color->caps[i].sink = NULL; + + core_color->state = dm_alloc(sizeof(struct color_state) * + MOD_COLOR_MAX_CONCURRENT_SINKS); + + /*hardcoded to sRGB with 6500 color temperature*/ + for (i = 0; i < MOD_COLOR_MAX_CONCURRENT_SINKS; i++) { + core_color->state[i].source_gamut.blueX = 1500; + core_color->state[i].source_gamut.blueY = 600; + core_color->state[i].source_gamut.greenX = 3000; + core_color->state[i].source_gamut.greenY = 6000; + core_color->state[i].source_gamut.redX = 6400; + core_color->state[i].source_gamut.redY = 3300; + core_color->state[i].source_gamut.whiteX = 3127; + core_color->state[i].source_gamut.whiteY = 3290; + + core_color->state[i].destination_gamut.blueX = 1500; + core_color->state[i].destination_gamut.blueY = 600; + core_color->state[i].destination_gamut.greenX = 3000; + core_color->state[i].destination_gamut.greenY = 6000; + core_color->state[i].destination_gamut.redX = 6400; + core_color->state[i].destination_gamut.redY = 3300; + core_color->state[i].destination_gamut.whiteX = 3127; + core_color->state[i].destination_gamut.whiteY = 3290; + + core_color->state[i].custom_color_temperature = 6500; + + core_color->state[i].contrast.current = 100; + core_color->state[i].contrast.min = 0; + core_color->state[i].contrast.max = 200; + + core_color->state[i].saturation.current = 100; + core_color->state[i].saturation.min = 0; + core_color->state[i].saturation.max = 200; + + core_color->state[i].brightness.current = 0; + core_color->state[i].brightness.min = -100; + core_color->state[i].brightness.max = 100; + + core_color->state[i].hue.current = 0; + core_color->state[i].hue.min = -30; + core_color->state[i].hue.max = 30; + } + + if (core_color->state == NULL) + goto fail_alloc_state; + + core_color->num_sinks = 0; + + if (dc == NULL) + goto fail_construct; + + core_color->dc = dc; + + if (!check_dc_support(dc)) + goto fail_construct; + + /* Create initial module folder in registry for color adjustment */ + flag.save_per_edid = true; + flag.save_per_link = false; + + dm_write_persistent_data(core_dc->ctx, NULL, COLOR_REGISTRY_NAME, NULL, + NULL, 0, &flag); + + return &core_color->public; + +fail_construct: + dm_free(core_color->state); + +fail_alloc_state: + dm_free(core_color->caps); + +fail_alloc_caps: + dm_free(core_color); + +fail_alloc_context: + return NULL; +} + +void mod_color_destroy(struct mod_color *mod_color) +{ + if (mod_color != NULL) { + int i; + struct core_color *core_color = + MOD_COLOR_TO_CORE(mod_color); + + dm_free(core_color->state); + + for (i = 0; i < core_color->num_sinks; i++) + dc_sink_release(core_color->caps[i].sink); + + dm_free(core_color->caps); + + dm_free(core_color); + } +} + +bool mod_color_add_sink(struct mod_color *mod_color, const struct dc_sink *sink) +{ + struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); + struct core_dc *core_dc = DC_TO_CORE(core_color->dc); + bool persistent_color_temp_enable; + int persistent_custom_color_temp = 0; + struct color_space_coordinates persistent_source_gamut; + struct color_space_coordinates persistent_destination_gamut; + int persistent_brightness; + int persistent_contrast; + int persistent_hue; + int persistent_saturation; + enum dc_quantization_range persistent_quantization_range; + struct persistent_data_flag flag; + + if (core_color->num_sinks < MOD_COLOR_MAX_CONCURRENT_SINKS) { + dc_sink_retain(sink); + core_color->caps[core_color->num_sinks].sink = sink; + core_color->state[core_color->num_sinks]. + user_enable_color_temperature = true; + + /* get persistent data from registry */ + flag.save_per_edid = true; + flag.save_per_link = false; + + + if (dm_read_persistent_data(core_dc->ctx, sink, + COLOR_REGISTRY_NAME, + "enablecolortempadj", + &persistent_color_temp_enable, + sizeof(bool), &flag)) + core_color->state[core_color->num_sinks]. + user_enable_color_temperature = + persistent_color_temp_enable; + else + core_color->state[core_color->num_sinks]. + user_enable_color_temperature = true; + + if (dm_read_persistent_data(core_dc->ctx, sink, + COLOR_REGISTRY_NAME, + "customcolortemp", + &persistent_custom_color_temp, + sizeof(int), &flag)) + core_color->state[core_color->num_sinks]. + custom_color_temperature + = persistent_custom_color_temp; + else + core_color->state[core_color->num_sinks]. + custom_color_temperature = 6500; + + if (dm_read_persistent_data(core_dc->ctx, sink, + COLOR_REGISTRY_NAME, + "sourcegamut", + &persistent_source_gamut, + sizeof(struct color_space_coordinates), + &flag)) { + memcpy(&core_color->state[core_color->num_sinks]. + source_gamut, &persistent_source_gamut, + sizeof(struct color_space_coordinates)); + } else { + core_color->state[core_color->num_sinks]. + source_gamut.blueX = 1500; + core_color->state[core_color->num_sinks]. + source_gamut.blueY = 600; + core_color->state[core_color->num_sinks]. + source_gamut.greenX = 3000; + core_color->state[core_color->num_sinks]. + source_gamut.greenY = 6000; + core_color->state[core_color->num_sinks]. + source_gamut.redX = 6400; + core_color->state[core_color->num_sinks]. + source_gamut.redY = 3300; + core_color->state[core_color->num_sinks]. + source_gamut.whiteX = 3127; + core_color->state[core_color->num_sinks]. + source_gamut.whiteY = 3290; + } + + if (dm_read_persistent_data(core_dc->ctx, sink, COLOR_REGISTRY_NAME, + "destgamut", + &persistent_destination_gamut, + sizeof(struct color_space_coordinates), + &flag)) { + memcpy(&core_color->state[core_color->num_sinks]. + destination_gamut, + &persistent_destination_gamut, + sizeof(struct color_space_coordinates)); + } else { + core_color->state[core_color->num_sinks]. + destination_gamut.blueX = 1500; + core_color->state[core_color->num_sinks]. + destination_gamut.blueY = 600; + core_color->state[core_color->num_sinks]. + destination_gamut.greenX = 3000; + core_color->state[core_color->num_sinks]. + destination_gamut.greenY = 6000; + core_color->state[core_color->num_sinks]. + destination_gamut.redX = 6400; + core_color->state[core_color->num_sinks]. + destination_gamut.redY = 3300; + core_color->state[core_color->num_sinks]. + destination_gamut.whiteX = 3127; + core_color->state[core_color->num_sinks]. + destination_gamut.whiteY = 3290; + } + + if (dm_read_persistent_data(core_dc->ctx, sink, COLOR_REGISTRY_NAME, + "brightness", + &persistent_brightness, + sizeof(int), &flag)) + core_color->state[core_color->num_sinks]. + brightness.current = persistent_brightness; + else + core_color->state[core_color->num_sinks]. + brightness.current = 0; + + if (dm_read_persistent_data(core_dc->ctx, sink, COLOR_REGISTRY_NAME, + "contrast", + &persistent_contrast, + sizeof(int), &flag)) + core_color->state[core_color->num_sinks]. + contrast.current = persistent_contrast; + else + core_color->state[core_color->num_sinks]. + contrast.current = 100; + + if (dm_read_persistent_data(core_dc->ctx, sink, COLOR_REGISTRY_NAME, + "hue", + &persistent_hue, + sizeof(int), &flag)) + core_color->state[core_color->num_sinks]. + hue.current = persistent_hue; + else + core_color->state[core_color->num_sinks]. + hue.current = 0; + + if (dm_read_persistent_data(core_dc->ctx, sink, COLOR_REGISTRY_NAME, + "saturation", + &persistent_saturation, + sizeof(int), &flag)) + core_color->state[core_color->num_sinks]. + saturation.current = persistent_saturation; + else + core_color->state[core_color->num_sinks]. + saturation.current = 100; + + if (dm_read_persistent_data(core_dc->ctx, sink, + COLOR_REGISTRY_NAME, + "preferred_quantization_range", + &persistent_quantization_range, + sizeof(int), &flag)) + core_color->state[core_color->num_sinks]. + preferred_quantization_range = + persistent_quantization_range; + else + core_color->state[core_color->num_sinks]. + preferred_quantization_range = QUANTIZATION_RANGE_FULL; + + core_color->num_sinks++; + return true; + } + return false; +} + +bool mod_color_remove_sink(struct mod_color *mod_color, + const struct dc_sink *sink) +{ + int i = 0, j = 0; + struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); + + for (i = 0; i < core_color->num_sinks; i++) { + if (core_color->caps[i].sink == sink) { + /* To remove this sink, shift everything after down */ + for (j = i; j < core_color->num_sinks - 1; j++) { + core_color->caps[j].sink = + core_color->caps[j + 1].sink; + + memcpy(&core_color->state[j], + &core_color->state[j + 1], + sizeof(struct color_state)); + } + + core_color->num_sinks--; + + dc_sink_release(sink); + + return true; + } + } + + return false; +} + +bool mod_color_update_gamut_to_stream(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams) +{ + struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); + struct core_dc *core_dc = DC_TO_CORE(core_color->dc); + struct persistent_data_flag flag; + struct gamut_src_dst_matrix *matrix = + dm_alloc(sizeof(struct gamut_src_dst_matrix)); + + unsigned int stream_index, sink_index, j; + + for (stream_index = 0; stream_index < num_streams; stream_index++) { + sink_index = sink_index_from_sink(core_color, + streams[stream_index]->sink); + + /* Write persistent data in registry*/ + flag.save_per_edid = true; + flag.save_per_link = false; + + dm_write_persistent_data(core_dc->ctx, + streams[stream_index]->sink, + COLOR_REGISTRY_NAME, + "sourcegamut", + &core_color->state[sink_index]. + source_gamut, + sizeof(struct color_space_coordinates), + &flag); + + dm_write_persistent_data(core_dc->ctx, + streams[stream_index]->sink, + COLOR_REGISTRY_NAME, + "destgamut", + &core_color->state[sink_index]. + destination_gamut, + sizeof(struct color_space_coordinates), + &flag); + + if (!build_gamut_remap_matrix + (core_color->state[sink_index].source_gamut, + matrix->rgbCoeffSrc, + matrix->whiteCoeffSrc)) + goto function_fail; + + if (!build_gamut_remap_matrix + (core_color->state[sink_index]. + destination_gamut, + matrix->rgbCoeffDst, matrix->whiteCoeffDst)) + goto function_fail; + + struct fixed31_32 gamut_result[12]; + struct fixed31_32 temp_matrix[9]; + + if (!gamut_to_color_matrix( + matrix->rgbCoeffDst, + matrix->whiteCoeffDst, + matrix->rgbCoeffSrc, + matrix->whiteCoeffSrc, + true, + temp_matrix)) + goto function_fail; + + gamut_result[0] = temp_matrix[0]; + gamut_result[1] = temp_matrix[1]; + gamut_result[2] = temp_matrix[2]; + gamut_result[3] = matrix->whiteCoeffSrc[0]; + gamut_result[4] = temp_matrix[3]; + gamut_result[5] = temp_matrix[4]; + gamut_result[6] = temp_matrix[5]; + gamut_result[7] = matrix->whiteCoeffSrc[1]; + gamut_result[8] = temp_matrix[6]; + gamut_result[9] = temp_matrix[7]; + gamut_result[10] = temp_matrix[8]; + gamut_result[11] = matrix->whiteCoeffSrc[2]; + + struct core_stream *core_stream = + DC_STREAM_TO_CORE + (streams[stream_index]); + + core_stream->public.gamut_remap_matrix.enable_remap = true; + + for (j = 0; j < 12; j++) + core_stream->public. + gamut_remap_matrix.matrix[j] = + gamut_result[j]; + } + + dm_free(matrix); + core_color->dc->stream_funcs.set_gamut_remap + (core_color->dc, streams, num_streams); + + return true; + +function_fail: + dm_free(matrix); + return false; +} + +bool mod_color_adjust_source_gamut(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + struct gamut_space_coordinates *input_gamut_coordinates, + struct white_point_coodinates *input_white_point_coordinates) +{ + struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); + + unsigned int stream_index, sink_index; + + for (stream_index = 0; stream_index < num_streams; stream_index++) { + sink_index = sink_index_from_sink(core_color, + streams[stream_index]->sink); + + core_color->state[sink_index].source_gamut.blueX = + input_gamut_coordinates->blueX; + core_color->state[sink_index].source_gamut.blueY = + input_gamut_coordinates->blueY; + core_color->state[sink_index].source_gamut.greenX = + input_gamut_coordinates->greenX; + core_color->state[sink_index].source_gamut.greenY = + input_gamut_coordinates->greenY; + core_color->state[sink_index].source_gamut.redX = + input_gamut_coordinates->redX; + core_color->state[sink_index].source_gamut.redY = + input_gamut_coordinates->redY; + core_color->state[sink_index].source_gamut.whiteX = + input_white_point_coordinates->whiteX; + core_color->state[sink_index].source_gamut.whiteY = + input_white_point_coordinates->whiteY; + } + + if (!mod_color_update_gamut_to_stream(mod_color, streams, num_streams)) + return false; + + return true; +} + +bool mod_color_adjust_destination_gamut(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + struct gamut_space_coordinates *input_gamut_coordinates, + struct white_point_coodinates *input_white_point_coordinates) +{ + struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); + + unsigned int stream_index, sink_index; + + for (stream_index = 0; stream_index < num_streams; stream_index++) { + sink_index = sink_index_from_sink(core_color, + streams[stream_index]->sink); + + core_color->state[sink_index].destination_gamut.blueX = + input_gamut_coordinates->blueX; + core_color->state[sink_index].destination_gamut.blueY = + input_gamut_coordinates->blueY; + core_color->state[sink_index].destination_gamut.greenX = + input_gamut_coordinates->greenX; + core_color->state[sink_index].destination_gamut.greenY = + input_gamut_coordinates->greenY; + core_color->state[sink_index].destination_gamut.redX = + input_gamut_coordinates->redX; + core_color->state[sink_index].destination_gamut.redY = + input_gamut_coordinates->redY; + core_color->state[sink_index].destination_gamut.whiteX = + input_white_point_coordinates->whiteX; + core_color->state[sink_index].destination_gamut.whiteY = + input_white_point_coordinates->whiteY; + } + + if (!mod_color_update_gamut_to_stream(mod_color, streams, num_streams)) + return false; + + return true; +} + +bool mod_color_set_white_point(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + struct white_point_coodinates *white_point) +{ + struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); + + unsigned int stream_index, sink_index; + + for (stream_index = 0; stream_index < num_streams; + stream_index++) { + sink_index = sink_index_from_sink(core_color, + streams[stream_index]->sink); + core_color->state[sink_index].source_gamut.whiteX = + white_point->whiteX; + core_color->state[sink_index].source_gamut.whiteY = + white_point->whiteY; + } + + if (!mod_color_update_gamut_to_stream(mod_color, streams, num_streams)) + return false; + + return true; +} + +bool mod_color_set_user_enable(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + bool user_enable) +{ + struct core_color *core_color = + MOD_COLOR_TO_CORE(mod_color); + struct core_dc *core_dc = DC_TO_CORE(core_color->dc); + struct persistent_data_flag flag; + unsigned int stream_index, sink_index; + + for (stream_index = 0; stream_index < num_streams; stream_index++) { + sink_index = sink_index_from_sink(core_color, + streams[stream_index]->sink); + core_color->state[sink_index].user_enable_color_temperature + = user_enable; + + /* Write persistent data in registry*/ + flag.save_per_edid = true; + flag.save_per_link = false; + + dm_write_persistent_data(core_dc->ctx, + streams[stream_index]->sink, + COLOR_REGISTRY_NAME, + "enablecolortempadj", + &user_enable, + sizeof(bool), + &flag); + } + return true; +} + +bool mod_color_get_user_enable(struct mod_color *mod_color, + const struct dc_sink *sink, + bool *user_enable) +{ + struct core_color *core_color = + MOD_COLOR_TO_CORE(mod_color); + + unsigned int sink_index = sink_index_from_sink(core_color, sink); + + *user_enable = core_color->state[sink_index]. + user_enable_color_temperature; + + return true; +} + +bool mod_color_get_custom_color_temperature(struct mod_color *mod_color, + const struct dc_sink *sink, + int *color_temperature) +{ + struct core_color *core_color = + MOD_COLOR_TO_CORE(mod_color); + + unsigned int sink_index = sink_index_from_sink(core_color, sink); + + *color_temperature = core_color->state[sink_index]. + custom_color_temperature; + + return true; +} + +bool mod_color_set_custom_color_temperature(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + int color_temperature) +{ + struct core_color *core_color = + MOD_COLOR_TO_CORE(mod_color); + struct core_dc *core_dc = DC_TO_CORE(core_color->dc); + struct persistent_data_flag flag; + unsigned int stream_index, sink_index; + + for (stream_index = 0; stream_index < num_streams; stream_index++) { + sink_index = sink_index_from_sink(core_color, + streams[stream_index]->sink); + core_color->state[sink_index].custom_color_temperature + = color_temperature; + + /* Write persistent data in registry*/ + flag.save_per_edid = true; + flag.save_per_link = false; + + dm_write_persistent_data(core_dc->ctx, + streams[stream_index]->sink, + COLOR_REGISTRY_NAME, + "customcolortemp", + &color_temperature, + sizeof(int), + &flag); + } + return true; +} + +bool mod_color_get_color_saturation(struct mod_color *mod_color, + const struct dc_sink *sink, + struct color_range *color_saturation) +{ + struct core_color *core_color = + MOD_COLOR_TO_CORE(mod_color); + + unsigned int sink_index = sink_index_from_sink(core_color, sink); + + *color_saturation = core_color->state[sink_index].saturation; + + return true; +} + +bool mod_color_get_color_contrast(struct mod_color *mod_color, + const struct dc_sink *sink, + struct color_range *color_contrast) +{ + struct core_color *core_color = + MOD_COLOR_TO_CORE(mod_color); + + unsigned int sink_index = sink_index_from_sink(core_color, sink); + + *color_contrast = core_color->state[sink_index].contrast; + + return true; +} + +bool mod_color_get_color_brightness(struct mod_color *mod_color, + const struct dc_sink *sink, + struct color_range *color_brightness) +{ + struct core_color *core_color = + MOD_COLOR_TO_CORE(mod_color); + + unsigned int sink_index = sink_index_from_sink(core_color, sink); + + *color_brightness = core_color->state[sink_index].brightness; + + return true; +} + +bool mod_color_get_color_hue(struct mod_color *mod_color, + const struct dc_sink *sink, + struct color_range *color_hue) +{ + struct core_color *core_color = + MOD_COLOR_TO_CORE(mod_color); + + unsigned int sink_index = sink_index_from_sink(core_color, sink); + + *color_hue = core_color->state[sink_index].hue; + + return true; +} + +bool mod_color_get_source_gamut(struct mod_color *mod_color, + const struct dc_sink *sink, + struct color_space_coordinates *source_gamut) +{ + struct core_color *core_color = + MOD_COLOR_TO_CORE(mod_color); + + unsigned int sink_index = sink_index_from_sink(core_color, sink); + + *source_gamut = core_color->state[sink_index].source_gamut; + + return true; +} + +bool mod_color_notify_mode_change(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams) +{ + struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); + + struct gamut_src_dst_matrix *matrix = + dm_alloc(sizeof(struct gamut_src_dst_matrix)); + + unsigned int stream_index, sink_index, j; + + for (stream_index = 0; stream_index < num_streams; stream_index++) { + sink_index = sink_index_from_sink(core_color, + streams[stream_index]->sink); + + if (!build_gamut_remap_matrix + (core_color->state[sink_index].source_gamut, + matrix->rgbCoeffSrc, + matrix->whiteCoeffSrc)) + goto function_fail; + + if (!build_gamut_remap_matrix + (core_color->state[sink_index]. + destination_gamut, + matrix->rgbCoeffDst, matrix->whiteCoeffDst)) + goto function_fail; + + struct fixed31_32 gamut_result[12]; + struct fixed31_32 temp_matrix[9]; + + if (!gamut_to_color_matrix( + matrix->rgbCoeffDst, + matrix->whiteCoeffDst, + matrix->rgbCoeffSrc, + matrix->whiteCoeffSrc, + true, + temp_matrix)) + goto function_fail; + + gamut_result[0] = temp_matrix[0]; + gamut_result[1] = temp_matrix[1]; + gamut_result[2] = temp_matrix[2]; + gamut_result[3] = matrix->whiteCoeffSrc[0]; + gamut_result[4] = temp_matrix[3]; + gamut_result[5] = temp_matrix[4]; + gamut_result[6] = temp_matrix[5]; + gamut_result[7] = matrix->whiteCoeffSrc[1]; + gamut_result[8] = temp_matrix[6]; + gamut_result[9] = temp_matrix[7]; + gamut_result[10] = temp_matrix[8]; + gamut_result[11] = matrix->whiteCoeffSrc[2]; + + + struct core_stream *core_stream = + DC_STREAM_TO_CORE + (streams[stream_index]); + + core_stream->public.gamut_remap_matrix.enable_remap = true; + + for (j = 0; j < 12; j++) + core_stream->public. + gamut_remap_matrix.matrix[j] = + gamut_result[j]; + + calculate_csc_matrix(core_color, sink_index, + core_stream->public.output_color_space, + core_stream->public.csc_color_matrix.matrix); + + core_stream->public.csc_color_matrix.enable_adjustment = true; + } + + dm_free(matrix); + + return true; + +function_fail: + dm_free(matrix); + return false; +} + +bool mod_color_set_brightness(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + int brightness_value) +{ + struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); + struct core_dc *core_dc = DC_TO_CORE(core_color->dc); + struct persistent_data_flag flag; + unsigned int stream_index, sink_index; + + for (stream_index = 0; stream_index < num_streams; stream_index++) { + sink_index = sink_index_from_sink(core_color, + streams[stream_index]->sink); + + struct core_stream *core_stream = + DC_STREAM_TO_CORE + (streams[stream_index]); + + core_color->state[sink_index].brightness.current = + brightness_value; + + calculate_csc_matrix(core_color, sink_index, + core_stream->public.output_color_space, + core_stream->public.csc_color_matrix.matrix); + + core_stream->public.csc_color_matrix.enable_adjustment = true; + + /* Write persistent data in registry*/ + flag.save_per_edid = true; + flag.save_per_link = false; + dm_write_persistent_data(core_dc->ctx, + streams[stream_index]->sink, + COLOR_REGISTRY_NAME, + "brightness", + &brightness_value, + sizeof(int), + &flag); + } + + core_color->dc->stream_funcs.set_gamut_remap + (core_color->dc, streams, num_streams); + + return true; +} + +bool mod_color_set_contrast(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + int contrast_value) +{ + struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); + struct core_dc *core_dc = DC_TO_CORE(core_color->dc); + struct persistent_data_flag flag; + unsigned int stream_index, sink_index; + + for (stream_index = 0; stream_index < num_streams; stream_index++) { + sink_index = sink_index_from_sink(core_color, + streams[stream_index]->sink); + + struct core_stream *core_stream = + DC_STREAM_TO_CORE + (streams[stream_index]); + + core_color->state[sink_index].contrast.current = + contrast_value; + + calculate_csc_matrix(core_color, sink_index, + core_stream->public.output_color_space, + core_stream->public.csc_color_matrix.matrix); + + core_stream->public.csc_color_matrix.enable_adjustment = true; + + /* Write persistent data in registry*/ + flag.save_per_edid = true; + flag.save_per_link = false; + dm_write_persistent_data(core_dc->ctx, + streams[stream_index]->sink, + COLOR_REGISTRY_NAME, + "contrast", + &contrast_value, + sizeof(int), + &flag); + } + + core_color->dc->stream_funcs.set_gamut_remap + (core_color->dc, streams, num_streams); + + return true; +} + +bool mod_color_set_hue(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + int hue_value) +{ + struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); + struct core_dc *core_dc = DC_TO_CORE(core_color->dc); + struct persistent_data_flag flag; + unsigned int stream_index, sink_index; + + for (stream_index = 0; stream_index < num_streams; stream_index++) { + sink_index = sink_index_from_sink(core_color, + streams[stream_index]->sink); + + struct core_stream *core_stream = + DC_STREAM_TO_CORE + (streams[stream_index]); + + core_color->state[sink_index].hue.current = hue_value; + + calculate_csc_matrix(core_color, sink_index, + core_stream->public.output_color_space, + core_stream->public.csc_color_matrix.matrix); + + core_stream->public.csc_color_matrix.enable_adjustment = true; + + /* Write persistent data in registry*/ + flag.save_per_edid = true; + flag.save_per_link = false; + dm_write_persistent_data(core_dc->ctx, + streams[stream_index]->sink, + COLOR_REGISTRY_NAME, + "hue", + &hue_value, + sizeof(int), + &flag); + } + + core_color->dc->stream_funcs.set_gamut_remap + (core_color->dc, streams, num_streams); + + return true; +} + +bool mod_color_set_saturation(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + int saturation_value) +{ + struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); + struct core_dc *core_dc = DC_TO_CORE(core_color->dc); + struct persistent_data_flag flag; + unsigned int stream_index, sink_index; + + for (stream_index = 0; stream_index < num_streams; stream_index++) { + sink_index = sink_index_from_sink(core_color, + streams[stream_index]->sink); + + struct core_stream *core_stream = + DC_STREAM_TO_CORE + (streams[stream_index]); + + core_color->state[sink_index].saturation.current = + saturation_value; + + calculate_csc_matrix(core_color, sink_index, + core_stream->public.output_color_space, + core_stream->public.csc_color_matrix.matrix); + + core_stream->public.csc_color_matrix.enable_adjustment = true; + + /* Write persistent data in registry*/ + flag.save_per_edid = true; + flag.save_per_link = false; + dm_write_persistent_data(core_dc->ctx, + streams[stream_index]->sink, + COLOR_REGISTRY_NAME, + "saturation", + &saturation_value, + sizeof(int), + &flag); + } + + core_color->dc->stream_funcs.set_gamut_remap + (core_color->dc, streams, num_streams); + + return true; +} + +bool mod_color_set_preferred_quantization_range(struct mod_color *mod_color, + const struct dc_sink *sink, + enum dc_quantization_range quantization_range) +{ + struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); + struct core_dc *core_dc = DC_TO_CORE(core_color->dc); + struct persistent_data_flag flag; + unsigned int sink_index; + + sink_index = sink_index_from_sink(core_color, sink); + if (core_color->state[sink_index]. + preferred_quantization_range != quantization_range) { + core_color->state[sink_index].preferred_quantization_range = + quantization_range; + flag.save_per_edid = true; + flag.save_per_link = false; + dm_write_persistent_data(core_dc->ctx, + sink, + COLOR_REGISTRY_NAME, + "quantization_range", + &quantization_range, + sizeof(int), + &flag); + } + + return true; +} + +bool mod_color_get_preferred_quantization_range(struct mod_color *mod_color, + const struct dc_sink *sink, + enum dc_quantization_range *quantization_range) +{ + struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); + unsigned int sink_index; + + sink_index = sink_index_from_sink(core_color, sink); + *quantization_range = core_color->state[sink_index]. + preferred_quantization_range; + return true; +} diff --git a/drivers/gpu/drm/amd/display/modules/freesync/Makefile b/drivers/gpu/drm/amd/display/modules/freesync/Makefile new file mode 100644 index 000000000000..db8e0ff6d7a9 --- /dev/null +++ b/drivers/gpu/drm/amd/display/modules/freesync/Makefile @@ -0,0 +1,10 @@ +# +# Makefile for the 'freesync' sub-module of DAL. +# + +FREESYNC = freesync.o + +AMD_DAL_FREESYNC = $(addprefix $(AMDDALPATH)/modules/freesync/,$(FREESYNC)) +#$(info ************ DAL-FREE SYNC_MAKEFILE ************) + +AMD_DISPLAY_FILES += $(AMD_DAL_FREESYNC) diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c new file mode 100644 index 000000000000..eb912baa0169 --- /dev/null +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -0,0 +1,1158 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "dc.h" +#include "mod_freesync.h" +#include "core_types.h" +#include "core_dc.h" + +#define MOD_FREESYNC_MAX_CONCURRENT_STREAMS 32 + +/* Refresh rate ramp at a fixed rate of 65 Hz/second */ +#define STATIC_SCREEN_RAMP_DELTA_REFRESH_RATE_PER_FRAME ((1000 / 60) * 65) +/* Number of elements in the render times cache array */ +#define RENDER_TIMES_MAX_COUNT 20 +/* Threshold to exit BTR (to avoid frequent enter-exits at the lower limit) */ +#define BTR_EXIT_MARGIN 2000 + +#define FREESYNC_REGISTRY_NAME "freesync_v1" + +struct gradual_static_ramp { + bool ramp_is_active; + bool ramp_direction_is_up; + unsigned int ramp_current_frame_duration_in_ns; +}; + +struct time_cache { + /* video (48Hz feature) related */ + unsigned int update_duration_in_ns; + + /* BTR/fixed refresh related */ + unsigned int prev_time_stamp_in_us; + + unsigned int min_render_time_in_us; + unsigned int max_render_time_in_us; + + unsigned int render_times_index; + unsigned int render_times[RENDER_TIMES_MAX_COUNT]; +}; + +struct below_the_range { + bool btr_active; + bool program_btr; + + unsigned int mid_point_in_us; + + unsigned int inserted_frame_duration_in_us; + unsigned int frames_to_insert; + unsigned int frame_counter; +}; + +struct fixed_refresh { + bool fixed_refresh_active; + bool program_fixed_refresh; +}; + +struct freesync_state { + bool fullscreen; + bool static_screen; + bool video; + + unsigned int nominal_refresh_rate_in_micro_hz; + bool windowed_fullscreen; + + struct time_cache time; + + struct gradual_static_ramp static_ramp; + struct below_the_range btr; + struct fixed_refresh fixed_refresh; +}; + +struct freesync_entity { + const struct dc_stream *stream; + struct mod_freesync_caps *caps; + struct freesync_state state; + struct mod_freesync_user_enable user_enable; +}; + +struct core_freesync { + struct mod_freesync public; + struct dc *dc; + struct freesync_entity *map; + int num_entities; +}; + +#define MOD_FREESYNC_TO_CORE(mod_freesync)\ + container_of(mod_freesync, struct core_freesync, public) + +static bool check_dc_support(const struct dc *dc) +{ + if (dc->stream_funcs.adjust_vmin_vmax == NULL) + return false; + + return true; +} + +struct mod_freesync *mod_freesync_create(struct dc *dc) +{ + struct core_freesync *core_freesync = + dm_alloc(sizeof(struct core_freesync)); + + struct core_dc *core_dc = DC_TO_CORE(dc); + + struct persistent_data_flag flag; + + int i = 0; + + if (core_freesync == NULL) + goto fail_alloc_context; + + core_freesync->map = dm_alloc(sizeof(struct freesync_entity) * + MOD_FREESYNC_MAX_CONCURRENT_STREAMS); + + if (core_freesync->map == NULL) + goto fail_alloc_map; + + for (i = 0; i < MOD_FREESYNC_MAX_CONCURRENT_STREAMS; i++) + core_freesync->map[i].stream = NULL; + + core_freesync->num_entities = 0; + + if (dc == NULL) + goto fail_construct; + + core_freesync->dc = dc; + + if (!check_dc_support(dc)) + goto fail_construct; + + /* Create initial module folder in registry for freesync enable data */ + flag.save_per_edid = true; + flag.save_per_link = false; + dm_write_persistent_data(core_dc->ctx, NULL, FREESYNC_REGISTRY_NAME, NULL, NULL, + 0, &flag); + + return &core_freesync->public; + +fail_construct: + dm_free(core_freesync->map); + +fail_alloc_map: + dm_free(core_freesync); + +fail_alloc_context: + return NULL; +} + +void mod_freesync_destroy(struct mod_freesync *mod_freesync) +{ + if (mod_freesync != NULL) { + int i; + struct core_freesync *core_freesync = + MOD_FREESYNC_TO_CORE(mod_freesync); + + for (i = 0; i < core_freesync->num_entities; i++) + if (core_freesync->map[i].stream) + dc_stream_release(core_freesync->map[i].stream); + + dm_free(core_freesync->map); + + dm_free(core_freesync); + } +} + +/* Given a specific dc_stream* this function finds its equivalent + * on the core_freesync->map and returns the corresponding index + */ +static unsigned int map_index_from_stream(struct core_freesync *core_freesync, + const struct dc_stream *stream) +{ + unsigned int index = 0; + + for (index = 0; index < core_freesync->num_entities; index++) { + if (core_freesync->map[index].stream == stream) { + return index; + } + } + /* Could not find stream requested */ + ASSERT(false); + return index; +} + +bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, + const struct dc_stream *stream, struct mod_freesync_caps *caps) +{ + struct core_freesync *core_freesync = + MOD_FREESYNC_TO_CORE(mod_freesync); + struct core_stream *core_stream = + DC_STREAM_TO_CORE(stream); + struct core_dc *core_dc = DC_TO_CORE(core_freesync->dc); + + int persistent_freesync_enable = 0; + struct persistent_data_flag flag; + + flag.save_per_edid = true; + flag.save_per_link = false; + + if (core_freesync->num_entities < MOD_FREESYNC_MAX_CONCURRENT_STREAMS) { + + dc_stream_retain(stream); + + core_freesync->map[core_freesync->num_entities].stream = stream; + core_freesync->map[core_freesync->num_entities].caps = caps; + + core_freesync->map[core_freesync->num_entities].state. + fullscreen = false; + core_freesync->map[core_freesync->num_entities].state. + static_screen = false; + core_freesync->map[core_freesync->num_entities].state. + video = false; + core_freesync->map[core_freesync->num_entities].state.time. + update_duration_in_ns = 0; + core_freesync->map[core_freesync->num_entities].state. + static_ramp.ramp_is_active = false; + + /* get persistent data from registry */ + if (dm_read_persistent_data(core_dc->ctx, stream->sink, + FREESYNC_REGISTRY_NAME, + "userenable", &persistent_freesync_enable, + sizeof(int), &flag)) { + core_freesync->map[core_freesync->num_entities].user_enable. + enable_for_gaming = + (persistent_freesync_enable & 1) ? true : false; + core_freesync->map[core_freesync->num_entities].user_enable. + enable_for_static = + (persistent_freesync_enable & 2) ? true : false; + core_freesync->map[core_freesync->num_entities].user_enable. + enable_for_video = + (persistent_freesync_enable & 4) ? true : false; + } else { + core_freesync->map[core_freesync->num_entities].user_enable. + enable_for_gaming = false; + core_freesync->map[core_freesync->num_entities].user_enable. + enable_for_static = false; + core_freesync->map[core_freesync->num_entities].user_enable. + enable_for_video = false; + } + + if (caps->supported) + core_stream->public.ignore_msa_timing_param = 1; + + core_freesync->num_entities++; + return true; + } + return false; +} + +bool mod_freesync_remove_stream(struct mod_freesync *mod_freesync, + const struct dc_stream *stream) +{ + struct core_freesync *core_freesync = + MOD_FREESYNC_TO_CORE(mod_freesync); + + int i = 0; + unsigned int index = map_index_from_stream(core_freesync, stream); + dc_stream_release(core_freesync->map[index].stream); + core_freesync->map[index].stream = NULL; + /* To remove this entity, shift everything after down */ + for (i = index; i < core_freesync->num_entities - 1; i++) + core_freesync->map[i] = core_freesync->map[i + 1]; + core_freesync->num_entities--; + return true; +} + +static void update_stream_freesync_context(struct core_freesync *core_freesync, + const struct dc_stream *stream) +{ + unsigned int index; + struct freesync_context *ctx; + struct core_stream *core_stream; + + core_stream = DC_STREAM_TO_CORE(stream); + ctx = &core_stream->public.freesync_ctx; + + index = map_index_from_stream(core_freesync, stream); + + ctx->supported = core_freesync->map[index].caps->supported; + ctx->enabled = (core_freesync->map[index].user_enable.enable_for_gaming || + core_freesync->map[index].user_enable.enable_for_video || + core_freesync->map[index].user_enable.enable_for_static); + ctx->active = (core_freesync->map[index].state.fullscreen || + core_freesync->map[index].state.video || + core_freesync->map[index].state.static_ramp.ramp_is_active); + ctx->min_refresh_in_micro_hz = + core_freesync->map[index].caps->min_refresh_in_micro_hz; + ctx->nominal_refresh_in_micro_hz = core_freesync-> + map[index].state.nominal_refresh_rate_in_micro_hz; + +} + +static void update_stream(struct core_freesync *core_freesync, + const struct dc_stream *stream) +{ + struct core_stream *core_stream = DC_STREAM_TO_CORE(stream); + + unsigned int index = map_index_from_stream(core_freesync, stream); + if (core_freesync->map[index].caps->supported) { + core_stream->public.ignore_msa_timing_param = 1; + update_stream_freesync_context(core_freesync, stream); + } +} + +static void calc_vmin_vmax(struct core_freesync *core_freesync, + const struct dc_stream *stream, int *vmin, int *vmax) +{ + unsigned int min_frame_duration_in_ns = 0, max_frame_duration_in_ns = 0; + unsigned int index = map_index_from_stream(core_freesync, stream); + + min_frame_duration_in_ns = ((unsigned int) (div64_u64( + (1000000000ULL * 1000000), + core_freesync->map[index].state. + nominal_refresh_rate_in_micro_hz))); + max_frame_duration_in_ns = ((unsigned int) (div64_u64( + (1000000000ULL * 1000000), + core_freesync->map[index].caps->min_refresh_in_micro_hz))); + + *vmax = div64_u64(div64_u64(((unsigned long long)( + max_frame_duration_in_ns) * stream->timing.pix_clk_khz), + stream->timing.h_total), 1000000); + *vmin = div64_u64(div64_u64(((unsigned long long)( + min_frame_duration_in_ns) * stream->timing.pix_clk_khz), + stream->timing.h_total), 1000000); +} + +static void calc_v_total_from_duration(const struct dc_stream *stream, + unsigned int duration_in_ns, int *v_total_nominal) +{ + *v_total_nominal = div64_u64(div64_u64(((unsigned long long)( + duration_in_ns) * stream->timing.pix_clk_khz), + stream->timing.h_total), 1000000); +} + +static void calc_v_total_for_static_ramp(struct core_freesync *core_freesync, + const struct dc_stream *stream, + unsigned int index, int *v_total) +{ + unsigned int frame_duration = 0; + + struct gradual_static_ramp *static_ramp_variables = + &core_freesync->map[index].state.static_ramp; + + /* Calc ratio between new and current frame duration with 3 digit */ + unsigned int frame_duration_ratio = div64_u64(1000000, + (1000 + div64_u64(((unsigned long long)( + STATIC_SCREEN_RAMP_DELTA_REFRESH_RATE_PER_FRAME) * + static_ramp_variables->ramp_current_frame_duration_in_ns), + 1000000000))); + + /* Calculate delta between new and current frame duration in ns */ + unsigned int frame_duration_delta = div64_u64(((unsigned long long)( + static_ramp_variables->ramp_current_frame_duration_in_ns) * + (1000 - frame_duration_ratio)), 1000); + + /* Adjust frame duration delta based on ratio between current and + * standard frame duration (frame duration at 60 Hz refresh rate). + */ + unsigned int ramp_rate_interpolated = div64_u64(((unsigned long long)( + frame_duration_delta) * static_ramp_variables-> + ramp_current_frame_duration_in_ns), 16666666); + + /* Going to a higher refresh rate (lower frame duration) */ + if (static_ramp_variables->ramp_direction_is_up) { + /* reduce frame duration */ + static_ramp_variables->ramp_current_frame_duration_in_ns -= + ramp_rate_interpolated; + + /* min frame duration */ + frame_duration = ((unsigned int) (div64_u64( + (1000000000ULL * 1000000), + core_freesync->map[index].state. + nominal_refresh_rate_in_micro_hz))); + + /* adjust for frame duration below min */ + if (static_ramp_variables->ramp_current_frame_duration_in_ns <= + frame_duration) { + + static_ramp_variables->ramp_is_active = false; + static_ramp_variables-> + ramp_current_frame_duration_in_ns = + frame_duration; + } + /* Going to a lower refresh rate (larger frame duration) */ + } else { + /* increase frame duration */ + static_ramp_variables->ramp_current_frame_duration_in_ns += + ramp_rate_interpolated; + + /* max frame duration */ + frame_duration = ((unsigned int) (div64_u64( + (1000000000ULL * 1000000), + core_freesync->map[index].caps->min_refresh_in_micro_hz))); + + /* adjust for frame duration above max */ + if (static_ramp_variables->ramp_current_frame_duration_in_ns >= + frame_duration) { + + static_ramp_variables->ramp_is_active = false; + static_ramp_variables-> + ramp_current_frame_duration_in_ns = + frame_duration; + } + } + + calc_v_total_from_duration(stream, static_ramp_variables-> + ramp_current_frame_duration_in_ns, v_total); +} + +static void reset_freesync_state_variables(struct freesync_state* state) +{ + state->static_ramp.ramp_is_active = false; + if (state->nominal_refresh_rate_in_micro_hz) + state->static_ramp.ramp_current_frame_duration_in_ns = + ((unsigned int) (div64_u64( + (1000000000ULL * 1000000), + state->nominal_refresh_rate_in_micro_hz))); + + state->btr.btr_active = false; + state->btr.frame_counter = 0; + state->btr.frames_to_insert = 0; + state->btr.inserted_frame_duration_in_us = 0; + state->btr.program_btr = false; + + state->fixed_refresh.fixed_refresh_active = false; + state->fixed_refresh.program_fixed_refresh = false; +} +/* + * Sets freesync mode on a stream depending on current freesync state. + */ +static bool set_freesync_on_streams(struct core_freesync *core_freesync, + const struct dc_stream **streams, int num_streams) +{ + int v_total_nominal = 0, v_total_min = 0, v_total_max = 0; + unsigned int stream_idx, map_index = 0; + struct freesync_state *state; + + if (num_streams == 0 || streams == NULL || num_streams > 1) + return false; + + for (stream_idx = 0; stream_idx < num_streams; stream_idx++) { + + map_index = map_index_from_stream(core_freesync, + streams[stream_idx]); + + state = &core_freesync->map[map_index].state; + + if (core_freesync->map[map_index].caps->supported) { + + /* Fullscreen has the topmost priority. If the + * fullscreen bit is set, we are in a fullscreen + * application where it should not matter if it is + * static screen. We should not check the static_screen + * or video bit. + * + * Special cases of fullscreen include btr and fixed + * refresh. We program btr on every flip and involves + * programming full range right before the last inserted frame. + * However, we do not want to program the full freesync range + * when fixed refresh is active, because we only program + * that logic once and this will override it. + */ + if (core_freesync->map[map_index].user_enable. + enable_for_gaming == true && + state->fullscreen == true && + state->fixed_refresh.fixed_refresh_active == false) { + /* Enable freesync */ + + calc_vmin_vmax(core_freesync, + streams[stream_idx], + &v_total_min, &v_total_max); + + /* Update the freesync context for the stream */ + update_stream_freesync_context(core_freesync, + streams[stream_idx]); + + core_freesync->dc->stream_funcs. + adjust_vmin_vmax(core_freesync->dc, streams, + num_streams, v_total_min, + v_total_max); + + return true; + + } else if (core_freesync->map[map_index].user_enable. + enable_for_video && state->video == true) { + /* Enable 48Hz feature */ + + calc_v_total_from_duration(streams[stream_idx], + state->time.update_duration_in_ns, + &v_total_nominal); + + /* Program only if v_total_nominal is in range*/ + if (v_total_nominal >= + streams[stream_idx]->timing.v_total) { + + /* Update the freesync context for + * the stream + */ + update_stream_freesync_context( + core_freesync, + streams[stream_idx]); + + core_freesync->dc->stream_funcs. + adjust_vmin_vmax( + core_freesync->dc, streams, + num_streams, v_total_nominal, + v_total_nominal); + } + return true; + + } else { + /* Disable freesync */ + v_total_nominal = streams[stream_idx]-> + timing.v_total; + + /* Update the freesync context for + * the stream + */ + update_stream_freesync_context( + core_freesync, + streams[stream_idx]); + + core_freesync->dc->stream_funcs. + adjust_vmin_vmax( + core_freesync->dc, streams, + num_streams, v_total_nominal, + v_total_nominal); + + /* Reset the cached variables */ + reset_freesync_state_variables(state); + + return true; + } + } else { + /* Disable freesync */ + v_total_nominal = streams[stream_idx]-> + timing.v_total; + /* + * we have to reset drr always even sink does + * not support freesync because a former stream has + * be programmed + */ + core_freesync->dc->stream_funcs. + adjust_vmin_vmax( + core_freesync->dc, streams, + num_streams, v_total_nominal, + v_total_nominal); + /* Reset the cached variables */ + reset_freesync_state_variables(state); + } + + } + + return false; +} + +static void set_static_ramp_variables(struct core_freesync *core_freesync, + unsigned int index, bool enable_static_screen) +{ + unsigned int frame_duration = 0; + + struct gradual_static_ramp *static_ramp_variables = + &core_freesync->map[index].state.static_ramp; + + /* If ramp is not active, set initial frame duration depending on + * whether we are enabling/disabling static screen mode. If the ramp is + * already active, ramp should continue in the opposite direction + * starting with the current frame duration + */ + if (!static_ramp_variables->ramp_is_active) { + + static_ramp_variables->ramp_is_active = true; + + if (enable_static_screen == true) { + /* Going to lower refresh rate, so start from max + * refresh rate (min frame duration) + */ + frame_duration = ((unsigned int) (div64_u64( + (1000000000ULL * 1000000), + core_freesync->map[index].state. + nominal_refresh_rate_in_micro_hz))); + } else { + /* Going to higher refresh rate, so start from min + * refresh rate (max frame duration) + */ + frame_duration = ((unsigned int) (div64_u64( + (1000000000ULL * 1000000), + core_freesync->map[index].caps->min_refresh_in_micro_hz))); + } + + static_ramp_variables-> + ramp_current_frame_duration_in_ns = frame_duration; + } + + /* If we are ENABLING static screen, refresh rate should go DOWN. + * If we are DISABLING static screen, refresh rate should go UP. + */ + static_ramp_variables->ramp_direction_is_up = !enable_static_screen; +} + +void mod_freesync_handle_v_update(struct mod_freesync *mod_freesync, + const struct dc_stream **streams, int num_streams) +{ + struct core_freesync *core_freesync = + MOD_FREESYNC_TO_CORE(mod_freesync); + + unsigned int index, v_total = 0; + struct freesync_state *state; + + if (core_freesync->num_entities == 0) + return; + + index = map_index_from_stream(core_freesync, + streams[0]); + + if (core_freesync->map[index].caps->supported == false) + return; + + state = &core_freesync->map[index].state; + + /* Below the Range Logic */ + + /* Only execute if in fullscreen mode */ + if (state->fullscreen == true && + core_freesync->map[index].user_enable.enable_for_gaming) { + + if (state->btr.btr_active) + if (state->btr.frame_counter > 0) + + state->btr.frame_counter--; + + if (state->btr.frame_counter == 1) { + + /* Restore FreeSync */ + set_freesync_on_streams(core_freesync, streams, + num_streams); + } + } + + /* If in fullscreen freesync mode or in video, do not program + * static screen ramp values + */ + if (state->fullscreen == true || state->video == true) { + + state->static_ramp.ramp_is_active = false; + + return; + } + + /* Gradual Static Screen Ramping Logic */ + + /* Execute if ramp is active and user enabled freesync static screen*/ + if (state->static_ramp.ramp_is_active && + core_freesync->map[index].user_enable.enable_for_static) { + + calc_v_total_for_static_ramp(core_freesync, streams[0], + index, &v_total); + + /* Update the freesync context for the stream */ + update_stream_freesync_context(core_freesync, streams[0]); + + /* Program static screen ramp values */ + core_freesync->dc->stream_funcs.adjust_vmin_vmax( + core_freesync->dc, streams, + num_streams, v_total, + v_total); + } +} + +void mod_freesync_update_state(struct mod_freesync *mod_freesync, + const struct dc_stream **streams, int num_streams, + struct mod_freesync_params *freesync_params) +{ + struct core_freesync *core_freesync = + MOD_FREESYNC_TO_CORE(mod_freesync); + bool freesync_program_required = false; + unsigned int stream_index; + struct freesync_state *state; + + if (core_freesync->num_entities == 0) + return; + + for(stream_index = 0; stream_index < num_streams; stream_index++) { + + unsigned int map_index = map_index_from_stream(core_freesync, + streams[stream_index]); + + state = &core_freesync->map[map_index].state; + + switch (freesync_params->state){ + case FREESYNC_STATE_FULLSCREEN: + state->fullscreen = freesync_params->enable; + freesync_program_required = true; + state->windowed_fullscreen = + freesync_params->windowed_fullscreen; + break; + case FREESYNC_STATE_STATIC_SCREEN: + /* Static screen ramp is only enabled for embedded + * panels. Also change core variables only if there + * is a change. + */ + if (dc_is_embedded_signal( + streams[stream_index]->sink->sink_signal) && + state->static_screen != + freesync_params->enable) { + + /* Change the state flag */ + state->static_screen = freesync_params->enable; + + /* Change static screen ramp variables */ + set_static_ramp_variables(core_freesync, + map_index, + freesync_params->enable); + } + /* We program the ramp starting next VUpdate */ + break; + case FREESYNC_STATE_VIDEO: + /* Change core variables only if there is a change*/ + if(freesync_params->update_duration_in_ns != + state->time.update_duration_in_ns) { + + state->video = freesync_params->enable; + state->time.update_duration_in_ns = + freesync_params->update_duration_in_ns; + + freesync_program_required = true; + } + break; + } + } + + if (freesync_program_required) + /* Program freesync according to current state*/ + set_freesync_on_streams(core_freesync, streams, num_streams); +} + + +bool mod_freesync_get_state(struct mod_freesync *mod_freesync, + const struct dc_stream *stream, + struct mod_freesync_params *freesync_params) +{ + struct core_freesync *core_freesync = + MOD_FREESYNC_TO_CORE(mod_freesync); + + unsigned int index = map_index_from_stream(core_freesync, stream); + + if (core_freesync->map[index].state.fullscreen) { + freesync_params->state = FREESYNC_STATE_FULLSCREEN; + freesync_params->enable = true; + } else if (core_freesync->map[index].state.static_screen) { + freesync_params->state = FREESYNC_STATE_STATIC_SCREEN; + freesync_params->enable = true; + } else if (core_freesync->map[index].state.video) { + freesync_params->state = FREESYNC_STATE_VIDEO; + freesync_params->enable = true; + } else { + freesync_params->state = FREESYNC_STATE_NONE; + freesync_params->enable = false; + } + + freesync_params->update_duration_in_ns = + core_freesync->map[index].state.time.update_duration_in_ns; + + return true; +} + +bool mod_freesync_set_user_enable(struct mod_freesync *mod_freesync, + const struct dc_stream **streams, int num_streams, + struct mod_freesync_user_enable *user_enable) +{ + struct core_freesync *core_freesync = + MOD_FREESYNC_TO_CORE(mod_freesync); + struct core_dc *core_dc = DC_TO_CORE(core_freesync->dc); + + unsigned int stream_index, map_index; + int persistent_data = 0; + struct persistent_data_flag flag; + + flag.save_per_edid = true; + flag.save_per_link = false; + + for(stream_index = 0; stream_index < num_streams; + stream_index++){ + + map_index = map_index_from_stream(core_freesync, + streams[stream_index]); + + core_freesync->map[map_index].user_enable = *user_enable; + + /* Write persistent data in registry*/ + if (core_freesync->map[map_index].user_enable. + enable_for_gaming) + persistent_data = persistent_data | 1; + if (core_freesync->map[map_index].user_enable. + enable_for_static) + persistent_data = persistent_data | 2; + if (core_freesync->map[map_index].user_enable. + enable_for_video) + persistent_data = persistent_data | 4; + + dm_write_persistent_data(core_dc->ctx, + streams[stream_index]->sink, + FREESYNC_REGISTRY_NAME, + "userenable", + &persistent_data, + sizeof(int), + &flag); + } + + set_freesync_on_streams(core_freesync, streams, num_streams); + + return true; +} + +bool mod_freesync_get_user_enable(struct mod_freesync *mod_freesync, + const struct dc_stream *stream, + struct mod_freesync_user_enable *user_enable) +{ + struct core_freesync *core_freesync = + MOD_FREESYNC_TO_CORE(mod_freesync); + + unsigned int index = map_index_from_stream(core_freesync, stream); + + *user_enable = core_freesync->map[index].user_enable; + + return true; +} + +void mod_freesync_notify_mode_change(struct mod_freesync *mod_freesync, + const struct dc_stream **streams, int num_streams) +{ + struct core_freesync *core_freesync = + MOD_FREESYNC_TO_CORE(mod_freesync); + + unsigned int stream_index, map_index; + unsigned min_frame_duration_in_ns, max_frame_duration_in_ns; + struct freesync_state *state; + + for (stream_index = 0; stream_index < num_streams; stream_index++) { + + map_index = map_index_from_stream(core_freesync, + streams[stream_index]); + + state = &core_freesync->map[map_index].state; + + if (core_freesync->map[map_index].caps->supported) { + /* Update the field rate for new timing */ + state->nominal_refresh_rate_in_micro_hz = 1000000 * + div64_u64(div64_u64((streams[stream_index]-> + timing.pix_clk_khz * 1000), + streams[stream_index]->timing.v_total), + streams[stream_index]->timing.h_total); + + /* Update the stream */ + update_stream(core_freesync, streams[stream_index]); + + /* Determine whether BTR can be supported */ + min_frame_duration_in_ns = ((unsigned int) (div64_u64( + (1000000000ULL * 1000000), + state->nominal_refresh_rate_in_micro_hz))); + + max_frame_duration_in_ns = ((unsigned int) (div64_u64( + (1000000000ULL * 1000000), + core_freesync->map[map_index].caps->min_refresh_in_micro_hz))); + + if (max_frame_duration_in_ns >= + 2 * min_frame_duration_in_ns) + core_freesync->map[map_index].caps->btr_supported = true; + else + core_freesync->map[map_index].caps->btr_supported = false; + + /* Cache the time variables */ + state->time.max_render_time_in_us = + max_frame_duration_in_ns / 1000; + state->time.min_render_time_in_us = + min_frame_duration_in_ns / 1000; + state->btr.mid_point_in_us = + (max_frame_duration_in_ns + + min_frame_duration_in_ns) / 2000; + + } + } + + /* Program freesync according to current state*/ + set_freesync_on_streams(core_freesync, streams, num_streams); +} + +/* Add the timestamps to the cache and determine whether BTR programming + * is required, depending on the times calculated + */ +static void update_timestamps(struct core_freesync *core_freesync, + const struct dc_stream *stream, unsigned int map_index, + unsigned int last_render_time_in_us) +{ + struct freesync_state *state = &core_freesync->map[map_index].state; + + state->time.render_times[state->time.render_times_index] = + last_render_time_in_us; + state->time.render_times_index++; + + if (state->time.render_times_index >= RENDER_TIMES_MAX_COUNT) + state->time.render_times_index = 0; + + if (last_render_time_in_us + BTR_EXIT_MARGIN < + state->time.max_render_time_in_us) { + + /* Exit Below the Range */ + if (state->btr.btr_active) { + + state->btr.program_btr = true; + state->btr.btr_active = false; + state->btr.frame_counter = 0; + + /* Exit Fixed Refresh mode */ + } else if (state->fixed_refresh.fixed_refresh_active) { + + state->fixed_refresh.program_fixed_refresh = true; + state->fixed_refresh.fixed_refresh_active = false; + + } + + } else if (last_render_time_in_us > state->time.max_render_time_in_us) { + + /* Enter Below the Range */ + if (!state->btr.btr_active && + core_freesync->map[map_index].caps->btr_supported) { + + state->btr.program_btr = true; + state->btr.btr_active = true; + + /* Enter Fixed Refresh mode */ + } else if (!state->fixed_refresh.fixed_refresh_active && + !core_freesync->map[map_index].caps->btr_supported) { + + state->fixed_refresh.program_fixed_refresh = true; + state->fixed_refresh.fixed_refresh_active = true; + + } + } + + /* When Below the Range is active, must react on every frame */ + if (state->btr.btr_active) + state->btr.program_btr = true; +} + +static void apply_below_the_range(struct core_freesync *core_freesync, + const struct dc_stream *stream, unsigned int map_index, + unsigned int last_render_time_in_us) +{ + unsigned int inserted_frame_duration_in_us = 0; + unsigned int mid_point_frames_ceil = 0; + unsigned int mid_point_frames_floor = 0; + unsigned int frame_time_in_us = 0; + unsigned int delta_from_mid_point_in_us_1 = 0xFFFFFFFF; + unsigned int delta_from_mid_point_in_us_2 = 0xFFFFFFFF; + unsigned int frames_to_insert = 0; + unsigned int inserted_frame_v_total = 0; + unsigned int vmin = 0, vmax = 0; + unsigned int min_frame_duration_in_ns = 0; + struct freesync_state *state = &core_freesync->map[map_index].state; + + if (!state->btr.program_btr) + return; + + state->btr.program_btr = false; + + min_frame_duration_in_ns = ((unsigned int) (div64_u64( + (1000000000ULL * 1000000), + state->nominal_refresh_rate_in_micro_hz))); + + /* Program BTR */ + + /* BTR set to "not active" so disengage */ + if (!state->btr.btr_active) + + /* Restore FreeSync */ + set_freesync_on_streams(core_freesync, &stream, 1); + + /* BTR set to "active" so engage */ + else { + + /* Calculate number of midPoint frames that could fit within + * the render time interval- take ceil of this value + */ + mid_point_frames_ceil = (last_render_time_in_us + + state->btr.mid_point_in_us- 1) / + state->btr.mid_point_in_us; + + if (mid_point_frames_ceil > 0) { + + frame_time_in_us = last_render_time_in_us / + mid_point_frames_ceil; + delta_from_mid_point_in_us_1 = (state->btr.mid_point_in_us > + frame_time_in_us) ? + (state->btr.mid_point_in_us - frame_time_in_us): + (frame_time_in_us - state->btr.mid_point_in_us); + } + + /* Calculate number of midPoint frames that could fit within + * the render time interval- take floor of this value + */ + mid_point_frames_floor = last_render_time_in_us / + state->btr.mid_point_in_us; + + if (mid_point_frames_floor > 0) { + + frame_time_in_us = last_render_time_in_us / + mid_point_frames_floor; + delta_from_mid_point_in_us_2 = (state->btr.mid_point_in_us > + frame_time_in_us) ? + (state->btr.mid_point_in_us - frame_time_in_us): + (frame_time_in_us - state->btr.mid_point_in_us); + } + + /* Choose number of frames to insert based on how close it + * can get to the mid point of the variable range. + */ + if (delta_from_mid_point_in_us_1 < delta_from_mid_point_in_us_2) + frames_to_insert = mid_point_frames_ceil; + else + frames_to_insert = mid_point_frames_floor; + + /* Either we've calculated the number of frames to insert, + * or we need to insert min duration frames + */ + if (frames_to_insert > 0) + inserted_frame_duration_in_us = last_render_time_in_us / + frames_to_insert; + + if (inserted_frame_duration_in_us < + state->time.min_render_time_in_us) + + inserted_frame_duration_in_us = + state->time.min_render_time_in_us; + + /* We need the v_total_min from capability */ + calc_vmin_vmax(core_freesync, stream, &vmin, &vmax); + + inserted_frame_v_total = vmin; + if (min_frame_duration_in_ns / 1000) + inserted_frame_v_total = inserted_frame_duration_in_us * + vmin / (min_frame_duration_in_ns / 1000); + + /* Set length of inserted frames as v_total_max*/ + vmax = inserted_frame_v_total; + + /* Program V_TOTAL */ + core_freesync->dc->stream_funcs.adjust_vmin_vmax( + core_freesync->dc, &stream, + 1, vmin, + vmax); + + /* Cache the calculated variables */ + state->btr.inserted_frame_duration_in_us = + inserted_frame_duration_in_us; + state->btr.frames_to_insert = frames_to_insert; + state->btr.frame_counter = frames_to_insert; + + } +} + +static void apply_fixed_refresh(struct core_freesync *core_freesync, + const struct dc_stream *stream, unsigned int map_index) +{ + unsigned int vmin = 0, vmax = 0; + struct freesync_state *state = &core_freesync->map[map_index].state; + + if (!state->fixed_refresh.program_fixed_refresh) + return; + + state->fixed_refresh.program_fixed_refresh = false; + + /* Program Fixed Refresh */ + + /* Fixed Refresh set to "not active" so disengage */ + if (!state->fixed_refresh.fixed_refresh_active) { + set_freesync_on_streams(core_freesync, &stream, 1); + + /* Fixed Refresh set to "active" so engage (fix to max) */ + } else { + + calc_vmin_vmax(core_freesync, stream, &vmin, &vmax); + + vmax = vmin; + + core_freesync->dc->stream_funcs.adjust_vmin_vmax( + core_freesync->dc, &stream, + 1, vmin, + vmax); + } +} + +void mod_freesync_pre_update_plane_addresses(struct mod_freesync *mod_freesync, + const struct dc_stream **streams, int num_streams, + unsigned int curr_time_stamp_in_us) +{ + unsigned int stream_index, map_index, last_render_time_in_us = 0; + struct core_freesync *core_freesync = + MOD_FREESYNC_TO_CORE(mod_freesync); + + for (stream_index = 0; stream_index < num_streams; stream_index++) { + + map_index = map_index_from_stream(core_freesync, + streams[stream_index]); + + if (core_freesync->map[map_index].caps->supported) { + + last_render_time_in_us = curr_time_stamp_in_us - + core_freesync->map[map_index].state.time. + prev_time_stamp_in_us; + + /* Add the timestamps to the cache and determine + * whether BTR program is required + */ + update_timestamps(core_freesync, streams[stream_index], + map_index, last_render_time_in_us); + + if (core_freesync->map[map_index].state.fullscreen && + core_freesync->map[map_index].user_enable. + enable_for_gaming) { + + if (core_freesync->map[map_index].caps->btr_supported) { + + apply_below_the_range(core_freesync, + streams[stream_index], map_index, + last_render_time_in_us); + } else { + apply_fixed_refresh(core_freesync, + streams[stream_index], map_index); + } + } + + core_freesync->map[map_index].state.time. + prev_time_stamp_in_us = curr_time_stamp_in_us; + } + + } +} diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_color.h b/drivers/gpu/drm/amd/display/modules/inc/mod_color.h new file mode 100644 index 000000000000..e54fe2cb8611 --- /dev/null +++ b/drivers/gpu/drm/amd/display/modules/inc/mod_color.h @@ -0,0 +1,179 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + + +#ifndef MOD_COLOR_H_ +#define MOD_COLOR_H_ + +#include "dm_services.h" + +struct mod_color { + int dummy; +}; + +struct color_space_coordinates { + unsigned int redX; + unsigned int redY; + unsigned int greenX; + unsigned int greenY; + unsigned int blueX; + unsigned int blueY; + unsigned int whiteX; + unsigned int whiteY; +}; + +struct gamut_space_coordinates { + unsigned int redX; + unsigned int redY; + unsigned int greenX; + unsigned int greenY; + unsigned int blueX; + unsigned int blueY; +}; + +struct gamut_space_entry { + unsigned int index; + unsigned int redX; + unsigned int redY; + unsigned int greenX; + unsigned int greenY; + unsigned int blueX; + unsigned int blueY; + + int a0; + int a1; + int a2; + int a3; + int gamma; +}; + +struct white_point_coodinates { + unsigned int whiteX; + unsigned int whiteY; +}; + +struct white_point_coodinates_entry { + unsigned int index; + unsigned int whiteX; + unsigned int whiteY; +}; + +struct color_range { + int current; + int min; + int max; +}; + +struct mod_color *mod_color_create(struct dc *dc); + +void mod_color_destroy(struct mod_color *mod_color); + +bool mod_color_add_sink(struct mod_color *mod_color, + const struct dc_sink *sink); + +bool mod_color_remove_sink(struct mod_color *mod_color, + const struct dc_sink *sink); + +bool mod_color_update_gamut_to_stream(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams); + +bool mod_color_set_white_point(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + struct white_point_coodinates *white_point); + +bool mod_color_adjust_source_gamut(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + struct gamut_space_coordinates *input_gamut_coordinates, + struct white_point_coodinates *input_white_point_coordinates); + +bool mod_color_adjust_destination_gamut(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + struct gamut_space_coordinates *input_gamut_coordinates, + struct white_point_coodinates *input_white_point_coordinates); + +bool mod_color_get_user_enable(struct mod_color *mod_color, + const struct dc_sink *sink, + bool *user_enable); + +bool mod_color_set_user_enable(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + bool user_enable); + +bool mod_color_get_custom_color_temperature(struct mod_color *mod_color, + const struct dc_sink *sink, + int *color_temperature); + +bool mod_color_set_custom_color_temperature(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + int color_temperature); + +bool mod_color_get_color_saturation(struct mod_color *mod_color, + const struct dc_sink *sink, + struct color_range *color_saturation); + +bool mod_color_get_color_contrast(struct mod_color *mod_color, + const struct dc_sink *sink, + struct color_range *color_contrast); + +bool mod_color_get_color_brightness(struct mod_color *mod_color, + const struct dc_sink *sink, + struct color_range *color_brightness); + +bool mod_color_get_color_hue(struct mod_color *mod_color, + const struct dc_sink *sink, + struct color_range *color_hue); + +bool mod_color_get_source_gamut(struct mod_color *mod_color, + const struct dc_sink *sink, + struct color_space_coordinates *source_gamut); + +bool mod_color_notify_mode_change(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams); + +bool mod_color_set_brightness(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + int brightness_value); + +bool mod_color_set_contrast(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + int contrast_value); + +bool mod_color_set_hue(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + int hue_value); + +bool mod_color_set_saturation(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + int saturation_value); + +bool mod_color_set_preferred_quantization_range(struct mod_color *mod_color, + const struct dc_sink *sink, + enum dc_quantization_range quantization_range); + +bool mod_color_get_preferred_quantization_range(struct mod_color *mod_color, + const struct dc_sink *sink, + enum dc_quantization_range *quantization_range); + +#endif /* MOD_COLOR_H_ */ diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h b/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h new file mode 100644 index 000000000000..7abfe34dc2d9 --- /dev/null +++ b/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h @@ -0,0 +1,149 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + + + + +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef MOD_FREESYNC_H_ +#define MOD_FREESYNC_H_ + +#include "dm_services.h" + +struct mod_freesync *mod_freesync_create(struct dc *dc); +void mod_freesync_destroy(struct mod_freesync *mod_freesync); + +struct mod_freesync { + int dummy; +}; + +enum mod_freesync_state { + FREESYNC_STATE_NONE, + FREESYNC_STATE_FULLSCREEN, + FREESYNC_STATE_STATIC_SCREEN, + FREESYNC_STATE_VIDEO +}; + +enum mod_freesync_user_enable_mask { + FREESYNC_USER_ENABLE_STATIC = 0x1, + FREESYNC_USER_ENABLE_VIDEO = 0x2, + FREESYNC_USER_ENABLE_GAMING = 0x4 +}; + +struct mod_freesync_user_enable { + bool enable_for_static; + bool enable_for_video; + bool enable_for_gaming; +}; + +struct mod_freesync_caps { + bool supported; + unsigned int min_refresh_in_micro_hz; + unsigned int max_refresh_in_micro_hz; + + bool btr_supported; +}; + +struct mod_freesync_params { + enum mod_freesync_state state; + bool enable; + unsigned int update_duration_in_ns; + bool windowed_fullscreen; +}; + +/* + * Add stream to be tracked by module + */ +bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, + const struct dc_stream *stream, struct mod_freesync_caps *caps); + +/* + * Remove stream to be tracked by module + */ +bool mod_freesync_remove_stream(struct mod_freesync *mod_freesync, + const struct dc_stream *stream); + +/* + * Build additional parameters for dc_stream when creating stream for + * sink to support freesync + */ +void mod_freesync_update_stream(struct mod_freesync *mod_freesync, + struct dc_stream *stream); + +/* + * Update the freesync state flags for each display and program + * freesync accordingly + */ +void mod_freesync_update_state(struct mod_freesync *mod_freesync, + const struct dc_stream **streams, int num_streams, + struct mod_freesync_params *freesync_params); + +bool mod_freesync_get_state(struct mod_freesync *mod_freesync, + const struct dc_stream *stream, + struct mod_freesync_params *freesync_params); + +bool mod_freesync_set_user_enable(struct mod_freesync *mod_freesync, + const struct dc_stream **streams, int num_streams, + struct mod_freesync_user_enable *user_enable); + +bool mod_freesync_get_user_enable(struct mod_freesync *mod_freesync, + const struct dc_stream *stream, + struct mod_freesync_user_enable *user_enable); + +void mod_freesync_handle_v_update(struct mod_freesync *mod_freesync, + const struct dc_stream **streams, int num_streams); + +void mod_freesync_notify_mode_change(struct mod_freesync *mod_freesync, + const struct dc_stream **streams, int num_streams); + +void mod_freesync_pre_update_plane_addresses(struct mod_freesync *mod_freesync, + const struct dc_stream **streams, int num_streams, + unsigned int curr_time_stamp); + +#endif diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_power.h b/drivers/gpu/drm/amd/display/modules/inc/mod_power.h new file mode 100644 index 000000000000..a204e8d6cd23 --- /dev/null +++ b/drivers/gpu/drm/amd/display/modules/inc/mod_power.h @@ -0,0 +1,112 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef MODULES_INC_MOD_POWER_H_ +#define MODULES_INC_MOD_POWER_H_ + +#include "dm_services.h" + +struct mod_power { + int dummy; +}; + +/* VariBright related commands */ +enum varibright_command { + VariBright_Cmd__SetVBLevel = 0, + VariBright_Cmd__UserEnable, + VariBright_Cmd__PreDisplayConfigChange, + VariBright_Cmd__PostDisplayConfigChange, + VariBright_Cmd__SuspendABM, + VariBright_Cmd__ResumeABM, + + VariBright_Cmd__Unknown, +}; + +/* VariBright settings structure */ +struct varibright_info { + enum varibright_command cmd; + + unsigned int level; + bool enable; + bool activate; +}; + +enum dmcu_block_psr_reason { + /* This is a bitfield mask */ + dmcu_block_psr_reason_invalid = 0x0, + dmcu_block_psr_reason_vsync_int = 0x1, + dmcu_block_psr_reason_shared_primary = 0x2, + dmcu_block_psr_reason_unsupported_link_rate = 0x4 +}; + +struct mod_power *mod_power_create(struct dc *dc); + +void mod_power_destroy(struct mod_power *mod_power); + +bool mod_power_add_sink(struct mod_power *mod_power, + const struct dc_sink *sink); + +bool mod_power_remove_sink(struct mod_power *mod_power, + const struct dc_sink *sink); + +bool mod_power_set_backlight(struct mod_power *mod_power, + const struct dc_stream **streams, int num_streams, + unsigned int backlight_8bit); + +bool mod_power_get_backlight(struct mod_power *mod_power, + const struct dc_sink *sink, + unsigned int *backlight_8bit); + +void mod_power_initialize_backlight_caps + (struct mod_power *mod_power); + +unsigned int mod_power_backlight_level_percentage_to_signal + (struct mod_power *mod_power, unsigned int percentage); + +unsigned int mod_power_backlight_level_signal_to_percentage + (struct mod_power *mod_power, unsigned int signalLevel8bit); + +bool mod_power_get_panel_backlight_boundaries + (struct mod_power *mod_power, + unsigned int *min_backlight, + unsigned int *max_backlight, + unsigned int *output_ac_level_percentage, + unsigned int *output_dc_level_percentage); + +bool mod_power_set_smooth_brightness(struct mod_power *mod_power, + const struct dc_sink *sink, bool enable_brightness); + +bool mod_power_notify_mode_change(struct mod_power *mod_power, + const struct dc_stream *stream); + +bool mod_power_varibright_control(struct mod_power *mod_power, + struct varibright_info *input_varibright_info); + +bool mod_power_block_psr(bool block_enable, enum dmcu_block_psr_reason reason); + +bool mod_power_set_psr_enable(struct mod_power *mod_power, + bool psr_enable); + +#endif /* MODULES_INC_MOD_POWER_H_ */ diff --git a/drivers/gpu/drm/amd/display/modules/power/power.c b/drivers/gpu/drm/amd/display/modules/power/power.c new file mode 100644 index 000000000000..ea07e847da0a --- /dev/null +++ b/drivers/gpu/drm/amd/display/modules/power/power.c @@ -0,0 +1,784 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "mod_power.h" +#include "dm_services.h" +#include "dc.h" +#include "core_types.h" +#include "core_dc.h" + +#define MOD_POWER_MAX_CONCURRENT_SINKS 32 +#define SMOOTH_BRIGHTNESS_ADJUSTMENT_TIME_IN_MS 500 + +struct sink_caps { + const struct dc_sink *sink; +}; + +struct backlight_state { + unsigned int backlight; + unsigned int frame_ramp; + bool smooth_brightness_enabled; +}; + +struct core_power { + struct mod_power public; + struct dc *dc; + int num_sinks; + struct sink_caps *caps; + struct backlight_state *state; +}; + +union dmcu_abm_set_bl_params { + struct { + unsigned int gradual_change : 1; /* [0:0] */ + unsigned int reserved : 15; /* [15:1] */ + unsigned int frame_ramp : 16; /* [31:16] */ + } bits; + unsigned int u32All; +}; + +/* Backlight cached properties */ +static unsigned int backlight_8bit_lut_array[101]; +static unsigned int ac_level_percentage; +static unsigned int dc_level_percentage; +static bool backlight_caps_valid; +/* we use lazy initialization of backlight capabilities cache */ +static bool backlight_caps_initialized; +/* AC/DC levels initialized later in separate context */ +static bool backlight_def_levels_valid; + +/* ABM cached properties */ +static unsigned int abm_level; +static bool abm_user_enable; +static bool abm_active; + +/*PSR cached properties*/ +static unsigned int block_psr; + +/* Defines default backlight curve F(x) = A(x*x) + Bx + C. + * + * Backlight curve should always satisfy F(0) = min, F(100) = max, + * so polynom coefficients are: + * A is 0.0255 - B/100 - min/10000 - (255-max)/10000 = (max - min)/10000 - B/100 + * B is adjustable factor to modify the curve. + * Bigger B results in less concave curve. B range is [0..(max-min)/100] + * C is backlight minimum + */ +static const unsigned int backlight_curve_coeff_a_factor = 10000; +static const unsigned int backlight_curve_coeff_b = 100; +static const unsigned int backlight_curve_coeff_b_factor = 100; + +/* Minimum and maximum backlight input signal levels */ +static const unsigned int default_min_backlight = 12; +static const unsigned int default_max_backlight = 255; + +/* Other backlight constants */ +static const unsigned int absolute_backlight_max = 255; + +#define MOD_POWER_TO_CORE(mod_power)\ + container_of(mod_power, struct core_power, public) + +static bool check_dc_support(const struct dc *dc) +{ + if (dc->stream_funcs.set_backlight == NULL) + return false; + + return true; +} + +/* Given a specific dc_sink* this function finds its equivalent + * on the dc_sink array and returns the corresponding index + */ +static unsigned int sink_index_from_sink(struct core_power *core_power, + const struct dc_sink *sink) +{ + unsigned int index = 0; + + for (index = 0; index < core_power->num_sinks; index++) + if (core_power->caps[index].sink == sink) + return index; + + /* Could not find sink requested */ + ASSERT(false); + return index; +} + +static unsigned int convertBL8to17(unsigned int backlight_8bit) +{ + unsigned int temp_ulong = backlight_8bit * 0x10101; + unsigned char temp_uchar = + (unsigned char)(((temp_ulong & 0x80) >> 7) & 1); + + temp_ulong = (temp_ulong >> 8) + temp_uchar; + + return temp_ulong; +} + +static uint16_t convertBL8to16(unsigned int backlight_8bit) +{ + return (uint16_t)((backlight_8bit * 0x10101) >> 8); +} + +/*This is used when OS wants to retrieve the current BL. + * We return the 8bit value to OS. + */ +static unsigned int convertBL17to8(unsigned int backlight_17bit) +{ + if (backlight_17bit & 0x10000) + return default_max_backlight; + else + return (backlight_17bit >> 8); +} + +struct mod_power *mod_power_create(struct dc *dc) +{ + struct core_power *core_power = + dm_alloc(sizeof(struct core_power)); + + struct core_dc *core_dc = DC_TO_CORE(dc); + + int i = 0; + + if (core_power == NULL) + goto fail_alloc_context; + + core_power->caps = dm_alloc(sizeof(struct sink_caps) * + MOD_POWER_MAX_CONCURRENT_SINKS); + + if (core_power->caps == NULL) + goto fail_alloc_caps; + + for (i = 0; i < MOD_POWER_MAX_CONCURRENT_SINKS; i++) + core_power->caps[i].sink = NULL; + + core_power->state = dm_alloc(sizeof(struct backlight_state) * + MOD_POWER_MAX_CONCURRENT_SINKS); + + if (core_power->state == NULL) + goto fail_alloc_state; + + core_power->num_sinks = 0; + backlight_caps_valid = false; + + if (dc == NULL) + goto fail_construct; + + core_power->dc = dc; + + if (!check_dc_support(dc)) + goto fail_construct; + + abm_user_enable = false; + abm_active = false; + + return &core_power->public; + +fail_construct: + dm_free(core_power->state); + +fail_alloc_state: + dm_free(core_power->caps); + +fail_alloc_caps: + dm_free(core_power); + +fail_alloc_context: + return NULL; +} + + +void mod_power_destroy(struct mod_power *mod_power) +{ + if (mod_power != NULL) { + int i; + struct core_power *core_power = + MOD_POWER_TO_CORE(mod_power); + + dm_free(core_power->state); + + for (i = 0; i < core_power->num_sinks; i++) + dc_sink_release(core_power->caps[i].sink); + + dm_free(core_power->caps); + + dm_free(core_power); + } +} + +bool mod_power_add_sink(struct mod_power *mod_power, + const struct dc_sink *sink) +{ + if (sink->sink_signal == SIGNAL_TYPE_VIRTUAL) + return false; + + struct core_power *core_power = + MOD_POWER_TO_CORE(mod_power); + struct core_dc *core_dc = DC_TO_CORE(core_power->dc); + + if (core_power->num_sinks < MOD_POWER_MAX_CONCURRENT_SINKS) { + dc_sink_retain(sink); + core_power->caps[core_power->num_sinks].sink = sink; + core_power->state[core_power->num_sinks]. + smooth_brightness_enabled = false; + core_power->state[core_power->num_sinks]. + backlight = 100; + core_power->num_sinks++; + return true; + } + + return false; +} + +bool mod_power_remove_sink(struct mod_power *mod_power, + const struct dc_sink *sink) +{ + int i = 0, j = 0; + struct core_power *core_power = + MOD_POWER_TO_CORE(mod_power); + + for (i = 0; i < core_power->num_sinks; i++) { + if (core_power->caps[i].sink == sink) { + /* To remove this sink, shift everything after down */ + for (j = i; j < core_power->num_sinks - 1; j++) { + core_power->caps[j].sink = + core_power->caps[j + 1].sink; + + memcpy(&core_power->state[j], + &core_power->state[j + 1], + sizeof(struct backlight_state)); + } + core_power->num_sinks--; + dc_sink_release(sink); + return true; + } + } + return false; +} + +bool mod_power_set_backlight(struct mod_power *mod_power, + const struct dc_stream **streams, int num_streams, + unsigned int backlight_8bit) +{ + struct core_power *core_power = + MOD_POWER_TO_CORE(mod_power); + + unsigned int frame_ramp = 0; + + unsigned int stream_index, sink_index, vsync_rate_hz; + + union dmcu_abm_set_bl_params params; + + for (stream_index = 0; stream_index < num_streams; stream_index++) { + if (streams[stream_index]->sink->sink_signal == SIGNAL_TYPE_VIRTUAL) { + core_power->state[sink_index].backlight = 0; + core_power->state[sink_index].frame_ramp = 0; + core_power->state[sink_index].smooth_brightness_enabled = false; + continue; + } + + sink_index = sink_index_from_sink(core_power, + streams[stream_index]->sink); + + vsync_rate_hz = div64_u64(div64_u64((streams[stream_index]-> + timing.pix_clk_khz * 1000), + streams[stream_index]->timing.v_total), + streams[stream_index]->timing.h_total); + + core_power->state[sink_index].backlight = backlight_8bit; + + if (core_power->state[sink_index].smooth_brightness_enabled) + frame_ramp = ((vsync_rate_hz * + SMOOTH_BRIGHTNESS_ADJUSTMENT_TIME_IN_MS) + 500) + / 1000; + else + frame_ramp = 0; + + core_power->state[sink_index].frame_ramp = frame_ramp; + } + + params.u32All = 0; + params.bits.gradual_change = (frame_ramp > 0); + params.bits.frame_ramp = frame_ramp; + + core_power->dc->stream_funcs.set_backlight + (core_power->dc, backlight_8bit, params.u32All, streams[0]); + + return true; +} + +bool mod_power_get_backlight(struct mod_power *mod_power, + const struct dc_sink *sink, + unsigned int *backlight_8bit) +{ + if (sink->sink_signal == SIGNAL_TYPE_VIRTUAL) + return false; + + struct core_power *core_power = + MOD_POWER_TO_CORE(mod_power); + + unsigned int sink_index = sink_index_from_sink(core_power, sink); + + *backlight_8bit = core_power->state[sink_index].backlight; + + return true; +} + +/* hard coded to default backlight curve. */ +void mod_power_initialize_backlight_caps(struct mod_power + *mod_power) +{ + struct core_power *core_power = + MOD_POWER_TO_CORE(mod_power); + struct core_dc *core_dc = DC_TO_CORE(core_power->dc); + unsigned int i; + + backlight_caps_initialized = true; + + struct dm_acpi_atif_backlight_caps *pExtCaps = NULL; + bool customCurvePresent = false; + bool customMinMaxPresent = false; + bool customDefLevelsPresent = false; + + /* Allocate memory for ATIF output + * (do not want to use 256 bytes on the stack) + */ + pExtCaps = (struct dm_acpi_atif_backlight_caps *) + (dm_alloc(sizeof(struct dm_acpi_atif_backlight_caps))); + if (pExtCaps == NULL) + return; + + /* Retrieve ACPI extended brightness caps */ + if (dm_query_extended_brightness_caps + (core_dc->ctx, AcpiDisplayType_LCD1, pExtCaps)) { + ac_level_percentage = pExtCaps->acLevelPercentage; + dc_level_percentage = pExtCaps->dcLevelPercentage; + customMinMaxPresent = true; + customDefLevelsPresent = true; + customCurvePresent = (pExtCaps->numOfDataPoints > 0); + + ASSERT(pExtCaps->numOfDataPoints <= 99); + } else { + dm_free(pExtCaps); + return; + } + + if (customMinMaxPresent) + backlight_8bit_lut_array[0] = pExtCaps->minInputSignal; + else + backlight_8bit_lut_array[0] = default_min_backlight; + + if (customMinMaxPresent) + backlight_8bit_lut_array[100] = pExtCaps->maxInputSignal; + else + backlight_8bit_lut_array[100] = default_max_backlight; + + ASSERT(backlight_8bit_lut_array[100] <= absolute_backlight_max); + ASSERT(backlight_8bit_lut_array[0] <= + backlight_8bit_lut_array[100]); + + /* Just to make sure we use valid values */ + if (backlight_8bit_lut_array[100] > absolute_backlight_max) + backlight_8bit_lut_array[100] = absolute_backlight_max; + if (backlight_8bit_lut_array[0] > backlight_8bit_lut_array[100]) { + unsigned int swap; + + swap = backlight_8bit_lut_array[0]; + backlight_8bit_lut_array[0] = backlight_8bit_lut_array[100]; + backlight_8bit_lut_array[100] = swap; + } + + /* Build backlight translation table for custom curve */ + if (customCurvePresent) { + unsigned int index = 1; + unsigned int numOfDataPoints = + (pExtCaps->numOfDataPoints <= 99 ? + pExtCaps->numOfDataPoints : 99); + + /* Filling translation table from data points - + * between every two provided data points we + * lineary interpolate missing values + */ + for (i = 0; i < numOfDataPoints; i++) { + /* Clamp signal level between min and max + * (since min and max might come other + * soruce like registry) + */ + unsigned int luminance = + pExtCaps->dataPoints[i].luminance; + unsigned int signalLevel = + pExtCaps->dataPoints[i].signalLevel; + + if (signalLevel < backlight_8bit_lut_array[0]) + signalLevel = backlight_8bit_lut_array[0]; + if (signalLevel > backlight_8bit_lut_array[100]) + signalLevel = backlight_8bit_lut_array[100]; + + /* Lineary interpolate missing values */ + if (index < luminance) { + unsigned int baseValue = + backlight_8bit_lut_array[index-1]; + unsigned int deltaSignal = + signalLevel - baseValue; + unsigned int deltaLuma = + luminance - index + 1; + unsigned int step = deltaSignal; + + for (; index < luminance; index++) { + backlight_8bit_lut_array[index] = + baseValue + (step / deltaLuma); + step += deltaSignal; + } + } + + /* Now [index == luminance], + * so we can add data point to the translation table + */ + backlight_8bit_lut_array[index++] = signalLevel; + } + + /* Complete the final segment of interpolation - + * between last datapoint and maximum value + */ + if (index < 100) { + unsigned int baseValue = + backlight_8bit_lut_array[index-1]; + unsigned int deltaSignal = + backlight_8bit_lut_array[100] - + baseValue; + unsigned int deltaLuma = 100 - index + 1; + unsigned int step = deltaSignal; + + for (; index < 100; index++) { + backlight_8bit_lut_array[index] = + baseValue + (step / deltaLuma); + step += deltaSignal; + } + } + /* Build backlight translation table based on default curve */ + } else { + unsigned int delta = + backlight_8bit_lut_array[100] - + backlight_8bit_lut_array[0]; + unsigned int coeffC = backlight_8bit_lut_array[0]; + unsigned int coeffB = + (backlight_curve_coeff_b < delta ? + backlight_curve_coeff_b : delta); + unsigned int coeffA = delta - coeffB; /* coeffB is B*100 */ + + for (i = 1; i < 100; i++) { + backlight_8bit_lut_array[i] = + (coeffA * i * i) / + backlight_curve_coeff_a_factor + + (coeffB * i) / + backlight_curve_coeff_b_factor + + coeffC; + } + } + + if (pExtCaps != NULL) + dm_free(pExtCaps); + + /* Successfully initialized */ + backlight_caps_valid = true; + backlight_def_levels_valid = customDefLevelsPresent; +} + +unsigned int mod_power_backlight_level_percentage_to_signal( + struct mod_power *mod_power, unsigned int percentage) +{ + /* Do lazy initialization of backlight capabilities*/ + if (!backlight_caps_initialized) + mod_power_initialize_backlight_caps(mod_power); + + /* Since the translation table is indexed by percentage, + * we simply return backlight value at given percent + */ + if (backlight_caps_valid && percentage <= 100) + return backlight_8bit_lut_array[percentage]; + + return -1; +} + +unsigned int mod_power_backlight_level_signal_to_percentage( + struct mod_power *mod_power, + unsigned int signalLevel8bit) +{ + unsigned int invalid_backlight = (unsigned int)(-1); + /* Do lazy initialization of backlight capabilities */ + if (!backlight_caps_initialized) + mod_power_initialize_backlight_caps(mod_power); + + /* If customer curve cannot convert to differentiated value near min + * it is important to report 0 for min signal to pass setting "Dimmed" + * setting in HCK brightness2 tests. + */ + if (signalLevel8bit <= backlight_8bit_lut_array[0]) + return 0; + + /* Since the translation table is indexed by percentage + * we need to do a binary search over the array + * Another option would be to guess entry based on linear distribution + * and then do linear search in correct direction + */ + if (backlight_caps_valid && signalLevel8bit <= + absolute_backlight_max) { + unsigned int min = 0; + unsigned int max = 100; + unsigned int mid = invalid_backlight; + + while (max >= min) { + mid = (min + max) / 2; /* floor of half range */ + + if (backlight_8bit_lut_array[mid] < signalLevel8bit) + min = mid + 1; + else if (backlight_8bit_lut_array[mid] > + signalLevel8bit) + max = mid - 1; + else + break; + + if (max == 0 || max == 1) + return invalid_backlight; + } + return mid; + } + + return invalid_backlight; +} + + +bool mod_power_get_panel_backlight_boundaries( + struct mod_power *mod_power, + unsigned int *min_backlight, + unsigned int *max_backlight, + unsigned int *output_ac_level_percentage, + unsigned int *output_dc_level_percentage) +{ + /* Do lazy initialization of backlight capabilities */ + if (!backlight_caps_initialized) + mod_power_initialize_backlight_caps(mod_power); + + /* If cache was successfully updated, + * copy the values to output structure and return success + */ + if (backlight_caps_valid) { + *min_backlight = backlight_8bit_lut_array[0]; + *max_backlight = backlight_8bit_lut_array[100]; + + *output_ac_level_percentage = ac_level_percentage; + *output_dc_level_percentage = dc_level_percentage; + + return true; + } + + return false; +} + +bool mod_power_set_smooth_brightness(struct mod_power *mod_power, + const struct dc_sink *sink, bool enable_brightness) +{ + if (sink->sink_signal == SIGNAL_TYPE_VIRTUAL) + return false; + + struct core_power *core_power = + MOD_POWER_TO_CORE(mod_power); + unsigned int sink_index = sink_index_from_sink(core_power, sink); + + core_power->state[sink_index].smooth_brightness_enabled + = enable_brightness; + return true; +} + +bool mod_power_notify_mode_change(struct mod_power *mod_power, + const struct dc_stream *stream) +{ + if (stream->sink->sink_signal == SIGNAL_TYPE_VIRTUAL) + return false; + + struct core_power *core_power = + MOD_POWER_TO_CORE(mod_power); + + unsigned int sink_index = sink_index_from_sink(core_power, + stream->sink); + unsigned int frame_ramp = core_power->state[sink_index].frame_ramp; + union dmcu_abm_set_bl_params params; + + params.u32All = 0; + params.bits.gradual_change = (frame_ramp > 0); + params.bits.frame_ramp = frame_ramp; + + core_power->dc->stream_funcs.set_backlight + (core_power->dc, + core_power->state[sink_index].backlight, + params.u32All, stream); + + core_power->dc->stream_funcs.setup_psr + (core_power->dc, stream); + + return true; +} + + +static bool mod_power_abm_feature_enable(struct mod_power + *mod_power, bool enable) +{ + struct core_power *core_power = + MOD_POWER_TO_CORE(mod_power); + if (abm_user_enable == enable) + return true; + + abm_user_enable = enable; + + if (enable) { + if (abm_level != 0 && abm_active) + core_power->dc->stream_funcs.set_abm_level + (core_power->dc, abm_level); + } else { + if (abm_level != 0 && abm_active) { + abm_level = 0; + core_power->dc->stream_funcs.set_abm_level + (core_power->dc, abm_level); + } + } + + return true; +} + +static bool mod_power_abm_activate(struct mod_power + *mod_power, bool activate) +{ + struct core_power *core_power = + MOD_POWER_TO_CORE(mod_power); + if (abm_active == activate) + return true; + + abm_active = activate; + + if (activate) { + if (abm_level != 0 && abm_user_enable) + core_power->dc->stream_funcs.set_abm_level + (core_power->dc, abm_level); + } else { + if (abm_level != 0 && abm_user_enable) { + abm_level = 0; + core_power->dc->stream_funcs.set_abm_level + (core_power->dc, abm_level); + } + } + + return true; +} + +static bool mod_power_abm_set_level(struct mod_power *mod_power, + unsigned int level) +{ + struct core_power *core_power = + MOD_POWER_TO_CORE(mod_power); + if (abm_level == level) + return true; + + if (abm_active && abm_user_enable && level == 0) + core_power->dc->stream_funcs.set_abm_level + (core_power->dc, 0); + else if (abm_active && abm_user_enable && level != 0) + core_power->dc->stream_funcs.set_abm_level + (core_power->dc, level); + + abm_level = level; + + return true; +} + +bool mod_power_varibright_control(struct mod_power *mod_power, + struct varibright_info *input_varibright_info) +{ + switch (input_varibright_info->cmd) { + case VariBright_Cmd__SetVBLevel: + { + /* Set VariBright user level. */ + mod_power_abm_set_level(mod_power, + input_varibright_info->level); + } + break; + + case VariBright_Cmd__UserEnable: + { + /* Set VariBright user enable state. */ + mod_power_abm_feature_enable(mod_power, + input_varibright_info->enable); + } + break; + + case VariBright_Cmd__PostDisplayConfigChange: + { + /* Set VariBright user level. */ + mod_power_abm_set_level(mod_power, + input_varibright_info->level); + + /* Set VariBright user enable state. */ + mod_power_abm_feature_enable(mod_power, + input_varibright_info->enable); + + /* Set VariBright activate based on power state. */ + mod_power_abm_activate(mod_power, + input_varibright_info->activate); + } + break; + + default: + { + return false; + } + break; + } + + return true; +} + +bool mod_power_block_psr(bool block_enable, enum dmcu_block_psr_reason reason) +{ + if (block_enable) + block_psr |= reason; + else + block_psr &= ~reason; + + return true; +} + + +bool mod_power_set_psr_enable(struct mod_power *mod_power, + bool psr_enable) +{ + struct core_power *core_power = + MOD_POWER_TO_CORE(mod_power); + + if (block_psr == 0) + return core_power->dc->stream_funcs.set_psr_enable + (core_power->dc, psr_enable); + + return false; +} + + -- cgit From 39cc5be276d4ea7d64531f6f207e57f27bdba47d Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 13 Dec 2016 15:42:48 -0500 Subject: drm/amd/dc/dm: remove redundant display structs Now that the mc_access functions are gone, we no longer need separate structs for all the different dce families in dm. Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 60 ++--------------------- 1 file changed, 4 insertions(+), 56 deletions(-) (limited to 'drivers/gpu') 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 ae4ba7777839..fa55147d0c47 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1386,48 +1386,7 @@ static int amdgpu_notify_freesync(struct drm_device *dev, void *data, return r; } -#ifdef CONFIG_DRM_AMDGPU_CIK -static const struct amdgpu_display_funcs dm_dce_v8_0_display_funcs = { - .bandwidth_update = dm_bandwidth_update, /* called unconditionally */ - .vblank_get_counter = dm_vblank_get_counter,/* called unconditionally */ - .vblank_wait = NULL, - .backlight_set_level = - dm_set_backlight_level,/* called unconditionally */ - .backlight_get_level = - dm_get_backlight_level,/* called unconditionally */ - .hpd_sense = NULL,/* called unconditionally */ - .hpd_set_polarity = NULL, /* called unconditionally */ - .hpd_get_gpio_reg = NULL, /* VBIOS parsing. DAL does it. */ - .page_flip = dm_page_flip, /* called unconditionally */ - .page_flip_get_scanoutpos = - dm_crtc_get_scanoutpos,/* called unconditionally */ - .add_encoder = NULL, /* VBIOS parsing. DAL does it. */ - .add_connector = NULL, /* VBIOS parsing. DAL does it. */ - .notify_freesync = amdgpu_notify_freesync, -}; -#endif - -static const struct amdgpu_display_funcs dm_dce_v10_0_display_funcs = { - .bandwidth_update = dm_bandwidth_update, /* called unconditionally */ - .vblank_get_counter = dm_vblank_get_counter,/* called unconditionally */ - .vblank_wait = NULL, - .backlight_set_level = - dm_set_backlight_level,/* called unconditionally */ - .backlight_get_level = - dm_get_backlight_level,/* called unconditionally */ - .hpd_sense = NULL,/* called unconditionally */ - .hpd_set_polarity = NULL, /* called unconditionally */ - .hpd_get_gpio_reg = NULL, /* VBIOS parsing. DAL does it. */ - .page_flip = dm_page_flip, /* called unconditionally */ - .page_flip_get_scanoutpos = - dm_crtc_get_scanoutpos,/* called unconditionally */ - .add_encoder = NULL, /* VBIOS parsing. DAL does it. */ - .add_connector = NULL, /* VBIOS parsing. DAL does it. */ - .notify_freesync = amdgpu_notify_freesync, - -}; - -static const struct amdgpu_display_funcs dm_dce_v11_0_display_funcs = { +static const struct amdgpu_display_funcs dm_display_funcs = { .bandwidth_update = dm_bandwidth_update, /* called unconditionally */ .vblank_get_counter = dm_vblank_get_counter,/* called unconditionally */ .vblank_wait = NULL, @@ -1491,52 +1450,41 @@ static int dm_early_init(void *handle) adev->mode_info.num_crtc = 6; adev->mode_info.num_hpd = 6; adev->mode_info.num_dig = 6; -#ifdef CONFIG_DRM_AMDGPU_CIK - if (adev->mode_info.funcs == NULL) - adev->mode_info.funcs = &dm_dce_v8_0_display_funcs; -#endif break; case CHIP_FIJI: case CHIP_TONGA: adev->mode_info.num_crtc = 6; adev->mode_info.num_hpd = 6; adev->mode_info.num_dig = 7; - if (adev->mode_info.funcs == NULL) - adev->mode_info.funcs = &dm_dce_v10_0_display_funcs; break; case CHIP_CARRIZO: adev->mode_info.num_crtc = 3; adev->mode_info.num_hpd = 6; adev->mode_info.num_dig = 9; - if (adev->mode_info.funcs == NULL) - adev->mode_info.funcs = &dm_dce_v11_0_display_funcs; break; case CHIP_STONEY: adev->mode_info.num_crtc = 2; adev->mode_info.num_hpd = 6; adev->mode_info.num_dig = 9; - if (adev->mode_info.funcs == NULL) - adev->mode_info.funcs = &dm_dce_v11_0_display_funcs; break; case CHIP_POLARIS11: adev->mode_info.num_crtc = 5; adev->mode_info.num_hpd = 5; adev->mode_info.num_dig = 5; - if (adev->mode_info.funcs == NULL) - adev->mode_info.funcs = &dm_dce_v11_0_display_funcs; break; case CHIP_POLARIS10: adev->mode_info.num_crtc = 6; adev->mode_info.num_hpd = 6; adev->mode_info.num_dig = 6; - if (adev->mode_info.funcs == NULL) - adev->mode_info.funcs = &dm_dce_v11_0_display_funcs; break; default: DRM_ERROR("Usupported ASIC type: 0x%X\n", adev->asic_type); return -EINVAL; } + if (adev->mode_info.funcs == NULL) + adev->mode_info.funcs = &dm_display_funcs; + /* Note: Do NOT change adev->audio_endpt_rreg and * adev->audio_endpt_wreg because they are initialised in * amdgpu_device_init() */ -- cgit From 56bc1c42610aa6328e6c4b222dc076acffb40243 Mon Sep 17 00:00:00 2001 From: Zeyu Fan Date: Wed, 7 Dec 2016 11:28:03 -0500 Subject: drm/amd/display: Fix hdmi not lighting up on Hawaii. Signed-off-by: Zeyu Fan Acked-by: Jordan Lazare Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 86e55d028cbf..10b70ca29ba3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -1233,7 +1233,7 @@ void dce110_link_encoder_enable_tmds_output( /* Enable the PHY */ cntl.action = TRANSMITTER_CONTROL_ENABLE; - cntl.engine_id = ENGINE_ID_UNKNOWN; + cntl.engine_id = enc->preferred_engine; cntl.transmitter = enc110->base.transmitter; cntl.pll_id = clock_source; if (hdmi) { -- cgit From 8e545104aa05b5e0720fd2042e2f9729f9c13744 Mon Sep 17 00:00:00 2001 From: Zeyu Fan Date: Tue, 6 Dec 2016 12:59:52 -0500 Subject: drm/amd/display: Fix bugs causing Hawaii and Bonaire not light up. Signed-off-by: Zeyu Fan Acked-by: Jordan Lazare Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.c | 2 +- .../gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c | 2 +- drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.c b/drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.c index dff82dd11721..8049320e8b03 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.c @@ -186,7 +186,7 @@ static uint8_t dig_encoder_sel_to_atom(enum engine_id id) break; } - return atom_dig_encoder_sel; + return 0; } static bool clock_source_id_to_atom( diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c index 8b72aa588b86..48e59963dad4 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c +++ b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c @@ -183,7 +183,7 @@ static uint8_t dig_encoder_sel_to_atom(enum engine_id id) break; } - return atom_dig_encoder_sel; + return 0; } static bool clock_source_id_to_atom( diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 10b70ca29ba3..c73d6054cdda 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -1281,7 +1281,7 @@ void dce110_link_encoder_enable_dp_output( configure_encoder(enc110, link_settings); cntl.action = TRANSMITTER_CONTROL_ENABLE; - cntl.engine_id = ENGINE_ID_UNKNOWN; + cntl.engine_id = enc->preferred_engine; cntl.transmitter = enc110->base.transmitter; cntl.pll_id = clock_source; cntl.signal = SIGNAL_TYPE_DISPLAY_PORT; -- cgit From ead964f24e111aa5ba6ec4c2ee15ae20f11a121a Mon Sep 17 00:00:00 2001 From: jimqu Date: Mon, 28 Nov 2016 08:05:46 +0800 Subject: drm/amd/display: Fix memory corruption issue. temp_flip_context is always same as current_context, and the current_context will be freed in dc_commit_targets(), but temp_flip_context will be used in dc_update_surfaces_for_target(). Signed-off-by: JimQu Reviewed-by: Andrey Grodzovsky Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index f7638f84421b..424a7d4b8731 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1096,8 +1096,12 @@ bool dc_commit_targets( resource_validate_ctx_destruct(core_dc->current_context); - dm_free(core_dc->current_context); + if (core_dc->temp_flip_context != core_dc->current_context) { + dm_free(core_dc->temp_flip_context); + core_dc->temp_flip_context = core_dc->current_context; + } core_dc->current_context = context; + memset(core_dc->temp_flip_context, 0, sizeof(*core_dc->temp_flip_context)); return (result == DC_OK); -- cgit From 1293b4339fb09693bdfc938495b671f0ac9bfae5 Mon Sep 17 00:00:00 2001 From: Joshua Aberback Date: Tue, 29 Nov 2016 17:56:05 -0500 Subject: drm/amd/display: Block 3D Timings - we don't yet support 3D timings in DAL3 - somehow a code path was being executed that resulted in HW programming for a 3D timing, which caused 3D displays to show half the desktop in one frame, and the other half of the desktop in the next frame - blocking all 3D timings in timing generator validation until we implement proper 3D timing support Signed-off-by: Joshua Aberback Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c index b1c97125f6fb..12a258763ef1 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c @@ -1113,6 +1113,10 @@ bool dce110_timing_generator_validate_timing( if (!timing) return false; + /* Currently we don't support 3D, so block all 3D timings */ + if (timing->timing_3d_format != TIMING_3D_FORMAT_NONE) + return false; + /* Check maximum number of pixels supported by Timing Generator * (Currently will never fail, in order to fail needs display which * needs more than 8192 horizontal and -- cgit From 0971d745f68bcd6eeda1d1a7420142dc41fac798 Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Wed, 30 Nov 2016 12:10:35 -0500 Subject: drm/amd/display: Update rgb limited range csc matrix calculation The issue causes hue adjustment for rgb limited range color space programmed wrong. Update calculation formula for rgb limited range Signed-off-by: Wenjing Liu Reviewed-by: Anthony Koo Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/modules/color/color.c | 300 ++++++++++++++++------ 1 file changed, 216 insertions(+), 84 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/modules/color/color.c b/drivers/gpu/drm/amd/display/modules/color/color.c index cf030b18f6a9..30d09d358576 100644 --- a/drivers/gpu/drm/amd/display/modules/color/color.c +++ b/drivers/gpu/drm/amd/display/modules/color/color.c @@ -854,26 +854,60 @@ static void calculate_rgb_matrix_legacy(struct core_color *core_color, rgb_matrix[11] = grph_bright; } -static void calculate_rgb_limited_range_matrix(struct core_color *core_color, - unsigned int sink_index, struct fixed31_32 *rgb_matrix) +static void calculate_rgb_limited_range_matrix_legacy( + struct core_color *core_color, unsigned int sink_index, + struct fixed31_32 *rgb_matrix) { - struct fixed31_32 ideal[12]; - - static const int32_t matrix_[] = { - 85546875, 0, 0, 6250000, - 0, 85546875, 0, 6250000, - 0, 0, 85546875, 6250000 - }; - - uint32_t i = 0; + const struct fixed31_32 k1 = + dal_fixed31_32_from_fraction(701000, 1000000); + const struct fixed31_32 k2 = + dal_fixed31_32_from_fraction(236568, 1000000); + const struct fixed31_32 k3 = + dal_fixed31_32_from_fraction(-587000, 1000000); + const struct fixed31_32 k4 = + dal_fixed31_32_from_fraction(464432, 1000000); + const struct fixed31_32 k5 = + dal_fixed31_32_from_fraction(-114000, 1000000); + const struct fixed31_32 k6 = + dal_fixed31_32_from_fraction(-701000, 1000000); + const struct fixed31_32 k7 = + dal_fixed31_32_from_fraction(-299000, 1000000); + const struct fixed31_32 k8 = + dal_fixed31_32_from_fraction(-292569, 1000000); + const struct fixed31_32 k9 = + dal_fixed31_32_from_fraction(413000, 1000000); + const struct fixed31_32 k10 = + dal_fixed31_32_from_fraction(-92482, 1000000); + const struct fixed31_32 k11 = + dal_fixed31_32_from_fraction(-114000, 1000000); + const struct fixed31_32 k12 = + dal_fixed31_32_from_fraction(385051, 1000000); + const struct fixed31_32 k13 = + dal_fixed31_32_from_fraction(-299000, 1000000); + const struct fixed31_32 k14 = + dal_fixed31_32_from_fraction(886000, 1000000); + const struct fixed31_32 k15 = + dal_fixed31_32_from_fraction(-587000, 1000000); + const struct fixed31_32 k16 = + dal_fixed31_32_from_fraction(-741914, 1000000); + const struct fixed31_32 k17 = + dal_fixed31_32_from_fraction(886000, 1000000); + const struct fixed31_32 k18 = + dal_fixed31_32_from_fraction(-144086, 1000000); - do { - ideal[i] = dal_fixed31_32_from_fraction( - matrix_[i], - 100000000); - ++i; - } while (i != ARRAY_SIZE(matrix_)); + const struct fixed31_32 luma_r = + dal_fixed31_32_from_fraction(299, 1000); + const struct fixed31_32 luma_g = + dal_fixed31_32_from_fraction(587, 1000); + const struct fixed31_32 luma_b = + dal_fixed31_32_from_fraction(114, 1000); + const struct fixed31_32 luma_scale = + dal_fixed31_32_from_fraction(875855, 1000000); + const struct fixed31_32 rgb_scale = + dal_fixed31_32_from_fraction(85546875, 100000000); + const struct fixed31_32 rgb_bias = + dal_fixed31_32_from_fraction(625, 10000); struct fixed31_32 grph_cont; struct fixed31_32 grph_sat; @@ -885,84 +919,182 @@ static void calculate_rgb_limited_range_matrix(struct core_color *core_color, core_color, sink_index, &grph_cont, &grph_sat, &grph_bright, &sin_grph_hue, &cos_grph_hue); - const struct fixed31_32 multiplier = - dal_fixed31_32_mul(grph_cont, grph_sat); - - rgb_matrix[8] = dal_fixed31_32_mul(ideal[0], grph_cont); + /* COEF_1_1 = GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K1 +*/ + /* Sin(GrphHue) * K2))*/ + /* (Cos(GrphHue) * K1 + Sin(GrphHue) * K2)*/ + rgb_matrix[0] = + dal_fixed31_32_add( + dal_fixed31_32_mul(cos_grph_hue, k1), + dal_fixed31_32_mul(sin_grph_hue, k2)); + /* GrphSat * (Cos(GrphHue) * K1 + Sin(GrphHue) * K2 */ + rgb_matrix[0] = dal_fixed31_32_mul(grph_sat, rgb_matrix[0]); + /* (LumaR + GrphSat * (Cos(GrphHue) * K1 + Sin(GrphHue) * K2))*/ + rgb_matrix[0] = dal_fixed31_32_add(luma_r, rgb_matrix[0]); + /* GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K1 + Sin(GrphHue)**/ + /* K2))*/ + rgb_matrix[0] = dal_fixed31_32_mul(grph_cont, rgb_matrix[0]); + /* LumaScale * GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K1 + */ + /* Sin(GrphHue) * K2))*/ + rgb_matrix[0] = dal_fixed31_32_mul(luma_scale, rgb_matrix[0]); - rgb_matrix[9] = dal_fixed31_32_mul(ideal[1], grph_cont); + /* COEF_1_2 = GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K3 +*/ + /* Sin(GrphHue) * K4))*/ + /* (Cos(GrphHue) * K3 + Sin(GrphHue) * K4)*/ + rgb_matrix[1] = + dal_fixed31_32_add( + dal_fixed31_32_mul(cos_grph_hue, k3), + dal_fixed31_32_mul(sin_grph_hue, k4)); + /* GrphSat * (Cos(GrphHue) * K3 + Sin(GrphHue) * K4)*/ + rgb_matrix[1] = dal_fixed31_32_mul(grph_sat, rgb_matrix[1]); + /* (LumaG + GrphSat * (Cos(GrphHue) * K3 + Sin(GrphHue) * K4))*/ + rgb_matrix[1] = dal_fixed31_32_add(luma_g, rgb_matrix[1]); + /* GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K3 + Sin(GrphHue)**/ + /* K4))*/ + rgb_matrix[1] = dal_fixed31_32_mul(grph_cont, rgb_matrix[1]); + /* LumaScale * GrphCont * (LumaG + GrphSat *(Cos(GrphHue) * K3 + */ + /* Sin(GrphHue) * K4))*/ + rgb_matrix[1] = dal_fixed31_32_mul(luma_scale, rgb_matrix[1]); - rgb_matrix[10] = dal_fixed31_32_mul(ideal[2], grph_cont); + /* COEF_1_3 = GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K5 +*/ + /* Sin(GrphHue) * K6))*/ + /* (Cos(GrphHue) * K5 + Sin(GrphHue) * K6)*/ + rgb_matrix[2] = + dal_fixed31_32_add( + dal_fixed31_32_mul(cos_grph_hue, k5), + dal_fixed31_32_mul(sin_grph_hue, k6)); + /* GrphSat * (Cos(GrphHue) * K5 + Sin(GrphHue) * K6)*/ + rgb_matrix[2] = dal_fixed31_32_mul(grph_sat, rgb_matrix[2]); + /* LumaB + GrphSat * (Cos(GrphHue) * K5 + Sin(GrphHue) * K6)*/ + rgb_matrix[2] = dal_fixed31_32_add(luma_b, rgb_matrix[2]); + /* GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K5 + Sin(GrphHue)**/ + /* K6))*/ + rgb_matrix[2] = dal_fixed31_32_mul(grph_cont, rgb_matrix[2]); + /* LumaScale * GrphCont * (LumaB + GrphSat *(Cos(GrphHue) * K5 + */ + /* Sin(GrphHue) * K6))*/ + rgb_matrix[2] = dal_fixed31_32_mul(luma_scale, rgb_matrix[2]); - rgb_matrix[11] = dal_fixed31_32_add( - ideal[3], - dal_fixed31_32_mul( - grph_bright, - dal_fixed31_32_from_fraction(86, 100))); + /* COEF_1_4 = RGBBias + RGBScale * GrphBright*/ + rgb_matrix[3] = dal_fixed31_32_add( + rgb_bias, + dal_fixed31_32_mul(rgb_scale, grph_bright)); - rgb_matrix[0] = dal_fixed31_32_mul( - multiplier, + /* COEF_2_1 = GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K7 +*/ + /* Sin(GrphHue) * K8))*/ + /* (Cos(GrphHue) * K7 + Sin(GrphHue) * K8)*/ + rgb_matrix[4] = dal_fixed31_32_add( - dal_fixed31_32_mul( - ideal[8], - sin_grph_hue), - dal_fixed31_32_mul( - ideal[4], - cos_grph_hue))); + dal_fixed31_32_mul(cos_grph_hue, k7), + dal_fixed31_32_mul(sin_grph_hue, k8)); + /* GrphSat * (Cos(GrphHue) * K7 + Sin(GrphHue) * K8)*/ + rgb_matrix[4] = dal_fixed31_32_mul(grph_sat, rgb_matrix[4]); + /* (LumaR + GrphSat * (Cos(GrphHue) * K7 + Sin(GrphHue) * K8))*/ + rgb_matrix[4] = dal_fixed31_32_add(luma_r, rgb_matrix[4]); + /* GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K7 + Sin(GrphHue)**/ + /* K8))*/ + rgb_matrix[4] = dal_fixed31_32_mul(grph_cont, rgb_matrix[4]); + /* LumaScale * GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K7 + */ + /* Sin(GrphHue) * K8))*/ + rgb_matrix[4] = dal_fixed31_32_mul(luma_scale, rgb_matrix[4]); - rgb_matrix[1] = dal_fixed31_32_mul( - multiplier, + /* COEF_2_2 = GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K9 +*/ + /* Sin(GrphHue) * K10))*/ + /* (Cos(GrphHue) * K9 + Sin(GrphHue) * K10))*/ + rgb_matrix[5] = dal_fixed31_32_add( - dal_fixed31_32_mul( - ideal[9], - sin_grph_hue), - dal_fixed31_32_mul( - ideal[5], - cos_grph_hue))); + dal_fixed31_32_mul(cos_grph_hue, k9), + dal_fixed31_32_mul(sin_grph_hue, k10)); + /* GrphSat * (Cos(GrphHue) * K9 + Sin(GrphHue) * K10))*/ + rgb_matrix[5] = dal_fixed31_32_mul(grph_sat, rgb_matrix[5]); + /* (LumaG + GrphSat * (Cos(GrphHue) * K9 + Sin(GrphHue) * K10))*/ + rgb_matrix[5] = dal_fixed31_32_add(luma_g, rgb_matrix[5]); + /* GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K9 + Sin(GrphHue)**/ + /* K10))*/ + rgb_matrix[5] = dal_fixed31_32_mul(grph_cont, rgb_matrix[5]); + /* LumaScale * GrphCont * (LumaG + GrphSat *(Cos(GrphHue) * K9 + */ + /* Sin(GrphHue) * K10))*/ + rgb_matrix[5] = dal_fixed31_32_mul(luma_scale, rgb_matrix[5]); - rgb_matrix[2] = dal_fixed31_32_mul( - multiplier, + /* COEF_2_3 = GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K11 +*/ + /* Sin(GrphHue) * K12))*/ + /* (Cos(GrphHue) * K11 + Sin(GrphHue) * K12))*/ + rgb_matrix[6] = dal_fixed31_32_add( - dal_fixed31_32_mul( - ideal[10], - sin_grph_hue), - dal_fixed31_32_mul( - ideal[6], - cos_grph_hue))); + dal_fixed31_32_mul(cos_grph_hue, k11), + dal_fixed31_32_mul(sin_grph_hue, k12)); + /* GrphSat * (Cos(GrphHue) * K11 + Sin(GrphHue) * K12))*/ + rgb_matrix[6] = dal_fixed31_32_mul(grph_sat, rgb_matrix[6]); + /* (LumaB + GrphSat * (Cos(GrphHue) * K11 + Sin(GrphHue) * K12))*/ + rgb_matrix[6] = dal_fixed31_32_add(luma_b, rgb_matrix[6]); + /* GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K11 + Sin(GrphHue)**/ + /* K12))*/ + rgb_matrix[6] = dal_fixed31_32_mul(grph_cont, rgb_matrix[6]); + /* LumaScale * GrphCont * (LumaB + GrphSat *(Cos(GrphHue) * K11 +*/ + /* Sin(GrphHue) * K12)) */ + rgb_matrix[6] = dal_fixed31_32_mul(luma_scale, rgb_matrix[6]); - rgb_matrix[3] = ideal[7]; + /* COEF_2_4 = RGBBias + RGBScale * GrphBright*/ + rgb_matrix[7] = dal_fixed31_32_add( + rgb_bias, + dal_fixed31_32_mul(rgb_scale, grph_bright)); - rgb_matrix[4] = dal_fixed31_32_mul( - multiplier, - dal_fixed31_32_sub( - dal_fixed31_32_mul( - ideal[8], - cos_grph_hue), - dal_fixed31_32_mul( - ideal[4], - sin_grph_hue))); + /* COEF_3_1 = GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K13 +*/ + /* Sin(GrphHue) * K14))*/ + /* (Cos(GrphHue) * K13 + Sin(GrphHue) * K14)) */ + rgb_matrix[8] = + dal_fixed31_32_add( + dal_fixed31_32_mul(cos_grph_hue, k13), + dal_fixed31_32_mul(sin_grph_hue, k14)); + /* GrphSat * (Cos(GrphHue) * K13 + Sin(GrphHue) * K14)) */ + rgb_matrix[8] = dal_fixed31_32_mul(grph_sat, rgb_matrix[8]); + /* (LumaR + GrphSat * (Cos(GrphHue) * K13 + Sin(GrphHue) * K14)) */ + rgb_matrix[8] = dal_fixed31_32_add(luma_r, rgb_matrix[8]); + /* GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K13 + Sin(GrphHue)**/ + /* K14)) */ + rgb_matrix[8] = dal_fixed31_32_mul(grph_cont, rgb_matrix[8]); + /* LumaScale * GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K13 +*/ + /* Sin(GrphHue) * K14))*/ + rgb_matrix[8] = dal_fixed31_32_mul(luma_scale, rgb_matrix[8]); - rgb_matrix[5] = dal_fixed31_32_mul( - multiplier, - dal_fixed31_32_sub( - dal_fixed31_32_mul( - ideal[9], - cos_grph_hue), - dal_fixed31_32_mul( - ideal[5], - sin_grph_hue))); + /* COEF_3_2 = GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K15 +*/ + /* Sin(GrphHue) * K16)) */ + /* GrphSat * (Cos(GrphHue) * K15 + Sin(GrphHue) * K16) */ + rgb_matrix[9] = + dal_fixed31_32_add( + dal_fixed31_32_mul(cos_grph_hue, k15), + dal_fixed31_32_mul(sin_grph_hue, k16)); + /* (LumaG + GrphSat * (Cos(GrphHue) * K15 + Sin(GrphHue) * K16)) */ + rgb_matrix[9] = dal_fixed31_32_mul(grph_sat, rgb_matrix[9]); + /* (LumaG + GrphSat * (Cos(GrphHue) * K15 + Sin(GrphHue) * K16)) */ + rgb_matrix[9] = dal_fixed31_32_add(luma_g, rgb_matrix[9]); + /* GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K15 + Sin(GrphHue)**/ + /* K16)) */ + rgb_matrix[9] = dal_fixed31_32_mul(grph_cont, rgb_matrix[9]); + /* LumaScale * GrphCont * (LumaG + GrphSat *(Cos(GrphHue) * K15 + */ + /* Sin(GrphHue) * K16))*/ + rgb_matrix[9] = dal_fixed31_32_mul(luma_scale, rgb_matrix[9]); - rgb_matrix[6] = dal_fixed31_32_mul( - multiplier, - dal_fixed31_32_sub( - dal_fixed31_32_mul( - ideal[10], - cos_grph_hue), - dal_fixed31_32_mul( - ideal[6], - sin_grph_hue))); + /* COEF_3_3 = GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K17 +*/ + /* Sin(GrphHue) * K18)) */ + /* (Cos(GrphHue) * K17 + Sin(GrphHue) * K18)) */ + rgb_matrix[10] = + dal_fixed31_32_add( + dal_fixed31_32_mul(cos_grph_hue, k17), + dal_fixed31_32_mul(sin_grph_hue, k18)); + /* GrphSat * (Cos(GrphHue) * K17 + Sin(GrphHue) * K18)) */ + rgb_matrix[10] = dal_fixed31_32_mul(grph_sat, rgb_matrix[10]); + /* (LumaB + GrphSat * (Cos(GrphHue) * K17 + Sin(GrphHue) * K18)) */ + rgb_matrix[10] = dal_fixed31_32_add(luma_b, rgb_matrix[10]); + /* GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K17 + Sin(GrphHue)**/ + /* K18)) */ + rgb_matrix[10] = dal_fixed31_32_mul(grph_cont, rgb_matrix[10]); + /* LumaScale * GrphCont * (LumaB + GrphSat *(Cos(GrphHue) * */ + /* K17 + Sin(GrphHue) * K18))*/ + rgb_matrix[10] = dal_fixed31_32_mul(luma_scale, rgb_matrix[10]); - rgb_matrix[7] = ideal[11]; + /* COEF_3_4 = RGBBias + RGBScale * GrphBright */ + rgb_matrix[11] = dal_fixed31_32_add( + rgb_bias, + dal_fixed31_32_mul(rgb_scale, grph_bright)); } static void calculate_yuv_matrix(struct core_color *core_color, @@ -1110,9 +1242,9 @@ static void calculate_csc_matrix(struct core_color *core_color, (csc_matrix, fixed_csc_matrix, 12); break; case COLOR_SPACE_SRGB_LIMITED: - calculate_rgb_limited_range_matrix(core_color, sink_index, - fixed_csc_matrix); - convert_float_matrix(csc_matrix, fixed_csc_matrix, 12); + calculate_rgb_limited_range_matrix_legacy( + core_color, sink_index, fixed_csc_matrix); + convert_float_matrix_legacy(csc_matrix, fixed_csc_matrix, 12); break; case COLOR_SPACE_YCBCR601: case COLOR_SPACE_YCBCR709: -- cgit From b32c34ae480b5f16e2a8efab56e39d58a191fd1e Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 1 Dec 2016 09:43:14 -0500 Subject: drm/amd/display: Removing extra newline Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/os_types.h | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/os_types.h b/drivers/gpu/drm/amd/display/dc/os_types.h index 459a2741eccb..7f0c282a1466 100644 --- a/drivers/gpu/drm/amd/display/dc/os_types.h +++ b/drivers/gpu/drm/amd/display/dc/os_types.h @@ -54,7 +54,6 @@ #define dm_min(x, y) min(x, y) #define dm_max(x, y) max(x, y) - #endif -- cgit From f60ea68d43798d9c366a8a38d4602fb7f12786e7 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 1 Dec 2016 10:00:09 -0500 Subject: drm/amd/display: Remove obsolete LATEST_ATOM_BIOS_SUPPORT Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/bios/Makefile | 1 - drivers/gpu/drm/amd/display/dc/bios/command_table.c | 16 ---------------- 2 files changed, 17 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/bios/Makefile b/drivers/gpu/drm/amd/display/dc/bios/Makefile index 9ba677f0ff01..876614d37412 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/Makefile +++ b/drivers/gpu/drm/amd/display/dc/bios/Makefile @@ -20,5 +20,4 @@ AMD_DISPLAY_FILES += $(AMDDALPATH)/dc/bios/dce80/command_table_helper_dce80.o ############################################################################### AMD_DISPLAY_FILES += $(AMDDALPATH)/dc/bios/dce110/command_table_helper_dce110.o -ccflags-y += -DLATEST_ATOM_BIOS_SUPPORT AMD_DISPLAY_FILES += $(AMDDALPATH)/dc/bios/dce112/command_table_helper_dce112.o diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table.c b/drivers/gpu/drm/amd/display/dc/bios/command_table.c index 51f6052eac96..d0eedb6235fe 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table.c @@ -115,11 +115,9 @@ static enum bp_result encoder_control_digx_v4( struct bios_parser *bp, struct bp_encoder_control *cntl); -#ifdef LATEST_ATOM_BIOS_SUPPORT static enum bp_result encoder_control_digx_v5( struct bios_parser *bp, struct bp_encoder_control *cntl); -#endif static void init_encoder_control_dig_v1(struct bios_parser *bp); @@ -136,11 +134,9 @@ static void init_dig_encoder_control(struct bios_parser *bp) bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v4; break; -#ifdef LATEST_ATOM_BIOS_SUPPORT case 5: bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v5; break; -#endif default: init_encoder_control_dig_v1(bp); @@ -290,7 +286,6 @@ static enum bp_result encoder_control_digx_v4( return result; } -#ifdef LATEST_ATOM_BIOS_SUPPORT static enum bp_result encoder_control_digx_v5( struct bios_parser *bp, struct bp_encoder_control *cntl) @@ -348,7 +343,6 @@ static enum bp_result encoder_control_digx_v5( return result; } -#endif /******************************************************************************* ******************************************************************************** @@ -829,7 +823,6 @@ static enum bp_result transmitter_control_v1_6( struct bp_transmitter_control *cntl) { enum bp_result result = BP_RESULT_FAILURE; -#ifdef LATEST_ATOM_BIOS_SUPPORT const struct command_table_helper *cmd = bp->cmd_helper; DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_6 params; @@ -883,7 +876,6 @@ static enum bp_result transmitter_control_v1_6( if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params)) result = BP_RESULT_OK; -#endif return result; } @@ -1141,7 +1133,6 @@ static enum bp_result set_pixel_clock_v7( struct bp_pixel_clock_parameters *bp_params) { enum bp_result result = BP_RESULT_FAILURE; -#ifdef LATEST_ATOM_BIOS_SUPPORT PIXEL_CLOCK_PARAMETERS_V7 clk; uint8_t controller_id; uint32_t pll_id; @@ -1203,7 +1194,6 @@ static enum bp_result set_pixel_clock_v7( if (EXEC_BIOS_CMD_TABLE(SetPixelClock, clk)) result = BP_RESULT_OK; } -#endif return result; } @@ -2539,15 +2529,12 @@ static enum bp_result enable_disp_power_gating_v2_1( ** ******************************************************************************** *******************************************************************************/ -#ifdef LATEST_ATOM_BIOS_SUPPORT static enum bp_result set_dce_clock_v2_1( struct bios_parser *bp, struct bp_set_dce_clock_parameters *bp_params); -#endif static void init_set_dce_clock(struct bios_parser *bp) { -#ifdef LATEST_ATOM_BIOS_SUPPORT switch (BIOS_CMD_TABLE_PARA_REVISION(SetDCEClock)) { case 1: bp->cmd_tbl.set_dce_clock = set_dce_clock_v2_1; @@ -2556,10 +2543,8 @@ static void init_set_dce_clock(struct bios_parser *bp) bp->cmd_tbl.set_dce_clock = NULL; break; } -#endif } -#ifdef LATEST_ATOM_BIOS_SUPPORT static enum bp_result set_dce_clock_v2_1( struct bios_parser *bp, struct bp_set_dce_clock_parameters *bp_params) @@ -2606,4 +2591,3 @@ static enum bp_result set_dce_clock_v2_1( return result; } -#endif -- cgit From 22f050be1558a878f0fec34e8efbb89f5c17a5eb Mon Sep 17 00:00:00 2001 From: Roman Li Date: Wed, 30 Nov 2016 16:23:16 -0500 Subject: drm/amd/display: fix REG_SET_5 macro Signed-off-by: Roman Li Reviewed-by: Tony Cheng Reviewed-by: Roman Li Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/inc/reg_helper.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h b/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h index 159b2c519f2b..dbc8424f7b69 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h +++ b/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h @@ -84,7 +84,7 @@ #define REG_SET_5(reg, init_value, f1, v1, f2, v2, f3, v3, f4, v4, \ f5, v5) \ - REG_SET_N(reg, 6, init_value, \ + REG_SET_N(reg, 5, init_value, \ FN(reg, f1), v1,\ FN(reg, f2), v2,\ FN(reg, f3), v3,\ -- cgit From 197062bf12d7a516ea96e24859fe5981e30ea9ff Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Wed, 30 Nov 2016 16:15:47 -0500 Subject: drm/amd/display: refactor DCE11 DVVM - move to new programming style - clean up table to make it obvious what we are programming Signed-off-by: Tony Cheng Reviewed-by: Zeyu Fan Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c | 135 ++++++++++++++++++++- drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h | 59 +++++++-- .../drm/amd/display/dc/dce100/dce100_resource.c | 6 +- .../drm/amd/display/dc/dce110/dce110_mem_input.c | 113 +---------------- .../drm/amd/display/dc/dce110/dce110_mem_input.h | 11 -- .../drm/amd/display/dc/dce110/dce110_mem_input_v.c | 8 +- .../drm/amd/display/dc/dce110/dce110_resource.c | 6 +- .../drm/amd/display/dc/dce112/dce112_resource.c | 6 +- .../gpu/drm/amd/display/dc/dce80/dce80_resource.c | 6 +- drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h | 4 +- 10 files changed, 201 insertions(+), 153 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c index 654731cccdcd..fd8a49afbec6 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c @@ -35,6 +35,137 @@ #define FN(reg_name, field_name) \ mi->shifts->field_name, mi->masks->field_name +struct pte_setting { + unsigned int bpp; + unsigned int page_width; + unsigned int page_height; + unsigned char min_pte_before_flip_horiz_scan; + unsigned char min_pte_before_flip_vert_scan; + unsigned char pte_req_per_chunk; + unsigned char param_6; + unsigned char param_7; + unsigned char param_8; +}; + +enum mi_bits_per_pixel { + mi_bpp_8 = 0, + mi_bpp_16, + mi_bpp_32, + mi_bpp_64, + mi_bpp_count, +}; + +enum mi_tiling_format { + mi_tiling_linear = 0, + mi_tiling_1D, + mi_tiling_2D, + mi_tiling_count, +}; + +static const struct pte_setting pte_settings[mi_tiling_count][mi_bpp_count] = { + [mi_tiling_linear] = { + { 8, 4096, 1, 8, 0, 1, 0, 0, 0}, + { 16, 2048, 1, 8, 0, 1, 0, 0, 0}, + { 32, 1024, 1, 8, 0, 1, 0, 0, 0}, + { 64, 512, 1, 8, 0, 1, 0, 0, 0}, /* new for 64bpp from HW */ + }, + [mi_tiling_1D] = { + { 8, 512, 8, 1, 0, 1, 0, 0, 0}, /* 0 for invalid */ + { 16, 256, 8, 2, 0, 1, 0, 0, 0}, + { 32, 128, 8, 4, 0, 1, 0, 0, 0}, + { 64, 64, 8, 4, 0, 1, 0, 0, 0}, /* fake */ + }, + [mi_tiling_2D] = { + { 8, 64, 64, 8, 8, 1, 4, 0, 0}, + { 16, 64, 32, 8, 16, 1, 8, 0, 0}, + { 32, 32, 32, 16, 16, 1, 8, 0, 0}, + { 64, 8, 32, 16, 16, 1, 8, 0, 0}, /* fake */ + }, +}; + +static enum mi_bits_per_pixel get_mi_bpp( + enum surface_pixel_format format) +{ + if (format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616) + return mi_bpp_64; + else if (format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB8888) + return mi_bpp_32; + else if (format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB1555) + return mi_bpp_16; + else + return mi_bpp_8; +} + +static enum mi_tiling_format get_mi_tiling( + union dc_tiling_info *tiling_info) +{ + switch (tiling_info->gfx8.array_mode) { + case DC_ARRAY_1D_TILED_THIN1: + case DC_ARRAY_1D_TILED_THICK: + case DC_ARRAY_PRT_TILED_THIN1: + return mi_tiling_1D; + case DC_ARRAY_2D_TILED_THIN1: + case DC_ARRAY_2D_TILED_THICK: + case DC_ARRAY_2D_TILED_X_THICK: + case DC_ARRAY_PRT_2D_TILED_THIN1: + case DC_ARRAY_PRT_2D_TILED_THICK: + return mi_tiling_2D; + case DC_ARRAY_LINEAR_GENERAL: + case DC_ARRAY_LINEAR_ALLIGNED: + return mi_tiling_linear; + default: + return mi_tiling_2D; + } +} + +static bool is_vert_scan(enum dc_rotation_angle rotation) +{ + switch (rotation) { + case ROTATION_ANGLE_90: + case ROTATION_ANGLE_270: + return true; + default: + return false; + } +} + +static unsigned int log_2(unsigned int num) +{ + unsigned int result = 0; + + while ((num >>= 1) != 0) + result++; + + return result; +} + +void dce_mem_input_program_pte_vm(struct mem_input *mi, + enum surface_pixel_format format, + union dc_tiling_info *tiling_info, + enum dc_rotation_angle rotation) +{ + enum mi_bits_per_pixel mi_bpp = get_mi_bpp(format); + enum mi_tiling_format mi_tiling = get_mi_tiling(tiling_info); + const struct pte_setting *pte = &pte_settings[mi_tiling][mi_bpp]; + + unsigned int page_width = log_2(pte->page_width); + unsigned int page_height = log_2(pte->page_height); + unsigned int min_pte_before_flip = is_vert_scan(rotation) ? + pte->min_pte_before_flip_vert_scan : + pte->min_pte_before_flip_horiz_scan; + + REG_UPDATE(GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT, + GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT, 0xff); + + REG_UPDATE_3(DVMM_PTE_CONTROL, + DVMM_PAGE_WIDTH, page_width, + DVMM_PAGE_HEIGHT, page_height, + DVMM_MIN_PTE_BEFORE_FLIP, min_pte_before_flip); + + REG_UPDATE_2(DVMM_PTE_ARB_CONTROL, + DVMM_PTE_REQ_PER_CHUNK, pte->pte_req_per_chunk, + DVMM_MAX_PTE_REQ_OUTSTANDING, 0xff); +} static void program_urgency_watermark(struct mem_input *mi, uint32_t wm_select, @@ -244,7 +375,7 @@ static void program_grph_pixel_format( GRPH_PRESCALE_B_SIGN, sign); } -bool dce_mem_input_program_surface_config(struct mem_input *mi, +void dce_mem_input_program_surface_config(struct mem_input *mi, enum surface_pixel_format format, union dc_tiling_info *tiling_info, union plane_size *plane_size, @@ -260,8 +391,6 @@ bool dce_mem_input_program_surface_config(struct mem_input *mi, if (format >= SURFACE_PIXEL_FORMAT_GRPH_BEGIN && format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) program_grph_pixel_format(mi, format); - - return true; } static uint32_t get_dmif_switch_time_us( diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h index d5930a925fcb..a366b3a5b79d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h @@ -42,10 +42,22 @@ SRI(DPG_PIPE_STUTTER_CONTROL, DMIF_PG, id),\ SRI(DMIF_BUFFER_CONTROL, PIPE, id) -#define MI_REG_LIST(id)\ +#define MI_DCE_PTE_REG_LIST(id)\ + SRI(DVMM_PTE_CONTROL, DCP, id),\ + SRI(DVMM_PTE_ARB_CONTROL, DCP, id) + +#define MI_DCE8_REG_LIST(id)\ MI_DCE_BASE_REG_LIST(id),\ SRI(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, DMIF_PG, id) +#define MI_DCE11_2_REG_LIST(id)\ + MI_DCE8_REG_LIST(id),\ + SRI(GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT, DCP, id) + +#define MI_DCE11_REG_LIST(id)\ + MI_DCE11_2_REG_LIST(id),\ + MI_DCE_PTE_REG_LIST(id) + struct dce_mem_input_registers { /* DCP */ uint32_t GRPH_ENABLE; @@ -58,6 +70,9 @@ struct dce_mem_input_registers { uint32_t HW_ROTATION; uint32_t GRPH_SWAP_CNTL; uint32_t PRESCALE_GRPH_CONTROL; + uint32_t GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT; + uint32_t DVMM_PTE_CONTROL; + uint32_t DVMM_PTE_ARB_CONTROL; /* DMIF_PG */ uint32_t DPG_PIPE_ARBITRATION_CONTROL1; uint32_t DPG_WATERMARK_MASK_CONTROL; @@ -103,6 +118,16 @@ struct dce_mem_input_registers { SFB(blk, PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_G_SIGN, mask_sh),\ SFB(blk, PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_B_SIGN, mask_sh) +#define MI_DCP_DCE11_MASK_SH_LIST(mask_sh, blk)\ + SFB(blk, GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT, GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT, mask_sh) + +#define MI_DCP_PTE_MASK_SH_LIST(mask_sh, blk)\ + SFB(blk, DVMM_PTE_CONTROL, DVMM_PAGE_WIDTH, mask_sh),\ + SFB(blk, DVMM_PTE_CONTROL, DVMM_PAGE_HEIGHT, mask_sh),\ + SFB(blk, DVMM_PTE_CONTROL, DVMM_MIN_PTE_BEFORE_FLIP, mask_sh),\ + SFB(blk, DVMM_PTE_ARB_CONTROL, DVMM_PTE_REQ_PER_CHUNK, mask_sh),\ + SFB(blk, DVMM_PTE_ARB_CONTROL, DVMM_MAX_PTE_REQ_OUTSTANDING, mask_sh) + #define MI_DMIF_PG_MASK_SH_LIST(mask_sh, blk)\ SFB(blk, DPG_PIPE_ARBITRATION_CONTROL1, PIXEL_DURATION, mask_sh),\ SFB(blk, DPG_WATERMARK_MASK_CONTROL, URGENCY_WATERMARK_MASK, mask_sh),\ @@ -122,11 +147,19 @@ struct dce_mem_input_registers { SFB(blk, DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST, mask_sh),\ SFB(blk, DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, NB_PSTATE_CHANGE_WATERMARK, mask_sh) -#define MI_DCE_MASK_SH_LIST(mask_sh)\ - MI_DCP_MASK_SH_LIST(mask_sh,),\ - MI_DMIF_PG_MASK_SH_LIST(mask_sh,),\ - MI_DMIF_PG_MASK_SH_DCE(mask_sh,),\ - MI_GFX8_TILE_MASK_SH_LIST(mask_sh,) +#define MI_DCE8_MASK_SH_LIST(mask_sh)\ + MI_DCP_MASK_SH_LIST(mask_sh, ),\ + MI_DMIF_PG_MASK_SH_LIST(mask_sh, ),\ + MI_DMIF_PG_MASK_SH_DCE(mask_sh, ),\ + MI_GFX8_TILE_MASK_SH_LIST(mask_sh, ) + +#define MI_DCE11_2_MASK_SH_LIST(mask_sh)\ + MI_DCE8_MASK_SH_LIST(mask_sh),\ + MI_DCP_DCE11_MASK_SH_LIST(mask_sh, ) + +#define MI_DCE11_MASK_SH_LIST(mask_sh)\ + MI_DCE11_2_MASK_SH_LIST(mask_sh),\ + MI_DCP_PTE_MASK_SH_LIST(mask_sh, ) #define MI_REG_FIELD_LIST(type) \ type GRPH_ENABLE; \ @@ -142,6 +175,12 @@ struct dce_mem_input_registers { type GRPH_PRESCALE_R_SIGN; \ type GRPH_PRESCALE_G_SIGN; \ type GRPH_PRESCALE_B_SIGN; \ + type GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT; \ + type DVMM_PAGE_WIDTH; \ + type DVMM_PAGE_HEIGHT; \ + type DVMM_MIN_PTE_BEFORE_FLIP; \ + type DVMM_PTE_REQ_PER_CHUNK; \ + type DVMM_MAX_PTE_REQ_OUTSTANDING; \ type GRPH_DEPTH; \ type GRPH_FORMAT; \ type GRPH_NUM_BANKS; \ @@ -191,7 +230,13 @@ struct dce_mem_input_wa { }; struct mem_input; -bool dce_mem_input_program_surface_config(struct mem_input *mi, + +void dce_mem_input_program_pte_vm(struct mem_input *mi, + enum surface_pixel_format format, + union dc_tiling_info *tiling_info, + enum dc_rotation_angle rotation); + +void dce_mem_input_program_surface_config(struct mem_input *mi, enum surface_pixel_format format, union dc_tiling_info *tiling_info, union plane_size *plane_size, diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 16595dc875a1..9ace6d1cca79 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -481,7 +481,7 @@ static const struct resource_create_funcs res_create_funcs = { }; #define mi_inst_regs(id) { \ - MI_REG_LIST(id), \ + MI_DCE8_REG_LIST(id), \ .MC_HUB_RDREQ_DMIF_LIMIT = mmMC_HUB_RDREQ_DMIF_LIMIT \ } static const struct dce_mem_input_registers mi_regs[] = { @@ -494,12 +494,12 @@ static const struct dce_mem_input_registers mi_regs[] = { }; static const struct dce_mem_input_shift mi_shifts = { - MI_DCE_MASK_SH_LIST(__SHIFT), + MI_DCE8_MASK_SH_LIST(__SHIFT), .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE__SHIFT }; static const struct dce_mem_input_mask mi_masks = { - MI_DCE_MASK_SH_LIST(_MASK), + MI_DCE8_MASK_SH_LIST(_MASK), .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE_MASK }; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c index c0a68c6f585e..af9d682f8943 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c @@ -150,117 +150,6 @@ bool dce110_mem_input_program_surface_flip_and_addr( return true; } -/* Scatter Gather param tables */ -static const unsigned int dvmm_Hw_Setting_2DTiling[4][9] = { - { 8, 64, 64, 8, 8, 1, 4, 0, 0}, - { 16, 64, 32, 8, 16, 1, 8, 0, 0}, - { 32, 32, 32, 16, 16, 1, 8, 0, 0}, - { 64, 8, 32, 16, 16, 1, 8, 0, 0}, /* fake */ -}; - -static const unsigned int dvmm_Hw_Setting_1DTiling[4][9] = { - { 8, 512, 8, 1, 0, 1, 0, 0, 0}, /* 0 for invalid */ - { 16, 256, 8, 2, 0, 1, 0, 0, 0}, - { 32, 128, 8, 4, 0, 1, 0, 0, 0}, - { 64, 64, 8, 4, 0, 1, 0, 0, 0}, /* fake */ -}; - -static const unsigned int dvmm_Hw_Setting_Linear[4][9] = { - { 8, 4096, 1, 8, 0, 1, 0, 0, 0}, - { 16, 2048, 1, 8, 0, 1, 0, 0, 0}, - { 32, 1024, 1, 8, 0, 1, 0, 0, 0}, - { 64, 512, 1, 8, 0, 1, 0, 0, 0}, /* new for 64bpp from HW */ -}; - -/* Helper to get table entry from surface info */ -static const unsigned int *get_dvmm_hw_setting( - union dc_tiling_info *tiling_info, - enum surface_pixel_format format) -{ - enum bits_per_pixel { - bpp_8 = 0, - bpp_16, - bpp_32, - bpp_64 - } bpp; - - if (format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616) - bpp = bpp_64; - else if (format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB8888) - bpp = bpp_32; - else if (format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB1555) - bpp = bpp_16; - else - bpp = bpp_8; - - switch (tiling_info->gfx8.array_mode) { - case DC_ARRAY_1D_TILED_THIN1: - case DC_ARRAY_1D_TILED_THICK: - case DC_ARRAY_PRT_TILED_THIN1: - return dvmm_Hw_Setting_1DTiling[bpp]; - case DC_ARRAY_2D_TILED_THIN1: - case DC_ARRAY_2D_TILED_THICK: - case DC_ARRAY_2D_TILED_X_THICK: - case DC_ARRAY_PRT_2D_TILED_THIN1: - case DC_ARRAY_PRT_2D_TILED_THICK: - return dvmm_Hw_Setting_2DTiling[bpp]; - case DC_ARRAY_LINEAR_GENERAL: - case DC_ARRAY_LINEAR_ALLIGNED: - return dvmm_Hw_Setting_Linear[bpp]; - default: - return dvmm_Hw_Setting_2DTiling[bpp]; - } -} - -bool dce110_mem_input_program_pte_vm( - struct mem_input *mem_input, - enum surface_pixel_format format, - union dc_tiling_info *tiling_info, - enum dc_rotation_angle rotation) -{ - struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input); - const unsigned int *pte = get_dvmm_hw_setting(tiling_info, format); - - unsigned int page_width = 0; - unsigned int page_height = 0; - unsigned int temp_page_width = pte[1]; - unsigned int temp_page_height = pte[2]; - unsigned int min_pte_before_flip = 0; - uint32_t value = 0; - - while ((temp_page_width >>= 1) != 0) - page_width++; - while ((temp_page_height >>= 1) != 0) - page_height++; - - switch (rotation) { - case ROTATION_ANGLE_90: - case ROTATION_ANGLE_270: - min_pte_before_flip = pte[4]; - break; - default: - min_pte_before_flip = pte[3]; - break; - } - - value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmGRPH_PIPE_OUTSTANDING_REQUEST_LIMIT)); - set_reg_field_value(value, 0xff, GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT, GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT); - dm_write_reg(mem_input110->base.ctx, DCP_REG(mmGRPH_PIPE_OUTSTANDING_REQUEST_LIMIT), value); - - value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmDVMM_PTE_CONTROL)); - set_reg_field_value(value, page_width, DVMM_PTE_CONTROL, DVMM_PAGE_WIDTH); - set_reg_field_value(value, page_height, DVMM_PTE_CONTROL, DVMM_PAGE_HEIGHT); - set_reg_field_value(value, min_pte_before_flip, DVMM_PTE_CONTROL, DVMM_MIN_PTE_BEFORE_FLIP); - dm_write_reg(mem_input110->base.ctx, DCP_REG(mmDVMM_PTE_CONTROL), value); - - value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmDVMM_PTE_ARB_CONTROL)); - set_reg_field_value(value, pte[5], DVMM_PTE_ARB_CONTROL, DVMM_PTE_REQ_PER_CHUNK); - set_reg_field_value(value, 0xff, DVMM_PTE_ARB_CONTROL, DVMM_MAX_PTE_REQ_OUTSTANDING); - dm_write_reg(mem_input110->base.ctx, DCP_REG(mmDVMM_PTE_ARB_CONTROL), value); - - return true; -} - static void program_urgency_watermark( const struct dc_context *ctx, const uint32_t offset, @@ -502,7 +391,7 @@ static struct mem_input_funcs dce110_mem_input_funcs = { .mem_input_program_surface_flip_and_addr = dce110_mem_input_program_surface_flip_and_addr, .mem_input_program_pte_vm = - dce110_mem_input_program_pte_vm, + dce_mem_input_program_pte_vm, .mem_input_program_surface_config = dce_mem_input_program_surface_config, .mem_input_is_flip_pending = diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.h index 83b2df93ce49..a80a20c09da4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.h @@ -107,17 +107,6 @@ bool dce110_mem_input_program_surface_config( struct dc_plane_dcc_param *dcc, bool horizontal_mirror); -/* - * dce110_mem_input_program_pte_vm - * - * This function will program pte vm registers. - */ -bool dce110_mem_input_program_pte_vm( - struct mem_input *mem_input, - enum surface_pixel_format format, - union dc_tiling_info *tiling_info, - enum dc_rotation_angle rotation); - /* * dce110_mem_input_is_flip_pending * diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c index f0310bab4030..757e946d0837 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c @@ -584,7 +584,7 @@ static const unsigned int *get_dvmm_hw_setting( } } -bool dce110_mem_input_v_program_pte_vm( +void dce110_mem_input_v_program_pte_vm( struct mem_input *mem_input, enum surface_pixel_format format, union dc_tiling_info *tiling_info, @@ -655,11 +655,9 @@ bool dce110_mem_input_v_program_pte_vm( set_reg_field_value(value, pte_chroma[5], UNP_DVMM_PTE_ARB_CONTROL_C, DVMM_PTE_REQ_PER_CHUNK_C); set_reg_field_value(value, 0xff, UNP_DVMM_PTE_ARB_CONTROL_C, DVMM_MAX_PTE_REQ_OUTSTANDING_C); dm_write_reg(mem_input110->base.ctx, DCP_REG(mmUNP_DVMM_PTE_ARB_CONTROL_C), value); - - return true; } -bool dce110_mem_input_v_program_surface_config( +void dce110_mem_input_v_program_surface_config( struct mem_input *mem_input, enum surface_pixel_format format, union dc_tiling_info *tiling_info, @@ -674,8 +672,6 @@ bool dce110_mem_input_v_program_surface_config( program_tiling(mem_input110, tiling_info, format); program_size_and_rotation(mem_input110, rotation, plane_size); program_pixel_format(mem_input110, format); - - return true; } static void program_urgency_watermark( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 959467fa421e..cac3dc425039 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -474,7 +474,7 @@ static const struct resource_create_funcs res_create_funcs = { }; #define mi_inst_regs(id) { \ - MI_REG_LIST(id), \ + MI_DCE11_REG_LIST(id), \ .MC_HUB_RDREQ_DMIF_LIMIT = mmMC_HUB_RDREQ_DMIF_LIMIT \ } static const struct dce_mem_input_registers mi_regs[] = { @@ -484,12 +484,12 @@ static const struct dce_mem_input_registers mi_regs[] = { }; static const struct dce_mem_input_shift mi_shifts = { - MI_DCE_MASK_SH_LIST(__SHIFT), + MI_DCE11_MASK_SH_LIST(__SHIFT), .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE__SHIFT }; static const struct dce_mem_input_mask mi_masks = { - MI_DCE_MASK_SH_LIST(_MASK), + MI_DCE11_MASK_SH_LIST(_MASK), .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE_MASK }; diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index bfb2c3fcd2cb..4e3273c0fa91 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -495,7 +495,7 @@ static const struct resource_create_funcs res_create_funcs = { .create_hwseq = dce112_hwseq_create, }; -#define mi_inst_regs(id) { MI_REG_LIST(id) } +#define mi_inst_regs(id) { MI_DCE11_2_REG_LIST(id) } static const struct dce_mem_input_registers mi_regs[] = { mi_inst_regs(0), mi_inst_regs(1), @@ -506,11 +506,11 @@ static const struct dce_mem_input_registers mi_regs[] = { }; static const struct dce_mem_input_shift mi_shifts = { - MI_DCE_MASK_SH_LIST(__SHIFT) + MI_DCE11_2_MASK_SH_LIST(__SHIFT) }; static const struct dce_mem_input_mask mi_masks = { - MI_DCE_MASK_SH_LIST(_MASK) + MI_DCE11_2_MASK_SH_LIST(_MASK) }; static struct mem_input *dce112_mem_input_create( diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 06720407b6fc..3b626b7883d4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -462,7 +462,7 @@ static const struct resource_create_funcs res_create_funcs = { }; #define mi_inst_regs(id) { \ - MI_REG_LIST(id), \ + MI_DCE8_REG_LIST(id), \ .MC_HUB_RDREQ_DMIF_LIMIT = mmMC_HUB_RDREQ_DMIF_LIMIT \ } static const struct dce_mem_input_registers mi_regs[] = { @@ -475,12 +475,12 @@ static const struct dce_mem_input_registers mi_regs[] = { }; static const struct dce_mem_input_shift mi_shifts = { - MI_DCE_MASK_SH_LIST(__SHIFT), + MI_DCE8_MASK_SH_LIST(__SHIFT), .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE__SHIFT }; static const struct dce_mem_input_mask mi_masks = { - MI_DCE_MASK_SH_LIST(_MASK), + MI_DCE8_MASK_SH_LIST(_MASK), .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE_MASK }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h index 78dab74edc2d..80566c844758 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h @@ -82,13 +82,13 @@ struct mem_input_funcs { const struct dc_plane_address *address, bool flip_immediate); - bool (*mem_input_program_pte_vm)( + void (*mem_input_program_pte_vm)( struct mem_input *mem_input, enum surface_pixel_format format, union dc_tiling_info *tiling_info, enum dc_rotation_angle rotation); - bool (*mem_input_program_surface_config)( + void (*mem_input_program_surface_config)( struct mem_input *mem_input, enum surface_pixel_format format, union dc_tiling_info *tiling_info, -- cgit From 565968219c7a8feebd0b0b0b960563d9a3500ba5 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Thu, 1 Dec 2016 13:37:25 -0500 Subject: drm/amd/display: Add missing GRPH register definition Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h index a366b3a5b79d..022272d30fe4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h @@ -193,6 +193,7 @@ struct dce_mem_input_registers { type GRPH_ARRAY_MODE;\ type GRPH_COLOR_EXPANSION_MODE;\ type GRPH_SW_MODE; \ + type GRPH_SE_ENABLE; \ type GRPH_NUM_SHADER_ENGINES; \ type GRPH_NUM_PIPES; \ type PIXEL_DURATION; \ -- cgit From 00d64d289fbba7f147b3a3a6fe88ca473ef6468d Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Tue, 29 Nov 2016 17:22:27 -0500 Subject: drm/amd/display: remove dead display clock code Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../display/dc/gpu/dce110/display_clock_dce110.c | 468 +------------------- .../display/dc/gpu/dce110/display_clock_dce110.h | 1 - .../display/dc/gpu/dce112/display_clock_dce112.c | 477 +-------------------- .../display/dc/gpu/dce112/display_clock_dce112.h | 18 - .../amd/display/dc/gpu/dce80/display_clock_dce80.c | 476 +------------------- .../amd/display/dc/gpu/dce80/display_clock_dce80.h | 1 - drivers/gpu/drm/amd/display/dc/gpu/display_clock.c | 122 ------ drivers/gpu/drm/amd/display/dc/gpu/display_clock.h | 28 -- .../amd/display/include/display_clock_interface.h | 85 ---- 9 files changed, 29 insertions(+), 1647 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c b/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c index 1bc39f12b6a1..cc13afa326ad 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c @@ -268,404 +268,6 @@ static void destroy(struct display_clock **base) *base = NULL; } -static uint32_t get_validation_clock(struct display_clock *dc) -{ - uint32_t clk = 0; - struct display_clock_dce110 *disp_clk = DCLCK110_FROM_BASE(dc); - - switch (disp_clk->max_clks_state) { - case CLOCKS_STATE_ULTRA_LOW: - /*Currently not supported, it has 0 in table entry*/ - case CLOCKS_STATE_LOW: - clk = max_clks_by_state[CLOCKS_STATE_LOW]. - display_clk_khz; - break; - - case CLOCKS_STATE_NOMINAL: - clk = max_clks_by_state[CLOCKS_STATE_NOMINAL]. - display_clk_khz; - break; - - case CLOCKS_STATE_PERFORMANCE: - clk = max_clks_by_state[CLOCKS_STATE_PERFORMANCE]. - display_clk_khz; - break; - - case CLOCKS_STATE_INVALID: - default: - /*Invalid Clocks State*/ - dm_logger_write(dc->ctx->logger, LOG_WARNING, - "Invalid clock state"); - /* just return the display engine clock for - * lowest supported state*/ - clk = max_clks_by_state[CLOCKS_STATE_LOW]. - display_clk_khz; - break; - } - return clk; -} - -static struct fixed32_32 get_deep_color_factor(struct min_clock_params *params) -{ - /* DeepColorFactor = IF (HDMI = True, bpp / 24, 1)*/ - struct fixed32_32 deep_color_factor = dal_fixed32_32_from_int(1); - - if (params->signal_type != SIGNAL_TYPE_HDMI_TYPE_A) - return deep_color_factor; - - switch (params->deep_color_depth) { - case COLOR_DEPTH_101010: - /*deep color ratio for 30bpp is 30/24 = 1.25*/ - deep_color_factor = dal_fixed32_32_from_fraction(30, 24); - break; - - case COLOR_DEPTH_121212: - /* deep color ratio for 36bpp is 36/24 = 1.5*/ - deep_color_factor = dal_fixed32_32_from_fraction(36, 24); - break; - - case COLOR_DEPTH_161616: - /* deep color ratio for 48bpp is 48/24 = 2.0 */ - deep_color_factor = dal_fixed32_32_from_fraction(48, 24); - break; - default: - break; - } - return deep_color_factor; -} - -static struct fixed32_32 get_scaler_efficiency( - struct dc_context *ctx, - struct min_clock_params *params) -{ - struct fixed32_32 scaler_efficiency = dal_fixed32_32_from_int(3); - - if (params->scaler_efficiency == V_SCALER_EFFICIENCY_LB18BPP) { - scaler_efficiency = - dal_fixed32_32_add( - dal_fixed32_32_from_fraction(35555, 10000), - dal_fixed32_32_from_fraction( - 55556, - 100000 * 10000)); - } else if (params->scaler_efficiency == V_SCALER_EFFICIENCY_LB24BPP) { - scaler_efficiency = - dal_fixed32_32_add( - dal_fixed32_32_from_fraction(34285, 10000), - dal_fixed32_32_from_fraction( - 71429, - 100000 * 10000)); - } else if (params->scaler_efficiency == V_SCALER_EFFICIENCY_LB30BPP) - scaler_efficiency = dal_fixed32_32_from_fraction(32, 10); - - return scaler_efficiency; -} - -static struct fixed32_32 get_lb_lines_in_per_line_out( - struct min_clock_params *params, - struct fixed32_32 v_scale_ratio) -{ - struct fixed32_32 two = dal_fixed32_32_from_int(2); - struct fixed32_32 four = dal_fixed32_32_from_int(4); - struct fixed32_32 f4_to_3 = dal_fixed32_32_from_fraction(4, 3); - struct fixed32_32 f6_to_4 = dal_fixed32_32_from_fraction(6, 4); - - if (params->line_buffer_prefetch_enabled) - return dal_fixed32_32_max(v_scale_ratio, dal_fixed32_32_one); - else if (dal_fixed32_32_le(v_scale_ratio, dal_fixed32_32_one)) - return dal_fixed32_32_one; - else if (dal_fixed32_32_le(v_scale_ratio, f4_to_3)) - return f4_to_3; - else if (dal_fixed32_32_le(v_scale_ratio, f6_to_4)) - return f6_to_4; - else if (dal_fixed32_32_le(v_scale_ratio, two)) - return two; - else if (dal_fixed32_32_le(v_scale_ratio, dal_fixed32_32_from_int(3))) - return four; - else - return dal_fixed32_32_zero; -} - -static uint32_t get_actual_required_display_clk( - struct display_clock_dce110 *disp_clk, - uint32_t target_clk_khz) -{ - uint32_t disp_clk_khz = target_clk_khz; - uint32_t div = INVALID_DIVIDER; - uint32_t did = INVALID_DID; - uint32_t scaled_vco = - disp_clk->dentist_vco_freq_khz * DIVIDER_RANGE_SCALE_FACTOR; - - ASSERT_CRITICAL(!!disp_clk_khz); - - if (disp_clk_khz) - div = scaled_vco / disp_clk_khz; - - did = dal_divider_range_get_did(divider_ranges, DIVIDER_RANGE_MAX, div); - - if (did != INVALID_DID) { - div = dal_divider_range_get_divider( - divider_ranges, DIVIDER_RANGE_MAX, did); - - if ((div != INVALID_DIVIDER) && - (did > DIVIDER_RANGE_01_BASE_DIVIDER_ID)) - if (disp_clk_khz > (scaled_vco / div)) - div = dal_divider_range_get_divider( - divider_ranges, DIVIDER_RANGE_MAX, - did - 1); - - if (div != INVALID_DIVIDER) - disp_clk_khz = scaled_vco / div; - - } - /* We need to add 10KHz to this value because the accuracy in VBIOS is - in 10KHz units. So we need to always round the last digit up in order - to reach the next div level.*/ - return disp_clk_khz + 10; -} - -static uint32_t calc_single_display_min_clks( - struct display_clock *base, - struct min_clock_params *params, - bool set_clk) -{ - struct fixed32_32 h_scale_ratio = dal_fixed32_32_one; - struct fixed32_32 v_scale_ratio = dal_fixed32_32_one; - uint32_t pix_clk_khz = 0; - uint32_t lb_source_width = 0; - struct fixed32_32 deep_color_factor; - struct fixed32_32 scaler_efficiency; - struct fixed32_32 v_filter_init; - uint32_t v_filter_init_trunc; - uint32_t num_lines_at_frame_start = 3; - struct fixed32_32 v_filter_init_ceil; - struct fixed32_32 lines_per_lines_out_at_frame_start; - struct fixed32_32 lb_lines_in_per_line_out; /* in middle of the frame*/ - uint32_t src_wdth_rnd_to_chunks; - struct fixed32_32 scaling_coeff; - struct fixed32_32 h_blank_granularity_factor = - dal_fixed32_32_one; - struct fixed32_32 fx_disp_clk_mhz; - struct fixed32_32 line_time; - struct fixed32_32 disp_pipe_pix_throughput; - struct fixed32_32 fx_alt_disp_clk_mhz; - uint32_t disp_clk_khz; - uint32_t alt_disp_clk_khz; - struct display_clock_dce110 *disp_clk_110 = DCLCK110_FROM_BASE(base); - uint32_t max_clk_khz = get_validation_clock(base); - bool panning_allowed = false; /* TODO: receive this value from AS */ - - if (params == NULL) { - dm_logger_write(base->ctx->logger, LOG_WARNING, - "Invalid input parameter in %s", - __func__); - return 0; - } - - deep_color_factor = get_deep_color_factor(params); - scaler_efficiency = get_scaler_efficiency(base->ctx, params); - pix_clk_khz = params->requested_pixel_clock; - lb_source_width = params->source_view.width; - - if (0 != params->dest_view.height && 0 != params->dest_view.width) { - - h_scale_ratio = dal_fixed32_32_from_fraction( - params->source_view.width, - params->dest_view.width); - v_scale_ratio = dal_fixed32_32_from_fraction( - params->source_view.height, - params->dest_view.height); - } else { - dm_logger_write(base->ctx->logger, LOG_WARNING, - "Destination height or width is 0!\n"); - } - - v_filter_init = - dal_fixed32_32_add( - v_scale_ratio, - dal_fixed32_32_add_int( - dal_fixed32_32_div_int( - dal_fixed32_32_mul_int( - v_scale_ratio, - params->timing_info.INTERLACED), - 2), - params->scaling_info.v_taps + 1)); - v_filter_init = dal_fixed32_32_div_int(v_filter_init, 2); - - v_filter_init_trunc = dal_fixed32_32_floor(v_filter_init); - - v_filter_init_ceil = dal_fixed32_32_from_fraction( - v_filter_init_trunc, 2); - v_filter_init_ceil = dal_fixed32_32_from_int( - dal_fixed32_32_ceil(v_filter_init_ceil)); - v_filter_init_ceil = dal_fixed32_32_mul_int(v_filter_init_ceil, 2); - - lines_per_lines_out_at_frame_start = - dal_fixed32_32_div_int(v_filter_init_ceil, - num_lines_at_frame_start); - lb_lines_in_per_line_out = - get_lb_lines_in_per_line_out(params, v_scale_ratio); - - if (panning_allowed) - src_wdth_rnd_to_chunks = - ((lb_source_width - 1) / 128) * 128 + 256; - else - src_wdth_rnd_to_chunks = - ((lb_source_width + 127) / 128) * 128; - - scaling_coeff = - dal_fixed32_32_div( - dal_fixed32_32_from_int(params->scaling_info.v_taps), - scaler_efficiency); - - if (dal_fixed32_32_le(h_scale_ratio, dal_fixed32_32_one)) - scaling_coeff = dal_fixed32_32_max( - dal_fixed32_32_from_int( - dal_fixed32_32_ceil( - dal_fixed32_32_from_fraction( - params->scaling_info.h_taps, - 4))), - dal_fixed32_32_max( - dal_fixed32_32_mul( - scaling_coeff, - h_scale_ratio), - dal_fixed32_32_one)); - - if (!params->line_buffer_prefetch_enabled && - dal_fixed32_32_floor(lb_lines_in_per_line_out) != 2 && - dal_fixed32_32_floor(lb_lines_in_per_line_out) != 4) { - uint32_t line_total_pixel = - params->timing_info.h_total + lb_source_width - 256; - h_blank_granularity_factor = dal_fixed32_32_div( - dal_fixed32_32_from_int(params->timing_info.h_total), - dal_fixed32_32_div( - dal_fixed32_32_from_fraction( - line_total_pixel, 2), - h_scale_ratio)); - } - - /* Calculate display clock with ramping. Ramping factor is 1.1*/ - fx_disp_clk_mhz = - dal_fixed32_32_div_int( - dal_fixed32_32_mul_int(scaling_coeff, 11), - 10); - line_time = dal_fixed32_32_from_fraction( - params->timing_info.h_total * 1000, pix_clk_khz); - - disp_pipe_pix_throughput = dal_fixed32_32_mul( - lb_lines_in_per_line_out, h_blank_granularity_factor); - disp_pipe_pix_throughput = dal_fixed32_32_max( - disp_pipe_pix_throughput, - lines_per_lines_out_at_frame_start); - disp_pipe_pix_throughput = dal_fixed32_32_div(dal_fixed32_32_mul_int( - disp_pipe_pix_throughput, src_wdth_rnd_to_chunks), - line_time); - - if (0 != params->timing_info.h_total) { - fx_disp_clk_mhz = - dal_fixed32_32_max( - dal_fixed32_32_div_int( - dal_fixed32_32_mul_int( - scaling_coeff, pix_clk_khz), - 1000), - disp_pipe_pix_throughput); - fx_disp_clk_mhz = - dal_fixed32_32_mul( - fx_disp_clk_mhz, - dal_fixed32_32_from_fraction(11, 10)); - } - - fx_disp_clk_mhz = dal_fixed32_32_max(fx_disp_clk_mhz, - dal_fixed32_32_mul(deep_color_factor, - dal_fixed32_32_from_fraction(11, 10))); - - /* Calculate display clock without ramping */ - fx_alt_disp_clk_mhz = scaling_coeff; - - if (0 != params->timing_info.h_total) { - fx_alt_disp_clk_mhz = dal_fixed32_32_max( - dal_fixed32_32_div_int(dal_fixed32_32_mul_int( - scaling_coeff, pix_clk_khz), - 1000), - dal_fixed32_32_div_int(dal_fixed32_32_mul_int( - disp_pipe_pix_throughput, 105), - 100)); - } - - if (set_clk && disp_clk_110->ss_on_gpu_pll && - disp_clk_110->gpu_pll_ss_divider) - fx_alt_disp_clk_mhz = dal_fixed32_32_mul(fx_alt_disp_clk_mhz, - dal_fixed32_32_add_int( - dal_fixed32_32_div_int( - dal_fixed32_32_div_int( - dal_fixed32_32_from_fraction( - disp_clk_110->gpu_pll_ss_percentage, - disp_clk_110->gpu_pll_ss_divider), 100), - 2), - 1)); - - /* convert to integer */ - disp_clk_khz = dal_fixed32_32_round( - dal_fixed32_32_mul_int(fx_disp_clk_mhz, 1000)); - alt_disp_clk_khz = dal_fixed32_32_round( - dal_fixed32_32_mul_int(fx_alt_disp_clk_mhz, 1000)); - - if ((disp_clk_khz > max_clk_khz) && (alt_disp_clk_khz <= max_clk_khz)) - disp_clk_khz = alt_disp_clk_khz; - - if (set_clk) { /* only compensate clock if we are going to set it.*/ - disp_clk_khz = get_actual_required_display_clk( - disp_clk_110, disp_clk_khz); - } - - disp_clk_khz = disp_clk_khz > max_clk_khz ? max_clk_khz : disp_clk_khz; - - return disp_clk_khz; -} - -static uint32_t calculate_min_clock( - struct display_clock *base, - uint32_t path_num, - struct min_clock_params *params) -{ - uint32_t i; - uint32_t validation_clk_khz = - get_validation_clock(base); - uint32_t min_clk_khz = validation_clk_khz; - uint32_t max_clk_khz = 0; - struct display_clock_dce110 *dc = DCLCK110_FROM_BASE(base); - - if (dc->use_max_disp_clk) - return min_clk_khz; - - if (params != NULL) { - uint32_t disp_clk_khz = 0; - - for (i = 0; i < path_num; ++i) { - - disp_clk_khz = calc_single_display_min_clks( - base, params, true); - - /* update the max required clock found*/ - if (disp_clk_khz > max_clk_khz) - max_clk_khz = disp_clk_khz; - - params++; - } - } - - min_clk_khz = max_clk_khz; - - if (min_clk_khz > validation_clk_khz) - min_clk_khz = validation_clk_khz; - else if (min_clk_khz < base->min_display_clk_threshold_khz) - min_clk_khz = base->min_display_clk_threshold_khz; - - if (dc->use_max_disp_clk) - min_clk_khz = get_validation_clock(base); - - return min_clk_khz; -} - static bool display_clock_integrated_info_construct( struct display_clock_dce110 *disp_clk) { @@ -741,38 +343,6 @@ static bool display_clock_integrated_info_construct( return true; } -static uint32_t get_clock(struct display_clock *dc) -{ - uint32_t disp_clock = get_validation_clock(dc); - uint32_t target_div = INVALID_DIVIDER; - uint32_t addr = mmDENTIST_DISPCLK_CNTL; - uint32_t value = 0; - uint32_t field = 0; - struct display_clock_dce110 *disp_clk = DCLCK110_FROM_BASE(dc); - - if (disp_clk->dfs_bypass_enabled && disp_clk->dfs_bypass_disp_clk) - return disp_clk->dfs_bypass_disp_clk; - - /* Read the mmDENTIST_DISPCLK_CNTL to get the currently programmed - DID DENTIST_DISPCLK_WDIVIDER.*/ - value = dm_read_reg(dc->ctx, addr); - field = get_reg_field_value( - value, DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER); - - /* Convert DENTIST_DISPCLK_WDIVIDER to actual divider*/ - target_div = dal_divider_range_get_divider( - divider_ranges, - DIVIDER_RANGE_MAX, - field); - - if (target_div != INVALID_DIVIDER) - /* Calculate the current DFS clock in KHz. - Should be okay up to 42.9 THz before overflowing.*/ - disp_clock = (DIVIDER_RANGE_SCALE_FACTOR - * disp_clk->dentist_vco_freq_khz) / target_div; - return disp_clock; -} - static enum clocks_state get_required_clocks_state( struct display_clock *dc, struct state_dependent_clocks *req_clocks) @@ -882,44 +452,15 @@ static void set_clock( psr_wait_loop(base->ctx, requested_clk_khz); } -static void set_clock_state( - struct display_clock *dc, - struct display_clock_state clk_state) -{ - struct display_clock_dce110 *disp_clk = DCLCK110_FROM_BASE(dc); - - disp_clk->clock_state = clk_state; -} - -static struct display_clock_state get_clock_state( - struct display_clock *dc) -{ - struct display_clock_dce110 *disp_clk = DCLCK110_FROM_BASE(dc); - - return disp_clk->clock_state; -} - -static uint32_t get_dfs_bypass_threshold(struct display_clock *dc) -{ - return DCE110_DFS_BYPASS_THRESHOLD_KHZ; -} static const struct display_clock_funcs funcs = { .destroy = destroy, - .calculate_min_clock = calculate_min_clock, - .get_clock = get_clock, - .get_clock_state = get_clock_state, - .get_dfs_bypass_threshold = get_dfs_bypass_threshold, .get_dp_ref_clk_frequency = get_dp_ref_clk_frequency, .get_min_clocks_state = get_min_clocks_state, .get_required_clocks_state = get_required_clocks_state, - .get_validation_clock = get_validation_clock, .set_clock = set_clock, - .set_clock_state = set_clock_state, - .set_dp_ref_clock_source = NULL, .set_min_clocks_state = set_min_clocks_state, - .store_max_clocks_state = store_max_clocks_state, - .validate = NULL, + .store_max_clocks_state = store_max_clocks_state }; static bool dal_display_clock_dce110_construct( @@ -929,8 +470,11 @@ static bool dal_display_clock_dce110_construct( struct display_clock *dc_base = &dc110->disp_clk_base; struct dc_bios *bp = ctx->dc_bios; - if (!dal_display_clock_construct_base(dc_base, ctx)) - return false; + dc_base->ctx = ctx; + dc_base->id = CLOCK_SOURCE_ID_DCPLL; + dc_base->min_display_clk_threshold_khz = 0; + + dc_base->cur_min_clks_state = CLOCKS_STATE_INVALID; dc_base->funcs = &funcs; diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.h b/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.h index 0cdc7b52a09f..88b4bdd75e56 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.h +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.h @@ -44,7 +44,6 @@ struct display_clock_dce110 { /* Cache the display clock returned by VBIOS if DFS-bypass is enabled. * This is basically "Crystal Frequency In KHz" (XTALIN) frequency */ uint32_t dfs_bypass_disp_clk; - struct display_clock_state clock_state; }; #define DCLCK110_FROM_BASE(dc_base) \ diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c index 9b7c9755e316..bf044260c0bb 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c @@ -242,406 +242,6 @@ void dispclk_dce112_destroy(struct display_clock **base) *base = NULL; } -uint32_t dispclk_dce112_get_validation_clock(struct display_clock *dc) -{ - uint32_t clk = 0; - struct display_clock_dce112 *disp_clk = DCLCK112_FROM_BASE(dc); - - switch (disp_clk->max_clks_state) { - case CLOCKS_STATE_ULTRA_LOW: - clk = (disp_clk->max_clks_by_state + CLOCKS_STATE_ULTRA_LOW)-> - display_clk_khz; - - case CLOCKS_STATE_LOW: - clk = (disp_clk->max_clks_by_state + CLOCKS_STATE_LOW)-> - display_clk_khz; - break; - - case CLOCKS_STATE_NOMINAL: - clk = (disp_clk->max_clks_by_state + CLOCKS_STATE_NOMINAL)-> - display_clk_khz; - break; - - case CLOCKS_STATE_PERFORMANCE: - clk = (disp_clk->max_clks_by_state + CLOCKS_STATE_PERFORMANCE)-> - display_clk_khz; - break; - - case CLOCKS_STATE_INVALID: - default: - /*Invalid Clocks State*/ - dm_logger_write(dc->ctx->logger, LOG_WARNING, - "Invalid clock state"); - /* just return the display engine clock for - * lowest supported state*/ - clk = (disp_clk->max_clks_by_state + CLOCKS_STATE_LOW)-> - display_clk_khz; - break; - } - return clk; -} - -static struct fixed32_32 get_deep_color_factor(struct min_clock_params *params) -{ - /* DeepColorFactor = IF (HDMI = True, bpp / 24, 1)*/ - struct fixed32_32 deep_color_factor = dal_fixed32_32_from_int(1); - - if (params->signal_type != SIGNAL_TYPE_HDMI_TYPE_A) - return deep_color_factor; - - switch (params->deep_color_depth) { - case COLOR_DEPTH_101010: - /*deep color ratio for 30bpp is 30/24 = 1.25*/ - deep_color_factor = dal_fixed32_32_from_fraction(30, 24); - break; - - case COLOR_DEPTH_121212: - /* deep color ratio for 36bpp is 36/24 = 1.5*/ - deep_color_factor = dal_fixed32_32_from_fraction(36, 24); - break; - - case COLOR_DEPTH_161616: - /* deep color ratio for 48bpp is 48/24 = 2.0 */ - deep_color_factor = dal_fixed32_32_from_fraction(48, 24); - break; - default: - break; - } - return deep_color_factor; -} - -static struct fixed32_32 get_scaler_efficiency( - struct dc_context *ctx, - struct min_clock_params *params) -{ - struct fixed32_32 scaler_efficiency = dal_fixed32_32_from_int(3); - - if (params->scaler_efficiency == V_SCALER_EFFICIENCY_LB18BPP) { - scaler_efficiency = - dal_fixed32_32_add( - dal_fixed32_32_from_fraction(35555, 10000), - dal_fixed32_32_from_fraction( - 55556, - 100000 * 10000)); - } else if (params->scaler_efficiency == V_SCALER_EFFICIENCY_LB24BPP) { - scaler_efficiency = - dal_fixed32_32_add( - dal_fixed32_32_from_fraction(34285, 10000), - dal_fixed32_32_from_fraction( - 71429, - 100000 * 10000)); - } else if (params->scaler_efficiency == V_SCALER_EFFICIENCY_LB30BPP) - scaler_efficiency = dal_fixed32_32_from_fraction(32, 10); - - return scaler_efficiency; -} - -static struct fixed32_32 get_lb_lines_in_per_line_out( - struct min_clock_params *params, - struct fixed32_32 v_scale_ratio) -{ - struct fixed32_32 two = dal_fixed32_32_from_int(2); - struct fixed32_32 four = dal_fixed32_32_from_int(4); - struct fixed32_32 f4_to_3 = dal_fixed32_32_from_fraction(4, 3); - struct fixed32_32 f6_to_4 = dal_fixed32_32_from_fraction(6, 4); - - if (params->line_buffer_prefetch_enabled) - return dal_fixed32_32_max(v_scale_ratio, dal_fixed32_32_one); - else if (dal_fixed32_32_le(v_scale_ratio, dal_fixed32_32_one)) - return dal_fixed32_32_one; - else if (dal_fixed32_32_le(v_scale_ratio, f4_to_3)) - return f4_to_3; - else if (dal_fixed32_32_le(v_scale_ratio, f6_to_4)) - return f6_to_4; - else if (dal_fixed32_32_le(v_scale_ratio, two)) - return two; - else if (dal_fixed32_32_le(v_scale_ratio, dal_fixed32_32_from_int(3))) - return four; - else - return dal_fixed32_32_zero; -} - -static uint32_t get_actual_required_display_clk( - struct display_clock_dce112 *disp_clk, - uint32_t target_clk_khz) -{ - uint32_t disp_clk_khz = target_clk_khz; - uint32_t div = INVALID_DIVIDER; - uint32_t did = INVALID_DID; - uint32_t scaled_vco = - disp_clk->dentist_vco_freq_khz * DIVIDER_RANGE_SCALE_FACTOR; - - ASSERT_CRITICAL(!!disp_clk_khz); - - if (disp_clk_khz) - div = scaled_vco / disp_clk_khz; - - did = dal_divider_range_get_did(divider_ranges, DIVIDER_RANGE_MAX, div); - - if (did != INVALID_DID) { - div = dal_divider_range_get_divider( - divider_ranges, DIVIDER_RANGE_MAX, did); - - if ((div != INVALID_DIVIDER) && - (did > DIVIDER_RANGE_01_BASE_DIVIDER_ID)) - if (disp_clk_khz > (scaled_vco / div)) - div = dal_divider_range_get_divider( - divider_ranges, DIVIDER_RANGE_MAX, - did - 1); - - if (div != INVALID_DIVIDER) - disp_clk_khz = scaled_vco / div; - - } - /* We need to add 10KHz to this value because the accuracy in VBIOS is - in 10KHz units. So we need to always round the last digit up in order - to reach the next div level.*/ - return disp_clk_khz + 10; -} - -static uint32_t calc_single_display_min_clks( - struct display_clock *base, - struct min_clock_params *params, - bool set_clk) -{ - struct fixed32_32 h_scale_ratio = dal_fixed32_32_one; - struct fixed32_32 v_scale_ratio = dal_fixed32_32_one; - uint32_t pix_clk_khz = 0; - uint32_t lb_source_width = 0; - struct fixed32_32 deep_color_factor; - struct fixed32_32 scaler_efficiency; - struct fixed32_32 v_filter_init; - uint32_t v_filter_init_trunc; - uint32_t num_lines_at_frame_start = 3; - struct fixed32_32 v_filter_init_ceil; - struct fixed32_32 lines_per_lines_out_at_frame_start; - struct fixed32_32 lb_lines_in_per_line_out; /* in middle of the frame*/ - uint32_t src_wdth_rnd_to_chunks; - struct fixed32_32 scaling_coeff; - struct fixed32_32 h_blank_granularity_factor = - dal_fixed32_32_one; - struct fixed32_32 fx_disp_clk_mhz; - struct fixed32_32 line_time; - struct fixed32_32 disp_pipe_pix_throughput; - struct fixed32_32 fx_alt_disp_clk_mhz; - uint32_t disp_clk_khz; - uint32_t alt_disp_clk_khz; - struct display_clock_dce112 *disp_clk_110 = DCLCK112_FROM_BASE(base); - uint32_t max_clk_khz = dispclk_dce112_get_validation_clock(base); - bool panning_allowed = false; /* TODO: receive this value from AS */ - - if (params == NULL) { - dm_logger_write(base->ctx->logger, LOG_WARNING, - "Invalid input parameter in %s", - __func__); - return 0; - } - - deep_color_factor = get_deep_color_factor(params); - scaler_efficiency = get_scaler_efficiency(base->ctx, params); - pix_clk_khz = params->requested_pixel_clock; - lb_source_width = params->source_view.width; - - if (0 != params->dest_view.height && 0 != params->dest_view.width) { - - h_scale_ratio = dal_fixed32_32_from_fraction( - params->source_view.width, - params->dest_view.width); - v_scale_ratio = dal_fixed32_32_from_fraction( - params->source_view.height, - params->dest_view.height); - } else { - dm_logger_write(base->ctx->logger, LOG_WARNING, - "Destination height or width is 0!\n"); - } - - v_filter_init = - dal_fixed32_32_add( - v_scale_ratio, - dal_fixed32_32_add_int( - dal_fixed32_32_div_int( - dal_fixed32_32_mul_int( - v_scale_ratio, - params->timing_info.INTERLACED), - 2), - params->scaling_info.v_taps + 1)); - v_filter_init = dal_fixed32_32_div_int(v_filter_init, 2); - - v_filter_init_trunc = dal_fixed32_32_floor(v_filter_init); - - v_filter_init_ceil = dal_fixed32_32_from_fraction( - v_filter_init_trunc, 2); - v_filter_init_ceil = dal_fixed32_32_from_int( - dal_fixed32_32_ceil(v_filter_init_ceil)); - v_filter_init_ceil = dal_fixed32_32_mul_int(v_filter_init_ceil, 2); - - lines_per_lines_out_at_frame_start = - dal_fixed32_32_div_int(v_filter_init_ceil, - num_lines_at_frame_start); - lb_lines_in_per_line_out = - get_lb_lines_in_per_line_out(params, v_scale_ratio); - - if (panning_allowed) - src_wdth_rnd_to_chunks = - ((lb_source_width - 1) / 128) * 128 + 256; - else - src_wdth_rnd_to_chunks = - ((lb_source_width + 127) / 128) * 128; - - scaling_coeff = - dal_fixed32_32_div( - dal_fixed32_32_from_int(params->scaling_info.v_taps), - scaler_efficiency); - - if (dal_fixed32_32_le(h_scale_ratio, dal_fixed32_32_one)) - scaling_coeff = dal_fixed32_32_max( - dal_fixed32_32_from_int( - dal_fixed32_32_ceil( - dal_fixed32_32_from_fraction( - params->scaling_info.h_taps, - 4))), - dal_fixed32_32_max( - dal_fixed32_32_mul( - scaling_coeff, - h_scale_ratio), - dal_fixed32_32_one)); - - if (!params->line_buffer_prefetch_enabled && - dal_fixed32_32_floor(lb_lines_in_per_line_out) != 2 && - dal_fixed32_32_floor(lb_lines_in_per_line_out) != 4) { - uint32_t line_total_pixel = - params->timing_info.h_total + lb_source_width - 256; - h_blank_granularity_factor = dal_fixed32_32_div( - dal_fixed32_32_from_int(params->timing_info.h_total), - dal_fixed32_32_div( - dal_fixed32_32_from_fraction( - line_total_pixel, 2), - h_scale_ratio)); - } - - /* Calculate display clock with ramping. Ramping factor is 1.1*/ - fx_disp_clk_mhz = - dal_fixed32_32_div_int( - dal_fixed32_32_mul_int(scaling_coeff, 11), - 10); - line_time = dal_fixed32_32_from_fraction( - params->timing_info.h_total * 1000, pix_clk_khz); - - disp_pipe_pix_throughput = dal_fixed32_32_mul( - lb_lines_in_per_line_out, h_blank_granularity_factor); - disp_pipe_pix_throughput = dal_fixed32_32_max( - disp_pipe_pix_throughput, - lines_per_lines_out_at_frame_start); - disp_pipe_pix_throughput = dal_fixed32_32_div(dal_fixed32_32_mul_int( - disp_pipe_pix_throughput, src_wdth_rnd_to_chunks), - line_time); - - if (0 != params->timing_info.h_total) { - fx_disp_clk_mhz = - dal_fixed32_32_max( - dal_fixed32_32_div_int( - dal_fixed32_32_mul_int( - scaling_coeff, pix_clk_khz), - 1000), - disp_pipe_pix_throughput); - fx_disp_clk_mhz = - dal_fixed32_32_mul( - fx_disp_clk_mhz, - dal_fixed32_32_from_fraction(11, 10)); - } - - fx_disp_clk_mhz = dal_fixed32_32_max(fx_disp_clk_mhz, - dal_fixed32_32_mul(deep_color_factor, - dal_fixed32_32_from_fraction(11, 10))); - - /* Calculate display clock without ramping */ - fx_alt_disp_clk_mhz = scaling_coeff; - - if (0 != params->timing_info.h_total) { - fx_alt_disp_clk_mhz = dal_fixed32_32_max( - dal_fixed32_32_div_int(dal_fixed32_32_mul_int( - scaling_coeff, pix_clk_khz), - 1000), - dal_fixed32_32_div_int(dal_fixed32_32_mul_int( - disp_pipe_pix_throughput, 105), - 100)); - } - - if (set_clk && disp_clk_110->ss_on_gpu_pll && - disp_clk_110->gpu_pll_ss_divider) - fx_alt_disp_clk_mhz = dal_fixed32_32_mul(fx_alt_disp_clk_mhz, - dal_fixed32_32_add_int( - dal_fixed32_32_div_int( - dal_fixed32_32_div_int( - dal_fixed32_32_from_fraction( - disp_clk_110->gpu_pll_ss_percentage, - disp_clk_110->gpu_pll_ss_divider), 100), - 2), - 1)); - - /* convert to integer */ - disp_clk_khz = dal_fixed32_32_round( - dal_fixed32_32_mul_int(fx_disp_clk_mhz, 1000)); - alt_disp_clk_khz = dal_fixed32_32_round( - dal_fixed32_32_mul_int(fx_alt_disp_clk_mhz, 1000)); - - if ((disp_clk_khz > max_clk_khz) && (alt_disp_clk_khz <= max_clk_khz)) - disp_clk_khz = alt_disp_clk_khz; - - if (set_clk) { /* only compensate clock if we are going to set it.*/ - disp_clk_khz = get_actual_required_display_clk( - disp_clk_110, disp_clk_khz); - } - - disp_clk_khz = disp_clk_khz > max_clk_khz ? max_clk_khz : disp_clk_khz; - - return disp_clk_khz; -} - -uint32_t dispclk_dce112_calculate_min_clock( - struct display_clock *base, - uint32_t path_num, - struct min_clock_params *params) -{ - uint32_t i; - uint32_t validation_clk_khz = - dispclk_dce112_get_validation_clock(base); - uint32_t min_clk_khz = validation_clk_khz; - uint32_t max_clk_khz = 0; - struct display_clock_dce112 *dc = DCLCK112_FROM_BASE(base); - - if (dc->use_max_disp_clk) - return min_clk_khz; - - if (params != NULL) { - uint32_t disp_clk_khz = 0; - - for (i = 0; i < path_num; ++i) { - - disp_clk_khz = calc_single_display_min_clks( - base, params, true); - - /* update the max required clock found*/ - if (disp_clk_khz > max_clk_khz) - max_clk_khz = disp_clk_khz; - - params++; - } - } - - min_clk_khz = max_clk_khz; - - if (min_clk_khz > validation_clk_khz) - min_clk_khz = validation_clk_khz; - else if (min_clk_khz < base->min_display_clk_threshold_khz) - min_clk_khz = base->min_display_clk_threshold_khz; - - if (dc->use_max_disp_clk) - min_clk_khz = dispclk_dce112_get_validation_clock(base); - - return min_clk_khz; -} - static bool display_clock_integrated_info_construct( struct display_clock_dce112 *disp_clk) { @@ -655,8 +255,6 @@ static bool display_clock_integrated_info_construct( if (disp_clk->dentist_vco_freq_khz == 0) disp_clk->dentist_vco_freq_khz = 3600000; - disp_clk->crystal_freq_khz = 100000; - base->min_display_clk_threshold_khz = disp_clk->dentist_vco_freq_khz / 64; @@ -698,35 +296,6 @@ static bool display_clock_integrated_info_construct( return true; } -static uint32_t get_clock(struct display_clock *dc) -{ - uint32_t disp_clock = dispclk_dce112_get_validation_clock(dc); - uint32_t target_div = INVALID_DIVIDER; - uint32_t addr = mmDENTIST_DISPCLK_CNTL; - uint32_t value = 0; - uint32_t field = 0; - struct display_clock_dce112 *disp_clk = DCLCK112_FROM_BASE(dc); - - /* Read the mmDENTIST_DISPCLK_CNTL to get the currently programmed - DID DENTIST_DISPCLK_WDIVIDER.*/ - value = dm_read_reg(dc->ctx, addr); - field = get_reg_field_value( - value, DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER); - - /* Convert DENTIST_DISPCLK_WDIVIDER to actual divider*/ - target_div = dal_divider_range_get_divider( - divider_ranges, - DIVIDER_RANGE_MAX, - field); - - if (target_div != INVALID_DIVIDER) - /* Calculate the current DFS clock in KHz. - Should be okay up to 42.9 THz before overflowing.*/ - disp_clock = (DIVIDER_RANGE_SCALE_FACTOR - * disp_clk->dentist_vco_freq_khz) / target_div; - return disp_clock; -} - enum clocks_state dispclk_dce112_get_required_clocks_state( struct display_clock *dc, struct state_dependent_clocks *req_clocks) @@ -797,45 +366,14 @@ void dispclk_dce112_set_clock( bp->funcs->set_dce_clock(bp, &dce_clk_params); } -void dispclk_dce112_set_clock_state( - struct display_clock *dc, - struct display_clock_state clk_state) -{ - struct display_clock_dce112 *disp_clk = DCLCK112_FROM_BASE(dc); - - disp_clk->clock_state = clk_state; -} - -struct display_clock_state dispclk_dce112_get_clock_state( - struct display_clock *dc) -{ - struct display_clock_dce112 *disp_clk = DCLCK112_FROM_BASE(dc); - - return disp_clk->clock_state; -} - -uint32_t dispclk_dce112_get_dfs_bypass_threshold( - struct display_clock *dc) -{ - return dce112_DFS_BYPASS_THRESHOLD_KHZ; -} - static const struct display_clock_funcs funcs = { .destroy = dispclk_dce112_destroy, - .calculate_min_clock = dispclk_dce112_calculate_min_clock, - .get_clock = get_clock, - .get_clock_state = dispclk_dce112_get_clock_state, - .get_dfs_bypass_threshold = dispclk_dce112_get_dfs_bypass_threshold, .get_dp_ref_clk_frequency = get_dp_ref_clk_frequency, .get_min_clocks_state = dispclk_dce112_get_min_clocks_state, .get_required_clocks_state = dispclk_dce112_get_required_clocks_state, - .get_validation_clock = dispclk_dce112_get_validation_clock, .set_clock = dispclk_dce112_set_clock, - .set_clock_state = dispclk_dce112_set_clock_state, - .set_dp_ref_clock_source = NULL, .set_min_clocks_state = dispclk_dce112_set_min_clocks_state, .store_max_clocks_state = dispclk_dce112_store_max_clocks_state, - .validate = NULL, }; bool dal_display_clock_dce112_construct( @@ -844,11 +382,11 @@ bool dal_display_clock_dce112_construct( { struct display_clock *dc_base = &dc112->disp_clk_base; - /*if (NULL == as) - return false;*/ + dc_base->ctx = ctx; + dc_base->id = CLOCK_SOURCE_ID_DCPLL; + dc_base->min_display_clk_threshold_khz = 0; - if (!dal_display_clock_construct_base(dc_base, ctx)) - return false; + dc_base->cur_min_clks_state = CLOCKS_STATE_INVALID; dc_base->funcs = &funcs; @@ -870,12 +408,7 @@ bool dal_display_clock_dce112_construct( dc112->max_clks_state = CLOCKS_STATE_NOMINAL; dc112->disp_clk_base.min_display_clk_threshold_khz = - dc112->crystal_freq_khz; - - if (dc112->disp_clk_base.min_display_clk_threshold_khz < - (dc112->dentist_vco_freq_khz / 62)) - dc112->disp_clk_base.min_display_clk_threshold_khz = - (dc112->dentist_vco_freq_khz / 62); + (dc112->dentist_vco_freq_khz / 62); dal_divider_range_construct( ÷r_ranges[DIVIDER_RANGE_01], diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h index 937e17929b7c..5ab31185d29d 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h @@ -45,7 +45,6 @@ struct display_clock_dce112 { /* Cache the display clock returned by VBIOS if DFS-bypass is enabled. * This is basically "Crystal Frequency In KHz" (XTALIN) frequency */ uint32_t dfs_bypass_disp_clk; - struct display_clock_state clock_state; struct state_dependent_clocks *max_clks_by_state; }; @@ -75,17 +74,6 @@ bool dal_display_clock_dce112_construct( void dispclk_dce112_destroy(struct display_clock **base); -uint32_t dispclk_dce112_calculate_min_clock( - struct display_clock *base, - uint32_t path_num, - struct min_clock_params *params); - -struct display_clock_state dispclk_dce112_get_clock_state( - struct display_clock *dc); - -uint32_t dispclk_dce112_get_dfs_bypass_threshold( - struct display_clock *dc); - enum clocks_state dispclk_dce112_get_min_clocks_state( struct display_clock *base); @@ -93,16 +81,10 @@ enum clocks_state dispclk_dce112_get_required_clocks_state( struct display_clock *dc, struct state_dependent_clocks *req_clocks); -uint32_t dispclk_dce112_get_validation_clock(struct display_clock *dc); - void dispclk_dce112_set_clock( struct display_clock *base, uint32_t requested_clk_khz); -void dispclk_dce112_set_clock_state( - struct display_clock *dc, - struct display_clock_state clk_state); - bool dispclk_dce112_set_min_clocks_state( struct display_clock *base, enum clocks_state clocks_state); diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c b/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c index eedcfd6232fc..89ee8bd96979 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c @@ -90,380 +90,6 @@ static struct divider_range divider_ranges[DIVIDER_RANGE_MAX]; #define FROM_DISPLAY_CLOCK(base) \ container_of(base, struct display_clock_dce80, disp_clk) -static struct fixed32_32 get_deep_color_factor(struct min_clock_params *params) -{ - /* DeepColorFactor = IF (HDMI = True, bpp / 24, 1)*/ - struct fixed32_32 deep_color_factor = dal_fixed32_32_from_int(1); - - if (params->signal_type != SIGNAL_TYPE_HDMI_TYPE_A) - return deep_color_factor; - - switch (params->deep_color_depth) { - case COLOR_DEPTH_101010: - /*deep color ratio for 30bpp is 30/24 = 1.25*/ - deep_color_factor = dal_fixed32_32_from_fraction(30, 24); - break; - - case COLOR_DEPTH_121212: - /* deep color ratio for 36bpp is 36/24 = 1.5*/ - deep_color_factor = dal_fixed32_32_from_fraction(36, 24); - break; - - case COLOR_DEPTH_161616: - /* deep color ratio for 48bpp is 48/24 = 2.0 */ - deep_color_factor = dal_fixed32_32_from_fraction(48, 24); - break; - default: - break; - } - return deep_color_factor; -} - -static uint32_t get_scaler_efficiency(struct min_clock_params *params) -{ - uint32_t scaler_efficiency = 3; - - switch (params->scaler_efficiency) { - case V_SCALER_EFFICIENCY_LB18BPP: - case V_SCALER_EFFICIENCY_LB24BPP: - scaler_efficiency = 4; - break; - - case V_SCALER_EFFICIENCY_LB30BPP: - case V_SCALER_EFFICIENCY_LB36BPP: - scaler_efficiency = 3; - break; - - default: - break; - } - - return scaler_efficiency; -} - -static uint32_t get_actual_required_display_clk( - struct display_clock_dce80 *disp_clk, - uint32_t target_clk_khz) -{ - uint32_t disp_clk_khz = target_clk_khz; - uint32_t div = INVALID_DIVIDER; - uint32_t did = INVALID_DID; - uint32_t scaled_vco = - disp_clk->dentist_vco_freq_khz * DIVIDER_RANGE_SCALE_FACTOR; - - ASSERT(disp_clk_khz); - - if (disp_clk_khz) - div = scaled_vco / disp_clk_khz; - - did = dal_divider_range_get_did(divider_ranges, DIVIDER_RANGE_MAX, div); - - if (did != INVALID_DID) { - div = dal_divider_range_get_divider( - divider_ranges, DIVIDER_RANGE_MAX, did); - - if ((div != INVALID_DIVIDER) && - (did > DIVIDER_RANGE_01_BASE_DIVIDER_ID)) - if (disp_clk_khz > (scaled_vco / div)) - div = dal_divider_range_get_divider( - divider_ranges, DIVIDER_RANGE_MAX, - did - 1); - - if (div != INVALID_DIVIDER) - disp_clk_khz = scaled_vco / div; - - } - /* We need to add 10KHz to this value because the accuracy in VBIOS is - in 10KHz units. So we need to always round the last digit up in order - to reach the next div level.*/ - return disp_clk_khz + 10; -} - -static uint32_t get_validation_clock(struct display_clock *dc) -{ - uint32_t clk = 0; - struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc); - - switch (disp_clk->max_clks_state) { - case CLOCKS_STATE_ULTRA_LOW: - /*Currently not supported, it has 0 in table entry*/ - case CLOCKS_STATE_LOW: - clk = max_clks_by_state[CLOCKS_STATE_LOW]. - display_clk_khz; - break; - - case CLOCKS_STATE_NOMINAL: - clk = max_clks_by_state[CLOCKS_STATE_NOMINAL]. - display_clk_khz; - break; - - case CLOCKS_STATE_PERFORMANCE: - clk = max_clks_by_state[CLOCKS_STATE_PERFORMANCE]. - display_clk_khz; - break; - - case CLOCKS_STATE_INVALID: - default: - /*Invalid Clocks State*/ - BREAK_TO_DEBUGGER(); - /* just return the display engine clock for - * lowest supported state*/ - clk = max_clks_by_state[CLOCKS_STATE_LOW]. - display_clk_khz; - break; - } - return clk; -} - -static uint32_t calc_single_display_min_clks( - struct display_clock *base, - struct min_clock_params *params, - bool set_clk) -{ - struct fixed32_32 h_scale = dal_fixed32_32_from_int(1); - struct fixed32_32 v_scale = dal_fixed32_32_from_int(1); - uint32_t pix_clk_khz = params->requested_pixel_clock; - uint32_t line_total = params->timing_info.h_total; - uint32_t max_clk_khz = get_validation_clock(base); - struct fixed32_32 deep_color_factor = get_deep_color_factor(params); - uint32_t scaler_efficiency = get_scaler_efficiency(params); - struct fixed32_32 v_filter_init; - uint32_t v_filter_init_trunc; - struct fixed32_32 v_filter_init_ceil; - struct fixed32_32 src_lines_per_dst_line; - uint32_t src_wdth_rnd_to_chunks; - struct fixed32_32 scaling_coeff; - struct fixed32_32 fx_disp_clk_khz; - struct fixed32_32 fx_alt_disp_clk_khz; - uint32_t disp_clk_khz; - uint32_t alt_disp_clk_khz; - struct display_clock_dce80 *dc = FROM_DISPLAY_CLOCK(base); - - if (0 != params->dest_view.height && 0 != params->dest_view.width) { - - h_scale = dal_fixed32_32_from_fraction( - params->source_view.width, - params->dest_view.width); - v_scale = dal_fixed32_32_from_fraction( - params->source_view.height, - params->dest_view.height); - } - - v_filter_init = dal_fixed32_32_from_fraction( - params->scaling_info.v_taps, 2u); - v_filter_init = dal_fixed32_32_add(v_filter_init, - dal_fixed32_32_div_int(v_scale, 2)); - v_filter_init = dal_fixed32_32_add(v_filter_init, - dal_fixed32_32_from_fraction(15, 10)); - - v_filter_init_trunc = dal_fixed32_32_floor(v_filter_init); - - v_filter_init_ceil = dal_fixed32_32_from_fraction( - v_filter_init_trunc, 2); - v_filter_init_ceil = dal_fixed32_32_from_int( - dal_fixed32_32_ceil(v_filter_init_ceil)); - v_filter_init_ceil = dal_fixed32_32_mul_int(v_filter_init_ceil, 2); - v_filter_init_ceil = dal_fixed32_32_div_int(v_filter_init_ceil, 3); - v_filter_init_ceil = dal_fixed32_32_from_int( - dal_fixed32_32_ceil(v_filter_init_ceil)); - - src_lines_per_dst_line = dal_fixed32_32_max( - dal_fixed32_32_from_int(dal_fixed32_32_ceil(v_scale)), - v_filter_init_ceil); - - src_wdth_rnd_to_chunks = - ((params->source_view.width - 1) / 128) * 128 + 256; - - scaling_coeff = dal_fixed32_32_max( - dal_fixed32_32_from_fraction(params->scaling_info.h_taps, 4), - dal_fixed32_32_mul( - dal_fixed32_32_from_fraction( - params->scaling_info.v_taps, - scaler_efficiency), - h_scale)); - - scaling_coeff = dal_fixed32_32_max(scaling_coeff, h_scale); - - fx_disp_clk_khz = dal_fixed32_32_mul( - scaling_coeff, dal_fixed32_32_from_fraction(11, 10)); - if (0 != line_total) { - struct fixed32_32 d_clk = dal_fixed32_32_mul_int( - src_lines_per_dst_line, src_wdth_rnd_to_chunks); - d_clk = dal_fixed32_32_div_int(d_clk, line_total); - d_clk = dal_fixed32_32_mul(d_clk, - dal_fixed32_32_from_fraction(11, 10)); - fx_disp_clk_khz = dal_fixed32_32_max(fx_disp_clk_khz, d_clk); - } - - fx_disp_clk_khz = dal_fixed32_32_max(fx_disp_clk_khz, - dal_fixed32_32_mul(deep_color_factor, - dal_fixed32_32_from_fraction(11, 10))); - - fx_disp_clk_khz = dal_fixed32_32_mul_int(fx_disp_clk_khz, pix_clk_khz); - fx_disp_clk_khz = dal_fixed32_32_mul(fx_disp_clk_khz, - dal_fixed32_32_from_fraction(1005, 1000)); - - fx_alt_disp_clk_khz = scaling_coeff; - - if (0 != line_total) { - struct fixed32_32 d_clk = dal_fixed32_32_mul_int( - src_lines_per_dst_line, src_wdth_rnd_to_chunks); - d_clk = dal_fixed32_32_div_int(d_clk, line_total); - d_clk = dal_fixed32_32_mul(d_clk, - dal_fixed32_32_from_fraction(105, 100)); - fx_alt_disp_clk_khz = dal_fixed32_32_max( - fx_alt_disp_clk_khz, d_clk); - } - fx_alt_disp_clk_khz = dal_fixed32_32_max( - fx_alt_disp_clk_khz, fx_alt_disp_clk_khz); - - fx_alt_disp_clk_khz = dal_fixed32_32_mul_int( - fx_alt_disp_clk_khz, pix_clk_khz); - - /* convert to integer*/ - disp_clk_khz = dal_fixed32_32_floor(fx_disp_clk_khz); - alt_disp_clk_khz = dal_fixed32_32_floor(fx_alt_disp_clk_khz); - - if (set_clk) { /* only compensate clock if we are going to set it.*/ - disp_clk_khz = get_actual_required_display_clk( - dc, disp_clk_khz); - alt_disp_clk_khz = get_actual_required_display_clk( - dc, alt_disp_clk_khz); - } - - if ((disp_clk_khz > max_clk_khz) && (alt_disp_clk_khz <= max_clk_khz)) - disp_clk_khz = alt_disp_clk_khz; - - return disp_clk_khz; - -} - -static uint32_t calc_cursor_bw_for_min_clks(struct min_clock_params *params) -{ - - struct fixed32_32 v_scale = dal_fixed32_32_from_int(1); - struct fixed32_32 v_filter_ceiling; - struct fixed32_32 src_lines_per_dst_line; - struct fixed32_32 cursor_bw; - - /* DCE8 Mode Support and Mode Set Architecture Specification Rev 1.3 - 6.3.3 Cursor data Throughput requirement on DISPCLK - The MCIF to DCP cursor data return throughput is one pixel per DISPCLK - shared among the display heads. - If (Total Cursor Bandwidth in pixels for All heads> DISPCLK) - The mode is not supported - Cursor Bandwidth in Pixels = Cursor Width * - (SourceLinesPerDestinationLine / Line Time) - Assuming that Cursor Width = 128 - */ - /*In the hardware doc they mention an Interlace Factor - It is not used here because we have already used it when - calculating destination view*/ - if (0 != params->dest_view.height) - v_scale = dal_fixed32_32_from_fraction( - params->source_view.height, - params->dest_view.height); - - { - /*Do: Vertical Filter Init = 0.5 + VTAPS/2 + VSR/2 * Interlace Factor*/ - /*Interlace Factor is included in verticalScaleRatio*/ - struct fixed32_32 v_filter = dal_fixed32_32_add( - dal_fixed32_32_from_fraction(params->scaling_info.v_taps, 2), - dal_fixed32_32_div_int(v_scale, 2)); - /*Do : Ceiling (Vertical Filter Init, 2)/3 )*/ - v_filter_ceiling = dal_fixed32_32_div_int(v_filter, 2); - v_filter_ceiling = dal_fixed32_32_mul_int( - dal_fixed32_32_from_int(dal_fixed32_32_ceil(v_filter_ceiling)), - 2); - v_filter_ceiling = dal_fixed32_32_div_int(v_filter_ceiling, 3); - } - /*Do : MAX( CeilCeiling (VSR), Ceiling (Vertical Filter Init, 2)/3 )*/ - /*Do : SourceLinesPerDestinationLine = - * MAX( Ceiling (VSR), Ceiling (Vertical Filter Init, 2)/3 )*/ - src_lines_per_dst_line = dal_fixed32_32_max(v_scale, v_filter_ceiling); - - if ((params->requested_pixel_clock != 0) && - (params->timing_info.h_total != 0)) { - /* pixelClock is in units of KHz. Calc lineTime in us*/ - struct fixed32_32 inv_line_time = dal_fixed32_32_from_fraction( - params->requested_pixel_clock, - params->timing_info.h_total); - cursor_bw = dal_fixed32_32_mul( - dal_fixed32_32_mul_int(inv_line_time, 128), - src_lines_per_dst_line); - } - - /* convert to integer*/ - return dal_fixed32_32_floor(cursor_bw); -} - -static bool validate( - struct display_clock *dc, - struct min_clock_params *params) -{ - uint32_t max_clk_khz = get_validation_clock(dc); - uint32_t req_clk_khz; - - if (params == NULL) - return false; - - req_clk_khz = calc_single_display_min_clks(dc, params, false); - - return (req_clk_khz <= max_clk_khz); -} - -static uint32_t calculate_min_clock( - struct display_clock *dc, - uint32_t path_num, - struct min_clock_params *params) -{ - uint32_t i; - uint32_t validation_clk_khz = get_validation_clock(dc); - uint32_t min_clk_khz = validation_clk_khz; - uint32_t max_clk_khz = 0; - uint32_t total_cursor_bw = 0; - struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc); - - if (disp_clk->use_max_disp_clk) - return min_clk_khz; - - if (params != NULL) { - uint32_t disp_clk_khz = 0; - - for (i = 0; i < path_num; ++i) { - disp_clk_khz = calc_single_display_min_clks( - dc, params, true); - - /* update the max required clock found*/ - if (disp_clk_khz > max_clk_khz) - max_clk_khz = disp_clk_khz; - - disp_clk_khz = calc_cursor_bw_for_min_clks(params); - - total_cursor_bw += disp_clk_khz; - - params++; - - } - } - - max_clk_khz = (total_cursor_bw > max_clk_khz) ? total_cursor_bw : - max_clk_khz; - - min_clk_khz = max_clk_khz; - - /*"Cursor data Throughput requirement on DISPCLK is now a factor, - * need to change the code */ - ASSERT(total_cursor_bw < validation_clk_khz); - - if (min_clk_khz > validation_clk_khz) - min_clk_khz = validation_clk_khz; - else if (min_clk_khz < dc->min_display_clk_threshold_khz) - min_clk_khz = dc->min_display_clk_threshold_khz; - - return min_clk_khz; -} - static void set_clock( struct display_clock *dc, uint32_t requested_clk_khz) @@ -493,54 +119,6 @@ static void set_clock( disp_clk->cur_min_clks_state = CLOCKS_STATE_NOMINAL; } -static uint32_t get_clock(struct display_clock *dc) -{ - uint32_t disp_clock = get_validation_clock(dc); - uint32_t target_div = INVALID_DIVIDER; - uint32_t addr = mmDENTIST_DISPCLK_CNTL; - uint32_t value = 0; - uint32_t field = 0; - struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc); - - if (disp_clk->dfs_bypass_enabled && disp_clk->dfs_bypass_disp_clk) - return disp_clk->dfs_bypass_disp_clk; - - /* Read the mmDENTIST_DISPCLK_CNTL to get the currently programmed - DID DENTIST_DISPCLK_WDIVIDER.*/ - value = dm_read_reg(dc->ctx, addr); - field = get_reg_field_value( - value, DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER); - - /* Convert DENTIST_DISPCLK_WDIVIDER to actual divider*/ - target_div = dal_divider_range_get_divider( - divider_ranges, - DIVIDER_RANGE_MAX, - field); - - if (target_div != INVALID_DIVIDER) - /* Calculate the current DFS clock in KHz. - Should be okay up to 42.9 THz before overflowing.*/ - disp_clock = (DIVIDER_RANGE_SCALE_FACTOR - * disp_clk->dentist_vco_freq_khz) / target_div; - return disp_clock; -} - -static void set_clock_state( - struct display_clock *dc, - struct display_clock_state clk_state) -{ - struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc); - - disp_clk->clock_state = clk_state; -} -static struct display_clock_state get_clock_state( - struct display_clock *dc) -{ - struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc); - - return disp_clk->clock_state; -} - static enum clocks_state get_min_clocks_state(struct display_clock *dc) { struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc); @@ -818,11 +396,6 @@ static bool display_clock_integrated_info_construct( return true; } -static uint32_t get_dfs_bypass_threshold(struct display_clock *dc) -{ - return DCE80_DFS_BYPASS_THRESHOLD_KHZ; -} - static void destroy(struct display_clock **dc) { struct display_clock_dce80 *disp_clk; @@ -833,32 +406,34 @@ static void destroy(struct display_clock **dc) } static const struct display_clock_funcs funcs = { - .calculate_min_clock = calculate_min_clock, .destroy = destroy, - .get_clock = get_clock, - .get_clock_state = get_clock_state, - .get_dfs_bypass_threshold = get_dfs_bypass_threshold, .get_dp_ref_clk_frequency = get_dp_ref_clk_frequency, .get_min_clocks_state = get_min_clocks_state, .get_required_clocks_state = get_required_clocks_state, - .get_validation_clock = get_validation_clock, .set_clock = set_clock, - .set_clock_state = set_clock_state, - .set_dp_ref_clock_source = - dal_display_clock_base_set_dp_ref_clock_source, .set_min_clocks_state = set_min_clocks_state, - .store_max_clocks_state = store_max_clocks_state, - .validate = validate, + .store_max_clocks_state = store_max_clocks_state }; -static bool display_clock_construct( - struct dc_context *ctx, - struct display_clock_dce80 *disp_clk) + +struct display_clock *dal_display_clock_dce80_create( + struct dc_context *ctx) { - struct display_clock *dc_base = &disp_clk->disp_clk; + struct display_clock_dce80 *disp_clk; + struct display_clock *dc_base; - if (!dal_display_clock_construct_base(dc_base, ctx)) - return false; + disp_clk = dm_alloc(sizeof(struct display_clock_dce80)); + + if (disp_clk == NULL) + return NULL; + + dc_base = &disp_clk->disp_clk; + + dc_base->ctx = ctx; + dc_base->id = CLOCK_SOURCE_ID_DCPLL; + dc_base->min_display_clk_threshold_khz = 0; + + dc_base->cur_min_clks_state = CLOCKS_STATE_INVALID; dc_base->funcs = &funcs; /* @@ -912,21 +487,6 @@ static bool display_clock_construct( DIVIDER_RANGE_03_STEP_SIZE, DIVIDER_RANGE_03_BASE_DIVIDER_ID, DIVIDER_RANGE_MAX_DIVIDER_ID); - return true; -} - -struct display_clock *dal_display_clock_dce80_create( - struct dc_context *ctx) -{ - struct display_clock_dce80 *disp_clk; - - disp_clk = dm_alloc(sizeof(struct display_clock_dce80)); - - if (disp_clk == NULL) - return NULL; - - if (display_clock_construct(ctx, disp_clk)) - return &disp_clk->disp_clk; dm_free(disp_clk); return NULL; diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.h b/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.h index 944dd0380413..c675f1e30870 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.h +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.h @@ -48,7 +48,6 @@ struct display_clock_dce80 { * This is basically "Crystal Frequency In KHz" (XTALIN) frequency */ uint32_t dfs_bypass_disp_clk; bool use_max_disp_clk; - struct display_clock_state clock_state; }; struct display_clock *dal_display_clock_dce80_create( diff --git a/drivers/gpu/drm/amd/display/dc/gpu/display_clock.c b/drivers/gpu/drm/amd/display/dc/gpu/display_clock.c index bcc0a5132600..73d982732a67 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/display_clock.c +++ b/drivers/gpu/drm/amd/display/dc/gpu/display_clock.c @@ -26,49 +26,6 @@ #include "dm_services.h" #include "display_clock.h" -void dal_display_clock_base_set_dp_ref_clock_source( - struct display_clock *disp_clk, - enum clock_source_id clk_src) -{/*must be implemented in derived*/ - -} - -void dal_display_clock_base_set_clock_state(struct display_clock *disp_clk, - struct display_clock_state clk_state) -{ - /*Implemented only in DCE81*/ -} -struct display_clock_state dal_display_clock_base_get_clock_state( - struct display_clock *disp_clk) -{ - /*Implemented only in DCE81*/ - struct display_clock_state state = {0}; - return state; -} -uint32_t dal_display_clock_base_get_dfs_bypass_threshold( - struct display_clock *disp_clk) -{ - /*Implemented only in DCE81*/ - return 0; -} - -bool dal_display_clock_construct_base( - struct display_clock *base, - struct dc_context *ctx) -{ - base->ctx = ctx; - base->id = CLOCK_SOURCE_ID_DCPLL; - base->min_display_clk_threshold_khz = 0; - -/* Initially set current min clocks state to invalid since we - * cannot make any assumption about PPLIB's initial state. This will be updated - * by HWSS via SetMinClocksState() on first mode set prior to programming - * state dependent clocks.*/ - base->cur_min_clks_state = CLOCKS_STATE_INVALID; - - return true; -} - void dal_display_clock_destroy(struct display_clock **disp_clk) { if (!disp_clk || !*disp_clk) { @@ -81,26 +38,6 @@ void dal_display_clock_destroy(struct display_clock **disp_clk) *disp_clk = NULL; } -bool dal_display_clock_validate( - struct display_clock *disp_clk, - struct min_clock_params *params) -{ - return disp_clk->funcs->validate(disp_clk, params); -} - -uint32_t dal_display_clock_calculate_min_clock( - struct display_clock *disp_clk, - uint32_t path_num, - struct min_clock_params *params) -{ - return disp_clk->funcs->calculate_min_clock(disp_clk, path_num, params); -} - -uint32_t dal_display_clock_get_validation_clock(struct display_clock *disp_clk) -{ - return disp_clk->funcs->get_validation_clock(disp_clk); -} - void dal_display_clock_set_clock( struct display_clock *disp_clk, uint32_t requested_clock_khz) @@ -108,11 +45,6 @@ void dal_display_clock_set_clock( disp_clk->funcs->set_clock(disp_clk, requested_clock_khz); } -uint32_t dal_display_clock_get_clock(struct display_clock *disp_clk) -{ - return disp_clk->funcs->get_clock(disp_clk); -} - bool dal_display_clock_get_min_clocks_state( struct display_clock *disp_clk, enum clocks_state *clocks_state) @@ -154,35 +86,6 @@ uint32_t dal_display_clock_get_dp_ref_clk_frequency( return disp_clk->funcs->get_dp_ref_clk_frequency(disp_clk); } -/*the second parameter of "switchreferenceclock" is - * a dummy argument for all pre dce 6.0 versions*/ - -void dal_display_clock_switch_reference_clock( - struct display_clock *disp_clk, - bool use_external_ref_clk, - uint32_t requested_clk_khz) -{ - /* TODO: requires Asic Control*/ - /* - struct ac_pixel_clk_params params; - struct asic_control *ac = - dal_adapter_service_get_asic_control(disp_clk->as); - dc_service_memset(¶ms, 0, sizeof(struct ac_pixel_clk_params)); - - params.tgt_pixel_clk_khz = requested_clk_khz; - params.flags.SET_EXTERNAL_REF_DIV_SRC = use_external_ref_clk; - params.pll_id = disp_clk->id; - dal_asic_control_program_display_engine_pll(ac, ¶ms); - */ -} - -void dal_display_clock_set_dp_ref_clock_source( - struct display_clock *disp_clk, - enum clock_source_id clk_src) -{ - disp_clk->funcs->set_dp_ref_clock_source(disp_clk, clk_src); -} - void dal_display_clock_store_max_clocks_state( struct display_clock *disp_clk, enum clocks_state max_clocks_state) @@ -190,28 +93,3 @@ void dal_display_clock_store_max_clocks_state( disp_clk->funcs->store_max_clocks_state(disp_clk, max_clocks_state); } -void dal_display_clock_set_clock_state( - struct display_clock *disp_clk, - struct display_clock_state clk_state) -{ - disp_clk->funcs->set_clock_state(disp_clk, clk_state); -} - -struct display_clock_state dal_display_clock_get_clock_state( - struct display_clock *disp_clk) -{ - return disp_clk->funcs->get_clock_state(disp_clk); -} - -uint32_t dal_display_clock_get_dfs_bypass_threshold( - struct display_clock *disp_clk) -{ - return disp_clk->funcs->get_dfs_bypass_threshold(disp_clk); -} - -void dal_display_clock_invalid_clock_state( - struct display_clock *disp_clk) -{ - disp_clk->cur_min_clks_state = CLOCKS_STATE_INVALID; -} - diff --git a/drivers/gpu/drm/amd/display/dc/gpu/display_clock.h b/drivers/gpu/drm/amd/display/dc/gpu/display_clock.h index 663580d18a09..4db8442e717a 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/display_clock.h +++ b/drivers/gpu/drm/amd/display/dc/gpu/display_clock.h @@ -30,14 +30,8 @@ struct display_clock_funcs { void (*destroy)(struct display_clock **to_destroy); - bool (*validate)(struct display_clock *disp_clk, - struct min_clock_params *params); - uint32_t (*calculate_min_clock)(struct display_clock *disp_clk, - uint32_t path_num, struct min_clock_params *params); - uint32_t (*get_validation_clock)(struct display_clock *disp_clk); void (*set_clock)(struct display_clock *disp_clk, uint32_t requested_clock_khz); - uint32_t (*get_clock)(struct display_clock *disp_clk); enum clocks_state (*get_min_clocks_state)( struct display_clock *disp_clk); enum clocks_state (*get_required_clocks_state)( @@ -46,15 +40,8 @@ struct display_clock_funcs { bool (*set_min_clocks_state)(struct display_clock *disp_clk, enum clocks_state clocks_state); uint32_t (*get_dp_ref_clk_frequency)(struct display_clock *disp_clk); - void (*set_dp_ref_clock_source)(struct display_clock *disp_clk, - enum clock_source_id clk_src); void (*store_max_clocks_state)(struct display_clock *disp_clk, enum clocks_state max_clocks_state); - void (*set_clock_state)(struct display_clock *disp_clk, - struct display_clock_state clk_state); - struct display_clock_state (*get_clock_state)( - struct display_clock *disp_clk); - uint32_t (*get_dfs_bypass_threshold)(struct display_clock *disp_clk); }; @@ -66,21 +53,6 @@ struct display_clock { enum clocks_state cur_min_clks_state; }; -void dal_display_clock_base_set_dp_ref_clock_source( - struct display_clock *disp_clk, - enum clock_source_id clk_src); -struct display_clock_state dal_display_clock_base_get_clock_state( - struct display_clock *disp_clk); -uint32_t dal_display_clock_base_get_dfs_bypass_threshold( - struct display_clock *disp_clk); -void dal_display_clock_base_set_clock_state(struct display_clock *disp_clk, - struct display_clock_state clk_state); -bool dal_display_clock_construct_base( - struct display_clock *base, - struct dc_context *ctx); - -uint32_t dal_display_clock_get_validation_clock(struct display_clock *disp_clk); - void dal_display_clock_store_max_clocks_state( struct display_clock *disp_clk, enum clocks_state max_clocks_state); diff --git a/drivers/gpu/drm/amd/display/include/display_clock_interface.h b/drivers/gpu/drm/amd/display/include/display_clock_interface.h index 2006fa21f54c..ef519a284e0f 100644 --- a/drivers/gpu/drm/amd/display/include/display_clock_interface.h +++ b/drivers/gpu/drm/amd/display/include/display_clock_interface.h @@ -30,60 +30,6 @@ #include "grph_object_defs.h" #include "signal_types.h" -/* Timing related information*/ -struct dc_timing_params { - uint32_t INTERLACED:1; - uint32_t HCOUNT_BY_TWO:1; - uint32_t PIXEL_REPETITION:4; /*< values 1 to 10 supported*/ - uint32_t PREFETCH:1; - - uint32_t h_total; - uint32_t h_addressable; - uint32_t h_sync_width; -}; - -/* Scaling related information*/ -struct dc_scaling_params { - uint32_t h_overscan_right; - uint32_t h_overscan_left; - uint32_t h_taps; - uint32_t v_taps; -}; - -/* VScalerEfficiency */ -enum v_scaler_efficiency { - V_SCALER_EFFICIENCY_LB36BPP = 0, - V_SCALER_EFFICIENCY_LB30BPP = 1, - V_SCALER_EFFICIENCY_LB24BPP = 2, - V_SCALER_EFFICIENCY_LB18BPP = 3 -}; - -/* Parameters required for minimum Engine - * and minimum Display clock calculations*/ -struct min_clock_params { - uint32_t id; - uint32_t requested_pixel_clock; /* in KHz */ - uint32_t actual_pixel_clock; /* in KHz */ - struct view source_view; - struct view dest_view; - struct dc_timing_params timing_info; - struct dc_scaling_params scaling_info; - enum signal_type signal_type; - enum dc_color_depth deep_color_depth; - enum v_scaler_efficiency scaler_efficiency; - bool line_buffer_prefetch_enabled; -}; - -/* Result of Minimum System and Display clock calculations. - * Minimum System clock and Display clock, source and path to be used - * for Display clock*/ -struct minimum_clocks_calculation_result { - uint32_t min_sclk_khz; - uint32_t min_dclk_khz; - uint32_t min_mclk_khz; - uint32_t min_deep_sleep_sclk; -}; - /* Enumeration of all clocks states */ enum clocks_state { CLOCKS_STATE_INVALID = 0, @@ -110,10 +56,6 @@ struct state_dependent_clocks { uint32_t pixel_clk_khz; }; -struct display_clock_state { - uint32_t DFS_BYPASS_ACTIVE:1; -}; - struct display_clock; struct display_clock *dal_display_clock_dce112_create( @@ -126,18 +68,9 @@ struct display_clock *dal_display_clock_dce80_create( struct dc_context *ctx); void dal_display_clock_destroy(struct display_clock **to_destroy); -bool dal_display_clock_validate( - struct display_clock *disp_clk, - struct min_clock_params *params); -uint32_t dal_display_clock_calculate_min_clock( - struct display_clock *disp_clk, - uint32_t path_num, - struct min_clock_params *params); -uint32_t dal_display_clock_get_validation_clock(struct display_clock *disp_clk); void dal_display_clock_set_clock( struct display_clock *disp_clk, uint32_t requested_clock_khz); -uint32_t dal_display_clock_get_clock(struct display_clock *disp_clk); bool dal_display_clock_get_min_clocks_state( struct display_clock *disp_clk, enum clocks_state *clocks_state); @@ -150,26 +83,8 @@ bool dal_display_clock_set_min_clocks_state( enum clocks_state clocks_state); uint32_t dal_display_clock_get_dp_ref_clk_frequency( struct display_clock *disp_clk); -/*the second parameter of "switchreferenceclock" is - * a dummy argument for all pre dce 6.0 versions*/ -void dal_display_clock_switch_reference_clock( - struct display_clock *disp_clk, - bool use_external_ref_clk, - uint32_t requested_clock_khz); -void dal_display_clock_set_dp_ref_clock_source( - struct display_clock *disp_clk, - enum clock_source_id clk_src); void dal_display_clock_store_max_clocks_state( struct display_clock *disp_clk, enum clocks_state max_clocks_state); -void dal_display_clock_set_clock_state( - struct display_clock *disp_clk, - struct display_clock_state clk_state); -struct display_clock_state dal_display_clock_get_clock_state( - struct display_clock *disp_clk); -uint32_t dal_display_clock_get_dfs_bypass_threshold( - struct display_clock *disp_clk); -void dal_display_clock_invalid_clock_state( - struct display_clock *disp_clk); #endif /* __DISPLAY_CLOCK_INTERFACE_H__ */ -- cgit From 1a687574a71f187dedcab3ac6012b0889c5a4e99 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 30 Nov 2016 10:49:51 -0500 Subject: drm/amd/display: restyle display clock calls part 1 Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 4 +- .../drm/amd/display/dc/dce100/dce100_resource.c | 2 +- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 48 ++++------------------ .../drm/amd/display/dc/dce110/dce110_resource.c | 2 +- .../drm/amd/display/dc/dce112/dce112_resource.c | 2 +- .../gpu/drm/amd/display/dc/dce80/dce80_resource.c | 2 +- .../display/dc/gpu/dce112/display_clock_dce112.c | 1 - .../display/dc/gpu/dce112/display_clock_dce112.h | 1 - drivers/gpu/drm/amd/display/dc/gpu/display_clock.c | 20 --------- drivers/gpu/drm/amd/display/dc/gpu/display_clock.h | 30 -------------- drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 2 - .../amd/display/include/display_clock_interface.h | 35 ++++++++++++---- 12 files changed, 42 insertions(+), 107 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 424a7d4b8731..70dc70685471 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1224,7 +1224,9 @@ bool dc_pre_update_surfaces_to_target( if (prev_disp_clk < context->bw_results.dispclk_khz) { pplib_apply_display_requirements(core_dc, context, &context->pp_display_cfg); - core_dc->hwss.set_display_clock(context); + context->res_ctx.pool->display_clock->funcs->set_clock( + context->res_ctx.pool->display_clock, + context->bw_results.dispclk_khz * 115 / 100); core_dc->current_context->bw_results.dispclk_khz = context->bw_results.dispclk_khz; } diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 9ace6d1cca79..8f18a9403525 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -984,7 +984,7 @@ static bool construct( dce110_resource_convert_clock_state_pp_to_dc( static_clk_info.max_clocks_state); - dal_display_clock_store_max_clocks_state( + pool->base.display_clock->funcs->store_max_clocks_state( pool->base.display_clock, max_clocks_state); } { diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 1a682996b531..16ee49dba97b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -497,8 +497,8 @@ static void build_audio_output( if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT || pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { audio_output->pll_info.dp_dto_source_clock_in_khz = - dal_display_clock_get_dp_ref_clk_frequency( - pipe_ctx->dis_clk); + pipe_ctx->dis_clk->funcs->get_dp_ref_clk_frequency( + pipe_ctx->dis_clk); } audio_output->pll_info.feed_back_divider = @@ -788,39 +788,6 @@ void dce110_enable_accelerated_mode(struct core_dc *dc) bios_set_scratch_acc_mode_change(dc->ctx->dc_bios); } -/** - * Call display_engine_clock_dce80 to perform the Dclk programming. - */ -void dce110_set_display_clock(struct validate_context *context) -{ - /* Program the display engine clock. - * Check DFS bypass mode support or not. DFSbypass feature is only when - * BIOS GPU info table reports support. */ - - if (/*dal_adapter_service_is_dfs_bypass_enabled()*/ false) { - /*TODO: set_display_clock_dfs_bypass( - hws, - path_set, - context->res_ctx.pool->display_clock, - context->res_ctx.min_clocks.min_dclk_khz);*/ - } else { - /* - * TODO: need to either port work around from DAL2 function - * getActualRequiredDisplayClock or program displayclock without - * calling vbios. Currently temporily work - * around by increasing the displclk by 15 percent - */ - dal_display_clock_set_clock( - context->res_ctx.pool->display_clock, - context->bw_results.dispclk_khz * 115 / 100); - } - - - /* TODO: When changing display engine clock, DMCU WaitLoop must be - * reconfigured in order to maintain the same delays within DMCU - * programming sequences. */ -} - static uint32_t compute_pstate_blackout_duration( struct bw_fixed blackout_duration, const struct core_stream *stream) @@ -1267,8 +1234,10 @@ enum dc_status dce110_apply_ctx_to_hw( apply_min_clocks(dc, context, &clocks_state, true); if (context->bw_results.dispclk_khz - > dc->current_context->bw_results.dispclk_khz) - dc->hwss.set_display_clock(context); + > dc->current_context->bw_results.dispclk_khz) + context->res_ctx.pool->display_clock->funcs->set_clock( + context->res_ctx.pool->display_clock, + context->bw_results.dispclk_khz * 115 / 100); for (i = 0; i < context->res_ctx.pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx_old = @@ -1738,7 +1707,9 @@ static void dce110_set_bandwidth(struct core_dc *dc) program_wm_for_pipe(dc, pipe_ctx, dc->current_context); } - dc->hwss.set_display_clock(dc->current_context); + dc->current_context->res_ctx.pool->display_clock->funcs->set_clock( + dc->current_context->res_ctx.pool->display_clock, + dc->current_context->bw_results.dispclk_khz * 115 / 100); } static void dce110_program_front_end_for_pipe( @@ -1959,7 +1930,6 @@ static const struct hw_sequencer_funcs dce110_funcs = { .enable_display_power_gating = dce110_enable_display_power_gating, .power_down_front_end = dce110_power_down_fe, .pipe_control_lock = dce_pipe_control_lock, - .set_display_clock = dce110_set_display_clock, .set_displaymarks = dce110_set_displaymarks, .increase_watermarks_for_pipe = dce110_increase_watermarks_for_pipe, .set_bandwidth = dce110_set_bandwidth, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index cac3dc425039..a63112b2bd36 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -1315,7 +1315,7 @@ static bool construct( dce110_resource_convert_clock_state_pp_to_dc( static_clk_info.max_clocks_state); - dal_display_clock_store_max_clocks_state( + pool->base.display_clock->funcs->store_max_clocks_state( pool->base.display_clock, max_clocks_state); } diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 4e3273c0fa91..70616019ae47 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -1315,7 +1315,7 @@ static bool construct( dce110_resource_convert_clock_state_pp_to_dc( static_clk_info.max_clocks_state); - dal_display_clock_store_max_clocks_state( + pool->base.display_clock->funcs->store_max_clocks_state( pool->base.display_clock, max_clocks_state); } diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 3b626b7883d4..dfff2bfff13d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -978,7 +978,7 @@ static bool construct( dce80_resource_convert_clock_state_pp_to_dc( static_clk_info.max_clocks_state); - dal_display_clock_store_max_clocks_state( + pool->base.display_clock->funcs->store_max_clocks_state( pool->base.display_clock, max_clocks_state); } diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c index bf044260c0bb..665832b0718a 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c @@ -383,7 +383,6 @@ bool dal_display_clock_dce112_construct( struct display_clock *dc_base = &dc112->disp_clk_base; dc_base->ctx = ctx; - dc_base->id = CLOCK_SOURCE_ID_DCPLL; dc_base->min_display_clk_threshold_khz = 0; dc_base->cur_min_clks_state = CLOCKS_STATE_INVALID; diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h index 5ab31185d29d..47a149709d91 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h @@ -32,7 +32,6 @@ struct display_clock_dce112 { /* Max display block clocks state*/ enum clocks_state max_clks_state; bool use_max_disp_clk; - uint32_t crystal_freq_khz; uint32_t dentist_vco_freq_khz; /* Cache the status of DFS-bypass feature*/ bool dfs_bypass_enabled; diff --git a/drivers/gpu/drm/amd/display/dc/gpu/display_clock.c b/drivers/gpu/drm/amd/display/dc/gpu/display_clock.c index 73d982732a67..c70c6b25892e 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/display_clock.c +++ b/drivers/gpu/drm/amd/display/dc/gpu/display_clock.c @@ -38,13 +38,6 @@ void dal_display_clock_destroy(struct display_clock **disp_clk) *disp_clk = NULL; } -void dal_display_clock_set_clock( - struct display_clock *disp_clk, - uint32_t requested_clock_khz) -{ - disp_clk->funcs->set_clock(disp_clk, requested_clock_khz); -} - bool dal_display_clock_get_min_clocks_state( struct display_clock *disp_clk, enum clocks_state *clocks_state) @@ -80,16 +73,3 @@ bool dal_display_clock_set_min_clocks_state( return true; } -uint32_t dal_display_clock_get_dp_ref_clk_frequency( - struct display_clock *disp_clk) -{ - return disp_clk->funcs->get_dp_ref_clk_frequency(disp_clk); -} - -void dal_display_clock_store_max_clocks_state( - struct display_clock *disp_clk, - enum clocks_state max_clocks_state) -{ - disp_clk->funcs->store_max_clocks_state(disp_clk, max_clocks_state); -} - diff --git a/drivers/gpu/drm/amd/display/dc/gpu/display_clock.h b/drivers/gpu/drm/amd/display/dc/gpu/display_clock.h index 4db8442e717a..68d2ab0500a6 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/display_clock.h +++ b/drivers/gpu/drm/amd/display/dc/gpu/display_clock.h @@ -28,34 +28,4 @@ #include "include/display_clock_interface.h" -struct display_clock_funcs { - void (*destroy)(struct display_clock **to_destroy); - void (*set_clock)(struct display_clock *disp_clk, - uint32_t requested_clock_khz); - enum clocks_state (*get_min_clocks_state)( - struct display_clock *disp_clk); - enum clocks_state (*get_required_clocks_state)( - struct display_clock *disp_clk, - struct state_dependent_clocks *req_clocks); - bool (*set_min_clocks_state)(struct display_clock *disp_clk, - enum clocks_state clocks_state); - uint32_t (*get_dp_ref_clk_frequency)(struct display_clock *disp_clk); - void (*store_max_clocks_state)(struct display_clock *disp_clk, - enum clocks_state max_clocks_state); - -}; - -struct display_clock { - struct dc_context *ctx; - const struct display_clock_funcs *funcs; - uint32_t min_display_clk_threshold_khz; - enum clock_source_id id; - - enum clocks_state cur_min_clks_state; -}; -void dal_display_clock_store_max_clocks_state( - struct display_clock *disp_clk, - enum clocks_state max_clocks_state); - - #endif /* __DAL_DISPLAY_CLOCK_H__*/ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 35a556dd9054..50d499cc01a4 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -132,8 +132,6 @@ struct hw_sequencer_funcs { struct pipe_ctx *pipe_ctx, struct validate_context *context); - void (*set_display_clock)(struct validate_context *context); - void (*set_bandwidth)(struct core_dc *dc); void (*set_drr)(struct pipe_ctx **pipe_ctx, int num_pipes, diff --git a/drivers/gpu/drm/amd/display/include/display_clock_interface.h b/drivers/gpu/drm/amd/display/include/display_clock_interface.h index ef519a284e0f..f49253714b1e 100644 --- a/drivers/gpu/drm/amd/display/include/display_clock_interface.h +++ b/drivers/gpu/drm/amd/display/include/display_clock_interface.h @@ -56,7 +56,31 @@ struct state_dependent_clocks { uint32_t pixel_clk_khz; }; -struct display_clock; +struct display_clock { + struct dc_context *ctx; + const struct display_clock_funcs *funcs; + uint32_t min_display_clk_threshold_khz; + enum clock_source_id id; + + enum clocks_state cur_min_clks_state; +}; + +struct display_clock_funcs { + void (*destroy)(struct display_clock **to_destroy); + void (*set_clock)(struct display_clock *disp_clk, + uint32_t requested_clock_khz); + enum clocks_state (*get_min_clocks_state)( + struct display_clock *disp_clk); + enum clocks_state (*get_required_clocks_state)( + struct display_clock *disp_clk, + struct state_dependent_clocks *req_clocks); + bool (*set_min_clocks_state)(struct display_clock *disp_clk, + enum clocks_state clocks_state); + uint32_t (*get_dp_ref_clk_frequency)(struct display_clock *disp_clk); + void (*store_max_clocks_state)(struct display_clock *disp_clk, + enum clocks_state max_clocks_state); + +}; struct display_clock *dal_display_clock_dce112_create( struct dc_context *ctx); @@ -68,9 +92,7 @@ struct display_clock *dal_display_clock_dce80_create( struct dc_context *ctx); void dal_display_clock_destroy(struct display_clock **to_destroy); -void dal_display_clock_set_clock( - struct display_clock *disp_clk, - uint32_t requested_clock_khz); + bool dal_display_clock_get_min_clocks_state( struct display_clock *disp_clk, enum clocks_state *clocks_state); @@ -81,10 +103,5 @@ bool dal_display_clock_get_required_clocks_state( bool dal_display_clock_set_min_clocks_state( struct display_clock *disp_clk, enum clocks_state clocks_state); -uint32_t dal_display_clock_get_dp_ref_clk_frequency( - struct display_clock *disp_clk); -void dal_display_clock_store_max_clocks_state( - struct display_clock *disp_clk, - enum clocks_state max_clocks_state); #endif /* __DISPLAY_CLOCK_INTERFACE_H__ */ -- cgit From 5d6d185f32eb0cce16caff13e716d08b594a6046 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 30 Nov 2016 11:03:37 -0500 Subject: drm/amd/display: restyle display clock calls part 2 Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 11 ++-- .../drm/amd/display/dc/dce100/dce100_resource.c | 4 +- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 13 ++-- .../drm/amd/display/dc/dce110/dce110_resource.c | 4 +- .../drm/amd/display/dc/dce112/dce112_resource.c | 4 +- .../gpu/drm/amd/display/dc/dce80/dce80_resource.c | 4 +- drivers/gpu/drm/amd/display/dc/gpu/Makefile | 2 +- .../display/dc/gpu/dce110/display_clock_dce110.h | 2 +- .../display/dc/gpu/dce112/display_clock_dce112.h | 2 +- .../amd/display/dc/gpu/dce80/display_clock_dce80.h | 2 +- drivers/gpu/drm/amd/display/dc/gpu/display_clock.c | 75 ---------------------- drivers/gpu/drm/amd/display/dc/gpu/display_clock.h | 31 --------- .../amd/display/include/display_clock_interface.h | 11 ---- 13 files changed, 30 insertions(+), 135 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/dc/gpu/display_clock.c delete mode 100644 drivers/gpu/drm/amd/display/dc/gpu/display_clock.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 70a25546de1e..ab4efde2d030 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1223,12 +1223,13 @@ static enum dc_status enable_link_dp(struct pipe_ctx *pipe_ctx) if (link_settings.link_rate == max_link_rate) { cur_min_clock_state = CLOCKS_STATE_INVALID; - if (dal_display_clock_get_min_clocks_state( - pipe_ctx->dis_clk, &cur_min_clock_state)) { + if (pipe_ctx->dis_clk->funcs->get_min_clocks_state) { + cur_min_clock_state = + pipe_ctx->dis_clk->funcs->get_min_clocks_state( + pipe_ctx->dis_clk); if (cur_min_clock_state < CLOCKS_STATE_NOMINAL) - dal_display_clock_set_min_clocks_state( - pipe_ctx->dis_clk, - CLOCKS_STATE_NOMINAL); + pipe_ctx->dis_clk->funcs->set_min_clocks_state( + pipe_ctx->dis_clk, CLOCKS_STATE_NOMINAL); } else { } } diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 8f18a9403525..fa88eb163ab8 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -717,7 +717,9 @@ static void destruct(struct dce110_resource_pool *pool) } if (pool->base.display_clock != NULL) - dal_display_clock_destroy(&pool->base.display_clock); + pool->base.display_clock->funcs->destroy( + &pool->base.display_clock); + pool->base.display_clock = NULL; if (pool->base.irqs != NULL) dal_irq_service_destroy(&pool->base.irqs); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 16ee49dba97b..ca71509af74d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1099,9 +1099,11 @@ static void apply_min_clocks( if (!pre_mode_set) { /* set clock_state without verification */ - if (dal_display_clock_set_min_clocks_state( - pipe_ctx->dis_clk, *clocks_state)) + if (pipe_ctx->dis_clk->funcs->set_min_clocks_state) { + pipe_ctx->dis_clk->funcs->set_min_clocks_state( + pipe_ctx->dis_clk, *clocks_state); return; + } /* TODOFPGA */ } @@ -1114,9 +1116,10 @@ static void apply_min_clocks( req_clocks.pixel_clk_khz = get_max_pixel_clock_for_all_paths( dc, context, true); - if (dal_display_clock_get_required_clocks_state( - pipe_ctx->dis_clk, &req_clocks, clocks_state)) { - dal_display_clock_set_min_clocks_state( + if (pipe_ctx->dis_clk->funcs->get_required_clocks_state) { + *clocks_state = pipe_ctx->dis_clk->funcs->get_required_clocks_state( + pipe_ctx->dis_clk, &req_clocks); + pipe_ctx->dis_clk->funcs->set_min_clocks_state( pipe_ctx->dis_clk, *clocks_state); } else { } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index a63112b2bd36..6c713396e6ba 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -700,7 +700,9 @@ static void destruct(struct dce110_resource_pool *pool) } if (pool->base.display_clock != NULL) { - dal_display_clock_destroy(&pool->base.display_clock); + pool->base.display_clock->funcs->destroy( + &pool->base.display_clock); + pool->base.display_clock = NULL; } if (pool->base.irqs != NULL) { diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 70616019ae47..8792c4ed6e65 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -734,7 +734,9 @@ static void destruct(struct dce110_resource_pool *pool) } if (pool->base.display_clock != NULL) { - dal_display_clock_destroy(&pool->base.display_clock); + pool->base.display_clock->funcs->destroy( + &pool->base.display_clock); + pool->base.display_clock = NULL; } if (pool->base.irqs != NULL) { diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index dfff2bfff13d..1e829f805d42 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -657,7 +657,9 @@ static void destruct(struct dce110_resource_pool *pool) } if (pool->base.display_clock != NULL) { - dal_display_clock_destroy(&pool->base.display_clock); + pool->base.display_clock->funcs->destroy( + &pool->base.display_clock); + pool->base.display_clock = NULL; } if (pool->base.irqs != NULL) { diff --git a/drivers/gpu/drm/amd/display/dc/gpu/Makefile b/drivers/gpu/drm/amd/display/dc/gpu/Makefile index fd17af1ce88e..0b99a7474950 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/Makefile +++ b/drivers/gpu/drm/amd/display/dc/gpu/Makefile @@ -3,7 +3,7 @@ # It provides the control and status of HW adapter resources, # that are global for the ASIC and sharable between pipes. -GPU = display_clock.o divider_range.o +GPU = divider_range.o AMD_DAL_GPU = $(addprefix $(AMDDALPATH)/dc/gpu/,$(GPU)) diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.h b/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.h index 88b4bdd75e56..703cd656b5b0 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.h +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.h @@ -25,7 +25,7 @@ #ifndef __DAL_DISPLAY_CLOCK_DCE110_H__ #define __DAL_DISPLAY_CLOCK_DCE110_H__ -#include "gpu/display_clock.h" +#include "display_clock_interface.h" struct display_clock_dce110 { struct display_clock disp_clk_base; diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h index 47a149709d91..34afff9a00bc 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h @@ -25,7 +25,7 @@ #ifndef __DAL_DISPLAY_CLOCK_DCE112_H__ #define __DAL_DISPLAY_CLOCK_DCE112_H__ -#include "gpu/display_clock.h" +#include "display_clock_interface.h" struct display_clock_dce112 { struct display_clock disp_clk_base; diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.h b/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.h index c675f1e30870..273a5d902840 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.h +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.h @@ -25,7 +25,7 @@ #ifndef __DAL_DISPLAY_CLOCK_DCE80_H__ #define __DAL_DISPLAY_CLOCK_DCE80_H__ -#include "gpu/display_clock.h" +#include "display_clock_interface.h" struct display_clock_dce80 { struct display_clock disp_clk; diff --git a/drivers/gpu/drm/amd/display/dc/gpu/display_clock.c b/drivers/gpu/drm/amd/display/dc/gpu/display_clock.c deleted file mode 100644 index c70c6b25892e..000000000000 --- a/drivers/gpu/drm/amd/display/dc/gpu/display_clock.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" -#include "display_clock.h" - -void dal_display_clock_destroy(struct display_clock **disp_clk) -{ - if (!disp_clk || !*disp_clk) { - BREAK_TO_DEBUGGER(); - return; - } - - (*disp_clk)->funcs->destroy(disp_clk); - - *disp_clk = NULL; -} - -bool dal_display_clock_get_min_clocks_state( - struct display_clock *disp_clk, - enum clocks_state *clocks_state) -{ - if (!disp_clk->funcs->get_min_clocks_state) - return false; - - *clocks_state = disp_clk->funcs->get_min_clocks_state(disp_clk); - return true; -} - -bool dal_display_clock_get_required_clocks_state( - struct display_clock *disp_clk, - struct state_dependent_clocks *req_clocks, - enum clocks_state *clocks_state) -{ - if (!disp_clk->funcs->get_required_clocks_state) - return false; - - *clocks_state = disp_clk->funcs->get_required_clocks_state( - disp_clk, req_clocks); - return true; -} - -bool dal_display_clock_set_min_clocks_state( - struct display_clock *disp_clk, - enum clocks_state clocks_state) -{ - if (!disp_clk->funcs->set_min_clocks_state) - return false; - - disp_clk->funcs->set_min_clocks_state(disp_clk, clocks_state); - return true; -} - diff --git a/drivers/gpu/drm/amd/display/dc/gpu/display_clock.h b/drivers/gpu/drm/amd/display/dc/gpu/display_clock.h deleted file mode 100644 index 68d2ab0500a6..000000000000 --- a/drivers/gpu/drm/amd/display/dc/gpu/display_clock.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DAL_DISPLAY_CLOCK_H__ -#define __DAL_DISPLAY_CLOCK_H__ - -#include "include/display_clock_interface.h" - -#endif /* __DAL_DISPLAY_CLOCK_H__*/ diff --git a/drivers/gpu/drm/amd/display/include/display_clock_interface.h b/drivers/gpu/drm/amd/display/include/display_clock_interface.h index f49253714b1e..a46ceebe2452 100644 --- a/drivers/gpu/drm/amd/display/include/display_clock_interface.h +++ b/drivers/gpu/drm/amd/display/include/display_clock_interface.h @@ -93,15 +93,4 @@ struct display_clock *dal_display_clock_dce80_create( void dal_display_clock_destroy(struct display_clock **to_destroy); -bool dal_display_clock_get_min_clocks_state( - struct display_clock *disp_clk, - enum clocks_state *clocks_state); -bool dal_display_clock_get_required_clocks_state( - struct display_clock *disp_clk, - struct state_dependent_clocks *req_clocks, - enum clocks_state *clocks_state); -bool dal_display_clock_set_min_clocks_state( - struct display_clock *disp_clk, - enum clocks_state clocks_state); - #endif /* __DISPLAY_CLOCK_INTERFACE_H__ */ -- cgit From 3bad7c5ccfacca7a893b2960d872878d75a151d7 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 30 Nov 2016 14:26:37 -0500 Subject: drm/amd/display: remove store clock state Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dce100/dce100_resource.c | 8 +--- .../drm/amd/display/dc/dce110/dce110_resource.c | 8 +--- .../drm/amd/display/dc/dce112/dce112_resource.c | 8 +--- .../gpu/drm/amd/display/dc/dce80/dce80_resource.c | 8 +--- .../display/dc/gpu/dce110/display_clock_dce110.c | 47 +++----------------- .../display/dc/gpu/dce110/display_clock_dce110.h | 2 - .../display/dc/gpu/dce112/display_clock_dce112.c | 50 +++------------------- .../display/dc/gpu/dce112/display_clock_dce112.h | 2 - .../amd/display/dc/gpu/dce80/display_clock_dce80.c | 50 +++------------------- .../amd/display/dc/gpu/dce80/display_clock_dce80.h | 2 - .../amd/display/include/display_clock_interface.h | 5 +-- 11 files changed, 29 insertions(+), 161 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index fa88eb163ab8..446f50bb4e0a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -981,14 +981,10 @@ static bool construct( /* get static clock information for PPLIB or firmware, save * max_clock_state */ - if (dm_pp_get_static_clocks(ctx, &static_clk_info)) { - enum clocks_state max_clocks_state = + if (dm_pp_get_static_clocks(ctx, &static_clk_info)) + pool->base.display_clock->max_clks_state = dce110_resource_convert_clock_state_pp_to_dc( static_clk_info.max_clocks_state); - - pool->base.display_clock->funcs->store_max_clocks_state( - pool->base.display_clock, max_clocks_state); - } { struct irq_service_init_data init_data; init_data.ctx = dc->ctx; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 6c713396e6ba..d5d888bdf882 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -1312,15 +1312,11 @@ static bool construct( /* get static clock information for PPLIB or firmware, save * max_clock_state */ - if (dm_pp_get_static_clocks(ctx, &static_clk_info)) { - enum clocks_state max_clocks_state = + if (dm_pp_get_static_clocks(ctx, &static_clk_info)) + pool->base.display_clock->max_clks_state = dce110_resource_convert_clock_state_pp_to_dc( static_clk_info.max_clocks_state); - pool->base.display_clock->funcs->store_max_clocks_state( - pool->base.display_clock, max_clocks_state); - } - { struct irq_service_init_data init_data; init_data.ctx = dc->ctx; diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 8792c4ed6e65..9903c9a4b8a1 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -1312,15 +1312,11 @@ static bool construct( /* get static clock information for PPLIB or firmware, save * max_clock_state */ - if (dm_pp_get_static_clocks(ctx, &static_clk_info)) { - enum clocks_state max_clocks_state = + if (dm_pp_get_static_clocks(ctx, &static_clk_info)) + pool->base.display_clock->max_clks_state = dce110_resource_convert_clock_state_pp_to_dc( static_clk_info.max_clocks_state); - pool->base.display_clock->funcs->store_max_clocks_state( - pool->base.display_clock, max_clocks_state); - } - { struct irq_service_init_data init_data; init_data.ctx = dc->ctx; diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 1e829f805d42..51721d10c811 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -975,15 +975,11 @@ static bool construct( } - if (dm_pp_get_static_clocks(ctx, &static_clk_info)) { - enum clocks_state max_clocks_state = + if (dm_pp_get_static_clocks(ctx, &static_clk_info)) + pool->base.display_clock->max_clks_state = dce80_resource_convert_clock_state_pp_to_dc( static_clk_info.max_clocks_state); - pool->base.display_clock->funcs->store_max_clocks_state( - pool->base.display_clock, max_clocks_state); - } - { struct irq_service_init_data init_data; init_data.ctx = dc->ctx; diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c b/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c index cc13afa326ad..ad7ebc1b434c 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c @@ -103,38 +103,6 @@ static struct divider_range divider_ranges[DIVIDER_RANGE_MAX]; * static functions *****************************************************************************/ -/* - * store_max_clocks_state - * - * @brief - * Cache the clock state - * - * @param - * struct display_clock *base - [out] cach the state in this structure - * enum clocks_state max_clocks_state - [in] state to be stored - */ -static void store_max_clocks_state( - struct display_clock *base, - enum clocks_state max_clocks_state) -{ - struct display_clock_dce110 *dc = DCLCK110_FROM_BASE(base); - - switch (max_clocks_state) { - case CLOCKS_STATE_LOW: - case CLOCKS_STATE_NOMINAL: - case CLOCKS_STATE_PERFORMANCE: - case CLOCKS_STATE_ULTRA_LOW: - dc->max_clks_state = max_clocks_state; - break; - - case CLOCKS_STATE_INVALID: - default: - /*Invalid Clocks State!*/ - ASSERT_CRITICAL(false); - break; - } -} - static enum clocks_state get_min_clocks_state(struct display_clock *base) { return base->cur_min_clks_state; @@ -148,7 +116,7 @@ static bool set_min_clocks_state( struct dm_pp_power_level_change_request level_change_req = { DM_PP_POWER_LEVEL_INVALID}; - if (clocks_state > dc->max_clks_state) { + if (clocks_state > base->max_clks_state) { /*Requested state exceeds max supported state.*/ dm_logger_write(base->ctx->logger, LOG_WARNING, "Requested state exceeds max supported state"); @@ -349,7 +317,7 @@ static enum clocks_state get_required_clocks_state( { int32_t i; struct display_clock_dce110 *disp_clk = DCLCK110_FROM_BASE(dc); - enum clocks_state low_req_clk = disp_clk->max_clks_state; + enum clocks_state low_req_clk = dc->max_clks_state; if (!req_clocks) { /* NULL pointer*/ @@ -363,7 +331,7 @@ static enum clocks_state get_required_clocks_state( * lowest RequiredState with the lowest state that satisfies * all required clocks */ - for (i = disp_clk->max_clks_state; i >= CLOCKS_STATE_ULTRA_LOW; --i) { + for (i = dc->max_clks_state; i >= CLOCKS_STATE_ULTRA_LOW; --i) { if ((req_clocks->display_clk_khz <= max_clks_by_state[i].display_clk_khz) && (req_clocks->pixel_clk_khz <= @@ -433,7 +401,7 @@ static void set_clock( base->min_display_clk_threshold_khz); pxl_clk_params.target_pixel_clock = requested_clk_khz; - pxl_clk_params.pll_id = base->id; + pxl_clk_params.pll_id = CLOCK_SOURCE_ID_DFS; bp->funcs->program_display_engine_pll(bp, &pxl_clk_params); @@ -459,8 +427,7 @@ static const struct display_clock_funcs funcs = { .get_min_clocks_state = get_min_clocks_state, .get_required_clocks_state = get_required_clocks_state, .set_clock = set_clock, - .set_min_clocks_state = set_min_clocks_state, - .store_max_clocks_state = store_max_clocks_state + .set_min_clocks_state = set_min_clocks_state }; static bool dal_display_clock_dce110_construct( @@ -471,7 +438,6 @@ static bool dal_display_clock_dce110_construct( struct dc_bios *bp = ctx->dc_bios; dc_base->ctx = ctx; - dc_base->id = CLOCK_SOURCE_ID_DCPLL; dc_base->min_display_clk_threshold_khz = 0; dc_base->cur_min_clks_state = CLOCKS_STATE_INVALID; @@ -488,12 +454,11 @@ static bool dal_display_clock_dce110_construct( dc110->gpu_pll_ss_divider = 1000; dc110->ss_on_gpu_pll = false; - dc_base->id = CLOCK_SOURCE_ID_DFS; /* Initially set max clocks state to nominal. This should be updated by * via a pplib call to DAL IRI eventually calling a * DisplayEngineClock_Dce110::StoreMaxClocksState(). This call will come in * on PPLIB init. This is from DCE5x. in case HW wants to use mixed method.*/ - dc110->max_clks_state = CLOCKS_STATE_NOMINAL; + dc_base->max_clks_state = CLOCKS_STATE_NOMINAL; dal_divider_range_construct( ÷r_ranges[DIVIDER_RANGE_01], diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.h b/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.h index 703cd656b5b0..50b51c41b0d9 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.h +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.h @@ -29,8 +29,6 @@ struct display_clock_dce110 { struct display_clock disp_clk_base; - /* Max display block clocks state*/ - enum clocks_state max_clks_state; bool use_max_disp_clk; uint32_t dentist_vco_freq_khz; /* Cache the status of DFS-bypass feature*/ diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c index 665832b0718a..d8c8d8a1e2b3 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c @@ -72,41 +72,6 @@ enum divider_range_step_size { static struct divider_range divider_ranges[DIVIDER_RANGE_MAX]; #define dce112_DFS_BYPASS_THRESHOLD_KHZ 400000 -/***************************************************************************** - * static functions - *****************************************************************************/ - -/* - * store_max_clocks_state - * - * @brief - * Cache the clock state - * - * @param - * struct display_clock *base - [out] cach the state in this structure - * enum clocks_state max_clocks_state - [in] state to be stored - */ -void dispclk_dce112_store_max_clocks_state( - struct display_clock *base, - enum clocks_state max_clocks_state) -{ - struct display_clock_dce112 *dc = DCLCK112_FROM_BASE(base); - - switch (max_clocks_state) { - case CLOCKS_STATE_LOW: - case CLOCKS_STATE_NOMINAL: - case CLOCKS_STATE_PERFORMANCE: - case CLOCKS_STATE_ULTRA_LOW: - dc->max_clks_state = max_clocks_state; - break; - - case CLOCKS_STATE_INVALID: - default: - /*Invalid Clocks State!*/ - ASSERT_CRITICAL(false); - break; - } -} enum clocks_state dispclk_dce112_get_min_clocks_state( struct display_clock *base) @@ -122,7 +87,7 @@ bool dispclk_dce112_set_min_clocks_state( struct dm_pp_power_level_change_request level_change_req = { DM_PP_POWER_LEVEL_INVALID}; - if (clocks_state > dc->max_clks_state) { + if (clocks_state > base->max_clks_state) { /*Requested state exceeds max supported state.*/ dm_logger_write(base->ctx->logger, LOG_WARNING, "Requested state exceeds max supported state"); @@ -302,7 +267,7 @@ enum clocks_state dispclk_dce112_get_required_clocks_state( { int32_t i; struct display_clock_dce112 *disp_clk = DCLCK112_FROM_BASE(dc); - enum clocks_state low_req_clk = disp_clk->max_clks_state; + enum clocks_state low_req_clk = dc->max_clks_state; if (!req_clocks) { /* NULL pointer*/ @@ -316,7 +281,7 @@ enum clocks_state dispclk_dce112_get_required_clocks_state( * lowest RequiredState with the lowest state that satisfies * all required clocks */ - for (i = disp_clk->max_clks_state; i >= CLOCKS_STATE_ULTRA_LOW; --i) { + for (i = dc->max_clks_state; i >= CLOCKS_STATE_ULTRA_LOW; --i) { if ((req_clocks->display_clk_khz <= (disp_clk->max_clks_by_state + i)-> display_clk_khz) && @@ -333,7 +298,6 @@ void dispclk_dce112_set_clock( uint32_t requested_clk_khz) { struct bp_set_dce_clock_parameters dce_clk_params; - struct display_clock_dce112 *dc = DCLCK112_FROM_BASE(base); struct dc_bios *bp = base->ctx->dc_bios; /* Prepare to program display clock*/ @@ -345,7 +309,7 @@ void dispclk_dce112_set_clock( base->min_display_clk_threshold_khz); dce_clk_params.target_clock_frequency = requested_clk_khz; - dce_clk_params.pll_id = dc->disp_clk_base.id; + dce_clk_params.pll_id = CLOCK_SOURCE_ID_DFS; dce_clk_params.clock_type = DCECLOCK_TYPE_DISPLAY_CLOCK; bp->funcs->set_dce_clock(bp, &dce_clk_params); @@ -372,8 +336,7 @@ static const struct display_clock_funcs funcs = { .get_min_clocks_state = dispclk_dce112_get_min_clocks_state, .get_required_clocks_state = dispclk_dce112_get_required_clocks_state, .set_clock = dispclk_dce112_set_clock, - .set_min_clocks_state = dispclk_dce112_set_min_clocks_state, - .store_max_clocks_state = dispclk_dce112_store_max_clocks_state, + .set_min_clocks_state = dispclk_dce112_set_min_clocks_state }; bool dal_display_clock_dce112_construct( @@ -399,12 +362,11 @@ bool dal_display_clock_dce112_construct( dc112->gpu_pll_ss_divider = 1000; dc112->ss_on_gpu_pll = false; - dc_base->id = CLOCK_SOURCE_ID_DFS; /* Initially set max clocks state to nominal. This should be updated by * via a pplib call to DAL IRI eventually calling a * DisplayEngineClock_dce112::StoreMaxClocksState(). This call will come in * on PPLIB init. This is from DCE5x. in case HW wants to use mixed method.*/ - dc112->max_clks_state = CLOCKS_STATE_NOMINAL; + dc_base->max_clks_state = CLOCKS_STATE_NOMINAL; dc112->disp_clk_base.min_display_clk_threshold_khz = (dc112->dentist_vco_freq_khz / 62); diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h index 34afff9a00bc..398af34720f7 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h @@ -29,8 +29,6 @@ struct display_clock_dce112 { struct display_clock disp_clk_base; - /* Max display block clocks state*/ - enum clocks_state max_clks_state; bool use_max_disp_clk; uint32_t dentist_vco_freq_khz; /* Cache the status of DFS-bypass feature*/ diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c b/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c index 89ee8bd96979..b101f7de2d11 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c @@ -95,28 +95,20 @@ static void set_clock( uint32_t requested_clk_khz) { struct bp_pixel_clock_parameters pxl_clk_params; - struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc); struct dc_bios *bp = dc->ctx->dc_bios; /* Prepare to program display clock*/ memset(&pxl_clk_params, 0, sizeof(pxl_clk_params)); pxl_clk_params.target_pixel_clock = requested_clk_khz; - pxl_clk_params.pll_id = dc->id; + pxl_clk_params.pll_id = CLOCK_SOURCE_ID_DFS; bp->funcs->program_display_engine_pll(bp, &pxl_clk_params); - if (disp_clk->dfs_bypass_enabled) { - - /* Cache the fixed display clock*/ - disp_clk->dfs_bypass_disp_clk = - pxl_clk_params.dfs_bypass_display_clock; - } - /* from power down, we need mark the clock state as ClocksStateNominal * from HWReset, so when resume we will call pplib voltage regulator.*/ if (requested_clk_khz == 0) - disp_clk->cur_min_clks_state = CLOCKS_STATE_NOMINAL; + dc->cur_min_clks_state = CLOCKS_STATE_NOMINAL; } static enum clocks_state get_min_clocks_state(struct display_clock *dc) @@ -131,8 +123,7 @@ static enum clocks_state get_required_clocks_state struct state_dependent_clocks *req_clocks) { int32_t i; - struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc); - enum clocks_state low_req_clk = disp_clk->max_clks_state; + enum clocks_state low_req_clk = dc->max_clks_state; if (!req_clocks) { /* NULL pointer*/ @@ -144,7 +135,7 @@ static enum clocks_state get_required_clocks_state * lowest RequiredState with the lowest state that satisfies * all required clocks */ - for (i = disp_clk->max_clks_state; i >= CLOCKS_STATE_ULTRA_LOW; --i) { + for (i = dc->max_clks_state; i >= CLOCKS_STATE_ULTRA_LOW; --i) { if ((req_clocks->display_clk_khz <= max_clks_by_state[i].display_clk_khz) && (req_clocks->pixel_clk_khz <= @@ -158,12 +149,10 @@ static bool set_min_clocks_state( struct display_clock *dc, enum clocks_state clocks_state) { - struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc); - struct dm_pp_power_level_change_request level_change_req = { DM_PP_POWER_LEVEL_INVALID}; - if (clocks_state > disp_clk->max_clks_state) { + if (clocks_state > dc->max_clks_state) { /*Requested state exceeds max supported state.*/ dm_logger_write(dc->ctx->logger, LOG_WARNING, "Requested state exceeds max supported state"); @@ -271,28 +260,6 @@ static uint32_t get_dp_ref_clk_frequency(struct display_clock *dc) return dp_ref_clk_khz; } -static void store_max_clocks_state( - struct display_clock *dc, - enum clocks_state max_clocks_state) -{ - struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc); - - switch (max_clocks_state) { - case CLOCKS_STATE_LOW: - case CLOCKS_STATE_NOMINAL: - case CLOCKS_STATE_PERFORMANCE: - case CLOCKS_STATE_ULTRA_LOW: - disp_clk->max_clks_state = max_clocks_state; - break; - - case CLOCKS_STATE_INVALID: - default: - /*Invalid Clocks State!*/ - BREAK_TO_DEBUGGER(); - break; - } -} - static void display_clock_ss_construct( struct display_clock_dce80 *disp_clk) { @@ -411,8 +378,7 @@ static const struct display_clock_funcs funcs = { .get_min_clocks_state = get_min_clocks_state, .get_required_clocks_state = get_required_clocks_state, .set_clock = set_clock, - .set_min_clocks_state = set_min_clocks_state, - .store_max_clocks_state = store_max_clocks_state + .set_min_clocks_state = set_min_clocks_state }; @@ -430,7 +396,6 @@ struct display_clock *dal_display_clock_dce80_create( dc_base = &disp_clk->disp_clk; dc_base->ctx = ctx; - dc_base->id = CLOCK_SOURCE_ID_DCPLL; dc_base->min_display_clk_threshold_khz = 0; dc_base->cur_min_clks_state = CLOCKS_STATE_INVALID; @@ -450,12 +415,11 @@ struct display_clock *dal_display_clock_dce80_create( disp_clk->dfs_bypass_disp_clk = 0; disp_clk->use_max_disp_clk = true;/* false will hang the system! */ - disp_clk->disp_clk.id = CLOCK_SOURCE_ID_DFS; /* Initially set max clocks state to nominal. This should be updated by * via a pplib call to DAL IRI eventually calling a * DisplayEngineClock_Dce50::StoreMaxClocksState(). This call will come in * on PPLIB init. This is from DCE5x. in case HW wants to use mixed method.*/ - disp_clk->max_clks_state = CLOCKS_STATE_NOMINAL; + dc_base->max_clks_state = CLOCKS_STATE_NOMINAL; /* Initially set current min clocks state to invalid since we * cannot make any assumption about PPLIB's initial state. This will be updated * by HWSS via SetMinClocksState() on first mode set prior to programming diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.h b/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.h index 273a5d902840..1193398b5cea 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.h +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.h @@ -37,8 +37,6 @@ struct display_clock_dce80 { uint32_t gpu_pll_ss_divider; /* Flag for Enabled SS on GPU PLL*/ bool ss_on_gpu_pll; - /* Max display block clocks state*/ - enum clocks_state max_clks_state; /* Current minimum display block clocks state*/ enum clocks_state cur_min_clks_state; /* DFS-bypass feature variable diff --git a/drivers/gpu/drm/amd/display/include/display_clock_interface.h b/drivers/gpu/drm/amd/display/include/display_clock_interface.h index a46ceebe2452..bc678a59a3c1 100644 --- a/drivers/gpu/drm/amd/display/include/display_clock_interface.h +++ b/drivers/gpu/drm/amd/display/include/display_clock_interface.h @@ -60,7 +60,8 @@ struct display_clock { struct dc_context *ctx; const struct display_clock_funcs *funcs; uint32_t min_display_clk_threshold_khz; - enum clock_source_id id; + /* Max display block clocks state*/ + enum clocks_state max_clks_state; enum clocks_state cur_min_clks_state; }; @@ -77,8 +78,6 @@ struct display_clock_funcs { bool (*set_min_clocks_state)(struct display_clock *disp_clk, enum clocks_state clocks_state); uint32_t (*get_dp_ref_clk_frequency)(struct display_clock *disp_clk); - void (*store_max_clocks_state)(struct display_clock *disp_clk, - enum clocks_state max_clocks_state); }; -- cgit From 95015be8f483afbdef32f24ac666c625a1480cc1 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 30 Nov 2016 15:45:51 -0500 Subject: drm/amd/display: remove get_min_clocks_state Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 10 +---- .../display/dc/gpu/dce110/display_clock_dce110.c | 42 +++++++++++--------- .../display/dc/gpu/dce112/display_clock_dce112.c | 45 ++++++++++++---------- .../display/dc/gpu/dce112/display_clock_dce112.h | 2 +- .../amd/display/dc/gpu/dce80/display_clock_dce80.c | 30 ++++++++------- .../amd/display/include/display_clock_interface.h | 2 - 6 files changed, 67 insertions(+), 64 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index ab4efde2d030..558eeefecbff 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1208,7 +1208,6 @@ static enum dc_status enable_link_dp(struct pipe_ctx *pipe_ctx) struct core_link *link = stream->sink->link; struct dc_link_settings link_settings = {0}; enum dp_panel_mode panel_mode; - enum clocks_state cur_min_clock_state; enum dc_link_rate max_link_rate = LINK_RATE_HIGH2; /* get link settings for video mode timing */ @@ -1221,13 +1220,8 @@ static enum dc_status enable_link_dp(struct pipe_ctx *pipe_ctx) max_link_rate = LINK_RATE_HIGH3; if (link_settings.link_rate == max_link_rate) { - cur_min_clock_state = CLOCKS_STATE_INVALID; - - if (pipe_ctx->dis_clk->funcs->get_min_clocks_state) { - cur_min_clock_state = - pipe_ctx->dis_clk->funcs->get_min_clocks_state( - pipe_ctx->dis_clk); - if (cur_min_clock_state < CLOCKS_STATE_NOMINAL) + if (pipe_ctx->dis_clk->funcs->set_min_clocks_state) { + if (pipe_ctx->dis_clk->cur_min_clks_state < CLOCKS_STATE_NOMINAL) pipe_ctx->dis_clk->funcs->set_min_clocks_state( pipe_ctx->dis_clk, CLOCKS_STATE_NOMINAL); } else { diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c b/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c index ad7ebc1b434c..83860208a9c5 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c @@ -103,25 +103,19 @@ static struct divider_range divider_ranges[DIVIDER_RANGE_MAX]; * static functions *****************************************************************************/ -static enum clocks_state get_min_clocks_state(struct display_clock *base) -{ - return base->cur_min_clks_state; -} - -static bool set_min_clocks_state( - struct display_clock *base, +static bool dce110_set_min_clocks_state( + struct display_clock *dc, enum clocks_state clocks_state) { - struct display_clock_dce110 *dc = DCLCK110_FROM_BASE(base); struct dm_pp_power_level_change_request level_change_req = { DM_PP_POWER_LEVEL_INVALID}; - if (clocks_state > base->max_clks_state) { + if (clocks_state > dc->max_clks_state) { /*Requested state exceeds max supported state.*/ - dm_logger_write(base->ctx->logger, LOG_WARNING, + dm_logger_write(dc->ctx->logger, LOG_WARNING, "Requested state exceeds max supported state"); return false; - } else if (clocks_state == base->cur_min_clks_state) { + } else if (clocks_state == dc->cur_min_clks_state) { /*if we're trying to set the same state, we can just return * since nothing needs to be done*/ return true; @@ -140,17 +134,28 @@ static bool set_min_clocks_state( case CLOCKS_STATE_PERFORMANCE: level_change_req.power_level = DM_PP_POWER_LEVEL_PERFORMANCE; break; + case CLOCKS_DPM_STATE_LEVEL_4: + level_change_req.power_level = DM_PP_POWER_LEVEL_4; + break; + case CLOCKS_DPM_STATE_LEVEL_5: + level_change_req.power_level = DM_PP_POWER_LEVEL_5; + break; + case CLOCKS_DPM_STATE_LEVEL_6: + level_change_req.power_level = DM_PP_POWER_LEVEL_6; + break; + case CLOCKS_DPM_STATE_LEVEL_7: + level_change_req.power_level = DM_PP_POWER_LEVEL_7; + break; case CLOCKS_STATE_INVALID: default: - dm_logger_write(base->ctx->logger, LOG_WARNING, + dm_logger_write(dc->ctx->logger, LOG_WARNING, "Requested state invalid state"); return false; } /* get max clock state from PPLIB */ - if (dm_pp_apply_power_level_change_request( - base->ctx, &level_change_req)) - base->cur_min_clks_state = clocks_state; + if (dm_pp_apply_power_level_change_request(dc->ctx, &level_change_req)) + dc->cur_min_clks_state = clocks_state; return true; } @@ -384,7 +389,7 @@ static void psr_wait_loop(struct dc_context *ctx, unsigned int display_clk_khz) dm_write_reg(ctx, mmMASTER_COMM_CNTL_REG, masterComCntl); } -static void set_clock( +static void dce110_set_clock( struct display_clock *base, uint32_t requested_clk_khz) { @@ -424,10 +429,9 @@ static void set_clock( static const struct display_clock_funcs funcs = { .destroy = destroy, .get_dp_ref_clk_frequency = get_dp_ref_clk_frequency, - .get_min_clocks_state = get_min_clocks_state, .get_required_clocks_state = get_required_clocks_state, - .set_clock = set_clock, - .set_min_clocks_state = set_min_clocks_state + .set_clock = dce110_set_clock, + .set_min_clocks_state = dce110_set_min_clocks_state }; static bool dal_display_clock_dce110_construct( diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c index d8c8d8a1e2b3..4488497c00fa 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c @@ -73,26 +73,19 @@ static struct divider_range divider_ranges[DIVIDER_RANGE_MAX]; #define dce112_DFS_BYPASS_THRESHOLD_KHZ 400000 -enum clocks_state dispclk_dce112_get_min_clocks_state( - struct display_clock *base) -{ - return base->cur_min_clks_state; -} - -bool dispclk_dce112_set_min_clocks_state( - struct display_clock *base, +static bool dce112_set_min_clocks_state( + struct display_clock *dc, enum clocks_state clocks_state) { - struct display_clock_dce112 *dc = DCLCK112_FROM_BASE(base); struct dm_pp_power_level_change_request level_change_req = { - DM_PP_POWER_LEVEL_INVALID}; + DM_PP_POWER_LEVEL_INVALID }; - if (clocks_state > base->max_clks_state) { + if (clocks_state > dc->max_clks_state) { /*Requested state exceeds max supported state.*/ - dm_logger_write(base->ctx->logger, LOG_WARNING, + dm_logger_write(dc->ctx->logger, LOG_WARNING, "Requested state exceeds max supported state"); return false; - } else if (clocks_state == base->cur_min_clks_state) { + } else if (clocks_state == dc->cur_min_clks_state) { /*if we're trying to set the same state, we can just return * since nothing needs to be done*/ return true; @@ -111,17 +104,28 @@ bool dispclk_dce112_set_min_clocks_state( case CLOCKS_STATE_PERFORMANCE: level_change_req.power_level = DM_PP_POWER_LEVEL_PERFORMANCE; break; + case CLOCKS_DPM_STATE_LEVEL_4: + level_change_req.power_level = DM_PP_POWER_LEVEL_4; + break; + case CLOCKS_DPM_STATE_LEVEL_5: + level_change_req.power_level = DM_PP_POWER_LEVEL_5; + break; + case CLOCKS_DPM_STATE_LEVEL_6: + level_change_req.power_level = DM_PP_POWER_LEVEL_6; + break; + case CLOCKS_DPM_STATE_LEVEL_7: + level_change_req.power_level = DM_PP_POWER_LEVEL_7; + break; case CLOCKS_STATE_INVALID: default: - dm_logger_write(base->ctx->logger, LOG_WARNING, + dm_logger_write(dc->ctx->logger, LOG_WARNING, "Requested state invalid state"); return false; } /* get max clock state from PPLIB */ - if (dm_pp_apply_power_level_change_request( - base->ctx, &level_change_req)) - base->cur_min_clks_state = clocks_state; + if (dm_pp_apply_power_level_change_request(dc->ctx, &level_change_req)) + dc->cur_min_clks_state = clocks_state; return true; } @@ -293,7 +297,7 @@ enum clocks_state dispclk_dce112_get_required_clocks_state( return low_req_clk; } -void dispclk_dce112_set_clock( +void dce112_set_clock( struct display_clock *base, uint32_t requested_clk_khz) { @@ -333,10 +337,9 @@ void dispclk_dce112_set_clock( static const struct display_clock_funcs funcs = { .destroy = dispclk_dce112_destroy, .get_dp_ref_clk_frequency = get_dp_ref_clk_frequency, - .get_min_clocks_state = dispclk_dce112_get_min_clocks_state, .get_required_clocks_state = dispclk_dce112_get_required_clocks_state, - .set_clock = dispclk_dce112_set_clock, - .set_min_clocks_state = dispclk_dce112_set_min_clocks_state + .set_clock = dce112_set_clock, + .set_min_clocks_state = dce112_set_min_clocks_state }; bool dal_display_clock_dce112_construct( diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h index 398af34720f7..0246f930ac35 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h @@ -78,7 +78,7 @@ enum clocks_state dispclk_dce112_get_required_clocks_state( struct display_clock *dc, struct state_dependent_clocks *req_clocks); -void dispclk_dce112_set_clock( +void dce112_set_clock( struct display_clock *base, uint32_t requested_clk_khz); diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c b/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c index b101f7de2d11..6057042739bf 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c @@ -90,7 +90,7 @@ static struct divider_range divider_ranges[DIVIDER_RANGE_MAX]; #define FROM_DISPLAY_CLOCK(base) \ container_of(base, struct display_clock_dce80, disp_clk) -static void set_clock( +static void dce80_set_clock( struct display_clock *dc, uint32_t requested_clk_khz) { @@ -111,13 +111,6 @@ static void set_clock( dc->cur_min_clks_state = CLOCKS_STATE_NOMINAL; } -static enum clocks_state get_min_clocks_state(struct display_clock *dc) -{ - struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc); - - return disp_clk->cur_min_clks_state; -} - static enum clocks_state get_required_clocks_state (struct display_clock *dc, struct state_dependent_clocks *req_clocks) @@ -145,12 +138,12 @@ static enum clocks_state get_required_clocks_state return low_req_clk; } -static bool set_min_clocks_state( +static bool dce80_set_min_clocks_state( struct display_clock *dc, enum clocks_state clocks_state) { struct dm_pp_power_level_change_request level_change_req = { - DM_PP_POWER_LEVEL_INVALID}; + DM_PP_POWER_LEVEL_INVALID }; if (clocks_state > dc->max_clks_state) { /*Requested state exceeds max supported state.*/ @@ -176,6 +169,18 @@ static bool set_min_clocks_state( case CLOCKS_STATE_PERFORMANCE: level_change_req.power_level = DM_PP_POWER_LEVEL_PERFORMANCE; break; + case CLOCKS_DPM_STATE_LEVEL_4: + level_change_req.power_level = DM_PP_POWER_LEVEL_4; + break; + case CLOCKS_DPM_STATE_LEVEL_5: + level_change_req.power_level = DM_PP_POWER_LEVEL_5; + break; + case CLOCKS_DPM_STATE_LEVEL_6: + level_change_req.power_level = DM_PP_POWER_LEVEL_6; + break; + case CLOCKS_DPM_STATE_LEVEL_7: + level_change_req.power_level = DM_PP_POWER_LEVEL_7; + break; case CLOCKS_STATE_INVALID: default: dm_logger_write(dc->ctx->logger, LOG_WARNING, @@ -375,10 +380,9 @@ static void destroy(struct display_clock **dc) static const struct display_clock_funcs funcs = { .destroy = destroy, .get_dp_ref_clk_frequency = get_dp_ref_clk_frequency, - .get_min_clocks_state = get_min_clocks_state, .get_required_clocks_state = get_required_clocks_state, - .set_clock = set_clock, - .set_min_clocks_state = set_min_clocks_state + .set_clock = dce80_set_clock, + .set_min_clocks_state = dce80_set_min_clocks_state }; diff --git a/drivers/gpu/drm/amd/display/include/display_clock_interface.h b/drivers/gpu/drm/amd/display/include/display_clock_interface.h index bc678a59a3c1..f2deafbd8b12 100644 --- a/drivers/gpu/drm/amd/display/include/display_clock_interface.h +++ b/drivers/gpu/drm/amd/display/include/display_clock_interface.h @@ -70,8 +70,6 @@ struct display_clock_funcs { void (*destroy)(struct display_clock **to_destroy); void (*set_clock)(struct display_clock *disp_clk, uint32_t requested_clock_khz); - enum clocks_state (*get_min_clocks_state)( - struct display_clock *disp_clk); enum clocks_state (*get_required_clocks_state)( struct display_clock *disp_clk, struct state_dependent_clocks *req_clocks); -- cgit From e9c58bb439bce021da205df09057fe6908ff54c5 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 30 Nov 2016 16:07:50 -0500 Subject: drm/amd/display: remove clocks_state enum Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 4 +- .../drm/amd/display/dc/dce100/dce100_resource.c | 3 +- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 4 +- .../drm/amd/display/dc/dce110/dce110_resource.c | 44 +-------------- .../drm/amd/display/dc/dce110/dce110_resource.h | 3 - .../drm/amd/display/dc/dce112/dce112_resource.c | 3 +- .../gpu/drm/amd/display/dc/dce80/dce80_resource.c | 24 ++++---- .../display/dc/gpu/dce110/display_clock_dce110.c | 62 +++++---------------- .../display/dc/gpu/dce112/display_clock_dce112.c | 62 +++++---------------- .../display/dc/gpu/dce112/display_clock_dce112.h | 8 +-- .../amd/display/dc/gpu/dce80/display_clock_dce80.c | 64 ++++++---------------- .../amd/display/dc/gpu/dce80/display_clock_dce80.h | 2 +- .../amd/display/include/display_clock_interface.h | 28 ++-------- 13 files changed, 75 insertions(+), 236 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 558eeefecbff..47f22d46c0ca 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1221,9 +1221,9 @@ static enum dc_status enable_link_dp(struct pipe_ctx *pipe_ctx) if (link_settings.link_rate == max_link_rate) { if (pipe_ctx->dis_clk->funcs->set_min_clocks_state) { - if (pipe_ctx->dis_clk->cur_min_clks_state < CLOCKS_STATE_NOMINAL) + if (pipe_ctx->dis_clk->cur_min_clks_state < DM_PP_CLOCKS_STATE_NOMINAL) pipe_ctx->dis_clk->funcs->set_min_clocks_state( - pipe_ctx->dis_clk, CLOCKS_STATE_NOMINAL); + pipe_ctx->dis_clk, DM_PP_CLOCKS_STATE_NOMINAL); } else { } } diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 446f50bb4e0a..5716ce1e58f4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -983,8 +983,7 @@ static bool construct( */ if (dm_pp_get_static_clocks(ctx, &static_clk_info)) pool->base.display_clock->max_clks_state = - dce110_resource_convert_clock_state_pp_to_dc( - static_clk_info.max_clocks_state); + static_clk_info.max_clocks_state; { struct irq_service_init_data init_data; init_data.ctx = dc->ctx; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index ca71509af74d..6ad23f327631 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1084,7 +1084,7 @@ static uint32_t get_max_pixel_clock_for_all_paths( static void apply_min_clocks( struct core_dc *dc, struct validate_context *context, - enum clocks_state *clocks_state, + enum dm_pp_clocks_state *clocks_state, bool pre_mode_set) { struct state_dependent_clocks req_clocks = {0}; @@ -1193,7 +1193,7 @@ enum dc_status dce110_apply_ctx_to_hw( enum dc_status status; int i; bool programmed_audio_dto = false; - enum clocks_state clocks_state = CLOCKS_STATE_INVALID; + enum dm_pp_clocks_state clocks_state = DM_PP_CLOCKS_STATE_INVALID; /* Reset old context */ /* look up the targets that have been removed since last commit */ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index d5d888bdf882..8682c8b2a547 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -1188,47 +1188,6 @@ static void bw_calcs_data_update_from_pplib(struct core_dc *dc) 1000); } -enum clocks_state dce110_resource_convert_clock_state_pp_to_dc( - enum dm_pp_clocks_state pp_clock_state) -{ - enum clocks_state dc_clocks_state = CLOCKS_STATE_INVALID; - - switch (pp_clock_state) { - case DM_PP_CLOCKS_STATE_INVALID: - dc_clocks_state = CLOCKS_STATE_INVALID; - break; - case DM_PP_CLOCKS_STATE_ULTRA_LOW: - dc_clocks_state = CLOCKS_STATE_ULTRA_LOW; - break; - case DM_PP_CLOCKS_STATE_LOW: - dc_clocks_state = CLOCKS_STATE_LOW; - break; - case DM_PP_CLOCKS_STATE_NOMINAL: - dc_clocks_state = CLOCKS_STATE_NOMINAL; - break; - case DM_PP_CLOCKS_STATE_PERFORMANCE: - dc_clocks_state = CLOCKS_STATE_PERFORMANCE; - break; - case DM_PP_CLOCKS_DPM_STATE_LEVEL_4: - dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_4; - break; - case DM_PP_CLOCKS_DPM_STATE_LEVEL_5: - dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_5; - break; - case DM_PP_CLOCKS_DPM_STATE_LEVEL_6: - dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_6; - break; - case DM_PP_CLOCKS_DPM_STATE_LEVEL_7: - dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_7; - break; - default: - dc_clocks_state = CLOCKS_STATE_INVALID; - break; - } - - return dc_clocks_state; -} - const struct resource_caps *dce110_resource_cap( struct hw_asic_id *asic_id) { @@ -1314,8 +1273,7 @@ static bool construct( */ if (dm_pp_get_static_clocks(ctx, &static_clk_info)) pool->base.display_clock->max_clks_state = - dce110_resource_convert_clock_state_pp_to_dc( - static_clk_info.max_clocks_state); + static_clk_info.max_clocks_state; { struct irq_service_init_data init_data; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.h index 535623aa0052..0c357fdfa8bc 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.h @@ -40,9 +40,6 @@ struct dce110_resource_pool { enum dc_status dce110_resource_build_pipe_hw_param(struct pipe_ctx *pipe_ctx); -enum clocks_state dce110_resource_convert_clock_state_pp_to_dc( - enum dm_pp_clocks_state pp_clock_state); - void dce110_resource_build_bit_depth_reduction_params( const struct core_stream *stream, struct bit_depth_reduction_params *fmt_bit_depth); diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 9903c9a4b8a1..c50a215172b7 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -1314,8 +1314,7 @@ static bool construct( */ if (dm_pp_get_static_clocks(ctx, &static_clk_info)) pool->base.display_clock->max_clks_state = - dce110_resource_convert_clock_state_pp_to_dc( - static_clk_info.max_clocks_state); + static_clk_info.max_clocks_state; { struct irq_service_init_data init_data; diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 51721d10c811..1d2a31e34617 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -857,41 +857,41 @@ static const struct resource_funcs dce80_res_pool_funcs = { .validate_bandwidth = dce80_validate_bandwidth }; -static enum clocks_state dce80_resource_convert_clock_state_pp_to_dc( +static enum dm_pp_clocks_state dce80_resource_convert_clock_state_pp_to_dc( enum dm_pp_clocks_state pp_clock_state) { - enum clocks_state dc_clocks_state = CLOCKS_STATE_INVALID; + enum dm_pp_clocks_state dc_clocks_state = DM_PP_CLOCKS_STATE_INVALID; switch (pp_clock_state) { case DM_PP_CLOCKS_STATE_INVALID: - dc_clocks_state = CLOCKS_STATE_INVALID; + dc_clocks_state = DM_PP_CLOCKS_STATE_INVALID; break; case DM_PP_CLOCKS_STATE_ULTRA_LOW: - dc_clocks_state = CLOCKS_STATE_ULTRA_LOW; + dc_clocks_state = DM_PP_CLOCKS_STATE_ULTRA_LOW; break; case DM_PP_CLOCKS_STATE_LOW: - dc_clocks_state = CLOCKS_STATE_LOW; + dc_clocks_state = DM_PP_CLOCKS_STATE_LOW; break; case DM_PP_CLOCKS_STATE_NOMINAL: - dc_clocks_state = CLOCKS_STATE_NOMINAL; + dc_clocks_state = DM_PP_CLOCKS_STATE_NOMINAL; break; case DM_PP_CLOCKS_STATE_PERFORMANCE: - dc_clocks_state = CLOCKS_STATE_PERFORMANCE; + dc_clocks_state = DM_PP_CLOCKS_STATE_PERFORMANCE; break; case DM_PP_CLOCKS_DPM_STATE_LEVEL_4: - dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_4; + dc_clocks_state = DM_PP_CLOCKS_DPM_STATE_LEVEL_4; break; case DM_PP_CLOCKS_DPM_STATE_LEVEL_5: - dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_5; + dc_clocks_state = DM_PP_CLOCKS_DPM_STATE_LEVEL_5; break; case DM_PP_CLOCKS_DPM_STATE_LEVEL_6: - dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_6; + dc_clocks_state = DM_PP_CLOCKS_DPM_STATE_LEVEL_6; break; case DM_PP_CLOCKS_DPM_STATE_LEVEL_7: - dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_7; + dc_clocks_state = DM_PP_CLOCKS_DPM_STATE_LEVEL_7; break; default: - dc_clocks_state = CLOCKS_STATE_INVALID; + dc_clocks_state = DM_PP_CLOCKS_STATE_INVALID; break; } diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c b/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c index 83860208a9c5..9dabaac2c550 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c @@ -105,10 +105,10 @@ static struct divider_range divider_ranges[DIVIDER_RANGE_MAX]; static bool dce110_set_min_clocks_state( struct display_clock *dc, - enum clocks_state clocks_state) + enum dm_pp_clocks_state clocks_state) { struct dm_pp_power_level_change_request level_change_req = { - DM_PP_POWER_LEVEL_INVALID}; + clocks_state }; if (clocks_state > dc->max_clks_state) { /*Requested state exceeds max supported state.*/ @@ -121,38 +121,6 @@ static bool dce110_set_min_clocks_state( return true; } - switch (clocks_state) { - case CLOCKS_STATE_ULTRA_LOW: - level_change_req.power_level = DM_PP_POWER_LEVEL_ULTRA_LOW; - break; - case CLOCKS_STATE_LOW: - level_change_req.power_level = DM_PP_POWER_LEVEL_LOW; - break; - case CLOCKS_STATE_NOMINAL: - level_change_req.power_level = DM_PP_POWER_LEVEL_NOMINAL; - break; - case CLOCKS_STATE_PERFORMANCE: - level_change_req.power_level = DM_PP_POWER_LEVEL_PERFORMANCE; - break; - case CLOCKS_DPM_STATE_LEVEL_4: - level_change_req.power_level = DM_PP_POWER_LEVEL_4; - break; - case CLOCKS_DPM_STATE_LEVEL_5: - level_change_req.power_level = DM_PP_POWER_LEVEL_5; - break; - case CLOCKS_DPM_STATE_LEVEL_6: - level_change_req.power_level = DM_PP_POWER_LEVEL_6; - break; - case CLOCKS_DPM_STATE_LEVEL_7: - level_change_req.power_level = DM_PP_POWER_LEVEL_7; - break; - case CLOCKS_STATE_INVALID: - default: - dm_logger_write(dc->ctx->logger, LOG_WARNING, - "Requested state invalid state"); - return false; - } - /* get max clock state from PPLIB */ if (dm_pp_apply_power_level_change_request(dc->ctx, &level_change_req)) dc->cur_min_clks_state = clocks_state; @@ -274,27 +242,27 @@ static bool display_clock_integrated_info_construct( /*update the maximum display clock for each power state*/ for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) { - enum clocks_state clk_state = CLOCKS_STATE_INVALID; + enum dm_pp_clocks_state clk_state = DM_PP_CLOCKS_STATE_INVALID; switch (i) { case 0: - clk_state = CLOCKS_STATE_ULTRA_LOW; + clk_state = DM_PP_CLOCKS_STATE_ULTRA_LOW; break; case 1: - clk_state = CLOCKS_STATE_LOW; + clk_state = DM_PP_CLOCKS_STATE_LOW; break; case 2: - clk_state = CLOCKS_STATE_NOMINAL; + clk_state = DM_PP_CLOCKS_STATE_NOMINAL; break; case 3: - clk_state = CLOCKS_STATE_PERFORMANCE; + clk_state = DM_PP_CLOCKS_STATE_PERFORMANCE; break; default: - clk_state = CLOCKS_STATE_INVALID; + clk_state = DM_PP_CLOCKS_STATE_INVALID; break; } @@ -316,27 +284,27 @@ static bool display_clock_integrated_info_construct( return true; } -static enum clocks_state get_required_clocks_state( +static enum dm_pp_clocks_state get_required_clocks_state( struct display_clock *dc, struct state_dependent_clocks *req_clocks) { int32_t i; struct display_clock_dce110 *disp_clk = DCLCK110_FROM_BASE(dc); - enum clocks_state low_req_clk = dc->max_clks_state; + enum dm_pp_clocks_state low_req_clk = dc->max_clks_state; if (!req_clocks) { /* NULL pointer*/ dm_logger_write(dc->ctx->logger, LOG_WARNING, "%s: Invalid parameter", __func__); - return CLOCKS_STATE_INVALID; + return DM_PP_CLOCKS_STATE_INVALID; } /* Iterate from highest supported to lowest valid state, and update * lowest RequiredState with the lowest state that satisfies * all required clocks */ - for (i = dc->max_clks_state; i >= CLOCKS_STATE_ULTRA_LOW; --i) { + for (i = dc->max_clks_state; i >= DM_PP_CLOCKS_STATE_ULTRA_LOW; --i) { if ((req_clocks->display_clk_khz <= max_clks_by_state[i].display_clk_khz) && (req_clocks->pixel_clk_khz <= @@ -420,7 +388,7 @@ static void dce110_set_clock( /* from power down, we need mark the clock state as ClocksStateNominal * from HWReset, so when resume we will call pplib voltage regulator.*/ if (requested_clk_khz == 0) - base->cur_min_clks_state = CLOCKS_STATE_NOMINAL; + base->cur_min_clks_state = DM_PP_CLOCKS_STATE_NOMINAL; psr_wait_loop(base->ctx, requested_clk_khz); } @@ -444,7 +412,7 @@ static bool dal_display_clock_dce110_construct( dc_base->ctx = ctx; dc_base->min_display_clk_threshold_khz = 0; - dc_base->cur_min_clks_state = CLOCKS_STATE_INVALID; + dc_base->cur_min_clks_state = DM_PP_CLOCKS_STATE_INVALID; dc_base->funcs = &funcs; @@ -462,7 +430,7 @@ static bool dal_display_clock_dce110_construct( * via a pplib call to DAL IRI eventually calling a * DisplayEngineClock_Dce110::StoreMaxClocksState(). This call will come in * on PPLIB init. This is from DCE5x. in case HW wants to use mixed method.*/ - dc_base->max_clks_state = CLOCKS_STATE_NOMINAL; + dc_base->max_clks_state = DM_PP_CLOCKS_STATE_NOMINAL; dal_divider_range_construct( ÷r_ranges[DIVIDER_RANGE_01], diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c index 4488497c00fa..930548bdd8b2 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c @@ -75,10 +75,10 @@ static struct divider_range divider_ranges[DIVIDER_RANGE_MAX]; static bool dce112_set_min_clocks_state( struct display_clock *dc, - enum clocks_state clocks_state) + enum dm_pp_clocks_state clocks_state) { struct dm_pp_power_level_change_request level_change_req = { - DM_PP_POWER_LEVEL_INVALID }; + clocks_state }; if (clocks_state > dc->max_clks_state) { /*Requested state exceeds max supported state.*/ @@ -91,38 +91,6 @@ static bool dce112_set_min_clocks_state( return true; } - switch (clocks_state) { - case CLOCKS_STATE_ULTRA_LOW: - level_change_req.power_level = DM_PP_POWER_LEVEL_ULTRA_LOW; - break; - case CLOCKS_STATE_LOW: - level_change_req.power_level = DM_PP_POWER_LEVEL_LOW; - break; - case CLOCKS_STATE_NOMINAL: - level_change_req.power_level = DM_PP_POWER_LEVEL_NOMINAL; - break; - case CLOCKS_STATE_PERFORMANCE: - level_change_req.power_level = DM_PP_POWER_LEVEL_PERFORMANCE; - break; - case CLOCKS_DPM_STATE_LEVEL_4: - level_change_req.power_level = DM_PP_POWER_LEVEL_4; - break; - case CLOCKS_DPM_STATE_LEVEL_5: - level_change_req.power_level = DM_PP_POWER_LEVEL_5; - break; - case CLOCKS_DPM_STATE_LEVEL_6: - level_change_req.power_level = DM_PP_POWER_LEVEL_6; - break; - case CLOCKS_DPM_STATE_LEVEL_7: - level_change_req.power_level = DM_PP_POWER_LEVEL_7; - break; - case CLOCKS_STATE_INVALID: - default: - dm_logger_write(dc->ctx->logger, LOG_WARNING, - "Requested state invalid state"); - return false; - } - /* get max clock state from PPLIB */ if (dm_pp_apply_power_level_change_request(dc->ctx, &level_change_req)) dc->cur_min_clks_state = clocks_state; @@ -229,27 +197,27 @@ static bool display_clock_integrated_info_construct( /*update the maximum display clock for each power state*/ for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) { - enum clocks_state clk_state = CLOCKS_STATE_INVALID; + enum dm_pp_clocks_state clk_state = DM_PP_CLOCKS_STATE_INVALID; switch (i) { case 0: - clk_state = CLOCKS_STATE_ULTRA_LOW; + clk_state = DM_PP_CLOCKS_STATE_ULTRA_LOW; break; case 1: - clk_state = CLOCKS_STATE_LOW; + clk_state = DM_PP_CLOCKS_STATE_LOW; break; case 2: - clk_state = CLOCKS_STATE_NOMINAL; + clk_state = DM_PP_CLOCKS_STATE_NOMINAL; break; case 3: - clk_state = CLOCKS_STATE_PERFORMANCE; + clk_state = DM_PP_CLOCKS_STATE_PERFORMANCE; break; default: - clk_state = CLOCKS_STATE_INVALID; + clk_state = DM_PP_CLOCKS_STATE_INVALID; break; } @@ -265,27 +233,27 @@ static bool display_clock_integrated_info_construct( return true; } -enum clocks_state dispclk_dce112_get_required_clocks_state( +enum dm_pp_clocks_state dispclk_dce112_get_required_clocks_state( struct display_clock *dc, struct state_dependent_clocks *req_clocks) { int32_t i; struct display_clock_dce112 *disp_clk = DCLCK112_FROM_BASE(dc); - enum clocks_state low_req_clk = dc->max_clks_state; + enum dm_pp_clocks_state low_req_clk = dc->max_clks_state; if (!req_clocks) { /* NULL pointer*/ dm_logger_write(dc->ctx->logger, LOG_WARNING, "%s: Invalid parameter", __func__); - return CLOCKS_STATE_INVALID; + return DM_PP_CLOCKS_STATE_INVALID; } /* Iterate from highest supported to lowest valid state, and update * lowest RequiredState with the lowest state that satisfies * all required clocks */ - for (i = dc->max_clks_state; i >= CLOCKS_STATE_ULTRA_LOW; --i) { + for (i = dc->max_clks_state; i >= DM_PP_CLOCKS_STATE_ULTRA_LOW; --i) { if ((req_clocks->display_clk_khz <= (disp_clk->max_clks_by_state + i)-> display_clk_khz) && @@ -321,7 +289,7 @@ void dce112_set_clock( /* from power down, we need mark the clock state as ClocksStateNominal * from HWReset, so when resume we will call pplib voltage regulator.*/ if (requested_clk_khz == 0) - base->cur_min_clks_state = CLOCKS_STATE_NOMINAL; + base->cur_min_clks_state = DM_PP_CLOCKS_STATE_NOMINAL; /*Program DP ref Clock*/ /*VBIOS will determine DPREFCLK frequency, so we don't set it*/ @@ -351,7 +319,7 @@ bool dal_display_clock_dce112_construct( dc_base->ctx = ctx; dc_base->min_display_clk_threshold_khz = 0; - dc_base->cur_min_clks_state = CLOCKS_STATE_INVALID; + dc_base->cur_min_clks_state = DM_PP_CLOCKS_STATE_INVALID; dc_base->funcs = &funcs; @@ -369,7 +337,7 @@ bool dal_display_clock_dce112_construct( * via a pplib call to DAL IRI eventually calling a * DisplayEngineClock_dce112::StoreMaxClocksState(). This call will come in * on PPLIB init. This is from DCE5x. in case HW wants to use mixed method.*/ - dc_base->max_clks_state = CLOCKS_STATE_NOMINAL; + dc_base->max_clks_state = DM_PP_CLOCKS_STATE_NOMINAL; dc112->disp_clk_base.min_display_clk_threshold_khz = (dc112->dentist_vco_freq_khz / 62); diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h index 0246f930ac35..b750bb1766bd 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h @@ -71,10 +71,10 @@ bool dal_display_clock_dce112_construct( void dispclk_dce112_destroy(struct display_clock **base); -enum clocks_state dispclk_dce112_get_min_clocks_state( +enum dm_pp_clocks_state dispclk_dce112_get_min_clocks_state( struct display_clock *base); -enum clocks_state dispclk_dce112_get_required_clocks_state( +enum dm_pp_clocks_state dispclk_dce112_get_required_clocks_state( struct display_clock *dc, struct state_dependent_clocks *req_clocks); @@ -84,10 +84,10 @@ void dce112_set_clock( bool dispclk_dce112_set_min_clocks_state( struct display_clock *base, - enum clocks_state clocks_state); + enum dm_pp_clocks_state clocks_state); void dispclk_dce112_store_max_clocks_state( struct display_clock *base, - enum clocks_state max_clocks_state); + enum dm_pp_clocks_state max_clocks_state); #endif /* __DAL_DISPLAY_CLOCK_DCE112_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c b/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c index 6057042739bf..9d7cb2cb161c 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c @@ -108,27 +108,27 @@ static void dce80_set_clock( /* from power down, we need mark the clock state as ClocksStateNominal * from HWReset, so when resume we will call pplib voltage regulator.*/ if (requested_clk_khz == 0) - dc->cur_min_clks_state = CLOCKS_STATE_NOMINAL; + dc->cur_min_clks_state = DM_PP_CLOCKS_STATE_NOMINAL; } -static enum clocks_state get_required_clocks_state +static enum dm_pp_clocks_state get_required_clocks_state (struct display_clock *dc, struct state_dependent_clocks *req_clocks) { int32_t i; - enum clocks_state low_req_clk = dc->max_clks_state; + enum dm_pp_clocks_state low_req_clk = dc->max_clks_state; if (!req_clocks) { /* NULL pointer*/ BREAK_TO_DEBUGGER(); - return CLOCKS_STATE_INVALID; + return DM_PP_CLOCKS_STATE_INVALID; } /* Iterate from highest supported to lowest valid state, and update * lowest RequiredState with the lowest state that satisfies * all required clocks */ - for (i = dc->max_clks_state; i >= CLOCKS_STATE_ULTRA_LOW; --i) { + for (i = dc->max_clks_state; i >= DM_PP_CLOCKS_STATE_ULTRA_LOW; --i) { if ((req_clocks->display_clk_khz <= max_clks_by_state[i].display_clk_khz) && (req_clocks->pixel_clk_khz <= @@ -140,10 +140,10 @@ static enum clocks_state get_required_clocks_state static bool dce80_set_min_clocks_state( struct display_clock *dc, - enum clocks_state clocks_state) + enum dm_pp_clocks_state clocks_state) { struct dm_pp_power_level_change_request level_change_req = { - DM_PP_POWER_LEVEL_INVALID }; + clocks_state }; if (clocks_state > dc->max_clks_state) { /*Requested state exceeds max supported state.*/ @@ -156,38 +156,6 @@ static bool dce80_set_min_clocks_state( return true; } - switch (clocks_state) { - case CLOCKS_STATE_ULTRA_LOW: - level_change_req.power_level = DM_PP_POWER_LEVEL_ULTRA_LOW; - break; - case CLOCKS_STATE_LOW: - level_change_req.power_level = DM_PP_POWER_LEVEL_LOW; - break; - case CLOCKS_STATE_NOMINAL: - level_change_req.power_level = DM_PP_POWER_LEVEL_NOMINAL; - break; - case CLOCKS_STATE_PERFORMANCE: - level_change_req.power_level = DM_PP_POWER_LEVEL_PERFORMANCE; - break; - case CLOCKS_DPM_STATE_LEVEL_4: - level_change_req.power_level = DM_PP_POWER_LEVEL_4; - break; - case CLOCKS_DPM_STATE_LEVEL_5: - level_change_req.power_level = DM_PP_POWER_LEVEL_5; - break; - case CLOCKS_DPM_STATE_LEVEL_6: - level_change_req.power_level = DM_PP_POWER_LEVEL_6; - break; - case CLOCKS_DPM_STATE_LEVEL_7: - level_change_req.power_level = DM_PP_POWER_LEVEL_7; - break; - case CLOCKS_STATE_INVALID: - default: - dm_logger_write(dc->ctx->logger, LOG_WARNING, - "Requested state invalid state"); - return false; - } - /* get max clock state from PPLIB */ if (dm_pp_apply_power_level_change_request(dc->ctx, &level_change_req)) dc->cur_min_clks_state = clocks_state; @@ -326,27 +294,27 @@ static bool display_clock_integrated_info_construct( /*update the maximum display clock for each power state*/ for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) { - enum clocks_state clk_state = CLOCKS_STATE_INVALID; + enum dm_pp_clocks_state clk_state = DM_PP_CLOCKS_STATE_INVALID; switch (i) { case 0: - clk_state = CLOCKS_STATE_ULTRA_LOW; + clk_state = DM_PP_CLOCKS_STATE_ULTRA_LOW; break; case 1: - clk_state = CLOCKS_STATE_LOW; + clk_state = DM_PP_CLOCKS_STATE_LOW; break; case 2: - clk_state = CLOCKS_STATE_NOMINAL; + clk_state = DM_PP_CLOCKS_STATE_NOMINAL; break; case 3: - clk_state = CLOCKS_STATE_PERFORMANCE; + clk_state = DM_PP_CLOCKS_STATE_PERFORMANCE; break; default: - clk_state = CLOCKS_STATE_INVALID; + clk_state = DM_PP_CLOCKS_STATE_INVALID; break; } @@ -402,7 +370,7 @@ struct display_clock *dal_display_clock_dce80_create( dc_base->ctx = ctx; dc_base->min_display_clk_threshold_khz = 0; - dc_base->cur_min_clks_state = CLOCKS_STATE_INVALID; + dc_base->cur_min_clks_state = DM_PP_CLOCKS_STATE_INVALID; dc_base->funcs = &funcs; /* @@ -423,12 +391,12 @@ struct display_clock *dal_display_clock_dce80_create( * via a pplib call to DAL IRI eventually calling a * DisplayEngineClock_Dce50::StoreMaxClocksState(). This call will come in * on PPLIB init. This is from DCE5x. in case HW wants to use mixed method.*/ - dc_base->max_clks_state = CLOCKS_STATE_NOMINAL; + dc_base->max_clks_state = DM_PP_CLOCKS_STATE_NOMINAL; /* Initially set current min clocks state to invalid since we * cannot make any assumption about PPLIB's initial state. This will be updated * by HWSS via SetMinClocksState() on first mode set prior to programming * state dependent clocks.*/ - disp_clk->cur_min_clks_state = CLOCKS_STATE_INVALID; + disp_clk->cur_min_clks_state = DM_PP_CLOCKS_STATE_INVALID; display_clock_ss_construct(disp_clk); diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.h b/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.h index 1193398b5cea..c155bb6a4321 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.h +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.h @@ -38,7 +38,7 @@ struct display_clock_dce80 { /* Flag for Enabled SS on GPU PLL*/ bool ss_on_gpu_pll; /* Current minimum display block clocks state*/ - enum clocks_state cur_min_clks_state; + enum dm_pp_clocks_state cur_min_clks_state; /* DFS-bypass feature variable Cache the status of DFS-bypass feature*/ bool dfs_bypass_enabled; diff --git a/drivers/gpu/drm/amd/display/include/display_clock_interface.h b/drivers/gpu/drm/amd/display/include/display_clock_interface.h index f2deafbd8b12..6ba8c093793d 100644 --- a/drivers/gpu/drm/amd/display/include/display_clock_interface.h +++ b/drivers/gpu/drm/amd/display/include/display_clock_interface.h @@ -26,29 +26,11 @@ #ifndef __DISPLAY_CLOCK_INTERFACE_H__ #define __DISPLAY_CLOCK_INTERFACE_H__ +#include "dm_services_types.h" #include "hw_sequencer_types.h" #include "grph_object_defs.h" #include "signal_types.h" -/* Enumeration of all clocks states */ -enum clocks_state { - CLOCKS_STATE_INVALID = 0, - CLOCKS_STATE_ULTRA_LOW, - CLOCKS_STATE_LOW, - CLOCKS_STATE_NOMINAL, - CLOCKS_STATE_PERFORMANCE, - /* Starting from DCE11, Max 8 level DPM state supported */ - CLOCKS_DPM_STATE_LEVEL_INVALID = CLOCKS_STATE_INVALID, - CLOCKS_DPM_STATE_LEVEL_0 = CLOCKS_STATE_ULTRA_LOW, - CLOCKS_DPM_STATE_LEVEL_1 = CLOCKS_STATE_LOW, - CLOCKS_DPM_STATE_LEVEL_2 = CLOCKS_STATE_NOMINAL, - CLOCKS_DPM_STATE_LEVEL_3 = CLOCKS_STATE_PERFORMANCE, - CLOCKS_DPM_STATE_LEVEL_4 = CLOCKS_DPM_STATE_LEVEL_3 + 1, - CLOCKS_DPM_STATE_LEVEL_5 = CLOCKS_DPM_STATE_LEVEL_4 + 1, - CLOCKS_DPM_STATE_LEVEL_6 = CLOCKS_DPM_STATE_LEVEL_5 + 1, - CLOCKS_DPM_STATE_LEVEL_7 = CLOCKS_DPM_STATE_LEVEL_6 + 1, -}; - /* Structure containing all state-dependent clocks * (dependent on "enum clocks_state") */ struct state_dependent_clocks { @@ -61,20 +43,20 @@ struct display_clock { const struct display_clock_funcs *funcs; uint32_t min_display_clk_threshold_khz; /* Max display block clocks state*/ - enum clocks_state max_clks_state; + enum dm_pp_clocks_state max_clks_state; - enum clocks_state cur_min_clks_state; + enum dm_pp_clocks_state cur_min_clks_state; }; struct display_clock_funcs { void (*destroy)(struct display_clock **to_destroy); void (*set_clock)(struct display_clock *disp_clk, uint32_t requested_clock_khz); - enum clocks_state (*get_required_clocks_state)( + enum dm_pp_clocks_state (*get_required_clocks_state)( struct display_clock *disp_clk, struct state_dependent_clocks *req_clocks); bool (*set_min_clocks_state)(struct display_clock *disp_clk, - enum clocks_state clocks_state); + enum dm_pp_clocks_state dm_pp_clocks_state); uint32_t (*get_dp_ref_clk_frequency)(struct display_clock *disp_clk); }; -- cgit From 9a70eba7f2c65b408ee56c7219b0cb4ae588b2bc Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Thu, 1 Dec 2016 18:13:25 -0500 Subject: drm/amd/display: consolidate dce8-11.2 display clock code Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/Makefile | 3 +- drivers/gpu/drm/amd/display/dc/dce/dce_audio.c | 4 +- drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c | 519 +++++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h | 133 ++++++ .../drm/amd/display/dc/dce100/dce100_resource.c | 22 +- .../drm/amd/display/dc/dce110/dce110_resource.c | 24 +- .../drm/amd/display/dc/dce112/dce112_resource.c | 28 +- .../gpu/drm/amd/display/dc/dce80/dce80_resource.c | 70 +-- drivers/gpu/drm/amd/display/dc/dm_services_types.h | 18 +- drivers/gpu/drm/amd/display/dc/gpu/Makefile | 15 - .../display/dc/gpu/dce110/display_clock_dce110.c | 516 -------------------- .../display/dc/gpu/dce110/display_clock_dce110.h | 50 -- .../display/dc/gpu/dce112/display_clock_dce112.c | 152 ------ .../display/dc/gpu/dce112/display_clock_dce112.h | 14 - .../amd/display/dc/gpu/dce80/display_clock_dce80.c | 430 ----------------- .../amd/display/dc/gpu/dce80/display_clock_dce80.h | 54 --- .../amd/display/include/display_clock_interface.h | 15 +- 17 files changed, 747 insertions(+), 1320 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h delete mode 100644 drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c delete mode 100644 drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.h delete mode 100644 drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c delete mode 100644 drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/Makefile b/drivers/gpu/drm/amd/display/dc/dce/Makefile index bfca38170329..6add5977fd39 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dce/Makefile @@ -6,7 +6,8 @@ # offset/shift/mask stored in dce_hw struct DCE = dce_audio.o dce_stream_encoder.o dce_link_encoder.o dce_hwseq.o \ -dce_mem_input.o dce_clock_source.o dce_scl_filters.o dce_transform.o +dce_mem_input.o dce_clock_source.o dce_scl_filters.o dce_transform.o \ +dce_clocks.o AMD_DAL_DCE = $(addprefix $(AMDDALPATH)/dc/dce/,$(DCE)) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c index dc44053e8575..2749c8fa4f1f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c @@ -888,7 +888,9 @@ static const struct audio_funcs funcs = { void dce_aud_destroy(struct audio **audio) { - dm_free(*audio); + struct dce_audio *aud = DCE_AUD(*audio); + + dm_free(aud); *audio = NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c new file mode 100644 index 000000000000..77033fe8a8e5 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c @@ -0,0 +1,519 @@ +/* + * Copyright 2012-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dce_clocks.h" +#include "dm_services.h" +#include "reg_helper.h" +#include "fixed32_32.h" +#include "bios_parser_interface.h" +#include "dc.h" + + +#define REG(reg) \ + (clk_dce->regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + clk_dce->clk_shift->field_name, clk_dce->clk_mask->field_name + +#define CTX \ + clk_dce->base.ctx + +/* Starting point for each divider range.*/ +enum divider_range_start { + DIVIDER_RANGE_01_START = 200, /* 2.00*/ + DIVIDER_RANGE_02_START = 1600, /* 16.00*/ + DIVIDER_RANGE_03_START = 3200, /* 32.00*/ + DIVIDER_RANGE_SCALE_FACTOR = 100 /* Results are scaled up by 100.*/ +}; + +/* Ranges for divider identifiers (Divider ID or DID) + mmDENTIST_DISPCLK_CNTL.DENTIST_DISPCLK_WDIVIDER*/ +enum divider_id_register_setting { + DIVIDER_RANGE_01_BASE_DIVIDER_ID = 0X08, + DIVIDER_RANGE_02_BASE_DIVIDER_ID = 0X40, + DIVIDER_RANGE_03_BASE_DIVIDER_ID = 0X60, + DIVIDER_RANGE_MAX_DIVIDER_ID = 0X80 +}; + +/* Step size between each divider within a range. + Incrementing the DENTIST_DISPCLK_WDIVIDER by one + will increment the divider by this much.*/ +enum divider_range_step_size { + DIVIDER_RANGE_01_STEP_SIZE = 25, /* 0.25*/ + DIVIDER_RANGE_02_STEP_SIZE = 50, /* 0.50*/ + DIVIDER_RANGE_03_STEP_SIZE = 100 /* 1.00 */ +}; + + +static uint32_t dce_clocks_get_dp_ref_freq(struct display_clock *clk) +{ + struct dce_disp_clk *clk_dce = TO_DCE_CLOCKS(clk); + int dprefclk_wdivider; + int dprefclk_src_sel; + int dp_ref_clk_khz = 600000; + int target_div = INVALID_DIVIDER; + + /* ASSERT DP Reference Clock source is from DFS*/ + REG_GET(DPREFCLK_CNTL, DPREFCLK_SRC_SEL, &dprefclk_src_sel); + ASSERT(dprefclk_src_sel == 0); + + /* Read the mmDENTIST_DISPCLK_CNTL to get the currently + * programmed DID DENTIST_DPREFCLK_WDIVIDER*/ + REG_GET(DENTIST_DISPCLK_CNTL, DENTIST_DPREFCLK_WDIVIDER, &dprefclk_wdivider); + + /* Convert DENTIST_DPREFCLK_WDIVIDERto actual divider*/ + target_div = dal_divider_range_get_divider( + clk_dce->divider_ranges, + DIVIDER_RANGE_MAX, + dprefclk_wdivider); + + if (target_div != INVALID_DIVIDER) { + /* Calculate the current DFS clock, in kHz.*/ + dp_ref_clk_khz = (DIVIDER_RANGE_SCALE_FACTOR + * clk_dce->dentist_vco_freq_khz) / target_div; + } + + /* SW will adjust DP REF Clock average value for all purposes + * (DP DTO / DP Audio DTO and DP GTC) + if clock is spread for all cases: + -if SS enabled on DP Ref clock and HW de-spreading enabled with SW + calculations for DS_INCR/DS_MODULO (this is planned to be default case) + -if SS enabled on DP Ref clock and HW de-spreading enabled with HW + calculations (not planned to be used, but average clock should still + be valid) + -if SS enabled on DP Ref clock and HW de-spreading disabled + (should not be case with CIK) then SW should program all rates + generated according to average value (case as with previous ASICs) + */ + if (clk_dce->ss_on_gpu_pll && clk_dce->gpu_pll_ss_divider != 0) { + struct fixed32_32 ss_percentage = dal_fixed32_32_div_int( + dal_fixed32_32_from_fraction( + clk_dce->gpu_pll_ss_percentage, + clk_dce->gpu_pll_ss_divider), 200); + struct fixed32_32 adj_dp_ref_clk_khz; + + ss_percentage = dal_fixed32_32_sub(dal_fixed32_32_one, + ss_percentage); + adj_dp_ref_clk_khz = + dal_fixed32_32_mul_int( + ss_percentage, + dp_ref_clk_khz); + dp_ref_clk_khz = dal_fixed32_32_floor(adj_dp_ref_clk_khz); + } + + return dp_ref_clk_khz; +} + +static enum dm_pp_clocks_state dce_get_required_clocks_state( + struct display_clock *clk, + struct state_dependent_clocks *req_clocks) +{ + struct dce_disp_clk *clk_dce = TO_DCE_CLOCKS(clk); + int i; + enum dm_pp_clocks_state low_req_clk; + + /* Iterate from highest supported to lowest valid state, and update + * lowest RequiredState with the lowest state that satisfies + * all required clocks + */ + for (i = clk->max_clks_state; i >= DM_PP_CLOCKS_STATE_ULTRA_LOW; i--) + if (req_clocks->display_clk_khz > + clk_dce->max_clks_by_state[i].display_clk_khz + || req_clocks->pixel_clk_khz > + clk_dce->max_clks_by_state[i].pixel_clk_khz) + break; + + low_req_clk = i + 1; + if (low_req_clk > clk->max_clks_state) { + dm_logger_write(clk->ctx->logger, LOG_WARNING, + "%s: clocks unsupported", __func__); + low_req_clk = DM_PP_CLOCKS_STATE_INVALID; + } + + return low_req_clk; +} + +static bool dce_clock_set_min_clocks_state( + struct display_clock *clk, + enum dm_pp_clocks_state clocks_state) +{ + struct dm_pp_power_level_change_request level_change_req = { + clocks_state }; + + if (clocks_state > clk->max_clks_state) { + /*Requested state exceeds max supported state.*/ + dm_logger_write(clk->ctx->logger, LOG_WARNING, + "Requested state exceeds max supported state"); + return false; + } else if (clocks_state == clk->cur_min_clks_state) { + /*if we're trying to set the same state, we can just return + * since nothing needs to be done*/ + return true; + } + + /* get max clock state from PPLIB */ + if (dm_pp_apply_power_level_change_request(clk->ctx, &level_change_req)) + clk->cur_min_clks_state = clocks_state; + + return true; +} + +static void dce_set_clock( + struct display_clock *clk, + uint32_t requested_clk_khz) +{ + struct dce_disp_clk *clk_dce = TO_DCE_CLOCKS(clk); + struct bp_pixel_clock_parameters pxl_clk_params = { 0 }; + struct dc_bios *bp = clk->ctx->dc_bios; + + /* Make sure requested clock isn't lower than minimum threshold*/ + if (requested_clk_khz > 0) + requested_clk_khz = dm_max(requested_clk_khz, + clk_dce->dentist_vco_freq_khz / 64); + + /* Prepare to program display clock*/ + pxl_clk_params.target_pixel_clock = requested_clk_khz; + pxl_clk_params.pll_id = CLOCK_SOURCE_ID_DFS; + + bp->funcs->program_display_engine_pll(bp, &pxl_clk_params); + + if (clk_dce->dfs_bypass_enabled) { + + /* Cache the fixed display clock*/ + clk_dce->dfs_bypass_disp_clk = + pxl_clk_params.dfs_bypass_display_clock; + } + + /* from power down, we need mark the clock state as ClocksStateNominal + * from HWReset, so when resume we will call pplib voltage regulator.*/ + if (requested_clk_khz == 0) + clk->cur_min_clks_state = DM_PP_CLOCKS_STATE_NOMINAL; +} + +#define PSR_SET_WAITLOOP 0x31 + +union dce110_dmcu_psr_config_data_wait_loop_reg1 { + struct { + unsigned int wait_loop:16; /* [15:0] */ + unsigned int reserved:16; /* [31:16] */ + } bits; + unsigned int u32; +}; + +static void dce_psr_wait_loop( + struct dce_disp_clk *clk_dce, unsigned int display_clk_khz) +{ + struct dc_context *ctx = clk_dce->base.ctx; + union dce110_dmcu_psr_config_data_wait_loop_reg1 masterCmdData1; + + /* waitDMCUReadyForCmd */ + REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 100, 100); + + masterCmdData1.u32 = 0; + masterCmdData1.bits.wait_loop = display_clk_khz / 1000 / 7; + dm_write_reg(ctx, REG(MASTER_COMM_DATA_REG1), masterCmdData1.u32); + + /* setDMCUParam_Cmd */ + REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, PSR_SET_WAITLOOP); + + /* notifyDMCUMsg */ + REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); +} + +static void dce_psr_set_clock( + struct display_clock *clk, + uint32_t requested_clk_khz) +{ + struct dce_disp_clk *clk_dce = TO_DCE_CLOCKS(clk); + + dce_set_clock(clk, requested_clk_khz); + dce_psr_wait_loop(clk_dce, requested_clk_khz); +} + +static void polaris_set_clock( + struct display_clock *clk, + uint32_t requested_clk_khz) +{ + struct dce_disp_clk *clk_dce = TO_DCE_CLOCKS(clk); + struct bp_set_dce_clock_parameters dce_clk_params; + struct dc_bios *bp = clk->ctx->dc_bios; + + /* Prepare to program display clock*/ + memset(&dce_clk_params, 0, sizeof(dce_clk_params)); + + /* Make sure requested clock isn't lower than minimum threshold*/ + if (requested_clk_khz > 0) + requested_clk_khz = dm_max(requested_clk_khz, + clk_dce->dentist_vco_freq_khz / 64); + + dce_clk_params.target_clock_frequency = requested_clk_khz; + dce_clk_params.pll_id = CLOCK_SOURCE_ID_DFS; + dce_clk_params.clock_type = DCECLOCK_TYPE_DISPLAY_CLOCK; + + bp->funcs->set_dce_clock(bp, &dce_clk_params); + + /* from power down, we need mark the clock state as ClocksStateNominal + * from HWReset, so when resume we will call pplib voltage regulator.*/ + if (requested_clk_khz == 0) + clk->cur_min_clks_state = DM_PP_CLOCKS_STATE_NOMINAL; + + /*Program DP ref Clock*/ + /*VBIOS will determine DPREFCLK frequency, so we don't set it*/ + dce_clk_params.target_clock_frequency = 0; + dce_clk_params.clock_type = DCECLOCK_TYPE_DPREFCLK; + dce_clk_params.flags.USE_GENLOCK_AS_SOURCE_FOR_DPREFCLK = 0; + + bp->funcs->set_dce_clock(bp, &dce_clk_params); +} + +static void dce_clock_read_integrated_info(struct dce_disp_clk *clk_dce) +{ + struct dc_debug *debug = &clk_dce->base.ctx->dc->debug; + struct dc_bios *bp = clk_dce->base.ctx->dc_bios; + struct integrated_info info = { 0 }; + struct firmware_info fw_info = { 0 }; + int i; + + if (bp->integrated_info) + info = *bp->integrated_info; + + clk_dce->dentist_vco_freq_khz = info.dentist_vco_freq; + if (clk_dce->dentist_vco_freq_khz == 0) { + bp->funcs->get_firmware_info(bp, &fw_info); + clk_dce->dentist_vco_freq_khz = + fw_info.smu_gpu_pll_output_freq; + if (clk_dce->dentist_vco_freq_khz == 0) + clk_dce->dentist_vco_freq_khz = 3600000; + } + + /*update the maximum display clock for each power state*/ + for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) { + enum dm_pp_clocks_state clk_state = DM_PP_CLOCKS_STATE_INVALID; + + switch (i) { + case 0: + clk_state = DM_PP_CLOCKS_STATE_ULTRA_LOW; + break; + + case 1: + clk_state = DM_PP_CLOCKS_STATE_LOW; + break; + + case 2: + clk_state = DM_PP_CLOCKS_STATE_NOMINAL; + break; + + case 3: + clk_state = DM_PP_CLOCKS_STATE_PERFORMANCE; + break; + + default: + clk_state = DM_PP_CLOCKS_STATE_INVALID; + break; + } + + /*Do not allow bad VBIOS/SBIOS to override with invalid values, + * check for > 100MHz*/ + if (info.disp_clk_voltage[i].max_supported_clk >= 100000) + clk_dce->max_clks_by_state[clk_state].display_clk_khz = + info.disp_clk_voltage[i].max_supported_clk; + } + + if (!debug->disable_dfs_bypass) + if (bp->integrated_info->gpu_cap_info & DFS_BYPASS_ENABLE) + clk_dce->dfs_bypass_enabled = true; + + clk_dce->use_max_disp_clk = debug->max_disp_clk; +} + +static void dce_clock_read_ss_info(struct dce_disp_clk *clk_dce) +{ + struct dc_bios *bp = clk_dce->base.ctx->dc_bios; + int ss_info_num = bp->funcs->get_ss_entry_number( + bp, AS_SIGNAL_TYPE_GPU_PLL); + + if (ss_info_num) { + struct spread_spectrum_info info = { 0 }; + enum bp_result result = bp->funcs->get_spread_spectrum_info( + bp, AS_SIGNAL_TYPE_GPU_PLL, 0, &info); + + /* Based on VBIOS, VBIOS will keep entry for GPU PLL SS + * even if SS not enabled and in that case + * SSInfo.spreadSpectrumPercentage !=0 would be sign + * that SS is enabled + */ + if (result == BP_RESULT_OK && + info.spread_spectrum_percentage != 0) { + clk_dce->ss_on_gpu_pll = true; + clk_dce->gpu_pll_ss_divider = info.spread_percentage_divider; + + if (info.type.CENTER_MODE == 0) { + /* Currently for DP Reference clock we + * need only SS percentage for + * downspread */ + clk_dce->gpu_pll_ss_percentage = + info.spread_spectrum_percentage; + } + } + + } +} + +static const struct display_clock_funcs dce112_funcs = { + .get_dp_ref_clk_frequency = dce_clocks_get_dp_ref_freq, + .get_required_clocks_state = dce_get_required_clocks_state, + .set_min_clocks_state = dce_clock_set_min_clocks_state, + .set_clock = polaris_set_clock +}; + +static const struct display_clock_funcs dce110_funcs = { + .get_dp_ref_clk_frequency = dce_clocks_get_dp_ref_freq, + .get_required_clocks_state = dce_get_required_clocks_state, + .set_min_clocks_state = dce_clock_set_min_clocks_state, + .set_clock = dce_psr_set_clock +}; + +static const struct display_clock_funcs dce_funcs = { + .get_dp_ref_clk_frequency = dce_clocks_get_dp_ref_freq, + .get_required_clocks_state = dce_get_required_clocks_state, + .set_min_clocks_state = dce_clock_set_min_clocks_state, + .set_clock = dce_set_clock +}; + +static void dce_disp_clk_construct( + struct dce_disp_clk *clk_dce, + struct dc_context *ctx, + const struct dce_disp_clk_registers *regs, + const struct dce_disp_clk_shift *clk_shift, + const struct dce_disp_clk_mask *clk_mask) +{ + struct display_clock *base = &clk_dce->base; + + base->ctx = ctx; + base->funcs = &dce_funcs; + + clk_dce->regs = regs; + clk_dce->clk_shift = clk_shift; + clk_dce->clk_mask = clk_mask; + + clk_dce->dfs_bypass_disp_clk = 0; + clk_dce->gpu_pll_ss_percentage = 0; + clk_dce->gpu_pll_ss_divider = 1000; + clk_dce->ss_on_gpu_pll = false; + base->max_clks_state = DM_PP_CLOCKS_STATE_NOMINAL; + base->cur_min_clks_state = DM_PP_CLOCKS_STATE_INVALID; + + dce_clock_read_integrated_info(clk_dce); + dce_clock_read_ss_info(clk_dce); + + dal_divider_range_construct( + &clk_dce->divider_ranges[DIVIDER_RANGE_01], + DIVIDER_RANGE_01_START, + DIVIDER_RANGE_01_STEP_SIZE, + DIVIDER_RANGE_01_BASE_DIVIDER_ID, + DIVIDER_RANGE_02_BASE_DIVIDER_ID); + dal_divider_range_construct( + &clk_dce->divider_ranges[DIVIDER_RANGE_02], + DIVIDER_RANGE_02_START, + DIVIDER_RANGE_02_STEP_SIZE, + DIVIDER_RANGE_02_BASE_DIVIDER_ID, + DIVIDER_RANGE_03_BASE_DIVIDER_ID); + dal_divider_range_construct( + &clk_dce->divider_ranges[DIVIDER_RANGE_03], + DIVIDER_RANGE_03_START, + DIVIDER_RANGE_03_STEP_SIZE, + DIVIDER_RANGE_03_BASE_DIVIDER_ID, + DIVIDER_RANGE_MAX_DIVIDER_ID); +} + +struct display_clock *dce_disp_clk_create( + struct dc_context *ctx, + const struct dce_disp_clk_registers *regs, + const struct dce_disp_clk_shift *clk_shift, + const struct dce_disp_clk_mask *clk_mask) +{ + struct dce_disp_clk *clk_dce = dm_alloc(sizeof(*clk_dce)); + + if (clk_dce == NULL) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dce_disp_clk_construct( + clk_dce, ctx, regs, clk_shift, clk_mask); + + return &clk_dce->base; +} + +struct display_clock *dce110_disp_clk_create( + struct dc_context *ctx, + const struct dce_disp_clk_registers *regs, + const struct dce_disp_clk_shift *clk_shift, + const struct dce_disp_clk_mask *clk_mask) +{ + struct dce_disp_clk *clk_dce = dm_alloc(sizeof(*clk_dce)); + + if (clk_dce == NULL) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dce_disp_clk_construct( + clk_dce, ctx, regs, clk_shift, clk_mask); + + clk_dce->base.funcs = &dce110_funcs; + + return &clk_dce->base; +} + +struct display_clock *dce112_disp_clk_create( + struct dc_context *ctx, + const struct dce_disp_clk_registers *regs, + const struct dce_disp_clk_shift *clk_shift, + const struct dce_disp_clk_mask *clk_mask) +{ + struct dce_disp_clk *clk_dce = dm_alloc(sizeof(*clk_dce)); + + if (clk_dce == NULL) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dce_disp_clk_construct( + clk_dce, ctx, regs, clk_shift, clk_mask); + + clk_dce->base.funcs = &dce112_funcs; + + return &clk_dce->base; +} + +void dce_disp_clk_destroy(struct display_clock **disp_clk) +{ + struct dce_disp_clk *clk_dce = TO_DCE_CLOCKS(*disp_clk); + + dm_free(clk_dce); + *disp_clk = NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h new file mode 100644 index 000000000000..e3b23749f0a2 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h @@ -0,0 +1,133 @@ +/* + * Copyright 2012-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + + +#ifndef _DCE_CLOCKS_H_ +#define _DCE_CLOCKS_H_ + +#include "display_clock_interface.h" +#include "../gpu/divider_range.h" + + +#define TO_DCE_CLOCKS(clocks)\ + container_of(clocks, struct dce_disp_clk, base) + +#define CLK_COMMON_REG_LIST_DCE_BASE() \ + .DPREFCLK_CNTL = mmDPREFCLK_CNTL, \ + .DENTIST_DISPCLK_CNTL = mmDENTIST_DISPCLK_CNTL, \ + .MASTER_COMM_DATA_REG1 = mmMASTER_COMM_DATA_REG1, \ + .MASTER_COMM_CMD_REG = mmMASTER_COMM_CMD_REG, \ + .MASTER_COMM_CNTL_REG = mmMASTER_COMM_CNTL_REG + +#define CLK_SF(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh) \ + CLK_SF(DPREFCLK_CNTL, DPREFCLK_SRC_SEL, mask_sh), \ + CLK_SF(DENTIST_DISPCLK_CNTL, DENTIST_DPREFCLK_WDIVIDER, mask_sh), \ + CLK_SF(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, mask_sh), \ + CLK_SF(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, mask_sh) + + +#define CLK_REG_FIELD_LIST(type) \ + type DPREFCLK_SRC_SEL; \ + type DENTIST_DPREFCLK_WDIVIDER; \ + type MASTER_COMM_CMD_REG_BYTE0; \ + type MASTER_COMM_INTERRUPT + +struct dce_disp_clk_shift { + CLK_REG_FIELD_LIST(uint8_t); +}; + +struct dce_disp_clk_mask { + CLK_REG_FIELD_LIST(uint32_t); +}; + +struct dce_disp_clk_registers { + uint32_t DPREFCLK_CNTL; + uint32_t DENTIST_DISPCLK_CNTL; + uint32_t MASTER_COMM_DATA_REG1; + uint32_t MASTER_COMM_CMD_REG; + uint32_t MASTER_COMM_CNTL_REG; +}; + +/* Array identifiers and count for the divider ranges.*/ +enum divider_range_count { + DIVIDER_RANGE_01 = 0, + DIVIDER_RANGE_02, + DIVIDER_RANGE_03, + DIVIDER_RANGE_MAX /* == 3*/ +}; + +struct dce_disp_clk { + struct display_clock base; + const struct dce_disp_clk_registers *regs; + const struct dce_disp_clk_shift *clk_shift; + const struct dce_disp_clk_mask *clk_mask; + + struct state_dependent_clocks max_clks_by_state[DM_PP_CLOCKS_MAX_STATES]; + struct divider_range divider_ranges[DIVIDER_RANGE_MAX]; + + bool use_max_disp_clk; + uint32_t dentist_vco_freq_khz; + + /* Cache the status of DFS-bypass feature*/ + bool dfs_bypass_enabled; + /* Cache the display clock returned by VBIOS if DFS-bypass is enabled. + * This is basically "Crystal Frequency In KHz" (XTALIN) frequency */ + uint32_t dfs_bypass_disp_clk; + + /* Flag for Enabled SS on GPU PLL */ + bool ss_on_gpu_pll; + /* GPU PLL SS percentage (if down-spread enabled) */ + uint32_t gpu_pll_ss_percentage; + /* GPU PLL SS percentage Divider (100 or 1000) */ + uint32_t gpu_pll_ss_divider; + + +}; + + +struct display_clock *dce_disp_clk_create( + struct dc_context *ctx, + const struct dce_disp_clk_registers *regs, + const struct dce_disp_clk_shift *clk_shift, + const struct dce_disp_clk_mask *clk_mask); + +struct display_clock *dce110_disp_clk_create( + struct dc_context *ctx, + const struct dce_disp_clk_registers *regs, + const struct dce_disp_clk_shift *clk_shift, + const struct dce_disp_clk_mask *clk_mask); + +struct display_clock *dce112_disp_clk_create( + struct dc_context *ctx, + const struct dce_disp_clk_registers *regs, + const struct dce_disp_clk_shift *clk_shift, + const struct dce_disp_clk_mask *clk_mask); + +void dce_disp_clk_destroy(struct display_clock **disp_clk); + +#endif /* _DCE_CLOCKS_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 5716ce1e58f4..c97416f7bc93 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -40,6 +40,7 @@ #include "dce110/dce110_ipp.h" #include "dce/dce_transform.h" #include "dce110/dce110_opp.h" +#include "dce/dce_clocks.h" #include "dce/dce_clock_source.h" #include "dce/dce_audio.h" #include "dce/dce_hwseq.h" @@ -200,6 +201,18 @@ static const struct dce110_ipp_reg_offsets dce100_ipp_reg_offsets[] = { .reg_name = mm ## block ## id ## _ ## reg_name +static const struct dce_disp_clk_registers disp_clk_regs = { + CLK_COMMON_REG_LIST_DCE_BASE() +}; + +static const struct dce_disp_clk_shift disp_clk_shift = { + CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) +}; + +static const struct dce_disp_clk_mask disp_clk_mask = { + CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) +}; + #define transform_regs(id)\ [id] = {\ XFM_COMMON_REG_LIST_DCE100(id)\ @@ -717,9 +730,7 @@ static void destruct(struct dce110_resource_pool *pool) } if (pool->base.display_clock != NULL) - pool->base.display_clock->funcs->destroy( - &pool->base.display_clock); - pool->base.display_clock = NULL; + dce_disp_clk_destroy(&pool->base.display_clock); if (pool->base.irqs != NULL) dal_irq_service_destroy(&pool->base.irqs); @@ -970,7 +981,10 @@ static bool construct( } } - pool->base.display_clock = dal_display_clock_dce110_create(ctx); + pool->base.display_clock = dce_disp_clk_create(ctx, + &disp_clk_regs, + &disp_clk_shift, + &disp_clk_mask); if (pool->base.display_clock == NULL) { dm_error("DC: failed to create display clock!\n"); BREAK_TO_DEBUGGER(); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 8682c8b2a547..fa601f7f0b5a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -45,6 +45,7 @@ #include "dce110/dce110_transform_v.h" #include "dce110/dce110_opp.h" #include "dce110/dce110_opp_v.h" +#include "dce/dce_clocks.h" #include "dce/dce_clock_source.h" #include "dce/dce_hwseq.h" #include "dce110/dce110_hw_sequencer.h" @@ -187,6 +188,17 @@ static const struct dce110_ipp_reg_offsets dce110_ipp_reg_offsets[] = { #define SRI(reg_name, block, id)\ .reg_name = mm ## block ## id ## _ ## reg_name +static const struct dce_disp_clk_registers disp_clk_regs = { + CLK_COMMON_REG_LIST_DCE_BASE() +}; + +static const struct dce_disp_clk_shift disp_clk_shift = { + CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) +}; + +static const struct dce_disp_clk_mask disp_clk_mask = { + CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) +}; #define transform_regs(id)\ [id] = {\ @@ -699,11 +711,8 @@ static void destruct(struct dce110_resource_pool *pool) } } - if (pool->base.display_clock != NULL) { - pool->base.display_clock->funcs->destroy( - &pool->base.display_clock); - pool->base.display_clock = NULL; - } + if (pool->base.display_clock != NULL) + dce_disp_clk_destroy(&pool->base.display_clock); if (pool->base.irqs != NULL) { dal_irq_service_destroy(&pool->base.irqs); @@ -1261,7 +1270,10 @@ static bool construct( } } - pool->base.display_clock = dal_display_clock_dce110_create(ctx); + pool->base.display_clock = dce110_disp_clk_create(ctx, + &disp_clk_regs, + &disp_clk_shift, + &disp_clk_mask); if (pool->base.display_clock == NULL) { dm_error("DC: failed to create display clock!\n"); BREAK_TO_DEBUGGER(); diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index c50a215172b7..3a478300b848 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -41,6 +41,7 @@ #include "dce/dce_audio.h" #include "dce112/dce112_opp.h" #include "dce110/dce110_ipp.h" +#include "dce/dce_clocks.h" #include "dce/dce_clock_source.h" #include "dce/dce_hwseq.h" @@ -204,6 +205,19 @@ static const struct dce110_ipp_reg_offsets ipp_reg_offsets[] = { #define SRI(reg_name, block, id)\ .reg_name = mm ## block ## id ## _ ## reg_name + +static const struct dce_disp_clk_registers disp_clk_regs = { + CLK_COMMON_REG_LIST_DCE_BASE() +}; + +static const struct dce_disp_clk_shift disp_clk_shift = { + CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) +}; + +static const struct dce_disp_clk_mask disp_clk_mask = { + CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) +}; + #define transform_regs(id)\ [id] = {\ XFM_COMMON_REG_LIST_DCE110(id)\ @@ -733,11 +747,8 @@ static void destruct(struct dce110_resource_pool *pool) } } - if (pool->base.display_clock != NULL) { - pool->base.display_clock->funcs->destroy( - &pool->base.display_clock); - pool->base.display_clock = NULL; - } + if (pool->base.display_clock != NULL) + dce_disp_clk_destroy(&pool->base.display_clock); if (pool->base.irqs != NULL) { dal_irq_service_destroy(&pool->base.irqs); @@ -1299,9 +1310,10 @@ static bool construct( } } - pool->base.display_clock = dal_display_clock_dce112_create( - ctx); - + pool->base.display_clock = dce112_disp_clk_create(ctx, + &disp_clk_regs, + &disp_clk_shift, + &disp_clk_mask); if (pool->base.display_clock == NULL) { dm_error("DC: failed to create display clock!\n"); BREAK_TO_DEBUGGER(); diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 1d2a31e34617..517d42dfff0c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -45,6 +45,7 @@ #include "dce/dce_transform.h" #include "dce80/dce80_opp.h" #include "dce110/dce110_ipp.h" +#include "dce/dce_clocks.h" #include "dce/dce_clock_source.h" #include "dce/dce_audio.h" #include "dce/dce_hwseq.h" @@ -215,6 +216,19 @@ static const struct dce110_ipp_reg_offsets ipp_reg_offsets[] = { #define SRI(reg_name, block, id)\ .reg_name = mm ## block ## id ## _ ## reg_name + +static const struct dce_disp_clk_registers disp_clk_regs = { + CLK_COMMON_REG_LIST_DCE_BASE() +}; + +static const struct dce_disp_clk_shift disp_clk_shift = { + CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) +}; + +static const struct dce_disp_clk_mask disp_clk_mask = { + CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) +}; + #define transform_regs(id)\ [id] = {\ XFM_COMMON_REG_LIST_DCE_BASE(id)\ @@ -656,11 +670,8 @@ static void destruct(struct dce110_resource_pool *pool) } } - if (pool->base.display_clock != NULL) { - pool->base.display_clock->funcs->destroy( - &pool->base.display_clock); - pool->base.display_clock = NULL; - } + if (pool->base.display_clock != NULL) + dce_disp_clk_destroy(&pool->base.display_clock); if (pool->base.irqs != NULL) { dal_irq_service_destroy(&pool->base.irqs); @@ -857,47 +868,6 @@ static const struct resource_funcs dce80_res_pool_funcs = { .validate_bandwidth = dce80_validate_bandwidth }; -static enum dm_pp_clocks_state dce80_resource_convert_clock_state_pp_to_dc( - enum dm_pp_clocks_state pp_clock_state) -{ - enum dm_pp_clocks_state dc_clocks_state = DM_PP_CLOCKS_STATE_INVALID; - - switch (pp_clock_state) { - case DM_PP_CLOCKS_STATE_INVALID: - dc_clocks_state = DM_PP_CLOCKS_STATE_INVALID; - break; - case DM_PP_CLOCKS_STATE_ULTRA_LOW: - dc_clocks_state = DM_PP_CLOCKS_STATE_ULTRA_LOW; - break; - case DM_PP_CLOCKS_STATE_LOW: - dc_clocks_state = DM_PP_CLOCKS_STATE_LOW; - break; - case DM_PP_CLOCKS_STATE_NOMINAL: - dc_clocks_state = DM_PP_CLOCKS_STATE_NOMINAL; - break; - case DM_PP_CLOCKS_STATE_PERFORMANCE: - dc_clocks_state = DM_PP_CLOCKS_STATE_PERFORMANCE; - break; - case DM_PP_CLOCKS_DPM_STATE_LEVEL_4: - dc_clocks_state = DM_PP_CLOCKS_DPM_STATE_LEVEL_4; - break; - case DM_PP_CLOCKS_DPM_STATE_LEVEL_5: - dc_clocks_state = DM_PP_CLOCKS_DPM_STATE_LEVEL_5; - break; - case DM_PP_CLOCKS_DPM_STATE_LEVEL_6: - dc_clocks_state = DM_PP_CLOCKS_DPM_STATE_LEVEL_6; - break; - case DM_PP_CLOCKS_DPM_STATE_LEVEL_7: - dc_clocks_state = DM_PP_CLOCKS_DPM_STATE_LEVEL_7; - break; - default: - dc_clocks_state = DM_PP_CLOCKS_STATE_INVALID; - break; - } - - return dc_clocks_state; -} - static bool construct( uint8_t num_virtual_links, struct core_dc *dc, @@ -967,7 +937,10 @@ static bool construct( } } - pool->base.display_clock = dal_display_clock_dce80_create(ctx); + pool->base.display_clock = dce_disp_clk_create(ctx, + &disp_clk_regs, + &disp_clk_shift, + &disp_clk_mask); if (pool->base.display_clock == NULL) { dm_error("DC: failed to create display clock!\n"); BREAK_TO_DEBUGGER(); @@ -977,8 +950,7 @@ static bool construct( if (dm_pp_get_static_clocks(ctx, &static_clk_info)) pool->base.display_clock->max_clks_state = - dce80_resource_convert_clock_state_pp_to_dc( - static_clk_info.max_clocks_state); + static_clk_info.max_clocks_state; { struct irq_service_init_data init_data; diff --git a/drivers/gpu/drm/amd/display/dc/dm_services_types.h b/drivers/gpu/drm/amd/display/dc/dm_services_types.h index 44bad17fa318..460971dc3a70 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services_types.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services_types.h @@ -43,15 +43,17 @@ enum dm_pp_clocks_state { /* Starting from DCE11, Max 8 levels of DPM state supported. */ DM_PP_CLOCKS_DPM_STATE_LEVEL_INVALID = DM_PP_CLOCKS_STATE_INVALID, - DM_PP_CLOCKS_DPM_STATE_LEVEL_0 = DM_PP_CLOCKS_STATE_ULTRA_LOW, - DM_PP_CLOCKS_DPM_STATE_LEVEL_1 = DM_PP_CLOCKS_STATE_LOW, - DM_PP_CLOCKS_DPM_STATE_LEVEL_2 = DM_PP_CLOCKS_STATE_NOMINAL, + DM_PP_CLOCKS_DPM_STATE_LEVEL_0, + DM_PP_CLOCKS_DPM_STATE_LEVEL_1, + DM_PP_CLOCKS_DPM_STATE_LEVEL_2, /* to be backward compatible */ - DM_PP_CLOCKS_DPM_STATE_LEVEL_3 = DM_PP_CLOCKS_STATE_PERFORMANCE, - DM_PP_CLOCKS_DPM_STATE_LEVEL_4 = DM_PP_CLOCKS_DPM_STATE_LEVEL_3 + 1, - DM_PP_CLOCKS_DPM_STATE_LEVEL_5 = DM_PP_CLOCKS_DPM_STATE_LEVEL_4 + 1, - DM_PP_CLOCKS_DPM_STATE_LEVEL_6 = DM_PP_CLOCKS_DPM_STATE_LEVEL_5 + 1, - DM_PP_CLOCKS_DPM_STATE_LEVEL_7 = DM_PP_CLOCKS_DPM_STATE_LEVEL_6 + 1, + DM_PP_CLOCKS_DPM_STATE_LEVEL_3, + DM_PP_CLOCKS_DPM_STATE_LEVEL_4, + DM_PP_CLOCKS_DPM_STATE_LEVEL_5, + DM_PP_CLOCKS_DPM_STATE_LEVEL_6, + DM_PP_CLOCKS_DPM_STATE_LEVEL_7, + + DM_PP_CLOCKS_MAX_STATES }; struct dm_pp_gpu_clock_range { diff --git a/drivers/gpu/drm/amd/display/dc/gpu/Makefile b/drivers/gpu/drm/amd/display/dc/gpu/Makefile index 0b99a7474950..6ab4078405f2 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/Makefile +++ b/drivers/gpu/drm/amd/display/dc/gpu/Makefile @@ -9,24 +9,9 @@ AMD_DAL_GPU = $(addprefix $(AMDDALPATH)/dc/gpu/,$(GPU)) AMD_DISPLAY_FILES += $(AMD_DAL_GPU) -############################################################################### -# DCE 80 family -############################################################################### -GPU_DCE80 = display_clock_dce80.o - -AMD_DAL_GPU_DCE80 = $(addprefix $(AMDDALPATH)/dc/gpu/dce80/,$(GPU_DCE80)) - -AMD_DISPLAY_FILES += $(AMD_DAL_GPU_DCE80) - - ############################################################################### # DCE 110 family ############################################################################### -GPU_DCE110 = display_clock_dce110.o - -AMD_DAL_GPU_DCE110 = $(addprefix $(AMDDALPATH)/dc/gpu/dce110/,$(GPU_DCE110)) - -AMD_DISPLAY_FILES += $(AMD_DAL_GPU_DCE110) GPU_DCE112 = display_clock_dce112.o diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c b/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c deleted file mode 100644 index 9dabaac2c550..000000000000 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c +++ /dev/null @@ -1,516 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" - -#include "dce/dce_11_0_d.h" -#include "dce/dce_11_0_sh_mask.h" - -#include "include/bios_parser_interface.h" -#include "include/fixed32_32.h" -#include "include/logger_interface.h" - -#include "../divider_range.h" - -#include "display_clock_dce110.h" -#include "dc.h" - -#define FROM_DISPLAY_CLOCK(base) \ - container_of(base, struct display_clock_dce110, disp_clk_base) - -#define PSR_SET_WAITLOOP 0x31 - -static struct state_dependent_clocks max_clks_by_state[] = { -/*ClocksStateInvalid - should not be used*/ -{ .display_clk_khz = 0, .pixel_clk_khz = 0 }, -/*ClocksStateUltraLow - currently by HW design team not supposed to be used*/ -{ .display_clk_khz = 352000, .pixel_clk_khz = 330000 }, -/*ClocksStateLow*/ -{ .display_clk_khz = 352000, .pixel_clk_khz = 330000 }, -/*ClocksStateNominal*/ -{ .display_clk_khz = 467000, .pixel_clk_khz = 400000 }, -/*ClocksStatePerformance*/ -{ .display_clk_khz = 643000, .pixel_clk_khz = 400000 } }; - -/* Starting point for each divider range.*/ -enum divider_range_start { - DIVIDER_RANGE_01_START = 200, /* 2.00*/ - DIVIDER_RANGE_02_START = 1600, /* 16.00*/ - DIVIDER_RANGE_03_START = 3200, /* 32.00*/ - DIVIDER_RANGE_SCALE_FACTOR = 100 /* Results are scaled up by 100.*/ -}; - -/* Array identifiers and count for the divider ranges.*/ -enum divider_range_count { - DIVIDER_RANGE_01 = 0, - DIVIDER_RANGE_02, - DIVIDER_RANGE_03, - DIVIDER_RANGE_MAX /* == 3*/ -}; - -/* Ranges for divider identifiers (Divider ID or DID) - mmDENTIST_DISPCLK_CNTL.DENTIST_DISPCLK_WDIVIDER*/ -enum divider_id_register_setting { - DIVIDER_RANGE_01_BASE_DIVIDER_ID = 0X08, - DIVIDER_RANGE_02_BASE_DIVIDER_ID = 0X40, - DIVIDER_RANGE_03_BASE_DIVIDER_ID = 0X60, - DIVIDER_RANGE_MAX_DIVIDER_ID = 0X80 -}; - -/* Step size between each divider within a range. - Incrementing the DENTIST_DISPCLK_WDIVIDER by one - will increment the divider by this much.*/ -enum divider_range_step_size { - DIVIDER_RANGE_01_STEP_SIZE = 25, /* 0.25*/ - DIVIDER_RANGE_02_STEP_SIZE = 50, /* 0.50*/ - DIVIDER_RANGE_03_STEP_SIZE = 100 /* 1.00 */ -}; - -union dce110_dmcu_psr_config_data_wait_loop_reg1 { - struct { - unsigned int waitLoop:16; /* [15:0] */ - unsigned int reserved:16; /* [31:16] */ - } bits; - unsigned int u32All; -}; - -static struct divider_range divider_ranges[DIVIDER_RANGE_MAX]; - -#define DCE110_DFS_BYPASS_THRESHOLD_KHZ 400000 -/***************************************************************************** - * static functions - *****************************************************************************/ - -static bool dce110_set_min_clocks_state( - struct display_clock *dc, - enum dm_pp_clocks_state clocks_state) -{ - struct dm_pp_power_level_change_request level_change_req = { - clocks_state }; - - if (clocks_state > dc->max_clks_state) { - /*Requested state exceeds max supported state.*/ - dm_logger_write(dc->ctx->logger, LOG_WARNING, - "Requested state exceeds max supported state"); - return false; - } else if (clocks_state == dc->cur_min_clks_state) { - /*if we're trying to set the same state, we can just return - * since nothing needs to be done*/ - return true; - } - - /* get max clock state from PPLIB */ - if (dm_pp_apply_power_level_change_request(dc->ctx, &level_change_req)) - dc->cur_min_clks_state = clocks_state; - - return true; -} - -static uint32_t get_dp_ref_clk_frequency(struct display_clock *dc) -{ - uint32_t dispclk_cntl_value; - uint32_t dp_ref_clk_cntl_value; - uint32_t dp_ref_clk_cntl_src_sel_value; - uint32_t dp_ref_clk_khz = 600000; - uint32_t target_div = INVALID_DIVIDER; - struct display_clock_dce110 *disp_clk = FROM_DISPLAY_CLOCK(dc); - - /* ASSERT DP Reference Clock source is from DFS*/ - dp_ref_clk_cntl_value = dm_read_reg(dc->ctx, - mmDPREFCLK_CNTL); - - dp_ref_clk_cntl_src_sel_value = - get_reg_field_value( - dp_ref_clk_cntl_value, - DPREFCLK_CNTL, DPREFCLK_SRC_SEL); - - ASSERT(dp_ref_clk_cntl_src_sel_value == 0); - - /* Read the mmDENTIST_DISPCLK_CNTL to get the currently - * programmed DID DENTIST_DPREFCLK_WDIVIDER*/ - dispclk_cntl_value = dm_read_reg(dc->ctx, - mmDENTIST_DISPCLK_CNTL); - - /* Convert DENTIST_DPREFCLK_WDIVIDERto actual divider*/ - target_div = dal_divider_range_get_divider( - divider_ranges, - DIVIDER_RANGE_MAX, - get_reg_field_value(dispclk_cntl_value, - DENTIST_DISPCLK_CNTL, - DENTIST_DPREFCLK_WDIVIDER)); - - if (target_div != INVALID_DIVIDER) { - /* Calculate the current DFS clock, in kHz.*/ - dp_ref_clk_khz = (DIVIDER_RANGE_SCALE_FACTOR - * disp_clk->dentist_vco_freq_khz) / target_div; - } - - /* SW will adjust DP REF Clock average value for all purposes - * (DP DTO / DP Audio DTO and DP GTC) - if clock is spread for all cases: - -if SS enabled on DP Ref clock and HW de-spreading enabled with SW - calculations for DS_INCR/DS_MODULO (this is planned to be default case) - -if SS enabled on DP Ref clock and HW de-spreading enabled with HW - calculations (not planned to be used, but average clock should still - be valid) - -if SS enabled on DP Ref clock and HW de-spreading disabled - (should not be case with CIK) then SW should program all rates - generated according to average value (case as with previous ASICs) - */ - if ((disp_clk->ss_on_gpu_pll) && (disp_clk->gpu_pll_ss_divider != 0)) { - struct fixed32_32 ss_percentage = dal_fixed32_32_div_int( - dal_fixed32_32_from_fraction( - disp_clk->gpu_pll_ss_percentage, - disp_clk->gpu_pll_ss_divider), 200); - struct fixed32_32 adj_dp_ref_clk_khz; - - ss_percentage = dal_fixed32_32_sub(dal_fixed32_32_one, - ss_percentage); - adj_dp_ref_clk_khz = - dal_fixed32_32_mul_int( - ss_percentage, - dp_ref_clk_khz); - dp_ref_clk_khz = dal_fixed32_32_floor(adj_dp_ref_clk_khz); - } - - return dp_ref_clk_khz; -} - -static void destroy(struct display_clock **base) -{ - struct display_clock_dce110 *dc110; - - dc110 = DCLCK110_FROM_BASE(*base); - - dm_free(dc110); - - *base = NULL; -} - -static bool display_clock_integrated_info_construct( - struct display_clock_dce110 *disp_clk) -{ - struct dc_debug *debug = &disp_clk->disp_clk_base.ctx->dc->debug; - struct dc_bios *bp = disp_clk->disp_clk_base.ctx->dc_bios; - struct integrated_info info; - struct firmware_info fw_info; - uint32_t i; - struct display_clock *base = &disp_clk->disp_clk_base; - - memset(&info, 0, sizeof(struct integrated_info)); - memset(&fw_info, 0, sizeof(struct firmware_info)); - - if (bp->integrated_info) - info = *bp->integrated_info; - - disp_clk->dentist_vco_freq_khz = info.dentist_vco_freq; - if (disp_clk->dentist_vco_freq_khz == 0) { - bp->funcs->get_firmware_info(bp, &fw_info); - disp_clk->dentist_vco_freq_khz = - fw_info.smu_gpu_pll_output_freq; - if (disp_clk->dentist_vco_freq_khz == 0) - disp_clk->dentist_vco_freq_khz = 3600000; - } - - base->min_display_clk_threshold_khz = - disp_clk->dentist_vco_freq_khz / 64; - - if (bp->integrated_info == NULL) - return false; - - /*update the maximum display clock for each power state*/ - for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) { - enum dm_pp_clocks_state clk_state = DM_PP_CLOCKS_STATE_INVALID; - - switch (i) { - case 0: - clk_state = DM_PP_CLOCKS_STATE_ULTRA_LOW; - break; - - case 1: - clk_state = DM_PP_CLOCKS_STATE_LOW; - break; - - case 2: - clk_state = DM_PP_CLOCKS_STATE_NOMINAL; - break; - - case 3: - clk_state = DM_PP_CLOCKS_STATE_PERFORMANCE; - break; - - default: - clk_state = DM_PP_CLOCKS_STATE_INVALID; - break; - } - - /*Do not allow bad VBIOS/SBIOS to override with invalid values, - * check for > 100MHz*/ - if (info.disp_clk_voltage[i].max_supported_clk >= 100000) { - max_clks_by_state[clk_state].display_clk_khz = - info.disp_clk_voltage[i].max_supported_clk; - } - } - - disp_clk->dfs_bypass_enabled = false; - if (!debug->disable_dfs_bypass) - if (bp->integrated_info->gpu_cap_info & DFS_BYPASS_ENABLE) - disp_clk->dfs_bypass_enabled = true; - - disp_clk->use_max_disp_clk = debug->max_disp_clk; - - return true; -} - -static enum dm_pp_clocks_state get_required_clocks_state( - struct display_clock *dc, - struct state_dependent_clocks *req_clocks) -{ - int32_t i; - struct display_clock_dce110 *disp_clk = DCLCK110_FROM_BASE(dc); - enum dm_pp_clocks_state low_req_clk = dc->max_clks_state; - - if (!req_clocks) { - /* NULL pointer*/ - dm_logger_write(dc->ctx->logger, LOG_WARNING, - "%s: Invalid parameter", - __func__); - return DM_PP_CLOCKS_STATE_INVALID; - } - - /* Iterate from highest supported to lowest valid state, and update - * lowest RequiredState with the lowest state that satisfies - * all required clocks - */ - for (i = dc->max_clks_state; i >= DM_PP_CLOCKS_STATE_ULTRA_LOW; --i) { - if ((req_clocks->display_clk_khz <= - max_clks_by_state[i].display_clk_khz) && - (req_clocks->pixel_clk_khz <= - max_clks_by_state[i].pixel_clk_khz)) - low_req_clk = i; - } - return low_req_clk; -} - -static void psr_wait_loop(struct dc_context *ctx, unsigned int display_clk_khz) -{ - unsigned int dmcu_max_retry_on_wait_reg_ready = 801; - unsigned int dmcu_wait_reg_ready_interval = 100; - unsigned int regValue; - uint32_t masterCmd; - uint32_t masterComCntl; - union dce110_dmcu_psr_config_data_wait_loop_reg1 masterCmdData1; - - /* waitDMCUReadyForCmd */ - do { - dm_delay_in_microseconds(ctx, dmcu_wait_reg_ready_interval); - regValue = dm_read_reg(ctx, mmMASTER_COMM_CNTL_REG); - dmcu_max_retry_on_wait_reg_ready--; - } while - /* expected value is 0, loop while not 0*/ - ((MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK & regValue) && - dmcu_max_retry_on_wait_reg_ready > 0); - - masterCmdData1.u32All = 0; - masterCmdData1.bits.waitLoop = display_clk_khz / 1000 / 7; - dm_write_reg(ctx, mmMASTER_COMM_DATA_REG1, masterCmdData1.u32All); - - /* setDMCUParam_Cmd */ - masterCmd = dm_read_reg(ctx, mmMASTER_COMM_CMD_REG); - set_reg_field_value( - masterCmd, - PSR_SET_WAITLOOP, - MASTER_COMM_CMD_REG, - MASTER_COMM_CMD_REG_BYTE0); - - dm_write_reg(ctx, mmMASTER_COMM_CMD_REG, masterCmd); - - /* notifyDMCUMsg */ - masterComCntl = dm_read_reg(ctx, mmMASTER_COMM_CNTL_REG); - set_reg_field_value( - masterComCntl, - 1, - MASTER_COMM_CNTL_REG, - MASTER_COMM_INTERRUPT); - dm_write_reg(ctx, mmMASTER_COMM_CNTL_REG, masterComCntl); -} - -static void dce110_set_clock( - struct display_clock *base, - uint32_t requested_clk_khz) -{ - struct bp_pixel_clock_parameters pxl_clk_params; - struct display_clock_dce110 *dc = DCLCK110_FROM_BASE(base); - struct dc_bios *bp = base->ctx->dc_bios; - - /* Prepare to program display clock*/ - memset(&pxl_clk_params, 0, sizeof(pxl_clk_params)); - - /* Make sure requested clock isn't lower than minimum threshold*/ - if (requested_clk_khz > 0) - requested_clk_khz = dm_max(requested_clk_khz, - base->min_display_clk_threshold_khz); - - pxl_clk_params.target_pixel_clock = requested_clk_khz; - pxl_clk_params.pll_id = CLOCK_SOURCE_ID_DFS; - - bp->funcs->program_display_engine_pll(bp, &pxl_clk_params); - - if (dc->dfs_bypass_enabled) { - - /* Cache the fixed display clock*/ - dc->dfs_bypass_disp_clk = - pxl_clk_params.dfs_bypass_display_clock; - } - - /* from power down, we need mark the clock state as ClocksStateNominal - * from HWReset, so when resume we will call pplib voltage regulator.*/ - if (requested_clk_khz == 0) - base->cur_min_clks_state = DM_PP_CLOCKS_STATE_NOMINAL; - - psr_wait_loop(base->ctx, requested_clk_khz); -} - - -static const struct display_clock_funcs funcs = { - .destroy = destroy, - .get_dp_ref_clk_frequency = get_dp_ref_clk_frequency, - .get_required_clocks_state = get_required_clocks_state, - .set_clock = dce110_set_clock, - .set_min_clocks_state = dce110_set_min_clocks_state -}; - -static bool dal_display_clock_dce110_construct( - struct display_clock_dce110 *dc110, - struct dc_context *ctx) -{ - struct display_clock *dc_base = &dc110->disp_clk_base; - struct dc_bios *bp = ctx->dc_bios; - - dc_base->ctx = ctx; - dc_base->min_display_clk_threshold_khz = 0; - - dc_base->cur_min_clks_state = DM_PP_CLOCKS_STATE_INVALID; - - dc_base->funcs = &funcs; - - dc110->dfs_bypass_disp_clk = 0; - - if (!display_clock_integrated_info_construct(dc110)) - dm_logger_write(dc_base->ctx->logger, LOG_WARNING, - "Cannot obtain VBIOS integrated info\n"); - - dc110->gpu_pll_ss_percentage = 0; - dc110->gpu_pll_ss_divider = 1000; - dc110->ss_on_gpu_pll = false; - -/* Initially set max clocks state to nominal. This should be updated by - * via a pplib call to DAL IRI eventually calling a - * DisplayEngineClock_Dce110::StoreMaxClocksState(). This call will come in - * on PPLIB init. This is from DCE5x. in case HW wants to use mixed method.*/ - dc_base->max_clks_state = DM_PP_CLOCKS_STATE_NOMINAL; - - dal_divider_range_construct( - ÷r_ranges[DIVIDER_RANGE_01], - DIVIDER_RANGE_01_START, - DIVIDER_RANGE_01_STEP_SIZE, - DIVIDER_RANGE_01_BASE_DIVIDER_ID, - DIVIDER_RANGE_02_BASE_DIVIDER_ID); - dal_divider_range_construct( - ÷r_ranges[DIVIDER_RANGE_02], - DIVIDER_RANGE_02_START, - DIVIDER_RANGE_02_STEP_SIZE, - DIVIDER_RANGE_02_BASE_DIVIDER_ID, - DIVIDER_RANGE_03_BASE_DIVIDER_ID); - dal_divider_range_construct( - ÷r_ranges[DIVIDER_RANGE_03], - DIVIDER_RANGE_03_START, - DIVIDER_RANGE_03_STEP_SIZE, - DIVIDER_RANGE_03_BASE_DIVIDER_ID, - DIVIDER_RANGE_MAX_DIVIDER_ID); - - { - uint32_t ss_info_num = - bp->funcs->get_ss_entry_number(bp, - AS_SIGNAL_TYPE_GPU_PLL); - - if (ss_info_num) { - struct spread_spectrum_info info; - enum bp_result result; - - memset(&info, 0, sizeof(info)); - - result = bp->funcs->get_spread_spectrum_info(bp, - AS_SIGNAL_TYPE_GPU_PLL, - 0, - &info); - - /* Based on VBIOS, VBIOS will keep entry for GPU PLL SS - * even if SS not enabled and in that case - * SSInfo.spreadSpectrumPercentage !=0 would be sign - * that SS is enabled - */ - if (result == BP_RESULT_OK && - info.spread_spectrum_percentage != 0) { - dc110->ss_on_gpu_pll = true; - dc110->gpu_pll_ss_divider = - info.spread_percentage_divider; - - if (info.type.CENTER_MODE == 0) { - /* Currently for DP Reference clock we - * need only SS percentage for - * downspread */ - dc110->gpu_pll_ss_percentage = - info.spread_spectrum_percentage; - } - } - - } - } - - return true; -} - -/***************************************************************************** - * public functions - *****************************************************************************/ - -struct display_clock *dal_display_clock_dce110_create( - struct dc_context *ctx) -{ - struct display_clock_dce110 *dc110; - - dc110 = dm_alloc(sizeof(struct display_clock_dce110)); - - if (dc110 == NULL) - return NULL; - - if (dal_display_clock_dce110_construct(dc110, ctx)) - return &dc110->disp_clk_base; - - dm_free(dc110); - - return NULL; -} diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.h b/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.h deleted file mode 100644 index 50b51c41b0d9..000000000000 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ -#ifndef __DAL_DISPLAY_CLOCK_DCE110_H__ -#define __DAL_DISPLAY_CLOCK_DCE110_H__ - -#include "display_clock_interface.h" - -struct display_clock_dce110 { - struct display_clock disp_clk_base; - bool use_max_disp_clk; - uint32_t dentist_vco_freq_khz; - /* Cache the status of DFS-bypass feature*/ - bool dfs_bypass_enabled; - /* GPU PLL SS percentage (if down-spread enabled) */ - uint32_t gpu_pll_ss_percentage; - /* GPU PLL SS percentage Divider (100 or 1000) */ - uint32_t gpu_pll_ss_divider; - /* Flag for Enabled SS on GPU PLL */ - bool ss_on_gpu_pll; - /* Cache the display clock returned by VBIOS if DFS-bypass is enabled. - * This is basically "Crystal Frequency In KHz" (XTALIN) frequency */ - uint32_t dfs_bypass_disp_clk; -}; - -#define DCLCK110_FROM_BASE(dc_base) \ - container_of(dc_base, struct display_clock_dce110, disp_clk_base) - -#endif /* __DAL_DISPLAY_CLOCK_DCE110_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c index 930548bdd8b2..e0d67fb6c633 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c @@ -71,102 +71,6 @@ enum divider_range_step_size { static struct divider_range divider_ranges[DIVIDER_RANGE_MAX]; -#define dce112_DFS_BYPASS_THRESHOLD_KHZ 400000 - -static bool dce112_set_min_clocks_state( - struct display_clock *dc, - enum dm_pp_clocks_state clocks_state) -{ - struct dm_pp_power_level_change_request level_change_req = { - clocks_state }; - - if (clocks_state > dc->max_clks_state) { - /*Requested state exceeds max supported state.*/ - dm_logger_write(dc->ctx->logger, LOG_WARNING, - "Requested state exceeds max supported state"); - return false; - } else if (clocks_state == dc->cur_min_clks_state) { - /*if we're trying to set the same state, we can just return - * since nothing needs to be done*/ - return true; - } - - /* get max clock state from PPLIB */ - if (dm_pp_apply_power_level_change_request(dc->ctx, &level_change_req)) - dc->cur_min_clks_state = clocks_state; - - return true; -} - -static uint32_t get_dp_ref_clk_frequency(struct display_clock *dc) -{ - uint32_t dispclk_cntl_value; - uint32_t dp_ref_clk_cntl_value; - uint32_t dp_ref_clk_cntl_src_sel_value; - uint32_t dp_ref_clk_khz = 600000; - uint32_t target_div = INVALID_DIVIDER; - struct display_clock_dce112 *disp_clk = FROM_DISPLAY_CLOCK(dc); - - /* ASSERT DP Reference Clock source is from DFS*/ - dp_ref_clk_cntl_value = dm_read_reg(dc->ctx, - mmDPREFCLK_CNTL); - - dp_ref_clk_cntl_src_sel_value = - get_reg_field_value( - dp_ref_clk_cntl_value, - DPREFCLK_CNTL, DPREFCLK_SRC_SEL); - - ASSERT(dp_ref_clk_cntl_src_sel_value == 0); - - /* Read the mmDENTIST_DISPCLK_CNTL to get the currently - * programmed DID DENTIST_DPREFCLK_WDIVIDER*/ - dispclk_cntl_value = dm_read_reg(dc->ctx, - mmDENTIST_DISPCLK_CNTL); - - /* Convert DENTIST_DPREFCLK_WDIVIDERto actual divider*/ - target_div = dal_divider_range_get_divider( - divider_ranges, - DIVIDER_RANGE_MAX, - get_reg_field_value(dispclk_cntl_value, - DENTIST_DISPCLK_CNTL, - DENTIST_DPREFCLK_WDIVIDER)); - - if (target_div != INVALID_DIVIDER) { - /* Calculate the current DFS clock, in kHz.*/ - dp_ref_clk_khz = (DIVIDER_RANGE_SCALE_FACTOR - * disp_clk->dentist_vco_freq_khz) / target_div; - } - - /* SW will adjust DP REF Clock average value for all purposes - * (DP DTO / DP Audio DTO and DP GTC) - if clock is spread for all cases: - -if SS enabled on DP Ref clock and HW de-spreading enabled with SW - calculations for DS_INCR/DS_MODULO (this is planned to be default case) - -if SS enabled on DP Ref clock and HW de-spreading enabled with HW - calculations (not planned to be used, but average clock should still - be valid) - -if SS enabled on DP Ref clock and HW de-spreading disabled - (should not be case with CIK) then SW should program all rates - generated according to average value (case as with previous ASICs) - */ - if ((disp_clk->ss_on_gpu_pll) && (disp_clk->gpu_pll_ss_divider != 0)) { - struct fixed32_32 ss_percentage = dal_fixed32_32_div_int( - dal_fixed32_32_from_fraction( - disp_clk->gpu_pll_ss_percentage, - disp_clk->gpu_pll_ss_divider), 200); - struct fixed32_32 adj_dp_ref_clk_khz; - - ss_percentage = dal_fixed32_32_sub(dal_fixed32_32_one, - ss_percentage); - adj_dp_ref_clk_khz = - dal_fixed32_32_mul_int( - ss_percentage, - dp_ref_clk_khz); - dp_ref_clk_khz = dal_fixed32_32_floor(adj_dp_ref_clk_khz); - } - - return dp_ref_clk_khz; -} void dispclk_dce112_destroy(struct display_clock **base) { @@ -233,38 +137,6 @@ static bool display_clock_integrated_info_construct( return true; } -enum dm_pp_clocks_state dispclk_dce112_get_required_clocks_state( - struct display_clock *dc, - struct state_dependent_clocks *req_clocks) -{ - int32_t i; - struct display_clock_dce112 *disp_clk = DCLCK112_FROM_BASE(dc); - enum dm_pp_clocks_state low_req_clk = dc->max_clks_state; - - if (!req_clocks) { - /* NULL pointer*/ - dm_logger_write(dc->ctx->logger, LOG_WARNING, - "%s: Invalid parameter", - __func__); - return DM_PP_CLOCKS_STATE_INVALID; - } - - /* Iterate from highest supported to lowest valid state, and update - * lowest RequiredState with the lowest state that satisfies - * all required clocks - */ - for (i = dc->max_clks_state; i >= DM_PP_CLOCKS_STATE_ULTRA_LOW; --i) { - if ((req_clocks->display_clk_khz <= - (disp_clk->max_clks_by_state + i)-> - display_clk_khz) && - (req_clocks->pixel_clk_khz <= - (disp_clk->max_clks_by_state + i)-> - pixel_clk_khz)) - low_req_clk = i; - } - return low_req_clk; -} - void dce112_set_clock( struct display_clock *base, uint32_t requested_clk_khz) @@ -304,10 +176,7 @@ void dce112_set_clock( static const struct display_clock_funcs funcs = { .destroy = dispclk_dce112_destroy, - .get_dp_ref_clk_frequency = get_dp_ref_clk_frequency, - .get_required_clocks_state = dispclk_dce112_get_required_clocks_state, .set_clock = dce112_set_clock, - .set_min_clocks_state = dce112_set_min_clocks_state }; bool dal_display_clock_dce112_construct( @@ -406,24 +275,3 @@ bool dal_display_clock_dce112_construct( return true; } -/***************************************************************************** - * public functions - *****************************************************************************/ - -struct display_clock *dal_display_clock_dce112_create( - struct dc_context *ctx) -{ - struct display_clock_dce112 *dc112; - - dc112 = dm_alloc(sizeof(struct display_clock_dce112)); - - if (dc112 == NULL) - return NULL; - - if (dal_display_clock_dce112_construct(dc112, ctx)) - return &dc112->disp_clk_base; - - dm_free(dc112); - - return NULL; -} diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h index b750bb1766bd..0743c514a60f 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h @@ -71,23 +71,9 @@ bool dal_display_clock_dce112_construct( void dispclk_dce112_destroy(struct display_clock **base); -enum dm_pp_clocks_state dispclk_dce112_get_min_clocks_state( - struct display_clock *base); - -enum dm_pp_clocks_state dispclk_dce112_get_required_clocks_state( - struct display_clock *dc, - struct state_dependent_clocks *req_clocks); - void dce112_set_clock( struct display_clock *base, uint32_t requested_clk_khz); -bool dispclk_dce112_set_min_clocks_state( - struct display_clock *base, - enum dm_pp_clocks_state clocks_state); - -void dispclk_dce112_store_max_clocks_state( - struct display_clock *base, - enum dm_pp_clocks_state max_clocks_state); #endif /* __DAL_DISPLAY_CLOCK_DCE112_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c b/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c deleted file mode 100644 index 9d7cb2cb161c..000000000000 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c +++ /dev/null @@ -1,430 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" - -#include "dce/dce_8_0_d.h" -#include "dce/dce_8_0_sh_mask.h" - -#include "include/bios_parser_interface.h" -#include "include/fixed32_32.h" -#include "include/logger_interface.h" - -#include "../divider_range.h" -#include "display_clock_dce80.h" -#include "dc.h" - -#define DCE80_DFS_BYPASS_THRESHOLD_KHZ 100000 - -/* Max clock values for each state indexed by "enum clocks_state": */ -static struct state_dependent_clocks max_clks_by_state[] = { -/* ClocksStateInvalid - should not be used */ -{ .display_clk_khz = 0, .pixel_clk_khz = 0 }, -/* ClocksStateUltraLow - not expected to be used for DCE 8.0 */ -{ .display_clk_khz = 0, .pixel_clk_khz = 0 }, -/* ClocksStateLow */ -{ .display_clk_khz = 352000, .pixel_clk_khz = 330000}, -/* ClocksStateNominal */ -{ .display_clk_khz = 600000, .pixel_clk_khz = 400000 }, -/* ClocksStatePerformance */ -{ .display_clk_khz = 600000, .pixel_clk_khz = 400000 } }; - -/* Starting point for each divider range.*/ -enum divider_range_start { - DIVIDER_RANGE_01_START = 200, /* 2.00*/ - DIVIDER_RANGE_02_START = 1600, /* 16.00*/ - DIVIDER_RANGE_03_START = 3200, /* 32.00*/ - DIVIDER_RANGE_SCALE_FACTOR = 100 /* Results are scaled up by 100.*/ -}; - -/* Ranges for divider identifiers (Divider ID or DID) - mmDENTIST_DISPCLK_CNTL.DENTIST_DISPCLK_WDIVIDER*/ -enum divider_id_register_setting { - DIVIDER_RANGE_01_BASE_DIVIDER_ID = 0X08, - DIVIDER_RANGE_02_BASE_DIVIDER_ID = 0X40, - DIVIDER_RANGE_03_BASE_DIVIDER_ID = 0X60, - DIVIDER_RANGE_MAX_DIVIDER_ID = 0X80 -}; - -/* Step size between each divider within a range. - Incrementing the DENTIST_DISPCLK_WDIVIDER by one - will increment the divider by this much.*/ -enum divider_range_step_size { - DIVIDER_RANGE_01_STEP_SIZE = 25, /* 0.25*/ - DIVIDER_RANGE_02_STEP_SIZE = 50, /* 0.50*/ - DIVIDER_RANGE_03_STEP_SIZE = 100 /* 1.00 */ -}; - -/* Array identifiers and count for the divider ranges.*/ -enum divider_range_count { - DIVIDER_RANGE_01 = 0, - DIVIDER_RANGE_02, - DIVIDER_RANGE_03, - DIVIDER_RANGE_MAX /* == 3*/ -}; - -static struct divider_range divider_ranges[DIVIDER_RANGE_MAX]; - -#define FROM_DISPLAY_CLOCK(base) \ - container_of(base, struct display_clock_dce80, disp_clk) - -static void dce80_set_clock( - struct display_clock *dc, - uint32_t requested_clk_khz) -{ - struct bp_pixel_clock_parameters pxl_clk_params; - struct dc_bios *bp = dc->ctx->dc_bios; - - /* Prepare to program display clock*/ - memset(&pxl_clk_params, 0, sizeof(pxl_clk_params)); - - pxl_clk_params.target_pixel_clock = requested_clk_khz; - pxl_clk_params.pll_id = CLOCK_SOURCE_ID_DFS; - - bp->funcs->program_display_engine_pll(bp, &pxl_clk_params); - - /* from power down, we need mark the clock state as ClocksStateNominal - * from HWReset, so when resume we will call pplib voltage regulator.*/ - if (requested_clk_khz == 0) - dc->cur_min_clks_state = DM_PP_CLOCKS_STATE_NOMINAL; -} - -static enum dm_pp_clocks_state get_required_clocks_state - (struct display_clock *dc, - struct state_dependent_clocks *req_clocks) -{ - int32_t i; - enum dm_pp_clocks_state low_req_clk = dc->max_clks_state; - - if (!req_clocks) { - /* NULL pointer*/ - BREAK_TO_DEBUGGER(); - return DM_PP_CLOCKS_STATE_INVALID; - } - - /* Iterate from highest supported to lowest valid state, and update - * lowest RequiredState with the lowest state that satisfies - * all required clocks - */ - for (i = dc->max_clks_state; i >= DM_PP_CLOCKS_STATE_ULTRA_LOW; --i) { - if ((req_clocks->display_clk_khz <= - max_clks_by_state[i].display_clk_khz) && - (req_clocks->pixel_clk_khz <= - max_clks_by_state[i].pixel_clk_khz)) - low_req_clk = i; - } - return low_req_clk; -} - -static bool dce80_set_min_clocks_state( - struct display_clock *dc, - enum dm_pp_clocks_state clocks_state) -{ - struct dm_pp_power_level_change_request level_change_req = { - clocks_state }; - - if (clocks_state > dc->max_clks_state) { - /*Requested state exceeds max supported state.*/ - dm_logger_write(dc->ctx->logger, LOG_WARNING, - "Requested state exceeds max supported state"); - return false; - } else if (clocks_state == dc->cur_min_clks_state) { - /*if we're trying to set the same state, we can just return - * since nothing needs to be done*/ - return true; - } - - /* get max clock state from PPLIB */ - if (dm_pp_apply_power_level_change_request(dc->ctx, &level_change_req)) - dc->cur_min_clks_state = clocks_state; - - return true; -} - -static uint32_t get_dp_ref_clk_frequency(struct display_clock *dc) -{ - uint32_t dispclk_cntl_value; - uint32_t dp_ref_clk_cntl_value; - uint32_t dp_ref_clk_cntl_src_sel_value; - uint32_t dp_ref_clk_khz = 600000; - uint32_t target_div = INVALID_DIVIDER; - struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc); - - /* ASSERT DP Reference Clock source is from DFS*/ - dp_ref_clk_cntl_value = dm_read_reg(dc->ctx, - mmDPREFCLK_CNTL); - - dp_ref_clk_cntl_src_sel_value = - get_reg_field_value( - dp_ref_clk_cntl_value, - DPREFCLK_CNTL, DPREFCLK_SRC_SEL); - - ASSERT(dp_ref_clk_cntl_src_sel_value == 0); - - /* Read the mmDENTIST_DISPCLK_CNTL to get the currently - * programmed DID DENTIST_DPREFCLK_WDIVIDER*/ - dispclk_cntl_value = dm_read_reg(dc->ctx, - mmDENTIST_DISPCLK_CNTL); - - /* Convert DENTIST_DPREFCLK_WDIVIDERto actual divider*/ - target_div = dal_divider_range_get_divider( - divider_ranges, - DIVIDER_RANGE_MAX, - get_reg_field_value(dispclk_cntl_value, - DENTIST_DISPCLK_CNTL, - DENTIST_DPREFCLK_WDIVIDER)); - - if (target_div != INVALID_DIVIDER) { - /* Calculate the current DFS clock, in kHz.*/ - dp_ref_clk_khz = (DIVIDER_RANGE_SCALE_FACTOR - * disp_clk->dentist_vco_freq_khz) / target_div; - } - - /* SW will adjust DP REF Clock average value for all purposes - * (DP DTO / DP Audio DTO and DP GTC) - if clock is spread for all cases: - -if SS enabled on DP Ref clock and HW de-spreading enabled with SW - calculations for DS_INCR/DS_MODULO (this is planned to be default case) - -if SS enabled on DP Ref clock and HW de-spreading enabled with HW - calculations (not planned to be used, but average clock should still - be valid) - -if SS enabled on DP Ref clock and HW de-spreading disabled - (should not be case with CIK) then SW should program all rates - generated according to average value (case as with previous ASICs) - */ - if ((disp_clk->ss_on_gpu_pll) && (disp_clk->gpu_pll_ss_divider != 0)) { - struct fixed32_32 ss_percentage = dal_fixed32_32_div_int( - dal_fixed32_32_from_fraction( - disp_clk->gpu_pll_ss_percentage, - disp_clk->gpu_pll_ss_divider), 200); - struct fixed32_32 adj_dp_ref_clk_khz; - - ss_percentage = dal_fixed32_32_sub(dal_fixed32_32_one, - ss_percentage); - adj_dp_ref_clk_khz = - dal_fixed32_32_mul_int( - ss_percentage, - dp_ref_clk_khz); - dp_ref_clk_khz = dal_fixed32_32_floor(adj_dp_ref_clk_khz); - } - - return dp_ref_clk_khz; -} - -static void display_clock_ss_construct( - struct display_clock_dce80 *disp_clk) -{ - struct dc_bios *bp = disp_clk->disp_clk.ctx->dc_bios; - uint32_t ss_entry_num = bp->funcs->get_ss_entry_number(bp, - AS_SIGNAL_TYPE_GPU_PLL); - - /*Read SS Info from VBIOS SS Info table for DP Reference Clock spread.*/ - if (ss_entry_num > 0) {/* Should be only one entry */ - struct spread_spectrum_info ss_info; - enum bp_result res; - - memset(&ss_info, 0, sizeof(struct spread_spectrum_info)); - - res = bp->funcs->get_spread_spectrum_info(bp, - AS_SIGNAL_TYPE_GPU_PLL, 0, &ss_info); - - /* Based on VBIOS, VBIOS will keep entry for GPU PLL SS even if - * SS not enabled and in that case - * SSInfo.spreadSpectrumPercentage !=0 would be - * sign that SS is enabled*/ - if (res == BP_RESULT_OK && ss_info.spread_spectrum_percentage != 0) { - disp_clk->ss_on_gpu_pll = true; - disp_clk->gpu_pll_ss_divider = - ss_info.spread_percentage_divider; - if (ss_info.type.CENTER_MODE == 0) - /* Currently we need only SS - * percentage for down-spread*/ - disp_clk->gpu_pll_ss_percentage = - ss_info.spread_spectrum_percentage; - } - } -} - -static bool display_clock_integrated_info_construct( - struct display_clock_dce80 *disp_clk) -{ - struct dc_debug *debug = &disp_clk->disp_clk.ctx->dc->debug; - struct dc_bios *bp = disp_clk->disp_clk.ctx->dc_bios; - struct integrated_info info = { { { 0 } } }; - struct firmware_info fw_info = { { 0 } }; - uint32_t i; - - if (bp->integrated_info) - info = *bp->integrated_info; - - disp_clk->dentist_vco_freq_khz = info.dentist_vco_freq; - if (disp_clk->dentist_vco_freq_khz == 0) { - bp->funcs->get_firmware_info(bp, &fw_info); - disp_clk->dentist_vco_freq_khz = - fw_info.smu_gpu_pll_output_freq; - if (disp_clk->dentist_vco_freq_khz == 0) - disp_clk->dentist_vco_freq_khz = 3600000; - } - disp_clk->disp_clk.min_display_clk_threshold_khz = - disp_clk->dentist_vco_freq_khz / 64; - - /* TODO: initialise disp_clk->dfs_bypass_disp_clk */ - - /*update the maximum display clock for each power state*/ - for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) { - enum dm_pp_clocks_state clk_state = DM_PP_CLOCKS_STATE_INVALID; - - switch (i) { - case 0: - clk_state = DM_PP_CLOCKS_STATE_ULTRA_LOW; - break; - - case 1: - clk_state = DM_PP_CLOCKS_STATE_LOW; - break; - - case 2: - clk_state = DM_PP_CLOCKS_STATE_NOMINAL; - break; - - case 3: - clk_state = DM_PP_CLOCKS_STATE_PERFORMANCE; - break; - - default: - clk_state = DM_PP_CLOCKS_STATE_INVALID; - break; - } - - /*Do not allow bad VBIOS/SBIOS to override with invalid values, - * check for > 100MHz*/ - if (info.disp_clk_voltage[i].max_supported_clk >= 100000) { - max_clks_by_state[clk_state].display_clk_khz = - info.disp_clk_voltage[i].max_supported_clk; - } - } - - disp_clk->dfs_bypass_enabled = false; - if (!debug->disable_dfs_bypass) - if (bp->integrated_info->gpu_cap_info & DFS_BYPASS_ENABLE) - disp_clk->dfs_bypass_enabled = true; - - disp_clk->use_max_disp_clk = debug->max_disp_clk; - - return true; -} - -static void destroy(struct display_clock **dc) -{ - struct display_clock_dce80 *disp_clk; - - disp_clk = FROM_DISPLAY_CLOCK(*dc); - dm_free(disp_clk); - *dc = NULL; -} - -static const struct display_clock_funcs funcs = { - .destroy = destroy, - .get_dp_ref_clk_frequency = get_dp_ref_clk_frequency, - .get_required_clocks_state = get_required_clocks_state, - .set_clock = dce80_set_clock, - .set_min_clocks_state = dce80_set_min_clocks_state -}; - - -struct display_clock *dal_display_clock_dce80_create( - struct dc_context *ctx) -{ - struct display_clock_dce80 *disp_clk; - struct display_clock *dc_base; - - disp_clk = dm_alloc(sizeof(struct display_clock_dce80)); - - if (disp_clk == NULL) - return NULL; - - dc_base = &disp_clk->disp_clk; - - dc_base->ctx = ctx; - dc_base->min_display_clk_threshold_khz = 0; - - dc_base->cur_min_clks_state = DM_PP_CLOCKS_STATE_INVALID; - - dc_base->funcs = &funcs; - /* - * set_dp_ref_clock_source - * set_clock_state - * get_clock_state - * get_dfs_bypass_threshold - */ - - disp_clk->gpu_pll_ss_percentage = 0; - disp_clk->gpu_pll_ss_divider = 1000; - disp_clk->ss_on_gpu_pll = false; - disp_clk->dfs_bypass_enabled = false; - disp_clk->dfs_bypass_disp_clk = 0; - disp_clk->use_max_disp_clk = true;/* false will hang the system! */ - -/* Initially set max clocks state to nominal. This should be updated by - * via a pplib call to DAL IRI eventually calling a - * DisplayEngineClock_Dce50::StoreMaxClocksState(). This call will come in - * on PPLIB init. This is from DCE5x. in case HW wants to use mixed method.*/ - dc_base->max_clks_state = DM_PP_CLOCKS_STATE_NOMINAL; -/* Initially set current min clocks state to invalid since we - * cannot make any assumption about PPLIB's initial state. This will be updated - * by HWSS via SetMinClocksState() on first mode set prior to programming - * state dependent clocks.*/ - disp_clk->cur_min_clks_state = DM_PP_CLOCKS_STATE_INVALID; - - display_clock_ss_construct(disp_clk); - - if (!display_clock_integrated_info_construct(disp_clk)) { - dm_logger_write(dc_base->ctx->logger, LOG_WARNING, - "Cannot obtain VBIOS integrated info"); - } - - dal_divider_range_construct( - ÷r_ranges[DIVIDER_RANGE_01], - DIVIDER_RANGE_01_START, - DIVIDER_RANGE_01_STEP_SIZE, - DIVIDER_RANGE_01_BASE_DIVIDER_ID, - DIVIDER_RANGE_02_BASE_DIVIDER_ID); - dal_divider_range_construct( - ÷r_ranges[DIVIDER_RANGE_02], - DIVIDER_RANGE_02_START, - DIVIDER_RANGE_02_STEP_SIZE, - DIVIDER_RANGE_02_BASE_DIVIDER_ID, - DIVIDER_RANGE_03_BASE_DIVIDER_ID); - dal_divider_range_construct( - ÷r_ranges[DIVIDER_RANGE_03], - DIVIDER_RANGE_03_START, - DIVIDER_RANGE_03_STEP_SIZE, - DIVIDER_RANGE_03_BASE_DIVIDER_ID, - DIVIDER_RANGE_MAX_DIVIDER_ID); - - dm_free(disp_clk); - return NULL; -} - diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.h b/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.h deleted file mode 100644 index c155bb6a4321..000000000000 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ -#ifndef __DAL_DISPLAY_CLOCK_DCE80_H__ -#define __DAL_DISPLAY_CLOCK_DCE80_H__ - -#include "display_clock_interface.h" - -struct display_clock_dce80 { - struct display_clock disp_clk; - /* DFS input - GPUPLL VCO frequency - from VBIOS Firmware info. */ - uint32_t dentist_vco_freq_khz; - /* GPU PLL SS percentage (if down-spread enabled)*/ - uint32_t gpu_pll_ss_percentage; - /* GPU PLL SS percentage Divider (100 or 1000)*/ - uint32_t gpu_pll_ss_divider; - /* Flag for Enabled SS on GPU PLL*/ - bool ss_on_gpu_pll; - /* Current minimum display block clocks state*/ - enum dm_pp_clocks_state cur_min_clks_state; - /* DFS-bypass feature variable - Cache the status of DFS-bypass feature*/ - bool dfs_bypass_enabled; - /* Cache the display clock returned by VBIOS if DFS-bypass is enabled. - * This is basically "Crystal Frequency In KHz" (XTALIN) frequency */ - uint32_t dfs_bypass_disp_clk; - bool use_max_disp_clk; -}; - -struct display_clock *dal_display_clock_dce80_create( - struct dc_context *ctx); - -#endif /* __DAL_DISPLAY_CLOCK_DCE80_H__ */ diff --git a/drivers/gpu/drm/amd/display/include/display_clock_interface.h b/drivers/gpu/drm/amd/display/include/display_clock_interface.h index 6ba8c093793d..53a01381c638 100644 --- a/drivers/gpu/drm/amd/display/include/display_clock_interface.h +++ b/drivers/gpu/drm/amd/display/include/display_clock_interface.h @@ -41,10 +41,9 @@ struct state_dependent_clocks { struct display_clock { struct dc_context *ctx; const struct display_clock_funcs *funcs; - uint32_t min_display_clk_threshold_khz; - /* Max display block clocks state*/ - enum dm_pp_clocks_state max_clks_state; + int min_display_clk_threshold_khz; + enum dm_pp_clocks_state max_clks_state; enum dm_pp_clocks_state cur_min_clks_state; }; @@ -61,15 +60,7 @@ struct display_clock_funcs { }; -struct display_clock *dal_display_clock_dce112_create( - struct dc_context *ctx); - -struct display_clock *dal_display_clock_dce110_create( - struct dc_context *ctx); - -struct display_clock *dal_display_clock_dce80_create( - struct dc_context *ctx); - void dal_display_clock_destroy(struct display_clock **to_destroy); + #endif /* __DISPLAY_CLOCK_INTERFACE_H__ */ -- cgit From 8318a7eb988c62fa231c71538628ba85d4fbe7ef Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 2 Dec 2016 10:55:32 -0500 Subject: drm/amd/display: add newline to generic_reg_wait timeout message Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc_helper.c b/drivers/gpu/drm/amd/display/dc/dc_helper.c index 3a80b0c08ae4..c5ff7b6d733d 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_helper.c +++ b/drivers/gpu/drm/amd/display/dc/dc_helper.c @@ -138,7 +138,7 @@ uint32_t generic_reg_wait(const struct dc_context *ctx, return reg_val; } - DC_ERR("REG_WAIT timeout %dus * %d tries - %s", + DC_ERR("REG_WAIT timeout %dus * %d tries - %s\n", delay_between_poll_us, time_out_num_tries, func_name); return reg_val; } -- cgit From 85944914f1de9b12fb2867f8dd835835f08861a2 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 2 Dec 2016 17:41:42 -0500 Subject: drm/amd/display: fix display clock integrated info read Signed-off-by: Dmytro Laktyushkin Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c index 77033fe8a8e5..846754c16831 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c @@ -342,7 +342,7 @@ static void dce_clock_read_integrated_info(struct dce_disp_clk *clk_dce) info.disp_clk_voltage[i].max_supported_clk; } - if (!debug->disable_dfs_bypass) + if (!debug->disable_dfs_bypass && bp->integrated_info) if (bp->integrated_info->gpu_cap_info & DFS_BYPASS_ENABLE) clk_dce->dfs_bypass_enabled = true; -- cgit From b007045674723f649e8a9cf0504dc987a141160d Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Wed, 30 Nov 2016 17:57:24 -0500 Subject: drm/amd/display: use rgb full range as default quantization for non HDMI Refactor the quantization decision to color module. Add the check if non HDMI, default quantization should be rgb full range. Signed-off-by: Wenjing Liu Reviewed-by: Tony Cheng Reviewed-by: Anthony Koo Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/modules/color/color.c | 88 ++++++++++++++++++++-- .../gpu/drm/amd/display/modules/inc/mod_color.h | 12 ++- 2 files changed, 94 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/modules/color/color.c b/drivers/gpu/drm/amd/display/modules/color/color.c index 30d09d358576..0610b82b6d84 100644 --- a/drivers/gpu/drm/amd/display/modules/color/color.c +++ b/drivers/gpu/drm/amd/display/modules/color/color.c @@ -2184,7 +2184,8 @@ bool mod_color_set_saturation(struct mod_color *mod_color, return true; } -bool mod_color_set_preferred_quantization_range(struct mod_color *mod_color, +bool mod_color_persist_user_preferred_quantization_range( + struct mod_color *mod_color, const struct dc_sink *sink, enum dc_quantization_range quantization_range) { @@ -2214,13 +2215,90 @@ bool mod_color_set_preferred_quantization_range(struct mod_color *mod_color, bool mod_color_get_preferred_quantization_range(struct mod_color *mod_color, const struct dc_sink *sink, + const struct dc_crtc_timing *timing, enum dc_quantization_range *quantization_range) { struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - unsigned int sink_index; + unsigned int sink_index = sink_index_from_sink(core_color, sink); + enum dc_quantization_range user_preferred_quantization_range = + core_color->state[sink_index]. + preferred_quantization_range; + bool rgb_full_range_supported = + mod_color_is_rgb_full_range_supported_for_timing( + sink, timing); + bool rgb_limited_range_supported = + mod_color_is_rgb_limited_range_supported_for_timing( + sink, timing); + + if (rgb_full_range_supported && rgb_limited_range_supported) + *quantization_range = user_preferred_quantization_range; + else if (rgb_full_range_supported && !rgb_limited_range_supported) + *quantization_range = QUANTIZATION_RANGE_FULL; + else if (!rgb_full_range_supported && rgb_limited_range_supported) + *quantization_range = QUANTIZATION_RANGE_LIMITED; + else + *quantization_range = QUANTIZATION_RANGE_UNKNOWN; - sink_index = sink_index_from_sink(core_color, sink); - *quantization_range = core_color->state[sink_index]. - preferred_quantization_range; return true; } + +bool mod_color_is_rgb_full_range_supported_for_timing( + const struct dc_sink *sink, + const struct dc_crtc_timing *timing) +{ + bool result = false; + + if (!sink || !timing) + return result; + + if (sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A) + if (timing->vic || timing->hdmi_vic) + if (timing->h_addressable == 640 && + timing->v_addressable == 480 && + (timing->pix_clk_khz == 25200 || + timing->pix_clk_khz == 25170 || + timing->pix_clk_khz == 25175)) + result = true; + else + /* don't support full range rgb */ + /* for HDMI CEA861 timings except VGA mode */ + result = false; + else + result = true; + else + result = true; + + return result; +} + +bool mod_color_is_rgb_limited_range_supported_for_timing( + const struct dc_sink *sink, + const struct dc_crtc_timing *timing) +{ + bool result = false; + + if (!sink || !timing) + return result; + + if (sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A) + if (timing->vic || timing->hdmi_vic) + if (timing->h_addressable == 640 && + timing->v_addressable == 480 && + (timing->pix_clk_khz == 25200 || + timing->pix_clk_khz == 25170 || + timing->pix_clk_khz == 25175)) + /* don't support rgb limited for */ + /* HDMI CEA VGA mode */ + result = false; + else + /* support rgb limited for non VGA CEA timing */ + result = true; + else + /* support rgb limited for non CEA HDMI timing */ + result = true; + else + /* don't support rgb limited for non HDMI signal */ + result = false; + + return result; +} diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_color.h b/drivers/gpu/drm/amd/display/modules/inc/mod_color.h index e54fe2cb8611..91abc173444a 100644 --- a/drivers/gpu/drm/amd/display/modules/inc/mod_color.h +++ b/drivers/gpu/drm/amd/display/modules/inc/mod_color.h @@ -168,12 +168,22 @@ bool mod_color_set_saturation(struct mod_color *mod_color, const struct dc_stream **streams, int num_streams, int saturation_value); -bool mod_color_set_preferred_quantization_range(struct mod_color *mod_color, +bool mod_color_persist_user_preferred_quantization_range( + struct mod_color *mod_color, const struct dc_sink *sink, enum dc_quantization_range quantization_range); bool mod_color_get_preferred_quantization_range(struct mod_color *mod_color, const struct dc_sink *sink, + const struct dc_crtc_timing *timing, enum dc_quantization_range *quantization_range); +bool mod_color_is_rgb_full_range_supported_for_timing( + const struct dc_sink *sink, + const struct dc_crtc_timing *timing); + +bool mod_color_is_rgb_limited_range_supported_for_timing( + const struct dc_sink *sink, + const struct dc_crtc_timing *timing); + #endif /* MOD_COLOR_H_ */ -- cgit From 13625c7bf328c9e201363eba3c3e5a15560c4ae9 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Tue, 29 Nov 2016 13:11:08 -0500 Subject: drm/amd/display: create scratch_val_ctx as temp w/a Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 5 ++++- drivers/gpu/drm/amd/display/dc/inc/core_dc.h | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 70dc70685471..a3c5def507a9 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -452,6 +452,8 @@ static void destruct(struct core_dc *dc) dm_free(dc->temp_flip_context); dc->temp_flip_context = NULL; + dm_free(dc->scratch_val_ctx); + dc->scratch_val_ctx = NULL; destroy_links(dc); @@ -490,6 +492,7 @@ static bool construct(struct core_dc *dc, dc->current_context = dm_alloc(sizeof(*dc->current_context)); dc->temp_flip_context = dm_alloc(sizeof(*dc->temp_flip_context)); + dc->scratch_val_ctx = dm_alloc(sizeof(*dc->temp_flip_context)); if (!dc->current_context || !dc->temp_flip_context) { dm_error("%s: failed to create validate ctx\n", __func__); @@ -1217,7 +1220,7 @@ bool dc_pre_update_surfaces_to_target( goto unexpected_fail; } resource_validate_ctx_destruct(context); - dm_free(context); + core_dc->scratch_val_ctx = context; context = temp_context; } diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_dc.h b/drivers/gpu/drm/amd/display/dc/inc/core_dc.h index 7d6dc8ea75ab..b5a5207a4df0 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_dc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_dc.h @@ -24,6 +24,7 @@ struct core_dc { /* TODO: determine max number of targets*/ struct validate_context *current_context; struct validate_context *temp_flip_context; + struct validate_context *scratch_val_ctx; struct resource_pool *res_pool; /*Power State*/ -- cgit From e91dbe3dee1acae4909bcc33288d47a779e8b27f Mon Sep 17 00:00:00 2001 From: Ding Wang Date: Mon, 5 Dec 2016 18:20:51 -0500 Subject: drm/amd/display: Temporarily blocking interlacing mode until it's supported. Signed-off-by: Ding Wang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c index 12a258763ef1..e70704d1ba87 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c @@ -1117,6 +1117,10 @@ bool dce110_timing_generator_validate_timing( if (timing->timing_3d_format != TIMING_3D_FORMAT_NONE) return false; + /* Temporarily blocking interlacing mode until it's supported */ + if (timing->flags.INTERLACE == 1) + return false; + /* Check maximum number of pixels supported by Timing Generator * (Currently will never fail, in order to fail needs display which * needs more than 8192 horizontal and -- cgit From e11b86ad7d97671ec9543824de0529bd3f8d2db7 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 2 Dec 2016 14:48:04 -0500 Subject: drm/amd/display: moving remaining functionality from gpu to dce_clocks Signed-off-by: Dmytro Laktyushkin Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/Makefile | 7 +- drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c | 183 ++++++++++++-- drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h | 36 ++- drivers/gpu/drm/amd/display/dc/gpu/Makefile | 21 -- .../display/dc/gpu/dce112/display_clock_dce112.c | 277 --------------------- .../display/dc/gpu/dce112/display_clock_dce112.h | 79 ------ drivers/gpu/drm/amd/display/dc/gpu/divider_range.c | 127 ---------- drivers/gpu/drm/amd/display/dc/gpu/divider_range.h | 62 ----- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 2 +- .../gpu/drm/amd/display/dc/inc/hw/display_clock.h | 61 +++++ .../amd/display/include/display_clock_interface.h | 66 ----- 11 files changed, 257 insertions(+), 664 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/dc/gpu/Makefile delete mode 100644 drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c delete mode 100644 drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h delete mode 100644 drivers/gpu/drm/amd/display/dc/gpu/divider_range.c delete mode 100644 drivers/gpu/drm/amd/display/dc/gpu/divider_range.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h delete mode 100644 drivers/gpu/drm/amd/display/include/display_clock_interface.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/Makefile b/drivers/gpu/drm/amd/display/dc/Makefile index 5fac034093e9..26e2b50e4954 100644 --- a/drivers/gpu/drm/amd/display/dc/Makefile +++ b/drivers/gpu/drm/amd/display/dc/Makefile @@ -2,8 +2,7 @@ # Makefile for Display Core (dc) component. # -DC_LIBS = basics bios calcs dce \ -gpio gpu i2caux irq virtual +DC_LIBS = basics bios calcs dce gpio i2caux irq virtual DC_LIBS += dce112 DC_LIBS += dce110 @@ -14,8 +13,8 @@ AMD_DC = $(addsuffix /Makefile, $(addprefix $(FULL_AMD_DISPLAY_PATH)/dc/,$(DC_LI include $(AMD_DC) -DISPLAY_CORE = dc.o dc_link.o dc_resource.o dc_hw_sequencer.o dc_target.o dc_sink.o dc_stream.o \ -dc_surface.o dc_link_hwss.o dc_link_dp.o dc_link_ddc.o dc_debug.o +DISPLAY_CORE = dc.o dc_link.o dc_resource.o dc_hw_sequencer.o dc_target.o dc_sink.o \ +dc_surface.o dc_link_hwss.o dc_link_dp.o dc_link_ddc.o dc_debug.o dc_stream.o AMD_DISPLAY_CORE = $(addprefix $(AMDDALPATH)/dc/core/,$(DISPLAY_CORE)) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c index 846754c16831..8e2519b1c9df 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c @@ -30,6 +30,8 @@ #include "bios_parser_interface.h" #include "dc.h" +#define TO_DCE_CLOCKS(clocks)\ + container_of(clocks, struct dce_disp_clk, base) #define REG(reg) \ (clk_dce->regs->reg) @@ -41,8 +43,45 @@ #define CTX \ clk_dce->base.ctx +/* Max clock values for each state indexed by "enum clocks_state": */ +static struct state_dependent_clocks dce80_max_clks_by_state[] = { +/* ClocksStateInvalid - should not be used */ +{ .display_clk_khz = 0, .pixel_clk_khz = 0 }, +/* ClocksStateUltraLow - not expected to be used for DCE 8.0 */ +{ .display_clk_khz = 0, .pixel_clk_khz = 0 }, +/* ClocksStateLow */ +{ .display_clk_khz = 352000, .pixel_clk_khz = 330000}, +/* ClocksStateNominal */ +{ .display_clk_khz = 600000, .pixel_clk_khz = 400000 }, +/* ClocksStatePerformance */ +{ .display_clk_khz = 600000, .pixel_clk_khz = 400000 } }; + +static struct state_dependent_clocks dce110_max_clks_by_state[] = { +/*ClocksStateInvalid - should not be used*/ +{ .display_clk_khz = 0, .pixel_clk_khz = 0 }, +/*ClocksStateUltraLow - currently by HW design team not supposed to be used*/ +{ .display_clk_khz = 352000, .pixel_clk_khz = 330000 }, +/*ClocksStateLow*/ +{ .display_clk_khz = 352000, .pixel_clk_khz = 330000 }, +/*ClocksStateNominal*/ +{ .display_clk_khz = 467000, .pixel_clk_khz = 400000 }, +/*ClocksStatePerformance*/ +{ .display_clk_khz = 643000, .pixel_clk_khz = 400000 } }; + +static struct state_dependent_clocks dce112_max_clks_by_state[] = { +/*ClocksStateInvalid - should not be used*/ +{ .display_clk_khz = 0, .pixel_clk_khz = 0 }, +/*ClocksStateUltraLow - currently by HW design team not supposed to be used*/ +{ .display_clk_khz = 389189, .pixel_clk_khz = 346672 }, +/*ClocksStateLow*/ +{ .display_clk_khz = 459000, .pixel_clk_khz = 400000 }, +/*ClocksStateNominal*/ +{ .display_clk_khz = 667000, .pixel_clk_khz = 600000 }, +/*ClocksStatePerformance*/ +{ .display_clk_khz = 1132000, .pixel_clk_khz = 600000 } }; + /* Starting point for each divider range.*/ -enum divider_range_start { +enum dce_divider_range_start { DIVIDER_RANGE_01_START = 200, /* 2.00*/ DIVIDER_RANGE_02_START = 1600, /* 16.00*/ DIVIDER_RANGE_03_START = 3200, /* 32.00*/ @@ -51,7 +90,7 @@ enum divider_range_start { /* Ranges for divider identifiers (Divider ID or DID) mmDENTIST_DISPCLK_CNTL.DENTIST_DISPCLK_WDIVIDER*/ -enum divider_id_register_setting { +enum dce_divider_id_register_setting { DIVIDER_RANGE_01_BASE_DIVIDER_ID = 0X08, DIVIDER_RANGE_02_BASE_DIVIDER_ID = 0X40, DIVIDER_RANGE_03_BASE_DIVIDER_ID = 0X60, @@ -61,14 +100,114 @@ enum divider_id_register_setting { /* Step size between each divider within a range. Incrementing the DENTIST_DISPCLK_WDIVIDER by one will increment the divider by this much.*/ -enum divider_range_step_size { +enum dce_divider_range_step_size { DIVIDER_RANGE_01_STEP_SIZE = 25, /* 0.25*/ DIVIDER_RANGE_02_STEP_SIZE = 50, /* 0.50*/ DIVIDER_RANGE_03_STEP_SIZE = 100 /* 1.00 */ }; +static bool dce_divider_range_construct( + struct dce_divider_range *div_range, + int range_start, + int range_step, + int did_min, + int did_max) +{ + div_range->div_range_start = range_start; + div_range->div_range_step = range_step; + div_range->did_min = did_min; + div_range->did_max = did_max; + + if (div_range->div_range_step == 0) { + div_range->div_range_step = 1; + /*div_range_step cannot be zero*/ + BREAK_TO_DEBUGGER(); + } + /* Calculate this based on the other inputs.*/ + /* See DividerRange.h for explanation of */ + /* the relationship between divider id (DID) and a divider.*/ + /* Number of Divider IDs = (Maximum Divider ID - Minimum Divider ID)*/ + /* Maximum divider identified in this range = + * (Number of Divider IDs)*Step size between dividers + * + The start of this range.*/ + div_range->div_range_end = (did_max - did_min) * range_step + + range_start; + return true; +} + +static int dce_divider_range_calc_divider( + struct dce_divider_range *div_range, + int did) +{ + /* Is this DID within our range?*/ + if ((did < div_range->did_min) || (did >= div_range->did_max)) + return INVALID_DIVIDER; + + return ((did - div_range->did_min) * div_range->div_range_step) + + div_range->div_range_start; + +} + +static int dce_divider_range_calc_did( + struct dce_divider_range *div_range, + int div) +{ + int did; + /* Check before dividing.*/ + if (div_range->div_range_step == 0) { + div_range->div_range_step = 1; + /*div_range_step cannot be zero*/ + BREAK_TO_DEBUGGER(); + } + /* Is this divider within our range?*/ + if ((div < div_range->div_range_start) + || (div >= div_range->div_range_end)) + return INVALID_DID; +/* did = (divider - range_start + (range_step-1)) / range_step) + did_min*/ + did = div - div_range->div_range_start; + did += div_range->div_range_step - 1; + did /= div_range->div_range_step; + did += div_range->did_min; + return did; +} + +static int dce_divider_range_get_divider( + struct dce_divider_range *div_range, + int ranges_num, + int did) +{ + int div = INVALID_DIVIDER; + int i; -static uint32_t dce_clocks_get_dp_ref_freq(struct display_clock *clk) + for (i = 0; i < ranges_num; i++) { + /* Calculate divider with given divider ID*/ + div = dce_divider_range_calc_divider(&div_range[i], did); + /* Found a valid return divider*/ + if (div != INVALID_DIVIDER) + break; + } + return div; +} + +static int dce_divider_range_get_did( + struct dce_divider_range *div_range, + int ranges_num, + int divider) +{ + int did = INVALID_DID; + int i; + + for (i = 0; i < ranges_num; i++) { + /* CalcDid returns InvalidDid if a divider ID isn't found*/ + did = dce_divider_range_calc_did(&div_range[i], divider); + /* Found a valid return did*/ + if (did != INVALID_DID) + break; + } + return did; +} + +static int dce_clocks_get_dp_ref_freq(struct display_clock *clk) { struct dce_disp_clk *clk_dce = TO_DCE_CLOCKS(clk); int dprefclk_wdivider; @@ -85,7 +224,7 @@ static uint32_t dce_clocks_get_dp_ref_freq(struct display_clock *clk) REG_GET(DENTIST_DISPCLK_CNTL, DENTIST_DPREFCLK_WDIVIDER, &dprefclk_wdivider); /* Convert DENTIST_DPREFCLK_WDIVIDERto actual divider*/ - target_div = dal_divider_range_get_divider( + target_div = dce_divider_range_get_divider( clk_dce->divider_ranges, DIVIDER_RANGE_MAX, dprefclk_wdivider); @@ -183,7 +322,7 @@ static bool dce_clock_set_min_clocks_state( static void dce_set_clock( struct display_clock *clk, - uint32_t requested_clk_khz) + int requested_clk_khz) { struct dce_disp_clk *clk_dce = TO_DCE_CLOCKS(clk); struct bp_pixel_clock_parameters pxl_clk_params = { 0 }; @@ -245,7 +384,7 @@ static void dce_psr_wait_loop( static void dce_psr_set_clock( struct display_clock *clk, - uint32_t requested_clk_khz) + int requested_clk_khz) { struct dce_disp_clk *clk_dce = TO_DCE_CLOCKS(clk); @@ -253,9 +392,9 @@ static void dce_psr_set_clock( dce_psr_wait_loop(clk_dce, requested_clk_khz); } -static void polaris_set_clock( +static void dce112_set_clock( struct display_clock *clk, - uint32_t requested_clk_khz) + int requested_clk_khz) { struct dce_disp_clk *clk_dce = TO_DCE_CLOCKS(clk); struct bp_set_dce_clock_parameters dce_clk_params; @@ -267,7 +406,7 @@ static void polaris_set_clock( /* Make sure requested clock isn't lower than minimum threshold*/ if (requested_clk_khz > 0) requested_clk_khz = dm_max(requested_clk_khz, - clk_dce->dentist_vco_freq_khz / 64); + clk_dce->dentist_vco_freq_khz / 62); dce_clk_params.target_clock_frequency = requested_clk_khz; dce_clk_params.pll_id = CLOCK_SOURCE_ID_DFS; @@ -284,7 +423,9 @@ static void polaris_set_clock( /*VBIOS will determine DPREFCLK frequency, so we don't set it*/ dce_clk_params.target_clock_frequency = 0; dce_clk_params.clock_type = DCECLOCK_TYPE_DPREFCLK; - dce_clk_params.flags.USE_GENLOCK_AS_SOURCE_FOR_DPREFCLK = 0; + dce_clk_params.flags.USE_GENLOCK_AS_SOURCE_FOR_DPREFCLK = + (dce_clk_params.pll_id == + CLOCK_SOURCE_COMBO_DISPLAY_PLL0); bp->funcs->set_dce_clock(bp, &dce_clk_params); } @@ -386,7 +527,7 @@ static const struct display_clock_funcs dce112_funcs = { .get_dp_ref_clk_frequency = dce_clocks_get_dp_ref_freq, .get_required_clocks_state = dce_get_required_clocks_state, .set_min_clocks_state = dce_clock_set_min_clocks_state, - .set_clock = polaris_set_clock + .set_clock = dce112_set_clock }; static const struct display_clock_funcs dce110_funcs = { @@ -429,19 +570,19 @@ static void dce_disp_clk_construct( dce_clock_read_integrated_info(clk_dce); dce_clock_read_ss_info(clk_dce); - dal_divider_range_construct( + dce_divider_range_construct( &clk_dce->divider_ranges[DIVIDER_RANGE_01], DIVIDER_RANGE_01_START, DIVIDER_RANGE_01_STEP_SIZE, DIVIDER_RANGE_01_BASE_DIVIDER_ID, DIVIDER_RANGE_02_BASE_DIVIDER_ID); - dal_divider_range_construct( + dce_divider_range_construct( &clk_dce->divider_ranges[DIVIDER_RANGE_02], DIVIDER_RANGE_02_START, DIVIDER_RANGE_02_STEP_SIZE, DIVIDER_RANGE_02_BASE_DIVIDER_ID, DIVIDER_RANGE_03_BASE_DIVIDER_ID); - dal_divider_range_construct( + dce_divider_range_construct( &clk_dce->divider_ranges[DIVIDER_RANGE_03], DIVIDER_RANGE_03_START, DIVIDER_RANGE_03_STEP_SIZE, @@ -462,6 +603,10 @@ struct display_clock *dce_disp_clk_create( return NULL; } + memcpy(clk_dce->max_clks_by_state, + dce80_max_clks_by_state, + sizeof(dce80_max_clks_by_state)); + dce_disp_clk_construct( clk_dce, ctx, regs, clk_shift, clk_mask); @@ -481,6 +626,10 @@ struct display_clock *dce110_disp_clk_create( return NULL; } + memcpy(clk_dce->max_clks_by_state, + dce110_max_clks_by_state, + sizeof(dce110_max_clks_by_state)); + dce_disp_clk_construct( clk_dce, ctx, regs, clk_shift, clk_mask); @@ -502,6 +651,10 @@ struct display_clock *dce112_disp_clk_create( return NULL; } + memcpy(clk_dce->max_clks_by_state, + dce112_max_clks_by_state, + sizeof(dce112_max_clks_by_state)); + dce_disp_clk_construct( clk_dce, ctx, regs, clk_shift, clk_mask); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h index e3b23749f0a2..4ad6fe4c2841 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h @@ -27,12 +27,7 @@ #ifndef _DCE_CLOCKS_H_ #define _DCE_CLOCKS_H_ -#include "display_clock_interface.h" -#include "../gpu/divider_range.h" - - -#define TO_DCE_CLOCKS(clocks)\ - container_of(clocks, struct dce_disp_clk, base) +#include "display_clock.h" #define CLK_COMMON_REG_LIST_DCE_BASE() \ .DPREFCLK_CNTL = mmDPREFCLK_CNTL, \ @@ -74,13 +69,30 @@ struct dce_disp_clk_registers { }; /* Array identifiers and count for the divider ranges.*/ -enum divider_range_count { +enum dce_divider_range_count { DIVIDER_RANGE_01 = 0, DIVIDER_RANGE_02, DIVIDER_RANGE_03, DIVIDER_RANGE_MAX /* == 3*/ }; +enum dce_divider_error_types { + INVALID_DID = 0, + INVALID_DIVIDER = 1 +}; + +struct dce_divider_range { + int div_range_start; + /* The end of this range of dividers.*/ + int div_range_end; + /* The distance between each divider in this range.*/ + int div_range_step; + /* The divider id for the lowest divider.*/ + int did_min; + /* The divider id for the highest divider.*/ + int did_max; +}; + struct dce_disp_clk { struct display_clock base; const struct dce_disp_clk_registers *regs; @@ -88,23 +100,23 @@ struct dce_disp_clk { const struct dce_disp_clk_mask *clk_mask; struct state_dependent_clocks max_clks_by_state[DM_PP_CLOCKS_MAX_STATES]; - struct divider_range divider_ranges[DIVIDER_RANGE_MAX]; + struct dce_divider_range divider_ranges[DIVIDER_RANGE_MAX]; bool use_max_disp_clk; - uint32_t dentist_vco_freq_khz; + int dentist_vco_freq_khz; /* Cache the status of DFS-bypass feature*/ bool dfs_bypass_enabled; /* Cache the display clock returned by VBIOS if DFS-bypass is enabled. * This is basically "Crystal Frequency In KHz" (XTALIN) frequency */ - uint32_t dfs_bypass_disp_clk; + int dfs_bypass_disp_clk; /* Flag for Enabled SS on GPU PLL */ bool ss_on_gpu_pll; /* GPU PLL SS percentage (if down-spread enabled) */ - uint32_t gpu_pll_ss_percentage; + int gpu_pll_ss_percentage; /* GPU PLL SS percentage Divider (100 or 1000) */ - uint32_t gpu_pll_ss_divider; + int gpu_pll_ss_divider; }; diff --git a/drivers/gpu/drm/amd/display/dc/gpu/Makefile b/drivers/gpu/drm/amd/display/dc/gpu/Makefile deleted file mode 100644 index 6ab4078405f2..000000000000 --- a/drivers/gpu/drm/amd/display/dc/gpu/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -# -# Makefile for the 'gpu' sub-component of DAL. -# It provides the control and status of HW adapter resources, -# that are global for the ASIC and sharable between pipes. - -GPU = divider_range.o - -AMD_DAL_GPU = $(addprefix $(AMDDALPATH)/dc/gpu/,$(GPU)) - -AMD_DISPLAY_FILES += $(AMD_DAL_GPU) - -############################################################################### -# DCE 110 family -############################################################################### - -GPU_DCE112 = display_clock_dce112.o - -AMD_DAL_GPU_DCE112 = $(addprefix $(AMDDALPATH)/dc/gpu/dce112/,$(GPU_DCE112)) - -AMD_DISPLAY_FILES += $(AMD_DAL_GPU_DCE110) $(AMD_DAL_GPU_DCE112) - diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c deleted file mode 100644 index e0d67fb6c633..000000000000 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c +++ /dev/null @@ -1,277 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" - -#include "dce/dce_11_2_d.h" -#include "dce/dce_11_2_sh_mask.h" - -#include "include/bios_parser_interface.h" -#include "include/fixed32_32.h" -#include "include/logger_interface.h" - -#include "../divider_range.h" - -#include "display_clock_dce112.h" - -#define FROM_DISPLAY_CLOCK(base) \ - container_of(base, struct display_clock_dce112, disp_clk_base) - -static struct state_dependent_clocks max_clks_by_state[] = { -/*ClocksStateInvalid - should not be used*/ -{ .display_clk_khz = 0, .pixel_clk_khz = 0 }, -/*ClocksStateUltraLow - currently by HW design team not supposed to be used*/ -{ .display_clk_khz = 389189, .pixel_clk_khz = 346672 }, -/*ClocksStateLow*/ -{ .display_clk_khz = 459000, .pixel_clk_khz = 400000 }, -/*ClocksStateNominal*/ -{ .display_clk_khz = 667000, .pixel_clk_khz = 600000 }, -/*ClocksStatePerformance*/ -{ .display_clk_khz = 1132000, .pixel_clk_khz = 600000 } }; - -/* Ranges for divider identifiers (Divider ID or DID) - mmDENTIST_DISPCLK_CNTL.DENTIST_DISPCLK_WDIVIDER*/ -enum divider_id_register_setting { - DIVIDER_RANGE_01_BASE_DIVIDER_ID = 0X08, - DIVIDER_RANGE_02_BASE_DIVIDER_ID = 0X40, - DIVIDER_RANGE_03_BASE_DIVIDER_ID = 0X60, - DIVIDER_RANGE_MAX_DIVIDER_ID = 0X80 -}; - -/* Step size between each divider within a range. - Incrementing the DENTIST_DISPCLK_WDIVIDER by one - will increment the divider by this much.*/ -enum divider_range_step_size { - DIVIDER_RANGE_01_STEP_SIZE = 25, /* 0.25*/ - DIVIDER_RANGE_02_STEP_SIZE = 50, /* 0.50*/ - DIVIDER_RANGE_03_STEP_SIZE = 100 /* 1.00 */ -}; - -static struct divider_range divider_ranges[DIVIDER_RANGE_MAX]; - - -void dispclk_dce112_destroy(struct display_clock **base) -{ - struct display_clock_dce112 *dc112; - - dc112 = DCLCK112_FROM_BASE(*base); - - dm_free(dc112); - - *base = NULL; -} - -static bool display_clock_integrated_info_construct( - struct display_clock_dce112 *disp_clk) -{ - struct integrated_info info; - uint32_t i; - struct display_clock *base = &disp_clk->disp_clk_base; - - memset(&info, 0, sizeof(struct integrated_info)); - - disp_clk->dentist_vco_freq_khz = info.dentist_vco_freq; - if (disp_clk->dentist_vco_freq_khz == 0) - disp_clk->dentist_vco_freq_khz = 3600000; - - base->min_display_clk_threshold_khz = - disp_clk->dentist_vco_freq_khz / 64; - - /*update the maximum display clock for each power state*/ - for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) { - enum dm_pp_clocks_state clk_state = DM_PP_CLOCKS_STATE_INVALID; - - switch (i) { - case 0: - clk_state = DM_PP_CLOCKS_STATE_ULTRA_LOW; - break; - - case 1: - clk_state = DM_PP_CLOCKS_STATE_LOW; - break; - - case 2: - clk_state = DM_PP_CLOCKS_STATE_NOMINAL; - break; - - case 3: - clk_state = DM_PP_CLOCKS_STATE_PERFORMANCE; - break; - - default: - clk_state = DM_PP_CLOCKS_STATE_INVALID; - break; - } - - /*Do not allow bad VBIOS/SBIOS to override with invalid values, - * check for > 100MHz*/ - if (info.disp_clk_voltage[i].max_supported_clk >= 100000) { - (disp_clk->max_clks_by_state + clk_state)-> - display_clk_khz = - info.disp_clk_voltage[i].max_supported_clk; - } - } - - return true; -} - -void dce112_set_clock( - struct display_clock *base, - uint32_t requested_clk_khz) -{ - struct bp_set_dce_clock_parameters dce_clk_params; - struct dc_bios *bp = base->ctx->dc_bios; - - /* Prepare to program display clock*/ - memset(&dce_clk_params, 0, sizeof(dce_clk_params)); - - /* Make sure requested clock isn't lower than minimum threshold*/ - if (requested_clk_khz > 0) - requested_clk_khz = dm_max(requested_clk_khz, - base->min_display_clk_threshold_khz); - - dce_clk_params.target_clock_frequency = requested_clk_khz; - dce_clk_params.pll_id = CLOCK_SOURCE_ID_DFS; - dce_clk_params.clock_type = DCECLOCK_TYPE_DISPLAY_CLOCK; - - bp->funcs->set_dce_clock(bp, &dce_clk_params); - - /* from power down, we need mark the clock state as ClocksStateNominal - * from HWReset, so when resume we will call pplib voltage regulator.*/ - if (requested_clk_khz == 0) - base->cur_min_clks_state = DM_PP_CLOCKS_STATE_NOMINAL; - - /*Program DP ref Clock*/ - /*VBIOS will determine DPREFCLK frequency, so we don't set it*/ - dce_clk_params.target_clock_frequency = 0; - dce_clk_params.clock_type = DCECLOCK_TYPE_DPREFCLK; - dce_clk_params.flags.USE_GENLOCK_AS_SOURCE_FOR_DPREFCLK = - (dce_clk_params.pll_id == - CLOCK_SOURCE_COMBO_DISPLAY_PLL0); - - bp->funcs->set_dce_clock(bp, &dce_clk_params); -} - -static const struct display_clock_funcs funcs = { - .destroy = dispclk_dce112_destroy, - .set_clock = dce112_set_clock, -}; - -bool dal_display_clock_dce112_construct( - struct display_clock_dce112 *dc112, - struct dc_context *ctx) -{ - struct display_clock *dc_base = &dc112->disp_clk_base; - - dc_base->ctx = ctx; - dc_base->min_display_clk_threshold_khz = 0; - - dc_base->cur_min_clks_state = DM_PP_CLOCKS_STATE_INVALID; - - dc_base->funcs = &funcs; - - dc112->dfs_bypass_disp_clk = 0; - - if (!display_clock_integrated_info_construct(dc112)) - dm_logger_write(dc_base->ctx->logger, LOG_WARNING, - "Cannot obtain VBIOS integrated info\n"); - - dc112->gpu_pll_ss_percentage = 0; - dc112->gpu_pll_ss_divider = 1000; - dc112->ss_on_gpu_pll = false; - -/* Initially set max clocks state to nominal. This should be updated by - * via a pplib call to DAL IRI eventually calling a - * DisplayEngineClock_dce112::StoreMaxClocksState(). This call will come in - * on PPLIB init. This is from DCE5x. in case HW wants to use mixed method.*/ - dc_base->max_clks_state = DM_PP_CLOCKS_STATE_NOMINAL; - - dc112->disp_clk_base.min_display_clk_threshold_khz = - (dc112->dentist_vco_freq_khz / 62); - - dal_divider_range_construct( - ÷r_ranges[DIVIDER_RANGE_01], - DIVIDER_RANGE_01_START, - DIVIDER_RANGE_01_STEP_SIZE, - DIVIDER_RANGE_01_BASE_DIVIDER_ID, - DIVIDER_RANGE_02_BASE_DIVIDER_ID); - dal_divider_range_construct( - ÷r_ranges[DIVIDER_RANGE_02], - DIVIDER_RANGE_02_START, - DIVIDER_RANGE_02_STEP_SIZE, - DIVIDER_RANGE_02_BASE_DIVIDER_ID, - DIVIDER_RANGE_03_BASE_DIVIDER_ID); - dal_divider_range_construct( - ÷r_ranges[DIVIDER_RANGE_03], - DIVIDER_RANGE_03_START, - DIVIDER_RANGE_03_STEP_SIZE, - DIVIDER_RANGE_03_BASE_DIVIDER_ID, - DIVIDER_RANGE_MAX_DIVIDER_ID); - - { - uint32_t ss_info_num = - ctx->dc_bios->funcs-> - get_ss_entry_number(ctx->dc_bios, AS_SIGNAL_TYPE_GPU_PLL); - - if (ss_info_num) { - struct spread_spectrum_info info; - bool result; - - memset(&info, 0, sizeof(info)); - - result = - (BP_RESULT_OK == ctx->dc_bios->funcs-> - get_spread_spectrum_info(ctx->dc_bios, - AS_SIGNAL_TYPE_GPU_PLL, 0, &info)) ? true : false; - - - /* Based on VBIOS, VBIOS will keep entry for GPU PLL SS - * even if SS not enabled and in that case - * SSInfo.spreadSpectrumPercentage !=0 would be sign - * that SS is enabled - */ - if (result && info.spread_spectrum_percentage != 0) { - dc112->ss_on_gpu_pll = true; - dc112->gpu_pll_ss_divider = - info.spread_percentage_divider; - - if (info.type.CENTER_MODE == 0) { - /* Currently for DP Reference clock we - * need only SS percentage for - * downspread */ - dc112->gpu_pll_ss_percentage = - info.spread_spectrum_percentage; - } - } - - } - } - - dc112->use_max_disp_clk = true; - dc112->max_clks_by_state = max_clks_by_state; - - return true; -} - diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h deleted file mode 100644 index 0743c514a60f..000000000000 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ -#ifndef __DAL_DISPLAY_CLOCK_DCE112_H__ -#define __DAL_DISPLAY_CLOCK_DCE112_H__ - -#include "display_clock_interface.h" - -struct display_clock_dce112 { - struct display_clock disp_clk_base; - bool use_max_disp_clk; - uint32_t dentist_vco_freq_khz; - /* Cache the status of DFS-bypass feature*/ - bool dfs_bypass_enabled; - /* GPU PLL SS percentage (if down-spread enabled) */ - uint32_t gpu_pll_ss_percentage; - /* GPU PLL SS percentage Divider (100 or 1000) */ - uint32_t gpu_pll_ss_divider; - /* Flag for Enabled SS on GPU PLL */ - bool ss_on_gpu_pll; - /* Cache the display clock returned by VBIOS if DFS-bypass is enabled. - * This is basically "Crystal Frequency In KHz" (XTALIN) frequency */ - uint32_t dfs_bypass_disp_clk; - struct state_dependent_clocks *max_clks_by_state; - -}; - -#define DCLCK112_FROM_BASE(dc_base) \ - container_of(dc_base, struct display_clock_dce112, disp_clk_base) - -/* Array identifiers and count for the divider ranges.*/ -enum divider_range_count { - DIVIDER_RANGE_01 = 0, - DIVIDER_RANGE_02, - DIVIDER_RANGE_03, - DIVIDER_RANGE_MAX /* == 3*/ -}; - -/* Starting point for each divider range.*/ -enum divider_range_start { - DIVIDER_RANGE_01_START = 200, /* 2.00*/ - DIVIDER_RANGE_02_START = 1600, /* 16.00*/ - DIVIDER_RANGE_03_START = 3200, /* 32.00*/ - DIVIDER_RANGE_SCALE_FACTOR = 100 /* Results are scaled up by 100.*/ -}; - -bool dal_display_clock_dce112_construct( - struct display_clock_dce112 *dc112, - struct dc_context *ctx); - -void dispclk_dce112_destroy(struct display_clock **base); - -void dce112_set_clock( - struct display_clock *base, - uint32_t requested_clk_khz); - - -#endif /* __DAL_DISPLAY_CLOCK_DCE112_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/gpu/divider_range.c b/drivers/gpu/drm/amd/display/dc/gpu/divider_range.c deleted file mode 100644 index 59d44004411b..000000000000 --- a/drivers/gpu/drm/amd/display/dc/gpu/divider_range.c +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ -#include "dm_services.h" -#include "divider_range.h" - -bool dal_divider_range_construct( - struct divider_range *div_range, - uint32_t range_start, - uint32_t range_step, - uint32_t did_min, - uint32_t did_max) -{ - div_range->div_range_start = range_start; - div_range->div_range_step = range_step; - div_range->did_min = did_min; - div_range->did_max = did_max; - - if (div_range->div_range_step == 0) { - div_range->div_range_step = 1; - /*div_range_step cannot be zero*/ - BREAK_TO_DEBUGGER(); - } - /* Calculate this based on the other inputs.*/ - /* See DividerRange.h for explanation of */ - /* the relationship between divider id (DID) and a divider.*/ - /* Number of Divider IDs = (Maximum Divider ID - Minimum Divider ID)*/ - /* Maximum divider identified in this range = - * (Number of Divider IDs)*Step size between dividers - * + The start of this range.*/ - div_range->div_range_end = (did_max - did_min) * range_step - + range_start; - return true; -} - -static uint32_t dal_divider_range_calc_divider( - struct divider_range *div_range, - uint32_t did) -{ - /* Is this DID within our range?*/ - if ((did < div_range->did_min) || (did >= div_range->did_max)) - return INVALID_DIVIDER; - - return ((did - div_range->did_min) * div_range->div_range_step) - + div_range->div_range_start; - -} - -static uint32_t dal_divider_range_calc_did( - struct divider_range *div_range, - uint32_t div) -{ - uint32_t did; - /* Check before dividing.*/ - if (div_range->div_range_step == 0) { - div_range->div_range_step = 1; - /*div_range_step cannot be zero*/ - BREAK_TO_DEBUGGER(); - } - /* Is this divider within our range?*/ - if ((div < div_range->div_range_start) - || (div >= div_range->div_range_end)) - return INVALID_DID; -/* did = (divider - range_start + (range_step-1)) / range_step) + did_min*/ - did = div - div_range->div_range_start; - did += div_range->div_range_step - 1; - did /= div_range->div_range_step; - did += div_range->did_min; - return did; -} - -uint32_t dal_divider_range_get_divider( - struct divider_range *div_range, - uint32_t ranges_num, - uint32_t did) -{ - uint32_t div = INVALID_DIVIDER; - uint32_t i; - - for (i = 0; i < ranges_num; i++) { - /* Calculate divider with given divider ID*/ - div = dal_divider_range_calc_divider(&div_range[i], did); - /* Found a valid return divider*/ - if (div != INVALID_DIVIDER) - break; - } - return div; -} -uint32_t dal_divider_range_get_did( - struct divider_range *div_range, - uint32_t ranges_num, - uint32_t divider) -{ - uint32_t did = INVALID_DID; - uint32_t i; - - for (i = 0; i < ranges_num; i++) { - /* CalcDid returns InvalidDid if a divider ID isn't found*/ - did = dal_divider_range_calc_did(&div_range[i], divider); - /* Found a valid return did*/ - if (did != INVALID_DID) - break; - } - return did; -} - diff --git a/drivers/gpu/drm/amd/display/dc/gpu/divider_range.h b/drivers/gpu/drm/amd/display/dc/gpu/divider_range.h deleted file mode 100644 index e53522f652cc..000000000000 --- a/drivers/gpu/drm/amd/display/dc/gpu/divider_range.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DAL_DIVIDER_RANGE_H__ -#define __DAL_DIVIDER_RANGE_H__ - -enum divider_error_types { - INVALID_DID = 0, - INVALID_DIVIDER = 1 -}; - -struct divider_range { - uint32_t div_range_start; - /* The end of this range of dividers.*/ - uint32_t div_range_end; - /* The distance between each divider in this range.*/ - uint32_t div_range_step; - /* The divider id for the lowest divider.*/ - uint32_t did_min; - /* The divider id for the highest divider.*/ - uint32_t did_max; -}; - -bool dal_divider_range_construct( - struct divider_range *div_range, - uint32_t range_start, - uint32_t range_step, - uint32_t did_min, - uint32_t did_max); - -uint32_t dal_divider_range_get_divider( - struct divider_range *div_range, - uint32_t ranges_num, - uint32_t did); -uint32_t dal_divider_range_get_did( - struct divider_range *div_range, - uint32_t ranges_num, - uint32_t divider); - -#endif /* __DAL_DIVIDER_RANGE_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index f2eb8945d5c4..0418e3e02c7a 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -188,7 +188,7 @@ void core_link_enable_stream(struct pipe_ctx *pipe_ctx); void core_link_disable_stream(struct pipe_ctx *pipe_ctx); /********** DAL Core*********************/ -#include "display_clock_interface.h" +#include "display_clock.h" #include "transform.h" struct resource_pool; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h b/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h new file mode 100644 index 000000000000..e163f5818dd9 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h @@ -0,0 +1,61 @@ +/* + * Copyright 2012-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DISPLAY_CLOCK_H__ +#define __DISPLAY_CLOCK_H__ + +#include "dm_services_types.h" + +/* Structure containing all state-dependent clocks + * (dependent on "enum clocks_state") */ +struct state_dependent_clocks { + int display_clk_khz; + int pixel_clk_khz; +}; + +struct display_clock { + struct dc_context *ctx; + const struct display_clock_funcs *funcs; + + enum dm_pp_clocks_state max_clks_state; + enum dm_pp_clocks_state cur_min_clks_state; +}; + +struct display_clock_funcs { + void (*set_clock)(struct display_clock *disp_clk, + int requested_clock_khz); + + enum dm_pp_clocks_state (*get_required_clocks_state)( + struct display_clock *disp_clk, + struct state_dependent_clocks *req_clocks); + + bool (*set_min_clocks_state)(struct display_clock *disp_clk, + enum dm_pp_clocks_state dm_pp_clocks_state); + + int (*get_dp_ref_clk_frequency)(struct display_clock *disp_clk); + +}; + +#endif /* __DISPLAY_CLOCK_H__ */ diff --git a/drivers/gpu/drm/amd/display/include/display_clock_interface.h b/drivers/gpu/drm/amd/display/include/display_clock_interface.h deleted file mode 100644 index 53a01381c638..000000000000 --- a/drivers/gpu/drm/amd/display/include/display_clock_interface.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DISPLAY_CLOCK_INTERFACE_H__ -#define __DISPLAY_CLOCK_INTERFACE_H__ - -#include "dm_services_types.h" -#include "hw_sequencer_types.h" -#include "grph_object_defs.h" -#include "signal_types.h" - -/* Structure containing all state-dependent clocks - * (dependent on "enum clocks_state") */ -struct state_dependent_clocks { - uint32_t display_clk_khz; - uint32_t pixel_clk_khz; -}; - -struct display_clock { - struct dc_context *ctx; - const struct display_clock_funcs *funcs; - - int min_display_clk_threshold_khz; - enum dm_pp_clocks_state max_clks_state; - enum dm_pp_clocks_state cur_min_clks_state; -}; - -struct display_clock_funcs { - void (*destroy)(struct display_clock **to_destroy); - void (*set_clock)(struct display_clock *disp_clk, - uint32_t requested_clock_khz); - enum dm_pp_clocks_state (*get_required_clocks_state)( - struct display_clock *disp_clk, - struct state_dependent_clocks *req_clocks); - bool (*set_min_clocks_state)(struct display_clock *disp_clk, - enum dm_pp_clocks_state dm_pp_clocks_state); - uint32_t (*get_dp_ref_clk_frequency)(struct display_clock *disp_clk); - -}; - -void dal_display_clock_destroy(struct display_clock **to_destroy); - - -#endif /* __DISPLAY_CLOCK_INTERFACE_H__ */ -- cgit From 49c07a99b2bdd6e6ed621f728d58d8535cc87a61 Mon Sep 17 00:00:00 2001 From: Arindam Nath Date: Mon, 5 Dec 2016 19:21:26 +0530 Subject: drm/amd/display: remove DM_NOT_IMPL messages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some functions like dm_bandwidth_update are placeholders for future implementations. Right now, they simply print messages like "DM_NOT_IMPL: dm_bandwidth_update". This message even though informational, sometimes can create some confusion for users. Since these functions are only skeletons for future, we simply remove the rather un-unecessary messages from these functions. Signed-off-by: Arindam Nath Reviewed-by: Christian König Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'drivers/gpu') 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 fa55147d0c47..396dbd661183 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -48,10 +48,6 @@ #include "modules/inc/mod_freesync.h" -/* Debug facilities */ -#define AMDGPU_DM_NOT_IMPL(fmt, ...) \ - DRM_INFO("DM_NOT_IMPL: " fmt, ##__VA_ARGS__) - /* * dm_vblank_get_counter * @@ -1269,20 +1265,18 @@ void amdgpu_dm_destroy_drm_device(struct amdgpu_display_manager *dm) */ static void dm_bandwidth_update(struct amdgpu_device *adev) { - AMDGPU_DM_NOT_IMPL("%s\n", __func__); + /* TODO: implement later */ } static void dm_set_backlight_level(struct amdgpu_encoder *amdgpu_encoder, u8 level) { /* TODO: translate amdgpu_encoder to display_index and call DAL */ - AMDGPU_DM_NOT_IMPL("%s\n", __func__); } static u8 dm_get_backlight_level(struct amdgpu_encoder *amdgpu_encoder) { /* TODO: translate amdgpu_encoder to display_index and call DAL */ - AMDGPU_DM_NOT_IMPL("%s\n", __func__); return 0; } -- cgit From a33fa99d8b8ec71a69e089e39ab1498d31169640 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 6 Dec 2016 11:26:08 -0500 Subject: drm/amd/display: Fix bunch of warnings in DC Some of those are potential bugs Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 5 ++- .../gpu/drm/amd/display/dc/dce/dce_clock_source.c | 5 --- drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c | 41 ---------------------- drivers/gpu/drm/amd/display/dc/dce/dce_transform.c | 2 -- .../drm/amd/display/dc/dce110/dce110_transform_v.c | 3 +- 6 files changed, 5 insertions(+), 53 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c index 0b2bb3992f1a..3b0710ef4716 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c @@ -1709,7 +1709,7 @@ static void calculate_bandwidth( else { data->blackout_recovery_time = bw_max2(data->blackout_recovery_time, bw_add(bw_mul(bw_int_to_fixed(2), vbios->mcifwrmc_urgent_latency), data->mcifwr_burst_time[data->y_clk_level][data->sclk_level])); if (bw_ltn(data->adjusted_data_buffer_size[k], bw_mul(bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]), (bw_add(vbios->blackout_duration, bw_add(bw_mul(bw_int_to_fixed(2), vbios->mcifwrmc_urgent_latency), data->mcifwr_burst_time[data->y_clk_level][data->sclk_level])))))) { - data->blackout_recovery_time = bw_max2(data->blackout_recovery_time, bw_div((bw_add(bw_mul(bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]), vbios->blackout_duration), bw_sub(bw_div(bw_mul(bw_mul(bw_mul((bw_add(bw_add(bw_mul(bw_int_to_fixed(2), vbios->mcifwrmc_urgent_latency), data->dmif_burst_time[i][j]), data->mcifwr_burst_time[data->y_clk_level][data->sclk_level])), data->dispclk), bw_int_to_fixed(data->bytes_per_pixel[k])), data->lines_interleaved_in_mem_access[k]), data->latency_hiding_lines[k]), data->adjusted_data_buffer_size[k]))), (bw_sub(bw_div(bw_mul(bw_mul(data->dispclk, bw_int_to_fixed(data->bytes_per_pixel[k])), data->lines_interleaved_in_mem_access[k]), data->latency_hiding_lines[k]), bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]))))); + data->blackout_recovery_time = bw_max2(data->blackout_recovery_time, bw_div((bw_add(bw_mul(bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]), vbios->blackout_duration), bw_sub(bw_div(bw_mul(bw_mul(bw_mul((bw_add(bw_add(bw_mul(bw_int_to_fixed(2), vbios->mcifwrmc_urgent_latency), data->dmif_burst_time[data->y_clk_level][data->sclk_level]), data->mcifwr_burst_time[data->y_clk_level][data->sclk_level])), data->dispclk), bw_int_to_fixed(data->bytes_per_pixel[k])), data->lines_interleaved_in_mem_access[k]), data->latency_hiding_lines[k]), data->adjusted_data_buffer_size[k]))), (bw_sub(bw_div(bw_mul(bw_mul(data->dispclk, bw_int_to_fixed(data->bytes_per_pixel[k])), data->lines_interleaved_in_mem_access[k]), data->latency_hiding_lines[k]), bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]))))); } } } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index bd53d27e5414..f552b0468186 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1834,11 +1834,10 @@ void resource_build_info_frame(struct pipe_ctx *pipe_ctx) set_vendor_info_packet( pipe_ctx->stream, &info_frame.vendor_info_packet); set_spd_info_packet(pipe_ctx->stream, &info_frame.spd_packet); - } - - else if (dc_is_dp_signal(signal)) + } else if (dc_is_dp_signal(signal)) { set_vsc_info_packet(pipe_ctx->stream, &info_frame.vsc_packet); set_spd_info_packet(pipe_ctx->stream, &info_frame.spd_packet); + } translate_info_frame(&info_frame, &pipe_ctx->encoder_info_frame); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index 80ac5d9efa71..3d1c32122d69 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -465,7 +465,6 @@ static uint32_t dce110_get_pix_clk_dividers_helper ( struct pll_settings *pll_settings, struct pixel_clk_params *pix_clk_params) { - uint32_t addr = 0; uint32_t value = 0; uint32_t field = 0; uint32_t pll_calc_error = MAX_PLL_CALC_ERROR; @@ -731,8 +730,6 @@ static void dce110_program_pixel_clk_resync( enum signal_type signal_type, enum dc_color_depth colordepth) { - uint32_t value = 0; - REG_UPDATE(RESYNC_CNTL, DCCG_DEEP_COLOR_CNTL1, 0); /* @@ -772,8 +769,6 @@ static void dce112_program_pixel_clk_resync( enum dc_color_depth colordepth, bool enable_ycbcr420) { - uint32_t value = 0; - REG_UPDATE(PIXCLK_RESYNC_CNTL, PHYPLLA_DCCG_DEEP_COLOR_CNTL, 0); /* diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c index 8e2519b1c9df..262612061c68 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c @@ -148,29 +148,6 @@ static int dce_divider_range_calc_divider( } -static int dce_divider_range_calc_did( - struct dce_divider_range *div_range, - int div) -{ - int did; - /* Check before dividing.*/ - if (div_range->div_range_step == 0) { - div_range->div_range_step = 1; - /*div_range_step cannot be zero*/ - BREAK_TO_DEBUGGER(); - } - /* Is this divider within our range?*/ - if ((div < div_range->div_range_start) - || (div >= div_range->div_range_end)) - return INVALID_DID; -/* did = (divider - range_start + (range_step-1)) / range_step) + did_min*/ - did = div - div_range->div_range_start; - did += div_range->div_range_step - 1; - did /= div_range->div_range_step; - did += div_range->did_min; - return did; -} - static int dce_divider_range_get_divider( struct dce_divider_range *div_range, int ranges_num, @@ -189,24 +166,6 @@ static int dce_divider_range_get_divider( return div; } -static int dce_divider_range_get_did( - struct dce_divider_range *div_range, - int ranges_num, - int divider) -{ - int did = INVALID_DID; - int i; - - for (i = 0; i < ranges_num; i++) { - /* CalcDid returns InvalidDid if a divider ID isn't found*/ - did = dce_divider_range_calc_did(&div_range[i], divider); - /* Found a valid return did*/ - if (did != INVALID_DID) - break; - } - return did; -} - static int dce_clocks_get_dp_ref_freq(struct display_clock *clk) { struct dce_disp_clk *clk_dce = TO_DCE_CLOCKS(clk); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c index f47b6617f662..bbf4d97cb980 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c @@ -83,8 +83,6 @@ static bool setup_scaling_configuration( struct dce_transform *xfm_dce, const struct scaler_data *data) { - struct dc_context *ctx = xfm_dce->base.ctx; - if (data->taps.h_taps + data->taps.v_taps <= 2) { /* Set bypass */ REG_UPDATE_2(SCL_MODE, SCL_MODE, 0, SCL_PSCL_EN, 0); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c index 7d8cf7a58f46..feb5f3c29804 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c @@ -621,7 +621,8 @@ static void dce110_xfmv_set_pixel_storage_depth( const struct bit_depth_reduction_params *bit_depth_params) { struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); - int pixel_depth, expan_mode; + int pixel_depth = 0; + int expan_mode = 0; uint32_t reg_data = 0; switch (depth) { -- cgit From eaf9094475504effe1a798199a1a118299cf0f74 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 6 Dec 2016 12:01:23 -0500 Subject: drm/amd/display: Fix warning in freesync module Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/modules/freesync/freesync.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index eb912baa0169..8892e8bec7c3 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -746,6 +746,9 @@ void mod_freesync_update_state(struct mod_freesync *mod_freesync, freesync_program_required = true; } break; + case FREESYNC_STATE_NONE: + /* handle here to avoid warning */ + break; } } -- cgit From 091a97e542cf9a9af6e48aa1324044433ea7341a Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 6 Dec 2016 12:25:52 -0500 Subject: drm/amd/display: Fix warning. Set MAX_SURFACES to 3 Currently we never use more than 2 surfaces in all use cases. This avoids pushing dc_commit_surfaces_to_target beyond a stacksize of 1024. Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 5575484323b3..e1f2434ee95e 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -34,7 +34,7 @@ #include "link_service_types.h" #define MAX_TARGETS 6 -#define MAX_SURFACES 6 +#define MAX_SURFACES 3 #define MAX_SINKS_PER_LINK 4 /******************************************************************************* -- cgit From edbd58af6998217c5c1ab91cb6ca239c607cc9e0 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Tue, 6 Dec 2016 22:12:09 -0500 Subject: drm/amd/display: fix indexing bug - is_new_pipe_surface should be addressed with pipe idx, not surface idx Signed-off-by: Tony Cheng Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index a3c5def507a9..70b7673993b2 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1334,7 +1334,7 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda struct core_dc *core_dc = DC_TO_CORE(dc); struct validate_context *context = core_dc->temp_flip_context; int i, j; - bool is_new_pipe_surface[MAX_SURFACES]; + bool is_new_pipe_surface[MAX_PIPES]; const struct dc_surface *new_surfaces[MAX_SURFACES] = { 0 }; update_surface_trace(dc, updates, surface_count); @@ -1353,7 +1353,7 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda &context->res_ctx.pipe_ctx[cur_pipe->bottom_pipe->pipe_idx]; } - for (j = 0; j < MAX_SURFACES; j++) + for (j = 0; j < MAX_PIPES; j++) is_new_pipe_surface[j] = true; for (i = 0 ; i < surface_count; i++) { @@ -1364,7 +1364,7 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; if (surface == pipe_ctx->surface) - is_new_pipe_surface[i] = false; + is_new_pipe_surface[j] = false; } } -- cgit From f4c07f88cc30e77d2431b5bcf95a05e0ee6f3482 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Tue, 6 Dec 2016 21:22:17 -0500 Subject: drm/amd/display: avoid apply_clk_constraints for address update - dc_update_surfaces_for_target get called in ISR but apply_clk_constraints allocates memory Signed-off-by: Tony Cheng Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 70b7673993b2..522ef7047564 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1336,6 +1336,7 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda int i, j; bool is_new_pipe_surface[MAX_PIPES]; const struct dc_surface *new_surfaces[MAX_SURFACES] = { 0 }; + bool need_apply_clk_constraints = false; update_surface_trace(dc, updates, surface_count); @@ -1405,6 +1406,7 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda if (updates[i].plane_info || updates[i].scaling_info || is_new_pipe_surface[j]) { + need_apply_clk_constraints = true; if (updates[i].plane_info) { surface->public.color_space = -- cgit From 922aa1e15e03ee2b32f50cd8a9d2c8376a19d22c Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Wed, 7 Dec 2016 14:10:05 -0500 Subject: drm/amd/display: Fix refcount over dc_sink. Retain a dc_sink pointer until a new physical pointer arrives in case of new display connected. Signed-off-by: Andrey Grodzovsky Reviewed-by: Andrey Grodzovsky Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') 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 396dbd661183..e5ba23253814 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -737,9 +737,17 @@ void amdgpu_dm_update_connector_after_detect( mutex_lock(&dev->mode_config.mutex); if (sink) { - if (aconnector->dc_sink) + if (aconnector->dc_sink) { amdgpu_dm_remove_sink_from_freesync_module( connector); + /* retain and release bellow are used for + * bump up refcount for sink because the link don't point + * to it anymore after disconnect so on next crtc to connector + * reshuffle by UMD we will get into unwanted dc_sink release + */ + if (aconnector->dc_sink != aconnector->dc_em_sink) + dc_sink_release(aconnector->dc_sink); + } aconnector->dc_sink = sink; amdgpu_dm_add_sink_to_freesync_module( connector, aconnector->edid); @@ -747,6 +755,8 @@ void amdgpu_dm_update_connector_after_detect( amdgpu_dm_remove_sink_from_freesync_module(connector); if (!aconnector->dc_sink) aconnector->dc_sink = aconnector->dc_em_sink; + else if (aconnector->dc_sink != aconnector->dc_em_sink) + dc_sink_retain(aconnector->dc_sink); } mutex_unlock(&dev->mode_config.mutex); -- cgit From 5ea81b91857882bb5bfa883fb27671133957a96c Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Mon, 5 Dec 2016 18:03:04 -0500 Subject: drm/amd/display: fix up construction of scratch_val_ctx Signed-off-by: Dmytro Laktyushkin Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 12 ++++++------ drivers/gpu/drm/amd/display/dc/inc/core_types.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 522ef7047564..8e1d695fcb77 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -450,11 +450,6 @@ static void destruct(struct core_dc *dc) { resource_validate_ctx_destruct(dc->current_context); - dm_free(dc->temp_flip_context); - dc->temp_flip_context = NULL; - dm_free(dc->scratch_val_ctx); - dc->scratch_val_ctx = NULL; - destroy_links(dc); dc_destroy_resource_pool(dc); @@ -473,6 +468,10 @@ static void destruct(struct core_dc *dc) dm_free(dc->current_context); dc->current_context = NULL; + dm_free(dc->temp_flip_context); + dc->temp_flip_context = NULL; + dm_free(dc->scratch_val_ctx); + dc->scratch_val_ctx = NULL; dm_free(dc->ctx); dc->ctx = NULL; @@ -492,7 +491,7 @@ static bool construct(struct core_dc *dc, dc->current_context = dm_alloc(sizeof(*dc->current_context)); dc->temp_flip_context = dm_alloc(sizeof(*dc->temp_flip_context)); - dc->scratch_val_ctx = dm_alloc(sizeof(*dc->temp_flip_context)); + dc->scratch_val_ctx = dm_alloc(sizeof(*dc->scratch_val_ctx)); if (!dc->current_context || !dc->temp_flip_context) { dm_error("%s: failed to create validate ctx\n", __func__); @@ -1220,6 +1219,7 @@ bool dc_pre_update_surfaces_to_target( goto unexpected_fail; } resource_validate_ctx_destruct(context); + ASSERT(core_dc->scratch_val_ctx == temp_context); core_dc->scratch_val_ctx = context; context = temp_context; } diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 0418e3e02c7a..3cf9bfb6decd 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -312,7 +312,7 @@ struct validate_context { /* The output from BW and WM calculations. */ struct bw_calcs_output bw_results; - /* Note: this is a big structure, do *not* put on stack! */ + /* Note: these are big structures, do *not* put on stack! */ struct dm_pp_display_configuration pp_display_cfg; }; -- cgit From 9474980ac470a20d244318db9a7c12be01437805 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Thu, 8 Dec 2016 09:47:11 -0500 Subject: drm/amd/display: Added timing sync trace. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 4 ++- drivers/gpu/drm/amd/display/dc/core/dc_debug.c | 32 ++++++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dc.h | 1 + .../amd/display/dc/dce110/dce110_hw_sequencer.c | 1 - .../gpu/drm/amd/display/include/logger_interface.h | 5 ++++ 5 files changed, 41 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 8e1d695fcb77..de99d71f9042 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1488,8 +1488,10 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda core_dc->hwss.prepare_pipe_for_context( core_dc, pipe_ctx, context); } - if (apply_ctx) + if (apply_ctx) { core_dc->hwss.apply_ctx_for_surface(core_dc, surface, context); + context_timing_trace(dc, &context->res_ctx); + } } for (i = context->res_ctx.pool->pipe_count - 1; i >= 0; i--) { diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c index 8ca0f1e0369a..78b8e0c5b4e7 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c @@ -22,6 +22,13 @@ ##__VA_ARGS__); \ } while (0) +#define TIMING_TRACE(...) do {\ + if (dc->debug.timing_trace) \ + dm_logger_write(logger, \ + LOG_SYNC, \ + ##__VA_ARGS__); \ +} while (0) + void pre_surface_trace( const struct dc *dc, const struct dc_surface *const *surfaces, @@ -268,3 +275,28 @@ void post_surface_trace(const struct dc *dc) SURFACE_TRACE("post surface process.\n"); } + +void context_timing_trace( + const struct dc *dc, + struct resource_context *res_ctx) +{ + int i; + struct core_dc *core_dc = DC_TO_CORE(dc); + struct dal_logger *logger = core_dc->ctx->logger; + + for (i = 0; i < core_dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; + int h_pos = 0; + int v_pos = 0; + + if (pipe_ctx->stream == NULL) + continue; + + pipe_ctx->tg->funcs->get_position(pipe_ctx->tg, &h_pos, &v_pos); + TIMING_TRACE("Pipe_%d H_tot:%d V_tot:%d H_pos:%d V_pos:%d\n", + pipe_ctx->pipe_idx, + pipe_ctx->stream->public.timing.h_total, + pipe_ctx->stream->public.timing.v_total, + h_pos, v_pos); + } +} diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index e1f2434ee95e..bb7cdde3e37b 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -140,6 +140,7 @@ struct dc_debug { bool max_disp_clk; bool target_trace; bool surface_trace; + bool timing_trace; bool validation_trace; bool disable_stutter; bool disable_dcc; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 6ad23f327631..99937facf645 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1892,7 +1892,6 @@ static void dce110_apply_ctx_for_surface( program_blender(dc, pipe_ctx); } - } static void dce110_power_down_fe(struct core_dc *dc, struct pipe_ctx *pipe) diff --git a/drivers/gpu/drm/amd/display/include/logger_interface.h b/drivers/gpu/drm/amd/display/include/logger_interface.h index b58d30de8293..08a6911d3a3a 100644 --- a/drivers/gpu/drm/amd/display/include/logger_interface.h +++ b/drivers/gpu/drm/amd/display/include/logger_interface.h @@ -31,6 +31,7 @@ struct dc_context; struct dc_link; struct dc_surface_update; +struct resource_context; /* * @@ -85,6 +86,10 @@ void update_surface_trace( void post_surface_trace(const struct dc *dc); +void context_timing_trace( + const struct dc *dc, + struct resource_context *res_ctx); + /* Any function which is empty or have incomplete implementation should be * marked by this macro. -- cgit From 89e8963036085e4e0e9a993d2e1bdbb931d53794 Mon Sep 17 00:00:00 2001 From: Amy Zhang Date: Mon, 12 Dec 2016 10:32:24 -0500 Subject: drm/amd/display: Fix Gamma Adjustment - Gamma correction is not properly copied to the surface after refactor - Make sure gamma correction is copied with correct retain Signed-off-by: Amy Zhang Reviewed-by: Anthony Koo Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 14 ++++++++++++-- drivers/gpu/drm/amd/display/dc/core/dc_surface.c | 3 ++- drivers/gpu/drm/amd/display/dc/dc.h | 1 + 3 files changed, 15 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index de99d71f9042..41df500817ad 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1302,8 +1302,8 @@ bool dc_commit_surfaces_to_target( for (i = 0; i < new_surface_count; i++) { updates[i].surface = new_surfaces[i]; - updates[i].gamma = (struct dc_gamma *)new_surfaces[i]->gamma_correction; - + updates[i].gamma = + (struct dc_gamma *)new_surfaces[i]->gamma_correction; flip_addr[i].address = new_surfaces[i]->address; flip_addr[i].flip_immediate = new_surfaces[i]->flip_immediate; plane_info[i].color_space = new_surfaces[i]->color_space; @@ -1444,6 +1444,16 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda pipe_ctx->scl_data.recout.width -= 2; } } + + if (updates[i].gamma) { + if (surface->public.gamma_correction != NULL) + dc_gamma_release(surface->public. + gamma_correction); + + dc_gamma_retain(updates[i].gamma); + surface->public.gamma_correction = + updates[i].gamma; + } } } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index b89d3b5d0ba0..06d8b326714a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -64,7 +64,8 @@ static bool construct(struct dc_context *ctx, struct surface *surface) static void destruct(struct surface *surface) { - + if (surface->protected.public.gamma_correction != NULL) + dc_gamma_release(surface->protected.public.gamma_correction); } /******************************************************************************* diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index bb7cdde3e37b..7733292d42f8 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -312,6 +312,7 @@ const struct dc_surface_status *dc_surface_get_status( void dc_surface_retain(const struct dc_surface *dc_surface); void dc_surface_release(const struct dc_surface *dc_surface); +void dc_gamma_retain(const struct dc_gamma *dc_gamma); void dc_gamma_release(const struct dc_gamma *dc_gamma); struct dc_gamma *dc_create_gamma(void); -- cgit From 98d2cc2b03d937af36ce5ef227ae57232bbe8471 Mon Sep 17 00:00:00 2001 From: Andrew Wong Date: Mon, 12 Dec 2016 11:17:06 -0500 Subject: drm/amd/display: Change locking of registers when flipping frames. - Introduce GRPH_UPDATE_LOCK around programming surface flip. - Remove the now unused graphic surface lock. - Add macros to get and set four registers - both immediate and H Retrace should not be enabled at the same time Signed-off-by: Andrew Wong Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 9 +-------- drivers/gpu/drm/amd/display/dc/dc_helper.c | 14 ++++++++++++++ drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c | 11 +++-------- .../gpu/drm/amd/display/dc/dce110/dce110_mem_input.c | 17 +++++++++++++++-- drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 3 +-- drivers/gpu/drm/amd/display/dc/inc/reg_helper.h | 13 +++++++++++++ 6 files changed, 47 insertions(+), 20 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 41df500817ad..75b6e404d016 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1468,11 +1468,6 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda continue; if (updates[i].flip_addr) { - core_dc->hwss.pipe_control_lock( - core_dc->hwseq, - pipe_ctx->pipe_idx, - PIPE_LOCK_CONTROL_SURFACE, - true); core_dc->hwss.update_plane_addr(core_dc, pipe_ctx); } @@ -1485,7 +1480,6 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda core_dc->hwss.pipe_control_lock( core_dc->hwseq, pipe_ctx->pipe_idx, - PIPE_LOCK_CONTROL_SURFACE | PIPE_LOCK_CONTROL_GRAPHICS | PIPE_LOCK_CONTROL_SCL | PIPE_LOCK_CONTROL_BLENDER | @@ -1515,8 +1509,7 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda pipe_ctx->pipe_idx, PIPE_LOCK_CONTROL_GRAPHICS | PIPE_LOCK_CONTROL_SCL | - PIPE_LOCK_CONTROL_BLENDER | - PIPE_LOCK_CONTROL_SURFACE, + PIPE_LOCK_CONTROL_BLENDER, false); } break; diff --git a/drivers/gpu/drm/amd/display/dc/dc_helper.c b/drivers/gpu/drm/amd/display/dc/dc_helper.c index c5ff7b6d733d..a950dd53bca4 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_helper.c +++ b/drivers/gpu/drm/amd/display/dc/dc_helper.c @@ -65,6 +65,20 @@ uint32_t generic_reg_get3(const struct dc_context *ctx, uint32_t addr, return reg_val; } +uint32_t generic_reg_get4(const struct dc_context *ctx, uint32_t addr, + uint8_t shift1, uint32_t mask1, uint32_t *field_value1, + uint8_t shift2, uint32_t mask2, uint32_t *field_value2, + uint8_t shift3, uint32_t mask3, uint32_t *field_value3, + uint8_t shift4, uint32_t mask4, uint32_t *field_value4) +{ + uint32_t reg_val = dm_read_reg(ctx, addr); + *field_value1 = get_reg_field_value_ex(reg_val, mask1, shift1); + *field_value2 = get_reg_field_value_ex(reg_val, mask2, shift2); + *field_value3 = get_reg_field_value_ex(reg_val, mask3, shift3); + *field_value4 = get_reg_field_value_ex(reg_val, mask4, shift4); + return reg_val; +} + uint32_t generic_reg_get5(const struct dc_context *ctx, uint32_t addr, uint8_t shift1, uint32_t mask1, uint32_t *field_value1, uint8_t shift2, uint32_t mask2, uint32_t *field_value2, diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c index dd1cf5e6e949..cd9a371ae237 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c @@ -49,12 +49,11 @@ void dce_pipe_control_lock(struct dce_hwseq *hws, bool lock) { uint32_t lock_val = lock ? 1 : 0; - uint32_t dcp_grph, scl, dcp_grph_surf, blnd, update_lock_mode; + uint32_t dcp_grph, scl, blnd, update_lock_mode; - uint32_t val = REG_GET_5(BLND_V_UPDATE_LOCK[blnd_inst], + uint32_t val = REG_GET_4(BLND_V_UPDATE_LOCK[blnd_inst], BLND_DCP_GRPH_V_UPDATE_LOCK, &dcp_grph, BLND_SCL_V_UPDATE_LOCK, &scl, - BLND_DCP_GRPH_SURF_V_UPDATE_LOCK, &dcp_grph_surf, BLND_BLND_V_UPDATE_LOCK, &blnd, BLND_V_UPDATE_LOCK_MODE, &update_lock_mode); @@ -64,19 +63,15 @@ void dce_pipe_control_lock(struct dce_hwseq *hws, if (control_mask & PIPE_LOCK_CONTROL_SCL) scl = lock_val; - if (control_mask & PIPE_LOCK_CONTROL_SURFACE) - dcp_grph_surf = lock_val; - if (control_mask & PIPE_LOCK_CONTROL_BLENDER) blnd = lock_val; if (control_mask & PIPE_LOCK_CONTROL_MODE) update_lock_mode = lock_val; - REG_SET_5(BLND_V_UPDATE_LOCK[blnd_inst], val, + REG_SET_4(BLND_V_UPDATE_LOCK[blnd_inst], val, BLND_DCP_GRPH_V_UPDATE_LOCK, dcp_grph, BLND_SCL_V_UPDATE_LOCK, scl, - BLND_DCP_GRPH_SURF_V_UPDATE_LOCK, dcp_grph_surf, BLND_BLND_V_UPDATE_LOCK, blnd, BLND_V_UPDATE_LOCK_MODE, update_lock_mode); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c index af9d682f8943..a20feaedfca4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c @@ -113,16 +113,25 @@ bool dce110_mem_input_program_surface_flip_and_addr( struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input); uint32_t value = 0; + uint32_t value_old = 0; + uint32_t lock_value = 0; + + lock_value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmGRPH_UPDATE)); + set_reg_field_value(lock_value, 1, GRPH_UPDATE, GRPH_UPDATE_LOCK); + dm_write_reg(mem_input110->base.ctx, DCP_REG(mmGRPH_UPDATE), lock_value); value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmGRPH_FLIP_CONTROL)); + value_old = value; if (flip_immediate) { - set_reg_field_value(value, 1, GRPH_FLIP_CONTROL, GRPH_SURFACE_UPDATE_IMMEDIATE_EN); + set_reg_field_value(value, 0, GRPH_FLIP_CONTROL, GRPH_SURFACE_UPDATE_IMMEDIATE_EN); set_reg_field_value(value, 1, GRPH_FLIP_CONTROL, GRPH_SURFACE_UPDATE_H_RETRACE_EN); } else { set_reg_field_value(value, 0, GRPH_FLIP_CONTROL, GRPH_SURFACE_UPDATE_IMMEDIATE_EN); set_reg_field_value(value, 0, GRPH_FLIP_CONTROL, GRPH_SURFACE_UPDATE_H_RETRACE_EN); } - dm_write_reg(mem_input110->base.ctx, DCP_REG(mmGRPH_FLIP_CONTROL), value); + if (value != value_old) { + dm_write_reg(mem_input110->base.ctx, DCP_REG(mmGRPH_FLIP_CONTROL), value); + } switch (address->type) { case PLN_ADDR_TYPE_GRAPHICS: @@ -147,6 +156,10 @@ bool dce110_mem_input_program_surface_flip_and_addr( if (flip_immediate) mem_input->current_address = *address; + lock_value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmGRPH_UPDATE)); + set_reg_field_value(lock_value, 0, GRPH_UPDATE, GRPH_UPDATE_LOCK); + dm_write_reg(mem_input110->base.ctx, DCP_REG(mmGRPH_UPDATE), lock_value); + return true; } diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 50d499cc01a4..fcaf2c71e4eb 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -40,8 +40,7 @@ enum pipe_lock_control { PIPE_LOCK_CONTROL_GRAPHICS = 1 << 0, PIPE_LOCK_CONTROL_BLENDER = 1 << 1, PIPE_LOCK_CONTROL_SCL = 1 << 2, - PIPE_LOCK_CONTROL_SURFACE = 1 << 3, - PIPE_LOCK_CONTROL_MODE = 1 << 4 + PIPE_LOCK_CONTROL_MODE = 1 << 3 }; struct dce_hwseq; diff --git a/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h b/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h index dbc8424f7b69..a07817472089 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h +++ b/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h @@ -143,6 +143,13 @@ FN(reg_name, f2), v2, \ FN(reg_name, f3), v3) +#define REG_GET_4(reg_name, f1, v1, f2, v2, f3, v3, f4, v4) \ + generic_reg_get4(CTX, REG(reg_name), \ + FN(reg_name, f1), v1, \ + FN(reg_name, f2), v2, \ + FN(reg_name, f3), v3, \ + FN(reg_name, f4), v4) + #define REG_GET_5(reg_name, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5) \ generic_reg_get5(CTX, REG(reg_name), \ FN(reg_name, f1), v1, \ @@ -280,6 +287,12 @@ uint32_t generic_reg_get3(const struct dc_context *ctx, uint32_t addr, uint8_t shift2, uint32_t mask2, uint32_t *field_value2, uint8_t shift3, uint32_t mask3, uint32_t *field_value3); +uint32_t generic_reg_get4(const struct dc_context *ctx, uint32_t addr, + uint8_t shift1, uint32_t mask1, uint32_t *field_value1, + uint8_t shift2, uint32_t mask2, uint32_t *field_value2, + uint8_t shift3, uint32_t mask3, uint32_t *field_value3, + uint8_t shift4, uint32_t mask4, uint32_t *field_value4); + uint32_t generic_reg_get5(const struct dc_context *ctx, uint32_t addr, uint8_t shift1, uint32_t mask1, uint32_t *field_value1, uint8_t shift2, uint32_t mask2, uint32_t *field_value2, -- cgit From 4b5752c7422f36664cea2ed300b698b4755b6dc5 Mon Sep 17 00:00:00 2001 From: Andrew Wong Date: Mon, 12 Dec 2016 11:47:47 -0500 Subject: drm/amd/display: Retrieve windowed fullscreen state - Retrieve windowed fullscreen state when getting freesync params. Signed-off-by: Andrew Wong Reviewed-by: Anthony Koo Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/modules/freesync/freesync.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index 8892e8bec7c3..6f4d169f4e4e 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -784,6 +784,9 @@ bool mod_freesync_get_state(struct mod_freesync *mod_freesync, freesync_params->update_duration_in_ns = core_freesync->map[index].state.time.update_duration_in_ns; + freesync_params->windowed_fullscreen = + core_freesync->map[index].state.windowed_fullscreen; + return true; } -- cgit From 30018e9fa27506933f232aaacfc0145ccb094272 Mon Sep 17 00:00:00 2001 From: Zeyu Fan Date: Mon, 12 Dec 2016 13:54:56 -0500 Subject: drm/amd/display: Fix HDMI scaling corruption issue. Signed-off-by: Zeyu Fan Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_transform.c | 5 +++++ drivers/gpu/drm/amd/display/dc/dce/dce_transform.h | 8 +++++++- 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c index bbf4d97cb980..50a6a25561b4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c @@ -83,6 +83,8 @@ static bool setup_scaling_configuration( struct dce_transform *xfm_dce, const struct scaler_data *data) { + REG_SET(SCL_BYPASS_CONTROL, 0, SCL_BYPASS_MODE, 0); + if (data->taps.h_taps + data->taps.v_taps <= 2) { /* Set bypass */ REG_UPDATE_2(SCL_MODE, SCL_MODE, 0, SCL_PSCL_EN, 0); @@ -285,6 +287,9 @@ static void dce_transform_set_scaler( LB_MEMORY_CONFIG, 0, LB_MEMORY_SIZE, xfm_dce->lb_memory_size); + /* Clear SCL_F_SHARP_CONTROL value to 0 */ + REG_WRITE(SCL_F_SHARP_CONTROL, 0); + /* 1. Program overscan */ program_overscan(xfm_dce, data); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h index 897645e2889f..b2cf9bfb0094 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h @@ -53,6 +53,7 @@ SRI(SCL_MODE, SCL, id), \ SRI(SCL_TAP_CONTROL, SCL, id), \ SRI(SCL_CONTROL, SCL, id), \ + SRI(SCL_BYPASS_CONTROL, SCL, id), \ SRI(EXT_OVERSCAN_LEFT_RIGHT, SCL, id), \ SRI(EXT_OVERSCAN_TOP_BOTTOM, SCL, id), \ SRI(SCL_VERT_FILTER_CONTROL, SCL, id), \ @@ -67,7 +68,8 @@ SRI(SCL_VERT_FILTER_INIT, SCL, id), \ SRI(SCL_AUTOMATIC_MODE_CONTROL, SCL, id), \ SRI(LB_MEMORY_CTRL, LB, id), \ - SRI(SCL_UPDATE, SCL, id) + SRI(SCL_UPDATE, SCL, id), \ + SRI(SCL_F_SHARP_CONTROL, SCL, id) #define XFM_COMMON_REG_LIST_DCE100(id) \ XFM_COMMON_REG_LIST_DCE_BASE(id), \ @@ -116,6 +118,7 @@ XFM_SF(SCL_TAP_CONTROL, SCL_H_NUM_OF_TAPS, mask_sh), \ XFM_SF(SCL_TAP_CONTROL, SCL_V_NUM_OF_TAPS, mask_sh), \ XFM_SF(SCL_CONTROL, SCL_BOUNDARY_MODE, mask_sh), \ + XFM_SF(SCL_BYPASS_CONTROL, SCL_BYPASS_MODE, mask_sh), \ XFM_SF(EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_LEFT, mask_sh), \ XFM_SF(EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_RIGHT, mask_sh), \ XFM_SF(EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_TOP, mask_sh), \ @@ -181,6 +184,7 @@ type GAMUT_REMAP_C34; \ type GRPH_GAMUT_REMAP_MODE; \ type SCL_MODE; \ + type SCL_BYPASS_MODE; \ type SCL_PSCL_EN; \ type SCL_H_NUM_OF_TAPS; \ type SCL_V_NUM_OF_TAPS; \ @@ -241,6 +245,7 @@ struct dce_transform_registers { uint32_t SCL_MODE; uint32_t SCL_TAP_CONTROL; uint32_t SCL_CONTROL; + uint32_t SCL_BYPASS_CONTROL; uint32_t EXT_OVERSCAN_LEFT_RIGHT; uint32_t EXT_OVERSCAN_TOP_BOTTOM; uint32_t SCL_VERT_FILTER_CONTROL; @@ -258,6 +263,7 @@ struct dce_transform_registers { uint32_t SCL_AUTOMATIC_MODE_CONTROL; uint32_t LB_MEMORY_CTRL; uint32_t SCL_UPDATE; + uint32_t SCL_F_SHARP_CONTROL; }; struct init_int_and_frac { -- cgit From 1e3d346f4fbb48f0a89134f4b834d3be2df3cc25 Mon Sep 17 00:00:00 2001 From: Vitaly Prosyak Date: Tue, 13 Dec 2016 14:23:16 -0600 Subject: drm/amd/display: re gamma programming Fix gamma update logic to avoid crash Signed-off-by: Vitaly Prosyak Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 75b6e404d016..9a35e3bb8283 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1445,7 +1445,8 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda } } - if (updates[i].gamma) { + if (updates[i].gamma && updates[i].gamma != + surface->public.gamma_correction) { if (surface->public.gamma_correction != NULL) dc_gamma_release(surface->public. gamma_correction); -- cgit From 88499197de090c9bb391cc11bf9410b9f020092f Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Mon, 12 Dec 2016 14:20:45 -0500 Subject: drm/amd/display: Moved swizzle parameter translation to dc. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/basics/conversion.c | 9 +++++++++ drivers/gpu/drm/amd/display/dc/basics/conversion.h | 2 ++ drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c | 11 +---------- 3 files changed, 12 insertions(+), 10 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/basics/conversion.c b/drivers/gpu/drm/amd/display/dc/basics/conversion.c index ebe14e17cc2e..5682fea2080d 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/conversion.c +++ b/drivers/gpu/drm/amd/display/dc/basics/conversion.c @@ -221,3 +221,12 @@ void calculate_adjustments_y_only( adjustments->brightness); } +unsigned int log_2(unsigned int num) +{ + unsigned int result = 0; + + while ((num >>= 1) != 0) + result++; + + return result; +} diff --git a/drivers/gpu/drm/amd/display/dc/basics/conversion.h b/drivers/gpu/drm/amd/display/dc/basics/conversion.h index 18cbe41e80ff..b7fe431a7952 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/conversion.h +++ b/drivers/gpu/drm/amd/display/dc/basics/conversion.h @@ -48,4 +48,6 @@ void calculate_adjustments_y_only( const struct dc_csc_adjustments *adjustments, struct fixed31_32 *matrix); +unsigned int log_2(unsigned int num); + #endif diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c index fd8a49afbec6..e9005e0048e6 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c @@ -25,6 +25,7 @@ #include "mem_input.h" #include "reg_helper.h" +#include "basics/conversion.h" #define CTX \ mi->ctx @@ -129,16 +130,6 @@ static bool is_vert_scan(enum dc_rotation_angle rotation) } } -static unsigned int log_2(unsigned int num) -{ - unsigned int result = 0; - - while ((num >>= 1) != 0) - result++; - - return result; -} - void dce_mem_input_program_pte_vm(struct mem_input *mi, enum surface_pixel_format format, union dc_tiling_info *tiling_info, -- cgit From fb735a9f29f94fcb29fee224b8da704a510a5a3a Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Tue, 13 Dec 2016 13:59:41 -0500 Subject: drm/amd/display: Add in/out transfer functions to DC Refactor part 1 of degamma/regamma programming. End goal is to have source and output transfer function in which dc can use to decide how to program the degamma and regamma HW. Gamma will be explicitly applied through dc_update_surfaces_for_target. Color module should build the logical curve with all adjustments applied and pass enough information for dc to program HW PWL. Signed-off-by: Anthony Koo Reviewed-by: Aric Cyr Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 38 +++++++++++-- drivers/gpu/drm/amd/display/dc/core/dc_surface.c | 64 ++++++++++++++++------ drivers/gpu/drm/amd/display/dc/dc.h | 40 +++++++++++++- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 36 ++++-------- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 5 ++ drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 4 +- 6 files changed, 135 insertions(+), 52 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 9a35e3bb8283..f20701a507da 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1455,6 +1455,34 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda surface->public.gamma_correction = updates[i].gamma; } + + if (updates[i].in_transfer_func && + updates[i].in_transfer_func != + surface->public.in_transfer_func) { + if (surface->public.in_transfer_func != NULL) + dc_transfer_func_release( + surface->public. + in_transfer_func); + + dc_transfer_func_retain( + updates[i].in_transfer_func); + surface->public.in_transfer_func = + updates[i].in_transfer_func; + } + + if (updates[i].out_transfer_func && + updates[i].out_transfer_func != + surface->public.out_transfer_func) { + if (surface->public.out_transfer_func != NULL) + dc_transfer_func_release( + surface->public. + out_transfer_func); + + dc_transfer_func_retain( + updates[i].out_transfer_func); + surface->public.out_transfer_func = + updates[i].out_transfer_func; + } } } @@ -1474,7 +1502,6 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda if (updates[i].plane_info || updates[i].scaling_info || is_new_pipe_surface[j]) { - apply_ctx = true; if (!pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) { @@ -1489,9 +1516,12 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda } } - if (updates[i].gamma) - core_dc->hwss.prepare_pipe_for_context( - core_dc, pipe_ctx, context); + if (is_new_pipe_surface[j] || + updates[i].gamma || + updates[i].in_transfer_func || + updates[i].out_transfer_func) + core_dc->hwss.set_gamma_correction( + pipe_ctx, pipe_ctx->surface); } if (apply_ctx) { core_dc->hwss.apply_ctx_for_surface(core_dc, surface, context); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index 06d8b326714a..8d2668406f3a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -45,11 +45,18 @@ struct gamma { int ref_count; }; +struct transfer_func { + struct core_transfer_func protected; + int ref_count; +}; + #define DC_SURFACE_TO_SURFACE(dc_surface) container_of(dc_surface, struct surface, protected.public) #define CORE_SURFACE_TO_SURFACE(core_surface) container_of(core_surface, struct surface, protected) #define DC_GAMMA_TO_GAMMA(dc_gamma) \ container_of(dc_gamma, struct gamma, protected.public) +#define DC_TRANSFER_FUNC_TO_TRANSFER_FUNC(dc_tf) \ + container_of(dc_tf, struct transfer_func, protected.public) #define CORE_GAMMA_TO_GAMMA(core_gamma) \ container_of(core_gamma, struct gamma, protected) @@ -66,6 +73,12 @@ static void destruct(struct surface *surface) { if (surface->protected.public.gamma_correction != NULL) dc_gamma_release(surface->protected.public.gamma_correction); + if (surface->protected.public.in_transfer_func != NULL) + dc_transfer_func_release( + surface->protected.public.in_transfer_func); + if (surface->protected.public.out_transfer_func != NULL) + dc_transfer_func_release( + surface->protected.public.out_transfer_func); } /******************************************************************************* @@ -163,16 +176,6 @@ void dc_surface_release(const struct dc_surface *dc_surface) } } -static bool construct_gamma(struct gamma *gamma) -{ - return true; -} - -static void destruct_gamma(struct gamma *gamma) -{ - -} - void dc_gamma_retain(const struct dc_gamma *dc_gamma) { struct gamma *gamma = DC_GAMMA_TO_GAMMA(dc_gamma); @@ -185,10 +188,8 @@ void dc_gamma_release(const struct dc_gamma *dc_gamma) struct gamma *gamma = DC_GAMMA_TO_GAMMA(dc_gamma); --gamma->ref_count; - if (gamma->ref_count == 0) { - destruct_gamma(gamma); + if (gamma->ref_count == 0) dm_free(gamma); - } } struct dc_gamma *dc_create_gamma() @@ -198,17 +199,44 @@ struct dc_gamma *dc_create_gamma() if (gamma == NULL) goto alloc_fail; - if (false == construct_gamma(gamma)) - goto construct_fail; - dc_gamma_retain(&gamma->protected.public); return &gamma->protected.public; -construct_fail: - dm_free(gamma); +alloc_fail: + return NULL; +} + +void dc_transfer_func_retain(const struct dc_transfer_func *dc_tf) +{ + struct transfer_func *tf = DC_TRANSFER_FUNC_TO_TRANSFER_FUNC(dc_tf); + + ++tf->ref_count; +} + +void dc_transfer_func_release(const struct dc_transfer_func *dc_tf) +{ + struct transfer_func *tf = DC_TRANSFER_FUNC_TO_TRANSFER_FUNC(dc_tf); + --tf->ref_count; + + if (tf->ref_count == 0) + dm_free(tf); +} + +struct dc_transfer_func *dc_create_transfer_func(const struct dc *dc) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + struct transfer_func *tf = dm_alloc(sizeof(*tf)); + + if (tf == NULL) + goto alloc_fail; + + dc_transfer_func_retain(&tf->protected.public); + + return &tf->protected.public; alloc_fail: return NULL; } + diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 7733292d42f8..aeb0c3be24d6 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -201,7 +201,8 @@ bool dc_init_dchub(struct dc *dc, struct dchub_init_data *dh_data); enum { RGB_256X3X16 = 256, - FLOAT_GAMMA_RAMP_MAX = 1025 + FLOAT_GAMMA_RAMP_MAX = 1025, + TRANSFER_FUNC_POINTS = 1025 }; enum dc_gamma_ramp_type { @@ -236,6 +237,31 @@ struct dc_gamma { uint32_t size; }; +enum dc_transfer_func_type { + TF_TYPE_PREDEFINED, + TF_TYPE_DISTRIBUTED_POINTS, +}; + +struct dc_transfer_func_distributed_points { + uint16_t red[TRANSFER_FUNC_POINTS]; + uint16_t green[TRANSFER_FUNC_POINTS]; + uint16_t blue[TRANSFER_FUNC_POINTS]; + uint16_t end_exponent; + uint16_t x_point_at_y1; +}; + +enum dc_transfer_func_predefined { + TRANSFER_FUNCTION_SRGB, + TRANSFER_FUNCTION_BT709, + TRANSFER_FUNCTION_LINEAR, +}; + +struct dc_transfer_func { + enum dc_transfer_func_type type; + enum dc_transfer_func_predefined tf; + struct dc_transfer_func_distributed_points tf_pts; +}; + struct dc_surface { bool visible; bool flip_immediate; @@ -256,7 +282,11 @@ struct dc_surface { bool horizontal_mirror; enum plane_stereo_format stereo_format; + /* TO BE REMOVED AFTER BELOW TRANSFER FUNCTIONS IMPLEMENTED */ const struct dc_gamma *gamma_correction; + + const struct dc_transfer_func *in_transfer_func; + const struct dc_transfer_func *out_transfer_func; }; struct dc_plane_info { @@ -287,8 +317,12 @@ struct dc_surface_update { /* following updates require alloc/sleep/spin that is not isr safe, * null means no updates */ + /* gamma TO BE REMOVED */ struct dc_gamma *gamma; + struct dc_transfer_func *in_transfer_func; + struct dc_transfer_func *out_transfer_func; + }; /* @@ -316,6 +350,10 @@ void dc_gamma_retain(const struct dc_gamma *dc_gamma); void dc_gamma_release(const struct dc_gamma *dc_gamma); struct dc_gamma *dc_create_gamma(void); +void dc_transfer_func_retain(const struct dc_transfer_func *dc_tf); +void dc_transfer_func_release(const struct dc_transfer_func *dc_tf); +struct dc_transfer_func *dc_create_transfer_func(const struct dc *dc); + /* * This structure holds a surface address. There could be multiple addresses * in cases such as Stereo 3D, Planar YUV, etc. Other per-flip attributes such diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 99937facf645..f6984e9ed169 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -231,16 +231,20 @@ static void build_prescale_params(struct ipp_prescale_params *prescale_params, } } -static bool set_gamma_ramp( - struct input_pixel_processor *ipp, - struct output_pixel_processor *opp, - const struct core_gamma *ramp, +static bool dce110_set_gamma_correction( + struct pipe_ctx *pipe_ctx, const struct core_surface *surface) { + struct input_pixel_processor *ipp = pipe_ctx->ipp; + struct output_pixel_processor *opp = pipe_ctx->opp; + const struct core_gamma *ramp = NULL; struct ipp_prescale_params prescale_params = { 0 }; struct pwl_params *regamma_params; bool result = false; + if (surface->public.gamma_correction) + ramp = DC_GAMMA_TO_CORE(surface->public.gamma_correction); + regamma_params = dm_alloc(sizeof(struct pwl_params)); if (regamma_params == NULL) goto regamma_alloc_fail; @@ -1842,33 +1846,13 @@ static void dce110_program_front_end_for_pipe( pipe_ctx->scl_data.recout.y); } - - -static void dce110_prepare_pipe_for_surface_commit( - struct core_dc *dc, - struct pipe_ctx *pipe_ctx, - struct validate_context *context) { - struct core_gamma *gamma = NULL; - - dc->hwss.increase_watermarks_for_pipe(dc, pipe_ctx, context); - - if (pipe_ctx->surface->public.gamma_correction) - gamma = DC_GAMMA_TO_CORE( - pipe_ctx->surface->public.gamma_correction); - - dc->hwss.set_gamma_correction( - pipe_ctx->ipp, - pipe_ctx->opp, - gamma, pipe_ctx->surface); -} - static void dce110_prepare_pipe_for_context( struct core_dc *dc, struct pipe_ctx *pipe_ctx, struct validate_context *context) { dce110_power_on_pipe_if_needed(dc, pipe_ctx, context); - dce110_prepare_pipe_for_surface_commit(dc, pipe_ctx, context); + dc->hwss.increase_watermarks_for_pipe(dc, pipe_ctx, context); } static void dce110_apply_ctx_for_surface( @@ -1920,7 +1904,7 @@ static const struct hw_sequencer_funcs dce110_funcs = { .set_plane_config = set_plane_config, .update_plane_addr = update_plane_addr, .update_pending_status = dce110_update_pending_status, - .set_gamma_correction = set_gamma_ramp, + .set_gamma_correction = dce110_set_gamma_correction, .power_down = dce110_power_down, .enable_accelerated_mode = dce110_enable_accelerated_mode, .enable_timing_synchronization = dce110_enable_timing_synchronization, diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 3cf9bfb6decd..a67d6756095d 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -66,6 +66,11 @@ struct core_gamma { struct dc_context *ctx; }; +struct core_transfer_func { + struct dc_transfer_func public; + struct dc_context *ctx; +}; + void enable_surface_flip_reporting(struct dc_surface *dc_surface, uint32_t controller_id); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index fcaf2c71e4eb..89a08342a51f 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -78,9 +78,7 @@ struct hw_sequencer_funcs { struct pipe_ctx *pipe_ctx); bool (*set_gamma_correction)( - struct input_pixel_processor *ipp, - struct output_pixel_processor *opp, - const struct core_gamma *ramp, + struct pipe_ctx *pipe_ctx, const struct core_surface *surface); void (*power_down)(struct core_dc *dc); -- cgit From b264d3455d9c8ce0bea422a04a867f0a724c7770 Mon Sep 17 00:00:00 2001 From: Jordan Lazare Date: Wed, 14 Dec 2016 15:35:13 -0500 Subject: drm/amd/dal: Add POLARIS12 support (v2) v2: agd: squash in dm fix, rebase Signed-off-by: Jordan Lazare Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 ++ drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 3 ++- drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c | 3 ++- drivers/gpu/drm/amd/display/include/dal_asic_id.h | 5 ++++- 4 files changed, 10 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') 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 e5ba23253814..2a7802c67eae 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1235,6 +1235,7 @@ int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) case CHIP_STONEY: case CHIP_POLARIS11: case CHIP_POLARIS10: + case CHIP_POLARIS12: if (dce110_register_irq_handlers(dm->adev)) { DRM_ERROR("DM: Failed to initialize IRQ\n"); return -1; @@ -1472,6 +1473,7 @@ static int dm_early_init(void *handle) adev->mode_info.num_dig = 9; break; case CHIP_POLARIS11: + case CHIP_POLARIS12: adev->mode_info.num_crtc = 5; adev->mode_info.num_hpd = 5; adev->mode_info.num_dig = 5; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index f552b0468186..343114b2680f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -60,7 +60,8 @@ enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id) break; } if (ASIC_REV_IS_POLARIS10_P(asic_id.hw_internal_rev) || - ASIC_REV_IS_POLARIS11_M(asic_id.hw_internal_rev)) { + ASIC_REV_IS_POLARIS11_M(asic_id.hw_internal_rev) || + ASIC_REV_IS_POLARIS12_V(asic_id.hw_internal_rev)) { dc_version = DCE_VERSION_11_2; } break; diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 3a478300b848..85d8b31acd02 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -1233,7 +1233,8 @@ static void bw_calcs_data_update_from_pplib(struct core_dc *dc) const struct resource_caps *dce112_resource_cap( struct hw_asic_id *asic_id) { - if (ASIC_REV_IS_POLARIS11_M(asic_id->hw_internal_rev)) + if (ASIC_REV_IS_POLARIS11_M(asic_id->hw_internal_rev) || + ASIC_REV_IS_POLARIS12_V(asic_id->hw_internal_rev)) return &polaris_11_resource_cap; else return &polaris_10_resource_cap; diff --git a/drivers/gpu/drm/amd/display/include/dal_asic_id.h b/drivers/gpu/drm/amd/display/include/dal_asic_id.h index 119297e3bdc0..46f1e88f5e27 100644 --- a/drivers/gpu/drm/amd/display/include/dal_asic_id.h +++ b/drivers/gpu/drm/amd/display/include/dal_asic_id.h @@ -85,6 +85,7 @@ /* DCE112 */ #define VI_POLARIS10_P_A0 80 #define VI_POLARIS11_M_A0 90 +#define VI_POLARIS12_V_A0 100 #define VI_UNKNOWN 0xFF @@ -95,7 +96,9 @@ #define ASIC_REV_IS_POLARIS10_P(eChipRev) ((eChipRev >= VI_POLARIS10_P_A0) && \ (eChipRev < VI_POLARIS11_M_A0)) -#define ASIC_REV_IS_POLARIS11_M(eChipRev) (eChipRev >= VI_POLARIS11_M_A0) +#define ASIC_REV_IS_POLARIS11_M(eChipRev) ((eChipRev >= VI_POLARIS11_M_A0) && \ + (eChipRev < VI_POLARIS12_V_A0)) +#define ASIC_REV_IS_POLARIS12_V(eChipRev) (eChipRev >= VI_POLARIS12_V_A0) /* DCE11 */ #define CZ_CARRIZO_A0 0x01 -- cgit From b90a2b23edeb1f5181c7baf0ecd305c7e6ab20b4 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Wed, 14 Dec 2016 16:05:22 -0500 Subject: drm/amd/display: Resolved HDMI assert in dal Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c index 842182ce93a8..0590e0a6cd07 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c @@ -94,12 +94,12 @@ static void dce110_update_generic_info_packet( /* poll dig_update_lock is not locked -> asic internal signal * assume otg master lock will unlock it */ - REG_WAIT(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_LOCK_STATUS, - 1, 10, max_retries); +/* REG_WAIT(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_LOCK_STATUS, + 0, 10, max_retries);*/ /* check if HW reading GSP memory */ REG_WAIT(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT, - 1, 10, max_retries); + 0, 10, max_retries); /* HW does is not reading GSP memory not reading too long -> * something wrong. clear GPS memory access and notify? -- cgit From ea24af3e21192a719603ed02ec42e549e3c4a66a Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Wed, 14 Dec 2016 16:26:27 -0500 Subject: drm/amd/display: Refactor to move color helper into module Refactor part 2 - Moving color helper into color module The color module will need table defined in the helper in order to calculate the logical regamma curve, and also to fully handle gamut remapping. Signed-off-by: Anthony Koo Reviewed-by: Aric Cyr Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/modules/color/color_helper.c | 199 +++++++++++++++++++++ .../drm/amd/display/modules/color/color_helper.h | 50 ++++++ .../gpu/drm/amd/display/modules/inc/mod_color.h | 4 +- 3 files changed, 251 insertions(+), 2 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/modules/color/color_helper.c create mode 100644 drivers/gpu/drm/amd/display/modules/color/color_helper.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/modules/color/color_helper.c b/drivers/gpu/drm/amd/display/modules/color/color_helper.c new file mode 100644 index 000000000000..c47d2962c6d4 --- /dev/null +++ b/drivers/gpu/drm/amd/display/modules/color/color_helper.c @@ -0,0 +1,199 @@ + +/** + * @file + * @date Copyright (c) 2008 Advanced Micro Devices, Inc. (unpublished) + * + * @brief Helper functions for color gamut calculation + * + * @internal + * All rights reserved. This notice is intended as a precaution against + * inadvertent publication and does not imply publication or any waiver + * of confidentiality. The year included in the foregoing notice is the + * year of creation of the work. + */ + +#include "dm_services.h" +#include "dc.h" +#include "mod_color.h" +#include "color_helper.h" + +const struct gamut_space_entry predefined_gamuts[] = { + /* x_red y_red x_gr y_gr x_blue y_blue a0 a1 a2 a3 gamma */ + [gamut_type_bt709] = {6400, 3300, 3000, 6000, 1500, 600, 180000, 4500, 99, 99, 2200}, + [gamut_type_bt601] = {6400, 3300, 2900, 6000, 1500, 600, 180000, 4500, 99, 99, 2200}, + [gamut_type_adobe_rgb] = {6400, 3300, 2100, 7100, 1500, 600, 180000, 4500, 99, 99, 2200}, + [gamut_type_srgb] = {6400, 3300, 3000, 6000, 1500, 600, 31308, 12920, 55, 55, 2400}, + [gamut_type_bt2020] = {7080, 2920, 1700, 7970, 1310, 460, 180000, 4500, 99, 99, 2200} +}; + +const struct white_point_coodinates_entry predefined_white_points[] = { + [white_point_type_5000k_horizon] = {5000, 3473, 3561}, + [white_point_type_6500k_noon] = {6500, 3127, 3290}, + [white_point_type_7500k_north_sky] = {7500, 3022, 3129}, + [white_point_type_9300k] = {9300, 2866, 2950} +}; + +const unsigned int white_point_entries = 91; + +const struct white_point_coodinates_entry white_point_temps[] = { + /*001*/{1000, 6499, 3474}, + /*002*/{1100, 6361, 3594}, + /*003*/{1200, 6226, 3703}, + /*004*/{1300, 6095, 3801}, + /*005*/{1400, 5966, 3887}, + /*006*/{1500, 5841, 3962}, + /*007*/{1600, 5720, 4025}, + /*008*/{1700, 5601, 4076}, + /*009*/{1800, 5486, 4118}, + /*010*/{1900, 5375, 4150}, + /*011*/{2000, 5267, 4173}, + /*012*/{2100, 5162, 4188}, + /*013*/{2200, 5062, 4196}, + /*014*/{2300, 4965, 4198}, + /*015*/{2400, 4872, 4194}, + /*016*/{2500, 4782, 4186}, + /*017*/{2600, 4696, 4173}, + /*018*/{2700, 4614, 4158}, + /*019*/{2800, 4535, 4139}, + /*020*/{2900, 4460, 4118}, + /*021*/{3000, 4388, 4095}, + /*022*/{3100, 4320, 4070}, + /*023*/{3200, 4254, 4044}, + /*024*/{3300, 4192, 4018}, + /*025*/{3400, 4132, 3990}, + /*026*/{3500, 4075, 3962}, + /*027*/{3600, 4021, 3934}, + /*028*/{3700, 3969, 3905}, + /*029*/{3800, 3919, 3877}, + /*030*/{3900, 3872, 3849}, + /*031*/{4000, 3827, 3820}, + /*032*/{4100, 3784, 3793}, + /*033*/{4200, 3743, 3765}, + /*034*/{4300, 3704, 3738}, + /*035*/{4400, 3666, 3711}, + /*036*/{4500, 3631, 3685}, + /*037*/{4600, 3596, 3659}, + /*038*/{4700, 3563, 3634}, + /*039*/{4800, 3532, 3609}, + /*040*/{4900, 3502, 3585}, + /*041*/{5000, 3473, 3561}, + /*042*/{5100, 3446, 3538}, + /*043*/{5200, 3419, 3516}, + /*044*/{5300, 3394, 3494}, + /*045*/{5400, 3369, 3472}, + /*046*/{5500, 3346, 3451}, + /*047*/{5600, 3323, 3431}, + /*048*/{5700, 3302, 3411}, + /*049*/{5800, 3281, 3392}, + /*050*/{5900, 3261, 3373}, + /*051*/{6000, 3242, 3355}, + /*052*/{6100, 3223, 3337}, + /*053*/{6200, 3205, 3319}, + /*054*/{6300, 3188, 3302}, + /*055*/{6400, 3161, 3296}, + /*056*/{6500, 3127, 3290}, /* This is the real white point sRGB */ + /*057*/{6600, 3126, 3264}, + /*058*/{6700, 3125, 3238}, + /*059*/{6800, 3110, 3224}, + /*060*/{6900, 3097, 3209}, + /*061*/{7000, 3083, 3195}, + /*062*/{7100, 3070, 3181}, + /*063*/{7200, 3058, 3168}, + /*064*/{7300, 3045, 3154}, + /*065*/{7400, 3034, 3142}, + /*066*/{7500, 3022, 3129}, + /*067*/{7600, 3011, 3117}, + /*068*/{7700, 3000, 3105}, + /*069*/{7800, 2990, 3094}, + /*070*/{7900, 2980, 3082}, + /*071*/{8000, 2970, 3071}, + /*072*/{8100, 2961, 3061}, + /*073*/{8200, 2952, 3050}, + /*074*/{8300, 2943, 3040}, + /*075*/{8400, 2934, 3030}, + /*076*/{8500, 2926, 3020}, + /*077*/{8600, 2917, 3011}, + /*078*/{8700, 2910, 3001}, + /*079*/{8800, 2902, 2992}, + /*080*/{8900, 2894, 2983}, + /*081*/{9000, 2887, 2975}, + /*082*/{9100, 2880, 2966}, + /*083*/{9200, 2873, 2958}, + /*084*/{9300, 2866, 2950}, + /*085*/{9400, 2860, 2942}, + /*086*/{9500, 2853, 2934}, + /*087*/{9600, 2847, 2927}, + /*088*/{9700, 2841, 2919}, + /*089*/{9800, 2835, 2912}, + /*090*/{9900, 2829, 2905}, + /*091*/{10000, 2824, 2898} +}; + +bool mod_color_find_predefined_gamut( + struct gamut_space_coordinates *out_gamut, + enum predefined_gamut_type type) +{ + out_gamut->redX = predefined_gamuts[type].redX; + out_gamut->redY = predefined_gamuts[type].redY; + out_gamut->greenX = predefined_gamuts[type].greenX; + out_gamut->greenY = predefined_gamuts[type].greenY; + out_gamut->blueX = predefined_gamuts[type].blueX; + out_gamut->blueY = predefined_gamuts[type].blueY; + + return true; +} + +bool mod_color_find_predefined_white_point( + struct white_point_coodinates *out_white_point, + enum predefined_white_point_type type) +{ + out_white_point->whiteX = predefined_white_points[type].whiteX; + out_white_point->whiteY = predefined_white_points[type].whiteY; + + return true; +} + +bool mod_color_find_white_point_from_temperature( + struct white_point_coodinates *out_white_point, + unsigned int temperature) +{ + int i; + unsigned int found = false; + struct white_point_coodinates_entry temp_white_point = + white_point_temps[55]; + + if (temperature < 1000 || temperature > 10000) + return false; + + for (i = 0; i < white_point_entries; i++) { + if (temperature == white_point_temps[i].temperature) { + temp_white_point = white_point_temps[i]; + found = true; + break; + } + } + + out_white_point->whiteX = temp_white_point.whiteX; + out_white_point->whiteY = temp_white_point.whiteY; + + return found; +} + +bool mod_color_find_temperature_from_white_point( + struct white_point_coodinates *in_white_point, + unsigned int *out_temperature) +{ + unsigned int i; + *out_temperature = 6500; + + for (i = 0; i < white_point_entries; i++) { + if (in_white_point->whiteX == white_point_temps[i].whiteX && + in_white_point->whiteY == white_point_temps[i].whiteY) { + *out_temperature = white_point_temps[i].temperature; + return true; + } + } + + return false; +} + diff --git a/drivers/gpu/drm/amd/display/modules/color/color_helper.h b/drivers/gpu/drm/amd/display/modules/color/color_helper.h new file mode 100644 index 000000000000..c0e6334b947e --- /dev/null +++ b/drivers/gpu/drm/amd/display/modules/color/color_helper.h @@ -0,0 +1,50 @@ +/** + * @file + * @date Copyright (c) 2008 Advanced Micro Devices, Inc. (unpublished) + * + * @brief Helper functions for color gamut calculation + * + * @internal + * All rights reserved. This notice is intended as a precaution against + * inadvertent publication and does not imply publication or any waiver + * of confidentiality. The year included in the foregoing notice is the + * year of creation of the work. + */ + +#ifndef COLOR_MOD_COLOR_HELPER_H_ +#define COLOR_MOD_COLOR_HELPER_H_ + +enum predefined_gamut_type { + gamut_type_bt709, + gamut_type_bt601, + gamut_type_adobe_rgb, + gamut_type_srgb, + gamut_type_bt2020, + gamut_type_unknown, +}; + +enum predefined_white_point_type { + white_point_type_5000k_horizon, + white_point_type_6500k_noon, + white_point_type_7500k_north_sky, + white_point_type_9300k, + white_point_type_unknown, +}; + +bool mod_color_find_predefined_gamut( + struct gamut_space_coordinates *out_gamut, + enum predefined_gamut_type type); + +bool mod_color_find_predefined_white_point( + struct white_point_coodinates *out_white_point, + unsigned int index); + +bool mod_color_find_white_point_from_temperature( + struct white_point_coodinates *out_white_point, + unsigned int temperature); + +bool mod_color_find_temperature_from_white_point( + struct white_point_coodinates *in_white_point, + unsigned int *out_temperature); + +#endif /* COLOR_MOD_COLOR_HELPER_H_ */ diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_color.h b/drivers/gpu/drm/amd/display/modules/inc/mod_color.h index 91abc173444a..787c2c0a0e14 100644 --- a/drivers/gpu/drm/amd/display/modules/inc/mod_color.h +++ b/drivers/gpu/drm/amd/display/modules/inc/mod_color.h @@ -28,6 +28,7 @@ #define MOD_COLOR_H_ #include "dm_services.h" +#include "color_helper.h" struct mod_color { int dummy; @@ -54,7 +55,6 @@ struct gamut_space_coordinates { }; struct gamut_space_entry { - unsigned int index; unsigned int redX; unsigned int redY; unsigned int greenX; @@ -75,7 +75,7 @@ struct white_point_coodinates { }; struct white_point_coodinates_entry { - unsigned int index; + unsigned int temperature; unsigned int whiteX; unsigned int whiteY; }; -- cgit From aa66df58b2f272dad459c9f02fa3718d844b9fc6 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Thu, 15 Dec 2016 10:50:48 -0500 Subject: drm/amd/display: Add debug option to disable dmcu Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 1 + drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 3 +++ 2 files changed, 4 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index aeb0c3be24d6..36f1c96605e8 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -147,6 +147,7 @@ struct dc_debug { bool disable_dfs_bypass; bool disable_power_gate; bool disable_clock_gate; + bool disable_dmcu; }; struct dc { diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index c73d6054cdda..a8a2290d47db 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -1821,6 +1821,9 @@ void dce110_link_encoder_init_dmcu_backlight_settings( uint32_t s2; uint32_t value; + if (enc->ctx->dc->debug.disable_dmcu) + return; + bl_pwm_cntl = REG_READ(BL_PWM_CNTL); /* It must not be 0, so we have to restore them -- cgit From 9cdc4e7ce4cae74bbe64a0e0ed15655dfa50a8a1 Mon Sep 17 00:00:00 2001 From: Roman Li Date: Thu, 15 Dec 2016 11:51:09 -0500 Subject: drm/amd/display: fix hotplug regression after code refactor The condition logic of REG_WAIT in dce110_stream_encoder_dp_blank() got inverted after refactoring. Signed-off-by: Roman Li Reviewed-by: Jordan Lazare Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c index 0590e0a6cd07..b74a29b40a66 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c @@ -635,7 +635,7 @@ static void dce110_stream_encoder_dp_blank( */ REG_WAIT(DP_VID_STREAM_CNTL, DP_VID_STREAM_STATUS, - 1, + 0, 10, max_retries); ASSERT(retries <= max_retries); -- cgit From 90e508ba253c9e43711a7bf16230cdb13d0b1440 Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Thu, 15 Dec 2016 12:09:46 -0500 Subject: drm/amd/display: Refactor output transfer function to stream Refactor part 3 - Moving output transfer function from surface to stream Split HWSS to program degamma and regamma separately. Degamma should be dependent on input transfer function. And Regamma should depend on the desired output transfer function. Signed-off-by: Anthony Koo Reviewed-by: Aric Cyr Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 11 ++++ drivers/gpu/drm/amd/display/dc/core/dc.c | 23 +++++--- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 3 + drivers/gpu/drm/amd/display/dc/core/dc_surface.c | 6 +- drivers/gpu/drm/amd/display/dc/dc.h | 9 +-- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 65 ++++++++++++++++++---- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 3 + drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 7 ++- 8 files changed, 97 insertions(+), 30 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index c073f4558cf4..364f2c970b6e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -513,6 +513,7 @@ static void fill_gamma_from_crtc( struct dc_gamma *gamma; struct drm_crtc_state *state = crtc->state; struct drm_color_lut *lut = (struct drm_color_lut *) state->gamma_lut->data; + struct dc_transfer_func *input_tf; gamma = dc_create_gamma(); @@ -529,6 +530,16 @@ static void fill_gamma_from_crtc( gamma->size = sizeof(gamma->gamma_ramp_rgb256x3x16); dc_surface->gamma_correction = gamma; + + input_tf = dc_create_transfer_func(); + + if (input_tf == NULL) + return; + + input_tf->type = TF_TYPE_PREDEFINED; + input_tf->tf = TRANSFER_FUNCTION_SRGB; + + dc_surface->in_transfer_func = input_tf; } static void fill_plane_attributes( diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index f20701a507da..df1bae8ea92b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1394,6 +1394,7 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; + struct core_stream *stream = pipe_ctx->stream; if (pipe_ctx->surface != surface) continue; @@ -1472,15 +1473,14 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda if (updates[i].out_transfer_func && updates[i].out_transfer_func != - surface->public.out_transfer_func) { - if (surface->public.out_transfer_func != NULL) + stream->public.out_transfer_func) { + if (stream->public.out_transfer_func != NULL) dc_transfer_func_release( - surface->public. + stream->public. out_transfer_func); - dc_transfer_func_retain( updates[i].out_transfer_func); - surface->public.out_transfer_func = + stream->public.out_transfer_func = updates[i].out_transfer_func; } } @@ -1516,12 +1516,19 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda } } + if (is_new_pipe_surface[j] || + updates[i].in_transfer_func) + core_dc->hwss.set_input_transfer_func( + pipe_ctx, pipe_ctx->surface); + if (is_new_pipe_surface[j] || updates[i].gamma || - updates[i].in_transfer_func || updates[i].out_transfer_func) - core_dc->hwss.set_gamma_correction( - pipe_ctx, pipe_ctx->surface); + core_dc->hwss.set_output_transfer_func( + pipe_ctx, + pipe_ctx->surface, + pipe_ctx->stream); + } if (apply_ctx) { core_dc->hwss.apply_ctx_for_surface(core_dc, surface, context); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 8d6aa607e1f5..237436e22720 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -89,6 +89,9 @@ static bool construct(struct core_stream *stream, static void destruct(struct core_stream *stream) { dc_sink_release(&stream->sink->public); + if (stream->public.out_transfer_func != NULL) + dc_transfer_func_release( + stream->public.out_transfer_func); } void dc_stream_retain(const struct dc_stream *dc_stream) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index 8d2668406f3a..3ec1f363e43e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -76,9 +76,6 @@ static void destruct(struct surface *surface) if (surface->protected.public.in_transfer_func != NULL) dc_transfer_func_release( surface->protected.public.in_transfer_func); - if (surface->protected.public.out_transfer_func != NULL) - dc_transfer_func_release( - surface->protected.public.out_transfer_func); } /******************************************************************************* @@ -223,9 +220,8 @@ void dc_transfer_func_release(const struct dc_transfer_func *dc_tf) dm_free(tf); } -struct dc_transfer_func *dc_create_transfer_func(const struct dc *dc) +struct dc_transfer_func *dc_create_transfer_func() { - struct core_dc *core_dc = DC_TO_CORE(dc); struct transfer_func *tf = dm_alloc(sizeof(*tf)); if (tf == NULL) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 36f1c96605e8..ffea10c73275 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -254,6 +254,7 @@ struct dc_transfer_func_distributed_points { enum dc_transfer_func_predefined { TRANSFER_FUNCTION_SRGB, TRANSFER_FUNCTION_BT709, + TRANSFER_FUNCTION_PQ, TRANSFER_FUNCTION_LINEAR, }; @@ -287,7 +288,6 @@ struct dc_surface { const struct dc_gamma *gamma_correction; const struct dc_transfer_func *in_transfer_func; - const struct dc_transfer_func *out_transfer_func; }; struct dc_plane_info { @@ -353,7 +353,7 @@ struct dc_gamma *dc_create_gamma(void); void dc_transfer_func_retain(const struct dc_transfer_func *dc_tf); void dc_transfer_func_release(const struct dc_transfer_func *dc_tf); -struct dc_transfer_func *dc_create_transfer_func(const struct dc *dc); +struct dc_transfer_func *dc_create_transfer_func(void); /* * This structure holds a surface address. There could be multiple addresses @@ -527,10 +527,11 @@ struct dc_stream { struct freesync_context freesync_ctx; - /* TODO: dithering */ - /* TODO: transfer function (CSC/regamma/gamut remap) */ + const struct dc_transfer_func *out_transfer_func; struct colorspace_transform gamut_remap_matrix; struct csc_transform csc_color_matrix; + + /* TODO: dithering */ /* TODO: custom INFO packets */ /* TODO: ABM info (DMCU) */ /* TODO: PSR info */ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index f6984e9ed169..72017d5a8252 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -231,11 +231,61 @@ static void build_prescale_params(struct ipp_prescale_params *prescale_params, } } -static bool dce110_set_gamma_correction( +static bool dce110_set_degamma( struct pipe_ctx *pipe_ctx, const struct core_surface *surface) { struct input_pixel_processor *ipp = pipe_ctx->ipp; + const struct core_transfer_func *tf = NULL; + struct ipp_prescale_params prescale_params = { 0 }; + bool result = true; + + if (ipp == NULL) + return false; + + if (surface->public.in_transfer_func) + tf = DC_TRANSFER_FUNC_TO_CORE(surface->public.in_transfer_func); + + build_prescale_params(&prescale_params, surface); + ipp->funcs->ipp_program_prescale(ipp, &prescale_params); + + if (tf == NULL) { + /* Default case if no input transfer function specified */ + ipp->funcs->ipp_set_degamma(ipp, + IPP_DEGAMMA_MODE_BYPASS); + } else if (tf->public.type == TF_TYPE_PREDEFINED) { + switch (tf->public.tf) { + case TRANSFER_FUNCTION_SRGB: + ipp->funcs->ipp_set_degamma(ipp, + IPP_DEGAMMA_MODE_HW_sRGB); + break; + case TRANSFER_FUNCTION_BT709: + ipp->funcs->ipp_set_degamma(ipp, + IPP_DEGAMMA_MODE_HW_xvYCC); + break; + case TRANSFER_FUNCTION_LINEAR: + ipp->funcs->ipp_set_degamma(ipp, + IPP_DEGAMMA_MODE_BYPASS); + break; + case TRANSFER_FUNCTION_PQ: + result = false; + break; + default: + result = false; + } + } else { + /*TF_TYPE_DISTRIBUTED_POINTS - Not supported in DCE 11*/ + result = false; + } + + return result; +} + +static bool dce110_set_output_transfer_func( + struct pipe_ctx *pipe_ctx, + const struct core_surface *surface, /* Surface - To be removed */ + const struct core_stream *stream) +{ struct output_pixel_processor *opp = pipe_ctx->opp; const struct core_gamma *ramp = NULL; struct ipp_prescale_params prescale_params = { 0 }; @@ -253,20 +303,10 @@ static bool dce110_set_gamma_correction( opp->funcs->opp_power_on_regamma_lut(opp, true); - if (ipp) { - build_prescale_params(&prescale_params, surface); - ipp->funcs->ipp_program_prescale(ipp, &prescale_params); - } - if (ramp && calculate_regamma_params(regamma_params, ramp, surface)) { - opp->funcs->opp_program_regamma_pwl(opp, regamma_params); - if (ipp) - ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_HW_sRGB); opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_USER); } else { - if (ipp) - ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS); opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_BYPASS); } @@ -1904,7 +1944,8 @@ static const struct hw_sequencer_funcs dce110_funcs = { .set_plane_config = set_plane_config, .update_plane_addr = update_plane_addr, .update_pending_status = dce110_update_pending_status, - .set_gamma_correction = dce110_set_gamma_correction, + .set_input_transfer_func = dce110_set_degamma, + .set_output_transfer_func = dce110_set_output_transfer_func, .power_down = dce110_power_down, .enable_accelerated_mode = dce110_enable_accelerated_mode, .enable_timing_synchronization = dce110_enable_timing_synchronization, diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index a67d6756095d..c2d35c2c28bf 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -55,6 +55,9 @@ struct core_target { #define DC_GAMMA_TO_CORE(dc_gamma) \ container_of(dc_gamma, struct core_gamma, public) +#define DC_TRANSFER_FUNC_TO_CORE(dc_transfer_func) \ + container_of(dc_transfer_func, struct core_transfer_func, public) + struct core_surface { struct dc_surface public; struct dc_surface_status status; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 89a08342a51f..0e803ca83bb9 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -77,10 +77,15 @@ struct hw_sequencer_funcs { void (*update_pending_status)( struct pipe_ctx *pipe_ctx); - bool (*set_gamma_correction)( + bool (*set_input_transfer_func)( struct pipe_ctx *pipe_ctx, const struct core_surface *surface); + bool (*set_output_transfer_func)( + struct pipe_ctx *pipe_ctx, + const struct core_surface *surface, + const struct core_stream *stream); + void (*power_down)(struct core_dc *dc); void (*enable_accelerated_mode)(struct core_dc *dc); -- cgit From cb9a5a90eee4a02ea529b3101645bb959efaf4a8 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Thu, 15 Dec 2016 13:53:15 -0500 Subject: drm/amd/display: define reg helpers to update registers with 8 and 9 fields Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/inc/reg_helper.h | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h b/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h index a07817472089..b595b94d2b69 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h +++ b/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h @@ -112,6 +112,31 @@ FN(reg, f6), v6,\ FN(reg, f7), v7) +#define REG_SET_8(reg, init_value, f1, v1, f2, v2, f3, v3, f4, v4, \ + f5, v5, f6, v6, f7, v7, f8, v8) \ + REG_SET_N(reg, 8, init_value, \ + FN(reg, f1), v1,\ + FN(reg, f2), v2,\ + FN(reg, f3), v3,\ + FN(reg, f4), v4,\ + FN(reg, f5), v5,\ + FN(reg, f6), v6,\ + FN(reg, f7), v7,\ + FN(reg, f8), v8) + +#define REG_SET_9(reg, init_value, f1, v1, f2, v2, f3, v3, f4, v4, f5, \ + v5, f6, v6, f7, v7, f8, v8, f9, v9) \ + REG_SET_N(reg, 9, init_value, \ + FN(reg, f1), v1,\ + FN(reg, f2), v2, \ + FN(reg, f3), v3, \ + FN(reg, f4), v4, \ + FN(reg, f5), v5, \ + FN(reg, f6), v6, \ + FN(reg, f7), v7, \ + FN(reg, f8), v8, \ + FN(reg, f9), v9) + #define REG_SET_10(reg, init_value, f1, v1, f2, v2, f3, v3, f4, v4, f5, \ v5, f6, v6, f7, v7, f8, v8, f9, v9, f10, v10) \ REG_SET_N(reg, 10, init_value, \ -- cgit From c5ea922237f7dda25c488810a7c1ee9deadc9684 Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Fri, 16 Dec 2016 10:43:21 -0500 Subject: drm/amd/display: Refactor to move gamma correction to module Refactor part 4 - Moving input gamma correction programming into color module DM will translate to dc_gamma structure, but programming will be moved into the color module. Later, this will allow gamma correction to be added on top of in/out transfer function curves. Signed-off-by: Anthony Koo Reviewed-by: Anthony Koo Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/modules/color/color.c | 77 ++++++++++++++++++++++ .../gpu/drm/amd/display/modules/inc/mod_color.h | 4 ++ 2 files changed, 81 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/modules/color/color.c b/drivers/gpu/drm/amd/display/modules/color/color.c index 0610b82b6d84..6613ff9f4d28 100644 --- a/drivers/gpu/drm/amd/display/modules/color/color.c +++ b/drivers/gpu/drm/amd/display/modules/color/color.c @@ -69,6 +69,7 @@ struct color_state { struct color_range saturation; struct color_range brightness; struct color_range hue; + struct dc_gamma *gamma; enum dc_quantization_range preferred_quantization_range; }; @@ -1265,6 +1266,26 @@ static void calculate_csc_matrix(struct core_color *core_color, } } +static struct dc_surface *dc_stream_to_surface_from_pipe_ctx( + struct core_color *core_color, + const struct dc_stream *stream) +{ + int i; + struct core_dc *core_dc = DC_TO_CORE(core_color->dc); + struct core_stream *core_stream = DC_STREAM_TO_CORE(stream); + struct dc_surface *out_surface = NULL; + + for (i = 0; i < MAX_PIPES; i++) { + if (core_dc->current_context->res_ctx.pipe_ctx[i].stream + == core_stream) { + out_surface = &core_dc->current_context->res_ctx. + pipe_ctx[i].surface->public; + break; + } + } + return out_surface; +} + struct mod_color *mod_color_create(struct dc *dc) { int i = 0; @@ -1369,6 +1390,10 @@ void mod_color_destroy(struct mod_color *mod_color) struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); + for (i = 0; i < core_color->num_sinks; i++) + if (core_color->state[i].gamma) + dc_gamma_release(core_color->state[i].gamma); + dm_free(core_color->state); for (i = 0; i < core_color->num_sinks; i++) @@ -1552,6 +1577,9 @@ bool mod_color_remove_sink(struct mod_color *mod_color, for (i = 0; i < core_color->num_sinks; i++) { if (core_color->caps[i].sink == sink) { + if (core_color->state[i].gamma) + dc_gamma_release(core_color->state[i].gamma); + /* To remove this sink, shift everything after down */ for (j = i; j < core_color->num_sinks - 1; j++) { core_color->caps[j].sink = @@ -2184,6 +2212,55 @@ bool mod_color_set_saturation(struct mod_color *mod_color, return true; } +bool mod_color_set_input_gamma_correction(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + struct dc_gamma *gamma) +{ + struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); + unsigned int stream_index, sink_index; + + for (stream_index = 0; stream_index < num_streams; stream_index++) { + sink_index = sink_index_from_sink(core_color, + streams[stream_index]->sink); + + struct dc_surface *surface = + dc_stream_to_surface_from_pipe_ctx(core_color, + streams[stream_index]); + + if (surface != NULL) { + struct dc_transfer_func *input_tf = + dc_create_transfer_func(core_color->dc); + struct dc_surface_update updates = {0}; + + if (input_tf != NULL) { + input_tf->type = TF_TYPE_PREDEFINED; + input_tf->tf = TRANSFER_FUNCTION_SRGB; + } + + if (core_color->state[sink_index].gamma != gamma) { + if (core_color->state[sink_index].gamma) + dc_gamma_release( + core_color->state[sink_index]. + gamma); + + dc_gamma_retain(gamma); + core_color->state[sink_index].gamma = gamma; + } + + updates.surface = surface; + updates.gamma = gamma; + updates.in_transfer_func = input_tf; + dc_update_surfaces_for_target(core_color->dc, &updates, + 1, NULL); + + if (input_tf != NULL) + dc_transfer_func_release(input_tf); + } + } + + return true; +} + bool mod_color_persist_user_preferred_quantization_range( struct mod_color *mod_color, const struct dc_sink *sink, diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_color.h b/drivers/gpu/drm/amd/display/modules/inc/mod_color.h index 787c2c0a0e14..fbf908141ba7 100644 --- a/drivers/gpu/drm/amd/display/modules/inc/mod_color.h +++ b/drivers/gpu/drm/amd/display/modules/inc/mod_color.h @@ -168,6 +168,10 @@ bool mod_color_set_saturation(struct mod_color *mod_color, const struct dc_stream **streams, int num_streams, int saturation_value); +bool mod_color_set_input_gamma_correction(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + struct dc_gamma *gamma); + bool mod_color_persist_user_preferred_quantization_range( struct mod_color *mod_color, const struct dc_sink *sink, -- cgit From e63d86dc9b59d72cf25c6bc75e641bceed4fcd40 Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Fri, 16 Dec 2016 12:12:03 -0500 Subject: drm/amd/display: Implement PQ curve based on output transfer function Refactor part 5 - Regamma programming should be dependent on Output transfer function type Program sRGB gamma or PQ transfer function based on output transfer function. Signed-off-by: Anthony Koo Reviewed-by: Aric Cyr Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c | 93 ++++++++++++++++++++-- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 3 +- drivers/gpu/drm/amd/display/dc/inc/gamma_calcs.h | 3 +- 3 files changed, 92 insertions(+), 7 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c index 854796aa0c71..973be8f649cc 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c @@ -791,6 +791,82 @@ static inline struct fixed31_32 calculate_oem_mapped_value( max_index); } +static void compute_pq(struct fixed31_32 in_x, struct fixed31_32 *out_y) +{ + /* consts for PQ gamma formula. */ + const struct fixed31_32 m1 = + dal_fixed31_32_from_fraction(159301758, 1000000000); + const struct fixed31_32 m2 = + dal_fixed31_32_from_fraction(7884375, 100000); + const struct fixed31_32 c1 = + dal_fixed31_32_from_fraction(8359375, 10000000); + const struct fixed31_32 c2 = + dal_fixed31_32_from_fraction(188515625, 10000000); + const struct fixed31_32 c3 = + dal_fixed31_32_from_fraction(186875, 10000); + + struct fixed31_32 l_pow_m1; + struct fixed31_32 base; + + if (dal_fixed31_32_lt(in_x, dal_fixed31_32_zero)) + in_x = dal_fixed31_32_zero; + + l_pow_m1 = dal_fixed31_32_pow(in_x, m1); + base = dal_fixed31_32_div( + dal_fixed31_32_add(c1, + (dal_fixed31_32_mul(c2, l_pow_m1))), + dal_fixed31_32_add(dal_fixed31_32_one, + (dal_fixed31_32_mul(c3, l_pow_m1)))); + *out_y = dal_fixed31_32_pow(base, m2); +} + +static void build_regamma_curve_pq(struct pwl_float_data_ex *rgb_regamma, + struct pwl_float_data *rgb_oem, + struct pixel_gamma_point *coeff128_oem, + const struct core_gamma *ramp, + const struct core_surface *surface, + uint32_t hw_points_num, + const struct hw_x_point *coordinate_x, + const struct gamma_pixel *axis_x, + struct dividers dividers) +{ + uint32_t i; + + struct pwl_float_data_ex *rgb = rgb_regamma; + const struct hw_x_point *coord_x = coordinate_x; + struct fixed31_32 x; + struct fixed31_32 output; + struct fixed31_32 scaling_factor = + dal_fixed31_32_from_fraction(8, 1000); + + /* use coord_x to retrieve coordinates chosen base on given user curve + * the x values are exponentially distributed and currently it is hard + * coded, the user curve shape is ignored. Need to recalculate coord_x + * based on input curve, translation from 256/1025 to 128 PWL points. + */ + for (i = 0; i <= hw_points_num; i++) { + /* Multiply 0.008 as regamma is 0-1 and FP16 input is 0-125. + * FP 1.0 = 80nits + */ + x = dal_fixed31_32_mul(coord_x->adjusted_x, scaling_factor); + + compute_pq(x, &output); + + /* should really not happen? */ + if (dal_fixed31_32_lt(output, dal_fixed31_32_zero)) + output = dal_fixed31_32_zero; + else if (dal_fixed31_32_lt(dal_fixed31_32_one, output)) + output = dal_fixed31_32_one; + + rgb->r = output; + rgb->g = output; + rgb->b = output; + + ++coord_x; + ++rgb; + } +} + static void build_regamma_curve(struct pwl_float_data_ex *rgb_regamma, struct pwl_float_data *rgb_oem, struct pixel_gamma_point *coeff128_oem, @@ -1286,7 +1362,8 @@ static bool convert_to_custom_float( bool calculate_regamma_params(struct pwl_params *params, const struct core_gamma *ramp, - const struct core_surface *surface) + const struct core_surface *surface, + const struct core_stream *stream) { struct gamma_curve *arr_curve_points = params->arr_curve_points; struct curve_points *arr_points = params->arr_points; @@ -1301,7 +1378,6 @@ bool calculate_regamma_params(struct pwl_params *params, struct pixel_gamma_point *coeff128_oem = NULL; struct pixel_gamma_point *coeff128 = NULL; - bool ret = false; coordinates_x = dm_alloc(sizeof(*coordinates_x)*(256 + 3)); @@ -1341,9 +1417,16 @@ bool calculate_regamma_params(struct pwl_params *params, setup_distribution_points(arr_curve_points, arr_points, ¶ms->hw_points_num, coordinates_x); - build_regamma_curve(rgb_regamma, rgb_oem, coeff128_oem, - ramp, surface, params->hw_points_num, - coordinates_x, axix_x_256, dividers); + if (stream->public.out_transfer_func && + stream->public.out_transfer_func->tf == TRANSFER_FUNCTION_PQ) { + build_regamma_curve_pq(rgb_regamma, rgb_oem, coeff128_oem, + ramp, surface, params->hw_points_num, + coordinates_x, axix_x_256, dividers); + } else { + build_regamma_curve(rgb_regamma, rgb_oem, coeff128_oem, + ramp, surface, params->hw_points_num, + coordinates_x, axix_x_256, dividers); + } map_regamma_hw_to_x_user(coeff128, rgb_oem, rgb_resulted, rgb_user, coordinates_x, axix_x_256, &ramp->public, rgb_regamma, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 72017d5a8252..2f790753b559 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -303,7 +303,8 @@ static bool dce110_set_output_transfer_func( opp->funcs->opp_power_on_regamma_lut(opp, true); - if (ramp && calculate_regamma_params(regamma_params, ramp, surface)) { + if (ramp && calculate_regamma_params( + regamma_params, ramp, surface, stream)) { opp->funcs->opp_program_regamma_pwl(opp, regamma_params); opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_USER); } else { diff --git a/drivers/gpu/drm/amd/display/dc/inc/gamma_calcs.h b/drivers/gpu/drm/amd/display/dc/inc/gamma_calcs.h index e2c63fd4fe92..0712268856c2 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/gamma_calcs.h +++ b/drivers/gpu/drm/amd/display/dc/inc/gamma_calcs.h @@ -14,6 +14,7 @@ bool calculate_regamma_params(struct pwl_params *params, const struct core_gamma *ramp, - const struct core_surface *surface); + const struct core_surface *surface, + const struct core_stream *stream); #endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_GAMMA_CALCS_H_ */ -- cgit From ab3ee7a556343c9549ccbefb9d31039377806f28 Mon Sep 17 00:00:00 2001 From: Zeyu Fan Date: Wed, 14 Dec 2016 18:54:41 -0500 Subject: drm/amd/display: OPP refactor and consolidation for DCE. Signed-off-by: Zeyu Fan Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/Makefile | 2 +- drivers/gpu/drm/amd/display/dc/dce/dce_opp.c | 996 +++++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dce/dce_opp.h | 418 +++++++++ .../drm/amd/display/dc/dce100/dce100_resource.c | 61 +- drivers/gpu/drm/amd/display/dc/dce110/Makefile | 4 +- drivers/gpu/drm/amd/display/dc/dce110/dce110_opp.c | 77 -- drivers/gpu/drm/amd/display/dc/dce110/dce110_opp.h | 149 --- .../gpu/drm/amd/display/dc/dce110/dce110_opp_csc.c | 363 -------- .../drm/amd/display/dc/dce110/dce110_opp_csc_v.c | 2 +- .../amd/display/dc/dce110/dce110_opp_formatter.c | 627 ------------- .../drm/amd/display/dc/dce110/dce110_opp_regamma.c | 537 ----------- .../amd/display/dc/dce110/dce110_opp_regamma_v.c | 2 +- .../gpu/drm/amd/display/dc/dce110/dce110_opp_v.c | 2 +- .../drm/amd/display/dc/dce110/dce110_resource.c | 60 +- drivers/gpu/drm/amd/display/dc/dce112/Makefile | 3 +- drivers/gpu/drm/amd/display/dc/dce112/dce112_opp.c | 72 -- drivers/gpu/drm/amd/display/dc/dce112/dce112_opp.h | 48 - .../amd/display/dc/dce112/dce112_opp_formatter.c | 215 ----- .../drm/amd/display/dc/dce112/dce112_resource.c | 70 +- drivers/gpu/drm/amd/display/dc/dce80/Makefile | 5 +- drivers/gpu/drm/amd/display/dc/dce80/dce80_opp.c | 136 --- drivers/gpu/drm/amd/display/dc/dce80/dce80_opp.h | 130 --- .../gpu/drm/amd/display/dc/dce80/dce80_opp_csc.c | 363 -------- .../drm/amd/display/dc/dce80/dce80_opp_formatter.c | 577 ------------ .../drm/amd/display/dc/dce80/dce80_opp_regamma.c | 543 ----------- .../gpu/drm/amd/display/dc/dce80/dce80_resource.c | 45 +- 26 files changed, 1547 insertions(+), 3960 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_opp.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_opp.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_opp.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_opp.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_formatter.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dce112/dce112_opp.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dce112/dce112_opp.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dce112/dce112_opp_formatter.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_opp.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_opp.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_csc.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_formatter.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_regamma.c (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/Makefile b/drivers/gpu/drm/amd/display/dc/dce/Makefile index 6add5977fd39..5ad59a27738c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dce/Makefile @@ -7,7 +7,7 @@ DCE = dce_audio.o dce_stream_encoder.o dce_link_encoder.o dce_hwseq.o \ dce_mem_input.o dce_clock_source.o dce_scl_filters.o dce_transform.o \ -dce_clocks.o +dce_clocks.o dce_opp.o AMD_DAL_DCE = $(addprefix $(AMDDALPATH)/dc/dce/,$(DCE)) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c new file mode 100644 index 000000000000..80443a1cccd2 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c @@ -0,0 +1,996 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "basics/conversion.h" + +#include "dce_opp.h" + +#include "gamma_types.h" + +#include "reg_helper.h" + +#define REG(reg)\ + (opp110->regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + opp110->opp_shift->field_name, opp110->opp_mask->field_name + +#define CTX \ + opp110->base.ctx + +enum { + MAX_PWL_ENTRY = 128, + MAX_REGIONS_NUMBER = 16 +}; + +enum { + MAX_LUT_ENTRY = 256, + MAX_NUMBER_OF_ENTRIES = 256 +}; + + +enum { + OUTPUT_CSC_MATRIX_SIZE = 12 +}; + +static const struct out_csc_color_matrix global_color_matrix[] = { +{ COLOR_SPACE_SRGB, + { 0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} }, +{ COLOR_SPACE_SRGB_LIMITED, + { 0x1B60, 0, 0, 0x200, 0, 0x1B60, 0, 0x200, 0, 0, 0x1B60, 0x200} }, +{ COLOR_SPACE_YCBCR601, + { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x82F, 0x1012, 0x31F, 0x200, 0xFB47, + 0xF6B9, 0xE00, 0x1000} }, +{ COLOR_SPACE_YCBCR709, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x5D2, 0x1394, 0x1FA, + 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} }, +/* TODO: correct values below */ +{ COLOR_SPACE_YCBCR601_LIMITED, { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x991, + 0x12C9, 0x3A6, 0x200, 0xFB47, 0xF6B9, 0xE00, 0x1000} }, +{ COLOR_SPACE_YCBCR709_LIMITED, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x6CE, 0x16E3, + 0x24F, 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} } +}; + +enum csc_color_mode { + /* 00 - BITS2:0 Bypass */ + CSC_COLOR_MODE_GRAPHICS_BYPASS, + /* 01 - hard coded coefficient TV RGB */ + CSC_COLOR_MODE_GRAPHICS_PREDEFINED, + /* 04 - programmable OUTPUT CSC coefficient */ + CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC, +}; + + + + + + + + + + + + + + + + + + +/* + ***************************************************************************** + * Function: regamma_config_regions_and_segments + * + * build regamma curve by using predefined hw points + * uses interface parameters ,like EDID coeff. + * + * @param : parameters interface parameters + * @return void + * + * @note + * + * @see + * + ***************************************************************************** + */ +static void regamma_config_regions_and_segments( + struct dce110_opp *opp110, + const struct pwl_params *params) +{ + const struct gamma_curve *curve; + uint32_t value = 0; + + { + REG_SET_2(REGAMMA_CNTLA_START_CNTL, 0, + REGAMMA_CNTLA_EXP_REGION_START, params->arr_points[0].custom_float_x, + REGAMMA_CNTLA_EXP_REGION_START_SEGMENT, 0); + } + { + REG_SET(REGAMMA_CNTLA_SLOPE_CNTL, 0, + REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE, params->arr_points[0].custom_float_slope); + + } + { + REG_SET(REGAMMA_CNTLA_END_CNTL1, 0, + REGAMMA_CNTLA_EXP_REGION_END, params->arr_points[1].custom_float_x); + } + { + REG_SET_2(REGAMMA_CNTLA_END_CNTL2, 0, + REGAMMA_CNTLA_EXP_REGION_END_BASE, params->arr_points[2].custom_float_slope, + REGAMMA_CNTLA_EXP_REGION_END_SLOPE, params->arr_points[1].custom_float_y); + } + + curve = params->arr_curve_points; + + { + REG_SET_4(REGAMMA_CNTLA_REGION_0_1, 0, + REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + } + + curve += 2; + + { + REG_SET_4(REGAMMA_CNTLA_REGION_2_3, 0, + REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + } + + curve += 2; + + { + REG_SET_4(REGAMMA_CNTLA_REGION_4_5, 0, + REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + } + + curve += 2; + + { + REG_SET_4(REGAMMA_CNTLA_REGION_6_7, 0, + REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + } + + curve += 2; + + { + REG_SET_4(REGAMMA_CNTLA_REGION_8_9, 0, + REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + } + + curve += 2; + + { + REG_SET_4(REGAMMA_CNTLA_REGION_10_11, 0, + REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + } + + curve += 2; + + { + REG_SET_4(REGAMMA_CNTLA_REGION_12_13, 0, + REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + } + + curve += 2; + + { + REG_SET_4(REGAMMA_CNTLA_REGION_14_15, 0, + REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + } +} + +static void program_pwl( + struct dce110_opp *opp110, + const struct pwl_params *params) +{ + uint32_t value; + int retval; + + { + uint8_t max_tries = 10; + uint8_t counter = 0; + + /* Power on LUT memory */ + if (REG(DCFE_MEM_PWR_CTRL)) + REG_UPDATE(DCFE_MEM_PWR_CTRL, + DCP_REGAMMA_MEM_PWR_DIS, 1); + else + REG_UPDATE(DCFE_MEM_LIGHT_SLEEP_CNTL, + REGAMMA_LUT_LIGHT_SLEEP_DIS, 1); + + while (counter < max_tries) { + if (REG(DCFE_MEM_PWR_STATUS)) { + value = REG_READ(DCFE_MEM_PWR_STATUS); + REG_GET(DCFE_MEM_PWR_STATUS, + DCP_REGAMMA_MEM_PWR_STATE, + &retval); + + if (retval == 0) + break; + ++counter; + } else { + value = REG_READ(DCFE_MEM_LIGHT_SLEEP_CNTL); + REG_GET(DCFE_MEM_LIGHT_SLEEP_CNTL, + REGAMMA_LUT_MEM_PWR_STATE, + &retval); + + if (retval == 0) + break; + ++counter; + } + } + + if (counter == max_tries) { + dm_logger_write(opp110->base.ctx->logger, LOG_WARNING, + "%s: regamma lut was not powered on " + "in a timely manner," + " programming still proceeds\n", + __func__); + } + } + + REG_UPDATE(REGAMMA_LUT_WRITE_EN_MASK, + REGAMMA_LUT_WRITE_EN_MASK, 7); + + REG_WRITE(REGAMMA_LUT_INDEX, 0); + + /* Program REGAMMA_LUT_DATA */ + { + uint32_t i = 0; + const struct pwl_result_data *rgb = params->rgb_resulted; + + while (i != params->hw_points_num) { + + REG_WRITE(REGAMMA_LUT_DATA, rgb->red_reg); + REG_WRITE(REGAMMA_LUT_DATA, rgb->green_reg); + REG_WRITE(REGAMMA_LUT_DATA, rgb->blue_reg); + REG_WRITE(REGAMMA_LUT_DATA, rgb->delta_red_reg); + REG_WRITE(REGAMMA_LUT_DATA, rgb->delta_green_reg); + REG_WRITE(REGAMMA_LUT_DATA, rgb->delta_blue_reg); + + ++rgb; + ++i; + } + } + + /* we are done with DCP LUT memory; re-enable low power mode */ + if (REG(DCFE_MEM_PWR_CTRL)) + REG_UPDATE(DCFE_MEM_PWR_CTRL, + DCP_REGAMMA_MEM_PWR_DIS, 0); + else + REG_UPDATE(DCFE_MEM_LIGHT_SLEEP_CNTL, + REGAMMA_LUT_LIGHT_SLEEP_DIS, 0); +} + +bool dce110_opp_program_regamma_pwl( + struct output_pixel_processor *opp, + const struct pwl_params *params) +{ + struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + + /* Setup regions */ + regamma_config_regions_and_segments(opp110, params); + + /* Program PWL */ + program_pwl(opp110, params); + + return true; +} + +void dce110_opp_power_on_regamma_lut( + struct output_pixel_processor *opp, + bool power_on) +{ + struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + + if (REG(DCFE_MEM_PWR_CTRL)) + REG_UPDATE_2(DCFE_MEM_PWR_CTRL, + DCP_REGAMMA_MEM_PWR_DIS, power_on, + DCP_LUT_MEM_PWR_DIS, power_on); + else + REG_UPDATE_2(DCFE_MEM_LIGHT_SLEEP_CNTL, + REGAMMA_LUT_LIGHT_SLEEP_DIS, power_on, + DCP_LUT_LIGHT_SLEEP_DIS, power_on); + +} + +void dce110_opp_set_regamma_mode(struct output_pixel_processor *opp, + enum opp_regamma mode) +{ + struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + + REG_SET(REGAMMA_CONTROL, 0, + GRPH_REGAMMA_MODE, mode); +} + +/** + * set_truncation + * 1) set truncation depth: 0 for 18 bpp or 1 for 24 bpp + * 2) enable truncation + * 3) HW remove 12bit FMT support for DCE11 power saving reason. + */ +static void set_truncation( + struct dce110_opp *opp110, + const struct bit_depth_reduction_params *params) +{ + /*Disable truncation*/ + REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, + FMT_TRUNCATE_EN, 0, + FMT_TRUNCATE_DEPTH, 0, + FMT_TRUNCATE_MODE, 0); + /* no 10bpc trunc on DCE11*/ + if (params->flags.TRUNCATE_ENABLED == 0 || + params->flags.TRUNCATE_DEPTH == 2) + return; + + /*Set truncation depth and Enable truncation*/ + REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, + FMT_TRUNCATE_EN, 1, + FMT_TRUNCATE_DEPTH, params->flags.TRUNCATE_MODE, + FMT_TRUNCATE_MODE, params->flags.TRUNCATE_DEPTH); + +} + +/** + * set_spatial_dither + * 1) set spatial dithering mode: pattern of seed + * 2) set spatical dithering depth: 0 for 18bpp or 1 for 24bpp + * 3) set random seed + * 4) set random mode + * lfsr is reset every frame or not reset + * RGB dithering method + * 0: RGB data are all dithered with x^28+x^3+1 + * 1: R data is dithered with x^28+x^3+1 + * G data is dithered with x^28+X^9+1 + * B data is dithered with x^28+x^13+1 + * enable high pass filter or not + * 5) enable spatical dithering + */ +static void set_spatial_dither( + struct dce110_opp *opp110, + const struct bit_depth_reduction_params *params) +{ + /*Disable spatial (random) dithering*/ + REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, + FMT_SPATIAL_DITHER_EN, 0, + FMT_SPATIAL_DITHER_DEPTH, 0, + FMT_SPATIAL_DITHER_MODE, 0); + + REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, + FMT_HIGHPASS_RANDOM_ENABLE, 0, + FMT_FRAME_RANDOM_ENABLE, 0, + FMT_RGB_RANDOM_ENABLE, 0); + + REG_UPDATE(FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_DITHER_EN, 0); + + /* no 10bpc on DCE11*/ + if (params->flags.SPATIAL_DITHER_ENABLED == 0 || + params->flags.SPATIAL_DITHER_DEPTH == 2) + return; + + /* only use FRAME_COUNTER_MAX if frameRandom == 1*/ + + if (opp110->opp_mask->FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX && + opp110->opp_mask->FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP) { + if (params->flags.FRAME_RANDOM == 1) { + if (params->flags.SPATIAL_DITHER_DEPTH == 0 || + params->flags.SPATIAL_DITHER_DEPTH == 1) { + REG_UPDATE_2(FMT_CONTROL, + FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 15, + FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 2); + } else if (params->flags.SPATIAL_DITHER_DEPTH == 2) { + REG_UPDATE_2(FMT_CONTROL, + FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 3, + FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 1); + } else + return; + } else { + REG_UPDATE_2(FMT_CONTROL, + FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 0, + FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 0); + } + } + /* Set seed for random values for + * spatial dithering for R,G,B channels + */ + REG_UPDATE(FMT_DITHER_RAND_R_SEED, + FMT_RAND_R_SEED, params->r_seed_value); + + REG_UPDATE(FMT_DITHER_RAND_G_SEED, + FMT_RAND_G_SEED, params->g_seed_value); + + REG_UPDATE(FMT_DITHER_RAND_B_SEED, + FMT_RAND_B_SEED, params->b_seed_value); + + /* FMT_OFFSET_R_Cr 31:16 0x0 Setting the zero + * offset for the R/Cr channel, lower 4LSB + * is forced to zeros. Typically set to 0 + * RGB and 0x80000 YCbCr. + */ + /* FMT_OFFSET_G_Y 31:16 0x0 Setting the zero + * offset for the G/Y channel, lower 4LSB is + * forced to zeros. Typically set to 0 RGB + * and 0x80000 YCbCr. + */ + /* FMT_OFFSET_B_Cb 31:16 0x0 Setting the zero + * offset for the B/Cb channel, lower 4LSB is + * forced to zeros. Typically set to 0 RGB and + * 0x80000 YCbCr. + */ + + /* Disable High pass filter + * Reset only at startup + * Set RGB data dithered with x^28+x^3+1 + */ + REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, + FMT_HIGHPASS_RANDOM_ENABLE, params->flags.HIGHPASS_RANDOM, + FMT_FRAME_RANDOM_ENABLE, params->flags.FRAME_RANDOM, + FMT_RGB_RANDOM_ENABLE, params->flags.RGB_RANDOM); + + /* Set spatial dithering bit depth + * Set spatial dithering mode + * (default is Seed patterrn AAAA...) + * Enable spatial dithering + */ + REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, + FMT_SPATIAL_DITHER_DEPTH, params->flags.SPATIAL_DITHER_DEPTH, + FMT_SPATIAL_DITHER_MODE, params->flags.SPATIAL_DITHER_MODE, + FMT_SPATIAL_DITHER_EN, 1); +} + +/** + * SetTemporalDither (Frame Modulation) + * 1) set temporal dither depth + * 2) select pattern: from hard-coded pattern or programmable pattern + * 3) select optimized strips for BGR or RGB LCD sub-pixel + * 4) set s matrix + * 5) set t matrix + * 6) set grey level for 0.25, 0.5, 0.75 + * 7) enable temporal dithering + */ + +static void set_temporal_dither( + struct dce110_opp *opp110, + const struct bit_depth_reduction_params *params) +{ + /*Disable temporal (frame modulation) dithering first*/ + REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_DITHER_EN, 0, + FMT_TEMPORAL_DITHER_RESET, 0, + FMT_TEMPORAL_DITHER_OFFSET, 0); + + REG_UPDATE_2(FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_DITHER_DEPTH, 0, + FMT_TEMPORAL_LEVEL, 0); + + REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, + FMT_25FRC_SEL, 0, + FMT_50FRC_SEL, 0, + FMT_75FRC_SEL, 0); + + /* no 10bpc dither on DCE11*/ + if (params->flags.FRAME_MODULATION_ENABLED == 0 || + params->flags.FRAME_MODULATION_DEPTH == 2) + return; + + /* Set temporal dithering depth*/ + REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_DITHER_DEPTH, params->flags.FRAME_MODULATION_DEPTH, + FMT_TEMPORAL_DITHER_RESET, 0, + FMT_TEMPORAL_DITHER_OFFSET, 0); + + /*Select legacy pattern based on FRC and Temporal level*/ + if (REG(FMT_TEMPORAL_DITHER_PATTERN_CONTROL)) { + REG_WRITE(FMT_TEMPORAL_DITHER_PATTERN_CONTROL, 0); + /*Set s matrix*/ + REG_WRITE(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX, 0); + /*Set t matrix*/ + REG_WRITE(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX, 0); + } + + /*Select patterns for 0.25, 0.5 and 0.75 grey level*/ + REG_UPDATE(FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_LEVEL, params->flags.TEMPORAL_LEVEL); + + REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, + FMT_25FRC_SEL, params->flags.FRC25, + FMT_50FRC_SEL, params->flags.FRC50, + FMT_75FRC_SEL, params->flags.FRC75); + + /*Enable bit reduction by temporal (frame modulation) dithering*/ + REG_UPDATE(FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_DITHER_EN, 1); +} + +/** + * Set Clamping + * 1) Set clamping format based on bpc - 0 for 6bpc (No clamping) + * 1 for 8 bpc + * 2 for 10 bpc + * 3 for 12 bpc + * 7 for programable + * 2) Enable clamp if Limited range requested + */ +void dce110_opp_set_clamping( + struct dce110_opp *opp110, + const struct clamping_and_pixel_encoding_params *params) +{ + uint32_t clamp_cntl_value = 0; + + REG_SET_2(FMT_CLAMP_CNTL, 0, + FMT_CLAMP_DATA_EN, 0, + FMT_CLAMP_COLOR_FORMAT, 0); + + switch (params->clamping_level) { + case CLAMPING_FULL_RANGE: + break; + case CLAMPING_LIMITED_RANGE_8BPC: + REG_SET_2(FMT_CLAMP_CNTL, 0, + FMT_CLAMP_DATA_EN, 1, + FMT_CLAMP_COLOR_FORMAT, 1); + break; + case CLAMPING_LIMITED_RANGE_10BPC: + REG_SET_2(FMT_CLAMP_CNTL, 0, + FMT_CLAMP_DATA_EN, 1, + FMT_CLAMP_COLOR_FORMAT, 2); + break; + case CLAMPING_LIMITED_RANGE_12BPC: + REG_SET_2(FMT_CLAMP_CNTL, 0, + FMT_CLAMP_DATA_EN, 1, + FMT_CLAMP_COLOR_FORMAT, 3); + break; + case CLAMPING_LIMITED_RANGE_PROGRAMMABLE: + /*Set clamp control*/ + REG_SET_2(FMT_CLAMP_CNTL, 0, + FMT_CLAMP_DATA_EN, 1, + FMT_CLAMP_COLOR_FORMAT, 7); + + /*set the defaults*/ + REG_SET_2(FMT_CLAMP_COMPONENT_R, 0, + FMT_CLAMP_LOWER_R, 0x10, + FMT_CLAMP_UPPER_R, 0xFEF); + + REG_SET_2(FMT_CLAMP_COMPONENT_G, 0, + FMT_CLAMP_LOWER_G, 0x10, + FMT_CLAMP_UPPER_G, 0xFEF); + + REG_SET_2(FMT_CLAMP_COMPONENT_B, 0, + FMT_CLAMP_LOWER_B, 0x10, + FMT_CLAMP_UPPER_B, 0xFEF); + break; + default: + break; + } +} + +/** + * set_pixel_encoding + * + * Set Pixel Encoding + * 0: RGB 4:4:4 or YCbCr 4:4:4 or YOnly + * 1: YCbCr 4:2:2 + */ +static void set_pixel_encoding( + struct dce110_opp *opp110, + const struct clamping_and_pixel_encoding_params *params) +{ + if (opp110->opp_mask->FMT_CBCR_BIT_REDUCTION_BYPASS) + REG_UPDATE_3(FMT_CONTROL, + FMT_PIXEL_ENCODING, 0, + FMT_SUBSAMPLING_MODE, 0, + FMT_CBCR_BIT_REDUCTION_BYPASS, 0); + else + REG_UPDATE_2(FMT_CONTROL, + FMT_PIXEL_ENCODING, 0, + FMT_SUBSAMPLING_MODE, 0); + + if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) { + REG_UPDATE_2(FMT_CONTROL, + FMT_PIXEL_ENCODING, 1, + FMT_SUBSAMPLING_ORDER, 0); + } + if (params->pixel_encoding == PIXEL_ENCODING_YCBCR420) { + REG_UPDATE_3(FMT_CONTROL, + FMT_PIXEL_ENCODING, 2, + FMT_SUBSAMPLING_MODE, 2, + FMT_CBCR_BIT_REDUCTION_BYPASS, 1); + } + +} + +void dce110_opp_program_bit_depth_reduction( + struct output_pixel_processor *opp, + const struct bit_depth_reduction_params *params) +{ + struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + + set_truncation(opp110, params); + set_spatial_dither(opp110, params); + set_temporal_dither(opp110, params); +} + +void dce110_opp_program_clamping_and_pixel_encoding( + struct output_pixel_processor *opp, + const struct clamping_and_pixel_encoding_params *params) +{ + struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + + dce110_opp_set_clamping(opp110, params); + set_pixel_encoding(opp110, params); +} + +static void program_formatter_420_memory(struct output_pixel_processor *opp) +{ + struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + uint32_t fmt_mem_cntl_value; + + /* Program source select*/ + /* Use HW default source select for FMT_MEMORYx_CONTROL */ + /* Use that value for FMT_SRC_SELECT as well*/ + REG_GET(CONTROL, + FMT420_MEM0_SOURCE_SEL, &fmt_mem_cntl_value); + + REG_UPDATE(FMT_CONTROL, + FMT_SRC_SELECT, fmt_mem_cntl_value); + + /* Turn on the memory */ + REG_UPDATE(CONTROL, + FMT420_MEM0_PWR_FORCE, 0); +} + +void dce110_opp_set_dyn_expansion( + struct output_pixel_processor *opp, + enum dc_color_space color_sp, + enum dc_color_depth color_dpth, + enum signal_type signal) +{ + struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + bool enable_dyn_exp = false; + + REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL, + FMT_DYNAMIC_EXP_EN, 0, + FMT_DYNAMIC_EXP_MODE, 0); + /* From HW programming guide: + FMT_DYNAMIC_EXP_EN = 0 for limited RGB or YCbCr output + FMT_DYNAMIC_EXP_EN = 1 for RGB full range only*/ + if (color_sp == COLOR_SPACE_SRGB) + enable_dyn_exp = true; + + /*00 - 10-bit -> 12-bit dynamic expansion*/ + /*01 - 8-bit -> 12-bit dynamic expansion*/ + if (signal == SIGNAL_TYPE_HDMI_TYPE_A) { + switch (color_dpth) { + case COLOR_DEPTH_888: + REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL, + FMT_DYNAMIC_EXP_EN, enable_dyn_exp ? 1:0, + FMT_DYNAMIC_EXP_MODE, 1); + break; + case COLOR_DEPTH_101010: + REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL, + FMT_DYNAMIC_EXP_EN, enable_dyn_exp ? 1:0, + FMT_DYNAMIC_EXP_MODE, 0); + break; + case COLOR_DEPTH_121212: + break; + default: + break; + } + } +} + +static void program_formatter_reset_dig_resync_fifo(struct output_pixel_processor *opp) +{ + struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + uint8_t counter = 10; + + /* clear previous phase lock status*/ + REG_UPDATE(FMT_CONTROL, + FMT_420_PIXEL_PHASE_LOCKED_CLEAR, 1); + + /* poll until FMT_420_PIXEL_PHASE_LOCKED become 1*/ + REG_WAIT(FMT_CONTROL, FMT_420_PIXEL_PHASE_LOCKED, 1, 10, 10); + +} + +void dce110_opp_program_fmt( + struct output_pixel_processor *opp, + struct bit_depth_reduction_params *fmt_bit_depth, + struct clamping_and_pixel_encoding_params *clamping) +{ + /* dithering is affected by , hence should be + * programmed afterwards */ + + if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420) + program_formatter_420_memory(opp); + + dce110_opp_program_bit_depth_reduction( + opp, + fmt_bit_depth); + + dce110_opp_program_clamping_and_pixel_encoding( + opp, + clamping); + + if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420) + program_formatter_reset_dig_resync_fifo(opp); + + return; +} + +static void program_color_matrix( + struct dce110_opp *opp110, + const struct out_csc_color_matrix *tbl_entry, + enum grph_color_adjust_option options) +{ + { + REG_SET_2(OUTPUT_CSC_C11_C12, 0, + OUTPUT_CSC_C11, tbl_entry->regval[0], + OUTPUT_CSC_C12, tbl_entry->regval[1]); + } + { + REG_SET_2(OUTPUT_CSC_C13_C14, 0, + OUTPUT_CSC_C11, tbl_entry->regval[2], + OUTPUT_CSC_C12, tbl_entry->regval[3]); + } + { + REG_SET_2(OUTPUT_CSC_C21_C22, 0, + OUTPUT_CSC_C11, tbl_entry->regval[4], + OUTPUT_CSC_C12, tbl_entry->regval[5]); + } + { + REG_SET_2(OUTPUT_CSC_C23_C24, 0, + OUTPUT_CSC_C11, tbl_entry->regval[6], + OUTPUT_CSC_C12, tbl_entry->regval[7]); + } + { + REG_SET_2(OUTPUT_CSC_C31_C32, 0, + OUTPUT_CSC_C11, tbl_entry->regval[8], + OUTPUT_CSC_C12, tbl_entry->regval[9]); + } + { + REG_SET_2(OUTPUT_CSC_C33_C34, 0, + OUTPUT_CSC_C11, tbl_entry->regval[10], + OUTPUT_CSC_C12, tbl_entry->regval[11]); + } +} + +static bool configure_graphics_mode( + struct dce110_opp *opp110, + enum csc_color_mode config, + enum graphics_csc_adjust_type csc_adjust_type, + enum dc_color_space color_space) +{ + struct dc_context *ctx = opp110->base.ctx; + + REG_SET(OUTPUT_CSC_CONTROL, 0, + OUTPUT_CSC_GRPH_MODE, 0); + + if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_SW) { + if (config == CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC) { + REG_SET(OUTPUT_CSC_CONTROL, 0, + OUTPUT_CSC_GRPH_MODE, 4); + } else { + + switch (color_space) { + case COLOR_SPACE_SRGB: + /* by pass */ + REG_SET(OUTPUT_CSC_CONTROL, 0, + OUTPUT_CSC_GRPH_MODE, 0); + break; + case COLOR_SPACE_SRGB_LIMITED: + /* TV RGB */ + REG_SET(OUTPUT_CSC_CONTROL, 0, + OUTPUT_CSC_GRPH_MODE, 1); + break; + case COLOR_SPACE_YCBCR601: + case COLOR_SPACE_YPBPR601: + case COLOR_SPACE_YCBCR601_LIMITED: + /* YCbCr601 */ + REG_SET(OUTPUT_CSC_CONTROL, 0, + OUTPUT_CSC_GRPH_MODE, 2); + break; + case COLOR_SPACE_YCBCR709: + case COLOR_SPACE_YPBPR709: + case COLOR_SPACE_YCBCR709_LIMITED: + /* YCbCr709 */ + REG_SET(OUTPUT_CSC_CONTROL, 0, + OUTPUT_CSC_GRPH_MODE, 3); + break; + default: + return false; + } + } + } else if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_HW) { + switch (color_space) { + case COLOR_SPACE_SRGB: + /* by pass */ + REG_SET(OUTPUT_CSC_CONTROL, 0, + OUTPUT_CSC_GRPH_MODE, 0); + break; + break; + case COLOR_SPACE_SRGB_LIMITED: + /* TV RGB */ + REG_SET(OUTPUT_CSC_CONTROL, 0, + OUTPUT_CSC_GRPH_MODE, 1); + break; + case COLOR_SPACE_YCBCR601: + case COLOR_SPACE_YPBPR601: + case COLOR_SPACE_YCBCR601_LIMITED: + /* YCbCr601 */ + REG_SET(OUTPUT_CSC_CONTROL, 0, + OUTPUT_CSC_GRPH_MODE, 2); + break; + case COLOR_SPACE_YCBCR709: + case COLOR_SPACE_YPBPR709: + case COLOR_SPACE_YCBCR709_LIMITED: + /* YCbCr709 */ + REG_SET(OUTPUT_CSC_CONTROL, 0, + OUTPUT_CSC_GRPH_MODE, 3); + break; + default: + return false; + } + + } else + /* by pass */ + REG_SET(OUTPUT_CSC_CONTROL, 0, + OUTPUT_CSC_GRPH_MODE, 0); + + return true; +} + +void dce110_opp_set_csc_adjustment( + struct output_pixel_processor *opp, + const struct out_csc_color_matrix *tbl_entry) +{ + struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + enum csc_color_mode config = + CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; + + program_color_matrix( + opp110, tbl_entry, GRAPHICS_CSC_ADJUST_TYPE_SW); + + /* We did everything ,now program DxOUTPUT_CSC_CONTROL */ + configure_graphics_mode(opp110, config, GRAPHICS_CSC_ADJUST_TYPE_SW, + tbl_entry->color_space); +} + +void dce110_opp_set_csc_default( + struct output_pixel_processor *opp, + const struct default_adjustment *default_adjust) +{ + struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + enum csc_color_mode config = + CSC_COLOR_MODE_GRAPHICS_PREDEFINED; + + if (default_adjust->force_hw_default == false) { + const struct out_csc_color_matrix *elm; + /* currently parameter not in use */ + enum grph_color_adjust_option option = + GRPH_COLOR_MATRIX_HW_DEFAULT; + uint32_t i; + /* + * HW default false we program locally defined matrix + * HW default true we use predefined hw matrix and we + * do not need to program matrix + * OEM wants the HW default via runtime parameter. + */ + option = GRPH_COLOR_MATRIX_SW; + + for (i = 0; i < ARRAY_SIZE(global_color_matrix); ++i) { + elm = &global_color_matrix[i]; + if (elm->color_space != default_adjust->out_color_space) + continue; + /* program the matrix with default values from this + * file */ + program_color_matrix(opp110, elm, option); + config = CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; + break; + } + } + + /* configure the what we programmed : + * 1. Default values from this file + * 2. Use hardware default from ROM_A and we do not need to program + * matrix */ + + configure_graphics_mode(opp110, config, + default_adjust->csc_adjust_type, + default_adjust->out_color_space); +} + + +/*****************************************/ +/* Constructor, Destructor */ +/*****************************************/ + +static const struct opp_funcs funcs = { + .opp_power_on_regamma_lut = dce110_opp_power_on_regamma_lut, + .opp_set_csc_adjustment = dce110_opp_set_csc_adjustment, + .opp_set_csc_default = dce110_opp_set_csc_default, + .opp_set_dyn_expansion = dce110_opp_set_dyn_expansion, + .opp_program_regamma_pwl = dce110_opp_program_regamma_pwl, + .opp_set_regamma_mode = dce110_opp_set_regamma_mode, + .opp_destroy = dce110_opp_destroy, + .opp_program_fmt = dce110_opp_program_fmt, + .opp_program_bit_depth_reduction = dce110_opp_program_bit_depth_reduction +}; + +bool dce110_opp_construct(struct dce110_opp *opp110, + struct dc_context *ctx, + uint32_t inst, + const struct dce_opp_registers *regs, + const struct dce_opp_shift *opp_shift, + const struct dce_opp_mask *opp_mask) +{ + opp110->base.funcs = &funcs; + + opp110->base.ctx = ctx; + + opp110->base.inst = inst; + + opp110->regs = regs; + opp110->opp_shift = opp_shift; + opp110->opp_mask = opp_mask; + + return true; +} + +void dce110_opp_destroy(struct output_pixel_processor **opp) +{ + dm_free(FROM_DCE11_OPP(*opp)); + *opp = NULL; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h new file mode 100644 index 000000000000..1c01a83ecc50 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h @@ -0,0 +1,418 @@ +/* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_OPP_DCE_H__ +#define __DC_OPP_DCE_H__ + +#include "dc_types.h" +#include "opp.h" +#include "core_types.h" + +#include "gamma_types.h" /* decprecated */ + +struct gamma_parameters; + +#define FROM_DCE11_OPP(opp)\ + container_of(opp, struct dce110_opp, base) + +enum dce110_opp_reg_type { + DCE110_OPP_REG_DCP = 0, + DCE110_OPP_REG_DCFE, + DCE110_OPP_REG_FMT, + + DCE110_OPP_REG_MAX +}; + +#define OPP_COMMON_REG_LIST_BASE(id) \ + SRI(REGAMMA_CNTLA_START_CNTL, DCP, id), \ + SRI(REGAMMA_CNTLA_SLOPE_CNTL, DCP, id), \ + SRI(REGAMMA_CNTLA_END_CNTL1, DCP, id), \ + SRI(REGAMMA_CNTLA_END_CNTL2, DCP, id), \ + SRI(REGAMMA_CNTLA_REGION_0_1, DCP, id), \ + SRI(REGAMMA_CNTLA_REGION_2_3, DCP, id), \ + SRI(REGAMMA_CNTLA_REGION_4_5, DCP, id), \ + SRI(REGAMMA_CNTLA_REGION_6_7, DCP, id), \ + SRI(REGAMMA_CNTLA_REGION_8_9, DCP, id), \ + SRI(REGAMMA_CNTLA_REGION_10_11, DCP, id), \ + SRI(REGAMMA_CNTLA_REGION_12_13, DCP, id), \ + SRI(REGAMMA_CNTLA_REGION_14_15, DCP, id), \ + SRI(REGAMMA_LUT_WRITE_EN_MASK, DCP, id), \ + SRI(REGAMMA_LUT_INDEX, DCP, id), \ + SRI(REGAMMA_LUT_DATA, DCP, id), \ + SRI(REGAMMA_CONTROL, DCP, id), \ + SRI(OUTPUT_CSC_C11_C12, DCP, id), \ + SRI(OUTPUT_CSC_C13_C14, DCP, id), \ + SRI(OUTPUT_CSC_C21_C22, DCP, id), \ + SRI(OUTPUT_CSC_C23_C24, DCP, id), \ + SRI(OUTPUT_CSC_C31_C32, DCP, id), \ + SRI(OUTPUT_CSC_C33_C34, DCP, id), \ + SRI(OUTPUT_CSC_CONTROL, DCP, id), \ + SRI(FMT_DYNAMIC_EXP_CNTL, FMT, id), \ + SRI(FMT_BIT_DEPTH_CONTROL, FMT, id), \ + SRI(FMT_CONTROL, FMT, id), \ + SRI(FMT_DITHER_RAND_R_SEED, FMT, id), \ + SRI(FMT_DITHER_RAND_G_SEED, FMT, id), \ + SRI(FMT_DITHER_RAND_B_SEED, FMT, id), \ + SRI(FMT_CLAMP_CNTL, FMT, id), \ + SRI(FMT_CLAMP_COMPONENT_R, FMT, id), \ + SRI(FMT_CLAMP_COMPONENT_G, FMT, id), \ + SRI(FMT_CLAMP_COMPONENT_B, FMT, id) + +#define OPP_DCE_80_REG_LIST(id) \ + OPP_COMMON_REG_LIST_BASE(id), \ + SRI(DCFE_MEM_LIGHT_SLEEP_CNTL, CRTC, id), \ + SRI(FMT_TEMPORAL_DITHER_PATTERN_CONTROL, FMT, id), \ + SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX, FMT, id), \ + SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX, FMT, id) + +#define OPP_DCE_100_REG_LIST(id) \ + OPP_COMMON_REG_LIST_BASE(id), \ + SRI(DCFE_MEM_PWR_CTRL, CRTC, id), \ + SRI(DCFE_MEM_PWR_STATUS, CRTC, id), \ + SRI(FMT_TEMPORAL_DITHER_PATTERN_CONTROL, FMT, id), \ + SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX, FMT, id), \ + SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX, FMT, id) + +#define OPP_DCE_110_REG_LIST(id) \ + OPP_COMMON_REG_LIST_BASE(id), \ + SRI(DCFE_MEM_PWR_CTRL, DCFE, id), \ + SRI(DCFE_MEM_PWR_STATUS, DCFE, id), \ + SRI(FMT_TEMPORAL_DITHER_PATTERN_CONTROL, FMT, id), \ + SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX, FMT, id), \ + SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX, FMT, id) + +#define OPP_DCE_112_REG_LIST(id) \ + OPP_COMMON_REG_LIST_BASE(id), \ + SRI(DCFE_MEM_PWR_CTRL, DCFE, id), \ + SRI(DCFE_MEM_PWR_STATUS, DCFE, id), \ + SRI(FMT_TEMPORAL_DITHER_PATTERN_CONTROL, FMT, id), \ + SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX, FMT, id), \ + SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX, FMT, id), \ + SRI(CONTROL, FMT_MEMORY, id) + +#define OPP_SF(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define OPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh)\ + OPP_SF(REGAMMA_CNTLA_START_CNTL, REGAMMA_CNTLA_EXP_REGION_START, mask_sh),\ + OPP_SF(REGAMMA_CNTLA_START_CNTL, REGAMMA_CNTLA_EXP_REGION_START_SEGMENT, mask_sh),\ + OPP_SF(REGAMMA_CNTLA_SLOPE_CNTL, REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE, mask_sh),\ + OPP_SF(REGAMMA_CNTLA_END_CNTL1, REGAMMA_CNTLA_EXP_REGION_END, mask_sh),\ + OPP_SF(REGAMMA_CNTLA_END_CNTL2, REGAMMA_CNTLA_EXP_REGION_END_BASE, mask_sh),\ + OPP_SF(REGAMMA_CNTLA_END_CNTL2, REGAMMA_CNTLA_EXP_REGION_END_SLOPE, mask_sh),\ + OPP_SF(REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, mask_sh),\ + OPP_SF(REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, mask_sh),\ + OPP_SF(REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, mask_sh),\ + OPP_SF(REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, mask_sh),\ + OPP_SF(REGAMMA_LUT_WRITE_EN_MASK, REGAMMA_LUT_WRITE_EN_MASK, mask_sh),\ + OPP_SF(REGAMMA_CONTROL, GRPH_REGAMMA_MODE, mask_sh),\ + OPP_SF(OUTPUT_CSC_C11_C12, OUTPUT_CSC_C11, mask_sh),\ + OPP_SF(OUTPUT_CSC_C11_C12, OUTPUT_CSC_C12, mask_sh),\ + OPP_SF(OUTPUT_CSC_CONTROL, OUTPUT_CSC_GRPH_MODE, mask_sh),\ + OPP_SF(FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN, mask_sh),\ + OPP_SF(FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_DEPTH, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_MODE, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_EN, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_DEPTH, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_MODE, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_HIGHPASS_RANDOM_ENABLE, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_FRAME_RANDOM_ENABLE, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_RGB_RANDOM_ENABLE, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_EN, mask_sh),\ + OPP_SF(FMT_DITHER_RAND_R_SEED, FMT_RAND_R_SEED, mask_sh),\ + OPP_SF(FMT_DITHER_RAND_G_SEED, FMT_RAND_G_SEED, mask_sh),\ + OPP_SF(FMT_DITHER_RAND_B_SEED, FMT_RAND_B_SEED, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_EN, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_RESET, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_OFFSET, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_DEPTH, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_LEVEL, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_25FRC_SEL, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_50FRC_SEL, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_75FRC_SEL, mask_sh),\ + OPP_SF(FMT_CONTROL, FMT_SRC_SELECT, mask_sh),\ + OPP_SF(FMT_CLAMP_CNTL, FMT_CLAMP_DATA_EN, mask_sh),\ + OPP_SF(FMT_CLAMP_CNTL, FMT_CLAMP_COLOR_FORMAT, mask_sh),\ + OPP_SF(FMT_CLAMP_COMPONENT_R, FMT_CLAMP_LOWER_R, mask_sh),\ + OPP_SF(FMT_CLAMP_COMPONENT_R, FMT_CLAMP_UPPER_R, mask_sh),\ + OPP_SF(FMT_CLAMP_COMPONENT_G, FMT_CLAMP_LOWER_G, mask_sh),\ + OPP_SF(FMT_CLAMP_COMPONENT_G, FMT_CLAMP_UPPER_G, mask_sh),\ + OPP_SF(FMT_CLAMP_COMPONENT_B, FMT_CLAMP_LOWER_B, mask_sh),\ + OPP_SF(FMT_CLAMP_COMPONENT_B, FMT_CLAMP_UPPER_B, mask_sh),\ + OPP_SF(FMT_CONTROL, FMT_PIXEL_ENCODING, mask_sh),\ + OPP_SF(FMT_CONTROL, FMT_SUBSAMPLING_MODE, mask_sh),\ + OPP_SF(FMT_CONTROL, FMT_SUBSAMPLING_ORDER, mask_sh) + +#define OPP_COMMON_MASK_SH_LIST_DCE_110(mask_sh)\ + OPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh),\ + OPP_SF(DCFE_MEM_PWR_CTRL, DCP_REGAMMA_MEM_PWR_DIS, mask_sh),\ + OPP_SF(DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, mask_sh),\ + OPP_SF(DCFE_MEM_PWR_STATUS, DCP_REGAMMA_MEM_PWR_STATE, mask_sh),\ + OPP_SF(FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, mask_sh),\ + OPP_SF(FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, mask_sh) + +#define OPP_COMMON_MASK_SH_LIST_DCE_100(mask_sh)\ + OPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh),\ + OPP_SF(DCFE_MEM_PWR_CTRL, DCP_REGAMMA_MEM_PWR_DIS, mask_sh),\ + OPP_SF(DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, mask_sh),\ + OPP_SF(DCFE_MEM_PWR_STATUS, DCP_REGAMMA_MEM_PWR_STATE, mask_sh),\ + OPP_SF(FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, mask_sh),\ + OPP_SF(FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, mask_sh) + +#define OPP_COMMON_MASK_SH_LIST_DCE_112(mask_sh)\ + OPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh),\ + OPP_SF(DCFE_MEM_PWR_CTRL, DCP_REGAMMA_MEM_PWR_DIS, mask_sh),\ + OPP_SF(DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, mask_sh),\ + OPP_SF(DCFE_MEM_PWR_STATUS, DCP_REGAMMA_MEM_PWR_STATE, mask_sh),\ + OPP_SF(FMT_MEMORY0_CONTROL, FMT420_MEM0_SOURCE_SEL, mask_sh),\ + OPP_SF(FMT_MEMORY0_CONTROL, FMT420_MEM0_PWR_FORCE, mask_sh),\ + OPP_SF(FMT_CONTROL, FMT_420_PIXEL_PHASE_LOCKED_CLEAR, mask_sh),\ + OPP_SF(FMT_CONTROL, FMT_420_PIXEL_PHASE_LOCKED, mask_sh),\ + OPP_SF(FMT_CONTROL, FMT_CBCR_BIT_REDUCTION_BYPASS, mask_sh),\ + OPP_SF(FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, mask_sh),\ + OPP_SF(FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, mask_sh) + +#define OPP_COMMON_MASK_SH_LIST_DCE_80(mask_sh)\ + OPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh),\ + OPP_SF(DCFE_MEM_LIGHT_SLEEP_CNTL, REGAMMA_LUT_LIGHT_SLEEP_DIS, mask_sh),\ + OPP_SF(DCFE_MEM_LIGHT_SLEEP_CNTL, DCP_LUT_LIGHT_SLEEP_DIS, mask_sh),\ + OPP_SF(DCFE_MEM_LIGHT_SLEEP_CNTL, REGAMMA_LUT_MEM_PWR_STATE, mask_sh) + +#define OPP_REG_FIELD_LIST(type) \ + type DCP_REGAMMA_MEM_PWR_DIS; \ + type DCP_LUT_MEM_PWR_DIS; \ + type REGAMMA_LUT_LIGHT_SLEEP_DIS; \ + type DCP_LUT_LIGHT_SLEEP_DIS; \ + type REGAMMA_CNTLA_EXP_REGION_START; \ + type REGAMMA_CNTLA_EXP_REGION_START_SEGMENT; \ + type REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE; \ + type REGAMMA_CNTLA_EXP_REGION_END; \ + type REGAMMA_CNTLA_EXP_REGION_END_BASE; \ + type REGAMMA_CNTLA_EXP_REGION_END_SLOPE; \ + type REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET; \ + type REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS; \ + type REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET; \ + type REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS; \ + type DCP_REGAMMA_MEM_PWR_STATE; \ + type REGAMMA_LUT_MEM_PWR_STATE; \ + type REGAMMA_LUT_WRITE_EN_MASK; \ + type GRPH_REGAMMA_MODE; \ + type OUTPUT_CSC_C11; \ + type OUTPUT_CSC_C12; \ + type OUTPUT_CSC_GRPH_MODE; \ + type FMT_DYNAMIC_EXP_EN; \ + type FMT_DYNAMIC_EXP_MODE; \ + type FMT_TRUNCATE_EN; \ + type FMT_TRUNCATE_DEPTH; \ + type FMT_TRUNCATE_MODE; \ + type FMT_SPATIAL_DITHER_EN; \ + type FMT_SPATIAL_DITHER_DEPTH; \ + type FMT_SPATIAL_DITHER_MODE; \ + type FMT_TEMPORAL_DITHER_EN; \ + type FMT_TEMPORAL_DITHER_RESET; \ + type FMT_TEMPORAL_DITHER_OFFSET; \ + type FMT_TEMPORAL_DITHER_DEPTH; \ + type FMT_TEMPORAL_LEVEL; \ + type FMT_25FRC_SEL; \ + type FMT_50FRC_SEL; \ + type FMT_75FRC_SEL; \ + type FMT_HIGHPASS_RANDOM_ENABLE; \ + type FMT_FRAME_RANDOM_ENABLE; \ + type FMT_RGB_RANDOM_ENABLE; \ + type FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX; \ + type FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP; \ + type FMT_RAND_R_SEED; \ + type FMT_RAND_G_SEED; \ + type FMT_RAND_B_SEED; \ + type FMT420_MEM0_SOURCE_SEL; \ + type FMT420_MEM0_PWR_FORCE; \ + type FMT_SRC_SELECT; \ + type FMT_420_PIXEL_PHASE_LOCKED_CLEAR; \ + type FMT_420_PIXEL_PHASE_LOCKED; \ + type FMT_CLAMP_DATA_EN; \ + type FMT_CLAMP_COLOR_FORMAT; \ + type FMT_CLAMP_LOWER_R; \ + type FMT_CLAMP_UPPER_R; \ + type FMT_CLAMP_LOWER_G; \ + type FMT_CLAMP_UPPER_G; \ + type FMT_CLAMP_LOWER_B; \ + type FMT_CLAMP_UPPER_B; \ + type FMT_PIXEL_ENCODING; \ + type FMT_SUBSAMPLING_ORDER; \ + type FMT_SUBSAMPLING_MODE; \ + type FMT_CBCR_BIT_REDUCTION_BYPASS;\ + +struct dce_opp_shift { + OPP_REG_FIELD_LIST(uint8_t) +}; + +struct dce_opp_mask { + OPP_REG_FIELD_LIST(uint32_t) +}; + +struct dce_opp_registers { + uint32_t DCFE_MEM_PWR_CTRL; + uint32_t DCFE_MEM_LIGHT_SLEEP_CNTL; + uint32_t REGAMMA_CNTLA_START_CNTL; + uint32_t REGAMMA_CNTLA_SLOPE_CNTL; + uint32_t REGAMMA_CNTLA_END_CNTL1; + uint32_t REGAMMA_CNTLA_END_CNTL2; + uint32_t REGAMMA_CNTLA_REGION_0_1; + uint32_t REGAMMA_CNTLA_REGION_2_3; + uint32_t REGAMMA_CNTLA_REGION_4_5; + uint32_t REGAMMA_CNTLA_REGION_6_7; + uint32_t REGAMMA_CNTLA_REGION_8_9; + uint32_t REGAMMA_CNTLA_REGION_10_11; + uint32_t REGAMMA_CNTLA_REGION_12_13; + uint32_t REGAMMA_CNTLA_REGION_14_15; + uint32_t REGAMMA_LUT_WRITE_EN_MASK; + uint32_t REGAMMA_LUT_INDEX; + uint32_t DCFE_MEM_PWR_STATUS; + uint32_t REGAMMA_LUT_DATA; + uint32_t REGAMMA_CONTROL; + uint32_t OUTPUT_CSC_C11_C12; + uint32_t OUTPUT_CSC_C13_C14; + uint32_t OUTPUT_CSC_C21_C22; + uint32_t OUTPUT_CSC_C23_C24; + uint32_t OUTPUT_CSC_C31_C32; + uint32_t OUTPUT_CSC_C33_C34; + uint32_t OUTPUT_CSC_CONTROL; + uint32_t FMT_DYNAMIC_EXP_CNTL; + uint32_t FMT_BIT_DEPTH_CONTROL; + uint32_t FMT_CONTROL; + uint32_t FMT_DITHER_RAND_R_SEED; + uint32_t FMT_DITHER_RAND_G_SEED; + uint32_t FMT_DITHER_RAND_B_SEED; + uint32_t FMT_TEMPORAL_DITHER_PATTERN_CONTROL; + uint32_t FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX; + uint32_t FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX; + uint32_t CONTROL; + uint32_t FMT_CLAMP_CNTL; + uint32_t FMT_CLAMP_COMPONENT_R; + uint32_t FMT_CLAMP_COMPONENT_G; + uint32_t FMT_CLAMP_COMPONENT_B; +}; + +struct dce110_regamma { + struct gamma_curve arr_curve_points[16]; + struct curve_points arr_points[3]; + uint32_t hw_points_num; + struct hw_x_point *coordinates_x; + struct pwl_result_data *rgb_resulted; + + /* re-gamma curve */ + struct pwl_float_data_ex *rgb_regamma; + /* coeff used to map user evenly distributed points + * to our hardware points (predefined) for gamma 256 */ + struct pixel_gamma_point *coeff128; + struct pixel_gamma_point *coeff128_oem; + /* coeff used to map user evenly distributed points + * to our hardware points (predefined) for gamma 1025 */ + struct pixel_gamma_point *coeff128_dx; + /* evenly distributed points, gamma 256 software points 0-255 */ + struct gamma_pixel *axis_x_256; + /* evenly distributed points, gamma 1025 software points 0-1025 */ + struct gamma_pixel *axis_x_1025; + /* OEM supplied gamma for regamma LUT */ + struct pwl_float_data *rgb_oem; + /* user supplied gamma */ + struct pwl_float_data *rgb_user; + uint32_t extra_points; + bool use_half_points; + struct fixed31_32 x_max1; + struct fixed31_32 x_max2; + struct fixed31_32 x_min; + struct fixed31_32 divider1; + struct fixed31_32 divider2; + struct fixed31_32 divider3; +}; + +/* OPP RELATED */ +#define TO_DCE110_OPP(opp)\ + container_of(opp, struct dce110_opp, base) + +struct dce110_opp { + struct output_pixel_processor base; + const struct dce_opp_registers *regs; + const struct dce_opp_shift *opp_shift; + const struct dce_opp_mask *opp_mask; + struct dce110_regamma regamma; +}; + +bool dce110_opp_construct(struct dce110_opp *opp110, + struct dc_context *ctx, + uint32_t inst, + const struct dce_opp_registers *regs, + const struct dce_opp_shift *opp_shift, + const struct dce_opp_mask *opp_mask); + +void dce110_opp_destroy(struct output_pixel_processor **opp); + +/* REGAMMA RELATED */ +void dce110_opp_power_on_regamma_lut( + struct output_pixel_processor *opp, + bool power_on); + +bool dce110_opp_program_regamma_pwl( + struct output_pixel_processor *opp, + const struct pwl_params *params); + +void dce110_opp_set_regamma_mode(struct output_pixel_processor *opp, + enum opp_regamma mode); + +void dce110_opp_set_csc_adjustment( + struct output_pixel_processor *opp, + const struct out_csc_color_matrix *tbl_entry); + +void dce110_opp_set_csc_default( + struct output_pixel_processor *opp, + const struct default_adjustment *default_adjust); + +/* FORMATTER RELATED */ +void dce110_opp_program_bit_depth_reduction( + struct output_pixel_processor *opp, + const struct bit_depth_reduction_params *params); + +void dce110_opp_program_clamping_and_pixel_encoding( + struct output_pixel_processor *opp, + const struct clamping_and_pixel_encoding_params *params); + +void dce110_opp_set_dyn_expansion( + struct output_pixel_processor *opp, + enum dc_color_space color_sp, + enum dc_color_depth color_dpth, + enum signal_type signal); + +void dce110_opp_program_fmt( + struct output_pixel_processor *opp, + struct bit_depth_reduction_params *fmt_bit_depth, + struct clamping_and_pixel_encoding_params *clamping); + +void dce110_opp_set_clamping( + struct dce110_opp *opp110, + const struct clamping_and_pixel_encoding_params *params); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index c97416f7bc93..161d4eee4423 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -39,7 +39,7 @@ #include "dce110/dce110_mem_input_v.h" #include "dce110/dce110_ipp.h" #include "dce/dce_transform.h" -#include "dce110/dce110_opp.h" +#include "dce/dce_opp.h" #include "dce/dce_clocks.h" #include "dce/dce_clock_source.h" #include "dce/dce_audio.h" @@ -302,6 +302,29 @@ static const struct dce_stream_encoder_mask se_mask = { SE_COMMON_MASK_SH_LIST_DCE80_100(_MASK) }; +#define opp_regs(id)\ +[id] = {\ + OPP_DCE_100_REG_LIST(id),\ +} + +static const struct dce_opp_registers opp_regs[] = { + opp_regs(0), + opp_regs(1), + opp_regs(2), + opp_regs(3), + opp_regs(4), + opp_regs(5) +}; + +static const struct dce_opp_shift opp_shift = { + OPP_COMMON_MASK_SH_LIST_DCE_100(__SHIFT) +}; + +static const struct dce_opp_mask opp_mask = { + OPP_COMMON_MASK_SH_LIST_DCE_100(_MASK) +}; + + #define audio_regs(id)\ [id] = {\ AUD_COMMON_REG_LIST(id)\ @@ -348,35 +371,6 @@ static const struct dce110_clk_src_mask cs_mask = { #define DCFE_MEM_PWR_CTRL_REG_BASE 0x1b03 -static const struct dce110_opp_reg_offsets dce100_opp_reg_offsets[] = { -{ - .fmt_offset = (mmFMT0_FMT_CONTROL - mmFMT_CONTROL), - .dcfe_offset = (mmCRTC0_DCFE_MEM_PWR_CTRL - DCFE_MEM_PWR_CTRL_REG_BASE), - .dcp_offset = (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL), -}, -{ .fmt_offset = (mmFMT1_FMT_CONTROL - mmFMT0_FMT_CONTROL), - .dcfe_offset = (mmCRTC1_DCFE_MEM_PWR_CTRL - DCFE_MEM_PWR_CTRL_REG_BASE), - .dcp_offset = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -}, -{ .fmt_offset = (mmFMT2_FMT_CONTROL - mmFMT0_FMT_CONTROL), - .dcfe_offset = (mmCRTC2_DCFE_MEM_PWR_CTRL - DCFE_MEM_PWR_CTRL_REG_BASE), - .dcp_offset = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -}, -{ - .fmt_offset = (mmFMT3_FMT_CONTROL - mmFMT0_FMT_CONTROL), - .dcfe_offset = (mmCRTC3_DCFE_MEM_PWR_CTRL - DCFE_MEM_PWR_CTRL_REG_BASE), - .dcp_offset = (mmDCP3_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -}, -{ .fmt_offset = (mmFMT4_FMT_CONTROL - mmFMT0_FMT_CONTROL), - .dcfe_offset = (mmCRTC4_DCFE_MEM_PWR_CTRL - DCFE_MEM_PWR_CTRL_REG_BASE), - .dcp_offset = (mmDCP4_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -}, -{ .fmt_offset = (mmFMT5_FMT_CONTROL - mmFMT0_FMT_CONTROL), - .dcfe_offset = (mmCRTC5_DCFE_MEM_PWR_CTRL - DCFE_MEM_PWR_CTRL_REG_BASE), - .dcp_offset = (mmDCP5_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -} -}; - static const struct bios_registers bios_regs = { .BIOS_SCRATCH_6 = mmBIOS_SCRATCH_6 }; @@ -615,8 +609,7 @@ struct link_encoder *dce100_link_encoder_create( struct output_pixel_processor *dce100_opp_create( struct dc_context *ctx, - uint32_t inst, - const struct dce110_opp_reg_offsets *offset) + uint32_t inst) { struct dce110_opp *opp = dm_alloc(sizeof(struct dce110_opp)); @@ -625,7 +618,7 @@ struct output_pixel_processor *dce100_opp_create( return NULL; if (dce110_opp_construct(opp, - ctx, inst, offset)) + ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask)) return &opp->base; BREAK_TO_DEBUGGER(); @@ -1052,7 +1045,7 @@ static bool construct( goto res_create_fail; } - pool->base.opps[i] = dce100_opp_create(ctx, i, &dce100_opp_reg_offsets[i]); + pool->base.opps[i] = dce100_opp_create(ctx, i); if (pool->base.opps[i] == NULL) { BREAK_TO_DEBUGGER(); dm_error( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/Makefile b/drivers/gpu/drm/amd/display/dc/dce110/Makefile index cd7a9095fa06..9c42afcac325 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dce110/Makefile @@ -3,8 +3,8 @@ # It provides the control and status of HW CRTC block. DCE110 = dce110_ipp.o dce110_ipp_cursor.o \ -dce110_ipp_gamma.o dce110_opp.o dce110_opp_csc.o \ -dce110_timing_generator.o dce110_opp_formatter.o dce110_opp_regamma.o \ +dce110_ipp_gamma.o \ +dce110_timing_generator.o \ dce110_compressor.o dce110_mem_input.o dce110_hw_sequencer.o \ dce110_resource.o \ dce110_opp_regamma_v.o dce110_opp_csc_v.o dce110_timing_generator_v.o \ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp.c deleted file mode 100644 index 698ec2f55d0f..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" - -/* include DCE11 register header files */ -#include "dce/dce_11_0_d.h" -#include "dce/dce_11_0_sh_mask.h" - -#include "dce110_opp.h" - -#include "gamma_types.h" - -enum { - MAX_LUT_ENTRY = 256, - MAX_NUMBER_OF_ENTRIES = 256 -}; - -/*****************************************/ -/* Constructor, Destructor */ -/*****************************************/ - -static const struct opp_funcs funcs = { - .opp_power_on_regamma_lut = dce110_opp_power_on_regamma_lut, - .opp_set_csc_adjustment = dce110_opp_set_csc_adjustment, - .opp_set_csc_default = dce110_opp_set_csc_default, - .opp_set_dyn_expansion = dce110_opp_set_dyn_expansion, - .opp_program_regamma_pwl = dce110_opp_program_regamma_pwl, - .opp_set_regamma_mode = dce110_opp_set_regamma_mode, - .opp_destroy = dce110_opp_destroy, - .opp_program_fmt = dce110_opp_program_fmt, -}; - -bool dce110_opp_construct(struct dce110_opp *opp110, - struct dc_context *ctx, - uint32_t inst, - const struct dce110_opp_reg_offsets *offsets) -{ - opp110->base.funcs = &funcs; - - opp110->base.ctx = ctx; - - opp110->base.inst = inst; - - opp110->offsets = *offsets; - - return true; -} - -void dce110_opp_destroy(struct output_pixel_processor **opp) -{ - dm_free(FROM_DCE11_OPP(*opp)); - *opp = NULL; -} - diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp.h deleted file mode 100644 index 2fbb2415cc97..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp.h +++ /dev/null @@ -1,149 +0,0 @@ -/* Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DC_OPP_DCE110_H__ -#define __DC_OPP_DCE110_H__ - -#include "dc_types.h" -#include "opp.h" -#include "core_types.h" - -#include "gamma_types.h" /* decprecated */ - -struct gamma_parameters; - -#define FROM_DCE11_OPP(opp)\ - container_of(opp, struct dce110_opp, base) - -enum dce110_opp_reg_type { - DCE110_OPP_REG_DCP = 0, - DCE110_OPP_REG_DCFE, - DCE110_OPP_REG_FMT, - - DCE110_OPP_REG_MAX -}; - -struct dce110_regamma { - struct gamma_curve arr_curve_points[16]; - struct curve_points arr_points[3]; - uint32_t hw_points_num; - struct hw_x_point *coordinates_x; - struct pwl_result_data *rgb_resulted; - - /* re-gamma curve */ - struct pwl_float_data_ex *rgb_regamma; - /* coeff used to map user evenly distributed points - * to our hardware points (predefined) for gamma 256 */ - struct pixel_gamma_point *coeff128; - struct pixel_gamma_point *coeff128_oem; - /* coeff used to map user evenly distributed points - * to our hardware points (predefined) for gamma 1025 */ - struct pixel_gamma_point *coeff128_dx; - /* evenly distributed points, gamma 256 software points 0-255 */ - struct gamma_pixel *axis_x_256; - /* evenly distributed points, gamma 1025 software points 0-1025 */ - struct gamma_pixel *axis_x_1025; - /* OEM supplied gamma for regamma LUT */ - struct pwl_float_data *rgb_oem; - /* user supplied gamma */ - struct pwl_float_data *rgb_user; - uint32_t extra_points; - bool use_half_points; - struct fixed31_32 x_max1; - struct fixed31_32 x_max2; - struct fixed31_32 x_min; - struct fixed31_32 divider1; - struct fixed31_32 divider2; - struct fixed31_32 divider3; -}; - -/* OPP RELATED */ -#define TO_DCE110_OPP(opp)\ - container_of(opp, struct dce110_opp, base) - -struct dce110_opp_reg_offsets { - uint32_t fmt_offset; - uint32_t fmt_mem_offset; - uint32_t dcp_offset; - uint32_t dcfe_offset; -}; - -struct dce110_opp { - struct output_pixel_processor base; - struct dce110_opp_reg_offsets offsets; - struct dce110_regamma regamma; -}; - -bool dce110_opp_construct(struct dce110_opp *opp110, - struct dc_context *ctx, - uint32_t inst, - const struct dce110_opp_reg_offsets *offsets); - -void dce110_opp_destroy(struct output_pixel_processor **opp); - -/* REGAMMA RELATED */ -void dce110_opp_power_on_regamma_lut( - struct output_pixel_processor *opp, - bool power_on); - -bool dce110_opp_program_regamma_pwl( - struct output_pixel_processor *opp, - const struct pwl_params *params); - -void dce110_opp_set_regamma_mode(struct output_pixel_processor *opp, - enum opp_regamma mode); - -void dce110_opp_set_csc_adjustment( - struct output_pixel_processor *opp, - const struct out_csc_color_matrix *tbl_entry); - -void dce110_opp_set_csc_default( - struct output_pixel_processor *opp, - const struct default_adjustment *default_adjust); - -/* FORMATTER RELATED */ -void dce110_opp_program_bit_depth_reduction( - struct output_pixel_processor *opp, - const struct bit_depth_reduction_params *params); - -void dce110_opp_program_clamping_and_pixel_encoding( - struct output_pixel_processor *opp, - const struct clamping_and_pixel_encoding_params *params); - -void dce110_opp_set_dyn_expansion( - struct output_pixel_processor *opp, - enum dc_color_space color_sp, - enum dc_color_depth color_dpth, - enum signal_type signal); - -void dce110_opp_program_fmt( - struct output_pixel_processor *opp, - struct bit_depth_reduction_params *fmt_bit_depth, - struct clamping_and_pixel_encoding_params *clamping); - -void dce110_opp_set_clamping( - struct dce110_opp *opp110, - const struct clamping_and_pixel_encoding_params *params); - -#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc.c deleted file mode 100644 index b46db202ddbb..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc.c +++ /dev/null @@ -1,363 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" -#include "dce110_opp.h" -#include "basics/conversion.h" - -/* include DCE11 register header files */ -#include "dce/dce_11_0_d.h" -#include "dce/dce_11_0_sh_mask.h" - -#define DCP_REG(reg)\ - (reg + opp110->offsets.dcp_offset) - -enum { - OUTPUT_CSC_MATRIX_SIZE = 12 -}; - -static const struct out_csc_color_matrix global_color_matrix[] = { -{ COLOR_SPACE_SRGB, - { 0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} }, -{ COLOR_SPACE_SRGB_LIMITED, - { 0x1B60, 0, 0, 0x200, 0, 0x1B60, 0, 0x200, 0, 0, 0x1B60, 0x200} }, -{ COLOR_SPACE_YCBCR601, - { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x82F, 0x1012, 0x31F, 0x200, 0xFB47, - 0xF6B9, 0xE00, 0x1000} }, -{ COLOR_SPACE_YCBCR709, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x5D2, 0x1394, 0x1FA, - 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} }, -/* TODO: correct values below */ -{ COLOR_SPACE_YCBCR601_LIMITED, { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x991, - 0x12C9, 0x3A6, 0x200, 0xFB47, 0xF6B9, 0xE00, 0x1000} }, -{ COLOR_SPACE_YCBCR709_LIMITED, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x6CE, 0x16E3, - 0x24F, 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} } -}; - -enum csc_color_mode { - /* 00 - BITS2:0 Bypass */ - CSC_COLOR_MODE_GRAPHICS_BYPASS, - /* 01 - hard coded coefficient TV RGB */ - CSC_COLOR_MODE_GRAPHICS_PREDEFINED, - /* 04 - programmable OUTPUT CSC coefficient */ - CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC, -}; - -static void program_color_matrix( - struct dce110_opp *opp110, - const struct out_csc_color_matrix *tbl_entry, - enum grph_color_adjust_option options) -{ - struct dc_context *ctx = opp110->base.ctx; - { - uint32_t value = 0; - uint32_t addr = DCP_REG(mmOUTPUT_CSC_C11_C12); - /* fixed S2.13 format */ - set_reg_field_value( - value, - tbl_entry->regval[0], - OUTPUT_CSC_C11_C12, - OUTPUT_CSC_C11); - - set_reg_field_value( - value, - tbl_entry->regval[1], - OUTPUT_CSC_C11_C12, - OUTPUT_CSC_C12); - - dm_write_reg(ctx, addr, value); - } - { - uint32_t value = 0; - uint32_t addr = DCP_REG(mmOUTPUT_CSC_C13_C14); - /* fixed S2.13 format */ - set_reg_field_value( - value, - tbl_entry->regval[2], - OUTPUT_CSC_C13_C14, - OUTPUT_CSC_C13); - /* fixed S0.13 format */ - set_reg_field_value( - value, - tbl_entry->regval[3], - OUTPUT_CSC_C13_C14, - OUTPUT_CSC_C14); - - dm_write_reg(ctx, addr, value); - } - { - uint32_t value = 0; - uint32_t addr = DCP_REG(mmOUTPUT_CSC_C21_C22); - /* fixed S2.13 format */ - set_reg_field_value( - value, - tbl_entry->regval[4], - OUTPUT_CSC_C21_C22, - OUTPUT_CSC_C21); - /* fixed S2.13 format */ - set_reg_field_value( - value, - tbl_entry->regval[5], - OUTPUT_CSC_C21_C22, - OUTPUT_CSC_C22); - - dm_write_reg(ctx, addr, value); - } - { - uint32_t value = 0; - uint32_t addr = DCP_REG(mmOUTPUT_CSC_C23_C24); - /* fixed S2.13 format */ - set_reg_field_value( - value, - tbl_entry->regval[6], - OUTPUT_CSC_C23_C24, - OUTPUT_CSC_C23); - /* fixed S0.13 format */ - set_reg_field_value( - value, - tbl_entry->regval[7], - OUTPUT_CSC_C23_C24, - OUTPUT_CSC_C24); - - dm_write_reg(ctx, addr, value); - } - { - uint32_t value = 0; - uint32_t addr = DCP_REG(mmOUTPUT_CSC_C31_C32); - /* fixed S2.13 format */ - set_reg_field_value( - value, - tbl_entry->regval[8], - OUTPUT_CSC_C31_C32, - OUTPUT_CSC_C31); - /* fixed S0.13 format */ - set_reg_field_value( - value, - tbl_entry->regval[9], - OUTPUT_CSC_C31_C32, - OUTPUT_CSC_C32); - - dm_write_reg(ctx, addr, value); - } - { - uint32_t value = 0; - uint32_t addr = DCP_REG(mmOUTPUT_CSC_C33_C34); - /* fixed S2.13 format */ - set_reg_field_value( - value, - tbl_entry->regval[10], - OUTPUT_CSC_C33_C34, - OUTPUT_CSC_C33); - /* fixed S0.13 format */ - set_reg_field_value( - value, - tbl_entry->regval[11], - OUTPUT_CSC_C33_C34, - OUTPUT_CSC_C34); - - dm_write_reg(ctx, addr, value); - } -} - -static bool configure_graphics_mode( - struct dce110_opp *opp110, - enum csc_color_mode config, - enum graphics_csc_adjust_type csc_adjust_type, - enum dc_color_space color_space) -{ - struct dc_context *ctx = opp110->base.ctx; - uint32_t addr = DCP_REG(mmOUTPUT_CSC_CONTROL); - uint32_t value = dm_read_reg(ctx, addr); - - set_reg_field_value( - value, - 0, - OUTPUT_CSC_CONTROL, - OUTPUT_CSC_GRPH_MODE); - - if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_SW) { - if (config == CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC) { - set_reg_field_value( - value, - 4, - OUTPUT_CSC_CONTROL, - OUTPUT_CSC_GRPH_MODE); - } else { - - switch (color_space) { - case COLOR_SPACE_SRGB: - /* by pass */ - set_reg_field_value( - value, - 0, - OUTPUT_CSC_CONTROL, - OUTPUT_CSC_GRPH_MODE); - break; - case COLOR_SPACE_SRGB_LIMITED: - /* TV RGB */ - set_reg_field_value( - value, - 1, - OUTPUT_CSC_CONTROL, - OUTPUT_CSC_GRPH_MODE); - break; - case COLOR_SPACE_YCBCR601: - case COLOR_SPACE_YPBPR601: - case COLOR_SPACE_YCBCR601_LIMITED: - /* YCbCr601 */ - set_reg_field_value( - value, - 2, - OUTPUT_CSC_CONTROL, - OUTPUT_CSC_GRPH_MODE); - break; - case COLOR_SPACE_YCBCR709: - case COLOR_SPACE_YPBPR709: - case COLOR_SPACE_YCBCR709_LIMITED: - /* YCbCr709 */ - set_reg_field_value( - value, - 3, - OUTPUT_CSC_CONTROL, - OUTPUT_CSC_GRPH_MODE); - break; - default: - return false; - } - } - } else if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_HW) { - switch (color_space) { - case COLOR_SPACE_SRGB: - /* by pass */ - set_reg_field_value( - value, - 0, - OUTPUT_CSC_CONTROL, - OUTPUT_CSC_GRPH_MODE); - break; - case COLOR_SPACE_SRGB_LIMITED: - /* TV RGB */ - set_reg_field_value( - value, - 1, - OUTPUT_CSC_CONTROL, - OUTPUT_CSC_GRPH_MODE); - break; - case COLOR_SPACE_YCBCR601: - case COLOR_SPACE_YPBPR601: - case COLOR_SPACE_YCBCR601_LIMITED: - /* YCbCr601 */ - set_reg_field_value( - value, - 2, - OUTPUT_CSC_CONTROL, - OUTPUT_CSC_GRPH_MODE); - break; - case COLOR_SPACE_YCBCR709: - case COLOR_SPACE_YPBPR709: - case COLOR_SPACE_YCBCR709_LIMITED: - /* YCbCr709 */ - set_reg_field_value( - value, - 3, - OUTPUT_CSC_CONTROL, - OUTPUT_CSC_GRPH_MODE); - break; - default: - return false; - } - - } else - /* by pass */ - set_reg_field_value( - value, - 0, - OUTPUT_CSC_CONTROL, - OUTPUT_CSC_GRPH_MODE); - - addr = DCP_REG(mmOUTPUT_CSC_CONTROL); - dm_write_reg(ctx, addr, value); - - return true; -} - -void dce110_opp_set_csc_adjustment( - struct output_pixel_processor *opp, - const struct out_csc_color_matrix *tbl_entry) -{ - struct dce110_opp *opp110 = TO_DCE110_OPP(opp); - enum csc_color_mode config = - CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; - - program_color_matrix( - opp110, tbl_entry, GRAPHICS_CSC_ADJUST_TYPE_SW); - - /* We did everything ,now program DxOUTPUT_CSC_CONTROL */ - configure_graphics_mode(opp110, config, GRAPHICS_CSC_ADJUST_TYPE_SW, - tbl_entry->color_space); -} - -void dce110_opp_set_csc_default( - struct output_pixel_processor *opp, - const struct default_adjustment *default_adjust) -{ - struct dce110_opp *opp110 = TO_DCE110_OPP(opp); - enum csc_color_mode config = - CSC_COLOR_MODE_GRAPHICS_PREDEFINED; - - if (default_adjust->force_hw_default == false) { - const struct out_csc_color_matrix *elm; - /* currently parameter not in use */ - enum grph_color_adjust_option option = - GRPH_COLOR_MATRIX_HW_DEFAULT; - uint32_t i; - /* - * HW default false we program locally defined matrix - * HW default true we use predefined hw matrix and we - * do not need to program matrix - * OEM wants the HW default via runtime parameter. - */ - option = GRPH_COLOR_MATRIX_SW; - - for (i = 0; i < ARRAY_SIZE(global_color_matrix); ++i) { - elm = &global_color_matrix[i]; - if (elm->color_space != default_adjust->out_color_space) - continue; - /* program the matrix with default values from this - * file */ - program_color_matrix(opp110, elm, option); - config = CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; - break; - } - } - - /* configure the what we programmed : - * 1. Default values from this file - * 2. Use hardware default from ROM_A and we do not need to program - * matrix */ - - configure_graphics_mode(opp110, config, - default_adjust->csc_adjust_type, - default_adjust->out_color_space); -} diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c index 975466f6e424..6995a3de7564 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c @@ -24,7 +24,7 @@ */ #include "dm_services.h" -#include "dce110_opp.h" +#include "dce/dce_opp.h" #include "basics/conversion.h" /* include DCE11 register header files */ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_formatter.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_formatter.c deleted file mode 100644 index eac20775c23f..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_formatter.c +++ /dev/null @@ -1,627 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" - -#include "dce/dce_11_0_d.h" -#include "dce/dce_11_0_sh_mask.h" - -#include "dce110_opp.h" - -#define FMT_REG(reg)\ - (reg + opp110->offsets.fmt_offset) -/** - * set_truncation - * 1) set truncation depth: 0 for 18 bpp or 1 for 24 bpp - * 2) enable truncation - * 3) HW remove 12bit FMT support for DCE11 power saving reason. - */ -static void set_truncation( - struct dce110_opp *opp110, - const struct bit_depth_reduction_params *params) -{ - uint32_t value = 0; - uint32_t addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL); - - /*Disable truncation*/ - value = dm_read_reg(opp110->base.ctx, addr); - set_reg_field_value(value, 0, - FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN); - set_reg_field_value(value, 0, - FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_DEPTH); - set_reg_field_value(value, 0, - FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_MODE); - - dm_write_reg(opp110->base.ctx, addr, value); - - /* no 10bpc trunc on DCE11*/ - if (params->flags.TRUNCATE_ENABLED == 0 || - params->flags.TRUNCATE_DEPTH == 2) - return; - - /*Set truncation depth and Enable truncation*/ - set_reg_field_value(value, 1, - FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN); - set_reg_field_value(value, params->flags.TRUNCATE_MODE, - FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_MODE); - set_reg_field_value(value, params->flags.TRUNCATE_DEPTH, - FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_DEPTH); - - dm_write_reg(opp110->base.ctx, addr, value); - -} - -/** - * set_spatial_dither - * 1) set spatial dithering mode: pattern of seed - * 2) set spatical dithering depth: 0 for 18bpp or 1 for 24bpp - * 3) set random seed - * 4) set random mode - * lfsr is reset every frame or not reset - * RGB dithering method - * 0: RGB data are all dithered with x^28+x^3+1 - * 1: R data is dithered with x^28+x^3+1 - * G data is dithered with x^28+X^9+1 - * B data is dithered with x^28+x^13+1 - * enable high pass filter or not - * 5) enable spatical dithering - */ -static void set_spatial_dither( - struct dce110_opp *opp110, - const struct bit_depth_reduction_params *params) -{ - uint32_t addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL); - uint32_t depth_cntl_value = 0; - uint32_t fmt_cntl_value = 0; - uint32_t dither_r_value = 0; - uint32_t dither_g_value = 0; - uint32_t dither_b_value = 0; - - /*Disable spatial (random) dithering*/ - depth_cntl_value = dm_read_reg(opp110->base.ctx, addr); - set_reg_field_value(depth_cntl_value, 0, - FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_EN); - set_reg_field_value(depth_cntl_value, 0, - FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_MODE); - set_reg_field_value(depth_cntl_value, 0, - FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_DEPTH); - set_reg_field_value(depth_cntl_value, 0, - FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_EN); - set_reg_field_value(depth_cntl_value, 0, - FMT_BIT_DEPTH_CONTROL, FMT_HIGHPASS_RANDOM_ENABLE); - set_reg_field_value(depth_cntl_value, 0, - FMT_BIT_DEPTH_CONTROL, FMT_FRAME_RANDOM_ENABLE); - set_reg_field_value(depth_cntl_value, 0, - FMT_BIT_DEPTH_CONTROL, FMT_RGB_RANDOM_ENABLE); - - dm_write_reg(opp110->base.ctx, addr, depth_cntl_value); - - /* no 10bpc on DCE11*/ - if (params->flags.SPATIAL_DITHER_ENABLED == 0 || - params->flags.SPATIAL_DITHER_DEPTH == 2) - return; - - addr = FMT_REG(mmFMT_CONTROL); - fmt_cntl_value = dm_read_reg(opp110->base.ctx, addr); - /* only use FRAME_COUNTER_MAX if frameRandom == 1*/ - if (params->flags.FRAME_RANDOM == 1) { - if (params->flags.SPATIAL_DITHER_DEPTH == 0 || - params->flags.SPATIAL_DITHER_DEPTH == 1) { - set_reg_field_value(fmt_cntl_value, 15, - FMT_CONTROL, - FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX); - set_reg_field_value(fmt_cntl_value, 2, - FMT_CONTROL, - FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP); - } else if (params->flags.SPATIAL_DITHER_DEPTH == 2) { - set_reg_field_value(fmt_cntl_value, 3, - FMT_CONTROL, - FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX); - set_reg_field_value(fmt_cntl_value, 1, - FMT_CONTROL, - FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP); - } else - return; - } else { - set_reg_field_value(fmt_cntl_value, 0, - FMT_CONTROL, - FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX); - set_reg_field_value(fmt_cntl_value, 0, - FMT_CONTROL, - FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP); - } - - dm_write_reg(opp110->base.ctx, addr, fmt_cntl_value); - - /*Set seed for random values for - * spatial dithering for R,G,B channels*/ - addr = FMT_REG(mmFMT_DITHER_RAND_R_SEED); - set_reg_field_value(dither_r_value, params->r_seed_value, - FMT_DITHER_RAND_R_SEED, - FMT_RAND_R_SEED); - dm_write_reg(opp110->base.ctx, addr, dither_r_value); - - addr = FMT_REG(mmFMT_DITHER_RAND_G_SEED); - set_reg_field_value(dither_g_value, - params->g_seed_value, - FMT_DITHER_RAND_G_SEED, - FMT_RAND_G_SEED); - dm_write_reg(opp110->base.ctx, addr, dither_g_value); - - addr = FMT_REG(mmFMT_DITHER_RAND_B_SEED); - set_reg_field_value(dither_b_value, params->b_seed_value, - FMT_DITHER_RAND_B_SEED, - FMT_RAND_B_SEED); - dm_write_reg(opp110->base.ctx, addr, dither_b_value); - - /* FMT_OFFSET_R_Cr 31:16 0x0 Setting the zero - * offset for the R/Cr channel, lower 4LSB - * is forced to zeros. Typically set to 0 - * RGB and 0x80000 YCbCr. - */ - /* FMT_OFFSET_G_Y 31:16 0x0 Setting the zero - * offset for the G/Y channel, lower 4LSB is - * forced to zeros. Typically set to 0 RGB - * and 0x80000 YCbCr. - */ - /* FMT_OFFSET_B_Cb 31:16 0x0 Setting the zero - * offset for the B/Cb channel, lower 4LSB is - * forced to zeros. Typically set to 0 RGB and - * 0x80000 YCbCr. - */ - - /*Set spatial dithering bit depth*/ - set_reg_field_value(depth_cntl_value, - params->flags.SPATIAL_DITHER_DEPTH, - FMT_BIT_DEPTH_CONTROL, - FMT_SPATIAL_DITHER_DEPTH); - - /* Set spatial dithering mode - * (default is Seed patterrn AAAA...) - */ - set_reg_field_value(depth_cntl_value, - params->flags.SPATIAL_DITHER_MODE, - FMT_BIT_DEPTH_CONTROL, - FMT_SPATIAL_DITHER_MODE); - - /*Reset only at startup*/ - set_reg_field_value(depth_cntl_value, - params->flags.FRAME_RANDOM, - FMT_BIT_DEPTH_CONTROL, - FMT_FRAME_RANDOM_ENABLE); - - /*Set RGB data dithered with x^28+x^3+1*/ - set_reg_field_value(depth_cntl_value, - params->flags.RGB_RANDOM, - FMT_BIT_DEPTH_CONTROL, - FMT_RGB_RANDOM_ENABLE); - - /*Disable High pass filter*/ - set_reg_field_value(depth_cntl_value, - params->flags.HIGHPASS_RANDOM, - FMT_BIT_DEPTH_CONTROL, - FMT_HIGHPASS_RANDOM_ENABLE); - - /*Enable spatial dithering*/ - set_reg_field_value(depth_cntl_value, - 1, - FMT_BIT_DEPTH_CONTROL, - FMT_SPATIAL_DITHER_EN); - - addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL); - dm_write_reg(opp110->base.ctx, addr, depth_cntl_value); - -} - -/** - * SetTemporalDither (Frame Modulation) - * 1) set temporal dither depth - * 2) select pattern: from hard-coded pattern or programmable pattern - * 3) select optimized strips for BGR or RGB LCD sub-pixel - * 4) set s matrix - * 5) set t matrix - * 6) set grey level for 0.25, 0.5, 0.75 - * 7) enable temporal dithering - */ -static void set_temporal_dither( - struct dce110_opp *opp110, - const struct bit_depth_reduction_params *params) -{ - uint32_t addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL); - uint32_t value; - - /*Disable temporal (frame modulation) dithering first*/ - value = dm_read_reg(opp110->base.ctx, addr); - - set_reg_field_value(value, - 0, - FMT_BIT_DEPTH_CONTROL, - FMT_TEMPORAL_DITHER_EN); - - set_reg_field_value(value, - 0, - FMT_BIT_DEPTH_CONTROL, - FMT_TEMPORAL_DITHER_RESET); - set_reg_field_value(value, - 0, - FMT_BIT_DEPTH_CONTROL, - FMT_TEMPORAL_DITHER_OFFSET); - set_reg_field_value(value, - 0, - FMT_BIT_DEPTH_CONTROL, - FMT_TEMPORAL_DITHER_DEPTH); - set_reg_field_value(value, - 0, - FMT_BIT_DEPTH_CONTROL, - FMT_TEMPORAL_LEVEL); - set_reg_field_value(value, - 0, - FMT_BIT_DEPTH_CONTROL, - FMT_25FRC_SEL); - - set_reg_field_value(value, - 0, - FMT_BIT_DEPTH_CONTROL, - FMT_50FRC_SEL); - - set_reg_field_value(value, - 0, - FMT_BIT_DEPTH_CONTROL, - FMT_75FRC_SEL); - - dm_write_reg(opp110->base.ctx, addr, value); - - /* no 10bpc dither on DCE11*/ - if (params->flags.FRAME_MODULATION_ENABLED == 0 || - params->flags.FRAME_MODULATION_DEPTH == 2) - return; - - /* Set temporal dithering depth*/ - set_reg_field_value(value, - params->flags.FRAME_MODULATION_DEPTH, - FMT_BIT_DEPTH_CONTROL, - FMT_TEMPORAL_DITHER_DEPTH); - - set_reg_field_value(value, - 0, - FMT_BIT_DEPTH_CONTROL, - FMT_TEMPORAL_DITHER_RESET); - - set_reg_field_value(value, - 0, - FMT_BIT_DEPTH_CONTROL, - FMT_TEMPORAL_DITHER_OFFSET); - - /*Select legacy pattern based on FRC and Temporal level*/ - addr = FMT_REG(mmFMT_TEMPORAL_DITHER_PATTERN_CONTROL); - dm_write_reg(opp110->base.ctx, addr, 0); - /*Set s matrix*/ - addr = FMT_REG( - mmFMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX); - dm_write_reg(opp110->base.ctx, addr, 0); - /*Set t matrix*/ - addr = FMT_REG( - mmFMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX); - dm_write_reg(opp110->base.ctx, addr, 0); - - /*Select patterns for 0.25, 0.5 and 0.75 grey level*/ - set_reg_field_value(value, - params->flags.TEMPORAL_LEVEL, - FMT_BIT_DEPTH_CONTROL, - FMT_TEMPORAL_LEVEL); - - set_reg_field_value(value, - params->flags.FRC25, - FMT_BIT_DEPTH_CONTROL, - FMT_25FRC_SEL); - - set_reg_field_value(value, - params->flags.FRC50, - FMT_BIT_DEPTH_CONTROL, - FMT_50FRC_SEL); - - set_reg_field_value(value, - params->flags.FRC75, - FMT_BIT_DEPTH_CONTROL, - FMT_75FRC_SEL); - - /*Enable bit reduction by temporal (frame modulation) dithering*/ - set_reg_field_value(value, - 1, - FMT_BIT_DEPTH_CONTROL, - FMT_TEMPORAL_DITHER_EN); - - addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL); - dm_write_reg(opp110->base.ctx, addr, value); - -} - -/** - * Set Clamping - * 1) Set clamping format based on bpc - 0 for 6bpc (No clamping) - * 1 for 8 bpc - * 2 for 10 bpc - * 3 for 12 bpc - * 7 for programable - * 2) Enable clamp if Limited range requested - */ -void dce110_opp_set_clamping( - struct dce110_opp *opp110, - const struct clamping_and_pixel_encoding_params *params) -{ - uint32_t clamp_cntl_value = 0; - uint32_t red_clamp_value = 0; - uint32_t green_clamp_value = 0; - uint32_t blue_clamp_value = 0; - uint32_t addr = FMT_REG(mmFMT_CLAMP_CNTL); - - clamp_cntl_value = dm_read_reg(opp110->base.ctx, addr); - - set_reg_field_value(clamp_cntl_value, - 0, - FMT_CLAMP_CNTL, - FMT_CLAMP_DATA_EN); - - set_reg_field_value(clamp_cntl_value, - 0, - FMT_CLAMP_CNTL, - FMT_CLAMP_COLOR_FORMAT); - - switch (params->clamping_level) { - case CLAMPING_FULL_RANGE: - break; - - case CLAMPING_LIMITED_RANGE_8BPC: - set_reg_field_value(clamp_cntl_value, - 1, - FMT_CLAMP_CNTL, - FMT_CLAMP_DATA_EN); - - set_reg_field_value(clamp_cntl_value, - 1, - FMT_CLAMP_CNTL, - FMT_CLAMP_COLOR_FORMAT); - - break; - - case CLAMPING_LIMITED_RANGE_10BPC: - set_reg_field_value(clamp_cntl_value, - 1, - FMT_CLAMP_CNTL, - FMT_CLAMP_DATA_EN); - - set_reg_field_value(clamp_cntl_value, - 2, - FMT_CLAMP_CNTL, - FMT_CLAMP_COLOR_FORMAT); - - break; - case CLAMPING_LIMITED_RANGE_12BPC: - set_reg_field_value(clamp_cntl_value, - 1, - FMT_CLAMP_CNTL, - FMT_CLAMP_DATA_EN); - - set_reg_field_value(clamp_cntl_value, - 3, - FMT_CLAMP_CNTL, - FMT_CLAMP_COLOR_FORMAT); - - break; - case CLAMPING_LIMITED_RANGE_PROGRAMMABLE: - set_reg_field_value(clamp_cntl_value, - 1, - FMT_CLAMP_CNTL, - FMT_CLAMP_DATA_EN); - - set_reg_field_value(clamp_cntl_value, - 7, - FMT_CLAMP_CNTL, - FMT_CLAMP_COLOR_FORMAT); - - /*set the defaults*/ - set_reg_field_value(red_clamp_value, - 0x10, - FMT_CLAMP_COMPONENT_R, - FMT_CLAMP_LOWER_R); - - set_reg_field_value(red_clamp_value, - 0xFEF, - FMT_CLAMP_COMPONENT_R, - FMT_CLAMP_UPPER_R); - - addr = FMT_REG(mmFMT_CLAMP_COMPONENT_R); - dm_write_reg(opp110->base.ctx, addr, red_clamp_value); - - set_reg_field_value(green_clamp_value, - 0x10, - FMT_CLAMP_COMPONENT_G, - FMT_CLAMP_LOWER_G); - - set_reg_field_value(green_clamp_value, - 0xFEF, - FMT_CLAMP_COMPONENT_G, - FMT_CLAMP_UPPER_G); - - addr = FMT_REG(mmFMT_CLAMP_COMPONENT_G); - dm_write_reg(opp110->base.ctx, addr, green_clamp_value); - - set_reg_field_value(blue_clamp_value, - 0x10, - FMT_CLAMP_COMPONENT_B, - FMT_CLAMP_LOWER_B); - - set_reg_field_value(blue_clamp_value, - 0xFEF, - FMT_CLAMP_COMPONENT_B, - FMT_CLAMP_UPPER_B); - - addr = FMT_REG(mmFMT_CLAMP_COMPONENT_B); - dm_write_reg(opp110->base.ctx, addr, blue_clamp_value); - - break; - - default: - break; - } - - addr = FMT_REG(mmFMT_CLAMP_CNTL); - /*Set clamp control*/ - dm_write_reg(opp110->base.ctx, addr, clamp_cntl_value); - -} - -/** - * set_pixel_encoding - * - * Set Pixel Encoding - * 0: RGB 4:4:4 or YCbCr 4:4:4 or YOnly - * 1: YCbCr 4:2:2 - */ -static void set_pixel_encoding( - struct dce110_opp *opp110, - const struct clamping_and_pixel_encoding_params *params) -{ - uint32_t fmt_cntl_value; - uint32_t addr = FMT_REG(mmFMT_CONTROL); - - /*RGB 4:4:4 or YCbCr 4:4:4 - 0; YCbCr 4:2:2 -1.*/ - fmt_cntl_value = dm_read_reg(opp110->base.ctx, addr); - - set_reg_field_value(fmt_cntl_value, - 0, - FMT_CONTROL, - FMT_PIXEL_ENCODING); - - if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) { - set_reg_field_value(fmt_cntl_value, - 1, - FMT_CONTROL, - FMT_PIXEL_ENCODING); - - /*00 - Pixels drop mode ,01 - Pixels average mode*/ - set_reg_field_value(fmt_cntl_value, - 0, - FMT_CONTROL, - FMT_SUBSAMPLING_MODE); - - /*00 - Cb before Cr ,01 - Cr before Cb*/ - set_reg_field_value(fmt_cntl_value, - 0, - FMT_CONTROL, - FMT_SUBSAMPLING_ORDER); - } - dm_write_reg(opp110->base.ctx, addr, fmt_cntl_value); - -} - -void dce110_opp_program_bit_depth_reduction( - struct output_pixel_processor *opp, - const struct bit_depth_reduction_params *params) -{ - struct dce110_opp *opp110 = TO_DCE110_OPP(opp); - - set_truncation(opp110, params); - set_spatial_dither(opp110, params); - set_temporal_dither(opp110, params); -} - -void dce110_opp_program_clamping_and_pixel_encoding( - struct output_pixel_processor *opp, - const struct clamping_and_pixel_encoding_params *params) -{ - struct dce110_opp *opp110 = TO_DCE110_OPP(opp); - - dce110_opp_set_clamping(opp110, params); - set_pixel_encoding(opp110, params); -} - -void dce110_opp_set_dyn_expansion( - struct output_pixel_processor *opp, - enum dc_color_space color_sp, - enum dc_color_depth color_dpth, - enum signal_type signal) -{ - struct dce110_opp *opp110 = TO_DCE110_OPP(opp); - uint32_t value; - bool enable_dyn_exp = false; - uint32_t addr = FMT_REG(mmFMT_DYNAMIC_EXP_CNTL); - - value = dm_read_reg(opp->ctx, addr); - - set_reg_field_value(value, 0, - FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN); - set_reg_field_value(value, 0, - FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE); - - /* From HW programming guide: - FMT_DYNAMIC_EXP_EN = 0 for limited RGB or YCbCr output - FMT_DYNAMIC_EXP_EN = 1 for RGB full range only*/ - if (color_sp == COLOR_SPACE_SRGB) - enable_dyn_exp = true; - - /*00 - 10-bit -> 12-bit dynamic expansion*/ - /*01 - 8-bit -> 12-bit dynamic expansion*/ - if (signal == SIGNAL_TYPE_HDMI_TYPE_A) { - switch (color_dpth) { - case COLOR_DEPTH_888: - set_reg_field_value(value, enable_dyn_exp ? 1:0, - FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN); - set_reg_field_value(value, 1, - FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE); - break; - case COLOR_DEPTH_101010: - set_reg_field_value(value, enable_dyn_exp ? 1:0, - FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN); - set_reg_field_value(value, 0, - FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE); - break; - case COLOR_DEPTH_121212: - break; - default: - break; - } - } - - dm_write_reg(opp->ctx, addr, value); -} - -void dce110_opp_program_fmt( - struct output_pixel_processor *opp, - struct bit_depth_reduction_params *fmt_bit_depth, - struct clamping_and_pixel_encoding_params *clamping) -{ - /* dithering is affected by , hence should be - * programmed afterwards */ - dce110_opp_program_bit_depth_reduction( - opp, - fmt_bit_depth); - - dce110_opp_program_clamping_and_pixel_encoding( - opp, - clamping); - - return; -} diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma.c deleted file mode 100644 index 62051abcfe2f..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma.c +++ /dev/null @@ -1,537 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" - -/* include DCE11 register header files */ -#include "dce/dce_11_0_d.h" -#include "dce/dce_11_0_sh_mask.h" - -#include "dce110_opp.h" -#include "gamma_types.h" - -#define DCP_REG(reg)\ - (reg + opp110->offsets.dcp_offset) - -#define DCFE_REG(reg)\ - (reg + opp110->offsets.dcfe_offset) - -enum { - MAX_PWL_ENTRY = 128, - MAX_REGIONS_NUMBER = 16 - -}; - -/* - ***************************************************************************** - * Function: regamma_config_regions_and_segments - * - * build regamma curve by using predefined hw points - * uses interface parameters ,like EDID coeff. - * - * @param : parameters interface parameters - * @return void - * - * @note - * - * @see - * - ***************************************************************************** - */ -static void regamma_config_regions_and_segments( - struct dce110_opp *opp110, - const struct pwl_params *params) -{ - const struct gamma_curve *curve; - uint32_t value = 0; - - { - set_reg_field_value( - value, - params->arr_points[0].custom_float_x, - REGAMMA_CNTLA_START_CNTL, - REGAMMA_CNTLA_EXP_REGION_START); - - set_reg_field_value( - value, - 0, - REGAMMA_CNTLA_START_CNTL, - REGAMMA_CNTLA_EXP_REGION_START_SEGMENT); - - dm_write_reg(opp110->base.ctx, - DCP_REG(mmREGAMMA_CNTLA_START_CNTL), - value); - } - { - value = 0; - set_reg_field_value( - value, - params->arr_points[0].custom_float_slope, - REGAMMA_CNTLA_SLOPE_CNTL, - REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE); - - dm_write_reg(opp110->base.ctx, - DCP_REG(mmREGAMMA_CNTLA_SLOPE_CNTL), value); - } - { - value = 0; - set_reg_field_value( - value, - params->arr_points[1].custom_float_x, - REGAMMA_CNTLA_END_CNTL1, - REGAMMA_CNTLA_EXP_REGION_END); - - dm_write_reg(opp110->base.ctx, - DCP_REG(mmREGAMMA_CNTLA_END_CNTL1), value); - } - { - value = 0; - set_reg_field_value( - value, - params->arr_points[2].custom_float_slope, - REGAMMA_CNTLA_END_CNTL2, - REGAMMA_CNTLA_EXP_REGION_END_BASE); - - set_reg_field_value( - value, - params->arr_points[1].custom_float_y, - REGAMMA_CNTLA_END_CNTL2, - REGAMMA_CNTLA_EXP_REGION_END_SLOPE); - - dm_write_reg(opp110->base.ctx, - DCP_REG(mmREGAMMA_CNTLA_END_CNTL2), value); - } - - curve = params->arr_curve_points; - - { - value = 0; - set_reg_field_value( - value, - curve[0].offset, - REGAMMA_CNTLA_REGION_0_1, - REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET); - - set_reg_field_value( - value, - curve[0].segments_num, - REGAMMA_CNTLA_REGION_0_1, - REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS); - - set_reg_field_value( - value, - curve[1].offset, - REGAMMA_CNTLA_REGION_0_1, - REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET); - - set_reg_field_value( - value, - curve[1].segments_num, - REGAMMA_CNTLA_REGION_0_1, - REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS); - - dm_write_reg( - opp110->base.ctx, - DCP_REG(mmREGAMMA_CNTLA_REGION_0_1), - value); - } - - curve += 2; - { - value = 0; - set_reg_field_value( - value, - curve[0].offset, - REGAMMA_CNTLA_REGION_2_3, - REGAMMA_CNTLA_EXP_REGION2_LUT_OFFSET); - - set_reg_field_value( - value, - curve[0].segments_num, - REGAMMA_CNTLA_REGION_2_3, - REGAMMA_CNTLA_EXP_REGION2_NUM_SEGMENTS); - - set_reg_field_value( - value, - curve[1].offset, - REGAMMA_CNTLA_REGION_2_3, - REGAMMA_CNTLA_EXP_REGION3_LUT_OFFSET); - - set_reg_field_value( - value, - curve[1].segments_num, - REGAMMA_CNTLA_REGION_2_3, - REGAMMA_CNTLA_EXP_REGION3_NUM_SEGMENTS); - - dm_write_reg(opp110->base.ctx, - DCP_REG(mmREGAMMA_CNTLA_REGION_2_3), - value); - } - - curve += 2; - { - value = 0; - set_reg_field_value( - value, - curve[0].offset, - REGAMMA_CNTLA_REGION_4_5, - REGAMMA_CNTLA_EXP_REGION4_LUT_OFFSET); - - set_reg_field_value( - value, - curve[0].segments_num, - REGAMMA_CNTLA_REGION_4_5, - REGAMMA_CNTLA_EXP_REGION4_NUM_SEGMENTS); - - set_reg_field_value( - value, - curve[1].offset, - REGAMMA_CNTLA_REGION_4_5, - REGAMMA_CNTLA_EXP_REGION5_LUT_OFFSET); - - set_reg_field_value( - value, - curve[1].segments_num, - REGAMMA_CNTLA_REGION_4_5, - REGAMMA_CNTLA_EXP_REGION5_NUM_SEGMENTS); - - dm_write_reg(opp110->base.ctx, - DCP_REG(mmREGAMMA_CNTLA_REGION_4_5), - value); - } - - curve += 2; - { - value = 0; - set_reg_field_value( - value, - curve[0].offset, - REGAMMA_CNTLA_REGION_6_7, - REGAMMA_CNTLA_EXP_REGION6_LUT_OFFSET); - - set_reg_field_value( - value, - curve[0].segments_num, - REGAMMA_CNTLA_REGION_6_7, - REGAMMA_CNTLA_EXP_REGION6_NUM_SEGMENTS); - - set_reg_field_value( - value, - curve[1].offset, - REGAMMA_CNTLA_REGION_6_7, - REGAMMA_CNTLA_EXP_REGION7_LUT_OFFSET); - - set_reg_field_value( - value, - curve[1].segments_num, - REGAMMA_CNTLA_REGION_6_7, - REGAMMA_CNTLA_EXP_REGION7_NUM_SEGMENTS); - - dm_write_reg(opp110->base.ctx, - DCP_REG(mmREGAMMA_CNTLA_REGION_6_7), - value); - } - - curve += 2; - { - value = 0; - set_reg_field_value( - value, - curve[0].offset, - REGAMMA_CNTLA_REGION_8_9, - REGAMMA_CNTLA_EXP_REGION8_LUT_OFFSET); - - set_reg_field_value( - value, - curve[0].segments_num, - REGAMMA_CNTLA_REGION_8_9, - REGAMMA_CNTLA_EXP_REGION8_NUM_SEGMENTS); - - set_reg_field_value( - value, - curve[1].offset, - REGAMMA_CNTLA_REGION_8_9, - REGAMMA_CNTLA_EXP_REGION9_LUT_OFFSET); - - set_reg_field_value( - value, - curve[1].segments_num, - REGAMMA_CNTLA_REGION_8_9, - REGAMMA_CNTLA_EXP_REGION9_NUM_SEGMENTS); - - dm_write_reg(opp110->base.ctx, - DCP_REG(mmREGAMMA_CNTLA_REGION_8_9), - value); - } - - curve += 2; - { - value = 0; - set_reg_field_value( - value, - curve[0].offset, - REGAMMA_CNTLA_REGION_10_11, - REGAMMA_CNTLA_EXP_REGION10_LUT_OFFSET); - - set_reg_field_value( - value, - curve[0].segments_num, - REGAMMA_CNTLA_REGION_10_11, - REGAMMA_CNTLA_EXP_REGION10_NUM_SEGMENTS); - - set_reg_field_value( - value, - curve[1].offset, - REGAMMA_CNTLA_REGION_10_11, - REGAMMA_CNTLA_EXP_REGION11_LUT_OFFSET); - - set_reg_field_value( - value, - curve[1].segments_num, - REGAMMA_CNTLA_REGION_10_11, - REGAMMA_CNTLA_EXP_REGION11_NUM_SEGMENTS); - - dm_write_reg(opp110->base.ctx, - DCP_REG(mmREGAMMA_CNTLA_REGION_10_11), - value); - } - - curve += 2; - { - value = 0; - set_reg_field_value( - value, - curve[0].offset, - REGAMMA_CNTLA_REGION_12_13, - REGAMMA_CNTLA_EXP_REGION12_LUT_OFFSET); - - set_reg_field_value( - value, - curve[0].segments_num, - REGAMMA_CNTLA_REGION_12_13, - REGAMMA_CNTLA_EXP_REGION12_NUM_SEGMENTS); - - set_reg_field_value( - value, - curve[1].offset, - REGAMMA_CNTLA_REGION_12_13, - REGAMMA_CNTLA_EXP_REGION13_LUT_OFFSET); - - set_reg_field_value( - value, - curve[1].segments_num, - REGAMMA_CNTLA_REGION_12_13, - REGAMMA_CNTLA_EXP_REGION13_NUM_SEGMENTS); - - dm_write_reg(opp110->base.ctx, - DCP_REG(mmREGAMMA_CNTLA_REGION_12_13), - value); - } - - curve += 2; - { - value = 0; - set_reg_field_value( - value, - curve[0].offset, - REGAMMA_CNTLA_REGION_14_15, - REGAMMA_CNTLA_EXP_REGION14_LUT_OFFSET); - - set_reg_field_value( - value, - curve[0].segments_num, - REGAMMA_CNTLA_REGION_14_15, - REGAMMA_CNTLA_EXP_REGION14_NUM_SEGMENTS); - - set_reg_field_value( - value, - curve[1].offset, - REGAMMA_CNTLA_REGION_14_15, - REGAMMA_CNTLA_EXP_REGION15_LUT_OFFSET); - - set_reg_field_value( - value, - curve[1].segments_num, - REGAMMA_CNTLA_REGION_14_15, - REGAMMA_CNTLA_EXP_REGION15_NUM_SEGMENTS); - - dm_write_reg(opp110->base.ctx, - DCP_REG(mmREGAMMA_CNTLA_REGION_14_15), - value); - } -} - -static void program_pwl( - struct dce110_opp *opp110, - const struct pwl_params *params) -{ - uint32_t value; - - { - uint8_t max_tries = 10; - uint8_t counter = 0; - - /* Power on LUT memory */ - value = dm_read_reg(opp110->base.ctx, - DCFE_REG(mmDCFE_MEM_PWR_CTRL)); - - set_reg_field_value( - value, - 1, - DCFE_MEM_PWR_CTRL, - DCP_REGAMMA_MEM_PWR_DIS); - - dm_write_reg(opp110->base.ctx, - DCFE_REG(mmDCFE_MEM_PWR_CTRL), value); - - while (counter < max_tries) { - value = - dm_read_reg( - opp110->base.ctx, - DCFE_REG(mmDCFE_MEM_PWR_STATUS)); - - if (get_reg_field_value( - value, - DCFE_MEM_PWR_STATUS, - DCP_REGAMMA_MEM_PWR_STATE) == 0) - break; - - ++counter; - } - - if (counter == max_tries) { - dm_logger_write(opp110->base.ctx->logger, LOG_WARNING, - "%s: regamma lut was not powered on " - "in a timely manner," - " programming still proceeds\n", - __func__); - } - } - - value = 0; - - set_reg_field_value( - value, - 7, - REGAMMA_LUT_WRITE_EN_MASK, - REGAMMA_LUT_WRITE_EN_MASK); - - dm_write_reg(opp110->base.ctx, - DCP_REG(mmREGAMMA_LUT_WRITE_EN_MASK), value); - dm_write_reg(opp110->base.ctx, - DCP_REG(mmREGAMMA_LUT_INDEX), 0); - - /* Program REGAMMA_LUT_DATA */ - { - const uint32_t addr = DCP_REG(mmREGAMMA_LUT_DATA); - - uint32_t i = 0; - - const struct pwl_result_data *rgb = params->rgb_resulted; - - while (i != params->hw_points_num) { - dm_write_reg(opp110->base.ctx, addr, rgb->red_reg); - dm_write_reg(opp110->base.ctx, addr, rgb->green_reg); - dm_write_reg(opp110->base.ctx, addr, rgb->blue_reg); - - dm_write_reg(opp110->base.ctx, addr, - rgb->delta_red_reg); - dm_write_reg(opp110->base.ctx, addr, - rgb->delta_green_reg); - dm_write_reg(opp110->base.ctx, addr, - rgb->delta_blue_reg); - - ++rgb; - ++i; - } - } - - /* we are done with DCP LUT memory; re-enable low power mode */ - value = dm_read_reg(opp110->base.ctx, DCFE_REG(mmDCFE_MEM_PWR_CTRL)); - - set_reg_field_value( - value, - 0, - DCFE_MEM_PWR_CTRL, - DCP_REGAMMA_MEM_PWR_DIS); - - dm_write_reg(opp110->base.ctx, DCFE_REG(mmDCFE_MEM_PWR_CTRL), value); -} - -bool dce110_opp_program_regamma_pwl( - struct output_pixel_processor *opp, - const struct pwl_params *params) -{ - struct dce110_opp *opp110 = TO_DCE110_OPP(opp); - - /* Setup regions */ - regamma_config_regions_and_segments(opp110, params); - - /* Program PWL */ - program_pwl(opp110, params); - - return true; -} - -void dce110_opp_power_on_regamma_lut( - struct output_pixel_processor *opp, - bool power_on) -{ - struct dce110_opp *opp110 = TO_DCE110_OPP(opp); - - uint32_t value = - dm_read_reg(opp->ctx, DCFE_REG(mmDCFE_MEM_PWR_CTRL)); - - set_reg_field_value( - value, - power_on, - DCFE_MEM_PWR_CTRL, - DCP_REGAMMA_MEM_PWR_DIS); - - set_reg_field_value( - value, - power_on, - DCFE_MEM_PWR_CTRL, - DCP_LUT_MEM_PWR_DIS); - - dm_write_reg(opp->ctx, DCFE_REG(mmDCFE_MEM_PWR_CTRL), value); -} - -void dce110_opp_set_regamma_mode(struct output_pixel_processor *opp, - enum opp_regamma mode) -{ - struct dce110_opp *opp110 = TO_DCE110_OPP(opp); - uint32_t value = dm_read_reg(opp110->base.ctx, - DCP_REG(mmREGAMMA_CONTROL)); - - set_reg_field_value( - value, - mode, - REGAMMA_CONTROL, - GRPH_REGAMMA_MODE); - - dm_write_reg(opp110->base.ctx, DCP_REG(mmREGAMMA_CONTROL), - value); -} diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c index 3b3a9175b2c3..81fcbc52e4ab 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c @@ -29,7 +29,7 @@ #include "dce/dce_11_0_d.h" #include "dce/dce_11_0_sh_mask.h" -#include "dce110_opp.h" +#include "dce/dce_opp.h" #include "gamma_types.h" static void power_on_lut(struct output_pixel_processor *opp, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c index 4b32397529ec..dfd63a71d214 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c @@ -29,7 +29,7 @@ #include "dce/dce_11_0_d.h" #include "dce/dce_11_0_sh_mask.h" -#include "dce110_opp.h" +#include "dce/dce_opp.h" #include "dce110_opp_v.h" #include "gamma_types.h" diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index fa601f7f0b5a..d4e1ca933b40 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -43,7 +43,7 @@ #include "dce110/dce110_ipp.h" #include "dce/dce_transform.h" #include "dce110/dce110_transform_v.h" -#include "dce110/dce110_opp.h" +#include "dce/dce_opp.h" #include "dce110/dce110_opp_v.h" #include "dce/dce_clocks.h" #include "dce/dce_clock_source.h" @@ -283,6 +283,28 @@ static const struct dce_stream_encoder_mask se_mask = { SE_COMMON_MASK_SH_LIST_DCE110(_MASK) }; +#define opp_regs(id)\ +[id] = {\ + OPP_DCE_110_REG_LIST(id),\ +} + +static const struct dce_opp_registers opp_regs[] = { + opp_regs(0), + opp_regs(1), + opp_regs(2), + opp_regs(3), + opp_regs(4), + opp_regs(5) +}; + +static const struct dce_opp_shift opp_shift = { + OPP_COMMON_MASK_SH_LIST_DCE_110(__SHIFT) +}; + +static const struct dce_opp_mask opp_mask = { + OPP_COMMON_MASK_SH_LIST_DCE_110(_MASK) +}; + #define audio_regs(id)\ [id] = {\ AUD_COMMON_REG_LIST(id)\ @@ -307,34 +329,7 @@ static const struct dce_aduio_mask audio_mask = { }; /* AG TBD Needs to be reduced back to 3 pipes once dce10 hw sequencer implemented. */ -static const struct dce110_opp_reg_offsets dce110_opp_reg_offsets[] = { -{ - .fmt_offset = (mmFMT0_FMT_CONTROL - mmFMT0_FMT_CONTROL), - .dcfe_offset = (mmDCFE0_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), - .dcp_offset = (mmDCP0_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -}, -{ .fmt_offset = (mmFMT1_FMT_CONTROL - mmFMT0_FMT_CONTROL), - .dcfe_offset = (mmDCFE1_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), - .dcp_offset = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -}, -{ .fmt_offset = (mmFMT2_FMT_CONTROL - mmFMT0_FMT_CONTROL), - .dcfe_offset = (mmDCFE2_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), - .dcp_offset = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -}, -{ - .fmt_offset = (mmFMT3_FMT_CONTROL - mmFMT0_FMT_CONTROL), - .dcfe_offset = (mmDCFE3_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), - .dcp_offset = (mmDCP3_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -}, -{ .fmt_offset = (mmFMT4_FMT_CONTROL - mmFMT0_FMT_CONTROL), - .dcfe_offset = (mmDCFE4_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), - .dcp_offset = (mmDCP4_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -}, -{ .fmt_offset = (mmFMT5_FMT_CONTROL - mmFMT0_FMT_CONTROL), - .dcfe_offset = (mmDCFE5_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), - .dcp_offset = (mmDCP5_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -} -}; + #define clk_src_regs(id)\ [id] = {\ @@ -603,8 +598,7 @@ struct link_encoder *dce110_link_encoder_create( static struct output_pixel_processor *dce110_opp_create( struct dc_context *ctx, - uint32_t inst, - const struct dce110_opp_reg_offsets *offsets) + uint32_t inst) { struct dce110_opp *opp = dm_alloc(sizeof(struct dce110_opp)); @@ -613,7 +607,7 @@ static struct output_pixel_processor *dce110_opp_create( return NULL; if (dce110_opp_construct(opp, - ctx, inst, offsets)) + ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask)) return &opp->base; BREAK_TO_DEBUGGER(); @@ -1329,7 +1323,7 @@ static bool construct( goto res_create_fail; } - pool->base.opps[i] = dce110_opp_create(ctx, i, &dce110_opp_reg_offsets[i]); + pool->base.opps[i] = dce110_opp_create(ctx, i); if (pool->base.opps[i] == NULL) { BREAK_TO_DEBUGGER(); dm_error( diff --git a/drivers/gpu/drm/amd/display/dc/dce112/Makefile b/drivers/gpu/drm/amd/display/dc/dce112/Makefile index 34fba0730bed..2d536fbc60c4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dce112/Makefile @@ -3,8 +3,7 @@ # It provides the control and status of HW CRTC block. DCE112 = dce112_compressor.o dce112_hw_sequencer.o \ -dce112_resource.o dce112_mem_input.o dce112_opp_formatter.o \ -dce112_opp.o +dce112_resource.o dce112_mem_input.o AMD_DAL_DCE112 = $(addprefix $(AMDDALPATH)/dc/dce112/,$(DCE112)) diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_opp.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_opp.c deleted file mode 100644 index 23c2d1086b3b..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_opp.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" - -/* include DCE11 register header files */ -#include "dce/dce_11_2_d.h" -#include "dce/dce_11_2_sh_mask.h" - -#include "dce112_opp.h" - -#include "gamma_types.h" - -enum { - MAX_LUT_ENTRY = 256, - MAX_NUMBER_OF_ENTRIES = 256 -}; - -/*****************************************/ -/* Constructor, Destructor */ -/*****************************************/ - -static struct opp_funcs funcs = { - .opp_power_on_regamma_lut = dce110_opp_power_on_regamma_lut, - .opp_set_csc_adjustment = dce110_opp_set_csc_adjustment, - .opp_set_csc_default = dce110_opp_set_csc_default, - .opp_set_dyn_expansion = dce110_opp_set_dyn_expansion, - .opp_program_regamma_pwl = dce110_opp_program_regamma_pwl, - .opp_set_regamma_mode = dce110_opp_set_regamma_mode, - .opp_destroy = dce110_opp_destroy, - .opp_program_fmt = dce112_opp_program_fmt, - .opp_program_bit_depth_reduction = - dce110_opp_program_bit_depth_reduction -}; - -bool dce112_opp_construct(struct dce110_opp *opp110, - struct dc_context *ctx, - uint32_t inst, - const struct dce110_opp_reg_offsets *offsets) -{ - opp110->base.funcs = &funcs; - - opp110->base.ctx = ctx; - - opp110->base.inst = inst; - - opp110->offsets = *offsets; - - return true; -} diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_opp.h b/drivers/gpu/drm/amd/display/dc/dce112/dce112_opp.h deleted file mode 100644 index 9443b87776c6..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_opp.h +++ /dev/null @@ -1,48 +0,0 @@ -/* Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DC_OPP_DCE112_H__ -#define __DC_OPP_DCE112_H__ - -#include "dc_types.h" -#include "opp.h" -#include "../dce110/dce110_opp.h" -#include "core_types.h" - -void dce112_opp_program_clamping_and_pixel_encoding( - struct output_pixel_processor *opp, - const struct clamping_and_pixel_encoding_params *params); - -void dce112_opp_program_fmt( - struct output_pixel_processor *opp, - struct bit_depth_reduction_params *fmt_bit_depth, - struct clamping_and_pixel_encoding_params *clamping); - -bool dce112_opp_construct(struct dce110_opp *opp110, - struct dc_context *ctx, - uint32_t inst, - const struct dce110_opp_reg_offsets *offsets); - - -#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_opp_formatter.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_opp_formatter.c deleted file mode 100644 index 2d9072138834..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_opp_formatter.c +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" - -#include "dce/dce_11_2_d.h" -#include "dce/dce_11_2_sh_mask.h" - -#include "dce112_opp.h" - -#define FMT_REG(reg)\ - (reg + opp110->offsets.fmt_offset) -#define FMT_MEM_REG(reg)\ - (reg + opp110->offsets.fmt_mem_offset) - -/** - * Set Clamping - * 1) Set clamping format based on bpc - 0 for 6bpc (No clamping) - * 1 for 8 bpc - * 2 for 10 bpc - * 3 for 12 bpc - * 7 for programable - * 2) Enable clamp if Limited range requested - */ - -/** - * set_pixel_encoding - * - * Set Pixel Encoding - * 0: RGB 4:4:4 or YCbCr 4:4:4 or YOnly - * 1: YCbCr 4:2:2 - * 2: YCbCr 4:2:0 - */ -static void set_pixel_encoding( - struct dce110_opp *opp110, - const struct clamping_and_pixel_encoding_params *params) -{ - uint32_t fmt_cntl_value; - uint32_t addr = FMT_REG(mmFMT_CONTROL); - - /*RGB 4:4:4 or YCbCr 4:4:4 - 0; YCbCr 4:2:2 -1.*/ - fmt_cntl_value = dm_read_reg(opp110->base.ctx, addr); - - set_reg_field_value(fmt_cntl_value, - 0, - FMT_CONTROL, - FMT_PIXEL_ENCODING); - - /*00 - Pixels drop mode HW default*/ - set_reg_field_value(fmt_cntl_value, - 0, - FMT_CONTROL, - FMT_SUBSAMPLING_MODE); - - /* By default no bypass*/ - set_reg_field_value(fmt_cntl_value, - 0, - FMT_CONTROL, - FMT_CBCR_BIT_REDUCTION_BYPASS); - - if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) { - set_reg_field_value(fmt_cntl_value, - 1, - FMT_CONTROL, - FMT_PIXEL_ENCODING); - - /*00 - Cb before Cr ,01 - Cr before Cb*/ - set_reg_field_value(fmt_cntl_value, - 0, - FMT_CONTROL, - FMT_SUBSAMPLING_ORDER); - } - - if (params->pixel_encoding == PIXEL_ENCODING_YCBCR420) { - set_reg_field_value(fmt_cntl_value, - 2, - FMT_CONTROL, - FMT_PIXEL_ENCODING); - - /* 02 - Subsampling mode, 3 taps*/ - set_reg_field_value(fmt_cntl_value, - 2, - FMT_CONTROL, - FMT_SUBSAMPLING_MODE); - - /* 00 - Enable CbCr bit reduction bypass to preserve precision*/ - set_reg_field_value(fmt_cntl_value, - 1, - FMT_CONTROL, - FMT_CBCR_BIT_REDUCTION_BYPASS); - } - dm_write_reg(opp110->base.ctx, addr, fmt_cntl_value); - -} - -void dce112_opp_program_clamping_and_pixel_encoding( - struct output_pixel_processor *opp, - const struct clamping_and_pixel_encoding_params *params) -{ - struct dce110_opp *opp110 = TO_DCE110_OPP(opp); - - dce110_opp_set_clamping(opp110, params); - set_pixel_encoding(opp110, params); -} - -static void program_formatter_420_memory(struct output_pixel_processor *opp) -{ - struct dce110_opp *opp110 = TO_DCE110_OPP(opp); - uint32_t fmt_cntl_value; - uint32_t fmt_mem_cntl_value; - uint32_t fmt_cntl_addr = FMT_REG(mmFMT_CONTROL); - uint32_t fmt_mem_cntl_addr = FMT_MEM_REG(mmFMT_MEMORY0_CONTROL); - - fmt_mem_cntl_value = dm_read_reg(opp110->base.ctx, fmt_mem_cntl_addr); - fmt_cntl_value = dm_read_reg(opp110->base.ctx, fmt_cntl_addr); - /* Program source select*/ - /* Use HW default source select for FMT_MEMORYx_CONTROL */ - /* Use that value for FMT_SRC_SELECT as well*/ - set_reg_field_value(fmt_cntl_value, - get_reg_field_value(fmt_mem_cntl_value, FMT_MEMORY0_CONTROL, FMT420_MEM0_SOURCE_SEL), - FMT_CONTROL, - FMT_SRC_SELECT); - dm_write_reg(opp110->base.ctx, fmt_cntl_addr, fmt_cntl_value); - - /* Turn on the memory */ - set_reg_field_value(fmt_mem_cntl_value, - 0, - FMT_MEMORY0_CONTROL, - FMT420_MEM0_PWR_FORCE); - dm_write_reg(opp110->base.ctx, fmt_mem_cntl_addr, fmt_mem_cntl_value); -} - -static void program_formatter_reset_dig_resync_fifo(struct output_pixel_processor *opp) -{ - struct dce110_opp *opp110 = TO_DCE110_OPP(opp); - uint32_t value; - uint32_t addr = FMT_REG(mmFMT_CONTROL); - uint8_t counter = 10; - - - value = dm_read_reg(opp110->base.ctx, addr); - - /* clear previous phase lock status*/ - set_reg_field_value(value, - 1, - FMT_CONTROL, - FMT_420_PIXEL_PHASE_LOCKED_CLEAR); - dm_write_reg(opp110->base.ctx, addr, value); - - /* poll until FMT_420_PIXEL_PHASE_LOCKED become 1*/ - while (counter > 0) { - value = dm_read_reg(opp110->base.ctx, addr); - - if (get_reg_field_value( - value, - FMT_CONTROL, - FMT_420_PIXEL_PHASE_LOCKED) == 1) - break; - - msleep(10); - counter--; - } - - if (counter == 0) - dm_logger_write(opp->ctx->logger, LOG_ERROR, - "%s:opp program formattter reset dig resync info time out.\n", - __func__); -} - -void dce112_opp_program_fmt( - struct output_pixel_processor *opp, - struct bit_depth_reduction_params *fmt_bit_depth, - struct clamping_and_pixel_encoding_params *clamping) -{ - /* dithering is affected by , hence should be - * programmed afterwards */ - - if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420) - program_formatter_420_memory(opp); - - dce110_opp_program_bit_depth_reduction( - opp, - fmt_bit_depth); - - dce112_opp_program_clamping_and_pixel_encoding( - opp, - clamping); - - if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420) - program_formatter_reset_dig_resync_fifo(opp); - - return; -} diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 85d8b31acd02..2711893b71e5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -39,7 +39,7 @@ #include "dce/dce_link_encoder.h" #include "dce/dce_stream_encoder.h" #include "dce/dce_audio.h" -#include "dce112/dce112_opp.h" +#include "dce/dce_opp.h" #include "dce110/dce110_ipp.h" #include "dce/dce_clocks.h" #include "dce/dce_clock_source.h" @@ -306,6 +306,28 @@ static const struct dce_stream_encoder_mask se_mask = { SE_COMMON_MASK_SH_LIST_DCE112(_MASK) }; +#define opp_regs(id)\ +[id] = {\ + OPP_DCE_112_REG_LIST(id),\ +} + +static const struct dce_opp_registers opp_regs[] = { + opp_regs(0), + opp_regs(1), + opp_regs(2), + opp_regs(3), + opp_regs(4), + opp_regs(5) +}; + +static const struct dce_opp_shift opp_shift = { + OPP_COMMON_MASK_SH_LIST_DCE_112(__SHIFT) +}; + +static const struct dce_opp_mask opp_mask = { + OPP_COMMON_MASK_SH_LIST_DCE_112(_MASK) +}; + #define audio_regs(id)\ [id] = {\ AUD_COMMON_REG_LIST(id)\ @@ -328,42 +350,6 @@ static const struct dce_aduio_mask audio_mask = { AUD_COMMON_MASK_SH_LIST(_MASK) }; - -static const struct dce110_opp_reg_offsets dce112_opp_reg_offsets[] = { -{ - .fmt_offset = (mmFMT0_FMT_CONTROL - mmFMT0_FMT_CONTROL), - .fmt_mem_offset = (mmFMT_MEMORY0_CONTROL - mmFMT_MEMORY0_CONTROL), - .dcfe_offset = (mmDCFE0_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), - .dcp_offset = (mmDCP0_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -}, -{ .fmt_offset = (mmFMT1_FMT_CONTROL - mmFMT0_FMT_CONTROL), - .fmt_mem_offset = (mmFMT_MEMORY1_CONTROL - mmFMT_MEMORY0_CONTROL), - .dcfe_offset = (mmDCFE1_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), - .dcp_offset = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -}, -{ .fmt_offset = (mmFMT2_FMT_CONTROL - mmFMT0_FMT_CONTROL), - .fmt_mem_offset = (mmFMT_MEMORY2_CONTROL - mmFMT_MEMORY0_CONTROL), - .dcfe_offset = (mmDCFE2_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), - .dcp_offset = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -}, -{ - .fmt_offset = (mmFMT3_FMT_CONTROL - mmFMT0_FMT_CONTROL), - .fmt_mem_offset = (mmFMT_MEMORY3_CONTROL - mmFMT_MEMORY0_CONTROL), - .dcfe_offset = (mmDCFE3_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), - .dcp_offset = (mmDCP3_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -}, -{ .fmt_offset = (mmFMT4_FMT_CONTROL - mmFMT0_FMT_CONTROL), - .fmt_mem_offset = (mmFMT_MEMORY4_CONTROL - mmFMT_MEMORY0_CONTROL), - .dcfe_offset = (mmDCFE4_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), - .dcp_offset = (mmDCP4_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -}, -{ .fmt_offset = (mmFMT5_FMT_CONTROL - mmFMT0_FMT_CONTROL), - .fmt_mem_offset = (mmFMT_MEMORY5_CONTROL - mmFMT_MEMORY0_CONTROL), - .dcfe_offset = (mmDCFE5_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), - .dcp_offset = (mmDCP5_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -} -}; - #define clk_src_regs(index, id)\ [index] = {\ CS_COMMON_REG_LIST_DCE_112(id),\ @@ -631,8 +617,7 @@ void dce112_ipp_destroy(struct input_pixel_processor **ipp) struct output_pixel_processor *dce112_opp_create( struct dc_context *ctx, - uint32_t inst, - const struct dce110_opp_reg_offsets *offset) + uint32_t inst) { struct dce110_opp *opp = dm_alloc(sizeof(struct dce110_opp)); @@ -640,8 +625,8 @@ struct output_pixel_processor *dce112_opp_create( if (!opp) return NULL; - if (dce112_opp_construct(opp, - ctx, inst, offset)) + if (dce110_opp_construct(opp, + ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask)) return &opp->base; BREAK_TO_DEBUGGER(); @@ -1381,8 +1366,7 @@ static bool construct( pool->base.opps[i] = dce112_opp_create( ctx, - i, - &dce112_opp_reg_offsets[i]); + i); if (pool->base.opps[i] == NULL) { BREAK_TO_DEBUGGER(); dm_error( diff --git a/drivers/gpu/drm/amd/display/dc/dce80/Makefile b/drivers/gpu/drm/amd/display/dc/dce80/Makefile index 9979b8441a8d..0261d1bfccb5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dce80/Makefile @@ -2,9 +2,8 @@ # Makefile for the 'controller' sub-component of DAL. # It provides the control and status of HW CRTC block. -DCE80 = dce80_ipp.o dce80_ipp_gamma.o dce80_opp.o \ - dce80_opp_formatter.o dce80_opp_regamma.o \ - dce80_timing_generator.o dce80_opp_csc.o\ +DCE80 = dce80_ipp.o dce80_ipp_gamma.o \ + dce80_timing_generator.o \ dce80_compressor.o dce80_mem_input.o dce80_hw_sequencer.o \ dce80_resource.o diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp.c deleted file mode 100644 index b69e8a5d844d..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp.c +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" - -/* include DCE8 register header files */ -#include "dce/dce_8_0_d.h" -#include "dce/dce_8_0_sh_mask.h" - -#include "dce80_opp.h" - -#define FROM_OPP(opp)\ - container_of(opp, struct dce80_opp, base) - -enum { - MAX_LUT_ENTRY = 256, - MAX_NUMBER_OF_ENTRIES = 256 -}; - -static const struct dce80_opp_reg_offsets reg_offsets[] = { -{ - .fmt_offset = (mmFMT0_FMT_CONTROL - mmFMT0_FMT_CONTROL), - .crtc_offset = (mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL - - mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL), - .dcp_offset = (mmDCP0_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -}, -{ .fmt_offset = (mmFMT1_FMT_CONTROL - mmFMT0_FMT_CONTROL), - .crtc_offset = (mmCRTC1_DCFE_MEM_LIGHT_SLEEP_CNTL - - mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL), - .dcp_offset = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -}, -{ .fmt_offset = (mmFMT2_FMT_CONTROL - mmFMT0_FMT_CONTROL), - .crtc_offset = (mmCRTC2_DCFE_MEM_LIGHT_SLEEP_CNTL - - mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL), - .dcp_offset = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -}, -{ - .fmt_offset = (mmFMT3_FMT_CONTROL - mmFMT0_FMT_CONTROL), - .crtc_offset = (mmCRTC3_DCFE_MEM_LIGHT_SLEEP_CNTL - - mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL), - .dcp_offset = (mmDCP3_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -}, -{ - .fmt_offset = (mmFMT4_FMT_CONTROL - mmFMT0_FMT_CONTROL), - .crtc_offset = (mmCRTC4_DCFE_MEM_LIGHT_SLEEP_CNTL - - mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL), - .dcp_offset = (mmDCP4_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -}, -{ - .fmt_offset = (mmFMT5_FMT_CONTROL - mmFMT0_FMT_CONTROL), - .crtc_offset = (mmCRTC5_DCFE_MEM_LIGHT_SLEEP_CNTL - - mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL), - .dcp_offset = (mmDCP5_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -} -}; - -static const struct opp_funcs funcs = { - .opp_power_on_regamma_lut = dce80_opp_power_on_regamma_lut, - .opp_set_csc_adjustment = dce80_opp_set_csc_adjustment, - .opp_set_csc_default = dce80_opp_set_csc_default, - .opp_set_dyn_expansion = dce80_opp_set_dyn_expansion, - .opp_program_regamma_pwl = dce80_opp_program_regamma_pwl, - .opp_set_regamma_mode = dce80_opp_set_regamma_mode, - .opp_destroy = dce80_opp_destroy, - .opp_program_fmt = dce110_opp_program_fmt, -}; - -/*****************************************/ -/* Constructor, Destructor */ -/*****************************************/ - -bool dce80_opp_construct(struct dce80_opp *opp80, - struct dc_context *ctx, - uint32_t inst) -{ - if (inst >= ARRAY_SIZE(reg_offsets)) - return false; - - opp80->base.funcs = &funcs; - - opp80->base.ctx = ctx; - - opp80->base.inst = inst; - - opp80->offsets = reg_offsets[inst]; - - return true; -} - -void dce80_opp_destroy(struct output_pixel_processor **opp) -{ - dm_free(FROM_OPP(*opp)); - *opp = NULL; -} - -struct output_pixel_processor *dce80_opp_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dce80_opp *opp = - dm_alloc(sizeof(struct dce80_opp)); - - if (!opp) - return NULL; - - if (dce80_opp_construct(opp, - ctx, inst)) - return &opp->base; - - BREAK_TO_DEBUGGER(); - dm_free(opp); - return NULL; -} - diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp.h b/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp.h deleted file mode 100644 index 965cce37f7e3..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp.h +++ /dev/null @@ -1,130 +0,0 @@ -/* Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DC_OPP_DCE80_H__ -#define __DC_OPP_DCE80_H__ - -#include "dc_types.h" -#include "opp.h" -#include "gamma_types.h" -#include "../dce110/dce110_opp.h" - -struct gamma_parameters; - -struct dce80_regamma { - struct gamma_curve arr_curve_points[16]; - struct curve_points arr_points[3]; - uint32_t hw_points_num; - struct hw_x_point *coordinates_x; - struct pwl_result_data *rgb_resulted; - - /* re-gamma curve */ - struct pwl_float_data_ex *rgb_regamma; - /* coeff used to map user evenly distributed points - * to our hardware points (predefined) for gamma 256 */ - struct pixel_gamma_point *coeff128; - struct pixel_gamma_point *coeff128_oem; - /* coeff used to map user evenly distributed points - * to our hardware points (predefined) for gamma 1025 */ - struct pixel_gamma_point *coeff128_dx; - /* evenly distributed points, gamma 256 software points 0-255 */ - struct gamma_pixel *axis_x_256; - /* evenly distributed points, gamma 1025 software points 0-1025 */ - struct gamma_pixel *axis_x_1025; - /* OEM supplied gamma for regamma LUT */ - struct pwl_float_data *rgb_oem; - /* user supplied gamma */ - struct pwl_float_data *rgb_user; - uint32_t extra_points; - bool use_half_points; - struct fixed31_32 x_max1; - struct fixed31_32 x_max2; - struct fixed31_32 x_min; - struct fixed31_32 divider1; - struct fixed31_32 divider2; - struct fixed31_32 divider3; -}; - -/* OPP RELATED */ -#define TO_DCE80_OPP(opp)\ - container_of(opp, struct dce80_opp, base) - -struct dce80_opp_reg_offsets { - uint32_t fmt_offset; - uint32_t dcp_offset; - uint32_t crtc_offset; -}; - -struct dce80_opp { - struct output_pixel_processor base; - struct dce80_opp_reg_offsets offsets; - struct dce80_regamma regamma; -}; - -bool dce80_opp_construct(struct dce80_opp *opp80, - struct dc_context *ctx, - uint32_t inst); - -void dce80_opp_destroy(struct output_pixel_processor **opp); - -struct output_pixel_processor *dce80_opp_create( - struct dc_context *ctx, - uint32_t inst); - -/* REGAMMA RELATED */ -void dce80_opp_power_on_regamma_lut( - struct output_pixel_processor *opp, - bool power_on); - -bool dce80_opp_program_regamma_pwl( - struct output_pixel_processor *opp, - const struct pwl_params *pamras); - -void dce80_opp_set_regamma_mode(struct output_pixel_processor *opp, - enum opp_regamma mode); - -void dce80_opp_set_csc_adjustment( - struct output_pixel_processor *opp, - const struct out_csc_color_matrix *tbl_entry); - -void dce80_opp_set_csc_default( - struct output_pixel_processor *opp, - const struct default_adjustment *default_adjust); - -/* FORMATTER RELATED */ -void dce80_opp_program_bit_depth_reduction( - struct output_pixel_processor *opp, - const struct bit_depth_reduction_params *params); - -void dce80_opp_program_clamping_and_pixel_encoding( - struct output_pixel_processor *opp, - const struct clamping_and_pixel_encoding_params *params); - -void dce80_opp_set_dyn_expansion( - struct output_pixel_processor *opp, - enum dc_color_space color_sp, - enum dc_color_depth color_dpth, - enum signal_type signal); - -#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_csc.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_csc.c deleted file mode 100644 index bdb9e0a77982..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_csc.c +++ /dev/null @@ -1,363 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" - -#include "dce80_opp.h" -#include "basics/conversion.h" - -/* include DCE8 register header files */ -#include "dce/dce_8_0_d.h" -#include "dce/dce_8_0_sh_mask.h" - -#define DCP_REG(reg)\ - (reg + opp80->offsets.dcp_offset) - -enum { - OUTPUT_CSC_MATRIX_SIZE = 12 -}; - -static const struct out_csc_color_matrix global_color_matrix[] = { -{ COLOR_SPACE_SRGB, - { 0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} }, -{ COLOR_SPACE_SRGB_LIMITED, - { 0x1B60, 0, 0, 0x200, 0, 0x1B60, 0, 0x200, 0, 0, 0x1B60, 0x200} }, -{ COLOR_SPACE_YCBCR601, - { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x82F, 0x1012, 0x31F, 0x200, 0xFB47, - 0xF6B9, 0xE00, 0x1000} }, -{ COLOR_SPACE_YCBCR709, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x5D2, 0x1394, 0x1FA, - 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} }, -/* TODO: correct values below */ -{ COLOR_SPACE_YCBCR601_LIMITED, { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x991, - 0x12C9, 0x3A6, 0x200, 0xFB47, 0xF6B9, 0xE00, 0x1000} }, -{ COLOR_SPACE_YCBCR709_LIMITED, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x6CE, 0x16E3, - 0x24F, 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} } -}; - -enum csc_color_mode { - /* 00 - BITS2:0 Bypass */ - CSC_COLOR_MODE_GRAPHICS_BYPASS, - /* 01 - hard coded coefficient TV RGB */ - CSC_COLOR_MODE_GRAPHICS_PREDEFINED, - /* 04 - programmable OUTPUT CSC coefficient */ - CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC, -}; - -static void program_color_matrix( - struct dce80_opp *opp80, - const struct out_csc_color_matrix *tbl_entry, - enum grph_color_adjust_option options) -{ - struct dc_context *ctx = opp80->base.ctx; - { - uint32_t value = 0; - uint32_t addr = DCP_REG(mmOUTPUT_CSC_C11_C12); - /* fixed S2.13 format */ - set_reg_field_value( - value, - tbl_entry->regval[0], - OUTPUT_CSC_C11_C12, - OUTPUT_CSC_C11); - - set_reg_field_value( - value, - tbl_entry->regval[1], - OUTPUT_CSC_C11_C12, - OUTPUT_CSC_C12); - - dm_write_reg(ctx, addr, value); - } - { - uint32_t value = 0; - uint32_t addr = DCP_REG(mmOUTPUT_CSC_C13_C14); - /* fixed S2.13 format */ - set_reg_field_value( - value, - tbl_entry->regval[2], - OUTPUT_CSC_C13_C14, - OUTPUT_CSC_C13); - /* fixed S0.13 format */ - set_reg_field_value( - value, - tbl_entry->regval[3], - OUTPUT_CSC_C13_C14, - OUTPUT_CSC_C14); - - dm_write_reg(ctx, addr, value); - } - { - uint32_t value = 0; - uint32_t addr = DCP_REG(mmOUTPUT_CSC_C21_C22); - /* fixed S2.13 format */ - set_reg_field_value( - value, - tbl_entry->regval[4], - OUTPUT_CSC_C21_C22, - OUTPUT_CSC_C21); - /* fixed S2.13 format */ - set_reg_field_value( - value, - tbl_entry->regval[5], - OUTPUT_CSC_C21_C22, - OUTPUT_CSC_C22); - - dm_write_reg(ctx, addr, value); - } - { - uint32_t value = 0; - uint32_t addr = DCP_REG(mmOUTPUT_CSC_C23_C24); - /* fixed S2.13 format */ - set_reg_field_value( - value, - tbl_entry->regval[6], - OUTPUT_CSC_C23_C24, - OUTPUT_CSC_C23); - /* fixed S0.13 format */ - set_reg_field_value( - value, - tbl_entry->regval[7], - OUTPUT_CSC_C23_C24, - OUTPUT_CSC_C24); - - dm_write_reg(ctx, addr, value); - } - { - uint32_t value = 0; - uint32_t addr = DCP_REG(mmOUTPUT_CSC_C31_C32); - /* fixed S2.13 format */ - set_reg_field_value( - value, - tbl_entry->regval[8], - OUTPUT_CSC_C31_C32, - OUTPUT_CSC_C31); - /* fixed S0.13 format */ - set_reg_field_value( - value, - tbl_entry->regval[9], - OUTPUT_CSC_C31_C32, - OUTPUT_CSC_C32); - - dm_write_reg(ctx, addr, value); - } - { - uint32_t value = 0; - uint32_t addr = DCP_REG(mmOUTPUT_CSC_C33_C34); - /* fixed S2.13 format */ - set_reg_field_value( - value, - tbl_entry->regval[10], - OUTPUT_CSC_C33_C34, - OUTPUT_CSC_C33); - /* fixed S0.13 format */ - set_reg_field_value( - value, - tbl_entry->regval[11], - OUTPUT_CSC_C33_C34, - OUTPUT_CSC_C34); - - dm_write_reg(ctx, addr, value); - } -} - -static bool configure_graphics_mode( - struct dce80_opp *opp80, - enum csc_color_mode config, - enum graphics_csc_adjust_type csc_adjust_type, - enum dc_color_space color_space) -{ - struct dc_context *ctx = opp80->base.ctx; - uint32_t addr = DCP_REG(mmOUTPUT_CSC_CONTROL); - uint32_t value = dm_read_reg(ctx, addr); - - set_reg_field_value( - value, - 0, - OUTPUT_CSC_CONTROL, - OUTPUT_CSC_GRPH_MODE); - - if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_SW) { - if (config == CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC) { - set_reg_field_value( - value, - 4, - OUTPUT_CSC_CONTROL, - OUTPUT_CSC_GRPH_MODE); - } else { - - switch (color_space) { - case COLOR_SPACE_SRGB: - /* by pass */ - set_reg_field_value( - value, - 0, - OUTPUT_CSC_CONTROL, - OUTPUT_CSC_GRPH_MODE); - break; - case COLOR_SPACE_SRGB_LIMITED: - /* TV RGB */ - set_reg_field_value( - value, - 1, - OUTPUT_CSC_CONTROL, - OUTPUT_CSC_GRPH_MODE); - break; - case COLOR_SPACE_YCBCR601: - case COLOR_SPACE_YPBPR601: - case COLOR_SPACE_YCBCR601_LIMITED: - /* YCbCr601 */ - set_reg_field_value( - value, - 2, - OUTPUT_CSC_CONTROL, - OUTPUT_CSC_GRPH_MODE); - break; - case COLOR_SPACE_YCBCR709: - case COLOR_SPACE_YPBPR709: - case COLOR_SPACE_YCBCR709_LIMITED: - /* YCbCr709 */ - set_reg_field_value( - value, - 3, - OUTPUT_CSC_CONTROL, - OUTPUT_CSC_GRPH_MODE); - break; - default: - return false; - } - } - } else if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_HW) { - switch (color_space) { - case COLOR_SPACE_SRGB: - /* by pass */ - set_reg_field_value( - value, - 0, - OUTPUT_CSC_CONTROL, - OUTPUT_CSC_GRPH_MODE); - break; - case COLOR_SPACE_SRGB_LIMITED: - /* TV RGB */ - set_reg_field_value( - value, - 1, - OUTPUT_CSC_CONTROL, - OUTPUT_CSC_GRPH_MODE); - break; - case COLOR_SPACE_YCBCR601: - case COLOR_SPACE_YPBPR601: - case COLOR_SPACE_YCBCR601_LIMITED: - /* YCbCr601 */ - set_reg_field_value( - value, - 2, - OUTPUT_CSC_CONTROL, - OUTPUT_CSC_GRPH_MODE); - break; - case COLOR_SPACE_YCBCR709: - case COLOR_SPACE_YPBPR709: - case COLOR_SPACE_YCBCR709_LIMITED: - /* YCbCr709 */ - set_reg_field_value( - value, - 3, - OUTPUT_CSC_CONTROL, - OUTPUT_CSC_GRPH_MODE); - break; - default: - return false; - } - - } else - /* by pass */ - set_reg_field_value( - value, - 0, - OUTPUT_CSC_CONTROL, - OUTPUT_CSC_GRPH_MODE); - - addr = DCP_REG(mmOUTPUT_CSC_CONTROL); - dm_write_reg(ctx, addr, value); - - return true; -} - -void dce80_opp_set_csc_adjustment( - struct output_pixel_processor *opp, - const struct out_csc_color_matrix *tbl_entry) -{ - struct dce80_opp *opp80 = TO_DCE80_OPP(opp); - enum csc_color_mode config = - CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; - - program_color_matrix(opp80, tbl_entry, GRAPHICS_CSC_ADJUST_TYPE_SW); - - /* We did everything ,now program DxOUTPUT_CSC_CONTROL */ - configure_graphics_mode(opp80, config, GRAPHICS_CSC_ADJUST_TYPE_SW, - tbl_entry->color_space); -} - -void dce80_opp_set_csc_default( - struct output_pixel_processor *opp, - const struct default_adjustment *default_adjust) -{ - struct dce80_opp *opp80 = TO_DCE80_OPP(opp); - enum csc_color_mode config = - CSC_COLOR_MODE_GRAPHICS_PREDEFINED; - - if (default_adjust->force_hw_default == false) { - const struct out_csc_color_matrix *elm; - /* currently parameter not in use */ - enum grph_color_adjust_option option = - GRPH_COLOR_MATRIX_HW_DEFAULT; - uint32_t i; - /* - * HW default false we program locally defined matrix - * HW default true we use predefined hw matrix and we - * do not need to program matrix - * OEM wants the HW default via runtime parameter. - */ - option = GRPH_COLOR_MATRIX_SW; - - for (i = 0; i < ARRAY_SIZE(global_color_matrix); ++i) { - elm = &global_color_matrix[i]; - if (elm->color_space != default_adjust->out_color_space) - continue; - /* program the matrix with default values from this - * file */ - program_color_matrix(opp80, elm, option); - config = CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; - break; - } - } - - /* configure the what we programmed : - * 1. Default values from this file - * 2. Use hardware default from ROM_A and we do not need to program - * matrix */ - - configure_graphics_mode(opp80, config, - default_adjust->csc_adjust_type, - default_adjust->out_color_space); -} diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_formatter.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_formatter.c deleted file mode 100644 index 433296a4ed12..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_formatter.c +++ /dev/null @@ -1,577 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" - -#include "dce/dce_8_0_d.h" -#include "dce/dce_8_0_sh_mask.h" - -#include "dce80_opp.h" - -#define FMT_REG(reg)\ - (reg + opp80->offsets.fmt_offset) - -/** - * set_truncation - * 1) set truncation depth: 0 for 18 bpp or 1 for 24 bpp - * 2) enable truncation - * 3) HW remove 12bit FMT support for DCE8 power saving reason. - */ -static void set_truncation( - struct dce80_opp *opp80, - const struct bit_depth_reduction_params *params) -{ - uint32_t value = 0; - uint32_t addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL); - - /*Disable truncation*/ - value = dm_read_reg(opp80->base.ctx, addr); - set_reg_field_value(value, 0, - FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN); - set_reg_field_value(value, 0, - FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_DEPTH); - set_reg_field_value(value, 0, - FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_MODE); - - dm_write_reg(opp80->base.ctx, addr, value); - - /* no 10bpc trunc on DCE8*/ - if (params->flags.TRUNCATE_ENABLED == 0 || - params->flags.TRUNCATE_DEPTH == 2) - return; - - /*Set truncation depth and Enable truncation*/ - set_reg_field_value(value, 1, - FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN); - set_reg_field_value(value, params->flags.TRUNCATE_MODE, - FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_MODE); - set_reg_field_value(value, params->flags.TRUNCATE_DEPTH, - FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_DEPTH); - - dm_write_reg(opp80->base.ctx, addr, value); - -} - -/** - * set_spatial_dither - * 1) set spatial dithering mode: pattern of seed - * 2) set spatical dithering depth: 0 for 18bpp or 1 for 24bpp - * 3) set random seed - * 4) set random mode - * lfsr is reset every frame or not reset - * RGB dithering method - * 0: RGB data are all dithered with x^28+x^3+1 - * 1: R data is dithered with x^28+x^3+1 - * G data is dithered with x^28+X^9+1 - * B data is dithered with x^28+x^13+1 - * enable high pass filter or not - * 5) enable spatical dithering - */ -static void set_spatial_dither( - struct dce80_opp *opp80, - const struct bit_depth_reduction_params *params) -{ - uint32_t addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL); - uint32_t depth_cntl_value = 0; - uint32_t dither_r_value = 0; - uint32_t dither_g_value = 0; - uint32_t dither_b_value = 0; - - /*Disable spatial (random) dithering*/ - depth_cntl_value = dm_read_reg(opp80->base.ctx, addr); - set_reg_field_value(depth_cntl_value, 0, - FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_EN); - set_reg_field_value(depth_cntl_value, 0, - FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_MODE); - set_reg_field_value(depth_cntl_value, 0, - FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_DEPTH); - set_reg_field_value(depth_cntl_value, 0, - FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_EN); - set_reg_field_value(depth_cntl_value, 0, - FMT_BIT_DEPTH_CONTROL, FMT_HIGHPASS_RANDOM_ENABLE); - set_reg_field_value(depth_cntl_value, 0, - FMT_BIT_DEPTH_CONTROL, FMT_FRAME_RANDOM_ENABLE); - set_reg_field_value(depth_cntl_value, 0, - FMT_BIT_DEPTH_CONTROL, FMT_RGB_RANDOM_ENABLE); - - dm_write_reg(opp80->base.ctx, addr, depth_cntl_value); - - /* no 10bpc on DCE8*/ - if (params->flags.SPATIAL_DITHER_ENABLED == 0 || - params->flags.SPATIAL_DITHER_DEPTH == 2) - return; - - /*Set seed for random values for - * spatial dithering for R,G,B channels*/ - addr = FMT_REG(mmFMT_DITHER_RAND_R_SEED); - set_reg_field_value(dither_r_value, params->r_seed_value, - FMT_DITHER_RAND_R_SEED, - FMT_RAND_R_SEED); - dm_write_reg(opp80->base.ctx, addr, dither_r_value); - - addr = FMT_REG(mmFMT_DITHER_RAND_G_SEED); - set_reg_field_value(dither_g_value, - params->g_seed_value, - FMT_DITHER_RAND_G_SEED, - FMT_RAND_G_SEED); - dm_write_reg(opp80->base.ctx, addr, dither_g_value); - - addr = FMT_REG(mmFMT_DITHER_RAND_B_SEED); - set_reg_field_value(dither_b_value, params->b_seed_value, - FMT_DITHER_RAND_B_SEED, - FMT_RAND_B_SEED); - dm_write_reg(opp80->base.ctx, addr, dither_b_value); - - /* FMT_OFFSET_R_Cr 31:16 0x0 Setting the zero - * offset for the R/Cr channel, lower 4LSB - * is forced to zeros. Typically set to 0 - * RGB and 0x80000 YCbCr. - */ - /* FMT_OFFSET_G_Y 31:16 0x0 Setting the zero - * offset for the G/Y channel, lower 4LSB is - * forced to zeros. Typically set to 0 RGB - * and 0x80000 YCbCr. - */ - /* FMT_OFFSET_B_Cb 31:16 0x0 Setting the zero - * offset for the B/Cb channel, lower 4LSB is - * forced to zeros. Typically set to 0 RGB and - * 0x80000 YCbCr. - */ - - /*Set spatial dithering bit depth*/ - set_reg_field_value(depth_cntl_value, - params->flags.SPATIAL_DITHER_DEPTH, - FMT_BIT_DEPTH_CONTROL, - FMT_SPATIAL_DITHER_DEPTH); - - /* Set spatial dithering mode - * (default is Seed patterrn AAAA...) - */ - set_reg_field_value(depth_cntl_value, - params->flags.SPATIAL_DITHER_MODE, - FMT_BIT_DEPTH_CONTROL, - FMT_SPATIAL_DITHER_MODE); - - /*Reset only at startup*/ - set_reg_field_value(depth_cntl_value, - params->flags.FRAME_RANDOM, - FMT_BIT_DEPTH_CONTROL, - FMT_FRAME_RANDOM_ENABLE); - - /*Set RGB data dithered with x^28+x^3+1*/ - set_reg_field_value(depth_cntl_value, - params->flags.RGB_RANDOM, - FMT_BIT_DEPTH_CONTROL, - FMT_RGB_RANDOM_ENABLE); - - /*Disable High pass filter*/ - set_reg_field_value(depth_cntl_value, - params->flags.HIGHPASS_RANDOM, - FMT_BIT_DEPTH_CONTROL, - FMT_HIGHPASS_RANDOM_ENABLE); - - /*Enable spatial dithering*/ - set_reg_field_value(depth_cntl_value, - 1, - FMT_BIT_DEPTH_CONTROL, - FMT_SPATIAL_DITHER_EN); - - addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL); - dm_write_reg(opp80->base.ctx, addr, depth_cntl_value); - -} - -/** - * SetTemporalDither (Frame Modulation) - * 1) set temporal dither depth - * 2) select pattern: from hard-coded pattern or programmable pattern - * 3) select optimized strips for BGR or RGB LCD sub-pixel - * 4) set s matrix - * 5) set t matrix - * 6) set grey level for 0.25, 0.5, 0.75 - * 7) enable temporal dithering - */ -static void set_temporal_dither( - struct dce80_opp *opp80, - const struct bit_depth_reduction_params *params) -{ - uint32_t addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL); - uint32_t value; - - /*Disable temporal (frame modulation) dithering first*/ - value = dm_read_reg(opp80->base.ctx, addr); - - set_reg_field_value(value, - 0, - FMT_BIT_DEPTH_CONTROL, - FMT_TEMPORAL_DITHER_EN); - - set_reg_field_value(value, - 0, - FMT_BIT_DEPTH_CONTROL, - FMT_TEMPORAL_DITHER_RESET); - set_reg_field_value(value, - 0, - FMT_BIT_DEPTH_CONTROL, - FMT_TEMPORAL_DITHER_OFFSET); - set_reg_field_value(value, - 0, - FMT_BIT_DEPTH_CONTROL, - FMT_TEMPORAL_DITHER_DEPTH); - set_reg_field_value(value, - 0, - FMT_BIT_DEPTH_CONTROL, - FMT_TEMPORAL_LEVEL); - set_reg_field_value(value, - 0, - FMT_BIT_DEPTH_CONTROL, - FMT_25FRC_SEL); - - set_reg_field_value(value, - 0, - FMT_BIT_DEPTH_CONTROL, - FMT_50FRC_SEL); - - set_reg_field_value(value, - 0, - FMT_BIT_DEPTH_CONTROL, - FMT_75FRC_SEL); - - dm_write_reg(opp80->base.ctx, addr, value); - - /* no 10bpc dither on DCE8*/ - if (params->flags.FRAME_MODULATION_ENABLED == 0 || - params->flags.FRAME_MODULATION_DEPTH == 2) - return; - - /* Set temporal dithering depth*/ - set_reg_field_value(value, - params->flags.FRAME_MODULATION_DEPTH, - FMT_BIT_DEPTH_CONTROL, - FMT_TEMPORAL_DITHER_DEPTH); - - set_reg_field_value(value, - 0, - FMT_BIT_DEPTH_CONTROL, - FMT_TEMPORAL_DITHER_RESET); - - set_reg_field_value(value, - 0, - FMT_BIT_DEPTH_CONTROL, - FMT_TEMPORAL_DITHER_OFFSET); - - /*Select legacy pattern based on FRC and Temporal level*/ - addr = FMT_REG(mmFMT_TEMPORAL_DITHER_PATTERN_CONTROL); - dm_write_reg(opp80->base.ctx, addr, 0); - /*Set s matrix*/ - addr = FMT_REG( - mmFMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX); - dm_write_reg(opp80->base.ctx, addr, 0); - /*Set t matrix*/ - addr = FMT_REG( - mmFMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX); - dm_write_reg(opp80->base.ctx, addr, 0); - - /*Select patterns for 0.25, 0.5 and 0.75 grey level*/ - set_reg_field_value(value, - params->flags.TEMPORAL_LEVEL, - FMT_BIT_DEPTH_CONTROL, - FMT_TEMPORAL_LEVEL); - - set_reg_field_value(value, - params->flags.FRC25, - FMT_BIT_DEPTH_CONTROL, - FMT_25FRC_SEL); - - set_reg_field_value(value, - params->flags.FRC50, - FMT_BIT_DEPTH_CONTROL, - FMT_50FRC_SEL); - - set_reg_field_value(value, - params->flags.FRC75, - FMT_BIT_DEPTH_CONTROL, - FMT_75FRC_SEL); - - /*Enable bit reduction by temporal (frame modulation) dithering*/ - set_reg_field_value(value, - 1, - FMT_BIT_DEPTH_CONTROL, - FMT_TEMPORAL_DITHER_EN); - - addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL); - dm_write_reg(opp80->base.ctx, addr, value); - -} - -/** - * Set Clamping - * 1) Set clamping format based on bpc - 0 for 6bpc (No clamping) - * 1 for 8 bpc - * 2 for 10 bpc - * 3 for 12 bpc - * 7 for programable - * 2) Enable clamp if Limited range requested - */ -static void set_clamping( - struct dce80_opp *opp80, - const struct clamping_and_pixel_encoding_params *params) -{ - uint32_t clamp_cntl_value = 0; - uint32_t red_clamp_value = 0; - uint32_t green_clamp_value = 0; - uint32_t blue_clamp_value = 0; - uint32_t addr = FMT_REG(mmFMT_CLAMP_CNTL); - - clamp_cntl_value = dm_read_reg(opp80->base.ctx, addr); - - set_reg_field_value(clamp_cntl_value, - 0, - FMT_CLAMP_CNTL, - FMT_CLAMP_DATA_EN); - - set_reg_field_value(clamp_cntl_value, - 0, - FMT_CLAMP_CNTL, - FMT_CLAMP_COLOR_FORMAT); - - switch (params->clamping_level) { - case CLAMPING_FULL_RANGE: - break; - - case CLAMPING_LIMITED_RANGE_8BPC: - set_reg_field_value(clamp_cntl_value, - 1, - FMT_CLAMP_CNTL, - FMT_CLAMP_DATA_EN); - - set_reg_field_value(clamp_cntl_value, - 1, - FMT_CLAMP_CNTL, - FMT_CLAMP_COLOR_FORMAT); - - break; - - case CLAMPING_LIMITED_RANGE_10BPC: - set_reg_field_value(clamp_cntl_value, - 1, - FMT_CLAMP_CNTL, - FMT_CLAMP_DATA_EN); - - set_reg_field_value(clamp_cntl_value, - 2, - FMT_CLAMP_CNTL, - FMT_CLAMP_COLOR_FORMAT); - - break; - case CLAMPING_LIMITED_RANGE_12BPC: - set_reg_field_value(clamp_cntl_value, - 1, - FMT_CLAMP_CNTL, - FMT_CLAMP_DATA_EN); - - set_reg_field_value(clamp_cntl_value, - 3, - FMT_CLAMP_CNTL, - FMT_CLAMP_COLOR_FORMAT); - - break; - case CLAMPING_LIMITED_RANGE_PROGRAMMABLE: - set_reg_field_value(clamp_cntl_value, - 1, - FMT_CLAMP_CNTL, - FMT_CLAMP_DATA_EN); - - set_reg_field_value(clamp_cntl_value, - 7, - FMT_CLAMP_CNTL, - FMT_CLAMP_COLOR_FORMAT); - - /*set the defaults*/ - set_reg_field_value(red_clamp_value, - 0x10, - FMT_CLAMP_COMPONENT_R, - FMT_CLAMP_LOWER_R); - - set_reg_field_value(red_clamp_value, - 0xFEF, - FMT_CLAMP_COMPONENT_R, - FMT_CLAMP_UPPER_R); - - addr = FMT_REG(mmFMT_CLAMP_COMPONENT_R); - dm_write_reg(opp80->base.ctx, addr, red_clamp_value); - - set_reg_field_value(green_clamp_value, - 0x10, - FMT_CLAMP_COMPONENT_G, - FMT_CLAMP_LOWER_G); - - set_reg_field_value(green_clamp_value, - 0xFEF, - FMT_CLAMP_COMPONENT_G, - FMT_CLAMP_UPPER_G); - - addr = FMT_REG(mmFMT_CLAMP_COMPONENT_G); - dm_write_reg(opp80->base.ctx, addr, green_clamp_value); - - set_reg_field_value(blue_clamp_value, - 0x10, - FMT_CLAMP_COMPONENT_B, - FMT_CLAMP_LOWER_B); - - set_reg_field_value(blue_clamp_value, - 0xFEF, - FMT_CLAMP_COMPONENT_B, - FMT_CLAMP_UPPER_B); - - addr = FMT_REG(mmFMT_CLAMP_COMPONENT_B); - dm_write_reg(opp80->base.ctx, addr, blue_clamp_value); - - break; - - default: - break; - } - - addr = FMT_REG(mmFMT_CLAMP_CNTL); - /*Set clamp control*/ - dm_write_reg(opp80->base.ctx, addr, clamp_cntl_value); - -} - -/** - * set_pixel_encoding - * - * Set Pixel Encoding - * 0: RGB 4:4:4 or YCbCr 4:4:4 or YOnly - * 1: YCbCr 4:2:2 - */ -static void set_pixel_encoding( - struct dce80_opp *opp80, - const struct clamping_and_pixel_encoding_params *params) -{ - uint32_t fmt_cntl_value; - uint32_t addr = FMT_REG(mmFMT_CONTROL); - - /*RGB 4:4:4 or YCbCr 4:4:4 - 0; YCbCr 4:2:2 -1.*/ - fmt_cntl_value = dm_read_reg(opp80->base.ctx, addr); - - set_reg_field_value(fmt_cntl_value, - 0, - FMT_CONTROL, - FMT_PIXEL_ENCODING); - - if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) { - set_reg_field_value(fmt_cntl_value, - 1, - FMT_CONTROL, - FMT_PIXEL_ENCODING); - - /*00 - Pixels drop mode ,01 - Pixels average mode*/ - set_reg_field_value(fmt_cntl_value, - 0, - FMT_CONTROL, - FMT_SUBSAMPLING_MODE); - - /*00 - Cb before Cr ,01 - Cr before Cb*/ - set_reg_field_value(fmt_cntl_value, - 0, - FMT_CONTROL, - FMT_SUBSAMPLING_ORDER); - } - dm_write_reg(opp80->base.ctx, addr, fmt_cntl_value); - -} - -void dce80_opp_program_bit_depth_reduction( - struct output_pixel_processor *opp, - const struct bit_depth_reduction_params *params) -{ - struct dce80_opp *opp80 = TO_DCE80_OPP(opp); - - set_truncation(opp80, params); - set_spatial_dither(opp80, params); - set_temporal_dither(opp80, params); -} - -void dce80_opp_program_clamping_and_pixel_encoding( - struct output_pixel_processor *opp, - const struct clamping_and_pixel_encoding_params *params) -{ - struct dce80_opp *opp80 = TO_DCE80_OPP(opp); - - set_clamping(opp80, params); - set_pixel_encoding(opp80, params); -} - -void dce80_opp_set_dyn_expansion( - struct output_pixel_processor *opp, - enum dc_color_space color_sp, - enum dc_color_depth color_dpth, - enum signal_type signal) -{ - struct dce80_opp *opp80 = TO_DCE80_OPP(opp); - uint32_t value; - bool enable_dyn_exp = false; - uint32_t addr = FMT_REG(mmFMT_DYNAMIC_EXP_CNTL); - - value = dm_read_reg(opp->ctx, addr); - - set_reg_field_value(value, 0, - FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN); - set_reg_field_value(value, 0, - FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE); - - /* From HW programming guide: - FMT_DYNAMIC_EXP_EN = 0 for limited RGB or YCbCr output - FMT_DYNAMIC_EXP_EN = 1 for RGB full range only*/ - if (color_sp == COLOR_SPACE_SRGB) - enable_dyn_exp = true; - - /*00 - 10-bit -> 12-bit dynamic expansion*/ - /*01 - 8-bit -> 12-bit dynamic expansion*/ - if (signal == SIGNAL_TYPE_HDMI_TYPE_A) { - switch (color_dpth) { - case COLOR_DEPTH_888: - set_reg_field_value(value, enable_dyn_exp ? 1:0, - FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN); - set_reg_field_value(value, 1, - FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE); - break; - case COLOR_DEPTH_101010: - set_reg_field_value(value, enable_dyn_exp ? 1:0, - FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN); - set_reg_field_value(value, 0, - FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE); - break; - case COLOR_DEPTH_121212: - break; - default: - break; - } - } - - dm_write_reg(opp->ctx, addr, value); -} diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_regamma.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_regamma.c deleted file mode 100644 index 648e3ef35d91..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_regamma.c +++ /dev/null @@ -1,543 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" - -/* include DCE8 register header files */ -#include "dce/dce_8_0_d.h" -#include "dce/dce_8_0_sh_mask.h" - -#include "dce80_opp.h" -#include "gamma_types.h" - -#define DCP_REG(reg)\ - (reg + opp80->offsets.dcp_offset) - -#define DCFE_REG(reg)\ - (reg + opp80->offsets.crtc_offset) - -enum { - MAX_PWL_ENTRY = 128, - MAX_REGIONS_NUMBER = 16 - -}; - -struct curve_config { - uint32_t offset; - int8_t segments[MAX_REGIONS_NUMBER]; - int8_t begin; -}; - -/* - ***************************************************************************** - * Function: regamma_config_regions_and_segments - * - * build regamma curve by using predefined hw points - * uses interface parameters ,like EDID coeff. - * - * @param : parameters interface parameters - * @return void - * - * @note - * - * @see - * - ***************************************************************************** - */ -static void regamma_config_regions_and_segments( - struct dce80_opp *opp80, const struct pwl_params *params) -{ - const struct gamma_curve *curve; - uint32_t value = 0; - - { - set_reg_field_value( - value, - params->arr_points[0].custom_float_x, - REGAMMA_CNTLA_START_CNTL, - REGAMMA_CNTLA_EXP_REGION_START); - - set_reg_field_value( - value, - 0, - REGAMMA_CNTLA_START_CNTL, - REGAMMA_CNTLA_EXP_REGION_START_SEGMENT); - - dm_write_reg(opp80->base.ctx, - DCP_REG(mmREGAMMA_CNTLA_START_CNTL), - value); - } - { - value = 0; - set_reg_field_value( - value, - params->arr_points[0].custom_float_slope, - REGAMMA_CNTLA_SLOPE_CNTL, - REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE); - - dm_write_reg(opp80->base.ctx, - DCP_REG(mmREGAMMA_CNTLA_SLOPE_CNTL), value); - } - { - value = 0; - set_reg_field_value( - value, - params->arr_points[1].custom_float_x, - REGAMMA_CNTLA_END_CNTL1, - REGAMMA_CNTLA_EXP_REGION_END); - - dm_write_reg(opp80->base.ctx, - DCP_REG(mmREGAMMA_CNTLA_END_CNTL1), value); - } - { - value = 0; - set_reg_field_value( - value, - params->arr_points[2].custom_float_slope, - REGAMMA_CNTLA_END_CNTL2, - REGAMMA_CNTLA_EXP_REGION_END_BASE); - - set_reg_field_value( - value, - params->arr_points[1].custom_float_y, - REGAMMA_CNTLA_END_CNTL2, - REGAMMA_CNTLA_EXP_REGION_END_SLOPE); - - dm_write_reg(opp80->base.ctx, - DCP_REG(mmREGAMMA_CNTLA_END_CNTL2), value); - } - - curve = params->arr_curve_points; - - { - value = 0; - set_reg_field_value( - value, - curve[0].offset, - REGAMMA_CNTLA_REGION_0_1, - REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET); - - set_reg_field_value( - value, - curve[0].segments_num, - REGAMMA_CNTLA_REGION_0_1, - REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS); - - set_reg_field_value( - value, - curve[1].offset, - REGAMMA_CNTLA_REGION_0_1, - REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET); - - set_reg_field_value( - value, - curve[1].segments_num, - REGAMMA_CNTLA_REGION_0_1, - REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS); - - dm_write_reg( - opp80->base.ctx, - DCP_REG(mmREGAMMA_CNTLA_REGION_0_1), - value); - } - - curve += 2; - { - value = 0; - set_reg_field_value( - value, - curve[0].offset, - REGAMMA_CNTLA_REGION_2_3, - REGAMMA_CNTLA_EXP_REGION2_LUT_OFFSET); - - set_reg_field_value( - value, - curve[0].segments_num, - REGAMMA_CNTLA_REGION_2_3, - REGAMMA_CNTLA_EXP_REGION2_NUM_SEGMENTS); - - set_reg_field_value( - value, - curve[1].offset, - REGAMMA_CNTLA_REGION_2_3, - REGAMMA_CNTLA_EXP_REGION3_LUT_OFFSET); - - set_reg_field_value( - value, - curve[1].segments_num, - REGAMMA_CNTLA_REGION_2_3, - REGAMMA_CNTLA_EXP_REGION3_NUM_SEGMENTS); - - dm_write_reg(opp80->base.ctx, - DCP_REG(mmREGAMMA_CNTLA_REGION_2_3), - value); - } - - curve += 2; - { - value = 0; - set_reg_field_value( - value, - curve[0].offset, - REGAMMA_CNTLA_REGION_4_5, - REGAMMA_CNTLA_EXP_REGION4_LUT_OFFSET); - - set_reg_field_value( - value, - curve[0].segments_num, - REGAMMA_CNTLA_REGION_4_5, - REGAMMA_CNTLA_EXP_REGION4_NUM_SEGMENTS); - - set_reg_field_value( - value, - curve[1].offset, - REGAMMA_CNTLA_REGION_4_5, - REGAMMA_CNTLA_EXP_REGION5_LUT_OFFSET); - - set_reg_field_value( - value, - curve[1].segments_num, - REGAMMA_CNTLA_REGION_4_5, - REGAMMA_CNTLA_EXP_REGION5_NUM_SEGMENTS); - - dm_write_reg(opp80->base.ctx, - DCP_REG(mmREGAMMA_CNTLA_REGION_4_5), - value); - } - - curve += 2; - { - value = 0; - set_reg_field_value( - value, - curve[0].offset, - REGAMMA_CNTLA_REGION_6_7, - REGAMMA_CNTLA_EXP_REGION6_LUT_OFFSET); - - set_reg_field_value( - value, - curve[0].segments_num, - REGAMMA_CNTLA_REGION_6_7, - REGAMMA_CNTLA_EXP_REGION6_NUM_SEGMENTS); - - set_reg_field_value( - value, - curve[1].offset, - REGAMMA_CNTLA_REGION_6_7, - REGAMMA_CNTLA_EXP_REGION7_LUT_OFFSET); - - set_reg_field_value( - value, - curve[1].segments_num, - REGAMMA_CNTLA_REGION_6_7, - REGAMMA_CNTLA_EXP_REGION7_NUM_SEGMENTS); - - dm_write_reg(opp80->base.ctx, - DCP_REG(mmREGAMMA_CNTLA_REGION_6_7), - value); - } - - curve += 2; - { - value = 0; - set_reg_field_value( - value, - curve[0].offset, - REGAMMA_CNTLA_REGION_8_9, - REGAMMA_CNTLA_EXP_REGION8_LUT_OFFSET); - - set_reg_field_value( - value, - curve[0].segments_num, - REGAMMA_CNTLA_REGION_8_9, - REGAMMA_CNTLA_EXP_REGION8_NUM_SEGMENTS); - - set_reg_field_value( - value, - curve[1].offset, - REGAMMA_CNTLA_REGION_8_9, - REGAMMA_CNTLA_EXP_REGION9_LUT_OFFSET); - - set_reg_field_value( - value, - curve[1].segments_num, - REGAMMA_CNTLA_REGION_8_9, - REGAMMA_CNTLA_EXP_REGION9_NUM_SEGMENTS); - - dm_write_reg(opp80->base.ctx, - DCP_REG(mmREGAMMA_CNTLA_REGION_8_9), - value); - } - - curve += 2; - { - value = 0; - set_reg_field_value( - value, - curve[0].offset, - REGAMMA_CNTLA_REGION_10_11, - REGAMMA_CNTLA_EXP_REGION10_LUT_OFFSET); - - set_reg_field_value( - value, - curve[0].segments_num, - REGAMMA_CNTLA_REGION_10_11, - REGAMMA_CNTLA_EXP_REGION10_NUM_SEGMENTS); - - set_reg_field_value( - value, - curve[1].offset, - REGAMMA_CNTLA_REGION_10_11, - REGAMMA_CNTLA_EXP_REGION11_LUT_OFFSET); - - set_reg_field_value( - value, - curve[1].segments_num, - REGAMMA_CNTLA_REGION_10_11, - REGAMMA_CNTLA_EXP_REGION11_NUM_SEGMENTS); - - dm_write_reg(opp80->base.ctx, - DCP_REG(mmREGAMMA_CNTLA_REGION_10_11), - value); - } - - curve += 2; - { - value = 0; - set_reg_field_value( - value, - curve[0].offset, - REGAMMA_CNTLA_REGION_12_13, - REGAMMA_CNTLA_EXP_REGION12_LUT_OFFSET); - - set_reg_field_value( - value, - curve[0].segments_num, - REGAMMA_CNTLA_REGION_12_13, - REGAMMA_CNTLA_EXP_REGION12_NUM_SEGMENTS); - - set_reg_field_value( - value, - curve[1].offset, - REGAMMA_CNTLA_REGION_12_13, - REGAMMA_CNTLA_EXP_REGION13_LUT_OFFSET); - - set_reg_field_value( - value, - curve[1].segments_num, - REGAMMA_CNTLA_REGION_12_13, - REGAMMA_CNTLA_EXP_REGION13_NUM_SEGMENTS); - - dm_write_reg(opp80->base.ctx, - DCP_REG(mmREGAMMA_CNTLA_REGION_12_13), - value); - } - - curve += 2; - { - value = 0; - set_reg_field_value( - value, - curve[0].offset, - REGAMMA_CNTLA_REGION_14_15, - REGAMMA_CNTLA_EXP_REGION14_LUT_OFFSET); - - set_reg_field_value( - value, - curve[0].segments_num, - REGAMMA_CNTLA_REGION_14_15, - REGAMMA_CNTLA_EXP_REGION14_NUM_SEGMENTS); - - set_reg_field_value( - value, - curve[1].offset, - REGAMMA_CNTLA_REGION_14_15, - REGAMMA_CNTLA_EXP_REGION15_LUT_OFFSET); - - set_reg_field_value( - value, - curve[1].segments_num, - REGAMMA_CNTLA_REGION_14_15, - REGAMMA_CNTLA_EXP_REGION15_NUM_SEGMENTS); - - dm_write_reg(opp80->base.ctx, - DCP_REG(mmREGAMMA_CNTLA_REGION_14_15), - value); - } -} - -static void program_pwl( - struct dce80_opp *opp80, - const struct pwl_params *params) -{ - uint32_t value; - - { - uint8_t max_tries = 10; - uint8_t counter = 0; - - /* Power on LUT memory */ - value = dm_read_reg(opp80->base.ctx, - DCFE_REG(mmDCFE_MEM_LIGHT_SLEEP_CNTL)); - - set_reg_field_value( - value, - 1, - DCFE_MEM_LIGHT_SLEEP_CNTL, - REGAMMA_LUT_LIGHT_SLEEP_DIS); - - dm_write_reg(opp80->base.ctx, - DCFE_REG(mmDCFE_MEM_LIGHT_SLEEP_CNTL), value); - - while (counter < max_tries) { - value = - dm_read_reg( - opp80->base.ctx, - DCFE_REG(mmDCFE_MEM_LIGHT_SLEEP_CNTL)); - - if (get_reg_field_value( - value, - DCFE_MEM_LIGHT_SLEEP_CNTL, - REGAMMA_LUT_MEM_PWR_STATE) == 0) - break; - - ++counter; - } - - if (counter == max_tries) { - dm_logger_write(opp80->base.ctx->logger, LOG_WARNING, - "%s: regamma lut was not powered on " - "in a timely manner," - " programming still proceeds\n", - __func__); - } - } - - value = 0; - - set_reg_field_value( - value, - 7, - REGAMMA_LUT_WRITE_EN_MASK, - REGAMMA_LUT_WRITE_EN_MASK); - - dm_write_reg(opp80->base.ctx, - DCP_REG(mmREGAMMA_LUT_WRITE_EN_MASK), value); - dm_write_reg(opp80->base.ctx, - DCP_REG(mmREGAMMA_LUT_INDEX), 0); - - /* Program REGAMMA_LUT_DATA */ - { - const uint32_t addr = DCP_REG(mmREGAMMA_LUT_DATA); - - uint32_t i = 0; - - const struct pwl_result_data *rgb = - params->rgb_resulted; - - while (i != params->hw_points_num) { - dm_write_reg(opp80->base.ctx, addr, rgb->red_reg); - dm_write_reg(opp80->base.ctx, addr, rgb->green_reg); - dm_write_reg(opp80->base.ctx, addr, rgb->blue_reg); - - dm_write_reg(opp80->base.ctx, addr, - rgb->delta_red_reg); - dm_write_reg(opp80->base.ctx, addr, - rgb->delta_green_reg); - dm_write_reg(opp80->base.ctx, addr, - rgb->delta_blue_reg); - - ++rgb; - ++i; - } - } - - /* we are done with DCP LUT memory; re-enable low power mode */ - value = dm_read_reg(opp80->base.ctx, - DCFE_REG(mmDCFE_MEM_LIGHT_SLEEP_CNTL)); - - set_reg_field_value( - value, - 0, - DCFE_MEM_LIGHT_SLEEP_CNTL, - REGAMMA_LUT_LIGHT_SLEEP_DIS); - - dm_write_reg(opp80->base.ctx, DCFE_REG(mmDCFE_MEM_LIGHT_SLEEP_CNTL), - value); -} - -void dce80_opp_power_on_regamma_lut( - struct output_pixel_processor *opp, - bool power_on) -{ - struct dce80_opp *opp80 = TO_DCE80_OPP(opp); - - uint32_t value = - dm_read_reg(opp->ctx, DCFE_REG(mmDCFE_MEM_LIGHT_SLEEP_CNTL)); - - set_reg_field_value( - value, - power_on, - DCFE_MEM_LIGHT_SLEEP_CNTL, - REGAMMA_LUT_LIGHT_SLEEP_DIS); - - set_reg_field_value( - value, - power_on, - DCFE_MEM_LIGHT_SLEEP_CNTL, - DCP_LUT_LIGHT_SLEEP_DIS); - - dm_write_reg(opp->ctx, DCFE_REG(mmDCFE_MEM_LIGHT_SLEEP_CNTL), value); -} - -bool dce80_opp_program_regamma_pwl( - struct output_pixel_processor *opp, - const struct pwl_params *params) -{ - - struct dce80_opp *opp80 = TO_DCE80_OPP(opp); - - regamma_config_regions_and_segments(opp80, params); - - program_pwl(opp80, params); - - return true; -} - -void dce80_opp_set_regamma_mode(struct output_pixel_processor *opp, - enum opp_regamma mode) -{ - struct dce80_opp *opp80 = TO_DCE80_OPP(opp); - uint32_t value = dm_read_reg(opp80->base.ctx, - DCP_REG(mmREGAMMA_CONTROL)); - - set_reg_field_value( - value, - mode, - REGAMMA_CONTROL, - GRPH_REGAMMA_MODE); - - dm_write_reg(opp80->base.ctx, DCP_REG(mmREGAMMA_CONTROL), value); -} diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 517d42dfff0c..56a63d985440 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -43,7 +43,7 @@ #include "dce80/dce80_mem_input.h" #include "dce80/dce80_ipp.h" #include "dce/dce_transform.h" -#include "dce80/dce80_opp.h" +#include "dce/dce_opp.h" #include "dce110/dce110_ipp.h" #include "dce/dce_clocks.h" #include "dce/dce_clock_source.h" @@ -317,6 +317,28 @@ static const struct dce_stream_encoder_mask se_mask = { SE_COMMON_MASK_SH_LIST_DCE80_100(_MASK) }; +#define opp_regs(id)\ +[id] = {\ + OPP_DCE_80_REG_LIST(id),\ +} + +static const struct dce_opp_registers opp_regs[] = { + opp_regs(0), + opp_regs(1), + opp_regs(2), + opp_regs(3), + opp_regs(4), + opp_regs(5) +}; + +static const struct dce_opp_shift opp_shift = { + OPP_COMMON_MASK_SH_LIST_DCE_80(__SHIFT) +}; + +static const struct dce_opp_mask opp_mask = { + OPP_COMMON_MASK_SH_LIST_DCE_80(_MASK) +}; + #define audio_regs(id)\ [id] = {\ AUD_COMMON_REG_LIST(id)\ @@ -419,6 +441,25 @@ static struct timing_generator *dce80_timing_generator_create( return NULL; } +static struct output_pixel_processor *dce80_opp_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dce110_opp *opp = + dm_alloc(sizeof(struct dce110_opp)); + + if (!opp) + return NULL; + + if (dce110_opp_construct(opp, + ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask)) + return &opp->base; + + BREAK_TO_DEBUGGER(); + dm_free(opp); + return NULL; +} + static struct stream_encoder *dce80_stream_encoder_create( enum engine_id eng_id, struct dc_context *ctx) @@ -631,7 +672,7 @@ static void destruct(struct dce110_resource_pool *pool) for (i = 0; i < pool->base.pipe_count; i++) { if (pool->base.opps[i] != NULL) - dce80_opp_destroy(&pool->base.opps[i]); + dce110_opp_destroy(&pool->base.opps[i]); if (pool->base.transforms[i] != NULL) dce80_transform_destroy(&pool->base.transforms[i]); -- cgit From 4a69244eb63794cc48ad3653e0f16f2eb096fcd7 Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Fri, 16 Dec 2016 12:12:03 -0500 Subject: drm/amd/display: Fix distribution of segments for PQ For PQ case, redistribution of segments should be done differently for FP16 case in order to handle content above FP16 value of 1.0 Signed-off-by: Anthony Koo Reviewed-by: Aric Cyr Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c | 51 ++++++++++++++++++++-- 1 file changed, 48 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c index 973be8f649cc..729652a3763d 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c @@ -387,6 +387,49 @@ static bool build_hw_curve_configuration( return result; } +static bool setup_distribution_points_pq( + struct gamma_curve *arr_curve_points, + struct curve_points *arr_points, + uint32_t *hw_points_num, + struct hw_x_point *coordinates_x, + enum surface_pixel_format format) +{ + struct curve_config cfg; + + cfg.offset = 0; + cfg.segments[0] = 2; + cfg.segments[1] = 2; + cfg.segments[2] = 2; + cfg.segments[3] = 2; + cfg.segments[4] = 2; + cfg.segments[5] = 2; + cfg.segments[6] = 3; + cfg.segments[7] = 4; + cfg.segments[8] = 4; + cfg.segments[9] = 4; + cfg.segments[10] = 4; + cfg.segments[11] = 5; + cfg.segments[12] = 5; + cfg.segments[13] = 5; + cfg.segments[14] = 5; + cfg.segments[15] = 5; + + if (format == SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F || + format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F) + cfg.begin = -11; + else + cfg.begin = -16; + + if (!build_hw_curve_configuration( + &cfg, arr_curve_points, + arr_points, + coordinates_x, hw_points_num)) { + ASSERT_CRITICAL(false); + return false; + } + return true; +} + static bool setup_distribution_points( struct gamma_curve *arr_curve_points, struct curve_points *arr_points, @@ -1414,15 +1457,17 @@ bool calculate_regamma_params(struct pwl_params *params, scale_gamma(rgb_user, ramp, dividers); - setup_distribution_points(arr_curve_points, arr_points, - ¶ms->hw_points_num, coordinates_x); - if (stream->public.out_transfer_func && stream->public.out_transfer_func->tf == TRANSFER_FUNCTION_PQ) { + setup_distribution_points_pq(arr_curve_points, arr_points, + ¶ms->hw_points_num, coordinates_x, + surface->public.format); build_regamma_curve_pq(rgb_regamma, rgb_oem, coeff128_oem, ramp, surface, params->hw_points_num, coordinates_x, axix_x_256, dividers); } else { + setup_distribution_points(arr_curve_points, arr_points, + ¶ms->hw_points_num, coordinates_x); build_regamma_curve(rgb_regamma, rgb_oem, coeff128_oem, ramp, surface, params->hw_points_num, coordinates_x, axix_x_256, dividers); -- cgit From 538735e9e501056a4370d445bffec4ecb2a59ca4 Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Fri, 16 Dec 2016 12:12:03 -0500 Subject: drm/amd/display: Fix programming of gamma end points Signed-off-by: Anthony Koo Reviewed-by: Anthony Koo Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c | 51 ++++++++++++---------- 1 file changed, 27 insertions(+), 24 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c index 729652a3763d..5cd408dadb20 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c @@ -245,6 +245,8 @@ static bool build_hw_curve_configuration( uint32_t segments = 0; uint32_t max_number; + int8_t num_regions = 0; + bool result = false; if (!number_of_points) { @@ -273,6 +275,7 @@ static bool build_hw_curve_configuration( ASSERT(curve_config->segments[i] >= 0); segments += (1 << curve_config->segments[i]); + ++num_regions; ++i; } @@ -284,12 +287,14 @@ static bool build_hw_curve_configuration( uint32_t offset = 0; int8_t begin = curve_config->begin; int32_t region_number = 0; + struct fixed31_32 magic_number = + dal_fixed31_32_from_fraction(249, 1000); i = begin; while ((index < max_number) && (region_number < max_regions_number) && - (i <= 1)) { + (i < (begin + num_regions))) { int32_t j = 0; segments = curve_config->segments[region_number]; @@ -345,8 +350,7 @@ static bool build_hw_curve_configuration( divisor); points[index].x = region1; - - round_custom_float_6_12(points + index); + points[index].adjusted_x = region1; ++index; ++region_number; @@ -366,9 +370,10 @@ static bool build_hw_curve_configuration( ++i; } - points[index].x = region1; - - round_custom_float_6_12(points + index); + points[index].x = + dal_fixed31_32_add(region1, magic_number); + points[index].adjusted_x = + dal_fixed31_32_add(region1, magic_number); *number_of_points = index; @@ -1215,15 +1220,11 @@ static void rebuild_curve_configuration_magic( const struct hw_x_point *coordinates_x, uint32_t hw_points_num) { - const struct fixed31_32 magic_number = - dal_fixed31_32_from_fraction(249, 1000); - struct fixed31_32 y_r; struct fixed31_32 y_g; struct fixed31_32 y_b; struct fixed31_32 y1_min; - struct fixed31_32 y2_max; struct fixed31_32 y3_max; y_r = rgb_resulted[0].red; @@ -1238,29 +1239,31 @@ static void rebuild_curve_configuration_magic( arr_points[0].y, arr_points[0].x); - arr_points[1].x = dal_fixed31_32_add( - coordinates_x[hw_points_num - 1].adjusted_x, - magic_number); - - arr_points[2].x = arr_points[1].x; - - y_r = rgb_resulted[hw_points_num - 1].red; - y_g = rgb_resulted[hw_points_num - 1].green; - y_b = rgb_resulted[hw_points_num - 1].blue; - - y2_max = dal_fixed31_32_max(y_r, dal_fixed31_32_max(y_g, y_b)); - - arr_points[1].y = y2_max; + /* this should be cleaned up as it's confusing my understanding (KK) is + * that REGAMMA_CNTLA_EXP_REGION_END is the X value for the region end + * REGAMMA_CNTLA_EXP_REGION_END_BASE is Y value for the above X + * REGAMMA_CNTLA_EXP_REGION_END_SLOPE is the slope beyond (X,Y) above + * currently when programming REGION_END = m_arrPoints[1].x, + * REGION_END_BASE = m_arrPoints[1].y, REGION_END_SLOPE=1 + * we don't use m_arrPoints[2] at all after this function, + * and its purpose isn't clear to me + */ + arr_points[1].x = coordinates_x[hw_points_num].adjusted_x; + arr_points[2].x = coordinates_x[hw_points_num].adjusted_x; y_r = rgb_resulted[hw_points_num].red; y_g = rgb_resulted[hw_points_num].green; y_b = rgb_resulted[hw_points_num].blue; + /* see comment above, m_arrPoints[1].y should be the Y value for the + * region end (m_numOfHwPoints), not last HW point(m_numOfHwPoints - 1) + */ y3_max = dal_fixed31_32_max(y_r, dal_fixed31_32_max(y_g, y_b)); + arr_points[1].y = y3_max; arr_points[2].y = y3_max; - arr_points[2].slope = dal_fixed31_32_one; + arr_points[2].slope = dal_fixed31_32_zero; } static bool convert_to_custom_float_format( -- cgit From 1964cb736aaa094379d47aa1dc056a5531cecbd6 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 13 Dec 2016 16:41:05 +1000 Subject: drm/amd/display: remove dc hub - this seems unused. Signed-off-by: Dave Airlie Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 27 ---------------------- drivers/gpu/drm/amd/display/dc/dc.h | 17 -------------- .../drm/amd/display/dc/dce110/dce110_mem_input.c | 1 - .../gpu/drm/amd/display/dc/dce80/dce80_mem_input.c | 1 - drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h | 2 -- 5 files changed, 48 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index df1bae8ea92b..891075e39ecf 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1871,30 +1871,3 @@ const struct dc_stream_status *dc_stream_get_status( return &stream->status; } -bool dc_init_dchub(struct dc *dc, struct dchub_init_data *dh_data) -{ - int i; - struct core_dc *core_dc = DC_TO_CORE(dc); - struct mem_input *mi = NULL; - - for (i = 0; i < core_dc->res_pool->pipe_count; i++) { - if (core_dc->res_pool->mis[i] != NULL) { - mi = core_dc->res_pool->mis[i]; - break; - } - } - if (mi == NULL) { - dm_error("no mem_input!\n"); - return false; - } - - if (mi->funcs->mem_input_update_dchub) - mi->funcs->mem_input_update_dchub(mi, dh_data); - else - ASSERT(mi->funcs->mem_input_update_dchub); - - - return true; - -} - diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index ffea10c73275..f786a17de1fd 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -159,21 +159,6 @@ struct dc { struct dc_debug debug; }; -enum frame_buffer_mode { - FRAME_BUFFER_MODE_LOCAL_ONLY = 0, - FRAME_BUFFER_MODE_ZFB_ONLY, - FRAME_BUFFER_MODE_MIXED_ZFB_AND_LOCAL, -} ; - -struct dchub_init_data { - bool dchub_initialzied; - bool dchub_info_valid; - int64_t zfb_phys_addr_base; - int64_t zfb_mc_base_addr; - uint64_t zfb_size_in_byte; - enum frame_buffer_mode fb_mode; -}; - struct dc_init_data { struct hw_asic_id asic_id; void *driver; /* ctx */ @@ -194,8 +179,6 @@ struct dc *dc_create(const struct dc_init_data *init_params); void dc_destroy(struct dc **dc); -bool dc_init_dchub(struct dc *dc, struct dchub_init_data *dh_data); - /******************************************************************************* * Surface Interfaces ******************************************************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c index a20feaedfca4..1643fb5d4b04 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c @@ -409,7 +409,6 @@ static struct mem_input_funcs dce110_mem_input_funcs = { dce_mem_input_program_surface_config, .mem_input_is_flip_pending = dce110_mem_input_is_flip_pending, - .mem_input_update_dchub = NULL }; /*****************************************/ /* Constructor, Destructor */ diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c index ebb8df3cdf4a..704a7ce62080 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c @@ -54,7 +54,6 @@ static struct mem_input_funcs dce80_mem_input_funcs = { dce_mem_input_program_surface_config, .mem_input_is_flip_pending = dce110_mem_input_is_flip_pending, - .mem_input_update_dchub = NULL }; /*****************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h index 80566c844758..2c0774f95c1c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h @@ -99,8 +99,6 @@ struct mem_input_funcs { bool (*mem_input_is_flip_pending)(struct mem_input *mem_input); - void (*mem_input_update_dchub)(struct mem_input *mem_input, - struct dchub_init_data *dh_data); }; #endif -- cgit From 55b99b4640d4898c140fef7073291918a6e32539 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 13 Dec 2016 16:41:06 +1000 Subject: drm/amd/display: remove some unused wrappers Signed-off-by: Dave Airlie Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c index 9d5125951acd..9c852a36a604 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c @@ -36,10 +36,6 @@ #include "amdgpu_dm_types.h" #include "amdgpu_pm.h" -#define dm_alloc(size) kzalloc(size, GFP_KERNEL) -#define dm_realloc(ptr, size) krealloc(ptr, size, GFP_KERNEL) -#define dm_free(ptr) kfree(ptr) - /****************************************************************************** * IRQ Interfaces. *****************************************************************************/ -- cgit From 2a0998846d2eadabf8c5770f66feb3cb04ad88b5 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 13 Dec 2016 16:41:07 +1000 Subject: drm/amd/display: drop register logger and pid/tgid getters While I'm sure this is useful I think we should bring it back later. It's usage of pid/tgid is incorrect, you have to get/put pid/tgids not store them away. Signed-off-by: Dave Airlie Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_services.c | 10 -- drivers/gpu/drm/amd/display/dc/basics/Makefile | 2 +- .../drm/amd/display/dc/basics/register_logger.c | 197 --------------------- drivers/gpu/drm/amd/display/dc/dm_services.h | 16 -- .../drm/amd/display/include/dal_register_logger.h | 42 ----- 5 files changed, 1 insertion(+), 266 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/dc/basics/register_logger.c delete mode 100644 drivers/gpu/drm/amd/display/include/dal_register_logger.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c index 9c852a36a604..565be0506059 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c @@ -447,13 +447,3 @@ void dal_notify_setmode_complete(struct dc_context *ctx, /*TODO*/ } /* End of calls to notification */ - -long dm_get_pid(void) -{ - return current->pid; -} - -long dm_get_tgid(void) -{ - return current->tgid; -} diff --git a/drivers/gpu/drm/amd/display/dc/basics/Makefile b/drivers/gpu/drm/amd/display/dc/basics/Makefile index a263cadcc0df..065816209da1 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/Makefile +++ b/drivers/gpu/drm/amd/display/dc/basics/Makefile @@ -4,7 +4,7 @@ # subcomponents. BASICS = conversion.o fixpt31_32.o fixpt32_32.o grph_object_id.o \ - logger.o log_helpers.o register_logger.o signal_types.o vector.o + logger.o log_helpers.o signal_types.o vector.o AMD_DAL_BASICS = $(addprefix $(AMDDALPATH)/dc/basics/,$(BASICS)) diff --git a/drivers/gpu/drm/amd/display/dc/basics/register_logger.c b/drivers/gpu/drm/amd/display/dc/basics/register_logger.c deleted file mode 100644 index b8d57d919fe4..000000000000 --- a/drivers/gpu/drm/amd/display/dc/basics/register_logger.c +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" -#include "include/dal_types.h" -#include "include/logger_interface.h" -#include "logger.h" - -/****************************************************************************** - * Register Logger. - * A facility to create register R/W logs. - * Currently used for DAL Test. - *****************************************************************************/ - -/****************************************************************************** - * Private structures - *****************************************************************************/ -struct dal_reg_dump_stack_location { - const char *current_caller_func; - long current_pid; - long current_tgid; - uint32_t rw_count;/* register access counter for current function. */ -}; - -/* This the maximum number of nested calls to the 'reg_dump' facility. */ -#define DAL_REG_DUMP_STACK_MAX_SIZE 32 - -struct dal_reg_dump_stack { - int32_t stack_pointer; - struct dal_reg_dump_stack_location - stack_locations[DAL_REG_DUMP_STACK_MAX_SIZE]; - uint32_t total_rw_count; /* Total count for *all* functions. */ -}; - -static struct dal_reg_dump_stack reg_dump_stack = {0}; - -/****************************************************************************** - * Private functions - *****************************************************************************/ - -/* Check if current process is the one which requested register dump. - * The reason for the check: - * mmCRTC_STATUS_FRAME_COUNT is accessed by dal_controller_get_vblank_counter(). - * Which runs all the time when at least one display is connected. - * (Triggered by drm_mode_page_flip_ioctl()). */ -static bool is_reg_dump_process(void) -{ - uint32_t i; - - /* walk the list of our processes */ - for (i = 0; i < reg_dump_stack.stack_pointer; i++) { - struct dal_reg_dump_stack_location *stack_location - = ®_dump_stack.stack_locations[i]; - - if (stack_location->current_pid == dm_get_pid() - && stack_location->current_tgid == dm_get_tgid()) - return true; - } - - return false; -} - -static bool dal_reg_dump_stack_is_empty(void) -{ - if (reg_dump_stack.stack_pointer <= 0) - return true; - else - return false; -} - -static struct dal_reg_dump_stack_location *dal_reg_dump_stack_push(void) -{ - struct dal_reg_dump_stack_location *current_location = NULL; - - if (reg_dump_stack.stack_pointer >= DAL_REG_DUMP_STACK_MAX_SIZE) { - /* stack is full */ - dm_output_to_console("[REG_DUMP]: %s: stack is full!\n", - __func__); - } else { - current_location = - ®_dump_stack.stack_locations[reg_dump_stack.stack_pointer]; - ++reg_dump_stack.stack_pointer; - } - - return current_location; -} - -static struct dal_reg_dump_stack_location *dal_reg_dump_stack_pop(void) -{ - struct dal_reg_dump_stack_location *current_location = NULL; - - if (dal_reg_dump_stack_is_empty()) { - /* stack is empty */ - dm_output_to_console("[REG_DUMP]: %s: stack is empty!\n", - __func__); - } else { - --reg_dump_stack.stack_pointer; - current_location = - ®_dump_stack.stack_locations[reg_dump_stack.stack_pointer]; - } - - return current_location; -} - -/****************************************************************************** - * Public functions - *****************************************************************************/ - -void dal_reg_logger_push(const char *caller_func) -{ - struct dal_reg_dump_stack_location *free_stack_location; - - free_stack_location = dal_reg_dump_stack_push(); - - if (NULL == free_stack_location) - return; - - memset(free_stack_location, 0, sizeof(*free_stack_location)); - - free_stack_location->current_caller_func = caller_func; - free_stack_location->current_pid = dm_get_pid(); - free_stack_location->current_tgid = dm_get_tgid(); - - dm_output_to_console("[REG_DUMP]:%s - start (pid:%ld, tgid:%ld)\n", - caller_func, - free_stack_location->current_pid, - free_stack_location->current_tgid); -} - -void dal_reg_logger_pop(void) -{ - struct dal_reg_dump_stack_location *top_stack_location; - - top_stack_location = dal_reg_dump_stack_pop(); - - if (NULL == top_stack_location) { - dm_output_to_console("[REG_DUMP]:%s - Stack is Empty!\n", - __func__); - return; - } - - dm_output_to_console( - "[REG_DUMP]:%s - end."\ - " Reg R/W Count: Total=%d Function=%d. (pid:%ld, tgid:%ld)\n", - top_stack_location->current_caller_func, - reg_dump_stack.total_rw_count, - top_stack_location->rw_count, - dm_get_pid(), - dm_get_tgid()); - - memset(top_stack_location, 0, sizeof(*top_stack_location)); -} - -void dal_reg_logger_rw_count_increment(void) -{ - ++reg_dump_stack.total_rw_count; - - ++reg_dump_stack.stack_locations - [reg_dump_stack.stack_pointer - 1].rw_count; -} - -bool dal_reg_logger_should_dump_register(void) -{ - if (true == dal_reg_dump_stack_is_empty()) - return false; - - if (false == is_reg_dump_process()) - return false; - - return true; -} - -/****************************************************************************** - * End of File. - *****************************************************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/dm_services.h b/drivers/gpu/drm/amd/display/dc/dm_services.h index 7a3f10354830..f3f9a401160c 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services.h @@ -109,12 +109,6 @@ static inline uint32_t dm_read_reg_func( value = cgs_read_register(ctx->cgs_device, address); -#if defined(__DAL_REGISTER_LOGGER__) - if (true == dal_reg_logger_should_dump_register()) { - dal_reg_logger_rw_count_increment(); - DRM_INFO("%s DC_READ_REG: 0x%x 0x%x\n", func_name, address, value); - } -#endif return value; } @@ -127,13 +121,6 @@ static inline void dm_write_reg_func( uint32_t value, const char *func_name) { -#if defined(__DAL_REGISTER_LOGGER__) - if (true == dal_reg_logger_should_dump_register()) { - dal_reg_logger_rw_count_increment(); - DRM_INFO("%s DC_WRITE_REG: 0x%x 0x%x\n", func_name, address, value); - } -#endif - if (address == 0) { DC_ERR("invalid register write. address = 0"); return; @@ -418,7 +405,4 @@ bool dm_dmcu_set_pipe(struct dc_context *ctx, unsigned int controller_id); #define dm_log_to_buffer(buffer, size, fmt, args)\ vsnprintf(buffer, size, fmt, args) -long dm_get_pid(void); -long dm_get_tgid(void); - #endif /* __DM_SERVICES_H__ */ diff --git a/drivers/gpu/drm/amd/display/include/dal_register_logger.h b/drivers/gpu/drm/amd/display/include/dal_register_logger.h deleted file mode 100644 index 00dfcd70cc37..000000000000 --- a/drivers/gpu/drm/amd/display/include/dal_register_logger.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DAL_REGISTER_LOGGER__ -#define __DAL_REGISTER_LOGGER__ - -/**************** - * API functions - ***************/ - -/* dal_reg_logger_push - begin Register Logging */ -void dal_reg_logger_push(const char *caller_func); -/* dal_reg_logger_pop - stop Register Logging */ -void dal_reg_logger_pop(void); - -/* for internal use of the Logger only */ -void dal_reg_logger_rw_count_increment(void); -bool dal_reg_logger_should_dump_register(void); - -#endif /* __DAL_REGISTER_LOGGER__ */ -- cgit From e285917063641f00086242d6c927ace9de24c357 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 13 Dec 2016 16:41:08 +1000 Subject: drm/amd/display: drop get platform info Signed-off-by: Dave Airlie Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_services.c | 7 ----- drivers/gpu/drm/amd/display/dc/dm_services.h | 32 ---------------------- 2 files changed, 39 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c index 565be0506059..b842eafdf66c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c @@ -77,13 +77,6 @@ void dal_isr_release_lock(struct dc_context *ctx) * End-of-IRQ Interfaces. *****************************************************************************/ -bool dm_get_platform_info(struct dc_context *ctx, - struct platform_info_params *params) -{ - /*TODO*/ - return false; -} - bool dm_write_persistent_data(struct dc_context *ctx, const struct dc_sink *sink, const char *module_name, diff --git a/drivers/gpu/drm/amd/display/dc/dm_services.h b/drivers/gpu/drm/amd/display/dc/dm_services.h index f3f9a401160c..11a0abfd3418 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services.h @@ -282,38 +282,6 @@ bool dm_pp_get_static_clocks( /****** end of PP interfaces ******/ -enum platform_method { - PM_GET_AVAILABLE_METHODS = 1 << 0, - PM_GET_LID_STATE = 1 << 1, - PM_GET_EXTENDED_BRIGHNESS_CAPS = 1 << 2 -}; - -struct platform_info_params { - enum platform_method method; - void *data; -}; - -struct platform_info_brightness_caps { - uint8_t ac_level_percentage; - uint8_t dc_level_percentage; -}; - -struct platform_info_ext_brightness_caps { - struct platform_info_brightness_caps basic_caps; - struct data_point { - uint8_t luminance; - uint8_t signal_level; - } data_points[99]; - - uint8_t data_points_num; - uint8_t min_input_signal; - uint8_t max_input_signal; -}; - -bool dm_get_platform_info( - struct dc_context *ctx, - struct platform_info_params *params); - struct persistent_data_flag { bool save_per_link; bool save_per_edid; -- cgit From 2c755dae303fa7eecc6400b2dcb544298d1e2e3e Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 13 Dec 2016 16:41:09 +1000 Subject: drm/amd/display: drop setmode complete notifier Signed-off-by: Dave Airlie Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c index b842eafdf66c..5af27aad2dad 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c @@ -427,16 +427,3 @@ bool dm_pp_get_static_clocks( } /**** end of power component interfaces ****/ - -/* Calls to notification */ - -void dal_notify_setmode_complete(struct dc_context *ctx, - uint32_t h_total, - uint32_t v_total, - uint32_t h_active, - uint32_t v_active, - uint32_t pix_clk_in_khz) -{ - /*TODO*/ -} -/* End of calls to notification */ -- cgit From eaca91eea60e5b0732b7e9ab213359d75f36901f Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 19 Dec 2016 14:10:53 -0500 Subject: drm/amd/display: Move dpcd structs into dp_types header Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 1 + drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 1 + drivers/gpu/drm/amd/display/dc/dc.h | 1 - drivers/gpu/drm/amd/display/dc/dc_dp_types.h | 359 +++++++++++++++++++++ drivers/gpu/drm/amd/display/include/dpcd_defs.h | 358 -------------------- .../drm/amd/display/include/link_service_types.h | 1 - 6 files changed, 361 insertions(+), 360 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 47f22d46c0ca..ecfca6204171 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -39,6 +39,7 @@ #include "resource.h" #include "fixed31_32.h" #include "include/asic_capability_interface.h" +#include "dpcd_defs.h" #include "dce/dce_11_0_d.h" #include "dce/dce_11_0_enum.h" diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index e89f5f176ec3..0c5f16cb1d54 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -13,6 +13,7 @@ #include "dm_helpers.h" #include "dce/dce_link_encoder.h" #include "dce/dce_stream_encoder.h" +#include "dpcd_defs.h" enum dc_status core_link_read_dpcd( struct core_link* link, diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index f786a17de1fd..61456f96419e 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -27,7 +27,6 @@ #define DC_INTERFACE_H_ #include "dc_types.h" -#include "dpcd_defs.h" #include "grph_object_defs.h" #include "logger_types.h" #include "gpio_types.h" diff --git a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h index befc4985fe54..1666f10a1e5c 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h @@ -102,4 +102,363 @@ struct dc_link_training_settings { struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]; }; + +union dpcd_rev { + struct { + uint8_t MINOR:4; + uint8_t MAJOR:4; + } bits; + uint8_t raw; +}; + +union max_lane_count { + struct { + uint8_t MAX_LANE_COUNT:5; + uint8_t POST_LT_ADJ_REQ_SUPPORTED:1; + uint8_t TPS3_SUPPORTED:1; + uint8_t ENHANCED_FRAME_CAP:1; + } bits; + uint8_t raw; +}; + +union max_down_spread { + struct { + uint8_t MAX_DOWN_SPREAD:1; + uint8_t RESERVED:5; + uint8_t NO_AUX_HANDSHAKE_LINK_TRAINING:1; + uint8_t TPS4_SUPPORTED:1; + } bits; + uint8_t raw; +}; + +union mstm_cap { + struct { + uint8_t MST_CAP:1; + uint8_t RESERVED:7; + } bits; + uint8_t raw; +}; + +union lane_count_set { + struct { + uint8_t LANE_COUNT_SET:5; + uint8_t POST_LT_ADJ_REQ_GRANTED:1; + uint8_t RESERVED:1; + uint8_t ENHANCED_FRAMING:1; + } bits; + uint8_t raw; +}; + +union lane_status { + struct { + uint8_t CR_DONE_0:1; + uint8_t CHANNEL_EQ_DONE_0:1; + uint8_t SYMBOL_LOCKED_0:1; + uint8_t RESERVED0:1; + uint8_t CR_DONE_1:1; + uint8_t CHANNEL_EQ_DONE_1:1; + uint8_t SYMBOL_LOCKED_1:1; + uint8_t RESERVED_1:1; + } bits; + uint8_t raw; +}; + +union device_service_irq { + struct { + uint8_t REMOTE_CONTROL_CMD_PENDING:1; + uint8_t AUTOMATED_TEST:1; + uint8_t CP_IRQ:1; + uint8_t MCCS_IRQ:1; + uint8_t DOWN_REP_MSG_RDY:1; + uint8_t UP_REQ_MSG_RDY:1; + uint8_t SINK_SPECIFIC:1; + uint8_t reserved:1; + } bits; + uint8_t raw; +}; + +union sink_count { + struct { + uint8_t SINK_COUNT:6; + uint8_t CPREADY:1; + uint8_t RESERVED:1; + } bits; + uint8_t raw; +}; + +union lane_align_status_updated { + struct { + uint8_t INTERLANE_ALIGN_DONE:1; + uint8_t POST_LT_ADJ_REQ_IN_PROGRESS:1; + uint8_t RESERVED:4; + uint8_t DOWNSTREAM_PORT_STATUS_CHANGED:1; + uint8_t LINK_STATUS_UPDATED:1; + } bits; + uint8_t raw; +}; + +union lane_adjust { + struct { + uint8_t VOLTAGE_SWING_LANE:2; + uint8_t PRE_EMPHASIS_LANE:2; + uint8_t RESERVED:4; + } bits; + uint8_t raw; +}; + +union dpcd_training_pattern { + struct { + uint8_t TRAINING_PATTERN_SET:4; + uint8_t RECOVERED_CLOCK_OUT_EN:1; + uint8_t SCRAMBLING_DISABLE:1; + uint8_t SYMBOL_ERROR_COUNT_SEL:2; + } v1_4; + struct { + uint8_t TRAINING_PATTERN_SET:2; + uint8_t LINK_QUAL_PATTERN_SET:2; + uint8_t RESERVED:4; + } v1_3; + uint8_t raw; +}; + +/* Training Lane is used to configure downstream DP device's voltage swing +and pre-emphasis levels*/ +/* The DPCD addresses are from 0x103 to 0x106*/ +union dpcd_training_lane { + struct { + uint8_t VOLTAGE_SWING_SET:2; + uint8_t MAX_SWING_REACHED:1; + uint8_t PRE_EMPHASIS_SET:2; + uint8_t MAX_PRE_EMPHASIS_REACHED:1; + uint8_t RESERVED:2; + } bits; + uint8_t raw; +}; + +/* TMDS-converter related */ +union dwnstream_port_caps_byte0 { + struct { + uint8_t DWN_STRM_PORTX_TYPE:3; + uint8_t DWN_STRM_PORTX_HPD:1; + uint8_t RESERVERD:4; + } bits; + uint8_t raw; +}; + +/* these are the detailed types stored at DWN_STRM_PORTX_CAP (00080h)*/ +enum dpcd_downstream_port_detailed_type { + DOWN_STREAM_DETAILED_DP = 0, + DOWN_STREAM_DETAILED_VGA, + DOWN_STREAM_DETAILED_DVI, + DOWN_STREAM_DETAILED_HDMI, + DOWN_STREAM_DETAILED_NONDDC,/* has no EDID (TV,CV)*/ + DOWN_STREAM_DETAILED_DP_PLUS_PLUS +}; + +union dwnstream_port_caps_byte2 { + struct { + uint8_t MAX_BITS_PER_COLOR_COMPONENT:2; + uint8_t RESERVED:6; + } bits; + uint8_t raw; +}; + +union dp_downstream_port_present { + uint8_t byte; + struct { + uint8_t PORT_PRESENT:1; + uint8_t PORT_TYPE:2; + uint8_t FMT_CONVERSION:1; + uint8_t DETAILED_CAPS:1; + uint8_t RESERVED:3; + } fields; +}; + +union dwnstream_port_caps_byte3_dvi { + struct { + uint8_t RESERVED1:1; + uint8_t DUAL_LINK:1; + uint8_t HIGH_COLOR_DEPTH:1; + uint8_t RESERVED2:5; + } bits; + uint8_t raw; +}; + +union dwnstream_port_caps_byte3_hdmi { + struct { + uint8_t FRAME_SEQ_TO_FRAME_PACK:1; + uint8_t RESERVED:7; + } bits; + uint8_t raw; +}; + +/*4-byte structure for detailed capabilities of a down-stream port +(DP-to-TMDS converter).*/ + +union sink_status { + struct { + uint8_t RX_PORT0_STATUS:1; + uint8_t RX_PORT1_STATUS:1; + uint8_t RESERVED:6; + } bits; + uint8_t raw; +}; + +/*6-byte structure corresponding to 6 registers (200h-205h) +read during handling of HPD-IRQ*/ +union hpd_irq_data { + struct { + union sink_count sink_cnt;/* 200h */ + union device_service_irq device_service_irq;/* 201h */ + union lane_status lane01_status;/* 202h */ + union lane_status lane23_status;/* 203h */ + union lane_align_status_updated lane_status_updated;/* 204h */ + union sink_status sink_status; + } bytes; + uint8_t raw[6]; +}; + +union down_stream_port_count { + struct { + uint8_t DOWN_STR_PORT_COUNT:4; + uint8_t RESERVED:2; /*Bits 5:4 = RESERVED. Read all 0s.*/ + /*Bit 6 = MSA_TIMING_PAR_IGNORED + 0 = Sink device requires the MSA timing parameters + 1 = Sink device is capable of rendering incoming video + stream without MSA timing parameters*/ + uint8_t IGNORE_MSA_TIMING_PARAM:1; + /*Bit 7 = OUI Support + 0 = OUI not supported + 1 = OUI supported + (OUI and Device Identification mandatory for DP 1.2)*/ + uint8_t OUI_SUPPORT:1; + } bits; + uint8_t raw; +}; + +union down_spread_ctrl { + struct { + uint8_t RESERVED1:4;/* Bit 3:0 = RESERVED. Read all 0s*/ + /* Bits 4 = SPREAD_AMP. Spreading amplitude + 0 = Main link signal is not downspread + 1 = Main link signal is downspread <= 0.5% + with frequency in the range of 30kHz ~ 33kHz*/ + uint8_t SPREAD_AMP:1; + uint8_t RESERVED2:2;/*Bit 6:5 = RESERVED. Read all 0s*/ + /*Bit 7 = MSA_TIMING_PAR_IGNORE_EN + 0 = Source device will send valid data for the MSA Timing Params + 1 = Source device may send invalid data for these MSA Timing Params*/ + uint8_t IGNORE_MSA_TIMING_PARAM:1; + } bits; + uint8_t raw; +}; + +union dpcd_edp_config { + struct { + uint8_t PANEL_MODE_EDP:1; + uint8_t FRAMING_CHANGE_ENABLE:1; + uint8_t RESERVED:5; + uint8_t PANEL_SELF_TEST_ENABLE:1; + } bits; + uint8_t raw; +}; + +struct dp_device_vendor_id { + uint8_t ieee_oui[3];/*24-bit IEEE OUI*/ + uint8_t ieee_device_id[6];/*usually 6-byte ASCII name*/ +}; + +struct dp_sink_hw_fw_revision { + uint8_t ieee_hw_rev; + uint8_t ieee_fw_rev[2]; +}; + +/*DPCD register of DP receiver capability field bits-*/ +union edp_configuration_cap { + struct { + uint8_t ALT_SCRAMBLER_RESET:1; + uint8_t FRAMING_CHANGE:1; + uint8_t RESERVED:1; + uint8_t DPCD_DISPLAY_CONTROL_CAPABLE:1; + uint8_t RESERVED2:4; + } bits; + uint8_t raw; +}; + +union training_aux_rd_interval { + struct { + uint8_t TRAINIG_AUX_RD_INTERVAL:7; + uint8_t EXT_RECIEVER_CAP_FIELD_PRESENT:1; + } bits; + uint8_t raw; +}; + +/* Automated test structures */ +union test_request { + struct { + uint8_t LINK_TRAINING :1; + uint8_t LINK_TEST_PATTRN :1; + uint8_t EDID_REAT :1; + uint8_t PHY_TEST_PATTERN :1; + uint8_t AUDIO_TEST_PATTERN :1; + uint8_t RESERVED :1; + uint8_t TEST_STEREO_3D :1; + } bits; + uint8_t raw; +}; + +union test_response { + struct { + uint8_t ACK :1; + uint8_t NO_ACK :1; + uint8_t RESERVED :6; + } bits; + uint8_t raw; +}; + +union phy_test_pattern { + struct { + /* DpcdPhyTestPatterns. This field is 2 bits for DP1.1 + * and 3 bits for DP1.2. + */ + uint8_t PATTERN :3; + /* BY speci, bit7:2 is 0 for DP1.1. */ + uint8_t RESERVED :5; + } bits; + uint8_t raw; +}; + +/* States of Compliance Test Specification (CTS DP1.2). */ +union compliance_test_state { + struct { + unsigned char STEREO_3D_RUNNING : 1; + unsigned char SET_TEST_PATTERN_PENDING : 1; + unsigned char RESERVED : 6; + } bits; + unsigned char raw; +}; + +union link_test_pattern { + struct { + /* dpcd_link_test_patterns */ + unsigned char PATTERN :2; + unsigned char RESERVED:6; + } bits; + unsigned char raw; +}; + +union test_misc { + struct dpcd_test_misc_bits { + unsigned char SYNC_CLOCK :1; + /* dpcd_test_color_format */ + unsigned char CLR_FORMAT :2; + /* dpcd_test_dyn_range */ + unsigned char DYN_RANGE :1; + unsigned char YCBCR :1; + /* dpcd_test_bit_depth */ + unsigned char BPC :3; + } bits; + unsigned char raw; +}; + #endif /* DC_DP_TYPES_H */ diff --git a/drivers/gpu/drm/amd/display/include/dpcd_defs.h b/drivers/gpu/drm/amd/display/include/dpcd_defs.h index fbb2729148df..adfbd3380bd5 100644 --- a/drivers/gpu/drm/amd/display/include/dpcd_defs.h +++ b/drivers/gpu/drm/amd/display/include/dpcd_defs.h @@ -381,362 +381,4 @@ enum dpcd_edp_revision { DPCD_EDP_REVISION_EDP_UNKNOWN = DPCD_EDP_REVISION_EDP_V1_1, }; -union dpcd_rev { - struct { - uint8_t MINOR:4; - uint8_t MAJOR:4; - } bits; - uint8_t raw; -}; - -union max_lane_count { - struct { - uint8_t MAX_LANE_COUNT:5; - uint8_t POST_LT_ADJ_REQ_SUPPORTED:1; - uint8_t TPS3_SUPPORTED:1; - uint8_t ENHANCED_FRAME_CAP:1; - } bits; - uint8_t raw; -}; - -union max_down_spread { - struct { - uint8_t MAX_DOWN_SPREAD:1; - uint8_t RESERVED:5; - uint8_t NO_AUX_HANDSHAKE_LINK_TRAINING:1; - uint8_t TPS4_SUPPORTED:1; - } bits; - uint8_t raw; -}; - -union mstm_cap { - struct { - uint8_t MST_CAP:1; - uint8_t RESERVED:7; - } bits; - uint8_t raw; -}; - -union lane_count_set { - struct { - uint8_t LANE_COUNT_SET:5; - uint8_t POST_LT_ADJ_REQ_GRANTED:1; - uint8_t RESERVED:1; - uint8_t ENHANCED_FRAMING:1; - } bits; - uint8_t raw; -}; - -union lane_status { - struct { - uint8_t CR_DONE_0:1; - uint8_t CHANNEL_EQ_DONE_0:1; - uint8_t SYMBOL_LOCKED_0:1; - uint8_t RESERVED0:1; - uint8_t CR_DONE_1:1; - uint8_t CHANNEL_EQ_DONE_1:1; - uint8_t SYMBOL_LOCKED_1:1; - uint8_t RESERVED_1:1; - } bits; - uint8_t raw; -}; - -union device_service_irq { - struct { - uint8_t REMOTE_CONTROL_CMD_PENDING:1; - uint8_t AUTOMATED_TEST:1; - uint8_t CP_IRQ:1; - uint8_t MCCS_IRQ:1; - uint8_t DOWN_REP_MSG_RDY:1; - uint8_t UP_REQ_MSG_RDY:1; - uint8_t SINK_SPECIFIC:1; - uint8_t reserved:1; - } bits; - uint8_t raw; -}; - -union sink_count { - struct { - uint8_t SINK_COUNT:6; - uint8_t CPREADY:1; - uint8_t RESERVED:1; - } bits; - uint8_t raw; -}; - -union lane_align_status_updated { - struct { - uint8_t INTERLANE_ALIGN_DONE:1; - uint8_t POST_LT_ADJ_REQ_IN_PROGRESS:1; - uint8_t RESERVED:4; - uint8_t DOWNSTREAM_PORT_STATUS_CHANGED:1; - uint8_t LINK_STATUS_UPDATED:1; - } bits; - uint8_t raw; -}; - -union lane_adjust { - struct { - uint8_t VOLTAGE_SWING_LANE:2; - uint8_t PRE_EMPHASIS_LANE:2; - uint8_t RESERVED:4; - } bits; - uint8_t raw; -}; - -union dpcd_training_pattern { - struct { - uint8_t TRAINING_PATTERN_SET:4; - uint8_t RECOVERED_CLOCK_OUT_EN:1; - uint8_t SCRAMBLING_DISABLE:1; - uint8_t SYMBOL_ERROR_COUNT_SEL:2; - } v1_4; - struct { - uint8_t TRAINING_PATTERN_SET:2; - uint8_t LINK_QUAL_PATTERN_SET:2; - uint8_t RESERVED:4; - } v1_3; - uint8_t raw; -}; - -/* Training Lane is used to configure downstream DP device's voltage swing -and pre-emphasis levels*/ -/* The DPCD addresses are from 0x103 to 0x106*/ -union dpcd_training_lane { - struct { - uint8_t VOLTAGE_SWING_SET:2; - uint8_t MAX_SWING_REACHED:1; - uint8_t PRE_EMPHASIS_SET:2; - uint8_t MAX_PRE_EMPHASIS_REACHED:1; - uint8_t RESERVED:2; - } bits; - uint8_t raw; -}; - -/* TMDS-converter related */ -union dwnstream_port_caps_byte0 { - struct { - uint8_t DWN_STRM_PORTX_TYPE:3; - uint8_t DWN_STRM_PORTX_HPD:1; - uint8_t RESERVERD:4; - } bits; - uint8_t raw; -}; - -/* these are the detailed types stored at DWN_STRM_PORTX_CAP (00080h)*/ -enum dpcd_downstream_port_detailed_type { - DOWN_STREAM_DETAILED_DP = 0, - DOWN_STREAM_DETAILED_VGA, - DOWN_STREAM_DETAILED_DVI, - DOWN_STREAM_DETAILED_HDMI, - DOWN_STREAM_DETAILED_NONDDC,/* has no EDID (TV,CV)*/ - DOWN_STREAM_DETAILED_DP_PLUS_PLUS -}; - -union dwnstream_port_caps_byte2 { - struct { - uint8_t MAX_BITS_PER_COLOR_COMPONENT:2; - uint8_t RESERVED:6; - } bits; - uint8_t raw; -}; - -union dp_downstream_port_present { - uint8_t byte; - struct { - uint8_t PORT_PRESENT:1; - uint8_t PORT_TYPE:2; - uint8_t FMT_CONVERSION:1; - uint8_t DETAILED_CAPS:1; - uint8_t RESERVED:3; - } fields; -}; - -union dwnstream_port_caps_byte3_dvi { - struct { - uint8_t RESERVED1:1; - uint8_t DUAL_LINK:1; - uint8_t HIGH_COLOR_DEPTH:1; - uint8_t RESERVED2:5; - } bits; - uint8_t raw; -}; - -union dwnstream_port_caps_byte3_hdmi { - struct { - uint8_t FRAME_SEQ_TO_FRAME_PACK:1; - uint8_t RESERVED:7; - } bits; - uint8_t raw; -}; - -/*4-byte structure for detailed capabilities of a down-stream port -(DP-to-TMDS converter).*/ - -union sink_status { - struct { - uint8_t RX_PORT0_STATUS:1; - uint8_t RX_PORT1_STATUS:1; - uint8_t RESERVED:6; - } bits; - uint8_t raw; -}; - -/*6-byte structure corresponding to 6 registers (200h-205h) -read during handling of HPD-IRQ*/ -union hpd_irq_data { - struct { - union sink_count sink_cnt;/* 200h */ - union device_service_irq device_service_irq;/* 201h */ - union lane_status lane01_status;/* 202h */ - union lane_status lane23_status;/* 203h */ - union lane_align_status_updated lane_status_updated;/* 204h */ - union sink_status sink_status; - } bytes; - uint8_t raw[6]; -}; - -union down_stream_port_count { - struct { - uint8_t DOWN_STR_PORT_COUNT:4; - uint8_t RESERVED:2; /*Bits 5:4 = RESERVED. Read all 0s.*/ - /*Bit 6 = MSA_TIMING_PAR_IGNORED - 0 = Sink device requires the MSA timing parameters - 1 = Sink device is capable of rendering incoming video - stream without MSA timing parameters*/ - uint8_t IGNORE_MSA_TIMING_PARAM:1; - /*Bit 7 = OUI Support - 0 = OUI not supported - 1 = OUI supported - (OUI and Device Identification mandatory for DP 1.2)*/ - uint8_t OUI_SUPPORT:1; - } bits; - uint8_t raw; -}; - -union down_spread_ctrl { - struct { - uint8_t RESERVED1:4;/* Bit 3:0 = RESERVED. Read all 0s*/ - /* Bits 4 = SPREAD_AMP. Spreading amplitude - 0 = Main link signal is not downspread - 1 = Main link signal is downspread <= 0.5% - with frequency in the range of 30kHz ~ 33kHz*/ - uint8_t SPREAD_AMP:1; - uint8_t RESERVED2:2;/*Bit 6:5 = RESERVED. Read all 0s*/ - /*Bit 7 = MSA_TIMING_PAR_IGNORE_EN - 0 = Source device will send valid data for the MSA Timing Params - 1 = Source device may send invalid data for these MSA Timing Params*/ - uint8_t IGNORE_MSA_TIMING_PARAM:1; - } bits; - uint8_t raw; -}; - -union dpcd_edp_config { - struct { - uint8_t PANEL_MODE_EDP:1; - uint8_t FRAMING_CHANGE_ENABLE:1; - uint8_t RESERVED:5; - uint8_t PANEL_SELF_TEST_ENABLE:1; - } bits; - uint8_t raw; -}; - -struct dp_device_vendor_id { - uint8_t ieee_oui[3];/*24-bit IEEE OUI*/ - uint8_t ieee_device_id[6];/*usually 6-byte ASCII name*/ -}; - -struct dp_sink_hw_fw_revision { - uint8_t ieee_hw_rev; - uint8_t ieee_fw_rev[2]; -}; - -/*DPCD register of DP receiver capability field bits-*/ -union edp_configuration_cap { - struct { - uint8_t ALT_SCRAMBLER_RESET:1; - uint8_t FRAMING_CHANGE:1; - uint8_t RESERVED:1; - uint8_t DPCD_DISPLAY_CONTROL_CAPABLE:1; - uint8_t RESERVED2:4; - } bits; - uint8_t raw; -}; - -union training_aux_rd_interval { - struct { - uint8_t TRAINIG_AUX_RD_INTERVAL:7; - uint8_t EXT_RECIEVER_CAP_FIELD_PRESENT:1; - } bits; - uint8_t raw; -}; - -/* Automated test structures */ -union test_request { - struct { - uint8_t LINK_TRAINING :1; - uint8_t LINK_TEST_PATTRN :1; - uint8_t EDID_REAT :1; - uint8_t PHY_TEST_PATTERN :1; - uint8_t AUDIO_TEST_PATTERN :1; - uint8_t RESERVED :1; - uint8_t TEST_STEREO_3D :1; - } bits; - uint8_t raw; -}; - -union test_response { - struct { - uint8_t ACK :1; - uint8_t NO_ACK :1; - uint8_t RESERVED :6; - } bits; - uint8_t raw; -}; - -union phy_test_pattern { - struct { - /* DpcdPhyTestPatterns. This field is 2 bits for DP1.1 - * and 3 bits for DP1.2. - */ - uint8_t PATTERN :3; - /* BY speci, bit7:2 is 0 for DP1.1. */ - uint8_t RESERVED :5; - } bits; - uint8_t raw; -}; - -/* States of Compliance Test Specification (CTS DP1.2). */ -union compliance_test_state { - struct { - unsigned char STEREO_3D_RUNNING : 1; - unsigned char SET_TEST_PATTERN_PENDING : 1; - unsigned char RESERVED : 6; - } bits; - unsigned char raw; -}; - -union link_test_pattern { - struct { - /* dpcd_link_test_patterns */ - unsigned char PATTERN :2; - unsigned char RESERVED:6; - } bits; - unsigned char raw; -}; - -union test_misc { - struct dpcd_test_misc_bits { - unsigned char SYNC_CLOCK :1; - /* dpcd_test_color_format */ - unsigned char CLR_FORMAT :2; - /* dpcd_test_dyn_range */ - unsigned char DYN_RANGE :1; - unsigned char YCBCR :1; - /* dpcd_test_bit_depth */ - unsigned char BPC :3; - } bits; - unsigned char raw; -}; - #endif /* __DAL_DPCD_DEFS_H__ */ diff --git a/drivers/gpu/drm/amd/display/include/link_service_types.h b/drivers/gpu/drm/amd/display/include/link_service_types.h index 06e68426d430..6160a467ba37 100644 --- a/drivers/gpu/drm/amd/display/include/link_service_types.h +++ b/drivers/gpu/drm/amd/display/include/link_service_types.h @@ -27,7 +27,6 @@ #define __DAL_LINK_SERVICE_TYPES_H__ #include "grph_object_id.h" -#include "dpcd_defs.h" #include "dal_types.h" #include "irq_types.h" -- cgit From 3a340294f7e7a784c83f9cd72f49987cc7daaced Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 13 Dec 2016 16:41:11 +1000 Subject: drm/amd/display: port to using drm dpcd defines We only keep one list of these defines in the kernel, so we should use it. Signed-off-by: Dave Airlie Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 8 +- drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 144 ++++++------- drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 2 +- drivers/gpu/drm/amd/display/include/dpcd_defs.h | 223 +-------------------- 5 files changed, 79 insertions(+), 300 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index ecfca6204171..b2fc290b5385 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1158,7 +1158,7 @@ static void dpcd_configure_panel_mode( /*set edp panel mode in receiver*/ core_link_read_dpcd( link, - DPCD_ADDRESS_EDP_CONFIG_SET, + DP_EDP_CONFIGURATION_SET, &edp_config_set.raw, sizeof(edp_config_set.raw)); @@ -1170,7 +1170,7 @@ static void dpcd_configure_panel_mode( panel_mode_edp; result = core_link_write_dpcd( link, - DPCD_ADDRESS_EDP_CONFIG_SET, + DP_EDP_CONFIGURATION_SET, &edp_config_set.raw, sizeof(edp_config_set.raw)); @@ -1191,13 +1191,13 @@ static void enable_stream_features(struct pipe_ctx *pipe_ctx) struct core_link *link = stream->sink->link; union down_spread_ctrl downspread; - core_link_read_dpcd(link, DPCD_ADDRESS_DOWNSPREAD_CNTL, + core_link_read_dpcd(link, DP_DOWNSPREAD_CTRL, &downspread.raw, sizeof(downspread)); downspread.bits.IGNORE_MSA_TIMING_PARAM = (stream->public.ignore_msa_timing_param) ? 1 : 0; - core_link_write_dpcd(link, DPCD_ADDRESS_DOWNSPREAD_CNTL, + core_link_write_dpcd(link, DP_DOWNSPREAD_CTRL, &downspread.raw, sizeof(downspread)); } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c index 6379ccfdb06e..cd66941b2c59 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c @@ -872,7 +872,7 @@ void dal_ddc_service_i2c_query_dp_dual_mode_adaptor( enum { DP_SINK_CAP_SIZE = - DPCD_ADDRESS_EDP_CONFIG_CAP - DPCD_ADDRESS_DPCD_REV + 1 + DP_EDP_CONFIGURATION_CAP - DP_DPCD_REV + 1 }; bool dal_ddc_service_query_ddc_data( 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 2585ec332e58..7238bfe0a068 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 @@ -70,7 +70,7 @@ static void wait_for_training_aux_rd_interval( * "DPCD_ADDR_TRAINING_AUX_RD_INTERVAL" register */ core_link_read_dpcd( link, - DPCD_ADDRESS_TRAINING_AUX_RD_INTERVAL, + DP_TRAINING_AUX_RD_INTERVAL, (uint8_t *)&training_rd_interval, sizeof(training_rd_interval)); @@ -93,14 +93,14 @@ static void dpcd_set_training_pattern( { core_link_write_dpcd( link, - DPCD_ADDRESS_TRAINING_PATTERN_SET, + DP_TRAINING_PATTERN_SET, &dpcd_pattern.raw, 1); dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING, "%s\n %x pattern = %x\n", __func__, - DPCD_ADDRESS_TRAINING_PATTERN_SET, + DP_TRAINING_PATTERN_SET, dpcd_pattern.v1_4.TRAINING_PATTERN_SET); } @@ -129,19 +129,19 @@ static void dpcd_set_link_settings( link_set_buffer[0] = rate; link_set_buffer[1] = lane_count_set.raw; - core_link_write_dpcd(link, DPCD_ADDRESS_LINK_BW_SET, + core_link_write_dpcd(link, DP_LINK_BW_SET, link_set_buffer, 2); - core_link_write_dpcd(link, DPCD_ADDRESS_DOWNSPREAD_CNTL, + core_link_write_dpcd(link, DP_DOWNSPREAD_CTRL, &downspread.raw, sizeof(downspread)); dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING, "%s\n %x rate = %x\n %x lane = %x\n %x spread = %x\n", __func__, - DPCD_ADDRESS_LINK_BW_SET, + DP_LINK_BW_SET, lt_settings->link_settings.link_rate, - DPCD_ADDRESS_LANE_COUNT_SET, + DP_LANE_COUNT_SET, lt_settings->link_settings.lane_count, - DPCD_ADDRESS_DOWNSPREAD_CNTL, + DP_DOWNSPREAD_CTRL, lt_settings->link_settings.link_spread); } @@ -186,7 +186,7 @@ static void dpcd_set_lt_pattern_and_lane_settings( { union dpcd_training_lane dpcd_lane[LANE_COUNT_DP_MAX] = {{{0}}}; const uint32_t dpcd_base_lt_offset = - DPCD_ADDRESS_TRAINING_PATTERN_SET; + DP_TRAINING_PATTERN_SET; uint8_t dpcd_lt_buffer[5] = {0}; union dpcd_training_pattern dpcd_pattern = {{0}}; uint32_t lane; @@ -199,13 +199,13 @@ static void dpcd_set_lt_pattern_and_lane_settings( dpcd_pattern.v1_4.TRAINING_PATTERN_SET = hw_training_pattern_to_dpcd_training_pattern(link, pattern); - dpcd_lt_buffer[DPCD_ADDRESS_TRAINING_PATTERN_SET - dpcd_base_lt_offset] + dpcd_lt_buffer[DP_TRAINING_PATTERN_SET - dpcd_base_lt_offset] = dpcd_pattern.raw; dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING, "%s\n %x pattern = %x\n", __func__, - DPCD_ADDRESS_TRAINING_PATTERN_SET, + DP_TRAINING_PATTERN_SET, dpcd_pattern.v1_4.TRAINING_PATTERN_SET); /***************************************************************** @@ -233,7 +233,7 @@ static void dpcd_set_lt_pattern_and_lane_settings( // 0x00103 - 0x00102 memmove( - &dpcd_lt_buffer[DPCD_ADDRESS_LANE0_SET - dpcd_base_lt_offset], + &dpcd_lt_buffer[DP_TRAINING_LANE0_SET - dpcd_base_lt_offset], dpcd_lane, size_in_bytes); @@ -241,7 +241,7 @@ static void dpcd_set_lt_pattern_and_lane_settings( "%s:\n %x VS set = %x PE set = %x \ max VS Reached = %x max PE Reached = %x\n", __func__, - DPCD_ADDRESS_LANE0_SET, + DP_TRAINING_LANE0_SET, dpcd_lane[0].bits.VOLTAGE_SWING_SET, dpcd_lane[0].bits.PRE_EMPHASIS_SET, dpcd_lane[0].bits.MAX_SWING_REACHED, @@ -253,13 +253,13 @@ static void dpcd_set_lt_pattern_and_lane_settings( */ core_link_write_dpcd( link, - DPCD_ADDRESS_TRAINING_PATTERN_SET, + DP_TRAINING_PATTERN_SET, &dpcd_pattern.raw, sizeof(dpcd_pattern.raw) ); core_link_write_dpcd( link, - DPCD_ADDRESS_LANE0_SET, + DP_TRAINING_LANE0_SET, (uint8_t *)(dpcd_lane), size_in_bytes); @@ -459,7 +459,7 @@ static void get_lane_status_and_drive_settings( core_link_read_dpcd( link, - DPCD_ADDRESS_LANE_01_STATUS, + DP_LANE0_1_STATUS, (uint8_t *)(dpcd_buf), sizeof(dpcd_buf)); @@ -478,15 +478,15 @@ static void get_lane_status_and_drive_settings( dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING, "%s:\n%x Lane01Status = %x\n %x Lane23Status = %x\n ", __func__, - DPCD_ADDRESS_LANE_01_STATUS, dpcd_buf[0], - DPCD_ADDRESS_LANE_23_STATUS, dpcd_buf[1]); + DP_LANE0_1_STATUS, dpcd_buf[0], + DP_LANE2_3_STATUS, dpcd_buf[1]); dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING, "%s:\n %x Lane01AdjustRequest = %x\n %x Lane23AdjustRequest = %x\n", __func__, - DPCD_ADDRESS_ADJUST_REQUEST_LANE0_1, + DP_ADJUST_REQUEST_LANE0_1, dpcd_buf[4], - DPCD_ADDRESS_ADJUST_REQUEST_LANE2_3, + DP_ADJUST_REQUEST_LANE2_3, dpcd_buf[5]); /*copy to req_settings*/ @@ -552,7 +552,7 @@ static void dpcd_set_lane_settings( } core_link_write_dpcd(link, - DPCD_ADDRESS_LANE0_SET, + DP_TRAINING_LANE0_SET, (uint8_t *)(dpcd_lane), link_training_setting->link_settings.lane_count); @@ -579,7 +579,7 @@ static void dpcd_set_lane_settings( "%s\n %x VS set = %x PE set = %x \ max VS Reached = %x max PE Reached = %x\n", __func__, - DPCD_ADDRESS_LANE0_SET, + DP_TRAINING_LANE0_SET, dpcd_lane[0].bits.VOLTAGE_SWING_SET, dpcd_lane[0].bits.PRE_EMPHASIS_SET, dpcd_lane[0].bits.MAX_SWING_REACHED, @@ -935,7 +935,7 @@ static inline bool perform_link_training_int( core_link_write_dpcd( link, - DPCD_ADDRESS_LANE_COUNT_SET, + DP_LANE_COUNT_SET, &lane_count_set.raw, sizeof(lane_count_set)); @@ -1385,18 +1385,18 @@ static bool hpd_rx_irq_check_link_loss_status( */ dpcd_result = core_link_read_dpcd(link, - DPCD_ADDRESS_POWER_STATE, + DP_SET_POWER, &irq_reg_rx_power_state, sizeof(irq_reg_rx_power_state)); if (dpcd_result != DC_OK) { - irq_reg_rx_power_state = DP_PWR_STATE_D0; + irq_reg_rx_power_state = DP_SET_POWER_D0; dm_logger_write(link->ctx->logger, LOG_HW_HPD_IRQ, "%s: DPCD read failed to obtain power state.\n", __func__); } - if (irq_reg_rx_power_state == DP_PWR_STATE_D0) { + if (irq_reg_rx_power_state == DP_SET_POWER_D0) { /*2. Check that Link Status changed, before re-training.*/ @@ -1452,7 +1452,7 @@ static enum dc_status read_hpd_rx_irq_data( */ return core_link_read_dpcd( link, - DPCD_ADDRESS_SINK_COUNT, + DP_SINK_COUNT, irq_data->raw, sizeof(union hpd_irq_data)); } @@ -1536,12 +1536,12 @@ static void dp_test_send_link_training(struct core_link *link) core_link_read_dpcd( link, - DPCD_ADDRESS_TEST_LANE_COUNT, + DP_TEST_LANE_COUNT, (unsigned char *)(&link_settings.lane_count), 1); core_link_read_dpcd( link, - DPCD_ADDRESS_TEST_LINK_RATE, + DP_TEST_LINK_RATE, (unsigned char *)(&link_settings.link_rate), 1); @@ -1558,8 +1558,8 @@ static void dp_test_send_phy_test_pattern(struct core_link *link) union lane_adjust dpcd_lane_adjustment[2]; unsigned char dpcd_post_cursor_2_adjustment = 0; unsigned char test_80_bit_pattern[ - (DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_79_72 - - DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_7_0)+1] = {0}; + (DP_TEST_80BIT_CUSTOM_PATTERN_79_72 - + DP_TEST_80BIT_CUSTOM_PATTERN_7_0)+1] = {0}; enum dp_test_pattern test_pattern; struct dc_link_training_settings link_settings; union lane_adjust dpcd_lane_adjust; @@ -1574,12 +1574,12 @@ static void dp_test_send_phy_test_pattern(struct core_link *link) /* get phy test pattern and pattern parameters from DP receiver */ core_link_read_dpcd( link, - DPCD_ADDRESS_TEST_PHY_PATTERN, + DP_TEST_PHY_PATTERN, &dpcd_test_pattern.raw, sizeof(dpcd_test_pattern)); core_link_read_dpcd( link, - DPCD_ADDRESS_ADJUST_REQUEST_LANE0_1, + DP_ADJUST_REQUEST_LANE0_1, &dpcd_lane_adjustment[0].raw, sizeof(dpcd_lane_adjustment)); @@ -1591,7 +1591,7 @@ static void dp_test_send_phy_test_pattern(struct core_link *link) */ core_link_read_dpcd( link, - DPCD_ADDRESS_ADJUST_REQUEST_POST_CURSOR2, + DP_ADJUST_REQUEST_POST_CURSOR2, &dpcd_post_cursor_2_adjustment, sizeof(dpcd_post_cursor_2_adjustment)); @@ -1620,7 +1620,7 @@ static void dp_test_send_phy_test_pattern(struct core_link *link) if (test_pattern == DP_TEST_PATTERN_80BIT_CUSTOM) core_link_read_dpcd( link, - DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_7_0, + DP_TEST_80BIT_CUSTOM_PATTERN_7_0, test_80_bit_pattern, sizeof(test_80_bit_pattern)); @@ -1660,8 +1660,8 @@ static void dp_test_send_phy_test_pattern(struct core_link *link) test_pattern, &link_training_settings, test_80_bit_pattern, - (DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_79_72 - - DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_7_0)+1); + (DP_TEST_80BIT_CUSTOM_PATTERN_79_72 - + DP_TEST_80BIT_CUSTOM_PATTERN_7_0)+1); } static void dp_test_send_link_test_pattern(struct core_link *link) @@ -1676,12 +1676,12 @@ static void dp_test_send_link_test_pattern(struct core_link *link) /* get link test pattern and pattern parameters */ core_link_read_dpcd( link, - DPCD_ADDRESS_TEST_PATTERN, + DP_TEST_PATTERN, &dpcd_test_pattern.raw, sizeof(dpcd_test_pattern)); core_link_read_dpcd( link, - DPCD_ADDRESS_TEST_MISC1, + DP_TEST_MISC0, &dpcd_test_params.raw, sizeof(dpcd_test_params)); @@ -1721,7 +1721,7 @@ static void handle_automated_test(struct core_link *link) core_link_read_dpcd( link, - DPCD_ADDRESS_TEST_REQUEST, + DP_TEST_REQUEST, &test_request.raw, sizeof(union test_request)); if (test_request.bits.LINK_TRAINING) { @@ -1729,7 +1729,7 @@ static void handle_automated_test(struct core_link *link) test_response.bits.ACK = 1; core_link_write_dpcd( link, - DPCD_ADDRESS_TEST_RESPONSE, + DP_TEST_RESPONSE, &test_response.raw, sizeof(test_response)); dp_test_send_link_training(link); @@ -1754,7 +1754,7 @@ static void handle_automated_test(struct core_link *link) if (test_response.bits.ACK) core_link_write_dpcd( link, - DPCD_ADDRESS_TEST_RESPONSE, + DP_TEST_RESPONSE, &test_response.raw, sizeof(test_response)); } @@ -1792,7 +1792,7 @@ bool dc_link_handle_hpd_rx_irq(const struct dc_link *dc_link) device_service_clear.bits.AUTOMATED_TEST = 1; core_link_write_dpcd( link, - DPCD_ADDRESS_DEVICE_SERVICE_IRQ_VECTOR, + DP_DEVICE_SERVICE_IRQ_VECTOR, &device_service_clear.raw, sizeof(device_service_clear.raw)); device_service_clear.raw = 0; @@ -1872,12 +1872,12 @@ bool is_mst_supported(struct core_link *link) rev.raw = 0; cap.raw = 0; - st = core_link_read_dpcd(link, DPCD_ADDRESS_DPCD_REV, &rev.raw, + st = core_link_read_dpcd(link, DP_DPCD_REV, &rev.raw, sizeof(rev)); if (st == DC_OK && rev.raw >= DPCD_REV_12) { - st = core_link_read_dpcd(link, DPCD_ADDRESS_MSTM_CAP, + st = core_link_read_dpcd(link, DP_MSTM_CAP, &cap.raw, sizeof(cap)); if (st == DC_OK && cap.bits.MST_CAP == 1) mst = true; @@ -1926,7 +1926,7 @@ static void get_active_converter_info( uint8_t det_caps[4]; union dwnstream_port_caps_byte0 *port_caps = (union dwnstream_port_caps_byte0 *)det_caps; - core_link_read_dpcd(link, DPCD_ADDRESS_DWN_STRM_PORT0_CAPS, + core_link_read_dpcd(link, DP_DOWNSTREAM_PORT_0, det_caps, sizeof(det_caps)); switch (port_caps->bits.DWN_STRM_PORTX_TYPE) { @@ -1962,7 +1962,7 @@ static void get_active_converter_info( /* read IEEE branch device id */ core_link_read_dpcd( link, - DPCD_ADDRESS_BRANCH_DEVICE_ID_START, + DP_BRANCH_OUI, (uint8_t *)&dp_id, sizeof(dp_id)); @@ -1982,7 +1982,7 @@ static void get_active_converter_info( core_link_read_dpcd( link, - DPCD_ADDRESS_BRANCH_REVISION_START, + DP_BRANCH_REVISION_START, (uint8_t *)&dp_hw_fw_revision, sizeof(dp_hw_fw_revision)); @@ -2000,16 +2000,16 @@ static void dp_wa_power_up_0010FA(struct core_link *link, uint8_t *dpcd_data, if (!link->dpcd_caps.dpcd_rev.raw) { do { dp_receiver_power_ctrl(link, true); - core_link_read_dpcd(link, DPCD_ADDRESS_DPCD_REV, + core_link_read_dpcd(link, DP_DPCD_REV, dpcd_data, length); link->dpcd_caps.dpcd_rev.raw = dpcd_data[ - DPCD_ADDRESS_DPCD_REV - - DPCD_ADDRESS_DPCD_REV]; + DP_DPCD_REV - + DP_DPCD_REV]; } while (retry++ < 4 && !link->dpcd_caps.dpcd_rev.raw); } - ds_port.byte = dpcd_data[DPCD_ADDRESS_DOWNSTREAM_PORT_PRESENT - - DPCD_ADDRESS_DPCD_REV]; + ds_port.byte = dpcd_data[DP_DOWNSTREAMPORT_PRESENT - + DP_DPCD_REV]; if (link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_VGA_CONVERTER) { switch (link->dpcd_caps.branch_dev_id) { @@ -2037,14 +2037,14 @@ static void retrieve_psr_link_cap(struct core_link *link, { if (edp_revision >= EDP_REVISION_13) { core_link_read_dpcd(link, - DPCD_ADDRESS_PSR_SUPPORT_VER, + DP_PSR_SUPPORT, (uint8_t *)(&link->public.psr_caps), sizeof(link->public.psr_caps)); if (link->public.psr_caps.psr_version != 0) { unsigned char psr_capability = 0; core_link_read_dpcd(link, - DPCD_ADDRESS_PSR_CAPABILITY, + DP_PSR_CAPS, &psr_capability, sizeof(psr_capability)); /* Bit 0 determines whether fast link training is @@ -2064,7 +2064,7 @@ static void retrieve_psr_link_cap(struct core_link *link, static void retrieve_link_cap(struct core_link *link) { - uint8_t dpcd_data[DPCD_ADDRESS_TRAINING_AUX_RD_INTERVAL - DPCD_ADDRESS_DPCD_REV + 1]; + uint8_t dpcd_data[DP_TRAINING_AUX_RD_INTERVAL - DP_DPCD_REV + 1]; union down_stream_port_count down_strm_port_count; union edp_configuration_cap edp_config_cap; @@ -2078,30 +2078,30 @@ static void retrieve_link_cap(struct core_link *link) core_link_read_dpcd( link, - DPCD_ADDRESS_DPCD_REV, + DP_DPCD_REV, dpcd_data, sizeof(dpcd_data)); link->dpcd_caps.dpcd_rev.raw = - dpcd_data[DPCD_ADDRESS_DPCD_REV - DPCD_ADDRESS_DPCD_REV]; + dpcd_data[DP_DPCD_REV - DP_DPCD_REV]; { union training_aux_rd_interval aux_rd_interval; aux_rd_interval.raw = - dpcd_data[DPCD_ADDRESS_TRAINING_AUX_RD_INTERVAL]; + dpcd_data[DP_TRAINING_AUX_RD_INTERVAL]; if (aux_rd_interval.bits.EXT_RECIEVER_CAP_FIELD_PRESENT == 1) { core_link_read_dpcd( link, - DPCD_ADDRESS_DP13_DPCD_REV, + DP_DP13_DPCD_REV, dpcd_data, sizeof(dpcd_data)); } } - ds_port.byte = dpcd_data[DPCD_ADDRESS_DOWNSTREAM_PORT_PRESENT - - DPCD_ADDRESS_DPCD_REV]; + ds_port.byte = dpcd_data[DP_DOWNSTREAMPORT_PRESENT - + DP_DPCD_REV]; get_active_converter_info(ds_port.byte, link); @@ -2111,21 +2111,21 @@ static void retrieve_link_cap(struct core_link *link) down_strm_port_count.bits.IGNORE_MSA_TIMING_PARAM; link->dpcd_caps.max_ln_count.raw = dpcd_data[ - DPCD_ADDRESS_MAX_LANE_COUNT - DPCD_ADDRESS_DPCD_REV]; + DP_MAX_LANE_COUNT - DP_DPCD_REV]; link->dpcd_caps.max_down_spread.raw = dpcd_data[ - DPCD_ADDRESS_MAX_DOWNSPREAD - DPCD_ADDRESS_DPCD_REV]; + DP_MAX_DOWNSPREAD - DP_DPCD_REV]; link->public.reported_link_cap.lane_count = link->dpcd_caps.max_ln_count.bits.MAX_LANE_COUNT; link->public.reported_link_cap.link_rate = dpcd_data[ - DPCD_ADDRESS_MAX_LINK_RATE - DPCD_ADDRESS_DPCD_REV]; + DP_MAX_LINK_RATE - DP_DPCD_REV]; link->public.reported_link_cap.link_spread = link->dpcd_caps.max_down_spread.bits.MAX_DOWN_SPREAD ? LINK_SPREAD_05_DOWNSPREAD_30KHZ : LINK_SPREAD_DISABLED; edp_config_cap.raw = dpcd_data[ - DPCD_ADDRESS_EDP_CONFIG_CAP - DPCD_ADDRESS_DPCD_REV]; + DP_EDP_CONFIGURATION_CAP - DP_DPCD_REV]; link->dpcd_caps.panel_mode_edp = edp_config_cap.bits.ALT_SCRAMBLER_RESET; @@ -2142,7 +2142,7 @@ static void retrieve_link_cap(struct core_link *link) /* read sink count */ core_link_read_dpcd(link, - DPCD_ADDRESS_SINK_COUNT, + DP_SINK_COUNT, &link->dpcd_caps.sink_count.raw, sizeof(link->dpcd_caps.sink_count.raw)); @@ -2151,7 +2151,7 @@ static void retrieve_link_cap(struct core_link *link) if (edp_config_cap.bits.DPCD_DISPLAY_CONTROL_CAPABLE) { /* Read the Panel's eDP revision at DPCD 700h. */ core_link_read_dpcd(link, - DPCD_ADDRESS_EDP_REV, + DP_EDP_DPCD_REV, (uint8_t *)(&link->edp_revision), sizeof(link->edp_revision)); } @@ -2415,7 +2415,7 @@ bool dc_link_dp_set_test_pattern( (unsigned char)(pattern); core_link_write_dpcd(core_link, - DPCD_ADDRESS_LINK_QUAL_LANE0_SET, + DP_LINK_QUAL_LANE0_SET, link_qual_pattern, sizeof(link_qual_pattern)); } else if (core_link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_10 || @@ -2428,12 +2428,12 @@ bool dc_link_dp_set_test_pattern( * setting test pattern for DP 1.1. */ core_link_read_dpcd(core_link, - DPCD_ADDRESS_TRAINING_PATTERN_SET, + DP_TRAINING_PATTERN_SET, &training_pattern.raw, sizeof(training_pattern)); training_pattern.v1_3.LINK_QUAL_PATTERN_SET = pattern; core_link_write_dpcd(core_link, - DPCD_ADDRESS_TRAINING_PATTERN_SET, + DP_TRAINING_PATTERN_SET, &training_pattern.raw, sizeof(training_pattern)); } @@ -2452,7 +2452,7 @@ bool dc_link_dp_set_test_pattern( SET_TEST_PATTERN_PENDING = 0; test_response.bits.ACK = 1; core_link_write_dpcd(core_link, - DPCD_ADDRESS_TEST_RESPONSE, + DP_TEST_RESPONSE, &test_response.raw, sizeof(test_response)); } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 0c5f16cb1d54..4febc8d2a96d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -49,7 +49,7 @@ void dp_receiver_power_ctrl(struct core_link *link, bool on) state = on ? DP_POWER_STATE_D0 : DP_POWER_STATE_D3; - core_link_write_dpcd(link, DPCD_ADDRESS_POWER_STATE, &state, + core_link_write_dpcd(link, DP_SET_POWER, &state, sizeof(state)); } diff --git a/drivers/gpu/drm/amd/display/include/dpcd_defs.h b/drivers/gpu/drm/amd/display/include/dpcd_defs.h index adfbd3380bd5..e6db9cee328a 100644 --- a/drivers/gpu/drm/amd/display/include/dpcd_defs.h +++ b/drivers/gpu/drm/amd/display/include/dpcd_defs.h @@ -26,223 +26,7 @@ #ifndef __DAL_DPCD_DEFS_H__ #define __DAL_DPCD_DEFS_H__ -enum dpcd_address { -/* addresses marked with 1.2 are only defined since DP 1.2 spec */ - - /* Reciever Capability Field */ - DPCD_ADDRESS_DPCD_REV = 0x00000, - DPCD_ADDRESS_MAX_LINK_RATE = 0x00001, - DPCD_ADDRESS_MAX_LANE_COUNT = 0x00002, - DPCD_ADDRESS_MAX_DOWNSPREAD = 0x00003, - DPCD_ADDRESS_NORP = 0x00004, - DPCD_ADDRESS_DOWNSTREAM_PORT_PRESENT = 0x00005, - DPCD_ADDRESS_MAIN_LINK_CHANNEL_CODING = 0x00006, - DPCD_ADDRESS_DOWNSTREAM_PORT_COUNT = 0x00007, - DPCD_ADDRESS_RECEIVE_PORT0_CAP0 = 0x00008, - DPCD_ADDRESS_RECEIVE_PORT0_CAP1 = 0x00009, - DPCD_ADDRESS_RECEIVE_PORT1_CAP0 = 0x0000A, - DPCD_ADDRESS_RECEIVE_PORT1_CAP1 = 0x0000B, - - DPCD_ADDRESS_I2C_SPEED_CNTL_CAP = 0x0000C,/*1.2*/ - DPCD_ADDRESS_EDP_CONFIG_CAP = 0x0000D,/*1.2*/ - DPCD_ADDRESS_TRAINING_AUX_RD_INTERVAL = 0x000E,/*1.2*/ - - DPCD_ADDRESS_MSTM_CAP = 0x00021,/*1.2*/ - - /* Audio Video Sync Data Feild */ - DPCD_ADDRESS_AV_GRANULARITY = 0x0023, - DPCD_ADDRESS_AUDIO_DECODE_LATENCY1 = 0x0024, - DPCD_ADDRESS_AUDIO_DECODE_LATENCY2 = 0x0025, - DPCD_ADDRESS_AUDIO_POSTPROCESSING_LATENCY1 = 0x0026, - DPCD_ADDRESS_AUDIO_POSTPROCESSING_LATENCY2 = 0x0027, - DPCD_ADDRESS_VIDEO_INTERLACED_LATENCY = 0x0028, - DPCD_ADDRESS_VIDEO_PROGRESSIVE_LATENCY = 0x0029, - DPCD_ADDRESS_AUDIO_DELAY_INSERT1 = 0x0002B, - DPCD_ADDRESS_AUDIO_DELAY_INSERT2 = 0x0002C, - DPCD_ADDRESS_AUDIO_DELAY_INSERT3 = 0x0002D, - - /* Audio capability */ - DPCD_ADDRESS_NUM_OF_AUDIO_ENDPOINTS = 0x00022, - - DPCD_ADDRESS_GUID_START = 0x00030,/*1.2*/ - DPCD_ADDRESS_GUID_END = 0x0003f,/*1.2*/ - - DPCD_ADDRESS_PSR_SUPPORT_VER = 0x00070, - DPCD_ADDRESS_PSR_CAPABILITY = 0x00071, - - DPCD_ADDRESS_DWN_STRM_PORT0_CAPS = 0x00080,/*1.2a*/ - - /* Link Configuration Field */ - DPCD_ADDRESS_LINK_BW_SET = 0x00100, - DPCD_ADDRESS_LANE_COUNT_SET = 0x00101, - DPCD_ADDRESS_TRAINING_PATTERN_SET = 0x00102, - DPCD_ADDRESS_LANE0_SET = 0x00103, - DPCD_ADDRESS_LANE1_SET = 0x00104, - DPCD_ADDRESS_LANE2_SET = 0x00105, - DPCD_ADDRESS_LANE3_SET = 0x00106, - DPCD_ADDRESS_DOWNSPREAD_CNTL = 0x00107, - DPCD_ADDRESS_I2C_SPEED_CNTL = 0x00109,/*1.2*/ - - DPCD_ADDRESS_EDP_CONFIG_SET = 0x0010A, - DPCD_ADDRESS_LINK_QUAL_LANE0_SET = 0x0010B, - DPCD_ADDRESS_LINK_QUAL_LANE1_SET = 0x0010C, - DPCD_ADDRESS_LINK_QUAL_LANE2_SET = 0x0010D, - DPCD_ADDRESS_LINK_QUAL_LANE3_SET = 0x0010E, - - DPCD_ADDRESS_LANE0_SET2 = 0x0010F,/*1.2*/ - DPCD_ADDRESS_LANE2_SET2 = 0x00110,/*1.2*/ - - DPCD_ADDRESS_MSTM_CNTL = 0x00111,/*1.2*/ - - DPCD_ADDRESS_PSR_ENABLE_CFG = 0x0170, - - /* Payload Table Configuration Field 1.2 */ - DPCD_ADDRESS_PAYLOAD_ALLOCATE_SET = 0x001C0, - DPCD_ADDRESS_PAYLOAD_ALLOCATE_START_TIMESLOT = 0x001C1, - DPCD_ADDRESS_PAYLOAD_ALLOCATE_TIMESLOT_COUNT = 0x001C2, - - DPCD_ADDRESS_SINK_COUNT = 0x0200, - DPCD_ADDRESS_DEVICE_SERVICE_IRQ_VECTOR = 0x0201, - - /* Link / Sink Status Field */ - DPCD_ADDRESS_LANE_01_STATUS = 0x00202, - DPCD_ADDRESS_LANE_23_STATUS = 0x00203, - DPCD_ADDRESS_LANE_ALIGN_STATUS_UPDATED = 0x0204, - DPCD_ADDRESS_SINK_STATUS = 0x0205, - - /* Adjust Request Field */ - DPCD_ADDRESS_ADJUST_REQUEST_LANE0_1 = 0x0206, - DPCD_ADDRESS_ADJUST_REQUEST_LANE2_3 = 0x0207, - DPCD_ADDRESS_ADJUST_REQUEST_POST_CURSOR2 = 0x020C, - - /* Test Request Field */ - DPCD_ADDRESS_TEST_REQUEST = 0x0218, - DPCD_ADDRESS_TEST_LINK_RATE = 0x0219, - DPCD_ADDRESS_TEST_LANE_COUNT = 0x0220, - DPCD_ADDRESS_TEST_PATTERN = 0x0221, - DPCD_ADDRESS_TEST_MISC1 = 0x0232, - - /* Phy Test Pattern Field */ - DPCD_ADDRESS_TEST_PHY_PATTERN = 0x0248, - DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_7_0 = 0x0250, - DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_15_8 = 0x0251, - DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_23_16 = 0x0252, - DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_31_24 = 0x0253, - DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_39_32 = 0x0254, - DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_47_40 = 0x0255, - DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_55_48 = 0x0256, - DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_63_56 = 0x0257, - DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_71_64 = 0x0258, - DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_79_72 = 0x0259, - - /* Test Response Field*/ - DPCD_ADDRESS_TEST_RESPONSE = 0x0260, - - /* Audio Test Pattern Field 1.2*/ - DPCD_ADDRESS_TEST_AUDIO_MODE = 0x0271, - DPCD_ADDRESS_TEST_AUDIO_PATTERN_TYPE = 0x0272, - DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_1 = 0x0273, - DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_2 = 0x0274, - DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_3 = 0x0275, - DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_4 = 0x0276, - DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_5 = 0x0277, - DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_6 = 0x0278, - DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_7 = 0x0279, - DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_8 = 0x027A, - - /* Payload Table Status Field */ - DPCD_ADDRESS_PAYLOAD_TABLE_UPDATE_STATUS = 0x002C0,/*1.2*/ - DPCD_ADDRESS_VC_PAYLOAD_ID_SLOT1 = 0x002C1,/*1.2*/ - DPCD_ADDRESS_VC_PAYLOAD_ID_SLOT63 = 0x002FF,/*1.2*/ - - /* Source Device Specific Field */ - DPCD_ADDRESS_SOURCE_DEVICE_ID_START = 0x0300, - DPCD_ADDRESS_SOURCE_DEVICE_ID_END = 0x0301, - DPCD_ADDRESS_AMD_INTERNAL_DEBUG_START = 0x030C, - DPCD_ADDRESS_AMD_INTERNAL_DEBUG_END = 0x030F, - DPCD_ADDRESS_SOURCE_SPECIFIC_TABLE_START = 0x0310, - DPCD_ADDRESS_SOURCE_SPECIFIC_TABLE_END = 0x037F, - DPCD_ADDRESS_SOURCE_RESERVED_START = 0x0380, - DPCD_ADDRESS_SOURCE_RESERVED_END = 0x03FF, - - /* Sink Device Specific Field */ - DPCD_ADDRESS_SINK_DEVICE_ID_START = 0x0400, - DPCD_ADDRESS_SINK_DEVICE_ID_END = 0x0402, - DPCD_ADDRESS_SINK_DEVICE_STR_START = 0x0403, - DPCD_ADDRESS_SINK_DEVICE_STR_END = 0x0408, - DPCD_ADDRESS_SINK_REVISION_START = 0x409, - DPCD_ADDRESS_SINK_REVISION_END = 0x40B, - - /* Branch Device Specific Field */ - DPCD_ADDRESS_BRANCH_DEVICE_ID_START = 0x0500, - DPCD_ADDRESS_BRANCH_DEVICE_ID_END = 0x0502, - DPCD_ADDRESS_BRANCH_DEVICE_STR_START = 0x0503, - DPCD_ADDRESS_BRANCH_DEVICE_STR_END = 0x0508, - DPCD_ADDRESS_BRANCH_REVISION_START = 0x0509, - DPCD_ADDRESS_BRANCH_REVISION_END = 0x050B, - - DPCD_ADDRESS_POWER_STATE = 0x0600, - - /* EDP related */ - DPCD_ADDRESS_EDP_REV = 0x0700, - DPCD_ADDRESS_EDP_CAPABILITY = 0x0701, - DPCD_ADDRESS_EDP_BACKLIGHT_ADJUST_CAP = 0x0702, - DPCD_ADDRESS_EDP_GENERAL_CAP2 = 0x0703, - - DPCD_ADDRESS_EDP_DISPLAY_CONTROL = 0x0720, - DPCD_ADDRESS_SUPPORTED_LINK_RATES = 0x00010, /* edp 1.4 */ - DPCD_ADDRESS_EDP_BACKLIGHT_SET = 0x0721, - DPCD_ADDRESS_EDP_BACKLIGHT_BRIGHTNESS_MSB = 0x0722, - DPCD_ADDRESS_EDP_BACKLIGHT_BRIGHTNESS_LSB = 0x0723, - DPCD_ADDRESS_EDP_PWMGEN_BIT_COUNT = 0x0724, - DPCD_ADDRESS_EDP_PWMGEN_BIT_COUNT_CAP_MIN = 0x0725, - DPCD_ADDRESS_EDP_PWMGEN_BIT_COUNT_CAP_MAX = 0x0726, - DPCD_ADDRESS_EDP_BACKLIGHT_CONTROL_STATUS = 0x0727, - DPCD_ADDRESS_EDP_BACKLIGHT_FREQ_SET = 0x0728, - DPCD_ADDRESS_EDP_REVERVED = 0x0729, - DPCD_ADDRESS_EDP_BACKLIGNT_FREQ_CAP_MIN_MSB = 0x072A, - DPCD_ADDRESS_EDP_BACKLIGNT_FREQ_CAP_MIN_MID = 0x072B, - DPCD_ADDRESS_EDP_BACKLIGNT_FREQ_CAP_MIN_LSB = 0x072C, - DPCD_ADDRESS_EDP_BACKLIGNT_FREQ_CAP_MAX_MSB = 0x072D, - DPCD_ADDRESS_EDP_BACKLIGNT_FREQ_CAP_MAX_MID = 0x072E, - DPCD_ADDRESS_EDP_BACKLIGNT_FREQ_CAP_MAX_LSB = 0x072F, - - DPCD_ADDRESS_EDP_DBC_MINIMUM_BRIGHTNESS_SET = 0x0732, - DPCD_ADDRESS_EDP_DBC_MAXIMUM_BRIGHTNESS_SET = 0x0733, - - /* Sideband MSG Buffers 1.2 */ - DPCD_ADDRESS_DOWN_REQ_START = 0x01000, - DPCD_ADDRESS_DOWN_REQ_END = 0x011ff, - - DPCD_ADDRESS_UP_REP_START = 0x01200, - DPCD_ADDRESS_UP_REP_END = 0x013ff, - - DPCD_ADDRESS_DOWN_REP_START = 0x01400, - DPCD_ADDRESS_DOWN_REP_END = 0x015ff, - - DPCD_ADDRESS_UP_REQ_START = 0x01600, - DPCD_ADDRESS_UP_REQ_END = 0x017ff, - - /* ESI (Event Status Indicator) Field 1.2 */ - DPCD_ADDRESS_SINK_COUNT_ESI = 0x02002, - DPCD_ADDRESS_DEVICE_IRQ_ESI0 = 0x02003, - DPCD_ADDRESS_DEVICE_IRQ_ESI1 = 0x02004, - /*@todo move dpcd_address_Lane01Status back here*/ - - DPCD_ADDRESS_PSR_ERROR_STATUS = 0x2006, - DPCD_ADDRESS_PSR_EVENT_STATUS = 0x2007, - DPCD_ADDRESS_PSR_SINK_STATUS = 0x2008, - DPCD_ADDRESS_PSR_DBG_REGISTER0 = 0x2009, - DPCD_ADDRESS_PSR_DBG_REGISTER1 = 0x200A, - - DPCD_ADDRESS_DP13_DPCD_REV = 0x2200, - DPCD_ADDRESS_DP13_MAX_LINK_RATE = 0x2201, - - /* Travis specific addresses */ - DPCD_ADDRESS_TRAVIS_SINK_DEV_SEL = 0x5f0, - DPCD_ADDRESS_TRAVIS_SINK_ACCESS_OFFSET = 0x5f1, - DPCD_ADDRESS_TRAVIS_SINK_ACCESS_REG = 0x5f2, -}; +#include enum dpcd_revision { DPCD_REV_10 = 0x10, @@ -252,11 +36,6 @@ enum dpcd_revision { DPCD_REV_14 = 0x14 }; -enum dp_pwr_state { - DP_PWR_STATE_D0 = 1,/* direct HW translation! */ - DP_PWR_STATE_D3 -}; - /* these are the types stored at DOWNSTREAMPORT_PRESENT */ enum dpcd_downstream_port_type { DOWNSTREAM_DP = 0, -- cgit From b39474ef0925a748d0dd43521fc1192777afd329 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 13 Dec 2016 16:41:12 +1000 Subject: drm/amd/display: assign correct enum for edp revision There are 2 edp enum revisions, no idea why, drop one, and just assign 1.1 to the default value. Signed-off-by: Dave Airlie Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 2 +- drivers/gpu/drm/amd/display/include/dpcd_defs.h | 16 ---------------- 2 files changed, 1 insertion(+), 17 deletions(-) (limited to 'drivers/gpu') 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 7238bfe0a068..d32bf61b66e9 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 @@ -2129,7 +2129,7 @@ static void retrieve_link_cap(struct core_link *link) link->dpcd_caps.panel_mode_edp = edp_config_cap.bits.ALT_SCRAMBLER_RESET; - link->edp_revision = DPCD_EDP_REVISION_EDP_UNKNOWN; + link->edp_revision = EDP_REVISION_11; link->public.test_pattern_enabled = false; link->public.compliance_test_state.raw = 0; diff --git a/drivers/gpu/drm/amd/display/include/dpcd_defs.h b/drivers/gpu/drm/amd/display/include/dpcd_defs.h index e6db9cee328a..ea8f5867e834 100644 --- a/drivers/gpu/drm/amd/display/include/dpcd_defs.h +++ b/drivers/gpu/drm/amd/display/include/dpcd_defs.h @@ -144,20 +144,4 @@ enum dpcd_psr_sink_states { PSR_SINK_STATE_SINK_INTERNAL_ERROR = 7, }; -/* This enum defines the Panel's eDP revision at DPCD 700h - * 00h = eDP v1.1 or lower - * 01h = eDP v1.2 - * 02h = eDP v1.3 (PSR support starts here) - * 03h = eDP v1.4 - * If unknown revision, treat as eDP v1.1, meaning least functionality set. - * This enum has values matched to eDP spec, thus values should not change. - */ -enum dpcd_edp_revision { - DPCD_EDP_REVISION_EDP_V1_1 = 0, - DPCD_EDP_REVISION_EDP_V1_2 = 1, - DPCD_EDP_REVISION_EDP_V1_3 = 2, - DPCD_EDP_REVISION_EDP_V1_4 = 3, - DPCD_EDP_REVISION_EDP_UNKNOWN = DPCD_EDP_REVISION_EDP_V1_1, -}; - #endif /* __DAL_DPCD_DEFS_H__ */ -- cgit From 5ce0183cdd00d9c9e57405fa5a06d2a97b747aeb Mon Sep 17 00:00:00 2001 From: Amy Zhang Date: Mon, 12 Dec 2016 16:57:40 -0500 Subject: drm/amd/display: Framework for degamma and regramma through color module Signed-off-by: Amy Zhang Reviewed-by: Aric Cyr Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/modules/color/color.c | 575 +++++++++++++++++---- .../drm/amd/display/modules/color/color_helper.h | 2 +- .../gpu/drm/amd/display/modules/inc/mod_color.h | 115 ++++- 3 files changed, 598 insertions(+), 94 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/modules/color/color.c b/drivers/gpu/drm/amd/display/modules/color/color.c index 6613ff9f4d28..938867282d04 100644 --- a/drivers/gpu/drm/amd/display/modules/color/color.c +++ b/drivers/gpu/drm/amd/display/modules/color/color.c @@ -63,14 +63,18 @@ struct gamut_src_dst_matrix { struct color_state { bool user_enable_color_temperature; int custom_color_temperature; - struct color_space_coordinates source_gamut; - struct color_space_coordinates destination_gamut; struct color_range contrast; struct color_range saturation; struct color_range brightness; struct color_range hue; struct dc_gamma *gamma; enum dc_quantization_range preferred_quantization_range; + + struct color_gamut_data source_gamut; + struct color_gamut_data destination_gamut; + enum color_transfer_func input_transfer_function; + enum color_transfer_func output_transfer_function; + struct color_mastering_info mastering_info; }; struct core_color { @@ -79,6 +83,7 @@ struct core_color { int num_sinks; struct sink_caps *caps; struct color_state *state; + struct color_edid_caps *edid_caps; }; #define MOD_COLOR_TO_CORE(mod_color)\ @@ -1286,6 +1291,142 @@ static struct dc_surface *dc_stream_to_surface_from_pipe_ctx( return out_surface; } +static enum predefined_gamut_type color_space_to_predefined_gamut_types(enum + color_color_space color_space) +{ + switch (color_space) { + case color_space_bt709: + case color_space_xv_ycc_bt709: + return gamut_type_bt709; + case color_space_bt601: + case color_space_xv_ycc_bt601: + return gamut_type_bt601; + case color_space_adobe: + return gamut_type_adobe_rgb; + case color_space_srgb: + case color_space_sc_rgb_ms_ref: + return gamut_type_srgb; + case color_space_bt2020: + return gamut_type_bt2020; + case color_space_dci_p3: /* TODO */ + default: + return gamut_type_unknown; + } +} + +static enum predefined_white_point_type white_point_to_predefined_white_point + (enum color_white_point_type white_point) +{ + switch (white_point) { + case color_white_point_type_5000k_horizon: + return white_point_type_5000k_horizon; + case color_white_point_type_6500k_noon: + return white_point_type_6500k_noon; + case color_white_point_type_7500k_north_sky: + return white_point_type_7500k_north_sky; + case color_white_point_type_9300k: + return white_point_type_9300k; + default: + return white_point_type_unknown; + } +} + +static bool update_color_gamut_data(struct color_gamut_data *input_data, + struct color_gamut_data *output_data) +{ + bool output_custom_cs = false; + bool output_custom_wp = false; + + if (input_data == NULL || output_data == NULL) + return false; + + if (input_data->color_space == color_space_custom_coordinates) { + output_data->color_space = input_data->color_space; + output_data->gamut.redX = input_data->gamut.redX; + output_data->gamut.redY = input_data->gamut.redY; + output_data->gamut.greenX = input_data->gamut.greenX; + output_data->gamut.greenY = input_data->gamut.greenY; + output_data->gamut.blueX = input_data->gamut.blueX; + output_data->gamut.blueY = input_data->gamut.blueY; + } else { + struct gamut_space_coordinates gamut_coord; + enum predefined_gamut_type gamut_type = + color_space_to_predefined_gamut_types + (input_data->color_space); + + /* fall back to original color space if unknown */ + if (gamut_type == gamut_type_unknown) { + if (output_data->color_space == + color_space_custom_coordinates) { + output_custom_cs = true; + } else { + gamut_type = + color_space_to_predefined_gamut_types + (output_data->color_space); + /* fall back to sRGB if both unknown*/ + if (gamut_type == gamut_type_unknown) { + output_data->color_space = + color_space_srgb; + gamut_type = gamut_type_srgb; + } + } + } else { + output_data->color_space = input_data->color_space; + } + + if (!output_custom_cs) { + mod_color_find_predefined_gamut(&gamut_coord, + gamut_type); + output_data->gamut.redX = gamut_coord.redX; + output_data->gamut.redY = gamut_coord.redY; + output_data->gamut.greenX = gamut_coord.greenX; + output_data->gamut.greenY = gamut_coord.greenY; + output_data->gamut.blueX = gamut_coord.blueX; + output_data->gamut.blueY = gamut_coord.blueY; + } + } + + if (input_data->white_point == color_space_custom_coordinates) { + output_data->white_point = input_data->white_point; + output_data->gamut.whiteX = input_data->gamut.whiteX; + output_data->gamut.whiteY = input_data->gamut.whiteY; + } else { + struct white_point_coodinates white_point_coord; + enum predefined_white_point_type white_type = + white_point_to_predefined_white_point + (input_data->white_point); + + /* fall back to original white point if not found */ + if (white_type == white_point_type_unknown) { + if (output_data->white_point == + color_white_point_type_custom_coordinates) { + output_custom_wp = true; + } else { + white_type = + white_point_to_predefined_white_point + (output_data->white_point); + /* fall back to 6500 if both unknown*/ + if (white_type == white_point_type_unknown) { + output_data->white_point = + color_white_point_type_6500k_noon; + white_type = + white_point_type_6500k_noon; + } + } + } else { + output_data->white_point = input_data->white_point; + } + + if (!output_custom_wp) { + mod_color_find_predefined_white_point( + &white_point_coord, white_type); + output_data->gamut.whiteX = white_point_coord.whiteX; + output_data->gamut.whiteY = white_point_coord.whiteY; + } + } + return true; +} + struct mod_color *mod_color_create(struct dc *dc) { int i = 0; @@ -1311,23 +1452,36 @@ struct mod_color *mod_color_create(struct dc *dc) /*hardcoded to sRGB with 6500 color temperature*/ for (i = 0; i < MOD_COLOR_MAX_CONCURRENT_SINKS; i++) { - core_color->state[i].source_gamut.blueX = 1500; - core_color->state[i].source_gamut.blueY = 600; - core_color->state[i].source_gamut.greenX = 3000; - core_color->state[i].source_gamut.greenY = 6000; - core_color->state[i].source_gamut.redX = 6400; - core_color->state[i].source_gamut.redY = 3300; - core_color->state[i].source_gamut.whiteX = 3127; - core_color->state[i].source_gamut.whiteY = 3290; - - core_color->state[i].destination_gamut.blueX = 1500; - core_color->state[i].destination_gamut.blueY = 600; - core_color->state[i].destination_gamut.greenX = 3000; - core_color->state[i].destination_gamut.greenY = 6000; - core_color->state[i].destination_gamut.redX = 6400; - core_color->state[i].destination_gamut.redY = 3300; - core_color->state[i].destination_gamut.whiteX = 3127; - core_color->state[i].destination_gamut.whiteY = 3290; + core_color->state[i].source_gamut.color_space = + color_space_srgb; + core_color->state[i].source_gamut.white_point = + color_white_point_type_6500k_noon; + core_color->state[i].source_gamut.gamut.blueX = 1500; + core_color->state[i].source_gamut.gamut.blueY = 600; + core_color->state[i].source_gamut.gamut.greenX = 3000; + core_color->state[i].source_gamut.gamut.greenY = 6000; + core_color->state[i].source_gamut.gamut.redX = 6400; + core_color->state[i].source_gamut.gamut.redY = 3300; + core_color->state[i].source_gamut.gamut.whiteX = 3127; + core_color->state[i].source_gamut.gamut.whiteY = 3290; + + core_color->state[i].destination_gamut.color_space = + color_space_srgb; + core_color->state[i].destination_gamut.white_point = + color_white_point_type_6500k_noon; + core_color->state[i].destination_gamut.gamut.blueX = 1500; + core_color->state[i].destination_gamut.gamut.blueY = 600; + core_color->state[i].destination_gamut.gamut.greenX = 3000; + core_color->state[i].destination_gamut.gamut.greenY = 6000; + core_color->state[i].destination_gamut.gamut.redX = 6400; + core_color->state[i].destination_gamut.gamut.redY = 3300; + core_color->state[i].destination_gamut.gamut.whiteX = 3127; + core_color->state[i].destination_gamut.gamut.whiteY = 3290; + + core_color->state[i].input_transfer_function = + transfer_func_srgb; + core_color->state[i].output_transfer_function = + transfer_func_srgb; core_color->state[i].custom_color_temperature = 6500; @@ -1351,6 +1505,12 @@ struct mod_color *mod_color_create(struct dc *dc) if (core_color->state == NULL) goto fail_alloc_state; + core_color->edid_caps = dm_alloc(sizeof(struct color_edid_caps) * + MOD_COLOR_MAX_CONCURRENT_SINKS); + + if (core_color->edid_caps == NULL) + goto fail_alloc_edid_caps; + core_color->num_sinks = 0; if (dc == NULL) @@ -1371,6 +1531,9 @@ struct mod_color *mod_color_create(struct dc *dc) return &core_color->public; fail_construct: + dm_free(core_color->edid_caps); + +fail_alloc_edid_caps: dm_free(core_color->state); fail_alloc_state: @@ -1390,6 +1553,8 @@ void mod_color_destroy(struct mod_color *mod_color) struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); + dm_free(core_color->edid_caps); + for (i = 0; i < core_color->num_sinks; i++) if (core_color->state[i].gamma) dc_gamma_release(core_color->state[i].gamma); @@ -1405,7 +1570,8 @@ void mod_color_destroy(struct mod_color *mod_color) } } -bool mod_color_add_sink(struct mod_color *mod_color, const struct dc_sink *sink) +bool mod_color_add_sink(struct mod_color *mod_color, const struct dc_sink *sink, + struct color_edid_caps *edid_caps) { struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); struct core_dc *core_dc = DC_TO_CORE(core_color->dc); @@ -1426,6 +1592,11 @@ bool mod_color_add_sink(struct mod_color *mod_color, const struct dc_sink *sink) core_color->state[core_color->num_sinks]. user_enable_color_temperature = true; + core_color->edid_caps[core_color->num_sinks].colorimetry_caps = + edid_caps->colorimetry_caps; + core_color->edid_caps[core_color->num_sinks].hdr_caps = + edid_caps->hdr_caps; + /* get persistent data from registry */ flag.save_per_edid = true; flag.save_per_link = false; @@ -1462,25 +1633,25 @@ bool mod_color_add_sink(struct mod_color *mod_color, const struct dc_sink *sink) sizeof(struct color_space_coordinates), &flag)) { memcpy(&core_color->state[core_color->num_sinks]. - source_gamut, &persistent_source_gamut, + source_gamut.gamut, &persistent_source_gamut, sizeof(struct color_space_coordinates)); } else { core_color->state[core_color->num_sinks]. - source_gamut.blueX = 1500; + source_gamut.gamut.blueX = 1500; core_color->state[core_color->num_sinks]. - source_gamut.blueY = 600; + source_gamut.gamut.blueY = 600; core_color->state[core_color->num_sinks]. - source_gamut.greenX = 3000; + source_gamut.gamut.greenX = 3000; core_color->state[core_color->num_sinks]. - source_gamut.greenY = 6000; + source_gamut.gamut.greenY = 6000; core_color->state[core_color->num_sinks]. - source_gamut.redX = 6400; + source_gamut.gamut.redX = 6400; core_color->state[core_color->num_sinks]. - source_gamut.redY = 3300; + source_gamut.gamut.redY = 3300; core_color->state[core_color->num_sinks]. - source_gamut.whiteX = 3127; + source_gamut.gamut.whiteX = 3127; core_color->state[core_color->num_sinks]. - source_gamut.whiteY = 3290; + source_gamut.gamut.whiteY = 3290; } if (dm_read_persistent_data(core_dc->ctx, sink, COLOR_REGISTRY_NAME, @@ -1489,26 +1660,26 @@ bool mod_color_add_sink(struct mod_color *mod_color, const struct dc_sink *sink) sizeof(struct color_space_coordinates), &flag)) { memcpy(&core_color->state[core_color->num_sinks]. - destination_gamut, + destination_gamut.gamut, &persistent_destination_gamut, sizeof(struct color_space_coordinates)); } else { core_color->state[core_color->num_sinks]. - destination_gamut.blueX = 1500; + destination_gamut.gamut.blueX = 1500; core_color->state[core_color->num_sinks]. - destination_gamut.blueY = 600; + destination_gamut.gamut.blueY = 600; core_color->state[core_color->num_sinks]. - destination_gamut.greenX = 3000; + destination_gamut.gamut.greenX = 3000; core_color->state[core_color->num_sinks]. - destination_gamut.greenY = 6000; + destination_gamut.gamut.greenY = 6000; core_color->state[core_color->num_sinks]. - destination_gamut.redX = 6400; + destination_gamut.gamut.redX = 6400; core_color->state[core_color->num_sinks]. - destination_gamut.redY = 3300; + destination_gamut.gamut.redY = 3300; core_color->state[core_color->num_sinks]. - destination_gamut.whiteX = 3127; + destination_gamut.gamut.whiteX = 3127; core_color->state[core_color->num_sinks]. - destination_gamut.whiteY = 3290; + destination_gamut.gamut.whiteY = 3290; } if (dm_read_persistent_data(core_dc->ctx, sink, COLOR_REGISTRY_NAME, @@ -1588,6 +1759,10 @@ bool mod_color_remove_sink(struct mod_color *mod_color, memcpy(&core_color->state[j], &core_color->state[j + 1], sizeof(struct color_state)); + + memcpy(&core_color->edid_caps[j], + &core_color->edid_caps[j + 1], + sizeof(struct color_edid_caps)); } core_color->num_sinks--; @@ -1625,7 +1800,7 @@ bool mod_color_update_gamut_to_stream(struct mod_color *mod_color, COLOR_REGISTRY_NAME, "sourcegamut", &core_color->state[sink_index]. - source_gamut, + source_gamut.gamut, sizeof(struct color_space_coordinates), &flag); @@ -1634,19 +1809,19 @@ bool mod_color_update_gamut_to_stream(struct mod_color *mod_color, COLOR_REGISTRY_NAME, "destgamut", &core_color->state[sink_index]. - destination_gamut, + destination_gamut.gamut, sizeof(struct color_space_coordinates), &flag); if (!build_gamut_remap_matrix - (core_color->state[sink_index].source_gamut, - matrix->rgbCoeffSrc, - matrix->whiteCoeffSrc)) + (core_color->state[sink_index].source_gamut.gamut, + matrix->rgbCoeffSrc, + matrix->whiteCoeffSrc)) goto function_fail; if (!build_gamut_remap_matrix (core_color->state[sink_index]. - destination_gamut, + destination_gamut.gamut, matrix->rgbCoeffDst, matrix->whiteCoeffDst)) goto function_fail; @@ -1700,8 +1875,7 @@ function_fail: bool mod_color_adjust_source_gamut(struct mod_color *mod_color, const struct dc_stream **streams, int num_streams, - struct gamut_space_coordinates *input_gamut_coordinates, - struct white_point_coodinates *input_white_point_coordinates) + struct color_gamut_data *input_gamut_data) { struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); @@ -1711,25 +1885,35 @@ bool mod_color_adjust_source_gamut(struct mod_color *mod_color, sink_index = sink_index_from_sink(core_color, streams[stream_index]->sink); - core_color->state[sink_index].source_gamut.blueX = - input_gamut_coordinates->blueX; - core_color->state[sink_index].source_gamut.blueY = - input_gamut_coordinates->blueY; - core_color->state[sink_index].source_gamut.greenX = - input_gamut_coordinates->greenX; - core_color->state[sink_index].source_gamut.greenY = - input_gamut_coordinates->greenY; - core_color->state[sink_index].source_gamut.redX = - input_gamut_coordinates->redX; - core_color->state[sink_index].source_gamut.redY = - input_gamut_coordinates->redY; - core_color->state[sink_index].source_gamut.whiteX = - input_white_point_coordinates->whiteX; - core_color->state[sink_index].source_gamut.whiteY = - input_white_point_coordinates->whiteY; + update_color_gamut_data(input_gamut_data, + &core_color->state[sink_index].source_gamut); } - if (!mod_color_update_gamut_to_stream(mod_color, streams, num_streams)) + if (!mod_color_update_gamut_info(mod_color, streams, num_streams)) + return false; + + return true; +} + +bool mod_color_adjust_source_gamut_and_tf(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + struct color_gamut_data *input_gamut_data, + enum color_transfer_func input_transfer_func) +{ + struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); + + unsigned int stream_index, sink_index; + + for (stream_index = 0; stream_index < num_streams; stream_index++) { + sink_index = sink_index_from_sink(core_color, + streams[stream_index]->sink); + update_color_gamut_data(input_gamut_data, + &core_color->state[sink_index].source_gamut); + core_color->state[sink_index].input_transfer_function = + input_transfer_func; + } + + if (!mod_color_update_gamut_info(mod_color, streams, num_streams)) return false; return true; @@ -1737,8 +1921,7 @@ bool mod_color_adjust_source_gamut(struct mod_color *mod_color, bool mod_color_adjust_destination_gamut(struct mod_color *mod_color, const struct dc_stream **streams, int num_streams, - struct gamut_space_coordinates *input_gamut_coordinates, - struct white_point_coodinates *input_white_point_coordinates) + struct color_gamut_data *input_gamut_data) { struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); @@ -1748,22 +1931,8 @@ bool mod_color_adjust_destination_gamut(struct mod_color *mod_color, sink_index = sink_index_from_sink(core_color, streams[stream_index]->sink); - core_color->state[sink_index].destination_gamut.blueX = - input_gamut_coordinates->blueX; - core_color->state[sink_index].destination_gamut.blueY = - input_gamut_coordinates->blueY; - core_color->state[sink_index].destination_gamut.greenX = - input_gamut_coordinates->greenX; - core_color->state[sink_index].destination_gamut.greenY = - input_gamut_coordinates->greenY; - core_color->state[sink_index].destination_gamut.redX = - input_gamut_coordinates->redX; - core_color->state[sink_index].destination_gamut.redY = - input_gamut_coordinates->redY; - core_color->state[sink_index].destination_gamut.whiteX = - input_white_point_coordinates->whiteX; - core_color->state[sink_index].destination_gamut.whiteY = - input_white_point_coordinates->whiteY; + update_color_gamut_data(input_gamut_data, + &core_color->state[sink_index].destination_gamut); } if (!mod_color_update_gamut_to_stream(mod_color, streams, num_streams)) @@ -1784,9 +1953,9 @@ bool mod_color_set_white_point(struct mod_color *mod_color, stream_index++) { sink_index = sink_index_from_sink(core_color, streams[stream_index]->sink); - core_color->state[sink_index].source_gamut.whiteX = + core_color->state[sink_index].source_gamut.gamut.whiteX = white_point->whiteX; - core_color->state[sink_index].source_gamut.whiteY = + core_color->state[sink_index].source_gamut.gamut.whiteY = white_point->whiteY; } @@ -1796,6 +1965,39 @@ bool mod_color_set_white_point(struct mod_color *mod_color, return true; } + +bool mod_color_set_mastering_info(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + struct color_mastering_info *mastering_info) +{ + struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); + unsigned int stream_index, sink_index; + + for (stream_index = 0; stream_index < num_streams; stream_index++) { + sink_index = sink_index_from_sink(core_color, + streams[stream_index]->sink); + memcpy(&core_color->state[sink_index].mastering_info, + mastering_info, + sizeof(struct color_mastering_info)); + } + return true; +} + +bool mod_color_get_mastering_info(struct mod_color *mod_color, + const struct dc_sink *sink, + struct color_mastering_info *mastering_info) +{ + struct core_color *core_color = + MOD_COLOR_TO_CORE(mod_color); + + unsigned int sink_index = sink_index_from_sink(core_color, sink); + + memcpy(mastering_info, &core_color->state[sink_index].mastering_info, + sizeof(struct color_mastering_info)); + + return true; +} + bool mod_color_set_user_enable(struct mod_color *mod_color, const struct dc_stream **streams, int num_streams, bool user_enable) @@ -1953,7 +2155,7 @@ bool mod_color_get_source_gamut(struct mod_color *mod_color, unsigned int sink_index = sink_index_from_sink(core_color, sink); - *source_gamut = core_color->state[sink_index].source_gamut; + *source_gamut = core_color->state[sink_index].source_gamut.gamut; return true; } @@ -1973,14 +2175,14 @@ bool mod_color_notify_mode_change(struct mod_color *mod_color, streams[stream_index]->sink); if (!build_gamut_remap_matrix - (core_color->state[sink_index].source_gamut, - matrix->rgbCoeffSrc, - matrix->whiteCoeffSrc)) + (core_color->state[sink_index].source_gamut.gamut, + matrix->rgbCoeffSrc, + matrix->whiteCoeffSrc)) goto function_fail; if (!build_gamut_remap_matrix (core_color->state[sink_index]. - destination_gamut, + destination_gamut.gamut, matrix->rgbCoeffDst, matrix->whiteCoeffDst)) goto function_fail; @@ -2379,3 +2581,200 @@ bool mod_color_is_rgb_limited_range_supported_for_timing( return result; } + +bool mod_color_set_regamma(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams) +{ + /*TODO*/ + return true; +} + +bool mod_color_set_degamma(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + enum color_transfer_func transfer_function) +{ + /*TODO*/ + return true; +} + +bool mod_color_update_gamut_info(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams) +{ + struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); + unsigned int stream_index, sink_index; + bool should_defer = false; + bool is_hdr = false; + enum color_color_space source_color_space; + enum color_transfer_func input_transfer_function; + struct color_gamut_data new_gamut_source; + struct color_gamut_data new_gamut_destination; + + for (stream_index = 0; stream_index < num_streams; stream_index++) { + sink_index = sink_index_from_sink(core_color, + streams[stream_index]->sink); + source_color_space = + core_color->state[sink_index].source_gamut.color_space; + input_transfer_function = + core_color->state[sink_index].input_transfer_function; + new_gamut_source.color_space = source_color_space; + new_gamut_destination.color_space = + core_color->state[sink_index]. + destination_gamut.color_space; + + struct dc_surface *surface = + dc_stream_to_surface_from_pipe_ctx(core_color, + streams[stream_index]); + if (surface == NULL) + return false; + + if (surface->format == SURFACE_PIXEL_FORMAT_GRPH_ARGB8888 || + surface->format == + SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010) { + + if (input_transfer_function == + transfer_func_pq2084 || + input_transfer_function == + transfer_func_pq2084_interim) { + /* For PQ and PQ interim, we bypass degamma+ + * remap+regamma, application needs to also + * handle gamut remapping + */ + /* TODO */ + is_hdr = true; + } else if (input_transfer_function == + transfer_func_linear_0_1 || + input_transfer_function == + transfer_func_linear_0_125) { + /* TF not supported in current surface format, + * but may be deferred to a later flip + */ + should_defer = true; + } else { + new_gamut_destination.color_space = + color_space_srgb; + } + } else if (surface->format == + SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F || + surface->format == + SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F || + surface->format == + SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616) { + if (input_transfer_function == + transfer_func_linear_0_125) { + /* Regamma PQ for HDR supported displays and + * 0-125 source + */ + if ((core_color->edid_caps[sink_index]. + hdr_caps) & smpte_st2084) + is_hdr = true; + + /* override for BT.2020 whenever PQ */ + if (core_color->state[sink_index]. + destination_gamut.color_space != + color_space_bt2020) { + if (streams[stream_index]->timing. + pixel_encoding == + PIXEL_ENCODING_RGB) { + if ((core_color-> + edid_caps[sink_index]. + colorimetry_caps) & bt_2020_rgb) + new_gamut_destination. + color_space = + color_space_bt2020; + } else { + if ((core_color-> + edid_caps[sink_index]. + colorimetry_caps) & bt_2020_ycc) + new_gamut_destination. + color_space = + color_space_bt2020; + } + } + } else if (input_transfer_function == + transfer_func_linear_0_1) { + new_gamut_destination.color_space = + color_space_srgb; + } else { + /* TF not supported in current surface format, + * but may be deferred to a later flip + */ + should_defer = true; + } + } + + /* 0. ---- CHECK DEFERRED ---- */ + if (should_defer) + return true; + + /* 1. ---- SET GAMUT SOURCE ---- */ + new_gamut_source.white_point = core_color->state[sink_index]. + source_gamut.white_point; + update_color_gamut_data(&new_gamut_source, + &core_color->state[sink_index].source_gamut); + + /* 2. ---- SET GAMUT DESTINATION ---- */ + new_gamut_destination.white_point = + core_color->state[sink_index]. + destination_gamut.white_point; + update_color_gamut_data(&new_gamut_destination, + &core_color->state[sink_index].destination_gamut); + + /* 3. ---- SET DEGAMMA ---- */ + struct dc_transfer_func *input_tf = NULL; + + input_tf = dc_create_transfer_func(core_color->dc); + + if (input_tf != NULL) { + input_tf->type = TF_TYPE_PREDEFINED; + + switch (input_transfer_function) { + case transfer_func_srgb: + input_tf->tf = TRANSFER_FUNCTION_SRGB; + break; + case transfer_func_linear_0_1: + case transfer_func_linear_0_125: + input_tf->tf = TRANSFER_FUNCTION_LINEAR; + break; + default: + dc_transfer_func_release(input_tf); + input_tf = NULL; + break; + } + } + + /* 4. ---- SET REGAMMA ---- */ + struct dc_transfer_func *output_tf = NULL; + + output_tf = dc_create_transfer_func(core_color->dc); + + if (output_tf != NULL) { + output_tf->type = TF_TYPE_PREDEFINED; + if (is_hdr) + output_tf->tf = TRANSFER_FUNCTION_PQ; + else + output_tf->tf = TRANSFER_FUNCTION_SRGB; + } + + /* 5. ---- TODO: UPDATE INFOPACKETS ---- */ + + if (!mod_color_update_gamut_to_stream( + mod_color, streams, num_streams)) + return false; + + struct dc_surface_update updates[4] = {0}; + + updates[0].surface = surface; + updates[0].gamma = core_color->state[sink_index].gamma; + updates[0].in_transfer_func = input_tf; + updates[0].out_transfer_func = output_tf; + + dc_update_surfaces_for_target(core_color->dc, updates, 1, NULL); + + if (input_tf != NULL) + dc_transfer_func_release(input_tf); + + if (output_tf != NULL) + dc_transfer_func_release(output_tf); + } + return true; +} diff --git a/drivers/gpu/drm/amd/display/modules/color/color_helper.h b/drivers/gpu/drm/amd/display/modules/color/color_helper.h index c0e6334b947e..b7a7ca4debd7 100644 --- a/drivers/gpu/drm/amd/display/modules/color/color_helper.h +++ b/drivers/gpu/drm/amd/display/modules/color/color_helper.h @@ -37,7 +37,7 @@ bool mod_color_find_predefined_gamut( bool mod_color_find_predefined_white_point( struct white_point_coodinates *out_white_point, - unsigned int index); + enum predefined_white_point_type type); bool mod_color_find_white_point_from_temperature( struct white_point_coodinates *out_white_point, diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_color.h b/drivers/gpu/drm/amd/display/modules/inc/mod_color.h index fbf908141ba7..670b87fb8bd2 100644 --- a/drivers/gpu/drm/amd/display/modules/inc/mod_color.h +++ b/drivers/gpu/drm/amd/display/modules/inc/mod_color.h @@ -30,6 +30,79 @@ #include "dm_services.h" #include "color_helper.h" +enum color_transfer_func { + transfer_func_unknown, + transfer_func_srgb, + transfer_func_bt709, + transfer_func_pq2084, + transfer_func_pq2084_interim, + transfer_func_linear_0_1, + transfer_func_linear_0_125, + transfer_func_dolbyvision, + transfer_func_gamma_22, + transfer_func_gamma_26 +}; + +enum color_color_space { + color_space_unsupported, + color_space_srgb, + color_space_bt601, + color_space_bt709, + color_space_xv_ycc_bt601, + color_space_xv_ycc_bt709, + color_space_xr_rgb, + color_space_bt2020, + color_space_adobe, + color_space_dci_p3, + color_space_sc_rgb_ms_ref, + color_space_display_native, + color_space_app_ctrl, + color_space_dolby_vision, + color_space_custom_coordinates +}; + +enum color_white_point_type { + color_white_point_type_unknown, + color_white_point_type_5000k_horizon, + color_white_point_type_6500k_noon, + color_white_point_type_7500k_north_sky, + color_white_point_type_9300k, + color_white_point_type_custom_coordinates +}; + +enum colorimetry_support_flag { + xv_ycc_bt601 = 0x01, + xv_ycc_bt709 = 0x02, + s_ycc_601 = 0x04, + adobe_ycc_601 = 0x08, + adobe_rgb = 0x10, + bt_2020_c_ycc = 0x20, + bt_2020_ycc = 0x40, + bt_2020_rgb = 0x80 +}; + +enum hdr_tf_support_flag { + traditional_gamma_sdr = 0x01, + traditional_gamma_hdr = 0x02, + smpte_st2084 = 0x04 +}; + +struct color_mastering_info { + unsigned int chromaticity_green_x; + unsigned int chromaticity_green_y; + unsigned int chromaticity_blue_x; + unsigned int chromaticity_blue_y; + unsigned int chromaticity_red_x; + unsigned int chromaticity_red_y; + unsigned int chromaticity_white_point_x; + unsigned int chromaticity_white_point_y; + + unsigned int min_luminance; + unsigned int max_luminance; + unsigned int maximum_content_light_level; + unsigned int maximum_frame_average_light_level; +}; + struct mod_color { int dummy; }; @@ -86,12 +159,23 @@ struct color_range { int max; }; +struct color_gamut_data { + enum color_color_space color_space; + enum color_white_point_type white_point; + struct color_space_coordinates gamut; +}; + +struct color_edid_caps { + unsigned int colorimetry_caps; + unsigned int hdr_caps; +}; + struct mod_color *mod_color_create(struct dc *dc); void mod_color_destroy(struct mod_color *mod_color); bool mod_color_add_sink(struct mod_color *mod_color, - const struct dc_sink *sink); + const struct dc_sink *sink, struct color_edid_caps *edid_caps); bool mod_color_remove_sink(struct mod_color *mod_color, const struct dc_sink *sink); @@ -105,18 +189,29 @@ bool mod_color_set_white_point(struct mod_color *mod_color, bool mod_color_adjust_source_gamut(struct mod_color *mod_color, const struct dc_stream **streams, int num_streams, - struct gamut_space_coordinates *input_gamut_coordinates, - struct white_point_coodinates *input_white_point_coordinates); + struct color_gamut_data *input_gamut_data); bool mod_color_adjust_destination_gamut(struct mod_color *mod_color, const struct dc_stream **streams, int num_streams, - struct gamut_space_coordinates *input_gamut_coordinates, - struct white_point_coodinates *input_white_point_coordinates); + struct color_gamut_data *input_gamut_data); + +bool mod_color_adjust_source_gamut_and_tf(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + struct color_gamut_data *input_gamut_data, + enum color_transfer_func input_transfer_func); bool mod_color_get_user_enable(struct mod_color *mod_color, const struct dc_sink *sink, bool *user_enable); +bool mod_color_set_mastering_info(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + struct color_mastering_info *mastering_info); + +bool mod_color_get_mastering_info(struct mod_color *mod_color, + const struct dc_sink *sink, + struct color_mastering_info *mastering_info); + bool mod_color_set_user_enable(struct mod_color *mod_color, const struct dc_stream **streams, int num_streams, bool user_enable); @@ -190,4 +285,14 @@ bool mod_color_is_rgb_limited_range_supported_for_timing( const struct dc_sink *sink, const struct dc_crtc_timing *timing); +bool mod_color_set_regamma(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams); + +bool mod_color_set_degamma(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + enum color_transfer_func transfer_function); + +bool mod_color_update_gamut_info(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams); + #endif /* MOD_COLOR_H_ */ -- cgit From 6f3f8d48664d0cecc559ea8c093838c13ba21192 Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Mon, 19 Dec 2016 15:16:12 -0500 Subject: drm/amd/display: Fix Regamma end point 1. HW register programmed to wrong value 2. End slope for PQ case not calculated correctly Signed-off-by: Anthony Koo Reviewed-by: Aric Cyr Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c | 34 +++++++++++++++------- drivers/gpu/drm/amd/display/dc/dce/dce_opp.c | 4 +-- 2 files changed, 26 insertions(+), 12 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c index 5cd408dadb20..f33135b53a80 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c @@ -287,8 +287,6 @@ static bool build_hw_curve_configuration( uint32_t offset = 0; int8_t begin = curve_config->begin; int32_t region_number = 0; - struct fixed31_32 magic_number = - dal_fixed31_32_from_fraction(249, 1000); i = begin; @@ -370,10 +368,8 @@ static bool build_hw_curve_configuration( ++i; } - points[index].x = - dal_fixed31_32_add(region1, magic_number); - points[index].adjusted_x = - dal_fixed31_32_add(region1, magic_number); + points[index].x = region1; + points[index].adjusted_x = region1; *number_of_points = index; @@ -1218,7 +1214,8 @@ static void rebuild_curve_configuration_magic( struct curve_points *arr_points, struct pwl_result_data *rgb_resulted, const struct hw_x_point *coordinates_x, - uint32_t hw_points_num) + uint32_t hw_points_num, + enum dc_transfer_func_predefined tf) { struct fixed31_32 y_r; struct fixed31_32 y_g; @@ -1264,6 +1261,18 @@ static void rebuild_curve_configuration_magic( arr_points[2].y = y3_max; arr_points[2].slope = dal_fixed31_32_zero; + + /* for PQ, we want to have a straight line from last HW X point, and the + * slope to be such that we hit 1.0 at 10000 nits. + */ + if (tf == TRANSFER_FUNCTION_PQ) { + const struct fixed31_32 end_value = + dal_fixed31_32_from_int(125); + + arr_points[2].slope = dal_fixed31_32_div( + dal_fixed31_32_sub(dal_fixed31_32_one, arr_points[1].y), + dal_fixed31_32_sub(end_value, arr_points[1].x)); + } } static bool convert_to_custom_float_format( @@ -1424,6 +1433,8 @@ bool calculate_regamma_params(struct pwl_params *params, struct pixel_gamma_point *coeff128_oem = NULL; struct pixel_gamma_point *coeff128 = NULL; + enum dc_transfer_func_predefined tf = TRANSFER_FUNCTION_SRGB; + bool ret = false; coordinates_x = dm_alloc(sizeof(*coordinates_x)*(256 + 3)); @@ -1452,6 +1463,9 @@ bool calculate_regamma_params(struct pwl_params *params, dividers.divider2 = dal_fixed31_32_from_int(2); dividers.divider3 = dal_fixed31_32_from_fraction(5, 2); + if (stream->public.out_transfer_func) + tf = stream->public.out_transfer_func->tf; + build_evenly_distributed_points( axix_x_256, 256, @@ -1460,8 +1474,7 @@ bool calculate_regamma_params(struct pwl_params *params, scale_gamma(rgb_user, ramp, dividers); - if (stream->public.out_transfer_func && - stream->public.out_transfer_func->tf == TRANSFER_FUNCTION_PQ) { + if (tf == TRANSFER_FUNCTION_PQ) { setup_distribution_points_pq(arr_curve_points, arr_points, ¶ms->hw_points_num, coordinates_x, surface->public.format); @@ -1486,7 +1499,8 @@ bool calculate_regamma_params(struct pwl_params *params, arr_points, rgb_resulted, coordinates_x, - params->hw_points_num); + params->hw_points_num, + tf); convert_to_custom_float(rgb_resulted, arr_points, params->hw_points_num); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c index 80443a1cccd2..653f93dd281f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c @@ -139,8 +139,8 @@ static void regamma_config_regions_and_segments( } { REG_SET_2(REGAMMA_CNTLA_END_CNTL2, 0, - REGAMMA_CNTLA_EXP_REGION_END_BASE, params->arr_points[2].custom_float_slope, - REGAMMA_CNTLA_EXP_REGION_END_SLOPE, params->arr_points[1].custom_float_y); + REGAMMA_CNTLA_EXP_REGION_END_BASE, params->arr_points[1].custom_float_y, + REGAMMA_CNTLA_EXP_REGION_END_SLOPE, params->arr_points[2].custom_float_slope); } curve = params->arr_curve_points; -- cgit From b76794d2e7198cf7c73f1b65dbc6dc796ac92685 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Mon, 19 Dec 2016 12:54:40 -0500 Subject: drm/amd/display: 4k split black out due to incorrect cursor - add handling to program both cursor for left and right pipe - add guard to disable cursor in case where cursor isn't visible to prevent pipe hang Signed-off-by: Tony Cheng Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_target.c | 83 ++++++++++------------ drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 9 +++ drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h | 3 +- .../drm/amd/display/dc/dce110/dce110_ipp_cursor.c | 3 +- drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h | 3 +- 5 files changed, 53 insertions(+), 48 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_target.c b/drivers/gpu/drm/amd/display/dc/core/dc_target.c index 48eb7b0e0350..2531df74871a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_target.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_target.c @@ -148,56 +148,49 @@ bool dc_target_set_cursor_attributes( struct dc_target *dc_target, const struct dc_cursor_attributes *attributes) { - uint8_t i, j; - struct core_target *target; - struct core_dc *core_dc; - struct resource_context *res_ctx; + int i, j; + struct core_target *target = DC_TARGET_TO_CORE(dc_target); + struct core_dc *core_dc = DC_TO_CORE(target->ctx->dc); + struct resource_context *res_ctx = &core_dc->current_context->res_ctx; + bool ret = false; if (NULL == dc_target) { dm_error("DC: dc_target is NULL!\n"); return false; - } if (NULL == attributes) { dm_error("DC: attributes is NULL!\n"); return false; - } - target = DC_TARGET_TO_CORE(dc_target); - core_dc = DC_TO_CORE(target->ctx->dc); - res_ctx = &core_dc->current_context->res_ctx; + for (i = 0; i < dc_target->stream_count; i++) { + const struct dc_stream *stream = dc_target->streams[i]; - for (i = 0; i < target->public.stream_count; i++) { for (j = 0; j < MAX_PIPES; j++) { - struct input_pixel_processor *ipp = - res_ctx->pipe_ctx[j].ipp; + struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[j]; - if (res_ctx->pipe_ctx[j].stream != - DC_STREAM_TO_CORE(target->public.streams[i])) - continue; + if (&pipe_ctx->stream->public == stream) { + struct input_pixel_processor *ipp = pipe_ctx->ipp; - /* As of writing of this code cursor is on the top - * plane so we only need to set it on first pipe we - * find. May need to make this code dce specific later. - */ - if (ipp->funcs->ipp_cursor_set_attributes( - ipp, attributes)) - return true; + if (ipp->funcs->ipp_cursor_set_attributes( + ipp, attributes)) + ret = true; + } } } - return false; + return ret; } bool dc_target_set_cursor_position( struct dc_target *dc_target, const struct dc_cursor_position *position) { - uint8_t i, j; - struct core_target *target; - struct core_dc *core_dc; - struct resource_context *res_ctx; + int i, j; + struct core_target *target = DC_TARGET_TO_CORE(dc_target); + struct core_dc *core_dc = DC_TO_CORE(target->ctx->dc); + struct resource_context *res_ctx = &core_dc->current_context->res_ctx; + bool ret = false; if (NULL == dc_target) { dm_error("DC: dc_target is NULL!\n"); @@ -209,29 +202,29 @@ bool dc_target_set_cursor_position( return false; } - target = DC_TARGET_TO_CORE(dc_target); - core_dc = DC_TO_CORE(target->ctx->dc); - res_ctx = &core_dc->current_context->res_ctx; + for (i = 0; i < dc_target->stream_count; i++) { + const struct dc_stream *stream = dc_target->streams[i]; - for (i = 0; i < target->public.stream_count; i++) { for (j = 0; j < MAX_PIPES; j++) { - struct input_pixel_processor *ipp = - res_ctx->pipe_ctx[j].ipp; - - if (res_ctx->pipe_ctx[j].stream != - DC_STREAM_TO_CORE(target->public.streams[i])) - continue; - - /* As of writing of this code cursor is on the top - * plane so we only need to set it on first pipe we - * find. May need to make this code dce specific later. - */ - ipp->funcs->ipp_cursor_set_position(ipp, position); - return true; + struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[j]; + + if (&pipe_ctx->stream->public == stream) { + struct input_pixel_processor *ipp = pipe_ctx->ipp; + struct dc_cursor_mi_param param = { + .pixel_clk_khz = stream->timing.pix_clk_khz, + .ref_clk_khz = 48000,/*todo refclk*/ + .viewport_x_start = pipe_ctx->scl_data.viewport.x, + .viewport_width = pipe_ctx->scl_data.viewport.width, + .h_scale_ratio = pipe_ctx->scl_data.ratios.horz, + }; + + ipp->funcs->ipp_cursor_set_position(ipp, position, ¶m); + ret = true; + } } } - return false; + return ret; } uint32_t dc_target_get_vblank_counter(const struct dc_target *dc_target) diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index 5605a5c96da7..bd603374a3c9 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -27,6 +27,7 @@ #define DC_HW_TYPES_H #include "os_types.h" +#include "fixed31_32.h" /****************************************************************************** * Data types for Virtual HW Layer of DAL3. @@ -359,6 +360,14 @@ struct dc_cursor_position { bool hot_spot_enable; }; +struct dc_cursor_mi_param { + unsigned int pixel_clk_khz; + unsigned int ref_clk_khz; + unsigned int viewport_x_start; + unsigned int viewport_width; + struct fixed31_32 h_scale_ratio; +}; + /* IPP related types */ /* Used by both ipp amd opp functions*/ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h index 60eebdecfa10..56fe3274407c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h @@ -54,7 +54,8 @@ void dce110_ipp_destroy(struct input_pixel_processor **ipp); /* CURSOR RELATED */ void dce110_ipp_cursor_set_position( struct input_pixel_processor *ipp, - const struct dc_cursor_position *position); + const struct dc_cursor_position *position, + const struct dc_cursor_mi_param *param); bool dce110_ipp_cursor_set_attributes( struct input_pixel_processor *ipp, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_cursor.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_cursor.c index 95f6ca3ba5df..1cab12ba8447 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_cursor.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_cursor.c @@ -72,7 +72,8 @@ static void program_address( void dce110_ipp_cursor_set_position( struct input_pixel_processor *ipp, - const struct dc_cursor_position *position) + const struct dc_cursor_position *position, + const struct dc_cursor_mi_param *param) { struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h index 7e5f3e02a719..81de97568d11 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h @@ -83,7 +83,8 @@ struct ipp_funcs { /*** cursor ***/ void (*ipp_cursor_set_position)( struct input_pixel_processor *ipp, - const struct dc_cursor_position *position); + const struct dc_cursor_position *position, + const struct dc_cursor_mi_param *param); bool (*ipp_cursor_set_attributes)( struct input_pixel_processor *ipp, -- cgit From 540f7d8068a7278ee0604083aad3c88f0deab6ed Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Mon, 19 Dec 2016 18:54:15 -0500 Subject: drm/amd/display: add pitch to cursor attributes Signed-off-by: Tony Cheng Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index bd603374a3c9..499f6b2a31f8 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -407,6 +407,7 @@ union dc_cursor_attribute_flags { struct dc_cursor_attributes { PHYSICAL_ADDRESS_LOC address; + uint32_t pitch; /* Width and height should correspond to cursor surface width x heigh */ uint32_t width; -- cgit From ae799430c59edb6915e87c7c3ab972a931c796d3 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Mon, 19 Dec 2016 15:41:49 -0500 Subject: drm/amd/display: minor clock source refactor This should make it easier to share code with newer ASICs Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dce/dce_clock_source.c | 68 +++++++++++----------- .../gpu/drm/amd/display/dc/dce/dce_clock_source.h | 9 ++- 2 files changed, 40 insertions(+), 37 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index 3d1c32122d69..a38172bdcb5e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -465,7 +465,6 @@ static uint32_t dce110_get_pix_clk_dividers_helper ( struct pll_settings *pll_settings, struct pixel_clk_params *pix_clk_params) { - uint32_t value = 0; uint32_t field = 0; uint32_t pll_calc_error = MAX_PLL_CALC_ERROR; @@ -473,7 +472,6 @@ static uint32_t dce110_get_pix_clk_dividers_helper ( * HW Dce80 spec: * 00 - PCIE_REFCLK, 01 - XTALIN, 02 - GENERICA, 03 - GENERICB * 04 - HSYNCA, 05 - GENLK_CLK, 06 - PCIE_REFCLK, 07 - DVOCLK0 */ - value = REG_READ(PLL_CNTL); REG_GET(PLL_CNTL, PLL_REF_DIV_SRC, &field); pll_settings->use_external_clk = (field > 1); @@ -807,51 +805,30 @@ static void dce112_program_pixel_clk_resync( } static bool dce110_program_pix_clk( - struct clock_source *clk_src, + struct clock_source *clock_source, struct pixel_clk_params *pix_clk_params, struct pll_settings *pll_settings) { - struct dce110_clk_src *dce110_clk_src = TO_DCE110_CLK_SRC(clk_src); + struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source); struct bp_pixel_clock_parameters bp_pc_params = {0}; /* First disable SS * ATOMBIOS will enable by default SS on PLL for DP, * do not disable it here */ - if (clk_src->id != CLOCK_SOURCE_ID_EXTERNAL && + if (clock_source->id != CLOCK_SOURCE_ID_EXTERNAL && !dc_is_dp_signal(pix_clk_params->signal_type) && - clk_src->ctx->dce_version <= DCE_VERSION_11_0) - disable_spread_spectrum(dce110_clk_src); + clock_source->ctx->dce_version <= DCE_VERSION_11_0) + disable_spread_spectrum(clk_src); /*ATOMBIOS expects pixel rate adjusted by deep color ratio)*/ bp_pc_params.controller_id = pix_clk_params->controller_id; - bp_pc_params.pll_id = clk_src->id; + bp_pc_params.pll_id = clock_source->id; bp_pc_params.target_pixel_clock = pll_settings->actual_pix_clk; bp_pc_params.encoder_object_id = pix_clk_params->encoder_object_id; bp_pc_params.signal_type = pix_clk_params->signal_type; - switch (clk_src->ctx->dce_version) { - case DCE_VERSION_11_2: - if (clk_src->id != CLOCK_SOURCE_ID_DP_DTO) { - bp_pc_params.flags.SET_GENLOCK_REF_DIV_SRC = - pll_settings->use_external_clk; - bp_pc_params.flags.SET_XTALIN_REF_SRC = - !pll_settings->use_external_clk; - if (pix_clk_params->flags.SUPPORT_YCBCR420) { - bp_pc_params.target_pixel_clock = pll_settings->actual_pix_clk / 2; - bp_pc_params.flags.SUPPORT_YUV_420 = 1; - } - } - if (dce110_clk_src->bios->funcs->set_pixel_clock( - dce110_clk_src->bios, &bp_pc_params) != BP_RESULT_OK) - return false; - /* Resync deep color DTO */ - if (clk_src->id != CLOCK_SOURCE_ID_DP_DTO) - dce112_program_pixel_clk_resync(dce110_clk_src, - pix_clk_params->signal_type, - pix_clk_params->color_depth, - pix_clk_params->flags.SUPPORT_YCBCR420); - break; + switch (clock_source->ctx->dce_version) { case DCE_VERSION_8_0: case DCE_VERSION_10_0: case DCE_VERSION_11_0: @@ -864,28 +841,49 @@ static bool dce110_program_pix_clk( bp_pc_params.flags.SET_EXTERNAL_REF_DIV_SRC = pll_settings->use_external_clk; - if (dce110_clk_src->bios->funcs->set_pixel_clock( - dce110_clk_src->bios, &bp_pc_params) != BP_RESULT_OK) + if (clk_src->bios->funcs->set_pixel_clock( + clk_src->bios, &bp_pc_params) != BP_RESULT_OK) return false; /* Enable SS * ATOMBIOS will enable by default SS for DP on PLL ( DP ID clock), * based on HW display PLL team, SS control settings should be programmed * during PLL Reset, but they do not have effect * until SS_EN is asserted.*/ - if (clk_src->id != CLOCK_SOURCE_ID_EXTERNAL + if (clock_source->id != CLOCK_SOURCE_ID_EXTERNAL && pix_clk_params->flags.ENABLE_SS && !dc_is_dp_signal( pix_clk_params->signal_type)) { - if (!enable_spread_spectrum(dce110_clk_src, + if (!enable_spread_spectrum(clk_src, pix_clk_params->signal_type, pll_settings)) return false; /* Resync deep color DTO */ - dce110_program_pixel_clk_resync(dce110_clk_src, + dce110_program_pixel_clk_resync(clk_src, pix_clk_params->signal_type, pix_clk_params->color_depth); } break; + case DCE_VERSION_11_2: + if (clock_source->id != CLOCK_SOURCE_ID_DP_DTO) { + bp_pc_params.flags.SET_GENLOCK_REF_DIV_SRC = + pll_settings->use_external_clk; + bp_pc_params.flags.SET_XTALIN_REF_SRC = + !pll_settings->use_external_clk; + if (pix_clk_params->flags.SUPPORT_YCBCR420) { + bp_pc_params.target_pixel_clock = pll_settings->actual_pix_clk / 2; + bp_pc_params.flags.SUPPORT_YUV_420 = 1; + } + } + if (clk_src->bios->funcs->set_pixel_clock( + clk_src->bios, &bp_pc_params) != BP_RESULT_OK) + return false; + /* Resync deep color DTO */ + if (clock_source->id != CLOCK_SOURCE_ID_DP_DTO) + dce112_program_pixel_clk_resync(clk_src, + pix_clk_params->signal_type, + pix_clk_params->color_depth, + pix_clk_params->flags.SUPPORT_YCBCR420); + break; default: break; } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h index 067e4ac0e67a..8ee00712ef8e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h @@ -41,6 +41,7 @@ #define CS_COMMON_REG_LIST_DCE_112(id) \ SRI(PIXCLK_RESYNC_CNTL, PHYPLL, id) + #define CS_SF(reg_name, field_name, post_fix)\ .field_name = reg_name ## __ ## field_name ## post_fix @@ -48,11 +49,11 @@ CS_SF(PLL_CNTL, PLL_REF_DIV_SRC, mask_sh),\ CS_SF(PIXCLK1_RESYNC_CNTL, DCCG_DEEP_COLOR_CNTL1, mask_sh),\ CS_SF(PLL_POST_DIV, PLL_POST_DIV_PIXCLK, mask_sh),\ - CS_SF(PLL_REF_DIV, PLL_REF_DIV, mask_sh),\ + CS_SF(PLL_REF_DIV, PLL_REF_DIV, mask_sh) #define CS_COMMON_MASK_SH_LIST_DCE_112(mask_sh)\ CS_SF(PHYPLLA_PIXCLK_RESYNC_CNTL, PHYPLLA_DCCG_DEEP_COLOR_CNTL, mask_sh),\ - CS_SF(PHYPLLA_PIXCLK_RESYNC_CNTL, PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE, mask_sh),\ + CS_SF(PHYPLLA_PIXCLK_RESYNC_CNTL, PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE, mask_sh) #define CS_REG_FIELD_LIST(type) \ type PLL_REF_DIV_SRC; \ @@ -61,6 +62,7 @@ type PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE; \ type PLL_POST_DIV_PIXCLK; \ type PLL_REF_DIV; \ + type DP_DTO0_ENABLE; struct dce110_clk_src_shift { CS_REG_FIELD_LIST(uint8_t) @@ -74,6 +76,9 @@ struct dce110_clk_src_regs { uint32_t RESYNC_CNTL; uint32_t PIXCLK_RESYNC_CNTL; uint32_t PLL_CNTL; + uint32_t PHASE; + uint32_t MODULO; + uint32_t PIXEL_RATE_CNTL; }; struct dce110_clk_src { -- cgit From 9cd09bfeb26e4ef51a6735f585784cd1b46a496c Mon Sep 17 00:00:00 2001 From: Leon Elazar Date: Mon, 19 Dec 2016 12:00:05 -0500 Subject: drm/amd/display: Add dcc param to surface Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 61456f96419e..478bdee52cd5 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -275,6 +275,7 @@ struct dc_surface { struct dc_plane_info { union plane_size plane_size; union dc_tiling_info tiling_info; + struct dc_plane_dcc_param dcc; enum surface_pixel_format format; enum dc_rotation_angle rotation; bool horizontal_mirror; -- cgit From fafba6de3a142f46c78b937ae9783d2d0cab044d Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Tue, 20 Dec 2016 10:54:38 -0500 Subject: drm/amd/display: track cursor width in ipp Signed-off-by: Tony Cheng Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h index 81de97568d11..e9ed167c9e41 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h @@ -35,8 +35,10 @@ /* IPP RELATED */ struct input_pixel_processor { struct dc_context *ctx; - uint32_t inst; + unsigned int inst; const struct ipp_funcs *funcs; + + unsigned int cusor_width; }; enum ipp_prescale_mode { -- cgit From 3c25e920f011d785725985733ca2625defbf680f Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Tue, 20 Dec 2016 18:48:11 -0500 Subject: drm/amd/display: Reset gamma to NULL after release Signed-off-by: Anthony Koo Reviewed-by: Aric Cyr Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/modules/color/color.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/modules/color/color.c b/drivers/gpu/drm/amd/display/modules/color/color.c index 938867282d04..6d1b20f6bf98 100644 --- a/drivers/gpu/drm/amd/display/modules/color/color.c +++ b/drivers/gpu/drm/amd/display/modules/color/color.c @@ -1748,8 +1748,10 @@ bool mod_color_remove_sink(struct mod_color *mod_color, for (i = 0; i < core_color->num_sinks; i++) { if (core_color->caps[i].sink == sink) { - if (core_color->state[i].gamma) + if (core_color->state[i].gamma) { dc_gamma_release(core_color->state[i].gamma); + core_color->state[i].gamma = NULL; + } /* To remove this sink, shift everything after down */ for (j = i; j < core_color->num_sinks - 1; j++) { -- cgit From d7194cf6b8ddf0344e70834397d0b1af2cc5fe05 Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Tue, 20 Dec 2016 20:24:24 -0500 Subject: drm/amd/display: Implement gamma correction using input LUT The dc_gamma in dc_surface will be programmed to the input LUT if provided. If dc_gamma is not provided in dc_surface regamma may be used to emulate gamma. Some refactor and cleanup included as well. Signed-off-by: Aric Cyr Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 17 +- drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c | 29 +- drivers/gpu/drm/amd/display/dc/dc.h | 36 --- drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 10 + drivers/gpu/drm/amd/display/dc/dce/dce_opp.c | 2 - drivers/gpu/drm/amd/display/dc/dce/dce_opp.h | 4 - .../amd/display/dc/dce110/dce110_hw_sequencer.c | 17 +- drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.c | 1 + drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h | 11 +- .../drm/amd/display/dc/dce110/dce110_ipp_gamma.c | 304 ++++++--------------- .../amd/display/dc/dce110/dce110_opp_regamma_v.c | 1 - .../gpu/drm/amd/display/dc/dce110/dce110_opp_v.c | 2 - .../gpu/drm/amd/display/dc/dce110/dce110_opp_v.h | 4 - drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.c | 1 + drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.h | 2 - .../gpu/drm/amd/display/dc/dce80/dce80_ipp_gamma.c | 5 - drivers/gpu/drm/amd/display/dc/inc/gamma_types.h | 38 --- drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h | 4 + drivers/gpu/drm/amd/display/dc/inc/hw/opp.h | 1 - drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 2 - drivers/gpu/drm/amd/display/modules/color/color.c | 6 +- 21 files changed, 138 insertions(+), 359 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/dc/inc/gamma_types.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 364f2c970b6e..f969bfedb368 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -521,14 +521,11 @@ static void fill_gamma_from_crtc( return; for (i = 0; i < NUM_OF_RAW_GAMMA_RAMP_RGB_256; i++) { - gamma->gamma_ramp_rgb256x3x16.red[i] = lut[i].red; - gamma->gamma_ramp_rgb256x3x16.green[i] = lut[i].green; - gamma->gamma_ramp_rgb256x3x16.blue[i] = lut[i].blue; + gamma->red[i] = lut[i].red; + gamma->green[i] = lut[i].green; + gamma->blue[i] = lut[i].blue; } - gamma->type = GAMMA_RAMP_RBG256X3X16; - gamma->size = sizeof(gamma->gamma_ramp_rgb256x3x16); - dc_surface->gamma_correction = gamma; input_tf = dc_create_transfer_func(); @@ -822,6 +819,12 @@ static void fill_stream_properties_from_drm_display_mode( stream->output_color_space = get_output_color_space(timing_out); + { + struct dc_transfer_func *tf = dc_create_transfer_func(); + tf->type = TF_TYPE_PREDEFINED; + tf->tf = TRANSFER_FUNCTION_SRGB; + stream->out_transfer_func = tf; + } } static void fill_audio_info( @@ -3066,7 +3069,7 @@ static bool is_dp_capable_without_timing_msa( dc_read_dpcd(dc, amdgpu_connector->dc_link->link_index, DP_DOWN_STREAM_PORT_COUNT, &dpcd_data, sizeof(dpcd_data)) ) - capable = dpcd_data & DP_MSA_TIMING_PAR_IGNORED? true:false; + capable = (dpcd_data & DP_MSA_TIMING_PAR_IGNORED) ? true:false; return capable; } diff --git a/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c index f33135b53a80..ca2234e4b7d2 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c @@ -573,7 +573,7 @@ static bool find_software_points( uint32_t *index_right, enum hw_point_position *pos) { - const uint32_t max_number = RGB_256X3X16 + 3; + const uint32_t max_number = INPUT_LUT_ENTRIES + 3; struct fixed31_32 left, right; @@ -686,12 +686,12 @@ static bool build_custom_gamma_mapping_coefficients_worker( return false; } - if (index_left >= RGB_256X3X16 + 3) { + if (index_left >= INPUT_LUT_ENTRIES + 3) { BREAK_TO_DEBUGGER(); return false; } - if (index_right >= RGB_256X3X16 + 3) { + if (index_right >= INPUT_LUT_ENTRIES + 3) { BREAK_TO_DEBUGGER(); return false; } @@ -958,20 +958,13 @@ static bool scale_gamma(struct pwl_float_data *pwl_rgb, const struct core_gamma *ramp, struct dividers dividers) { - const struct dc_gamma_ramp_rgb256x3x16 *gamma; + const struct dc_gamma *gamma = &ramp->public; const uint16_t max_driver = 0xFFFF; const uint16_t max_os = 0xFF00; uint16_t scaler = max_os; - uint32_t i; + uint32_t i = 0; struct pwl_float_data *rgb = pwl_rgb; - struct pwl_float_data *rgb_last = rgb + RGB_256X3X16 - 1; - - if (ramp->public.type == GAMMA_RAMP_RBG256X3X16) - gamma = &ramp->public.gamma_ramp_rgb256x3x16; - else - return false; /* invalid option */ - - i = 0; + struct pwl_float_data *rgb_last = rgb + INPUT_LUT_ENTRIES - 1; do { if ((gamma->red[i] > max_os) || @@ -981,7 +974,7 @@ static bool scale_gamma(struct pwl_float_data *pwl_rgb, break; } ++i; - } while (i != RGB_256X3X16); + } while (i != INPUT_LUT_ENTRIES); i = 0; @@ -995,7 +988,7 @@ static bool scale_gamma(struct pwl_float_data *pwl_rgb, ++rgb; ++i; - } while (i != RGB_256X3X16); + } while (i != INPUT_LUT_ENTRIES); rgb->r = dal_fixed31_32_mul(rgb_last->r, dividers.divider1); @@ -1110,7 +1103,7 @@ static bool calculate_interpolated_hardware_curve( return false; coeff = coeff128; - max_entries += RGB_256X3X16; + max_entries += INPUT_LUT_ENTRIES; /* TODO: float point case */ @@ -1440,13 +1433,13 @@ bool calculate_regamma_params(struct pwl_params *params, coordinates_x = dm_alloc(sizeof(*coordinates_x)*(256 + 3)); if (!coordinates_x) goto coordinates_x_alloc_fail; - rgb_user = dm_alloc(sizeof(*rgb_user) * (FLOAT_GAMMA_RAMP_MAX + 3)); + rgb_user = dm_alloc(sizeof(*rgb_user) * (TRANSFER_FUNC_POINTS + 3)); if (!rgb_user) goto rgb_user_alloc_fail; rgb_regamma = dm_alloc(sizeof(*rgb_regamma) * (256 + 3)); if (!rgb_regamma) goto rgb_regamma_alloc_fail; - rgb_oem = dm_alloc(sizeof(*rgb_oem) * (FLOAT_GAMMA_RAMP_MAX + 3)); + rgb_oem = dm_alloc(sizeof(*rgb_oem) * (TRANSFER_FUNC_POINTS + 3)); if (!rgb_oem) goto rgb_oem_alloc_fail; axix_x_256 = dm_alloc(sizeof(*axix_x_256) * (256 + 3)); diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 478bdee52cd5..0ee6f41b6047 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -183,43 +183,9 @@ void dc_destroy(struct dc **dc); ******************************************************************************/ enum { - RGB_256X3X16 = 256, - FLOAT_GAMMA_RAMP_MAX = 1025, TRANSFER_FUNC_POINTS = 1025 }; -enum dc_gamma_ramp_type { - GAMMA_RAMP_RBG256X3X16, - GAMMA_RAMP_FLOAT, -}; - -struct float_rgb { - struct fixed32_32 red; - struct fixed32_32 green; - struct fixed32_32 blue; -}; - -struct dc_gamma_ramp_float { - struct float_rgb scale; - struct float_rgb offset; - struct float_rgb gamma_curve[FLOAT_GAMMA_RAMP_MAX]; -}; - -struct dc_gamma_ramp_rgb256x3x16 { - uint16_t red[RGB_256X3X16]; - uint16_t green[RGB_256X3X16]; - uint16_t blue[RGB_256X3X16]; -}; - -struct dc_gamma { - enum dc_gamma_ramp_type type; - union { - struct dc_gamma_ramp_rgb256x3x16 gamma_ramp_rgb256x3x16; - struct dc_gamma_ramp_float gamma_ramp_float; - }; - uint32_t size; -}; - enum dc_transfer_func_type { TF_TYPE_PREDEFINED, TF_TYPE_DISTRIBUTED_POINTS, @@ -266,9 +232,7 @@ struct dc_surface { bool horizontal_mirror; enum plane_stereo_format stereo_format; - /* TO BE REMOVED AFTER BELOW TRANSFER FUNCTIONS IMPLEMENTED */ const struct dc_gamma *gamma_correction; - const struct dc_transfer_func *in_transfer_func; }; diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index 499f6b2a31f8..00958bdbb417 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -370,6 +370,16 @@ struct dc_cursor_mi_param { /* IPP related types */ +enum { + INPUT_LUT_ENTRIES = 256 +}; + +struct dc_gamma { + uint16_t red[INPUT_LUT_ENTRIES]; + uint16_t green[INPUT_LUT_ENTRIES]; + uint16_t blue[INPUT_LUT_ENTRIES]; +}; + /* Used by both ipp amd opp functions*/ /* TODO: to be consolidated with enum color_space */ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c index 653f93dd281f..46b128708c7e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c @@ -28,8 +28,6 @@ #include "dce_opp.h" -#include "gamma_types.h" - #include "reg_helper.h" #define REG(reg)\ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h index 1c01a83ecc50..f2828f044b96 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h @@ -29,10 +29,6 @@ #include "opp.h" #include "core_types.h" -#include "gamma_types.h" /* decprecated */ - -struct gamma_parameters; - #define FROM_DCE11_OPP(opp)\ container_of(opp, struct dce110_opp, base) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 2f790753b559..e4cef9da5de1 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -228,10 +228,11 @@ static void build_prescale_params(struct ipp_prescale_params *prescale_params, break; default: ASSERT(false); + break; } } -static bool dce110_set_degamma( +static bool dce110_set_input_transfer_func( struct pipe_ctx *pipe_ctx, const struct core_surface *surface) { @@ -249,6 +250,9 @@ static bool dce110_set_degamma( build_prescale_params(&prescale_params, surface); ipp->funcs->ipp_program_prescale(ipp, &prescale_params); + if (surface->public.gamma_correction) + ipp->funcs->ipp_program_input_lut(ipp, surface->public.gamma_correction); + if (tf == NULL) { /* Default case if no input transfer function specified */ ipp->funcs->ipp_set_degamma(ipp, @@ -272,6 +276,7 @@ static bool dce110_set_degamma( break; default: result = false; + break; } } else { /*TF_TYPE_DISTRIBUTED_POINTS - Not supported in DCE 11*/ @@ -303,8 +308,11 @@ static bool dce110_set_output_transfer_func( opp->funcs->opp_power_on_regamma_lut(opp, true); - if (ramp && calculate_regamma_params( - regamma_params, ramp, surface, stream)) { + if (stream->public.out_transfer_func && + stream->public.out_transfer_func->type == TF_TYPE_PREDEFINED && + stream->public.out_transfer_func->tf == TRANSFER_FUNCTION_SRGB) { + opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_SRGB); + } else if (ramp && calculate_regamma_params(regamma_params, ramp, surface, stream)) { opp->funcs->opp_program_regamma_pwl(opp, regamma_params); opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_USER); } else { @@ -1318,7 +1326,6 @@ enum dc_status dce110_apply_ctx_to_hw( * instead of per pipe. */ struct audio_output audio_output; - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; build_audio_output(pipe_ctx, &audio_output); @@ -1945,7 +1952,7 @@ static const struct hw_sequencer_funcs dce110_funcs = { .set_plane_config = set_plane_config, .update_plane_addr = update_plane_addr, .update_pending_status = dce110_update_pending_status, - .set_input_transfer_func = dce110_set_degamma, + .set_input_transfer_func = dce110_set_input_transfer_func, .set_output_transfer_func = dce110_set_output_transfer_func, .power_down = dce110_power_down, .enable_accelerated_mode = dce110_enable_accelerated_mode, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.c index dd69f6060bb9..86fa7657a756 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.c @@ -35,6 +35,7 @@ static const struct ipp_funcs funcs = { .ipp_cursor_set_attributes = dce110_ipp_cursor_set_attributes, .ipp_cursor_set_position = dce110_ipp_cursor_set_position, .ipp_program_prescale = dce110_ipp_program_prescale, + .ipp_program_input_lut = dce110_ipp_program_input_lut, .ipp_set_degamma = dce110_ipp_set_degamma, }; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h index 56fe3274407c..a374ef2c9d0b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h @@ -28,9 +28,6 @@ #include "ipp.h" -struct gamma_parameters; -struct dev_c_lut; - #define TO_DCE110_IPP(input_pixel_processor)\ container_of(input_pixel_processor, struct dce110_ipp, base) @@ -69,9 +66,9 @@ bool dce110_ipp_set_degamma( void dce110_ipp_program_prescale( struct input_pixel_processor *ipp, struct ipp_prescale_params *params); -/* - * Helper functions to be resused in other ASICs - */ -void dce110_helper_select_lut(struct dce110_ipp *ipp110); + +void dce110_ipp_program_input_lut( + struct input_pixel_processor *ipp, + const struct dc_gamma *gamma); #endif /*__DC_IPP_DCE110_H__*/ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_gamma.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_gamma.c index 79a6a6dd72fc..c68914bf7af0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_gamma.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_gamma.c @@ -32,21 +32,39 @@ #include "dce/dce_11_0_sh_mask.h" #include "dce110_ipp.h" -#include "gamma_types.h" #define DCP_REG(reg)\ - (reg + ipp110->offsets.dcp_offset) + (mm##reg + ipp110->offsets.dcp_offset) + +#define DCP_REG_SET_N(reg_name, n, ...) \ + generic_reg_update_ex(ipp110->base.ctx, \ + DCP_REG(reg_name), \ + 0, n, __VA_ARGS__) + +#define DCP_REG_SET(reg, field1, val1) \ + DCP_REG_SET_N(reg, 1, FD(reg##__##field1), val1) + +#define DCP_REG_SET_2(reg, field1, val1, field2, val2) \ + DCP_REG_SET_N(reg, 2, \ + FD(reg##__##field1), val1, \ + FD(reg##__##field2), val2) + +#define DCP_REG_SET_3(reg, field1, val1, field2, val2, field3, val3) \ + DCP_REG_SET_N(reg, 3, \ + FD(reg##__##field1), val1, \ + FD(reg##__##field2), val2, \ + FD(reg##__##field3), val3) + +#define DCP_REG_UPDATE_N(reg_name, n, ...) \ + generic_reg_update_ex(ipp110->base.ctx, \ + DCP_REG(reg_name), \ + dm_read_reg(ipp110->base.ctx, DCP_REG(reg_name)), \ + n, __VA_ARGS__) + +#define DCP_REG_UPDATE(reg, field, val) \ + DCP_REG_UPDATE_N(reg, 1, FD(reg##__##field), val) -enum { - MAX_INPUT_LUT_ENTRY = 256 -}; -/*PROTOTYPE DECLARATIONS*/ -static void set_lut_inc( - struct dce110_ipp *ipp110, - uint8_t inc, - bool is_float, - bool is_signed); bool dce110_ipp_set_degamma( struct input_pixel_processor *ipp, @@ -61,25 +79,11 @@ bool dce110_ipp_set_degamma( ASSERT(mode == IPP_DEGAMMA_MODE_BYPASS || mode == IPP_DEGAMMA_MODE_HW_sRGB); - set_reg_field_value( - value, - degamma_type, - DEGAMMA_CONTROL, - GRPH_DEGAMMA_MODE); - - set_reg_field_value( - value, - degamma_type, - DEGAMMA_CONTROL, - CURSOR_DEGAMMA_MODE); - - set_reg_field_value( - value, - degamma_type, + DCP_REG_SET_3( DEGAMMA_CONTROL, - CURSOR2_DEGAMMA_MODE); - - dm_write_reg(ipp110->base.ctx, DCP_REG(mmDEGAMMA_CONTROL), value); + GRPH_DEGAMMA_MODE, degamma_type, + CURSOR_DEGAMMA_MODE, degamma_type, + CURSOR2_DEGAMMA_MODE, degamma_type); return true; } @@ -90,214 +94,70 @@ void dce110_ipp_program_prescale( { struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); - uint32_t prescale_control = 0; - uint32_t prescale_value = 0; - uint32_t legacy_lut_control = 0; + /* set to bypass mode first before change */ + DCP_REG_UPDATE(PRESCALE_GRPH_CONTROL, + GRPH_PRESCALE_BYPASS, 1); - prescale_control = dm_read_reg(ipp110->base.ctx, - DCP_REG(mmPRESCALE_GRPH_CONTROL)); + DCP_REG_SET_2(PRESCALE_VALUES_GRPH_R, + GRPH_PRESCALE_SCALE_R, params->scale, + GRPH_PRESCALE_BIAS_R, params->bias); - if (params->mode != IPP_PRESCALE_MODE_BYPASS) { + DCP_REG_SET_2(PRESCALE_VALUES_GRPH_G, + GRPH_PRESCALE_SCALE_G, params->scale, + GRPH_PRESCALE_BIAS_G, params->bias); - set_reg_field_value( - prescale_control, - 0, - PRESCALE_GRPH_CONTROL, - GRPH_PRESCALE_BYPASS); - - /* - * If prescale is in use, then legacy lut should - * be bypassed - */ - legacy_lut_control = dm_read_reg(ipp110->base.ctx, - DCP_REG(mmINPUT_GAMMA_CONTROL)); - - set_reg_field_value( - legacy_lut_control, - 1, - INPUT_GAMMA_CONTROL, - GRPH_INPUT_GAMMA_MODE); - - dm_write_reg(ipp110->base.ctx, - DCP_REG(mmINPUT_GAMMA_CONTROL), - legacy_lut_control); - } else { - set_reg_field_value( - prescale_control, - 1, - PRESCALE_GRPH_CONTROL, - GRPH_PRESCALE_BYPASS); - } + DCP_REG_SET_2(PRESCALE_VALUES_GRPH_B, + GRPH_PRESCALE_SCALE_B, params->scale, + GRPH_PRESCALE_BIAS_B, params->bias); - set_reg_field_value( - prescale_value, - params->scale, - PRESCALE_VALUES_GRPH_R, - GRPH_PRESCALE_SCALE_R); - - set_reg_field_value( - prescale_value, - params->bias, - PRESCALE_VALUES_GRPH_R, - GRPH_PRESCALE_BIAS_R); - - dm_write_reg(ipp110->base.ctx, - DCP_REG(mmPRESCALE_GRPH_CONTROL), - prescale_control); - - dm_write_reg(ipp110->base.ctx, - DCP_REG(mmPRESCALE_VALUES_GRPH_R), - prescale_value); - - dm_write_reg(ipp110->base.ctx, - DCP_REG(mmPRESCALE_VALUES_GRPH_G), - prescale_value); - - dm_write_reg(ipp110->base.ctx, - DCP_REG(mmPRESCALE_VALUES_GRPH_B), - prescale_value); -} - -static void set_lut_inc( - struct dce110_ipp *ipp110, - uint8_t inc, - bool is_float, - bool is_signed) -{ - const uint32_t addr = DCP_REG(mmDC_LUT_CONTROL); - - uint32_t value = dm_read_reg(ipp110->base.ctx, addr); - - set_reg_field_value( - value, - inc, - DC_LUT_CONTROL, - DC_LUT_INC_R); - - set_reg_field_value( - value, - inc, - DC_LUT_CONTROL, - DC_LUT_INC_G); - - set_reg_field_value( - value, - inc, - DC_LUT_CONTROL, - DC_LUT_INC_B); - - set_reg_field_value( - value, - is_float, - DC_LUT_CONTROL, - DC_LUT_DATA_R_FLOAT_POINT_EN); - - set_reg_field_value( - value, - is_float, - DC_LUT_CONTROL, - DC_LUT_DATA_G_FLOAT_POINT_EN); - - set_reg_field_value( - value, - is_float, - DC_LUT_CONTROL, - DC_LUT_DATA_B_FLOAT_POINT_EN); - - set_reg_field_value( - value, - is_signed, - DC_LUT_CONTROL, - DC_LUT_DATA_R_SIGNED_EN); - - set_reg_field_value( - value, - is_signed, - DC_LUT_CONTROL, - DC_LUT_DATA_G_SIGNED_EN); - - set_reg_field_value( - value, - is_signed, - DC_LUT_CONTROL, - DC_LUT_DATA_B_SIGNED_EN); - - dm_write_reg(ipp110->base.ctx, addr, value); + if (params->mode != IPP_PRESCALE_MODE_BYPASS) { + /* If prescale is in use, then legacy lut should be bypassed */ + DCP_REG_UPDATE(PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_BYPASS, 0); + DCP_REG_UPDATE(INPUT_GAMMA_CONTROL, GRPH_INPUT_GAMMA_MODE, 1); + } } -void dce110_helper_select_lut(struct dce110_ipp *ipp110) +static void dce110_helper_select_lut(struct dce110_ipp *ipp110) { - uint32_t value = 0; - - set_lut_inc(ipp110, 0, false, false); - - { - const uint32_t addr = DCP_REG(mmDC_LUT_WRITE_EN_MASK); - - value = dm_read_reg(ipp110->base.ctx, addr); - - /* enable all */ - set_reg_field_value( - value, - 0x7, - DC_LUT_WRITE_EN_MASK, - DC_LUT_WRITE_EN_MASK); - - dm_write_reg(ipp110->base.ctx, addr, value); - } - - { - const uint32_t addr = DCP_REG(mmDC_LUT_RW_MODE); - - value = dm_read_reg(ipp110->base.ctx, addr); + /* enable all */ + DCP_REG_SET(DC_LUT_WRITE_EN_MASK, DC_LUT_WRITE_EN_MASK, 0x7); - set_reg_field_value( - value, - 0, - DC_LUT_RW_MODE, - DC_LUT_RW_MODE); + /* 256 entry mode */ + DCP_REG_UPDATE(DC_LUT_RW_MODE, DC_LUT_RW_MODE, 0); - dm_write_reg(ipp110->base.ctx, addr, value); - } - - { - const uint32_t addr = DCP_REG(mmDC_LUT_CONTROL); + /* LUT-256, unsigned, integer, new u0.12 format */ + DCP_REG_SET_3(DC_LUT_CONTROL, + DC_LUT_DATA_R_FORMAT, 3, + DC_LUT_DATA_G_FORMAT, 3, + DC_LUT_DATA_B_FORMAT, 3); - value = dm_read_reg(ipp110->base.ctx, addr); + /* start from index 0 */ + DCP_REG_SET(DC_LUT_RW_INDEX, DC_LUT_RW_INDEX, 0); +} - /* 00 - new u0.12 */ - set_reg_field_value( - value, - 3, - DC_LUT_CONTROL, - DC_LUT_DATA_R_FORMAT); +void dce110_ipp_program_input_lut( + struct input_pixel_processor *ipp, + const struct dc_gamma *gamma) +{ + int i; + struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); - set_reg_field_value( - value, - 3, - DC_LUT_CONTROL, - DC_LUT_DATA_G_FORMAT); + dce110_helper_select_lut(ipp110); - set_reg_field_value( - value, - 3, - DC_LUT_CONTROL, - DC_LUT_DATA_B_FORMAT); + /* power on LUT memory and give it time to settle */ + DCP_REG_SET(DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, 1); + udelay(10); - dm_write_reg(ipp110->base.ctx, addr, value); + for (i = 0; i < INPUT_LUT_ENTRIES; i++) { + DCP_REG_SET(DC_LUT_SEQ_COLOR, DC_LUT_SEQ_COLOR, gamma->red[i]); + DCP_REG_SET(DC_LUT_SEQ_COLOR, DC_LUT_SEQ_COLOR, gamma->green[i]); + DCP_REG_SET(DC_LUT_SEQ_COLOR, DC_LUT_SEQ_COLOR, gamma->blue[i]); } - { - const uint32_t addr = DCP_REG(mmDC_LUT_RW_INDEX); - - value = dm_read_reg(ipp110->base.ctx, addr); + /* power off LUT memory */ + DCP_REG_SET(DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, 0); - set_reg_field_value( - value, - 0, - DC_LUT_RW_INDEX, - DC_LUT_RW_INDEX); - - dm_write_reg(ipp110->base.ctx, addr, value); - } + /* bypass prescale, enable legacy LUT */ + DCP_REG_UPDATE(PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_BYPASS, 1); + DCP_REG_UPDATE(INPUT_GAMMA_CONTROL, GRPH_INPUT_GAMMA_MODE, 0); } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c index 81fcbc52e4ab..8164aa6bcb00 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c @@ -30,7 +30,6 @@ #include "dce/dce_11_0_sh_mask.h" #include "dce/dce_opp.h" -#include "gamma_types.h" static void power_on_lut(struct output_pixel_processor *opp, bool power_on, bool inputgamma, bool regamma) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c index dfd63a71d214..0a9b384303d0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c @@ -32,8 +32,6 @@ #include "dce/dce_opp.h" #include "dce110_opp_v.h" -#include "gamma_types.h" - /*****************************************/ /* Constructor, Destructor */ /*****************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h index dcdbf86fccc1..ac5937786ce3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h @@ -29,10 +29,6 @@ #include "opp.h" #include "core_types.h" -#include "gamma_types.h" /* decprecated */ - -struct gamma_parameters; - bool dce110_opp_v_construct(struct dce110_opp *opp110, struct dc_context *ctx); diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.c index 86826c229d39..c195acb6e1a6 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.c @@ -37,6 +37,7 @@ static const struct ipp_funcs funcs = { .ipp_cursor_set_attributes = dce110_ipp_cursor_set_attributes, .ipp_cursor_set_position = dce110_ipp_cursor_set_position, .ipp_program_prescale = dce110_ipp_program_prescale, + .ipp_program_input_lut = dce110_ipp_program_input_lut, .ipp_set_degamma = dce110_ipp_set_degamma, }; diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.h b/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.h index d350138e5feb..06e8598d395f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.h +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.h @@ -33,8 +33,6 @@ struct dce110_ipp; struct dce110_ipp_reg_offsets; -struct gamma_parameters; -struct dev_c_lut; bool dce80_ipp_construct( struct dce110_ipp *ipp, diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp_gamma.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp_gamma.c index eacb14e40d52..760168df5290 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp_gamma.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp_gamma.c @@ -34,15 +34,10 @@ #include "dce80_ipp.h" #include "dce110/dce110_ipp.h" -#include "gamma_types.h" #define DCP_REG(reg)\ (reg + ipp80->offsets.dcp_offset) -enum { - MAX_INPUT_LUT_ENTRY = 256 -}; - /*PROTOTYPE DECLARATIONS*/ static void set_legacy_input_gamma_mode( diff --git a/drivers/gpu/drm/amd/display/dc/inc/gamma_types.h b/drivers/gpu/drm/amd/display/dc/inc/gamma_types.h deleted file mode 100644 index 7948d2cc0715..000000000000 --- a/drivers/gpu/drm/amd/display/dc/inc/gamma_types.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ -#ifndef GAMMA_TYPES_H_ - -#define GAMMA_TYPES_H_ - -#include "dc_types.h" - -/* TODO: Used in IPP and OPP */ - -struct dev_c_lut16 { - uint16_t red; - uint16_t green; - uint16_t blue; -}; -#endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h index e9ed167c9e41..0457bc7a44d4 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h @@ -110,6 +110,10 @@ struct ipp_funcs { struct input_pixel_processor *ipp, struct ipp_prescale_params *params); + void (*ipp_program_input_lut)( + struct input_pixel_processor *ipp, + const struct dc_gamma *gamma); + /*** DEGAMMA RELATED ***/ bool (*ipp_set_degamma)( struct input_pixel_processor *ipp, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h index e615997be20e..a1f31a4410a3 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h @@ -30,7 +30,6 @@ #include "transform.h" struct fixed31_32; -struct gamma_parameters; /* TODO: Need cleanup */ enum clamping_range { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 0e803ca83bb9..895c446cebf9 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -28,8 +28,6 @@ #include "core_types.h" #include "timing_generator.h" -struct gamma_parameters; - enum pipe_gating_control { PIPE_GATING_CONTROL_DISABLE = 0, PIPE_GATING_CONTROL_ENABLE, diff --git a/drivers/gpu/drm/amd/display/modules/color/color.c b/drivers/gpu/drm/amd/display/modules/color/color.c index 6d1b20f6bf98..5c578aecf21c 100644 --- a/drivers/gpu/drm/amd/display/modules/color/color.c +++ b/drivers/gpu/drm/amd/display/modules/color/color.c @@ -2433,7 +2433,7 @@ bool mod_color_set_input_gamma_correction(struct mod_color *mod_color, if (surface != NULL) { struct dc_transfer_func *input_tf = - dc_create_transfer_func(core_color->dc); + dc_create_transfer_func(); struct dc_surface_update updates = {0}; if (input_tf != NULL) { @@ -2724,7 +2724,7 @@ bool mod_color_update_gamut_info(struct mod_color *mod_color, /* 3. ---- SET DEGAMMA ---- */ struct dc_transfer_func *input_tf = NULL; - input_tf = dc_create_transfer_func(core_color->dc); + input_tf = dc_create_transfer_func(); if (input_tf != NULL) { input_tf->type = TF_TYPE_PREDEFINED; @@ -2747,7 +2747,7 @@ bool mod_color_update_gamut_info(struct mod_color *mod_color, /* 4. ---- SET REGAMMA ---- */ struct dc_transfer_func *output_tf = NULL; - output_tf = dc_create_transfer_func(core_color->dc); + output_tf = dc_create_transfer_func(); if (output_tf != NULL) { output_tf->type = TF_TYPE_PREDEFINED; -- cgit From 0f4e66cd7dac538adca4b1cac8f36b90db1709e6 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Wed, 21 Dec 2016 11:16:48 -0500 Subject: drm/amd/display: don't crash if stream is NULL when trying to share clocks Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 343114b2680f..eac597d0c790 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -288,6 +288,11 @@ static bool is_sharable_clk_src( if (pipe_with_clk_src->clock_source == NULL) return false; + if (pipe_with_clk_src->stream == NULL) { + ASSERT(0); + return false; + } + if (pipe_with_clk_src->stream->signal == SIGNAL_TYPE_VIRTUAL) return false; -- cgit From 80bd20967261d9438dc814f3e6e904aea053163b Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Wed, 21 Dec 2016 11:13:48 -0500 Subject: drm/amd/display: reset transfer_func to NULL on release Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 4 +++- drivers/gpu/drm/amd/display/dc/core/dc_surface.c | 8 ++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 237436e22720..84e3fbbe23ac 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -89,9 +89,11 @@ static bool construct(struct core_stream *stream, static void destruct(struct core_stream *stream) { dc_sink_release(&stream->sink->public); - if (stream->public.out_transfer_func != NULL) + if (stream->public.out_transfer_func != NULL) { dc_transfer_func_release( stream->public.out_transfer_func); + stream->public.out_transfer_func = NULL; + } } void dc_stream_retain(const struct dc_stream *dc_stream) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index 3ec1f363e43e..cf8fb9a8ce8e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -71,11 +71,15 @@ static bool construct(struct dc_context *ctx, struct surface *surface) static void destruct(struct surface *surface) { - if (surface->protected.public.gamma_correction != NULL) + if (surface->protected.public.gamma_correction != NULL) { dc_gamma_release(surface->protected.public.gamma_correction); - if (surface->protected.public.in_transfer_func != NULL) + surface->protected.public.gamma_correction = NULL; + } + if (surface->protected.public.in_transfer_func != NULL) { dc_transfer_func_release( surface->protected.public.in_transfer_func); + surface->protected.public.in_transfer_func = NULL; + } } /******************************************************************************* -- cgit From 6680b6a1377f944e5369f456fe1b9d193dd4624b Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Wed, 21 Dec 2016 16:48:51 -0500 Subject: drm/amd/display: Fixed crash Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 891075e39ecf..e6010abc9e0d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -167,24 +167,20 @@ static bool stream_adjust_vmin_vmax(struct dc *dc, struct core_stream *core_stream = DC_STREAM_TO_CORE(stream[0]); int i = 0; bool ret = false; - struct pipe_ctx *pipes; - unsigned int underlay_idx = core_dc->res_pool->underlay_pipe_index; for (i = 0; i < MAX_PIPES; i++) { - if (core_dc->current_context->res_ctx.pipe_ctx[i].stream == core_stream - && i != underlay_idx) { + struct pipe_ctx *pipe = &core_dc->current_context->res_ctx.pipe_ctx[i]; - pipes = &core_dc->current_context->res_ctx.pipe_ctx[i]; - core_dc->hwss.set_drr(&pipes, 1, vmin, vmax); + if (pipe->stream == core_stream && pipe->stream_enc) { + core_dc->hwss.set_drr(&pipe, 1, vmin, vmax); /* build and update the info frame */ - resource_build_info_frame(pipes); - core_dc->hwss.update_info_frame(pipes); + resource_build_info_frame(pipe); + core_dc->hwss.update_info_frame(pipe); ret = true; } } - return ret; } -- cgit From 0347c854094c14469ca4be2192e93e773b164741 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 22 Dec 2016 10:25:57 -0500 Subject: drm/amd/display: Fix licensing header Signed-off-by: Harry Wentland Reviewed-by: Anthony Koo Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/modules/color/color_helper.c | 31 +++++++++++++++------- .../drm/amd/display/modules/color/color_helper.h | 30 ++++++++++++++------- 2 files changed, 42 insertions(+), 19 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/modules/color/color_helper.c b/drivers/gpu/drm/amd/display/modules/color/color_helper.c index c47d2962c6d4..ff6779cdd623 100644 --- a/drivers/gpu/drm/amd/display/modules/color/color_helper.c +++ b/drivers/gpu/drm/amd/display/modules/color/color_helper.c @@ -1,15 +1,26 @@ - -/** - * @file - * @date Copyright (c) 2008 Advanced Micro Devices, Inc. (unpublished) +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. * - * @brief Helper functions for color gamut calculation + * Authors: AMD * - * @internal - * All rights reserved. This notice is intended as a precaution against - * inadvertent publication and does not imply publication or any waiver - * of confidentiality. The year included in the foregoing notice is the - * year of creation of the work. */ #include "dm_services.h" diff --git a/drivers/gpu/drm/amd/display/modules/color/color_helper.h b/drivers/gpu/drm/amd/display/modules/color/color_helper.h index b7a7ca4debd7..76575c1dc043 100644 --- a/drivers/gpu/drm/amd/display/modules/color/color_helper.h +++ b/drivers/gpu/drm/amd/display/modules/color/color_helper.h @@ -1,14 +1,26 @@ -/** - * @file - * @date Copyright (c) 2008 Advanced Micro Devices, Inc. (unpublished) +/* + * Copyright 2016 Advanced Micro Devices, Inc. * - * @brief Helper functions for color gamut calculation + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD * - * @internal - * All rights reserved. This notice is intended as a precaution against - * inadvertent publication and does not imply publication or any waiver - * of confidentiality. The year included in the foregoing notice is the - * year of creation of the work. */ #ifndef COLOR_MOD_COLOR_HELPER_H_ -- cgit From 1c4e6bcefd0e70eae4f1145e334955b4b21ebb42 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Thu, 22 Dec 2016 10:48:19 -0500 Subject: drm/amd/display: Fixed split update bug. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index e6010abc9e0d..5e60640df61b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1333,6 +1333,7 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda bool is_new_pipe_surface[MAX_PIPES]; const struct dc_surface *new_surfaces[MAX_SURFACES] = { 0 }; bool need_apply_clk_constraints = false; + bool can_skip_context_building = true; update_surface_trace(dc, updates, surface_count); @@ -1355,17 +1356,26 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda for (i = 0 ; i < surface_count; i++) { struct core_surface *surface = DC_SURFACE_TO_CORE(updates[i].surface); + bool existing_surface = false; new_surfaces[i] = updates[i].surface; + for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - if (surface == pipe_ctx->surface) + if (surface == pipe_ctx->surface) { + existing_surface = true; is_new_pipe_surface[j] = false; + } } + + if (updates[i].plane_info || + updates[i].scaling_info || + !existing_surface) + can_skip_context_building = false; } - if (dc_target) { + if (!can_skip_context_building && dc_target) { struct core_target *target = DC_TARGET_TO_CORE(dc_target); if (core_dc->current_context->target_count == 0) -- cgit From 8c737fcc24b01ef36da5f78aace70d444485abf9 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Thu, 22 Dec 2016 13:07:11 -0500 Subject: drm/amd/display: Fixed crash caused by unnecessary clock source in split pipe. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 20 ++++++++++---------- .../drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 4 ++-- drivers/gpu/drm/amd/display/dc/inc/resource.h | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index eac597d0c790..386b3cc14fbe 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -211,27 +211,28 @@ bool resource_construct( void resource_unreference_clock_source( struct resource_context *res_ctx, - struct clock_source *clock_source) + struct clock_source **clock_source) { int i; for (i = 0; i < res_ctx->pool->clk_src_count; i++) { - if (res_ctx->pool->clock_sources[i] != clock_source) + if (res_ctx->pool->clock_sources[i] != *clock_source) continue; res_ctx->clock_source_ref_count[i]--; if (res_ctx->clock_source_ref_count[i] == 0) - clock_source->funcs->cs_power_down(clock_source); + (*clock_source)->funcs->cs_power_down(*clock_source); break; } - if (res_ctx->pool->dp_clock_source == clock_source) { + if (res_ctx->pool->dp_clock_source == *clock_source) { res_ctx->dp_clock_source_ref_count--; if (res_ctx->dp_clock_source_ref_count == 0) - clock_source->funcs->cs_power_down(clock_source); + (*clock_source)->funcs->cs_power_down(*clock_source); } + *clock_source = NULL; } void resource_reference_clock_source( @@ -288,11 +289,6 @@ static bool is_sharable_clk_src( if (pipe_with_clk_src->clock_source == NULL) return false; - if (pipe_with_clk_src->stream == NULL) { - ASSERT(0); - return false; - } - if (pipe_with_clk_src->stream->signal == SIGNAL_TYPE_VIRTUAL) return false; @@ -1148,6 +1144,10 @@ enum dc_status resource_map_pool_resources( pipe_ctx->stream = stream; copy_pipe_ctx(old_pipe_ctx, pipe_ctx); + /* Split pipe resource, do not acquire back end */ + if (!pipe_ctx->stream_enc) + continue; + set_stream_engine_in_use( &context->res_ctx, pipe_ctx->stream_enc); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index e4cef9da5de1..6a7cb3e9294a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1028,7 +1028,7 @@ static void switch_dp_clock_sources( if (clk_src && clk_src != pipe_ctx->clock_source) { resource_unreference_clock_source( - res_ctx, pipe_ctx->clock_source); + res_ctx, &pipe_ctx->clock_source); pipe_ctx->clock_source = clk_src; resource_reference_clock_source(res_ctx, clk_src); @@ -1056,7 +1056,7 @@ static void reset_single_pipe_hw_ctx( pipe_ctx->mi->funcs->free_mem_input( pipe_ctx->mi, context->target_count); resource_unreference_clock_source( - &context->res_ctx, pipe_ctx->clock_source); + &context->res_ctx, &pipe_ctx->clock_source); dc->hwss.power_down_front_end((struct core_dc *)dc, pipe_ctx); diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index 8dd676de6b07..adf297ec33b6 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -94,7 +94,7 @@ void resource_build_info_frame(struct pipe_ctx *pipe_ctx); void resource_unreference_clock_source( struct resource_context *res_ctx, - struct clock_source *clock_source); + struct clock_source **clock_source); void resource_reference_clock_source( struct resource_context *res_ctx, -- cgit From db96c69ee78845c4f4cadea9fd282fb265253874 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Tue, 20 Dec 2016 18:01:30 -0500 Subject: drm/amd/display: Add refcount debug assert Signed-off-by: Andrey Grodzovsky Signed-off-by: Jordan Lazare Signed-off-by: Tony Cheng Reviewed-by: Andrey Grodzovsky Reviewed-by: Jordan Lazare Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_sink.c | 5 +++-- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 5 ++++- drivers/gpu/drm/amd/display/dc/core/dc_surface.c | 14 +++++++++++--- drivers/gpu/drm/amd/display/dc/core/dc_target.c | 4 +++- 4 files changed, 21 insertions(+), 7 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_sink.c b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c index 67ae799b6f4f..9dff0bfd5b23 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_sink.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c @@ -71,6 +71,7 @@ void dc_sink_retain(const struct dc_sink *dc_sink) { struct sink *sink = DC_SINK_TO_SINK(dc_sink); + ASSERT(sink->ref_count > 0); ++sink->ref_count; } @@ -78,6 +79,7 @@ void dc_sink_release(const struct dc_sink *dc_sink) { struct sink *sink = DC_SINK_TO_SINK(dc_sink); + ASSERT(sink->ref_count > 0); --sink->ref_count; if (sink->ref_count == 0) { @@ -96,8 +98,7 @@ struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params) if (false == construct(sink, init_params)) goto construct_fail; - /* TODO should we move this outside to where the assignment actually happens? */ - dc_sink_retain(&sink->protected.public); + ++sink->ref_count; return &sink->protected.public; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 84e3fbbe23ac..39a6124aa85f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -99,6 +99,8 @@ static void destruct(struct core_stream *stream) void dc_stream_retain(const struct dc_stream *dc_stream) { struct stream *stream = DC_STREAM_TO_STREAM(dc_stream); + + ASSERT(stream->ref_count > 0); stream->ref_count++; } @@ -108,6 +110,7 @@ void dc_stream_release(const struct dc_stream *public) struct core_stream *protected = DC_STREAM_TO_CORE(public); if (public != NULL) { + ASSERT(stream->ref_count > 0); stream->ref_count--; if (stream->ref_count == 0) { @@ -134,7 +137,7 @@ struct dc_stream *dc_create_stream_for_sink( if (false == construct(&stream->protected, dc_sink)) goto construct_fail; - dc_stream_retain(&stream->protected.public); + stream->ref_count++; return &stream->protected.public; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index cf8fb9a8ce8e..6b4c75a78fe8 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -105,7 +105,7 @@ struct dc_surface *dc_create_surface(const struct dc *dc) if (false == construct(core_dc->ctx, surface)) goto construct_fail; - dc_surface_retain(&surface->protected.public); + ++surface->ref_count; return &surface->protected.public; @@ -162,6 +162,7 @@ void dc_surface_retain(const struct dc_surface *dc_surface) { struct surface *surface = DC_SURFACE_TO_SURFACE(dc_surface); + ASSERT(surface->ref_count > 0); ++surface->ref_count; } @@ -169,6 +170,7 @@ void dc_surface_release(const struct dc_surface *dc_surface) { struct surface *surface = DC_SURFACE_TO_SURFACE(dc_surface); + ASSERT(surface->ref_count > 0); --surface->ref_count; if (surface->ref_count == 0) { @@ -181,12 +183,15 @@ void dc_gamma_retain(const struct dc_gamma *dc_gamma) { struct gamma *gamma = DC_GAMMA_TO_GAMMA(dc_gamma); + ASSERT(gamma->ref_count > 0); ++gamma->ref_count; } void dc_gamma_release(const struct dc_gamma *dc_gamma) { struct gamma *gamma = DC_GAMMA_TO_GAMMA(dc_gamma); + + ASSERT(gamma->ref_count > 0); --gamma->ref_count; if (gamma->ref_count == 0) @@ -200,7 +205,7 @@ struct dc_gamma *dc_create_gamma() if (gamma == NULL) goto alloc_fail; - dc_gamma_retain(&gamma->protected.public); + ++gamma->ref_count; return &gamma->protected.public; @@ -212,12 +217,15 @@ void dc_transfer_func_retain(const struct dc_transfer_func *dc_tf) { struct transfer_func *tf = DC_TRANSFER_FUNC_TO_TRANSFER_FUNC(dc_tf); + ASSERT(tf->ref_count > 0); ++tf->ref_count; } void dc_transfer_func_release(const struct dc_transfer_func *dc_tf) { struct transfer_func *tf = DC_TRANSFER_FUNC_TO_TRANSFER_FUNC(dc_tf); + + ASSERT(tf->ref_count > 0); --tf->ref_count; if (tf->ref_count == 0) @@ -231,7 +239,7 @@ struct dc_transfer_func *dc_create_transfer_func() if (tf == NULL) goto alloc_fail; - dc_transfer_func_retain(&tf->protected.public); + ++tf->ref_count; return &tf->protected.public; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_target.c b/drivers/gpu/drm/amd/display/dc/core/dc_target.c index 2531df74871a..d4ecf2da26d2 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_target.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_target.c @@ -71,6 +71,7 @@ void dc_target_retain(const struct dc_target *dc_target) { struct target *target = DC_TARGET_TO_TARGET(dc_target); + ASSERT(target->ref_count > 0); target->ref_count++; } @@ -81,6 +82,7 @@ void dc_target_release(const struct dc_target *dc_target) ASSERT(target->ref_count > 0); target->ref_count--; + if (target->ref_count == 0) { destruct(protected); dm_free(target); @@ -120,7 +122,7 @@ struct dc_target *dc_create_target_for_streams( construct(&target->protected, stream->ctx, dc_streams, stream_count); - dc_target_retain(&target->protected.public); + target->ref_count++; return &target->protected.public; -- cgit From 6a1f8cabc651c20bc00d211aef24ea9174141515 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Thu, 15 Dec 2016 00:53:04 -0500 Subject: drm/amd/display: Pass adev to fill_plane_attr Signed-off-by: Andrey Grodzovsky Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index f969bfedb368..da8bd66f99ee 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -411,6 +411,7 @@ static bool get_fb_info( return true; } static void fill_plane_attributes_from_fb( + struct amdgpu_device *adev, struct dc_surface *surface, const struct amdgpu_framebuffer *amdgpu_fb, bool addReq) { @@ -455,6 +456,7 @@ static void fill_plane_attributes_from_fb( memset(&surface->tiling_info, 0, sizeof(surface->tiling_info)); + /* Fill GFX8 params */ if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE) == DC_ARRAY_2D_TILED_THIN1) { unsigned bankw, bankh, mtaspect, tile_split, num_banks; @@ -540,6 +542,7 @@ static void fill_gamma_from_crtc( } static void fill_plane_attributes( + struct amdgpu_device *adev, struct dc_surface *surface, struct drm_plane_state *state, bool addrReq) { @@ -549,6 +552,7 @@ static void fill_plane_attributes( fill_rects_from_plane_state(state, surface); fill_plane_attributes_from_fb( + crtc->dev->dev_private, surface, amdgpu_fb, addrReq); @@ -662,7 +666,11 @@ static void dm_dc_surface_commit( } /* Surface programming */ - fill_plane_attributes(dc_surface, crtc->primary->state, true); + fill_plane_attributes( + crtc->dev->dev_private, + dc_surface, + crtc->primary->state, + true); dc_surfaces[0] = dc_surface; @@ -3026,6 +3034,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, surface = dc_create_surface(dc); fill_plane_attributes( + crtc->dev->dev_private, surface, plane_state, false); -- cgit From c89a58cd0d1cc940a29a00cc03e441f97fab56e1 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Thu, 22 Dec 2016 14:54:50 -0500 Subject: drm/amd/display: Allow multiple instance of DTO regs Signed-off-by: Tony Cheng Reviewed-by: Jordan Lazare Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h index 8ee00712ef8e..28984c79fc46 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h @@ -76,9 +76,13 @@ struct dce110_clk_src_regs { uint32_t RESYNC_CNTL; uint32_t PIXCLK_RESYNC_CNTL; uint32_t PLL_CNTL; - uint32_t PHASE; - uint32_t MODULO; - uint32_t PIXEL_RATE_CNTL; + + /* below are for DTO. + * todo: should probably use different struct to not waste space + */ + uint32_t PHASE[4]; + uint32_t MODULO[4]; + uint32_t PIXEL_RATE_CNTL[4]; }; struct dce110_clk_src { -- cgit From 1646a6fe746d7e923774994d2020e1707dcda884 Mon Sep 17 00:00:00 2001 From: Andrew Wong Date: Thu, 22 Dec 2016 15:41:30 -0500 Subject: drm/amd/display: DAL3: HDR10 Infoframe encoding - Add HDR metadata struct - Add register programming calculations - Added HDR metadata to surface and update_surface - Add HDR info packet programming for DP port Signed-off-by: Andrew Wong Reviewed-by: Aric Cyr Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 7 ++ drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 115 ++++++++++++++++++++- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 1 - drivers/gpu/drm/amd/display/dc/core/dc_surface.c | 2 + drivers/gpu/drm/amd/display/dc/dc.h | 23 ++++- .../drm/amd/display/dc/dce/dce_stream_encoder.c | 20 +++- .../gpu/drm/amd/display/dc/inc/hw/stream_encoder.h | 2 + .../drm/amd/display/include/hw_sequencer_types.h | 3 +- drivers/gpu/drm/amd/display/modules/color/color.c | 16 +-- .../gpu/drm/amd/display/modules/inc/mod_color.h | 20 +--- 10 files changed, 176 insertions(+), 33 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 5e60640df61b..e368d660362f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1489,6 +1489,9 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda stream->public.out_transfer_func = updates[i].out_transfer_func; } + if (updates[i].hdr_static_metadata) + surface->public.hdr_static_ctx = + *(updates[i].hdr_static_metadata); } } @@ -1522,6 +1525,10 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda } } + if (updates[i].hdr_static_metadata) { + resource_build_info_frame(pipe_ctx); + core_dc->hwss.update_info_frame(pipe_ctx); + } if (is_new_pipe_surface[j] || updates[i].in_transfer_func) core_dc->hwss.set_input_transfer_func( diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 386b3cc14fbe..2b08f5ae5e33 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -32,7 +32,6 @@ #include "timing_generator.h" #include "transform.h" #include "set_mode_types.h" - #include "virtual/virtual_stream_encoder.h" #include "dce80/dce80_resource.h" @@ -1303,6 +1302,13 @@ static void translate_info_frame(const struct hw_info_frame *hw_info_frame, &hw_info_frame->vsc_packet, sizeof(struct hw_info_packet)); } + + if (hw_info_frame->hdrsmd_packet.valid) { + memmove( + &encoder_info_frame->hdrsmd, + &hw_info_frame->hdrsmd_packet, + sizeof(struct hw_info_packet)); + } } static void set_avi_info_frame( @@ -1720,6 +1726,108 @@ static void set_spd_info_packet(struct core_stream *stream, info_packet->valid = true; } +static void set_hdr_static_info_packet( + struct core_surface *surface, + struct core_stream *stream, + struct hw_info_packet *info_packet) +{ + uint16_t i; + enum signal_type signal = stream->signal; + + if (!surface) + return; + + struct dc_hdr_static_metadata hdr_metadata = + surface->public.hdr_static_ctx; + + if (dc_is_hdmi_signal(signal)) { + info_packet->valid = true; + + info_packet->hb0 = 0x87; + info_packet->hb1 = 0x01; + info_packet->hb2 = 0x1A; + i = 1; + } else if (dc_is_dp_signal(signal)) { + info_packet->valid = true; + + info_packet->hb0 = 0x00; + info_packet->hb1 = 0x87; + info_packet->hb2 = 0x1D; + info_packet->hb3 = (0x13 << 2); + i = 2; + } + + uint32_t data; + + data = hdr_metadata.is_hdr; + info_packet->sb[i++] = data ? 0x02 : 0x00; + info_packet->sb[i++] = 0x00; + + data = hdr_metadata.chromaticity_green_x / 2; + info_packet->sb[i++] = data & 0xFF; + info_packet->sb[i++] = (data & 0xFF00) >> 8; + + data = hdr_metadata.chromaticity_green_y / 2; + info_packet->sb[i++] = data & 0xFF; + info_packet->sb[i++] = (data & 0xFF00) >> 8; + + data = hdr_metadata.chromaticity_blue_x / 2; + info_packet->sb[i++] = data & 0xFF; + info_packet->sb[i++] = (data & 0xFF00) >> 8; + + data = hdr_metadata.chromaticity_blue_y / 2; + info_packet->sb[i++] = data & 0xFF; + info_packet->sb[i++] = (data & 0xFF00) >> 8; + + data = hdr_metadata.chromaticity_red_x / 2; + info_packet->sb[i++] = data & 0xFF; + info_packet->sb[i++] = (data & 0xFF00) >> 8; + + data = hdr_metadata.chromaticity_red_y / 2; + info_packet->sb[i++] = data & 0xFF; + info_packet->sb[i++] = (data & 0xFF00) >> 8; + + data = hdr_metadata.chromaticity_white_point_x / 2; + info_packet->sb[i++] = data & 0xFF; + info_packet->sb[i++] = (data & 0xFF00) >> 8; + + data = hdr_metadata.chromaticity_white_point_y / 2; + info_packet->sb[i++] = data & 0xFF; + info_packet->sb[i++] = (data & 0xFF00) >> 8; + + data = hdr_metadata.max_luminance; + info_packet->sb[i++] = data & 0xFF; + info_packet->sb[i++] = (data & 0xFF00) >> 8; + + data = hdr_metadata.min_luminance; + info_packet->sb[i++] = data & 0xFF; + info_packet->sb[i++] = (data & 0xFF00) >> 8; + + data = hdr_metadata.maximum_content_light_level; + info_packet->sb[i++] = data & 0xFF; + info_packet->sb[i++] = (data & 0xFF00) >> 8; + + data = hdr_metadata.maximum_frame_average_light_level; + info_packet->sb[i++] = data & 0xFF; + info_packet->sb[i++] = (data & 0xFF00) >> 8; + + if (dc_is_hdmi_signal(signal)) { + uint32_t checksum = 0; + + checksum += info_packet->hb0; + checksum += info_packet->hb1; + checksum += info_packet->hb2; + + for (i = 1; i <= info_packet->hb2; i++) + checksum += info_packet->sb[i]; + + info_packet->sb[0] = 0x100 - checksum; + } else if (dc_is_dp_signal(signal)) { + info_packet->sb[0] = 0x01; + info_packet->sb[1] = 0x1A; + } +} + static void set_vsc_info_packet(struct core_stream *stream, struct hw_info_packet *info_packet) { @@ -1830,6 +1938,7 @@ void resource_build_info_frame(struct pipe_ctx *pipe_ctx) info_frame.vendor_info_packet.valid = false; info_frame.spd_packet.valid = false; info_frame.vsc_packet.valid = false; + info_frame.hdrsmd_packet.valid = false; signal = pipe_ctx->stream->signal; @@ -1840,9 +1949,13 @@ void resource_build_info_frame(struct pipe_ctx *pipe_ctx) set_vendor_info_packet( pipe_ctx->stream, &info_frame.vendor_info_packet); set_spd_info_packet(pipe_ctx->stream, &info_frame.spd_packet); + set_hdr_static_info_packet(pipe_ctx->surface, + pipe_ctx->stream, &info_frame.hdrsmd_packet); } else if (dc_is_dp_signal(signal)) { set_vsc_info_packet(pipe_ctx->stream, &info_frame.vsc_packet); set_spd_info_packet(pipe_ctx->stream, &info_frame.spd_packet); + set_hdr_static_info_packet(pipe_ctx->surface, + pipe_ctx->stream, &info_frame.hdrsmd_packet); } translate_info_frame(&info_frame, diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 39a6124aa85f..cda67a78dbfd 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -82,7 +82,6 @@ static bool construct(struct core_stream *stream, stream->public.timing.flags.LTE_340MCSC_SCRAMBLE = dc_sink_data->edid_caps.lte_340mcsc_scramble; stream->status.link = &stream->sink->link->public; - return true; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index 6b4c75a78fe8..d962baa477f5 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -66,6 +66,8 @@ struct transfer_func { static bool construct(struct dc_context *ctx, struct surface *surface) { surface->protected.ctx = ctx; + memset(&surface->protected.public.hdr_static_ctx, + 0, sizeof(struct dc_hdr_static_metadata)); return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 0ee6f41b6047..ef9a69759bd5 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -186,6 +186,25 @@ enum { TRANSFER_FUNC_POINTS = 1025 }; +struct dc_hdr_static_metadata { + bool is_hdr; + + /* display chromaticities and white point in units of 0.00001 */ + unsigned int chromaticity_green_x; + unsigned int chromaticity_green_y; + unsigned int chromaticity_blue_x; + unsigned int chromaticity_blue_y; + unsigned int chromaticity_red_x; + unsigned int chromaticity_red_y; + unsigned int chromaticity_white_point_x; + unsigned int chromaticity_white_point_y; + + uint32_t min_luminance; + uint32_t max_luminance; + uint32_t maximum_content_light_level; + uint32_t maximum_frame_average_light_level; +}; + enum dc_transfer_func_type { TF_TYPE_PREDEFINED, TF_TYPE_DISTRIBUTED_POINTS, @@ -232,6 +251,8 @@ struct dc_surface { bool horizontal_mirror; enum plane_stereo_format stereo_format; + struct dc_hdr_static_metadata hdr_static_ctx; + const struct dc_gamma *gamma_correction; const struct dc_transfer_func *in_transfer_func; }; @@ -267,7 +288,7 @@ struct dc_surface_update { */ /* gamma TO BE REMOVED */ struct dc_gamma *gamma; - + struct dc_hdr_static_metadata *hdr_static_metadata; struct dc_transfer_func *in_transfer_func; struct dc_transfer_func *out_transfer_func; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c index b74a29b40a66..82133ab3224d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c @@ -518,6 +518,7 @@ static void dce110_stream_encoder_update_hdmi_info_packets( dce110_update_hdmi_info_packet(enc110, 0, &info_frame->vendor); dce110_update_hdmi_info_packet(enc110, 1, &info_frame->gamut); dce110_update_hdmi_info_packet(enc110, 2, &info_frame->spd); + dce110_update_hdmi_info_packet(enc110, 3, &info_frame->hdrsmd); } } @@ -554,16 +555,25 @@ static void dce110_stream_encoder_update_dp_info_packets( struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); uint32_t value = REG_READ(DP_SEC_CNTL); - if (info_frame->vsc.valid) - dce110_update_generic_info_packet( + dce110_update_generic_info_packet( + enc110, + 0, /* packetIndex */ + &info_frame->vsc); + dce110_update_generic_info_packet( + enc110, + 2, /* packetIndex */ + &info_frame->spd); + dce110_update_generic_info_packet( enc110, - 0, /* packetIndex */ - &info_frame->vsc); + 3, /* packetIndex */ + &info_frame->hdrsmd); /* enable/disable transmission of packet(s). * If enabled, packet transmission begins on the next frame */ - REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP0_ENABLE, info_frame->vsc.valid); + REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP0_ENABLE, info_frame->vsc.valid); + REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP2_ENABLE, info_frame->spd.valid); + REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP3_ENABLE, info_frame->hdrsmd.valid); /* This bit is the master enable bit. * When enabling secondary stream engine, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h index 9caf2b365420..8b4a30459eeb 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h @@ -31,6 +31,8 @@ struct encoder_info_frame { struct encoder_info_packet spd; /* video stream configuration */ struct encoder_info_packet vsc; + /* HDR Static MetaData */ + struct encoder_info_packet hdrsmd; }; struct encoder_unblank_param { diff --git a/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h b/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h index 9a78097e70f3..6bbca1b4d736 100644 --- a/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h +++ b/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h @@ -88,7 +88,7 @@ struct hw_info_packet { uint8_t hb1; uint8_t hb2; uint8_t hb3; - uint8_t sb[28]; + uint8_t sb[32]; }; struct hw_info_frame { @@ -100,6 +100,7 @@ struct hw_info_frame { struct hw_info_packet spd_packet; /* Video Stream Configuration */ struct hw_info_packet vsc_packet; + struct hw_info_packet hdrsmd_packet; }; #endif diff --git a/drivers/gpu/drm/amd/display/modules/color/color.c b/drivers/gpu/drm/amd/display/modules/color/color.c index 5c578aecf21c..599d9f9aa7ca 100644 --- a/drivers/gpu/drm/amd/display/modules/color/color.c +++ b/drivers/gpu/drm/amd/display/modules/color/color.c @@ -74,7 +74,7 @@ struct color_state { struct color_gamut_data destination_gamut; enum color_transfer_func input_transfer_function; enum color_transfer_func output_transfer_function; - struct color_mastering_info mastering_info; + struct dc_hdr_static_metadata mastering_info; }; struct core_color { @@ -1970,7 +1970,7 @@ bool mod_color_set_white_point(struct mod_color *mod_color, bool mod_color_set_mastering_info(struct mod_color *mod_color, const struct dc_stream **streams, int num_streams, - struct color_mastering_info *mastering_info) + const struct dc_hdr_static_metadata *mastering_info) { struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); unsigned int stream_index, sink_index; @@ -1980,14 +1980,14 @@ bool mod_color_set_mastering_info(struct mod_color *mod_color, streams[stream_index]->sink); memcpy(&core_color->state[sink_index].mastering_info, mastering_info, - sizeof(struct color_mastering_info)); + sizeof(struct dc_hdr_static_metadata)); } return true; } bool mod_color_get_mastering_info(struct mod_color *mod_color, const struct dc_sink *sink, - struct color_mastering_info *mastering_info) + struct dc_hdr_static_metadata *mastering_info) { struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); @@ -1995,7 +1995,7 @@ bool mod_color_get_mastering_info(struct mod_color *mod_color, unsigned int sink_index = sink_index_from_sink(core_color, sink); memcpy(mastering_info, &core_color->state[sink_index].mastering_info, - sizeof(struct color_mastering_info)); + sizeof(struct dc_hdr_static_metadata)); return true; } @@ -2756,8 +2756,10 @@ bool mod_color_update_gamut_info(struct mod_color *mod_color, else output_tf->tf = TRANSFER_FUNCTION_SRGB; } + /* 5. ---- POPULATE HDR METADATA ---- */ + core_color->state[sink_index].mastering_info.is_hdr = is_hdr; - /* 5. ---- TODO: UPDATE INFOPACKETS ---- */ + /* 6. ---- TODO: UPDATE INFOPACKETS ---- */ if (!mod_color_update_gamut_to_stream( mod_color, streams, num_streams)) @@ -2769,6 +2771,8 @@ bool mod_color_update_gamut_info(struct mod_color *mod_color, updates[0].gamma = core_color->state[sink_index].gamma; updates[0].in_transfer_func = input_tf; updates[0].out_transfer_func = output_tf; + updates[0].hdr_static_metadata = + &core_color->state[sink_index].mastering_info; dc_update_surfaces_for_target(core_color->dc, updates, 1, NULL); diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_color.h b/drivers/gpu/drm/amd/display/modules/inc/mod_color.h index 670b87fb8bd2..70349a88916c 100644 --- a/drivers/gpu/drm/amd/display/modules/inc/mod_color.h +++ b/drivers/gpu/drm/amd/display/modules/inc/mod_color.h @@ -87,22 +87,6 @@ enum hdr_tf_support_flag { smpte_st2084 = 0x04 }; -struct color_mastering_info { - unsigned int chromaticity_green_x; - unsigned int chromaticity_green_y; - unsigned int chromaticity_blue_x; - unsigned int chromaticity_blue_y; - unsigned int chromaticity_red_x; - unsigned int chromaticity_red_y; - unsigned int chromaticity_white_point_x; - unsigned int chromaticity_white_point_y; - - unsigned int min_luminance; - unsigned int max_luminance; - unsigned int maximum_content_light_level; - unsigned int maximum_frame_average_light_level; -}; - struct mod_color { int dummy; }; @@ -206,11 +190,11 @@ bool mod_color_get_user_enable(struct mod_color *mod_color, bool mod_color_set_mastering_info(struct mod_color *mod_color, const struct dc_stream **streams, int num_streams, - struct color_mastering_info *mastering_info); + const struct dc_hdr_static_metadata *mastering_info); bool mod_color_get_mastering_info(struct mod_color *mod_color, const struct dc_sink *sink, - struct color_mastering_info *mastering_info); + struct dc_hdr_static_metadata *mastering_info); bool mod_color_set_user_enable(struct mod_color *mod_color, const struct dc_stream **streams, int num_streams, -- cgit From dc0bcaf2cafaa7a6023055d13ebf7dcc8c6e00b5 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Fri, 23 Dec 2016 07:12:19 -0500 Subject: drm/amd/display: debug opt disable hdmi deep color Signed-off-by: Tony Cheng Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 1 + drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 3 +++ 2 files changed, 4 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index ef9a69759bd5..823a87224498 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -147,6 +147,7 @@ struct dc_debug { bool disable_power_gate; bool disable_clock_gate; bool disable_dmcu; + bool disable_hdmi_deep_color; }; struct dc { diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index a8a2290d47db..b439a9ee0228 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -993,6 +993,9 @@ bool dce110_link_encoder_construct( enc110->base.features.max_deep_color = COLOR_DEPTH_121212; enc110->base.features.max_hdmi_deep_color = COLOR_DEPTH_121212; + if (enc110->base.ctx->dc->debug.disable_hdmi_deep_color) + enc110->base.features.max_hdmi_deep_color = COLOR_DEPTH_888; + /* set the flag to indicate whether driver poll the I2C data pin * while doing the DP sink detect */ -- cgit From e12078c56c24894b07cd3aae43788b90d6ea390e Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Fri, 23 Dec 2016 07:20:53 -0500 Subject: drm/amd/display: debug option to disable color module fucntionality Signed-off-by: Tony Cheng Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 13 +++++++------ drivers/gpu/drm/amd/display/dc/dc.h | 1 + 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index e368d660362f..aca13d1cd4bb 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1452,8 +1452,11 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda } } - if (updates[i].gamma && updates[i].gamma != - surface->public.gamma_correction) { + if (dc->debug.disable_color_module) + continue; /* skip below color updates */ + + if (updates[i].gamma && + updates[i].gamma != surface->public.gamma_correction) { if (surface->public.gamma_correction != NULL) dc_gamma_release(surface->public. gamma_correction); @@ -1464,8 +1467,7 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda } if (updates[i].in_transfer_func && - updates[i].in_transfer_func != - surface->public.in_transfer_func) { + updates[i].in_transfer_func != surface->public.in_transfer_func) { if (surface->public.in_transfer_func != NULL) dc_transfer_func_release( surface->public. @@ -1478,8 +1480,7 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda } if (updates[i].out_transfer_func && - updates[i].out_transfer_func != - stream->public.out_transfer_func) { + updates[i].out_transfer_func != stream->public.out_transfer_func) { if (stream->public.out_transfer_func != NULL) dc_transfer_func_release( stream->public. diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 823a87224498..23f41b690c02 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -148,6 +148,7 @@ struct dc_debug { bool disable_clock_gate; bool disable_dmcu; bool disable_hdmi_deep_color; + bool disable_color_module; }; struct dc { -- cgit From f79d7749e7381b0ff9d26733f338ad767d75539c Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Fri, 23 Dec 2016 10:53:24 -0500 Subject: drm/amd/display: Don't use target before null check It might blow up. Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_target.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_target.c b/drivers/gpu/drm/amd/display/dc/core/dc_target.c index d4ecf2da26d2..2d25b00b4bff 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_target.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_target.c @@ -151,9 +151,9 @@ bool dc_target_set_cursor_attributes( const struct dc_cursor_attributes *attributes) { int i, j; - struct core_target *target = DC_TARGET_TO_CORE(dc_target); - struct core_dc *core_dc = DC_TO_CORE(target->ctx->dc); - struct resource_context *res_ctx = &core_dc->current_context->res_ctx; + struct core_target *target; + struct core_dc *core_dc; + struct resource_context *res_ctx; bool ret = false; if (NULL == dc_target) { @@ -165,6 +165,10 @@ bool dc_target_set_cursor_attributes( return false; } + target = DC_TARGET_TO_CORE(dc_target); + core_dc = DC_TO_CORE(target->ctx->dc); + res_ctx = &core_dc->current_context->res_ctx; + for (i = 0; i < dc_target->stream_count; i++) { const struct dc_stream *stream = dc_target->streams[i]; -- cgit From d5de97a2b9ec8ba249df6a3e29f20b56285a48dd Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Fri, 23 Dec 2016 10:39:22 -0500 Subject: drm/amd/display: Add missing function to fix crash for DP Test pattern 4 Signed-off-by: Hersen Wu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index b439a9ee0228..6481fb2028ee 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -1472,6 +1472,9 @@ void dce110_link_encoder_dp_set_phy_pattern( case DP_TEST_PATTERN_TRAINING_PATTERN3: dce110_link_encoder_set_dp_phy_pattern_training_pattern(enc, 2); break; + case DP_TEST_PATTERN_TRAINING_PATTERN4: + dce110_link_encoder_set_dp_phy_pattern_training_pattern(enc, 3); + break; case DP_TEST_PATTERN_D102: set_dp_phy_pattern_d102(enc110); break; -- cgit From aff20230b439921d6660eb2ef6d9f6c273d9b240 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Fri, 23 Dec 2016 10:18:08 -0500 Subject: drm/amd/display: Set gamma to NULL at release Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_surface.c | 9 +++++---- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- drivers/gpu/drm/amd/display/modules/color/color.c | 8 +++----- 4 files changed, 10 insertions(+), 11 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index aca13d1cd4bb..12620df7056d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1458,7 +1458,7 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda if (updates[i].gamma && updates[i].gamma != surface->public.gamma_correction) { if (surface->public.gamma_correction != NULL) - dc_gamma_release(surface->public. + dc_gamma_release(&surface->public. gamma_correction); dc_gamma_retain(updates[i].gamma); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index d962baa477f5..d607972b830b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -74,8 +74,7 @@ static bool construct(struct dc_context *ctx, struct surface *surface) static void destruct(struct surface *surface) { if (surface->protected.public.gamma_correction != NULL) { - dc_gamma_release(surface->protected.public.gamma_correction); - surface->protected.public.gamma_correction = NULL; + dc_gamma_release(&surface->protected.public.gamma_correction); } if (surface->protected.public.in_transfer_func != NULL) { dc_transfer_func_release( @@ -189,15 +188,17 @@ void dc_gamma_retain(const struct dc_gamma *dc_gamma) ++gamma->ref_count; } -void dc_gamma_release(const struct dc_gamma *dc_gamma) +void dc_gamma_release(const struct dc_gamma **dc_gamma) { - struct gamma *gamma = DC_GAMMA_TO_GAMMA(dc_gamma); + struct gamma *gamma = DC_GAMMA_TO_GAMMA(*dc_gamma); ASSERT(gamma->ref_count > 0); --gamma->ref_count; if (gamma->ref_count == 0) dm_free(gamma); + + *dc_gamma = NULL; } struct dc_gamma *dc_create_gamma() diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 23f41b690c02..599f8b0894c2 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -318,7 +318,7 @@ void dc_surface_retain(const struct dc_surface *dc_surface); void dc_surface_release(const struct dc_surface *dc_surface); void dc_gamma_retain(const struct dc_gamma *dc_gamma); -void dc_gamma_release(const struct dc_gamma *dc_gamma); +void dc_gamma_release(const struct dc_gamma **dc_gamma); struct dc_gamma *dc_create_gamma(void); void dc_transfer_func_retain(const struct dc_transfer_func *dc_tf); diff --git a/drivers/gpu/drm/amd/display/modules/color/color.c b/drivers/gpu/drm/amd/display/modules/color/color.c index 599d9f9aa7ca..3611de90e1e9 100644 --- a/drivers/gpu/drm/amd/display/modules/color/color.c +++ b/drivers/gpu/drm/amd/display/modules/color/color.c @@ -1557,7 +1557,7 @@ void mod_color_destroy(struct mod_color *mod_color) for (i = 0; i < core_color->num_sinks; i++) if (core_color->state[i].gamma) - dc_gamma_release(core_color->state[i].gamma); + dc_gamma_release(&core_color->state[i].gamma); dm_free(core_color->state); @@ -1749,8 +1749,7 @@ bool mod_color_remove_sink(struct mod_color *mod_color, for (i = 0; i < core_color->num_sinks; i++) { if (core_color->caps[i].sink == sink) { if (core_color->state[i].gamma) { - dc_gamma_release(core_color->state[i].gamma); - core_color->state[i].gamma = NULL; + dc_gamma_release(&core_color->state[i].gamma); } /* To remove this sink, shift everything after down */ @@ -2444,8 +2443,7 @@ bool mod_color_set_input_gamma_correction(struct mod_color *mod_color, if (core_color->state[sink_index].gamma != gamma) { if (core_color->state[sink_index].gamma) dc_gamma_release( - core_color->state[sink_index]. - gamma); + &core_color->state[sink_index].gamma); dc_gamma_retain(gamma); core_color->state[sink_index].gamma = gamma; -- cgit From 5a7a1eebc6199a8e19cc6497cffb3e16d9d55333 Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Fri, 23 Dec 2016 15:13:13 -0500 Subject: drm/amd/display: set HBR3 and TPS4 capable flags Signed-off-by: Hersen Wu Reviewed-by: Zeyu Fan Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 6481fb2028ee..ea4778b6e6d8 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -1068,9 +1068,19 @@ bool dce110_link_encoder_construct( &bp_cap_info)) enc110->base.features.flags.bits.IS_HBR2_CAPABLE = bp_cap_info.DP_HBR2_CAP; + enc110->base.features.flags.bits.IS_HBR3_CAPABLE = + bp_cap_info.DP_HBR3_EN; + } + + /* TODO: check PPLIB maxPhyClockInKHz <= 540000, if yes, + * IS_HBR3_CAPABLE = 0. + */ + /* test pattern 3 support */ enc110->base.features.flags.bits.IS_TPS3_CAPABLE = true; + /* test pattern 4 support */ + enc110->base.features.flags.bits.IS_TPS4_CAPABLE = true; enc110->base.features.flags.bits.IS_Y_ONLY_CAPABLE = false; /* -- cgit From afed48a00c26cb6cbe2cfe72ce459dc3e13b42d4 Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Fri, 23 Dec 2016 15:43:04 -0500 Subject: drm/amd/display: Fix color module crash when hotplug monitors. Assume we have two monitors, and monitor 0 is unplugged. This shifts the internal state of index 1 to index 0 by memcpy. This means there are two copies of the gamma pointer previously owned by state[1]. When hotplug occurs, this re-assigns the new display with state[1], which has some garbage left over from before, including the gamma pointer. We should correctly clear unused states and re-initialize correctly. Also, due to async nature of the hotplug and other events like commit, we also need to safe guard against sink that has been removed. Signed-off-by: Anthony Koo Reviewed-by: Aric Cyr Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/modules/color/color.c | 309 ++++++++++++---------- 1 file changed, 175 insertions(+), 134 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/modules/color/color.c b/drivers/gpu/drm/amd/display/modules/color/color.c index 3611de90e1e9..74298c8aad8d 100644 --- a/drivers/gpu/drm/amd/display/modules/color/color.c +++ b/drivers/gpu/drm/amd/display/modules/color/color.c @@ -643,10 +643,10 @@ static void initialize_fix_point_color_values( /* Given a specific dc_sink* this function finds its equivalent * on the dc_sink array and returns the corresponding index */ -static unsigned int sink_index_from_sink(struct core_color *core_color, +static int sink_index_from_sink(struct core_color *core_color, const struct dc_sink *sink) { - unsigned int index = 0; + int index = 0; for (index = 0; index < core_color->num_sinks; index++) if (core_color->caps[index].sink == sink) @@ -654,7 +654,7 @@ static unsigned int sink_index_from_sink(struct core_color *core_color, /* Could not find sink requested */ ASSERT(false); - return index; + return -1; } static void calculate_rgb_matrix_legacy(struct core_color *core_color, @@ -1427,6 +1427,65 @@ static bool update_color_gamut_data(struct color_gamut_data *input_data, return true; } +void initialize_color_state(struct core_color *core_color, int index) +{ + core_color->state[index].user_enable_color_temperature = true; + + core_color->state[index].custom_color_temperature = 6500; + + core_color->state[index].contrast.current = 100; + core_color->state[index].contrast.min = 0; + core_color->state[index].contrast.max = 200; + + core_color->state[index].saturation.current = 100; + core_color->state[index].saturation.min = 0; + core_color->state[index].saturation.max = 200; + + core_color->state[index].brightness.current = 0; + core_color->state[index].brightness.min = -100; + core_color->state[index].brightness.max = 100; + + core_color->state[index].hue.current = 0; + core_color->state[index].hue.min = -30; + core_color->state[index].hue.max = 30; + + core_color->state[index].gamma = NULL; + + core_color->state[index].preferred_quantization_range = + QUANTIZATION_RANGE_FULL; + + core_color->state[index].source_gamut.color_space = + color_space_srgb; + core_color->state[index].source_gamut.white_point = + color_white_point_type_6500k_noon; + core_color->state[index].source_gamut.gamut.blueX = 1500; + core_color->state[index].source_gamut.gamut.blueY = 600; + core_color->state[index].source_gamut.gamut.greenX = 3000; + core_color->state[index].source_gamut.gamut.greenY = 6000; + core_color->state[index].source_gamut.gamut.redX = 6400; + core_color->state[index].source_gamut.gamut.redY = 3300; + core_color->state[index].source_gamut.gamut.whiteX = 3127; + core_color->state[index].source_gamut.gamut.whiteY = 3290; + + core_color->state[index].destination_gamut.color_space = + color_space_srgb; + core_color->state[index].destination_gamut.white_point = + color_white_point_type_6500k_noon; + core_color->state[index].destination_gamut.gamut.blueX = 1500; + core_color->state[index].destination_gamut.gamut.blueY = 600; + core_color->state[index].destination_gamut.gamut.greenX = 3000; + core_color->state[index].destination_gamut.gamut.greenY = 6000; + core_color->state[index].destination_gamut.gamut.redX = 6400; + core_color->state[index].destination_gamut.gamut.redY = 3300; + core_color->state[index].destination_gamut.gamut.whiteX = 3127; + core_color->state[index].destination_gamut.gamut.whiteY = 3290; + + core_color->state[index].input_transfer_function = + transfer_func_srgb; + core_color->state[index].output_transfer_function = + transfer_func_srgb; +} + struct mod_color *mod_color_create(struct dc *dc) { int i = 0; @@ -1452,54 +1511,7 @@ struct mod_color *mod_color_create(struct dc *dc) /*hardcoded to sRGB with 6500 color temperature*/ for (i = 0; i < MOD_COLOR_MAX_CONCURRENT_SINKS; i++) { - core_color->state[i].source_gamut.color_space = - color_space_srgb; - core_color->state[i].source_gamut.white_point = - color_white_point_type_6500k_noon; - core_color->state[i].source_gamut.gamut.blueX = 1500; - core_color->state[i].source_gamut.gamut.blueY = 600; - core_color->state[i].source_gamut.gamut.greenX = 3000; - core_color->state[i].source_gamut.gamut.greenY = 6000; - core_color->state[i].source_gamut.gamut.redX = 6400; - core_color->state[i].source_gamut.gamut.redY = 3300; - core_color->state[i].source_gamut.gamut.whiteX = 3127; - core_color->state[i].source_gamut.gamut.whiteY = 3290; - - core_color->state[i].destination_gamut.color_space = - color_space_srgb; - core_color->state[i].destination_gamut.white_point = - color_white_point_type_6500k_noon; - core_color->state[i].destination_gamut.gamut.blueX = 1500; - core_color->state[i].destination_gamut.gamut.blueY = 600; - core_color->state[i].destination_gamut.gamut.greenX = 3000; - core_color->state[i].destination_gamut.gamut.greenY = 6000; - core_color->state[i].destination_gamut.gamut.redX = 6400; - core_color->state[i].destination_gamut.gamut.redY = 3300; - core_color->state[i].destination_gamut.gamut.whiteX = 3127; - core_color->state[i].destination_gamut.gamut.whiteY = 3290; - - core_color->state[i].input_transfer_function = - transfer_func_srgb; - core_color->state[i].output_transfer_function = - transfer_func_srgb; - - core_color->state[i].custom_color_temperature = 6500; - - core_color->state[i].contrast.current = 100; - core_color->state[i].contrast.min = 0; - core_color->state[i].contrast.max = 200; - - core_color->state[i].saturation.current = 100; - core_color->state[i].saturation.min = 0; - core_color->state[i].saturation.max = 200; - - core_color->state[i].brightness.current = 0; - core_color->state[i].brightness.min = -100; - core_color->state[i].brightness.max = 100; - - core_color->state[i].hue.current = 0; - core_color->state[i].hue.min = -30; - core_color->state[i].hue.max = 30; + initialize_color_state(core_color, i); } if (core_color->state == NULL) @@ -1589,8 +1601,8 @@ bool mod_color_add_sink(struct mod_color *mod_color, const struct dc_sink *sink, if (core_color->num_sinks < MOD_COLOR_MAX_CONCURRENT_SINKS) { dc_sink_retain(sink); core_color->caps[core_color->num_sinks].sink = sink; - core_color->state[core_color->num_sinks]. - user_enable_color_temperature = true; + + initialize_color_state(core_color, core_color->num_sinks); core_color->edid_caps[core_color->num_sinks].colorimetry_caps = edid_caps->colorimetry_caps; @@ -1601,7 +1613,6 @@ bool mod_color_add_sink(struct mod_color *mod_color, const struct dc_sink *sink, flag.save_per_edid = true; flag.save_per_link = false; - if (dm_read_persistent_data(core_dc->ctx, sink, COLOR_REGISTRY_NAME, "enablecolortempadj", @@ -1610,9 +1621,6 @@ bool mod_color_add_sink(struct mod_color *mod_color, const struct dc_sink *sink, core_color->state[core_color->num_sinks]. user_enable_color_temperature = persistent_color_temp_enable; - else - core_color->state[core_color->num_sinks]. - user_enable_color_temperature = true; if (dm_read_persistent_data(core_dc->ctx, sink, COLOR_REGISTRY_NAME, @@ -1622,9 +1630,6 @@ bool mod_color_add_sink(struct mod_color *mod_color, const struct dc_sink *sink, core_color->state[core_color->num_sinks]. custom_color_temperature = persistent_custom_color_temp; - else - core_color->state[core_color->num_sinks]. - custom_color_temperature = 6500; if (dm_read_persistent_data(core_dc->ctx, sink, COLOR_REGISTRY_NAME, @@ -1635,23 +1640,6 @@ bool mod_color_add_sink(struct mod_color *mod_color, const struct dc_sink *sink, memcpy(&core_color->state[core_color->num_sinks]. source_gamut.gamut, &persistent_source_gamut, sizeof(struct color_space_coordinates)); - } else { - core_color->state[core_color->num_sinks]. - source_gamut.gamut.blueX = 1500; - core_color->state[core_color->num_sinks]. - source_gamut.gamut.blueY = 600; - core_color->state[core_color->num_sinks]. - source_gamut.gamut.greenX = 3000; - core_color->state[core_color->num_sinks]. - source_gamut.gamut.greenY = 6000; - core_color->state[core_color->num_sinks]. - source_gamut.gamut.redX = 6400; - core_color->state[core_color->num_sinks]. - source_gamut.gamut.redY = 3300; - core_color->state[core_color->num_sinks]. - source_gamut.gamut.whiteX = 3127; - core_color->state[core_color->num_sinks]. - source_gamut.gamut.whiteY = 3290; } if (dm_read_persistent_data(core_dc->ctx, sink, COLOR_REGISTRY_NAME, @@ -1663,23 +1651,6 @@ bool mod_color_add_sink(struct mod_color *mod_color, const struct dc_sink *sink, destination_gamut.gamut, &persistent_destination_gamut, sizeof(struct color_space_coordinates)); - } else { - core_color->state[core_color->num_sinks]. - destination_gamut.gamut.blueX = 1500; - core_color->state[core_color->num_sinks]. - destination_gamut.gamut.blueY = 600; - core_color->state[core_color->num_sinks]. - destination_gamut.gamut.greenX = 3000; - core_color->state[core_color->num_sinks]. - destination_gamut.gamut.greenY = 6000; - core_color->state[core_color->num_sinks]. - destination_gamut.gamut.redX = 6400; - core_color->state[core_color->num_sinks]. - destination_gamut.gamut.redY = 3300; - core_color->state[core_color->num_sinks]. - destination_gamut.gamut.whiteX = 3127; - core_color->state[core_color->num_sinks]. - destination_gamut.gamut.whiteY = 3290; } if (dm_read_persistent_data(core_dc->ctx, sink, COLOR_REGISTRY_NAME, @@ -1688,9 +1659,6 @@ bool mod_color_add_sink(struct mod_color *mod_color, const struct dc_sink *sink, sizeof(int), &flag)) core_color->state[core_color->num_sinks]. brightness.current = persistent_brightness; - else - core_color->state[core_color->num_sinks]. - brightness.current = 0; if (dm_read_persistent_data(core_dc->ctx, sink, COLOR_REGISTRY_NAME, "contrast", @@ -1698,9 +1666,6 @@ bool mod_color_add_sink(struct mod_color *mod_color, const struct dc_sink *sink, sizeof(int), &flag)) core_color->state[core_color->num_sinks]. contrast.current = persistent_contrast; - else - core_color->state[core_color->num_sinks]. - contrast.current = 100; if (dm_read_persistent_data(core_dc->ctx, sink, COLOR_REGISTRY_NAME, "hue", @@ -1708,9 +1673,6 @@ bool mod_color_add_sink(struct mod_color *mod_color, const struct dc_sink *sink, sizeof(int), &flag)) core_color->state[core_color->num_sinks]. hue.current = persistent_hue; - else - core_color->state[core_color->num_sinks]. - hue.current = 0; if (dm_read_persistent_data(core_dc->ctx, sink, COLOR_REGISTRY_NAME, "saturation", @@ -1718,9 +1680,6 @@ bool mod_color_add_sink(struct mod_color *mod_color, const struct dc_sink *sink, sizeof(int), &flag)) core_color->state[core_color->num_sinks]. saturation.current = persistent_saturation; - else - core_color->state[core_color->num_sinks]. - saturation.current = 100; if (dm_read_persistent_data(core_dc->ctx, sink, COLOR_REGISTRY_NAME, @@ -1730,9 +1689,6 @@ bool mod_color_add_sink(struct mod_color *mod_color, const struct dc_sink *sink, core_color->state[core_color->num_sinks]. preferred_quantization_range = persistent_quantization_range; - else - core_color->state[core_color->num_sinks]. - preferred_quantization_range = QUANTIZATION_RANGE_FULL; core_color->num_sinks++; return true; @@ -1751,6 +1707,10 @@ bool mod_color_remove_sink(struct mod_color *mod_color, if (core_color->state[i].gamma) { dc_gamma_release(&core_color->state[i].gamma); } + memset(&core_color->state[i], 0, + sizeof(struct color_state)); + memset(&core_color->edid_caps[i], 0, + sizeof(struct color_edid_caps)); /* To remove this sink, shift everything after down */ for (j = i; j < core_color->num_sinks - 1; j++) { @@ -1766,6 +1726,11 @@ bool mod_color_remove_sink(struct mod_color *mod_color, sizeof(struct color_edid_caps)); } + memset(&core_color->state[core_color->num_sinks - 1], 0, + sizeof(struct color_state)); + memset(&core_color->edid_caps[core_color->num_sinks - 1], 0, + sizeof(struct color_edid_caps)); + core_color->num_sinks--; dc_sink_release(sink); @@ -1786,11 +1751,14 @@ bool mod_color_update_gamut_to_stream(struct mod_color *mod_color, struct gamut_src_dst_matrix *matrix = dm_alloc(sizeof(struct gamut_src_dst_matrix)); - unsigned int stream_index, sink_index, j; + unsigned int stream_index, j; + int sink_index; for (stream_index = 0; stream_index < num_streams; stream_index++) { sink_index = sink_index_from_sink(core_color, streams[stream_index]->sink); + if (sink_index == -1) + continue; /* Write persistent data in registry*/ flag.save_per_edid = true; @@ -1880,11 +1848,14 @@ bool mod_color_adjust_source_gamut(struct mod_color *mod_color, { struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - unsigned int stream_index, sink_index; + unsigned int stream_index; + int sink_index; for (stream_index = 0; stream_index < num_streams; stream_index++) { sink_index = sink_index_from_sink(core_color, streams[stream_index]->sink); + if (sink_index == -1) + continue; update_color_gamut_data(input_gamut_data, &core_color->state[sink_index].source_gamut); @@ -1903,11 +1874,14 @@ bool mod_color_adjust_source_gamut_and_tf(struct mod_color *mod_color, { struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - unsigned int stream_index, sink_index; + unsigned int stream_index; + int sink_index; for (stream_index = 0; stream_index < num_streams; stream_index++) { sink_index = sink_index_from_sink(core_color, streams[stream_index]->sink); + if (sink_index == -1) + continue; update_color_gamut_data(input_gamut_data, &core_color->state[sink_index].source_gamut); core_color->state[sink_index].input_transfer_function = @@ -1926,11 +1900,14 @@ bool mod_color_adjust_destination_gamut(struct mod_color *mod_color, { struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - unsigned int stream_index, sink_index; + unsigned int stream_index; + int sink_index; for (stream_index = 0; stream_index < num_streams; stream_index++) { sink_index = sink_index_from_sink(core_color, streams[stream_index]->sink); + if (sink_index == -1) + continue; update_color_gamut_data(input_gamut_data, &core_color->state[sink_index].destination_gamut); @@ -1948,12 +1925,15 @@ bool mod_color_set_white_point(struct mod_color *mod_color, { struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - unsigned int stream_index, sink_index; + unsigned int stream_index; + int sink_index; for (stream_index = 0; stream_index < num_streams; stream_index++) { sink_index = sink_index_from_sink(core_color, streams[stream_index]->sink); + if (sink_index == -1) + continue; core_color->state[sink_index].source_gamut.gamut.whiteX = white_point->whiteX; core_color->state[sink_index].source_gamut.gamut.whiteY = @@ -1972,11 +1952,14 @@ bool mod_color_set_mastering_info(struct mod_color *mod_color, const struct dc_hdr_static_metadata *mastering_info) { struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - unsigned int stream_index, sink_index; + unsigned int stream_index; + int sink_index; for (stream_index = 0; stream_index < num_streams; stream_index++) { sink_index = sink_index_from_sink(core_color, streams[stream_index]->sink); + if (sink_index == -1) + continue; memcpy(&core_color->state[sink_index].mastering_info, mastering_info, sizeof(struct dc_hdr_static_metadata)); @@ -1991,7 +1974,10 @@ bool mod_color_get_mastering_info(struct mod_color *mod_color, struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - unsigned int sink_index = sink_index_from_sink(core_color, sink); + int sink_index = sink_index_from_sink(core_color, sink); + + if (sink_index == -1) + return false; memcpy(mastering_info, &core_color->state[sink_index].mastering_info, sizeof(struct dc_hdr_static_metadata)); @@ -2007,11 +1993,14 @@ bool mod_color_set_user_enable(struct mod_color *mod_color, MOD_COLOR_TO_CORE(mod_color); struct core_dc *core_dc = DC_TO_CORE(core_color->dc); struct persistent_data_flag flag; - unsigned int stream_index, sink_index; + unsigned int stream_index; + int sink_index; for (stream_index = 0; stream_index < num_streams; stream_index++) { sink_index = sink_index_from_sink(core_color, streams[stream_index]->sink); + if (sink_index == -1) + continue; core_color->state[sink_index].user_enable_color_temperature = user_enable; @@ -2037,7 +2026,10 @@ bool mod_color_get_user_enable(struct mod_color *mod_color, struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - unsigned int sink_index = sink_index_from_sink(core_color, sink); + int sink_index = sink_index_from_sink(core_color, sink); + + if (sink_index == -1) + return false; *user_enable = core_color->state[sink_index]. user_enable_color_temperature; @@ -2052,7 +2044,10 @@ bool mod_color_get_custom_color_temperature(struct mod_color *mod_color, struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - unsigned int sink_index = sink_index_from_sink(core_color, sink); + int sink_index = sink_index_from_sink(core_color, sink); + + if (sink_index == -1) + return false; *color_temperature = core_color->state[sink_index]. custom_color_temperature; @@ -2068,11 +2063,14 @@ bool mod_color_set_custom_color_temperature(struct mod_color *mod_color, MOD_COLOR_TO_CORE(mod_color); struct core_dc *core_dc = DC_TO_CORE(core_color->dc); struct persistent_data_flag flag; - unsigned int stream_index, sink_index; + unsigned int stream_index; + int sink_index; for (stream_index = 0; stream_index < num_streams; stream_index++) { sink_index = sink_index_from_sink(core_color, streams[stream_index]->sink); + if (sink_index == -1) + continue; core_color->state[sink_index].custom_color_temperature = color_temperature; @@ -2098,7 +2096,10 @@ bool mod_color_get_color_saturation(struct mod_color *mod_color, struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - unsigned int sink_index = sink_index_from_sink(core_color, sink); + int sink_index = sink_index_from_sink(core_color, sink); + + if (sink_index == -1) + return false; *color_saturation = core_color->state[sink_index].saturation; @@ -2112,7 +2113,10 @@ bool mod_color_get_color_contrast(struct mod_color *mod_color, struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - unsigned int sink_index = sink_index_from_sink(core_color, sink); + int sink_index = sink_index_from_sink(core_color, sink); + + if (sink_index == -1) + return false; *color_contrast = core_color->state[sink_index].contrast; @@ -2126,7 +2130,10 @@ bool mod_color_get_color_brightness(struct mod_color *mod_color, struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - unsigned int sink_index = sink_index_from_sink(core_color, sink); + int sink_index = sink_index_from_sink(core_color, sink); + + if (sink_index == -1) + return false; *color_brightness = core_color->state[sink_index].brightness; @@ -2140,7 +2147,10 @@ bool mod_color_get_color_hue(struct mod_color *mod_color, struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - unsigned int sink_index = sink_index_from_sink(core_color, sink); + int sink_index = sink_index_from_sink(core_color, sink); + + if (sink_index == -1) + return false; *color_hue = core_color->state[sink_index].hue; @@ -2154,7 +2164,10 @@ bool mod_color_get_source_gamut(struct mod_color *mod_color, struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - unsigned int sink_index = sink_index_from_sink(core_color, sink); + int sink_index = sink_index_from_sink(core_color, sink); + + if (sink_index == -1) + return false; *source_gamut = core_color->state[sink_index].source_gamut.gamut; @@ -2169,11 +2182,14 @@ bool mod_color_notify_mode_change(struct mod_color *mod_color, struct gamut_src_dst_matrix *matrix = dm_alloc(sizeof(struct gamut_src_dst_matrix)); - unsigned int stream_index, sink_index, j; + unsigned int stream_index, j; + int sink_index; for (stream_index = 0; stream_index < num_streams; stream_index++) { sink_index = sink_index_from_sink(core_color, streams[stream_index]->sink); + if (sink_index == -1) + continue; if (!build_gamut_remap_matrix (core_color->state[sink_index].source_gamut.gamut, @@ -2247,11 +2263,14 @@ bool mod_color_set_brightness(struct mod_color *mod_color, struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); struct core_dc *core_dc = DC_TO_CORE(core_color->dc); struct persistent_data_flag flag; - unsigned int stream_index, sink_index; + unsigned int stream_index; + int sink_index; for (stream_index = 0; stream_index < num_streams; stream_index++) { sink_index = sink_index_from_sink(core_color, streams[stream_index]->sink); + if (sink_index == -1) + continue; struct core_stream *core_stream = DC_STREAM_TO_CORE @@ -2291,11 +2310,14 @@ bool mod_color_set_contrast(struct mod_color *mod_color, struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); struct core_dc *core_dc = DC_TO_CORE(core_color->dc); struct persistent_data_flag flag; - unsigned int stream_index, sink_index; + unsigned int stream_index; + int sink_index; for (stream_index = 0; stream_index < num_streams; stream_index++) { sink_index = sink_index_from_sink(core_color, streams[stream_index]->sink); + if (sink_index == -1) + continue; struct core_stream *core_stream = DC_STREAM_TO_CORE @@ -2335,11 +2357,14 @@ bool mod_color_set_hue(struct mod_color *mod_color, struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); struct core_dc *core_dc = DC_TO_CORE(core_color->dc); struct persistent_data_flag flag; - unsigned int stream_index, sink_index; + unsigned int stream_index; + int sink_index; for (stream_index = 0; stream_index < num_streams; stream_index++) { sink_index = sink_index_from_sink(core_color, streams[stream_index]->sink); + if (sink_index == -1) + continue; struct core_stream *core_stream = DC_STREAM_TO_CORE @@ -2378,11 +2403,14 @@ bool mod_color_set_saturation(struct mod_color *mod_color, struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); struct core_dc *core_dc = DC_TO_CORE(core_color->dc); struct persistent_data_flag flag; - unsigned int stream_index, sink_index; + unsigned int stream_index; + int sink_index; for (stream_index = 0; stream_index < num_streams; stream_index++) { sink_index = sink_index_from_sink(core_color, streams[stream_index]->sink); + if (sink_index == -1) + continue; struct core_stream *core_stream = DC_STREAM_TO_CORE @@ -2420,11 +2448,14 @@ bool mod_color_set_input_gamma_correction(struct mod_color *mod_color, struct dc_gamma *gamma) { struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - unsigned int stream_index, sink_index; + unsigned int stream_index; + int sink_index; for (stream_index = 0; stream_index < num_streams; stream_index++) { sink_index = sink_index_from_sink(core_color, streams[stream_index]->sink); + if (sink_index == -1) + continue; struct dc_surface *surface = dc_stream_to_surface_from_pipe_ctx(core_color, @@ -2471,9 +2502,12 @@ bool mod_color_persist_user_preferred_quantization_range( struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); struct core_dc *core_dc = DC_TO_CORE(core_color->dc); struct persistent_data_flag flag; - unsigned int sink_index; + int sink_index; sink_index = sink_index_from_sink(core_color, sink); + if (sink_index == -1) + return false; + if (core_color->state[sink_index]. preferred_quantization_range != quantization_range) { core_color->state[sink_index].preferred_quantization_range = @@ -2498,7 +2532,11 @@ bool mod_color_get_preferred_quantization_range(struct mod_color *mod_color, enum dc_quantization_range *quantization_range) { struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - unsigned int sink_index = sink_index_from_sink(core_color, sink); + int sink_index = sink_index_from_sink(core_color, sink); + + if (sink_index == -1) + return false; + enum dc_quantization_range user_preferred_quantization_range = core_color->state[sink_index]. preferred_quantization_range; @@ -2601,7 +2639,8 @@ bool mod_color_update_gamut_info(struct mod_color *mod_color, const struct dc_stream **streams, int num_streams) { struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - unsigned int stream_index, sink_index; + unsigned int stream_index; + int sink_index; bool should_defer = false; bool is_hdr = false; enum color_color_space source_color_space; @@ -2612,6 +2651,8 @@ bool mod_color_update_gamut_info(struct mod_color *mod_color, for (stream_index = 0; stream_index < num_streams; stream_index++) { sink_index = sink_index_from_sink(core_color, streams[stream_index]->sink); + if (sink_index == -1) + continue; source_color_space = core_color->state[sink_index].source_gamut.color_space; input_transfer_function = -- cgit From 649aa6f4fc40395153834ea78531e0cffd5ee49d Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Fri, 23 Dec 2016 11:08:43 -0500 Subject: drm/amd/display: enable option to disable HDR related updates. Signed-off-by: Tony Cheng Reviewed-by: Anthony Koo Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 12620df7056d..69819d834543 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1526,6 +1526,9 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda } } + if (dc->debug.disable_color_module) + continue; /* skip below color updates */ + if (updates[i].hdr_static_metadata) { resource_build_info_frame(pipe_ctx); core_dc->hwss.update_info_frame(pipe_ctx); -- cgit From 84773406bbe77c0be5abe3b616a78bfb34b128ad Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 29 Dec 2016 15:27:07 -0500 Subject: drm/amd/display: Remove unused color and power modules Signed-off-by: Harry Wentland Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/modules/color/color.c | 2825 -------------------- .../drm/amd/display/modules/color/color_helper.c | 210 -- .../drm/amd/display/modules/color/color_helper.h | 62 - .../gpu/drm/amd/display/modules/inc/mod_color.h | 282 -- .../gpu/drm/amd/display/modules/inc/mod_power.h | 112 - drivers/gpu/drm/amd/display/modules/power/power.c | 784 ------ 6 files changed, 4275 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/modules/color/color.c delete mode 100644 drivers/gpu/drm/amd/display/modules/color/color_helper.c delete mode 100644 drivers/gpu/drm/amd/display/modules/color/color_helper.h delete mode 100644 drivers/gpu/drm/amd/display/modules/inc/mod_color.h delete mode 100644 drivers/gpu/drm/amd/display/modules/inc/mod_power.h delete mode 100644 drivers/gpu/drm/amd/display/modules/power/power.c (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/modules/color/color.c b/drivers/gpu/drm/amd/display/modules/color/color.c deleted file mode 100644 index 74298c8aad8d..000000000000 --- a/drivers/gpu/drm/amd/display/modules/color/color.c +++ /dev/null @@ -1,2825 +0,0 @@ -/* - * Copyright 2016 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" -#include "dc.h" -#include "mod_color.h" -#include "core_types.h" -#include "fixed31_32.h" -#include "core_dc.h" - -#define MOD_COLOR_MAX_CONCURRENT_SINKS 32 -#define DIVIDER 10000 -/* S2D13 value in [-3.00...0.9999] */ -#define S2D13_MIN (-3 * DIVIDER) -#define S2D13_MAX (3 * DIVIDER) -#define S0D13_MIN (-1 * DIVIDER) -#define S0D13_MAX (1 * DIVIDER) - -struct sink_caps { - const struct dc_sink *sink; -}; - -struct gamut_calculation_matrix { - struct fixed31_32 MTransposed[9]; - struct fixed31_32 XYZtoRGB_Custom[9]; - struct fixed31_32 XYZtoRGB_Ref[9]; - struct fixed31_32 RGBtoXYZ_Final[9]; - - struct fixed31_32 MResult[9]; - struct fixed31_32 fXYZofWhiteRef[9]; - struct fixed31_32 fXYZofRGBRef[9]; -}; - -struct gamut_src_dst_matrix { - struct fixed31_32 rgbCoeffDst[9]; - struct fixed31_32 whiteCoeffDst[3]; - struct fixed31_32 rgbCoeffSrc[9]; - struct fixed31_32 whiteCoeffSrc[3]; -}; - -struct color_state { - bool user_enable_color_temperature; - int custom_color_temperature; - struct color_range contrast; - struct color_range saturation; - struct color_range brightness; - struct color_range hue; - struct dc_gamma *gamma; - enum dc_quantization_range preferred_quantization_range; - - struct color_gamut_data source_gamut; - struct color_gamut_data destination_gamut; - enum color_transfer_func input_transfer_function; - enum color_transfer_func output_transfer_function; - struct dc_hdr_static_metadata mastering_info; -}; - -struct core_color { - struct mod_color public; - struct dc *dc; - int num_sinks; - struct sink_caps *caps; - struct color_state *state; - struct color_edid_caps *edid_caps; -}; - -#define MOD_COLOR_TO_CORE(mod_color)\ - container_of(mod_color, struct core_color, public) - -#define COLOR_REGISTRY_NAME "color_v1" - -/*Matrix Calculation Functions*/ -/** - ***************************************************************************** - * Function: transposeMatrix - * - * @brief - * rotate the matrix 90 degrees clockwise - * rows become a columns and columns to rows - * @param [ in ] M - source matrix - * @param [ in ] Rows - num of Rows of the original matrix - * @param [ in ] Cols - num of Cols of the original matrix - * @param [ out] MTransposed - result matrix - * @return void - * - ***************************************************************************** - */ -static void transpose_matrix(const struct fixed31_32 *M, unsigned int Rows, - unsigned int Cols, struct fixed31_32 *MTransposed) -{ - unsigned int i, j; - - for (i = 0; i < Rows; i++) { - for (j = 0; j < Cols; j++) - MTransposed[(j*Rows)+i] = M[(i*Cols)+j]; - } -} - -/** - ***************************************************************************** - * Function: multiplyMatrices - * - * @brief - * multiplies produce of two matrices: M = M1[ulRows1 x ulCols1] * - * M2[ulCols1 x ulCols2]. - * - * @param [ in ] M1 - first Matrix. - * @param [ in ] M2 - second Matrix. - * @param [ in ] Rows1 - num of Rows of the first Matrix - * @param [ in ] Cols1 - num of Cols of the first Matrix/Num of Rows - * of the second Matrix - * @param [ in ] Cols2 - num of Cols of the second Matrix - * @param [out ] mResult - resulting matrix. - * @return void - * - ***************************************************************************** - */ -static void multiply_matrices(struct fixed31_32 *mResult, - const struct fixed31_32 *M1, - const struct fixed31_32 *M2, unsigned int Rows1, - unsigned int Cols1, unsigned int Cols2) -{ - unsigned int i, j, k; - - for (i = 0; i < Rows1; i++) { - for (j = 0; j < Cols2; j++) { - mResult[(i * Cols2) + j] = dal_fixed31_32_zero; - for (k = 0; k < Cols1; k++) - mResult[(i * Cols2) + j] = - dal_fixed31_32_add - (mResult[(i * Cols2) + j], - dal_fixed31_32_mul(M1[(i * Cols1) + k], - M2[(k * Cols2) + j])); - } - } -} - -/** - ***************************************************************************** - * Function: cFind3X3Det - * - * @brief - * finds determinant of given 3x3 matrix - * - * @param [ in ] m - matrix - * @return determinate whioch could not be zero - * - ***************************************************************************** - */ -static struct fixed31_32 find_3X3_det(const struct fixed31_32 *m) -{ - struct fixed31_32 det, A1, A2, A3; - - A1 = dal_fixed31_32_mul(m[0], - dal_fixed31_32_sub(dal_fixed31_32_mul(m[4], m[8]), - dal_fixed31_32_mul(m[5], m[7]))); - A2 = dal_fixed31_32_mul(m[1], - dal_fixed31_32_sub(dal_fixed31_32_mul(m[3], m[8]), - dal_fixed31_32_mul(m[5], m[6]))); - A3 = dal_fixed31_32_mul(m[2], - dal_fixed31_32_sub(dal_fixed31_32_mul(m[3], m[7]), - dal_fixed31_32_mul(m[4], m[6]))); - det = dal_fixed31_32_add(dal_fixed31_32_sub(A1, A2), A3); - return det; -} - - -/** - ***************************************************************************** - * Function: computeInverseMatrix_3x3 - * - * @brief - * builds inverse matrix - * - * @param [ in ] m - matrix - * @param [ out ] im - result matrix - * @return true if success - * - ***************************************************************************** - */ -static bool compute_inverse_matrix_3x3(const struct fixed31_32 *m, - struct fixed31_32 *im) -{ - struct fixed31_32 determinant = find_3X3_det(m); - - if (dal_fixed31_32_eq(determinant, dal_fixed31_32_zero) == false) { - im[0] = dal_fixed31_32_div(dal_fixed31_32_sub - (dal_fixed31_32_mul(m[4], m[8]), - dal_fixed31_32_mul(m[5], m[7])), determinant); - im[1] = dal_fixed31_32_neg(dal_fixed31_32_div(dal_fixed31_32_sub - (dal_fixed31_32_mul(m[1], m[8]), - dal_fixed31_32_mul(m[2], m[7])), determinant)); - im[2] = dal_fixed31_32_div(dal_fixed31_32_sub - (dal_fixed31_32_mul(m[1], m[5]), - dal_fixed31_32_mul(m[2], m[4])), determinant); - im[3] = dal_fixed31_32_neg(dal_fixed31_32_div(dal_fixed31_32_sub - (dal_fixed31_32_mul(m[3], m[8]), - dal_fixed31_32_mul(m[5], m[6])), determinant)); - im[4] = dal_fixed31_32_div(dal_fixed31_32_sub - (dal_fixed31_32_mul(m[0], m[8]), - dal_fixed31_32_mul(m[2], m[6])), determinant); - im[5] = dal_fixed31_32_neg(dal_fixed31_32_div(dal_fixed31_32_sub - (dal_fixed31_32_mul(m[0], m[5]), - dal_fixed31_32_mul(m[2], m[3])), determinant)); - im[6] = dal_fixed31_32_div(dal_fixed31_32_sub - (dal_fixed31_32_mul(m[3], m[7]), - dal_fixed31_32_mul(m[4], m[6])), determinant); - im[7] = dal_fixed31_32_neg(dal_fixed31_32_div(dal_fixed31_32_sub - (dal_fixed31_32_mul(m[0], m[7]), - dal_fixed31_32_mul(m[1], m[6])), determinant)); - im[8] = dal_fixed31_32_div(dal_fixed31_32_sub - (dal_fixed31_32_mul(m[0], m[4]), - dal_fixed31_32_mul(m[1], m[3])), determinant); - return true; - } - return false; -} - -/** - ***************************************************************************** - * Function: calculateXYZtoRGB_M3x3 - * - * @brief - * Calculates transformation matrix from XYZ coordinates to RBG - * - * @param [ in ] XYZofRGB - primaries XYZ - * @param [ in ] XYZofWhite - white point. - * @param [ out ] XYZtoRGB - RGB primires - * @return true if success - * - ***************************************************************************** - */ -static bool calculate_XYZ_to_RGB_3x3(const struct fixed31_32 *XYZofRGB, - const struct fixed31_32 *XYZofWhite, - struct fixed31_32 *XYZtoRGB) -{ - - struct fixed31_32 MInversed[9]; - struct fixed31_32 SVector[3]; - - /*1. Find Inverse matrix 3x3 of MTransposed*/ - if (!compute_inverse_matrix_3x3(XYZofRGB, MInversed)) - return false; - - /*2. Calculate vector: |Sr Sg Sb| = [MInversed] * |Wx Wy Wz|*/ - multiply_matrices(SVector, MInversed, XYZofWhite, 3, 3, 1); - - /*3. Calculate matrix XYZtoRGB 3x3*/ - XYZtoRGB[0] = dal_fixed31_32_mul(XYZofRGB[0], SVector[0]); - XYZtoRGB[1] = dal_fixed31_32_mul(XYZofRGB[1], SVector[1]); - XYZtoRGB[2] = dal_fixed31_32_mul(XYZofRGB[2], SVector[2]); - - XYZtoRGB[3] = dal_fixed31_32_mul(XYZofRGB[3], SVector[0]); - XYZtoRGB[4] = dal_fixed31_32_mul(XYZofRGB[4], SVector[1]); - XYZtoRGB[5] = dal_fixed31_32_mul(XYZofRGB[5], SVector[2]); - - XYZtoRGB[6] = dal_fixed31_32_mul(XYZofRGB[6], SVector[0]); - XYZtoRGB[7] = dal_fixed31_32_mul(XYZofRGB[7], SVector[1]); - XYZtoRGB[8] = dal_fixed31_32_mul(XYZofRGB[8], SVector[2]); - - return true; -} - -static bool gamut_to_color_matrix( - const struct fixed31_32 *pXYZofRGB,/*destination gamut*/ - const struct fixed31_32 *pXYZofWhite,/*destination of white point*/ - const struct fixed31_32 *pRefXYZofRGB,/*source gamut*/ - const struct fixed31_32 *pRefXYZofWhite,/*source of white point*/ - bool invert, - struct fixed31_32 *tempMatrix3X3) -{ - int i = 0; - struct gamut_calculation_matrix *matrix = - dm_alloc(sizeof(struct gamut_calculation_matrix)); - - struct fixed31_32 *pXYZtoRGB_Temp; - struct fixed31_32 *pXYZtoRGB_Final; - - matrix->fXYZofWhiteRef[0] = pRefXYZofWhite[0]; - matrix->fXYZofWhiteRef[1] = pRefXYZofWhite[1]; - matrix->fXYZofWhiteRef[2] = pRefXYZofWhite[2]; - - - matrix->fXYZofRGBRef[0] = pRefXYZofRGB[0]; - matrix->fXYZofRGBRef[1] = pRefXYZofRGB[1]; - matrix->fXYZofRGBRef[2] = pRefXYZofRGB[2]; - - matrix->fXYZofRGBRef[3] = pRefXYZofRGB[3]; - matrix->fXYZofRGBRef[4] = pRefXYZofRGB[4]; - matrix->fXYZofRGBRef[5] = pRefXYZofRGB[5]; - - matrix->fXYZofRGBRef[6] = pRefXYZofRGB[6]; - matrix->fXYZofRGBRef[7] = pRefXYZofRGB[7]; - matrix->fXYZofRGBRef[8] = pRefXYZofRGB[8]; - - /*default values - unity matrix*/ - while (i < 9) { - if (i == 0 || i == 4 || i == 8) - tempMatrix3X3[i] = dal_fixed31_32_one; - else - tempMatrix3X3[i] = dal_fixed31_32_zero; - i++; - } - - /*1. Decide about the order of calculation. - * bInvert == FALSE --> RGBtoXYZ_Ref * XYZtoRGB_Custom - * bInvert == TRUE --> RGBtoXYZ_Custom * XYZtoRGB_Ref */ - if (invert) { - pXYZtoRGB_Temp = matrix->XYZtoRGB_Custom; - pXYZtoRGB_Final = matrix->XYZtoRGB_Ref; - } else { - pXYZtoRGB_Temp = matrix->XYZtoRGB_Ref; - pXYZtoRGB_Final = matrix->XYZtoRGB_Custom; - } - - /*2. Calculate XYZtoRGB_Ref*/ - transpose_matrix(matrix->fXYZofRGBRef, 3, 3, matrix->MTransposed); - - if (!calculate_XYZ_to_RGB_3x3( - matrix->MTransposed, - matrix->fXYZofWhiteRef, - matrix->XYZtoRGB_Ref)) - goto function_fail; - - /*3. Calculate XYZtoRGB_Custom*/ - transpose_matrix(pXYZofRGB, 3, 3, matrix->MTransposed); - - if (!calculate_XYZ_to_RGB_3x3( - matrix->MTransposed, - pXYZofWhite, - matrix->XYZtoRGB_Custom)) - goto function_fail; - - /*4. Calculate RGBtoXYZ - - * inverse matrix 3x3 of XYZtoRGB_Ref or XYZtoRGB_Custom*/ - if (!compute_inverse_matrix_3x3(pXYZtoRGB_Temp, matrix->RGBtoXYZ_Final)) - goto function_fail; - - /*5. Calculate M(3x3) = RGBtoXYZ * XYZtoRGB*/ - multiply_matrices(matrix->MResult, matrix->RGBtoXYZ_Final, - pXYZtoRGB_Final, 3, 3, 3); - - for (i = 0; i < 9; i++) - tempMatrix3X3[i] = matrix->MResult[i]; - - dm_free(matrix); - - return true; - -function_fail: - dm_free(matrix); - return false; -} - -static bool build_gamut_remap_matrix - (struct color_space_coordinates gamut_description, - struct fixed31_32 *rgb_matrix, - struct fixed31_32 *white_point_matrix) -{ - struct fixed31_32 fixed_blueX = dal_fixed31_32_from_fraction - (gamut_description.blueX, DIVIDER); - struct fixed31_32 fixed_blueY = dal_fixed31_32_from_fraction - (gamut_description.blueY, DIVIDER); - struct fixed31_32 fixed_greenX = dal_fixed31_32_from_fraction - (gamut_description.greenX, DIVIDER); - struct fixed31_32 fixed_greenY = dal_fixed31_32_from_fraction - (gamut_description.greenY, DIVIDER); - struct fixed31_32 fixed_redX = dal_fixed31_32_from_fraction - (gamut_description.redX, DIVIDER); - struct fixed31_32 fixed_redY = dal_fixed31_32_from_fraction - (gamut_description.redY, DIVIDER); - struct fixed31_32 fixed_whiteX = dal_fixed31_32_from_fraction - (gamut_description.whiteX, DIVIDER); - struct fixed31_32 fixed_whiteY = dal_fixed31_32_from_fraction - (gamut_description.whiteY, DIVIDER); - - rgb_matrix[0] = dal_fixed31_32_div(fixed_redX, fixed_redY); - rgb_matrix[1] = dal_fixed31_32_one; - rgb_matrix[2] = dal_fixed31_32_div(dal_fixed31_32_sub - (dal_fixed31_32_sub(dal_fixed31_32_one, fixed_redX), - fixed_redY), fixed_redY); - - rgb_matrix[3] = dal_fixed31_32_div(fixed_greenX, fixed_greenY); - rgb_matrix[4] = dal_fixed31_32_one; - rgb_matrix[5] = dal_fixed31_32_div(dal_fixed31_32_sub - (dal_fixed31_32_sub(dal_fixed31_32_one, fixed_greenX), - fixed_greenY), fixed_greenY); - - rgb_matrix[6] = dal_fixed31_32_div(fixed_blueX, fixed_blueY); - rgb_matrix[7] = dal_fixed31_32_one; - rgb_matrix[8] = dal_fixed31_32_div(dal_fixed31_32_sub - (dal_fixed31_32_sub(dal_fixed31_32_one, fixed_blueX), - fixed_blueY), fixed_blueY); - - white_point_matrix[0] = dal_fixed31_32_div(fixed_whiteX, fixed_whiteY); - white_point_matrix[1] = dal_fixed31_32_one; - white_point_matrix[2] = dal_fixed31_32_div(dal_fixed31_32_sub - (dal_fixed31_32_sub(dal_fixed31_32_one, fixed_whiteX), - fixed_whiteY), fixed_whiteY); - - return true; -} - -static bool check_dc_support(const struct dc *dc) -{ - if (dc->stream_funcs.set_gamut_remap == NULL) - return false; - - return true; -} - -static uint16_t fixed_point_to_int_frac( - struct fixed31_32 arg, - uint8_t integer_bits, - uint8_t fractional_bits) -{ - int32_t numerator; - int32_t divisor = 1 << fractional_bits; - - uint16_t result; - - uint16_t d = (uint16_t)dal_fixed31_32_floor( - dal_fixed31_32_abs( - arg)); - - if (d <= (uint16_t)(1 << integer_bits) - (1 / (uint16_t)divisor)) - numerator = (uint16_t)dal_fixed31_32_floor( - dal_fixed31_32_mul_int( - arg, - divisor)); - else { - numerator = dal_fixed31_32_floor( - dal_fixed31_32_sub( - dal_fixed31_32_from_int( - 1LL << integer_bits), - dal_fixed31_32_recip( - dal_fixed31_32_from_int( - divisor)))); - } - - if (numerator >= 0) - result = (uint16_t)numerator; - else - result = (uint16_t)( - (1 << (integer_bits + fractional_bits + 1)) + numerator); - - if ((result != 0) && dal_fixed31_32_lt( - arg, dal_fixed31_32_zero)) - result |= 1 << (integer_bits + fractional_bits); - - return result; -} - -/** -* convert_float_matrix -* This converts a double into HW register spec defined format S2D13. -* @param : -* @return None -*/ - -static void convert_float_matrix_legacy( - uint16_t *matrix, - struct fixed31_32 *flt, - uint32_t buffer_size) -{ - const struct fixed31_32 min_2_13 = - dal_fixed31_32_from_fraction(S2D13_MIN, DIVIDER); - const struct fixed31_32 max_2_13 = - dal_fixed31_32_from_fraction(S2D13_MAX, DIVIDER); - uint32_t i; - - for (i = 0; i < buffer_size; ++i) { - uint32_t reg_value = - fixed_point_to_int_frac( - dal_fixed31_32_clamp( - flt[i], - min_2_13, - max_2_13), - 2, - 13); - - matrix[i] = (uint16_t)reg_value; - } -} - -static void convert_float_matrix( - uint16_t *matrix, - struct fixed31_32 *flt, - uint32_t buffer_size) -{ - const struct fixed31_32 min_0_13 = - dal_fixed31_32_from_fraction(S0D13_MIN, DIVIDER); - const struct fixed31_32 max_0_13 = - dal_fixed31_32_from_fraction(S0D13_MAX, DIVIDER); - const struct fixed31_32 min_2_13 = - dal_fixed31_32_from_fraction(S2D13_MIN, DIVIDER); - const struct fixed31_32 max_2_13 = - dal_fixed31_32_from_fraction(S2D13_MAX, DIVIDER); - uint32_t i; - uint16_t temp_matrix[12]; - - for (i = 0; i < buffer_size; ++i) { - if (i == 3 || i == 7 || i == 11) { - uint32_t reg_value = - fixed_point_to_int_frac( - dal_fixed31_32_clamp( - flt[i], - min_0_13, - max_0_13), - 2, - 13); - - temp_matrix[i] = (uint16_t)reg_value; - } else { - uint32_t reg_value = - fixed_point_to_int_frac( - dal_fixed31_32_clamp( - flt[i], - min_2_13, - max_2_13), - 2, - 13); - - temp_matrix[i] = (uint16_t)reg_value; - } - } - - matrix[4] = temp_matrix[0]; - matrix[5] = temp_matrix[1]; - matrix[6] = temp_matrix[2]; - matrix[7] = temp_matrix[3]; - - matrix[8] = temp_matrix[4]; - matrix[9] = temp_matrix[5]; - matrix[10] = temp_matrix[6]; - matrix[11] = temp_matrix[7]; - - matrix[0] = temp_matrix[8]; - matrix[1] = temp_matrix[9]; - matrix[2] = temp_matrix[10]; - matrix[3] = temp_matrix[11]; -} - -static int get_hw_value_from_sw_value(int swVal, int swMin, - int swMax, int hwMin, int hwMax) -{ - int dSW = swMax - swMin; /*software adjustment range size*/ - int dHW = hwMax - hwMin; /*hardware adjustment range size*/ - int hwVal; /*HW adjustment value*/ - - /* error case, I preserve the behavior from the predecessor - *getHwStepFromSwHwMinMaxValue (removed in Feb 2013) - *which was the FP version that only computed SCLF (i.e. dHW/dSW). - *it would return 0 in this case so - *hwVal = hwMin from the formula given in @brief - */ - if (dSW == 0) - return hwMin; - - /*it's quite often that ranges match, - *e.g. for overlay colors currently (Feb 2013) - *only brightness has a different - *HW range, and in this case no multiplication or division is needed, - *and if minimums match, no calculation at all - */ - if (dSW != dHW) { - hwVal = (swVal - swMin)*dHW/dSW + hwMin; - } else { - hwVal = swVal; - if (swMin != hwMin) - hwVal += (hwMin - swMin); - } - - return hwVal; -} - -static void initialize_fix_point_color_values( - struct core_color *core_color, - unsigned int sink_index, - struct fixed31_32 *grph_cont, - struct fixed31_32 *grph_sat, - struct fixed31_32 *grph_bright, - struct fixed31_32 *sin_grph_hue, - struct fixed31_32 *cos_grph_hue) -{ - /* Hue adjustment could be negative. -45 ~ +45 */ - struct fixed31_32 hue = - dal_fixed31_32_mul( - dal_fixed31_32_from_fraction - (get_hw_value_from_sw_value - (core_color->state[sink_index].hue.current, - core_color->state[sink_index].hue.min, - core_color->state[sink_index].hue.max, - -30, 30), 180), - dal_fixed31_32_pi); - - *sin_grph_hue = dal_fixed31_32_sin(hue); - *cos_grph_hue = dal_fixed31_32_cos(hue); - - *grph_cont = - dal_fixed31_32_from_fraction(get_hw_value_from_sw_value - (core_color->state[sink_index].contrast.current, - core_color->state[sink_index].contrast.min, - core_color->state[sink_index].contrast.max, - 50, 150), 100); - *grph_sat = - dal_fixed31_32_from_fraction(get_hw_value_from_sw_value - (core_color->state[sink_index].saturation.current, - core_color->state[sink_index].saturation.min, - core_color->state[sink_index].saturation.max, - 0, 200), 100); - *grph_bright = - dal_fixed31_32_from_fraction(get_hw_value_from_sw_value - (core_color->state[sink_index].brightness.current, - core_color->state[sink_index].brightness.min, - core_color->state[sink_index].brightness.max, - -25, 25), 100); -} - - -/* Given a specific dc_sink* this function finds its equivalent - * on the dc_sink array and returns the corresponding index - */ -static int sink_index_from_sink(struct core_color *core_color, - const struct dc_sink *sink) -{ - int index = 0; - - for (index = 0; index < core_color->num_sinks; index++) - if (core_color->caps[index].sink == sink) - return index; - - /* Could not find sink requested */ - ASSERT(false); - return -1; -} - -static void calculate_rgb_matrix_legacy(struct core_color *core_color, - unsigned int sink_index, - struct fixed31_32 *rgb_matrix) -{ - const struct fixed31_32 k1 = - dal_fixed31_32_from_fraction(701000, 1000000); - const struct fixed31_32 k2 = - dal_fixed31_32_from_fraction(236568, 1000000); - const struct fixed31_32 k3 = - dal_fixed31_32_from_fraction(-587000, 1000000); - const struct fixed31_32 k4 = - dal_fixed31_32_from_fraction(464432, 1000000); - const struct fixed31_32 k5 = - dal_fixed31_32_from_fraction(-114000, 1000000); - const struct fixed31_32 k6 = - dal_fixed31_32_from_fraction(-701000, 1000000); - const struct fixed31_32 k7 = - dal_fixed31_32_from_fraction(-299000, 1000000); - const struct fixed31_32 k8 = - dal_fixed31_32_from_fraction(-292569, 1000000); - const struct fixed31_32 k9 = - dal_fixed31_32_from_fraction(413000, 1000000); - const struct fixed31_32 k10 = - dal_fixed31_32_from_fraction(-92482, 1000000); - const struct fixed31_32 k11 = - dal_fixed31_32_from_fraction(-114000, 1000000); - const struct fixed31_32 k12 = - dal_fixed31_32_from_fraction(385051, 1000000); - const struct fixed31_32 k13 = - dal_fixed31_32_from_fraction(-299000, 1000000); - const struct fixed31_32 k14 = - dal_fixed31_32_from_fraction(886000, 1000000); - const struct fixed31_32 k15 = - dal_fixed31_32_from_fraction(-587000, 1000000); - const struct fixed31_32 k16 = - dal_fixed31_32_from_fraction(-741914, 1000000); - const struct fixed31_32 k17 = - dal_fixed31_32_from_fraction(886000, 1000000); - const struct fixed31_32 k18 = - dal_fixed31_32_from_fraction(-144086, 1000000); - - const struct fixed31_32 luma_r = - dal_fixed31_32_from_fraction(299, 1000); - const struct fixed31_32 luma_g = - dal_fixed31_32_from_fraction(587, 1000); - const struct fixed31_32 luma_b = - dal_fixed31_32_from_fraction(114, 1000); - - struct fixed31_32 grph_cont; - struct fixed31_32 grph_sat; - struct fixed31_32 grph_bright; - struct fixed31_32 sin_grph_hue; - struct fixed31_32 cos_grph_hue; - - initialize_fix_point_color_values( - core_color, sink_index, &grph_cont, &grph_sat, - &grph_bright, &sin_grph_hue, &cos_grph_hue); - - /* COEF_1_1 = GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K1 +*/ - /* Sin(GrphHue) * K2))*/ - /* (Cos(GrphHue) * K1 + Sin(GrphHue) * K2)*/ - rgb_matrix[0] = - dal_fixed31_32_add( - dal_fixed31_32_mul(cos_grph_hue, k1), - dal_fixed31_32_mul(sin_grph_hue, k2)); - /* GrphSat * (Cos(GrphHue) * K1 + Sin(GrphHue) * K2 */ - rgb_matrix[0] = dal_fixed31_32_mul(grph_sat, rgb_matrix[0]); - /* (LumaR + GrphSat * (Cos(GrphHue) * K1 + Sin(GrphHue) * K2))*/ - rgb_matrix[0] = dal_fixed31_32_add(luma_r, rgb_matrix[0]); - /* GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K1 + Sin(GrphHue)**/ - /* K2))*/ - rgb_matrix[0] = dal_fixed31_32_mul(grph_cont, rgb_matrix[0]); - - /* COEF_1_2 = GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K3 +*/ - /* Sin(GrphHue) * K4))*/ - /* (Cos(GrphHue) * K3 + Sin(GrphHue) * K4)*/ - rgb_matrix[1] = - dal_fixed31_32_add( - dal_fixed31_32_mul(cos_grph_hue, k3), - dal_fixed31_32_mul(sin_grph_hue, k4)); - /* GrphSat * (Cos(GrphHue) * K3 + Sin(GrphHue) * K4)*/ - rgb_matrix[1] = dal_fixed31_32_mul(grph_sat, rgb_matrix[1]); - /* (LumaG + GrphSat * (Cos(GrphHue) * K3 + Sin(GrphHue) * K4))*/ - rgb_matrix[1] = dal_fixed31_32_add(luma_g, rgb_matrix[1]); - /* GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K3 + Sin(GrphHue)**/ - /* K4))*/ - rgb_matrix[1] = dal_fixed31_32_mul(grph_cont, rgb_matrix[1]); - - /* COEF_1_3 = GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K5 +*/ - /* Sin(GrphHue) * K6))*/ - /* (Cos(GrphHue) * K5 + Sin(GrphHue) * K6)*/ - rgb_matrix[2] = - dal_fixed31_32_add( - dal_fixed31_32_mul(cos_grph_hue, k5), - dal_fixed31_32_mul(sin_grph_hue, k6)); - /* GrphSat * (Cos(GrphHue) * K5 + Sin(GrphHue) * K6)*/ - rgb_matrix[2] = dal_fixed31_32_mul(grph_sat, rgb_matrix[2]); - /* LumaB + GrphSat * (Cos(GrphHue) * K5 + Sin(GrphHue) * K6)*/ - rgb_matrix[2] = dal_fixed31_32_add(luma_b, rgb_matrix[2]); - /* GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K5 + Sin(GrphHue)**/ - /* K6))*/ - rgb_matrix[2] = dal_fixed31_32_mul(grph_cont, rgb_matrix[2]); - - /* COEF_1_4 = GrphBright*/ - rgb_matrix[3] = grph_bright; - - /* COEF_2_1 = GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K7 +*/ - /* Sin(GrphHue) * K8))*/ - /* (Cos(GrphHue) * K7 + Sin(GrphHue) * K8)*/ - rgb_matrix[4] = - dal_fixed31_32_add( - dal_fixed31_32_mul(cos_grph_hue, k7), - dal_fixed31_32_mul(sin_grph_hue, k8)); - /* GrphSat * (Cos(GrphHue) * K7 + Sin(GrphHue) * K8)*/ - rgb_matrix[4] = dal_fixed31_32_mul(grph_sat, rgb_matrix[4]); - /* (LumaR + GrphSat * (Cos(GrphHue) * K7 + Sin(GrphHue) * K8))*/ - rgb_matrix[4] = dal_fixed31_32_add(luma_r, rgb_matrix[4]); - /* GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K7 + Sin(GrphHue)**/ - /* K8))*/ - rgb_matrix[4] = dal_fixed31_32_mul(grph_cont, rgb_matrix[4]); - - /* COEF_2_2 = GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K9 +*/ - /* Sin(GrphHue) * K10))*/ - /* (Cos(GrphHue) * K9 + Sin(GrphHue) * K10))*/ - rgb_matrix[5] = - dal_fixed31_32_add( - dal_fixed31_32_mul(cos_grph_hue, k9), - dal_fixed31_32_mul(sin_grph_hue, k10)); - /* GrphSat * (Cos(GrphHue) * K9 + Sin(GrphHue) * K10))*/ - rgb_matrix[5] = dal_fixed31_32_mul(grph_sat, rgb_matrix[5]); - /* (LumaG + GrphSat * (Cos(GrphHue) * K9 + Sin(GrphHue) * K10))*/ - rgb_matrix[5] = dal_fixed31_32_add(luma_g, rgb_matrix[5]); - /* GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K9 + Sin(GrphHue)**/ - /* K10))*/ - rgb_matrix[5] = dal_fixed31_32_mul(grph_cont, rgb_matrix[5]); - - /* COEF_2_3 = GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K11 +*/ - /* Sin(GrphHue) * K12))*/ - /* (Cos(GrphHue) * K11 + Sin(GrphHue) * K12))*/ - rgb_matrix[6] = - dal_fixed31_32_add( - dal_fixed31_32_mul(cos_grph_hue, k11), - dal_fixed31_32_mul(sin_grph_hue, k12)); - /* GrphSat * (Cos(GrphHue) * K11 + Sin(GrphHue) * K12))*/ - rgb_matrix[6] = dal_fixed31_32_mul(grph_sat, rgb_matrix[6]); - /* (LumaB + GrphSat * (Cos(GrphHue) * K11 + Sin(GrphHue) * K12))*/ - rgb_matrix[6] = dal_fixed31_32_add(luma_b, rgb_matrix[6]); - /* GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K11 + Sin(GrphHue)**/ - /* K12))*/ - rgb_matrix[6] = dal_fixed31_32_mul(grph_cont, rgb_matrix[6]); - - /* COEF_2_4 = GrphBright*/ - rgb_matrix[7] = grph_bright; - - /* COEF_3_1 = GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K13 +*/ - /* Sin(GrphHue) * K14))*/ - /* (Cos(GrphHue) * K13 + Sin(GrphHue) * K14)) */ - rgb_matrix[8] = - dal_fixed31_32_add( - dal_fixed31_32_mul(cos_grph_hue, k13), - dal_fixed31_32_mul(sin_grph_hue, k14)); - /* GrphSat * (Cos(GrphHue) * K13 + Sin(GrphHue) * K14)) */ - rgb_matrix[8] = dal_fixed31_32_mul(grph_sat, rgb_matrix[8]); - /* (LumaR + GrphSat * (Cos(GrphHue) * K13 + Sin(GrphHue) * K14)) */ - rgb_matrix[8] = dal_fixed31_32_add(luma_r, rgb_matrix[8]); - /* GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K13 + Sin(GrphHue)**/ - /* K14)) */ - rgb_matrix[8] = dal_fixed31_32_mul(grph_cont, rgb_matrix[8]); - - /* COEF_3_2 = GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K15 +*/ - /* Sin(GrphHue) * K16)) */ - /* GrphSat * (Cos(GrphHue) * K15 + Sin(GrphHue) * K16) */ - rgb_matrix[9] = - dal_fixed31_32_add( - dal_fixed31_32_mul(cos_grph_hue, k15), - dal_fixed31_32_mul(sin_grph_hue, k16)); - /* (LumaG + GrphSat * (Cos(GrphHue) * K15 + Sin(GrphHue) * K16)) */ - rgb_matrix[9] = dal_fixed31_32_mul(grph_sat, rgb_matrix[9]); - /* (LumaG + GrphSat * (Cos(GrphHue) * K15 + Sin(GrphHue) * K16)) */ - rgb_matrix[9] = dal_fixed31_32_add(luma_g, rgb_matrix[9]); - /* GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K15 + Sin(GrphHue)**/ - /* K16)) */ - rgb_matrix[9] = dal_fixed31_32_mul(grph_cont, rgb_matrix[9]); - - /* COEF_3_3 = GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K17 +*/ - /* Sin(GrphHue) * K18)) */ - /* (Cos(GrphHue) * K17 + Sin(GrphHue) * K18)) */ - rgb_matrix[10] = - dal_fixed31_32_add( - dal_fixed31_32_mul(cos_grph_hue, k17), - dal_fixed31_32_mul(sin_grph_hue, k18)); - /* GrphSat * (Cos(GrphHue) * K17 + Sin(GrphHue) * K18)) */ - rgb_matrix[10] = dal_fixed31_32_mul(grph_sat, rgb_matrix[10]); - /* (LumaB + GrphSat * (Cos(GrphHue) * K17 + Sin(GrphHue) * K18)) */ - rgb_matrix[10] = dal_fixed31_32_add(luma_b, rgb_matrix[10]); - /* GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K17 + Sin(GrphHue)**/ - /* K18)) */ - rgb_matrix[10] = dal_fixed31_32_mul(grph_cont, rgb_matrix[10]); - - /* COEF_3_4 = GrphBright */ - rgb_matrix[11] = grph_bright; -} - -static void calculate_rgb_limited_range_matrix_legacy( - struct core_color *core_color, unsigned int sink_index, - struct fixed31_32 *rgb_matrix) -{ - const struct fixed31_32 k1 = - dal_fixed31_32_from_fraction(701000, 1000000); - const struct fixed31_32 k2 = - dal_fixed31_32_from_fraction(236568, 1000000); - const struct fixed31_32 k3 = - dal_fixed31_32_from_fraction(-587000, 1000000); - const struct fixed31_32 k4 = - dal_fixed31_32_from_fraction(464432, 1000000); - const struct fixed31_32 k5 = - dal_fixed31_32_from_fraction(-114000, 1000000); - const struct fixed31_32 k6 = - dal_fixed31_32_from_fraction(-701000, 1000000); - const struct fixed31_32 k7 = - dal_fixed31_32_from_fraction(-299000, 1000000); - const struct fixed31_32 k8 = - dal_fixed31_32_from_fraction(-292569, 1000000); - const struct fixed31_32 k9 = - dal_fixed31_32_from_fraction(413000, 1000000); - const struct fixed31_32 k10 = - dal_fixed31_32_from_fraction(-92482, 1000000); - const struct fixed31_32 k11 = - dal_fixed31_32_from_fraction(-114000, 1000000); - const struct fixed31_32 k12 = - dal_fixed31_32_from_fraction(385051, 1000000); - const struct fixed31_32 k13 = - dal_fixed31_32_from_fraction(-299000, 1000000); - const struct fixed31_32 k14 = - dal_fixed31_32_from_fraction(886000, 1000000); - const struct fixed31_32 k15 = - dal_fixed31_32_from_fraction(-587000, 1000000); - const struct fixed31_32 k16 = - dal_fixed31_32_from_fraction(-741914, 1000000); - const struct fixed31_32 k17 = - dal_fixed31_32_from_fraction(886000, 1000000); - const struct fixed31_32 k18 = - dal_fixed31_32_from_fraction(-144086, 1000000); - - const struct fixed31_32 luma_r = - dal_fixed31_32_from_fraction(299, 1000); - const struct fixed31_32 luma_g = - dal_fixed31_32_from_fraction(587, 1000); - const struct fixed31_32 luma_b = - dal_fixed31_32_from_fraction(114, 1000); - const struct fixed31_32 luma_scale = - dal_fixed31_32_from_fraction(875855, 1000000); - - const struct fixed31_32 rgb_scale = - dal_fixed31_32_from_fraction(85546875, 100000000); - const struct fixed31_32 rgb_bias = - dal_fixed31_32_from_fraction(625, 10000); - - struct fixed31_32 grph_cont; - struct fixed31_32 grph_sat; - struct fixed31_32 grph_bright; - struct fixed31_32 sin_grph_hue; - struct fixed31_32 cos_grph_hue; - - initialize_fix_point_color_values( - core_color, sink_index, &grph_cont, &grph_sat, - &grph_bright, &sin_grph_hue, &cos_grph_hue); - - /* COEF_1_1 = GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K1 +*/ - /* Sin(GrphHue) * K2))*/ - /* (Cos(GrphHue) * K1 + Sin(GrphHue) * K2)*/ - rgb_matrix[0] = - dal_fixed31_32_add( - dal_fixed31_32_mul(cos_grph_hue, k1), - dal_fixed31_32_mul(sin_grph_hue, k2)); - /* GrphSat * (Cos(GrphHue) * K1 + Sin(GrphHue) * K2 */ - rgb_matrix[0] = dal_fixed31_32_mul(grph_sat, rgb_matrix[0]); - /* (LumaR + GrphSat * (Cos(GrphHue) * K1 + Sin(GrphHue) * K2))*/ - rgb_matrix[0] = dal_fixed31_32_add(luma_r, rgb_matrix[0]); - /* GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K1 + Sin(GrphHue)**/ - /* K2))*/ - rgb_matrix[0] = dal_fixed31_32_mul(grph_cont, rgb_matrix[0]); - /* LumaScale * GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K1 + */ - /* Sin(GrphHue) * K2))*/ - rgb_matrix[0] = dal_fixed31_32_mul(luma_scale, rgb_matrix[0]); - - /* COEF_1_2 = GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K3 +*/ - /* Sin(GrphHue) * K4))*/ - /* (Cos(GrphHue) * K3 + Sin(GrphHue) * K4)*/ - rgb_matrix[1] = - dal_fixed31_32_add( - dal_fixed31_32_mul(cos_grph_hue, k3), - dal_fixed31_32_mul(sin_grph_hue, k4)); - /* GrphSat * (Cos(GrphHue) * K3 + Sin(GrphHue) * K4)*/ - rgb_matrix[1] = dal_fixed31_32_mul(grph_sat, rgb_matrix[1]); - /* (LumaG + GrphSat * (Cos(GrphHue) * K3 + Sin(GrphHue) * K4))*/ - rgb_matrix[1] = dal_fixed31_32_add(luma_g, rgb_matrix[1]); - /* GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K3 + Sin(GrphHue)**/ - /* K4))*/ - rgb_matrix[1] = dal_fixed31_32_mul(grph_cont, rgb_matrix[1]); - /* LumaScale * GrphCont * (LumaG + GrphSat *(Cos(GrphHue) * K3 + */ - /* Sin(GrphHue) * K4))*/ - rgb_matrix[1] = dal_fixed31_32_mul(luma_scale, rgb_matrix[1]); - - /* COEF_1_3 = GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K5 +*/ - /* Sin(GrphHue) * K6))*/ - /* (Cos(GrphHue) * K5 + Sin(GrphHue) * K6)*/ - rgb_matrix[2] = - dal_fixed31_32_add( - dal_fixed31_32_mul(cos_grph_hue, k5), - dal_fixed31_32_mul(sin_grph_hue, k6)); - /* GrphSat * (Cos(GrphHue) * K5 + Sin(GrphHue) * K6)*/ - rgb_matrix[2] = dal_fixed31_32_mul(grph_sat, rgb_matrix[2]); - /* LumaB + GrphSat * (Cos(GrphHue) * K5 + Sin(GrphHue) * K6)*/ - rgb_matrix[2] = dal_fixed31_32_add(luma_b, rgb_matrix[2]); - /* GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K5 + Sin(GrphHue)**/ - /* K6))*/ - rgb_matrix[2] = dal_fixed31_32_mul(grph_cont, rgb_matrix[2]); - /* LumaScale * GrphCont * (LumaB + GrphSat *(Cos(GrphHue) * K5 + */ - /* Sin(GrphHue) * K6))*/ - rgb_matrix[2] = dal_fixed31_32_mul(luma_scale, rgb_matrix[2]); - - /* COEF_1_4 = RGBBias + RGBScale * GrphBright*/ - rgb_matrix[3] = dal_fixed31_32_add( - rgb_bias, - dal_fixed31_32_mul(rgb_scale, grph_bright)); - - /* COEF_2_1 = GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K7 +*/ - /* Sin(GrphHue) * K8))*/ - /* (Cos(GrphHue) * K7 + Sin(GrphHue) * K8)*/ - rgb_matrix[4] = - dal_fixed31_32_add( - dal_fixed31_32_mul(cos_grph_hue, k7), - dal_fixed31_32_mul(sin_grph_hue, k8)); - /* GrphSat * (Cos(GrphHue) * K7 + Sin(GrphHue) * K8)*/ - rgb_matrix[4] = dal_fixed31_32_mul(grph_sat, rgb_matrix[4]); - /* (LumaR + GrphSat * (Cos(GrphHue) * K7 + Sin(GrphHue) * K8))*/ - rgb_matrix[4] = dal_fixed31_32_add(luma_r, rgb_matrix[4]); - /* GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K7 + Sin(GrphHue)**/ - /* K8))*/ - rgb_matrix[4] = dal_fixed31_32_mul(grph_cont, rgb_matrix[4]); - /* LumaScale * GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K7 + */ - /* Sin(GrphHue) * K8))*/ - rgb_matrix[4] = dal_fixed31_32_mul(luma_scale, rgb_matrix[4]); - - /* COEF_2_2 = GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K9 +*/ - /* Sin(GrphHue) * K10))*/ - /* (Cos(GrphHue) * K9 + Sin(GrphHue) * K10))*/ - rgb_matrix[5] = - dal_fixed31_32_add( - dal_fixed31_32_mul(cos_grph_hue, k9), - dal_fixed31_32_mul(sin_grph_hue, k10)); - /* GrphSat * (Cos(GrphHue) * K9 + Sin(GrphHue) * K10))*/ - rgb_matrix[5] = dal_fixed31_32_mul(grph_sat, rgb_matrix[5]); - /* (LumaG + GrphSat * (Cos(GrphHue) * K9 + Sin(GrphHue) * K10))*/ - rgb_matrix[5] = dal_fixed31_32_add(luma_g, rgb_matrix[5]); - /* GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K9 + Sin(GrphHue)**/ - /* K10))*/ - rgb_matrix[5] = dal_fixed31_32_mul(grph_cont, rgb_matrix[5]); - /* LumaScale * GrphCont * (LumaG + GrphSat *(Cos(GrphHue) * K9 + */ - /* Sin(GrphHue) * K10))*/ - rgb_matrix[5] = dal_fixed31_32_mul(luma_scale, rgb_matrix[5]); - - /* COEF_2_3 = GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K11 +*/ - /* Sin(GrphHue) * K12))*/ - /* (Cos(GrphHue) * K11 + Sin(GrphHue) * K12))*/ - rgb_matrix[6] = - dal_fixed31_32_add( - dal_fixed31_32_mul(cos_grph_hue, k11), - dal_fixed31_32_mul(sin_grph_hue, k12)); - /* GrphSat * (Cos(GrphHue) * K11 + Sin(GrphHue) * K12))*/ - rgb_matrix[6] = dal_fixed31_32_mul(grph_sat, rgb_matrix[6]); - /* (LumaB + GrphSat * (Cos(GrphHue) * K11 + Sin(GrphHue) * K12))*/ - rgb_matrix[6] = dal_fixed31_32_add(luma_b, rgb_matrix[6]); - /* GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K11 + Sin(GrphHue)**/ - /* K12))*/ - rgb_matrix[6] = dal_fixed31_32_mul(grph_cont, rgb_matrix[6]); - /* LumaScale * GrphCont * (LumaB + GrphSat *(Cos(GrphHue) * K11 +*/ - /* Sin(GrphHue) * K12)) */ - rgb_matrix[6] = dal_fixed31_32_mul(luma_scale, rgb_matrix[6]); - - /* COEF_2_4 = RGBBias + RGBScale * GrphBright*/ - rgb_matrix[7] = dal_fixed31_32_add( - rgb_bias, - dal_fixed31_32_mul(rgb_scale, grph_bright)); - - /* COEF_3_1 = GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K13 +*/ - /* Sin(GrphHue) * K14))*/ - /* (Cos(GrphHue) * K13 + Sin(GrphHue) * K14)) */ - rgb_matrix[8] = - dal_fixed31_32_add( - dal_fixed31_32_mul(cos_grph_hue, k13), - dal_fixed31_32_mul(sin_grph_hue, k14)); - /* GrphSat * (Cos(GrphHue) * K13 + Sin(GrphHue) * K14)) */ - rgb_matrix[8] = dal_fixed31_32_mul(grph_sat, rgb_matrix[8]); - /* (LumaR + GrphSat * (Cos(GrphHue) * K13 + Sin(GrphHue) * K14)) */ - rgb_matrix[8] = dal_fixed31_32_add(luma_r, rgb_matrix[8]); - /* GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K13 + Sin(GrphHue)**/ - /* K14)) */ - rgb_matrix[8] = dal_fixed31_32_mul(grph_cont, rgb_matrix[8]); - /* LumaScale * GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K13 +*/ - /* Sin(GrphHue) * K14))*/ - rgb_matrix[8] = dal_fixed31_32_mul(luma_scale, rgb_matrix[8]); - - /* COEF_3_2 = GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K15 +*/ - /* Sin(GrphHue) * K16)) */ - /* GrphSat * (Cos(GrphHue) * K15 + Sin(GrphHue) * K16) */ - rgb_matrix[9] = - dal_fixed31_32_add( - dal_fixed31_32_mul(cos_grph_hue, k15), - dal_fixed31_32_mul(sin_grph_hue, k16)); - /* (LumaG + GrphSat * (Cos(GrphHue) * K15 + Sin(GrphHue) * K16)) */ - rgb_matrix[9] = dal_fixed31_32_mul(grph_sat, rgb_matrix[9]); - /* (LumaG + GrphSat * (Cos(GrphHue) * K15 + Sin(GrphHue) * K16)) */ - rgb_matrix[9] = dal_fixed31_32_add(luma_g, rgb_matrix[9]); - /* GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K15 + Sin(GrphHue)**/ - /* K16)) */ - rgb_matrix[9] = dal_fixed31_32_mul(grph_cont, rgb_matrix[9]); - /* LumaScale * GrphCont * (LumaG + GrphSat *(Cos(GrphHue) * K15 + */ - /* Sin(GrphHue) * K16))*/ - rgb_matrix[9] = dal_fixed31_32_mul(luma_scale, rgb_matrix[9]); - - /* COEF_3_3 = GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K17 +*/ - /* Sin(GrphHue) * K18)) */ - /* (Cos(GrphHue) * K17 + Sin(GrphHue) * K18)) */ - rgb_matrix[10] = - dal_fixed31_32_add( - dal_fixed31_32_mul(cos_grph_hue, k17), - dal_fixed31_32_mul(sin_grph_hue, k18)); - /* GrphSat * (Cos(GrphHue) * K17 + Sin(GrphHue) * K18)) */ - rgb_matrix[10] = dal_fixed31_32_mul(grph_sat, rgb_matrix[10]); - /* (LumaB + GrphSat * (Cos(GrphHue) * K17 + Sin(GrphHue) * K18)) */ - rgb_matrix[10] = dal_fixed31_32_add(luma_b, rgb_matrix[10]); - /* GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K17 + Sin(GrphHue)**/ - /* K18)) */ - rgb_matrix[10] = dal_fixed31_32_mul(grph_cont, rgb_matrix[10]); - /* LumaScale * GrphCont * (LumaB + GrphSat *(Cos(GrphHue) * */ - /* K17 + Sin(GrphHue) * K18))*/ - rgb_matrix[10] = dal_fixed31_32_mul(luma_scale, rgb_matrix[10]); - - /* COEF_3_4 = RGBBias + RGBScale * GrphBright */ - rgb_matrix[11] = dal_fixed31_32_add( - rgb_bias, - dal_fixed31_32_mul(rgb_scale, grph_bright)); -} - -static void calculate_yuv_matrix(struct core_color *core_color, - unsigned int sink_index, - enum dc_color_space color_space, - struct fixed31_32 *yuv_matrix) -{ - struct fixed31_32 ideal[12]; - uint32_t i = 0; - - if ((color_space == COLOR_SPACE_YPBPR601) || - (color_space == COLOR_SPACE_YCBCR601) || - (color_space == COLOR_SPACE_YCBCR601_LIMITED)) { - static const int32_t matrix_[] = { - 25578516, 50216016, 9752344, 6250000, - -14764391, -28985609, 43750000, 50000000, - 43750000, -36635164, -7114836, 50000000 - }; - do { - ideal[i] = dal_fixed31_32_from_fraction( - matrix_[i], - 100000000); - ++i; - } while (i != ARRAY_SIZE(matrix_)); - } else { - static const int32_t matrix_[] = { - 18187266, 61183125, 6176484, 6250000, - -10025059, -33724941, 43750000, 50000000, - 43750000, -39738379, -4011621, 50000000 - }; - do { - ideal[i] = dal_fixed31_32_from_fraction( - matrix_[i], - 100000000); - ++i; - } while (i != ARRAY_SIZE(matrix_)); - } - - struct fixed31_32 grph_cont; - struct fixed31_32 grph_sat; - struct fixed31_32 grph_bright; - struct fixed31_32 sin_grph_hue; - struct fixed31_32 cos_grph_hue; - - initialize_fix_point_color_values( - core_color, sink_index, &grph_cont, &grph_sat, - &grph_bright, &sin_grph_hue, &cos_grph_hue); - - const struct fixed31_32 multiplier = - dal_fixed31_32_mul(grph_cont, grph_sat); - - yuv_matrix[0] = dal_fixed31_32_mul(ideal[0], grph_cont); - - yuv_matrix[1] = dal_fixed31_32_mul(ideal[1], grph_cont); - - yuv_matrix[2] = dal_fixed31_32_mul(ideal[2], grph_cont); - - yuv_matrix[4] = dal_fixed31_32_mul( - multiplier, - dal_fixed31_32_add( - dal_fixed31_32_mul( - ideal[4], - cos_grph_hue), - dal_fixed31_32_mul( - ideal[8], - sin_grph_hue))); - - yuv_matrix[5] = dal_fixed31_32_mul( - multiplier, - dal_fixed31_32_add( - dal_fixed31_32_mul( - ideal[5], - cos_grph_hue), - dal_fixed31_32_mul( - ideal[9], - sin_grph_hue))); - - yuv_matrix[6] = dal_fixed31_32_mul( - multiplier, - dal_fixed31_32_add( - dal_fixed31_32_mul( - ideal[6], - cos_grph_hue), - dal_fixed31_32_mul( - ideal[10], - sin_grph_hue))); - - yuv_matrix[7] = ideal[7]; - - yuv_matrix[8] = dal_fixed31_32_mul( - multiplier, - dal_fixed31_32_sub( - dal_fixed31_32_mul( - ideal[8], - cos_grph_hue), - dal_fixed31_32_mul( - ideal[4], - sin_grph_hue))); - - yuv_matrix[9] = dal_fixed31_32_mul( - multiplier, - dal_fixed31_32_sub( - dal_fixed31_32_mul( - ideal[9], - cos_grph_hue), - dal_fixed31_32_mul( - ideal[5], - sin_grph_hue))); - - yuv_matrix[10] = dal_fixed31_32_mul( - multiplier, - dal_fixed31_32_sub( - dal_fixed31_32_mul( - ideal[10], - cos_grph_hue), - dal_fixed31_32_mul( - ideal[6], - sin_grph_hue))); - - yuv_matrix[11] = ideal[11]; - - if ((color_space == COLOR_SPACE_YCBCR601_LIMITED) || - (color_space == COLOR_SPACE_YCBCR709_LIMITED)) { - yuv_matrix[3] = dal_fixed31_32_add(ideal[3], grph_bright); - } else { - yuv_matrix[3] = dal_fixed31_32_add( - ideal[3], - dal_fixed31_32_mul( - grph_bright, - dal_fixed31_32_from_fraction(86, 100))); - } -} - -static void calculate_csc_matrix(struct core_color *core_color, - unsigned int sink_index, - enum dc_color_space color_space, - uint16_t *csc_matrix) -{ - struct fixed31_32 fixed_csc_matrix[12]; - switch (color_space) { - case COLOR_SPACE_SRGB: - calculate_rgb_matrix_legacy - (core_color, sink_index, fixed_csc_matrix); - convert_float_matrix_legacy - (csc_matrix, fixed_csc_matrix, 12); - break; - case COLOR_SPACE_SRGB_LIMITED: - calculate_rgb_limited_range_matrix_legacy( - core_color, sink_index, fixed_csc_matrix); - convert_float_matrix_legacy(csc_matrix, fixed_csc_matrix, 12); - break; - case COLOR_SPACE_YCBCR601: - case COLOR_SPACE_YCBCR709: - case COLOR_SPACE_YCBCR601_LIMITED: - case COLOR_SPACE_YCBCR709_LIMITED: - case COLOR_SPACE_YPBPR601: - case COLOR_SPACE_YPBPR709: - calculate_yuv_matrix(core_color, sink_index, color_space, - fixed_csc_matrix); - convert_float_matrix(csc_matrix, fixed_csc_matrix, 12); - break; - default: - calculate_rgb_matrix_legacy - (core_color, sink_index, fixed_csc_matrix); - convert_float_matrix_legacy - (csc_matrix, fixed_csc_matrix, 12); - break; - } -} - -static struct dc_surface *dc_stream_to_surface_from_pipe_ctx( - struct core_color *core_color, - const struct dc_stream *stream) -{ - int i; - struct core_dc *core_dc = DC_TO_CORE(core_color->dc); - struct core_stream *core_stream = DC_STREAM_TO_CORE(stream); - struct dc_surface *out_surface = NULL; - - for (i = 0; i < MAX_PIPES; i++) { - if (core_dc->current_context->res_ctx.pipe_ctx[i].stream - == core_stream) { - out_surface = &core_dc->current_context->res_ctx. - pipe_ctx[i].surface->public; - break; - } - } - return out_surface; -} - -static enum predefined_gamut_type color_space_to_predefined_gamut_types(enum - color_color_space color_space) -{ - switch (color_space) { - case color_space_bt709: - case color_space_xv_ycc_bt709: - return gamut_type_bt709; - case color_space_bt601: - case color_space_xv_ycc_bt601: - return gamut_type_bt601; - case color_space_adobe: - return gamut_type_adobe_rgb; - case color_space_srgb: - case color_space_sc_rgb_ms_ref: - return gamut_type_srgb; - case color_space_bt2020: - return gamut_type_bt2020; - case color_space_dci_p3: /* TODO */ - default: - return gamut_type_unknown; - } -} - -static enum predefined_white_point_type white_point_to_predefined_white_point - (enum color_white_point_type white_point) -{ - switch (white_point) { - case color_white_point_type_5000k_horizon: - return white_point_type_5000k_horizon; - case color_white_point_type_6500k_noon: - return white_point_type_6500k_noon; - case color_white_point_type_7500k_north_sky: - return white_point_type_7500k_north_sky; - case color_white_point_type_9300k: - return white_point_type_9300k; - default: - return white_point_type_unknown; - } -} - -static bool update_color_gamut_data(struct color_gamut_data *input_data, - struct color_gamut_data *output_data) -{ - bool output_custom_cs = false; - bool output_custom_wp = false; - - if (input_data == NULL || output_data == NULL) - return false; - - if (input_data->color_space == color_space_custom_coordinates) { - output_data->color_space = input_data->color_space; - output_data->gamut.redX = input_data->gamut.redX; - output_data->gamut.redY = input_data->gamut.redY; - output_data->gamut.greenX = input_data->gamut.greenX; - output_data->gamut.greenY = input_data->gamut.greenY; - output_data->gamut.blueX = input_data->gamut.blueX; - output_data->gamut.blueY = input_data->gamut.blueY; - } else { - struct gamut_space_coordinates gamut_coord; - enum predefined_gamut_type gamut_type = - color_space_to_predefined_gamut_types - (input_data->color_space); - - /* fall back to original color space if unknown */ - if (gamut_type == gamut_type_unknown) { - if (output_data->color_space == - color_space_custom_coordinates) { - output_custom_cs = true; - } else { - gamut_type = - color_space_to_predefined_gamut_types - (output_data->color_space); - /* fall back to sRGB if both unknown*/ - if (gamut_type == gamut_type_unknown) { - output_data->color_space = - color_space_srgb; - gamut_type = gamut_type_srgb; - } - } - } else { - output_data->color_space = input_data->color_space; - } - - if (!output_custom_cs) { - mod_color_find_predefined_gamut(&gamut_coord, - gamut_type); - output_data->gamut.redX = gamut_coord.redX; - output_data->gamut.redY = gamut_coord.redY; - output_data->gamut.greenX = gamut_coord.greenX; - output_data->gamut.greenY = gamut_coord.greenY; - output_data->gamut.blueX = gamut_coord.blueX; - output_data->gamut.blueY = gamut_coord.blueY; - } - } - - if (input_data->white_point == color_space_custom_coordinates) { - output_data->white_point = input_data->white_point; - output_data->gamut.whiteX = input_data->gamut.whiteX; - output_data->gamut.whiteY = input_data->gamut.whiteY; - } else { - struct white_point_coodinates white_point_coord; - enum predefined_white_point_type white_type = - white_point_to_predefined_white_point - (input_data->white_point); - - /* fall back to original white point if not found */ - if (white_type == white_point_type_unknown) { - if (output_data->white_point == - color_white_point_type_custom_coordinates) { - output_custom_wp = true; - } else { - white_type = - white_point_to_predefined_white_point - (output_data->white_point); - /* fall back to 6500 if both unknown*/ - if (white_type == white_point_type_unknown) { - output_data->white_point = - color_white_point_type_6500k_noon; - white_type = - white_point_type_6500k_noon; - } - } - } else { - output_data->white_point = input_data->white_point; - } - - if (!output_custom_wp) { - mod_color_find_predefined_white_point( - &white_point_coord, white_type); - output_data->gamut.whiteX = white_point_coord.whiteX; - output_data->gamut.whiteY = white_point_coord.whiteY; - } - } - return true; -} - -void initialize_color_state(struct core_color *core_color, int index) -{ - core_color->state[index].user_enable_color_temperature = true; - - core_color->state[index].custom_color_temperature = 6500; - - core_color->state[index].contrast.current = 100; - core_color->state[index].contrast.min = 0; - core_color->state[index].contrast.max = 200; - - core_color->state[index].saturation.current = 100; - core_color->state[index].saturation.min = 0; - core_color->state[index].saturation.max = 200; - - core_color->state[index].brightness.current = 0; - core_color->state[index].brightness.min = -100; - core_color->state[index].brightness.max = 100; - - core_color->state[index].hue.current = 0; - core_color->state[index].hue.min = -30; - core_color->state[index].hue.max = 30; - - core_color->state[index].gamma = NULL; - - core_color->state[index].preferred_quantization_range = - QUANTIZATION_RANGE_FULL; - - core_color->state[index].source_gamut.color_space = - color_space_srgb; - core_color->state[index].source_gamut.white_point = - color_white_point_type_6500k_noon; - core_color->state[index].source_gamut.gamut.blueX = 1500; - core_color->state[index].source_gamut.gamut.blueY = 600; - core_color->state[index].source_gamut.gamut.greenX = 3000; - core_color->state[index].source_gamut.gamut.greenY = 6000; - core_color->state[index].source_gamut.gamut.redX = 6400; - core_color->state[index].source_gamut.gamut.redY = 3300; - core_color->state[index].source_gamut.gamut.whiteX = 3127; - core_color->state[index].source_gamut.gamut.whiteY = 3290; - - core_color->state[index].destination_gamut.color_space = - color_space_srgb; - core_color->state[index].destination_gamut.white_point = - color_white_point_type_6500k_noon; - core_color->state[index].destination_gamut.gamut.blueX = 1500; - core_color->state[index].destination_gamut.gamut.blueY = 600; - core_color->state[index].destination_gamut.gamut.greenX = 3000; - core_color->state[index].destination_gamut.gamut.greenY = 6000; - core_color->state[index].destination_gamut.gamut.redX = 6400; - core_color->state[index].destination_gamut.gamut.redY = 3300; - core_color->state[index].destination_gamut.gamut.whiteX = 3127; - core_color->state[index].destination_gamut.gamut.whiteY = 3290; - - core_color->state[index].input_transfer_function = - transfer_func_srgb; - core_color->state[index].output_transfer_function = - transfer_func_srgb; -} - -struct mod_color *mod_color_create(struct dc *dc) -{ - int i = 0; - struct core_color *core_color = - dm_alloc(sizeof(struct core_color)); - struct core_dc *core_dc = DC_TO_CORE(dc); - struct persistent_data_flag flag; - - if (core_color == NULL) - goto fail_alloc_context; - - core_color->caps = dm_alloc(sizeof(struct sink_caps) * - MOD_COLOR_MAX_CONCURRENT_SINKS); - - if (core_color->caps == NULL) - goto fail_alloc_caps; - - for (i = 0; i < MOD_COLOR_MAX_CONCURRENT_SINKS; i++) - core_color->caps[i].sink = NULL; - - core_color->state = dm_alloc(sizeof(struct color_state) * - MOD_COLOR_MAX_CONCURRENT_SINKS); - - /*hardcoded to sRGB with 6500 color temperature*/ - for (i = 0; i < MOD_COLOR_MAX_CONCURRENT_SINKS; i++) { - initialize_color_state(core_color, i); - } - - if (core_color->state == NULL) - goto fail_alloc_state; - - core_color->edid_caps = dm_alloc(sizeof(struct color_edid_caps) * - MOD_COLOR_MAX_CONCURRENT_SINKS); - - if (core_color->edid_caps == NULL) - goto fail_alloc_edid_caps; - - core_color->num_sinks = 0; - - if (dc == NULL) - goto fail_construct; - - core_color->dc = dc; - - if (!check_dc_support(dc)) - goto fail_construct; - - /* Create initial module folder in registry for color adjustment */ - flag.save_per_edid = true; - flag.save_per_link = false; - - dm_write_persistent_data(core_dc->ctx, NULL, COLOR_REGISTRY_NAME, NULL, - NULL, 0, &flag); - - return &core_color->public; - -fail_construct: - dm_free(core_color->edid_caps); - -fail_alloc_edid_caps: - dm_free(core_color->state); - -fail_alloc_state: - dm_free(core_color->caps); - -fail_alloc_caps: - dm_free(core_color); - -fail_alloc_context: - return NULL; -} - -void mod_color_destroy(struct mod_color *mod_color) -{ - if (mod_color != NULL) { - int i; - struct core_color *core_color = - MOD_COLOR_TO_CORE(mod_color); - - dm_free(core_color->edid_caps); - - for (i = 0; i < core_color->num_sinks; i++) - if (core_color->state[i].gamma) - dc_gamma_release(&core_color->state[i].gamma); - - dm_free(core_color->state); - - for (i = 0; i < core_color->num_sinks; i++) - dc_sink_release(core_color->caps[i].sink); - - dm_free(core_color->caps); - - dm_free(core_color); - } -} - -bool mod_color_add_sink(struct mod_color *mod_color, const struct dc_sink *sink, - struct color_edid_caps *edid_caps) -{ - struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - struct core_dc *core_dc = DC_TO_CORE(core_color->dc); - bool persistent_color_temp_enable; - int persistent_custom_color_temp = 0; - struct color_space_coordinates persistent_source_gamut; - struct color_space_coordinates persistent_destination_gamut; - int persistent_brightness; - int persistent_contrast; - int persistent_hue; - int persistent_saturation; - enum dc_quantization_range persistent_quantization_range; - struct persistent_data_flag flag; - - if (core_color->num_sinks < MOD_COLOR_MAX_CONCURRENT_SINKS) { - dc_sink_retain(sink); - core_color->caps[core_color->num_sinks].sink = sink; - - initialize_color_state(core_color, core_color->num_sinks); - - core_color->edid_caps[core_color->num_sinks].colorimetry_caps = - edid_caps->colorimetry_caps; - core_color->edid_caps[core_color->num_sinks].hdr_caps = - edid_caps->hdr_caps; - - /* get persistent data from registry */ - flag.save_per_edid = true; - flag.save_per_link = false; - - if (dm_read_persistent_data(core_dc->ctx, sink, - COLOR_REGISTRY_NAME, - "enablecolortempadj", - &persistent_color_temp_enable, - sizeof(bool), &flag)) - core_color->state[core_color->num_sinks]. - user_enable_color_temperature = - persistent_color_temp_enable; - - if (dm_read_persistent_data(core_dc->ctx, sink, - COLOR_REGISTRY_NAME, - "customcolortemp", - &persistent_custom_color_temp, - sizeof(int), &flag)) - core_color->state[core_color->num_sinks]. - custom_color_temperature - = persistent_custom_color_temp; - - if (dm_read_persistent_data(core_dc->ctx, sink, - COLOR_REGISTRY_NAME, - "sourcegamut", - &persistent_source_gamut, - sizeof(struct color_space_coordinates), - &flag)) { - memcpy(&core_color->state[core_color->num_sinks]. - source_gamut.gamut, &persistent_source_gamut, - sizeof(struct color_space_coordinates)); - } - - if (dm_read_persistent_data(core_dc->ctx, sink, COLOR_REGISTRY_NAME, - "destgamut", - &persistent_destination_gamut, - sizeof(struct color_space_coordinates), - &flag)) { - memcpy(&core_color->state[core_color->num_sinks]. - destination_gamut.gamut, - &persistent_destination_gamut, - sizeof(struct color_space_coordinates)); - } - - if (dm_read_persistent_data(core_dc->ctx, sink, COLOR_REGISTRY_NAME, - "brightness", - &persistent_brightness, - sizeof(int), &flag)) - core_color->state[core_color->num_sinks]. - brightness.current = persistent_brightness; - - if (dm_read_persistent_data(core_dc->ctx, sink, COLOR_REGISTRY_NAME, - "contrast", - &persistent_contrast, - sizeof(int), &flag)) - core_color->state[core_color->num_sinks]. - contrast.current = persistent_contrast; - - if (dm_read_persistent_data(core_dc->ctx, sink, COLOR_REGISTRY_NAME, - "hue", - &persistent_hue, - sizeof(int), &flag)) - core_color->state[core_color->num_sinks]. - hue.current = persistent_hue; - - if (dm_read_persistent_data(core_dc->ctx, sink, COLOR_REGISTRY_NAME, - "saturation", - &persistent_saturation, - sizeof(int), &flag)) - core_color->state[core_color->num_sinks]. - saturation.current = persistent_saturation; - - if (dm_read_persistent_data(core_dc->ctx, sink, - COLOR_REGISTRY_NAME, - "preferred_quantization_range", - &persistent_quantization_range, - sizeof(int), &flag)) - core_color->state[core_color->num_sinks]. - preferred_quantization_range = - persistent_quantization_range; - - core_color->num_sinks++; - return true; - } - return false; -} - -bool mod_color_remove_sink(struct mod_color *mod_color, - const struct dc_sink *sink) -{ - int i = 0, j = 0; - struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - - for (i = 0; i < core_color->num_sinks; i++) { - if (core_color->caps[i].sink == sink) { - if (core_color->state[i].gamma) { - dc_gamma_release(&core_color->state[i].gamma); - } - memset(&core_color->state[i], 0, - sizeof(struct color_state)); - memset(&core_color->edid_caps[i], 0, - sizeof(struct color_edid_caps)); - - /* To remove this sink, shift everything after down */ - for (j = i; j < core_color->num_sinks - 1; j++) { - core_color->caps[j].sink = - core_color->caps[j + 1].sink; - - memcpy(&core_color->state[j], - &core_color->state[j + 1], - sizeof(struct color_state)); - - memcpy(&core_color->edid_caps[j], - &core_color->edid_caps[j + 1], - sizeof(struct color_edid_caps)); - } - - memset(&core_color->state[core_color->num_sinks - 1], 0, - sizeof(struct color_state)); - memset(&core_color->edid_caps[core_color->num_sinks - 1], 0, - sizeof(struct color_edid_caps)); - - core_color->num_sinks--; - - dc_sink_release(sink); - - return true; - } - } - - return false; -} - -bool mod_color_update_gamut_to_stream(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams) -{ - struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - struct core_dc *core_dc = DC_TO_CORE(core_color->dc); - struct persistent_data_flag flag; - struct gamut_src_dst_matrix *matrix = - dm_alloc(sizeof(struct gamut_src_dst_matrix)); - - unsigned int stream_index, j; - int sink_index; - - for (stream_index = 0; stream_index < num_streams; stream_index++) { - sink_index = sink_index_from_sink(core_color, - streams[stream_index]->sink); - if (sink_index == -1) - continue; - - /* Write persistent data in registry*/ - flag.save_per_edid = true; - flag.save_per_link = false; - - dm_write_persistent_data(core_dc->ctx, - streams[stream_index]->sink, - COLOR_REGISTRY_NAME, - "sourcegamut", - &core_color->state[sink_index]. - source_gamut.gamut, - sizeof(struct color_space_coordinates), - &flag); - - dm_write_persistent_data(core_dc->ctx, - streams[stream_index]->sink, - COLOR_REGISTRY_NAME, - "destgamut", - &core_color->state[sink_index]. - destination_gamut.gamut, - sizeof(struct color_space_coordinates), - &flag); - - if (!build_gamut_remap_matrix - (core_color->state[sink_index].source_gamut.gamut, - matrix->rgbCoeffSrc, - matrix->whiteCoeffSrc)) - goto function_fail; - - if (!build_gamut_remap_matrix - (core_color->state[sink_index]. - destination_gamut.gamut, - matrix->rgbCoeffDst, matrix->whiteCoeffDst)) - goto function_fail; - - struct fixed31_32 gamut_result[12]; - struct fixed31_32 temp_matrix[9]; - - if (!gamut_to_color_matrix( - matrix->rgbCoeffDst, - matrix->whiteCoeffDst, - matrix->rgbCoeffSrc, - matrix->whiteCoeffSrc, - true, - temp_matrix)) - goto function_fail; - - gamut_result[0] = temp_matrix[0]; - gamut_result[1] = temp_matrix[1]; - gamut_result[2] = temp_matrix[2]; - gamut_result[3] = matrix->whiteCoeffSrc[0]; - gamut_result[4] = temp_matrix[3]; - gamut_result[5] = temp_matrix[4]; - gamut_result[6] = temp_matrix[5]; - gamut_result[7] = matrix->whiteCoeffSrc[1]; - gamut_result[8] = temp_matrix[6]; - gamut_result[9] = temp_matrix[7]; - gamut_result[10] = temp_matrix[8]; - gamut_result[11] = matrix->whiteCoeffSrc[2]; - - struct core_stream *core_stream = - DC_STREAM_TO_CORE - (streams[stream_index]); - - core_stream->public.gamut_remap_matrix.enable_remap = true; - - for (j = 0; j < 12; j++) - core_stream->public. - gamut_remap_matrix.matrix[j] = - gamut_result[j]; - } - - dm_free(matrix); - core_color->dc->stream_funcs.set_gamut_remap - (core_color->dc, streams, num_streams); - - return true; - -function_fail: - dm_free(matrix); - return false; -} - -bool mod_color_adjust_source_gamut(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - struct color_gamut_data *input_gamut_data) -{ - struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - - unsigned int stream_index; - int sink_index; - - for (stream_index = 0; stream_index < num_streams; stream_index++) { - sink_index = sink_index_from_sink(core_color, - streams[stream_index]->sink); - if (sink_index == -1) - continue; - - update_color_gamut_data(input_gamut_data, - &core_color->state[sink_index].source_gamut); - } - - if (!mod_color_update_gamut_info(mod_color, streams, num_streams)) - return false; - - return true; -} - -bool mod_color_adjust_source_gamut_and_tf(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - struct color_gamut_data *input_gamut_data, - enum color_transfer_func input_transfer_func) -{ - struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - - unsigned int stream_index; - int sink_index; - - for (stream_index = 0; stream_index < num_streams; stream_index++) { - sink_index = sink_index_from_sink(core_color, - streams[stream_index]->sink); - if (sink_index == -1) - continue; - update_color_gamut_data(input_gamut_data, - &core_color->state[sink_index].source_gamut); - core_color->state[sink_index].input_transfer_function = - input_transfer_func; - } - - if (!mod_color_update_gamut_info(mod_color, streams, num_streams)) - return false; - - return true; -} - -bool mod_color_adjust_destination_gamut(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - struct color_gamut_data *input_gamut_data) -{ - struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - - unsigned int stream_index; - int sink_index; - - for (stream_index = 0; stream_index < num_streams; stream_index++) { - sink_index = sink_index_from_sink(core_color, - streams[stream_index]->sink); - if (sink_index == -1) - continue; - - update_color_gamut_data(input_gamut_data, - &core_color->state[sink_index].destination_gamut); - } - - if (!mod_color_update_gamut_to_stream(mod_color, streams, num_streams)) - return false; - - return true; -} - -bool mod_color_set_white_point(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - struct white_point_coodinates *white_point) -{ - struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - - unsigned int stream_index; - int sink_index; - - for (stream_index = 0; stream_index < num_streams; - stream_index++) { - sink_index = sink_index_from_sink(core_color, - streams[stream_index]->sink); - if (sink_index == -1) - continue; - core_color->state[sink_index].source_gamut.gamut.whiteX = - white_point->whiteX; - core_color->state[sink_index].source_gamut.gamut.whiteY = - white_point->whiteY; - } - - if (!mod_color_update_gamut_to_stream(mod_color, streams, num_streams)) - return false; - - return true; -} - - -bool mod_color_set_mastering_info(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - const struct dc_hdr_static_metadata *mastering_info) -{ - struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - unsigned int stream_index; - int sink_index; - - for (stream_index = 0; stream_index < num_streams; stream_index++) { - sink_index = sink_index_from_sink(core_color, - streams[stream_index]->sink); - if (sink_index == -1) - continue; - memcpy(&core_color->state[sink_index].mastering_info, - mastering_info, - sizeof(struct dc_hdr_static_metadata)); - } - return true; -} - -bool mod_color_get_mastering_info(struct mod_color *mod_color, - const struct dc_sink *sink, - struct dc_hdr_static_metadata *mastering_info) -{ - struct core_color *core_color = - MOD_COLOR_TO_CORE(mod_color); - - int sink_index = sink_index_from_sink(core_color, sink); - - if (sink_index == -1) - return false; - - memcpy(mastering_info, &core_color->state[sink_index].mastering_info, - sizeof(struct dc_hdr_static_metadata)); - - return true; -} - -bool mod_color_set_user_enable(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - bool user_enable) -{ - struct core_color *core_color = - MOD_COLOR_TO_CORE(mod_color); - struct core_dc *core_dc = DC_TO_CORE(core_color->dc); - struct persistent_data_flag flag; - unsigned int stream_index; - int sink_index; - - for (stream_index = 0; stream_index < num_streams; stream_index++) { - sink_index = sink_index_from_sink(core_color, - streams[stream_index]->sink); - if (sink_index == -1) - continue; - core_color->state[sink_index].user_enable_color_temperature - = user_enable; - - /* Write persistent data in registry*/ - flag.save_per_edid = true; - flag.save_per_link = false; - - dm_write_persistent_data(core_dc->ctx, - streams[stream_index]->sink, - COLOR_REGISTRY_NAME, - "enablecolortempadj", - &user_enable, - sizeof(bool), - &flag); - } - return true; -} - -bool mod_color_get_user_enable(struct mod_color *mod_color, - const struct dc_sink *sink, - bool *user_enable) -{ - struct core_color *core_color = - MOD_COLOR_TO_CORE(mod_color); - - int sink_index = sink_index_from_sink(core_color, sink); - - if (sink_index == -1) - return false; - - *user_enable = core_color->state[sink_index]. - user_enable_color_temperature; - - return true; -} - -bool mod_color_get_custom_color_temperature(struct mod_color *mod_color, - const struct dc_sink *sink, - int *color_temperature) -{ - struct core_color *core_color = - MOD_COLOR_TO_CORE(mod_color); - - int sink_index = sink_index_from_sink(core_color, sink); - - if (sink_index == -1) - return false; - - *color_temperature = core_color->state[sink_index]. - custom_color_temperature; - - return true; -} - -bool mod_color_set_custom_color_temperature(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - int color_temperature) -{ - struct core_color *core_color = - MOD_COLOR_TO_CORE(mod_color); - struct core_dc *core_dc = DC_TO_CORE(core_color->dc); - struct persistent_data_flag flag; - unsigned int stream_index; - int sink_index; - - for (stream_index = 0; stream_index < num_streams; stream_index++) { - sink_index = sink_index_from_sink(core_color, - streams[stream_index]->sink); - if (sink_index == -1) - continue; - core_color->state[sink_index].custom_color_temperature - = color_temperature; - - /* Write persistent data in registry*/ - flag.save_per_edid = true; - flag.save_per_link = false; - - dm_write_persistent_data(core_dc->ctx, - streams[stream_index]->sink, - COLOR_REGISTRY_NAME, - "customcolortemp", - &color_temperature, - sizeof(int), - &flag); - } - return true; -} - -bool mod_color_get_color_saturation(struct mod_color *mod_color, - const struct dc_sink *sink, - struct color_range *color_saturation) -{ - struct core_color *core_color = - MOD_COLOR_TO_CORE(mod_color); - - int sink_index = sink_index_from_sink(core_color, sink); - - if (sink_index == -1) - return false; - - *color_saturation = core_color->state[sink_index].saturation; - - return true; -} - -bool mod_color_get_color_contrast(struct mod_color *mod_color, - const struct dc_sink *sink, - struct color_range *color_contrast) -{ - struct core_color *core_color = - MOD_COLOR_TO_CORE(mod_color); - - int sink_index = sink_index_from_sink(core_color, sink); - - if (sink_index == -1) - return false; - - *color_contrast = core_color->state[sink_index].contrast; - - return true; -} - -bool mod_color_get_color_brightness(struct mod_color *mod_color, - const struct dc_sink *sink, - struct color_range *color_brightness) -{ - struct core_color *core_color = - MOD_COLOR_TO_CORE(mod_color); - - int sink_index = sink_index_from_sink(core_color, sink); - - if (sink_index == -1) - return false; - - *color_brightness = core_color->state[sink_index].brightness; - - return true; -} - -bool mod_color_get_color_hue(struct mod_color *mod_color, - const struct dc_sink *sink, - struct color_range *color_hue) -{ - struct core_color *core_color = - MOD_COLOR_TO_CORE(mod_color); - - int sink_index = sink_index_from_sink(core_color, sink); - - if (sink_index == -1) - return false; - - *color_hue = core_color->state[sink_index].hue; - - return true; -} - -bool mod_color_get_source_gamut(struct mod_color *mod_color, - const struct dc_sink *sink, - struct color_space_coordinates *source_gamut) -{ - struct core_color *core_color = - MOD_COLOR_TO_CORE(mod_color); - - int sink_index = sink_index_from_sink(core_color, sink); - - if (sink_index == -1) - return false; - - *source_gamut = core_color->state[sink_index].source_gamut.gamut; - - return true; -} - -bool mod_color_notify_mode_change(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams) -{ - struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - - struct gamut_src_dst_matrix *matrix = - dm_alloc(sizeof(struct gamut_src_dst_matrix)); - - unsigned int stream_index, j; - int sink_index; - - for (stream_index = 0; stream_index < num_streams; stream_index++) { - sink_index = sink_index_from_sink(core_color, - streams[stream_index]->sink); - if (sink_index == -1) - continue; - - if (!build_gamut_remap_matrix - (core_color->state[sink_index].source_gamut.gamut, - matrix->rgbCoeffSrc, - matrix->whiteCoeffSrc)) - goto function_fail; - - if (!build_gamut_remap_matrix - (core_color->state[sink_index]. - destination_gamut.gamut, - matrix->rgbCoeffDst, matrix->whiteCoeffDst)) - goto function_fail; - - struct fixed31_32 gamut_result[12]; - struct fixed31_32 temp_matrix[9]; - - if (!gamut_to_color_matrix( - matrix->rgbCoeffDst, - matrix->whiteCoeffDst, - matrix->rgbCoeffSrc, - matrix->whiteCoeffSrc, - true, - temp_matrix)) - goto function_fail; - - gamut_result[0] = temp_matrix[0]; - gamut_result[1] = temp_matrix[1]; - gamut_result[2] = temp_matrix[2]; - gamut_result[3] = matrix->whiteCoeffSrc[0]; - gamut_result[4] = temp_matrix[3]; - gamut_result[5] = temp_matrix[4]; - gamut_result[6] = temp_matrix[5]; - gamut_result[7] = matrix->whiteCoeffSrc[1]; - gamut_result[8] = temp_matrix[6]; - gamut_result[9] = temp_matrix[7]; - gamut_result[10] = temp_matrix[8]; - gamut_result[11] = matrix->whiteCoeffSrc[2]; - - - struct core_stream *core_stream = - DC_STREAM_TO_CORE - (streams[stream_index]); - - core_stream->public.gamut_remap_matrix.enable_remap = true; - - for (j = 0; j < 12; j++) - core_stream->public. - gamut_remap_matrix.matrix[j] = - gamut_result[j]; - - calculate_csc_matrix(core_color, sink_index, - core_stream->public.output_color_space, - core_stream->public.csc_color_matrix.matrix); - - core_stream->public.csc_color_matrix.enable_adjustment = true; - } - - dm_free(matrix); - - return true; - -function_fail: - dm_free(matrix); - return false; -} - -bool mod_color_set_brightness(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - int brightness_value) -{ - struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - struct core_dc *core_dc = DC_TO_CORE(core_color->dc); - struct persistent_data_flag flag; - unsigned int stream_index; - int sink_index; - - for (stream_index = 0; stream_index < num_streams; stream_index++) { - sink_index = sink_index_from_sink(core_color, - streams[stream_index]->sink); - if (sink_index == -1) - continue; - - struct core_stream *core_stream = - DC_STREAM_TO_CORE - (streams[stream_index]); - - core_color->state[sink_index].brightness.current = - brightness_value; - - calculate_csc_matrix(core_color, sink_index, - core_stream->public.output_color_space, - core_stream->public.csc_color_matrix.matrix); - - core_stream->public.csc_color_matrix.enable_adjustment = true; - - /* Write persistent data in registry*/ - flag.save_per_edid = true; - flag.save_per_link = false; - dm_write_persistent_data(core_dc->ctx, - streams[stream_index]->sink, - COLOR_REGISTRY_NAME, - "brightness", - &brightness_value, - sizeof(int), - &flag); - } - - core_color->dc->stream_funcs.set_gamut_remap - (core_color->dc, streams, num_streams); - - return true; -} - -bool mod_color_set_contrast(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - int contrast_value) -{ - struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - struct core_dc *core_dc = DC_TO_CORE(core_color->dc); - struct persistent_data_flag flag; - unsigned int stream_index; - int sink_index; - - for (stream_index = 0; stream_index < num_streams; stream_index++) { - sink_index = sink_index_from_sink(core_color, - streams[stream_index]->sink); - if (sink_index == -1) - continue; - - struct core_stream *core_stream = - DC_STREAM_TO_CORE - (streams[stream_index]); - - core_color->state[sink_index].contrast.current = - contrast_value; - - calculate_csc_matrix(core_color, sink_index, - core_stream->public.output_color_space, - core_stream->public.csc_color_matrix.matrix); - - core_stream->public.csc_color_matrix.enable_adjustment = true; - - /* Write persistent data in registry*/ - flag.save_per_edid = true; - flag.save_per_link = false; - dm_write_persistent_data(core_dc->ctx, - streams[stream_index]->sink, - COLOR_REGISTRY_NAME, - "contrast", - &contrast_value, - sizeof(int), - &flag); - } - - core_color->dc->stream_funcs.set_gamut_remap - (core_color->dc, streams, num_streams); - - return true; -} - -bool mod_color_set_hue(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - int hue_value) -{ - struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - struct core_dc *core_dc = DC_TO_CORE(core_color->dc); - struct persistent_data_flag flag; - unsigned int stream_index; - int sink_index; - - for (stream_index = 0; stream_index < num_streams; stream_index++) { - sink_index = sink_index_from_sink(core_color, - streams[stream_index]->sink); - if (sink_index == -1) - continue; - - struct core_stream *core_stream = - DC_STREAM_TO_CORE - (streams[stream_index]); - - core_color->state[sink_index].hue.current = hue_value; - - calculate_csc_matrix(core_color, sink_index, - core_stream->public.output_color_space, - core_stream->public.csc_color_matrix.matrix); - - core_stream->public.csc_color_matrix.enable_adjustment = true; - - /* Write persistent data in registry*/ - flag.save_per_edid = true; - flag.save_per_link = false; - dm_write_persistent_data(core_dc->ctx, - streams[stream_index]->sink, - COLOR_REGISTRY_NAME, - "hue", - &hue_value, - sizeof(int), - &flag); - } - - core_color->dc->stream_funcs.set_gamut_remap - (core_color->dc, streams, num_streams); - - return true; -} - -bool mod_color_set_saturation(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - int saturation_value) -{ - struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - struct core_dc *core_dc = DC_TO_CORE(core_color->dc); - struct persistent_data_flag flag; - unsigned int stream_index; - int sink_index; - - for (stream_index = 0; stream_index < num_streams; stream_index++) { - sink_index = sink_index_from_sink(core_color, - streams[stream_index]->sink); - if (sink_index == -1) - continue; - - struct core_stream *core_stream = - DC_STREAM_TO_CORE - (streams[stream_index]); - - core_color->state[sink_index].saturation.current = - saturation_value; - - calculate_csc_matrix(core_color, sink_index, - core_stream->public.output_color_space, - core_stream->public.csc_color_matrix.matrix); - - core_stream->public.csc_color_matrix.enable_adjustment = true; - - /* Write persistent data in registry*/ - flag.save_per_edid = true; - flag.save_per_link = false; - dm_write_persistent_data(core_dc->ctx, - streams[stream_index]->sink, - COLOR_REGISTRY_NAME, - "saturation", - &saturation_value, - sizeof(int), - &flag); - } - - core_color->dc->stream_funcs.set_gamut_remap - (core_color->dc, streams, num_streams); - - return true; -} - -bool mod_color_set_input_gamma_correction(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - struct dc_gamma *gamma) -{ - struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - unsigned int stream_index; - int sink_index; - - for (stream_index = 0; stream_index < num_streams; stream_index++) { - sink_index = sink_index_from_sink(core_color, - streams[stream_index]->sink); - if (sink_index == -1) - continue; - - struct dc_surface *surface = - dc_stream_to_surface_from_pipe_ctx(core_color, - streams[stream_index]); - - if (surface != NULL) { - struct dc_transfer_func *input_tf = - dc_create_transfer_func(); - struct dc_surface_update updates = {0}; - - if (input_tf != NULL) { - input_tf->type = TF_TYPE_PREDEFINED; - input_tf->tf = TRANSFER_FUNCTION_SRGB; - } - - if (core_color->state[sink_index].gamma != gamma) { - if (core_color->state[sink_index].gamma) - dc_gamma_release( - &core_color->state[sink_index].gamma); - - dc_gamma_retain(gamma); - core_color->state[sink_index].gamma = gamma; - } - - updates.surface = surface; - updates.gamma = gamma; - updates.in_transfer_func = input_tf; - dc_update_surfaces_for_target(core_color->dc, &updates, - 1, NULL); - - if (input_tf != NULL) - dc_transfer_func_release(input_tf); - } - } - - return true; -} - -bool mod_color_persist_user_preferred_quantization_range( - struct mod_color *mod_color, - const struct dc_sink *sink, - enum dc_quantization_range quantization_range) -{ - struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - struct core_dc *core_dc = DC_TO_CORE(core_color->dc); - struct persistent_data_flag flag; - int sink_index; - - sink_index = sink_index_from_sink(core_color, sink); - if (sink_index == -1) - return false; - - if (core_color->state[sink_index]. - preferred_quantization_range != quantization_range) { - core_color->state[sink_index].preferred_quantization_range = - quantization_range; - flag.save_per_edid = true; - flag.save_per_link = false; - dm_write_persistent_data(core_dc->ctx, - sink, - COLOR_REGISTRY_NAME, - "quantization_range", - &quantization_range, - sizeof(int), - &flag); - } - - return true; -} - -bool mod_color_get_preferred_quantization_range(struct mod_color *mod_color, - const struct dc_sink *sink, - const struct dc_crtc_timing *timing, - enum dc_quantization_range *quantization_range) -{ - struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - int sink_index = sink_index_from_sink(core_color, sink); - - if (sink_index == -1) - return false; - - enum dc_quantization_range user_preferred_quantization_range = - core_color->state[sink_index]. - preferred_quantization_range; - bool rgb_full_range_supported = - mod_color_is_rgb_full_range_supported_for_timing( - sink, timing); - bool rgb_limited_range_supported = - mod_color_is_rgb_limited_range_supported_for_timing( - sink, timing); - - if (rgb_full_range_supported && rgb_limited_range_supported) - *quantization_range = user_preferred_quantization_range; - else if (rgb_full_range_supported && !rgb_limited_range_supported) - *quantization_range = QUANTIZATION_RANGE_FULL; - else if (!rgb_full_range_supported && rgb_limited_range_supported) - *quantization_range = QUANTIZATION_RANGE_LIMITED; - else - *quantization_range = QUANTIZATION_RANGE_UNKNOWN; - - return true; -} - -bool mod_color_is_rgb_full_range_supported_for_timing( - const struct dc_sink *sink, - const struct dc_crtc_timing *timing) -{ - bool result = false; - - if (!sink || !timing) - return result; - - if (sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A) - if (timing->vic || timing->hdmi_vic) - if (timing->h_addressable == 640 && - timing->v_addressable == 480 && - (timing->pix_clk_khz == 25200 || - timing->pix_clk_khz == 25170 || - timing->pix_clk_khz == 25175)) - result = true; - else - /* don't support full range rgb */ - /* for HDMI CEA861 timings except VGA mode */ - result = false; - else - result = true; - else - result = true; - - return result; -} - -bool mod_color_is_rgb_limited_range_supported_for_timing( - const struct dc_sink *sink, - const struct dc_crtc_timing *timing) -{ - bool result = false; - - if (!sink || !timing) - return result; - - if (sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A) - if (timing->vic || timing->hdmi_vic) - if (timing->h_addressable == 640 && - timing->v_addressable == 480 && - (timing->pix_clk_khz == 25200 || - timing->pix_clk_khz == 25170 || - timing->pix_clk_khz == 25175)) - /* don't support rgb limited for */ - /* HDMI CEA VGA mode */ - result = false; - else - /* support rgb limited for non VGA CEA timing */ - result = true; - else - /* support rgb limited for non CEA HDMI timing */ - result = true; - else - /* don't support rgb limited for non HDMI signal */ - result = false; - - return result; -} - -bool mod_color_set_regamma(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams) -{ - /*TODO*/ - return true; -} - -bool mod_color_set_degamma(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - enum color_transfer_func transfer_function) -{ - /*TODO*/ - return true; -} - -bool mod_color_update_gamut_info(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams) -{ - struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - unsigned int stream_index; - int sink_index; - bool should_defer = false; - bool is_hdr = false; - enum color_color_space source_color_space; - enum color_transfer_func input_transfer_function; - struct color_gamut_data new_gamut_source; - struct color_gamut_data new_gamut_destination; - - for (stream_index = 0; stream_index < num_streams; stream_index++) { - sink_index = sink_index_from_sink(core_color, - streams[stream_index]->sink); - if (sink_index == -1) - continue; - source_color_space = - core_color->state[sink_index].source_gamut.color_space; - input_transfer_function = - core_color->state[sink_index].input_transfer_function; - new_gamut_source.color_space = source_color_space; - new_gamut_destination.color_space = - core_color->state[sink_index]. - destination_gamut.color_space; - - struct dc_surface *surface = - dc_stream_to_surface_from_pipe_ctx(core_color, - streams[stream_index]); - if (surface == NULL) - return false; - - if (surface->format == SURFACE_PIXEL_FORMAT_GRPH_ARGB8888 || - surface->format == - SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010) { - - if (input_transfer_function == - transfer_func_pq2084 || - input_transfer_function == - transfer_func_pq2084_interim) { - /* For PQ and PQ interim, we bypass degamma+ - * remap+regamma, application needs to also - * handle gamut remapping - */ - /* TODO */ - is_hdr = true; - } else if (input_transfer_function == - transfer_func_linear_0_1 || - input_transfer_function == - transfer_func_linear_0_125) { - /* TF not supported in current surface format, - * but may be deferred to a later flip - */ - should_defer = true; - } else { - new_gamut_destination.color_space = - color_space_srgb; - } - } else if (surface->format == - SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F || - surface->format == - SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F || - surface->format == - SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616) { - if (input_transfer_function == - transfer_func_linear_0_125) { - /* Regamma PQ for HDR supported displays and - * 0-125 source - */ - if ((core_color->edid_caps[sink_index]. - hdr_caps) & smpte_st2084) - is_hdr = true; - - /* override for BT.2020 whenever PQ */ - if (core_color->state[sink_index]. - destination_gamut.color_space != - color_space_bt2020) { - if (streams[stream_index]->timing. - pixel_encoding == - PIXEL_ENCODING_RGB) { - if ((core_color-> - edid_caps[sink_index]. - colorimetry_caps) & bt_2020_rgb) - new_gamut_destination. - color_space = - color_space_bt2020; - } else { - if ((core_color-> - edid_caps[sink_index]. - colorimetry_caps) & bt_2020_ycc) - new_gamut_destination. - color_space = - color_space_bt2020; - } - } - } else if (input_transfer_function == - transfer_func_linear_0_1) { - new_gamut_destination.color_space = - color_space_srgb; - } else { - /* TF not supported in current surface format, - * but may be deferred to a later flip - */ - should_defer = true; - } - } - - /* 0. ---- CHECK DEFERRED ---- */ - if (should_defer) - return true; - - /* 1. ---- SET GAMUT SOURCE ---- */ - new_gamut_source.white_point = core_color->state[sink_index]. - source_gamut.white_point; - update_color_gamut_data(&new_gamut_source, - &core_color->state[sink_index].source_gamut); - - /* 2. ---- SET GAMUT DESTINATION ---- */ - new_gamut_destination.white_point = - core_color->state[sink_index]. - destination_gamut.white_point; - update_color_gamut_data(&new_gamut_destination, - &core_color->state[sink_index].destination_gamut); - - /* 3. ---- SET DEGAMMA ---- */ - struct dc_transfer_func *input_tf = NULL; - - input_tf = dc_create_transfer_func(); - - if (input_tf != NULL) { - input_tf->type = TF_TYPE_PREDEFINED; - - switch (input_transfer_function) { - case transfer_func_srgb: - input_tf->tf = TRANSFER_FUNCTION_SRGB; - break; - case transfer_func_linear_0_1: - case transfer_func_linear_0_125: - input_tf->tf = TRANSFER_FUNCTION_LINEAR; - break; - default: - dc_transfer_func_release(input_tf); - input_tf = NULL; - break; - } - } - - /* 4. ---- SET REGAMMA ---- */ - struct dc_transfer_func *output_tf = NULL; - - output_tf = dc_create_transfer_func(); - - if (output_tf != NULL) { - output_tf->type = TF_TYPE_PREDEFINED; - if (is_hdr) - output_tf->tf = TRANSFER_FUNCTION_PQ; - else - output_tf->tf = TRANSFER_FUNCTION_SRGB; - } - /* 5. ---- POPULATE HDR METADATA ---- */ - core_color->state[sink_index].mastering_info.is_hdr = is_hdr; - - /* 6. ---- TODO: UPDATE INFOPACKETS ---- */ - - if (!mod_color_update_gamut_to_stream( - mod_color, streams, num_streams)) - return false; - - struct dc_surface_update updates[4] = {0}; - - updates[0].surface = surface; - updates[0].gamma = core_color->state[sink_index].gamma; - updates[0].in_transfer_func = input_tf; - updates[0].out_transfer_func = output_tf; - updates[0].hdr_static_metadata = - &core_color->state[sink_index].mastering_info; - - dc_update_surfaces_for_target(core_color->dc, updates, 1, NULL); - - if (input_tf != NULL) - dc_transfer_func_release(input_tf); - - if (output_tf != NULL) - dc_transfer_func_release(output_tf); - } - return true; -} diff --git a/drivers/gpu/drm/amd/display/modules/color/color_helper.c b/drivers/gpu/drm/amd/display/modules/color/color_helper.c deleted file mode 100644 index ff6779cdd623..000000000000 --- a/drivers/gpu/drm/amd/display/modules/color/color_helper.c +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright 2016 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" -#include "dc.h" -#include "mod_color.h" -#include "color_helper.h" - -const struct gamut_space_entry predefined_gamuts[] = { - /* x_red y_red x_gr y_gr x_blue y_blue a0 a1 a2 a3 gamma */ - [gamut_type_bt709] = {6400, 3300, 3000, 6000, 1500, 600, 180000, 4500, 99, 99, 2200}, - [gamut_type_bt601] = {6400, 3300, 2900, 6000, 1500, 600, 180000, 4500, 99, 99, 2200}, - [gamut_type_adobe_rgb] = {6400, 3300, 2100, 7100, 1500, 600, 180000, 4500, 99, 99, 2200}, - [gamut_type_srgb] = {6400, 3300, 3000, 6000, 1500, 600, 31308, 12920, 55, 55, 2400}, - [gamut_type_bt2020] = {7080, 2920, 1700, 7970, 1310, 460, 180000, 4500, 99, 99, 2200} -}; - -const struct white_point_coodinates_entry predefined_white_points[] = { - [white_point_type_5000k_horizon] = {5000, 3473, 3561}, - [white_point_type_6500k_noon] = {6500, 3127, 3290}, - [white_point_type_7500k_north_sky] = {7500, 3022, 3129}, - [white_point_type_9300k] = {9300, 2866, 2950} -}; - -const unsigned int white_point_entries = 91; - -const struct white_point_coodinates_entry white_point_temps[] = { - /*001*/{1000, 6499, 3474}, - /*002*/{1100, 6361, 3594}, - /*003*/{1200, 6226, 3703}, - /*004*/{1300, 6095, 3801}, - /*005*/{1400, 5966, 3887}, - /*006*/{1500, 5841, 3962}, - /*007*/{1600, 5720, 4025}, - /*008*/{1700, 5601, 4076}, - /*009*/{1800, 5486, 4118}, - /*010*/{1900, 5375, 4150}, - /*011*/{2000, 5267, 4173}, - /*012*/{2100, 5162, 4188}, - /*013*/{2200, 5062, 4196}, - /*014*/{2300, 4965, 4198}, - /*015*/{2400, 4872, 4194}, - /*016*/{2500, 4782, 4186}, - /*017*/{2600, 4696, 4173}, - /*018*/{2700, 4614, 4158}, - /*019*/{2800, 4535, 4139}, - /*020*/{2900, 4460, 4118}, - /*021*/{3000, 4388, 4095}, - /*022*/{3100, 4320, 4070}, - /*023*/{3200, 4254, 4044}, - /*024*/{3300, 4192, 4018}, - /*025*/{3400, 4132, 3990}, - /*026*/{3500, 4075, 3962}, - /*027*/{3600, 4021, 3934}, - /*028*/{3700, 3969, 3905}, - /*029*/{3800, 3919, 3877}, - /*030*/{3900, 3872, 3849}, - /*031*/{4000, 3827, 3820}, - /*032*/{4100, 3784, 3793}, - /*033*/{4200, 3743, 3765}, - /*034*/{4300, 3704, 3738}, - /*035*/{4400, 3666, 3711}, - /*036*/{4500, 3631, 3685}, - /*037*/{4600, 3596, 3659}, - /*038*/{4700, 3563, 3634}, - /*039*/{4800, 3532, 3609}, - /*040*/{4900, 3502, 3585}, - /*041*/{5000, 3473, 3561}, - /*042*/{5100, 3446, 3538}, - /*043*/{5200, 3419, 3516}, - /*044*/{5300, 3394, 3494}, - /*045*/{5400, 3369, 3472}, - /*046*/{5500, 3346, 3451}, - /*047*/{5600, 3323, 3431}, - /*048*/{5700, 3302, 3411}, - /*049*/{5800, 3281, 3392}, - /*050*/{5900, 3261, 3373}, - /*051*/{6000, 3242, 3355}, - /*052*/{6100, 3223, 3337}, - /*053*/{6200, 3205, 3319}, - /*054*/{6300, 3188, 3302}, - /*055*/{6400, 3161, 3296}, - /*056*/{6500, 3127, 3290}, /* This is the real white point sRGB */ - /*057*/{6600, 3126, 3264}, - /*058*/{6700, 3125, 3238}, - /*059*/{6800, 3110, 3224}, - /*060*/{6900, 3097, 3209}, - /*061*/{7000, 3083, 3195}, - /*062*/{7100, 3070, 3181}, - /*063*/{7200, 3058, 3168}, - /*064*/{7300, 3045, 3154}, - /*065*/{7400, 3034, 3142}, - /*066*/{7500, 3022, 3129}, - /*067*/{7600, 3011, 3117}, - /*068*/{7700, 3000, 3105}, - /*069*/{7800, 2990, 3094}, - /*070*/{7900, 2980, 3082}, - /*071*/{8000, 2970, 3071}, - /*072*/{8100, 2961, 3061}, - /*073*/{8200, 2952, 3050}, - /*074*/{8300, 2943, 3040}, - /*075*/{8400, 2934, 3030}, - /*076*/{8500, 2926, 3020}, - /*077*/{8600, 2917, 3011}, - /*078*/{8700, 2910, 3001}, - /*079*/{8800, 2902, 2992}, - /*080*/{8900, 2894, 2983}, - /*081*/{9000, 2887, 2975}, - /*082*/{9100, 2880, 2966}, - /*083*/{9200, 2873, 2958}, - /*084*/{9300, 2866, 2950}, - /*085*/{9400, 2860, 2942}, - /*086*/{9500, 2853, 2934}, - /*087*/{9600, 2847, 2927}, - /*088*/{9700, 2841, 2919}, - /*089*/{9800, 2835, 2912}, - /*090*/{9900, 2829, 2905}, - /*091*/{10000, 2824, 2898} -}; - -bool mod_color_find_predefined_gamut( - struct gamut_space_coordinates *out_gamut, - enum predefined_gamut_type type) -{ - out_gamut->redX = predefined_gamuts[type].redX; - out_gamut->redY = predefined_gamuts[type].redY; - out_gamut->greenX = predefined_gamuts[type].greenX; - out_gamut->greenY = predefined_gamuts[type].greenY; - out_gamut->blueX = predefined_gamuts[type].blueX; - out_gamut->blueY = predefined_gamuts[type].blueY; - - return true; -} - -bool mod_color_find_predefined_white_point( - struct white_point_coodinates *out_white_point, - enum predefined_white_point_type type) -{ - out_white_point->whiteX = predefined_white_points[type].whiteX; - out_white_point->whiteY = predefined_white_points[type].whiteY; - - return true; -} - -bool mod_color_find_white_point_from_temperature( - struct white_point_coodinates *out_white_point, - unsigned int temperature) -{ - int i; - unsigned int found = false; - struct white_point_coodinates_entry temp_white_point = - white_point_temps[55]; - - if (temperature < 1000 || temperature > 10000) - return false; - - for (i = 0; i < white_point_entries; i++) { - if (temperature == white_point_temps[i].temperature) { - temp_white_point = white_point_temps[i]; - found = true; - break; - } - } - - out_white_point->whiteX = temp_white_point.whiteX; - out_white_point->whiteY = temp_white_point.whiteY; - - return found; -} - -bool mod_color_find_temperature_from_white_point( - struct white_point_coodinates *in_white_point, - unsigned int *out_temperature) -{ - unsigned int i; - *out_temperature = 6500; - - for (i = 0; i < white_point_entries; i++) { - if (in_white_point->whiteX == white_point_temps[i].whiteX && - in_white_point->whiteY == white_point_temps[i].whiteY) { - *out_temperature = white_point_temps[i].temperature; - return true; - } - } - - return false; -} - diff --git a/drivers/gpu/drm/amd/display/modules/color/color_helper.h b/drivers/gpu/drm/amd/display/modules/color/color_helper.h deleted file mode 100644 index 76575c1dc043..000000000000 --- a/drivers/gpu/drm/amd/display/modules/color/color_helper.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2016 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef COLOR_MOD_COLOR_HELPER_H_ -#define COLOR_MOD_COLOR_HELPER_H_ - -enum predefined_gamut_type { - gamut_type_bt709, - gamut_type_bt601, - gamut_type_adobe_rgb, - gamut_type_srgb, - gamut_type_bt2020, - gamut_type_unknown, -}; - -enum predefined_white_point_type { - white_point_type_5000k_horizon, - white_point_type_6500k_noon, - white_point_type_7500k_north_sky, - white_point_type_9300k, - white_point_type_unknown, -}; - -bool mod_color_find_predefined_gamut( - struct gamut_space_coordinates *out_gamut, - enum predefined_gamut_type type); - -bool mod_color_find_predefined_white_point( - struct white_point_coodinates *out_white_point, - enum predefined_white_point_type type); - -bool mod_color_find_white_point_from_temperature( - struct white_point_coodinates *out_white_point, - unsigned int temperature); - -bool mod_color_find_temperature_from_white_point( - struct white_point_coodinates *in_white_point, - unsigned int *out_temperature); - -#endif /* COLOR_MOD_COLOR_HELPER_H_ */ diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_color.h b/drivers/gpu/drm/amd/display/modules/inc/mod_color.h deleted file mode 100644 index 70349a88916c..000000000000 --- a/drivers/gpu/drm/amd/display/modules/inc/mod_color.h +++ /dev/null @@ -1,282 +0,0 @@ -/* - * Copyright 2016 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - - -#ifndef MOD_COLOR_H_ -#define MOD_COLOR_H_ - -#include "dm_services.h" -#include "color_helper.h" - -enum color_transfer_func { - transfer_func_unknown, - transfer_func_srgb, - transfer_func_bt709, - transfer_func_pq2084, - transfer_func_pq2084_interim, - transfer_func_linear_0_1, - transfer_func_linear_0_125, - transfer_func_dolbyvision, - transfer_func_gamma_22, - transfer_func_gamma_26 -}; - -enum color_color_space { - color_space_unsupported, - color_space_srgb, - color_space_bt601, - color_space_bt709, - color_space_xv_ycc_bt601, - color_space_xv_ycc_bt709, - color_space_xr_rgb, - color_space_bt2020, - color_space_adobe, - color_space_dci_p3, - color_space_sc_rgb_ms_ref, - color_space_display_native, - color_space_app_ctrl, - color_space_dolby_vision, - color_space_custom_coordinates -}; - -enum color_white_point_type { - color_white_point_type_unknown, - color_white_point_type_5000k_horizon, - color_white_point_type_6500k_noon, - color_white_point_type_7500k_north_sky, - color_white_point_type_9300k, - color_white_point_type_custom_coordinates -}; - -enum colorimetry_support_flag { - xv_ycc_bt601 = 0x01, - xv_ycc_bt709 = 0x02, - s_ycc_601 = 0x04, - adobe_ycc_601 = 0x08, - adobe_rgb = 0x10, - bt_2020_c_ycc = 0x20, - bt_2020_ycc = 0x40, - bt_2020_rgb = 0x80 -}; - -enum hdr_tf_support_flag { - traditional_gamma_sdr = 0x01, - traditional_gamma_hdr = 0x02, - smpte_st2084 = 0x04 -}; - -struct mod_color { - int dummy; -}; - -struct color_space_coordinates { - unsigned int redX; - unsigned int redY; - unsigned int greenX; - unsigned int greenY; - unsigned int blueX; - unsigned int blueY; - unsigned int whiteX; - unsigned int whiteY; -}; - -struct gamut_space_coordinates { - unsigned int redX; - unsigned int redY; - unsigned int greenX; - unsigned int greenY; - unsigned int blueX; - unsigned int blueY; -}; - -struct gamut_space_entry { - unsigned int redX; - unsigned int redY; - unsigned int greenX; - unsigned int greenY; - unsigned int blueX; - unsigned int blueY; - - int a0; - int a1; - int a2; - int a3; - int gamma; -}; - -struct white_point_coodinates { - unsigned int whiteX; - unsigned int whiteY; -}; - -struct white_point_coodinates_entry { - unsigned int temperature; - unsigned int whiteX; - unsigned int whiteY; -}; - -struct color_range { - int current; - int min; - int max; -}; - -struct color_gamut_data { - enum color_color_space color_space; - enum color_white_point_type white_point; - struct color_space_coordinates gamut; -}; - -struct color_edid_caps { - unsigned int colorimetry_caps; - unsigned int hdr_caps; -}; - -struct mod_color *mod_color_create(struct dc *dc); - -void mod_color_destroy(struct mod_color *mod_color); - -bool mod_color_add_sink(struct mod_color *mod_color, - const struct dc_sink *sink, struct color_edid_caps *edid_caps); - -bool mod_color_remove_sink(struct mod_color *mod_color, - const struct dc_sink *sink); - -bool mod_color_update_gamut_to_stream(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams); - -bool mod_color_set_white_point(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - struct white_point_coodinates *white_point); - -bool mod_color_adjust_source_gamut(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - struct color_gamut_data *input_gamut_data); - -bool mod_color_adjust_destination_gamut(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - struct color_gamut_data *input_gamut_data); - -bool mod_color_adjust_source_gamut_and_tf(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - struct color_gamut_data *input_gamut_data, - enum color_transfer_func input_transfer_func); - -bool mod_color_get_user_enable(struct mod_color *mod_color, - const struct dc_sink *sink, - bool *user_enable); - -bool mod_color_set_mastering_info(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - const struct dc_hdr_static_metadata *mastering_info); - -bool mod_color_get_mastering_info(struct mod_color *mod_color, - const struct dc_sink *sink, - struct dc_hdr_static_metadata *mastering_info); - -bool mod_color_set_user_enable(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - bool user_enable); - -bool mod_color_get_custom_color_temperature(struct mod_color *mod_color, - const struct dc_sink *sink, - int *color_temperature); - -bool mod_color_set_custom_color_temperature(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - int color_temperature); - -bool mod_color_get_color_saturation(struct mod_color *mod_color, - const struct dc_sink *sink, - struct color_range *color_saturation); - -bool mod_color_get_color_contrast(struct mod_color *mod_color, - const struct dc_sink *sink, - struct color_range *color_contrast); - -bool mod_color_get_color_brightness(struct mod_color *mod_color, - const struct dc_sink *sink, - struct color_range *color_brightness); - -bool mod_color_get_color_hue(struct mod_color *mod_color, - const struct dc_sink *sink, - struct color_range *color_hue); - -bool mod_color_get_source_gamut(struct mod_color *mod_color, - const struct dc_sink *sink, - struct color_space_coordinates *source_gamut); - -bool mod_color_notify_mode_change(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams); - -bool mod_color_set_brightness(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - int brightness_value); - -bool mod_color_set_contrast(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - int contrast_value); - -bool mod_color_set_hue(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - int hue_value); - -bool mod_color_set_saturation(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - int saturation_value); - -bool mod_color_set_input_gamma_correction(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - struct dc_gamma *gamma); - -bool mod_color_persist_user_preferred_quantization_range( - struct mod_color *mod_color, - const struct dc_sink *sink, - enum dc_quantization_range quantization_range); - -bool mod_color_get_preferred_quantization_range(struct mod_color *mod_color, - const struct dc_sink *sink, - const struct dc_crtc_timing *timing, - enum dc_quantization_range *quantization_range); - -bool mod_color_is_rgb_full_range_supported_for_timing( - const struct dc_sink *sink, - const struct dc_crtc_timing *timing); - -bool mod_color_is_rgb_limited_range_supported_for_timing( - const struct dc_sink *sink, - const struct dc_crtc_timing *timing); - -bool mod_color_set_regamma(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams); - -bool mod_color_set_degamma(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - enum color_transfer_func transfer_function); - -bool mod_color_update_gamut_info(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams); - -#endif /* MOD_COLOR_H_ */ diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_power.h b/drivers/gpu/drm/amd/display/modules/inc/mod_power.h deleted file mode 100644 index a204e8d6cd23..000000000000 --- a/drivers/gpu/drm/amd/display/modules/inc/mod_power.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright 2016 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef MODULES_INC_MOD_POWER_H_ -#define MODULES_INC_MOD_POWER_H_ - -#include "dm_services.h" - -struct mod_power { - int dummy; -}; - -/* VariBright related commands */ -enum varibright_command { - VariBright_Cmd__SetVBLevel = 0, - VariBright_Cmd__UserEnable, - VariBright_Cmd__PreDisplayConfigChange, - VariBright_Cmd__PostDisplayConfigChange, - VariBright_Cmd__SuspendABM, - VariBright_Cmd__ResumeABM, - - VariBright_Cmd__Unknown, -}; - -/* VariBright settings structure */ -struct varibright_info { - enum varibright_command cmd; - - unsigned int level; - bool enable; - bool activate; -}; - -enum dmcu_block_psr_reason { - /* This is a bitfield mask */ - dmcu_block_psr_reason_invalid = 0x0, - dmcu_block_psr_reason_vsync_int = 0x1, - dmcu_block_psr_reason_shared_primary = 0x2, - dmcu_block_psr_reason_unsupported_link_rate = 0x4 -}; - -struct mod_power *mod_power_create(struct dc *dc); - -void mod_power_destroy(struct mod_power *mod_power); - -bool mod_power_add_sink(struct mod_power *mod_power, - const struct dc_sink *sink); - -bool mod_power_remove_sink(struct mod_power *mod_power, - const struct dc_sink *sink); - -bool mod_power_set_backlight(struct mod_power *mod_power, - const struct dc_stream **streams, int num_streams, - unsigned int backlight_8bit); - -bool mod_power_get_backlight(struct mod_power *mod_power, - const struct dc_sink *sink, - unsigned int *backlight_8bit); - -void mod_power_initialize_backlight_caps - (struct mod_power *mod_power); - -unsigned int mod_power_backlight_level_percentage_to_signal - (struct mod_power *mod_power, unsigned int percentage); - -unsigned int mod_power_backlight_level_signal_to_percentage - (struct mod_power *mod_power, unsigned int signalLevel8bit); - -bool mod_power_get_panel_backlight_boundaries - (struct mod_power *mod_power, - unsigned int *min_backlight, - unsigned int *max_backlight, - unsigned int *output_ac_level_percentage, - unsigned int *output_dc_level_percentage); - -bool mod_power_set_smooth_brightness(struct mod_power *mod_power, - const struct dc_sink *sink, bool enable_brightness); - -bool mod_power_notify_mode_change(struct mod_power *mod_power, - const struct dc_stream *stream); - -bool mod_power_varibright_control(struct mod_power *mod_power, - struct varibright_info *input_varibright_info); - -bool mod_power_block_psr(bool block_enable, enum dmcu_block_psr_reason reason); - -bool mod_power_set_psr_enable(struct mod_power *mod_power, - bool psr_enable); - -#endif /* MODULES_INC_MOD_POWER_H_ */ diff --git a/drivers/gpu/drm/amd/display/modules/power/power.c b/drivers/gpu/drm/amd/display/modules/power/power.c deleted file mode 100644 index ea07e847da0a..000000000000 --- a/drivers/gpu/drm/amd/display/modules/power/power.c +++ /dev/null @@ -1,784 +0,0 @@ -/* - * Copyright 2016 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "mod_power.h" -#include "dm_services.h" -#include "dc.h" -#include "core_types.h" -#include "core_dc.h" - -#define MOD_POWER_MAX_CONCURRENT_SINKS 32 -#define SMOOTH_BRIGHTNESS_ADJUSTMENT_TIME_IN_MS 500 - -struct sink_caps { - const struct dc_sink *sink; -}; - -struct backlight_state { - unsigned int backlight; - unsigned int frame_ramp; - bool smooth_brightness_enabled; -}; - -struct core_power { - struct mod_power public; - struct dc *dc; - int num_sinks; - struct sink_caps *caps; - struct backlight_state *state; -}; - -union dmcu_abm_set_bl_params { - struct { - unsigned int gradual_change : 1; /* [0:0] */ - unsigned int reserved : 15; /* [15:1] */ - unsigned int frame_ramp : 16; /* [31:16] */ - } bits; - unsigned int u32All; -}; - -/* Backlight cached properties */ -static unsigned int backlight_8bit_lut_array[101]; -static unsigned int ac_level_percentage; -static unsigned int dc_level_percentage; -static bool backlight_caps_valid; -/* we use lazy initialization of backlight capabilities cache */ -static bool backlight_caps_initialized; -/* AC/DC levels initialized later in separate context */ -static bool backlight_def_levels_valid; - -/* ABM cached properties */ -static unsigned int abm_level; -static bool abm_user_enable; -static bool abm_active; - -/*PSR cached properties*/ -static unsigned int block_psr; - -/* Defines default backlight curve F(x) = A(x*x) + Bx + C. - * - * Backlight curve should always satisfy F(0) = min, F(100) = max, - * so polynom coefficients are: - * A is 0.0255 - B/100 - min/10000 - (255-max)/10000 = (max - min)/10000 - B/100 - * B is adjustable factor to modify the curve. - * Bigger B results in less concave curve. B range is [0..(max-min)/100] - * C is backlight minimum - */ -static const unsigned int backlight_curve_coeff_a_factor = 10000; -static const unsigned int backlight_curve_coeff_b = 100; -static const unsigned int backlight_curve_coeff_b_factor = 100; - -/* Minimum and maximum backlight input signal levels */ -static const unsigned int default_min_backlight = 12; -static const unsigned int default_max_backlight = 255; - -/* Other backlight constants */ -static const unsigned int absolute_backlight_max = 255; - -#define MOD_POWER_TO_CORE(mod_power)\ - container_of(mod_power, struct core_power, public) - -static bool check_dc_support(const struct dc *dc) -{ - if (dc->stream_funcs.set_backlight == NULL) - return false; - - return true; -} - -/* Given a specific dc_sink* this function finds its equivalent - * on the dc_sink array and returns the corresponding index - */ -static unsigned int sink_index_from_sink(struct core_power *core_power, - const struct dc_sink *sink) -{ - unsigned int index = 0; - - for (index = 0; index < core_power->num_sinks; index++) - if (core_power->caps[index].sink == sink) - return index; - - /* Could not find sink requested */ - ASSERT(false); - return index; -} - -static unsigned int convertBL8to17(unsigned int backlight_8bit) -{ - unsigned int temp_ulong = backlight_8bit * 0x10101; - unsigned char temp_uchar = - (unsigned char)(((temp_ulong & 0x80) >> 7) & 1); - - temp_ulong = (temp_ulong >> 8) + temp_uchar; - - return temp_ulong; -} - -static uint16_t convertBL8to16(unsigned int backlight_8bit) -{ - return (uint16_t)((backlight_8bit * 0x10101) >> 8); -} - -/*This is used when OS wants to retrieve the current BL. - * We return the 8bit value to OS. - */ -static unsigned int convertBL17to8(unsigned int backlight_17bit) -{ - if (backlight_17bit & 0x10000) - return default_max_backlight; - else - return (backlight_17bit >> 8); -} - -struct mod_power *mod_power_create(struct dc *dc) -{ - struct core_power *core_power = - dm_alloc(sizeof(struct core_power)); - - struct core_dc *core_dc = DC_TO_CORE(dc); - - int i = 0; - - if (core_power == NULL) - goto fail_alloc_context; - - core_power->caps = dm_alloc(sizeof(struct sink_caps) * - MOD_POWER_MAX_CONCURRENT_SINKS); - - if (core_power->caps == NULL) - goto fail_alloc_caps; - - for (i = 0; i < MOD_POWER_MAX_CONCURRENT_SINKS; i++) - core_power->caps[i].sink = NULL; - - core_power->state = dm_alloc(sizeof(struct backlight_state) * - MOD_POWER_MAX_CONCURRENT_SINKS); - - if (core_power->state == NULL) - goto fail_alloc_state; - - core_power->num_sinks = 0; - backlight_caps_valid = false; - - if (dc == NULL) - goto fail_construct; - - core_power->dc = dc; - - if (!check_dc_support(dc)) - goto fail_construct; - - abm_user_enable = false; - abm_active = false; - - return &core_power->public; - -fail_construct: - dm_free(core_power->state); - -fail_alloc_state: - dm_free(core_power->caps); - -fail_alloc_caps: - dm_free(core_power); - -fail_alloc_context: - return NULL; -} - - -void mod_power_destroy(struct mod_power *mod_power) -{ - if (mod_power != NULL) { - int i; - struct core_power *core_power = - MOD_POWER_TO_CORE(mod_power); - - dm_free(core_power->state); - - for (i = 0; i < core_power->num_sinks; i++) - dc_sink_release(core_power->caps[i].sink); - - dm_free(core_power->caps); - - dm_free(core_power); - } -} - -bool mod_power_add_sink(struct mod_power *mod_power, - const struct dc_sink *sink) -{ - if (sink->sink_signal == SIGNAL_TYPE_VIRTUAL) - return false; - - struct core_power *core_power = - MOD_POWER_TO_CORE(mod_power); - struct core_dc *core_dc = DC_TO_CORE(core_power->dc); - - if (core_power->num_sinks < MOD_POWER_MAX_CONCURRENT_SINKS) { - dc_sink_retain(sink); - core_power->caps[core_power->num_sinks].sink = sink; - core_power->state[core_power->num_sinks]. - smooth_brightness_enabled = false; - core_power->state[core_power->num_sinks]. - backlight = 100; - core_power->num_sinks++; - return true; - } - - return false; -} - -bool mod_power_remove_sink(struct mod_power *mod_power, - const struct dc_sink *sink) -{ - int i = 0, j = 0; - struct core_power *core_power = - MOD_POWER_TO_CORE(mod_power); - - for (i = 0; i < core_power->num_sinks; i++) { - if (core_power->caps[i].sink == sink) { - /* To remove this sink, shift everything after down */ - for (j = i; j < core_power->num_sinks - 1; j++) { - core_power->caps[j].sink = - core_power->caps[j + 1].sink; - - memcpy(&core_power->state[j], - &core_power->state[j + 1], - sizeof(struct backlight_state)); - } - core_power->num_sinks--; - dc_sink_release(sink); - return true; - } - } - return false; -} - -bool mod_power_set_backlight(struct mod_power *mod_power, - const struct dc_stream **streams, int num_streams, - unsigned int backlight_8bit) -{ - struct core_power *core_power = - MOD_POWER_TO_CORE(mod_power); - - unsigned int frame_ramp = 0; - - unsigned int stream_index, sink_index, vsync_rate_hz; - - union dmcu_abm_set_bl_params params; - - for (stream_index = 0; stream_index < num_streams; stream_index++) { - if (streams[stream_index]->sink->sink_signal == SIGNAL_TYPE_VIRTUAL) { - core_power->state[sink_index].backlight = 0; - core_power->state[sink_index].frame_ramp = 0; - core_power->state[sink_index].smooth_brightness_enabled = false; - continue; - } - - sink_index = sink_index_from_sink(core_power, - streams[stream_index]->sink); - - vsync_rate_hz = div64_u64(div64_u64((streams[stream_index]-> - timing.pix_clk_khz * 1000), - streams[stream_index]->timing.v_total), - streams[stream_index]->timing.h_total); - - core_power->state[sink_index].backlight = backlight_8bit; - - if (core_power->state[sink_index].smooth_brightness_enabled) - frame_ramp = ((vsync_rate_hz * - SMOOTH_BRIGHTNESS_ADJUSTMENT_TIME_IN_MS) + 500) - / 1000; - else - frame_ramp = 0; - - core_power->state[sink_index].frame_ramp = frame_ramp; - } - - params.u32All = 0; - params.bits.gradual_change = (frame_ramp > 0); - params.bits.frame_ramp = frame_ramp; - - core_power->dc->stream_funcs.set_backlight - (core_power->dc, backlight_8bit, params.u32All, streams[0]); - - return true; -} - -bool mod_power_get_backlight(struct mod_power *mod_power, - const struct dc_sink *sink, - unsigned int *backlight_8bit) -{ - if (sink->sink_signal == SIGNAL_TYPE_VIRTUAL) - return false; - - struct core_power *core_power = - MOD_POWER_TO_CORE(mod_power); - - unsigned int sink_index = sink_index_from_sink(core_power, sink); - - *backlight_8bit = core_power->state[sink_index].backlight; - - return true; -} - -/* hard coded to default backlight curve. */ -void mod_power_initialize_backlight_caps(struct mod_power - *mod_power) -{ - struct core_power *core_power = - MOD_POWER_TO_CORE(mod_power); - struct core_dc *core_dc = DC_TO_CORE(core_power->dc); - unsigned int i; - - backlight_caps_initialized = true; - - struct dm_acpi_atif_backlight_caps *pExtCaps = NULL; - bool customCurvePresent = false; - bool customMinMaxPresent = false; - bool customDefLevelsPresent = false; - - /* Allocate memory for ATIF output - * (do not want to use 256 bytes on the stack) - */ - pExtCaps = (struct dm_acpi_atif_backlight_caps *) - (dm_alloc(sizeof(struct dm_acpi_atif_backlight_caps))); - if (pExtCaps == NULL) - return; - - /* Retrieve ACPI extended brightness caps */ - if (dm_query_extended_brightness_caps - (core_dc->ctx, AcpiDisplayType_LCD1, pExtCaps)) { - ac_level_percentage = pExtCaps->acLevelPercentage; - dc_level_percentage = pExtCaps->dcLevelPercentage; - customMinMaxPresent = true; - customDefLevelsPresent = true; - customCurvePresent = (pExtCaps->numOfDataPoints > 0); - - ASSERT(pExtCaps->numOfDataPoints <= 99); - } else { - dm_free(pExtCaps); - return; - } - - if (customMinMaxPresent) - backlight_8bit_lut_array[0] = pExtCaps->minInputSignal; - else - backlight_8bit_lut_array[0] = default_min_backlight; - - if (customMinMaxPresent) - backlight_8bit_lut_array[100] = pExtCaps->maxInputSignal; - else - backlight_8bit_lut_array[100] = default_max_backlight; - - ASSERT(backlight_8bit_lut_array[100] <= absolute_backlight_max); - ASSERT(backlight_8bit_lut_array[0] <= - backlight_8bit_lut_array[100]); - - /* Just to make sure we use valid values */ - if (backlight_8bit_lut_array[100] > absolute_backlight_max) - backlight_8bit_lut_array[100] = absolute_backlight_max; - if (backlight_8bit_lut_array[0] > backlight_8bit_lut_array[100]) { - unsigned int swap; - - swap = backlight_8bit_lut_array[0]; - backlight_8bit_lut_array[0] = backlight_8bit_lut_array[100]; - backlight_8bit_lut_array[100] = swap; - } - - /* Build backlight translation table for custom curve */ - if (customCurvePresent) { - unsigned int index = 1; - unsigned int numOfDataPoints = - (pExtCaps->numOfDataPoints <= 99 ? - pExtCaps->numOfDataPoints : 99); - - /* Filling translation table from data points - - * between every two provided data points we - * lineary interpolate missing values - */ - for (i = 0; i < numOfDataPoints; i++) { - /* Clamp signal level between min and max - * (since min and max might come other - * soruce like registry) - */ - unsigned int luminance = - pExtCaps->dataPoints[i].luminance; - unsigned int signalLevel = - pExtCaps->dataPoints[i].signalLevel; - - if (signalLevel < backlight_8bit_lut_array[0]) - signalLevel = backlight_8bit_lut_array[0]; - if (signalLevel > backlight_8bit_lut_array[100]) - signalLevel = backlight_8bit_lut_array[100]; - - /* Lineary interpolate missing values */ - if (index < luminance) { - unsigned int baseValue = - backlight_8bit_lut_array[index-1]; - unsigned int deltaSignal = - signalLevel - baseValue; - unsigned int deltaLuma = - luminance - index + 1; - unsigned int step = deltaSignal; - - for (; index < luminance; index++) { - backlight_8bit_lut_array[index] = - baseValue + (step / deltaLuma); - step += deltaSignal; - } - } - - /* Now [index == luminance], - * so we can add data point to the translation table - */ - backlight_8bit_lut_array[index++] = signalLevel; - } - - /* Complete the final segment of interpolation - - * between last datapoint and maximum value - */ - if (index < 100) { - unsigned int baseValue = - backlight_8bit_lut_array[index-1]; - unsigned int deltaSignal = - backlight_8bit_lut_array[100] - - baseValue; - unsigned int deltaLuma = 100 - index + 1; - unsigned int step = deltaSignal; - - for (; index < 100; index++) { - backlight_8bit_lut_array[index] = - baseValue + (step / deltaLuma); - step += deltaSignal; - } - } - /* Build backlight translation table based on default curve */ - } else { - unsigned int delta = - backlight_8bit_lut_array[100] - - backlight_8bit_lut_array[0]; - unsigned int coeffC = backlight_8bit_lut_array[0]; - unsigned int coeffB = - (backlight_curve_coeff_b < delta ? - backlight_curve_coeff_b : delta); - unsigned int coeffA = delta - coeffB; /* coeffB is B*100 */ - - for (i = 1; i < 100; i++) { - backlight_8bit_lut_array[i] = - (coeffA * i * i) / - backlight_curve_coeff_a_factor + - (coeffB * i) / - backlight_curve_coeff_b_factor + - coeffC; - } - } - - if (pExtCaps != NULL) - dm_free(pExtCaps); - - /* Successfully initialized */ - backlight_caps_valid = true; - backlight_def_levels_valid = customDefLevelsPresent; -} - -unsigned int mod_power_backlight_level_percentage_to_signal( - struct mod_power *mod_power, unsigned int percentage) -{ - /* Do lazy initialization of backlight capabilities*/ - if (!backlight_caps_initialized) - mod_power_initialize_backlight_caps(mod_power); - - /* Since the translation table is indexed by percentage, - * we simply return backlight value at given percent - */ - if (backlight_caps_valid && percentage <= 100) - return backlight_8bit_lut_array[percentage]; - - return -1; -} - -unsigned int mod_power_backlight_level_signal_to_percentage( - struct mod_power *mod_power, - unsigned int signalLevel8bit) -{ - unsigned int invalid_backlight = (unsigned int)(-1); - /* Do lazy initialization of backlight capabilities */ - if (!backlight_caps_initialized) - mod_power_initialize_backlight_caps(mod_power); - - /* If customer curve cannot convert to differentiated value near min - * it is important to report 0 for min signal to pass setting "Dimmed" - * setting in HCK brightness2 tests. - */ - if (signalLevel8bit <= backlight_8bit_lut_array[0]) - return 0; - - /* Since the translation table is indexed by percentage - * we need to do a binary search over the array - * Another option would be to guess entry based on linear distribution - * and then do linear search in correct direction - */ - if (backlight_caps_valid && signalLevel8bit <= - absolute_backlight_max) { - unsigned int min = 0; - unsigned int max = 100; - unsigned int mid = invalid_backlight; - - while (max >= min) { - mid = (min + max) / 2; /* floor of half range */ - - if (backlight_8bit_lut_array[mid] < signalLevel8bit) - min = mid + 1; - else if (backlight_8bit_lut_array[mid] > - signalLevel8bit) - max = mid - 1; - else - break; - - if (max == 0 || max == 1) - return invalid_backlight; - } - return mid; - } - - return invalid_backlight; -} - - -bool mod_power_get_panel_backlight_boundaries( - struct mod_power *mod_power, - unsigned int *min_backlight, - unsigned int *max_backlight, - unsigned int *output_ac_level_percentage, - unsigned int *output_dc_level_percentage) -{ - /* Do lazy initialization of backlight capabilities */ - if (!backlight_caps_initialized) - mod_power_initialize_backlight_caps(mod_power); - - /* If cache was successfully updated, - * copy the values to output structure and return success - */ - if (backlight_caps_valid) { - *min_backlight = backlight_8bit_lut_array[0]; - *max_backlight = backlight_8bit_lut_array[100]; - - *output_ac_level_percentage = ac_level_percentage; - *output_dc_level_percentage = dc_level_percentage; - - return true; - } - - return false; -} - -bool mod_power_set_smooth_brightness(struct mod_power *mod_power, - const struct dc_sink *sink, bool enable_brightness) -{ - if (sink->sink_signal == SIGNAL_TYPE_VIRTUAL) - return false; - - struct core_power *core_power = - MOD_POWER_TO_CORE(mod_power); - unsigned int sink_index = sink_index_from_sink(core_power, sink); - - core_power->state[sink_index].smooth_brightness_enabled - = enable_brightness; - return true; -} - -bool mod_power_notify_mode_change(struct mod_power *mod_power, - const struct dc_stream *stream) -{ - if (stream->sink->sink_signal == SIGNAL_TYPE_VIRTUAL) - return false; - - struct core_power *core_power = - MOD_POWER_TO_CORE(mod_power); - - unsigned int sink_index = sink_index_from_sink(core_power, - stream->sink); - unsigned int frame_ramp = core_power->state[sink_index].frame_ramp; - union dmcu_abm_set_bl_params params; - - params.u32All = 0; - params.bits.gradual_change = (frame_ramp > 0); - params.bits.frame_ramp = frame_ramp; - - core_power->dc->stream_funcs.set_backlight - (core_power->dc, - core_power->state[sink_index].backlight, - params.u32All, stream); - - core_power->dc->stream_funcs.setup_psr - (core_power->dc, stream); - - return true; -} - - -static bool mod_power_abm_feature_enable(struct mod_power - *mod_power, bool enable) -{ - struct core_power *core_power = - MOD_POWER_TO_CORE(mod_power); - if (abm_user_enable == enable) - return true; - - abm_user_enable = enable; - - if (enable) { - if (abm_level != 0 && abm_active) - core_power->dc->stream_funcs.set_abm_level - (core_power->dc, abm_level); - } else { - if (abm_level != 0 && abm_active) { - abm_level = 0; - core_power->dc->stream_funcs.set_abm_level - (core_power->dc, abm_level); - } - } - - return true; -} - -static bool mod_power_abm_activate(struct mod_power - *mod_power, bool activate) -{ - struct core_power *core_power = - MOD_POWER_TO_CORE(mod_power); - if (abm_active == activate) - return true; - - abm_active = activate; - - if (activate) { - if (abm_level != 0 && abm_user_enable) - core_power->dc->stream_funcs.set_abm_level - (core_power->dc, abm_level); - } else { - if (abm_level != 0 && abm_user_enable) { - abm_level = 0; - core_power->dc->stream_funcs.set_abm_level - (core_power->dc, abm_level); - } - } - - return true; -} - -static bool mod_power_abm_set_level(struct mod_power *mod_power, - unsigned int level) -{ - struct core_power *core_power = - MOD_POWER_TO_CORE(mod_power); - if (abm_level == level) - return true; - - if (abm_active && abm_user_enable && level == 0) - core_power->dc->stream_funcs.set_abm_level - (core_power->dc, 0); - else if (abm_active && abm_user_enable && level != 0) - core_power->dc->stream_funcs.set_abm_level - (core_power->dc, level); - - abm_level = level; - - return true; -} - -bool mod_power_varibright_control(struct mod_power *mod_power, - struct varibright_info *input_varibright_info) -{ - switch (input_varibright_info->cmd) { - case VariBright_Cmd__SetVBLevel: - { - /* Set VariBright user level. */ - mod_power_abm_set_level(mod_power, - input_varibright_info->level); - } - break; - - case VariBright_Cmd__UserEnable: - { - /* Set VariBright user enable state. */ - mod_power_abm_feature_enable(mod_power, - input_varibright_info->enable); - } - break; - - case VariBright_Cmd__PostDisplayConfigChange: - { - /* Set VariBright user level. */ - mod_power_abm_set_level(mod_power, - input_varibright_info->level); - - /* Set VariBright user enable state. */ - mod_power_abm_feature_enable(mod_power, - input_varibright_info->enable); - - /* Set VariBright activate based on power state. */ - mod_power_abm_activate(mod_power, - input_varibright_info->activate); - } - break; - - default: - { - return false; - } - break; - } - - return true; -} - -bool mod_power_block_psr(bool block_enable, enum dmcu_block_psr_reason reason) -{ - if (block_enable) - block_psr |= reason; - else - block_psr &= ~reason; - - return true; -} - - -bool mod_power_set_psr_enable(struct mod_power *mod_power, - bool psr_enable) -{ - struct core_power *core_power = - MOD_POWER_TO_CORE(mod_power); - - if (block_psr == 0) - return core_power->dc->stream_funcs.set_psr_enable - (core_power->dc, psr_enable); - - return false; -} - - -- cgit From 886391680cce3b7c4543b88bbd4eb49c80c26532 Mon Sep 17 00:00:00 2001 From: Zeyu Fan Date: Fri, 23 Dec 2016 16:53:12 -0500 Subject: drm/amd/display: Fix link retraining hw sequence Signed-off-by: Zeyu Fan Reviewed-by: Hersen Wu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 15 +++---- drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 49 +++++++++++++++++++++- drivers/gpu/drm/amd/display/dc/dc.h | 3 +- drivers/gpu/drm/amd/display/dc/inc/link_hwss.h | 4 ++ 4 files changed, 62 insertions(+), 9 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 69819d834543..ad1ce600a165 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -357,17 +357,18 @@ static void perform_link_training(struct dc *dc, } static void set_preferred_link_settings(struct dc *dc, - struct dc_link_settings *link_setting) + struct dc_link_settings *link_setting, + const struct dc_link *link) { - struct core_dc *core_dc = DC_TO_CORE(dc); - int i; + struct core_link *core_link = DC_LINK_TO_CORE(link); - for (i = 0; i < core_dc->link_count; i++) { - core_dc->links[i]->public.verified_link_cap.lane_count = + core_link->public.verified_link_cap.lane_count = link_setting->lane_count; - core_dc->links[i]->public.verified_link_cap.link_rate = + core_link->public.verified_link_cap.link_rate = link_setting->link_rate; - } + dp_retrain_link_physi(core_link, + link_setting, + false); } static void enable_hpd(const struct dc_link *link) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 4febc8d2a96d..f870a0e72074 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -200,7 +200,6 @@ void dp_set_hw_test_pattern( encoder->funcs->dp_set_phy_pattern(encoder, &pattern_param); } - void dp_retrain_link(struct core_link *link) { struct pipe_ctx *pipes = link->dc->current_context->res_ctx.pipe_ctx; @@ -221,3 +220,51 @@ void dp_retrain_link(struct core_link *link) } } } + +void dp_retrain_link_physi(struct core_link *link, + struct dc_link_settings *link_setting, + bool skip_video_pattern) +{ + struct pipe_ctx *pipes = + &link->dc->current_context->res_ctx.pipe_ctx[0]; + unsigned int i; + + for (i = 0; i < MAX_PIPES; i++) { + if (pipes[i].stream != NULL && + pipes[i].stream->sink != NULL && + pipes[i].stream->sink->link != NULL && + pipes[i].stream_enc != NULL && + pipes[i].stream->sink->link == link) { + dm_delay_in_microseconds(link->ctx, 100); + + pipes[i].stream_enc->funcs->dp_blank( + pipes[i].stream_enc); + + dp_receiver_power_ctrl(link, false); + + link->link_enc->funcs->disable_output( + link->link_enc, + SIGNAL_TYPE_DISPLAY_PORT); + + /* Clear current link setting. + * memset(&link->public.cur_link_settings, 0, + * sizeof(link->public.cur_link_settings)); + */ + + link->link_enc->funcs->enable_dp_output( + link->link_enc, + link_setting, + pipes[i].clock_source->id); + + dp_receiver_power_ctrl(link, true); + + dc_link_dp_perform_link_training( + &link->public, + link_setting, + skip_video_pattern); + + link->dc->hwss.unblank_stream(&pipes[i], + link_setting); + } + } +} diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 599f8b0894c2..83d78c2dc24d 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -117,7 +117,8 @@ struct dc_link_funcs { struct dc_link_settings *link_setting, bool skip_video_pattern); void (*set_preferred_link_settings)(struct dc *dc, - struct dc_link_settings *link_setting); + struct dc_link_settings *link_setting, + const struct dc_link *link); void (*enable_hpd)(const struct dc_link *link); void (*disable_hpd)(const struct dc_link *link); void (*set_test_pattern)( diff --git a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h index 662fa30d45f7..30831c54878b 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h +++ b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h @@ -70,4 +70,8 @@ enum dp_panel_mode dp_get_panel_mode(struct core_link *link); void dp_retrain_link(struct core_link *link); +void dp_retrain_link_physi(struct core_link *link, + struct dc_link_settings *link_setting, + bool skip_video_pattern); + #endif /* __DC_LINK_HWSS_H__ */ -- cgit From 73c7260292db3f506b2562cbb25c06adfe90ca99 Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Thu, 29 Dec 2016 14:58:54 -0500 Subject: drm/amd/display: Fix link retraining hw sequence for auto test Signed-off-by: Hersen Wu Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 4 +--- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 4 ++-- drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 27 ++++------------------ drivers/gpu/drm/amd/display/dc/inc/link_hwss.h | 4 +--- 4 files changed, 9 insertions(+), 30 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index ad1ce600a165..a7c6c980927e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -366,9 +366,7 @@ static void set_preferred_link_settings(struct dc *dc, link_setting->lane_count; core_link->public.verified_link_cap.link_rate = link_setting->link_rate; - dp_retrain_link_physi(core_link, - link_setting, - false); + dp_retrain_link_dp_test(core_link, link_setting, false); } static void enable_hpd(const struct dc_link *link) 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 d32bf61b66e9..a661fc6a69dd 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 @@ -1532,7 +1532,7 @@ static bool handle_hpd_irq_psr_sink(const struct core_link *link) static void dp_test_send_link_training(struct core_link *link) { - struct dc_link_settings link_settings; + struct dc_link_settings link_settings = {0}; core_link_read_dpcd( link, @@ -1549,7 +1549,7 @@ static void dp_test_send_link_training(struct core_link *link) link->public.verified_link_cap.lane_count = link_settings.lane_count; link->public.verified_link_cap.link_rate = link_settings.link_rate; - dp_retrain_link(link); + dp_retrain_link_dp_test(link, &link_settings, false); } static void dp_test_send_phy_test_pattern(struct core_link *link) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index f870a0e72074..e287584ade29 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -200,28 +200,7 @@ void dp_set_hw_test_pattern( encoder->funcs->dp_set_phy_pattern(encoder, &pattern_param); } -void dp_retrain_link(struct core_link *link) -{ - struct pipe_ctx *pipes = link->dc->current_context->res_ctx.pipe_ctx; - unsigned int i; - - for (i = 0; i < MAX_PIPES; i++) { - if (pipes[i].stream_enc != NULL) { - dm_delay_in_microseconds(link->ctx, 100); - pipes->stream_enc->funcs->dp_blank(pipes[i].stream_enc); - link->dc->hwss.disable_stream(&pipes[i]); - dc_link_dp_perform_link_training( - &link->public, - &link->public.verified_link_cap, - true); - link->dc->hwss.enable_stream(&pipes[i]); - link->dc->hwss.unblank_stream(&pipes[i], - &link->public.verified_link_cap); - } - } -} - -void dp_retrain_link_physi(struct core_link *link, +void dp_retrain_link_dp_test(struct core_link *link, struct dc_link_settings *link_setting, bool skip_video_pattern) { @@ -240,6 +219,10 @@ void dp_retrain_link_physi(struct core_link *link, pipes[i].stream_enc->funcs->dp_blank( pipes[i].stream_enc); + /* disable any test pattern that might be active */ + dp_set_hw_test_pattern(link, + DP_TEST_PATTERN_VIDEO_MODE, NULL, 0); + dp_receiver_power_ctrl(link, false); link->link_enc->funcs->disable_output( diff --git a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h index 30831c54878b..75d10e93b002 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h +++ b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h @@ -68,9 +68,7 @@ void dp_set_hw_test_pattern( enum dp_panel_mode dp_get_panel_mode(struct core_link *link); -void dp_retrain_link(struct core_link *link); - -void dp_retrain_link_physi(struct core_link *link, +void dp_retrain_link_dp_test(struct core_link *link, struct dc_link_settings *link_setting, bool skip_video_pattern); -- cgit From 4dfb0badee55bf163f4ce3307572cd4963c791d0 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Thu, 29 Dec 2016 10:56:32 -0500 Subject: drm/amd/display: simplify link_encoder - remove unnecessary feature flags - remove wireless and VGA validation Signed-off-by: Tony Cheng Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 8 +-- .../gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 64 ++-------------------- .../gpu/drm/amd/display/dc/inc/hw/link_encoder.h | 20 +------ .../amd/display/dc/virtual/virtual_link_encoder.c | 4 -- 4 files changed, 6 insertions(+), 90 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index b2fc290b5385..b0f316344e86 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -317,7 +317,6 @@ static bool is_dp_sink_present(struct core_link *link) { enum gpio_result gpio_result; uint32_t clock_pin = 0; - uint32_t data_pin = 0; struct ddc *ddc; @@ -353,12 +352,7 @@ static bool is_dp_sink_present(struct core_link *link) gpio_result = dal_gpio_get_value(ddc->pin_clock, &clock_pin); ASSERT(gpio_result == GPIO_RESULT_OK); - if (gpio_result == GPIO_RESULT_OK) - if (link->link_enc->features.flags.bits. - DP_SINK_DETECT_POLL_DATA_PIN) - gpio_result = dal_gpio_get_value(ddc->pin_data, &data_pin); - - present = (gpio_result == GPIO_RESULT_OK) && !(clock_pin || data_pin); + present = (gpio_result == GPIO_RESULT_OK) && !clock_pin; dal_ddc_close(ddc); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index ea4778b6e6d8..aa6b3449913c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -67,11 +67,6 @@ #define HPD_REG(reg)\ (enc110->hpd_regs->reg) -/* For current ASICs pixel clock - 600MHz */ -#define MAX_ENCODER_CLK 600000 - -#define DCE11_UNIPHY_MAX_PIXEL_CLK_IN_KHZ 594000 - #define DEFAULT_AUX_MAX_DATA_SIZE 16 #define AUX_MAX_DEFER_WRITE_RETRY 20 /* @@ -845,18 +840,15 @@ bool dce110_link_encoder_validate_dvi_output( { uint32_t max_pixel_clock = TMDS_MAX_PIXEL_CLOCK; - if (enc110->base.features.max_pixel_clock < TMDS_MAX_PIXEL_CLOCK) - max_pixel_clock = enc110->base.features.max_pixel_clock; - if (signal == SIGNAL_TYPE_DVI_DUAL_LINK) - max_pixel_clock <<= 1; + max_pixel_clock *= 2; /* This handles the case of HDMI downgrade to DVI we don't want to * we don't want to cap the pixel clock if the DDI is not DVI. */ if (connector_signal != SIGNAL_TYPE_DVI_DUAL_LINK && connector_signal != SIGNAL_TYPE_DVI_SINGLE_LINK) - max_pixel_clock = enc110->base.features.max_pixel_clock; + max_pixel_clock = enc110->base.features.max_hdmi_pixel_clock; /* DVI only support RGB pixel encoding */ if (crtc_timing->pixel_encoding != PIXEL_ENCODING_RGB) @@ -893,9 +885,6 @@ static bool dce110_link_encoder_validate_hdmi_output( enum dc_color_depth max_deep_color = enc110->base.features.max_hdmi_deep_color; - if (max_deep_color > enc110->base.features.max_deep_color) - max_deep_color = enc110->base.features.max_deep_color; - if (max_deep_color < crtc_timing->display_color_depth) return false; @@ -903,8 +892,7 @@ static bool dce110_link_encoder_validate_hdmi_output( return false; if ((adjusted_pix_clk_khz == 0) || - (adjusted_pix_clk_khz > enc110->base.features.max_hdmi_pixel_clock) || - (adjusted_pix_clk_khz > enc110->base.features.max_pixel_clock)) + (adjusted_pix_clk_khz > enc110->base.features.max_hdmi_pixel_clock)) return false; /* DCE11 HW does not support 420 */ @@ -915,19 +903,6 @@ static bool dce110_link_encoder_validate_hdmi_output( return true; } -bool dce110_link_encoder_validate_rgb_output( - const struct dce110_link_encoder *enc110, - const struct dc_crtc_timing *crtc_timing) -{ - if (crtc_timing->pix_clk_khz > enc110->base.features.max_pixel_clock) - return false; - - if (crtc_timing->pixel_encoding != PIXEL_ENCODING_RGB) - return false; - - return true; -} - bool dce110_link_encoder_validate_dp_output( const struct dce110_link_encoder *enc110, const struct dc_crtc_timing *crtc_timing) @@ -949,21 +924,6 @@ bool dce110_link_encoder_validate_dp_output( return false; } -bool dce110_link_encoder_validate_wireless_output( - const struct dce110_link_encoder *enc110, - const struct dc_crtc_timing *crtc_timing) -{ - if (crtc_timing->pix_clk_khz > enc110->base.features.max_pixel_clock) - return false; - - /* Wireless only supports YCbCr444 */ - if (crtc_timing->pixel_encoding == - PIXEL_ENCODING_YCBCR444) - return true; - - return false; -} - bool dce110_link_encoder_construct( struct dce110_link_encoder *enc110, const struct encoder_init_data *init_data, @@ -985,12 +945,6 @@ bool dce110_link_encoder_construct( enc110->base.transmitter = init_data->transmitter; - enc110->base.features.flags.bits.IS_AUDIO_CAPABLE = true; - - enc110->base.features.max_pixel_clock = - MAX_ENCODER_CLK; - - enc110->base.features.max_deep_color = COLOR_DEPTH_121212; enc110->base.features.max_hdmi_deep_color = COLOR_DEPTH_121212; if (enc110->base.ctx->dc->debug.disable_hdmi_deep_color) @@ -1070,7 +1024,6 @@ bool dce110_link_encoder_construct( bp_cap_info.DP_HBR2_CAP; enc110->base.features.flags.bits.IS_HBR3_CAPABLE = bp_cap_info.DP_HBR3_EN; - } /* TODO: check PPLIB maxPhyClockInKHz <= 540000, if yes, @@ -1082,7 +1035,6 @@ bool dce110_link_encoder_construct( /* test pattern 4 support */ enc110->base.features.flags.bits.IS_TPS4_CAPABLE = true; - enc110->base.features.flags.bits.IS_Y_ONLY_CAPABLE = false; /* dal_adapter_service_is_feature_supported(as, FEATURE_SUPPORT_DP_Y_ONLY); @@ -1118,22 +1070,14 @@ bool dce110_link_encoder_validate_output_with_stream( &stream->public.timing, stream->phy_pix_clk); break; - case SIGNAL_TYPE_RGB: - is_valid = dce110_link_encoder_validate_rgb_output( - enc110, &stream->public.timing); - break; case SIGNAL_TYPE_DISPLAY_PORT: case SIGNAL_TYPE_DISPLAY_PORT_MST: case SIGNAL_TYPE_EDP: is_valid = dce110_link_encoder_validate_dp_output( enc110, &stream->public.timing); break; - case SIGNAL_TYPE_WIRELESS: - is_valid = dce110_link_encoder_validate_wireless_output( - enc110, &stream->public.timing); - break; default: - is_valid = true; + is_valid = false; break; } diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h index 77f8aa410898..49c4b6587456 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h @@ -33,34 +33,16 @@ struct encoder_init_data { struct encoder_feature_support { union { struct { - /* 1 - external encoder; 0 - internal encoder */ - uint32_t EXTERNAL_ENCODER:1; - uint32_t ANALOG_ENCODER:1; - uint32_t STEREO_SYNC:1; - /* check the DDC data pin - * when performing DP Sink detection */ - uint32_t DP_SINK_DETECT_POLL_DATA_PIN:1; - /* CPLIB authentication - * for external DP chip supported */ - uint32_t CPLIB_DP_AUTHENTICATION:1; uint32_t IS_HBR2_CAPABLE:1; uint32_t IS_HBR3_CAPABLE:1; - uint32_t IS_HBR2_VALIDATED:1; uint32_t IS_TPS3_CAPABLE:1; uint32_t IS_TPS4_CAPABLE:1; - uint32_t IS_AUDIO_CAPABLE:1; - uint32_t IS_VCE_SUPPORTED:1; - uint32_t IS_CONVERTER:1; - uint32_t IS_Y_ONLY_CAPABLE:1; uint32_t IS_YCBCR_CAPABLE:1; } bits; uint32_t raw; } flags; - /* maximum supported deep color depth */ - enum dc_color_depth max_deep_color; + enum dc_color_depth max_hdmi_deep_color; - /* maximum supported clock */ - unsigned int max_pixel_clock; unsigned int max_hdmi_pixel_clock; bool ycbcr420_supported; }; diff --git a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c index bb4433ff3b6e..869dedca0b17 100644 --- a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c @@ -28,8 +28,6 @@ #include "virtual_link_encoder.h" -#define VIRTUAL_MAX_PIXEL_CLK_IN_KHZ 600000 - static bool virtual_link_encoder_validate_output_with_stream( struct link_encoder *enc, struct pipe_ctx *pipe_ctx) { return true; } @@ -138,8 +136,6 @@ bool virtual_link_encoder_construct( enc->transmitter = init_data->transmitter; - enc->features.max_pixel_clock = VIRTUAL_MAX_PIXEL_CLK_IN_KHZ; - enc->output_signals = SIGNAL_TYPE_VIRTUAL; enc->preferred_engine = ENGINE_ID_VIRTUAL; -- cgit From 7fc698a0c0e5901923a6d6c04a59aceefffe4c9b Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Tue, 3 Jan 2017 12:40:40 -0500 Subject: drm/amd/display: limit HBR3 support to Polaris and up - also fix YCbCr420 supported on Polaris and up Signed-off-by: Tony Cheng Reviewed-by: Hersen Wu Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 31 ++++------------------ .../gpu/drm/amd/display/dc/dce/dce_link_encoder.h | 1 + .../drm/amd/display/dc/dce100/dce100_resource.c | 11 ++++++-- .../drm/amd/display/dc/dce110/dce110_resource.c | 11 ++++++-- .../drm/amd/display/dc/dce112/dce112_resource.c | 15 +++++++++-- .../gpu/drm/amd/display/dc/dce80/dce80_resource.c | 11 ++++++-- 6 files changed, 46 insertions(+), 34 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index aa6b3449913c..323493b9e129 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -927,10 +927,14 @@ bool dce110_link_encoder_validate_dp_output( bool dce110_link_encoder_construct( struct dce110_link_encoder *enc110, const struct encoder_init_data *init_data, + const struct encoder_feature_support *enc_features, const struct dce110_link_enc_registers *link_regs, const struct dce110_link_enc_aux_registers *aux_regs, const struct dce110_link_enc_hpd_registers *hpd_regs) { + struct bp_encoder_cap_info bp_cap_info = {0}; + const struct dc_vbios_funcs *bp_funcs = init_data->ctx->dc_bios->funcs; + enc110->base.funcs = &dce110_lnk_enc_funcs; enc110->base.ctx = init_data->ctx; enc110->base.id = init_data->encoder; @@ -941,12 +945,10 @@ bool dce110_link_encoder_construct( enc110->base.preferred_engine = ENGINE_ID_UNKNOWN; - enc110->base.features.flags.raw = 0; + enc110->base.features = *enc_features; enc110->base.transmitter = init_data->transmitter; - enc110->base.features.max_hdmi_deep_color = COLOR_DEPTH_121212; - if (enc110->base.ctx->dc->debug.disable_hdmi_deep_color) enc110->base.features.max_hdmi_deep_color = COLOR_DEPTH_888; @@ -1013,10 +1015,6 @@ bool dce110_link_encoder_construct( init_data->channel); /* Override features with DCE-specific values */ - { - struct bp_encoder_cap_info bp_cap_info = {0}; - const struct dc_vbios_funcs *bp_funcs = enc110->base.ctx->dc_bios->funcs; - if (BP_RESULT_OK == bp_funcs->get_encoder_cap_info( enc110->base.ctx->dc_bios, enc110->base.id, &bp_cap_info)) @@ -1024,26 +1022,7 @@ bool dce110_link_encoder_construct( bp_cap_info.DP_HBR2_CAP; enc110->base.features.flags.bits.IS_HBR3_CAPABLE = bp_cap_info.DP_HBR3_EN; - } - - /* TODO: check PPLIB maxPhyClockInKHz <= 540000, if yes, - * IS_HBR3_CAPABLE = 0. - */ - /* test pattern 3 support */ - enc110->base.features.flags.bits.IS_TPS3_CAPABLE = true; - /* test pattern 4 support */ - enc110->base.features.flags.bits.IS_TPS4_CAPABLE = true; - - /* - dal_adapter_service_is_feature_supported(as, - FEATURE_SUPPORT_DP_Y_ONLY); -*/ - enc110->base.features.flags.bits.IS_YCBCR_CAPABLE = true; - /* - dal_adapter_service_is_feature_supported(as, - FEATURE_SUPPORT_DP_YUV); - */ return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h index 1635b239402f..b3667df5250b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h @@ -236,6 +236,7 @@ struct dce110_abm_backlight_registers { bool dce110_link_encoder_construct( struct dce110_link_encoder *enc110, const struct encoder_init_data *init_data, + const struct encoder_feature_support *enc_features, const struct dce110_link_enc_registers *link_regs, const struct dce110_link_enc_aux_registers *aux_regs, const struct dce110_link_enc_hpd_registers *hpd_regs); diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 161d4eee4423..082f1f053a3a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -581,6 +581,14 @@ static struct input_pixel_processor *dce100_ipp_create( return NULL; } +static const struct encoder_feature_support link_enc_feature = { + .max_hdmi_deep_color = COLOR_DEPTH_121212, + .max_hdmi_pixel_clock = 300000, + .flags.bits.IS_HBR2_CAPABLE = true, + .flags.bits.IS_TPS3_CAPABLE = true, + .flags.bits.IS_YCBCR_CAPABLE = true +}; + struct link_encoder *dce100_link_encoder_create( const struct encoder_init_data *enc_init_data) { @@ -593,12 +601,11 @@ struct link_encoder *dce100_link_encoder_create( if (dce110_link_encoder_construct( enc110, enc_init_data, + &link_enc_feature, &link_enc_regs[enc_init_data->transmitter], &link_enc_aux_regs[enc_init_data->channel - 1], &link_enc_hpd_regs[enc_init_data->hpd_source])) { - enc110->base.features.ycbcr420_supported = false; - enc110->base.features.max_hdmi_pixel_clock = 300000; return &enc110->base; } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index d4e1ca933b40..ae90da8c1b8c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -570,6 +570,14 @@ static struct input_pixel_processor *dce110_ipp_create( return NULL; } +static const struct encoder_feature_support link_enc_feature = { + .max_hdmi_deep_color = COLOR_DEPTH_121212, + .max_hdmi_pixel_clock = 594000, + .flags.bits.IS_HBR2_CAPABLE = true, + .flags.bits.IS_TPS3_CAPABLE = true, + .flags.bits.IS_YCBCR_CAPABLE = true +}; + struct link_encoder *dce110_link_encoder_create( const struct encoder_init_data *enc_init_data) { @@ -582,12 +590,11 @@ struct link_encoder *dce110_link_encoder_create( if (dce110_link_encoder_construct( enc110, enc_init_data, + &link_enc_feature, &link_enc_regs[enc_init_data->transmitter], &link_enc_aux_regs[enc_init_data->channel - 1], &link_enc_hpd_regs[enc_init_data->hpd_source])) { - enc110->base.features.ycbcr420_supported = false; - enc110->base.features.max_hdmi_pixel_clock = 594000; return &enc110->base; } diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 2711893b71e5..c63030e9f515 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -564,6 +564,18 @@ static struct transform *dce112_transform_create( dm_free(transform); return NULL; } + +static const struct encoder_feature_support link_enc_feature = { + .max_hdmi_deep_color = COLOR_DEPTH_121212, + .max_hdmi_pixel_clock = 600000, + .ycbcr420_supported = true, + .flags.bits.IS_HBR2_CAPABLE = true, + .flags.bits.IS_HBR3_CAPABLE = true, + .flags.bits.IS_TPS3_CAPABLE = true, + .flags.bits.IS_TPS4_CAPABLE = true, + .flags.bits.IS_YCBCR_CAPABLE = true +}; + struct link_encoder *dce112_link_encoder_create( const struct encoder_init_data *enc_init_data) { @@ -576,12 +588,11 @@ struct link_encoder *dce112_link_encoder_create( if (dce110_link_encoder_construct( enc110, enc_init_data, + &link_enc_feature, &link_enc_regs[enc_init_data->transmitter], &link_enc_aux_regs[enc_init_data->channel - 1], &link_enc_hpd_regs[enc_init_data->hpd_source])) { - enc110->base.features.ycbcr420_supported = false; - enc110->base.features.max_hdmi_pixel_clock = 600000; return &enc110->base; } diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 56a63d985440..e2bfa7efce1c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -611,6 +611,14 @@ static struct input_pixel_processor *dce80_ipp_create( return NULL; } +static const struct encoder_feature_support link_enc_feature = { + .max_hdmi_deep_color = COLOR_DEPTH_121212, + .max_hdmi_pixel_clock = 297000, + .flags.bits.IS_HBR2_CAPABLE = true, + .flags.bits.IS_TPS3_CAPABLE = true, + .flags.bits.IS_YCBCR_CAPABLE = true +}; + struct link_encoder *dce80_link_encoder_create( const struct encoder_init_data *enc_init_data) { @@ -623,12 +631,11 @@ struct link_encoder *dce80_link_encoder_create( if (dce110_link_encoder_construct( enc110, enc_init_data, + &link_enc_feature, &link_enc_regs[enc_init_data->transmitter], &link_enc_aux_regs[enc_init_data->channel - 1], &link_enc_hpd_regs[enc_init_data->hpd_source])) { - enc110->base.features.ycbcr420_supported = false; - enc110->base.features.max_hdmi_pixel_clock = 297000; return &enc110->base; } -- cgit From 18f39f2d674e6556d169dcf1a42493c2a632c005 Mon Sep 17 00:00:00 2001 From: Roman Li Date: Tue, 3 Jan 2017 13:46:45 -0500 Subject: drm/amd/display: fix gamma for dpms usecase For dpms usecase we need to set surface transfer function regardless of gamma set flag. Signed-off-by: Roman Li Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index da8bd66f99ee..8807b48bc110 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -515,7 +515,6 @@ static void fill_gamma_from_crtc( struct dc_gamma *gamma; struct drm_crtc_state *state = crtc->state; struct drm_color_lut *lut = (struct drm_color_lut *) state->gamma_lut->data; - struct dc_transfer_func *input_tf; gamma = dc_create_gamma(); @@ -529,16 +528,6 @@ static void fill_gamma_from_crtc( } dc_surface->gamma_correction = gamma; - - input_tf = dc_create_transfer_func(); - - if (input_tf == NULL) - return; - - input_tf->type = TF_TYPE_PREDEFINED; - input_tf->tf = TRANSFER_FUNCTION_SRGB; - - dc_surface->in_transfer_func = input_tf; } static void fill_plane_attributes( @@ -549,6 +538,7 @@ static void fill_plane_attributes( const struct amdgpu_framebuffer *amdgpu_fb = to_amdgpu_framebuffer(state->fb); const struct drm_crtc *crtc = state->crtc; + struct dc_transfer_func *input_tf; fill_rects_from_plane_state(state, surface); fill_plane_attributes_from_fb( @@ -557,6 +547,16 @@ static void fill_plane_attributes( amdgpu_fb, addrReq); + input_tf = dc_create_transfer_func(); + + if (input_tf == NULL) + return; + + input_tf->type = TF_TYPE_PREDEFINED; + input_tf->tf = TRANSFER_FUNCTION_SRGB; + + surface->in_transfer_func = input_tf; + /* In case of gamma set, update gamma value */ if (state->crtc->state->gamma_lut) { fill_gamma_from_crtc(crtc, surface); -- cgit From bf5cda339d3609408624afcb6f533f4eabc7d142 Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Wed, 4 Jan 2017 10:22:35 -0500 Subject: drm/amd/display: Fix DP PHY test pre-emphasis not set properly Signed-off-by: Hersen Wu Reviewed-by: Hersen Wu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 15 +++++++++++---- drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 9 +++++---- drivers/gpu/drm/amd/display/dc/dc.h | 3 ++- drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 2 +- 4 files changed, 19 insertions(+), 10 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index a7c6c980927e..25e7d7bc282b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -332,14 +332,21 @@ static bool setup_psr(struct dc *dc, const struct dc_stream *stream) } static void set_drive_settings(struct dc *dc, - struct link_training_settings *lt_settings) + struct link_training_settings *lt_settings, + const struct dc_link *link) { struct core_dc *core_dc = DC_TO_CORE(dc); int i; - for (i = 0; i < core_dc->link_count; i++) - dc_link_dp_set_drive_settings(&core_dc->links[i]->public, - lt_settings); + for (i = 0; i < core_dc->link_count; i++) { + if (&core_dc->links[i]->public == link) + break; + } + + if (i >= core_dc->link_count) + ASSERT_CRITICAL(false); + + dc_link_dp_set_drive_settings(&core_dc->links[i]->public, lt_settings); } static void perform_link_training(struct dc *dc, diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index e287584ade29..da49be0672d7 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -229,10 +229,9 @@ void dp_retrain_link_dp_test(struct core_link *link, link->link_enc, SIGNAL_TYPE_DISPLAY_PORT); - /* Clear current link setting. - * memset(&link->public.cur_link_settings, 0, - * sizeof(link->public.cur_link_settings)); - */ + /* Clear current link setting. */ + memset(&link->public.cur_link_settings, 0, + sizeof(link->public.cur_link_settings)); link->link_enc->funcs->enable_dp_output( link->link_enc, @@ -246,6 +245,8 @@ void dp_retrain_link_dp_test(struct core_link *link, link_setting, skip_video_pattern); + link->public.cur_link_settings = *link_setting; + link->dc->hwss.unblank_stream(&pipes[i], link_setting); } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 83d78c2dc24d..64002268818a 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -112,7 +112,8 @@ struct link_training_settings; struct dc_link_funcs { void (*set_drive_settings)(struct dc *dc, - struct link_training_settings *lt_settings); + struct link_training_settings *lt_settings, + const struct dc_link *link); void (*perform_link_training)(struct dc *dc, struct dc_link_settings *link_setting, bool skip_video_pattern); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 323493b9e129..cb5e5953b7ab 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -1363,7 +1363,7 @@ void dce110_link_encoder_dp_set_lane_settings( cntl.pixel_clock = link_settings->link_settings.link_rate * LINK_RATE_REF_FREQ_IN_KHZ; - for (lane = 0; lane < link_settings->link_settings.lane_count; ++lane) { + for (lane = 0; lane < link_settings->link_settings.lane_count; lane++) { /* translate lane settings */ training_lane_set.bits.VOLTAGE_SWING_SET = -- cgit From 7abcf6b5043a94e850d8f38b625fd022492e8303 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Thu, 29 Dec 2016 13:21:31 -0500 Subject: drm/amd/display: [MST] Fix startup sequence v3. Problem: MST topology discovery was started before fbdev init causing kernel panic on boot. Fix: Defer MST to late init hook, after fbdev strucutres already initilized. v2: Add explicit late_init hook function in DAL. v3: Change signature of detect_mst_link_for_all_connectors from void* to drm_dev* Signed-off-by: Andrey Grodzovsky Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 35 ++++++++++++++--------- 1 file changed, 22 insertions(+), 13 deletions(-) (limited to 'drivers/gpu') 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 2a7802c67eae..2af4ac0bffcb 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -367,27 +367,39 @@ static int dm_sw_fini(void *handle) return 0; } -static void detect_link_for_all_connectors(struct drm_device *dev) +static int detect_mst_link_for_all_connectors(struct drm_device *dev) { struct amdgpu_connector *aconnector; struct drm_connector *connector; + int ret = 0; drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); list_for_each_entry(connector, &dev->mode_config.connector_list, head) { aconnector = to_amdgpu_connector(connector); - if (aconnector->dc_link->type == dc_connection_mst_branch) { - DRM_INFO("DM_MST: starting TM on aconnector: %p [id: %d]\n", - aconnector, aconnector->base.base.id); - - if (drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_mgr, true) < 0) { - DRM_ERROR("DM_MST: Failed to start MST\n"); - ((struct dc_link *)aconnector->dc_link)->type = dc_connection_single; + if (aconnector->dc_link->type == dc_connection_mst_branch) { + DRM_INFO("DM_MST: starting TM on aconnector: %p [id: %d]\n", + aconnector, aconnector->base.base.id); + + ret = drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_mgr, true); + if (ret < 0) { + DRM_ERROR("DM_MST: Failed to start MST\n"); + ((struct dc_link *)aconnector->dc_link)->type = dc_connection_single; + return ret; } - } + } } drm_modeset_unlock(&dev->mode_config.connection_mutex); + return ret; +} + +static int dm_late_init(void *handle) +{ + struct drm_device *dev = ((struct amdgpu_device *)handle)->ddev; + int r = detect_mst_link_for_all_connectors(dev); + + return r; } static void s3_handle_mst(struct drm_device *dev, bool suspend) @@ -417,11 +429,8 @@ static int dm_hw_init(void *handle) struct amdgpu_device *adev = (struct amdgpu_device *)handle; /* Create DAL display manager */ amdgpu_dm_init(adev); - amdgpu_dm_hpd_init(adev); - detect_link_for_all_connectors(adev->ddev); - return 0; } @@ -680,7 +689,7 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev ) static const struct amd_ip_funcs amdgpu_dm_funcs = { .name = "dm", .early_init = dm_early_init, - .late_init = NULL, + .late_init = dm_late_init, .sw_init = dm_sw_init, .sw_fini = dm_sw_fini, .hw_init = dm_hw_init, -- cgit From 7a8b8b1403a115fe303e67d356df7520095222d4 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Wed, 4 Jan 2017 18:41:25 -0500 Subject: drm/amd/display: Remove unused function in gamma_calcs Signed-off-by: Harry Wentland Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c | 39 ---------------------- 1 file changed, 39 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c index ca2234e4b7d2..fd300db833c7 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c @@ -185,45 +185,6 @@ static bool setup_custom_float( return true; } -static bool convert_to_custom_float_format_ex( - struct fixed31_32 value, - const struct custom_float_format *format, - struct custom_float_value *result) -{ - return build_custom_float( - value, format, - &result->negative, &result->mantissa, &result->exponenta) && - setup_custom_float( - format, result->negative, result->mantissa, result->exponenta, - &result->value); -} - -static bool round_custom_float_6_12( - struct hw_x_point *x) -{ - struct custom_float_format fmt; - - struct custom_float_value value; - - fmt.exponenta_bits = 6; - fmt.mantissa_bits = 12; - fmt.sign = true; - - if (!convert_to_custom_float_format_ex( - x->x, &fmt, &value)) - return false; - - x->adjusted_x = x->x; - - if (value.mantissa) { - BREAK_TO_DEBUGGER(); - - return false; - } - - return true; -} - static bool build_hw_curve_configuration( const struct curve_config *curve_config, struct gamma_curve *gamma_curve, -- cgit From 5727c77cf8de2fd603780151b9c9e17828464360 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Wed, 4 Jan 2017 18:43:04 -0500 Subject: drm/amd/display: Fix misleading indentation bug in link_encoder Signed-off-by: Harry Wentland Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index cb5e5953b7ab..81144586995a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -1017,11 +1017,12 @@ bool dce110_link_encoder_construct( /* Override features with DCE-specific values */ if (BP_RESULT_OK == bp_funcs->get_encoder_cap_info( enc110->base.ctx->dc_bios, enc110->base.id, - &bp_cap_info)) + &bp_cap_info)) { enc110->base.features.flags.bits.IS_HBR2_CAPABLE = bp_cap_info.DP_HBR2_CAP; enc110->base.features.flags.bits.IS_HBR3_CAPABLE = bp_cap_info.DP_HBR3_EN; + } return true; } -- cgit From e5cf325b0c21e626c402b57a055f02c478e3df40 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Wed, 4 Jan 2017 18:48:07 -0500 Subject: drm/amd/display: Fix warnings in DC Signed-off-by: Harry Wentland Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 9 ++++----- drivers/gpu/drm/amd/display/dc/dce/dce_opp.c | 6 ------ drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 1 - drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_gamma.c | 2 -- 4 files changed, 4 insertions(+), 14 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 2b08f5ae5e33..3e3379529b69 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1731,14 +1731,15 @@ static void set_hdr_static_info_packet( struct core_stream *stream, struct hw_info_packet *info_packet) { - uint16_t i; + uint16_t i = 0; enum signal_type signal = stream->signal; + struct dc_hdr_static_metadata hdr_metadata; + uint32_t data; if (!surface) return; - struct dc_hdr_static_metadata hdr_metadata = - surface->public.hdr_static_ctx; + hdr_metadata = surface->public.hdr_static_ctx; if (dc_is_hdmi_signal(signal)) { info_packet->valid = true; @@ -1757,8 +1758,6 @@ static void set_hdr_static_info_packet( i = 2; } - uint32_t data; - data = hdr_metadata.is_hdr; info_packet->sb[i++] = data ? 0x02 : 0x00; info_packet->sb[i++] = 0x00; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c index 46b128708c7e..167f523df657 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c @@ -119,7 +119,6 @@ static void regamma_config_regions_and_segments( const struct pwl_params *params) { const struct gamma_curve *curve; - uint32_t value = 0; { REG_SET_2(REGAMMA_CNTLA_START_CNTL, 0, @@ -565,8 +564,6 @@ void dce110_opp_set_clamping( struct dce110_opp *opp110, const struct clamping_and_pixel_encoding_params *params) { - uint32_t clamp_cntl_value = 0; - REG_SET_2(FMT_CLAMP_CNTL, 0, FMT_CLAMP_DATA_EN, 0, FMT_CLAMP_COLOR_FORMAT, 0); @@ -731,7 +728,6 @@ void dce110_opp_set_dyn_expansion( static void program_formatter_reset_dig_resync_fifo(struct output_pixel_processor *opp) { struct dce110_opp *opp110 = TO_DCE110_OPP(opp); - uint8_t counter = 10; /* clear previous phase lock status*/ REG_UPDATE(FMT_CONTROL, @@ -810,8 +806,6 @@ static bool configure_graphics_mode( enum graphics_csc_adjust_type csc_adjust_type, enum dc_color_space color_space) { - struct dc_context *ctx = opp110->base.ctx; - REG_SET(OUTPUT_CSC_CONTROL, 0, OUTPUT_CSC_GRPH_MODE, 0); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 6a7cb3e9294a..2b61fdf3f03d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -293,7 +293,6 @@ static bool dce110_set_output_transfer_func( { struct output_pixel_processor *opp = pipe_ctx->opp; const struct core_gamma *ramp = NULL; - struct ipp_prescale_params prescale_params = { 0 }; struct pwl_params *regamma_params; bool result = false; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_gamma.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_gamma.c index c68914bf7af0..f05cc9e981f3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_gamma.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_gamma.c @@ -72,8 +72,6 @@ bool dce110_ipp_set_degamma( { struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); - uint32_t value = 0; - uint32_t degamma_type = (mode == IPP_DEGAMMA_MODE_HW_sRGB) ? 1 : 0; ASSERT(mode == IPP_DEGAMMA_MODE_BYPASS || -- cgit From e66e4d64289b647f7787d257dd2be0055ae7df94 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Wed, 4 Jan 2017 18:54:29 -0500 Subject: drm/amd/display: Fix wrong index bug in set_avi_info_frame Signed-off-by: Harry Wentland Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 3e3379529b69..80fe6b9f9397 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1490,9 +1490,10 @@ static void set_avi_info_frame( info_packet->hb2 = info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.hb2; - for (byte_index = 0; byte_index < sizeof(info_packet->sb); byte_index++) + for (byte_index = 0; byte_index < sizeof(info_frame.avi_info_packet. + info_packet_hdmi.packet_raw_data.sb); byte_index++) info_packet->sb[byte_index] = info_frame.avi_info_packet. - info_packet_hdmi.packet_raw_data.sb[byte_index]; + info_packet_hdmi.packet_raw_data.sb[byte_index]; info_packet->valid = true; } -- cgit From 10bff005926af12aa7b1d97ea9bc948ccbaed1c9 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Thu, 5 Jan 2017 11:26:59 -0500 Subject: drm/amd/display: Check hdr support before setting. In case of programing info frame to some monitors don't support HDR, it will result in black screen or corruption when unplug monitor. By checking hdr flag to avoid unnecessary setting for monitors don't support HDR. Signed-off-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 3 +++ .../drm/amd/display/dc/dce/dce_stream_encoder.c | 27 +++++++++++++--------- 2 files changed, 19 insertions(+), 11 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 80fe6b9f9397..a82f2d6ea80f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1742,6 +1742,9 @@ static void set_hdr_static_info_packet( hdr_metadata = surface->public.hdr_static_ctx; + if (!hdr_metadata.is_hdr) + return; + if (dc_is_hdmi_signal(signal)) { info_packet->valid = true; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c index 82133ab3224d..8156c6a8ff5d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c @@ -555,18 +555,23 @@ static void dce110_stream_encoder_update_dp_info_packets( struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); uint32_t value = REG_READ(DP_SEC_CNTL); - dce110_update_generic_info_packet( + if (info_frame->vsc.valid) + dce110_update_generic_info_packet( + enc110, + 0, /* packetIndex */ + &info_frame->vsc); + + if (info_frame->spd.valid) + dce110_update_generic_info_packet( enc110, - 0, /* packetIndex */ - &info_frame->vsc); - dce110_update_generic_info_packet( - enc110, - 2, /* packetIndex */ - &info_frame->spd); - dce110_update_generic_info_packet( - enc110, - 3, /* packetIndex */ - &info_frame->hdrsmd); + 2, /* packetIndex */ + &info_frame->spd); + + if (info_frame->hdrsmd.valid) + dce110_update_generic_info_packet( + enc110, + 3, /* packetIndex */ + &info_frame->hdrsmd); /* enable/disable transmission of packet(s). * If enabled, packet transmission begins on the next frame -- cgit From e33a18f333e8b1abe892e5f5d516e89dffcb5cc3 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Thu, 5 Jan 2017 11:29:27 -0500 Subject: drm/amd/display: fix Infoframe byte 28-31 doesn't get written out to register Signed-off-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c | 4 ++-- drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c index 8156c6a8ff5d..c510e95eb948 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c @@ -137,8 +137,8 @@ static void dce110_update_generic_info_packet( REG_WRITE(AFMT_GENERIC_3, *content++); REG_WRITE(AFMT_GENERIC_4, *content++); REG_WRITE(AFMT_GENERIC_5, *content++); - REG_WRITE(AFMT_GENERIC_6, *content); - REG_WRITE(AFMT_GENERIC_7, 0); + REG_WRITE(AFMT_GENERIC_6, *content++); + REG_WRITE(AFMT_GENERIC_7, *content); } if (!REG(AFMT_VBI_PACKET_CONTROL1)) { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h index 8b4a30459eeb..cb369af29d69 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h @@ -19,7 +19,7 @@ struct encoder_info_packet { uint8_t hb1; uint8_t hb2; uint8_t hb3; - uint8_t sb[28]; + uint8_t sb[32]; }; struct encoder_info_frame { -- cgit From c87af595c03e73cc3175cf282858af22b374e20c Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Thu, 5 Jan 2017 12:59:34 -0500 Subject: drm/amd/display: remove HDMI deep color debug flag Signed-off-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 1 - drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 3 --- 2 files changed, 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 64002268818a..e8cb7a4dee80 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -149,7 +149,6 @@ struct dc_debug { bool disable_power_gate; bool disable_clock_gate; bool disable_dmcu; - bool disable_hdmi_deep_color; bool disable_color_module; }; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 81144586995a..c08337696cf8 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -949,9 +949,6 @@ bool dce110_link_encoder_construct( enc110->base.transmitter = init_data->transmitter; - if (enc110->base.ctx->dc->debug.disable_hdmi_deep_color) - enc110->base.features.max_hdmi_deep_color = COLOR_DEPTH_888; - /* set the flag to indicate whether driver poll the I2C data pin * while doing the DP sink detect */ -- cgit From 546b9b619bfe490ed7cf10c39827e4e578ba8135 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Fri, 6 Jan 2017 11:21:47 -0500 Subject: drm/amd/display: Don't fail validation for SIGNAL_TYPE_VIRTUAL Signed-off-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index c08337696cf8..930ae1377ab6 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -1053,6 +1053,9 @@ bool dce110_link_encoder_validate_output_with_stream( is_valid = dce110_link_encoder_validate_dp_output( enc110, &stream->public.timing); break; + case SIGNAL_TYPE_VIRTUAL: + is_valid = true; + break; default: is_valid = false; break; -- cgit From 2555039d129e4e637cbc6a1048d1005dd9c78b7a Mon Sep 17 00:00:00 2001 From: Xiangliang Yu Date: Tue, 10 Jan 2017 17:34:52 +0800 Subject: drm/amdgpu/virt: disable dc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Virtualization don't need the dc, disable it. Signed-off-by: Xiangliang Yu Reviewed-by: Alex Deucher Acked-by: Christian König Reviewed-by: Monk Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 226d10f288a3..2efb486e283d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2006,6 +2006,9 @@ bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type) */ bool amdgpu_device_has_dc_support(struct amdgpu_device *adev) { + if (amdgpu_sriov_vf(adev)) + return false; + return amdgpu_device_asic_has_dc_support(adev->asic_type); } -- cgit From cf388c0da8e978ed766b975ceccbf699e98bd476 Mon Sep 17 00:00:00 2001 From: Arindam Nath Date: Mon, 9 Jan 2017 11:50:27 +0530 Subject: drm/amd/display: fix cursor disappearing after resume Since during suspend, the cursor registers are cleared, once the system resumes back, the cursor remains disabled. cursor_set_attributes() only sets the cursor attributes along with cursor size and surface address, but does not enable the cursor back on. We need to save the current cursor location so that we can resume back to the same location. This is done in dm_crtc_cursor_move(), where we save the current cursor location into cursor_x and cursor_y. Later during resume we use these same values to set the cursor position along with cursor attributes. Signed-off-by: Arindam Nath Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 38 ++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 8807b48bc110..e1b5f7d7b6da 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -78,6 +78,11 @@ static void dm_set_cursor( uint32_t height) { struct dc_cursor_attributes attributes; + struct dc_cursor_position position; + struct drm_crtc *crtc = &amdgpu_crtc->base; + int x, y; + int xorigin = 0, yorigin = 0; + amdgpu_crtc->cursor_width = width; amdgpu_crtc->cursor_height = height; @@ -91,11 +96,41 @@ static void dm_set_cursor( attributes.rotation_angle = 0; attributes.attribute_flags.value = 0; + x = amdgpu_crtc->cursor_x; + y = amdgpu_crtc->cursor_y; + + /* avivo cursor are offset into the total surface */ + x += crtc->primary->state->src_x >> 16; + y += crtc->primary->state->src_y >> 16; + + if (x < 0) { + xorigin = min(-x, amdgpu_crtc->max_cursor_width - 1); + x = 0; + } + if (y < 0) { + yorigin = min(-y, amdgpu_crtc->max_cursor_height - 1); + y = 0; + } + + position.enable = true; + position.x = x; + position.y = y; + + position.hot_spot_enable = true; + position.x_hotspot = xorigin; + position.y_hotspot = yorigin; + if (!dc_target_set_cursor_attributes( amdgpu_crtc->target, &attributes)) { DRM_ERROR("DC failed to set cursor attributes\n"); } + + if (!dc_target_set_cursor_position( + amdgpu_crtc->target, + &position)) { + DRM_ERROR("DC failed to set cursor position\n"); + } } static int dm_crtc_unpin_cursor_bo_old( @@ -274,6 +309,9 @@ static int dm_crtc_cursor_move(struct drm_crtc *crtc, int xorigin = 0, yorigin = 0; struct dc_cursor_position position; + amdgpu_crtc->cursor_x = x; + amdgpu_crtc->cursor_y = y; + /* avivo cursor are offset into the total surface */ x += crtc->primary->state->src_x >> 16; y += crtc->primary->state->src_y >> 16; -- cgit From b06b7680e341151c8c60b07ddc6f5e63e7392c17 Mon Sep 17 00:00:00 2001 From: Leon Elazar Date: Thu, 5 Jan 2017 17:47:43 -0500 Subject: drm/amd/display: blank mechanism for supporting MPO blank/unblanck functionality apply_ctx_for_surface will update planes visibility by manipulating Blender and CRTC HW modules. Signed-off-by: Leon Elazar Reviewed-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 4 --- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 42 +++++++++++++++++++--- 2 files changed, 37 insertions(+), 9 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 25e7d7bc282b..2277f9bf4bb1 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1246,10 +1246,6 @@ bool dc_pre_update_surfaces_to_target( core_dc, &context->res_ctx.pipe_ctx[j], context); - - if (!new_surfaces[i]->visible) - context->res_ctx.pipe_ctx[j].tg->funcs->set_blank( - context->res_ctx.pipe_ctx[j].tg, true); } unexpected_fail: diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 2b61fdf3f03d..7c27a820e5be 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1409,20 +1409,52 @@ static void set_default_colors(struct pipe_ctx *pipe_ctx) pipe_ctx->opp, &default_adjust); } -static void program_blender(const struct core_dc *dc, + +/******************************************************************************* + * In order to turn on/off specific surface we will program + * Blender + CRTC + * + * In case that we have two surfaces and they have a different visibility + * we can't turn off the CRTC since it will turn off the entire display + * + * |----------------------------------------------- | + * |bottom pipe|curr pipe | | | + * |Surface |Surface | Blender | CRCT | + * |visibility |visibility | Configuration| | + * |------------------------------------------------| + * | off | off | CURRENT_PIPE | blank | + * | off | on | CURRENT_PIPE | unblank | + * | on | off | OTHER_PIPE | unblank | + * | on | on | BLENDING | unblank | + * -------------------------------------------------| + * + ******************************************************************************/ +static void program_surface_visibility(const struct core_dc *dc, struct pipe_ctx *pipe_ctx) { enum blnd_mode blender_mode = BLND_MODE_CURRENT_PIPE; + bool blank_target = false; if (pipe_ctx->bottom_pipe) { + + /* For now we are supporting only two pipes */ + ASSERT(pipe_ctx->bottom_pipe->bottom_pipe == NULL); + if (pipe_ctx->bottom_pipe->surface->public.visible) { if (pipe_ctx->surface->public.visible) blender_mode = BLND_MODE_BLENDING; else blender_mode = BLND_MODE_OTHER_PIPE; - } - } + + } else if (!pipe_ctx->surface->public.visible) + blank_target = true; + + } else if (!pipe_ctx->surface->public.visible) + blank_target = true; + dce_set_blender_mode(dc->hwseq, pipe_ctx->pipe_idx, blender_mode); + pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, blank_target); + } /** @@ -1495,7 +1527,7 @@ static void set_plane_config( pipe_ctx->scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; program_scaler(dc, pipe_ctx); - program_blender(dc, pipe_ctx); + program_surface_visibility(dc, pipe_ctx); mi->funcs->mem_input_program_surface_config( mi, @@ -1920,7 +1952,7 @@ static void dce110_apply_ctx_for_surface( continue; dce110_program_front_end_for_pipe(dc, pipe_ctx); - program_blender(dc, pipe_ctx); + program_surface_visibility(dc, pipe_ctx); } } -- cgit From 4b5e7d620901778b24a2980bbc9941eff9b47f77 Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Fri, 6 Jan 2017 16:23:18 -0500 Subject: drm/amd/display: set blank functionality 1. remove the sleep mechanism while set_blank true from the timing generator. Since Hw sequencer is the one that manages the flow he will be responsible for wait for blanck in a critical places. Signed-off-by: Leon Elazar Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_hw_sequencer.c | 20 +++++++++++ .../amd/display/dc/dce110/dce110_hw_sequencer.c | 12 +++---- .../display/dc/dce110/dce110_timing_generator.c | 28 +--------------- .../display/dc/dce110/dce110_timing_generator.h | 2 +- .../display/dc/dce110/dce110_timing_generator_v.c | 39 +++------------------- .../drm/amd/display/dc/inc/hw/timing_generator.h | 2 +- drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 3 ++ 7 files changed, 37 insertions(+), 69 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c index d5cffa51ca96..9f462a299ff3 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c @@ -91,3 +91,23 @@ void color_space_to_black_color( break; } } + +bool hwss_wait_for_blank_complete( + struct timing_generator *tg) +{ + int counter; + + for (counter = 0; counter < 100; counter++) { + if (tg->funcs->is_blanked(tg)) + break; + + msleep(1); + } + + if (counter == 100) { + dm_error("DC: failed to blank crtc!\n"); + return false; + } + + return true; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 7c27a820e5be..965e47a5acfa 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -623,7 +623,7 @@ static void program_scaler(const struct core_dc *dc, &pipe_ctx->scl_data); } -static enum dc_status prog_pixclk_crtc_otg( +static enum dc_status dce110_prog_pixclk_crtc_otg( struct pipe_ctx *pipe_ctx, struct validate_context *context, struct core_dc *dc) @@ -641,6 +641,7 @@ static enum dc_status prog_pixclk_crtc_otg( pipe_ctx->tg->funcs->set_blank_color( pipe_ctx->tg, &black_color); + /* * Must blank CRTC after disabling power gating and before any * programming, otherwise CRTC will be hung in bad state @@ -1047,7 +1048,8 @@ static void reset_single_pipe_hw_ctx( struct validate_context *context) { core_link_disable_stream(pipe_ctx); - if (!pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, true)) { + pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, true); + if (!hwss_wait_for_blank_complete(pipe_ctx->tg)) { dm_error("DC: failed to blank crtc!\n"); BREAK_TO_DEBUGGER(); } @@ -1560,9 +1562,6 @@ static void update_plane_addr(const struct core_dc *dc, surface->public.flip_immediate); surface->status.requested_address = surface->public.address; - - if (surface->public.visible) - pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, false); } void dce110_update_pending_status(struct pipe_ctx *pipe_ctx) @@ -1718,6 +1717,7 @@ static void init_hw(struct core_dc *dc) /* Blank controller using driver code instead of * command table. */ tg->funcs->set_blank(tg, true); + hwss_wait_for_blank_complete(tg); } for (i = 0; i < dc->res_pool->audio_count; i++) { @@ -2002,7 +2002,7 @@ static const struct hw_sequencer_funcs dce110_funcs = { .set_drr = set_drr, .set_static_screen_control = set_static_screen_control, .reset_hw_ctx_wrap = reset_hw_ctx_wrap, - .prog_pixclk_crtc_otg = prog_pixclk_crtc_otg, + .prog_pixclk_crtc_otg = dce110_prog_pixclk_crtc_otg, }; bool dce110_hw_sequencer_construct(struct core_dc *dc) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c index e70704d1ba87..f4b8576a0546 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c @@ -1808,7 +1808,7 @@ bool dce110_tg_is_blanked(struct timing_generator *tg) return false; } -bool dce110_tg_set_blank(struct timing_generator *tg, +void dce110_tg_set_blank(struct timing_generator *tg, bool enable_blanking) { struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); @@ -1824,8 +1824,6 @@ bool dce110_tg_set_blank(struct timing_generator *tg, value = 0; if (enable_blanking) { - int counter; - set_reg_field_value( value, 1, @@ -1834,32 +1832,8 @@ bool dce110_tg_set_blank(struct timing_generator *tg, dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_BLANK_CONTROL), value); - for (counter = 0; counter < 100; counter++) { - value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_BLANK_CONTROL)); - - if (get_reg_field_value( - value, - CRTC_BLANK_CONTROL, - CRTC_BLANK_DATA_EN) == 1 && - get_reg_field_value( - value, - CRTC_BLANK_CONTROL, - CRTC_CURRENT_BLANK_STATE) == 1) - break; - - msleep(1); - } - - if (counter == 100) { - dm_logger_write(tg->ctx->logger, LOG_ERROR, - "timing generator %d blank timing out.\n", - tg110->controller_id); - return false; - } } else dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_BLANK_CONTROL), 0); - - return true; } bool dce110_tg_validate_timing(struct timing_generator *tg, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h index 39906502ad5c..dcb49fe452c5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h @@ -257,7 +257,7 @@ void dce110_tg_program_timing(struct timing_generator *tg, bool dce110_tg_is_blanked(struct timing_generator *tg); -bool dce110_tg_set_blank(struct timing_generator *tg, +void dce110_tg_set_blank(struct timing_generator *tg, bool enable_blanking); bool dce110_tg_validate_timing(struct timing_generator *tg, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c index 3bf3179e07c5..682a3de7ba48 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c @@ -72,12 +72,11 @@ static bool dce110_timing_generator_v_disable_crtc(struct timing_generator *tg) return true; } -static bool dce110_timing_generator_v_blank_crtc(struct timing_generator *tg) +static void dce110_timing_generator_v_blank_crtc(struct timing_generator *tg) { struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); uint32_t addr = mmCRTCV_BLANK_CONTROL; uint32_t value = dm_read_reg(tg->ctx, addr); - uint8_t counter = 100; set_reg_field_value( value, @@ -92,35 +91,9 @@ static bool dce110_timing_generator_v_blank_crtc(struct timing_generator *tg) CRTC_BLANK_DE_MODE); dm_write_reg(tg->ctx, addr, value); - - while (counter > 0) { - value = dm_read_reg(tg->ctx, addr); - - if (get_reg_field_value( - value, - CRTCV_BLANK_CONTROL, - CRTC_BLANK_DATA_EN) == 1 && - get_reg_field_value( - value, - CRTCV_BLANK_CONTROL, - CRTC_CURRENT_BLANK_STATE) == 1) - break; - - msleep(1); - counter--; - } - - if (!counter) { - dm_logger_write(tg->ctx->logger, LOG_ERROR, - "timing generator %d blank timing out.\n", - tg110->controller_id); - return false; - } - - return true; } -static bool dce110_timing_generator_v_unblank_crtc(struct timing_generator *tg) +static void dce110_timing_generator_v_unblank_crtc(struct timing_generator *tg) { uint32_t addr = mmCRTCV_BLANK_CONTROL; uint32_t value = dm_read_reg(tg->ctx, addr); @@ -138,8 +111,6 @@ static bool dce110_timing_generator_v_unblank_crtc(struct timing_generator *tg) CRTC_BLANK_DE_MODE); dm_write_reg(tg->ctx, addr, value); - - return true; } static bool dce110_timing_generator_v_is_in_vertical_blank( @@ -429,13 +400,13 @@ static void dce110_timing_generator_v_enable_advanced_request( dm_write_reg(tg->ctx, addr, value); } -static bool dce110_timing_generator_v_set_blank(struct timing_generator *tg, +static void dce110_timing_generator_v_set_blank(struct timing_generator *tg, bool enable_blanking) { if (enable_blanking) - return dce110_timing_generator_v_blank_crtc(tg); + dce110_timing_generator_v_blank_crtc(tg); else - return dce110_timing_generator_v_unblank_crtc(tg); + dce110_timing_generator_v_unblank_crtc(tg); } static void dce110_timing_generator_v_program_timing(struct timing_generator *tg, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h index 6ac609f6f89f..baa9445833fb 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h @@ -129,7 +129,7 @@ struct timing_generator_funcs { uint32_t early_cntl); void (*wait_for_state)(struct timing_generator *tg, enum crtc_state state); - bool (*set_blank)(struct timing_generator *tg, + void (*set_blank)(struct timing_generator *tg, bool enable_blanking); bool (*is_blanked)(struct timing_generator *tg); void (*set_overscan_blank_color) (struct timing_generator *tg, const struct tg_color *color); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 895c446cebf9..562c8978fe9c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -151,4 +151,7 @@ void color_space_to_black_color( enum dc_color_space colorspace, struct tg_color *black_color); +bool hwss_wait_for_blank_complete( + struct timing_generator *tg); + #endif /* __DC_HW_SEQUENCER_H__ */ -- cgit From 2796eaee69ce139aa5ae8047bf3071650893ce1d Mon Sep 17 00:00:00 2001 From: Joshua Aberback Date: Mon, 9 Jan 2017 14:43:08 -0500 Subject: drm/amd/display: When signal type of sink is none, use link type for stream Signed-off-by: Joshua Aberback Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index a82f2d6ea80f..59770bc9c8fe 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -984,19 +984,20 @@ static void update_stream_signal(struct core_stream *stream) { const struct dc_sink *dc_sink = stream->public.sink; - stream->signal = dc_sink->sink_signal; - /* For asic supports dual link DVI, we should adjust signal type - * based on timing pixel clock. If pixel clock more than 165Mhz, - * signal is dual link, otherwise, single link. - */ - if (dc_sink->sink_signal == SIGNAL_TYPE_DVI_SINGLE_LINK || - dc_sink->sink_signal == SIGNAL_TYPE_DVI_DUAL_LINK) { - if (stream->public.timing.pix_clk_khz > - TMDS_MAX_PIXEL_CLOCK_IN_KHZ) + if (dc_sink->sink_signal == SIGNAL_TYPE_NONE) + stream->signal = stream->sink->link->public.connector_signal; + else if (dc_sink->sink_signal == SIGNAL_TYPE_DVI_SINGLE_LINK || + dc_sink->sink_signal == SIGNAL_TYPE_DVI_DUAL_LINK) + /* For asic supports dual link DVI, we should adjust signal type + * based on timing pixel clock. If pixel clock more than 165Mhz, + * signal is dual link, otherwise, single link. + */ + if (stream->public.timing.pix_clk_khz > TMDS_MAX_PIXEL_CLOCK_IN_KHZ) stream->signal = SIGNAL_TYPE_DVI_DUAL_LINK; else stream->signal = SIGNAL_TYPE_DVI_SINGLE_LINK; - } + else + stream->signal = dc_sink->sink_signal; } bool resource_is_stream_unchanged( -- cgit From 00c91d0d480a0c5f6507da80f7e13dab7e6b7c79 Mon Sep 17 00:00:00 2001 From: Joshua Aberback Date: Mon, 9 Jan 2017 16:26:58 -0500 Subject: drm/amd/display: Support 64-bit Polaris11 5k VSR - pass full asic_id info into bw_calc_init instead of only version enum - 64-bit Polaris11 needs an extra microsecond of dmif_urgent_latency - add helper to convert from asic_id.family to bw_calc version enum Signed-off-by: Joshua Aberback Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c | 40 ++++++++++++++++++---- .../drm/amd/display/dc/dce110/dce110_resource.c | 5 +-- .../drm/amd/display/dc/dce112/dce112_resource.c | 2 +- .../gpu/drm/amd/display/dc/inc/bandwidth_calcs.h | 2 +- 4 files changed, 37 insertions(+), 12 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c index 3b0710ef4716..aa187736b534 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c @@ -27,11 +27,34 @@ #include "bandwidth_calcs.h" #include "dc.h" #include "core_types.h" +#include "dal_asic_id.h" /******************************************************************************* * Private Functions ******************************************************************************/ +static enum bw_calcs_version bw_calcs_version_from_asic_id(struct hw_asic_id asic_id) +{ + switch (asic_id.chip_family) { + + case FAMILY_CZ: + if (ASIC_REV_IS_STONEY(asic_id.hw_internal_rev)) + return BW_CALCS_VERSION_STONEY; + return BW_CALCS_VERSION_CARRIZO; + + case FAMILY_VI: + if (ASIC_REV_IS_POLARIS10_P(asic_id.hw_internal_rev)) + // || ASIC_REV_IS_POLARIS12_V(asic_id.hw_internal_rev) + return BW_CALCS_VERSION_POLARIS10; + if (ASIC_REV_IS_POLARIS11_M(asic_id.hw_internal_rev)) + return BW_CALCS_VERSION_POLARIS11; + return BW_CALCS_VERSION_INVALID; + + default: + return BW_CALCS_VERSION_INVALID; + } +} + static void calculate_bandwidth( const struct bw_calcs_dceip *dceip, const struct bw_calcs_vbios *vbios, @@ -1954,18 +1977,20 @@ static void calculate_bandwidth( ******************************************************************************/ void bw_calcs_init(struct bw_calcs_dceip *bw_dceip, struct bw_calcs_vbios *bw_vbios, - enum bw_calcs_version version) + struct hw_asic_id asic_id) { struct bw_calcs_dceip dceip = { 0 }; struct bw_calcs_vbios vbios = { 0 }; + enum bw_calcs_version version = bw_calcs_version_from_asic_id(asic_id); + dceip.version = version; switch (version) { case BW_CALCS_VERSION_CARRIZO: vbios.memory_type = bw_def_gddr5; vbios.dram_channel_width_in_bits = 64; - vbios.number_of_dram_channels = 2; + vbios.number_of_dram_channels = asic_id.vram_width / vbios.dram_channel_width_in_bits; vbios.number_of_dram_banks = 8; vbios.high_yclk = bw_int_to_fixed(1600); vbios.mid_yclk = bw_int_to_fixed(1600); @@ -2075,7 +2100,7 @@ void bw_calcs_init(struct bw_calcs_dceip *bw_dceip, case BW_CALCS_VERSION_POLARIS10: vbios.memory_type = bw_def_gddr5; vbios.dram_channel_width_in_bits = 32; - vbios.number_of_dram_channels = 8; + vbios.number_of_dram_channels = asic_id.vram_width / vbios.dram_channel_width_in_bits; vbios.number_of_dram_banks = 8; vbios.high_yclk = bw_int_to_fixed(6000); vbios.mid_yclk = bw_int_to_fixed(3200); @@ -2185,7 +2210,7 @@ void bw_calcs_init(struct bw_calcs_dceip *bw_dceip, case BW_CALCS_VERSION_POLARIS11: vbios.memory_type = bw_def_gddr5; vbios.dram_channel_width_in_bits = 32; - vbios.number_of_dram_channels = 4; + vbios.number_of_dram_channels = asic_id.vram_width / vbios.dram_channel_width_in_bits; vbios.number_of_dram_banks = 8; vbios.high_yclk = bw_int_to_fixed(6000); vbios.mid_yclk = bw_int_to_fixed(3200); @@ -2206,7 +2231,10 @@ void bw_calcs_init(struct bw_calcs_dceip *bw_dceip, vbios.high_voltage_max_phyclk = bw_int_to_fixed(810); vbios.data_return_bus_width = bw_int_to_fixed(32); vbios.trc = bw_int_to_fixed(48); - vbios.dmifmc_urgent_latency = bw_int_to_fixed(3); + if (vbios.number_of_dram_channels == 2) // 64-bit + vbios.dmifmc_urgent_latency = bw_int_to_fixed(4); + else + vbios.dmifmc_urgent_latency = bw_int_to_fixed(3); vbios.stutter_self_refresh_exit_latency = bw_int_to_fixed(5); vbios.stutter_self_refresh_entry_latency = bw_int_to_fixed(0); vbios.nbp_state_change_latency = bw_int_to_fixed(45); @@ -2295,7 +2323,7 @@ void bw_calcs_init(struct bw_calcs_dceip *bw_dceip, case BW_CALCS_VERSION_STONEY: vbios.memory_type = bw_def_gddr5; vbios.dram_channel_width_in_bits = 64; - vbios.number_of_dram_channels = 1; + vbios.number_of_dram_channels = asic_id.vram_width / vbios.dram_channel_width_in_bits; vbios.number_of_dram_banks = 8; vbios.high_yclk = bw_int_to_fixed(1866); vbios.mid_yclk = bw_int_to_fixed(1866); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index ae90da8c1b8c..968ee99003fc 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -1349,10 +1349,7 @@ static bool construct( if (!dce110_hw_sequencer_construct(dc)) goto res_create_fail; - if (ASIC_REV_IS_STONEY(ctx->asic_id.hw_internal_rev)) - bw_calcs_init(&dc->bw_dceip, &dc->bw_vbios, BW_CALCS_VERSION_STONEY); - else - bw_calcs_init(&dc->bw_dceip, &dc->bw_vbios, BW_CALCS_VERSION_CARRIZO); + bw_calcs_init(&dc->bw_dceip, &dc->bw_vbios, dc->ctx->asic_id); bw_calcs_data_update_from_pplib(dc); diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index c63030e9f515..7fca2eb188cf 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -1394,7 +1394,7 @@ static bool construct( if (!dce112_hw_sequencer_construct(dc)) goto res_create_fail; - bw_calcs_init(&dc->bw_dceip, &dc->bw_vbios, BW_CALCS_VERSION_POLARIS11); + bw_calcs_init(&dc->bw_dceip, &dc->bw_vbios, dc->ctx->asic_id); bw_calcs_data_update_from_pplib(dc); diff --git a/drivers/gpu/drm/amd/display/dc/inc/bandwidth_calcs.h b/drivers/gpu/drm/amd/display/dc/inc/bandwidth_calcs.h index f9b871b6199b..16f06fa2d69c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/bandwidth_calcs.h +++ b/drivers/gpu/drm/amd/display/dc/inc/bandwidth_calcs.h @@ -483,7 +483,7 @@ struct bw_calcs_output { void bw_calcs_init( struct bw_calcs_dceip *bw_dceip, struct bw_calcs_vbios *bw_vbios, - enum bw_calcs_version version); + struct hw_asic_id asic_id); /** * Return: -- cgit From 7d7024ca202c502324dce683f2061b35d113a6aa Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 10 Jan 2017 08:35:47 +1000 Subject: drm/amd/display: drop min/max wrappers These aren't needed, and aren't really used in too many places. Signed-off-by: Dave Airlie Reviewed-by: Tony Cheng Reviewed-by: Harry Wentland Reviewed-by: Edward O'Callaghan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 2 +- drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c | 4 ++-- drivers/gpu/drm/amd/display/dc/os_types.h | 2 -- 3 files changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 2277f9bf4bb1..a7348573ebca 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -634,7 +634,7 @@ struct dc *dc_create(const struct dc_init_data *init_params) full_pipe_count = core_dc->res_pool->pipe_count; if (core_dc->res_pool->underlay_pipe_index >= 0) full_pipe_count--; - core_dc->public.caps.max_targets = dm_min( + core_dc->public.caps.max_targets = min( full_pipe_count, core_dc->res_pool->stream_enc_count); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c index 262612061c68..dd922bdcc145 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c @@ -289,7 +289,7 @@ static void dce_set_clock( /* Make sure requested clock isn't lower than minimum threshold*/ if (requested_clk_khz > 0) - requested_clk_khz = dm_max(requested_clk_khz, + requested_clk_khz = max(requested_clk_khz, clk_dce->dentist_vco_freq_khz / 64); /* Prepare to program display clock*/ @@ -364,7 +364,7 @@ static void dce112_set_clock( /* Make sure requested clock isn't lower than minimum threshold*/ if (requested_clk_khz > 0) - requested_clk_khz = dm_max(requested_clk_khz, + requested_clk_khz = max(requested_clk_khz, clk_dce->dentist_vco_freq_khz / 62); dce_clk_params.target_clock_frequency = requested_clk_khz; diff --git a/drivers/gpu/drm/amd/display/dc/os_types.h b/drivers/gpu/drm/amd/display/dc/os_types.h index 7f0c282a1466..27ed2a61c3c8 100644 --- a/drivers/gpu/drm/amd/display/dc/os_types.h +++ b/drivers/gpu/drm/amd/display/dc/os_types.h @@ -52,8 +52,6 @@ #define dm_vlog(fmt, args) vprintk(fmt, args) -#define dm_min(x, y) min(x, y) -#define dm_max(x, y) max(x, y) #endif -- cgit From 3e183c5f083125986dd0cd0ab609252349983f0e Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 10 Jan 2017 09:33:32 +1000 Subject: drm/amd/display: start using linux hdmi header DAL has defines for things, and it doesn't even use them itself. Signed-off-by: Dave Airlie Reviewed-by: Tony Cheng Reviewed-by: Harry Wentland Reviewed-by: Edward O'Callaghan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 18 ++++++++---------- .../gpu/drm/amd/display/include/set_mode_types.h | 22 +--------------------- 2 files changed, 9 insertions(+), 31 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 59770bc9c8fe..4bb6b1d9c970 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1334,13 +1334,12 @@ static void set_avi_info_frame( /* Initialize header */ info_frame.avi_info_packet.info_packet_hdmi.bits.header. - info_frame_type = INFO_FRAME_AVI; + info_frame_type = HDMI_INFOFRAME_TYPE_AVI; /* InfoFrameVersion_3 is defined by CEA861F (Section 6.4), but shall * not be used in HDMI 2.0 (Section 10.1) */ - info_frame.avi_info_packet.info_packet_hdmi.bits.header.version = - INFO_FRAME_VERSION_2; + info_frame.avi_info_packet.info_packet_hdmi.bits.header.version = 2; info_frame.avi_info_packet.info_packet_hdmi.bits.header.length = - INFO_FRAME_SIZE_AVI; + HDMI_AVI_INFOFRAME_SIZE; /* * IDO-defined (Y2,Y1,Y0 = 1,1,1) shall not be used by devices built @@ -1473,10 +1472,9 @@ static void set_avi_info_frame( check_sum = &info_frame. avi_info_packet.info_packet_hdmi.packet_raw_data.sb[0]; - *check_sum = INFO_FRAME_AVI + INFO_FRAME_SIZE_AVI - + INFO_FRAME_VERSION_2; + *check_sum = HDMI_INFOFRAME_TYPE_AVI + HDMI_AVI_INFOFRAME_SIZE + 2; - for (byte_index = 1; byte_index <= INFO_FRAME_SIZE_AVI; byte_index++) + for (byte_index = 1; byte_index <= HDMI_AVI_INFOFRAME_SIZE; byte_index++) *check_sum += info_frame.avi_info_packet.info_packet_hdmi. packet_raw_data.sb[byte_index]; @@ -1588,7 +1586,7 @@ static void set_vendor_info_packet(struct core_stream *stream, info_packet->sb[5] = stream->public.timing.hdmi_vic; /* Header */ - info_packet->hb0 = 0x81; /* VSIF packet type. */ + info_packet->hb0 = HDMI_INFOFRAME_TYPE_VENDOR; /* VSIF packet type. */ info_packet->hb1 = 0x01; /* Version */ /* 4 lower bits = Length, 4 higher bits = 0 (reserved) */ @@ -1629,7 +1627,7 @@ static void set_spd_info_packet(struct core_stream *stream, /* HB0 = Packet Type = 0x83 (Source Product * Descriptor InfoFrame) */ - info_packet->hb0 = 0x83; + info_packet->hb0 = HDMI_INFOFRAME_TYPE_SPD; /* HB1 = Version = 0x01 */ info_packet->hb1 = 0x01; @@ -1651,7 +1649,7 @@ static void set_spd_info_packet(struct core_stream *stream, /* HB1 = Packet Type = 0x83 (Source Product * Descriptor InfoFrame) */ - info_packet->hb1 = 0x83; + info_packet->hb1 = HDMI_INFOFRAME_TYPE_SPD; /* HB2 = [Bits 7:0 = Least significant eight bits - * For INFOFRAME, the value must be 1Bh] diff --git a/drivers/gpu/drm/amd/display/include/set_mode_types.h b/drivers/gpu/drm/amd/display/include/set_mode_types.h index d18210ff5b7a..fee2b6ffcfc1 100644 --- a/drivers/gpu/drm/amd/display/include/set_mode_types.h +++ b/drivers/gpu/drm/amd/display/include/set_mode_types.h @@ -27,6 +27,7 @@ #define __DAL_SET_MODE_TYPES_H__ #include "dc_types.h" +#include /* Info frame packet status */ enum info_frame_flag { @@ -36,27 +37,6 @@ enum info_frame_flag { INFO_PACKET_PACKET_UPDATE_SCAN_TYPE = 8 }; -/* Info frame types */ -enum info_frame_type { - INFO_FRAME_GAMUT = 0x0A, - INFO_FRAME_VENDOR_INFO = 0x81, - INFO_FRAME_AVI = 0x82 -}; - -/* Info frame versions */ -enum info_frame_version { - INFO_FRAME_VERSION_1 = 1, - INFO_FRAME_VERSION_2 = 2, - INFO_FRAME_VERSION_3 = 3 -}; - -/* Info frame size */ -enum info_frame_size { - INFO_FRAME_SIZE_AVI = 13, - INFO_FRAME_SIZE_VENDOR = 25, - INFO_FRAME_SIZE_AUDIO = 10 -}; - struct hdmi_info_frame_header { uint8_t info_frame_type; uint8_t version; -- cgit From 0ea9e02af5572323f79b493ec8d6bfa55effb2f7 Mon Sep 17 00:00:00 2001 From: Ding Wang Date: Tue, 10 Jan 2017 12:47:37 -0500 Subject: drm/amd/display: Use DTO as clock on DP if not Use DVO as pixel clock for DP before enabling link PHY. Otherwise, when switching from HDMI passive dongle to DP on the same connector, the PHY PLL is used as pixel clock, and CRTC would stop working. Signed-off-by: Ding Wang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 25 ++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index da49be0672d7..55d96656e54b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -61,6 +61,31 @@ void dp_enable_link_phy( { struct link_encoder *link_enc = link->link_enc; + struct pipe_ctx *pipes = + link->dc->current_context->res_ctx.pipe_ctx; + struct clock_source *dp_cs = + link->dc->res_pool->dp_clock_source; + unsigned int i; + /* If the current pixel clock source is not DTO(happens after + * switching from HDMI passive dongle to DP on the same connector), + * switch the pixel clock source to DTO. + */ + for (i = 0; i < MAX_PIPES; i++) { + if (pipes[i].stream != NULL && + pipes[i].stream->sink != NULL && + pipes[i].stream->sink->link == link) { + if (pipes[i].clock_source->id != CLOCK_SOURCE_ID_DP_DTO) { + pipes[i].clock_source = dp_cs; + pipes[i].pix_clk_params.requested_pix_clk = + pipes[i].stream->public.timing.pix_clk_khz; + pipes[i].clock_source->funcs->program_pix_clk( + pipes[i].clock_source, + &pipes[i].pix_clk_params, + &pipes[i].pll_settings); + } + } + } + if (dc_is_dp_sst_signal(signal)) { if (signal == SIGNAL_TYPE_EDP) { link_enc->funcs->power_control(link_enc, true); -- cgit From 02dfc70737ae4eafee202d23d29c16213ee750fb Mon Sep 17 00:00:00 2001 From: Joshua Aberback Date: Tue, 10 Jan 2017 14:05:49 -0500 Subject: drm/amd/display: Add Polaris12 to bw_calc Signed-off-by: Joshua Aberback Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c index aa187736b534..54388c0e29e0 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c @@ -44,9 +44,9 @@ static enum bw_calcs_version bw_calcs_version_from_asic_id(struct hw_asic_id asi case FAMILY_VI: if (ASIC_REV_IS_POLARIS10_P(asic_id.hw_internal_rev)) - // || ASIC_REV_IS_POLARIS12_V(asic_id.hw_internal_rev) return BW_CALCS_VERSION_POLARIS10; - if (ASIC_REV_IS_POLARIS11_M(asic_id.hw_internal_rev)) + if (ASIC_REV_IS_POLARIS11_M(asic_id.hw_internal_rev) || + ASIC_REV_IS_POLARIS12_V(asic_id.hw_internal_rev)) return BW_CALCS_VERSION_POLARIS11; return BW_CALCS_VERSION_INVALID; -- cgit From 624d7c4708b27be2dc095579394efadd80f090dd Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Mon, 9 Jan 2017 09:42:33 -0500 Subject: drm/amd/display: Pass visible flag into surface programming Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c | 3 ++- drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h | 3 ++- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 6 ++++-- drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.h | 3 ++- drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c | 3 ++- drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.h | 3 ++- drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h | 3 ++- 7 files changed, 16 insertions(+), 8 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c index e9005e0048e6..130935fffba3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c @@ -372,7 +372,8 @@ void dce_mem_input_program_surface_config(struct mem_input *mi, union plane_size *plane_size, enum dc_rotation_angle rotation, struct dc_plane_dcc_param *dcc, - bool horizontal_mirror) + bool horizontal_mirror, + bool visible) { REG_UPDATE(GRPH_ENABLE, GRPH_ENABLE, 1); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h index 022272d30fe4..f90d586656ef 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h @@ -243,7 +243,8 @@ void dce_mem_input_program_surface_config(struct mem_input *mi, union plane_size *plane_size, enum dc_rotation_angle rotation, struct dc_plane_dcc_param *dcc, - bool horizontal_mirror); + bool horizontal_mirror, + bool visible); void dce_mem_input_allocate_dmif(struct mem_input *mi, uint32_t h_total, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 965e47a5acfa..751dbb88c265 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1538,7 +1538,8 @@ static void set_plane_config( &surface->public.plane_size, surface->public.rotation, NULL, - false); + false, + pipe_ctx->surface->public.visible); if (dc->public.config.gpu_vm_support) mi->funcs->mem_input_program_pte_vm( @@ -1877,8 +1878,9 @@ static void dce110_program_front_end_for_pipe( &surface->public.tiling_info, &surface->public.plane_size, surface->public.rotation, + NULL, false, - false); + pipe_ctx->surface->public.visible); if (dc->public.config.gpu_vm_support) mi->funcs->mem_input_program_pte_vm( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.h index a80a20c09da4..4aec18c94c49 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.h @@ -105,7 +105,8 @@ bool dce110_mem_input_program_surface_config( union plane_size *plane_size, enum dc_rotation_angle rotation, struct dc_plane_dcc_param *dcc, - bool horizontal_mirror); + bool horizontal_mirror, + bool visible); /* * dce110_mem_input_is_flip_pending diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c index 757e946d0837..b12506adcba4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c @@ -664,7 +664,8 @@ void dce110_mem_input_v_program_surface_config( union plane_size *plane_size, enum dc_rotation_angle rotation, struct dc_plane_dcc_param *dcc, - bool horizotal_mirror) + bool horizotal_mirror, + bool visible) { struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.h index 5b1796ccefc0..44cf066279c0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.h @@ -89,6 +89,7 @@ bool dce110_mem_input_v_program_surface_config( enum surface_pixel_format format, union dc_tiling_info *tiling_info, union plane_size *plane_size, - enum dc_rotation_angle rotation); + enum dc_rotation_angle rotation, + bool visible); #endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h index 2c0774f95c1c..ed980aed1677 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h @@ -95,7 +95,8 @@ struct mem_input_funcs { union plane_size *plane_size, enum dc_rotation_angle rotation, struct dc_plane_dcc_param *dcc, - bool horizontal_mirror); + bool horizontal_mirror, + bool visible); bool (*mem_input_is_flip_pending)(struct mem_input *mem_input); -- cgit From ab2541b67395088b9de8ebf3943ef9ef86bccc41 Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Thu, 29 Dec 2016 15:27:12 -0500 Subject: drm/amd/display: Remove dc_target object dc_target does not fit well into DRM framework so removed it. This will prevent the driver from leveraging the pipe-split code for tiled displays, so will have to be handled at a higher level. Most places that used dc_target now directly use dc_stream instead. Signed-off-by: Aric Cyr Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 6 +- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 47 ++- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 349 +++++++--------- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.h | 2 +- drivers/gpu/drm/amd/display/dc/Makefile | 2 +- drivers/gpu/drm/amd/display/dc/core/dc.c | 292 +++++++------- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 437 ++++++++++----------- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 183 +++++++++ drivers/gpu/drm/amd/display/dc/core/dc_target.c | 333 ---------------- drivers/gpu/drm/amd/display/dc/dc.h | 194 ++++----- drivers/gpu/drm/amd/display/dc/dc_types.h | 1 - .../drm/amd/display/dc/dce100/dce100_resource.c | 89 ++--- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 8 +- .../drm/amd/display/dc/dce110/dce110_resource.c | 103 +++-- .../drm/amd/display/dc/dce112/dce112_resource.c | 144 ++++--- .../drm/amd/display/dc/dce112/dce112_resource.h | 2 +- .../gpu/drm/amd/display/dc/dce80/dce80_resource.c | 89 ++--- drivers/gpu/drm/amd/display/dc/inc/core_dc.h | 1 - drivers/gpu/drm/amd/display/dc/inc/core_types.h | 19 +- drivers/gpu/drm/amd/display/dc/inc/resource.h | 13 +- 20 files changed, 977 insertions(+), 1337 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/dc/core/dc_target.c (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index 3a3adfa16ada..0d92126b4c4a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -428,8 +428,8 @@ struct amdgpu_crtc { int otg_inst; uint32_t flip_flags; - /* After Set Mode target will be non-NULL */ - struct dc_target *target; + /* After Set Mode stream will be non-NULL */ + const struct dc_stream *stream; }; struct amdgpu_encoder_atom_dig { @@ -550,7 +550,7 @@ struct amdgpu_connector { const struct dc_sink *dc_sink; const struct dc_link *dc_link; const struct dc_sink *dc_em_sink; - const struct dc_target *target; + const struct dc_stream *stream; void *con_priv; bool dac_load_detect; bool detected_by_load; /* if the connection status was determined by load */ 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 2af4ac0bffcb..214cd38b8135 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -68,12 +68,12 @@ static u32 dm_vblank_get_counter(struct amdgpu_device *adev, int crtc) else { struct amdgpu_crtc *acrtc = adev->mode_info.crtcs[crtc]; - if (NULL == acrtc->target) { - DRM_ERROR("dc_target is NULL for crtc '%d'!\n", crtc); + if (NULL == acrtc->stream) { + DRM_ERROR("dc_stream is NULL for crtc '%d'!\n", crtc); return 0; } - return dc_target_get_vblank_counter(acrtc->target); + return dc_stream_get_vblank_counter(acrtc->stream); } } @@ -85,12 +85,12 @@ static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc, else { struct amdgpu_crtc *acrtc = adev->mode_info.crtcs[crtc]; - if (NULL == acrtc->target) { - DRM_ERROR("dc_target is NULL for crtc '%d'!\n", crtc); + if (NULL == acrtc->stream) { + DRM_ERROR("dc_stream is NULL for crtc '%d'!\n", crtc); return 0; } - return dc_target_get_scanoutpos(acrtc->target, vbl, position); + return dc_stream_get_scanoutpos(acrtc->stream, vbl, position); } return 0; @@ -461,7 +461,7 @@ static int dm_suspend(void *handle) drm_modeset_lock_all(adev->ddev); list_for_each_entry(crtc, &adev->ddev->mode_config.crtc_list, head) { struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - if (acrtc->target) + if (acrtc->stream) drm_crtc_vblank_off(crtc); } drm_modeset_unlock_all(adev->ddev); @@ -655,7 +655,7 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev ) drm_modeset_lock_all(ddev); list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head) { struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - if (acrtc->target) + if (acrtc->stream) drm_crtc_vblank_on(crtc); } drm_modeset_unlock_all(ddev); @@ -740,7 +740,7 @@ void amdgpu_dm_update_connector_after_detect( if (aconnector->base.force != DRM_FORCE_UNSPECIFIED && aconnector->dc_em_sink) { - /* For S3 resume with headless use eml_sink to fake target + /* For S3 resume with headless use eml_sink to fake stream * because on resume connecotr->sink is set ti NULL */ mutex_lock(&dev->mode_config.mutex); @@ -1184,7 +1184,7 @@ int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) return -1; } - for (i = 0; i < dm->dc->caps.max_targets; i++) { + for (i = 0; i < dm->dc->caps.max_streams; i++) { acrtc = kzalloc(sizeof(struct amdgpu_crtc), GFP_KERNEL); if (!acrtc) goto fail; @@ -1199,7 +1199,7 @@ int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) } } - dm->display_indexes_num = dm->dc->caps.max_targets; + dm->display_indexes_num = dm->dc->caps.max_streams; /* loops over all connectors on the board */ for (i = 0; i < link_cnt; i++) { @@ -1318,7 +1318,7 @@ static void dm_page_flip(struct amdgpu_device *adev, int crtc_id, u64 crtc_base, bool async) { struct amdgpu_crtc *acrtc; - struct dc_target *target; + const struct dc_stream *stream; struct dc_flip_addrs addr = { {0} }; /* @@ -1336,7 +1336,7 @@ static void dm_page_flip(struct amdgpu_device *adev, * a little longer to lock up all cores. * * The reason we should lock on dal_mutex is so that we can be sure - * nobody messes with acrtc->target after we read and check its value. + * nobody messes with acrtc->stream after we read and check its value. * * We might be able to fix our concurrency issues with a work queue * where we schedule all work items (mode_set, page_flip, etc.) and @@ -1345,14 +1345,14 @@ static void dm_page_flip(struct amdgpu_device *adev, */ acrtc = adev->mode_info.crtcs[crtc_id]; - target = acrtc->target; + stream = acrtc->stream; /* * Received a page flip call after the display has been reset. * Just return in this case. Everything should be clean-up on reset. */ - if (!target) { + if (!stream) { WARN_ON(1); return; } @@ -1368,7 +1368,7 @@ static void dm_page_flip(struct amdgpu_device *adev, dc_flip_surface_addrs( adev->dm.dc, - dc_target_get_status(target)->surfaces, + dc_stream_get_status(stream)->surfaces, &addr, 1); } @@ -1376,25 +1376,22 @@ static int amdgpu_notify_freesync(struct drm_device *dev, void *data, struct drm_file *filp) { struct mod_freesync_params freesync_params; - uint8_t num_targets; + uint8_t num_streams; uint8_t i; - struct dc_target *target; struct amdgpu_device *adev = dev->dev_private; int r = 0; /* Get freesync enable flag from DRM */ - num_targets = dc_get_current_target_count(adev->dm.dc); + num_streams = dc_get_current_stream_count(adev->dm.dc); - for (i = 0; i < num_targets; i++) { - - target = dc_get_target_at_index(adev->dm.dc, i); + for (i = 0; i < num_streams; i++) { + const struct dc_stream *stream; + stream = dc_get_stream_at_index(adev->dm.dc, i); mod_freesync_update_state(adev->dm.freesync_module, - target->streams, - target->stream_count, - &freesync_params); + &stream, 1, &freesync_params); } return r; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index e1b5f7d7b6da..c32fc6d26088 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -120,14 +120,14 @@ static void dm_set_cursor( position.x_hotspot = xorigin; position.y_hotspot = yorigin; - if (!dc_target_set_cursor_attributes( - amdgpu_crtc->target, + if (!dc_stream_set_cursor_attributes( + amdgpu_crtc->stream, &attributes)) { DRM_ERROR("DC failed to set cursor attributes\n"); } - if (!dc_target_set_cursor_position( - amdgpu_crtc->target, + if (!dc_stream_set_cursor_position( + amdgpu_crtc->stream, &position)) { DRM_ERROR("DC failed to set cursor position\n"); } @@ -260,10 +260,10 @@ static int dm_crtc_cursor_set( position.y = 0; position.hot_spot_enable = false; - if (amdgpu_crtc->target) { + if (amdgpu_crtc->stream) { /*set cursor visible false*/ - dc_target_set_cursor_position( - amdgpu_crtc->target, + dc_stream_set_cursor_position( + amdgpu_crtc->stream, &position); } /*unpin old cursor buffer and update cache*/ @@ -346,9 +346,9 @@ static int dm_crtc_cursor_move(struct drm_crtc *crtc, position.x_hotspot = xorigin; position.y_hotspot = yorigin; - if (amdgpu_crtc->target) { - if (!dc_target_set_cursor_position( - amdgpu_crtc->target, + if (amdgpu_crtc->stream) { + if (!dc_stream_set_cursor_position( + amdgpu_crtc->stream, &position)) { DRM_ERROR("DC failed to set cursor position\n"); return -EINVAL; @@ -367,7 +367,7 @@ static void dm_crtc_cursor_reset(struct drm_crtc *crtc) __func__, amdgpu_crtc->cursor_bo); - if (amdgpu_crtc->cursor_bo && amdgpu_crtc->target) { + if (amdgpu_crtc->cursor_bo && amdgpu_crtc->stream) { dm_set_cursor( amdgpu_crtc, amdgpu_crtc->cursor_addr, @@ -635,7 +635,7 @@ static void update_stream_scaling_settings( struct amdgpu_device *adev = dm_state->base.crtc->dev->dev_private; enum amdgpu_rmx_type rmx_type; - struct rect src = { 0 }; /* viewport in target space*/ + struct rect src = { 0 }; /* viewport in composition space*/ struct rect dst = { 0 }; /* stream addressable area */ /* Full screen scaling by default */ @@ -684,11 +684,11 @@ static void dm_dc_surface_commit( struct dc_surface *dc_surface; const struct dc_surface *dc_surfaces[1]; const struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - struct dc_target *dc_target = acrtc->target; + const struct dc_stream *dc_stream = acrtc->stream; - if (!dc_target) { + if (!dc_stream) { dm_error( - "%s: Failed to obtain target on crtc (%d)!\n", + "%s: Failed to obtain stream on crtc (%d)!\n", __func__, acrtc->crtc_id); goto fail; @@ -712,11 +712,11 @@ static void dm_dc_surface_commit( dc_surfaces[0] = dc_surface; - if (false == dc_commit_surfaces_to_target( + if (false == dc_commit_surfaces_to_stream( dc, dc_surfaces, 1, - dc_target)) { + dc_stream)) { dm_error( "%s: Failed to attach surface!\n", __func__); @@ -957,15 +957,14 @@ static void decide_crtc_timing_for_drm_display_mode( } } -static struct dc_target *create_target_for_sink( +static struct dc_stream *create_stream_for_sink( const struct amdgpu_connector *aconnector, const struct drm_display_mode *drm_mode, const struct dm_connector_state *dm_state) { struct drm_display_mode *preferred_mode = NULL; const struct drm_connector *drm_connector; - struct dc_target *target = NULL; - struct dc_stream *stream; + struct dc_stream *stream = NULL; struct drm_display_mode mode = *drm_mode; bool native_mode_found = false; @@ -1022,19 +1021,10 @@ static struct dc_target *create_target_for_sink( drm_connector, aconnector->dc_sink); - target = dc_create_target_for_streams(&stream, 1); - dc_stream_release(stream); - - if (NULL == target) { - DRM_ERROR("Failed to create target with streams!\n"); - goto target_create_fail; - } - +stream_create_fail: dm_state_null: drm_connector_null: -target_create_fail: -stream_create_fail: - return target; + return stream; } void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc) @@ -1316,8 +1306,7 @@ int amdgpu_dm_connector_mode_valid( struct amdgpu_device *adev = connector->dev->dev_private; struct dc_validation_set val_set = { 0 }; /* TODO: Unhardcode stream count */ - struct dc_stream *streams[1]; - struct dc_target *target; + struct dc_stream *stream; struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); if ((mode->flags & DRM_MODE_FLAG_INTERLACE) || @@ -1335,39 +1324,31 @@ int amdgpu_dm_connector_mode_valid( if (NULL == dc_sink) { DRM_ERROR("dc_sink is NULL!\n"); - goto stream_create_fail; + goto null_sink; } - streams[0] = dc_create_stream_for_sink(dc_sink); - - if (NULL == streams[0]) { + stream = dc_create_stream_for_sink(dc_sink); + if (NULL == stream) { DRM_ERROR("Failed to create stream for sink!\n"); goto stream_create_fail; } drm_mode_set_crtcinfo(mode, 0); - fill_stream_properties_from_drm_display_mode(streams[0], mode, connector); - - target = dc_create_target_for_streams(streams, 1); - val_set.target = target; - - if (NULL == val_set.target) { - DRM_ERROR("Failed to create target with stream!\n"); - goto target_create_fail; - } + fill_stream_properties_from_drm_display_mode(stream, mode, connector); + val_set.stream = stream; val_set.surface_count = 0; - streams[0]->src.width = mode->hdisplay; - streams[0]->src.height = mode->vdisplay; - streams[0]->dst = streams[0]->src; + stream->src.width = mode->hdisplay; + stream->src.height = mode->vdisplay; + stream->dst = stream->src; if (dc_validate_resources(adev->dm.dc, &val_set, 1)) result = MODE_OK; - dc_target_release(target); -target_create_fail: - dc_stream_release(streams[0]); + dc_stream_release(stream); + stream_create_fail: +null_sink: /* TODO: error handling*/ return result; } @@ -1562,15 +1543,14 @@ static void dm_plane_helper_cleanup_fb( } } -int dm_create_validation_set_for_target(struct drm_connector *connector, +int dm_create_validation_set_for_connector(struct drm_connector *connector, struct drm_display_mode *mode, struct dc_validation_set *val_set) { int result = MODE_ERROR; const struct dc_sink *dc_sink = to_amdgpu_connector(connector)->dc_sink; /* TODO: Unhardcode stream count */ - struct dc_stream *streams[1]; - struct dc_target *target; + struct dc_stream *stream; if ((mode->flags & DRM_MODE_FLAG_INTERLACE) || (mode->flags & DRM_MODE_FLAG_DBLSCAN)) @@ -1581,35 +1561,24 @@ int dm_create_validation_set_for_target(struct drm_connector *connector, return result; } - streams[0] = dc_create_stream_for_sink(dc_sink); + stream = dc_create_stream_for_sink(dc_sink); - if (NULL == streams[0]) { + if (NULL == stream) { DRM_ERROR("Failed to create stream for sink!\n"); return result; } drm_mode_set_crtcinfo(mode, 0); - fill_stream_properties_from_drm_display_mode(streams[0], mode, connector); + fill_stream_properties_from_drm_display_mode(stream, mode, connector); - target = dc_create_target_for_streams(streams, 1); - val_set->target = target; + val_set->stream = stream; - if (NULL == val_set->target) { - DRM_ERROR("Failed to create target with stream!\n"); - goto fail; - } - - streams[0]->src.width = mode->hdisplay; - streams[0]->src.height = mode->vdisplay; - streams[0]->dst = streams[0]->src; + stream->src.width = mode->hdisplay; + stream->src.height = mode->vdisplay; + stream->dst = stream->src; return MODE_OK; - -fail: - dc_stream_release(streams[0]); - return result; - } static const struct drm_plane_helper_funcs dm_plane_helper_funcs = { @@ -2262,23 +2231,21 @@ static bool is_scaling_state_different( return false; } -static void remove_target(struct amdgpu_device *adev, struct amdgpu_crtc *acrtc) +static void remove_stream(struct amdgpu_device *adev, struct amdgpu_crtc *acrtc) { - int i; - /* * we evade vblanks and pflips on crtc that * should be changed */ manage_dm_interrupts(adev, acrtc, false); + /* this is the update mode case */ if (adev->dm.freesync_module) - for (i = 0; i < acrtc->target->stream_count; i++) - mod_freesync_remove_stream( - adev->dm.freesync_module, - acrtc->target->streams[i]); - dc_target_release(acrtc->target); - acrtc->target = NULL; + mod_freesync_remove_stream(adev->dm.freesync_module, + acrtc->stream); + + dc_stream_release(acrtc->stream); + acrtc->stream = NULL; acrtc->otg_inst = -1; acrtc->enabled = false; } @@ -2293,20 +2260,20 @@ int amdgpu_dm_atomic_commit( struct drm_plane *plane; struct drm_plane_state *new_plane_state; struct drm_plane_state *old_plane_state; - uint32_t i, j; + uint32_t i; int32_t ret = 0; - uint32_t commit_targets_count = 0; + uint32_t commit_streams_count = 0; uint32_t new_crtcs_count = 0; uint32_t flip_crtcs_count = 0; struct drm_crtc *crtc; struct drm_crtc_state *old_crtc_state; - struct dc_target *commit_targets[MAX_TARGETS]; - struct amdgpu_crtc *new_crtcs[MAX_TARGETS]; - struct dc_target *new_target; - struct drm_crtc *flip_crtcs[MAX_TARGETS]; - struct amdgpu_flip_work *work[MAX_TARGETS] = {0}; - struct amdgpu_bo *new_abo[MAX_TARGETS] = {0}; + const struct dc_stream *commit_streams[MAX_STREAMS]; + struct amdgpu_crtc *new_crtcs[MAX_STREAMS]; + const struct dc_stream *new_stream; + struct drm_crtc *flip_crtcs[MAX_STREAMS]; + struct amdgpu_flip_work *work[MAX_STREAMS] = {0}; + struct amdgpu_bo *new_abo[MAX_STREAMS] = {0}; /* In this step all new fb would be pinned */ @@ -2422,19 +2389,19 @@ int amdgpu_dm_atomic_commit( case DM_COMMIT_ACTION_DPMS_ON: case DM_COMMIT_ACTION_SET: { struct dm_connector_state *dm_state = NULL; - new_target = NULL; + new_stream = NULL; if (aconnector) dm_state = to_dm_connector_state(aconnector->base.state); - new_target = create_target_for_sink( + new_stream = create_stream_for_sink( aconnector, &crtc->state->mode, dm_state); DRM_INFO("Atomic commit: SET crtc id %d: [%p]\n", acrtc->crtc_id, acrtc); - if (!new_target) { + if (!new_stream) { /* * this could happen because of issues with * userspace notifications delivery. @@ -2450,23 +2417,23 @@ int amdgpu_dm_atomic_commit( * have a sink to keep the pipe running so that * hw state is consistent with the sw state */ - DRM_DEBUG_KMS("%s: Failed to create new target for crtc %d\n", + DRM_DEBUG_KMS("%s: Failed to create new stream for crtc %d\n", __func__, acrtc->base.base.id); break; } - if (acrtc->target) - remove_target(adev, acrtc); + if (acrtc->stream) + remove_stream(adev, acrtc); /* * this loop saves set mode crtcs * we needed to enable vblanks once all - * resources acquired in dc after dc_commit_targets + * resources acquired in dc after dc_commit_streams */ new_crtcs[new_crtcs_count] = acrtc; new_crtcs_count++; - acrtc->target = new_target; + acrtc->stream = new_stream; acrtc->enabled = true; acrtc->hw_mode = crtc->state->mode; crtc->hwmode = crtc->state->mode; @@ -2483,10 +2450,8 @@ int amdgpu_dm_atomic_commit( dm_state = to_dm_connector_state(aconnector->base.state); /* Scaling update */ - update_stream_scaling_settings( - &crtc->state->mode, - dm_state, - acrtc->target->streams[0]); + update_stream_scaling_settings(&crtc->state->mode, + dm_state, acrtc->stream); break; } @@ -2494,8 +2459,8 @@ int amdgpu_dm_atomic_commit( case DM_COMMIT_ACTION_RESET: DRM_INFO("Atomic commit: RESET. crtc id %d:[%p]\n", acrtc->crtc_id, acrtc); /* i.e. reset mode */ - if (acrtc->target) - remove_target(adev, acrtc); + if (acrtc->stream) + remove_stream(adev, acrtc); break; } /* switch() */ } /* for_each_crtc_in_state() */ @@ -2504,20 +2469,20 @@ int amdgpu_dm_atomic_commit( struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - if (acrtc->target) { - commit_targets[commit_targets_count] = acrtc->target; - ++commit_targets_count; + if (acrtc->stream) { + commit_streams[commit_streams_count] = acrtc->stream; + ++commit_streams_count; } } /* - * Add streams after required streams from new and replaced targets + * Add streams after required streams from new and replaced streams * are removed from freesync module */ if (adev->dm.freesync_module) { for (i = 0; i < new_crtcs_count; i++) { struct amdgpu_connector *aconnector = NULL; - new_target = new_crtcs[i]->target; + new_stream = new_crtcs[i]->stream; aconnector = amdgpu_dm_find_first_crct_matching_connector( state, @@ -2531,22 +2496,20 @@ int amdgpu_dm_atomic_commit( continue; } - for (j = 0; j < new_target->stream_count; j++) - mod_freesync_add_stream( - adev->dm.freesync_module, - new_target->streams[j], &aconnector->caps); + mod_freesync_add_stream(adev->dm.freesync_module, + new_stream, &aconnector->caps); } } - /* DC is optimized not to do anything if 'targets' didn't change. */ - dc_commit_targets(dm->dc, commit_targets, commit_targets_count); + /* DC is optimized not to do anything if 'streams' didn't change. */ + dc_commit_streams(dm->dc, commit_streams, commit_streams_count); list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - if (acrtc->target != NULL) + if (acrtc->stream != NULL) acrtc->otg_inst = - dc_target_get_status(acrtc->target)->primary_otg_inst; + dc_stream_get_status(acrtc->stream)->primary_otg_inst; } /* update planes when needed */ @@ -2566,7 +2529,7 @@ int amdgpu_dm_atomic_commit( /* Surfaces are created under two scenarios: * 1. This commit is not a page flip. - * 2. This commit is a page flip, and targets are created. + * 2. This commit is a page flip, and streams are created. */ if (!page_flip_needed( plane_state, @@ -2618,13 +2581,9 @@ int amdgpu_dm_atomic_commit( */ struct amdgpu_crtc *acrtc = new_crtcs[i]; - if (adev->dm.freesync_module) { - for (j = 0; j < acrtc->target->stream_count; j++) - mod_freesync_notify_mode_change( - adev->dm.freesync_module, - acrtc->target->streams, - acrtc->target->stream_count); - } + if (adev->dm.freesync_module) + mod_freesync_notify_mode_change( + adev->dm.freesync_module, &acrtc->stream, 1); manage_dm_interrupts(adev, acrtc, true); dm_crtc_cursor_reset(&acrtc->base); @@ -2682,20 +2641,19 @@ void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); struct amdgpu_crtc *disconnected_acrtc; const struct dc_sink *sink; - struct dc_target *commit_targets[6]; - struct dc_target *current_target; - uint32_t commit_targets_count = 0; - int i; + const struct dc_stream *commit_streams[MAX_STREAMS]; + const struct dc_stream *current_stream; + uint32_t commit_streams_count = 0; if (!aconnector->dc_sink || !connector->state || !connector->encoder) return; disconnected_acrtc = to_amdgpu_crtc(connector->encoder->crtc); - if (!disconnected_acrtc || !disconnected_acrtc->target) + if (!disconnected_acrtc || !disconnected_acrtc->stream) return; - sink = disconnected_acrtc->target->streams[0]->sink; + sink = disconnected_acrtc->stream->sink; /* * If the previous sink is not released and different from the current, @@ -2706,8 +2664,8 @@ void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector struct dm_connector_state *dm_state = to_dm_connector_state(aconnector->base.state); - struct dc_target *new_target = - create_target_for_sink( + struct dc_stream *new_stream = + create_stream_for_sink( aconnector, &disconnected_acrtc->base.state->mode, dm_state); @@ -2720,56 +2678,51 @@ void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector manage_dm_interrupts(adev, disconnected_acrtc, false); /* this is the update mode case */ - current_target = disconnected_acrtc->target; + current_stream = disconnected_acrtc->stream; - disconnected_acrtc->target = new_target; + disconnected_acrtc->stream = new_stream; disconnected_acrtc->enabled = true; disconnected_acrtc->hw_mode = disconnected_acrtc->base.state->mode; - commit_targets_count = 0; + commit_streams_count = 0; list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - if (acrtc->target) { - commit_targets[commit_targets_count] = acrtc->target; - ++commit_targets_count; + if (acrtc->stream) { + commit_streams[commit_streams_count] = acrtc->stream; + ++commit_streams_count; } } - /* DC is optimized not to do anything if 'targets' didn't change. */ - if (!dc_commit_targets(dc, commit_targets, - commit_targets_count)) { + /* DC is optimized not to do anything if 'streams' didn't change. */ + if (!dc_commit_streams(dc, commit_streams, + commit_streams_count)) { DRM_INFO("Failed to restore connector state!\n"); - dc_target_release(disconnected_acrtc->target); - disconnected_acrtc->target = current_target; + dc_stream_release(disconnected_acrtc->stream); + disconnected_acrtc->stream = current_stream; manage_dm_interrupts(adev, disconnected_acrtc, true); return; } if (adev->dm.freesync_module) { + mod_freesync_remove_stream(adev->dm.freesync_module, + current_stream); - for (i = 0; i < current_target->stream_count; i++) - mod_freesync_remove_stream( - adev->dm.freesync_module, - current_target->streams[i]); - - for (i = 0; i < new_target->stream_count; i++) - mod_freesync_add_stream( - adev->dm.freesync_module, - new_target->streams[i], - &aconnector->caps); + mod_freesync_add_stream(adev->dm.freesync_module, + new_stream, &aconnector->caps); } + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - if (acrtc->target != NULL) { + if (acrtc->stream != NULL) { acrtc->otg_inst = - dc_target_get_status(acrtc->target)->primary_otg_inst; + dc_stream_get_status(acrtc->stream)->primary_otg_inst; } } - dc_target_release(current_target); + dc_stream_release(current_stream); dm_dc_surface_commit(dc, &disconnected_acrtc->base); @@ -2782,13 +2735,13 @@ void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector static uint32_t add_val_sets_surface( struct dc_validation_set *val_sets, uint32_t set_count, - const struct dc_target *target, + const struct dc_stream *stream, const struct dc_surface *surface) { uint32_t i = 0; while (i < set_count) { - if (val_sets[i].target == target) + if (val_sets[i].stream == stream) break; ++i; } @@ -2799,23 +2752,23 @@ static uint32_t add_val_sets_surface( return val_sets[i].surface_count; } -static uint32_t update_in_val_sets_target( +static uint32_t update_in_val_sets_stream( struct dc_validation_set *val_sets, struct drm_crtc **crtcs, uint32_t set_count, - const struct dc_target *old_target, - const struct dc_target *new_target, + const struct dc_stream *old_stream, + const struct dc_stream *new_stream, struct drm_crtc *crtc) { uint32_t i = 0; while (i < set_count) { - if (val_sets[i].target == old_target) + if (val_sets[i].stream == old_stream) break; ++i; } - val_sets[i].target = new_target; + val_sets[i].stream = new_stream; crtcs[i] = crtc; if (i == set_count) { @@ -2829,12 +2782,12 @@ static uint32_t update_in_val_sets_target( static uint32_t remove_from_val_sets( struct dc_validation_set *val_sets, uint32_t set_count, - const struct dc_target *target) + const struct dc_stream *stream) { int i; for (i = 0; i < set_count; i++) - if (val_sets[i].target == target) + if (val_sets[i].stream == stream) break; if (i == set_count) { @@ -2861,10 +2814,10 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, int i, j; int ret; int set_count; - int new_target_count; - struct dc_validation_set set[MAX_TARGETS] = {{ 0 }}; - struct dc_target *new_targets[MAX_TARGETS] = { 0 }; - struct drm_crtc *crtc_set[MAX_TARGETS] = { 0 }; + int new_stream_count; + struct dc_validation_set set[MAX_STREAMS] = {{ 0 }}; + struct dc_stream *new_streams[MAX_STREAMS] = { 0 }; + struct drm_crtc *crtc_set[MAX_STREAMS] = { 0 }; struct amdgpu_device *adev = dev->dev_private; struct dc *dc = adev->dm.dc; bool need_to_validate = false; @@ -2880,14 +2833,14 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, ret = -EINVAL; /* copy existing configuration */ - new_target_count = 0; + new_stream_count = 0; set_count = 0; list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - if (acrtc->target) { - set[set_count].target = acrtc->target; + if (acrtc->stream) { + set[set_count].stream = acrtc->stream; crtc_set[set_count] = crtc; ++set_count; } @@ -2908,7 +2861,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, switch (action) { case DM_COMMIT_ACTION_DPMS_ON: case DM_COMMIT_ACTION_SET: { - struct dc_target *new_target = NULL; + struct dc_stream *new_stream = NULL; struct drm_connector_state *conn_state = NULL; struct dm_connector_state *dm_state = NULL; @@ -2919,30 +2872,30 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, dm_state = to_dm_connector_state(conn_state); } - new_target = create_target_for_sink(aconnector, &crtc_state->mode, dm_state); + new_stream = create_stream_for_sink(aconnector, &crtc_state->mode, dm_state); /* - * we can have no target on ACTION_SET if a display + * we can have no stream on ACTION_SET if a display * was disconnected during S3, in this case it not and * error, the OS will be updated after detection, and * do the right thing on next atomic commit */ - if (!new_target) { - DRM_DEBUG_KMS("%s: Failed to create new target for crtc %d\n", + if (!new_stream) { + DRM_DEBUG_KMS("%s: Failed to create new stream for crtc %d\n", __func__, acrtc->base.base.id); break; } - new_targets[new_target_count] = new_target; - set_count = update_in_val_sets_target( + new_streams[new_stream_count] = new_stream; + set_count = update_in_val_sets_stream( set, crtc_set, set_count, - acrtc->target, - new_target, + acrtc->stream, + new_stream, crtc); - new_target_count++; + new_stream_count++; need_to_validate = true; break; } @@ -2952,7 +2905,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, struct drm_connector_state *conn_state = NULL; struct dm_connector_state *dm_state = NULL; struct dm_connector_state *old_dm_state = NULL; - struct dc_target *new_target; + struct dc_stream *new_stream; if (!aconnector) break; @@ -2970,24 +2923,24 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, if (!is_scaling_state_different(dm_state, old_dm_state)) break; - new_target = create_target_for_sink(aconnector, &crtc_state->mode, dm_state); + new_stream = create_stream_for_sink(aconnector, &crtc_state->mode, dm_state); - if (!new_target) { - DRM_ERROR("%s: Failed to create new target for crtc %d\n", + if (!new_stream) { + DRM_ERROR("%s: Failed to create new stream for crtc %d\n", __func__, acrtc->base.base.id); break; } - new_targets[new_target_count] = new_target; - set_count = update_in_val_sets_target( + new_streams[new_stream_count] = new_stream; + set_count = update_in_val_sets_stream( set, crtc_set, set_count, - acrtc->target, - new_target, + acrtc->stream, + new_stream, crtc); - new_target_count++; + new_stream_count++; need_to_validate = true; break; @@ -2995,11 +2948,11 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, case DM_COMMIT_ACTION_DPMS_OFF: case DM_COMMIT_ACTION_RESET: /* i.e. reset mode */ - if (acrtc->target) { + if (acrtc->stream) { set_count = remove_from_val_sets( set, set_count, - acrtc->target); + acrtc->stream); } break; } @@ -3035,7 +2988,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, /* Surfaces are created under two scenarios: * 1. This commit is not a page flip. - * 2. This commit is a page flip, and targets are created. + * 2. This commit is a page flip, and streams are created. */ crtc_state = drm_atomic_get_crtc_state(state, crtc); if (!page_flip_needed(plane_state, old_plane_state, @@ -3080,7 +3033,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, add_val_sets_surface( set, set_count, - set[i].target, + set[i].stream, surface); need_to_validate = true; @@ -3097,8 +3050,8 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, dc_surface_release(set[i].surfaces[j]); } } - for (i = 0; i < new_target_count; i++) - dc_target_release(new_targets[i]); + for (i = 0; i < new_stream_count; i++) + dc_stream_release(new_streams[i]); if (ret != 0) DRM_ERROR("Atomic check failed.\n"); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h index 4f7bd3bae44e..6ed1480a8bc3 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h @@ -59,7 +59,7 @@ int amdgpu_dm_atomic_commit( int amdgpu_dm_atomic_check(struct drm_device *dev, struct drm_atomic_state *state); -int dm_create_validation_set_for_target( +int dm_create_validation_set_for_stream( struct drm_connector *connector, struct drm_display_mode *mode, struct dc_validation_set *val_set); diff --git a/drivers/gpu/drm/amd/display/dc/Makefile b/drivers/gpu/drm/amd/display/dc/Makefile index 26e2b50e4954..2df163bc83e9 100644 --- a/drivers/gpu/drm/amd/display/dc/Makefile +++ b/drivers/gpu/drm/amd/display/dc/Makefile @@ -13,7 +13,7 @@ AMD_DC = $(addsuffix /Makefile, $(addprefix $(FULL_AMD_DISPLAY_PATH)/dc/,$(DC_LI include $(AMD_DC) -DISPLAY_CORE = dc.o dc_link.o dc_resource.o dc_hw_sequencer.o dc_target.o dc_sink.o \ +DISPLAY_CORE = dc.o dc_link.o dc_resource.o dc_hw_sequencer.o dc_sink.o \ dc_surface.o dc_link_hwss.o dc_link_dp.o dc_link_ddc.o dc_debug.o dc_stream.o AMD_DISPLAY_CORE = $(addprefix $(AMDDALPATH)/dc/core/,$(DISPLAY_CORE)) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index a7348573ebca..7d4299b9ee1f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -49,15 +49,6 @@ #include "dm_helpers.h" #include "mem_input.h" -/******************************************************************************* - * Private structures - ******************************************************************************/ - -struct dc_target_sync_report { - uint32_t h_count; - uint32_t v_count; -}; - /******************************************************************************* * Private functions ******************************************************************************/ @@ -221,7 +212,7 @@ static void stream_update_scaling( struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); struct core_dc *core_dc = DC_TO_CORE(dc); struct validate_context *cur_ctx = core_dc->current_context; - int i, j; + int i; if (src) stream->public.src = *src; @@ -229,20 +220,18 @@ static void stream_update_scaling( if (dst) stream->public.dst = *dst; - for (i = 0; i < cur_ctx->target_count; i++) { - struct core_target *target = cur_ctx->targets[i]; - struct dc_target_status *status = &cur_ctx->target_status[i]; + for (i = 0; i < cur_ctx->stream_count; i++) { + struct core_stream *cur_stream = cur_ctx->streams[i]; - for (j = 0; j < target->public.stream_count; j++) { - if (target->public.streams[j] != dc_stream) - continue; + if (stream == cur_stream) { + struct dc_stream_status *status = &cur_ctx->stream_status[i]; if (status->surface_count) - if (!dc_commit_surfaces_to_target( + if (!dc_commit_surfaces_to_stream( &core_dc->public, status->surfaces, status->surface_count, - &target->public)) + &cur_stream->public)) /* Need to debug validation */ BREAK_TO_DEBUGGER(); @@ -634,7 +623,7 @@ struct dc *dc_create(const struct dc_init_data *init_params) full_pipe_count = core_dc->res_pool->pipe_count; if (core_dc->res_pool->underlay_pipe_index >= 0) full_pipe_count--; - core_dc->public.caps.max_targets = min( + core_dc->public.caps.max_streams = min( full_pipe_count, core_dc->res_pool->stream_enc_count); @@ -675,20 +664,20 @@ static bool is_validation_required( const struct validate_context *context = dc->current_context; int i, j; - if (context->target_count != set_count) + if (context->stream_count != set_count) return true; for (i = 0; i < set_count; i++) { - if (set[i].surface_count != context->target_status[i].surface_count) + if (set[i].surface_count != context->stream_status[i].surface_count) return true; - if (!is_target_unchanged(DC_TARGET_TO_CORE(set[i].target), context->targets[i])) + if (!is_stream_unchanged(DC_STREAM_TO_CORE(set[i].stream), context->streams[i])) return true; for (j = 0; j < set[i].surface_count; j++) { struct dc_surface temp_surf = { 0 }; - temp_surf = *context->target_status[i].surfaces[j]; + temp_surf = *context->stream_status[i].surfaces[j]; temp_surf.clip_rect = set[i].surfaces[j]->clip_rect; temp_surf.dst_rect.x = set[i].surfaces[j]->dst_rect.x; temp_surf.dst_rect.y = set[i].surfaces[j]->dst_rect.y; @@ -737,7 +726,7 @@ context_alloc_fail: bool dc_validate_guaranteed( const struct dc *dc, - const struct dc_target *dc_target) + const struct dc_stream *stream) { struct core_dc *core_dc = DC_TO_CORE(dc); enum dc_status result = DC_ERROR_UNEXPECTED; @@ -748,7 +737,7 @@ bool dc_validate_guaranteed( goto context_alloc_fail; result = core_dc->res_pool->funcs->validate_guaranteed( - core_dc, dc_target, context); + core_dc, stream, context); resource_validate_ctx_destruct(context); dm_free(context); @@ -838,18 +827,18 @@ static void program_timing_sync( } } -static bool targets_changed( +static bool streams_changed( struct core_dc *dc, - struct dc_target *targets[], - uint8_t target_count) + const struct dc_stream *streams[], + uint8_t stream_count) { uint8_t i; - if (target_count != dc->current_context->target_count) + if (stream_count != dc->current_context->stream_count) return true; - for (i = 0; i < dc->current_context->target_count; i++) { - if (&dc->current_context->targets[i]->public != targets[i]) + for (i = 0; i < dc->current_context->stream_count; i++) { + if (&dc->current_context->streams[i]->public != streams[i]) return true; } @@ -860,74 +849,72 @@ static void fill_display_configs( const struct validate_context *context, struct dm_pp_display_configuration *pp_display_cfg) { - uint8_t i, j, k; - uint8_t num_cfgs = 0; - - for (i = 0; i < context->target_count; i++) { - const struct core_target *target = context->targets[i]; - - for (j = 0; j < target->public.stream_count; j++) { - const struct core_stream *stream = - DC_STREAM_TO_CORE(target->public.streams[j]); - struct dm_pp_single_disp_config *cfg = - &pp_display_cfg->disp_configs[num_cfgs]; - const struct pipe_ctx *pipe_ctx = NULL; - - for (k = 0; k < MAX_PIPES; k++) - if (stream == - context->res_ctx.pipe_ctx[k].stream) { - pipe_ctx = &context->res_ctx.pipe_ctx[k]; - break; - } + int j; + int num_cfgs = 0; - ASSERT(pipe_ctx != NULL); - - num_cfgs++; - cfg->signal = pipe_ctx->stream->signal; - cfg->pipe_idx = pipe_ctx->pipe_idx; - cfg->src_height = stream->public.src.height; - cfg->src_width = stream->public.src.width; - cfg->ddi_channel_mapping = - stream->sink->link->ddi_channel_mapping.raw; - cfg->transmitter = - stream->sink->link->link_enc->transmitter; - cfg->link_settings.lane_count = stream->sink->link->public.cur_link_settings.lane_count; - cfg->link_settings.link_rate = stream->sink->link->public.cur_link_settings.link_rate; - cfg->link_settings.link_spread = stream->sink->link->public.cur_link_settings.link_spread; - cfg->sym_clock = stream->phy_pix_clk; - /* Round v_refresh*/ - cfg->v_refresh = stream->public.timing.pix_clk_khz * 1000; - cfg->v_refresh /= stream->public.timing.h_total; - cfg->v_refresh = (cfg->v_refresh + stream->public.timing.v_total / 2) - / stream->public.timing.v_total; - } + for (j = 0; j < context->stream_count; j++) { + int k; + + const struct core_stream *stream = context->streams[j]; + struct dm_pp_single_disp_config *cfg = + &pp_display_cfg->disp_configs[num_cfgs]; + const struct pipe_ctx *pipe_ctx = NULL; + + for (k = 0; k < MAX_PIPES; k++) + if (stream == context->res_ctx.pipe_ctx[k].stream) { + pipe_ctx = &context->res_ctx.pipe_ctx[k]; + break; + } + + ASSERT(pipe_ctx != NULL); + + num_cfgs++; + cfg->signal = pipe_ctx->stream->signal; + cfg->pipe_idx = pipe_ctx->pipe_idx; + cfg->src_height = stream->public.src.height; + cfg->src_width = stream->public.src.width; + cfg->ddi_channel_mapping = + stream->sink->link->ddi_channel_mapping.raw; + cfg->transmitter = + stream->sink->link->link_enc->transmitter; + cfg->link_settings.lane_count = + stream->sink->link->public.cur_link_settings.lane_count; + cfg->link_settings.link_rate = + stream->sink->link->public.cur_link_settings.link_rate; + cfg->link_settings.link_spread = + stream->sink->link->public.cur_link_settings.link_spread; + cfg->sym_clock = stream->phy_pix_clk; + /* Round v_refresh*/ + cfg->v_refresh = stream->public.timing.pix_clk_khz * 1000; + cfg->v_refresh /= stream->public.timing.h_total; + cfg->v_refresh = (cfg->v_refresh + stream->public.timing.v_total / 2) + / stream->public.timing.v_total; } + pp_display_cfg->display_count = num_cfgs; } static uint32_t get_min_vblank_time_us(const struct validate_context *context) { - uint8_t i, j; + uint8_t j; uint32_t min_vertical_blank_time = -1; - for (i = 0; i < context->target_count; i++) { - const struct core_target *target = context->targets[i]; - - for (j = 0; j < target->public.stream_count; j++) { - const struct dc_stream *stream = - target->public.streams[j]; + for (j = 0; j < context->stream_count; j++) { + const struct dc_stream *stream = &context->streams[j]->public; uint32_t vertical_blank_in_pixels = 0; uint32_t vertical_blank_time = 0; vertical_blank_in_pixels = stream->timing.h_total * (stream->timing.v_total - stream->timing.v_addressable); + vertical_blank_time = vertical_blank_in_pixels * 1000 / stream->timing.pix_clk_khz; + if (min_vertical_blank_time > vertical_blank_time) min_vertical_blank_time = vertical_blank_time; } - } + return min_vertical_blank_time; } @@ -995,7 +982,7 @@ void pplib_apply_display_requirements( /* TODO: is this still applicable?*/ if (pp_display_cfg->display_count == 1) { const struct dc_crtc_timing *timing = - &context->targets[0]->public.streams[0]->timing; + &context->streams[0]->public.timing; pp_display_cfg->crtc_index = pp_display_cfg->disp_configs[0].pipe_idx; @@ -1011,34 +998,32 @@ void pplib_apply_display_requirements( } -bool dc_commit_targets( +bool dc_commit_streams( struct dc *dc, - struct dc_target *targets[], - uint8_t target_count) + const struct dc_stream *streams[], + uint8_t stream_count) { struct core_dc *core_dc = DC_TO_CORE(dc); struct dc_bios *dcb = core_dc->ctx->dc_bios; enum dc_status result = DC_ERROR_UNEXPECTED; struct validate_context *context; - struct dc_validation_set set[MAX_TARGETS]; + struct dc_validation_set set[MAX_STREAMS]; int i, j, k; - if (false == targets_changed(core_dc, targets, target_count)) + if (false == streams_changed(core_dc, streams, stream_count)) return DC_OK; - dm_logger_write(core_dc->ctx->logger, LOG_DC, - "%s: %d targets\n", - __func__, - target_count); + dm_logger_write(core_dc->ctx->logger, LOG_DC, "%s: %d streams\n", + __func__, stream_count); - for (i = 0; i < target_count; i++) { - struct dc_target *target = targets[i]; + for (i = 0; i < stream_count; i++) { + const struct dc_stream *stream = streams[i]; - dc_target_log(target, + dc_stream_log(stream, core_dc->ctx->logger, LOG_DC); - set[i].target = targets[i]; + set[i].stream = stream; set[i].surface_count = 0; } @@ -1047,7 +1032,7 @@ bool dc_commit_targets( if (context == NULL) goto context_alloc_fail; - result = core_dc->res_pool->funcs->validate_with_context(core_dc, set, target_count, context); + result = core_dc->res_pool->funcs->validate_with_context(core_dc, set, stream_count, context); if (result != DC_OK){ dm_logger_write(core_dc->ctx->logger, LOG_ERROR, "%s: Context validation failed! dc_status:%d\n", @@ -1068,13 +1053,12 @@ bool dc_commit_targets( program_timing_sync(core_dc, context); - for (i = 0; i < context->target_count; i++) { - struct dc_target *dc_target = &context->targets[i]->public; - struct core_sink *sink = DC_SINK_TO_CORE(dc_target->streams[0]->sink); + for (i = 0; i < context->stream_count; i++) { + const struct core_sink *sink = context->streams[i]->sink; - for (j = 0; j < context->target_status[i].surface_count; j++) { + for (j = 0; j < context->stream_status[i].surface_count; j++) { const struct dc_surface *dc_surface = - context->target_status[i].surfaces[j]; + context->stream_status[i].surfaces[j]; for (k = 0; k < context->res_ctx.pool->pipe_count; k++) { struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[k]; @@ -1088,11 +1072,11 @@ bool dc_commit_targets( } CONN_MSG_MODE(sink->link, "{%dx%d, %dx%d@%dKhz}", - dc_target->streams[0]->timing.h_addressable, - dc_target->streams[0]->timing.v_addressable, - dc_target->streams[0]->timing.h_total, - dc_target->streams[0]->timing.v_total, - dc_target->streams[0]->timing.pix_clk_khz); + context->streams[i]->public.timing.h_addressable, + context->streams[i]->public.timing.v_addressable, + context->streams[i]->public.timing.h_total, + context->streams[i]->public.timing.v_total, + context->streams[i]->public.timing.pix_clk_khz); } pplib_apply_display_requirements(core_dc, @@ -1116,43 +1100,42 @@ context_alloc_fail: return (result == DC_OK); } -bool dc_pre_update_surfaces_to_target( +bool dc_pre_update_surfaces_to_stream( struct dc *dc, const struct dc_surface *const *new_surfaces, uint8_t new_surface_count, - struct dc_target *dc_target) + const struct dc_stream *dc_stream) { int i, j; struct core_dc *core_dc = DC_TO_CORE(dc); uint32_t prev_disp_clk = core_dc->current_context->bw_results.dispclk_khz; - struct core_target *target = DC_TARGET_TO_CORE(dc_target); - struct dc_target_status *target_status = NULL; + struct dc_stream_status *stream_status = NULL; struct validate_context *context; struct validate_context *temp_context; bool ret = true; pre_surface_trace(dc, new_surfaces, new_surface_count); - if (core_dc->current_context->target_count == 0) + if (core_dc->current_context->stream_count == 0) return false; - /* Cannot commit surface to a target that is not commited */ - for (i = 0; i < core_dc->current_context->target_count; i++) - if (target == core_dc->current_context->targets[i]) + /* Cannot commit surface to a stream that is not commited */ + for (i = 0; i < core_dc->current_context->stream_count; i++) + if (dc_stream == &core_dc->current_context->streams[i]->public) break; - if (i == core_dc->current_context->target_count) + if (i == core_dc->current_context->stream_count) return false; - target_status = &core_dc->current_context->target_status[i]; + stream_status = &core_dc->current_context->stream_status[i]; - if (new_surface_count == target_status->surface_count) { + if (new_surface_count == stream_status->surface_count) { bool skip_pre = true; - for (i = 0; i < target_status->surface_count; i++) { + for (i = 0; i < stream_status->surface_count; i++) { struct dc_surface temp_surf = { 0 }; - temp_surf = *target_status->surfaces[i]; + temp_surf = *stream_status->surfaces[i]; temp_surf.clip_rect = new_surfaces[i]->clip_rect; temp_surf.dst_rect.x = new_surfaces[i]->dst_rect.x; temp_surf.dst_rect.y = new_surfaces[i]->dst_rect.y; @@ -1178,13 +1161,13 @@ bool dc_pre_update_surfaces_to_target( resource_validate_ctx_copy_construct(core_dc->current_context, context); dm_logger_write(core_dc->ctx->logger, LOG_DC, - "%s: commit %d surfaces to target 0x%x\n", + "%s: commit %d surfaces to stream 0x%x\n", __func__, new_surface_count, - dc_target); + dc_stream); if (!resource_attach_surfaces_to_context( - new_surfaces, new_surface_count, dc_target, context)) { + new_surfaces, new_surface_count, dc_stream, context)) { BREAK_TO_DEBUGGER(); ret = false; goto unexpected_fail; @@ -1256,7 +1239,7 @@ val_ctx_fail: return ret; } -bool dc_post_update_surfaces_to_target(struct dc *dc) +bool dc_post_update_surfaces_to_stream(struct dc *dc) { struct core_dc *core_dc = DC_TO_CORE(dc); int i; @@ -1282,22 +1265,27 @@ bool dc_post_update_surfaces_to_target(struct dc *dc) return true; } -bool dc_commit_surfaces_to_target( +bool dc_commit_surfaces_to_stream( struct dc *dc, const struct dc_surface **new_surfaces, uint8_t new_surface_count, - struct dc_target *dc_target) + const struct dc_stream *dc_stream) { - struct dc_surface_update updates[MAX_SURFACES] = { 0 }; - struct dc_flip_addrs flip_addr[MAX_SURFACES] = { 0 }; - struct dc_plane_info plane_info[MAX_SURFACES] = { 0 }; - struct dc_scaling_info scaling_info[MAX_SURFACES] = { 0 }; + struct dc_surface_update updates[MAX_SURFACES]; + struct dc_flip_addrs flip_addr[MAX_SURFACES]; + struct dc_plane_info plane_info[MAX_SURFACES]; + struct dc_scaling_info scaling_info[MAX_SURFACES]; int i; - if (!dc_pre_update_surfaces_to_target( - dc, new_surfaces, new_surface_count, dc_target)) + if (!dc_pre_update_surfaces_to_stream( + dc, new_surfaces, new_surface_count, dc_stream)) return false; + memset(updates, 0, sizeof(updates)); + memset(flip_addr, 0, sizeof(flip_addr)); + memset(plane_info, 0, sizeof(plane_info)); + memset(scaling_info, 0, sizeof(scaling_info)); + for (i = 0; i < new_surface_count; i++) { updates[i].surface = new_surfaces[i]; updates[i].gamma = @@ -1321,13 +1309,13 @@ bool dc_commit_surfaces_to_target( updates[i].plane_info = &plane_info[i]; updates[i].scaling_info = &scaling_info[i]; } - dc_update_surfaces_for_target(dc, updates, new_surface_count, dc_target); + dc_update_surfaces_for_stream(dc, updates, new_surface_count, dc_stream); - return dc_post_update_surfaces_to_target(dc); + return dc_post_update_surfaces_to_stream(dc); } -void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *updates, - int surface_count, struct dc_target *dc_target) +void dc_update_surfaces_for_stream(struct dc *dc, struct dc_surface_update *updates, + int surface_count, const struct dc_stream *dc_stream) { struct core_dc *core_dc = DC_TO_CORE(dc); struct validate_context *context = core_dc->temp_flip_context; @@ -1377,21 +1365,21 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda can_skip_context_building = false; } - if (!can_skip_context_building && dc_target) { - struct core_target *target = DC_TARGET_TO_CORE(dc_target); + if (!can_skip_context_building && dc_stream) { + const struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); - if (core_dc->current_context->target_count == 0) + if (core_dc->current_context->stream_count == 0) return; - /* Cannot commit surface to a target that is not commited */ - for (i = 0; i < core_dc->current_context->target_count; i++) - if (target == core_dc->current_context->targets[i]) + /* Cannot commit surface to a stream that is not commited */ + for (i = 0; i < core_dc->current_context->stream_count; i++) + if (stream == core_dc->current_context->streams[i]) break; - if (i == core_dc->current_context->target_count) + if (i == core_dc->current_context->stream_count) return; if (!resource_attach_surfaces_to_context( - new_surfaces, surface_count, dc_target, context)) { + new_surfaces, surface_count, dc_stream, context)) { BREAK_TO_DEBUGGER(); return; } @@ -1578,17 +1566,17 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda core_dc->current_context = context; } -uint8_t dc_get_current_target_count(const struct dc *dc) +uint8_t dc_get_current_stream_count(const struct dc *dc) { struct core_dc *core_dc = DC_TO_CORE(dc); - return core_dc->current_context->target_count; + return core_dc->current_context->stream_count; } -struct dc_target *dc_get_target_at_index(const struct dc *dc, uint8_t i) +struct dc_stream *dc_get_stream_at_index(const struct dc *dc, uint8_t i) { struct core_dc *core_dc = DC_TO_CORE(dc); - if (i < core_dc->current_context->target_count) - return &(core_dc->current_context->targets[i]->public); + if (i < core_dc->current_context->stream_count) + return &(core_dc->current_context->streams[i]->public); return NULL; } @@ -1687,8 +1675,8 @@ void dc_set_power_state( core_dc->hwss.init_hw(core_dc); break; default: - /* NULL means "reset/release all DC targets" */ - dc_commit_targets(dc, NULL, 0); + /* NULL means "reset/release all DC streams" */ + dc_commit_streams(dc, NULL, 0); core_dc->hwss.power_down(core_dc); @@ -1882,11 +1870,3 @@ void dc_link_remove_remote_sink(const struct dc_link *link, const struct dc_sink } } -const struct dc_stream_status *dc_stream_get_status( - const struct dc_stream *dc_stream) -{ - struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); - - return &stream->status; -} - diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 4bb6b1d9c970..1f87b948678b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -591,12 +591,12 @@ enum dc_status resource_build_scaling_params_for_context( return DC_OK; } -static void detach_surfaces_for_target( +static void detach_surfaces_for_stream( struct validate_context *context, - const struct dc_target *dc_target) + const struct dc_stream *dc_stream) { int i; - struct core_stream *stream = DC_STREAM_TO_CORE(dc_target->streams[0]); + struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); for (i = 0; i < context->res_ctx.pool->pipe_count; i++) { struct pipe_ctx *cur_pipe = &context->res_ctx.pipe_ctx[i]; @@ -646,15 +646,15 @@ struct pipe_ctx *resource_get_head_pipe_for_stream( } /* - * A free_pipe for a target is defined here as a pipe with a stream that belongs - * to the target but has no surface attached yet + * A free_pipe for a stream is defined here as a pipe + * that has no surface attached yet */ -static struct pipe_ctx *acquire_free_pipe_for_target( +static struct pipe_ctx *acquire_free_pipe_for_stream( struct resource_context *res_ctx, - const struct dc_target *dc_target) + const struct dc_stream *dc_stream) { int i; - struct core_stream *stream = DC_STREAM_TO_CORE(dc_target->streams[0]); + struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); struct pipe_ctx *head_pipe = NULL; @@ -688,12 +688,12 @@ static struct pipe_ctx *acquire_free_pipe_for_target( } -static void release_free_pipes_for_target( +static void release_free_pipes_for_stream( struct resource_context *res_ctx, - const struct dc_target *dc_target) + const struct dc_stream *dc_stream) { int i; - struct core_stream *stream = DC_STREAM_TO_CORE(dc_target->streams[0]); + struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); for (i = res_ctx->pool->pipe_count - 1; i >= 0; i--) { if (res_ctx->pipe_ctx[i].stream == stream && @@ -706,12 +706,12 @@ static void release_free_pipes_for_target( bool resource_attach_surfaces_to_context( const struct dc_surface * const *surfaces, int surface_count, - const struct dc_target *dc_target, + const struct dc_stream *dc_stream, struct validate_context *context) { int i; struct pipe_ctx *tail_pipe; - struct dc_target_status *target_status = NULL; + struct dc_stream_status *stream_status = NULL; if (surface_count > MAX_SURFACE_NUM) { @@ -720,13 +720,13 @@ bool resource_attach_surfaces_to_context( return false; } - for (i = 0; i < context->target_count; i++) - if (&context->targets[i]->public == dc_target) { - target_status = &context->target_status[i]; + for (i = 0; i < context->stream_count; i++) + if (&context->streams[i]->public == dc_stream) { + stream_status = &context->stream_status[i]; break; } - if (target_status == NULL) { - dm_error("Existing target not found; failed to attach surfaces\n"); + if (stream_status == NULL) { + dm_error("Existing stream not found; failed to attach surfaces\n"); return false; } @@ -734,16 +734,16 @@ bool resource_attach_surfaces_to_context( for (i = 0; i < surface_count; i++) dc_surface_retain(surfaces[i]); - detach_surfaces_for_target(context, dc_target); + detach_surfaces_for_stream(context, dc_stream); /* release existing surfaces*/ - for (i = 0; i < target_status->surface_count; i++) - dc_surface_release(target_status->surfaces[i]); + for (i = 0; i < stream_status->surface_count; i++) + dc_surface_release(stream_status->surfaces[i]); - for (i = surface_count; i < target_status->surface_count; i++) - target_status->surfaces[i] = NULL; + for (i = surface_count; i < stream_status->surface_count; i++) + stream_status->surfaces[i] = NULL; - target_status->surface_count = 0; + stream_status->surface_count = 0; if (surface_count == 0) return true; @@ -751,11 +751,11 @@ bool resource_attach_surfaces_to_context( tail_pipe = NULL; for (i = 0; i < surface_count; i++) { struct core_surface *surface = DC_SURFACE_TO_CORE(surfaces[i]); - struct pipe_ctx *free_pipe = acquire_free_pipe_for_target( - &context->res_ctx, dc_target); + struct pipe_ctx *free_pipe = acquire_free_pipe_for_stream( + &context->res_ctx, dc_stream); if (!free_pipe) { - target_status->surfaces[i] = NULL; + stream_status->surfaces[i] = NULL; return false; } @@ -769,13 +769,13 @@ bool resource_attach_surfaces_to_context( tail_pipe = free_pipe; } - release_free_pipes_for_target(&context->res_ctx, dc_target); + release_free_pipes_for_stream(&context->res_ctx, dc_stream); /* assign new surfaces*/ for (i = 0; i < surface_count; i++) - target_status->surfaces[i] = surfaces[i]; + stream_status->surfaces[i] = surfaces[i]; - target_status->surface_count = surface_count; + stream_status->surface_count = surface_count; return true; } @@ -819,25 +819,14 @@ static bool are_stream_backends_same( return true; } -bool is_target_unchanged( - const struct core_target *old_target, const struct core_target *target) +bool is_stream_unchanged( + const struct core_stream *old_stream, const struct core_stream *stream) { - int i; - - if (old_target == target) + if (old_stream == stream) return true; - if (old_target->public.stream_count != target->public.stream_count) - return false; - - for (i = 0; i < old_target->public.stream_count; i++) { - const struct core_stream *old_stream = DC_STREAM_TO_CORE( - old_target->public.streams[i]); - const struct core_stream *stream = DC_STREAM_TO_CORE( - target->public.streams[i]); - if (!are_stream_backends_same(old_stream, stream)) - return false; - } + if (!are_stream_backends_same(old_stream, stream)) + return false; return true; } @@ -851,23 +840,23 @@ bool resource_validate_attach_surfaces( int i, j; for (i = 0; i < set_count; i++) { - for (j = 0; j < old_context->target_count; j++) - if (is_target_unchanged( - old_context->targets[j], - context->targets[i])) { + for (j = 0; j < old_context->stream_count; j++) + if (is_stream_unchanged( + old_context->streams[j], + context->streams[i])) { if (!resource_attach_surfaces_to_context( - old_context->target_status[j].surfaces, - old_context->target_status[j].surface_count, - &context->targets[i]->public, + old_context->stream_status[j].surfaces, + old_context->stream_status[j].surface_count, + &context->streams[i]->public, context)) return false; - context->target_status[i] = old_context->target_status[j]; + context->stream_status[i] = old_context->stream_status[j]; } if (set[i].surface_count != 0) if (!resource_attach_surfaces_to_context( set[i].surfaces, set[i].surface_count, - &context->targets[i]->public, + &context->streams[i]->public, context)) return false; @@ -1001,20 +990,15 @@ static void update_stream_signal(struct core_stream *stream) } bool resource_is_stream_unchanged( - const struct validate_context *old_context, struct core_stream *stream) + const struct validate_context *old_context, const struct core_stream *stream) { - int i, j; - - for (i = 0; i < old_context->target_count; i++) { - struct core_target *old_target = old_context->targets[i]; + int i; - for (j = 0; j < old_target->public.stream_count; j++) { - struct core_stream *old_stream = - DC_STREAM_TO_CORE(old_target->public.streams[j]); + for (i = 0; i < old_context->stream_count; i++) { + const struct core_stream *old_stream = old_context->streams[i]; - if (are_stream_backends_same(old_stream, stream)) + if (are_stream_backends_same(old_stream, stream)) return true; - } } return false; @@ -1036,23 +1020,19 @@ static struct core_stream *find_pll_sharable_stream( const struct core_stream *stream_needs_pll, struct validate_context *context) { - int i, j; + int i; - for (i = 0; i < context->target_count; i++) { - struct core_target *target = context->targets[i]; + for (i = 0; i < context->stream_count; i++) { + struct core_stream *stream_has_pll = context->streams[i]; - for (j = 0; j < target->public.stream_count; j++) { - struct core_stream *stream_has_pll = - DC_STREAM_TO_CORE(target->public.streams[j]); + /* We are looking for non dp, non virtual stream */ + if (resource_are_streams_timing_synchronizable( + stream_needs_pll, stream_has_pll) + && !dc_is_dp_signal(stream_has_pll->signal) + && stream_has_pll->sink->link->public.connector_signal + != SIGNAL_TYPE_VIRTUAL) + return stream_has_pll; - /* We are looking for non dp, non virtual stream */ - if (resource_are_streams_timing_synchronizable( - stream_needs_pll, stream_has_pll) - && !dc_is_dp_signal(stream_has_pll->signal) - && stream_has_pll->sink->link->public.connector_signal - != SIGNAL_TYPE_VIRTUAL) - return stream_has_pll; - } } return NULL; @@ -1091,25 +1071,20 @@ static void calculate_phy_pix_clks( const struct core_dc *dc, struct validate_context *context) { - int i, j; - - for (i = 0; i < context->target_count; i++) { - struct core_target *target = context->targets[i]; + int i; - for (j = 0; j < target->public.stream_count; j++) { - struct core_stream *stream = - DC_STREAM_TO_CORE(target->public.streams[j]); + for (i = 0; i < context->stream_count; i++) { + struct core_stream *stream = context->streams[i]; - update_stream_signal(stream); + update_stream_signal(stream); - /* update actual pixel clock on all streams */ - if (dc_is_hdmi_signal(stream->signal)) - stream->phy_pix_clk = get_norm_pix_clk( - &stream->public.timing); - else - stream->phy_pix_clk = - stream->public.timing.pix_clk_khz; - } + /* update actual pixel clock on all streams */ + if (dc_is_hdmi_signal(stream->signal)) + stream->phy_pix_clk = get_norm_pix_clk( + &stream->public.timing); + else + stream->phy_pix_clk = + stream->public.timing.pix_clk_khz; } } @@ -1117,136 +1092,122 @@ enum dc_status resource_map_pool_resources( const struct core_dc *dc, struct validate_context *context) { - int i, j, k; + int i, j; calculate_phy_pix_clks(dc, context); - for (i = 0; i < context->target_count; i++) { - struct core_target *target = context->targets[i]; - - for (j = 0; j < target->public.stream_count; j++) { - struct core_stream *stream = - DC_STREAM_TO_CORE(target->public.streams[j]); - - if (!resource_is_stream_unchanged(dc->current_context, stream)) - continue; - - /* mark resources used for stream that is already active */ - for (k = 0; k < MAX_PIPES; k++) { - struct pipe_ctx *pipe_ctx = - &context->res_ctx.pipe_ctx[k]; - const struct pipe_ctx *old_pipe_ctx = - &dc->current_context->res_ctx.pipe_ctx[k]; + for (i = 0; i < context->stream_count; i++) { + struct core_stream *stream = context->streams[i]; - if (!are_stream_backends_same(old_pipe_ctx->stream, stream)) - continue; + if (!resource_is_stream_unchanged(dc->current_context, stream)) + continue; - pipe_ctx->stream = stream; - copy_pipe_ctx(old_pipe_ctx, pipe_ctx); + /* mark resources used for stream that is already active */ + for (j = 0; j < MAX_PIPES; j++) { + struct pipe_ctx *pipe_ctx = + &context->res_ctx.pipe_ctx[j]; + const struct pipe_ctx *old_pipe_ctx = + &dc->current_context->res_ctx.pipe_ctx[j]; - /* Split pipe resource, do not acquire back end */ - if (!pipe_ctx->stream_enc) - continue; + if (!are_stream_backends_same(old_pipe_ctx->stream, stream)) + continue; - set_stream_engine_in_use( - &context->res_ctx, - pipe_ctx->stream_enc); - - /* Switch to dp clock source only if there is - * no non dp stream that shares the same timing - * with the dp stream. - */ - if (dc_is_dp_signal(pipe_ctx->stream->signal) && - !find_pll_sharable_stream(stream, context)) - pipe_ctx->clock_source = - context->res_ctx.pool->dp_clock_source; + pipe_ctx->stream = stream; + copy_pipe_ctx(old_pipe_ctx, pipe_ctx); - resource_reference_clock_source( - &context->res_ctx, - pipe_ctx->clock_source); + /* Split pipe resource, do not acquire back end */ + if (!pipe_ctx->stream_enc) + continue; - set_audio_in_use(&context->res_ctx, - pipe_ctx->audio); - } + set_stream_engine_in_use( + &context->res_ctx, + pipe_ctx->stream_enc); + + /* Switch to dp clock source only if there is + * no non dp stream that shares the same timing + * with the dp stream. + */ + if (dc_is_dp_signal(pipe_ctx->stream->signal) && + !find_pll_sharable_stream(stream, context)) + pipe_ctx->clock_source = + context->res_ctx.pool->dp_clock_source; + + resource_reference_clock_source( + &context->res_ctx, + pipe_ctx->clock_source); + + set_audio_in_use(&context->res_ctx, + pipe_ctx->audio); } } - for (i = 0; i < context->target_count; i++) { - struct core_target *target = context->targets[i]; - - for (j = 0; j < target->public.stream_count; j++) { - struct core_stream *stream = - DC_STREAM_TO_CORE(target->public.streams[j]); - struct pipe_ctx *pipe_ctx = NULL; - int pipe_idx = -1; - - if (resource_is_stream_unchanged(dc->current_context, stream)) - continue; - /* acquire new resources */ - pipe_idx = acquire_first_free_pipe( - &context->res_ctx, stream); - if (pipe_idx < 0) - return DC_NO_CONTROLLER_RESOURCE; - - - pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx]; + for (i = 0; i < context->stream_count; i++) { + struct core_stream *stream = context->streams[i]; + struct pipe_ctx *pipe_ctx = NULL; + int pipe_idx = -1; - pipe_ctx->stream_enc = - find_first_free_match_stream_enc_for_link( - &context->res_ctx, stream); - - if (!pipe_ctx->stream_enc) - return DC_NO_STREAM_ENG_RESOURCE; - - set_stream_engine_in_use( + if (resource_is_stream_unchanged(dc->current_context, stream)) + continue; + /* acquire new resources */ + pipe_idx = acquire_first_free_pipe(&context->res_ctx, stream); + if (pipe_idx < 0) + return DC_NO_CONTROLLER_RESOURCE; + + + pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx]; + + pipe_ctx->stream_enc = + find_first_free_match_stream_enc_for_link( + &context->res_ctx, stream); + + if (!pipe_ctx->stream_enc) + return DC_NO_STREAM_ENG_RESOURCE; + + set_stream_engine_in_use( + &context->res_ctx, + pipe_ctx->stream_enc); + + /* TODO: Add check if ASIC support and EDID audio */ + if (!stream->sink->converter_disable_audio && + dc_is_audio_capable_signal(pipe_ctx->stream->signal) && + stream->public.audio_info.mode_count) { + pipe_ctx->audio = find_first_free_audio( + &context->res_ctx); + + /* + * Audio assigned in order first come first get. + * There are asics which has number of audio + * resources less then number of pipes + */ + if (pipe_ctx->audio) + set_audio_in_use( &context->res_ctx, - pipe_ctx->stream_enc); - - /* TODO: Add check if ASIC support and EDID audio */ - if (!stream->sink->converter_disable_audio && - dc_is_audio_capable_signal(pipe_ctx->stream->signal) && - stream->public.audio_info.mode_count) { - pipe_ctx->audio = find_first_free_audio( - &context->res_ctx); - - /* - * Audio assigned in order first come first get. - * There are asics which has number of audio - * resources less then number of pipes - */ - if (pipe_ctx->audio) - set_audio_in_use( - &context->res_ctx, - pipe_ctx->audio); - } - - if (j == 0) { - context->target_status[i].primary_otg_inst = - pipe_ctx->tg->inst; - } + pipe_ctx->audio); } + + context->stream_status[i].primary_otg_inst = pipe_ctx->tg->inst; } return DC_OK; } -/* first target in the context is used to populate the rest */ -void validate_guaranteed_copy_target( +/* first stream in the context is used to populate the rest */ +void validate_guaranteed_copy_streams( struct validate_context *context, - int max_targets) + int max_streams) { int i; - for (i = 1; i < max_targets; i++) { - context->targets[i] = context->targets[0]; + for (i = 1; i < max_streams; i++) { + context->streams[i] = context->streams[0]; copy_pipe_ctx(&context->res_ctx.pipe_ctx[0], &context->res_ctx.pipe_ctx[i]); context->res_ctx.pipe_ctx[i].stream = context->res_ctx.pipe_ctx[0].stream; - dc_target_retain(&context->targets[i]->public); - context->target_count++; + dc_stream_retain(&context->streams[i]->public); + context->stream_count++; } } @@ -1875,18 +1836,19 @@ void resource_validate_ctx_destruct(struct validate_context *context) { int i, j; - for (i = 0; i < context->target_count; i++) { - for (j = 0; j < context->target_status[i].surface_count; j++) + for (i = 0; i < context->stream_count; i++) { + for (j = 0; j < context->stream_status[i].surface_count; j++) dc_surface_release( - context->target_status[i].surfaces[j]); + context->stream_status[i].surfaces[j]); - context->target_status[i].surface_count = 0; - dc_target_release(&context->targets[i]->public); + context->stream_status[i].surface_count = 0; + dc_stream_release(&context->streams[i]->public); + context->streams[i] = NULL; } } /* - * Copy src_ctx into dst_ctx and retain all surfaces and targets referenced + * Copy src_ctx into dst_ctx and retain all surfaces and streams referenced * by the src_ctx */ void resource_validate_ctx_copy_construct( @@ -1908,11 +1870,11 @@ void resource_validate_ctx_copy_construct( } - for (i = 0; i < dst_ctx->target_count; i++) { - dc_target_retain(&dst_ctx->targets[i]->public); - for (j = 0; j < dst_ctx->target_status[i].surface_count; j++) + for (i = 0; i < dst_ctx->stream_count; i++) { + dc_stream_retain(&dst_ctx->streams[i]->public); + for (j = 0; j < dst_ctx->stream_status[i].surface_count; j++) dc_surface_retain( - dst_ctx->target_status[i].surfaces[j]); + dst_ctx->stream_status[i].surfaces[j]); } } @@ -1968,53 +1930,48 @@ enum dc_status resource_map_clock_resources( const struct core_dc *dc, struct validate_context *context) { - int i, j, k; + int i, j; /* acquire new resources */ - for (i = 0; i < context->target_count; i++) { - struct core_target *target = context->targets[i]; + for (i = 0; i < context->stream_count; i++) { + const struct core_stream *stream = context->streams[i]; - for (j = 0; j < target->public.stream_count; j++) { - struct core_stream *stream = - DC_STREAM_TO_CORE(target->public.streams[j]); + if (resource_is_stream_unchanged(dc->current_context, stream)) + continue; + + for (j = 0; j < MAX_PIPES; j++) { + struct pipe_ctx *pipe_ctx = + &context->res_ctx.pipe_ctx[j]; - if (resource_is_stream_unchanged(dc->current_context, stream)) + if (context->res_ctx.pipe_ctx[j].stream != stream) continue; - for (k = 0; k < MAX_PIPES; k++) { - struct pipe_ctx *pipe_ctx = - &context->res_ctx.pipe_ctx[k]; + if (dc_is_dp_signal(pipe_ctx->stream->signal) + || pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL) + pipe_ctx->clock_source = + context->res_ctx.pool->dp_clock_source; + else { + pipe_ctx->clock_source = NULL; - if (context->res_ctx.pipe_ctx[k].stream != stream) - continue; + if (!dc->public.config.disable_disp_pll_sharing) + resource_find_used_clk_src_for_sharing( + &context->res_ctx, + pipe_ctx); - if (dc_is_dp_signal(pipe_ctx->stream->signal) - || pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL) + if (pipe_ctx->clock_source == NULL) pipe_ctx->clock_source = - context->res_ctx.pool->dp_clock_source; - else { - pipe_ctx->clock_source = NULL; - - if (!dc->public.config.disable_disp_pll_sharing) - resource_find_used_clk_src_for_sharing( - &context->res_ctx, - pipe_ctx); - - if (pipe_ctx->clock_source == NULL) - pipe_ctx->clock_source = - dc_resource_find_first_free_pll(&context->res_ctx); - } + dc_resource_find_first_free_pll(&context->res_ctx); + } - if (pipe_ctx->clock_source == NULL) - return DC_NO_CLOCK_SOURCE_RESOURCE; + if (pipe_ctx->clock_source == NULL) + return DC_NO_CLOCK_SOURCE_RESOURCE; - resource_reference_clock_source( - &context->res_ctx, - pipe_ctx->clock_source); + resource_reference_clock_source( + &context->res_ctx, + pipe_ctx->clock_source); - /* only one cs per stream regardless of mpo */ - break; - } + /* only one cs per stream regardless of mpo */ + break; } } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index cda67a78dbfd..bc1f387d1992 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -27,6 +27,8 @@ #include "dc.h" #include "core_types.h" #include "resource.h" +#include "ipp.h" +#include "timing_generator.h" /******************************************************************************* * Private definitions @@ -146,3 +148,184 @@ construct_fail: alloc_fail: return NULL; } + +const struct dc_stream_status *dc_stream_get_status( + const struct dc_stream *dc_stream) +{ + uint8_t i; + struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); + struct core_dc *dc = DC_TO_CORE(stream->ctx->dc); + + for (i = 0; i < dc->current_context->stream_count; i++) + if (stream == dc->current_context->streams[i]) + return &dc->current_context->stream_status[i]; + + return NULL; +} + +/** + * Update the cursor attributes and set cursor surface address + */ +bool dc_stream_set_cursor_attributes( + const struct dc_stream *dc_stream, + const struct dc_cursor_attributes *attributes) +{ + int i; + struct core_stream *stream; + struct core_dc *core_dc; + struct resource_context *res_ctx; + bool ret = false; + + if (NULL == dc_stream) { + dm_error("DC: dc_stream is NULL!\n"); + return false; + } + if (NULL == attributes) { + dm_error("DC: attributes is NULL!\n"); + return false; + } + + stream = DC_STREAM_TO_CORE(dc_stream); + core_dc = DC_TO_CORE(stream->ctx->dc); + res_ctx = &core_dc->current_context->res_ctx; + + for (i = 0; i < MAX_PIPES; i++) { + struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; + + if (pipe_ctx->stream == stream) { + struct input_pixel_processor *ipp = pipe_ctx->ipp; + + if (ipp->funcs->ipp_cursor_set_attributes( + ipp, attributes)) + ret = true; + } + } + + return ret; +} + +bool dc_stream_set_cursor_position( + const struct dc_stream *dc_stream, + const struct dc_cursor_position *position) +{ + int i; + struct core_stream *stream; + struct core_dc *core_dc; + struct resource_context *res_ctx; + bool ret = false; + + if (NULL == dc_stream) { + dm_error("DC: dc_stream is NULL!\n"); + return false; + } + + if (NULL == position) { + dm_error("DC: cursor position is NULL!\n"); + return false; + } + + stream = DC_STREAM_TO_CORE(dc_stream); + core_dc = DC_TO_CORE(stream->ctx->dc); + res_ctx = &core_dc->current_context->res_ctx; + + for (i = 0; i < MAX_PIPES; i++) { + struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; + + if (pipe_ctx->stream == stream) { + struct input_pixel_processor *ipp = pipe_ctx->ipp; + struct dc_cursor_mi_param param = { + .pixel_clk_khz = dc_stream->timing.pix_clk_khz, + .ref_clk_khz = 48000,/*todo refclk*/ + .viewport_x_start = pipe_ctx->scl_data.viewport.x, + .viewport_width = pipe_ctx->scl_data.viewport.width, + .h_scale_ratio = pipe_ctx->scl_data.ratios.horz, + }; + + ipp->funcs->ipp_cursor_set_position(ipp, position, ¶m); + ret = true; + } + } + + return ret; +} + +uint32_t dc_stream_get_vblank_counter(const struct dc_stream *dc_stream) +{ + uint8_t i; + struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); + struct core_dc *core_dc = DC_TO_CORE(stream->ctx->dc); + struct resource_context *res_ctx = + &core_dc->current_context->res_ctx; + + for (i = 0; i < MAX_PIPES; i++) { + struct timing_generator *tg = res_ctx->pipe_ctx[i].tg; + + if (res_ctx->pipe_ctx[i].stream != stream) + continue; + + return tg->funcs->get_frame_count(tg); + } + + return 0; +} + +uint32_t dc_stream_get_scanoutpos( + const struct dc_stream *dc_stream, + uint32_t *vbl, + uint32_t *position) +{ + uint8_t i; + struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); + struct core_dc *core_dc = DC_TO_CORE(stream->ctx->dc); + struct resource_context *res_ctx = + &core_dc->current_context->res_ctx; + + for (i = 0; i < MAX_PIPES; i++) { + struct timing_generator *tg = res_ctx->pipe_ctx[i].tg; + + if (res_ctx->pipe_ctx[i].stream != stream) + continue; + + return tg->funcs->get_scanoutpos(tg, vbl, position); + } + + return 0; +} + + +void dc_stream_log( + const struct dc_stream *stream, + struct dal_logger *dm_logger, + enum dc_log_type log_type) +{ + const struct core_stream *core_stream = + DC_STREAM_TO_CORE(stream); + + dm_logger_write(dm_logger, + log_type, + "core_stream 0x%x: src: %d, %d, %d, %d; dst: %d, %d, %d, %d;\n", + core_stream, + core_stream->public.src.x, + core_stream->public.src.y, + core_stream->public.src.width, + core_stream->public.src.height, + core_stream->public.dst.x, + core_stream->public.dst.y, + core_stream->public.dst.width, + core_stream->public.dst.height); + dm_logger_write(dm_logger, + log_type, + "\tpix_clk_khz: %d, h_total: %d, v_total: %d\n", + core_stream->public.timing.pix_clk_khz, + core_stream->public.timing.h_total, + core_stream->public.timing.v_total); + dm_logger_write(dm_logger, + log_type, + "\tsink name: %s, serial: %d\n", + core_stream->sink->public.edid_caps.display_name, + core_stream->sink->public.edid_caps.serial_number); + dm_logger_write(dm_logger, + log_type, + "\tlink: %d\n", + core_stream->sink->link->public.link_index); +} diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_target.c b/drivers/gpu/drm/amd/display/dc/core/dc_target.c deleted file mode 100644 index 2d25b00b4bff..000000000000 --- a/drivers/gpu/drm/amd/display/dc/core/dc_target.c +++ /dev/null @@ -1,333 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" -#include "core_types.h" -#include "hw_sequencer.h" -#include "resource.h" -#include "ipp.h" -#include "timing_generator.h" - -struct target { - struct core_target protected; - int ref_count; -}; - -#define DC_TARGET_TO_TARGET(dc_target) \ - container_of(dc_target, struct target, protected.public) -#define CORE_TARGET_TO_TARGET(core_target) \ - container_of(core_target, struct target, protected) - -static void construct( - struct core_target *target, - struct dc_context *ctx, - struct dc_stream *dc_streams[], - uint8_t stream_count) -{ - uint8_t i; - for (i = 0; i < stream_count; i++) { - target->public.streams[i] = dc_streams[i]; - dc_stream_retain(dc_streams[i]); - } - - target->ctx = ctx; - target->public.stream_count = stream_count; -} - -static void destruct(struct core_target *core_target) -{ - int i; - - for (i = 0; i < core_target->public.stream_count; i++) { - dc_stream_release( - (struct dc_stream *)core_target->public.streams[i]); - core_target->public.streams[i] = NULL; - } -} - -void dc_target_retain(const struct dc_target *dc_target) -{ - struct target *target = DC_TARGET_TO_TARGET(dc_target); - - ASSERT(target->ref_count > 0); - target->ref_count++; -} - -void dc_target_release(const struct dc_target *dc_target) -{ - struct target *target = DC_TARGET_TO_TARGET(dc_target); - struct core_target *protected = DC_TARGET_TO_CORE(dc_target); - - ASSERT(target->ref_count > 0); - target->ref_count--; - - if (target->ref_count == 0) { - destruct(protected); - dm_free(target); - } -} - -const struct dc_target_status *dc_target_get_status( - const struct dc_target* dc_target) -{ - uint8_t i; - struct core_target* target = DC_TARGET_TO_CORE(dc_target); - struct core_dc *dc = DC_TO_CORE(target->ctx->dc); - - for (i = 0; i < dc->current_context->target_count; i++) - if (target == dc->current_context->targets[i]) - return &dc->current_context->target_status[i]; - - return NULL; -} - -struct dc_target *dc_create_target_for_streams( - struct dc_stream *dc_streams[], - uint8_t stream_count) -{ - struct core_stream *stream; - struct target *target; - - if (0 == stream_count) - goto target_alloc_fail; - - stream = DC_STREAM_TO_CORE(dc_streams[0]); - - target = dm_alloc(sizeof(struct target)); - - if (NULL == target) - goto target_alloc_fail; - - construct(&target->protected, stream->ctx, dc_streams, stream_count); - - target->ref_count++; - - return &target->protected.public; - -target_alloc_fail: - return NULL; -} - -bool dc_target_is_connected_to_sink( - const struct dc_target * dc_target, - const struct dc_sink *dc_sink) -{ - struct core_target *target = DC_TARGET_TO_CORE(dc_target); - uint8_t i; - for (i = 0; i < target->public.stream_count; i++) { - if (target->public.streams[i]->sink == dc_sink) - return true; - } - return false; -} - -/** - * Update the cursor attributes and set cursor surface address - */ -bool dc_target_set_cursor_attributes( - struct dc_target *dc_target, - const struct dc_cursor_attributes *attributes) -{ - int i, j; - struct core_target *target; - struct core_dc *core_dc; - struct resource_context *res_ctx; - bool ret = false; - - if (NULL == dc_target) { - dm_error("DC: dc_target is NULL!\n"); - return false; - } - if (NULL == attributes) { - dm_error("DC: attributes is NULL!\n"); - return false; - } - - target = DC_TARGET_TO_CORE(dc_target); - core_dc = DC_TO_CORE(target->ctx->dc); - res_ctx = &core_dc->current_context->res_ctx; - - for (i = 0; i < dc_target->stream_count; i++) { - const struct dc_stream *stream = dc_target->streams[i]; - - for (j = 0; j < MAX_PIPES; j++) { - struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[j]; - - if (&pipe_ctx->stream->public == stream) { - struct input_pixel_processor *ipp = pipe_ctx->ipp; - - if (ipp->funcs->ipp_cursor_set_attributes( - ipp, attributes)) - ret = true; - } - } - } - - return ret; -} - -bool dc_target_set_cursor_position( - struct dc_target *dc_target, - const struct dc_cursor_position *position) -{ - int i, j; - struct core_target *target = DC_TARGET_TO_CORE(dc_target); - struct core_dc *core_dc = DC_TO_CORE(target->ctx->dc); - struct resource_context *res_ctx = &core_dc->current_context->res_ctx; - bool ret = false; - - if (NULL == dc_target) { - dm_error("DC: dc_target is NULL!\n"); - return false; - } - - if (NULL == position) { - dm_error("DC: cursor position is NULL!\n"); - return false; - } - - for (i = 0; i < dc_target->stream_count; i++) { - const struct dc_stream *stream = dc_target->streams[i]; - - for (j = 0; j < MAX_PIPES; j++) { - struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[j]; - - if (&pipe_ctx->stream->public == stream) { - struct input_pixel_processor *ipp = pipe_ctx->ipp; - struct dc_cursor_mi_param param = { - .pixel_clk_khz = stream->timing.pix_clk_khz, - .ref_clk_khz = 48000,/*todo refclk*/ - .viewport_x_start = pipe_ctx->scl_data.viewport.x, - .viewport_width = pipe_ctx->scl_data.viewport.width, - .h_scale_ratio = pipe_ctx->scl_data.ratios.horz, - }; - - ipp->funcs->ipp_cursor_set_position(ipp, position, ¶m); - ret = true; - } - } - } - - return ret; -} - -uint32_t dc_target_get_vblank_counter(const struct dc_target *dc_target) -{ - uint8_t i, j; - struct core_target *target = DC_TARGET_TO_CORE(dc_target); - struct core_dc *core_dc = DC_TO_CORE(target->ctx->dc); - struct resource_context *res_ctx = - &core_dc->current_context->res_ctx; - - for (i = 0; i < target->public.stream_count; i++) { - for (j = 0; j < MAX_PIPES; j++) { - struct timing_generator *tg = res_ctx->pipe_ctx[j].tg; - - if (res_ctx->pipe_ctx[j].stream != - DC_STREAM_TO_CORE(target->public.streams[i])) - continue; - - return tg->funcs->get_frame_count(tg); - } - } - - return 0; -} - -uint32_t dc_target_get_scanoutpos( - const struct dc_target *dc_target, - uint32_t *vbl, - uint32_t *position) -{ - uint8_t i, j; - struct core_target *target = DC_TARGET_TO_CORE(dc_target); - struct core_dc *core_dc = DC_TO_CORE(target->ctx->dc); - struct resource_context *res_ctx = - &core_dc->current_context->res_ctx; - - for (i = 0; i < target->public.stream_count; i++) { - for (j = 0; j < MAX_PIPES; j++) { - struct timing_generator *tg = res_ctx->pipe_ctx[j].tg; - - if (res_ctx->pipe_ctx[j].stream != - DC_STREAM_TO_CORE(target->public.streams[i])) - continue; - - return tg->funcs->get_scanoutpos(tg, vbl, position); - } - } - - return 0; -} - -void dc_target_log( - const struct dc_target *dc_target, - struct dal_logger *dm_logger, - enum dc_log_type log_type) -{ - int i; - - const struct core_target *core_target = - CONST_DC_TARGET_TO_CORE(dc_target); - - dm_logger_write(dm_logger, - log_type, - "core_target 0x%x: stream_count=%d\n", - core_target, - core_target->public.stream_count); - - for (i = 0; i < core_target->public.stream_count; i++) { - const struct core_stream *core_stream = - DC_STREAM_TO_CORE(core_target->public.streams[i]); - - dm_logger_write(dm_logger, - log_type, - "core_stream 0x%x: src: %d, %d, %d, %d; dst: %d, %d, %d, %d;\n", - core_stream, - core_stream->public.src.x, - core_stream->public.src.y, - core_stream->public.src.width, - core_stream->public.src.height, - core_stream->public.dst.x, - core_stream->public.dst.y, - core_stream->public.dst.width, - core_stream->public.dst.height); - dm_logger_write(dm_logger, - log_type, - "\tpix_clk_khz: %d, h_total: %d, v_total: %d\n", - core_stream->public.timing.pix_clk_khz, - core_stream->public.timing.h_total, - core_stream->public.timing.v_total); - dm_logger_write(dm_logger, - log_type, - "\tsink name: %s, serial: %d\n", - core_stream->sink->public.edid_caps.display_name, - core_stream->sink->public.edid_caps.serial_number); - dm_logger_write(dm_logger, - log_type, - "\tlink: %d\n", - core_stream->sink->link->public.link_index); - } -} diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index e8cb7a4dee80..b814e7b76bbc 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -32,8 +32,8 @@ #include "gpio_types.h" #include "link_service_types.h" -#define MAX_TARGETS 6 #define MAX_SURFACES 3 +#define MAX_STREAMS 6 #define MAX_SINKS_PER_LINK 4 /******************************************************************************* @@ -41,7 +41,7 @@ ******************************************************************************/ struct dc_caps { - uint32_t max_targets; + uint32_t max_streams; uint32_t max_links; uint32_t max_audios; uint32_t max_slave_planes; @@ -139,7 +139,6 @@ struct dc_config { struct dc_debug { bool surface_visual_confirm; bool max_disp_clk; - bool target_trace; bool surface_trace; bool timing_trace; bool validation_trace; @@ -351,95 +350,91 @@ void dc_flip_surface_addrs(struct dc *dc, uint32_t count); /* - * Set up surface attributes and associate to a target - * The surfaces parameter is an absolute set of all surface active for the target. - * If no surfaces are provided, the target will be blanked; no memory read. + * Set up surface attributes and associate to a stream + * The surfaces parameter is an absolute set of all surface active for the stream. + * If no surfaces are provided, the stream will be blanked; no memory read. * Any flip related attribute changes must be done through this interface. * * After this call: - * Surfaces attributes are programmed and configured to be composed into target. + * Surfaces attributes are programmed and configured to be composed into stream. * This does not trigger a flip. No surface address is programmed. */ -bool dc_commit_surfaces_to_target( +bool dc_commit_surfaces_to_stream( struct dc *dc, const struct dc_surface **dc_surfaces, uint8_t surface_count, - struct dc_target *dc_target); + const struct dc_stream *stream); -bool dc_pre_update_surfaces_to_target( +bool dc_pre_update_surfaces_to_stream( struct dc *dc, const struct dc_surface *const *new_surfaces, uint8_t new_surface_count, - struct dc_target *dc_target); + const struct dc_stream *stream); -bool dc_post_update_surfaces_to_target( +bool dc_post_update_surfaces_to_stream( struct dc *dc); -void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *updates, - int surface_count, struct dc_target *dc_target); +void dc_update_surfaces_for_stream(struct dc *dc, struct dc_surface_update *updates, + int surface_count, const struct dc_stream *stream); /******************************************************************************* - * Target Interfaces + * Stream Interfaces ******************************************************************************/ -#define MAX_STREAM_NUM 1 +struct dc_stream { + const struct dc_sink *sink; + struct dc_crtc_timing timing; -struct dc_target { - uint8_t stream_count; - const struct dc_stream *streams[MAX_STREAM_NUM]; -}; + enum dc_color_space output_color_space; -/* - * Target status is returned from dc_target_get_status in order to get the - * the IRQ source, current frame counter and currently attached surfaces. - */ -struct dc_target_status { - int primary_otg_inst; - int cur_frame_count; - int surface_count; - const struct dc_surface *surfaces[MAX_SURFACE_NUM]; -}; + struct rect src; /* composition area */ + struct rect dst; /* stream addressable area */ -struct dc_target *dc_create_target_for_streams( - struct dc_stream *dc_streams[], - uint8_t stream_count); + struct audio_info audio_info; + + bool ignore_msa_timing_param; + + struct freesync_context freesync_ctx; + + const struct dc_transfer_func *out_transfer_func; + struct colorspace_transform gamut_remap_matrix; + struct csc_transform csc_color_matrix; + + /* TODO: dithering */ + /* TODO: custom INFO packets */ + /* TODO: ABM info (DMCU) */ + /* TODO: PSR info */ + /* TODO: CEA VIC */ +}; /* - * Get the current target status. + * Log the current stream state. */ -const struct dc_target_status *dc_target_get_status( - const struct dc_target* dc_target); - -void dc_target_retain(const struct dc_target *dc_target); -void dc_target_release(const struct dc_target *dc_target); -void dc_target_log( - const struct dc_target *dc_target, +void dc_stream_log( + const struct dc_stream *stream, struct dal_logger *dc_logger, enum dc_log_type log_type); -uint8_t dc_get_current_target_count(const struct dc *dc); -struct dc_target *dc_get_target_at_index(const struct dc *dc, uint8_t i); +uint8_t dc_get_current_stream_count(const struct dc *dc); +struct dc_stream *dc_get_stream_at_index(const struct dc *dc, uint8_t i); -bool dc_target_is_connected_to_sink( - const struct dc_target *dc_target, - const struct dc_sink *dc_sink); - -uint32_t dc_target_get_vblank_counter(const struct dc_target *dc_target); +/* + * Return the current frame counter. + */ +uint32_t dc_stream_get_vblank_counter(const struct dc_stream *stream); /* TODO: Return parsed values rather than direct register read * This has a dependency on the caller (amdgpu_get_crtc_scanoutpos) * being refactored properly to be dce-specific */ -uint32_t dc_target_get_scanoutpos( - const struct dc_target *dc_target, - uint32_t *vbl, - uint32_t *position); +uint32_t dc_stream_get_scanoutpos( + const struct dc_stream *stream, uint32_t *vbl, uint32_t *position); /* - * Structure to store surface/target associations for validation + * Structure to store surface/stream associations for validation */ struct dc_validation_set { - const struct dc_target *target; + const struct dc_stream *stream; const struct dc_surface *surfaces[MAX_SURFACES]; uint8_t surface_count; }; @@ -456,8 +451,8 @@ bool dc_validate_resources( uint8_t set_count); /* - * This function takes a target and checks if it is guaranteed to be supported. - * Guaranteed means that MAX_COFUNC*target is supported. + * This function takes a stream and checks if it is guaranteed to be supported. + * Guaranteed means that MAX_COFUNC similar streams are supported. * * After this call: * No hardware is programmed for call. Only validation is done. @@ -465,49 +460,20 @@ bool dc_validate_resources( bool dc_validate_guaranteed( const struct dc *dc, - const struct dc_target *dc_target); + const struct dc_stream *stream); /* - * Set up streams and links associated to targets to drive sinks - * The targets parameter is an absolute set of all active targets. + * Set up streams and links associated to drive sinks + * The streams parameter is an absolute set of all active streams. * * After this call: * Phy, Encoder, Timing Generator are programmed and enabled. - * New targets are enabled with blank stream; no memory read. + * New streams are enabled with blank stream; no memory read. */ -bool dc_commit_targets( +bool dc_commit_streams( struct dc *dc, - struct dc_target *targets[], - uint8_t target_count); - -/******************************************************************************* - * Stream Interfaces - ******************************************************************************/ -struct dc_stream { - const struct dc_sink *sink; - struct dc_crtc_timing timing; - - enum dc_color_space output_color_space; - - struct rect src; /* viewport in target space*/ - struct rect dst; /* stream addressable area */ - - struct audio_info audio_info; - - bool ignore_msa_timing_param; - - struct freesync_context freesync_ctx; - - const struct dc_transfer_func *out_transfer_func; - struct colorspace_transform gamut_remap_matrix; - struct csc_transform csc_color_matrix; - - /* TODO: dithering */ - /* TODO: custom INFO packets */ - /* TODO: ABM info (DMCU) */ - /* TODO: PSR info */ - /* TODO: CEA VIC */ -}; + const struct dc_stream *streams[], + uint8_t stream_count); /** * Create a new default stream for the requested sink @@ -518,6 +484,10 @@ void dc_stream_retain(const struct dc_stream *dc_stream); void dc_stream_release(const struct dc_stream *dc_stream); struct dc_stream_status { + int primary_otg_inst; + int surface_count; + const struct dc_surface *surfaces[MAX_SURFACE_NUM]; + /* * link this stream passes through */ @@ -691,15 +661,15 @@ struct dc_sink_init_data { struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params); /******************************************************************************* - * Cursor interfaces - To manages the cursor within a target + * Cursor interfaces - To manages the cursor within a stream ******************************************************************************/ /* TODO: Deprecated once we switch to dc_set_cursor_position */ -bool dc_target_set_cursor_attributes( - struct dc_target *dc_target, +bool dc_stream_set_cursor_attributes( + const struct dc_stream *stream, const struct dc_cursor_attributes *attributes); -bool dc_target_set_cursor_position( - struct dc_target *dc_target, +bool dc_stream_set_cursor_position( + const struct dc_stream *stream, const struct dc_cursor_position *position); /* Newer interfaces */ @@ -708,36 +678,6 @@ struct dc_cursor { struct dc_cursor_attributes attributes; }; -/* - * Create a new cursor with default values for a given target. - */ -struct dc_cursor *dc_create_cursor_for_target( - const struct dc *dc, - struct dc_target *dc_target); - -/** - * Commit cursor attribute changes such as pixel format and dimensions and - * surface address. - * - * After this call: - * Cursor address and format is programmed to the new values. - * Cursor position is unmodified. - */ -bool dc_commit_cursor( - const struct dc *dc, - struct dc_cursor *cursor); - -/* - * Optimized cursor position update - * - * After this call: - * Cursor position will be programmed as well as enable/disable bit. - */ -bool dc_set_cursor_position( - const struct dc *dc, - struct dc_cursor *cursor, - struct dc_cursor_position *pos); - /******************************************************************************* * Interrupt interfaces ******************************************************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index ae9fcca121e6..242dd7b3b6b1 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -34,7 +34,6 @@ /* forward declarations */ struct dc_surface; -struct dc_target; struct dc_stream; struct dc_link; struct dc_sink; diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 082f1f053a3a..ae0e7eac2c9d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -741,53 +741,48 @@ static enum dc_status validate_mapped_resource( struct validate_context *context) { enum dc_status status = DC_OK; - uint8_t i, j, k; + uint8_t i, j; - for (i = 0; i < context->target_count; i++) { - struct core_target *target = context->targets[i]; + for (i = 0; i < context->stream_count; i++) { + struct core_stream *stream = context->streams[i]; + struct core_link *link = stream->sink->link; - for (j = 0; j < target->public.stream_count; j++) { - struct core_stream *stream = - DC_STREAM_TO_CORE(target->public.streams[j]); - struct core_link *link = stream->sink->link; - - if (resource_is_stream_unchanged(dc->current_context, stream)) - continue; + if (resource_is_stream_unchanged(dc->current_context, stream)) + continue; - for (k = 0; k < MAX_PIPES; k++) { - struct pipe_ctx *pipe_ctx = - &context->res_ctx.pipe_ctx[k]; + for (j = 0; j < MAX_PIPES; j++) { + struct pipe_ctx *pipe_ctx = + &context->res_ctx.pipe_ctx[j]; - if (context->res_ctx.pipe_ctx[k].stream != stream) - continue; + if (context->res_ctx.pipe_ctx[j].stream != stream) + continue; - if (!pipe_ctx->tg->funcs->validate_timing( - pipe_ctx->tg, &stream->public.timing)) - return DC_FAIL_CONTROLLER_VALIDATE; + if (!pipe_ctx->tg->funcs->validate_timing( + pipe_ctx->tg, &stream->public.timing)) + return DC_FAIL_CONTROLLER_VALIDATE; - status = dce110_resource_build_pipe_hw_param(pipe_ctx); + status = dce110_resource_build_pipe_hw_param(pipe_ctx); - if (status != DC_OK) - return status; + if (status != DC_OK) + return status; - if (!link->link_enc->funcs->validate_output_with_stream( - link->link_enc, - pipe_ctx)) - return DC_FAIL_ENC_VALIDATE; + if (!link->link_enc->funcs->validate_output_with_stream( + link->link_enc, + pipe_ctx)) + return DC_FAIL_ENC_VALIDATE; - /* TODO: validate audio ASIC caps, encoder */ - status = dc_link_validate_mode_timing(stream, - link, - &stream->public.timing); + /* TODO: validate audio ASIC caps, encoder */ + status = dc_link_validate_mode_timing(stream, + link, + &stream->public.timing); - if (status != DC_OK) - return status; + if (status != DC_OK) + return status; - resource_build_info_frame(pipe_ctx); + resource_build_info_frame(pipe_ctx); - /* do not need to validate non root pipes */ - break; - } + /* do not need to validate non root pipes */ + break; } } @@ -818,9 +813,9 @@ static bool dce100_validate_surface_sets( return false; if (set[i].surfaces[0]->clip_rect.width - != set[i].target->streams[0]->src.width + != set[i].stream->src.width || set[i].surfaces[0]->clip_rect.height - != set[i].target->streams[0]->src.height) + != set[i].stream->src.height) return false; if (set[i].surfaces[0]->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) @@ -846,9 +841,9 @@ enum dc_status dce100_validate_with_context( context->res_ctx.pool = dc->res_pool; for (i = 0; i < set_count; i++) { - context->targets[i] = DC_TARGET_TO_CORE(set[i].target); - dc_target_retain(&context->targets[i]->public); - context->target_count++; + context->streams[i] = DC_STREAM_TO_CORE(set[i].stream); + dc_stream_retain(&context->streams[i]->public); + context->stream_count++; } result = resource_map_pool_resources(dc, context); @@ -858,7 +853,7 @@ enum dc_status dce100_validate_with_context( if (!resource_validate_attach_surfaces( set, set_count, dc->current_context, context)) { - DC_ERROR("Failed to attach surface to target!\n"); + DC_ERROR("Failed to attach surface to stream!\n"); return DC_FAIL_ATTACH_SURFACES; } @@ -876,16 +871,16 @@ enum dc_status dce100_validate_with_context( enum dc_status dce100_validate_guaranteed( const struct core_dc *dc, - const struct dc_target *dc_target, + const struct dc_stream *dc_stream, struct validate_context *context) { enum dc_status result = DC_ERROR_UNEXPECTED; context->res_ctx.pool = dc->res_pool; - context->targets[0] = DC_TARGET_TO_CORE(dc_target); - dc_target_retain(&context->targets[0]->public); - context->target_count++; + context->streams[0] = DC_STREAM_TO_CORE(dc_stream); + dc_stream_retain(&context->streams[0]->public); + context->stream_count++; result = resource_map_pool_resources(dc, context); @@ -896,8 +891,8 @@ enum dc_status dce100_validate_guaranteed( result = validate_mapped_resource(dc, context); if (result == DC_OK) { - validate_guaranteed_copy_target( - context, dc->public.caps.max_targets); + validate_guaranteed_copy_streams( + context, dc->public.caps.max_streams); result = resource_build_scaling_params_for_context(dc, context); } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 751dbb88c265..415b12accd2c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -753,7 +753,7 @@ static enum dc_status apply_single_controller_ctx_to_hw( stream->public.timing.h_total, stream->public.timing.v_total, stream->public.timing.pix_clk_khz, - context->target_count); + context->stream_count); return DC_OK; } @@ -1055,7 +1055,7 @@ static void reset_single_pipe_hw_ctx( } pipe_ctx->tg->funcs->disable_crtc(pipe_ctx->tg); pipe_ctx->mi->funcs->free_mem_input( - pipe_ctx->mi, context->target_count); + pipe_ctx->mi, context->stream_count); resource_unreference_clock_source( &context->res_ctx, &pipe_ctx->clock_source); @@ -1254,7 +1254,7 @@ enum dc_status dce110_apply_ctx_to_hw( dc->hwss.reset_hw_ctx_wrap(dc, context); /* Skip applying if no targets */ - if (context->target_count <= 0) + if (context->stream_count <= 0) return DC_OK; if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { @@ -1761,7 +1761,7 @@ static void dce110_power_on_pipe_if_needed( pipe_ctx->stream->public.timing.h_total, pipe_ctx->stream->public.timing.v_total, pipe_ctx->stream->public.timing.pix_clk_khz, - context->target_count); + context->stream_count); /* TODO unhardcode*/ color_space_to_black_color(dc, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 968ee99003fc..cfbb4ef21f8b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -817,58 +817,53 @@ static enum dc_status validate_mapped_resource( struct validate_context *context) { enum dc_status status = DC_OK; - uint8_t i, j, k; + uint8_t i, j; - for (i = 0; i < context->target_count; i++) { - struct core_target *target = context->targets[i]; + for (i = 0; i < context->stream_count; i++) { + struct core_stream *stream = context->streams[i]; + struct core_link *link = stream->sink->link; - for (j = 0; j < target->public.stream_count; j++) { - struct core_stream *stream = - DC_STREAM_TO_CORE(target->public.streams[j]); - struct core_link *link = stream->sink->link; - - if (resource_is_stream_unchanged(dc->current_context, stream)) - continue; + if (resource_is_stream_unchanged(dc->current_context, stream)) + continue; - for (k = 0; k < MAX_PIPES; k++) { - struct pipe_ctx *pipe_ctx = - &context->res_ctx.pipe_ctx[k]; + for (j = 0; j < MAX_PIPES; j++) { + struct pipe_ctx *pipe_ctx = + &context->res_ctx.pipe_ctx[j]; - if (context->res_ctx.pipe_ctx[k].stream != stream) - continue; + if (context->res_ctx.pipe_ctx[j].stream != stream) + continue; - if (!is_surface_pixel_format_supported(pipe_ctx, - context->res_ctx.pool->underlay_pipe_index)) - return DC_SURFACE_PIXEL_FORMAT_UNSUPPORTED; + if (!is_surface_pixel_format_supported(pipe_ctx, + context->res_ctx.pool->underlay_pipe_index)) + return DC_SURFACE_PIXEL_FORMAT_UNSUPPORTED; - if (!pipe_ctx->tg->funcs->validate_timing( - pipe_ctx->tg, &stream->public.timing)) - return DC_FAIL_CONTROLLER_VALIDATE; + if (!pipe_ctx->tg->funcs->validate_timing( + pipe_ctx->tg, &stream->public.timing)) + return DC_FAIL_CONTROLLER_VALIDATE; - status = dce110_resource_build_pipe_hw_param(pipe_ctx); + status = dce110_resource_build_pipe_hw_param(pipe_ctx); - if (status != DC_OK) - return status; + if (status != DC_OK) + return status; - if (!link->link_enc->funcs->validate_output_with_stream( - link->link_enc, - pipe_ctx)) - return DC_FAIL_ENC_VALIDATE; + if (!link->link_enc->funcs->validate_output_with_stream( + link->link_enc, + pipe_ctx)) + return DC_FAIL_ENC_VALIDATE; - /* TODO: validate audio ASIC caps, encoder */ + /* TODO: validate audio ASIC caps, encoder */ - status = dc_link_validate_mode_timing(stream, - link, - &stream->public.timing); + status = dc_link_validate_mode_timing(stream, + link, + &stream->public.timing); - if (status != DC_OK) - return status; + if (status != DC_OK) + return status; - resource_build_info_frame(pipe_ctx); + resource_build_info_frame(pipe_ctx); - /* do not need to validate non root pipes */ - break; - } + /* do not need to validate non root pipes */ + break; } } @@ -901,9 +896,9 @@ enum dc_status dce110_validate_bandwidth( dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_VALIDATION, "%s: %dx%d@%d Bandwidth validation failed!\n", __func__, - context->targets[0]->public.streams[0]->timing.h_addressable, - context->targets[0]->public.streams[0]->timing.v_addressable, - context->targets[0]->public.streams[0]->timing.pix_clk_khz); + context->streams[0]->public.timing.h_addressable, + context->streams[0]->public.timing.v_addressable, + context->streams[0]->public.timing.pix_clk_khz); if (memcmp(&dc->current_context->bw_results, &context->bw_results, sizeof(context->bw_results))) { @@ -972,9 +967,9 @@ static bool dce110_validate_surface_sets( return false; if (set[i].surfaces[0]->src_rect.width - != set[i].target->streams[0]->src.width + != set[i].stream->src.width || set[i].surfaces[0]->src_rect.height - != set[i].target->streams[0]->src.height) + != set[i].stream->src.height) return false; if (set[i].surfaces[0]->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) @@ -988,7 +983,7 @@ static bool dce110_validate_surface_sets( || set[i].surfaces[1]->src_rect.height > 1080) return false; - if (set[i].target->streams[0]->timing.pixel_encoding != PIXEL_ENCODING_RGB) + if (set[i].stream->timing.pixel_encoding != PIXEL_ENCODING_RGB) return false; } } @@ -1012,9 +1007,9 @@ enum dc_status dce110_validate_with_context( context->res_ctx.pool = dc->res_pool; for (i = 0; i < set_count; i++) { - context->targets[i] = DC_TARGET_TO_CORE(set[i].target); - dc_target_retain(&context->targets[i]->public); - context->target_count++; + context->streams[i] = DC_STREAM_TO_CORE(set[i].stream); + dc_stream_retain(&context->streams[i]->public); + context->stream_count++; } result = resource_map_pool_resources(dc, context); @@ -1024,7 +1019,7 @@ enum dc_status dce110_validate_with_context( if (!resource_validate_attach_surfaces( set, set_count, dc->current_context, context)) { - DC_ERROR("Failed to attach surface to target!\n"); + DC_ERROR("Failed to attach surface to stream!\n"); return DC_FAIL_ATTACH_SURFACES; } @@ -1042,16 +1037,16 @@ enum dc_status dce110_validate_with_context( enum dc_status dce110_validate_guaranteed( const struct core_dc *dc, - const struct dc_target *dc_target, + const struct dc_stream *dc_stream, struct validate_context *context) { enum dc_status result = DC_ERROR_UNEXPECTED; context->res_ctx.pool = dc->res_pool; - context->targets[0] = DC_TARGET_TO_CORE(dc_target); - dc_target_retain(&context->targets[0]->public); - context->target_count++; + context->streams[0] = DC_STREAM_TO_CORE(dc_stream); + dc_stream_retain(&context->streams[0]->public); + context->stream_count++; result = resource_map_pool_resources(dc, context); @@ -1062,8 +1057,8 @@ enum dc_status dce110_validate_guaranteed( result = validate_mapped_resource(dc, context); if (result == DC_OK) { - validate_guaranteed_copy_target( - context, dc->public.caps.max_targets); + validate_guaranteed_copy_streams( + context, dc->public.caps.max_streams); result = resource_build_scaling_params_for_context(dc, context); } diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 7fca2eb188cf..64fae91dd5eb 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -779,54 +779,49 @@ static enum dc_status validate_mapped_resource( struct validate_context *context) { enum dc_status status = DC_OK; - uint8_t i, j, k; + uint8_t i, j; - for (i = 0; i < context->target_count; i++) { - struct core_target *target = context->targets[i]; + for (i = 0; i < context->stream_count; i++) { + struct core_stream *stream = context->streams[i]; + struct core_link *link = stream->sink->link; - for (j = 0; j < target->public.stream_count; j++) { - struct core_stream *stream = - DC_STREAM_TO_CORE(target->public.streams[j]); - struct core_link *link = stream->sink->link; - - if (resource_is_stream_unchanged(dc->current_context, stream)) - continue; + if (resource_is_stream_unchanged(dc->current_context, stream)) + continue; - for (k = 0; k < MAX_PIPES; k++) { - struct pipe_ctx *pipe_ctx = - &context->res_ctx.pipe_ctx[k]; + for (j = 0; j < MAX_PIPES; j++) { + struct pipe_ctx *pipe_ctx = + &context->res_ctx.pipe_ctx[j]; - if (context->res_ctx.pipe_ctx[k].stream != stream) - continue; + if (context->res_ctx.pipe_ctx[j].stream != stream) + continue; - if (!pipe_ctx->tg->funcs->validate_timing( - pipe_ctx->tg, &stream->public.timing)) - return DC_FAIL_CONTROLLER_VALIDATE; + if (!pipe_ctx->tg->funcs->validate_timing( + pipe_ctx->tg, &stream->public.timing)) + return DC_FAIL_CONTROLLER_VALIDATE; - status = dce110_resource_build_pipe_hw_param(pipe_ctx); + status = dce110_resource_build_pipe_hw_param(pipe_ctx); - if (status != DC_OK) - return status; + if (status != DC_OK) + return status; - if (!link->link_enc->funcs->validate_output_with_stream( - link->link_enc, - pipe_ctx)) - return DC_FAIL_ENC_VALIDATE; + if (!link->link_enc->funcs->validate_output_with_stream( + link->link_enc, + pipe_ctx)) + return DC_FAIL_ENC_VALIDATE; - /* TODO: validate audio ASIC caps, encoder */ + /* TODO: validate audio ASIC caps, encoder */ - status = dc_link_validate_mode_timing(stream, - link, - &stream->public.timing); + status = dc_link_validate_mode_timing(stream, + link, + &stream->public.timing); - if (status != DC_OK) - return status; + if (status != DC_OK) + return status; - resource_build_info_frame(pipe_ctx); + resource_build_info_frame(pipe_ctx); - /* do not need to validate non root pipes */ - break; - } + /* do not need to validate non root pipes */ + break; } } @@ -917,45 +912,40 @@ enum dc_status resource_map_phy_clock_resources( const struct core_dc *dc, struct validate_context *context) { - uint8_t i, j, k; + uint8_t i, j; /* acquire new resources */ - for (i = 0; i < context->target_count; i++) { - struct core_target *target = context->targets[i]; + for (i = 0; i < context->stream_count; i++) { + struct core_stream *stream = context->streams[i]; - for (j = 0; j < target->public.stream_count; j++) { - struct core_stream *stream = - DC_STREAM_TO_CORE(target->public.streams[j]); - - if (resource_is_stream_unchanged(dc->current_context, stream)) - continue; + if (resource_is_stream_unchanged(dc->current_context, stream)) + continue; - for (k = 0; k < MAX_PIPES; k++) { - struct pipe_ctx *pipe_ctx = - &context->res_ctx.pipe_ctx[k]; + for (j = 0; j < MAX_PIPES; j++) { + struct pipe_ctx *pipe_ctx = + &context->res_ctx.pipe_ctx[j]; - if (context->res_ctx.pipe_ctx[k].stream != stream) - continue; + if (context->res_ctx.pipe_ctx[j].stream != stream) + continue; - if (dc_is_dp_signal(pipe_ctx->stream->signal) - || pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL) - pipe_ctx->clock_source = - context->res_ctx.pool->dp_clock_source; - else - pipe_ctx->clock_source = - find_matching_pll(&context->res_ctx, - stream); + if (dc_is_dp_signal(pipe_ctx->stream->signal) + || pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL) + pipe_ctx->clock_source = + context->res_ctx.pool->dp_clock_source; + else + pipe_ctx->clock_source = + find_matching_pll(&context->res_ctx, + stream); - if (pipe_ctx->clock_source == NULL) - return DC_NO_CLOCK_SOURCE_RESOURCE; + if (pipe_ctx->clock_source == NULL) + return DC_NO_CLOCK_SOURCE_RESOURCE; - resource_reference_clock_source( - &context->res_ctx, - pipe_ctx->clock_source); + resource_reference_clock_source( + &context->res_ctx, + pipe_ctx->clock_source); - /* only one cs per stream regardless of mpo */ - break; - } + /* only one cs per stream regardless of mpo */ + break; } } @@ -976,9 +966,9 @@ static bool dce112_validate_surface_sets( return false; if (set[i].surfaces[0]->clip_rect.width - != set[i].target->streams[0]->src.width + != set[i].stream->src.width || set[i].surfaces[0]->clip_rect.height - != set[i].target->streams[0]->src.height) + != set[i].stream->src.height) return false; if (set[i].surfaces[0]->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) @@ -1004,9 +994,9 @@ enum dc_status dce112_validate_with_context( context->res_ctx.pool = dc->res_pool; for (i = 0; i < set_count; i++) { - context->targets[i] = DC_TARGET_TO_CORE(set[i].target); - dc_target_retain(&context->targets[i]->public); - context->target_count++; + context->streams[i] = DC_STREAM_TO_CORE(set[i].stream); + dc_stream_retain(&context->streams[i]->public); + context->stream_count++; } result = resource_map_pool_resources(dc, context); @@ -1016,7 +1006,7 @@ enum dc_status dce112_validate_with_context( if (!resource_validate_attach_surfaces( set, set_count, dc->current_context, context)) { - DC_ERROR("Failed to attach surface to target!\n"); + DC_ERROR("Failed to attach surface to stream!\n"); return DC_FAIL_ATTACH_SURFACES; } @@ -1034,16 +1024,16 @@ enum dc_status dce112_validate_with_context( enum dc_status dce112_validate_guaranteed( const struct core_dc *dc, - const struct dc_target *dc_target, + const struct dc_stream *dc_stream, struct validate_context *context) { enum dc_status result = DC_ERROR_UNEXPECTED; context->res_ctx.pool = dc->res_pool; - context->targets[0] = DC_TARGET_TO_CORE(dc_target); - dc_target_retain(&context->targets[0]->public); - context->target_count++; + context->streams[0] = DC_STREAM_TO_CORE(dc_stream); + dc_stream_retain(&context->streams[0]->public); + context->stream_count++; result = resource_map_pool_resources(dc, context); @@ -1054,8 +1044,8 @@ enum dc_status dce112_validate_guaranteed( result = validate_mapped_resource(dc, context); if (result == DC_OK) { - validate_guaranteed_copy_target( - context, dc->public.caps.max_targets); + validate_guaranteed_copy_streams( + context, dc->public.caps.max_streams); result = resource_build_scaling_params_for_context(dc, context); } diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h index f21eb57857d4..faa8c45a3544 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h @@ -43,7 +43,7 @@ enum dc_status dce112_validate_with_context( enum dc_status dce112_validate_guaranteed( const struct core_dc *dc, - const struct dc_target *dc_target, + const struct dc_stream *dc_stream, struct validate_context *context); enum dc_status dce112_validate_bandwidth( diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index e2bfa7efce1c..bee3a41ffe9f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -731,54 +731,49 @@ static enum dc_status validate_mapped_resource( struct validate_context *context) { enum dc_status status = DC_OK; - uint8_t i, j, k; + uint8_t i, j; - for (i = 0; i < context->target_count; i++) { - struct core_target *target = context->targets[i]; + for (i = 0; i < context->stream_count; i++) { + struct core_stream *stream = context->streams[i]; + struct core_link *link = stream->sink->link; - for (j = 0; j < target->public.stream_count; j++) { - struct core_stream *stream = - DC_STREAM_TO_CORE(target->public.streams[j]); - struct core_link *link = stream->sink->link; - - if (resource_is_stream_unchanged(dc->current_context, stream)) - continue; + if (resource_is_stream_unchanged(dc->current_context, stream)) + continue; - for (k = 0; k < MAX_PIPES; k++) { - struct pipe_ctx *pipe_ctx = - &context->res_ctx.pipe_ctx[k]; + for (j = 0; j < MAX_PIPES; j++) { + struct pipe_ctx *pipe_ctx = + &context->res_ctx.pipe_ctx[j]; - if (context->res_ctx.pipe_ctx[k].stream != stream) - continue; + if (context->res_ctx.pipe_ctx[j].stream != stream) + continue; - if (!pipe_ctx->tg->funcs->validate_timing( - pipe_ctx->tg, &stream->public.timing)) - return DC_FAIL_CONTROLLER_VALIDATE; + if (!pipe_ctx->tg->funcs->validate_timing( + pipe_ctx->tg, &stream->public.timing)) + return DC_FAIL_CONTROLLER_VALIDATE; - status = dce110_resource_build_pipe_hw_param(pipe_ctx); + status = dce110_resource_build_pipe_hw_param(pipe_ctx); - if (status != DC_OK) - return status; + if (status != DC_OK) + return status; - if (!link->link_enc->funcs->validate_output_with_stream( - link->link_enc, - pipe_ctx)) - return DC_FAIL_ENC_VALIDATE; + if (!link->link_enc->funcs->validate_output_with_stream( + link->link_enc, + pipe_ctx)) + return DC_FAIL_ENC_VALIDATE; - /* TODO: validate audio ASIC caps, encoder */ + /* TODO: validate audio ASIC caps, encoder */ - status = dc_link_validate_mode_timing(stream, - link, - &stream->public.timing); + status = dc_link_validate_mode_timing(stream, + link, + &stream->public.timing); - if (status != DC_OK) - return status; + if (status != DC_OK) + return status; - resource_build_info_frame(pipe_ctx); + resource_build_info_frame(pipe_ctx); - /* do not need to validate non root pipes */ - break; - } + /* do not need to validate non root pipes */ + break; } } @@ -810,9 +805,9 @@ static bool dce80_validate_surface_sets( return false; if (set[i].surfaces[0]->clip_rect.width - != set[i].target->streams[0]->src.width + != set[i].stream->src.width || set[i].surfaces[0]->clip_rect.height - != set[i].target->streams[0]->src.height) + != set[i].stream->src.height) return false; if (set[i].surfaces[0]->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) @@ -838,9 +833,9 @@ enum dc_status dce80_validate_with_context( context->res_ctx.pool = dc->res_pool; for (i = 0; i < set_count; i++) { - context->targets[i] = DC_TARGET_TO_CORE(set[i].target); - dc_target_retain(&context->targets[i]->public); - context->target_count++; + context->streams[i] = DC_STREAM_TO_CORE(set[i].stream); + dc_stream_retain(&context->streams[i]->public); + context->stream_count++; } result = resource_map_pool_resources(dc, context); @@ -850,7 +845,7 @@ enum dc_status dce80_validate_with_context( if (!resource_validate_attach_surfaces( set, set_count, dc->current_context, context)) { - DC_ERROR("Failed to attach surface to target!\n"); + DC_ERROR("Failed to attach surface to stream!\n"); return DC_FAIL_ATTACH_SURFACES; } @@ -868,16 +863,16 @@ enum dc_status dce80_validate_with_context( enum dc_status dce80_validate_guaranteed( const struct core_dc *dc, - const struct dc_target *dc_target, + const struct dc_stream *dc_stream, struct validate_context *context) { enum dc_status result = DC_ERROR_UNEXPECTED; context->res_ctx.pool = dc->res_pool; - context->targets[0] = DC_TARGET_TO_CORE(dc_target); - dc_target_retain(&context->targets[0]->public); - context->target_count++; + context->streams[0] = DC_STREAM_TO_CORE(dc_stream); + dc_stream_retain(&context->streams[0]->public); + context->stream_count++; result = resource_map_pool_resources(dc, context); @@ -888,8 +883,8 @@ enum dc_status dce80_validate_guaranteed( result = validate_mapped_resource(dc, context); if (result == DC_OK) { - validate_guaranteed_copy_target( - context, dc->public.caps.max_targets); + validate_guaranteed_copy_streams( + context, dc->public.caps.max_streams); result = resource_build_scaling_params_for_context(dc, context); } diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_dc.h b/drivers/gpu/drm/amd/display/dc/inc/core_dc.h index b5a5207a4df0..7a6444dc2957 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_dc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_dc.h @@ -21,7 +21,6 @@ struct core_dc { uint8_t link_count; struct core_link *links[MAX_PIPES * 2]; - /* TODO: determine max number of targets*/ struct validate_context *current_context; struct validate_context *temp_flip_context; struct validate_context *scratch_val_ctx; diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index c2d35c2c28bf..66bfcdb57c4c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -32,21 +32,10 @@ #include "dc_bios_types.h" struct core_stream; -/********* core_target *************/ - -#define CONST_DC_TARGET_TO_CORE(dc_target) \ - container_of(dc_target, const struct core_target, public) -#define DC_TARGET_TO_CORE(dc_target) \ - container_of(dc_target, struct core_target, public) #define MAX_PIPES 6 #define MAX_CLOCK_SOURCES 7 -struct core_target { - struct dc_target public; - - struct dc_context *ctx; -}; /********* core_surface **********/ #define DC_SURFACE_TO_CORE(dc_surface) \ @@ -215,7 +204,7 @@ struct resource_funcs { enum dc_status (*validate_guaranteed)( const struct core_dc *dc, - const struct dc_target *dc_target, + const struct dc_stream *stream, struct validate_context *context); enum dc_status (*validate_bandwidth)( @@ -312,9 +301,9 @@ struct resource_context { }; struct validate_context { - struct core_target *targets[MAX_PIPES]; - struct dc_target_status target_status[MAX_PIPES]; - uint8_t target_count; + struct core_stream *streams[MAX_PIPES]; + struct dc_stream_status stream_status[MAX_PIPES]; + uint8_t stream_count; struct resource_context res_ctx; diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index adf297ec33b6..d96c64bb0a70 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -118,25 +118,26 @@ struct pipe_ctx *resource_get_head_pipe_for_stream( bool resource_attach_surfaces_to_context( const struct dc_surface *const *surfaces, int surface_count, - const struct dc_target *dc_target, + const struct dc_stream *dc_stream, struct validate_context *context); struct pipe_ctx *find_idle_secondary_pipe(struct resource_context *res_ctx); bool resource_is_stream_unchanged( - const struct validate_context *old_context, struct core_stream *stream); + const struct validate_context *old_context, const struct core_stream *stream); + +bool is_stream_unchanged( + const struct core_stream *old_stream, const struct core_stream *stream); -bool is_target_unchanged( - const struct core_target *old_target, const struct core_target *target); bool resource_validate_attach_surfaces( const struct dc_validation_set set[], int set_count, const struct validate_context *old_context, struct validate_context *context); -void validate_guaranteed_copy_target( +void validate_guaranteed_copy_streams( struct validate_context *context, - int max_targets); + int max_streams); void resource_validate_ctx_update_pointer_after_copy( const struct validate_context *src_ctx, -- cgit From 457b74cb3773a1950e49c2d4826d1b295c59bdf1 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Wed, 11 Jan 2017 15:52:06 -0500 Subject: drm/amd/display: Null check clock source. Signed-off-by: Yongqiang Sun Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 55d96656e54b..b0ac94d673c4 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -74,7 +74,8 @@ void dp_enable_link_phy( if (pipes[i].stream != NULL && pipes[i].stream->sink != NULL && pipes[i].stream->sink->link == link) { - if (pipes[i].clock_source->id != CLOCK_SOURCE_ID_DP_DTO) { + if (pipes[i].clock_source != NULL && + pipes[i].clock_source->id != CLOCK_SOURCE_ID_DP_DTO) { pipes[i].clock_source = dp_cs; pipes[i].pix_clk_params.requested_pix_clk = pipes[i].stream->public.timing.pix_clk_khz; -- cgit From fcd2f4bf8bbe73ac860d1be275a22a54a8d8d385 Mon Sep 17 00:00:00 2001 From: Amy Zhang Date: Thu, 5 Jan 2017 17:12:20 -0500 Subject: drm/amd/display: Output Transfer Function Regamma Refactor - Create translation function to translate logical format to hw format - Refactor to use transfer function in dc instead of input gamma Signed-off-by: Amy Zhang Acked-by: Harry Wentland Reviewed-by: Anthony Koo Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c | 9 + drivers/gpu/drm/amd/display/dc/calcs/Makefile | 2 +- drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c | 1481 -------------------- drivers/gpu/drm/amd/display/dc/core/dc.c | 10 +- drivers/gpu/drm/amd/display/dc/dc.h | 11 +- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 440 +++++- drivers/gpu/drm/amd/display/dc/inc/gamma_calcs.h | 20 - drivers/gpu/drm/amd/display/dc/inc/hw/opp.h | 2 - drivers/gpu/drm/amd/display/include/fixed31_32.h | 8 + 9 files changed, 466 insertions(+), 1517 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c delete mode 100644 drivers/gpu/drm/amd/display/dc/inc/gamma_calcs.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c b/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c index 5a6e46843502..546ed67c6f83 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c +++ b/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c @@ -246,6 +246,15 @@ struct fixed31_32 dal_fixed31_32_add( return res; } +struct fixed31_32 dal_fixed31_32_add_int( + struct fixed31_32 arg1, + int32_t arg2) +{ + return dal_fixed31_32_add( + arg1, + dal_fixed31_32_from_int(arg2)); +} + struct fixed31_32 dal_fixed31_32_sub_int( struct fixed31_32 arg1, int32_t arg2) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/Makefile b/drivers/gpu/drm/amd/display/dc/calcs/Makefile index 4001933e7808..4bb08aea6a03 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/Makefile +++ b/drivers/gpu/drm/amd/display/dc/calcs/Makefile @@ -3,7 +3,7 @@ # It calculates Bandwidth and Watermarks values for HW programming # -BW_CALCS = bandwidth_calcs.o bw_fixed.o gamma_calcs.o +BW_CALCS = bandwidth_calcs.o bw_fixed.o AMD_DAL_BW_CALCS = $(addprefix $(AMDDALPATH)/dc/calcs/,$(BW_CALCS)) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c deleted file mode 100644 index fd300db833c7..000000000000 --- a/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c +++ /dev/null @@ -1,1481 +0,0 @@ -/* - * Copyright 2015 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" -#include "gamma_calcs.h" - -struct curve_config { - uint32_t offset; - int8_t segments[16]; - int8_t begin; -}; - -static bool build_custom_float( - struct fixed31_32 value, - const struct custom_float_format *format, - bool *negative, - uint32_t *mantissa, - uint32_t *exponenta) -{ - uint32_t exp_offset = (1 << (format->exponenta_bits - 1)) - 1; - - const struct fixed31_32 mantissa_constant_plus_max_fraction = - dal_fixed31_32_from_fraction( - (1LL << (format->mantissa_bits + 1)) - 1, - 1LL << format->mantissa_bits); - - struct fixed31_32 mantiss; - - if (dal_fixed31_32_eq( - value, - dal_fixed31_32_zero)) { - *negative = false; - *mantissa = 0; - *exponenta = 0; - return true; - } - - if (dal_fixed31_32_lt( - value, - dal_fixed31_32_zero)) { - *negative = format->sign; - value = dal_fixed31_32_neg(value); - } else { - *negative = false; - } - - if (dal_fixed31_32_lt( - value, - dal_fixed31_32_one)) { - uint32_t i = 1; - - do { - value = dal_fixed31_32_shl(value, 1); - ++i; - } while (dal_fixed31_32_lt( - value, - dal_fixed31_32_one)); - - --i; - - if (exp_offset <= i) { - *mantissa = 0; - *exponenta = 0; - return true; - } - - *exponenta = exp_offset - i; - } else if (dal_fixed31_32_le( - mantissa_constant_plus_max_fraction, - value)) { - uint32_t i = 1; - - do { - value = dal_fixed31_32_shr(value, 1); - ++i; - } while (dal_fixed31_32_lt( - mantissa_constant_plus_max_fraction, - value)); - - *exponenta = exp_offset + i - 1; - } else { - *exponenta = exp_offset; - } - - mantiss = dal_fixed31_32_sub( - value, - dal_fixed31_32_one); - - if (dal_fixed31_32_lt( - mantiss, - dal_fixed31_32_zero) || - dal_fixed31_32_lt( - dal_fixed31_32_one, - mantiss)) - mantiss = dal_fixed31_32_zero; - else - mantiss = dal_fixed31_32_shl( - mantiss, - format->mantissa_bits); - - *mantissa = dal_fixed31_32_floor(mantiss); - - return true; -} - -static bool setup_custom_float( - const struct custom_float_format *format, - bool negative, - uint32_t mantissa, - uint32_t exponenta, - uint32_t *result) -{ - uint32_t i = 0; - uint32_t j = 0; - - uint32_t value = 0; - - /* verification code: - * once calculation is ok we can remove it - */ - - const uint32_t mantissa_mask = - (1 << (format->mantissa_bits + 1)) - 1; - - const uint32_t exponenta_mask = - (1 << (format->exponenta_bits + 1)) - 1; - - if (mantissa & ~mantissa_mask) { - BREAK_TO_DEBUGGER(); - mantissa = mantissa_mask; - } - - if (exponenta & ~exponenta_mask) { - BREAK_TO_DEBUGGER(); - exponenta = exponenta_mask; - } - - /* end of verification code */ - - while (i < format->mantissa_bits) { - uint32_t mask = 1 << i; - - if (mantissa & mask) - value |= mask; - - ++i; - } - - while (j < format->exponenta_bits) { - uint32_t mask = 1 << j; - - if (exponenta & mask) - value |= mask << i; - - ++j; - } - - if (negative && format->sign) - value |= 1 << (i + j); - - *result = value; - - return true; -} - -static bool build_hw_curve_configuration( - const struct curve_config *curve_config, - struct gamma_curve *gamma_curve, - struct curve_points *curve_points, - struct hw_x_point *points, - uint32_t *number_of_points) -{ - const int8_t max_regions_number = ARRAY_SIZE(curve_config->segments); - - int8_t i; - - uint8_t segments_calculation[8] = { 0 }; - - struct fixed31_32 region1 = dal_fixed31_32_zero; - struct fixed31_32 region2; - struct fixed31_32 increment; - - uint32_t index = 0; - uint32_t segments = 0; - uint32_t max_number; - - int8_t num_regions = 0; - - bool result = false; - - if (!number_of_points) { - BREAK_TO_DEBUGGER(); - return false; - } - - max_number = *number_of_points; - - i = 0; - - while (i != max_regions_number) { - gamma_curve[i].offset = 0; - gamma_curve[i].segments_num = 0; - - ++i; - } - - i = 0; - - while (i != max_regions_number) { - /* number should go in uninterruptible sequence */ - if (curve_config->segments[i] == -1) - break; - - ASSERT(curve_config->segments[i] >= 0); - - segments += (1 << curve_config->segments[i]); - ++num_regions; - - ++i; - } - - if (segments > max_number) { - BREAK_TO_DEBUGGER(); - } else { - int32_t divisor; - uint32_t offset = 0; - int8_t begin = curve_config->begin; - int32_t region_number = 0; - - i = begin; - - while ((index < max_number) && - (region_number < max_regions_number) && - (i < (begin + num_regions))) { - int32_t j = 0; - - segments = curve_config->segments[region_number]; - divisor = 1 << segments; - - if (segments == -1) { - if (i > 0) { - region1 = dal_fixed31_32_shl( - dal_fixed31_32_one, - i - 1); - region2 = dal_fixed31_32_shl( - dal_fixed31_32_one, - i); - } else { - region1 = dal_fixed31_32_shr( - dal_fixed31_32_one, - -(i - 1)); - region2 = dal_fixed31_32_shr( - dal_fixed31_32_one, - -i); - } - - break; - } - - if (i > -1) { - region1 = dal_fixed31_32_shl( - dal_fixed31_32_one, - i); - region2 = dal_fixed31_32_shl( - dal_fixed31_32_one, - i + 1); - } else { - region1 = dal_fixed31_32_shr( - dal_fixed31_32_one, - -i); - region2 = dal_fixed31_32_shr( - dal_fixed31_32_one, - -(i + 1)); - } - - gamma_curve[region_number].offset = offset; - gamma_curve[region_number].segments_num = segments; - - offset += divisor; - - ++segments_calculation[segments]; - - increment = dal_fixed31_32_div_int( - dal_fixed31_32_sub( - region2, - region1), - divisor); - - points[index].x = region1; - points[index].adjusted_x = region1; - - ++index; - ++region_number; - - while ((index < max_number) && (j < divisor - 1)) { - region1 = dal_fixed31_32_add( - region1, - increment); - - points[index].x = region1; - points[index].adjusted_x = region1; - - ++index; - ++j; - } - - ++i; - } - - points[index].x = region1; - points[index].adjusted_x = region1; - - *number_of_points = index; - - result = true; - } - - curve_points[0].x = points[0].adjusted_x; - curve_points[0].offset = dal_fixed31_32_zero; - - curve_points[1].x = points[index - 1].adjusted_x; - curve_points[1].offset = dal_fixed31_32_zero; - - curve_points[2].x = points[index].adjusted_x; - curve_points[2].offset = dal_fixed31_32_zero; - - return result; -} - -static bool setup_distribution_points_pq( - struct gamma_curve *arr_curve_points, - struct curve_points *arr_points, - uint32_t *hw_points_num, - struct hw_x_point *coordinates_x, - enum surface_pixel_format format) -{ - struct curve_config cfg; - - cfg.offset = 0; - cfg.segments[0] = 2; - cfg.segments[1] = 2; - cfg.segments[2] = 2; - cfg.segments[3] = 2; - cfg.segments[4] = 2; - cfg.segments[5] = 2; - cfg.segments[6] = 3; - cfg.segments[7] = 4; - cfg.segments[8] = 4; - cfg.segments[9] = 4; - cfg.segments[10] = 4; - cfg.segments[11] = 5; - cfg.segments[12] = 5; - cfg.segments[13] = 5; - cfg.segments[14] = 5; - cfg.segments[15] = 5; - - if (format == SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F || - format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F) - cfg.begin = -11; - else - cfg.begin = -16; - - if (!build_hw_curve_configuration( - &cfg, arr_curve_points, - arr_points, - coordinates_x, hw_points_num)) { - ASSERT_CRITICAL(false); - return false; - } - return true; -} - -static bool setup_distribution_points( - struct gamma_curve *arr_curve_points, - struct curve_points *arr_points, - uint32_t *hw_points_num, - struct hw_x_point *coordinates_x) -{ - struct curve_config cfg; - - cfg.offset = 0; - cfg.segments[0] = 3; - cfg.segments[1] = 4; - cfg.segments[2] = 4; - cfg.segments[3] = 4; - cfg.segments[4] = 4; - cfg.segments[5] = 4; - cfg.segments[6] = 4; - cfg.segments[7] = 4; - cfg.segments[8] = 5; - cfg.segments[9] = 5; - cfg.segments[10] = 0; - cfg.segments[11] = -1; - cfg.segments[12] = -1; - cfg.segments[13] = -1; - cfg.segments[14] = -1; - cfg.segments[15] = -1; - - cfg.begin = -10; - - if (!build_hw_curve_configuration( - &cfg, arr_curve_points, - arr_points, - coordinates_x, hw_points_num)) { - ASSERT_CRITICAL(false); - return false; - } - return true; -} - -struct dividers { - struct fixed31_32 divider1; - struct fixed31_32 divider2; - struct fixed31_32 divider3; -}; - -static void build_regamma_coefficients(struct gamma_coefficients *coefficients) -{ - /* sRGB should apply 2.4 */ - static const int32_t numerator01[3] = { 31308, 31308, 31308 }; - static const int32_t numerator02[3] = { 12920, 12920, 12920 }; - static const int32_t numerator03[3] = { 55, 55, 55 }; - static const int32_t numerator04[3] = { 55, 55, 55 }; - static const int32_t numerator05[3] = { 2400, 2400, 2400 }; - - const int32_t *numerator1; - const int32_t *numerator2; - const int32_t *numerator3; - const int32_t *numerator4; - const int32_t *numerator5; - - uint32_t i = 0; - - numerator1 = numerator01; - numerator2 = numerator02; - numerator3 = numerator03; - numerator4 = numerator04; - numerator5 = numerator05; - - do { - coefficients->a0[i] = dal_fixed31_32_from_fraction( - numerator1[i], 10000000); - coefficients->a1[i] = dal_fixed31_32_from_fraction( - numerator2[i], 1000); - coefficients->a2[i] = dal_fixed31_32_from_fraction( - numerator3[i], 1000); - coefficients->a3[i] = dal_fixed31_32_from_fraction( - numerator4[i], 1000); - coefficients->user_gamma[i] = dal_fixed31_32_from_fraction( - numerator5[i], 1000); - - ++i; - } while (i != ARRAY_SIZE(coefficients->a0)); -} - -static struct fixed31_32 translate_from_linear_space( - struct fixed31_32 arg, - struct fixed31_32 a0, - struct fixed31_32 a1, - struct fixed31_32 a2, - struct fixed31_32 a3, - struct fixed31_32 gamma) -{ - const struct fixed31_32 one = dal_fixed31_32_from_int(1); - - if (dal_fixed31_32_le(arg, dal_fixed31_32_neg(a0))) - return dal_fixed31_32_sub( - a2, - dal_fixed31_32_mul( - dal_fixed31_32_add( - one, - a3), - dal_fixed31_32_pow( - dal_fixed31_32_neg(arg), - dal_fixed31_32_recip(gamma)))); - else if (dal_fixed31_32_le(a0, arg)) - return dal_fixed31_32_sub( - dal_fixed31_32_mul( - dal_fixed31_32_add( - one, - a3), - dal_fixed31_32_pow( - arg, - dal_fixed31_32_recip(gamma))), - a2); - else - return dal_fixed31_32_mul( - arg, - a1); -} - -static inline struct fixed31_32 translate_from_linear_space_ex( - struct fixed31_32 arg, - struct gamma_coefficients *coeff, - uint32_t color_index) -{ - return translate_from_linear_space( - arg, - coeff->a0[color_index], - coeff->a1[color_index], - coeff->a2[color_index], - coeff->a3[color_index], - coeff->user_gamma[color_index]); -} - -static bool find_software_points( - const struct gamma_pixel *axis_x_256, - struct fixed31_32 hw_point, - enum channel_name channel, - uint32_t *index_to_start, - uint32_t *index_left, - uint32_t *index_right, - enum hw_point_position *pos) -{ - const uint32_t max_number = INPUT_LUT_ENTRIES + 3; - - struct fixed31_32 left, right; - - uint32_t i = *index_to_start; - - while (i < max_number) { - if (channel == CHANNEL_NAME_RED) { - left = axis_x_256[i].r; - - if (i < max_number - 1) - right = axis_x_256[i + 1].r; - else - right = axis_x_256[max_number - 1].r; - } else if (channel == CHANNEL_NAME_GREEN) { - left = axis_x_256[i].g; - - if (i < max_number - 1) - right = axis_x_256[i + 1].g; - else - right = axis_x_256[max_number - 1].g; - } else { - left = axis_x_256[i].b; - - if (i < max_number - 1) - right = axis_x_256[i + 1].b; - else - right = axis_x_256[max_number - 1].b; - } - - if (dal_fixed31_32_le(left, hw_point) && - dal_fixed31_32_le(hw_point, right)) { - *index_to_start = i; - *index_left = i; - - if (i < max_number - 1) - *index_right = i + 1; - else - *index_right = max_number - 1; - - *pos = HW_POINT_POSITION_MIDDLE; - - return true; - } else if ((i == *index_to_start) && - dal_fixed31_32_le(hw_point, left)) { - *index_to_start = i; - *index_left = i; - *index_right = i; - - *pos = HW_POINT_POSITION_LEFT; - - return true; - } else if ((i == max_number - 1) && - dal_fixed31_32_le(right, hw_point)) { - *index_to_start = i; - *index_left = i; - *index_right = i; - - *pos = HW_POINT_POSITION_RIGHT; - - return true; - } - - ++i; - } - - return false; -} - -static bool build_custom_gamma_mapping_coefficients_worker( - struct pixel_gamma_point *coeff, - const struct hw_x_point *coordinates_x, - const struct gamma_pixel *axis_x_256, - enum channel_name channel, - uint32_t number_of_points, - enum surface_pixel_format pixel_format) -{ - uint32_t i = 0; - - while (i <= number_of_points) { - struct fixed31_32 coord_x; - - uint32_t index_to_start = 0; - uint32_t index_left = 0; - uint32_t index_right = 0; - - enum hw_point_position hw_pos; - - struct gamma_point *point; - - struct fixed31_32 left_pos; - struct fixed31_32 right_pos; - - /* - * TODO: confirm enum in surface_pixel_format - * if (pixel_format == PIXEL_FORMAT_FP16) - *coord_x = coordinates_x[i].adjusted_x; - *else - */ - if (channel == CHANNEL_NAME_RED) - coord_x = coordinates_x[i].regamma_y_red; - else if (channel == CHANNEL_NAME_GREEN) - coord_x = coordinates_x[i].regamma_y_green; - else - coord_x = coordinates_x[i].regamma_y_blue; - - if (!find_software_points( - axis_x_256, coord_x, channel, - &index_to_start, &index_left, &index_right, &hw_pos)) { - BREAK_TO_DEBUGGER(); - return false; - } - - if (index_left >= INPUT_LUT_ENTRIES + 3) { - BREAK_TO_DEBUGGER(); - return false; - } - - if (index_right >= INPUT_LUT_ENTRIES + 3) { - BREAK_TO_DEBUGGER(); - return false; - } - - if (channel == CHANNEL_NAME_RED) { - point = &coeff[i].r; - - left_pos = axis_x_256[index_left].r; - right_pos = axis_x_256[index_right].r; - } else if (channel == CHANNEL_NAME_GREEN) { - point = &coeff[i].g; - - left_pos = axis_x_256[index_left].g; - right_pos = axis_x_256[index_right].g; - } else { - point = &coeff[i].b; - - left_pos = axis_x_256[index_left].b; - right_pos = axis_x_256[index_right].b; - } - - if (hw_pos == HW_POINT_POSITION_MIDDLE) - point->coeff = dal_fixed31_32_div( - dal_fixed31_32_sub( - coord_x, - left_pos), - dal_fixed31_32_sub( - right_pos, - left_pos)); - else if (hw_pos == HW_POINT_POSITION_LEFT) - point->coeff = dal_fixed31_32_zero; - else if (hw_pos == HW_POINT_POSITION_RIGHT) - point->coeff = dal_fixed31_32_from_int(2); - else { - BREAK_TO_DEBUGGER(); - return false; - } - - point->left_index = index_left; - point->right_index = index_right; - point->pos = hw_pos; - - ++i; - } - - return true; -} - -static inline bool build_oem_custom_gamma_mapping_coefficients( - struct pixel_gamma_point *coeff128_oem, - const struct hw_x_point *coordinates_x, - const struct gamma_pixel *axis_x_256, - uint32_t number_of_points, - enum surface_pixel_format pixel_format) -{ - int i; - - for (i = 0; i < 3; i++) { - if (!build_custom_gamma_mapping_coefficients_worker( - coeff128_oem, coordinates_x, axis_x_256, i, - number_of_points, pixel_format)) - return false; - } - return true; -} - -static struct fixed31_32 calculate_mapped_value( - struct pwl_float_data *rgb, - const struct pixel_gamma_point *coeff, - enum channel_name channel, - uint32_t max_index) -{ - const struct gamma_point *point; - - struct fixed31_32 result; - - if (channel == CHANNEL_NAME_RED) - point = &coeff->r; - else if (channel == CHANNEL_NAME_GREEN) - point = &coeff->g; - else - point = &coeff->b; - - if ((point->left_index < 0) || (point->left_index > max_index)) { - BREAK_TO_DEBUGGER(); - return dal_fixed31_32_zero; - } - - if ((point->right_index < 0) || (point->right_index > max_index)) { - BREAK_TO_DEBUGGER(); - return dal_fixed31_32_zero; - } - - if (point->pos == HW_POINT_POSITION_MIDDLE) - if (channel == CHANNEL_NAME_RED) - result = dal_fixed31_32_add( - dal_fixed31_32_mul( - point->coeff, - dal_fixed31_32_sub( - rgb[point->right_index].r, - rgb[point->left_index].r)), - rgb[point->left_index].r); - else if (channel == CHANNEL_NAME_GREEN) - result = dal_fixed31_32_add( - dal_fixed31_32_mul( - point->coeff, - dal_fixed31_32_sub( - rgb[point->right_index].g, - rgb[point->left_index].g)), - rgb[point->left_index].g); - else - result = dal_fixed31_32_add( - dal_fixed31_32_mul( - point->coeff, - dal_fixed31_32_sub( - rgb[point->right_index].b, - rgb[point->left_index].b)), - rgb[point->left_index].b); - else if (point->pos == HW_POINT_POSITION_LEFT) { - BREAK_TO_DEBUGGER(); - result = dal_fixed31_32_zero; - } else { - BREAK_TO_DEBUGGER(); - result = dal_fixed31_32_one; - } - - return result; -} - -static inline struct fixed31_32 calculate_oem_mapped_value( - struct pwl_float_data *rgb_oem, - const struct pixel_gamma_point *coeff, - uint32_t index, - enum channel_name channel, - uint32_t max_index) -{ - return calculate_mapped_value( - rgb_oem, - coeff + index, - channel, - max_index); -} - -static void compute_pq(struct fixed31_32 in_x, struct fixed31_32 *out_y) -{ - /* consts for PQ gamma formula. */ - const struct fixed31_32 m1 = - dal_fixed31_32_from_fraction(159301758, 1000000000); - const struct fixed31_32 m2 = - dal_fixed31_32_from_fraction(7884375, 100000); - const struct fixed31_32 c1 = - dal_fixed31_32_from_fraction(8359375, 10000000); - const struct fixed31_32 c2 = - dal_fixed31_32_from_fraction(188515625, 10000000); - const struct fixed31_32 c3 = - dal_fixed31_32_from_fraction(186875, 10000); - - struct fixed31_32 l_pow_m1; - struct fixed31_32 base; - - if (dal_fixed31_32_lt(in_x, dal_fixed31_32_zero)) - in_x = dal_fixed31_32_zero; - - l_pow_m1 = dal_fixed31_32_pow(in_x, m1); - base = dal_fixed31_32_div( - dal_fixed31_32_add(c1, - (dal_fixed31_32_mul(c2, l_pow_m1))), - dal_fixed31_32_add(dal_fixed31_32_one, - (dal_fixed31_32_mul(c3, l_pow_m1)))); - *out_y = dal_fixed31_32_pow(base, m2); -} - -static void build_regamma_curve_pq(struct pwl_float_data_ex *rgb_regamma, - struct pwl_float_data *rgb_oem, - struct pixel_gamma_point *coeff128_oem, - const struct core_gamma *ramp, - const struct core_surface *surface, - uint32_t hw_points_num, - const struct hw_x_point *coordinate_x, - const struct gamma_pixel *axis_x, - struct dividers dividers) -{ - uint32_t i; - - struct pwl_float_data_ex *rgb = rgb_regamma; - const struct hw_x_point *coord_x = coordinate_x; - struct fixed31_32 x; - struct fixed31_32 output; - struct fixed31_32 scaling_factor = - dal_fixed31_32_from_fraction(8, 1000); - - /* use coord_x to retrieve coordinates chosen base on given user curve - * the x values are exponentially distributed and currently it is hard - * coded, the user curve shape is ignored. Need to recalculate coord_x - * based on input curve, translation from 256/1025 to 128 PWL points. - */ - for (i = 0; i <= hw_points_num; i++) { - /* Multiply 0.008 as regamma is 0-1 and FP16 input is 0-125. - * FP 1.0 = 80nits - */ - x = dal_fixed31_32_mul(coord_x->adjusted_x, scaling_factor); - - compute_pq(x, &output); - - /* should really not happen? */ - if (dal_fixed31_32_lt(output, dal_fixed31_32_zero)) - output = dal_fixed31_32_zero; - else if (dal_fixed31_32_lt(dal_fixed31_32_one, output)) - output = dal_fixed31_32_one; - - rgb->r = output; - rgb->g = output; - rgb->b = output; - - ++coord_x; - ++rgb; - } -} - -static void build_regamma_curve(struct pwl_float_data_ex *rgb_regamma, - struct pwl_float_data *rgb_oem, - struct pixel_gamma_point *coeff128_oem, - const struct core_gamma *ramp, - const struct core_surface *surface, - uint32_t hw_points_num, - const struct hw_x_point *coordinate_x, - const struct gamma_pixel *axis_x, - struct dividers dividers) -{ - uint32_t i; - - struct gamma_coefficients coeff; - struct pwl_float_data_ex *rgb = rgb_regamma; - const struct hw_x_point *coord_x = coordinate_x; - - build_regamma_coefficients(&coeff); - - /* Use opp110->regamma.coordinates_x to retrieve - * coordinates chosen base on given user curve (future task). - * The x values are exponentially distributed and currently - * it is hard-coded, the user curve shape is ignored. - * The future task is to recalculate opp110- - * regamma.coordinates_x based on input/user curve, - * translation from 256/1025 to 128 pwl points. - */ - - i = 0; - - while (i != hw_points_num + 1) { - rgb->r = translate_from_linear_space_ex( - coord_x->adjusted_x, &coeff, 0); - rgb->g = translate_from_linear_space_ex( - coord_x->adjusted_x, &coeff, 1); - rgb->b = translate_from_linear_space_ex( - coord_x->adjusted_x, &coeff, 2); - - ++coord_x; - ++rgb; - ++i; - } -} - -static bool scale_gamma(struct pwl_float_data *pwl_rgb, - const struct core_gamma *ramp, - struct dividers dividers) -{ - const struct dc_gamma *gamma = &ramp->public; - const uint16_t max_driver = 0xFFFF; - const uint16_t max_os = 0xFF00; - uint16_t scaler = max_os; - uint32_t i = 0; - struct pwl_float_data *rgb = pwl_rgb; - struct pwl_float_data *rgb_last = rgb + INPUT_LUT_ENTRIES - 1; - - do { - if ((gamma->red[i] > max_os) || - (gamma->green[i] > max_os) || - (gamma->blue[i] > max_os)) { - scaler = max_driver; - break; - } - ++i; - } while (i != INPUT_LUT_ENTRIES); - - i = 0; - - do { - rgb->r = dal_fixed31_32_from_fraction( - gamma->red[i], scaler); - rgb->g = dal_fixed31_32_from_fraction( - gamma->green[i], scaler); - rgb->b = dal_fixed31_32_from_fraction( - gamma->blue[i], scaler); - - ++rgb; - ++i; - } while (i != INPUT_LUT_ENTRIES); - - rgb->r = dal_fixed31_32_mul(rgb_last->r, - dividers.divider1); - rgb->g = dal_fixed31_32_mul(rgb_last->g, - dividers.divider1); - rgb->b = dal_fixed31_32_mul(rgb_last->b, - dividers.divider1); - - ++rgb; - - rgb->r = dal_fixed31_32_mul(rgb_last->r, - dividers.divider2); - rgb->g = dal_fixed31_32_mul(rgb_last->g, - dividers.divider2); - rgb->b = dal_fixed31_32_mul(rgb_last->b, - dividers.divider2); - - ++rgb; - - rgb->r = dal_fixed31_32_mul(rgb_last->r, - dividers.divider3); - rgb->g = dal_fixed31_32_mul(rgb_last->g, - dividers.divider3); - rgb->b = dal_fixed31_32_mul(rgb_last->b, - dividers.divider3); - - return true; -} - -static void build_evenly_distributed_points( - struct gamma_pixel *points, - uint32_t numberof_points, - struct fixed31_32 max_value, - struct dividers dividers) -{ - struct gamma_pixel *p = points; - struct gamma_pixel *p_last = p + numberof_points - 1; - - uint32_t i = 0; - - do { - struct fixed31_32 value = dal_fixed31_32_div_int( - dal_fixed31_32_mul_int(max_value, i), - numberof_points - 1); - - p->r = value; - p->g = value; - p->b = value; - - ++p; - ++i; - } while (i != numberof_points); - - p->r = dal_fixed31_32_div(p_last->r, dividers.divider1); - p->g = dal_fixed31_32_div(p_last->g, dividers.divider1); - p->b = dal_fixed31_32_div(p_last->b, dividers.divider1); - - ++p; - - p->r = dal_fixed31_32_div(p_last->r, dividers.divider2); - p->g = dal_fixed31_32_div(p_last->g, dividers.divider2); - p->b = dal_fixed31_32_div(p_last->b, dividers.divider2); - - ++p; - - p->r = dal_fixed31_32_div(p_last->r, dividers.divider3); - p->g = dal_fixed31_32_div(p_last->g, dividers.divider3); - p->b = dal_fixed31_32_div(p_last->b, dividers.divider3); -} - -static inline void copy_rgb_regamma_to_coordinates_x( - struct hw_x_point *coordinates_x, - uint32_t hw_points_num, - const struct pwl_float_data_ex *rgb_ex) -{ - struct hw_x_point *coords = coordinates_x; - uint32_t i = 0; - const struct pwl_float_data_ex *rgb_regamma = rgb_ex; - - while (i <= hw_points_num) { - coords->regamma_y_red = rgb_regamma->r; - coords->regamma_y_green = rgb_regamma->g; - coords->regamma_y_blue = rgb_regamma->b; - - ++coords; - ++rgb_regamma; - ++i; - } -} - -static bool calculate_interpolated_hardware_curve( - struct pwl_result_data *rgb, - struct pixel_gamma_point *coeff128, - struct pwl_float_data *rgb_user, - const struct hw_x_point *coordinates_x, - const struct gamma_pixel *axis_x_256, - uint32_t number_of_points, - enum surface_pixel_format pixel_format) -{ - - const struct pixel_gamma_point *coeff; - struct pixel_gamma_point *coeff_128 = coeff128; - uint32_t max_entries = 3 - 1; - struct pwl_result_data *rgb_resulted = rgb; - - uint32_t i = 0; - - if (!build_oem_custom_gamma_mapping_coefficients( - coeff_128, coordinates_x, axis_x_256, - number_of_points, - pixel_format)) - return false; - - coeff = coeff128; - max_entries += INPUT_LUT_ENTRIES; - - /* TODO: float point case */ - - while (i <= number_of_points) { - rgb_resulted->red = calculate_mapped_value( - rgb_user, coeff, CHANNEL_NAME_RED, max_entries); - rgb_resulted->green = calculate_mapped_value( - rgb_user, coeff, CHANNEL_NAME_GREEN, max_entries); - rgb_resulted->blue = calculate_mapped_value( - rgb_user, coeff, CHANNEL_NAME_BLUE, max_entries); - - ++coeff; - ++rgb_resulted; - ++i; - } - - return true; -} - -static bool map_regamma_hw_to_x_user( - struct pixel_gamma_point *coeff128, - struct pwl_float_data *rgb_oem, - struct pwl_result_data *rgb_resulted, - struct pwl_float_data *rgb_user, - struct hw_x_point *coords_x, - const struct gamma_pixel *axis_x, - const struct dc_gamma *gamma, - const struct pwl_float_data_ex *rgb_regamma, - struct dividers dividers, - uint32_t hw_points_num, - const struct core_surface *surface) -{ - /* setup to spare calculated ideal regamma values */ - - struct pixel_gamma_point *coeff = coeff128; - - struct hw_x_point *coords = coords_x; - - copy_rgb_regamma_to_coordinates_x(coords, hw_points_num, rgb_regamma); - - return calculate_interpolated_hardware_curve( - rgb_resulted, coeff, rgb_user, coords, axis_x, - hw_points_num, surface->public.format); -} - -static void build_new_custom_resulted_curve( - struct pwl_result_data *rgb_resulted, - uint32_t hw_points_num) -{ - struct pwl_result_data *rgb = rgb_resulted; - struct pwl_result_data *rgb_plus_1 = rgb + 1; - - uint32_t i; - - i = 0; - - while (i != hw_points_num + 1) { - rgb->red = dal_fixed31_32_clamp( - rgb->red, dal_fixed31_32_zero, - dal_fixed31_32_one); - rgb->green = dal_fixed31_32_clamp( - rgb->green, dal_fixed31_32_zero, - dal_fixed31_32_one); - rgb->blue = dal_fixed31_32_clamp( - rgb->blue, dal_fixed31_32_zero, - dal_fixed31_32_one); - - ++rgb; - ++i; - } - - rgb = rgb_resulted; - - i = 1; - - while (i != hw_points_num + 1) { - if (dal_fixed31_32_lt(rgb_plus_1->red, rgb->red)) - rgb_plus_1->red = rgb->red; - if (dal_fixed31_32_lt(rgb_plus_1->green, rgb->green)) - rgb_plus_1->green = rgb->green; - if (dal_fixed31_32_lt(rgb_plus_1->blue, rgb->blue)) - rgb_plus_1->blue = rgb->blue; - - rgb->delta_red = dal_fixed31_32_sub( - rgb_plus_1->red, - rgb->red); - rgb->delta_green = dal_fixed31_32_sub( - rgb_plus_1->green, - rgb->green); - rgb->delta_blue = dal_fixed31_32_sub( - rgb_plus_1->blue, - rgb->blue); - - ++rgb_plus_1; - ++rgb; - ++i; - } -} - -static void rebuild_curve_configuration_magic( - struct curve_points *arr_points, - struct pwl_result_data *rgb_resulted, - const struct hw_x_point *coordinates_x, - uint32_t hw_points_num, - enum dc_transfer_func_predefined tf) -{ - struct fixed31_32 y_r; - struct fixed31_32 y_g; - struct fixed31_32 y_b; - - struct fixed31_32 y1_min; - struct fixed31_32 y3_max; - - y_r = rgb_resulted[0].red; - y_g = rgb_resulted[0].green; - y_b = rgb_resulted[0].blue; - - y1_min = dal_fixed31_32_min(y_r, dal_fixed31_32_min(y_g, y_b)); - - arr_points[0].x = coordinates_x[0].adjusted_x; - arr_points[0].y = y1_min; - arr_points[0].slope = dal_fixed31_32_div( - arr_points[0].y, - arr_points[0].x); - - /* this should be cleaned up as it's confusing my understanding (KK) is - * that REGAMMA_CNTLA_EXP_REGION_END is the X value for the region end - * REGAMMA_CNTLA_EXP_REGION_END_BASE is Y value for the above X - * REGAMMA_CNTLA_EXP_REGION_END_SLOPE is the slope beyond (X,Y) above - * currently when programming REGION_END = m_arrPoints[1].x, - * REGION_END_BASE = m_arrPoints[1].y, REGION_END_SLOPE=1 - * we don't use m_arrPoints[2] at all after this function, - * and its purpose isn't clear to me - */ - arr_points[1].x = coordinates_x[hw_points_num].adjusted_x; - arr_points[2].x = coordinates_x[hw_points_num].adjusted_x; - - y_r = rgb_resulted[hw_points_num].red; - y_g = rgb_resulted[hw_points_num].green; - y_b = rgb_resulted[hw_points_num].blue; - - /* see comment above, m_arrPoints[1].y should be the Y value for the - * region end (m_numOfHwPoints), not last HW point(m_numOfHwPoints - 1) - */ - y3_max = dal_fixed31_32_max(y_r, dal_fixed31_32_max(y_g, y_b)); - - arr_points[1].y = y3_max; - arr_points[2].y = y3_max; - - arr_points[2].slope = dal_fixed31_32_zero; - - /* for PQ, we want to have a straight line from last HW X point, and the - * slope to be such that we hit 1.0 at 10000 nits. - */ - if (tf == TRANSFER_FUNCTION_PQ) { - const struct fixed31_32 end_value = - dal_fixed31_32_from_int(125); - - arr_points[2].slope = dal_fixed31_32_div( - dal_fixed31_32_sub(dal_fixed31_32_one, arr_points[1].y), - dal_fixed31_32_sub(end_value, arr_points[1].x)); - } -} - -static bool convert_to_custom_float_format( - struct fixed31_32 value, - const struct custom_float_format *format, - uint32_t *result) -{ - uint32_t mantissa; - uint32_t exponenta; - bool negative; - - return build_custom_float( - value, format, &negative, &mantissa, &exponenta) && - setup_custom_float( - format, negative, mantissa, exponenta, result); -} - -static bool convert_to_custom_float( - struct pwl_result_data *rgb_resulted, - struct curve_points *arr_points, - uint32_t hw_points_num) -{ - struct custom_float_format fmt; - - struct pwl_result_data *rgb = rgb_resulted; - - uint32_t i = 0; - - fmt.exponenta_bits = 6; - fmt.mantissa_bits = 12; - fmt.sign = true; - - if (!convert_to_custom_float_format( - arr_points[0].x, - &fmt, - &arr_points[0].custom_float_x)) { - BREAK_TO_DEBUGGER(); - return false; - } - - if (!convert_to_custom_float_format( - arr_points[0].offset, - &fmt, - &arr_points[0].custom_float_offset)) { - BREAK_TO_DEBUGGER(); - return false; - } - - if (!convert_to_custom_float_format( - arr_points[0].slope, - &fmt, - &arr_points[0].custom_float_slope)) { - BREAK_TO_DEBUGGER(); - return false; - } - - fmt.mantissa_bits = 10; - fmt.sign = false; - - if (!convert_to_custom_float_format( - arr_points[1].x, - &fmt, - &arr_points[1].custom_float_x)) { - BREAK_TO_DEBUGGER(); - return false; - } - - if (!convert_to_custom_float_format( - arr_points[1].y, - &fmt, - &arr_points[1].custom_float_y)) { - BREAK_TO_DEBUGGER(); - return false; - } - - if (!convert_to_custom_float_format( - arr_points[2].slope, - &fmt, - &arr_points[2].custom_float_slope)) { - BREAK_TO_DEBUGGER(); - return false; - } - - fmt.mantissa_bits = 12; - fmt.sign = true; - - while (i != hw_points_num) { - if (!convert_to_custom_float_format( - rgb->red, - &fmt, - &rgb->red_reg)) { - BREAK_TO_DEBUGGER(); - return false; - } - - if (!convert_to_custom_float_format( - rgb->green, - &fmt, - &rgb->green_reg)) { - BREAK_TO_DEBUGGER(); - return false; - } - - if (!convert_to_custom_float_format( - rgb->blue, - &fmt, - &rgb->blue_reg)) { - BREAK_TO_DEBUGGER(); - return false; - } - - if (!convert_to_custom_float_format( - rgb->delta_red, - &fmt, - &rgb->delta_red_reg)) { - BREAK_TO_DEBUGGER(); - return false; - } - - if (!convert_to_custom_float_format( - rgb->delta_green, - &fmt, - &rgb->delta_green_reg)) { - BREAK_TO_DEBUGGER(); - return false; - } - - if (!convert_to_custom_float_format( - rgb->delta_blue, - &fmt, - &rgb->delta_blue_reg)) { - BREAK_TO_DEBUGGER(); - return false; - } - - ++rgb; - ++i; - } - - return true; -} - -bool calculate_regamma_params(struct pwl_params *params, - const struct core_gamma *ramp, - const struct core_surface *surface, - const struct core_stream *stream) -{ - struct gamma_curve *arr_curve_points = params->arr_curve_points; - struct curve_points *arr_points = params->arr_points; - struct pwl_result_data *rgb_resulted = params->rgb_resulted; - struct dividers dividers; - - struct hw_x_point *coordinates_x = NULL; - struct pwl_float_data *rgb_user = NULL ; - struct pwl_float_data_ex *rgb_regamma = NULL; - struct pwl_float_data *rgb_oem = NULL; - struct gamma_pixel *axix_x_256 = NULL; - struct pixel_gamma_point *coeff128_oem = NULL; - struct pixel_gamma_point *coeff128 = NULL; - - enum dc_transfer_func_predefined tf = TRANSFER_FUNCTION_SRGB; - - bool ret = false; - - coordinates_x = dm_alloc(sizeof(*coordinates_x)*(256 + 3)); - if (!coordinates_x) - goto coordinates_x_alloc_fail; - rgb_user = dm_alloc(sizeof(*rgb_user) * (TRANSFER_FUNC_POINTS + 3)); - if (!rgb_user) - goto rgb_user_alloc_fail; - rgb_regamma = dm_alloc(sizeof(*rgb_regamma) * (256 + 3)); - if (!rgb_regamma) - goto rgb_regamma_alloc_fail; - rgb_oem = dm_alloc(sizeof(*rgb_oem) * (TRANSFER_FUNC_POINTS + 3)); - if (!rgb_oem) - goto rgb_oem_alloc_fail; - axix_x_256 = dm_alloc(sizeof(*axix_x_256) * (256 + 3)); - if (!axix_x_256) - goto axix_x_256_alloc_fail; - coeff128_oem = dm_alloc(sizeof(*coeff128_oem) * (256 + 3)); - if (!coeff128_oem) - goto coeff128_oem_alloc_fail; - coeff128 = dm_alloc(sizeof(*coeff128) * (256 + 3)); - if (!coeff128) - goto coeff128_alloc_fail; - - dividers.divider1 = dal_fixed31_32_from_fraction(3, 2); - dividers.divider2 = dal_fixed31_32_from_int(2); - dividers.divider3 = dal_fixed31_32_from_fraction(5, 2); - - if (stream->public.out_transfer_func) - tf = stream->public.out_transfer_func->tf; - - build_evenly_distributed_points( - axix_x_256, - 256, - dal_fixed31_32_one, - dividers); - - scale_gamma(rgb_user, ramp, dividers); - - if (tf == TRANSFER_FUNCTION_PQ) { - setup_distribution_points_pq(arr_curve_points, arr_points, - ¶ms->hw_points_num, coordinates_x, - surface->public.format); - build_regamma_curve_pq(rgb_regamma, rgb_oem, coeff128_oem, - ramp, surface, params->hw_points_num, - coordinates_x, axix_x_256, dividers); - } else { - setup_distribution_points(arr_curve_points, arr_points, - ¶ms->hw_points_num, coordinates_x); - build_regamma_curve(rgb_regamma, rgb_oem, coeff128_oem, - ramp, surface, params->hw_points_num, - coordinates_x, axix_x_256, dividers); - } - - map_regamma_hw_to_x_user(coeff128, rgb_oem, rgb_resulted, rgb_user, - coordinates_x, axix_x_256, &ramp->public, rgb_regamma, - dividers, params->hw_points_num, surface); - - build_new_custom_resulted_curve(rgb_resulted, params->hw_points_num); - - rebuild_curve_configuration_magic( - arr_points, - rgb_resulted, - coordinates_x, - params->hw_points_num, - tf); - - convert_to_custom_float(rgb_resulted, arr_points, - params->hw_points_num); - - ret = true; - - dm_free(coeff128); -coeff128_alloc_fail: - dm_free(coeff128_oem); -coeff128_oem_alloc_fail: - dm_free(axix_x_256); -axix_x_256_alloc_fail: - dm_free(rgb_oem); -rgb_oem_alloc_fail: - dm_free(rgb_regamma); -rgb_regamma_alloc_fail: - dm_free(rgb_user); -rgb_user_alloc_fail: - dm_free(coordinates_x); -coordinates_x_alloc_fail: - return ret; - -} - diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 7d4299b9ee1f..948f82a56472 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1519,23 +1519,23 @@ void dc_update_surfaces_for_stream(struct dc *dc, struct dc_surface_update *upda if (dc->debug.disable_color_module) continue; /* skip below color updates */ - if (updates[i].hdr_static_metadata) { - resource_build_info_frame(pipe_ctx); - core_dc->hwss.update_info_frame(pipe_ctx); - } if (is_new_pipe_surface[j] || updates[i].in_transfer_func) core_dc->hwss.set_input_transfer_func( pipe_ctx, pipe_ctx->surface); if (is_new_pipe_surface[j] || - updates[i].gamma || updates[i].out_transfer_func) core_dc->hwss.set_output_transfer_func( pipe_ctx, pipe_ctx->surface, pipe_ctx->stream); + if (updates[i].hdr_static_metadata) { + resource_build_info_frame(pipe_ctx); + core_dc->hwss.update_info_frame(pipe_ctx); + } + } if (apply_ctx) { core_dc->hwss.apply_ctx_for_surface(core_dc, surface, context); diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index b814e7b76bbc..f53b41339951 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -213,11 +213,14 @@ enum dc_transfer_func_type { }; struct dc_transfer_func_distributed_points { - uint16_t red[TRANSFER_FUNC_POINTS]; - uint16_t green[TRANSFER_FUNC_POINTS]; - uint16_t blue[TRANSFER_FUNC_POINTS]; + struct fixed31_32 red[TRANSFER_FUNC_POINTS]; + struct fixed31_32 green[TRANSFER_FUNC_POINTS]; + struct fixed31_32 blue[TRANSFER_FUNC_POINTS]; + uint16_t end_exponent; - uint16_t x_point_at_y1; + uint16_t x_point_at_y1_red; + uint16_t x_point_at_y1_green; + uint16_t x_point_at_y1_blue; }; enum dc_transfer_func_predefined { diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 415b12accd2c..6e70cf7b99ef 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -42,7 +42,6 @@ #include "stream_encoder.h" #include "link_encoder.h" #include "clock_source.h" -#include "gamma_calcs.h" #include "audio.h" #include "dce/dce_hwseq.h" @@ -286,6 +285,436 @@ static bool dce110_set_input_transfer_func( return result; } +static bool build_custom_float( + struct fixed31_32 value, + const struct custom_float_format *format, + bool *negative, + uint32_t *mantissa, + uint32_t *exponenta) +{ + uint32_t exp_offset = (1 << (format->exponenta_bits - 1)) - 1; + + const struct fixed31_32 mantissa_constant_plus_max_fraction = + dal_fixed31_32_from_fraction( + (1LL << (format->mantissa_bits + 1)) - 1, + 1LL << format->mantissa_bits); + + struct fixed31_32 mantiss; + + if (dal_fixed31_32_eq( + value, + dal_fixed31_32_zero)) { + *negative = false; + *mantissa = 0; + *exponenta = 0; + return true; + } + + if (dal_fixed31_32_lt( + value, + dal_fixed31_32_zero)) { + *negative = format->sign; + value = dal_fixed31_32_neg(value); + } else { + *negative = false; + } + + if (dal_fixed31_32_lt( + value, + dal_fixed31_32_one)) { + uint32_t i = 1; + + do { + value = dal_fixed31_32_shl(value, 1); + ++i; + } while (dal_fixed31_32_lt( + value, + dal_fixed31_32_one)); + + --i; + + if (exp_offset <= i) { + *mantissa = 0; + *exponenta = 0; + return true; + } + + *exponenta = exp_offset - i; + } else if (dal_fixed31_32_le( + mantissa_constant_plus_max_fraction, + value)) { + uint32_t i = 1; + + do { + value = dal_fixed31_32_shr(value, 1); + ++i; + } while (dal_fixed31_32_lt( + mantissa_constant_plus_max_fraction, + value)); + + *exponenta = exp_offset + i - 1; + } else { + *exponenta = exp_offset; + } + + mantiss = dal_fixed31_32_sub( + value, + dal_fixed31_32_one); + + if (dal_fixed31_32_lt( + mantiss, + dal_fixed31_32_zero) || + dal_fixed31_32_lt( + dal_fixed31_32_one, + mantiss)) + mantiss = dal_fixed31_32_zero; + else + mantiss = dal_fixed31_32_shl( + mantiss, + format->mantissa_bits); + + *mantissa = dal_fixed31_32_floor(mantiss); + + return true; +} + +static bool setup_custom_float( + const struct custom_float_format *format, + bool negative, + uint32_t mantissa, + uint32_t exponenta, + uint32_t *result) +{ + uint32_t i = 0; + uint32_t j = 0; + + uint32_t value = 0; + + /* verification code: + * once calculation is ok we can remove it + */ + + const uint32_t mantissa_mask = + (1 << (format->mantissa_bits + 1)) - 1; + + const uint32_t exponenta_mask = + (1 << (format->exponenta_bits + 1)) - 1; + + if (mantissa & ~mantissa_mask) { + BREAK_TO_DEBUGGER(); + mantissa = mantissa_mask; + } + + if (exponenta & ~exponenta_mask) { + BREAK_TO_DEBUGGER(); + exponenta = exponenta_mask; + } + + /* end of verification code */ + + while (i < format->mantissa_bits) { + uint32_t mask = 1 << i; + + if (mantissa & mask) + value |= mask; + + ++i; + } + + while (j < format->exponenta_bits) { + uint32_t mask = 1 << j; + + if (exponenta & mask) + value |= mask << i; + + ++j; + } + + if (negative && format->sign) + value |= 1 << (i + j); + + *result = value; + + return true; +} + +static bool convert_to_custom_float_format( + struct fixed31_32 value, + const struct custom_float_format *format, + uint32_t *result) +{ + uint32_t mantissa; + uint32_t exponenta; + bool negative; + + return build_custom_float( + value, format, &negative, &mantissa, &exponenta) && + setup_custom_float( + format, negative, mantissa, exponenta, result); +} + +static bool convert_to_custom_float( + struct pwl_result_data *rgb_resulted, + struct curve_points *arr_points, + uint32_t hw_points_num) +{ + struct custom_float_format fmt; + + struct pwl_result_data *rgb = rgb_resulted; + + uint32_t i = 0; + + fmt.exponenta_bits = 6; + fmt.mantissa_bits = 12; + fmt.sign = true; + + if (!convert_to_custom_float_format( + arr_points[0].x, + &fmt, + &arr_points[0].custom_float_x)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + arr_points[0].offset, + &fmt, + &arr_points[0].custom_float_offset)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + arr_points[0].slope, + &fmt, + &arr_points[0].custom_float_slope)) { + BREAK_TO_DEBUGGER(); + return false; + } + + fmt.mantissa_bits = 10; + fmt.sign = false; + + if (!convert_to_custom_float_format( + arr_points[1].x, + &fmt, + &arr_points[1].custom_float_x)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + arr_points[1].y, + &fmt, + &arr_points[1].custom_float_y)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + arr_points[2].slope, + &fmt, + &arr_points[2].custom_float_slope)) { + BREAK_TO_DEBUGGER(); + return false; + } + + fmt.mantissa_bits = 12; + fmt.sign = true; + + while (i != hw_points_num) { + if (!convert_to_custom_float_format( + rgb->red, + &fmt, + &rgb->red_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + rgb->green, + &fmt, + &rgb->green_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + rgb->blue, + &fmt, + &rgb->blue_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + rgb->delta_red, + &fmt, + &rgb->delta_red_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + rgb->delta_green, + &fmt, + &rgb->delta_green_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + rgb->delta_blue, + &fmt, + &rgb->delta_blue_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + ++rgb; + ++i; + } + + return true; +} + +static bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func + *output_tf, struct pwl_params *regamma_params) +{ + if (output_tf == NULL || regamma_params == NULL) + return false; + + struct gamma_curve *arr_curve_points = regamma_params->arr_curve_points; + struct curve_points *arr_points = regamma_params->arr_points; + struct pwl_result_data *rgb_resulted = regamma_params->rgb_resulted; + struct fixed31_32 y_r; + struct fixed31_32 y_g; + struct fixed31_32 y_b; + struct fixed31_32 y1_min; + struct fixed31_32 y3_max; + + int32_t segment_start, segment_end; + uint32_t hw_points, start_index; + uint32_t i, j; + + memset(regamma_params, 0, sizeof(struct pwl_params)); + + if (output_tf->tf == TRANSFER_FUNCTION_PQ) { + /* 16 segments x 16 points + * segments are from 2^-11 to 2^5 + */ + segment_start = -11; + segment_end = 5; + + } else { + /* 10 segments x 16 points + * segment is from 2^-10 to 2^0 + */ + segment_start = -10; + segment_end = 0; + } + + hw_points = (segment_end - segment_start) * 16; + j = 0; + /* (segment + 25) * 32, every 2nd point */ + start_index = (segment_start + 25) * 32; + for (i = start_index; i <= 1025; i += 2) { + if (j > hw_points) + break; + 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]; + j++; + } + + arr_points[0].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2), + dal_fixed31_32_from_int(segment_start)); + arr_points[1].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2), + dal_fixed31_32_from_int(segment_end)); + arr_points[2].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2), + dal_fixed31_32_from_int(segment_end)); + + y_r = rgb_resulted[0].red; + y_g = rgb_resulted[0].green; + y_b = rgb_resulted[0].blue; + + y1_min = dal_fixed31_32_min(y_r, dal_fixed31_32_min(y_g, y_b)); + + arr_points[0].y = y1_min; + arr_points[0].slope = dal_fixed31_32_div( + arr_points[0].y, + arr_points[0].x); + + y_r = rgb_resulted[hw_points - 1].red; + y_g = rgb_resulted[hw_points - 1].green; + y_b = rgb_resulted[hw_points - 1].blue; + + /* see comment above, m_arrPoints[1].y should be the Y value for the + * region end (m_numOfHwPoints), not last HW point(m_numOfHwPoints - 1) + */ + y3_max = dal_fixed31_32_max(y_r, dal_fixed31_32_max(y_g, y_b)); + + arr_points[1].y = y3_max; + arr_points[2].y = y3_max; + + arr_points[1].slope = dal_fixed31_32_zero; + arr_points[2].slope = dal_fixed31_32_zero; + + if (output_tf->tf == TRANSFER_FUNCTION_PQ) { + /* for PQ, we want to have a straight line from last HW X point, + * and the slope to be such that we hit 1.0 at 10000 nits. + */ + const struct fixed31_32 end_value = + dal_fixed31_32_from_int(125); + + arr_points[1].slope = dal_fixed31_32_div( + dal_fixed31_32_sub(dal_fixed31_32_one, arr_points[1].y), + dal_fixed31_32_sub(end_value, arr_points[1].x)); + arr_points[2].slope = dal_fixed31_32_div( + dal_fixed31_32_sub(dal_fixed31_32_one, arr_points[1].y), + dal_fixed31_32_sub(end_value, arr_points[1].x)); + } + + regamma_params->hw_points_num = hw_points; + + for (i = 0; i < segment_end - segment_start; i++) { + regamma_params->arr_curve_points[i].offset = i * 16; + regamma_params->arr_curve_points[i].segments_num = 4; + } + + struct pwl_result_data *rgb = rgb_resulted; + struct pwl_result_data *rgb_plus_1 = rgb_resulted + 1; + + i = 1; + + while (i != hw_points + 1) { + if (dal_fixed31_32_lt(rgb_plus_1->red, rgb->red)) + rgb_plus_1->red = rgb->red; + if (dal_fixed31_32_lt(rgb_plus_1->green, rgb->green)) + rgb_plus_1->green = rgb->green; + if (dal_fixed31_32_lt(rgb_plus_1->blue, rgb->blue)) + rgb_plus_1->blue = rgb->blue; + + rgb->delta_red = dal_fixed31_32_sub( + rgb_plus_1->red, + rgb->red); + rgb->delta_green = dal_fixed31_32_sub( + rgb_plus_1->green, + rgb->green); + rgb->delta_blue = dal_fixed31_32_sub( + rgb_plus_1->blue, + rgb->blue); + + ++rgb_plus_1; + ++rgb; + ++i; + } + + convert_to_custom_float(rgb_resulted, arr_points, hw_points); + + return true; +} + static bool dce110_set_output_transfer_func( struct pipe_ctx *pipe_ctx, const struct core_surface *surface, /* Surface - To be removed */ @@ -308,10 +737,13 @@ static bool dce110_set_output_transfer_func( opp->funcs->opp_power_on_regamma_lut(opp, true); if (stream->public.out_transfer_func && - stream->public.out_transfer_func->type == TF_TYPE_PREDEFINED && - stream->public.out_transfer_func->tf == TRANSFER_FUNCTION_SRGB) { + stream->public.out_transfer_func->type == + TF_TYPE_PREDEFINED && + stream->public.out_transfer_func->tf == + TRANSFER_FUNCTION_SRGB) { opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_SRGB); - } else if (ramp && calculate_regamma_params(regamma_params, ramp, surface, stream)) { + } else if (dce110_translate_regamma_to_hw_format( + stream->public.out_transfer_func, regamma_params)) { opp->funcs->opp_program_regamma_pwl(opp, regamma_params); opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_USER); } else { diff --git a/drivers/gpu/drm/amd/display/dc/inc/gamma_calcs.h b/drivers/gpu/drm/amd/display/dc/inc/gamma_calcs.h deleted file mode 100644 index 0712268856c2..000000000000 --- a/drivers/gpu/drm/amd/display/dc/inc/gamma_calcs.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * gamma_calcs.h - * - * Created on: Feb 9, 2016 - * Author: yonsun - */ - -#ifndef DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_GAMMA_CALCS_H_ -#define DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_GAMMA_CALCS_H_ - -#include "opp.h" -#include "core_types.h" -#include "dc.h" - -bool calculate_regamma_params(struct pwl_params *params, - const struct core_gamma *ramp, - const struct core_surface *surface, - const struct core_stream *stream); - -#endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_GAMMA_CALCS_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h index a1f31a4410a3..bef5e2cacbe3 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h @@ -138,9 +138,7 @@ struct custom_float_value { struct hw_x_point { uint32_t custom_float_x; - uint32_t custom_float_x_adjusted; struct fixed31_32 x; - struct fixed31_32 adjusted_x; struct fixed31_32 regamma_y_red; struct fixed31_32 regamma_y_green; struct fixed31_32 regamma_y_blue; diff --git a/drivers/gpu/drm/amd/display/include/fixed31_32.h b/drivers/gpu/drm/amd/display/include/fixed31_32.h index c28de167250f..5a4364dfd2f7 100644 --- a/drivers/gpu/drm/amd/display/include/fixed31_32.h +++ b/drivers/gpu/drm/amd/display/include/fixed31_32.h @@ -190,6 +190,14 @@ struct fixed31_32 dal_fixed31_32_add( struct fixed31_32 arg1, struct fixed31_32 arg2); +/* + * @brief + * result = arg1 + arg2 + */ +struct fixed31_32 dal_fixed31_32_add_int( + struct fixed31_32 arg1, + int32_t arg2); + /* * @brief * result = arg1 - arg2 -- cgit From 7a1c37e00a660b380fe258fed54fd5af6735814e Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Thu, 12 Jan 2017 14:24:11 -0500 Subject: drm/amd/display: Disable Modules at Runtime Add NULL check in modules Signed-off-by: Anthony Koo Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- .../drm/amd/display/modules/freesync/freesync.c | 94 +++++++++++++++------- .../gpu/drm/amd/display/modules/inc/mod_freesync.h | 7 -- 2 files changed, 65 insertions(+), 36 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index 6f4d169f4e4e..e0703c588e47 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -205,11 +205,16 @@ static unsigned int map_index_from_stream(struct core_freesync *core_freesync, bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, const struct dc_stream *stream, struct mod_freesync_caps *caps) { - struct core_freesync *core_freesync = - MOD_FREESYNC_TO_CORE(mod_freesync); - struct core_stream *core_stream = - DC_STREAM_TO_CORE(stream); - struct core_dc *core_dc = DC_TO_CORE(core_freesync->dc); + struct core_stream *core_stream = NULL; + struct core_dc *core_dc = NULL; + struct core_freesync *core_freesync = NULL; + + if (mod_freesync == NULL) + return false; + + core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync); + core_stream = DC_STREAM_TO_CORE(stream); + core_dc = DC_TO_CORE(core_freesync->dc); int persistent_freesync_enable = 0; struct persistent_data_flag flag; @@ -270,11 +275,16 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, bool mod_freesync_remove_stream(struct mod_freesync *mod_freesync, const struct dc_stream *stream) { - struct core_freesync *core_freesync = - MOD_FREESYNC_TO_CORE(mod_freesync); - int i = 0; - unsigned int index = map_index_from_stream(core_freesync, stream); + struct core_freesync *core_freesync = NULL; + unsigned int index = 0; + + if (mod_freesync == NULL) + return false; + + core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync); + index = map_index_from_stream(core_freesync, stream); + dc_stream_release(core_freesync->map[index].stream); core_freesync->map[index].stream = NULL; /* To remove this entity, shift everything after down */ @@ -621,11 +631,14 @@ static void set_static_ramp_variables(struct core_freesync *core_freesync, void mod_freesync_handle_v_update(struct mod_freesync *mod_freesync, const struct dc_stream **streams, int num_streams) { - struct core_freesync *core_freesync = - MOD_FREESYNC_TO_CORE(mod_freesync); - unsigned int index, v_total = 0; struct freesync_state *state; + struct core_freesync *core_freesync = NULL; + + if (mod_freesync == NULL) + return; + + core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync); if (core_freesync->num_entities == 0) return; @@ -691,11 +704,15 @@ void mod_freesync_update_state(struct mod_freesync *mod_freesync, const struct dc_stream **streams, int num_streams, struct mod_freesync_params *freesync_params) { - struct core_freesync *core_freesync = - MOD_FREESYNC_TO_CORE(mod_freesync); bool freesync_program_required = false; unsigned int stream_index; struct freesync_state *state; + struct core_freesync *core_freesync = NULL; + + if (mod_freesync == NULL) + return; + + core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync); if (core_freesync->num_entities == 0) return; @@ -762,10 +779,14 @@ bool mod_freesync_get_state(struct mod_freesync *mod_freesync, const struct dc_stream *stream, struct mod_freesync_params *freesync_params) { - struct core_freesync *core_freesync = - MOD_FREESYNC_TO_CORE(mod_freesync); + unsigned int index = NULL; + struct core_freesync *core_freesync = NULL; - unsigned int index = map_index_from_stream(core_freesync, stream); + if (mod_freesync == NULL) + return false; + + core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync); + index = map_index_from_stream(core_freesync, stream); if (core_freesync->map[index].state.fullscreen) { freesync_params->state = FREESYNC_STATE_FULLSCREEN; @@ -794,13 +815,17 @@ bool mod_freesync_set_user_enable(struct mod_freesync *mod_freesync, const struct dc_stream **streams, int num_streams, struct mod_freesync_user_enable *user_enable) { - struct core_freesync *core_freesync = - MOD_FREESYNC_TO_CORE(mod_freesync); - struct core_dc *core_dc = DC_TO_CORE(core_freesync->dc); - unsigned int stream_index, map_index; int persistent_data = 0; struct persistent_data_flag flag; + struct core_dc *core_dc = NULL; + struct core_freesync *core_freesync = NULL; + + if (mod_freesync == NULL) + return false; + + core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync); + core_dc = DC_TO_CORE(core_freesync->dc); flag.save_per_edid = true; flag.save_per_link = false; @@ -842,10 +867,14 @@ bool mod_freesync_get_user_enable(struct mod_freesync *mod_freesync, const struct dc_stream *stream, struct mod_freesync_user_enable *user_enable) { - struct core_freesync *core_freesync = - MOD_FREESYNC_TO_CORE(mod_freesync); + unsigned int index = 0; + struct core_freesync *core_freesync = NULL; - unsigned int index = map_index_from_stream(core_freesync, stream); + if (mod_freesync == NULL) + return false; + + core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync); + index = map_index_from_stream(core_freesync, stream); *user_enable = core_freesync->map[index].user_enable; @@ -855,12 +884,15 @@ bool mod_freesync_get_user_enable(struct mod_freesync *mod_freesync, void mod_freesync_notify_mode_change(struct mod_freesync *mod_freesync, const struct dc_stream **streams, int num_streams) { - struct core_freesync *core_freesync = - MOD_FREESYNC_TO_CORE(mod_freesync); - unsigned int stream_index, map_index; unsigned min_frame_duration_in_ns, max_frame_duration_in_ns; struct freesync_state *state; + struct core_freesync *core_freesync = NULL; + + if (mod_freesync == NULL) + return; + + core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync); for (stream_index = 0; stream_index < num_streams; stream_index++) { @@ -1121,8 +1153,12 @@ void mod_freesync_pre_update_plane_addresses(struct mod_freesync *mod_freesync, unsigned int curr_time_stamp_in_us) { unsigned int stream_index, map_index, last_render_time_in_us = 0; - struct core_freesync *core_freesync = - MOD_FREESYNC_TO_CORE(mod_freesync); + struct core_freesync *core_freesync = NULL; + + if (mod_freesync == NULL) + return; + + core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync); for (stream_index = 0; stream_index < num_streams; stream_index++) { diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h b/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h index 7abfe34dc2d9..783ff2ef3bee 100644 --- a/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h +++ b/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h @@ -109,13 +109,6 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, bool mod_freesync_remove_stream(struct mod_freesync *mod_freesync, const struct dc_stream *stream); -/* - * Build additional parameters for dc_stream when creating stream for - * sink to support freesync - */ -void mod_freesync_update_stream(struct mod_freesync *mod_freesync, - struct dc_stream *stream); - /* * Update the freesync state flags for each display and program * freesync accordingly -- cgit From cc0cb445ae56890a322abe2cc8df63b1ccab74fb Mon Sep 17 00:00:00 2001 From: Leon Elazar Date: Wed, 11 Jan 2017 14:33:36 -0500 Subject: drm/amd/display: Fixing some fallout from dc_target removal Also avoid allocating memory dce110_set_output_transfer_func if not needed Signed-off-by: Leon Elazar Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 6 +++-- drivers/gpu/drm/amd/display/dc/dce/dce_opp.c | 7 +++++ .../amd/display/dc/dce110/dce110_hw_sequencer.c | 30 +++++----------------- .../amd/display/dc/dce110/dce110_opp_regamma_v.c | 7 +++++ .../gpu/drm/amd/display/dc/dce110/dce110_opp_v.c | 6 ++++- .../gpu/drm/amd/display/dc/dce110/dce110_opp_v.h | 4 +++ .../drm/amd/display/dc/dce110/dce110_resource.c | 17 +++++++++--- drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h | 1 - drivers/gpu/drm/amd/display/dc/inc/hw/opp.h | 1 + 9 files changed, 49 insertions(+), 30 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index bc1f387d1992..47816c5ee0e0 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -192,7 +192,8 @@ bool dc_stream_set_cursor_attributes( for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; - if (pipe_ctx->stream == stream) { + if ((pipe_ctx->stream == stream) && + (pipe_ctx->ipp != NULL)) { struct input_pixel_processor *ipp = pipe_ctx->ipp; if (ipp->funcs->ipp_cursor_set_attributes( @@ -231,7 +232,8 @@ bool dc_stream_set_cursor_position( for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; - if (pipe_ctx->stream == stream) { + if ((pipe_ctx->stream == stream) && + (pipe_ctx->ipp != NULL)) { struct input_pixel_processor *ipp = pipe_ctx->ipp; struct dc_cursor_mi_param param = { .pixel_clk_khz = dc_stream->timing.pix_clk_khz, diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c index 167f523df657..061de9e8249d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c @@ -973,6 +973,10 @@ bool dce110_opp_construct(struct dce110_opp *opp110, opp110->base.inst = inst; + opp110->base.regamma_params = dm_alloc(sizeof(struct pwl_params)); + if (opp110->base.regamma_params == NULL) + return false; + opp110->regs = regs; opp110->opp_shift = opp_shift; opp110->opp_mask = opp_mask; @@ -982,6 +986,9 @@ bool dce110_opp_construct(struct dce110_opp *opp110, void dce110_opp_destroy(struct output_pixel_processor **opp) { + dm_free((*opp)->regamma_params); + (*opp)->regamma_params = NULL; + dm_free(FROM_DCE11_OPP(*opp)); *opp = NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 6e70cf7b99ef..1a9ba127b781 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -721,43 +721,27 @@ static bool dce110_set_output_transfer_func( const struct core_stream *stream) { struct output_pixel_processor *opp = pipe_ctx->opp; - const struct core_gamma *ramp = NULL; - struct pwl_params *regamma_params; - bool result = false; - - if (surface->public.gamma_correction) - ramp = DC_GAMMA_TO_CORE(surface->public.gamma_correction); - - regamma_params = dm_alloc(sizeof(struct pwl_params)); - if (regamma_params == NULL) - goto regamma_alloc_fail; - - regamma_params->hw_points_num = GAMMA_HW_POINTS_NUM; opp->funcs->opp_power_on_regamma_lut(opp, true); + opp->regamma_params->hw_points_num = GAMMA_HW_POINTS_NUM; if (stream->public.out_transfer_func && - stream->public.out_transfer_func->type == + stream->public.out_transfer_func->type == TF_TYPE_PREDEFINED && - stream->public.out_transfer_func->tf == + stream->public.out_transfer_func->tf == TRANSFER_FUNCTION_SRGB) { opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_SRGB); } else if (dce110_translate_regamma_to_hw_format( - stream->public.out_transfer_func, regamma_params)) { - opp->funcs->opp_program_regamma_pwl(opp, regamma_params); - opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_USER); + stream->public.out_transfer_func, opp->regamma_params)) { + opp->funcs->opp_program_regamma_pwl(opp, opp->regamma_params); + opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_USER); } else { opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_BYPASS); } opp->funcs->opp_power_on_regamma_lut(opp, false); - result = true; - - dm_free(regamma_params); - -regamma_alloc_fail: - return result; + return true; } static enum dc_status bios_parser_crtc_source_select( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c index 8164aa6bcb00..876445f14c85 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c @@ -548,3 +548,10 @@ void dce110_opp_power_on_regamma_lut_v( dm_write_reg(opp->ctx, mmDCFEV_MEM_PWR_CTRL, value); } + +void dce110_opp_set_regamma_mode_v( + struct output_pixel_processor *opp, + enum opp_regamma mode) +{ + // TODO: need to implement the function +} diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c index 0a9b384303d0..95b3d2eb8428 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c @@ -42,7 +42,7 @@ static const struct opp_funcs funcs = { .opp_set_csc_default = dce110_opp_v_set_csc_default, .opp_set_csc_adjustment = dce110_opp_v_set_csc_adjustment, .opp_set_dyn_expansion = dce110_opp_set_dyn_expansion, - .opp_set_regamma_mode = dce110_opp_set_regamma_mode, + .opp_set_regamma_mode = dce110_opp_set_regamma_mode_v, .opp_destroy = dce110_opp_destroy, .opp_program_fmt = dce110_opp_program_fmt, .opp_program_bit_depth_reduction = @@ -56,6 +56,10 @@ bool dce110_opp_v_construct(struct dce110_opp *opp110, opp110->base.ctx = ctx; + opp110->base.regamma_params = dm_alloc(sizeof(struct pwl_params)); + if (opp110->base.regamma_params == NULL) + return false; + return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h index ac5937786ce3..cb26c515d30f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h @@ -49,4 +49,8 @@ void dce110_opp_power_on_regamma_lut_v( struct output_pixel_processor *opp, bool power_on); +void dce110_opp_set_regamma_mode_v( + struct output_pixel_processor *opp, + enum opp_regamma mode); + #endif /* __DC_OPP_DCE110_V_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index cfbb4ef21f8b..82cddb6425a0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -1114,14 +1114,22 @@ static const struct resource_funcs dce110_res_pool_funcs = { dce110_resource_build_bit_depth_reduction_params }; -static void underlay_create(struct dc_context *ctx, struct resource_pool *pool) +static bool underlay_create(struct dc_context *ctx, struct resource_pool *pool) { struct dce110_timing_generator *dce110_tgv = dm_alloc(sizeof (*dce110_tgv)); struct dce_transform *dce110_xfmv = dm_alloc(sizeof (*dce110_xfmv)); struct dce110_mem_input *dce110_miv = dm_alloc(sizeof (*dce110_miv)); struct dce110_opp *dce110_oppv = dm_alloc(sizeof (*dce110_oppv)); - dce110_opp_v_construct(dce110_oppv, ctx); + if ((dce110_tgv == NULL) || + (dce110_xfmv == NULL) || + (dce110_miv == NULL) || + (dce110_oppv == NULL)) + return false; + + if (!dce110_opp_v_construct(dce110_oppv, ctx)) + return false; + dce110_timing_generator_v_construct(dce110_tgv, ctx); dce110_mem_input_v_construct(dce110_miv, ctx); dce110_transform_v_construct(dce110_xfmv, ctx); @@ -1135,6 +1143,8 @@ static void underlay_create(struct dc_context *ctx, struct resource_pool *pool) /* update the public caps to indicate an underlay is available */ ctx->dc->caps.max_slave_planes = 1; ctx->dc->caps.max_slave_planes = 1; + + return true; } static void bw_calcs_data_update_from_pplib(struct core_dc *dc) @@ -1334,7 +1344,8 @@ static bool construct( } } - underlay_create(ctx, &pool->base); + if (!underlay_create(ctx, &pool->base)) + goto res_create_fail; if (!resource_construct(num_virtual_links, dc, &pool->base, &res_create_funcs)) diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h index 3b0e616f7066..b8735b27e9bc 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h @@ -65,7 +65,6 @@ struct pwl_result_data { }; struct pwl_params { - uint32_t *data; struct gamma_curve arr_curve_points[16]; struct curve_points arr_points[3]; struct pwl_result_data rgb_resulted[256 + 3]; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h index bef5e2cacbe3..a10c4e296960 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h @@ -202,6 +202,7 @@ enum opp_regamma { struct output_pixel_processor { struct dc_context *ctx; uint32_t inst; + struct pwl_params *regamma_params; const struct opp_funcs *funcs; }; -- cgit From 721d30cf8363247c0c6cb44514e88a5811151c01 Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Fri, 13 Jan 2017 10:10:26 -0500 Subject: drm/amd/display: No audio output heard from DP panel Signed-off-by: Hersen Wu Acked-by: Harry Wentland Reviewed-by: Eagle Yeh Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_audio.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.h b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.h index bf97cd8c8221..c244887ba15e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.h @@ -50,8 +50,8 @@ SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO_SEL, mask_sh),\ SF(DCCG_AUDIO_DTO0_MODULE, DCCG_AUDIO_DTO0_MODULE, mask_sh),\ SF(DCCG_AUDIO_DTO0_PHASE, DCCG_AUDIO_DTO0_PHASE, mask_sh),\ - SF(DCCG_AUDIO_DTO0_MODULE, DCCG_AUDIO_DTO0_MODULE, mask_sh),\ - SF(DCCG_AUDIO_DTO0_PHASE, DCCG_AUDIO_DTO0_PHASE, mask_sh),\ + SF(DCCG_AUDIO_DTO1_MODULE, DCCG_AUDIO_DTO1_MODULE, mask_sh),\ + SF(DCCG_AUDIO_DTO1_PHASE, DCCG_AUDIO_DTO1_PHASE, mask_sh),\ SF(AZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES, AUDIO_RATE_CAPABILITIES, mask_sh),\ SF(AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES, CLKSTOP, mask_sh),\ SF(AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES, EPSS, mask_sh) -- cgit From 858058da47a557b6c0211830d530045c1c8e62ab Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Wed, 9 Nov 2016 05:41:51 -0500 Subject: drm/amd/display: Use pflip prepare and submit parts (v2) Use new functions so flip failures can be gracefully handled v2: Avoid -EINVAL returned from amdgpu_crtc_prepare_flip in some error cases, it is not allowed according to expected return values for atomic_commit hook. Signed-off-by: Andrey Grodzovsky Acked-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index c32fc6d26088..ad08d6f7f094 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2267,7 +2267,6 @@ int amdgpu_dm_atomic_commit( uint32_t flip_crtcs_count = 0; struct drm_crtc *crtc; struct drm_crtc_state *old_crtc_state; - const struct dc_stream *commit_streams[MAX_STREAMS]; struct amdgpu_crtc *new_crtcs[MAX_STREAMS]; const struct dc_stream *new_stream; -- cgit From f84a8161cb1652281746d113667427dbbf8bd5db Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Thu, 12 Jan 2017 23:18:33 -0500 Subject: drm/amd/display: mode change without breaking unaffected streams - include clock constraint logic in validate - in dc_commit_streams, include surfaces of unaffected streams Signed-off-by: Yongqiang Sun Acked-by: Harry Wentland Reviewed-by: Dmytro Laktyushkin Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 11 +++++++++-- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/inc/core_status.h | 2 ++ 3 files changed, 12 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 948f82a56472..9deddc8ee2d1 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1007,7 +1007,7 @@ bool dc_commit_streams( struct dc_bios *dcb = core_dc->ctx->dc_bios; enum dc_status result = DC_ERROR_UNEXPECTED; struct validate_context *context; - struct dc_validation_set set[MAX_STREAMS]; + struct dc_validation_set set[MAX_STREAMS] = { 0 }; int i, j, k; if (false == streams_changed(core_dc, streams, stream_count)) @@ -1018,13 +1018,20 @@ bool dc_commit_streams( for (i = 0; i < stream_count; i++) { const struct dc_stream *stream = streams[i]; + const struct dc_stream_status *status = dc_stream_get_status(stream); + int j; dc_stream_log(stream, core_dc->ctx->logger, LOG_DC); set[i].stream = stream; - set[i].surface_count = 0; + + if (status) { + set[i].surface_count = status->surface_count; + for (j = 0; j < status->surface_count; j++) + set[i].surfaces[j] = status->surfaces[j]; + } } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 1f87b948678b..6037ee25598c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -585,7 +585,7 @@ enum dc_status resource_build_scaling_params_for_context( if (!resource_build_scaling_params( &context->res_ctx.pipe_ctx[i].surface->public, &context->res_ctx.pipe_ctx[i])) - return DC_FAIL_BANDWIDTH_VALIDATE; + return DC_FAIL_SCALING; } return DC_OK; diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_status.h b/drivers/gpu/drm/amd/display/dc/inc/core_status.h index 32a2cc712000..147eb7cac701 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_status.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_status.h @@ -40,6 +40,8 @@ enum dc_status { DC_EXCEED_DONGLE_MAX_CLK, DC_SURFACE_PIXEL_FORMAT_UNSUPPORTED, DC_FAIL_BANDWIDTH_VALIDATE, /* BW and Watermark validation */ + DC_FAIL_SCALING, + DC_FAIL_CLK_CONSTRAINT, DC_ERROR_UNEXPECTED = -1 }; -- cgit From bf72726358adfedcf1c268690521891809332151 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Sat, 14 Jan 2017 01:44:52 -0500 Subject: drm/amd/display: assert if mask is 0 in set_reg_field_value_ex - mask = 0 means something is wrong in caller and no register field will be updated Signed-off-by: Tony Cheng Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dm_services.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dm_services.h b/drivers/gpu/drm/amd/display/dc/dm_services.h index 11a0abfd3418..052a43af1bd3 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services.h @@ -165,6 +165,7 @@ static inline uint32_t set_reg_field_value_ex( uint32_t mask, uint8_t shift) { + ASSERT(mask != 0); return (reg_value & ~mask) | (mask & (value << shift)); } -- cgit From ac0e562c521228215d597fe3ef0c13f02077f700 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Sat, 14 Jan 2017 11:46:53 -0500 Subject: drm/amd/display: remove un-used defines and dead code Signed-off-by: Tony Cheng Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/basics/signal_types.c | 35 ------- .../gpu/drm/amd/display/dc/bios/command_table.c | 55 ---------- .../gpu/drm/amd/display/dc/bios/command_table.h | 3 - drivers/gpu/drm/amd/display/dc/core/dc_link.c | 1 - drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 2 +- .../display/include/asic_capability_interface.h | 55 ---------- .../amd/display/include/asic_capability_types.h | 116 --------------------- .../drm/amd/display/include/bios_parser_types.h | 8 -- .../drm/amd/display/include/ddc_service_types.h | 7 -- .../gpu/drm/amd/display/include/irq_interface.h | 31 ------ .../drm/amd/display/include/link_service_types.h | 75 ------------- drivers/gpu/drm/amd/display/include/signal_types.h | 3 - 12 files changed, 1 insertion(+), 390 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/include/asic_capability_interface.h delete mode 100644 drivers/gpu/drm/amd/display/include/asic_capability_types.h delete mode 100644 drivers/gpu/drm/amd/display/include/irq_interface.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/basics/signal_types.c b/drivers/gpu/drm/amd/display/dc/basics/signal_types.c index 44447e07803a..247487c3db71 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/signal_types.c +++ b/drivers/gpu/drm/amd/display/dc/basics/signal_types.c @@ -44,23 +44,6 @@ bool dc_is_dp_signal(enum signal_type signal) signal == SIGNAL_TYPE_DISPLAY_PORT_MST); } -bool dc_is_dp_external_signal(enum signal_type signal) -{ - return (signal == SIGNAL_TYPE_DISPLAY_PORT || - signal == SIGNAL_TYPE_DISPLAY_PORT_MST); -} - -bool dc_is_analog_signal(enum signal_type signal) -{ - switch (signal) { - case SIGNAL_TYPE_RGB: - return true; - break; - default: - return false; - } -} - bool dc_is_embedded_signal(enum signal_type signal) { return (signal == SIGNAL_TYPE_EDP || signal == SIGNAL_TYPE_LVDS); @@ -96,21 +79,3 @@ bool dc_is_audio_capable_signal(enum signal_type signal) signal == SIGNAL_TYPE_WIRELESS); } -/* - * @brief - * Returns whether the signal is compatible - * with other digital encoder signal types. - * This is true for DVI, LVDS, and HDMI signal types. - */ -bool dc_is_digital_encoder_compatible_signal(enum signal_type signal) -{ - switch (signal) { - case SIGNAL_TYPE_DVI_SINGLE_LINK: - case SIGNAL_TYPE_DVI_DUAL_LINK: - case SIGNAL_TYPE_HDMI_TYPE_A: - case SIGNAL_TYPE_LVDS: - return true; - default: - return false; - } -} diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table.c b/drivers/gpu/drm/amd/display/dc/bios/command_table.c index d0eedb6235fe..88aaf53cb8c4 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table.c @@ -56,7 +56,6 @@ static void init_dac_encoder_control(struct bios_parser *bp); static void init_dac_output_control(struct bios_parser *bp); static void init_blank_crtc(struct bios_parser *bp); static void init_set_crtc_timing(struct bios_parser *bp); -static void init_set_crtc_overscan(struct bios_parser *bp); static void init_select_crtc_source(struct bios_parser *bp); static void init_enable_crtc(struct bios_parser *bp); static void init_enable_crtc_mem_req(struct bios_parser *bp); @@ -77,7 +76,6 @@ void dal_bios_parser_init_cmd_tbl(struct bios_parser *bp) init_dac_output_control(bp); init_blank_crtc(bp); init_set_crtc_timing(bp); - init_set_crtc_overscan(bp); init_select_crtc_source(bp); init_enable_crtc(bp); init_enable_crtc_mem_req(bp); @@ -1931,59 +1929,6 @@ static enum bp_result set_crtc_using_dtd_timing_v3( return result; } -/******************************************************************************* - ******************************************************************************** - ** - ** SET CRTC OVERSCAN - ** - ******************************************************************************** - *******************************************************************************/ - -static enum bp_result set_crtc_overscan_v1( - struct bios_parser *bp, - struct bp_hw_crtc_overscan_parameters *bp_params); - -static void init_set_crtc_overscan(struct bios_parser *bp) -{ - switch (BIOS_CMD_TABLE_PARA_REVISION(SetCRTC_OverScan)) { - case 1: - bp->cmd_tbl.set_crtc_overscan = set_crtc_overscan_v1; - break; - default: - bp->cmd_tbl.set_crtc_overscan = NULL; - break; - } -} - -static enum bp_result set_crtc_overscan_v1( - struct bios_parser *bp, - struct bp_hw_crtc_overscan_parameters *bp_params) -{ - enum bp_result result = BP_RESULT_FAILURE; - SET_CRTC_OVERSCAN_PARAMETERS params = {0}; - uint8_t atom_controller_id; - - if (bp->cmd_helper->controller_id_to_atom( - bp_params->controller_id, &atom_controller_id)) - params.ucCRTC = atom_controller_id; - else - return BP_RESULT_BADINPUT; - - params.usOverscanRight = - cpu_to_le16((uint16_t)bp_params->h_overscan_right); - params.usOverscanLeft = - cpu_to_le16((uint16_t)bp_params->h_overscan_left); - params.usOverscanBottom = - cpu_to_le16((uint16_t)bp_params->v_overscan_bottom); - params.usOverscanTop = - cpu_to_le16((uint16_t)bp_params->v_overscan_top); - - if (EXEC_BIOS_CMD_TABLE(SetCRTC_OverScan, params)) - result = BP_RESULT_OK; - - return result; -} - /******************************************************************************* ******************************************************************************** ** diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table.h b/drivers/gpu/drm/amd/display/dc/bios/command_table.h index e1cd21b6e968..b8e6ef06c0c7 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table.h +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table.h @@ -75,9 +75,6 @@ struct cmd_tbl { enum bp_result (*set_crtc_timing)( struct bios_parser *bp, struct bp_hw_crtc_timing_parameters *bp_params); - enum bp_result (*set_crtc_overscan)( - struct bios_parser *bp, - struct bp_hw_crtc_overscan_parameters *bp_params); enum bp_result (*select_crtc_source)( struct bios_parser *bp, struct bp_crtc_source_select *bp_params); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index b0f316344e86..62cfc5cbe773 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -38,7 +38,6 @@ #include "hw_sequencer.h" #include "resource.h" #include "fixed31_32.h" -#include "include/asic_capability_interface.h" #include "dpcd_defs.h" #include "dce/dce_11_0_d.h" 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 a661fc6a69dd..c9c1b48df384 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 @@ -1922,7 +1922,7 @@ static void get_active_converter_info( break; } - if (link->dpcd_caps.dpcd_rev.raw >= DCS_DPCD_REV_11) { + if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_11) { uint8_t det_caps[4]; union dwnstream_port_caps_byte0 *port_caps = (union dwnstream_port_caps_byte0 *)det_caps; diff --git a/drivers/gpu/drm/amd/display/include/asic_capability_interface.h b/drivers/gpu/drm/amd/display/include/asic_capability_interface.h deleted file mode 100644 index 57cc72fdc560..000000000000 --- a/drivers/gpu/drm/amd/display/include/asic_capability_interface.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of enc software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and enc permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DAL_ASIC_CAPABILITY_INTERFACE_H__ -#define __DAL_ASIC_CAPABILITY_INTERFACE_H__ - -/* Include */ -#include "include/asic_capability_types.h" - -/* Forward declaration */ -struct hw_asic_id; - -/* ASIC capability */ -struct asic_capability { - struct dc_context *ctx; - struct asic_caps caps; - struct asic_stereo_3d_caps stereo_3d_caps; - struct asic_bugs bugs; - uint32_t data[ASIC_DATA_MAX_NUMBER]; -}; - -/** - * Interfaces - */ - -/* Create and initialize ASIC capability */ -struct asic_capability *dal_asic_capability_create(struct hw_asic_id *init, - struct dc_context *ctx); - -/* Destroy ASIC capability and free memory space */ -void dal_asic_capability_destroy(struct asic_capability **cap); - -#endif /* __DAL_ASIC_CAPABILITY_INTERFACE_H__ */ diff --git a/drivers/gpu/drm/amd/display/include/asic_capability_types.h b/drivers/gpu/drm/amd/display/include/asic_capability_types.h deleted file mode 100644 index c44dae043599..000000000000 --- a/drivers/gpu/drm/amd/display/include/asic_capability_types.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ -#ifndef __DAL_ASIC_CAPABILITY_TYPES_H__ -#define __DAL_ASIC_CAPABILITY_TYPES_H__ - -/* - * ASIC Capabilities - */ -struct asic_caps { - bool CONSUMER_SINGLE_SELECTED_TIMING:1; - bool UNDERSCAN_ADJUST:1; - bool DELTA_SIGMA_SUPPORT:1; - bool PANEL_SELF_REFRESH_SUPPORTED:1; - bool IS_FUSION:1; - bool DP_MST_SUPPORTED:1; - bool UNDERSCAN_FOR_HDMI_ONLY:1; - bool DVI_CLOCK_SHARE_CAPABILITY:1; - bool SUPPORT_CEA861E_FINAL:1; - bool MIRABILIS_SUPPORTED:1; - bool MIRABILIS_ENABLED_BY_DEFAULT:1; - bool DEVICE_TAG_REMAP_SUPPORTED:1; - bool HEADLESS_NO_OPM_SUPPORTED:1; - bool WIRELESS_LIMIT_TO_720P:1; - bool WIRELESS_FULL_TIMING_ADJUSTMENT:1; - bool WIRELESS_TIMING_ADJUSTMENT:1; - bool WIRELESS_COMPRESSED_AUDIO:1; - bool VCE_SUPPORTED:1; - bool HPD_CHECK_FOR_EDID:1; - bool NEED_MC_TUNING:1; - bool SKIP_PSR_WAIT_FOR_PLL_LOCK_BIT:1; - bool DFSBYPASS_DYNAMIC_SUPPORT:1; - bool SUPPORT_8BPP:1; -}; - -/* - * ASIC Stereo 3D Caps - */ -struct asic_stereo_3d_caps { - bool SUPPORTED:1; - bool DISPLAY_BASED_ON_WS:1; - bool HDMI_FRAME_PACK:1; - bool INTERLACE_FRAME_PACK:1; - bool DISPLAYPORT_FRAME_PACK:1; - bool DISPLAYPORT_FRAME_ALT:1; - bool INTERLEAVE:1; -}; - -/* - * ASIC Bugs - */ -struct asic_bugs { - bool MST_SYMBOL_MISALIGNMENT:1; - bool PSR_2X_LANE_GANGING:1; - bool LB_WA_IS_SUPPORTED:1; - bool ROM_REGISTER_ACCESS:1; - bool PSR_WA_OVERSCAN_CRC_ERROR:1; -}; - -/* - * ASIC Data - */ -enum asic_data { - ASIC_DATA_FIRST = 0, - ASIC_DATA_DCE_VERSION = ASIC_DATA_FIRST, - ASIC_DATA_DCE_VERSION_MINOR, - ASIC_DATA_LINEBUFFER_SIZE, - ASIC_DATA_DRAM_BANDWIDTH_EFFICIENCY, - ASIC_DATA_MC_LATENCY, - ASIC_DATA_MC_LATENCY_SLOW, - ASIC_DATA_MEMORYTYPE_MULTIPLIER, - ASIC_DATA_PATH_NUM_PER_DPMST_CONNECTOR, - ASIC_DATA_MAX_UNDERSCAN_PERCENTAGE, - ASIC_DATA_VIEWPORT_PIXEL_GRANULARITY, - ASIC_DATA_MIN_DISPCLK_FOR_UNDERSCAN, - ASIC_DATA_DOWNSCALE_LIMIT, - ASIC_DATA_MAX_NUMBER /* end of enum */ -}; - -/* - * ASIC Feature Flags - */ -struct asic_feature_flags { - union { - uint32_t raw; - struct { - uint32_t LEGACY_CLIENT:1; - uint32_t PACKED_PIXEL_FORMAT:1; - uint32_t WORKSTATION_STEREO:1; - uint32_t WORKSTATION:1; - } bits; - }; -}; - -#endif /* __DAL_ASIC_CAPABILITY_TYPES_H__ */ diff --git a/drivers/gpu/drm/amd/display/include/bios_parser_types.h b/drivers/gpu/drm/amd/display/include/bios_parser_types.h index 9ab9065735f7..7de4fa5a0726 100644 --- a/drivers/gpu/drm/amd/display/include/bios_parser_types.h +++ b/drivers/gpu/drm/amd/display/include/bios_parser_types.h @@ -190,14 +190,6 @@ struct bp_hw_crtc_timing_parameters { } flags; }; -struct bp_hw_crtc_overscan_parameters { - enum controller_id controller_id; - uint32_t h_overscan_left; - uint32_t h_overscan_right; - uint32_t v_overscan_top; - uint32_t v_overscan_bottom; -}; - struct bp_adjust_pixel_clock_parameters { /* Input: Signal Type - to be converted to Encoder mode */ enum signal_type signal_type; diff --git a/drivers/gpu/drm/amd/display/include/ddc_service_types.h b/drivers/gpu/drm/amd/display/include/ddc_service_types.h index 0a6ba91e3eba..effe03b8f418 100644 --- a/drivers/gpu/drm/amd/display/include/ddc_service_types.h +++ b/drivers/gpu/drm/amd/display/include/ddc_service_types.h @@ -52,12 +52,6 @@ enum ddc_service_type { DDC_SERVICE_TYPE_DISPLAY_PORT_MST, }; -enum dcs_dpcd_revision { - DCS_DPCD_REV_10 = 0x10, - DCS_DPCD_REV_11 = 0x11, - DCS_DPCD_REV_12 = 0x12 -}; - /** * display sink capability */ @@ -97,7 +91,6 @@ struct display_sink_capability { uint32_t dp_link_rate; uint32_t dp_link_spead; - enum dcs_dpcd_revision dpcd_revision; /* If dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER, indicates 'Frame Sequential-to-lllFrame Pack' conversion capability.*/ bool is_dp_hdmi_s3d_converter; diff --git a/drivers/gpu/drm/amd/display/include/irq_interface.h b/drivers/gpu/drm/amd/display/include/irq_interface.h deleted file mode 100644 index 077ded3fbedd..000000000000 --- a/drivers/gpu/drm/amd/display/include/irq_interface.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DAL_IRQ_INTERFACE_H__ -#define __DAL_IRQ_INTERFACE_H__ - -#include "gpio_types.h" - -#endif diff --git a/drivers/gpu/drm/amd/display/include/link_service_types.h b/drivers/gpu/drm/amd/display/include/link_service_types.h index 6160a467ba37..479e5fff8a00 100644 --- a/drivers/gpu/drm/amd/display/include/link_service_types.h +++ b/drivers/gpu/drm/amd/display/include/link_service_types.h @@ -38,34 +38,11 @@ enum { MAX_CONTROLLER_NUM = 6 }; -enum link_service_type { - LINK_SERVICE_TYPE_LEGACY = 0, - LINK_SERVICE_TYPE_DP_SST, - LINK_SERVICE_TYPE_DP_MST, - LINK_SERVICE_TYPE_MAX -}; - -enum dpcd_value_mask { - DPCD_VALUE_MASK_MAX_LANE_COUNT_LANE_COUNT = 0x1F, - DPCD_VALUE_MASK_MAX_LANE_COUNT_TPS3_SUPPORTED = 0x40, - DPCD_VALUE_MASK_MAX_LANE_COUNT_ENHANCED_FRAME_EN = 0x80, - DPCD_VALUE_MASK_MAX_DOWNSPREAD = 0x01, - DPCD_VALUE_MASK_LANE_ALIGN_STATUS_INTERLANE_ALIGN_DONE = 0x01 -}; - enum dp_power_state { DP_POWER_STATE_D0 = 1, DP_POWER_STATE_D3 }; -enum dpcd_downstream_port_types { - DPCD_DOWNSTREAM_DP, - DPCD_DOWNSTREAM_VGA, - DPCD_DOWNSTREAM_DVI_HDMI, - /* has no EDID (TV, CV) */ - DPCD_DOWNSTREAM_NON_DDC -}; - enum edp_revision { /* eDP version 1.1 or lower */ EDP_REVISION_11 = 0x00, @@ -135,36 +112,6 @@ enum dp_panel_mode { DP_PANEL_MODE_SPECIAL }; -/** - * @brief LinkServiceInitOptions to set certain bits - */ -struct link_service_init_options { - uint32_t APPLY_MISALIGNMENT_BUG_WORKAROUND:1; -}; - -/** - * @brief data required to initialize LinkService - */ -struct link_service_init_data { - /* number of displays indices which the MST Mgr would manange*/ - uint32_t num_of_displays; - enum link_service_type link_type; - /*struct mst_mgr_callback_object*topology_change_callback;*/ - /* native aux access */ - struct ddc_service *dpcd_access_srv; - /* for calling HWSS to program HW */ - struct hw_sequencer *hwss; - /* the source which to register IRQ on */ - enum dc_irq_source irq_src_hpd_rx; - enum dc_irq_source irq_src_dp_sink; - /* other init options such as SW Workarounds */ - struct link_service_init_options init_options; - uint32_t connector_enum_id; - struct graphics_object_id connector_id; - struct dc_context *ctx; - struct topology_mgr *tm; -}; - /* DPCD_ADDR_TRAINING_LANEx_SET registers value */ union dpcd_training_lane_set { struct { @@ -189,28 +136,6 @@ union dpcd_training_lane_set { uint8_t raw; }; -/** - * @brief represent the 16 byte - * global unique identifier - */ -struct mst_guid { - uint8_t ids[16]; -}; - -/** - * @brief represents the relative address used - * to identify a node in MST topology network - */ -struct mst_rad { - /* number of links. rad[0] up to - * rad [linkCount - 1] are valid. */ - uint32_t rad_link_count; - /* relative address. rad[0] is the - * first device connected to the source. */ - uint8_t rad[15]; - /* extra 10 bytes for underscores; for e.g.:2_1_8*/ - int8_t rad_str[25]; -}; /* DP MST stream allocation (payload bandwidth number) */ struct dp_mst_stream_allocation { diff --git a/drivers/gpu/drm/amd/display/include/signal_types.h b/drivers/gpu/drm/amd/display/include/signal_types.h index a50f7ed74a33..d87f84a56fcc 100644 --- a/drivers/gpu/drm/amd/display/include/signal_types.h +++ b/drivers/gpu/drm/amd/display/include/signal_types.h @@ -47,13 +47,10 @@ enum signal_type { bool dc_is_hdmi_signal(enum signal_type signal); bool dc_is_dp_sst_signal(enum signal_type signal); bool dc_is_dp_signal(enum signal_type signal); -bool dc_is_dp_external_signal(enum signal_type signal); -bool dc_is_analog_signal(enum signal_type signal); bool dc_is_embedded_signal(enum signal_type signal); bool dc_is_dvi_signal(enum signal_type signal); bool dc_is_dvi_single_link_signal(enum signal_type signal); bool dc_is_dual_link_signal(enum signal_type signal); bool dc_is_audio_capable_signal(enum signal_type signal); -bool dc_is_digital_encoder_compatible_signal(enum signal_type signal); #endif -- cgit From 6235b23cb92ba5bf30430400b216ea2114afe777 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Sat, 14 Jan 2017 18:57:57 -0500 Subject: drm/amd/display: remove hw_crtc_timing Signed-off-by: Tony Cheng Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dce/dce_stream_encoder.c | 2 +- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 2 +- .../gpu/drm/amd/display/dc/inc/hw/stream_encoder.h | 2 +- .../drm/amd/display/include/hw_sequencer_types.h | 40 ---------------------- 4 files changed, 3 insertions(+), 43 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c index c510e95eb948..7e6661bda970 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c @@ -681,7 +681,7 @@ static void dce110_stream_encoder_dp_unblank( uint64_t m_vid_l = n_vid; - m_vid_l *= param->crtc_timing.pixel_clock; + m_vid_l *= param->pixel_clk_khz; m_vid_l = div_u64(m_vid_l, param->link_settings.link_rate * LINK_RATE_REF_FREQ_IN_KHZ); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 1a9ba127b781..b51668e3bb52 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -886,7 +886,7 @@ void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, struct encoder_unblank_param params = { { 0 } }; /* only 3 items below are used by unblank */ - params.crtc_timing.pixel_clock = + params.pixel_clk_khz = pipe_ctx->stream->public.timing.pix_clk_khz; params.link_settings.link_rate = link_settings->link_rate; pipe_ctx->stream_enc->funcs->dp_unblank(pipe_ctx->stream_enc, ¶ms); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h index cb369af29d69..674bebfe3bd2 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h @@ -36,8 +36,8 @@ struct encoder_info_frame { }; struct encoder_unblank_param { - struct hw_crtc_timing crtc_timing; struct dc_link_settings link_settings; + unsigned int pixel_clk_khz; }; struct encoder_set_dp_phy_pattern_param { diff --git a/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h b/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h index 6bbca1b4d736..f99a03266149 100644 --- a/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h +++ b/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h @@ -40,46 +40,6 @@ struct drr_params { uint32_t vertical_total_max; }; -/* CRTC timing structure */ -struct hw_crtc_timing { - uint32_t h_total; - uint32_t h_addressable; - uint32_t h_overscan_left; - uint32_t h_overscan_right; - uint32_t h_sync_start; - uint32_t h_sync_width; - - uint32_t v_total; - uint32_t v_addressable; - uint32_t v_overscan_top; - uint32_t v_overscan_bottom; - uint32_t v_sync_start; - uint32_t v_sync_width; - - /* in KHz */ - uint32_t pixel_clock; - - struct { - uint32_t INTERLACED:1; - uint32_t DOUBLESCAN:1; - uint32_t PIXEL_REPETITION:4; /* 1...10 */ - uint32_t HSYNC_POSITIVE_POLARITY:1; - uint32_t VSYNC_POSITIVE_POLARITY:1; - /* frame should be packed for 3D - * (currently this refers to HDMI 1.4a FramePacking format */ - uint32_t HORZ_COUNT_BY_TWO:1; - uint32_t PACK_3D_FRAME:1; - /* 0 - left eye polarity, 1 - right eye polarity */ - uint32_t RIGHT_EYE_3D_POLARITY:1; - /* DVI-DL High-Color mode */ - uint32_t HIGH_COLOR_DL_MODE:1; - uint32_t Y_ONLY:1; - /* HDMI 2.0 - Support scrambling for TMDS character - * rates less than or equal to 340Mcsc */ - uint32_t LTE_340MCSC_SCRAMBLE:1; - } flags; -}; - /* TODO hw_info_frame and hw_info_packet structures are same as in encoder * merge it*/ struct hw_info_packet { -- cgit From 6e4d6beec6dae279ec7ac27c9034b2208898f382 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Sat, 14 Jan 2017 20:36:14 -0500 Subject: drm/amd/display: remove hw_info_frame - construct using encoder_info_frame directly Signed-off-by: Tony Cheng Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 124 +++++++-------------- .../drm/amd/display/include/hw_sequencer_types.h | 23 ---- 2 files changed, 40 insertions(+), 107 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 6037ee25598c..fe79a2890247 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1211,70 +1211,27 @@ void validate_guaranteed_copy_streams( } } -static void translate_info_frame(const struct hw_info_frame *hw_info_frame, - struct encoder_info_frame *encoder_info_frame) +static void patch_gamut_packet_checksum( + struct encoder_info_packet *gamut_packet) { - memset( - encoder_info_frame, 0, sizeof(struct encoder_info_frame)); - /* For gamut we recalc checksum */ - if (hw_info_frame->gamut_packet.valid) { + if (gamut_packet->valid) { uint8_t chk_sum = 0; uint8_t *ptr; uint8_t i; - memmove( - &encoder_info_frame->gamut, - &hw_info_frame->gamut_packet, - sizeof(struct hw_info_packet)); - /*start of the Gamut data. */ - ptr = &encoder_info_frame->gamut.sb[3]; + ptr = &gamut_packet->sb[3]; - for (i = 0; i <= encoder_info_frame->gamut.sb[1]; i++) + for (i = 0; i <= gamut_packet->sb[1]; i++) chk_sum += ptr[i]; - encoder_info_frame->gamut.sb[2] = (uint8_t) (0x100 - chk_sum); - } - - if (hw_info_frame->avi_info_packet.valid) { - memmove( - &encoder_info_frame->avi, - &hw_info_frame->avi_info_packet, - sizeof(struct hw_info_packet)); - } - - if (hw_info_frame->vendor_info_packet.valid) { - memmove( - &encoder_info_frame->vendor, - &hw_info_frame->vendor_info_packet, - sizeof(struct hw_info_packet)); - } - - if (hw_info_frame->spd_packet.valid) { - memmove( - &encoder_info_frame->spd, - &hw_info_frame->spd_packet, - sizeof(struct hw_info_packet)); - } - - if (hw_info_frame->vsc_packet.valid) { - memmove( - &encoder_info_frame->vsc, - &hw_info_frame->vsc_packet, - sizeof(struct hw_info_packet)); - } - - if (hw_info_frame->hdrsmd_packet.valid) { - memmove( - &encoder_info_frame->hdrsmd, - &hw_info_frame->hdrsmd_packet, - sizeof(struct hw_info_packet)); + gamut_packet->sb[2] = (uint8_t) (0x100 - chk_sum); } } static void set_avi_info_frame( - struct hw_info_packet *info_packet, + struct encoder_info_packet *info_packet, struct pipe_ctx *pipe_ctx) { struct core_stream *stream = pipe_ctx->stream; @@ -1288,9 +1245,6 @@ static void set_avi_info_frame( uint8_t *check_sum = NULL; uint8_t byte_index = 0; - if (info_packet == NULL) - return; - color_space = pipe_ctx->stream->public.output_color_space; /* Initialize header */ @@ -1458,8 +1412,9 @@ static void set_avi_info_frame( info_packet->valid = true; } -static void set_vendor_info_packet(struct core_stream *stream, - struct hw_info_packet *info_packet) +static void set_vendor_info_packet( + struct encoder_info_packet *info_packet, + struct core_stream *stream) { uint32_t length = 0; bool hdmi_vic_mode = false; @@ -1467,9 +1422,6 @@ static void set_vendor_info_packet(struct core_stream *stream, uint32_t i = 0; enum dc_timing_3d_format format; - ASSERT_CRITICAL(stream != NULL); - ASSERT_CRITICAL(info_packet != NULL); - format = stream->public.timing.timing_3d_format; /* Can be different depending on packet content */ @@ -1567,8 +1519,9 @@ static void set_vendor_info_packet(struct core_stream *stream, info_packet->valid = true; } -static void set_spd_info_packet(struct core_stream *stream, - struct hw_info_packet *info_packet) +static void set_spd_info_packet( + struct encoder_info_packet *info_packet, + struct core_stream *stream) { /* SPD info packet for FreeSync */ @@ -1688,9 +1641,9 @@ static void set_spd_info_packet(struct core_stream *stream, } static void set_hdr_static_info_packet( + struct encoder_info_packet *info_packet, struct core_surface *surface, - struct core_stream *stream, - struct hw_info_packet *info_packet) + struct core_stream *stream) { uint16_t i = 0; enum signal_type signal = stream->signal; @@ -1791,8 +1744,9 @@ static void set_hdr_static_info_packet( } } -static void set_vsc_info_packet(struct core_stream *stream, - struct hw_info_packet *info_packet) +static void set_vsc_info_packet( + struct encoder_info_packet *info_packet, + struct core_stream *stream) { unsigned int vscPacketRevision = 0; unsigned int i; @@ -1894,36 +1848,38 @@ struct clock_source *dc_resource_find_first_free_pll( void resource_build_info_frame(struct pipe_ctx *pipe_ctx) { enum signal_type signal = SIGNAL_TYPE_NONE; - struct hw_info_frame info_frame = { { 0 } }; + struct encoder_info_frame *info = &pipe_ctx->encoder_info_frame; /* default all packets to invalid */ - info_frame.avi_info_packet.valid = false; - info_frame.gamut_packet.valid = false; - info_frame.vendor_info_packet.valid = false; - info_frame.spd_packet.valid = false; - info_frame.vsc_packet.valid = false; - info_frame.hdrsmd_packet.valid = false; + info->avi.valid = false; + info->gamut.valid = false; + info->vendor.valid = false; + info->hdrsmd.valid = false; + info->vsc.valid = false; signal = pipe_ctx->stream->signal; /* HDMi and DP have different info packets*/ if (dc_is_hdmi_signal(signal)) { - set_avi_info_frame( - &info_frame.avi_info_packet, pipe_ctx); - set_vendor_info_packet( - pipe_ctx->stream, &info_frame.vendor_info_packet); - set_spd_info_packet(pipe_ctx->stream, &info_frame.spd_packet); - set_hdr_static_info_packet(pipe_ctx->surface, - pipe_ctx->stream, &info_frame.hdrsmd_packet); + set_avi_info_frame(&info->avi, pipe_ctx); + + set_vendor_info_packet(&info->vendor, pipe_ctx->stream); + + set_spd_info_packet(&info->spd, pipe_ctx->stream); + + set_hdr_static_info_packet(&info->hdrsmd, + pipe_ctx->surface, pipe_ctx->stream); + } else if (dc_is_dp_signal(signal)) { - set_vsc_info_packet(pipe_ctx->stream, &info_frame.vsc_packet); - set_spd_info_packet(pipe_ctx->stream, &info_frame.spd_packet); - set_hdr_static_info_packet(pipe_ctx->surface, - pipe_ctx->stream, &info_frame.hdrsmd_packet); + set_vsc_info_packet(&info->vsc, pipe_ctx->stream); + + set_spd_info_packet(&info->spd, pipe_ctx->stream); + + set_hdr_static_info_packet(&info->hdrsmd, + pipe_ctx->surface, pipe_ctx->stream); } - translate_info_frame(&info_frame, - &pipe_ctx->encoder_info_frame); + patch_gamut_packet_checksum(&info->gamut); } enum dc_status resource_map_clock_resources( diff --git a/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h b/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h index f99a03266149..6f0475c25566 100644 --- a/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h +++ b/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h @@ -40,27 +40,4 @@ struct drr_params { uint32_t vertical_total_max; }; -/* TODO hw_info_frame and hw_info_packet structures are same as in encoder - * merge it*/ -struct hw_info_packet { - bool valid; - uint8_t hb0; - uint8_t hb1; - uint8_t hb2; - uint8_t hb3; - uint8_t sb[32]; -}; - -struct hw_info_frame { - /* Auxiliary Video Information */ - struct hw_info_packet avi_info_packet; - struct hw_info_packet gamut_packet; - struct hw_info_packet vendor_info_packet; - /* Source Product Description */ - struct hw_info_packet spd_packet; - /* Video Stream Configuration */ - struct hw_info_packet vsc_packet; - struct hw_info_packet hdrsmd_packet; -}; - #endif -- cgit From a10eadfb152960a760c4f52c42607d27cb3f1543 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Sat, 14 Jan 2017 20:48:21 -0500 Subject: drm/amd/display: remove SIGNAL_TYPE_WIRELESS Signed-off-by: Tony Cheng Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/basics/log_helpers.c | 1 - drivers/gpu/drm/amd/display/dc/basics/signal_types.c | 3 +-- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 3 --- drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 1 - drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h | 1 - drivers/gpu/drm/amd/display/include/signal_types.h | 4 ---- 6 files changed, 1 insertion(+), 12 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/basics/log_helpers.c b/drivers/gpu/drm/amd/display/dc/basics/log_helpers.c index 61f36a7f322b..c4eddee8de1b 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/log_helpers.c +++ b/drivers/gpu/drm/amd/display/dc/basics/log_helpers.c @@ -44,7 +44,6 @@ static const struct dc_signal_type_info signal_type_info_tbl[] = { {SIGNAL_TYPE_DISPLAY_PORT, "DP"}, {SIGNAL_TYPE_DISPLAY_PORT_MST, "MST"}, {SIGNAL_TYPE_EDP, "eDP"}, - {SIGNAL_TYPE_WIRELESS, "Wireless"}, {SIGNAL_TYPE_VIRTUAL, "Virtual"} }; diff --git a/drivers/gpu/drm/amd/display/dc/basics/signal_types.c b/drivers/gpu/drm/amd/display/dc/basics/signal_types.c index 247487c3db71..534c803e7091 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/signal_types.c +++ b/drivers/gpu/drm/amd/display/dc/basics/signal_types.c @@ -75,7 +75,6 @@ bool dc_is_audio_capable_signal(enum signal_type signal) { return (signal == SIGNAL_TYPE_DISPLAY_PORT || signal == SIGNAL_TYPE_DISPLAY_PORT_MST || - dc_is_hdmi_signal(signal) || - signal == SIGNAL_TYPE_WIRELESS); + dc_is_hdmi_signal(signal)); } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 62cfc5cbe773..f4f46d4f0cf0 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1051,9 +1051,6 @@ static bool construct( if (link->device_tag.dev_id.device_type == DEVICE_TYPE_LCD && link->public.connector_signal == SIGNAL_TYPE_RGB) continue; - if (link->device_tag.dev_id.device_type == DEVICE_TYPE_WIRELESS - && link->public.connector_signal != SIGNAL_TYPE_WIRELESS) - continue; break; } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 930ae1377ab6..e9d1a54bffd3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -941,7 +941,6 @@ bool dce110_link_encoder_construct( enc110->base.hpd_source = init_data->hpd_source; enc110->base.connector = init_data->connector; - enc110->base.input_signals = SIGNAL_TYPE_ALL; enc110->base.preferred_engine = ENGINE_ID_UNKNOWN; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h index 49c4b6587456..ac4010b9c638 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h @@ -186,7 +186,6 @@ struct link_encoder { struct dc_context *ctx; struct graphics_object_id id; struct graphics_object_id connector; - uint32_t input_signals; uint32_t output_signals; enum engine_id preferred_engine; struct encoder_feature_support features; diff --git a/drivers/gpu/drm/amd/display/include/signal_types.h b/drivers/gpu/drm/amd/display/include/signal_types.h index d87f84a56fcc..1a2ca53c68cd 100644 --- a/drivers/gpu/drm/amd/display/include/signal_types.h +++ b/drivers/gpu/drm/amd/display/include/signal_types.h @@ -36,11 +36,7 @@ enum signal_type { SIGNAL_TYPE_DISPLAY_PORT = (1 << 5), SIGNAL_TYPE_DISPLAY_PORT_MST = (1 << 6), SIGNAL_TYPE_EDP = (1 << 7), - SIGNAL_TYPE_WIRELESS = (1 << 8), /* Wireless Display */ SIGNAL_TYPE_VIRTUAL = (1 << 9), /* Virtual Display */ - - SIGNAL_TYPE_COUNT = 10, - SIGNAL_TYPE_ALL = (1 << SIGNAL_TYPE_COUNT) - 1 }; /* help functions for signal types manipulation */ -- cgit From 5e701406ed446a79787feede65c81b8d3cfbdfb8 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Sat, 14 Jan 2017 20:56:08 -0500 Subject: drm/amd/display: remove dead code Signed-off-by: Tony Cheng Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/bios/bios_parser.c | 76 -------------- .../gpu/drm/amd/display/dc/bios/command_table.c | 114 --------------------- .../gpu/drm/amd/display/dc/bios/command_table.h | 7 -- drivers/gpu/drm/amd/display/dc/dc_bios_types.h | 6 -- .../drm/amd/display/include/bios_parser_types.h | 20 ---- 5 files changed, 223 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c index ebd2e419f8f2..656c39ac0256 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c @@ -545,80 +545,6 @@ static enum bp_result bios_parser_get_hpd_info(struct dc_bios *dcb, return BP_RESULT_NORECORD; } -static uint32_t bios_parser_get_gpio_record( - struct dc_bios *dcb, - struct graphics_object_id id, - struct bp_gpio_cntl_info *gpio_record, - uint32_t record_size) -{ - struct bios_parser *bp = BP_FROM_DCB(dcb); - ATOM_COMMON_RECORD_HEADER *header = NULL; - ATOM_OBJECT_GPIO_CNTL_RECORD *record = NULL; - ATOM_OBJECT *object = get_bios_object(bp, id); - uint32_t offset; - uint32_t pins_number; - uint32_t i; - - if (!object) - return 0; - - /* Initialise offset */ - offset = le16_to_cpu(object->usRecordOffset) - + bp->object_info_tbl_offset; - - for (;;) { - /* Get record header */ - header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset); - if (!header || header->ucRecordType == LAST_RECORD_TYPE || - !header->ucRecordSize) - break; - - /* If this is gpio control record - stop. We found the record */ - if (header->ucRecordType == ATOM_OBJECT_GPIO_CNTL_RECORD_TYPE - && header->ucRecordSize - >= sizeof(ATOM_OBJECT_GPIO_CNTL_RECORD)) { - record = (ATOM_OBJECT_GPIO_CNTL_RECORD *) header; - break; - } - - /* Advance to next record */ - offset += header->ucRecordSize; - } - - /* If we did not find a record - return */ - if (!record) - return 0; - - /* Extract gpio IDs from bios record (make sure we do not exceed passed - * array size) */ - pins_number = (record->ucNumberOfPins < record_size ? - record->ucNumberOfPins : record_size); - for (i = 0; i < pins_number; i++) { - uint8_t output_state = ((record->asGpio[i].ucGPIO_PinState - & GPIO_PIN_OUTPUT_STATE_MASK) - >> GPIO_PIN_OUTPUT_STATE_SHIFT); - gpio_record[i].id = record->asGpio[i].ucGPIOID; - - switch (output_state) { - case GPIO_PIN_STATE_ACTIVE_LOW: - gpio_record[i].state = - GPIO_PIN_OUTPUT_STATE_ACTIVE_LOW; - break; - - case GPIO_PIN_STATE_ACTIVE_HIGH: - gpio_record[i].state = - GPIO_PIN_OUTPUT_STATE_ACTIVE_HIGH; - break; - - default: - BREAK_TO_DEBUGGER(); /* Invalid Pin Output State */ - break; - } - } - - return pins_number; -} - enum bp_result bios_parser_get_device_tag_record( struct bios_parser *bp, ATOM_OBJECT *object, @@ -4064,8 +3990,6 @@ static const struct dc_vbios_funcs vbios_funcs = { .get_dst_number = bios_parser_get_dst_number, - .get_gpio_record = bios_parser_get_gpio_record, - .get_src_obj = bios_parser_get_src_obj, .get_dst_obj = bios_parser_get_dst_obj, diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table.c b/drivers/gpu/drm/amd/display/dc/bios/command_table.c index 88aaf53cb8c4..3f7b2dabc2b0 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table.c @@ -54,12 +54,10 @@ static void init_enable_spread_spectrum_on_ppll(struct bios_parser *bp); static void init_adjust_display_pll(struct bios_parser *bp); static void init_dac_encoder_control(struct bios_parser *bp); static void init_dac_output_control(struct bios_parser *bp); -static void init_blank_crtc(struct bios_parser *bp); static void init_set_crtc_timing(struct bios_parser *bp); static void init_select_crtc_source(struct bios_parser *bp); static void init_enable_crtc(struct bios_parser *bp); static void init_enable_crtc_mem_req(struct bios_parser *bp); -static void init_compute_memore_engine_pll(struct bios_parser *bp); static void init_external_encoder_control(struct bios_parser *bp); static void init_enable_disp_power_gating(struct bios_parser *bp); static void init_program_clock(struct bios_parser *bp); @@ -74,13 +72,11 @@ void dal_bios_parser_init_cmd_tbl(struct bios_parser *bp) init_adjust_display_pll(bp); init_dac_encoder_control(bp); init_dac_output_control(bp); - init_blank_crtc(bp); init_set_crtc_timing(bp); init_select_crtc_source(bp); init_enable_crtc(bp); init_enable_crtc_mem_req(bp); init_program_clock(bp); - init_compute_memore_engine_pll(bp); init_external_encoder_control(bp); init_enable_disp_power_gating(bp); init_set_dce_clock(bp); @@ -1673,66 +1669,6 @@ static enum bp_result dac2_output_control_v1( return result; } -/******************************************************************************* - ******************************************************************************** - ** - ** BLANK CRTC - ** - ******************************************************************************** - *******************************************************************************/ - -static enum bp_result blank_crtc_v1( - struct bios_parser *bp, - struct bp_blank_crtc_parameters *bp_params, - bool blank); - -static void init_blank_crtc(struct bios_parser *bp) -{ - switch (BIOS_CMD_TABLE_PARA_REVISION(BlankCRTC)) { - case 1: - bp->cmd_tbl.blank_crtc = blank_crtc_v1; - break; - default: - bp->cmd_tbl.blank_crtc = NULL; - break; - } -} - -static enum bp_result blank_crtc_v1( - struct bios_parser *bp, - struct bp_blank_crtc_parameters *bp_params, - bool blank) -{ - enum bp_result result = BP_RESULT_FAILURE; - BLANK_CRTC_PARAMETERS params = {0}; - uint8_t atom_controller_id; - - if (bp->cmd_helper->controller_id_to_atom(bp_params->controller_id, - &atom_controller_id)) { - params.ucCRTC = (uint8_t)atom_controller_id; - - if (blank) - params.ucBlanking = ATOM_BLANKING; - else - params.ucBlanking = ATOM_BLANKING_OFF; - params.usBlackColorRCr = - cpu_to_le16((uint16_t)bp_params->black_color_rcr); - params.usBlackColorGY = - cpu_to_le16((uint16_t)bp_params->black_color_gy); - params.usBlackColorBCb = - cpu_to_le16((uint16_t)bp_params->black_color_bcb); - - if (EXEC_BIOS_CMD_TABLE(BlankCRTC, params)) - result = BP_RESULT_OK; - } else - /* Not support more than two CRTC as current ASIC, update this - * if needed. - */ - result = BP_RESULT_BADINPUT; - - return result; -} - /******************************************************************************* ******************************************************************************** ** @@ -2239,56 +2175,6 @@ static enum bp_result program_clock_v6( return result; } -/******************************************************************************* - ******************************************************************************** - ** - ** COMPUTE MEMORY ENGINE PLL - ** - ******************************************************************************** - *******************************************************************************/ - -static enum bp_result compute_memore_engine_pll_v4( - struct bios_parser *bp, - struct bp_display_clock_parameters *bp_params); - -static void init_compute_memore_engine_pll(struct bios_parser *bp) -{ - switch (BIOS_CMD_TABLE_PARA_REVISION(ComputeMemoryEnginePLL)) { - case 4: - bp->cmd_tbl.compute_memore_engine_pll = - compute_memore_engine_pll_v4; - break; - default: - bp->cmd_tbl.compute_memore_engine_pll = NULL; - break; - } -} - -static enum bp_result compute_memore_engine_pll_v4( - struct bios_parser *bp, - struct bp_display_clock_parameters *bp_params) -{ - enum bp_result result = BP_RESULT_FAILURE; - COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V4 params; - - memset(¶ms, 0, sizeof(params)); - - params.ulClock = cpu_to_le32(bp_params->target_display_clock / 10); - - /* Initialize this to the target clock in case this call fails */ - bp_params->actual_display_clock = bp_params->target_display_clock; - - if (EXEC_BIOS_CMD_TABLE(ComputeMemoryEnginePLL, params)) { - /* Convert from 10KHz units back to KHz */ - bp_params->actual_display_clock = - le32_to_cpu(params.ulClock) * 10; - bp_params->actual_post_divider_id = params.ucPostDiv; - result = BP_RESULT_OK; - } - - return result; -} - /******************************************************************************* ******************************************************************************** ** diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table.h b/drivers/gpu/drm/amd/display/dc/bios/command_table.h index b8e6ef06c0c7..94f3d43a7471 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table.h +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table.h @@ -68,10 +68,6 @@ struct cmd_tbl { enum bp_result (*dac2_output_control)( struct bios_parser *bp, bool enable); - enum bp_result (*blank_crtc)( - struct bios_parser *bp, - struct bp_blank_crtc_parameters *bp_params, - bool blank); enum bp_result (*set_crtc_timing)( struct bios_parser *bp, struct bp_hw_crtc_timing_parameters *bp_params); @@ -89,9 +85,6 @@ struct cmd_tbl { enum bp_result (*program_clock)( struct bios_parser *bp, struct bp_pixel_clock_parameters *bp_params); - enum bp_result (*compute_memore_engine_pll)( - struct bios_parser *bp, - struct bp_display_clock_parameters *bp_params); enum bp_result (*external_encoder_control)( struct bios_parser *bp, struct bp_external_encoder_control *cntl); diff --git a/drivers/gpu/drm/amd/display/dc/dc_bios_types.h b/drivers/gpu/drm/amd/display/dc/dc_bios_types.h index 790c5bd51cb9..6e1291d5f51d 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_bios_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_bios_types.h @@ -51,12 +51,6 @@ struct dc_vbios_funcs { struct dc_bios *bios, struct graphics_object_id id); - uint32_t (*get_gpio_record)( - struct dc_bios *dcb, - struct graphics_object_id id, - struct bp_gpio_cntl_info *gpio_record, - uint32_t record_size); - enum bp_result (*get_src_obj)( struct dc_bios *bios, struct graphics_object_id object_id, uint32_t index, diff --git a/drivers/gpu/drm/amd/display/include/bios_parser_types.h b/drivers/gpu/drm/amd/display/include/bios_parser_types.h index 7de4fa5a0726..0840f69cde99 100644 --- a/drivers/gpu/drm/amd/display/include/bios_parser_types.h +++ b/drivers/gpu/drm/amd/display/include/bios_parser_types.h @@ -156,13 +156,6 @@ struct bp_transmitter_control { bool single_pll_mode; }; -struct bp_blank_crtc_parameters { - enum controller_id controller_id; - uint32_t black_color_rcr; - uint32_t black_color_gy; - uint32_t black_color_bcb; -}; - struct bp_hw_crtc_timing_parameters { enum controller_id controller_id; /* horizontal part */ @@ -252,14 +245,6 @@ struct bp_pixel_clock_parameters { } flags; }; -struct bp_display_clock_parameters { - uint32_t target_display_clock; /* KHz */ - /* Actual Display Clock set due to clock divider granularity KHz */ - uint32_t actual_display_clock; - /* Actual Post Divider ID used to generate the actual clock */ - uint32_t actual_post_divider_id; -}; - enum bp_dce_clock_type { DCECLOCK_TYPE_DISPLAY_CLOCK = 0, DCECLOCK_TYPE_DPREFCLK = 1 @@ -322,9 +307,4 @@ struct bp_encoder_cap_info { uint32_t RESERVED:30; }; -struct bp_gpio_cntl_info { - uint32_t id; - enum gpio_pin_output_state state; -}; - #endif /*__DAL_BIOS_PARSER_TYPES_H__ */ -- cgit From f33ad37feb12639e3b4015d27840395793107d7b Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Sat, 14 Jan 2017 20:56:08 -0500 Subject: drm/amd/display: remove calculate_adjustments in conversion.h - these are moved to color module Signed-off-by: Tony Cheng Acked-by: Harry Wentland Reviewed-by: Aric Cyr Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/basics/conversion.c | 118 --------------------- drivers/gpu/drm/amd/display/dc/basics/conversion.h | 10 -- 2 files changed, 128 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/basics/conversion.c b/drivers/gpu/drm/amd/display/dc/basics/conversion.c index 5682fea2080d..a2e22ae12adb 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/conversion.c +++ b/drivers/gpu/drm/amd/display/dc/basics/conversion.c @@ -103,124 +103,6 @@ void convert_float_matrix( } } -static void calculate_adjustments_common( - const struct fixed31_32 *ideal_matrix, - const struct dc_csc_adjustments *adjustments, - struct fixed31_32 *matrix) -{ - const struct fixed31_32 sin_hue = - dal_fixed31_32_sin(adjustments->hue); - const struct fixed31_32 cos_hue = - dal_fixed31_32_cos(adjustments->hue); - - const struct fixed31_32 multiplier = - dal_fixed31_32_mul( - adjustments->contrast, - adjustments->saturation); - - matrix[0] = dal_fixed31_32_mul( - ideal_matrix[0], - adjustments->contrast); - - matrix[1] = dal_fixed31_32_mul( - ideal_matrix[1], - adjustments->contrast); - - matrix[2] = dal_fixed31_32_mul( - ideal_matrix[2], - adjustments->contrast); - - matrix[4] = dal_fixed31_32_mul( - multiplier, - dal_fixed31_32_add( - dal_fixed31_32_mul( - ideal_matrix[8], - sin_hue), - dal_fixed31_32_mul( - ideal_matrix[4], - cos_hue))); - - matrix[5] = dal_fixed31_32_mul( - multiplier, - dal_fixed31_32_add( - dal_fixed31_32_mul( - ideal_matrix[9], - sin_hue), - dal_fixed31_32_mul( - ideal_matrix[5], - cos_hue))); - - matrix[6] = dal_fixed31_32_mul( - multiplier, - dal_fixed31_32_add( - dal_fixed31_32_mul( - ideal_matrix[10], - sin_hue), - dal_fixed31_32_mul( - ideal_matrix[6], - cos_hue))); - - matrix[7] = ideal_matrix[7]; - - matrix[8] = dal_fixed31_32_mul( - multiplier, - dal_fixed31_32_sub( - dal_fixed31_32_mul( - ideal_matrix[8], - cos_hue), - dal_fixed31_32_mul( - ideal_matrix[4], - sin_hue))); - - matrix[9] = dal_fixed31_32_mul( - multiplier, - dal_fixed31_32_sub( - dal_fixed31_32_mul( - ideal_matrix[9], - cos_hue), - dal_fixed31_32_mul( - ideal_matrix[5], - sin_hue))); - - matrix[10] = dal_fixed31_32_mul( - multiplier, - dal_fixed31_32_sub( - dal_fixed31_32_mul( - ideal_matrix[10], - cos_hue), - dal_fixed31_32_mul( - ideal_matrix[6], - sin_hue))); - - matrix[11] = ideal_matrix[11]; -} - -void calculate_adjustments( - const struct fixed31_32 *ideal_matrix, - const struct dc_csc_adjustments *adjustments, - struct fixed31_32 *matrix) -{ - calculate_adjustments_common(ideal_matrix, adjustments, matrix); - - matrix[3] = dal_fixed31_32_add( - ideal_matrix[3], - dal_fixed31_32_mul( - adjustments->brightness, - dal_fixed31_32_from_fraction(86, 100))); -} - -void calculate_adjustments_y_only( - const struct fixed31_32 *ideal_matrix, - const struct dc_csc_adjustments *adjustments, - struct fixed31_32 *matrix) -{ - calculate_adjustments_common(ideal_matrix, adjustments, matrix); - - matrix[3] = dal_fixed31_32_add( - ideal_matrix[3], - adjustments->brightness); -} - unsigned int log_2(unsigned int num) { unsigned int result = 0; diff --git a/drivers/gpu/drm/amd/display/dc/basics/conversion.h b/drivers/gpu/drm/amd/display/dc/basics/conversion.h index b7fe431a7952..189325f68cfd 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/conversion.h +++ b/drivers/gpu/drm/amd/display/dc/basics/conversion.h @@ -38,16 +38,6 @@ void convert_float_matrix( struct fixed31_32 *flt, uint32_t buffer_size); -void calculate_adjustments( - const struct fixed31_32 *ideal_matrix, - const struct dc_csc_adjustments *adjustments, - struct fixed31_32 *matrix); - -void calculate_adjustments_y_only( - const struct fixed31_32 *ideal_matrix, - const struct dc_csc_adjustments *adjustments, - struct fixed31_32 *matrix); - unsigned int log_2(unsigned int num); #endif -- cgit From e0d7ce783a88824cc7e3af0f1aa2d1076364cbf4 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Fri, 6 Jan 2017 15:55:47 -0500 Subject: drm/amd/display: enable clock gating and dchubp power gating also refactor to clean reduce loc to achieve same logic Signed-off-by: Tony Cheng Acked-by: Harry Wentland Reviewed-by: Yongqiang Sun Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index f53b41339951..e0143f9f0421 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -145,7 +145,8 @@ struct dc_debug { bool disable_stutter; bool disable_dcc; bool disable_dfs_bypass; - bool disable_power_gate; + bool disable_dpp_power_gate; + bool disable_hubp_power_gate; bool disable_clock_gate; bool disable_dmcu; bool disable_color_module; -- cgit From 306dadf01aba27bed2daa49a782b22586af64c93 Mon Sep 17 00:00:00 2001 From: Amy Zhang Date: Fri, 13 Jan 2017 16:19:36 -0500 Subject: drm/amd/display: Set default degamma to sRGB instead of bypass Signed-off-by: Amy Zhang Acked-by: Harry Wentland Reviewed-by: Aric Cyr Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index b51668e3bb52..ee393a168c84 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -255,7 +255,7 @@ static bool dce110_set_input_transfer_func( if (tf == NULL) { /* Default case if no input transfer function specified */ ipp->funcs->ipp_set_degamma(ipp, - IPP_DEGAMMA_MODE_BYPASS); + IPP_DEGAMMA_MODE_HW_sRGB); } else if (tf->public.type == TF_TYPE_PREDEFINED) { switch (tf->public.tf) { case TRANSFER_FUNCTION_SRGB: -- cgit From 534db198866070fdb655423637afdce6cf0c05db Mon Sep 17 00:00:00 2001 From: Amy Zhang Date: Fri, 13 Jan 2017 16:49:26 -0500 Subject: drm/amd/display: HDR Enablement For Applications - Made sure dest color space is updated in stream and info frame - Optimized segment distribution algorithm for regamma mapping Signed-off-by: Amy Zhang Acked-by: Harry Wentland Reviewed-by: Aric Cyr Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 14 ++++ drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 6 +- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 94 ++++++++++++++++++---- drivers/gpu/drm/amd/display/dc/inc/hw/transform.h | 11 +++ 4 files changed, 107 insertions(+), 18 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index fe79a2890247..8b41c7708562 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1310,6 +1310,20 @@ static void set_avi_info_frame( info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 = COLORIMETRY_NO_DATA; + if (color_space == COLOR_SPACE_2020_RGB_FULLRANGE || + color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE || + color_space == COLOR_SPACE_2020_YCBCR) { + info_frame.avi_info_packet.info_packet_hdmi.bits.EC0_EC2 = + COLORIMETRYEX_BT2020RGBYCBCR; + info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 = + COLORIMETRY_EXTENDED; + } else if (color_space == COLOR_SPACE_ADOBERGB) { + info_frame.avi_info_packet.info_packet_hdmi.bits.EC0_EC2 = + COLORIMETRYEX_ADOBERGB; + info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 = + COLORIMETRY_EXTENDED; + } + /* TODO: un-hardcode aspect ratio */ aspect = stream->public.timing.aspect_ratio; diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index 00958bdbb417..a17e7bc96f9e 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -444,7 +444,11 @@ enum dc_color_space { COLOR_SPACE_YCBCR601, COLOR_SPACE_YCBCR709, COLOR_SPACE_YCBCR601_LIMITED, - COLOR_SPACE_YCBCR709_LIMITED + COLOR_SPACE_YCBCR709_LIMITED, + COLOR_SPACE_2020_RGB_FULLRANGE, + COLOR_SPACE_2020_RGB_LIMITEDRANGE, + COLOR_SPACE_2020_YCBCR, + COLOR_SPACE_ADOBERGB, }; enum dc_quantization_range { diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index ee393a168c84..e9fd83e9af79 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -594,39 +594,88 @@ static bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func struct fixed31_32 y3_max; int32_t segment_start, segment_end; - uint32_t hw_points, start_index; - uint32_t i, j; + uint32_t i, j, k, seg_distr[16], increment, start_index; + uint32_t hw_points = 0; memset(regamma_params, 0, sizeof(struct pwl_params)); if (output_tf->tf == TRANSFER_FUNCTION_PQ) { - /* 16 segments x 16 points + /* 16 segments * segments are from 2^-11 to 2^5 */ segment_start = -11; segment_end = 5; + seg_distr[0] = 2; + seg_distr[1] = 2; + seg_distr[2] = 2; + seg_distr[3] = 2; + seg_distr[4] = 2; + seg_distr[5] = 2; + seg_distr[6] = 3; + seg_distr[7] = 4; + seg_distr[8] = 4; + seg_distr[9] = 4; + seg_distr[10] = 4; + seg_distr[11] = 5; + seg_distr[12] = 5; + seg_distr[13] = 5; + seg_distr[14] = 5; + seg_distr[15] = 5; + } else { - /* 10 segments x 16 points + /* 10 segments * segment is from 2^-10 to 2^0 */ segment_start = -10; segment_end = 0; + + seg_distr[0] = 3; + seg_distr[1] = 4; + seg_distr[2] = 4; + seg_distr[3] = 4; + seg_distr[4] = 4; + seg_distr[5] = 4; + seg_distr[6] = 4; + seg_distr[7] = 4; + seg_distr[8] = 5; + seg_distr[9] = 5; + seg_distr[10] = -1; + seg_distr[11] = -1; + seg_distr[12] = -1; + seg_distr[13] = -1; + seg_distr[14] = -1; + seg_distr[15] = -1; + } + + for (k = 0; k < 16; k++) { + if (seg_distr[k] != -1) + hw_points += (1 << seg_distr[k]); } - hw_points = (segment_end - segment_start) * 16; j = 0; - /* (segment + 25) * 32, every 2nd point */ - start_index = (segment_start + 25) * 32; - for (i = start_index; i <= 1025; i += 2) { - if (j > hw_points) - break; - 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]; - j++; + for (k = 0; k < (segment_end - segment_start); k++) { + increment = 32 / (1 << seg_distr[k]); + start_index = (segment_start + k + 25) * 32; + for (i = start_index; i < start_index + 32; i += increment) { + if (j == hw_points - 1) + break; + 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]; + j++; + } } + /* last point */ + start_index = (segment_end + 25) * 32; + rgb_resulted[hw_points - 1].red = + output_tf->tf_pts.red[start_index]; + rgb_resulted[hw_points - 1].green = + output_tf->tf_pts.green[start_index]; + rgb_resulted[hw_points - 1].blue = + output_tf->tf_pts.blue[start_index]; + arr_points[0].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2), dal_fixed31_32_from_int(segment_start)); arr_points[1].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2), @@ -677,11 +726,22 @@ static bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func regamma_params->hw_points_num = hw_points; - for (i = 0; i < segment_end - segment_start; i++) { - regamma_params->arr_curve_points[i].offset = i * 16; - regamma_params->arr_curve_points[i].segments_num = 4; + i = 1; + for (k = 0; k < 16 && i < 16; k++) { + if (seg_distr[k] != -1) { + regamma_params->arr_curve_points[k].segments_num = + seg_distr[k]; + regamma_params->arr_curve_points[i].offset = + regamma_params->arr_curve_points[k]. + offset + (1 << seg_distr[k]); + } + i++; } + if (seg_distr[k] != -1) + regamma_params->arr_curve_points[k].segments_num = + seg_distr[k]; + struct pwl_result_data *rgb = rgb_resulted; struct pwl_result_data *rgb_plus_1 = rgb_resulted + 1; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h index ef743b70b3e9..a510d3fe48ec 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h @@ -47,6 +47,17 @@ enum colorimetry { COLORIMETRY_EXTENDED = 3 }; +enum colorimetry_ext { + COLORIMETRYEX_XVYCC601 = 0, + COLORIMETRYEX_XVYCC709 = 1, + COLORIMETRYEX_SYCC601 = 2, + COLORIMETRYEX_ADOBEYCC601 = 3, + COLORIMETRYEX_ADOBERGB = 4, + COLORIMETRYEX_BT2020YCC = 5, + COLORIMETRYEX_BT2020RGBYCBCR = 6, + COLORIMETRYEX_RESERVED = 7 +}; + enum active_format_info { ACTIVE_FORMAT_NO_DATA = 0, ACTIVE_FORMAT_VALID = 1 -- cgit From ab7044d0d17a8226a8b51e235e16204e696ae42a Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Mon, 16 Jan 2017 20:37:08 -0500 Subject: drm/amd/display: refactor clk_resync to avoid assertion - not all DCE has PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE bit defined. Signed-off-by: Tony Cheng Acked-by: Harry Wentland Reviewed-by: Yongqiang Sun Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dce/dce_clock_source.c | 57 ++++++++++++---------- 1 file changed, 30 insertions(+), 27 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index a38172bdcb5e..78f43274a03a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -767,41 +767,44 @@ static void dce112_program_pixel_clk_resync( enum dc_color_depth colordepth, bool enable_ycbcr420) { - REG_UPDATE(PIXCLK_RESYNC_CNTL, - PHYPLLA_DCCG_DEEP_COLOR_CNTL, 0); + uint32_t deep_color_cntl = 0; + uint32_t double_rate_enable = 0; + /* 24 bit mode: TMDS clock = 1.0 x pixel clock (1:1) 30 bit mode: TMDS clock = 1.25 x pixel clock (5:4) 36 bit mode: TMDS clock = 1.5 x pixel clock (3:2) 48 bit mode: TMDS clock = 2 x pixel clock (2:1) */ - if (signal_type != SIGNAL_TYPE_HDMI_TYPE_A) - return; + if (signal_type == SIGNAL_TYPE_HDMI_TYPE_A) { + double_rate_enable = enable_ycbcr420 ? 1 : 0; - switch (colordepth) { - case COLOR_DEPTH_888: - REG_UPDATE_2(PIXCLK_RESYNC_CNTL, - PHYPLLA_DCCG_DEEP_COLOR_CNTL, 0, - PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE, enable_ycbcr420); - break; - case COLOR_DEPTH_101010: - REG_UPDATE_2(PIXCLK_RESYNC_CNTL, - PHYPLLA_DCCG_DEEP_COLOR_CNTL, 1, - PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE, enable_ycbcr420); - break; - case COLOR_DEPTH_121212: - REG_UPDATE_2(PIXCLK_RESYNC_CNTL, - PHYPLLA_DCCG_DEEP_COLOR_CNTL, 2, - PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE, enable_ycbcr420); - break; - case COLOR_DEPTH_161616: - REG_UPDATE_2(PIXCLK_RESYNC_CNTL, - PHYPLLA_DCCG_DEEP_COLOR_CNTL, 3, - PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE, enable_ycbcr420); - break; - default: - break; + switch (colordepth) { + case COLOR_DEPTH_888: + deep_color_cntl = 0; + break; + case COLOR_DEPTH_101010: + deep_color_cntl = 1; + break; + case COLOR_DEPTH_121212: + deep_color_cntl = 2; + break; + case COLOR_DEPTH_161616: + deep_color_cntl = 3; + break; + default: + break; + } } + + if (clk_src->cs_mask->PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE) + REG_UPDATE_2(PIXCLK_RESYNC_CNTL, + PHYPLLA_DCCG_DEEP_COLOR_CNTL, deep_color_cntl, + PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE, double_rate_enable); + else + REG_UPDATE(PIXCLK_RESYNC_CNTL, + PHYPLLA_DCCG_DEEP_COLOR_CNTL, deep_color_cntl); + } static bool dce110_program_pix_clk( -- cgit From 031ec2764064d79b1e1d8c30a6785ed19184fb47 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Tue, 17 Jan 2017 11:18:55 -0500 Subject: drm/amd/display: Remove meta_pitch Signed-off-by: Dmytro Laktyushkin Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_debug.c | 8 ++------ drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 4 ---- 2 files changed, 2 insertions(+), 10 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c index 78b8e0c5b4e7..959c3f372e73 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c @@ -94,14 +94,12 @@ void pre_surface_trace( "surface->plane_size.grph.surface_size.y = %d;\n" "surface->plane_size.grph.surface_size.width = %d;\n" "surface->plane_size.grph.surface_size.height = %d;\n" - "surface->plane_size.grph.surface_pitch = %d;\n" - "surface->plane_size.grph.meta_pitch = %d;\n", + "surface->plane_size.grph.surface_pitch = %d;\n", surface->plane_size.grph.surface_size.x, surface->plane_size.grph.surface_size.y, surface->plane_size.grph.surface_size.width, surface->plane_size.grph.surface_size.height, - surface->plane_size.grph.surface_pitch, - surface->plane_size.grph.meta_pitch); + surface->plane_size.grph.surface_pitch); SURFACE_TRACE( @@ -176,7 +174,6 @@ void update_surface_trace( SURFACE_TRACE( "plane_info->color_space = %d;\n" "plane_info->format = %d;\n" - "plane_info->plane_size.grph.meta_pitch = %d;\n" "plane_info->plane_size.grph.surface_pitch = %d;\n" "plane_info->plane_size.grph.surface_size.height = %d;\n" "plane_info->plane_size.grph.surface_size.width = %d;\n" @@ -185,7 +182,6 @@ void update_surface_trace( "plane_info->rotation = %d;\n", update->plane_info->color_space, update->plane_info->format, - update->plane_info->plane_size.grph.meta_pitch, update->plane_info->plane_size.grph.surface_pitch, update->plane_info->plane_size.grph.surface_size.height, update->plane_info->plane_size.grph.surface_size.width, diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index a17e7bc96f9e..5c1b2f833fe2 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -123,8 +123,6 @@ union plane_size { * is 32 pixel aligned. */ uint32_t surface_pitch; - - uint32_t meta_pitch; } grph; struct { @@ -134,7 +132,6 @@ union plane_size { * 32 pixel aligned. */ uint32_t luma_pitch; - uint32_t meta_luma_pitch; struct rect chroma_size; /* Graphic surface pitch in pixels. @@ -142,7 +139,6 @@ union plane_size { * 32 pixel aligned. */ uint32_t chroma_pitch; - uint32_t meta_chroma_pitch; } video; }; -- cgit From 8693049a896c2c3a2bb74f0efde62318636beaef Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Mon, 16 Jan 2017 20:50:47 -0500 Subject: drm/amd/display: rename BGRA8888 to ABGR8888 DC actually support ABGR8888 instead of BGRA8888 (R/B swap rather than endian swap) , rename to avoid confusion Signed-off-by: Tony Cheng Acked-by: Harry Wentland Reviewed-by: Yongqiang Sun Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c | 4 ++-- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 2 +- drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c | 4 ++-- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 2 +- drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c index 54388c0e29e0..946379852b2a 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c @@ -2530,7 +2530,7 @@ static void populate_initial_data( data->bytes_per_pixel[num_displays + 4] = 2; break; case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: - case SURFACE_PIXEL_FORMAT_GRPH_BGRA8888: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: @@ -2626,7 +2626,7 @@ static void populate_initial_data( data->bytes_per_pixel[num_displays + 4] = 2; break; case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: - case SURFACE_PIXEL_FORMAT_GRPH_BGRA8888: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 8b41c7708562..ee1c3b029394 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -341,7 +341,7 @@ static enum pixel_format convert_pixel_format_to_dalsurface( case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: dal_pixel_format = PIXEL_FORMAT_ARGB8888; break; - case SURFACE_PIXEL_FORMAT_GRPH_BGRA8888: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: dal_pixel_format = PIXEL_FORMAT_ARGB8888; break; case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index 5c1b2f833fe2..53c73de75da9 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -174,7 +174,7 @@ enum surface_pixel_format { /*32 bpp*/ SURFACE_PIXEL_FORMAT_GRPH_ARGB8888, /*32 bpp swaped*/ - SURFACE_PIXEL_FORMAT_GRPH_BGRA8888, + SURFACE_PIXEL_FORMAT_GRPH_ABGR8888, SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010, /*swaped*/ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c index 130935fffba3..e14a21cedfd5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c @@ -302,7 +302,7 @@ static void program_grph_pixel_format( uint32_t grph_depth, grph_format; uint32_t sign = 0, floating = 0; - if (format == SURFACE_PIXEL_FORMAT_GRPH_BGRA8888 || + if (format == SURFACE_PIXEL_FORMAT_GRPH_ABGR8888 || /*todo: doesn't look like we handle BGRA here, * should problem swap endian*/ format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010 || @@ -331,7 +331,7 @@ static void program_grph_pixel_format( grph_format = 1; break; case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: - case SURFACE_PIXEL_FORMAT_GRPH_BGRA8888: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: grph_depth = 2; grph_format = 0; break; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index e9fd83e9af79..6dbfc570b8c6 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -214,7 +214,7 @@ static void build_prescale_params(struct ipp_prescale_params *prescale_params, switch (surface->public.format) { case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: - case SURFACE_PIXEL_FORMAT_GRPH_BGRA8888: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: prescale_params->scale = 0x2020; break; case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c index b12506adcba4..aac47955e9bf 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c @@ -405,7 +405,7 @@ static void program_pixel_format( grph_format = 1; break; case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: - case SURFACE_PIXEL_FORMAT_GRPH_BGRA8888: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: grph_depth = 2; grph_format = 0; break; -- cgit From 009432e58159e640e942092ca68d78f589549d14 Mon Sep 17 00:00:00 2001 From: Zeyu Fan Date: Tue, 17 Jan 2017 15:14:11 -0500 Subject: drm/amd/display: Fix missing conditions in hw sequencer. Signed-off-by: Zeyu Fan Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c index cd9a371ae237..0eee135bfa54 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c @@ -160,7 +160,7 @@ void dce_crtc_switch_to_clk_src(struct dce_hwseq *hws, struct clock_source *clk_src, unsigned int tg_inst) { - if (clk_src->id == CLOCK_SOURCE_ID_DP_DTO) { + if (clk_src->id == CLOCK_SOURCE_ID_DP_DTO || clk_src->dp_clk_src) { REG_UPDATE(PIXEL_RATE_CNTL[tg_inst], DP_DTO0_ENABLE, 1); -- cgit From b565ff86aaebee65141a4a441f782a05962d4c14 Mon Sep 17 00:00:00 2001 From: Leon Elazar Date: Tue, 17 Jan 2017 16:16:04 -0500 Subject: drm/amd/display: Add missing MI masks This will fix the memory Input programing with MST tiled display. This Fix should fix connectivity problems with MST tiled Display Signed-off-by: Leon Elazar Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h index f90d586656ef..ec053c241901 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h @@ -92,6 +92,8 @@ struct dce_mem_input_registers { .field_name = blk_name ## reg_name ## __ ## field_name ## post_fix #define MI_GFX8_TILE_MASK_SH_LIST(mask_sh, blk)\ + SFB(blk, GRPH_CONTROL, GRPH_NUM_BANKS, mask_sh),\ + SFB(blk, GRPH_CONTROL, GRPH_BANK_WIDTH, mask_sh),\ SFB(blk, GRPH_CONTROL, GRPH_BANK_HEIGHT, mask_sh),\ SFB(blk, GRPH_CONTROL, GRPH_MACRO_TILE_ASPECT, mask_sh),\ SFB(blk, GRPH_CONTROL, GRPH_TILE_SPLIT, mask_sh),\ -- cgit From b10d51f8b094f73c6c27d389013304e59e3062b2 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Mon, 16 Jan 2017 16:16:22 -0500 Subject: drm/amd/display: Add interrupt entries for VBLANK isr. Signed-off-by: Andrey Grodzovsky Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- .../amd/display/dc/irq/dce110/irq_service_dce110.c | 42 ++++++++++++++++++++++ .../amd/display/dc/irq/dce80/irq_service_dce80.c | 22 ++++++++++++ drivers/gpu/drm/amd/display/dc/irq_types.h | 8 +++++ 3 files changed, 72 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c index f3eda1b4eebf..4c7c85d45518 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c @@ -33,6 +33,13 @@ #include "dce/dce_11_0_sh_mask.h" #include "ivsrcid/ivsrcid_vislands30.h" +#define VISLANDS30_IV_SRCID_D1_VBLANK 1 +#define VISLANDS30_IV_SRCID_D2_VBLANK 2 +#define VISLANDS30_IV_SRCID_D3_VBLANK 3 +#define VISLANDS30_IV_SRCID_D4_VBLANK 4 +#define VISLANDS30_IV_SRCID_D5_VBLANK 5 +#define VISLANDS30_IV_SRCID_D6_VBLANK 6 + static bool hpd_ack( struct irq_service *irq_service, const struct irq_source_info *info) @@ -139,6 +146,22 @@ static const struct irq_source_info_funcs vblank_irq_info_funcs = { .funcs = &vblank_irq_info_funcs\ } +#define vblank_int_entry(reg_num)\ + [DC_IRQ_SOURCE_VBLANK1 + reg_num] = {\ + .enable_reg = mmLB ## reg_num ## _LB_INTERRUPT_MASK,\ + .enable_mask =\ + LB_INTERRUPT_MASK__VBLANK_INTERRUPT_MASK_MASK,\ + .enable_value = {\ + LB_INTERRUPT_MASK__VBLANK_INTERRUPT_MASK_MASK,\ + ~LB_INTERRUPT_MASK__VBLANK_INTERRUPT_MASK_MASK},\ + .ack_reg = mmLB ## reg_num ## _LB_VBLANK_STATUS,\ + .ack_mask =\ + LB_VBLANK_STATUS__VBLANK_ACK_MASK,\ + .ack_value =\ + LB_VBLANK_STATUS__VBLANK_ACK_MASK,\ + .funcs = &vblank_irq_info_funcs\ + } + #define dummy_irq_entry() \ {\ .funcs = &dummy_irq_info_funcs\ @@ -264,6 +287,13 @@ irq_source_info_dce110[DAL_IRQ_SOURCES_NUMBER] = { vupdate_int_entry(3), vupdate_int_entry(4), vupdate_int_entry(5), + vblank_int_entry(0), + vblank_int_entry(1), + vblank_int_entry(2), + vblank_int_entry(3), + vblank_int_entry(4), + vblank_int_entry(5), + }; enum dc_irq_source to_dal_irq_source_dce110( @@ -272,6 +302,18 @@ enum dc_irq_source to_dal_irq_source_dce110( uint32_t ext_id) { switch (src_id) { + case VISLANDS30_IV_SRCID_D1_VBLANK: + return DC_IRQ_SOURCE_VBLANK1; + case VISLANDS30_IV_SRCID_D2_VBLANK: + return DC_IRQ_SOURCE_VBLANK2; + case VISLANDS30_IV_SRCID_D3_VBLANK: + return DC_IRQ_SOURCE_VBLANK3; + case VISLANDS30_IV_SRCID_D4_VBLANK: + return DC_IRQ_SOURCE_VBLANK4; + case VISLANDS30_IV_SRCID_D5_VBLANK: + return DC_IRQ_SOURCE_VBLANK5; + case VISLANDS30_IV_SRCID_D6_VBLANK: + return DC_IRQ_SOURCE_VBLANK6; case VISLANDS30_IV_SRCID_D1_V_UPDATE_INT: return DC_IRQ_SOURCE_VUPDATE1; case VISLANDS30_IV_SRCID_D2_V_UPDATE_INT: diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c b/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c index 8b4f45389783..dd09d2b6d4a7 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c @@ -143,6 +143,22 @@ static const struct irq_source_info_funcs vblank_irq_info_funcs = { .funcs = &vblank_irq_info_funcs\ } +#define vblank_int_entry(reg_num)\ + [DC_IRQ_SOURCE_VBLANK1 + reg_num] = {\ + .enable_reg = mmLB ## reg_num ## _LB_INTERRUPT_MASK,\ + .enable_mask =\ + LB_INTERRUPT_MASK__VBLANK_INTERRUPT_MASK_MASK,\ + .enable_value = {\ + LB_INTERRUPT_MASK__VBLANK_INTERRUPT_MASK_MASK,\ + ~LB_INTERRUPT_MASK__VBLANK_INTERRUPT_MASK_MASK},\ + .ack_reg = mmLB ## reg_num ## _LB_VBLANK_STATUS,\ + .ack_mask =\ + LB_VBLANK_STATUS__VBLANK_ACK_MASK,\ + .ack_value =\ + LB_VBLANK_STATUS__VBLANK_ACK_MASK,\ + .funcs = &vblank_irq_info_funcs\ + } + #define dummy_irq_entry() \ {\ .funcs = &dummy_irq_info_funcs\ @@ -246,6 +262,12 @@ irq_source_info_dce80[DAL_IRQ_SOURCES_NUMBER] = { vupdate_int_entry(3), vupdate_int_entry(4), vupdate_int_entry(5), + vblank_int_entry(0), + vblank_int_entry(1), + vblank_int_entry(2), + vblank_int_entry(3), + vblank_int_entry(4), + vblank_int_entry(5), }; static const struct irq_service_funcs irq_service_funcs_dce80 = { diff --git a/drivers/gpu/drm/amd/display/dc/irq_types.h b/drivers/gpu/drm/amd/display/dc/irq_types.h index e4b4b99a86fc..a506c2e939f5 100644 --- a/drivers/gpu/drm/amd/display/dc/irq_types.h +++ b/drivers/gpu/drm/amd/display/dc/irq_types.h @@ -128,6 +128,13 @@ enum dc_irq_source { DC_IRQ_SOURCE_VUPDATE5, DC_IRQ_SOURCE_VUPDATE6, + DC_IRQ_SOURCE_VBLANK1, + DC_IRQ_SOURCE_VBLANK2, + DC_IRQ_SOURCE_VBLANK3, + DC_IRQ_SOURCE_VBLANK4, + DC_IRQ_SOURCE_VBLANK5, + DC_IRQ_SOURCE_VBLANK6, + DAL_IRQ_SOURCES_NUMBER }; @@ -135,6 +142,7 @@ enum irq_type { IRQ_TYPE_PFLIP = DC_IRQ_SOURCE_PFLIP1, IRQ_TYPE_VUPDATE = DC_IRQ_SOURCE_VUPDATE1, + IRQ_TYPE_VBLANK = DC_IRQ_SOURCE_VBLANK1, }; #define DAL_VALID_IRQ_SRC_NUM(src) \ -- cgit From b57de80a51479f19a41f737ddd1ab18028bf9a43 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Wed, 19 Apr 2017 13:29:11 -0400 Subject: drm/amd/display: Register on VLBLANK ISR. Switch from VUPDATE to VBLANK. Signed-off-by: Andrey Grodzovsky Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 13 +++++++------ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 2 +- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c | 2 +- 3 files changed, 9 insertions(+), 8 deletions(-) (limited to 'drivers/gpu') 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 214cd38b8135..b85f34ba158c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -201,7 +201,7 @@ static void dm_crtc_high_irq(void *interrupt_params) uint8_t crtc_index = 0; struct amdgpu_crtc *acrtc; - acrtc = get_crtc_by_otg_inst(adev, irq_params->irq_src - IRQ_TYPE_VUPDATE); + acrtc = get_crtc_by_otg_inst(adev, irq_params->irq_src - IRQ_TYPE_VBLANK); if (acrtc) crtc_index = acrtc->crtc_id; @@ -1026,9 +1026,10 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev) * amdgpu_dm_irq_handler() will re-direct the interrupt to DC * for acknowledging and handling. */ - for (i = VISLANDS30_IV_SRCID_D1_V_UPDATE_INT; - i <= VISLANDS30_IV_SRCID_D6_V_UPDATE_INT; i += 2) { - r = amdgpu_irq_add_id(adev, AMDGPU_IH_CLIENTID_LEGACY, i, &adev->crtc_irq); + /* Use VBLANK interrupt */ + for (i = 0; i < adev->mode_info.num_crtc; i++) { + r = amdgpu_irq_add_id(adev, AMDGPU_IH_CLIENTID_LEGACY, i+1, &adev->crtc_irq); + if (r) { DRM_ERROR("Failed to add crtc irq id!\n"); return r; @@ -1036,9 +1037,9 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev) int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT; int_params.irq_source = - dc_interrupt_to_irq_source(dc, i, 0); + dc_interrupt_to_irq_source(dc, i+1, 0); - c_irq_params = &adev->dm.vupdate_params[int_params.irq_source - DC_IRQ_SOURCE_VUPDATE1]; + c_irq_params = &adev->dm.vblank_params[int_params.irq_source - DC_IRQ_SOURCE_VBLANK1]; c_irq_params->adev = adev; c_irq_params->irq_src = int_params.irq_source; 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 1b54566f5da1..d6ebba012e15 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -105,7 +105,7 @@ struct amdgpu_display_manager { pflip_params[DC_IRQ_SOURCE_PFLIP_LAST - DC_IRQ_SOURCE_PFLIP_FIRST + 1]; struct common_irq_params - vupdate_params[DC_IRQ_SOURCE_VUPDATE6 - DC_IRQ_SOURCE_VUPDATE1 + 1]; + vblank_params[DC_IRQ_SOURCE_VBLANK6 - DC_IRQ_SOURCE_VBLANK1 + 1]; /* this spin lock synchronizes access to 'irq_handler_list_table' */ spinlock_t irq_handler_list_table_lock; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c index 20e074971bff..682e9c3ad8e5 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c @@ -736,7 +736,7 @@ static int amdgpu_dm_set_crtc_irq_state(struct amdgpu_device *adev, source, crtc_id, state, - IRQ_TYPE_VUPDATE, + IRQ_TYPE_VBLANK, __func__); } -- cgit From 3d761e7990a27dca7481d4f4e4d6b3751509ab11 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Wed, 19 Apr 2017 13:55:35 -0400 Subject: drm/amd/display: Clean index in irq init loop Signed-off-by: Andrey Grodzovsky Acked-by: Harry Wentland Reviewed-by: Tony Cheng Reviewed-by: Jordan Lazare Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') 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 b85f34ba158c..0c50433d6ba3 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1027,8 +1027,8 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev) * for acknowledging and handling. */ /* Use VBLANK interrupt */ - for (i = 0; i < adev->mode_info.num_crtc; i++) { - r = amdgpu_irq_add_id(adev, AMDGPU_IH_CLIENTID_LEGACY, i+1, &adev->crtc_irq); + for (i = 1; i <= adev->mode_info.num_crtc; i++) { + r = amdgpu_irq_add_id(adev, AMDGPU_IH_CLIENTID_LEGACY, i, &adev->crtc_irq); if (r) { DRM_ERROR("Failed to add crtc irq id!\n"); @@ -1037,7 +1037,7 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev) int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT; int_params.irq_source = - dc_interrupt_to_irq_source(dc, i+1, 0); + dc_interrupt_to_irq_source(dc, i, 0); c_irq_params = &adev->dm.vblank_params[int_params.irq_source - DC_IRQ_SOURCE_VBLANK1]; @@ -1048,6 +1048,7 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev) dm_crtc_high_irq, c_irq_params); } + /* Use GRPH_PFLIP interrupt */ for (i = VISLANDS30_IV_SRCID_D1_GRPH_PFLIP; i <= VISLANDS30_IV_SRCID_D6_GRPH_PFLIP; i += 2) { r = amdgpu_irq_add_id(adev, AMDGPU_IH_CLIENTID_LEGACY, i, &adev->pageflip_irq); -- cgit From adc9b14139de00b9fe016acc901a5fcf50145008 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Tue, 17 Jan 2017 17:40:13 -0500 Subject: drm/amd/display: add missing dcc update on flip call Signed-off-by: Dmytro Laktyushkin Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 9deddc8ee2d1..f9b7fc85d71a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1429,6 +1429,8 @@ void dc_update_surfaces_for_stream(struct dc *dc, struct dc_surface_update *upda updates[i].plane_info->tiling_info; surface->public.visible = updates[i].plane_info->visible; + surface->public.dcc = + updates[i].plane_info->dcc; } if (updates[i].scaling_info) { -- cgit From f0e3db90a6fbee4acc921a4912a3e3460efb5cc0 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 23 Jan 2017 11:49:24 -0500 Subject: drm/amd/display: Don't reserve pipe for underlay on ASIC without underlay Signed-off-by: Harry Wentland Acked-by: Jordan Lazare Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 2 +- drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c | 4 ++-- drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 2 ++ 5 files changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index f9b7fc85d71a..270f8c5cfeda 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -621,7 +621,7 @@ struct dc *dc_create(const struct dc_init_data *init_params) core_dc->hwss.init_hw(core_dc); full_pipe_count = core_dc->res_pool->pipe_count; - if (core_dc->res_pool->underlay_pipe_index >= 0) + if (core_dc->res_pool->underlay_pipe_index != NO_UNDERLAY_PIPE) full_pipe_count--; core_dc->public.caps.max_streams = min( full_pipe_count, diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index ae0e7eac2c9d..dc4f270ae44a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -934,7 +934,7 @@ static bool construct( pool->base.res_cap = &res_cap; pool->base.funcs = &dce100_res_pool_funcs; - pool->base.underlay_pipe_index = -1; + pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; bp = ctx->dc_bios; @@ -1004,7 +1004,7 @@ static bool construct( /************************************************* * Resource + asic cap harcoding * *************************************************/ - pool->base.underlay_pipe_index = -1; + pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; pool->base.pipe_count = res_cap.num_timing_generator; dc->public.caps.max_downscale_ratio = 200; dc->public.caps.i2c_speed_in_khz = 40; diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 64fae91dd5eb..fa8699d3b9ef 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -1243,7 +1243,7 @@ static bool construct( /************************************************* * Resource + asic cap harcoding * *************************************************/ - pool->base.underlay_pipe_index = -1; + pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; pool->base.pipe_count = pool->base.res_cap->num_timing_generator; dc->public.caps.max_downscale_ratio = 200; dc->public.caps.i2c_speed_in_khz = 100; diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index bee3a41ffe9f..fea60aa5d297 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -931,7 +931,7 @@ static bool construct( /************************************************* * Resource + asic cap harcoding * *************************************************/ - pool->base.underlay_pipe_index = -1; + pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; pool->base.pipe_count = res_cap.num_timing_generator; dc->public.caps.max_downscale_ratio = 200; dc->public.caps.i2c_speed_in_khz = 40; diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 66bfcdb57c4c..b349b5768b6e 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -230,6 +230,8 @@ struct audio_support{ bool hdmi_audio_native; }; +#define NO_UNDERLAY_PIPE -1 + struct resource_pool { struct mem_input *mis[MAX_PIPES]; struct input_pixel_processor *ipps[MAX_PIPES]; -- cgit From cad3c7a99725f5f241ee7e8e1657c54c5b532d51 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 19 Jan 2017 18:58:33 -0500 Subject: drm/amd/display: Remove power gating debug flags They're not used anywhere Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index e0143f9f0421..332ecf8b1157 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -145,8 +145,6 @@ struct dc_debug { bool disable_stutter; bool disable_dcc; bool disable_dfs_bypass; - bool disable_dpp_power_gate; - bool disable_hubp_power_gate; bool disable_clock_gate; bool disable_dmcu; bool disable_color_module; -- cgit From 9c1a57d79dbc96e808ea81aa1385f2d9d03570a0 Mon Sep 17 00:00:00 2001 From: Leon Elazar Date: Tue, 17 Jan 2017 16:16:04 -0500 Subject: drm/amd/display: check surface size is at least as large as stream Signed-off-by: Leon Elazar Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c | 4 ++-- drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 82cddb6425a0..0b8f8927162f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -967,9 +967,9 @@ static bool dce110_validate_surface_sets( return false; if (set[i].surfaces[0]->src_rect.width - != set[i].stream->src.width + < set[i].stream->src.width || set[i].surfaces[0]->src_rect.height - != set[i].stream->src.height) + < set[i].stream->src.height) return false; if (set[i].surfaces[0]->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index fa8699d3b9ef..7c12185b1dbe 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -966,9 +966,9 @@ static bool dce112_validate_surface_sets( return false; if (set[i].surfaces[0]->clip_rect.width - != set[i].stream->src.width + < set[i].stream->src.width || set[i].surfaces[0]->clip_rect.height - != set[i].stream->src.height) + < set[i].stream->src.height) return false; if (set[i].surfaces[0]->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) -- cgit From 4d35b093e635de739d0bdcbb57244424cb1abb61 Mon Sep 17 00:00:00 2001 From: Joshua Aberback Date: Tue, 17 Jan 2017 16:01:35 -0500 Subject: drm/amd/display: Proper de-allocation of OPP - refactor opp_destroy functions to dce common file - fixes memory leak, dce specific variations didn't free regamma_params - remove unused dce110_regamma structure Signed-off-by: Joshua Aberback Reviewed-by: Jun Lei Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_opp.c | 10 ++++--- drivers/gpu/drm/amd/display/dc/dce/dce_opp.h | 35 ---------------------- .../drm/amd/display/dc/dce100/dce100_resource.c | 26 +--------------- .../drm/amd/display/dc/dce112/dce112_resource.c | 26 +--------------- 4 files changed, 8 insertions(+), 89 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c index 061de9e8249d..62f01911639f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c @@ -986,10 +986,12 @@ bool dce110_opp_construct(struct dce110_opp *opp110, void dce110_opp_destroy(struct output_pixel_processor **opp) { - dm_free((*opp)->regamma_params); - (*opp)->regamma_params = NULL; - - dm_free(FROM_DCE11_OPP(*opp)); + if (*opp) { + if ((*opp)->regamma_params) + dm_free((*opp)->regamma_params); + (*opp)->regamma_params = NULL; + dm_free(FROM_DCE11_OPP(*opp)); + } *opp = NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h index f2828f044b96..a5afc0298d6f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h @@ -312,40 +312,6 @@ struct dce_opp_registers { uint32_t FMT_CLAMP_COMPONENT_B; }; -struct dce110_regamma { - struct gamma_curve arr_curve_points[16]; - struct curve_points arr_points[3]; - uint32_t hw_points_num; - struct hw_x_point *coordinates_x; - struct pwl_result_data *rgb_resulted; - - /* re-gamma curve */ - struct pwl_float_data_ex *rgb_regamma; - /* coeff used to map user evenly distributed points - * to our hardware points (predefined) for gamma 256 */ - struct pixel_gamma_point *coeff128; - struct pixel_gamma_point *coeff128_oem; - /* coeff used to map user evenly distributed points - * to our hardware points (predefined) for gamma 1025 */ - struct pixel_gamma_point *coeff128_dx; - /* evenly distributed points, gamma 256 software points 0-255 */ - struct gamma_pixel *axis_x_256; - /* evenly distributed points, gamma 1025 software points 0-1025 */ - struct gamma_pixel *axis_x_1025; - /* OEM supplied gamma for regamma LUT */ - struct pwl_float_data *rgb_oem; - /* user supplied gamma */ - struct pwl_float_data *rgb_user; - uint32_t extra_points; - bool use_half_points; - struct fixed31_32 x_max1; - struct fixed31_32 x_max2; - struct fixed31_32 x_min; - struct fixed31_32 divider1; - struct fixed31_32 divider2; - struct fixed31_32 divider3; -}; - /* OPP RELATED */ #define TO_DCE110_OPP(opp)\ container_of(opp, struct dce110_opp, base) @@ -355,7 +321,6 @@ struct dce110_opp { const struct dce_opp_registers *regs; const struct dce_opp_shift *opp_shift; const struct dce_opp_mask *opp_mask; - struct dce110_regamma regamma; }; bool dce110_opp_construct(struct dce110_opp *opp110, diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index dc4f270ae44a..6ae334b42fbf 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -633,30 +633,6 @@ struct output_pixel_processor *dce100_opp_create( return NULL; } -void dce100_opp_destroy(struct output_pixel_processor **opp) -{ - struct dce110_opp *dce110_opp; - - if (!opp || !*opp) - return; - - dce110_opp = FROM_DCE11_OPP(*opp); - - dm_free(dce110_opp->regamma.coeff128_dx); - dm_free(dce110_opp->regamma.coeff128_oem); - dm_free(dce110_opp->regamma.coeff128); - dm_free(dce110_opp->regamma.axis_x_1025); - dm_free(dce110_opp->regamma.axis_x_256); - dm_free(dce110_opp->regamma.coordinates_x); - dm_free(dce110_opp->regamma.rgb_regamma); - dm_free(dce110_opp->regamma.rgb_resulted); - dm_free(dce110_opp->regamma.rgb_oem); - dm_free(dce110_opp->regamma.rgb_user); - dm_free(dce110_opp); - - *opp = NULL; -} - struct clock_source *dce100_clock_source_create( struct dc_context *ctx, struct dc_bios *bios, @@ -692,7 +668,7 @@ static void destruct(struct dce110_resource_pool *pool) for (i = 0; i < pool->base.pipe_count; i++) { if (pool->base.opps[i] != NULL) - dce100_opp_destroy(&pool->base.opps[i]); + dce110_opp_destroy(&pool->base.opps[i]); if (pool->base.transforms[i] != NULL) dce100_transform_destroy(&pool->base.transforms[i]); diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 7c12185b1dbe..cc826efac58d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -645,30 +645,6 @@ struct output_pixel_processor *dce112_opp_create( return NULL; } -void dce112_opp_destroy(struct output_pixel_processor **opp) -{ - struct dce110_opp *dce110_opp; - - if (!opp || !*opp) - return; - - dce110_opp = FROM_DCE11_OPP(*opp); - - dm_free(dce110_opp->regamma.coeff128_dx); - dm_free(dce110_opp->regamma.coeff128_oem); - dm_free(dce110_opp->regamma.coeff128); - dm_free(dce110_opp->regamma.axis_x_1025); - dm_free(dce110_opp->regamma.axis_x_256); - dm_free(dce110_opp->regamma.coordinates_x); - dm_free(dce110_opp->regamma.rgb_regamma); - dm_free(dce110_opp->regamma.rgb_resulted); - dm_free(dce110_opp->regamma.rgb_oem); - dm_free(dce110_opp->regamma.rgb_user); - - dm_free(dce110_opp); - *opp = NULL; -} - struct clock_source *dce112_clock_source_create( struct dc_context *ctx, struct dc_bios *bios, @@ -704,7 +680,7 @@ static void destruct(struct dce110_resource_pool *pool) for (i = 0; i < pool->base.pipe_count; i++) { if (pool->base.opps[i] != NULL) - dce112_opp_destroy(&pool->base.opps[i]); + dce110_opp_destroy(&pool->base.opps[i]); if (pool->base.transforms[i] != NULL) dce112_transform_destroy(&pool->base.transforms[i]); -- cgit From dcbd4ee0fabcc1f6a40d67e8a8621e9ac5a382ac Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Thu, 19 Jan 2017 10:53:58 -0500 Subject: drm/amd/display: Change update surface condition, fix surface transition corruption. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 270f8c5cfeda..de6ef8713ea8 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1497,7 +1497,6 @@ void dc_update_surfaces_for_stream(struct dc *dc, struct dc_surface_update *upda for (i = 0; i < surface_count; i++) { struct core_surface *surface = DC_SURFACE_TO_CORE(updates[i].surface); - bool apply_ctx = false; for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; @@ -1505,13 +1504,9 @@ void dc_update_surfaces_for_stream(struct dc *dc, struct dc_surface_update *upda if (pipe_ctx->surface != surface) continue; - if (updates[i].flip_addr) { + if (updates[i].flip_addr && can_skip_context_building) { core_dc->hwss.update_plane_addr(core_dc, pipe_ctx); - } - - if (updates[i].plane_info || updates[i].scaling_info - || is_new_pipe_surface[j]) { - apply_ctx = true; + } else { if (!pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) { core_dc->hwss.pipe_control_lock( @@ -1546,7 +1541,7 @@ void dc_update_surfaces_for_stream(struct dc *dc, struct dc_surface_update *upda } } - if (apply_ctx) { + if (!can_skip_context_building) { core_dc->hwss.apply_ctx_for_surface(core_dc, surface, context); context_timing_trace(dc, &context->res_ctx); } -- cgit From 0be06fc29b31d92a22180deaf866ad5f97133a9e Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Thu, 19 Jan 2017 17:54:39 -0500 Subject: drm/amd/display: prevent setting cursor position with no surface Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 47816c5ee0e0..e1f579bcd789 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -232,8 +232,8 @@ bool dc_stream_set_cursor_position( for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; - if ((pipe_ctx->stream == stream) && - (pipe_ctx->ipp != NULL)) { + if (pipe_ctx->stream == stream && + pipe_ctx->ipp && pipe_ctx->surface) { struct input_pixel_processor *ipp = pipe_ctx->ipp; struct dc_cursor_mi_param param = { .pixel_clk_khz = dc_stream->timing.pix_clk_khz, -- cgit From fde2deae86220eb5c3f88bf5ee9ff47175810b34 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Thu, 19 Jan 2017 10:57:56 -0500 Subject: drm/amd/display: improve debug-ability - make failure status obvious Signed-off-by: Tony Cheng Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/inc/core_status.h | 26 ++++++++++++------------ 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_status.h b/drivers/gpu/drm/amd/display/dc/inc/core_status.h index 147eb7cac701..23d52aea55dd 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_status.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_status.h @@ -29,19 +29,19 @@ enum dc_status { DC_OK = 1, - DC_NO_CONTROLLER_RESOURCE, - DC_NO_STREAM_ENG_RESOURCE, - DC_NO_CLOCK_SOURCE_RESOURCE, - DC_FAIL_CONTROLLER_VALIDATE, - DC_FAIL_ENC_VALIDATE, - DC_FAIL_ATTACH_SURFACES, - DC_FAIL_SURFACE_VALIDATE, - DC_NO_DP_LINK_BANDWIDTH, - DC_EXCEED_DONGLE_MAX_CLK, - DC_SURFACE_PIXEL_FORMAT_UNSUPPORTED, - DC_FAIL_BANDWIDTH_VALIDATE, /* BW and Watermark validation */ - DC_FAIL_SCALING, - DC_FAIL_CLK_CONSTRAINT, + DC_NO_CONTROLLER_RESOURCE = 2, + DC_NO_STREAM_ENG_RESOURCE = 3, + DC_NO_CLOCK_SOURCE_RESOURCE = 4, + DC_FAIL_CONTROLLER_VALIDATE = 5, + DC_FAIL_ENC_VALIDATE = 6, + DC_FAIL_ATTACH_SURFACES = 7, + DC_FAIL_SURFACE_VALIDATE = 8, + DC_NO_DP_LINK_BANDWIDTH = 9, + DC_EXCEED_DONGLE_MAX_CLK = 10, + DC_SURFACE_PIXEL_FORMAT_UNSUPPORTED = 11, + DC_FAIL_BANDWIDTH_VALIDATE = 12, /* BW and Watermark validation */ + DC_FAIL_SCALING = 13, + DC_FAIL_CLK_CONSTRAINT = 14, DC_ERROR_UNEXPECTED = -1 }; -- cgit From e72f0acd369d3ddfa6e924279d4010bcdb3de31b Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Thu, 19 Jan 2017 23:57:09 -0500 Subject: drm/amd/display: refactor dc_update_surfaces_for_stream - reuse existing helper functions - helper function to make it more obvious which cases we can do optimize programming Signed-off-by: Tony Cheng Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 367 ++++++++++++++++++------------- 1 file changed, 212 insertions(+), 155 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index de6ef8713ea8..170936bb378a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1007,7 +1007,7 @@ bool dc_commit_streams( struct dc_bios *dcb = core_dc->ctx->dc_bios; enum dc_status result = DC_ERROR_UNEXPECTED; struct validate_context *context; - struct dc_validation_set set[MAX_STREAMS] = { 0 }; + struct dc_validation_set set[MAX_STREAMS] = { {0, {0} } }; int i, j, k; if (false == streams_changed(core_dc, streams, stream_count)) @@ -1321,80 +1321,167 @@ bool dc_commit_surfaces_to_stream( return dc_post_update_surfaces_to_stream(dc); } -void dc_update_surfaces_for_stream(struct dc *dc, struct dc_surface_update *updates, - int surface_count, const struct dc_stream *dc_stream) +static bool is_surface_in_context( + const struct validate_context *context, + const struct dc_surface *surface) { - struct core_dc *core_dc = DC_TO_CORE(dc); - struct validate_context *context = core_dc->temp_flip_context; - int i, j; - bool is_new_pipe_surface[MAX_PIPES]; - const struct dc_surface *new_surfaces[MAX_SURFACES] = { 0 }; - bool need_apply_clk_constraints = false; - bool can_skip_context_building = true; + int j; - update_surface_trace(dc, updates, surface_count); + for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { + const struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - *context = *core_dc->current_context; + if (surface == &pipe_ctx->surface->public) { + return true; + } + } - for (i = 0; i < context->res_ctx.pool->pipe_count; i++) { - struct pipe_ctx *cur_pipe = &context->res_ctx.pipe_ctx[i]; + return false; +} - if (cur_pipe->top_pipe) - cur_pipe->top_pipe = - &context->res_ctx.pipe_ctx[cur_pipe->top_pipe->pipe_idx]; +enum surface_update_type { + UPDATE_TYPE_FAST, /* super fast, safe to execute in isr */ + UPDATE_TYPE_MED, /* a lot of programming needed. may need to alloc */ + UPDATE_TYPE_FULL, /* may need to shuffle resources */ +}; - if (cur_pipe->bottom_pipe) - cur_pipe->bottom_pipe = - &context->res_ctx.pipe_ctx[cur_pipe->bottom_pipe->pipe_idx]; - } +static enum surface_update_type det_surface_update( + const struct core_dc *dc, + const struct dc_surface_update *u) +{ + const struct validate_context *context = dc->current_context; - for (j = 0; j < MAX_PIPES; j++) - is_new_pipe_surface[j] = true; + if (u->scaling_info || u->plane_info) + /* todo: not all scale and plane_info update need full update + * ie. check if following is the same + * scale ratio, view port, surface bpp etc + */ + return UPDATE_TYPE_FULL; /* may need bandwidth update */ - for (i = 0 ; i < surface_count; i++) { - struct core_surface *surface = DC_SURFACE_TO_CORE(updates[i].surface); - bool existing_surface = false; + if (!is_surface_in_context(context, u->surface)) + return UPDATE_TYPE_FULL; - new_surfaces[i] = updates[i].surface; + if (u->in_transfer_func || + u->out_transfer_func || + u->hdr_static_metadata) + return UPDATE_TYPE_MED; - for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; + return UPDATE_TYPE_FAST; +} - if (surface == pipe_ctx->surface) { - existing_surface = true; - is_new_pipe_surface[j] = false; - } - } +static enum surface_update_type check_update_surfaces_for_stream( + struct core_dc *dc, + struct dc_surface_update *updates, + int surface_count, + const struct dc_stream_status *stream_status) +{ + int i; + enum surface_update_type overall_type = UPDATE_TYPE_FAST; - if (updates[i].plane_info || - updates[i].scaling_info || - !existing_surface) - can_skip_context_building = false; + if (stream_status->surface_count != surface_count) + return UPDATE_TYPE_FULL; + + for (i = 0 ; i < surface_count; i++) { + enum surface_update_type type = + det_surface_update(dc, &updates[i]); + + if (type == UPDATE_TYPE_FULL) + return type; + + if (overall_type < type) + overall_type = type; } - if (!can_skip_context_building && dc_stream) { - const struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); + return overall_type; +} - if (core_dc->current_context->stream_count == 0) - return; +enum surface_update_type update_surface_trace_level = UPDATE_TYPE_FULL; - /* Cannot commit surface to a stream that is not commited */ - for (i = 0; i < core_dc->current_context->stream_count; i++) - if (stream == core_dc->current_context->streams[i]) - break; - if (i == core_dc->current_context->stream_count) - return; +void dc_update_surfaces_for_stream(struct dc *dc, + struct dc_surface_update *updates, int surface_count, + const struct dc_stream *dc_stream) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + struct validate_context *context; + int i, j; + + enum surface_update_type update_type; + const struct dc_stream_status *stream_status; + + stream_status = dc_stream_get_status(dc_stream); + ASSERT(stream_status); + if (!stream_status) + return; /* Cannot commit surface to stream that is not committed */ + + update_type = check_update_surfaces_for_stream( + core_dc, updates, surface_count, stream_status); + + if (update_type >= update_surface_trace_level) + update_surface_trace(dc, updates, surface_count); + if (update_type >= UPDATE_TYPE_FULL) { + const struct dc_surface *new_surfaces[MAX_SURFACES] = { 0 }; + + for (i = 0; i < surface_count; i++) + new_surfaces[i] = updates[i].surface; + + /* initialize scratch memory for building context */ + context = core_dc->temp_flip_context; + resource_validate_ctx_copy_construct( + core_dc->current_context, context); + + /* add surface to context */ if (!resource_attach_surfaces_to_context( new_surfaces, surface_count, dc_stream, context)) { BREAK_TO_DEBUGGER(); return; } + } else { + context = core_dc->current_context; } - for (i = 0; i < surface_count; i++) { + /* save update param into surface */ struct core_surface *surface = DC_SURFACE_TO_CORE(updates[i].surface); + struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); + if (updates[i].flip_addr) { + surface->public.address = updates[i].flip_addr->address; + surface->public.flip_immediate = + updates[i].flip_addr->flip_immediate; + } + + if (updates[i].scaling_info) { + surface->public.scaling_quality = + updates[i].scaling_info->scaling_quality; + surface->public.dst_rect = + updates[i].scaling_info->dst_rect; + surface->public.src_rect = + updates[i].scaling_info->src_rect; + surface->public.clip_rect = + updates[i].scaling_info->clip_rect; + } + + if (updates[i].plane_info) { + surface->public.color_space = + updates[i].plane_info->color_space; + surface->public.format = + updates[i].plane_info->format; + surface->public.plane_size = + updates[i].plane_info->plane_size; + surface->public.rotation = + updates[i].plane_info->rotation; + surface->public.horizontal_mirror = + updates[i].plane_info->horizontal_mirror; + surface->public.stereo_format = + updates[i].plane_info->stereo_format; + surface->public.tiling_info = + updates[i].plane_info->tiling_info; + surface->public.visible = + updates[i].plane_info->visible; + surface->public.dcc = + updates[i].plane_info->dcc; + } + + /* not sure if we still need this */ for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; struct core_stream *stream = pipe_ctx->stream; @@ -1402,133 +1489,101 @@ void dc_update_surfaces_for_stream(struct dc *dc, struct dc_surface_update *upda if (pipe_ctx->surface != surface) continue; - if (updates[i].flip_addr) { - surface->public.address = updates[i].flip_addr->address; - surface->public.flip_immediate = - updates[i].flip_addr->flip_immediate; - } - - if (updates[i].plane_info || updates[i].scaling_info - || is_new_pipe_surface[j]) { - need_apply_clk_constraints = true; - - if (updates[i].plane_info) { - surface->public.color_space = - updates[i].plane_info->color_space; - surface->public.format = - updates[i].plane_info->format; - surface->public.plane_size = - updates[i].plane_info->plane_size; - surface->public.rotation = - updates[i].plane_info->rotation; - surface->public.horizontal_mirror = - updates[i].plane_info->horizontal_mirror; - surface->public.stereo_format = - updates[i].plane_info->stereo_format; - surface->public.tiling_info = - updates[i].plane_info->tiling_info; - surface->public.visible = - updates[i].plane_info->visible; - surface->public.dcc = - updates[i].plane_info->dcc; - } - - if (updates[i].scaling_info) { - surface->public.scaling_quality = - updates[i].scaling_info->scaling_quality; - surface->public.dst_rect = - updates[i].scaling_info->dst_rect; - surface->public.src_rect = - updates[i].scaling_info->src_rect; - surface->public.clip_rect = - updates[i].scaling_info->clip_rect; - } - - resource_build_scaling_params(updates[i].surface, pipe_ctx); - if (dc->debug.surface_visual_confirm) { - pipe_ctx->scl_data.recout.height -= 2; - pipe_ctx->scl_data.recout.width -= 2; - } + resource_build_scaling_params(updates[i].surface, pipe_ctx); + if (dc->debug.surface_visual_confirm) { + pipe_ctx->scl_data.recout.height -= 2; + pipe_ctx->scl_data.recout.width -= 2; } + } - if (dc->debug.disable_color_module) - continue; /* skip below color updates */ + if (dc->debug.disable_color_module) + continue; /* skip below color updates */ - if (updates[i].gamma && - updates[i].gamma != surface->public.gamma_correction) { - if (surface->public.gamma_correction != NULL) - dc_gamma_release(&surface->public. - gamma_correction); + if (updates[i].gamma && + updates[i].gamma != surface->public.gamma_correction) { + if (surface->public.gamma_correction != NULL) + dc_gamma_release(&surface->public. + gamma_correction); - dc_gamma_retain(updates[i].gamma); - surface->public.gamma_correction = - updates[i].gamma; - } + dc_gamma_retain(updates[i].gamma); + surface->public.gamma_correction = + updates[i].gamma; + } - if (updates[i].in_transfer_func && - updates[i].in_transfer_func != surface->public.in_transfer_func) { - if (surface->public.in_transfer_func != NULL) - dc_transfer_func_release( - surface->public. - in_transfer_func); - - dc_transfer_func_retain( - updates[i].in_transfer_func); - surface->public.in_transfer_func = - updates[i].in_transfer_func; - } + if (updates[i].in_transfer_func && + updates[i].in_transfer_func != surface->public.in_transfer_func) { + if (surface->public.in_transfer_func != NULL) + dc_transfer_func_release( + surface->public. + in_transfer_func); + + dc_transfer_func_retain( + updates[i].in_transfer_func); + surface->public.in_transfer_func = + updates[i].in_transfer_func; + } - if (updates[i].out_transfer_func && - updates[i].out_transfer_func != stream->public.out_transfer_func) { - if (stream->public.out_transfer_func != NULL) - dc_transfer_func_release( - stream->public. - out_transfer_func); - dc_transfer_func_retain( - updates[i].out_transfer_func); - stream->public.out_transfer_func = - updates[i].out_transfer_func; - } - if (updates[i].hdr_static_metadata) - surface->public.hdr_static_ctx = - *(updates[i].hdr_static_metadata); + if (updates[i].out_transfer_func && + updates[i].out_transfer_func != dc_stream->out_transfer_func) { + if (dc_stream->out_transfer_func != NULL) + dc_transfer_func_release(dc_stream->out_transfer_func); + dc_transfer_func_retain(updates[i].out_transfer_func); + stream->public.out_transfer_func = updates[i].out_transfer_func; } + if (updates[i].hdr_static_metadata) + surface->public.hdr_static_ctx = + *(updates[i].hdr_static_metadata); } + + if (!surface_count) /* reset */ + core_dc->hwss.apply_ctx_for_surface(core_dc, NULL, context); + for (i = 0; i < surface_count; i++) { struct core_surface *surface = DC_SURFACE_TO_CORE(updates[i].surface); for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; + struct pipe_ctx *cur_pipe_ctx; + bool is_new_pipe_surface = true; if (pipe_ctx->surface != surface) continue; - if (updates[i].flip_addr && can_skip_context_building) { - core_dc->hwss.update_plane_addr(core_dc, pipe_ctx); - } else { + if (update_type != UPDATE_TYPE_FAST && + !pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) { + core_dc->hwss.pipe_control_lock( + core_dc->hwseq, + pipe_ctx->pipe_idx, + PIPE_LOCK_CONTROL_GRAPHICS | + PIPE_LOCK_CONTROL_SCL | + PIPE_LOCK_CONTROL_BLENDER | + PIPE_LOCK_CONTROL_MODE, + true); + } - if (!pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) { - core_dc->hwss.pipe_control_lock( - core_dc->hwseq, - pipe_ctx->pipe_idx, - PIPE_LOCK_CONTROL_GRAPHICS | - PIPE_LOCK_CONTROL_SCL | - PIPE_LOCK_CONTROL_BLENDER | - PIPE_LOCK_CONTROL_MODE, - true); - } + if (update_type == UPDATE_TYPE_FULL) { + core_dc->hwss.apply_ctx_for_surface(core_dc, surface, context); + } else if (updates[i].flip_addr) { + core_dc->hwss.update_plane_addr(core_dc, pipe_ctx); } + if (update_type == UPDATE_TYPE_FAST) + continue; + + cur_pipe_ctx = &core_dc->current_context->res_ctx.pipe_ctx[j]; + if (cur_pipe_ctx->surface == pipe_ctx->surface) + is_new_pipe_surface = false; + if (dc->debug.disable_color_module) continue; /* skip below color updates */ - if (is_new_pipe_surface[j] || + if (is_new_pipe_surface || updates[i].in_transfer_func) core_dc->hwss.set_input_transfer_func( pipe_ctx, pipe_ctx->surface); - if (is_new_pipe_surface[j] || + if (is_new_pipe_surface || updates[i].out_transfer_func) core_dc->hwss.set_output_transfer_func( pipe_ctx, @@ -1539,14 +1594,12 @@ void dc_update_surfaces_for_stream(struct dc *dc, struct dc_surface_update *upda resource_build_info_frame(pipe_ctx); core_dc->hwss.update_info_frame(pipe_ctx); } - - } - if (!can_skip_context_building) { - core_dc->hwss.apply_ctx_for_surface(core_dc, surface, context); - context_timing_trace(dc, &context->res_ctx); } } + if (update_type == UPDATE_TYPE_FAST) + return; + for (i = context->res_ctx.pool->pipe_count - 1; i >= 0; i--) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; @@ -1566,8 +1619,12 @@ void dc_update_surfaces_for_stream(struct dc *dc, struct dc_surface_update *upda } } - core_dc->temp_flip_context = core_dc->current_context; - core_dc->current_context = context; + if (core_dc->current_context != context) { + resource_validate_ctx_destruct(core_dc->current_context); + core_dc->temp_flip_context = core_dc->current_context; + + core_dc->current_context = context; + } } uint8_t dc_get_current_stream_count(const struct dc *dc) -- cgit From e4e354b02fa8b6d53ec65bd5dbd27d014e4e752f Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Thu, 19 Jan 2017 14:46:26 -0500 Subject: drm/amd/display: clean up redundant logic Signed-off-by: Tony Cheng Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_surface.c | 23 ++++++++--------------- drivers/gpu/drm/amd/display/dc/dc.h | 1 - 2 files changed, 8 insertions(+), 16 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index d607972b830b..21fedd447bd1 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -121,26 +121,20 @@ const struct dc_surface_status *dc_surface_get_status( const struct dc_surface *dc_surface) { struct dc_surface_status *surface_status; - struct core_surface *core_surface; + struct core_surface *core_surface = DC_SURFACE_TO_CORE(dc_surface);; struct core_dc *core_dc; int i; - if (dc_surface == NULL) - return NULL; - - core_surface = DC_SURFACE_TO_CORE(dc_surface); - - if (core_surface == NULL || core_surface->ctx == NULL) - return NULL; + if (!dc_surface || + !core_surface->ctx || + !core_surface->ctx->dc) { + ASSERT(0); + return NULL; /* remove this if above assert never hit */ + } surface_status = &core_surface->status; - - if (core_surface->ctx == NULL || core_surface->ctx->dc == NULL) - return NULL; - core_dc = DC_TO_CORE(core_surface->ctx->dc); - if (core_dc->current_context == NULL) return NULL; @@ -149,8 +143,7 @@ const struct dc_surface_status *dc_surface_get_status( struct pipe_ctx *pipe_ctx = &core_dc->current_context->res_ctx.pipe_ctx[i]; - if (pipe_ctx->surface != - DC_SURFACE_TO_CORE(dc_surface)) + if (pipe_ctx->surface != core_surface) continue; core_dc->hwss.update_pending_status(pipe_ctx); diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 332ecf8b1157..c3aca8d44d4c 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -335,7 +335,6 @@ struct dc_transfer_func *dc_create_transfer_func(void); struct dc_flip_addrs { struct dc_plane_address address; bool flip_immediate; - /* TODO: DCC format info */ /* TODO: add flip duration for FreeSync */ }; -- cgit From 86e2e1bee07134f712cb6b807b7f0205057bd11e Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Fri, 20 Jan 2017 15:54:13 -0500 Subject: drm/amd/display: Check we got a stream in update_info_frame Signed-off-by: Hersen Wu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 6dbfc570b8c6..ce56f23806bc 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -837,6 +837,11 @@ static enum dc_status bios_parser_crtc_source_select( void dce110_update_info_frame(struct pipe_ctx *pipe_ctx) { + ASSERT(pipe_ctx->stream); + + if (pipe_ctx->stream_enc == NULL) + return; /* this is not root pipe */ + if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) pipe_ctx->stream_enc->funcs->update_hdmi_info_packets( pipe_ctx->stream_enc, -- cgit From ed1519403227490d517c2d59755d68d3c31afa12 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Mon, 23 Jan 2017 17:10:04 -0500 Subject: drm/amd/display: Fixed 4K black issue by refactor update surface. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 170936bb378a..01d614781def 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1482,17 +1482,19 @@ void dc_update_surfaces_for_stream(struct dc *dc, } /* not sure if we still need this */ - for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - struct core_stream *stream = pipe_ctx->stream; + if (update_type == UPDATE_TYPE_FULL) { + for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; + struct core_stream *stream = pipe_ctx->stream; - if (pipe_ctx->surface != surface) - continue; + if (pipe_ctx->surface != surface) + continue; - resource_build_scaling_params(updates[i].surface, pipe_ctx); - if (dc->debug.surface_visual_confirm) { - pipe_ctx->scl_data.recout.height -= 2; - pipe_ctx->scl_data.recout.width -= 2; + resource_build_scaling_params(updates[i].surface, pipe_ctx); + if (dc->debug.surface_visual_confirm) { + pipe_ctx->scl_data.recout.height -= 2; + pipe_ctx->scl_data.recout.width -= 2; + } } } @@ -1563,10 +1565,12 @@ void dc_update_surfaces_for_stream(struct dc *dc, } if (update_type == UPDATE_TYPE_FULL) { - core_dc->hwss.apply_ctx_for_surface(core_dc, surface, context); - } else if (updates[i].flip_addr) { + /* only apply for top pipe */ + if (!pipe_ctx->top_pipe) + core_dc->hwss.apply_ctx_for_surface(core_dc, + surface, context); + } else if (updates[i].flip_addr) core_dc->hwss.update_plane_addr(core_dc, pipe_ctx); - } if (update_type == UPDATE_TYPE_FAST) continue; -- cgit From 954815153b4b1213237d389be15d5448f67154ff Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Mon, 23 Jan 2017 17:51:17 -0500 Subject: drm/amd/display: enable color gamma programming Signed-off-by: Tony Cheng Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 6 ------ drivers/gpu/drm/amd/display/dc/dc.h | 1 - 2 files changed, 7 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 01d614781def..c627b907528c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1498,9 +1498,6 @@ void dc_update_surfaces_for_stream(struct dc *dc, } } - if (dc->debug.disable_color_module) - continue; /* skip below color updates */ - if (updates[i].gamma && updates[i].gamma != surface->public.gamma_correction) { if (surface->public.gamma_correction != NULL) @@ -1579,9 +1576,6 @@ void dc_update_surfaces_for_stream(struct dc *dc, if (cur_pipe_ctx->surface == pipe_ctx->surface) is_new_pipe_surface = false; - if (dc->debug.disable_color_module) - continue; /* skip below color updates */ - if (is_new_pipe_surface || updates[i].in_transfer_func) core_dc->hwss.set_input_transfer_func( diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index c3aca8d44d4c..f485f70bf3ef 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -147,7 +147,6 @@ struct dc_debug { bool disable_dfs_bypass; bool disable_clock_gate; bool disable_dmcu; - bool disable_color_module; }; struct dc { -- cgit From 23ae4f8e59c926df806ba837b2a2040984077641 Mon Sep 17 00:00:00 2001 From: Amy Zhang Date: Tue, 24 Jan 2017 09:50:05 -0500 Subject: drm/amd/display: Fix Warnings - Remove mixed declarations and unused variables Signed-off-by: Amy Zhang Reviewed-by: Anthony Koo Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 24 +++++++++++++--------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index ce56f23806bc..c3e0865f3148 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -581,12 +581,10 @@ static bool convert_to_custom_float( static bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func *output_tf, struct pwl_params *regamma_params) { - if (output_tf == NULL || regamma_params == NULL) - return false; - - struct gamma_curve *arr_curve_points = regamma_params->arr_curve_points; - struct curve_points *arr_points = regamma_params->arr_points; - struct pwl_result_data *rgb_resulted = regamma_params->rgb_resulted; + struct curve_points *arr_points; + struct pwl_result_data *rgb_resulted; + struct pwl_result_data *rgb; + struct pwl_result_data *rgb_plus_1; struct fixed31_32 y_r; struct fixed31_32 y_g; struct fixed31_32 y_b; @@ -594,8 +592,14 @@ static bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func struct fixed31_32 y3_max; int32_t segment_start, segment_end; - uint32_t i, j, k, seg_distr[16], increment, start_index; - uint32_t hw_points = 0; + uint32_t i, j, k, seg_distr[16], increment, start_index, hw_points; + + if (output_tf == NULL || regamma_params == NULL) + return false; + + arr_points = regamma_params->arr_points; + rgb_resulted = regamma_params->rgb_resulted; + hw_points = 0; memset(regamma_params, 0, sizeof(struct pwl_params)); @@ -742,8 +746,8 @@ static bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func regamma_params->arr_curve_points[k].segments_num = seg_distr[k]; - struct pwl_result_data *rgb = rgb_resulted; - struct pwl_result_data *rgb_plus_1 = rgb_resulted + 1; + rgb = rgb_resulted; + rgb_plus_1 = rgb_resulted + 1; i = 1; -- cgit From 37d66a339b6f29251ebe0da78816d6d07554c617 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 20 Jan 2017 17:14:23 -0500 Subject: drm/amd/display: fix timing trace debug print Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 4 +++- drivers/gpu/drm/amd/display/dc/core/dc_debug.c | 18 ++++++++++++------ 2 files changed, 15 insertions(+), 7 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index c627b907528c..c863bffab989 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1563,9 +1563,11 @@ void dc_update_surfaces_for_stream(struct dc *dc, if (update_type == UPDATE_TYPE_FULL) { /* only apply for top pipe */ - if (!pipe_ctx->top_pipe) + if (!pipe_ctx->top_pipe) { core_dc->hwss.apply_ctx_for_surface(core_dc, surface, context); + context_timing_trace(dc, &context->res_ctx); + } } else if (updates[i].flip_addr) core_dc->hwss.update_plane_addr(core_dc, pipe_ctx); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c index 959c3f372e73..85ddf5fc4291 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c @@ -279,20 +279,26 @@ void context_timing_trace( int i; struct core_dc *core_dc = DC_TO_CORE(dc); struct dal_logger *logger = core_dc->ctx->logger; + int h_pos[MAX_PIPES], v_pos[MAX_PIPES]; for (i = 0; i < core_dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; - int h_pos = 0; - int v_pos = 0; if (pipe_ctx->stream == NULL) continue; - pipe_ctx->tg->funcs->get_position(pipe_ctx->tg, &h_pos, &v_pos); - TIMING_TRACE("Pipe_%d H_tot:%d V_tot:%d H_pos:%d V_pos:%d\n", - pipe_ctx->pipe_idx, + pipe_ctx->tg->funcs->get_position(pipe_ctx->tg, &h_pos[i], &v_pos[i]); + } + for (i = 0; i < core_dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; + + if (pipe_ctx->stream == NULL) + continue; + + TIMING_TRACE("OTG_%d H_tot:%d V_tot:%d H_pos:%d V_pos:%d\n", + pipe_ctx->tg->inst, pipe_ctx->stream->public.timing.h_total, pipe_ctx->stream->public.timing.v_total, - h_pos, v_pos); + h_pos[i], v_pos[i]); } } -- cgit From 17c06cab918e23b15dcf1618d9735a46fd1529f8 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 24 Jan 2017 16:06:32 -0500 Subject: drm/amd/display: Make sure to update address without flip Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index c863bffab989..75718151356d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1568,7 +1568,9 @@ void dc_update_surfaces_for_stream(struct dc *dc, surface, context); context_timing_trace(dc, &context->res_ctx); } - } else if (updates[i].flip_addr) + } + + if (updates[i].flip_addr) core_dc->hwss.update_plane_addr(core_dc, pipe_ctx); if (update_type == UPDATE_TYPE_FAST) -- cgit From 8fb234135027899e5a62e357baa7c43546a1d57b Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Tue, 24 Jan 2017 17:28:50 -0500 Subject: drm/amd/display: Rename atomic_commit parameter. This parameter name is misleading. It's previous meaning confuses with ASYNC (immidiate flip) which is totatlly different thing then nonblocking commit. Signed-off-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index ad08d6f7f094..ad60a28975ca 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2253,7 +2253,7 @@ static void remove_stream(struct amdgpu_device *adev, struct amdgpu_crtc *acrtc) int amdgpu_dm_atomic_commit( struct drm_device *dev, struct drm_atomic_state *state, - bool async) + bool nonblock) { struct amdgpu_device *adev = dev->dev_private; struct amdgpu_display_manager *dm = &adev->dm; @@ -2282,7 +2282,7 @@ int amdgpu_dm_atomic_commit( * we should not pin/unpin the fb here, it should be done in * amdgpu_crtc_flip and from the vblank irq handler. */ - if (!async) { + if (!nonblock) { ret = drm_atomic_helper_prepare_planes(dev, state); if (ret) return ret; @@ -2620,7 +2620,7 @@ int amdgpu_dm_atomic_commit( /* In this state all old framebuffers would be unpinned */ /* TODO: Revisit when we support true asynchronous commit.*/ - if (!async) + if (!nonblock) drm_atomic_helper_cleanup_planes(dev, state); drm_atomic_state_put(state); -- cgit From c7141c47d371fbe6dfbdadf92cd4abb750111a62 Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Wed, 25 Jan 2017 09:31:45 -0500 Subject: drm/amd/display: Fix compile warnings 1. Fix init of integer 2. Fix mixed declarations Signed-off-by: Anthony Koo Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/modules/freesync/freesync.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index e0703c588e47..1ee732768f6e 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -208,6 +208,8 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, struct core_stream *core_stream = NULL; struct core_dc *core_dc = NULL; struct core_freesync *core_freesync = NULL; + int persistent_freesync_enable = 0; + struct persistent_data_flag flag; if (mod_freesync == NULL) return false; @@ -216,9 +218,6 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, core_stream = DC_STREAM_TO_CORE(stream); core_dc = DC_TO_CORE(core_freesync->dc); - int persistent_freesync_enable = 0; - struct persistent_data_flag flag; - flag.save_per_edid = true; flag.save_per_link = false; @@ -779,7 +778,7 @@ bool mod_freesync_get_state(struct mod_freesync *mod_freesync, const struct dc_stream *stream, struct mod_freesync_params *freesync_params) { - unsigned int index = NULL; + unsigned int index = 0; struct core_freesync *core_freesync = NULL; if (mod_freesync == NULL) -- cgit From 7ec6b963b17a51159c38e2446499a69edf5b20e5 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Wed, 25 Jan 2017 14:51:39 -0500 Subject: drm/amd/display: Expose hw sequencer gamma function Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 2 +- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index c3e0865f3148..6acb9faf29f1 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -578,7 +578,7 @@ static bool convert_to_custom_float( return true; } -static bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func +bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func *output_tf, struct pwl_params *regamma_params) { struct curve_points *arr_points; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h index a6b4d0d2429f..68632dd28155 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h @@ -58,5 +58,8 @@ void dce110_power_down(struct core_dc *dc); void dce110_update_pending_status(struct pipe_ctx *pipe_ctx); +bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func + *output_tf, struct pwl_params *regamma_params); + #endif /* __DC_HWSS_DCE110_H__ */ -- cgit From 75a74755763062b5dd722a19b3fe7a60813ee369 Mon Sep 17 00:00:00 2001 From: Leon Elazar Date: Thu, 26 Jan 2017 18:03:16 -0500 Subject: drm/amd/display: DP compliance automation test fixes Fixes: 1. Removing pending flag since we are executing teh entire flow without context switches 2. Adding stream enablment - connection between DIG BE to DIG FE during test link training Signed-off-by: Leon Elazar Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 19 +------------------ drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 4 ++++ drivers/gpu/drm/amd/display/dc/dc_dp_types.h | 3 +-- 3 files changed, 6 insertions(+), 20 deletions(-) (limited to 'drivers/gpu') 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 c9c1b48df384..6fe5acbc16ca 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 @@ -1738,8 +1738,7 @@ static void handle_automated_test(struct core_link *link) } if (test_request.bits.LINK_TEST_PATTRN) { dp_test_send_link_test_pattern(link); - link->public.compliance_test_state.bits. - SET_TEST_PATTERN_PENDING = 1; + test_response.bits.ACK = 1; } if (test_request.bits.PHY_TEST_PATTERN) { dp_test_send_phy_test_pattern(link); @@ -2308,11 +2307,9 @@ bool dc_link_dp_set_test_pattern( unsigned int i; unsigned char link_qual_pattern[LANE_COUNT_DP_MAX] = {0}; union dpcd_training_pattern training_pattern; - union test_response test_response; enum dpcd_phy_test_patterns pattern; memset(&training_pattern, 0, sizeof(training_pattern)); - memset(&test_response, 0, sizeof(test_response)); for (i = 0; i < MAX_PIPES; i++) { if (pipes[i].stream->sink->link == core_link) { @@ -2442,20 +2439,6 @@ bool dc_link_dp_set_test_pattern( set_crtc_test_pattern(core_link, &pipe_ctx, test_pattern); /* Set Test Pattern state */ core_link->public.test_pattern_enabled = true; - - /* If this is called because of compliance test request, - * we respond ack here. - */ - if (core_link->public.compliance_test_state.bits. - SET_TEST_PATTERN_PENDING == 1) { - core_link->public.compliance_test_state.bits. - SET_TEST_PATTERN_PENDING = 0; - test_response.bits.ACK = 1; - core_link_write_dpcd(core_link, - DP_TEST_RESPONSE, - &test_response.raw, - sizeof(test_response)); - } } return true; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index b0ac94d673c4..3b814592fd70 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -251,6 +251,8 @@ void dp_retrain_link_dp_test(struct core_link *link, dp_receiver_power_ctrl(link, false); + link->dc->hwss.disable_stream(&pipes[i]); + link->link_enc->funcs->disable_output( link->link_enc, SIGNAL_TYPE_DISPLAY_PORT); @@ -273,6 +275,8 @@ void dp_retrain_link_dp_test(struct core_link *link, link->public.cur_link_settings = *link_setting; + link->dc->hwss.enable_stream(&pipes[i]); + link->dc->hwss.unblank_stream(&pipes[i], link_setting); } diff --git a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h index 1666f10a1e5c..cd2323a71760 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h @@ -432,8 +432,7 @@ union phy_test_pattern { union compliance_test_state { struct { unsigned char STEREO_3D_RUNNING : 1; - unsigned char SET_TEST_PATTERN_PENDING : 1; - unsigned char RESERVED : 6; + unsigned char RESERVED : 7; } bits; unsigned char raw; }; -- cgit From bb9042da8e8ada796cfae7e432a54e872c5b1784 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Fri, 27 Jan 2017 10:29:01 -0500 Subject: drm/amd/display: Change power gating off sequence to fix hang Power off plane clear all the reg values includes cursor. When OS call set cursor position, cursor address reg is cleared, results in system hard hang. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 75718151356d..474c2d42525d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1254,9 +1254,12 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) post_surface_trace(dc); for (i = 0; i < core_dc->current_context->res_ctx.pool->pipe_count; i++) - if (core_dc->current_context->res_ctx.pipe_ctx[i].stream == NULL) + if (core_dc->current_context->res_ctx.pipe_ctx[i].stream == NULL) { + core_dc->current_context->res_ctx.pipe_ctx[i].pipe_idx = i; core_dc->hwss.power_down_front_end( - core_dc, &core_dc->current_context->res_ctx.pipe_ctx[i]); + core_dc, &core_dc->current_context->res_ctx.pipe_ctx[i]); + } + if (core_dc->res_pool->funcs->validate_bandwidth(core_dc, core_dc->current_context) != DC_OK) { -- cgit From 5e7773a219f7821163ad2b17be0d02f8be8ce0c6 Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Mon, 23 Jan 2017 16:55:20 -0500 Subject: drm/amd/display: DMCU Compile and Load Signed-off-by: Anthony Koo Reviewed-by: Aric Cyr Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 16 -- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 12 -- drivers/gpu/drm/amd/display/dc/dc.h | 4 +- drivers/gpu/drm/amd/display/dc/dce/Makefile | 2 +- drivers/gpu/drm/amd/display/dc/dce/dce_abm.c | 214 +++++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dce/dce_abm.h | 157 +++++++++++++++ drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c | 127 ++++++++++++ drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h | 91 +++++++++ .../gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 40 +--- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 6 + .../drm/amd/display/dc/dce110/dce110_resource.c | 52 +++++ .../drm/amd/display/dc/dce112/dce112_resource.c | 51 +++++ drivers/gpu/drm/amd/display/dc/inc/core_types.h | 3 + drivers/gpu/drm/amd/display/dc/inc/hw/abm.h | 40 ++++ drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h | 42 ++++ .../gpu/drm/amd/display/dc/inc/hw/link_encoder.h | 1 - 16 files changed, 788 insertions(+), 70 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_abm.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_abm.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw/abm.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 474c2d42525d..152c694cc044 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -268,19 +268,6 @@ static bool init_dmcu_backlight_settings(struct dc *dc) return true; } - -static bool set_abm_level(struct dc *dc, unsigned int abm_level) -{ - struct core_dc *core_dc = DC_TO_CORE(dc); - int i; - - for (i = 0; i < core_dc->link_count; i++) - dc_link_set_abm_level(&core_dc->links[i]->public, - abm_level); - - return true; -} - static bool set_psr_enable(struct dc *dc, bool enable) { struct core_dc *core_dc = DC_TO_CORE(dc); @@ -409,9 +396,6 @@ static void allocate_dc_stream_funcs(struct core_dc *core_dc) core_dc->public.stream_funcs.init_dmcu_backlight_settings = init_dmcu_backlight_settings; - core_dc->public.stream_funcs.set_abm_level = - set_abm_level; - core_dc->public.stream_funcs.set_psr_enable = set_psr_enable; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index f4f46d4f0cf0..84efc25d0e33 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1432,18 +1432,6 @@ bool dc_link_init_dmcu_backlight_settings(const struct dc_link *dc_link) return true; } -bool dc_link_set_abm_level(const struct dc_link *dc_link, uint32_t level) -{ - struct core_link *link = DC_LINK_TO_CORE(dc_link); - struct dc_context *ctx = link->ctx; - - dm_logger_write(ctx->logger, LOG_BACKLIGHT, - "New abm level: %d (0x%X)\n", level, level); - - link->link_enc->funcs->set_dmcu_abm_level(link->link_enc, level); - return true; -} - bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable) { struct core_link *link = DC_LINK_TO_CORE(dc_link); diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index f485f70bf3ef..8cb53b626641 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -103,7 +103,6 @@ struct dc_stream_funcs { bool (*set_backlight)(struct dc *dc, unsigned int backlight_level, unsigned int frame_ramp, const struct dc_stream *stream); bool (*init_dmcu_backlight_settings)(struct dc *dc); - bool (*set_abm_level)(struct dc *dc, unsigned int abm_level); bool (*set_psr_enable)(struct dc *dc, bool enable); bool (*setup_psr)(struct dc *dc, const struct dc_stream *stream); }; @@ -575,8 +574,6 @@ bool dc_link_set_backlight_level(const struct dc_link *dc_link, uint32_t level, bool dc_link_init_dmcu_backlight_settings(const struct dc_link *dc_link); -bool dc_link_set_abm_level(const struct dc_link *dc_link, uint32_t level); - bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable); bool dc_link_setup_psr(const struct dc_link *dc_link, @@ -730,4 +727,5 @@ bool dc_submit_i2c( uint32_t link_index, struct i2c_command *cmd); + #endif /* DC_INTERFACE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce/Makefile b/drivers/gpu/drm/amd/display/dc/dce/Makefile index 5ad59a27738c..05562553b656 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dce/Makefile @@ -7,7 +7,7 @@ DCE = dce_audio.o dce_stream_encoder.o dce_link_encoder.o dce_hwseq.o \ dce_mem_input.o dce_clock_source.o dce_scl_filters.o dce_transform.o \ -dce_clocks.o dce_opp.o +dce_clocks.o dce_opp.o dce_dmcu.o dce_abm.o AMD_DAL_DCE = $(addprefix $(AMDDALPATH)/dc/dce/,$(DCE)) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c new file mode 100644 index 000000000000..ce49bee8e038 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c @@ -0,0 +1,214 @@ +/* + * Copyright 2012-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dce_abm.h" +#include "dm_services.h" +#include "reg_helper.h" +#include "fixed32_32.h" +#include "dc.h" + +#define TO_DCE_ABM(abm)\ + container_of(abm, struct dce_abm, base) + +#define REG(reg) \ + (abm_dce->regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + abm_dce->abm_shift->field_name, abm_dce->abm_mask->field_name + +#define CTX \ + abm_dce->base.ctx + +#define MCP_ABM_LEVEL_SET 0x65 + +static unsigned int get_current_backlight(struct dce_abm *abm_dce) +{ + uint64_t current_backlight; + uint32_t round_result; + uint32_t pwm_period_cntl, bl_period, bl_int_count; + uint32_t bl_pwm_cntl, bl_pwm, fractional_duty_cycle_en; + uint32_t bl_period_mask, bl_pwm_mask; + + pwm_period_cntl = REG_READ(BL_PWM_PERIOD_CNTL); + REG_GET(BL_PWM_PERIOD_CNTL, BL_PWM_PERIOD, &bl_period); + REG_GET(BL_PWM_PERIOD_CNTL, BL_PWM_PERIOD_BITCNT, &bl_int_count); + + bl_pwm_cntl = REG_READ(BL_PWM_CNTL); + REG_GET(BL_PWM_CNTL, BL_ACTIVE_INT_FRAC_CNT, (uint32_t *)(&bl_pwm)); + REG_GET(BL_PWM_CNTL, BL_PWM_FRACTIONAL_EN, &fractional_duty_cycle_en); + + if (bl_int_count == 0) + bl_int_count = 16; + + bl_period_mask = (1 << bl_int_count) - 1; + bl_period &= bl_period_mask; + + bl_pwm_mask = bl_period_mask << (16 - bl_int_count); + + if (fractional_duty_cycle_en == 0) + bl_pwm &= bl_pwm_mask; + else + bl_pwm &= 0xFFFF; + + current_backlight = bl_pwm << (1 + bl_int_count); + + if (bl_period == 0) + bl_period = 0xFFFF; + + current_backlight /= bl_period; + current_backlight = (current_backlight + 1) >> 1; + + current_backlight = (uint64_t)(current_backlight) * bl_period; + + round_result = (uint32_t)(current_backlight & 0xFFFFFFFF); + + round_result = (round_result >> (bl_int_count-1)) & 1; + + current_backlight >>= bl_int_count; + current_backlight += round_result; + + return (uint32_t)(current_backlight); +} + +void dce_abm_init(struct abm *abm) +{ + struct dce_abm *abm_dce = TO_DCE_ABM(abm); + unsigned int backlight = get_current_backlight(abm_dce); + + REG_WRITE(DC_ABM1_HG_SAMPLE_RATE, 0x103); + REG_WRITE(DC_ABM1_HG_SAMPLE_RATE, 0x101); + REG_WRITE(DC_ABM1_LS_SAMPLE_RATE, 0x103); + REG_WRITE(DC_ABM1_LS_SAMPLE_RATE, 0x101); + REG_WRITE(BL1_PWM_BL_UPDATE_SAMPLE_RATE, 0x101); + + REG_SET_3(DC_ABM1_HG_MISC_CTRL, 0, + ABM1_HG_NUM_OF_BINS_SEL, 0, + ABM1_HG_VMAX_SEL, 1, + ABM1_HG_BIN_BITWIDTH_SIZE_SEL, 0); + + REG_SET_3(DC_ABM1_IPCSC_COEFF_SEL, 0, + ABM1_IPCSC_COEFF_SEL_R, 2, + ABM1_IPCSC_COEFF_SEL_G, 4, + ABM1_IPCSC_COEFF_SEL_B, 2); + + REG_UPDATE(BL1_PWM_CURRENT_ABM_LEVEL, + BL1_PWM_CURRENT_ABM_LEVEL, backlight); + + REG_UPDATE(BL1_PWM_TARGET_ABM_LEVEL, + BL1_PWM_TARGET_ABM_LEVEL, backlight); + + REG_UPDATE(BL1_PWM_USER_LEVEL, + BL1_PWM_USER_LEVEL, backlight); + + REG_UPDATE_2(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, + ABM1_LS_MIN_PIXEL_VALUE_THRES, 0, + ABM1_LS_MAX_PIXEL_VALUE_THRES, 1000); + + REG_SET_3(DC_ABM1_HGLS_REG_READ_PROGRESS, 0, + ABM1_HG_REG_READ_MISSED_FRAME_CLEAR, 1, + ABM1_LS_REG_READ_MISSED_FRAME_CLEAR, 1, + ABM1_BL_REG_READ_MISSED_FRAME_CLEAR, 1); +} + +bool dce_abm_set_level(struct abm *abm, uint32_t level) +{ + struct dce_abm *abm_dce = TO_DCE_ABM(abm); + struct dc_context *ctx = abm_dce->base.ctx; + + unsigned int dmcu_max_retry_on_wait_reg_ready = 801; + unsigned int dmcu_wait_reg_ready_interval = 100; + unsigned int value; + + /* waitDMCUReadyForCmd */ + do { + dm_delay_in_microseconds(ctx, dmcu_wait_reg_ready_interval); + REG_GET(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, &value); + dmcu_max_retry_on_wait_reg_ready--; + } while + /* expected value is 0, loop while not 0*/ + ((value & abm_dce->abm_mask->MASTER_COMM_INTERRUPT) && + dmcu_max_retry_on_wait_reg_ready > 0); + + /* setDMCUParam_ABMLevel */ + REG_UPDATE_2(MASTER_COMM_CMD_REG, + MASTER_COMM_CMD_REG_BYTE0, MCP_ABM_LEVEL_SET, + MASTER_COMM_CMD_REG_BYTE2, level); + + /* notifyDMCUMsg */ + REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); + + return true; +} + +static const struct abm_funcs dce_funcs = { + .abm_init = dce_abm_init, + .set_abm_level = dce_abm_set_level, +}; + +static void dce_abm_construct( + struct dce_abm *abm_dce, + struct dc_context *ctx, + const struct dce_abm_registers *regs, + const struct dce_abm_shift *abm_shift, + const struct dce_abm_mask *abm_mask) +{ + struct abm *base = &abm_dce->base; + + base->ctx = ctx; + base->funcs = &dce_funcs; + + abm_dce->regs = regs; + abm_dce->abm_shift = abm_shift; + abm_dce->abm_mask = abm_mask; +} + +struct abm *dce_abm_create( + struct dc_context *ctx, + const struct dce_abm_registers *regs, + const struct dce_abm_shift *abm_shift, + const struct dce_abm_mask *abm_mask) +{ + struct dce_abm *abm_dce = dm_alloc(sizeof(*abm_dce)); + + if (abm_dce == NULL) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dce_abm_construct(abm_dce, ctx, regs, abm_shift, abm_mask); + + abm_dce->base.funcs = &dce_funcs; + + return &abm_dce->base; +} + +void dce_abm_destroy(struct abm **abm) +{ + struct dce_abm *abm_dce = TO_DCE_ABM(*abm); + + dm_free(abm_dce); + *abm = NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h new file mode 100644 index 000000000000..cf40e303cbcf --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h @@ -0,0 +1,157 @@ +/* + * Copyright 2012-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + + +#ifndef _DCE_ABM_H_ +#define _DCE_ABM_H_ + +#include "abm.h" + +#define ABM_COMMON_REG_LIST_DCE_BASE() \ + SR(BL_PWM_PERIOD_CNTL), \ + SR(BL_PWM_CNTL), \ + SR(MASTER_COMM_CNTL_REG), \ + SR(MASTER_COMM_CMD_REG) + +#define ABM_DCE110_COMMON_REG_LIST() \ + ABM_COMMON_REG_LIST_DCE_BASE(), \ + SR(DC_ABM1_HG_SAMPLE_RATE), \ + SR(DC_ABM1_LS_SAMPLE_RATE), \ + SR(BL1_PWM_BL_UPDATE_SAMPLE_RATE), \ + SR(DC_ABM1_HG_MISC_CTRL), \ + SR(DC_ABM1_IPCSC_COEFF_SEL), \ + SR(BL1_PWM_CURRENT_ABM_LEVEL), \ + SR(BL1_PWM_TARGET_ABM_LEVEL), \ + SR(BL1_PWM_USER_LEVEL), \ + SR(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES), \ + SR(DC_ABM1_HGLS_REG_READ_PROGRESS) + +#define ABM_SF(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define ABM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh) \ + ABM_SF(BL_PWM_PERIOD_CNTL, BL_PWM_PERIOD, mask_sh), \ + ABM_SF(BL_PWM_PERIOD_CNTL, BL_PWM_PERIOD_BITCNT, mask_sh), \ + ABM_SF(BL_PWM_CNTL, BL_ACTIVE_INT_FRAC_CNT, mask_sh), \ + ABM_SF(BL_PWM_CNTL, BL_PWM_FRACTIONAL_EN, mask_sh), \ + ABM_SF(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, mask_sh), \ + ABM_SF(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, mask_sh), \ + ABM_SF(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE2, mask_sh) + +#define ABM_MASK_SH_LIST_DCE110(mask_sh) \ + ABM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh), \ + ABM_SF(DC_ABM1_HG_MISC_CTRL, \ + ABM1_HG_NUM_OF_BINS_SEL, mask_sh), \ + ABM_SF(DC_ABM1_HG_MISC_CTRL, \ + ABM1_HG_VMAX_SEL, mask_sh), \ + ABM_SF(DC_ABM1_HG_MISC_CTRL, \ + ABM1_HG_BIN_BITWIDTH_SIZE_SEL, mask_sh), \ + ABM_SF(DC_ABM1_IPCSC_COEFF_SEL, \ + ABM1_IPCSC_COEFF_SEL_R, mask_sh), \ + ABM_SF(DC_ABM1_IPCSC_COEFF_SEL, \ + ABM1_IPCSC_COEFF_SEL_G, mask_sh), \ + ABM_SF(DC_ABM1_IPCSC_COEFF_SEL, \ + ABM1_IPCSC_COEFF_SEL_B, mask_sh), \ + ABM_SF(BL1_PWM_CURRENT_ABM_LEVEL, \ + BL1_PWM_CURRENT_ABM_LEVEL, mask_sh), \ + ABM_SF(BL1_PWM_TARGET_ABM_LEVEL, \ + BL1_PWM_TARGET_ABM_LEVEL, mask_sh), \ + ABM_SF(BL1_PWM_USER_LEVEL, \ + BL1_PWM_USER_LEVEL, mask_sh), \ + ABM_SF(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, \ + ABM1_LS_MIN_PIXEL_VALUE_THRES, mask_sh), \ + ABM_SF(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, \ + ABM1_LS_MAX_PIXEL_VALUE_THRES, mask_sh), \ + ABM_SF(DC_ABM1_HGLS_REG_READ_PROGRESS, \ + ABM1_HG_REG_READ_MISSED_FRAME_CLEAR, mask_sh), \ + ABM_SF(DC_ABM1_HGLS_REG_READ_PROGRESS, \ + ABM1_LS_REG_READ_MISSED_FRAME_CLEAR, mask_sh), \ + ABM_SF(DC_ABM1_HGLS_REG_READ_PROGRESS, \ + ABM1_BL_REG_READ_MISSED_FRAME_CLEAR, mask_sh) + +#define ABM_REG_FIELD_LIST(type) \ + type ABM1_HG_NUM_OF_BINS_SEL; \ + type ABM1_HG_VMAX_SEL; \ + type ABM1_HG_BIN_BITWIDTH_SIZE_SEL; \ + type ABM1_IPCSC_COEFF_SEL_R; \ + type ABM1_IPCSC_COEFF_SEL_G; \ + type ABM1_IPCSC_COEFF_SEL_B; \ + type BL1_PWM_CURRENT_ABM_LEVEL; \ + type BL1_PWM_TARGET_ABM_LEVEL; \ + type BL1_PWM_USER_LEVEL; \ + type ABM1_LS_MIN_PIXEL_VALUE_THRES; \ + type ABM1_LS_MAX_PIXEL_VALUE_THRES; \ + type ABM1_HG_REG_READ_MISSED_FRAME_CLEAR; \ + type ABM1_LS_REG_READ_MISSED_FRAME_CLEAR; \ + type ABM1_BL_REG_READ_MISSED_FRAME_CLEAR; \ + type BL_PWM_PERIOD; \ + type BL_PWM_PERIOD_BITCNT; \ + type BL_ACTIVE_INT_FRAC_CNT; \ + type BL_PWM_FRACTIONAL_EN; \ + type MASTER_COMM_INTERRUPT; \ + type MASTER_COMM_CMD_REG_BYTE0; \ + type MASTER_COMM_CMD_REG_BYTE2 + +struct dce_abm_shift { + ABM_REG_FIELD_LIST(uint8_t); +}; + +struct dce_abm_mask { + ABM_REG_FIELD_LIST(uint32_t); +}; + +struct dce_abm_registers { + uint32_t BL_PWM_PERIOD_CNTL; + uint32_t BL_PWM_CNTL; + uint32_t DC_ABM1_HG_SAMPLE_RATE; + uint32_t DC_ABM1_LS_SAMPLE_RATE; + uint32_t BL1_PWM_BL_UPDATE_SAMPLE_RATE; + uint32_t DC_ABM1_HG_MISC_CTRL; + uint32_t DC_ABM1_IPCSC_COEFF_SEL; + uint32_t BL1_PWM_CURRENT_ABM_LEVEL; + uint32_t BL1_PWM_TARGET_ABM_LEVEL; + uint32_t BL1_PWM_USER_LEVEL; + uint32_t DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES; + uint32_t DC_ABM1_HGLS_REG_READ_PROGRESS; + uint32_t MASTER_COMM_CNTL_REG; + uint32_t MASTER_COMM_CMD_REG; +}; + +struct dce_abm { + struct abm base; + const struct dce_abm_registers *regs; + const struct dce_abm_shift *abm_shift; + const struct dce_abm_mask *abm_mask; +}; + +struct abm *dce_abm_create( + struct dc_context *ctx, + const struct dce_abm_registers *regs, + const struct dce_abm_shift *abm_shift, + const struct dce_abm_mask *abm_mask); + +void dce_abm_destroy(struct abm **abm); + +#endif /* _DCE_ABM_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c new file mode 100644 index 000000000000..eb0e95f57aa9 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c @@ -0,0 +1,127 @@ +/* + * Copyright 2012-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dce_dmcu.h" +#include "dm_services.h" +#include "reg_helper.h" +#include "fixed32_32.h" +#include "dc.h" + +#define TO_DCE_DMCU(dmcu)\ + container_of(dmcu, struct dce_dmcu, base) + +#define REG(reg) \ + (dmcu_dce->regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + dmcu_dce->dmcu_shift->field_name, dmcu_dce->dmcu_mask->field_name + +#define CTX \ + dmcu_dce->base.ctx + +bool dce_dmcu_load_iram(struct dmcu *dmcu, + unsigned int start_offset, + const char *src, + unsigned int bytes) +{ + struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); + unsigned int count = 0; + uint32_t status; + + /* Enable write access to IRAM */ + REG_UPDATE_2(DMCU_RAM_ACCESS_CTRL, + IRAM_HOST_ACCESS_EN, 1, + IRAM_WR_ADDR_AUTO_INC, 1); + + do { + dm_delay_in_microseconds(dmcu->ctx, 2); + REG_GET(DCI_MEM_PWR_STATUS, DMCU_IRAM_MEM_PWR_STATE, &status); + count++; + } while + ((status & dmcu_dce->dmcu_mask->DMCU_IRAM_MEM_PWR_STATE) && count < 10); + + REG_WRITE(DMCU_IRAM_WR_CTRL, start_offset); + + for (count = 0; count < bytes; count++) + REG_WRITE(DMCU_IRAM_WR_DATA, src[count]); + + /* Disable write access to IRAM to allow dynamic sleep state */ + REG_UPDATE_2(DMCU_RAM_ACCESS_CTRL, + IRAM_HOST_ACCESS_EN, 0, + IRAM_WR_ADDR_AUTO_INC, 0); + + return true; +} + +static const struct dmcu_funcs dce_funcs = { + .load_iram = dce_dmcu_load_iram, +}; + +static void dce_dmcu_construct( + struct dce_dmcu *dmcu_dce, + struct dc_context *ctx, + const struct dce_dmcu_registers *regs, + const struct dce_dmcu_shift *dmcu_shift, + const struct dce_dmcu_mask *dmcu_mask) +{ + struct dmcu *base = &dmcu_dce->base; + + base->ctx = ctx; + base->funcs = &dce_funcs; + + dmcu_dce->regs = regs; + dmcu_dce->dmcu_shift = dmcu_shift; + dmcu_dce->dmcu_mask = dmcu_mask; +} + +struct dmcu *dce_dmcu_create( + struct dc_context *ctx, + const struct dce_dmcu_registers *regs, + const struct dce_dmcu_shift *dmcu_shift, + const struct dce_dmcu_mask *dmcu_mask) +{ + struct dce_dmcu *dmcu_dce = dm_alloc(sizeof(*dmcu_dce)); + + if (dmcu_dce == NULL) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dce_dmcu_construct( + dmcu_dce, ctx, regs, dmcu_shift, dmcu_mask); + + dmcu_dce->base.funcs = &dce_funcs; + + return &dmcu_dce->base; +} + +void dce_dmcu_destroy(struct dmcu **dmcu) +{ + struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(*dmcu); + + dm_free(dmcu_dce); + *dmcu = NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h new file mode 100644 index 000000000000..b026157a2eea --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h @@ -0,0 +1,91 @@ +/* + * Copyright 2012-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + + +#ifndef _DCE_DMCU_H_ +#define _DCE_DMCU_H_ + +#include "dmcu.h" + +#define DMCU_COMMON_REG_LIST_DCE_BASE() \ + SR(DMCU_RAM_ACCESS_CTRL), \ + SR(DMCU_IRAM_WR_CTRL), \ + SR(DMCU_IRAM_WR_DATA) + +#define DMCU_DCE110_COMMON_REG_LIST() \ + DMCU_COMMON_REG_LIST_DCE_BASE(), \ + SR(DCI_MEM_PWR_STATUS) + +#define DMCU_SF(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define DMCU_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh) \ + DMCU_SF(DMCU_RAM_ACCESS_CTRL, \ + IRAM_HOST_ACCESS_EN, mask_sh), \ + DMCU_SF(DMCU_RAM_ACCESS_CTRL, \ + IRAM_WR_ADDR_AUTO_INC, mask_sh) + +#define DMCU_MASK_SH_LIST_DCE110(mask_sh) \ + DMCU_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh), \ + DMCU_SF(DCI_MEM_PWR_STATUS, \ + DMCU_IRAM_MEM_PWR_STATE, mask_sh) + +#define DMCU_REG_FIELD_LIST(type) \ + type DMCU_IRAM_MEM_PWR_STATE; \ + type IRAM_HOST_ACCESS_EN; \ + type IRAM_WR_ADDR_AUTO_INC + +struct dce_dmcu_shift { + DMCU_REG_FIELD_LIST(uint8_t); +}; + +struct dce_dmcu_mask { + DMCU_REG_FIELD_LIST(uint32_t); +}; + +struct dce_dmcu_registers { + uint32_t DMCU_RAM_ACCESS_CTRL; + uint32_t DCI_MEM_PWR_STATUS; + uint32_t DMU_MEM_PWR_CNTL; + uint32_t DMCU_IRAM_WR_CTRL; + uint32_t DMCU_IRAM_WR_DATA; +}; + +struct dce_dmcu { + struct dmcu base; + const struct dce_dmcu_registers *regs; + const struct dce_dmcu_shift *dmcu_shift; + const struct dce_dmcu_mask *dmcu_mask; +}; + +struct dmcu *dce_dmcu_create( + struct dc_context *ctx, + const struct dce_dmcu_registers *regs, + const struct dce_dmcu_shift *dmcu_shift, + const struct dce_dmcu_mask *dmcu_mask); + +void dce_dmcu_destroy(struct dmcu **dmcu); + +#endif /* _DCE_ABM_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index e9d1a54bffd3..f9325626c26e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -142,7 +142,6 @@ static const struct link_encoder_funcs dce110_lnk_enc_funcs = { dce110_link_encoder_set_dmcu_backlight_level, .init_dmcu_backlight_settings = dce110_link_encoder_init_dmcu_backlight_settings, - .set_dmcu_abm_level = dce110_link_encoder_set_dmcu_abm_level, .set_dmcu_psr_enable = dce110_link_encoder_set_dmcu_psr_enable, .setup_dmcu_psr = dce110_link_encoder_setup_dmcu_psr, .backlight_control = dce110_link_encoder_edp_backlight_control, @@ -1769,8 +1768,7 @@ void dce110_link_encoder_init_dmcu_backlight_settings( * Bios bug w/a - period resets to zero, * restoring to cache values which is always correct */ - REG_GET(BL_PWM_CNTL, - BL_ACTIVE_INT_FRAC_CNT, &value); + REG_GET(BL_PWM_CNTL, BL_ACTIVE_INT_FRAC_CNT, &value); if (value == 0 || bl_pwm_cntl == 1) { if (stored_backlight_registers.vBL_PWM_CNTL != 0) { pwmCntl = stored_backlight_registers.vBL_PWM_CNTL; @@ -1810,36 +1808,6 @@ void dce110_link_encoder_init_dmcu_backlight_settings( /* Enable the backlight output */ REG_UPDATE(BL_PWM_CNTL, BL_PWM_EN, 1); - -} - -void dce110_link_encoder_set_dmcu_abm_level( - struct link_encoder *enc, uint32_t level) -{ - struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); - struct dc_context *ctx = enc110->base.ctx; - - unsigned int dmcu_max_retry_on_wait_reg_ready = 801; - unsigned int dmcu_wait_reg_ready_interval = 100; - unsigned int regValue; - - /* waitDMCUReadyForCmd */ - do { - dm_delay_in_microseconds(ctx, dmcu_wait_reg_ready_interval); - regValue = REG_READ(MASTER_COMM_CNTL_REG); - dmcu_max_retry_on_wait_reg_ready--; - } while - /* expected value is 0, loop while not 0*/ - ((MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK & regValue) && - dmcu_max_retry_on_wait_reg_ready > 0); - - /* setDMCUParam_ABMLevel */ - REG_UPDATE_2(MASTER_COMM_CMD_REG, - MASTER_COMM_CMD_REG_BYTE0, MCP_ABM_LEVEL_SET, - MASTER_COMM_CMD_REG_BYTE2, level); - - /* notifyDMCUMsg */ - REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); } static void get_dmcu_psr_state(struct link_encoder *enc, uint32_t *psr_state) @@ -1856,10 +1824,8 @@ static void get_dmcu_psr_state(struct link_encoder *enc, uint32_t *psr_state) do { dm_delay_in_microseconds(ctx, 2); - REG_GET(DCI_MEM_PWR_STATUS, - DMCU_IRAM_MEM_PWR_STATE, &value); - } while - (value != 0 && count++ < 10); + REG_GET(DCI_MEM_PWR_STATUS, DMCU_IRAM_MEM_PWR_STATE, &value); + } while (value != 0 && count++ < 10); /* Write address to IRAM_RD_ADDR in DMCU_IRAM_RD_CTRL */ REG_WRITE(DMCU_IRAM_RD_CTRL, psrStateOffset); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 6acb9faf29f1..d67f1100c3d9 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -42,6 +42,7 @@ #include "stream_encoder.h" #include "link_encoder.h" #include "clock_source.h" +#include "abm.h" #include "audio.h" #include "dce/dce_hwseq.h" @@ -2166,6 +2167,7 @@ static void init_hw(struct core_dc *dc) int i; struct dc_bios *bp; struct transform *xfm; + struct abm *abm; bp = dc->ctx->dc_bios; for (i = 0; i < dc->res_pool->pipe_count; i++) { @@ -2210,6 +2212,10 @@ static void init_hw(struct core_dc *dc) struct audio *audio = dc->res_pool->audios[i]; audio->funcs->hw_init(audio); } + + abm = dc->res_pool->abm; + if (abm != NULL) + abm->funcs->abm_init(abm); } /* TODO: move this to apply_ctx_tohw some how?*/ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 0b8f8927162f..8dc69be15182 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -49,6 +49,8 @@ #include "dce/dce_clock_source.h" #include "dce/dce_hwseq.h" #include "dce110/dce110_hw_sequencer.h" +#include "dce/dce_abm.h" +#include "dce/dce_dmcu.h" #include "reg_helper.h" @@ -200,6 +202,30 @@ static const struct dce_disp_clk_mask disp_clk_mask = { CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) }; +static const struct dce_dmcu_registers dmcu_regs = { + DMCU_DCE110_COMMON_REG_LIST() +}; + +static const struct dce_dmcu_shift dmcu_shift = { + DMCU_MASK_SH_LIST_DCE110(__SHIFT) +}; + +static const struct dce_dmcu_mask dmcu_mask = { + DMCU_MASK_SH_LIST_DCE110(_MASK) +}; + +static const struct dce_abm_registers abm_regs = { + ABM_DCE110_COMMON_REG_LIST() +}; + +static const struct dce_abm_shift abm_shift = { + ABM_MASK_SH_LIST_DCE110(__SHIFT) +}; + +static const struct dce_abm_mask abm_mask = { + ABM_MASK_SH_LIST_DCE110(_MASK) +}; + #define transform_regs(id)\ [id] = {\ XFM_COMMON_REG_LIST_DCE110(id)\ @@ -712,6 +738,12 @@ static void destruct(struct dce110_resource_pool *pool) } } + if (pool->base.abm != NULL) + dce_abm_destroy(&pool->base.abm); + + if (pool->base.dmcu != NULL) + dce_dmcu_destroy(&pool->base.dmcu); + if (pool->base.display_clock != NULL) dce_disp_clk_destroy(&pool->base.display_clock); @@ -1286,6 +1318,26 @@ static bool construct( goto res_create_fail; } + pool->base.dmcu = dce_dmcu_create(ctx, + &dmcu_regs, + &dmcu_shift, + &dmcu_mask); + if (pool->base.dmcu == NULL) { + dm_error("DC: failed to create dmcu!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + pool->base.abm = dce_abm_create(ctx, + &abm_regs, + &abm_shift, + &abm_mask); + if (pool->base.abm == NULL) { + dm_error("DC: failed to create abm!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + /* get static clock information for PPLIB or firmware, save * max_clock_state */ diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index cc826efac58d..7e99b2b96794 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -46,6 +46,8 @@ #include "dce/dce_hwseq.h" #include "dce112/dce112_hw_sequencer.h" +#include "dce/dce_abm.h" +#include "dce/dce_dmcu.h" #include "reg_helper.h" @@ -218,6 +220,30 @@ static const struct dce_disp_clk_mask disp_clk_mask = { CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) }; +static const struct dce_dmcu_registers dmcu_regs = { + DMCU_DCE110_COMMON_REG_LIST() +}; + +static const struct dce_dmcu_shift dmcu_shift = { + DMCU_MASK_SH_LIST_DCE110(__SHIFT) +}; + +static const struct dce_dmcu_mask dmcu_mask = { + DMCU_MASK_SH_LIST_DCE110(_MASK) +}; + +static const struct dce_abm_registers abm_regs = { + ABM_DCE110_COMMON_REG_LIST() +}; + +static const struct dce_abm_shift abm_shift = { + ABM_MASK_SH_LIST_DCE110(__SHIFT) +}; + +static const struct dce_abm_mask abm_mask = { + ABM_MASK_SH_LIST_DCE110(_MASK) +}; + #define transform_regs(id)\ [id] = {\ XFM_COMMON_REG_LIST_DCE110(id)\ @@ -719,6 +745,12 @@ static void destruct(struct dce110_resource_pool *pool) } } + if (pool->base.abm != NULL) + dce_abm_destroy(&pool->base.abm); + + if (pool->base.dmcu != NULL) + dce_dmcu_destroy(&pool->base.dmcu); + if (pool->base.display_clock != NULL) dce_disp_clk_destroy(&pool->base.display_clock); @@ -1283,6 +1315,25 @@ static bool construct( goto res_create_fail; } + pool->base.dmcu = dce_dmcu_create(ctx, + &dmcu_regs, + &dmcu_shift, + &dmcu_mask); + if (pool->base.dmcu == NULL) { + dm_error("DC: failed to create dmcu!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + pool->base.abm = dce_abm_create(ctx, + &abm_regs, + &abm_shift, + &abm_mask); + if (pool->base.abm == NULL) { + dm_error("DC: failed to create abm!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } /* get static clock information for PPLIB or firmware, save * max_clock_state diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index b349b5768b6e..1a81e83d1785 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -259,6 +259,9 @@ struct resource_pool { struct display_clock *display_clock; struct irq_service *irqs; + struct abm *abm; + struct dmcu *dmcu; + const struct resource_funcs *funcs; const struct resource_caps *res_cap; }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h b/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h new file mode 100644 index 000000000000..9c9a6877387a --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h @@ -0,0 +1,40 @@ +/* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_ABM_H__ +#define __DC_ABM_H__ + +#include "dm_services_types.h" + +struct abm { + struct dc_context *ctx; + const struct abm_funcs *funcs; +}; + +struct abm_funcs { + void (*abm_init)(struct abm *abm); + bool (*set_abm_level)(struct abm *abm, unsigned int abm_level); +}; + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h new file mode 100644 index 000000000000..62012f091836 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h @@ -0,0 +1,42 @@ +/* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_DMCU_H__ +#define __DC_DMCU_H__ + +#include "dm_services_types.h" + +struct dmcu { + struct dc_context *ctx; + const struct dmcu_funcs *funcs; +}; + +struct dmcu_funcs { + bool (*load_iram)(struct dmcu *dmcu, + unsigned int start_offset, + const char *src, + unsigned int bytes); +}; + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h index ac4010b9c638..949eae6d5402 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h @@ -225,7 +225,6 @@ struct link_encoder_funcs { void (*set_dmcu_backlight_level)(struct link_encoder *enc, uint32_t level, uint32_t frame_ramp, uint32_t controller_id); void (*init_dmcu_backlight_settings)(struct link_encoder *enc); - void (*set_dmcu_abm_level)(struct link_encoder *enc, uint32_t level); void (*set_dmcu_psr_enable)(struct link_encoder *enc, bool enable); void (*setup_dmcu_psr)(struct link_encoder *enc, struct psr_dmcu_context *psr_context); -- cgit From 6728b30c974e38711f70dc38edf68503bf71c4a9 Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Tue, 24 Jan 2017 15:19:42 -0500 Subject: drm/amd/display: Move backlight from encoder to ABM Signed-off-by: Anthony Koo Reviewed-by: Aric Cyr Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 34 --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 63 +++-- drivers/gpu/drm/amd/display/dc/dc.h | 5 - drivers/gpu/drm/amd/display/dc/dce/dce_abm.c | 264 +++++++++++++++++++-- drivers/gpu/drm/amd/display/dc/dce/dce_abm.h | 35 ++- .../gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 260 -------------------- .../gpu/drm/amd/display/dc/dce/dce_link_encoder.h | 24 -- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 4 +- drivers/gpu/drm/amd/display/dc/inc/hw/abm.h | 5 + .../gpu/drm/amd/display/dc/inc/hw/link_encoder.h | 5 - drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 4 - .../amd/display/dc/virtual/virtual_link_encoder.c | 13 - 12 files changed, 316 insertions(+), 400 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 152c694cc044..499ef561bbfc 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -240,34 +240,6 @@ static void stream_update_scaling( } } -static bool set_backlight(struct dc *dc, unsigned int backlight_level, - unsigned int frame_ramp, const struct dc_stream *stream) -{ - struct core_dc *core_dc = DC_TO_CORE(dc); - int i; - - if (stream->sink->sink_signal == SIGNAL_TYPE_EDP) { - for (i = 0; i < core_dc->link_count; i++) - dc_link_set_backlight_level(&core_dc->links[i]->public, - backlight_level, frame_ramp, stream); - } - - return true; - -} - -static bool init_dmcu_backlight_settings(struct dc *dc) -{ - struct core_dc *core_dc = DC_TO_CORE(dc); - int i; - - for (i = 0; i < core_dc->link_count; i++) - dc_link_init_dmcu_backlight_settings - (&core_dc->links[i]->public); - - return true; -} - static bool set_psr_enable(struct dc *dc, bool enable) { struct core_dc *core_dc = DC_TO_CORE(dc); @@ -390,12 +362,6 @@ static void allocate_dc_stream_funcs(struct core_dc *core_dc) core_dc->public.stream_funcs.set_gamut_remap = set_gamut_remap; - core_dc->public.stream_funcs.set_backlight = - set_backlight; - - core_dc->public.stream_funcs.init_dmcu_backlight_settings = - init_dmcu_backlight_settings; - core_dc->public.stream_funcs.set_psr_enable = set_psr_enable; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 84efc25d0e33..2bceb3aa24b5 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -37,6 +37,7 @@ #include "link_encoder.h" #include "hw_sequencer.h" #include "resource.h" +#include "abm.h" #include "fixed31_32.h" #include "dpcd_defs.h" @@ -1386,48 +1387,40 @@ bool dc_link_set_backlight_level(const struct dc_link *dc_link, uint32_t level, uint32_t frame_ramp, const struct dc_stream *stream) { struct core_link *link = DC_LINK_TO_CORE(dc_link); - struct dc_context *ctx = link->ctx; - struct core_dc *core_dc = DC_TO_CORE(ctx->dc); - struct core_stream *core_stream = DC_STREAM_TO_CORE(stream); + struct core_dc *core_dc = DC_TO_CORE(link->ctx->dc); + struct core_stream *core_stream = NULL; + struct abm *abm = core_dc->res_pool->abm; unsigned int controller_id = 0; int i; - uint32_t dmcu_status; - dm_logger_write(ctx->logger, LOG_BACKLIGHT, - "New Backlight level: %d (0x%X)\n", level, level); + if ((abm == NULL) || (abm->funcs->set_backlight_level == NULL)) + return false; - dmcu_status = dm_read_reg(ctx, mmDMCU_STATUS); + dm_logger_write(link->ctx->logger, LOG_BACKLIGHT, + "New Backlight level: %d (0x%X)\n", level, level); - /* If DMCU is in reset state, DMCU is uninitialized */ - if (get_reg_field_value(dmcu_status, mmDMCU_STATUS, UC_IN_RESET)) { - link->link_enc->funcs->set_lcd_backlight_level(link->link_enc, - level); - } else { - for (i = 0; i < MAX_PIPES; i++) { - if (core_dc->current_context->res_ctx.pipe_ctx[i].stream - == core_stream) - /* dmcu -1 for all controller id values, - * therefore +1 here - */ - controller_id = core_dc->current_context->res_ctx. - pipe_ctx[i].tg->inst + 1; + if (link->device_tag.dev_id.device_type == DEVICE_TYPE_LCD) { + if (stream != NULL) { + core_stream = DC_STREAM_TO_CORE(stream); + for (i = 0; i < MAX_PIPES; i++) { + if (core_dc->current_context->res_ctx. + pipe_ctx[i].stream + == core_stream) + /* DMCU -1 for all controller id values, + * therefore +1 here + */ + controller_id = + core_dc->current_context-> + res_ctx.pipe_ctx[i].tg->inst + + 1; + } } - - link->link_enc->funcs->set_dmcu_backlight_level - (link->link_enc, level, - frame_ramp, controller_id); + abm->funcs->set_backlight_level( + abm, + level, + frame_ramp, + controller_id); } - return true; -} - - -bool dc_link_init_dmcu_backlight_settings(const struct dc_link *dc_link) -{ - struct core_link *link = DC_LINK_TO_CORE(dc_link); - - if (link->link_enc->funcs->init_dmcu_backlight_settings != NULL) - link->link_enc->funcs-> - init_dmcu_backlight_settings(link->link_enc); return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 8cb53b626641..1308af59d839 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -100,9 +100,6 @@ struct dc_stream_funcs { const struct rect *dst); bool (*set_gamut_remap)(struct dc *dc, const struct dc_stream **stream, int num_streams); - bool (*set_backlight)(struct dc *dc, unsigned int backlight_level, - unsigned int frame_ramp, const struct dc_stream *stream); - bool (*init_dmcu_backlight_settings)(struct dc *dc); bool (*set_psr_enable)(struct dc *dc, bool enable); bool (*setup_psr)(struct dc *dc, const struct dc_stream *stream); }; @@ -572,8 +569,6 @@ const struct graphics_object_id dc_get_link_id_at_index( bool dc_link_set_backlight_level(const struct dc_link *dc_link, uint32_t level, uint32_t frame_ramp, const struct dc_stream *stream); -bool dc_link_init_dmcu_backlight_settings(const struct dc_link *dc_link); - bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable); bool dc_link_setup_psr(const struct dc_link *dc_link, diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c index ce49bee8e038..f4696bf14a70 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c @@ -29,6 +29,9 @@ #include "fixed32_32.h" #include "dc.h" +#include "atom.h" + + #define TO_DCE_ABM(abm)\ container_of(abm, struct dce_abm, base) @@ -43,6 +46,19 @@ abm_dce->base.ctx #define MCP_ABM_LEVEL_SET 0x65 +#define MCP_ABM_PIPE_SET 0x66 +#define MCP_BL_SET 0x67 + +struct abm_backlight_registers { + unsigned int BL_PWM_CNTL; + unsigned int BL_PWM_CNTL2; + unsigned int BL_PWM_PERIOD_CNTL; + unsigned int LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV; +}; + +/* registers setting needs to be save and restored used at InitBacklight */ +static struct abm_backlight_registers stored_backlight_registers = {0}; + static unsigned int get_current_backlight(struct dce_abm *abm_dce) { @@ -93,7 +109,147 @@ static unsigned int get_current_backlight(struct dce_abm *abm_dce) return (uint32_t)(current_backlight); } -void dce_abm_init(struct abm *abm) +static void driver_set_backlight_level(struct dce_abm *abm_dce, uint32_t level) +{ + uint32_t backlight_24bit; + uint32_t backlight_17bit; + uint32_t backlight_16bit; + uint32_t masked_pwm_period; + uint8_t rounding_bit; + uint8_t bit_count; + uint64_t active_duty_cycle; + uint32_t pwm_period_bitcnt; + + /* + * 1. Convert 8-bit value to 17 bit U1.16 format + * (1 integer, 16 fractional bits) + */ + + /* 1.1 multiply 8 bit value by 0x10101 to get a 24 bit value, + * effectively multiplying value by 256/255 + * eg. for a level of 0xEF, backlight_24bit = 0xEF * 0x10101 = 0xEFEFEF + */ + backlight_24bit = level * 0x10101; + + /* 1.2 The upper 16 bits of the 24 bit value is the fraction, lower 8 + * used for rounding, take most significant bit of fraction for + * rounding, e.g. for 0xEFEFEF, rounding bit is 1 + */ + rounding_bit = (backlight_24bit >> 7) & 1; + + /* 1.3 Add the upper 16 bits of the 24 bit value with the rounding bit + * resulting in a 17 bit value e.g. 0xEFF0 = (0xEFEFEF >> 8) + 1 + */ + backlight_17bit = (backlight_24bit >> 8) + rounding_bit; + + /* + * 2. Find 16 bit backlight active duty cycle, where 0 <= backlight + * active duty cycle <= backlight period + */ + + /* 2.1 Apply bitmask for backlight period value based on value of BITCNT + */ + REG_GET_2(BL_PWM_PERIOD_CNTL, + BL_PWM_PERIOD_BITCNT, &pwm_period_bitcnt, + BL_PWM_PERIOD, &masked_pwm_period); + + if (pwm_period_bitcnt == 0) + bit_count = 16; + else + bit_count = pwm_period_bitcnt; + + /* e.g. maskedPwmPeriod = 0x24 when bitCount is 6 */ + masked_pwm_period = masked_pwm_period & ((1 << bit_count) - 1); + + /* 2.2 Calculate integer active duty cycle required upper 16 bits + * contain integer component, lower 16 bits contain fractional component + * of active duty cycle e.g. 0x21BDC0 = 0xEFF0 * 0x24 + */ + active_duty_cycle = backlight_17bit * masked_pwm_period; + + /* 2.3 Calculate 16 bit active duty cycle from integer and fractional + * components shift by bitCount then mask 16 bits and add rounding bit + * from MSB of fraction e.g. 0x86F7 = ((0x21BDC0 >> 6) & 0xFFF) + 0 + */ + backlight_16bit = active_duty_cycle >> bit_count; + backlight_16bit &= 0xFFFF; + backlight_16bit += (active_duty_cycle >> (bit_count - 1)) & 0x1; + + /* + * 3. Program register with updated value + */ + + /* 3.1 Lock group 2 backlight registers */ + + REG_UPDATE_2(BL_PWM_GRP1_REG_LOCK, + BL_PWM_GRP1_IGNORE_MASTER_LOCK_EN, 1, + BL_PWM_GRP1_REG_LOCK, 1); + + // 3.2 Write new active duty cycle + REG_UPDATE(BL_PWM_CNTL, BL_ACTIVE_INT_FRAC_CNT, backlight_16bit); + + /* 3.3 Unlock group 2 backlight registers */ + REG_UPDATE(BL_PWM_GRP1_REG_LOCK, + BL_PWM_GRP1_REG_LOCK, 0); + + /* 5.4.4 Wait for pending bit to be cleared */ + REG_WAIT(BL_PWM_GRP1_REG_LOCK, BL_PWM_GRP1_REG_UPDATE_PENDING, + 0, 10, 1000); +} + +static void dmcu_set_backlight_level( + struct dce_abm *abm_dce, + uint32_t level, + uint32_t frame_ramp, + uint32_t controller_id) +{ + unsigned int backlight_16_bit = (level * 0x10101) >> 8; + unsigned int backlight_17_bit = backlight_16_bit + + (((backlight_16_bit & 0x80) >> 7) & 1); + uint32_t rampingBoundary = 0xFFFF; + uint32_t s2; + + /* set ramping boundary */ + REG_WRITE(MASTER_COMM_DATA_REG1, rampingBoundary); + + /* setDMCUParam_Pipe */ + REG_UPDATE_2(MASTER_COMM_CMD_REG, + MASTER_COMM_CMD_REG_BYTE0, MCP_ABM_PIPE_SET, + MASTER_COMM_CMD_REG_BYTE1, controller_id); + + /* notifyDMCUMsg */ + REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); + + /* waitDMCUReadyForCmd */ + REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, + 0, 100, 800); + + /* setDMCUParam_BL */ + REG_UPDATE(BL1_PWM_USER_LEVEL, BL1_PWM_USER_LEVEL, backlight_17_bit); + + /* write ramp */ + if (controller_id == 0) + frame_ramp = 0; + REG_WRITE(MASTER_COMM_DATA_REG1, frame_ramp); + + /* setDMCUParam_Cmd */ + REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, MCP_BL_SET); + + /* notifyDMCUMsg */ + REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); + + /* UpdateRequestedBacklightLevel */ + s2 = REG_READ(BIOS_SCRATCH_2); + + s2 &= ~ATOM_S2_CURRENT_BL_LEVEL_MASK; + level &= (ATOM_S2_CURRENT_BL_LEVEL_MASK >> + ATOM_S2_CURRENT_BL_LEVEL_SHIFT); + s2 |= (level << ATOM_S2_CURRENT_BL_LEVEL_SHIFT); + + REG_WRITE(BIOS_SCRATCH_2, s2); +} + +static void dce_abm_init(struct abm *abm) { struct dce_abm *abm_dce = TO_DCE_ABM(abm); unsigned int backlight = get_current_backlight(abm_dce); @@ -133,24 +289,13 @@ void dce_abm_init(struct abm *abm) ABM1_BL_REG_READ_MISSED_FRAME_CLEAR, 1); } -bool dce_abm_set_level(struct abm *abm, uint32_t level) +static bool dce_abm_set_level(struct abm *abm, uint32_t level) { struct dce_abm *abm_dce = TO_DCE_ABM(abm); struct dc_context *ctx = abm_dce->base.ctx; - unsigned int dmcu_max_retry_on_wait_reg_ready = 801; - unsigned int dmcu_wait_reg_ready_interval = 100; - unsigned int value; - - /* waitDMCUReadyForCmd */ - do { - dm_delay_in_microseconds(ctx, dmcu_wait_reg_ready_interval); - REG_GET(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, &value); - dmcu_max_retry_on_wait_reg_ready--; - } while - /* expected value is 0, loop while not 0*/ - ((value & abm_dce->abm_mask->MASTER_COMM_INTERRUPT) && - dmcu_max_retry_on_wait_reg_ready > 0); + REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, + 100, 800); /* setDMCUParam_ABMLevel */ REG_UPDATE_2(MASTER_COMM_CMD_REG, @@ -163,9 +308,98 @@ bool dce_abm_set_level(struct abm *abm, uint32_t level) return true; } +static bool dce_abm_init_backlight(struct abm *abm) +{ + struct dce_abm *abm_dce = TO_DCE_ABM(abm); + uint32_t value; + + /* It must not be 0, so we have to restore them + * Bios bug w/a - period resets to zero, + * restoring to cache values which is always correct + */ + REG_GET(BL_PWM_CNTL, BL_ACTIVE_INT_FRAC_CNT, &value); + if (value == 0 || value == 1) { + if (stored_backlight_registers.BL_PWM_CNTL != 0) { + REG_WRITE(BL_PWM_CNTL, + stored_backlight_registers.BL_PWM_CNTL); + REG_WRITE(BL_PWM_CNTL2, + stored_backlight_registers.BL_PWM_CNTL2); + REG_WRITE(BL_PWM_PERIOD_CNTL, + stored_backlight_registers.BL_PWM_PERIOD_CNTL); + REG_UPDATE(LVTMA_PWRSEQ_REF_DIV, + BL_PWM_REF_DIV, + stored_backlight_registers. + LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV); + } else { + /* TODO: Note: This should not really happen since VBIOS + * should have initialized PWM registers on boot. + */ + REG_WRITE(BL_PWM_CNTL, 0xC000FA00); + REG_WRITE(BL_PWM_PERIOD_CNTL, 0x000C0FA0); + } + } else { + stored_backlight_registers.BL_PWM_CNTL = + REG_READ(BL_PWM_CNTL); + stored_backlight_registers.BL_PWM_CNTL2 = + REG_READ(BL_PWM_CNTL2); + stored_backlight_registers.BL_PWM_PERIOD_CNTL = + REG_READ(BL_PWM_PERIOD_CNTL); + + REG_GET(LVTMA_PWRSEQ_REF_DIV, BL_PWM_REF_DIV, + &stored_backlight_registers. + LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV); + } + + /* Have driver take backlight control + * TakeBacklightControl(true) + */ + value = REG_READ(BIOS_SCRATCH_2); + value |= ATOM_S2_VRI_BRIGHT_ENABLE; + REG_WRITE(BIOS_SCRATCH_2, value); + + /* Enable the backlight output */ + REG_UPDATE(BL_PWM_CNTL, BL_PWM_EN, 1); + + /* Unlock group 2 backlight registers */ + REG_UPDATE(BL_PWM_GRP1_REG_LOCK, + BL_PWM_GRP1_REG_LOCK, 0); + + return true; +} + +static bool dce_abm_set_backlight_level( + struct abm *abm, + unsigned int backlight_level, + unsigned int frame_ramp, + unsigned int controller_id) +{ + struct dce_abm *abm_dce = TO_DCE_ABM(abm); + unsigned int dmcu_uc_reset; + + dm_logger_write(abm->ctx->logger, LOG_BACKLIGHT, + "New Backlight level: %d (0x%X)\n", + backlight_level, backlight_level); + + REG_GET(DMCU_STATUS, UC_IN_RESET, &dmcu_uc_reset); + + /* If DMCU is in reset state, DMCU is uninitialized */ + if (dmcu_uc_reset) { + driver_set_backlight_level(abm_dce, backlight_level); + } else { + dmcu_set_backlight_level(abm_dce, + backlight_level, + frame_ramp, + controller_id); + } + + return true; +} + static const struct abm_funcs dce_funcs = { .abm_init = dce_abm_init, .set_abm_level = dce_abm_set_level, + .init_backlight = dce_abm_init_backlight, + .set_backlight_level = dce_abm_set_backlight_level }; static void dce_abm_construct( diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h index cf40e303cbcf..56087b36bdeb 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h @@ -32,8 +32,13 @@ #define ABM_COMMON_REG_LIST_DCE_BASE() \ SR(BL_PWM_PERIOD_CNTL), \ SR(BL_PWM_CNTL), \ + SR(BL_PWM_CNTL2), \ + SR(BL_PWM_GRP1_REG_LOCK), \ + SR(LVTMA_PWRSEQ_REF_DIV), \ SR(MASTER_COMM_CNTL_REG), \ - SR(MASTER_COMM_CMD_REG) + SR(MASTER_COMM_CMD_REG), \ + SR(MASTER_COMM_DATA_REG1), \ + SR(DMCU_STATUS) #define ABM_DCE110_COMMON_REG_LIST() \ ABM_COMMON_REG_LIST_DCE_BASE(), \ @@ -46,7 +51,8 @@ SR(BL1_PWM_TARGET_ABM_LEVEL), \ SR(BL1_PWM_USER_LEVEL), \ SR(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES), \ - SR(DC_ABM1_HGLS_REG_READ_PROGRESS) + SR(DC_ABM1_HGLS_REG_READ_PROGRESS), \ + SR(BIOS_SCRATCH_2) #define ABM_SF(reg_name, field_name, post_fix)\ .field_name = reg_name ## __ ## field_name ## post_fix @@ -56,9 +62,16 @@ ABM_SF(BL_PWM_PERIOD_CNTL, BL_PWM_PERIOD_BITCNT, mask_sh), \ ABM_SF(BL_PWM_CNTL, BL_ACTIVE_INT_FRAC_CNT, mask_sh), \ ABM_SF(BL_PWM_CNTL, BL_PWM_FRACTIONAL_EN, mask_sh), \ + ABM_SF(BL_PWM_CNTL, BL_PWM_EN, mask_sh), \ + ABM_SF(BL_PWM_GRP1_REG_LOCK, BL_PWM_GRP1_IGNORE_MASTER_LOCK_EN, mask_sh), \ + ABM_SF(BL_PWM_GRP1_REG_LOCK, BL_PWM_GRP1_REG_LOCK, mask_sh), \ + ABM_SF(BL_PWM_GRP1_REG_LOCK, BL_PWM_GRP1_REG_UPDATE_PENDING, mask_sh), \ + ABM_SF(LVTMA_PWRSEQ_REF_DIV, BL_PWM_REF_DIV, mask_sh), \ ABM_SF(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, mask_sh), \ ABM_SF(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, mask_sh), \ - ABM_SF(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE2, mask_sh) + ABM_SF(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE1, mask_sh), \ + ABM_SF(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE2, mask_sh), \ + ABM_SF(DMCU_STATUS, UC_IN_RESET, mask_sh) #define ABM_MASK_SH_LIST_DCE110(mask_sh) \ ABM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh), \ @@ -91,6 +104,7 @@ ABM_SF(DC_ABM1_HGLS_REG_READ_PROGRESS, \ ABM1_BL_REG_READ_MISSED_FRAME_CLEAR, mask_sh) + #define ABM_REG_FIELD_LIST(type) \ type ABM1_HG_NUM_OF_BINS_SEL; \ type ABM1_HG_VMAX_SEL; \ @@ -112,7 +126,14 @@ type BL_PWM_FRACTIONAL_EN; \ type MASTER_COMM_INTERRUPT; \ type MASTER_COMM_CMD_REG_BYTE0; \ - type MASTER_COMM_CMD_REG_BYTE2 + type MASTER_COMM_CMD_REG_BYTE1; \ + type MASTER_COMM_CMD_REG_BYTE2; \ + type BL_PWM_REF_DIV; \ + type BL_PWM_EN; \ + type UC_IN_RESET; \ + type BL_PWM_GRP1_IGNORE_MASTER_LOCK_EN; \ + type BL_PWM_GRP1_REG_LOCK; \ + type BL_PWM_GRP1_REG_UPDATE_PENDING struct dce_abm_shift { ABM_REG_FIELD_LIST(uint8_t); @@ -125,6 +146,8 @@ struct dce_abm_mask { struct dce_abm_registers { uint32_t BL_PWM_PERIOD_CNTL; uint32_t BL_PWM_CNTL; + uint32_t BL_PWM_CNTL2; + uint32_t LVTMA_PWRSEQ_REF_DIV; uint32_t DC_ABM1_HG_SAMPLE_RATE; uint32_t DC_ABM1_LS_SAMPLE_RATE; uint32_t BL1_PWM_BL_UPDATE_SAMPLE_RATE; @@ -137,6 +160,10 @@ struct dce_abm_registers { uint32_t DC_ABM1_HGLS_REG_READ_PROGRESS; uint32_t MASTER_COMM_CNTL_REG; uint32_t MASTER_COMM_CMD_REG; + uint32_t MASTER_COMM_DATA_REG1; + uint32_t BIOS_SCRATCH_2; + uint32_t DMCU_STATUS; + uint32_t BL_PWM_GRP1_REG_LOCK; }; struct dce_abm { diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index f9325626c26e..3847764688dd 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -38,15 +38,6 @@ #include "dce/dce_11_0_sh_mask.h" #include "dce/dce_11_0_enum.h" -#ifndef ATOM_S2_CURRENT_BL_LEVEL_MASK -#define ATOM_S2_CURRENT_BL_LEVEL_MASK 0x0000FF00L -#define ATOM_S2_VRI_BRIGHT_ENABLE 0x20000000L -#endif - -#ifndef ATOM_S2_CURRENT_BL_LEVEL_SHIFT -#define ATOM_S2_CURRENT_BL_LEVEL_SHIFT 8 -#endif - #ifndef HPD0_DC_HPD_CONTROL__DC_HPD_EN_MASK #define HPD0_DC_HPD_CONTROL__DC_HPD_EN_MASK 0x10000000L #endif @@ -96,13 +87,6 @@ /* For current ASICs pixel clock - 600MHz */ #define MAX_ENCODER_CLOCK 600000 -/* Set the ABM Pipe */ -#define MCP_ABM_PIPE_SET 0x66 -/* Set the ABM level */ -#define MCP_ABM_LEVEL_SET 0x65 -/* Set backlight level */ -#define MCP_BL_SET 0x67 - /* PSR related commands */ #define PSR_ENABLE 0x20 #define PSR_EXIT 0x21 @@ -111,9 +95,6 @@ /*TODO: Used for psr wakeup for set backlight level*/ static unsigned int psr_crtc_offset; -/* registers setting needs to be save and restored used at InitBacklight */ -static struct dce110_abm_backlight_registers stored_backlight_registers; - enum { DP_MST_UPDATE_MAX_RETRY = 50 }; @@ -137,11 +118,6 @@ static const struct link_encoder_funcs dce110_lnk_enc_funcs = { .dp_set_phy_pattern = dce110_link_encoder_dp_set_phy_pattern, .update_mst_stream_allocation_table = dce110_link_encoder_update_mst_stream_allocation_table, - .set_lcd_backlight_level = dce110_link_encoder_set_lcd_backlight_level, - .set_dmcu_backlight_level = - dce110_link_encoder_set_dmcu_backlight_level, - .init_dmcu_backlight_settings = - dce110_link_encoder_init_dmcu_backlight_settings, .set_dmcu_psr_enable = dce110_link_encoder_set_dmcu_psr_enable, .setup_dmcu_psr = dce110_link_encoder_setup_dmcu_psr, .backlight_control = dce110_link_encoder_edp_backlight_control, @@ -1574,242 +1550,6 @@ void dce110_link_encoder_update_mst_stream_allocation_table( } while (retries < DP_MST_UPDATE_MAX_RETRY); } -void dce110_link_encoder_set_lcd_backlight_level( - struct link_encoder *enc, - uint32_t level) -{ - struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); - - const uint32_t backlight_update_pending_max_retry = 1000; - - uint32_t backlight_lock; - - uint32_t i; - uint32_t backlight_24bit; - uint32_t backlight_17bit; - uint32_t backlight_16bit; - uint32_t masked_pwm_period; - uint8_t rounding_bit; - uint8_t bit_count; - uint64_t active_duty_cycle; - uint32_t pwm_period_bitcnt; - - backlight_lock = REG_READ(BL_PWM_GRP1_REG_LOCK); - - /* - * 1. Convert 8-bit value to 17 bit U1.16 format - * (1 integer, 16 fractional bits) - */ - - /* 1.1 multiply 8 bit value by 0x10101 to get a 24 bit value, - * effectively multiplying value by 256/255 - * eg. for a level of 0xEF, backlight_24bit = 0xEF * 0x10101 = 0xEFEFEF - */ - backlight_24bit = level * 0x10101; - - /* 1.2 The upper 16 bits of the 24 bit value is the fraction, lower 8 - * used for rounding, take most significant bit of fraction for - * rounding, e.g. for 0xEFEFEF, rounding bit is 1 - */ - rounding_bit = (backlight_24bit >> 7) & 1; - - /* 1.3 Add the upper 16 bits of the 24 bit value with the rounding bit - * resulting in a 17 bit value e.g. 0xEFF0 = (0xEFEFEF >> 8) + 1 - */ - backlight_17bit = (backlight_24bit >> 8) + rounding_bit; - - /* - * 2. Find 16 bit backlight active duty cycle, where 0 <= backlight - * active duty cycle <= backlight period - */ - - /* 2.1 Apply bitmask for backlight period value based on value of BITCNT - */ - { - REG_GET(BL_PWM_PERIOD_CNTL, - BL_PWM_PERIOD_BITCNT, &pwm_period_bitcnt); - - if (pwm_period_bitcnt == 0) - bit_count = 16; - else - bit_count = pwm_period_bitcnt; - } - - /* e.g. maskedPwmPeriod = 0x24 when bitCount is 6 */ - masked_pwm_period = - REG_GET(BL_PWM_PERIOD_CNTL, - BL_PWM_PERIOD, &masked_pwm_period) - & ((1 << bit_count) - 1); - - /* 2.2 Calculate integer active duty cycle required upper 16 bits - * contain integer component, lower 16 bits contain fractional component - * of active duty cycle e.g. 0x21BDC0 = 0xEFF0 * 0x24 - */ - active_duty_cycle = backlight_17bit * masked_pwm_period; - - /* 2.3 Calculate 16 bit active duty cycle from integer and fractional - * components shift by bitCount then mask 16 bits and add rounding bit - * from MSB of fraction e.g. 0x86F7 = ((0x21BDC0 >> 6) & 0xFFF) + 0 - */ - backlight_16bit = active_duty_cycle >> bit_count; - backlight_16bit &= 0xFFFF; - backlight_16bit += (active_duty_cycle >> (bit_count - 1)) & 0x1; - - REG_UPDATE(BL_PWM_CNTL, - BL_ACTIVE_INT_FRAC_CNT, backlight_16bit); - - /* - * 3. Program register with updated value - */ - - /* 3.1 Lock group 2 backlight registers */ - - REG_UPDATE(BL_PWM_GRP1_REG_LOCK, - BL_PWM_GRP1_IGNORE_MASTER_LOCK_EN, 1); - - REG_UPDATE(BL_PWM_GRP1_REG_LOCK, - BL_PWM_GRP1_REG_LOCK, 1); - - /* 3.3 Unlock group 2 backlight registers */ - REG_UPDATE(BL_PWM_GRP1_REG_LOCK, - BL_PWM_GRP1_REG_LOCK, 0); - - /* 5.4.4 Wait for pending bit to be cleared */ - for (i = 0; i < backlight_update_pending_max_retry; ++i) { - REG_GET(BL_PWM_GRP1_REG_LOCK, - BL_PWM_GRP1_REG_UPDATE_PENDING, &backlight_lock); - if (!backlight_lock) - break; - - udelay(10); - } -} - -void dce110_link_encoder_set_dmcu_backlight_level( - struct link_encoder *enc, - uint32_t level, - uint32_t frame_ramp, - uint32_t controller_id) -{ - struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); - struct dc_context *ctx = enc110->base.ctx; - unsigned int dmcu_max_retry_on_wait_reg_ready = 801; - unsigned int dmcu_wait_reg_ready_interval = 100; - unsigned int backlight_17bit = level * 0x10101; - unsigned char temp_uchar = - (unsigned char)(((backlight_17bit & 0x80) >> 7) & 1); - unsigned int regValue; - uint32_t rampingBoundary = 0xFFFF; - uint32_t s2; - - backlight_17bit = (backlight_17bit >> 8) + temp_uchar; - - /* set ramping boundary */ - REG_WRITE(MASTER_COMM_DATA_REG1, rampingBoundary); - - /* setDMCUParam_Pipe */ - REG_UPDATE_2(MASTER_COMM_CMD_REG, - MASTER_COMM_CMD_REG_BYTE0, MCP_ABM_PIPE_SET, - MASTER_COMM_CMD_REG_BYTE1, controller_id); - - /* notifyDMCUMsg */ - REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); - - /* waitDMCUReadyForCmd */ - do { - dm_delay_in_microseconds(ctx, dmcu_wait_reg_ready_interval); - regValue = REG_READ(MASTER_COMM_CNTL_REG); - dmcu_max_retry_on_wait_reg_ready--; - } while - /* expected value is 0, loop while not 0*/ - ((MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK & regValue) && - dmcu_max_retry_on_wait_reg_ready > 0); - - /* setDMCUParam_BL */ - REG_UPDATE(BL1_PWM_USER_LEVEL, BL1_PWM_USER_LEVEL, backlight_17bit); - - /* write ramp */ - REG_WRITE(MASTER_COMM_DATA_REG1, frame_ramp); - - /* setDMCUParam_Cmd */ - REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, MCP_BL_SET); - - /* notifyDMCUMsg */ - REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); - - /* UpdateRequestedBacklightLevel */ - s2 = REG_READ(BIOS_SCRATCH_2); - - s2 &= ~ATOM_S2_CURRENT_BL_LEVEL_MASK; - level &= (ATOM_S2_CURRENT_BL_LEVEL_MASK >> - ATOM_S2_CURRENT_BL_LEVEL_SHIFT); - s2 |= (level << ATOM_S2_CURRENT_BL_LEVEL_SHIFT); - - REG_WRITE(BIOS_SCRATCH_2, s2); -} - -void dce110_link_encoder_init_dmcu_backlight_settings( - struct link_encoder *enc) -{ - struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); - uint32_t bl_pwm_cntl; - uint32_t pwmCntl; - uint32_t pwmCntl2; - uint32_t periodCntl; - uint32_t s2; - uint32_t value; - - if (enc->ctx->dc->debug.disable_dmcu) - return; - - bl_pwm_cntl = REG_READ(BL_PWM_CNTL); - - /* It must not be 0, so we have to restore them - * Bios bug w/a - period resets to zero, - * restoring to cache values which is always correct - */ - REG_GET(BL_PWM_CNTL, BL_ACTIVE_INT_FRAC_CNT, &value); - if (value == 0 || bl_pwm_cntl == 1) { - if (stored_backlight_registers.vBL_PWM_CNTL != 0) { - pwmCntl = stored_backlight_registers.vBL_PWM_CNTL; - REG_WRITE(BL_PWM_CNTL, pwmCntl); - - pwmCntl2 = stored_backlight_registers.vBL_PWM_CNTL2; - REG_WRITE(BL_PWM_CNTL2, pwmCntl2); - - periodCntl = - stored_backlight_registers.vBL_PWM_PERIOD_CNTL; - REG_WRITE(BL_PWM_PERIOD_CNTL, periodCntl); - - REG_UPDATE(LVTMA_PWRSEQ_REF_DIV, - BL_PWM_REF_DIV, - stored_backlight_registers. - vLVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV); - } - } else { - stored_backlight_registers.vBL_PWM_CNTL = - REG_READ(BL_PWM_CNTL); - stored_backlight_registers.vBL_PWM_CNTL2 = - REG_READ(BL_PWM_CNTL2); - stored_backlight_registers.vBL_PWM_PERIOD_CNTL = - REG_READ(BL_PWM_PERIOD_CNTL); - - REG_GET(LVTMA_PWRSEQ_REF_DIV, BL_PWM_REF_DIV, - &stored_backlight_registers. - vLVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV); - } - - /* Have driver take backlight control - * TakeBacklightControl(true) - */ - s2 = REG_READ(BIOS_SCRATCH_2); - s2 |= ATOM_S2_VRI_BRIGHT_ENABLE; - REG_WRITE(BIOS_SCRATCH_2, s2); - - /* Enable the backlight output */ - REG_UPDATE(BL_PWM_CNTL, BL_PWM_EN, 1); -} - static void get_dmcu_psr_state(struct link_encoder *enc, uint32_t *psr_state) { struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h index b3667df5250b..053f72b91b3c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h @@ -226,13 +226,6 @@ union dce110_dmcu_psr_config_data_reg3 { unsigned int u32All; }; -struct dce110_abm_backlight_registers { - unsigned int vBL_PWM_CNTL; - unsigned int vBL_PWM_CNTL2; - unsigned int vBL_PWM_PERIOD_CNTL; - unsigned int vLVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV; -}; - bool dce110_link_encoder_construct( struct dce110_link_encoder *enc110, const struct encoder_init_data *init_data, @@ -317,23 +310,6 @@ void dce110_link_encoder_update_mst_stream_allocation_table( struct link_encoder *enc, const struct link_mst_stream_allocation_table *table); -void dce110_link_encoder_set_lcd_backlight_level( - struct link_encoder *enc, - uint32_t level); - -void dce110_link_encoder_set_dmcu_backlight_level( - struct link_encoder *enc, - uint32_t level, - uint32_t frame_ramp, - uint32_t controller_id); - -void dce110_link_encoder_init_dmcu_backlight_settings( - struct link_encoder *enc); - -void dce110_link_encoder_set_dmcu_abm_level( - struct link_encoder *enc, - uint32_t level); - void dce110_link_encoder_set_dmcu_psr_enable( struct link_encoder *enc, bool enable); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index d67f1100c3d9..a1a5dc6fcb67 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -2214,8 +2214,10 @@ static void init_hw(struct core_dc *dc) } abm = dc->res_pool->abm; - if (abm != NULL) + if (abm != NULL) { + abm->funcs->init_backlight(abm); abm->funcs->abm_init(abm); + } } /* TODO: move this to apply_ctx_tohw some how?*/ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h b/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h index 9c9a6877387a..7d07b7922391 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h @@ -35,6 +35,11 @@ struct abm { struct abm_funcs { void (*abm_init)(struct abm *abm); bool (*set_abm_level)(struct abm *abm, unsigned int abm_level); + bool (*init_backlight)(struct abm *abm); + bool (*set_backlight_level)(struct abm *abm, + unsigned int backlight_level, + unsigned int frame_ramp, + unsigned int controller_id); }; #endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h index 949eae6d5402..7b37b963666e 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h @@ -220,11 +220,6 @@ struct link_encoder_funcs { void (*update_mst_stream_allocation_table)( struct link_encoder *enc, const struct link_mst_stream_allocation_table *table); - void (*set_lcd_backlight_level) (struct link_encoder *enc, - uint32_t level); - void (*set_dmcu_backlight_level)(struct link_encoder *enc, - uint32_t level, uint32_t frame_ramp, uint32_t controller_id); - void (*init_dmcu_backlight_settings)(struct link_encoder *enc); void (*set_dmcu_psr_enable)(struct link_encoder *enc, bool enable); void (*setup_dmcu_psr)(struct link_encoder *enc, struct psr_dmcu_context *psr_context); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 562c8978fe9c..758a568589bb 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -94,10 +94,6 @@ struct hw_sequencer_funcs { int group_size, struct pipe_ctx *grouped_pipes[]); - /* backlight control */ - void (*encoder_set_lcd_backlight_level)( - struct link_encoder *enc, uint32_t level); - void (*enable_display_pipe_clock_gating)( struct dc_context *ctx, bool clock_gating); diff --git a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c index 869dedca0b17..12df49927f09 100644 --- a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c @@ -72,16 +72,6 @@ static void virtual_link_encoder_update_mst_stream_allocation_table( struct link_encoder *enc, const struct link_mst_stream_allocation_table *table) {} -static void virtual_link_encoder_set_lcd_backlight_level( - struct link_encoder *enc, - uint32_t level) {} - -static void virtual_link_encoder_set_dmcu_backlight_level( - struct link_encoder *enc, - uint32_t level, - uint32_t frame_ramp, - uint32_t controller_id) {} - static void virtual_link_encoder_edp_backlight_control( struct link_encoder *enc, bool enable) {} @@ -115,9 +105,6 @@ static const struct link_encoder_funcs virtual_lnk_enc_funcs = { .dp_set_phy_pattern = virtual_link_encoder_dp_set_phy_pattern, .update_mst_stream_allocation_table = virtual_link_encoder_update_mst_stream_allocation_table, - .set_lcd_backlight_level = virtual_link_encoder_set_lcd_backlight_level, - .set_dmcu_backlight_level = - virtual_link_encoder_set_dmcu_backlight_level, .backlight_control = virtual_link_encoder_edp_backlight_control, .power_control = virtual_link_encoder_edp_power_control, .connect_dig_be_to_fe = virtual_link_encoder_connect_dig_be_to_fe, -- cgit From 998166a6116bea93f6e1672177581b689b008bf7 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Tue, 24 Jan 2017 15:45:33 -0500 Subject: drm/amd/display: Make new pixel clock more obvious Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 499ef561bbfc..e05e4199e38a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1066,6 +1066,7 @@ bool dc_pre_update_surfaces_to_stream( int i, j; struct core_dc *core_dc = DC_TO_CORE(dc); uint32_t prev_disp_clk = core_dc->current_context->bw_results.dispclk_khz; + int new_disp_clk; struct dc_stream_status *stream_status = NULL; struct validate_context *context; struct validate_context *temp_context; @@ -1150,6 +1151,7 @@ bool dc_pre_update_surfaces_to_stream( ret = false; goto unexpected_fail; } + new_disp_clk = context->bw_results.dispclk_khz; if (core_dc->res_pool->funcs->apply_clk_constraints) { temp_context = core_dc->res_pool->funcs->apply_clk_constraints( @@ -1166,7 +1168,7 @@ bool dc_pre_update_surfaces_to_stream( context = temp_context; } - if (prev_disp_clk < context->bw_results.dispclk_khz) { + if (prev_disp_clk < new_disp_clk) { pplib_apply_display_requirements(core_dc, context, &context->pp_display_cfg); context->res_ctx.pool->display_clock->funcs->set_clock( -- cgit From 90b9d7fa107d1bde344af6df81927c07cb882f5e Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Fri, 27 Jan 2017 17:22:46 -0500 Subject: drm/amd/display: Support ABM without PPlib Fix problem with loading IRAM Signed-off-by: Anthony Koo Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h | 7 +++++- .../gpu/drm/amd/display/dc/dce/dce_link_encoder.h | 26 +++------------------- 2 files changed, 9 insertions(+), 24 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h index b026157a2eea..33c1754f04f1 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h @@ -30,6 +30,7 @@ #include "dmcu.h" #define DMCU_COMMON_REG_LIST_DCE_BASE() \ + SR(DMCU_CTRL), \ SR(DMCU_RAM_ACCESS_CTRL), \ SR(DMCU_IRAM_WR_CTRL), \ SR(DMCU_IRAM_WR_DATA) @@ -42,6 +43,8 @@ .field_name = reg_name ## __ ## field_name ## post_fix #define DMCU_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh) \ + DMCU_SF(DMCU_CTRL, \ + DMCU_ENABLE, mask_sh), \ DMCU_SF(DMCU_RAM_ACCESS_CTRL, \ IRAM_HOST_ACCESS_EN, mask_sh), \ DMCU_SF(DMCU_RAM_ACCESS_CTRL, \ @@ -55,7 +58,8 @@ #define DMCU_REG_FIELD_LIST(type) \ type DMCU_IRAM_MEM_PWR_STATE; \ type IRAM_HOST_ACCESS_EN; \ - type IRAM_WR_ADDR_AUTO_INC + type IRAM_WR_ADDR_AUTO_INC; \ + type DMCU_ENABLE struct dce_dmcu_shift { DMCU_REG_FIELD_LIST(uint8_t); @@ -66,6 +70,7 @@ struct dce_dmcu_mask { }; struct dce_dmcu_registers { + uint32_t DMCU_CTRL; uint32_t DMCU_RAM_ACCESS_CTRL; uint32_t DCI_MEM_PWR_STATUS; uint32_t DMU_MEM_PWR_CNTL; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h index 053f72b91b3c..8a07665e693b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h @@ -39,18 +39,13 @@ SRI(DC_HPD_CONTROL, HPD, id) #define LE_COMMON_REG_LIST_BASE(id) \ - SR(BL_PWM_CNTL), \ - SR(BL_PWM_GRP1_REG_LOCK), \ - SR(BL_PWM_PERIOD_CNTL), \ - SR(LVTMA_PWRSEQ_CNTL), \ - SR(LVTMA_PWRSEQ_STATE), \ - SR(BL_PWM_CNTL2), \ - SR(LVTMA_PWRSEQ_REF_DIV), \ SR(MASTER_COMM_DATA_REG1), \ SR(MASTER_COMM_DATA_REG2), \ SR(MASTER_COMM_DATA_REG3), \ SR(MASTER_COMM_CMD_REG), \ SR(MASTER_COMM_CNTL_REG), \ + SR(LVTMA_PWRSEQ_CNTL), \ + SR(LVTMA_PWRSEQ_STATE), \ SR(DMCU_RAM_ACCESS_CTRL), \ SR(DMCU_IRAM_RD_CTRL), \ SR(DMCU_IRAM_RD_DATA), \ @@ -81,22 +76,16 @@ LE_COMMON_REG_LIST_BASE(id), \ SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ - SR(BIOS_SCRATCH_2), \ - SR(BL1_PWM_USER_LEVEL), \ SR(DCI_MEM_PWR_STATUS) #define LE_DCE110_REG_LIST(id)\ LE_COMMON_REG_LIST_BASE(id), \ SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ - SR(BIOS_SCRATCH_2), \ - SR(BL1_PWM_USER_LEVEL), \ SR(DCI_MEM_PWR_STATUS) #define LE_DCE80_REG_LIST(id)\ - SR(BIOS_SCRATCH_2), \ SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ - SR(BL1_PWM_USER_LEVEL), \ LE_COMMON_REG_LIST_BASE(id) @@ -110,24 +99,16 @@ struct dce110_link_enc_hpd_registers { }; struct dce110_link_enc_registers { - /* BL registers */ - uint32_t BL_PWM_CNTL; - uint32_t BL_PWM_GRP1_REG_LOCK; - uint32_t BL_PWM_PERIOD_CNTL; + /* Backlight registers */ uint32_t LVTMA_PWRSEQ_CNTL; uint32_t LVTMA_PWRSEQ_STATE; - uint32_t BL_PWM_CNTL2; - uint32_t LVTMA_PWRSEQ_REF_DIV; /* DMCU registers */ - uint32_t BL1_PWM_USER_LEVEL; - uint32_t ABM0_BL1_PWM_USER_LEVEL; uint32_t MASTER_COMM_DATA_REG1; uint32_t MASTER_COMM_DATA_REG2; uint32_t MASTER_COMM_DATA_REG3; uint32_t MASTER_COMM_CMD_REG; uint32_t MASTER_COMM_CNTL_REG; - uint32_t BIOS_SCRATCH_2; uint32_t DMCU_RAM_ACCESS_CTRL; uint32_t DCI_MEM_PWR_STATUS; uint32_t DMU_MEM_PWR_CNTL; @@ -136,7 +117,6 @@ struct dce110_link_enc_registers { uint32_t DMCU_INTERRUPT_TO_UC_EN_MASK; uint32_t SMU_INTERRUPT_CONTROL; - /* Common DP registers */ uint32_t DIG_BE_CNTL; uint32_t DIG_BE_EN_CNTL; -- cgit From 70814f6f092a91a552eef9f4580c9ddc7cdcbb32 Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Fri, 27 Jan 2017 17:50:03 -0500 Subject: drm/amd/display: Debug option to force enable ABM Signed-off-by: Anthony Koo Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 1308af59d839..d7f848495d8a 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -143,6 +143,7 @@ struct dc_debug { bool disable_dfs_bypass; bool disable_clock_gate; bool disable_dmcu; + bool force_abm_enable; }; struct dc { -- cgit From 0f56b418ef497032a71358fb8c76d10f24fd5d58 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 25 Jan 2017 13:58:46 -0500 Subject: drm/amd/display: add dcfclk reporting to pplib Signed-off-by: Dmytro Laktyushkin Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 48 +++++++++---------------- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 1 + 2 files changed, 18 insertions(+), 31 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index e05e4199e38a..9d2f78f21748 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1065,7 +1065,7 @@ bool dc_pre_update_surfaces_to_stream( { int i, j; struct core_dc *core_dc = DC_TO_CORE(dc); - uint32_t prev_disp_clk = core_dc->current_context->bw_results.dispclk_khz; + int prev_disp_clk = core_dc->current_context->bw_results.dispclk_khz; int new_disp_clk; struct dc_stream_status *stream_status = NULL; struct validate_context *context; @@ -1146,36 +1146,23 @@ bool dc_pre_update_surfaces_to_stream( } } - if (core_dc->res_pool->funcs->validate_bandwidth(core_dc, context) != DC_OK) { - BREAK_TO_DEBUGGER(); - ret = false; - goto unexpected_fail; - } - new_disp_clk = context->bw_results.dispclk_khz; - - if (core_dc->res_pool->funcs->apply_clk_constraints) { - temp_context = core_dc->res_pool->funcs->apply_clk_constraints( - core_dc, - context); - if (!temp_context) { - dm_error("%s:failed apply clk constraints\n", __func__); + if (core_dc->res_pool->funcs->validate_bandwidth) + if (core_dc->res_pool->funcs->validate_bandwidth(core_dc, context) != DC_OK) { + BREAK_TO_DEBUGGER(); ret = false; goto unexpected_fail; } - resource_validate_ctx_destruct(context); - ASSERT(core_dc->scratch_val_ctx == temp_context); - core_dc->scratch_val_ctx = context; - context = temp_context; - } + new_disp_clk = context->bw_results.dispclk_khz; - if (prev_disp_clk < new_disp_clk) { + if (!IS_FPGA_MAXIMUS_DC(core_dc->ctx->dce_environment) + && prev_disp_clk < new_disp_clk) { pplib_apply_display_requirements(core_dc, context, &context->pp_display_cfg); context->res_ctx.pool->display_clock->funcs->set_clock( context->res_ctx.pool->display_clock, - context->bw_results.dispclk_khz * 115 / 100); - core_dc->current_context->bw_results.dispclk_khz = - context->bw_results.dispclk_khz; + new_disp_clk * 115 / 100); + core_dc->current_context->bw_results.dispclk_khz = new_disp_clk; + core_dc->current_context->dispclk_khz = new_disp_clk; } for (i = 0; i < new_surface_count; i++) @@ -1209,15 +1196,14 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) if (core_dc->current_context->res_ctx.pipe_ctx[i].stream == NULL) { core_dc->current_context->res_ctx.pipe_ctx[i].pipe_idx = i; core_dc->hwss.power_down_front_end( - core_dc, &core_dc->current_context->res_ctx.pipe_ctx[i]); + core_dc, &core_dc->current_context->res_ctx.pipe_ctx[i]); + } + if (core_dc->res_pool->funcs->validate_bandwidth) + if (core_dc->res_pool->funcs->validate_bandwidth( + core_dc, core_dc->current_context) != DC_OK) { + BREAK_TO_DEBUGGER(); + return false; } - - - if (core_dc->res_pool->funcs->validate_bandwidth(core_dc, core_dc->current_context) - != DC_OK) { - BREAK_TO_DEBUGGER(); - return false; - } core_dc->hwss.set_bandwidth(core_dc); diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 1a81e83d1785..124df6795b34 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -316,6 +316,7 @@ struct validate_context { struct bw_calcs_output bw_results; /* Note: these are big structures, do *not* put on stack! */ struct dm_pp_display_configuration pp_display_cfg; + int dispclk_khz; }; #endif /* _CORE_TYPES_H_ */ -- cgit From 3efeef11f471c1c5ee116cb00d27f426bfa969dc Mon Sep 17 00:00:00 2001 From: Leon Elazar Date: Mon, 30 Jan 2017 10:25:43 -0500 Subject: drm/amd/display: surface validation on dce100 Signed-off-by: Leon Elazar Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 6ae334b42fbf..800b22e70c7e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -789,9 +789,9 @@ static bool dce100_validate_surface_sets( return false; if (set[i].surfaces[0]->clip_rect.width - != set[i].stream->src.width + < set[i].stream->src.width || set[i].surfaces[0]->clip_rect.height - != set[i].stream->src.height) + < set[i].stream->src.height) return false; if (set[i].surfaces[0]->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) -- cgit From 71f7256e41ad036215a69e6bf561f7d4a541f150 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Mon, 30 Jan 2017 17:35:59 -0500 Subject: drm/amd/display: remove CV-specific timing standard Signed-off-by: Charlene Liu Reviewed-by: Jordan Lazare Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c | 5 ----- drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 2 -- drivers/gpu/drm/amd/display/dc/dce/dce_opp.c | 4 ---- drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c | 5 ----- 4 files changed, 16 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c index 9f462a299ff3..6cd1e93b5084 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c @@ -66,11 +66,6 @@ void color_space_to_black_color( } switch (colorspace) { - case COLOR_SPACE_YPBPR601: - *black_color = black_color_format[BLACK_COLOR_FORMAT_YUV_TV]; - break; - - case COLOR_SPACE_YPBPR709: case COLOR_SPACE_YCBCR601: case COLOR_SPACE_YCBCR709: case COLOR_SPACE_YCBCR601_LIMITED: diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index 53c73de75da9..21092f33c83b 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -435,8 +435,6 @@ enum dc_color_space { COLOR_SPACE_UNKNOWN, COLOR_SPACE_SRGB, COLOR_SPACE_SRGB_LIMITED, - COLOR_SPACE_YPBPR601, - COLOR_SPACE_YPBPR709, COLOR_SPACE_YCBCR601, COLOR_SPACE_YCBCR709, COLOR_SPACE_YCBCR601_LIMITED, diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c index 62f01911639f..9247afd4d42f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c @@ -827,14 +827,12 @@ static bool configure_graphics_mode( OUTPUT_CSC_GRPH_MODE, 1); break; case COLOR_SPACE_YCBCR601: - case COLOR_SPACE_YPBPR601: case COLOR_SPACE_YCBCR601_LIMITED: /* YCbCr601 */ REG_SET(OUTPUT_CSC_CONTROL, 0, OUTPUT_CSC_GRPH_MODE, 2); break; case COLOR_SPACE_YCBCR709: - case COLOR_SPACE_YPBPR709: case COLOR_SPACE_YCBCR709_LIMITED: /* YCbCr709 */ REG_SET(OUTPUT_CSC_CONTROL, 0, @@ -858,14 +856,12 @@ static bool configure_graphics_mode( OUTPUT_CSC_GRPH_MODE, 1); break; case COLOR_SPACE_YCBCR601: - case COLOR_SPACE_YPBPR601: case COLOR_SPACE_YCBCR601_LIMITED: /* YCbCr601 */ REG_SET(OUTPUT_CSC_CONTROL, 0, OUTPUT_CSC_GRPH_MODE, 2); break; case COLOR_SPACE_YCBCR709: - case COLOR_SPACE_YPBPR709: case COLOR_SPACE_YCBCR709_LIMITED: /* YCbCr709 */ REG_SET(OUTPUT_CSC_CONTROL, 0, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c index 6995a3de7564..019effe4c99c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c @@ -383,8 +383,6 @@ static bool configure_graphics_mode_v( /* not supported for underlay on CZ */ return false; - case COLOR_SPACE_YCBCR601: - case COLOR_SPACE_YPBPR601: case COLOR_SPACE_YCBCR601_LIMITED: /* YCbCr601 */ set_reg_field_value( @@ -394,7 +392,6 @@ static bool configure_graphics_mode_v( OUTPUT_CSC_MODE); break; case COLOR_SPACE_YCBCR709: - case COLOR_SPACE_YPBPR709: case COLOR_SPACE_YCBCR709_LIMITED: /* YCbCr709 */ set_reg_field_value( @@ -421,7 +418,6 @@ static bool configure_graphics_mode_v( /* not supported for underlay on CZ */ return false; case COLOR_SPACE_YCBCR601: - case COLOR_SPACE_YPBPR601: case COLOR_SPACE_YCBCR601_LIMITED: /* YCbCr601 */ set_reg_field_value( @@ -431,7 +427,6 @@ static bool configure_graphics_mode_v( OUTPUT_CSC_MODE); break; case COLOR_SPACE_YCBCR709: - case COLOR_SPACE_YPBPR709: case COLOR_SPACE_YCBCR709_LIMITED: /* YCbCr709 */ set_reg_field_value( -- cgit From ca709397b5bf904ef04eb981d3b50e8e93c15394 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 6 Feb 2017 11:23:20 -0500 Subject: drm/amd/display: Fix 64-bit division Signed-off-by: Harry Wentland Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_abm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c index f4696bf14a70..7005ebb28d46 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c @@ -94,7 +94,7 @@ static unsigned int get_current_backlight(struct dce_abm *abm_dce) if (bl_period == 0) bl_period = 0xFFFF; - current_backlight /= bl_period; + current_backlight = div_u64(current_backlight, bl_period); current_backlight = (current_backlight + 1) >> 1; current_backlight = (uint64_t)(current_backlight) * bl_period; -- cgit From b7e2439c7878f06edb70379454d57ce3d51d3feb Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Mon, 6 Feb 2017 12:37:44 +0800 Subject: drm/amd/display: mclk level can't be 0. Signed-off-by: Rex Zhu Acked-by: Alex Deucher Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c index 5af27aad2dad..1ddc56cfbdc4 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c @@ -357,8 +357,8 @@ bool dm_pp_get_clock_levels_by_type( * Than means the previous one is the highest * non-boosted one. */ DRM_INFO("DM_PPLIB: reducing engine clock level from %d to %d\n", - dc_clks->num_levels, i + 1); - dc_clks->num_levels = i; + dc_clks->num_levels, i); + dc_clks->num_levels = i > 0 ? i : 1; break; } } @@ -366,8 +366,8 @@ bool dm_pp_get_clock_levels_by_type( for (i = 0; i < dc_clks->num_levels; i++) { if (dc_clks->clocks_in_khz[i] > validation_clks.memory_max_clock) { DRM_INFO("DM_PPLIB: reducing memory clock level from %d to %d\n", - dc_clks->num_levels, i + 1); - dc_clks->num_levels = i; + dc_clks->num_levels, i); + dc_clks->num_levels = i > 0 ? i : 1; break; } } -- cgit From 71021265a6f03893139f58f2bc50d2ad9adc3826 Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Fri, 27 Jan 2017 15:44:26 -0500 Subject: drm/amd/display: Clear test pattern when enabling stream Signed-off-by: Hersen Wu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 2bceb3aa24b5..ec5de329b091 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1846,6 +1846,11 @@ void core_link_enable_stream(struct pipe_ctx *pipe_ctx) return; } + /* turn off otg test pattern if enable */ + pipe_ctx->tg->funcs->set_test_pattern(pipe_ctx->tg, + CONTROLLER_DP_TEST_PATTERN_VIDEOMODE, + COLOR_DEPTH_UNDEFINED); + core_dc->hwss.enable_stream(pipe_ctx); if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) -- cgit From 8fde5884f4a18dec81ab5d498bf7bf3c156f8dfb Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Tue, 31 Jan 2017 20:18:05 -0500 Subject: drm/amd/display: Fix YCbCr pixel format shows green issue Signed-off-by: Charlene Liu Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index ee1c3b029394..3d8a85e48b05 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1300,19 +1300,23 @@ static void set_avi_info_frame( info_frame.avi_info_packet.info_packet_hdmi.bits.S0_S1 = scan_type; /* C0, C1 : Colorimetry */ - if (color_space == COLOR_SPACE_YCBCR709) + if (color_space == COLOR_SPACE_YCBCR709 || + color_space == COLOR_SPACE_YCBCR709_LIMITED) info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 = COLORIMETRY_ITU709; - else if (color_space == COLOR_SPACE_YCBCR601) + else if (color_space == COLOR_SPACE_YCBCR601 || + color_space == COLOR_SPACE_YCBCR601_LIMITED) info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 = COLORIMETRY_ITU601; - else + else { + if (stream->public.timing.pixel_encoding != PIXEL_ENCODING_RGB) + BREAK_TO_DEBUGGER(); info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 = COLORIMETRY_NO_DATA; - + } if (color_space == COLOR_SPACE_2020_RGB_FULLRANGE || - color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE || - color_space == COLOR_SPACE_2020_YCBCR) { + color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE || + color_space == COLOR_SPACE_2020_YCBCR) { info_frame.avi_info_packet.info_packet_hdmi.bits.EC0_EC2 = COLORIMETRYEX_BT2020RGBYCBCR; info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 = -- cgit From cc4d99b8a888e16093b985d6a11fbd37ab92697c Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Wed, 1 Feb 2017 20:35:53 -0500 Subject: drm/amd/display: HDMI YCbCr422 12bpc pixel format issue Signed-off-by: Charlene Liu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 7 ++++- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 30 ++++++++++---------- .../gpu/drm/amd/display/dc/dce/dce_clock_source.c | 29 ++++++++++---------- drivers/gpu/drm/amd/display/dc/dce/dce_opp.c | 32 +++++++++++++++++----- .../drm/amd/display/dc/dce/dce_stream_encoder.c | 16 +++++++---- .../drm/amd/display/dc/dce110/dce110_resource.c | 3 ++ drivers/gpu/drm/amd/display/dc/inc/clock_source.h | 2 +- drivers/gpu/drm/amd/display/dc/inc/hw/opp.h | 1 + 8 files changed, 76 insertions(+), 44 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index ec5de329b091..2b929393f68a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1267,6 +1267,7 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) { struct core_stream *stream = pipe_ctx->stream; struct core_link *link = stream->sink->link; + enum dc_color_depth display_color_depth; if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) dal_ddc_service_write_scdc_data( @@ -1277,10 +1278,14 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) memset(&stream->sink->link->public.cur_link_settings, 0, sizeof(struct dc_link_settings)); + display_color_depth = stream->public.timing.display_color_depth; + if (stream->public.timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) + display_color_depth = COLOR_DEPTH_888; + link->link_enc->funcs->enable_tmds_output( link->link_enc, pipe_ctx->clock_source->id, - stream->public.timing.display_color_depth, + display_color_depth, pipe_ctx->stream->signal == SIGNAL_TYPE_HDMI_TYPE_A, pipe_ctx->stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK, stream->phy_pix_clk); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 3d8a85e48b05..856a33ad8ec1 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1045,25 +1045,25 @@ static int get_norm_pix_clk(const struct dc_crtc_timing *timing) if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) pix_clk /= 2; - - switch (timing->display_color_depth) { - case COLOR_DEPTH_888: - normalized_pix_clk = pix_clk; - break; - case COLOR_DEPTH_101010: - normalized_pix_clk = (pix_clk * 30) / 24; + if (timing->pixel_encoding != PIXEL_ENCODING_YCBCR422) { + switch (timing->display_color_depth) { + case COLOR_DEPTH_888: + normalized_pix_clk = pix_clk; + break; + case COLOR_DEPTH_101010: + normalized_pix_clk = (pix_clk * 30) / 24; + break; + case COLOR_DEPTH_121212: + normalized_pix_clk = (pix_clk * 36) / 24; break; - case COLOR_DEPTH_121212: - normalized_pix_clk = (pix_clk * 36) / 24; + case COLOR_DEPTH_161616: + normalized_pix_clk = (pix_clk * 48) / 24; break; - case COLOR_DEPTH_161616: - normalized_pix_clk = (pix_clk * 48) / 24; - break; - default: - ASSERT(0); + default: + ASSERT(0); break; + } } - return normalized_pix_clk; } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index 78f43274a03a..a9f39218ce82 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -390,25 +390,24 @@ static bool pll_adjust_pix_clk( struct bp_adjust_pixel_clock_parameters bp_adjust_pixel_clock_params = { 0 }; enum bp_result bp_result; - switch (pix_clk_params->signal_type) { case SIGNAL_TYPE_HDMI_TYPE_A: { requested_clk_khz = pix_clk_params->requested_pix_clk; - - switch (pix_clk_params->color_depth) { - case COLOR_DEPTH_101010: - requested_clk_khz = (requested_clk_khz * 5) >> 2; - break; /* x1.25*/ - case COLOR_DEPTH_121212: - requested_clk_khz = (requested_clk_khz * 6) >> 2; - break; /* x1.5*/ - case COLOR_DEPTH_161616: - requested_clk_khz = requested_clk_khz * 2; - break; /* x2.0*/ - default: - break; + if (pix_clk_params->pixel_encoding != PIXEL_ENCODING_YCBCR422) { + switch (pix_clk_params->color_depth) { + case COLOR_DEPTH_101010: + requested_clk_khz = (requested_clk_khz * 5) >> 2; + break; /* x1.25*/ + case COLOR_DEPTH_121212: + requested_clk_khz = (requested_clk_khz * 6) >> 2; + break; /* x1.5*/ + case COLOR_DEPTH_161616: + requested_clk_khz = requested_clk_khz * 2; + break; /* x2.0*/ + default: + break; + } } - actual_pix_clk_khz = requested_clk_khz; } break; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c index 9247afd4d42f..a2f57cf603aa 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c @@ -366,19 +366,37 @@ static void set_truncation( FMT_TRUNCATE_EN, 0, FMT_TRUNCATE_DEPTH, 0, FMT_TRUNCATE_MODE, 0); - /* no 10bpc trunc on DCE11*/ + + + if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) { + /* 8bpc trunc on YCbCr422*/ + if (params->flags.TRUNCATE_DEPTH == 1) + REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, + FMT_TRUNCATE_EN, 1, + FMT_TRUNCATE_DEPTH, 1, + FMT_TRUNCATE_MODE, 0); + else if (params->flags.TRUNCATE_DEPTH == 2) + /* 10bpc trunc on YCbCr422*/ + REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, + FMT_TRUNCATE_EN, 1, + FMT_TRUNCATE_DEPTH, 2, + FMT_TRUNCATE_MODE, 0); + return; + } + /* on other format-to do */ if (params->flags.TRUNCATE_ENABLED == 0 || - params->flags.TRUNCATE_DEPTH == 2) + params->flags.TRUNCATE_DEPTH == 2) return; - /*Set truncation depth and Enable truncation*/ REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, - FMT_TRUNCATE_EN, 1, - FMT_TRUNCATE_DEPTH, params->flags.TRUNCATE_MODE, - FMT_TRUNCATE_MODE, params->flags.TRUNCATE_DEPTH); - + FMT_TRUNCATE_EN, 1, + FMT_TRUNCATE_DEPTH, + params->flags.TRUNCATE_MODE, + FMT_TRUNCATE_MODE, + params->flags.TRUNCATE_DEPTH); } + /** * set_spatial_dither * 1) set spatial dithering mode: pattern of seed diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c index 7e6661bda970..a28d9c7ba17e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c @@ -367,14 +367,20 @@ static void dce110_stream_encoder_hdmi_set_stream_attribute( HDMI_DEEP_COLOR_ENABLE, 1); break; case COLOR_DEPTH_121212: - REG_UPDATE_2(HDMI_CONTROL, - HDMI_DEEP_COLOR_DEPTH, 2, - HDMI_DEEP_COLOR_ENABLE, 1); + if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) { + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DEEP_COLOR_DEPTH, 2, + HDMI_DEEP_COLOR_ENABLE, 0); + } else { + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DEEP_COLOR_DEPTH, 2, + HDMI_DEEP_COLOR_ENABLE, 1); + } break; case COLOR_DEPTH_161616: REG_UPDATE_2(HDMI_CONTROL, - HDMI_DEEP_COLOR_DEPTH, 3, - HDMI_DEEP_COLOR_ENABLE, 1); + HDMI_DEEP_COLOR_DEPTH, 3, + HDMI_DEEP_COLOR_ENABLE, 1); break; default: break; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 8dc69be15182..4c108d0fb164 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -814,6 +814,9 @@ void dce110_resource_build_bit_depth_reduction_params( fmt_bit_depth->flags.HIGHPASS_RANDOM = 1; fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; fmt_bit_depth->flags.TRUNCATE_DEPTH = 2; + + fmt_bit_depth->pixel_encoding = + stream->public.timing.pixel_encoding; } return; diff --git a/drivers/gpu/drm/amd/display/dc/inc/clock_source.h b/drivers/gpu/drm/amd/display/dc/inc/clock_source.h index c91c7815ec6e..47ef90495376 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/clock_source.h +++ b/drivers/gpu/drm/amd/display/dc/inc/clock_source.h @@ -94,7 +94,7 @@ struct pixel_clk_params { enum dc_color_depth color_depth; struct csdp_ref_clk_ds_params de_spread_params; /*> de-spread info, relevant only for on-the-fly tune-up pixel rate*/ - + enum dc_pixel_encoding pixel_encoding; struct pixel_clk_flags flags; }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h index a10c4e296960..e01b831a7e7f 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h @@ -86,6 +86,7 @@ struct bit_depth_reduction_params { uint32_t r_seed_value; uint32_t b_seed_value; uint32_t g_seed_value; + enum dc_pixel_encoding pixel_encoding; }; enum wide_gamut_regamma_mode { -- cgit From ffbcd19a8856a63f4310c89b2af599409e3f2216 Mon Sep 17 00:00:00 2001 From: Vitaly Prosyak Date: Wed, 1 Feb 2017 12:54:15 -0600 Subject: drm/amd/display: Adding 10 bpcc video P010 format Signed-off-by: Vitaly Prosyak Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c | 5 +++++ drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 6 ++++-- drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 5 ++++- 3 files changed, 13 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c index 946379852b2a..ab8d1e931846 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c @@ -2534,6 +2534,8 @@ static void populate_initial_data( case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: data->bytes_per_pixel[num_displays + 4] = 4; break; case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: @@ -2621,6 +2623,7 @@ static void populate_initial_data( } switch (pipe[i].surface->public.format) { case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: case SURFACE_PIXEL_FORMAT_GRPH_RGB565: data->bytes_per_pixel[num_displays + 4] = 2; @@ -2630,6 +2633,8 @@ static void populate_initial_data( case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: data->bytes_per_pixel[num_displays + 4] = 4; break; case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 856a33ad8ec1..e4e86110d45d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -358,11 +358,13 @@ static enum pixel_format convert_pixel_format_to_dalsurface( dal_pixel_format = PIXEL_FORMAT_FP16; break; case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: - dal_pixel_format = PIXEL_FORMAT_420BPP12; - break; case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: dal_pixel_format = PIXEL_FORMAT_420BPP12; break; + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: + dal_pixel_format = PIXEL_FORMAT_420BPP15; + break; case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: default: dal_pixel_format = PIXEL_FORMAT_UNKNOWN; diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index 21092f33c83b..75e16ac70f5f 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -195,6 +195,8 @@ enum surface_pixel_format { SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr = SURFACE_PIXEL_FORMAT_VIDEO_BEGIN, SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb, + SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr, + SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb, SURFACE_PIXEL_FORMAT_INVALID /*grow 444 video here if necessary */ @@ -212,13 +214,14 @@ enum pixel_format { PIXEL_FORMAT_FP16, /*video*/ PIXEL_FORMAT_420BPP12, + PIXEL_FORMAT_420BPP15, /*end of pixel format definition*/ PIXEL_FORMAT_INVALID, PIXEL_FORMAT_GRPH_BEGIN = PIXEL_FORMAT_INDEX8, PIXEL_FORMAT_GRPH_END = PIXEL_FORMAT_FP16, PIXEL_FORMAT_VIDEO_BEGIN = PIXEL_FORMAT_420BPP12, - PIXEL_FORMAT_VIDEO_END = PIXEL_FORMAT_420BPP12, + PIXEL_FORMAT_VIDEO_END = PIXEL_FORMAT_420BPP15, PIXEL_FORMAT_UNKNOWN }; -- cgit From 94cd1f79b05994b712a2cf0563ac73be0323978b Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Thu, 2 Feb 2017 15:21:45 -0500 Subject: drm/amd/display: Fixed color temperature corruption. Signed-off-by: Yongqiang Sun Reviewed-by: Jordan Lazare Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h index b8735b27e9bc..dfe590198a33 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h @@ -65,7 +65,7 @@ struct pwl_result_data { }; struct pwl_params { - struct gamma_curve arr_curve_points[16]; + struct gamma_curve arr_curve_points[34]; struct curve_points arr_points[3]; struct pwl_result_data rgb_resulted[256 + 3]; uint32_t hw_points_num; -- cgit From f7f3cfee084b0c68789e2b4231b0d3de3466a52b Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Fri, 3 Feb 2017 11:45:43 -0500 Subject: drm/amd/display: fix crash with modesetting driver They might call commit with ACTION_NOTHING without a mode. We shouldn't crash but simply skip updating stream scaling settings since scaling obviously didn't change without a provided mode. Signed-off-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index ad60a28975ca..fdb264c6e859 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -638,6 +638,10 @@ static void update_stream_scaling_settings( struct rect src = { 0 }; /* viewport in composition space*/ struct rect dst = { 0 }; /* stream addressable area */ + /* no mode. nothing to be done */ + if (!mode) + return; + /* Full screen scaling by default */ src.width = mode->hdisplay; src.height = mode->vdisplay; -- cgit From a2b763cbd69e59854ed3ff9f79b7e8471748ea69 Mon Sep 17 00:00:00 2001 From: Krzysztof Nowicki Date: Fri, 27 Jan 2017 18:58:27 +0100 Subject: drm/amd/display: Fix MST physical ports always disconnected Remove a false assumption that a cached EDID will be present whenever the connector is in a connected state as this will only be true for logical MST ports. For physical ports the EDID will never be cached, which will cause them to always appear as disconnected. This reverts commit 4ff8a88888de271bfb7750b2a5c68163848e2bf1 Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index e4d94d4c215d..41988c89d471 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -127,14 +127,6 @@ dm_dp_mst_detect(struct drm_connector *connector, bool force) &master->mst_mgr, aconnector->port); - /* - * we do not want to make this connector connected until we have edid on - * it - */ - if (status == connector_status_connected && - !aconnector->port->cached_edid) - status = connector_status_disconnected; - return status; } -- cgit From a99240d5f8e14fc081e2cccad6ac46b48cea7def Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Thu, 2 Feb 2017 17:08:19 -0500 Subject: drm/amd/display: use disp clock value in context rather than bw_results Signed-off-by: Dmytro Laktyushkin Reviewed-by: Jordan Lazare Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 14 ++++++-------- drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c | 2 +- .../gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 10 +++++----- drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c | 1 + drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c | 1 + drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c | 2 +- 6 files changed, 15 insertions(+), 15 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 9d2f78f21748..4c405f4b880e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -925,7 +925,7 @@ void pplib_apply_display_requirements( /* TODO: dce11.2*/ pp_display_cfg->avail_mclk_switch_time_in_disp_active_us = 0; - pp_display_cfg->disp_clk_khz = context->bw_results.dispclk_khz; + pp_display_cfg->disp_clk_khz = context->dispclk_khz; fill_display_configs(context, pp_display_cfg); @@ -1065,8 +1065,7 @@ bool dc_pre_update_surfaces_to_stream( { int i, j; struct core_dc *core_dc = DC_TO_CORE(dc); - int prev_disp_clk = core_dc->current_context->bw_results.dispclk_khz; - int new_disp_clk; + int prev_disp_clk = core_dc->current_context->dispclk_khz; struct dc_stream_status *stream_status = NULL; struct validate_context *context; struct validate_context *temp_context; @@ -1152,17 +1151,16 @@ bool dc_pre_update_surfaces_to_stream( ret = false; goto unexpected_fail; } - new_disp_clk = context->bw_results.dispclk_khz; if (!IS_FPGA_MAXIMUS_DC(core_dc->ctx->dce_environment) - && prev_disp_clk < new_disp_clk) { + && prev_disp_clk < context->dispclk_khz) { pplib_apply_display_requirements(core_dc, context, &context->pp_display_cfg); context->res_ctx.pool->display_clock->funcs->set_clock( context->res_ctx.pool->display_clock, - new_disp_clk * 115 / 100); - core_dc->current_context->bw_results.dispclk_khz = new_disp_clk; - core_dc->current_context->dispclk_khz = new_disp_clk; + context->dispclk_khz * 115 / 100); + core_dc->current_context->bw_results.dispclk_khz = context->dispclk_khz; + core_dc->current_context->dispclk_khz = context->dispclk_khz; } for (i = 0; i < new_surface_count; i++) diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 800b22e70c7e..55501b381692 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -770,7 +770,7 @@ enum dc_status dce100_validate_bandwidth( struct validate_context *context) { /* TODO implement when needed but for now hardcode max value*/ - context->bw_results.dispclk_khz = 681000; + context->dispclk_khz = 681000; return DC_OK; } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index a1a5dc6fcb67..5e99f6c27c9a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1651,7 +1651,7 @@ static void apply_min_clocks( /* get the required state based on state dependent clocks: * display clock and pixel clock */ - req_clocks.display_clk_khz = context->bw_results.dispclk_khz; + req_clocks.display_clk_khz = context->dispclk_khz; req_clocks.pixel_clk_khz = get_max_pixel_clock_for_all_paths( dc, context, true); @@ -1776,11 +1776,11 @@ enum dc_status dce110_apply_ctx_to_hw( /*TODO: when pplib works*/ apply_min_clocks(dc, context, &clocks_state, true); - if (context->bw_results.dispclk_khz - > dc->current_context->bw_results.dispclk_khz) + if (context->dispclk_khz + > dc->current_context->dispclk_khz) context->res_ctx.pool->display_clock->funcs->set_clock( context->res_ctx.pool->display_clock, - context->bw_results.dispclk_khz * 115 / 100); + context->dispclk_khz * 115 / 100); for (i = 0; i < context->res_ctx.pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx_old = @@ -2289,7 +2289,7 @@ static void dce110_set_bandwidth(struct core_dc *dc) dc->current_context->res_ctx.pool->display_clock->funcs->set_clock( dc->current_context->res_ctx.pool->display_clock, - dc->current_context->bw_results.dispclk_khz * 115 / 100); + dc->current_context->dispclk_khz * 115 / 100); } static void dce110_program_front_end_for_pipe( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 4c108d0fb164..ee4fda514de6 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -926,6 +926,7 @@ enum dc_status dce110_validate_bandwidth( result = DC_FAIL_BANDWIDTH_VALIDATE; else result = DC_OK; + context->dispclk_khz = context->bw_results.dispclk_khz; if (result == DC_FAIL_BANDWIDTH_VALIDATE) dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_VALIDATION, diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 7e99b2b96794..54af84ebf2bc 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -857,6 +857,7 @@ enum dc_status dce112_validate_bandwidth( result = DC_FAIL_BANDWIDTH_VALIDATE; else result = DC_OK; + context->dispclk_khz = context->bw_results.dispclk_khz; if (result == DC_FAIL_BANDWIDTH_VALIDATE) dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_VALIDATION, diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index fea60aa5d297..3de8bfb47dce 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -785,7 +785,7 @@ enum dc_status dce80_validate_bandwidth( struct validate_context *context) { /* TODO implement when needed but for now hardcode max value*/ - context->bw_results.dispclk_khz = 681000; + context->dispclk_khz = 681000; context->bw_results.required_yclk = 250000 * MEMORY_TYPE_MULTIPLIER; return DC_OK; -- cgit From 871ffb606a3eb9b29891b25228f569899bbd216c Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Mon, 6 Feb 2017 15:07:19 -0500 Subject: drm/amd/display: fix psr status wait Signed-off-by: Dmytro Laktyushkin Reviewed-by: Eagle Yeh Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 18 +++++++++++++++--- .../gpu/drm/amd/display/dc/dce/dce_link_encoder.h | 22 +++++++++++----------- drivers/gpu/drm/amd/display/dc/dm_services.h | 2 +- 3 files changed, 27 insertions(+), 15 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 3847764688dd..60fdf58fc5cc 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -38,6 +38,14 @@ #include "dce/dce_11_0_sh_mask.h" #include "dce/dce_11_0_enum.h" +#ifndef DMU_MEM_PWR_CNTL__DMCU_IRAM_MEM_PWR_STATE__SHIFT +#define DMU_MEM_PWR_CNTL__DMCU_IRAM_MEM_PWR_STATE__SHIFT 0xa +#endif + +#ifndef DMU_MEM_PWR_CNTL__DMCU_IRAM_MEM_PWR_STATE_MASK +#define DMU_MEM_PWR_CNTL__DMCU_IRAM_MEM_PWR_STATE_MASK 0x00000400L +#endif + #ifndef HPD0_DC_HPD_CONTROL__DC_HPD_EN_MASK #define HPD0_DC_HPD_CONTROL__DC_HPD_EN_MASK 0x10000000L #endif @@ -1557,15 +1565,19 @@ static void get_dmcu_psr_state(struct link_encoder *enc, uint32_t *psr_state) uint32_t count = 0; uint32_t psrStateOffset = 0xf0; - uint32_t value; + uint32_t value = -1; /* Enable write access to IRAM */ REG_UPDATE(DMCU_RAM_ACCESS_CTRL, IRAM_HOST_ACCESS_EN, 1); - do { + while (REG(DCI_MEM_PWR_STATUS) && value != 0 && count++ < 10) { dm_delay_in_microseconds(ctx, 2); REG_GET(DCI_MEM_PWR_STATUS, DMCU_IRAM_MEM_PWR_STATE, &value); - } while (value != 0 && count++ < 10); + } + while (REG(DMU_MEM_PWR_CNTL) && value != 0 && count++ < 10) { + dm_delay_in_microseconds(ctx, 2); + REG_GET(DMU_MEM_PWR_CNTL, DMCU_IRAM_MEM_PWR_STATE, &value); + } /* Write address to IRAM_RD_ADDR in DMCU_IRAM_RD_CTRL */ REG_WRITE(DMCU_IRAM_RD_CTRL, psrStateOffset); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h index 8a07665e693b..d382a6882d95 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h @@ -72,17 +72,17 @@ SRI(DP_DPHY_FAST_TRAINING, DP, id), \ SRI(DP_SEC_CNTL1, DP, id) - #define LE_COMMON_REG_LIST(id)\ - LE_COMMON_REG_LIST_BASE(id), \ - SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ - SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ - SR(DCI_MEM_PWR_STATUS) - - #define LE_DCE110_REG_LIST(id)\ - LE_COMMON_REG_LIST_BASE(id), \ - SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ - SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ - SR(DCI_MEM_PWR_STATUS) +#define LE_COMMON_REG_LIST(id)\ + LE_COMMON_REG_LIST_BASE(id), \ + SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ + SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ + SR(DCI_MEM_PWR_STATUS) + +#define LE_DCE110_REG_LIST(id)\ + LE_COMMON_REG_LIST_BASE(id), \ + SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ + SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ + SR(DCI_MEM_PWR_STATUS) #define LE_DCE80_REG_LIST(id)\ SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ diff --git a/drivers/gpu/drm/amd/display/dc/dm_services.h b/drivers/gpu/drm/amd/display/dc/dm_services.h index 052a43af1bd3..73c0f1f83999 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services.h @@ -103,7 +103,7 @@ static inline uint32_t dm_read_reg_func( uint32_t value; if (address == 0) { - DC_ERR("invalid register read. address = 0"); + DC_ERR("invalid register read; address = 0\n"); return 0; } -- cgit From ab8812a3861efd3d60a4079711f2d1b08b8af50e Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Wed, 8 Feb 2017 11:28:33 -0500 Subject: drm/amd/display: Audio is not switching to DP when HDMI/DP hot plug/unplug Signed-off-by: Hersen Wu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 100 +++++++++++++++------ 1 file changed, 75 insertions(+), 25 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 5e99f6c27c9a..6a5cec0d4e1f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1732,7 +1732,6 @@ enum dc_status dce110_apply_ctx_to_hw( struct dc_bios *dcb = dc->ctx->dc_bios; enum dc_status status; int i; - bool programmed_audio_dto = false; enum dm_pp_clocks_state clocks_state = DM_PP_CLOCKS_STATE_INVALID; /* Reset old context */ @@ -1782,6 +1781,80 @@ enum dc_status dce110_apply_ctx_to_hw( context->res_ctx.pool->display_clock, context->dispclk_khz * 115 / 100); + /* program audio wall clock. use HDMI as clock source if HDMI + * audio active. Otherwise, use DP as clock source + * first, loop to find any HDMI audio, if not, loop find DP audio + */ + /* Setup audio rate clock source */ + /* Issue: + * Audio lag happened on DP monitor when unplug a HDMI monitor + * + * Cause: + * In case of DP and HDMI connected or HDMI only, DCCG_AUDIO_DTO_SEL + * is set to either dto0 or dto1, audio should work fine. + * In case of DP connected only, DCCG_AUDIO_DTO_SEL should be dto1, + * set to dto0 will cause audio lag. + * + * Solution: + * Not optimized audio wall dto setup. When mode set, iterate pipe_ctx, + * find first available pipe with audio, setup audio wall DTO per topology + * instead of per pipe. + */ + for (i = 0; i < context->res_ctx.pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + + if (pipe_ctx->stream == NULL) + continue; + + if (pipe_ctx->top_pipe) + continue; + + if (pipe_ctx->stream->signal != SIGNAL_TYPE_HDMI_TYPE_A) + continue; + + if (pipe_ctx->audio != NULL) { + struct audio_output audio_output; + + build_audio_output(pipe_ctx, &audio_output); + + pipe_ctx->audio->funcs->wall_dto_setup( + pipe_ctx->audio, + pipe_ctx->stream->signal, + &audio_output.crtc_info, + &audio_output.pll_info); + break; + } + } + + /* no HDMI audio is found, try DP audio */ + if (i == context->res_ctx.pool->pipe_count) { + for (i = 0; i < context->res_ctx.pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + + if (pipe_ctx->stream == NULL) + continue; + + if (pipe_ctx->top_pipe) + continue; + + if (!dc_is_dp_signal(pipe_ctx->stream->signal)) + continue; + + if (pipe_ctx->audio != NULL) { + struct audio_output audio_output; + + build_audio_output(pipe_ctx, &audio_output); + + pipe_ctx->audio->funcs->wall_dto_setup( + pipe_ctx->audio, + pipe_ctx->stream->signal, + &audio_output.crtc_info, + &audio_output.pll_info); + break; + } + } + } + for (i = 0; i < context->res_ctx.pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx_old = &dc->current_context->res_ctx.pipe_ctx[i]; @@ -1797,21 +1870,7 @@ enum dc_status dce110_apply_ctx_to_hw( continue; if (context->res_ctx.pipe_ctx[i].audio != NULL) { - /* Setup audio rate clock source */ - /* Issue: - * Audio lag happened on DP monitor when unplug a HDMI monitor - * - * Cause: - * In case of DP and HDMI connected or HDMI only, DCCG_AUDIO_DTO_SEL - * is set to either dto0 or dto1, audio should work fine. - * In case of DP connected only, DCCG_AUDIO_DTO_SEL should be dto1, - * set to dto0 will cause audio lag. - * - * Solution: - * Not optimized audio wall dto setup. When mode set, iterate pipe_ctx, - * find first available pipe with audio, setup audio wall DTO per topology - * instead of per pipe. - */ + struct audio_output audio_output; build_audio_output(pipe_ctx, &audio_output); @@ -1833,15 +1892,6 @@ enum dc_status dce110_apply_ctx_to_hw( pipe_ctx->stream->signal, &audio_output.crtc_info, &pipe_ctx->stream->public.audio_info); - - if (!programmed_audio_dto) { - pipe_ctx->audio->funcs->wall_dto_setup( - pipe_ctx->audio, - pipe_ctx->stream->signal, - &audio_output.crtc_info, - &audio_output.pll_info); - programmed_audio_dto = true; - } } status = apply_single_controller_ctx_to_hw( -- cgit From 67c3bd40b3b97cac40e01aaef712ccf4af5a48b1 Mon Sep 17 00:00:00 2001 From: Reza Amini Date: Fri, 3 Feb 2017 14:19:41 -0500 Subject: drm/amd/display: handle unsupported sink types Signed-off-by: Reza Amini Reviewed-by: Wesley Chalmers Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_sink.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_sink.c b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c index 9dff0bfd5b23..0a805ea1159a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_sink.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c @@ -53,6 +53,10 @@ static bool construct(struct sink *sink, const struct dc_sink_init_data *init_pa struct core_link *core_link = DC_LINK_TO_LINK(init_params->link); + if (!core_link) { + return false; + } + sink->protected.public.sink_signal = init_params->sink_signal; sink->protected.link = core_link; sink->protected.ctx = core_link->ctx; -- cgit From e266fdf6944749e100b065b5a95c7bb33d2aa2d6 Mon Sep 17 00:00:00 2001 From: Vitaly Prosyak Date: Tue, 7 Feb 2017 10:41:37 -0600 Subject: drm/amd/display: Enable regamma 25 segments and use double buffer. Moved custom floating point calculation to the shared place between dce's. Signed-off-by: Vitaly Prosyak Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/Makefile | 2 +- .../gpu/drm/amd/display/dc/calcs/custom_float.c | 197 +++++++++++++++++++++ .../amd/display/dc/dce110/dce110_hw_sequencer.c | 171 +----------------- .../amd/display/dc/dce110/dce110_hw_sequencer.h | 3 - drivers/gpu/drm/amd/display/dc/inc/custom_float.h | 40 +++++ 5 files changed, 240 insertions(+), 173 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/dc/calcs/custom_float.c create mode 100644 drivers/gpu/drm/amd/display/dc/inc/custom_float.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/Makefile b/drivers/gpu/drm/amd/display/dc/calcs/Makefile index 4bb08aea6a03..2f4c8e771b8f 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/Makefile +++ b/drivers/gpu/drm/amd/display/dc/calcs/Makefile @@ -3,7 +3,7 @@ # It calculates Bandwidth and Watermarks values for HW programming # -BW_CALCS = bandwidth_calcs.o bw_fixed.o +BW_CALCS = bandwidth_calcs.o bw_fixed.o custom_float.o AMD_DAL_BW_CALCS = $(addprefix $(AMDDALPATH)/dc/calcs/,$(BW_CALCS)) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/custom_float.c b/drivers/gpu/drm/amd/display/dc/calcs/custom_float.c new file mode 100644 index 000000000000..7243c37f569e --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/calcs/custom_float.c @@ -0,0 +1,197 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#include "dm_services.h" +#include "custom_float.h" + + +static bool build_custom_float( + struct fixed31_32 value, + const struct custom_float_format *format, + bool *negative, + uint32_t *mantissa, + uint32_t *exponenta) +{ + uint32_t exp_offset = (1 << (format->exponenta_bits - 1)) - 1; + + const struct fixed31_32 mantissa_constant_plus_max_fraction = + dal_fixed31_32_from_fraction( + (1LL << (format->mantissa_bits + 1)) - 1, + 1LL << format->mantissa_bits); + + struct fixed31_32 mantiss; + + if (dal_fixed31_32_eq( + value, + dal_fixed31_32_zero)) { + *negative = false; + *mantissa = 0; + *exponenta = 0; + return true; + } + + if (dal_fixed31_32_lt( + value, + dal_fixed31_32_zero)) { + *negative = format->sign; + value = dal_fixed31_32_neg(value); + } else { + *negative = false; + } + + if (dal_fixed31_32_lt( + value, + dal_fixed31_32_one)) { + uint32_t i = 1; + + do { + value = dal_fixed31_32_shl(value, 1); + ++i; + } while (dal_fixed31_32_lt( + value, + dal_fixed31_32_one)); + + --i; + + if (exp_offset <= i) { + *mantissa = 0; + *exponenta = 0; + return true; + } + + *exponenta = exp_offset - i; + } else if (dal_fixed31_32_le( + mantissa_constant_plus_max_fraction, + value)) { + uint32_t i = 1; + + do { + value = dal_fixed31_32_shr(value, 1); + ++i; + } while (dal_fixed31_32_lt( + mantissa_constant_plus_max_fraction, + value)); + + *exponenta = exp_offset + i - 1; + } else { + *exponenta = exp_offset; + } + + mantiss = dal_fixed31_32_sub( + value, + dal_fixed31_32_one); + + if (dal_fixed31_32_lt( + mantiss, + dal_fixed31_32_zero) || + dal_fixed31_32_lt( + dal_fixed31_32_one, + mantiss)) + mantiss = dal_fixed31_32_zero; + else + mantiss = dal_fixed31_32_shl( + mantiss, + format->mantissa_bits); + + *mantissa = dal_fixed31_32_floor(mantiss); + + return true; +} + +static bool setup_custom_float( + const struct custom_float_format *format, + bool negative, + uint32_t mantissa, + uint32_t exponenta, + uint32_t *result) +{ + uint32_t i = 0; + uint32_t j = 0; + + uint32_t value = 0; + + /* verification code: + * once calculation is ok we can remove it + */ + + const uint32_t mantissa_mask = + (1 << (format->mantissa_bits + 1)) - 1; + + const uint32_t exponenta_mask = + (1 << (format->exponenta_bits + 1)) - 1; + + if (mantissa & ~mantissa_mask) { + BREAK_TO_DEBUGGER(); + mantissa = mantissa_mask; + } + + if (exponenta & ~exponenta_mask) { + BREAK_TO_DEBUGGER(); + exponenta = exponenta_mask; + } + + /* end of verification code */ + + while (i < format->mantissa_bits) { + uint32_t mask = 1 << i; + + if (mantissa & mask) + value |= mask; + + ++i; + } + + while (j < format->exponenta_bits) { + uint32_t mask = 1 << j; + + if (exponenta & mask) + value |= mask << i; + + ++j; + } + + if (negative && format->sign) + value |= 1 << (i + j); + + *result = value; + + return true; +} + +bool convert_to_custom_float_format( + struct fixed31_32 value, + const struct custom_float_format *format, + uint32_t *result) +{ + uint32_t mantissa; + uint32_t exponenta; + bool negative; + + return build_custom_float( + value, format, &negative, &mantissa, &exponenta) && + setup_custom_float( + format, negative, mantissa, exponenta, result); +} + + diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 6a5cec0d4e1f..88a2fa99f5da 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -49,6 +49,7 @@ /* include DCE11 register header files */ #include "dce/dce_11_0_d.h" #include "dce/dce_11_0_sh_mask.h" +#include "custom_float.h" struct dce110_hw_seq_reg_offsets { uint32_t crtc; @@ -286,174 +287,6 @@ static bool dce110_set_input_transfer_func( return result; } -static bool build_custom_float( - struct fixed31_32 value, - const struct custom_float_format *format, - bool *negative, - uint32_t *mantissa, - uint32_t *exponenta) -{ - uint32_t exp_offset = (1 << (format->exponenta_bits - 1)) - 1; - - const struct fixed31_32 mantissa_constant_plus_max_fraction = - dal_fixed31_32_from_fraction( - (1LL << (format->mantissa_bits + 1)) - 1, - 1LL << format->mantissa_bits); - - struct fixed31_32 mantiss; - - if (dal_fixed31_32_eq( - value, - dal_fixed31_32_zero)) { - *negative = false; - *mantissa = 0; - *exponenta = 0; - return true; - } - - if (dal_fixed31_32_lt( - value, - dal_fixed31_32_zero)) { - *negative = format->sign; - value = dal_fixed31_32_neg(value); - } else { - *negative = false; - } - - if (dal_fixed31_32_lt( - value, - dal_fixed31_32_one)) { - uint32_t i = 1; - - do { - value = dal_fixed31_32_shl(value, 1); - ++i; - } while (dal_fixed31_32_lt( - value, - dal_fixed31_32_one)); - - --i; - - if (exp_offset <= i) { - *mantissa = 0; - *exponenta = 0; - return true; - } - - *exponenta = exp_offset - i; - } else if (dal_fixed31_32_le( - mantissa_constant_plus_max_fraction, - value)) { - uint32_t i = 1; - - do { - value = dal_fixed31_32_shr(value, 1); - ++i; - } while (dal_fixed31_32_lt( - mantissa_constant_plus_max_fraction, - value)); - - *exponenta = exp_offset + i - 1; - } else { - *exponenta = exp_offset; - } - - mantiss = dal_fixed31_32_sub( - value, - dal_fixed31_32_one); - - if (dal_fixed31_32_lt( - mantiss, - dal_fixed31_32_zero) || - dal_fixed31_32_lt( - dal_fixed31_32_one, - mantiss)) - mantiss = dal_fixed31_32_zero; - else - mantiss = dal_fixed31_32_shl( - mantiss, - format->mantissa_bits); - - *mantissa = dal_fixed31_32_floor(mantiss); - - return true; -} - -static bool setup_custom_float( - const struct custom_float_format *format, - bool negative, - uint32_t mantissa, - uint32_t exponenta, - uint32_t *result) -{ - uint32_t i = 0; - uint32_t j = 0; - - uint32_t value = 0; - - /* verification code: - * once calculation is ok we can remove it - */ - - const uint32_t mantissa_mask = - (1 << (format->mantissa_bits + 1)) - 1; - - const uint32_t exponenta_mask = - (1 << (format->exponenta_bits + 1)) - 1; - - if (mantissa & ~mantissa_mask) { - BREAK_TO_DEBUGGER(); - mantissa = mantissa_mask; - } - - if (exponenta & ~exponenta_mask) { - BREAK_TO_DEBUGGER(); - exponenta = exponenta_mask; - } - - /* end of verification code */ - - while (i < format->mantissa_bits) { - uint32_t mask = 1 << i; - - if (mantissa & mask) - value |= mask; - - ++i; - } - - while (j < format->exponenta_bits) { - uint32_t mask = 1 << j; - - if (exponenta & mask) - value |= mask << i; - - ++j; - } - - if (negative && format->sign) - value |= 1 << (i + j); - - *result = value; - - return true; -} - -static bool convert_to_custom_float_format( - struct fixed31_32 value, - const struct custom_float_format *format, - uint32_t *result) -{ - uint32_t mantissa; - uint32_t exponenta; - bool negative; - - return build_custom_float( - value, format, &negative, &mantissa, &exponenta) && - setup_custom_float( - format, negative, mantissa, exponenta, result); -} - static bool convert_to_custom_float( struct pwl_result_data *rgb_resulted, struct curve_points *arr_points, @@ -579,7 +412,7 @@ static bool convert_to_custom_float( return true; } -bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func +static bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func *output_tf, struct pwl_params *regamma_params) { struct curve_points *arr_points; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h index 68632dd28155..a6b4d0d2429f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h @@ -58,8 +58,5 @@ void dce110_power_down(struct core_dc *dc); void dce110_update_pending_status(struct pipe_ctx *pipe_ctx); -bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func - *output_tf, struct pwl_params *regamma_params); - #endif /* __DC_HWSS_DCE110_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/custom_float.h b/drivers/gpu/drm/amd/display/dc/inc/custom_float.h new file mode 100644 index 000000000000..f57239672216 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/custom_float.h @@ -0,0 +1,40 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef CUSTOM_FLOAT_H_ +#define CUSTOM_FLOAT_H_ + +#include "bw_fixed.h" +#include "hw_shared.h" +#include "opp.h" + + +bool convert_to_custom_float_format( + struct fixed31_32 value, + const struct custom_float_format *format, + uint32_t *result); + + +#endif //CUSTOM_FLOAT_H_ -- cgit From 8f16f28936afcf68b92625d331a8ca760a386139 Mon Sep 17 00:00:00 2001 From: Sylvia Tsai Date: Thu, 9 Feb 2017 16:35:39 -0500 Subject: drm/amd/display: Set ignore_msa_timing flag for freesync modes - Set ignore_msa_timing_param to 1 only for modes that can support freesync Signed-off-by: Sylvia Tsai Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/modules/freesync/freesync.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index 1ee732768f6e..b00b1df71f3e 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -262,7 +262,11 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, enable_for_video = false; } - if (caps->supported) + unsigned int nom_refresh_rate_micro_hz = (unsigned int) + (((unsigned long long) core_stream->public.timing.pix_clk_khz) * 1000ULL * 1000ULL * 1000ULL + / core_stream->public.timing.h_total / core_stream->public.timing.v_total); + + if (caps->supported && nom_refresh_rate_micro_hz >= caps->min_refresh_in_micro_hz && nom_refresh_rate_micro_hz <= caps->max_refresh_in_micro_hz) core_stream->public.ignore_msa_timing_param = 1; core_freesync->num_entities++; -- cgit From 27e947b0e13835cb782aa267b7d77e1f5a028e87 Mon Sep 17 00:00:00 2001 From: Zeyu Fan Date: Fri, 10 Feb 2017 11:59:31 -0500 Subject: drm/amd/display: Fix program pix clk logic to unblock deep color set. Signed-off-by: Zeyu Fan Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index a9f39218ce82..87eba4be3249 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -854,16 +854,16 @@ static bool dce110_program_pix_clk( if (clock_source->id != CLOCK_SOURCE_ID_EXTERNAL && pix_clk_params->flags.ENABLE_SS && !dc_is_dp_signal( pix_clk_params->signal_type)) { - if (!enable_spread_spectrum(clk_src, pix_clk_params->signal_type, pll_settings)) return false; - /* Resync deep color DTO */ - dce110_program_pixel_clk_resync(clk_src, - pix_clk_params->signal_type, - pix_clk_params->color_depth); } + /* Resync deep color DTO */ + dce110_program_pixel_clk_resync(clk_src, + pix_clk_params->signal_type, + pix_clk_params->color_depth); + break; case DCE_VERSION_11_2: if (clock_source->id != CLOCK_SOURCE_ID_DP_DTO) { -- cgit From a37656b99aca947967f32931bfd5ba04133154d8 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Wed, 8 Feb 2017 22:13:52 -0500 Subject: drm/amd/display: report cursor size base on the ASIC Signed-off-by: Tony Cheng Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 ++ drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c | 1 + drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c | 1 + drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c | 1 + drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c | 1 + 5 files changed, 6 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index d7f848495d8a..13e7134fccb8 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -47,6 +47,8 @@ struct dc_caps { uint32_t max_slave_planes; uint32_t max_downscale_ratio; uint32_t i2c_speed_in_khz; + + unsigned int max_cursor_size; }; diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 55501b381692..9ed7c06132fe 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -984,6 +984,7 @@ static bool construct( pool->base.pipe_count = res_cap.num_timing_generator; dc->public.caps.max_downscale_ratio = 200; dc->public.caps.i2c_speed_in_khz = 40; + dc->public.caps.max_cursor_size = 128; for (i = 0; i < pool->base.pipe_count; i++) { pool->base.timing_generators[i] = diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index ee4fda514de6..f6e546addbd3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -1274,6 +1274,7 @@ static bool construct( dc->public.caps.max_downscale_ratio = 150; dc->public.caps.i2c_speed_in_khz = 100; + dc->public.caps.max_cursor_size = 128; /************************************************* * Create resources * diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 54af84ebf2bc..526c106f6ebf 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -1256,6 +1256,7 @@ static bool construct( pool->base.pipe_count = pool->base.res_cap->num_timing_generator; dc->public.caps.max_downscale_ratio = 200; dc->public.caps.i2c_speed_in_khz = 100; + dc->public.caps.max_cursor_size = 128; /************************************************* * Create resources * diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 3de8bfb47dce..272c7fc31406 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -935,6 +935,7 @@ static bool construct( pool->base.pipe_count = res_cap.num_timing_generator; dc->public.caps.max_downscale_ratio = 200; dc->public.caps.i2c_speed_in_khz = 40; + dc->public.caps.max_cursor_size = 128; /************************************************* * Create resources * -- cgit From b3c64dff24e829c0b61b340fbaf0efaf20ce5d58 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Fri, 10 Feb 2017 17:51:27 -0500 Subject: drm/amd/display: color distortion after DPMS+ background color fix Signed-off-by: Charlene Liu Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 88a2fa99f5da..0afb3c64b651 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1054,6 +1054,8 @@ static enum dc_status apply_single_controller_ctx_to_hw( if (!pipe_ctx_old->stream) { core_link_enable_stream(pipe_ctx); + resource_build_info_frame(pipe_ctx); + dce110_update_info_frame(pipe_ctx); if (dc_is_dp_signal(pipe_ctx->stream->signal)) dce110_unblank_stream(pipe_ctx, &stream->sink->link->public.cur_link_settings); -- cgit From 77f36b27127630f326d6967318159e938a4137dd Mon Sep 17 00:00:00 2001 From: Zeyu Fan Date: Mon, 13 Feb 2017 11:49:07 -0500 Subject: drm/amd/display: Fix logic that causes segfault on DP display. Signed-off-by: Zeyu Fan Acked-by: Jordan Lazare Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dce/dce_clock_source.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index 87eba4be3249..26742e038274 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -852,17 +852,19 @@ static bool dce110_program_pix_clk( * during PLL Reset, but they do not have effect * until SS_EN is asserted.*/ if (clock_source->id != CLOCK_SOURCE_ID_EXTERNAL - && pix_clk_params->flags.ENABLE_SS && !dc_is_dp_signal( - pix_clk_params->signal_type)) { - if (!enable_spread_spectrum(clk_src, - pix_clk_params->signal_type, - pll_settings)) - return false; + && !dc_is_dp_signal(pix_clk_params->signal_type)) { + + if (pix_clk_params->flags.ENABLE_SS) + if (!enable_spread_spectrum(clk_src, + pix_clk_params->signal_type, + pll_settings)) + return false; + + /* Resync deep color DTO */ + dce110_program_pixel_clk_resync(clk_src, + pix_clk_params->signal_type, + pix_clk_params->color_depth); } - /* Resync deep color DTO */ - dce110_program_pixel_clk_resync(clk_src, - pix_clk_params->signal_type, - pix_clk_params->color_depth); break; case DCE_VERSION_11_2: -- cgit From 26ada804d62e5aedf16be8dfe2cb9bf4907815e5 Mon Sep 17 00:00:00 2001 From: Jordan Lazare Date: Tue, 14 Feb 2017 15:03:04 -0500 Subject: drm/amd/display: Fix missing fcn pointer on DCE8 Signed-off-by: Jordan Lazare Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c index e8fae0a7eeb4..eeccabd65a7a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c @@ -141,12 +141,14 @@ static const struct timing_generator_funcs dce80_tg_funcs = { .disable_reset_trigger = dce110_timing_generator_disable_reset_trigger, .tear_down_global_swap_lock = dce110_timing_generator_tear_down_global_swap_lock, + .set_drr = dce110_timing_generator_set_drr, + .set_static_screen_control = + dce110_timing_generator_set_static_screen_control, + .set_test_pattern = dce110_timing_generator_set_test_pattern, /* DCE8.0 overrides */ .enable_advanced_request = dce80_timing_generator_enable_advanced_request, - .set_drr = - dce110_timing_generator_set_drr, }; bool dce80_timing_generator_construct( -- cgit From 5866e7cf7d4f989cc17a781b8c4315345bc6de04 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Tue, 14 Feb 2017 07:13:04 +0100 Subject: drm/amd/dc: fix semicolon.cocci warnings Remove unneeded semicolons. Generated by: scripts/coccinelle/misc/semicolon.cocci Signed-off-by: Julia Lawall Signed-off-by: Fengguang Wu Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index fdb264c6e859..dc0d8533521f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -938,11 +938,11 @@ static void copy_crtc_timing_for_drm_display_mode( dst_mode->crtc_hsync_end = src_mode->crtc_hsync_end; dst_mode->crtc_htotal = src_mode->crtc_htotal; dst_mode->crtc_hskew = src_mode->crtc_hskew; - dst_mode->crtc_vblank_start = src_mode->crtc_vblank_start;; - dst_mode->crtc_vblank_end = src_mode->crtc_vblank_end;; - dst_mode->crtc_vsync_start = src_mode->crtc_vsync_start;; - dst_mode->crtc_vsync_end = src_mode->crtc_vsync_end;; - dst_mode->crtc_vtotal = src_mode->crtc_vtotal;; + dst_mode->crtc_vblank_start = src_mode->crtc_vblank_start; + dst_mode->crtc_vblank_end = src_mode->crtc_vblank_end; + dst_mode->crtc_vsync_start = src_mode->crtc_vsync_start; + dst_mode->crtc_vsync_end = src_mode->crtc_vsync_end; + dst_mode->crtc_vtotal = src_mode->crtc_vtotal; } static void decide_crtc_timing_for_drm_display_mode( -- cgit From 17a96033dae7e56cd48d1b3c952e0b4ca9384312 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Tue, 14 Feb 2017 07:14:58 +0100 Subject: drm/amd/dc: fix semicolon.cocci warnings Remove unneeded semicolon. Generated by: scripts/coccinelle/misc/semicolon.cocci Signed-off-by: Julia Lawall Signed-off-by: Fengguang Wu Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index e4e86110d45d..991828f503aa 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -135,7 +135,7 @@ static void update_num_audio( break; default: DC_ERR("DC: unexpected audio fuse!\n"); - }; + } } bool resource_construct( -- cgit From e166ad43d5c1312f258ef4adabe1fac2b9da7e18 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Tue, 14 Feb 2017 07:19:36 +0100 Subject: drm/amd/dc: hw_sequencer: fix semicolon.cocci warnings Remove unneeded semicolon. Generated by: scripts/coccinelle/misc/semicolon.cocci Signed-off-by: Julia Lawall Signed-off-by: Fengguang Wu Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 0afb3c64b651..9b6d251a1c22 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -2070,7 +2070,7 @@ static void init_hw(struct core_dc *dc) true); } - dce_clock_gating_power_up(dc->hwseq, false);; + dce_clock_gating_power_up(dc->hwseq, false); /***************************************/ for (i = 0; i < dc->link_count; i++) { -- cgit From 4a9054dda6df8e94b6a54a181277e25d189198c4 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 14 Feb 2017 14:51:06 -0500 Subject: drm/amd/display: Fix 64-bit division, yet again Also make the code somewhat more readable. Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/modules/freesync/freesync.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index b00b1df71f3e..2026ef34b11b 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -210,6 +210,8 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, struct core_freesync *core_freesync = NULL; int persistent_freesync_enable = 0; struct persistent_data_flag flag; + unsigned int nom_refresh_rate_micro_hz; + unsigned long long temp; if (mod_freesync == NULL) return false; @@ -262,11 +264,16 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, enable_for_video = false; } - unsigned int nom_refresh_rate_micro_hz = (unsigned int) - (((unsigned long long) core_stream->public.timing.pix_clk_khz) * 1000ULL * 1000ULL * 1000ULL - / core_stream->public.timing.h_total / core_stream->public.timing.v_total); + temp = core_stream->public.timing.pix_clk_khz; + temp *= 1000ULL * 1000ULL * 1000ULL; + temp = div_u64(temp, core_stream->public.timing.h_total); + temp = div_u64(temp, core_stream->public.timing.v_total); - if (caps->supported && nom_refresh_rate_micro_hz >= caps->min_refresh_in_micro_hz && nom_refresh_rate_micro_hz <= caps->max_refresh_in_micro_hz) + nom_refresh_rate_micro_hz = (unsigned int) temp; + + if (caps->supported && + nom_refresh_rate_micro_hz >= caps->min_refresh_in_micro_hz && + nom_refresh_rate_micro_hz <= caps->max_refresh_in_micro_hz) core_stream->public.ignore_msa_timing_param = 1; core_freesync->num_entities++; -- cgit From beed42b5bc68e9c37c4474393a2e3dbf6ed4c26b Mon Sep 17 00:00:00 2001 From: Jordan Lazare Date: Tue, 14 Feb 2017 18:20:35 -0500 Subject: drm/amd/display: Don't attempt to program missing register fields on DCE8 When moving to a common dce/ infrastructure for all asics, some register fields do not exist in DCE8, and cause ASSERTS and debug spam. Instead, check to see whether a register field mask is valid before attempting to program the register field Signed-off-by: Jordan Lazare Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c | 29 ++++++++++++++-------- drivers/gpu/drm/amd/display/dc/dce/dce_transform.c | 12 ++++++--- 2 files changed, 28 insertions(+), 13 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c index 0eee135bfa54..8eb755620c48 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c @@ -69,17 +69,22 @@ void dce_pipe_control_lock(struct dce_hwseq *hws, if (control_mask & PIPE_LOCK_CONTROL_MODE) update_lock_mode = lock_val; - REG_SET_4(BLND_V_UPDATE_LOCK[blnd_inst], val, + + REG_SET_2(BLND_V_UPDATE_LOCK[blnd_inst], val, BLND_DCP_GRPH_V_UPDATE_LOCK, dcp_grph, - BLND_SCL_V_UPDATE_LOCK, scl, - BLND_BLND_V_UPDATE_LOCK, blnd, - BLND_V_UPDATE_LOCK_MODE, update_lock_mode); + BLND_SCL_V_UPDATE_LOCK, scl); + + if (hws->masks->BLND_BLND_V_UPDATE_LOCK != 0) + REG_SET_2(BLND_V_UPDATE_LOCK[blnd_inst], val, + BLND_BLND_V_UPDATE_LOCK, blnd, + BLND_V_UPDATE_LOCK_MODE, update_lock_mode); - if (hws->wa.blnd_crtc_trigger) + if (hws->wa.blnd_crtc_trigger) { if (!lock && (control_mask & PIPE_LOCK_CONTROL_BLENDER)) { uint32_t value = REG_READ(CRTC_H_BLANK_START_END[blnd_inst]); REG_WRITE(CRTC_H_BLANK_START_END[blnd_inst], value); } + } } void dce_set_blender_mode(struct dce_hwseq *hws, @@ -111,11 +116,15 @@ void dce_set_blender_mode(struct dce_hwseq *hws, break; } - REG_UPDATE_4(BLND_CONTROL[blnd_inst], - BLND_FEEDTHROUGH_EN, feedthrough, - BLND_ALPHA_MODE, alpha_mode, - BLND_MODE, blnd_mode, - BLND_MULTIPLIED_MODE, multiplied_mode); + REG_UPDATE(BLND_CONTROL[blnd_inst], + BLND_MODE, blnd_mode); + + if (hws->masks->BLND_ALPHA_MODE != 0) { + REG_UPDATE_3(BLND_CONTROL[blnd_inst], + BLND_FEEDTHROUGH_EN, feedthrough, + BLND_ALPHA_MODE, alpha_mode, + BLND_MULTIPLIED_MODE, multiplied_mode); + } } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c index 50a6a25561b4..d8ffbff9a268 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c @@ -87,7 +87,10 @@ static bool setup_scaling_configuration( if (data->taps.h_taps + data->taps.v_taps <= 2) { /* Set bypass */ - REG_UPDATE_2(SCL_MODE, SCL_MODE, 0, SCL_PSCL_EN, 0); + if (xfm_dce->xfm_mask->SCL_PSCL_EN != 0) + REG_UPDATE_2(SCL_MODE, SCL_MODE, 0, SCL_PSCL_EN, 0); + else + REG_UPDATE(SCL_MODE, SCL_MODE, 0); return false; } @@ -96,9 +99,12 @@ static bool setup_scaling_configuration( SCL_V_NUM_OF_TAPS, data->taps.v_taps - 1); if (data->format <= PIXEL_FORMAT_GRPH_END) - REG_UPDATE_2(SCL_MODE, SCL_MODE, 1, SCL_PSCL_EN, 1); + REG_UPDATE(SCL_MODE, SCL_MODE, 1); else - REG_UPDATE_2(SCL_MODE, SCL_MODE, 2, SCL_PSCL_EN, 1); + REG_UPDATE(SCL_MODE, SCL_MODE, 2); + + if (xfm_dce->xfm_mask->SCL_PSCL_EN != 0) + REG_UPDATE(SCL_MODE, SCL_PSCL_EN, 1); /* 1 - Replace out of bound pixels with edge */ REG_SET(SCL_CONTROL, 0, SCL_BOUNDARY_MODE, 1); -- cgit From 7d4e9bf9835ad081fb5967336cace7f5aa8ffd6d Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 21 Feb 2017 17:09:34 -0500 Subject: drm/amd/display: Remove LINUX_VERSION_CODE check Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/gpu') 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 0c50433d6ba3..d0706e550e84 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -886,14 +886,12 @@ static void dm_handle_hpd_rx_irq(struct amdgpu_connector *aconnector) process_count++; DRM_DEBUG_KMS("ESI %02x %02x %02x\n", esi[0], esi[1], esi[2]); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 3, 0) /* handle HPD short pulse irq */ if (aconnector->mst_mgr.mst_state) drm_dp_mst_hpd_irq( &aconnector->mst_mgr, esi, &new_irq_handled); -#endif if (new_irq_handled) { /* ACK at DPCD to notify down stream */ -- cgit From 5c1879b6b93898d65e05dfb47f947fa4f5a904a4 Mon Sep 17 00:00:00 2001 From: Ken Chalmers Date: Mon, 13 Feb 2017 11:07:33 -0500 Subject: drm/amd/display: fix dc_commit_surfaces_to_stream for dcc Signed-off-by: Ken Chalmers Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 4c405f4b880e..84412e752017 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1246,6 +1246,7 @@ bool dc_commit_surfaces_to_stream( plane_info[i].stereo_format = new_surfaces[i]->stereo_format; plane_info[i].tiling_info = new_surfaces[i]->tiling_info; plane_info[i].visible = new_surfaces[i]->visible; + plane_info[i].dcc = new_surfaces[i]->dcc; scaling_info[i].scaling_quality = new_surfaces[i]->scaling_quality; scaling_info[i].src_rect = new_surfaces[i]->src_rect; scaling_info[i].dst_rect = new_surfaces[i]->dst_rect; -- cgit From 70063a5957126087f167ff3890784d7b3b36c844 Mon Sep 17 00:00:00 2001 From: Amy Zhang Date: Thu, 16 Feb 2017 11:04:48 -0500 Subject: drm/amd/display: Add bypass case for PQ transfer function - Source and destination color space should be the same for app control case - Bypass degamma, regamma, and gamut remap - Add hdr supported check for info frame Signed-off-by: Amy Zhang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/dc.h | 2 ++ drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 5 ++++- 3 files changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 991828f503aa..4d556b379524 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1675,7 +1675,7 @@ static void set_hdr_static_info_packet( hdr_metadata = surface->public.hdr_static_ctx; - if (!hdr_metadata.is_hdr) + if (!hdr_metadata.hdr_supported) return; if (dc_is_hdmi_signal(signal)) { diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 13e7134fccb8..71d7dde79ae0 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -186,6 +186,7 @@ enum { }; struct dc_hdr_static_metadata { + bool hdr_supported; bool is_hdr; /* display chromaticities and white point in units of 0.00001 */ @@ -207,6 +208,7 @@ struct dc_hdr_static_metadata { enum dc_transfer_func_type { TF_TYPE_PREDEFINED, TF_TYPE_DISTRIBUTED_POINTS, + TF_TYPE_BYPASS }; struct dc_transfer_func_distributed_points { diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 9b6d251a1c22..9c9183f96e04 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -279,6 +279,8 @@ static bool dce110_set_input_transfer_func( result = false; break; } + } else if (tf->public.type == TF_TYPE_BYPASS) { + ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS); } else { /*TF_TYPE_DISTRIBUTED_POINTS - Not supported in DCE 11*/ result = false; @@ -428,7 +430,8 @@ static bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func int32_t segment_start, segment_end; uint32_t i, j, k, seg_distr[16], increment, start_index, hw_points; - if (output_tf == NULL || regamma_params == NULL) + if (output_tf == NULL || regamma_params == NULL || + output_tf->type == TF_TYPE_BYPASS) return false; arr_points = regamma_params->arr_points; -- cgit From 2b230ea3e76f6238b31fd270cab76d55394f3293 Mon Sep 17 00:00:00 2001 From: Zeyu Fan Date: Thu, 16 Feb 2017 16:15:30 -0500 Subject: drm/amd/display: Add query_ddc_data function Signed-off-by: Zeyu Fan Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 25 +++++++++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dc.h | 11 ++++++++++- 2 files changed, 35 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 84412e752017..6516c275e0c7 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1725,6 +1725,31 @@ bool dc_read_dpcd( return r == DDC_RESULT_SUCESSFULL; } +bool dc_query_ddc_data( + struct dc *dc, + uint32_t link_index, + uint32_t address, + uint8_t *write_buf, + uint32_t write_size, + uint8_t *read_buf, + uint32_t read_size) { + + struct core_dc *core_dc = DC_TO_CORE(dc); + + struct core_link *link = core_dc->links[link_index]; + + bool result = dal_ddc_service_query_ddc_data( + link->ddc, + address, + write_buf, + write_size, + read_buf, + read_size); + + return result; +} + + bool dc_write_dpcd( struct dc *dc, uint32_t link_index, diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 71d7dde79ae0..2d84b18f48b0 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -720,7 +720,16 @@ bool dc_write_dpcd( uint32_t link_index, uint32_t address, const uint8_t *data, - uint32_t size); + uint32_t size); + +bool dc_query_ddc_data( + struct dc *dc, + uint32_t link_index, + uint32_t address, + uint8_t *write_buf, + uint32_t write_size, + uint8_t *read_buf, + uint32_t read_size); bool dc_submit_i2c( struct dc *dc, -- cgit From 185189dc51a5c968ce35b0e1f2b529736e789c9c Mon Sep 17 00:00:00 2001 From: Zeyu Fan Date: Thu, 16 Feb 2017 18:34:50 -0500 Subject: drm/amd/display: Fix error where wrong payload size is given. Signed-off-by: Zeyu Fan Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c index cd66941b2c59..4e9465b630d1 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c @@ -198,7 +198,7 @@ struct aux_payloads *dal_ddc_aux_payloads_create(struct dc_context *ctx, uint32_ return NULL; if (dal_vector_construct( - &payloads->payloads, ctx, count, sizeof(struct aux_payloads))) + &payloads->payloads, ctx, count, sizeof(struct aux_payload))) return payloads; dm_free(payloads); -- cgit From 87b58768eccd311fdc7694c09966754d5ce90538 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Thu, 16 Feb 2017 22:28:46 -0500 Subject: drm/amd/display: audio bug fix part 1: Add missing audio ACR Signed-off-by: Charlene Liu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_audio.c | 8 +-- drivers/gpu/drm/amd/display/dc/dce/dce_audio.h | 2 + .../gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 2 + .../drm/amd/display/dc/dce/dce_stream_encoder.c | 81 +++++++++++++++------- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 31 +++++++++ .../drm/amd/display/dc/dce110/dce110_resource.c | 1 + 6 files changed, 95 insertions(+), 30 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c index 2749c8fa4f1f..596e039ee315 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c @@ -828,11 +828,9 @@ void dce_aud_wall_dto_setup( REG_UPDATE(DCCG_AUDIO_DTO1_PHASE, DCCG_AUDIO_DTO1_PHASE, clock_info.audio_dto_phase); - /* DAL2 code separate DCCG_AUDIO_DTO_SEL and - DCCG_AUDIO_DTO2_USE_512FBR_DTO programming into two different - location. merge together should not hurt */ - /*value.bits.DCCG_AUDIO_DTO2_USE_512FBR_DTO = 1; - dal_write_reg(mmDCCG_AUDIO_DTO_SOURCE, value);*/ + REG_UPDATE(DCCG_AUDIO_DTO_SOURCE, + DCCG_AUDIO_DTO2_USE_512FBR_DTO, 1); + } } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.h b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.h index c244887ba15e..b98ee2d2a9c7 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.h @@ -93,6 +93,7 @@ struct dce_audio_shift { uint8_t DCCG_AUDIO_DTO0_PHASE; uint8_t DCCG_AUDIO_DTO1_MODULE; uint8_t DCCG_AUDIO_DTO1_PHASE; + uint8_t DCCG_AUDIO_DTO2_USE_512FBR_DTO; }; struct dce_aduio_mask { @@ -109,6 +110,7 @@ struct dce_aduio_mask { uint32_t DCCG_AUDIO_DTO0_PHASE; uint32_t DCCG_AUDIO_DTO1_MODULE; uint32_t DCCG_AUDIO_DTO1_PHASE; + uint32_t DCCG_AUDIO_DTO2_USE_512FBR_DTO; }; struct dce_audio { diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 60fdf58fc5cc..305a9d86a5d2 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -871,6 +871,8 @@ static bool dce110_link_encoder_validate_hdmi_output( if (max_deep_color < crtc_timing->display_color_depth) return false; + if (crtc_timing->display_color_depth < COLOR_DEPTH_888) + return false; if (adjusted_pix_clk_khz < TMDS_MIN_PIXEL_CLOCK) return false; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c index a28d9c7ba17e..aba392ff5095 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c @@ -848,7 +848,7 @@ struct audio_clock_info { /* 148.5MHz/1.001*/ /* 148.5MHz*/ -static const struct audio_clock_info audio_clock_info_table[12] = { +static const struct audio_clock_info audio_clock_info_table[16] = { {2517, 4576, 28125, 7007, 31250, 6864, 28125}, {2518, 4576, 28125, 7007, 31250, 6864, 28125}, {2520, 4096, 25200, 6272, 28000, 6144, 25200}, @@ -860,37 +860,63 @@ static const struct audio_clock_info audio_clock_info_table[12] = { {7417, 11648, 210937, 17836, 234375, 11648, 140625}, {7425, 4096, 74250, 6272, 82500, 6144, 74250}, {14835, 11648, 421875, 8918, 234375, 5824, 140625}, - {14850, 4096, 148500, 6272, 165000, 6144, 148500} + {14850, 4096, 148500, 6272, 165000, 6144, 148500}, + {29670, 5824, 421875, 4459, 234375, 5824, 281250}, + {29700, 3072, 222750, 4704, 247500, 5120, 247500}, + {59340, 5824, 843750, 8918, 937500, 5824, 562500}, + {59400, 3072, 445500, 9408, 990000, 6144, 594000} }; -static const struct audio_clock_info audio_clock_info_table_36bpc[12] = { - {2517, 9152, 84375, 7007, 48875, 9152, 56250}, - {2518, 9152, 84375, 7007, 48875, 9152, 56250}, - {2520, 4096, 37800, 6272, 42000, 6144, 37800}, - {2700, 4096, 40500, 6272, 45000, 6144, 40500}, - {2702, 8192, 81081, 6272, 45045, 8192, 54054}, - {2703, 8192, 81081, 6272, 45045, 8192, 54054}, - {5400, 4096, 81000, 6272, 90000, 6144, 81000}, - {5405, 4096, 81081, 6272, 90090, 6144, 81081}, +static const struct audio_clock_info audio_clock_info_table_30bpc[14] = { + {2517, 9152, 70312, 14014, 78125, 9152, 46875}, + {2518, 9152, 70312, 14014, 78125, 9152, 46875}, + {2520, 4096, 31500, 6272, 35000, 6144, 31500}, + {2700, 4096, 33750, 6272, 37500, 6144, 33750}, + {2702, 8192, 67567, 12544, 75075, 8192, 45045}, + {2703, 8192, 67567, 12544, 75075, 8192, 45045}, + {5400, 4096, 67500, 6272, 75000, 6144, 67500}, + {5405, 8192, 135135, 6272, 75075, 8192, 90090}, + {7417, 11648, 263672, 17836, 292969, 11648, 175181}, + {7425, 8192, 185625, 6272, 103125, 12288, 185625}, + {14835, 11648, 527344, 17836, 585938, 11648, 351563}, + {14850, 4096, 185625, 6272, 206250, 6144, 185625}, + {29670, 11648, 527344, 17836, 585938, 11648, 703125}, + {29700, 6144, 556875, 4704, 309375, 5120, 309375} +}; +static const struct audio_clock_info audio_clock_info_table_36bpc[14] = { + {2517, 9152, 84375, 7007, 48875, 9152, 56250}, + {2518, 9152, 84375, 7007, 48875, 9152, 56250}, + {2520, 4096, 37800, 6272, 42000, 6144, 37800}, + {2700, 4096, 40500, 6272, 45000, 6144, 40500}, + {2702, 8192, 81081, 6272, 45045, 8192, 54054}, + {2703, 8192, 81081, 6272, 45045, 8192, 54054}, + {5400, 4096, 81000, 6272, 90000, 6144, 81000}, + {5405, 4096, 81081, 6272, 90090, 6144, 81081}, {7417, 11648, 316406, 17836, 351562, 11648, 210937}, - {7425, 4096, 111375, 6272, 123750, 6144, 111375}, + {7425, 4096, 111375, 6272, 123750, 6144, 111375}, {14835, 11648, 632812, 17836, 703125, 11648, 421875}, - {14850, 4096, 222750, 6272, 247500, 6144, 222750} + {14850, 4096, 222750, 6272, 247500, 6144, 222750}, + {29670, 5824, 632812, 8918, 703125, 5824, 421875}, + {29700, 4096, 445500, 4704, 371250, 5120, 371250} }; -static const struct audio_clock_info audio_clock_info_table_48bpc[12] = { - {2517, 4576, 56250, 7007, 62500, 6864, 56250}, - {2518, 4576, 56250, 7007, 62500, 6864, 56250}, - {2520, 4096, 50400, 6272, 56000, 6144, 50400}, - {2700, 4096, 54000, 6272, 60000, 6144, 54000}, - {2702, 4096, 54054, 6267, 60060, 8192, 54054}, - {2703, 4096, 54054, 6272, 60060, 8192, 54054}, - {5400, 4096, 108000, 6272, 120000, 6144, 108000}, - {5405, 4096, 108108, 6272, 120120, 6144, 108108}, +static const struct audio_clock_info audio_clock_info_table_48bpc[14] = { + {2517, 4576, 56250, 7007, 62500, 6864, 56250}, + {2518, 4576, 56250, 7007, 62500, 6864, 56250}, + {2520, 4096, 50400, 6272, 56000, 6144, 50400}, + {2700, 4096, 54000, 6272, 60000, 6144, 54000}, + {2702, 4096, 54054, 6267, 60060, 8192, 54054}, + {2703, 4096, 54054, 6272, 60060, 8192, 54054}, + {5400, 4096, 108000, 6272, 120000, 6144, 108000}, + {5405, 4096, 108108, 6272, 120120, 6144, 108108}, {7417, 11648, 421875, 17836, 468750, 11648, 281250}, - {7425, 4096, 148500, 6272, 165000, 6144, 148500}, - {14835, 11648, 843750, 8918, 468750, 11648, 281250}, - {14850, 4096, 297000, 6272, 330000, 6144, 297000} + {7425, 4096, 148500, 6272, 165000, 6144, 148500}, + {14835, 11648, 843750, 8918, 468750, 11648, 281250}, + {14850, 4096, 297000, 6272, 330000, 6144, 297000}, + {29670, 5824, 843750, 4459, 468750, 5824, 562500}, + {29700, 3072, 445500, 4704, 495000, 5120, 495000} + + }; union audio_cea_channels speakers_to_channels( @@ -973,6 +999,11 @@ bool get_audio_clock_info( audio_array_size = ARRAY_SIZE( audio_clock_info_table_36bpc); break; + case COLOR_DEPTH_101010: + clock_info = audio_clock_info_table_30bpc; + audio_array_size = ARRAY_SIZE( + audio_clock_info_table_30bpc); + break; default: clock_info = audio_clock_info_table; audio_array_size = ARRAY_SIZE( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 9c9183f96e04..76a397d90adc 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -868,6 +868,37 @@ static void build_audio_output( audio_output->crtc_info.calculated_pixel_clock = pipe_ctx->pix_clk_params.requested_pix_clk; +/*for HDMI, audio ACR is with deep color ratio factor*/ + if (dc_is_hdmi_signal(pipe_ctx->stream->signal) && + audio_output->crtc_info.requested_pixel_clock == + stream->public.timing.pix_clk_khz) { + if (pipe_ctx->pix_clk_params.pixel_encoding == PIXEL_ENCODING_YCBCR420) { + audio_output->crtc_info.requested_pixel_clock = + audio_output->crtc_info.requested_pixel_clock/2; + audio_output->crtc_info.calculated_pixel_clock = + pipe_ctx->pix_clk_params.requested_pix_clk/2; + } + + if (pipe_ctx->pix_clk_params.pixel_encoding != PIXEL_ENCODING_YCBCR422) { + switch (pipe_ctx->pix_clk_params.color_depth) { + case COLOR_DEPTH_888: + break; + case COLOR_DEPTH_101010: + audio_output->crtc_info.calculated_pixel_clock = (audio_output->crtc_info.calculated_pixel_clock * 30) / 24; + break; + case COLOR_DEPTH_121212: + audio_output->crtc_info.calculated_pixel_clock = (audio_output->crtc_info.calculated_pixel_clock * 36) / 24; + break; + case COLOR_DEPTH_161616: + audio_output->crtc_info.calculated_pixel_clock = (audio_output->crtc_info.calculated_pixel_clock * 48) / 24; + break; + default: + ASSERT(0); + break; + } + } + } + if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT || pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { audio_output->pll_info.dp_dto_source_clock_in_khz = diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index f6e546addbd3..074fb978e076 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -776,6 +776,7 @@ static void get_pixel_clock_parameters( pixel_clk_params->flags.DISPLAY_BLANKED = 1; pixel_clk_params->flags.SUPPORT_YCBCR420 = (stream->public.timing.pixel_encoding == PIXEL_ENCODING_YCBCR420); + pixel_clk_params->pixel_encoding = stream->public.timing.pixel_encoding; } void dce110_resource_build_bit_depth_reduction_params( -- cgit From 896b3cb3f48e662abdaaaeb5a4e1001723081a19 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Fri, 17 Feb 2017 13:51:32 -0500 Subject: drm/amd/display: fix 12bpc truncate to 10bpc Signed-off-by: Charlene Liu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_opp.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c index a2f57cf603aa..121ccbb1ad2d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c @@ -710,32 +710,32 @@ void dce110_opp_set_dyn_expansion( enum signal_type signal) { struct dce110_opp *opp110 = TO_DCE110_OPP(opp); - bool enable_dyn_exp = false; REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN, 0, FMT_DYNAMIC_EXP_MODE, 0); - /* From HW programming guide: - FMT_DYNAMIC_EXP_EN = 0 for limited RGB or YCbCr output - FMT_DYNAMIC_EXP_EN = 1 for RGB full range only*/ - if (color_sp == COLOR_SPACE_SRGB) - enable_dyn_exp = true; /*00 - 10-bit -> 12-bit dynamic expansion*/ /*01 - 8-bit -> 12-bit dynamic expansion*/ - if (signal == SIGNAL_TYPE_HDMI_TYPE_A) { + if (signal == SIGNAL_TYPE_HDMI_TYPE_A || + signal == SIGNAL_TYPE_DISPLAY_PORT || + signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { switch (color_dpth) { case COLOR_DEPTH_888: REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL, - FMT_DYNAMIC_EXP_EN, enable_dyn_exp ? 1:0, + FMT_DYNAMIC_EXP_EN, 1, FMT_DYNAMIC_EXP_MODE, 1); break; case COLOR_DEPTH_101010: REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL, - FMT_DYNAMIC_EXP_EN, enable_dyn_exp ? 1:0, + FMT_DYNAMIC_EXP_EN, 1, FMT_DYNAMIC_EXP_MODE, 0); break; case COLOR_DEPTH_121212: + REG_UPDATE_2( + FMT_DYNAMIC_EXP_CNTL, + FMT_DYNAMIC_EXP_EN, 1,/*otherwise last two bits are zero*/ + FMT_DYNAMIC_EXP_MODE, 0); break; default: break; -- cgit From 181a888fcd723c4bc63f43aac50713c34ae9102e Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Fri, 17 Feb 2017 13:59:11 -0500 Subject: drm/amd/display: fix incorrect programming for YCbCr422 and YCbCr420 Signed-off-by: Charlene Liu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c | 12 +++++++++--- .../gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 17 +++++++++-------- drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c | 3 +++ 3 files changed, 21 insertions(+), 11 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c index aba392ff5095..e4092fd458a1 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c @@ -362,9 +362,15 @@ static void dce110_stream_encoder_hdmi_set_stream_attribute( REG_UPDATE(HDMI_CONTROL, HDMI_DEEP_COLOR_DEPTH, 0); break; case COLOR_DEPTH_101010: - REG_UPDATE_2(HDMI_CONTROL, - HDMI_DEEP_COLOR_DEPTH, 1, - HDMI_DEEP_COLOR_ENABLE, 1); + if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) { + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DEEP_COLOR_DEPTH, 1, + HDMI_DEEP_COLOR_ENABLE, 0); + } else { + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DEEP_COLOR_DEPTH, 1, + HDMI_DEEP_COLOR_ENABLE, 1); + } break; case COLOR_DEPTH_121212: if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) { diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 76a397d90adc..6915cc46754b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -861,10 +861,6 @@ static void build_audio_output( audio_output->crtc_info.requested_pixel_clock = pipe_ctx->pix_clk_params.requested_pix_clk; - /* - * TODO - Investigate why calculated pixel clk has to be - * requested pixel clk - */ audio_output->crtc_info.calculated_pixel_clock = pipe_ctx->pix_clk_params.requested_pix_clk; @@ -1044,15 +1040,14 @@ static enum dc_status apply_single_controller_ctx_to_hw( stream->public.timing.display_color_depth, pipe_ctx->stream->signal); + /* FPGA does not program backend */ + if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { pipe_ctx->opp->funcs->opp_program_fmt( pipe_ctx->opp, &stream->bit_depth_params, &stream->clamping); - - /* FPGA does not program backend */ - if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) return DC_OK; - + } /* TODO: move to stream encoder */ if (pipe_ctx->stream->signal != SIGNAL_TYPE_VIRTUAL) if (DC_OK != bios_parser_crtc_source_select(pipe_ctx)) { @@ -1065,6 +1060,12 @@ static enum dc_status apply_single_controller_ctx_to_hw( stream->sink->link->link_enc, pipe_ctx->stream->signal); +/*vbios crtc_source_selection and encoder_setup will override fmt_C*/ + pipe_ctx->opp->funcs->opp_program_fmt( + pipe_ctx->opp, + &stream->bit_depth_params, + &stream->clamping); + if (dc_is_dp_signal(pipe_ctx->stream->signal)) pipe_ctx->stream_enc->funcs->dp_set_stream_attribute( pipe_ctx->stream_enc, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 074fb978e076..478c8d27f3bd 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -777,6 +777,9 @@ static void get_pixel_clock_parameters( pixel_clk_params->flags.SUPPORT_YCBCR420 = (stream->public.timing.pixel_encoding == PIXEL_ENCODING_YCBCR420); pixel_clk_params->pixel_encoding = stream->public.timing.pixel_encoding; + if (stream->public.timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) { + pixel_clk_params->color_depth = COLOR_DEPTH_888; + } } void dce110_resource_build_bit_depth_reduction_params( -- cgit From b0fb632f9b511145dfe49b783dd99adc6c6f8687 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 12 Jan 2017 09:07:38 -0500 Subject: drm/amdgpu: Expose mode_config functions for DM Signed-off-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/amdgpu_display.h | 33 +++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_display.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index e23b89cc6636..b1079930630e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -598,7 +598,7 @@ amdgpu_framebuffer_init(struct drm_device *dev, return 0; } -static struct drm_framebuffer * +struct drm_framebuffer * amdgpu_user_framebuffer_create(struct drm_device *dev, struct drm_file *file_priv, const struct drm_mode_fb_cmd2 *mode_cmd) @@ -636,7 +636,7 @@ amdgpu_user_framebuffer_create(struct drm_device *dev, return &amdgpu_fb->base; } -static void amdgpu_output_poll_changed(struct drm_device *dev) +void amdgpu_output_poll_changed(struct drm_device *dev) { struct amdgpu_device *adev = dev->dev_private; amdgpu_fb_output_poll_changed(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.h new file mode 100644 index 000000000000..3cc0ef0c055e --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.h @@ -0,0 +1,33 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#ifndef __AMDGPU_DISPLAY_H__ +#define __AMDGPU_DISPLAY_H__ + +struct drm_framebuffer * +amdgpu_user_framebuffer_create(struct drm_device *dev, + struct drm_file *file_priv, + const struct drm_mode_fb_cmd2 *mode_cmd); + +void amdgpu_output_poll_changed(struct drm_device *dev); + +#endif -- cgit From dd55d12c2675859fa4d4947dafc44515eedbccc4 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Sun, 29 Jan 2017 23:16:03 -0500 Subject: drm/amdgpu: Add a few members to support DAL atomic refactor. Signed-off-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index 0d92126b4c4a..813108eab6fc 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -310,6 +310,9 @@ struct amdgpu_display_funcs { struct amdgpu_framebuffer { struct drm_framebuffer base; struct drm_gem_object *obj; + + /* caching for later use */ + uint64_t address; }; struct amdgpu_fbdev { @@ -430,6 +433,7 @@ struct amdgpu_crtc { uint32_t flip_flags; /* After Set Mode stream will be non-NULL */ const struct dc_stream *stream; + struct drm_pending_vblank_event *event; }; struct amdgpu_encoder_atom_dig { -- cgit From 4ef3a67b6a1af2fc9030bc955200e764edfc37fb Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 15 Feb 2017 18:21:20 -0500 Subject: drm/amd/display: rename bandwidth_calcs.c to dce_calcs.c (v2) v2: agd: squash in the Makefile change as well. Signed-off-by: Dmytro Laktyushkin Acked-by: Harry Wentland Reviewed-by: Eagle Yeh Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/Makefile | 2 +- .../gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c | 3141 -------------------- drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c | 3141 ++++++++++++++++++++ 3 files changed, 3142 insertions(+), 3142 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c create mode 100644 drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/Makefile b/drivers/gpu/drm/amd/display/dc/calcs/Makefile index 2f4c8e771b8f..63a0edbc32e7 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/Makefile +++ b/drivers/gpu/drm/amd/display/dc/calcs/Makefile @@ -3,7 +3,7 @@ # It calculates Bandwidth and Watermarks values for HW programming # -BW_CALCS = bandwidth_calcs.o bw_fixed.o custom_float.o +BW_CALCS = dce_calcs.o bw_fixed.o custom_float.o AMD_DAL_BW_CALCS = $(addprefix $(AMDDALPATH)/dc/calcs/,$(BW_CALCS)) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c deleted file mode 100644 index ab8d1e931846..000000000000 --- a/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c +++ /dev/null @@ -1,3141 +0,0 @@ -/* - * Copyright 2015 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" -#include "bandwidth_calcs.h" -#include "dc.h" -#include "core_types.h" -#include "dal_asic_id.h" - -/******************************************************************************* - * Private Functions - ******************************************************************************/ - -static enum bw_calcs_version bw_calcs_version_from_asic_id(struct hw_asic_id asic_id) -{ - switch (asic_id.chip_family) { - - case FAMILY_CZ: - if (ASIC_REV_IS_STONEY(asic_id.hw_internal_rev)) - return BW_CALCS_VERSION_STONEY; - return BW_CALCS_VERSION_CARRIZO; - - case FAMILY_VI: - if (ASIC_REV_IS_POLARIS10_P(asic_id.hw_internal_rev)) - return BW_CALCS_VERSION_POLARIS10; - if (ASIC_REV_IS_POLARIS11_M(asic_id.hw_internal_rev) || - ASIC_REV_IS_POLARIS12_V(asic_id.hw_internal_rev)) - return BW_CALCS_VERSION_POLARIS11; - return BW_CALCS_VERSION_INVALID; - - default: - return BW_CALCS_VERSION_INVALID; - } -} - -static void calculate_bandwidth( - const struct bw_calcs_dceip *dceip, - const struct bw_calcs_vbios *vbios, - struct bw_calcs_data *data) - -{ - const int32_t pixels_per_chunk = 512; - const int32_t high = 2; - const int32_t mid = 1; - const int32_t low = 0; - const uint32_t s_low = 0; - const uint32_t s_mid1 = 1; - const uint32_t s_mid2 = 2; - const uint32_t s_mid3 = 3; - const uint32_t s_mid4 = 4; - const uint32_t s_mid5 = 5; - const uint32_t s_mid6 = 6; - const uint32_t s_high = 7; - const uint32_t bus_efficiency = 1; - const uint32_t dmif_chunk_buff_margin = 1; - - uint32_t max_chunks_fbc_mode; - int32_t num_cursor_lines; - - int32_t i, j, k; - struct bw_fixed yclk[3]; - struct bw_fixed sclk[8]; - bool d0_underlay_enable; - bool d1_underlay_enable; - bool fbc_enabled; - bool lpt_enabled; - enum bw_defines sclk_message; - enum bw_defines yclk_message; - enum bw_defines v_filter_init_mode[maximum_number_of_surfaces]; - enum bw_defines tiling_mode[maximum_number_of_surfaces]; - enum bw_defines surface_type[maximum_number_of_surfaces]; - enum bw_defines voltage; - enum bw_defines pipe_check; - enum bw_defines hsr_check; - enum bw_defines vsr_check; - enum bw_defines lb_size_check; - enum bw_defines fbc_check; - enum bw_defines rotation_check; - enum bw_defines mode_check; - enum bw_defines nbp_state_change_enable_blank; - /*initialize variables*/ - int32_t number_of_displays_enabled = 0; - int32_t number_of_displays_enabled_with_margin = 0; - int32_t number_of_aligned_displays_with_no_margin = 0; - - yclk[low] = vbios->low_yclk; - yclk[mid] = vbios->mid_yclk; - yclk[high] = vbios->high_yclk; - sclk[s_low] = vbios->low_sclk; - sclk[s_mid1] = vbios->mid1_sclk; - sclk[s_mid2] = vbios->mid2_sclk; - sclk[s_mid3] = vbios->mid3_sclk; - sclk[s_mid4] = vbios->mid4_sclk; - sclk[s_mid5] = vbios->mid5_sclk; - sclk[s_mid6] = vbios->mid6_sclk; - sclk[s_high] = vbios->high_sclk; - /*''''''''''''''''''*/ - /* surface assignment:*/ - /* 0: d0 underlay or underlay luma*/ - /* 1: d0 underlay chroma*/ - /* 2: d1 underlay or underlay luma*/ - /* 3: d1 underlay chroma*/ - /* 4: d0 graphics*/ - /* 5: d1 graphics*/ - /* 6: d2 graphics*/ - /* 7: d3 graphics, same mode as d2*/ - /* 8: d4 graphics, same mode as d2*/ - /* 9: d5 graphics, same mode as d2*/ - /* ...*/ - /* maximum_number_of_surfaces-2: d1 display_write_back420 luma*/ - /* maximum_number_of_surfaces-1: d1 display_write_back420 chroma*/ - /* underlay luma and chroma surface parameters from spreadsheet*/ - - - - - if (data->d0_underlay_mode == bw_def_none) { d0_underlay_enable = 0; } - else { - d0_underlay_enable = 1; - } - if (data->d1_underlay_mode == bw_def_none) { d1_underlay_enable = 0; } - else { - d1_underlay_enable = 1; - } - data->number_of_underlay_surfaces = d0_underlay_enable + d1_underlay_enable; - switch (data->underlay_surface_type) { - case bw_def_420: - surface_type[0] = bw_def_underlay420_luma; - surface_type[2] = bw_def_underlay420_luma; - data->bytes_per_pixel[0] = 1; - data->bytes_per_pixel[2] = 1; - surface_type[1] = bw_def_underlay420_chroma; - surface_type[3] = bw_def_underlay420_chroma; - data->bytes_per_pixel[1] = 2; - data->bytes_per_pixel[3] = 2; - data->lb_size_per_component[0] = dceip->underlay420_luma_lb_size_per_component; - data->lb_size_per_component[1] = dceip->underlay420_chroma_lb_size_per_component; - data->lb_size_per_component[2] = dceip->underlay420_luma_lb_size_per_component; - data->lb_size_per_component[3] = dceip->underlay420_chroma_lb_size_per_component; - break; - case bw_def_422: - surface_type[0] = bw_def_underlay422; - surface_type[2] = bw_def_underlay422; - data->bytes_per_pixel[0] = 2; - data->bytes_per_pixel[2] = 2; - data->lb_size_per_component[0] = dceip->underlay422_lb_size_per_component; - data->lb_size_per_component[2] = dceip->underlay422_lb_size_per_component; - break; - default: - surface_type[0] = bw_def_underlay444; - surface_type[2] = bw_def_underlay444; - data->bytes_per_pixel[0] = 4; - data->bytes_per_pixel[2] = 4; - data->lb_size_per_component[0] = dceip->lb_size_per_component444; - data->lb_size_per_component[2] = dceip->lb_size_per_component444; - break; - } - if (d0_underlay_enable) { - switch (data->underlay_surface_type) { - case bw_def_420: - data->enable[0] = 1; - data->enable[1] = 1; - break; - default: - data->enable[0] = 1; - data->enable[1] = 0; - break; - } - } - else { - data->enable[0] = 0; - data->enable[1] = 0; - } - if (d1_underlay_enable) { - switch (data->underlay_surface_type) { - case bw_def_420: - data->enable[2] = 1; - data->enable[3] = 1; - break; - default: - data->enable[2] = 1; - data->enable[3] = 0; - break; - } - } - else { - data->enable[2] = 0; - data->enable[3] = 0; - } - data->use_alpha[0] = 0; - data->use_alpha[1] = 0; - data->use_alpha[2] = 0; - data->use_alpha[3] = 0; - data->scatter_gather_enable_for_pipe[0] = vbios->scatter_gather_enable; - data->scatter_gather_enable_for_pipe[1] = vbios->scatter_gather_enable; - data->scatter_gather_enable_for_pipe[2] = vbios->scatter_gather_enable; - data->scatter_gather_enable_for_pipe[3] = vbios->scatter_gather_enable; - /*underlay0 same and graphics display pipe0*/ - data->interlace_mode[0] = data->interlace_mode[4]; - data->interlace_mode[1] = data->interlace_mode[4]; - /*underlay1 same and graphics display pipe1*/ - data->interlace_mode[2] = data->interlace_mode[5]; - data->interlace_mode[3] = data->interlace_mode[5]; - /*underlay0 same and graphics display pipe0*/ - data->h_total[0] = data->h_total[4]; - data->v_total[0] = data->v_total[4]; - data->h_total[1] = data->h_total[4]; - data->v_total[1] = data->v_total[4]; - /*underlay1 same and graphics display pipe1*/ - data->h_total[2] = data->h_total[5]; - data->v_total[2] = data->v_total[5]; - data->h_total[3] = data->h_total[5]; - data->v_total[3] = data->v_total[5]; - /*underlay0 same and graphics display pipe0*/ - data->pixel_rate[0] = data->pixel_rate[4]; - data->pixel_rate[1] = data->pixel_rate[4]; - /*underlay1 same and graphics display pipe1*/ - data->pixel_rate[2] = data->pixel_rate[5]; - data->pixel_rate[3] = data->pixel_rate[5]; - if ((data->underlay_tiling_mode == bw_def_array_linear_general || data->underlay_tiling_mode == bw_def_array_linear_aligned)) { - tiling_mode[0] = bw_def_linear; - tiling_mode[1] = bw_def_linear; - tiling_mode[2] = bw_def_linear; - tiling_mode[3] = bw_def_linear; - } - else { - tiling_mode[0] = bw_def_landscape; - tiling_mode[1] = bw_def_landscape; - tiling_mode[2] = bw_def_landscape; - tiling_mode[3] = bw_def_landscape; - } - data->lb_bpc[0] = data->underlay_lb_bpc; - data->lb_bpc[1] = data->underlay_lb_bpc; - data->lb_bpc[2] = data->underlay_lb_bpc; - data->lb_bpc[3] = data->underlay_lb_bpc; - data->compression_rate[0] = bw_int_to_fixed(1); - data->compression_rate[1] = bw_int_to_fixed(1); - data->compression_rate[2] = bw_int_to_fixed(1); - data->compression_rate[3] = bw_int_to_fixed(1); - data->access_one_channel_only[0] = 0; - data->access_one_channel_only[1] = 0; - data->access_one_channel_only[2] = 0; - data->access_one_channel_only[3] = 0; - data->cursor_width_pixels[0] = bw_int_to_fixed(0); - data->cursor_width_pixels[1] = bw_int_to_fixed(0); - data->cursor_width_pixels[2] = bw_int_to_fixed(0); - data->cursor_width_pixels[3] = bw_int_to_fixed(0); - /* graphics surface parameters from spreadsheet*/ - fbc_enabled = 0; - lpt_enabled = 0; - for (i = 4; i <= maximum_number_of_surfaces - 3; i++) { - if (i < data->number_of_displays + 4) { - if (i == 4 && data->d0_underlay_mode == bw_def_underlay_only) { - data->enable[i] = 0; - data->use_alpha[i] = 0; - } - else if (i == 4 && data->d0_underlay_mode == bw_def_blend) { - data->enable[i] = 1; - data->use_alpha[i] = 1; - } - else if (i == 4) { - data->enable[i] = 1; - data->use_alpha[i] = 0; - } - else if (i == 5 && data->d1_underlay_mode == bw_def_underlay_only) { - data->enable[i] = 0; - data->use_alpha[i] = 0; - } - else if (i == 5 && data->d1_underlay_mode == bw_def_blend) { - data->enable[i] = 1; - data->use_alpha[i] = 1; - } - else { - data->enable[i] = 1; - data->use_alpha[i] = 0; - } - } - else { - data->enable[i] = 0; - data->use_alpha[i] = 0; - } - data->scatter_gather_enable_for_pipe[i] = vbios->scatter_gather_enable; - surface_type[i] = bw_def_graphics; - data->lb_size_per_component[i] = dceip->lb_size_per_component444; - if (data->graphics_tiling_mode == bw_def_array_linear_general || data->graphics_tiling_mode == bw_def_array_linear_aligned) { - tiling_mode[i] = bw_def_linear; - } - else { - tiling_mode[i] = bw_def_tiled; - } - data->lb_bpc[i] = data->graphics_lb_bpc; - if ((data->fbc_en[i] == 1 && (dceip->argb_compression_support || data->d0_underlay_mode != bw_def_blended))) { - data->compression_rate[i] = bw_int_to_fixed(vbios->average_compression_rate); - data->access_one_channel_only[i] = data->lpt_en[i]; - } - else { - data->compression_rate[i] = bw_int_to_fixed(1); - data->access_one_channel_only[i] = 0; - } - if (data->fbc_en[i] == 1) { - fbc_enabled = 1; - if (data->lpt_en[i] == 1) { - lpt_enabled = 1; - } - } - data->cursor_width_pixels[i] = bw_int_to_fixed(vbios->cursor_width); - } - /* display_write_back420*/ - data->scatter_gather_enable_for_pipe[maximum_number_of_surfaces - 2] = 0; - data->scatter_gather_enable_for_pipe[maximum_number_of_surfaces - 1] = 0; - if (data->d1_display_write_back_dwb_enable == 1) { - data->enable[maximum_number_of_surfaces - 2] = 1; - data->enable[maximum_number_of_surfaces - 1] = 1; - } - else { - data->enable[maximum_number_of_surfaces - 2] = 0; - data->enable[maximum_number_of_surfaces - 1] = 0; - } - surface_type[maximum_number_of_surfaces - 2] = bw_def_display_write_back420_luma; - surface_type[maximum_number_of_surfaces - 1] = bw_def_display_write_back420_chroma; - data->lb_size_per_component[maximum_number_of_surfaces - 2] = dceip->underlay420_luma_lb_size_per_component; - data->lb_size_per_component[maximum_number_of_surfaces - 1] = dceip->underlay420_chroma_lb_size_per_component; - data->bytes_per_pixel[maximum_number_of_surfaces - 2] = 1; - data->bytes_per_pixel[maximum_number_of_surfaces - 1] = 2; - data->interlace_mode[maximum_number_of_surfaces - 2] = data->interlace_mode[5]; - data->interlace_mode[maximum_number_of_surfaces - 1] = data->interlace_mode[5]; - data->h_taps[maximum_number_of_surfaces - 2] = bw_int_to_fixed(1); - data->h_taps[maximum_number_of_surfaces - 1] = bw_int_to_fixed(1); - data->v_taps[maximum_number_of_surfaces - 2] = bw_int_to_fixed(1); - data->v_taps[maximum_number_of_surfaces - 1] = bw_int_to_fixed(1); - data->rotation_angle[maximum_number_of_surfaces - 2] = bw_int_to_fixed(0); - data->rotation_angle[maximum_number_of_surfaces - 1] = bw_int_to_fixed(0); - tiling_mode[maximum_number_of_surfaces - 2] = bw_def_linear; - tiling_mode[maximum_number_of_surfaces - 1] = bw_def_linear; - data->lb_bpc[maximum_number_of_surfaces - 2] = 8; - data->lb_bpc[maximum_number_of_surfaces - 1] = 8; - data->compression_rate[maximum_number_of_surfaces - 2] = bw_int_to_fixed(1); - data->compression_rate[maximum_number_of_surfaces - 1] = bw_int_to_fixed(1); - data->access_one_channel_only[maximum_number_of_surfaces - 2] = 0; - data->access_one_channel_only[maximum_number_of_surfaces - 1] = 0; - /*assume display pipe1 has dwb enabled*/ - data->h_total[maximum_number_of_surfaces - 2] = data->h_total[5]; - data->h_total[maximum_number_of_surfaces - 1] = data->h_total[5]; - data->v_total[maximum_number_of_surfaces - 2] = data->v_total[5]; - data->v_total[maximum_number_of_surfaces - 1] = data->v_total[5]; - data->pixel_rate[maximum_number_of_surfaces - 2] = data->pixel_rate[5]; - data->pixel_rate[maximum_number_of_surfaces - 1] = data->pixel_rate[5]; - data->src_width[maximum_number_of_surfaces - 2] = data->src_width[5]; - data->src_width[maximum_number_of_surfaces - 1] = data->src_width[5]; - data->src_height[maximum_number_of_surfaces - 2] = data->src_height[5]; - data->src_height[maximum_number_of_surfaces - 1] = data->src_height[5]; - data->pitch_in_pixels[maximum_number_of_surfaces - 2] = data->src_width[5]; - data->pitch_in_pixels[maximum_number_of_surfaces - 1] = data->src_width[5]; - data->h_scale_ratio[maximum_number_of_surfaces - 2] = bw_int_to_fixed(1); - data->h_scale_ratio[maximum_number_of_surfaces - 1] = bw_int_to_fixed(1); - data->v_scale_ratio[maximum_number_of_surfaces - 2] = bw_int_to_fixed(1); - data->v_scale_ratio[maximum_number_of_surfaces - 1] = bw_int_to_fixed(1); - data->stereo_mode[maximum_number_of_surfaces - 2] = bw_def_mono; - data->stereo_mode[maximum_number_of_surfaces - 1] = bw_def_mono; - data->cursor_width_pixels[maximum_number_of_surfaces - 2] = bw_int_to_fixed(0); - data->cursor_width_pixels[maximum_number_of_surfaces - 1] = bw_int_to_fixed(0); - data->use_alpha[maximum_number_of_surfaces - 2] = 0; - data->use_alpha[maximum_number_of_surfaces - 1] = 0; - /*mode check calculations:*/ - /* mode within dce ip capabilities*/ - /* fbc*/ - /* hsr*/ - /* vsr*/ - /* lb size*/ - /*effective scaling source and ratios:*/ - /*for graphics, non-stereo, non-interlace surfaces when the size of the source and destination are the same, only one tap is used*/ - /*420 chroma has half the width, height, horizontal and vertical scaling ratios than luma*/ - /*rotating a graphic or underlay surface swaps the width, height, horizontal and vertical scaling ratios*/ - /*in top-bottom stereo mode there is 2:1 vertical downscaling for each eye*/ - /*in side-by-side stereo mode there is 2:1 horizontal downscaling for each eye*/ - /*in interlace mode there is 2:1 vertical downscaling for each field*/ - /*in panning or bezel adjustment mode the source width has an extra 128 pixels*/ - for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { - if (data->enable[i]) { - if (bw_equ(data->h_scale_ratio[i], bw_int_to_fixed(1)) && bw_equ(data->v_scale_ratio[i], bw_int_to_fixed(1)) && surface_type[i] == bw_def_graphics && data->stereo_mode[i] == bw_def_mono && data->interlace_mode[i] == 0) { - data->h_taps[i] = bw_int_to_fixed(1); - data->v_taps[i] = bw_int_to_fixed(1); - } - if (surface_type[i] == bw_def_display_write_back420_chroma || surface_type[i] == bw_def_underlay420_chroma) { - data->pitch_in_pixels_after_surface_type[i] = bw_div(data->pitch_in_pixels[i], bw_int_to_fixed(2)); - data->src_width_after_surface_type = bw_div(data->src_width[i], bw_int_to_fixed(2)); - data->src_height_after_surface_type = bw_div(data->src_height[i], bw_int_to_fixed(2)); - data->hsr_after_surface_type = bw_div(data->h_scale_ratio[i], bw_int_to_fixed(2)); - data->vsr_after_surface_type = bw_div(data->v_scale_ratio[i], bw_int_to_fixed(2)); - } - else { - data->pitch_in_pixels_after_surface_type[i] = data->pitch_in_pixels[i]; - data->src_width_after_surface_type = data->src_width[i]; - data->src_height_after_surface_type = data->src_height[i]; - data->hsr_after_surface_type = data->h_scale_ratio[i]; - data->vsr_after_surface_type = data->v_scale_ratio[i]; - } - if ((bw_equ(data->rotation_angle[i], bw_int_to_fixed(90)) || bw_equ(data->rotation_angle[i], bw_int_to_fixed(270))) && surface_type[i] != bw_def_display_write_back420_luma && surface_type[i] != bw_def_display_write_back420_chroma) { - data->src_width_after_rotation = data->src_height_after_surface_type; - data->src_height_after_rotation = data->src_width_after_surface_type; - data->hsr_after_rotation = data->vsr_after_surface_type; - data->vsr_after_rotation = data->hsr_after_surface_type; - } - else { - data->src_width_after_rotation = data->src_width_after_surface_type; - data->src_height_after_rotation = data->src_height_after_surface_type; - data->hsr_after_rotation = data->hsr_after_surface_type; - data->vsr_after_rotation = data->vsr_after_surface_type; - } - switch (data->stereo_mode[i]) { - case bw_def_top_bottom: - data->source_width_pixels[i] = data->src_width_after_rotation; - data->source_height_pixels = bw_mul(bw_int_to_fixed(2), data->src_height_after_rotation); - data->hsr_after_stereo = data->hsr_after_rotation; - data->vsr_after_stereo = bw_mul(bw_int_to_fixed(1), data->vsr_after_rotation); - break; - case bw_def_side_by_side: - data->source_width_pixels[i] = bw_mul(bw_int_to_fixed(2), data->src_width_after_rotation); - data->source_height_pixels = data->src_height_after_rotation; - data->hsr_after_stereo = bw_mul(bw_int_to_fixed(1), data->hsr_after_rotation); - data->vsr_after_stereo = data->vsr_after_rotation; - break; - default: - data->source_width_pixels[i] = data->src_width_after_rotation; - data->source_height_pixels = data->src_height_after_rotation; - data->hsr_after_stereo = data->hsr_after_rotation; - data->vsr_after_stereo = data->vsr_after_rotation; - break; - } - data->hsr[i] = data->hsr_after_stereo; - if (data->interlace_mode[i]) { - data->vsr[i] = bw_mul(data->vsr_after_stereo, bw_int_to_fixed(2)); - } - else { - data->vsr[i] = data->vsr_after_stereo; - } - if (data->panning_and_bezel_adjustment != bw_def_none) { - data->source_width_rounded_up_to_chunks[i] = bw_add(bw_floor2(bw_sub(data->source_width_pixels[i], bw_int_to_fixed(1)), bw_int_to_fixed(128)), bw_int_to_fixed(256)); - } - else { - data->source_width_rounded_up_to_chunks[i] = bw_ceil2(data->source_width_pixels[i], bw_int_to_fixed(128)); - } - data->source_height_rounded_up_to_chunks[i] = data->source_height_pixels; - } - } - /*mode support checks:*/ - /*the number of graphics and underlay pipes is limited by the ip support*/ - /*maximum horizontal and vertical scale ratio is 4, and should not exceed the number of taps*/ - /*for downscaling with the pre-downscaler, the horizontal scale ratio must be more than the ceiling of one quarter of the number of taps*/ - /*the pre-downscaler reduces the line buffer source by the horizontal scale ratio*/ - /*the number of lines in the line buffer has to exceed the number of vertical taps*/ - /*the size of the line in the line buffer is the product of the source width and the bits per component, rounded up to a multiple of 48*/ - /*the size of the line in the line buffer in the case of 10 bit per component is the product of the source width rounded up to multiple of 8 and 30.023438 / 3, rounded up to a multiple of 48*/ - /*the size of the line in the line buffer in the case of 8 bit per component is the product of the source width rounded up to multiple of 8 and 30.023438 / 3, rounded up to a multiple of 48*/ - /*frame buffer compression is not supported with stereo mode, rotation, or non- 888 formats*/ - /*rotation is not supported with linear of stereo modes*/ - if (dceip->number_of_graphics_pipes >= data->number_of_displays && dceip->number_of_underlay_pipes >= data->number_of_underlay_surfaces && !(dceip->display_write_back_supported == 0 && data->d1_display_write_back_dwb_enable == 1)) { - pipe_check = bw_def_ok; - } - else { - pipe_check = bw_def_notok; - } - hsr_check = bw_def_ok; - for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { - if (data->enable[i]) { - if (bw_neq(data->hsr[i], bw_int_to_fixed(1))) { - if (bw_mtn(data->hsr[i], bw_int_to_fixed(4))) { - hsr_check = bw_def_hsr_mtn_4; - } - else { - if (bw_mtn(data->hsr[i], data->h_taps[i])) { - hsr_check = bw_def_hsr_mtn_h_taps; - } - else { - if (dceip->pre_downscaler_enabled == 1 && bw_mtn(data->hsr[i], bw_int_to_fixed(1)) && bw_leq(data->hsr[i], bw_ceil2(bw_div(data->h_taps[i], bw_int_to_fixed(4)), bw_int_to_fixed(1)))) { - hsr_check = bw_def_ceiling__h_taps_div_4___meq_hsr; - } - } - } - } - } - } - vsr_check = bw_def_ok; - for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { - if (data->enable[i]) { - if (bw_neq(data->vsr[i], bw_int_to_fixed(1))) { - if (bw_mtn(data->vsr[i], bw_int_to_fixed(4))) { - vsr_check = bw_def_vsr_mtn_4; - } - else { - if (bw_mtn(data->vsr[i], data->v_taps[i])) { - vsr_check = bw_def_vsr_mtn_v_taps; - } - } - } - } - } - lb_size_check = bw_def_ok; - for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { - if (data->enable[i]) { - if ((dceip->pre_downscaler_enabled && bw_mtn(data->hsr[i], bw_int_to_fixed(1)))) { - data->source_width_in_lb = bw_div(data->source_width_pixels[i], data->hsr[i]); - } - else { - data->source_width_in_lb = data->source_width_pixels[i]; - } - switch (data->lb_bpc[i]) { - case 8: - data->lb_line_pitch = bw_ceil2(bw_mul(bw_div(bw_frc_to_fixed(2401171875, 100000000), bw_int_to_fixed(3)), bw_ceil2(data->source_width_in_lb, bw_int_to_fixed(8))), bw_int_to_fixed(48)); - break; - case 10: - data->lb_line_pitch = bw_ceil2(bw_mul(bw_div(bw_frc_to_fixed(300234375, 10000000), bw_int_to_fixed(3)), bw_ceil2(data->source_width_in_lb, bw_int_to_fixed(8))), bw_int_to_fixed(48)); - break; - default: - data->lb_line_pitch = bw_ceil2(bw_mul(bw_int_to_fixed(data->lb_bpc[i]), data->source_width_in_lb), bw_int_to_fixed(48)); - break; - } - data->lb_partitions[i] = bw_floor2(bw_div(data->lb_size_per_component[i], data->lb_line_pitch), bw_int_to_fixed(1)); - /*clamp the partitions to the maxium number supported by the lb*/ - if ((surface_type[i] != bw_def_graphics || dceip->graphics_lb_nodownscaling_multi_line_prefetching == 1)) { - data->lb_partitions_max[i] = bw_int_to_fixed(10); - } - else { - data->lb_partitions_max[i] = bw_int_to_fixed(7); - } - data->lb_partitions[i] = bw_min2(data->lb_partitions_max[i], data->lb_partitions[i]); - if (bw_mtn(bw_add(data->v_taps[i], bw_int_to_fixed(1)), data->lb_partitions[i])) { - lb_size_check = bw_def_notok; - } - } - } - fbc_check = bw_def_ok; - for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { - if (data->enable[i] && data->fbc_en[i] == 1 && (bw_equ(data->rotation_angle[i], bw_int_to_fixed(90)) || bw_equ(data->rotation_angle[i], bw_int_to_fixed(270)) || data->stereo_mode[i] != bw_def_mono || data->bytes_per_pixel[i] != 4)) { - fbc_check = bw_def_invalid_rotation_or_bpp_or_stereo; - } - } - rotation_check = bw_def_ok; - for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { - if (data->enable[i]) { - if ((bw_equ(data->rotation_angle[i], bw_int_to_fixed(90)) || bw_equ(data->rotation_angle[i], bw_int_to_fixed(270))) && (tiling_mode[i] == bw_def_linear || data->stereo_mode[i] != bw_def_mono)) { - rotation_check = bw_def_invalid_linear_or_stereo_mode; - } - } - } - if (pipe_check == bw_def_ok && hsr_check == bw_def_ok && vsr_check == bw_def_ok && lb_size_check == bw_def_ok && fbc_check == bw_def_ok && rotation_check == bw_def_ok) { - mode_check = bw_def_ok; - } - else { - mode_check = bw_def_notok; - } - /*number of memory channels for write-back client*/ - data->number_of_dram_wrchannels = vbios->number_of_dram_channels; - data->number_of_dram_channels = vbios->number_of_dram_channels; - /*modify number of memory channels if lpt mode is enabled*/ - /* low power tiling mode register*/ - /* 0 = use channel 0*/ - /* 1 = use channel 0 and 1*/ - /* 2 = use channel 0,1,2,3*/ - if ((fbc_enabled == 1 && lpt_enabled == 1)) { - data->dram_efficiency = bw_int_to_fixed(1); - if (dceip->low_power_tiling_mode == 0) { - data->number_of_dram_channels = 1; - } - else if (dceip->low_power_tiling_mode == 1) { - data->number_of_dram_channels = 2; - } - else if (dceip->low_power_tiling_mode == 2) { - data->number_of_dram_channels = 4; - } - else { - data->number_of_dram_channels = 1; - } - } - else { - data->dram_efficiency = bw_frc_to_fixed(8, 10); - } - /*memory request size and latency hiding:*/ - /*request size is normally 64 byte, 2-line interleaved, with full latency hiding*/ - /*the display write-back requests are single line*/ - /*for tiled graphics surfaces, or undelay surfaces with width higher than the maximum size for full efficiency, request size is 32 byte in 8 and 16 bpp or if the rotation is orthogonal to the tiling grain. only half is useful of the bytes in the request size in 8 bpp or in 32 bpp if the rotation is orthogonal to the tiling grain.*/ - /*for undelay surfaces with width lower than the maximum size for full efficiency, requests are 4-line interleaved in 16bpp if the rotation is parallel to the tiling grain, and 8-line interleaved with 4-line latency hiding in 8bpp or if the rotation is orthogonal to the tiling grain.*/ - for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { - if (data->enable[i]) { - if ((bw_equ(data->rotation_angle[i], bw_int_to_fixed(90)) || bw_equ(data->rotation_angle[i], bw_int_to_fixed(270)))) { - if ((i < 4)) { - /*underlay portrait tiling mode is not supported*/ - data->orthogonal_rotation[i] = 1; - } - else { - /*graphics portrait tiling mode*/ - if ((data->graphics_micro_tile_mode == bw_def_rotated_micro_tiling)) { - data->orthogonal_rotation[i] = 0; - } - else { - data->orthogonal_rotation[i] = 1; - } - } - } - else { - if ((i < 4)) { - /*underlay landscape tiling mode is only supported*/ - if ((data->underlay_micro_tile_mode == bw_def_display_micro_tiling)) { - data->orthogonal_rotation[i] = 0; - } - else { - data->orthogonal_rotation[i] = 1; - } - } - else { - /*graphics landscape tiling mode*/ - if ((data->graphics_micro_tile_mode == bw_def_display_micro_tiling)) { - data->orthogonal_rotation[i] = 0; - } - else { - data->orthogonal_rotation[i] = 1; - } - } - } - if (bw_equ(data->rotation_angle[i], bw_int_to_fixed(90)) || bw_equ(data->rotation_angle[i], bw_int_to_fixed(270))) { - data->underlay_maximum_source_efficient_for_tiling = dceip->underlay_maximum_height_efficient_for_tiling; - } - else { - data->underlay_maximum_source_efficient_for_tiling = dceip->underlay_maximum_width_efficient_for_tiling; - } - if (surface_type[i] == bw_def_display_write_back420_luma || surface_type[i] == bw_def_display_write_back420_chroma) { - data->bytes_per_request[i] = bw_int_to_fixed(64); - data->useful_bytes_per_request[i] = bw_int_to_fixed(64); - data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(1); - data->latency_hiding_lines[i] = bw_int_to_fixed(1); - } - else if (tiling_mode[i] == bw_def_linear) { - data->bytes_per_request[i] = bw_int_to_fixed(64); - data->useful_bytes_per_request[i] = bw_int_to_fixed(64); - data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(2); - data->latency_hiding_lines[i] = bw_int_to_fixed(2); - } - else { - if (surface_type[i] == bw_def_graphics || (bw_mtn(data->source_width_rounded_up_to_chunks[i], bw_ceil2(data->underlay_maximum_source_efficient_for_tiling, bw_int_to_fixed(256))))) { - switch (data->bytes_per_pixel[i]) { - case 8: - data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(2); - data->latency_hiding_lines[i] = bw_int_to_fixed(2); - if (data->orthogonal_rotation[i]) { - data->bytes_per_request[i] = bw_int_to_fixed(32); - data->useful_bytes_per_request[i] = bw_int_to_fixed(32); - } - else { - data->bytes_per_request[i] = bw_int_to_fixed(64); - data->useful_bytes_per_request[i] = bw_int_to_fixed(64); - } - break; - case 4: - if (data->orthogonal_rotation[i]) { - data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(2); - data->latency_hiding_lines[i] = bw_int_to_fixed(2); - data->bytes_per_request[i] = bw_int_to_fixed(32); - data->useful_bytes_per_request[i] = bw_int_to_fixed(16); - } - else { - data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(2); - data->latency_hiding_lines[i] = bw_int_to_fixed(2); - data->bytes_per_request[i] = bw_int_to_fixed(64); - data->useful_bytes_per_request[i] = bw_int_to_fixed(64); - } - break; - case 2: - data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(2); - data->latency_hiding_lines[i] = bw_int_to_fixed(2); - data->bytes_per_request[i] = bw_int_to_fixed(32); - data->useful_bytes_per_request[i] = bw_int_to_fixed(32); - break; - default: - data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(2); - data->latency_hiding_lines[i] = bw_int_to_fixed(2); - data->bytes_per_request[i] = bw_int_to_fixed(32); - data->useful_bytes_per_request[i] = bw_int_to_fixed(16); - break; - } - } - else { - data->bytes_per_request[i] = bw_int_to_fixed(64); - data->useful_bytes_per_request[i] = bw_int_to_fixed(64); - if (data->orthogonal_rotation[i]) { - data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(8); - data->latency_hiding_lines[i] = bw_int_to_fixed(4); - } - else { - switch (data->bytes_per_pixel[i]) { - case 4: - data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(2); - data->latency_hiding_lines[i] = bw_int_to_fixed(2); - break; - case 2: - data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(4); - data->latency_hiding_lines[i] = bw_int_to_fixed(4); - break; - default: - data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(8); - data->latency_hiding_lines[i] = bw_int_to_fixed(4); - break; - } - } - } - } - } - } - /*requested peak bandwidth:*/ - /*the peak request-per-second bandwidth is the product of the maximum source lines in per line out in the beginning*/ - /*and in the middle of the frame, the ratio of the source width to the line time, the ratio of line interleaving*/ - /*in memory to lines of latency hiding, and the ratio of bytes per pixel to useful bytes per request.*/ - /**/ - /*if the dmif data buffer size holds more than vta_ps worth of source lines, then only vsr is used.*/ - /*the peak bandwidth is the peak request-per-second bandwidth times the request size.*/ - /**/ - /*the line buffer lines in per line out in the beginning of the frame is the vertical filter initialization value*/ - /*rounded up to even and divided by the line times for initialization, which is normally three.*/ - /*the line buffer lines in per line out in the middle of the frame is at least one, or the vertical scale ratio,*/ - /*rounded up to line pairs if not doing line buffer prefetching.*/ - /**/ - /*the non-prefetching rounding up of the vertical scale ratio can also be done up to 1 (for a 0,2 pattern), 4/3 (for a 0,2,2 pattern),*/ - /*6/4 (for a 0,2,2,2 pattern), or 3 (for a 2,4 pattern).*/ - /**/ - /*the scaler vertical filter initialization value is calculated by the hardware as the floor of the average of the*/ - /*vertical scale ratio and the number of vertical taps increased by one. add one more for possible odd line*/ - /*panning/bezel adjustment mode.*/ - /**/ - /*for the bottom interlace field an extra 50% of the vertical scale ratio is considered for this calculation.*/ - /*in top-bottom stereo mode software has to set the filter initialization value manually and explicitly limit it to 4.*/ - /*furthermore, there is only one line time for initialization.*/ - /**/ - /*line buffer prefetching is done when the number of lines in the line buffer exceeds the number of taps plus*/ - /*the ceiling of the vertical scale ratio.*/ - /**/ - /*multi-line buffer prefetching is only done in the graphics pipe when the scaler is disabled or when upscaling and the vsr <= 0.8.'*/ - /**/ - /*the horizontal blank and chunk granularity factor is indirectly used indicate the interval of time required to transfer the source pixels.*/ - /*the denominator of this term represents the total number of destination output pixels required for the input source pixels.*/ - /*it applies when the lines in per line out is not 2 or 4. it does not apply when there is a line buffer between the scl and blnd.*/ - for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { - if (data->enable[i]) { - data->v_filter_init[i] = bw_floor2(bw_div((bw_add(bw_add(bw_add(bw_int_to_fixed(1), data->v_taps[i]), data->vsr[i]), bw_mul(bw_mul(bw_int_to_fixed(data->interlace_mode[i]), bw_frc_to_fixed(5, 10)), data->vsr[i]))), bw_int_to_fixed(2)), bw_int_to_fixed(1)); - if (data->panning_and_bezel_adjustment == bw_def_any_lines) { - data->v_filter_init[i] = bw_add(data->v_filter_init[i], bw_int_to_fixed(1)); - } - if (data->stereo_mode[i] == bw_def_top_bottom) { - v_filter_init_mode[i] = bw_def_manual; - data->v_filter_init[i] = bw_min2(data->v_filter_init[i], bw_int_to_fixed(4)); - } - else { - v_filter_init_mode[i] = bw_def_auto; - } - if (data->stereo_mode[i] == bw_def_top_bottom) { - data->num_lines_at_frame_start = bw_int_to_fixed(1); - } - else { - data->num_lines_at_frame_start = bw_int_to_fixed(3); - } - if ((bw_mtn(data->vsr[i], bw_int_to_fixed(1)) && surface_type[i] == bw_def_graphics) || data->panning_and_bezel_adjustment == bw_def_any_lines) { - data->line_buffer_prefetch[i] = 0; - } - else if ((((dceip->underlay_downscale_prefetch_enabled == 1 && surface_type[i] != bw_def_graphics) || surface_type[i] == bw_def_graphics) && (bw_mtn(data->lb_partitions[i], bw_add(data->v_taps[i], bw_ceil2(data->vsr[i], bw_int_to_fixed(1))))))) { - data->line_buffer_prefetch[i] = 1; - } - else { - data->line_buffer_prefetch[i] = 0; - } - data->lb_lines_in_per_line_out_in_beginning_of_frame[i] = bw_div(bw_ceil2(data->v_filter_init[i], bw_int_to_fixed(dceip->lines_interleaved_into_lb)), data->num_lines_at_frame_start); - if (data->line_buffer_prefetch[i] == 1) { - data->lb_lines_in_per_line_out_in_middle_of_frame[i] = bw_max2(bw_int_to_fixed(1), data->vsr[i]); - } - else if (bw_leq(data->vsr[i], bw_int_to_fixed(1))) { - data->lb_lines_in_per_line_out_in_middle_of_frame[i] = bw_int_to_fixed(1); - } - else if (bw_leq(data->vsr[i], bw_int_to_fixed(4 / 3))) { - data->lb_lines_in_per_line_out_in_middle_of_frame[i] = bw_div(bw_int_to_fixed(4), bw_int_to_fixed(3)); - } - else if (bw_leq(data->vsr[i], bw_int_to_fixed(6 / 4))) { - data->lb_lines_in_per_line_out_in_middle_of_frame[i] = bw_div(bw_int_to_fixed(6), bw_int_to_fixed(4)); - } - else if (bw_leq(data->vsr[i], bw_int_to_fixed(2))) { - data->lb_lines_in_per_line_out_in_middle_of_frame[i] = bw_int_to_fixed(2); - } - else if (bw_leq(data->vsr[i], bw_int_to_fixed(3))) { - data->lb_lines_in_per_line_out_in_middle_of_frame[i] = bw_int_to_fixed(3); - } - else { - data->lb_lines_in_per_line_out_in_middle_of_frame[i] = bw_int_to_fixed(4); - } - if (data->line_buffer_prefetch[i] == 1 || bw_equ(data->lb_lines_in_per_line_out_in_middle_of_frame[i], bw_int_to_fixed(2)) || bw_equ(data->lb_lines_in_per_line_out_in_middle_of_frame[i], bw_int_to_fixed(4))) { - data->horizontal_blank_and_chunk_granularity_factor[i] = bw_int_to_fixed(1); - } - else { - data->horizontal_blank_and_chunk_granularity_factor[i] = bw_div(data->h_total[i], (bw_div((bw_add(data->h_total[i], bw_div((bw_sub(data->source_width_pixels[i], bw_int_to_fixed(dceip->chunk_width))), data->hsr[i]))), bw_int_to_fixed(2)))); - } - data->request_bandwidth[i] = bw_div(bw_mul(bw_div(bw_mul(bw_div(bw_mul(bw_max2(data->lb_lines_in_per_line_out_in_beginning_of_frame[i], data->lb_lines_in_per_line_out_in_middle_of_frame[i]), data->source_width_rounded_up_to_chunks[i]), (bw_div(data->h_total[i], data->pixel_rate[i]))), bw_int_to_fixed(data->bytes_per_pixel[i])), data->useful_bytes_per_request[i]), data->lines_interleaved_in_mem_access[i]), data->latency_hiding_lines[i]); - data->display_bandwidth[i] = bw_mul(data->request_bandwidth[i], data->bytes_per_request[i]); - } - } - /*outstanding chunk request limit*/ - /*if underlay buffer sharing is enabled, the data buffer size for underlay in 422 or 444 is the sum of the luma and chroma data buffer sizes.*/ - /*underlay buffer sharing mode is only permitted in orthogonal rotation modes.*/ - /**/ - /*if there is only one display enabled, the dmif data buffer size for the graphics surface is increased by concatenating the adjacent buffers.*/ - /**/ - /*the memory chunk size in bytes is 1024 for the writeback, and 256 times the memory line interleaving and the bytes per pixel for graphics*/ - /*and underlay.*/ - /**/ - /*the pipe chunk size uses 2 for line interleaving, except for the write back, in which case it is 1.*/ - /*graphics and underlay data buffer size is adjusted (limited) using the outstanding chunk request limit if there is more than one*/ - /*display enabled or if the dmif request buffer is not large enough for the total data buffer size.*/ - /*the outstanding chunk request limit is the ceiling of the adjusted data buffer size divided by the chunk size in bytes*/ - /*the adjusted data buffer size is the product of the display bandwidth and the minimum effective data buffer size in terms of time,*/ - /*rounded up to the chunk size in bytes, but should not exceed the original data buffer size*/ - for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { - if (data->enable[i]) { - if ((dceip->dmif_pipe_en_fbc_chunk_tracker + 3 == i && fbc_enabled == 0 && tiling_mode[i] != bw_def_linear)) { - data->max_chunks_non_fbc_mode[i] = 128 - dmif_chunk_buff_margin; - } - else { - data->max_chunks_non_fbc_mode[i] = 16 - dmif_chunk_buff_margin; - } - } - if (data->fbc_en[i] == 1) { - max_chunks_fbc_mode = 128 - dmif_chunk_buff_margin; - } - } - for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { - if (data->enable[i]) { - switch (surface_type[i]) { - case bw_def_display_write_back420_luma: - data->data_buffer_size[i] = bw_int_to_fixed(dceip->display_write_back420_luma_mcifwr_buffer_size); - break; - case bw_def_display_write_back420_chroma: - data->data_buffer_size[i] = bw_int_to_fixed(dceip->display_write_back420_chroma_mcifwr_buffer_size); - break; - case bw_def_underlay420_luma: - data->data_buffer_size[i] = bw_int_to_fixed(dceip->underlay_luma_dmif_size); - break; - case bw_def_underlay420_chroma: - data->data_buffer_size[i] = bw_div(bw_int_to_fixed(dceip->underlay_chroma_dmif_size), bw_int_to_fixed(2)); - break; - case bw_def_underlay422:case bw_def_underlay444: - if (data->orthogonal_rotation[i] == 0) { - data->data_buffer_size[i] = bw_int_to_fixed(dceip->underlay_luma_dmif_size); - } - else { - data->data_buffer_size[i] = bw_add(bw_int_to_fixed(dceip->underlay_luma_dmif_size), bw_int_to_fixed(dceip->underlay_chroma_dmif_size)); - } - break; - default: - if (data->fbc_en[i] == 1) { - /*data_buffer_size(i) = max_dmif_buffer_allocated * graphics_dmif_size*/ - if (data->number_of_displays == 1) { - data->data_buffer_size[i] = bw_min2(bw_mul(bw_mul(bw_int_to_fixed(max_chunks_fbc_mode), bw_int_to_fixed(pixels_per_chunk)), bw_int_to_fixed(data->bytes_per_pixel[i])), bw_mul(bw_int_to_fixed(dceip->max_dmif_buffer_allocated), bw_int_to_fixed(dceip->graphics_dmif_size))); - } - else { - data->data_buffer_size[i] = bw_min2(bw_mul(bw_mul(bw_int_to_fixed(max_chunks_fbc_mode), bw_int_to_fixed(pixels_per_chunk)), bw_int_to_fixed(data->bytes_per_pixel[i])), bw_int_to_fixed(dceip->graphics_dmif_size)); - } - } - else { - /*the effective dmif buffer size in non-fbc mode is limited by the 16 entry chunk tracker*/ - if (data->number_of_displays == 1) { - data->data_buffer_size[i] = bw_min2(bw_mul(bw_mul(bw_int_to_fixed(data->max_chunks_non_fbc_mode[i]), bw_int_to_fixed(pixels_per_chunk)), bw_int_to_fixed(data->bytes_per_pixel[i])), bw_mul(bw_int_to_fixed(dceip->max_dmif_buffer_allocated), bw_int_to_fixed(dceip->graphics_dmif_size))); - } - else { - data->data_buffer_size[i] = bw_min2(bw_mul(bw_mul(bw_int_to_fixed(data->max_chunks_non_fbc_mode[i]), bw_int_to_fixed(pixels_per_chunk)), bw_int_to_fixed(data->bytes_per_pixel[i])), bw_int_to_fixed(dceip->graphics_dmif_size)); - } - } - break; - } - if (surface_type[i] == bw_def_display_write_back420_luma || surface_type[i] == bw_def_display_write_back420_chroma) { - data->memory_chunk_size_in_bytes[i] = bw_int_to_fixed(1024); - data->pipe_chunk_size_in_bytes[i] = bw_int_to_fixed(1024); - } - else { - data->memory_chunk_size_in_bytes[i] = bw_mul(bw_mul(bw_int_to_fixed(dceip->chunk_width), data->lines_interleaved_in_mem_access[i]), bw_int_to_fixed(data->bytes_per_pixel[i])); - data->pipe_chunk_size_in_bytes[i] = bw_mul(bw_mul(bw_int_to_fixed(dceip->chunk_width), bw_int_to_fixed(dceip->lines_interleaved_into_lb)), bw_int_to_fixed(data->bytes_per_pixel[i])); - } - } - } - data->min_dmif_size_in_time = bw_int_to_fixed(9999); - data->min_mcifwr_size_in_time = bw_int_to_fixed(9999); - for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { - if (data->enable[i]) { - if (surface_type[i] != bw_def_display_write_back420_luma && surface_type[i] != bw_def_display_write_back420_chroma) { - if (bw_ltn(bw_div(bw_div(bw_mul(data->data_buffer_size[i], data->bytes_per_request[i]), data->useful_bytes_per_request[i]), data->display_bandwidth[i]), data->min_dmif_size_in_time)) { - data->min_dmif_size_in_time = bw_div(bw_div(bw_mul(data->data_buffer_size[i], data->bytes_per_request[i]), data->useful_bytes_per_request[i]), data->display_bandwidth[i]); - } - } - else { - if (bw_ltn(bw_div(bw_div(bw_mul(data->data_buffer_size[i], data->bytes_per_request[i]), data->useful_bytes_per_request[i]), data->display_bandwidth[i]), data->min_mcifwr_size_in_time)) { - data->min_mcifwr_size_in_time = bw_div(bw_div(bw_mul(data->data_buffer_size[i], data->bytes_per_request[i]), data->useful_bytes_per_request[i]), data->display_bandwidth[i]); - } - } - } - } - data->total_requests_for_dmif_size = bw_int_to_fixed(0); - for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { - if (data->enable[i] && surface_type[i] != bw_def_display_write_back420_luma && surface_type[i] != bw_def_display_write_back420_chroma) { - data->total_requests_for_dmif_size = bw_add(data->total_requests_for_dmif_size, bw_div(data->data_buffer_size[i], data->useful_bytes_per_request[i])); - } - } - for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { - if (data->enable[i]) { - if (surface_type[i] != bw_def_display_write_back420_luma && surface_type[i] != bw_def_display_write_back420_chroma && dceip->limit_excessive_outstanding_dmif_requests && (data->number_of_displays > 1 || bw_mtn(data->total_requests_for_dmif_size, dceip->dmif_request_buffer_size))) { - data->adjusted_data_buffer_size[i] = bw_min2(data->data_buffer_size[i], bw_ceil2(bw_mul(data->min_dmif_size_in_time, data->display_bandwidth[i]), data->memory_chunk_size_in_bytes[i])); - } - else { - data->adjusted_data_buffer_size[i] = data->data_buffer_size[i]; - } - } - } - for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { - if (data->enable[i]) { - if ((data->number_of_displays == 1 && data->number_of_underlay_surfaces == 0)) { - /*set maximum chunk limit if only one graphic pipe is enabled*/ - data->outstanding_chunk_request_limit[i] = bw_int_to_fixed(127); - } - else { - data->outstanding_chunk_request_limit[i] = bw_ceil2(bw_div(data->adjusted_data_buffer_size[i], data->pipe_chunk_size_in_bytes[i]), bw_int_to_fixed(1)); - /*clamp maximum chunk limit in the graphic display pipe*/ - if ((i >= 4)) { - data->outstanding_chunk_request_limit[i] = bw_max2(bw_int_to_fixed(127), data->outstanding_chunk_request_limit[i]); - } - } - } - } - /*outstanding pte request limit*/ - /*in tiling mode with no rotation the sg pte requests are 8 useful pt_es, the sg row height is the page height and the sg page width x height is 64x64 for 8bpp, 64x32 for 16 bpp, 32x32 for 32 bpp*/ - /*in tiling mode with rotation the sg pte requests are only one useful pte, and the sg row height is also the page height, but the sg page width and height are swapped*/ - /*in linear mode the pte requests are 8 useful pt_es, the sg page width is 4096 divided by the bytes per pixel, the sg page height is 1, but there is just one row whose height is the lines of pte prefetching*/ - /*the outstanding pte request limit is obtained by multiplying the outstanding chunk request limit by the peak pte request to eviction limiting ratio, rounding up to integer, multiplying by the pte requests per chunk, and rounding up to integer again*/ - /*if not using peak pte request to eviction limiting, the outstanding pte request limit is the pte requests in the vblank*/ - /*the pte requests in the vblank is the product of the number of pte request rows times the number of pte requests in a row*/ - /*the number of pte requests in a row is the quotient of the source width divided by 256, multiplied by the pte requests per chunk, rounded up to even, multiplied by the scatter-gather row height and divided by the scatter-gather page height*/ - /*the pte requests per chunk is 256 divided by the scatter-gather page width and the useful pt_es per pte request*/ - if (data->number_of_displays > 1 || (bw_neq(data->rotation_angle[4], bw_int_to_fixed(0)) && bw_neq(data->rotation_angle[4], bw_int_to_fixed(180)))) { - data->peak_pte_request_to_eviction_ratio_limiting = dceip->peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display; - } - else { - data->peak_pte_request_to_eviction_ratio_limiting = dceip->peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation; - } - for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { - if (data->enable[i] && data->scatter_gather_enable_for_pipe[i] == 1) { - if (tiling_mode[i] == bw_def_linear) { - data->useful_pte_per_pte_request = bw_int_to_fixed(8); - data->scatter_gather_page_width[i] = bw_div(bw_int_to_fixed(4096), bw_int_to_fixed(data->bytes_per_pixel[i])); - data->scatter_gather_page_height[i] = bw_int_to_fixed(1); - data->scatter_gather_pte_request_rows = bw_int_to_fixed(1); - data->scatter_gather_row_height = bw_int_to_fixed(dceip->scatter_gather_lines_of_pte_prefetching_in_linear_mode); - } - else if (bw_equ(data->rotation_angle[i], bw_int_to_fixed(0)) || bw_equ(data->rotation_angle[i], bw_int_to_fixed(180))) { - data->useful_pte_per_pte_request = bw_int_to_fixed(8); - switch (data->bytes_per_pixel[i]) { - case 4: - data->scatter_gather_page_width[i] = bw_int_to_fixed(32); - data->scatter_gather_page_height[i] = bw_int_to_fixed(32); - break; - case 2: - data->scatter_gather_page_width[i] = bw_int_to_fixed(64); - data->scatter_gather_page_height[i] = bw_int_to_fixed(32); - break; - default: - data->scatter_gather_page_width[i] = bw_int_to_fixed(64); - data->scatter_gather_page_height[i] = bw_int_to_fixed(64); - break; - } - data->scatter_gather_pte_request_rows = bw_int_to_fixed(dceip->scatter_gather_pte_request_rows_in_tiling_mode); - data->scatter_gather_row_height = data->scatter_gather_page_height[i]; - } - else { - data->useful_pte_per_pte_request = bw_int_to_fixed(1); - switch (data->bytes_per_pixel[i]) { - case 4: - data->scatter_gather_page_width[i] = bw_int_to_fixed(32); - data->scatter_gather_page_height[i] = bw_int_to_fixed(32); - break; - case 2: - data->scatter_gather_page_width[i] = bw_int_to_fixed(32); - data->scatter_gather_page_height[i] = bw_int_to_fixed(64); - break; - default: - data->scatter_gather_page_width[i] = bw_int_to_fixed(64); - data->scatter_gather_page_height[i] = bw_int_to_fixed(64); - break; - } - data->scatter_gather_pte_request_rows = bw_int_to_fixed(dceip->scatter_gather_pte_request_rows_in_tiling_mode); - data->scatter_gather_row_height = data->scatter_gather_page_height[i]; - } - data->pte_request_per_chunk[i] = bw_div(bw_div(bw_int_to_fixed(dceip->chunk_width), data->scatter_gather_page_width[i]), data->useful_pte_per_pte_request); - data->scatter_gather_pte_requests_in_row[i] = bw_div(bw_mul(bw_ceil2(bw_mul(bw_div(data->source_width_rounded_up_to_chunks[i], bw_int_to_fixed(dceip->chunk_width)), data->pte_request_per_chunk[i]), bw_int_to_fixed(1)), data->scatter_gather_row_height), data->scatter_gather_page_height[i]); - data->scatter_gather_pte_requests_in_vblank = bw_mul(data->scatter_gather_pte_request_rows, data->scatter_gather_pte_requests_in_row[i]); - if (bw_equ(data->peak_pte_request_to_eviction_ratio_limiting, bw_int_to_fixed(0))) { - data->scatter_gather_pte_request_limit[i] = data->scatter_gather_pte_requests_in_vblank; - } - else { - data->scatter_gather_pte_request_limit[i] = bw_max2(dceip->minimum_outstanding_pte_request_limit, bw_min2(data->scatter_gather_pte_requests_in_vblank, bw_ceil2(bw_mul(bw_mul(bw_div(bw_ceil2(data->adjusted_data_buffer_size[i], data->memory_chunk_size_in_bytes[i]), data->memory_chunk_size_in_bytes[i]), data->pte_request_per_chunk[i]), data->peak_pte_request_to_eviction_ratio_limiting), bw_int_to_fixed(1)))); - } - } - } - /*pitch padding recommended for efficiency in linear mode*/ - /*in linear mode graphics or underlay with scatter gather, a pitch that is a multiple of the channel interleave (256 bytes) times the channel-bank rotation is not efficient*/ - /*if that is the case it is recommended to pad the pitch by at least 256 pixels*/ - data->inefficient_linear_pitch_in_bytes = bw_mul(bw_mul(bw_int_to_fixed(256), bw_int_to_fixed(vbios->number_of_dram_banks)), bw_int_to_fixed(data->number_of_dram_channels)); - - /*pixel transfer time*/ - /*the dmif and mcifwr yclk(pclk) required is the one that allows the transfer of all pipe's data buffer size in memory in the time for data transfer*/ - /*for dmif, pte and cursor requests have to be included.*/ - /*the dram data requirement is doubled when the data request size in bytes is less than the dram channel width times the burst size (8)*/ - /*the dram data requirement is also multiplied by the number of channels in the case of low power tiling*/ - /*the page close-open time is determined by trc and the number of page close-opens*/ - /*in tiled mode graphics or underlay with scatter-gather enabled the bytes per page close-open is the product of the memory line interleave times the maximum of the scatter-gather page width and the product of the tile width (8 pixels) times the number of channels times the number of banks.*/ - /*in linear mode graphics or underlay with scatter-gather enabled and inefficient pitch, the bytes per page close-open is the line request alternation slice, because different lines are in completely different 4k address bases.*/ - /*otherwise, the bytes page close-open is the chunk size because that is the arbitration slice.*/ - /*pte requests are grouped by pte requests per chunk if that is more than 1. each group costs a page close-open time for dmif reads*/ - /*cursor requests outstanding are limited to a group of two source lines. each group costs a page close-open time for dmif reads*/ - /*the display reads and writes time for data transfer is the minimum data or cursor buffer size in time minus the mc urgent latency*/ - /*the mc urgent latency is experienced more than one time if the number of dmif requests in the data buffer exceeds the request buffer size plus the request slots reserved for dmif in the dram channel arbiter queues*/ - /*the dispclk required is the maximum for all surfaces of the maximum of the source pixels for first output pixel times the throughput factor, divided by the pixels per dispclk, and divided by the minimum latency hiding minus the dram speed/p-state change latency minus the burst time, and the source pixels for last output pixel, times the throughput factor, divided by the pixels per dispclk, and divided by the minimum latency hiding minus the dram speed/p-state change latency minus the burst time, plus the active time.*/ - /*the data burst time is the maximum of the total page close-open time, total dmif/mcifwr buffer size in memory divided by the dram bandwidth, and the total dmif/mcifwr buffer size in memory divided by the 32 byte sclk data bus bandwidth, each multiplied by its efficiency.*/ - /*the source line transfer time is the maximum for all surfaces of the maximum of the burst time plus the urgent latency times the floor of the data required divided by the buffer size for the fist pixel, and the burst time plus the urgent latency times the floor of the data required divided by the buffer size for the last pixel plus the active time.*/ - /*the source pixels for the first output pixel is 512 if the scaler vertical filter initialization value is greater than 2, and it is 4 times the source width if it is greater than 4.*/ - /*the source pixels for the last output pixel is the source width times the scaler vertical filter initialization value rounded up to even*/ - /*the source data for these pixels is the number of pixels times the bytes per pixel times the bytes per request divided by the useful bytes per request.*/ - data->cursor_total_data = bw_int_to_fixed(0); - data->cursor_total_request_groups = bw_int_to_fixed(0); - data->scatter_gather_total_pte_requests = bw_int_to_fixed(0); - data->scatter_gather_total_pte_request_groups = bw_int_to_fixed(0); - for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { - if (data->enable[i]) { - data->cursor_total_data = bw_add(data->cursor_total_data, bw_mul(bw_mul(bw_int_to_fixed(2), data->cursor_width_pixels[i]), bw_int_to_fixed(4))); - if (dceip->large_cursor == 1) { - data->cursor_total_request_groups = bw_add(data->cursor_total_request_groups, bw_int_to_fixed((dceip->cursor_max_outstanding_group_num + 1))); - } - else { - data->cursor_total_request_groups = bw_add(data->cursor_total_request_groups, bw_ceil2(bw_div(data->cursor_width_pixels[i], dceip->cursor_chunk_width), bw_int_to_fixed(1))); - } - if (data->scatter_gather_enable_for_pipe[i]) { - data->scatter_gather_total_pte_requests = bw_add(data->scatter_gather_total_pte_requests, data->scatter_gather_pte_request_limit[i]); - data->scatter_gather_total_pte_request_groups = bw_add(data->scatter_gather_total_pte_request_groups, bw_ceil2(bw_div(data->scatter_gather_pte_request_limit[i], bw_ceil2(data->pte_request_per_chunk[i], bw_int_to_fixed(1))), bw_int_to_fixed(1))); - } - } - } - data->tile_width_in_pixels = bw_int_to_fixed(8); - data->dmif_total_number_of_data_request_page_close_open = bw_int_to_fixed(0); - data->mcifwr_total_number_of_data_request_page_close_open = bw_int_to_fixed(0); - for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { - if (data->enable[i]) { - if (data->scatter_gather_enable_for_pipe[i] == 1 && tiling_mode[i] != bw_def_linear) { - data->bytes_per_page_close_open = bw_mul(data->lines_interleaved_in_mem_access[i], bw_max2(bw_mul(bw_mul(bw_mul(bw_int_to_fixed(data->bytes_per_pixel[i]), data->tile_width_in_pixels), bw_int_to_fixed(vbios->number_of_dram_banks)), bw_int_to_fixed(data->number_of_dram_channels)), bw_mul(bw_int_to_fixed(data->bytes_per_pixel[i]), data->scatter_gather_page_width[i]))); - } - else if (data->scatter_gather_enable_for_pipe[i] == 1 && tiling_mode[i] == bw_def_linear && bw_equ(bw_mod((bw_mul(data->pitch_in_pixels_after_surface_type[i], bw_int_to_fixed(data->bytes_per_pixel[i]))), data->inefficient_linear_pitch_in_bytes), bw_int_to_fixed(0))) { - data->bytes_per_page_close_open = dceip->linear_mode_line_request_alternation_slice; - } - else { - data->bytes_per_page_close_open = data->memory_chunk_size_in_bytes[i]; - } - if (surface_type[i] != bw_def_display_write_back420_luma && surface_type[i] != bw_def_display_write_back420_chroma) { - data->dmif_total_number_of_data_request_page_close_open = bw_add(data->dmif_total_number_of_data_request_page_close_open, bw_div(bw_ceil2(data->adjusted_data_buffer_size[i], data->memory_chunk_size_in_bytes[i]), data->bytes_per_page_close_open)); - } - else { - data->mcifwr_total_number_of_data_request_page_close_open = bw_add(data->mcifwr_total_number_of_data_request_page_close_open, bw_div(bw_ceil2(data->adjusted_data_buffer_size[i], data->memory_chunk_size_in_bytes[i]), data->bytes_per_page_close_open)); - } - } - } - data->dmif_total_page_close_open_time = bw_div(bw_mul((bw_add(bw_add(data->dmif_total_number_of_data_request_page_close_open, data->scatter_gather_total_pte_request_groups), data->cursor_total_request_groups)), vbios->trc), bw_int_to_fixed(1000)); - data->mcifwr_total_page_close_open_time = bw_div(bw_mul(data->mcifwr_total_number_of_data_request_page_close_open, vbios->trc), bw_int_to_fixed(1000)); - for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { - if (data->enable[i]) { - data->adjusted_data_buffer_size_in_memory[i] = bw_div(bw_mul(data->adjusted_data_buffer_size[i], data->bytes_per_request[i]), data->useful_bytes_per_request[i]); - } - } - data->total_requests_for_adjusted_dmif_size = bw_int_to_fixed(0); - for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { - if (data->enable[i]) { - if (surface_type[i] != bw_def_display_write_back420_luma && surface_type[i] != bw_def_display_write_back420_chroma) { - data->total_requests_for_adjusted_dmif_size = bw_add(data->total_requests_for_adjusted_dmif_size, bw_div(data->adjusted_data_buffer_size[i], data->useful_bytes_per_request[i])); - } - } - } - data->total_dmifmc_urgent_trips = bw_ceil2(bw_div(data->total_requests_for_adjusted_dmif_size, (bw_add(dceip->dmif_request_buffer_size, bw_int_to_fixed(vbios->number_of_request_slots_gmc_reserves_for_dmif_per_channel * data->number_of_dram_channels)))), bw_int_to_fixed(1)); - data->total_dmifmc_urgent_latency = bw_mul(vbios->dmifmc_urgent_latency, data->total_dmifmc_urgent_trips); - data->total_display_reads_required_data = bw_int_to_fixed(0); - data->total_display_reads_required_dram_access_data = bw_int_to_fixed(0); - data->total_display_writes_required_data = bw_int_to_fixed(0); - data->total_display_writes_required_dram_access_data = bw_int_to_fixed(0); - for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { - if (data->enable[i]) { - if (surface_type[i] != bw_def_display_write_back420_luma && surface_type[i] != bw_def_display_write_back420_chroma) { - data->display_reads_required_data = data->adjusted_data_buffer_size_in_memory[i]; - /*for hbm memories, each channel is split into 2 pseudo-channels that are each 64 bits in width. each*/ - /*pseudo-channel may be read independently of one another.*/ - /*the read burst length (bl) for hbm memories is 4, so each read command will access 32 bytes of data.*/ - /*the 64 or 32 byte sized data is stored in one pseudo-channel.*/ - /*it will take 4 memclk cycles or 8 yclk cycles to fetch 64 bytes of data from the hbm memory (2 read commands).*/ - /*it will take 2 memclk cycles or 4 yclk cycles to fetch 32 bytes of data from the hbm memory (1 read command).*/ - /*for gddr5/ddr4 memories, there is additional overhead if the size of the request is smaller than 64 bytes.*/ - /*the read burst length (bl) for gddr5/ddr4 memories is 8, regardless of the size of the data request.*/ - /*therefore it will require 8 cycles to fetch 64 or 32 bytes of data from the memory.*/ - /*the memory efficiency will be 50% for the 32 byte sized data.*/ - if (vbios->memory_type == bw_def_hbm) { - data->display_reads_required_dram_access_data = data->adjusted_data_buffer_size_in_memory[i]; - } - else { - data->display_reads_required_dram_access_data = bw_mul(data->adjusted_data_buffer_size_in_memory[i], bw_ceil2(bw_div(bw_int_to_fixed((8 * vbios->dram_channel_width_in_bits / 8)), data->bytes_per_request[i]), bw_int_to_fixed(1))); - } - data->total_display_reads_required_data = bw_add(data->total_display_reads_required_data, data->display_reads_required_data); - data->total_display_reads_required_dram_access_data = bw_add(data->total_display_reads_required_dram_access_data, data->display_reads_required_dram_access_data); - } - else { - data->total_display_writes_required_data = bw_add(data->total_display_writes_required_data, data->adjusted_data_buffer_size_in_memory[i]); - data->total_display_writes_required_dram_access_data = bw_add(data->total_display_writes_required_dram_access_data, bw_mul(data->adjusted_data_buffer_size_in_memory[i], bw_ceil2(bw_div(bw_int_to_fixed(vbios->dram_channel_width_in_bits), data->bytes_per_request[i]), bw_int_to_fixed(1)))); - } - } - } - data->total_display_reads_required_data = bw_add(bw_add(data->total_display_reads_required_data, data->cursor_total_data), bw_mul(data->scatter_gather_total_pte_requests, bw_int_to_fixed(64))); - data->total_display_reads_required_dram_access_data = bw_add(bw_add(data->total_display_reads_required_dram_access_data, data->cursor_total_data), bw_mul(data->scatter_gather_total_pte_requests, bw_int_to_fixed(64))); - for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { - if (data->enable[i]) { - if (bw_mtn(data->v_filter_init[i], bw_int_to_fixed(4))) { - data->src_pixels_for_first_output_pixel[i] = bw_mul(bw_int_to_fixed(4), data->source_width_rounded_up_to_chunks[i]); - } - else { - if (bw_mtn(data->v_filter_init[i], bw_int_to_fixed(2))) { - data->src_pixels_for_first_output_pixel[i] = bw_int_to_fixed(512); - } - else { - data->src_pixels_for_first_output_pixel[i] = bw_int_to_fixed(0); - } - } - data->src_data_for_first_output_pixel[i] = bw_div(bw_mul(bw_mul(data->src_pixels_for_first_output_pixel[i], bw_int_to_fixed(data->bytes_per_pixel[i])), data->bytes_per_request[i]), data->useful_bytes_per_request[i]); - data->src_pixels_for_last_output_pixel[i] = bw_mul(data->source_width_rounded_up_to_chunks[i], bw_max2(bw_ceil2(data->v_filter_init[i], bw_int_to_fixed(dceip->lines_interleaved_into_lb)), bw_mul(bw_ceil2(data->vsr[i], bw_int_to_fixed(dceip->lines_interleaved_into_lb)), data->horizontal_blank_and_chunk_granularity_factor[i]))); - data->src_data_for_last_output_pixel[i] = bw_div(bw_mul(bw_mul(bw_mul(data->source_width_rounded_up_to_chunks[i], bw_max2(bw_ceil2(data->v_filter_init[i], bw_int_to_fixed(dceip->lines_interleaved_into_lb)), data->lines_interleaved_in_mem_access[i])), bw_int_to_fixed(data->bytes_per_pixel[i])), data->bytes_per_request[i]), data->useful_bytes_per_request[i]); - data->active_time[i] = bw_div(bw_div(data->source_width_rounded_up_to_chunks[i], data->hsr[i]), data->pixel_rate[i]); - } - } - for (i = 0; i <= 2; i++) { - for (j = 0; j <= 7; j++) { - data->dmif_burst_time[i][j] = bw_max3(data->dmif_total_page_close_open_time, bw_div(data->total_display_reads_required_dram_access_data, (bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[i]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels)))), bw_div(data->total_display_reads_required_data, (bw_mul(bw_mul(sclk[j], vbios->data_return_bus_width), bw_int_to_fixed(bus_efficiency))))); - if (data->d1_display_write_back_dwb_enable == 1) { - data->mcifwr_burst_time[i][j] = bw_max3(data->mcifwr_total_page_close_open_time, bw_div(data->total_display_writes_required_dram_access_data, (bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[i]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_wrchannels)))), bw_div(data->total_display_writes_required_data, (bw_mul(bw_mul(sclk[j], vbios->data_return_bus_width), bw_int_to_fixed(bus_efficiency))))); - } - } - } - for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { - for (j = 0; j <= 2; j++) { - for (k = 0; k <= 7; k++) { - if (data->enable[i]) { - if (surface_type[i] != bw_def_display_write_back420_luma && surface_type[i] != bw_def_display_write_back420_chroma) { - /*time to transfer data from the dmif buffer to the lb. since the mc to dmif transfer time overlaps*/ - /*with the dmif to lb transfer time, only time to transfer the last chunk is considered.*/ - data->dmif_buffer_transfer_time[i] = bw_mul(data->source_width_rounded_up_to_chunks[i], (bw_div(dceip->lb_write_pixels_per_dispclk, (bw_div(vbios->low_voltage_max_dispclk, dceip->display_pipe_throughput_factor))))); - data->line_source_transfer_time[i][j][k] = bw_max2(bw_mul((bw_add(data->total_dmifmc_urgent_latency, data->dmif_burst_time[j][k])), bw_floor2(bw_div(data->src_data_for_first_output_pixel[i], data->adjusted_data_buffer_size_in_memory[i]), bw_int_to_fixed(1))), bw_sub(bw_add(bw_mul((bw_add(data->total_dmifmc_urgent_latency, data->dmif_burst_time[j][k])), bw_floor2(bw_div(data->src_data_for_last_output_pixel[i], data->adjusted_data_buffer_size_in_memory[i]), bw_int_to_fixed(1))), data->dmif_buffer_transfer_time[i]), data->active_time[i])); - /*during an mclk switch the requests from the dce ip are stored in the gmc/arb. these requests should be serviced immediately*/ - /*after the mclk switch sequence and not incur an urgent latency penalty. it is assumed that the gmc/arb can hold up to 256 requests*/ - /*per memory channel. if the dce ip is urgent after the mclk switch sequence, all pending requests and subsequent requests should be*/ - /*immediately serviced without a gap in the urgent requests.*/ - /*the latency incurred would be the time to issue the requests and return the data for the first or last output pixel.*/ - if (surface_type[i] == bw_def_graphics) { - switch (data->lb_bpc[i]) { - case 6: - data->v_scaler_efficiency = dceip->graphics_vscaler_efficiency6_bit_per_component; - break; - case 8: - data->v_scaler_efficiency = dceip->graphics_vscaler_efficiency8_bit_per_component; - break; - case 10: - data->v_scaler_efficiency = dceip->graphics_vscaler_efficiency10_bit_per_component; - break; - default: - data->v_scaler_efficiency = dceip->graphics_vscaler_efficiency12_bit_per_component; - break; - } - if (data->use_alpha[i] == 1) { - data->v_scaler_efficiency = bw_min2(data->v_scaler_efficiency, dceip->alpha_vscaler_efficiency); - } - } - else { - switch (data->lb_bpc[i]) { - case 6: - data->v_scaler_efficiency = dceip->underlay_vscaler_efficiency6_bit_per_component; - break; - case 8: - data->v_scaler_efficiency = dceip->underlay_vscaler_efficiency8_bit_per_component; - break; - case 10: - data->v_scaler_efficiency = dceip->underlay_vscaler_efficiency10_bit_per_component; - break; - default: - data->v_scaler_efficiency = bw_int_to_fixed(3); - break; - } - } - if (dceip->pre_downscaler_enabled && bw_mtn(data->hsr[i], bw_int_to_fixed(1))) { - data->scaler_limits_factor = bw_max2(bw_div(data->v_taps[i], data->v_scaler_efficiency), bw_div(data->source_width_rounded_up_to_chunks[i], data->h_total[i])); - } - else { - data->scaler_limits_factor = bw_max3(bw_int_to_fixed(1), bw_ceil2(bw_div(data->h_taps[i], bw_int_to_fixed(4)), bw_int_to_fixed(1)), bw_mul(data->hsr[i], bw_max2(bw_div(data->v_taps[i], data->v_scaler_efficiency), bw_int_to_fixed(1)))); - } - data->dram_speed_change_line_source_transfer_time[i][j][k] = bw_mul(bw_int_to_fixed(2), bw_max2((bw_add((bw_div(data->src_data_for_first_output_pixel[i], bw_min2(bw_mul(data->bytes_per_request[i], sclk[k]), bw_div(bw_mul(bw_mul(data->bytes_per_request[i], data->pixel_rate[i]), data->scaler_limits_factor), bw_int_to_fixed(2))))), (bw_mul(data->dmif_burst_time[j][k], bw_floor2(bw_div(data->src_data_for_first_output_pixel[i], data->adjusted_data_buffer_size_in_memory[i]), bw_int_to_fixed(1)))))), (bw_add((bw_div(data->src_data_for_last_output_pixel[i], bw_min2(bw_mul(data->bytes_per_request[i], sclk[k]), bw_div(bw_mul(bw_mul(data->bytes_per_request[i], data->pixel_rate[i]), data->scaler_limits_factor), bw_int_to_fixed(2))))), (bw_sub(bw_mul(data->dmif_burst_time[j][k], bw_floor2(bw_div(data->src_data_for_last_output_pixel[i], data->adjusted_data_buffer_size_in_memory[i]), bw_int_to_fixed(1))), data->active_time[i])))))); - } - else { - data->line_source_transfer_time[i][j][k] = bw_max2(bw_mul((bw_add(vbios->mcifwrmc_urgent_latency, data->mcifwr_burst_time[j][k])), bw_floor2(bw_div(data->src_data_for_first_output_pixel[i], data->adjusted_data_buffer_size_in_memory[i]), bw_int_to_fixed(1))), bw_sub(bw_mul((bw_add(vbios->mcifwrmc_urgent_latency, data->mcifwr_burst_time[j][k])), bw_floor2(bw_div(data->src_data_for_last_output_pixel[i], data->adjusted_data_buffer_size_in_memory[i]), bw_int_to_fixed(1))), data->active_time[i])); - /*during an mclk switch the requests from the dce ip are stored in the gmc/arb. these requests should be serviced immediately*/ - /*after the mclk switch sequence and not incur an urgent latency penalty. it is assumed that the gmc/arb can hold up to 256 requests*/ - /*per memory channel. if the dce ip is urgent after the mclk switch sequence, all pending requests and subsequent requests should be*/ - /*immediately serviced without a gap in the urgent requests.*/ - /*the latency incurred would be the time to issue the requests and return the data for the first or last output pixel.*/ - data->dram_speed_change_line_source_transfer_time[i][j][k] = bw_max2((bw_add((bw_div(data->src_data_for_first_output_pixel[i], bw_min2(bw_mul(data->bytes_per_request[i], sclk[k]), bw_div(bw_mul(data->bytes_per_request[i], vbios->low_voltage_max_dispclk), bw_int_to_fixed(2))))), (bw_mul(data->mcifwr_burst_time[j][k], bw_floor2(bw_div(data->src_data_for_first_output_pixel[i], data->adjusted_data_buffer_size_in_memory[i]), bw_int_to_fixed(1)))))), (bw_add((bw_div(data->src_data_for_last_output_pixel[i], bw_min2(bw_mul(data->bytes_per_request[i], sclk[k]), bw_div(bw_mul(data->bytes_per_request[i], vbios->low_voltage_max_dispclk), bw_int_to_fixed(2))))), (bw_sub(bw_mul(data->mcifwr_burst_time[j][k], bw_floor2(bw_div(data->src_data_for_last_output_pixel[i], data->adjusted_data_buffer_size_in_memory[i]), bw_int_to_fixed(1))), data->active_time[i]))))); - } - } - } - } - } - /*cpu c-state and p-state change enable*/ - /*for cpu p-state change to be possible for a yclk(pclk) and sclk level the dispclk required has to be enough for the blackout duration*/ - /*for cpu c-state change to be possible for a yclk(pclk) and sclk level the dispclk required has to be enough for the blackout duration and recovery*/ - /*condition for the blackout duration:*/ - /* minimum latency hiding > blackout duration + dmif burst time + line source transfer time*/ - /*condition for the blackout recovery:*/ - /* recovery time > dmif burst time + 2 * urgent latency*/ - /* recovery time > (display bw * blackout duration + (2 * urgent latency + dmif burst time)*dispclk - dmif size )*/ - /* / (dispclk - display bw)*/ - /*the minimum latency hiding is the minimum for all pipes of one screen line time, plus one more line time if doing lb prefetch, plus the dmif data buffer size equivalent in time, minus the urgent latency.*/ - /*the minimum latency hiding is further limited by the cursor. the cursor latency hiding is the number of lines of the cursor buffer, minus one if the downscaling is less than two, or minus three if it is more*/ - for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { - if (data->enable[i]) { - if ((bw_equ(dceip->stutter_and_dram_clock_state_change_gated_before_cursor, bw_int_to_fixed(0)) && bw_mtn(data->cursor_width_pixels[i], bw_int_to_fixed(0)))) { - if (bw_ltn(data->vsr[i], bw_int_to_fixed(2))) { - data->cursor_latency_hiding[i] = bw_div(bw_div(bw_mul((bw_sub(dceip->cursor_dcp_buffer_lines, bw_int_to_fixed(1))), data->h_total[i]), data->vsr[i]), data->pixel_rate[i]); - } - else { - data->cursor_latency_hiding[i] = bw_div(bw_div(bw_mul((bw_sub(dceip->cursor_dcp_buffer_lines, bw_int_to_fixed(3))), data->h_total[i]), data->vsr[i]), data->pixel_rate[i]); - } - } - else { - data->cursor_latency_hiding[i] = bw_int_to_fixed(9999); - } - } - } - for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { - if (data->enable[i]) { - if (dceip->graphics_lb_nodownscaling_multi_line_prefetching == 1 && (bw_equ(data->vsr[i], bw_int_to_fixed(1)) || (bw_leq(data->vsr[i], bw_frc_to_fixed(8, 10)) && bw_leq(data->v_taps[i], bw_int_to_fixed(2)) && data->lb_bpc[i] == 8)) && surface_type[i] == bw_def_graphics) { - data->minimum_latency_hiding[i] = bw_sub(bw_div(bw_mul((bw_div((bw_add(bw_sub(data->lb_partitions[i], bw_int_to_fixed(1)), bw_div(bw_div(data->data_buffer_size[i], bw_int_to_fixed(data->bytes_per_pixel[i])), data->source_width_pixels[i]))), data->vsr[i])), data->h_total[i]), data->pixel_rate[i]), data->total_dmifmc_urgent_latency); - } - else { - data->minimum_latency_hiding[i] = bw_sub(bw_div(bw_mul((bw_div((bw_add(bw_int_to_fixed(1 + data->line_buffer_prefetch[i]), bw_div(bw_div(data->data_buffer_size[i], bw_int_to_fixed(data->bytes_per_pixel[i])), data->source_width_pixels[i]))), data->vsr[i])), data->h_total[i]), data->pixel_rate[i]), data->total_dmifmc_urgent_latency); - } - data->minimum_latency_hiding_with_cursor[i] = bw_min2(data->minimum_latency_hiding[i], data->cursor_latency_hiding[i]); - } - } - for (i = 0; i <= 2; i++) { - for (j = 0; j <= 7; j++) { - data->blackout_duration_margin[i][j] = bw_int_to_fixed(9999); - data->dispclk_required_for_blackout_duration[i][j] = bw_int_to_fixed(0); - data->dispclk_required_for_blackout_recovery[i][j] = bw_int_to_fixed(0); - for (k = 0; k <= maximum_number_of_surfaces - 1; k++) { - if (data->enable[k] && bw_mtn(vbios->blackout_duration, bw_int_to_fixed(0))) { - if (surface_type[k] != bw_def_display_write_back420_luma && surface_type[k] != bw_def_display_write_back420_chroma) { - data->blackout_duration_margin[i][j] = bw_min2(data->blackout_duration_margin[i][j], bw_sub(bw_sub(bw_sub(data->minimum_latency_hiding_with_cursor[k], vbios->blackout_duration), data->dmif_burst_time[i][j]), data->line_source_transfer_time[k][i][j])); - data->dispclk_required_for_blackout_duration[i][j] = bw_max3(data->dispclk_required_for_blackout_duration[i][j], bw_div(bw_div(bw_mul(data->src_pixels_for_first_output_pixel[k], dceip->display_pipe_throughput_factor), dceip->lb_write_pixels_per_dispclk), (bw_sub(bw_sub(data->minimum_latency_hiding_with_cursor[k], vbios->blackout_duration), data->dmif_burst_time[i][j]))), bw_div(bw_div(bw_mul(data->src_pixels_for_last_output_pixel[k], dceip->display_pipe_throughput_factor), dceip->lb_write_pixels_per_dispclk), (bw_add(bw_sub(bw_sub(data->minimum_latency_hiding_with_cursor[k], vbios->blackout_duration), data->dmif_burst_time[i][j]), data->active_time[k])))); - if (bw_leq(vbios->maximum_blackout_recovery_time, bw_add(bw_mul(bw_int_to_fixed(2), data->total_dmifmc_urgent_latency), data->dmif_burst_time[i][j]))) { - data->dispclk_required_for_blackout_recovery[i][j] = bw_int_to_fixed(9999); - } - else if (bw_ltn(data->adjusted_data_buffer_size[k], bw_mul(bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]), (bw_add(vbios->blackout_duration, bw_add(bw_mul(bw_int_to_fixed(2), data->total_dmifmc_urgent_latency), data->dmif_burst_time[i][j])))))) { - data->dispclk_required_for_blackout_recovery[i][j] = bw_max2(data->dispclk_required_for_blackout_recovery[i][j], bw_div(bw_mul(bw_div(bw_div((bw_sub(bw_mul(bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]), (bw_add(vbios->blackout_duration, vbios->maximum_blackout_recovery_time))), data->adjusted_data_buffer_size[k])), bw_int_to_fixed(data->bytes_per_pixel[k])), (bw_sub(vbios->maximum_blackout_recovery_time, bw_sub(bw_mul(bw_int_to_fixed(2), data->total_dmifmc_urgent_latency), data->dmif_burst_time[i][j])))), data->latency_hiding_lines[k]), data->lines_interleaved_in_mem_access[k])); - } - } - else { - data->blackout_duration_margin[i][j] = bw_min2(data->blackout_duration_margin[i][j], bw_sub(bw_sub(bw_sub(bw_sub(data->minimum_latency_hiding_with_cursor[k], vbios->blackout_duration), data->dmif_burst_time[i][j]), data->mcifwr_burst_time[i][j]), data->line_source_transfer_time[k][i][j])); - data->dispclk_required_for_blackout_duration[i][j] = bw_max3(data->dispclk_required_for_blackout_duration[i][j], bw_div(bw_div(bw_mul(data->src_pixels_for_first_output_pixel[k], dceip->display_pipe_throughput_factor), dceip->lb_write_pixels_per_dispclk), (bw_sub(bw_sub(bw_sub(data->minimum_latency_hiding_with_cursor[k], vbios->blackout_duration), data->dmif_burst_time[i][j]), data->mcifwr_burst_time[i][j]))), bw_div(bw_div(bw_mul(data->src_pixels_for_last_output_pixel[k], dceip->display_pipe_throughput_factor), dceip->lb_write_pixels_per_dispclk), (bw_add(bw_sub(bw_sub(bw_sub(data->minimum_latency_hiding_with_cursor[k], vbios->blackout_duration), data->dmif_burst_time[i][j]), data->mcifwr_burst_time[i][j]), data->active_time[k])))); - if (bw_ltn(vbios->maximum_blackout_recovery_time, bw_add(bw_add(bw_mul(bw_int_to_fixed(2), vbios->mcifwrmc_urgent_latency), data->dmif_burst_time[i][j]), data->mcifwr_burst_time[i][j]))) { - data->dispclk_required_for_blackout_recovery[i][j] = bw_int_to_fixed(9999); - } - else if (bw_ltn(data->adjusted_data_buffer_size[k], bw_mul(bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]), (bw_add(vbios->blackout_duration, bw_add(bw_mul(bw_int_to_fixed(2), data->total_dmifmc_urgent_latency), data->dmif_burst_time[i][j])))))) { - data->dispclk_required_for_blackout_recovery[i][j] = bw_max2(data->dispclk_required_for_blackout_recovery[i][j], bw_div(bw_mul(bw_div(bw_div((bw_sub(bw_mul(bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]), (bw_add(vbios->blackout_duration, vbios->maximum_blackout_recovery_time))), data->adjusted_data_buffer_size[k])), bw_int_to_fixed(data->bytes_per_pixel[k])), (bw_sub(vbios->maximum_blackout_recovery_time, (bw_add(bw_mul(bw_int_to_fixed(2), data->total_dmifmc_urgent_latency), data->dmif_burst_time[i][j]))))), data->latency_hiding_lines[k]), data->lines_interleaved_in_mem_access[k])); - } - } - } - } - } - } - if (bw_mtn(data->blackout_duration_margin[high][s_high], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[high][s_high], vbios->high_voltage_max_dispclk)) { - data->cpup_state_change_enable = bw_def_yes; - if (bw_ltn(data->dispclk_required_for_blackout_recovery[high][s_high], vbios->high_voltage_max_dispclk)) { - data->cpuc_state_change_enable = bw_def_yes; - } - else { - data->cpuc_state_change_enable = bw_def_no; - } - } - else { - data->cpup_state_change_enable = bw_def_no; - data->cpuc_state_change_enable = bw_def_no; - } - /*nb p-state change enable*/ - /*for dram speed/p-state change to be possible for a yclk(pclk) and sclk level there has to be positive margin and the dispclk required has to be*/ - /*below the maximum.*/ - /*the dram speed/p-state change margin is the minimum for all surfaces of the maximum latency hiding minus the dram speed/p-state change latency,*/ - /*minus the dmif burst time, minus the source line transfer time*/ - /*the maximum latency hiding is the minimum latency hiding plus one source line used for de-tiling in the line buffer, plus half the urgent latency*/ - /*if stutter and dram clock state change are gated before cursor then the cursor latency hiding does not limit stutter or dram clock state change*/ - for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { - if (data->enable[i]) { - if ((dceip->graphics_lb_nodownscaling_multi_line_prefetching == 1)) { - data->maximum_latency_hiding[i] = bw_add(data->minimum_latency_hiding[i], bw_mul(bw_frc_to_fixed(8, 10), data->total_dmifmc_urgent_latency)); - } - else { - /*maximum_latency_hiding(i) = minimum_latency_hiding(i) + 1 / vsr(i) * h_total(i) / pixel_rate(i) + 0.5 * total_dmifmc_urgent_latency*/ - data->maximum_latency_hiding[i] = bw_add(data->minimum_latency_hiding[i], bw_mul(bw_frc_to_fixed(8, 10), data->total_dmifmc_urgent_latency)); - } - data->maximum_latency_hiding_with_cursor[i] = bw_min2(data->maximum_latency_hiding[i], data->cursor_latency_hiding[i]); - } - } - /*initialize variables*/ - number_of_displays_enabled = 0; - number_of_displays_enabled_with_margin = 0; - for (k = 0; k < maximum_number_of_surfaces; k++) { - if (data->enable[k]) { - number_of_displays_enabled = number_of_displays_enabled + 1; - } - } - data->display_pstate_change_enable[maximum_number_of_surfaces - 1] = 0; - for (i = 0; i <= 2; i++) { - for (j = 0; j <= 7; j++) { - data->min_dram_speed_change_margin[i][j] = bw_int_to_fixed(9999); - data->dram_speed_change_margin = bw_int_to_fixed(9999); - data->dispclk_required_for_dram_speed_change[i][j] = bw_int_to_fixed(0); - data->num_displays_with_margin[i][j] = 0; - for (k = 0; k <= maximum_number_of_surfaces - 1; k++) { - if (data->enable[k]) { - if (surface_type[k] != bw_def_display_write_back420_luma && surface_type[k] != bw_def_display_write_back420_chroma) { - data->dram_speed_change_margin = bw_sub(bw_sub(bw_sub(data->maximum_latency_hiding_with_cursor[k], vbios->nbp_state_change_latency), data->dmif_burst_time[i][j]), data->dram_speed_change_line_source_transfer_time[k][i][j]); - if ((bw_mtn(data->dram_speed_change_margin, bw_int_to_fixed(0)) && bw_ltn(data->dram_speed_change_margin, bw_int_to_fixed(9999)))) { - /*determine the minimum dram clock change margin for each set of clock frequencies*/ - data->min_dram_speed_change_margin[i][j] = bw_min2(data->min_dram_speed_change_margin[i][j], data->dram_speed_change_margin); - /*compute the maximum clock frequuency required for the dram clock change at each set of clock frequencies*/ - data->dispclk_required_for_dram_speed_change[i][j] = bw_max3(data->dispclk_required_for_dram_speed_change[i][j], bw_div(bw_div(bw_mul(data->src_pixels_for_first_output_pixel[k], dceip->display_pipe_throughput_factor), dceip->lb_write_pixels_per_dispclk), (bw_sub(bw_sub(bw_sub(data->maximum_latency_hiding_with_cursor[k], vbios->nbp_state_change_latency), data->dmif_burst_time[i][j]), data->dram_speed_change_line_source_transfer_time[k][i][j]))), bw_div(bw_div(bw_mul(data->src_pixels_for_last_output_pixel[k], dceip->display_pipe_throughput_factor), dceip->lb_write_pixels_per_dispclk), (bw_add(bw_sub(bw_sub(bw_sub(data->maximum_latency_hiding_with_cursor[k], vbios->nbp_state_change_latency), data->dmif_burst_time[i][j]), data->dram_speed_change_line_source_transfer_time[k][i][j]), data->active_time[k])))); - if ((bw_ltn(data->dispclk_required_for_dram_speed_change[i][j], vbios->high_voltage_max_dispclk))) { - data->display_pstate_change_enable[k] = 1; - data->num_displays_with_margin[i][j] = data->num_displays_with_margin[i][j] + 1; - } - } - } - else { - data->dram_speed_change_margin = bw_sub(bw_sub(bw_sub(bw_sub(data->maximum_latency_hiding_with_cursor[k], vbios->nbp_state_change_latency), data->dmif_burst_time[i][j]), data->mcifwr_burst_time[i][j]), data->dram_speed_change_line_source_transfer_time[k][i][j]); - if ((bw_mtn(data->dram_speed_change_margin, bw_int_to_fixed(0)) && bw_ltn(data->dram_speed_change_margin, bw_int_to_fixed(9999)))) { - /*determine the minimum dram clock change margin for each display pipe*/ - data->min_dram_speed_change_margin[i][j] = bw_min2(data->min_dram_speed_change_margin[i][j], data->dram_speed_change_margin); - /*compute the maximum clock frequuency required for the dram clock change at each set of clock frequencies*/ - data->dispclk_required_for_dram_speed_change[i][j] = bw_max3(data->dispclk_required_for_dram_speed_change[i][j], bw_div(bw_div(bw_mul(data->src_pixels_for_first_output_pixel[k], dceip->display_pipe_throughput_factor), dceip->lb_write_pixels_per_dispclk), (bw_sub(bw_sub(bw_sub(bw_sub(data->maximum_latency_hiding_with_cursor[k], vbios->nbp_state_change_latency), data->dmif_burst_time[i][j]), data->dram_speed_change_line_source_transfer_time[k][i][j]), data->mcifwr_burst_time[i][j]))), bw_div(bw_div(bw_mul(data->src_pixels_for_last_output_pixel[k], dceip->display_pipe_throughput_factor), dceip->lb_write_pixels_per_dispclk), (bw_add(bw_sub(bw_sub(bw_sub(bw_sub(data->maximum_latency_hiding_with_cursor[k], vbios->nbp_state_change_latency), data->dmif_burst_time[i][j]), data->dram_speed_change_line_source_transfer_time[k][i][j]), data->mcifwr_burst_time[i][j]), data->active_time[k])))); - if ((bw_ltn(data->dispclk_required_for_dram_speed_change[i][j], vbios->high_voltage_max_dispclk))) { - data->display_pstate_change_enable[k] = 1; - data->num_displays_with_margin[i][j] = data->num_displays_with_margin[i][j] + 1; - } - } - } - } - } - } - } - /*determine the number of displays with margin to switch in the v_active region*/ - for (k = 0; k <= maximum_number_of_surfaces - 1; k++) { - if ((data->enable[k] == 1 && data->display_pstate_change_enable[k] == 1)) { - number_of_displays_enabled_with_margin = number_of_displays_enabled_with_margin + 1; - } - } - /*determine the number of displays that don't have any dram clock change margin, but*/ - /*have the same resolution. these displays can switch in a common vblank region if*/ - /*their frames are aligned.*/ - data->min_vblank_dram_speed_change_margin = bw_int_to_fixed(9999); - for (k = 0; k <= maximum_number_of_surfaces - 1; k++) { - if (data->enable[k]) { - if (surface_type[k] != bw_def_display_write_back420_luma && surface_type[k] != bw_def_display_write_back420_chroma) { - data->v_blank_dram_speed_change_margin[k] = bw_sub(bw_sub(bw_sub(bw_div(bw_mul((bw_sub(data->v_total[k], bw_sub(bw_div(data->src_height[k], data->v_scale_ratio[k]), bw_int_to_fixed(4)))), data->h_total[k]), data->pixel_rate[k]), vbios->nbp_state_change_latency), data->dmif_burst_time[low][s_low]), data->dram_speed_change_line_source_transfer_time[k][low][s_low]); - data->min_vblank_dram_speed_change_margin = bw_min2(data->min_vblank_dram_speed_change_margin, data->v_blank_dram_speed_change_margin[k]); - } - else { - data->v_blank_dram_speed_change_margin[k] = bw_sub(bw_sub(bw_sub(bw_sub(bw_div(bw_mul((bw_sub(data->v_total[k], bw_sub(bw_div(data->src_height[k], data->v_scale_ratio[k]), bw_int_to_fixed(4)))), data->h_total[k]), data->pixel_rate[k]), vbios->nbp_state_change_latency), data->dmif_burst_time[low][s_low]), data->mcifwr_burst_time[low][s_low]), data->dram_speed_change_line_source_transfer_time[k][low][s_low]); - data->min_vblank_dram_speed_change_margin = bw_min2(data->min_vblank_dram_speed_change_margin, data->v_blank_dram_speed_change_margin[k]); - } - } - } - for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { - data->displays_with_same_mode[i] = bw_int_to_fixed(0); - if (data->enable[i] == 1 && data->display_pstate_change_enable[i] == 0 && bw_mtn(data->v_blank_dram_speed_change_margin[i], bw_int_to_fixed(0))) { - for (j = 0; j <= maximum_number_of_surfaces - 1; j++) { - if ((data->enable[j] == 1 && bw_equ(data->source_width_rounded_up_to_chunks[i], data->source_width_rounded_up_to_chunks[j]) && bw_equ(data->source_height_rounded_up_to_chunks[i], data->source_height_rounded_up_to_chunks[j]) && bw_equ(data->vsr[i], data->vsr[j]) && bw_equ(data->hsr[i], data->hsr[j]) && bw_equ(data->pixel_rate[i], data->pixel_rate[j]))) { - data->displays_with_same_mode[i] = bw_add(data->displays_with_same_mode[i], bw_int_to_fixed(1)); - } - } - } - } - /*compute the maximum number of aligned displays with no margin*/ - number_of_aligned_displays_with_no_margin = 0; - for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { - number_of_aligned_displays_with_no_margin = bw_fixed_to_int(bw_max2(bw_int_to_fixed(number_of_aligned_displays_with_no_margin), data->displays_with_same_mode[i])); - } - /*dram clock change is possible, if all displays have positive margin except for one display or a group of*/ - /*aligned displays with the same timing.*/ - /*the display(s) with the negative margin can be switched in the v_blank region while the other*/ - /*displays are in v_blank or v_active.*/ - if ((number_of_displays_enabled_with_margin + number_of_aligned_displays_with_no_margin == number_of_displays_enabled && bw_mtn(data->min_dram_speed_change_margin[high][s_high], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[high][s_high], bw_int_to_fixed(9999)) && bw_ltn(data->dispclk_required_for_dram_speed_change[high][s_high], vbios->high_voltage_max_dispclk))) { - data->nbp_state_change_enable = bw_def_yes; - } - else { - data->nbp_state_change_enable = bw_def_no; - } - /*dram clock change is possible only in vblank if all displays are aligned and have no margin*/ - if ((number_of_aligned_displays_with_no_margin == number_of_displays_enabled)) { - nbp_state_change_enable_blank = bw_def_yes; - } - else { - nbp_state_change_enable_blank = bw_def_no; - } - /*required yclk(pclk)*/ - /*yclk requirement only makes sense if the dmif and mcifwr data total page close-open time is less than the time for data transfer and the total pte requests fit in the scatter-gather saw queque size*/ - /*if that is the case, the yclk requirement is the maximum of the ones required by dmif and mcifwr, and the high/low yclk(pclk) is chosen accordingly*/ - /*high yclk(pclk) has to be selected when dram speed/p-state change is not possible.*/ - data->min_cursor_memory_interface_buffer_size_in_time = bw_int_to_fixed(9999); - /* number of cursor lines stored in the cursor data return buffer*/ - num_cursor_lines = 0; - for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { - if (data->enable[i]) { - if (bw_mtn(data->cursor_width_pixels[i], bw_int_to_fixed(0))) { - /*compute number of cursor lines stored in data return buffer*/ - if (bw_leq(data->cursor_width_pixels[i], bw_int_to_fixed(64)) && dceip->large_cursor == 1) { - num_cursor_lines = 4; - } - else { - num_cursor_lines = 2; - } - data->min_cursor_memory_interface_buffer_size_in_time = bw_min2(data->min_cursor_memory_interface_buffer_size_in_time, bw_div(bw_mul(bw_div(bw_int_to_fixed(num_cursor_lines), data->vsr[i]), data->h_total[i]), data->pixel_rate[i])); - } - } - } - /*compute minimum time to read one chunk from the dmif buffer*/ - if ((number_of_displays_enabled > 2)) { - data->chunk_request_delay = 0; - } - else { - data->chunk_request_delay = bw_fixed_to_int(bw_div(bw_int_to_fixed(512), vbios->high_voltage_max_dispclk)); - } - data->min_read_buffer_size_in_time = bw_min2(data->min_cursor_memory_interface_buffer_size_in_time, data->min_dmif_size_in_time); - data->display_reads_time_for_data_transfer = bw_sub(bw_sub(data->min_read_buffer_size_in_time, data->total_dmifmc_urgent_latency), bw_int_to_fixed(data->chunk_request_delay)); - data->display_writes_time_for_data_transfer = bw_sub(data->min_mcifwr_size_in_time, vbios->mcifwrmc_urgent_latency); - data->dmif_required_dram_bandwidth = bw_div(data->total_display_reads_required_dram_access_data, data->display_reads_time_for_data_transfer); - data->mcifwr_required_dram_bandwidth = bw_div(data->total_display_writes_required_dram_access_data, data->display_writes_time_for_data_transfer); - data->required_dmifmc_urgent_latency_for_page_close_open = bw_div((bw_sub(data->min_read_buffer_size_in_time, data->dmif_total_page_close_open_time)), data->total_dmifmc_urgent_trips); - data->required_mcifmcwr_urgent_latency = bw_sub(data->min_mcifwr_size_in_time, data->mcifwr_total_page_close_open_time); - if (bw_mtn(data->scatter_gather_total_pte_requests, dceip->maximum_total_outstanding_pte_requests_allowed_by_saw)) { - data->required_dram_bandwidth_gbyte_per_second = bw_int_to_fixed(9999); - yclk_message = bw_def_exceeded_allowed_outstanding_pte_req_queue_size; - data->y_clk_level = high; - data->dram_bandwidth = bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[high]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels)); - } - else if (bw_mtn(vbios->dmifmc_urgent_latency, data->required_dmifmc_urgent_latency_for_page_close_open) || bw_mtn(vbios->mcifwrmc_urgent_latency, data->required_mcifmcwr_urgent_latency)) { - data->required_dram_bandwidth_gbyte_per_second = bw_int_to_fixed(9999); - yclk_message = bw_def_exceeded_allowed_page_close_open; - data->y_clk_level = high; - data->dram_bandwidth = bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[high]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels)); - } - else { - data->required_dram_bandwidth_gbyte_per_second = bw_div(bw_max2(data->dmif_required_dram_bandwidth, data->mcifwr_required_dram_bandwidth), bw_int_to_fixed(1000)); - if (bw_ltn(bw_mul(data->required_dram_bandwidth_gbyte_per_second, bw_int_to_fixed(1000)), bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[low]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels))) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[low][s_high], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[low][s_high], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[low][s_high], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[low][s_high], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[low][s_high], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[low][s_high], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[low][s_high], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[low][s_high], vbios->high_voltage_max_dispclk) && data->num_displays_with_margin[low][s_high] == number_of_displays_enabled_with_margin))) { - yclk_message = bw_fixed_to_int(vbios->low_yclk); - data->y_clk_level = low; - data->dram_bandwidth = bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[low]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels)); - } - else if (bw_ltn(bw_mul(data->required_dram_bandwidth_gbyte_per_second, bw_int_to_fixed(1000)), bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[mid]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels))) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[mid][s_high], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[mid][s_high], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[mid][s_high], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[mid][s_high], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[mid][s_high], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[mid][s_high], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[mid][s_high], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[mid][s_high], vbios->high_voltage_max_dispclk) && data->num_displays_with_margin[mid][s_high] == number_of_displays_enabled_with_margin))) { - yclk_message = bw_fixed_to_int(vbios->mid_yclk); - data->y_clk_level = mid; - data->dram_bandwidth = bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[mid]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels)); - } - else if (bw_ltn(bw_mul(data->required_dram_bandwidth_gbyte_per_second, bw_int_to_fixed(1000)), bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[high]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels)))) { - yclk_message = bw_fixed_to_int(vbios->high_yclk); - data->y_clk_level = high; - data->dram_bandwidth = bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[high]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels)); - } - else { - yclk_message = bw_def_exceeded_allowed_maximum_bw; - data->y_clk_level = high; - data->dram_bandwidth = bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[high]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels)); - } - } - /*required sclk*/ - /*sclk requirement only makes sense if the total pte requests fit in the scatter-gather saw queque size*/ - /*if that is the case, the sclk requirement is the maximum of the ones required by dmif and mcifwr, and the high/mid/low sclk is chosen accordingly, unless that choice results in foresaking dram speed/nb p-state change.*/ - /*the dmif and mcifwr sclk required is the one that allows the transfer of all pipe's data buffer size through the sclk bus in the time for data transfer*/ - /*for dmif, pte and cursor requests have to be included.*/ - data->dmif_required_sclk = bw_div(bw_div(data->total_display_reads_required_data, data->display_reads_time_for_data_transfer), (bw_mul(vbios->data_return_bus_width, bw_int_to_fixed(bus_efficiency)))); - data->mcifwr_required_sclk = bw_div(bw_div(data->total_display_writes_required_data, data->display_writes_time_for_data_transfer), (bw_mul(vbios->data_return_bus_width, bw_int_to_fixed(bus_efficiency)))); - if (bw_mtn(data->scatter_gather_total_pte_requests, dceip->maximum_total_outstanding_pte_requests_allowed_by_saw)) { - data->required_sclk = bw_int_to_fixed(9999); - sclk_message = bw_def_exceeded_allowed_outstanding_pte_req_queue_size; - data->sclk_level = s_high; - } - else if (bw_mtn(vbios->dmifmc_urgent_latency, data->required_dmifmc_urgent_latency_for_page_close_open) || bw_mtn(vbios->mcifwrmc_urgent_latency, data->required_mcifmcwr_urgent_latency)) { - data->required_sclk = bw_int_to_fixed(9999); - sclk_message = bw_def_exceeded_allowed_page_close_open; - data->sclk_level = s_high; - } - else { - data->required_sclk = bw_max2(data->dmif_required_sclk, data->mcifwr_required_sclk); - if (bw_ltn(data->required_sclk, sclk[s_low]) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_low], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_low], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_low], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_low], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[data->y_clk_level][s_low], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[data->y_clk_level][s_low], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[data->y_clk_level][s_low], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[data->y_clk_level][s_low], vbios->low_voltage_max_dispclk) && data->num_displays_with_margin[data->y_clk_level][s_low] == number_of_displays_enabled_with_margin))) { - sclk_message = bw_def_low; - data->sclk_level = s_low; - data->required_sclk = vbios->low_sclk; - } - else if (bw_ltn(data->required_sclk, sclk[s_mid1]) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid1], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid1], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid1], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid1], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[data->y_clk_level][s_mid1], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid1], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid1], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[data->y_clk_level][s_mid1], vbios->mid_voltage_max_dispclk) && data->num_displays_with_margin[data->y_clk_level][s_mid1] == number_of_displays_enabled_with_margin))) { - sclk_message = bw_def_mid; - data->sclk_level = s_mid1; - data->required_sclk = vbios->mid1_sclk; - } - else if (bw_ltn(data->required_sclk, sclk[s_mid2]) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid2], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid2], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid2], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid2], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[data->y_clk_level][s_mid2], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid2], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid2], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[data->y_clk_level][s_mid2], vbios->mid_voltage_max_dispclk) && data->num_displays_with_margin[data->y_clk_level][s_mid2] == number_of_displays_enabled_with_margin))) { - sclk_message = bw_def_mid; - data->sclk_level = s_mid2; - data->required_sclk = vbios->mid2_sclk; - } - else if (bw_ltn(data->required_sclk, sclk[s_mid3]) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid3], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid3], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid3], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid3], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[data->y_clk_level][s_mid3], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid3], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid3], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[data->y_clk_level][s_mid3], vbios->mid_voltage_max_dispclk) && data->num_displays_with_margin[data->y_clk_level][s_mid3] == number_of_displays_enabled_with_margin))) { - sclk_message = bw_def_mid; - data->sclk_level = s_mid3; - data->required_sclk = vbios->mid3_sclk; - } - else if (bw_ltn(data->required_sclk, sclk[s_mid4]) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid4], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid4], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid4], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid4], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[data->y_clk_level][s_mid4], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid4], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid4], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[data->y_clk_level][s_mid4], vbios->mid_voltage_max_dispclk) && data->num_displays_with_margin[data->y_clk_level][s_mid4] == number_of_displays_enabled_with_margin))) { - sclk_message = bw_def_mid; - data->sclk_level = s_mid4; - data->required_sclk = vbios->mid4_sclk; - } - else if (bw_ltn(data->required_sclk, sclk[s_mid5]) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid5], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid5], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid5], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid5], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[data->y_clk_level][s_mid5], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid5], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid5], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[data->y_clk_level][s_mid5], vbios->mid_voltage_max_dispclk) && data->num_displays_with_margin[data->y_clk_level][s_mid5] == number_of_displays_enabled_with_margin))) { - sclk_message = bw_def_mid; - data->sclk_level = s_mid5; - data->required_sclk = vbios->mid5_sclk; - } - else if (bw_ltn(data->required_sclk, sclk[s_mid6]) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid6], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid6], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid6], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid6], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[data->y_clk_level][s_mid6], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid6], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid6], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[data->y_clk_level][s_mid6], vbios->high_voltage_max_dispclk) && data->num_displays_with_margin[data->y_clk_level][s_mid6] == number_of_displays_enabled_with_margin))) { - sclk_message = bw_def_mid; - data->sclk_level = s_mid6; - data->required_sclk = vbios->mid6_sclk; - } - else if (bw_ltn(data->required_sclk, sclk[s_high])) { - sclk_message = bw_def_high; - data->sclk_level = s_high; - data->required_sclk = vbios->high_sclk; - } - else { - sclk_message = bw_def_exceeded_allowed_maximum_sclk; - data->sclk_level = s_high; - /*required_sclk = high_sclk*/ - } - } - /*dispclk*/ - /*if dispclk is set to the maximum, ramping is not required. dispclk required without ramping is less than the dispclk required with ramping.*/ - /*if dispclk required without ramping is more than the maximum dispclk, that is the dispclk required, and the mode is not supported*/ - /*if that does not happen, but dispclk required with ramping is more than the maximum dispclk, dispclk required is just the maximum dispclk*/ - /*if that does not happen either, dispclk required is the dispclk required with ramping.*/ - /*dispclk required without ramping is the maximum of the one required for display pipe pixel throughput, for scaler throughput, for total read request thrrougput and for dram/np p-state change if enabled.*/ - /*the display pipe pixel throughput is the maximum of lines in per line out in the beginning of the frame and lines in per line out in the middle of the frame multiplied by the horizontal blank and chunk granularity factor, altogether multiplied by the ratio of the source width to the line time, divided by the line buffer pixels per dispclk throughput, and multiplied by the display pipe throughput factor.*/ - /*the horizontal blank and chunk granularity factor is the ratio of the line time divided by the line time minus half the horizontal blank and chunk time. it applies when the lines in per line out is not 2 or 4.*/ - /*the dispclk required for scaler throughput is the product of the pixel rate and the scaling limits factor.*/ - /*the dispclk required for total read request throughput is the product of the peak request-per-second bandwidth and the dispclk cycles per request, divided by the request efficiency.*/ - /*for the dispclk required with ramping, instead of multiplying just the pipe throughput by the display pipe throughput factor, we multiply the scaler and pipe throughput by the ramping factor.*/ - /*the scaling limits factor is the product of the horizontal scale ratio, and the ratio of the vertical taps divided by the scaler efficiency clamped to at least 1.*/ - /*the scaling limits factor itself it also clamped to at least 1*/ - /*if doing downscaling with the pre-downscaler enabled, the horizontal scale ratio should not be considered above (use "1")*/ - data->downspread_factor = bw_add(bw_int_to_fixed(1), bw_div(vbios->down_spread_percentage, bw_int_to_fixed(100))); - for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { - if (data->enable[i]) { - if (surface_type[i] == bw_def_graphics) { - switch (data->lb_bpc[i]) { - case 6: - data->v_scaler_efficiency = dceip->graphics_vscaler_efficiency6_bit_per_component; - break; - case 8: - data->v_scaler_efficiency = dceip->graphics_vscaler_efficiency8_bit_per_component; - break; - case 10: - data->v_scaler_efficiency = dceip->graphics_vscaler_efficiency10_bit_per_component; - break; - default: - data->v_scaler_efficiency = dceip->graphics_vscaler_efficiency12_bit_per_component; - break; - } - if (data->use_alpha[i] == 1) { - data->v_scaler_efficiency = bw_min2(data->v_scaler_efficiency, dceip->alpha_vscaler_efficiency); - } - } - else { - switch (data->lb_bpc[i]) { - case 6: - data->v_scaler_efficiency = dceip->underlay_vscaler_efficiency6_bit_per_component; - break; - case 8: - data->v_scaler_efficiency = dceip->underlay_vscaler_efficiency8_bit_per_component; - break; - case 10: - data->v_scaler_efficiency = dceip->underlay_vscaler_efficiency10_bit_per_component; - break; - default: - data->v_scaler_efficiency = dceip->underlay_vscaler_efficiency12_bit_per_component; - break; - } - } - if (dceip->pre_downscaler_enabled && bw_mtn(data->hsr[i], bw_int_to_fixed(1))) { - data->scaler_limits_factor = bw_max2(bw_div(data->v_taps[i], data->v_scaler_efficiency), bw_div(data->source_width_rounded_up_to_chunks[i], data->h_total[i])); - } - else { - data->scaler_limits_factor = bw_max3(bw_int_to_fixed(1), bw_ceil2(bw_div(data->h_taps[i], bw_int_to_fixed(4)), bw_int_to_fixed(1)), bw_mul(data->hsr[i], bw_max2(bw_div(data->v_taps[i], data->v_scaler_efficiency), bw_int_to_fixed(1)))); - } - data->display_pipe_pixel_throughput = bw_div(bw_div(bw_mul(bw_max2(data->lb_lines_in_per_line_out_in_beginning_of_frame[i], bw_mul(data->lb_lines_in_per_line_out_in_middle_of_frame[i], data->horizontal_blank_and_chunk_granularity_factor[i])), data->source_width_rounded_up_to_chunks[i]), (bw_div(data->h_total[i], data->pixel_rate[i]))), dceip->lb_write_pixels_per_dispclk); - data->dispclk_required_without_ramping[i] = bw_mul(data->downspread_factor, bw_max2(bw_mul(data->pixel_rate[i], data->scaler_limits_factor), bw_mul(dceip->display_pipe_throughput_factor, data->display_pipe_pixel_throughput))); - data->dispclk_required_with_ramping[i] = bw_mul(dceip->dispclk_ramping_factor, bw_max2(bw_mul(data->pixel_rate[i], data->scaler_limits_factor), data->display_pipe_pixel_throughput)); - } - } - data->total_dispclk_required_with_ramping = bw_int_to_fixed(0); - data->total_dispclk_required_without_ramping = bw_int_to_fixed(0); - for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { - if (data->enable[i]) { - if (bw_ltn(data->total_dispclk_required_with_ramping, data->dispclk_required_with_ramping[i])) { - data->total_dispclk_required_with_ramping = data->dispclk_required_with_ramping[i]; - } - if (bw_ltn(data->total_dispclk_required_without_ramping, data->dispclk_required_without_ramping[i])) { - data->total_dispclk_required_without_ramping = data->dispclk_required_without_ramping[i]; - } - } - } - data->total_read_request_bandwidth = bw_int_to_fixed(0); - data->total_write_request_bandwidth = bw_int_to_fixed(0); - for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { - if (data->enable[i]) { - if (surface_type[i] != bw_def_display_write_back420_luma && surface_type[i] != bw_def_display_write_back420_chroma) { - data->total_read_request_bandwidth = bw_add(data->total_read_request_bandwidth, data->request_bandwidth[i]); - } - else { - data->total_write_request_bandwidth = bw_add(data->total_write_request_bandwidth, data->request_bandwidth[i]); - } - } - } - data->dispclk_required_for_total_read_request_bandwidth = bw_div(bw_mul(data->total_read_request_bandwidth, dceip->dispclk_per_request), dceip->request_efficiency); - data->total_dispclk_required_with_ramping_with_request_bandwidth = bw_max2(data->total_dispclk_required_with_ramping, data->dispclk_required_for_total_read_request_bandwidth); - data->total_dispclk_required_without_ramping_with_request_bandwidth = bw_max2(data->total_dispclk_required_without_ramping, data->dispclk_required_for_total_read_request_bandwidth); - if (data->cpuc_state_change_enable == bw_def_yes) { - data->total_dispclk_required_with_ramping_with_request_bandwidth = bw_max3(data->total_dispclk_required_with_ramping_with_request_bandwidth, data->dispclk_required_for_blackout_duration[data->y_clk_level][data->sclk_level], data->dispclk_required_for_blackout_recovery[data->y_clk_level][data->sclk_level]); - data->total_dispclk_required_without_ramping_with_request_bandwidth = bw_max3(data->total_dispclk_required_without_ramping_with_request_bandwidth, data->dispclk_required_for_blackout_duration[data->y_clk_level][data->sclk_level], data->dispclk_required_for_blackout_recovery[data->y_clk_level][data->sclk_level]); - } - if (data->cpup_state_change_enable == bw_def_yes) { - data->total_dispclk_required_with_ramping_with_request_bandwidth = bw_max2(data->total_dispclk_required_with_ramping_with_request_bandwidth, data->dispclk_required_for_blackout_duration[data->y_clk_level][data->sclk_level]); - data->total_dispclk_required_without_ramping_with_request_bandwidth = bw_max2(data->total_dispclk_required_without_ramping_with_request_bandwidth, data->dispclk_required_for_blackout_duration[data->y_clk_level][data->sclk_level]); - } - if (data->nbp_state_change_enable == bw_def_yes) { - data->total_dispclk_required_with_ramping_with_request_bandwidth = bw_max2(data->total_dispclk_required_with_ramping_with_request_bandwidth, data->dispclk_required_for_dram_speed_change[data->y_clk_level][data->sclk_level]); - data->total_dispclk_required_without_ramping_with_request_bandwidth = bw_max2(data->total_dispclk_required_without_ramping_with_request_bandwidth, data->dispclk_required_for_dram_speed_change[data->y_clk_level][data->sclk_level]); - } - if (bw_ltn(data->total_dispclk_required_with_ramping_with_request_bandwidth, vbios->high_voltage_max_dispclk)) { - data->dispclk = data->total_dispclk_required_with_ramping_with_request_bandwidth; - } - else if (bw_ltn(data->total_dispclk_required_without_ramping_with_request_bandwidth, vbios->high_voltage_max_dispclk)) { - data->dispclk = vbios->high_voltage_max_dispclk; - } - else { - data->dispclk = data->total_dispclk_required_without_ramping_with_request_bandwidth; - } - /* required core voltage*/ - /* the core voltage required is low if sclk, yclk(pclk)and dispclk are within the low limits*/ - /* otherwise, the core voltage required is medium if yclk (pclk) is within the low limit and sclk and dispclk are within the medium limit*/ - /* otherwise, the core voltage required is high if the three clocks are within the high limits*/ - /* otherwise, or if the mode is not supported, core voltage requirement is not applicable*/ - if (pipe_check == bw_def_notok) { - voltage = bw_def_na; - } - else if (mode_check == bw_def_notok) { - voltage = bw_def_notok; - } - else if (bw_equ(bw_int_to_fixed(yclk_message), vbios->low_yclk) && sclk_message == bw_def_low && bw_ltn(data->dispclk, vbios->low_voltage_max_dispclk)) { - voltage = bw_def_0_72; - } - else if ((bw_equ(bw_int_to_fixed(yclk_message), vbios->low_yclk) || bw_equ(bw_int_to_fixed(yclk_message), vbios->mid_yclk)) && (sclk_message == bw_def_low || sclk_message == bw_def_mid) && bw_ltn(data->dispclk, vbios->mid_voltage_max_dispclk)) { - voltage = bw_def_0_8; - } - else if ((bw_equ(bw_int_to_fixed(yclk_message), vbios->low_yclk) || bw_equ(bw_int_to_fixed(yclk_message), vbios->mid_yclk) || bw_equ(bw_int_to_fixed(yclk_message), vbios->high_yclk)) && (sclk_message == bw_def_low || sclk_message == bw_def_mid || sclk_message == bw_def_high) && bw_leq(data->dispclk, vbios->high_voltage_max_dispclk)) { - if ((data->nbp_state_change_enable == bw_def_no && nbp_state_change_enable_blank == bw_def_no)) { - voltage = bw_def_high_no_nbp_state_change; - } - else { - voltage = bw_def_0_9; - } - } - else { - voltage = bw_def_notok; - } - if (voltage == bw_def_0_72) { - data->max_phyclk = vbios->low_voltage_max_phyclk; - } - else if (voltage == bw_def_0_8) { - data->max_phyclk = vbios->mid_voltage_max_phyclk; - } - else { - data->max_phyclk = vbios->high_voltage_max_phyclk; - } - /*required blackout recovery time*/ - data->blackout_recovery_time = bw_int_to_fixed(0); - for (k = 0; k <= maximum_number_of_surfaces - 1; k++) { - if (data->enable[k] && bw_mtn(vbios->blackout_duration, bw_int_to_fixed(0)) && data->cpup_state_change_enable == bw_def_yes) { - if (surface_type[k] != bw_def_display_write_back420_luma && surface_type[k] != bw_def_display_write_back420_chroma) { - data->blackout_recovery_time = bw_max2(data->blackout_recovery_time, bw_add(bw_mul(bw_int_to_fixed(2), data->total_dmifmc_urgent_latency), data->dmif_burst_time[data->y_clk_level][data->sclk_level])); - if (bw_ltn(data->adjusted_data_buffer_size[k], bw_mul(bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]), (bw_add(vbios->blackout_duration, bw_add(bw_mul(bw_int_to_fixed(2), data->total_dmifmc_urgent_latency), data->dmif_burst_time[data->y_clk_level][data->sclk_level])))))) { - data->blackout_recovery_time = bw_max2(data->blackout_recovery_time, bw_div((bw_add(bw_mul(bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]), vbios->blackout_duration), bw_sub(bw_div(bw_mul(bw_mul(bw_mul((bw_add(bw_mul(bw_int_to_fixed(2), data->total_dmifmc_urgent_latency), data->dmif_burst_time[data->y_clk_level][data->sclk_level])), data->dispclk), bw_int_to_fixed(data->bytes_per_pixel[k])), data->lines_interleaved_in_mem_access[k]), data->latency_hiding_lines[k]), data->adjusted_data_buffer_size[k]))), (bw_sub(bw_div(bw_mul(bw_mul(data->dispclk, bw_int_to_fixed(data->bytes_per_pixel[k])), data->lines_interleaved_in_mem_access[k]), data->latency_hiding_lines[k]), bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]))))); - } - } - else { - data->blackout_recovery_time = bw_max2(data->blackout_recovery_time, bw_add(bw_mul(bw_int_to_fixed(2), vbios->mcifwrmc_urgent_latency), data->mcifwr_burst_time[data->y_clk_level][data->sclk_level])); - if (bw_ltn(data->adjusted_data_buffer_size[k], bw_mul(bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]), (bw_add(vbios->blackout_duration, bw_add(bw_mul(bw_int_to_fixed(2), vbios->mcifwrmc_urgent_latency), data->mcifwr_burst_time[data->y_clk_level][data->sclk_level])))))) { - data->blackout_recovery_time = bw_max2(data->blackout_recovery_time, bw_div((bw_add(bw_mul(bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]), vbios->blackout_duration), bw_sub(bw_div(bw_mul(bw_mul(bw_mul((bw_add(bw_add(bw_mul(bw_int_to_fixed(2), vbios->mcifwrmc_urgent_latency), data->dmif_burst_time[data->y_clk_level][data->sclk_level]), data->mcifwr_burst_time[data->y_clk_level][data->sclk_level])), data->dispclk), bw_int_to_fixed(data->bytes_per_pixel[k])), data->lines_interleaved_in_mem_access[k]), data->latency_hiding_lines[k]), data->adjusted_data_buffer_size[k]))), (bw_sub(bw_div(bw_mul(bw_mul(data->dispclk, bw_int_to_fixed(data->bytes_per_pixel[k])), data->lines_interleaved_in_mem_access[k]), data->latency_hiding_lines[k]), bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]))))); - } - } - } - } - /*sclk deep sleep*/ - /*during self-refresh, sclk can be reduced to dispclk divided by the minimum pixels in the data fifo entry, with 15% margin, but shoudl not be set to less than the request bandwidth.*/ - /*the data fifo entry is 16 pixels for the writeback, 64 bytes/bytes_per_pixel for the graphics, 16 pixels for the parallel rotation underlay,*/ - /*and 16 bytes/bytes_per_pixel for the orthogonal rotation underlay.*/ - /*in parallel mode (underlay pipe), the data read from the dmifv buffer is variable and based on the pixel depth (8bbp - 16 bytes, 16 bpp - 32 bytes, 32 bpp - 64 bytes)*/ - /*in orthogonal mode (underlay pipe), the data read from the dmifv buffer is fixed at 16 bytes.*/ - for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { - if (data->enable[i]) { - if (surface_type[i] == bw_def_display_write_back420_luma || surface_type[i] == bw_def_display_write_back420_chroma) { - data->pixels_per_data_fifo_entry[i] = bw_int_to_fixed(16); - } - else if (surface_type[i] == bw_def_graphics) { - data->pixels_per_data_fifo_entry[i] = bw_div(bw_int_to_fixed(64), bw_int_to_fixed(data->bytes_per_pixel[i])); - } - else if (data->orthogonal_rotation[i] == 0) { - data->pixels_per_data_fifo_entry[i] = bw_int_to_fixed(16); - } - else { - data->pixels_per_data_fifo_entry[i] = bw_div(bw_int_to_fixed(16), bw_int_to_fixed(data->bytes_per_pixel[i])); - } - } - } - data->min_pixels_per_data_fifo_entry = bw_int_to_fixed(9999); - for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { - if (data->enable[i]) { - if (bw_mtn(data->min_pixels_per_data_fifo_entry, data->pixels_per_data_fifo_entry[i])) { - data->min_pixels_per_data_fifo_entry = data->pixels_per_data_fifo_entry[i]; - } - } - } - data->sclk_deep_sleep = bw_max2(bw_div(bw_mul(data->dispclk, bw_frc_to_fixed(115, 100)), data->min_pixels_per_data_fifo_entry), data->total_read_request_bandwidth); - /*urgent, stutter and nb-p_state watermark*/ - /*the urgent watermark is the maximum of the urgent trip time plus the pixel transfer time, the urgent trip times to get data for the first pixel, and the urgent trip times to get data for the last pixel.*/ - /*the stutter exit watermark is the self refresh exit time plus the maximum of the data burst time plus the pixel transfer time, the data burst times to get data for the first pixel, and the data burst times to get data for the last pixel. it does not apply to the writeback.*/ - /*the nb p-state change watermark is the dram speed/p-state change time plus the maximum of the data burst time plus the pixel transfer time, the data burst times to get data for the first pixel, and the data burst times to get data for the last pixel.*/ - /*the pixel transfer time is the maximum of the time to transfer the source pixels required for the first output pixel, and the time to transfer the pixels for the last output pixel minus the active line time.*/ - /*blackout_duration is added to the urgent watermark*/ - data->chunk_request_time = bw_int_to_fixed(0); - data->cursor_request_time = bw_int_to_fixed(0); - /*compute total time to request one chunk from each active display pipe*/ - for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { - if (data->enable[i]) { - data->chunk_request_time = bw_add(data->chunk_request_time, (bw_div((bw_div(bw_int_to_fixed(pixels_per_chunk * data->bytes_per_pixel[i]), data->useful_bytes_per_request[i])), bw_min2(sclk[data->sclk_level], bw_div(data->dispclk, bw_int_to_fixed(2)))))); - } - } - /*compute total time to request cursor data*/ - data->cursor_request_time = (bw_div(data->cursor_total_data, (bw_mul(bw_int_to_fixed(32), sclk[data->sclk_level])))); - for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { - if (data->enable[i]) { - data->line_source_pixels_transfer_time = bw_max2(bw_div(bw_div(data->src_pixels_for_first_output_pixel[i], dceip->lb_write_pixels_per_dispclk), (bw_div(data->dispclk, dceip->display_pipe_throughput_factor))), bw_sub(bw_div(bw_div(data->src_pixels_for_last_output_pixel[i], dceip->lb_write_pixels_per_dispclk), (bw_div(data->dispclk, dceip->display_pipe_throughput_factor))), data->active_time[i])); - if (surface_type[i] != bw_def_display_write_back420_luma && surface_type[i] != bw_def_display_write_back420_chroma) { - data->urgent_watermark[i] = bw_add(bw_add(bw_add(bw_add(bw_add(data->total_dmifmc_urgent_latency, data->dmif_burst_time[data->y_clk_level][data->sclk_level]), bw_max2(data->line_source_pixels_transfer_time, data->line_source_transfer_time[i][data->y_clk_level][data->sclk_level])), vbios->blackout_duration), data->chunk_request_time), data->cursor_request_time); - data->stutter_exit_watermark[i] = bw_add(bw_sub(vbios->stutter_self_refresh_exit_latency, data->total_dmifmc_urgent_latency), data->urgent_watermark[i]); - data->stutter_entry_watermark[i] = bw_add(bw_sub(bw_add(vbios->stutter_self_refresh_exit_latency, vbios->stutter_self_refresh_entry_latency), data->total_dmifmc_urgent_latency), data->urgent_watermark[i]); - /*unconditionally remove black out time from the nb p_state watermark*/ - if ((data->display_pstate_change_enable[i] == 1)) { - data->nbp_state_change_watermark[i] = bw_add(bw_add(vbios->nbp_state_change_latency, data->dmif_burst_time[data->y_clk_level][data->sclk_level]), bw_max2(data->line_source_pixels_transfer_time, data->dram_speed_change_line_source_transfer_time[i][data->y_clk_level][data->sclk_level])); - } - else { - /*maximize the watermark to force the switch in the vb_lank region of the frame*/ - data->nbp_state_change_watermark[i] = bw_int_to_fixed(131000); - } - } - else { - data->urgent_watermark[i] = bw_add(bw_add(bw_add(bw_add(bw_add(vbios->mcifwrmc_urgent_latency, data->mcifwr_burst_time[data->y_clk_level][data->sclk_level]), bw_max2(data->line_source_pixels_transfer_time, data->line_source_transfer_time[i][data->y_clk_level][data->sclk_level])), vbios->blackout_duration), data->chunk_request_time), data->cursor_request_time); - data->stutter_exit_watermark[i] = bw_int_to_fixed(0); - data->stutter_entry_watermark[i] = bw_int_to_fixed(0); - if ((data->display_pstate_change_enable[i] == 1)) { - data->nbp_state_change_watermark[i] = bw_add(bw_add(vbios->nbp_state_change_latency, data->mcifwr_burst_time[data->y_clk_level][data->sclk_level]), bw_max2(data->line_source_pixels_transfer_time, data->dram_speed_change_line_source_transfer_time[i][data->y_clk_level][data->sclk_level])); - } - else { - /*maximize the watermark to force the switch in the vb_lank region of the frame*/ - data->nbp_state_change_watermark[i] = bw_int_to_fixed(131000); - } - } - } - } - /*stutter mode enable*/ - /*in the multi-display case the stutter exit or entry watermark cannot exceed the minimum latency hiding capabilities of the*/ - /*display pipe.*/ - data->stutter_mode_enable = data->cpuc_state_change_enable; - if (data->number_of_displays > 1) { - for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { - if (data->enable[i]) { - if ((bw_mtn(data->stutter_exit_watermark[i], data->minimum_latency_hiding[i]) || bw_mtn(data->stutter_entry_watermark[i], data->minimum_latency_hiding[i]))) { - data->stutter_mode_enable = bw_def_no; - } - } - } - } - /*performance metrics*/ - /* display read access efficiency (%)*/ - /* display write back access efficiency (%)*/ - /* stutter efficiency (%)*/ - /* extra underlay pitch recommended for efficiency (pixels)*/ - /* immediate flip time (us)*/ - /* latency for other clients due to urgent display read (us)*/ - /* latency for other clients due to urgent display write (us)*/ - /* average bandwidth consumed by display (no compression) (gb/s)*/ - /* required dram bandwidth (gb/s)*/ - /* required sclk (m_hz)*/ - /* required rd urgent latency (us)*/ - /* nb p-state change margin (us)*/ - /*dmif and mcifwr dram access efficiency*/ - /*is the ratio between the ideal dram access time (which is the data buffer size in memory divided by the dram bandwidth), and the actual time which is the total page close-open time. but it cannot exceed the dram efficiency provided by the memory subsystem*/ - data->dmifdram_access_efficiency = bw_min2(bw_div(bw_div(data->total_display_reads_required_dram_access_data, data->dram_bandwidth), data->dmif_total_page_close_open_time), bw_int_to_fixed(1)); - if (bw_mtn(data->total_display_writes_required_dram_access_data, bw_int_to_fixed(0))) { - data->mcifwrdram_access_efficiency = bw_min2(bw_div(bw_div(data->total_display_writes_required_dram_access_data, data->dram_bandwidth), data->mcifwr_total_page_close_open_time), bw_int_to_fixed(1)); - } - else { - data->mcifwrdram_access_efficiency = bw_int_to_fixed(0); - } - /*average bandwidth*/ - /*the average bandwidth with no compression is the vertical active time is the source width times the bytes per pixel divided by the line time, multiplied by the vertical scale ratio and the ratio of bytes per request divided by the useful bytes per request.*/ - /*the average bandwidth with compression is the same, divided by the compression ratio*/ - for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { - if (data->enable[i]) { - data->average_bandwidth_no_compression[i] = bw_div(bw_mul(bw_mul(bw_div(bw_mul(data->source_width_rounded_up_to_chunks[i], bw_int_to_fixed(data->bytes_per_pixel[i])), (bw_div(data->h_total[i], data->pixel_rate[i]))), data->vsr[i]), data->bytes_per_request[i]), data->useful_bytes_per_request[i]); - data->average_bandwidth[i] = bw_div(data->average_bandwidth_no_compression[i], data->compression_rate[i]); - } - } - data->total_average_bandwidth_no_compression = bw_int_to_fixed(0); - data->total_average_bandwidth = bw_int_to_fixed(0); - for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { - if (data->enable[i]) { - data->total_average_bandwidth_no_compression = bw_add(data->total_average_bandwidth_no_compression, data->average_bandwidth_no_compression[i]); - data->total_average_bandwidth = bw_add(data->total_average_bandwidth, data->average_bandwidth[i]); - } - } - /*stutter efficiency*/ - /*the stutter efficiency is the frame-average time in self-refresh divided by the frame-average stutter cycle duration. only applies if the display write-back is not enabled.*/ - /*the frame-average stutter cycle used is the minimum for all pipes of the frame-average data buffer size in time, times the compression rate*/ - /*the frame-average time in self-refresh is the stutter cycle minus the self refresh exit latency and the burst time*/ - /*the stutter cycle is the dmif buffer size reduced by the excess of the stutter exit watermark over the lb size in time.*/ - /*the burst time is the data needed during the stutter cycle divided by the available bandwidth*/ - /*compute the time read all the data from the dmif buffer to the lb (dram refresh period)*/ - for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { - if (data->enable[i]) { - data->stutter_refresh_duration[i] = bw_sub(bw_mul(bw_div(bw_div(bw_mul(bw_div(bw_div(data->adjusted_data_buffer_size[i], bw_int_to_fixed(data->bytes_per_pixel[i])), data->source_width_rounded_up_to_chunks[i]), data->h_total[i]), data->vsr[i]), data->pixel_rate[i]), data->compression_rate[i]), bw_max2(bw_int_to_fixed(0), bw_sub(data->stutter_exit_watermark[i], bw_div(bw_mul((bw_sub(data->lb_partitions[i], bw_int_to_fixed(1))), data->h_total[i]), data->pixel_rate[i])))); - data->stutter_dmif_buffer_size[i] = bw_div(bw_mul(bw_mul(bw_div(bw_mul(bw_mul(data->stutter_refresh_duration[i], bw_int_to_fixed(data->bytes_per_pixel[i])), data->source_width_rounded_up_to_chunks[i]), data->h_total[i]), data->vsr[i]), data->pixel_rate[i]), data->compression_rate[i]); - } - } - data->min_stutter_refresh_duration = bw_int_to_fixed(9999); - data->total_stutter_dmif_buffer_size = 0; - data->total_bytes_requested = 0; - data->min_stutter_dmif_buffer_size = 9999; - for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { - if (data->enable[i]) { - if (bw_mtn(data->min_stutter_refresh_duration, data->stutter_refresh_duration[i])) { - data->min_stutter_refresh_duration = data->stutter_refresh_duration[i]; - data->total_bytes_requested = bw_fixed_to_int(bw_add(bw_int_to_fixed(data->total_bytes_requested), (bw_mul(bw_mul(data->source_height_rounded_up_to_chunks[i], data->source_width_rounded_up_to_chunks[i]), bw_int_to_fixed(data->bytes_per_pixel[i]))))); - data->min_stutter_dmif_buffer_size = bw_fixed_to_int(data->stutter_dmif_buffer_size[i]); - } - data->total_stutter_dmif_buffer_size = bw_fixed_to_int(bw_add(data->stutter_dmif_buffer_size[i], bw_int_to_fixed(data->total_stutter_dmif_buffer_size))); - } - } - data->stutter_burst_time = bw_div(bw_int_to_fixed(data->total_stutter_dmif_buffer_size), bw_min2(bw_mul(data->dram_bandwidth, data->dmifdram_access_efficiency), bw_mul(sclk[data->sclk_level], bw_int_to_fixed(32)))); - data->num_stutter_bursts = data->total_bytes_requested / data->min_stutter_dmif_buffer_size; - data->total_stutter_cycle_duration = bw_add(bw_add(data->min_stutter_refresh_duration, vbios->stutter_self_refresh_exit_latency), data->stutter_burst_time); - data->time_in_self_refresh = data->min_stutter_refresh_duration; - if (data->d1_display_write_back_dwb_enable == 1) { - data->stutter_efficiency = bw_int_to_fixed(0); - } - else if (bw_ltn(data->time_in_self_refresh, bw_int_to_fixed(0))) { - data->stutter_efficiency = bw_int_to_fixed(0); - } - else { - /*compute stutter efficiency assuming 60 hz refresh rate*/ - data->stutter_efficiency = bw_max2(bw_int_to_fixed(0), bw_mul((bw_sub(bw_int_to_fixed(1), (bw_div(bw_mul((bw_add(vbios->stutter_self_refresh_exit_latency, data->stutter_burst_time)), bw_int_to_fixed(data->num_stutter_bursts)), bw_frc_to_fixed(166666667, 10000))))), bw_int_to_fixed(100))); - } - /*immediate flip time*/ - /*if scatter gather is enabled, the immediate flip takes a number of urgent memory trips equivalent to the pte requests in a row divided by the pte request limit.*/ - /*otherwise, it may take just one urgenr memory trip*/ - data->worst_number_of_trips_to_memory = bw_int_to_fixed(1); - for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { - if (data->enable[i] && data->scatter_gather_enable_for_pipe[i] == 1) { - data->number_of_trips_to_memory_for_getting_apte_row[i] = bw_ceil2(bw_div(data->scatter_gather_pte_requests_in_row[i], data->scatter_gather_pte_request_limit[i]), bw_int_to_fixed(1)); - if (bw_ltn(data->worst_number_of_trips_to_memory, data->number_of_trips_to_memory_for_getting_apte_row[i])) { - data->worst_number_of_trips_to_memory = data->number_of_trips_to_memory_for_getting_apte_row[i]; - } - } - } - data->immediate_flip_time = bw_mul(data->worst_number_of_trips_to_memory, data->total_dmifmc_urgent_latency); - /*worst latency for other clients*/ - /*it is the urgent latency plus the urgent burst time*/ - data->latency_for_non_dmif_clients = bw_add(data->total_dmifmc_urgent_latency, data->dmif_burst_time[data->y_clk_level][data->sclk_level]); - if (data->d1_display_write_back_dwb_enable == 1) { - data->latency_for_non_mcifwr_clients = bw_add(vbios->mcifwrmc_urgent_latency, dceip->mcifwr_all_surfaces_burst_time); - } - else { - data->latency_for_non_mcifwr_clients = bw_int_to_fixed(0); - } - /*dmif mc urgent latency suppported in high sclk and yclk*/ - data->dmifmc_urgent_latency_supported_in_high_sclk_and_yclk = bw_div((bw_sub(data->min_read_buffer_size_in_time, data->dmif_burst_time[high][s_high])), data->total_dmifmc_urgent_trips); - /*dram speed/p-state change margin*/ - /*in the multi-display case the nb p-state change watermark cannot exceed the average lb size plus the dmif size or the cursor dcp buffer size*/ - data->v_blank_nbp_state_dram_speed_change_latency_supported = bw_int_to_fixed(99999); - data->nbp_state_dram_speed_change_latency_supported = bw_int_to_fixed(99999); - for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { - if (data->enable[i]) { - data->nbp_state_dram_speed_change_latency_supported = bw_min2(data->nbp_state_dram_speed_change_latency_supported, bw_add(bw_sub(data->maximum_latency_hiding_with_cursor[i], data->nbp_state_change_watermark[i]), vbios->nbp_state_change_latency)); - data->v_blank_nbp_state_dram_speed_change_latency_supported = bw_min2(data->v_blank_nbp_state_dram_speed_change_latency_supported, bw_add(bw_sub(bw_div(bw_mul((bw_sub(data->v_total[i], bw_sub(bw_div(data->src_height[i], data->v_scale_ratio[i]), bw_int_to_fixed(4)))), data->h_total[i]), data->pixel_rate[i]), data->nbp_state_change_watermark[i]), vbios->nbp_state_change_latency)); - } - } - /*sclk required vs urgent latency*/ - for (i = 1; i <= 5; i++) { - data->display_reads_time_for_data_transfer_and_urgent_latency = bw_sub(data->min_read_buffer_size_in_time, bw_mul(data->total_dmifmc_urgent_trips, bw_int_to_fixed(i))); - if (pipe_check == bw_def_ok && (bw_mtn(data->display_reads_time_for_data_transfer_and_urgent_latency, data->dmif_total_page_close_open_time))) { - data->dmif_required_sclk_for_urgent_latency[i] = bw_div(bw_div(data->total_display_reads_required_data, data->display_reads_time_for_data_transfer_and_urgent_latency), (bw_mul(vbios->data_return_bus_width, bw_int_to_fixed(bus_efficiency)))); - } - else { - data->dmif_required_sclk_for_urgent_latency[i] = bw_int_to_fixed(bw_def_na); - } - } - /*output link bit per pixel supported*/ - for (k = 0; k <= maximum_number_of_surfaces - 1; k++) { - data->output_bpphdmi[k] = bw_def_na; - data->output_bppdp4_lane_hbr[k] = bw_def_na; - data->output_bppdp4_lane_hbr2[k] = bw_def_na; - data->output_bppdp4_lane_hbr3[k] = bw_def_na; - if (data->enable[k]) { - data->output_bpphdmi[k] = bw_fixed_to_int(bw_mul(bw_div(bw_min2(bw_int_to_fixed(600), data->max_phyclk), data->pixel_rate[k]), bw_int_to_fixed(24))); - if (bw_meq(data->max_phyclk, bw_int_to_fixed(270))) { - data->output_bppdp4_lane_hbr[k] = bw_fixed_to_int(bw_mul(bw_div(bw_mul(bw_int_to_fixed(270), bw_int_to_fixed(4)), data->pixel_rate[k]), bw_int_to_fixed(8))); - } - if (bw_meq(data->max_phyclk, bw_int_to_fixed(540))) { - data->output_bppdp4_lane_hbr2[k] = bw_fixed_to_int(bw_mul(bw_div(bw_mul(bw_int_to_fixed(540), bw_int_to_fixed(4)), data->pixel_rate[k]), bw_int_to_fixed(8))); - } - if (bw_meq(data->max_phyclk, bw_int_to_fixed(810))) { - data->output_bppdp4_lane_hbr3[k] = bw_fixed_to_int(bw_mul(bw_div(bw_mul(bw_int_to_fixed(810), bw_int_to_fixed(4)), data->pixel_rate[k]), bw_int_to_fixed(8))); - } - } - } -} - -/******************************************************************************* - * Public functions - ******************************************************************************/ -void bw_calcs_init(struct bw_calcs_dceip *bw_dceip, - struct bw_calcs_vbios *bw_vbios, - struct hw_asic_id asic_id) -{ - struct bw_calcs_dceip dceip = { 0 }; - struct bw_calcs_vbios vbios = { 0 }; - - enum bw_calcs_version version = bw_calcs_version_from_asic_id(asic_id); - - dceip.version = version; - - switch (version) { - case BW_CALCS_VERSION_CARRIZO: - vbios.memory_type = bw_def_gddr5; - vbios.dram_channel_width_in_bits = 64; - vbios.number_of_dram_channels = asic_id.vram_width / vbios.dram_channel_width_in_bits; - vbios.number_of_dram_banks = 8; - vbios.high_yclk = bw_int_to_fixed(1600); - vbios.mid_yclk = bw_int_to_fixed(1600); - vbios.low_yclk = bw_frc_to_fixed(66666, 100); - vbios.low_sclk = bw_int_to_fixed(200); - vbios.mid1_sclk = bw_int_to_fixed(300); - vbios.mid2_sclk = bw_int_to_fixed(300); - vbios.mid3_sclk = bw_int_to_fixed(300); - vbios.mid4_sclk = bw_int_to_fixed(300); - vbios.mid5_sclk = bw_int_to_fixed(300); - vbios.mid6_sclk = bw_int_to_fixed(300); - vbios.high_sclk = bw_frc_to_fixed(62609, 100); - vbios.low_voltage_max_dispclk = bw_int_to_fixed(352); - vbios.mid_voltage_max_dispclk = bw_int_to_fixed(467); - vbios.high_voltage_max_dispclk = bw_int_to_fixed(643); - vbios.low_voltage_max_phyclk = bw_int_to_fixed(540); - vbios.mid_voltage_max_phyclk = bw_int_to_fixed(810); - vbios.high_voltage_max_phyclk = bw_int_to_fixed(810); - vbios.data_return_bus_width = bw_int_to_fixed(32); - vbios.trc = bw_int_to_fixed(50); - vbios.dmifmc_urgent_latency = bw_int_to_fixed(4); - vbios.stutter_self_refresh_exit_latency = bw_frc_to_fixed(153, 10); - vbios.stutter_self_refresh_entry_latency = bw_int_to_fixed(0); - vbios.nbp_state_change_latency = bw_frc_to_fixed(19649, 1000); - vbios.mcifwrmc_urgent_latency = bw_int_to_fixed(10); - vbios.scatter_gather_enable = true; - vbios.down_spread_percentage = bw_frc_to_fixed(5, 10); - vbios.cursor_width = 32; - vbios.average_compression_rate = 4; - vbios.number_of_request_slots_gmc_reserves_for_dmif_per_channel = 256; - vbios.blackout_duration = bw_int_to_fixed(18); /* us */ - vbios.maximum_blackout_recovery_time = bw_int_to_fixed(20); - - dceip.large_cursor = false; - dceip.dmif_request_buffer_size = bw_int_to_fixed(768); - dceip.dmif_pipe_en_fbc_chunk_tracker = false; - dceip.cursor_max_outstanding_group_num = 1; - dceip.lines_interleaved_into_lb = 2; - dceip.chunk_width = 256; - dceip.number_of_graphics_pipes = 3; - dceip.number_of_underlay_pipes = 1; - dceip.low_power_tiling_mode = 0; - dceip.display_write_back_supported = false; - dceip.argb_compression_support = false; - dceip.underlay_vscaler_efficiency6_bit_per_component = - bw_frc_to_fixed(35556, 10000); - dceip.underlay_vscaler_efficiency8_bit_per_component = - bw_frc_to_fixed(34286, 10000); - dceip.underlay_vscaler_efficiency10_bit_per_component = - bw_frc_to_fixed(32, 10); - dceip.underlay_vscaler_efficiency12_bit_per_component = - bw_int_to_fixed(3); - dceip.graphics_vscaler_efficiency6_bit_per_component = - bw_frc_to_fixed(35, 10); - dceip.graphics_vscaler_efficiency8_bit_per_component = - bw_frc_to_fixed(34286, 10000); - dceip.graphics_vscaler_efficiency10_bit_per_component = - bw_frc_to_fixed(32, 10); - dceip.graphics_vscaler_efficiency12_bit_per_component = - bw_int_to_fixed(3); - dceip.alpha_vscaler_efficiency = bw_int_to_fixed(3); - dceip.max_dmif_buffer_allocated = 2; - dceip.graphics_dmif_size = 12288; - dceip.underlay_luma_dmif_size = 19456; - dceip.underlay_chroma_dmif_size = 23552; - dceip.pre_downscaler_enabled = true; - dceip.underlay_downscale_prefetch_enabled = true; - dceip.lb_write_pixels_per_dispclk = bw_int_to_fixed(1); - dceip.lb_size_per_component444 = bw_int_to_fixed(82176); - dceip.graphics_lb_nodownscaling_multi_line_prefetching = false; - dceip.stutter_and_dram_clock_state_change_gated_before_cursor = - bw_int_to_fixed(0); - dceip.underlay420_luma_lb_size_per_component = bw_int_to_fixed( - 82176); - dceip.underlay420_chroma_lb_size_per_component = - bw_int_to_fixed(164352); - dceip.underlay422_lb_size_per_component = bw_int_to_fixed( - 82176); - dceip.cursor_chunk_width = bw_int_to_fixed(64); - dceip.cursor_dcp_buffer_lines = bw_int_to_fixed(4); - dceip.underlay_maximum_width_efficient_for_tiling = - bw_int_to_fixed(1920); - dceip.underlay_maximum_height_efficient_for_tiling = - bw_int_to_fixed(1080); - dceip.peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display = - bw_frc_to_fixed(3, 10); - dceip.peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation = - bw_int_to_fixed(25); - dceip.minimum_outstanding_pte_request_limit = bw_int_to_fixed( - 2); - dceip.maximum_total_outstanding_pte_requests_allowed_by_saw = - bw_int_to_fixed(128); - dceip.limit_excessive_outstanding_dmif_requests = true; - dceip.linear_mode_line_request_alternation_slice = - bw_int_to_fixed(64); - dceip.scatter_gather_lines_of_pte_prefetching_in_linear_mode = - 32; - dceip.display_write_back420_luma_mcifwr_buffer_size = 12288; - dceip.display_write_back420_chroma_mcifwr_buffer_size = 8192; - dceip.request_efficiency = bw_frc_to_fixed(8, 10); - dceip.dispclk_per_request = bw_int_to_fixed(2); - dceip.dispclk_ramping_factor = bw_frc_to_fixed(105, 100); - dceip.display_pipe_throughput_factor = bw_frc_to_fixed(105, 100); - dceip.scatter_gather_pte_request_rows_in_tiling_mode = 2; - dceip.mcifwr_all_surfaces_burst_time = bw_int_to_fixed(0); /* todo: this is a bug*/ - break; - case BW_CALCS_VERSION_POLARIS10: - vbios.memory_type = bw_def_gddr5; - vbios.dram_channel_width_in_bits = 32; - vbios.number_of_dram_channels = asic_id.vram_width / vbios.dram_channel_width_in_bits; - vbios.number_of_dram_banks = 8; - vbios.high_yclk = bw_int_to_fixed(6000); - vbios.mid_yclk = bw_int_to_fixed(3200); - vbios.low_yclk = bw_int_to_fixed(1000); - vbios.low_sclk = bw_int_to_fixed(300); - vbios.mid1_sclk = bw_int_to_fixed(400); - vbios.mid2_sclk = bw_int_to_fixed(500); - vbios.mid3_sclk = bw_int_to_fixed(600); - vbios.mid4_sclk = bw_int_to_fixed(700); - vbios.mid5_sclk = bw_int_to_fixed(800); - vbios.mid6_sclk = bw_int_to_fixed(974); - vbios.high_sclk = bw_int_to_fixed(1154); - vbios.low_voltage_max_dispclk = bw_int_to_fixed(459); - vbios.mid_voltage_max_dispclk = bw_int_to_fixed(654); - vbios.high_voltage_max_dispclk = bw_int_to_fixed(1108); - vbios.low_voltage_max_phyclk = bw_int_to_fixed(540); - vbios.mid_voltage_max_phyclk = bw_int_to_fixed(810); - vbios.high_voltage_max_phyclk = bw_int_to_fixed(810); - vbios.data_return_bus_width = bw_int_to_fixed(32); - vbios.trc = bw_int_to_fixed(48); - vbios.dmifmc_urgent_latency = bw_int_to_fixed(3); - vbios.stutter_self_refresh_exit_latency = bw_int_to_fixed(5); - vbios.stutter_self_refresh_entry_latency = bw_int_to_fixed(0); - vbios.nbp_state_change_latency = bw_int_to_fixed(45); - vbios.mcifwrmc_urgent_latency = bw_int_to_fixed(10); - vbios.scatter_gather_enable = true; - vbios.down_spread_percentage = bw_frc_to_fixed(5, 10); - vbios.cursor_width = 32; - vbios.average_compression_rate = 4; - vbios.number_of_request_slots_gmc_reserves_for_dmif_per_channel = 256; - vbios.blackout_duration = bw_int_to_fixed(0); /* us */ - vbios.maximum_blackout_recovery_time = bw_int_to_fixed(0); - - dceip.large_cursor = false; - dceip.dmif_request_buffer_size = bw_int_to_fixed(768); - dceip.dmif_pipe_en_fbc_chunk_tracker = false; - dceip.cursor_max_outstanding_group_num = 1; - dceip.lines_interleaved_into_lb = 2; - dceip.chunk_width = 256; - dceip.number_of_graphics_pipes = 6; - dceip.number_of_underlay_pipes = 0; - dceip.low_power_tiling_mode = 0; - dceip.display_write_back_supported = false; - dceip.argb_compression_support = true; - dceip.underlay_vscaler_efficiency6_bit_per_component = - bw_frc_to_fixed(35556, 10000); - dceip.underlay_vscaler_efficiency8_bit_per_component = - bw_frc_to_fixed(34286, 10000); - dceip.underlay_vscaler_efficiency10_bit_per_component = - bw_frc_to_fixed(32, 10); - dceip.underlay_vscaler_efficiency12_bit_per_component = - bw_int_to_fixed(3); - dceip.graphics_vscaler_efficiency6_bit_per_component = - bw_frc_to_fixed(35, 10); - dceip.graphics_vscaler_efficiency8_bit_per_component = - bw_frc_to_fixed(34286, 10000); - dceip.graphics_vscaler_efficiency10_bit_per_component = - bw_frc_to_fixed(32, 10); - dceip.graphics_vscaler_efficiency12_bit_per_component = - bw_int_to_fixed(3); - dceip.alpha_vscaler_efficiency = bw_int_to_fixed(3); - dceip.max_dmif_buffer_allocated = 4; - dceip.graphics_dmif_size = 12288; - dceip.underlay_luma_dmif_size = 19456; - dceip.underlay_chroma_dmif_size = 23552; - dceip.pre_downscaler_enabled = true; - dceip.underlay_downscale_prefetch_enabled = true; - dceip.lb_write_pixels_per_dispclk = bw_int_to_fixed(1); - dceip.lb_size_per_component444 = bw_int_to_fixed(245952); - dceip.graphics_lb_nodownscaling_multi_line_prefetching = true; - dceip.stutter_and_dram_clock_state_change_gated_before_cursor = - bw_int_to_fixed(1); - dceip.underlay420_luma_lb_size_per_component = bw_int_to_fixed( - 82176); - dceip.underlay420_chroma_lb_size_per_component = - bw_int_to_fixed(164352); - dceip.underlay422_lb_size_per_component = bw_int_to_fixed( - 82176); - dceip.cursor_chunk_width = bw_int_to_fixed(64); - dceip.cursor_dcp_buffer_lines = bw_int_to_fixed(4); - dceip.underlay_maximum_width_efficient_for_tiling = - bw_int_to_fixed(1920); - dceip.underlay_maximum_height_efficient_for_tiling = - bw_int_to_fixed(1080); - dceip.peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display = - bw_frc_to_fixed(3, 10); - dceip.peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation = - bw_int_to_fixed(25); - dceip.minimum_outstanding_pte_request_limit = bw_int_to_fixed( - 2); - dceip.maximum_total_outstanding_pte_requests_allowed_by_saw = - bw_int_to_fixed(128); - dceip.limit_excessive_outstanding_dmif_requests = true; - dceip.linear_mode_line_request_alternation_slice = - bw_int_to_fixed(64); - dceip.scatter_gather_lines_of_pte_prefetching_in_linear_mode = - 32; - dceip.display_write_back420_luma_mcifwr_buffer_size = 12288; - dceip.display_write_back420_chroma_mcifwr_buffer_size = 8192; - dceip.request_efficiency = bw_frc_to_fixed(8, 10); - dceip.dispclk_per_request = bw_int_to_fixed(2); - dceip.dispclk_ramping_factor = bw_frc_to_fixed(105, 100); - dceip.display_pipe_throughput_factor = bw_frc_to_fixed(105, 100); - dceip.scatter_gather_pte_request_rows_in_tiling_mode = 2; - dceip.mcifwr_all_surfaces_burst_time = bw_int_to_fixed(0); - break; - case BW_CALCS_VERSION_POLARIS11: - vbios.memory_type = bw_def_gddr5; - vbios.dram_channel_width_in_bits = 32; - vbios.number_of_dram_channels = asic_id.vram_width / vbios.dram_channel_width_in_bits; - vbios.number_of_dram_banks = 8; - vbios.high_yclk = bw_int_to_fixed(6000); - vbios.mid_yclk = bw_int_to_fixed(3200); - vbios.low_yclk = bw_int_to_fixed(1000); - vbios.low_sclk = bw_int_to_fixed(300); - vbios.mid1_sclk = bw_int_to_fixed(400); - vbios.mid2_sclk = bw_int_to_fixed(500); - vbios.mid3_sclk = bw_int_to_fixed(600); - vbios.mid4_sclk = bw_int_to_fixed(700); - vbios.mid5_sclk = bw_int_to_fixed(800); - vbios.mid6_sclk = bw_int_to_fixed(974); - vbios.high_sclk = bw_int_to_fixed(1154); - vbios.low_voltage_max_dispclk = bw_int_to_fixed(459); - vbios.mid_voltage_max_dispclk = bw_int_to_fixed(654); - vbios.high_voltage_max_dispclk = bw_int_to_fixed(1108); - vbios.low_voltage_max_phyclk = bw_int_to_fixed(540); - vbios.mid_voltage_max_phyclk = bw_int_to_fixed(810); - vbios.high_voltage_max_phyclk = bw_int_to_fixed(810); - vbios.data_return_bus_width = bw_int_to_fixed(32); - vbios.trc = bw_int_to_fixed(48); - if (vbios.number_of_dram_channels == 2) // 64-bit - vbios.dmifmc_urgent_latency = bw_int_to_fixed(4); - else - vbios.dmifmc_urgent_latency = bw_int_to_fixed(3); - vbios.stutter_self_refresh_exit_latency = bw_int_to_fixed(5); - vbios.stutter_self_refresh_entry_latency = bw_int_to_fixed(0); - vbios.nbp_state_change_latency = bw_int_to_fixed(45); - vbios.mcifwrmc_urgent_latency = bw_int_to_fixed(10); - vbios.scatter_gather_enable = true; - vbios.down_spread_percentage = bw_frc_to_fixed(5, 10); - vbios.cursor_width = 32; - vbios.average_compression_rate = 4; - vbios.number_of_request_slots_gmc_reserves_for_dmif_per_channel = 256; - vbios.blackout_duration = bw_int_to_fixed(0); /* us */ - vbios.maximum_blackout_recovery_time = bw_int_to_fixed(0); - - dceip.large_cursor = false; - dceip.dmif_request_buffer_size = bw_int_to_fixed(768); - dceip.dmif_pipe_en_fbc_chunk_tracker = false; - dceip.cursor_max_outstanding_group_num = 1; - dceip.lines_interleaved_into_lb = 2; - dceip.chunk_width = 256; - dceip.number_of_graphics_pipes = 5; - dceip.number_of_underlay_pipes = 0; - dceip.low_power_tiling_mode = 0; - dceip.display_write_back_supported = false; - dceip.argb_compression_support = true; - dceip.underlay_vscaler_efficiency6_bit_per_component = - bw_frc_to_fixed(35556, 10000); - dceip.underlay_vscaler_efficiency8_bit_per_component = - bw_frc_to_fixed(34286, 10000); - dceip.underlay_vscaler_efficiency10_bit_per_component = - bw_frc_to_fixed(32, 10); - dceip.underlay_vscaler_efficiency12_bit_per_component = - bw_int_to_fixed(3); - dceip.graphics_vscaler_efficiency6_bit_per_component = - bw_frc_to_fixed(35, 10); - dceip.graphics_vscaler_efficiency8_bit_per_component = - bw_frc_to_fixed(34286, 10000); - dceip.graphics_vscaler_efficiency10_bit_per_component = - bw_frc_to_fixed(32, 10); - dceip.graphics_vscaler_efficiency12_bit_per_component = - bw_int_to_fixed(3); - dceip.alpha_vscaler_efficiency = bw_int_to_fixed(3); - dceip.max_dmif_buffer_allocated = 4; - dceip.graphics_dmif_size = 12288; - dceip.underlay_luma_dmif_size = 19456; - dceip.underlay_chroma_dmif_size = 23552; - dceip.pre_downscaler_enabled = true; - dceip.underlay_downscale_prefetch_enabled = true; - dceip.lb_write_pixels_per_dispclk = bw_int_to_fixed(1); - dceip.lb_size_per_component444 = bw_int_to_fixed(245952); - dceip.graphics_lb_nodownscaling_multi_line_prefetching = true; - dceip.stutter_and_dram_clock_state_change_gated_before_cursor = - bw_int_to_fixed(1); - dceip.underlay420_luma_lb_size_per_component = bw_int_to_fixed( - 82176); - dceip.underlay420_chroma_lb_size_per_component = - bw_int_to_fixed(164352); - dceip.underlay422_lb_size_per_component = bw_int_to_fixed( - 82176); - dceip.cursor_chunk_width = bw_int_to_fixed(64); - dceip.cursor_dcp_buffer_lines = bw_int_to_fixed(4); - dceip.underlay_maximum_width_efficient_for_tiling = - bw_int_to_fixed(1920); - dceip.underlay_maximum_height_efficient_for_tiling = - bw_int_to_fixed(1080); - dceip.peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display = - bw_frc_to_fixed(3, 10); - dceip.peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation = - bw_int_to_fixed(25); - dceip.minimum_outstanding_pte_request_limit = bw_int_to_fixed( - 2); - dceip.maximum_total_outstanding_pte_requests_allowed_by_saw = - bw_int_to_fixed(128); - dceip.limit_excessive_outstanding_dmif_requests = true; - dceip.linear_mode_line_request_alternation_slice = - bw_int_to_fixed(64); - dceip.scatter_gather_lines_of_pte_prefetching_in_linear_mode = - 32; - dceip.display_write_back420_luma_mcifwr_buffer_size = 12288; - dceip.display_write_back420_chroma_mcifwr_buffer_size = 8192; - dceip.request_efficiency = bw_frc_to_fixed(8, 10); - dceip.dispclk_per_request = bw_int_to_fixed(2); - dceip.dispclk_ramping_factor = bw_frc_to_fixed(105, 100); - dceip.display_pipe_throughput_factor = bw_frc_to_fixed(105, 100); - dceip.scatter_gather_pte_request_rows_in_tiling_mode = 2; - dceip.mcifwr_all_surfaces_burst_time = bw_int_to_fixed(0); - break; - case BW_CALCS_VERSION_STONEY: - vbios.memory_type = bw_def_gddr5; - vbios.dram_channel_width_in_bits = 64; - vbios.number_of_dram_channels = asic_id.vram_width / vbios.dram_channel_width_in_bits; - vbios.number_of_dram_banks = 8; - vbios.high_yclk = bw_int_to_fixed(1866); - vbios.mid_yclk = bw_int_to_fixed(1866); - vbios.low_yclk = bw_int_to_fixed(1333); - vbios.low_sclk = bw_int_to_fixed(200); - vbios.mid1_sclk = bw_int_to_fixed(600); - vbios.mid2_sclk = bw_int_to_fixed(600); - vbios.mid3_sclk = bw_int_to_fixed(600); - vbios.mid4_sclk = bw_int_to_fixed(600); - vbios.mid5_sclk = bw_int_to_fixed(600); - vbios.mid6_sclk = bw_int_to_fixed(600); - vbios.high_sclk = bw_int_to_fixed(800); - vbios.low_voltage_max_dispclk = bw_int_to_fixed(352); - vbios.mid_voltage_max_dispclk = bw_int_to_fixed(467); - vbios.high_voltage_max_dispclk = bw_int_to_fixed(643); - vbios.low_voltage_max_phyclk = bw_int_to_fixed(540); - vbios.mid_voltage_max_phyclk = bw_int_to_fixed(810); - vbios.high_voltage_max_phyclk = bw_int_to_fixed(810); - vbios.data_return_bus_width = bw_int_to_fixed(32); - vbios.trc = bw_int_to_fixed(50); - vbios.dmifmc_urgent_latency = bw_int_to_fixed(4); - vbios.stutter_self_refresh_exit_latency = bw_frc_to_fixed(158, 10); - vbios.stutter_self_refresh_entry_latency = bw_int_to_fixed(0); - vbios.nbp_state_change_latency = bw_frc_to_fixed(2008, 100); - vbios.mcifwrmc_urgent_latency = bw_int_to_fixed(10); - vbios.scatter_gather_enable = true; - vbios.down_spread_percentage = bw_frc_to_fixed(5, 10); - vbios.cursor_width = 32; - vbios.average_compression_rate = 4; - vbios.number_of_request_slots_gmc_reserves_for_dmif_per_channel = 256; - vbios.blackout_duration = bw_int_to_fixed(18); /* us */ - vbios.maximum_blackout_recovery_time = bw_int_to_fixed(20); - - dceip.large_cursor = false; - dceip.dmif_request_buffer_size = bw_int_to_fixed(768); - dceip.dmif_pipe_en_fbc_chunk_tracker = false; - dceip.cursor_max_outstanding_group_num = 1; - dceip.lines_interleaved_into_lb = 2; - dceip.chunk_width = 256; - dceip.number_of_graphics_pipes = 2; - dceip.number_of_underlay_pipes = 1; - dceip.low_power_tiling_mode = 0; - dceip.display_write_back_supported = false; - dceip.argb_compression_support = true; - dceip.underlay_vscaler_efficiency6_bit_per_component = - bw_frc_to_fixed(35556, 10000); - dceip.underlay_vscaler_efficiency8_bit_per_component = - bw_frc_to_fixed(34286, 10000); - dceip.underlay_vscaler_efficiency10_bit_per_component = - bw_frc_to_fixed(32, 10); - dceip.underlay_vscaler_efficiency12_bit_per_component = - bw_int_to_fixed(3); - dceip.graphics_vscaler_efficiency6_bit_per_component = - bw_frc_to_fixed(35, 10); - dceip.graphics_vscaler_efficiency8_bit_per_component = - bw_frc_to_fixed(34286, 10000); - dceip.graphics_vscaler_efficiency10_bit_per_component = - bw_frc_to_fixed(32, 10); - dceip.graphics_vscaler_efficiency12_bit_per_component = - bw_int_to_fixed(3); - dceip.alpha_vscaler_efficiency = bw_int_to_fixed(3); - dceip.max_dmif_buffer_allocated = 2; - dceip.graphics_dmif_size = 12288; - dceip.underlay_luma_dmif_size = 19456; - dceip.underlay_chroma_dmif_size = 23552; - dceip.pre_downscaler_enabled = true; - dceip.underlay_downscale_prefetch_enabled = true; - dceip.lb_write_pixels_per_dispclk = bw_int_to_fixed(1); - dceip.lb_size_per_component444 = bw_int_to_fixed(82176); - dceip.graphics_lb_nodownscaling_multi_line_prefetching = false; - dceip.stutter_and_dram_clock_state_change_gated_before_cursor = - bw_int_to_fixed(0); - dceip.underlay420_luma_lb_size_per_component = bw_int_to_fixed( - 82176); - dceip.underlay420_chroma_lb_size_per_component = - bw_int_to_fixed(164352); - dceip.underlay422_lb_size_per_component = bw_int_to_fixed( - 82176); - dceip.cursor_chunk_width = bw_int_to_fixed(64); - dceip.cursor_dcp_buffer_lines = bw_int_to_fixed(4); - dceip.underlay_maximum_width_efficient_for_tiling = - bw_int_to_fixed(1920); - dceip.underlay_maximum_height_efficient_for_tiling = - bw_int_to_fixed(1080); - dceip.peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display = - bw_frc_to_fixed(3, 10); - dceip.peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation = - bw_int_to_fixed(25); - dceip.minimum_outstanding_pte_request_limit = bw_int_to_fixed( - 2); - dceip.maximum_total_outstanding_pte_requests_allowed_by_saw = - bw_int_to_fixed(128); - dceip.limit_excessive_outstanding_dmif_requests = true; - dceip.linear_mode_line_request_alternation_slice = - bw_int_to_fixed(64); - dceip.scatter_gather_lines_of_pte_prefetching_in_linear_mode = - 32; - dceip.display_write_back420_luma_mcifwr_buffer_size = 12288; - dceip.display_write_back420_chroma_mcifwr_buffer_size = 8192; - dceip.request_efficiency = bw_frc_to_fixed(8, 10); - dceip.dispclk_per_request = bw_int_to_fixed(2); - dceip.dispclk_ramping_factor = bw_frc_to_fixed(105, 100); - dceip.display_pipe_throughput_factor = bw_frc_to_fixed(105, 100); - dceip.scatter_gather_pte_request_rows_in_tiling_mode = 2; - dceip.mcifwr_all_surfaces_burst_time = bw_int_to_fixed(0); - break; - default: - break; - } - *bw_dceip = dceip; - *bw_vbios = vbios; - -} - -/** - * Compare calculated (required) clocks against the clocks available at - * maximum voltage (max Performance Level). - */ -static bool is_display_configuration_supported( - const struct bw_calcs_vbios *vbios, - const struct bw_calcs_output *calcs_output) -{ - uint32_t int_max_clk; - - int_max_clk = bw_fixed_to_int(vbios->high_voltage_max_dispclk); - int_max_clk *= 1000; /* MHz to kHz */ - if (calcs_output->dispclk_khz > int_max_clk) - return false; - - int_max_clk = bw_fixed_to_int(vbios->high_sclk); - int_max_clk *= 1000; /* MHz to kHz */ - if (calcs_output->required_sclk > int_max_clk) - return false; - - return true; -} - -static void populate_initial_data( - const struct pipe_ctx pipe[], int pipe_count, struct bw_calcs_data *data) -{ - int i, j; - int num_displays = 0; - - data->underlay_surface_type = bw_def_420; - data->panning_and_bezel_adjustment = bw_def_none; - data->graphics_lb_bpc = 10; - data->underlay_lb_bpc = 8; - data->underlay_tiling_mode = bw_def_tiled; - data->graphics_tiling_mode = bw_def_tiled; - data->underlay_micro_tile_mode = bw_def_display_micro_tiling; - data->graphics_micro_tile_mode = bw_def_display_micro_tiling; - - /* Pipes with underlay first */ - for (i = 0; i < pipe_count; i++) { - if (!pipe[i].stream || !pipe[i].bottom_pipe) - continue; - - ASSERT(pipe[i].surface); - - if (num_displays == 0) { - if (!pipe[i].surface->public.visible) - data->d0_underlay_mode = bw_def_underlay_only; - else - data->d0_underlay_mode = bw_def_blend; - } else { - if (!pipe[i].surface->public.visible) - data->d1_underlay_mode = bw_def_underlay_only; - else - data->d1_underlay_mode = bw_def_blend; - } - - data->fbc_en[num_displays + 4] = false; - data->lpt_en[num_displays + 4] = false; - data->h_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->public.timing.h_total); - data->v_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->public.timing.v_total); - data->pixel_rate[num_displays + 4] = bw_frc_to_fixed(pipe[i].stream->public.timing.pix_clk_khz, 1000); - data->src_width[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.viewport.width); - data->pitch_in_pixels[num_displays + 4] = bw_int_to_fixed(pipe[i].surface->public.plane_size.grph.surface_pitch); - data->src_height[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.viewport.height); - data->h_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.taps.h_taps); - data->v_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.taps.v_taps); - data->h_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].scl_data.ratios.horz.value); - data->v_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].scl_data.ratios.vert.value); - switch (pipe[i].surface->public.rotation) { - case ROTATION_ANGLE_0: - data->rotation_angle[num_displays + 4] = bw_int_to_fixed(0); - break; - case ROTATION_ANGLE_90: - data->rotation_angle[num_displays + 4] = bw_int_to_fixed(90); - break; - case ROTATION_ANGLE_180: - data->rotation_angle[num_displays + 4] = bw_int_to_fixed(180); - break; - case ROTATION_ANGLE_270: - data->rotation_angle[num_displays + 4] = bw_int_to_fixed(270); - break; - default: - break; - } - switch (pipe[i].surface->public.format) { - case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: - case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: - case SURFACE_PIXEL_FORMAT_GRPH_RGB565: - data->bytes_per_pixel[num_displays + 4] = 2; - break; - case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: - case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: - case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: - case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: - case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: - case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: - case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: - data->bytes_per_pixel[num_displays + 4] = 4; - break; - case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: - case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: - data->bytes_per_pixel[num_displays + 4] = 8; - break; - default: - data->bytes_per_pixel[num_displays + 4] = 4; - break; - } - data->interlace_mode[num_displays + 4] = false; - data->stereo_mode[num_displays + 4] = bw_def_mono; - - - for (j = 0; j < 2; j++) { - data->fbc_en[num_displays * 2 + j] = false; - data->lpt_en[num_displays * 2 + j] = false; - - data->src_height[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->scl_data.viewport.height); - data->src_width[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->scl_data.viewport.width); - data->pitch_in_pixels[num_displays * 2 + j] = bw_int_to_fixed( - pipe[i].bottom_pipe->surface->public.plane_size.grph.surface_pitch); - data->h_taps[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->scl_data.taps.h_taps); - data->v_taps[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->scl_data.taps.v_taps); - data->h_scale_ratio[num_displays * 2 + j] = fixed31_32_to_bw_fixed( - pipe[i].bottom_pipe->scl_data.ratios.horz.value); - data->v_scale_ratio[num_displays * 2 + j] = fixed31_32_to_bw_fixed( - pipe[i].bottom_pipe->scl_data.ratios.vert.value); - switch (pipe[i].bottom_pipe->surface->public.rotation) { - case ROTATION_ANGLE_0: - data->rotation_angle[num_displays * 2 + j] = bw_int_to_fixed(0); - break; - case ROTATION_ANGLE_90: - data->rotation_angle[num_displays * 2 + j] = bw_int_to_fixed(90); - break; - case ROTATION_ANGLE_180: - data->rotation_angle[num_displays * 2 + j] = bw_int_to_fixed(180); - break; - case ROTATION_ANGLE_270: - data->rotation_angle[num_displays * 2 + j] = bw_int_to_fixed(270); - break; - default: - break; - } - data->stereo_mode[num_displays * 2 + j] = bw_def_mono; - } - - num_displays++; - } - - /* Pipes without underlay after */ - for (i = 0; i < pipe_count; i++) { - if (!pipe[i].stream || pipe[i].bottom_pipe) - continue; - - - data->fbc_en[num_displays + 4] = false; - data->lpt_en[num_displays + 4] = false; - data->h_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->public.timing.h_total); - data->v_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->public.timing.v_total); - data->pixel_rate[num_displays + 4] = bw_frc_to_fixed(pipe[i].stream->public.timing.pix_clk_khz, 1000); - if (pipe[i].surface) { - data->src_width[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.viewport.width); - data->pitch_in_pixels[num_displays + 4] = bw_int_to_fixed(pipe[i].surface->public.plane_size.grph.surface_pitch); - data->src_height[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.viewport.height); - data->h_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.taps.h_taps); - data->v_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.taps.v_taps); - data->h_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].scl_data.ratios.horz.value); - data->v_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].scl_data.ratios.vert.value); - switch (pipe[i].surface->public.rotation) { - case ROTATION_ANGLE_0: - data->rotation_angle[num_displays + 4] = bw_int_to_fixed(0); - break; - case ROTATION_ANGLE_90: - data->rotation_angle[num_displays + 4] = bw_int_to_fixed(90); - break; - case ROTATION_ANGLE_180: - data->rotation_angle[num_displays + 4] = bw_int_to_fixed(180); - break; - case ROTATION_ANGLE_270: - data->rotation_angle[num_displays + 4] = bw_int_to_fixed(270); - break; - default: - break; - } - switch (pipe[i].surface->public.format) { - case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: - case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: - case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: - case SURFACE_PIXEL_FORMAT_GRPH_RGB565: - data->bytes_per_pixel[num_displays + 4] = 2; - break; - case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: - case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: - case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: - case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: - case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: - case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: - case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: - data->bytes_per_pixel[num_displays + 4] = 4; - break; - case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: - case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: - data->bytes_per_pixel[num_displays + 4] = 8; - break; - default: - data->bytes_per_pixel[num_displays + 4] = 4; - break; - } - } else { - data->src_width[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->public.timing.h_addressable); - data->pitch_in_pixels[num_displays + 4] = data->src_width[num_displays + 4]; - data->src_height[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->public.timing.v_addressable); - data->h_taps[num_displays + 4] = bw_int_to_fixed(1); - data->v_taps[num_displays + 4] = bw_int_to_fixed(1); - data->h_scale_ratio[num_displays + 4] = bw_int_to_fixed(1); - data->v_scale_ratio[num_displays + 4] = bw_int_to_fixed(1); - data->rotation_angle[num_displays + 4] = bw_int_to_fixed(0); - data->bytes_per_pixel[num_displays + 4] = 4; - } - - data->interlace_mode[num_displays + 4] = false; - data->stereo_mode[num_displays + 4] = bw_def_mono; - num_displays++; - } - - data->number_of_displays = num_displays; -} - -/** - * Return: - * true - Display(s) configuration supported. - * In this case 'calcs_output' contains data for HW programming - * false - Display(s) configuration not supported (not enough bandwidth). - */ - -bool bw_calcs(struct dc_context *ctx, - const struct bw_calcs_dceip *dceip, - const struct bw_calcs_vbios *vbios, - const struct pipe_ctx pipe[], - int pipe_count, - struct bw_calcs_output *calcs_output) -{ - struct bw_calcs_data *data = dm_alloc(sizeof(struct bw_calcs_data)); - - populate_initial_data(pipe, pipe_count, data); - - /*TODO: this should be taken out calcs output and assigned during timing sync for pplib use*/ - calcs_output->all_displays_in_sync = false; - - if (data->number_of_displays != 0) { - uint8_t yclk_lvl, sclk_lvl; - struct bw_fixed high_sclk = vbios->high_sclk; - struct bw_fixed mid1_sclk = vbios->mid1_sclk; - struct bw_fixed mid2_sclk = vbios->mid2_sclk; - struct bw_fixed mid3_sclk = vbios->mid3_sclk; - struct bw_fixed mid4_sclk = vbios->mid4_sclk; - struct bw_fixed mid5_sclk = vbios->mid5_sclk; - struct bw_fixed mid6_sclk = vbios->mid6_sclk; - struct bw_fixed low_sclk = vbios->low_sclk; - struct bw_fixed high_yclk = vbios->high_yclk; - struct bw_fixed mid_yclk = vbios->mid_yclk; - struct bw_fixed low_yclk = vbios->low_yclk; - - calculate_bandwidth(dceip, vbios, data); - - yclk_lvl = data->y_clk_level; - sclk_lvl = data->sclk_level; - - calcs_output->nbp_state_change_enable = - data->nbp_state_change_enable; - calcs_output->cpuc_state_change_enable = - data->cpuc_state_change_enable; - calcs_output->cpup_state_change_enable = - data->cpup_state_change_enable; - calcs_output->stutter_mode_enable = - data->stutter_mode_enable; - calcs_output->dispclk_khz = - bw_fixed_to_int(bw_mul(data->dispclk, - bw_int_to_fixed(1000))); - calcs_output->blackout_recovery_time_us = - bw_fixed_to_int(data->blackout_recovery_time); - calcs_output->required_sclk = - bw_fixed_to_int(bw_mul(data->required_sclk, - bw_int_to_fixed(1000))); - calcs_output->required_sclk_deep_sleep = - bw_fixed_to_int(bw_mul(data->sclk_deep_sleep, - bw_int_to_fixed(1000))); - if (yclk_lvl == 0) - calcs_output->required_yclk = bw_fixed_to_int( - bw_mul(low_yclk, bw_int_to_fixed(1000))); - else if (yclk_lvl == 1) - calcs_output->required_yclk = bw_fixed_to_int( - bw_mul(mid_yclk, bw_int_to_fixed(1000))); - else - calcs_output->required_yclk = bw_fixed_to_int( - bw_mul(high_yclk, bw_int_to_fixed(1000))); - - /* units: nanosecond, 16bit storage. */ - - calcs_output->nbp_state_change_wm_ns[0].a_mark = - bw_fixed_to_int(bw_mul(data-> - nbp_state_change_watermark[4], bw_int_to_fixed(1000))); - calcs_output->nbp_state_change_wm_ns[1].a_mark = - bw_fixed_to_int(bw_mul(data-> - nbp_state_change_watermark[5], bw_int_to_fixed(1000))); - calcs_output->nbp_state_change_wm_ns[2].a_mark = - bw_fixed_to_int(bw_mul(data-> - nbp_state_change_watermark[6], bw_int_to_fixed(1000))); - - if (ctx->dc->caps.max_slave_planes) { - calcs_output->nbp_state_change_wm_ns[3].a_mark = - bw_fixed_to_int(bw_mul(data-> - nbp_state_change_watermark[0], bw_int_to_fixed(1000))); - calcs_output->nbp_state_change_wm_ns[4].a_mark = - bw_fixed_to_int(bw_mul(data-> - nbp_state_change_watermark[1], bw_int_to_fixed(1000))); - } else { - calcs_output->nbp_state_change_wm_ns[3].a_mark = - bw_fixed_to_int(bw_mul(data-> - nbp_state_change_watermark[7], bw_int_to_fixed(1000))); - calcs_output->nbp_state_change_wm_ns[4].a_mark = - bw_fixed_to_int(bw_mul(data-> - nbp_state_change_watermark[8], bw_int_to_fixed(1000))); - } - calcs_output->nbp_state_change_wm_ns[5].a_mark = - bw_fixed_to_int(bw_mul(data-> - nbp_state_change_watermark[9], bw_int_to_fixed(1000))); - - - - calcs_output->stutter_exit_wm_ns[0].a_mark = - bw_fixed_to_int(bw_mul(data-> - stutter_exit_watermark[4], bw_int_to_fixed(1000))); - calcs_output->stutter_exit_wm_ns[1].a_mark = - bw_fixed_to_int(bw_mul(data-> - stutter_exit_watermark[5], bw_int_to_fixed(1000))); - calcs_output->stutter_exit_wm_ns[2].a_mark = - bw_fixed_to_int(bw_mul(data-> - stutter_exit_watermark[6], bw_int_to_fixed(1000))); - if (ctx->dc->caps.max_slave_planes) { - calcs_output->stutter_exit_wm_ns[3].a_mark = - bw_fixed_to_int(bw_mul(data-> - stutter_exit_watermark[0], bw_int_to_fixed(1000))); - calcs_output->stutter_exit_wm_ns[4].a_mark = - bw_fixed_to_int(bw_mul(data-> - stutter_exit_watermark[1], bw_int_to_fixed(1000))); - } else { - calcs_output->stutter_exit_wm_ns[3].a_mark = - bw_fixed_to_int(bw_mul(data-> - stutter_exit_watermark[7], bw_int_to_fixed(1000))); - calcs_output->stutter_exit_wm_ns[4].a_mark = - bw_fixed_to_int(bw_mul(data-> - stutter_exit_watermark[8], bw_int_to_fixed(1000))); - } - calcs_output->stutter_exit_wm_ns[5].a_mark = - bw_fixed_to_int(bw_mul(data-> - stutter_exit_watermark[9], bw_int_to_fixed(1000))); - - - - calcs_output->urgent_wm_ns[0].a_mark = - bw_fixed_to_int(bw_mul(data-> - urgent_watermark[4], bw_int_to_fixed(1000))); - calcs_output->urgent_wm_ns[1].a_mark = - bw_fixed_to_int(bw_mul(data-> - urgent_watermark[5], bw_int_to_fixed(1000))); - calcs_output->urgent_wm_ns[2].a_mark = - bw_fixed_to_int(bw_mul(data-> - urgent_watermark[6], bw_int_to_fixed(1000))); - if (ctx->dc->caps.max_slave_planes) { - calcs_output->urgent_wm_ns[3].a_mark = - bw_fixed_to_int(bw_mul(data-> - urgent_watermark[0], bw_int_to_fixed(1000))); - calcs_output->urgent_wm_ns[4].a_mark = - bw_fixed_to_int(bw_mul(data-> - urgent_watermark[1], bw_int_to_fixed(1000))); - } else { - calcs_output->urgent_wm_ns[3].a_mark = - bw_fixed_to_int(bw_mul(data-> - urgent_watermark[7], bw_int_to_fixed(1000))); - calcs_output->urgent_wm_ns[4].a_mark = - bw_fixed_to_int(bw_mul(data-> - urgent_watermark[8], bw_int_to_fixed(1000))); - } - calcs_output->urgent_wm_ns[5].a_mark = - bw_fixed_to_int(bw_mul(data-> - urgent_watermark[9], bw_int_to_fixed(1000))); - - if (dceip->version != BW_CALCS_VERSION_CARRIZO) { - ((struct bw_calcs_vbios *)vbios)->low_sclk = mid3_sclk; - ((struct bw_calcs_vbios *)vbios)->mid1_sclk = mid3_sclk; - ((struct bw_calcs_vbios *)vbios)->mid2_sclk = mid3_sclk; - calculate_bandwidth(dceip, vbios, data); - - calcs_output->nbp_state_change_wm_ns[0].b_mark = - bw_fixed_to_int(bw_mul(data-> - nbp_state_change_watermark[4],bw_int_to_fixed(1000))); - calcs_output->nbp_state_change_wm_ns[1].b_mark = - bw_fixed_to_int(bw_mul(data-> - nbp_state_change_watermark[5], bw_int_to_fixed(1000))); - calcs_output->nbp_state_change_wm_ns[2].b_mark = - bw_fixed_to_int(bw_mul(data-> - nbp_state_change_watermark[6], bw_int_to_fixed(1000))); - - if (ctx->dc->caps.max_slave_planes) { - calcs_output->nbp_state_change_wm_ns[3].b_mark = - bw_fixed_to_int(bw_mul(data-> - nbp_state_change_watermark[0], bw_int_to_fixed(1000))); - calcs_output->nbp_state_change_wm_ns[4].b_mark = - bw_fixed_to_int(bw_mul(data-> - nbp_state_change_watermark[1], bw_int_to_fixed(1000))); - } else { - calcs_output->nbp_state_change_wm_ns[3].b_mark = - bw_fixed_to_int(bw_mul(data-> - nbp_state_change_watermark[7], bw_int_to_fixed(1000))); - calcs_output->nbp_state_change_wm_ns[4].b_mark = - bw_fixed_to_int(bw_mul(data-> - nbp_state_change_watermark[8], bw_int_to_fixed(1000))); - } - calcs_output->nbp_state_change_wm_ns[5].b_mark = - bw_fixed_to_int(bw_mul(data-> - nbp_state_change_watermark[9], bw_int_to_fixed(1000))); - - - - calcs_output->stutter_exit_wm_ns[0].b_mark = - bw_fixed_to_int(bw_mul(data-> - stutter_exit_watermark[4], bw_int_to_fixed(1000))); - calcs_output->stutter_exit_wm_ns[1].b_mark = - bw_fixed_to_int(bw_mul(data-> - stutter_exit_watermark[5], bw_int_to_fixed(1000))); - calcs_output->stutter_exit_wm_ns[2].b_mark = - bw_fixed_to_int(bw_mul(data-> - stutter_exit_watermark[6], bw_int_to_fixed(1000))); - if (ctx->dc->caps.max_slave_planes) { - calcs_output->stutter_exit_wm_ns[3].b_mark = - bw_fixed_to_int(bw_mul(data-> - stutter_exit_watermark[0], bw_int_to_fixed(1000))); - calcs_output->stutter_exit_wm_ns[4].b_mark = - bw_fixed_to_int(bw_mul(data-> - stutter_exit_watermark[1], bw_int_to_fixed(1000))); - } else { - calcs_output->stutter_exit_wm_ns[3].b_mark = - bw_fixed_to_int(bw_mul(data-> - stutter_exit_watermark[7], bw_int_to_fixed(1000))); - calcs_output->stutter_exit_wm_ns[4].b_mark = - bw_fixed_to_int(bw_mul(data-> - stutter_exit_watermark[8], bw_int_to_fixed(1000))); - } - calcs_output->stutter_exit_wm_ns[5].b_mark = - bw_fixed_to_int(bw_mul(data-> - stutter_exit_watermark[9], bw_int_to_fixed(1000))); - - - - calcs_output->urgent_wm_ns[0].b_mark = - bw_fixed_to_int(bw_mul(data-> - urgent_watermark[4], bw_int_to_fixed(1000))); - calcs_output->urgent_wm_ns[1].b_mark = - bw_fixed_to_int(bw_mul(data-> - urgent_watermark[5], bw_int_to_fixed(1000))); - calcs_output->urgent_wm_ns[2].b_mark = - bw_fixed_to_int(bw_mul(data-> - urgent_watermark[6], bw_int_to_fixed(1000))); - if (ctx->dc->caps.max_slave_planes) { - calcs_output->urgent_wm_ns[3].b_mark = - bw_fixed_to_int(bw_mul(data-> - urgent_watermark[0], bw_int_to_fixed(1000))); - calcs_output->urgent_wm_ns[4].b_mark = - bw_fixed_to_int(bw_mul(data-> - urgent_watermark[1], bw_int_to_fixed(1000))); - } else { - calcs_output->urgent_wm_ns[3].b_mark = - bw_fixed_to_int(bw_mul(data-> - urgent_watermark[7], bw_int_to_fixed(1000))); - calcs_output->urgent_wm_ns[4].b_mark = - bw_fixed_to_int(bw_mul(data-> - urgent_watermark[8], bw_int_to_fixed(1000))); - } - calcs_output->urgent_wm_ns[5].b_mark = - bw_fixed_to_int(bw_mul(data-> - urgent_watermark[9], bw_int_to_fixed(1000))); - - ((struct bw_calcs_vbios *)vbios)->low_sclk = low_sclk; - ((struct bw_calcs_vbios *)vbios)->mid1_sclk = mid1_sclk; - ((struct bw_calcs_vbios *)vbios)->mid2_sclk = mid2_sclk; - ((struct bw_calcs_vbios *)vbios)->low_yclk = mid_yclk; - calculate_bandwidth(dceip, vbios, data); - - calcs_output->nbp_state_change_wm_ns[0].c_mark = - bw_fixed_to_int(bw_mul(data-> - nbp_state_change_watermark[4], bw_int_to_fixed(1000))); - calcs_output->nbp_state_change_wm_ns[1].c_mark = - bw_fixed_to_int(bw_mul(data-> - nbp_state_change_watermark[5], bw_int_to_fixed(1000))); - calcs_output->nbp_state_change_wm_ns[2].c_mark = - bw_fixed_to_int(bw_mul(data-> - nbp_state_change_watermark[6], bw_int_to_fixed(1000))); - if (ctx->dc->caps.max_slave_planes) { - calcs_output->nbp_state_change_wm_ns[3].c_mark = - bw_fixed_to_int(bw_mul(data-> - nbp_state_change_watermark[0], bw_int_to_fixed(1000))); - calcs_output->nbp_state_change_wm_ns[4].c_mark = - bw_fixed_to_int(bw_mul(data-> - nbp_state_change_watermark[1], bw_int_to_fixed(1000))); - } else { - calcs_output->nbp_state_change_wm_ns[3].c_mark = - bw_fixed_to_int(bw_mul(data-> - nbp_state_change_watermark[7], bw_int_to_fixed(1000))); - calcs_output->nbp_state_change_wm_ns[4].c_mark = - bw_fixed_to_int(bw_mul(data-> - nbp_state_change_watermark[8], bw_int_to_fixed(1000))); - } - calcs_output->nbp_state_change_wm_ns[5].c_mark = - bw_fixed_to_int(bw_mul(data-> - nbp_state_change_watermark[9], bw_int_to_fixed(1000))); - - - calcs_output->stutter_exit_wm_ns[0].c_mark = - bw_fixed_to_int(bw_mul(data-> - stutter_exit_watermark[4], bw_int_to_fixed(1000))); - calcs_output->stutter_exit_wm_ns[1].c_mark = - bw_fixed_to_int(bw_mul(data-> - stutter_exit_watermark[5], bw_int_to_fixed(1000))); - calcs_output->stutter_exit_wm_ns[2].c_mark = - bw_fixed_to_int(bw_mul(data-> - stutter_exit_watermark[6], bw_int_to_fixed(1000))); - if (ctx->dc->caps.max_slave_planes) { - calcs_output->stutter_exit_wm_ns[3].c_mark = - bw_fixed_to_int(bw_mul(data-> - stutter_exit_watermark[0], bw_int_to_fixed(1000))); - calcs_output->stutter_exit_wm_ns[4].c_mark = - bw_fixed_to_int(bw_mul(data-> - stutter_exit_watermark[1], bw_int_to_fixed(1000))); - } else { - calcs_output->stutter_exit_wm_ns[3].c_mark = - bw_fixed_to_int(bw_mul(data-> - stutter_exit_watermark[7], bw_int_to_fixed(1000))); - calcs_output->stutter_exit_wm_ns[4].c_mark = - bw_fixed_to_int(bw_mul(data-> - stutter_exit_watermark[8], bw_int_to_fixed(1000))); - } - calcs_output->stutter_exit_wm_ns[5].c_mark = - bw_fixed_to_int(bw_mul(data-> - stutter_exit_watermark[9], bw_int_to_fixed(1000))); - - calcs_output->urgent_wm_ns[0].c_mark = - bw_fixed_to_int(bw_mul(data-> - urgent_watermark[4], bw_int_to_fixed(1000))); - calcs_output->urgent_wm_ns[1].c_mark = - bw_fixed_to_int(bw_mul(data-> - urgent_watermark[5], bw_int_to_fixed(1000))); - calcs_output->urgent_wm_ns[2].c_mark = - bw_fixed_to_int(bw_mul(data-> - urgent_watermark[6], bw_int_to_fixed(1000))); - if (ctx->dc->caps.max_slave_planes) { - calcs_output->urgent_wm_ns[3].c_mark = - bw_fixed_to_int(bw_mul(data-> - urgent_watermark[0], bw_int_to_fixed(1000))); - calcs_output->urgent_wm_ns[4].c_mark = - bw_fixed_to_int(bw_mul(data-> - urgent_watermark[1], bw_int_to_fixed(1000))); - } else { - calcs_output->urgent_wm_ns[3].c_mark = - bw_fixed_to_int(bw_mul(data-> - urgent_watermark[7], bw_int_to_fixed(1000))); - calcs_output->urgent_wm_ns[4].c_mark = - bw_fixed_to_int(bw_mul(data-> - urgent_watermark[8], bw_int_to_fixed(1000))); - } - calcs_output->urgent_wm_ns[5].c_mark = - bw_fixed_to_int(bw_mul(data-> - urgent_watermark[9], bw_int_to_fixed(1000))); - } - - if (dceip->version == BW_CALCS_VERSION_CARRIZO) { - ((struct bw_calcs_vbios *)vbios)->low_yclk = high_yclk; - ((struct bw_calcs_vbios *)vbios)->mid_yclk = high_yclk; - ((struct bw_calcs_vbios *)vbios)->low_sclk = high_sclk; - ((struct bw_calcs_vbios *)vbios)->mid1_sclk = high_sclk; - ((struct bw_calcs_vbios *)vbios)->mid2_sclk = high_sclk; - ((struct bw_calcs_vbios *)vbios)->mid3_sclk = high_sclk; - ((struct bw_calcs_vbios *)vbios)->mid4_sclk = high_sclk; - ((struct bw_calcs_vbios *)vbios)->mid5_sclk = high_sclk; - ((struct bw_calcs_vbios *)vbios)->mid6_sclk = high_sclk; - } else { - ((struct bw_calcs_vbios *)vbios)->low_yclk = mid_yclk; - ((struct bw_calcs_vbios *)vbios)->low_sclk = mid3_sclk; - ((struct bw_calcs_vbios *)vbios)->mid1_sclk = mid3_sclk; - ((struct bw_calcs_vbios *)vbios)->mid2_sclk = mid3_sclk; - } - - calculate_bandwidth(dceip, vbios, data); - - calcs_output->nbp_state_change_wm_ns[0].d_mark = - bw_fixed_to_int(bw_mul(data-> - nbp_state_change_watermark[4], bw_int_to_fixed(1000))); - calcs_output->nbp_state_change_wm_ns[1].d_mark = - bw_fixed_to_int(bw_mul(data-> - nbp_state_change_watermark[5], bw_int_to_fixed(1000))); - calcs_output->nbp_state_change_wm_ns[2].d_mark = - bw_fixed_to_int(bw_mul(data-> - nbp_state_change_watermark[6], bw_int_to_fixed(1000))); - if (ctx->dc->caps.max_slave_planes) { - calcs_output->nbp_state_change_wm_ns[3].d_mark = - bw_fixed_to_int(bw_mul(data-> - nbp_state_change_watermark[0], bw_int_to_fixed(1000))); - calcs_output->nbp_state_change_wm_ns[4].d_mark = - bw_fixed_to_int(bw_mul(data-> - nbp_state_change_watermark[1], bw_int_to_fixed(1000))); - } else { - calcs_output->nbp_state_change_wm_ns[3].d_mark = - bw_fixed_to_int(bw_mul(data-> - nbp_state_change_watermark[7], bw_int_to_fixed(1000))); - calcs_output->nbp_state_change_wm_ns[4].d_mark = - bw_fixed_to_int(bw_mul(data-> - nbp_state_change_watermark[8], bw_int_to_fixed(1000))); - } - calcs_output->nbp_state_change_wm_ns[5].d_mark = - bw_fixed_to_int(bw_mul(data-> - nbp_state_change_watermark[9], bw_int_to_fixed(1000))); - - calcs_output->stutter_exit_wm_ns[0].d_mark = - bw_fixed_to_int(bw_mul(data-> - stutter_exit_watermark[4], bw_int_to_fixed(1000))); - calcs_output->stutter_exit_wm_ns[1].d_mark = - bw_fixed_to_int(bw_mul(data-> - stutter_exit_watermark[5], bw_int_to_fixed(1000))); - calcs_output->stutter_exit_wm_ns[2].d_mark = - bw_fixed_to_int(bw_mul(data-> - stutter_exit_watermark[6], bw_int_to_fixed(1000))); - if (ctx->dc->caps.max_slave_planes) { - calcs_output->stutter_exit_wm_ns[3].d_mark = - bw_fixed_to_int(bw_mul(data-> - stutter_exit_watermark[0], bw_int_to_fixed(1000))); - calcs_output->stutter_exit_wm_ns[4].d_mark = - bw_fixed_to_int(bw_mul(data-> - stutter_exit_watermark[1], bw_int_to_fixed(1000))); - } else { - calcs_output->stutter_exit_wm_ns[3].d_mark = - bw_fixed_to_int(bw_mul(data-> - stutter_exit_watermark[7], bw_int_to_fixed(1000))); - calcs_output->stutter_exit_wm_ns[4].d_mark = - bw_fixed_to_int(bw_mul(data-> - stutter_exit_watermark[8], bw_int_to_fixed(1000))); - } - calcs_output->stutter_exit_wm_ns[5].d_mark = - bw_fixed_to_int(bw_mul(data-> - stutter_exit_watermark[9], bw_int_to_fixed(1000))); - - - calcs_output->urgent_wm_ns[0].d_mark = - bw_fixed_to_int(bw_mul(data-> - urgent_watermark[4], bw_int_to_fixed(1000))); - calcs_output->urgent_wm_ns[1].d_mark = - bw_fixed_to_int(bw_mul(data-> - urgent_watermark[5], bw_int_to_fixed(1000))); - calcs_output->urgent_wm_ns[2].d_mark = - bw_fixed_to_int(bw_mul(data-> - urgent_watermark[6], bw_int_to_fixed(1000))); - if (ctx->dc->caps.max_slave_planes) { - calcs_output->urgent_wm_ns[3].d_mark = - bw_fixed_to_int(bw_mul(data-> - urgent_watermark[0], bw_int_to_fixed(1000))); - calcs_output->urgent_wm_ns[4].d_mark = - bw_fixed_to_int(bw_mul(data-> - urgent_watermark[1], bw_int_to_fixed(1000))); - } else { - calcs_output->urgent_wm_ns[3].d_mark = - bw_fixed_to_int(bw_mul(data-> - urgent_watermark[7], bw_int_to_fixed(1000))); - calcs_output->urgent_wm_ns[4].d_mark = - bw_fixed_to_int(bw_mul(data-> - urgent_watermark[8], bw_int_to_fixed(1000))); - } - calcs_output->urgent_wm_ns[5].d_mark = - bw_fixed_to_int(bw_mul(data-> - urgent_watermark[9], bw_int_to_fixed(1000))); - - ((struct bw_calcs_vbios *)vbios)->low_yclk = low_yclk; - ((struct bw_calcs_vbios *)vbios)->mid_yclk = mid_yclk; - ((struct bw_calcs_vbios *)vbios)->low_sclk = low_sclk; - ((struct bw_calcs_vbios *)vbios)->mid1_sclk = mid1_sclk; - ((struct bw_calcs_vbios *)vbios)->mid2_sclk = mid2_sclk; - ((struct bw_calcs_vbios *)vbios)->mid3_sclk = mid3_sclk; - ((struct bw_calcs_vbios *)vbios)->mid4_sclk = mid4_sclk; - ((struct bw_calcs_vbios *)vbios)->mid5_sclk = mid5_sclk; - ((struct bw_calcs_vbios *)vbios)->mid6_sclk = mid6_sclk; - ((struct bw_calcs_vbios *)vbios)->high_sclk = high_sclk; - } else { - calcs_output->nbp_state_change_enable = true; - calcs_output->cpuc_state_change_enable = true; - calcs_output->cpup_state_change_enable = true; - calcs_output->stutter_mode_enable = true; - calcs_output->dispclk_khz = 0; - calcs_output->required_sclk = 0; - } - - dm_free(data); - - return is_display_configuration_supported(vbios, calcs_output); -} diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c new file mode 100644 index 000000000000..ab8d1e931846 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c @@ -0,0 +1,3141 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "bandwidth_calcs.h" +#include "dc.h" +#include "core_types.h" +#include "dal_asic_id.h" + +/******************************************************************************* + * Private Functions + ******************************************************************************/ + +static enum bw_calcs_version bw_calcs_version_from_asic_id(struct hw_asic_id asic_id) +{ + switch (asic_id.chip_family) { + + case FAMILY_CZ: + if (ASIC_REV_IS_STONEY(asic_id.hw_internal_rev)) + return BW_CALCS_VERSION_STONEY; + return BW_CALCS_VERSION_CARRIZO; + + case FAMILY_VI: + if (ASIC_REV_IS_POLARIS10_P(asic_id.hw_internal_rev)) + return BW_CALCS_VERSION_POLARIS10; + if (ASIC_REV_IS_POLARIS11_M(asic_id.hw_internal_rev) || + ASIC_REV_IS_POLARIS12_V(asic_id.hw_internal_rev)) + return BW_CALCS_VERSION_POLARIS11; + return BW_CALCS_VERSION_INVALID; + + default: + return BW_CALCS_VERSION_INVALID; + } +} + +static void calculate_bandwidth( + const struct bw_calcs_dceip *dceip, + const struct bw_calcs_vbios *vbios, + struct bw_calcs_data *data) + +{ + const int32_t pixels_per_chunk = 512; + const int32_t high = 2; + const int32_t mid = 1; + const int32_t low = 0; + const uint32_t s_low = 0; + const uint32_t s_mid1 = 1; + const uint32_t s_mid2 = 2; + const uint32_t s_mid3 = 3; + const uint32_t s_mid4 = 4; + const uint32_t s_mid5 = 5; + const uint32_t s_mid6 = 6; + const uint32_t s_high = 7; + const uint32_t bus_efficiency = 1; + const uint32_t dmif_chunk_buff_margin = 1; + + uint32_t max_chunks_fbc_mode; + int32_t num_cursor_lines; + + int32_t i, j, k; + struct bw_fixed yclk[3]; + struct bw_fixed sclk[8]; + bool d0_underlay_enable; + bool d1_underlay_enable; + bool fbc_enabled; + bool lpt_enabled; + enum bw_defines sclk_message; + enum bw_defines yclk_message; + enum bw_defines v_filter_init_mode[maximum_number_of_surfaces]; + enum bw_defines tiling_mode[maximum_number_of_surfaces]; + enum bw_defines surface_type[maximum_number_of_surfaces]; + enum bw_defines voltage; + enum bw_defines pipe_check; + enum bw_defines hsr_check; + enum bw_defines vsr_check; + enum bw_defines lb_size_check; + enum bw_defines fbc_check; + enum bw_defines rotation_check; + enum bw_defines mode_check; + enum bw_defines nbp_state_change_enable_blank; + /*initialize variables*/ + int32_t number_of_displays_enabled = 0; + int32_t number_of_displays_enabled_with_margin = 0; + int32_t number_of_aligned_displays_with_no_margin = 0; + + yclk[low] = vbios->low_yclk; + yclk[mid] = vbios->mid_yclk; + yclk[high] = vbios->high_yclk; + sclk[s_low] = vbios->low_sclk; + sclk[s_mid1] = vbios->mid1_sclk; + sclk[s_mid2] = vbios->mid2_sclk; + sclk[s_mid3] = vbios->mid3_sclk; + sclk[s_mid4] = vbios->mid4_sclk; + sclk[s_mid5] = vbios->mid5_sclk; + sclk[s_mid6] = vbios->mid6_sclk; + sclk[s_high] = vbios->high_sclk; + /*''''''''''''''''''*/ + /* surface assignment:*/ + /* 0: d0 underlay or underlay luma*/ + /* 1: d0 underlay chroma*/ + /* 2: d1 underlay or underlay luma*/ + /* 3: d1 underlay chroma*/ + /* 4: d0 graphics*/ + /* 5: d1 graphics*/ + /* 6: d2 graphics*/ + /* 7: d3 graphics, same mode as d2*/ + /* 8: d4 graphics, same mode as d2*/ + /* 9: d5 graphics, same mode as d2*/ + /* ...*/ + /* maximum_number_of_surfaces-2: d1 display_write_back420 luma*/ + /* maximum_number_of_surfaces-1: d1 display_write_back420 chroma*/ + /* underlay luma and chroma surface parameters from spreadsheet*/ + + + + + if (data->d0_underlay_mode == bw_def_none) { d0_underlay_enable = 0; } + else { + d0_underlay_enable = 1; + } + if (data->d1_underlay_mode == bw_def_none) { d1_underlay_enable = 0; } + else { + d1_underlay_enable = 1; + } + data->number_of_underlay_surfaces = d0_underlay_enable + d1_underlay_enable; + switch (data->underlay_surface_type) { + case bw_def_420: + surface_type[0] = bw_def_underlay420_luma; + surface_type[2] = bw_def_underlay420_luma; + data->bytes_per_pixel[0] = 1; + data->bytes_per_pixel[2] = 1; + surface_type[1] = bw_def_underlay420_chroma; + surface_type[3] = bw_def_underlay420_chroma; + data->bytes_per_pixel[1] = 2; + data->bytes_per_pixel[3] = 2; + data->lb_size_per_component[0] = dceip->underlay420_luma_lb_size_per_component; + data->lb_size_per_component[1] = dceip->underlay420_chroma_lb_size_per_component; + data->lb_size_per_component[2] = dceip->underlay420_luma_lb_size_per_component; + data->lb_size_per_component[3] = dceip->underlay420_chroma_lb_size_per_component; + break; + case bw_def_422: + surface_type[0] = bw_def_underlay422; + surface_type[2] = bw_def_underlay422; + data->bytes_per_pixel[0] = 2; + data->bytes_per_pixel[2] = 2; + data->lb_size_per_component[0] = dceip->underlay422_lb_size_per_component; + data->lb_size_per_component[2] = dceip->underlay422_lb_size_per_component; + break; + default: + surface_type[0] = bw_def_underlay444; + surface_type[2] = bw_def_underlay444; + data->bytes_per_pixel[0] = 4; + data->bytes_per_pixel[2] = 4; + data->lb_size_per_component[0] = dceip->lb_size_per_component444; + data->lb_size_per_component[2] = dceip->lb_size_per_component444; + break; + } + if (d0_underlay_enable) { + switch (data->underlay_surface_type) { + case bw_def_420: + data->enable[0] = 1; + data->enable[1] = 1; + break; + default: + data->enable[0] = 1; + data->enable[1] = 0; + break; + } + } + else { + data->enable[0] = 0; + data->enable[1] = 0; + } + if (d1_underlay_enable) { + switch (data->underlay_surface_type) { + case bw_def_420: + data->enable[2] = 1; + data->enable[3] = 1; + break; + default: + data->enable[2] = 1; + data->enable[3] = 0; + break; + } + } + else { + data->enable[2] = 0; + data->enable[3] = 0; + } + data->use_alpha[0] = 0; + data->use_alpha[1] = 0; + data->use_alpha[2] = 0; + data->use_alpha[3] = 0; + data->scatter_gather_enable_for_pipe[0] = vbios->scatter_gather_enable; + data->scatter_gather_enable_for_pipe[1] = vbios->scatter_gather_enable; + data->scatter_gather_enable_for_pipe[2] = vbios->scatter_gather_enable; + data->scatter_gather_enable_for_pipe[3] = vbios->scatter_gather_enable; + /*underlay0 same and graphics display pipe0*/ + data->interlace_mode[0] = data->interlace_mode[4]; + data->interlace_mode[1] = data->interlace_mode[4]; + /*underlay1 same and graphics display pipe1*/ + data->interlace_mode[2] = data->interlace_mode[5]; + data->interlace_mode[3] = data->interlace_mode[5]; + /*underlay0 same and graphics display pipe0*/ + data->h_total[0] = data->h_total[4]; + data->v_total[0] = data->v_total[4]; + data->h_total[1] = data->h_total[4]; + data->v_total[1] = data->v_total[4]; + /*underlay1 same and graphics display pipe1*/ + data->h_total[2] = data->h_total[5]; + data->v_total[2] = data->v_total[5]; + data->h_total[3] = data->h_total[5]; + data->v_total[3] = data->v_total[5]; + /*underlay0 same and graphics display pipe0*/ + data->pixel_rate[0] = data->pixel_rate[4]; + data->pixel_rate[1] = data->pixel_rate[4]; + /*underlay1 same and graphics display pipe1*/ + data->pixel_rate[2] = data->pixel_rate[5]; + data->pixel_rate[3] = data->pixel_rate[5]; + if ((data->underlay_tiling_mode == bw_def_array_linear_general || data->underlay_tiling_mode == bw_def_array_linear_aligned)) { + tiling_mode[0] = bw_def_linear; + tiling_mode[1] = bw_def_linear; + tiling_mode[2] = bw_def_linear; + tiling_mode[3] = bw_def_linear; + } + else { + tiling_mode[0] = bw_def_landscape; + tiling_mode[1] = bw_def_landscape; + tiling_mode[2] = bw_def_landscape; + tiling_mode[3] = bw_def_landscape; + } + data->lb_bpc[0] = data->underlay_lb_bpc; + data->lb_bpc[1] = data->underlay_lb_bpc; + data->lb_bpc[2] = data->underlay_lb_bpc; + data->lb_bpc[3] = data->underlay_lb_bpc; + data->compression_rate[0] = bw_int_to_fixed(1); + data->compression_rate[1] = bw_int_to_fixed(1); + data->compression_rate[2] = bw_int_to_fixed(1); + data->compression_rate[3] = bw_int_to_fixed(1); + data->access_one_channel_only[0] = 0; + data->access_one_channel_only[1] = 0; + data->access_one_channel_only[2] = 0; + data->access_one_channel_only[3] = 0; + data->cursor_width_pixels[0] = bw_int_to_fixed(0); + data->cursor_width_pixels[1] = bw_int_to_fixed(0); + data->cursor_width_pixels[2] = bw_int_to_fixed(0); + data->cursor_width_pixels[3] = bw_int_to_fixed(0); + /* graphics surface parameters from spreadsheet*/ + fbc_enabled = 0; + lpt_enabled = 0; + for (i = 4; i <= maximum_number_of_surfaces - 3; i++) { + if (i < data->number_of_displays + 4) { + if (i == 4 && data->d0_underlay_mode == bw_def_underlay_only) { + data->enable[i] = 0; + data->use_alpha[i] = 0; + } + else if (i == 4 && data->d0_underlay_mode == bw_def_blend) { + data->enable[i] = 1; + data->use_alpha[i] = 1; + } + else if (i == 4) { + data->enable[i] = 1; + data->use_alpha[i] = 0; + } + else if (i == 5 && data->d1_underlay_mode == bw_def_underlay_only) { + data->enable[i] = 0; + data->use_alpha[i] = 0; + } + else if (i == 5 && data->d1_underlay_mode == bw_def_blend) { + data->enable[i] = 1; + data->use_alpha[i] = 1; + } + else { + data->enable[i] = 1; + data->use_alpha[i] = 0; + } + } + else { + data->enable[i] = 0; + data->use_alpha[i] = 0; + } + data->scatter_gather_enable_for_pipe[i] = vbios->scatter_gather_enable; + surface_type[i] = bw_def_graphics; + data->lb_size_per_component[i] = dceip->lb_size_per_component444; + if (data->graphics_tiling_mode == bw_def_array_linear_general || data->graphics_tiling_mode == bw_def_array_linear_aligned) { + tiling_mode[i] = bw_def_linear; + } + else { + tiling_mode[i] = bw_def_tiled; + } + data->lb_bpc[i] = data->graphics_lb_bpc; + if ((data->fbc_en[i] == 1 && (dceip->argb_compression_support || data->d0_underlay_mode != bw_def_blended))) { + data->compression_rate[i] = bw_int_to_fixed(vbios->average_compression_rate); + data->access_one_channel_only[i] = data->lpt_en[i]; + } + else { + data->compression_rate[i] = bw_int_to_fixed(1); + data->access_one_channel_only[i] = 0; + } + if (data->fbc_en[i] == 1) { + fbc_enabled = 1; + if (data->lpt_en[i] == 1) { + lpt_enabled = 1; + } + } + data->cursor_width_pixels[i] = bw_int_to_fixed(vbios->cursor_width); + } + /* display_write_back420*/ + data->scatter_gather_enable_for_pipe[maximum_number_of_surfaces - 2] = 0; + data->scatter_gather_enable_for_pipe[maximum_number_of_surfaces - 1] = 0; + if (data->d1_display_write_back_dwb_enable == 1) { + data->enable[maximum_number_of_surfaces - 2] = 1; + data->enable[maximum_number_of_surfaces - 1] = 1; + } + else { + data->enable[maximum_number_of_surfaces - 2] = 0; + data->enable[maximum_number_of_surfaces - 1] = 0; + } + surface_type[maximum_number_of_surfaces - 2] = bw_def_display_write_back420_luma; + surface_type[maximum_number_of_surfaces - 1] = bw_def_display_write_back420_chroma; + data->lb_size_per_component[maximum_number_of_surfaces - 2] = dceip->underlay420_luma_lb_size_per_component; + data->lb_size_per_component[maximum_number_of_surfaces - 1] = dceip->underlay420_chroma_lb_size_per_component; + data->bytes_per_pixel[maximum_number_of_surfaces - 2] = 1; + data->bytes_per_pixel[maximum_number_of_surfaces - 1] = 2; + data->interlace_mode[maximum_number_of_surfaces - 2] = data->interlace_mode[5]; + data->interlace_mode[maximum_number_of_surfaces - 1] = data->interlace_mode[5]; + data->h_taps[maximum_number_of_surfaces - 2] = bw_int_to_fixed(1); + data->h_taps[maximum_number_of_surfaces - 1] = bw_int_to_fixed(1); + data->v_taps[maximum_number_of_surfaces - 2] = bw_int_to_fixed(1); + data->v_taps[maximum_number_of_surfaces - 1] = bw_int_to_fixed(1); + data->rotation_angle[maximum_number_of_surfaces - 2] = bw_int_to_fixed(0); + data->rotation_angle[maximum_number_of_surfaces - 1] = bw_int_to_fixed(0); + tiling_mode[maximum_number_of_surfaces - 2] = bw_def_linear; + tiling_mode[maximum_number_of_surfaces - 1] = bw_def_linear; + data->lb_bpc[maximum_number_of_surfaces - 2] = 8; + data->lb_bpc[maximum_number_of_surfaces - 1] = 8; + data->compression_rate[maximum_number_of_surfaces - 2] = bw_int_to_fixed(1); + data->compression_rate[maximum_number_of_surfaces - 1] = bw_int_to_fixed(1); + data->access_one_channel_only[maximum_number_of_surfaces - 2] = 0; + data->access_one_channel_only[maximum_number_of_surfaces - 1] = 0; + /*assume display pipe1 has dwb enabled*/ + data->h_total[maximum_number_of_surfaces - 2] = data->h_total[5]; + data->h_total[maximum_number_of_surfaces - 1] = data->h_total[5]; + data->v_total[maximum_number_of_surfaces - 2] = data->v_total[5]; + data->v_total[maximum_number_of_surfaces - 1] = data->v_total[5]; + data->pixel_rate[maximum_number_of_surfaces - 2] = data->pixel_rate[5]; + data->pixel_rate[maximum_number_of_surfaces - 1] = data->pixel_rate[5]; + data->src_width[maximum_number_of_surfaces - 2] = data->src_width[5]; + data->src_width[maximum_number_of_surfaces - 1] = data->src_width[5]; + data->src_height[maximum_number_of_surfaces - 2] = data->src_height[5]; + data->src_height[maximum_number_of_surfaces - 1] = data->src_height[5]; + data->pitch_in_pixels[maximum_number_of_surfaces - 2] = data->src_width[5]; + data->pitch_in_pixels[maximum_number_of_surfaces - 1] = data->src_width[5]; + data->h_scale_ratio[maximum_number_of_surfaces - 2] = bw_int_to_fixed(1); + data->h_scale_ratio[maximum_number_of_surfaces - 1] = bw_int_to_fixed(1); + data->v_scale_ratio[maximum_number_of_surfaces - 2] = bw_int_to_fixed(1); + data->v_scale_ratio[maximum_number_of_surfaces - 1] = bw_int_to_fixed(1); + data->stereo_mode[maximum_number_of_surfaces - 2] = bw_def_mono; + data->stereo_mode[maximum_number_of_surfaces - 1] = bw_def_mono; + data->cursor_width_pixels[maximum_number_of_surfaces - 2] = bw_int_to_fixed(0); + data->cursor_width_pixels[maximum_number_of_surfaces - 1] = bw_int_to_fixed(0); + data->use_alpha[maximum_number_of_surfaces - 2] = 0; + data->use_alpha[maximum_number_of_surfaces - 1] = 0; + /*mode check calculations:*/ + /* mode within dce ip capabilities*/ + /* fbc*/ + /* hsr*/ + /* vsr*/ + /* lb size*/ + /*effective scaling source and ratios:*/ + /*for graphics, non-stereo, non-interlace surfaces when the size of the source and destination are the same, only one tap is used*/ + /*420 chroma has half the width, height, horizontal and vertical scaling ratios than luma*/ + /*rotating a graphic or underlay surface swaps the width, height, horizontal and vertical scaling ratios*/ + /*in top-bottom stereo mode there is 2:1 vertical downscaling for each eye*/ + /*in side-by-side stereo mode there is 2:1 horizontal downscaling for each eye*/ + /*in interlace mode there is 2:1 vertical downscaling for each field*/ + /*in panning or bezel adjustment mode the source width has an extra 128 pixels*/ + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if (bw_equ(data->h_scale_ratio[i], bw_int_to_fixed(1)) && bw_equ(data->v_scale_ratio[i], bw_int_to_fixed(1)) && surface_type[i] == bw_def_graphics && data->stereo_mode[i] == bw_def_mono && data->interlace_mode[i] == 0) { + data->h_taps[i] = bw_int_to_fixed(1); + data->v_taps[i] = bw_int_to_fixed(1); + } + if (surface_type[i] == bw_def_display_write_back420_chroma || surface_type[i] == bw_def_underlay420_chroma) { + data->pitch_in_pixels_after_surface_type[i] = bw_div(data->pitch_in_pixels[i], bw_int_to_fixed(2)); + data->src_width_after_surface_type = bw_div(data->src_width[i], bw_int_to_fixed(2)); + data->src_height_after_surface_type = bw_div(data->src_height[i], bw_int_to_fixed(2)); + data->hsr_after_surface_type = bw_div(data->h_scale_ratio[i], bw_int_to_fixed(2)); + data->vsr_after_surface_type = bw_div(data->v_scale_ratio[i], bw_int_to_fixed(2)); + } + else { + data->pitch_in_pixels_after_surface_type[i] = data->pitch_in_pixels[i]; + data->src_width_after_surface_type = data->src_width[i]; + data->src_height_after_surface_type = data->src_height[i]; + data->hsr_after_surface_type = data->h_scale_ratio[i]; + data->vsr_after_surface_type = data->v_scale_ratio[i]; + } + if ((bw_equ(data->rotation_angle[i], bw_int_to_fixed(90)) || bw_equ(data->rotation_angle[i], bw_int_to_fixed(270))) && surface_type[i] != bw_def_display_write_back420_luma && surface_type[i] != bw_def_display_write_back420_chroma) { + data->src_width_after_rotation = data->src_height_after_surface_type; + data->src_height_after_rotation = data->src_width_after_surface_type; + data->hsr_after_rotation = data->vsr_after_surface_type; + data->vsr_after_rotation = data->hsr_after_surface_type; + } + else { + data->src_width_after_rotation = data->src_width_after_surface_type; + data->src_height_after_rotation = data->src_height_after_surface_type; + data->hsr_after_rotation = data->hsr_after_surface_type; + data->vsr_after_rotation = data->vsr_after_surface_type; + } + switch (data->stereo_mode[i]) { + case bw_def_top_bottom: + data->source_width_pixels[i] = data->src_width_after_rotation; + data->source_height_pixels = bw_mul(bw_int_to_fixed(2), data->src_height_after_rotation); + data->hsr_after_stereo = data->hsr_after_rotation; + data->vsr_after_stereo = bw_mul(bw_int_to_fixed(1), data->vsr_after_rotation); + break; + case bw_def_side_by_side: + data->source_width_pixels[i] = bw_mul(bw_int_to_fixed(2), data->src_width_after_rotation); + data->source_height_pixels = data->src_height_after_rotation; + data->hsr_after_stereo = bw_mul(bw_int_to_fixed(1), data->hsr_after_rotation); + data->vsr_after_stereo = data->vsr_after_rotation; + break; + default: + data->source_width_pixels[i] = data->src_width_after_rotation; + data->source_height_pixels = data->src_height_after_rotation; + data->hsr_after_stereo = data->hsr_after_rotation; + data->vsr_after_stereo = data->vsr_after_rotation; + break; + } + data->hsr[i] = data->hsr_after_stereo; + if (data->interlace_mode[i]) { + data->vsr[i] = bw_mul(data->vsr_after_stereo, bw_int_to_fixed(2)); + } + else { + data->vsr[i] = data->vsr_after_stereo; + } + if (data->panning_and_bezel_adjustment != bw_def_none) { + data->source_width_rounded_up_to_chunks[i] = bw_add(bw_floor2(bw_sub(data->source_width_pixels[i], bw_int_to_fixed(1)), bw_int_to_fixed(128)), bw_int_to_fixed(256)); + } + else { + data->source_width_rounded_up_to_chunks[i] = bw_ceil2(data->source_width_pixels[i], bw_int_to_fixed(128)); + } + data->source_height_rounded_up_to_chunks[i] = data->source_height_pixels; + } + } + /*mode support checks:*/ + /*the number of graphics and underlay pipes is limited by the ip support*/ + /*maximum horizontal and vertical scale ratio is 4, and should not exceed the number of taps*/ + /*for downscaling with the pre-downscaler, the horizontal scale ratio must be more than the ceiling of one quarter of the number of taps*/ + /*the pre-downscaler reduces the line buffer source by the horizontal scale ratio*/ + /*the number of lines in the line buffer has to exceed the number of vertical taps*/ + /*the size of the line in the line buffer is the product of the source width and the bits per component, rounded up to a multiple of 48*/ + /*the size of the line in the line buffer in the case of 10 bit per component is the product of the source width rounded up to multiple of 8 and 30.023438 / 3, rounded up to a multiple of 48*/ + /*the size of the line in the line buffer in the case of 8 bit per component is the product of the source width rounded up to multiple of 8 and 30.023438 / 3, rounded up to a multiple of 48*/ + /*frame buffer compression is not supported with stereo mode, rotation, or non- 888 formats*/ + /*rotation is not supported with linear of stereo modes*/ + if (dceip->number_of_graphics_pipes >= data->number_of_displays && dceip->number_of_underlay_pipes >= data->number_of_underlay_surfaces && !(dceip->display_write_back_supported == 0 && data->d1_display_write_back_dwb_enable == 1)) { + pipe_check = bw_def_ok; + } + else { + pipe_check = bw_def_notok; + } + hsr_check = bw_def_ok; + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if (bw_neq(data->hsr[i], bw_int_to_fixed(1))) { + if (bw_mtn(data->hsr[i], bw_int_to_fixed(4))) { + hsr_check = bw_def_hsr_mtn_4; + } + else { + if (bw_mtn(data->hsr[i], data->h_taps[i])) { + hsr_check = bw_def_hsr_mtn_h_taps; + } + else { + if (dceip->pre_downscaler_enabled == 1 && bw_mtn(data->hsr[i], bw_int_to_fixed(1)) && bw_leq(data->hsr[i], bw_ceil2(bw_div(data->h_taps[i], bw_int_to_fixed(4)), bw_int_to_fixed(1)))) { + hsr_check = bw_def_ceiling__h_taps_div_4___meq_hsr; + } + } + } + } + } + } + vsr_check = bw_def_ok; + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if (bw_neq(data->vsr[i], bw_int_to_fixed(1))) { + if (bw_mtn(data->vsr[i], bw_int_to_fixed(4))) { + vsr_check = bw_def_vsr_mtn_4; + } + else { + if (bw_mtn(data->vsr[i], data->v_taps[i])) { + vsr_check = bw_def_vsr_mtn_v_taps; + } + } + } + } + } + lb_size_check = bw_def_ok; + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if ((dceip->pre_downscaler_enabled && bw_mtn(data->hsr[i], bw_int_to_fixed(1)))) { + data->source_width_in_lb = bw_div(data->source_width_pixels[i], data->hsr[i]); + } + else { + data->source_width_in_lb = data->source_width_pixels[i]; + } + switch (data->lb_bpc[i]) { + case 8: + data->lb_line_pitch = bw_ceil2(bw_mul(bw_div(bw_frc_to_fixed(2401171875, 100000000), bw_int_to_fixed(3)), bw_ceil2(data->source_width_in_lb, bw_int_to_fixed(8))), bw_int_to_fixed(48)); + break; + case 10: + data->lb_line_pitch = bw_ceil2(bw_mul(bw_div(bw_frc_to_fixed(300234375, 10000000), bw_int_to_fixed(3)), bw_ceil2(data->source_width_in_lb, bw_int_to_fixed(8))), bw_int_to_fixed(48)); + break; + default: + data->lb_line_pitch = bw_ceil2(bw_mul(bw_int_to_fixed(data->lb_bpc[i]), data->source_width_in_lb), bw_int_to_fixed(48)); + break; + } + data->lb_partitions[i] = bw_floor2(bw_div(data->lb_size_per_component[i], data->lb_line_pitch), bw_int_to_fixed(1)); + /*clamp the partitions to the maxium number supported by the lb*/ + if ((surface_type[i] != bw_def_graphics || dceip->graphics_lb_nodownscaling_multi_line_prefetching == 1)) { + data->lb_partitions_max[i] = bw_int_to_fixed(10); + } + else { + data->lb_partitions_max[i] = bw_int_to_fixed(7); + } + data->lb_partitions[i] = bw_min2(data->lb_partitions_max[i], data->lb_partitions[i]); + if (bw_mtn(bw_add(data->v_taps[i], bw_int_to_fixed(1)), data->lb_partitions[i])) { + lb_size_check = bw_def_notok; + } + } + } + fbc_check = bw_def_ok; + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i] && data->fbc_en[i] == 1 && (bw_equ(data->rotation_angle[i], bw_int_to_fixed(90)) || bw_equ(data->rotation_angle[i], bw_int_to_fixed(270)) || data->stereo_mode[i] != bw_def_mono || data->bytes_per_pixel[i] != 4)) { + fbc_check = bw_def_invalid_rotation_or_bpp_or_stereo; + } + } + rotation_check = bw_def_ok; + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if ((bw_equ(data->rotation_angle[i], bw_int_to_fixed(90)) || bw_equ(data->rotation_angle[i], bw_int_to_fixed(270))) && (tiling_mode[i] == bw_def_linear || data->stereo_mode[i] != bw_def_mono)) { + rotation_check = bw_def_invalid_linear_or_stereo_mode; + } + } + } + if (pipe_check == bw_def_ok && hsr_check == bw_def_ok && vsr_check == bw_def_ok && lb_size_check == bw_def_ok && fbc_check == bw_def_ok && rotation_check == bw_def_ok) { + mode_check = bw_def_ok; + } + else { + mode_check = bw_def_notok; + } + /*number of memory channels for write-back client*/ + data->number_of_dram_wrchannels = vbios->number_of_dram_channels; + data->number_of_dram_channels = vbios->number_of_dram_channels; + /*modify number of memory channels if lpt mode is enabled*/ + /* low power tiling mode register*/ + /* 0 = use channel 0*/ + /* 1 = use channel 0 and 1*/ + /* 2 = use channel 0,1,2,3*/ + if ((fbc_enabled == 1 && lpt_enabled == 1)) { + data->dram_efficiency = bw_int_to_fixed(1); + if (dceip->low_power_tiling_mode == 0) { + data->number_of_dram_channels = 1; + } + else if (dceip->low_power_tiling_mode == 1) { + data->number_of_dram_channels = 2; + } + else if (dceip->low_power_tiling_mode == 2) { + data->number_of_dram_channels = 4; + } + else { + data->number_of_dram_channels = 1; + } + } + else { + data->dram_efficiency = bw_frc_to_fixed(8, 10); + } + /*memory request size and latency hiding:*/ + /*request size is normally 64 byte, 2-line interleaved, with full latency hiding*/ + /*the display write-back requests are single line*/ + /*for tiled graphics surfaces, or undelay surfaces with width higher than the maximum size for full efficiency, request size is 32 byte in 8 and 16 bpp or if the rotation is orthogonal to the tiling grain. only half is useful of the bytes in the request size in 8 bpp or in 32 bpp if the rotation is orthogonal to the tiling grain.*/ + /*for undelay surfaces with width lower than the maximum size for full efficiency, requests are 4-line interleaved in 16bpp if the rotation is parallel to the tiling grain, and 8-line interleaved with 4-line latency hiding in 8bpp or if the rotation is orthogonal to the tiling grain.*/ + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if ((bw_equ(data->rotation_angle[i], bw_int_to_fixed(90)) || bw_equ(data->rotation_angle[i], bw_int_to_fixed(270)))) { + if ((i < 4)) { + /*underlay portrait tiling mode is not supported*/ + data->orthogonal_rotation[i] = 1; + } + else { + /*graphics portrait tiling mode*/ + if ((data->graphics_micro_tile_mode == bw_def_rotated_micro_tiling)) { + data->orthogonal_rotation[i] = 0; + } + else { + data->orthogonal_rotation[i] = 1; + } + } + } + else { + if ((i < 4)) { + /*underlay landscape tiling mode is only supported*/ + if ((data->underlay_micro_tile_mode == bw_def_display_micro_tiling)) { + data->orthogonal_rotation[i] = 0; + } + else { + data->orthogonal_rotation[i] = 1; + } + } + else { + /*graphics landscape tiling mode*/ + if ((data->graphics_micro_tile_mode == bw_def_display_micro_tiling)) { + data->orthogonal_rotation[i] = 0; + } + else { + data->orthogonal_rotation[i] = 1; + } + } + } + if (bw_equ(data->rotation_angle[i], bw_int_to_fixed(90)) || bw_equ(data->rotation_angle[i], bw_int_to_fixed(270))) { + data->underlay_maximum_source_efficient_for_tiling = dceip->underlay_maximum_height_efficient_for_tiling; + } + else { + data->underlay_maximum_source_efficient_for_tiling = dceip->underlay_maximum_width_efficient_for_tiling; + } + if (surface_type[i] == bw_def_display_write_back420_luma || surface_type[i] == bw_def_display_write_back420_chroma) { + data->bytes_per_request[i] = bw_int_to_fixed(64); + data->useful_bytes_per_request[i] = bw_int_to_fixed(64); + data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(1); + data->latency_hiding_lines[i] = bw_int_to_fixed(1); + } + else if (tiling_mode[i] == bw_def_linear) { + data->bytes_per_request[i] = bw_int_to_fixed(64); + data->useful_bytes_per_request[i] = bw_int_to_fixed(64); + data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(2); + data->latency_hiding_lines[i] = bw_int_to_fixed(2); + } + else { + if (surface_type[i] == bw_def_graphics || (bw_mtn(data->source_width_rounded_up_to_chunks[i], bw_ceil2(data->underlay_maximum_source_efficient_for_tiling, bw_int_to_fixed(256))))) { + switch (data->bytes_per_pixel[i]) { + case 8: + data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(2); + data->latency_hiding_lines[i] = bw_int_to_fixed(2); + if (data->orthogonal_rotation[i]) { + data->bytes_per_request[i] = bw_int_to_fixed(32); + data->useful_bytes_per_request[i] = bw_int_to_fixed(32); + } + else { + data->bytes_per_request[i] = bw_int_to_fixed(64); + data->useful_bytes_per_request[i] = bw_int_to_fixed(64); + } + break; + case 4: + if (data->orthogonal_rotation[i]) { + data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(2); + data->latency_hiding_lines[i] = bw_int_to_fixed(2); + data->bytes_per_request[i] = bw_int_to_fixed(32); + data->useful_bytes_per_request[i] = bw_int_to_fixed(16); + } + else { + data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(2); + data->latency_hiding_lines[i] = bw_int_to_fixed(2); + data->bytes_per_request[i] = bw_int_to_fixed(64); + data->useful_bytes_per_request[i] = bw_int_to_fixed(64); + } + break; + case 2: + data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(2); + data->latency_hiding_lines[i] = bw_int_to_fixed(2); + data->bytes_per_request[i] = bw_int_to_fixed(32); + data->useful_bytes_per_request[i] = bw_int_to_fixed(32); + break; + default: + data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(2); + data->latency_hiding_lines[i] = bw_int_to_fixed(2); + data->bytes_per_request[i] = bw_int_to_fixed(32); + data->useful_bytes_per_request[i] = bw_int_to_fixed(16); + break; + } + } + else { + data->bytes_per_request[i] = bw_int_to_fixed(64); + data->useful_bytes_per_request[i] = bw_int_to_fixed(64); + if (data->orthogonal_rotation[i]) { + data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(8); + data->latency_hiding_lines[i] = bw_int_to_fixed(4); + } + else { + switch (data->bytes_per_pixel[i]) { + case 4: + data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(2); + data->latency_hiding_lines[i] = bw_int_to_fixed(2); + break; + case 2: + data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(4); + data->latency_hiding_lines[i] = bw_int_to_fixed(4); + break; + default: + data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(8); + data->latency_hiding_lines[i] = bw_int_to_fixed(4); + break; + } + } + } + } + } + } + /*requested peak bandwidth:*/ + /*the peak request-per-second bandwidth is the product of the maximum source lines in per line out in the beginning*/ + /*and in the middle of the frame, the ratio of the source width to the line time, the ratio of line interleaving*/ + /*in memory to lines of latency hiding, and the ratio of bytes per pixel to useful bytes per request.*/ + /**/ + /*if the dmif data buffer size holds more than vta_ps worth of source lines, then only vsr is used.*/ + /*the peak bandwidth is the peak request-per-second bandwidth times the request size.*/ + /**/ + /*the line buffer lines in per line out in the beginning of the frame is the vertical filter initialization value*/ + /*rounded up to even and divided by the line times for initialization, which is normally three.*/ + /*the line buffer lines in per line out in the middle of the frame is at least one, or the vertical scale ratio,*/ + /*rounded up to line pairs if not doing line buffer prefetching.*/ + /**/ + /*the non-prefetching rounding up of the vertical scale ratio can also be done up to 1 (for a 0,2 pattern), 4/3 (for a 0,2,2 pattern),*/ + /*6/4 (for a 0,2,2,2 pattern), or 3 (for a 2,4 pattern).*/ + /**/ + /*the scaler vertical filter initialization value is calculated by the hardware as the floor of the average of the*/ + /*vertical scale ratio and the number of vertical taps increased by one. add one more for possible odd line*/ + /*panning/bezel adjustment mode.*/ + /**/ + /*for the bottom interlace field an extra 50% of the vertical scale ratio is considered for this calculation.*/ + /*in top-bottom stereo mode software has to set the filter initialization value manually and explicitly limit it to 4.*/ + /*furthermore, there is only one line time for initialization.*/ + /**/ + /*line buffer prefetching is done when the number of lines in the line buffer exceeds the number of taps plus*/ + /*the ceiling of the vertical scale ratio.*/ + /**/ + /*multi-line buffer prefetching is only done in the graphics pipe when the scaler is disabled or when upscaling and the vsr <= 0.8.'*/ + /**/ + /*the horizontal blank and chunk granularity factor is indirectly used indicate the interval of time required to transfer the source pixels.*/ + /*the denominator of this term represents the total number of destination output pixels required for the input source pixels.*/ + /*it applies when the lines in per line out is not 2 or 4. it does not apply when there is a line buffer between the scl and blnd.*/ + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + data->v_filter_init[i] = bw_floor2(bw_div((bw_add(bw_add(bw_add(bw_int_to_fixed(1), data->v_taps[i]), data->vsr[i]), bw_mul(bw_mul(bw_int_to_fixed(data->interlace_mode[i]), bw_frc_to_fixed(5, 10)), data->vsr[i]))), bw_int_to_fixed(2)), bw_int_to_fixed(1)); + if (data->panning_and_bezel_adjustment == bw_def_any_lines) { + data->v_filter_init[i] = bw_add(data->v_filter_init[i], bw_int_to_fixed(1)); + } + if (data->stereo_mode[i] == bw_def_top_bottom) { + v_filter_init_mode[i] = bw_def_manual; + data->v_filter_init[i] = bw_min2(data->v_filter_init[i], bw_int_to_fixed(4)); + } + else { + v_filter_init_mode[i] = bw_def_auto; + } + if (data->stereo_mode[i] == bw_def_top_bottom) { + data->num_lines_at_frame_start = bw_int_to_fixed(1); + } + else { + data->num_lines_at_frame_start = bw_int_to_fixed(3); + } + if ((bw_mtn(data->vsr[i], bw_int_to_fixed(1)) && surface_type[i] == bw_def_graphics) || data->panning_and_bezel_adjustment == bw_def_any_lines) { + data->line_buffer_prefetch[i] = 0; + } + else if ((((dceip->underlay_downscale_prefetch_enabled == 1 && surface_type[i] != bw_def_graphics) || surface_type[i] == bw_def_graphics) && (bw_mtn(data->lb_partitions[i], bw_add(data->v_taps[i], bw_ceil2(data->vsr[i], bw_int_to_fixed(1))))))) { + data->line_buffer_prefetch[i] = 1; + } + else { + data->line_buffer_prefetch[i] = 0; + } + data->lb_lines_in_per_line_out_in_beginning_of_frame[i] = bw_div(bw_ceil2(data->v_filter_init[i], bw_int_to_fixed(dceip->lines_interleaved_into_lb)), data->num_lines_at_frame_start); + if (data->line_buffer_prefetch[i] == 1) { + data->lb_lines_in_per_line_out_in_middle_of_frame[i] = bw_max2(bw_int_to_fixed(1), data->vsr[i]); + } + else if (bw_leq(data->vsr[i], bw_int_to_fixed(1))) { + data->lb_lines_in_per_line_out_in_middle_of_frame[i] = bw_int_to_fixed(1); + } + else if (bw_leq(data->vsr[i], bw_int_to_fixed(4 / 3))) { + data->lb_lines_in_per_line_out_in_middle_of_frame[i] = bw_div(bw_int_to_fixed(4), bw_int_to_fixed(3)); + } + else if (bw_leq(data->vsr[i], bw_int_to_fixed(6 / 4))) { + data->lb_lines_in_per_line_out_in_middle_of_frame[i] = bw_div(bw_int_to_fixed(6), bw_int_to_fixed(4)); + } + else if (bw_leq(data->vsr[i], bw_int_to_fixed(2))) { + data->lb_lines_in_per_line_out_in_middle_of_frame[i] = bw_int_to_fixed(2); + } + else if (bw_leq(data->vsr[i], bw_int_to_fixed(3))) { + data->lb_lines_in_per_line_out_in_middle_of_frame[i] = bw_int_to_fixed(3); + } + else { + data->lb_lines_in_per_line_out_in_middle_of_frame[i] = bw_int_to_fixed(4); + } + if (data->line_buffer_prefetch[i] == 1 || bw_equ(data->lb_lines_in_per_line_out_in_middle_of_frame[i], bw_int_to_fixed(2)) || bw_equ(data->lb_lines_in_per_line_out_in_middle_of_frame[i], bw_int_to_fixed(4))) { + data->horizontal_blank_and_chunk_granularity_factor[i] = bw_int_to_fixed(1); + } + else { + data->horizontal_blank_and_chunk_granularity_factor[i] = bw_div(data->h_total[i], (bw_div((bw_add(data->h_total[i], bw_div((bw_sub(data->source_width_pixels[i], bw_int_to_fixed(dceip->chunk_width))), data->hsr[i]))), bw_int_to_fixed(2)))); + } + data->request_bandwidth[i] = bw_div(bw_mul(bw_div(bw_mul(bw_div(bw_mul(bw_max2(data->lb_lines_in_per_line_out_in_beginning_of_frame[i], data->lb_lines_in_per_line_out_in_middle_of_frame[i]), data->source_width_rounded_up_to_chunks[i]), (bw_div(data->h_total[i], data->pixel_rate[i]))), bw_int_to_fixed(data->bytes_per_pixel[i])), data->useful_bytes_per_request[i]), data->lines_interleaved_in_mem_access[i]), data->latency_hiding_lines[i]); + data->display_bandwidth[i] = bw_mul(data->request_bandwidth[i], data->bytes_per_request[i]); + } + } + /*outstanding chunk request limit*/ + /*if underlay buffer sharing is enabled, the data buffer size for underlay in 422 or 444 is the sum of the luma and chroma data buffer sizes.*/ + /*underlay buffer sharing mode is only permitted in orthogonal rotation modes.*/ + /**/ + /*if there is only one display enabled, the dmif data buffer size for the graphics surface is increased by concatenating the adjacent buffers.*/ + /**/ + /*the memory chunk size in bytes is 1024 for the writeback, and 256 times the memory line interleaving and the bytes per pixel for graphics*/ + /*and underlay.*/ + /**/ + /*the pipe chunk size uses 2 for line interleaving, except for the write back, in which case it is 1.*/ + /*graphics and underlay data buffer size is adjusted (limited) using the outstanding chunk request limit if there is more than one*/ + /*display enabled or if the dmif request buffer is not large enough for the total data buffer size.*/ + /*the outstanding chunk request limit is the ceiling of the adjusted data buffer size divided by the chunk size in bytes*/ + /*the adjusted data buffer size is the product of the display bandwidth and the minimum effective data buffer size in terms of time,*/ + /*rounded up to the chunk size in bytes, but should not exceed the original data buffer size*/ + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if ((dceip->dmif_pipe_en_fbc_chunk_tracker + 3 == i && fbc_enabled == 0 && tiling_mode[i] != bw_def_linear)) { + data->max_chunks_non_fbc_mode[i] = 128 - dmif_chunk_buff_margin; + } + else { + data->max_chunks_non_fbc_mode[i] = 16 - dmif_chunk_buff_margin; + } + } + if (data->fbc_en[i] == 1) { + max_chunks_fbc_mode = 128 - dmif_chunk_buff_margin; + } + } + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + switch (surface_type[i]) { + case bw_def_display_write_back420_luma: + data->data_buffer_size[i] = bw_int_to_fixed(dceip->display_write_back420_luma_mcifwr_buffer_size); + break; + case bw_def_display_write_back420_chroma: + data->data_buffer_size[i] = bw_int_to_fixed(dceip->display_write_back420_chroma_mcifwr_buffer_size); + break; + case bw_def_underlay420_luma: + data->data_buffer_size[i] = bw_int_to_fixed(dceip->underlay_luma_dmif_size); + break; + case bw_def_underlay420_chroma: + data->data_buffer_size[i] = bw_div(bw_int_to_fixed(dceip->underlay_chroma_dmif_size), bw_int_to_fixed(2)); + break; + case bw_def_underlay422:case bw_def_underlay444: + if (data->orthogonal_rotation[i] == 0) { + data->data_buffer_size[i] = bw_int_to_fixed(dceip->underlay_luma_dmif_size); + } + else { + data->data_buffer_size[i] = bw_add(bw_int_to_fixed(dceip->underlay_luma_dmif_size), bw_int_to_fixed(dceip->underlay_chroma_dmif_size)); + } + break; + default: + if (data->fbc_en[i] == 1) { + /*data_buffer_size(i) = max_dmif_buffer_allocated * graphics_dmif_size*/ + if (data->number_of_displays == 1) { + data->data_buffer_size[i] = bw_min2(bw_mul(bw_mul(bw_int_to_fixed(max_chunks_fbc_mode), bw_int_to_fixed(pixels_per_chunk)), bw_int_to_fixed(data->bytes_per_pixel[i])), bw_mul(bw_int_to_fixed(dceip->max_dmif_buffer_allocated), bw_int_to_fixed(dceip->graphics_dmif_size))); + } + else { + data->data_buffer_size[i] = bw_min2(bw_mul(bw_mul(bw_int_to_fixed(max_chunks_fbc_mode), bw_int_to_fixed(pixels_per_chunk)), bw_int_to_fixed(data->bytes_per_pixel[i])), bw_int_to_fixed(dceip->graphics_dmif_size)); + } + } + else { + /*the effective dmif buffer size in non-fbc mode is limited by the 16 entry chunk tracker*/ + if (data->number_of_displays == 1) { + data->data_buffer_size[i] = bw_min2(bw_mul(bw_mul(bw_int_to_fixed(data->max_chunks_non_fbc_mode[i]), bw_int_to_fixed(pixels_per_chunk)), bw_int_to_fixed(data->bytes_per_pixel[i])), bw_mul(bw_int_to_fixed(dceip->max_dmif_buffer_allocated), bw_int_to_fixed(dceip->graphics_dmif_size))); + } + else { + data->data_buffer_size[i] = bw_min2(bw_mul(bw_mul(bw_int_to_fixed(data->max_chunks_non_fbc_mode[i]), bw_int_to_fixed(pixels_per_chunk)), bw_int_to_fixed(data->bytes_per_pixel[i])), bw_int_to_fixed(dceip->graphics_dmif_size)); + } + } + break; + } + if (surface_type[i] == bw_def_display_write_back420_luma || surface_type[i] == bw_def_display_write_back420_chroma) { + data->memory_chunk_size_in_bytes[i] = bw_int_to_fixed(1024); + data->pipe_chunk_size_in_bytes[i] = bw_int_to_fixed(1024); + } + else { + data->memory_chunk_size_in_bytes[i] = bw_mul(bw_mul(bw_int_to_fixed(dceip->chunk_width), data->lines_interleaved_in_mem_access[i]), bw_int_to_fixed(data->bytes_per_pixel[i])); + data->pipe_chunk_size_in_bytes[i] = bw_mul(bw_mul(bw_int_to_fixed(dceip->chunk_width), bw_int_to_fixed(dceip->lines_interleaved_into_lb)), bw_int_to_fixed(data->bytes_per_pixel[i])); + } + } + } + data->min_dmif_size_in_time = bw_int_to_fixed(9999); + data->min_mcifwr_size_in_time = bw_int_to_fixed(9999); + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if (surface_type[i] != bw_def_display_write_back420_luma && surface_type[i] != bw_def_display_write_back420_chroma) { + if (bw_ltn(bw_div(bw_div(bw_mul(data->data_buffer_size[i], data->bytes_per_request[i]), data->useful_bytes_per_request[i]), data->display_bandwidth[i]), data->min_dmif_size_in_time)) { + data->min_dmif_size_in_time = bw_div(bw_div(bw_mul(data->data_buffer_size[i], data->bytes_per_request[i]), data->useful_bytes_per_request[i]), data->display_bandwidth[i]); + } + } + else { + if (bw_ltn(bw_div(bw_div(bw_mul(data->data_buffer_size[i], data->bytes_per_request[i]), data->useful_bytes_per_request[i]), data->display_bandwidth[i]), data->min_mcifwr_size_in_time)) { + data->min_mcifwr_size_in_time = bw_div(bw_div(bw_mul(data->data_buffer_size[i], data->bytes_per_request[i]), data->useful_bytes_per_request[i]), data->display_bandwidth[i]); + } + } + } + } + data->total_requests_for_dmif_size = bw_int_to_fixed(0); + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i] && surface_type[i] != bw_def_display_write_back420_luma && surface_type[i] != bw_def_display_write_back420_chroma) { + data->total_requests_for_dmif_size = bw_add(data->total_requests_for_dmif_size, bw_div(data->data_buffer_size[i], data->useful_bytes_per_request[i])); + } + } + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if (surface_type[i] != bw_def_display_write_back420_luma && surface_type[i] != bw_def_display_write_back420_chroma && dceip->limit_excessive_outstanding_dmif_requests && (data->number_of_displays > 1 || bw_mtn(data->total_requests_for_dmif_size, dceip->dmif_request_buffer_size))) { + data->adjusted_data_buffer_size[i] = bw_min2(data->data_buffer_size[i], bw_ceil2(bw_mul(data->min_dmif_size_in_time, data->display_bandwidth[i]), data->memory_chunk_size_in_bytes[i])); + } + else { + data->adjusted_data_buffer_size[i] = data->data_buffer_size[i]; + } + } + } + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if ((data->number_of_displays == 1 && data->number_of_underlay_surfaces == 0)) { + /*set maximum chunk limit if only one graphic pipe is enabled*/ + data->outstanding_chunk_request_limit[i] = bw_int_to_fixed(127); + } + else { + data->outstanding_chunk_request_limit[i] = bw_ceil2(bw_div(data->adjusted_data_buffer_size[i], data->pipe_chunk_size_in_bytes[i]), bw_int_to_fixed(1)); + /*clamp maximum chunk limit in the graphic display pipe*/ + if ((i >= 4)) { + data->outstanding_chunk_request_limit[i] = bw_max2(bw_int_to_fixed(127), data->outstanding_chunk_request_limit[i]); + } + } + } + } + /*outstanding pte request limit*/ + /*in tiling mode with no rotation the sg pte requests are 8 useful pt_es, the sg row height is the page height and the sg page width x height is 64x64 for 8bpp, 64x32 for 16 bpp, 32x32 for 32 bpp*/ + /*in tiling mode with rotation the sg pte requests are only one useful pte, and the sg row height is also the page height, but the sg page width and height are swapped*/ + /*in linear mode the pte requests are 8 useful pt_es, the sg page width is 4096 divided by the bytes per pixel, the sg page height is 1, but there is just one row whose height is the lines of pte prefetching*/ + /*the outstanding pte request limit is obtained by multiplying the outstanding chunk request limit by the peak pte request to eviction limiting ratio, rounding up to integer, multiplying by the pte requests per chunk, and rounding up to integer again*/ + /*if not using peak pte request to eviction limiting, the outstanding pte request limit is the pte requests in the vblank*/ + /*the pte requests in the vblank is the product of the number of pte request rows times the number of pte requests in a row*/ + /*the number of pte requests in a row is the quotient of the source width divided by 256, multiplied by the pte requests per chunk, rounded up to even, multiplied by the scatter-gather row height and divided by the scatter-gather page height*/ + /*the pte requests per chunk is 256 divided by the scatter-gather page width and the useful pt_es per pte request*/ + if (data->number_of_displays > 1 || (bw_neq(data->rotation_angle[4], bw_int_to_fixed(0)) && bw_neq(data->rotation_angle[4], bw_int_to_fixed(180)))) { + data->peak_pte_request_to_eviction_ratio_limiting = dceip->peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display; + } + else { + data->peak_pte_request_to_eviction_ratio_limiting = dceip->peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation; + } + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i] && data->scatter_gather_enable_for_pipe[i] == 1) { + if (tiling_mode[i] == bw_def_linear) { + data->useful_pte_per_pte_request = bw_int_to_fixed(8); + data->scatter_gather_page_width[i] = bw_div(bw_int_to_fixed(4096), bw_int_to_fixed(data->bytes_per_pixel[i])); + data->scatter_gather_page_height[i] = bw_int_to_fixed(1); + data->scatter_gather_pte_request_rows = bw_int_to_fixed(1); + data->scatter_gather_row_height = bw_int_to_fixed(dceip->scatter_gather_lines_of_pte_prefetching_in_linear_mode); + } + else if (bw_equ(data->rotation_angle[i], bw_int_to_fixed(0)) || bw_equ(data->rotation_angle[i], bw_int_to_fixed(180))) { + data->useful_pte_per_pte_request = bw_int_to_fixed(8); + switch (data->bytes_per_pixel[i]) { + case 4: + data->scatter_gather_page_width[i] = bw_int_to_fixed(32); + data->scatter_gather_page_height[i] = bw_int_to_fixed(32); + break; + case 2: + data->scatter_gather_page_width[i] = bw_int_to_fixed(64); + data->scatter_gather_page_height[i] = bw_int_to_fixed(32); + break; + default: + data->scatter_gather_page_width[i] = bw_int_to_fixed(64); + data->scatter_gather_page_height[i] = bw_int_to_fixed(64); + break; + } + data->scatter_gather_pte_request_rows = bw_int_to_fixed(dceip->scatter_gather_pte_request_rows_in_tiling_mode); + data->scatter_gather_row_height = data->scatter_gather_page_height[i]; + } + else { + data->useful_pte_per_pte_request = bw_int_to_fixed(1); + switch (data->bytes_per_pixel[i]) { + case 4: + data->scatter_gather_page_width[i] = bw_int_to_fixed(32); + data->scatter_gather_page_height[i] = bw_int_to_fixed(32); + break; + case 2: + data->scatter_gather_page_width[i] = bw_int_to_fixed(32); + data->scatter_gather_page_height[i] = bw_int_to_fixed(64); + break; + default: + data->scatter_gather_page_width[i] = bw_int_to_fixed(64); + data->scatter_gather_page_height[i] = bw_int_to_fixed(64); + break; + } + data->scatter_gather_pte_request_rows = bw_int_to_fixed(dceip->scatter_gather_pte_request_rows_in_tiling_mode); + data->scatter_gather_row_height = data->scatter_gather_page_height[i]; + } + data->pte_request_per_chunk[i] = bw_div(bw_div(bw_int_to_fixed(dceip->chunk_width), data->scatter_gather_page_width[i]), data->useful_pte_per_pte_request); + data->scatter_gather_pte_requests_in_row[i] = bw_div(bw_mul(bw_ceil2(bw_mul(bw_div(data->source_width_rounded_up_to_chunks[i], bw_int_to_fixed(dceip->chunk_width)), data->pte_request_per_chunk[i]), bw_int_to_fixed(1)), data->scatter_gather_row_height), data->scatter_gather_page_height[i]); + data->scatter_gather_pte_requests_in_vblank = bw_mul(data->scatter_gather_pte_request_rows, data->scatter_gather_pte_requests_in_row[i]); + if (bw_equ(data->peak_pte_request_to_eviction_ratio_limiting, bw_int_to_fixed(0))) { + data->scatter_gather_pte_request_limit[i] = data->scatter_gather_pte_requests_in_vblank; + } + else { + data->scatter_gather_pte_request_limit[i] = bw_max2(dceip->minimum_outstanding_pte_request_limit, bw_min2(data->scatter_gather_pte_requests_in_vblank, bw_ceil2(bw_mul(bw_mul(bw_div(bw_ceil2(data->adjusted_data_buffer_size[i], data->memory_chunk_size_in_bytes[i]), data->memory_chunk_size_in_bytes[i]), data->pte_request_per_chunk[i]), data->peak_pte_request_to_eviction_ratio_limiting), bw_int_to_fixed(1)))); + } + } + } + /*pitch padding recommended for efficiency in linear mode*/ + /*in linear mode graphics or underlay with scatter gather, a pitch that is a multiple of the channel interleave (256 bytes) times the channel-bank rotation is not efficient*/ + /*if that is the case it is recommended to pad the pitch by at least 256 pixels*/ + data->inefficient_linear_pitch_in_bytes = bw_mul(bw_mul(bw_int_to_fixed(256), bw_int_to_fixed(vbios->number_of_dram_banks)), bw_int_to_fixed(data->number_of_dram_channels)); + + /*pixel transfer time*/ + /*the dmif and mcifwr yclk(pclk) required is the one that allows the transfer of all pipe's data buffer size in memory in the time for data transfer*/ + /*for dmif, pte and cursor requests have to be included.*/ + /*the dram data requirement is doubled when the data request size in bytes is less than the dram channel width times the burst size (8)*/ + /*the dram data requirement is also multiplied by the number of channels in the case of low power tiling*/ + /*the page close-open time is determined by trc and the number of page close-opens*/ + /*in tiled mode graphics or underlay with scatter-gather enabled the bytes per page close-open is the product of the memory line interleave times the maximum of the scatter-gather page width and the product of the tile width (8 pixels) times the number of channels times the number of banks.*/ + /*in linear mode graphics or underlay with scatter-gather enabled and inefficient pitch, the bytes per page close-open is the line request alternation slice, because different lines are in completely different 4k address bases.*/ + /*otherwise, the bytes page close-open is the chunk size because that is the arbitration slice.*/ + /*pte requests are grouped by pte requests per chunk if that is more than 1. each group costs a page close-open time for dmif reads*/ + /*cursor requests outstanding are limited to a group of two source lines. each group costs a page close-open time for dmif reads*/ + /*the display reads and writes time for data transfer is the minimum data or cursor buffer size in time minus the mc urgent latency*/ + /*the mc urgent latency is experienced more than one time if the number of dmif requests in the data buffer exceeds the request buffer size plus the request slots reserved for dmif in the dram channel arbiter queues*/ + /*the dispclk required is the maximum for all surfaces of the maximum of the source pixels for first output pixel times the throughput factor, divided by the pixels per dispclk, and divided by the minimum latency hiding minus the dram speed/p-state change latency minus the burst time, and the source pixels for last output pixel, times the throughput factor, divided by the pixels per dispclk, and divided by the minimum latency hiding minus the dram speed/p-state change latency minus the burst time, plus the active time.*/ + /*the data burst time is the maximum of the total page close-open time, total dmif/mcifwr buffer size in memory divided by the dram bandwidth, and the total dmif/mcifwr buffer size in memory divided by the 32 byte sclk data bus bandwidth, each multiplied by its efficiency.*/ + /*the source line transfer time is the maximum for all surfaces of the maximum of the burst time plus the urgent latency times the floor of the data required divided by the buffer size for the fist pixel, and the burst time plus the urgent latency times the floor of the data required divided by the buffer size for the last pixel plus the active time.*/ + /*the source pixels for the first output pixel is 512 if the scaler vertical filter initialization value is greater than 2, and it is 4 times the source width if it is greater than 4.*/ + /*the source pixels for the last output pixel is the source width times the scaler vertical filter initialization value rounded up to even*/ + /*the source data for these pixels is the number of pixels times the bytes per pixel times the bytes per request divided by the useful bytes per request.*/ + data->cursor_total_data = bw_int_to_fixed(0); + data->cursor_total_request_groups = bw_int_to_fixed(0); + data->scatter_gather_total_pte_requests = bw_int_to_fixed(0); + data->scatter_gather_total_pte_request_groups = bw_int_to_fixed(0); + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + data->cursor_total_data = bw_add(data->cursor_total_data, bw_mul(bw_mul(bw_int_to_fixed(2), data->cursor_width_pixels[i]), bw_int_to_fixed(4))); + if (dceip->large_cursor == 1) { + data->cursor_total_request_groups = bw_add(data->cursor_total_request_groups, bw_int_to_fixed((dceip->cursor_max_outstanding_group_num + 1))); + } + else { + data->cursor_total_request_groups = bw_add(data->cursor_total_request_groups, bw_ceil2(bw_div(data->cursor_width_pixels[i], dceip->cursor_chunk_width), bw_int_to_fixed(1))); + } + if (data->scatter_gather_enable_for_pipe[i]) { + data->scatter_gather_total_pte_requests = bw_add(data->scatter_gather_total_pte_requests, data->scatter_gather_pte_request_limit[i]); + data->scatter_gather_total_pte_request_groups = bw_add(data->scatter_gather_total_pte_request_groups, bw_ceil2(bw_div(data->scatter_gather_pte_request_limit[i], bw_ceil2(data->pte_request_per_chunk[i], bw_int_to_fixed(1))), bw_int_to_fixed(1))); + } + } + } + data->tile_width_in_pixels = bw_int_to_fixed(8); + data->dmif_total_number_of_data_request_page_close_open = bw_int_to_fixed(0); + data->mcifwr_total_number_of_data_request_page_close_open = bw_int_to_fixed(0); + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if (data->scatter_gather_enable_for_pipe[i] == 1 && tiling_mode[i] != bw_def_linear) { + data->bytes_per_page_close_open = bw_mul(data->lines_interleaved_in_mem_access[i], bw_max2(bw_mul(bw_mul(bw_mul(bw_int_to_fixed(data->bytes_per_pixel[i]), data->tile_width_in_pixels), bw_int_to_fixed(vbios->number_of_dram_banks)), bw_int_to_fixed(data->number_of_dram_channels)), bw_mul(bw_int_to_fixed(data->bytes_per_pixel[i]), data->scatter_gather_page_width[i]))); + } + else if (data->scatter_gather_enable_for_pipe[i] == 1 && tiling_mode[i] == bw_def_linear && bw_equ(bw_mod((bw_mul(data->pitch_in_pixels_after_surface_type[i], bw_int_to_fixed(data->bytes_per_pixel[i]))), data->inefficient_linear_pitch_in_bytes), bw_int_to_fixed(0))) { + data->bytes_per_page_close_open = dceip->linear_mode_line_request_alternation_slice; + } + else { + data->bytes_per_page_close_open = data->memory_chunk_size_in_bytes[i]; + } + if (surface_type[i] != bw_def_display_write_back420_luma && surface_type[i] != bw_def_display_write_back420_chroma) { + data->dmif_total_number_of_data_request_page_close_open = bw_add(data->dmif_total_number_of_data_request_page_close_open, bw_div(bw_ceil2(data->adjusted_data_buffer_size[i], data->memory_chunk_size_in_bytes[i]), data->bytes_per_page_close_open)); + } + else { + data->mcifwr_total_number_of_data_request_page_close_open = bw_add(data->mcifwr_total_number_of_data_request_page_close_open, bw_div(bw_ceil2(data->adjusted_data_buffer_size[i], data->memory_chunk_size_in_bytes[i]), data->bytes_per_page_close_open)); + } + } + } + data->dmif_total_page_close_open_time = bw_div(bw_mul((bw_add(bw_add(data->dmif_total_number_of_data_request_page_close_open, data->scatter_gather_total_pte_request_groups), data->cursor_total_request_groups)), vbios->trc), bw_int_to_fixed(1000)); + data->mcifwr_total_page_close_open_time = bw_div(bw_mul(data->mcifwr_total_number_of_data_request_page_close_open, vbios->trc), bw_int_to_fixed(1000)); + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + data->adjusted_data_buffer_size_in_memory[i] = bw_div(bw_mul(data->adjusted_data_buffer_size[i], data->bytes_per_request[i]), data->useful_bytes_per_request[i]); + } + } + data->total_requests_for_adjusted_dmif_size = bw_int_to_fixed(0); + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if (surface_type[i] != bw_def_display_write_back420_luma && surface_type[i] != bw_def_display_write_back420_chroma) { + data->total_requests_for_adjusted_dmif_size = bw_add(data->total_requests_for_adjusted_dmif_size, bw_div(data->adjusted_data_buffer_size[i], data->useful_bytes_per_request[i])); + } + } + } + data->total_dmifmc_urgent_trips = bw_ceil2(bw_div(data->total_requests_for_adjusted_dmif_size, (bw_add(dceip->dmif_request_buffer_size, bw_int_to_fixed(vbios->number_of_request_slots_gmc_reserves_for_dmif_per_channel * data->number_of_dram_channels)))), bw_int_to_fixed(1)); + data->total_dmifmc_urgent_latency = bw_mul(vbios->dmifmc_urgent_latency, data->total_dmifmc_urgent_trips); + data->total_display_reads_required_data = bw_int_to_fixed(0); + data->total_display_reads_required_dram_access_data = bw_int_to_fixed(0); + data->total_display_writes_required_data = bw_int_to_fixed(0); + data->total_display_writes_required_dram_access_data = bw_int_to_fixed(0); + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if (surface_type[i] != bw_def_display_write_back420_luma && surface_type[i] != bw_def_display_write_back420_chroma) { + data->display_reads_required_data = data->adjusted_data_buffer_size_in_memory[i]; + /*for hbm memories, each channel is split into 2 pseudo-channels that are each 64 bits in width. each*/ + /*pseudo-channel may be read independently of one another.*/ + /*the read burst length (bl) for hbm memories is 4, so each read command will access 32 bytes of data.*/ + /*the 64 or 32 byte sized data is stored in one pseudo-channel.*/ + /*it will take 4 memclk cycles or 8 yclk cycles to fetch 64 bytes of data from the hbm memory (2 read commands).*/ + /*it will take 2 memclk cycles or 4 yclk cycles to fetch 32 bytes of data from the hbm memory (1 read command).*/ + /*for gddr5/ddr4 memories, there is additional overhead if the size of the request is smaller than 64 bytes.*/ + /*the read burst length (bl) for gddr5/ddr4 memories is 8, regardless of the size of the data request.*/ + /*therefore it will require 8 cycles to fetch 64 or 32 bytes of data from the memory.*/ + /*the memory efficiency will be 50% for the 32 byte sized data.*/ + if (vbios->memory_type == bw_def_hbm) { + data->display_reads_required_dram_access_data = data->adjusted_data_buffer_size_in_memory[i]; + } + else { + data->display_reads_required_dram_access_data = bw_mul(data->adjusted_data_buffer_size_in_memory[i], bw_ceil2(bw_div(bw_int_to_fixed((8 * vbios->dram_channel_width_in_bits / 8)), data->bytes_per_request[i]), bw_int_to_fixed(1))); + } + data->total_display_reads_required_data = bw_add(data->total_display_reads_required_data, data->display_reads_required_data); + data->total_display_reads_required_dram_access_data = bw_add(data->total_display_reads_required_dram_access_data, data->display_reads_required_dram_access_data); + } + else { + data->total_display_writes_required_data = bw_add(data->total_display_writes_required_data, data->adjusted_data_buffer_size_in_memory[i]); + data->total_display_writes_required_dram_access_data = bw_add(data->total_display_writes_required_dram_access_data, bw_mul(data->adjusted_data_buffer_size_in_memory[i], bw_ceil2(bw_div(bw_int_to_fixed(vbios->dram_channel_width_in_bits), data->bytes_per_request[i]), bw_int_to_fixed(1)))); + } + } + } + data->total_display_reads_required_data = bw_add(bw_add(data->total_display_reads_required_data, data->cursor_total_data), bw_mul(data->scatter_gather_total_pte_requests, bw_int_to_fixed(64))); + data->total_display_reads_required_dram_access_data = bw_add(bw_add(data->total_display_reads_required_dram_access_data, data->cursor_total_data), bw_mul(data->scatter_gather_total_pte_requests, bw_int_to_fixed(64))); + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if (bw_mtn(data->v_filter_init[i], bw_int_to_fixed(4))) { + data->src_pixels_for_first_output_pixel[i] = bw_mul(bw_int_to_fixed(4), data->source_width_rounded_up_to_chunks[i]); + } + else { + if (bw_mtn(data->v_filter_init[i], bw_int_to_fixed(2))) { + data->src_pixels_for_first_output_pixel[i] = bw_int_to_fixed(512); + } + else { + data->src_pixels_for_first_output_pixel[i] = bw_int_to_fixed(0); + } + } + data->src_data_for_first_output_pixel[i] = bw_div(bw_mul(bw_mul(data->src_pixels_for_first_output_pixel[i], bw_int_to_fixed(data->bytes_per_pixel[i])), data->bytes_per_request[i]), data->useful_bytes_per_request[i]); + data->src_pixels_for_last_output_pixel[i] = bw_mul(data->source_width_rounded_up_to_chunks[i], bw_max2(bw_ceil2(data->v_filter_init[i], bw_int_to_fixed(dceip->lines_interleaved_into_lb)), bw_mul(bw_ceil2(data->vsr[i], bw_int_to_fixed(dceip->lines_interleaved_into_lb)), data->horizontal_blank_and_chunk_granularity_factor[i]))); + data->src_data_for_last_output_pixel[i] = bw_div(bw_mul(bw_mul(bw_mul(data->source_width_rounded_up_to_chunks[i], bw_max2(bw_ceil2(data->v_filter_init[i], bw_int_to_fixed(dceip->lines_interleaved_into_lb)), data->lines_interleaved_in_mem_access[i])), bw_int_to_fixed(data->bytes_per_pixel[i])), data->bytes_per_request[i]), data->useful_bytes_per_request[i]); + data->active_time[i] = bw_div(bw_div(data->source_width_rounded_up_to_chunks[i], data->hsr[i]), data->pixel_rate[i]); + } + } + for (i = 0; i <= 2; i++) { + for (j = 0; j <= 7; j++) { + data->dmif_burst_time[i][j] = bw_max3(data->dmif_total_page_close_open_time, bw_div(data->total_display_reads_required_dram_access_data, (bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[i]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels)))), bw_div(data->total_display_reads_required_data, (bw_mul(bw_mul(sclk[j], vbios->data_return_bus_width), bw_int_to_fixed(bus_efficiency))))); + if (data->d1_display_write_back_dwb_enable == 1) { + data->mcifwr_burst_time[i][j] = bw_max3(data->mcifwr_total_page_close_open_time, bw_div(data->total_display_writes_required_dram_access_data, (bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[i]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_wrchannels)))), bw_div(data->total_display_writes_required_data, (bw_mul(bw_mul(sclk[j], vbios->data_return_bus_width), bw_int_to_fixed(bus_efficiency))))); + } + } + } + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + for (j = 0; j <= 2; j++) { + for (k = 0; k <= 7; k++) { + if (data->enable[i]) { + if (surface_type[i] != bw_def_display_write_back420_luma && surface_type[i] != bw_def_display_write_back420_chroma) { + /*time to transfer data from the dmif buffer to the lb. since the mc to dmif transfer time overlaps*/ + /*with the dmif to lb transfer time, only time to transfer the last chunk is considered.*/ + data->dmif_buffer_transfer_time[i] = bw_mul(data->source_width_rounded_up_to_chunks[i], (bw_div(dceip->lb_write_pixels_per_dispclk, (bw_div(vbios->low_voltage_max_dispclk, dceip->display_pipe_throughput_factor))))); + data->line_source_transfer_time[i][j][k] = bw_max2(bw_mul((bw_add(data->total_dmifmc_urgent_latency, data->dmif_burst_time[j][k])), bw_floor2(bw_div(data->src_data_for_first_output_pixel[i], data->adjusted_data_buffer_size_in_memory[i]), bw_int_to_fixed(1))), bw_sub(bw_add(bw_mul((bw_add(data->total_dmifmc_urgent_latency, data->dmif_burst_time[j][k])), bw_floor2(bw_div(data->src_data_for_last_output_pixel[i], data->adjusted_data_buffer_size_in_memory[i]), bw_int_to_fixed(1))), data->dmif_buffer_transfer_time[i]), data->active_time[i])); + /*during an mclk switch the requests from the dce ip are stored in the gmc/arb. these requests should be serviced immediately*/ + /*after the mclk switch sequence and not incur an urgent latency penalty. it is assumed that the gmc/arb can hold up to 256 requests*/ + /*per memory channel. if the dce ip is urgent after the mclk switch sequence, all pending requests and subsequent requests should be*/ + /*immediately serviced without a gap in the urgent requests.*/ + /*the latency incurred would be the time to issue the requests and return the data for the first or last output pixel.*/ + if (surface_type[i] == bw_def_graphics) { + switch (data->lb_bpc[i]) { + case 6: + data->v_scaler_efficiency = dceip->graphics_vscaler_efficiency6_bit_per_component; + break; + case 8: + data->v_scaler_efficiency = dceip->graphics_vscaler_efficiency8_bit_per_component; + break; + case 10: + data->v_scaler_efficiency = dceip->graphics_vscaler_efficiency10_bit_per_component; + break; + default: + data->v_scaler_efficiency = dceip->graphics_vscaler_efficiency12_bit_per_component; + break; + } + if (data->use_alpha[i] == 1) { + data->v_scaler_efficiency = bw_min2(data->v_scaler_efficiency, dceip->alpha_vscaler_efficiency); + } + } + else { + switch (data->lb_bpc[i]) { + case 6: + data->v_scaler_efficiency = dceip->underlay_vscaler_efficiency6_bit_per_component; + break; + case 8: + data->v_scaler_efficiency = dceip->underlay_vscaler_efficiency8_bit_per_component; + break; + case 10: + data->v_scaler_efficiency = dceip->underlay_vscaler_efficiency10_bit_per_component; + break; + default: + data->v_scaler_efficiency = bw_int_to_fixed(3); + break; + } + } + if (dceip->pre_downscaler_enabled && bw_mtn(data->hsr[i], bw_int_to_fixed(1))) { + data->scaler_limits_factor = bw_max2(bw_div(data->v_taps[i], data->v_scaler_efficiency), bw_div(data->source_width_rounded_up_to_chunks[i], data->h_total[i])); + } + else { + data->scaler_limits_factor = bw_max3(bw_int_to_fixed(1), bw_ceil2(bw_div(data->h_taps[i], bw_int_to_fixed(4)), bw_int_to_fixed(1)), bw_mul(data->hsr[i], bw_max2(bw_div(data->v_taps[i], data->v_scaler_efficiency), bw_int_to_fixed(1)))); + } + data->dram_speed_change_line_source_transfer_time[i][j][k] = bw_mul(bw_int_to_fixed(2), bw_max2((bw_add((bw_div(data->src_data_for_first_output_pixel[i], bw_min2(bw_mul(data->bytes_per_request[i], sclk[k]), bw_div(bw_mul(bw_mul(data->bytes_per_request[i], data->pixel_rate[i]), data->scaler_limits_factor), bw_int_to_fixed(2))))), (bw_mul(data->dmif_burst_time[j][k], bw_floor2(bw_div(data->src_data_for_first_output_pixel[i], data->adjusted_data_buffer_size_in_memory[i]), bw_int_to_fixed(1)))))), (bw_add((bw_div(data->src_data_for_last_output_pixel[i], bw_min2(bw_mul(data->bytes_per_request[i], sclk[k]), bw_div(bw_mul(bw_mul(data->bytes_per_request[i], data->pixel_rate[i]), data->scaler_limits_factor), bw_int_to_fixed(2))))), (bw_sub(bw_mul(data->dmif_burst_time[j][k], bw_floor2(bw_div(data->src_data_for_last_output_pixel[i], data->adjusted_data_buffer_size_in_memory[i]), bw_int_to_fixed(1))), data->active_time[i])))))); + } + else { + data->line_source_transfer_time[i][j][k] = bw_max2(bw_mul((bw_add(vbios->mcifwrmc_urgent_latency, data->mcifwr_burst_time[j][k])), bw_floor2(bw_div(data->src_data_for_first_output_pixel[i], data->adjusted_data_buffer_size_in_memory[i]), bw_int_to_fixed(1))), bw_sub(bw_mul((bw_add(vbios->mcifwrmc_urgent_latency, data->mcifwr_burst_time[j][k])), bw_floor2(bw_div(data->src_data_for_last_output_pixel[i], data->adjusted_data_buffer_size_in_memory[i]), bw_int_to_fixed(1))), data->active_time[i])); + /*during an mclk switch the requests from the dce ip are stored in the gmc/arb. these requests should be serviced immediately*/ + /*after the mclk switch sequence and not incur an urgent latency penalty. it is assumed that the gmc/arb can hold up to 256 requests*/ + /*per memory channel. if the dce ip is urgent after the mclk switch sequence, all pending requests and subsequent requests should be*/ + /*immediately serviced without a gap in the urgent requests.*/ + /*the latency incurred would be the time to issue the requests and return the data for the first or last output pixel.*/ + data->dram_speed_change_line_source_transfer_time[i][j][k] = bw_max2((bw_add((bw_div(data->src_data_for_first_output_pixel[i], bw_min2(bw_mul(data->bytes_per_request[i], sclk[k]), bw_div(bw_mul(data->bytes_per_request[i], vbios->low_voltage_max_dispclk), bw_int_to_fixed(2))))), (bw_mul(data->mcifwr_burst_time[j][k], bw_floor2(bw_div(data->src_data_for_first_output_pixel[i], data->adjusted_data_buffer_size_in_memory[i]), bw_int_to_fixed(1)))))), (bw_add((bw_div(data->src_data_for_last_output_pixel[i], bw_min2(bw_mul(data->bytes_per_request[i], sclk[k]), bw_div(bw_mul(data->bytes_per_request[i], vbios->low_voltage_max_dispclk), bw_int_to_fixed(2))))), (bw_sub(bw_mul(data->mcifwr_burst_time[j][k], bw_floor2(bw_div(data->src_data_for_last_output_pixel[i], data->adjusted_data_buffer_size_in_memory[i]), bw_int_to_fixed(1))), data->active_time[i]))))); + } + } + } + } + } + /*cpu c-state and p-state change enable*/ + /*for cpu p-state change to be possible for a yclk(pclk) and sclk level the dispclk required has to be enough for the blackout duration*/ + /*for cpu c-state change to be possible for a yclk(pclk) and sclk level the dispclk required has to be enough for the blackout duration and recovery*/ + /*condition for the blackout duration:*/ + /* minimum latency hiding > blackout duration + dmif burst time + line source transfer time*/ + /*condition for the blackout recovery:*/ + /* recovery time > dmif burst time + 2 * urgent latency*/ + /* recovery time > (display bw * blackout duration + (2 * urgent latency + dmif burst time)*dispclk - dmif size )*/ + /* / (dispclk - display bw)*/ + /*the minimum latency hiding is the minimum for all pipes of one screen line time, plus one more line time if doing lb prefetch, plus the dmif data buffer size equivalent in time, minus the urgent latency.*/ + /*the minimum latency hiding is further limited by the cursor. the cursor latency hiding is the number of lines of the cursor buffer, minus one if the downscaling is less than two, or minus three if it is more*/ + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if ((bw_equ(dceip->stutter_and_dram_clock_state_change_gated_before_cursor, bw_int_to_fixed(0)) && bw_mtn(data->cursor_width_pixels[i], bw_int_to_fixed(0)))) { + if (bw_ltn(data->vsr[i], bw_int_to_fixed(2))) { + data->cursor_latency_hiding[i] = bw_div(bw_div(bw_mul((bw_sub(dceip->cursor_dcp_buffer_lines, bw_int_to_fixed(1))), data->h_total[i]), data->vsr[i]), data->pixel_rate[i]); + } + else { + data->cursor_latency_hiding[i] = bw_div(bw_div(bw_mul((bw_sub(dceip->cursor_dcp_buffer_lines, bw_int_to_fixed(3))), data->h_total[i]), data->vsr[i]), data->pixel_rate[i]); + } + } + else { + data->cursor_latency_hiding[i] = bw_int_to_fixed(9999); + } + } + } + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if (dceip->graphics_lb_nodownscaling_multi_line_prefetching == 1 && (bw_equ(data->vsr[i], bw_int_to_fixed(1)) || (bw_leq(data->vsr[i], bw_frc_to_fixed(8, 10)) && bw_leq(data->v_taps[i], bw_int_to_fixed(2)) && data->lb_bpc[i] == 8)) && surface_type[i] == bw_def_graphics) { + data->minimum_latency_hiding[i] = bw_sub(bw_div(bw_mul((bw_div((bw_add(bw_sub(data->lb_partitions[i], bw_int_to_fixed(1)), bw_div(bw_div(data->data_buffer_size[i], bw_int_to_fixed(data->bytes_per_pixel[i])), data->source_width_pixels[i]))), data->vsr[i])), data->h_total[i]), data->pixel_rate[i]), data->total_dmifmc_urgent_latency); + } + else { + data->minimum_latency_hiding[i] = bw_sub(bw_div(bw_mul((bw_div((bw_add(bw_int_to_fixed(1 + data->line_buffer_prefetch[i]), bw_div(bw_div(data->data_buffer_size[i], bw_int_to_fixed(data->bytes_per_pixel[i])), data->source_width_pixels[i]))), data->vsr[i])), data->h_total[i]), data->pixel_rate[i]), data->total_dmifmc_urgent_latency); + } + data->minimum_latency_hiding_with_cursor[i] = bw_min2(data->minimum_latency_hiding[i], data->cursor_latency_hiding[i]); + } + } + for (i = 0; i <= 2; i++) { + for (j = 0; j <= 7; j++) { + data->blackout_duration_margin[i][j] = bw_int_to_fixed(9999); + data->dispclk_required_for_blackout_duration[i][j] = bw_int_to_fixed(0); + data->dispclk_required_for_blackout_recovery[i][j] = bw_int_to_fixed(0); + for (k = 0; k <= maximum_number_of_surfaces - 1; k++) { + if (data->enable[k] && bw_mtn(vbios->blackout_duration, bw_int_to_fixed(0))) { + if (surface_type[k] != bw_def_display_write_back420_luma && surface_type[k] != bw_def_display_write_back420_chroma) { + data->blackout_duration_margin[i][j] = bw_min2(data->blackout_duration_margin[i][j], bw_sub(bw_sub(bw_sub(data->minimum_latency_hiding_with_cursor[k], vbios->blackout_duration), data->dmif_burst_time[i][j]), data->line_source_transfer_time[k][i][j])); + data->dispclk_required_for_blackout_duration[i][j] = bw_max3(data->dispclk_required_for_blackout_duration[i][j], bw_div(bw_div(bw_mul(data->src_pixels_for_first_output_pixel[k], dceip->display_pipe_throughput_factor), dceip->lb_write_pixels_per_dispclk), (bw_sub(bw_sub(data->minimum_latency_hiding_with_cursor[k], vbios->blackout_duration), data->dmif_burst_time[i][j]))), bw_div(bw_div(bw_mul(data->src_pixels_for_last_output_pixel[k], dceip->display_pipe_throughput_factor), dceip->lb_write_pixels_per_dispclk), (bw_add(bw_sub(bw_sub(data->minimum_latency_hiding_with_cursor[k], vbios->blackout_duration), data->dmif_burst_time[i][j]), data->active_time[k])))); + if (bw_leq(vbios->maximum_blackout_recovery_time, bw_add(bw_mul(bw_int_to_fixed(2), data->total_dmifmc_urgent_latency), data->dmif_burst_time[i][j]))) { + data->dispclk_required_for_blackout_recovery[i][j] = bw_int_to_fixed(9999); + } + else if (bw_ltn(data->adjusted_data_buffer_size[k], bw_mul(bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]), (bw_add(vbios->blackout_duration, bw_add(bw_mul(bw_int_to_fixed(2), data->total_dmifmc_urgent_latency), data->dmif_burst_time[i][j])))))) { + data->dispclk_required_for_blackout_recovery[i][j] = bw_max2(data->dispclk_required_for_blackout_recovery[i][j], bw_div(bw_mul(bw_div(bw_div((bw_sub(bw_mul(bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]), (bw_add(vbios->blackout_duration, vbios->maximum_blackout_recovery_time))), data->adjusted_data_buffer_size[k])), bw_int_to_fixed(data->bytes_per_pixel[k])), (bw_sub(vbios->maximum_blackout_recovery_time, bw_sub(bw_mul(bw_int_to_fixed(2), data->total_dmifmc_urgent_latency), data->dmif_burst_time[i][j])))), data->latency_hiding_lines[k]), data->lines_interleaved_in_mem_access[k])); + } + } + else { + data->blackout_duration_margin[i][j] = bw_min2(data->blackout_duration_margin[i][j], bw_sub(bw_sub(bw_sub(bw_sub(data->minimum_latency_hiding_with_cursor[k], vbios->blackout_duration), data->dmif_burst_time[i][j]), data->mcifwr_burst_time[i][j]), data->line_source_transfer_time[k][i][j])); + data->dispclk_required_for_blackout_duration[i][j] = bw_max3(data->dispclk_required_for_blackout_duration[i][j], bw_div(bw_div(bw_mul(data->src_pixels_for_first_output_pixel[k], dceip->display_pipe_throughput_factor), dceip->lb_write_pixels_per_dispclk), (bw_sub(bw_sub(bw_sub(data->minimum_latency_hiding_with_cursor[k], vbios->blackout_duration), data->dmif_burst_time[i][j]), data->mcifwr_burst_time[i][j]))), bw_div(bw_div(bw_mul(data->src_pixels_for_last_output_pixel[k], dceip->display_pipe_throughput_factor), dceip->lb_write_pixels_per_dispclk), (bw_add(bw_sub(bw_sub(bw_sub(data->minimum_latency_hiding_with_cursor[k], vbios->blackout_duration), data->dmif_burst_time[i][j]), data->mcifwr_burst_time[i][j]), data->active_time[k])))); + if (bw_ltn(vbios->maximum_blackout_recovery_time, bw_add(bw_add(bw_mul(bw_int_to_fixed(2), vbios->mcifwrmc_urgent_latency), data->dmif_burst_time[i][j]), data->mcifwr_burst_time[i][j]))) { + data->dispclk_required_for_blackout_recovery[i][j] = bw_int_to_fixed(9999); + } + else if (bw_ltn(data->adjusted_data_buffer_size[k], bw_mul(bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]), (bw_add(vbios->blackout_duration, bw_add(bw_mul(bw_int_to_fixed(2), data->total_dmifmc_urgent_latency), data->dmif_burst_time[i][j])))))) { + data->dispclk_required_for_blackout_recovery[i][j] = bw_max2(data->dispclk_required_for_blackout_recovery[i][j], bw_div(bw_mul(bw_div(bw_div((bw_sub(bw_mul(bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]), (bw_add(vbios->blackout_duration, vbios->maximum_blackout_recovery_time))), data->adjusted_data_buffer_size[k])), bw_int_to_fixed(data->bytes_per_pixel[k])), (bw_sub(vbios->maximum_blackout_recovery_time, (bw_add(bw_mul(bw_int_to_fixed(2), data->total_dmifmc_urgent_latency), data->dmif_burst_time[i][j]))))), data->latency_hiding_lines[k]), data->lines_interleaved_in_mem_access[k])); + } + } + } + } + } + } + if (bw_mtn(data->blackout_duration_margin[high][s_high], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[high][s_high], vbios->high_voltage_max_dispclk)) { + data->cpup_state_change_enable = bw_def_yes; + if (bw_ltn(data->dispclk_required_for_blackout_recovery[high][s_high], vbios->high_voltage_max_dispclk)) { + data->cpuc_state_change_enable = bw_def_yes; + } + else { + data->cpuc_state_change_enable = bw_def_no; + } + } + else { + data->cpup_state_change_enable = bw_def_no; + data->cpuc_state_change_enable = bw_def_no; + } + /*nb p-state change enable*/ + /*for dram speed/p-state change to be possible for a yclk(pclk) and sclk level there has to be positive margin and the dispclk required has to be*/ + /*below the maximum.*/ + /*the dram speed/p-state change margin is the minimum for all surfaces of the maximum latency hiding minus the dram speed/p-state change latency,*/ + /*minus the dmif burst time, minus the source line transfer time*/ + /*the maximum latency hiding is the minimum latency hiding plus one source line used for de-tiling in the line buffer, plus half the urgent latency*/ + /*if stutter and dram clock state change are gated before cursor then the cursor latency hiding does not limit stutter or dram clock state change*/ + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if ((dceip->graphics_lb_nodownscaling_multi_line_prefetching == 1)) { + data->maximum_latency_hiding[i] = bw_add(data->minimum_latency_hiding[i], bw_mul(bw_frc_to_fixed(8, 10), data->total_dmifmc_urgent_latency)); + } + else { + /*maximum_latency_hiding(i) = minimum_latency_hiding(i) + 1 / vsr(i) * h_total(i) / pixel_rate(i) + 0.5 * total_dmifmc_urgent_latency*/ + data->maximum_latency_hiding[i] = bw_add(data->minimum_latency_hiding[i], bw_mul(bw_frc_to_fixed(8, 10), data->total_dmifmc_urgent_latency)); + } + data->maximum_latency_hiding_with_cursor[i] = bw_min2(data->maximum_latency_hiding[i], data->cursor_latency_hiding[i]); + } + } + /*initialize variables*/ + number_of_displays_enabled = 0; + number_of_displays_enabled_with_margin = 0; + for (k = 0; k < maximum_number_of_surfaces; k++) { + if (data->enable[k]) { + number_of_displays_enabled = number_of_displays_enabled + 1; + } + } + data->display_pstate_change_enable[maximum_number_of_surfaces - 1] = 0; + for (i = 0; i <= 2; i++) { + for (j = 0; j <= 7; j++) { + data->min_dram_speed_change_margin[i][j] = bw_int_to_fixed(9999); + data->dram_speed_change_margin = bw_int_to_fixed(9999); + data->dispclk_required_for_dram_speed_change[i][j] = bw_int_to_fixed(0); + data->num_displays_with_margin[i][j] = 0; + for (k = 0; k <= maximum_number_of_surfaces - 1; k++) { + if (data->enable[k]) { + if (surface_type[k] != bw_def_display_write_back420_luma && surface_type[k] != bw_def_display_write_back420_chroma) { + data->dram_speed_change_margin = bw_sub(bw_sub(bw_sub(data->maximum_latency_hiding_with_cursor[k], vbios->nbp_state_change_latency), data->dmif_burst_time[i][j]), data->dram_speed_change_line_source_transfer_time[k][i][j]); + if ((bw_mtn(data->dram_speed_change_margin, bw_int_to_fixed(0)) && bw_ltn(data->dram_speed_change_margin, bw_int_to_fixed(9999)))) { + /*determine the minimum dram clock change margin for each set of clock frequencies*/ + data->min_dram_speed_change_margin[i][j] = bw_min2(data->min_dram_speed_change_margin[i][j], data->dram_speed_change_margin); + /*compute the maximum clock frequuency required for the dram clock change at each set of clock frequencies*/ + data->dispclk_required_for_dram_speed_change[i][j] = bw_max3(data->dispclk_required_for_dram_speed_change[i][j], bw_div(bw_div(bw_mul(data->src_pixels_for_first_output_pixel[k], dceip->display_pipe_throughput_factor), dceip->lb_write_pixels_per_dispclk), (bw_sub(bw_sub(bw_sub(data->maximum_latency_hiding_with_cursor[k], vbios->nbp_state_change_latency), data->dmif_burst_time[i][j]), data->dram_speed_change_line_source_transfer_time[k][i][j]))), bw_div(bw_div(bw_mul(data->src_pixels_for_last_output_pixel[k], dceip->display_pipe_throughput_factor), dceip->lb_write_pixels_per_dispclk), (bw_add(bw_sub(bw_sub(bw_sub(data->maximum_latency_hiding_with_cursor[k], vbios->nbp_state_change_latency), data->dmif_burst_time[i][j]), data->dram_speed_change_line_source_transfer_time[k][i][j]), data->active_time[k])))); + if ((bw_ltn(data->dispclk_required_for_dram_speed_change[i][j], vbios->high_voltage_max_dispclk))) { + data->display_pstate_change_enable[k] = 1; + data->num_displays_with_margin[i][j] = data->num_displays_with_margin[i][j] + 1; + } + } + } + else { + data->dram_speed_change_margin = bw_sub(bw_sub(bw_sub(bw_sub(data->maximum_latency_hiding_with_cursor[k], vbios->nbp_state_change_latency), data->dmif_burst_time[i][j]), data->mcifwr_burst_time[i][j]), data->dram_speed_change_line_source_transfer_time[k][i][j]); + if ((bw_mtn(data->dram_speed_change_margin, bw_int_to_fixed(0)) && bw_ltn(data->dram_speed_change_margin, bw_int_to_fixed(9999)))) { + /*determine the minimum dram clock change margin for each display pipe*/ + data->min_dram_speed_change_margin[i][j] = bw_min2(data->min_dram_speed_change_margin[i][j], data->dram_speed_change_margin); + /*compute the maximum clock frequuency required for the dram clock change at each set of clock frequencies*/ + data->dispclk_required_for_dram_speed_change[i][j] = bw_max3(data->dispclk_required_for_dram_speed_change[i][j], bw_div(bw_div(bw_mul(data->src_pixels_for_first_output_pixel[k], dceip->display_pipe_throughput_factor), dceip->lb_write_pixels_per_dispclk), (bw_sub(bw_sub(bw_sub(bw_sub(data->maximum_latency_hiding_with_cursor[k], vbios->nbp_state_change_latency), data->dmif_burst_time[i][j]), data->dram_speed_change_line_source_transfer_time[k][i][j]), data->mcifwr_burst_time[i][j]))), bw_div(bw_div(bw_mul(data->src_pixels_for_last_output_pixel[k], dceip->display_pipe_throughput_factor), dceip->lb_write_pixels_per_dispclk), (bw_add(bw_sub(bw_sub(bw_sub(bw_sub(data->maximum_latency_hiding_with_cursor[k], vbios->nbp_state_change_latency), data->dmif_burst_time[i][j]), data->dram_speed_change_line_source_transfer_time[k][i][j]), data->mcifwr_burst_time[i][j]), data->active_time[k])))); + if ((bw_ltn(data->dispclk_required_for_dram_speed_change[i][j], vbios->high_voltage_max_dispclk))) { + data->display_pstate_change_enable[k] = 1; + data->num_displays_with_margin[i][j] = data->num_displays_with_margin[i][j] + 1; + } + } + } + } + } + } + } + /*determine the number of displays with margin to switch in the v_active region*/ + for (k = 0; k <= maximum_number_of_surfaces - 1; k++) { + if ((data->enable[k] == 1 && data->display_pstate_change_enable[k] == 1)) { + number_of_displays_enabled_with_margin = number_of_displays_enabled_with_margin + 1; + } + } + /*determine the number of displays that don't have any dram clock change margin, but*/ + /*have the same resolution. these displays can switch in a common vblank region if*/ + /*their frames are aligned.*/ + data->min_vblank_dram_speed_change_margin = bw_int_to_fixed(9999); + for (k = 0; k <= maximum_number_of_surfaces - 1; k++) { + if (data->enable[k]) { + if (surface_type[k] != bw_def_display_write_back420_luma && surface_type[k] != bw_def_display_write_back420_chroma) { + data->v_blank_dram_speed_change_margin[k] = bw_sub(bw_sub(bw_sub(bw_div(bw_mul((bw_sub(data->v_total[k], bw_sub(bw_div(data->src_height[k], data->v_scale_ratio[k]), bw_int_to_fixed(4)))), data->h_total[k]), data->pixel_rate[k]), vbios->nbp_state_change_latency), data->dmif_burst_time[low][s_low]), data->dram_speed_change_line_source_transfer_time[k][low][s_low]); + data->min_vblank_dram_speed_change_margin = bw_min2(data->min_vblank_dram_speed_change_margin, data->v_blank_dram_speed_change_margin[k]); + } + else { + data->v_blank_dram_speed_change_margin[k] = bw_sub(bw_sub(bw_sub(bw_sub(bw_div(bw_mul((bw_sub(data->v_total[k], bw_sub(bw_div(data->src_height[k], data->v_scale_ratio[k]), bw_int_to_fixed(4)))), data->h_total[k]), data->pixel_rate[k]), vbios->nbp_state_change_latency), data->dmif_burst_time[low][s_low]), data->mcifwr_burst_time[low][s_low]), data->dram_speed_change_line_source_transfer_time[k][low][s_low]); + data->min_vblank_dram_speed_change_margin = bw_min2(data->min_vblank_dram_speed_change_margin, data->v_blank_dram_speed_change_margin[k]); + } + } + } + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + data->displays_with_same_mode[i] = bw_int_to_fixed(0); + if (data->enable[i] == 1 && data->display_pstate_change_enable[i] == 0 && bw_mtn(data->v_blank_dram_speed_change_margin[i], bw_int_to_fixed(0))) { + for (j = 0; j <= maximum_number_of_surfaces - 1; j++) { + if ((data->enable[j] == 1 && bw_equ(data->source_width_rounded_up_to_chunks[i], data->source_width_rounded_up_to_chunks[j]) && bw_equ(data->source_height_rounded_up_to_chunks[i], data->source_height_rounded_up_to_chunks[j]) && bw_equ(data->vsr[i], data->vsr[j]) && bw_equ(data->hsr[i], data->hsr[j]) && bw_equ(data->pixel_rate[i], data->pixel_rate[j]))) { + data->displays_with_same_mode[i] = bw_add(data->displays_with_same_mode[i], bw_int_to_fixed(1)); + } + } + } + } + /*compute the maximum number of aligned displays with no margin*/ + number_of_aligned_displays_with_no_margin = 0; + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + number_of_aligned_displays_with_no_margin = bw_fixed_to_int(bw_max2(bw_int_to_fixed(number_of_aligned_displays_with_no_margin), data->displays_with_same_mode[i])); + } + /*dram clock change is possible, if all displays have positive margin except for one display or a group of*/ + /*aligned displays with the same timing.*/ + /*the display(s) with the negative margin can be switched in the v_blank region while the other*/ + /*displays are in v_blank or v_active.*/ + if ((number_of_displays_enabled_with_margin + number_of_aligned_displays_with_no_margin == number_of_displays_enabled && bw_mtn(data->min_dram_speed_change_margin[high][s_high], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[high][s_high], bw_int_to_fixed(9999)) && bw_ltn(data->dispclk_required_for_dram_speed_change[high][s_high], vbios->high_voltage_max_dispclk))) { + data->nbp_state_change_enable = bw_def_yes; + } + else { + data->nbp_state_change_enable = bw_def_no; + } + /*dram clock change is possible only in vblank if all displays are aligned and have no margin*/ + if ((number_of_aligned_displays_with_no_margin == number_of_displays_enabled)) { + nbp_state_change_enable_blank = bw_def_yes; + } + else { + nbp_state_change_enable_blank = bw_def_no; + } + /*required yclk(pclk)*/ + /*yclk requirement only makes sense if the dmif and mcifwr data total page close-open time is less than the time for data transfer and the total pte requests fit in the scatter-gather saw queque size*/ + /*if that is the case, the yclk requirement is the maximum of the ones required by dmif and mcifwr, and the high/low yclk(pclk) is chosen accordingly*/ + /*high yclk(pclk) has to be selected when dram speed/p-state change is not possible.*/ + data->min_cursor_memory_interface_buffer_size_in_time = bw_int_to_fixed(9999); + /* number of cursor lines stored in the cursor data return buffer*/ + num_cursor_lines = 0; + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if (bw_mtn(data->cursor_width_pixels[i], bw_int_to_fixed(0))) { + /*compute number of cursor lines stored in data return buffer*/ + if (bw_leq(data->cursor_width_pixels[i], bw_int_to_fixed(64)) && dceip->large_cursor == 1) { + num_cursor_lines = 4; + } + else { + num_cursor_lines = 2; + } + data->min_cursor_memory_interface_buffer_size_in_time = bw_min2(data->min_cursor_memory_interface_buffer_size_in_time, bw_div(bw_mul(bw_div(bw_int_to_fixed(num_cursor_lines), data->vsr[i]), data->h_total[i]), data->pixel_rate[i])); + } + } + } + /*compute minimum time to read one chunk from the dmif buffer*/ + if ((number_of_displays_enabled > 2)) { + data->chunk_request_delay = 0; + } + else { + data->chunk_request_delay = bw_fixed_to_int(bw_div(bw_int_to_fixed(512), vbios->high_voltage_max_dispclk)); + } + data->min_read_buffer_size_in_time = bw_min2(data->min_cursor_memory_interface_buffer_size_in_time, data->min_dmif_size_in_time); + data->display_reads_time_for_data_transfer = bw_sub(bw_sub(data->min_read_buffer_size_in_time, data->total_dmifmc_urgent_latency), bw_int_to_fixed(data->chunk_request_delay)); + data->display_writes_time_for_data_transfer = bw_sub(data->min_mcifwr_size_in_time, vbios->mcifwrmc_urgent_latency); + data->dmif_required_dram_bandwidth = bw_div(data->total_display_reads_required_dram_access_data, data->display_reads_time_for_data_transfer); + data->mcifwr_required_dram_bandwidth = bw_div(data->total_display_writes_required_dram_access_data, data->display_writes_time_for_data_transfer); + data->required_dmifmc_urgent_latency_for_page_close_open = bw_div((bw_sub(data->min_read_buffer_size_in_time, data->dmif_total_page_close_open_time)), data->total_dmifmc_urgent_trips); + data->required_mcifmcwr_urgent_latency = bw_sub(data->min_mcifwr_size_in_time, data->mcifwr_total_page_close_open_time); + if (bw_mtn(data->scatter_gather_total_pte_requests, dceip->maximum_total_outstanding_pte_requests_allowed_by_saw)) { + data->required_dram_bandwidth_gbyte_per_second = bw_int_to_fixed(9999); + yclk_message = bw_def_exceeded_allowed_outstanding_pte_req_queue_size; + data->y_clk_level = high; + data->dram_bandwidth = bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[high]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels)); + } + else if (bw_mtn(vbios->dmifmc_urgent_latency, data->required_dmifmc_urgent_latency_for_page_close_open) || bw_mtn(vbios->mcifwrmc_urgent_latency, data->required_mcifmcwr_urgent_latency)) { + data->required_dram_bandwidth_gbyte_per_second = bw_int_to_fixed(9999); + yclk_message = bw_def_exceeded_allowed_page_close_open; + data->y_clk_level = high; + data->dram_bandwidth = bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[high]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels)); + } + else { + data->required_dram_bandwidth_gbyte_per_second = bw_div(bw_max2(data->dmif_required_dram_bandwidth, data->mcifwr_required_dram_bandwidth), bw_int_to_fixed(1000)); + if (bw_ltn(bw_mul(data->required_dram_bandwidth_gbyte_per_second, bw_int_to_fixed(1000)), bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[low]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels))) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[low][s_high], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[low][s_high], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[low][s_high], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[low][s_high], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[low][s_high], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[low][s_high], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[low][s_high], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[low][s_high], vbios->high_voltage_max_dispclk) && data->num_displays_with_margin[low][s_high] == number_of_displays_enabled_with_margin))) { + yclk_message = bw_fixed_to_int(vbios->low_yclk); + data->y_clk_level = low; + data->dram_bandwidth = bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[low]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels)); + } + else if (bw_ltn(bw_mul(data->required_dram_bandwidth_gbyte_per_second, bw_int_to_fixed(1000)), bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[mid]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels))) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[mid][s_high], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[mid][s_high], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[mid][s_high], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[mid][s_high], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[mid][s_high], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[mid][s_high], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[mid][s_high], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[mid][s_high], vbios->high_voltage_max_dispclk) && data->num_displays_with_margin[mid][s_high] == number_of_displays_enabled_with_margin))) { + yclk_message = bw_fixed_to_int(vbios->mid_yclk); + data->y_clk_level = mid; + data->dram_bandwidth = bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[mid]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels)); + } + else if (bw_ltn(bw_mul(data->required_dram_bandwidth_gbyte_per_second, bw_int_to_fixed(1000)), bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[high]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels)))) { + yclk_message = bw_fixed_to_int(vbios->high_yclk); + data->y_clk_level = high; + data->dram_bandwidth = bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[high]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels)); + } + else { + yclk_message = bw_def_exceeded_allowed_maximum_bw; + data->y_clk_level = high; + data->dram_bandwidth = bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[high]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels)); + } + } + /*required sclk*/ + /*sclk requirement only makes sense if the total pte requests fit in the scatter-gather saw queque size*/ + /*if that is the case, the sclk requirement is the maximum of the ones required by dmif and mcifwr, and the high/mid/low sclk is chosen accordingly, unless that choice results in foresaking dram speed/nb p-state change.*/ + /*the dmif and mcifwr sclk required is the one that allows the transfer of all pipe's data buffer size through the sclk bus in the time for data transfer*/ + /*for dmif, pte and cursor requests have to be included.*/ + data->dmif_required_sclk = bw_div(bw_div(data->total_display_reads_required_data, data->display_reads_time_for_data_transfer), (bw_mul(vbios->data_return_bus_width, bw_int_to_fixed(bus_efficiency)))); + data->mcifwr_required_sclk = bw_div(bw_div(data->total_display_writes_required_data, data->display_writes_time_for_data_transfer), (bw_mul(vbios->data_return_bus_width, bw_int_to_fixed(bus_efficiency)))); + if (bw_mtn(data->scatter_gather_total_pte_requests, dceip->maximum_total_outstanding_pte_requests_allowed_by_saw)) { + data->required_sclk = bw_int_to_fixed(9999); + sclk_message = bw_def_exceeded_allowed_outstanding_pte_req_queue_size; + data->sclk_level = s_high; + } + else if (bw_mtn(vbios->dmifmc_urgent_latency, data->required_dmifmc_urgent_latency_for_page_close_open) || bw_mtn(vbios->mcifwrmc_urgent_latency, data->required_mcifmcwr_urgent_latency)) { + data->required_sclk = bw_int_to_fixed(9999); + sclk_message = bw_def_exceeded_allowed_page_close_open; + data->sclk_level = s_high; + } + else { + data->required_sclk = bw_max2(data->dmif_required_sclk, data->mcifwr_required_sclk); + if (bw_ltn(data->required_sclk, sclk[s_low]) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_low], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_low], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_low], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_low], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[data->y_clk_level][s_low], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[data->y_clk_level][s_low], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[data->y_clk_level][s_low], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[data->y_clk_level][s_low], vbios->low_voltage_max_dispclk) && data->num_displays_with_margin[data->y_clk_level][s_low] == number_of_displays_enabled_with_margin))) { + sclk_message = bw_def_low; + data->sclk_level = s_low; + data->required_sclk = vbios->low_sclk; + } + else if (bw_ltn(data->required_sclk, sclk[s_mid1]) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid1], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid1], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid1], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid1], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[data->y_clk_level][s_mid1], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid1], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid1], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[data->y_clk_level][s_mid1], vbios->mid_voltage_max_dispclk) && data->num_displays_with_margin[data->y_clk_level][s_mid1] == number_of_displays_enabled_with_margin))) { + sclk_message = bw_def_mid; + data->sclk_level = s_mid1; + data->required_sclk = vbios->mid1_sclk; + } + else if (bw_ltn(data->required_sclk, sclk[s_mid2]) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid2], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid2], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid2], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid2], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[data->y_clk_level][s_mid2], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid2], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid2], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[data->y_clk_level][s_mid2], vbios->mid_voltage_max_dispclk) && data->num_displays_with_margin[data->y_clk_level][s_mid2] == number_of_displays_enabled_with_margin))) { + sclk_message = bw_def_mid; + data->sclk_level = s_mid2; + data->required_sclk = vbios->mid2_sclk; + } + else if (bw_ltn(data->required_sclk, sclk[s_mid3]) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid3], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid3], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid3], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid3], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[data->y_clk_level][s_mid3], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid3], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid3], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[data->y_clk_level][s_mid3], vbios->mid_voltage_max_dispclk) && data->num_displays_with_margin[data->y_clk_level][s_mid3] == number_of_displays_enabled_with_margin))) { + sclk_message = bw_def_mid; + data->sclk_level = s_mid3; + data->required_sclk = vbios->mid3_sclk; + } + else if (bw_ltn(data->required_sclk, sclk[s_mid4]) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid4], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid4], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid4], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid4], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[data->y_clk_level][s_mid4], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid4], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid4], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[data->y_clk_level][s_mid4], vbios->mid_voltage_max_dispclk) && data->num_displays_with_margin[data->y_clk_level][s_mid4] == number_of_displays_enabled_with_margin))) { + sclk_message = bw_def_mid; + data->sclk_level = s_mid4; + data->required_sclk = vbios->mid4_sclk; + } + else if (bw_ltn(data->required_sclk, sclk[s_mid5]) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid5], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid5], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid5], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid5], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[data->y_clk_level][s_mid5], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid5], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid5], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[data->y_clk_level][s_mid5], vbios->mid_voltage_max_dispclk) && data->num_displays_with_margin[data->y_clk_level][s_mid5] == number_of_displays_enabled_with_margin))) { + sclk_message = bw_def_mid; + data->sclk_level = s_mid5; + data->required_sclk = vbios->mid5_sclk; + } + else if (bw_ltn(data->required_sclk, sclk[s_mid6]) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid6], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid6], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid6], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid6], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[data->y_clk_level][s_mid6], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid6], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid6], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[data->y_clk_level][s_mid6], vbios->high_voltage_max_dispclk) && data->num_displays_with_margin[data->y_clk_level][s_mid6] == number_of_displays_enabled_with_margin))) { + sclk_message = bw_def_mid; + data->sclk_level = s_mid6; + data->required_sclk = vbios->mid6_sclk; + } + else if (bw_ltn(data->required_sclk, sclk[s_high])) { + sclk_message = bw_def_high; + data->sclk_level = s_high; + data->required_sclk = vbios->high_sclk; + } + else { + sclk_message = bw_def_exceeded_allowed_maximum_sclk; + data->sclk_level = s_high; + /*required_sclk = high_sclk*/ + } + } + /*dispclk*/ + /*if dispclk is set to the maximum, ramping is not required. dispclk required without ramping is less than the dispclk required with ramping.*/ + /*if dispclk required without ramping is more than the maximum dispclk, that is the dispclk required, and the mode is not supported*/ + /*if that does not happen, but dispclk required with ramping is more than the maximum dispclk, dispclk required is just the maximum dispclk*/ + /*if that does not happen either, dispclk required is the dispclk required with ramping.*/ + /*dispclk required without ramping is the maximum of the one required for display pipe pixel throughput, for scaler throughput, for total read request thrrougput and for dram/np p-state change if enabled.*/ + /*the display pipe pixel throughput is the maximum of lines in per line out in the beginning of the frame and lines in per line out in the middle of the frame multiplied by the horizontal blank and chunk granularity factor, altogether multiplied by the ratio of the source width to the line time, divided by the line buffer pixels per dispclk throughput, and multiplied by the display pipe throughput factor.*/ + /*the horizontal blank and chunk granularity factor is the ratio of the line time divided by the line time minus half the horizontal blank and chunk time. it applies when the lines in per line out is not 2 or 4.*/ + /*the dispclk required for scaler throughput is the product of the pixel rate and the scaling limits factor.*/ + /*the dispclk required for total read request throughput is the product of the peak request-per-second bandwidth and the dispclk cycles per request, divided by the request efficiency.*/ + /*for the dispclk required with ramping, instead of multiplying just the pipe throughput by the display pipe throughput factor, we multiply the scaler and pipe throughput by the ramping factor.*/ + /*the scaling limits factor is the product of the horizontal scale ratio, and the ratio of the vertical taps divided by the scaler efficiency clamped to at least 1.*/ + /*the scaling limits factor itself it also clamped to at least 1*/ + /*if doing downscaling with the pre-downscaler enabled, the horizontal scale ratio should not be considered above (use "1")*/ + data->downspread_factor = bw_add(bw_int_to_fixed(1), bw_div(vbios->down_spread_percentage, bw_int_to_fixed(100))); + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if (surface_type[i] == bw_def_graphics) { + switch (data->lb_bpc[i]) { + case 6: + data->v_scaler_efficiency = dceip->graphics_vscaler_efficiency6_bit_per_component; + break; + case 8: + data->v_scaler_efficiency = dceip->graphics_vscaler_efficiency8_bit_per_component; + break; + case 10: + data->v_scaler_efficiency = dceip->graphics_vscaler_efficiency10_bit_per_component; + break; + default: + data->v_scaler_efficiency = dceip->graphics_vscaler_efficiency12_bit_per_component; + break; + } + if (data->use_alpha[i] == 1) { + data->v_scaler_efficiency = bw_min2(data->v_scaler_efficiency, dceip->alpha_vscaler_efficiency); + } + } + else { + switch (data->lb_bpc[i]) { + case 6: + data->v_scaler_efficiency = dceip->underlay_vscaler_efficiency6_bit_per_component; + break; + case 8: + data->v_scaler_efficiency = dceip->underlay_vscaler_efficiency8_bit_per_component; + break; + case 10: + data->v_scaler_efficiency = dceip->underlay_vscaler_efficiency10_bit_per_component; + break; + default: + data->v_scaler_efficiency = dceip->underlay_vscaler_efficiency12_bit_per_component; + break; + } + } + if (dceip->pre_downscaler_enabled && bw_mtn(data->hsr[i], bw_int_to_fixed(1))) { + data->scaler_limits_factor = bw_max2(bw_div(data->v_taps[i], data->v_scaler_efficiency), bw_div(data->source_width_rounded_up_to_chunks[i], data->h_total[i])); + } + else { + data->scaler_limits_factor = bw_max3(bw_int_to_fixed(1), bw_ceil2(bw_div(data->h_taps[i], bw_int_to_fixed(4)), bw_int_to_fixed(1)), bw_mul(data->hsr[i], bw_max2(bw_div(data->v_taps[i], data->v_scaler_efficiency), bw_int_to_fixed(1)))); + } + data->display_pipe_pixel_throughput = bw_div(bw_div(bw_mul(bw_max2(data->lb_lines_in_per_line_out_in_beginning_of_frame[i], bw_mul(data->lb_lines_in_per_line_out_in_middle_of_frame[i], data->horizontal_blank_and_chunk_granularity_factor[i])), data->source_width_rounded_up_to_chunks[i]), (bw_div(data->h_total[i], data->pixel_rate[i]))), dceip->lb_write_pixels_per_dispclk); + data->dispclk_required_without_ramping[i] = bw_mul(data->downspread_factor, bw_max2(bw_mul(data->pixel_rate[i], data->scaler_limits_factor), bw_mul(dceip->display_pipe_throughput_factor, data->display_pipe_pixel_throughput))); + data->dispclk_required_with_ramping[i] = bw_mul(dceip->dispclk_ramping_factor, bw_max2(bw_mul(data->pixel_rate[i], data->scaler_limits_factor), data->display_pipe_pixel_throughput)); + } + } + data->total_dispclk_required_with_ramping = bw_int_to_fixed(0); + data->total_dispclk_required_without_ramping = bw_int_to_fixed(0); + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if (bw_ltn(data->total_dispclk_required_with_ramping, data->dispclk_required_with_ramping[i])) { + data->total_dispclk_required_with_ramping = data->dispclk_required_with_ramping[i]; + } + if (bw_ltn(data->total_dispclk_required_without_ramping, data->dispclk_required_without_ramping[i])) { + data->total_dispclk_required_without_ramping = data->dispclk_required_without_ramping[i]; + } + } + } + data->total_read_request_bandwidth = bw_int_to_fixed(0); + data->total_write_request_bandwidth = bw_int_to_fixed(0); + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if (surface_type[i] != bw_def_display_write_back420_luma && surface_type[i] != bw_def_display_write_back420_chroma) { + data->total_read_request_bandwidth = bw_add(data->total_read_request_bandwidth, data->request_bandwidth[i]); + } + else { + data->total_write_request_bandwidth = bw_add(data->total_write_request_bandwidth, data->request_bandwidth[i]); + } + } + } + data->dispclk_required_for_total_read_request_bandwidth = bw_div(bw_mul(data->total_read_request_bandwidth, dceip->dispclk_per_request), dceip->request_efficiency); + data->total_dispclk_required_with_ramping_with_request_bandwidth = bw_max2(data->total_dispclk_required_with_ramping, data->dispclk_required_for_total_read_request_bandwidth); + data->total_dispclk_required_without_ramping_with_request_bandwidth = bw_max2(data->total_dispclk_required_without_ramping, data->dispclk_required_for_total_read_request_bandwidth); + if (data->cpuc_state_change_enable == bw_def_yes) { + data->total_dispclk_required_with_ramping_with_request_bandwidth = bw_max3(data->total_dispclk_required_with_ramping_with_request_bandwidth, data->dispclk_required_for_blackout_duration[data->y_clk_level][data->sclk_level], data->dispclk_required_for_blackout_recovery[data->y_clk_level][data->sclk_level]); + data->total_dispclk_required_without_ramping_with_request_bandwidth = bw_max3(data->total_dispclk_required_without_ramping_with_request_bandwidth, data->dispclk_required_for_blackout_duration[data->y_clk_level][data->sclk_level], data->dispclk_required_for_blackout_recovery[data->y_clk_level][data->sclk_level]); + } + if (data->cpup_state_change_enable == bw_def_yes) { + data->total_dispclk_required_with_ramping_with_request_bandwidth = bw_max2(data->total_dispclk_required_with_ramping_with_request_bandwidth, data->dispclk_required_for_blackout_duration[data->y_clk_level][data->sclk_level]); + data->total_dispclk_required_without_ramping_with_request_bandwidth = bw_max2(data->total_dispclk_required_without_ramping_with_request_bandwidth, data->dispclk_required_for_blackout_duration[data->y_clk_level][data->sclk_level]); + } + if (data->nbp_state_change_enable == bw_def_yes) { + data->total_dispclk_required_with_ramping_with_request_bandwidth = bw_max2(data->total_dispclk_required_with_ramping_with_request_bandwidth, data->dispclk_required_for_dram_speed_change[data->y_clk_level][data->sclk_level]); + data->total_dispclk_required_without_ramping_with_request_bandwidth = bw_max2(data->total_dispclk_required_without_ramping_with_request_bandwidth, data->dispclk_required_for_dram_speed_change[data->y_clk_level][data->sclk_level]); + } + if (bw_ltn(data->total_dispclk_required_with_ramping_with_request_bandwidth, vbios->high_voltage_max_dispclk)) { + data->dispclk = data->total_dispclk_required_with_ramping_with_request_bandwidth; + } + else if (bw_ltn(data->total_dispclk_required_without_ramping_with_request_bandwidth, vbios->high_voltage_max_dispclk)) { + data->dispclk = vbios->high_voltage_max_dispclk; + } + else { + data->dispclk = data->total_dispclk_required_without_ramping_with_request_bandwidth; + } + /* required core voltage*/ + /* the core voltage required is low if sclk, yclk(pclk)and dispclk are within the low limits*/ + /* otherwise, the core voltage required is medium if yclk (pclk) is within the low limit and sclk and dispclk are within the medium limit*/ + /* otherwise, the core voltage required is high if the three clocks are within the high limits*/ + /* otherwise, or if the mode is not supported, core voltage requirement is not applicable*/ + if (pipe_check == bw_def_notok) { + voltage = bw_def_na; + } + else if (mode_check == bw_def_notok) { + voltage = bw_def_notok; + } + else if (bw_equ(bw_int_to_fixed(yclk_message), vbios->low_yclk) && sclk_message == bw_def_low && bw_ltn(data->dispclk, vbios->low_voltage_max_dispclk)) { + voltage = bw_def_0_72; + } + else if ((bw_equ(bw_int_to_fixed(yclk_message), vbios->low_yclk) || bw_equ(bw_int_to_fixed(yclk_message), vbios->mid_yclk)) && (sclk_message == bw_def_low || sclk_message == bw_def_mid) && bw_ltn(data->dispclk, vbios->mid_voltage_max_dispclk)) { + voltage = bw_def_0_8; + } + else if ((bw_equ(bw_int_to_fixed(yclk_message), vbios->low_yclk) || bw_equ(bw_int_to_fixed(yclk_message), vbios->mid_yclk) || bw_equ(bw_int_to_fixed(yclk_message), vbios->high_yclk)) && (sclk_message == bw_def_low || sclk_message == bw_def_mid || sclk_message == bw_def_high) && bw_leq(data->dispclk, vbios->high_voltage_max_dispclk)) { + if ((data->nbp_state_change_enable == bw_def_no && nbp_state_change_enable_blank == bw_def_no)) { + voltage = bw_def_high_no_nbp_state_change; + } + else { + voltage = bw_def_0_9; + } + } + else { + voltage = bw_def_notok; + } + if (voltage == bw_def_0_72) { + data->max_phyclk = vbios->low_voltage_max_phyclk; + } + else if (voltage == bw_def_0_8) { + data->max_phyclk = vbios->mid_voltage_max_phyclk; + } + else { + data->max_phyclk = vbios->high_voltage_max_phyclk; + } + /*required blackout recovery time*/ + data->blackout_recovery_time = bw_int_to_fixed(0); + for (k = 0; k <= maximum_number_of_surfaces - 1; k++) { + if (data->enable[k] && bw_mtn(vbios->blackout_duration, bw_int_to_fixed(0)) && data->cpup_state_change_enable == bw_def_yes) { + if (surface_type[k] != bw_def_display_write_back420_luma && surface_type[k] != bw_def_display_write_back420_chroma) { + data->blackout_recovery_time = bw_max2(data->blackout_recovery_time, bw_add(bw_mul(bw_int_to_fixed(2), data->total_dmifmc_urgent_latency), data->dmif_burst_time[data->y_clk_level][data->sclk_level])); + if (bw_ltn(data->adjusted_data_buffer_size[k], bw_mul(bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]), (bw_add(vbios->blackout_duration, bw_add(bw_mul(bw_int_to_fixed(2), data->total_dmifmc_urgent_latency), data->dmif_burst_time[data->y_clk_level][data->sclk_level])))))) { + data->blackout_recovery_time = bw_max2(data->blackout_recovery_time, bw_div((bw_add(bw_mul(bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]), vbios->blackout_duration), bw_sub(bw_div(bw_mul(bw_mul(bw_mul((bw_add(bw_mul(bw_int_to_fixed(2), data->total_dmifmc_urgent_latency), data->dmif_burst_time[data->y_clk_level][data->sclk_level])), data->dispclk), bw_int_to_fixed(data->bytes_per_pixel[k])), data->lines_interleaved_in_mem_access[k]), data->latency_hiding_lines[k]), data->adjusted_data_buffer_size[k]))), (bw_sub(bw_div(bw_mul(bw_mul(data->dispclk, bw_int_to_fixed(data->bytes_per_pixel[k])), data->lines_interleaved_in_mem_access[k]), data->latency_hiding_lines[k]), bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]))))); + } + } + else { + data->blackout_recovery_time = bw_max2(data->blackout_recovery_time, bw_add(bw_mul(bw_int_to_fixed(2), vbios->mcifwrmc_urgent_latency), data->mcifwr_burst_time[data->y_clk_level][data->sclk_level])); + if (bw_ltn(data->adjusted_data_buffer_size[k], bw_mul(bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]), (bw_add(vbios->blackout_duration, bw_add(bw_mul(bw_int_to_fixed(2), vbios->mcifwrmc_urgent_latency), data->mcifwr_burst_time[data->y_clk_level][data->sclk_level])))))) { + data->blackout_recovery_time = bw_max2(data->blackout_recovery_time, bw_div((bw_add(bw_mul(bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]), vbios->blackout_duration), bw_sub(bw_div(bw_mul(bw_mul(bw_mul((bw_add(bw_add(bw_mul(bw_int_to_fixed(2), vbios->mcifwrmc_urgent_latency), data->dmif_burst_time[data->y_clk_level][data->sclk_level]), data->mcifwr_burst_time[data->y_clk_level][data->sclk_level])), data->dispclk), bw_int_to_fixed(data->bytes_per_pixel[k])), data->lines_interleaved_in_mem_access[k]), data->latency_hiding_lines[k]), data->adjusted_data_buffer_size[k]))), (bw_sub(bw_div(bw_mul(bw_mul(data->dispclk, bw_int_to_fixed(data->bytes_per_pixel[k])), data->lines_interleaved_in_mem_access[k]), data->latency_hiding_lines[k]), bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]))))); + } + } + } + } + /*sclk deep sleep*/ + /*during self-refresh, sclk can be reduced to dispclk divided by the minimum pixels in the data fifo entry, with 15% margin, but shoudl not be set to less than the request bandwidth.*/ + /*the data fifo entry is 16 pixels for the writeback, 64 bytes/bytes_per_pixel for the graphics, 16 pixels for the parallel rotation underlay,*/ + /*and 16 bytes/bytes_per_pixel for the orthogonal rotation underlay.*/ + /*in parallel mode (underlay pipe), the data read from the dmifv buffer is variable and based on the pixel depth (8bbp - 16 bytes, 16 bpp - 32 bytes, 32 bpp - 64 bytes)*/ + /*in orthogonal mode (underlay pipe), the data read from the dmifv buffer is fixed at 16 bytes.*/ + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if (surface_type[i] == bw_def_display_write_back420_luma || surface_type[i] == bw_def_display_write_back420_chroma) { + data->pixels_per_data_fifo_entry[i] = bw_int_to_fixed(16); + } + else if (surface_type[i] == bw_def_graphics) { + data->pixels_per_data_fifo_entry[i] = bw_div(bw_int_to_fixed(64), bw_int_to_fixed(data->bytes_per_pixel[i])); + } + else if (data->orthogonal_rotation[i] == 0) { + data->pixels_per_data_fifo_entry[i] = bw_int_to_fixed(16); + } + else { + data->pixels_per_data_fifo_entry[i] = bw_div(bw_int_to_fixed(16), bw_int_to_fixed(data->bytes_per_pixel[i])); + } + } + } + data->min_pixels_per_data_fifo_entry = bw_int_to_fixed(9999); + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if (bw_mtn(data->min_pixels_per_data_fifo_entry, data->pixels_per_data_fifo_entry[i])) { + data->min_pixels_per_data_fifo_entry = data->pixels_per_data_fifo_entry[i]; + } + } + } + data->sclk_deep_sleep = bw_max2(bw_div(bw_mul(data->dispclk, bw_frc_to_fixed(115, 100)), data->min_pixels_per_data_fifo_entry), data->total_read_request_bandwidth); + /*urgent, stutter and nb-p_state watermark*/ + /*the urgent watermark is the maximum of the urgent trip time plus the pixel transfer time, the urgent trip times to get data for the first pixel, and the urgent trip times to get data for the last pixel.*/ + /*the stutter exit watermark is the self refresh exit time plus the maximum of the data burst time plus the pixel transfer time, the data burst times to get data for the first pixel, and the data burst times to get data for the last pixel. it does not apply to the writeback.*/ + /*the nb p-state change watermark is the dram speed/p-state change time plus the maximum of the data burst time plus the pixel transfer time, the data burst times to get data for the first pixel, and the data burst times to get data for the last pixel.*/ + /*the pixel transfer time is the maximum of the time to transfer the source pixels required for the first output pixel, and the time to transfer the pixels for the last output pixel minus the active line time.*/ + /*blackout_duration is added to the urgent watermark*/ + data->chunk_request_time = bw_int_to_fixed(0); + data->cursor_request_time = bw_int_to_fixed(0); + /*compute total time to request one chunk from each active display pipe*/ + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + data->chunk_request_time = bw_add(data->chunk_request_time, (bw_div((bw_div(bw_int_to_fixed(pixels_per_chunk * data->bytes_per_pixel[i]), data->useful_bytes_per_request[i])), bw_min2(sclk[data->sclk_level], bw_div(data->dispclk, bw_int_to_fixed(2)))))); + } + } + /*compute total time to request cursor data*/ + data->cursor_request_time = (bw_div(data->cursor_total_data, (bw_mul(bw_int_to_fixed(32), sclk[data->sclk_level])))); + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + data->line_source_pixels_transfer_time = bw_max2(bw_div(bw_div(data->src_pixels_for_first_output_pixel[i], dceip->lb_write_pixels_per_dispclk), (bw_div(data->dispclk, dceip->display_pipe_throughput_factor))), bw_sub(bw_div(bw_div(data->src_pixels_for_last_output_pixel[i], dceip->lb_write_pixels_per_dispclk), (bw_div(data->dispclk, dceip->display_pipe_throughput_factor))), data->active_time[i])); + if (surface_type[i] != bw_def_display_write_back420_luma && surface_type[i] != bw_def_display_write_back420_chroma) { + data->urgent_watermark[i] = bw_add(bw_add(bw_add(bw_add(bw_add(data->total_dmifmc_urgent_latency, data->dmif_burst_time[data->y_clk_level][data->sclk_level]), bw_max2(data->line_source_pixels_transfer_time, data->line_source_transfer_time[i][data->y_clk_level][data->sclk_level])), vbios->blackout_duration), data->chunk_request_time), data->cursor_request_time); + data->stutter_exit_watermark[i] = bw_add(bw_sub(vbios->stutter_self_refresh_exit_latency, data->total_dmifmc_urgent_latency), data->urgent_watermark[i]); + data->stutter_entry_watermark[i] = bw_add(bw_sub(bw_add(vbios->stutter_self_refresh_exit_latency, vbios->stutter_self_refresh_entry_latency), data->total_dmifmc_urgent_latency), data->urgent_watermark[i]); + /*unconditionally remove black out time from the nb p_state watermark*/ + if ((data->display_pstate_change_enable[i] == 1)) { + data->nbp_state_change_watermark[i] = bw_add(bw_add(vbios->nbp_state_change_latency, data->dmif_burst_time[data->y_clk_level][data->sclk_level]), bw_max2(data->line_source_pixels_transfer_time, data->dram_speed_change_line_source_transfer_time[i][data->y_clk_level][data->sclk_level])); + } + else { + /*maximize the watermark to force the switch in the vb_lank region of the frame*/ + data->nbp_state_change_watermark[i] = bw_int_to_fixed(131000); + } + } + else { + data->urgent_watermark[i] = bw_add(bw_add(bw_add(bw_add(bw_add(vbios->mcifwrmc_urgent_latency, data->mcifwr_burst_time[data->y_clk_level][data->sclk_level]), bw_max2(data->line_source_pixels_transfer_time, data->line_source_transfer_time[i][data->y_clk_level][data->sclk_level])), vbios->blackout_duration), data->chunk_request_time), data->cursor_request_time); + data->stutter_exit_watermark[i] = bw_int_to_fixed(0); + data->stutter_entry_watermark[i] = bw_int_to_fixed(0); + if ((data->display_pstate_change_enable[i] == 1)) { + data->nbp_state_change_watermark[i] = bw_add(bw_add(vbios->nbp_state_change_latency, data->mcifwr_burst_time[data->y_clk_level][data->sclk_level]), bw_max2(data->line_source_pixels_transfer_time, data->dram_speed_change_line_source_transfer_time[i][data->y_clk_level][data->sclk_level])); + } + else { + /*maximize the watermark to force the switch in the vb_lank region of the frame*/ + data->nbp_state_change_watermark[i] = bw_int_to_fixed(131000); + } + } + } + } + /*stutter mode enable*/ + /*in the multi-display case the stutter exit or entry watermark cannot exceed the minimum latency hiding capabilities of the*/ + /*display pipe.*/ + data->stutter_mode_enable = data->cpuc_state_change_enable; + if (data->number_of_displays > 1) { + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if ((bw_mtn(data->stutter_exit_watermark[i], data->minimum_latency_hiding[i]) || bw_mtn(data->stutter_entry_watermark[i], data->minimum_latency_hiding[i]))) { + data->stutter_mode_enable = bw_def_no; + } + } + } + } + /*performance metrics*/ + /* display read access efficiency (%)*/ + /* display write back access efficiency (%)*/ + /* stutter efficiency (%)*/ + /* extra underlay pitch recommended for efficiency (pixels)*/ + /* immediate flip time (us)*/ + /* latency for other clients due to urgent display read (us)*/ + /* latency for other clients due to urgent display write (us)*/ + /* average bandwidth consumed by display (no compression) (gb/s)*/ + /* required dram bandwidth (gb/s)*/ + /* required sclk (m_hz)*/ + /* required rd urgent latency (us)*/ + /* nb p-state change margin (us)*/ + /*dmif and mcifwr dram access efficiency*/ + /*is the ratio between the ideal dram access time (which is the data buffer size in memory divided by the dram bandwidth), and the actual time which is the total page close-open time. but it cannot exceed the dram efficiency provided by the memory subsystem*/ + data->dmifdram_access_efficiency = bw_min2(bw_div(bw_div(data->total_display_reads_required_dram_access_data, data->dram_bandwidth), data->dmif_total_page_close_open_time), bw_int_to_fixed(1)); + if (bw_mtn(data->total_display_writes_required_dram_access_data, bw_int_to_fixed(0))) { + data->mcifwrdram_access_efficiency = bw_min2(bw_div(bw_div(data->total_display_writes_required_dram_access_data, data->dram_bandwidth), data->mcifwr_total_page_close_open_time), bw_int_to_fixed(1)); + } + else { + data->mcifwrdram_access_efficiency = bw_int_to_fixed(0); + } + /*average bandwidth*/ + /*the average bandwidth with no compression is the vertical active time is the source width times the bytes per pixel divided by the line time, multiplied by the vertical scale ratio and the ratio of bytes per request divided by the useful bytes per request.*/ + /*the average bandwidth with compression is the same, divided by the compression ratio*/ + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + data->average_bandwidth_no_compression[i] = bw_div(bw_mul(bw_mul(bw_div(bw_mul(data->source_width_rounded_up_to_chunks[i], bw_int_to_fixed(data->bytes_per_pixel[i])), (bw_div(data->h_total[i], data->pixel_rate[i]))), data->vsr[i]), data->bytes_per_request[i]), data->useful_bytes_per_request[i]); + data->average_bandwidth[i] = bw_div(data->average_bandwidth_no_compression[i], data->compression_rate[i]); + } + } + data->total_average_bandwidth_no_compression = bw_int_to_fixed(0); + data->total_average_bandwidth = bw_int_to_fixed(0); + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + data->total_average_bandwidth_no_compression = bw_add(data->total_average_bandwidth_no_compression, data->average_bandwidth_no_compression[i]); + data->total_average_bandwidth = bw_add(data->total_average_bandwidth, data->average_bandwidth[i]); + } + } + /*stutter efficiency*/ + /*the stutter efficiency is the frame-average time in self-refresh divided by the frame-average stutter cycle duration. only applies if the display write-back is not enabled.*/ + /*the frame-average stutter cycle used is the minimum for all pipes of the frame-average data buffer size in time, times the compression rate*/ + /*the frame-average time in self-refresh is the stutter cycle minus the self refresh exit latency and the burst time*/ + /*the stutter cycle is the dmif buffer size reduced by the excess of the stutter exit watermark over the lb size in time.*/ + /*the burst time is the data needed during the stutter cycle divided by the available bandwidth*/ + /*compute the time read all the data from the dmif buffer to the lb (dram refresh period)*/ + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + data->stutter_refresh_duration[i] = bw_sub(bw_mul(bw_div(bw_div(bw_mul(bw_div(bw_div(data->adjusted_data_buffer_size[i], bw_int_to_fixed(data->bytes_per_pixel[i])), data->source_width_rounded_up_to_chunks[i]), data->h_total[i]), data->vsr[i]), data->pixel_rate[i]), data->compression_rate[i]), bw_max2(bw_int_to_fixed(0), bw_sub(data->stutter_exit_watermark[i], bw_div(bw_mul((bw_sub(data->lb_partitions[i], bw_int_to_fixed(1))), data->h_total[i]), data->pixel_rate[i])))); + data->stutter_dmif_buffer_size[i] = bw_div(bw_mul(bw_mul(bw_div(bw_mul(bw_mul(data->stutter_refresh_duration[i], bw_int_to_fixed(data->bytes_per_pixel[i])), data->source_width_rounded_up_to_chunks[i]), data->h_total[i]), data->vsr[i]), data->pixel_rate[i]), data->compression_rate[i]); + } + } + data->min_stutter_refresh_duration = bw_int_to_fixed(9999); + data->total_stutter_dmif_buffer_size = 0; + data->total_bytes_requested = 0; + data->min_stutter_dmif_buffer_size = 9999; + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if (bw_mtn(data->min_stutter_refresh_duration, data->stutter_refresh_duration[i])) { + data->min_stutter_refresh_duration = data->stutter_refresh_duration[i]; + data->total_bytes_requested = bw_fixed_to_int(bw_add(bw_int_to_fixed(data->total_bytes_requested), (bw_mul(bw_mul(data->source_height_rounded_up_to_chunks[i], data->source_width_rounded_up_to_chunks[i]), bw_int_to_fixed(data->bytes_per_pixel[i]))))); + data->min_stutter_dmif_buffer_size = bw_fixed_to_int(data->stutter_dmif_buffer_size[i]); + } + data->total_stutter_dmif_buffer_size = bw_fixed_to_int(bw_add(data->stutter_dmif_buffer_size[i], bw_int_to_fixed(data->total_stutter_dmif_buffer_size))); + } + } + data->stutter_burst_time = bw_div(bw_int_to_fixed(data->total_stutter_dmif_buffer_size), bw_min2(bw_mul(data->dram_bandwidth, data->dmifdram_access_efficiency), bw_mul(sclk[data->sclk_level], bw_int_to_fixed(32)))); + data->num_stutter_bursts = data->total_bytes_requested / data->min_stutter_dmif_buffer_size; + data->total_stutter_cycle_duration = bw_add(bw_add(data->min_stutter_refresh_duration, vbios->stutter_self_refresh_exit_latency), data->stutter_burst_time); + data->time_in_self_refresh = data->min_stutter_refresh_duration; + if (data->d1_display_write_back_dwb_enable == 1) { + data->stutter_efficiency = bw_int_to_fixed(0); + } + else if (bw_ltn(data->time_in_self_refresh, bw_int_to_fixed(0))) { + data->stutter_efficiency = bw_int_to_fixed(0); + } + else { + /*compute stutter efficiency assuming 60 hz refresh rate*/ + data->stutter_efficiency = bw_max2(bw_int_to_fixed(0), bw_mul((bw_sub(bw_int_to_fixed(1), (bw_div(bw_mul((bw_add(vbios->stutter_self_refresh_exit_latency, data->stutter_burst_time)), bw_int_to_fixed(data->num_stutter_bursts)), bw_frc_to_fixed(166666667, 10000))))), bw_int_to_fixed(100))); + } + /*immediate flip time*/ + /*if scatter gather is enabled, the immediate flip takes a number of urgent memory trips equivalent to the pte requests in a row divided by the pte request limit.*/ + /*otherwise, it may take just one urgenr memory trip*/ + data->worst_number_of_trips_to_memory = bw_int_to_fixed(1); + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i] && data->scatter_gather_enable_for_pipe[i] == 1) { + data->number_of_trips_to_memory_for_getting_apte_row[i] = bw_ceil2(bw_div(data->scatter_gather_pte_requests_in_row[i], data->scatter_gather_pte_request_limit[i]), bw_int_to_fixed(1)); + if (bw_ltn(data->worst_number_of_trips_to_memory, data->number_of_trips_to_memory_for_getting_apte_row[i])) { + data->worst_number_of_trips_to_memory = data->number_of_trips_to_memory_for_getting_apte_row[i]; + } + } + } + data->immediate_flip_time = bw_mul(data->worst_number_of_trips_to_memory, data->total_dmifmc_urgent_latency); + /*worst latency for other clients*/ + /*it is the urgent latency plus the urgent burst time*/ + data->latency_for_non_dmif_clients = bw_add(data->total_dmifmc_urgent_latency, data->dmif_burst_time[data->y_clk_level][data->sclk_level]); + if (data->d1_display_write_back_dwb_enable == 1) { + data->latency_for_non_mcifwr_clients = bw_add(vbios->mcifwrmc_urgent_latency, dceip->mcifwr_all_surfaces_burst_time); + } + else { + data->latency_for_non_mcifwr_clients = bw_int_to_fixed(0); + } + /*dmif mc urgent latency suppported in high sclk and yclk*/ + data->dmifmc_urgent_latency_supported_in_high_sclk_and_yclk = bw_div((bw_sub(data->min_read_buffer_size_in_time, data->dmif_burst_time[high][s_high])), data->total_dmifmc_urgent_trips); + /*dram speed/p-state change margin*/ + /*in the multi-display case the nb p-state change watermark cannot exceed the average lb size plus the dmif size or the cursor dcp buffer size*/ + data->v_blank_nbp_state_dram_speed_change_latency_supported = bw_int_to_fixed(99999); + data->nbp_state_dram_speed_change_latency_supported = bw_int_to_fixed(99999); + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + data->nbp_state_dram_speed_change_latency_supported = bw_min2(data->nbp_state_dram_speed_change_latency_supported, bw_add(bw_sub(data->maximum_latency_hiding_with_cursor[i], data->nbp_state_change_watermark[i]), vbios->nbp_state_change_latency)); + data->v_blank_nbp_state_dram_speed_change_latency_supported = bw_min2(data->v_blank_nbp_state_dram_speed_change_latency_supported, bw_add(bw_sub(bw_div(bw_mul((bw_sub(data->v_total[i], bw_sub(bw_div(data->src_height[i], data->v_scale_ratio[i]), bw_int_to_fixed(4)))), data->h_total[i]), data->pixel_rate[i]), data->nbp_state_change_watermark[i]), vbios->nbp_state_change_latency)); + } + } + /*sclk required vs urgent latency*/ + for (i = 1; i <= 5; i++) { + data->display_reads_time_for_data_transfer_and_urgent_latency = bw_sub(data->min_read_buffer_size_in_time, bw_mul(data->total_dmifmc_urgent_trips, bw_int_to_fixed(i))); + if (pipe_check == bw_def_ok && (bw_mtn(data->display_reads_time_for_data_transfer_and_urgent_latency, data->dmif_total_page_close_open_time))) { + data->dmif_required_sclk_for_urgent_latency[i] = bw_div(bw_div(data->total_display_reads_required_data, data->display_reads_time_for_data_transfer_and_urgent_latency), (bw_mul(vbios->data_return_bus_width, bw_int_to_fixed(bus_efficiency)))); + } + else { + data->dmif_required_sclk_for_urgent_latency[i] = bw_int_to_fixed(bw_def_na); + } + } + /*output link bit per pixel supported*/ + for (k = 0; k <= maximum_number_of_surfaces - 1; k++) { + data->output_bpphdmi[k] = bw_def_na; + data->output_bppdp4_lane_hbr[k] = bw_def_na; + data->output_bppdp4_lane_hbr2[k] = bw_def_na; + data->output_bppdp4_lane_hbr3[k] = bw_def_na; + if (data->enable[k]) { + data->output_bpphdmi[k] = bw_fixed_to_int(bw_mul(bw_div(bw_min2(bw_int_to_fixed(600), data->max_phyclk), data->pixel_rate[k]), bw_int_to_fixed(24))); + if (bw_meq(data->max_phyclk, bw_int_to_fixed(270))) { + data->output_bppdp4_lane_hbr[k] = bw_fixed_to_int(bw_mul(bw_div(bw_mul(bw_int_to_fixed(270), bw_int_to_fixed(4)), data->pixel_rate[k]), bw_int_to_fixed(8))); + } + if (bw_meq(data->max_phyclk, bw_int_to_fixed(540))) { + data->output_bppdp4_lane_hbr2[k] = bw_fixed_to_int(bw_mul(bw_div(bw_mul(bw_int_to_fixed(540), bw_int_to_fixed(4)), data->pixel_rate[k]), bw_int_to_fixed(8))); + } + if (bw_meq(data->max_phyclk, bw_int_to_fixed(810))) { + data->output_bppdp4_lane_hbr3[k] = bw_fixed_to_int(bw_mul(bw_div(bw_mul(bw_int_to_fixed(810), bw_int_to_fixed(4)), data->pixel_rate[k]), bw_int_to_fixed(8))); + } + } + } +} + +/******************************************************************************* + * Public functions + ******************************************************************************/ +void bw_calcs_init(struct bw_calcs_dceip *bw_dceip, + struct bw_calcs_vbios *bw_vbios, + struct hw_asic_id asic_id) +{ + struct bw_calcs_dceip dceip = { 0 }; + struct bw_calcs_vbios vbios = { 0 }; + + enum bw_calcs_version version = bw_calcs_version_from_asic_id(asic_id); + + dceip.version = version; + + switch (version) { + case BW_CALCS_VERSION_CARRIZO: + vbios.memory_type = bw_def_gddr5; + vbios.dram_channel_width_in_bits = 64; + vbios.number_of_dram_channels = asic_id.vram_width / vbios.dram_channel_width_in_bits; + vbios.number_of_dram_banks = 8; + vbios.high_yclk = bw_int_to_fixed(1600); + vbios.mid_yclk = bw_int_to_fixed(1600); + vbios.low_yclk = bw_frc_to_fixed(66666, 100); + vbios.low_sclk = bw_int_to_fixed(200); + vbios.mid1_sclk = bw_int_to_fixed(300); + vbios.mid2_sclk = bw_int_to_fixed(300); + vbios.mid3_sclk = bw_int_to_fixed(300); + vbios.mid4_sclk = bw_int_to_fixed(300); + vbios.mid5_sclk = bw_int_to_fixed(300); + vbios.mid6_sclk = bw_int_to_fixed(300); + vbios.high_sclk = bw_frc_to_fixed(62609, 100); + vbios.low_voltage_max_dispclk = bw_int_to_fixed(352); + vbios.mid_voltage_max_dispclk = bw_int_to_fixed(467); + vbios.high_voltage_max_dispclk = bw_int_to_fixed(643); + vbios.low_voltage_max_phyclk = bw_int_to_fixed(540); + vbios.mid_voltage_max_phyclk = bw_int_to_fixed(810); + vbios.high_voltage_max_phyclk = bw_int_to_fixed(810); + vbios.data_return_bus_width = bw_int_to_fixed(32); + vbios.trc = bw_int_to_fixed(50); + vbios.dmifmc_urgent_latency = bw_int_to_fixed(4); + vbios.stutter_self_refresh_exit_latency = bw_frc_to_fixed(153, 10); + vbios.stutter_self_refresh_entry_latency = bw_int_to_fixed(0); + vbios.nbp_state_change_latency = bw_frc_to_fixed(19649, 1000); + vbios.mcifwrmc_urgent_latency = bw_int_to_fixed(10); + vbios.scatter_gather_enable = true; + vbios.down_spread_percentage = bw_frc_to_fixed(5, 10); + vbios.cursor_width = 32; + vbios.average_compression_rate = 4; + vbios.number_of_request_slots_gmc_reserves_for_dmif_per_channel = 256; + vbios.blackout_duration = bw_int_to_fixed(18); /* us */ + vbios.maximum_blackout_recovery_time = bw_int_to_fixed(20); + + dceip.large_cursor = false; + dceip.dmif_request_buffer_size = bw_int_to_fixed(768); + dceip.dmif_pipe_en_fbc_chunk_tracker = false; + dceip.cursor_max_outstanding_group_num = 1; + dceip.lines_interleaved_into_lb = 2; + dceip.chunk_width = 256; + dceip.number_of_graphics_pipes = 3; + dceip.number_of_underlay_pipes = 1; + dceip.low_power_tiling_mode = 0; + dceip.display_write_back_supported = false; + dceip.argb_compression_support = false; + dceip.underlay_vscaler_efficiency6_bit_per_component = + bw_frc_to_fixed(35556, 10000); + dceip.underlay_vscaler_efficiency8_bit_per_component = + bw_frc_to_fixed(34286, 10000); + dceip.underlay_vscaler_efficiency10_bit_per_component = + bw_frc_to_fixed(32, 10); + dceip.underlay_vscaler_efficiency12_bit_per_component = + bw_int_to_fixed(3); + dceip.graphics_vscaler_efficiency6_bit_per_component = + bw_frc_to_fixed(35, 10); + dceip.graphics_vscaler_efficiency8_bit_per_component = + bw_frc_to_fixed(34286, 10000); + dceip.graphics_vscaler_efficiency10_bit_per_component = + bw_frc_to_fixed(32, 10); + dceip.graphics_vscaler_efficiency12_bit_per_component = + bw_int_to_fixed(3); + dceip.alpha_vscaler_efficiency = bw_int_to_fixed(3); + dceip.max_dmif_buffer_allocated = 2; + dceip.graphics_dmif_size = 12288; + dceip.underlay_luma_dmif_size = 19456; + dceip.underlay_chroma_dmif_size = 23552; + dceip.pre_downscaler_enabled = true; + dceip.underlay_downscale_prefetch_enabled = true; + dceip.lb_write_pixels_per_dispclk = bw_int_to_fixed(1); + dceip.lb_size_per_component444 = bw_int_to_fixed(82176); + dceip.graphics_lb_nodownscaling_multi_line_prefetching = false; + dceip.stutter_and_dram_clock_state_change_gated_before_cursor = + bw_int_to_fixed(0); + dceip.underlay420_luma_lb_size_per_component = bw_int_to_fixed( + 82176); + dceip.underlay420_chroma_lb_size_per_component = + bw_int_to_fixed(164352); + dceip.underlay422_lb_size_per_component = bw_int_to_fixed( + 82176); + dceip.cursor_chunk_width = bw_int_to_fixed(64); + dceip.cursor_dcp_buffer_lines = bw_int_to_fixed(4); + dceip.underlay_maximum_width_efficient_for_tiling = + bw_int_to_fixed(1920); + dceip.underlay_maximum_height_efficient_for_tiling = + bw_int_to_fixed(1080); + dceip.peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display = + bw_frc_to_fixed(3, 10); + dceip.peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation = + bw_int_to_fixed(25); + dceip.minimum_outstanding_pte_request_limit = bw_int_to_fixed( + 2); + dceip.maximum_total_outstanding_pte_requests_allowed_by_saw = + bw_int_to_fixed(128); + dceip.limit_excessive_outstanding_dmif_requests = true; + dceip.linear_mode_line_request_alternation_slice = + bw_int_to_fixed(64); + dceip.scatter_gather_lines_of_pte_prefetching_in_linear_mode = + 32; + dceip.display_write_back420_luma_mcifwr_buffer_size = 12288; + dceip.display_write_back420_chroma_mcifwr_buffer_size = 8192; + dceip.request_efficiency = bw_frc_to_fixed(8, 10); + dceip.dispclk_per_request = bw_int_to_fixed(2); + dceip.dispclk_ramping_factor = bw_frc_to_fixed(105, 100); + dceip.display_pipe_throughput_factor = bw_frc_to_fixed(105, 100); + dceip.scatter_gather_pte_request_rows_in_tiling_mode = 2; + dceip.mcifwr_all_surfaces_burst_time = bw_int_to_fixed(0); /* todo: this is a bug*/ + break; + case BW_CALCS_VERSION_POLARIS10: + vbios.memory_type = bw_def_gddr5; + vbios.dram_channel_width_in_bits = 32; + vbios.number_of_dram_channels = asic_id.vram_width / vbios.dram_channel_width_in_bits; + vbios.number_of_dram_banks = 8; + vbios.high_yclk = bw_int_to_fixed(6000); + vbios.mid_yclk = bw_int_to_fixed(3200); + vbios.low_yclk = bw_int_to_fixed(1000); + vbios.low_sclk = bw_int_to_fixed(300); + vbios.mid1_sclk = bw_int_to_fixed(400); + vbios.mid2_sclk = bw_int_to_fixed(500); + vbios.mid3_sclk = bw_int_to_fixed(600); + vbios.mid4_sclk = bw_int_to_fixed(700); + vbios.mid5_sclk = bw_int_to_fixed(800); + vbios.mid6_sclk = bw_int_to_fixed(974); + vbios.high_sclk = bw_int_to_fixed(1154); + vbios.low_voltage_max_dispclk = bw_int_to_fixed(459); + vbios.mid_voltage_max_dispclk = bw_int_to_fixed(654); + vbios.high_voltage_max_dispclk = bw_int_to_fixed(1108); + vbios.low_voltage_max_phyclk = bw_int_to_fixed(540); + vbios.mid_voltage_max_phyclk = bw_int_to_fixed(810); + vbios.high_voltage_max_phyclk = bw_int_to_fixed(810); + vbios.data_return_bus_width = bw_int_to_fixed(32); + vbios.trc = bw_int_to_fixed(48); + vbios.dmifmc_urgent_latency = bw_int_to_fixed(3); + vbios.stutter_self_refresh_exit_latency = bw_int_to_fixed(5); + vbios.stutter_self_refresh_entry_latency = bw_int_to_fixed(0); + vbios.nbp_state_change_latency = bw_int_to_fixed(45); + vbios.mcifwrmc_urgent_latency = bw_int_to_fixed(10); + vbios.scatter_gather_enable = true; + vbios.down_spread_percentage = bw_frc_to_fixed(5, 10); + vbios.cursor_width = 32; + vbios.average_compression_rate = 4; + vbios.number_of_request_slots_gmc_reserves_for_dmif_per_channel = 256; + vbios.blackout_duration = bw_int_to_fixed(0); /* us */ + vbios.maximum_blackout_recovery_time = bw_int_to_fixed(0); + + dceip.large_cursor = false; + dceip.dmif_request_buffer_size = bw_int_to_fixed(768); + dceip.dmif_pipe_en_fbc_chunk_tracker = false; + dceip.cursor_max_outstanding_group_num = 1; + dceip.lines_interleaved_into_lb = 2; + dceip.chunk_width = 256; + dceip.number_of_graphics_pipes = 6; + dceip.number_of_underlay_pipes = 0; + dceip.low_power_tiling_mode = 0; + dceip.display_write_back_supported = false; + dceip.argb_compression_support = true; + dceip.underlay_vscaler_efficiency6_bit_per_component = + bw_frc_to_fixed(35556, 10000); + dceip.underlay_vscaler_efficiency8_bit_per_component = + bw_frc_to_fixed(34286, 10000); + dceip.underlay_vscaler_efficiency10_bit_per_component = + bw_frc_to_fixed(32, 10); + dceip.underlay_vscaler_efficiency12_bit_per_component = + bw_int_to_fixed(3); + dceip.graphics_vscaler_efficiency6_bit_per_component = + bw_frc_to_fixed(35, 10); + dceip.graphics_vscaler_efficiency8_bit_per_component = + bw_frc_to_fixed(34286, 10000); + dceip.graphics_vscaler_efficiency10_bit_per_component = + bw_frc_to_fixed(32, 10); + dceip.graphics_vscaler_efficiency12_bit_per_component = + bw_int_to_fixed(3); + dceip.alpha_vscaler_efficiency = bw_int_to_fixed(3); + dceip.max_dmif_buffer_allocated = 4; + dceip.graphics_dmif_size = 12288; + dceip.underlay_luma_dmif_size = 19456; + dceip.underlay_chroma_dmif_size = 23552; + dceip.pre_downscaler_enabled = true; + dceip.underlay_downscale_prefetch_enabled = true; + dceip.lb_write_pixels_per_dispclk = bw_int_to_fixed(1); + dceip.lb_size_per_component444 = bw_int_to_fixed(245952); + dceip.graphics_lb_nodownscaling_multi_line_prefetching = true; + dceip.stutter_and_dram_clock_state_change_gated_before_cursor = + bw_int_to_fixed(1); + dceip.underlay420_luma_lb_size_per_component = bw_int_to_fixed( + 82176); + dceip.underlay420_chroma_lb_size_per_component = + bw_int_to_fixed(164352); + dceip.underlay422_lb_size_per_component = bw_int_to_fixed( + 82176); + dceip.cursor_chunk_width = bw_int_to_fixed(64); + dceip.cursor_dcp_buffer_lines = bw_int_to_fixed(4); + dceip.underlay_maximum_width_efficient_for_tiling = + bw_int_to_fixed(1920); + dceip.underlay_maximum_height_efficient_for_tiling = + bw_int_to_fixed(1080); + dceip.peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display = + bw_frc_to_fixed(3, 10); + dceip.peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation = + bw_int_to_fixed(25); + dceip.minimum_outstanding_pte_request_limit = bw_int_to_fixed( + 2); + dceip.maximum_total_outstanding_pte_requests_allowed_by_saw = + bw_int_to_fixed(128); + dceip.limit_excessive_outstanding_dmif_requests = true; + dceip.linear_mode_line_request_alternation_slice = + bw_int_to_fixed(64); + dceip.scatter_gather_lines_of_pte_prefetching_in_linear_mode = + 32; + dceip.display_write_back420_luma_mcifwr_buffer_size = 12288; + dceip.display_write_back420_chroma_mcifwr_buffer_size = 8192; + dceip.request_efficiency = bw_frc_to_fixed(8, 10); + dceip.dispclk_per_request = bw_int_to_fixed(2); + dceip.dispclk_ramping_factor = bw_frc_to_fixed(105, 100); + dceip.display_pipe_throughput_factor = bw_frc_to_fixed(105, 100); + dceip.scatter_gather_pte_request_rows_in_tiling_mode = 2; + dceip.mcifwr_all_surfaces_burst_time = bw_int_to_fixed(0); + break; + case BW_CALCS_VERSION_POLARIS11: + vbios.memory_type = bw_def_gddr5; + vbios.dram_channel_width_in_bits = 32; + vbios.number_of_dram_channels = asic_id.vram_width / vbios.dram_channel_width_in_bits; + vbios.number_of_dram_banks = 8; + vbios.high_yclk = bw_int_to_fixed(6000); + vbios.mid_yclk = bw_int_to_fixed(3200); + vbios.low_yclk = bw_int_to_fixed(1000); + vbios.low_sclk = bw_int_to_fixed(300); + vbios.mid1_sclk = bw_int_to_fixed(400); + vbios.mid2_sclk = bw_int_to_fixed(500); + vbios.mid3_sclk = bw_int_to_fixed(600); + vbios.mid4_sclk = bw_int_to_fixed(700); + vbios.mid5_sclk = bw_int_to_fixed(800); + vbios.mid6_sclk = bw_int_to_fixed(974); + vbios.high_sclk = bw_int_to_fixed(1154); + vbios.low_voltage_max_dispclk = bw_int_to_fixed(459); + vbios.mid_voltage_max_dispclk = bw_int_to_fixed(654); + vbios.high_voltage_max_dispclk = bw_int_to_fixed(1108); + vbios.low_voltage_max_phyclk = bw_int_to_fixed(540); + vbios.mid_voltage_max_phyclk = bw_int_to_fixed(810); + vbios.high_voltage_max_phyclk = bw_int_to_fixed(810); + vbios.data_return_bus_width = bw_int_to_fixed(32); + vbios.trc = bw_int_to_fixed(48); + if (vbios.number_of_dram_channels == 2) // 64-bit + vbios.dmifmc_urgent_latency = bw_int_to_fixed(4); + else + vbios.dmifmc_urgent_latency = bw_int_to_fixed(3); + vbios.stutter_self_refresh_exit_latency = bw_int_to_fixed(5); + vbios.stutter_self_refresh_entry_latency = bw_int_to_fixed(0); + vbios.nbp_state_change_latency = bw_int_to_fixed(45); + vbios.mcifwrmc_urgent_latency = bw_int_to_fixed(10); + vbios.scatter_gather_enable = true; + vbios.down_spread_percentage = bw_frc_to_fixed(5, 10); + vbios.cursor_width = 32; + vbios.average_compression_rate = 4; + vbios.number_of_request_slots_gmc_reserves_for_dmif_per_channel = 256; + vbios.blackout_duration = bw_int_to_fixed(0); /* us */ + vbios.maximum_blackout_recovery_time = bw_int_to_fixed(0); + + dceip.large_cursor = false; + dceip.dmif_request_buffer_size = bw_int_to_fixed(768); + dceip.dmif_pipe_en_fbc_chunk_tracker = false; + dceip.cursor_max_outstanding_group_num = 1; + dceip.lines_interleaved_into_lb = 2; + dceip.chunk_width = 256; + dceip.number_of_graphics_pipes = 5; + dceip.number_of_underlay_pipes = 0; + dceip.low_power_tiling_mode = 0; + dceip.display_write_back_supported = false; + dceip.argb_compression_support = true; + dceip.underlay_vscaler_efficiency6_bit_per_component = + bw_frc_to_fixed(35556, 10000); + dceip.underlay_vscaler_efficiency8_bit_per_component = + bw_frc_to_fixed(34286, 10000); + dceip.underlay_vscaler_efficiency10_bit_per_component = + bw_frc_to_fixed(32, 10); + dceip.underlay_vscaler_efficiency12_bit_per_component = + bw_int_to_fixed(3); + dceip.graphics_vscaler_efficiency6_bit_per_component = + bw_frc_to_fixed(35, 10); + dceip.graphics_vscaler_efficiency8_bit_per_component = + bw_frc_to_fixed(34286, 10000); + dceip.graphics_vscaler_efficiency10_bit_per_component = + bw_frc_to_fixed(32, 10); + dceip.graphics_vscaler_efficiency12_bit_per_component = + bw_int_to_fixed(3); + dceip.alpha_vscaler_efficiency = bw_int_to_fixed(3); + dceip.max_dmif_buffer_allocated = 4; + dceip.graphics_dmif_size = 12288; + dceip.underlay_luma_dmif_size = 19456; + dceip.underlay_chroma_dmif_size = 23552; + dceip.pre_downscaler_enabled = true; + dceip.underlay_downscale_prefetch_enabled = true; + dceip.lb_write_pixels_per_dispclk = bw_int_to_fixed(1); + dceip.lb_size_per_component444 = bw_int_to_fixed(245952); + dceip.graphics_lb_nodownscaling_multi_line_prefetching = true; + dceip.stutter_and_dram_clock_state_change_gated_before_cursor = + bw_int_to_fixed(1); + dceip.underlay420_luma_lb_size_per_component = bw_int_to_fixed( + 82176); + dceip.underlay420_chroma_lb_size_per_component = + bw_int_to_fixed(164352); + dceip.underlay422_lb_size_per_component = bw_int_to_fixed( + 82176); + dceip.cursor_chunk_width = bw_int_to_fixed(64); + dceip.cursor_dcp_buffer_lines = bw_int_to_fixed(4); + dceip.underlay_maximum_width_efficient_for_tiling = + bw_int_to_fixed(1920); + dceip.underlay_maximum_height_efficient_for_tiling = + bw_int_to_fixed(1080); + dceip.peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display = + bw_frc_to_fixed(3, 10); + dceip.peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation = + bw_int_to_fixed(25); + dceip.minimum_outstanding_pte_request_limit = bw_int_to_fixed( + 2); + dceip.maximum_total_outstanding_pte_requests_allowed_by_saw = + bw_int_to_fixed(128); + dceip.limit_excessive_outstanding_dmif_requests = true; + dceip.linear_mode_line_request_alternation_slice = + bw_int_to_fixed(64); + dceip.scatter_gather_lines_of_pte_prefetching_in_linear_mode = + 32; + dceip.display_write_back420_luma_mcifwr_buffer_size = 12288; + dceip.display_write_back420_chroma_mcifwr_buffer_size = 8192; + dceip.request_efficiency = bw_frc_to_fixed(8, 10); + dceip.dispclk_per_request = bw_int_to_fixed(2); + dceip.dispclk_ramping_factor = bw_frc_to_fixed(105, 100); + dceip.display_pipe_throughput_factor = bw_frc_to_fixed(105, 100); + dceip.scatter_gather_pte_request_rows_in_tiling_mode = 2; + dceip.mcifwr_all_surfaces_burst_time = bw_int_to_fixed(0); + break; + case BW_CALCS_VERSION_STONEY: + vbios.memory_type = bw_def_gddr5; + vbios.dram_channel_width_in_bits = 64; + vbios.number_of_dram_channels = asic_id.vram_width / vbios.dram_channel_width_in_bits; + vbios.number_of_dram_banks = 8; + vbios.high_yclk = bw_int_to_fixed(1866); + vbios.mid_yclk = bw_int_to_fixed(1866); + vbios.low_yclk = bw_int_to_fixed(1333); + vbios.low_sclk = bw_int_to_fixed(200); + vbios.mid1_sclk = bw_int_to_fixed(600); + vbios.mid2_sclk = bw_int_to_fixed(600); + vbios.mid3_sclk = bw_int_to_fixed(600); + vbios.mid4_sclk = bw_int_to_fixed(600); + vbios.mid5_sclk = bw_int_to_fixed(600); + vbios.mid6_sclk = bw_int_to_fixed(600); + vbios.high_sclk = bw_int_to_fixed(800); + vbios.low_voltage_max_dispclk = bw_int_to_fixed(352); + vbios.mid_voltage_max_dispclk = bw_int_to_fixed(467); + vbios.high_voltage_max_dispclk = bw_int_to_fixed(643); + vbios.low_voltage_max_phyclk = bw_int_to_fixed(540); + vbios.mid_voltage_max_phyclk = bw_int_to_fixed(810); + vbios.high_voltage_max_phyclk = bw_int_to_fixed(810); + vbios.data_return_bus_width = bw_int_to_fixed(32); + vbios.trc = bw_int_to_fixed(50); + vbios.dmifmc_urgent_latency = bw_int_to_fixed(4); + vbios.stutter_self_refresh_exit_latency = bw_frc_to_fixed(158, 10); + vbios.stutter_self_refresh_entry_latency = bw_int_to_fixed(0); + vbios.nbp_state_change_latency = bw_frc_to_fixed(2008, 100); + vbios.mcifwrmc_urgent_latency = bw_int_to_fixed(10); + vbios.scatter_gather_enable = true; + vbios.down_spread_percentage = bw_frc_to_fixed(5, 10); + vbios.cursor_width = 32; + vbios.average_compression_rate = 4; + vbios.number_of_request_slots_gmc_reserves_for_dmif_per_channel = 256; + vbios.blackout_duration = bw_int_to_fixed(18); /* us */ + vbios.maximum_blackout_recovery_time = bw_int_to_fixed(20); + + dceip.large_cursor = false; + dceip.dmif_request_buffer_size = bw_int_to_fixed(768); + dceip.dmif_pipe_en_fbc_chunk_tracker = false; + dceip.cursor_max_outstanding_group_num = 1; + dceip.lines_interleaved_into_lb = 2; + dceip.chunk_width = 256; + dceip.number_of_graphics_pipes = 2; + dceip.number_of_underlay_pipes = 1; + dceip.low_power_tiling_mode = 0; + dceip.display_write_back_supported = false; + dceip.argb_compression_support = true; + dceip.underlay_vscaler_efficiency6_bit_per_component = + bw_frc_to_fixed(35556, 10000); + dceip.underlay_vscaler_efficiency8_bit_per_component = + bw_frc_to_fixed(34286, 10000); + dceip.underlay_vscaler_efficiency10_bit_per_component = + bw_frc_to_fixed(32, 10); + dceip.underlay_vscaler_efficiency12_bit_per_component = + bw_int_to_fixed(3); + dceip.graphics_vscaler_efficiency6_bit_per_component = + bw_frc_to_fixed(35, 10); + dceip.graphics_vscaler_efficiency8_bit_per_component = + bw_frc_to_fixed(34286, 10000); + dceip.graphics_vscaler_efficiency10_bit_per_component = + bw_frc_to_fixed(32, 10); + dceip.graphics_vscaler_efficiency12_bit_per_component = + bw_int_to_fixed(3); + dceip.alpha_vscaler_efficiency = bw_int_to_fixed(3); + dceip.max_dmif_buffer_allocated = 2; + dceip.graphics_dmif_size = 12288; + dceip.underlay_luma_dmif_size = 19456; + dceip.underlay_chroma_dmif_size = 23552; + dceip.pre_downscaler_enabled = true; + dceip.underlay_downscale_prefetch_enabled = true; + dceip.lb_write_pixels_per_dispclk = bw_int_to_fixed(1); + dceip.lb_size_per_component444 = bw_int_to_fixed(82176); + dceip.graphics_lb_nodownscaling_multi_line_prefetching = false; + dceip.stutter_and_dram_clock_state_change_gated_before_cursor = + bw_int_to_fixed(0); + dceip.underlay420_luma_lb_size_per_component = bw_int_to_fixed( + 82176); + dceip.underlay420_chroma_lb_size_per_component = + bw_int_to_fixed(164352); + dceip.underlay422_lb_size_per_component = bw_int_to_fixed( + 82176); + dceip.cursor_chunk_width = bw_int_to_fixed(64); + dceip.cursor_dcp_buffer_lines = bw_int_to_fixed(4); + dceip.underlay_maximum_width_efficient_for_tiling = + bw_int_to_fixed(1920); + dceip.underlay_maximum_height_efficient_for_tiling = + bw_int_to_fixed(1080); + dceip.peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display = + bw_frc_to_fixed(3, 10); + dceip.peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation = + bw_int_to_fixed(25); + dceip.minimum_outstanding_pte_request_limit = bw_int_to_fixed( + 2); + dceip.maximum_total_outstanding_pte_requests_allowed_by_saw = + bw_int_to_fixed(128); + dceip.limit_excessive_outstanding_dmif_requests = true; + dceip.linear_mode_line_request_alternation_slice = + bw_int_to_fixed(64); + dceip.scatter_gather_lines_of_pte_prefetching_in_linear_mode = + 32; + dceip.display_write_back420_luma_mcifwr_buffer_size = 12288; + dceip.display_write_back420_chroma_mcifwr_buffer_size = 8192; + dceip.request_efficiency = bw_frc_to_fixed(8, 10); + dceip.dispclk_per_request = bw_int_to_fixed(2); + dceip.dispclk_ramping_factor = bw_frc_to_fixed(105, 100); + dceip.display_pipe_throughput_factor = bw_frc_to_fixed(105, 100); + dceip.scatter_gather_pte_request_rows_in_tiling_mode = 2; + dceip.mcifwr_all_surfaces_burst_time = bw_int_to_fixed(0); + break; + default: + break; + } + *bw_dceip = dceip; + *bw_vbios = vbios; + +} + +/** + * Compare calculated (required) clocks against the clocks available at + * maximum voltage (max Performance Level). + */ +static bool is_display_configuration_supported( + const struct bw_calcs_vbios *vbios, + const struct bw_calcs_output *calcs_output) +{ + uint32_t int_max_clk; + + int_max_clk = bw_fixed_to_int(vbios->high_voltage_max_dispclk); + int_max_clk *= 1000; /* MHz to kHz */ + if (calcs_output->dispclk_khz > int_max_clk) + return false; + + int_max_clk = bw_fixed_to_int(vbios->high_sclk); + int_max_clk *= 1000; /* MHz to kHz */ + if (calcs_output->required_sclk > int_max_clk) + return false; + + return true; +} + +static void populate_initial_data( + const struct pipe_ctx pipe[], int pipe_count, struct bw_calcs_data *data) +{ + int i, j; + int num_displays = 0; + + data->underlay_surface_type = bw_def_420; + data->panning_and_bezel_adjustment = bw_def_none; + data->graphics_lb_bpc = 10; + data->underlay_lb_bpc = 8; + data->underlay_tiling_mode = bw_def_tiled; + data->graphics_tiling_mode = bw_def_tiled; + data->underlay_micro_tile_mode = bw_def_display_micro_tiling; + data->graphics_micro_tile_mode = bw_def_display_micro_tiling; + + /* Pipes with underlay first */ + for (i = 0; i < pipe_count; i++) { + if (!pipe[i].stream || !pipe[i].bottom_pipe) + continue; + + ASSERT(pipe[i].surface); + + if (num_displays == 0) { + if (!pipe[i].surface->public.visible) + data->d0_underlay_mode = bw_def_underlay_only; + else + data->d0_underlay_mode = bw_def_blend; + } else { + if (!pipe[i].surface->public.visible) + data->d1_underlay_mode = bw_def_underlay_only; + else + data->d1_underlay_mode = bw_def_blend; + } + + data->fbc_en[num_displays + 4] = false; + data->lpt_en[num_displays + 4] = false; + data->h_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->public.timing.h_total); + data->v_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->public.timing.v_total); + data->pixel_rate[num_displays + 4] = bw_frc_to_fixed(pipe[i].stream->public.timing.pix_clk_khz, 1000); + data->src_width[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.viewport.width); + data->pitch_in_pixels[num_displays + 4] = bw_int_to_fixed(pipe[i].surface->public.plane_size.grph.surface_pitch); + data->src_height[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.viewport.height); + data->h_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.taps.h_taps); + data->v_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.taps.v_taps); + data->h_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].scl_data.ratios.horz.value); + data->v_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].scl_data.ratios.vert.value); + switch (pipe[i].surface->public.rotation) { + case ROTATION_ANGLE_0: + data->rotation_angle[num_displays + 4] = bw_int_to_fixed(0); + break; + case ROTATION_ANGLE_90: + data->rotation_angle[num_displays + 4] = bw_int_to_fixed(90); + break; + case ROTATION_ANGLE_180: + data->rotation_angle[num_displays + 4] = bw_int_to_fixed(180); + break; + case ROTATION_ANGLE_270: + data->rotation_angle[num_displays + 4] = bw_int_to_fixed(270); + break; + default: + break; + } + switch (pipe[i].surface->public.format) { + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: + case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: + case SURFACE_PIXEL_FORMAT_GRPH_RGB565: + data->bytes_per_pixel[num_displays + 4] = 2; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: + case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: + data->bytes_per_pixel[num_displays + 4] = 4; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: + data->bytes_per_pixel[num_displays + 4] = 8; + break; + default: + data->bytes_per_pixel[num_displays + 4] = 4; + break; + } + data->interlace_mode[num_displays + 4] = false; + data->stereo_mode[num_displays + 4] = bw_def_mono; + + + for (j = 0; j < 2; j++) { + data->fbc_en[num_displays * 2 + j] = false; + data->lpt_en[num_displays * 2 + j] = false; + + data->src_height[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->scl_data.viewport.height); + data->src_width[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->scl_data.viewport.width); + data->pitch_in_pixels[num_displays * 2 + j] = bw_int_to_fixed( + pipe[i].bottom_pipe->surface->public.plane_size.grph.surface_pitch); + data->h_taps[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->scl_data.taps.h_taps); + data->v_taps[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->scl_data.taps.v_taps); + data->h_scale_ratio[num_displays * 2 + j] = fixed31_32_to_bw_fixed( + pipe[i].bottom_pipe->scl_data.ratios.horz.value); + data->v_scale_ratio[num_displays * 2 + j] = fixed31_32_to_bw_fixed( + pipe[i].bottom_pipe->scl_data.ratios.vert.value); + switch (pipe[i].bottom_pipe->surface->public.rotation) { + case ROTATION_ANGLE_0: + data->rotation_angle[num_displays * 2 + j] = bw_int_to_fixed(0); + break; + case ROTATION_ANGLE_90: + data->rotation_angle[num_displays * 2 + j] = bw_int_to_fixed(90); + break; + case ROTATION_ANGLE_180: + data->rotation_angle[num_displays * 2 + j] = bw_int_to_fixed(180); + break; + case ROTATION_ANGLE_270: + data->rotation_angle[num_displays * 2 + j] = bw_int_to_fixed(270); + break; + default: + break; + } + data->stereo_mode[num_displays * 2 + j] = bw_def_mono; + } + + num_displays++; + } + + /* Pipes without underlay after */ + for (i = 0; i < pipe_count; i++) { + if (!pipe[i].stream || pipe[i].bottom_pipe) + continue; + + + data->fbc_en[num_displays + 4] = false; + data->lpt_en[num_displays + 4] = false; + data->h_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->public.timing.h_total); + data->v_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->public.timing.v_total); + data->pixel_rate[num_displays + 4] = bw_frc_to_fixed(pipe[i].stream->public.timing.pix_clk_khz, 1000); + if (pipe[i].surface) { + data->src_width[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.viewport.width); + data->pitch_in_pixels[num_displays + 4] = bw_int_to_fixed(pipe[i].surface->public.plane_size.grph.surface_pitch); + data->src_height[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.viewport.height); + data->h_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.taps.h_taps); + data->v_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.taps.v_taps); + data->h_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].scl_data.ratios.horz.value); + data->v_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].scl_data.ratios.vert.value); + switch (pipe[i].surface->public.rotation) { + case ROTATION_ANGLE_0: + data->rotation_angle[num_displays + 4] = bw_int_to_fixed(0); + break; + case ROTATION_ANGLE_90: + data->rotation_angle[num_displays + 4] = bw_int_to_fixed(90); + break; + case ROTATION_ANGLE_180: + data->rotation_angle[num_displays + 4] = bw_int_to_fixed(180); + break; + case ROTATION_ANGLE_270: + data->rotation_angle[num_displays + 4] = bw_int_to_fixed(270); + break; + default: + break; + } + switch (pipe[i].surface->public.format) { + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: + case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: + case SURFACE_PIXEL_FORMAT_GRPH_RGB565: + data->bytes_per_pixel[num_displays + 4] = 2; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: + case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: + data->bytes_per_pixel[num_displays + 4] = 4; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: + data->bytes_per_pixel[num_displays + 4] = 8; + break; + default: + data->bytes_per_pixel[num_displays + 4] = 4; + break; + } + } else { + data->src_width[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->public.timing.h_addressable); + data->pitch_in_pixels[num_displays + 4] = data->src_width[num_displays + 4]; + data->src_height[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->public.timing.v_addressable); + data->h_taps[num_displays + 4] = bw_int_to_fixed(1); + data->v_taps[num_displays + 4] = bw_int_to_fixed(1); + data->h_scale_ratio[num_displays + 4] = bw_int_to_fixed(1); + data->v_scale_ratio[num_displays + 4] = bw_int_to_fixed(1); + data->rotation_angle[num_displays + 4] = bw_int_to_fixed(0); + data->bytes_per_pixel[num_displays + 4] = 4; + } + + data->interlace_mode[num_displays + 4] = false; + data->stereo_mode[num_displays + 4] = bw_def_mono; + num_displays++; + } + + data->number_of_displays = num_displays; +} + +/** + * Return: + * true - Display(s) configuration supported. + * In this case 'calcs_output' contains data for HW programming + * false - Display(s) configuration not supported (not enough bandwidth). + */ + +bool bw_calcs(struct dc_context *ctx, + const struct bw_calcs_dceip *dceip, + const struct bw_calcs_vbios *vbios, + const struct pipe_ctx pipe[], + int pipe_count, + struct bw_calcs_output *calcs_output) +{ + struct bw_calcs_data *data = dm_alloc(sizeof(struct bw_calcs_data)); + + populate_initial_data(pipe, pipe_count, data); + + /*TODO: this should be taken out calcs output and assigned during timing sync for pplib use*/ + calcs_output->all_displays_in_sync = false; + + if (data->number_of_displays != 0) { + uint8_t yclk_lvl, sclk_lvl; + struct bw_fixed high_sclk = vbios->high_sclk; + struct bw_fixed mid1_sclk = vbios->mid1_sclk; + struct bw_fixed mid2_sclk = vbios->mid2_sclk; + struct bw_fixed mid3_sclk = vbios->mid3_sclk; + struct bw_fixed mid4_sclk = vbios->mid4_sclk; + struct bw_fixed mid5_sclk = vbios->mid5_sclk; + struct bw_fixed mid6_sclk = vbios->mid6_sclk; + struct bw_fixed low_sclk = vbios->low_sclk; + struct bw_fixed high_yclk = vbios->high_yclk; + struct bw_fixed mid_yclk = vbios->mid_yclk; + struct bw_fixed low_yclk = vbios->low_yclk; + + calculate_bandwidth(dceip, vbios, data); + + yclk_lvl = data->y_clk_level; + sclk_lvl = data->sclk_level; + + calcs_output->nbp_state_change_enable = + data->nbp_state_change_enable; + calcs_output->cpuc_state_change_enable = + data->cpuc_state_change_enable; + calcs_output->cpup_state_change_enable = + data->cpup_state_change_enable; + calcs_output->stutter_mode_enable = + data->stutter_mode_enable; + calcs_output->dispclk_khz = + bw_fixed_to_int(bw_mul(data->dispclk, + bw_int_to_fixed(1000))); + calcs_output->blackout_recovery_time_us = + bw_fixed_to_int(data->blackout_recovery_time); + calcs_output->required_sclk = + bw_fixed_to_int(bw_mul(data->required_sclk, + bw_int_to_fixed(1000))); + calcs_output->required_sclk_deep_sleep = + bw_fixed_to_int(bw_mul(data->sclk_deep_sleep, + bw_int_to_fixed(1000))); + if (yclk_lvl == 0) + calcs_output->required_yclk = bw_fixed_to_int( + bw_mul(low_yclk, bw_int_to_fixed(1000))); + else if (yclk_lvl == 1) + calcs_output->required_yclk = bw_fixed_to_int( + bw_mul(mid_yclk, bw_int_to_fixed(1000))); + else + calcs_output->required_yclk = bw_fixed_to_int( + bw_mul(high_yclk, bw_int_to_fixed(1000))); + + /* units: nanosecond, 16bit storage. */ + + calcs_output->nbp_state_change_wm_ns[0].a_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[4], bw_int_to_fixed(1000))); + calcs_output->nbp_state_change_wm_ns[1].a_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[5], bw_int_to_fixed(1000))); + calcs_output->nbp_state_change_wm_ns[2].a_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[6], bw_int_to_fixed(1000))); + + if (ctx->dc->caps.max_slave_planes) { + calcs_output->nbp_state_change_wm_ns[3].a_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[0], bw_int_to_fixed(1000))); + calcs_output->nbp_state_change_wm_ns[4].a_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[1], bw_int_to_fixed(1000))); + } else { + calcs_output->nbp_state_change_wm_ns[3].a_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[7], bw_int_to_fixed(1000))); + calcs_output->nbp_state_change_wm_ns[4].a_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[8], bw_int_to_fixed(1000))); + } + calcs_output->nbp_state_change_wm_ns[5].a_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[9], bw_int_to_fixed(1000))); + + + + calcs_output->stutter_exit_wm_ns[0].a_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[4], bw_int_to_fixed(1000))); + calcs_output->stutter_exit_wm_ns[1].a_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[5], bw_int_to_fixed(1000))); + calcs_output->stutter_exit_wm_ns[2].a_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[6], bw_int_to_fixed(1000))); + if (ctx->dc->caps.max_slave_planes) { + calcs_output->stutter_exit_wm_ns[3].a_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[0], bw_int_to_fixed(1000))); + calcs_output->stutter_exit_wm_ns[4].a_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[1], bw_int_to_fixed(1000))); + } else { + calcs_output->stutter_exit_wm_ns[3].a_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[7], bw_int_to_fixed(1000))); + calcs_output->stutter_exit_wm_ns[4].a_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[8], bw_int_to_fixed(1000))); + } + calcs_output->stutter_exit_wm_ns[5].a_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[9], bw_int_to_fixed(1000))); + + + + calcs_output->urgent_wm_ns[0].a_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[4], bw_int_to_fixed(1000))); + calcs_output->urgent_wm_ns[1].a_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[5], bw_int_to_fixed(1000))); + calcs_output->urgent_wm_ns[2].a_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[6], bw_int_to_fixed(1000))); + if (ctx->dc->caps.max_slave_planes) { + calcs_output->urgent_wm_ns[3].a_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[0], bw_int_to_fixed(1000))); + calcs_output->urgent_wm_ns[4].a_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[1], bw_int_to_fixed(1000))); + } else { + calcs_output->urgent_wm_ns[3].a_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[7], bw_int_to_fixed(1000))); + calcs_output->urgent_wm_ns[4].a_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[8], bw_int_to_fixed(1000))); + } + calcs_output->urgent_wm_ns[5].a_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[9], bw_int_to_fixed(1000))); + + if (dceip->version != BW_CALCS_VERSION_CARRIZO) { + ((struct bw_calcs_vbios *)vbios)->low_sclk = mid3_sclk; + ((struct bw_calcs_vbios *)vbios)->mid1_sclk = mid3_sclk; + ((struct bw_calcs_vbios *)vbios)->mid2_sclk = mid3_sclk; + calculate_bandwidth(dceip, vbios, data); + + calcs_output->nbp_state_change_wm_ns[0].b_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[4],bw_int_to_fixed(1000))); + calcs_output->nbp_state_change_wm_ns[1].b_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[5], bw_int_to_fixed(1000))); + calcs_output->nbp_state_change_wm_ns[2].b_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[6], bw_int_to_fixed(1000))); + + if (ctx->dc->caps.max_slave_planes) { + calcs_output->nbp_state_change_wm_ns[3].b_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[0], bw_int_to_fixed(1000))); + calcs_output->nbp_state_change_wm_ns[4].b_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[1], bw_int_to_fixed(1000))); + } else { + calcs_output->nbp_state_change_wm_ns[3].b_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[7], bw_int_to_fixed(1000))); + calcs_output->nbp_state_change_wm_ns[4].b_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[8], bw_int_to_fixed(1000))); + } + calcs_output->nbp_state_change_wm_ns[5].b_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[9], bw_int_to_fixed(1000))); + + + + calcs_output->stutter_exit_wm_ns[0].b_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[4], bw_int_to_fixed(1000))); + calcs_output->stutter_exit_wm_ns[1].b_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[5], bw_int_to_fixed(1000))); + calcs_output->stutter_exit_wm_ns[2].b_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[6], bw_int_to_fixed(1000))); + if (ctx->dc->caps.max_slave_planes) { + calcs_output->stutter_exit_wm_ns[3].b_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[0], bw_int_to_fixed(1000))); + calcs_output->stutter_exit_wm_ns[4].b_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[1], bw_int_to_fixed(1000))); + } else { + calcs_output->stutter_exit_wm_ns[3].b_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[7], bw_int_to_fixed(1000))); + calcs_output->stutter_exit_wm_ns[4].b_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[8], bw_int_to_fixed(1000))); + } + calcs_output->stutter_exit_wm_ns[5].b_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[9], bw_int_to_fixed(1000))); + + + + calcs_output->urgent_wm_ns[0].b_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[4], bw_int_to_fixed(1000))); + calcs_output->urgent_wm_ns[1].b_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[5], bw_int_to_fixed(1000))); + calcs_output->urgent_wm_ns[2].b_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[6], bw_int_to_fixed(1000))); + if (ctx->dc->caps.max_slave_planes) { + calcs_output->urgent_wm_ns[3].b_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[0], bw_int_to_fixed(1000))); + calcs_output->urgent_wm_ns[4].b_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[1], bw_int_to_fixed(1000))); + } else { + calcs_output->urgent_wm_ns[3].b_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[7], bw_int_to_fixed(1000))); + calcs_output->urgent_wm_ns[4].b_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[8], bw_int_to_fixed(1000))); + } + calcs_output->urgent_wm_ns[5].b_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[9], bw_int_to_fixed(1000))); + + ((struct bw_calcs_vbios *)vbios)->low_sclk = low_sclk; + ((struct bw_calcs_vbios *)vbios)->mid1_sclk = mid1_sclk; + ((struct bw_calcs_vbios *)vbios)->mid2_sclk = mid2_sclk; + ((struct bw_calcs_vbios *)vbios)->low_yclk = mid_yclk; + calculate_bandwidth(dceip, vbios, data); + + calcs_output->nbp_state_change_wm_ns[0].c_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[4], bw_int_to_fixed(1000))); + calcs_output->nbp_state_change_wm_ns[1].c_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[5], bw_int_to_fixed(1000))); + calcs_output->nbp_state_change_wm_ns[2].c_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[6], bw_int_to_fixed(1000))); + if (ctx->dc->caps.max_slave_planes) { + calcs_output->nbp_state_change_wm_ns[3].c_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[0], bw_int_to_fixed(1000))); + calcs_output->nbp_state_change_wm_ns[4].c_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[1], bw_int_to_fixed(1000))); + } else { + calcs_output->nbp_state_change_wm_ns[3].c_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[7], bw_int_to_fixed(1000))); + calcs_output->nbp_state_change_wm_ns[4].c_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[8], bw_int_to_fixed(1000))); + } + calcs_output->nbp_state_change_wm_ns[5].c_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[9], bw_int_to_fixed(1000))); + + + calcs_output->stutter_exit_wm_ns[0].c_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[4], bw_int_to_fixed(1000))); + calcs_output->stutter_exit_wm_ns[1].c_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[5], bw_int_to_fixed(1000))); + calcs_output->stutter_exit_wm_ns[2].c_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[6], bw_int_to_fixed(1000))); + if (ctx->dc->caps.max_slave_planes) { + calcs_output->stutter_exit_wm_ns[3].c_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[0], bw_int_to_fixed(1000))); + calcs_output->stutter_exit_wm_ns[4].c_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[1], bw_int_to_fixed(1000))); + } else { + calcs_output->stutter_exit_wm_ns[3].c_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[7], bw_int_to_fixed(1000))); + calcs_output->stutter_exit_wm_ns[4].c_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[8], bw_int_to_fixed(1000))); + } + calcs_output->stutter_exit_wm_ns[5].c_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[9], bw_int_to_fixed(1000))); + + calcs_output->urgent_wm_ns[0].c_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[4], bw_int_to_fixed(1000))); + calcs_output->urgent_wm_ns[1].c_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[5], bw_int_to_fixed(1000))); + calcs_output->urgent_wm_ns[2].c_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[6], bw_int_to_fixed(1000))); + if (ctx->dc->caps.max_slave_planes) { + calcs_output->urgent_wm_ns[3].c_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[0], bw_int_to_fixed(1000))); + calcs_output->urgent_wm_ns[4].c_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[1], bw_int_to_fixed(1000))); + } else { + calcs_output->urgent_wm_ns[3].c_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[7], bw_int_to_fixed(1000))); + calcs_output->urgent_wm_ns[4].c_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[8], bw_int_to_fixed(1000))); + } + calcs_output->urgent_wm_ns[5].c_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[9], bw_int_to_fixed(1000))); + } + + if (dceip->version == BW_CALCS_VERSION_CARRIZO) { + ((struct bw_calcs_vbios *)vbios)->low_yclk = high_yclk; + ((struct bw_calcs_vbios *)vbios)->mid_yclk = high_yclk; + ((struct bw_calcs_vbios *)vbios)->low_sclk = high_sclk; + ((struct bw_calcs_vbios *)vbios)->mid1_sclk = high_sclk; + ((struct bw_calcs_vbios *)vbios)->mid2_sclk = high_sclk; + ((struct bw_calcs_vbios *)vbios)->mid3_sclk = high_sclk; + ((struct bw_calcs_vbios *)vbios)->mid4_sclk = high_sclk; + ((struct bw_calcs_vbios *)vbios)->mid5_sclk = high_sclk; + ((struct bw_calcs_vbios *)vbios)->mid6_sclk = high_sclk; + } else { + ((struct bw_calcs_vbios *)vbios)->low_yclk = mid_yclk; + ((struct bw_calcs_vbios *)vbios)->low_sclk = mid3_sclk; + ((struct bw_calcs_vbios *)vbios)->mid1_sclk = mid3_sclk; + ((struct bw_calcs_vbios *)vbios)->mid2_sclk = mid3_sclk; + } + + calculate_bandwidth(dceip, vbios, data); + + calcs_output->nbp_state_change_wm_ns[0].d_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[4], bw_int_to_fixed(1000))); + calcs_output->nbp_state_change_wm_ns[1].d_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[5], bw_int_to_fixed(1000))); + calcs_output->nbp_state_change_wm_ns[2].d_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[6], bw_int_to_fixed(1000))); + if (ctx->dc->caps.max_slave_planes) { + calcs_output->nbp_state_change_wm_ns[3].d_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[0], bw_int_to_fixed(1000))); + calcs_output->nbp_state_change_wm_ns[4].d_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[1], bw_int_to_fixed(1000))); + } else { + calcs_output->nbp_state_change_wm_ns[3].d_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[7], bw_int_to_fixed(1000))); + calcs_output->nbp_state_change_wm_ns[4].d_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[8], bw_int_to_fixed(1000))); + } + calcs_output->nbp_state_change_wm_ns[5].d_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[9], bw_int_to_fixed(1000))); + + calcs_output->stutter_exit_wm_ns[0].d_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[4], bw_int_to_fixed(1000))); + calcs_output->stutter_exit_wm_ns[1].d_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[5], bw_int_to_fixed(1000))); + calcs_output->stutter_exit_wm_ns[2].d_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[6], bw_int_to_fixed(1000))); + if (ctx->dc->caps.max_slave_planes) { + calcs_output->stutter_exit_wm_ns[3].d_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[0], bw_int_to_fixed(1000))); + calcs_output->stutter_exit_wm_ns[4].d_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[1], bw_int_to_fixed(1000))); + } else { + calcs_output->stutter_exit_wm_ns[3].d_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[7], bw_int_to_fixed(1000))); + calcs_output->stutter_exit_wm_ns[4].d_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[8], bw_int_to_fixed(1000))); + } + calcs_output->stutter_exit_wm_ns[5].d_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[9], bw_int_to_fixed(1000))); + + + calcs_output->urgent_wm_ns[0].d_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[4], bw_int_to_fixed(1000))); + calcs_output->urgent_wm_ns[1].d_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[5], bw_int_to_fixed(1000))); + calcs_output->urgent_wm_ns[2].d_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[6], bw_int_to_fixed(1000))); + if (ctx->dc->caps.max_slave_planes) { + calcs_output->urgent_wm_ns[3].d_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[0], bw_int_to_fixed(1000))); + calcs_output->urgent_wm_ns[4].d_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[1], bw_int_to_fixed(1000))); + } else { + calcs_output->urgent_wm_ns[3].d_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[7], bw_int_to_fixed(1000))); + calcs_output->urgent_wm_ns[4].d_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[8], bw_int_to_fixed(1000))); + } + calcs_output->urgent_wm_ns[5].d_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[9], bw_int_to_fixed(1000))); + + ((struct bw_calcs_vbios *)vbios)->low_yclk = low_yclk; + ((struct bw_calcs_vbios *)vbios)->mid_yclk = mid_yclk; + ((struct bw_calcs_vbios *)vbios)->low_sclk = low_sclk; + ((struct bw_calcs_vbios *)vbios)->mid1_sclk = mid1_sclk; + ((struct bw_calcs_vbios *)vbios)->mid2_sclk = mid2_sclk; + ((struct bw_calcs_vbios *)vbios)->mid3_sclk = mid3_sclk; + ((struct bw_calcs_vbios *)vbios)->mid4_sclk = mid4_sclk; + ((struct bw_calcs_vbios *)vbios)->mid5_sclk = mid5_sclk; + ((struct bw_calcs_vbios *)vbios)->mid6_sclk = mid6_sclk; + ((struct bw_calcs_vbios *)vbios)->high_sclk = high_sclk; + } else { + calcs_output->nbp_state_change_enable = true; + calcs_output->cpuc_state_change_enable = true; + calcs_output->cpup_state_change_enable = true; + calcs_output->stutter_mode_enable = true; + calcs_output->dispclk_khz = 0; + calcs_output->required_sclk = 0; + } + + dm_free(data); + + return is_display_configuration_supported(vbios, calcs_output); +} -- cgit From 4b679bc3cab09f2af44bd34dfc197939a4602aa8 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Wed, 22 Feb 2017 13:46:29 -0500 Subject: drm/amd/display: HDMI deep color mode audio issue Signed-off-by: Charlene Liu Acked-by: Harry Wentland Reviewed-by: Charlene Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 9 ++++++-- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 11 +++++---- drivers/gpu/drm/amd/display/dc/dce/dce_audio.c | 9 ++++++++ .../gpu/drm/amd/display/dc/dce/dce_clock_source.c | 1 - .../drm/amd/display/dc/dce/dce_stream_encoder.c | 26 +++++----------------- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 18 --------------- 6 files changed, 28 insertions(+), 46 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 4d556b379524..407ce60f253e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1101,9 +1101,14 @@ enum dc_status resource_map_pool_resources( for (i = 0; i < context->stream_count; i++) { struct core_stream *stream = context->streams[i]; - if (!resource_is_stream_unchanged(dc->current_context, stream)) + if (!resource_is_stream_unchanged(dc->current_context, stream)) { + if (stream != NULL && dc->current_context->streams[i] != NULL) { + stream->bit_depth_params = + dc->current_context->streams[i]->bit_depth_params; + stream->clamping = dc->current_context->streams[i]->clamping; continue; - + } + } /* mark resources used for stream that is already active */ for (j = 0; j < MAX_PIPES; j++) { struct pipe_ctx *pipe_ctx = diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index e1f579bcd789..4e1a933be021 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -305,7 +305,7 @@ void dc_stream_log( dm_logger_write(dm_logger, log_type, - "core_stream 0x%x: src: %d, %d, %d, %d; dst: %d, %d, %d, %d;\n", + "core_stream 0x%x: src: %d, %d, %d, %d; dst: %d, %d, %d, %d, colorSpace:%d\n", core_stream, core_stream->public.src.x, core_stream->public.src.y, @@ -314,13 +314,16 @@ void dc_stream_log( core_stream->public.dst.x, core_stream->public.dst.y, core_stream->public.dst.width, - core_stream->public.dst.height); + core_stream->public.dst.height, + core_stream->public.output_color_space); dm_logger_write(dm_logger, log_type, - "\tpix_clk_khz: %d, h_total: %d, v_total: %d\n", + "\tpix_clk_khz: %d, h_total: %d, v_total: %d, pixelencoder:%d, displaycolorDepth:%d\n", core_stream->public.timing.pix_clk_khz, core_stream->public.timing.h_total, - core_stream->public.timing.v_total); + core_stream->public.timing.v_total, + core_stream->public.timing.pixel_encoding, + core_stream->public.timing.display_color_depth); dm_logger_write(dm_logger, log_type, "\tsink name: %s, serial: %d\n", diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c index 596e039ee315..7f52e39ec92a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c @@ -773,6 +773,15 @@ void dce_aud_wall_dto_setup( crtc_info->calculated_pixel_clock, &clock_info); + dm_logger_write(audio->ctx->logger, LOG_HW_SET_MODE,\ + "\n************************%s:Input::requested_pixel_clock = %d"\ + "calculated_pixel_clock =%d\n"\ + "audio_dto_module = %d audio_dto_phase =%d \n\n", __func__,\ + crtc_info->requested_pixel_clock,\ + crtc_info->calculated_pixel_clock,\ + clock_info.audio_dto_module,\ + clock_info.audio_dto_phase); + /* On TN/SI, Program DTO source select and DTO select before programming DTO modulo and DTO phase. These bits must be programmed first, otherwise there will be no HDMI audio at boot diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index 26742e038274..a2a2ecf8d077 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -874,7 +874,6 @@ static bool dce110_program_pix_clk( bp_pc_params.flags.SET_XTALIN_REF_SRC = !pll_settings->use_external_clk; if (pix_clk_params->flags.SUPPORT_YCBCR420) { - bp_pc_params.target_pixel_clock = pll_settings->actual_pix_clk / 2; bp_pc_params.flags.SUPPORT_YUV_420 = 1; } } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c index e4092fd458a1..d6662fa2f4e1 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c @@ -873,22 +873,6 @@ static const struct audio_clock_info audio_clock_info_table[16] = { {59400, 3072, 445500, 9408, 990000, 6144, 594000} }; -static const struct audio_clock_info audio_clock_info_table_30bpc[14] = { - {2517, 9152, 70312, 14014, 78125, 9152, 46875}, - {2518, 9152, 70312, 14014, 78125, 9152, 46875}, - {2520, 4096, 31500, 6272, 35000, 6144, 31500}, - {2700, 4096, 33750, 6272, 37500, 6144, 33750}, - {2702, 8192, 67567, 12544, 75075, 8192, 45045}, - {2703, 8192, 67567, 12544, 75075, 8192, 45045}, - {5400, 4096, 67500, 6272, 75000, 6144, 67500}, - {5405, 8192, 135135, 6272, 75075, 8192, 90090}, - {7417, 11648, 263672, 17836, 292969, 11648, 175181}, - {7425, 8192, 185625, 6272, 103125, 12288, 185625}, - {14835, 11648, 527344, 17836, 585938, 11648, 351563}, - {14850, 4096, 185625, 6272, 206250, 6144, 185625}, - {29670, 11648, 527344, 17836, 585938, 11648, 703125}, - {29700, 6144, 556875, 4704, 309375, 5120, 309375} -}; static const struct audio_clock_info audio_clock_info_table_36bpc[14] = { {2517, 9152, 84375, 7007, 48875, 9152, 56250}, {2518, 9152, 84375, 7007, 48875, 9152, 56250}, @@ -1005,11 +989,6 @@ bool get_audio_clock_info( audio_array_size = ARRAY_SIZE( audio_clock_info_table_36bpc); break; - case COLOR_DEPTH_101010: - clock_info = audio_clock_info_table_30bpc; - audio_array_size = ARRAY_SIZE( - audio_clock_info_table_30bpc); - break; default: clock_info = audio_clock_info_table; audio_array_size = ARRAY_SIZE( @@ -1114,6 +1093,11 @@ static void dce110_se_setup_hdmi_audio( crtc_info->requested_pixel_clock, crtc_info->calculated_pixel_clock, &audio_clock_info)) { + dm_logger_write(enc->ctx->logger, LOG_HW_SET_MODE, + "\n*********************%s:Input::requested_pixel_clock = %d"\ + "calculated_pixel_clock = %d \n", __func__,\ + crtc_info->requested_pixel_clock,\ + crtc_info->calculated_pixel_clock); /* HDMI_ACR_32_0__HDMI_ACR_CTS_32_MASK */ REG_UPDATE(HDMI_ACR_32_0, HDMI_ACR_CTS_32, audio_clock_info.cts_32khz); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 6915cc46754b..2f68bf20dfe2 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -873,25 +873,7 @@ static void build_audio_output( audio_output->crtc_info.requested_pixel_clock/2; audio_output->crtc_info.calculated_pixel_clock = pipe_ctx->pix_clk_params.requested_pix_clk/2; - } - if (pipe_ctx->pix_clk_params.pixel_encoding != PIXEL_ENCODING_YCBCR422) { - switch (pipe_ctx->pix_clk_params.color_depth) { - case COLOR_DEPTH_888: - break; - case COLOR_DEPTH_101010: - audio_output->crtc_info.calculated_pixel_clock = (audio_output->crtc_info.calculated_pixel_clock * 30) / 24; - break; - case COLOR_DEPTH_121212: - audio_output->crtc_info.calculated_pixel_clock = (audio_output->crtc_info.calculated_pixel_clock * 36) / 24; - break; - case COLOR_DEPTH_161616: - audio_output->crtc_info.calculated_pixel_clock = (audio_output->crtc_info.calculated_pixel_clock * 48) / 24; - break; - default: - ASSERT(0); - break; - } } } -- cgit From d5b4f2bcff03c6cafb0a890360f1f8fbc99071a1 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Wed, 22 Feb 2017 18:26:20 -0500 Subject: drm/amd/display: 420 clock divided by 2 twice Signed-off-by: Charlene Liu Acked-by: Harry Wentland Reviewed-by: Krunoslav Kovac Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 478c8d27f3bd..cd3942df70a7 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -780,6 +780,9 @@ static void get_pixel_clock_parameters( if (stream->public.timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) { pixel_clk_params->color_depth = COLOR_DEPTH_888; } + if (stream->public.timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) { + pixel_clk_params->requested_pix_clk = pixel_clk_params->requested_pix_clk / 2; + } } void dce110_resource_build_bit_depth_reduction_params( -- cgit From 3548f0731a2fa823bcb31b5ea662603926b85c43 Mon Sep 17 00:00:00 2001 From: Amy Zhang Date: Fri, 17 Feb 2017 11:56:03 -0500 Subject: drm/amd/display: DMCU PSR Refactor - Move PSR programming from link encoder to dmcu Signed-off-by: Amy Zhang Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 21 +- drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c | 208 +++++++++++++++ drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h | 107 +++++++- .../gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 280 +++------------------ .../gpu/drm/amd/display/dc/dce/dce_link_encoder.h | 73 +----- drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h | 4 + .../gpu/drm/amd/display/dc/inc/hw/link_encoder.h | 9 +- 7 files changed, 376 insertions(+), 326 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 2b929393f68a..8eb6b342a49d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -40,6 +40,7 @@ #include "abm.h" #include "fixed31_32.h" #include "dpcd_defs.h" +#include "dmcu.h" #include "dce/dce_11_0_d.h" #include "dce/dce_11_0_enum.h" @@ -1433,28 +1434,33 @@ bool dc_link_set_backlight_level(const struct dc_link *dc_link, uint32_t level, bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable) { struct core_link *link = DC_LINK_TO_CORE(dc_link); + struct dc_context *ctx = link->ctx; + struct core_dc *core_dc = DC_TO_CORE(ctx->dc); + struct dmcu *dmcu = core_dc->res_pool->dmcu; + + if (dmcu != NULL && dc_link->psr_caps.psr_version > 0) + dmcu->funcs->set_psr_enable(dmcu, enable); - if (dc_link != NULL && dc_link->psr_caps.psr_version > 0) - link->link_enc->funcs->set_dmcu_psr_enable(link->link_enc, - enable); return true; } bool dc_link_setup_psr(const struct dc_link *dc_link, const struct dc_stream *stream) { - struct core_link *link = DC_LINK_TO_CORE(dc_link); struct dc_context *ctx = link->ctx; struct core_dc *core_dc = DC_TO_CORE(ctx->dc); + struct dmcu *dmcu = core_dc->res_pool->dmcu; struct core_stream *core_stream = DC_STREAM_TO_CORE(stream); - struct psr_dmcu_context psr_context = {0}; + struct psr_context psr_context = {0}; int i; psr_context.controllerId = CONTROLLER_ID_UNDEFINED; - if (dc_link != NULL && dc_link->psr_caps.psr_version > 0) { + if (dc_link != NULL && + dmcu != NULL && + dc_link->psr_caps.psr_version > 0) { /* updateSinkPsrDpcdConfig*/ union dpcd_psr_configuration psr_configuration; @@ -1552,8 +1558,7 @@ bool dc_link_setup_psr(const struct dc_link *dc_link, */ psr_context.frame_delay = 0; - link->link_enc->funcs->setup_dmcu_psr - (link->link_enc, &psr_context); + dmcu->funcs->setup_psr(dmcu, link, &psr_context); return true; } else return false; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c index eb0e95f57aa9..44eeeeb888fe 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c @@ -23,6 +23,8 @@ * */ +#include "core_types.h" +#include "link_encoder.h" #include "dce_dmcu.h" #include "dm_services.h" #include "reg_helper.h" @@ -42,6 +44,12 @@ #define CTX \ dmcu_dce->base.ctx +/* PSR related commands */ +#define PSR_ENABLE 0x20 +#define PSR_EXIT 0x21 +#define PSR_SET 0x23 +#define MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK 0x00000001L + bool dce_dmcu_load_iram(struct dmcu *dmcu, unsigned int start_offset, const char *src, @@ -76,8 +84,208 @@ bool dce_dmcu_load_iram(struct dmcu *dmcu, return true; } +static void dce_get_dmcu_psr_state(struct dmcu *dmcu, uint32_t *psr_state) +{ + struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); + + uint32_t count = 0; + uint32_t psrStateOffset = 0xf0; + uint32_t value = -1; + + /* Enable write access to IRAM */ + REG_UPDATE(DMCU_RAM_ACCESS_CTRL, IRAM_HOST_ACCESS_EN, 1); + + while (REG(DCI_MEM_PWR_STATUS) && value != 0 && count++ < 10) { + dm_delay_in_microseconds(dmcu->ctx, 2); + REG_GET(DCI_MEM_PWR_STATUS, DMCU_IRAM_MEM_PWR_STATE, &value); + } + while (REG(DMU_MEM_PWR_CNTL) && value != 0 && count++ < 10) { + dm_delay_in_microseconds(dmcu->ctx, 2); + REG_GET(DMU_MEM_PWR_CNTL, DMCU_IRAM_MEM_PWR_STATE, &value); + } + + /* Write address to IRAM_RD_ADDR in DMCU_IRAM_RD_CTRL */ + REG_WRITE(DMCU_IRAM_RD_CTRL, psrStateOffset); + + /* Read data from IRAM_RD_DATA in DMCU_IRAM_RD_DATA*/ + *psr_state = REG_READ(DMCU_IRAM_RD_DATA); + + /* Disable write access to IRAM after finished using IRAM + * in order to allow dynamic sleep state + */ + REG_UPDATE(DMCU_RAM_ACCESS_CTRL, IRAM_HOST_ACCESS_EN, 0); +} + +static void dce_dmcu_set_psr_enable(struct dmcu *dmcu, bool enable) +{ + struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); + unsigned int dmcu_max_retry_on_wait_reg_ready = 801; + unsigned int dmcu_wait_reg_ready_interval = 100; + + unsigned int regValue; + + unsigned int retryCount; + uint32_t psr_state = 0; + + /* waitDMCUReadyForCmd */ + do { + dm_delay_in_microseconds(dmcu->ctx, + dmcu_wait_reg_ready_interval); + regValue = REG_READ(MASTER_COMM_CNTL_REG); + dmcu_max_retry_on_wait_reg_ready--; + } while + /* expected value is 0, loop while not 0*/ + ((MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK & regValue) && + dmcu_max_retry_on_wait_reg_ready > 0); + + /* setDMCUParam_Cmd */ + if (enable) + REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, + PSR_ENABLE); + else + REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, + PSR_EXIT); + + /* notifyDMCUMsg */ + REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); + + for (retryCount = 0; retryCount <= 100; retryCount++) { + dce_get_dmcu_psr_state(dmcu, &psr_state); + if (enable) { + if (psr_state != 0) + break; + } else { + if (psr_state == 0) + break; + } + dm_delay_in_microseconds(dmcu->ctx, 10); + } +} + +static void dce_dmcu_setup_psr(struct dmcu *dmcu, + struct core_link *link, + struct psr_context *psr_context) +{ + struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); + + unsigned int dmcu_max_retry_on_wait_reg_ready = 801; + unsigned int dmcu_wait_reg_ready_interval = 100; + unsigned int regValue; + + union dce_dmcu_psr_config_data_reg1 masterCmdData1; + union dce_dmcu_psr_config_data_reg2 masterCmdData2; + union dce_dmcu_psr_config_data_reg3 masterCmdData3; + + link->link_enc->funcs->psr_program_dp_dphy_fast_training(link->link_enc, + psr_context->psrExitLinkTrainingRequired); + + /* Enable static screen interrupts for PSR supported display */ + /* Disable the interrupt coming from other displays. */ + REG_UPDATE_4(DMCU_INTERRUPT_TO_UC_EN_MASK, + STATIC_SCREEN1_INT_TO_UC_EN, 0, + STATIC_SCREEN2_INT_TO_UC_EN, 0, + STATIC_SCREEN3_INT_TO_UC_EN, 0, + STATIC_SCREEN4_INT_TO_UC_EN, 0); + + switch (psr_context->controllerId) { + /* Driver uses case 1 for unconfigured */ + case 1: + REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK, + STATIC_SCREEN1_INT_TO_UC_EN, 1); + break; + case 2: + REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK, + STATIC_SCREEN2_INT_TO_UC_EN, 1); + break; + case 3: + REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK, + STATIC_SCREEN3_INT_TO_UC_EN, 1); + break; + case 4: + REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK, + STATIC_SCREEN4_INT_TO_UC_EN, 1); + break; + case 5: + /* CZ/NL only has 4 CRTC!! + * really valid. + * There is no interrupt enable mask for these instances. + */ + break; + case 6: + /* CZ/NL only has 4 CRTC!! + * These are here because they are defined in HW regspec, + * but not really valid. There is no interrupt enable mask + * for these instances. + */ + break; + default: + REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK, + STATIC_SCREEN1_INT_TO_UC_EN, 1); + break; + } + + link->link_enc->funcs->psr_program_secondary_packet(link->link_enc, + psr_context->sdpTransmitLineNumDeadline); + + if (psr_context->psr_level.bits.SKIP_SMU_NOTIFICATION) + REG_UPDATE(SMU_INTERRUPT_CONTROL, DC_SMU_INT_ENABLE, 1); + + /* waitDMCUReadyForCmd */ + do { + dm_delay_in_microseconds(dmcu->ctx, + dmcu_wait_reg_ready_interval); + regValue = REG_READ(MASTER_COMM_CNTL_REG); + dmcu_max_retry_on_wait_reg_ready--; + } while + /* expected value is 0, loop while not 0*/ + ((MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK & regValue) && + dmcu_max_retry_on_wait_reg_ready > 0); + + /* setDMCUParam_PSRHostConfigData */ + masterCmdData1.u32All = 0; + masterCmdData1.bits.timehyst_frames = psr_context->timehyst_frames; + masterCmdData1.bits.hyst_lines = psr_context->hyst_lines; + masterCmdData1.bits.rfb_update_auto_en = + psr_context->rfb_update_auto_en; + masterCmdData1.bits.dp_port_num = psr_context->transmitterId; + masterCmdData1.bits.dcp_sel = psr_context->controllerId; + masterCmdData1.bits.phy_type = psr_context->phyType; + masterCmdData1.bits.frame_cap_ind = + psr_context->psrFrameCaptureIndicationReq; + masterCmdData1.bits.aux_chan = psr_context->channel; + masterCmdData1.bits.aux_repeat = psr_context->aux_repeats; + dm_write_reg(dmcu->ctx, REG(MASTER_COMM_DATA_REG1), + masterCmdData1.u32All); + + masterCmdData2.u32All = 0; + masterCmdData2.bits.dig_fe = psr_context->engineId; + masterCmdData2.bits.dig_be = psr_context->transmitterId; + masterCmdData2.bits.skip_wait_for_pll_lock = + psr_context->skipPsrWaitForPllLock; + masterCmdData2.bits.frame_delay = psr_context->frame_delay; + masterCmdData2.bits.smu_phy_id = psr_context->smuPhyId; + masterCmdData2.bits.num_of_controllers = + psr_context->numberOfControllers; + dm_write_reg(dmcu->ctx, REG(MASTER_COMM_DATA_REG2), + masterCmdData2.u32All); + + masterCmdData3.u32All = 0; + masterCmdData3.bits.psr_level = psr_context->psr_level.u32all; + dm_write_reg(dmcu->ctx, REG(MASTER_COMM_DATA_REG3), + masterCmdData3.u32All); + + /* setDMCUParam_Cmd */ + REG_UPDATE(MASTER_COMM_CMD_REG, + MASTER_COMM_CMD_REG_BYTE0, PSR_SET); + + /* notifyDMCUMsg */ + REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); +} + static const struct dmcu_funcs dce_funcs = { .load_iram = dce_dmcu_load_iram, + .set_psr_enable = dce_dmcu_set_psr_enable, + .setup_psr = dce_dmcu_setup_psr, }; static void dce_dmcu_construct( diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h index 33c1754f04f1..7dc25386c2bf 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h @@ -33,7 +33,16 @@ SR(DMCU_CTRL), \ SR(DMCU_RAM_ACCESS_CTRL), \ SR(DMCU_IRAM_WR_CTRL), \ - SR(DMCU_IRAM_WR_DATA) + SR(DMCU_IRAM_WR_DATA), \ + SR(MASTER_COMM_DATA_REG1), \ + SR(MASTER_COMM_DATA_REG2), \ + SR(MASTER_COMM_DATA_REG3), \ + SR(MASTER_COMM_CMD_REG), \ + SR(MASTER_COMM_CNTL_REG), \ + SR(DMCU_IRAM_RD_CTRL), \ + SR(DMCU_IRAM_RD_DATA), \ + SR(DMCU_INTERRUPT_TO_UC_EN_MASK), \ + SR(SMU_INTERRUPT_CONTROL) #define DMCU_DCE110_COMMON_REG_LIST() \ DMCU_COMMON_REG_LIST_DCE_BASE(), \ @@ -48,18 +57,41 @@ DMCU_SF(DMCU_RAM_ACCESS_CTRL, \ IRAM_HOST_ACCESS_EN, mask_sh), \ DMCU_SF(DMCU_RAM_ACCESS_CTRL, \ - IRAM_WR_ADDR_AUTO_INC, mask_sh) + IRAM_WR_ADDR_AUTO_INC, mask_sh), \ + DMCU_SF(MASTER_COMM_CMD_REG, \ + MASTER_COMM_CMD_REG_BYTE0, mask_sh), \ + DMCU_SF(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, mask_sh), \ + DMCU_SF(DMCU_INTERRUPT_TO_UC_EN_MASK, \ + STATIC_SCREEN1_INT_TO_UC_EN, mask_sh), \ + DMCU_SF(DMCU_INTERRUPT_TO_UC_EN_MASK, \ + STATIC_SCREEN2_INT_TO_UC_EN, mask_sh), \ + DMCU_SF(DMCU_INTERRUPT_TO_UC_EN_MASK, \ + STATIC_SCREEN3_INT_TO_UC_EN, mask_sh), \ + DMCU_SF(DMCU_INTERRUPT_TO_UC_EN_MASK, \ + STATIC_SCREEN4_INT_TO_UC_EN, mask_sh), \ + DMCU_SF(SMU_INTERRUPT_CONTROL, DC_SMU_INT_ENABLE, mask_sh) #define DMCU_MASK_SH_LIST_DCE110(mask_sh) \ DMCU_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh), \ DMCU_SF(DCI_MEM_PWR_STATUS, \ - DMCU_IRAM_MEM_PWR_STATE, mask_sh) + DMCU_IRAM_MEM_PWR_STATE, mask_sh) #define DMCU_REG_FIELD_LIST(type) \ type DMCU_IRAM_MEM_PWR_STATE; \ type IRAM_HOST_ACCESS_EN; \ type IRAM_WR_ADDR_AUTO_INC; \ - type DMCU_ENABLE + type DMCU_ENABLE; \ + type MASTER_COMM_CMD_REG_BYTE0; \ + type MASTER_COMM_INTERRUPT; \ + type DPHY_RX_FAST_TRAINING_CAPABLE; \ + type DPHY_LOAD_BS_COUNT; \ + type STATIC_SCREEN1_INT_TO_UC_EN; \ + type STATIC_SCREEN2_INT_TO_UC_EN; \ + type STATIC_SCREEN3_INT_TO_UC_EN; \ + type STATIC_SCREEN4_INT_TO_UC_EN; \ + type DP_SEC_GSP0_LINE_NUM; \ + type DP_SEC_GSP0_PRIORITY; \ + type DC_SMU_INT_ENABLE struct dce_dmcu_shift { DMCU_REG_FIELD_LIST(uint8_t); @@ -76,6 +108,16 @@ struct dce_dmcu_registers { uint32_t DMU_MEM_PWR_CNTL; uint32_t DMCU_IRAM_WR_CTRL; uint32_t DMCU_IRAM_WR_DATA; + + uint32_t MASTER_COMM_DATA_REG1; + uint32_t MASTER_COMM_DATA_REG2; + uint32_t MASTER_COMM_DATA_REG3; + uint32_t MASTER_COMM_CMD_REG; + uint32_t MASTER_COMM_CNTL_REG; + uint32_t DMCU_IRAM_RD_CTRL; + uint32_t DMCU_IRAM_RD_DATA; + uint32_t DMCU_INTERRUPT_TO_UC_EN_MASK; + uint32_t SMU_INTERRUPT_CONTROL; }; struct dce_dmcu { @@ -85,6 +127,63 @@ struct dce_dmcu { const struct dce_dmcu_mask *dmcu_mask; }; +/******************************************************************* + * MASTER_COMM_DATA_REG1 Bit position Data + * 7:0 hyst_frames[7:0] + * 14:8 hyst_lines[6:0] + * 15 RFB_UPDATE_AUTO_EN + * 18:16 phy_num[2:0] + * 21:19 dcp_sel[2:0] + * 22 phy_type + * 23 frame_cap_ind + * 26:24 aux_chan[2:0] + * 30:27 aux_repeat[3:0] + * 31:31 reserved[31:31] + ******************************************************************/ +union dce_dmcu_psr_config_data_reg1 { + struct { + unsigned int timehyst_frames:8; /*[7:0]*/ + unsigned int hyst_lines:7; /*[14:8]*/ + unsigned int rfb_update_auto_en:1; /*[15:15]*/ + unsigned int dp_port_num:3; /*[18:16]*/ + unsigned int dcp_sel:3; /*[21:19]*/ + unsigned int phy_type:1; /*[22:22]*/ + unsigned int frame_cap_ind:1; /*[23:23]*/ + unsigned int aux_chan:3; /*[26:24]*/ + unsigned int aux_repeat:4; /*[30:27]*/ + unsigned int reserved:1; /*[31:31]*/ + } bits; + unsigned int u32All; +}; + +/******************************************************************* + * MASTER_COMM_DATA_REG2 + *******************************************************************/ +union dce_dmcu_psr_config_data_reg2 { + struct { + unsigned int dig_fe:3; /*[2:0]*/ + unsigned int dig_be:3; /*[5:3]*/ + unsigned int skip_wait_for_pll_lock:1; /*[6:6]*/ + unsigned int reserved:9; /*[15:7]*/ + unsigned int frame_delay:8; /*[23:16]*/ + unsigned int smu_phy_id:4; /*[27:24]*/ + unsigned int num_of_controllers:4; /*[31:28]*/ + } bits; + unsigned int u32All; +}; + +/******************************************************************* + * MASTER_COMM_DATA_REG3 + *******************************************************************/ +union dce_dmcu_psr_config_data_reg3 { + struct { + unsigned int psr_level:16; /*[15:0]*/ + unsigned int link_rate:4; /*[19:16]*/ + unsigned int reserved:12; /*[31:20]*/ + } bits; + unsigned int u32All; +}; + struct dmcu *dce_dmcu_create( struct dc_context *ctx, const struct dce_dmcu_registers *regs, diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 305a9d86a5d2..a1d35ad85605 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -95,14 +95,6 @@ /* For current ASICs pixel clock - 600MHz */ #define MAX_ENCODER_CLOCK 600000 -/* PSR related commands */ -#define PSR_ENABLE 0x20 -#define PSR_EXIT 0x21 -#define PSR_SET 0x23 - -/*TODO: Used for psr wakeup for set backlight level*/ -static unsigned int psr_crtc_offset; - enum { DP_MST_UPDATE_MAX_RETRY = 50 }; @@ -126,8 +118,9 @@ static const struct link_encoder_funcs dce110_lnk_enc_funcs = { .dp_set_phy_pattern = dce110_link_encoder_dp_set_phy_pattern, .update_mst_stream_allocation_table = dce110_link_encoder_update_mst_stream_allocation_table, - .set_dmcu_psr_enable = dce110_link_encoder_set_dmcu_psr_enable, - .setup_dmcu_psr = dce110_link_encoder_setup_dmcu_psr, + .psr_program_dp_dphy_fast_training = + dce110_psr_program_dp_dphy_fast_training, + .psr_program_secondary_packet = dce110_psr_program_secondary_packet, .backlight_control = dce110_link_encoder_edp_backlight_control, .power_control = dce110_link_encoder_edp_power_control, .connect_dig_be_to_fe = dce110_link_encoder_connect_dig_be_to_fe, @@ -136,7 +129,6 @@ static const struct link_encoder_funcs dce110_lnk_enc_funcs = { .destroy = dce110_link_encoder_destroy }; - static enum bp_result link_transmitter_control( struct dce110_link_encoder *enc110, struct bp_transmitter_control *cntl) @@ -721,6 +713,40 @@ static bool is_panel_backlight_on(struct dce110_link_encoder *enc110) return value; } +void dce110_psr_program_dp_dphy_fast_training(struct link_encoder *enc, + bool exit_link_training_required) +{ + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + + if (exit_link_training_required) + REG_UPDATE(DP_DPHY_FAST_TRAINING, + DPHY_RX_FAST_TRAINING_CAPABLE, 1); + else { + REG_UPDATE(DP_DPHY_FAST_TRAINING, + DPHY_RX_FAST_TRAINING_CAPABLE, 0); + /*In DCE 11, we are able to pre-program a Force SR register + * to be able to trigger SR symbol after 5 idle patterns + * transmitted. Upon PSR Exit, DMCU can trigger + * DPHY_LOAD_BS_COUNT_START = 1. Upon writing 1 to + * DPHY_LOAD_BS_COUNT_START and the internal counter + * reaches DPHY_LOAD_BS_COUNT, the next BS symbol will be + * replaced by SR symbol once. + */ + + REG_UPDATE(DP_DPHY_BS_SR_SWAP_CNTL, DPHY_LOAD_BS_COUNT, 0x5); + } +} + +void dce110_psr_program_secondary_packet(struct link_encoder *enc, + unsigned int sdp_transmit_line_num_deadline) +{ + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + + REG_UPDATE_2(DP_SEC_CNTL1, + DP_SEC_GSP0_LINE_NUM, sdp_transmit_line_num_deadline, + DP_SEC_GSP0_PRIORITY, 1); +} + /*todo: cloned in stream enc, fix*/ /* * @brief @@ -1560,238 +1586,6 @@ void dce110_link_encoder_update_mst_stream_allocation_table( } while (retries < DP_MST_UPDATE_MAX_RETRY); } -static void get_dmcu_psr_state(struct link_encoder *enc, uint32_t *psr_state) -{ - struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); - struct dc_context *ctx = enc110->base.ctx; - - uint32_t count = 0; - uint32_t psrStateOffset = 0xf0; - uint32_t value = -1; - - /* Enable write access to IRAM */ - REG_UPDATE(DMCU_RAM_ACCESS_CTRL, IRAM_HOST_ACCESS_EN, 1); - - while (REG(DCI_MEM_PWR_STATUS) && value != 0 && count++ < 10) { - dm_delay_in_microseconds(ctx, 2); - REG_GET(DCI_MEM_PWR_STATUS, DMCU_IRAM_MEM_PWR_STATE, &value); - } - while (REG(DMU_MEM_PWR_CNTL) && value != 0 && count++ < 10) { - dm_delay_in_microseconds(ctx, 2); - REG_GET(DMU_MEM_PWR_CNTL, DMCU_IRAM_MEM_PWR_STATE, &value); - } - - /* Write address to IRAM_RD_ADDR in DMCU_IRAM_RD_CTRL */ - REG_WRITE(DMCU_IRAM_RD_CTRL, psrStateOffset); - - /* Read data from IRAM_RD_DATA in DMCU_IRAM_RD_DATA*/ - *psr_state = REG_READ(DMCU_IRAM_RD_DATA); - - /* Disable write access to IRAM after finished using IRAM - * in order to allow dynamic sleep state - */ - REG_UPDATE(DMCU_RAM_ACCESS_CTRL, IRAM_HOST_ACCESS_EN, 0); -} - -void dce110_link_encoder_set_dmcu_psr_enable(struct link_encoder *enc, - bool enable) -{ - struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); - struct dc_context *ctx = enc110->base.ctx; - - unsigned int dmcu_max_retry_on_wait_reg_ready = 801; - unsigned int dmcu_wait_reg_ready_interval = 100; - - unsigned int regValue; - - unsigned int retryCount; - uint32_t psr_state = 0; - - /* waitDMCUReadyForCmd */ - do { - dm_delay_in_microseconds(ctx, dmcu_wait_reg_ready_interval); - regValue = REG_READ(MASTER_COMM_CNTL_REG); - dmcu_max_retry_on_wait_reg_ready--; - } while - /* expected value is 0, loop while not 0*/ - ((MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK & regValue) && - dmcu_max_retry_on_wait_reg_ready > 0); - - /* setDMCUParam_Cmd */ - if (enable) - REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, PSR_ENABLE); - else - REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, PSR_EXIT); - - /* notifyDMCUMsg */ - REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); - - for (retryCount = 0; retryCount <= 100; retryCount++) { - get_dmcu_psr_state(enc, &psr_state); - if (enable) { - if (psr_state != 0) - break; - } else { - if (psr_state == 0) - break; - } - dm_delay_in_microseconds(ctx, 10); - } -} - -void dce110_link_encoder_setup_dmcu_psr(struct link_encoder *enc, - struct psr_dmcu_context *psr_context) -{ - struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); - struct dc_context *ctx = enc110->base.ctx; - - unsigned int dmcu_max_retry_on_wait_reg_ready = 801; - unsigned int dmcu_wait_reg_ready_interval = 100; - unsigned int regValue; - - union dce110_dmcu_psr_config_data_reg1 masterCmdData1; - union dce110_dmcu_psr_config_data_reg2 masterCmdData2; - union dce110_dmcu_psr_config_data_reg3 masterCmdData3; - - if (psr_context->psrExitLinkTrainingRequired) - REG_UPDATE(DP_DPHY_FAST_TRAINING, DPHY_RX_FAST_TRAINING_CAPABLE, 1); - else { - REG_UPDATE(DP_DPHY_FAST_TRAINING, DPHY_RX_FAST_TRAINING_CAPABLE, 0); - /*In DCE 11, we are able to pre-program a Force SR register - * to be able to trigger SR symbol after 5 idle patterns - * transmitted. Upon PSR Exit, DMCU can trigger - * DPHY_LOAD_BS_COUNT_START = 1. Upon writing 1 to - * DPHY_LOAD_BS_COUNT_START and the internal counter - * reaches DPHY_LOAD_BS_COUNT, the next BS symbol will be - * replaced by SR symbol once. - */ - - REG_UPDATE(DP_DPHY_BS_SR_SWAP_CNTL, DPHY_LOAD_BS_COUNT, 0x5); - } - - /* Enable static screen interrupts for PSR supported display */ - /* Disable the interrupt coming from other displays. */ - REG_UPDATE_4(DMCU_INTERRUPT_TO_UC_EN_MASK, - STATIC_SCREEN1_INT_TO_UC_EN, 0, - STATIC_SCREEN2_INT_TO_UC_EN, 0, - STATIC_SCREEN3_INT_TO_UC_EN, 0, - STATIC_SCREEN4_INT_TO_UC_EN, 0); - - switch (psr_context->controllerId) { - /* Driver uses case 1 for unconfigured */ - case 1: - psr_crtc_offset = mmCRTC0_CRTC_STATIC_SCREEN_CONTROL - - mmCRTC0_CRTC_STATIC_SCREEN_CONTROL; - - REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK, - STATIC_SCREEN1_INT_TO_UC_EN, 1); - break; - case 2: - psr_crtc_offset = mmCRTC1_CRTC_STATIC_SCREEN_CONTROL - - mmCRTC0_CRTC_STATIC_SCREEN_CONTROL; - - REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK, - STATIC_SCREEN2_INT_TO_UC_EN, 1); - break; - case 3: - psr_crtc_offset = mmCRTC2_CRTC_STATIC_SCREEN_CONTROL - - mmCRTC0_CRTC_STATIC_SCREEN_CONTROL; - - REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK, - STATIC_SCREEN3_INT_TO_UC_EN, 1); - break; - case 4: - psr_crtc_offset = mmCRTC3_CRTC_STATIC_SCREEN_CONTROL - - mmCRTC0_CRTC_STATIC_SCREEN_CONTROL; - - REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK, - STATIC_SCREEN4_INT_TO_UC_EN, 1); - break; - case 5: - psr_crtc_offset = mmCRTC4_CRTC_STATIC_SCREEN_CONTROL - - mmCRTC0_CRTC_STATIC_SCREEN_CONTROL; - /* CZ/NL only has 4 CRTC!! - * really valid. - * There is no interrupt enable mask for these instances. - */ - break; - case 6: - psr_crtc_offset = mmCRTC5_CRTC_STATIC_SCREEN_CONTROL - - mmCRTC0_CRTC_STATIC_SCREEN_CONTROL; - /* CZ/NL only has 4 CRTC!! - * These are here because they are defined in HW regspec, - * but not really valid. There is no interrupt enable mask - * for these instances. - */ - break; - default: - psr_crtc_offset = mmCRTC0_CRTC_STATIC_SCREEN_CONTROL - - mmCRTC0_CRTC_STATIC_SCREEN_CONTROL; - - REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK, - STATIC_SCREEN1_INT_TO_UC_EN, 1); - break; - } - - REG_UPDATE_2(DP_SEC_CNTL1, - DP_SEC_GSP0_LINE_NUM, psr_context->sdpTransmitLineNumDeadline, - DP_SEC_GSP0_PRIORITY, 1); - - if (psr_context->psr_level.bits.SKIP_SMU_NOTIFICATION) { - REG_UPDATE(SMU_INTERRUPT_CONTROL, DC_SMU_INT_ENABLE, 1); - } - - /* waitDMCUReadyForCmd */ - do { - dm_delay_in_microseconds(ctx, dmcu_wait_reg_ready_interval); - regValue = REG_READ(MASTER_COMM_CNTL_REG); - dmcu_max_retry_on_wait_reg_ready--; - } while - /* expected value is 0, loop while not 0*/ - ((MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK & regValue) && - dmcu_max_retry_on_wait_reg_ready > 0); - - /* setDMCUParam_PSRHostConfigData */ - masterCmdData1.u32All = 0; - masterCmdData1.bits.timehyst_frames = psr_context->timehyst_frames; - masterCmdData1.bits.hyst_lines = psr_context->hyst_lines; - masterCmdData1.bits.rfb_update_auto_en = - psr_context->rfb_update_auto_en; - masterCmdData1.bits.dp_port_num = psr_context->transmitterId; - masterCmdData1.bits.dcp_sel = psr_context->controllerId; - masterCmdData1.bits.phy_type = psr_context->phyType; - masterCmdData1.bits.frame_cap_ind = - psr_context->psrFrameCaptureIndicationReq; - masterCmdData1.bits.aux_chan = psr_context->channel; - masterCmdData1.bits.aux_repeat = psr_context->aux_repeats; - dm_write_reg(ctx, REG(MASTER_COMM_DATA_REG1), - masterCmdData1.u32All); - - masterCmdData2.u32All = 0; - masterCmdData2.bits.dig_fe = psr_context->engineId; - masterCmdData2.bits.dig_be = psr_context->transmitterId; - masterCmdData2.bits.skip_wait_for_pll_lock = - psr_context->skipPsrWaitForPllLock; - masterCmdData2.bits.frame_delay = psr_context->frame_delay; - masterCmdData2.bits.smu_phy_id = psr_context->smuPhyId; - masterCmdData2.bits.num_of_controllers = - psr_context->numberOfControllers; - dm_write_reg(ctx, REG(MASTER_COMM_DATA_REG2), - masterCmdData2.u32All); - - masterCmdData3.u32All = 0; - masterCmdData3.bits.psr_level = psr_context->psr_level.u32all; - dm_write_reg(ctx, REG(MASTER_COMM_DATA_REG3), - masterCmdData3.u32All); - - /* setDMCUParam_Cmd */ - REG_UPDATE(MASTER_COMM_CMD_REG, - MASTER_COMM_CMD_REG_BYTE0, PSR_SET); - - /* notifyDMCUMsg */ - REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); -} - void dce110_link_encoder_connect_dig_be_to_fe( struct link_encoder *enc, enum engine_id engine, diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h index d382a6882d95..f337d607e36c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h @@ -39,11 +39,6 @@ SRI(DC_HPD_CONTROL, HPD, id) #define LE_COMMON_REG_LIST_BASE(id) \ - SR(MASTER_COMM_DATA_REG1), \ - SR(MASTER_COMM_DATA_REG2), \ - SR(MASTER_COMM_DATA_REG3), \ - SR(MASTER_COMM_CMD_REG), \ - SR(MASTER_COMM_CNTL_REG), \ SR(LVTMA_PWRSEQ_CNTL), \ SR(LVTMA_PWRSEQ_STATE), \ SR(DMCU_RAM_ACCESS_CTRL), \ @@ -149,62 +144,6 @@ struct dce110_link_encoder { const struct dce110_link_enc_hpd_registers *hpd_regs; }; -/******************************************************************* -* MASTER_COMM_DATA_REG1 Bit position Data -* 7:0 hyst_frames[7:0] -* 14:8 hyst_lines[6:0] -* 15 RFB_UPDATE_AUTO_EN -* 18:16 phy_num[2:0] -* 21:19 dcp_sel[2:0] -* 22 phy_type -* 23 frame_cap_ind -* 26:24 aux_chan[2:0] -* 30:27 aux_repeat[3:0] -* 31:31 reserved[31:31] -*******************************************************************/ -union dce110_dmcu_psr_config_data_reg1 { - struct { - unsigned int timehyst_frames:8; /*[7:0]*/ - unsigned int hyst_lines:7; /*[14:8]*/ - unsigned int rfb_update_auto_en:1; /*[15:15]*/ - unsigned int dp_port_num:3; /*[18:16]*/ - unsigned int dcp_sel:3; /*[21:19]*/ - unsigned int phy_type:1; /*[22:22]*/ - unsigned int frame_cap_ind:1; /*[23:23]*/ - unsigned int aux_chan:3; /*[26:24]*/ - unsigned int aux_repeat:4; /*[30:27]*/ - unsigned int reserved:1; /*[31:31]*/ - } bits; - unsigned int u32All; -}; - -/******************************************************************* -* MASTER_COMM_DATA_REG2 -*******************************************************************/ -union dce110_dmcu_psr_config_data_reg2 { - struct { - unsigned int dig_fe:3; /*[2:0]*/ - unsigned int dig_be:3; /*[5:3]*/ - unsigned int skip_wait_for_pll_lock:1; /*[6:6]*/ - unsigned int reserved:9; /*[15:7]*/ - unsigned int frame_delay:8; /*[23:16]*/ - unsigned int smu_phy_id:4; /*[27:24]*/ - unsigned int num_of_controllers:4; /*[31:28]*/ - } bits; - unsigned int u32All; -}; - -/******************************************************************* -* MASTER_COMM_DATA_REG3 -*******************************************************************/ -union dce110_dmcu_psr_config_data_reg3 { - struct { - unsigned int psr_level:16; /*[15:0]*/ - unsigned int link_rate:4; /*[19:16]*/ - unsigned int reserved:12; /*[31:20]*/ - } bits; - unsigned int u32All; -}; bool dce110_link_encoder_construct( struct dce110_link_encoder *enc110, @@ -290,12 +229,6 @@ void dce110_link_encoder_update_mst_stream_allocation_table( struct link_encoder *enc, const struct link_mst_stream_allocation_table *table); -void dce110_link_encoder_set_dmcu_psr_enable( - struct link_encoder *enc, bool enable); - -void dce110_link_encoder_setup_dmcu_psr(struct link_encoder *enc, - struct psr_dmcu_context *psr_context); - void dce110_link_encoder_edp_backlight_control( struct link_encoder *enc, bool enable); @@ -317,4 +250,10 @@ void dce110_link_encoder_enable_hpd(struct link_encoder *enc); void dce110_link_encoder_disable_hpd(struct link_encoder *enc); +void dce110_psr_program_dp_dphy_fast_training(struct link_encoder *enc, + bool exit_link_training_required); + +void dce110_psr_program_secondary_packet(struct link_encoder *enc, + unsigned int sdp_transmit_line_num_deadline); + #endif /* __DC_LINK_ENCODER__DCE110_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h index 62012f091836..656cfdc79891 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h @@ -37,6 +37,10 @@ struct dmcu_funcs { unsigned int start_offset, const char *src, unsigned int bytes); + void (*set_psr_enable)(struct dmcu *dmcu, bool enable); + void (*setup_psr)(struct dmcu *dmcu, + struct core_link *link, + struct psr_context *psr_context); }; #endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h index 7b37b963666e..7307f96c7679 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h @@ -116,7 +116,7 @@ union psr_sink_psr_status { unsigned char raw; }; -struct psr_dmcu_context { +struct psr_context { /* ddc line */ enum channel_id channel; /* Transmitter id */ @@ -220,9 +220,10 @@ struct link_encoder_funcs { void (*update_mst_stream_allocation_table)( struct link_encoder *enc, const struct link_mst_stream_allocation_table *table); - void (*set_dmcu_psr_enable)(struct link_encoder *enc, bool enable); - void (*setup_dmcu_psr)(struct link_encoder *enc, - struct psr_dmcu_context *psr_context); + void (*psr_program_dp_dphy_fast_training)(struct link_encoder *enc, + bool exit_link_training_required); + void (*psr_program_secondary_packet)(struct link_encoder *enc, + unsigned int sdp_transmit_line_num_deadline); void (*backlight_control) (struct link_encoder *enc, bool enable); void (*power_control) (struct link_encoder *enc, -- cgit From 5936223f7b51e122beb511265e2112777f7a887e Mon Sep 17 00:00:00 2001 From: Jordan Lazare Date: Thu, 23 Feb 2017 14:07:29 -0500 Subject: drm/amd/display: Fix gamma colour corruption for 10 bit surfaces Gamma LUT shouldn't be used for 10-bit and above. Should instead be using prescale and bypassing input gamma. Signed-off-by: Jordan Lazare Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 15 ++++- drivers/gpu/drm/amd/display/dc/dce80/Makefile | 3 +- .../gpu/drm/amd/display/dc/dce80/dce80_ipp_gamma.c | 71 ---------------------- 3 files changed, 15 insertions(+), 74 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp_gamma.c (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 2f68bf20dfe2..2d2daa694a30 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -233,6 +233,19 @@ static void build_prescale_params(struct ipp_prescale_params *prescale_params, } } + +/* Only use LUT for 8 bit formats */ +static bool use_lut(const struct core_surface *surface) +{ + switch (surface->public.format) { + case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: + return true; + default: + return false; + } +} + static bool dce110_set_input_transfer_func( struct pipe_ctx *pipe_ctx, const struct core_surface *surface) @@ -251,7 +264,7 @@ static bool dce110_set_input_transfer_func( build_prescale_params(&prescale_params, surface); ipp->funcs->ipp_program_prescale(ipp, &prescale_params); - if (surface->public.gamma_correction) + if (surface->public.gamma_correction && use_lut(surface)) ipp->funcs->ipp_program_input_lut(ipp, surface->public.gamma_correction); if (tf == NULL) { diff --git a/drivers/gpu/drm/amd/display/dc/dce80/Makefile b/drivers/gpu/drm/amd/display/dc/dce80/Makefile index 0261d1bfccb5..8d2c3dbfced1 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dce80/Makefile @@ -2,8 +2,7 @@ # Makefile for the 'controller' sub-component of DAL. # It provides the control and status of HW CRTC block. -DCE80 = dce80_ipp.o dce80_ipp_gamma.o \ - dce80_timing_generator.o \ +DCE80 = dce80_ipp.o dce80_timing_generator.o \ dce80_compressor.o dce80_mem_input.o dce80_hw_sequencer.o \ dce80_resource.o diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp_gamma.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp_gamma.c deleted file mode 100644 index 760168df5290..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp_gamma.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" - -#include "include/logger_interface.h" -#include "include/fixed31_32.h" -#include "basics/conversion.h" - -#include "dce/dce_8_0_d.h" -#include "dce/dce_8_0_sh_mask.h" - -#include "dce80_ipp.h" -#include "dce110/dce110_ipp.h" - -#define DCP_REG(reg)\ - (reg + ipp80->offsets.dcp_offset) - -/*PROTOTYPE DECLARATIONS*/ - -static void set_legacy_input_gamma_mode( - struct dce110_ipp *ipp80, - bool is_legacy); - -void dce80_ipp_set_legacy_input_gamma_mode( - struct input_pixel_processor *ipp, - bool is_legacy) -{ - struct dce110_ipp *ipp80 = TO_DCE80_IPP(ipp); - - set_legacy_input_gamma_mode(ipp80, is_legacy); -} - -static void set_legacy_input_gamma_mode( - struct dce110_ipp *ipp80, - bool is_legacy) -{ - const uint32_t addr = DCP_REG(mmINPUT_GAMMA_CONTROL); - uint32_t value = dm_read_reg(ipp80->base.ctx, addr); - - set_reg_field_value( - value, - !is_legacy, - INPUT_GAMMA_CONTROL, - GRPH_INPUT_GAMMA_MODE); - - dm_write_reg(ipp80->base.ctx, addr, value); -} - -- cgit From 227d2518997e122bb702d2110eafd337ad9ff078 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Thu, 23 Feb 2017 15:25:51 -0500 Subject: drm/amd/display: add scaler coefficients for 64 phase 5-8 taps Signed-off-by: Dmytro Laktyushkin Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dce/dce_scl_filters.c | 608 +++++++++++++++++++++ drivers/gpu/drm/amd/display/dc/inc/hw/transform.h | 4 + 2 files changed, 612 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_scl_filters.c b/drivers/gpu/drm/amd/display/dc/dce/dce_scl_filters.c index 3aab86781be2..2cfdb835f1a8 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_scl_filters.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_scl_filters.c @@ -452,6 +452,566 @@ const uint16_t filter_4tap_64p_183[132] = { 252, 1832, 1784, 220, 236, 1808, 1808, 236 }; +const uint16_t filter_5tap_64p_upscale[165] = { + 15936, 2496, 2496, 15936, 0, + 15948, 2404, 2580, 15924, 0, + 15960, 2312, 2664, 15912, 4, + 15976, 2220, 2748, 15904, 8, + 15992, 2128, 2832, 15896, 12, + 16004, 2036, 2912, 15888, 16, + 16020, 1944, 2992, 15880, 20, + 16036, 1852, 3068, 15876, 20, + 16056, 1760, 3140, 15876, 24, + 16072, 1668, 3216, 15872, 28, + 16088, 1580, 3284, 15872, 32, + 16104, 1492, 3352, 15876, 32, + 16120, 1404, 3420, 15876, 36, + 16140, 1316, 3480, 15884, 40, + 16156, 1228, 3540, 15892, 40, + 16172, 1144, 3600, 15900, 40, + 16188, 1060, 3652, 15908, 44, + 16204, 980, 3704, 15924, 44, + 16220, 900, 3756, 15936, 44, + 16236, 824, 3800, 15956, 44, + 16248, 744, 3844, 15972, 44, + 16264, 672, 3884, 15996, 44, + 16276, 600, 3920, 16020, 44, + 16292, 528, 3952, 16044, 40, + 16304, 460, 3980, 16072, 40, + 16316, 396, 4008, 16104, 36, + 16328, 332, 4032, 16136, 32, + 16336, 272, 4048, 16172, 28, + 16348, 212, 4064, 16208, 24, + 16356, 156, 4080, 16248, 16, + 16368, 100, 4088, 16292, 12, + 16376, 48, 4092, 16336, 4, + 0, 0, 4096, 0, 0 }; + +const uint16_t filter_5tap_64p_117[165] = { + 16056, 2372, 2372, 16056, 0, + 16052, 2312, 2432, 16060, 0, + 16052, 2252, 2488, 16064, 0, + 16052, 2188, 2548, 16072, 0, + 16052, 2124, 2600, 16076, 0, + 16052, 2064, 2656, 16088, 0, + 16052, 2000, 2708, 16096, 0, + 16056, 1932, 2760, 16108, 0, + 16060, 1868, 2808, 16120, 0, + 16064, 1804, 2856, 16132, 0, + 16068, 1740, 2904, 16148, 16380, + 16076, 1676, 2948, 16164, 16380, + 16080, 1612, 2992, 16180, 16376, + 16088, 1544, 3032, 16200, 16372, + 16096, 1480, 3072, 16220, 16372, + 16104, 1420, 3108, 16244, 16368, + 16112, 1356, 3144, 16268, 16364, + 16120, 1292, 3180, 16292, 16360, + 16128, 1232, 3212, 16320, 16356, + 16136, 1168, 3240, 16344, 16352, + 16144, 1108, 3268, 16376, 16344, + 16156, 1048, 3292, 20, 16340, + 16164, 988, 3316, 52, 16332, + 16172, 932, 3336, 88, 16328, + 16184, 872, 3356, 124, 16320, + 16192, 816, 3372, 160, 16316, + 16204, 760, 3388, 196, 16308, + 16212, 708, 3400, 236, 16300, + 16220, 656, 3412, 276, 16292, + 16232, 604, 3420, 320, 16284, + 16240, 552, 3424, 364, 16276, + 16248, 504, 3428, 408, 16268, + 16256, 456, 3428, 456, 16256 }; + +const uint16_t filter_5tap_64p_150[165] = { + 16368, 2064, 2064, 16368, 0, + 16352, 2028, 2100, 16380, 16380, + 16340, 1996, 2132, 12, 16376, + 16328, 1960, 2168, 24, 16376, + 16316, 1924, 2204, 44, 16372, + 16308, 1888, 2236, 60, 16368, + 16296, 1848, 2268, 76, 16364, + 16288, 1812, 2300, 96, 16360, + 16280, 1772, 2328, 116, 16356, + 16272, 1736, 2360, 136, 16352, + 16268, 1696, 2388, 160, 16348, + 16260, 1656, 2416, 180, 16344, + 16256, 1616, 2440, 204, 16340, + 16248, 1576, 2464, 228, 16336, + 16244, 1536, 2492, 252, 16332, + 16240, 1496, 2512, 276, 16324, + 16240, 1456, 2536, 304, 16320, + 16236, 1416, 2556, 332, 16316, + 16232, 1376, 2576, 360, 16312, + 16232, 1336, 2592, 388, 16308, + 16232, 1296, 2612, 416, 16300, + 16232, 1256, 2628, 448, 16296, + 16232, 1216, 2640, 480, 16292, + 16232, 1172, 2652, 512, 16288, + 16232, 1132, 2664, 544, 16284, + 16232, 1092, 2676, 576, 16280, + 16236, 1056, 2684, 608, 16272, + 16236, 1016, 2692, 644, 16268, + 16240, 976, 2700, 680, 16264, + 16240, 936, 2704, 712, 16260, + 16244, 900, 2708, 748, 16256, + 16248, 860, 2708, 788, 16252, + 16248, 824, 2708, 824, 16248 }; + +const uint16_t filter_5tap_64p_183[165] = { + 228, 1816, 1816, 228, 0, + 216, 1792, 1836, 248, 16380, + 200, 1772, 1860, 264, 16376, + 184, 1748, 1884, 280, 16376, + 168, 1728, 1904, 300, 16372, + 156, 1704, 1928, 316, 16368, + 144, 1680, 1948, 336, 16364, + 128, 1656, 1968, 356, 16364, + 116, 1632, 1988, 376, 16360, + 104, 1604, 2008, 396, 16356, + 96, 1580, 2024, 416, 16356, + 84, 1556, 2044, 440, 16352, + 72, 1528, 2060, 460, 16348, + 64, 1504, 2076, 484, 16348, + 52, 1476, 2092, 504, 16344, + 44, 1448, 2104, 528, 16344, + 36, 1424, 2120, 552, 16340, + 28, 1396, 2132, 576, 16340, + 20, 1368, 2144, 600, 16340, + 12, 1340, 2156, 624, 16336, + 4, 1312, 2168, 652, 16336, + 0, 1284, 2180, 676, 16336, + 16376, 1256, 2188, 700, 16332, + 16372, 1228, 2196, 728, 16332, + 16368, 1200, 2204, 752, 16332, + 16364, 1172, 2212, 780, 16332, + 16356, 1144, 2216, 808, 16332, + 16352, 1116, 2220, 836, 16332, + 16352, 1084, 2224, 860, 16332, + 16348, 1056, 2228, 888, 16336, + 16344, 1028, 2232, 916, 16336, + 16340, 1000, 2232, 944, 16336, + 16340, 972, 2232, 972, 16340 }; + +const uint16_t filter_6tap_64p_upscale[198] = { + 0, 0, 4092, 0, 0, 0, + 12, 16332, 4092, 52, 16368, 0, + 24, 16280, 4088, 108, 16356, 0, + 36, 16236, 4080, 168, 16340, 0, + 44, 16188, 4064, 228, 16324, 0, + 56, 16148, 4052, 292, 16308, 0, + 64, 16108, 4032, 356, 16292, 4, + 72, 16072, 4008, 424, 16276, 4, + 80, 16036, 3980, 492, 16256, 4, + 88, 16004, 3952, 564, 16240, 8, + 96, 15972, 3920, 636, 16220, 8, + 100, 15944, 3884, 712, 16204, 12, + 108, 15916, 3844, 788, 16184, 16, + 112, 15896, 3800, 864, 16164, 20, + 116, 15872, 3756, 944, 16144, 20, + 120, 15852, 3708, 1024, 16124, 24, + 120, 15836, 3656, 1108, 16104, 28, + 124, 15824, 3600, 1192, 16084, 32, + 124, 15808, 3544, 1276, 16064, 36, + 124, 15800, 3484, 1360, 16044, 40, + 128, 15792, 3420, 1448, 16024, 44, + 128, 15784, 3352, 1536, 16004, 48, + 124, 15780, 3288, 1624, 15988, 52, + 124, 15776, 3216, 1712, 15968, 56, + 124, 15776, 3144, 1800, 15948, 64, + 120, 15776, 3068, 1888, 15932, 68, + 120, 15780, 2992, 1976, 15912, 72, + 116, 15784, 2916, 2064, 15896, 76, + 112, 15792, 2836, 2152, 15880, 80, + 108, 15796, 2752, 2244, 15868, 84, + 104, 15804, 2672, 2328, 15852, 88, + 104, 15816, 2588, 2416, 15840, 92, + 100, 15828, 2504, 2504, 15828, 100 }; + +const uint16_t filter_6tap_64p_117[198] = { + 16168, 476, 3568, 476, 16168, 0, + 16180, 428, 3564, 528, 16156, 0, + 16192, 376, 3556, 584, 16144, 4, + 16204, 328, 3548, 636, 16128, 4, + 16216, 280, 3540, 692, 16116, 8, + 16228, 232, 3524, 748, 16104, 12, + 16240, 188, 3512, 808, 16092, 12, + 16252, 148, 3492, 864, 16080, 16, + 16264, 104, 3472, 924, 16068, 16, + 16276, 64, 3452, 984, 16056, 20, + 16284, 28, 3428, 1044, 16048, 24, + 16296, 16376, 3400, 1108, 16036, 24, + 16304, 16340, 3372, 1168, 16024, 28, + 16316, 16304, 3340, 1232, 16016, 32, + 16324, 16272, 3308, 1296, 16004, 32, + 16332, 16244, 3272, 1360, 15996, 36, + 16344, 16212, 3236, 1424, 15988, 36, + 16352, 16188, 3200, 1488, 15980, 40, + 16360, 16160, 3160, 1552, 15972, 40, + 16368, 16136, 3116, 1616, 15964, 40, + 16372, 16112, 3072, 1680, 15956, 44, + 16380, 16092, 3028, 1744, 15952, 44, + 0, 16072, 2980, 1808, 15948, 44, + 8, 16052, 2932, 1872, 15944, 48, + 12, 16036, 2880, 1936, 15940, 48, + 16, 16020, 2828, 2000, 15936, 48, + 20, 16008, 2776, 2064, 15936, 48, + 24, 15996, 2724, 2128, 15936, 48, + 28, 15984, 2668, 2192, 15936, 48, + 32, 15972, 2612, 2252, 15940, 44, + 36, 15964, 2552, 2316, 15940, 44, + 40, 15956, 2496, 2376, 15944, 44, + 40, 15952, 2436, 2436, 15952, 40 }; + +const uint16_t filter_6tap_64p_150[198] = { + 16148, 920, 2724, 920, 16148, 0, + 16152, 880, 2724, 956, 16148, 0, + 16152, 844, 2720, 996, 16144, 0, + 16156, 804, 2716, 1032, 16144, 0, + 16156, 768, 2712, 1072, 16144, 0, + 16160, 732, 2708, 1112, 16144, 16380, + 16164, 696, 2700, 1152, 16144, 16380, + 16168, 660, 2692, 1192, 16148, 16380, + 16172, 628, 2684, 1232, 16148, 16380, + 16176, 592, 2672, 1272, 16152, 16376, + 16180, 560, 2660, 1312, 16152, 16376, + 16184, 524, 2648, 1348, 16156, 16376, + 16192, 492, 2632, 1388, 16160, 16372, + 16196, 460, 2616, 1428, 16164, 16372, + 16200, 432, 2600, 1468, 16168, 16368, + 16204, 400, 2584, 1508, 16176, 16364, + 16212, 368, 2564, 1548, 16180, 16364, + 16216, 340, 2544, 1588, 16188, 16360, + 16220, 312, 2524, 1628, 16196, 16356, + 16228, 284, 2504, 1668, 16204, 16356, + 16232, 256, 2480, 1704, 16212, 16352, + 16240, 232, 2456, 1744, 16224, 16348, + 16244, 204, 2432, 1780, 16232, 16344, + 16248, 180, 2408, 1820, 16244, 16340, + 16256, 156, 2380, 1856, 16256, 16336, + 16260, 132, 2352, 1896, 16268, 16332, + 16268, 108, 2324, 1932, 16280, 16328, + 16272, 88, 2296, 1968, 16292, 16324, + 16276, 64, 2268, 2004, 16308, 16320, + 16284, 44, 2236, 2036, 16324, 16312, + 16288, 24, 2204, 2072, 16340, 16308, + 16292, 8, 2172, 2108, 16356, 16304, + 16300, 16372, 2140, 2140, 16372, 16300 }; + +const uint16_t filter_6tap_64p_183[198] = { + 16296, 1032, 2196, 1032, 16296, 0, + 16292, 1004, 2200, 1060, 16304, 16380, + 16288, 976, 2200, 1088, 16308, 16380, + 16284, 952, 2196, 1116, 16312, 16376, + 16284, 924, 2196, 1144, 16320, 16376, + 16280, 900, 2192, 1172, 16324, 16372, + 16276, 872, 2192, 1200, 16332, 16368, + 16276, 848, 2188, 1228, 16340, 16368, + 16272, 820, 2180, 1256, 16348, 16364, + 16272, 796, 2176, 1280, 16356, 16360, + 16268, 768, 2168, 1308, 16364, 16360, + 16268, 744, 2164, 1336, 16372, 16356, + 16268, 716, 2156, 1364, 16380, 16352, + 16264, 692, 2148, 1392, 4, 16352, + 16264, 668, 2136, 1420, 16, 16348, + 16264, 644, 2128, 1448, 28, 16344, + 16264, 620, 2116, 1472, 36, 16340, + 16264, 596, 2108, 1500, 48, 16340, + 16268, 572, 2096, 1524, 60, 16336, + 16268, 548, 2080, 1552, 72, 16332, + 16268, 524, 2068, 1576, 88, 16328, + 16268, 504, 2056, 1604, 100, 16324, + 16272, 480, 2040, 1628, 112, 16324, + 16272, 456, 2024, 1652, 128, 16320, + 16272, 436, 2008, 1680, 144, 16316, + 16276, 416, 1992, 1704, 156, 16312, + 16276, 392, 1976, 1724, 172, 16308, + 16280, 372, 1956, 1748, 188, 16308, + 16280, 352, 1940, 1772, 204, 16304, + 16284, 332, 1920, 1796, 224, 16300, + 16288, 312, 1900, 1816, 240, 16296, + 16288, 296, 1880, 1840, 256, 16296, + 16292, 276, 1860, 1860, 276, 16292 }; + +const uint16_t filter_7tap_64p_upscale[231] = { + 176, 15760, 2488, 2488, 15760, 176, 0, + 172, 15772, 2404, 2572, 15752, 180, 16380, + 168, 15784, 2324, 2656, 15740, 184, 16380, + 164, 15800, 2240, 2736, 15732, 188, 16376, + 160, 15812, 2152, 2816, 15728, 192, 16376, + 152, 15828, 2068, 2896, 15724, 192, 16376, + 148, 15848, 1984, 2972, 15720, 196, 16372, + 140, 15864, 1896, 3048, 15720, 196, 16372, + 136, 15884, 1812, 3124, 15720, 196, 16368, + 128, 15900, 1724, 3196, 15720, 196, 16368, + 120, 15920, 1640, 3268, 15724, 196, 16368, + 116, 15940, 1552, 3336, 15732, 196, 16364, + 108, 15964, 1468, 3400, 15740, 196, 16364, + 104, 15984, 1384, 3464, 15748, 192, 16364, + 96, 16004, 1300, 3524, 15760, 188, 16364, + 88, 16028, 1216, 3584, 15776, 184, 16364, + 84, 16048, 1132, 3640, 15792, 180, 16360, + 76, 16072, 1048, 3692, 15812, 176, 16360, + 68, 16092, 968, 3744, 15832, 168, 16360, + 64, 16116, 888, 3788, 15856, 160, 16360, + 56, 16140, 812, 3832, 15884, 152, 16360, + 52, 16160, 732, 3876, 15912, 144, 16360, + 44, 16184, 656, 3912, 15944, 136, 16364, + 40, 16204, 584, 3944, 15976, 124, 16364, + 32, 16228, 512, 3976, 16012, 116, 16364, + 28, 16248, 440, 4004, 16048, 104, 16364, + 24, 16268, 372, 4028, 16092, 88, 16368, + 20, 16288, 304, 4048, 16132, 76, 16368, + 12, 16308, 240, 4064, 16180, 60, 16372, + 8, 16328, 176, 4076, 16228, 48, 16372, + 4, 16348, 112, 4088, 16276, 32, 16376, + 0, 16364, 56, 4092, 16328, 16, 16380, + 0, 0, 0, 4096, 0, 0, 0 }; + +const uint16_t filter_7tap_64p_117[231] = { + 92, 15868, 2464, 2464, 15868, 92, 0, + 96, 15864, 2404, 2528, 15876, 88, 0, + 100, 15860, 2344, 2584, 15884, 84, 0, + 104, 15856, 2280, 2644, 15892, 76, 0, + 108, 15852, 2216, 2700, 15904, 72, 0, + 108, 15852, 2152, 2756, 15916, 64, 0, + 112, 15852, 2088, 2812, 15932, 60, 0, + 112, 15852, 2024, 2864, 15948, 52, 0, + 112, 15856, 1960, 2916, 15964, 44, 0, + 116, 15860, 1892, 2964, 15984, 36, 0, + 116, 15864, 1828, 3016, 16004, 24, 4, + 116, 15868, 1760, 3060, 16024, 16, 4, + 116, 15876, 1696, 3108, 16048, 8, 8, + 116, 15884, 1628, 3152, 16072, 16380, 8, + 112, 15892, 1564, 3192, 16100, 16372, 8, + 112, 15900, 1496, 3232, 16124, 16360, 12, + 112, 15908, 1428, 3268, 16156, 16348, 12, + 108, 15920, 1364, 3304, 16188, 16336, 16, + 108, 15928, 1300, 3340, 16220, 16324, 20, + 104, 15940, 1232, 3372, 16252, 16312, 20, + 104, 15952, 1168, 3400, 16288, 16300, 24, + 100, 15964, 1104, 3428, 16328, 16284, 28, + 96, 15980, 1040, 3452, 16364, 16272, 28, + 96, 15992, 976, 3476, 20, 16256, 32, + 92, 16004, 916, 3496, 64, 16244, 36, + 88, 16020, 856, 3516, 108, 16228, 40, + 84, 16032, 792, 3532, 152, 16216, 44, + 80, 16048, 732, 3544, 200, 16200, 48, + 80, 16064, 676, 3556, 248, 16184, 48, + 76, 16080, 616, 3564, 296, 16168, 52, + 72, 16092, 560, 3568, 344, 16156, 56, + 68, 16108, 504, 3572, 396, 16140, 60, + 64, 16124, 452, 3576, 452, 16124, 64 }; + +const uint16_t filter_7tap_64p_150[231] = { + 16224, 16380, 2208, 2208, 16380, 16224, 0, + 16232, 16360, 2172, 2236, 16, 16216, 0, + 16236, 16340, 2140, 2268, 40, 16212, 0, + 16244, 16324, 2104, 2296, 60, 16204, 4, + 16252, 16304, 2072, 2324, 84, 16196, 4, + 16256, 16288, 2036, 2352, 108, 16192, 4, + 16264, 16268, 2000, 2380, 132, 16184, 8, + 16272, 16252, 1960, 2408, 160, 16176, 8, + 16276, 16240, 1924, 2432, 184, 16172, 8, + 16284, 16224, 1888, 2456, 212, 16164, 8, + 16288, 16212, 1848, 2480, 240, 16160, 12, + 16296, 16196, 1812, 2500, 268, 16152, 12, + 16300, 16184, 1772, 2524, 296, 16144, 12, + 16308, 16172, 1736, 2544, 324, 16140, 12, + 16312, 16164, 1696, 2564, 356, 16136, 12, + 16320, 16152, 1656, 2584, 388, 16128, 12, + 16324, 16144, 1616, 2600, 416, 16124, 12, + 16328, 16136, 1576, 2616, 448, 16116, 12, + 16332, 16128, 1536, 2632, 480, 16112, 12, + 16340, 16120, 1496, 2648, 516, 16108, 12, + 16344, 16112, 1456, 2660, 548, 16104, 12, + 16348, 16104, 1416, 2672, 580, 16100, 12, + 16352, 16100, 1376, 2684, 616, 16096, 12, + 16356, 16096, 1336, 2696, 652, 16092, 12, + 16360, 16092, 1296, 2704, 688, 16088, 12, + 16364, 16088, 1256, 2712, 720, 16084, 12, + 16368, 16084, 1220, 2720, 760, 16084, 8, + 16368, 16080, 1180, 2724, 796, 16080, 8, + 16372, 16080, 1140, 2732, 832, 16080, 8, + 16376, 16076, 1100, 2732, 868, 16076, 4, + 16380, 16076, 1060, 2736, 908, 16076, 4, + 16380, 16076, 1020, 2740, 944, 16076, 0, + 0, 16076, 984, 2740, 984, 16076, 0 }; + +const uint16_t filter_7tap_64p_183[231] = { + 16216, 324, 1884, 1884, 324, 16216, 0, + 16220, 304, 1864, 1904, 344, 16216, 0, + 16224, 284, 1844, 1924, 364, 16216, 0, + 16224, 264, 1824, 1944, 384, 16212, 16380, + 16228, 248, 1804, 1960, 408, 16212, 16380, + 16228, 228, 1784, 1976, 428, 16208, 16380, + 16232, 212, 1760, 1996, 452, 16208, 16380, + 16236, 192, 1740, 2012, 472, 16208, 16376, + 16240, 176, 1716, 2028, 496, 16208, 16376, + 16240, 160, 1696, 2040, 516, 16208, 16376, + 16244, 144, 1672, 2056, 540, 16208, 16376, + 16248, 128, 1648, 2068, 564, 16208, 16372, + 16252, 112, 1624, 2084, 588, 16208, 16372, + 16256, 96, 1600, 2096, 612, 16208, 16368, + 16256, 84, 1576, 2108, 636, 16208, 16368, + 16260, 68, 1552, 2120, 660, 16208, 16368, + 16264, 56, 1524, 2132, 684, 16212, 16364, + 16268, 40, 1500, 2140, 712, 16212, 16364, + 16272, 28, 1476, 2152, 736, 16216, 16360, + 16276, 16, 1448, 2160, 760, 16216, 16356, + 16280, 4, 1424, 2168, 788, 16220, 16356, + 16284, 16376, 1396, 2176, 812, 16224, 16352, + 16288, 16368, 1372, 2184, 840, 16224, 16352, + 16292, 16356, 1344, 2188, 864, 16228, 16348, + 16292, 16344, 1320, 2196, 892, 16232, 16344, + 16296, 16336, 1292, 2200, 916, 16236, 16344, + 16300, 16324, 1264, 2204, 944, 16240, 16340, + 16304, 16316, 1240, 2208, 972, 16248, 16336, + 16308, 16308, 1212, 2212, 996, 16252, 16332, + 16312, 16300, 1184, 2216, 1024, 16256, 16332, + 16316, 16292, 1160, 2216, 1052, 16264, 16328, + 16316, 16284, 1132, 2216, 1076, 16268, 16324, + 16320, 16276, 1104, 2216, 1104, 16276, 16320 }; + +const uint16_t filter_8tap_64p_upscale[264] = { + 0, 0, 0, 4096, 0, 0, 0, 0, + 16376, 20, 16328, 4092, 56, 16364, 4, 0, + 16372, 36, 16272, 4088, 116, 16340, 12, 0, + 16364, 56, 16220, 4080, 180, 16320, 20, 0, + 16360, 76, 16172, 4064, 244, 16296, 24, 16380, + 16356, 92, 16124, 4048, 312, 16276, 32, 16380, + 16352, 108, 16080, 4032, 380, 16252, 40, 16380, + 16344, 124, 16036, 4008, 452, 16228, 48, 16380, + 16340, 136, 15996, 3980, 524, 16204, 56, 16380, + 16340, 152, 15956, 3952, 600, 16180, 64, 16376, + 16336, 164, 15920, 3920, 672, 16156, 76, 16376, + 16332, 176, 15888, 3884, 752, 16132, 84, 16376, + 16328, 188, 15860, 3844, 828, 16104, 92, 16372, + 16328, 200, 15828, 3800, 908, 16080, 100, 16372, + 16324, 208, 15804, 3756, 992, 16056, 108, 16372, + 16324, 216, 15780, 3708, 1072, 16032, 120, 16368, + 16320, 224, 15760, 3656, 1156, 16008, 128, 16368, + 16320, 232, 15740, 3604, 1240, 15984, 136, 16364, + 16320, 240, 15724, 3548, 1324, 15960, 144, 16364, + 16320, 244, 15708, 3488, 1412, 15936, 152, 16360, + 16320, 248, 15696, 3428, 1496, 15912, 160, 16360, + 16320, 252, 15688, 3364, 1584, 15892, 172, 16356, + 16320, 256, 15680, 3296, 1672, 15868, 180, 16352, + 16320, 256, 15672, 3228, 1756, 15848, 188, 16352, + 16320, 256, 15668, 3156, 1844, 15828, 192, 16348, + 16320, 260, 15668, 3084, 1932, 15808, 200, 16348, + 16320, 256, 15668, 3012, 2020, 15792, 208, 16344, + 16324, 256, 15668, 2936, 2108, 15772, 216, 16344, + 16324, 256, 15672, 2856, 2192, 15756, 220, 16340, + 16324, 252, 15676, 2776, 2280, 15740, 228, 16336, + 16328, 252, 15684, 2696, 2364, 15728, 232, 16336, + 16328, 248, 15692, 2616, 2448, 15716, 240, 16332, + 16332, 244, 15704, 2532, 2532, 15704, 244, 16332 }; + +const uint16_t filter_8tap_64p_117[264] = { + 116, 16100, 428, 3564, 428, 16100, 116, 0, + 112, 16116, 376, 3564, 484, 16084, 120, 16380, + 104, 16136, 324, 3560, 540, 16064, 124, 16380, + 100, 16152, 272, 3556, 600, 16048, 128, 16380, + 96, 16168, 220, 3548, 656, 16032, 136, 16376, + 88, 16188, 172, 3540, 716, 16016, 140, 16376, + 84, 16204, 124, 3528, 780, 16000, 144, 16376, + 80, 16220, 76, 3512, 840, 15984, 148, 16372, + 76, 16236, 32, 3496, 904, 15968, 152, 16372, + 68, 16252, 16376, 3480, 968, 15952, 156, 16372, + 64, 16268, 16332, 3456, 1032, 15936, 160, 16372, + 60, 16284, 16292, 3432, 1096, 15920, 164, 16368, + 56, 16300, 16252, 3408, 1164, 15908, 164, 16368, + 48, 16316, 16216, 3380, 1228, 15892, 168, 16368, + 44, 16332, 16180, 3348, 1296, 15880, 168, 16368, + 40, 16348, 16148, 3316, 1364, 15868, 172, 16364, + 36, 16360, 16116, 3284, 1428, 15856, 172, 16364, + 32, 16376, 16084, 3248, 1496, 15848, 176, 16364, + 28, 4, 16052, 3208, 1564, 15836, 176, 16364, + 24, 16, 16028, 3168, 1632, 15828, 176, 16364, + 20, 28, 16000, 3124, 1700, 15820, 176, 16364, + 16, 40, 15976, 3080, 1768, 15812, 176, 16364, + 12, 52, 15952, 3036, 1836, 15808, 176, 16364, + 8, 64, 15932, 2988, 1904, 15800, 176, 16364, + 4, 76, 15912, 2940, 1972, 15800, 172, 16364, + 4, 84, 15892, 2888, 2040, 15796, 172, 16364, + 0, 96, 15876, 2836, 2104, 15792, 168, 16364, + 16380, 104, 15864, 2780, 2172, 15792, 164, 16364, + 16380, 112, 15848, 2724, 2236, 15792, 160, 16364, + 16376, 120, 15836, 2668, 2300, 15796, 156, 16368, + 16376, 128, 15828, 2608, 2364, 15800, 152, 16368, + 16372, 136, 15816, 2548, 2428, 15804, 148, 16368, + 16372, 140, 15812, 2488, 2488, 15812, 140, 16372 }; + +const uint16_t filter_8tap_64p_150[264] = { + 16380, 16020, 1032, 2756, 1032, 16020, 16380, 0, + 0, 16020, 992, 2756, 1068, 16024, 16376, 0, + 4, 16020, 952, 2752, 1108, 16024, 16372, 0, + 8, 16020, 916, 2748, 1148, 16028, 16368, 0, + 12, 16020, 876, 2744, 1184, 16032, 16364, 4, + 16, 16020, 840, 2740, 1224, 16036, 16356, 4, + 20, 16024, 800, 2732, 1264, 16040, 16352, 4, + 20, 16024, 764, 2724, 1304, 16044, 16348, 8, + 24, 16028, 728, 2716, 1344, 16052, 16340, 8, + 28, 16028, 692, 2704, 1380, 16056, 16336, 12, + 28, 16032, 656, 2696, 1420, 16064, 16328, 12, + 32, 16036, 620, 2684, 1460, 16072, 16324, 12, + 36, 16040, 584, 2668, 1500, 16080, 16316, 16, + 36, 16044, 548, 2656, 1536, 16088, 16308, 16, + 36, 16048, 516, 2640, 1576, 16096, 16304, 20, + 40, 16052, 480, 2624, 1612, 16108, 16296, 20, + 40, 16060, 448, 2608, 1652, 16120, 16288, 20, + 44, 16064, 416, 2588, 1692, 16132, 16280, 24, + 44, 16068, 384, 2568, 1728, 16144, 16276, 24, + 44, 16076, 352, 2548, 1764, 16156, 16268, 28, + 44, 16080, 320, 2528, 1804, 16168, 16260, 28, + 44, 16088, 292, 2508, 1840, 16184, 16252, 28, + 44, 16096, 264, 2484, 1876, 16200, 16244, 32, + 48, 16100, 232, 2460, 1912, 16216, 16236, 32, + 48, 16108, 204, 2436, 1948, 16232, 16228, 32, + 48, 16116, 176, 2412, 1980, 16248, 16220, 36, + 48, 16124, 152, 2384, 2016, 16264, 16216, 36, + 44, 16128, 124, 2356, 2052, 16284, 16208, 36, + 44, 16136, 100, 2328, 2084, 16304, 16200, 40, + 44, 16144, 72, 2300, 2116, 16324, 16192, 40, + 44, 16152, 48, 2272, 2148, 16344, 16184, 40, + 44, 16160, 24, 2244, 2180, 16364, 16176, 40, + 44, 16168, 4, 2212, 2212, 4, 16168, 44 }; + +const uint16_t filter_8tap_64p_183[264] = { + 16264, 16264, 1164, 2244, 1164, 16264, 16264, 0, + 16268, 16256, 1136, 2240, 1188, 16272, 16260, 0, + 16272, 16248, 1108, 2240, 1216, 16280, 16256, 0, + 16276, 16240, 1080, 2236, 1240, 16292, 16252, 0, + 16280, 16232, 1056, 2236, 1268, 16300, 16248, 0, + 16284, 16224, 1028, 2232, 1292, 16312, 16244, 0, + 16288, 16216, 1000, 2228, 1320, 16324, 16240, 0, + 16292, 16212, 976, 2224, 1344, 16336, 16236, 0, + 16296, 16204, 948, 2220, 1372, 16348, 16232, 0, + 16300, 16200, 920, 2212, 1396, 16360, 16228, 4, + 16304, 16196, 896, 2204, 1424, 16372, 16224, 4, + 16308, 16188, 868, 2200, 1448, 0, 16220, 4, + 16312, 16184, 844, 2192, 1472, 12, 16216, 4, + 16316, 16180, 816, 2184, 1500, 28, 16212, 4, + 16320, 16176, 792, 2172, 1524, 40, 16208, 4, + 16324, 16172, 764, 2164, 1548, 56, 16204, 0, + 16328, 16172, 740, 2156, 1572, 72, 16200, 0, + 16328, 16168, 712, 2144, 1596, 88, 16196, 0, + 16332, 16164, 688, 2132, 1620, 100, 16192, 0, + 16336, 16164, 664, 2120, 1644, 120, 16192, 0, + 16340, 16160, 640, 2108, 1668, 136, 16188, 0, + 16344, 16160, 616, 2096, 1688, 152, 16184, 0, + 16344, 16160, 592, 2080, 1712, 168, 16180, 0, + 16348, 16156, 568, 2068, 1736, 188, 16176, 16380, + 16352, 16156, 544, 2052, 1756, 204, 16176, 16380, + 16352, 16156, 520, 2036, 1780, 224, 16172, 16380, + 16356, 16156, 496, 2024, 1800, 244, 16172, 16380, + 16360, 16156, 472, 2008, 1820, 260, 16168, 16376, + 16360, 16156, 452, 1988, 1840, 280, 16164, 16376, + 16364, 16156, 428, 1972, 1860, 300, 16164, 16376, + 16364, 16156, 408, 1956, 1880, 320, 16164, 16372, + 16368, 16160, 384, 1936, 1900, 344, 16160, 16372, + 16368, 16160, 364, 1920, 1920, 364, 16160, 16368 }; + const uint16_t *get_filter_3tap_16p(struct fixed31_32 ratio) { if (ratio.value < dal_fixed31_32_one.value) @@ -499,3 +1059,51 @@ const uint16_t *get_filter_4tap_64p(struct fixed31_32 ratio) else return filter_4tap_64p_183; } + +const uint16_t *get_filter_5tap_64p(struct fixed31_32 ratio) +{ + if (ratio.value < dal_fixed31_32_one.value) + return filter_5tap_64p_upscale; + else if (ratio.value < dal_fixed31_32_from_fraction(4, 3).value) + return filter_5tap_64p_117; + else if (ratio.value < dal_fixed31_32_from_fraction(5, 3).value) + return filter_5tap_64p_150; + else + return filter_5tap_64p_183; +} + +const uint16_t *get_filter_6tap_64p(struct fixed31_32 ratio) +{ + if (ratio.value < dal_fixed31_32_one.value) + return filter_6tap_64p_upscale; + else if (ratio.value < dal_fixed31_32_from_fraction(4, 3).value) + return filter_6tap_64p_117; + else if (ratio.value < dal_fixed31_32_from_fraction(5, 3).value) + return filter_6tap_64p_150; + else + return filter_6tap_64p_183; +} + +const uint16_t *get_filter_7tap_64p(struct fixed31_32 ratio) +{ + if (ratio.value < dal_fixed31_32_one.value) + return filter_7tap_64p_upscale; + else if (ratio.value < dal_fixed31_32_from_fraction(4, 3).value) + return filter_7tap_64p_117; + else if (ratio.value < dal_fixed31_32_from_fraction(5, 3).value) + return filter_7tap_64p_150; + else + return filter_7tap_64p_183; +} + +const uint16_t *get_filter_8tap_64p(struct fixed31_32 ratio) +{ + if (ratio.value < dal_fixed31_32_one.value) + return filter_8tap_64p_upscale; + else if (ratio.value < dal_fixed31_32_from_fraction(4, 3).value) + return filter_8tap_64p_117; + else if (ratio.value < dal_fixed31_32_from_fraction(5, 3).value) + return filter_8tap_64p_150; + else + return filter_8tap_64p_183; +} diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h index a510d3fe48ec..9c5cb0ee4243 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h @@ -186,5 +186,9 @@ const uint16_t *get_filter_3tap_16p(struct fixed31_32 ratio); const uint16_t *get_filter_3tap_64p(struct fixed31_32 ratio); const uint16_t *get_filter_4tap_16p(struct fixed31_32 ratio); const uint16_t *get_filter_4tap_64p(struct fixed31_32 ratio); +const uint16_t *get_filter_5tap_64p(struct fixed31_32 ratio); +const uint16_t *get_filter_6tap_64p(struct fixed31_32 ratio); +const uint16_t *get_filter_7tap_64p(struct fixed31_32 ratio); +const uint16_t *get_filter_8tap_64p(struct fixed31_32 ratio); #endif -- cgit From 1781958ff41b28b3cd7b4a2ed691c932031c5515 Mon Sep 17 00:00:00 2001 From: Leon Elazar Date: Thu, 23 Feb 2017 16:10:43 -0500 Subject: drm/amd/display: Surface Validation Fixes + Audio Mask 1. dc: Adding missing mask for audio register DCCG_AUDIO_DTO_SOURCE 2. Changing the surface validation to check the limits of the clip rect instead of the source rect. Signed-off-by: Leon Elazar Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_audio.h | 1 + drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c | 8 ++++---- drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c | 4 ++-- drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c | 4 ++-- 4 files changed, 9 insertions(+), 8 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.h b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.h index b98ee2d2a9c7..0dc5ff137c7a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.h @@ -48,6 +48,7 @@ #define AUD_COMMON_MASK_SH_LIST_BASE(mask_sh)\ SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO0_SOURCE_SEL, mask_sh),\ SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO_SEL, mask_sh),\ + SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO2_USE_512FBR_DTO, mask_sh),\ SF(DCCG_AUDIO_DTO0_MODULE, DCCG_AUDIO_DTO0_MODULE, mask_sh),\ SF(DCCG_AUDIO_DTO0_PHASE, DCCG_AUDIO_DTO0_PHASE, mask_sh),\ SF(DCCG_AUDIO_DTO1_MODULE, DCCG_AUDIO_DTO1_MODULE, mask_sh),\ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index cd3942df70a7..80b2359a3cb4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -1009,10 +1009,10 @@ static bool dce110_validate_surface_sets( if (set[i].surface_count > 2) return false; - if (set[i].surfaces[0]->src_rect.width - < set[i].stream->src.width - || set[i].surfaces[0]->src_rect.height - < set[i].stream->src.height) + if (set[i].surfaces[0]->clip_rect.width + > set[i].stream->src.width + || set[i].surfaces[0]->clip_rect.height + > set[i].stream->src.height) return false; if (set[i].surfaces[0]->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 526c106f6ebf..ce6c69fd1041 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -975,9 +975,9 @@ static bool dce112_validate_surface_sets( return false; if (set[i].surfaces[0]->clip_rect.width - < set[i].stream->src.width + > set[i].stream->src.width || set[i].surfaces[0]->clip_rect.height - < set[i].stream->src.height) + > set[i].stream->src.height) return false; if (set[i].surfaces[0]->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 272c7fc31406..fbbdd0ee2d4c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -805,9 +805,9 @@ static bool dce80_validate_surface_sets( return false; if (set[i].surfaces[0]->clip_rect.width - != set[i].stream->src.width + > set[i].stream->src.width || set[i].surfaces[0]->clip_rect.height - != set[i].stream->src.height) + > set[i].stream->src.height) return false; if (set[i].surfaces[0]->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) -- cgit From 0d70570f712e2db49396eaef61790bac2a08ec1c Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Fri, 24 Feb 2017 11:21:11 -0500 Subject: drm/amd/display: Fix warnings in amdgpu_dm Signed-off-by: Harry Wentland Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index dc0d8533521f..862bbd745bb9 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -962,7 +962,7 @@ static void decide_crtc_timing_for_drm_display_mode( } static struct dc_stream *create_stream_for_sink( - const struct amdgpu_connector *aconnector, + struct amdgpu_connector *aconnector, const struct drm_display_mode *drm_mode, const struct dm_connector_state *dm_state) { -- cgit From 648013696767f0266aa7bd44407786a99f7a7910 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Fri, 24 Feb 2017 11:31:23 -0500 Subject: drm/amd/display: Fix warnings in DC Signed-off-by: Harry Wentland Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 2 -- drivers/gpu/drm/amd/display/dc/core/dc_surface.c | 2 +- drivers/gpu/drm/amd/display/dc/dce/dce_abm.c | 1 - drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c | 1 - 4 files changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 6516c275e0c7..e0d9572768cb 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1068,7 +1068,6 @@ bool dc_pre_update_surfaces_to_stream( int prev_disp_clk = core_dc->current_context->dispclk_khz; struct dc_stream_status *stream_status = NULL; struct validate_context *context; - struct validate_context *temp_context; bool ret = true; pre_surface_trace(dc, new_surfaces, new_surface_count); @@ -1425,7 +1424,6 @@ void dc_update_surfaces_for_stream(struct dc *dc, if (update_type == UPDATE_TYPE_FULL) { for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - struct core_stream *stream = pipe_ctx->stream; if (pipe_ctx->surface != surface) continue; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index 21fedd447bd1..943895faee49 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -121,7 +121,7 @@ const struct dc_surface_status *dc_surface_get_status( const struct dc_surface *dc_surface) { struct dc_surface_status *surface_status; - struct core_surface *core_surface = DC_SURFACE_TO_CORE(dc_surface);; + struct core_surface *core_surface = DC_SURFACE_TO_CORE(dc_surface); struct core_dc *core_dc; int i; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c index 7005ebb28d46..45a3079c0973 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c @@ -292,7 +292,6 @@ static void dce_abm_init(struct abm *abm) static bool dce_abm_set_level(struct abm *abm, uint32_t level) { struct dce_abm *abm_dce = TO_DCE_ABM(abm); - struct dc_context *ctx = abm_dce->base.ctx; REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 100, 800); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c index 682a3de7ba48..c95b69446ced 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c @@ -74,7 +74,6 @@ static bool dce110_timing_generator_v_disable_crtc(struct timing_generator *tg) static void dce110_timing_generator_v_blank_crtc(struct timing_generator *tg) { - struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); uint32_t addr = mmCRTCV_BLANK_CONTROL; uint32_t value = dm_read_reg(tg->ctx, addr); -- cgit From 45209ef7197bd4b5e7e224ff46fa9a3eca25c3bd Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 24 Feb 2017 14:19:40 -0500 Subject: drm/amd/display: remove apply_clk_constraints, used validate_bandwidth universally Signed-off-by: Dmytro Laktyushkin Acked-by: Harry Wentland Reviewed-by: Dmytro Laktyushkin Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 50 ++++++++++++++-------- .../drm/amd/display/dc/dce100/dce100_resource.c | 10 +++-- .../drm/amd/display/dc/dce110/dce110_resource.c | 18 ++++---- .../drm/amd/display/dc/dce112/dce112_resource.c | 18 ++++---- .../drm/amd/display/dc/dce112/dce112_resource.h | 2 +- .../gpu/drm/amd/display/dc/dce80/dce80_resource.c | 4 +- drivers/gpu/drm/amd/display/dc/inc/core_status.h | 1 - drivers/gpu/drm/amd/display/dc/inc/core_types.h | 6 +-- 8 files changed, 59 insertions(+), 50 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index e0d9572768cb..da0f72071ef5 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1144,12 +1144,11 @@ bool dc_pre_update_surfaces_to_stream( } } - if (core_dc->res_pool->funcs->validate_bandwidth) - if (core_dc->res_pool->funcs->validate_bandwidth(core_dc, context) != DC_OK) { - BREAK_TO_DEBUGGER(); - ret = false; - goto unexpected_fail; - } + if (!core_dc->res_pool->funcs->validate_bandwidth(core_dc, context)) { + BREAK_TO_DEBUGGER(); + ret = false; + goto unexpected_fail; + } if (!IS_FPGA_MAXIMUS_DC(core_dc->ctx->dce_environment) && prev_disp_clk < context->dispclk_khz) { @@ -1184,28 +1183,36 @@ val_ctx_fail: bool dc_post_update_surfaces_to_stream(struct dc *dc) { - struct core_dc *core_dc = DC_TO_CORE(dc); int i; + struct core_dc *core_dc = DC_TO_CORE(dc); + struct validate_context *context = dm_alloc(sizeof(struct validate_context)); + + if (!context) { + dm_error("%s: failed to create validate ctx\n", __func__); + return false; + } + resource_validate_ctx_copy_construct(core_dc->current_context, context); post_surface_trace(dc); - for (i = 0; i < core_dc->current_context->res_ctx.pool->pipe_count; i++) - if (core_dc->current_context->res_ctx.pipe_ctx[i].stream == NULL) { - core_dc->current_context->res_ctx.pipe_ctx[i].pipe_idx = i; + for (i = 0; i < context->res_ctx.pool->pipe_count; i++) + if (context->res_ctx.pipe_ctx[i].stream == NULL) { + context->res_ctx.pipe_ctx[i].pipe_idx = i; core_dc->hwss.power_down_front_end( - core_dc, &core_dc->current_context->res_ctx.pipe_ctx[i]); - } - if (core_dc->res_pool->funcs->validate_bandwidth) - if (core_dc->res_pool->funcs->validate_bandwidth( - core_dc, core_dc->current_context) != DC_OK) { - BREAK_TO_DEBUGGER(); - return false; + core_dc, &context->res_ctx.pipe_ctx[i]); } + if (!core_dc->res_pool->funcs->validate_bandwidth(core_dc, context)) { + BREAK_TO_DEBUGGER(); + return false; + } core_dc->hwss.set_bandwidth(core_dc); - pplib_apply_display_requirements( - core_dc, core_dc->current_context, &core_dc->current_context->pp_display_cfg); + /*TODO: dce specific*/ + pplib_apply_display_requirements(core_dc, context, &context->pp_display_cfg); + + resource_validate_ctx_destruct(core_dc->current_context); + core_dc->current_context = context; return true; } @@ -1472,6 +1479,11 @@ void dc_update_surfaces_for_stream(struct dc *dc, *(updates[i].hdr_static_metadata); } + if (update_type == UPDATE_TYPE_FULL && + !core_dc->res_pool->funcs->validate_bandwidth(core_dc, context)) { + BREAK_TO_DEBUGGER(); + return; + } if (!surface_count) /* reset */ core_dc->hwss.apply_ctx_for_surface(core_dc, NULL, context); diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 9ed7c06132fe..fc85efafb104 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -765,14 +765,14 @@ static enum dc_status validate_mapped_resource( return DC_OK; } -enum dc_status dce100_validate_bandwidth( +bool dce100_validate_bandwidth( const struct core_dc *dc, struct validate_context *context) { /* TODO implement when needed but for now hardcode max value*/ context->dispclk_khz = 681000; - return DC_OK; + return false; } static bool dce100_validate_surface_sets( @@ -840,7 +840,8 @@ enum dc_status dce100_validate_with_context( result = resource_build_scaling_params_for_context(dc, context); if (result == DC_OK) - result = dce100_validate_bandwidth(dc, context); + if (!dce100_validate_bandwidth(dc, context)) + result = DC_FAIL_BANDWIDTH_VALIDATE; return result; } @@ -873,7 +874,8 @@ enum dc_status dce100_validate_guaranteed( } if (result == DC_OK) - result = dce100_validate_bandwidth(dc, context); + if (!dce100_validate_bandwidth(dc, context)) + result = DC_FAIL_BANDWIDTH_VALIDATE; return result; } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 80b2359a3cb4..b9d0b5eeca13 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -912,30 +912,28 @@ static enum dc_status validate_mapped_resource( return DC_OK; } -enum dc_status dce110_validate_bandwidth( +bool dce110_validate_bandwidth( const struct core_dc *dc, struct validate_context *context) { - enum dc_status result = DC_ERROR_UNEXPECTED; + bool result = false; dm_logger_write( dc->ctx->logger, LOG_BANDWIDTH_CALCS, "%s: start", __func__); - if (!bw_calcs( + if (bw_calcs( dc->ctx, &dc->bw_dceip, &dc->bw_vbios, context->res_ctx.pipe_ctx, context->res_ctx.pool->pipe_count, &context->bw_results)) - result = DC_FAIL_BANDWIDTH_VALIDATE; - else - result = DC_OK; + result = true; context->dispclk_khz = context->bw_results.dispclk_khz; - if (result == DC_FAIL_BANDWIDTH_VALIDATE) + if (!result) dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_VALIDATION, "%s: %dx%d@%d Bandwidth validation failed!\n", __func__, @@ -1073,7 +1071,8 @@ enum dc_status dce110_validate_with_context( result = resource_build_scaling_params_for_context(dc, context); if (result == DC_OK) - result = dce110_validate_bandwidth(dc, context); + if (!dce110_validate_bandwidth(dc, context)) + result = DC_FAIL_BANDWIDTH_VALIDATE; return result; } @@ -1106,7 +1105,8 @@ enum dc_status dce110_validate_guaranteed( } if (result == DC_OK) - result = dce110_validate_bandwidth(dc, context); + if (!dce110_validate_bandwidth(dc, context)) + result = DC_FAIL_BANDWIDTH_VALIDATE; return result; } diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index ce6c69fd1041..32aa1b5bf1f9 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -836,30 +836,28 @@ static enum dc_status validate_mapped_resource( return DC_OK; } -enum dc_status dce112_validate_bandwidth( +bool dce112_validate_bandwidth( const struct core_dc *dc, struct validate_context *context) { - enum dc_status result = DC_ERROR_UNEXPECTED; + bool result = false; dm_logger_write( dc->ctx->logger, LOG_BANDWIDTH_CALCS, "%s: start", __func__); - if (!bw_calcs( + if (bw_calcs( dc->ctx, &dc->bw_dceip, &dc->bw_vbios, context->res_ctx.pipe_ctx, context->res_ctx.pool->pipe_count, &context->bw_results)) - result = DC_FAIL_BANDWIDTH_VALIDATE; - else - result = DC_OK; + result = true; context->dispclk_khz = context->bw_results.dispclk_khz; - if (result == DC_FAIL_BANDWIDTH_VALIDATE) + if (!result) dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_VALIDATION, "%s: Bandwidth validation failed!", __func__); @@ -1026,7 +1024,8 @@ enum dc_status dce112_validate_with_context( result = resource_build_scaling_params_for_context(dc, context); if (result == DC_OK) - result = dce112_validate_bandwidth(dc, context); + if (!dce112_validate_bandwidth(dc, context)) + result = DC_FAIL_BANDWIDTH_VALIDATE; return result; } @@ -1059,7 +1058,8 @@ enum dc_status dce112_validate_guaranteed( } if (result == DC_OK) - result = dce112_validate_bandwidth(dc, context); + if (!dce112_validate_bandwidth(dc, context)) + result = DC_FAIL_BANDWIDTH_VALIDATE; return result; } diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h index faa8c45a3544..dc842aace766 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h @@ -46,7 +46,7 @@ enum dc_status dce112_validate_guaranteed( const struct dc_stream *dc_stream, struct validate_context *context); -enum dc_status dce112_validate_bandwidth( +bool dce112_validate_bandwidth( const struct core_dc *dc, struct validate_context *context); diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index fbbdd0ee2d4c..a3e8182885b2 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -780,7 +780,7 @@ static enum dc_status validate_mapped_resource( return DC_OK; } -enum dc_status dce80_validate_bandwidth( +bool dce80_validate_bandwidth( const struct core_dc *dc, struct validate_context *context) { @@ -788,7 +788,7 @@ enum dc_status dce80_validate_bandwidth( context->dispclk_khz = 681000; context->bw_results.required_yclk = 250000 * MEMORY_TYPE_MULTIPLIER; - return DC_OK; + return true; } static bool dce80_validate_surface_sets( diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_status.h b/drivers/gpu/drm/amd/display/dc/inc/core_status.h index 23d52aea55dd..128617dabc4a 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_status.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_status.h @@ -41,7 +41,6 @@ enum dc_status { DC_SURFACE_PIXEL_FORMAT_UNSUPPORTED = 11, DC_FAIL_BANDWIDTH_VALIDATE = 12, /* BW and Watermark validation */ DC_FAIL_SCALING = 13, - DC_FAIL_CLK_CONSTRAINT = 14, DC_ERROR_UNEXPECTED = -1 }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 124df6795b34..e8fe333c5918 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -207,11 +207,7 @@ struct resource_funcs { const struct dc_stream *stream, struct validate_context *context); - enum dc_status (*validate_bandwidth)( - const struct core_dc *dc, - struct validate_context *context); - - struct validate_context *(*apply_clk_constraints)( + bool (*validate_bandwidth)( const struct core_dc *dc, struct validate_context *context); -- cgit From cf43759306002e29f025344504dc680a9a0b3ac8 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 22 Feb 2017 17:52:22 -0500 Subject: drm/amd/display: bandwidth update fix Signed-off-by: Dmytro Laktyushkin Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 173 +------------ .../amd/display/dc/dce100/dce100_hw_sequencer.c | 15 +- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 279 ++++++++++++--------- .../drm/amd/display/dc/dce80/dce80_hw_sequencer.c | 16 +- drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 9 +- 5 files changed, 179 insertions(+), 313 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index da0f72071ef5..0ec2c4f39735 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -795,159 +795,6 @@ static bool streams_changed( return false; } -static void fill_display_configs( - const struct validate_context *context, - struct dm_pp_display_configuration *pp_display_cfg) -{ - int j; - int num_cfgs = 0; - - for (j = 0; j < context->stream_count; j++) { - int k; - - const struct core_stream *stream = context->streams[j]; - struct dm_pp_single_disp_config *cfg = - &pp_display_cfg->disp_configs[num_cfgs]; - const struct pipe_ctx *pipe_ctx = NULL; - - for (k = 0; k < MAX_PIPES; k++) - if (stream == context->res_ctx.pipe_ctx[k].stream) { - pipe_ctx = &context->res_ctx.pipe_ctx[k]; - break; - } - - ASSERT(pipe_ctx != NULL); - - num_cfgs++; - cfg->signal = pipe_ctx->stream->signal; - cfg->pipe_idx = pipe_ctx->pipe_idx; - cfg->src_height = stream->public.src.height; - cfg->src_width = stream->public.src.width; - cfg->ddi_channel_mapping = - stream->sink->link->ddi_channel_mapping.raw; - cfg->transmitter = - stream->sink->link->link_enc->transmitter; - cfg->link_settings.lane_count = - stream->sink->link->public.cur_link_settings.lane_count; - cfg->link_settings.link_rate = - stream->sink->link->public.cur_link_settings.link_rate; - cfg->link_settings.link_spread = - stream->sink->link->public.cur_link_settings.link_spread; - cfg->sym_clock = stream->phy_pix_clk; - /* Round v_refresh*/ - cfg->v_refresh = stream->public.timing.pix_clk_khz * 1000; - cfg->v_refresh /= stream->public.timing.h_total; - cfg->v_refresh = (cfg->v_refresh + stream->public.timing.v_total / 2) - / stream->public.timing.v_total; - } - - pp_display_cfg->display_count = num_cfgs; -} - -static uint32_t get_min_vblank_time_us(const struct validate_context *context) -{ - uint8_t j; - uint32_t min_vertical_blank_time = -1; - - for (j = 0; j < context->stream_count; j++) { - const struct dc_stream *stream = &context->streams[j]->public; - uint32_t vertical_blank_in_pixels = 0; - uint32_t vertical_blank_time = 0; - - vertical_blank_in_pixels = stream->timing.h_total * - (stream->timing.v_total - - stream->timing.v_addressable); - - vertical_blank_time = vertical_blank_in_pixels - * 1000 / stream->timing.pix_clk_khz; - - if (min_vertical_blank_time > vertical_blank_time) - min_vertical_blank_time = vertical_blank_time; - } - - return min_vertical_blank_time; -} - -static int determine_sclk_from_bounding_box( - const struct core_dc *dc, - int required_sclk) -{ - int i; - - /* - * Some asics do not give us sclk levels, so we just report the actual - * required sclk - */ - if (dc->sclk_lvls.num_levels == 0) - return required_sclk; - - for (i = 0; i < dc->sclk_lvls.num_levels; i++) { - if (dc->sclk_lvls.clocks_in_khz[i] >= required_sclk) - return dc->sclk_lvls.clocks_in_khz[i]; - } - /* - * even maximum level could not satisfy requirement, this - * is unexpected at this stage, should have been caught at - * validation time - */ - ASSERT(0); - return dc->sclk_lvls.clocks_in_khz[dc->sclk_lvls.num_levels - 1]; -} - -void pplib_apply_display_requirements( - struct core_dc *dc, - const struct validate_context *context, - struct dm_pp_display_configuration *pp_display_cfg) -{ - pp_display_cfg->all_displays_in_sync = - context->bw_results.all_displays_in_sync; - pp_display_cfg->nb_pstate_switch_disable = - context->bw_results.nbp_state_change_enable == false; - pp_display_cfg->cpu_cc6_disable = - context->bw_results.cpuc_state_change_enable == false; - pp_display_cfg->cpu_pstate_disable = - context->bw_results.cpup_state_change_enable == false; - pp_display_cfg->cpu_pstate_separation_time = - context->bw_results.blackout_recovery_time_us; - - pp_display_cfg->min_memory_clock_khz = context->bw_results.required_yclk - / MEMORY_TYPE_MULTIPLIER; - - pp_display_cfg->min_engine_clock_khz = determine_sclk_from_bounding_box( - dc, - context->bw_results.required_sclk); - - pp_display_cfg->min_engine_clock_deep_sleep_khz - = context->bw_results.required_sclk_deep_sleep; - - pp_display_cfg->avail_mclk_switch_time_us = - get_min_vblank_time_us(context); - /* TODO: dce11.2*/ - pp_display_cfg->avail_mclk_switch_time_in_disp_active_us = 0; - - pp_display_cfg->disp_clk_khz = context->dispclk_khz; - - fill_display_configs(context, pp_display_cfg); - - /* TODO: is this still applicable?*/ - if (pp_display_cfg->display_count == 1) { - const struct dc_crtc_timing *timing = - &context->streams[0]->public.timing; - - pp_display_cfg->crtc_index = - pp_display_cfg->disp_configs[0].pipe_idx; - pp_display_cfg->line_time_in_us = timing->h_total * 1000 - / timing->pix_clk_khz; - } - - if (memcmp(&dc->prev_display_config, pp_display_cfg, sizeof( - struct dm_pp_display_configuration)) != 0) - dm_pp_apply_display_requirements(dc->ctx, pp_display_cfg); - - dc->prev_display_config = *pp_display_cfg; - -} - bool dc_commit_streams( struct dc *dc, const struct dc_stream *streams[], @@ -1036,9 +883,6 @@ bool dc_commit_streams( context->streams[i]->public.timing.pix_clk_khz); } - pplib_apply_display_requirements(core_dc, - context, &context->pp_display_cfg); - resource_validate_ctx_destruct(core_dc->current_context); if (core_dc->temp_flip_context != core_dc->current_context) { @@ -1065,7 +909,6 @@ bool dc_pre_update_surfaces_to_stream( { int i, j; struct core_dc *core_dc = DC_TO_CORE(dc); - int prev_disp_clk = core_dc->current_context->dispclk_khz; struct dc_stream_status *stream_status = NULL; struct validate_context *context; bool ret = true; @@ -1150,16 +993,7 @@ bool dc_pre_update_surfaces_to_stream( goto unexpected_fail; } - if (!IS_FPGA_MAXIMUS_DC(core_dc->ctx->dce_environment) - && prev_disp_clk < context->dispclk_khz) { - pplib_apply_display_requirements(core_dc, context, - &context->pp_display_cfg); - context->res_ctx.pool->display_clock->funcs->set_clock( - context->res_ctx.pool->display_clock, - context->dispclk_khz * 115 / 100); - core_dc->current_context->bw_results.dispclk_khz = context->dispclk_khz; - core_dc->current_context->dispclk_khz = context->dispclk_khz; - } + core_dc->hwss.set_bandwidth(core_dc, context, false); for (i = 0; i < new_surface_count; i++) for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { @@ -1206,10 +1040,7 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) return false; } - core_dc->hwss.set_bandwidth(core_dc); - - /*TODO: dce specific*/ - pplib_apply_display_requirements(core_dc, context, &context->pp_display_cfg); + core_dc->hwss.set_bandwidth(core_dc, context, true); resource_validate_ctx_destruct(core_dc->current_context); core_dc->current_context = context; diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c index e2fe024e1182..bd8e19f1038b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c @@ -104,22 +104,18 @@ static bool dce100_enable_display_power_gating( return false; } -static void set_display_mark_for_pipe_if_needed(struct core_dc *dc, - struct pipe_ctx *pipe_ctx, - struct validate_context *context) -{ - /* Do nothing until we have proper bandwitdth calcs */ -} - static void set_displaymarks( const struct core_dc *dc, struct validate_context *context) { /* Do nothing until we have proper bandwitdth calcs */ } -static void set_bandwidth(struct core_dc *dc) +static void set_bandwidth( + struct core_dc *dc, + struct validate_context *context, + bool decrease_allowed) { - /* Do nothing until we have proper bandwitdth calcs */ + dc->hwss.set_displaymarks(dc, context); } @@ -132,7 +128,6 @@ bool dce100_hw_sequencer_construct(struct core_dc *dc) /* TODO: dce80 is empty implementation at the moment*/ dc->hwss.enable_display_power_gating = dce100_enable_display_power_gating; dc->hwss.set_displaymarks = set_displaymarks; - dc->hwss.increase_watermarks_for_pipe = set_display_mark_for_pipe_if_needed; dc->hwss.set_bandwidth = set_bandwidth; return true; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 2d2daa694a30..d9dcb37a4f65 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1209,93 +1209,6 @@ static uint32_t compute_pstate_blackout_duration( return total_dest_line_time_ns; } -/* get the index of the pipe_ctx if there were no gaps in the pipe_ctx array*/ -int get_bw_result_idx( - struct resource_context *res_ctx, - int pipe_idx) -{ - int i, collapsed_idx; - - if (res_ctx->pipe_ctx[pipe_idx].top_pipe) - return 3; - - collapsed_idx = 0; - for (i = 0; i < pipe_idx; i++) { - if (res_ctx->pipe_ctx[i].stream) - collapsed_idx++; - } - - return collapsed_idx; -} - -static bool is_watermark_set_a_greater( - const struct bw_watermarks *set_a, - const struct bw_watermarks *set_b) -{ - if (set_a->a_mark > set_b->a_mark - || set_a->b_mark > set_b->b_mark - || set_a->c_mark > set_b->c_mark - || set_a->d_mark > set_b->d_mark) - return true; - return false; -} - -static bool did_watermarks_increase( - struct pipe_ctx *pipe_ctx, - struct validate_context *context, - struct validate_context *old_context) -{ - int collapsed_pipe_idx = get_bw_result_idx(&context->res_ctx, - pipe_ctx->pipe_idx); - int old_collapsed_pipe_idx = get_bw_result_idx(&old_context->res_ctx, - pipe_ctx->pipe_idx); - struct pipe_ctx *old_pipe_ctx = &old_context->res_ctx.pipe_ctx[pipe_ctx->pipe_idx]; - - if (!old_pipe_ctx->stream) - return true; - - if (is_watermark_set_a_greater( - &context->bw_results.nbp_state_change_wm_ns[collapsed_pipe_idx], - &old_context->bw_results.nbp_state_change_wm_ns[old_collapsed_pipe_idx])) - return true; - if (is_watermark_set_a_greater( - &context->bw_results.stutter_exit_wm_ns[collapsed_pipe_idx], - &old_context->bw_results.stutter_exit_wm_ns[old_collapsed_pipe_idx])) - return true; - if (is_watermark_set_a_greater( - &context->bw_results.urgent_wm_ns[collapsed_pipe_idx], - &old_context->bw_results.urgent_wm_ns[old_collapsed_pipe_idx])) - return true; - - return false; -} - -static void program_wm_for_pipe(struct core_dc *dc, - struct pipe_ctx *pipe_ctx, - struct validate_context *context) -{ - int total_dest_line_time_ns = compute_pstate_blackout_duration( - dc->bw_vbios.blackout_duration, - pipe_ctx->stream); - int bw_result_idx = get_bw_result_idx(&context->res_ctx, - pipe_ctx->pipe_idx); - - pipe_ctx->mi->funcs->mem_input_program_display_marks( - pipe_ctx->mi, - context->bw_results.nbp_state_change_wm_ns[bw_result_idx], - context->bw_results.stutter_exit_wm_ns[bw_result_idx], - context->bw_results.urgent_wm_ns[bw_result_idx], - total_dest_line_time_ns); - - if (pipe_ctx->top_pipe) - pipe_ctx->mi->funcs->mem_input_program_chroma_display_marks( - pipe_ctx->mi, - context->bw_results.nbp_state_change_wm_ns[bw_result_idx + 1], - context->bw_results.stutter_exit_wm_ns[bw_result_idx + 1], - context->bw_results.urgent_wm_ns[bw_result_idx + 1], - total_dest_line_time_ns); -} - void dce110_set_displaymarks( const struct core_dc *dc, struct validate_context *context) @@ -1589,7 +1502,7 @@ static void reset_hw_ctx_wrap( } } -/*TODO: const validate_context*/ + enum dc_status dce110_apply_ctx_to_hw( struct core_dc *dc, struct validate_context *context) @@ -1768,7 +1681,7 @@ enum dc_status dce110_apply_ctx_to_hw( return status; } - dc->hwss.set_displaymarks(dc, context); + dc->hwss.set_bandwidth(dc, context, true); /* to save power */ apply_min_clocks(dc, context, &clocks_state, false); @@ -1777,6 +1690,7 @@ enum dc_status dce110_apply_ctx_to_hw( switch_dp_clock_sources(dc, &context->res_ctx); + return DC_OK; } @@ -2135,7 +2049,6 @@ static void init_hw(struct core_dc *dc) } } -/* TODO: move this to apply_ctx_tohw some how?*/ static void dce110_power_on_pipe_if_needed( struct core_dc *dc, struct pipe_ctx *pipe_ctx, @@ -2180,31 +2093,175 @@ static void dce110_power_on_pipe_if_needed( } } -static void dce110_increase_watermarks_for_pipe( - struct core_dc *dc, - struct pipe_ctx *pipe_ctx, - struct validate_context *context) +static void fill_display_configs( + const struct validate_context *context, + struct dm_pp_display_configuration *pp_display_cfg) +{ + int j; + int num_cfgs = 0; + + for (j = 0; j < context->stream_count; j++) { + int k; + + const struct core_stream *stream = context->streams[j]; + struct dm_pp_single_disp_config *cfg = + &pp_display_cfg->disp_configs[num_cfgs]; + const struct pipe_ctx *pipe_ctx = NULL; + + for (k = 0; k < MAX_PIPES; k++) + if (stream == context->res_ctx.pipe_ctx[k].stream) { + pipe_ctx = &context->res_ctx.pipe_ctx[k]; + break; + } + + ASSERT(pipe_ctx != NULL); + + num_cfgs++; + cfg->signal = pipe_ctx->stream->signal; + cfg->pipe_idx = pipe_ctx->pipe_idx; + cfg->src_height = stream->public.src.height; + cfg->src_width = stream->public.src.width; + cfg->ddi_channel_mapping = + stream->sink->link->ddi_channel_mapping.raw; + cfg->transmitter = + stream->sink->link->link_enc->transmitter; + cfg->link_settings.lane_count = + stream->sink->link->public.cur_link_settings.lane_count; + cfg->link_settings.link_rate = + stream->sink->link->public.cur_link_settings.link_rate; + cfg->link_settings.link_spread = + stream->sink->link->public.cur_link_settings.link_spread; + cfg->sym_clock = stream->phy_pix_clk; + /* Round v_refresh*/ + cfg->v_refresh = stream->public.timing.pix_clk_khz * 1000; + cfg->v_refresh /= stream->public.timing.h_total; + cfg->v_refresh = (cfg->v_refresh + stream->public.timing.v_total / 2) + / stream->public.timing.v_total; + } + + pp_display_cfg->display_count = num_cfgs; +} + +static uint32_t get_min_vblank_time_us(const struct validate_context *context) { - if (did_watermarks_increase(pipe_ctx, context, dc->current_context)) - program_wm_for_pipe(dc, pipe_ctx, context); + uint8_t j; + uint32_t min_vertical_blank_time = -1; + + for (j = 0; j < context->stream_count; j++) { + const struct dc_stream *stream = &context->streams[j]->public; + uint32_t vertical_blank_in_pixels = 0; + uint32_t vertical_blank_time = 0; + + vertical_blank_in_pixels = stream->timing.h_total * + (stream->timing.v_total + - stream->timing.v_addressable); + + vertical_blank_time = vertical_blank_in_pixels + * 1000 / stream->timing.pix_clk_khz; + + if (min_vertical_blank_time > vertical_blank_time) + min_vertical_blank_time = vertical_blank_time; + } + + return min_vertical_blank_time; } -static void dce110_set_bandwidth(struct core_dc *dc) +static int determine_sclk_from_bounding_box( + const struct core_dc *dc, + int required_sclk) { int i; - for (i = 0; i < dc->current_context->res_ctx.pool->pipe_count; i++) { - struct pipe_ctx *pipe_ctx = &dc->current_context->res_ctx.pipe_ctx[i]; + /* + * Some asics do not give us sclk levels, so we just report the actual + * required sclk + */ + if (dc->sclk_lvls.num_levels == 0) + return required_sclk; - if (!pipe_ctx->stream) - continue; + for (i = 0; i < dc->sclk_lvls.num_levels; i++) { + if (dc->sclk_lvls.clocks_in_khz[i] >= required_sclk) + return dc->sclk_lvls.clocks_in_khz[i]; + } + /* + * even maximum level could not satisfy requirement, this + * is unexpected at this stage, should have been caught at + * validation time + */ + ASSERT(0); + return dc->sclk_lvls.clocks_in_khz[dc->sclk_lvls.num_levels - 1]; +} + +static void pplib_apply_display_requirements( + struct core_dc *dc, + struct validate_context *context) +{ + struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg; + + pp_display_cfg->all_displays_in_sync = + context->bw_results.all_displays_in_sync; + pp_display_cfg->nb_pstate_switch_disable = + context->bw_results.nbp_state_change_enable == false; + pp_display_cfg->cpu_cc6_disable = + context->bw_results.cpuc_state_change_enable == false; + pp_display_cfg->cpu_pstate_disable = + context->bw_results.cpup_state_change_enable == false; + pp_display_cfg->cpu_pstate_separation_time = + context->bw_results.blackout_recovery_time_us; + + pp_display_cfg->min_memory_clock_khz = context->bw_results.required_yclk + / MEMORY_TYPE_MULTIPLIER; + + pp_display_cfg->min_engine_clock_khz = determine_sclk_from_bounding_box( + dc, + context->bw_results.required_sclk); + + pp_display_cfg->min_engine_clock_deep_sleep_khz + = context->bw_results.required_sclk_deep_sleep; + + pp_display_cfg->avail_mclk_switch_time_us = + get_min_vblank_time_us(context); + /* TODO: dce11.2*/ + pp_display_cfg->avail_mclk_switch_time_in_disp_active_us = 0; - program_wm_for_pipe(dc, pipe_ctx, dc->current_context); + pp_display_cfg->disp_clk_khz = context->dispclk_khz; + + fill_display_configs(context, pp_display_cfg); + + /* TODO: is this still applicable?*/ + if (pp_display_cfg->display_count == 1) { + const struct dc_crtc_timing *timing = + &context->streams[0]->public.timing; + + pp_display_cfg->crtc_index = + pp_display_cfg->disp_configs[0].pipe_idx; + pp_display_cfg->line_time_in_us = timing->h_total * 1000 + / timing->pix_clk_khz; + } + + if (memcmp(&dc->prev_display_config, pp_display_cfg, sizeof( + struct dm_pp_display_configuration)) != 0) + dm_pp_apply_display_requirements(dc->ctx, pp_display_cfg); + + dc->prev_display_config = *pp_display_cfg; +} + +static void dce110_set_bandwidth( + struct core_dc *dc, + struct validate_context *context, + bool decrease_allowed) +{ + dc->hwss.set_displaymarks(dc, context); + + if (decrease_allowed || context->dispclk_khz > dc->current_context->dispclk_khz) { + context->res_ctx.pool->display_clock->funcs->set_clock( + context->res_ctx.pool->display_clock, + context->dispclk_khz * 115 / 100); + dc->current_context->bw_results.dispclk_khz = context->dispclk_khz; + dc->current_context->dispclk_khz = context->dispclk_khz; } - dc->current_context->res_ctx.pool->display_clock->funcs->set_clock( - dc->current_context->res_ctx.pool->display_clock, - dc->current_context->dispclk_khz * 115 / 100); + pplib_apply_display_requirements(dc, context); } static void dce110_program_front_end_for_pipe( @@ -2335,15 +2392,6 @@ static void dce110_program_front_end_for_pipe( pipe_ctx->scl_data.recout.y); } -static void dce110_prepare_pipe_for_context( - struct core_dc *dc, - struct pipe_ctx *pipe_ctx, - struct validate_context *context) -{ - dce110_power_on_pipe_if_needed(dc, pipe_ctx, context); - dc->hwss.increase_watermarks_for_pipe(dc, pipe_ctx, context); -} - static void dce110_apply_ctx_for_surface( struct core_dc *dc, struct core_surface *surface, @@ -2388,7 +2436,7 @@ static void dce110_power_down_fe(struct core_dc *dc, struct pipe_ctx *pipe) static const struct hw_sequencer_funcs dce110_funcs = { .init_hw = init_hw, .apply_ctx_to_hw = dce110_apply_ctx_to_hw, - .prepare_pipe_for_context = dce110_prepare_pipe_for_context, + .prepare_pipe_for_context = dce110_power_on_pipe_if_needed, .apply_ctx_for_surface = dce110_apply_ctx_for_surface, .set_plane_config = set_plane_config, .update_plane_addr = update_plane_addr, @@ -2407,7 +2455,6 @@ static const struct hw_sequencer_funcs dce110_funcs = { .power_down_front_end = dce110_power_down_fe, .pipe_control_lock = dce_pipe_control_lock, .set_displaymarks = dce110_set_displaymarks, - .increase_watermarks_for_pipe = dce110_increase_watermarks_for_pipe, .set_bandwidth = dce110_set_bandwidth, .set_drr = set_drr, .set_static_screen_control = set_static_screen_control, diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c index c7a2b768bcd1..85a54d963f8d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c @@ -106,23 +106,18 @@ static bool dce80_enable_display_power_gating( return false; } - -static void set_display_mark_for_pipe_if_needed(struct core_dc *dc, - struct pipe_ctx *pipe_ctx, - struct validate_context *context) -{ - /* Do nothing until we have proper bandwitdth calcs */ -} - static void set_displaymarks( const struct core_dc *dc, struct validate_context *context) { /* Do nothing until we have proper bandwitdth calcs */ } -static void set_bandwidth(struct core_dc *dc) +static void set_bandwidth( + struct core_dc *dc, + struct validate_context *context, + bool decrease_allowed) { - /* Do nothing until we have proper bandwitdth calcs */ + dc->hwss.set_displaymarks(dc, context); } @@ -133,7 +128,6 @@ bool dce80_hw_sequencer_construct(struct core_dc *dc) dc->hwss.enable_display_power_gating = dce80_enable_display_power_gating; dc->hwss.pipe_control_lock = dce_pipe_control_lock; dc->hwss.set_displaymarks = set_displaymarks; - dc->hwss.increase_watermarks_for_pipe = set_display_mark_for_pipe_if_needed; dc->hwss.set_bandwidth = set_bandwidth; return true; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 758a568589bb..7b780c610631 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -124,11 +124,10 @@ struct hw_sequencer_funcs { const struct core_dc *dc, struct validate_context *context); - void (*increase_watermarks_for_pipe)(struct core_dc *dc, - struct pipe_ctx *pipe_ctx, - struct validate_context *context); - - void (*set_bandwidth)(struct core_dc *dc); + void (*set_bandwidth)( + struct core_dc *dc, + struct validate_context *context, + bool decrease_allowed); void (*set_drr)(struct pipe_ctx **pipe_ctx, int num_pipes, int vmin, int vmax); -- cgit From ce9c088051e198b19eb533b24c605b7cedbe5b9c Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 22 Feb 2017 18:14:52 -0500 Subject: drm/amd/display: move visual confirm recout adjustment to scaler Signed-off-by: Dmytro Laktyushkin Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 9 --------- drivers/gpu/drm/amd/display/dc/dce/dce_transform.c | 6 ++++++ drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c | 6 ++++++ 3 files changed, 12 insertions(+), 9 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 0ec2c4f39735..852932aec436 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -980,11 +980,6 @@ bool dc_pre_update_surfaces_to_stream( resource_build_scaling_params( new_surfaces[i], &context->res_ctx.pipe_ctx[j]); - - if (dc->debug.surface_visual_confirm) { - context->res_ctx.pipe_ctx[j].scl_data.recout.height -= 2; - context->res_ctx.pipe_ctx[j].scl_data.recout.width -= 2; - } } if (!core_dc->res_pool->funcs->validate_bandwidth(core_dc, context)) { @@ -1267,10 +1262,6 @@ void dc_update_surfaces_for_stream(struct dc *dc, continue; resource_build_scaling_params(updates[i].surface, pipe_ctx); - if (dc->debug.surface_visual_confirm) { - pipe_ctx->scl_data.recout.height -= 2; - pipe_ctx->scl_data.recout.width -= 2; - } } } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c index d8ffbff9a268..c861fd7b5767 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c @@ -27,6 +27,7 @@ #include "reg_helper.h" #include "opp.h" #include "basics/conversion.h" +#include "dc.h" #define REG(reg) \ (xfm_dce->regs->reg) @@ -121,6 +122,11 @@ static void program_overscan( int overscan_bottom = data->v_active - data->recout.y - data->recout.height; + if (xfm_dce->base.ctx->dc->debug.surface_visual_confirm) { + overscan_bottom += 2; + overscan_right += 2; + } + if (overscan_right < 0) { BREAK_TO_DEBUGGER(); overscan_right = 0; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c index feb5f3c29804..28963996693c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c @@ -25,6 +25,7 @@ #include "dce110_transform_v.h" #include "dm_services.h" +#include "dc.h" #include "dce/dce_11_0_d.h" #include "dce/dce_11_0_sh_mask.h" @@ -232,6 +233,11 @@ static void program_overscan( int overscan_right = data->h_active - data->recout.x - data->recout.width; int overscan_bottom = data->v_active - data->recout.y - data->recout.height; + if (xfm_dce->base.ctx->dc->debug.surface_visual_confirm) { + overscan_bottom += 2; + overscan_right += 2; + } + if (overscan_right < 0) { BREAK_TO_DEBUGGER(); overscan_right = 0; -- cgit From c2e218dda078f4e8d09d2493b01a7e256cfe38aa Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Fri, 24 Feb 2017 16:25:51 -0500 Subject: drm/amd/display: Some more warning fixes This doesn't show with gcc6 Signed-off-by: Harry Wentland Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 2 +- drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 8eb6b342a49d..d275fc88f71e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -928,7 +928,7 @@ static bool construct( { uint8_t i; struct gpio *hpd_gpio = NULL; - struct ddc_service_init_data ddc_service_init_data = { 0 }; + struct ddc_service_init_data ddc_service_init_data = { { 0 } }; struct dc_context *dc_ctx = init_params->ctx; struct encoder_init_data enc_init_data = { 0 }; struct integrated_info info = {{{ 0 }}}; 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 6fe5acbc16ca..37efa40a9bca 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 @@ -1762,7 +1762,7 @@ bool dc_link_handle_hpd_rx_irq(const struct dc_link *dc_link) { struct core_link *link = DC_LINK_TO_LINK(dc_link); union hpd_irq_data hpd_irq_dpcd_data = {{{{0}}}}; - union device_service_irq device_service_clear = {0}; + union device_service_irq device_service_clear = { { 0 } }; enum dc_status result = DDC_RESULT_UNKNOWN; bool status = false; /* For use cases related to down stream connection status change, diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c index dd922bdcc145..3e3eefea3e82 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c @@ -393,8 +393,8 @@ static void dce_clock_read_integrated_info(struct dce_disp_clk *clk_dce) { struct dc_debug *debug = &clk_dce->base.ctx->dc->debug; struct dc_bios *bp = clk_dce->base.ctx->dc_bios; - struct integrated_info info = { 0 }; - struct firmware_info fw_info = { 0 }; + struct integrated_info info = { { { 0 } } }; + struct firmware_info fw_info = { { 0 } }; int i; if (bp->integrated_info) @@ -456,7 +456,7 @@ static void dce_clock_read_ss_info(struct dce_disp_clk *clk_dce) bp, AS_SIGNAL_TYPE_GPU_PLL); if (ss_info_num) { - struct spread_spectrum_info info = { 0 }; + struct spread_spectrum_info info = { { 0 } }; enum bp_result result = bp->funcs->get_spread_spectrum_info( bp, AS_SIGNAL_TYPE_GPU_PLL, 0, &info); -- cgit From 3853c184ed9a258e2d720f98ef77112625300e36 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Tue, 28 Feb 2017 16:14:10 -0500 Subject: drm/amd/display: fix dce100_validate_bandwidth return value Signed-off-by: Dmytro Laktyushkin Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index fc85efafb104..c72858a1452f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -772,7 +772,7 @@ bool dce100_validate_bandwidth( /* TODO implement when needed but for now hardcode max value*/ context->dispclk_khz = 681000; - return false; + return true; } static bool dce100_validate_surface_sets( -- cgit From a49dcb88e8159b12d1af5f67d657388c4a1c96cb Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 12 Jan 2017 09:09:08 -0500 Subject: drm/amd/display: Use amdgpu mode funcs statically No need to assign them dynamically. This is much more readable. Signed-off-by: Harry Wentland Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') 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 d0706e550e84..21dcd6caf628 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -28,6 +28,7 @@ #include "vid.h" #include "amdgpu.h" +#include "amdgpu_display.h" #include "atom.h" #include "amdgpu_dm.h" #include "amdgpu_dm_types.h" @@ -715,6 +716,8 @@ const struct amdgpu_ip_block_version dm_ip_block = /* TODO: it is temporary non-const, should fixed later */ static struct drm_mode_config_funcs amdgpu_dm_mode_funcs = { + .fb_create = amdgpu_user_framebuffer_create, + .output_poll_changed = amdgpu_output_poll_changed, .atomic_check = amdgpu_dm_atomic_check, .atomic_commit = amdgpu_dm_atomic_commit }; @@ -1088,11 +1091,6 @@ static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev) adev->mode_info.mode_config_initialized = true; - amdgpu_dm_mode_funcs.fb_create = - amdgpu_mode_funcs.fb_create; - amdgpu_dm_mode_funcs.output_poll_changed = - amdgpu_mode_funcs.output_poll_changed; - adev->ddev->mode_config.funcs = (void *)&amdgpu_dm_mode_funcs; adev->ddev->mode_config.max_width = 16384; -- cgit From e7738c8a50ea426a57184ef2275b8163ab79febe Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 17 Jan 2017 20:24:03 -0500 Subject: drm/amd/display: Remove unused define from amdgpu_dm_types Signed-off-by: Harry Wentland Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h index 6ed1480a8bc3..4faa1659f7f9 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h @@ -59,11 +59,6 @@ int amdgpu_dm_atomic_commit( int amdgpu_dm_atomic_check(struct drm_device *dev, struct drm_atomic_state *state); -int dm_create_validation_set_for_stream( - struct drm_connector *connector, - struct drm_display_mode *mode, - struct dc_validation_set *val_set); - void amdgpu_dm_connector_funcs_reset(struct drm_connector *connector); struct drm_connector_state *amdgpu_dm_connector_atomic_duplicate_state( struct drm_connector *connector); -- cgit From f0828115efa0406fbe0010b1d8c9c965fc718733 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Tue, 28 Feb 2017 15:23:38 -0500 Subject: drm/amd/display: freesync pipe split :VTotal_Min_Mask for Hflip/lock. Signed-off-by: Charlene Liu Acked-by: Harry Wentland Reviewed-by: Jordan Lazare Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 40 +++++++++++++++------- drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c | 21 +++++++----- drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h | 15 ++------ drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 20 ++++++++--- .../drm/amd/display/include/hw_sequencer_types.h | 1 + 5 files changed, 59 insertions(+), 38 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 852932aec436..66a5b2745501 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1178,6 +1178,7 @@ void dc_update_surfaces_for_stream(struct dc *dc, enum surface_update_type update_type; const struct dc_stream_status *stream_status; + unsigned int lock_mask = 0; stream_status = dc_stream_get_status(dc_stream); ASSERT(stream_status); @@ -1313,6 +1314,23 @@ void dc_update_surfaces_for_stream(struct dc *dc, for (i = 0; i < surface_count; i++) { struct core_surface *surface = DC_SURFACE_TO_CORE(updates[i].surface); + for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; + if (pipe_ctx->surface != surface) + continue; + /*lock all the MCPP if blnd is enable for DRR*/ + if ((update_type == UPDATE_TYPE_FAST && + (dc_stream->freesync_ctx.enabled == true && + surface_count != context->res_ctx.pool->pipe_count)) && + !pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) { + lock_mask = PIPE_LOCK_CONTROL_MPCC_ADDR; + core_dc->hwss.pipe_control_lock( + core_dc, + pipe_ctx, + lock_mask, + true); + } + } for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; struct pipe_ctx *cur_pipe_ctx; @@ -1320,16 +1338,16 @@ void dc_update_surfaces_for_stream(struct dc *dc, if (pipe_ctx->surface != surface) continue; - if (update_type != UPDATE_TYPE_FAST && !pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) { - core_dc->hwss.pipe_control_lock( - core_dc->hwseq, - pipe_ctx->pipe_idx, - PIPE_LOCK_CONTROL_GRAPHICS | + lock_mask = PIPE_LOCK_CONTROL_GRAPHICS | PIPE_LOCK_CONTROL_SCL | PIPE_LOCK_CONTROL_BLENDER | - PIPE_LOCK_CONTROL_MODE, + PIPE_LOCK_CONTROL_MODE; + core_dc->hwss.pipe_control_lock( + core_dc, + pipe_ctx, + lock_mask, true); } @@ -1371,7 +1389,7 @@ void dc_update_surfaces_for_stream(struct dc *dc, } } - if (update_type == UPDATE_TYPE_FAST) + if (update_type == UPDATE_TYPE_FAST && (lock_mask == 0)) return; for (i = context->res_ctx.pool->pipe_count - 1; i >= 0; i--) { @@ -1381,11 +1399,9 @@ void dc_update_surfaces_for_stream(struct dc *dc, if (updates[j].surface == &pipe_ctx->surface->public) { if (!pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) { core_dc->hwss.pipe_control_lock( - core_dc->hwseq, - pipe_ctx->pipe_idx, - PIPE_LOCK_CONTROL_GRAPHICS | - PIPE_LOCK_CONTROL_SCL | - PIPE_LOCK_CONTROL_BLENDER, + core_dc, + pipe_ctx, + lock_mask, false); } break; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c index 8eb755620c48..1e1d60af8306 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c @@ -26,6 +26,7 @@ #include "dce_hwseq.h" #include "reg_helper.h" #include "hw_sequencer.h" +#include "core_dc.h" #define CTX \ hws->ctx @@ -43,15 +44,17 @@ void dce_enable_fe_clock(struct dce_hwseq *hws, DCFE_CLOCK_ENABLE, enable); } -void dce_pipe_control_lock(struct dce_hwseq *hws, - unsigned int blnd_inst, +void dce_pipe_control_lock(struct core_dc *dc, + struct pipe_ctx *pipe, enum pipe_lock_control control_mask, bool lock) { uint32_t lock_val = lock ? 1 : 0; - uint32_t dcp_grph, scl, blnd, update_lock_mode; - - uint32_t val = REG_GET_4(BLND_V_UPDATE_LOCK[blnd_inst], + uint32_t dcp_grph, scl, blnd, update_lock_mode, val; + struct dce_hwseq *hws = dc->hwseq; + if (control_mask & PIPE_LOCK_CONTROL_MPCC_ADDR) + return; + val = REG_GET_4(BLND_V_UPDATE_LOCK[pipe->pipe_idx], BLND_DCP_GRPH_V_UPDATE_LOCK, &dcp_grph, BLND_SCL_V_UPDATE_LOCK, &scl, BLND_BLND_V_UPDATE_LOCK, &blnd, @@ -70,19 +73,19 @@ void dce_pipe_control_lock(struct dce_hwseq *hws, update_lock_mode = lock_val; - REG_SET_2(BLND_V_UPDATE_LOCK[blnd_inst], val, + REG_SET_2(BLND_V_UPDATE_LOCK[pipe->pipe_idx], val, BLND_DCP_GRPH_V_UPDATE_LOCK, dcp_grph, BLND_SCL_V_UPDATE_LOCK, scl); if (hws->masks->BLND_BLND_V_UPDATE_LOCK != 0) - REG_SET_2(BLND_V_UPDATE_LOCK[blnd_inst], val, + REG_SET_2(BLND_V_UPDATE_LOCK[pipe->pipe_idx], val, BLND_BLND_V_UPDATE_LOCK, blnd, BLND_V_UPDATE_LOCK_MODE, update_lock_mode); if (hws->wa.blnd_crtc_trigger) { if (!lock && (control_mask & PIPE_LOCK_CONTROL_BLENDER)) { - uint32_t value = REG_READ(CRTC_H_BLANK_START_END[blnd_inst]); - REG_WRITE(CRTC_H_BLANK_START_END[blnd_inst], value); + uint32_t value = REG_READ(CRTC_H_BLANK_START_END[pipe->pipe_idx]); + REG_WRITE(CRTC_H_BLANK_START_END[pipe->pipe_idx], value); } } } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index 4af8d560a7ee..9ef618443255 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -212,17 +212,6 @@ struct dce_hwseq_mask { HWSEQ_REG_FIED_LIST(uint32_t) }; -struct dce_hwseq_wa { - bool blnd_crtc_trigger; -}; - -struct dce_hwseq { - struct dc_context *ctx; - const struct dce_hwseq_registers *regs; - const struct dce_hwseq_shift *shifts; - const struct dce_hwseq_mask *masks; - struct dce_hwseq_wa wa; -}; enum blnd_mode { BLND_MODE_CURRENT_PIPE = 0,/* Data from current pipe only */ @@ -233,8 +222,8 @@ enum blnd_mode { void dce_enable_fe_clock(struct dce_hwseq *hwss, unsigned int inst, bool enable); -void dce_pipe_control_lock(struct dce_hwseq *hws, - unsigned int blnd_inst, +void dce_pipe_control_lock(struct core_dc *dc, + struct pipe_ctx *pipe, enum pipe_lock_control control_mask, bool lock); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 7b780c610631..a902de52107f 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -38,10 +38,22 @@ enum pipe_lock_control { PIPE_LOCK_CONTROL_GRAPHICS = 1 << 0, PIPE_LOCK_CONTROL_BLENDER = 1 << 1, PIPE_LOCK_CONTROL_SCL = 1 << 2, - PIPE_LOCK_CONTROL_MODE = 1 << 3 + PIPE_LOCK_CONTROL_MODE = 1 << 3, + PIPE_LOCK_CONTROL_MPCC_ADDR = 1 << 4 +}; + +struct dce_hwseq_wa { + bool blnd_crtc_trigger; +}; + +struct dce_hwseq { + struct dc_context *ctx; + const struct dce_hwseq_registers *regs; + const struct dce_hwseq_shift *shifts; + const struct dce_hwseq_mask *masks; + struct dce_hwseq_wa wa; }; -struct dce_hwseq; struct hw_sequencer_funcs { @@ -115,8 +127,8 @@ struct hw_sequencer_funcs { struct dc_link_settings *link_settings); void (*pipe_control_lock)( - struct dce_hwseq *hwseq, - unsigned int blnd_inst, + struct core_dc *dc, + struct pipe_ctx *pipe, enum pipe_lock_control control_mask, bool lock); diff --git a/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h b/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h index 6f0475c25566..065a91a7002f 100644 --- a/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h +++ b/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h @@ -38,6 +38,7 @@ struct drr_params { /* defines the maximum possible vertical dimension of display timing * for CRTC as supported by the panel */ uint32_t vertical_total_max; + bool immediate_flip; }; #endif -- cgit From 67a277055b98e998c34d311cc956f809a0f92504 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 16 Feb 2017 10:37:00 -0500 Subject: drm/amd/display: We don't support interlace and doublescan Don't tell DRM otherwise. Signed-off-by: Harry Wentland Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 862bbd745bb9..008c7a55e992 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -1851,8 +1851,9 @@ void amdgpu_dm_connector_init_helper( aconnector->connector_id = link_index; aconnector->dc_link = link; - aconnector->base.interlace_allowed = true; - aconnector->base.doublescan_allowed = true; + aconnector->base.interlace_allowed = false; + aconnector->base.doublescan_allowed = false; + aconnector->base.stereo_allowed = false; aconnector->base.dpms = DRM_MODE_DPMS_OFF; aconnector->hpd.hpd = AMDGPU_HPD_NONE; /* not used */ -- cgit From 92a65e32ade943135a6e48ec756661c0896392d0 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Tue, 28 Feb 2017 19:49:15 -0500 Subject: drm/amd/display: extended the programming sequence to VFlip as well Signed-off-by: Charlene Liu Acked-by: Harry Wentland Reviewed-by: Charlene Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 66a5b2745501..efe50fd2be78 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1316,6 +1316,9 @@ void dc_update_surfaces_for_stream(struct dc *dc, for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; + struct pipe_ctx *cur_pipe_ctx; + bool is_new_pipe_surface = true; + if (pipe_ctx->surface != surface) continue; /*lock all the MCPP if blnd is enable for DRR*/ @@ -1324,26 +1327,16 @@ void dc_update_surfaces_for_stream(struct dc *dc, surface_count != context->res_ctx.pool->pipe_count)) && !pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) { lock_mask = PIPE_LOCK_CONTROL_MPCC_ADDR; - core_dc->hwss.pipe_control_lock( - core_dc, - pipe_ctx, - lock_mask, - true); - } } - for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - struct pipe_ctx *cur_pipe_ctx; - bool is_new_pipe_surface = true; - if (pipe_ctx->surface != surface) - continue; if (update_type != UPDATE_TYPE_FAST && !pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) { lock_mask = PIPE_LOCK_CONTROL_GRAPHICS | PIPE_LOCK_CONTROL_SCL | PIPE_LOCK_CONTROL_BLENDER | PIPE_LOCK_CONTROL_MODE; + } + if (lock_mask != 0) { core_dc->hwss.pipe_control_lock( core_dc, pipe_ctx, @@ -1389,7 +1382,7 @@ void dc_update_surfaces_for_stream(struct dc *dc, } } - if (update_type == UPDATE_TYPE_FAST && (lock_mask == 0)) + if ((update_type == UPDATE_TYPE_FAST) && lock_mask == 0) return; for (i = context->res_ctx.pool->pipe_count - 1; i >= 0; i--) { -- cgit From 54f5499a54fe671c56012684d5a68efbb4fe0b53 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Thu, 20 Apr 2017 15:57:05 -0400 Subject: drm/amd/display: Refactor atomic commit implementation. (v2) Modify amdgpu_dm_atomic_comit to implement atomic_comit_tail hook. Unify Buffer objects allocation and dealocation for surface updates and page flips. Simplify wait for fences and target_vbank logic for non blockiing commit. Remove hacky update surface to page flip synchronization we had and rely on atomic framework synchronization logic. v2: Add state->allow_modeset as indicator of page flip call. Signed-off-by: Andrey Grodzovsky Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 58 +++- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 343 ++++++++++----------- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.h | 7 +- 3 files changed, 203 insertions(+), 205 deletions(-) (limited to 'drivers/gpu') 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 21dcd6caf628..da499ab7eab5 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -149,7 +149,6 @@ static struct amdgpu_crtc *get_crtc_by_otg_inst( static void dm_pflip_high_irq(void *interrupt_params) { - struct amdgpu_flip_work *works; struct amdgpu_crtc *amdgpu_crtc; struct common_irq_params *irq_params = interrupt_params; struct amdgpu_device *adev = irq_params->adev; @@ -165,7 +164,6 @@ static void dm_pflip_high_irq(void *interrupt_params) } spin_lock_irqsave(&adev->ddev->event_lock, flags); - works = amdgpu_crtc->pflip_works; if (amdgpu_crtc->pflip_status != AMDGPU_FLIP_SUBMITTED){ DRM_DEBUG_DRIVER("amdgpu_crtc->pflip_status = %d !=AMDGPU_FLIP_SUBMITTED(%d) on crtc:%d[%p] \n", @@ -177,22 +175,24 @@ static void dm_pflip_high_irq(void *interrupt_params) return; } - /* page flip completed. clean up */ - amdgpu_crtc->pflip_status = AMDGPU_FLIP_NONE; - amdgpu_crtc->pflip_works = NULL; /* wakeup usersapce */ - if (works->event) - drm_crtc_send_vblank_event(&amdgpu_crtc->base, - works->event); + if (amdgpu_crtc->event + && amdgpu_crtc->event->event.base.type + == DRM_EVENT_FLIP_COMPLETE) { + drm_crtc_send_vblank_event(&amdgpu_crtc->base, amdgpu_crtc->event); + /* page flip completed. clean up */ + amdgpu_crtc->event = NULL; + } else + WARN_ON(1); + amdgpu_crtc->pflip_status = AMDGPU_FLIP_NONE; spin_unlock_irqrestore(&adev->ddev->event_lock, flags); - DRM_DEBUG_DRIVER("%s - crtc :%d[%p], pflip_stat:AMDGPU_FLIP_NONE, work: %p,\n", - __func__, amdgpu_crtc->crtc_id, amdgpu_crtc, works); + DRM_DEBUG_DRIVER("%s - crtc :%d[%p], pflip_stat:AMDGPU_FLIP_NONE\n", + __func__, amdgpu_crtc->crtc_id, amdgpu_crtc); drm_crtc_vblank_put(&amdgpu_crtc->base); - schedule_work(&works->unpin_work); } static void dm_crtc_high_irq(void *interrupt_params) @@ -719,7 +719,11 @@ static struct drm_mode_config_funcs amdgpu_dm_mode_funcs = { .fb_create = amdgpu_user_framebuffer_create, .output_poll_changed = amdgpu_output_poll_changed, .atomic_check = amdgpu_dm_atomic_check, - .atomic_commit = amdgpu_dm_atomic_commit + .atomic_commit = drm_atomic_helper_commit +}; + +static struct drm_mode_config_helper_funcs amdgpu_dm_mode_config_helperfuncs = { + .atomic_commit_tail = amdgpu_dm_atomic_commit_tail }; void amdgpu_dm_update_connector_after_detect( @@ -1092,6 +1096,7 @@ static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev) adev->mode_info.mode_config_initialized = true; adev->ddev->mode_config.funcs = (void *)&amdgpu_dm_mode_funcs; + adev->ddev->mode_config.helper_private = &amdgpu_dm_mode_config_helperfuncs; adev->ddev->mode_config.max_width = 16384; adev->ddev->mode_config.max_height = 16384; @@ -1345,6 +1350,14 @@ static void dm_page_flip(struct amdgpu_device *adev, acrtc = adev->mode_info.crtcs[crtc_id]; stream = acrtc->stream; + + if (acrtc->pflip_status != AMDGPU_FLIP_NONE) { + DRM_ERROR("flip queue: acrtc %d, already busy\n", acrtc->crtc_id); + /* In commit tail framework this cannot happen */ + BUG_ON(0); + } + + /* * Received a page flip call after the display has been reset. * Just return in this case. Everything should be clean-up on reset. @@ -1359,15 +1372,28 @@ static void dm_page_flip(struct amdgpu_device *adev, addr.address.grph.addr.high_part = upper_32_bits(crtc_base); addr.flip_immediate = async; + + if (acrtc->base.state->event && + acrtc->base.state->event->event.base.type == + DRM_EVENT_FLIP_COMPLETE) { + acrtc->event = acrtc->base.state->event; + + /* Set the flip status */ + acrtc->pflip_status = AMDGPU_FLIP_SUBMITTED; + + /* Mark this event as consumed */ + acrtc->base.state->event = NULL; + } + + dc_flip_surface_addrs(adev->dm.dc, + dc_stream_get_status(stream)->surfaces, + &addr, 1); + DRM_DEBUG_DRIVER("%s Flipping to hi: 0x%x, low: 0x%x \n", __func__, addr.address.grph.addr.high_part, addr.address.grph.addr.low_part); - dc_flip_surface_addrs( - adev->dm.dc, - dc_stream_get_status(stream)->surfaces, - &addr, 1); } static int amdgpu_notify_freesync(struct drm_device *dev, void *data, diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 008c7a55e992..956ff5a7b9b6 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -687,8 +687,18 @@ static void dm_dc_surface_commit( { struct dc_surface *dc_surface; const struct dc_surface *dc_surfaces[1]; - const struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); const struct dc_stream *dc_stream = acrtc->stream; + unsigned long flags; + + spin_lock_irqsave(&crtc->dev->event_lock, flags); + if (acrtc->pflip_status != AMDGPU_FLIP_NONE) { + DRM_ERROR("dm_dc_surface_commit: acrtc %d, already busy\n", acrtc->crtc_id); + spin_unlock_irqrestore(&crtc->dev->event_lock, flags); + /* In comit tail framework this cannot happen */ + BUG_ON(0); + } + spin_unlock_irqrestore(&crtc->dev->event_lock, flags); if (!dc_stream) { dm_error( @@ -1427,6 +1437,7 @@ static void clear_unrelated_fields(struct drm_plane_state *state) state->fence = NULL; } +/*TODO update because event is always present now */ static bool page_flip_needed( const struct drm_plane_state *new_state, const struct drm_plane_state *old_state, @@ -1482,11 +1493,13 @@ static bool page_flip_needed( page_flip_required = memcmp(&old_state_tmp, &new_state_tmp, sizeof(old_state_tmp)) == 0 ? true:false; + if (new_state->crtc && page_flip_required == false) { acrtc_new = to_amdgpu_crtc(new_state->crtc); if (acrtc_new->flip_flags & DRM_MODE_PAGE_FLIP_ASYNC) page_flip_required = true; } + return page_flip_required; } @@ -1512,7 +1525,7 @@ static int dm_plane_helper_prepare_fb( if (unlikely(r != 0)) return r; - r = amdgpu_bo_pin(rbo, AMDGPU_GEM_DOMAIN_VRAM, NULL); + r = amdgpu_bo_pin(rbo, AMDGPU_GEM_DOMAIN_VRAM, &afb->address); amdgpu_bo_unreserve(rbo); @@ -1521,6 +1534,7 @@ static int dm_plane_helper_prepare_fb( return r; } + amdgpu_bo_ref(rbo); return 0; } @@ -1544,7 +1558,10 @@ static void dm_plane_helper_cleanup_fb( } else { amdgpu_bo_unpin(rbo); amdgpu_bo_unreserve(rbo); + amdgpu_bo_unref(&rbo); } + + afb->address = 0; } int dm_create_validation_set_for_connector(struct drm_connector *connector, @@ -2135,51 +2152,6 @@ static enum dm_commit_action get_dm_commit_action(struct drm_crtc_state *state) } } - -typedef bool (*predicate)(struct amdgpu_crtc *acrtc); - -static void wait_while_pflip_status(struct amdgpu_device *adev, - struct amdgpu_crtc *acrtc, predicate f) { - int count = 0; - while (f(acrtc)) { - /* Spin Wait*/ - msleep(1); - count++; - if (count == 1000) { - DRM_ERROR("%s - crtc:%d[%p], pflip_stat:%d, probable hang!\n", - __func__, acrtc->crtc_id, - acrtc, - acrtc->pflip_status); - - /* we do not expect to hit this case except on Polaris with PHY PLL - * 1. DP to HDMI passive dongle connected - * 2. unplug (headless) - * 3. plug in DP - * 3a. on plug in, DP will try verify link by training, and training - * would disable PHY PLL which HDMI rely on to drive TG - * 3b. this will cause flip interrupt cannot be generated, and we - * exit when timeout expired. however we do not have code to clean - * up flip, flip clean up will happen when the address is written - * with the restore mode change - */ - WARN_ON(1); - break; - } - } - - DRM_DEBUG_DRIVER("%s - Finished waiting for:%d msec, crtc:%d[%p], pflip_stat:%d \n", - __func__, - count, - acrtc->crtc_id, - acrtc, - acrtc->pflip_status); -} - -static bool pflip_in_progress_predicate(struct amdgpu_crtc *acrtc) -{ - return acrtc->pflip_status != AMDGPU_FLIP_NONE; -} - static void manage_dm_interrupts( struct amdgpu_device *adev, struct amdgpu_crtc *acrtc, @@ -2201,8 +2173,6 @@ static void manage_dm_interrupts( &adev->pageflip_irq, irq_type); } else { - wait_while_pflip_status(adev, acrtc, - pflip_in_progress_predicate); amdgpu_irq_put( adev, @@ -2212,12 +2182,6 @@ static void manage_dm_interrupts( } } - -static bool pflip_pending_predicate(struct amdgpu_crtc *acrtc) -{ - return acrtc->pflip_status == AMDGPU_FLIP_PENDING; -} - static bool is_scaling_state_different( const struct dm_connector_state *dm_state, const struct dm_connector_state *old_dm_state) @@ -2255,116 +2219,94 @@ static void remove_stream(struct amdgpu_device *adev, struct amdgpu_crtc *acrtc) acrtc->enabled = false; } -int amdgpu_dm_atomic_commit( - struct drm_device *dev, - struct drm_atomic_state *state, - bool nonblock) + +/* + * Executes flip + * + * Waits on all BO's fences and for proper vblank count + */ +static void amdgpu_dm_do_flip( + struct drm_crtc *crtc, + struct drm_framebuffer *fb, + uint32_t target) +{ + unsigned long flags; + uint32_t target_vblank; + int r, vpos, hpos; + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + struct amdgpu_framebuffer *afb = to_amdgpu_framebuffer(fb); + struct amdgpu_bo *abo = gem_to_amdgpu_bo(afb->obj); + struct amdgpu_device *adev = crtc->dev->dev_private; + bool async_flip = (acrtc->flip_flags & DRM_MODE_PAGE_FLIP_ASYNC) != 0; + + + /*TODO This might fail and hence better not used, wait + * explicitly on fences instead + * and in general should be called for + * blocking commit to as per framework helpers + * */ + r = amdgpu_bo_reserve(abo, true); + if (unlikely(r != 0)) { + DRM_ERROR("failed to reserve buffer before flip\n"); + BUG_ON(0); + } + + /* Wait for all fences on this FB */ + WARN_ON(reservation_object_wait_timeout_rcu(abo->tbo.resv, true, false, + MAX_SCHEDULE_TIMEOUT) < 0); + + amdgpu_bo_unreserve(abo); + + /* Wait for target vblank */ + /* Wait until we're out of the vertical blank period before the one + * targeted by the flip + */ + target_vblank = target - drm_crtc_vblank_count(crtc) + + amdgpu_get_vblank_counter_kms(crtc->dev, acrtc->crtc_id); + + while ((acrtc->enabled && + (amdgpu_get_crtc_scanoutpos(adev->ddev, acrtc->crtc_id, 0, + &vpos, &hpos, NULL, NULL, + &crtc->hwmode) + & (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_IN_VBLANK)) == + (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_IN_VBLANK) && + (int)(target_vblank - + amdgpu_get_vblank_counter_kms(adev->ddev, acrtc->crtc_id)) > 0)) { + usleep_range(1000, 1100); + } + + /* Flip */ + spin_lock_irqsave(&crtc->dev->event_lock, flags); + /* update crtc fb */ + crtc->primary->fb = fb; + + /* Do the flip (mmio) */ + adev->mode_info.funcs->page_flip(adev, acrtc->crtc_id, afb->address, async_flip); + + spin_unlock_irqrestore(&crtc->dev->event_lock, flags); + DRM_DEBUG_DRIVER("crtc:%d, pflip_stat:AMDGPU_FLIP_SUBMITTED\n", + acrtc->crtc_id); +} + +void amdgpu_dm_atomic_commit_tail( + struct drm_atomic_state *state) { + struct drm_device *dev = state->dev; struct amdgpu_device *adev = dev->dev_private; struct amdgpu_display_manager *dm = &adev->dm; struct drm_plane *plane; - struct drm_plane_state *new_plane_state; struct drm_plane_state *old_plane_state; uint32_t i; - int32_t ret = 0; uint32_t commit_streams_count = 0; uint32_t new_crtcs_count = 0; - uint32_t flip_crtcs_count = 0; struct drm_crtc *crtc; struct drm_crtc_state *old_crtc_state; const struct dc_stream *commit_streams[MAX_STREAMS]; struct amdgpu_crtc *new_crtcs[MAX_STREAMS]; const struct dc_stream *new_stream; - struct drm_crtc *flip_crtcs[MAX_STREAMS]; - struct amdgpu_flip_work *work[MAX_STREAMS] = {0}; - struct amdgpu_bo *new_abo[MAX_STREAMS] = {0}; - - /* In this step all new fb would be pinned */ - - /* - * TODO: Revisit when we support true asynchronous commit. - * Right now we receive async commit only from pageflip, in which case - * we should not pin/unpin the fb here, it should be done in - * amdgpu_crtc_flip and from the vblank irq handler. - */ - if (!nonblock) { - ret = drm_atomic_helper_prepare_planes(dev, state); - if (ret) - return ret; - } - - /* Page flip if needed */ - for_each_plane_in_state(state, plane, new_plane_state, i) { - struct drm_plane_state *old_plane_state = plane->state; - struct drm_crtc *crtc = new_plane_state->crtc; - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - struct drm_framebuffer *fb = new_plane_state->fb; - struct drm_crtc_state *crtc_state; + unsigned long flags; + bool wait_for_vblank = true; - if (!fb || !crtc) - continue; - - crtc_state = drm_atomic_get_crtc_state(state, crtc); - - if (!crtc_state->planes_changed || !crtc_state->active) - continue; - - if (page_flip_needed( - new_plane_state, - old_plane_state, - crtc_state->event, - false)) { - ret = amdgpu_crtc_prepare_flip(crtc, - fb, - crtc_state->event, - acrtc->flip_flags, - drm_crtc_vblank_count(crtc), - &work[flip_crtcs_count], - &new_abo[flip_crtcs_count]); - - if (ret) { - /* According to atomic_commit hook API, EINVAL is not allowed */ - if (unlikely(ret == -EINVAL)) - ret = -ENOMEM; - - DRM_ERROR("Atomic commit: Flip for crtc id %d: [%p], " - "failed, errno = %d\n", - acrtc->crtc_id, - acrtc, - ret); - /* cleanup all flip configurations which - * succeeded in this commit - */ - for (i = 0; i < flip_crtcs_count; i++) - amdgpu_crtc_cleanup_flip_ctx( - work[i], - new_abo[i]); - - return ret; - } - - flip_crtcs[flip_crtcs_count] = crtc; - flip_crtcs_count++; - } - } - - /* - * This is the point of no return - everything below never fails except - * when the hw goes bonghits. Which means we can commit the new state on - * the software side now. - */ - - drm_atomic_helper_swap_state(state, true); - - /* - * From this point state become old state really. New state is - * initialized to appropriate objects and could be accessed from there - */ - - /* - * there is no fences usage yet in state. We can skip the following line - * wait_for_fences(dev, state); - */ drm_atomic_helper_update_legacy_modeset_state(dev, state); @@ -2520,11 +2462,11 @@ int amdgpu_dm_atomic_commit( for_each_plane_in_state(state, plane, old_plane_state, i) { struct drm_plane_state *plane_state = plane->state; struct drm_crtc *crtc = plane_state->crtc; - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); struct drm_framebuffer *fb = plane_state->fb; struct drm_connector *connector; struct dm_connector_state *dm_state = NULL; enum dm_commit_action action; + bool pflip_needed; if (!fb || !crtc || !crtc->state->active) continue; @@ -2535,12 +2477,14 @@ int amdgpu_dm_atomic_commit( * 1. This commit is not a page flip. * 2. This commit is a page flip, and streams are created. */ - if (!page_flip_needed( + pflip_needed = !state->allow_modeset && + page_flip_needed( plane_state, old_plane_state, - crtc->state->event, true) || - action == DM_COMMIT_ACTION_DPMS_ON || - action == DM_COMMIT_ACTION_SET) { + crtc->state->event, true); + if (!pflip_needed || + action == DM_COMMIT_ACTION_DPMS_ON || + action == DM_COMMIT_ACTION_SET) { list_for_each_entry(connector, &dev->mode_config.connector_list, head) { if (connector->state->crtc == crtc) { @@ -2567,14 +2511,6 @@ int amdgpu_dm_atomic_commit( if (!dm_state) continue; - /* - * if flip is pending (ie, still waiting for fence to return - * before address is submitted) here, we cannot commit_surface - * as commit_surface will pre-maturely write out the future - * address. wait until flip is submitted before proceeding. - */ - wait_while_pflip_status(adev, acrtc, pflip_pending_predicate); - dm_dc_surface_commit(dm->dc, crtc); } } @@ -2594,43 +2530,77 @@ int amdgpu_dm_atomic_commit( } - /* Do actual flip */ - flip_crtcs_count = 0; for_each_plane_in_state(state, plane, old_plane_state, i) { struct drm_plane_state *plane_state = plane->state; struct drm_crtc *crtc = plane_state->crtc; struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); struct drm_framebuffer *fb = plane_state->fb; + bool pflip_needed; if (!fb || !crtc || !crtc->state->planes_changed || !crtc->state->active) continue; - - if (page_flip_needed( + pflip_needed = !state->allow_modeset && + page_flip_needed( plane_state, old_plane_state, crtc->state->event, - false)) { - amdgpu_crtc_submit_flip( - crtc, - fb, - work[flip_crtcs_count], - new_abo[i]); - flip_crtcs_count++; + false); + + if (pflip_needed) { + amdgpu_dm_do_flip( + crtc, + fb, + drm_crtc_vblank_count(crtc)); + + wait_for_vblank = + acrtc->flip_flags & DRM_MODE_PAGE_FLIP_ASYNC ? + false : true; /*clean up the flags for next usage*/ acrtc->flip_flags = 0; } } - /* In this state all old framebuffers would be unpinned */ - /* TODO: Revisit when we support true asynchronous commit.*/ - if (!nonblock) - drm_atomic_helper_cleanup_planes(dev, state); + /*TODO mark consumed event on all crtc assigned event + * in drm_atomic_helper_setup_commit just to signal completion + */ + spin_lock_irqsave(&adev->ddev->event_lock, flags); + for_each_crtc_in_state(state, crtc, old_crtc_state, i) { + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + + if (acrtc->base.state->event && + acrtc->base.state->event->event.base.type != DRM_EVENT_FLIP_COMPLETE) { + acrtc->event = acrtc->base.state->event; + acrtc->base.state->event = NULL; + } + } + spin_unlock_irqrestore(&adev->ddev->event_lock, flags); + + /* Signal HW programming completion */ + drm_atomic_helper_commit_hw_done(state); + + if (wait_for_vblank) + drm_atomic_helper_wait_for_vblanks(dev, state); + + /*TODO send vblank event on all crtc assigned event + * in drm_atomic_helper_setup_commit just to signal completion + */ + spin_lock_irqsave(&adev->ddev->event_lock, flags); + for_each_crtc_in_state(state, crtc, old_crtc_state, i) { + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - drm_atomic_state_put(state); + if (acrtc->event && + acrtc->event->event.base.type != DRM_EVENT_FLIP_COMPLETE) { + drm_send_event_locked(dev, &acrtc->event->base); + acrtc->event = NULL; + } + } + spin_unlock_irqrestore(&adev->ddev->event_lock, flags); - return ret; + /*TODO Is it to early if actual flip haven't happened yet ?*/ + /* Release old FB */ + drm_atomic_helper_cleanup_planes(dev, state); } /* * This functions handle all cases when set mode does not come upon hotplug. @@ -2982,6 +2952,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, struct dm_connector_state *dm_state = NULL; enum dm_commit_action action; struct drm_crtc_state *crtc_state; + bool pflip_needed; if (!fb || !crtc || crtc_set[i] != crtc || @@ -2995,10 +2966,12 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, * 2. This commit is a page flip, and streams are created. */ crtc_state = drm_atomic_get_crtc_state(state, crtc); - if (!page_flip_needed(plane_state, old_plane_state, - crtc_state->event, true) || - action == DM_COMMIT_ACTION_DPMS_ON || - action == DM_COMMIT_ACTION_SET) { + pflip_needed = !state->allow_modeset && + page_flip_needed(plane_state, old_plane_state, + crtc_state->event, true); + if (!pflip_needed || + action == DM_COMMIT_ACTION_DPMS_ON || + action == DM_COMMIT_ACTION_SET) { struct dc_surface *surface; list_for_each_entry(connector, diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h index 4faa1659f7f9..1bbeb87dc9d0 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h @@ -52,10 +52,9 @@ void amdgpu_dm_encoder_destroy(struct drm_encoder *encoder); int amdgpu_dm_connector_get_modes(struct drm_connector *connector); -int amdgpu_dm_atomic_commit( - struct drm_device *dev, - struct drm_atomic_state *state, - bool async); +void amdgpu_dm_atomic_commit_tail( + struct drm_atomic_state *state); + int amdgpu_dm_atomic_check(struct drm_device *dev, struct drm_atomic_state *state); -- cgit From 5f42aa394e50e4993ec370aca4bb36c3b6a81a60 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Wed, 13 Sep 2017 15:17:19 -0400 Subject: Revert "drm/amdgpu: Pulling old prepare and submit for flip back" This reverts commit 0eb4667a073e. Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 138 ++++++---------------------- drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 15 --- 2 files changed, 29 insertions(+), 124 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index b1079930630e..138beb550a58 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -138,52 +138,11 @@ static void amdgpu_unpin_work_func(struct work_struct *__work) kfree(work); } - -static void amdgpu_flip_work_cleanup(struct amdgpu_flip_work *work) -{ - int i; - - amdgpu_bo_unref(&work->old_abo); - dma_fence_put(work->excl); - for (i = 0; i < work->shared_count; ++i) - dma_fence_put(work->shared[i]); - kfree(work->shared); - kfree(work); -} - -static void amdgpu_flip_cleanup_unreserve(struct amdgpu_flip_work *work, - struct amdgpu_bo *new_abo) -{ - amdgpu_bo_unreserve(new_abo); - amdgpu_flip_work_cleanup(work); -} - -static void amdgpu_flip_cleanup_unpin(struct amdgpu_flip_work *work, - struct amdgpu_bo *new_abo) -{ - if (unlikely(amdgpu_bo_unpin(new_abo) != 0)) - DRM_ERROR("failed to unpin new abo in error path\n"); - amdgpu_flip_cleanup_unreserve(work, new_abo); -} - -void amdgpu_crtc_cleanup_flip_ctx(struct amdgpu_flip_work *work, - struct amdgpu_bo *new_abo) -{ - if (unlikely(amdgpu_bo_reserve(new_abo, true) != 0)) { - DRM_ERROR("failed to reserve new abo in error path\n"); - amdgpu_flip_work_cleanup(work); - return; - } - amdgpu_flip_cleanup_unpin(work, new_abo); -} - -int amdgpu_crtc_prepare_flip(struct drm_crtc *crtc, - struct drm_framebuffer *fb, - struct drm_pending_vblank_event *event, - uint32_t page_flip_flags, - uint32_t target, - struct amdgpu_flip_work **work_p, - struct amdgpu_bo **new_abo_p) +int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + struct drm_pending_vblank_event *event, + uint32_t page_flip_flags, uint32_t target, + struct drm_modeset_acquire_ctx *ctx) { struct drm_device *dev = crtc->dev; struct amdgpu_device *adev = dev->dev_private; @@ -196,7 +155,7 @@ int amdgpu_crtc_prepare_flip(struct drm_crtc *crtc, unsigned long flags; u64 tiling_flags; u64 base; - int r; + int i, r; work = kzalloc(sizeof *work, GFP_KERNEL); if (work == NULL) @@ -257,80 +216,41 @@ int amdgpu_crtc_prepare_flip(struct drm_crtc *crtc, spin_unlock_irqrestore(&crtc->dev->event_lock, flags); r = -EBUSY; goto pflip_cleanup; - } - spin_unlock_irqrestore(&crtc->dev->event_lock, flags); - - *work_p = work; - *new_abo_p = new_abo; - - return 0; - -pflip_cleanup: - amdgpu_crtc_cleanup_flip_ctx(work, new_abo); - return r; - -unpin: - amdgpu_flip_cleanup_unpin(work, new_abo); - return r; - -unreserve: - amdgpu_flip_cleanup_unreserve(work, new_abo); - return r; -cleanup: - amdgpu_flip_work_cleanup(work); - return r; - -} - -void amdgpu_crtc_submit_flip(struct drm_crtc *crtc, - struct drm_framebuffer *fb, - struct amdgpu_flip_work *work, - struct amdgpu_bo *new_abo) -{ - unsigned long flags; - struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); - - spin_lock_irqsave(&crtc->dev->event_lock, flags); amdgpu_crtc->pflip_status = AMDGPU_FLIP_PENDING; amdgpu_crtc->pflip_works = work; + + DRM_DEBUG_DRIVER("crtc:%d[%p], pflip_stat:AMDGPU_FLIP_PENDING, work: %p,\n", + amdgpu_crtc->crtc_id, amdgpu_crtc, work); /* update crtc fb */ crtc->primary->fb = fb; spin_unlock_irqrestore(&crtc->dev->event_lock, flags); - - DRM_DEBUG_DRIVER( - "crtc:%d[%p], pflip_stat:AMDGPU_FLIP_PENDING, work: %p,\n", - amdgpu_crtc->crtc_id, amdgpu_crtc, work); - amdgpu_flip_work_func(&work->flip_work.work); -} - -int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc, - struct drm_framebuffer *fb, - struct drm_pending_vblank_event *event, - uint32_t page_flip_flags, - uint32_t target, - struct drm_modeset_acquire_ctx *ctx) -{ - struct amdgpu_bo *new_abo; - struct amdgpu_flip_work *work; - int r; + return 0; - r = amdgpu_crtc_prepare_flip(crtc, - fb, - event, - page_flip_flags, - target, - &work, - &new_abo); - if (r) - return r; +pflip_cleanup: + if (unlikely(amdgpu_bo_reserve(new_abo, false) != 0)) { + DRM_ERROR("failed to reserve new abo in error path\n"); + goto cleanup; + } +unpin: + if (unlikely(amdgpu_bo_unpin(new_abo) != 0)) { + DRM_ERROR("failed to unpin new abo in error path\n"); + } +unreserve: + amdgpu_bo_unreserve(new_abo); - amdgpu_crtc_submit_flip(crtc, fb, work, new_abo); +cleanup: + amdgpu_bo_unref(&work->old_abo); + dma_fence_put(work->excl); + for (i = 0; i < work->shared_count; ++i) + dma_fence_put(work->shared[i]); + kfree(work->shared); + kfree(work); - return 0; + return r; } int amdgpu_crtc_set_config(struct drm_mode_set *set, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index 813108eab6fc..e5d2ce48cb1e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -670,21 +670,6 @@ int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc, struct drm_pending_vblank_event *event, uint32_t page_flip_flags, uint32_t target, struct drm_modeset_acquire_ctx *ctx); -void amdgpu_crtc_cleanup_flip_ctx(struct amdgpu_flip_work *work, - struct amdgpu_bo *new_abo); -int amdgpu_crtc_prepare_flip(struct drm_crtc *crtc, - struct drm_framebuffer *fb, - struct drm_pending_vblank_event *event, - uint32_t page_flip_flags, - uint32_t target, - struct amdgpu_flip_work **work, - struct amdgpu_bo **new_abo); - -void amdgpu_crtc_submit_flip(struct drm_crtc *crtc, - struct drm_framebuffer *fb, - struct amdgpu_flip_work *work, - struct amdgpu_bo *new_abo); - extern const struct drm_mode_config_funcs amdgpu_mode_funcs; #endif -- cgit From 92cc37fba0b54091b4dde4bced52c1b94d44e11f Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Sun, 5 Feb 2017 21:48:19 -0500 Subject: drm/amd/display: Refactor headless to use atomic commit. (v2) Headless mode set needs to be synchronized against outstanding nonblocking commits. This achieved by building atomic state and commiting it. v2: rebase on 4.11 Signed-off-by: Andrey Grodzovsky Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 140 +++++++++------------ 1 file changed, 61 insertions(+), 79 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 956ff5a7b9b6..cfc86bc5dd2b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2602,6 +2602,65 @@ void amdgpu_dm_atomic_commit_tail( /* Release old FB */ drm_atomic_helper_cleanup_planes(dev, state); } + + +static int dm_force_atomic_commit(struct drm_connector *connector) +{ + int ret = 0; + struct drm_device *ddev = connector->dev; + struct drm_atomic_state *state = drm_atomic_state_alloc(ddev); + struct amdgpu_crtc *disconnected_acrtc = to_amdgpu_crtc(connector->encoder->crtc); + struct drm_plane *plane = disconnected_acrtc->base.primary; + struct drm_connector_state *conn_state; + struct drm_crtc_state *crtc_state; + struct drm_plane_state *plane_state; + + if (!state) + return -ENOMEM; + + state->acquire_ctx = ddev->mode_config.acquire_ctx; + + /* Construct an atomic state to restore previous display setting */ + + /* + * Attach connectors to drm_atomic_state + */ + conn_state = drm_atomic_get_connector_state(state, connector); + + ret = PTR_ERR_OR_ZERO(conn_state); + if (ret) + goto err; + + /* Attach crtc to drm_atomic_state*/ + crtc_state = drm_atomic_get_crtc_state(state, &disconnected_acrtc->base); + + ret = PTR_ERR_OR_ZERO(crtc_state); + if (ret) + goto err; + + /* force a restore */ + crtc_state->mode_changed = true; + + /* Attach plane to drm_atomic_state */ + plane_state = drm_atomic_get_plane_state(state, plane); + + ret = PTR_ERR_OR_ZERO(plane_state); + if (ret) + goto err; + + + /* Call commit internally with the state we just constructed */ + ret = drm_atomic_commit(state); + if (!ret) + return 0; + +err: + DRM_ERROR("Restoring old state failed with %i\n", ret); + drm_atomic_state_put(state); + + return ret; +} + /* * This functions handle all cases when set mode does not come upon hotplug. * This include when the same display is unplugged then plugged back into the @@ -2609,15 +2668,8 @@ void amdgpu_dm_atomic_commit_tail( */ void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector *connector) { - struct drm_crtc *crtc; - struct amdgpu_device *adev = dev->dev_private; - struct dc *dc = adev->dm.dc; struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); struct amdgpu_crtc *disconnected_acrtc; - const struct dc_sink *sink; - const struct dc_stream *commit_streams[MAX_STREAMS]; - const struct dc_stream *current_stream; - uint32_t commit_streams_count = 0; if (!aconnector->dc_sink || !connector->state || !connector->encoder) return; @@ -2627,83 +2679,13 @@ void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector if (!disconnected_acrtc || !disconnected_acrtc->stream) return; - sink = disconnected_acrtc->stream->sink; - /* * If the previous sink is not released and different from the current, * we deduce we are in a state where we can not rely on usermode call * to turn on the display, so we do it here */ - if (sink != aconnector->dc_sink) { - struct dm_connector_state *dm_state = - to_dm_connector_state(aconnector->base.state); - - struct dc_stream *new_stream = - create_stream_for_sink( - aconnector, - &disconnected_acrtc->base.state->mode, - dm_state); - - DRM_INFO("Headless hotplug, restoring connector state\n"); - /* - * we evade vblanks and pflips on crtc that - * should be changed - */ - manage_dm_interrupts(adev, disconnected_acrtc, false); - /* this is the update mode case */ - - current_stream = disconnected_acrtc->stream; - - disconnected_acrtc->stream = new_stream; - disconnected_acrtc->enabled = true; - disconnected_acrtc->hw_mode = disconnected_acrtc->base.state->mode; - - commit_streams_count = 0; - - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - - if (acrtc->stream) { - commit_streams[commit_streams_count] = acrtc->stream; - ++commit_streams_count; - } - } - - /* DC is optimized not to do anything if 'streams' didn't change. */ - if (!dc_commit_streams(dc, commit_streams, - commit_streams_count)) { - DRM_INFO("Failed to restore connector state!\n"); - dc_stream_release(disconnected_acrtc->stream); - disconnected_acrtc->stream = current_stream; - manage_dm_interrupts(adev, disconnected_acrtc, true); - return; - } - - if (adev->dm.freesync_module) { - mod_freesync_remove_stream(adev->dm.freesync_module, - current_stream); - - mod_freesync_add_stream(adev->dm.freesync_module, - new_stream, &aconnector->caps); - } - - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - - if (acrtc->stream != NULL) { - acrtc->otg_inst = - dc_stream_get_status(acrtc->stream)->primary_otg_inst; - } - } - - dc_stream_release(current_stream); - - dm_dc_surface_commit(dc, &disconnected_acrtc->base); - - manage_dm_interrupts(adev, disconnected_acrtc, true); - dm_crtc_cursor_reset(&disconnected_acrtc->base); - - } + if (disconnected_acrtc->stream->sink != aconnector->dc_sink) + dm_force_atomic_commit(&aconnector->base); } static uint32_t add_val_sets_surface( -- cgit From 2d60ded1325e0b4407aaa5396d1b331ea58f4f85 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Tue, 28 Feb 2017 16:45:46 -0500 Subject: drm/amd/display: Remove page_fleep_needed function. This function makes a lot of assumptions to try and deduce tha an atomic_commit came from FLIP ioctl. Those assumptions are not explicit contract with DRM API and might lead to wrong result as the code changes. Instead use drm_atomic_state.allow_modeset flag which explicitly is set to false only in atomic flip helper function, otherwise this flag is always true. P.S When we get to do actual atomic IOCTL this will have to be revised with the atomic call behavior. Signed-off-by: Andrey Grodzovsky Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 92 +--------------------- 1 file changed, 3 insertions(+), 89 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index cfc86bc5dd2b..098a801ae745 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -1429,80 +1429,6 @@ static const struct drm_plane_funcs dm_plane_funcs = { .atomic_destroy_state = drm_atomic_helper_plane_destroy_state }; -static void clear_unrelated_fields(struct drm_plane_state *state) -{ - state->crtc = NULL; - state->fb = NULL; - state->state = NULL; - state->fence = NULL; -} - -/*TODO update because event is always present now */ -static bool page_flip_needed( - const struct drm_plane_state *new_state, - const struct drm_plane_state *old_state, - struct drm_pending_vblank_event *event, - bool commit_surface_required) -{ - struct drm_plane_state old_state_tmp; - struct drm_plane_state new_state_tmp; - - struct amdgpu_framebuffer *amdgpu_fb_old; - struct amdgpu_framebuffer *amdgpu_fb_new; - struct amdgpu_crtc *acrtc_new; - - uint64_t old_tiling_flags; - uint64_t new_tiling_flags; - - bool page_flip_required; - - if (!old_state) - return false; - - if (!old_state->fb) - return false; - - if (!new_state) - return false; - - if (!new_state->fb) - return false; - - old_state_tmp = *old_state; - new_state_tmp = *new_state; - - if (!event) - return false; - - amdgpu_fb_old = to_amdgpu_framebuffer(old_state->fb); - amdgpu_fb_new = to_amdgpu_framebuffer(new_state->fb); - - if (!get_fb_info(amdgpu_fb_old, &old_tiling_flags, NULL)) - return false; - - if (!get_fb_info(amdgpu_fb_new, &new_tiling_flags, NULL)) - return false; - - if (commit_surface_required == true && - old_tiling_flags != new_tiling_flags) - return false; - - clear_unrelated_fields(&old_state_tmp); - clear_unrelated_fields(&new_state_tmp); - - page_flip_required = memcmp(&old_state_tmp, - &new_state_tmp, - sizeof(old_state_tmp)) == 0 ? true:false; - - if (new_state->crtc && page_flip_required == false) { - acrtc_new = to_amdgpu_crtc(new_state->crtc); - if (acrtc_new->flip_flags & DRM_MODE_PAGE_FLIP_ASYNC) - page_flip_required = true; - } - - return page_flip_required; -} - static int dm_plane_helper_prepare_fb( struct drm_plane *plane, struct drm_plane_state *new_state) @@ -2477,11 +2403,7 @@ void amdgpu_dm_atomic_commit_tail( * 1. This commit is not a page flip. * 2. This commit is a page flip, and streams are created. */ - pflip_needed = !state->allow_modeset && - page_flip_needed( - plane_state, - old_plane_state, - crtc->state->event, true); + pflip_needed = !state->allow_modeset; if (!pflip_needed || action == DM_COMMIT_ACTION_DPMS_ON || action == DM_COMMIT_ACTION_SET) { @@ -2540,12 +2462,7 @@ void amdgpu_dm_atomic_commit_tail( if (!fb || !crtc || !crtc->state->planes_changed || !crtc->state->active) continue; - pflip_needed = !state->allow_modeset && - page_flip_needed( - plane_state, - old_plane_state, - crtc->state->event, - false); + pflip_needed = !state->allow_modeset; if (pflip_needed) { amdgpu_dm_do_flip( @@ -2927,7 +2844,6 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, for (i = 0; i < set_count; i++) { for_each_plane_in_state(state, plane, plane_state, j) { - struct drm_plane_state *old_plane_state = plane->state; struct drm_crtc *crtc = plane_state->crtc; struct drm_framebuffer *fb = plane_state->fb; struct drm_connector *connector; @@ -2948,9 +2864,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, * 2. This commit is a page flip, and streams are created. */ crtc_state = drm_atomic_get_crtc_state(state, crtc); - pflip_needed = !state->allow_modeset && - page_flip_needed(plane_state, old_plane_state, - crtc_state->event, true); + pflip_needed = !state->allow_modeset; if (!pflip_needed || action == DM_COMMIT_ACTION_DPMS_ON || action == DM_COMMIT_ACTION_SET) { -- cgit From d98e5cc2ddacb34e9cdf1c06dce2758198af0120 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Tue, 28 Feb 2017 21:30:32 -0500 Subject: drm/amd/display: clean up and simply locking logic always take update lock instead of using HW built in update lock trigger with write to primary_addr_lo. we will be a little more inefficient with the extra registers write to lock, but this simplify code and make it always correct. Will revisit locking optimization once update sequence mature Signed-off-by: Tony Cheng Acked-by: Harry Wentland Reviewed-by: Charlene Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 32 +++++++---------------- drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c | 3 +-- drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 1 - 3 files changed, 11 insertions(+), 25 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index efe50fd2be78..8f871924beb9 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1321,22 +1321,22 @@ void dc_update_surfaces_for_stream(struct dc *dc, if (pipe_ctx->surface != surface) continue; - /*lock all the MCPP if blnd is enable for DRR*/ - if ((update_type == UPDATE_TYPE_FAST && - (dc_stream->freesync_ctx.enabled == true && - surface_count != context->res_ctx.pool->pipe_count)) && - !pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) { - lock_mask = PIPE_LOCK_CONTROL_MPCC_ADDR; + + if (update_type == UPDATE_TYPE_FULL) { + /* only apply for top pipe */ + if (!pipe_ctx->top_pipe) { + core_dc->hwss.apply_ctx_for_surface(core_dc, + surface, context); + context_timing_trace(dc, &context->res_ctx); + } } - if (update_type != UPDATE_TYPE_FAST && - !pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) { + if (!pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) { lock_mask = PIPE_LOCK_CONTROL_GRAPHICS | PIPE_LOCK_CONTROL_SCL | PIPE_LOCK_CONTROL_BLENDER | PIPE_LOCK_CONTROL_MODE; - } - if (lock_mask != 0) { + core_dc->hwss.pipe_control_lock( core_dc, pipe_ctx, @@ -1344,15 +1344,6 @@ void dc_update_surfaces_for_stream(struct dc *dc, true); } - if (update_type == UPDATE_TYPE_FULL) { - /* only apply for top pipe */ - if (!pipe_ctx->top_pipe) { - core_dc->hwss.apply_ctx_for_surface(core_dc, - surface, context); - context_timing_trace(dc, &context->res_ctx); - } - } - if (updates[i].flip_addr) core_dc->hwss.update_plane_addr(core_dc, pipe_ctx); @@ -1382,9 +1373,6 @@ void dc_update_surfaces_for_stream(struct dc *dc, } } - if ((update_type == UPDATE_TYPE_FAST) && lock_mask == 0) - return; - for (i = context->res_ctx.pool->pipe_count - 1; i >= 0; i--) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c index 1e1d60af8306..89a8274e12ea 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c @@ -52,8 +52,7 @@ void dce_pipe_control_lock(struct core_dc *dc, uint32_t lock_val = lock ? 1 : 0; uint32_t dcp_grph, scl, blnd, update_lock_mode, val; struct dce_hwseq *hws = dc->hwseq; - if (control_mask & PIPE_LOCK_CONTROL_MPCC_ADDR) - return; + val = REG_GET_4(BLND_V_UPDATE_LOCK[pipe->pipe_idx], BLND_DCP_GRPH_V_UPDATE_LOCK, &dcp_grph, BLND_SCL_V_UPDATE_LOCK, &scl, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index a902de52107f..612910e720af 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -39,7 +39,6 @@ enum pipe_lock_control { PIPE_LOCK_CONTROL_BLENDER = 1 << 1, PIPE_LOCK_CONTROL_SCL = 1 << 2, PIPE_LOCK_CONTROL_MODE = 1 << 3, - PIPE_LOCK_CONTROL_MPCC_ADDR = 1 << 4 }; struct dce_hwseq_wa { -- cgit From 773d1bcae744379a03f525bfc9249d8abf0550a8 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Tue, 28 Feb 2017 22:52:29 -0500 Subject: drm/amd/display: remove independent lock as we have no use case today Signed-off-by: Tony Cheng Acked-by: Harry Wentland Reviewed-by: Charlene Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 8 -------- drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c | 19 +++++-------------- drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h | 1 - drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 8 -------- 4 files changed, 5 insertions(+), 31 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 8f871924beb9..c34232c8c322 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1178,7 +1178,6 @@ void dc_update_surfaces_for_stream(struct dc *dc, enum surface_update_type update_type; const struct dc_stream_status *stream_status; - unsigned int lock_mask = 0; stream_status = dc_stream_get_status(dc_stream); ASSERT(stream_status); @@ -1332,15 +1331,9 @@ void dc_update_surfaces_for_stream(struct dc *dc, } if (!pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) { - lock_mask = PIPE_LOCK_CONTROL_GRAPHICS | - PIPE_LOCK_CONTROL_SCL | - PIPE_LOCK_CONTROL_BLENDER | - PIPE_LOCK_CONTROL_MODE; - core_dc->hwss.pipe_control_lock( core_dc, pipe_ctx, - lock_mask, true); } @@ -1382,7 +1375,6 @@ void dc_update_surfaces_for_stream(struct dc *dc, core_dc->hwss.pipe_control_lock( core_dc, pipe_ctx, - lock_mask, false); } break; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c index 89a8274e12ea..17cdd70a2c27 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c @@ -46,7 +46,6 @@ void dce_enable_fe_clock(struct dce_hwseq *hws, void dce_pipe_control_lock(struct core_dc *dc, struct pipe_ctx *pipe, - enum pipe_lock_control control_mask, bool lock) { uint32_t lock_val = lock ? 1 : 0; @@ -59,18 +58,10 @@ void dce_pipe_control_lock(struct core_dc *dc, BLND_BLND_V_UPDATE_LOCK, &blnd, BLND_V_UPDATE_LOCK_MODE, &update_lock_mode); - if (control_mask & PIPE_LOCK_CONTROL_GRAPHICS) - dcp_grph = lock_val; - - if (control_mask & PIPE_LOCK_CONTROL_SCL) - scl = lock_val; - - if (control_mask & PIPE_LOCK_CONTROL_BLENDER) - blnd = lock_val; - - if (control_mask & PIPE_LOCK_CONTROL_MODE) - update_lock_mode = lock_val; - + dcp_grph = lock_val; + scl = lock_val; + blnd = lock_val; + update_lock_mode = lock_val; REG_SET_2(BLND_V_UPDATE_LOCK[pipe->pipe_idx], val, BLND_DCP_GRPH_V_UPDATE_LOCK, dcp_grph, @@ -82,7 +73,7 @@ void dce_pipe_control_lock(struct core_dc *dc, BLND_V_UPDATE_LOCK_MODE, update_lock_mode); if (hws->wa.blnd_crtc_trigger) { - if (!lock && (control_mask & PIPE_LOCK_CONTROL_BLENDER)) { + if (!lock) { uint32_t value = REG_READ(CRTC_H_BLANK_START_END[pipe->pipe_idx]); REG_WRITE(CRTC_H_BLANK_START_END[pipe->pipe_idx], value); } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index 9ef618443255..70e0652be071 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -224,7 +224,6 @@ void dce_enable_fe_clock(struct dce_hwseq *hwss, void dce_pipe_control_lock(struct core_dc *dc, struct pipe_ctx *pipe, - enum pipe_lock_control control_mask, bool lock); void dce_set_blender_mode(struct dce_hwseq *hws, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 612910e720af..98a04cd46178 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -34,13 +34,6 @@ enum pipe_gating_control { PIPE_GATING_CONTROL_INIT }; -enum pipe_lock_control { - PIPE_LOCK_CONTROL_GRAPHICS = 1 << 0, - PIPE_LOCK_CONTROL_BLENDER = 1 << 1, - PIPE_LOCK_CONTROL_SCL = 1 << 2, - PIPE_LOCK_CONTROL_MODE = 1 << 3, -}; - struct dce_hwseq_wa { bool blnd_crtc_trigger; }; @@ -128,7 +121,6 @@ struct hw_sequencer_funcs { void (*pipe_control_lock)( struct core_dc *dc, struct pipe_ctx *pipe, - enum pipe_lock_control control_mask, bool lock); void (*set_displaymarks)( -- cgit From 3e337d15bf211ce1fe388d00a7f6a955550b3edf Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Wed, 1 Mar 2017 18:20:58 -0500 Subject: drm/amd/display: sometime VtotalMin less than VTotal (rounding issue) Signed-off-by: Charlene Liu Acked-by: Harry Wentland Reviewed-by: Jordan Lazare Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/modules/freesync/freesync.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index 2026ef34b11b..7a0731e2dbb0 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -905,7 +905,6 @@ void mod_freesync_notify_mode_change(struct mod_freesync *mod_freesync, core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync); for (stream_index = 0; stream_index < num_streams; stream_index++) { - map_index = map_index_from_stream(core_freesync, streams[stream_index]); @@ -913,11 +912,12 @@ void mod_freesync_notify_mode_change(struct mod_freesync *mod_freesync, if (core_freesync->map[map_index].caps->supported) { /* Update the field rate for new timing */ - state->nominal_refresh_rate_in_micro_hz = 1000000 * - div64_u64(div64_u64((streams[stream_index]-> - timing.pix_clk_khz * 1000), - streams[stream_index]->timing.v_total), - streams[stream_index]->timing.h_total); + unsigned long long temp; + temp = streams[stream_index]->timing.pix_clk_khz; + temp *= 1000ULL * 1000ULL * 1000ULL; + temp = div_u64(temp, streams[stream_index]->timing.h_total); + temp = div_u64(temp, streams[stream_index]->timing.v_total); + state->nominal_refresh_rate_in_micro_hz = (unsigned int) temp; /* Update the stream */ update_stream(core_freesync, streams[stream_index]); -- cgit From 5869b0f6bc631d8c697018e7f1d873419da1dba2 Mon Sep 17 00:00:00 2001 From: Leon Elazar Date: Wed, 1 Mar 2017 12:30:11 -0500 Subject: drm/amd/display: Adding FastUpdate functionality Exposing DC Api dc_check_update_surfaces_for_stream validation will return the answer which type of update is required, so upper layers can is it safe to call the update API fro high IRQ yes/no. Signed-off-by: Leon Elazar Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 149 ++++++++++++++++++++++++++----- drivers/gpu/drm/amd/display/dc/dc.h | 12 +++ 2 files changed, 140 insertions(+), 21 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index c34232c8c322..27e31bd665ce 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1110,42 +1110,149 @@ static bool is_surface_in_context( return false; } -enum surface_update_type { - UPDATE_TYPE_FAST, /* super fast, safe to execute in isr */ - UPDATE_TYPE_MED, /* a lot of programming needed. may need to alloc */ - UPDATE_TYPE_FULL, /* may need to shuffle resources */ -}; +static unsigned int pixel_format_to_bpp(enum surface_pixel_format format) +{ + switch (format) { + case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: + case SURFACE_PIXEL_FORMAT_GRPH_RGB565: + return 16; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: + case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: + return 32; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: + return 64; + default: + ASSERT_CRITICAL(false); + return -1; + } +} + +static enum surface_update_type get_plane_info_update_type( + const struct dc_surface_update *u) +{ + struct dc_plane_info temp_plane_info = { { { { 0 } } } }; + + if (!u->plane_info) + return UPDATE_TYPE_FAST; + + /* Copy all parameters that will cause a full update + * from current surface, the rest of the parameters + * from provided plane configuration. + * Perform memory compare and special validation + * for those that can cause fast/medium updates + */ + + /* Full update parameters */ + temp_plane_info.color_space = u->surface->color_space; + temp_plane_info.dcc = u->surface->dcc; + temp_plane_info.horizontal_mirror = u->surface->horizontal_mirror; + temp_plane_info.plane_size = u->surface->plane_size; + temp_plane_info.rotation = u->surface->rotation; + temp_plane_info.stereo_format = u->surface->stereo_format; + temp_plane_info.tiling_info = u->surface->tiling_info; + temp_plane_info.visible = u->surface->visible; + + /* Special Validation parameters */ + temp_plane_info.format = u->plane_info->format; + + if (memcmp(u->plane_info, &temp_plane_info, + sizeof(struct dc_plane_info)) != 0) + return UPDATE_TYPE_FULL; + + if (pixel_format_to_bpp(u->plane_info->format) != + pixel_format_to_bpp(u->surface->format)) { + return UPDATE_TYPE_FULL; + } else { + return UPDATE_TYPE_MED; + } +} + +static enum surface_update_type get_scaling_info_update_type( + const struct dc_surface_update *u) +{ + struct dc_scaling_info temp_scaling_info = { { 0 } }; + + if (!u->scaling_info) + return UPDATE_TYPE_FAST; + + /* Copy all parameters that will cause a full update + * from current surface, the rest of the parameters + * from provided plane configuration. + * Perform memory compare and special validation + * for those that can cause fast/medium updates + */ + + /* Full Update Parameters */ + temp_scaling_info.dst_rect = u->surface->dst_rect; + temp_scaling_info.src_rect = u->surface->src_rect; + temp_scaling_info.scaling_quality = u->surface->scaling_quality; + + /* Special validation required */ + temp_scaling_info.clip_rect = u->scaling_info->clip_rect; + + if (memcmp(u->scaling_info, &temp_scaling_info, + sizeof(struct dc_scaling_info)) != 0) + return UPDATE_TYPE_FULL; + + /* Check Clip rectangles if not equal + * difference is in offsets == > UPDATE_TYPE_FAST + * difference is in dimensions == > UPDATE_TYPE_FULL + */ + if (memcmp(&u->scaling_info->clip_rect, + &u->surface->clip_rect, sizeof(struct rect)) != 0) { + if ((u->scaling_info->clip_rect.height == + u->surface->clip_rect.height) && + (u->scaling_info->clip_rect.width == + u->surface->clip_rect.width)) { + return UPDATE_TYPE_FAST; + } else { + return UPDATE_TYPE_FULL; + } + } + + return UPDATE_TYPE_FAST; +} static enum surface_update_type det_surface_update( const struct core_dc *dc, const struct dc_surface_update *u) { const struct validate_context *context = dc->current_context; - - if (u->scaling_info || u->plane_info) - /* todo: not all scale and plane_info update need full update - * ie. check if following is the same - * scale ratio, view port, surface bpp etc - */ - return UPDATE_TYPE_FULL; /* may need bandwidth update */ + enum surface_update_type type = UPDATE_TYPE_FAST; + enum surface_update_type overall_type = UPDATE_TYPE_FAST; if (!is_surface_in_context(context, u->surface)) return UPDATE_TYPE_FULL; + type = get_plane_info_update_type(u); + if (overall_type < type) + overall_type = type; + + type = get_scaling_info_update_type(u); + if (overall_type < type) + overall_type = type; + if (u->in_transfer_func || u->out_transfer_func || - u->hdr_static_metadata) - return UPDATE_TYPE_MED; + u->hdr_static_metadata) { + if (overall_type < UPDATE_TYPE_MED) + overall_type = UPDATE_TYPE_MED; + } - return UPDATE_TYPE_FAST; + return overall_type; } -static enum surface_update_type check_update_surfaces_for_stream( - struct core_dc *dc, +enum surface_update_type dc_check_update_surfaces_for_stream( + struct dc *dc, struct dc_surface_update *updates, int surface_count, const struct dc_stream_status *stream_status) { + struct core_dc *core_dc = DC_TO_CORE(dc); int i; enum surface_update_type overall_type = UPDATE_TYPE_FAST; @@ -1154,7 +1261,7 @@ static enum surface_update_type check_update_surfaces_for_stream( for (i = 0 ; i < surface_count; i++) { enum surface_update_type type = - det_surface_update(dc, &updates[i]); + det_surface_update(core_dc, &updates[i]); if (type == UPDATE_TYPE_FULL) return type; @@ -1184,8 +1291,8 @@ void dc_update_surfaces_for_stream(struct dc *dc, if (!stream_status) return; /* Cannot commit surface to stream that is not committed */ - update_type = check_update_surfaces_for_stream( - core_dc, updates, surface_count, stream_status); + update_type = dc_check_update_surfaces_for_stream( + dc, updates, surface_count, stream_status); if (update_type >= update_surface_trace_level) update_surface_trace(dc, updates, surface_count); @@ -1321,7 +1428,7 @@ void dc_update_surfaces_for_stream(struct dc *dc, if (pipe_ctx->surface != surface) continue; - if (update_type == UPDATE_TYPE_FULL) { + if (update_type >= UPDATE_TYPE_MED) { /* only apply for top pipe */ if (!pipe_ctx->top_pipe) { core_dc->hwss.apply_ctx_for_surface(core_dc, diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 2d84b18f48b0..69ae94bb209f 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -379,6 +379,12 @@ bool dc_post_update_surfaces_to_stream( void dc_update_surfaces_for_stream(struct dc *dc, struct dc_surface_update *updates, int surface_count, const struct dc_stream *stream); +enum surface_update_type { + UPDATE_TYPE_FAST, /* super fast, safe to execute in isr */ + UPDATE_TYPE_MED, /* a lot of programming needed. may need to alloc */ + UPDATE_TYPE_FULL, /* may need to shuffle resources */ +}; + /******************************************************************************* * Stream Interfaces ******************************************************************************/ @@ -498,6 +504,12 @@ struct dc_stream_status { const struct dc_stream_status *dc_stream_get_status( const struct dc_stream *dc_stream); +enum surface_update_type dc_check_update_surfaces_for_stream( + struct dc *dc, + struct dc_surface_update *updates, + int surface_count, + const struct dc_stream_status *stream_status); + /******************************************************************************* * Link Interfaces ******************************************************************************/ -- cgit From ece4f358cb57c33089daaea1d86c62fa924060d1 Mon Sep 17 00:00:00 2001 From: Amy Zhang Date: Wed, 1 Mar 2017 09:46:20 -0500 Subject: drm/amd/display: Simplify some DMCU waits Signed-off-by: Amy Zhang Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c | 1 + drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h | 1 - drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c | 46 +++++-------------------- 3 files changed, 9 insertions(+), 39 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c index 3e3eefea3e82..ac1febafcaa4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c @@ -387,6 +387,7 @@ static void dce112_set_clock( CLOCK_SOURCE_COMBO_DISPLAY_PLL0); bp->funcs->set_dce_clock(bp, &dce_clk_params); + } static void dce_clock_read_integrated_info(struct dce_disp_clk *clk_dce) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h index 4ad6fe4c2841..020ab9d5434d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h @@ -45,7 +45,6 @@ CLK_SF(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, mask_sh), \ CLK_SF(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, mask_sh) - #define CLK_REG_FIELD_LIST(type) \ type DPREFCLK_SRC_SEL; \ type DENTIST_DPREFCLK_WDIVIDER; \ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c index 44eeeeb888fe..da7f86b61de4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c @@ -57,19 +57,13 @@ bool dce_dmcu_load_iram(struct dmcu *dmcu, { struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); unsigned int count = 0; - uint32_t status; /* Enable write access to IRAM */ REG_UPDATE_2(DMCU_RAM_ACCESS_CTRL, IRAM_HOST_ACCESS_EN, 1, IRAM_WR_ADDR_AUTO_INC, 1); - do { - dm_delay_in_microseconds(dmcu->ctx, 2); - REG_GET(DCI_MEM_PWR_STATUS, DMCU_IRAM_MEM_PWR_STATE, &status); - count++; - } while - ((status & dmcu_dce->dmcu_mask->DMCU_IRAM_MEM_PWR_STATE) && count < 10); + REG_WAIT(DCI_MEM_PWR_STATUS, DMCU_IRAM_MEM_PWR_STATE, 0, 2, 10); REG_WRITE(DMCU_IRAM_WR_CTRL, start_offset); @@ -88,21 +82,12 @@ static void dce_get_dmcu_psr_state(struct dmcu *dmcu, uint32_t *psr_state) { struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); - uint32_t count = 0; uint32_t psrStateOffset = 0xf0; - uint32_t value = -1; /* Enable write access to IRAM */ REG_UPDATE(DMCU_RAM_ACCESS_CTRL, IRAM_HOST_ACCESS_EN, 1); - while (REG(DCI_MEM_PWR_STATUS) && value != 0 && count++ < 10) { - dm_delay_in_microseconds(dmcu->ctx, 2); - REG_GET(DCI_MEM_PWR_STATUS, DMCU_IRAM_MEM_PWR_STATE, &value); - } - while (REG(DMU_MEM_PWR_CNTL) && value != 0 && count++ < 10) { - dm_delay_in_microseconds(dmcu->ctx, 2); - REG_GET(DMU_MEM_PWR_CNTL, DMCU_IRAM_MEM_PWR_STATE, &value); - } + REG_WAIT(DCI_MEM_PWR_STATUS, DMCU_IRAM_MEM_PWR_STATE, 0, 2, 10); /* Write address to IRAM_RD_ADDR in DMCU_IRAM_RD_CTRL */ REG_WRITE(DMCU_IRAM_RD_CTRL, psrStateOffset); @@ -122,21 +107,13 @@ static void dce_dmcu_set_psr_enable(struct dmcu *dmcu, bool enable) unsigned int dmcu_max_retry_on_wait_reg_ready = 801; unsigned int dmcu_wait_reg_ready_interval = 100; - unsigned int regValue; - unsigned int retryCount; uint32_t psr_state = 0; /* waitDMCUReadyForCmd */ - do { - dm_delay_in_microseconds(dmcu->ctx, - dmcu_wait_reg_ready_interval); - regValue = REG_READ(MASTER_COMM_CNTL_REG); - dmcu_max_retry_on_wait_reg_ready--; - } while - /* expected value is 0, loop while not 0*/ - ((MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK & regValue) && - dmcu_max_retry_on_wait_reg_ready > 0); + REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, + dmcu_wait_reg_ready_interval, + dmcu_max_retry_on_wait_reg_ready); /* setDMCUParam_Cmd */ if (enable) @@ -170,7 +147,6 @@ static void dce_dmcu_setup_psr(struct dmcu *dmcu, unsigned int dmcu_max_retry_on_wait_reg_ready = 801; unsigned int dmcu_wait_reg_ready_interval = 100; - unsigned int regValue; union dce_dmcu_psr_config_data_reg1 masterCmdData1; union dce_dmcu_psr_config_data_reg2 masterCmdData2; @@ -231,15 +207,9 @@ static void dce_dmcu_setup_psr(struct dmcu *dmcu, REG_UPDATE(SMU_INTERRUPT_CONTROL, DC_SMU_INT_ENABLE, 1); /* waitDMCUReadyForCmd */ - do { - dm_delay_in_microseconds(dmcu->ctx, - dmcu_wait_reg_ready_interval); - regValue = REG_READ(MASTER_COMM_CNTL_REG); - dmcu_max_retry_on_wait_reg_ready--; - } while - /* expected value is 0, loop while not 0*/ - ((MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK & regValue) && - dmcu_max_retry_on_wait_reg_ready > 0); + REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, + dmcu_wait_reg_ready_interval, + dmcu_max_retry_on_wait_reg_ready); /* setDMCUParam_PSRHostConfigData */ masterCmdData1.u32All = 0; -- cgit From e8c963d6d970220ab33f4197ab4dea18c1615e52 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Thu, 2 Mar 2017 21:18:03 -0500 Subject: drm/amd/display: refclock from bios firmwareInfoTable Signed-off-by: Charlene Liu Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 10 +++++++++- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 2 +- drivers/gpu/drm/amd/display/dc/dc_types.h | 1 + drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c | 17 ++++++----------- 4 files changed, 17 insertions(+), 13 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 27e31bd665ce..302a10c86afb 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -467,6 +467,8 @@ static bool construct(struct core_dc *dc, else { /* Create BIOS parser */ struct bp_init_data bp_init_data; + struct firmware_info fw_info = { { 0 } }; + bp_init_data.ctx = dc_ctx; bp_init_data.bios = init_params->asic_id.atombios_base_address; @@ -479,7 +481,13 @@ static bool construct(struct core_dc *dc, } dc_ctx->created_bios = true; - } + + if (dc_ctx->dc_bios->funcs->get_firmware_info( + dc_ctx->dc_bios, &fw_info) == BP_RESULT_OK) { + dc->ctx->ref_clock_inKhz = fw_info.pll_info.crystal_frequency; + } else + ASSERT_CRITICAL(false); + } /* Create I2C AUX */ dc_ctx->i2caux = dal_i2caux_create(dc_ctx); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 4e1a933be021..365a19e5d11c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -237,7 +237,7 @@ bool dc_stream_set_cursor_position( struct input_pixel_processor *ipp = pipe_ctx->ipp; struct dc_cursor_mi_param param = { .pixel_clk_khz = dc_stream->timing.pix_clk_khz, - .ref_clk_khz = 48000,/*todo refclk*/ + .ref_clk_khz = core_dc->ctx->ref_clock_inKhz, .viewport_x_start = pipe_ctx->scl_data.viewport.x, .viewport_width = pipe_ctx->scl_data.viewport.width, .h_scale_ratio = pipe_ctx->scl_data.ratios.horz, diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 242dd7b3b6b1..c428a0249488 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -91,6 +91,7 @@ struct dc_context { bool created_bios; struct gpio_service *gpio_service; struct i2caux *i2caux; + unsigned int ref_clock_inKhz; }; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index a2a2ecf8d077..1d6a9da45ba6 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -1230,17 +1230,12 @@ bool dce110_clk_src_construct( goto unexpected_failure; } - if (clk_src->ref_freq_khz == 48000) { - calc_pll_cs_init_data_hdmi. - min_override_input_pxl_clk_pll_freq_khz = 24000; - calc_pll_cs_init_data_hdmi. - max_override_input_pxl_clk_pll_freq_khz = 48000; - } else if (clk_src->ref_freq_khz == 100000) { - calc_pll_cs_init_data_hdmi. - min_override_input_pxl_clk_pll_freq_khz = 25000; - calc_pll_cs_init_data_hdmi. - max_override_input_pxl_clk_pll_freq_khz = 50000; - } + + calc_pll_cs_init_data_hdmi. + min_override_input_pxl_clk_pll_freq_khz = clk_src->ref_freq_khz/2; + calc_pll_cs_init_data_hdmi. + max_override_input_pxl_clk_pll_freq_khz = clk_src->ref_freq_khz; + if (!calc_pll_max_vco_construct( &clk_src->calc_pll_hdmi, &calc_pll_cs_init_data_hdmi)) { -- cgit From 68339af3cb7fa32634170fe5cf5cba1335bb8cc9 Mon Sep 17 00:00:00 2001 From: Leon Elazar Date: Fri, 3 Mar 2017 14:37:08 -0500 Subject: drm/amd/display: Memory leak fix during disable 1.current_context memory wasn't released at dc_post_update_surfaces_to_stream during context swap. Signed-off-by: Leon Elazar Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 302a10c86afb..4fed2f25cd96 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1046,6 +1046,9 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) core_dc->hwss.set_bandwidth(core_dc, context, true); resource_validate_ctx_destruct(core_dc->current_context); + if (core_dc->current_context) + dm_free(core_dc->current_context); + core_dc->current_context = context; return true; -- cgit From 5ac3d3c9b79fb607fc25268c8dbd220ac14f5ac6 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Fri, 3 Mar 2017 13:44:35 -0500 Subject: drm/amd/display: move refclk from dc to resource_pool Signed-off-by: Charlene Liu Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 7 ------- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 25 ++++++++++++++++++----- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 2 +- drivers/gpu/drm/amd/display/dc/dc_types.h | 1 - drivers/gpu/drm/amd/display/dc/inc/core_types.h | 1 + 5 files changed, 22 insertions(+), 14 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 4fed2f25cd96..f1ec27365f56 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -467,7 +467,6 @@ static bool construct(struct core_dc *dc, else { /* Create BIOS parser */ struct bp_init_data bp_init_data; - struct firmware_info fw_info = { { 0 } }; bp_init_data.ctx = dc_ctx; bp_init_data.bios = init_params->asic_id.atombios_base_address; @@ -481,12 +480,6 @@ static bool construct(struct core_dc *dc, } dc_ctx->created_bios = true; - - if (dc_ctx->dc_bios->funcs->get_firmware_info( - dc_ctx->dc_bios, &fw_info) == BP_RESULT_OK) { - dc->ctx->ref_clock_inKhz = fw_info.pll_info.crystal_frequency; - } else - ASSERT_CRITICAL(false); } /* Create I2C AUX */ diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 407ce60f253e..f1b1dae5399e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -31,6 +31,7 @@ #include "opp.h" #include "timing_generator.h" #include "transform.h" +#include "core_types.h" #include "set_mode_types.h" #include "virtual/virtual_stream_encoder.h" @@ -77,25 +78,39 @@ struct resource_pool *dc_create_resource_pool( enum dce_version dc_version, struct hw_asic_id asic_id) { + struct resource_pool *res_pool = NULL; switch (dc_version) { case DCE_VERSION_8_0: - return dce80_create_resource_pool( + res_pool = dce80_create_resource_pool( num_virtual_links, dc); + break; case DCE_VERSION_10_0: - return dce100_create_resource_pool( + res_pool = dce100_create_resource_pool( num_virtual_links, dc); + break; case DCE_VERSION_11_0: - return dce110_create_resource_pool( + res_pool = dce110_create_resource_pool( num_virtual_links, dc, asic_id); + break; case DCE_VERSION_11_2: - return dce112_create_resource_pool( + res_pool = dce112_create_resource_pool( num_virtual_links, dc); + break; default: break; } + if (res_pool != NULL) { + struct firmware_info fw_info = { { 0 } }; + + if (dc->ctx->dc_bios->funcs->get_firmware_info( + dc->ctx->dc_bios, &fw_info) == BP_RESULT_OK) { + res_pool->ref_clock_inKhz = fw_info.pll_info.crystal_frequency; + } else + ASSERT_CRITICAL(false); + } - return false; + return res_pool; } void dc_destroy_resource_pool(struct core_dc *dc) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 365a19e5d11c..bafba1f13a1a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -237,7 +237,7 @@ bool dc_stream_set_cursor_position( struct input_pixel_processor *ipp = pipe_ctx->ipp; struct dc_cursor_mi_param param = { .pixel_clk_khz = dc_stream->timing.pix_clk_khz, - .ref_clk_khz = core_dc->ctx->ref_clock_inKhz, + .ref_clk_khz = res_ctx->pool->ref_clock_inKhz, .viewport_x_start = pipe_ctx->scl_data.viewport.x, .viewport_width = pipe_ctx->scl_data.viewport.width, .h_scale_ratio = pipe_ctx->scl_data.ratios.horz, diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index c428a0249488..242dd7b3b6b1 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -91,7 +91,6 @@ struct dc_context { bool created_bios; struct gpio_service *gpio_service; struct i2caux *i2caux; - unsigned int ref_clock_inKhz; }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index e8fe333c5918..b29fca9dfeff 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -239,6 +239,7 @@ struct resource_pool { unsigned int pipe_count; unsigned int underlay_pipe_index; unsigned int stream_enc_count; + unsigned int ref_clock_inKhz; /* * reserved clock source for DP -- cgit From c30267f5023aef44d4367c631c42f217a2ec37f6 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Fri, 3 Mar 2017 15:16:03 -0500 Subject: drm/amd/display: TPS4 logic typo fix Signed-off-by: Charlene Liu Acked-by: Harry Wentland Reviewed-by: Wenjing Liu Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') 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 37efa40a9bca..80002795adc2 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 @@ -921,8 +921,8 @@ static inline bool perform_link_training_int( * If the upstream DPTX and downstream DPRX both support TPS4, * TPS4 must be used instead of POST_LT_ADJ_REQ. */ - if (link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED != 1 && - get_supported_tp(link) == HW_DP_TRAINING_PATTERN_4) + if (link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED != 1 || + get_supported_tp(link) == HW_DP_TRAINING_PATTERN_4) return status; if (status && -- cgit From f196f0805b5b75f024481ab4dc65f60d86fe6441 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Fri, 3 Mar 2017 09:37:11 -0500 Subject: drm/amd/display: After program backend, also program front end regs. Issue: In case of two 4K@60 + one non-4k monitor, when unplug non-4k monitor, the remain two 4k monitor don't work properly. Reason: In that case, two 4k use two pipes and no split, when unplug happens, those two monitor will use 4 pipes and split, but on that time, frontend is not programed properly. Solution: After programed backend, front end should be programmed as per new pipe setting. Signed-off-by: Yongqiang Sun Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index f1ec27365f56..a39b9987b9d6 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -806,7 +806,7 @@ bool dc_commit_streams( enum dc_status result = DC_ERROR_UNEXPECTED; struct validate_context *context; struct dc_validation_set set[MAX_STREAMS] = { {0, {0} } }; - int i, j, k; + int i, j; if (false == streams_changed(core_dc, streams, stream_count)) return DC_OK; @@ -862,18 +862,10 @@ bool dc_commit_streams( const struct core_sink *sink = context->streams[i]->sink; for (j = 0; j < context->stream_status[i].surface_count; j++) { - const struct dc_surface *dc_surface = - context->stream_status[i].surfaces[j]; - - for (k = 0; k < context->res_ctx.pool->pipe_count; k++) { - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[k]; + struct core_surface *surface = + DC_SURFACE_TO_CORE(context->stream_status[i].surfaces[j]); - if (dc_surface != &pipe->surface->public - || !dc_surface->visible) - continue; - - pipe->tg->funcs->set_blank(pipe->tg, false); - } + core_dc->hwss.apply_ctx_for_surface(core_dc, surface, context); } CONN_MSG_MODE(sink->link, "{%dx%d, %dx%d@%dKhz}", -- cgit From 268cadbd653d3d9172975a46c79f458475f82cb5 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Mon, 6 Mar 2017 14:58:59 -0500 Subject: drm/amd/display: Do not copy bottom pipe when map resource. Signed-off-by: Yongqiang Sun Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index f1b1dae5399e..c38f71e45381 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1134,6 +1134,9 @@ enum dc_status resource_map_pool_resources( if (!are_stream_backends_same(old_pipe_ctx->stream, stream)) continue; + if (old_pipe_ctx->top_pipe) + continue; + pipe_ctx->stream = stream; copy_pipe_ctx(old_pipe_ctx, pipe_ctx); -- cgit From a36214858c9093086c1bf1415af6b67c220d711f Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Thu, 20 Apr 2017 15:59:25 -0400 Subject: drm/amd/display: Switch to DRM helpers in s3. Signed-off-by: Andrey Grodzovsky Acked-by: Harry Wentland Reviewed-by: Tony Cheng Reviewed-by: Jordan Lazare Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 157 ++-------------------- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 5 + drivers/gpu/drm/amd/display/dc/core/dc.c | 8 +- drivers/gpu/drm/amd/display/dc/dc.h | 3 +- drivers/gpu/drm/amd/display/dc/inc/core_dc.h | 4 - 5 files changed, 21 insertions(+), 156 deletions(-) (limited to 'drivers/gpu') 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 da499ab7eab5..a69ce27b8ed6 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -451,28 +451,17 @@ static int dm_suspend(void *handle) struct amdgpu_device *adev = handle; struct amdgpu_display_manager *dm = &adev->dm; int ret = 0; - struct drm_crtc *crtc; s3_handle_mst(adev->ddev, true); - /* flash all pending vblank events and turn interrupt off - * before disabling CRTCs. They will be enabled back in - * dm_display_resume - */ - drm_modeset_lock_all(adev->ddev); - list_for_each_entry(crtc, &adev->ddev->mode_config.crtc_list, head) { - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - if (acrtc->stream) - drm_crtc_vblank_off(crtc); - } - drm_modeset_unlock_all(adev->ddev); - amdgpu_dm_irq_suspend(adev); + adev->dm.cached_state = drm_atomic_helper_suspend(adev->ddev); + dc_set_power_state( dm->dc, - DC_ACPI_CM_POWER_STATE_D3, - DC_VIDEO_POWER_SUSPEND); + DC_ACPI_CM_POWER_STATE_D3 + ); return ret; } @@ -504,120 +493,6 @@ struct amdgpu_connector *amdgpu_dm_find_first_crct_matching_connector( return NULL; } -static int dm_display_resume(struct drm_device *ddev) -{ - int ret = 0; - struct drm_connector *connector; - - struct drm_atomic_state *state = drm_atomic_state_alloc(ddev); - struct drm_plane *plane; - struct drm_crtc *crtc; - struct amdgpu_connector *aconnector; - struct drm_connector_state *conn_state; - - if (!state) - return ENOMEM; - - state->acquire_ctx = ddev->mode_config.acquire_ctx; - - /* Construct an atomic state to restore previous display setting */ - - /* - * Attach connectors to drm_atomic_state - * Should be done in the first place in order to make connectors - * available in state during crtc state processing. It is used for - * making decision if crtc should be disabled in case sink got - * disconnected. - * - * Connectors state crtc with NULL dc_sink should be cleared, because it - * will fail validation during commit - */ - list_for_each_entry(connector, &ddev->mode_config.connector_list, head) { - aconnector = to_amdgpu_connector(connector); - conn_state = drm_atomic_get_connector_state(state, connector); - - ret = PTR_ERR_OR_ZERO(conn_state); - if (ret) - goto err; - } - - /* Attach crtcs to drm_atomic_state*/ - list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head) { - struct drm_crtc_state *crtc_state = - drm_atomic_get_crtc_state(state, crtc); - - ret = PTR_ERR_OR_ZERO(crtc_state); - if (ret) - goto err; - - /* force a restore */ - crtc_state->mode_changed = true; - } - - - /* Attach planes to drm_atomic_state */ - list_for_each_entry(plane, &ddev->mode_config.plane_list, head) { - - struct drm_crtc *crtc; - struct drm_gem_object *obj; - struct drm_framebuffer *fb; - struct amdgpu_framebuffer *afb; - struct amdgpu_bo *rbo; - int r; - struct drm_plane_state *plane_state = drm_atomic_get_plane_state(state, plane); - - ret = PTR_ERR_OR_ZERO(plane_state); - if (ret) - goto err; - - crtc = plane_state->crtc; - fb = plane_state->fb; - - if (!crtc || !crtc->state || !crtc->state->active) - continue; - - if (!fb) { - DRM_DEBUG_KMS("No FB bound\n"); - return 0; - } - - /* - * Pin back the front buffers, cursor buffer was already pinned - * back in amdgpu_resume_kms - */ - - afb = to_amdgpu_framebuffer(fb); - - obj = afb->obj; - rbo = gem_to_amdgpu_bo(obj); - r = amdgpu_bo_reserve(rbo, false); - if (unlikely(r != 0)) - return r; - - r = amdgpu_bo_pin(rbo, AMDGPU_GEM_DOMAIN_VRAM, NULL); - - amdgpu_bo_unreserve(rbo); - - if (unlikely(r != 0)) { - DRM_ERROR("Failed to pin framebuffer\n"); - return r; - } - - } - - - /* Call commit internally with the state we just constructed */ - ret = drm_atomic_commit(state); - if (!ret) - return 0; - -err: - DRM_ERROR("Restoring old state failed with %i\n", ret); - drm_atomic_state_put(state); - - return ret; -} - static int dm_resume(void *handle) { struct amdgpu_device *adev = handle; @@ -626,8 +501,8 @@ static int dm_resume(void *handle) /* power on hardware */ dc_set_power_state( dm->dc, - DC_ACPI_CM_POWER_STATE_D0, - DC_VIDEO_POWER_ON); + DC_ACPI_CM_POWER_STATE_D0 + ); return 0; } @@ -638,8 +513,10 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev ) struct amdgpu_display_manager *dm = &adev->dm; struct amdgpu_connector *aconnector; struct drm_connector *connector; - int ret = 0; struct drm_crtc *crtc; + struct drm_crtc_state *crtc_state; + int ret = 0; + int i; /* program HPD filter */ dc_resume(dm->dc); @@ -653,14 +530,6 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev ) */ amdgpu_dm_irq_resume_early(adev); - drm_modeset_lock_all(ddev); - list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head) { - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - if (acrtc->stream) - drm_crtc_vblank_on(crtc); - } - drm_modeset_unlock_all(ddev); - /* Do detection*/ list_for_each_entry(connector, &ddev->mode_config.connector_list, head) { @@ -678,9 +547,11 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev ) amdgpu_dm_update_connector_after_detect(aconnector); } - drm_modeset_lock_all(ddev); - ret = dm_display_resume(ddev); - drm_modeset_unlock_all(ddev); + /* Force mode set in atomic comit */ + for_each_crtc_in_state(adev->dm.cached_state, crtc, crtc_state, i) + crtc_state->active_changed = true; + + ret = drm_atomic_helper_resume(ddev, adev->dm.cached_state); amdgpu_dm_irq_resume(adev); 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 d6ebba012e15..ee69179636a1 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -128,6 +128,11 @@ struct amdgpu_display_manager { struct work_struct mst_hotplug_work; struct mod_freesync *freesync_module; + + /** + * Caches device atomic state for suspend/resume + */ + struct drm_atomic_state *cached_state; }; /* basic init/fini API */ diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index a39b9987b9d6..edcb731a3aea 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1589,21 +1589,15 @@ void dc_interrupt_ack(struct dc *dc, enum dc_irq_source src) void dc_set_power_state( struct dc *dc, - enum dc_acpi_cm_power_state power_state, - enum dc_video_power_state video_power_state) + enum dc_acpi_cm_power_state power_state) { struct core_dc *core_dc = DC_TO_CORE(dc); - core_dc->previous_power_state = core_dc->current_power_state; - core_dc->current_power_state = video_power_state; - switch (power_state) { case DC_ACPI_CM_POWER_STATE_D0: core_dc->hwss.init_hw(core_dc); break; default: - /* NULL means "reset/release all DC streams" */ - dc_commit_streams(dc, NULL, 0); core_dc->hwss.power_down(core_dc); diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 69ae94bb209f..e2c2a0bf764d 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -705,8 +705,7 @@ enum dc_irq_source dc_get_hpd_irq_source_at_index( void dc_set_power_state( struct dc *dc, - enum dc_acpi_cm_power_state power_state, - enum dc_video_power_state video_power_state); + enum dc_acpi_cm_power_state power_state); void dc_resume(const struct dc *dc); /******************************************************************************* diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_dc.h b/drivers/gpu/drm/amd/display/dc/inc/core_dc.h index 7a6444dc2957..8d87f490dc1c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_dc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_dc.h @@ -26,10 +26,6 @@ struct core_dc { struct validate_context *scratch_val_ctx; struct resource_pool *res_pool; - /*Power State*/ - enum dc_video_power_state previous_power_state; - enum dc_video_power_state current_power_state; - /* Display Engine Clock levels */ struct dm_pp_clock_levels sclk_lvls; -- cgit From 4a9a5d62ec01755d36aa72782ff023da417b472a Mon Sep 17 00:00:00 2001 From: Zeyu Fan Date: Tue, 7 Mar 2017 11:48:50 -0500 Subject: drm/amd/display: Refactor on dc_sink structure. Signed-off-by: Zeyu Fan Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 9 ++++----- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_sink.c | 4 ++-- drivers/gpu/drm/amd/display/dc/dc.h | 2 ++ drivers/gpu/drm/amd/display/dc/inc/core_types.h | 2 -- 5 files changed, 9 insertions(+), 10 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index d275fc88f71e..5ca72afe8f6f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -675,10 +675,6 @@ bool dc_link_detect(const struct dc_link *dc_link, bool boot) sink_init_data.link = &link->public; sink_init_data.sink_signal = sink_caps.signal; - sink_init_data.dongle_max_pix_clk = - sink_caps.max_hdmi_pixel_clock; - sink_init_data.converter_disable_audio = - converter_disable_audio; dc_sink = dc_sink_create(&sink_init_data); if (!dc_sink) { @@ -686,6 +682,9 @@ bool dc_link_detect(const struct dc_link *dc_link, bool boot) return false; } + dc_sink->dongle_max_pix_clk = sink_caps.max_hdmi_pixel_clock; + dc_sink->converter_disable_audio = converter_disable_audio; + sink = DC_SINK_TO_CORE(dc_sink); link->public.local_sink = &sink->public; @@ -1361,7 +1360,7 @@ enum dc_status dc_link_validate_mode_timing( struct core_link *link, const struct dc_crtc_timing *timing) { - uint32_t max_pix_clk = stream->sink->dongle_max_pix_clk; + uint32_t max_pix_clk = stream->sink->public.dongle_max_pix_clk; /* A hack to avoid failing any modes for EDID override feature on * topology change such as lower quality cable for DP or different dongle diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index c38f71e45381..326019407cb1 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1193,7 +1193,7 @@ enum dc_status resource_map_pool_resources( pipe_ctx->stream_enc); /* TODO: Add check if ASIC support and EDID audio */ - if (!stream->sink->converter_disable_audio && + if (!stream->sink->public.converter_disable_audio && dc_is_audio_capable_signal(pipe_ctx->stream->signal) && stream->public.audio_info.mode_count) { pipe_ctx->audio = find_first_free_audio( diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_sink.c b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c index 0a805ea1159a..8a204731301d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_sink.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c @@ -60,8 +60,8 @@ static bool construct(struct sink *sink, const struct dc_sink_init_data *init_pa sink->protected.public.sink_signal = init_params->sink_signal; sink->protected.link = core_link; sink->protected.ctx = core_link->ctx; - sink->protected.dongle_max_pix_clk = init_params->dongle_max_pix_clk; - sink->protected.converter_disable_audio = + sink->protected.public.dongle_max_pix_clk = init_params->dongle_max_pix_clk; + sink->protected.public.converter_disable_audio = init_params->converter_disable_audio; return true; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index e2c2a0bf764d..c6c0cf500ae8 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -653,6 +653,8 @@ struct dc_sink { enum signal_type sink_signal; struct dc_edid dc_edid; /* raw edid */ struct dc_edid_caps edid_caps; /* parse display caps */ + uint32_t dongle_max_pix_clk; + bool converter_disable_audio; }; void dc_sink_retain(const struct dc_sink *sink); diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index b29fca9dfeff..faec2292cc27 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -109,8 +109,6 @@ struct core_sink { /* not used for now */ struct core_link *link; struct dc_context *ctx; - uint32_t dongle_max_pix_clk; - bool converter_disable_audio; }; /************ link *****************/ -- cgit From b2d0a103e6a0a823b46dd2d7f8c2de82c419e286 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 1 Mar 2017 18:27:17 -0500 Subject: drm/amd/display: add init calculation to scaler params Signed-off-by: Dmytro Laktyushkin Acked-by: Harry Wentland Reviewed-by: Dmytro Laktyushkin Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 5 +- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 245 ++++++++++++++++++--- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 1 + drivers/gpu/drm/amd/display/dc/inc/hw/transform.h | 11 + drivers/gpu/drm/amd/display/dc/inc/resource.h | 4 +- 5 files changed, 229 insertions(+), 37 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index edcb731a3aea..b9ca9688f8a3 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -971,8 +971,7 @@ bool dc_pre_update_surfaces_to_stream( DC_SURFACE_TO_CORE(new_surfaces[i])) continue; - resource_build_scaling_params( - new_surfaces[i], &context->res_ctx.pipe_ctx[j]); + resource_build_scaling_params(&context->res_ctx.pipe_ctx[j]); } if (!core_dc->res_pool->funcs->validate_bandwidth(core_dc, context)) { @@ -1364,7 +1363,7 @@ void dc_update_surfaces_for_stream(struct dc *dc, if (pipe_ctx->surface != surface) continue; - resource_build_scaling_params(updates[i].surface, pipe_ctx); + resource_build_scaling_params(pipe_ctx); } } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 326019407cb1..d4b338fa4ab9 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -401,15 +401,17 @@ static void rect_swap_helper(struct rect *rect) rect->y = temp; } -static void calculate_viewport( - const struct dc_surface *surface, - struct pipe_ctx *pipe_ctx) +static void calculate_viewport(struct pipe_ctx *pipe_ctx) { + const struct dc_surface *surface = &pipe_ctx->surface->public; + struct scaler_data *data = &pipe_ctx->scl_data; struct rect stream_src = pipe_ctx->stream->public.src; struct rect src = surface->src_rect; struct rect dst = surface->dst_rect; struct rect surface_clip = surface->clip_rect; struct rect clip = {0}; + int vpc_div = (data->format == PIXEL_FORMAT_420BPP12 + || data->format == PIXEL_FORMAT_420BPP15) ? 2 : 1; if (surface->rotation == ROTATION_ANGLE_90 || @@ -442,27 +444,45 @@ static void calculate_viewport( /* offset = src.ofs + (clip.ofs - dst.ofs) * scl_ratio * num_pixels = clip.num_pix * scl_ratio */ - pipe_ctx->scl_data.viewport.x = src.x + (clip.x - dst.x) * + data->viewport.x = src.x + (clip.x - dst.x) * src.width / dst.width; - pipe_ctx->scl_data.viewport.width = clip.width * + data->viewport.width = clip.width * src.width / dst.width; - pipe_ctx->scl_data.viewport.y = src.y + (clip.y - dst.y) * + data->viewport.y = src.y + (clip.y - dst.y) * src.height / dst.height; - pipe_ctx->scl_data.viewport.height = clip.height * + data->viewport.height = clip.height * src.height / dst.height; - /* Minimum viewport such that 420/422 chroma vp is non 0 */ - if (pipe_ctx->scl_data.viewport.width < 2) - pipe_ctx->scl_data.viewport.width = 2; - if (pipe_ctx->scl_data.viewport.height < 2) - pipe_ctx->scl_data.viewport.height = 2; + /* Round down, compensate in init */ + data->viewport_c.x = data->viewport.x / vpc_div; + data->viewport_c.y = data->viewport.y / vpc_div; + data->inits.h_c = (data->viewport.x % vpc_div) != 0 ? + dal_fixed31_32_half : dal_fixed31_32_zero; + data->inits.v_c = (data->viewport.y % vpc_div) != 0 ? + dal_fixed31_32_half : dal_fixed31_32_zero; + /* Round up, assume original video size always even dimensions */ + data->viewport_c.width = (data->viewport.width + vpc_div - 1) / vpc_div; + data->viewport_c.height = (data->viewport.height + vpc_div - 1) / vpc_div; + + /* Handle hsplit */ + if (pipe_ctx->top_pipe && pipe_ctx->top_pipe->surface == pipe_ctx->surface) { + data->viewport.width /= 2; + data->viewport_c.width /= 2; + data->viewport.x += data->viewport.width; + data->viewport_c.x += data->viewport_c.width; + /* Floor primary pipe, ceil 2ndary pipe */ + data->viewport.width += data->viewport.width % 2; + data->viewport_c.width += data->viewport_c.width % 2; + } else if (pipe_ctx->bottom_pipe && pipe_ctx->bottom_pipe->surface == pipe_ctx->surface) { + data->viewport.width /= 2; + data->viewport_c.width /= 2; + } } -static void calculate_recout( - const struct dc_surface *surface, - struct pipe_ctx *pipe_ctx) +static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip) { + const struct dc_surface *surface = &pipe_ctx->surface->public; struct core_stream *stream = pipe_ctx->stream; struct rect clip = surface->clip_rect; @@ -493,12 +513,26 @@ static void calculate_recout( pipe_ctx->scl_data.recout.height = stream->public.dst.y + stream->public.dst.height - pipe_ctx->scl_data.recout.y; + + /* Handle hsplit */ + if (pipe_ctx->top_pipe && pipe_ctx->top_pipe->surface == pipe_ctx->surface) { + pipe_ctx->scl_data.recout.width /= 2; + pipe_ctx->scl_data.recout.x += pipe_ctx->scl_data.recout.width; + /* Floor primary pipe, ceil 2ndary pipe */ + pipe_ctx->scl_data.recout.width += pipe_ctx->scl_data.recout.width % 2; + } else if (pipe_ctx->bottom_pipe && pipe_ctx->bottom_pipe->surface == pipe_ctx->surface) { + pipe_ctx->scl_data.recout.width /= 2; + } + + recout_skip->width = pipe_ctx->scl_data.recout.x - stream->public.dst.x - + surface->dst_rect.x * stream->public.dst.width / stream->public.src.width; + recout_skip->height = pipe_ctx->scl_data.recout.y - stream->public.dst.y - + surface->dst_rect.y * stream->public.dst.height / stream->public.src.height; } -static void calculate_scaling_ratios( - const struct dc_surface *surface, - struct pipe_ctx *pipe_ctx) +static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) { + const struct dc_surface *surface = &pipe_ctx->surface->public; struct core_stream *stream = pipe_ctx->stream; const uint32_t in_w = stream->public.src.width; const uint32_t in_h = stream->public.src.height; @@ -525,31 +559,179 @@ static void calculate_scaling_ratios( pipe_ctx->scl_data.ratios.horz_c = pipe_ctx->scl_data.ratios.horz; pipe_ctx->scl_data.ratios.vert_c = pipe_ctx->scl_data.ratios.vert; - if (pipe_ctx->scl_data.format == PIXEL_FORMAT_420BPP12) { + if (pipe_ctx->scl_data.format == PIXEL_FORMAT_420BPP12 + || pipe_ctx->scl_data.format == PIXEL_FORMAT_420BPP15) { pipe_ctx->scl_data.ratios.horz_c.value /= 2; pipe_ctx->scl_data.ratios.vert_c.value /= 2; } } -bool resource_build_scaling_params( - const struct dc_surface *surface, - struct pipe_ctx *pipe_ctx) +static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *recout_skip) { - bool res; + struct scaler_data *data = &pipe_ctx->scl_data; + struct rect src = pipe_ctx->surface->public.src_rect; + int vpc_div = (data->format == PIXEL_FORMAT_420BPP12 + || data->format == PIXEL_FORMAT_420BPP15) ? 2 : 1; + + /* + * Init calculated according to formula: + * init = (scaling_ratio + number_of_taps + 1) / 2 + * init_bot = init + scaling_ratio + * init_c = init + truncated_vp_c_offset(from calculate viewport) + */ + data->inits.h = dal_fixed31_32_div_int( + dal_fixed31_32_add_int(data->ratios.horz, data->taps.h_taps + 1), 2); + + data->inits.h_c = dal_fixed31_32_add(data->inits.h_c, dal_fixed31_32_div_int( + dal_fixed31_32_add_int(data->ratios.horz_c, data->taps.h_taps_c + 1), 2)); + + data->inits.v = dal_fixed31_32_div_int( + dal_fixed31_32_add_int(data->ratios.vert, data->taps.v_taps + 1), 2); + + data->inits.v_c = dal_fixed31_32_add(data->inits.v_c, dal_fixed31_32_div_int( + dal_fixed31_32_add_int(data->ratios.vert_c, data->taps.v_taps_c + 1), 2)); + + + /* Adjust for viewport end clip-off */ + if ((data->viewport.x + data->viewport.width) < (src.x + src.width)) { + int vp_clip = src.x + src.width - data->viewport.width - data->viewport.x; + int int_part = dal_fixed31_32_floor(data->inits.h); + + data->viewport.width += int_part < vp_clip ? int_part : vp_clip; + } + if ((data->viewport.y + data->viewport.height) < (src.y + src.height)) { + int vp_clip = src.y + src.height - data->viewport.height - data->viewport.y; + int int_part = dal_fixed31_32_floor(data->inits.v); + + data->viewport.height += int_part < vp_clip ? int_part : vp_clip; + } + if ((data->viewport_c.x + data->viewport_c.width) < (src.x + src.width) / vpc_div) { + int vp_clip = (src.x + src.width) / vpc_div - + data->viewport_c.width - data->viewport_c.x; + int int_part = dal_fixed31_32_floor(data->inits.h_c); + + data->viewport_c.width += int_part < vp_clip ? int_part : vp_clip; + } + if ((data->viewport_c.y + data->viewport_c.height) < (src.y + src.height) / vpc_div) { + int vp_clip = (src.y + src.height) / vpc_div - + data->viewport_c.height - data->viewport_c.y; + int int_part = dal_fixed31_32_floor(data->inits.v_c); + + data->viewport_c.height += int_part < vp_clip ? int_part : vp_clip; + } + + /* Adjust for non-0 viewport offset */ + if (data->viewport.x) { + int int_part; + + data->inits.h = dal_fixed31_32_add(data->inits.h, dal_fixed31_32_mul_int( + data->ratios.horz, recout_skip->width)); + int_part = dal_fixed31_32_floor(data->inits.h) - data->viewport.x; + if (int_part < data->taps.h_taps) { + int int_adj = data->viewport.x >= (data->taps.h_taps - int_part) ? + (data->taps.h_taps - int_part) : data->viewport.x; + data->viewport.x -= int_adj; + data->viewport.width += int_adj; + int_part += int_adj; + } else if (int_part > data->taps.h_taps) { + data->viewport.x += int_part - data->taps.h_taps; + data->viewport.width -= int_part - data->taps.h_taps; + int_part = data->taps.h_taps; + } + data->inits.h.value &= 0xffffffff; + data->inits.h = dal_fixed31_32_add_int(data->inits.h, int_part); + } + + if (data->viewport_c.x) { + int int_part; + + data->inits.h_c = dal_fixed31_32_add(data->inits.h_c, dal_fixed31_32_mul_int( + data->ratios.horz_c, recout_skip->width)); + int_part = dal_fixed31_32_floor(data->inits.h_c) - data->viewport_c.x; + if (int_part < data->taps.h_taps_c) { + int int_adj = data->viewport_c.x >= (data->taps.h_taps_c - int_part) ? + (data->taps.h_taps_c - int_part) : data->viewport_c.x; + data->viewport_c.x -= int_adj; + data->viewport_c.width += int_adj; + int_part += int_adj; + } else if (int_part > data->taps.h_taps_c) { + data->viewport_c.x += int_part - data->taps.h_taps_c; + data->viewport_c.width -= int_part - data->taps.h_taps_c; + int_part = data->taps.h_taps_c; + } + data->inits.h_c.value &= 0xffffffff; + data->inits.h_c = dal_fixed31_32_add_int(data->inits.h_c, int_part); + } + + if (data->viewport.y) { + int int_part; + + data->inits.v = dal_fixed31_32_add(data->inits.v, dal_fixed31_32_mul_int( + data->ratios.vert, recout_skip->height)); + int_part = dal_fixed31_32_floor(data->inits.v) - data->viewport.y; + if (int_part < data->taps.v_taps) { + int int_adj = data->viewport.y >= (data->taps.v_taps - int_part) ? + (data->taps.v_taps - int_part) : data->viewport.y; + data->viewport.y -= int_adj; + data->viewport.height += int_adj; + int_part += int_adj; + } else if (int_part > data->taps.v_taps) { + data->viewport.y += int_part - data->taps.v_taps; + data->viewport.height -= int_part - data->taps.v_taps; + int_part = data->taps.v_taps; + } + data->inits.v.value &= 0xffffffff; + data->inits.v = dal_fixed31_32_add_int(data->inits.v, int_part); + } + + if (data->viewport_c.y) { + int int_part; + + data->inits.v_c = dal_fixed31_32_add(data->inits.v_c, dal_fixed31_32_mul_int( + data->ratios.vert_c, recout_skip->height)); + int_part = dal_fixed31_32_floor(data->inits.v_c) - data->viewport_c.y; + if (int_part < data->taps.v_taps_c) { + int int_adj = data->viewport_c.y >= (data->taps.v_taps_c - int_part) ? + (data->taps.v_taps_c - int_part) : data->viewport_c.y; + data->viewport_c.y -= int_adj; + data->viewport_c.height += int_adj; + int_part += int_adj; + } else if (int_part > data->taps.v_taps_c) { + data->viewport_c.y += int_part - data->taps.v_taps_c; + data->viewport_c.height -= int_part - data->taps.v_taps_c; + int_part = data->taps.v_taps_c; + } + data->inits.v_c.value &= 0xffffffff; + data->inits.v_c = dal_fixed31_32_add_int(data->inits.v_c, int_part); + } + + /* Interlaced inits based on final vert inits */ + data->inits.v_bot = dal_fixed31_32_add(data->inits.v, data->ratios.vert); + data->inits.v_c_bot = dal_fixed31_32_add(data->inits.v_c, data->ratios.vert_c); +} + +bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) +{ + const struct dc_surface *surface = &pipe_ctx->surface->public; struct dc_crtc_timing *timing = &pipe_ctx->stream->public.timing; + struct view recout_skip = { 0 }; + bool res = false; + /* Important: scaling ratio calculation requires pixel format, * lb depth calculation requires recout and taps require scaling ratios. + * Inits require viewport, taps, ratios and recout of split pipe */ - pipe_ctx->scl_data.format = convert_pixel_format_to_dalsurface(surface->format); + pipe_ctx->scl_data.format = convert_pixel_format_to_dalsurface( + pipe_ctx->surface->public.format); + + calculate_scaling_ratios(pipe_ctx); - calculate_viewport(surface, pipe_ctx); + calculate_viewport(pipe_ctx); if (pipe_ctx->scl_data.viewport.height < 16 || pipe_ctx->scl_data.viewport.width < 16) return false; - calculate_scaling_ratios(surface, pipe_ctx); - - calculate_recout(surface, pipe_ctx); + calculate_recout(pipe_ctx, &recout_skip); /** * Setting line buffer pixel depth to 24bpp yields banding @@ -572,6 +754,9 @@ bool resource_build_scaling_params( pipe_ctx->xfm, &pipe_ctx->scl_data, &surface->scaling_quality); } + if (res) + calculate_inits_and_adj_vp(pipe_ctx, &recout_skip); + dm_logger_write(pipe_ctx->stream->ctx->logger, LOG_SCALER, "%s: Viewport:\nheight:%d width:%d x:%d " "y:%d\n dst_rect:\nheight:%d width:%d x:%d " @@ -599,9 +784,7 @@ enum dc_status resource_build_scaling_params_for_context( for (i = 0; i < MAX_PIPES; i++) { if (context->res_ctx.pipe_ctx[i].surface != NULL && context->res_ctx.pipe_ctx[i].stream != NULL) - if (!resource_build_scaling_params( - &context->res_ctx.pipe_ctx[i].surface->public, - &context->res_ctx.pipe_ctx[i])) + if (!resource_build_scaling_params(&context->res_ctx.pipe_ctx[i])) return DC_FAIL_SCALING; } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index d9dcb37a4f65..041830e05b67 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -927,6 +927,7 @@ static void get_surface_visual_confirm_color(const struct pipe_ctx *pipe_ctx, color->color_b_cb = color_value; break; case PIXEL_FORMAT_420BPP12: + case PIXEL_FORMAT_420BPP15: /* set boarder color to green */ color->color_g_y = color_value; break; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h index 9c5cb0ee4243..8325a0a47179 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h @@ -147,13 +147,24 @@ struct line_buffer_params { enum lb_pixel_depth depth; }; +struct scl_inits { + struct fixed31_32 h; + struct fixed31_32 h_c; + struct fixed31_32 v; + struct fixed31_32 v_bot; + struct fixed31_32 v_c; + struct fixed31_32 v_c_bot; +}; + struct scaler_data { int h_active; int v_active; struct scaling_taps taps; struct rect viewport; + struct rect viewport_c; struct rect recout; struct scaling_ratios ratios; + struct scl_inits inits; struct sharpness_adj sharpness; enum pixel_format format; struct line_buffer_params lb_params; diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index d96c64bb0a70..eb9c96634578 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -82,9 +82,7 @@ enum dc_status resource_map_pool_resources( const struct core_dc *dc, struct validate_context *context); -bool resource_build_scaling_params( - const struct dc_surface *surface, - struct pipe_ctx *pipe_ctx); +bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx); enum dc_status resource_build_scaling_params_for_context( const struct core_dc *dc, -- cgit From 9e6c74ceef866edf2cec380c8ce06ef73d56478d Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Mon, 6 Mar 2017 14:57:28 -0500 Subject: drm/amd/display: fix hsplit viewport calculation for rotated/mirrored usecases Signed-off-by: Dmytro Laktyushkin Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 47 +++++++++++++++++------ 1 file changed, 36 insertions(+), 11 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index d4b338fa4ab9..e34b52e28e52 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -412,6 +412,8 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) struct rect clip = {0}; int vpc_div = (data->format == PIXEL_FORMAT_420BPP12 || data->format == PIXEL_FORMAT_420BPP15) ? 2 : 1; + bool need_split = (pipe_ctx->top_pipe && pipe_ctx->top_pipe->surface == pipe_ctx->surface) + || (pipe_ctx->bottom_pipe && pipe_ctx->bottom_pipe->surface == pipe_ctx->surface); if (surface->rotation == ROTATION_ANGLE_90 || @@ -466,17 +468,40 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) data->viewport_c.height = (data->viewport.height + vpc_div - 1) / vpc_div; /* Handle hsplit */ - if (pipe_ctx->top_pipe && pipe_ctx->top_pipe->surface == pipe_ctx->surface) { - data->viewport.width /= 2; - data->viewport_c.width /= 2; - data->viewport.x += data->viewport.width; - data->viewport_c.x += data->viewport_c.width; - /* Floor primary pipe, ceil 2ndary pipe */ - data->viewport.width += data->viewport.width % 2; - data->viewport_c.width += data->viewport_c.width % 2; - } else if (pipe_ctx->bottom_pipe && pipe_ctx->bottom_pipe->surface == pipe_ctx->surface) { - data->viewport.width /= 2; - data->viewport_c.width /= 2; + if (need_split && (surface->rotation == ROTATION_ANGLE_90 || + surface->rotation == ROTATION_ANGLE_270)) { + bool lower_view = (surface->rotation == ROTATION_ANGLE_270) ^ + (pipe_ctx->top_pipe && pipe_ctx->top_pipe->surface == pipe_ctx->surface); + + if (lower_view) { + data->viewport.height /= 2; + data->viewport_c.height /= 2; + data->viewport.y += data->viewport.height; + data->viewport_c.y += data->viewport_c.height; + /* Ceil offset pipe */ + data->viewport.height += data->viewport.height % 2; + data->viewport_c.height += data->viewport_c.height % 2; + } else { + data->viewport.height /= 2; + data->viewport_c.height /= 2; + } + } else if (need_split) { + bool right_view = (surface->rotation == ROTATION_ANGLE_180) ^ + (pipe_ctx->top_pipe && pipe_ctx->top_pipe->surface == pipe_ctx->surface) ^ + surface->horizontal_mirror; + + if (right_view) { + data->viewport.width /= 2; + data->viewport_c.width /= 2; + data->viewport.x += data->viewport.width; + data->viewport_c.x += data->viewport_c.width; + /* Ceil offset pipe */ + data->viewport.width += data->viewport.width % 2; + data->viewport_c.width += data->viewport_c.width % 2; + } else { + data->viewport.width /= 2; + data->viewport_c.width /= 2; + } } } -- cgit From 1fbd2cfc15988f90ce5bebbbeaf759f4d1c615e1 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Mon, 6 Mar 2017 18:02:30 -0500 Subject: drm/amd/display: fix viewport adjustment on rotated surface Signed-off-by: Dmytro Laktyushkin Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 133 +++++++++++----------- 1 file changed, 69 insertions(+), 64 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index e34b52e28e52..01f15052bebf 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -404,57 +404,47 @@ static void rect_swap_helper(struct rect *rect) static void calculate_viewport(struct pipe_ctx *pipe_ctx) { const struct dc_surface *surface = &pipe_ctx->surface->public; + const struct dc_stream *stream = &pipe_ctx->stream->public; struct scaler_data *data = &pipe_ctx->scl_data; - struct rect stream_src = pipe_ctx->stream->public.src; - struct rect src = surface->src_rect; - struct rect dst = surface->dst_rect; - struct rect surface_clip = surface->clip_rect; - struct rect clip = {0}; + struct rect clip = { 0 }; int vpc_div = (data->format == PIXEL_FORMAT_420BPP12 || data->format == PIXEL_FORMAT_420BPP15) ? 2 : 1; - bool need_split = (pipe_ctx->top_pipe && pipe_ctx->top_pipe->surface == pipe_ctx->surface) - || (pipe_ctx->bottom_pipe && pipe_ctx->bottom_pipe->surface == pipe_ctx->surface); - - - if (surface->rotation == ROTATION_ANGLE_90 || - surface->rotation == ROTATION_ANGLE_270) { - rect_swap_helper(&src); - rect_swap_helper(&dst); - rect_swap_helper(&surface_clip); - rect_swap_helper(&stream_src); - } + bool pri_split = pipe_ctx->bottom_pipe && + pipe_ctx->bottom_pipe->surface == pipe_ctx->surface; + bool sec_split = pipe_ctx->top_pipe && + pipe_ctx->top_pipe->surface == pipe_ctx->surface; /* The actual clip is an intersection between stream * source and surface clip */ - clip.x = stream_src.x > surface_clip.x ? - stream_src.x : surface_clip.x; + clip.x = stream->src.x > surface->clip_rect.x ? + stream->src.x : surface->clip_rect.x; - clip.width = stream_src.x + stream_src.width < - surface_clip.x + surface_clip.width ? - stream_src.x + stream_src.width - clip.x : - surface_clip.x + surface_clip.width - clip.x ; + clip.width = stream->src.x + stream->src.width < + surface->clip_rect.x + surface->clip_rect.width ? + stream->src.x + stream->src.width - clip.x : + surface->clip_rect.x + surface->clip_rect.width - clip.x ; - clip.y = stream_src.y > surface_clip.y ? - stream_src.y : surface_clip.y; + clip.y = stream->src.y > surface->clip_rect.y ? + stream->src.y : surface->clip_rect.y; - clip.height = stream_src.y + stream_src.height < - surface_clip.y + surface_clip.height ? - stream_src.y + stream_src.height - clip.y : - surface_clip.y + surface_clip.height - clip.y ; + clip.height = stream->src.y + stream->src.height < + surface->clip_rect.y + surface->clip_rect.height ? + stream->src.y + stream->src.height - clip.y : + surface->clip_rect.y + surface->clip_rect.height - clip.y ; - /* offset = src.ofs + (clip.ofs - dst.ofs) * scl_ratio + /* offset = src.ofs + (clip.ofs - surface->dst_rect.ofs) * scl_ratio * num_pixels = clip.num_pix * scl_ratio */ - data->viewport.x = src.x + (clip.x - dst.x) * - src.width / dst.width; + data->viewport.x = surface->src_rect.x + (clip.x - surface->dst_rect.x) * + surface->src_rect.width / surface->dst_rect.width; data->viewport.width = clip.width * - src.width / dst.width; + surface->src_rect.width / surface->dst_rect.width; - data->viewport.y = src.y + (clip.y - dst.y) * - src.height / dst.height; + data->viewport.y = surface->src_rect.y + (clip.y - surface->dst_rect.y) * + surface->src_rect.height / surface->dst_rect.height; data->viewport.height = clip.height * - src.height / dst.height; + surface->src_rect.height / surface->dst_rect.height; /* Round down, compensate in init */ data->viewport_c.x = data->viewport.x / vpc_div; @@ -468,27 +458,15 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) data->viewport_c.height = (data->viewport.height + vpc_div - 1) / vpc_div; /* Handle hsplit */ - if (need_split && (surface->rotation == ROTATION_ANGLE_90 || - surface->rotation == ROTATION_ANGLE_270)) { - bool lower_view = (surface->rotation == ROTATION_ANGLE_270) ^ - (pipe_ctx->top_pipe && pipe_ctx->top_pipe->surface == pipe_ctx->surface); - - if (lower_view) { - data->viewport.height /= 2; - data->viewport_c.height /= 2; - data->viewport.y += data->viewport.height; - data->viewport_c.y += data->viewport_c.height; - /* Ceil offset pipe */ - data->viewport.height += data->viewport.height % 2; - data->viewport_c.height += data->viewport_c.height % 2; - } else { - data->viewport.height /= 2; - data->viewport_c.height /= 2; - } - } else if (need_split) { - bool right_view = (surface->rotation == ROTATION_ANGLE_180) ^ - (pipe_ctx->top_pipe && pipe_ctx->top_pipe->surface == pipe_ctx->surface) ^ - surface->horizontal_mirror; + if (pri_split || sec_split) { + /* HMirror XOR Secondary_pipe XOR Rotation_180 */ + bool right_view = (sec_split != surface->horizontal_mirror) != + (surface->rotation == ROTATION_ANGLE_180); + + if (surface->rotation == ROTATION_ANGLE_90 + || surface->rotation == ROTATION_ANGLE_270) + /* Secondary_pipe XOR Rotation_270 */ + right_view = (surface->rotation == ROTATION_ANGLE_270) != sec_split; if (right_view) { data->viewport.width /= 2; @@ -503,6 +481,12 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) data->viewport_c.width /= 2; } } + + if (surface->rotation == ROTATION_ANGLE_90 || + surface->rotation == ROTATION_ANGLE_270) { + rect_swap_helper(&data->viewport_c); + rect_swap_helper(&data->viewport); + } } static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip) @@ -559,10 +543,10 @@ static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) { const struct dc_surface *surface = &pipe_ctx->surface->public; struct core_stream *stream = pipe_ctx->stream; - const uint32_t in_w = stream->public.src.width; - const uint32_t in_h = stream->public.src.height; - const uint32_t out_w = stream->public.dst.width; - const uint32_t out_h = stream->public.dst.height; + const int in_w = stream->public.src.width; + const int in_h = stream->public.src.height; + const int out_w = stream->public.dst.width; + const int out_h = stream->public.dst.height; pipe_ctx->scl_data.ratios.horz = dal_fixed31_32_from_fraction( surface->src_rect.width, @@ -598,6 +582,12 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *r int vpc_div = (data->format == PIXEL_FORMAT_420BPP12 || data->format == PIXEL_FORMAT_420BPP15) ? 2 : 1; + if (pipe_ctx->surface->public.rotation == ROTATION_ANGLE_90 || + pipe_ctx->surface->public.rotation == ROTATION_ANGLE_270) { + rect_swap_helper(&data->viewport_c); + rect_swap_helper(&data->viewport); + } + /* * Init calculated according to formula: * init = (scaling_ratio + number_of_taps + 1) / 2 @@ -620,28 +610,36 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *r /* Adjust for viewport end clip-off */ if ((data->viewport.x + data->viewport.width) < (src.x + src.width)) { int vp_clip = src.x + src.width - data->viewport.width - data->viewport.x; - int int_part = dal_fixed31_32_floor(data->inits.h); + int int_part = dal_fixed31_32_floor( + dal_fixed31_32_sub(data->inits.h, data->ratios.horz)); + int_part = int_part > 0 ? int_part : 0; data->viewport.width += int_part < vp_clip ? int_part : vp_clip; } if ((data->viewport.y + data->viewport.height) < (src.y + src.height)) { int vp_clip = src.y + src.height - data->viewport.height - data->viewport.y; - int int_part = dal_fixed31_32_floor(data->inits.v); + int int_part = dal_fixed31_32_floor( + dal_fixed31_32_sub(data->inits.v, data->ratios.vert)); + int_part = int_part > 0 ? int_part : 0; data->viewport.height += int_part < vp_clip ? int_part : vp_clip; } if ((data->viewport_c.x + data->viewport_c.width) < (src.x + src.width) / vpc_div) { int vp_clip = (src.x + src.width) / vpc_div - data->viewport_c.width - data->viewport_c.x; - int int_part = dal_fixed31_32_floor(data->inits.h_c); + int int_part = dal_fixed31_32_floor( + dal_fixed31_32_sub(data->inits.h_c, data->ratios.horz_c)); + int_part = int_part > 0 ? int_part : 0; data->viewport_c.width += int_part < vp_clip ? int_part : vp_clip; } if ((data->viewport_c.y + data->viewport_c.height) < (src.y + src.height) / vpc_div) { int vp_clip = (src.y + src.height) / vpc_div - data->viewport_c.height - data->viewport_c.y; - int int_part = dal_fixed31_32_floor(data->inits.v_c); + int int_part = dal_fixed31_32_floor( + dal_fixed31_32_sub(data->inits.v_c, data->ratios.vert_c)); + int_part = int_part > 0 ? int_part : 0; data->viewport_c.height += int_part < vp_clip ? int_part : vp_clip; } @@ -733,6 +731,12 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *r /* Interlaced inits based on final vert inits */ data->inits.v_bot = dal_fixed31_32_add(data->inits.v, data->ratios.vert); data->inits.v_c_bot = dal_fixed31_32_add(data->inits.v_c, data->ratios.vert_c); + + if (pipe_ctx->surface->public.rotation == ROTATION_ANGLE_90 || + pipe_ctx->surface->public.rotation == ROTATION_ANGLE_270) { + rect_swap_helper(&data->viewport_c); + rect_swap_helper(&data->viewport); + } } bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) @@ -780,6 +784,7 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) } if (res) + /* May need to re-check lb size after this in some obscure scenario */ calculate_inits_and_adj_vp(pipe_ctx, &recout_skip); dm_logger_write(pipe_ctx->stream->ctx->logger, LOG_SCALER, -- cgit From c0bc0bd587a6f98fd1e2264a4fc2af49039627b6 Mon Sep 17 00:00:00 2001 From: Jordan Lazare Date: Wed, 8 Mar 2017 14:04:16 -0500 Subject: drm/amd/display: Less log spam Signed-off-by: Jordan Lazare Acked-by: Harry Wentland Reviewed-by: Charlene Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/basics/logger.c | 4 +++- drivers/gpu/drm/amd/display/dc/bios/bios_parser.c | 2 +- drivers/gpu/drm/amd/display/dc/dce/dce_audio.c | 4 ++-- drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c | 4 ++-- drivers/gpu/drm/amd/display/include/logger_types.h | 1 + 5 files changed, 9 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/basics/logger.c b/drivers/gpu/drm/amd/display/dc/basics/logger.c index a5625a3badab..8f4497332bda 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/logger.c +++ b/drivers/gpu/drm/amd/display/dc/basics/logger.c @@ -32,6 +32,7 @@ static const struct dc_log_type_info log_type_info_tbl[] = { {LOG_ERROR, "Error"}, {LOG_WARNING, "Warning"}, + {LOG_DEBUG, "Debug"}, {LOG_DC, "DC_Interface"}, {LOG_SURFACE, "Surface"}, {LOG_HW_HOTPLUG, "HW_Hotplug"}, @@ -80,12 +81,13 @@ static const struct dc_log_type_info log_type_info_tbl[] = { (1 << LOG_SYNC) | \ (1 << LOG_BANDWIDTH_VALIDATION) | \ (1 << LOG_MST) | \ - (1 << LOG_BIOS) | \ (1 << LOG_DETECTION_EDID_PARSER) | \ (1 << LOG_DETECTION_DP_CAPS) | \ (1 << LOG_BACKLIGHT)) | \ (1 << LOG_I2C_AUX) | \ (1 << LOG_IF_TRACE) /* | \ + (1 << LOG_DEBUG) | \ + (1 << LOG_BIOS) | \ (1 << LOG_SURFACE) | \ (1 << LOG_SCALER) | \ (1 << LOG_DML) | \ diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c index 656c39ac0256..50163a06a653 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c @@ -3299,7 +3299,7 @@ static enum bp_result patch_bios_image_from_ext_display_connection_info( opm_object, &ext_display_connection_info_tbl) != BP_RESULT_OK) { - dm_logger_write(bp->base.ctx->logger, LOG_BIOS, + dm_logger_write(bp->base.ctx->logger, LOG_WARNING, "%s: Failed to read Connection Info Table", __func__); return BP_RESULT_UNSUPPORTED; } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c index 7f52e39ec92a..b94c1e5d85cb 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c @@ -773,8 +773,8 @@ void dce_aud_wall_dto_setup( crtc_info->calculated_pixel_clock, &clock_info); - dm_logger_write(audio->ctx->logger, LOG_HW_SET_MODE,\ - "\n************************%s:Input::requested_pixel_clock = %d"\ + dm_logger_write(audio->ctx->logger, LOG_HW_AUDIO,\ + "\n%s:Input::requested_pixel_clock = %d"\ "calculated_pixel_clock =%d\n"\ "audio_dto_module = %d audio_dto_phase =%d \n\n", __func__,\ crtc_info->requested_pixel_clock,\ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c index d6662fa2f4e1..f3e1a293351f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c @@ -1093,8 +1093,8 @@ static void dce110_se_setup_hdmi_audio( crtc_info->requested_pixel_clock, crtc_info->calculated_pixel_clock, &audio_clock_info)) { - dm_logger_write(enc->ctx->logger, LOG_HW_SET_MODE, - "\n*********************%s:Input::requested_pixel_clock = %d"\ + dm_logger_write(enc->ctx->logger, LOG_HW_AUDIO, + "\n%s:Input::requested_pixel_clock = %d"\ "calculated_pixel_clock = %d \n", __func__,\ crtc_info->requested_pixel_clock,\ crtc_info->calculated_pixel_clock); diff --git a/drivers/gpu/drm/amd/display/include/logger_types.h b/drivers/gpu/drm/amd/display/include/logger_types.h index babd6523b105..832d17e1cc49 100644 --- a/drivers/gpu/drm/amd/display/include/logger_types.h +++ b/drivers/gpu/drm/amd/display/include/logger_types.h @@ -35,6 +35,7 @@ struct dal_logger; enum dc_log_type { LOG_ERROR = 0, LOG_WARNING, + LOG_DEBUG, LOG_DC, LOG_SURFACE, LOG_HW_HOTPLUG, -- cgit From c802570ed5a679c3c58fdde4b23d494bd884efc9 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 8 Mar 2017 13:45:33 -0500 Subject: drm/amd/display: fix incorrect vp adjustment Viewport would be incorrectly adjusted when surface was used for multiple displays Signed-off-by: Dmytro Laktyushkin Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 01f15052bebf..6119973c7f0a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -494,6 +494,7 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip const struct dc_surface *surface = &pipe_ctx->surface->public; struct core_stream *stream = pipe_ctx->stream; struct rect clip = surface->clip_rect; + int recout_full_x, recout_full_y; pipe_ctx->scl_data.recout.x = stream->public.dst.x; if (stream->public.src.x < clip.x) @@ -533,10 +534,21 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip pipe_ctx->scl_data.recout.width /= 2; } - recout_skip->width = pipe_ctx->scl_data.recout.x - stream->public.dst.x - - surface->dst_rect.x * stream->public.dst.width / stream->public.src.width; - recout_skip->height = pipe_ctx->scl_data.recout.y - stream->public.dst.y - - surface->dst_rect.y * stream->public.dst.height / stream->public.src.height; + /* Unclipped recout offset = stream dst offset + ((surf dst offset - stream src offset) + * * 1/ stream scaling ratio) - (surf src offset * 1/ full scl + * ratio) + */ + recout_full_x = stream->public.dst.x + (surface->dst_rect.x - stream->public.src.x) + * stream->public.dst.width / stream->public.src.width - + surface->src_rect.x * surface->dst_rect.width / surface->src_rect.width + * stream->public.dst.width / stream->public.src.width; + recout_full_y = stream->public.dst.y + (surface->dst_rect.y - stream->public.src.y) + * stream->public.dst.height / stream->public.src.height - + surface->src_rect.y * surface->dst_rect.height / surface->src_rect.height + * stream->public.dst.height / stream->public.src.height; + + recout_skip->width = pipe_ctx->scl_data.recout.x - recout_full_x; + recout_skip->height = pipe_ctx->scl_data.recout.y - recout_full_y; } static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) -- cgit From b7ad57b5791e6cbeeb2e0df3e2e2769d4128d144 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Tue, 28 Feb 2017 16:21:27 +0800 Subject: drm/amdgpu: get display info from DC when DC enabled. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c | 59 +++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 25 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c index 383204e911a4..1933253d2e0a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c @@ -889,10 +889,6 @@ static int amdgpu_cgs_get_active_displays_info(struct cgs_device *cgs_device, struct cgs_display_info *info) { CGS_FUNC_ADEV; - struct amdgpu_crtc *amdgpu_crtc; - struct drm_device *ddev = adev->ddev; - struct drm_crtc *crtc; - uint32_t line_time_us, vblank_lines; struct cgs_mode_info *mode_info; if (info == NULL) @@ -906,30 +902,43 @@ static int amdgpu_cgs_get_active_displays_info(struct cgs_device *cgs_device, mode_info->ref_clock = adev->clock.spll.reference_freq; } - if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) { - list_for_each_entry(crtc, - &ddev->mode_config.crtc_list, head) { - amdgpu_crtc = to_amdgpu_crtc(crtc); - if (crtc->enabled) { - info->active_display_mask |= (1 << amdgpu_crtc->crtc_id); - info->display_count++; - } - if (mode_info != NULL && - crtc->enabled && amdgpu_crtc->enabled && - amdgpu_crtc->hw_mode.clock) { - line_time_us = (amdgpu_crtc->hw_mode.crtc_htotal * 1000) / - amdgpu_crtc->hw_mode.clock; - vblank_lines = amdgpu_crtc->hw_mode.crtc_vblank_end - - amdgpu_crtc->hw_mode.crtc_vdisplay + - (amdgpu_crtc->v_border * 2); - mode_info->vblank_time_us = vblank_lines * line_time_us; - mode_info->refresh_rate = drm_mode_vrefresh(&amdgpu_crtc->hw_mode); - mode_info->ref_clock = adev->clock.spll.reference_freq; - mode_info = NULL; + if (!amdgpu_device_has_dc_support(adev)) { + struct amdgpu_crtc *amdgpu_crtc; + struct drm_device *ddev = adev->ddev; + struct drm_crtc *crtc; + uint32_t line_time_us, vblank_lines; + + if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) { + list_for_each_entry(crtc, + &ddev->mode_config.crtc_list, head) { + amdgpu_crtc = to_amdgpu_crtc(crtc); + if (crtc->enabled) { + info->active_display_mask |= (1 << amdgpu_crtc->crtc_id); + info->display_count++; + } + if (mode_info != NULL && + crtc->enabled && amdgpu_crtc->enabled && + amdgpu_crtc->hw_mode.clock) { + line_time_us = (amdgpu_crtc->hw_mode.crtc_htotal * 1000) / + amdgpu_crtc->hw_mode.clock; + vblank_lines = amdgpu_crtc->hw_mode.crtc_vblank_end - + amdgpu_crtc->hw_mode.crtc_vdisplay + + (amdgpu_crtc->v_border * 2); + mode_info->vblank_time_us = vblank_lines * line_time_us; + mode_info->refresh_rate = drm_mode_vrefresh(&amdgpu_crtc->hw_mode); + mode_info->ref_clock = adev->clock.spll.reference_freq; + mode_info = NULL; + } } } + } else { + info->display_count = adev->pm.pm_display_cfg.num_display; + if (mode_info != NULL) { + mode_info->vblank_time_us = adev->pm.pm_display_cfg.min_vblank_time; + mode_info->refresh_rate = adev->pm.pm_display_cfg.vrefresh; + mode_info->ref_clock = adev->clock.spll.reference_freq; + } } - return 0; } -- cgit From ae79c310b1a6f97429a5784b65f125d9cc9c95b1 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 6 Mar 2017 14:29:52 -0500 Subject: drm/amd/display: Add DCE12 bios parser support Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c | 2085 ++++++++++++++++++++ drivers/gpu/drm/amd/display/dc/bios/bios_parser2.h | 33 + .../display/dc/bios/bios_parser_types_internal2.h | 74 + .../gpu/drm/amd/display/dc/bios/command_table2.c | 813 ++++++++ .../gpu/drm/amd/display/dc/bios/command_table2.h | 105 + .../amd/display/dc/bios/command_table_helper2.c | 260 +++ .../amd/display/dc/bios/command_table_helper2.h | 82 + .../dc/bios/dce112/command_table_helper2_dce112.c | 418 ++++ .../dc/bios/dce112/command_table_helper2_dce112.h | 34 + 9 files changed, 3904 insertions(+) create mode 100644 drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c create mode 100644 drivers/gpu/drm/amd/display/dc/bios/bios_parser2.h create mode 100644 drivers/gpu/drm/amd/display/dc/bios/bios_parser_types_internal2.h create mode 100644 drivers/gpu/drm/amd/display/dc/bios/command_table2.c create mode 100644 drivers/gpu/drm/amd/display/dc/bios/command_table2.h create mode 100644 drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c create mode 100644 drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.h create mode 100644 drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.c create mode 100644 drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c new file mode 100644 index 000000000000..f6e77da7d302 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -0,0 +1,2085 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#define _BIOS_PARSER_2_ + +#include "ObjectID.h" +#include "atomfirmware.h" +#include "atomfirmwareid.h" + +#include "dc_bios_types.h" +#include "include/grph_object_ctrl_defs.h" +#include "include/bios_parser_interface.h" +#include "include/i2caux_interface.h" +#include "include/logger_interface.h" + +#include "command_table2.h" + +#include "bios_parser_helper.h" +#include "command_table_helper2.h" +#include "bios_parser2.h" +#include "bios_parser_types_internal2.h" +#include "bios_parser_interface.h" + +#define LAST_RECORD_TYPE 0xff + + +struct i2c_id_config_access { + uint8_t bfI2C_LineMux:4; + uint8_t bfHW_EngineID:3; + uint8_t bfHW_Capable:1; + uint8_t ucAccess; +}; + +static enum object_type object_type_from_bios_object_id( + uint32_t bios_object_id); + +static enum object_enum_id enum_id_from_bios_object_id(uint32_t bios_object_id); + +static struct graphics_object_id object_id_from_bios_object_id( + uint32_t bios_object_id); + +static uint32_t id_from_bios_object_id(enum object_type type, + uint32_t bios_object_id); + +static uint32_t gpu_id_from_bios_object_id(uint32_t bios_object_id); + +static enum encoder_id encoder_id_from_bios_object_id(uint32_t bios_object_id); + +static enum connector_id connector_id_from_bios_object_id( + uint32_t bios_object_id); + +static enum generic_id generic_id_from_bios_object_id(uint32_t bios_object_id); + +static enum bp_result get_gpio_i2c_info(struct bios_parser *bp, + struct atom_i2c_record *record, + struct graphics_object_i2c_info *info); + +static enum bp_result bios_parser_get_firmware_info( + struct dc_bios *dcb, + struct firmware_info *info); + +static enum bp_result bios_parser_get_encoder_cap_info( + struct dc_bios *dcb, + struct graphics_object_id object_id, + struct bp_encoder_cap_info *info); + +static enum bp_result get_firmware_info_v3_1( + struct bios_parser *bp, + struct firmware_info *info); + +static struct atom_hpd_int_record *get_hpd_record(struct bios_parser *bp, + struct atom_display_object_path_v2 *object); + +static struct atom_encoder_caps_record *get_encoder_cap_record( + struct bios_parser *bp, + struct atom_display_object_path_v2 *object); + +#define BIOS_IMAGE_SIZE_OFFSET 2 +#define BIOS_IMAGE_SIZE_UNIT 512 + +#define DATA_TABLES(table) (bp->master_data_tbl->listOfdatatables.table) + + +static void destruct(struct bios_parser *bp) +{ + if (bp->base.bios_local_image) + dm_free(bp->base.bios_local_image); + + if (bp->base.integrated_info) + dm_free(bp->base.integrated_info); +} + +static void firmware_parser_destroy(struct dc_bios **dcb) +{ + struct bios_parser *bp = BP_FROM_DCB(*dcb); + + if (!bp) { + BREAK_TO_DEBUGGER(); + return; + } + + destruct(bp); + + dm_free(bp); + *dcb = NULL; +} + +static void get_atom_data_table_revision( + struct atom_common_table_header *atom_data_tbl, + struct atom_data_revision *tbl_revision) +{ + if (!tbl_revision) + return; + + /* initialize the revision to 0 which is invalid revision */ + tbl_revision->major = 0; + tbl_revision->minor = 0; + + if (!atom_data_tbl) + return; + + tbl_revision->major = + (uint32_t) atom_data_tbl->format_revision & 0x3f; + tbl_revision->minor = + (uint32_t) atom_data_tbl->content_revision & 0x3f; +} + +static struct graphics_object_id object_id_from_bios_object_id( + uint32_t bios_object_id) +{ + enum object_type type; + enum object_enum_id enum_id; + struct graphics_object_id go_id = { 0 }; + + type = object_type_from_bios_object_id(bios_object_id); + + if (type == OBJECT_TYPE_UNKNOWN) + return go_id; + + enum_id = enum_id_from_bios_object_id(bios_object_id); + + if (enum_id == ENUM_ID_UNKNOWN) + return go_id; + + go_id = dal_graphics_object_id_init( + id_from_bios_object_id(type, bios_object_id), + enum_id, type); + + return go_id; +} + +static enum object_type object_type_from_bios_object_id(uint32_t bios_object_id) +{ + uint32_t bios_object_type = (bios_object_id & OBJECT_TYPE_MASK) + >> OBJECT_TYPE_SHIFT; + enum object_type object_type; + + switch (bios_object_type) { + case GRAPH_OBJECT_TYPE_GPU: + object_type = OBJECT_TYPE_GPU; + break; + case GRAPH_OBJECT_TYPE_ENCODER: + object_type = OBJECT_TYPE_ENCODER; + break; + case GRAPH_OBJECT_TYPE_CONNECTOR: + object_type = OBJECT_TYPE_CONNECTOR; + break; + case GRAPH_OBJECT_TYPE_ROUTER: + object_type = OBJECT_TYPE_ROUTER; + break; + case GRAPH_OBJECT_TYPE_GENERIC: + object_type = OBJECT_TYPE_GENERIC; + break; + default: + object_type = OBJECT_TYPE_UNKNOWN; + break; + } + + return object_type; +} + +static enum object_enum_id enum_id_from_bios_object_id(uint32_t bios_object_id) +{ + uint32_t bios_enum_id = + (bios_object_id & ENUM_ID_MASK) >> ENUM_ID_SHIFT; + enum object_enum_id id; + + switch (bios_enum_id) { + case GRAPH_OBJECT_ENUM_ID1: + id = ENUM_ID_1; + break; + case GRAPH_OBJECT_ENUM_ID2: + id = ENUM_ID_2; + break; + case GRAPH_OBJECT_ENUM_ID3: + id = ENUM_ID_3; + break; + case GRAPH_OBJECT_ENUM_ID4: + id = ENUM_ID_4; + break; + case GRAPH_OBJECT_ENUM_ID5: + id = ENUM_ID_5; + break; + case GRAPH_OBJECT_ENUM_ID6: + id = ENUM_ID_6; + break; + case GRAPH_OBJECT_ENUM_ID7: + id = ENUM_ID_7; + break; + default: + id = ENUM_ID_UNKNOWN; + break; + } + + return id; +} + +static uint32_t id_from_bios_object_id(enum object_type type, + uint32_t bios_object_id) +{ + switch (type) { + case OBJECT_TYPE_GPU: + return gpu_id_from_bios_object_id(bios_object_id); + case OBJECT_TYPE_ENCODER: + return (uint32_t)encoder_id_from_bios_object_id(bios_object_id); + case OBJECT_TYPE_CONNECTOR: + return (uint32_t)connector_id_from_bios_object_id( + bios_object_id); + case OBJECT_TYPE_GENERIC: + return generic_id_from_bios_object_id(bios_object_id); + default: + return 0; + } +} + +uint32_t gpu_id_from_bios_object_id(uint32_t bios_object_id) +{ + return (bios_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; +} + +static enum encoder_id encoder_id_from_bios_object_id(uint32_t bios_object_id) +{ + uint32_t bios_encoder_id = gpu_id_from_bios_object_id(bios_object_id); + enum encoder_id id; + + switch (bios_encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_LVDS: + id = ENCODER_ID_INTERNAL_LVDS; + break; + case ENCODER_OBJECT_ID_INTERNAL_TMDS1: + id = ENCODER_ID_INTERNAL_TMDS1; + break; + case ENCODER_OBJECT_ID_INTERNAL_TMDS2: + id = ENCODER_ID_INTERNAL_TMDS2; + break; + case ENCODER_OBJECT_ID_INTERNAL_DAC1: + id = ENCODER_ID_INTERNAL_DAC1; + break; + case ENCODER_OBJECT_ID_INTERNAL_DAC2: + id = ENCODER_ID_INTERNAL_DAC2; + break; + case ENCODER_OBJECT_ID_INTERNAL_LVTM1: + id = ENCODER_ID_INTERNAL_LVTM1; + break; + case ENCODER_OBJECT_ID_HDMI_INTERNAL: + id = ENCODER_ID_INTERNAL_HDMI; + break; + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: + id = ENCODER_ID_INTERNAL_KLDSCP_TMDS1; + break; + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: + id = ENCODER_ID_INTERNAL_KLDSCP_DAC1; + break; + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: + id = ENCODER_ID_INTERNAL_KLDSCP_DAC2; + break; + case ENCODER_OBJECT_ID_MVPU_FPGA: + id = ENCODER_ID_EXTERNAL_MVPU_FPGA; + break; + case ENCODER_OBJECT_ID_INTERNAL_DDI: + id = ENCODER_ID_INTERNAL_DDI; + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: + id = ENCODER_ID_INTERNAL_UNIPHY; + break; + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: + id = ENCODER_ID_INTERNAL_KLDSCP_LVTMA; + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: + id = ENCODER_ID_INTERNAL_UNIPHY1; + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: + id = ENCODER_ID_INTERNAL_UNIPHY2; + break; + case ENCODER_OBJECT_ID_ALMOND: /* ENCODER_OBJECT_ID_NUTMEG */ + id = ENCODER_ID_EXTERNAL_NUTMEG; + break; + case ENCODER_OBJECT_ID_TRAVIS: + id = ENCODER_ID_EXTERNAL_TRAVIS; + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3: + id = ENCODER_ID_INTERNAL_UNIPHY3; + break; + default: + id = ENCODER_ID_UNKNOWN; + ASSERT(0); + break; + } + + return id; +} + +static enum connector_id connector_id_from_bios_object_id( + uint32_t bios_object_id) +{ + uint32_t bios_connector_id = gpu_id_from_bios_object_id(bios_object_id); + + enum connector_id id; + + switch (bios_connector_id) { + case CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I: + id = CONNECTOR_ID_SINGLE_LINK_DVII; + break; + case CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I: + id = CONNECTOR_ID_DUAL_LINK_DVII; + break; + case CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D: + id = CONNECTOR_ID_SINGLE_LINK_DVID; + break; + case CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D: + id = CONNECTOR_ID_DUAL_LINK_DVID; + break; + case CONNECTOR_OBJECT_ID_VGA: + id = CONNECTOR_ID_VGA; + break; + case CONNECTOR_OBJECT_ID_HDMI_TYPE_A: + id = CONNECTOR_ID_HDMI_TYPE_A; + break; + case CONNECTOR_OBJECT_ID_LVDS: + id = CONNECTOR_ID_LVDS; + break; + case CONNECTOR_OBJECT_ID_PCIE_CONNECTOR: + id = CONNECTOR_ID_PCIE; + break; + case CONNECTOR_OBJECT_ID_HARDCODE_DVI: + id = CONNECTOR_ID_HARDCODE_DVI; + break; + case CONNECTOR_OBJECT_ID_DISPLAYPORT: + id = CONNECTOR_ID_DISPLAY_PORT; + break; + case CONNECTOR_OBJECT_ID_eDP: + id = CONNECTOR_ID_EDP; + break; + case CONNECTOR_OBJECT_ID_MXM: + id = CONNECTOR_ID_MXM; + break; + default: + id = CONNECTOR_ID_UNKNOWN; + break; + } + + return id; +} + +enum generic_id generic_id_from_bios_object_id(uint32_t bios_object_id) +{ + uint32_t bios_generic_id = gpu_id_from_bios_object_id(bios_object_id); + + enum generic_id id; + + switch (bios_generic_id) { + case GENERIC_OBJECT_ID_MXM_OPM: + id = GENERIC_ID_MXM_OPM; + break; + case GENERIC_OBJECT_ID_GLSYNC: + id = GENERIC_ID_GLSYNC; + break; + case GENERIC_OBJECT_ID_STEREO_PIN: + id = GENERIC_ID_STEREO; + break; + default: + id = GENERIC_ID_UNKNOWN; + break; + } + + return id; +} + +static uint8_t bios_parser_get_connectors_number(struct dc_bios *dcb) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + unsigned int count = 0; + unsigned int i; + + for (i = 0; i < bp->object_info_tbl.v1_4->number_of_path; i++) { + if (bp->object_info_tbl.v1_4->display_path[i].encoderobjid != 0 + && + bp->object_info_tbl.v1_4->display_path[i].display_objid != 0) + count++; + } + return count; +} + +static struct graphics_object_id bios_parser_get_encoder_id( + struct dc_bios *dcb, + uint32_t i) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + struct graphics_object_id object_id = dal_graphics_object_id_init( + 0, ENUM_ID_UNKNOWN, OBJECT_TYPE_UNKNOWN); + + if (bp->object_info_tbl.v1_4->number_of_path > i) + object_id = object_id_from_bios_object_id( + bp->object_info_tbl.v1_4->display_path[i].encoderobjid); + + return object_id; +} + +static struct graphics_object_id bios_parser_get_connector_id( + struct dc_bios *dcb, + uint8_t i) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + struct graphics_object_id object_id = dal_graphics_object_id_init( + 0, ENUM_ID_UNKNOWN, OBJECT_TYPE_UNKNOWN); + struct object_info_table *tbl = &bp->object_info_tbl; + struct display_object_info_table_v1_4 *v1_4 = tbl->v1_4; + + if (v1_4->number_of_path > i) { + /* If display_objid is generic object id, the encoderObj + * /extencoderobjId should be 0 + */ + if (v1_4->display_path[i].encoderobjid != 0 && + v1_4->display_path[i].display_objid != 0) + object_id = object_id_from_bios_object_id( + v1_4->display_path[i].display_objid); + } + + return object_id; +} + + +/* TODO: GetNumberOfSrc*/ + +static uint32_t bios_parser_get_dst_number(struct dc_bios *dcb, + struct graphics_object_id id) +{ + /* connector has 1 Dest, encoder has 0 Dest */ + switch (id.type) { + case OBJECT_TYPE_ENCODER: + return 0; + case OBJECT_TYPE_CONNECTOR: + return 1; + default: + return 0; + } +} + +/* removed getSrcObjList, getDestObjList*/ + + +static enum bp_result bios_parser_get_src_obj(struct dc_bios *dcb, + struct graphics_object_id object_id, uint32_t index, + struct graphics_object_id *src_object_id) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + unsigned int i; + enum bp_result bp_result = BP_RESULT_BADINPUT; + struct graphics_object_id obj_id = {0}; + struct object_info_table *tbl = &bp->object_info_tbl; + + if (!src_object_id) + return bp_result; + + switch (object_id.type) { + /* Encoder's Source is GPU. BIOS does not provide GPU, since all + * displaypaths point to same GPU (0x1100). Hardcode GPU object type + */ + case OBJECT_TYPE_ENCODER: + /* TODO: since num of src must be less than 2. + * If found in for loop, should break. + * DAL2 implementation may be changed too + */ + for (i = 0; i < tbl->v1_4->number_of_path; i++) { + obj_id = object_id_from_bios_object_id( + tbl->v1_4->display_path[i].encoderobjid); + if (object_id.type == obj_id.type && + object_id.id == obj_id.id && + object_id.enum_id == + obj_id.enum_id) { + *src_object_id = + object_id_from_bios_object_id(0x1100); + /* break; */ + } + } + bp_result = BP_RESULT_OK; + break; + case OBJECT_TYPE_CONNECTOR: + for (i = 0; i < tbl->v1_4->number_of_path; i++) { + obj_id = object_id_from_bios_object_id( + tbl->v1_4->display_path[i].display_objid); + + if (object_id.type == obj_id.type && + object_id.id == obj_id.id && + object_id.enum_id == obj_id.enum_id) { + *src_object_id = + object_id_from_bios_object_id( + tbl->v1_4->display_path[i].encoderobjid); + /* break; */ + } + } + bp_result = BP_RESULT_OK; + break; + default: + break; + } + + return bp_result; +} + +static enum bp_result bios_parser_get_dst_obj(struct dc_bios *dcb, + struct graphics_object_id object_id, uint32_t index, + struct graphics_object_id *dest_object_id) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + unsigned int i; + enum bp_result bp_result = BP_RESULT_BADINPUT; + struct graphics_object_id obj_id = {0}; + struct object_info_table *tbl = &bp->object_info_tbl; + + if (!dest_object_id) + return BP_RESULT_BADINPUT; + + switch (object_id.type) { + case OBJECT_TYPE_ENCODER: + /* TODO: since num of src must be less than 2. + * If found in for loop, should break. + * DAL2 implementation may be changed too + */ + for (i = 0; i < tbl->v1_4->number_of_path; i++) { + obj_id = object_id_from_bios_object_id( + tbl->v1_4->display_path[i].encoderobjid); + if (object_id.type == obj_id.type && + object_id.id == obj_id.id && + object_id.enum_id == + obj_id.enum_id) { + *dest_object_id = + object_id_from_bios_object_id( + tbl->v1_4->display_path[i].display_objid); + /* break; */ + } + } + bp_result = BP_RESULT_OK; + break; + default: + break; + } + + return bp_result; +} + + +/* from graphics_object_id, find display path which includes the object_id */ +static struct atom_display_object_path_v2 *get_bios_object( + struct bios_parser *bp, + struct graphics_object_id id) +{ + unsigned int i; + struct graphics_object_id obj_id = {0}; + + switch (id.type) { + case OBJECT_TYPE_ENCODER: + for (i = 0; i < bp->object_info_tbl.v1_4->number_of_path; i++) { + obj_id = object_id_from_bios_object_id( + bp->object_info_tbl.v1_4->display_path[i].encoderobjid); + if (id.type == obj_id.type && + id.id == obj_id.id && + id.enum_id == obj_id.enum_id) + return + &bp->object_info_tbl.v1_4->display_path[i]; + } + case OBJECT_TYPE_CONNECTOR: + case OBJECT_TYPE_GENERIC: + /* Both Generic and Connector Object ID + * will be stored on display_objid + */ + for (i = 0; i < bp->object_info_tbl.v1_4->number_of_path; i++) { + obj_id = object_id_from_bios_object_id( + bp->object_info_tbl.v1_4->display_path[i].display_objid + ); + if (id.type == obj_id.type && + id.id == obj_id.id && + id.enum_id == obj_id.enum_id) + return + &bp->object_info_tbl.v1_4->display_path[i]; + } + default: + return NULL; + } +} + +static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb, + struct graphics_object_id id, + struct graphics_object_i2c_info *info) +{ + uint32_t offset; + struct atom_display_object_path_v2 *object; + struct atom_common_record_header *header; + struct atom_i2c_record *record; + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!info) + return BP_RESULT_BADINPUT; + + object = get_bios_object(bp, id); + + if (!object) + return BP_RESULT_BADINPUT; + + offset = object->disp_recordoffset + bp->object_info_tbl_offset; + + for (;;) { + header = GET_IMAGE(struct atom_common_record_header, offset); + + if (!header) + return BP_RESULT_BADBIOSTABLE; + + if (header->record_type == LAST_RECORD_TYPE || + !header->record_size) + break; + + if (header->record_type == ATOM_I2C_RECORD_TYPE + && sizeof(struct atom_i2c_record) <= + header->record_size) { + /* get the I2C info */ + record = (struct atom_i2c_record *) header; + + if (get_gpio_i2c_info(bp, record, info) == + BP_RESULT_OK) + return BP_RESULT_OK; + } + + offset += header->record_size; + } + + return BP_RESULT_NORECORD; +} + +static enum bp_result get_gpio_i2c_info( + struct bios_parser *bp, + struct atom_i2c_record *record, + struct graphics_object_i2c_info *info) +{ + struct atom_gpio_pin_lut_v2_1 *header; + uint32_t count = 0; + unsigned int table_index = 0; + + if (!info) + return BP_RESULT_BADINPUT; + + /* get the GPIO_I2C info */ + if (!DATA_TABLES(gpio_pin_lut)) + return BP_RESULT_BADBIOSTABLE; + + header = GET_IMAGE(struct atom_gpio_pin_lut_v2_1, + DATA_TABLES(gpio_pin_lut)); + if (!header) + return BP_RESULT_BADBIOSTABLE; + + if (sizeof(struct atom_common_table_header) + + sizeof(struct atom_gpio_pin_assignment) > + le16_to_cpu(header->table_header.structuresize)) + return BP_RESULT_BADBIOSTABLE; + + /* TODO: is version change? */ + if (header->table_header.content_revision != 1) + return BP_RESULT_UNSUPPORTED; + + /* get data count */ + count = (le16_to_cpu(header->table_header.structuresize) + - sizeof(struct atom_common_table_header)) + / sizeof(struct atom_gpio_pin_assignment); + + table_index = record->i2c_id & I2C_HW_LANE_MUX; + + if (count < table_index) { + bool find_valid = false; + + for (table_index = 0; table_index < count; table_index++) { + if (((record->i2c_id & I2C_HW_CAP) == ( + header->gpio_pin[table_index].gpio_id & + I2C_HW_CAP)) && + ((record->i2c_id & I2C_HW_ENGINE_ID_MASK) == + (header->gpio_pin[table_index].gpio_id & + I2C_HW_ENGINE_ID_MASK)) && + ((record->i2c_id & I2C_HW_LANE_MUX) == + (header->gpio_pin[table_index].gpio_id & + I2C_HW_LANE_MUX))) { + /* still valid */ + find_valid = true; + break; + } + } + /* If we don't find the entry that we are looking for then + * we will return BP_Result_BadBiosTable. + */ + if (find_valid == false) + return BP_RESULT_BADBIOSTABLE; + } + + /* get the GPIO_I2C_INFO */ + info->i2c_hw_assist = (record->i2c_id & I2C_HW_CAP) ? true : false; + info->i2c_line = record->i2c_id & I2C_HW_LANE_MUX; + info->i2c_engine_id = (record->i2c_id & I2C_HW_ENGINE_ID_MASK) >> 4; + info->i2c_slave_address = record->i2c_slave_addr; + + /* TODO: check how to get register offset for en, Y, etc. */ + info->gpio_info.clk_a_register_index = + le16_to_cpu( + header->gpio_pin[table_index].data_a_reg_index); + info->gpio_info.clk_a_shift = + header->gpio_pin[table_index].gpio_bitshift; + + return BP_RESULT_OK; +} + +static enum bp_result get_voltage_ddc_info_v4( + uint8_t *i2c_line, + uint32_t index, + struct atom_common_table_header *header, + uint8_t *address) +{ + enum bp_result result = BP_RESULT_NORECORD; + struct atom_voltage_objects_info_v4_1 *info = + (struct atom_voltage_objects_info_v4_1 *) address; + + uint8_t *voltage_current_object = + (uint8_t *) (&(info->voltage_object[0])); + + while ((address + le16_to_cpu(header->structuresize)) > + voltage_current_object) { + struct atom_i2c_voltage_object_v4 *object = + (struct atom_i2c_voltage_object_v4 *) + voltage_current_object; + + if (object->header.voltage_mode == + ATOM_INIT_VOLTAGE_REGULATOR) { + if (object->header.voltage_type == index) { + *i2c_line = object->i2c_id ^ 0x90; + result = BP_RESULT_OK; + break; + } + } + + voltage_current_object += + le16_to_cpu(object->header.object_size); + } + return result; +} + +static enum bp_result bios_parser_get_thermal_ddc_info( + struct dc_bios *dcb, + uint32_t i2c_channel_id, + struct graphics_object_i2c_info *info) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + struct i2c_id_config_access *config; + struct atom_i2c_record record; + + if (!info) + return BP_RESULT_BADINPUT; + + config = (struct i2c_id_config_access *) &i2c_channel_id; + + record.i2c_id = config->bfHW_Capable; + record.i2c_id |= config->bfI2C_LineMux; + record.i2c_id |= config->bfHW_EngineID; + + return get_gpio_i2c_info(bp, &record, info); +} + +static enum bp_result bios_parser_get_voltage_ddc_info(struct dc_bios *dcb, + uint32_t index, + struct graphics_object_i2c_info *info) +{ + uint8_t i2c_line = 0; + enum bp_result result = BP_RESULT_NORECORD; + uint8_t *voltage_info_address; + struct atom_common_table_header *header; + struct atom_data_revision revision = {0}; + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!DATA_TABLES(voltageobject_info)) + return result; + + voltage_info_address = get_image(&bp->base, + DATA_TABLES(voltageobject_info), + sizeof(struct atom_common_table_header)); + + header = (struct atom_common_table_header *) voltage_info_address; + + get_atom_data_table_revision(header, &revision); + + switch (revision.major) { + case 4: + if (revision.minor != 1) + break; + result = get_voltage_ddc_info_v4(&i2c_line, index, header, + voltage_info_address); + break; + } + + if (result == BP_RESULT_OK) + result = bios_parser_get_thermal_ddc_info(dcb, + i2c_line, info); + + return result; +} + +static enum bp_result bios_parser_get_hpd_info( + struct dc_bios *dcb, + struct graphics_object_id id, + struct graphics_object_hpd_info *info) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + struct atom_display_object_path_v2 *object; + struct atom_hpd_int_record *record = NULL; + + if (!info) + return BP_RESULT_BADINPUT; + + object = get_bios_object(bp, id); + + if (!object) + return BP_RESULT_BADINPUT; + + record = get_hpd_record(bp, object); + + if (record != NULL) { + info->hpd_int_gpio_uid = record->pin_id; + info->hpd_active = record->plugin_pin_state; + return BP_RESULT_OK; + } + + return BP_RESULT_NORECORD; +} + +static struct atom_hpd_int_record *get_hpd_record( + struct bios_parser *bp, + struct atom_display_object_path_v2 *object) +{ + struct atom_common_record_header *header; + uint32_t offset; + + if (!object) { + BREAK_TO_DEBUGGER(); /* Invalid object */ + return NULL; + } + + offset = le16_to_cpu(object->disp_recordoffset) + + bp->object_info_tbl_offset; + + for (;;) { + header = GET_IMAGE(struct atom_common_record_header, offset); + + if (!header) + return NULL; + + if (header->record_type == LAST_RECORD_TYPE || + !header->record_size) + break; + + if (header->record_type == ATOM_HPD_INT_RECORD_TYPE + && sizeof(struct atom_hpd_int_record) <= + header->record_size) + return (struct atom_hpd_int_record *) header; + + offset += header->record_size; + } + + return NULL; +} + +/** + * bios_parser_get_gpio_pin_info + * Get GpioPin information of input gpio id + * + * @param gpio_id, GPIO ID + * @param info, GpioPin information structure + * @return Bios parser result code + * @note + * to get the GPIO PIN INFO, we need: + * 1. get the GPIO_ID from other object table, see GetHPDInfo() + * 2. in DATA_TABLE.GPIO_Pin_LUT, search all records, + * to get the registerA offset/mask + */ +static enum bp_result bios_parser_get_gpio_pin_info( + struct dc_bios *dcb, + uint32_t gpio_id, + struct gpio_pin_info *info) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + struct atom_gpio_pin_lut_v2_1 *header; + uint32_t count = 0; + uint32_t i = 0; + + if (!DATA_TABLES(gpio_pin_lut)) + return BP_RESULT_BADBIOSTABLE; + + header = GET_IMAGE(struct atom_gpio_pin_lut_v2_1, + DATA_TABLES(gpio_pin_lut)); + if (!header) + return BP_RESULT_BADBIOSTABLE; + + if (sizeof(struct atom_common_table_header) + + sizeof(struct atom_gpio_pin_lut_v2_1) + > le16_to_cpu(header->table_header.structuresize)) + return BP_RESULT_BADBIOSTABLE; + + if (header->table_header.content_revision != 1) + return BP_RESULT_UNSUPPORTED; + + /* Temporary hard code gpio pin info */ +#if defined(FOR_SIMNOW_BOOT) + { + struct atom_gpio_pin_assignment gpio_pin[8] = { + {0x5db5, 0, 0, 1, 0}, + {0x5db5, 8, 8, 2, 0}, + {0x5db5, 0x10, 0x10, 3, 0}, + {0x5db5, 0x18, 0x14, 4, 0}, + {0x5db5, 0x1A, 0x18, 5, 0}, + {0x5db5, 0x1C, 0x1C, 6, 0}, + }; + + count = 6; + memmove(header->gpio_pin, gpio_pin, sizeof(gpio_pin)); + } +#else + count = (le16_to_cpu(header->table_header.structuresize) + - sizeof(struct atom_common_table_header)) + / sizeof(struct atom_gpio_pin_assignment); +#endif + for (i = 0; i < count; ++i) { + if (header->gpio_pin[i].gpio_id != gpio_id) + continue; + + info->offset = + (uint32_t) le16_to_cpu( + header->gpio_pin[i].data_a_reg_index); + info->offset_y = info->offset + 2; + info->offset_en = info->offset + 1; + info->offset_mask = info->offset - 1; + + info->mask = (uint32_t) (1 << + header->gpio_pin[i].gpio_bitshift); + info->mask_y = info->mask + 2; + info->mask_en = info->mask + 1; + info->mask_mask = info->mask - 1; + + return BP_RESULT_OK; + } + + return BP_RESULT_NORECORD; +} + +static struct device_id device_type_from_device_id(uint16_t device_id) +{ + + struct device_id result_device_id; + + switch (device_id) { + case ATOM_DISPLAY_LCD1_SUPPORT: + result_device_id.device_type = DEVICE_TYPE_LCD; + result_device_id.enum_id = 1; + break; + + case ATOM_DISPLAY_DFP1_SUPPORT: + result_device_id.device_type = DEVICE_TYPE_DFP; + result_device_id.enum_id = 1; + break; + + case ATOM_DISPLAY_DFP2_SUPPORT: + result_device_id.device_type = DEVICE_TYPE_DFP; + result_device_id.enum_id = 2; + break; + + case ATOM_DISPLAY_DFP3_SUPPORT: + result_device_id.device_type = DEVICE_TYPE_DFP; + result_device_id.enum_id = 3; + break; + + case ATOM_DISPLAY_DFP4_SUPPORT: + result_device_id.device_type = DEVICE_TYPE_DFP; + result_device_id.enum_id = 4; + break; + + case ATOM_DISPLAY_DFP5_SUPPORT: + result_device_id.device_type = DEVICE_TYPE_DFP; + result_device_id.enum_id = 5; + break; + + case ATOM_DISPLAY_DFP6_SUPPORT: + result_device_id.device_type = DEVICE_TYPE_DFP; + result_device_id.enum_id = 6; + break; + + default: + BREAK_TO_DEBUGGER(); /* Invalid device Id */ + result_device_id.device_type = DEVICE_TYPE_UNKNOWN; + result_device_id.enum_id = 0; + } + return result_device_id; +} + +static enum bp_result bios_parser_get_device_tag( + struct dc_bios *dcb, + struct graphics_object_id connector_object_id, + uint32_t device_tag_index, + struct connector_device_tag_info *info) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + struct atom_display_object_path_v2 *object; + + if (!info) + return BP_RESULT_BADINPUT; + + /* getBiosObject will return MXM object */ + object = get_bios_object(bp, connector_object_id); + + if (!object) { + BREAK_TO_DEBUGGER(); /* Invalid object id */ + return BP_RESULT_BADINPUT; + } + + info->acpi_device = 0; /* BIOS no longer provides this */ + info->dev_id = device_type_from_device_id(object->device_tag); + + return BP_RESULT_OK; +} + +static enum bp_result get_ss_info_v4_1( + struct bios_parser *bp, + uint32_t id, + uint32_t index, + struct spread_spectrum_info *ss_info) +{ + enum bp_result result = BP_RESULT_OK; + struct atom_display_controller_info_v4_1 *disp_cntl_tbl = NULL; + struct atom_smu_info_v3_1 *smu_tbl = NULL; + + if (!ss_info) + return BP_RESULT_BADINPUT; + + if (!DATA_TABLES(dce_info)) + return BP_RESULT_BADBIOSTABLE; + + if (!DATA_TABLES(smu_info)) + return BP_RESULT_BADBIOSTABLE; + + disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_1, + DATA_TABLES(dce_info)); + if (!disp_cntl_tbl) + return BP_RESULT_BADBIOSTABLE; + + smu_tbl = GET_IMAGE(struct atom_smu_info_v3_1, DATA_TABLES(smu_info)); + if (!smu_tbl) + return BP_RESULT_BADBIOSTABLE; + + + ss_info->type.STEP_AND_DELAY_INFO = false; + ss_info->spread_percentage_divider = 1000; + /* BIOS no longer uses target clock. Always enable for now */ + ss_info->target_clock_range = 0xffffffff; + + switch (id) { + case AS_SIGNAL_TYPE_DVI: + ss_info->spread_spectrum_percentage = + disp_cntl_tbl->dvi_ss_percentage; + ss_info->spread_spectrum_range = + disp_cntl_tbl->dvi_ss_rate_10hz * 10; + if (disp_cntl_tbl->dvi_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE) + ss_info->type.CENTER_MODE = true; + break; + case AS_SIGNAL_TYPE_HDMI: + ss_info->spread_spectrum_percentage = + disp_cntl_tbl->hdmi_ss_percentage; + ss_info->spread_spectrum_range = + disp_cntl_tbl->hdmi_ss_rate_10hz * 10; + if (disp_cntl_tbl->hdmi_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE) + ss_info->type.CENTER_MODE = true; + break; + /* TODO LVDS not support anymore? */ + case AS_SIGNAL_TYPE_DISPLAY_PORT: + ss_info->spread_spectrum_percentage = + disp_cntl_tbl->dp_ss_percentage; + ss_info->spread_spectrum_range = + disp_cntl_tbl->dp_ss_rate_10hz * 10; + if (disp_cntl_tbl->dp_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE) + ss_info->type.CENTER_MODE = true; + break; + case AS_SIGNAL_TYPE_GPU_PLL: + ss_info->spread_spectrum_percentage = + smu_tbl->gpuclk_ss_percentage; + ss_info->spread_spectrum_range = + smu_tbl->gpuclk_ss_rate_10hz * 10; + if (smu_tbl->gpuclk_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE) + ss_info->type.CENTER_MODE = true; + break; + default: + result = BP_RESULT_UNSUPPORTED; + } + + return result; +} + +/** + * bios_parser_get_spread_spectrum_info + * Get spread spectrum information from the ASIC_InternalSS_Info(ver 2.1 or + * ver 3.1) or SS_Info table from the VBIOS. Currently ASIC_InternalSS_Info + * ver 2.1 can co-exist with SS_Info table. Expect ASIC_InternalSS_Info + * ver 3.1, + * there is only one entry for each signal /ss id. However, there is + * no planning of supporting multiple spread Sprectum entry for EverGreen + * @param [in] this + * @param [in] signal, ASSignalType to be converted to info index + * @param [in] index, number of entries that match the converted info index + * @param [out] ss_info, sprectrum information structure, + * @return Bios parser result code + */ +static enum bp_result bios_parser_get_spread_spectrum_info( + struct dc_bios *dcb, + enum as_signal_type signal, + uint32_t index, + struct spread_spectrum_info *ss_info) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + enum bp_result result = BP_RESULT_UNSUPPORTED; + struct atom_common_table_header *header; + struct atom_data_revision tbl_revision; + + if (!ss_info) /* check for bad input */ + return BP_RESULT_BADINPUT; + + if (!DATA_TABLES(dce_info)) + return BP_RESULT_UNSUPPORTED; + + header = GET_IMAGE(struct atom_common_table_header, + DATA_TABLES(dce_info)); + get_atom_data_table_revision(header, &tbl_revision); + + switch (tbl_revision.major) { + case 4: + switch (tbl_revision.minor) { + case 1: + return get_ss_info_v4_1(bp, signal, index, ss_info); + default: + break; + } + break; + default: + break; + } + /* there can not be more then one entry for SS Info table */ + return result; +} + +static enum bp_result get_embedded_panel_info_v2_1( + struct bios_parser *bp, + struct embedded_panel_info *info) +{ + struct lcd_info_v2_1 *lvds; + + if (!info) + return BP_RESULT_BADINPUT; + + if (!DATA_TABLES(lcd_info)) + return BP_RESULT_UNSUPPORTED; + + lvds = GET_IMAGE(struct lcd_info_v2_1, DATA_TABLES(lcd_info)); + + if (!lvds) + return BP_RESULT_BADBIOSTABLE; + + /* TODO: previous vv1_3, should v2_1 */ + if (!((lvds->table_header.format_revision == 2) + && (lvds->table_header.content_revision >= 1))) + return BP_RESULT_UNSUPPORTED; + + memset(info, 0, sizeof(struct embedded_panel_info)); + + /* We need to convert from 10KHz units into KHz units */ + info->lcd_timing.pixel_clk = + le16_to_cpu(lvds->lcd_timing.pixclk) * 10; + /* usHActive does not include borders, according to VBIOS team */ + info->lcd_timing.horizontal_addressable = + le16_to_cpu(lvds->lcd_timing.h_active); + /* usHBlanking_Time includes borders, so we should really be + * subtractingborders duing this translation, but LVDS generally + * doesn't have borders, so we should be okay leaving this as is for + * now. May need to revisit if we ever have LVDS with borders + */ + info->lcd_timing.horizontal_blanking_time = + le16_to_cpu(lvds->lcd_timing.h_blanking_time); + /* usVActive does not include borders, according to VBIOS team*/ + info->lcd_timing.vertical_addressable = + le16_to_cpu(lvds->lcd_timing.v_active); + /* usVBlanking_Time includes borders, so we should really be + * subtracting borders duing this translation, but LVDS generally + * doesn't have borders, so we should be okay leaving this as is for + * now. May need to revisit if we ever have LVDS with borders + */ + info->lcd_timing.vertical_blanking_time = + le16_to_cpu(lvds->lcd_timing.v_blanking_time); + info->lcd_timing.horizontal_sync_offset = + le16_to_cpu(lvds->lcd_timing.h_sync_offset); + info->lcd_timing.horizontal_sync_width = + le16_to_cpu(lvds->lcd_timing.h_sync_width); + info->lcd_timing.vertical_sync_offset = + le16_to_cpu(lvds->lcd_timing.v_sync_offset); + info->lcd_timing.vertical_sync_width = + le16_to_cpu(lvds->lcd_timing.v_syncwidth); + info->lcd_timing.horizontal_border = lvds->lcd_timing.h_border; + info->lcd_timing.vertical_border = lvds->lcd_timing.v_border; + + /* not provided by VBIOS */ + info->lcd_timing.misc_info.HORIZONTAL_CUT_OFF = 0; + + info->lcd_timing.misc_info.H_SYNC_POLARITY = + ~(uint32_t) + (lvds->lcd_timing.miscinfo & ATOM_HSYNC_POLARITY); + info->lcd_timing.misc_info.V_SYNC_POLARITY = + ~(uint32_t) + (lvds->lcd_timing.miscinfo & ATOM_VSYNC_POLARITY); + + /* not provided by VBIOS */ + info->lcd_timing.misc_info.VERTICAL_CUT_OFF = 0; + + info->lcd_timing.misc_info.H_REPLICATION_BY2 = + lvds->lcd_timing.miscinfo & ATOM_H_REPLICATIONBY2; + info->lcd_timing.misc_info.V_REPLICATION_BY2 = + lvds->lcd_timing.miscinfo & ATOM_V_REPLICATIONBY2; + info->lcd_timing.misc_info.COMPOSITE_SYNC = + lvds->lcd_timing.miscinfo & ATOM_COMPOSITESYNC; + info->lcd_timing.misc_info.INTERLACE = + lvds->lcd_timing.miscinfo & ATOM_INTERLACE; + + /* not provided by VBIOS*/ + info->lcd_timing.misc_info.DOUBLE_CLOCK = 0; + /* not provided by VBIOS*/ + info->ss_id = 0; + + info->realtek_eDPToLVDS = + (lvds->dplvdsrxid == eDP_TO_LVDS_REALTEK_ID ? 1:0); + + return BP_RESULT_OK; +} + +static enum bp_result bios_parser_get_embedded_panel_info( + struct dc_bios *dcb, + struct embedded_panel_info *info) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + struct atom_common_table_header *header; + struct atom_data_revision tbl_revision; + + if (!DATA_TABLES(lcd_info)) + return BP_RESULT_FAILURE; + + header = GET_IMAGE(struct atom_common_table_header, + DATA_TABLES(lcd_info)); + + if (!header) + return BP_RESULT_BADBIOSTABLE; + + get_atom_data_table_revision(header, &tbl_revision); + + + switch (tbl_revision.major) { + case 2: + switch (tbl_revision.minor) { + case 1: + return get_embedded_panel_info_v2_1(bp, info); + default: + break; + } + default: + break; + } + + return BP_RESULT_FAILURE; +} + +static uint32_t get_support_mask_for_device_id(struct device_id device_id) +{ + enum dal_device_type device_type = device_id.device_type; + uint32_t enum_id = device_id.enum_id; + + switch (device_type) { + case DEVICE_TYPE_LCD: + switch (enum_id) { + case 1: + return ATOM_DISPLAY_LCD1_SUPPORT; + default: + break; + } + break; + case DEVICE_TYPE_DFP: + switch (enum_id) { + case 1: + return ATOM_DISPLAY_DFP1_SUPPORT; + case 2: + return ATOM_DISPLAY_DFP2_SUPPORT; + case 3: + return ATOM_DISPLAY_DFP3_SUPPORT; + case 4: + return ATOM_DISPLAY_DFP4_SUPPORT; + case 5: + return ATOM_DISPLAY_DFP5_SUPPORT; + case 6: + return ATOM_DISPLAY_DFP6_SUPPORT; + default: + break; + } + break; + default: + break; + }; + + /* Unidentified device ID, return empty support mask. */ + return 0; +} + +static bool bios_parser_is_device_id_supported( + struct dc_bios *dcb, + struct device_id id) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + uint32_t mask = get_support_mask_for_device_id(id); + + return (le16_to_cpu(bp->object_info_tbl.v1_4->supporteddevices) & + mask) != 0; +} + +static void bios_parser_post_init( + struct dc_bios *dcb) +{ + /* TODO for OPM module. Need implement later */ +} + +static uint32_t bios_parser_get_ss_entry_number( + struct dc_bios *dcb, + enum as_signal_type signal) +{ + /* TODO: DAL2 atomfirmware implementation does not need this. + * why DAL3 need this? + */ + return 1; +} + +static enum bp_result bios_parser_transmitter_control( + struct dc_bios *dcb, + struct bp_transmitter_control *cntl) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!bp->cmd_tbl.transmitter_control) + return BP_RESULT_FAILURE; + + return bp->cmd_tbl.transmitter_control(bp, cntl); +} + +static enum bp_result bios_parser_encoder_control( + struct dc_bios *dcb, + struct bp_encoder_control *cntl) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!bp->cmd_tbl.dig_encoder_control) + return BP_RESULT_FAILURE; + + return bp->cmd_tbl.dig_encoder_control(bp, cntl); +} + +static enum bp_result bios_parser_set_pixel_clock( + struct dc_bios *dcb, + struct bp_pixel_clock_parameters *bp_params) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!bp->cmd_tbl.set_pixel_clock) + return BP_RESULT_FAILURE; + + return bp->cmd_tbl.set_pixel_clock(bp, bp_params); +} + +static enum bp_result bios_parser_set_dce_clock( + struct dc_bios *dcb, + struct bp_set_dce_clock_parameters *bp_params) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!bp->cmd_tbl.set_dce_clock) + return BP_RESULT_FAILURE; + + return bp->cmd_tbl.set_dce_clock(bp, bp_params); +} + +static unsigned int bios_parser_get_smu_clock_info( + struct dc_bios *dcb) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!bp->cmd_tbl.get_smu_clock_info) + return BP_RESULT_FAILURE; + + return bp->cmd_tbl.get_smu_clock_info(bp); +} + +static enum bp_result bios_parser_program_crtc_timing( + struct dc_bios *dcb, + struct bp_hw_crtc_timing_parameters *bp_params) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!bp->cmd_tbl.set_crtc_timing) + return BP_RESULT_FAILURE; + + return bp->cmd_tbl.set_crtc_timing(bp, bp_params); +} + +static enum bp_result bios_parser_enable_crtc( + struct dc_bios *dcb, + enum controller_id id, + bool enable) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!bp->cmd_tbl.enable_crtc) + return BP_RESULT_FAILURE; + + return bp->cmd_tbl.enable_crtc(bp, id, enable); +} + +static enum bp_result bios_parser_crtc_source_select( + struct dc_bios *dcb, + struct bp_crtc_source_select *bp_params) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!bp->cmd_tbl.select_crtc_source) + return BP_RESULT_FAILURE; + + return bp->cmd_tbl.select_crtc_source(bp, bp_params); +} + +static enum bp_result bios_parser_enable_disp_power_gating( + struct dc_bios *dcb, + enum controller_id controller_id, + enum bp_pipe_control_action action) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!bp->cmd_tbl.enable_disp_power_gating) + return BP_RESULT_FAILURE; + + return bp->cmd_tbl.enable_disp_power_gating(bp, controller_id, + action); +} + +static bool bios_parser_is_accelerated_mode( + struct dc_bios *dcb) +{ + return bios_is_accelerated_mode(dcb); +} + + +/** + * bios_parser_set_scratch_critical_state + * + * @brief + * update critical state bit in VBIOS scratch register + * + * @param + * bool - to set or reset state + */ +static void bios_parser_set_scratch_critical_state( + struct dc_bios *dcb, + bool state) +{ + bios_set_scratch_critical_state(dcb, state); +} + +static enum bp_result bios_parser_get_firmware_info( + struct dc_bios *dcb, + struct firmware_info *info) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + enum bp_result result = BP_RESULT_BADBIOSTABLE; + struct atom_common_table_header *header; + + struct atom_data_revision revision; + + if (info && DATA_TABLES(firmwareinfo)) { + header = GET_IMAGE(struct atom_common_table_header, + DATA_TABLES(firmwareinfo)); + get_atom_data_table_revision(header, &revision); + switch (revision.major) { + case 3: + switch (revision.minor) { + case 1: + result = get_firmware_info_v3_1(bp, info); + break; + default: + break; + } + break; + default: + break; + } + } + + return result; +} + +static enum bp_result get_firmware_info_v3_1( + struct bios_parser *bp, + struct firmware_info *info) +{ + struct atom_firmware_info_v3_1 *firmware_info; + struct atom_display_controller_info_v4_1 *dce_info = NULL; + + if (!info) + return BP_RESULT_BADINPUT; + + firmware_info = GET_IMAGE(struct atom_firmware_info_v3_1, + DATA_TABLES(firmwareinfo)); + + dce_info = GET_IMAGE(struct atom_display_controller_info_v4_1, + DATA_TABLES(dce_info)); + + if (!firmware_info || !dce_info) + return BP_RESULT_BADBIOSTABLE; + + memset(info, 0, sizeof(*info)); + + /* Pixel clock pll information. */ + /* We need to convert from 10KHz units into KHz units */ + info->default_memory_clk = firmware_info->bootup_mclk_in10khz * 10; + info->default_engine_clk = firmware_info->bootup_sclk_in10khz * 10; + + /* 27MHz for Vega10: */ + info->pll_info.crystal_frequency = dce_info->dce_refclk_10khz * 10; + + /* Hardcode frequency if BIOS gives no DCE Ref Clk */ + if (info->pll_info.crystal_frequency == 0) + info->pll_info.crystal_frequency = 27000; + + info->dp_phy_ref_clk = dce_info->dpphy_refclk_10khz * 10; + info->i2c_engine_ref_clk = dce_info->i2c_engine_refclk_10khz * 10; + + /* Get GPU PLL VCO Clock */ + + if (bp->cmd_tbl.get_smu_clock_info != NULL) { + /* VBIOS gives in 10KHz */ + info->smu_gpu_pll_output_freq = + bp->cmd_tbl.get_smu_clock_info(bp) * 10; + } + + return BP_RESULT_OK; +} + +static enum bp_result bios_parser_get_encoder_cap_info( + struct dc_bios *dcb, + struct graphics_object_id object_id, + struct bp_encoder_cap_info *info) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + struct atom_display_object_path_v2 *object; + struct atom_encoder_caps_record *record = NULL; + + if (!info) + return BP_RESULT_BADINPUT; + + object = get_bios_object(bp, object_id); + + if (!object) + return BP_RESULT_BADINPUT; + + record = get_encoder_cap_record(bp, object); + if (!record) + return BP_RESULT_NORECORD; + + info->DP_HBR2_CAP = (record->encodercaps & + ATOM_ENCODER_CAP_RECORD_HBR2) ? 1 : 0; + info->DP_HBR2_EN = (record->encodercaps & + ATOM_ENCODER_CAP_RECORD_HBR2_EN) ? 1 : 0; + info->DP_HBR3_EN = (record->encodercaps & + ATOM_ENCODER_CAP_RECORD_HBR3_EN) ? 1 : 0; + info->HDMI_6GB_EN = (record->encodercaps & + ATOM_ENCODER_CAP_RECORD_HDMI6Gbps_EN) ? 1 : 0; + + return BP_RESULT_OK; +} + + +static struct atom_encoder_caps_record *get_encoder_cap_record( + struct bios_parser *bp, + struct atom_display_object_path_v2 *object) +{ + struct atom_common_record_header *header; + uint32_t offset; + + if (!object) { + BREAK_TO_DEBUGGER(); /* Invalid object */ + return NULL; + } + + offset = object->encoder_recordoffset + bp->object_info_tbl_offset; + + for (;;) { + header = GET_IMAGE(struct atom_common_record_header, offset); + + if (!header) + return NULL; + + offset += header->record_size; + + if (header->record_type == LAST_RECORD_TYPE || + !header->record_size) + break; + + if (header->record_type != ATOM_ENCODER_CAP_RECORD_TYPE) + continue; + + if (sizeof(struct atom_encoder_caps_record) <= + header->record_size) + return (struct atom_encoder_caps_record *)header; + } + + return NULL; +} + +/* + * get_integrated_info_v11 + * + * @brief + * Get V8 integrated BIOS information + * + * @param + * bios_parser *bp - [in]BIOS parser handler to get master data table + * integrated_info *info - [out] store and output integrated info + * + * @return + * enum bp_result - BP_RESULT_OK if information is available, + * BP_RESULT_BADBIOSTABLE otherwise. + */ +static enum bp_result get_integrated_info_v11( + struct bios_parser *bp, + struct integrated_info *info) +{ + struct atom_integrated_system_info_v1_11 *info_v11; + uint32_t i; + + info_v11 = GET_IMAGE(struct atom_integrated_system_info_v1_11, + DATA_TABLES(integratedsysteminfo)); + + if (info_v11 == NULL) + return BP_RESULT_BADBIOSTABLE; + + info->gpu_cap_info = + le32_to_cpu(info_v11->gpucapinfo); + /* + * system_config: Bit[0] = 0 : PCIE power gating disabled + * = 1 : PCIE power gating enabled + * Bit[1] = 0 : DDR-PLL shut down disabled + * = 1 : DDR-PLL shut down enabled + * Bit[2] = 0 : DDR-PLL power down disabled + * = 1 : DDR-PLL power down enabled + */ + info->system_config = le32_to_cpu(info_v11->system_config); + info->cpu_cap_info = le32_to_cpu(info_v11->cpucapinfo); + info->memory_type = info_v11->memorytype; + info->ma_channel_number = info_v11->umachannelnumber; + info->lvds_ss_percentage = + le16_to_cpu(info_v11->lvds_ss_percentage); + info->lvds_sspread_rate_in_10hz = + le16_to_cpu(info_v11->lvds_ss_rate_10hz); + info->hdmi_ss_percentage = + le16_to_cpu(info_v11->hdmi_ss_percentage); + info->hdmi_sspread_rate_in_10hz = + le16_to_cpu(info_v11->hdmi_ss_rate_10hz); + info->dvi_ss_percentage = + le16_to_cpu(info_v11->dvi_ss_percentage); + info->dvi_sspread_rate_in_10_hz = + le16_to_cpu(info_v11->dvi_ss_rate_10hz); + info->lvds_misc = info_v11->lvds_misc; + for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) { + info->ext_disp_conn_info.gu_id[i] = + info_v11->extdispconninfo.guid[i]; + } + + for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) { + info->ext_disp_conn_info.path[i].device_connector_id = + object_id_from_bios_object_id( + le16_to_cpu(info_v11->extdispconninfo.path[i].connectorobjid)); + + info->ext_disp_conn_info.path[i].ext_encoder_obj_id = + object_id_from_bios_object_id( + le16_to_cpu( + info_v11->extdispconninfo.path[i].ext_encoder_objid)); + + info->ext_disp_conn_info.path[i].device_tag = + le16_to_cpu( + info_v11->extdispconninfo.path[i].device_tag); + info->ext_disp_conn_info.path[i].device_acpi_enum = + le16_to_cpu( + info_v11->extdispconninfo.path[i].device_acpi_enum); + info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index = + info_v11->extdispconninfo.path[i].auxddclut_index; + info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index = + info_v11->extdispconninfo.path[i].hpdlut_index; + info->ext_disp_conn_info.path[i].channel_mapping.raw = + info_v11->extdispconninfo.path[i].channelmapping; + } + info->ext_disp_conn_info.checksum = + info_v11->extdispconninfo.checksum; + + /** TODO - review **/ + #if 0 + info->boot_up_engine_clock = le32_to_cpu(info_v11->ulBootUpEngineClock) + * 10; + info->dentist_vco_freq = le32_to_cpu(info_v11->ulDentistVCOFreq) * 10; + info->boot_up_uma_clock = le32_to_cpu(info_v8->ulBootUpUMAClock) * 10; + + for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) { + /* Convert [10KHz] into [KHz] */ + info->disp_clk_voltage[i].max_supported_clk = + le32_to_cpu(info_v11->sDISPCLK_Voltage[i]. + ulMaximumSupportedCLK) * 10; + info->disp_clk_voltage[i].voltage_index = + le32_to_cpu(info_v11->sDISPCLK_Voltage[i].ulVoltageIndex); + } + + info->boot_up_req_display_vector = + le32_to_cpu(info_v11->ulBootUpReqDisplayVector); + info->boot_up_nb_voltage = + le16_to_cpu(info_v11->usBootUpNBVoltage); + info->ext_disp_conn_info_offset = + le16_to_cpu(info_v11->usExtDispConnInfoOffset); + info->gmc_restore_reset_time = + le32_to_cpu(info_v11->ulGMCRestoreResetTime); + info->minimum_n_clk = + le32_to_cpu(info_v11->ulNbpStateNClkFreq[0]); + for (i = 1; i < 4; ++i) + info->minimum_n_clk = + info->minimum_n_clk < + le32_to_cpu(info_v11->ulNbpStateNClkFreq[i]) ? + info->minimum_n_clk : le32_to_cpu( + info_v11->ulNbpStateNClkFreq[i]); + + info->idle_n_clk = le32_to_cpu(info_v11->ulIdleNClk); + info->ddr_dll_power_up_time = + le32_to_cpu(info_v11->ulDDR_DLL_PowerUpTime); + info->ddr_pll_power_up_time = + le32_to_cpu(info_v11->ulDDR_PLL_PowerUpTime); + info->pcie_clk_ss_type = le16_to_cpu(info_v11->usPCIEClkSSType); + info->max_lvds_pclk_freq_in_single_link = + le16_to_cpu(info_v11->usMaxLVDSPclkFreqInSingleLink); + info->max_lvds_pclk_freq_in_single_link = + le16_to_cpu(info_v11->usMaxLVDSPclkFreqInSingleLink); + info->lvds_pwr_on_seq_dig_on_to_de_in_4ms = + info_v11->ucLVDSPwrOnSeqDIGONtoDE_in4Ms; + info->lvds_pwr_on_seq_de_to_vary_bl_in_4ms = + info_v11->ucLVDSPwrOnSeqDEtoVARY_BL_in4Ms; + info->lvds_pwr_on_seq_vary_bl_to_blon_in_4ms = + info_v11->ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms; + info->lvds_pwr_off_seq_vary_bl_to_de_in4ms = + info_v11->ucLVDSPwrOffSeqVARY_BLtoDE_in4Ms; + info->lvds_pwr_off_seq_de_to_dig_on_in4ms = + info_v11->ucLVDSPwrOffSeqDEtoDIGON_in4Ms; + info->lvds_pwr_off_seq_blon_to_vary_bl_in_4ms = + info_v11->ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms; + info->lvds_off_to_on_delay_in_4ms = + info_v11->ucLVDSOffToOnDelay_in4Ms; + info->lvds_bit_depth_control_val = + le32_to_cpu(info_v11->ulLCDBitDepthControlVal); + + for (i = 0; i < NUMBER_OF_AVAILABLE_SCLK; ++i) { + /* Convert [10KHz] into [KHz] */ + info->avail_s_clk[i].supported_s_clk = + le32_to_cpu(info_v11->sAvail_SCLK[i].ulSupportedSCLK) + * 10; + info->avail_s_clk[i].voltage_index = + le16_to_cpu(info_v11->sAvail_SCLK[i].usVoltageIndex); + info->avail_s_clk[i].voltage_id = + le16_to_cpu(info_v11->sAvail_SCLK[i].usVoltageID); + } + #endif /* TODO*/ + + return BP_RESULT_OK; +} + + +/* + * construct_integrated_info + * + * @brief + * Get integrated BIOS information based on table revision + * + * @param + * bios_parser *bp - [in]BIOS parser handler to get master data table + * integrated_info *info - [out] store and output integrated info + * + * @return + * enum bp_result - BP_RESULT_OK if information is available, + * BP_RESULT_BADBIOSTABLE otherwise. + */ +static enum bp_result construct_integrated_info( + struct bios_parser *bp, + struct integrated_info *info) +{ + enum bp_result result = BP_RESULT_BADBIOSTABLE; + + struct atom_common_table_header *header; + struct atom_data_revision revision; + + struct clock_voltage_caps temp = {0, 0}; + uint32_t i; + uint32_t j; + + if (info && DATA_TABLES(integratedsysteminfo)) { + header = GET_IMAGE(struct atom_common_table_header, + DATA_TABLES(integratedsysteminfo)); + + get_atom_data_table_revision(header, &revision); + + /* Don't need to check major revision as they are all 1 */ + switch (revision.minor) { + case 11: + result = get_integrated_info_v11(bp, info); + break; + default: + return result; + } + } + + if (result != BP_RESULT_OK) + return result; + + /* Sort voltage table from low to high*/ + for (i = 1; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) { + for (j = i; j > 0; --j) { + if (info->disp_clk_voltage[j].max_supported_clk < + info->disp_clk_voltage[j-1].max_supported_clk + ) { + /* swap j and j - 1*/ + temp = info->disp_clk_voltage[j-1]; + info->disp_clk_voltage[j-1] = + info->disp_clk_voltage[j]; + info->disp_clk_voltage[j] = temp; + } + } + } + + return result; +} + +static struct integrated_info *bios_parser_create_integrated_info( + struct dc_bios *dcb) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + struct integrated_info *info = NULL; + + info = dm_alloc(sizeof(struct integrated_info)); + + if (info == NULL) { + ASSERT_CRITICAL(0); + return NULL; + } + + if (construct_integrated_info(bp, info) == BP_RESULT_OK) + return info; + + dm_free(info); + + return NULL; +} + +static const struct dc_vbios_funcs vbios_funcs = { + .get_connectors_number = bios_parser_get_connectors_number, + + .get_encoder_id = bios_parser_get_encoder_id, + + .get_connector_id = bios_parser_get_connector_id, + + .get_dst_number = bios_parser_get_dst_number, + + .get_src_obj = bios_parser_get_src_obj, + + .get_dst_obj = bios_parser_get_dst_obj, + + .get_i2c_info = bios_parser_get_i2c_info, + + .get_voltage_ddc_info = bios_parser_get_voltage_ddc_info, + + .get_thermal_ddc_info = bios_parser_get_thermal_ddc_info, + + .get_hpd_info = bios_parser_get_hpd_info, + + .get_device_tag = bios_parser_get_device_tag, + + .get_firmware_info = bios_parser_get_firmware_info, + + .get_spread_spectrum_info = bios_parser_get_spread_spectrum_info, + + .get_ss_entry_number = bios_parser_get_ss_entry_number, + + .get_embedded_panel_info = bios_parser_get_embedded_panel_info, + + .get_gpio_pin_info = bios_parser_get_gpio_pin_info, + + .get_encoder_cap_info = bios_parser_get_encoder_cap_info, + + .is_device_id_supported = bios_parser_is_device_id_supported, + + + + .is_accelerated_mode = bios_parser_is_accelerated_mode, + + .set_scratch_critical_state = bios_parser_set_scratch_critical_state, + + +/* COMMANDS */ + .encoder_control = bios_parser_encoder_control, + + .transmitter_control = bios_parser_transmitter_control, + + .enable_crtc = bios_parser_enable_crtc, + + .set_pixel_clock = bios_parser_set_pixel_clock, + + .set_dce_clock = bios_parser_set_dce_clock, + + .program_crtc_timing = bios_parser_program_crtc_timing, + + /* .blank_crtc = bios_parser_blank_crtc, */ + + .crtc_source_select = bios_parser_crtc_source_select, + + /* .external_encoder_control = bios_parser_external_encoder_control, */ + + .enable_disp_power_gating = bios_parser_enable_disp_power_gating, + + .post_init = bios_parser_post_init, + + .bios_parser_destroy = firmware_parser_destroy, + + .get_smu_clock_info = bios_parser_get_smu_clock_info, +}; + +static bool bios_parser_construct( + struct bios_parser *bp, + struct bp_init_data *init, + enum dce_version dce_version) +{ + uint16_t *rom_header_offset = NULL; + struct atom_rom_header_v2_2 *rom_header = NULL; + struct display_object_info_table_v1_4 *object_info_tbl; + struct atom_data_revision tbl_rev = {0}; + + if (!init) + return false; + + if (!init->bios) + return false; + + bp->base.funcs = &vbios_funcs; + bp->base.bios = init->bios; + bp->base.bios_size = bp->base.bios[OFFSET_TO_ATOM_ROM_IMAGE_SIZE] * BIOS_IMAGE_SIZE_UNIT; + + bp->base.ctx = init->ctx; + + bp->base.bios_local_image = NULL; + + rom_header_offset = + GET_IMAGE(uint16_t, OFFSET_TO_ATOM_ROM_HEADER_POINTER); + + if (!rom_header_offset) + return false; + + rom_header = GET_IMAGE(struct atom_rom_header_v2_2, *rom_header_offset); + + if (!rom_header) + return false; + + get_atom_data_table_revision(&rom_header->table_header, &tbl_rev); + if (!(tbl_rev.major >= 2 && tbl_rev.minor >= 2)) + return false; + + bp->master_data_tbl = + GET_IMAGE(struct atom_master_data_table_v2_1, + rom_header->masterdatatable_offset); + + if (!bp->master_data_tbl) + return false; + + bp->object_info_tbl_offset = DATA_TABLES(displayobjectinfo); + + if (!bp->object_info_tbl_offset) + return false; + + object_info_tbl = + GET_IMAGE(struct display_object_info_table_v1_4, + bp->object_info_tbl_offset); + + if (!object_info_tbl) + return false; + + get_atom_data_table_revision(&object_info_tbl->table_header, + &bp->object_info_tbl.revision); + + if (bp->object_info_tbl.revision.major == 1 + && bp->object_info_tbl.revision.minor >= 4) { + struct display_object_info_table_v1_4 *tbl_v1_4; + + tbl_v1_4 = GET_IMAGE(struct display_object_info_table_v1_4, + bp->object_info_tbl_offset); + if (!tbl_v1_4) + return false; + + bp->object_info_tbl.v1_4 = tbl_v1_4; + } else + return false; + + dal_firmware_parser_init_cmd_tbl(bp); + dal_bios_parser_init_cmd_tbl_helper2(&bp->cmd_helper, dce_version); + + bp->base.integrated_info = bios_parser_create_integrated_info(&bp->base); + + return true; +} + +struct dc_bios *firmware_parser_create( + struct bp_init_data *init, + enum dce_version dce_version) +{ + struct bios_parser *bp = NULL; + + bp = dm_alloc(sizeof(struct bios_parser)); + if (!bp) + return NULL; + + if (bios_parser_construct(bp, init, dce_version)) + return &bp->base; + + dm_free(bp); + return NULL; +} + + diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.h b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.h new file mode 100644 index 000000000000..cb40546cdafe --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.h @@ -0,0 +1,33 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_BIOS_PARSER2_H__ +#define __DAL_BIOS_PARSER2_H__ + +struct dc_bios *firmware_parser_create( + struct bp_init_data *init, + enum dce_version dce_version); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_types_internal2.h b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_types_internal2.h new file mode 100644 index 000000000000..bf1f5c86e65c --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_types_internal2.h @@ -0,0 +1,74 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_BIOS_PARSER_TYPES_BIOS2_H__ +#define __DAL_BIOS_PARSER_TYPES_BIOS2_H__ + +#include "dc_bios_types.h" +#include "bios_parser_helper.h" + +/* use atomfirmware_bringup.h only. Not atombios.h anymore */ + +struct atom_data_revision { + uint32_t major; + uint32_t minor; +}; + +struct object_info_table { + struct atom_data_revision revision; + union { + struct display_object_info_table_v1_4 *v1_4; + }; +}; + +enum spread_spectrum_id { + SS_ID_UNKNOWN = 0, + SS_ID_DP1 = 0xf1, + SS_ID_DP2 = 0xf2, + SS_ID_LVLINK_2700MHZ = 0xf3, + SS_ID_LVLINK_1620MHZ = 0xf4 +}; + +struct bios_parser { + struct dc_bios base; + + struct object_info_table object_info_tbl; + uint32_t object_info_tbl_offset; + struct atom_master_data_table_v2_1 *master_data_tbl; + + + const struct bios_parser_helper *bios_helper; + + const struct command_table_helper *cmd_helper; + struct cmd_tbl cmd_tbl; + + bool remap_device_tags; +}; + +/* Bios Parser from DC Bios */ +#define BP_FROM_DCB(dc_bios) \ + container_of(dc_bios, struct bios_parser, base) + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c new file mode 100644 index 000000000000..36d158249182 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c @@ -0,0 +1,813 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "ObjectID.h" +#include "atomfirmware.h" +#include "atomfirmwareid.h" + +#include "include/bios_parser_interface.h" + +#include "command_table2.h" +#include "command_table_helper2.h" +#include "bios_parser_helper.h" +#include "bios_parser_types_internal2.h" + +#define GET_INDEX_INTO_MASTER_TABLE(MasterOrData, FieldName)\ + (((char *)(&((\ + struct atom_master_list_of_##MasterOrData##_functions_v2_1 *)0)\ + ->FieldName)-(char *)0)/sizeof(uint16_t)) + +#define EXEC_BIOS_CMD_TABLE(fname, params)\ + (cgs_atom_exec_cmd_table(bp->base.ctx->cgs_device, \ + GET_INDEX_INTO_MASTER_TABLE(command, fname), \ + ¶ms) == 0) + +#define BIOS_CMD_TABLE_REVISION(fname, frev, crev)\ + cgs_atom_get_cmd_table_revs(bp->base.ctx->cgs_device, \ + GET_INDEX_INTO_MASTER_TABLE(command, fname), &frev, &crev) + +#define BIOS_CMD_TABLE_PARA_REVISION(fname)\ + bios_cmd_table_para_revision(bp->base.ctx->cgs_device, \ + GET_INDEX_INTO_MASTER_TABLE(command, fname)) + +static void init_dig_encoder_control(struct bios_parser *bp); +static void init_transmitter_control(struct bios_parser *bp); +static void init_set_pixel_clock(struct bios_parser *bp); + +static void init_set_crtc_timing(struct bios_parser *bp); + +static void init_select_crtc_source(struct bios_parser *bp); +static void init_enable_crtc(struct bios_parser *bp); + +static void init_external_encoder_control(struct bios_parser *bp); +static void init_enable_disp_power_gating(struct bios_parser *bp); +static void init_set_dce_clock(struct bios_parser *bp); +static void init_get_smu_clock_info(struct bios_parser *bp); + +void dal_firmware_parser_init_cmd_tbl(struct bios_parser *bp) +{ + init_dig_encoder_control(bp); + init_transmitter_control(bp); + init_set_pixel_clock(bp); + + init_set_crtc_timing(bp); + + init_select_crtc_source(bp); + init_enable_crtc(bp); + + init_external_encoder_control(bp); + init_enable_disp_power_gating(bp); + init_set_dce_clock(bp); + init_get_smu_clock_info(bp); +} + +static uint32_t bios_cmd_table_para_revision(void *cgs_device, + uint32_t index) +{ + uint8_t frev, crev; + + if (cgs_atom_get_cmd_table_revs(cgs_device, + index, + &frev, &crev) != 0) + return 0; + return crev; +} + +/****************************************************************************** + ****************************************************************************** + ** + ** D I G E N C O D E R C O N T R O L + ** + ****************************************************************************** + *****************************************************************************/ + +static enum bp_result encoder_control_digx_v1_5( + struct bios_parser *bp, + struct bp_encoder_control *cntl); + +static void init_dig_encoder_control(struct bios_parser *bp) +{ + uint32_t version = + BIOS_CMD_TABLE_PARA_REVISION(digxencodercontrol); + + switch (version) { + case 5: + bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v1_5; + break; + default: + bp->cmd_tbl.dig_encoder_control = NULL; + break; + } +} + +static enum bp_result encoder_control_digx_v1_5( + struct bios_parser *bp, + struct bp_encoder_control *cntl) +{ + enum bp_result result = BP_RESULT_FAILURE; + struct dig_encoder_stream_setup_parameters_v1_5 params = {0}; + + params.digid = (uint8_t)(cntl->engine_id); + params.action = bp->cmd_helper->encoder_action_to_atom(cntl->action); + + params.pclk_10khz = cntl->pixel_clock / 10; + params.digmode = + (uint8_t)(bp->cmd_helper->encoder_mode_bp_to_atom( + cntl->signal, + cntl->enable_dp_audio)); + params.lanenum = (uint8_t)(cntl->lanes_number); + + switch (cntl->color_depth) { + case COLOR_DEPTH_888: + params.bitpercolor = PANEL_8BIT_PER_COLOR; + break; + case COLOR_DEPTH_101010: + params.bitpercolor = PANEL_10BIT_PER_COLOR; + break; + case COLOR_DEPTH_121212: + params.bitpercolor = PANEL_12BIT_PER_COLOR; + break; + case COLOR_DEPTH_161616: + params.bitpercolor = PANEL_16BIT_PER_COLOR; + break; + default: + break; + } + + if (cntl->signal == SIGNAL_TYPE_HDMI_TYPE_A) + switch (cntl->color_depth) { + case COLOR_DEPTH_101010: + params.pclk_10khz = + (params.pclk_10khz * 30) / 24; + break; + case COLOR_DEPTH_121212: + params.pclk_10khz = + (params.pclk_10khz * 36) / 24; + break; + case COLOR_DEPTH_161616: + params.pclk_10khz = + (params.pclk_10khz * 48) / 24; + break; + default: + break; + } + + if (EXEC_BIOS_CMD_TABLE(digxencodercontrol, params)) + result = BP_RESULT_OK; + + return result; +} + +/***************************************************************************** + ****************************************************************************** + ** + ** TRANSMITTER CONTROL + ** + ****************************************************************************** + *****************************************************************************/ + +static enum bp_result transmitter_control_v1_6( + struct bios_parser *bp, + struct bp_transmitter_control *cntl); + +static void init_transmitter_control(struct bios_parser *bp) +{ + uint8_t frev; + uint8_t crev; + + if (BIOS_CMD_TABLE_REVISION(dig1transmittercontrol, frev, crev) != 0) + BREAK_TO_DEBUGGER(); + switch (crev) { + case 6: + bp->cmd_tbl.transmitter_control = transmitter_control_v1_6; + break; + default: + bp->cmd_tbl.transmitter_control = NULL; + break; + } +} + +static enum bp_result transmitter_control_v1_6( + struct bios_parser *bp, + struct bp_transmitter_control *cntl) +{ + enum bp_result result = BP_RESULT_FAILURE; + const struct command_table_helper *cmd = bp->cmd_helper; + struct dig_transmitter_control_ps_allocation_v1_6 ps = { { 0 } }; + + ps.param.phyid = cmd->phy_id_to_atom(cntl->transmitter); + ps.param.action = (uint8_t)cntl->action; + + if (cntl->action == TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS) + ps.param.mode_laneset.dplaneset = (uint8_t)cntl->lane_settings; + else + ps.param.mode_laneset.digmode = + cmd->signal_type_to_atom_dig_mode(cntl->signal); + + ps.param.lanenum = (uint8_t)cntl->lanes_number; + ps.param.hpdsel = cmd->hpd_sel_to_atom(cntl->hpd_sel); + ps.param.digfe_sel = cmd->dig_encoder_sel_to_atom(cntl->engine_id); + ps.param.connobj_id = (uint8_t)cntl->connector_obj_id.id; + ps.param.symclk_10khz = cntl->pixel_clock/10; + + + if (cntl->action == TRANSMITTER_CONTROL_ENABLE || + cntl->action == TRANSMITTER_CONTROL_ACTIAVATE || + cntl->action == TRANSMITTER_CONTROL_DEACTIVATE) { + dm_logger_write(bp->base.ctx->logger, LOG_HW_SET_MODE,\ + "************************%s:ps.param.symclk_10khz = %d\n",\ + __func__, ps.param.symclk_10khz); + } + + +/*color_depth not used any more, driver has deep color factor in the Phyclk*/ + if (EXEC_BIOS_CMD_TABLE(dig1transmittercontrol, ps)) + result = BP_RESULT_OK; + return result; +} + +/****************************************************************************** + ****************************************************************************** + ** + ** SET PIXEL CLOCK + ** + ****************************************************************************** + *****************************************************************************/ + +static enum bp_result set_pixel_clock_v7( + struct bios_parser *bp, + struct bp_pixel_clock_parameters *bp_params); + +static void init_set_pixel_clock(struct bios_parser *bp) +{ + switch (BIOS_CMD_TABLE_PARA_REVISION(setpixelclock)) { + case 7: + bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v7; + break; + default: + bp->cmd_tbl.set_pixel_clock = NULL; + break; + } +} + + + +static enum bp_result set_pixel_clock_v7( + struct bios_parser *bp, + struct bp_pixel_clock_parameters *bp_params) +{ + enum bp_result result = BP_RESULT_FAILURE; + struct set_pixel_clock_parameter_v1_7 clk; + uint8_t controller_id; + uint32_t pll_id; + + memset(&clk, 0, sizeof(clk)); + + if (bp->cmd_helper->clock_source_id_to_atom(bp_params->pll_id, &pll_id) + && bp->cmd_helper->controller_id_to_atom(bp_params-> + controller_id, &controller_id)) { + /* Note: VBIOS still wants to use ucCRTC name which is now + * 1 byte in ULONG + *typedef struct _CRTC_PIXEL_CLOCK_FREQ + *{ + * target the pixel clock to drive the CRTC timing. + * ULONG ulPixelClock:24; + * 0 means disable PPLL/DCPLL. Expanded to 24 bits comparing to + * previous version. + * ATOM_CRTC1~6, indicate the CRTC controller to + * ULONG ucCRTC:8; + * drive the pixel clock. not used for DCPLL case. + *}CRTC_PIXEL_CLOCK_FREQ; + *union + *{ + * pixel clock and CRTC id frequency + * CRTC_PIXEL_CLOCK_FREQ ulCrtcPclkFreq; + * ULONG ulDispEngClkFreq; dispclk frequency + *}; + */ + clk.crtc_id = controller_id; + clk.pll_id = (uint8_t) pll_id; + clk.encoderobjid = + bp->cmd_helper->encoder_id_to_atom( + dal_graphics_object_id_get_encoder_id( + bp_params->encoder_object_id)); + + clk.encoder_mode = (uint8_t) bp-> + cmd_helper->encoder_mode_bp_to_atom( + bp_params->signal_type, false); + + /* We need to convert from KHz units into 10KHz units */ + clk.pixclk_100hz = cpu_to_le32(bp_params->target_pixel_clock * + 10); + + clk.deep_color_ratio = + (uint8_t) bp->cmd_helper-> + transmitter_color_depth_to_atom( + bp_params->color_depth); + dm_logger_write(bp->base.ctx->logger, LOG_HW_SET_MODE,\ + "************************%s:program display clock = %d"\ + "colorDepth = %d\n", __func__,\ + bp_params->target_pixel_clock, bp_params->color_depth); + + if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL) + clk.miscinfo |= PIXEL_CLOCK_V7_MISC_FORCE_PROG_PPLL; + + if (bp_params->flags.PROGRAM_PHY_PLL_ONLY) + clk.miscinfo |= PIXEL_CLOCK_V7_MISC_PROG_PHYPLL; + + if (bp_params->flags.SUPPORT_YUV_420) + clk.miscinfo |= PIXEL_CLOCK_V7_MISC_YUV420_MODE; + + if (bp_params->flags.SET_XTALIN_REF_SRC) + clk.miscinfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC_XTALIN; + + if (bp_params->flags.SET_GENLOCK_REF_DIV_SRC) + clk.miscinfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC_GENLK; + + if (bp_params->signal_type == SIGNAL_TYPE_DVI_DUAL_LINK) + clk.miscinfo |= PIXEL_CLOCK_V7_MISC_DVI_DUALLINK_EN; + + if (EXEC_BIOS_CMD_TABLE(setpixelclock, clk)) + result = BP_RESULT_OK; + } + return result; +} + +/****************************************************************************** + ****************************************************************************** + ** + ** SET CRTC TIMING + ** + ****************************************************************************** + *****************************************************************************/ + +static enum bp_result set_crtc_using_dtd_timing_v3( + struct bios_parser *bp, + struct bp_hw_crtc_timing_parameters *bp_params); + +static void init_set_crtc_timing(struct bios_parser *bp) +{ + uint32_t dtd_version = + BIOS_CMD_TABLE_PARA_REVISION(setcrtc_usingdtdtiming); + + switch (dtd_version) { + case 3: + bp->cmd_tbl.set_crtc_timing = + set_crtc_using_dtd_timing_v3; + break; + default: + bp->cmd_tbl.set_crtc_timing = NULL; + break; + } +} + +static enum bp_result set_crtc_using_dtd_timing_v3( + struct bios_parser *bp, + struct bp_hw_crtc_timing_parameters *bp_params) +{ + enum bp_result result = BP_RESULT_FAILURE; + struct set_crtc_using_dtd_timing_parameters params = {0}; + uint8_t atom_controller_id; + + if (bp->cmd_helper->controller_id_to_atom( + bp_params->controller_id, &atom_controller_id)) + params.crtc_id = atom_controller_id; + + /* bios usH_Size wants h addressable size */ + params.h_size = cpu_to_le16((uint16_t)bp_params->h_addressable); + /* bios usH_Blanking_Time wants borders included in blanking */ + params.h_blanking_time = + cpu_to_le16((uint16_t)(bp_params->h_total - + bp_params->h_addressable)); + /* bios usV_Size wants v addressable size */ + params.v_size = cpu_to_le16((uint16_t)bp_params->v_addressable); + /* bios usV_Blanking_Time wants borders included in blanking */ + params.v_blanking_time = + cpu_to_le16((uint16_t)(bp_params->v_total - + bp_params->v_addressable)); + /* bios usHSyncOffset is the offset from the end of h addressable, + * our horizontalSyncStart is the offset from the beginning + * of h addressable + */ + params.h_syncoffset = + cpu_to_le16((uint16_t)(bp_params->h_sync_start - + bp_params->h_addressable)); + params.h_syncwidth = cpu_to_le16((uint16_t)bp_params->h_sync_width); + /* bios usHSyncOffset is the offset from the end of v addressable, + * our verticalSyncStart is the offset from the beginning of + * v addressable + */ + params.v_syncoffset = + cpu_to_le16((uint16_t)(bp_params->v_sync_start - + bp_params->v_addressable)); + params.v_syncwidth = cpu_to_le16((uint16_t)bp_params->v_sync_width); + + /* we assume that overscan from original timing does not get bigger + * than 255 + * we will program all the borders in the Set CRTC Overscan call below + */ + + if (bp_params->flags.HSYNC_POSITIVE_POLARITY == 0) + params.modemiscinfo = + cpu_to_le16(le16_to_cpu(params.modemiscinfo) | + ATOM_HSYNC_POLARITY); + + if (bp_params->flags.VSYNC_POSITIVE_POLARITY == 0) + params.modemiscinfo = + cpu_to_le16(le16_to_cpu(params.modemiscinfo) | + ATOM_VSYNC_POLARITY); + + if (bp_params->flags.INTERLACE) { + params.modemiscinfo = + cpu_to_le16(le16_to_cpu(params.modemiscinfo) | + ATOM_INTERLACE); + + /* original DAL code has this condition to apply this + * for non-TV/CV only + * due to complex MV testing for possible impact + * if ( pACParameters->signal != SignalType_YPbPr && + * pACParameters->signal != SignalType_Composite && + * pACParameters->signal != SignalType_SVideo) + */ + { + /* HW will deduct 0.5 line from 2nd feild. + * i.e. for 1080i, it is 2 lines for 1st field, + * 2.5 lines for the 2nd feild. we need input as 5 + * instead of 4. + * but it is 4 either from Edid data (spec CEA 861) + * or CEA timing table. + */ + params.v_syncoffset = + cpu_to_le16(le16_to_cpu(params.v_syncoffset) + + 1); + + } + } + + if (bp_params->flags.HORZ_COUNT_BY_TWO) + params.modemiscinfo = + cpu_to_le16(le16_to_cpu(params.modemiscinfo) | + 0x100); /* ATOM_DOUBLE_CLOCK_MODE */ + + if (EXEC_BIOS_CMD_TABLE(setcrtc_usingdtdtiming, params)) + result = BP_RESULT_OK; + + return result; +} + +/****************************************************************************** + ****************************************************************************** + ** + ** SELECT CRTC SOURCE + ** + ****************************************************************************** + *****************************************************************************/ + + +static enum bp_result select_crtc_source_v3( + struct bios_parser *bp, + struct bp_crtc_source_select *bp_params); + +static void init_select_crtc_source(struct bios_parser *bp) +{ + switch (BIOS_CMD_TABLE_PARA_REVISION(selectcrtc_source)) { + case 3: + bp->cmd_tbl.select_crtc_source = select_crtc_source_v3; + break; + default: + bp->cmd_tbl.select_crtc_source = NULL; + break; + } +} + + +static enum bp_result select_crtc_source_v3( + struct bios_parser *bp, + struct bp_crtc_source_select *bp_params) +{ + bool result = BP_RESULT_FAILURE; + struct select_crtc_source_parameters_v2_3 params; + uint8_t atom_controller_id; + uint32_t atom_engine_id; + enum signal_type s = bp_params->signal; + + memset(¶ms, 0, sizeof(params)); + + if (bp->cmd_helper->controller_id_to_atom(bp_params->controller_id, + &atom_controller_id)) + params.crtc_id = atom_controller_id; + else + return result; + + if (bp->cmd_helper->engine_bp_to_atom(bp_params->engine_id, + &atom_engine_id)) + params.encoder_id = (uint8_t)atom_engine_id; + else + return result; + + if (s == SIGNAL_TYPE_EDP || + (s == SIGNAL_TYPE_DISPLAY_PORT && bp_params->sink_signal == + SIGNAL_TYPE_LVDS)) + s = SIGNAL_TYPE_LVDS; + + params.encode_mode = + bp->cmd_helper->encoder_mode_bp_to_atom( + s, bp_params->enable_dp_audio); + /* Needed for VBIOS Random Spatial Dithering feature */ + params.dst_bpc = (uint8_t)(bp_params->display_output_bit_depth); + + if (EXEC_BIOS_CMD_TABLE(selectcrtc_source, params)) + result = BP_RESULT_OK; + + return result; +} + +/****************************************************************************** + ****************************************************************************** + ** + ** ENABLE CRTC + ** + ****************************************************************************** + *****************************************************************************/ + +static enum bp_result enable_crtc_v1( + struct bios_parser *bp, + enum controller_id controller_id, + bool enable); + +static void init_enable_crtc(struct bios_parser *bp) +{ + switch (BIOS_CMD_TABLE_PARA_REVISION(enablecrtc)) { + case 1: + bp->cmd_tbl.enable_crtc = enable_crtc_v1; + break; + default: + bp->cmd_tbl.enable_crtc = NULL; + break; + } +} + +static enum bp_result enable_crtc_v1( + struct bios_parser *bp, + enum controller_id controller_id, + bool enable) +{ + bool result = BP_RESULT_FAILURE; + struct enable_crtc_parameters params = {0}; + uint8_t id; + + if (bp->cmd_helper->controller_id_to_atom(controller_id, &id)) + params.crtc_id = id; + else + return BP_RESULT_BADINPUT; + + if (enable) + params.enable = ATOM_ENABLE; + else + params.enable = ATOM_DISABLE; + + if (EXEC_BIOS_CMD_TABLE(enablecrtc, params)) + result = BP_RESULT_OK; + + return result; +} + +/****************************************************************************** + ****************************************************************************** + ** + ** DISPLAY PLL + ** + ****************************************************************************** + *****************************************************************************/ + + + +/****************************************************************************** + ****************************************************************************** + ** + ** EXTERNAL ENCODER CONTROL + ** + ****************************************************************************** + *****************************************************************************/ + +static enum bp_result external_encoder_control_v3( + struct bios_parser *bp, + struct bp_external_encoder_control *cntl); + +static void init_external_encoder_control( + struct bios_parser *bp) +{ + switch (BIOS_CMD_TABLE_PARA_REVISION(externalencodercontrol)) { + case 3: + bp->cmd_tbl.external_encoder_control = + external_encoder_control_v3; + break; + default: + bp->cmd_tbl.external_encoder_control = NULL; + break; + } +} + +static enum bp_result external_encoder_control_v3( + struct bios_parser *bp, + struct bp_external_encoder_control *cntl) +{ + /* TODO */ + return BP_RESULT_OK; +} + +/****************************************************************************** + ****************************************************************************** + ** + ** ENABLE DISPLAY POWER GATING + ** + ****************************************************************************** + *****************************************************************************/ + +static enum bp_result enable_disp_power_gating_v2_1( + struct bios_parser *bp, + enum controller_id crtc_id, + enum bp_pipe_control_action action); + +static void init_enable_disp_power_gating( + struct bios_parser *bp) +{ + switch (BIOS_CMD_TABLE_PARA_REVISION(enabledisppowergating)) { + case 1: + bp->cmd_tbl.enable_disp_power_gating = + enable_disp_power_gating_v2_1; + break; + default: + bp->cmd_tbl.enable_disp_power_gating = NULL; + break; + } +} + +static enum bp_result enable_disp_power_gating_v2_1( + struct bios_parser *bp, + enum controller_id crtc_id, + enum bp_pipe_control_action action) +{ + enum bp_result result = BP_RESULT_FAILURE; + + + struct enable_disp_power_gating_ps_allocation ps = { { 0 } }; + uint8_t atom_crtc_id; + + if (bp->cmd_helper->controller_id_to_atom(crtc_id, &atom_crtc_id)) + ps.param.disp_pipe_id = atom_crtc_id; + else + return BP_RESULT_BADINPUT; + + ps.param.enable = + bp->cmd_helper->disp_power_gating_action_to_atom(action); + + if (EXEC_BIOS_CMD_TABLE(enabledisppowergating, ps.param)) + result = BP_RESULT_OK; + + return result; +} + +/****************************************************************************** +******************************************************************************* + ** + ** SET DCE CLOCK + ** +******************************************************************************* +*******************************************************************************/ + +static enum bp_result set_dce_clock_v2_1( + struct bios_parser *bp, + struct bp_set_dce_clock_parameters *bp_params); + +static void init_set_dce_clock(struct bios_parser *bp) +{ + switch (BIOS_CMD_TABLE_PARA_REVISION(setdceclock)) { + case 1: + bp->cmd_tbl.set_dce_clock = set_dce_clock_v2_1; + break; + default: + bp->cmd_tbl.set_dce_clock = NULL; + break; + } +} + +static enum bp_result set_dce_clock_v2_1( + struct bios_parser *bp, + struct bp_set_dce_clock_parameters *bp_params) +{ + enum bp_result result = BP_RESULT_FAILURE; + + struct set_dce_clock_ps_allocation_v2_1 params; + uint32_t atom_pll_id; + uint32_t atom_clock_type; + const struct command_table_helper *cmd = bp->cmd_helper; + + memset(¶ms, 0, sizeof(params)); + + if (!cmd->clock_source_id_to_atom(bp_params->pll_id, &atom_pll_id) || + !cmd->dc_clock_type_to_atom(bp_params->clock_type, + &atom_clock_type)) + return BP_RESULT_BADINPUT; + + params.param.dceclksrc = atom_pll_id; + params.param.dceclktype = atom_clock_type; + + if (bp_params->clock_type == DCECLOCK_TYPE_DPREFCLK) { + if (bp_params->flags.USE_GENLOCK_AS_SOURCE_FOR_DPREFCLK) + params.param.dceclkflag |= + DCE_CLOCK_FLAG_PLL_REFCLK_SRC_GENLK; + + if (bp_params->flags.USE_PCIE_AS_SOURCE_FOR_DPREFCLK) + params.param.dceclkflag |= + DCE_CLOCK_FLAG_PLL_REFCLK_SRC_PCIE; + + if (bp_params->flags.USE_XTALIN_AS_SOURCE_FOR_DPREFCLK) + params.param.dceclkflag |= + DCE_CLOCK_FLAG_PLL_REFCLK_SRC_XTALIN; + + if (bp_params->flags.USE_GENERICA_AS_SOURCE_FOR_DPREFCLK) + params.param.dceclkflag |= + DCE_CLOCK_FLAG_PLL_REFCLK_SRC_GENERICA; + } else + /* only program clock frequency if display clock is used; + * VBIOS will program DPREFCLK + * We need to convert from KHz units into 10KHz units + */ + params.param.dceclk_10khz = cpu_to_le32( + bp_params->target_clock_frequency / 10); + dm_logger_write(bp->base.ctx->logger, LOG_HW_SET_MODE, + "************************%s:target_clock_frequency = %d"\ + "clock_type = %d \n", __func__,\ + bp_params->target_clock_frequency,\ + bp_params->clock_type); + + if (EXEC_BIOS_CMD_TABLE(setdceclock, params)) { + /* Convert from 10KHz units back to KHz */ + bp_params->target_clock_frequency = le32_to_cpu( + params.param.dceclk_10khz) * 10; + result = BP_RESULT_OK; + } + + return result; +} + + +/****************************************************************************** + ****************************************************************************** + ** + ** GET SMU CLOCK INFO + ** + ****************************************************************************** + *****************************************************************************/ + +static unsigned int get_smu_clock_info_v3_1(struct bios_parser *bp); + +static void init_get_smu_clock_info(struct bios_parser *bp) +{ + /* TODO add switch for table vrsion */ + bp->cmd_tbl.get_smu_clock_info = get_smu_clock_info_v3_1; + +} + +static unsigned int get_smu_clock_info_v3_1(struct bios_parser *bp) +{ + struct atom_get_smu_clock_info_parameters_v3_1 smu_input = {0}; + struct atom_get_smu_clock_info_output_parameters_v3_1 smu_output; + + smu_input.command = GET_SMU_CLOCK_INFO_V3_1_GET_PLLVCO_FREQ; + + /* Get Specific Clock */ + if (EXEC_BIOS_CMD_TABLE(getsmuclockinfo, smu_input)) { + memmove(&smu_output, &smu_input, sizeof( + struct atom_get_smu_clock_info_parameters_v3_1)); + return smu_output.atom_smu_outputclkfreq.syspllvcofreq_10khz; + } + + return 0; +} + diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.h b/drivers/gpu/drm/amd/display/dc/bios/command_table2.h new file mode 100644 index 000000000000..59061b806df5 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.h @@ -0,0 +1,105 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_COMMAND_TABLE2_H__ +#define __DAL_COMMAND_TABLE2_H__ + +struct bios_parser; +struct bp_encoder_control; + +struct cmd_tbl { + enum bp_result (*dig_encoder_control)( + struct bios_parser *bp, + struct bp_encoder_control *control); + enum bp_result (*encoder_control_dig1)( + struct bios_parser *bp, + struct bp_encoder_control *control); + enum bp_result (*encoder_control_dig2)( + struct bios_parser *bp, + struct bp_encoder_control *control); + enum bp_result (*transmitter_control)( + struct bios_parser *bp, + struct bp_transmitter_control *control); + enum bp_result (*set_pixel_clock)( + struct bios_parser *bp, + struct bp_pixel_clock_parameters *bp_params); + enum bp_result (*enable_spread_spectrum_on_ppll)( + struct bios_parser *bp, + struct bp_spread_spectrum_parameters *bp_params, + bool enable); + enum bp_result (*adjust_display_pll)( + struct bios_parser *bp, + struct bp_adjust_pixel_clock_parameters *bp_params); + enum bp_result (*dac1_encoder_control)( + struct bios_parser *bp, + bool enable, + uint32_t pixel_clock, + uint8_t dac_standard); + enum bp_result (*dac2_encoder_control)( + struct bios_parser *bp, + bool enable, + uint32_t pixel_clock, + uint8_t dac_standard); + enum bp_result (*dac1_output_control)( + struct bios_parser *bp, + bool enable); + enum bp_result (*dac2_output_control)( + struct bios_parser *bp, + bool enable); + enum bp_result (*set_crtc_timing)( + struct bios_parser *bp, + struct bp_hw_crtc_timing_parameters *bp_params); + enum bp_result (*select_crtc_source)( + struct bios_parser *bp, + struct bp_crtc_source_select *bp_params); + enum bp_result (*enable_crtc)( + struct bios_parser *bp, + enum controller_id controller_id, + bool enable); + enum bp_result (*enable_crtc_mem_req)( + struct bios_parser *bp, + enum controller_id controller_id, + bool enable); + enum bp_result (*program_clock)( + struct bios_parser *bp, + struct bp_pixel_clock_parameters *bp_params); + enum bp_result (*external_encoder_control)( + struct bios_parser *bp, + struct bp_external_encoder_control *cntl); + enum bp_result (*enable_disp_power_gating)( + struct bios_parser *bp, + enum controller_id crtc_id, + enum bp_pipe_control_action action); + enum bp_result (*set_dce_clock)( + struct bios_parser *bp, + struct bp_set_dce_clock_parameters *bp_params); + unsigned int (*get_smu_clock_info)( + struct bios_parser *bp); + +}; + +void dal_firmware_parser_init_cmd_tbl(struct bios_parser *bp); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c new file mode 100644 index 000000000000..b0dcad260be6 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c @@ -0,0 +1,260 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "ObjectID.h" +#include "atomfirmware.h" +#include "atomfirmwareid.h" + +#include "include/bios_parser_types.h" + +#include "command_table_helper2.h" + +bool dal_bios_parser_init_cmd_tbl_helper2( + const struct command_table_helper **h, + enum dce_version dce) +{ + switch (dce) { + case DCE_VERSION_8_0: + *h = dal_cmd_tbl_helper_dce80_get_table(); + return true; + + case DCE_VERSION_10_0: + *h = dal_cmd_tbl_helper_dce110_get_table(); + return true; + + case DCE_VERSION_11_0: + *h = dal_cmd_tbl_helper_dce110_get_table(); + return true; + + case DCE_VERSION_11_2: + *h = dal_cmd_tbl_helper_dce112_get_table2(); + return true; +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + case DCE_VERSION_12_0: + *h = dal_cmd_tbl_helper_dce112_get_table2(); + return true; +#endif + + default: + /* Unsupported DCE */ + BREAK_TO_DEBUGGER(); + return false; + } +} + +/* real implementations */ + +bool dal_cmd_table_helper_controller_id_to_atom2( + enum controller_id id, + uint8_t *atom_id) +{ + if (atom_id == NULL) { + BREAK_TO_DEBUGGER(); + return false; + } + + switch (id) { + case CONTROLLER_ID_D0: + *atom_id = ATOM_CRTC1; + return true; + case CONTROLLER_ID_D1: + *atom_id = ATOM_CRTC2; + return true; + case CONTROLLER_ID_D2: + *atom_id = ATOM_CRTC3; + return true; + case CONTROLLER_ID_D3: + *atom_id = ATOM_CRTC4; + return true; + case CONTROLLER_ID_D4: + *atom_id = ATOM_CRTC5; + return true; + case CONTROLLER_ID_D5: + *atom_id = ATOM_CRTC6; + return true; + /* TODO :case CONTROLLER_ID_UNDERLAY0: + *atom_id = ATOM_UNDERLAY_PIPE0; + return true; + */ + case CONTROLLER_ID_UNDEFINED: + *atom_id = ATOM_CRTC_INVALID; + return true; + default: + /* Wrong controller id */ + BREAK_TO_DEBUGGER(); + return false; + } +} + +/** +* translate_transmitter_bp_to_atom +* +* @brief +* Translate the Transmitter to the corresponding ATOM BIOS value +* +* @param +* input transmitter +* output digitalTransmitter +* // =00: Digital Transmitter1 ( UNIPHY linkAB ) +* // =01: Digital Transmitter2 ( UNIPHY linkCD ) +* // =02: Digital Transmitter3 ( UNIPHY linkEF ) +*/ +uint8_t dal_cmd_table_helper_transmitter_bp_to_atom2( + enum transmitter t) +{ + switch (t) { + case TRANSMITTER_UNIPHY_A: + case TRANSMITTER_UNIPHY_B: + case TRANSMITTER_TRAVIS_LCD: + return 0; + case TRANSMITTER_UNIPHY_C: + case TRANSMITTER_UNIPHY_D: + return 1; + case TRANSMITTER_UNIPHY_E: + case TRANSMITTER_UNIPHY_F: + return 2; + default: + /* Invalid Transmitter Type! */ + BREAK_TO_DEBUGGER(); + return 0; + } +} + +uint32_t dal_cmd_table_helper_encoder_mode_bp_to_atom2( + enum signal_type s, + bool enable_dp_audio) +{ + switch (s) { + case SIGNAL_TYPE_DVI_SINGLE_LINK: + case SIGNAL_TYPE_DVI_DUAL_LINK: + return ATOM_ENCODER_MODE_DVI; + case SIGNAL_TYPE_HDMI_TYPE_A: + return ATOM_ENCODER_MODE_HDMI; + case SIGNAL_TYPE_LVDS: + return ATOM_ENCODER_MODE_LVDS; + case SIGNAL_TYPE_EDP: + case SIGNAL_TYPE_DISPLAY_PORT_MST: + case SIGNAL_TYPE_DISPLAY_PORT: + case SIGNAL_TYPE_VIRTUAL: + if (enable_dp_audio) + return ATOM_ENCODER_MODE_DP_AUDIO; + else + return ATOM_ENCODER_MODE_DP; + case SIGNAL_TYPE_RGB: + return ATOM_ENCODER_MODE_CRT; + default: + return ATOM_ENCODER_MODE_CRT; + } +} + +bool dal_cmd_table_helper_clock_source_id_to_ref_clk_src2( + enum clock_source_id id, + uint32_t *ref_clk_src_id) +{ + if (ref_clk_src_id == NULL) { + BREAK_TO_DEBUGGER(); + return false; + } + + switch (id) { + case CLOCK_SOURCE_ID_PLL1: + *ref_clk_src_id = ENCODER_REFCLK_SRC_P1PLL; + return true; + case CLOCK_SOURCE_ID_PLL2: + *ref_clk_src_id = ENCODER_REFCLK_SRC_P2PLL; + return true; + /*TODO:case CLOCK_SOURCE_ID_DCPLL: + *ref_clk_src_id = ENCODER_REFCLK_SRC_DCPLL; + return true; + */ + case CLOCK_SOURCE_ID_EXTERNAL: + *ref_clk_src_id = ENCODER_REFCLK_SRC_EXTCLK; + return true; + case CLOCK_SOURCE_ID_UNDEFINED: + *ref_clk_src_id = ENCODER_REFCLK_SRC_INVALID; + return true; + default: + /* Unsupported clock source id */ + BREAK_TO_DEBUGGER(); + return false; + } +} + +uint8_t dal_cmd_table_helper_encoder_id_to_atom2( + enum encoder_id id) +{ + switch (id) { + case ENCODER_ID_INTERNAL_LVDS: + return ENCODER_OBJECT_ID_INTERNAL_LVDS; + case ENCODER_ID_INTERNAL_TMDS1: + return ENCODER_OBJECT_ID_INTERNAL_TMDS1; + case ENCODER_ID_INTERNAL_TMDS2: + return ENCODER_OBJECT_ID_INTERNAL_TMDS2; + case ENCODER_ID_INTERNAL_DAC1: + return ENCODER_OBJECT_ID_INTERNAL_DAC1; + case ENCODER_ID_INTERNAL_DAC2: + return ENCODER_OBJECT_ID_INTERNAL_DAC2; + case ENCODER_ID_INTERNAL_LVTM1: + return ENCODER_OBJECT_ID_INTERNAL_LVTM1; + case ENCODER_ID_INTERNAL_HDMI: + return ENCODER_OBJECT_ID_HDMI_INTERNAL; + case ENCODER_ID_EXTERNAL_TRAVIS: + return ENCODER_OBJECT_ID_TRAVIS; + case ENCODER_ID_EXTERNAL_NUTMEG: + return ENCODER_OBJECT_ID_NUTMEG; + case ENCODER_ID_INTERNAL_KLDSCP_TMDS1: + return ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1; + case ENCODER_ID_INTERNAL_KLDSCP_DAC1: + return ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1; + case ENCODER_ID_INTERNAL_KLDSCP_DAC2: + return ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2; + case ENCODER_ID_EXTERNAL_MVPU_FPGA: + return ENCODER_OBJECT_ID_MVPU_FPGA; + case ENCODER_ID_INTERNAL_DDI: + return ENCODER_OBJECT_ID_INTERNAL_DDI; + case ENCODER_ID_INTERNAL_UNIPHY: + return ENCODER_OBJECT_ID_INTERNAL_UNIPHY; + case ENCODER_ID_INTERNAL_KLDSCP_LVTMA: + return ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA; + case ENCODER_ID_INTERNAL_UNIPHY1: + return ENCODER_OBJECT_ID_INTERNAL_UNIPHY1; + case ENCODER_ID_INTERNAL_UNIPHY2: + return ENCODER_OBJECT_ID_INTERNAL_UNIPHY2; + case ENCODER_ID_INTERNAL_UNIPHY3: + return ENCODER_OBJECT_ID_INTERNAL_UNIPHY3; + case ENCODER_ID_INTERNAL_WIRELESS: + return ENCODER_OBJECT_ID_INTERNAL_VCE; + case ENCODER_ID_INTERNAL_VIRTUAL: + return ENCODER_OBJECT_ID_NONE; + case ENCODER_ID_UNKNOWN: + return ENCODER_OBJECT_ID_NONE; + default: + /* Invalid encoder id */ + BREAK_TO_DEBUGGER(); + return ENCODER_OBJECT_ID_NONE; + } +} diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.h b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.h new file mode 100644 index 000000000000..9f587c91d843 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.h @@ -0,0 +1,82 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_COMMAND_TABLE_HELPER2_H__ +#define __DAL_COMMAND_TABLE_HELPER2_H__ + +#include "dce80/command_table_helper_dce80.h" +#include "dce110/command_table_helper_dce110.h" +#include "dce112/command_table_helper2_dce112.h" + +struct command_table_helper { + bool (*controller_id_to_atom)(enum controller_id id, uint8_t *atom_id); + uint8_t (*encoder_action_to_atom)( + enum bp_encoder_control_action action); + uint32_t (*encoder_mode_bp_to_atom)(enum signal_type s, + bool enable_dp_audio); + bool (*engine_bp_to_atom)(enum engine_id engine_id, + uint32_t *atom_engine_id); + bool (*clock_source_id_to_atom)(enum clock_source_id id, + uint32_t *atom_pll_id); + bool (*clock_source_id_to_ref_clk_src)( + enum clock_source_id id, + uint32_t *ref_clk_src_id); + uint8_t (*transmitter_bp_to_atom)(enum transmitter t); + uint8_t (*encoder_id_to_atom)(enum encoder_id id); + uint8_t (*clock_source_id_to_atom_phy_clk_src_id)( + enum clock_source_id id); + uint8_t (*signal_type_to_atom_dig_mode)(enum signal_type s); + uint8_t (*hpd_sel_to_atom)(enum hpd_source_id id); + uint8_t (*dig_encoder_sel_to_atom)(enum engine_id engine_id); + uint8_t (*phy_id_to_atom)(enum transmitter t); + uint8_t (*disp_power_gating_action_to_atom)( + enum bp_pipe_control_action action); + bool (*dc_clock_type_to_atom)(enum bp_dce_clock_type id, + uint32_t *atom_clock_type); + uint8_t (*transmitter_color_depth_to_atom)( + enum transmitter_color_depth id); +}; + +bool dal_bios_parser_init_cmd_tbl_helper2(const struct command_table_helper **h, + enum dce_version dce); + +bool dal_cmd_table_helper_controller_id_to_atom2( + enum controller_id id, + uint8_t *atom_id); + +uint32_t dal_cmd_table_helper_encoder_mode_bp_to_atom2( + enum signal_type s, + bool enable_dp_audio); + +bool dal_cmd_table_helper_clock_source_id_to_ref_clk_src2( + enum clock_source_id id, + uint32_t *ref_clk_src_id); + +uint8_t dal_cmd_table_helper_transmitter_bp_to_atom2( + enum transmitter t); + +uint8_t dal_cmd_table_helper_encoder_id_to_atom2( + enum encoder_id id); +#endif diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.c b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.c new file mode 100644 index 000000000000..d342cdecba11 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.c @@ -0,0 +1,418 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "atom.h" + +#include "include/bios_parser_types.h" + +#include "../command_table_helper2.h" + +static uint8_t phy_id_to_atom(enum transmitter t) +{ + uint8_t atom_phy_id; + + switch (t) { + case TRANSMITTER_UNIPHY_A: + atom_phy_id = ATOM_PHY_ID_UNIPHYA; + break; + case TRANSMITTER_UNIPHY_B: + atom_phy_id = ATOM_PHY_ID_UNIPHYB; + break; + case TRANSMITTER_UNIPHY_C: + atom_phy_id = ATOM_PHY_ID_UNIPHYC; + break; + case TRANSMITTER_UNIPHY_D: + atom_phy_id = ATOM_PHY_ID_UNIPHYD; + break; + case TRANSMITTER_UNIPHY_E: + atom_phy_id = ATOM_PHY_ID_UNIPHYE; + break; + case TRANSMITTER_UNIPHY_F: + atom_phy_id = ATOM_PHY_ID_UNIPHYF; + break; + case TRANSMITTER_UNIPHY_G: + atom_phy_id = ATOM_PHY_ID_UNIPHYG; + break; + default: + atom_phy_id = ATOM_PHY_ID_UNIPHYA; + break; + } + return atom_phy_id; +} + +static uint8_t signal_type_to_atom_dig_mode(enum signal_type s) +{ + uint8_t atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_DP; + + switch (s) { + case SIGNAL_TYPE_DISPLAY_PORT: + case SIGNAL_TYPE_EDP: + atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_DP; + break; + case SIGNAL_TYPE_DVI_SINGLE_LINK: + case SIGNAL_TYPE_DVI_DUAL_LINK: + atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_DVI; + break; + case SIGNAL_TYPE_HDMI_TYPE_A: + atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_HDMI; + break; + case SIGNAL_TYPE_DISPLAY_PORT_MST: + atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_DP_MST; + break; + default: + atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_DVI; + break; + } + + return atom_dig_mode; +} + +static uint8_t clock_source_id_to_atom_phy_clk_src_id( + enum clock_source_id id) +{ + uint8_t atom_phy_clk_src_id = 0; + + switch (id) { + case CLOCK_SOURCE_ID_PLL0: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P0PLL; + break; + case CLOCK_SOURCE_ID_PLL1: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL; + break; + case CLOCK_SOURCE_ID_PLL2: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P2PLL; + break; + case CLOCK_SOURCE_ID_EXTERNAL: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_REFCLK_SRC_EXT; + break; + default: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL; + break; + } + + return atom_phy_clk_src_id >> 2; +} + +static uint8_t hpd_sel_to_atom(enum hpd_source_id id) +{ + uint8_t atom_hpd_sel = 0; + + switch (id) { + case HPD_SOURCEID1: + atom_hpd_sel = ATOM_TRANSMITTER_V6_HPD1_SEL; + break; + case HPD_SOURCEID2: + atom_hpd_sel = ATOM_TRANSMITTER_V6_HPD2_SEL; + break; + case HPD_SOURCEID3: + atom_hpd_sel = ATOM_TRANSMITTER_V6_HPD3_SEL; + break; + case HPD_SOURCEID4: + atom_hpd_sel = ATOM_TRANSMITTER_V6_HPD4_SEL; + break; + case HPD_SOURCEID5: + atom_hpd_sel = ATOM_TRANSMITTER_V6_HPD5_SEL; + break; + case HPD_SOURCEID6: + atom_hpd_sel = ATOM_TRANSMITTER_V6_HPD6_SEL; + break; + case HPD_SOURCEID_UNKNOWN: + default: + atom_hpd_sel = 0; + break; + } + return atom_hpd_sel; +} + +static uint8_t dig_encoder_sel_to_atom(enum engine_id id) +{ + uint8_t atom_dig_encoder_sel = 0; + + switch (id) { + case ENGINE_ID_DIGA: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGA_SEL; + break; + case ENGINE_ID_DIGB: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGB_SEL; + break; + case ENGINE_ID_DIGC: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGC_SEL; + break; + case ENGINE_ID_DIGD: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGD_SEL; + break; + case ENGINE_ID_DIGE: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGE_SEL; + break; + case ENGINE_ID_DIGF: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGF_SEL; + break; + case ENGINE_ID_DIGG: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGG_SEL; + break; + case ENGINE_ID_UNKNOWN: + /* No DIG_FRONT is associated to DIG_BACKEND */ + atom_dig_encoder_sel = 0; + break; + default: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGA_SEL; + break; + } + + return 0; +} + +static bool clock_source_id_to_atom( + enum clock_source_id id, + uint32_t *atom_pll_id) +{ + bool result = true; + + if (atom_pll_id != NULL) + switch (id) { + case CLOCK_SOURCE_COMBO_PHY_PLL0: + *atom_pll_id = ATOM_COMBOPHY_PLL0; + break; + case CLOCK_SOURCE_COMBO_PHY_PLL1: + *atom_pll_id = ATOM_COMBOPHY_PLL1; + break; + case CLOCK_SOURCE_COMBO_PHY_PLL2: + *atom_pll_id = ATOM_COMBOPHY_PLL2; + break; + case CLOCK_SOURCE_COMBO_PHY_PLL3: + *atom_pll_id = ATOM_COMBOPHY_PLL3; + break; + case CLOCK_SOURCE_COMBO_PHY_PLL4: + *atom_pll_id = ATOM_COMBOPHY_PLL4; + break; + case CLOCK_SOURCE_COMBO_PHY_PLL5: + *atom_pll_id = ATOM_COMBOPHY_PLL5; + break; + case CLOCK_SOURCE_COMBO_DISPLAY_PLL0: + *atom_pll_id = ATOM_PPLL0; + break; + case CLOCK_SOURCE_ID_DFS: + *atom_pll_id = ATOM_GCK_DFS; + break; + case CLOCK_SOURCE_ID_VCE: + *atom_pll_id = ATOM_DP_DTO; + break; + case CLOCK_SOURCE_ID_DP_DTO: + *atom_pll_id = ATOM_DP_DTO; + break; + case CLOCK_SOURCE_ID_UNDEFINED: + /* Should not happen */ + *atom_pll_id = ATOM_PPLL_INVALID; + result = false; + break; + default: + result = false; + break; + } + + return result; +} + +static bool engine_bp_to_atom(enum engine_id id, uint32_t *atom_engine_id) +{ + bool result = false; + + if (atom_engine_id != NULL) + switch (id) { + case ENGINE_ID_DIGA: + *atom_engine_id = ASIC_INT_DIG1_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGB: + *atom_engine_id = ASIC_INT_DIG2_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGC: + *atom_engine_id = ASIC_INT_DIG3_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGD: + *atom_engine_id = ASIC_INT_DIG4_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGE: + *atom_engine_id = ASIC_INT_DIG5_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGF: + *atom_engine_id = ASIC_INT_DIG6_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGG: + *atom_engine_id = ASIC_INT_DIG7_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DACA: + *atom_engine_id = ASIC_INT_DAC1_ENCODER_ID; + result = true; + break; + default: + break; + } + + return result; +} + +static uint8_t encoder_action_to_atom(enum bp_encoder_control_action action) +{ + uint8_t atom_action = 0; + + switch (action) { + case ENCODER_CONTROL_ENABLE: + atom_action = ATOM_ENABLE; + break; + case ENCODER_CONTROL_DISABLE: + atom_action = ATOM_DISABLE; + break; + case ENCODER_CONTROL_SETUP: + atom_action = ATOM_ENCODER_CMD_STREAM_SETUP; + break; + case ENCODER_CONTROL_INIT: + atom_action = ATOM_ENCODER_INIT; + break; + default: + BREAK_TO_DEBUGGER(); /* Unhandle action in driver.!! */ + break; + } + + return atom_action; +} + +static uint8_t disp_power_gating_action_to_atom( + enum bp_pipe_control_action action) +{ + uint8_t atom_pipe_action = 0; + + switch (action) { + case ASIC_PIPE_DISABLE: + atom_pipe_action = ATOM_DISABLE; + break; + case ASIC_PIPE_ENABLE: + atom_pipe_action = ATOM_ENABLE; + break; + case ASIC_PIPE_INIT: + atom_pipe_action = ATOM_INIT; + break; + default: + ASSERT_CRITICAL(false); /* Unhandle action in driver! */ + break; + } + + return atom_pipe_action; +} + +static bool dc_clock_type_to_atom( + enum bp_dce_clock_type id, + uint32_t *atom_clock_type) +{ + bool retCode = true; + + if (atom_clock_type != NULL) { + switch (id) { + case DCECLOCK_TYPE_DISPLAY_CLOCK: + *atom_clock_type = DCE_CLOCK_TYPE_DISPCLK; + break; + + case DCECLOCK_TYPE_DPREFCLK: + *atom_clock_type = DCE_CLOCK_TYPE_DPREFCLK; + break; + + default: + ASSERT_CRITICAL(false); /* Unhandle action in driver! */ + break; + } + } + + return retCode; +} + +static uint8_t transmitter_color_depth_to_atom(enum transmitter_color_depth id) +{ + uint8_t atomColorDepth = 0; + + switch (id) { + case TRANSMITTER_COLOR_DEPTH_24: + atomColorDepth = PIXEL_CLOCK_V7_DEEPCOLOR_RATIO_DIS; + break; + case TRANSMITTER_COLOR_DEPTH_30: + atomColorDepth = PIXEL_CLOCK_V7_DEEPCOLOR_RATIO_5_4; + break; + case TRANSMITTER_COLOR_DEPTH_36: + atomColorDepth = PIXEL_CLOCK_V7_DEEPCOLOR_RATIO_3_2; + break; + case TRANSMITTER_COLOR_DEPTH_48: + atomColorDepth = PIXEL_CLOCK_V7_DEEPCOLOR_RATIO_2_1; + break; + default: + ASSERT_CRITICAL(false); /* Unhandle action in driver! */ + break; + } + + return atomColorDepth; +} + +/* function table */ +static const struct command_table_helper command_table_helper_funcs = { + .controller_id_to_atom = dal_cmd_table_helper_controller_id_to_atom2, + .encoder_action_to_atom = encoder_action_to_atom, + .engine_bp_to_atom = engine_bp_to_atom, + .clock_source_id_to_atom = clock_source_id_to_atom, + .clock_source_id_to_atom_phy_clk_src_id = + clock_source_id_to_atom_phy_clk_src_id, + .signal_type_to_atom_dig_mode = signal_type_to_atom_dig_mode, + .hpd_sel_to_atom = hpd_sel_to_atom, + .dig_encoder_sel_to_atom = dig_encoder_sel_to_atom, + .phy_id_to_atom = phy_id_to_atom, + .disp_power_gating_action_to_atom = disp_power_gating_action_to_atom, + .clock_source_id_to_ref_clk_src = NULL, + .transmitter_bp_to_atom = NULL, + .encoder_id_to_atom = dal_cmd_table_helper_encoder_id_to_atom2, + .encoder_mode_bp_to_atom = + dal_cmd_table_helper_encoder_mode_bp_to_atom2, + .dc_clock_type_to_atom = dc_clock_type_to_atom, + .transmitter_color_depth_to_atom = transmitter_color_depth_to_atom, +}; + +/* + * dal_cmd_tbl_helper_dce110_get_table + * + * @brief + * Initialize command table helper functions + * + * @param + * const struct command_table_helper **h - [out] struct of functions + * + */ +const struct command_table_helper *dal_cmd_tbl_helper_dce112_get_table2() +{ + return &command_table_helper_funcs; +} diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.h b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.h new file mode 100644 index 000000000000..abf28a06f5bc --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.h @@ -0,0 +1,34 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_COMMAND_TABLE_HELPER2_DCE112_H__ +#define __DAL_COMMAND_TABLE_HELPER2_DCE112_H__ + +struct command_table_helper; + +/* Initialize command table helper functions */ +const struct command_table_helper *dal_cmd_tbl_helper_dce112_get_table2(void); + +#endif /* __DAL_COMMAND_TABLE_HELPER_DCE110_H__ */ -- cgit From ef40b2346563aa11575446c8e3b04af44c31abb5 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 6 Mar 2017 14:32:06 -0500 Subject: drm/amd/display: Add DCE12 gpio support Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/gpio/dce120/hw_factory_dce120.c | 197 ++++++++++ .../amd/display/dc/gpio/dce120/hw_factory_dce120.h | 32 ++ .../display/dc/gpio/dce120/hw_translate_dce120.c | 408 +++++++++++++++++++++ .../display/dc/gpio/dce120/hw_translate_dce120.h | 34 ++ 4 files changed, 671 insertions(+) create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dce120/hw_factory_dce120.c create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dce120/hw_factory_dce120.h create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dce120/hw_translate_dce120.c create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dce120/hw_translate_dce120.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dce120/hw_factory_dce120.c b/drivers/gpu/drm/amd/display/dc/gpio/dce120/hw_factory_dce120.c new file mode 100644 index 000000000000..4ced9a7d63dd --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/dce120/hw_factory_dce120.c @@ -0,0 +1,197 @@ +/* + * Copyright 2013-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "include/gpio_types.h" +#include "../hw_factory.h" + + +#include "../hw_gpio.h" +#include "../hw_ddc.h" +#include "../hw_hpd.h" + +#include "hw_factory_dce120.h" + +#include "vega10/DC/dce_12_0_offset.h" +#include "vega10/DC/dce_12_0_sh_mask.h" +#include "vega10/soc15ip.h" + +#define block HPD +#define reg_num 0 + +/* set field name */ +#define SF_HPD(reg_name, field_name, post_fix)\ + .field_name = HPD0_ ## reg_name ## __ ## field_name ## post_fix + +/* set field name */ +#define SF_HPD(reg_name, field_name, post_fix)\ + .field_name = HPD0_ ## reg_name ## __ ## field_name ## post_fix + +#define BASE_INNER(seg) \ + DCE_BASE__INST0_SEG ## seg + +/* compile time expand base address. */ +#define BASE(seg) \ + BASE_INNER(seg) + +#define REG(reg_name)\ + BASE(mm ## reg_name ## _BASE_IDX) + mm ## reg_name + +#define REGI(reg_name, block, id)\ + BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + + +#include "reg_helper.h" +#include "../hpd_regs.h" + +#define hpd_regs(id) \ +{\ + HPD_REG_LIST(id)\ +} + +static const struct hpd_registers hpd_regs[] = { + hpd_regs(0), + hpd_regs(1), + hpd_regs(2), + hpd_regs(3), + hpd_regs(4), + hpd_regs(5) +}; + +static const struct hpd_sh_mask hpd_shift = { + HPD_MASK_SH_LIST(__SHIFT) +}; + +static const struct hpd_sh_mask hpd_mask = { + HPD_MASK_SH_LIST(_MASK) +}; + +#include "../ddc_regs.h" + + /* set field name */ +#define SF_DDC(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +static const struct ddc_registers ddc_data_regs[] = { + ddc_data_regs(1), + ddc_data_regs(2), + ddc_data_regs(3), + ddc_data_regs(4), + ddc_data_regs(5), + ddc_data_regs(6), + ddc_vga_data_regs, + ddc_i2c_data_regs +}; + +static const struct ddc_registers ddc_clk_regs[] = { + ddc_clk_regs(1), + ddc_clk_regs(2), + ddc_clk_regs(3), + ddc_clk_regs(4), + ddc_clk_regs(5), + ddc_clk_regs(6), + ddc_vga_clk_regs, + ddc_i2c_clk_regs +}; + +static const struct ddc_sh_mask ddc_shift = { + DDC_MASK_SH_LIST(__SHIFT) +}; + +static const struct ddc_sh_mask ddc_mask = { + DDC_MASK_SH_LIST(_MASK) +}; + +static void define_ddc_registers( + struct hw_gpio_pin *pin, + uint32_t en) +{ + struct hw_ddc *ddc = HW_DDC_FROM_BASE(pin); + + switch (pin->id) { + case GPIO_ID_DDC_DATA: + ddc->regs = &ddc_data_regs[en]; + ddc->base.regs = &ddc_data_regs[en].gpio; + break; + case GPIO_ID_DDC_CLOCK: + ddc->regs = &ddc_clk_regs[en]; + ddc->base.regs = &ddc_clk_regs[en].gpio; + break; + default: + ASSERT_CRITICAL(false); + return; + } + + ddc->shifts = &ddc_shift; + ddc->masks = &ddc_mask; + +} + +static void define_hpd_registers(struct hw_gpio_pin *pin, uint32_t en) +{ + struct hw_hpd *hpd = HW_HPD_FROM_BASE(pin); + + hpd->regs = &hpd_regs[en]; + hpd->shifts = &hpd_shift; + hpd->masks = &hpd_mask; + hpd->base.regs = &hpd_regs[en].gpio; +} + + +/* fucntion table */ +static const struct hw_factory_funcs funcs = { + .create_ddc_data = dal_hw_ddc_create, + .create_ddc_clock = dal_hw_ddc_create, + .create_generic = NULL, + .create_hpd = dal_hw_hpd_create, + .create_sync = NULL, + .create_gsl = NULL, + .define_hpd_registers = define_hpd_registers, + .define_ddc_registers = define_ddc_registers +}; +/* + * dal_hw_factory_dce120_init + * + * @brief + * Initialize HW factory function pointers and pin info + * + * @param + * struct hw_factory *factory - [out] struct of function pointers + */ +void dal_hw_factory_dce120_init(struct hw_factory *factory) +{ + /*TODO check ASIC CAPs*/ + factory->number_of_pins[GPIO_ID_DDC_DATA] = 8; + factory->number_of_pins[GPIO_ID_DDC_CLOCK] = 8; + factory->number_of_pins[GPIO_ID_GENERIC] = 7; + factory->number_of_pins[GPIO_ID_HPD] = 6; + factory->number_of_pins[GPIO_ID_GPIO_PAD] = 31; + factory->number_of_pins[GPIO_ID_VIP_PAD] = 0; + factory->number_of_pins[GPIO_ID_SYNC] = 2; + factory->number_of_pins[GPIO_ID_GSL] = 4; + + factory->funcs = &funcs; +} diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dce120/hw_factory_dce120.h b/drivers/gpu/drm/amd/display/dc/gpio/dce120/hw_factory_dce120.h new file mode 100644 index 000000000000..db260c351f73 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/dce120/hw_factory_dce120.h @@ -0,0 +1,32 @@ +/* + * Copyright 2013-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_HW_FACTORY_DCE120_H__ +#define __DAL_HW_FACTORY_DCE120_H__ + +/* Initialize HW factory function pointers and pin info */ +void dal_hw_factory_dce120_init(struct hw_factory *factory); + +#endif /* __DAL_HW_FACTORY_DCE120_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dce120/hw_translate_dce120.c b/drivers/gpu/drm/amd/display/dc/gpio/dce120/hw_translate_dce120.c new file mode 100644 index 000000000000..af3843a69652 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/dce120/hw_translate_dce120.c @@ -0,0 +1,408 @@ +/* + * Copyright 2013-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +/* + * Pre-requisites: headers required by header of this unit + */ + +#include "hw_translate_dce120.h" + +#include "dm_services.h" +#include "include/gpio_types.h" +#include "../hw_translate.h" + +#include "vega10/DC/dce_12_0_offset.h" +#include "vega10/DC/dce_12_0_sh_mask.h" +#include "vega10/soc15ip.h" + +/* begin ********************* + * macros to expend register list macro defined in HW object header file */ + +#define BASE_INNER(seg) \ + DCE_BASE__INST0_SEG ## seg + +/* compile time expand base address. */ +#define BASE(seg) \ + BASE_INNER(seg) + +#define REG(reg_name)\ + BASE(mm ## reg_name ## _BASE_IDX) + mm ## reg_name + +#define REGI(reg_name, block, id)\ + BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +/* macros to expend register list macro defined in HW object header file + * end *********************/ + +static bool offset_to_id( + uint32_t offset, + uint32_t mask, + enum gpio_id *id, + uint32_t *en) +{ + switch (offset) { + /* GENERIC */ + case REG(DC_GPIO_GENERIC_A): + *id = GPIO_ID_GENERIC; + switch (mask) { + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICA_A_MASK: + *en = GPIO_GENERIC_A; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICB_A_MASK: + *en = GPIO_GENERIC_B; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICC_A_MASK: + *en = GPIO_GENERIC_C; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICD_A_MASK: + *en = GPIO_GENERIC_D; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICE_A_MASK: + *en = GPIO_GENERIC_E; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICF_A_MASK: + *en = GPIO_GENERIC_F; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICG_A_MASK: + *en = GPIO_GENERIC_G; + return true; + default: + ASSERT_CRITICAL(false); + return false; + } + break; + /* HPD */ + case REG(DC_GPIO_HPD_A): + *id = GPIO_ID_HPD; + switch (mask) { + case DC_GPIO_HPD_A__DC_GPIO_HPD1_A_MASK: + *en = GPIO_HPD_1; + return true; + case DC_GPIO_HPD_A__DC_GPIO_HPD2_A_MASK: + *en = GPIO_HPD_2; + return true; + case DC_GPIO_HPD_A__DC_GPIO_HPD3_A_MASK: + *en = GPIO_HPD_3; + return true; + case DC_GPIO_HPD_A__DC_GPIO_HPD4_A_MASK: + *en = GPIO_HPD_4; + return true; + case DC_GPIO_HPD_A__DC_GPIO_HPD5_A_MASK: + *en = GPIO_HPD_5; + return true; + case DC_GPIO_HPD_A__DC_GPIO_HPD6_A_MASK: + *en = GPIO_HPD_6; + return true; + default: + ASSERT_CRITICAL(false); + return false; + } + break; + /* SYNCA */ + case REG(DC_GPIO_SYNCA_A): + *id = GPIO_ID_SYNC; + switch (mask) { + case DC_GPIO_SYNCA_A__DC_GPIO_HSYNCA_A_MASK: + *en = GPIO_SYNC_HSYNC_A; + return true; + case DC_GPIO_SYNCA_A__DC_GPIO_VSYNCA_A_MASK: + *en = GPIO_SYNC_VSYNC_A; + return true; + default: + ASSERT_CRITICAL(false); + return false; + } + break; + /* REG(DC_GPIO_GENLK_MASK */ + case REG(DC_GPIO_GENLK_A): + *id = GPIO_ID_GSL; + switch (mask) { + case DC_GPIO_GENLK_A__DC_GPIO_GENLK_CLK_A_MASK: + *en = GPIO_GSL_GENLOCK_CLOCK; + return true; + case DC_GPIO_GENLK_A__DC_GPIO_GENLK_VSYNC_A_MASK: + *en = GPIO_GSL_GENLOCK_VSYNC; + return true; + case DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_A_A_MASK: + *en = GPIO_GSL_SWAPLOCK_A; + return true; + case DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_B_A_MASK: + *en = GPIO_GSL_SWAPLOCK_B; + return true; + default: + ASSERT_CRITICAL(false); + return false; + } + break; + /* DDC */ + /* we don't care about the GPIO_ID for DDC + * in DdcHandle it will use GPIO_ID_DDC_DATA/GPIO_ID_DDC_CLOCK + * directly in the create method */ + case REG(DC_GPIO_DDC1_A): + *en = GPIO_DDC_LINE_DDC1; + return true; + case REG(DC_GPIO_DDC2_A): + *en = GPIO_DDC_LINE_DDC2; + return true; + case REG(DC_GPIO_DDC3_A): + *en = GPIO_DDC_LINE_DDC3; + return true; + case REG(DC_GPIO_DDC4_A): + *en = GPIO_DDC_LINE_DDC4; + return true; + case REG(DC_GPIO_DDC5_A): + *en = GPIO_DDC_LINE_DDC5; + return true; + case REG(DC_GPIO_DDC6_A): + *en = GPIO_DDC_LINE_DDC6; + return true; + case REG(DC_GPIO_DDCVGA_A): + *en = GPIO_DDC_LINE_DDC_VGA; + return true; + /* GPIO_I2CPAD */ + case REG(DC_GPIO_I2CPAD_A): + *en = GPIO_DDC_LINE_I2C_PAD; + return true; + /* Not implemented */ + case REG(DC_GPIO_PWRSEQ_A): + case REG(DC_GPIO_PAD_STRENGTH_1): + case REG(DC_GPIO_PAD_STRENGTH_2): + case REG(DC_GPIO_DEBUG): + return false; + /* UNEXPECTED */ + default: + ASSERT_CRITICAL(false); + return false; + } +} + +static bool id_to_offset( + enum gpio_id id, + uint32_t en, + struct gpio_pin_info *info) +{ + bool result = true; + + switch (id) { + case GPIO_ID_DDC_DATA: + info->mask = DC_GPIO_DDC6_A__DC_GPIO_DDC6DATA_A_MASK; + switch (en) { + case GPIO_DDC_LINE_DDC1: + info->offset = REG(DC_GPIO_DDC1_A); + break; + case GPIO_DDC_LINE_DDC2: + info->offset = REG(DC_GPIO_DDC2_A); + break; + case GPIO_DDC_LINE_DDC3: + info->offset = REG(DC_GPIO_DDC3_A); + break; + case GPIO_DDC_LINE_DDC4: + info->offset = REG(DC_GPIO_DDC4_A); + break; + case GPIO_DDC_LINE_DDC5: + info->offset = REG(DC_GPIO_DDC5_A); + break; + case GPIO_DDC_LINE_DDC6: + info->offset = REG(DC_GPIO_DDC6_A); + break; + case GPIO_DDC_LINE_DDC_VGA: + info->offset = REG(DC_GPIO_DDCVGA_A); + break; + case GPIO_DDC_LINE_I2C_PAD: + info->offset = REG(DC_GPIO_I2CPAD_A); + break; + default: + ASSERT_CRITICAL(false); + result = false; + } + break; + case GPIO_ID_DDC_CLOCK: + info->mask = DC_GPIO_DDC6_A__DC_GPIO_DDC6CLK_A_MASK; + switch (en) { + case GPIO_DDC_LINE_DDC1: + info->offset = REG(DC_GPIO_DDC1_A); + break; + case GPIO_DDC_LINE_DDC2: + info->offset = REG(DC_GPIO_DDC2_A); + break; + case GPIO_DDC_LINE_DDC3: + info->offset = REG(DC_GPIO_DDC3_A); + break; + case GPIO_DDC_LINE_DDC4: + info->offset = REG(DC_GPIO_DDC4_A); + break; + case GPIO_DDC_LINE_DDC5: + info->offset = REG(DC_GPIO_DDC5_A); + break; + case GPIO_DDC_LINE_DDC6: + info->offset = REG(DC_GPIO_DDC6_A); + break; + case GPIO_DDC_LINE_DDC_VGA: + info->offset = REG(DC_GPIO_DDCVGA_A); + break; + case GPIO_DDC_LINE_I2C_PAD: + info->offset = REG(DC_GPIO_I2CPAD_A); + break; + default: + ASSERT_CRITICAL(false); + result = false; + } + break; + case GPIO_ID_GENERIC: + info->offset = REG(DC_GPIO_GENERIC_A); + switch (en) { + case GPIO_GENERIC_A: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICA_A_MASK; + break; + case GPIO_GENERIC_B: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICB_A_MASK; + break; + case GPIO_GENERIC_C: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICC_A_MASK; + break; + case GPIO_GENERIC_D: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICD_A_MASK; + break; + case GPIO_GENERIC_E: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICE_A_MASK; + break; + case GPIO_GENERIC_F: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICF_A_MASK; + break; + case GPIO_GENERIC_G: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICG_A_MASK; + break; + default: + ASSERT_CRITICAL(false); + result = false; + } + break; + case GPIO_ID_HPD: + info->offset = REG(DC_GPIO_HPD_A); + switch (en) { + case GPIO_HPD_1: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD1_A_MASK; + break; + case GPIO_HPD_2: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD2_A_MASK; + break; + case GPIO_HPD_3: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD3_A_MASK; + break; + case GPIO_HPD_4: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD4_A_MASK; + break; + case GPIO_HPD_5: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD5_A_MASK; + break; + case GPIO_HPD_6: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD6_A_MASK; + break; + default: + ASSERT_CRITICAL(false); + result = false; + } + break; + case GPIO_ID_SYNC: + switch (en) { + case GPIO_SYNC_HSYNC_A: + info->offset = REG(DC_GPIO_SYNCA_A); + info->mask = DC_GPIO_SYNCA_A__DC_GPIO_HSYNCA_A_MASK; + break; + case GPIO_SYNC_VSYNC_A: + info->offset = REG(DC_GPIO_SYNCA_A); + info->mask = DC_GPIO_SYNCA_A__DC_GPIO_VSYNCA_A_MASK; + break; + case GPIO_SYNC_HSYNC_B: + case GPIO_SYNC_VSYNC_B: + default: + ASSERT_CRITICAL(false); + result = false; + } + break; + case GPIO_ID_GSL: + switch (en) { + case GPIO_GSL_GENLOCK_CLOCK: + info->offset = REG(DC_GPIO_GENLK_A); + info->mask = DC_GPIO_GENLK_A__DC_GPIO_GENLK_CLK_A_MASK; + break; + case GPIO_GSL_GENLOCK_VSYNC: + info->offset = REG(DC_GPIO_GENLK_A); + info->mask = + DC_GPIO_GENLK_A__DC_GPIO_GENLK_VSYNC_A_MASK; + break; + case GPIO_GSL_SWAPLOCK_A: + info->offset = REG(DC_GPIO_GENLK_A); + info->mask = DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_A_A_MASK; + break; + case GPIO_GSL_SWAPLOCK_B: + info->offset = REG(DC_GPIO_GENLK_A); + info->mask = DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_B_A_MASK; + break; + default: + ASSERT_CRITICAL(false); + result = false; + } + break; + case GPIO_ID_VIP_PAD: + default: + ASSERT_CRITICAL(false); + result = false; + } + + if (result) { + info->offset_y = info->offset + 2; + info->offset_en = info->offset + 1; + info->offset_mask = info->offset - 1; + + info->mask_y = info->mask; + info->mask_en = info->mask; + info->mask_mask = info->mask; + } + + return result; +} + +/* function table */ +static const struct hw_translate_funcs funcs = { + .offset_to_id = offset_to_id, + .id_to_offset = id_to_offset, +}; + +/* + * dal_hw_translate_dce120_init + * + * @brief + * Initialize Hw translate function pointers. + * + * @param + * struct hw_translate *tr - [out] struct of function pointers + * + */ +void dal_hw_translate_dce120_init(struct hw_translate *tr) +{ + tr->funcs = &funcs; +} diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dce120/hw_translate_dce120.h b/drivers/gpu/drm/amd/display/dc/gpio/dce120/hw_translate_dce120.h new file mode 100644 index 000000000000..c21766894af3 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/dce120/hw_translate_dce120.h @@ -0,0 +1,34 @@ +/* + * Copyright 2013-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_HW_TRANSLATE_DCE120_H__ +#define __DAL_HW_TRANSLATE_DCE120_H__ + +struct hw_translate; + +/* Initialize Hw translate function pointers */ +void dal_hw_translate_dce120_init(struct hw_translate *tr); + +#endif /* __DAL_HW_TRANSLATE_DCE120_H__ */ -- cgit From c56fbb34717367bbd47fc795625100e53bed600f Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 6 Mar 2017 14:33:19 -0500 Subject: drm/amd/display: Add DCE12 i2c/aux support Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/i2caux/dce120/i2caux_dce120.c | 125 +++++++++++++++++++++ .../amd/display/dc/i2caux/dce120/i2caux_dce120.h | 32 ++++++ 2 files changed, 157 insertions(+) create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce120/i2caux_dce120.c create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce120/i2caux_dce120.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce120/i2caux_dce120.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce120/i2caux_dce120.c new file mode 100644 index 000000000000..91198295f1a4 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce120/i2caux_dce120.c @@ -0,0 +1,125 @@ +/* + * Copyright 2012-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "include/i2caux_interface.h" +#include "../i2caux.h" +#include "../engine.h" +#include "../i2c_engine.h" +#include "../i2c_sw_engine.h" +#include "../i2c_hw_engine.h" + +#include "../dce110/i2c_hw_engine_dce110.h" +#include "../dce110/aux_engine_dce110.h" +#include "../dce110/i2caux_dce110.h" + +#include "vega10/DC/dce_12_0_offset.h" +#include "vega10/DC/dce_12_0_sh_mask.h" +#include "vega10/soc15ip.h" + +/* begin ********************* + * macros to expend register list macro defined in HW object header file */ + +#define BASE_INNER(seg) \ + DCE_BASE__INST0_SEG ## seg + +/* compile time expand base address. */ +#define BASE(seg) \ + BASE_INNER(seg) + +#define SR(reg_name)\ + .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + \ + mm ## reg_name + +#define SRI(reg_name, block, id)\ + .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name +/* macros to expend register list macro defined in HW object header file + * end *********************/ + +#define aux_regs(id)\ +[id] = {\ + AUX_COMMON_REG_LIST(id), \ + .AUX_RESET_MASK = DP_AUX0_AUX_CONTROL__AUX_RESET_MASK \ +} + +static const struct dce110_aux_registers dce120_aux_regs[] = { + aux_regs(0), + aux_regs(1), + aux_regs(2), + aux_regs(3), + aux_regs(4), + aux_regs(5), +}; + +#define hw_engine_regs(id)\ +{\ + I2C_HW_ENGINE_COMMON_REG_LIST(id) \ +} + +static const struct dce110_i2c_hw_engine_registers dce120_hw_engine_regs[] = { + hw_engine_regs(1), + hw_engine_regs(2), + hw_engine_regs(3), + hw_engine_regs(4), + hw_engine_regs(5), + hw_engine_regs(6) +}; + +static const struct dce110_i2c_hw_engine_shift i2c_shift = { + I2C_COMMON_MASK_SH_LIST_DCE110(__SHIFT) +}; + +static const struct dce110_i2c_hw_engine_mask i2c_mask = { + I2C_COMMON_MASK_SH_LIST_DCE110(_MASK) +}; + +struct i2caux *dal_i2caux_dce120_create( + struct dc_context *ctx) +{ + struct i2caux_dce110 *i2caux_dce110 = + dm_alloc(sizeof(struct i2caux_dce110)); + + if (!i2caux_dce110) { + ASSERT_CRITICAL(false); + return NULL; + } + + if (dal_i2caux_dce110_construct( + i2caux_dce110, + ctx, + dce120_aux_regs, + dce120_hw_engine_regs, + &i2c_shift, + &i2c_mask)) + return &i2caux_dce110->base; + + ASSERT_CRITICAL(false); + + dm_free(i2caux_dce110); + + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce120/i2caux_dce120.h b/drivers/gpu/drm/amd/display/dc/i2caux/dce120/i2caux_dce120.h new file mode 100644 index 000000000000..b6ac47617c70 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce120/i2caux_dce120.h @@ -0,0 +1,32 @@ +/* + * Copyright 2012-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_I2C_AUX_DCE120_H__ +#define __DAL_I2C_AUX_DCE120_H__ + +struct i2caux *dal_i2caux_dce120_create( + struct dc_context *ctx); + +#endif /* __DAL_I2C_AUX_DCE120_H__ */ -- cgit From 9a48d684482e32edd5d96b14aa5517689bf904a3 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 6 Mar 2017 14:34:18 -0500 Subject: drm/amd/display: Add DCE12 irq support Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/irq/dce120/irq_service_dce120.c | 293 +++++++++++++++++++++ .../amd/display/dc/irq/dce120/irq_service_dce120.h | 34 +++ 2 files changed, 327 insertions(+) create mode 100644 drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c create mode 100644 drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c b/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c new file mode 100644 index 000000000000..5a263b2efa51 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c @@ -0,0 +1,293 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "include/logger_interface.h" + +#include "irq_service_dce120.h" +#include "../dce110/irq_service_dce110.h" + +#include "vega10/DC/dce_12_0_offset.h" +#include "vega10/DC/dce_12_0_sh_mask.h" +#include "vega10/soc15ip.h" + +#include "ivsrcid/ivsrcid_vislands30.h" + +static bool hpd_ack( + struct irq_service *irq_service, + const struct irq_source_info *info) +{ + uint32_t addr = info->status_reg; + uint32_t value = dm_read_reg(irq_service->ctx, addr); + uint32_t current_status = + get_reg_field_value( + value, + HPD0_DC_HPD_INT_STATUS, + DC_HPD_SENSE_DELAYED); + + dal_irq_service_ack_generic(irq_service, info); + + value = dm_read_reg(irq_service->ctx, info->enable_reg); + + set_reg_field_value( + value, + current_status ? 0 : 1, + HPD0_DC_HPD_INT_CONTROL, + DC_HPD_INT_POLARITY); + + dm_write_reg(irq_service->ctx, info->enable_reg, value); + + return true; +} + +static const struct irq_source_info_funcs hpd_irq_info_funcs = { + .set = NULL, + .ack = hpd_ack +}; + +static const struct irq_source_info_funcs hpd_rx_irq_info_funcs = { + .set = NULL, + .ack = NULL +}; + +static const struct irq_source_info_funcs pflip_irq_info_funcs = { + .set = NULL, + .ack = NULL +}; + +static const struct irq_source_info_funcs vblank_irq_info_funcs = { + .set = NULL, + .ack = NULL +}; + +#define BASE_INNER(seg) \ + DCE_BASE__INST0_SEG ## seg + +#define BASE(seg) \ + BASE_INNER(seg) + +#define SRI(reg_name, block, id)\ + BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + + +#define IRQ_REG_ENTRY(block, reg_num, reg1, mask1, reg2, mask2)\ + .enable_reg = SRI(reg1, block, reg_num),\ + .enable_mask = \ + block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\ + .enable_value = {\ + block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\ + ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \ + },\ + .ack_reg = SRI(reg2, block, reg_num),\ + .ack_mask = \ + block ## reg_num ## _ ## reg2 ## __ ## mask2 ## _MASK,\ + .ack_value = \ + block ## reg_num ## _ ## reg2 ## __ ## mask2 ## _MASK \ + +#define hpd_int_entry(reg_num)\ + [DC_IRQ_SOURCE_HPD1 + reg_num] = {\ + IRQ_REG_ENTRY(HPD, reg_num,\ + DC_HPD_INT_CONTROL, DC_HPD_INT_EN,\ + DC_HPD_INT_CONTROL, DC_HPD_INT_ACK),\ + .status_reg = SRI(DC_HPD_INT_STATUS, HPD, reg_num),\ + .funcs = &hpd_irq_info_funcs\ + } + +#define hpd_rx_int_entry(reg_num)\ + [DC_IRQ_SOURCE_HPD1RX + reg_num] = {\ + IRQ_REG_ENTRY(HPD, reg_num,\ + DC_HPD_INT_CONTROL, DC_HPD_RX_INT_EN,\ + DC_HPD_INT_CONTROL, DC_HPD_RX_INT_ACK),\ + .status_reg = SRI(DC_HPD_INT_STATUS, HPD, reg_num),\ + .funcs = &hpd_rx_irq_info_funcs\ + } +#define pflip_int_entry(reg_num)\ + [DC_IRQ_SOURCE_PFLIP1 + reg_num] = {\ + IRQ_REG_ENTRY(DCP, reg_num, \ + GRPH_INTERRUPT_CONTROL, GRPH_PFLIP_INT_MASK, \ + GRPH_INTERRUPT_STATUS, GRPH_PFLIP_INT_CLEAR),\ + .status_reg = SRI(GRPH_INTERRUPT_STATUS, DCP, reg_num),\ + .funcs = &pflip_irq_info_funcs\ + } + +#define vupdate_int_entry(reg_num)\ + [DC_IRQ_SOURCE_VUPDATE1 + reg_num] = {\ + IRQ_REG_ENTRY(CRTC, reg_num,\ + CRTC_INTERRUPT_CONTROL, CRTC_V_UPDATE_INT_MSK,\ + CRTC_V_UPDATE_INT_STATUS, CRTC_V_UPDATE_INT_CLEAR),\ + .funcs = &vblank_irq_info_funcs\ + } + +#define vblank_int_entry(reg_num)\ + [DC_IRQ_SOURCE_VBLANK1 + reg_num] = {\ + IRQ_REG_ENTRY(LB, reg_num,\ + LB_INTERRUPT_MASK, VBLANK_INTERRUPT_MASK,\ + LB_VBLANK_STATUS, VBLANK_ACK),\ + .funcs = &vblank_irq_info_funcs\ + } + +#define dummy_irq_entry() \ + {\ + .funcs = &dummy_irq_info_funcs\ + } + +#define i2c_int_entry(reg_num) \ + [DC_IRQ_SOURCE_I2C_DDC ## reg_num] = dummy_irq_entry() + +#define dp_sink_int_entry(reg_num) \ + [DC_IRQ_SOURCE_DPSINK ## reg_num] = dummy_irq_entry() + +#define gpio_pad_int_entry(reg_num) \ + [DC_IRQ_SOURCE_GPIOPAD ## reg_num] = dummy_irq_entry() + +#define dc_underflow_int_entry(reg_num) \ + [DC_IRQ_SOURCE_DC ## reg_num ## UNDERFLOW] = dummy_irq_entry() + +static const struct irq_source_info_funcs dummy_irq_info_funcs = { + .set = dal_irq_service_dummy_set, + .ack = dal_irq_service_dummy_ack +}; + +static const struct irq_source_info +irq_source_info_dce120[DAL_IRQ_SOURCES_NUMBER] = { + [DC_IRQ_SOURCE_INVALID] = dummy_irq_entry(), + hpd_int_entry(0), + hpd_int_entry(1), + hpd_int_entry(2), + hpd_int_entry(3), + hpd_int_entry(4), + hpd_int_entry(5), + hpd_rx_int_entry(0), + hpd_rx_int_entry(1), + hpd_rx_int_entry(2), + hpd_rx_int_entry(3), + hpd_rx_int_entry(4), + hpd_rx_int_entry(5), + i2c_int_entry(1), + i2c_int_entry(2), + i2c_int_entry(3), + i2c_int_entry(4), + i2c_int_entry(5), + i2c_int_entry(6), + dp_sink_int_entry(1), + dp_sink_int_entry(2), + dp_sink_int_entry(3), + dp_sink_int_entry(4), + dp_sink_int_entry(5), + dp_sink_int_entry(6), + [DC_IRQ_SOURCE_TIMER] = dummy_irq_entry(), + pflip_int_entry(0), + pflip_int_entry(1), + pflip_int_entry(2), + pflip_int_entry(3), + pflip_int_entry(4), + pflip_int_entry(5), + [DC_IRQ_SOURCE_PFLIP_UNDERLAY0] = dummy_irq_entry(), + gpio_pad_int_entry(0), + gpio_pad_int_entry(1), + gpio_pad_int_entry(2), + gpio_pad_int_entry(3), + gpio_pad_int_entry(4), + gpio_pad_int_entry(5), + gpio_pad_int_entry(6), + gpio_pad_int_entry(7), + gpio_pad_int_entry(8), + gpio_pad_int_entry(9), + gpio_pad_int_entry(10), + gpio_pad_int_entry(11), + gpio_pad_int_entry(12), + gpio_pad_int_entry(13), + gpio_pad_int_entry(14), + gpio_pad_int_entry(15), + gpio_pad_int_entry(16), + gpio_pad_int_entry(17), + gpio_pad_int_entry(18), + gpio_pad_int_entry(19), + gpio_pad_int_entry(20), + gpio_pad_int_entry(21), + gpio_pad_int_entry(22), + gpio_pad_int_entry(23), + gpio_pad_int_entry(24), + gpio_pad_int_entry(25), + gpio_pad_int_entry(26), + gpio_pad_int_entry(27), + gpio_pad_int_entry(28), + gpio_pad_int_entry(29), + gpio_pad_int_entry(30), + dc_underflow_int_entry(1), + dc_underflow_int_entry(2), + dc_underflow_int_entry(3), + dc_underflow_int_entry(4), + dc_underflow_int_entry(5), + dc_underflow_int_entry(6), + [DC_IRQ_SOURCE_DMCU_SCP] = dummy_irq_entry(), + [DC_IRQ_SOURCE_VBIOS_SW] = dummy_irq_entry(), + vupdate_int_entry(0), + vupdate_int_entry(1), + vupdate_int_entry(2), + vupdate_int_entry(3), + vupdate_int_entry(4), + vupdate_int_entry(5), + vblank_int_entry(0), + vblank_int_entry(1), + vblank_int_entry(2), + vblank_int_entry(3), + vblank_int_entry(4), + vblank_int_entry(5), +}; + +static const struct irq_service_funcs irq_service_funcs_dce120 = { + .to_dal_irq_source = to_dal_irq_source_dce110 +}; + +static bool construct( + struct irq_service *irq_service, + struct irq_service_init_data *init_data) +{ + if (!dal_irq_service_construct(irq_service, init_data)) + return false; + + irq_service->info = irq_source_info_dce120; + irq_service->funcs = &irq_service_funcs_dce120; + + return true; +} + +struct irq_service *dal_irq_service_dce120_create( + struct irq_service_init_data *init_data) +{ + struct irq_service *irq_service = dm_alloc(sizeof(*irq_service)); + + if (!irq_service) + return NULL; + + if (construct(irq_service, init_data)) + return irq_service; + + dm_free(irq_service); + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.h b/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.h new file mode 100644 index 000000000000..420c96e8fefc --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.h @@ -0,0 +1,34 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_IRQ_SERVICE_DCE120_H__ +#define __DAL_IRQ_SERVICE_DCE120_H__ + +#include "../irq_service.h" + +struct irq_service *dal_irq_service_dce120_create( + struct irq_service_init_data *init_data); + +#endif -- cgit From b8fdfcc6a92cd1defa770eb75607d579ad9e2e4e Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 6 Mar 2017 14:36:02 -0500 Subject: drm/amd/display: Add DCE12 core support Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/dce120/dce120_hw_sequencer.c | 197 ++++ .../amd/display/dc/dce120/dce120_hw_sequencer.h | 36 + drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp.c | 58 + drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp.h | 62 ++ .../drm/amd/display/dc/dce120/dce120_ipp_cursor.c | 202 ++++ .../drm/amd/display/dc/dce120/dce120_ipp_gamma.c | 167 +++ .../drm/amd/display/dc/dce120/dce120_mem_input.c | 340 ++++++ .../drm/amd/display/dc/dce120/dce120_mem_input.h | 37 + .../drm/amd/display/dc/dce120/dce120_resource.c | 1099 +++++++++++++++++++ .../drm/amd/display/dc/dce120/dce120_resource.h | 39 + .../display/dc/dce120/dce120_timing_generator.c | 1109 ++++++++++++++++++++ .../display/dc/dce120/dce120_timing_generator.h | 41 + 12 files changed, 3387 insertions(+) create mode 100644 drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp_cursor.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp_gamma.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce120/dce120_mem_input.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce120/dce120_mem_input.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c new file mode 100644 index 000000000000..f5ffd8f6ed3b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c @@ -0,0 +1,197 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "dc.h" +#include "core_dc.h" +#include "core_types.h" +#include "dce120_hw_sequencer.h" + +#include "dce110/dce110_hw_sequencer.h" + +/* include DCE12.0 register header files */ +#include "vega10/DC/dce_12_0_offset.h" +#include "vega10/DC/dce_12_0_sh_mask.h" +#include "vega10/soc15ip.h" +#include "reg_helper.h" + +struct dce120_hw_seq_reg_offsets { + uint32_t crtc; +}; + +static const struct dce120_hw_seq_reg_offsets reg_offsets[] = { +{ + .crtc = (mmCRTC0_CRTC_GSL_CONTROL - mmCRTC0_CRTC_GSL_CONTROL), +}, +{ + .crtc = (mmCRTC1_CRTC_GSL_CONTROL - mmCRTC0_CRTC_GSL_CONTROL), +}, +{ + .crtc = (mmCRTC2_CRTC_GSL_CONTROL - mmCRTC0_CRTC_GSL_CONTROL), +}, +{ + .crtc = (mmCRTC3_CRTC_GSL_CONTROL - mmCRTC0_CRTC_GSL_CONTROL), +}, +{ + .crtc = (mmCRTC4_CRTC_GSL_CONTROL - mmCRTC0_CRTC_GSL_CONTROL), +}, +{ + .crtc = (mmCRTC5_CRTC_GSL_CONTROL - mmCRTC0_CRTC_GSL_CONTROL), +} +}; + +#define HW_REG_CRTC(reg, id)\ + (reg + reg_offsets[id].crtc) + +#define CNTL_ID(controller_id)\ + controller_id +/******************************************************************************* + * Private definitions + ******************************************************************************/ +#if 0 +static void dce120_init_pte(struct dc_context *ctx, uint8_t controller_id) +{ + uint32_t addr; + uint32_t value = 0; + uint32_t chunk_int = 0; + uint32_t chunk_mul = 0; +/* + addr = mmDCP0_DVMM_PTE_CONTROL + controller_id * + (mmDCP1_DVMM_PTE_CONTROL- mmDCP0_DVMM_PTE_CONTROL); + + value = dm_read_reg(ctx, addr); + + set_reg_field_value( + value, 0, DCP, controller_id, + DVMM_PTE_CONTROL, + DVMM_USE_SINGLE_PTE); + + set_reg_field_value_soc15( + value, 1, DCP, controller_id, + DVMM_PTE_CONTROL, + DVMM_PTE_BUFFER_MODE0); + + set_reg_field_value_soc15( + value, 1, DCP, controller_id, + DVMM_PTE_CONTROL, + DVMM_PTE_BUFFER_MODE1); + + dm_write_reg(ctx, addr, value);*/ + + addr = mmDVMM_PTE_REQ; + value = dm_read_reg(ctx, addr); + + chunk_int = get_reg_field_value( + value, + DVMM_PTE_REQ, + HFLIP_PTEREQ_PER_CHUNK_INT); + + chunk_mul = get_reg_field_value( + value, + DVMM_PTE_REQ, + HFLIP_PTEREQ_PER_CHUNK_MULTIPLIER); + + if (chunk_int != 0x4 || chunk_mul != 0x4) { + + set_reg_field_value( + value, + 255, + DVMM_PTE_REQ, + MAX_PTEREQ_TO_ISSUE); + + set_reg_field_value( + value, + 4, + DVMM_PTE_REQ, + HFLIP_PTEREQ_PER_CHUNK_INT); + + set_reg_field_value( + value, + 4, + DVMM_PTE_REQ, + HFLIP_PTEREQ_PER_CHUNK_MULTIPLIER); + + dm_write_reg(ctx, addr, value); + } +} +#endif + +static bool dce120_enable_display_power_gating( + struct core_dc *dc, + uint8_t controller_id, + struct dc_bios *dcb, + enum pipe_gating_control power_gating) +{ + /* disable for bringup */ +#if 0 + enum bp_result bp_result = BP_RESULT_OK; + enum bp_pipe_control_action cntl; + struct dc_context *ctx = dc->ctx; + + if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment)) + return true; + + if (power_gating == PIPE_GATING_CONTROL_INIT) + cntl = ASIC_PIPE_INIT; + else if (power_gating == PIPE_GATING_CONTROL_ENABLE) + cntl = ASIC_PIPE_ENABLE; + else + cntl = ASIC_PIPE_DISABLE; + + if (power_gating != PIPE_GATING_CONTROL_INIT || controller_id == 0) { + + bp_result = dcb->funcs->enable_disp_power_gating( + dcb, controller_id + 1, cntl); + + /* Revert MASTER_UPDATE_MODE to 0 because bios sets it 2 + * by default when command table is called + */ + dm_write_reg(ctx, + HW_REG_CRTC(mmCRTC0_CRTC_MASTER_UPDATE_MODE, controller_id), + 0); + } + + if (power_gating != PIPE_GATING_CONTROL_ENABLE) + dce120_init_pte(ctx, controller_id); + + if (bp_result == BP_RESULT_OK) + return true; + else + return false; +#endif + return false; +} + +bool dce120_hw_sequencer_construct(struct core_dc *dc) +{ + /* All registers used by dce11.2 match those in dce11 in offset and + * structure + */ + dce110_hw_sequencer_construct(dc); + dc->hwss.enable_display_power_gating = dce120_enable_display_power_gating; + + return true; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.h new file mode 100644 index 000000000000..3402413c7156 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.h @@ -0,0 +1,36 @@ +/* +* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_HWSS_DCE120_H__ +#define __DC_HWSS_DCE120_H__ + +#include "core_types.h" + +struct core_dc; + +bool dce120_hw_sequencer_construct(struct core_dc *dc); + +#endif /* __DC_HWSS_DCE112_H__ */ + diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp.c new file mode 100644 index 000000000000..f4505690e01a --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp.c @@ -0,0 +1,58 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "include/logger_interface.h" + +#include "vega10/DC/dce_12_0_offset.h" +#include "vega10/DC/dce_12_0_sh_mask.h" +#include "vega10/soc15ip.h" + +#include "dce120_ipp.h" + +static const struct ipp_funcs funcs = { + .ipp_cursor_set_attributes = dce120_ipp_cursor_set_attributes, + .ipp_cursor_set_position = dce120_ipp_cursor_set_position, + .ipp_program_prescale = dce120_ipp_program_prescale, + .ipp_program_input_lut = dce120_ipp_program_input_lut, + .ipp_set_degamma = dce120_ipp_set_degamma, +}; + +bool dce120_ipp_construct( + struct dce110_ipp *ipp, + struct dc_context *ctx, + uint32_t inst, + const struct dce110_ipp_reg_offsets *offset) +{ + if (!dce110_ipp_construct(ipp, ctx, inst, offset)) { + ASSERT_CRITICAL(false); + return false; + } + + ipp->base.funcs = &funcs; + + return true; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp.h b/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp.h new file mode 100644 index 000000000000..4b326bcb4600 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp.h @@ -0,0 +1,62 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_IPP_DCE120_H__ +#define __DC_IPP_DCE120_H__ + +#include "ipp.h" +#include "../dce110/dce110_ipp.h" + + +bool dce120_ipp_construct( + struct dce110_ipp *ipp, + struct dc_context *ctx, + enum controller_id id, + const struct dce110_ipp_reg_offsets *offset); + +/* CURSOR RELATED */ +void dce120_ipp_cursor_set_position( + struct input_pixel_processor *ipp, + const struct dc_cursor_position *position, + const struct dc_cursor_mi_param *param); + +bool dce120_ipp_cursor_set_attributes( + struct input_pixel_processor *ipp, + const struct dc_cursor_attributes *attributes); + +/* DEGAMMA RELATED */ +bool dce120_ipp_set_degamma( + struct input_pixel_processor *ipp, + enum ipp_degamma_mode mode); + +void dce120_ipp_program_prescale( + struct input_pixel_processor *ipp, + struct ipp_prescale_params *params); + +void dce120_ipp_program_input_lut( + struct input_pixel_processor *ipp, + const struct dc_gamma *gamma); + +#endif /*__DC_IPP_DCE120_H__*/ diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp_cursor.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp_cursor.c new file mode 100644 index 000000000000..d520b5d7aa81 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp_cursor.c @@ -0,0 +1,202 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "include/logger_interface.h" + +#include "vega10/DC/dce_12_0_offset.h" +#include "vega10/DC/dce_12_0_sh_mask.h" +#include "vega10/soc15ip.h" + +#include "../dce110/dce110_ipp.h" + + +#define DCP_REG_UPDATE_N(reg_name, n, ...) \ + generic_reg_update_soc15(ipp110->base.ctx, ipp110->offsets.dcp_offset, reg_name, n, __VA_ARGS__) + +#define DCP_REG_SET_N(reg_name, n, ...) \ + generic_reg_set_soc15(ipp110->base.ctx, ipp110->offsets.dcp_offset, reg_name, n, __VA_ARGS__) + +#define DCP_REG_UPDATE(reg, field, val) \ + DCP_REG_UPDATE_N(reg, 1, FD(reg##__##field), val) + +#define DCP_REG_UPDATE_2(reg, field1, val1, field2, val2) \ + DCP_REG_UPDATE_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) + +#define DCP_REG_UPDATE_3(reg, field1, val1, field2, val2, field3, val3) \ + DCP_REG_UPDATE_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3) + +#define DCP_REG_SET(reg, field, val) \ + DCP_REG_SET_N(reg, 1, FD(reg##__##field), val) + +#define DCP_REG_SET_2(reg, field1, val1, field2, val2) \ + DCP_REG_SET_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) + +#define DCP_REG_SET_3(reg, field1, val1, field2, val2, field3, val3) \ + DCP_REG_SET_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3) + +/* TODO: DAL3 does not implement cursor memory control + * MCIF_MEM_CONTROL, DMIF_CURSOR_MEM_CONTROL + */ +static void lock( + struct dce110_ipp *ipp110, bool lock) +{ + DCP_REG_UPDATE(DCP0_CUR_UPDATE, CURSOR_UPDATE_LOCK, lock); +} + +static bool program_control( + struct dce110_ipp *ipp110, + enum dc_cursor_color_format color_format, + bool enable_magnification, + bool inverse_transparent_clamping) +{ + uint32_t mode = 0; + + switch (color_format) { + case CURSOR_MODE_MONO: + mode = 0; + break; + case CURSOR_MODE_COLOR_1BIT_AND: + mode = 1; + break; + case CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA: + mode = 2; + break; + case CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA: + mode = 3; + break; + default: + return false; + } + + DCP_REG_UPDATE_3( + DCP0_CUR_CONTROL, + CURSOR_MODE, mode, + CURSOR_2X_MAGNIFY, enable_magnification, + CUR_INV_TRANS_CLAMP, inverse_transparent_clamping); + + if (color_format == CURSOR_MODE_MONO) { + DCP_REG_SET_3( + DCP0_CUR_COLOR1, + CUR_COLOR1_BLUE, 0, + CUR_COLOR1_GREEN, 0, + CUR_COLOR1_RED, 0); + + DCP_REG_SET_3( + DCP0_CUR_COLOR2, + CUR_COLOR2_BLUE, 0xff, + CUR_COLOR2_GREEN, 0xff, + CUR_COLOR2_RED, 0xff); + } + return true; +} + +static void program_address( + struct dce110_ipp *ipp110, + PHYSICAL_ADDRESS_LOC address) +{ + /* SURFACE_ADDRESS_HIGH: Higher order bits (39:32) of hardware cursor + * surface base address in byte. It is 4K byte aligned. + * The correct way to program cursor surface address is to first write + * to CUR_SURFACE_ADDRESS_HIGH, and then write to CUR_SURFACE_ADDRESS + */ + + DCP_REG_SET( + DCP0_CUR_SURFACE_ADDRESS_HIGH, + CURSOR_SURFACE_ADDRESS_HIGH, address.high_part); + + DCP_REG_SET( + DCP0_CUR_SURFACE_ADDRESS, + CURSOR_SURFACE_ADDRESS, address.low_part); +} + +void dce120_ipp_cursor_set_position( + struct input_pixel_processor *ipp, + const struct dc_cursor_position *position, + const struct dc_cursor_mi_param *param) +{ + struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); + + /* lock cursor registers */ + lock(ipp110, true); + + /* Flag passed in structure differentiates cursor enable/disable. */ + /* Update if it differs from cached state. */ + DCP_REG_UPDATE(DCP0_CUR_CONTROL, CURSOR_EN, position->enable); + + DCP_REG_SET_2( + DCP0_CUR_POSITION, + CURSOR_X_POSITION, position->x, + CURSOR_Y_POSITION, position->y); + + if (position->hot_spot_enable) + DCP_REG_SET_2( + DCP0_CUR_HOT_SPOT, + CURSOR_HOT_SPOT_X, position->x_hotspot, + CURSOR_HOT_SPOT_Y, position->y_hotspot); + + /* unlock cursor registers */ + lock(ipp110, false); +} + +bool dce120_ipp_cursor_set_attributes( + struct input_pixel_processor *ipp, + const struct dc_cursor_attributes *attributes) +{ + struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); + /* Lock cursor registers */ + lock(ipp110, true); + + /* Program cursor control */ + program_control( + ipp110, + attributes->color_format, + attributes->attribute_flags.bits.ENABLE_MAGNIFICATION, + attributes->attribute_flags.bits.INVERSE_TRANSPARENT_CLAMPING); + + /* Program hot spot coordinates */ + DCP_REG_SET_2( + DCP0_CUR_HOT_SPOT, + CURSOR_HOT_SPOT_X, attributes->x_hot, + CURSOR_HOT_SPOT_Y, attributes->y_hot); + + /* + * Program cursor size -- NOTE: HW spec specifies that HW register + * stores size as (height - 1, width - 1) + */ + DCP_REG_SET_2( + DCP0_CUR_SIZE, + CURSOR_WIDTH, attributes->width-1, + CURSOR_HEIGHT, attributes->height-1); + + /* Program cursor surface address */ + program_address(ipp110, attributes->address); + + /* Unlock Cursor registers. */ + lock(ipp110, false); + + return true; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp_gamma.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp_gamma.c new file mode 100644 index 000000000000..7aa5a49c01e2 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp_gamma.c @@ -0,0 +1,167 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "include/logger_interface.h" +#include "include/fixed31_32.h" +#include "basics/conversion.h" + +#include "vega10/DC/dce_12_0_offset.h" +#include "vega10/DC/dce_12_0_sh_mask.h" +#include "vega10/soc15ip.h" + +#include "../dce110/dce110_ipp.h" + +#define DCP_REG_UPDATE_N(reg_name, n, ...) \ + generic_reg_update_soc15(ipp110->base.ctx, ipp110->offsets.dcp_offset, reg_name, n, __VA_ARGS__) + +#define DCP_REG_SET_N(reg_name, n, ...) \ + generic_reg_set_soc15(ipp110->base.ctx, ipp110->offsets.dcp_offset, reg_name, n, __VA_ARGS__) + +#define DCP_REG_UPDATE(reg, field, val) \ + DCP_REG_UPDATE_N(reg, 1, FD(reg##__##field), val) + +#define DCP_REG_UPDATE_2(reg, field1, val1, field2, val2) \ + DCP_REG_UPDATE_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) + +#define DCP_REG_UPDATE_3(reg, field1, val1, field2, val2, field3, val3) \ + DCP_REG_UPDATE_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3) + +#define DCP_REG_SET(reg, field, val) \ + DCP_REG_SET_N(reg, 1, FD(reg##__##field), val) + +#define DCP_REG_SET_2(reg, field1, val1, field2, val2) \ + DCP_REG_SET_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) + +#define DCP_REG_SET_3(reg, field1, val1, field2, val2, field3, val3) \ + DCP_REG_SET_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3) + + +bool dce120_ipp_set_degamma( + struct input_pixel_processor *ipp, + enum ipp_degamma_mode mode) +{ + struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); + uint32_t degamma_type = (mode == IPP_DEGAMMA_MODE_HW_sRGB) ? 1 : 0; + + ASSERT(mode == IPP_DEGAMMA_MODE_BYPASS || + mode == IPP_DEGAMMA_MODE_HW_sRGB); + + DCP_REG_SET_3( + DCP0_DEGAMMA_CONTROL, + GRPH_DEGAMMA_MODE, degamma_type, + CURSOR_DEGAMMA_MODE, degamma_type, + CURSOR2_DEGAMMA_MODE, degamma_type); + + return true; +} + +void dce120_ipp_program_prescale( + struct input_pixel_processor *ipp, + struct ipp_prescale_params *params) +{ + struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); + + /* set to bypass mode first before change */ + DCP_REG_UPDATE( + DCP0_PRESCALE_GRPH_CONTROL, + GRPH_PRESCALE_BYPASS, + 1); + + DCP_REG_SET_2( + DCP0_PRESCALE_VALUES_GRPH_R, + GRPH_PRESCALE_SCALE_R, params->scale, + GRPH_PRESCALE_BIAS_R, params->bias); + + DCP_REG_SET_2( + DCP0_PRESCALE_VALUES_GRPH_G, + GRPH_PRESCALE_SCALE_G, params->scale, + GRPH_PRESCALE_BIAS_G, params->bias); + + DCP_REG_SET_2( + DCP0_PRESCALE_VALUES_GRPH_B, + GRPH_PRESCALE_SCALE_B, params->scale, + GRPH_PRESCALE_BIAS_B, params->bias); + + if (params->mode != IPP_PRESCALE_MODE_BYPASS) { + DCP_REG_UPDATE(DCP0_PRESCALE_GRPH_CONTROL, + GRPH_PRESCALE_BYPASS, 0); + + /* If prescale is in use, then legacy lut should be bypassed */ + DCP_REG_UPDATE(DCP0_INPUT_GAMMA_CONTROL, + GRPH_INPUT_GAMMA_MODE, 1); + } +} + +static void dce120_helper_select_lut(struct dce110_ipp *ipp110) +{ + /* enable all */ + DCP_REG_SET( + DCP0_DC_LUT_WRITE_EN_MASK, + DC_LUT_WRITE_EN_MASK, + 0x7); + + /* 256 entry mode */ + DCP_REG_UPDATE(DCP0_DC_LUT_RW_MODE, DC_LUT_RW_MODE, 0); + + /* LUT-256, unsigned, integer, new u0.12 format */ + DCP_REG_SET_3( + DCP0_DC_LUT_CONTROL, + DC_LUT_DATA_R_FORMAT, 3, + DC_LUT_DATA_G_FORMAT, 3, + DC_LUT_DATA_B_FORMAT, 3); + + /* start from index 0 */ + DCP_REG_SET( + DCP0_DC_LUT_RW_INDEX, + DC_LUT_RW_INDEX, + 0); +} + +void dce120_ipp_program_input_lut( + struct input_pixel_processor *ipp, + const struct dc_gamma *gamma) +{ + int i; + struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); + + /* power on LUT memory */ + DCP_REG_SET(DCFE0_DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, 1); + + dce120_helper_select_lut(ipp110); + + for (i = 0; i < INPUT_LUT_ENTRIES; i++) { + DCP_REG_SET(DCP0_DC_LUT_SEQ_COLOR, DC_LUT_SEQ_COLOR, gamma->red[i]); + DCP_REG_SET(DCP0_DC_LUT_SEQ_COLOR, DC_LUT_SEQ_COLOR, gamma->green[i]); + DCP_REG_SET(DCP0_DC_LUT_SEQ_COLOR, DC_LUT_SEQ_COLOR, gamma->blue[i]); + } + + /* power off LUT memory */ + DCP_REG_SET(DCFE0_DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, 0); + + /* bypass prescale, enable legacy LUT */ + DCP_REG_UPDATE(DCP0_PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_BYPASS, 1); + DCP_REG_UPDATE(DCP0_INPUT_GAMMA_CONTROL, GRPH_INPUT_GAMMA_MODE, 0); +} diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_mem_input.c new file mode 100644 index 000000000000..c0677211bd93 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_mem_input.c @@ -0,0 +1,340 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#include "dm_services.h" +#include "dce120_mem_input.h" + + +#include "vega10/DC/dce_12_0_offset.h" +#include "vega10/DC/dce_12_0_sh_mask.h" +#include "vega10/soc15ip.h" + +#define GENERAL_REG_UPDATE_N(reg_name, n, ...) \ + generic_reg_update_soc15(mem_input110->base.ctx, 0, reg_name, n, __VA_ARGS__) + +#define GENERAL_REG_UPDATE(reg, field, val) \ + GENERAL_REG_UPDATE_N(reg, 1, FD(reg##__##field), val) + +#define GENERAL_REG_UPDATE_2(reg, field1, val1, field2, val2) \ + GENERAL_REG_UPDATE_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) + + + +#define DCP_REG_UPDATE_N(reg_name, n, ...) \ + generic_reg_update_soc15(mem_input110->base.ctx, mem_input110->offsets.dcp, reg_name, n, __VA_ARGS__) + +#define DCP_REG_SET_N(reg_name, n, ...) \ + generic_reg_set_soc15(mem_input110->base.ctx, mem_input110->offsets.dcp, reg_name, n, __VA_ARGS__) + +#define DCP_REG_UPDATE(reg, field, val) \ + DCP_REG_UPDATE_N(reg, 1, FD(reg##__##field), val) + +#define DCP_REG_UPDATE_2(reg, field1, val1, field2, val2) \ + DCP_REG_UPDATE_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) + +#define DCP_REG_UPDATE_3(reg, field1, val1, field2, val2, field3, val3) \ + DCP_REG_UPDATE_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3) + +#define DCP_REG_SET(reg, field, val) \ + DCP_REG_SET_N(reg, 1, FD(reg##__##field), val) + +#define DCP_REG_SET_2(reg, field1, val1, field2, val2) \ + DCP_REG_SET_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) + +#define DCP_REG_SET_3(reg, field1, val1, field2, val2, field3, val3) \ + DCP_REG_SET_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3) + + + +#define DMIF_REG_UPDATE_N(reg_name, n, ...) \ + generic_reg_update_soc15(mem_input110->base.ctx, mem_input110->offsets.dmif, reg_name, n, __VA_ARGS__) + +#define DMIF_REG_SET_N(reg_name, n, ...) \ + generic_reg_set_soc15(mem_input110->base.ctx, mem_input110->offsets.dmif, reg_name, n, __VA_ARGS__) + +#define DMIF_REG_UPDATE(reg, field, val) \ + DMIF_REG_UPDATE_N(reg, 1, FD(reg##__##field), val) + +#define DMIF_REG_UPDATE_2(reg, field1, val1, field2, val2) \ + DMIF_REG_UPDATE_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) + +#define DMIF_REG_UPDATE_3(reg, field1, val1, field2, val2, field3, val3) \ + DMIF_REG_UPDATE_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3) + +#define DMIF_REG_SET(reg, field, val) \ + DMIF_REG_SET_N(reg, 1, FD(reg##__##field), val) + +#define DMIF_REG_SET_2(reg, field1, val1, field2, val2) \ + DMIF_REG_SET_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) + +#define DMIF_REG_SET_3(reg, field1, val1, field2, val2, field3, val3) \ + DMIF_REG_SET_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3) + + + +#define PIPE_REG_UPDATE_N(reg_name, n, ...) \ + generic_reg_update_soc15(mem_input110->base.ctx, mem_input110->offsets.pipe, reg_name, n, __VA_ARGS__) + +#define PIPE_REG_SET_N(reg_name, n, ...) \ + generic_reg_set_soc15(mem_input110->base.ctx, mem_input110->offsets.pipe, reg_name, n, __VA_ARGS__) + +#define PIPE_REG_UPDATE(reg, field, val) \ + PIPE_REG_UPDATE_N(reg, 1, FD(reg##__##field), val) + +#define PIPE_REG_UPDATE_2(reg, field1, val1, field2, val2) \ + PIPE_REG_UPDATE_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) + +#define PIPE_REG_UPDATE_3(reg, field1, val1, field2, val2, field3, val3) \ + PIPE_REG_UPDATE_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3) + +#define PIPE_REG_SET(reg, field, val) \ + PIPE_REG_SET_N(reg, 1, FD(reg##__##field), val) + +#define PIPE_REG_SET_2(reg, field1, val1, field2, val2) \ + PIPE_REG_SET_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) + +#define PIPE_REG_SET_3(reg, field1, val1, field2, val2, field3, val3) \ + PIPE_REG_SET_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3) + + + +static void program_sec_addr( + struct dce110_mem_input *mem_input110, + PHYSICAL_ADDRESS_LOC address) +{ + uint32_t temp; + + /*high register MUST be programmed first*/ + temp = address.high_part & + DCP0_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH__GRPH_SECONDARY_SURFACE_ADDRESS_HIGH_MASK; + + DCP_REG_SET( + DCP0_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, + GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, + temp); + + temp = address.low_part >> + DCP0_GRPH_SECONDARY_SURFACE_ADDRESS__GRPH_SECONDARY_SURFACE_ADDRESS__SHIFT; + + DCP_REG_SET_2( + DCP0_GRPH_SECONDARY_SURFACE_ADDRESS, + GRPH_SECONDARY_SURFACE_ADDRESS, temp, + GRPH_SECONDARY_DFQ_ENABLE, 0); +} + +static void program_pri_addr( + struct dce110_mem_input *mem_input110, + PHYSICAL_ADDRESS_LOC address) +{ + uint32_t temp; + + /*high register MUST be programmed first*/ + temp = address.high_part & + DCP0_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH__GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_MASK; + + DCP_REG_SET( + DCP0_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, + GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, + temp); + + temp = address.low_part >> + DCP0_GRPH_PRIMARY_SURFACE_ADDRESS__GRPH_PRIMARY_SURFACE_ADDRESS__SHIFT; + + DCP_REG_SET( + DCP0_GRPH_PRIMARY_SURFACE_ADDRESS, + GRPH_PRIMARY_SURFACE_ADDRESS, + temp); +} + + +static bool mem_input_is_flip_pending(struct mem_input *mem_input) +{ + struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input); + uint32_t value; + + value = dm_read_reg_soc15(mem_input110->base.ctx, + mmDCP0_GRPH_UPDATE, mem_input110->offsets.dcp); + + if (get_reg_field_value(value, DCP0_GRPH_UPDATE, + GRPH_SURFACE_UPDATE_PENDING)) + return true; + + mem_input->current_address = mem_input->request_address; + return false; +} + +static bool mem_input_program_surface_flip_and_addr( + struct mem_input *mem_input, + const struct dc_plane_address *address, + bool flip_immediate) +{ + struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input); + + /* TODO: Figure out if two modes are needed: + * non-XDMA Mode: GRPH_SURFACE_UPDATE_IMMEDIATE_EN = 1 + * XDMA Mode: GRPH_SURFACE_UPDATE_H_RETRACE_EN = 1 + */ + DCP_REG_UPDATE(DCP0_GRPH_UPDATE, + GRPH_UPDATE_LOCK, 1); + + if (flip_immediate) { + DCP_REG_UPDATE_2( + DCP0_GRPH_FLIP_CONTROL, + GRPH_SURFACE_UPDATE_IMMEDIATE_EN, 0, + GRPH_SURFACE_UPDATE_H_RETRACE_EN, 1); + } else { + DCP_REG_UPDATE_2( + DCP0_GRPH_FLIP_CONTROL, + GRPH_SURFACE_UPDATE_IMMEDIATE_EN, 0, + GRPH_SURFACE_UPDATE_H_RETRACE_EN, 0); + } + + switch (address->type) { + case PLN_ADDR_TYPE_GRAPHICS: + if (address->grph.addr.quad_part == 0) + break; + program_pri_addr(mem_input110, address->grph.addr); + break; + case PLN_ADDR_TYPE_GRPH_STEREO: + if (address->grph_stereo.left_addr.quad_part == 0 + || address->grph_stereo.right_addr.quad_part == 0) + break; + program_pri_addr(mem_input110, address->grph_stereo.left_addr); + program_sec_addr(mem_input110, address->grph_stereo.right_addr); + break; + default: + /* not supported */ + BREAK_TO_DEBUGGER(); + break; + } + + mem_input->request_address = *address; + + if (flip_immediate) + mem_input->current_address = *address; + + DCP_REG_UPDATE(DCP0_GRPH_UPDATE, + GRPH_UPDATE_LOCK, 0); + + return true; +} + +static void mem_input_update_dchub(struct mem_input *mi, + struct dchub_init_data *dh_data) +{ + struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mi); + /* TODO: port code from dal2 */ + switch (dh_data->fb_mode) { + case FRAME_BUFFER_MODE_ZFB_ONLY: + /*For ZFB case need to put DCHUB FB BASE and TOP upside down to indicate ZFB mode*/ + GENERAL_REG_UPDATE_2( + DCHUB_FB_LOCATION, + FB_TOP, 0, + FB_BASE, 0x0FFFF); + + GENERAL_REG_UPDATE( + DCHUB_AGP_BASE, + AGP_BASE, dh_data->zfb_phys_addr_base >> 22); + + GENERAL_REG_UPDATE( + DCHUB_AGP_BOT, + AGP_BOT, dh_data->zfb_mc_base_addr >> 22); + + GENERAL_REG_UPDATE( + DCHUB_AGP_TOP, + AGP_TOP, (dh_data->zfb_mc_base_addr + dh_data->zfb_size_in_byte - 1) >> 22); + break; + case FRAME_BUFFER_MODE_MIXED_ZFB_AND_LOCAL: + /*Should not touch FB LOCATION (done by VBIOS on AsicInit table)*/ + GENERAL_REG_UPDATE( + DCHUB_AGP_BASE, + AGP_BASE, dh_data->zfb_phys_addr_base >> 22); + + GENERAL_REG_UPDATE( + DCHUB_AGP_BOT, + AGP_BOT, dh_data->zfb_mc_base_addr >> 22); + + GENERAL_REG_UPDATE( + DCHUB_AGP_TOP, + AGP_TOP, (dh_data->zfb_mc_base_addr + dh_data->zfb_size_in_byte - 1) >> 22); + break; + case FRAME_BUFFER_MODE_LOCAL_ONLY: + /*Should not touch FB LOCATION (done by VBIOS on AsicInit table)*/ + GENERAL_REG_UPDATE( + DCHUB_AGP_BASE, + AGP_BASE, 0); + + GENERAL_REG_UPDATE( + DCHUB_AGP_BOT, + AGP_BOT, 0x03FFFF); + + GENERAL_REG_UPDATE( + DCHUB_AGP_TOP, + AGP_TOP, 0); + break; + default: + break; + } + + dh_data->dchub_initialzied = true; + dh_data->dchub_info_valid = false; +} + +static struct mem_input_funcs dce120_mem_input_funcs = { + .mem_input_program_display_marks = dce_mem_input_program_display_marks, + .allocate_mem_input = dce_mem_input_allocate_dmif, + .free_mem_input = dce_mem_input_free_dmif, + .mem_input_program_surface_flip_and_addr = + mem_input_program_surface_flip_and_addr, + .mem_input_program_pte_vm = dce_mem_input_program_pte_vm, + .mem_input_program_surface_config = + dce_mem_input_program_surface_config, + .mem_input_is_flip_pending = mem_input_is_flip_pending, + .mem_input_update_dchub = mem_input_update_dchub +}; + +/*****************************************/ +/* Constructor, Destructor */ +/*****************************************/ + +bool dce120_mem_input_construct( + struct dce110_mem_input *mem_input110, + struct dc_context *ctx, + uint32_t inst, + const struct dce110_mem_input_reg_offsets *offsets) +{ + /* supported stutter method + * STUTTER_MODE_ENHANCED + * STUTTER_MODE_QUAD_DMIF_BUFFER + * STUTTER_MODE_WATERMARK_NBP_STATE + */ + + if (!dce110_mem_input_construct(mem_input110, ctx, inst, offsets)) + return false; + + mem_input110->base.funcs = &dce120_mem_input_funcs; + mem_input110->offsets = *offsets; + + return true; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce120/dce120_mem_input.h new file mode 100644 index 000000000000..379fd72155b9 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_mem_input.h @@ -0,0 +1,37 @@ +/* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_MEM_INPUT_DCE120_H__ +#define __DC_MEM_INPUT_DCE120_H__ + +#include "mem_input.h" +#include "dce110/dce110_mem_input.h" + +bool dce120_mem_input_construct( + struct dce110_mem_input *mem_input110, + struct dc_context *ctx, + uint32_t inst, + const struct dce110_mem_input_reg_offsets *offsets); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c new file mode 100644 index 000000000000..9a1984b36592 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -0,0 +1,1099 @@ +/* +* Copyright 2012-15 Advanced Micro Devices, Inc.cls +* + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + + +#include "stream_encoder.h" +#include "resource.h" +#include "include/irq_service_interface.h" +#include "dce120_resource.h" +#include "dce112/dce112_resource.h" + +#include "dce110/dce110_resource.h" +#include "../virtual/virtual_stream_encoder.h" +#include "dce120_timing_generator.h" +#include "irq/dce120/irq_service_dce120.h" +#include "dce/dce_opp.h" +#include "dce/dce_clock_source.h" +#include "dce/dce_clocks.h" +#include "dce120_ipp.h" +#include "dce110/dce110_mem_input.h" +#include "dce120/dce120_mem_input.h" + +#include "dce110/dce110_hw_sequencer.h" +#include "dce120/dce120_hw_sequencer.h" +#include "dce/dce_transform.h" + +#include "dce/dce_audio.h" +#include "dce/dce_link_encoder.h" +#include "dce/dce_stream_encoder.h" +#include "dce/dce_hwseq.h" +#include "dce/dce_abm.h" +#include "dce/dce_dmcu.h" + +#include "vega10/DC/dce_12_0_offset.h" +#include "vega10/DC/dce_12_0_sh_mask.h" +#include "vega10/soc15ip.h" +#include "vega10/NBIO/nbio_6_1_offset.h" +#include "reg_helper.h" + +#ifndef mmDP0_DP_DPHY_INTERNAL_CTRL + #define mmDP0_DP_DPHY_INTERNAL_CTRL 0x210f + #define mmDP0_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 + #define mmDP1_DP_DPHY_INTERNAL_CTRL 0x220f + #define mmDP1_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 + #define mmDP2_DP_DPHY_INTERNAL_CTRL 0x230f + #define mmDP2_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 + #define mmDP3_DP_DPHY_INTERNAL_CTRL 0x240f + #define mmDP3_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 + #define mmDP4_DP_DPHY_INTERNAL_CTRL 0x250f + #define mmDP4_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 + #define mmDP5_DP_DPHY_INTERNAL_CTRL 0x260f + #define mmDP5_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 + #define mmDP6_DP_DPHY_INTERNAL_CTRL 0x270f + #define mmDP6_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 +#endif + +enum dce120_clk_src_array_id { + DCE120_CLK_SRC_PLL0, + DCE120_CLK_SRC_PLL1, + DCE120_CLK_SRC_PLL2, + DCE120_CLK_SRC_PLL3, + DCE120_CLK_SRC_PLL4, + DCE120_CLK_SRC_PLL5, + + DCE120_CLK_SRC_TOTAL +}; + +static const struct dce110_timing_generator_offsets dce120_tg_offsets[] = { + { + .crtc = (mmCRTC0_CRTC_CONTROL - mmCRTC0_CRTC_CONTROL), + }, + { + .crtc = (mmCRTC1_CRTC_CONTROL - mmCRTC0_CRTC_CONTROL), + }, + { + .crtc = (mmCRTC2_CRTC_CONTROL - mmCRTC0_CRTC_CONTROL), + }, + { + .crtc = (mmCRTC3_CRTC_CONTROL - mmCRTC0_CRTC_CONTROL), + }, + { + .crtc = (mmCRTC4_CRTC_CONTROL - mmCRTC0_CRTC_CONTROL), + }, + { + .crtc = (mmCRTC5_CRTC_CONTROL - mmCRTC0_CRTC_CONTROL), + } +}; + +/* begin ********************* + * macros to expend register list macro defined in HW object header file */ + +#define BASE_INNER(seg) \ + DCE_BASE__INST0_SEG ## seg + +#define NBIO_BASE_INNER(seg) \ + NBIF_BASE__INST0_SEG ## seg + +#define NBIO_BASE(seg) \ + NBIO_BASE_INNER(seg) + +/* compile time expand base address. */ +#define BASE(seg) \ + BASE_INNER(seg) + +#define SR(reg_name)\ + .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + \ + mm ## reg_name + +#define SRI(reg_name, block, id)\ + .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +/* macros to expend register list macro defined in HW object header file + * end *********************/ + + +static const struct dce_disp_clk_registers disp_clk_regs = { + CLK_COMMON_REG_LIST_DCE_BASE() +}; + +static const struct dce_disp_clk_shift disp_clk_shift = { + CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) +}; + +static const struct dce_disp_clk_mask disp_clk_mask = { + CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) +}; + +static const struct dce_dmcu_registers dmcu_regs = { + DMCU_DCE110_COMMON_REG_LIST() +}; + +static const struct dce_dmcu_shift dmcu_shift = { + DMCU_MASK_SH_LIST_DCE110(__SHIFT) +}; + +static const struct dce_dmcu_mask dmcu_mask = { + DMCU_MASK_SH_LIST_DCE110(_MASK) +}; + +static const struct dce_abm_registers abm_regs = { + ABM_DCE110_COMMON_REG_LIST() +}; + +static const struct dce_abm_shift abm_shift = { + ABM_MASK_SH_LIST_DCE110(__SHIFT) +}; + +static const struct dce_abm_mask abm_mask = { + ABM_MASK_SH_LIST_DCE110(_MASK) +}; + +#define transform_regs(id)\ +[id] = {\ + XFM_COMMON_REG_LIST_DCE110(id)\ +} + +static const struct dce_transform_registers xfm_regs[] = { + transform_regs(0), + transform_regs(1), + transform_regs(2), + transform_regs(3), + transform_regs(4), + transform_regs(5) +}; + +static const struct dce_transform_shift xfm_shift = { + XFM_COMMON_MASK_SH_LIST_SOC_BASE(__SHIFT) +}; + +static const struct dce_transform_mask xfm_mask = { + XFM_COMMON_MASK_SH_LIST_SOC_BASE(_MASK) +}; + +#define aux_regs(id)\ +[id] = {\ + AUX_REG_LIST(id)\ +} + +static const struct dce110_link_enc_aux_registers link_enc_aux_regs[] = { + aux_regs(0), + aux_regs(1), + aux_regs(2), + aux_regs(3), + aux_regs(4), + aux_regs(5) +}; + +#define hpd_regs(id)\ +[id] = {\ + HPD_REG_LIST(id)\ +} + +static const struct dce110_link_enc_hpd_registers link_enc_hpd_regs[] = { + hpd_regs(0), + hpd_regs(1), + hpd_regs(2), + hpd_regs(3), + hpd_regs(4), + hpd_regs(5) +}; + +#define link_regs(id)\ +[id] = {\ + LE_DCE120_REG_LIST(id), \ + SRI(DP_DPHY_INTERNAL_CTRL, DP, id) \ +} + +static const struct dce110_link_enc_registers link_enc_regs[] = { + link_regs(0), + link_regs(1), + link_regs(2), + link_regs(3), + link_regs(4), + link_regs(5), + link_regs(6), +}; + + +#define stream_enc_regs(id)\ +[id] = {\ + SE_COMMON_REG_LIST(id),\ + .TMDS_CNTL = 0,\ +} + +static const struct dce110_stream_enc_registers stream_enc_regs[] = { + stream_enc_regs(0), + stream_enc_regs(1), + stream_enc_regs(2), + stream_enc_regs(3), + stream_enc_regs(4), + stream_enc_regs(5) +}; + +static const struct dce_stream_encoder_shift se_shift = { + SE_COMMON_MASK_SH_LIST_DCE120(__SHIFT) +}; + +static const struct dce_stream_encoder_mask se_mask = { + SE_COMMON_MASK_SH_LIST_DCE120(_MASK) +}; + +#define opp_regs(id)\ +[id] = {\ + OPP_DCE_120_REG_LIST(id),\ +} + +static const struct dce_opp_registers opp_regs[] = { + opp_regs(0), + opp_regs(1), + opp_regs(2), + opp_regs(3), + opp_regs(4), + opp_regs(5) +}; + +static const struct dce_opp_shift opp_shift = { + OPP_COMMON_MASK_SH_LIST_DCE_120(__SHIFT) +}; + +static const struct dce_opp_mask opp_mask = { + OPP_COMMON_MASK_SH_LIST_DCE_120(_MASK) +}; + +#define audio_regs(id)\ +[id] = {\ + AUD_COMMON_REG_LIST(id)\ +} + +static struct dce_audio_registers audio_regs[] = { + audio_regs(0), + audio_regs(1), + audio_regs(2), + audio_regs(3), + audio_regs(4), + audio_regs(5) +}; + +#define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\ + SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\ + SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\ + AUD_COMMON_MASK_SH_LIST_BASE(mask_sh) + +static const struct dce_audio_shift audio_shift = { + DCE120_AUD_COMMON_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_aduio_mask audio_mask = { + DCE120_AUD_COMMON_MASK_SH_LIST(_MASK) +}; + +#define clk_src_regs(index, id)\ +[index] = {\ + CS_COMMON_REG_LIST_DCE_112(id),\ +} + +static const struct dce110_clk_src_regs clk_src_regs[] = { + clk_src_regs(0, A), + clk_src_regs(1, B), + clk_src_regs(2, C), + clk_src_regs(3, D), + clk_src_regs(4, E), + clk_src_regs(5, F) +}; + +static const struct dce110_clk_src_shift cs_shift = { + CS_COMMON_MASK_SH_LIST_DCE_112(__SHIFT) +}; + +static const struct dce110_clk_src_mask cs_mask = { + CS_COMMON_MASK_SH_LIST_DCE_112(_MASK) +}; + +struct output_pixel_processor *dce120_opp_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dce110_opp *opp = + dm_alloc(sizeof(struct dce110_opp)); + + if (!opp) + return NULL; + + if (dce110_opp_construct(opp, + ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask)) + return &opp->base; + + BREAK_TO_DEBUGGER(); + dm_free(opp); + return NULL; +} + +static const struct dce110_ipp_reg_offsets dce120_ipp_reg_offsets[] = { + { + .dcp_offset = (mmDCP0_CUR_CONTROL - mmDCP0_CUR_CONTROL), + }, + { + .dcp_offset = (mmDCP1_CUR_CONTROL - mmDCP0_CUR_CONTROL), + }, + { + .dcp_offset = (mmDCP2_CUR_CONTROL - mmDCP0_CUR_CONTROL), + }, + { + .dcp_offset = (mmDCP3_CUR_CONTROL - mmDCP0_CUR_CONTROL), + }, + { + .dcp_offset = (mmDCP4_CUR_CONTROL - mmDCP0_CUR_CONTROL), + }, + { + .dcp_offset = (mmDCP5_CUR_CONTROL - mmDCP0_CUR_CONTROL), + } +}; + +static const struct dce110_mem_input_reg_offsets dce120_mi_reg_offsets[] = { + { + .dcp = (mmDCP0_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), + .dmif = (mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL + - mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE0_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + }, + { + .dcp = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), + .dmif = (mmDMIF_PG1_DPG_WATERMARK_MASK_CONTROL + - mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE1_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + }, + { + .dcp = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), + .dmif = (mmDMIF_PG2_DPG_WATERMARK_MASK_CONTROL + - mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE2_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + }, + { + .dcp = (mmDCP3_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), + .dmif = (mmDMIF_PG3_DPG_WATERMARK_MASK_CONTROL + - mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE3_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + }, + { + .dcp = (mmDCP4_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), + .dmif = (mmDMIF_PG4_DPG_WATERMARK_MASK_CONTROL + - mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE4_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + }, + { + .dcp = (mmDCP5_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), + .dmif = (mmDMIF_PG5_DPG_WATERMARK_MASK_CONTROL + - mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE5_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + } +}; + +static const struct bios_registers bios_regs = { + .BIOS_SCRATCH_6 = mmBIOS_SCRATCH_6 + NBIO_BASE(mmBIOS_SCRATCH_6_BASE_IDX) +}; + +static const struct resource_caps res_cap = { + .num_timing_generator = 3, + .num_audio = 7, + .num_stream_encoder = 6, + .num_pll = 6, +}; + +static const struct dc_debug debug_defaults = { + .disable_clock_gate = true, +}; + +struct clock_source *dce120_clock_source_create( + struct dc_context *ctx, + struct dc_bios *bios, + enum clock_source_id id, + const struct dce110_clk_src_regs *regs, + bool dp_clk_src) +{ + struct dce110_clk_src *clk_src = + dm_alloc(sizeof(struct dce110_clk_src)); + + if (!clk_src) + return NULL; + + if (dce110_clk_src_construct(clk_src, ctx, bios, id, + regs, &cs_shift, &cs_mask)) { + clk_src->base.dp_clk_src = dp_clk_src; + return &clk_src->base; + } + + BREAK_TO_DEBUGGER(); + return NULL; +} + +void dce120_clock_source_destroy(struct clock_source **clk_src) +{ + dm_free(TO_DCE110_CLK_SRC(*clk_src)); + *clk_src = NULL; +} + + +bool dce120_hw_sequencer_create(struct core_dc *dc) +{ + /* All registers used by dce11.2 match those in dce11 in offset and + * structure + */ + dce120_hw_sequencer_construct(dc); + + /*TODO Move to separate file and Override what is needed */ + + return true; +} + +static struct timing_generator *dce120_timing_generator_create( + struct dc_context *ctx, + uint32_t instance, + const struct dce110_timing_generator_offsets *offsets) +{ + struct dce110_timing_generator *tg110 = + dm_alloc(sizeof(struct dce110_timing_generator)); + + if (!tg110) + return NULL; + + if (dce120_timing_generator_construct(tg110, ctx, instance, offsets)) + return &tg110->base; + + BREAK_TO_DEBUGGER(); + dm_free(tg110); + return NULL; +} + +static void dce120_ipp_destroy(struct input_pixel_processor **ipp) +{ + dm_free(TO_DCE110_IPP(*ipp)); + *ipp = NULL; +} + +static void dce120_transform_destroy(struct transform **xfm) +{ + dm_free(TO_DCE_TRANSFORM(*xfm)); + *xfm = NULL; +} + +static void destruct(struct dce110_resource_pool *pool) +{ + unsigned int i; + + for (i = 0; i < pool->base.pipe_count; i++) { + if (pool->base.opps[i] != NULL) + dce110_opp_destroy(&pool->base.opps[i]); + + if (pool->base.transforms[i] != NULL) + dce120_transform_destroy(&pool->base.transforms[i]); + + if (pool->base.ipps[i] != NULL) + dce120_ipp_destroy(&pool->base.ipps[i]); + + if (pool->base.mis[i] != NULL) { + dm_free(TO_DCE110_MEM_INPUT(pool->base.mis[i])); + pool->base.mis[i] = NULL; + } + + if (pool->base.irqs != NULL) { + dal_irq_service_destroy(&pool->base.irqs); + } + + if (pool->base.timing_generators[i] != NULL) { + dm_free(DCE110TG_FROM_TG(pool->base.timing_generators[i])); + pool->base.timing_generators[i] = NULL; + } + } + + for (i = 0; i < pool->base.audio_count; i++) { + if (pool->base.audios[i]) + dce_aud_destroy(&pool->base.audios[i]); + } + + for (i = 0; i < pool->base.stream_enc_count; i++) { + if (pool->base.stream_enc[i] != NULL) + dm_free(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); + } + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] != NULL) + dce120_clock_source_destroy( + &pool->base.clock_sources[i]); + } + + if (pool->base.dp_clock_source != NULL) + dce120_clock_source_destroy(&pool->base.dp_clock_source); + + if (pool->base.abm != NULL) + dce_abm_destroy(&pool->base.abm); + + if (pool->base.dmcu != NULL) + dce_dmcu_destroy(&pool->base.dmcu); + + if (pool->base.display_clock != NULL) + dce_disp_clk_destroy(&pool->base.display_clock); +} + +static void read_dce_straps( + struct dc_context *ctx, + struct resource_straps *straps) +{ + /* TODO: Registers are missing */ + /*REG_GET_2(CC_DC_HDMI_STRAPS, + HDMI_DISABLE, &straps->hdmi_disable, + AUDIO_STREAM_NUMBER, &straps->audio_stream_number); + + REG_GET(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO, &straps->dc_pinstraps_audio);*/ +} + +static struct audio *create_audio( + struct dc_context *ctx, unsigned int inst) +{ + return dce_audio_create(ctx, inst, + &audio_regs[inst], &audio_shift, &audio_mask); +} + +static const struct encoder_feature_support link_enc_feature = { + .max_hdmi_deep_color = COLOR_DEPTH_121212, + .max_hdmi_pixel_clock = 600000, + .ycbcr420_supported = true, + .flags.bits.IS_HBR2_CAPABLE = true, + .flags.bits.IS_HBR3_CAPABLE = true, + .flags.bits.IS_TPS3_CAPABLE = true, + .flags.bits.IS_TPS4_CAPABLE = true, + .flags.bits.IS_YCBCR_CAPABLE = true +}; + +struct link_encoder *dce120_link_encoder_create( + const struct encoder_init_data *enc_init_data) +{ + struct dce110_link_encoder *enc110 = + dm_alloc(sizeof(struct dce110_link_encoder)); + + if (!enc110) + return NULL; + + if (dce110_link_encoder_construct( + enc110, + enc_init_data, + &link_enc_feature, + &link_enc_regs[enc_init_data->transmitter], + &link_enc_aux_regs[enc_init_data->channel - 1], + &link_enc_hpd_regs[enc_init_data->hpd_source])) { + + return &enc110->base; + } + + BREAK_TO_DEBUGGER(); + dm_free(enc110); + return NULL; +} + +static struct input_pixel_processor *dce120_ipp_create( + struct dc_context *ctx, + uint32_t inst, + const struct dce110_ipp_reg_offsets *offset) +{ + struct dce110_ipp *ipp = dm_alloc(sizeof(struct dce110_ipp)); + + if (!ipp) + return NULL; + + if (dce120_ipp_construct(ipp, ctx, inst, offset)) + return &ipp->base; + + BREAK_TO_DEBUGGER(); + dm_free(ipp); + return NULL; +} + +static struct stream_encoder *dce120_stream_encoder_create( + enum engine_id eng_id, + struct dc_context *ctx) +{ + struct dce110_stream_encoder *enc110 = + dm_alloc(sizeof(struct dce110_stream_encoder)); + + if (!enc110) + return NULL; + + if (dce110_stream_encoder_construct( + enc110, ctx, ctx->dc_bios, eng_id, + &stream_enc_regs[eng_id], &se_shift, &se_mask)) + return &enc110->base; + + BREAK_TO_DEBUGGER(); + dm_free(enc110); + return NULL; +} + +#define SRII(reg_name, block, id)\ + .reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +static const struct dce_hwseq_registers hwseq_reg = { + HWSEQ_DCE112_REG_LIST() +}; + +static const struct dce_hwseq_shift hwseq_shift = { + HWSEQ_DCE12_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_hwseq_mask hwseq_mask = { + HWSEQ_DCE12_MASK_SH_LIST(_MASK) +}; + +static struct dce_hwseq *dce120_hwseq_create( + struct dc_context *ctx) +{ + struct dce_hwseq *hws = dm_alloc(sizeof(struct dce_hwseq)); + + if (hws) { + hws->ctx = ctx; + hws->regs = &hwseq_reg; + hws->shifts = &hwseq_shift; + hws->masks = &hwseq_mask; + } + return hws; +} + +static const struct resource_create_funcs res_create_funcs = { + .read_dce_straps = read_dce_straps, + .create_audio = create_audio, + .create_stream_encoder = dce120_stream_encoder_create, + .create_hwseq = dce120_hwseq_create, +}; + +#define mi_inst_regs(id) { MI_DCE12_REG_LIST(id) } +static const struct dce_mem_input_registers mi_regs[] = { + mi_inst_regs(0), + mi_inst_regs(1), + mi_inst_regs(2), + mi_inst_regs(3), + mi_inst_regs(4), + mi_inst_regs(5), +}; + +static const struct dce_mem_input_shift mi_shifts = { + MI_DCE12_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_mem_input_mask mi_masks = { + MI_DCE12_MASK_SH_LIST(_MASK) +}; + +static struct mem_input *dce120_mem_input_create( + struct dc_context *ctx, + uint32_t inst, + const struct dce110_mem_input_reg_offsets *offset) +{ + struct dce110_mem_input *mem_input110 = + dm_alloc(sizeof(struct dce110_mem_input)); + + if (!mem_input110) + return NULL; + + if (dce120_mem_input_construct(mem_input110, ctx, inst, offset)) { + struct mem_input *mi = &mem_input110->base; + + mi->regs = &mi_regs[inst]; + mi->shifts = &mi_shifts; + mi->masks = &mi_masks; + return mi; + } + + BREAK_TO_DEBUGGER(); + dm_free(mem_input110); + return NULL; +} + +static struct transform *dce120_transform_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dce_transform *transform = + dm_alloc(sizeof(struct dce_transform)); + + if (!transform) + return NULL; + + if (dce_transform_construct(transform, ctx, inst, + &xfm_regs[inst], &xfm_shift, &xfm_mask)) { + transform->lb_memory_size = 0x1404; /*5124*/ + return &transform->base; + } + + BREAK_TO_DEBUGGER(); + dm_free(transform); + return NULL; +} + +static void dce120_destroy_resource_pool(struct resource_pool **pool) +{ + struct dce110_resource_pool *dce110_pool = TO_DCE110_RES_POOL(*pool); + + destruct(dce110_pool); + dm_free(dce110_pool); + *pool = NULL; +} + +static const struct resource_funcs dce120_res_pool_funcs = { + .destroy = dce120_destroy_resource_pool, + .link_enc_create = dce120_link_encoder_create, + .validate_with_context = dce112_validate_with_context, + .validate_guaranteed = dce112_validate_guaranteed, + .validate_bandwidth = dce112_validate_bandwidth +}; + +static void bw_calcs_data_update_from_pplib(struct core_dc *dc) +{ + struct dm_pp_clock_levels_with_latency eng_clks = {0}; + struct dm_pp_clock_levels_with_latency mem_clks = {0}; + struct dm_pp_wm_sets_with_clock_ranges clk_ranges = {0}; + int i; + unsigned int clk; + unsigned int latency; + + /*do system clock*/ + if (!dm_pp_get_clock_levels_by_type_with_latency( + dc->ctx, + DM_PP_CLOCK_TYPE_ENGINE_CLK, + &eng_clks) || eng_clks.num_levels == 0) { + + eng_clks.num_levels = 8; + clk = 300000; + + for (i = 0; i < eng_clks.num_levels; i++) { + eng_clks.data[i].clocks_in_khz = clk; + clk += 100000; + } + } + + /* convert all the clock fro kHz to fix point mHz TODO: wloop data */ + dc->bw_vbios.high_sclk = bw_frc_to_fixed( + eng_clks.data[eng_clks.num_levels-1].clocks_in_khz, 1000); + dc->bw_vbios.mid1_sclk = bw_frc_to_fixed( + eng_clks.data[eng_clks.num_levels/8].clocks_in_khz, 1000); + dc->bw_vbios.mid2_sclk = bw_frc_to_fixed( + eng_clks.data[eng_clks.num_levels*2/8].clocks_in_khz, 1000); + dc->bw_vbios.mid3_sclk = bw_frc_to_fixed( + eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz, 1000); + dc->bw_vbios.mid4_sclk = bw_frc_to_fixed( + eng_clks.data[eng_clks.num_levels*4/8].clocks_in_khz, 1000); + dc->bw_vbios.mid5_sclk = bw_frc_to_fixed( + eng_clks.data[eng_clks.num_levels*5/8].clocks_in_khz, 1000); + dc->bw_vbios.mid6_sclk = bw_frc_to_fixed( + eng_clks.data[eng_clks.num_levels*6/8].clocks_in_khz, 1000); + dc->bw_vbios.low_sclk = bw_frc_to_fixed( + eng_clks.data[0].clocks_in_khz, 1000); + + /*do memory clock*/ + if (!dm_pp_get_clock_levels_by_type_with_latency( + dc->ctx, + DM_PP_CLOCK_TYPE_MEMORY_CLK, + &mem_clks) || mem_clks.num_levels == 0) { + + mem_clks.num_levels = 3; + clk = 250000; + latency = 45; + + for (i = 0; i < eng_clks.num_levels; i++) { + mem_clks.data[i].clocks_in_khz = clk; + mem_clks.data[i].latency_in_us = latency; + clk += 500000; + latency -= 5; + } + + } + + /* we don't need to call PPLIB for validation clock since they + * also give us the highest sclk and highest mclk (UMA clock). + * ALSO always convert UMA clock (from PPLIB) to YCLK (HW formula): + * YCLK = UMACLK*m_memoryTypeMultiplier + */ + dc->bw_vbios.low_yclk = bw_frc_to_fixed( + mem_clks.data[0].clocks_in_khz * MEMORY_TYPE_MULTIPLIER, 1000); + dc->bw_vbios.mid_yclk = bw_frc_to_fixed( + mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz * MEMORY_TYPE_MULTIPLIER, + 1000); + dc->bw_vbios.high_yclk = bw_frc_to_fixed( + mem_clks.data[mem_clks.num_levels-1].clocks_in_khz * MEMORY_TYPE_MULTIPLIER, + 1000); + + /* Now notify PPLib/SMU about which Watermarks sets they should select + * depending on DPM state they are in. And update BW MGR GFX Engine and + * Memory clock member variables for Watermarks calculations for each + * Watermark Set + */ + clk_ranges.num_wm_sets = 4; + clk_ranges.wm_clk_ranges[0].wm_set_id = WM_SET_A; + clk_ranges.wm_clk_ranges[0].wm_min_eng_clk_in_khz = + eng_clks.data[0].clocks_in_khz; + clk_ranges.wm_clk_ranges[0].wm_max_eng_clk_in_khz = + eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz - 1; + clk_ranges.wm_clk_ranges[0].wm_min_memg_clk_in_khz = + mem_clks.data[0].clocks_in_khz; + clk_ranges.wm_clk_ranges[0].wm_max_mem_clk_in_khz = + mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz - 1; + + clk_ranges.wm_clk_ranges[1].wm_set_id = WM_SET_B; + clk_ranges.wm_clk_ranges[1].wm_min_eng_clk_in_khz = + eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz; + /* 5 GHz instead of data[7].clockInKHz to cover Overdrive */ + clk_ranges.wm_clk_ranges[1].wm_max_eng_clk_in_khz = 5000000; + clk_ranges.wm_clk_ranges[1].wm_min_memg_clk_in_khz = + mem_clks.data[0].clocks_in_khz; + clk_ranges.wm_clk_ranges[1].wm_max_mem_clk_in_khz = + mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz - 1; + + clk_ranges.wm_clk_ranges[2].wm_set_id = WM_SET_C; + clk_ranges.wm_clk_ranges[2].wm_min_eng_clk_in_khz = + eng_clks.data[0].clocks_in_khz; + clk_ranges.wm_clk_ranges[2].wm_max_eng_clk_in_khz = + eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz - 1; + clk_ranges.wm_clk_ranges[2].wm_min_memg_clk_in_khz = + mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz; + /* 5 GHz instead of data[2].clockInKHz to cover Overdrive */ + clk_ranges.wm_clk_ranges[2].wm_max_mem_clk_in_khz = 5000000; + + clk_ranges.wm_clk_ranges[3].wm_set_id = WM_SET_D; + clk_ranges.wm_clk_ranges[3].wm_min_eng_clk_in_khz = + eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz; + /* 5 GHz instead of data[7].clockInKHz to cover Overdrive */ + clk_ranges.wm_clk_ranges[3].wm_max_eng_clk_in_khz = 5000000; + clk_ranges.wm_clk_ranges[3].wm_min_memg_clk_in_khz = + mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz; + /* 5 GHz instead of data[2].clockInKHz to cover Overdrive */ + clk_ranges.wm_clk_ranges[3].wm_max_mem_clk_in_khz = 5000000; + + /* Notify PP Lib/SMU which Watermarks to use for which clock ranges */ + dm_pp_notify_wm_clock_changes(dc->ctx, &clk_ranges); +} + +static bool construct( + uint8_t num_virtual_links, + struct core_dc *dc, + struct dce110_resource_pool *pool) +{ + unsigned int i; + struct dc_context *ctx = dc->ctx; + + ctx->dc_bios->regs = &bios_regs; + + pool->base.res_cap = &res_cap; + pool->base.funcs = &dce120_res_pool_funcs; + + /* TODO: Fill more data from GreenlandAsicCapability.cpp */ + pool->base.pipe_count = 6; + pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + + dc->public.caps.max_downscale_ratio = 200; + dc->public.caps.i2c_speed_in_khz = 100; + dc->public.caps.max_cursor_size = 128; + dc->public.debug = debug_defaults; + + /************************************************* + * Create resources * + *************************************************/ + + pool->base.clock_sources[DCE120_CLK_SRC_PLL0] = + dce120_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL0, + &clk_src_regs[0], false); + pool->base.clock_sources[DCE120_CLK_SRC_PLL1] = + dce120_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL1, + &clk_src_regs[1], false); + pool->base.clock_sources[DCE120_CLK_SRC_PLL2] = + dce120_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL2, + &clk_src_regs[2], false); + pool->base.clock_sources[DCE120_CLK_SRC_PLL3] = + dce120_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL3, + &clk_src_regs[3], false); + pool->base.clock_sources[DCE120_CLK_SRC_PLL4] = + dce120_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL4, + &clk_src_regs[4], false); + pool->base.clock_sources[DCE120_CLK_SRC_PLL5] = + dce120_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL5, + &clk_src_regs[5], false); + pool->base.clk_src_count = DCE120_CLK_SRC_TOTAL; + + pool->base.dp_clock_source = + dce120_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_ID_DP_DTO, + &clk_src_regs[0], true); + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] == NULL) { + dm_error("DC: failed to create clock sources!\n"); + BREAK_TO_DEBUGGER(); + goto clk_src_create_fail; + } + } + + pool->base.display_clock = dce120_disp_clk_create(ctx, + &disp_clk_regs, + &disp_clk_shift, + &disp_clk_mask); + if (pool->base.display_clock == NULL) { + dm_error("DC: failed to create display clock!\n"); + BREAK_TO_DEBUGGER(); + goto disp_clk_create_fail; + } + + pool->base.dmcu = dce_dmcu_create(ctx, + &dmcu_regs, + &dmcu_shift, + &dmcu_mask); + if (pool->base.dmcu == NULL) { + dm_error("DC: failed to create dmcu!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + pool->base.abm = dce_abm_create(ctx, + &abm_regs, + &abm_shift, + &abm_mask); + if (pool->base.abm == NULL) { + dm_error("DC: failed to create abm!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + { + #if defined(CONFIG_DRM_AMD_DC_DCE12_0) + struct irq_service_init_data init_data; + init_data.ctx = dc->ctx; + pool->base.irqs = dal_irq_service_dce120_create(&init_data); + if (!pool->base.irqs) + goto irqs_create_fail; + #endif + } + + for (i = 0; i < pool->base.pipe_count; i++) { + pool->base.timing_generators[i] = + dce120_timing_generator_create( + ctx, + i, + &dce120_tg_offsets[i]); + if (pool->base.timing_generators[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create tg!\n"); + goto controller_create_fail; + } + + pool->base.mis[i] = dce120_mem_input_create(ctx, + i, &dce120_mi_reg_offsets[i]); + + if (pool->base.mis[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create memory input!\n"); + goto controller_create_fail; + } + + pool->base.ipps[i] = dce120_ipp_create(ctx, i, + &dce120_ipp_reg_offsets[i]); + if (pool->base.ipps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create input pixel processor!\n"); + goto controller_create_fail; + } + + pool->base.transforms[i] = dce120_transform_create(ctx, i); + if (pool->base.transforms[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create transform!\n"); + goto res_create_fail; + } + + pool->base.opps[i] = dce120_opp_create( + ctx, + i); + if (pool->base.opps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create output pixel processor!\n"); + } + } + + if (!resource_construct(num_virtual_links, dc, &pool->base, + &res_create_funcs)) + goto res_create_fail; + + /* Create hardware sequencer */ + if (!dce120_hw_sequencer_create(dc)) + goto controller_create_fail; + + bw_calcs_init(&dc->bw_dceip, &dc->bw_vbios, dc->ctx->asic_id); + + bw_calcs_data_update_from_pplib(dc); + + return true; + +irqs_create_fail: +controller_create_fail: +disp_clk_create_fail: +clk_src_create_fail: +res_create_fail: + + destruct(pool); + + return false; +} + +struct resource_pool *dce120_create_resource_pool( + uint8_t num_virtual_links, + struct core_dc *dc) +{ + struct dce110_resource_pool *pool = + dm_alloc(sizeof(struct dce110_resource_pool)); + + if (!pool) + return NULL; + + if (construct(num_virtual_links, dc, pool)) + return &pool->base; + + BREAK_TO_DEBUGGER(); + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.h b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.h new file mode 100644 index 000000000000..038c78dcc247 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.h @@ -0,0 +1,39 @@ +/* +* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_RESOURCE_DCE120_H__ +#define __DC_RESOURCE_DCE120_H__ + +#include "core_types.h" + +struct core_dc; +struct resource_pool; + +struct resource_pool *dce120_create_resource_pool( + uint8_t num_virtual_links, + struct core_dc *dc); + +#endif /* __DC_RESOURCE_DCE120_H__ */ + diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c new file mode 100644 index 000000000000..d7e787b591a0 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c @@ -0,0 +1,1109 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "vega10/DC/dce_12_0_offset.h" +#include "vega10/DC/dce_12_0_sh_mask.h" +#include "vega10/soc15ip.h" + +#include "dc_types.h" +#include "dc_bios_types.h" + +#include "include/grph_object_id.h" +#include "include/logger_interface.h" +#include "dce120_timing_generator.h" + +#include "timing_generator.h" + +#define CRTC_REG_UPDATE_N(reg_name, n, ...) \ + generic_reg_update_soc15(tg110->base.ctx, tg110->offsets.crtc, reg_name, n, __VA_ARGS__) + +#define CRTC_REG_SET_N(reg_name, n, ...) \ + generic_reg_set_soc15(tg110->base.ctx, tg110->offsets.crtc, reg_name, n, __VA_ARGS__) + +#define CRTC_REG_UPDATE(reg, field, val) \ + CRTC_REG_UPDATE_N(reg, 1, FD(reg##__##field), val) + +#define CRTC_REG_UPDATE_2(reg, field1, val1, field2, val2) \ + CRTC_REG_UPDATE_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) + +#define CRTC_REG_UPDATE_3(reg, field1, val1, field2, val2, field3, val3) \ + CRTC_REG_UPDATE_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3) + +#define CRTC_REG_UPDATE_4(reg, field1, val1, field2, val2, field3, val3, field4, val4) \ + CRTC_REG_UPDATE_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3, FD(reg##__##field4), val4) + +#define CRTC_REG_UPDATE_5(reg, field1, val1, field2, val2, field3, val3, field4, val4, field5, val5) \ + CRTC_REG_UPDATE_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3, FD(reg##__##field4), val4, FD(reg##__##field5), val5) + +#define CRTC_REG_SET(reg, field, val) \ + CRTC_REG_SET_N(reg, 1, FD(reg##__##field), val) + +#define CRTC_REG_SET_2(reg, field1, val1, field2, val2) \ + CRTC_REG_SET_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) + +#define CRTC_REG_SET_3(reg, field1, val1, field2, val2, field3, val3) \ + CRTC_REG_SET_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3) + +/** + ***************************************************************************** + * Function: is_in_vertical_blank + * + * @brief + * check the current status of CRTC to check if we are in Vertical Blank + * regioneased" state + * + * @return + * true if currently in blank region, false otherwise + * + ***************************************************************************** + */ +static bool dce120_timing_generator_is_in_vertical_blank( + struct timing_generator *tg) +{ + uint32_t field = 0; + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t value = dm_read_reg_soc15( + tg->ctx, + mmCRTC0_CRTC_STATUS, + tg110->offsets.crtc); + + field = get_reg_field_value(value, CRTC0_CRTC_STATUS, CRTC_V_BLANK); + return field == 1; +} + + +/* determine if given timing can be supported by TG */ +bool dce120_timing_generator_validate_timing( + struct timing_generator *tg, + const struct dc_crtc_timing *timing, + enum signal_type signal) +{ + uint32_t interlace_factor = timing->flags.INTERLACE ? 2 : 1; + uint32_t v_blank = + (timing->v_total - timing->v_addressable - + timing->v_border_top - timing->v_border_bottom) * + interlace_factor; + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + if (!dce110_timing_generator_validate_timing( + tg, + timing, + signal)) + return false; + + + if (v_blank < tg110->min_v_blank || + timing->h_sync_width < tg110->min_h_sync_width || + timing->v_sync_width < tg110->min_v_sync_width) + return false; + + return true; +} + +bool dce120_tg_validate_timing(struct timing_generator *tg, + const struct dc_crtc_timing *timing) +{ + return dce120_timing_generator_validate_timing(tg, timing, SIGNAL_TYPE_NONE); +} + +/******** HW programming ************/ +/* Disable/Enable Timing Generator */ +bool dce120_timing_generator_enable_crtc(struct timing_generator *tg) +{ + enum bp_result result; + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + /* Set MASTER_UPDATE_MODE to 0 + * This is needed for DRR, and also suggested to be default value by Syed.*/ + + CRTC_REG_UPDATE(CRTC0_CRTC_MASTER_UPDATE_MODE, + MASTER_UPDATE_MODE, 0); + + CRTC_REG_UPDATE(CRTC0_CRTC_MASTER_UPDATE_LOCK, + UNDERFLOW_UPDATE_LOCK, 0); + + /* TODO API for AtomFirmware didn't change*/ + result = tg->bp->funcs->enable_crtc(tg->bp, tg110->controller_id, true); + + return result == BP_RESULT_OK; +} + +void dce120_timing_generator_set_early_control( + struct timing_generator *tg, + uint32_t early_cntl) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + CRTC_REG_UPDATE(CRTC0_CRTC_CONTROL, + CRTC_HBLANK_EARLY_CONTROL, early_cntl); +} + +/**************** TG current status ******************/ + +/* return the current frame counter. Used by Linux kernel DRM */ +uint32_t dce120_timing_generator_get_vblank_counter( + struct timing_generator *tg) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t value = dm_read_reg_soc15( + tg->ctx, + mmCRTC0_CRTC_STATUS_FRAME_COUNT, + tg110->offsets.crtc); + uint32_t field = get_reg_field_value( + value, CRTC0_CRTC_STATUS_FRAME_COUNT, CRTC_FRAME_COUNT); + + return field; +} + +/* Get current H and V position */ +void dce120_timing_generator_get_crtc_positions( + struct timing_generator *tg, + int32_t *h_position, + int32_t *v_position) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t value = dm_read_reg_soc15( + tg->ctx, + mmCRTC0_CRTC_STATUS_POSITION, + tg110->offsets.crtc); + + *h_position = get_reg_field_value( + value, CRTC0_CRTC_STATUS_POSITION, CRTC_HORZ_COUNT); + + *v_position = get_reg_field_value( + value, CRTC0_CRTC_STATUS_POSITION, CRTC_VERT_COUNT); +} + +/* wait until TG is in beginning of vertical blank region */ +void dce120_timing_generator_wait_for_vblank(struct timing_generator *tg) +{ + /* We want to catch beginning of VBlank here, so if the first try are + * in VBlank, we might be very close to Active, in this case wait for + * another frame + */ + while (dce120_timing_generator_is_in_vertical_blank(tg)) { + if (!tg->funcs->is_counter_moving(tg)) { + /* error - no point to wait if counter is not moving */ + break; + } + } + + while (!dce120_timing_generator_is_in_vertical_blank(tg)) { + if (!tg->funcs->is_counter_moving(tg)) { + /* error - no point to wait if counter is not moving */ + break; + } + } +} + +/* wait until TG is in beginning of active region */ +void dce120_timing_generator_wait_for_vactive(struct timing_generator *tg) +{ + while (dce120_timing_generator_is_in_vertical_blank(tg)) { + if (!tg->funcs->is_counter_moving(tg)) { + /* error - no point to wait if counter is not moving */ + break; + } + } +} + +/*********** Timing Generator Synchronization routines ****/ + +/* Setups Global Swap Lock group, TimingServer or TimingClient*/ +void dce120_timing_generator_setup_global_swap_lock( + struct timing_generator *tg, + const struct dcp_gsl_params *gsl_params) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t value_crtc_vtotal = + dm_read_reg_soc15(tg->ctx, + mmCRTC0_CRTC_V_TOTAL, + tg110->offsets.crtc); + /* Checkpoint relative to end of frame */ + uint32_t check_point = + get_reg_field_value(value_crtc_vtotal, + CRTC0_CRTC_V_TOTAL, + CRTC_V_TOTAL); + + + dm_write_reg_soc15(tg->ctx, mmCRTC0_CRTC_GSL_WINDOW, tg110->offsets.crtc, 0); + + CRTC_REG_UPDATE_N(DCP0_DCP_GSL_CONTROL, 6, + /* This pipe will belong to GSL Group zero. */ + FD(DCP0_DCP_GSL_CONTROL__DCP_GSL0_EN), 1, + FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_MASTER_EN), gsl_params->gsl_master == tg->inst, + FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_HSYNC_FLIP_FORCE_DELAY), HFLIP_READY_DELAY, + /* Keep signal low (pending high) during 6 lines. + * Also defines minimum interval before re-checking signal. */ + FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_HSYNC_FLIP_CHECK_DELAY), HFLIP_CHECK_DELAY, + /* DCP_GSL_PURPOSE_SURFACE_FLIP */ + FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_SYNC_SOURCE), 0, + FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_DELAY_SURFACE_UPDATE_PENDING), 1); + + CRTC_REG_SET_2( + CRTC0_CRTC_GSL_CONTROL, + CRTC_GSL_CHECK_LINE_NUM, check_point - FLIP_READY_BACK_LOOKUP, + CRTC_GSL_FORCE_DELAY, VFLIP_READY_DELAY); +} + +/* Clear all the register writes done by setup_global_swap_lock */ +void dce120_timing_generator_tear_down_global_swap_lock( + struct timing_generator *tg) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + /* Settig HW default values from reg specs */ + CRTC_REG_SET_N(DCP0_DCP_GSL_CONTROL, 6, + FD(DCP0_DCP_GSL_CONTROL__DCP_GSL0_EN), 0, + FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_MASTER_EN), 0, + FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_HSYNC_FLIP_FORCE_DELAY), HFLIP_READY_DELAY, + FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_HSYNC_FLIP_CHECK_DELAY), HFLIP_CHECK_DELAY, + /* DCP_GSL_PURPOSE_SURFACE_FLIP */ + FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_SYNC_SOURCE), 0, + FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_DELAY_SURFACE_UPDATE_PENDING), 0); + + CRTC_REG_SET_2( + CRTC0_CRTC_GSL_CONTROL, + CRTC_GSL_CHECK_LINE_NUM, 0, + CRTC_GSL_FORCE_DELAY, 0x2); /*TODO Why this value here ?*/ +} + +/* Reset slave controllers on master VSync */ +void dce120_timing_generator_enable_reset_trigger( + struct timing_generator *tg, + int source) +{ + enum trigger_source_select trig_src_select = TRIGGER_SOURCE_SELECT_LOGIC_ZERO; + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t rising_edge = 0; + uint32_t falling_edge = 0; + /* Setup trigger edge */ + uint32_t pol_value = dm_read_reg_soc15( + tg->ctx, + mmCRTC0_CRTC_V_SYNC_A_CNTL, + tg110->offsets.crtc); + + /* Register spec has reversed definition: + * 0 for positive, 1 for negative */ + if (get_reg_field_value(pol_value, + CRTC0_CRTC_V_SYNC_A_CNTL, + CRTC_V_SYNC_A_POL) == 0) { + rising_edge = 1; + } else { + falling_edge = 1; + } + + /* TODO What about other sources ?*/ + trig_src_select = TRIGGER_SOURCE_SELECT_GSL_GROUP0; + + CRTC_REG_UPDATE_N(CRTC0_CRTC_TRIGB_CNTL, 7, + FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_SOURCE_SELECT), trig_src_select, + FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_POLARITY_SELECT), TRIGGER_POLARITY_SELECT_LOGIC_ZERO, + FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_RISING_EDGE_DETECT_CNTL), rising_edge, + FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_FALLING_EDGE_DETECT_CNTL), falling_edge, + /* send every signal */ + FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_FREQUENCY_SELECT), 0, + /* no delay */ + FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_DELAY), 0, + /* clear trigger status */ + FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_CLEAR), 1); + + CRTC_REG_UPDATE_3( + CRTC0_CRTC_FORCE_COUNT_NOW_CNTL, + CRTC_FORCE_COUNT_NOW_MODE, 2, + CRTC_FORCE_COUNT_NOW_TRIG_SEL, 1, + CRTC_FORCE_COUNT_NOW_CLEAR, 1); +} + +/* disabling trigger-reset */ +void dce120_timing_generator_disable_reset_trigger( + struct timing_generator *tg) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + CRTC_REG_UPDATE_2( + CRTC0_CRTC_FORCE_COUNT_NOW_CNTL, + CRTC_FORCE_COUNT_NOW_MODE, 0, + CRTC_FORCE_COUNT_NOW_CLEAR, 1); + + CRTC_REG_UPDATE_3( + CRTC0_CRTC_TRIGB_CNTL, + CRTC_TRIGB_SOURCE_SELECT, TRIGGER_SOURCE_SELECT_LOGIC_ZERO, + CRTC_TRIGB_POLARITY_SELECT, TRIGGER_POLARITY_SELECT_LOGIC_ZERO, + /* clear trigger status */ + CRTC_TRIGB_CLEAR, 1); + +} + +/* Checks whether CRTC triggered reset occurred */ +bool dce120_timing_generator_did_triggered_reset_occur( + struct timing_generator *tg) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t value = dm_read_reg_soc15( + tg->ctx, + mmCRTC0_CRTC_FORCE_COUNT_NOW_CNTL, + tg110->offsets.crtc); + + return get_reg_field_value(value, + CRTC0_CRTC_FORCE_COUNT_NOW_CNTL, + CRTC_FORCE_COUNT_NOW_OCCURRED) != 0; +} + + +/******** Stuff to move to other virtual HW objects *****************/ +/* Move to enable accelerated mode */ +void dce120_timing_generator_disable_vga(struct timing_generator *tg) +{ + uint32_t addr = 0; + uint32_t offset = 0; + uint32_t value = 0; + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + switch (tg110->controller_id) { + case CONTROLLER_ID_D0: + addr = mmD1VGA_CONTROL; + offset = 0; + break; + case CONTROLLER_ID_D1: + addr = mmD2VGA_CONTROL; + offset = mmD2VGA_CONTROL - mmD1VGA_CONTROL; + break; + case CONTROLLER_ID_D2: + addr = mmD3VGA_CONTROL; + offset = mmD3VGA_CONTROL - mmD1VGA_CONTROL; + break; + case CONTROLLER_ID_D3: + addr = mmD4VGA_CONTROL; + offset = mmD4VGA_CONTROL - mmD1VGA_CONTROL; + break; + case CONTROLLER_ID_D4: + addr = mmD1VGA_CONTROL; + offset = mmD1VGA_CONTROL - mmD1VGA_CONTROL; + break; + case CONTROLLER_ID_D5: + addr = mmD6VGA_CONTROL; + offset = mmD6VGA_CONTROL - mmD1VGA_CONTROL; + break; + default: + break; + } + + value = dm_read_reg_soc15(tg->ctx, mmD1VGA_CONTROL, offset); + + set_reg_field_value(value, 0, D1VGA_CONTROL, D1VGA_MODE_ENABLE); + set_reg_field_value(value, 0, D1VGA_CONTROL, D1VGA_TIMING_SELECT); + set_reg_field_value( + value, 0, D1VGA_CONTROL, D1VGA_SYNC_POLARITY_SELECT); + set_reg_field_value(value, 0, D1VGA_CONTROL, D1VGA_OVERSCAN_COLOR_EN); + + dm_write_reg_soc15(tg->ctx, mmD1VGA_CONTROL, offset, value); +} +/* TODO: Should we move it to transform */ +/* Fully program CRTC timing in timing generator */ +void dce120_timing_generator_program_blanking( + struct timing_generator *tg, + const struct dc_crtc_timing *timing) +{ + uint32_t tmp1 = 0; + uint32_t tmp2 = 0; + uint32_t vsync_offset = timing->v_border_bottom + + timing->v_front_porch; + uint32_t v_sync_start = timing->v_addressable + vsync_offset; + + uint32_t hsync_offset = timing->h_border_right + + timing->h_front_porch; + uint32_t h_sync_start = timing->h_addressable + hsync_offset; + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + CRTC_REG_UPDATE( + CRTC0_CRTC_H_TOTAL, + CRTC_H_TOTAL, + timing->h_total - 1); + + CRTC_REG_UPDATE( + CRTC0_CRTC_V_TOTAL, + CRTC_V_TOTAL, + timing->v_total - 1); + + tmp1 = timing->h_total - + (h_sync_start + timing->h_border_left); + tmp2 = tmp1 + timing->h_addressable + + timing->h_border_left + timing->h_border_right; + + CRTC_REG_UPDATE_2( + CRTC0_CRTC_H_BLANK_START_END, + CRTC_H_BLANK_END, tmp1, + CRTC_H_BLANK_START, tmp2); + + tmp1 = timing->v_total - (v_sync_start + timing->v_border_top); + tmp2 = tmp1 + timing->v_addressable + timing->v_border_top + + timing->v_border_bottom; + + CRTC_REG_UPDATE_2( + CRTC0_CRTC_V_BLANK_START_END, + CRTC_V_BLANK_END, tmp1, + CRTC_V_BLANK_START, tmp2); +} + +/* TODO: Should we move it to opp? */ +/* Combine with below and move YUV/RGB color conversion to SW layer */ +void dce120_timing_generator_program_blank_color( + struct timing_generator *tg, + const struct tg_color *black_color) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + CRTC_REG_UPDATE_3( + CRTC0_CRTC_BLACK_COLOR, + CRTC_BLACK_COLOR_B_CB, black_color->color_b_cb, + CRTC_BLACK_COLOR_G_Y, black_color->color_g_y, + CRTC_BLACK_COLOR_R_CR, black_color->color_r_cr); +} +/* Combine with above and move YUV/RGB color conversion to SW layer */ +void dce120_timing_generator_set_overscan_color_black( + struct timing_generator *tg, + const struct tg_color *color) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t value = 0; + CRTC_REG_SET_3( + CRTC0_CRTC_OVERSCAN_COLOR, + CRTC_OVERSCAN_COLOR_BLUE, color->color_b_cb, + CRTC_OVERSCAN_COLOR_GREEN, color->color_g_y, + CRTC_OVERSCAN_COLOR_RED, color->color_r_cr); + + value = dm_read_reg_soc15( + tg->ctx, + mmCRTC0_CRTC_OVERSCAN_COLOR, + tg110->offsets.crtc); + + dm_write_reg_soc15( + tg->ctx, + mmCRTC0_CRTC_BLACK_COLOR, + tg110->offsets.crtc, + value); + + /* This is desirable to have a constant DAC output voltage during the + * blank time that is higher than the 0 volt reference level that the + * DAC outputs when the NBLANK signal + * is asserted low, such as for output to an analog TV. */ + dm_write_reg_soc15( + tg->ctx, + mmCRTC0_CRTC_BLANK_DATA_COLOR, + tg110->offsets.crtc, + value); + + /* TO DO we have to program EXT registers and we need to know LB DATA + * format because it is used when more 10 , i.e. 12 bits per color + * + * m_mmDxCRTC_OVERSCAN_COLOR_EXT + * m_mmDxCRTC_BLACK_COLOR_EXT + * m_mmDxCRTC_BLANK_DATA_COLOR_EXT + */ +} + +void dce120_timing_generator_set_drr( + struct timing_generator *tg, + const struct drr_params *params) +{ + + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + if (params != NULL && + params->vertical_total_max > 0 && + params->vertical_total_min > 0) { + + CRTC_REG_UPDATE( + CRTC0_CRTC_V_TOTAL_MIN, + CRTC_V_TOTAL_MIN, params->vertical_total_min - 1); + CRTC_REG_UPDATE( + CRTC0_CRTC_V_TOTAL_MAX, + CRTC_V_TOTAL_MAX, params->vertical_total_max - 1); + CRTC_REG_SET_N(CRTC0_CRTC_V_TOTAL_CONTROL, 6, + FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MIN_SEL), 1, + FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MAX_SEL), 1, + FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_FORCE_LOCK_ON_EVENT), 0, + FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_FORCE_LOCK_TO_MASTER_VSYNC), 0, + FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_SET_V_TOTAL_MIN_MASK_EN), 0, + FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_SET_V_TOTAL_MIN_MASK), 0); + CRTC_REG_UPDATE( + CRTC0_CRTC_STATIC_SCREEN_CONTROL, + CRTC_STATIC_SCREEN_EVENT_MASK, + 0x180); + + } else { + CRTC_REG_UPDATE( + CRTC0_CRTC_V_TOTAL_MIN, + CRTC_V_TOTAL_MIN, 0); + CRTC_REG_UPDATE( + CRTC0_CRTC_V_TOTAL_MAX, + CRTC_V_TOTAL_MAX, 0); + CRTC_REG_SET_N(CRTC0_CRTC_V_TOTAL_CONTROL, 5, + FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MIN_SEL), 0, + FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MAX_SEL), 0, + FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_FORCE_LOCK_ON_EVENT), 0, + FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_FORCE_LOCK_TO_MASTER_VSYNC), 0, + FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_SET_V_TOTAL_MIN_MASK), 0); + CRTC_REG_UPDATE( + CRTC0_CRTC_STATIC_SCREEN_CONTROL, + CRTC_STATIC_SCREEN_EVENT_MASK, + 0); + } +} + +uint32_t dce120_timing_generator_get_crtc_scanoutpos( + struct timing_generator *tg, + uint32_t *vbl, + uint32_t *position) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + *vbl = dm_read_reg_soc15( + tg->ctx, + mmCRTC0_CRTC_V_BLANK_START_END, + tg110->offsets.crtc); + + *position = dm_read_reg_soc15( + tg->ctx, + mmCRTC0_CRTC_STATUS_POSITION, + tg110->offsets.crtc); + + return 0; +} + +void dce120_timing_generator_enable_advanced_request( + struct timing_generator *tg, + bool enable, + const struct dc_crtc_timing *timing) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t v_sync_width_and_b_porch = + timing->v_total - timing->v_addressable - + timing->v_border_bottom - timing->v_front_porch; + uint32_t value = dm_read_reg_soc15( + tg->ctx, + mmCRTC0_CRTC_START_LINE_CONTROL, + tg110->offsets.crtc); + + + if (enable) { + set_reg_field_value( + value, + 0, + CRTC0_CRTC_START_LINE_CONTROL, + CRTC_LEGACY_REQUESTOR_EN); + } else { + set_reg_field_value( + value, + 1, + CRTC0_CRTC_START_LINE_CONTROL, + CRTC_LEGACY_REQUESTOR_EN); + } + + /* Program advanced line position acc.to the best case from fetching data perspective to hide MC latency + * and prefilling Line Buffer in V Blank (to 10 lines as LB can store max 10 lines) + */ + if (v_sync_width_and_b_porch > 10) + set_reg_field_value( + value, + 10, + CRTC0_CRTC_START_LINE_CONTROL, + CRTC_ADVANCED_START_LINE_POSITION); + else + set_reg_field_value( + value, + v_sync_width_and_b_porch, + CRTC0_CRTC_START_LINE_CONTROL, + CRTC_ADVANCED_START_LINE_POSITION); + + dm_write_reg_soc15(tg->ctx, + mmCRTC0_CRTC_START_LINE_CONTROL, + tg110->offsets.crtc, + value); +} + +void dce120_tg_program_blank_color(struct timing_generator *tg, + const struct tg_color *black_color) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t value = 0; + + CRTC_REG_UPDATE_3( + CRTC0_CRTC_BLACK_COLOR, + CRTC_BLACK_COLOR_B_CB, black_color->color_b_cb, + CRTC_BLACK_COLOR_G_Y, black_color->color_g_y, + CRTC_BLACK_COLOR_R_CR, black_color->color_r_cr); + + value = dm_read_reg_soc15( + tg->ctx, + mmCRTC0_CRTC_BLACK_COLOR, + tg110->offsets.crtc); + dm_write_reg_soc15( + tg->ctx, + mmCRTC0_CRTC_BLANK_DATA_COLOR, + tg110->offsets.crtc, + value); +} + +void dce120_tg_set_overscan_color(struct timing_generator *tg, + const struct tg_color *overscan_color) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + CRTC_REG_SET_3( + CRTC0_CRTC_OVERSCAN_COLOR, + CRTC_OVERSCAN_COLOR_BLUE, overscan_color->color_b_cb, + CRTC_OVERSCAN_COLOR_GREEN, overscan_color->color_g_y, + CRTC_OVERSCAN_COLOR_RED, overscan_color->color_r_cr); +} + +void dce120_tg_program_timing(struct timing_generator *tg, + const struct dc_crtc_timing *timing, + bool use_vbios) +{ + if (use_vbios) + dce110_timing_generator_program_timing_generator(tg, timing); + else + dce120_timing_generator_program_blanking(tg, timing); +} + +bool dce120_tg_is_blanked(struct timing_generator *tg) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t value = dm_read_reg_soc15( + tg->ctx, + mmCRTC0_CRTC_BLANK_CONTROL, + tg110->offsets.crtc); + + if ( + get_reg_field_value( + value, + CRTC0_CRTC_BLANK_CONTROL, + CRTC_BLANK_DATA_EN) == 1 && + get_reg_field_value( + value, + CRTC0_CRTC_BLANK_CONTROL, + CRTC_CURRENT_BLANK_STATE) == 1) + return true; + + return false; +} + +void dce120_tg_set_blank(struct timing_generator *tg, + bool enable_blanking) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + CRTC_REG_SET( + CRTC0_CRTC_DOUBLE_BUFFER_CONTROL, + CRTC_BLANK_DATA_DOUBLE_BUFFER_EN, 0); + + if (enable_blanking) { + CRTC_REG_SET( + CRTC0_CRTC_BLANK_CONTROL, + CRTC_BLANK_DATA_EN, 1); + + } else + dm_write_reg_soc15( + tg->ctx, + mmCRTC0_CRTC_BLANK_CONTROL, + tg110->offsets.crtc, + 0); +} + +bool dce120_tg_validate_timing(struct timing_generator *tg, + const struct dc_crtc_timing *timing); + +void dce120_tg_wait_for_state(struct timing_generator *tg, + enum crtc_state state) +{ + switch (state) { + case CRTC_STATE_VBLANK: + dce120_timing_generator_wait_for_vblank(tg); + break; + + case CRTC_STATE_VACTIVE: + dce120_timing_generator_wait_for_vactive(tg); + break; + + default: + break; + } +} + +void dce120_tg_set_colors(struct timing_generator *tg, + const struct tg_color *blank_color, + const struct tg_color *overscan_color) +{ + if (blank_color != NULL) + dce120_tg_program_blank_color(tg, blank_color); + + if (overscan_color != NULL) + dce120_tg_set_overscan_color(tg, overscan_color); +} + +static void dce120_timing_generator_set_static_screen_control( + struct timing_generator *tg, + uint32_t value) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + CRTC_REG_UPDATE_2(CRTC0_CRTC_STATIC_SCREEN_CONTROL, + CRTC_STATIC_SCREEN_EVENT_MASK, value, + CRTC_STATIC_SCREEN_FRAME_COUNT, 2); +} + +void dce120_timing_generator_set_test_pattern( + struct timing_generator *tg, + /* TODO: replace 'controller_dp_test_pattern' by 'test_pattern_mode' + * because this is not DP-specific (which is probably somewhere in DP + * encoder) */ + enum controller_dp_test_pattern test_pattern, + enum dc_color_depth color_depth) +{ + struct dc_context *ctx = tg->ctx; + uint32_t value; + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + enum test_pattern_color_format bit_depth; + enum test_pattern_dyn_range dyn_range; + enum test_pattern_mode mode; + /* color ramp generator mixes 16-bits color */ + uint32_t src_bpc = 16; + /* requested bpc */ + uint32_t dst_bpc; + uint32_t index; + /* RGB values of the color bars. + * Produce two RGB colors: RGB0 - white (all Fs) + * and RGB1 - black (all 0s) + * (three RGB components for two colors) + */ + uint16_t src_color[6] = {0xFFFF, 0xFFFF, 0xFFFF, 0x0000, + 0x0000, 0x0000}; + /* dest color (converted to the specified color format) */ + uint16_t dst_color[6]; + uint32_t inc_base; + + /* translate to bit depth */ + switch (color_depth) { + case COLOR_DEPTH_666: + bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_6; + break; + case COLOR_DEPTH_888: + bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8; + break; + case COLOR_DEPTH_101010: + bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_10; + break; + case COLOR_DEPTH_121212: + bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_12; + break; + default: + bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8; + break; + } + + switch (test_pattern) { + case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES: + case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA: + { + dyn_range = (test_pattern == + CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA ? + TEST_PATTERN_DYN_RANGE_CEA : + TEST_PATTERN_DYN_RANGE_VESA); + mode = TEST_PATTERN_MODE_COLORSQUARES_RGB; + + CRTC_REG_UPDATE_2(CRTC0_CRTC_TEST_PATTERN_PARAMETERS, + CRTC_TEST_PATTERN_VRES, 6, + CRTC_TEST_PATTERN_HRES, 6); + + CRTC_REG_UPDATE_4(CRTC0_CRTC_TEST_PATTERN_CONTROL, + CRTC_TEST_PATTERN_EN, 1, + CRTC_TEST_PATTERN_MODE, mode, + CRTC_TEST_PATTERN_DYNAMIC_RANGE, dyn_range, + CRTC_TEST_PATTERN_COLOR_FORMAT, bit_depth); + } + break; + + case CONTROLLER_DP_TEST_PATTERN_VERTICALBARS: + case CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS: + { + mode = (test_pattern == + CONTROLLER_DP_TEST_PATTERN_VERTICALBARS ? + TEST_PATTERN_MODE_VERTICALBARS : + TEST_PATTERN_MODE_HORIZONTALBARS); + + switch (bit_depth) { + case TEST_PATTERN_COLOR_FORMAT_BPC_6: + dst_bpc = 6; + break; + case TEST_PATTERN_COLOR_FORMAT_BPC_8: + dst_bpc = 8; + break; + case TEST_PATTERN_COLOR_FORMAT_BPC_10: + dst_bpc = 10; + break; + default: + dst_bpc = 8; + break; + } + + /* adjust color to the required colorFormat */ + for (index = 0; index < 6; index++) { + /* dst = 2^dstBpc * src / 2^srcBpc = src >> + * (srcBpc - dstBpc); + */ + dst_color[index] = + src_color[index] >> (src_bpc - dst_bpc); + /* CRTC_TEST_PATTERN_DATA has 16 bits, + * lowest 6 are hardwired to ZERO + * color bits should be left aligned aligned to MSB + * XXXXXXXXXX000000 for 10 bit, + * XXXXXXXX00000000 for 8 bit and XXXXXX0000000000 for 6 + */ + dst_color[index] <<= (16 - dst_bpc); + } + + dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_PARAMETERS, tg110->offsets.crtc, 0); + + /* We have to write the mask before data, similar to pipeline. + * For example, for 8 bpc, if we want RGB0 to be magenta, + * and RGB1 to be cyan, + * we need to make 7 writes: + * MASK DATA + * 000001 00000000 00000000 set mask to R0 + * 000010 11111111 00000000 R0 255, 0xFF00, set mask to G0 + * 000100 00000000 00000000 G0 0, 0x0000, set mask to B0 + * 001000 11111111 00000000 B0 255, 0xFF00, set mask to R1 + * 010000 00000000 00000000 R1 0, 0x0000, set mask to G1 + * 100000 11111111 00000000 G1 255, 0xFF00, set mask to B1 + * 100000 11111111 00000000 B1 255, 0xFF00 + * + * we will make a loop of 6 in which we prepare the mask, + * then write, then prepare the color for next write. + * first iteration will write mask only, + * but each next iteration color prepared in + * previous iteration will be written within new mask, + * the last component will written separately, + * mask is not changing between 6th and 7th write + * and color will be prepared by last iteration + */ + + /* write color, color values mask in CRTC_TEST_PATTERN_MASK + * is B1, G1, R1, B0, G0, R0 + */ + value = 0; + for (index = 0; index < 6; index++) { + /* prepare color mask, first write PATTERN_DATA + * will have all zeros + */ + set_reg_field_value( + value, + (1 << index), + CRTC0_CRTC_TEST_PATTERN_COLOR, + CRTC_TEST_PATTERN_MASK); + /* write color component */ + dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_COLOR, tg110->offsets.crtc, value); + /* prepare next color component, + * will be written in the next iteration + */ + set_reg_field_value( + value, + dst_color[index], + CRTC0_CRTC_TEST_PATTERN_COLOR, + CRTC_TEST_PATTERN_DATA); + } + /* write last color component, + * it's been already prepared in the loop + */ + dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_COLOR, tg110->offsets.crtc, value); + + /* enable test pattern */ + CRTC_REG_UPDATE_4(CRTC0_CRTC_TEST_PATTERN_CONTROL, + CRTC_TEST_PATTERN_EN, 1, + CRTC_TEST_PATTERN_MODE, mode, + CRTC_TEST_PATTERN_DYNAMIC_RANGE, 0, + CRTC_TEST_PATTERN_COLOR_FORMAT, bit_depth); + } + break; + + case CONTROLLER_DP_TEST_PATTERN_COLORRAMP: + { + mode = (bit_depth == + TEST_PATTERN_COLOR_FORMAT_BPC_10 ? + TEST_PATTERN_MODE_DUALRAMP_RGB : + TEST_PATTERN_MODE_SINGLERAMP_RGB); + + switch (bit_depth) { + case TEST_PATTERN_COLOR_FORMAT_BPC_6: + dst_bpc = 6; + break; + case TEST_PATTERN_COLOR_FORMAT_BPC_8: + dst_bpc = 8; + break; + case TEST_PATTERN_COLOR_FORMAT_BPC_10: + dst_bpc = 10; + break; + default: + dst_bpc = 8; + break; + } + + /* increment for the first ramp for one color gradation + * 1 gradation for 6-bit color is 2^10 + * gradations in 16-bit color + */ + inc_base = (src_bpc - dst_bpc); + + switch (bit_depth) { + case TEST_PATTERN_COLOR_FORMAT_BPC_6: + { + CRTC_REG_UPDATE_5(CRTC0_CRTC_TEST_PATTERN_PARAMETERS, + CRTC_TEST_PATTERN_INC0, inc_base, + CRTC_TEST_PATTERN_INC1, 0, + CRTC_TEST_PATTERN_HRES, 6, + CRTC_TEST_PATTERN_VRES, 6, + CRTC_TEST_PATTERN_RAMP0_OFFSET, 0); + } + break; + case TEST_PATTERN_COLOR_FORMAT_BPC_8: + { + CRTC_REG_UPDATE_5(CRTC0_CRTC_TEST_PATTERN_PARAMETERS, + CRTC_TEST_PATTERN_INC0, inc_base, + CRTC_TEST_PATTERN_INC1, 0, + CRTC_TEST_PATTERN_HRES, 8, + CRTC_TEST_PATTERN_VRES, 6, + CRTC_TEST_PATTERN_RAMP0_OFFSET, 0); + } + break; + case TEST_PATTERN_COLOR_FORMAT_BPC_10: + { + CRTC_REG_UPDATE_5(CRTC0_CRTC_TEST_PATTERN_PARAMETERS, + CRTC_TEST_PATTERN_INC0, inc_base, + CRTC_TEST_PATTERN_INC1, inc_base + 2, + CRTC_TEST_PATTERN_HRES, 8, + CRTC_TEST_PATTERN_VRES, 5, + CRTC_TEST_PATTERN_RAMP0_OFFSET, 384 << 6); + } + break; + default: + break; + } + + dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_COLOR, tg110->offsets.crtc, 0); + + /* enable test pattern */ + dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_CONTROL, tg110->offsets.crtc, 0); + + CRTC_REG_UPDATE_4(CRTC0_CRTC_TEST_PATTERN_CONTROL, + CRTC_TEST_PATTERN_EN, 1, + CRTC_TEST_PATTERN_MODE, mode, + CRTC_TEST_PATTERN_DYNAMIC_RANGE, 0, + CRTC_TEST_PATTERN_COLOR_FORMAT, bit_depth); + } + break; + case CONTROLLER_DP_TEST_PATTERN_VIDEOMODE: + { + value = 0; + dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_CONTROL, tg110->offsets.crtc, value); + dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_COLOR, tg110->offsets.crtc, value); + dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_PARAMETERS, tg110->offsets.crtc, value); + } + break; + default: + break; + } +} + +static struct timing_generator_funcs dce120_tg_funcs = { + .validate_timing = dce120_tg_validate_timing, + .program_timing = dce120_tg_program_timing, + .enable_crtc = dce120_timing_generator_enable_crtc, + .disable_crtc = dce110_timing_generator_disable_crtc, + /* used by enable_timing_synchronization. Not need for FPGA */ + .is_counter_moving = dce110_timing_generator_is_counter_moving, + /* never be called */ + .get_position = dce120_timing_generator_get_crtc_positions, + .get_frame_count = dce120_timing_generator_get_vblank_counter, + .get_scanoutpos = dce120_timing_generator_get_crtc_scanoutpos, + .set_early_control = dce120_timing_generator_set_early_control, + /* used by enable_timing_synchronization. Not need for FPGA */ + .wait_for_state = dce120_tg_wait_for_state, + .set_blank = dce120_tg_set_blank, + .is_blanked = dce120_tg_is_blanked, + /* never be called */ + .set_colors = dce120_tg_set_colors, + .set_overscan_blank_color = dce120_timing_generator_set_overscan_color_black, + .set_blank_color = dce120_timing_generator_program_blank_color, + .disable_vga = dce120_timing_generator_disable_vga, + .did_triggered_reset_occur = dce120_timing_generator_did_triggered_reset_occur, + .setup_global_swap_lock = dce120_timing_generator_setup_global_swap_lock, + .enable_reset_trigger = dce120_timing_generator_enable_reset_trigger, + .disable_reset_trigger = dce120_timing_generator_disable_reset_trigger, + .tear_down_global_swap_lock = dce120_timing_generator_tear_down_global_swap_lock, + .enable_advanced_request = dce120_timing_generator_enable_advanced_request, + .set_drr = dce120_timing_generator_set_drr, + .set_static_screen_control = dce120_timing_generator_set_static_screen_control, + .set_test_pattern = dce120_timing_generator_set_test_pattern +}; + + +bool dce120_timing_generator_construct( + struct dce110_timing_generator *tg110, + struct dc_context *ctx, + uint32_t instance, + const struct dce110_timing_generator_offsets *offsets) +{ + if (!tg110) + return false; + + tg110->controller_id = CONTROLLER_ID_D0 + instance; + tg110->base.inst = instance; + + tg110->offsets = *offsets; + + tg110->base.funcs = &dce120_tg_funcs; + + tg110->base.ctx = ctx; + tg110->base.bp = ctx->dc_bios; + + tg110->max_h_total = CRTC0_CRTC_H_TOTAL__CRTC_H_TOTAL_MASK + 1; + tg110->max_v_total = CRTC0_CRTC_V_TOTAL__CRTC_V_TOTAL_MASK + 1; + + /*//CRTC requires a minimum HBLANK = 32 pixels and o + * Minimum HSYNC = 8 pixels*/ + tg110->min_h_blank = 32; + /*DCE12_CRTC_Block_ARch.doc*/ + tg110->min_h_front_porch = 0; + tg110->min_h_back_porch = 0; + + tg110->min_h_sync_width = 8; + tg110->min_v_sync_width = 1; + tg110->min_v_blank = 3; + + return true; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.h new file mode 100644 index 000000000000..243c0a3493da --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.h @@ -0,0 +1,41 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_TIMING_GENERATOR_DCE120_H__ +#define __DC_TIMING_GENERATOR_DCE120_H__ + +#include "timing_generator.h" +#include "../include/grph_object_id.h" +#include "../include/hw_sequencer_types.h" +#include "dce110/dce110_timing_generator.h" + + +bool dce120_timing_generator_construct( + struct dce110_timing_generator *tg110, + struct dc_context *ctx, + uint32_t instance, + const struct dce110_timing_generator_offsets *offsets); + +#endif /* __DC_TIMING_GENERATOR_DCE120_H__ */ -- cgit From 2c8ad2d5a20c8b7425b547dd4a969ffecad29b39 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 15 Jun 2017 16:20:24 -0400 Subject: drm/amd/display: Enable DCE12 support This wires DCE12 support into DC and enables it. Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 4 + drivers/gpu/drm/amd/display/Kconfig | 7 + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 23 +++- .../drm/amd/display/amdgpu_dm/amdgpu_dm_services.c | 10 ++ .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 22 ++- drivers/gpu/drm/amd/display/dc/Makefile | 4 + drivers/gpu/drm/amd/display/dc/bios/Makefile | 8 ++ .../amd/display/dc/bios/bios_parser_interface.c | 14 ++ drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c | 117 ++++++++++++++++ drivers/gpu/drm/amd/display/dc/core/dc.c | 29 ++++ drivers/gpu/drm/amd/display/dc/core/dc_debug.c | 11 ++ drivers/gpu/drm/amd/display/dc/core/dc_link.c | 19 +++ drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 14 ++ drivers/gpu/drm/amd/display/dc/dc.h | 27 ++++ drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 46 +++++++ .../gpu/drm/amd/display/dc/dce/dce_clock_source.c | 6 + drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c | 149 +++++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h | 20 +++ drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h | 8 ++ .../gpu/drm/amd/display/dc/dce/dce_link_encoder.h | 14 ++ drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c | 35 +++++ drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h | 34 +++++ drivers/gpu/drm/amd/display/dc/dce/dce_opp.h | 72 ++++++++++ .../drm/amd/display/dc/dce/dce_stream_encoder.h | 100 ++++++++++++++ drivers/gpu/drm/amd/display/dc/dce/dce_transform.h | 68 ++++++++++ .../amd/display/dc/dce110/dce110_hw_sequencer.c | 53 +++++++- .../drm/amd/display/dc/dce110/dce110_mem_input.c | 3 + .../display/dc/dce110/dce110_timing_generator.h | 3 + drivers/gpu/drm/amd/display/dc/dce120/Makefile | 12 ++ .../gpu/drm/amd/display/dc/dce80/dce80_mem_input.c | 3 + drivers/gpu/drm/amd/display/dc/dm_services.h | 89 ++++++++++++ drivers/gpu/drm/amd/display/dc/dm_services_types.h | 27 ++++ drivers/gpu/drm/amd/display/dc/gpio/Makefile | 11 ++ drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c | 9 ++ drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c | 9 +- drivers/gpu/drm/amd/display/dc/i2caux/Makefile | 11 ++ drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c | 8 ++ .../gpu/drm/amd/display/dc/inc/bandwidth_calcs.h | 3 + .../gpu/drm/amd/display/dc/inc/hw/display_clock.h | 23 ++++ drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h | 4 + drivers/gpu/drm/amd/display/dc/irq/Makefile | 12 ++ drivers/gpu/drm/amd/display/dc/irq/irq_service.c | 3 + drivers/gpu/drm/amd/display/include/dal_asic_id.h | 4 + drivers/gpu/drm/amd/display/include/dal_types.h | 3 + 44 files changed, 1143 insertions(+), 8 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/dc/dce120/Makefile (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 2efb486e283d..96955c9b4cdf 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1984,8 +1984,12 @@ bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type) case CHIP_STONEY: case CHIP_POLARIS11: case CHIP_POLARIS10: + case CHIP_POLARIS12: case CHIP_TONGA: case CHIP_FIJI: +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + case CHIP_VEGA10: +#endif #if defined(CONFIG_DRM_AMD_DC_PRE_VEGA) return amdgpu_dc != 0; #else diff --git a/drivers/gpu/drm/amd/display/Kconfig b/drivers/gpu/drm/amd/display/Kconfig index 47c8e2940a91..32826a0eafe7 100644 --- a/drivers/gpu/drm/amd/display/Kconfig +++ b/drivers/gpu/drm/amd/display/Kconfig @@ -17,6 +17,13 @@ config DRM_AMD_DC_PRE_VEGA by default. This includes Polaris, Carrizo, Tonga, Bonaire, and Hawaii. +config DRM_AMD_DC_DCE12_0 + bool "Vega10 family" + depends on DRM_AMD_DC + help + Choose this option if you want to have + VG family for display engine. + config DEBUG_KERNEL_DC bool "Enable kgdb break in DC" depends on DRM_AMD_DC 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 a69ce27b8ed6..9157772a0af3 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -888,6 +888,10 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev) struct dc_interrupt_params int_params = {0}; int r; int i; + unsigned client_id = AMDGPU_IH_CLIENTID_LEGACY; + + if (adev->asic_type == CHIP_VEGA10) + client_id = AMDGPU_IH_CLIENTID_DCE; int_params.requested_polarity = INTERRUPT_POLARITY_DEFAULT; int_params.current_polarity = INTERRUPT_POLARITY_DEFAULT; @@ -904,7 +908,7 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev) /* Use VBLANK interrupt */ for (i = 1; i <= adev->mode_info.num_crtc; i++) { - r = amdgpu_irq_add_id(adev, AMDGPU_IH_CLIENTID_LEGACY, i, &adev->crtc_irq); + r = amdgpu_irq_add_id(adev, client_id, i, &adev->crtc_irq); if (r) { DRM_ERROR("Failed to add crtc irq id!\n"); @@ -927,7 +931,7 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev) /* Use GRPH_PFLIP interrupt */ for (i = VISLANDS30_IV_SRCID_D1_GRPH_PFLIP; i <= VISLANDS30_IV_SRCID_D6_GRPH_PFLIP; i += 2) { - r = amdgpu_irq_add_id(adev, AMDGPU_IH_CLIENTID_LEGACY, i, &adev->pageflip_irq); + r = amdgpu_irq_add_id(adev, client_id, i, &adev->pageflip_irq); if (r) { DRM_ERROR("Failed to add page flip irq id!\n"); return r; @@ -948,8 +952,8 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev) } /* HPD */ - r = amdgpu_irq_add_id(adev, AMDGPU_IH_CLIENTID_LEGACY, VISLANDS30_IV_SRCID_HOTPLUG_DETECT_A, - &adev->hpd_irq); + r = amdgpu_irq_add_id(adev, client_id, + VISLANDS30_IV_SRCID_HOTPLUG_DETECT_A, &adev->hpd_irq); if (r) { DRM_ERROR("Failed to add hpd irq id!\n"); return r; @@ -1119,6 +1123,9 @@ int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) case CHIP_POLARIS11: case CHIP_POLARIS10: case CHIP_POLARIS12: +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + case CHIP_VEGA10: +#endif if (dce110_register_irq_handlers(dm->adev)) { DRM_ERROR("DM: Failed to initialize IRQ\n"); return -1; @@ -1312,6 +1319,7 @@ static const struct amdgpu_display_funcs dm_display_funcs = { }; + #if defined(CONFIG_DEBUG_KERNEL_DC) static ssize_t s3_debug_store( @@ -1384,6 +1392,13 @@ static int dm_early_init(void *handle) adev->mode_info.num_hpd = 6; adev->mode_info.num_dig = 6; break; +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + case CHIP_VEGA10: + adev->mode_info.num_crtc = 6; + adev->mode_info.num_hpd = 6; + adev->mode_info.num_dig = 6; + break; +#endif default: DRM_ERROR("Usupported ASIC type: 0x%X\n", adev->asic_type); return -EINVAL; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c index 1ddc56cfbdc4..df53092abc39 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c @@ -402,6 +402,16 @@ bool dm_pp_notify_wm_clock_changes( return false; } +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +bool dm_pp_notify_wm_clock_changes_soc15( + const struct dc_context *ctx, + struct dm_pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges) +{ + /* TODO: to be implemented */ + return false; +} +#endif + bool dm_pp_apply_power_level_change_request( const struct dc_context *ctx, struct dm_pp_power_level_change_request *level_change_req) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 098a801ae745..01aaf968854d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -494,7 +494,7 @@ static void fill_plane_attributes_from_fb( memset(&surface->tiling_info, 0, sizeof(surface->tiling_info)); - /* Fill GFX8 params */ + /* Fill GFX params */ if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE) == DC_ARRAY_2D_TILED_THIN1) { unsigned bankw, bankh, mtaspect, tile_split, num_banks; @@ -523,6 +523,26 @@ static void fill_plane_attributes_from_fb( surface->tiling_info.gfx8.pipe_config = AMDGPU_TILING_GET(tiling_flags, PIPE_CONFIG); +#if defined (CONFIG_DRM_AMD_DC_DCE12_0) + if (adev->asic_type == CHIP_VEGA10) { + /* Fill GFX9 params */ + surface->tiling_info.gfx9.num_pipes = + adev->gfx.config.gb_addr_config_fields.num_pipes; + surface->tiling_info.gfx9.num_banks = + adev->gfx.config.gb_addr_config_fields.num_banks; + surface->tiling_info.gfx9.pipe_interleave = + adev->gfx.config.gb_addr_config_fields.pipe_interleave_size; + surface->tiling_info.gfx9.num_shader_engines = + adev->gfx.config.gb_addr_config_fields.num_se; + surface->tiling_info.gfx9.max_compressed_frags = + adev->gfx.config.gb_addr_config_fields.max_compress_frags; + surface->tiling_info.gfx9.swizzle = + AMDGPU_TILING_GET(tiling_flags, SWIZZLE_MODE); + surface->tiling_info.gfx9.shaderEnable = 1; + } +#endif + + surface->plane_size.grph.surface_size.x = 0; surface->plane_size.grph.surface_size.y = 0; surface->plane_size.grph.surface_size.width = fb->width; diff --git a/drivers/gpu/drm/amd/display/dc/Makefile b/drivers/gpu/drm/amd/display/dc/Makefile index 2df163bc83e9..a580cab6bf56 100644 --- a/drivers/gpu/drm/amd/display/dc/Makefile +++ b/drivers/gpu/drm/amd/display/dc/Makefile @@ -4,6 +4,10 @@ DC_LIBS = basics bios calcs dce gpio i2caux irq virtual +ifdef CONFIG_DRM_AMD_DC_DCE12_0 +DC_LIBS += dce120 +endif + DC_LIBS += dce112 DC_LIBS += dce110 DC_LIBS += dce100 diff --git a/drivers/gpu/drm/amd/display/dc/bios/Makefile b/drivers/gpu/drm/amd/display/dc/bios/Makefile index 876614d37412..770248429a81 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/Makefile +++ b/drivers/gpu/drm/amd/display/dc/bios/Makefile @@ -4,6 +4,10 @@ BIOS = bios_parser.o bios_parser_interface.o bios_parser_helper.o command_table.o command_table_helper.o +ifdef CONFIG_DRM_AMD_DC_DCE12_0 +BIOS += command_table2.o command_table_helper2.o bios_parser2.o +endif + AMD_DAL_BIOS = $(addprefix $(AMDDALPATH)/dc/bios/,$(BIOS)) AMD_DISPLAY_FILES += $(AMD_DAL_BIOS) @@ -21,3 +25,7 @@ AMD_DISPLAY_FILES += $(AMDDALPATH)/dc/bios/dce80/command_table_helper_dce80.o AMD_DISPLAY_FILES += $(AMDDALPATH)/dc/bios/dce110/command_table_helper_dce110.o AMD_DISPLAY_FILES += $(AMDDALPATH)/dc/bios/dce112/command_table_helper_dce112.o + +ifdef CONFIG_DRM_AMD_DC_DCE12_0 +AMD_DISPLAY_FILES += $(AMDDALPATH)/dc/bios/dce112/command_table_helper2_dce112.o +endif diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_interface.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_interface.c index 42272c35df2d..7fe2a791ef42 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_interface.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_interface.c @@ -29,6 +29,10 @@ #include "bios_parser_interface.h" #include "bios_parser.h" +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +#include "bios_parser2.h" +#endif + struct dc_bios *dal_bios_parser_create( struct bp_init_data *init, @@ -36,7 +40,17 @@ struct dc_bios *dal_bios_parser_create( { struct dc_bios *bios = NULL; +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + bios = firmware_parser_create(init, dce_version); + + if (bios == NULL) + /* TODO: remove dce_version from bios_parser. + * cannot remove today because dal enum to bp enum translation is dce specific + */ + bios = bios_parser_create(init, dce_version); +#else bios = bios_parser_create(init, dce_version); +#endif return bios; } diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c index ab8d1e931846..aa98762346d2 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c @@ -50,6 +50,11 @@ static enum bw_calcs_version bw_calcs_version_from_asic_id(struct hw_asic_id asi return BW_CALCS_VERSION_POLARIS11; return BW_CALCS_VERSION_INVALID; +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + case FAMILY_AI: + return BW_CALCS_VERSION_VEGA10; +#endif + default: return BW_CALCS_VERSION_INVALID; } @@ -2430,6 +2435,118 @@ void bw_calcs_init(struct bw_calcs_dceip *bw_dceip, dceip.scatter_gather_pte_request_rows_in_tiling_mode = 2; dceip.mcifwr_all_surfaces_burst_time = bw_int_to_fixed(0); break; +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + case BW_CALCS_VERSION_VEGA10: + vbios.memory_type = bw_def_hbm; + vbios.dram_channel_width_in_bits = 128; + vbios.number_of_dram_channels = asic_id.vram_width / vbios.dram_channel_width_in_bits; + vbios.number_of_dram_banks = 16; + vbios.high_yclk = bw_int_to_fixed(2400); + vbios.mid_yclk = bw_int_to_fixed(1700); + vbios.low_yclk = bw_int_to_fixed(1000); + vbios.low_sclk = bw_int_to_fixed(300); + vbios.mid1_sclk = bw_int_to_fixed(350); + vbios.mid2_sclk = bw_int_to_fixed(400); + vbios.mid3_sclk = bw_int_to_fixed(500); + vbios.mid4_sclk = bw_int_to_fixed(600); + vbios.mid5_sclk = bw_int_to_fixed(700); + vbios.mid6_sclk = bw_int_to_fixed(760); + vbios.high_sclk = bw_int_to_fixed(776); + vbios.low_voltage_max_dispclk = bw_int_to_fixed(460); + vbios.mid_voltage_max_dispclk = bw_int_to_fixed(670); + vbios.high_voltage_max_dispclk = bw_int_to_fixed(1133); + vbios.low_voltage_max_phyclk = bw_int_to_fixed(540); + vbios.mid_voltage_max_phyclk = bw_int_to_fixed(810); + vbios.high_voltage_max_phyclk = bw_int_to_fixed(810); + vbios.data_return_bus_width = bw_int_to_fixed(32); + vbios.trc = bw_int_to_fixed(48); + vbios.dmifmc_urgent_latency = bw_int_to_fixed(3); + vbios.stutter_self_refresh_exit_latency = bw_frc_to_fixed(75, 10); + vbios.stutter_self_refresh_entry_latency = bw_frc_to_fixed(19, 10); + vbios.nbp_state_change_latency = bw_int_to_fixed(39); + vbios.mcifwrmc_urgent_latency = bw_int_to_fixed(10); + vbios.scatter_gather_enable = false; + vbios.down_spread_percentage = bw_frc_to_fixed(5, 10); + vbios.cursor_width = 32; + vbios.average_compression_rate = 4; + vbios.number_of_request_slots_gmc_reserves_for_dmif_per_channel = 8; + vbios.blackout_duration = bw_int_to_fixed(0); /* us */ + vbios.maximum_blackout_recovery_time = bw_int_to_fixed(0); + + dceip.large_cursor = false; + dceip.dmif_request_buffer_size = bw_int_to_fixed(2304); + dceip.dmif_pipe_en_fbc_chunk_tracker = true; + dceip.cursor_max_outstanding_group_num = 1; + dceip.lines_interleaved_into_lb = 2; + dceip.chunk_width = 256; + dceip.number_of_graphics_pipes = 6; + dceip.number_of_underlay_pipes = 0; + dceip.low_power_tiling_mode = 0; + dceip.display_write_back_supported = true; + dceip.argb_compression_support = true; + dceip.underlay_vscaler_efficiency6_bit_per_component = + bw_frc_to_fixed(35556, 10000); + dceip.underlay_vscaler_efficiency8_bit_per_component = + bw_frc_to_fixed(34286, 10000); + dceip.underlay_vscaler_efficiency10_bit_per_component = + bw_frc_to_fixed(32, 10); + dceip.underlay_vscaler_efficiency12_bit_per_component = + bw_int_to_fixed(3); + dceip.graphics_vscaler_efficiency6_bit_per_component = + bw_frc_to_fixed(35, 10); + dceip.graphics_vscaler_efficiency8_bit_per_component = + bw_frc_to_fixed(34286, 10000); + dceip.graphics_vscaler_efficiency10_bit_per_component = + bw_frc_to_fixed(32, 10); + dceip.graphics_vscaler_efficiency12_bit_per_component = + bw_int_to_fixed(3); + dceip.alpha_vscaler_efficiency = bw_int_to_fixed(3); + dceip.max_dmif_buffer_allocated = 4; + dceip.graphics_dmif_size = 24576; + dceip.underlay_luma_dmif_size = 19456; + dceip.underlay_chroma_dmif_size = 23552; + dceip.pre_downscaler_enabled = true; + dceip.underlay_downscale_prefetch_enabled = false; + dceip.lb_write_pixels_per_dispclk = bw_int_to_fixed(1); + dceip.lb_size_per_component444 = bw_int_to_fixed(245952); + dceip.graphics_lb_nodownscaling_multi_line_prefetching = true; + dceip.stutter_and_dram_clock_state_change_gated_before_cursor = + bw_int_to_fixed(1); + dceip.underlay420_luma_lb_size_per_component = bw_int_to_fixed( + 82176); + dceip.underlay420_chroma_lb_size_per_component = + bw_int_to_fixed(164352); + dceip.underlay422_lb_size_per_component = bw_int_to_fixed( + 82176); + dceip.cursor_chunk_width = bw_int_to_fixed(64); + dceip.cursor_dcp_buffer_lines = bw_int_to_fixed(4); + dceip.underlay_maximum_width_efficient_for_tiling = + bw_int_to_fixed(1920); + dceip.underlay_maximum_height_efficient_for_tiling = + bw_int_to_fixed(1080); + dceip.peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display = + bw_frc_to_fixed(3, 10); + dceip.peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation = + bw_int_to_fixed(25); + dceip.minimum_outstanding_pte_request_limit = bw_int_to_fixed( + 2); + dceip.maximum_total_outstanding_pte_requests_allowed_by_saw = + bw_int_to_fixed(128); + dceip.limit_excessive_outstanding_dmif_requests = true; + dceip.linear_mode_line_request_alternation_slice = + bw_int_to_fixed(64); + dceip.scatter_gather_lines_of_pte_prefetching_in_linear_mode = + 32; + dceip.display_write_back420_luma_mcifwr_buffer_size = 12288; + dceip.display_write_back420_chroma_mcifwr_buffer_size = 8192; + dceip.request_efficiency = bw_frc_to_fixed(8, 10); + dceip.dispclk_per_request = bw_int_to_fixed(2); + dceip.dispclk_ramping_factor = bw_frc_to_fixed(105, 100); + dceip.display_pipe_throughput_factor = bw_frc_to_fixed(105, 100); + dceip.scatter_gather_pte_request_rows_in_tiling_mode = 2; + dceip.mcifwr_all_surfaces_burst_time = bw_int_to_fixed(0); + break; +#endif default: break; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index b9ca9688f8a3..28ed8eaee1ff 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1815,3 +1815,32 @@ void dc_link_remove_remote_sink(const struct dc_link *link, const struct dc_sink } } +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +bool dc_init_dchub(struct dc *dc, struct dchub_init_data *dh_data) +{ + int i; + struct core_dc *core_dc = DC_TO_CORE(dc); + struct mem_input *mi = NULL; + + for (i = 0; i < core_dc->res_pool->pipe_count; i++) { + if (core_dc->res_pool->mis[i] != NULL) { + mi = core_dc->res_pool->mis[i]; + break; + } + } + if (mi == NULL) { + dm_error("no mem_input!\n"); + return false; + } + + if (mi->funcs->mem_input_update_dchub) + mi->funcs->mem_input_update_dchub(mi, dh_data); + else + ASSERT(mi->funcs->mem_input_update_dchub); + + + return true; + +} +#endif + diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c index 85ddf5fc4291..079558ab81c0 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c @@ -141,6 +141,12 @@ void pre_surface_trace( surface->format, surface->rotation, surface->stereo_format); + +#if defined (CONFIG_DRM_AMD_DC_DCE12_0) + SURFACE_TRACE("surface->tiling_info.gfx9.swizzle = %d;\n", + surface->tiling_info.gfx9.swizzle); +#endif + SURFACE_TRACE("\n"); } SURFACE_TRACE("\n"); @@ -221,6 +227,11 @@ void update_surface_trace( update->plane_info->tiling_info.gfx8.pipe_config, update->plane_info->tiling_info.gfx8.array_mode, update->plane_info->visible); + + #if defined (CONFIG_DRM_AMD_DC_DCE12_0) + SURFACE_TRACE("surface->tiling_info.gfx9.swizzle = %d;\n", + update->plane_info->tiling_info.gfx9.swizzle); + #endif } if (update->scaling_info) { diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 5ca72afe8f6f..f13da7c227f4 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1217,6 +1217,25 @@ static enum dc_status enable_link_dp(struct pipe_ctx *pipe_ctx) pipe_ctx->dis_clk->funcs->set_min_clocks_state( pipe_ctx->dis_clk, DM_PP_CLOCKS_STATE_NOMINAL); } else { +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + uint32_t dp_phyclk_in_khz; + const struct clocks_value clocks_value = + pipe_ctx->dis_clk->cur_clocks_value; + + /* 27mhz = 27000000hz= 27000khz */ + dp_phyclk_in_khz = link_settings.link_rate * 27000; + + if (((clocks_value.max_non_dp_phyclk_in_khz != 0) && + (dp_phyclk_in_khz > clocks_value.max_non_dp_phyclk_in_khz)) || + (dp_phyclk_in_khz > clocks_value.max_dp_phyclk_in_khz)) { + pipe_ctx->dis_clk->funcs->apply_clock_voltage_request( + pipe_ctx->dis_clk, + DM_PP_CLOCK_TYPE_DISPLAYPHYCLK, + dp_phyclk_in_khz, + false, + true); + } +#endif } } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 6119973c7f0a..77ef3304d2bc 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -39,6 +39,9 @@ #include "dce100/dce100_resource.h" #include "dce110/dce110_resource.h" #include "dce112/dce112_resource.h" +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +#include "dce120/dce120_resource.h" +#endif enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id) { @@ -65,6 +68,11 @@ enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id) dc_version = DCE_VERSION_11_2; } break; +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + case FAMILY_AI: + dc_version = DCE_VERSION_12_0; + break; +#endif default: dc_version = DCE_VERSION_UNKNOWN; break; @@ -97,6 +105,12 @@ struct resource_pool *dc_create_resource_pool( res_pool = dce112_create_resource_pool( num_virtual_links, dc); break; +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + case DCE_VERSION_12_0: + res_pool = dce120_create_resource_pool( + num_virtual_links, dc); + break; +#endif default: break; } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index c6c0cf500ae8..bc15065e489b 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -55,6 +55,9 @@ struct dc_caps { struct dc_dcc_surface_param { enum surface_pixel_format format; struct dc_size surface_size; +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + enum swizzle_mode_values swizzle_mode; +#endif enum dc_scan_direction scan; }; @@ -143,6 +146,9 @@ struct dc_debug { bool disable_stutter; bool disable_dcc; bool disable_dfs_bypass; +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + bool disable_pplib_clock_request; +#endif bool disable_clock_gate; bool disable_dmcu; bool force_abm_enable; @@ -157,6 +163,23 @@ struct dc { struct dc_debug debug; }; +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +enum frame_buffer_mode { + FRAME_BUFFER_MODE_LOCAL_ONLY = 0, + FRAME_BUFFER_MODE_ZFB_ONLY, + FRAME_BUFFER_MODE_MIXED_ZFB_AND_LOCAL, +} ; + +struct dchub_init_data { + bool dchub_initialzied; + bool dchub_info_valid; + int64_t zfb_phys_addr_base; + int64_t zfb_mc_base_addr; + uint64_t zfb_size_in_byte; + enum frame_buffer_mode fb_mode; +}; +#endif + struct dc_init_data { struct hw_asic_id asic_id; void *driver; /* ctx */ @@ -177,6 +200,10 @@ struct dc *dc_create(const struct dc_init_data *init_params); void dc_destroy(struct dc **dc); +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +bool dc_init_dchub(struct dc *dc, struct dchub_init_data *dh_data); +#endif + /******************************************************************************* * Surface Interfaces ******************************************************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index 75e16ac70f5f..63813404276d 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -259,6 +259,36 @@ enum tile_mode_values { DC_ADDR_SURF_MICRO_TILING_NON_DISPLAY = 0x1, }; +#if defined (CONFIG_DRM_AMD_DC_DCE12_0) +enum swizzle_mode_values { + DC_SW_LINEAR = 0, + DC_SW_256B_S = 1, + DC_SW_256_D = 2, + DC_SW_256_R = 3, + DC_SW_4KB_S = 5, + DC_SW_4KB_D = 6, + DC_SW_4KB_R = 7, + DC_SW_64KB_S = 9, + DC_SW_64KB_D = 10, + DC_SW_64KB_R = 11, + DC_SW_VAR_S = 13, + DC_SW_VAR_D = 14, + DC_SW_VAR_R = 15, + DC_SW_64KB_S_T = 17, + DC_SW_64KB_D_T = 18, + DC_SW_4KB_S_X = 21, + DC_SW_4KB_D_X = 22, + DC_SW_4KB_R_X = 23, + DC_SW_64KB_S_X = 25, + DC_SW_64KB_D_X = 26, + DC_SW_64KB_R_X = 27, + DC_SW_VAR_S_X = 29, + DC_SW_VAR_D_X = 30, + DC_SW_VAR_R_X = 31, + DC_SW_MAX +}; +#endif + union dc_tiling_info { struct { @@ -323,6 +353,22 @@ union dc_tiling_info { enum array_mode_values array_mode; } gfx8; +#if defined (CONFIG_DRM_AMD_DC_DCE12_0) + struct { + unsigned int num_pipes; + unsigned int num_banks; + unsigned int pipe_interleave; + unsigned int num_shader_engines; + unsigned int num_rb_per_se; + unsigned int max_compressed_frags; + bool shaderEnable; + + enum swizzle_mode_values swizzle; + bool meta_linear; + bool rb_aligned; + bool pipe_aligned; + } gfx9; +#endif }; /* Rotation angle */ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index 1d6a9da45ba6..f53dc157db97 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -585,6 +585,9 @@ static uint32_t dce110_get_pix_clk_dividers( pll_settings, pix_clk_params); break; case DCE_VERSION_11_2: +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + case DCE_VERSION_12_0: +#endif dce112_get_pix_clk_dividers_helper(clk_src, pll_settings, pix_clk_params); break; @@ -868,6 +871,9 @@ static bool dce110_program_pix_clk( break; case DCE_VERSION_11_2: +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + case DCE_VERSION_12_0: +#endif if (clock_source->id != CLOCK_SOURCE_ID_DP_DTO) { bp_pc_params.flags.SET_GENLOCK_REF_DIV_SRC = pll_settings->use_external_clk; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c index ac1febafcaa4..9c743e51c091 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c @@ -80,6 +80,20 @@ static struct state_dependent_clocks dce112_max_clks_by_state[] = { /*ClocksStatePerformance*/ { .display_clk_khz = 1132000, .pixel_clk_khz = 600000 } }; +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +static struct state_dependent_clocks dce120_max_clks_by_state[] = { +/*ClocksStateInvalid - should not be used*/ +{ .display_clk_khz = 0, .pixel_clk_khz = 0 }, +/*ClocksStateUltraLow - currently by HW design team not supposed to be used*/ +{ .display_clk_khz = 0, .pixel_clk_khz = 0 }, +/*ClocksStateLow*/ +{ .display_clk_khz = 460000, .pixel_clk_khz = 400000 }, +/*ClocksStateNominal*/ +{ .display_clk_khz = 670000, .pixel_clk_khz = 600000 }, +/*ClocksStatePerformance*/ +{ .display_clk_khz = 1133000, .pixel_clk_khz = 600000 } }; +#endif + /* Starting point for each divider range.*/ enum dce_divider_range_start { DIVIDER_RANGE_01_START = 200, /* 2.00*/ @@ -483,6 +497,103 @@ static void dce_clock_read_ss_info(struct dce_disp_clk *clk_dce) } } +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +static bool dce_apply_clock_voltage_request( + struct display_clock *clk, + enum dm_pp_clock_type clocks_type, + int clocks_in_khz, + bool pre_mode_set, + bool update_dp_phyclk) +{ + struct dm_pp_clock_for_voltage_req clock_voltage_req = {0}; + + switch (clocks_type) { + case DM_PP_CLOCK_TYPE_DISPLAY_CLK: + case DM_PP_CLOCK_TYPE_PIXELCLK: + case DM_PP_CLOCK_TYPE_DISPLAYPHYCLK: + break; + default: + BREAK_TO_DEBUGGER(); + return false; + } + + clock_voltage_req.clk_type = clocks_type; + clock_voltage_req.clocks_in_khz = clocks_in_khz; + + /* to pplib */ + if (pre_mode_set) { + switch (clocks_type) { + case DM_PP_CLOCK_TYPE_DISPLAY_CLK: + if (clocks_in_khz > clk->cur_clocks_value.dispclk_in_khz) { + dm_pp_apply_clock_for_voltage_request( + clk->ctx, &clock_voltage_req); + clk->cur_clocks_value.dispclk_notify_pplib_done = true; + } else + clk->cur_clocks_value.dispclk_notify_pplib_done = false; + /* no matter incrase or decrase clock, update current clock value */ + clk->cur_clocks_value.dispclk_in_khz = clocks_in_khz; + break; + case DM_PP_CLOCK_TYPE_PIXELCLK: + if (clocks_in_khz > clk->cur_clocks_value.max_pixelclk_in_khz) { + dm_pp_apply_clock_for_voltage_request( + clk->ctx, &clock_voltage_req); + clk->cur_clocks_value.pixelclk_notify_pplib_done = true; + } else + clk->cur_clocks_value.pixelclk_notify_pplib_done = false; + /* no matter incrase or decrase clock, update current clock value */ + clk->cur_clocks_value.max_pixelclk_in_khz = clocks_in_khz; + break; + case DM_PP_CLOCK_TYPE_DISPLAYPHYCLK: + if (clocks_in_khz > clk->cur_clocks_value.max_non_dp_phyclk_in_khz) { + dm_pp_apply_clock_for_voltage_request( + clk->ctx, &clock_voltage_req); + clk->cur_clocks_value.phyclk_notigy_pplib_done = true; + } else + clk->cur_clocks_value.phyclk_notigy_pplib_done = false; + /* no matter incrase or decrase clock, update current clock value */ + clk->cur_clocks_value.max_non_dp_phyclk_in_khz = clocks_in_khz; + break; + default: + ASSERT(0); + break; + } + } else { + switch (clocks_type) { + case DM_PP_CLOCK_TYPE_DISPLAY_CLK: + if (!clk->cur_clocks_value.dispclk_notify_pplib_done) + dm_pp_apply_clock_for_voltage_request( + clk->ctx, &clock_voltage_req); + break; + case DM_PP_CLOCK_TYPE_PIXELCLK: + if (!clk->cur_clocks_value.pixelclk_notify_pplib_done) + dm_pp_apply_clock_for_voltage_request( + clk->ctx, &clock_voltage_req); + break; + case DM_PP_CLOCK_TYPE_DISPLAYPHYCLK: + if (!clk->cur_clocks_value.phyclk_notigy_pplib_done) + dm_pp_apply_clock_for_voltage_request( + clk->ctx, &clock_voltage_req); + break; + default: + ASSERT(0); + break; + } + } + + if (update_dp_phyclk && (clocks_in_khz > + clk->cur_clocks_value.max_dp_phyclk_in_khz)) + clk->cur_clocks_value.max_dp_phyclk_in_khz = clocks_in_khz; + + return true; +} + +static const struct display_clock_funcs dce120_funcs = { + .get_dp_ref_clk_frequency = dce_clocks_get_dp_ref_freq, + .apply_clock_voltage_request = dce_apply_clock_voltage_request, + .set_clock = dce112_set_clock +}; +#endif + static const struct display_clock_funcs dce112_funcs = { .get_dp_ref_clk_frequency = dce_clocks_get_dp_ref_freq, .get_required_clocks_state = dce_get_required_clocks_state, @@ -623,6 +734,44 @@ struct display_clock *dce112_disp_clk_create( return &clk_dce->base; } +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +struct display_clock *dce120_disp_clk_create( + struct dc_context *ctx, + const struct dce_disp_clk_registers *regs, + const struct dce_disp_clk_shift *clk_shift, + const struct dce_disp_clk_mask *clk_mask) +{ + struct dce_disp_clk *clk_dce = dm_alloc(sizeof(*clk_dce)); + struct dm_pp_clock_levels_with_voltage clk_level_info = {0}; + + if (clk_dce == NULL) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + memcpy(clk_dce->max_clks_by_state, + dce120_max_clks_by_state, + sizeof(dce120_max_clks_by_state)); + + dce_disp_clk_construct( + clk_dce, ctx, regs, clk_shift, clk_mask); + + clk_dce->base.funcs = &dce120_funcs; + + /* new in dce120 */ + if (!ctx->dc->debug.disable_pplib_clock_request && + dm_pp_get_clock_levels_by_type_with_voltage( + ctx, DM_PP_CLOCK_TYPE_DISPLAY_CLK, &clk_level_info) + && clk_level_info.num_levels) + clk_dce->max_displ_clk_in_khz = + clk_level_info.data[clk_level_info.num_levels - 1].clocks_in_khz; + else + clk_dce->max_displ_clk_in_khz = 1133000; + + return &clk_dce->base; +} +#endif + void dce_disp_clk_destroy(struct display_clock **disp_clk) { struct dce_disp_clk *clk_dce = TO_DCE_CLOCKS(*disp_clk); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h index 020ab9d5434d..18787f6d4e2a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h @@ -45,6 +45,14 @@ CLK_SF(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, mask_sh), \ CLK_SF(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, mask_sh) +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +#define CLK_COMMON_MASK_SH_LIST_SOC_BASE(mask_sh) \ + CLK_SF(DCCG_DFS_DPREFCLK_CNTL, DPREFCLK_SRC_SEL, mask_sh), \ + CLK_SF(DCCG_DFS_DENTIST_DISPCLK_CNTL, DENTIST_DPREFCLK_WDIVIDER, mask_sh), \ + CLK_SF(DCCG_DFS_MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, mask_sh), \ + CLK_SF(DCCG_DFS_MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, mask_sh) +#endif + #define CLK_REG_FIELD_LIST(type) \ type DPREFCLK_SRC_SEL; \ type DENTIST_DPREFCLK_WDIVIDER; \ @@ -118,6 +126,10 @@ struct dce_disp_clk { int gpu_pll_ss_divider; +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + /* max disp_clk from PPLIB for max validation display clock*/ + int max_displ_clk_in_khz; +#endif }; @@ -139,6 +151,14 @@ struct display_clock *dce112_disp_clk_create( const struct dce_disp_clk_shift *clk_shift, const struct dce_disp_clk_mask *clk_mask); +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +struct display_clock *dce120_disp_clk_create( + struct dc_context *ctx, + const struct dce_disp_clk_registers *regs, + const struct dce_disp_clk_shift *clk_shift, + const struct dce_disp_clk_mask *clk_mask); +#endif + void dce_disp_clk_destroy(struct display_clock **disp_clk); #endif /* _DCE_CLOCKS_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index 70e0652be071..ff7984b08095 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -186,6 +186,14 @@ struct dce_hwseq_registers { HWSEQ_DCE10_MASK_SH_LIST(mask_sh),\ HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, CRTC0_) +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +#define HWSEQ_DCE12_MASK_SH_LIST(mask_sh)\ + HWSEQ_DCEF_MASK_SH_LIST(mask_sh, DCFE0_DCFE_),\ + HWSEQ_BLND_MASK_SH_LIST(mask_sh, BLND0_BLND_),\ + HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_),\ + HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, CRTC0_) +#endif + #define HWSEQ_REG_FIED_LIST(type) \ type DCFE_CLOCK_ENABLE; \ type DCFEV_CLOCK_ENABLE; \ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h index f337d607e36c..f6a1006a6472 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h @@ -31,6 +31,13 @@ #define TO_DCE110_LINK_ENC(link_encoder)\ container_of(link_encoder, struct dce110_link_encoder, base) +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +/* Not found regs in dce120 spec + * BIOS_SCRATCH_2 + * DP_DPHY_INTERNAL_CTRL + */ +#endif + #define AUX_REG_LIST(id)\ SRI(AUX_CONTROL, DP_AUX, id), \ SRI(AUX_DPHY_RX_CONTROL0, DP_AUX, id) @@ -79,6 +86,13 @@ SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ SR(DCI_MEM_PWR_STATUS) +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + #define LE_DCE120_REG_LIST(id)\ + LE_COMMON_REG_LIST_BASE(id), \ + SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ + SR(DCI_MEM_PWR_STATUS) +#endif + #define LE_DCE80_REG_LIST(id)\ SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ LE_COMMON_REG_LIST_BASE(id) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c index e14a21cedfd5..c494f712b5b5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c @@ -187,6 +187,20 @@ static void program_nbp_watermark(struct mem_input *mi, REG_UPDATE(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, NB_PSTATE_CHANGE_WATERMARK, nbp_wm); } +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + if (REG(DPG_PIPE_LOW_POWER_CONTROL)) { + REG_UPDATE(DPG_WATERMARK_MASK_CONTROL, + PSTATE_CHANGE_WATERMARK_MASK, wm_select); + + REG_UPDATE_3(DPG_PIPE_LOW_POWER_CONTROL, + PSTATE_CHANGE_ENABLE, 1, + PSTATE_CHANGE_URGENT_DURING_REQUEST, 1, + PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST, 1); + + REG_UPDATE(DPG_PIPE_LOW_POWER_CONTROL, + PSTATE_CHANGE_WATERMARK, nbp_wm); + } +#endif } static void program_stutter_watermark(struct mem_input *mi, @@ -196,6 +210,12 @@ static void program_stutter_watermark(struct mem_input *mi, REG_UPDATE(DPG_WATERMARK_MASK_CONTROL, STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK, wm_select); +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + if (REG(DPG_PIPE_STUTTER_CONTROL2)) + REG_UPDATE(DPG_PIPE_STUTTER_CONTROL2, + STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark); + else +#endif REG_UPDATE(DPG_PIPE_STUTTER_CONTROL, STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark); } @@ -234,6 +254,21 @@ void dce_mem_input_program_display_marks(struct mem_input *mi, static void program_tiling(struct mem_input *mi, const union dc_tiling_info *info) { +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + if (mi->masks->GRPH_SW_MODE) { /* GFX9 */ + REG_UPDATE_6(GRPH_CONTROL, + GRPH_SW_MODE, info->gfx9.swizzle, + GRPH_NUM_BANKS, log_2(info->gfx9.num_banks), + GRPH_NUM_SHADER_ENGINES, log_2(info->gfx9.num_shader_engines), + GRPH_NUM_PIPES, log_2(info->gfx9.num_pipes), + GRPH_COLOR_EXPANSION_MODE, 1, + GRPH_SE_ENABLE, info->gfx9.shaderEnable); + /* TODO: DCP0_GRPH_CONTROL__GRPH_SE_ENABLE where to get info + GRPH_SE_ENABLE, 1, + GRPH_Z, 0); + */ + } +#endif if (mi->masks->GRPH_ARRAY_MODE) { /* GFX8 */ REG_UPDATE_9(GRPH_CONTROL, GRPH_NUM_BANKS, info->gfx8.num_banks, diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h index ec053c241901..9e18c2a34e85 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h @@ -58,6 +58,15 @@ MI_DCE11_2_REG_LIST(id),\ MI_DCE_PTE_REG_LIST(id) +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +#define MI_DCE12_REG_LIST(id)\ + MI_DCE_BASE_REG_LIST(id),\ + MI_DCE_PTE_REG_LIST(id),\ + SRI(GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT, DCP, id),\ + SRI(DPG_PIPE_STUTTER_CONTROL2, DMIF_PG, id),\ + SRI(DPG_PIPE_LOW_POWER_CONTROL, DMIF_PG, id) +#endif + struct dce_mem_input_registers { /* DCP */ uint32_t GRPH_ENABLE; @@ -163,6 +172,31 @@ struct dce_mem_input_registers { MI_DCE11_2_MASK_SH_LIST(mask_sh),\ MI_DCP_PTE_MASK_SH_LIST(mask_sh, ) +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +#define MI_GFX9_TILE_MASK_SH_LIST(mask_sh, blk)\ + SFB(blk, GRPH_CONTROL, GRPH_SW_MODE, mask_sh),\ + SFB(blk, GRPH_CONTROL, GRPH_SE_ENABLE, mask_sh),\ + SFB(blk, GRPH_CONTROL, GRPH_NUM_SHADER_ENGINES, mask_sh),\ + SFB(blk, GRPH_CONTROL, GRPH_NUM_PIPES, mask_sh),\ + SFB(blk, GRPH_CONTROL, GRPH_COLOR_EXPANSION_MODE, mask_sh) + +#define MI_DCE12_DMIF_PG_MASK_SH_LIST(mask_sh, blk)\ + SFB(blk, DPG_PIPE_STUTTER_CONTROL2, STUTTER_EXIT_SELF_REFRESH_WATERMARK, mask_sh),\ + SFB(blk, DPG_WATERMARK_MASK_CONTROL, PSTATE_CHANGE_WATERMARK_MASK, mask_sh),\ + SFB(blk, DPG_PIPE_LOW_POWER_CONTROL, PSTATE_CHANGE_ENABLE, mask_sh),\ + SFB(blk, DPG_PIPE_LOW_POWER_CONTROL, PSTATE_CHANGE_URGENT_DURING_REQUEST, mask_sh),\ + SFB(blk, DPG_PIPE_LOW_POWER_CONTROL, PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST, mask_sh),\ + SFB(blk, DPG_PIPE_LOW_POWER_CONTROL, PSTATE_CHANGE_WATERMARK, mask_sh) + +#define MI_DCE12_MASK_SH_LIST(mask_sh)\ + MI_DCP_MASK_SH_LIST(mask_sh, DCP0_),\ + MI_DCP_DCE11_MASK_SH_LIST(mask_sh, DCP0_),\ + MI_DCP_PTE_MASK_SH_LIST(mask_sh, DCP0_),\ + MI_DMIF_PG_MASK_SH_LIST(mask_sh, DMIF_PG0_),\ + MI_DCE12_DMIF_PG_MASK_SH_LIST(mask_sh, DMIF_PG0_),\ + MI_GFX9_TILE_MASK_SH_LIST(mask_sh, DCP0_) +#endif + #define MI_REG_FIELD_LIST(type) \ type GRPH_ENABLE; \ type GRPH_X_START; \ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h index a5afc0298d6f..4784ced6fc80 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h @@ -107,6 +107,14 @@ enum dce110_opp_reg_type { SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX, FMT, id), \ SRI(CONTROL, FMT_MEMORY, id) +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +#define OPP_DCE_120_REG_LIST(id) \ + OPP_COMMON_REG_LIST_BASE(id), \ + SRI(DCFE_MEM_PWR_CTRL, DCFE, id), \ + SRI(DCFE_MEM_PWR_STATUS, DCFE, id), \ + SRI(CONTROL, FMT_MEMORY, id) +#endif + #define OPP_SF(reg_name, field_name, post_fix)\ .field_name = reg_name ## __ ## field_name ## post_fix @@ -197,6 +205,70 @@ enum dce110_opp_reg_type { OPP_SF(DCFE_MEM_LIGHT_SLEEP_CNTL, DCP_LUT_LIGHT_SLEEP_DIS, mask_sh),\ OPP_SF(DCFE_MEM_LIGHT_SLEEP_CNTL, REGAMMA_LUT_MEM_PWR_STATE, mask_sh) +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +#define OPP_COMMON_MASK_SH_LIST_DCE_120(mask_sh)\ + OPP_SF(DCFE0_DCFE_MEM_PWR_CTRL, DCP_REGAMMA_MEM_PWR_DIS, mask_sh),\ + OPP_SF(DCFE0_DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, mask_sh),\ + OPP_SF(DCP0_REGAMMA_CNTLA_START_CNTL, REGAMMA_CNTLA_EXP_REGION_START, mask_sh),\ + OPP_SF(DCP0_REGAMMA_CNTLA_START_CNTL, REGAMMA_CNTLA_EXP_REGION_START_SEGMENT, mask_sh),\ + OPP_SF(DCP0_REGAMMA_CNTLA_SLOPE_CNTL, REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE, mask_sh),\ + OPP_SF(DCP0_REGAMMA_CNTLA_END_CNTL1, REGAMMA_CNTLA_EXP_REGION_END, mask_sh),\ + OPP_SF(DCP0_REGAMMA_CNTLA_END_CNTL2, REGAMMA_CNTLA_EXP_REGION_END_BASE, mask_sh),\ + OPP_SF(DCP0_REGAMMA_CNTLA_END_CNTL2, REGAMMA_CNTLA_EXP_REGION_END_SLOPE, mask_sh),\ + OPP_SF(DCP0_REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, mask_sh),\ + OPP_SF(DCP0_REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, mask_sh),\ + OPP_SF(DCP0_REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, mask_sh),\ + OPP_SF(DCP0_REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, mask_sh),\ + OPP_SF(DCFE0_DCFE_MEM_PWR_STATUS, DCP_REGAMMA_MEM_PWR_STATE, mask_sh),\ + OPP_SF(DCP0_REGAMMA_LUT_WRITE_EN_MASK, REGAMMA_LUT_WRITE_EN_MASK, mask_sh),\ + OPP_SF(DCP0_REGAMMA_CONTROL, GRPH_REGAMMA_MODE, mask_sh),\ + OPP_SF(DCP0_OUTPUT_CSC_C11_C12, OUTPUT_CSC_C11, mask_sh),\ + OPP_SF(DCP0_OUTPUT_CSC_C11_C12, OUTPUT_CSC_C12, mask_sh),\ + OPP_SF(DCP0_OUTPUT_CSC_CONTROL, OUTPUT_CSC_GRPH_MODE, mask_sh),\ + OPP_SF(FMT0_FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN, mask_sh),\ + OPP_SF(FMT0_FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE, mask_sh),\ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN, mask_sh),\ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_DEPTH, mask_sh),\ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_MODE, mask_sh),\ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_EN, mask_sh),\ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_DEPTH, mask_sh),\ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_MODE, mask_sh),\ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_EN, mask_sh),\ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_RESET, mask_sh),\ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_OFFSET, mask_sh),\ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_DEPTH, mask_sh),\ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_LEVEL, mask_sh),\ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_25FRC_SEL, mask_sh),\ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_50FRC_SEL, mask_sh),\ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_75FRC_SEL, mask_sh),\ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_HIGHPASS_RANDOM_ENABLE, mask_sh),\ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_FRAME_RANDOM_ENABLE, mask_sh),\ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_RGB_RANDOM_ENABLE, mask_sh),\ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_EN, mask_sh),\ + OPP_SF(FMT0_FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, mask_sh),\ + OPP_SF(FMT0_FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, mask_sh),\ + OPP_SF(FMT0_FMT_DITHER_RAND_R_SEED, FMT_RAND_R_SEED, mask_sh),\ + OPP_SF(FMT0_FMT_DITHER_RAND_G_SEED, FMT_RAND_G_SEED, mask_sh),\ + OPP_SF(FMT0_FMT_DITHER_RAND_B_SEED, FMT_RAND_B_SEED, mask_sh),\ + OPP_SF(FMT_MEMORY0_CONTROL, FMT420_MEM0_SOURCE_SEL, mask_sh),\ + OPP_SF(FMT_MEMORY0_CONTROL, FMT420_MEM0_PWR_FORCE, mask_sh),\ + OPP_SF(FMT0_FMT_CONTROL, FMT_SRC_SELECT, mask_sh),\ + OPP_SF(FMT0_FMT_CONTROL, FMT_420_PIXEL_PHASE_LOCKED_CLEAR, mask_sh),\ + OPP_SF(FMT0_FMT_CONTROL, FMT_420_PIXEL_PHASE_LOCKED, mask_sh),\ + OPP_SF(FMT0_FMT_CLAMP_CNTL, FMT_CLAMP_DATA_EN, mask_sh),\ + OPP_SF(FMT0_FMT_CLAMP_CNTL, FMT_CLAMP_COLOR_FORMAT, mask_sh),\ + OPP_SF(FMT0_FMT_CLAMP_COMPONENT_R, FMT_CLAMP_LOWER_R, mask_sh),\ + OPP_SF(FMT0_FMT_CLAMP_COMPONENT_R, FMT_CLAMP_UPPER_R, mask_sh),\ + OPP_SF(FMT0_FMT_CLAMP_COMPONENT_G, FMT_CLAMP_LOWER_G, mask_sh),\ + OPP_SF(FMT0_FMT_CLAMP_COMPONENT_G, FMT_CLAMP_UPPER_G, mask_sh),\ + OPP_SF(FMT0_FMT_CLAMP_COMPONENT_B, FMT_CLAMP_LOWER_B, mask_sh),\ + OPP_SF(FMT0_FMT_CLAMP_COMPONENT_B, FMT_CLAMP_UPPER_B, mask_sh),\ + OPP_SF(FMT0_FMT_CONTROL, FMT_PIXEL_ENCODING, mask_sh),\ + OPP_SF(FMT0_FMT_CONTROL, FMT_SUBSAMPLING_MODE, mask_sh),\ + OPP_SF(FMT0_FMT_CONTROL, FMT_SUBSAMPLING_ORDER, mask_sh),\ + OPP_SF(FMT0_FMT_CONTROL, FMT_CBCR_BIT_REDUCTION_BYPASS, mask_sh) +#endif + #define OPP_REG_FIELD_LIST(type) \ type DCP_REGAMMA_MEM_PWR_DIS; \ type DCP_LUT_MEM_PWR_DIS; \ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h index 458a37000956..c784c1b961c6 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h @@ -187,6 +187,91 @@ #define SE_COMMON_MASK_SH_LIST_DCE_COMMON(mask_sh)\ SE_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh) +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +#define SE_COMMON_MASK_SH_LIST_SOC_BASE(mask_sh)\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_INDEX, mask_sh),\ + SE_SF(DIG0_AFMT_GENERIC_HDR, AFMT_GENERIC_HB0, mask_sh),\ + SE_SF(DIG0_AFMT_GENERIC_HDR, AFMT_GENERIC_HB1, mask_sh),\ + SE_SF(DIG0_AFMT_GENERIC_HDR, AFMT_GENERIC_HB2, mask_sh),\ + SE_SF(DIG0_AFMT_GENERIC_HDR, AFMT_GENERIC_HB3, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_LINE, mask_sh),\ + SE_SF(DP0_DP_PIXEL_FORMAT, DP_PIXEL_ENCODING, mask_sh),\ + SE_SF(DP0_DP_PIXEL_FORMAT, DP_COMPONENT_DEPTH, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_PACKET_GEN_VERSION, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_KEEPOUT_MODE, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_DEEP_COLOR_ENABLE, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_DEEP_COLOR_DEPTH, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_DATA_SCRAMBLE_EN, mask_sh),\ + SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_GC_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_GC_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_NULL_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_SEND, mask_sh),\ + SE_SF(DIG0_AFMT_INFOFRAME_CONTROL0, AFMT_AUDIO_INFO_UPDATE, mask_sh),\ + SE_SF(DIG0_HDMI_INFOFRAME_CONTROL1, HDMI_AUDIO_INFO_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GC, HDMI_GC_AVMUTE, mask_sh),\ + SE_SF(DP0_DP_MSE_RATE_CNTL, DP_MSE_RATE_X, mask_sh),\ + SE_SF(DP0_DP_MSE_RATE_CNTL, DP_MSE_RATE_Y, mask_sh),\ + SE_SF(DP0_DP_MSE_RATE_UPDATE, DP_MSE_RATE_UPDATE_PENDING, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP0_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP1_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP2_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP3_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_MPG_ENABLE, mask_sh),\ + SE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_DIS_DEFER, mask_sh),\ + SE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, mask_sh),\ + SE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_STATUS, mask_sh),\ + SE_SF(DP0_DP_STEER_FIFO, DP_STEER_FIFO_RESET, mask_sh),\ + SE_SF(DP0_DP_VID_TIMING, DP_VID_M_N_GEN_EN, mask_sh),\ + SE_SF(DP0_DP_VID_N, DP_VID_N, mask_sh),\ + SE_SF(DP0_DP_VID_M, DP_VID_M, mask_sh),\ + SE_SF(DIG0_DIG_FE_CNTL, DIG_START, mask_sh),\ + SE_SF(DIG0_AFMT_AUDIO_SRC_CONTROL, AFMT_AUDIO_SRC_SELECT, mask_sh),\ + SE_SF(DIG0_AFMT_AUDIO_PACKET_CONTROL2, AFMT_AUDIO_CHANNEL_ENABLE, mask_sh),\ + SE_SF(DIG0_HDMI_AUDIO_PACKET_CONTROL, HDMI_AUDIO_PACKETS_PER_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_AUDIO_PACKET_CONTROL, HDMI_AUDIO_DELAY_EN, mask_sh),\ + SE_SF(DIG0_AFMT_AUDIO_PACKET_CONTROL, AFMT_60958_CS_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_AUDIO_PACKET_CONTROL2, AFMT_AUDIO_LAYOUT_OVRD, mask_sh),\ + SE_SF(DIG0_AFMT_AUDIO_PACKET_CONTROL2, AFMT_60958_OSF_OVRD, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_PACKET_CONTROL, HDMI_ACR_AUTO_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_PACKET_CONTROL, HDMI_ACR_SOURCE, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_PACKET_CONTROL, HDMI_ACR_AUDIO_PRIORITY, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_32_0, HDMI_ACR_CTS_32, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_32_1, HDMI_ACR_N_32, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_44_0, HDMI_ACR_CTS_44, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_44_1, HDMI_ACR_N_44, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_48_0, HDMI_ACR_CTS_48, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_48_1, HDMI_ACR_N_48, mask_sh),\ + SE_SF(DIG0_AFMT_60958_0, AFMT_60958_CS_CHANNEL_NUMBER_L, mask_sh),\ + SE_SF(DIG0_AFMT_60958_0, AFMT_60958_CS_CLOCK_ACCURACY, mask_sh),\ + SE_SF(DIG0_AFMT_60958_1, AFMT_60958_CS_CHANNEL_NUMBER_R, mask_sh),\ + SE_SF(DIG0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_2, mask_sh),\ + SE_SF(DIG0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_3, mask_sh),\ + SE_SF(DIG0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_4, mask_sh),\ + SE_SF(DIG0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_5, mask_sh),\ + SE_SF(DIG0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_6, mask_sh),\ + SE_SF(DIG0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_7, mask_sh),\ + SE_SF(DP0_DP_SEC_AUD_N, DP_SEC_AUD_N, mask_sh),\ + SE_SF(DP0_DP_SEC_TIMESTAMP, DP_SEC_TIMESTAMP_MODE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_ASP_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_ATP_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_AIP_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_ACM_ENABLE, mask_sh),\ + SE_SF(DIG0_AFMT_AUDIO_PACKET_CONTROL, AFMT_AUDIO_SAMPLE_SEND, mask_sh),\ + SE_SF(DIG0_AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_CLOCK_CHANNEL_RATE, mask_sh),\ + SE_SF(DIG0_DIG_FE_CNTL, TMDS_PIXEL_ENCODING, mask_sh),\ + SE_SF(DIG0_DIG_FE_CNTL, TMDS_COLOR_FORMAT, mask_sh) +#endif + +#define SE_COMMON_MASK_SH_LIST_SOC(mask_sh)\ + SE_COMMON_MASK_SH_LIST_SOC_BASE(mask_sh) + #define SE_COMMON_MASK_SH_LIST_DCE80_100(mask_sh)\ SE_COMMON_MASK_SH_LIST_DCE_COMMON(mask_sh),\ SE_SF(TMDS_CNTL, TMDS_PIXEL_ENCODING, mask_sh),\ @@ -209,6 +294,21 @@ SE_SF(DIG_FE_CNTL, TMDS_COLOR_FORMAT, mask_sh),\ SE_SF(DP_VID_TIMING, DP_VID_M_DOUBLE_VALUE_EN, mask_sh) +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +#define SE_COMMON_MASK_SH_LIST_DCE120(mask_sh)\ + SE_COMMON_MASK_SH_LIST_SOC(mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC0_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC2_UPDATE, mask_sh),\ + SE_SF(DP0_DP_PIXEL_FORMAT, DP_DYN_RANGE, mask_sh),\ + SE_SF(DP0_DP_PIXEL_FORMAT, DP_YCBCR_RANGE, mask_sh),\ + SE_SF(DIG0_HDMI_INFOFRAME_CONTROL0, HDMI_AVI_INFO_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_INFOFRAME_CONTROL0, HDMI_AVI_INFO_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_INFOFRAME_CONTROL1, HDMI_AVI_INFO_LINE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_AVI_ENABLE, mask_sh),\ + SE_SF(DIG0_AFMT_AVI_INFO3, AFMT_AVI_INFO_VERSION, mask_sh),\ + SE_SF(DP0_DP_VID_TIMING, DP_VID_M_DOUBLE_VALUE_EN, mask_sh) +#endif + struct dce_stream_encoder_shift { uint8_t AFMT_GENERIC_INDEX; uint8_t AFMT_GENERIC0_UPDATE; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h index b2cf9bfb0094..aa6bc4fc80c5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h @@ -153,6 +153,74 @@ XFM_SF(DCFE_MEM_PWR_STATUS, SCL_COEFF_MEM_PWR_STATE, mask_sh), \ XFM_SF(SCL_MODE, SCL_PSCL_EN, mask_sh) +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +#define XFM_COMMON_MASK_SH_LIST_SOC_BASE(mask_sh) \ + XFM_SF(DCP0_OUT_CLAMP_CONTROL_B_CB, OUT_CLAMP_MIN_B_CB, mask_sh), \ + XFM_SF(DCP0_OUT_CLAMP_CONTROL_B_CB, OUT_CLAMP_MAX_B_CB, mask_sh), \ + XFM_SF(DCP0_OUT_CLAMP_CONTROL_G_Y, OUT_CLAMP_MIN_G_Y, mask_sh), \ + XFM_SF(DCP0_OUT_CLAMP_CONTROL_G_Y, OUT_CLAMP_MAX_G_Y, mask_sh), \ + XFM_SF(DCP0_OUT_CLAMP_CONTROL_R_CR, OUT_CLAMP_MIN_R_CR, mask_sh), \ + XFM_SF(DCP0_OUT_CLAMP_CONTROL_R_CR, OUT_CLAMP_MAX_R_CR, mask_sh), \ + XFM_SF(DCP0_OUT_ROUND_CONTROL, OUT_ROUND_TRUNC_MODE, mask_sh), \ + XFM_SF(DCP0_DCP_SPATIAL_DITHER_CNTL, DCP_SPATIAL_DITHER_EN, mask_sh), \ + XFM_SF(DCP0_DCP_SPATIAL_DITHER_CNTL, DCP_SPATIAL_DITHER_MODE, mask_sh), \ + XFM_SF(DCP0_DCP_SPATIAL_DITHER_CNTL, DCP_SPATIAL_DITHER_DEPTH, mask_sh), \ + XFM_SF(DCP0_DCP_SPATIAL_DITHER_CNTL, DCP_FRAME_RANDOM_ENABLE, mask_sh), \ + XFM_SF(DCP0_DCP_SPATIAL_DITHER_CNTL, DCP_RGB_RANDOM_ENABLE, mask_sh), \ + XFM_SF(DCP0_DCP_SPATIAL_DITHER_CNTL, DCP_HIGHPASS_RANDOM_ENABLE, mask_sh), \ + XFM_SF(DCP0_DENORM_CONTROL, DENORM_MODE, mask_sh), \ + XFM_SF(LB0_LB_DATA_FORMAT, PIXEL_DEPTH, mask_sh), \ + XFM_SF(LB0_LB_DATA_FORMAT, PIXEL_EXPAN_MODE, mask_sh), \ + XFM_SF(DCP0_GAMUT_REMAP_C11_C12, GAMUT_REMAP_C11, mask_sh), \ + XFM_SF(DCP0_GAMUT_REMAP_C11_C12, GAMUT_REMAP_C12, mask_sh), \ + XFM_SF(DCP0_GAMUT_REMAP_C13_C14, GAMUT_REMAP_C13, mask_sh), \ + XFM_SF(DCP0_GAMUT_REMAP_C13_C14, GAMUT_REMAP_C14, mask_sh), \ + XFM_SF(DCP0_GAMUT_REMAP_C21_C22, GAMUT_REMAP_C21, mask_sh), \ + XFM_SF(DCP0_GAMUT_REMAP_C21_C22, GAMUT_REMAP_C22, mask_sh), \ + XFM_SF(DCP0_GAMUT_REMAP_C23_C24, GAMUT_REMAP_C23, mask_sh), \ + XFM_SF(DCP0_GAMUT_REMAP_C23_C24, GAMUT_REMAP_C24, mask_sh), \ + XFM_SF(DCP0_GAMUT_REMAP_C31_C32, GAMUT_REMAP_C31, mask_sh), \ + XFM_SF(DCP0_GAMUT_REMAP_C31_C32, GAMUT_REMAP_C32, mask_sh), \ + XFM_SF(DCP0_GAMUT_REMAP_C33_C34, GAMUT_REMAP_C33, mask_sh), \ + XFM_SF(DCP0_GAMUT_REMAP_C33_C34, GAMUT_REMAP_C34, mask_sh), \ + XFM_SF(DCP0_GAMUT_REMAP_CONTROL, GRPH_GAMUT_REMAP_MODE, mask_sh), \ + XFM_SF(SCL0_SCL_MODE, SCL_MODE, mask_sh), \ + XFM_SF(SCL0_SCL_TAP_CONTROL, SCL_H_NUM_OF_TAPS, mask_sh), \ + XFM_SF(SCL0_SCL_TAP_CONTROL, SCL_V_NUM_OF_TAPS, mask_sh), \ + XFM_SF(SCL0_SCL_CONTROL, SCL_BOUNDARY_MODE, mask_sh), \ + XFM_SF(SCL0_SCL_BYPASS_CONTROL, SCL_BYPASS_MODE, mask_sh), \ + XFM_SF(SCL0_EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_LEFT, mask_sh), \ + XFM_SF(SCL0_EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_RIGHT, mask_sh), \ + XFM_SF(SCL0_EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_TOP, mask_sh), \ + XFM_SF(SCL0_EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_BOTTOM, mask_sh), \ + XFM_SF(SCL0_SCL_COEF_RAM_SELECT, SCL_C_RAM_FILTER_TYPE, mask_sh), \ + XFM_SF(SCL0_SCL_COEF_RAM_SELECT, SCL_C_RAM_PHASE, mask_sh), \ + XFM_SF(SCL0_SCL_COEF_RAM_SELECT, SCL_C_RAM_TAP_PAIR_IDX, mask_sh), \ + XFM_SF(SCL0_SCL_COEF_RAM_TAP_DATA, SCL_C_RAM_EVEN_TAP_COEF_EN, mask_sh), \ + XFM_SF(SCL0_SCL_COEF_RAM_TAP_DATA, SCL_C_RAM_EVEN_TAP_COEF, mask_sh), \ + XFM_SF(SCL0_SCL_COEF_RAM_TAP_DATA, SCL_C_RAM_ODD_TAP_COEF_EN, mask_sh), \ + XFM_SF(SCL0_SCL_COEF_RAM_TAP_DATA, SCL_C_RAM_ODD_TAP_COEF, mask_sh), \ + XFM_SF(SCL0_VIEWPORT_START, VIEWPORT_X_START, mask_sh), \ + XFM_SF(SCL0_VIEWPORT_START, VIEWPORT_Y_START, mask_sh), \ + XFM_SF(SCL0_VIEWPORT_SIZE, VIEWPORT_HEIGHT, mask_sh), \ + XFM_SF(SCL0_VIEWPORT_SIZE, VIEWPORT_WIDTH, mask_sh), \ + XFM_SF(SCL0_SCL_HORZ_FILTER_SCALE_RATIO, SCL_H_SCALE_RATIO, mask_sh), \ + XFM_SF(SCL0_SCL_VERT_FILTER_SCALE_RATIO, SCL_V_SCALE_RATIO, mask_sh), \ + XFM_SF(SCL0_SCL_HORZ_FILTER_INIT, SCL_H_INIT_INT, mask_sh), \ + XFM_SF(SCL0_SCL_HORZ_FILTER_INIT, SCL_H_INIT_FRAC, mask_sh), \ + XFM_SF(SCL0_SCL_VERT_FILTER_INIT, SCL_V_INIT_INT, mask_sh), \ + XFM_SF(SCL0_SCL_VERT_FILTER_INIT, SCL_V_INIT_FRAC, mask_sh), \ + XFM_SF(LB0_LB_MEMORY_CTRL, LB_MEMORY_CONFIG, mask_sh), \ + XFM_SF(LB0_LB_MEMORY_CTRL, LB_MEMORY_SIZE, mask_sh), \ + XFM_SF(SCL0_SCL_VERT_FILTER_CONTROL, SCL_V_2TAP_HARDCODE_COEF_EN, mask_sh), \ + XFM_SF(SCL0_SCL_HORZ_FILTER_CONTROL, SCL_H_2TAP_HARDCODE_COEF_EN, mask_sh), \ + XFM_SF(SCL0_SCL_UPDATE, SCL_COEF_UPDATE_COMPLETE, mask_sh), \ + XFM_SF(LB0_LB_DATA_FORMAT, ALPHA_EN, mask_sh), \ + XFM_SF(DCFE0_DCFE_MEM_PWR_CTRL, SCL_COEFF_MEM_PWR_DIS, mask_sh), \ + XFM_SF(DCFE0_DCFE_MEM_PWR_STATUS, SCL_COEFF_MEM_PWR_STATE, mask_sh), \ + XFM_SF(SCL0_SCL_MODE, SCL_PSCL_EN, mask_sh) +#endif + #define XFM_REG_FIELD_LIST(type) \ type OUT_CLAMP_MIN_B_CB; \ type OUT_CLAMP_MAX_B_CB; \ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 041830e05b67..66d5f346f195 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1396,9 +1396,12 @@ static uint32_t get_max_pixel_clock_for_all_paths( return max_pix_clk; } -/* - * Find clock state based on clock requested. if clock value is 0, simply +/* Find clock state based on clock requested. if clock value is 0, simply * set clock state as requested without finding clock state by clock value + *TODO: when dce120_hw_sequencer.c is created, override apply_min_clock. + * + * TODOFPGA remove TODO after implement dal_display_clock_get_cur_clocks_value + * etc support for dcn1.0 */ static void apply_min_clocks( struct core_dc *dc, @@ -1425,6 +1428,30 @@ static void apply_min_clocks( } /* TODOFPGA */ +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + /* TODO: This is incorrect. Figure out how to fix. */ + pipe_ctx->dis_clk->funcs->apply_clock_voltage_request( + pipe_ctx->dis_clk, + DM_PP_CLOCK_TYPE_DISPLAY_CLK, + pipe_ctx->dis_clk->cur_clocks_value.dispclk_in_khz, + pre_mode_set, + false); + + pipe_ctx->dis_clk->funcs->apply_clock_voltage_request( + pipe_ctx->dis_clk, + DM_PP_CLOCK_TYPE_PIXELCLK, + pipe_ctx->dis_clk->cur_clocks_value.max_pixelclk_in_khz, + pre_mode_set, + false); + + pipe_ctx->dis_clk->funcs->apply_clock_voltage_request( + pipe_ctx->dis_clk, + DM_PP_CLOCK_TYPE_DISPLAYPHYCLK, + pipe_ctx->dis_clk->cur_clocks_value.max_non_dp_phyclk_in_khz, + pre_mode_set, + false); + return; +#endif } /* get the required state based on state dependent clocks: @@ -1441,6 +1468,28 @@ static void apply_min_clocks( pipe_ctx->dis_clk->funcs->set_min_clocks_state( pipe_ctx->dis_clk, *clocks_state); } else { +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + pipe_ctx->dis_clk->funcs->apply_clock_voltage_request( + pipe_ctx->dis_clk, + DM_PP_CLOCK_TYPE_DISPLAY_CLK, + req_clocks.display_clk_khz, + pre_mode_set, + false); + + pipe_ctx->dis_clk->funcs->apply_clock_voltage_request( + pipe_ctx->dis_clk, + DM_PP_CLOCK_TYPE_PIXELCLK, + req_clocks.pixel_clk_khz, + pre_mode_set, + false); + + pipe_ctx->dis_clk->funcs->apply_clock_voltage_request( + pipe_ctx->dis_clk, + DM_PP_CLOCK_TYPE_DISPLAYPHYCLK, + req_clocks.pixel_clk_khz, + pre_mode_set, + false); +#endif } } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c index 1643fb5d4b04..3ffb845f843a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c @@ -409,6 +409,9 @@ static struct mem_input_funcs dce110_mem_input_funcs = { dce_mem_input_program_surface_config, .mem_input_is_flip_pending = dce110_mem_input_is_flip_pending, +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + .mem_input_update_dchub = NULL +#endif }; /*****************************************/ /* Constructor, Destructor */ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h index dcb49fe452c5..55f0a94e7cae 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h @@ -108,6 +108,9 @@ struct dce110_timing_generator { uint32_t min_h_front_porch; uint32_t min_h_back_porch; +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + /* DCE 12 */ +#endif uint32_t min_h_sync_width; uint32_t min_v_sync_width; uint32_t min_v_blank; diff --git a/drivers/gpu/drm/amd/display/dc/dce120/Makefile b/drivers/gpu/drm/amd/display/dc/dce120/Makefile new file mode 100644 index 000000000000..3c6b3fa98ddc --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce120/Makefile @@ -0,0 +1,12 @@ +# +# Makefile for the 'controller' sub-component of DAL. +# It provides the control and status of HW CRTC block. + + +DCE120 = dce120_resource.o dce120_timing_generator.o \ +dce120_ipp.o dce120_ipp_cursor.o dce120_ipp_gamma.o \ +dce120_mem_input.o dce120_hw_sequencer.o + +AMD_DAL_DCE120 = $(addprefix $(AMDDALPATH)/dc/dce120/,$(DCE120)) + +AMD_DISPLAY_FILES += $(AMD_DAL_DCE120) \ No newline at end of file diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c index 704a7ce62080..2f22931f457b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c @@ -54,6 +54,9 @@ static struct mem_input_funcs dce80_mem_input_funcs = { dce_mem_input_program_surface_config, .mem_input_is_flip_pending = dce110_mem_input_is_flip_pending, +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + .mem_input_update_dchub = NULL +#endif }; /*****************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/dm_services.h b/drivers/gpu/drm/amd/display/dc/dm_services.h index 73c0f1f83999..bdc7cb045eed 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services.h @@ -192,6 +192,89 @@ unsigned int generic_reg_wait(const struct dc_context *ctx, unsigned int delay_between_poll_us, unsigned int time_out_num_tries, const char *func_name); +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + +/* These macros need to be used with soc15 registers in order to retrieve + * the actual offset. + */ +#define REG_OFFSET(reg) (reg + DCE_BASE.instance[0].segment[reg##_BASE_IDX]) +#define REG_BIF_OFFSET(reg) (reg + NBIF_BASE.instance[0].segment[reg##_BASE_IDX]) + +#define dm_write_reg_soc15(ctx, reg, inst_offset, value) \ + dm_write_reg_func(ctx, reg + DCE_BASE.instance[0].segment[reg##_BASE_IDX] + inst_offset, value, __func__) + +#define dm_read_reg_soc15(ctx, reg, inst_offset) \ + dm_read_reg_func(ctx, reg + DCE_BASE.instance[0].segment[reg##_BASE_IDX] + inst_offset, __func__) + +#define generic_reg_update_soc15(ctx, inst_offset, reg_name, n, ...)\ + generic_reg_update_ex(ctx, DCE_BASE.instance[0].segment[mm##reg_name##_BASE_IDX] + mm##reg_name + inst_offset, \ + dm_read_reg_func(ctx, mm##reg_name + DCE_BASE.instance[0].segment[mm##reg_name##_BASE_IDX] + inst_offset, __func__), \ + n, __VA_ARGS__) + +#define generic_reg_set_soc15(ctx, inst_offset, reg_name, n, ...)\ + generic_reg_update_ex(ctx, DCE_BASE.instance[0].segment[mm##reg_name##_BASE_IDX] + mm##reg_name + inst_offset, 0, \ + n, __VA_ARGS__) + +#define get_reg_field_value_soc15(reg_value, block, reg_num, reg_name, reg_field)\ + get_reg_field_value_ex(\ + (reg_value),\ + block ## reg_num ## _ ## reg_name ## __ ## reg_field ## _MASK,\ + block ## reg_num ## _ ## reg_name ## __ ## reg_field ## __SHIFT) + +#define set_reg_field_value_soc15(reg_value, value, block, reg_num, reg_name, reg_field)\ + (reg_value) = set_reg_field_value_ex(\ + (reg_value),\ + (value),\ + block ## reg_num ## _ ## reg_name ## __ ## reg_field ## _MASK,\ + block ## reg_num ## _ ## reg_name ## __ ## reg_field ## __SHIFT) + +/* TODO get rid of this pos*/ +static inline bool wait_reg_func( + const struct dc_context *ctx, + uint32_t addr, + uint32_t mask, + uint8_t shift, + uint32_t condition_value, + unsigned int interval_us, + unsigned int timeout_us) +{ + uint32_t field_value; + uint32_t reg_val; + unsigned int count = 0; + + if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment)) + timeout_us *= 655; /* 6553 give about 30 second before time out */ + + do { + /* try once without sleeping */ + if (count > 0) { + if (interval_us >= 1000) + msleep(interval_us/1000); + else + udelay(interval_us); + } + reg_val = dm_read_reg(ctx, addr); + field_value = get_reg_field_value_ex(reg_val, mask, shift); + count += interval_us; + + } while (field_value != condition_value && count <= timeout_us); + + ASSERT(count <= timeout_us); + + return count <= timeout_us; +} + +#define wait_reg(ctx, inst_offset, reg_name, reg_field, condition_value)\ + wait_reg_func(\ + ctx,\ + mm##reg_name + inst_offset + DCE_BASE.instance[0].segment[mm##reg_name##_BASE_IDX],\ + reg_name ## __ ## reg_field ## _MASK,\ + reg_name ## __ ## reg_field ## __SHIFT,\ + condition_value,\ + 20000,\ + 200000) + +#endif /************************************** * Power Play (PP) interfaces **************************************/ @@ -254,6 +337,12 @@ bool dm_pp_notify_wm_clock_changes( const struct dc_context *ctx, struct dm_pp_wm_sets_with_clock_ranges *wm_with_clock_ranges); +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +bool dm_pp_notify_wm_clock_changes_soc15( + const struct dc_context *ctx, + struct dm_pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges); +#endif + /* DAL calls this function to notify PP about completion of Mode Set. * For PP it means that current DCE clocks are those which were returned * by dc_service_pp_pre_dce_clock_change(), in the 'output' parameter. diff --git a/drivers/gpu/drm/amd/display/dc/dm_services_types.h b/drivers/gpu/drm/amd/display/dc/dm_services_types.h index 460971dc3a70..8d2661583f21 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services_types.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services_types.h @@ -141,6 +141,33 @@ struct dm_pp_wm_sets_with_clock_ranges { struct dm_pp_clock_range_for_wm_set wm_clk_ranges[MAX_WM_SETS]; }; +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +struct dm_pp_clock_range_for_dmif_wm_set_soc15 { + enum dm_pp_wm_set_id wm_set_id; + uint32_t wm_min_dcfclk_clk_in_khz; + uint32_t wm_max_dcfclk_clk_in_khz; + uint32_t wm_min_memg_clk_in_khz; + uint32_t wm_max_mem_clk_in_khz; +}; + +struct dm_pp_clock_range_for_mcif_wm_set_soc15 { + enum dm_pp_wm_set_id wm_set_id; + uint32_t wm_min_socclk_clk_in_khz; + uint32_t wm_max_socclk_clk_in_khz; + uint32_t wm_min_memg_clk_in_khz; + uint32_t wm_max_mem_clk_in_khz; +}; + +struct dm_pp_wm_sets_with_clock_ranges_soc15 { + uint32_t num_wm_dmif_sets; + uint32_t num_wm_mcif_sets; + struct dm_pp_clock_range_for_dmif_wm_set_soc15 + wm_dmif_clocks_ranges[MAX_WM_SETS]; + struct dm_pp_clock_range_for_mcif_wm_set_soc15 + wm_mcif_clocks_ranges[MAX_WM_SETS]; +}; +#endif + #define MAX_DISPLAY_CONFIGS 6 struct dm_pp_display_configuration { diff --git a/drivers/gpu/drm/amd/display/dc/gpio/Makefile b/drivers/gpu/drm/amd/display/dc/gpio/Makefile index a15c257fd2fa..8cf12a8ca28f 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/Makefile +++ b/drivers/gpu/drm/amd/display/dc/gpio/Makefile @@ -28,6 +28,17 @@ AMD_DAL_GPIO_DCE110 = $(addprefix $(AMDDALPATH)/dc/gpio/dce110/,$(GPIO_DCE110)) AMD_DISPLAY_FILES += $(AMD_DAL_GPIO_DCE110) +############################################################################### +# DCE 12x +############################################################################### +ifdef CONFIG_DRM_AMD_DC_DCE12_0 +GPIO_DCE120 = hw_translate_dce120.o hw_factory_dce120.o + +AMD_DAL_GPIO_DCE120 = $(addprefix $(AMDDALPATH)/dc/gpio/dce120/,$(GPIO_DCE120)) + +AMD_DISPLAY_FILES += $(AMD_DAL_GPIO_DCE120) +endif + ############################################################################### # Diagnostics on FPGA ############################################################################### diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c index f1a6fa7391c6..66ea3b31b980 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c @@ -44,6 +44,10 @@ #include "dce110/hw_factory_dce110.h" +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +#include "dce120/hw_factory_dce120.h" +#endif + #include "diagnostics/hw_factory_diag.h" /* @@ -72,6 +76,11 @@ bool dal_hw_factory_init( case DCE_VERSION_11_2: dal_hw_factory_dce110_init(factory); return true; +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + case DCE_VERSION_12_0: + dal_hw_factory_dce120_init(factory); + return true; +#endif default: ASSERT_CRITICAL(false); return false; diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c index 23e097fa5ace..10e86447f179 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c @@ -42,7 +42,9 @@ #include "dce80/hw_translate_dce80.h" #include "dce110/hw_translate_dce110.h" - +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +#include "dce120/hw_translate_dce120.h" +#endif #include "diagnostics/hw_translate_diag.h" /* @@ -68,6 +70,11 @@ bool dal_hw_translate_init( case DCE_VERSION_11_2: dal_hw_translate_dce110_init(translate); return true; +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + case DCE_VERSION_12_0: + dal_hw_translate_dce120_init(translate); + return true; +#endif default: BREAK_TO_DEBUGGER(); return false; diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/Makefile b/drivers/gpu/drm/amd/display/dc/i2caux/Makefile index 83dfc437aae4..99aa5d8fb9a7 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/Makefile +++ b/drivers/gpu/drm/amd/display/dc/i2caux/Makefile @@ -47,6 +47,17 @@ AMD_DAL_I2CAUX_DCE112 = $(addprefix $(AMDDALPATH)/dc/i2caux/dce112/,$(I2CAUX_DCE AMD_DISPLAY_FILES += $(AMD_DAL_I2CAUX_DCE112) +############################################################################### +# DCE 120 family +############################################################################### +ifdef CONFIG_DRM_AMD_DC_DCE12_0 +I2CAUX_DCE120 = i2caux_dce120.o + +AMD_DAL_I2CAUX_DCE120 = $(addprefix $(AMDDALPATH)/dc/i2caux/dce120/,$(I2CAUX_DCE120)) + +AMD_DISPLAY_FILES += $(AMD_DAL_I2CAUX_DCE120) +endif + ############################################################################### # Diagnostics on FPGA ############################################################################### diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c index 5391655af23a..ea3bd75e0555 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c @@ -57,6 +57,10 @@ #include "dce112/i2caux_dce112.h" +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +#include "dce120/i2caux_dce120.h" +#endif + #include "diagnostics/i2caux_diag.h" /* @@ -80,6 +84,10 @@ struct i2caux *dal_i2caux_create( return dal_i2caux_dce110_create(ctx); case DCE_VERSION_10_0: return dal_i2caux_dce100_create(ctx); + #if defined(CONFIG_DRM_AMD_DC_DCE12_0) + case DCE_VERSION_12_0: + return dal_i2caux_dce120_create(ctx); + #endif default: BREAK_TO_DEBUGGER(); return NULL; diff --git a/drivers/gpu/drm/amd/display/dc/inc/bandwidth_calcs.h b/drivers/gpu/drm/amd/display/dc/inc/bandwidth_calcs.h index 16f06fa2d69c..a7eaecd32aea 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/bandwidth_calcs.h +++ b/drivers/gpu/drm/amd/display/dc/inc/bandwidth_calcs.h @@ -40,6 +40,9 @@ enum bw_calcs_version { BW_CALCS_VERSION_POLARIS10, BW_CALCS_VERSION_POLARIS11, BW_CALCS_VERSION_STONEY, +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + BW_CALCS_VERSION_VEGA10 +#endif }; /******************************************************************************* diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h b/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h index e163f5818dd9..bf77aa6172e1 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h @@ -28,6 +28,18 @@ #include "dm_services_types.h" +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +struct clocks_value { + int dispclk_in_khz; + int max_pixelclk_in_khz; + int max_non_dp_phyclk_in_khz; + int max_dp_phyclk_in_khz; + bool dispclk_notify_pplib_done; + bool pixelclk_notify_pplib_done; + bool phyclk_notigy_pplib_done; +}; +#endif + /* Structure containing all state-dependent clocks * (dependent on "enum clocks_state") */ struct state_dependent_clocks { @@ -41,6 +53,9 @@ struct display_clock { enum dm_pp_clocks_state max_clks_state; enum dm_pp_clocks_state cur_min_clks_state; +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + struct clocks_value cur_clocks_value; +#endif }; struct display_clock_funcs { @@ -56,6 +71,14 @@ struct display_clock_funcs { int (*get_dp_ref_clk_frequency)(struct display_clock *disp_clk); +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + bool (*apply_clock_voltage_request)( + struct display_clock *disp_clk, + enum dm_pp_clock_type clocks_type, + int clocks_in_khz, + bool pre_mode_set, + bool update_dp_phyclk); +#endif }; #endif /* __DISPLAY_CLOCK_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h index ed980aed1677..6c0600696d02 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h @@ -100,6 +100,10 @@ struct mem_input_funcs { bool (*mem_input_is_flip_pending)(struct mem_input *mem_input); +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + void (*mem_input_update_dchub)(struct mem_input *mem_input, + struct dchub_init_data *dh_data); +#endif }; #endif diff --git a/drivers/gpu/drm/amd/display/dc/irq/Makefile b/drivers/gpu/drm/amd/display/dc/irq/Makefile index 02710333ce0a..140e49811dd1 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/Makefile +++ b/drivers/gpu/drm/amd/display/dc/irq/Makefile @@ -26,3 +26,15 @@ IRQ_DCE11 = irq_service_dce110.o AMD_DAL_IRQ_DCE11 = $(addprefix $(AMDDALPATH)/dc/irq/dce110/,$(IRQ_DCE11)) AMD_DISPLAY_FILES += $(AMD_DAL_IRQ_DCE11) + +############################################################################### +# DCE 12x +############################################################################### +ifdef CONFIG_DRM_AMD_DC_DCE12_0 +IRQ_DCE12 = irq_service_dce120.o + +AMD_DAL_IRQ_DCE12 = $(addprefix $(AMDDALPATH)/dc/irq/dce120/,$(IRQ_DCE12)) + +AMD_DISPLAY_FILES += $(AMD_DAL_IRQ_DCE12) +endif + diff --git a/drivers/gpu/drm/amd/display/dc/irq/irq_service.c b/drivers/gpu/drm/amd/display/dc/irq/irq_service.c index fbaa2fc00ddb..a1b6d83b1cbb 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/irq_service.c +++ b/drivers/gpu/drm/amd/display/dc/irq/irq_service.c @@ -33,6 +33,9 @@ #include "dce80/irq_service_dce80.h" +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +#include "dce120/irq_service_dce120.h" +#endif #include "reg_helper.h" #include "irq_service.h" diff --git a/drivers/gpu/drm/amd/display/include/dal_asic_id.h b/drivers/gpu/drm/amd/display/include/dal_asic_id.h index 46f1e88f5e27..15c0b8c14b30 100644 --- a/drivers/gpu/drm/amd/display/include/dal_asic_id.h +++ b/drivers/gpu/drm/amd/display/include/dal_asic_id.h @@ -123,6 +123,10 @@ #define FAMILY_VI 130 /* Volcanic Islands: Iceland (V), Tonga (M) */ #define FAMILY_CZ 135 /* Carrizo */ +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +#define FAMILY_AI 141 +#endif + #define FAMILY_UNKNOWN 0xFF #endif /* __DAL_ASIC_ID_H__ */ diff --git a/drivers/gpu/drm/amd/display/include/dal_types.h b/drivers/gpu/drm/amd/display/include/dal_types.h index ada5b19e85eb..e24c1ef58d2f 100644 --- a/drivers/gpu/drm/amd/display/include/dal_types.h +++ b/drivers/gpu/drm/amd/display/include/dal_types.h @@ -38,6 +38,9 @@ enum dce_version { DCE_VERSION_10_0, DCE_VERSION_11_0, DCE_VERSION_11_2, +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + DCE_VERSION_12_0, +#endif DCE_VERSION_MAX, }; -- cgit From 85a51eeec7ed5bb1dab67e2691813418e9185add Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Tue, 7 Mar 2017 16:54:32 -0500 Subject: drm/amd/display: need to handle DCE_Info table ver4.2 Signed-off-by: Charlene Liu Acked-by: Harry Wentland Reviewed-by: Krunoslav Kovac Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c | 79 +++++++++++++++++++++- 1 file changed, 78 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c index f6e77da7d302..123942f4cbde 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -1137,6 +1137,81 @@ static enum bp_result get_ss_info_v4_1( return result; } +static enum bp_result get_ss_info_v4_2( + struct bios_parser *bp, + uint32_t id, + uint32_t index, + struct spread_spectrum_info *ss_info) +{ + enum bp_result result = BP_RESULT_OK; + struct atom_display_controller_info_v4_2 *disp_cntl_tbl = NULL; + struct atom_smu_info_v3_1 *smu_tbl = NULL; + + if (!ss_info) + return BP_RESULT_BADINPUT; + + if (!DATA_TABLES(dce_info)) + return BP_RESULT_BADBIOSTABLE; + + if (!DATA_TABLES(smu_info)) + return BP_RESULT_BADBIOSTABLE; + + disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_2, + DATA_TABLES(dce_info)); + if (!disp_cntl_tbl) + return BP_RESULT_BADBIOSTABLE; + + smu_tbl = GET_IMAGE(struct atom_smu_info_v3_1, DATA_TABLES(smu_info)); + if (!smu_tbl) + return BP_RESULT_BADBIOSTABLE; + + + ss_info->type.STEP_AND_DELAY_INFO = false; + ss_info->spread_percentage_divider = 1000; + /* BIOS no longer uses target clock. Always enable for now */ + ss_info->target_clock_range = 0xffffffff; + + switch (id) { + case AS_SIGNAL_TYPE_DVI: + ss_info->spread_spectrum_percentage = + disp_cntl_tbl->dvi_ss_percentage; + ss_info->spread_spectrum_range = + disp_cntl_tbl->dvi_ss_rate_10hz * 10; + if (disp_cntl_tbl->dvi_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE) + ss_info->type.CENTER_MODE = true; + break; + case AS_SIGNAL_TYPE_HDMI: + ss_info->spread_spectrum_percentage = + disp_cntl_tbl->hdmi_ss_percentage; + ss_info->spread_spectrum_range = + disp_cntl_tbl->hdmi_ss_rate_10hz * 10; + if (disp_cntl_tbl->hdmi_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE) + ss_info->type.CENTER_MODE = true; + break; + /* TODO LVDS not support anymore? */ + case AS_SIGNAL_TYPE_DISPLAY_PORT: + ss_info->spread_spectrum_percentage = + disp_cntl_tbl->dp_ss_percentage; + ss_info->spread_spectrum_range = + disp_cntl_tbl->dp_ss_rate_10hz * 10; + if (disp_cntl_tbl->dp_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE) + ss_info->type.CENTER_MODE = true; + break; + case AS_SIGNAL_TYPE_GPU_PLL: + ss_info->spread_spectrum_percentage = + smu_tbl->gpuclk_ss_percentage; + ss_info->spread_spectrum_range = + smu_tbl->gpuclk_ss_rate_10hz * 10; + if (smu_tbl->gpuclk_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE) + ss_info->type.CENTER_MODE = true; + break; + default: + result = BP_RESULT_UNSUPPORTED; + } + + return result; +} + /** * bios_parser_get_spread_spectrum_info * Get spread spectrum information from the ASIC_InternalSS_Info(ver 2.1 or @@ -1177,6 +1252,8 @@ static enum bp_result bios_parser_get_spread_spectrum_info( switch (tbl_revision.minor) { case 1: return get_ss_info_v4_1(bp, signal, index, ss_info); + case 2: + return get_ss_info_v4_2(bp, signal, index, ss_info); default: break; } @@ -1579,7 +1656,7 @@ static enum bp_result get_firmware_info_v3_1( /* Hardcode frequency if BIOS gives no DCE Ref Clk */ if (info->pll_info.crystal_frequency == 0) info->pll_info.crystal_frequency = 27000; - + /*dp_phy_ref_clk is not correct for atom_display_controller_info_v4_2, but we don't use it*/ info->dp_phy_ref_clk = dce_info->dpphy_refclk_10khz * 10; info->i2c_engine_ref_clk = dce_info->i2c_engine_refclk_10khz * 10; -- cgit From 7fc6ff772b22cad6fc5fe06b0dfa3f730559faf4 Mon Sep 17 00:00:00 2001 From: Jordan Lazare Date: Wed, 8 Mar 2017 14:04:16 -0500 Subject: drm/amd/display: Less log spam Signed-off-by: Jordan Lazare Acked-by: Harry Wentland Reviewed-by: Charlene Liu Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/bios/command_table2.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c index 36d158249182..e33e6bfccb6d 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c @@ -238,8 +238,8 @@ static enum bp_result transmitter_control_v1_6( if (cntl->action == TRANSMITTER_CONTROL_ENABLE || cntl->action == TRANSMITTER_CONTROL_ACTIAVATE || cntl->action == TRANSMITTER_CONTROL_DEACTIVATE) { - dm_logger_write(bp->base.ctx->logger, LOG_HW_SET_MODE,\ - "************************%s:ps.param.symclk_10khz = %d\n",\ + dm_logger_write(bp->base.ctx->logger, LOG_BIOS,\ + "%s:ps.param.symclk_10khz = %d\n",\ __func__, ps.param.symclk_10khz); } @@ -328,8 +328,8 @@ static enum bp_result set_pixel_clock_v7( (uint8_t) bp->cmd_helper-> transmitter_color_depth_to_atom( bp_params->color_depth); - dm_logger_write(bp->base.ctx->logger, LOG_HW_SET_MODE,\ - "************************%s:program display clock = %d"\ + dm_logger_write(bp->base.ctx->logger, LOG_BIOS,\ + "%s:program display clock = %d"\ "colorDepth = %d\n", __func__,\ bp_params->target_pixel_clock, bp_params->color_depth); @@ -760,8 +760,8 @@ static enum bp_result set_dce_clock_v2_1( */ params.param.dceclk_10khz = cpu_to_le32( bp_params->target_clock_frequency / 10); - dm_logger_write(bp->base.ctx->logger, LOG_HW_SET_MODE, - "************************%s:target_clock_frequency = %d"\ + dm_logger_write(bp->base.ctx->logger, LOG_BIOS, + "%s:target_clock_frequency = %d"\ "clock_type = %d \n", __func__,\ bp_params->target_clock_frequency,\ bp_params->clock_type); -- cgit From 8fa9ca2ec6919656db87391a1633692ee8d57c22 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 15 Jun 2017 16:21:43 -0400 Subject: drm/amd/display: Remove DCE12 guards Signed-off-by: Jordan Lazare Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 2 -- drivers/gpu/drm/amd/display/Kconfig | 7 ------- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 ---- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c | 2 -- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 2 -- drivers/gpu/drm/amd/display/dc/Makefile | 3 --- drivers/gpu/drm/amd/display/dc/bios/Makefile | 4 ---- .../drm/amd/display/dc/bios/bios_parser_interface.c | 10 +--------- .../drm/amd/display/dc/bios/command_table_helper2.c | 2 -- drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c | 4 ---- drivers/gpu/drm/amd/display/dc/core/dc.c | 2 -- drivers/gpu/drm/amd/display/dc/core/dc_debug.c | 6 +----- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 2 -- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 6 ------ drivers/gpu/drm/amd/display/dc/dc.h | 8 -------- drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 4 ---- drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c | 4 ---- drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c | 6 ------ drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h | 6 ------ drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h | 2 -- drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h | 18 +++++++----------- drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c | 8 ++------ drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h | 4 ---- drivers/gpu/drm/amd/display/dc/dce/dce_opp.h | 4 ---- .../gpu/drm/amd/display/dc/dce/dce_stream_encoder.h | 4 ---- drivers/gpu/drm/amd/display/dc/dce/dce_transform.h | 2 -- .../drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 5 ----- .../gpu/drm/amd/display/dc/dce110/dce110_mem_input.c | 2 -- .../amd/display/dc/dce110/dce110_timing_generator.h | 2 -- .../gpu/drm/amd/display/dc/dce120/dce120_resource.c | 14 +++++--------- drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c | 2 -- drivers/gpu/drm/amd/display/dc/dm_services.h | 4 ---- drivers/gpu/drm/amd/display/dc/dm_services_types.h | 2 -- drivers/gpu/drm/amd/display/dc/gpio/Makefile | 2 -- drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c | 4 ---- drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c | 4 ---- drivers/gpu/drm/amd/display/dc/i2caux/Makefile | 2 -- drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c | 4 ---- drivers/gpu/drm/amd/display/dc/inc/bandwidth_calcs.h | 2 -- drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h | 6 ------ drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h | 2 -- drivers/gpu/drm/amd/display/dc/irq/Makefile | 2 -- drivers/gpu/drm/amd/display/dc/irq/irq_service.c | 2 -- drivers/gpu/drm/amd/display/include/dal_asic_id.h | 2 -- drivers/gpu/drm/amd/display/include/dal_types.h | 2 -- 45 files changed, 16 insertions(+), 175 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 96955c9b4cdf..df95dd8439b6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1987,9 +1987,7 @@ bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type) case CHIP_POLARIS12: case CHIP_TONGA: case CHIP_FIJI: -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) case CHIP_VEGA10: -#endif #if defined(CONFIG_DRM_AMD_DC_PRE_VEGA) return amdgpu_dc != 0; #else diff --git a/drivers/gpu/drm/amd/display/Kconfig b/drivers/gpu/drm/amd/display/Kconfig index 32826a0eafe7..47c8e2940a91 100644 --- a/drivers/gpu/drm/amd/display/Kconfig +++ b/drivers/gpu/drm/amd/display/Kconfig @@ -17,13 +17,6 @@ config DRM_AMD_DC_PRE_VEGA by default. This includes Polaris, Carrizo, Tonga, Bonaire, and Hawaii. -config DRM_AMD_DC_DCE12_0 - bool "Vega10 family" - depends on DRM_AMD_DC - help - Choose this option if you want to have - VG family for display engine. - config DEBUG_KERNEL_DC bool "Enable kgdb break in DC" depends on DRM_AMD_DC 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 9157772a0af3..97d949affcfb 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1123,9 +1123,7 @@ int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) case CHIP_POLARIS11: case CHIP_POLARIS10: case CHIP_POLARIS12: -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) case CHIP_VEGA10: -#endif if (dce110_register_irq_handlers(dm->adev)) { DRM_ERROR("DM: Failed to initialize IRQ\n"); return -1; @@ -1392,13 +1390,11 @@ static int dm_early_init(void *handle) adev->mode_info.num_hpd = 6; adev->mode_info.num_dig = 6; break; -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) case CHIP_VEGA10: adev->mode_info.num_crtc = 6; adev->mode_info.num_hpd = 6; adev->mode_info.num_dig = 6; break; -#endif default: DRM_ERROR("Usupported ASIC type: 0x%X\n", adev->asic_type); return -EINVAL; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c index df53092abc39..a8a53b85905a 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c @@ -402,7 +402,6 @@ bool dm_pp_notify_wm_clock_changes( return false; } -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) bool dm_pp_notify_wm_clock_changes_soc15( const struct dc_context *ctx, struct dm_pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges) @@ -410,7 +409,6 @@ bool dm_pp_notify_wm_clock_changes_soc15( /* TODO: to be implemented */ return false; } -#endif bool dm_pp_apply_power_level_change_request( const struct dc_context *ctx, diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 01aaf968854d..1c1c643439b8 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -523,7 +523,6 @@ static void fill_plane_attributes_from_fb( surface->tiling_info.gfx8.pipe_config = AMDGPU_TILING_GET(tiling_flags, PIPE_CONFIG); -#if defined (CONFIG_DRM_AMD_DC_DCE12_0) if (adev->asic_type == CHIP_VEGA10) { /* Fill GFX9 params */ surface->tiling_info.gfx9.num_pipes = @@ -540,7 +539,6 @@ static void fill_plane_attributes_from_fb( AMDGPU_TILING_GET(tiling_flags, SWIZZLE_MODE); surface->tiling_info.gfx9.shaderEnable = 1; } -#endif surface->plane_size.grph.surface_size.x = 0; diff --git a/drivers/gpu/drm/amd/display/dc/Makefile b/drivers/gpu/drm/amd/display/dc/Makefile index a580cab6bf56..1a79762425ea 100644 --- a/drivers/gpu/drm/amd/display/dc/Makefile +++ b/drivers/gpu/drm/amd/display/dc/Makefile @@ -4,10 +4,7 @@ DC_LIBS = basics bios calcs dce gpio i2caux irq virtual -ifdef CONFIG_DRM_AMD_DC_DCE12_0 DC_LIBS += dce120 -endif - DC_LIBS += dce112 DC_LIBS += dce110 DC_LIBS += dce100 diff --git a/drivers/gpu/drm/amd/display/dc/bios/Makefile b/drivers/gpu/drm/amd/display/dc/bios/Makefile index 770248429a81..a26cc605462d 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/Makefile +++ b/drivers/gpu/drm/amd/display/dc/bios/Makefile @@ -4,9 +4,7 @@ BIOS = bios_parser.o bios_parser_interface.o bios_parser_helper.o command_table.o command_table_helper.o -ifdef CONFIG_DRM_AMD_DC_DCE12_0 BIOS += command_table2.o command_table_helper2.o bios_parser2.o -endif AMD_DAL_BIOS = $(addprefix $(AMDDALPATH)/dc/bios/,$(BIOS)) @@ -26,6 +24,4 @@ AMD_DISPLAY_FILES += $(AMDDALPATH)/dc/bios/dce110/command_table_helper_dce110.o AMD_DISPLAY_FILES += $(AMDDALPATH)/dc/bios/dce112/command_table_helper_dce112.o -ifdef CONFIG_DRM_AMD_DC_DCE12_0 AMD_DISPLAY_FILES += $(AMDDALPATH)/dc/bios/dce112/command_table_helper2_dce112.o -endif diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_interface.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_interface.c index 7fe2a791ef42..0079a1e26efd 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_interface.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_interface.c @@ -29,9 +29,7 @@ #include "bios_parser_interface.h" #include "bios_parser.h" -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) #include "bios_parser2.h" -#endif struct dc_bios *dal_bios_parser_create( @@ -40,17 +38,11 @@ struct dc_bios *dal_bios_parser_create( { struct dc_bios *bios = NULL; -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) bios = firmware_parser_create(init, dce_version); + /* Fall back to old bios parser for older asics */ if (bios == NULL) - /* TODO: remove dce_version from bios_parser. - * cannot remove today because dal enum to bp enum translation is dce specific - */ bios = bios_parser_create(init, dce_version); -#else - bios = bios_parser_create(init, dce_version); -#endif return bios; } diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c index b0dcad260be6..1cc3df1d5698 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c @@ -53,11 +53,9 @@ bool dal_bios_parser_init_cmd_tbl_helper2( case DCE_VERSION_11_2: *h = dal_cmd_tbl_helper_dce112_get_table2(); return true; -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) case DCE_VERSION_12_0: *h = dal_cmd_tbl_helper_dce112_get_table2(); return true; -#endif default: /* Unsupported DCE */ diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c index aa98762346d2..c855e49eb116 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c @@ -50,10 +50,8 @@ static enum bw_calcs_version bw_calcs_version_from_asic_id(struct hw_asic_id asi return BW_CALCS_VERSION_POLARIS11; return BW_CALCS_VERSION_INVALID; -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) case FAMILY_AI: return BW_CALCS_VERSION_VEGA10; -#endif default: return BW_CALCS_VERSION_INVALID; @@ -2435,7 +2433,6 @@ void bw_calcs_init(struct bw_calcs_dceip *bw_dceip, dceip.scatter_gather_pte_request_rows_in_tiling_mode = 2; dceip.mcifwr_all_surfaces_burst_time = bw_int_to_fixed(0); break; -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) case BW_CALCS_VERSION_VEGA10: vbios.memory_type = bw_def_hbm; vbios.dram_channel_width_in_bits = 128; @@ -2546,7 +2543,6 @@ void bw_calcs_init(struct bw_calcs_dceip *bw_dceip, dceip.scatter_gather_pte_request_rows_in_tiling_mode = 2; dceip.mcifwr_all_surfaces_burst_time = bw_int_to_fixed(0); break; -#endif default: break; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 28ed8eaee1ff..d6041e842347 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1815,7 +1815,6 @@ void dc_link_remove_remote_sink(const struct dc_link *link, const struct dc_sink } } -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) bool dc_init_dchub(struct dc *dc, struct dchub_init_data *dh_data) { int i; @@ -1842,5 +1841,4 @@ bool dc_init_dchub(struct dc *dc, struct dchub_init_data *dh_data) return true; } -#endif diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c index 079558ab81c0..fb48b8909e7f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c @@ -142,10 +142,8 @@ void pre_surface_trace( surface->rotation, surface->stereo_format); -#if defined (CONFIG_DRM_AMD_DC_DCE12_0) SURFACE_TRACE("surface->tiling_info.gfx9.swizzle = %d;\n", surface->tiling_info.gfx9.swizzle); -#endif SURFACE_TRACE("\n"); } @@ -228,10 +226,8 @@ void update_surface_trace( update->plane_info->tiling_info.gfx8.array_mode, update->plane_info->visible); - #if defined (CONFIG_DRM_AMD_DC_DCE12_0) - SURFACE_TRACE("surface->tiling_info.gfx9.swizzle = %d;\n", + SURFACE_TRACE("surface->tiling_info.gfx9.swizzle = %d;\n", update->plane_info->tiling_info.gfx9.swizzle); - #endif } if (update->scaling_info) { diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index f13da7c227f4..74dd272d7452 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1217,7 +1217,6 @@ static enum dc_status enable_link_dp(struct pipe_ctx *pipe_ctx) pipe_ctx->dis_clk->funcs->set_min_clocks_state( pipe_ctx->dis_clk, DM_PP_CLOCKS_STATE_NOMINAL); } else { -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) uint32_t dp_phyclk_in_khz; const struct clocks_value clocks_value = pipe_ctx->dis_clk->cur_clocks_value; @@ -1235,7 +1234,6 @@ static enum dc_status enable_link_dp(struct pipe_ctx *pipe_ctx) false, true); } -#endif } } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 77ef3304d2bc..ad37d0efca2e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -39,9 +39,7 @@ #include "dce100/dce100_resource.h" #include "dce110/dce110_resource.h" #include "dce112/dce112_resource.h" -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) #include "dce120/dce120_resource.h" -#endif enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id) { @@ -68,11 +66,9 @@ enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id) dc_version = DCE_VERSION_11_2; } break; -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) case FAMILY_AI: dc_version = DCE_VERSION_12_0; break; -#endif default: dc_version = DCE_VERSION_UNKNOWN; break; @@ -105,12 +101,10 @@ struct resource_pool *dc_create_resource_pool( res_pool = dce112_create_resource_pool( num_virtual_links, dc); break; -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) case DCE_VERSION_12_0: res_pool = dce120_create_resource_pool( num_virtual_links, dc); break; -#endif default: break; } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index bc15065e489b..106addc937ca 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -55,9 +55,7 @@ struct dc_caps { struct dc_dcc_surface_param { enum surface_pixel_format format; struct dc_size surface_size; -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) enum swizzle_mode_values swizzle_mode; -#endif enum dc_scan_direction scan; }; @@ -146,9 +144,7 @@ struct dc_debug { bool disable_stutter; bool disable_dcc; bool disable_dfs_bypass; -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) bool disable_pplib_clock_request; -#endif bool disable_clock_gate; bool disable_dmcu; bool force_abm_enable; @@ -163,7 +159,6 @@ struct dc { struct dc_debug debug; }; -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) enum frame_buffer_mode { FRAME_BUFFER_MODE_LOCAL_ONLY = 0, FRAME_BUFFER_MODE_ZFB_ONLY, @@ -178,7 +173,6 @@ struct dchub_init_data { uint64_t zfb_size_in_byte; enum frame_buffer_mode fb_mode; }; -#endif struct dc_init_data { struct hw_asic_id asic_id; @@ -200,9 +194,7 @@ struct dc *dc_create(const struct dc_init_data *init_params); void dc_destroy(struct dc **dc); -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) bool dc_init_dchub(struct dc *dc, struct dchub_init_data *dh_data); -#endif /******************************************************************************* * Surface Interfaces diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index 63813404276d..33e3377f69fe 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -259,7 +259,6 @@ enum tile_mode_values { DC_ADDR_SURF_MICRO_TILING_NON_DISPLAY = 0x1, }; -#if defined (CONFIG_DRM_AMD_DC_DCE12_0) enum swizzle_mode_values { DC_SW_LINEAR = 0, DC_SW_256B_S = 1, @@ -287,7 +286,6 @@ enum swizzle_mode_values { DC_SW_VAR_R_X = 31, DC_SW_MAX }; -#endif union dc_tiling_info { @@ -353,7 +351,6 @@ union dc_tiling_info { enum array_mode_values array_mode; } gfx8; -#if defined (CONFIG_DRM_AMD_DC_DCE12_0) struct { unsigned int num_pipes; unsigned int num_banks; @@ -368,7 +365,6 @@ union dc_tiling_info { bool rb_aligned; bool pipe_aligned; } gfx9; -#endif }; /* Rotation angle */ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index f53dc157db97..bd4524ef3a37 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -585,9 +585,7 @@ static uint32_t dce110_get_pix_clk_dividers( pll_settings, pix_clk_params); break; case DCE_VERSION_11_2: -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) case DCE_VERSION_12_0: -#endif dce112_get_pix_clk_dividers_helper(clk_src, pll_settings, pix_clk_params); break; @@ -871,9 +869,7 @@ static bool dce110_program_pix_clk( break; case DCE_VERSION_11_2: -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) case DCE_VERSION_12_0: -#endif if (clock_source->id != CLOCK_SOURCE_ID_DP_DTO) { bp_pc_params.flags.SET_GENLOCK_REF_DIV_SRC = pll_settings->use_external_clk; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c index 9c743e51c091..263f8900e39c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c @@ -80,7 +80,6 @@ static struct state_dependent_clocks dce112_max_clks_by_state[] = { /*ClocksStatePerformance*/ { .display_clk_khz = 1132000, .pixel_clk_khz = 600000 } }; -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) static struct state_dependent_clocks dce120_max_clks_by_state[] = { /*ClocksStateInvalid - should not be used*/ { .display_clk_khz = 0, .pixel_clk_khz = 0 }, @@ -92,7 +91,6 @@ static struct state_dependent_clocks dce120_max_clks_by_state[] = { { .display_clk_khz = 670000, .pixel_clk_khz = 600000 }, /*ClocksStatePerformance*/ { .display_clk_khz = 1133000, .pixel_clk_khz = 600000 } }; -#endif /* Starting point for each divider range.*/ enum dce_divider_range_start { @@ -497,7 +495,6 @@ static void dce_clock_read_ss_info(struct dce_disp_clk *clk_dce) } } -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) static bool dce_apply_clock_voltage_request( struct display_clock *clk, enum dm_pp_clock_type clocks_type, @@ -592,7 +589,6 @@ static const struct display_clock_funcs dce120_funcs = { .apply_clock_voltage_request = dce_apply_clock_voltage_request, .set_clock = dce112_set_clock }; -#endif static const struct display_clock_funcs dce112_funcs = { .get_dp_ref_clk_frequency = dce_clocks_get_dp_ref_freq, @@ -734,7 +730,6 @@ struct display_clock *dce112_disp_clk_create( return &clk_dce->base; } -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) struct display_clock *dce120_disp_clk_create( struct dc_context *ctx, const struct dce_disp_clk_registers *regs, @@ -770,7 +765,6 @@ struct display_clock *dce120_disp_clk_create( return &clk_dce->base; } -#endif void dce_disp_clk_destroy(struct display_clock **disp_clk) { diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h index 18787f6d4e2a..2fd00e45395c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h @@ -45,13 +45,11 @@ CLK_SF(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, mask_sh), \ CLK_SF(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, mask_sh) -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) #define CLK_COMMON_MASK_SH_LIST_SOC_BASE(mask_sh) \ CLK_SF(DCCG_DFS_DPREFCLK_CNTL, DPREFCLK_SRC_SEL, mask_sh), \ CLK_SF(DCCG_DFS_DENTIST_DISPCLK_CNTL, DENTIST_DPREFCLK_WDIVIDER, mask_sh), \ CLK_SF(DCCG_DFS_MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, mask_sh), \ CLK_SF(DCCG_DFS_MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, mask_sh) -#endif #define CLK_REG_FIELD_LIST(type) \ type DPREFCLK_SRC_SEL; \ @@ -126,10 +124,8 @@ struct dce_disp_clk { int gpu_pll_ss_divider; -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) /* max disp_clk from PPLIB for max validation display clock*/ int max_displ_clk_in_khz; -#endif }; @@ -151,13 +147,11 @@ struct display_clock *dce112_disp_clk_create( const struct dce_disp_clk_shift *clk_shift, const struct dce_disp_clk_mask *clk_mask); -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) struct display_clock *dce120_disp_clk_create( struct dc_context *ctx, const struct dce_disp_clk_registers *regs, const struct dce_disp_clk_shift *clk_shift, const struct dce_disp_clk_mask *clk_mask); -#endif void dce_disp_clk_destroy(struct display_clock **disp_clk); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index ff7984b08095..c66585188ecd 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -186,13 +186,11 @@ struct dce_hwseq_registers { HWSEQ_DCE10_MASK_SH_LIST(mask_sh),\ HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, CRTC0_) -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) #define HWSEQ_DCE12_MASK_SH_LIST(mask_sh)\ HWSEQ_DCEF_MASK_SH_LIST(mask_sh, DCFE0_DCFE_),\ HWSEQ_BLND_MASK_SH_LIST(mask_sh, BLND0_BLND_),\ HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_),\ HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, CRTC0_) -#endif #define HWSEQ_REG_FIED_LIST(type) \ type DCFE_CLOCK_ENABLE; \ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h index f6a1006a6472..25ba583dbb8f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h @@ -31,12 +31,10 @@ #define TO_DCE110_LINK_ENC(link_encoder)\ container_of(link_encoder, struct dce110_link_encoder, base) -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) /* Not found regs in dce120 spec * BIOS_SCRATCH_2 * DP_DPHY_INTERNAL_CTRL */ -#endif #define AUX_REG_LIST(id)\ SRI(AUX_CONTROL, DP_AUX, id), \ @@ -86,16 +84,14 @@ SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ SR(DCI_MEM_PWR_STATUS) -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) - #define LE_DCE120_REG_LIST(id)\ - LE_COMMON_REG_LIST_BASE(id), \ - SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ - SR(DCI_MEM_PWR_STATUS) -#endif +#define LE_DCE120_REG_LIST(id)\ + LE_COMMON_REG_LIST_BASE(id), \ + SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ + SR(DCI_MEM_PWR_STATUS) - #define LE_DCE80_REG_LIST(id)\ - SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ - LE_COMMON_REG_LIST_BASE(id) +#define LE_DCE80_REG_LIST(id)\ + SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ + LE_COMMON_REG_LIST_BASE(id) struct dce110_link_enc_aux_registers { diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c index c494f712b5b5..7acd87152811 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c @@ -187,7 +187,7 @@ static void program_nbp_watermark(struct mem_input *mi, REG_UPDATE(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, NB_PSTATE_CHANGE_WATERMARK, nbp_wm); } -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + if (REG(DPG_PIPE_LOW_POWER_CONTROL)) { REG_UPDATE(DPG_WATERMARK_MASK_CONTROL, PSTATE_CHANGE_WATERMARK_MASK, wm_select); @@ -200,7 +200,6 @@ static void program_nbp_watermark(struct mem_input *mi, REG_UPDATE(DPG_PIPE_LOW_POWER_CONTROL, PSTATE_CHANGE_WATERMARK, nbp_wm); } -#endif } static void program_stutter_watermark(struct mem_input *mi, @@ -210,12 +209,10 @@ static void program_stutter_watermark(struct mem_input *mi, REG_UPDATE(DPG_WATERMARK_MASK_CONTROL, STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK, wm_select); -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) if (REG(DPG_PIPE_STUTTER_CONTROL2)) REG_UPDATE(DPG_PIPE_STUTTER_CONTROL2, STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark); else -#endif REG_UPDATE(DPG_PIPE_STUTTER_CONTROL, STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark); } @@ -254,7 +251,6 @@ void dce_mem_input_program_display_marks(struct mem_input *mi, static void program_tiling(struct mem_input *mi, const union dc_tiling_info *info) { -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) if (mi->masks->GRPH_SW_MODE) { /* GFX9 */ REG_UPDATE_6(GRPH_CONTROL, GRPH_SW_MODE, info->gfx9.swizzle, @@ -268,7 +264,7 @@ static void program_tiling(struct mem_input *mi, GRPH_Z, 0); */ } -#endif + if (mi->masks->GRPH_ARRAY_MODE) { /* GFX8 */ REG_UPDATE_9(GRPH_CONTROL, GRPH_NUM_BANKS, info->gfx8.num_banks, diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h index 9e18c2a34e85..6af533bdf98c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h @@ -58,14 +58,12 @@ MI_DCE11_2_REG_LIST(id),\ MI_DCE_PTE_REG_LIST(id) -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) #define MI_DCE12_REG_LIST(id)\ MI_DCE_BASE_REG_LIST(id),\ MI_DCE_PTE_REG_LIST(id),\ SRI(GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT, DCP, id),\ SRI(DPG_PIPE_STUTTER_CONTROL2, DMIF_PG, id),\ SRI(DPG_PIPE_LOW_POWER_CONTROL, DMIF_PG, id) -#endif struct dce_mem_input_registers { /* DCP */ @@ -172,7 +170,6 @@ struct dce_mem_input_registers { MI_DCE11_2_MASK_SH_LIST(mask_sh),\ MI_DCP_PTE_MASK_SH_LIST(mask_sh, ) -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) #define MI_GFX9_TILE_MASK_SH_LIST(mask_sh, blk)\ SFB(blk, GRPH_CONTROL, GRPH_SW_MODE, mask_sh),\ SFB(blk, GRPH_CONTROL, GRPH_SE_ENABLE, mask_sh),\ @@ -195,7 +192,6 @@ struct dce_mem_input_registers { MI_DMIF_PG_MASK_SH_LIST(mask_sh, DMIF_PG0_),\ MI_DCE12_DMIF_PG_MASK_SH_LIST(mask_sh, DMIF_PG0_),\ MI_GFX9_TILE_MASK_SH_LIST(mask_sh, DCP0_) -#endif #define MI_REG_FIELD_LIST(type) \ type GRPH_ENABLE; \ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h index 4784ced6fc80..03ce9ba50b64 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h @@ -107,13 +107,11 @@ enum dce110_opp_reg_type { SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX, FMT, id), \ SRI(CONTROL, FMT_MEMORY, id) -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) #define OPP_DCE_120_REG_LIST(id) \ OPP_COMMON_REG_LIST_BASE(id), \ SRI(DCFE_MEM_PWR_CTRL, DCFE, id), \ SRI(DCFE_MEM_PWR_STATUS, DCFE, id), \ SRI(CONTROL, FMT_MEMORY, id) -#endif #define OPP_SF(reg_name, field_name, post_fix)\ .field_name = reg_name ## __ ## field_name ## post_fix @@ -205,7 +203,6 @@ enum dce110_opp_reg_type { OPP_SF(DCFE_MEM_LIGHT_SLEEP_CNTL, DCP_LUT_LIGHT_SLEEP_DIS, mask_sh),\ OPP_SF(DCFE_MEM_LIGHT_SLEEP_CNTL, REGAMMA_LUT_MEM_PWR_STATE, mask_sh) -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) #define OPP_COMMON_MASK_SH_LIST_DCE_120(mask_sh)\ OPP_SF(DCFE0_DCFE_MEM_PWR_CTRL, DCP_REGAMMA_MEM_PWR_DIS, mask_sh),\ OPP_SF(DCFE0_DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, mask_sh),\ @@ -267,7 +264,6 @@ enum dce110_opp_reg_type { OPP_SF(FMT0_FMT_CONTROL, FMT_SUBSAMPLING_MODE, mask_sh),\ OPP_SF(FMT0_FMT_CONTROL, FMT_SUBSAMPLING_ORDER, mask_sh),\ OPP_SF(FMT0_FMT_CONTROL, FMT_CBCR_BIT_REDUCTION_BYPASS, mask_sh) -#endif #define OPP_REG_FIELD_LIST(type) \ type DCP_REGAMMA_MEM_PWR_DIS; \ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h index c784c1b961c6..c2f4050fc6dc 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h @@ -187,7 +187,6 @@ #define SE_COMMON_MASK_SH_LIST_DCE_COMMON(mask_sh)\ SE_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh) -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) #define SE_COMMON_MASK_SH_LIST_SOC_BASE(mask_sh)\ SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_INDEX, mask_sh),\ SE_SF(DIG0_AFMT_GENERIC_HDR, AFMT_GENERIC_HB0, mask_sh),\ @@ -267,7 +266,6 @@ SE_SF(DIG0_HDMI_CONTROL, HDMI_CLOCK_CHANNEL_RATE, mask_sh),\ SE_SF(DIG0_DIG_FE_CNTL, TMDS_PIXEL_ENCODING, mask_sh),\ SE_SF(DIG0_DIG_FE_CNTL, TMDS_COLOR_FORMAT, mask_sh) -#endif #define SE_COMMON_MASK_SH_LIST_SOC(mask_sh)\ SE_COMMON_MASK_SH_LIST_SOC_BASE(mask_sh) @@ -294,7 +292,6 @@ SE_SF(DIG_FE_CNTL, TMDS_COLOR_FORMAT, mask_sh),\ SE_SF(DP_VID_TIMING, DP_VID_M_DOUBLE_VALUE_EN, mask_sh) -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) #define SE_COMMON_MASK_SH_LIST_DCE120(mask_sh)\ SE_COMMON_MASK_SH_LIST_SOC(mask_sh),\ SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC0_UPDATE, mask_sh),\ @@ -307,7 +304,6 @@ SE_SF(DP0_DP_SEC_CNTL, DP_SEC_AVI_ENABLE, mask_sh),\ SE_SF(DIG0_AFMT_AVI_INFO3, AFMT_AVI_INFO_VERSION, mask_sh),\ SE_SF(DP0_DP_VID_TIMING, DP_VID_M_DOUBLE_VALUE_EN, mask_sh) -#endif struct dce_stream_encoder_shift { uint8_t AFMT_GENERIC_INDEX; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h index aa6bc4fc80c5..da2a02434665 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h @@ -153,7 +153,6 @@ XFM_SF(DCFE_MEM_PWR_STATUS, SCL_COEFF_MEM_PWR_STATE, mask_sh), \ XFM_SF(SCL_MODE, SCL_PSCL_EN, mask_sh) -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) #define XFM_COMMON_MASK_SH_LIST_SOC_BASE(mask_sh) \ XFM_SF(DCP0_OUT_CLAMP_CONTROL_B_CB, OUT_CLAMP_MIN_B_CB, mask_sh), \ XFM_SF(DCP0_OUT_CLAMP_CONTROL_B_CB, OUT_CLAMP_MAX_B_CB, mask_sh), \ @@ -219,7 +218,6 @@ XFM_SF(DCFE0_DCFE_MEM_PWR_CTRL, SCL_COEFF_MEM_PWR_DIS, mask_sh), \ XFM_SF(DCFE0_DCFE_MEM_PWR_STATUS, SCL_COEFF_MEM_PWR_STATE, mask_sh), \ XFM_SF(SCL0_SCL_MODE, SCL_PSCL_EN, mask_sh) -#endif #define XFM_REG_FIELD_LIST(type) \ type OUT_CLAMP_MIN_B_CB; \ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 66d5f346f195..cb7a673e15e9 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1427,8 +1427,6 @@ static void apply_min_clocks( return; } - /* TODOFPGA */ -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) /* TODO: This is incorrect. Figure out how to fix. */ pipe_ctx->dis_clk->funcs->apply_clock_voltage_request( pipe_ctx->dis_clk, @@ -1451,7 +1449,6 @@ static void apply_min_clocks( pre_mode_set, false); return; -#endif } /* get the required state based on state dependent clocks: @@ -1468,7 +1465,6 @@ static void apply_min_clocks( pipe_ctx->dis_clk->funcs->set_min_clocks_state( pipe_ctx->dis_clk, *clocks_state); } else { -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) pipe_ctx->dis_clk->funcs->apply_clock_voltage_request( pipe_ctx->dis_clk, DM_PP_CLOCK_TYPE_DISPLAY_CLK, @@ -1489,7 +1485,6 @@ static void apply_min_clocks( req_clocks.pixel_clk_khz, pre_mode_set, false); -#endif } } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c index 3ffb845f843a..a20feaedfca4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c @@ -409,9 +409,7 @@ static struct mem_input_funcs dce110_mem_input_funcs = { dce_mem_input_program_surface_config, .mem_input_is_flip_pending = dce110_mem_input_is_flip_pending, -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) .mem_input_update_dchub = NULL -#endif }; /*****************************************/ /* Constructor, Destructor */ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h index 55f0a94e7cae..378509b8e56c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h @@ -108,9 +108,7 @@ struct dce110_timing_generator { uint32_t min_h_front_porch; uint32_t min_h_back_porch; -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) /* DCE 12 */ -#endif uint32_t min_h_sync_width; uint32_t min_v_sync_width; uint32_t min_v_blank; diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index 9a1984b36592..efa58889058b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -909,6 +909,7 @@ static bool construct( { unsigned int i; struct dc_context *ctx = dc->ctx; + struct irq_service_init_data irq_init_data; ctx->dc_bios->regs = &bios_regs; @@ -997,15 +998,10 @@ static bool construct( goto res_create_fail; } - { - #if defined(CONFIG_DRM_AMD_DC_DCE12_0) - struct irq_service_init_data init_data; - init_data.ctx = dc->ctx; - pool->base.irqs = dal_irq_service_dce120_create(&init_data); - if (!pool->base.irqs) - goto irqs_create_fail; - #endif - } + irq_init_data.ctx = dc->ctx; + pool->base.irqs = dal_irq_service_dce120_create(&irq_init_data); + if (!pool->base.irqs) + goto irqs_create_fail; for (i = 0; i < pool->base.pipe_count; i++) { pool->base.timing_generators[i] = diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c index 2f22931f457b..ebb8df3cdf4a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c @@ -54,9 +54,7 @@ static struct mem_input_funcs dce80_mem_input_funcs = { dce_mem_input_program_surface_config, .mem_input_is_flip_pending = dce110_mem_input_is_flip_pending, -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) .mem_input_update_dchub = NULL -#endif }; /*****************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/dm_services.h b/drivers/gpu/drm/amd/display/dc/dm_services.h index bdc7cb045eed..cf6ecfcadd5e 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services.h @@ -192,7 +192,6 @@ unsigned int generic_reg_wait(const struct dc_context *ctx, unsigned int delay_between_poll_us, unsigned int time_out_num_tries, const char *func_name); -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) /* These macros need to be used with soc15 registers in order to retrieve * the actual offset. @@ -274,7 +273,6 @@ static inline bool wait_reg_func( 20000,\ 200000) -#endif /************************************** * Power Play (PP) interfaces **************************************/ @@ -337,11 +335,9 @@ bool dm_pp_notify_wm_clock_changes( const struct dc_context *ctx, struct dm_pp_wm_sets_with_clock_ranges *wm_with_clock_ranges); -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) bool dm_pp_notify_wm_clock_changes_soc15( const struct dc_context *ctx, struct dm_pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges); -#endif /* DAL calls this function to notify PP about completion of Mode Set. * For PP it means that current DCE clocks are those which were returned diff --git a/drivers/gpu/drm/amd/display/dc/dm_services_types.h b/drivers/gpu/drm/amd/display/dc/dm_services_types.h index 8d2661583f21..c631dec489e7 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services_types.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services_types.h @@ -141,7 +141,6 @@ struct dm_pp_wm_sets_with_clock_ranges { struct dm_pp_clock_range_for_wm_set wm_clk_ranges[MAX_WM_SETS]; }; -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) struct dm_pp_clock_range_for_dmif_wm_set_soc15 { enum dm_pp_wm_set_id wm_set_id; uint32_t wm_min_dcfclk_clk_in_khz; @@ -166,7 +165,6 @@ struct dm_pp_wm_sets_with_clock_ranges_soc15 { struct dm_pp_clock_range_for_mcif_wm_set_soc15 wm_mcif_clocks_ranges[MAX_WM_SETS]; }; -#endif #define MAX_DISPLAY_CONFIGS 6 diff --git a/drivers/gpu/drm/amd/display/dc/gpio/Makefile b/drivers/gpu/drm/amd/display/dc/gpio/Makefile index 8cf12a8ca28f..5e831aff4830 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/Makefile +++ b/drivers/gpu/drm/amd/display/dc/gpio/Makefile @@ -31,13 +31,11 @@ AMD_DISPLAY_FILES += $(AMD_DAL_GPIO_DCE110) ############################################################################### # DCE 12x ############################################################################### -ifdef CONFIG_DRM_AMD_DC_DCE12_0 GPIO_DCE120 = hw_translate_dce120.o hw_factory_dce120.o AMD_DAL_GPIO_DCE120 = $(addprefix $(AMDDALPATH)/dc/gpio/dce120/,$(GPIO_DCE120)) AMD_DISPLAY_FILES += $(AMD_DAL_GPIO_DCE120) -endif ############################################################################### # Diagnostics on FPGA diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c index 66ea3b31b980..29ba83d2c211 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c @@ -44,9 +44,7 @@ #include "dce110/hw_factory_dce110.h" -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) #include "dce120/hw_factory_dce120.h" -#endif #include "diagnostics/hw_factory_diag.h" @@ -76,11 +74,9 @@ bool dal_hw_factory_init( case DCE_VERSION_11_2: dal_hw_factory_dce110_init(factory); return true; -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) case DCE_VERSION_12_0: dal_hw_factory_dce120_init(factory); return true; -#endif default: ASSERT_CRITICAL(false); return false; diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c index 10e86447f179..872edda54536 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c @@ -42,9 +42,7 @@ #include "dce80/hw_translate_dce80.h" #include "dce110/hw_translate_dce110.h" -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) #include "dce120/hw_translate_dce120.h" -#endif #include "diagnostics/hw_translate_diag.h" /* @@ -70,11 +68,9 @@ bool dal_hw_translate_init( case DCE_VERSION_11_2: dal_hw_translate_dce110_init(translate); return true; -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) case DCE_VERSION_12_0: dal_hw_translate_dce120_init(translate); return true; -#endif default: BREAK_TO_DEBUGGER(); return false; diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/Makefile b/drivers/gpu/drm/amd/display/dc/i2caux/Makefile index 99aa5d8fb9a7..a636768d06d5 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/Makefile +++ b/drivers/gpu/drm/amd/display/dc/i2caux/Makefile @@ -50,13 +50,11 @@ AMD_DISPLAY_FILES += $(AMD_DAL_I2CAUX_DCE112) ############################################################################### # DCE 120 family ############################################################################### -ifdef CONFIG_DRM_AMD_DC_DCE12_0 I2CAUX_DCE120 = i2caux_dce120.o AMD_DAL_I2CAUX_DCE120 = $(addprefix $(AMDDALPATH)/dc/i2caux/dce120/,$(I2CAUX_DCE120)) AMD_DISPLAY_FILES += $(AMD_DAL_I2CAUX_DCE120) -endif ############################################################################### # Diagnostics on FPGA diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c index ea3bd75e0555..bd84b932aaae 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c @@ -57,9 +57,7 @@ #include "dce112/i2caux_dce112.h" -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) #include "dce120/i2caux_dce120.h" -#endif #include "diagnostics/i2caux_diag.h" @@ -84,10 +82,8 @@ struct i2caux *dal_i2caux_create( return dal_i2caux_dce110_create(ctx); case DCE_VERSION_10_0: return dal_i2caux_dce100_create(ctx); - #if defined(CONFIG_DRM_AMD_DC_DCE12_0) case DCE_VERSION_12_0: return dal_i2caux_dce120_create(ctx); - #endif default: BREAK_TO_DEBUGGER(); return NULL; diff --git a/drivers/gpu/drm/amd/display/dc/inc/bandwidth_calcs.h b/drivers/gpu/drm/amd/display/dc/inc/bandwidth_calcs.h index a7eaecd32aea..81fab9ef3637 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/bandwidth_calcs.h +++ b/drivers/gpu/drm/amd/display/dc/inc/bandwidth_calcs.h @@ -40,9 +40,7 @@ enum bw_calcs_version { BW_CALCS_VERSION_POLARIS10, BW_CALCS_VERSION_POLARIS11, BW_CALCS_VERSION_STONEY, -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) BW_CALCS_VERSION_VEGA10 -#endif }; /******************************************************************************* diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h b/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h index bf77aa6172e1..79aa75c150ec 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h @@ -28,7 +28,6 @@ #include "dm_services_types.h" -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) struct clocks_value { int dispclk_in_khz; int max_pixelclk_in_khz; @@ -38,7 +37,6 @@ struct clocks_value { bool pixelclk_notify_pplib_done; bool phyclk_notigy_pplib_done; }; -#endif /* Structure containing all state-dependent clocks * (dependent on "enum clocks_state") */ @@ -53,9 +51,7 @@ struct display_clock { enum dm_pp_clocks_state max_clks_state; enum dm_pp_clocks_state cur_min_clks_state; -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) struct clocks_value cur_clocks_value; -#endif }; struct display_clock_funcs { @@ -71,14 +67,12 @@ struct display_clock_funcs { int (*get_dp_ref_clk_frequency)(struct display_clock *disp_clk); -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) bool (*apply_clock_voltage_request)( struct display_clock *disp_clk, enum dm_pp_clock_type clocks_type, int clocks_in_khz, bool pre_mode_set, bool update_dp_phyclk); -#endif }; #endif /* __DISPLAY_CLOCK_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h index 6c0600696d02..7ec4027700d8 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h @@ -100,10 +100,8 @@ struct mem_input_funcs { bool (*mem_input_is_flip_pending)(struct mem_input *mem_input); -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) void (*mem_input_update_dchub)(struct mem_input *mem_input, struct dchub_init_data *dh_data); -#endif }; #endif diff --git a/drivers/gpu/drm/amd/display/dc/irq/Makefile b/drivers/gpu/drm/amd/display/dc/irq/Makefile index 140e49811dd1..222f36e3074f 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/Makefile +++ b/drivers/gpu/drm/amd/display/dc/irq/Makefile @@ -30,11 +30,9 @@ AMD_DISPLAY_FILES += $(AMD_DAL_IRQ_DCE11) ############################################################################### # DCE 12x ############################################################################### -ifdef CONFIG_DRM_AMD_DC_DCE12_0 IRQ_DCE12 = irq_service_dce120.o AMD_DAL_IRQ_DCE12 = $(addprefix $(AMDDALPATH)/dc/irq/dce120/,$(IRQ_DCE12)) AMD_DISPLAY_FILES += $(AMD_DAL_IRQ_DCE12) -endif diff --git a/drivers/gpu/drm/amd/display/dc/irq/irq_service.c b/drivers/gpu/drm/amd/display/dc/irq/irq_service.c index a1b6d83b1cbb..5255c14254df 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/irq_service.c +++ b/drivers/gpu/drm/amd/display/dc/irq/irq_service.c @@ -33,9 +33,7 @@ #include "dce80/irq_service_dce80.h" -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) #include "dce120/irq_service_dce120.h" -#endif #include "reg_helper.h" #include "irq_service.h" diff --git a/drivers/gpu/drm/amd/display/include/dal_asic_id.h b/drivers/gpu/drm/amd/display/include/dal_asic_id.h index 15c0b8c14b30..6dab058f8f3c 100644 --- a/drivers/gpu/drm/amd/display/include/dal_asic_id.h +++ b/drivers/gpu/drm/amd/display/include/dal_asic_id.h @@ -123,9 +123,7 @@ #define FAMILY_VI 130 /* Volcanic Islands: Iceland (V), Tonga (M) */ #define FAMILY_CZ 135 /* Carrizo */ -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) #define FAMILY_AI 141 -#endif #define FAMILY_UNKNOWN 0xFF diff --git a/drivers/gpu/drm/amd/display/include/dal_types.h b/drivers/gpu/drm/amd/display/include/dal_types.h index e24c1ef58d2f..0cefde14aa02 100644 --- a/drivers/gpu/drm/amd/display/include/dal_types.h +++ b/drivers/gpu/drm/amd/display/include/dal_types.h @@ -38,9 +38,7 @@ enum dce_version { DCE_VERSION_10_0, DCE_VERSION_11_0, DCE_VERSION_11_2, -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) DCE_VERSION_12_0, -#endif DCE_VERSION_MAX, }; -- cgit From ab587d4a654ea299bef20bf3d363f7faaea35e7d Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 19 Apr 2017 17:28:47 -0400 Subject: drm/amdgpu/soc15: enable dc on vega10 Add the DC display module to drive the DCE12 IP on vega10. Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/soc15.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c index 245a18aeb389..3d9a51d6e1aa 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15.c +++ b/drivers/gpu/drm/amd/amdgpu/soc15.c @@ -535,6 +535,12 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev) amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block); if (adev->enable_virtual_display || amdgpu_sriov_vf(adev)) amdgpu_ip_block_add(adev, &dce_virtual_ip_block); +#if defined(CONFIG_DRM_AMD_DC) + else if (amdgpu_device_has_dc_support(adev)) + amdgpu_ip_block_add(adev, &dm_ip_block); +#else +# warning "Enable CONFIG_DRM_AMD_DC for display support on SOC15." +#endif amdgpu_ip_block_add(adev, &gfx_v9_0_ip_block); amdgpu_ip_block_add(adev, &sdma_v4_0_ip_block); amdgpu_ip_block_add(adev, &uvd_v7_0_ip_block); -- cgit From a783e7b5182ba5df2916c7abda60b8e781bdb3aa Mon Sep 17 00:00:00 2001 From: Leon Elazar Date: Thu, 9 Mar 2017 14:38:15 -0500 Subject: drm/amd/display: adding new dc_update_surfaces_and_stream Signed-off-by: Leon Elazar Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 21 +++++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dc.h | 29 +++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index d6041e842347..228ef6b310e0 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1268,6 +1268,27 @@ enum surface_update_type dc_check_update_surfaces_for_stream( return overall_type; } +void dc_update_surfaces_and_stream(struct dc *dc, + struct dc_surface_update *surface_updates, int surface_count, + const struct dc_stream *dc_stream, + struct dc_stream_update *stream_update) +{ + const struct dc_stream_status *stream_status; + + stream_status = dc_stream_get_status(dc_stream); + ASSERT(stream_status); + if (!stream_status) + return; /* Cannot update stream that is not committed */ + + if (stream_update) { + dc->stream_funcs.stream_update_scaling(dc, dc_stream, + &stream_update->src, &stream_update->dst); + } + + dc_update_surfaces_for_stream(dc, surface_updates, + surface_count, dc_stream); +} + enum surface_update_type update_surface_trace_level = UPDATE_TYPE_FULL; void dc_update_surfaces_for_stream(struct dc *dc, diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 106addc937ca..b1bff597c0f7 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -433,6 +433,35 @@ struct dc_stream { /* TODO: CEA VIC */ }; +struct dc_stream_update { + + struct rect src; + + struct rect dst; + +}; + + +/* + * Setup stream attributes if no stream updates are provided + * there will be no impact on the stream parameters + * + * Set up surface attributes and associate to a stream + * The surfaces parameter is an absolute set of all surface active for the stream. + * If no surfaces are provided, the stream will be blanked; no memory read. + * Any flip related attribute changes must be done through this interface. + * + * After this call: + * Surfaces attributes are programmed and configured to be composed into stream. + * This does not trigger a flip. No surface address is programmed. + * + */ + +void dc_update_surfaces_and_stream(struct dc *dc, + struct dc_surface_update *surface_updates, int surface_count, + const struct dc_stream *dc_stream, + struct dc_stream_update *stream_update); + /* * Log the current stream state. */ -- cgit From 1de8c33bbde4115561a5b2e684be7af66b3f085d Mon Sep 17 00:00:00 2001 From: Logatharshan Thothiralingam Date: Thu, 9 Mar 2017 11:37:26 -0500 Subject: drm/amd/display: Fixed bandwidth calculation error when converting fractions [Problem] VSR greyed out [Root cause] When converting fractions, we were using the integer function, which let to a large display clock and the view was not supported [Solution] Change the integer to fraction functions Signed-off-by: Logatharshan Thothiralingam Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c index c855e49eb116..e47794398942 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c @@ -796,11 +796,11 @@ static void calculate_bandwidth( } else if (bw_leq(data->vsr[i], bw_int_to_fixed(1))) { data->lb_lines_in_per_line_out_in_middle_of_frame[i] = bw_int_to_fixed(1); - } - else if (bw_leq(data->vsr[i], bw_int_to_fixed(4 / 3))) { + } else if (bw_leq(data->vsr[i], + bw_frc_to_fixed(4, 3))) { data->lb_lines_in_per_line_out_in_middle_of_frame[i] = bw_div(bw_int_to_fixed(4), bw_int_to_fixed(3)); - } - else if (bw_leq(data->vsr[i], bw_int_to_fixed(6 / 4))) { + } else if (bw_leq(data->vsr[i], + bw_frc_to_fixed(6, 4))) { data->lb_lines_in_per_line_out_in_middle_of_frame[i] = bw_div(bw_int_to_fixed(6), bw_int_to_fixed(4)); } else if (bw_leq(data->vsr[i], bw_int_to_fixed(2))) { -- cgit From faddcb360c04f007966ffe8eabe3786655ba6a1a Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Tue, 14 Mar 2017 11:16:11 -0400 Subject: drm/amd/display: fix bw calc internal initialization error Signed-off-by: Dmytro Laktyushkin Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c index e47794398942..4820660f51d6 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c @@ -1341,12 +1341,12 @@ static void calculate_bandwidth( /*initialize variables*/ number_of_displays_enabled = 0; number_of_displays_enabled_with_margin = 0; - for (k = 0; k < maximum_number_of_surfaces; k++) { + for (k = 0; k <= maximum_number_of_surfaces - 1; k++) { if (data->enable[k]) { number_of_displays_enabled = number_of_displays_enabled + 1; } + data->display_pstate_change_enable[k] = 0; } - data->display_pstate_change_enable[maximum_number_of_surfaces - 1] = 0; for (i = 0; i <= 2; i++) { for (j = 0; j <= 7; j++) { data->min_dram_speed_change_margin[i][j] = bw_int_to_fixed(9999); -- cgit From ee8f63e1781eb3e4acdcff5324ca29b723aded45 Mon Sep 17 00:00:00 2001 From: Leon Elazar Date: Tue, 14 Mar 2017 11:54:31 -0400 Subject: drm/amd/display: changing the dc_update_surfaces_and_stream 1. Adding the ability to update the stream parameters during FULL_UPDATE type Signed-off-by: Leon Elazar Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 129 +++++++++++++++---------------- drivers/gpu/drm/amd/display/dc/dc.h | 1 + 2 files changed, 65 insertions(+), 65 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 228ef6b310e0..26f227ddd025 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1245,6 +1245,7 @@ enum surface_update_type dc_check_update_surfaces_for_stream( struct dc *dc, struct dc_surface_update *updates, int surface_count, + struct dc_stream_update *stream_update, const struct dc_stream_status *stream_status) { struct core_dc *core_dc = DC_TO_CORE(dc); @@ -1254,6 +1255,9 @@ enum surface_update_type dc_check_update_surfaces_for_stream( if (stream_status->surface_count != surface_count) return UPDATE_TYPE_FULL; + if (stream_update) + return UPDATE_TYPE_FULL; + for (i = 0 ; i < surface_count; i++) { enum surface_update_type type = det_surface_update(core_dc, &updates[i]); @@ -1268,39 +1272,27 @@ enum surface_update_type dc_check_update_surfaces_for_stream( return overall_type; } -void dc_update_surfaces_and_stream(struct dc *dc, +void dc_update_surfaces_for_stream(struct dc *dc, struct dc_surface_update *surface_updates, int surface_count, - const struct dc_stream *dc_stream, - struct dc_stream_update *stream_update) + const struct dc_stream *dc_stream) { - const struct dc_stream_status *stream_status; - - stream_status = dc_stream_get_status(dc_stream); - ASSERT(stream_status); - if (!stream_status) - return; /* Cannot update stream that is not committed */ - - if (stream_update) { - dc->stream_funcs.stream_update_scaling(dc, dc_stream, - &stream_update->src, &stream_update->dst); - } - - dc_update_surfaces_for_stream(dc, surface_updates, - surface_count, dc_stream); + dc_update_surfaces_and_stream(dc, surface_updates, surface_count, + dc_stream, NULL); } enum surface_update_type update_surface_trace_level = UPDATE_TYPE_FULL; -void dc_update_surfaces_for_stream(struct dc *dc, - struct dc_surface_update *updates, int surface_count, - const struct dc_stream *dc_stream) +void dc_update_surfaces_and_stream(struct dc *dc, + struct dc_surface_update *srf_updates, int surface_count, + const struct dc_stream *dc_stream, + struct dc_stream_update *stream_update) { struct core_dc *core_dc = DC_TO_CORE(dc); struct validate_context *context; int i, j; - enum surface_update_type update_type; const struct dc_stream_status *stream_status; + struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); stream_status = dc_stream_get_status(dc_stream); ASSERT(stream_status); @@ -1308,16 +1300,16 @@ void dc_update_surfaces_for_stream(struct dc *dc, return; /* Cannot commit surface to stream that is not committed */ update_type = dc_check_update_surfaces_for_stream( - dc, updates, surface_count, stream_status); + dc, srf_updates, surface_count, stream_update, stream_status); if (update_type >= update_surface_trace_level) - update_surface_trace(dc, updates, surface_count); + update_surface_trace(dc, srf_updates, surface_count); if (update_type >= UPDATE_TYPE_FULL) { const struct dc_surface *new_surfaces[MAX_SURFACES] = { 0 }; for (i = 0; i < surface_count; i++) - new_surfaces[i] = updates[i].surface; + new_surfaces[i] = srf_updates[i].surface; /* initialize scratch memory for building context */ context = core_dc->temp_flip_context; @@ -1333,47 +1325,54 @@ void dc_update_surfaces_for_stream(struct dc *dc, } else { context = core_dc->current_context; } + + /* update current stream with the new updates */ + if (stream_update) { + stream->public.src = stream_update->src; + stream->public.dst = stream_update->dst; + } + + /* save update parameters into surface */ for (i = 0; i < surface_count; i++) { - /* save update param into surface */ - struct core_surface *surface = DC_SURFACE_TO_CORE(updates[i].surface); - struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); + struct core_surface *surface = + DC_SURFACE_TO_CORE(srf_updates[i].surface); - if (updates[i].flip_addr) { - surface->public.address = updates[i].flip_addr->address; + if (srf_updates[i].flip_addr) { + surface->public.address = srf_updates[i].flip_addr->address; surface->public.flip_immediate = - updates[i].flip_addr->flip_immediate; + srf_updates[i].flip_addr->flip_immediate; } - if (updates[i].scaling_info) { + if (srf_updates[i].scaling_info) { surface->public.scaling_quality = - updates[i].scaling_info->scaling_quality; + srf_updates[i].scaling_info->scaling_quality; surface->public.dst_rect = - updates[i].scaling_info->dst_rect; + srf_updates[i].scaling_info->dst_rect; surface->public.src_rect = - updates[i].scaling_info->src_rect; + srf_updates[i].scaling_info->src_rect; surface->public.clip_rect = - updates[i].scaling_info->clip_rect; + srf_updates[i].scaling_info->clip_rect; } - if (updates[i].plane_info) { + if (srf_updates[i].plane_info) { surface->public.color_space = - updates[i].plane_info->color_space; + srf_updates[i].plane_info->color_space; surface->public.format = - updates[i].plane_info->format; + srf_updates[i].plane_info->format; surface->public.plane_size = - updates[i].plane_info->plane_size; + srf_updates[i].plane_info->plane_size; surface->public.rotation = - updates[i].plane_info->rotation; + srf_updates[i].plane_info->rotation; surface->public.horizontal_mirror = - updates[i].plane_info->horizontal_mirror; + srf_updates[i].plane_info->horizontal_mirror; surface->public.stereo_format = - updates[i].plane_info->stereo_format; + srf_updates[i].plane_info->stereo_format; surface->public.tiling_info = - updates[i].plane_info->tiling_info; + srf_updates[i].plane_info->tiling_info; surface->public.visible = - updates[i].plane_info->visible; + srf_updates[i].plane_info->visible; surface->public.dcc = - updates[i].plane_info->dcc; + srf_updates[i].plane_info->dcc; } /* not sure if we still need this */ @@ -1388,40 +1387,40 @@ void dc_update_surfaces_for_stream(struct dc *dc, } } - if (updates[i].gamma && - updates[i].gamma != surface->public.gamma_correction) { + if (srf_updates[i].gamma && + srf_updates[i].gamma != surface->public.gamma_correction) { if (surface->public.gamma_correction != NULL) dc_gamma_release(&surface->public. gamma_correction); - dc_gamma_retain(updates[i].gamma); + dc_gamma_retain(srf_updates[i].gamma); surface->public.gamma_correction = - updates[i].gamma; + srf_updates[i].gamma; } - if (updates[i].in_transfer_func && - updates[i].in_transfer_func != surface->public.in_transfer_func) { + if (srf_updates[i].in_transfer_func && + srf_updates[i].in_transfer_func != surface->public.in_transfer_func) { if (surface->public.in_transfer_func != NULL) dc_transfer_func_release( surface->public. in_transfer_func); dc_transfer_func_retain( - updates[i].in_transfer_func); + srf_updates[i].in_transfer_func); surface->public.in_transfer_func = - updates[i].in_transfer_func; + srf_updates[i].in_transfer_func; } - if (updates[i].out_transfer_func && - updates[i].out_transfer_func != dc_stream->out_transfer_func) { + if (srf_updates[i].out_transfer_func && + srf_updates[i].out_transfer_func != dc_stream->out_transfer_func) { if (dc_stream->out_transfer_func != NULL) dc_transfer_func_release(dc_stream->out_transfer_func); - dc_transfer_func_retain(updates[i].out_transfer_func); - stream->public.out_transfer_func = updates[i].out_transfer_func; + dc_transfer_func_retain(srf_updates[i].out_transfer_func); + stream->public.out_transfer_func = srf_updates[i].out_transfer_func; } - if (updates[i].hdr_static_metadata) + if (srf_updates[i].hdr_static_metadata) surface->public.hdr_static_ctx = - *(updates[i].hdr_static_metadata); + *(srf_updates[i].hdr_static_metadata); } if (update_type == UPDATE_TYPE_FULL && @@ -1434,7 +1433,7 @@ void dc_update_surfaces_for_stream(struct dc *dc, core_dc->hwss.apply_ctx_for_surface(core_dc, NULL, context); for (i = 0; i < surface_count; i++) { - struct core_surface *surface = DC_SURFACE_TO_CORE(updates[i].surface); + struct core_surface *surface = DC_SURFACE_TO_CORE(srf_updates[i].surface); for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; @@ -1460,7 +1459,7 @@ void dc_update_surfaces_for_stream(struct dc *dc, true); } - if (updates[i].flip_addr) + if (srf_updates[i].flip_addr) core_dc->hwss.update_plane_addr(core_dc, pipe_ctx); if (update_type == UPDATE_TYPE_FAST) @@ -1471,18 +1470,18 @@ void dc_update_surfaces_for_stream(struct dc *dc, is_new_pipe_surface = false; if (is_new_pipe_surface || - updates[i].in_transfer_func) + srf_updates[i].in_transfer_func) core_dc->hwss.set_input_transfer_func( pipe_ctx, pipe_ctx->surface); if (is_new_pipe_surface || - updates[i].out_transfer_func) + srf_updates[i].out_transfer_func) core_dc->hwss.set_output_transfer_func( pipe_ctx, pipe_ctx->surface, pipe_ctx->stream); - if (updates[i].hdr_static_metadata) { + if (srf_updates[i].hdr_static_metadata) { resource_build_info_frame(pipe_ctx); core_dc->hwss.update_info_frame(pipe_ctx); } @@ -1493,7 +1492,7 @@ void dc_update_surfaces_for_stream(struct dc *dc, struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; for (j = 0; j < surface_count; j++) { - if (updates[j].surface == &pipe_ctx->surface->public) { + if (srf_updates[j].surface == &pipe_ctx->surface->public) { if (!pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) { core_dc->hwss.pipe_control_lock( core_dc, diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index b1bff597c0f7..8b033ba5df6e 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -556,6 +556,7 @@ enum surface_update_type dc_check_update_surfaces_for_stream( struct dc *dc, struct dc_surface_update *updates, int surface_count, + struct dc_stream_update *stream_update, const struct dc_stream_status *stream_status); /******************************************************************************* -- cgit From cc04bf7e4f87730a35b14056e23852e010f079ff Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Tue, 14 Mar 2017 01:40:53 -0400 Subject: drm/amd/display: use extended receiver cap for dpcd ver Signed-off-by: Tony Cheng Acked-by: Harry Wentland Reviewed-by: Anthony Koo Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') 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 80002795adc2..282bb59ea2f3 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 @@ -2081,9 +2081,6 @@ static void retrieve_link_cap(struct core_link *link) dpcd_data, sizeof(dpcd_data)); - link->dpcd_caps.dpcd_rev.raw = - dpcd_data[DP_DPCD_REV - DP_DPCD_REV]; - { union training_aux_rd_interval aux_rd_interval; @@ -2099,6 +2096,9 @@ static void retrieve_link_cap(struct core_link *link) } } + link->dpcd_caps.dpcd_rev.raw = + dpcd_data[DP_DPCD_REV - DP_DPCD_REV]; + ds_port.byte = dpcd_data[DP_DOWNSTREAMPORT_PRESENT - DP_DPCD_REV]; -- cgit From 745cc746da42a3a8a48fb7a6b8c4ee2c3f2cdf8b Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Tue, 14 Mar 2017 12:30:29 -0400 Subject: drm/amd/display: remove dc_pre_update_surfaces_to_stream from dc use Signed-off-by: Dmytro Laktyushkin Acked-by: Harry Wentland Reviewed-by: Dmytro Laktyushkin Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 115 ++------------------- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 8 +- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 45 -------- .../drm/amd/display/dc/dce110/dce110_resource.c | 48 +++++++-- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 2 +- drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 5 - 6 files changed, 54 insertions(+), 169 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 26f227ddd025..6409d4d1d7f8 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -900,106 +900,7 @@ bool dc_pre_update_surfaces_to_stream( uint8_t new_surface_count, const struct dc_stream *dc_stream) { - int i, j; - struct core_dc *core_dc = DC_TO_CORE(dc); - struct dc_stream_status *stream_status = NULL; - struct validate_context *context; - bool ret = true; - - pre_surface_trace(dc, new_surfaces, new_surface_count); - - if (core_dc->current_context->stream_count == 0) - return false; - - /* Cannot commit surface to a stream that is not commited */ - for (i = 0; i < core_dc->current_context->stream_count; i++) - if (dc_stream == &core_dc->current_context->streams[i]->public) - break; - - if (i == core_dc->current_context->stream_count) - return false; - - stream_status = &core_dc->current_context->stream_status[i]; - - if (new_surface_count == stream_status->surface_count) { - bool skip_pre = true; - - for (i = 0; i < stream_status->surface_count; i++) { - struct dc_surface temp_surf = { 0 }; - - temp_surf = *stream_status->surfaces[i]; - temp_surf.clip_rect = new_surfaces[i]->clip_rect; - temp_surf.dst_rect.x = new_surfaces[i]->dst_rect.x; - temp_surf.dst_rect.y = new_surfaces[i]->dst_rect.y; - - if (memcmp(&temp_surf, new_surfaces[i], sizeof(temp_surf)) != 0) { - skip_pre = false; - break; - } - } - - if (skip_pre) - return true; - } - - context = dm_alloc(sizeof(struct validate_context)); - - if (!context) { - dm_error("%s: failed to create validate ctx\n", __func__); - ret = false; - goto val_ctx_fail; - } - - resource_validate_ctx_copy_construct(core_dc->current_context, context); - - dm_logger_write(core_dc->ctx->logger, LOG_DC, - "%s: commit %d surfaces to stream 0x%x\n", - __func__, - new_surface_count, - dc_stream); - - if (!resource_attach_surfaces_to_context( - new_surfaces, new_surface_count, dc_stream, context)) { - BREAK_TO_DEBUGGER(); - ret = false; - goto unexpected_fail; - } - - for (i = 0; i < new_surface_count; i++) - for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { - if (context->res_ctx.pipe_ctx[j].surface != - DC_SURFACE_TO_CORE(new_surfaces[i])) - continue; - - resource_build_scaling_params(&context->res_ctx.pipe_ctx[j]); - } - - if (!core_dc->res_pool->funcs->validate_bandwidth(core_dc, context)) { - BREAK_TO_DEBUGGER(); - ret = false; - goto unexpected_fail; - } - - core_dc->hwss.set_bandwidth(core_dc, context, false); - - for (i = 0; i < new_surface_count; i++) - for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { - if (context->res_ctx.pipe_ctx[j].surface != - DC_SURFACE_TO_CORE(new_surfaces[i])) - continue; - - core_dc->hwss.prepare_pipe_for_context( - core_dc, - &context->res_ctx.pipe_ctx[j], - context); - } - -unexpected_fail: - resource_validate_ctx_destruct(context); - dm_free(context); -val_ctx_fail: - - return ret; + return true; } bool dc_post_update_surfaces_to_stream(struct dc *dc) @@ -1050,10 +951,6 @@ bool dc_commit_surfaces_to_stream( struct dc_scaling_info scaling_info[MAX_SURFACES]; int i; - if (!dc_pre_update_surfaces_to_stream( - dc, new_surfaces, new_surface_count, dc_stream)) - return false; - memset(updates, 0, sizeof(updates)); memset(flip_addr, 0, sizeof(flip_addr)); memset(plane_info, 0, sizeof(plane_info)); @@ -1423,10 +1320,12 @@ void dc_update_surfaces_and_stream(struct dc *dc, *(srf_updates[i].hdr_static_metadata); } - if (update_type == UPDATE_TYPE_FULL && - !core_dc->res_pool->funcs->validate_bandwidth(core_dc, context)) { - BREAK_TO_DEBUGGER(); - return; + if (update_type == UPDATE_TYPE_FULL) { + if (!core_dc->res_pool->funcs->validate_bandwidth(core_dc, context)) { + BREAK_TO_DEBUGGER(); + return; + } else + core_dc->hwss.set_bandwidth(core_dc, context, false); } if (!surface_count) /* reset */ diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index ad37d0efca2e..6700d6b27a8a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -900,10 +900,11 @@ struct pipe_ctx *resource_get_head_pipe_for_stream( * that has no surface attached yet */ static struct pipe_ctx *acquire_free_pipe_for_stream( - struct resource_context *res_ctx, + struct validate_context *context, const struct dc_stream *dc_stream) { int i; + struct resource_context *res_ctx = &context->res_ctx; struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); struct pipe_ctx *head_pipe = NULL; @@ -934,7 +935,7 @@ static struct pipe_ctx *acquire_free_pipe_for_stream( if(!res_ctx->pool->funcs->acquire_idle_pipe_for_layer) return NULL; - return res_ctx->pool->funcs->acquire_idle_pipe_for_layer(res_ctx, stream); + return res_ctx->pool->funcs->acquire_idle_pipe_for_layer(context, stream); } @@ -1001,8 +1002,7 @@ bool resource_attach_surfaces_to_context( tail_pipe = NULL; for (i = 0; i < surface_count; i++) { struct core_surface *surface = DC_SURFACE_TO_CORE(surfaces[i]); - struct pipe_ctx *free_pipe = acquire_free_pipe_for_stream( - &context->res_ctx, dc_stream); + struct pipe_ctx *free_pipe = acquire_free_pipe_for_stream(context, dc_stream); if (!free_pipe) { stream_status->surfaces[i] = NULL; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index cb7a673e15e9..e5e52c705954 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -2094,50 +2094,6 @@ static void init_hw(struct core_dc *dc) } } -static void dce110_power_on_pipe_if_needed( - struct core_dc *dc, - struct pipe_ctx *pipe_ctx, - struct validate_context *context) -{ - struct pipe_ctx *old_pipe_ctx = &dc->current_context->res_ctx.pipe_ctx[pipe_ctx->pipe_idx]; - struct dc_bios *dcb = dc->ctx->dc_bios; - struct tg_color black_color = {0}; - - if (!old_pipe_ctx->stream && pipe_ctx->stream) { - dc->hwss.enable_display_power_gating( - dc, - pipe_ctx->pipe_idx, - dcb, PIPE_GATING_CONTROL_DISABLE); - - /* - * This is for powering on underlay, so crtc does not - * need to be enabled - */ - - pipe_ctx->tg->funcs->program_timing(pipe_ctx->tg, - &pipe_ctx->stream->public.timing, - false); - - pipe_ctx->tg->funcs->enable_advanced_request( - pipe_ctx->tg, - true, - &pipe_ctx->stream->public.timing); - - pipe_ctx->mi->funcs->allocate_mem_input(pipe_ctx->mi, - pipe_ctx->stream->public.timing.h_total, - pipe_ctx->stream->public.timing.v_total, - pipe_ctx->stream->public.timing.pix_clk_khz, - context->stream_count); - - /* TODO unhardcode*/ - color_space_to_black_color(dc, - COLOR_SPACE_YCBCR601, &black_color); - pipe_ctx->tg->funcs->set_blank_color( - pipe_ctx->tg, - &black_color); - } -} - static void fill_display_configs( const struct validate_context *context, struct dm_pp_display_configuration *pp_display_cfg) @@ -2481,7 +2437,6 @@ static void dce110_power_down_fe(struct core_dc *dc, struct pipe_ctx *pipe) static const struct hw_sequencer_funcs dce110_funcs = { .init_hw = init_hw, .apply_ctx_to_hw = dce110_apply_ctx_to_hw, - .prepare_pipe_for_context = dce110_power_on_pipe_if_needed, .apply_ctx_for_surface = dce110_apply_ctx_for_surface, .set_plane_config = set_plane_config, .update_plane_addr = update_plane_addr, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index b9d0b5eeca13..e3002031c40d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -1111,16 +1111,17 @@ enum dc_status dce110_validate_guaranteed( return result; } -static struct pipe_ctx *dce110_acquire_idle_pipe_for_layer( - struct resource_context *res_ctx, +static struct pipe_ctx *dce110_acquire_underlay( + struct validate_context *context, struct core_stream *stream) { + struct core_dc *dc = DC_TO_CORE(stream->ctx->dc); + struct resource_context *res_ctx = &context->res_ctx; unsigned int underlay_idx = res_ctx->pool->underlay_pipe_index; struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[underlay_idx]; - if (res_ctx->pipe_ctx[underlay_idx].stream) { + if (res_ctx->pipe_ctx[underlay_idx].stream) return NULL; - } pipe_ctx->tg = res_ctx->pool->timing_generators[underlay_idx]; pipe_ctx->mi = res_ctx->pool->mis[underlay_idx]; @@ -1132,8 +1133,43 @@ static struct pipe_ctx *dce110_acquire_idle_pipe_for_layer( pipe_ctx->stream = stream; - return pipe_ctx; + if (!dc->current_context->res_ctx.pipe_ctx[underlay_idx].stream) { + struct tg_color black_color = {0}; + struct dc_bios *dcb = dc->ctx->dc_bios; + + dc->hwss.enable_display_power_gating( + dc, + pipe_ctx->pipe_idx, + dcb, PIPE_GATING_CONTROL_DISABLE); + + /* + * This is for powering on underlay, so crtc does not + * need to be enabled + */ + + pipe_ctx->tg->funcs->program_timing(pipe_ctx->tg, + &stream->public.timing, + false); + + pipe_ctx->tg->funcs->enable_advanced_request( + pipe_ctx->tg, + true, + &stream->public.timing); + + pipe_ctx->mi->funcs->allocate_mem_input(pipe_ctx->mi, + stream->public.timing.h_total, + stream->public.timing.v_total, + stream->public.timing.pix_clk_khz, + context->stream_count); + + color_space_to_black_color(dc, + COLOR_SPACE_YCBCR601, &black_color); + pipe_ctx->tg->funcs->set_blank_color( + pipe_ctx->tg, + &black_color); + } + return pipe_ctx; } static void dce110_destroy_resource_pool(struct resource_pool **pool) @@ -1152,7 +1188,7 @@ static const struct resource_funcs dce110_res_pool_funcs = { .validate_with_context = dce110_validate_with_context, .validate_guaranteed = dce110_validate_guaranteed, .validate_bandwidth = dce110_validate_bandwidth, - .acquire_idle_pipe_for_layer = dce110_acquire_idle_pipe_for_layer, + .acquire_idle_pipe_for_layer = dce110_acquire_underlay, .build_bit_depth_reduction_params = dce110_resource_build_bit_depth_reduction_params }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index faec2292cc27..7f3c6da1ebd7 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -210,7 +210,7 @@ struct resource_funcs { struct validate_context *context); struct pipe_ctx *(*acquire_idle_pipe_for_layer)( - struct resource_context *res_ctx, + struct validate_context *context, struct core_stream *stream); void (*build_bit_depth_reduction_params)( diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 98a04cd46178..bcb267295cb9 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -57,11 +57,6 @@ struct hw_sequencer_funcs { void (*reset_hw_ctx_wrap)( struct core_dc *dc, struct validate_context *context); - void (*prepare_pipe_for_context)( - struct core_dc *dc, - struct pipe_ctx *pipe_ctx, - struct validate_context *context); - void (*apply_ctx_for_surface)( struct core_dc *dc, struct core_surface *surface, -- cgit From e73c1efca8c5fd4a53f6d725fc6ca18c65570d37 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Tue, 14 Mar 2017 16:41:50 -0400 Subject: drm/amd/display: Use stream_enc to get head pipe. Signed-off-by: Yongqiang Sun Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 6700d6b27a8a..9f624e84f59b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -887,7 +887,7 @@ struct pipe_ctx *resource_get_head_pipe_for_stream( int i; for (i = 0; i < res_ctx->pool->pipe_count; i++) { if (res_ctx->pipe_ctx[i].stream == stream && - !res_ctx->pipe_ctx[i].top_pipe) { + res_ctx->pipe_ctx[i].stream_enc) { return &res_ctx->pipe_ctx[i]; break; } -- cgit From 3f8a944016674bdc64a4307a6898c3d919eb8768 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Tue, 14 Mar 2017 16:30:06 -0400 Subject: drm/amd/display: support CP2520 pattern 2 for HBR2 compliance - also some clean up Signed-off-by: Tony Cheng Acked-by: Harry Wentland Reviewed-by: Charlene Liu Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 149 ++++++++------------- .../gpu/drm/amd/display/dc/dce/dce_link_encoder.h | 10 +- .../drm/amd/display/dc/dce100/dce100_resource.c | 2 +- 3 files changed, 66 insertions(+), 95 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index a1d35ad85605..65cc64a17f41 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -169,9 +169,6 @@ static void disable_prbs_symbols( static void disable_prbs_mode( struct dce110_link_encoder *enc110) { - /* This register resides in DP back end block; - * transmitter is used for the offset */ - REG_UPDATE(DP_DPHY_PRBS_CNTL, DPHY_PRBS_EN, 0); } @@ -216,9 +213,7 @@ static void set_dp_phy_pattern_d102( disable_prbs_symbols(enc110, true); - /* Disable PRBS mode, - * make sure DPHY_PRBS_CNTL.DPHY_PRBS_EN=0 */ - + /* Disable PRBS mode */ disable_prbs_mode(enc110); /* Program debug symbols to be output */ @@ -264,43 +259,54 @@ void dce110_link_encoder_set_dp_phy_pattern_training_pattern( enable_phy_bypass_mode(enc110, false); - /* Disable PRBS mode, - * make sure DPHY_PRBS_CNTL.DPHY_PRBS_EN=0 */ - + /* Disable PRBS mode */ disable_prbs_mode(enc110); } +static void setup_panel_mode( + struct dce110_link_encoder *enc110, + enum dp_panel_mode panel_mode) +{ + uint32_t value; + + ASSERT(REG(DP_DPHY_INTERNAL_CTRL)); + value = REG_READ(DP_DPHY_INTERNAL_CTRL); + + switch (panel_mode) { + case DP_PANEL_MODE_EDP: + value = 0x1; + break; + case DP_PANEL_MODE_SPECIAL: + value = 0x11; + break; + default: + value = 0x0; + break; + } + + REG_WRITE(DP_DPHY_INTERNAL_CTRL, value); +} + static void set_dp_phy_pattern_symbol_error( struct dce110_link_encoder *enc110) { /* Disable PHY Bypass mode to setup the test pattern */ - uint32_t value = 0x0; - enable_phy_bypass_mode(enc110, false); /* program correct panel mode*/ - { - ASSERT(REG(DP_DPHY_INTERNAL_CTRL)); - /*DCE 120 does not have this reg*/ - - REG_WRITE(DP_DPHY_INTERNAL_CTRL, value); - } + setup_panel_mode(enc110, DP_PANEL_MODE_DEFAULT); /* A PRBS23 pattern is used for most DP electrical measurements. */ /* Enable PRBS symbols on the lanes */ - disable_prbs_symbols(enc110, false); /* For PRBS23 Set bit DPHY_PRBS_SEL=1 and Set bit DPHY_PRBS_EN=1 */ - { - REG_UPDATE_2(DP_DPHY_PRBS_CNTL, - DPHY_PRBS_SEL, 1, - DPHY_PRBS_EN, 1); - } + REG_UPDATE_2(DP_DPHY_PRBS_CNTL, + DPHY_PRBS_SEL, 1, + DPHY_PRBS_EN, 1); /* Enable phy bypass mode to enable the test pattern */ - enable_phy_bypass_mode(enc110, true); } @@ -308,24 +314,19 @@ static void set_dp_phy_pattern_prbs7( struct dce110_link_encoder *enc110) { /* Disable PHY Bypass mode to setup the test pattern */ - enable_phy_bypass_mode(enc110, false); /* A PRBS7 pattern is used for most DP electrical measurements. */ /* Enable PRBS symbols on the lanes */ - disable_prbs_symbols(enc110, false); /* For PRBS7 Set bit DPHY_PRBS_SEL=0 and Set bit DPHY_PRBS_EN=1 */ - { - REG_UPDATE_2(DP_DPHY_PRBS_CNTL, - DPHY_PRBS_SEL, 0, - DPHY_PRBS_EN, 1); - } + REG_UPDATE_2(DP_DPHY_PRBS_CNTL, + DPHY_PRBS_SEL, 0, + DPHY_PRBS_EN, 1); /* Enable phy bypass mode to enable the test pattern */ - enable_phy_bypass_mode(enc110, true); } @@ -374,7 +375,7 @@ static void set_dp_phy_pattern_80bit_custom( enable_phy_bypass_mode(enc110, true); } -static void set_dp_phy_pattern_hbr2_compliance( +static void set_dp_phy_pattern_hbr2_compliance_cp2520_2( struct dce110_link_encoder *enc110) { @@ -391,56 +392,34 @@ static void set_dp_phy_pattern_hbr2_compliance( enable_phy_bypass_mode(enc110, false); /* Setup DIG encoder in DP SST mode */ - enc110->base.funcs->setup(&enc110->base, SIGNAL_TYPE_DISPLAY_PORT); - /* program correct panel mode*/ - { - ASSERT(REG(DP_DPHY_INTERNAL_CTRL)); - - REG_WRITE(DP_DPHY_INTERNAL_CTRL, 0x0); - } + /* ensure normal panel mode. */ + setup_panel_mode(enc110, DP_PANEL_MODE_DEFAULT); /* no vbid after BS (SR) * DP_LINK_FRAMING_CNTL changed history Sandra Liu * 11000260 / 11000104 / 110000FC */ + REG_UPDATE_3(DP_LINK_FRAMING_CNTL, + DP_IDLE_BS_INTERVAL, 0xFC, + DP_VBID_DISABLE, 1, + DP_VID_ENHANCED_FRAME_MODE, 1); - /* TODO DP_LINK_FRAMING_CNTL should always use hardware default value - * output except output hbr2_compliance pattern for physical PHY - * measurement. This is not normal usage case. SW should reset this - * register to hardware default value after end use of HBR2 eye - */ - BREAK_TO_DEBUGGER(); - /* TODO: do we still need this, find out at compliance test - addr = mmDP_LINK_FRAMING_CNTL + fe_addr_offset; - - value = dal_read_reg(ctx, addr); - - set_reg_field_value(value, 0xFC, - DP_LINK_FRAMING_CNTL, DP_IDLE_BS_INTERVAL); - set_reg_field_value(value, 1, - DP_LINK_FRAMING_CNTL, DP_VBID_DISABLE); - set_reg_field_value(value, 1, - DP_LINK_FRAMING_CNTL, DP_VID_ENHANCED_FRAME_MODE); - - dal_write_reg(ctx, addr, value); - */ /* swap every BS with SR */ - REG_UPDATE(DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_BS_COUNT, 0); - /*TODO add support for this test pattern - * support_dp_hbr2_eye_pattern - */ + /* select cp2520 pattern 2 */ + if (REG(DP_DPHY_HBR2_PATTERN_CONTROL)) + REG_UPDATE(DP_DPHY_HBR2_PATTERN_CONTROL, + DP_DPHY_HBR2_PATTERN_CONTROL, 0x2); /* set link training complete */ set_link_training_complete(enc110, true); - /* do not enable video stream */ + /* disable video stream */ REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, 0); /* Disable PHY Bypass mode to setup the test pattern */ - enable_phy_bypass_mode(enc110, false); } @@ -448,41 +427,26 @@ static void set_dp_phy_pattern_passthrough_mode( struct dce110_link_encoder *enc110, enum dp_panel_mode panel_mode) { - uint32_t value; - /* program correct panel mode */ - { - ASSERT(REG(DP_DPHY_INTERNAL_CTRL)); - value = REG_READ(DP_DPHY_INTERNAL_CTRL); + setup_panel_mode(enc110, panel_mode); - switch (panel_mode) { - case DP_PANEL_MODE_EDP: - value = 0x1; - break; - case DP_PANEL_MODE_SPECIAL: - value = 0x11; - break; - default: - value = 0x0; - break; - } - - REG_WRITE(DP_DPHY_INTERNAL_CTRL, value); - } + /* restore LINK_FRAMING_CNTL and DPHY_SCRAMBLER_BS_COUNT + * in case we were doing HBR2 compliance pattern before + */ + REG_UPDATE_3(DP_LINK_FRAMING_CNTL, + DP_IDLE_BS_INTERVAL, 0x2000, + DP_VBID_DISABLE, 0, + DP_VID_ENHANCED_FRAME_MODE, 1); REG_UPDATE(DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_BS_COUNT, 0x1FF); /* set link training complete */ - set_link_training_complete(enc110, true); /* Disable PHY Bypass mode to setup the test pattern */ - enable_phy_bypass_mode(enc110, false); - /* Disable PRBS mode, - * make sure DPHY_PRBS_CNTL.DPHY_PRBS_EN=0 */ - + /* Disable PRBS mode */ disable_prbs_mode(enc110); } @@ -828,8 +792,7 @@ static void link_encoder_disable(struct dce110_link_encoder *enc110) REG_UPDATE(DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE, 0); /* reset panel mode */ - ASSERT(REG(DP_DPHY_INTERNAL_CTRL)); - REG_WRITE(DP_DPHY_INTERNAL_CTRL, 0); + setup_panel_mode(enc110, DP_PANEL_MODE_DEFAULT); } static void hpd_initialize( @@ -1433,7 +1396,7 @@ void dce110_link_encoder_dp_set_phy_pattern( enc110, param->custom_pattern); break; case DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE: - set_dp_phy_pattern_hbr2_compliance(enc110); + set_dp_phy_pattern_hbr2_compliance_cp2520_2(enc110); break; case DP_TEST_PATTERN_VIDEO_MODE: { set_dp_phy_pattern_passthrough_mode( diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h index 25ba583dbb8f..4e0b5d965355 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h @@ -78,22 +78,29 @@ SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ SR(DCI_MEM_PWR_STATUS) +#define LE_DCE100_REG_LIST(id)\ + LE_COMMON_REG_LIST_BASE(id), \ + SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ + SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ + SR(DCI_MEM_PWR_STATUS) + #define LE_DCE110_REG_LIST(id)\ LE_COMMON_REG_LIST_BASE(id), \ SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ + SRI(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id), \ SR(DCI_MEM_PWR_STATUS) #define LE_DCE120_REG_LIST(id)\ LE_COMMON_REG_LIST_BASE(id), \ SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ + SRI(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id), \ SR(DCI_MEM_PWR_STATUS) #define LE_DCE80_REG_LIST(id)\ SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ LE_COMMON_REG_LIST_BASE(id) - struct dce110_link_enc_aux_registers { uint32_t AUX_CONTROL; uint32_t AUX_DPHY_RX_CONTROL0; @@ -144,6 +151,7 @@ struct dce110_link_enc_registers { uint32_t DP_VID_STREAM_CNTL; uint32_t DP_DPHY_FAST_TRAINING; uint32_t DP_DPHY_BS_SR_SWAP_CNTL; + uint32_t DP_DPHY_HBR2_PATTERN_CONTROL; uint32_t DP_SEC_CNTL1; }; diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index c72858a1452f..b6f77f88be9c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -265,7 +265,7 @@ static const struct dce110_link_enc_hpd_registers link_enc_hpd_regs[] = { #define link_regs(id)\ [id] = {\ - LE_DCE110_REG_LIST(id)\ + LE_DCE100_REG_LIST(id)\ } static const struct dce110_link_enc_registers link_enc_regs[] = { -- cgit From 0e19401f9506e710379396479c3824d80ccdc332 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Tue, 14 Mar 2017 19:16:36 -0400 Subject: drm/amd/display: support PHY compliance automation for CP2520 pattern 1/2/3 Signed-off-by: Tony Cheng Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 55 ++++++++++++---------- .../gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 17 +++++-- drivers/gpu/drm/amd/display/include/dpcd_defs.h | 4 +- .../drm/amd/display/include/link_service_types.h | 11 +++-- 4 files changed, 53 insertions(+), 34 deletions(-) (limited to 'drivers/gpu') 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 282bb59ea2f3..4f6d1d2d5b9b 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 @@ -1599,19 +1599,25 @@ static void dp_test_send_phy_test_pattern(struct core_link *link) switch (dpcd_test_pattern.bits.PATTERN) { case PHY_TEST_PATTERN_D10_2: test_pattern = DP_TEST_PATTERN_D102; - break; + break; case PHY_TEST_PATTERN_SYMBOL_ERROR: test_pattern = DP_TEST_PATTERN_SYMBOL_ERROR; - break; + break; case PHY_TEST_PATTERN_PRBS7: test_pattern = DP_TEST_PATTERN_PRBS7; - break; + break; case PHY_TEST_PATTERN_80BIT_CUSTOM: test_pattern = DP_TEST_PATTERN_80BIT_CUSTOM; - break; - case PHY_TEST_PATTERN_HBR2_COMPLIANCE_EYE: - test_pattern = DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE; - break; + break; + case PHY_TEST_PATTERN_CP2520_1: + test_pattern = DP_TEST_PATTERN_CP2520_1; + break; + case PHY_TEST_PATTERN_CP2520_2: + test_pattern = DP_TEST_PATTERN_CP2520_2; + break; + case PHY_TEST_PATTERN_CP2520_3: + test_pattern = DP_TEST_PATTERN_CP2520_3; + break; default: test_pattern = DP_TEST_PATTERN_VIDEO_MODE; break; @@ -2202,16 +2208,9 @@ void dc_link_dp_disable_hpd(const struct dc_link *link) static bool is_dp_phy_pattern(enum dp_test_pattern test_pattern) { - if (test_pattern == DP_TEST_PATTERN_D102 || - test_pattern == DP_TEST_PATTERN_SYMBOL_ERROR || - test_pattern == DP_TEST_PATTERN_PRBS7 || - test_pattern == DP_TEST_PATTERN_80BIT_CUSTOM || - test_pattern == DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE || - test_pattern == DP_TEST_PATTERN_TRAINING_PATTERN1 || - test_pattern == DP_TEST_PATTERN_TRAINING_PATTERN2 || - test_pattern == DP_TEST_PATTERN_TRAINING_PATTERN3 || - test_pattern == DP_TEST_PATTERN_TRAINING_PATTERN4 || - test_pattern == DP_TEST_PATTERN_VIDEO_MODE) + if ((DP_TEST_PATTERN_PHY_PATTERN_BEGIN <= test_pattern && + test_pattern <= DP_TEST_PATTERN_PHY_PATTERN_END) || + test_pattern == DP_TEST_PATTERN_VIDEO_MODE) return true; else return false; @@ -2377,22 +2376,28 @@ bool dc_link_dp_set_test_pattern( switch (test_pattern) { case DP_TEST_PATTERN_VIDEO_MODE: pattern = PHY_TEST_PATTERN_NONE; - break; + break; case DP_TEST_PATTERN_D102: pattern = PHY_TEST_PATTERN_D10_2; - break; + break; case DP_TEST_PATTERN_SYMBOL_ERROR: pattern = PHY_TEST_PATTERN_SYMBOL_ERROR; - break; + break; case DP_TEST_PATTERN_PRBS7: pattern = PHY_TEST_PATTERN_PRBS7; - break; + break; case DP_TEST_PATTERN_80BIT_CUSTOM: pattern = PHY_TEST_PATTERN_80BIT_CUSTOM; - break; - case DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE: - pattern = PHY_TEST_PATTERN_HBR2_COMPLIANCE_EYE; - break; + break; + case DP_TEST_PATTERN_CP2520_1: + pattern = PHY_TEST_PATTERN_CP2520_1; + break; + case DP_TEST_PATTERN_CP2520_2: + pattern = PHY_TEST_PATTERN_CP2520_2; + break; + case DP_TEST_PATTERN_CP2520_3: + pattern = PHY_TEST_PATTERN_CP2520_3; + break; default: return false; } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 65cc64a17f41..ed46e9aaf357 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -376,7 +376,8 @@ static void set_dp_phy_pattern_80bit_custom( } static void set_dp_phy_pattern_hbr2_compliance_cp2520_2( - struct dce110_link_encoder *enc110) + struct dce110_link_encoder *enc110, + unsigned int cp2520_pattern) { /* previously there is a register DP_HBR2_EYE_PATTERN @@ -408,10 +409,13 @@ static void set_dp_phy_pattern_hbr2_compliance_cp2520_2( /* swap every BS with SR */ REG_UPDATE(DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_BS_COUNT, 0); - /* select cp2520 pattern 2 */ + /* select cp2520 patterns */ if (REG(DP_DPHY_HBR2_PATTERN_CONTROL)) REG_UPDATE(DP_DPHY_HBR2_PATTERN_CONTROL, - DP_DPHY_HBR2_PATTERN_CONTROL, 0x2); + DP_DPHY_HBR2_PATTERN_CONTROL, cp2520_pattern); + else + /* pre-DCE11 can only generate CP2520 pattern 2 */ + ASSERT(cp2520_pattern == 2); /* set link training complete */ set_link_training_complete(enc110, true); @@ -1395,8 +1399,11 @@ void dce110_link_encoder_dp_set_phy_pattern( set_dp_phy_pattern_80bit_custom( enc110, param->custom_pattern); break; - case DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE: - set_dp_phy_pattern_hbr2_compliance_cp2520_2(enc110); + case DP_TEST_PATTERN_CP2520_1: + set_dp_phy_pattern_hbr2_compliance_cp2520_2(enc110, 1); + break; + case DP_TEST_PATTERN_CP2520_2: + set_dp_phy_pattern_hbr2_compliance_cp2520_2(enc110, 2); break; case DP_TEST_PATTERN_VIDEO_MODE: { set_dp_phy_pattern_passthrough_mode( diff --git a/drivers/gpu/drm/amd/display/include/dpcd_defs.h b/drivers/gpu/drm/amd/display/include/dpcd_defs.h index ea8f5867e834..d8e52e3b8e3c 100644 --- a/drivers/gpu/drm/amd/display/include/dpcd_defs.h +++ b/drivers/gpu/drm/amd/display/include/dpcd_defs.h @@ -74,7 +74,9 @@ enum dpcd_phy_test_patterns { PHY_TEST_PATTERN_SYMBOL_ERROR, PHY_TEST_PATTERN_PRBS7, PHY_TEST_PATTERN_80BIT_CUSTOM,/* For DP1.2 only */ - PHY_TEST_PATTERN_HBR2_COMPLIANCE_EYE/* For DP1.2 only */ + PHY_TEST_PATTERN_CP2520_1, + PHY_TEST_PATTERN_CP2520_2, + PHY_TEST_PATTERN_CP2520_3, /* same as TPS4 */ }; enum dpcd_test_dyn_range { diff --git a/drivers/gpu/drm/amd/display/include/link_service_types.h b/drivers/gpu/drm/amd/display/include/link_service_types.h index 479e5fff8a00..b2326017e4c7 100644 --- a/drivers/gpu/drm/amd/display/include/link_service_types.h +++ b/drivers/gpu/drm/amd/display/include/link_service_types.h @@ -75,19 +75,24 @@ enum dp_test_pattern { /* Input data is pass through Scrambler * and 8b10b Encoder straight to output*/ DP_TEST_PATTERN_VIDEO_MODE = 0, + /* phy test patterns*/ - DP_TEST_PATTERN_D102, + DP_TEST_PATTERN_PHY_PATTERN_BEGIN, + DP_TEST_PATTERN_D102 = DP_TEST_PATTERN_PHY_PATTERN_BEGIN, DP_TEST_PATTERN_SYMBOL_ERROR, DP_TEST_PATTERN_PRBS7, - DP_TEST_PATTERN_80BIT_CUSTOM, - DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE, + DP_TEST_PATTERN_CP2520_1, + DP_TEST_PATTERN_CP2520_2, + DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE = DP_TEST_PATTERN_CP2520_2, /* Link Training Patterns */ DP_TEST_PATTERN_TRAINING_PATTERN1, DP_TEST_PATTERN_TRAINING_PATTERN2, DP_TEST_PATTERN_TRAINING_PATTERN3, DP_TEST_PATTERN_TRAINING_PATTERN4, + DP_TEST_PATTERN_CP2520_3 = DP_TEST_PATTERN_TRAINING_PATTERN4, + DP_TEST_PATTERN_PHY_PATTERN_END = DP_TEST_PATTERN_TRAINING_PATTERN4, /* link test patterns*/ DP_TEST_PATTERN_COLOR_SQUARES, -- cgit From 53d35dc60d386cdf1d04a318dc010524bf5607a3 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Thu, 16 Mar 2017 15:51:00 -0400 Subject: drm/amd/display: Fix the NULL pointer. (v2) ret value in amdgpu_dm_atomic_check was not rest to EINVAL after drm_atomic_add_affected_planes and by this making any subsequent validation failure pass when returning to atomic_check. v2: Add WARN_ON print for dc_commit_streams in amdgpu_dm_atomic_commit_tail since this should never fail. Signed-off-by: Andrey Grodzovsky Acked-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 1c1c643439b8..7f2d17784a8e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2392,7 +2392,7 @@ void amdgpu_dm_atomic_commit_tail( } /* DC is optimized not to do anything if 'streams' didn't change. */ - dc_commit_streams(dm->dc, commit_streams, commit_streams_count); + WARN_ON(!dc_commit_streams(dm->dc, commit_streams, commit_streams_count)); list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); @@ -2858,6 +2858,8 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, ret = drm_atomic_add_affected_planes(state, crtc); if (ret) return ret; + + ret = -EINVAL; } for (i = 0; i < set_count; i++) { -- cgit From d092bf65851802593ed331ff5a6309b625f36bea Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Wed, 8 Feb 2017 15:58:50 -0500 Subject: drm/amd/display: Fix gfx9 parameters reading for DC. Signed-off-by: Andrey Grodzovsky Acked-by: Harry Wentland Reviewed-by: Jordan Lazare Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 7f2d17784a8e..8ae78c0653b6 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -535,6 +535,8 @@ static void fill_plane_attributes_from_fb( adev->gfx.config.gb_addr_config_fields.num_se; surface->tiling_info.gfx9.max_compressed_frags = adev->gfx.config.gb_addr_config_fields.max_compress_frags; + surface->tiling_info.gfx9.num_rb_per_se = + adev->gfx.config.gb_addr_config_fields.num_rb_per_se; surface->tiling_info.gfx9.swizzle = AMDGPU_TILING_GET(tiling_flags, SWIZZLE_MODE); surface->tiling_info.gfx9.shaderEnable = 1; -- cgit From 1034934584cf3e2f93da56cc00d6f1ffe2d2d5a9 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Wed, 22 Feb 2017 15:31:47 -0500 Subject: drm/amd/display: Unhardcode acrtc->max_cursor_{height,width} Signed-off-by: Andrey Grodzovsky Reviewed-by: Jordan Lazare Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 8ae78c0653b6..19c92aec2f58 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -1615,8 +1615,8 @@ int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, drm_crtc_helper_add(&acrtc->base, &amdgpu_dm_crtc_helper_funcs); - acrtc->max_cursor_width = 128; - acrtc->max_cursor_height = 128; + acrtc->max_cursor_width = dm->adev->dm.dc->caps.max_cursor_size; + acrtc->max_cursor_height = dm->adev->dm.dc->caps.max_cursor_size; acrtc->crtc_id = crtc_index; acrtc->base.enabled = false; -- cgit From ce75805e0a63843af71a07e7e95443866e118af0 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Wed, 22 Feb 2017 14:24:11 -0500 Subject: drm/amd/display: Unhardcode cursor size reported back to UMD. This will return back MAX cursor size for given ASIC. Signed-off-by: Andrey Grodzovsky Reviewed-by: Jordan Lazare Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') 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 97d949affcfb..c559c71d558e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -311,8 +311,8 @@ int amdgpu_dm_init(struct amdgpu_device *adev) /* TODO: Add_display_info? */ /* TODO use dynamic cursor width */ - adev->ddev->mode_config.cursor_width = 128; - adev->ddev->mode_config.cursor_height = 128; + adev->ddev->mode_config.cursor_width = adev->dm.dc->caps.max_cursor_size; + adev->ddev->mode_config.cursor_height = adev->dm.dc->caps.max_cursor_size; if (drm_vblank_init(adev->ddev, adev->dm.display_indexes_num)) { DRM_ERROR( -- cgit From 0702a01f97ec24b20bf20bf6f36250de08bcc8cb Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Wed, 22 Feb 2017 14:23:51 -0500 Subject: drm/amd/display: Set cursor pitch to cursor width (in pixels). Signed-off-by: Andrey Grodzovsky Reviewed-by: Jordan Lazare Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 19c92aec2f58..ee9239ab734c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -96,6 +96,8 @@ static void dm_set_cursor( attributes.rotation_angle = 0; attributes.attribute_flags.value = 0; + attributes.pitch = attributes.width; + x = amdgpu_crtc->cursor_x; y = amdgpu_crtc->cursor_y; -- cgit From 00f02019990d9020321c446a04044b6ca05d20f8 Mon Sep 17 00:00:00 2001 From: Leon Elazar Date: Fri, 17 Mar 2017 12:02:58 -0400 Subject: drm/amd/display: Fix applying surface to underlay pipe 1. Locking all pipes before doing any changes 2. Applying surface for both top and bottom pipes Signed-off-by: Leon Elazar Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 34 +++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 12 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 6409d4d1d7f8..c0889ad8357e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1331,32 +1331,41 @@ void dc_update_surfaces_and_stream(struct dc *dc, if (!surface_count) /* reset */ core_dc->hwss.apply_ctx_for_surface(core_dc, NULL, context); + /* Lock pipes for provided surfaces */ for (i = 0; i < surface_count; i++) { struct core_surface *surface = DC_SURFACE_TO_CORE(srf_updates[i].surface); for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - struct pipe_ctx *cur_pipe_ctx; - bool is_new_pipe_surface = true; if (pipe_ctx->surface != surface) continue; - - if (update_type >= UPDATE_TYPE_MED) { - /* only apply for top pipe */ - if (!pipe_ctx->top_pipe) { - core_dc->hwss.apply_ctx_for_surface(core_dc, - surface, context); - context_timing_trace(dc, &context->res_ctx); - } - } - if (!pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) { core_dc->hwss.pipe_control_lock( core_dc, pipe_ctx, true); } + } + } + + /* Perform requested Updates */ + for (i = 0; i < surface_count; i++) { + struct core_surface *surface = DC_SURFACE_TO_CORE(srf_updates[i].surface); + + if (update_type >= UPDATE_TYPE_MED) { + core_dc->hwss.apply_ctx_for_surface( + core_dc, surface, context); + context_timing_trace(dc, &context->res_ctx); + } + + for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; + struct pipe_ctx *cur_pipe_ctx; + bool is_new_pipe_surface = true; + + if (pipe_ctx->surface != surface) + continue; if (srf_updates[i].flip_addr) core_dc->hwss.update_plane_addr(core_dc, pipe_ctx); @@ -1387,6 +1396,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, } } + /* Unlock pipes */ for (i = context->res_ctx.pool->pipe_count - 1; i >= 0; i--) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; -- cgit From 7e2fe3190dc2eb62d84069f18cbf3fbabf79ded7 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Fri, 17 Mar 2017 13:09:09 -0400 Subject: drm/amd/display: DP is hotplugged, HDMI with 4:2:0 corruption Signed-off-by: Charlene Liu Acked-by: Harry Wentland Reviewed-by: Charlene Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 9f624e84f59b..875d1a63fcea 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -297,8 +297,8 @@ bool resource_are_streams_timing_synchronizable( return false; if (stream1->phy_pix_clk != stream2->phy_pix_clk - && !dc_is_dp_signal(stream1->signal) - && !dc_is_dp_signal(stream2->signal)) + && (!dc_is_dp_signal(stream1->signal) + || !dc_is_dp_signal(stream2->signal))) return false; return true; @@ -1063,6 +1063,8 @@ static bool are_stream_backends_same( if (stream_a == NULL || stream_b == NULL) return false; + if (stream_a->public.timing.pixel_encoding != stream_b->public.timing.pixel_encoding) + return false; if (is_timing_changed(stream_a, stream_b)) return false; @@ -1072,8 +1074,8 @@ static bool are_stream_backends_same( bool is_stream_unchanged( const struct core_stream *old_stream, const struct core_stream *stream) { - if (old_stream == stream) - return true; + if (old_stream != stream) + return false; if (!are_stream_backends_same(old_stream, stream)) return false; @@ -1357,6 +1359,7 @@ enum dc_status resource_map_pool_resources( continue; } } + /* mark resources used for stream that is already active */ for (j = 0; j < MAX_PIPES; j++) { struct pipe_ctx *pipe_ctx = -- cgit From 2fc67983fbc56b7b6bba64d4410e3bfeee467834 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Mon, 20 Mar 2017 14:49:53 -0400 Subject: drm/amd/display: remove redundant check Signed-off-by: Charlene Liu Acked-by: Harry Wentland Reviewed-by: Charlene Liu Reviewed-by: Anthony Koo Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 875d1a63fcea..61ca1e21ae66 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1063,8 +1063,6 @@ static bool are_stream_backends_same( if (stream_a == NULL || stream_b == NULL) return false; - if (stream_a->public.timing.pixel_encoding != stream_b->public.timing.pixel_encoding) - return false; if (is_timing_changed(stream_a, stream_b)) return false; @@ -1074,8 +1072,6 @@ static bool are_stream_backends_same( bool is_stream_unchanged( const struct core_stream *old_stream, const struct core_stream *stream) { - if (old_stream != stream) - return false; if (!are_stream_backends_same(old_stream, stream)) return false; -- cgit From 3c8c9d6cd1f9c1d6ce53091a0b41fcf2ffc7e16f Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Tue, 21 Mar 2017 15:16:04 -0400 Subject: drm/amd/display: using calculated values for VReady/Startup Signed-off-by: Charlene Liu Acked-by: Harry Wentland Reviewed-by: Dmytro Laktyushkin Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 9 +++++++++ drivers/gpu/drm/amd/display/dc/dm_services_types.h | 2 ++ drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h | 1 - drivers/gpu/drm/amd/display/include/logger_types.h | 1 + 4 files changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index 33e3377f69fe..568b7f0569f8 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -28,6 +28,7 @@ #include "os_types.h" #include "fixed31_32.h" +#include "signal_types.h" /****************************************************************************** * Data types for Virtual HW Layer of DAL3. @@ -647,5 +648,13 @@ struct dc_crtc_timing { struct dc_crtc_timing_flags flags; }; +struct _dlg_otg_param { + int vstartup_start; + int vupdate_offset; + int vupdate_width; + int vready_offset; + enum signal_type signal; +}; + #endif /* DC_HW_TYPES_H */ diff --git a/drivers/gpu/drm/amd/display/dc/dm_services_types.h b/drivers/gpu/drm/amd/display/dc/dm_services_types.h index c631dec489e7..f89395e0c107 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services_types.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services_types.h @@ -180,6 +180,8 @@ struct dm_pp_display_configuration { uint32_t avail_mclk_switch_time_us; uint32_t avail_mclk_switch_time_in_disp_active_us; + uint32_t min_dcfclock_khz; + uint32_t min_dcfc_deep_sleep_clock_khz; uint32_t disp_clk_khz; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h index baa9445833fb..62c19358254b 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h @@ -96,7 +96,6 @@ enum crtc_state { CRTC_STATE_VBLANK = 0, CRTC_STATE_VACTIVE }; - struct timing_generator { const struct timing_generator_funcs *funcs; struct dc_bios *bp; diff --git a/drivers/gpu/drm/amd/display/include/logger_types.h b/drivers/gpu/drm/amd/display/include/logger_types.h index 832d17e1cc49..982c67f7de43 100644 --- a/drivers/gpu/drm/amd/display/include/logger_types.h +++ b/drivers/gpu/drm/amd/display/include/logger_types.h @@ -63,6 +63,7 @@ enum dc_log_type { LOG_EVENT_LINK_LOSS, LOG_EVENT_UNDERFLOW, LOG_IF_TRACE, + LOG_HW_MARKS, LOG_SECTION_TOTAL_COUNT }; -- cgit From 8c8953139c4b8e1be14d0b1a53dc1fd607727b59 Mon Sep 17 00:00:00 2001 From: xhdu Date: Tue, 21 Mar 2017 11:05:32 -0400 Subject: drm/amd/display: Add audio/video ContainerId implementation Leave hardcoded if no ContainerId provided by DM. Signed-off-by: Duke Du Acked-by: Harry Wentland Reviewed-by: Charlene Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_sink.c | 39 ++++++++++++++++++++++++- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 14 +++++++-- drivers/gpu/drm/amd/display/dc/dc.h | 14 +++++++++ 3 files changed, 63 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_sink.c b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c index 8a204731301d..da9955675fbf 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_sink.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c @@ -45,7 +45,10 @@ struct sink { static void destruct(struct sink *sink) { - + if (sink->protected.public.dc_container_id) { + dm_free(sink->protected.public.dc_container_id); + sink->protected.public.dc_container_id = NULL; + } } static bool construct(struct sink *sink, const struct dc_sink_init_data *init_params) @@ -63,6 +66,7 @@ static bool construct(struct sink *sink, const struct dc_sink_init_data *init_pa sink->protected.public.dongle_max_pix_clk = init_params->dongle_max_pix_clk; sink->protected.public.converter_disable_audio = init_params->converter_disable_audio; + sink->protected.public.dc_container_id = NULL; return true; } @@ -113,6 +117,39 @@ alloc_fail: return NULL; } +bool dc_sink_get_container_id(struct dc_sink *dc_sink, struct dc_container_id *container_id) +{ + if (dc_sink && container_id && dc_sink->dc_container_id) { + memmove(&container_id->guid, &dc_sink->dc_container_id->guid, + sizeof(container_id->guid)); + memmove(&container_id->portId, &dc_sink->dc_container_id->portId, + sizeof(container_id->portId)); + container_id->manufacturerName = dc_sink->dc_container_id->manufacturerName; + container_id->productCode = dc_sink->dc_container_id->productCode; + return true; + } + return false; +} + +bool dc_sink_set_container_id(struct dc_sink *dc_sink, const struct dc_container_id *container_id) +{ + if (dc_sink && container_id) { + if (!dc_sink->dc_container_id) + dc_sink->dc_container_id = dm_alloc(sizeof(*dc_sink->dc_container_id)); + + if (dc_sink->dc_container_id) { + memmove(&dc_sink->dc_container_id->guid, &container_id->guid, + sizeof(container_id->guid)); + memmove(&dc_sink->dc_container_id->portId, &container_id->portId, + sizeof(container_id->portId)); + dc_sink->dc_container_id->manufacturerName = container_id->manufacturerName; + dc_sink->dc_container_id->productCode = container_id->productCode; + return true; + } + } + return false; +} + /******************************************************************************* * Protected functions - visible only inside of DC (not visible in DM) ******************************************************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index bafba1f13a1a..512a53bdc32f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -76,9 +76,17 @@ static bool construct(struct core_stream *stream, stream->public.audio_info.product_id = dc_sink_data->edid_caps.product_id; stream->public.audio_info.flags.all = dc_sink_data->edid_caps.speaker_flags; - /* TODO - Unhardcode port_id */ - stream->public.audio_info.port_id[0] = 0x5558859e; - stream->public.audio_info.port_id[1] = 0xd989449; + if (dc_sink_data->dc_container_id != NULL) { + struct dc_container_id *dc_container_id = dc_sink_data->dc_container_id; + + stream->public.audio_info.port_id[0] = dc_container_id->portId[0]; + stream->public.audio_info.port_id[1] = dc_container_id->portId[1]; + } else { + /* TODO - WindowDM has implemented, + other DMs need Unhardcode port_id */ + stream->public.audio_info.port_id[0] = 0x5558859e; + stream->public.audio_info.port_id[1] = 0xd989449; + } /* EDID CAP translation for HDMI 2.0 */ stream->public.timing.flags.LTE_340MCSC_SCRAMBLE = dc_sink_data->edid_caps.lte_340mcsc_scramble; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 8b033ba5df6e..b3d5b922aae4 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -695,6 +695,17 @@ bool dc_link_dp_set_test_pattern( * Sink Interfaces - A sink corresponds to a display output device ******************************************************************************/ +struct dc_container_id { + // 128bit GUID in binary form + unsigned char guid[16]; + // 8 byte port ID -> ELD.PortID + unsigned int portId[2]; + // 128bit GUID in binary formufacturer name -> ELD.ManufacturerName + unsigned short manufacturerName; + // 2 byte product code -> ELD.ProductCode + unsigned short productCode; +}; + /* * The sink structure contains EDID and other display device properties */ @@ -702,6 +713,7 @@ struct dc_sink { enum signal_type sink_signal; struct dc_edid dc_edid; /* raw edid */ struct dc_edid_caps edid_caps; /* parse display caps */ + struct dc_container_id *dc_container_id; uint32_t dongle_max_pix_clk; bool converter_disable_audio; }; @@ -719,6 +731,8 @@ struct dc_sink_init_data { }; struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params); +bool dc_sink_get_container_id(struct dc_sink *dc_sink, struct dc_container_id *container_id); +bool dc_sink_set_container_id(struct dc_sink *dc_sink, const struct dc_container_id *container_id); /******************************************************************************* * Cursor interfaces - To manages the cursor within a stream -- cgit From 18f7a1e4083a5be0ce02df736d3f9a82246dd89b Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Thu, 23 Mar 2017 10:34:06 -0400 Subject: drm/amd/display: Power on front end during set mode. Signed-off-by: Yongqiang Sun Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 3 +++ drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 5 +++++ 2 files changed, 8 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index e5e52c705954..2a3a39e31717 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1722,6 +1722,9 @@ enum dc_status dce110_apply_ctx_to_hw( context, dc); + if (dc->hwss.power_on_front_end) + dc->hwss.power_on_front_end(dc, pipe_ctx, context); + if (DC_OK != status) return status; } diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index bcb267295cb9..077dc7573c52 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -104,6 +104,11 @@ struct hw_sequencer_funcs { enum pipe_gating_control power_gating); void (*power_down_front_end)(struct core_dc *dc, struct pipe_ctx *pipe); + + void (*power_on_front_end)(struct core_dc *dc, + struct pipe_ctx *pipe, + struct validate_context *context); + void (*update_info_frame)(struct pipe_ctx *pipe_ctx); void (*enable_stream)(struct pipe_ctx *pipe_ctx); -- cgit From 5e141de45218d36a6b98c783834684fd0d617f7a Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 21 Mar 2017 18:17:12 -0400 Subject: drm/amd/display: Rename bandwidth_calcs.h to dce_calcs.h Signed-off-by: Harry Wentland Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc.c | 2 +- .../drm/amd/display/dc/dce110/dce110_mem_input_v.c | 2 +- .../gpu/drm/amd/display/dc/dce80/dce80_mem_input.c | 2 +- .../gpu/drm/amd/display/dc/inc/bandwidth_calcs.h | 504 -------------------- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 2 +- drivers/gpu/drm/amd/display/dc/inc/dce_calcs.h | 506 +++++++++++++++++++++ drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h | 2 +- 8 files changed, 512 insertions(+), 510 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/dc/inc/bandwidth_calcs.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/dce_calcs.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c index 4820660f51d6..5ac614f433f8 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c @@ -24,7 +24,7 @@ */ #include "dm_services.h" -#include "bandwidth_calcs.h" +#include "dce_calcs.h" #include "dc.h" #include "core_types.h" #include "dal_asic_id.h" diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index c0889ad8357e..b3891228b499 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -35,7 +35,7 @@ #include "clock_source.h" #include "dc_bios_types.h" -#include "bandwidth_calcs.h" +#include "dce_calcs.h" #include "bios_parser_interface.h" #include "include/irq_service_interface.h" #include "transform.h" diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c index aac47955e9bf..9c32b5bbdff5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c @@ -31,7 +31,7 @@ #include "gmc/gmc_8_2_sh_mask.h" #include "include/logger_interface.h" -#include "inc/bandwidth_calcs.h" +#include "inc/dce_calcs.h" #include "dce110_mem_input.h" diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c index ebb8df3cdf4a..933e3d819f27 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c @@ -31,7 +31,7 @@ #include "gmc/gmc_7_1_sh_mask.h" #include "include/logger_interface.h" -#include "inc/bandwidth_calcs.h" +#include "inc/dce_calcs.h" #include "../dce110/dce110_mem_input.h" #include "dce80_mem_input.h" diff --git a/drivers/gpu/drm/amd/display/dc/inc/bandwidth_calcs.h b/drivers/gpu/drm/amd/display/dc/inc/bandwidth_calcs.h deleted file mode 100644 index 81fab9ef3637..000000000000 --- a/drivers/gpu/drm/amd/display/dc/inc/bandwidth_calcs.h +++ /dev/null @@ -1,504 +0,0 @@ -/* - * Copyright 2015 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -/** - * Bandwidth and Watermark calculations interface. - * (Refer to "DCEx_mode_support.xlsm" from Perforce.) - */ -#ifndef __BANDWIDTH_CALCS_H__ -#define __BANDWIDTH_CALCS_H__ - -#include "bw_fixed.h" - -struct pipe_ctx; - -enum bw_calcs_version { - BW_CALCS_VERSION_INVALID, - BW_CALCS_VERSION_CARRIZO, - BW_CALCS_VERSION_POLARIS10, - BW_CALCS_VERSION_POLARIS11, - BW_CALCS_VERSION_STONEY, - BW_CALCS_VERSION_VEGA10 -}; - -/******************************************************************************* - * There are three types of input into Calculations: - * 1. per-DCE static values - these are "hardcoded" properties of the DCEIP - * 2. board-level values - these are generally coming from VBIOS parser - * 3. mode/configuration values - depending Mode, Scaling number of Displays etc. - ******************************************************************************/ - -enum bw_defines { - //Common - bw_def_no = 0, - bw_def_none = 0, - bw_def_yes = 1, - bw_def_ok = 1, - bw_def_high = 2, - bw_def_mid = 1, - bw_def_low = 0, - - //Internal - bw_defs_start = 255, - bw_def_underlay422, - bw_def_underlay420_luma, - bw_def_underlay420_chroma, - bw_def_underlay444, - bw_def_graphics, - bw_def_display_write_back420_luma, - bw_def_display_write_back420_chroma, - bw_def_portrait, - bw_def_hsr_mtn_4, - bw_def_hsr_mtn_h_taps, - bw_def_ceiling__h_taps_div_4___meq_hsr, - bw_def_invalid_linear_or_stereo_mode, - bw_def_invalid_rotation_or_bpp_or_stereo, - bw_def_vsr_mtn_v_taps, - bw_def_vsr_mtn_4, - bw_def_auto, - bw_def_manual, - bw_def_exceeded_allowed_maximum_sclk, - bw_def_exceeded_allowed_page_close_open, - bw_def_exceeded_allowed_outstanding_pte_req_queue_size, - bw_def_exceeded_allowed_maximum_bw, - bw_def_landscape, - - //Panning and bezel - bw_def_any_lines, - - //Underlay mode - bw_def_underlay_only, - bw_def_blended, - bw_def_blend, - - //Stereo mode - bw_def_mono, - bw_def_side_by_side, - bw_def_top_bottom, - - //Underlay surface type - bw_def_420, - bw_def_422, - bw_def_444, - - //Tiling mode - bw_def_linear, - bw_def_tiled, - bw_def_array_linear_general, - bw_def_array_linear_aligned, - bw_def_rotated_micro_tiling, - bw_def_display_micro_tiling, - - //Memory type - bw_def_gddr5, - bw_def_hbm, - - //Voltage - bw_def_high_no_nbp_state_change, - bw_def_0_72, - bw_def_0_8, - bw_def_0_9, - - bw_def_notok = -1, - bw_def_na = -1 -}; - -struct bw_calcs_dceip { - enum bw_calcs_version version; - bool large_cursor; - uint32_t cursor_max_outstanding_group_num; - bool dmif_pipe_en_fbc_chunk_tracker; - struct bw_fixed dmif_request_buffer_size; - uint32_t lines_interleaved_into_lb; - uint32_t low_power_tiling_mode; - uint32_t chunk_width; - uint32_t number_of_graphics_pipes; - uint32_t number_of_underlay_pipes; - bool display_write_back_supported; - bool argb_compression_support; - struct bw_fixed underlay_vscaler_efficiency6_bit_per_component; - struct bw_fixed underlay_vscaler_efficiency8_bit_per_component; - struct bw_fixed underlay_vscaler_efficiency10_bit_per_component; - struct bw_fixed underlay_vscaler_efficiency12_bit_per_component; - struct bw_fixed graphics_vscaler_efficiency6_bit_per_component; - struct bw_fixed graphics_vscaler_efficiency8_bit_per_component; - struct bw_fixed graphics_vscaler_efficiency10_bit_per_component; - struct bw_fixed graphics_vscaler_efficiency12_bit_per_component; - struct bw_fixed alpha_vscaler_efficiency; - uint32_t max_dmif_buffer_allocated; - uint32_t graphics_dmif_size; - uint32_t underlay_luma_dmif_size; - uint32_t underlay_chroma_dmif_size; - bool pre_downscaler_enabled; - bool underlay_downscale_prefetch_enabled; - struct bw_fixed lb_write_pixels_per_dispclk; - struct bw_fixed lb_size_per_component444; - bool graphics_lb_nodownscaling_multi_line_prefetching; - struct bw_fixed stutter_and_dram_clock_state_change_gated_before_cursor; - struct bw_fixed underlay420_luma_lb_size_per_component; - struct bw_fixed underlay420_chroma_lb_size_per_component; - struct bw_fixed underlay422_lb_size_per_component; - struct bw_fixed cursor_chunk_width; - struct bw_fixed cursor_dcp_buffer_lines; - struct bw_fixed underlay_maximum_width_efficient_for_tiling; - struct bw_fixed underlay_maximum_height_efficient_for_tiling; - struct bw_fixed peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display; - struct bw_fixed peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation; - struct bw_fixed minimum_outstanding_pte_request_limit; - struct bw_fixed maximum_total_outstanding_pte_requests_allowed_by_saw; - bool limit_excessive_outstanding_dmif_requests; - struct bw_fixed linear_mode_line_request_alternation_slice; - uint32_t scatter_gather_lines_of_pte_prefetching_in_linear_mode; - uint32_t display_write_back420_luma_mcifwr_buffer_size; - uint32_t display_write_back420_chroma_mcifwr_buffer_size; - struct bw_fixed request_efficiency; - struct bw_fixed dispclk_per_request; - struct bw_fixed dispclk_ramping_factor; - struct bw_fixed display_pipe_throughput_factor; - uint32_t scatter_gather_pte_request_rows_in_tiling_mode; - struct bw_fixed mcifwr_all_surfaces_burst_time; -}; - -struct bw_calcs_vbios { - enum bw_defines memory_type; - uint32_t dram_channel_width_in_bits; - uint32_t number_of_dram_channels; - uint32_t number_of_dram_banks; - struct bw_fixed low_yclk; /*m_hz*/ - struct bw_fixed mid_yclk; /*m_hz*/ - struct bw_fixed high_yclk; /*m_hz*/ - struct bw_fixed low_sclk; /*m_hz*/ - struct bw_fixed mid1_sclk; /*m_hz*/ - struct bw_fixed mid2_sclk; /*m_hz*/ - struct bw_fixed mid3_sclk; /*m_hz*/ - struct bw_fixed mid4_sclk; /*m_hz*/ - struct bw_fixed mid5_sclk; /*m_hz*/ - struct bw_fixed mid6_sclk; /*m_hz*/ - struct bw_fixed high_sclk; /*m_hz*/ - struct bw_fixed low_voltage_max_dispclk; /*m_hz*/ - struct bw_fixed mid_voltage_max_dispclk; /*m_hz*/ - struct bw_fixed high_voltage_max_dispclk; /*m_hz*/ - struct bw_fixed low_voltage_max_phyclk; - struct bw_fixed mid_voltage_max_phyclk; - struct bw_fixed high_voltage_max_phyclk; - struct bw_fixed data_return_bus_width; - struct bw_fixed trc; - struct bw_fixed dmifmc_urgent_latency; - struct bw_fixed stutter_self_refresh_exit_latency; - struct bw_fixed stutter_self_refresh_entry_latency; - struct bw_fixed nbp_state_change_latency; - struct bw_fixed mcifwrmc_urgent_latency; - bool scatter_gather_enable; - struct bw_fixed down_spread_percentage; - uint32_t cursor_width; - uint32_t average_compression_rate; - uint32_t number_of_request_slots_gmc_reserves_for_dmif_per_channel; - struct bw_fixed blackout_duration; - struct bw_fixed maximum_blackout_recovery_time; -}; - -/******************************************************************************* - * Temporary data structure(s). - ******************************************************************************/ -#define maximum_number_of_surfaces 12 -/*Units : MHz, us */ - -struct bw_calcs_data { - /* data for all displays */ - uint32_t number_of_displays; - enum bw_defines underlay_surface_type; - enum bw_defines panning_and_bezel_adjustment; - enum bw_defines graphics_tiling_mode; - uint32_t graphics_lb_bpc; - uint32_t underlay_lb_bpc; - enum bw_defines underlay_tiling_mode; - enum bw_defines d0_underlay_mode; - bool d1_display_write_back_dwb_enable; - enum bw_defines d1_underlay_mode; - - bool cpup_state_change_enable; - bool cpuc_state_change_enable; - bool nbp_state_change_enable; - bool stutter_mode_enable; - uint32_t y_clk_level; - uint32_t sclk_level; - uint32_t number_of_underlay_surfaces; - uint32_t number_of_dram_wrchannels; - uint32_t chunk_request_delay; - uint32_t number_of_dram_channels; - enum bw_defines underlay_micro_tile_mode; - enum bw_defines graphics_micro_tile_mode; - struct bw_fixed max_phyclk; - struct bw_fixed dram_efficiency; - struct bw_fixed src_width_after_surface_type; - struct bw_fixed src_height_after_surface_type; - struct bw_fixed hsr_after_surface_type; - struct bw_fixed vsr_after_surface_type; - struct bw_fixed src_width_after_rotation; - struct bw_fixed src_height_after_rotation; - struct bw_fixed hsr_after_rotation; - struct bw_fixed vsr_after_rotation; - struct bw_fixed source_height_pixels; - struct bw_fixed hsr_after_stereo; - struct bw_fixed vsr_after_stereo; - struct bw_fixed source_width_in_lb; - struct bw_fixed lb_line_pitch; - struct bw_fixed underlay_maximum_source_efficient_for_tiling; - struct bw_fixed num_lines_at_frame_start; - struct bw_fixed min_dmif_size_in_time; - struct bw_fixed min_mcifwr_size_in_time; - struct bw_fixed total_requests_for_dmif_size; - struct bw_fixed peak_pte_request_to_eviction_ratio_limiting; - struct bw_fixed useful_pte_per_pte_request; - struct bw_fixed scatter_gather_pte_request_rows; - struct bw_fixed scatter_gather_row_height; - struct bw_fixed scatter_gather_pte_requests_in_vblank; - struct bw_fixed inefficient_linear_pitch_in_bytes; - struct bw_fixed cursor_total_data; - struct bw_fixed cursor_total_request_groups; - struct bw_fixed scatter_gather_total_pte_requests; - struct bw_fixed scatter_gather_total_pte_request_groups; - struct bw_fixed tile_width_in_pixels; - struct bw_fixed dmif_total_number_of_data_request_page_close_open; - struct bw_fixed mcifwr_total_number_of_data_request_page_close_open; - struct bw_fixed bytes_per_page_close_open; - struct bw_fixed mcifwr_total_page_close_open_time; - struct bw_fixed total_requests_for_adjusted_dmif_size; - struct bw_fixed total_dmifmc_urgent_trips; - struct bw_fixed total_dmifmc_urgent_latency; - struct bw_fixed total_display_reads_required_data; - struct bw_fixed total_display_reads_required_dram_access_data; - struct bw_fixed total_display_writes_required_data; - struct bw_fixed total_display_writes_required_dram_access_data; - struct bw_fixed display_reads_required_data; - struct bw_fixed display_reads_required_dram_access_data; - struct bw_fixed dmif_total_page_close_open_time; - struct bw_fixed min_cursor_memory_interface_buffer_size_in_time; - struct bw_fixed min_read_buffer_size_in_time; - struct bw_fixed display_reads_time_for_data_transfer; - struct bw_fixed display_writes_time_for_data_transfer; - struct bw_fixed dmif_required_dram_bandwidth; - struct bw_fixed mcifwr_required_dram_bandwidth; - struct bw_fixed required_dmifmc_urgent_latency_for_page_close_open; - struct bw_fixed required_mcifmcwr_urgent_latency; - struct bw_fixed required_dram_bandwidth_gbyte_per_second; - struct bw_fixed dram_bandwidth; - struct bw_fixed dmif_required_sclk; - struct bw_fixed mcifwr_required_sclk; - struct bw_fixed required_sclk; - struct bw_fixed downspread_factor; - struct bw_fixed v_scaler_efficiency; - struct bw_fixed scaler_limits_factor; - struct bw_fixed display_pipe_pixel_throughput; - struct bw_fixed total_dispclk_required_with_ramping; - struct bw_fixed total_dispclk_required_without_ramping; - struct bw_fixed total_read_request_bandwidth; - struct bw_fixed total_write_request_bandwidth; - struct bw_fixed dispclk_required_for_total_read_request_bandwidth; - struct bw_fixed total_dispclk_required_with_ramping_with_request_bandwidth; - struct bw_fixed total_dispclk_required_without_ramping_with_request_bandwidth; - struct bw_fixed dispclk; - struct bw_fixed blackout_recovery_time; - struct bw_fixed min_pixels_per_data_fifo_entry; - struct bw_fixed sclk_deep_sleep; - struct bw_fixed chunk_request_time; - struct bw_fixed cursor_request_time; - struct bw_fixed line_source_pixels_transfer_time; - struct bw_fixed dmifdram_access_efficiency; - struct bw_fixed mcifwrdram_access_efficiency; - struct bw_fixed total_average_bandwidth_no_compression; - struct bw_fixed total_average_bandwidth; - struct bw_fixed total_stutter_cycle_duration; - struct bw_fixed stutter_burst_time; - struct bw_fixed time_in_self_refresh; - struct bw_fixed stutter_efficiency; - struct bw_fixed worst_number_of_trips_to_memory; - struct bw_fixed immediate_flip_time; - struct bw_fixed latency_for_non_dmif_clients; - struct bw_fixed latency_for_non_mcifwr_clients; - struct bw_fixed dmifmc_urgent_latency_supported_in_high_sclk_and_yclk; - struct bw_fixed nbp_state_dram_speed_change_margin; - struct bw_fixed display_reads_time_for_data_transfer_and_urgent_latency; - struct bw_fixed dram_speed_change_margin; - struct bw_fixed min_vblank_dram_speed_change_margin; - struct bw_fixed min_stutter_refresh_duration; - uint32_t total_stutter_dmif_buffer_size; - uint32_t total_bytes_requested; - uint32_t min_stutter_dmif_buffer_size; - uint32_t num_stutter_bursts; - struct bw_fixed v_blank_nbp_state_dram_speed_change_latency_supported; - struct bw_fixed nbp_state_dram_speed_change_latency_supported; - bool fbc_en[maximum_number_of_surfaces]; - bool lpt_en[maximum_number_of_surfaces]; - bool displays_match_flag[maximum_number_of_surfaces]; - bool use_alpha[maximum_number_of_surfaces]; - bool orthogonal_rotation[maximum_number_of_surfaces]; - bool enable[maximum_number_of_surfaces]; - bool access_one_channel_only[maximum_number_of_surfaces]; - bool scatter_gather_enable_for_pipe[maximum_number_of_surfaces]; - bool interlace_mode[maximum_number_of_surfaces]; - bool display_pstate_change_enable[maximum_number_of_surfaces]; - bool line_buffer_prefetch[maximum_number_of_surfaces]; - uint32_t bytes_per_pixel[maximum_number_of_surfaces]; - uint32_t max_chunks_non_fbc_mode[maximum_number_of_surfaces]; - uint32_t lb_bpc[maximum_number_of_surfaces]; - uint32_t output_bpphdmi[maximum_number_of_surfaces]; - uint32_t output_bppdp4_lane_hbr[maximum_number_of_surfaces]; - uint32_t output_bppdp4_lane_hbr2[maximum_number_of_surfaces]; - uint32_t output_bppdp4_lane_hbr3[maximum_number_of_surfaces]; - enum bw_defines stereo_mode[maximum_number_of_surfaces]; - struct bw_fixed dmif_buffer_transfer_time[maximum_number_of_surfaces]; - struct bw_fixed displays_with_same_mode[maximum_number_of_surfaces]; - struct bw_fixed stutter_dmif_buffer_size[maximum_number_of_surfaces]; - struct bw_fixed stutter_refresh_duration[maximum_number_of_surfaces]; - struct bw_fixed stutter_exit_watermark[maximum_number_of_surfaces]; - struct bw_fixed stutter_entry_watermark[maximum_number_of_surfaces]; - struct bw_fixed h_total[maximum_number_of_surfaces]; - struct bw_fixed v_total[maximum_number_of_surfaces]; - struct bw_fixed pixel_rate[maximum_number_of_surfaces]; - struct bw_fixed src_width[maximum_number_of_surfaces]; - struct bw_fixed pitch_in_pixels[maximum_number_of_surfaces]; - struct bw_fixed pitch_in_pixels_after_surface_type[maximum_number_of_surfaces]; - struct bw_fixed src_height[maximum_number_of_surfaces]; - struct bw_fixed scale_ratio[maximum_number_of_surfaces]; - struct bw_fixed h_taps[maximum_number_of_surfaces]; - struct bw_fixed v_taps[maximum_number_of_surfaces]; - struct bw_fixed h_scale_ratio[maximum_number_of_surfaces]; - struct bw_fixed v_scale_ratio[maximum_number_of_surfaces]; - struct bw_fixed rotation_angle[maximum_number_of_surfaces]; - struct bw_fixed compression_rate[maximum_number_of_surfaces]; - struct bw_fixed hsr[maximum_number_of_surfaces]; - struct bw_fixed vsr[maximum_number_of_surfaces]; - struct bw_fixed source_width_rounded_up_to_chunks[maximum_number_of_surfaces]; - struct bw_fixed source_width_pixels[maximum_number_of_surfaces]; - struct bw_fixed source_height_rounded_up_to_chunks[maximum_number_of_surfaces]; - struct bw_fixed display_bandwidth[maximum_number_of_surfaces]; - struct bw_fixed request_bandwidth[maximum_number_of_surfaces]; - struct bw_fixed bytes_per_request[maximum_number_of_surfaces]; - struct bw_fixed useful_bytes_per_request[maximum_number_of_surfaces]; - struct bw_fixed lines_interleaved_in_mem_access[maximum_number_of_surfaces]; - struct bw_fixed latency_hiding_lines[maximum_number_of_surfaces]; - struct bw_fixed lb_partitions[maximum_number_of_surfaces]; - struct bw_fixed lb_partitions_max[maximum_number_of_surfaces]; - struct bw_fixed dispclk_required_with_ramping[maximum_number_of_surfaces]; - struct bw_fixed dispclk_required_without_ramping[maximum_number_of_surfaces]; - struct bw_fixed data_buffer_size[maximum_number_of_surfaces]; - struct bw_fixed outstanding_chunk_request_limit[maximum_number_of_surfaces]; - struct bw_fixed urgent_watermark[maximum_number_of_surfaces]; - struct bw_fixed nbp_state_change_watermark[maximum_number_of_surfaces]; - struct bw_fixed v_filter_init[maximum_number_of_surfaces]; - struct bw_fixed stutter_cycle_duration[maximum_number_of_surfaces]; - struct bw_fixed average_bandwidth[maximum_number_of_surfaces]; - struct bw_fixed average_bandwidth_no_compression[maximum_number_of_surfaces]; - struct bw_fixed scatter_gather_pte_request_limit[maximum_number_of_surfaces]; - struct bw_fixed lb_size_per_component[maximum_number_of_surfaces]; - struct bw_fixed memory_chunk_size_in_bytes[maximum_number_of_surfaces]; - struct bw_fixed pipe_chunk_size_in_bytes[maximum_number_of_surfaces]; - struct bw_fixed number_of_trips_to_memory_for_getting_apte_row[maximum_number_of_surfaces]; - struct bw_fixed adjusted_data_buffer_size[maximum_number_of_surfaces]; - struct bw_fixed adjusted_data_buffer_size_in_memory[maximum_number_of_surfaces]; - struct bw_fixed pixels_per_data_fifo_entry[maximum_number_of_surfaces]; - struct bw_fixed scatter_gather_pte_requests_in_row[maximum_number_of_surfaces]; - struct bw_fixed pte_request_per_chunk[maximum_number_of_surfaces]; - struct bw_fixed scatter_gather_page_width[maximum_number_of_surfaces]; - struct bw_fixed scatter_gather_page_height[maximum_number_of_surfaces]; - struct bw_fixed lb_lines_in_per_line_out_in_beginning_of_frame[maximum_number_of_surfaces]; - struct bw_fixed lb_lines_in_per_line_out_in_middle_of_frame[maximum_number_of_surfaces]; - struct bw_fixed cursor_width_pixels[maximum_number_of_surfaces]; - struct bw_fixed minimum_latency_hiding[maximum_number_of_surfaces]; - struct bw_fixed maximum_latency_hiding[maximum_number_of_surfaces]; - struct bw_fixed minimum_latency_hiding_with_cursor[maximum_number_of_surfaces]; - struct bw_fixed maximum_latency_hiding_with_cursor[maximum_number_of_surfaces]; - struct bw_fixed src_pixels_for_first_output_pixel[maximum_number_of_surfaces]; - struct bw_fixed src_pixels_for_last_output_pixel[maximum_number_of_surfaces]; - struct bw_fixed src_data_for_first_output_pixel[maximum_number_of_surfaces]; - struct bw_fixed src_data_for_last_output_pixel[maximum_number_of_surfaces]; - struct bw_fixed active_time[maximum_number_of_surfaces]; - struct bw_fixed horizontal_blank_and_chunk_granularity_factor[maximum_number_of_surfaces]; - struct bw_fixed cursor_latency_hiding[maximum_number_of_surfaces]; - struct bw_fixed v_blank_dram_speed_change_margin[maximum_number_of_surfaces]; - uint32_t num_displays_with_margin[3][8]; - struct bw_fixed dmif_burst_time[3][8]; - struct bw_fixed mcifwr_burst_time[3][8]; - struct bw_fixed line_source_transfer_time[maximum_number_of_surfaces][3][8]; - struct bw_fixed dram_speed_change_line_source_transfer_time[maximum_number_of_surfaces][3][8]; - struct bw_fixed min_dram_speed_change_margin[3][8]; - struct bw_fixed dispclk_required_for_dram_speed_change[3][8]; - struct bw_fixed blackout_duration_margin[3][8]; - struct bw_fixed dispclk_required_for_blackout_duration[3][8]; - struct bw_fixed dispclk_required_for_blackout_recovery[3][8]; - struct bw_fixed dmif_required_sclk_for_urgent_latency[6]; -}; - -/******************************************************************************* - * Output data structures. - ******************************************************************************/ -struct bw_watermarks { - uint32_t a_mark; - uint32_t b_mark; - uint32_t c_mark; - uint32_t d_mark; -}; - -struct bw_calcs_output { - bool cpuc_state_change_enable; - bool cpup_state_change_enable; - bool stutter_mode_enable; - bool nbp_state_change_enable; - bool all_displays_in_sync; - struct bw_watermarks urgent_wm_ns[6]; - struct bw_watermarks stutter_exit_wm_ns[6]; - struct bw_watermarks nbp_state_change_wm_ns[6]; - uint32_t required_sclk; - uint32_t required_sclk_deep_sleep; - uint32_t required_yclk; - uint32_t dispclk_khz; - int blackout_recovery_time_us; -}; - -/** - * Initialize structures with data which will NOT change at runtime. - */ -void bw_calcs_init( - struct bw_calcs_dceip *bw_dceip, - struct bw_calcs_vbios *bw_vbios, - struct hw_asic_id asic_id); - -/** - * Return: - * true - Display(s) configuration supported. - * In this case 'calcs_output' contains data for HW programming - * false - Display(s) configuration not supported (not enough bandwidth). - */ -bool bw_calcs( - struct dc_context *ctx, - const struct bw_calcs_dceip *dceip, - const struct bw_calcs_vbios *vbios, - const struct pipe_ctx *pipe, - int pipe_count, - struct bw_calcs_output *calcs_output); - -#endif /* __BANDWIDTH_CALCS_H__ */ - diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 7f3c6da1ebd7..405608318ccc 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -27,7 +27,7 @@ #define _CORE_TYPES_H_ #include "dc.h" -#include "bandwidth_calcs.h" +#include "dce_calcs.h" #include "ddc_service_types.h" #include "dc_bios_types.h" diff --git a/drivers/gpu/drm/amd/display/dc/inc/dce_calcs.h b/drivers/gpu/drm/amd/display/dc/inc/dce_calcs.h new file mode 100644 index 000000000000..580dee95e57a --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/dce_calcs.h @@ -0,0 +1,506 @@ +/* + * Copyright 2015-2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +/** + * Bandwidth and Watermark calculations interface. + * (Refer to "DCEx_mode_support.xlsm" from Perforce.) + */ +#ifndef __DCE_CALCS_H__ +#define __DCE_CALCS_H__ + +#include "bw_fixed.h" + +struct pipe_ctx; +struct core_dc; +struct validate_context; + +enum bw_calcs_version { + BW_CALCS_VERSION_INVALID, + BW_CALCS_VERSION_CARRIZO, + BW_CALCS_VERSION_POLARIS10, + BW_CALCS_VERSION_POLARIS11, + BW_CALCS_VERSION_STONEY, + BW_CALCS_VERSION_VEGA10 +}; + +/******************************************************************************* + * There are three types of input into Calculations: + * 1. per-DCE static values - these are "hardcoded" properties of the DCEIP + * 2. board-level values - these are generally coming from VBIOS parser + * 3. mode/configuration values - depending Mode, Scaling number of Displays etc. + ******************************************************************************/ + +enum bw_defines { + //Common + bw_def_no = 0, + bw_def_none = 0, + bw_def_yes = 1, + bw_def_ok = 1, + bw_def_high = 2, + bw_def_mid = 1, + bw_def_low = 0, + + //Internal + bw_defs_start = 255, + bw_def_underlay422, + bw_def_underlay420_luma, + bw_def_underlay420_chroma, + bw_def_underlay444, + bw_def_graphics, + bw_def_display_write_back420_luma, + bw_def_display_write_back420_chroma, + bw_def_portrait, + bw_def_hsr_mtn_4, + bw_def_hsr_mtn_h_taps, + bw_def_ceiling__h_taps_div_4___meq_hsr, + bw_def_invalid_linear_or_stereo_mode, + bw_def_invalid_rotation_or_bpp_or_stereo, + bw_def_vsr_mtn_v_taps, + bw_def_vsr_mtn_4, + bw_def_auto, + bw_def_manual, + bw_def_exceeded_allowed_maximum_sclk, + bw_def_exceeded_allowed_page_close_open, + bw_def_exceeded_allowed_outstanding_pte_req_queue_size, + bw_def_exceeded_allowed_maximum_bw, + bw_def_landscape, + + //Panning and bezel + bw_def_any_lines, + + //Underlay mode + bw_def_underlay_only, + bw_def_blended, + bw_def_blend, + + //Stereo mode + bw_def_mono, + bw_def_side_by_side, + bw_def_top_bottom, + + //Underlay surface type + bw_def_420, + bw_def_422, + bw_def_444, + + //Tiling mode + bw_def_linear, + bw_def_tiled, + bw_def_array_linear_general, + bw_def_array_linear_aligned, + bw_def_rotated_micro_tiling, + bw_def_display_micro_tiling, + + //Memory type + bw_def_gddr5, + bw_def_hbm, + + //Voltage + bw_def_high_no_nbp_state_change, + bw_def_0_72, + bw_def_0_8, + bw_def_0_9, + + bw_def_notok = -1, + bw_def_na = -1 +}; + +struct bw_calcs_dceip { + enum bw_calcs_version version; + bool large_cursor; + uint32_t cursor_max_outstanding_group_num; + bool dmif_pipe_en_fbc_chunk_tracker; + struct bw_fixed dmif_request_buffer_size; + uint32_t lines_interleaved_into_lb; + uint32_t low_power_tiling_mode; + uint32_t chunk_width; + uint32_t number_of_graphics_pipes; + uint32_t number_of_underlay_pipes; + bool display_write_back_supported; + bool argb_compression_support; + struct bw_fixed underlay_vscaler_efficiency6_bit_per_component; + struct bw_fixed underlay_vscaler_efficiency8_bit_per_component; + struct bw_fixed underlay_vscaler_efficiency10_bit_per_component; + struct bw_fixed underlay_vscaler_efficiency12_bit_per_component; + struct bw_fixed graphics_vscaler_efficiency6_bit_per_component; + struct bw_fixed graphics_vscaler_efficiency8_bit_per_component; + struct bw_fixed graphics_vscaler_efficiency10_bit_per_component; + struct bw_fixed graphics_vscaler_efficiency12_bit_per_component; + struct bw_fixed alpha_vscaler_efficiency; + uint32_t max_dmif_buffer_allocated; + uint32_t graphics_dmif_size; + uint32_t underlay_luma_dmif_size; + uint32_t underlay_chroma_dmif_size; + bool pre_downscaler_enabled; + bool underlay_downscale_prefetch_enabled; + struct bw_fixed lb_write_pixels_per_dispclk; + struct bw_fixed lb_size_per_component444; + bool graphics_lb_nodownscaling_multi_line_prefetching; + struct bw_fixed stutter_and_dram_clock_state_change_gated_before_cursor; + struct bw_fixed underlay420_luma_lb_size_per_component; + struct bw_fixed underlay420_chroma_lb_size_per_component; + struct bw_fixed underlay422_lb_size_per_component; + struct bw_fixed cursor_chunk_width; + struct bw_fixed cursor_dcp_buffer_lines; + struct bw_fixed underlay_maximum_width_efficient_for_tiling; + struct bw_fixed underlay_maximum_height_efficient_for_tiling; + struct bw_fixed peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display; + struct bw_fixed peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation; + struct bw_fixed minimum_outstanding_pte_request_limit; + struct bw_fixed maximum_total_outstanding_pte_requests_allowed_by_saw; + bool limit_excessive_outstanding_dmif_requests; + struct bw_fixed linear_mode_line_request_alternation_slice; + uint32_t scatter_gather_lines_of_pte_prefetching_in_linear_mode; + uint32_t display_write_back420_luma_mcifwr_buffer_size; + uint32_t display_write_back420_chroma_mcifwr_buffer_size; + struct bw_fixed request_efficiency; + struct bw_fixed dispclk_per_request; + struct bw_fixed dispclk_ramping_factor; + struct bw_fixed display_pipe_throughput_factor; + uint32_t scatter_gather_pte_request_rows_in_tiling_mode; + struct bw_fixed mcifwr_all_surfaces_burst_time; +}; + +struct bw_calcs_vbios { + enum bw_defines memory_type; + uint32_t dram_channel_width_in_bits; + uint32_t number_of_dram_channels; + uint32_t number_of_dram_banks; + struct bw_fixed low_yclk; /*m_hz*/ + struct bw_fixed mid_yclk; /*m_hz*/ + struct bw_fixed high_yclk; /*m_hz*/ + struct bw_fixed low_sclk; /*m_hz*/ + struct bw_fixed mid1_sclk; /*m_hz*/ + struct bw_fixed mid2_sclk; /*m_hz*/ + struct bw_fixed mid3_sclk; /*m_hz*/ + struct bw_fixed mid4_sclk; /*m_hz*/ + struct bw_fixed mid5_sclk; /*m_hz*/ + struct bw_fixed mid6_sclk; /*m_hz*/ + struct bw_fixed high_sclk; /*m_hz*/ + struct bw_fixed low_voltage_max_dispclk; /*m_hz*/ + struct bw_fixed mid_voltage_max_dispclk; /*m_hz*/ + struct bw_fixed high_voltage_max_dispclk; /*m_hz*/ + struct bw_fixed low_voltage_max_phyclk; + struct bw_fixed mid_voltage_max_phyclk; + struct bw_fixed high_voltage_max_phyclk; + struct bw_fixed data_return_bus_width; + struct bw_fixed trc; + struct bw_fixed dmifmc_urgent_latency; + struct bw_fixed stutter_self_refresh_exit_latency; + struct bw_fixed stutter_self_refresh_entry_latency; + struct bw_fixed nbp_state_change_latency; + struct bw_fixed mcifwrmc_urgent_latency; + bool scatter_gather_enable; + struct bw_fixed down_spread_percentage; + uint32_t cursor_width; + uint32_t average_compression_rate; + uint32_t number_of_request_slots_gmc_reserves_for_dmif_per_channel; + struct bw_fixed blackout_duration; + struct bw_fixed maximum_blackout_recovery_time; +}; + +/******************************************************************************* + * Temporary data structure(s). + ******************************************************************************/ +#define maximum_number_of_surfaces 12 +/*Units : MHz, us */ + +struct bw_calcs_data { + /* data for all displays */ + uint32_t number_of_displays; + enum bw_defines underlay_surface_type; + enum bw_defines panning_and_bezel_adjustment; + enum bw_defines graphics_tiling_mode; + uint32_t graphics_lb_bpc; + uint32_t underlay_lb_bpc; + enum bw_defines underlay_tiling_mode; + enum bw_defines d0_underlay_mode; + bool d1_display_write_back_dwb_enable; + enum bw_defines d1_underlay_mode; + + bool cpup_state_change_enable; + bool cpuc_state_change_enable; + bool nbp_state_change_enable; + bool stutter_mode_enable; + uint32_t y_clk_level; + uint32_t sclk_level; + uint32_t number_of_underlay_surfaces; + uint32_t number_of_dram_wrchannels; + uint32_t chunk_request_delay; + uint32_t number_of_dram_channels; + enum bw_defines underlay_micro_tile_mode; + enum bw_defines graphics_micro_tile_mode; + struct bw_fixed max_phyclk; + struct bw_fixed dram_efficiency; + struct bw_fixed src_width_after_surface_type; + struct bw_fixed src_height_after_surface_type; + struct bw_fixed hsr_after_surface_type; + struct bw_fixed vsr_after_surface_type; + struct bw_fixed src_width_after_rotation; + struct bw_fixed src_height_after_rotation; + struct bw_fixed hsr_after_rotation; + struct bw_fixed vsr_after_rotation; + struct bw_fixed source_height_pixels; + struct bw_fixed hsr_after_stereo; + struct bw_fixed vsr_after_stereo; + struct bw_fixed source_width_in_lb; + struct bw_fixed lb_line_pitch; + struct bw_fixed underlay_maximum_source_efficient_for_tiling; + struct bw_fixed num_lines_at_frame_start; + struct bw_fixed min_dmif_size_in_time; + struct bw_fixed min_mcifwr_size_in_time; + struct bw_fixed total_requests_for_dmif_size; + struct bw_fixed peak_pte_request_to_eviction_ratio_limiting; + struct bw_fixed useful_pte_per_pte_request; + struct bw_fixed scatter_gather_pte_request_rows; + struct bw_fixed scatter_gather_row_height; + struct bw_fixed scatter_gather_pte_requests_in_vblank; + struct bw_fixed inefficient_linear_pitch_in_bytes; + struct bw_fixed cursor_total_data; + struct bw_fixed cursor_total_request_groups; + struct bw_fixed scatter_gather_total_pte_requests; + struct bw_fixed scatter_gather_total_pte_request_groups; + struct bw_fixed tile_width_in_pixels; + struct bw_fixed dmif_total_number_of_data_request_page_close_open; + struct bw_fixed mcifwr_total_number_of_data_request_page_close_open; + struct bw_fixed bytes_per_page_close_open; + struct bw_fixed mcifwr_total_page_close_open_time; + struct bw_fixed total_requests_for_adjusted_dmif_size; + struct bw_fixed total_dmifmc_urgent_trips; + struct bw_fixed total_dmifmc_urgent_latency; + struct bw_fixed total_display_reads_required_data; + struct bw_fixed total_display_reads_required_dram_access_data; + struct bw_fixed total_display_writes_required_data; + struct bw_fixed total_display_writes_required_dram_access_data; + struct bw_fixed display_reads_required_data; + struct bw_fixed display_reads_required_dram_access_data; + struct bw_fixed dmif_total_page_close_open_time; + struct bw_fixed min_cursor_memory_interface_buffer_size_in_time; + struct bw_fixed min_read_buffer_size_in_time; + struct bw_fixed display_reads_time_for_data_transfer; + struct bw_fixed display_writes_time_for_data_transfer; + struct bw_fixed dmif_required_dram_bandwidth; + struct bw_fixed mcifwr_required_dram_bandwidth; + struct bw_fixed required_dmifmc_urgent_latency_for_page_close_open; + struct bw_fixed required_mcifmcwr_urgent_latency; + struct bw_fixed required_dram_bandwidth_gbyte_per_second; + struct bw_fixed dram_bandwidth; + struct bw_fixed dmif_required_sclk; + struct bw_fixed mcifwr_required_sclk; + struct bw_fixed required_sclk; + struct bw_fixed downspread_factor; + struct bw_fixed v_scaler_efficiency; + struct bw_fixed scaler_limits_factor; + struct bw_fixed display_pipe_pixel_throughput; + struct bw_fixed total_dispclk_required_with_ramping; + struct bw_fixed total_dispclk_required_without_ramping; + struct bw_fixed total_read_request_bandwidth; + struct bw_fixed total_write_request_bandwidth; + struct bw_fixed dispclk_required_for_total_read_request_bandwidth; + struct bw_fixed total_dispclk_required_with_ramping_with_request_bandwidth; + struct bw_fixed total_dispclk_required_without_ramping_with_request_bandwidth; + struct bw_fixed dispclk; + struct bw_fixed blackout_recovery_time; + struct bw_fixed min_pixels_per_data_fifo_entry; + struct bw_fixed sclk_deep_sleep; + struct bw_fixed chunk_request_time; + struct bw_fixed cursor_request_time; + struct bw_fixed line_source_pixels_transfer_time; + struct bw_fixed dmifdram_access_efficiency; + struct bw_fixed mcifwrdram_access_efficiency; + struct bw_fixed total_average_bandwidth_no_compression; + struct bw_fixed total_average_bandwidth; + struct bw_fixed total_stutter_cycle_duration; + struct bw_fixed stutter_burst_time; + struct bw_fixed time_in_self_refresh; + struct bw_fixed stutter_efficiency; + struct bw_fixed worst_number_of_trips_to_memory; + struct bw_fixed immediate_flip_time; + struct bw_fixed latency_for_non_dmif_clients; + struct bw_fixed latency_for_non_mcifwr_clients; + struct bw_fixed dmifmc_urgent_latency_supported_in_high_sclk_and_yclk; + struct bw_fixed nbp_state_dram_speed_change_margin; + struct bw_fixed display_reads_time_for_data_transfer_and_urgent_latency; + struct bw_fixed dram_speed_change_margin; + struct bw_fixed min_vblank_dram_speed_change_margin; + struct bw_fixed min_stutter_refresh_duration; + uint32_t total_stutter_dmif_buffer_size; + uint32_t total_bytes_requested; + uint32_t min_stutter_dmif_buffer_size; + uint32_t num_stutter_bursts; + struct bw_fixed v_blank_nbp_state_dram_speed_change_latency_supported; + struct bw_fixed nbp_state_dram_speed_change_latency_supported; + bool fbc_en[maximum_number_of_surfaces]; + bool lpt_en[maximum_number_of_surfaces]; + bool displays_match_flag[maximum_number_of_surfaces]; + bool use_alpha[maximum_number_of_surfaces]; + bool orthogonal_rotation[maximum_number_of_surfaces]; + bool enable[maximum_number_of_surfaces]; + bool access_one_channel_only[maximum_number_of_surfaces]; + bool scatter_gather_enable_for_pipe[maximum_number_of_surfaces]; + bool interlace_mode[maximum_number_of_surfaces]; + bool display_pstate_change_enable[maximum_number_of_surfaces]; + bool line_buffer_prefetch[maximum_number_of_surfaces]; + uint32_t bytes_per_pixel[maximum_number_of_surfaces]; + uint32_t max_chunks_non_fbc_mode[maximum_number_of_surfaces]; + uint32_t lb_bpc[maximum_number_of_surfaces]; + uint32_t output_bpphdmi[maximum_number_of_surfaces]; + uint32_t output_bppdp4_lane_hbr[maximum_number_of_surfaces]; + uint32_t output_bppdp4_lane_hbr2[maximum_number_of_surfaces]; + uint32_t output_bppdp4_lane_hbr3[maximum_number_of_surfaces]; + enum bw_defines stereo_mode[maximum_number_of_surfaces]; + struct bw_fixed dmif_buffer_transfer_time[maximum_number_of_surfaces]; + struct bw_fixed displays_with_same_mode[maximum_number_of_surfaces]; + struct bw_fixed stutter_dmif_buffer_size[maximum_number_of_surfaces]; + struct bw_fixed stutter_refresh_duration[maximum_number_of_surfaces]; + struct bw_fixed stutter_exit_watermark[maximum_number_of_surfaces]; + struct bw_fixed stutter_entry_watermark[maximum_number_of_surfaces]; + struct bw_fixed h_total[maximum_number_of_surfaces]; + struct bw_fixed v_total[maximum_number_of_surfaces]; + struct bw_fixed pixel_rate[maximum_number_of_surfaces]; + struct bw_fixed src_width[maximum_number_of_surfaces]; + struct bw_fixed pitch_in_pixels[maximum_number_of_surfaces]; + struct bw_fixed pitch_in_pixels_after_surface_type[maximum_number_of_surfaces]; + struct bw_fixed src_height[maximum_number_of_surfaces]; + struct bw_fixed scale_ratio[maximum_number_of_surfaces]; + struct bw_fixed h_taps[maximum_number_of_surfaces]; + struct bw_fixed v_taps[maximum_number_of_surfaces]; + struct bw_fixed h_scale_ratio[maximum_number_of_surfaces]; + struct bw_fixed v_scale_ratio[maximum_number_of_surfaces]; + struct bw_fixed rotation_angle[maximum_number_of_surfaces]; + struct bw_fixed compression_rate[maximum_number_of_surfaces]; + struct bw_fixed hsr[maximum_number_of_surfaces]; + struct bw_fixed vsr[maximum_number_of_surfaces]; + struct bw_fixed source_width_rounded_up_to_chunks[maximum_number_of_surfaces]; + struct bw_fixed source_width_pixels[maximum_number_of_surfaces]; + struct bw_fixed source_height_rounded_up_to_chunks[maximum_number_of_surfaces]; + struct bw_fixed display_bandwidth[maximum_number_of_surfaces]; + struct bw_fixed request_bandwidth[maximum_number_of_surfaces]; + struct bw_fixed bytes_per_request[maximum_number_of_surfaces]; + struct bw_fixed useful_bytes_per_request[maximum_number_of_surfaces]; + struct bw_fixed lines_interleaved_in_mem_access[maximum_number_of_surfaces]; + struct bw_fixed latency_hiding_lines[maximum_number_of_surfaces]; + struct bw_fixed lb_partitions[maximum_number_of_surfaces]; + struct bw_fixed lb_partitions_max[maximum_number_of_surfaces]; + struct bw_fixed dispclk_required_with_ramping[maximum_number_of_surfaces]; + struct bw_fixed dispclk_required_without_ramping[maximum_number_of_surfaces]; + struct bw_fixed data_buffer_size[maximum_number_of_surfaces]; + struct bw_fixed outstanding_chunk_request_limit[maximum_number_of_surfaces]; + struct bw_fixed urgent_watermark[maximum_number_of_surfaces]; + struct bw_fixed nbp_state_change_watermark[maximum_number_of_surfaces]; + struct bw_fixed v_filter_init[maximum_number_of_surfaces]; + struct bw_fixed stutter_cycle_duration[maximum_number_of_surfaces]; + struct bw_fixed average_bandwidth[maximum_number_of_surfaces]; + struct bw_fixed average_bandwidth_no_compression[maximum_number_of_surfaces]; + struct bw_fixed scatter_gather_pte_request_limit[maximum_number_of_surfaces]; + struct bw_fixed lb_size_per_component[maximum_number_of_surfaces]; + struct bw_fixed memory_chunk_size_in_bytes[maximum_number_of_surfaces]; + struct bw_fixed pipe_chunk_size_in_bytes[maximum_number_of_surfaces]; + struct bw_fixed number_of_trips_to_memory_for_getting_apte_row[maximum_number_of_surfaces]; + struct bw_fixed adjusted_data_buffer_size[maximum_number_of_surfaces]; + struct bw_fixed adjusted_data_buffer_size_in_memory[maximum_number_of_surfaces]; + struct bw_fixed pixels_per_data_fifo_entry[maximum_number_of_surfaces]; + struct bw_fixed scatter_gather_pte_requests_in_row[maximum_number_of_surfaces]; + struct bw_fixed pte_request_per_chunk[maximum_number_of_surfaces]; + struct bw_fixed scatter_gather_page_width[maximum_number_of_surfaces]; + struct bw_fixed scatter_gather_page_height[maximum_number_of_surfaces]; + struct bw_fixed lb_lines_in_per_line_out_in_beginning_of_frame[maximum_number_of_surfaces]; + struct bw_fixed lb_lines_in_per_line_out_in_middle_of_frame[maximum_number_of_surfaces]; + struct bw_fixed cursor_width_pixels[maximum_number_of_surfaces]; + struct bw_fixed minimum_latency_hiding[maximum_number_of_surfaces]; + struct bw_fixed maximum_latency_hiding[maximum_number_of_surfaces]; + struct bw_fixed minimum_latency_hiding_with_cursor[maximum_number_of_surfaces]; + struct bw_fixed maximum_latency_hiding_with_cursor[maximum_number_of_surfaces]; + struct bw_fixed src_pixels_for_first_output_pixel[maximum_number_of_surfaces]; + struct bw_fixed src_pixels_for_last_output_pixel[maximum_number_of_surfaces]; + struct bw_fixed src_data_for_first_output_pixel[maximum_number_of_surfaces]; + struct bw_fixed src_data_for_last_output_pixel[maximum_number_of_surfaces]; + struct bw_fixed active_time[maximum_number_of_surfaces]; + struct bw_fixed horizontal_blank_and_chunk_granularity_factor[maximum_number_of_surfaces]; + struct bw_fixed cursor_latency_hiding[maximum_number_of_surfaces]; + struct bw_fixed v_blank_dram_speed_change_margin[maximum_number_of_surfaces]; + uint32_t num_displays_with_margin[3][8]; + struct bw_fixed dmif_burst_time[3][8]; + struct bw_fixed mcifwr_burst_time[3][8]; + struct bw_fixed line_source_transfer_time[maximum_number_of_surfaces][3][8]; + struct bw_fixed dram_speed_change_line_source_transfer_time[maximum_number_of_surfaces][3][8]; + struct bw_fixed min_dram_speed_change_margin[3][8]; + struct bw_fixed dispclk_required_for_dram_speed_change[3][8]; + struct bw_fixed blackout_duration_margin[3][8]; + struct bw_fixed dispclk_required_for_blackout_duration[3][8]; + struct bw_fixed dispclk_required_for_blackout_recovery[3][8]; + struct bw_fixed dmif_required_sclk_for_urgent_latency[6]; +}; + +/******************************************************************************* + * Output data structures. + ******************************************************************************/ +struct bw_watermarks { + uint32_t a_mark; + uint32_t b_mark; + uint32_t c_mark; + uint32_t d_mark; +}; + +struct bw_calcs_output { + bool cpuc_state_change_enable; + bool cpup_state_change_enable; + bool stutter_mode_enable; + bool nbp_state_change_enable; + bool all_displays_in_sync; + struct bw_watermarks urgent_wm_ns[6]; + struct bw_watermarks stutter_exit_wm_ns[6]; + struct bw_watermarks nbp_state_change_wm_ns[6]; + uint32_t required_sclk; + uint32_t required_sclk_deep_sleep; + uint32_t required_yclk; + uint32_t dispclk_khz; + int blackout_recovery_time_us; +}; + +/** + * Initialize structures with data which will NOT change at runtime. + */ +void bw_calcs_init( + struct bw_calcs_dceip *bw_dceip, + struct bw_calcs_vbios *bw_vbios, + struct hw_asic_id asic_id); + +/** + * Return: + * true - Display(s) configuration supported. + * In this case 'calcs_output' contains data for HW programming + * false - Display(s) configuration not supported (not enough bandwidth). + */ +bool bw_calcs( + struct dc_context *ctx, + const struct bw_calcs_dceip *dceip, + const struct bw_calcs_vbios *vbios, + const struct pipe_ctx *pipe, + int pipe_count, + struct bw_calcs_output *calcs_output); + +#endif /* __BANDWIDTH_CALCS_H__ */ + diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h index 7ec4027700d8..179f5ad70f48 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h @@ -27,7 +27,7 @@ #include "dc.h" #include "include/grph_object_id.h" -#include "inc/bandwidth_calcs.h" +#include "inc/dce_calcs.h" #include "dce/dce_mem_input.h" /* temporary */ -- cgit From 667e1498a9d0e43849fa84c1c6874184b33aee5f Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Thu, 23 Mar 2017 15:27:15 -0400 Subject: drm/amd/display: use CRTC_VERTICAL_INTERRUPT0 as VBLANK trigger. VBLANK interrupt is driven bu line buffer vcounter which is ahead of CRTC vcounter. Use an interrupt that fires at the actual CRTC vblank start boundry. Signed-off-by: Andrey Grodzovsky Acked-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Signed-off-by: Alex Deucher --- .../display/dc/dce110/dce110_timing_generator.c | 46 ++++++++++++++- .../display/dc/dce110/dce110_timing_generator.h | 3 + .../display/dc/dce120/dce120_timing_generator.c | 32 +++++++++- .../amd/display/dc/dce80/dce80_timing_generator.c | 1 + .../drm/amd/display/dc/inc/hw/timing_generator.h | 2 + .../amd/display/dc/irq/dce110/irq_service_dce110.c | 68 +++++++++++++++------- .../amd/display/dc/irq/dce110/irq_service_dce110.h | 5 ++ .../amd/display/dc/irq/dce120/irq_service_dce120.c | 11 ++-- .../amd/display/dc/irq/dce80/irq_service_dce80.c | 22 ++++--- 9 files changed, 152 insertions(+), 38 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c index f4b8576a0546..006412be7a02 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c @@ -1869,6 +1869,48 @@ void dce110_tg_set_colors(struct timing_generator *tg, dce110_tg_set_overscan_color(tg, overscan_color); } +/* Gets first line of blank region of the display timing for CRTC + * and programms is as a trigger to fire vertical interrupt + */ +bool dce110_arm_vert_intr(struct timing_generator *tg, uint8_t width) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t vbl = 0; + uint32_t val = 0; + uint32_t position, vbl_start; + + tg->funcs->get_scanoutpos( + tg, + &vbl, + &position); + + if (vbl == 0) + return false; + + vbl_start = + get_reg_field_value( + vbl, + CRTC_V_BLANK_START_END, + CRTC_V_BLANK_START); + + set_reg_field_value( + val, + vbl_start, + CRTC_VERTICAL_INTERRUPT0_POSITION, + CRTC_VERTICAL_INTERRUPT0_LINE_START); + + /* Set interaval width for interrupt to fire to 1 scanline */ + set_reg_field_value( + val, + vbl_start + width, + CRTC_VERTICAL_INTERRUPT0_POSITION, + CRTC_VERTICAL_INTERRUPT0_LINE_END); + + dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_VERTICAL_INTERRUPT0_POSITION), val); + + return true; +} + static const struct timing_generator_funcs dce110_tg_funcs = { .validate_timing = dce110_tg_validate_timing, .program_timing = dce110_tg_program_timing, @@ -1901,8 +1943,8 @@ static const struct timing_generator_funcs dce110_tg_funcs = { dce110_timing_generator_set_drr, .set_static_screen_control = dce110_timing_generator_set_static_screen_control, - .set_test_pattern = dce110_timing_generator_set_test_pattern - + .set_test_pattern = dce110_timing_generator_set_test_pattern, + .arm_vert_intr = dce110_arm_vert_intr, }; bool dce110_timing_generator_construct( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h index 378509b8e56c..ca387b40fc67 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h @@ -271,4 +271,7 @@ void dce110_tg_set_colors(struct timing_generator *tg, const struct tg_color *blank_color, const struct tg_color *overscan_color); +bool dce110_arm_vert_intr( + struct timing_generator *tg, uint8_t width); + #endif /* __DC_TIMING_GENERATOR_DCE110_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c index d7e787b591a0..95cb1768aeb5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c @@ -1039,6 +1039,35 @@ void dce120_timing_generator_set_test_pattern( } } +static bool dce120_arm_vert_intr( + struct timing_generator *tg, + uint8_t width) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t vbl, position, vbl_start; + + tg->funcs->get_scanoutpos( + tg, + &vbl, + &position); + + if (vbl == 0) + return false; + + vbl_start = + get_reg_field_value( + vbl, + CRTC0_CRTC_V_BLANK_START_END, + CRTC_V_BLANK_START); + + CRTC_REG_SET_2( + CRTC0_CRTC_VERTICAL_INTERRUPT0_POSITION, + CRTC_VERTICAL_INTERRUPT0_LINE_START, vbl_start, + CRTC_VERTICAL_INTERRUPT0_LINE_END, vbl_start + width); + + return true; +} + static struct timing_generator_funcs dce120_tg_funcs = { .validate_timing = dce120_tg_validate_timing, .program_timing = dce120_tg_program_timing, @@ -1068,7 +1097,8 @@ static struct timing_generator_funcs dce120_tg_funcs = { .enable_advanced_request = dce120_timing_generator_enable_advanced_request, .set_drr = dce120_timing_generator_set_drr, .set_static_screen_control = dce120_timing_generator_set_static_screen_control, - .set_test_pattern = dce120_timing_generator_set_test_pattern + .set_test_pattern = dce120_timing_generator_set_test_pattern, + .arm_vert_intr = dce120_arm_vert_intr, }; diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c index eeccabd65a7a..1198f2fbf9c7 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c @@ -145,6 +145,7 @@ static const struct timing_generator_funcs dce80_tg_funcs = { .set_static_screen_control = dce110_timing_generator_set_static_screen_control, .set_test_pattern = dce110_timing_generator_set_test_pattern, + .arm_vert_intr = dce110_arm_vert_intr, /* DCE8.0 overrides */ .enable_advanced_request = diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h index 62c19358254b..51902a4f8798 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h @@ -156,6 +156,8 @@ struct timing_generator_funcs { enum controller_dp_test_pattern test_pattern, enum dc_color_depth color_depth); + bool (*arm_vert_intr)(struct timing_generator *tg, uint8_t width); + }; #endif diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c index 4c7c85d45518..52361d1472fa 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c @@ -31,14 +31,10 @@ #include "dce/dce_11_0_d.h" #include "dce/dce_11_0_sh_mask.h" + #include "ivsrcid/ivsrcid_vislands30.h" -#define VISLANDS30_IV_SRCID_D1_VBLANK 1 -#define VISLANDS30_IV_SRCID_D2_VBLANK 2 -#define VISLANDS30_IV_SRCID_D3_VBLANK 3 -#define VISLANDS30_IV_SRCID_D4_VBLANK 4 -#define VISLANDS30_IV_SRCID_D5_VBLANK 5 -#define VISLANDS30_IV_SRCID_D6_VBLANK 6 +#include "core_dc.h" static bool hpd_ack( struct irq_service *irq_service, @@ -83,7 +79,7 @@ static const struct irq_source_info_funcs pflip_irq_info_funcs = { }; static const struct irq_source_info_funcs vblank_irq_info_funcs = { - .set = NULL, + .set = dce110_vblank_set, .ack = NULL }; @@ -148,18 +144,19 @@ static const struct irq_source_info_funcs vblank_irq_info_funcs = { #define vblank_int_entry(reg_num)\ [DC_IRQ_SOURCE_VBLANK1 + reg_num] = {\ - .enable_reg = mmLB ## reg_num ## _LB_INTERRUPT_MASK,\ + .enable_reg = mmCRTC ## reg_num ## _CRTC_VERTICAL_INTERRUPT0_CONTROL,\ .enable_mask =\ - LB_INTERRUPT_MASK__VBLANK_INTERRUPT_MASK_MASK,\ + CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_ENABLE_MASK,\ .enable_value = {\ - LB_INTERRUPT_MASK__VBLANK_INTERRUPT_MASK_MASK,\ - ~LB_INTERRUPT_MASK__VBLANK_INTERRUPT_MASK_MASK},\ - .ack_reg = mmLB ## reg_num ## _LB_VBLANK_STATUS,\ + CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_ENABLE_MASK,\ + ~CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_ENABLE_MASK},\ + .ack_reg = mmCRTC ## reg_num ## _CRTC_VERTICAL_INTERRUPT0_CONTROL,\ .ack_mask =\ - LB_VBLANK_STATUS__VBLANK_ACK_MASK,\ + CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_CLEAR_MASK,\ .ack_value =\ - LB_VBLANK_STATUS__VBLANK_ACK_MASK,\ - .funcs = &vblank_irq_info_funcs\ + CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_CLEAR_MASK,\ + .funcs = &vblank_irq_info_funcs,\ + .src_id = VISLANDS30_IV_SRCID_D1_VERTICAL_INTERRUPT0 + reg_num\ } #define dummy_irq_entry() \ @@ -202,6 +199,35 @@ bool dal_irq_service_dummy_ack( return false; } + +bool dce110_vblank_set( + struct irq_service *irq_service, + const struct irq_source_info *info, + bool enable) +{ + struct dc_context *dc_ctx = irq_service->ctx; + struct core_dc *core_dc = DC_TO_CORE(irq_service->ctx->dc); + enum dc_irq_source dal_irq_src = dc_interrupt_to_irq_source( + irq_service->ctx->dc, + info->src_id, + info->ext_id); + uint8_t pipe_offset = dal_irq_src - IRQ_TYPE_VBLANK; + + struct timing_generator *tg = + core_dc->current_context->res_ctx.pipe_ctx[pipe_offset].tg; + + if (enable) { + if (!tg->funcs->arm_vert_intr(tg, 2)) { + DC_ERROR("Failed to get VBLANK!\n"); + return false; + } + } + + dal_irq_service_set_generic(irq_service, info, enable); + return true; + +} + static const struct irq_source_info_funcs dummy_irq_info_funcs = { .set = dal_irq_service_dummy_set, .ack = dal_irq_service_dummy_ack @@ -302,17 +328,17 @@ enum dc_irq_source to_dal_irq_source_dce110( uint32_t ext_id) { switch (src_id) { - case VISLANDS30_IV_SRCID_D1_VBLANK: + case VISLANDS30_IV_SRCID_D1_VERTICAL_INTERRUPT0: return DC_IRQ_SOURCE_VBLANK1; - case VISLANDS30_IV_SRCID_D2_VBLANK: + case VISLANDS30_IV_SRCID_D2_VERTICAL_INTERRUPT0: return DC_IRQ_SOURCE_VBLANK2; - case VISLANDS30_IV_SRCID_D3_VBLANK: + case VISLANDS30_IV_SRCID_D3_VERTICAL_INTERRUPT0: return DC_IRQ_SOURCE_VBLANK3; - case VISLANDS30_IV_SRCID_D4_VBLANK: + case VISLANDS30_IV_SRCID_D4_VERTICAL_INTERRUPT0: return DC_IRQ_SOURCE_VBLANK4; - case VISLANDS30_IV_SRCID_D5_VBLANK: + case VISLANDS30_IV_SRCID_D5_VERTICAL_INTERRUPT0: return DC_IRQ_SOURCE_VBLANK5; - case VISLANDS30_IV_SRCID_D6_VBLANK: + case VISLANDS30_IV_SRCID_D6_VERTICAL_INTERRUPT0: return DC_IRQ_SOURCE_VBLANK6; case VISLANDS30_IV_SRCID_D1_V_UPDATE_INT: return DC_IRQ_SOURCE_VUPDATE1; diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.h b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.h index a84f360c6515..9237646c0959 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.h +++ b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.h @@ -45,4 +45,9 @@ bool dal_irq_service_dummy_ack( struct irq_service *irq_service, const struct irq_source_info *info); +bool dce110_vblank_set( + struct irq_service *irq_service, + const struct irq_source_info *info, + bool enable); + #endif diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c b/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c index 5a263b2efa51..3871633ac635 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c @@ -79,7 +79,7 @@ static const struct irq_source_info_funcs pflip_irq_info_funcs = { }; static const struct irq_source_info_funcs vblank_irq_info_funcs = { - .set = NULL, + .set = dce110_vblank_set, .ack = NULL }; @@ -144,10 +144,11 @@ static const struct irq_source_info_funcs vblank_irq_info_funcs = { #define vblank_int_entry(reg_num)\ [DC_IRQ_SOURCE_VBLANK1 + reg_num] = {\ - IRQ_REG_ENTRY(LB, reg_num,\ - LB_INTERRUPT_MASK, VBLANK_INTERRUPT_MASK,\ - LB_VBLANK_STATUS, VBLANK_ACK),\ - .funcs = &vblank_irq_info_funcs\ + IRQ_REG_ENTRY(CRTC, reg_num,\ + CRTC_VERTICAL_INTERRUPT0_CONTROL, CRTC_VERTICAL_INTERRUPT0_INT_ENABLE,\ + CRTC_VERTICAL_INTERRUPT0_CONTROL, CRTC_VERTICAL_INTERRUPT0_CLEAR),\ + .funcs = &vblank_irq_info_funcs,\ + .src_id = VISLANDS30_IV_SRCID_D1_VERTICAL_INTERRUPT0 + reg_num\ } #define dummy_irq_entry() \ diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c b/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c index dd09d2b6d4a7..7e8cb22f280f 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c @@ -35,6 +35,9 @@ #include "ivsrcid/ivsrcid_vislands30.h" +#include "dc_types.h" +#include "inc/core_dc.h" + static bool hpd_ack( struct irq_service *irq_service, const struct irq_source_info *info) @@ -78,7 +81,7 @@ static const struct irq_source_info_funcs pflip_irq_info_funcs = { }; static const struct irq_source_info_funcs vblank_irq_info_funcs = { - .set = NULL, + .set = dce110_vblank_set, .ack = NULL }; @@ -145,18 +148,19 @@ static const struct irq_source_info_funcs vblank_irq_info_funcs = { #define vblank_int_entry(reg_num)\ [DC_IRQ_SOURCE_VBLANK1 + reg_num] = {\ - .enable_reg = mmLB ## reg_num ## _LB_INTERRUPT_MASK,\ + .enable_reg = mmCRTC ## reg_num ## _CRTC_VERTICAL_INTERRUPT0_CONTROL,\ .enable_mask =\ - LB_INTERRUPT_MASK__VBLANK_INTERRUPT_MASK_MASK,\ + CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_ENABLE_MASK,\ .enable_value = {\ - LB_INTERRUPT_MASK__VBLANK_INTERRUPT_MASK_MASK,\ - ~LB_INTERRUPT_MASK__VBLANK_INTERRUPT_MASK_MASK},\ - .ack_reg = mmLB ## reg_num ## _LB_VBLANK_STATUS,\ + CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_ENABLE_MASK,\ + ~CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_ENABLE_MASK},\ + .ack_reg = mmCRTC ## reg_num ## _CRTC_VERTICAL_INTERRUPT0_CONTROL,\ .ack_mask =\ - LB_VBLANK_STATUS__VBLANK_ACK_MASK,\ + CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_CLEAR_MASK,\ .ack_value =\ - LB_VBLANK_STATUS__VBLANK_ACK_MASK,\ - .funcs = &vblank_irq_info_funcs\ + CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_CLEAR_MASK,\ + .funcs = &vblank_irq_info_funcs,\ + .src_id = VISLANDS30_IV_SRCID_D1_VERTICAL_INTERRUPT0 + reg_num\ } #define dummy_irq_entry() \ -- cgit From e902915507bd20115e1e21bc99ea36ea7986cebc Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Thu, 23 Mar 2017 15:30:35 -0400 Subject: drm/amd/display: use CRTC_VERTICAL_INTERRUPT0 as a trigger for VBLANK. Register ISR hnadler on the new interrupt. Signed-off-by: Andrey Grodzovsky Acked-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/gpu') 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 c559c71d558e..b08ec453b773 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -907,9 +907,8 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev) * for acknowledging and handling. */ /* Use VBLANK interrupt */ - for (i = 1; i <= adev->mode_info.num_crtc; i++) { + for (i = VISLANDS30_IV_SRCID_D1_VERTICAL_INTERRUPT0; i <= VISLANDS30_IV_SRCID_D6_VERTICAL_INTERRUPT0; i++) { r = amdgpu_irq_add_id(adev, client_id, i, &adev->crtc_irq); - if (r) { DRM_ERROR("Failed to add crtc irq id!\n"); return r; -- cgit From fd8cc371ede63d69cf69bb3a8a9a005d91ae023f Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Fri, 24 Mar 2017 16:54:02 -0400 Subject: drm/amd/display: voltage request related change Signed-off-by: Charlene Liu Acked-by: Harry Wentland Reviewed-by: Krunoslav Kovac Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dce/dce_clock_source.c | 1 + drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c | 27 +++++++++++----------- .../gpu/drm/amd/display/dc/inc/hw/display_clock.h | 2 ++ drivers/gpu/drm/amd/display/include/logger_types.h | 1 + 4 files changed, 18 insertions(+), 13 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index bd4524ef3a37..8ddad3a877d6 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -1035,6 +1035,7 @@ static void get_ss_info_from_atombios( } *spread_spectrum_data = ss_data; + dm_free(ss_data); dm_free(ss_info); return; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c index 263f8900e39c..b4fd02219c2c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c @@ -495,6 +495,7 @@ static void dce_clock_read_ss_info(struct dce_disp_clk *clk_dce) } } + static bool dce_apply_clock_voltage_request( struct display_clock *clk, enum dm_pp_clock_type clocks_type, @@ -502,6 +503,7 @@ static bool dce_apply_clock_voltage_request( bool pre_mode_set, bool update_dp_phyclk) { + bool send_request = false; struct dm_pp_clock_for_voltage_req clock_voltage_req = {0}; switch (clocks_type) { @@ -522,9 +524,8 @@ static bool dce_apply_clock_voltage_request( switch (clocks_type) { case DM_PP_CLOCK_TYPE_DISPLAY_CLK: if (clocks_in_khz > clk->cur_clocks_value.dispclk_in_khz) { - dm_pp_apply_clock_for_voltage_request( - clk->ctx, &clock_voltage_req); clk->cur_clocks_value.dispclk_notify_pplib_done = true; + send_request = true; } else clk->cur_clocks_value.dispclk_notify_pplib_done = false; /* no matter incrase or decrase clock, update current clock value */ @@ -532,9 +533,8 @@ static bool dce_apply_clock_voltage_request( break; case DM_PP_CLOCK_TYPE_PIXELCLK: if (clocks_in_khz > clk->cur_clocks_value.max_pixelclk_in_khz) { - dm_pp_apply_clock_for_voltage_request( - clk->ctx, &clock_voltage_req); clk->cur_clocks_value.pixelclk_notify_pplib_done = true; + send_request = true; } else clk->cur_clocks_value.pixelclk_notify_pplib_done = false; /* no matter incrase or decrase clock, update current clock value */ @@ -542,9 +542,8 @@ static bool dce_apply_clock_voltage_request( break; case DM_PP_CLOCK_TYPE_DISPLAYPHYCLK: if (clocks_in_khz > clk->cur_clocks_value.max_non_dp_phyclk_in_khz) { - dm_pp_apply_clock_for_voltage_request( - clk->ctx, &clock_voltage_req); clk->cur_clocks_value.phyclk_notigy_pplib_done = true; + send_request = true; } else clk->cur_clocks_value.phyclk_notigy_pplib_done = false; /* no matter incrase or decrase clock, update current clock value */ @@ -554,29 +553,30 @@ static bool dce_apply_clock_voltage_request( ASSERT(0); break; } + } else { switch (clocks_type) { case DM_PP_CLOCK_TYPE_DISPLAY_CLK: if (!clk->cur_clocks_value.dispclk_notify_pplib_done) - dm_pp_apply_clock_for_voltage_request( - clk->ctx, &clock_voltage_req); + send_request = true; break; case DM_PP_CLOCK_TYPE_PIXELCLK: if (!clk->cur_clocks_value.pixelclk_notify_pplib_done) - dm_pp_apply_clock_for_voltage_request( - clk->ctx, &clock_voltage_req); + send_request = true; break; case DM_PP_CLOCK_TYPE_DISPLAYPHYCLK: if (!clk->cur_clocks_value.phyclk_notigy_pplib_done) - dm_pp_apply_clock_for_voltage_request( - clk->ctx, &clock_voltage_req); + send_request = true; break; default: ASSERT(0); break; } } - + if (send_request) { + dm_pp_apply_clock_for_voltage_request( + clk->ctx, &clock_voltage_req); + } if (update_dp_phyclk && (clocks_in_khz > clk->cur_clocks_value.max_dp_phyclk_in_khz)) clk->cur_clocks_value.max_dp_phyclk_in_khz = clocks_in_khz; @@ -584,6 +584,7 @@ static bool dce_apply_clock_voltage_request( return true; } + static const struct display_clock_funcs dce120_funcs = { .get_dp_ref_clk_frequency = dce_clocks_get_dp_ref_freq, .apply_clock_voltage_request = dce_apply_clock_voltage_request, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h b/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h index 79aa75c150ec..97f26b55535f 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h @@ -28,6 +28,7 @@ #include "dm_services_types.h" + struct clocks_value { int dispclk_in_khz; int max_pixelclk_in_khz; @@ -38,6 +39,7 @@ struct clocks_value { bool phyclk_notigy_pplib_done; }; + /* Structure containing all state-dependent clocks * (dependent on "enum clocks_state") */ struct state_dependent_clocks { diff --git a/drivers/gpu/drm/amd/display/include/logger_types.h b/drivers/gpu/drm/amd/display/include/logger_types.h index 982c67f7de43..dfc0f102b33d 100644 --- a/drivers/gpu/drm/amd/display/include/logger_types.h +++ b/drivers/gpu/drm/amd/display/include/logger_types.h @@ -64,6 +64,7 @@ enum dc_log_type { LOG_EVENT_UNDERFLOW, LOG_IF_TRACE, LOG_HW_MARKS, + LOG_PPLIB, LOG_SECTION_TOTAL_COUNT }; -- cgit From 940c654e64e1ed70b49ec663f2370a8b4de6d2ac Mon Sep 17 00:00:00 2001 From: Roman Li Date: Fri, 24 Mar 2017 16:26:09 -0400 Subject: drm/amd/display: increase timeout for dmif dealloc In some use-cases, e.g. multiple 4K displays, exisitng wait time for reg update of 30msec timed out during mode setiing that sometimes resulted in system bad state as we continue without waiting for registry update complete. Increasing timeout to 35msec fixes that problem. Signed-off-by: Roman Li Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c index 7acd87152811..884f453d91b0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c @@ -524,7 +524,7 @@ void dce_mem_input_free_dmif(struct mem_input *mi, REG_WAIT(DMIF_BUFFER_CONTROL, DMIF_BUFFERS_ALLOCATION_COMPLETED, 1, - 10, 0xBB8); + 10, 3500); if (mi->wa.single_head_rdreq_dmif_limit) { uint32_t eanble = (total_stream_num > 1) ? 0 : -- cgit From dabb3979e1cdfddbc9121116cfcf69f01991e51d Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Mon, 27 Mar 2017 09:59:38 -0400 Subject: drm/amd/display: Fix MPO exit and cursor issue. Signed-off-by: Yongqiang Sun Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 5 ++++- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 512a53bdc32f..bf209f7bbf98 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -215,7 +215,7 @@ bool dc_stream_set_cursor_attributes( bool dc_stream_set_cursor_position( const struct dc_stream *dc_stream, - const struct dc_cursor_position *position) + struct dc_cursor_position *position) { int i; struct core_stream *stream; @@ -251,6 +251,9 @@ bool dc_stream_set_cursor_position( .h_scale_ratio = pipe_ctx->scl_data.ratios.horz, }; + if (pipe_ctx->top_pipe && pipe_ctx->surface != pipe_ctx->top_pipe->surface) + position->enable = false; + ipp->funcs->ipp_cursor_set_position(ipp, position, ¶m); ret = true; } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index b3d5b922aae4..0731045f6084 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -744,7 +744,7 @@ bool dc_stream_set_cursor_attributes( bool dc_stream_set_cursor_position( const struct dc_stream *stream, - const struct dc_cursor_position *position); + struct dc_cursor_position *position); /* Newer interfaces */ struct dc_cursor { -- cgit From fcbb5ad3fef1ee8461150e7213806cbb46b6f076 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Mon, 27 Mar 2017 12:39:22 -0400 Subject: drm/amd/display: use CP2520-3 for PHY compliance automation Signed-off-by: Tony Cheng Acked-by: Harry Wentland Reviewed-by: Hersen Wu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 3 +++ drivers/gpu/drm/amd/display/include/link_service_types.h | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index ed46e9aaf357..df116f86ab45 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -1405,6 +1405,9 @@ void dce110_link_encoder_dp_set_phy_pattern( case DP_TEST_PATTERN_CP2520_2: set_dp_phy_pattern_hbr2_compliance_cp2520_2(enc110, 2); break; + case DP_TEST_PATTERN_CP2520_3: + set_dp_phy_pattern_hbr2_compliance_cp2520_2(enc110, 3); + break; case DP_TEST_PATTERN_VIDEO_MODE: { set_dp_phy_pattern_passthrough_mode( enc110, param->dp_panel_mode); diff --git a/drivers/gpu/drm/amd/display/include/link_service_types.h b/drivers/gpu/drm/amd/display/include/link_service_types.h index b2326017e4c7..fe8b5144e03f 100644 --- a/drivers/gpu/drm/amd/display/include/link_service_types.h +++ b/drivers/gpu/drm/amd/display/include/link_service_types.h @@ -85,13 +85,13 @@ enum dp_test_pattern { DP_TEST_PATTERN_CP2520_1, DP_TEST_PATTERN_CP2520_2, DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE = DP_TEST_PATTERN_CP2520_2, + DP_TEST_PATTERN_CP2520_3, /* Link Training Patterns */ DP_TEST_PATTERN_TRAINING_PATTERN1, DP_TEST_PATTERN_TRAINING_PATTERN2, DP_TEST_PATTERN_TRAINING_PATTERN3, DP_TEST_PATTERN_TRAINING_PATTERN4, - DP_TEST_PATTERN_CP2520_3 = DP_TEST_PATTERN_TRAINING_PATTERN4, DP_TEST_PATTERN_PHY_PATTERN_END = DP_TEST_PATTERN_TRAINING_PATTERN4, /* link test patterns*/ -- cgit From 7b779c991d9422f677dff70d701eae448c7c696a Mon Sep 17 00:00:00 2001 From: Vitaly Prosyak Date: Mon, 27 Mar 2017 12:48:46 -0500 Subject: drm/amd/display: stereo support Frame sequential, top-bottom and side-by-side support. Signed-off-by: Vitaly Prosyak Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 34 +++++++++++++++++------ 1 file changed, 26 insertions(+), 8 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 61ca1e21ae66..8f53d7a9f4dd 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -422,6 +422,11 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) bool sec_split = pipe_ctx->top_pipe && pipe_ctx->top_pipe->surface == pipe_ctx->surface; + if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_SIDE_BY_SIDE || + stream->timing.timing_3d_format == TIMING_3D_FORMAT_TOP_AND_BOTTOM) { + pri_split = false; + sec_split = false; + } /* The actual clip is an intersection between stream * source and surface clip */ @@ -532,14 +537,27 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip stream->public.dst.y + stream->public.dst.height - pipe_ctx->scl_data.recout.y; - /* Handle hsplit */ - if (pipe_ctx->top_pipe && pipe_ctx->top_pipe->surface == pipe_ctx->surface) { - pipe_ctx->scl_data.recout.width /= 2; - pipe_ctx->scl_data.recout.x += pipe_ctx->scl_data.recout.width; - /* Floor primary pipe, ceil 2ndary pipe */ - pipe_ctx->scl_data.recout.width += pipe_ctx->scl_data.recout.width % 2; - } else if (pipe_ctx->bottom_pipe && pipe_ctx->bottom_pipe->surface == pipe_ctx->surface) { - pipe_ctx->scl_data.recout.width /= 2; + /* Handle h & vsplit */ + if (pipe_ctx->top_pipe && pipe_ctx->top_pipe->surface == + pipe_ctx->surface) { + if (stream->public.timing.timing_3d_format == + TIMING_3D_FORMAT_TOP_AND_BOTTOM) { + pipe_ctx->scl_data.recout.height /= 2; + pipe_ctx->scl_data.recout.y += pipe_ctx->scl_data.recout.height; + /* Floor primary pipe, ceil 2ndary pipe */ + pipe_ctx->scl_data.recout.height += pipe_ctx->scl_data.recout.height % 2; + } else { + pipe_ctx->scl_data.recout.width /= 2; + pipe_ctx->scl_data.recout.x += pipe_ctx->scl_data.recout.width; + pipe_ctx->scl_data.recout.width += pipe_ctx->scl_data.recout.width % 2; + } + } else if (pipe_ctx->bottom_pipe && + pipe_ctx->bottom_pipe->surface == pipe_ctx->surface) { + if (stream->public.timing.timing_3d_format == + TIMING_3D_FORMAT_TOP_AND_BOTTOM) + pipe_ctx->scl_data.recout.height /= 2; + else + pipe_ctx->scl_data.recout.width /= 2; } /* Unclipped recout offset = stream dst offset + ((surf dst offset - stream src offset) -- cgit From 4e3133c79dc4b7dc0ff81eb884d6cfe736fc49b1 Mon Sep 17 00:00:00 2001 From: Ding Wang Date: Mon, 27 Mar 2017 14:50:27 -0400 Subject: drm/amd/display: obtain usHBR3En bit from BP 1 ASICs using bios parser 1 don't check HBR3 capability as there is no such a bit usHBR3En in ATOM_ENCODER_CAP_RECORDER. Therefore, will use ATOM_ENCODER_CAP_RECORDER_V2 and thus obtain the usHBR3En bit. Signed-off-by: Ding Wang Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/bios/bios_parser.c | 14 +++++++------- drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c index 50163a06a653..47a467688073 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c @@ -88,7 +88,7 @@ static ATOM_HPD_INT_RECORD *get_hpd_record(struct bios_parser *bp, static struct device_id device_type_from_device_id(uint16_t device_id); static uint32_t signal_to_ss_id(enum as_signal_type signal); static uint32_t get_support_mask_for_device_id(struct device_id device_id); -static ATOM_ENCODER_CAP_RECORD *get_encoder_cap_record( +static ATOM_ENCODER_CAP_RECORD_V2 *get_encoder_cap_record( struct bios_parser *bp, ATOM_OBJECT *object); @@ -1837,7 +1837,7 @@ static enum bp_result bios_parser_get_encoder_cap_info( { struct bios_parser *bp = BP_FROM_DCB(dcb); ATOM_OBJECT *object; - ATOM_ENCODER_CAP_RECORD *record = NULL; + ATOM_ENCODER_CAP_RECORD_V2 *record = NULL; if (!info) return BP_RESULT_BADINPUT; @@ -1851,8 +1851,8 @@ static enum bp_result bios_parser_get_encoder_cap_info( if (!record) return BP_RESULT_NORECORD; - info->DP_HBR2_CAP = record->usHBR2Cap; info->DP_HBR2_EN = record->usHBR2En; + info->DP_HBR3_EN = record->usHBR3En; return BP_RESULT_OK; } @@ -1867,9 +1867,9 @@ static enum bp_result bios_parser_get_encoder_cap_info( * @return atom encoder cap record * * @note - * search all records to find the ATOM_ENCODER_CAP_RECORD record + * search all records to find the ATOM_ENCODER_CAP_RECORD_V2 record */ -static ATOM_ENCODER_CAP_RECORD *get_encoder_cap_record( +static ATOM_ENCODER_CAP_RECORD_V2 *get_encoder_cap_record( struct bios_parser *bp, ATOM_OBJECT *object) { @@ -1899,8 +1899,8 @@ static ATOM_ENCODER_CAP_RECORD *get_encoder_cap_record( if (ATOM_ENCODER_CAP_RECORD_TYPE != header->ucRecordType) continue; - if (sizeof(ATOM_ENCODER_CAP_RECORD) <= header->ucRecordSize) - return (ATOM_ENCODER_CAP_RECORD *)header; + if (sizeof(ATOM_ENCODER_CAP_RECORD_V2) <= header->ucRecordSize) + return (ATOM_ENCODER_CAP_RECORD_V2 *)header; } return NULL; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index df116f86ab45..1a84ee0105da 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -993,7 +993,7 @@ bool dce110_link_encoder_construct( enc110->base.ctx->dc_bios, enc110->base.id, &bp_cap_info)) { enc110->base.features.flags.bits.IS_HBR2_CAPABLE = - bp_cap_info.DP_HBR2_CAP; + bp_cap_info.DP_HBR2_EN; enc110->base.features.flags.bits.IS_HBR3_CAPABLE = bp_cap_info.DP_HBR3_EN; } -- cgit From d4e13b0db124345be93bc2ff39ecb48409da2c9b Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 15 Jun 2017 16:24:01 -0400 Subject: drm/amd/display: decouple per-crtc-plane model Current design has per-crtc-plane model. As a result, for asic's that support underlay, are unable to expose it to user space for modesetting. To enable this, the drm driver intialisation now runs for number of surfaces instead of stream/crtc. This patch plumbs surface capabilities to drm framework so that it can be effectively used by user space. Tests: (On Chromium OS for Stoney Only) * 'modetest -p' now shows additional plane with YUV capabilities in case of CZ and ST. * 'plane_test' fails with below error: [drm:amdgpu_dm_connector_atomic_set_property [amdgpu]] *ERROR* Unsupported screen depth 0 as ther is no support for YUYV * Checked multimonitor display works fine Signed-off-by: Shirish S Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 8 +++ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 67 ++++++++++++++----- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 76 +++++++++++++++------- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.h | 5 +- drivers/gpu/drm/amd/display/dc/dc.h | 1 + .../drm/amd/display/dc/dce100/dce100_resource.c | 2 + .../drm/amd/display/dc/dce110/dce110_resource.c | 2 + .../drm/amd/display/dc/dce112/dce112_resource.c | 2 + .../drm/amd/display/dc/dce120/dce120_resource.c | 2 + .../gpu/drm/amd/display/dc/dce80/dce80_resource.c | 2 + 10 files changed, 127 insertions(+), 40 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index e5d2ce48cb1e..362d9559f065 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -60,6 +60,7 @@ struct amdgpu_hpd; #define AMDGPU_MAX_HPD_PINS 6 #define AMDGPU_MAX_CRTCS 6 +#define AMDGPU_MAX_PLANES 6 #define AMDGPU_MAX_AFMT_BLOCKS 9 enum amdgpu_rmx_type { @@ -327,6 +328,7 @@ struct amdgpu_mode_info { struct card_info *atom_card_info; bool mode_config_initialized; struct amdgpu_crtc *crtcs[AMDGPU_MAX_CRTCS]; + struct amdgpu_plane *planes[AMDGPU_MAX_PLANES]; struct amdgpu_afmt *afmt[AMDGPU_MAX_AFMT_BLOCKS]; /* DVI-I properties */ struct drm_property *coherent_mode_property; @@ -356,6 +358,7 @@ struct amdgpu_mode_info { int num_dig; /* number of dig blocks */ int disp_priority; const struct amdgpu_display_funcs *funcs; + enum drm_plane_type *plane_type; }; #define AMDGPU_MAX_BL_LEVEL 0xFF @@ -436,6 +439,11 @@ struct amdgpu_crtc { struct drm_pending_vblank_event *event; }; +struct amdgpu_plane { + struct drm_plane base; + enum drm_plane_type plane_type; +}; + struct amdgpu_encoder_atom_dig { bool linkb; /* atom dig */ 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 b08ec453b773..d76448d04423 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -49,6 +49,28 @@ #include "modules/inc/mod_freesync.h" +static enum drm_plane_type dm_surfaces_type_default[AMDGPU_MAX_PLANES] = { + DRM_PLANE_TYPE_PRIMARY, + DRM_PLANE_TYPE_PRIMARY, + DRM_PLANE_TYPE_PRIMARY, + DRM_PLANE_TYPE_PRIMARY, + DRM_PLANE_TYPE_PRIMARY, + DRM_PLANE_TYPE_PRIMARY, +}; + +static enum drm_plane_type dm_surfaces_type_carizzo[AMDGPU_MAX_PLANES] = { + DRM_PLANE_TYPE_PRIMARY, + DRM_PLANE_TYPE_PRIMARY, + DRM_PLANE_TYPE_PRIMARY, + DRM_PLANE_TYPE_OVERLAY,/* YUV Capable Underlay */ +}; + +static enum drm_plane_type dm_surfaces_type_stoney[AMDGPU_MAX_PLANES] = { + DRM_PLANE_TYPE_PRIMARY, + DRM_PLANE_TYPE_PRIMARY, + DRM_PLANE_TYPE_OVERLAY, /* YUV Capable Underlay */ +}; + /* * dm_vblank_get_counter * @@ -1051,30 +1073,34 @@ int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) uint32_t i; struct amdgpu_connector *aconnector; struct amdgpu_encoder *aencoder; - struct amdgpu_crtc *acrtc; + struct amdgpu_mode_info *mode_info = &adev->mode_info; uint32_t link_cnt; link_cnt = dm->dc->caps.max_links; - if (amdgpu_dm_mode_config_init(dm->adev)) { DRM_ERROR("DM: Failed to initialize mode config\n"); - return -1; + goto fail; } - for (i = 0; i < dm->dc->caps.max_streams; i++) { - acrtc = kzalloc(sizeof(struct amdgpu_crtc), GFP_KERNEL); - if (!acrtc) - goto fail; + for (i = 0; i < dm->dc->caps.max_surfaces; i++) { + mode_info->planes[i] = kzalloc(sizeof(struct amdgpu_plane), + GFP_KERNEL); + if (!mode_info->planes[i]) { + DRM_ERROR("KMS: Failed to allocate surface\n"); + goto fail_free_planes; + } + mode_info->planes[i]->plane_type = mode_info->plane_type[i]; + if (amdgpu_dm_plane_init(dm, mode_info->planes[i], 1)) { + DRM_ERROR("KMS: Failed to initialize plane\n"); + goto fail_free_planes; + } + } - if (amdgpu_dm_crtc_init( - dm, - acrtc, - i)) { + for (i = 0; i < dm->dc->caps.max_streams; i++) + if (amdgpu_dm_crtc_init(dm, &mode_info->planes[i]->base, i)) { DRM_ERROR("KMS: Failed to initialize crtc\n"); - kfree(acrtc); - goto fail; + goto fail_free_planes; } - } dm->display_indexes_num = dm->dc->caps.max_streams; @@ -1125,12 +1151,12 @@ int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) case CHIP_VEGA10: if (dce110_register_irq_handlers(dm->adev)) { DRM_ERROR("DM: Failed to initialize IRQ\n"); - return -1; + goto fail_free_encoder; } break; default: DRM_ERROR("Usupported ASIC type: 0x%X\n", adev->asic_type); - return -1; + goto fail_free_encoder; } drm_mode_config_reset(dm->ddev); @@ -1140,6 +1166,9 @@ fail_free_encoder: kfree(aencoder); fail_free_connector: kfree(aconnector); +fail_free_planes: + for (i = 0; i < dm->dc->caps.max_surfaces; i++) + kfree(mode_info->planes[i]); fail: return -1; } @@ -1361,33 +1390,39 @@ static int dm_early_init(void *handle) adev->mode_info.num_crtc = 6; adev->mode_info.num_hpd = 6; adev->mode_info.num_dig = 6; + adev->mode_info.plane_type = dm_surfaces_type_default; break; case CHIP_FIJI: case CHIP_TONGA: adev->mode_info.num_crtc = 6; adev->mode_info.num_hpd = 6; adev->mode_info.num_dig = 7; + adev->mode_info.plane_type = dm_surfaces_type_default; break; case CHIP_CARRIZO: adev->mode_info.num_crtc = 3; adev->mode_info.num_hpd = 6; adev->mode_info.num_dig = 9; + adev->mode_info.plane_type = dm_surfaces_type_carizzo; break; case CHIP_STONEY: adev->mode_info.num_crtc = 2; adev->mode_info.num_hpd = 6; adev->mode_info.num_dig = 9; + adev->mode_info.plane_type = dm_surfaces_type_stoney; break; case CHIP_POLARIS11: case CHIP_POLARIS12: adev->mode_info.num_crtc = 5; adev->mode_info.num_hpd = 5; adev->mode_info.num_dig = 5; + adev->mode_info.plane_type = dm_surfaces_type_default; break; case CHIP_POLARIS10: adev->mode_info.num_crtc = 6; adev->mode_info.num_hpd = 6; adev->mode_info.num_dig = 6; + adev->mode_info.plane_type = dm_surfaces_type_default; break; case CHIP_VEGA10: adev->mode_info.num_crtc = 6; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index ee9239ab734c..1751f138c36a 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -1446,6 +1446,8 @@ const struct drm_encoder_helper_funcs amdgpu_dm_encoder_helper_funcs = { }; static const struct drm_plane_funcs dm_plane_funcs = { + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, .reset = drm_atomic_helper_plane_reset, .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, .atomic_destroy_state = drm_atomic_helper_plane_destroy_state @@ -1577,38 +1579,67 @@ static uint32_t rgb_formats[] = { DRM_FORMAT_ABGR2101010, }; -int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, - struct amdgpu_crtc *acrtc, - uint32_t crtc_index) +static uint32_t yuv_formats[] = { + DRM_FORMAT_YUYV, + DRM_FORMAT_YVYU, + DRM_FORMAT_UYVY, + DRM_FORMAT_VYUY, +}; + +int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, + struct amdgpu_plane *aplane, + unsigned long possible_crtcs) { - int res = -ENOMEM; + int res = -EPERM; - struct drm_plane *primary_plane = - kzalloc(sizeof(*primary_plane), GFP_KERNEL); + switch (aplane->plane_type) { + case DRM_PLANE_TYPE_PRIMARY: + aplane->base.format_default = true; - if (!primary_plane) - goto fail_plane; + res = drm_universal_plane_init( + dm->adev->ddev, + &aplane->base, + possible_crtcs, + &dm_plane_funcs, + rgb_formats, + ARRAY_SIZE(rgb_formats), + NULL, aplane->plane_type, NULL); + break; + case DRM_PLANE_TYPE_OVERLAY: + res = drm_universal_plane_init( + dm->adev->ddev, + &aplane->base, + possible_crtcs, + &dm_plane_funcs, + yuv_formats, + ARRAY_SIZE(yuv_formats), + NULL, aplane->plane_type, NULL); + break; + case DRM_PLANE_TYPE_CURSOR: + DRM_ERROR("KMS: Cursor plane not implemented."); + break; + } - primary_plane->format_default = true; + drm_plane_helper_add(&aplane->base, &dm_plane_helper_funcs); - res = drm_universal_plane_init( - dm->adev->ddev, - primary_plane, - 0, - &dm_plane_funcs, - rgb_formats, - ARRAY_SIZE(rgb_formats), - NULL, - DRM_PLANE_TYPE_PRIMARY, NULL); + return res; +} - primary_plane->crtc = &acrtc->base; +int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, + struct drm_plane *plane, + uint32_t crtc_index) +{ + struct amdgpu_crtc *acrtc; + int res = -ENOMEM; - drm_plane_helper_add(primary_plane, &dm_plane_helper_funcs); + acrtc = kzalloc(sizeof(struct amdgpu_crtc), GFP_KERNEL); + if (!acrtc) + goto fail; res = drm_crtc_init_with_planes( dm->ddev, &acrtc->base, - primary_plane, + plane, NULL, &amdgpu_dm_crtc_funcs, NULL); @@ -1628,8 +1659,7 @@ int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, return 0; fail: - kfree(primary_plane); -fail_plane: + kfree(acrtc); acrtc->crtc_id = -1; return res; } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h index 1bbeb87dc9d0..ab6d51dbbf4b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h @@ -34,8 +34,11 @@ struct dc_validation_set; struct dc_surface; /*TODO Jodan Hersen use the one in amdgpu_dm*/ +int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, + struct amdgpu_plane *aplane, + unsigned long possible_crtcs); int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, - struct amdgpu_crtc *amdgpu_crtc, + struct drm_plane *plane, uint32_t link_index); int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm, struct amdgpu_connector *amdgpu_connector, diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 0731045f6084..9dd8b2ad4c59 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -45,6 +45,7 @@ struct dc_caps { uint32_t max_links; uint32_t max_audios; uint32_t max_slave_planes; + uint32_t max_surfaces; uint32_t max_downscale_ratio; uint32_t i2c_speed_in_khz; diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index b6f77f88be9c..d1685df09815 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -1035,6 +1035,8 @@ static bool construct( } } + dc->public.caps.max_surfaces = pool->base.pipe_count; + if (!resource_construct(num_virtual_links, dc, &pool->base, &res_create_funcs)) goto res_create_fail; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index e3002031c40d..065a2986b666 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -1455,6 +1455,8 @@ static bool construct( if (!dce110_hw_sequencer_construct(dc)) goto res_create_fail; + dc->public.caps.max_surfaces = pool->base.pipe_count; + bw_calcs_init(&dc->bw_dceip, &dc->bw_vbios, dc->ctx->asic_id); bw_calcs_data_update_from_pplib(dc); diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 32aa1b5bf1f9..ece3ec72363d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -1409,6 +1409,8 @@ static bool construct( &res_create_funcs)) goto res_create_fail; + dc->public.caps.max_surfaces = pool->base.pipe_count; + /* Create hardware sequencer */ if (!dce112_hw_sequencer_construct(dc)) goto res_create_fail; diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index efa58889058b..f677a77ca6e0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -1060,6 +1060,8 @@ static bool construct( if (!dce120_hw_sequencer_create(dc)) goto controller_create_fail; + dc->public.caps.max_surfaces = pool->base.pipe_count; + bw_calcs_init(&dc->bw_dceip, &dc->bw_vbios, dc->ctx->asic_id); bw_calcs_data_update_from_pplib(dc); diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index a3e8182885b2..752e0e7579b9 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -1043,6 +1043,8 @@ static bool construct( } } + dc->public.caps.max_surfaces = pool->base.pipe_count; + if (!resource_construct(num_virtual_links, dc, &pool->base, &res_create_funcs)) goto res_create_fail; -- cgit From f2a0f5e6b23d6649577081df3762e41abee04691 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 3 Apr 2017 13:36:26 -0400 Subject: drm/amd/display: Fix cleanup in amdgpu_dm_initialize_drm_device Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') 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 d76448d04423..1077af91884f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1071,15 +1071,15 @@ int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) { struct amdgpu_display_manager *dm = &adev->dm; uint32_t i; - struct amdgpu_connector *aconnector; - struct amdgpu_encoder *aencoder; + struct amdgpu_connector *aconnector = NULL; + struct amdgpu_encoder *aencoder = NULL; struct amdgpu_mode_info *mode_info = &adev->mode_info; uint32_t link_cnt; link_cnt = dm->dc->caps.max_links; if (amdgpu_dm_mode_config_init(dm->adev)) { DRM_ERROR("DM: Failed to initialize mode config\n"); - goto fail; + return -1; } for (i = 0; i < dm->dc->caps.max_surfaces; i++) { @@ -1116,7 +1116,7 @@ int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) aconnector = kzalloc(sizeof(*aconnector), GFP_KERNEL); if (!aconnector) - goto fail; + goto fail_free_planes; aencoder = kzalloc(sizeof(*aencoder), GFP_KERNEL); if (!aencoder) { @@ -1130,7 +1130,7 @@ int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) if (amdgpu_dm_connector_init(dm, aconnector, i, aencoder)) { DRM_ERROR("KMS: Failed to initialize connector\n"); - goto fail_free_connector; + goto fail_free_encoder; } if (dc_link_detect(dc_get_link_at_index(dm->dc, i), true)) @@ -1169,7 +1169,6 @@ fail_free_connector: fail_free_planes: for (i = 0; i < dm->dc->caps.max_surfaces; i++) kfree(mode_info->planes[i]); -fail: return -1; } -- cgit From 64d8b7806e40a1520d5eb47157ff4ee15efc3bf6 Mon Sep 17 00:00:00 2001 From: Shirish S Date: Thu, 23 Mar 2017 14:54:40 +0530 Subject: drm/amd/display: update plane functionalities This patch introduces amdgpu_drm_plane_state structure, which subclasses drm_plane_state and holds data suitable for configuring hardware. It switches reset(), atomic_duplicate_state() & atomic_destroy_state() functions to new internal implementation, earlier they were pointing to drm core functions. TESTS(On Chromium OS on Stoney Only) * Builds without compilation errors. * 'plane_test' passes for XR24 format based Overlay plane. * Chromium OS ui comes up. Signed-off-by: Shirish S Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 13 ++++++ .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 54 ++++++++++++++++++++-- 2 files changed, 62 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index 362d9559f065..bdae70e128c4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -57,6 +57,7 @@ struct amdgpu_hpd; #define to_amdgpu_connector(x) container_of(x, struct amdgpu_connector, base) #define to_amdgpu_encoder(x) container_of(x, struct amdgpu_encoder, base) #define to_amdgpu_framebuffer(x) container_of(x, struct amdgpu_framebuffer, base) +#define to_amdgpu_plane(x) container_of(x, struct amdgpu_plane, base) #define AMDGPU_MAX_HPD_PINS 6 #define AMDGPU_MAX_CRTCS 6 @@ -439,6 +440,18 @@ struct amdgpu_crtc { struct drm_pending_vblank_event *event; }; +struct amdgpu_drm_plane_state { + struct drm_plane_state base; + unsigned int h_ratio; + unsigned int v_ratio; +}; + +static inline struct amdgpu_drm_plane_state * +to_amdgpu_plane_state(struct drm_plane_state *state) +{ + return container_of(state, struct amdgpu_drm_plane_state, base); +} + struct amdgpu_plane { struct drm_plane base; enum drm_plane_type plane_type; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 1751f138c36a..aa243584b2cc 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -1445,12 +1445,56 @@ const struct drm_encoder_helper_funcs amdgpu_dm_encoder_helper_funcs = { .atomic_check = dm_encoder_helper_atomic_check }; +static void dm_drm_plane_reset(struct drm_plane *plane) +{ + struct amdgpu_drm_plane_state *amdgpu_state; + + if (plane->state) { + amdgpu_state = to_amdgpu_plane_state(plane->state); + if (amdgpu_state->base.fb) + drm_framebuffer_unreference(amdgpu_state->base.fb); + kfree(amdgpu_state); + plane->state = NULL; + } + + amdgpu_state = kzalloc(sizeof(*amdgpu_state), GFP_KERNEL); + if (amdgpu_state) { + plane->state = &amdgpu_state->base; + plane->state->plane = plane; + } +} + +static struct drm_plane_state * +dm_drm_plane_duplicate_state(struct drm_plane *plane) +{ + struct amdgpu_drm_plane_state *amdgpu_state; + struct amdgpu_drm_plane_state *copy; + + amdgpu_state = to_amdgpu_plane_state(plane->state); + copy = kzalloc(sizeof(*amdgpu_state), GFP_KERNEL); + if (!copy) + return NULL; + + __drm_atomic_helper_plane_duplicate_state(plane, ©->base); + return ©->base; +} + +static void dm_drm_plane_destroy_state(struct drm_plane *plane, + struct drm_plane_state *old_state) +{ + struct amdgpu_drm_plane_state *old_amdgpu_state = + to_amdgpu_plane_state(old_state); + __drm_atomic_helper_plane_destroy_state(old_state); + kfree(old_amdgpu_state); +} + static const struct drm_plane_funcs dm_plane_funcs = { - .update_plane = drm_atomic_helper_update_plane, - .disable_plane = drm_atomic_helper_disable_plane, - .reset = drm_atomic_helper_plane_reset, - .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, - .atomic_destroy_state = drm_atomic_helper_plane_destroy_state + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, + .destroy = drm_plane_cleanup, + .reset = dm_drm_plane_reset, + .atomic_duplicate_state = dm_drm_plane_duplicate_state, + .atomic_destroy_state = dm_drm_plane_destroy_state, }; static int dm_plane_helper_prepare_fb( -- cgit From 934d292316b5d3933d7fe6811c5d7a696c33910c Mon Sep 17 00:00:00 2001 From: Reza Amini Date: Fri, 17 Mar 2017 15:24:09 -0400 Subject: drm/amd/display: remove surface validation against stream rect Surface information is by default copied from old context in dc_commit_stream. Thus unchange streams will not be affected. For new streams, we shouldn't validate the new mode against the surface configuration of old_context. Signed-off-by: Reza Amini Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c | 5 ----- drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c | 5 ----- drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c | 5 ----- drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c | 5 ----- 4 files changed, 20 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index d1685df09815..7fae8537e18a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -788,11 +788,6 @@ static bool dce100_validate_surface_sets( if (set[i].surface_count > 1) return false; - if (set[i].surfaces[0]->clip_rect.width - < set[i].stream->src.width - || set[i].surfaces[0]->clip_rect.height - < set[i].stream->src.height) - return false; if (set[i].surfaces[0]->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) return false; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 065a2986b666..b4ab438e1c97 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -1007,11 +1007,6 @@ static bool dce110_validate_surface_sets( if (set[i].surface_count > 2) return false; - if (set[i].surfaces[0]->clip_rect.width - > set[i].stream->src.width - || set[i].surfaces[0]->clip_rect.height - > set[i].stream->src.height) - return false; if (set[i].surfaces[0]->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) return false; diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index ece3ec72363d..0a1ad2808129 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -972,11 +972,6 @@ static bool dce112_validate_surface_sets( if (set[i].surface_count > 1) return false; - if (set[i].surfaces[0]->clip_rect.width - > set[i].stream->src.width - || set[i].surfaces[0]->clip_rect.height - > set[i].stream->src.height) - return false; if (set[i].surfaces[0]->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) return false; diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 752e0e7579b9..ab8cee3e734e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -804,11 +804,6 @@ static bool dce80_validate_surface_sets( if (set[i].surface_count > 1) return false; - if (set[i].surfaces[0]->clip_rect.width - > set[i].stream->src.width - || set[i].surfaces[0]->clip_rect.height - > set[i].stream->src.height) - return false; if (set[i].surfaces[0]->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) return false; -- cgit From e8d726b71c55fb5c20fcf76bdea93c148a4b11e5 Mon Sep 17 00:00:00 2001 From: Reza Amini Date: Wed, 29 Mar 2017 12:05:15 -0400 Subject: drm/amd/display: refactor member referencing to improve readability Signed-off-by: Reza Amini Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 107 ++++++++-------------- 1 file changed, 39 insertions(+), 68 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 8f53d7a9f4dd..069f588a9e02 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1519,17 +1519,16 @@ static void set_avi_info_frame( uint8_t cn0_cn1 = 0; uint8_t *check_sum = NULL; uint8_t byte_index = 0; + union hdmi_info_packet *hdmi_info = &info_frame.avi_info_packet.info_packet_hdmi; color_space = pipe_ctx->stream->public.output_color_space; /* Initialize header */ - info_frame.avi_info_packet.info_packet_hdmi.bits.header. - info_frame_type = HDMI_INFOFRAME_TYPE_AVI; + hdmi_info->bits.header.info_frame_type = HDMI_INFOFRAME_TYPE_AVI; /* InfoFrameVersion_3 is defined by CEA861F (Section 6.4), but shall * not be used in HDMI 2.0 (Section 10.1) */ - info_frame.avi_info_packet.info_packet_hdmi.bits.header.version = 2; - info_frame.avi_info_packet.info_packet_hdmi.bits.header.length = - HDMI_AVI_INFOFRAME_SIZE; + hdmi_info->bits.header.version = 2; + hdmi_info->bits.header.length = HDMI_AVI_INFOFRAME_SIZE; /* * IDO-defined (Y2,Y1,Y0 = 1,1,1) shall not be used by devices built @@ -1555,52 +1554,41 @@ static void set_avi_info_frame( /* Y0_Y1_Y2 : The pixel encoding */ /* H14b AVI InfoFrame has extension on Y-field from 2 bits to 3 bits */ - info_frame.avi_info_packet.info_packet_hdmi.bits.Y0_Y1_Y2 = - pixel_encoding; + hdmi_info->bits.Y0_Y1_Y2 = pixel_encoding; /* A0 = 1 Active Format Information valid */ - info_frame.avi_info_packet.info_packet_hdmi.bits.A0 = - ACTIVE_FORMAT_VALID; + hdmi_info->bits.A0 = ACTIVE_FORMAT_VALID; /* B0, B1 = 3; Bar info data is valid */ - info_frame.avi_info_packet.info_packet_hdmi.bits.B0_B1 = - BAR_INFO_BOTH_VALID; + hdmi_info->bits.B0_B1 = BAR_INFO_BOTH_VALID; - info_frame.avi_info_packet.info_packet_hdmi.bits.SC0_SC1 = - PICTURE_SCALING_UNIFORM; + hdmi_info->bits.SC0_SC1 = PICTURE_SCALING_UNIFORM; /* S0, S1 : Underscan / Overscan */ /* TODO: un-hardcode scan type */ scan_type = SCANNING_TYPE_UNDERSCAN; - info_frame.avi_info_packet.info_packet_hdmi.bits.S0_S1 = scan_type; + hdmi_info->bits.S0_S1 = scan_type; /* C0, C1 : Colorimetry */ if (color_space == COLOR_SPACE_YCBCR709 || color_space == COLOR_SPACE_YCBCR709_LIMITED) - info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 = - COLORIMETRY_ITU709; + hdmi_info->bits.C0_C1 = COLORIMETRY_ITU709; else if (color_space == COLOR_SPACE_YCBCR601 || color_space == COLOR_SPACE_YCBCR601_LIMITED) - info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 = - COLORIMETRY_ITU601; + hdmi_info->bits.C0_C1 = COLORIMETRY_ITU601; else { if (stream->public.timing.pixel_encoding != PIXEL_ENCODING_RGB) BREAK_TO_DEBUGGER(); - info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 = - COLORIMETRY_NO_DATA; + hdmi_info->bits.C0_C1 = COLORIMETRY_NO_DATA; } if (color_space == COLOR_SPACE_2020_RGB_FULLRANGE || color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE || color_space == COLOR_SPACE_2020_YCBCR) { - info_frame.avi_info_packet.info_packet_hdmi.bits.EC0_EC2 = - COLORIMETRYEX_BT2020RGBYCBCR; - info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 = - COLORIMETRY_EXTENDED; + hdmi_info->bits.EC0_EC2 = COLORIMETRYEX_BT2020RGBYCBCR; + hdmi_info->bits.C0_C1 = COLORIMETRY_EXTENDED; } else if (color_space == COLOR_SPACE_ADOBERGB) { - info_frame.avi_info_packet.info_packet_hdmi.bits.EC0_EC2 = - COLORIMETRYEX_ADOBERGB; - info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 = - COLORIMETRY_EXTENDED; + hdmi_info->bits.EC0_EC2 = COLORIMETRYEX_ADOBERGB; + hdmi_info->bits.C0_C1 = COLORIMETRY_EXTENDED; } /* TODO: un-hardcode aspect ratio */ @@ -1609,93 +1597,76 @@ static void set_avi_info_frame( switch (aspect) { case ASPECT_RATIO_4_3: case ASPECT_RATIO_16_9: - info_frame.avi_info_packet.info_packet_hdmi.bits.M0_M1 = aspect; + hdmi_info->bits.M0_M1 = aspect; break; case ASPECT_RATIO_NO_DATA: case ASPECT_RATIO_64_27: case ASPECT_RATIO_256_135: default: - info_frame.avi_info_packet.info_packet_hdmi.bits.M0_M1 = 0; + hdmi_info->bits.M0_M1 = 0; } /* Active Format Aspect ratio - same as Picture Aspect Ratio. */ - info_frame.avi_info_packet.info_packet_hdmi.bits.R0_R3 = - ACTIVE_FORMAT_ASPECT_RATIO_SAME_AS_PICTURE; + hdmi_info->bits.R0_R3 = ACTIVE_FORMAT_ASPECT_RATIO_SAME_AS_PICTURE; /* TODO: un-hardcode cn0_cn1 and itc */ cn0_cn1 = 0; itc = false; if (itc) { - info_frame.avi_info_packet.info_packet_hdmi.bits.ITC = 1; - info_frame.avi_info_packet.info_packet_hdmi.bits.CN0_CN1 = - cn0_cn1; + hdmi_info->bits.ITC = 1; + hdmi_info->bits.CN0_CN1 = cn0_cn1; } /* TODO : We should handle YCC quantization */ /* but we do not have matrix calculation */ if (color_space == COLOR_SPACE_SRGB) { - info_frame.avi_info_packet.info_packet_hdmi.bits.Q0_Q1 = - RGB_QUANTIZATION_FULL_RANGE; - info_frame.avi_info_packet.info_packet_hdmi.bits.YQ0_YQ1 = - YYC_QUANTIZATION_FULL_RANGE; + hdmi_info->bits.Q0_Q1 = RGB_QUANTIZATION_FULL_RANGE; + hdmi_info->bits.YQ0_YQ1 = YYC_QUANTIZATION_FULL_RANGE; } else if (color_space == COLOR_SPACE_SRGB_LIMITED) { - info_frame.avi_info_packet.info_packet_hdmi.bits.Q0_Q1 = - RGB_QUANTIZATION_LIMITED_RANGE; - info_frame.avi_info_packet.info_packet_hdmi.bits.YQ0_YQ1 = - YYC_QUANTIZATION_LIMITED_RANGE; + hdmi_info->bits.Q0_Q1 = RGB_QUANTIZATION_LIMITED_RANGE; + hdmi_info->bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; } else { - info_frame.avi_info_packet.info_packet_hdmi.bits.Q0_Q1 = - RGB_QUANTIZATION_DEFAULT_RANGE; - info_frame.avi_info_packet.info_packet_hdmi.bits.YQ0_YQ1 = - YYC_QUANTIZATION_LIMITED_RANGE; + hdmi_info->bits.Q0_Q1 = RGB_QUANTIZATION_DEFAULT_RANGE; + hdmi_info->bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; } - info_frame.avi_info_packet.info_packet_hdmi.bits.VIC0_VIC7 = + hdmi_info->bits.VIC0_VIC7 = stream->public.timing.vic; /* pixel repetition * PR0 - PR3 start from 0 whereas pHwPathMode->mode.timing.flags.pixel * repetition start from 1 */ - info_frame.avi_info_packet.info_packet_hdmi.bits.PR0_PR3 = 0; + hdmi_info->bits.PR0_PR3 = 0; /* Bar Info * barTop: Line Number of End of Top Bar. * barBottom: Line Number of Start of Bottom Bar. * barLeft: Pixel Number of End of Left Bar. * barRight: Pixel Number of Start of Right Bar. */ - info_frame.avi_info_packet.info_packet_hdmi.bits.bar_top = - stream->public.timing.v_border_top; - info_frame.avi_info_packet.info_packet_hdmi.bits.bar_bottom = - (stream->public.timing.v_border_top + hdmi_info->bits.bar_top = stream->public.timing.v_border_top; + hdmi_info->bits.bar_bottom = (stream->public.timing.v_border_top - stream->public.timing.v_border_bottom + 1); - info_frame.avi_info_packet.info_packet_hdmi.bits.bar_left = - stream->public.timing.h_border_left; - info_frame.avi_info_packet.info_packet_hdmi.bits.bar_right = - (stream->public.timing.h_total + hdmi_info->bits.bar_left = stream->public.timing.h_border_left; + hdmi_info->bits.bar_right = (stream->public.timing.h_total - stream->public.timing.h_border_right + 1); /* check_sum - Calculate AFMT_AVI_INFO0 ~ AFMT_AVI_INFO3 */ - check_sum = - &info_frame. - avi_info_packet.info_packet_hdmi.packet_raw_data.sb[0]; + check_sum = &info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.sb[0]; + *check_sum = HDMI_INFOFRAME_TYPE_AVI + HDMI_AVI_INFOFRAME_SIZE + 2; for (byte_index = 1; byte_index <= HDMI_AVI_INFOFRAME_SIZE; byte_index++) - *check_sum += info_frame.avi_info_packet.info_packet_hdmi. - packet_raw_data.sb[byte_index]; + *check_sum += hdmi_info->packet_raw_data.sb[byte_index]; /* one byte complement */ *check_sum = (uint8_t) (0x100 - *check_sum); /* Store in hw_path_mode */ - info_packet->hb0 = - info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.hb0; - info_packet->hb1 = - info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.hb1; - info_packet->hb2 = - info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.hb2; + info_packet->hb0 = hdmi_info->packet_raw_data.hb0; + info_packet->hb1 = hdmi_info->packet_raw_data.hb1; + info_packet->hb2 = hdmi_info->packet_raw_data.hb2; for (byte_index = 0; byte_index < sizeof(info_frame.avi_info_packet. info_packet_hdmi.packet_raw_data.sb); byte_index++) -- cgit From bddd696ddd437ce15d278b2a5318ef44d3c171cd Mon Sep 17 00:00:00 2001 From: Zeyu Fan Date: Wed, 29 Mar 2017 17:21:56 -0400 Subject: drm/amd/display: Temporary disable PSR for HBR2 & HBR3 Signed-off-by: Zeyu Fan Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') 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 4f6d1d2d5b9b..b8c40e8bee5a 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 @@ -2165,7 +2165,8 @@ static void retrieve_link_cap(struct core_link *link) CONN_DATA_DETECT(link, dpcd_data, sizeof(dpcd_data), "Rx Caps: "); /* TODO: Confirm if need retrieve_psr_link_cap */ - retrieve_psr_link_cap(link, link->edp_revision); + if (link->public.reported_link_cap.link_rate < LINK_RATE_HIGH2) + retrieve_psr_link_cap(link, link->edp_revision); } void detect_dp_sink_caps(struct core_link *link) -- cgit From dff06ddd7f0d322a046fd4a34dec589fbb97adef Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 29 Mar 2017 16:24:19 -0400 Subject: drm/amd/display: fix dce_calc surface pitch setting for non underlay pipes Signed-off-by: Dmytro Laktyushkin Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c index 5ac614f433f8..627b7582394a 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c @@ -2614,7 +2614,7 @@ static void populate_initial_data( data->v_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->public.timing.v_total); data->pixel_rate[num_displays + 4] = bw_frc_to_fixed(pipe[i].stream->public.timing.pix_clk_khz, 1000); data->src_width[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.viewport.width); - data->pitch_in_pixels[num_displays + 4] = bw_int_to_fixed(pipe[i].surface->public.plane_size.grph.surface_pitch); + data->pitch_in_pixels[num_displays + 4] = data->src_width[num_displays + 4]; data->src_height[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.viewport.height); data->h_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.taps.h_taps); data->v_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.taps.v_taps); @@ -2712,7 +2712,7 @@ static void populate_initial_data( data->pixel_rate[num_displays + 4] = bw_frc_to_fixed(pipe[i].stream->public.timing.pix_clk_khz, 1000); if (pipe[i].surface) { data->src_width[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.viewport.width); - data->pitch_in_pixels[num_displays + 4] = bw_int_to_fixed(pipe[i].surface->public.plane_size.grph.surface_pitch); + data->pitch_in_pixels[num_displays + 4] = data->src_width[num_displays + 4]; data->src_height[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.viewport.height); data->h_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.taps.h_taps); data->v_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.taps.v_taps); -- cgit From 9fb8de78ed01453ccc696a9f18cbfe41c60fd433 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Tue, 14 Feb 2017 13:50:17 -0500 Subject: drm/amd/display: Remove get_connector_for_link. We can keep a 1:1 relation between a link and a physical connector and hence skip the iteration. This function is used in context of only physical connetors. Signed-off-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 36 +++------------------- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 1 + drivers/gpu/drm/amd/display/dc/dc.h | 2 ++ 3 files changed, 8 insertions(+), 31 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index d4e01b51f949..bdf7c6075414 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -148,21 +148,6 @@ static struct amdgpu_connector *get_connector_for_sink( return NULL; } -static struct amdgpu_connector *get_connector_for_link( - struct drm_device *dev, - const struct dc_link *link) -{ - struct drm_connector *connector; - - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); - if (aconnector->dc_link == link) - return aconnector; - } - - return NULL; -} - static void get_payload_table( struct amdgpu_connector *aconnector, struct dp_mst_stream_allocation_table *proposed_table) @@ -363,9 +348,7 @@ bool dm_helpers_dp_mst_start_top_mgr( const struct dc_link *link, bool boot) { - struct amdgpu_device *adev = ctx->driver_context; - struct drm_device *dev = adev->ddev; - struct amdgpu_connector *aconnector = get_connector_for_link(dev, link); + struct amdgpu_connector *aconnector = link->priv; if (!aconnector) { DRM_ERROR("Failed to found connector for link!"); @@ -388,9 +371,7 @@ void dm_helpers_dp_mst_stop_top_mgr( struct dc_context *ctx, const struct dc_link *link) { - struct amdgpu_device *adev = ctx->driver_context; - struct drm_device *dev = adev->ddev; - struct amdgpu_connector *aconnector = get_connector_for_link(dev, link); + struct amdgpu_connector *aconnector = link->priv; if (!aconnector) { DRM_ERROR("Failed to found connector for link!"); @@ -412,9 +393,7 @@ bool dm_helpers_dp_read_dpcd( uint32_t size) { - struct amdgpu_device *adev = ctx->driver_context; - struct drm_device *dev = adev->ddev; - struct amdgpu_connector *aconnector = get_connector_for_link(dev, link); + struct amdgpu_connector *aconnector = link->priv; if (!aconnector) { DRM_ERROR("Failed to found connector for link!"); @@ -432,10 +411,7 @@ bool dm_helpers_dp_write_dpcd( const uint8_t *data, uint32_t size) { - - struct amdgpu_device *adev = ctx->driver_context; - struct drm_device *dev = adev->ddev; - struct amdgpu_connector *aconnector = get_connector_for_link(dev, link); + struct amdgpu_connector *aconnector = link->priv; if (!aconnector) { DRM_ERROR("Failed to found connector for link!"); @@ -451,9 +427,7 @@ bool dm_helpers_submit_i2c( const struct dc_link *link, struct i2c_command *cmd) { - struct amdgpu_device *adev = ctx->driver_context; - struct drm_device *dev = adev->ddev; - struct amdgpu_connector *aconnector = get_connector_for_link(dev, link); + struct amdgpu_connector *aconnector = link->priv; struct i2c_msg *msgs; int i = 0; int num = cmd->number_of_payloads; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index aa243584b2cc..df7cc463b946 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2002,6 +2002,7 @@ int amdgpu_dm_connector_init( struct dc *dc = dm->dc; const struct dc_link *link = dc_get_link_at_index(dc, link_index); struct amdgpu_i2c_adapter *i2c; + ((struct dc_link *)link)->priv = aconnector; DRM_DEBUG_KMS("%s()\n", __func__); diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 9dd8b2ad4c59..6bb6ad23b31b 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -592,6 +592,8 @@ struct dc_link { struct psr_caps psr_caps; bool test_pattern_enabled; union compliance_test_state compliance_test_state; + + void *priv; }; struct dpcd_caps { -- cgit From 5c4e9806435d7da665af08b3071446b9617eb9cb Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Tue, 14 Feb 2017 15:47:24 -0500 Subject: drm/amd/display: Remove get_connector_for_sink. Keep 1:1 relation between MST sink and it's MST connector. Signed-off-by: Andrey Grodzovsky Reviewed-by: Tony Cheng Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 27 +++------------------- .../amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 7 +++++- drivers/gpu/drm/amd/display/dc/dc.h | 1 + 3 files changed, 10 insertions(+), 25 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index bdf7c6075414..bc0bfa9586ee 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -133,21 +133,6 @@ enum dc_edid_status dm_helpers_parse_edid_caps( return result; } -static struct amdgpu_connector *get_connector_for_sink( - struct drm_device *dev, - const struct dc_sink *sink) -{ - struct drm_connector *connector; - - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); - if (aconnector->dc_sink == sink) - return aconnector; - } - - return NULL; -} - static void get_payload_table( struct amdgpu_connector *aconnector, struct dp_mst_stream_allocation_table *proposed_table) @@ -194,8 +179,6 @@ bool dm_helpers_dp_mst_write_payload_allocation_table( struct dp_mst_stream_allocation_table *proposed_table, bool enable) { - struct amdgpu_device *adev = ctx->driver_context; - struct drm_device *dev = adev->ddev; struct amdgpu_connector *aconnector; struct drm_dp_mst_topology_mgr *mst_mgr; struct drm_dp_mst_port *mst_port; @@ -205,7 +188,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table( int bpp = 0; int pbn = 0; - aconnector = get_connector_for_sink(dev, stream->sink); + aconnector = stream->sink->priv; if (!aconnector || !aconnector->mst_port) return false; @@ -284,13 +267,11 @@ bool dm_helpers_dp_mst_poll_for_allocation_change_trigger( struct dc_context *ctx, const struct dc_stream *stream) { - struct amdgpu_device *adev = ctx->driver_context; - struct drm_device *dev = adev->ddev; struct amdgpu_connector *aconnector; struct drm_dp_mst_topology_mgr *mst_mgr; int ret; - aconnector = get_connector_for_sink(dev, stream->sink); + aconnector = stream->sink->priv; if (!aconnector || !aconnector->mst_port) return false; @@ -313,14 +294,12 @@ bool dm_helpers_dp_mst_send_payload_allocation( const struct dc_stream *stream, bool enable) { - struct amdgpu_device *adev = ctx->driver_context; - struct drm_device *dev = adev->ddev; struct amdgpu_connector *aconnector; struct drm_dp_mst_topology_mgr *mst_mgr; struct drm_dp_mst_port *mst_port; int ret; - aconnector = get_connector_for_sink(dev, stream->sink); + aconnector = stream->sink->priv; if (!aconnector || !aconnector->mst_port) return false; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 41988c89d471..069511bb6fab 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -325,6 +325,7 @@ static void dm_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr) struct drm_connector *connector; struct amdgpu_connector *aconnector; struct edid *edid; + struct dc_sink *dc_sink; drm_modeset_lock_all(dev); list_for_each_entry(connector, &dev->mode_config.connector_list, head) { @@ -352,11 +353,15 @@ static void dm_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr) aconnector->edid = edid; - aconnector->dc_sink = dc_link_add_remote_sink( + dc_sink = dc_link_add_remote_sink( aconnector->dc_link, (uint8_t *)edid, (edid->extensions + 1) * EDID_LENGTH, &init_params); + + dc_sink->priv = aconnector; + aconnector->dc_sink = dc_sink; + if (aconnector->dc_sink) amdgpu_dm_add_sink_to_freesync_module( connector, diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 6bb6ad23b31b..d2960552c78e 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -719,6 +719,7 @@ struct dc_sink { struct dc_container_id *dc_container_id; uint32_t dongle_max_pix_clk; bool converter_disable_audio; + void *priv; }; void dc_sink_retain(const struct dc_sink *sink); -- cgit From bb01672c79649de08fe335b55aea5315d781c443 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Sat, 4 Mar 2017 20:56:46 -0500 Subject: drm/amd/display: Fix i2c write flag. I2C_M_RD was translated to write instead of read. Signed-off-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 2 +- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index bc0bfa9586ee..5b096be44e59 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -423,7 +423,7 @@ bool dm_helpers_submit_i2c( return false; for (i = 0; i < num; i++) { - msgs[i].flags = cmd->payloads[i].write ? I2C_M_RD : 0; + msgs[i].flags = cmd->payloads[i].write ? 0 : I2C_M_RD; msgs[i].addr = cmd->payloads[i].address; msgs[i].len = cmd->payloads[i].length; msgs[i].buf = cmd->payloads[i].data; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index df7cc463b946..c09af2b3350c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -1948,7 +1948,7 @@ int amdgpu_dm_i2c_xfer(struct i2c_adapter *i2c_adap, cmd.speed = 100; for (i = 0; i < num; i++) { - cmd.payloads[i].write = (msgs[i].flags & I2C_M_RD); + cmd.payloads[i].write = !(msgs[i].flags & I2C_M_RD); cmd.payloads[i].address = msgs[i].addr; cmd.payloads[i].length = msgs[i].len; cmd.payloads[i].data = msgs[i].buf; -- cgit From 7c7f5b15be6528b33d825ead6acb739d7d061a2e Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Tue, 28 Mar 2017 16:57:52 -0400 Subject: drm/amd/display: Refactor edid read. Allow Linux to use DRM provided EDID read functioality by moving DAL edid implementation to module hence removing this code from DC by this cleaning up DC code for upstream. v2: Removing ddc_service. No more need for it. Signed-off-by: Andrey Grodzovsky Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 47 +++ .../amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 47 ++- .../amd/display/amdgpu_dm/amdgpu_dm_mst_types.h | 2 +- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 10 +- drivers/gpu/drm/amd/display/dc/core/dc.c | 78 +++-- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 53 +--- drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c | 337 +-------------------- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 30 +- drivers/gpu/drm/amd/display/dc/dc.h | 21 +- drivers/gpu/drm/amd/display/dc/dc_types.h | 6 + drivers/gpu/drm/amd/display/dc/dm_helpers.h | 10 + drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c | 9 +- drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h | 38 ++- .../drm/amd/display/include/ddc_service_types.h | 28 -- .../gpu/drm/amd/display/include/i2caux_interface.h | 3 + 15 files changed, 254 insertions(+), 465 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index 5b096be44e59..01d04fa2419e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -435,3 +435,50 @@ bool dm_helpers_submit_i2c( return result; } + +enum dc_edid_status dm_helpers_read_local_edid( + struct dc_context *ctx, + struct dc_link *link, + struct dc_sink *sink) +{ + struct amdgpu_connector *aconnector = link->priv; + struct i2c_adapter *ddc; + int retry = 3; + enum dc_edid_status edid_status; + struct edid *edid; + + if (link->aux_mode) + ddc = &aconnector->dm_dp_aux.aux.ddc; + else + ddc = &aconnector->i2c->base; + + /* some dongles read edid incorrectly the first time, + * do check sum and retry to make sure read correct edid. + */ + do { + + edid = drm_get_edid(&aconnector->base, ddc); + + if (!edid) + return EDID_NO_RESPONSE; + + sink->dc_edid.length = EDID_LENGTH * (edid->extensions + 1); + memmove(sink->dc_edid.raw_edid, (uint8_t *)edid, sink->dc_edid.length); + + /* We don't need the original edid anymore */ + kfree(edid); + + edid_status = dm_helpers_parse_edid_caps( + ctx, + &sink->dc_edid, + &sink->edid_caps); + + } while (edid_status == EDID_BAD_CHECKSUM && --retry > 0); + + if (edid_status != EDID_OK) + DRM_ERROR("EDID err: %d, on connector: %s", + edid_status, + aconnector->base.name); + + return edid_status; +} diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 069511bb6fab..187464ac27b3 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -81,24 +81,43 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg struct drm_device *drm_dev = pci_get_drvdata(pdev); struct amdgpu_device *adev = drm_dev->dev_private; struct dc *dc = adev->dm.dc; + enum i2c_mot_mode mot = (msg->request & DP_AUX_I2C_MOT) ? I2C_MOT_TRUE : I2C_MOT_FALSE; bool res; - switch (msg->request) { + switch (msg->request & ~DP_AUX_I2C_MOT) { case DP_AUX_NATIVE_READ: - res = dc_read_dpcd( - dc, - TO_DM_AUX(aux)->link_index, - msg->address, - msg->buffer, - msg->size); + res = dc_read_aux_dpcd( + dc, + TO_DM_AUX(aux)->link_index, + msg->address, + msg->buffer, + msg->size); break; case DP_AUX_NATIVE_WRITE: - res = dc_write_dpcd( - dc, - TO_DM_AUX(aux)->link_index, - msg->address, - msg->buffer, - msg->size); + res = dc_write_aux_dpcd( + dc, + TO_DM_AUX(aux)->link_index, + msg->address, + msg->buffer, + msg->size); + break; + case DP_AUX_I2C_READ: + res = dc_read_aux_i2c( + dc, + TO_DM_AUX(aux)->link_index, + mot, + msg->address, + msg->buffer, + msg->size); + break; + case DP_AUX_I2C_WRITE: + res = dc_write_aux_i2c( + dc, + TO_DM_AUX(aux)->link_index, + mot, + msg->address, + msg->buffer, + msg->size); break; default: return 0; @@ -418,7 +437,7 @@ static const struct drm_dp_mst_topology_cbs dm_mst_cbs = { .register_connector = dm_dp_mst_register_connector }; -void amdgpu_dm_initialize_mst_connector( +void amdgpu_dm_initialize_dp_connector( struct amdgpu_display_manager *dm, struct amdgpu_connector *aconnector) { diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h index 6130d62ac65c..418061f3b46b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h @@ -29,7 +29,7 @@ struct amdgpu_display_manager; struct amdgpu_connector; -void amdgpu_dm_initialize_mst_connector( +void amdgpu_dm_initialize_dp_connector( struct amdgpu_display_manager *dm, struct amdgpu_connector *aconnector); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index c09af2b3350c..345df1b6d82b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2047,7 +2047,7 @@ int amdgpu_dm_connector_init( if (connector_type == DRM_MODE_CONNECTOR_DisplayPort || connector_type == DRM_MODE_CONNECTOR_eDP) - amdgpu_dm_initialize_mst_connector(dm, aconnector); + amdgpu_dm_initialize_dp_connector(dm, aconnector); #if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\ defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) @@ -3038,9 +3038,11 @@ static bool is_dp_capable_without_timing_msa( uint8_t dpcd_data; bool capable = false; if (amdgpu_connector->dc_link && - dc_read_dpcd(dc, amdgpu_connector->dc_link->link_index, - DP_DOWN_STREAM_PORT_COUNT, - &dpcd_data, sizeof(dpcd_data)) ) + dc_read_aux_dpcd( + dc, + amdgpu_connector->dc_link->link_index, + DP_DOWN_STREAM_PORT_COUNT, + &dpcd_data, sizeof(dpcd_data))) capable = (dpcd_data & DP_MSA_TIMING_PAR_IGNORED) ? true:false; return capable; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index b3891228b499..40a800155fe6 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1553,7 +1553,7 @@ void dc_resume(const struct dc *dc) core_link_resume(core_dc->links[i]); } -bool dc_read_dpcd( +bool dc_read_aux_dpcd( struct dc *dc, uint32_t link_index, uint32_t address, @@ -1565,56 +1565,100 @@ bool dc_read_dpcd( struct core_link *link = core_dc->links[link_index]; enum ddc_result r = dal_ddc_service_read_dpcd_data( link->ddc, + false, + I2C_MOT_UNDEF, address, data, size); return r == DDC_RESULT_SUCESSFULL; } -bool dc_query_ddc_data( +bool dc_write_aux_dpcd( struct dc *dc, uint32_t link_index, uint32_t address, - uint8_t *write_buf, - uint32_t write_size, - uint8_t *read_buf, - uint32_t read_size) { - + const uint8_t *data, + uint32_t size) +{ struct core_dc *core_dc = DC_TO_CORE(dc); - struct core_link *link = core_dc->links[link_index]; - bool result = dal_ddc_service_query_ddc_data( + enum ddc_result r = dal_ddc_service_write_dpcd_data( link->ddc, + false, + I2C_MOT_UNDEF, address, - write_buf, - write_size, - read_buf, - read_size); - - return result; + data, + size); + return r == DDC_RESULT_SUCESSFULL; } +bool dc_read_aux_i2c( + struct dc *dc, + uint32_t link_index, + enum i2c_mot_mode mot, + uint32_t address, + uint8_t *data, + uint32_t size) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); -bool dc_write_dpcd( + struct core_link *link = core_dc->links[link_index]; + enum ddc_result r = dal_ddc_service_read_dpcd_data( + link->ddc, + true, + mot, + address, + data, + size); + return r == DDC_RESULT_SUCESSFULL; +} + +bool dc_write_aux_i2c( struct dc *dc, uint32_t link_index, + enum i2c_mot_mode mot, uint32_t address, const uint8_t *data, uint32_t size) { struct core_dc *core_dc = DC_TO_CORE(dc); - struct core_link *link = core_dc->links[link_index]; enum ddc_result r = dal_ddc_service_write_dpcd_data( link->ddc, + true, + mot, address, data, size); return r == DDC_RESULT_SUCESSFULL; } +bool dc_query_ddc_data( + struct dc *dc, + uint32_t link_index, + uint32_t address, + uint8_t *write_buf, + uint32_t write_size, + uint8_t *read_buf, + uint32_t read_size) { + + struct core_dc *core_dc = DC_TO_CORE(dc); + + struct core_link *link = core_dc->links[link_index]; + + bool result = dal_ddc_service_query_ddc_data( + link->ddc, + address, + write_buf, + write_size, + read_buf, + read_size); + + return result; +} + bool dc_submit_i2c( struct dc *dc, uint32_t link_index, diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 74dd272d7452..0f825f6326ab 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -464,39 +464,6 @@ static void link_disconnect_sink(struct core_link *link) link->dpcd_sink_count = 0; } -static enum dc_edid_status read_edid( - struct core_link *link, - struct core_sink *sink) -{ - uint32_t edid_retry = 3; - enum dc_edid_status edid_status; - - /* some dongles read edid incorrectly the first time, - * do check sum and retry to make sure read correct edid. - */ - do { - sink->public.dc_edid.length = - dal_ddc_service_edid_query(link->ddc); - - if (0 == sink->public.dc_edid.length) - return EDID_NO_RESPONSE; - - dal_ddc_service_get_edid_buf(link->ddc, - sink->public.dc_edid.raw_edid); - edid_status = dm_helpers_parse_edid_caps( - sink->ctx, - &sink->public.dc_edid, - &sink->public.edid_caps); - --edid_retry; - if (edid_status == EDID_BAD_CHECKSUM) - dm_logger_write(link->ctx->logger, LOG_WARNING, - "Bad EDID checksum, retry remain: %d\n", - edid_retry); - } while (edid_status == EDID_BAD_CHECKSUM && edid_retry > 0); - - return edid_status; -} - static void detect_dp( struct core_link *link, struct display_sink_capability *sink_caps, @@ -673,6 +640,9 @@ bool dc_link_detect(const struct dc_link *dc_link, bool boot) link->ddc, sink_caps.transaction_type); + link->public.aux_mode = dal_ddc_service_is_in_aux_transaction_mode( + link->ddc); + sink_init_data.link = &link->public; sink_init_data.sink_signal = sink_caps.signal; @@ -688,7 +658,10 @@ bool dc_link_detect(const struct dc_link *dc_link, bool boot) sink = DC_SINK_TO_CORE(dc_sink); link->public.local_sink = &sink->public; - edid_status = read_edid(link, sink); + edid_status = dm_helpers_read_local_edid( + link->ctx, + &link->public, + &sink->public); switch (edid_status) { case EDID_BAD_CHECKSUM: @@ -1500,11 +1473,13 @@ bool dc_link_setup_psr(const struct dc_link *dc_link, */ psr_configuration.bits.IRQ_HPD_WITH_CRC_ERROR = 1; } - dal_ddc_service_write_dpcd_data( - link->ddc, - 368, - &psr_configuration.raw, - sizeof(psr_configuration.raw)); + + dm_helpers_dp_write_dpcd( + link->ctx, + dc_link, + 368, + &psr_configuration.raw, + sizeof(psr_configuration.raw)); psr_context.channel = link->ddc->ddc_pin->hw_info.ddc_channel; if (psr_context.channel == 0) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c index 4e9465b630d1..2f5a89c5b063 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c @@ -58,30 +58,6 @@ struct dp_hdmi_dongle_signature_data { uint8_t eot;/* end of transmition '\x4' */ }; -/* Address range from 0x00 to 0x1F.*/ -#define DP_ADAPTOR_TYPE2_SIZE 0x20 -#define DP_ADAPTOR_TYPE2_REG_ID 0x10 -#define DP_ADAPTOR_TYPE2_REG_MAX_TMDS_CLK 0x1D -/* Identifies adaptor as Dual-mode adaptor */ -#define DP_ADAPTOR_TYPE2_ID 0xA0 -/* MHz*/ -#define DP_ADAPTOR_TYPE2_MAX_TMDS_CLK 600 -/* MHz*/ -#define DP_ADAPTOR_TYPE2_MIN_TMDS_CLK 25 -/* kHZ*/ -#define DP_ADAPTOR_DVI_MAX_TMDS_CLK 165000 -/* kHZ*/ -#define DP_ADAPTOR_HDMI_SAFE_MAX_TMDS_CLK 165000 - -#define DDC_I2C_COMMAND_ENGINE I2C_COMMAND_ENGINE_SW - -enum edid_read_result { - EDID_READ_RESULT_EDID_MATCH = 0, - EDID_READ_RESULT_EDID_MISMATCH, - EDID_READ_RESULT_CHECKSUM_READ_ERR, - EDID_READ_RESULT_VENDOR_READ_ERR -}; - /* SCDC Address defines (HDMI 2.0)*/ #define HDMI_SCDC_WRITE_UPDATE_0_ARRAY 3 #define HDMI_SCDC_ADDRESS 0x54 @@ -392,7 +368,7 @@ static uint32_t defer_delay_converter_wa( #define DP_TRANSLATOR_DELAY 5 -static uint32_t get_defer_delay(struct ddc_service *ddc) +uint32_t get_defer_delay(struct ddc_service *ddc) { uint32_t defer_delay = 0; @@ -451,307 +427,6 @@ static bool i2c_read( &command); } -static uint8_t aux_read_edid_block( - struct ddc_service *ddc, - uint8_t address, - uint8_t index, - uint8_t *buf) -{ - struct aux_command cmd = { - .payloads = NULL, - .number_of_payloads = 0, - .defer_delay = get_defer_delay(ddc), - .max_defer_write_retry = 0 }; - - uint8_t retrieved = 0; - uint8_t base_offset = - (index % DDC_EDID_BLOCKS_PER_SEGMENT) * DDC_EDID_BLOCK_SIZE; - uint8_t segment = index / DDC_EDID_BLOCKS_PER_SEGMENT; - - for (retrieved = 0; retrieved < DDC_EDID_BLOCK_SIZE; - retrieved += DEFAULT_AUX_MAX_DATA_SIZE) { - - uint8_t offset = base_offset + retrieved; - - struct aux_payload payloads[3] = { - { - .i2c_over_aux = true, - .write = true, - .address = DDC_EDID_SEGMENT_ADDRESS, - .length = 1, - .data = &segment }, - { - .i2c_over_aux = true, - .write = true, - .address = address, - .length = 1, - .data = &offset }, - { - .i2c_over_aux = true, - .write = false, - .address = address, - .length = DEFAULT_AUX_MAX_DATA_SIZE, - .data = &buf[retrieved] } }; - - if (segment == 0) { - cmd.payloads = &payloads[1]; - cmd.number_of_payloads = 2; - } else { - cmd.payloads = payloads; - cmd.number_of_payloads = 3; - } - - if (!dal_i2caux_submit_aux_command( - ddc->ctx->i2caux, - ddc->ddc_pin, - &cmd)) - /* cannot read, break*/ - break; - } - - /* Reset segment to 0. Needed by some panels */ - if (0 != segment) { - struct aux_payload payloads[1] = { { - .i2c_over_aux = true, - .write = true, - .address = DDC_EDID_SEGMENT_ADDRESS, - .length = 1, - .data = &segment } }; - bool result = false; - - segment = 0; - - cmd.number_of_payloads = ARRAY_SIZE(payloads); - cmd.payloads = payloads; - - result = dal_i2caux_submit_aux_command( - ddc->ctx->i2caux, - ddc->ddc_pin, - &cmd); - - if (false == result) - dm_logger_write( - ddc->ctx->logger, LOG_ERROR, - "%s: Writing of EDID Segment (0x30) failed!\n", - __func__); - } - - return retrieved; -} - -static uint8_t i2c_read_edid_block( - struct ddc_service *ddc, - uint8_t address, - uint8_t index, - uint8_t *buf) -{ - bool ret = false; - uint8_t offset = (index % DDC_EDID_BLOCKS_PER_SEGMENT) * - DDC_EDID_BLOCK_SIZE; - uint8_t segment = index / DDC_EDID_BLOCKS_PER_SEGMENT; - - struct i2c_command cmd = { - .payloads = NULL, - .number_of_payloads = 0, - .engine = DDC_I2C_COMMAND_ENGINE, - .speed = ddc->ctx->dc->caps.i2c_speed_in_khz }; - - struct i2c_payload payloads[3] = { - { - .write = true, - .address = DDC_EDID_SEGMENT_ADDRESS, - .length = 1, - .data = &segment }, - { - .write = true, - .address = address, - .length = 1, - .data = &offset }, - { - .write = false, - .address = address, - .length = DDC_EDID_BLOCK_SIZE, - .data = buf } }; -/* - * Some I2C engines don't handle stop/start between write-offset and read-data - * commands properly. For those displays, we have to force the newer E-DDC - * behavior of repeated-start which can be enabled by runtime parameter. */ -/* Originally implemented for OnLive using NXP receiver chip */ - - if (index == 0 && !ddc->flags.FORCE_READ_REPEATED_START) { - /* base block, use use DDC2B, submit as 2 commands */ - cmd.payloads = &payloads[1]; - cmd.number_of_payloads = 1; - - if (dm_helpers_submit_i2c( - ddc->ctx, - &ddc->link->public, - &cmd)) { - - cmd.payloads = &payloads[2]; - cmd.number_of_payloads = 1; - - ret = dm_helpers_submit_i2c( - ddc->ctx, - &ddc->link->public, - &cmd); - } - - } else { - /* - * extension block use E-DDC, submit as 1 command - * or if repeated-start is forced by runtime parameter - */ - if (segment != 0) { - /* include segment offset in command*/ - cmd.payloads = payloads; - cmd.number_of_payloads = 3; - } else { - /* we are reading first segment, - * segment offset is not required */ - cmd.payloads = &payloads[1]; - cmd.number_of_payloads = 2; - } - - ret = dm_helpers_submit_i2c( - ddc->ctx, - &ddc->link->public, - &cmd); - } - - return ret ? DDC_EDID_BLOCK_SIZE : 0; -} - -static uint32_t query_edid_block( - struct ddc_service *ddc, - uint8_t address, - uint8_t index, - uint8_t *buf, - uint32_t size) -{ - uint32_t size_retrieved = 0; - - if (size < DDC_EDID_BLOCK_SIZE) - return 0; - - if (dal_ddc_service_is_in_aux_transaction_mode(ddc)) { - size_retrieved = - aux_read_edid_block(ddc, address, index, buf); - } else { - size_retrieved = - i2c_read_edid_block(ddc, address, index, buf); - } - - return size_retrieved; -} - -#define DDC_DPCD_EDID_CHECKSUM_WRITE_ADDRESS 0x261 -#define DDC_TEST_ACK_ADDRESS 0x260 -#define DDC_DPCD_EDID_TEST_ACK 0x04 -#define DDC_DPCD_EDID_TEST_MASK 0x04 -#define DDC_DPCD_TEST_REQUEST_ADDRESS 0x218 - -/* AG TODO GO throug DM callback here like for DPCD */ - -static void write_dp_edid_checksum( - struct ddc_service *ddc, - uint8_t checksum) -{ - uint8_t dpcd_data; - - dal_ddc_service_read_dpcd_data( - ddc, - DDC_DPCD_TEST_REQUEST_ADDRESS, - &dpcd_data, - 1); - - if (dpcd_data & DDC_DPCD_EDID_TEST_MASK) { - - dal_ddc_service_write_dpcd_data( - ddc, - DDC_DPCD_EDID_CHECKSUM_WRITE_ADDRESS, - &checksum, - 1); - - dpcd_data = DDC_DPCD_EDID_TEST_ACK; - - dal_ddc_service_write_dpcd_data( - ddc, - DDC_TEST_ACK_ADDRESS, - &dpcd_data, - 1); - } -} - -uint32_t dal_ddc_service_edid_query(struct ddc_service *ddc) -{ - uint32_t bytes_read = 0; - uint32_t ext_cnt = 0; - - uint8_t address; - uint32_t i; - - for (address = DDC_EDID_ADDRESS_START; - address <= DDC_EDID_ADDRESS_END; ++address) { - - bytes_read = query_edid_block( - ddc, - address, - 0, - ddc->edid_buf, - sizeof(ddc->edid_buf) - bytes_read); - - if (bytes_read != DDC_EDID_BLOCK_SIZE) - continue; - - /* get the number of ext blocks*/ - ext_cnt = ddc->edid_buf[DDC_EDID_EXT_COUNT_OFFSET]; - - /* EDID 2.0, need to read 1 more block because EDID2.0 is - * 256 byte in size*/ - if (ddc->edid_buf[DDC_EDID_20_SIGNATURE_OFFSET] == - DDC_EDID_20_SIGNATURE) - ext_cnt = 1; - - for (i = 0; i < ext_cnt; i++) { - /* read additional ext blocks accordingly */ - bytes_read += query_edid_block( - ddc, - address, - i+1, - &ddc->edid_buf[bytes_read], - sizeof(ddc->edid_buf) - bytes_read); - } - - /*this is special code path for DP compliance*/ - if (DDC_TRANSACTION_TYPE_I2C_OVER_AUX == ddc->transaction_type) - write_dp_edid_checksum( - ddc, - ddc->edid_buf[(ext_cnt * DDC_EDID_BLOCK_SIZE) + - DDC_EDID1X_CHECKSUM_OFFSET]); - - /*remembers the address where we fetch the EDID from - * for later signature check use */ - ddc->address = address; - - break;/* already read edid, done*/ - } - - ddc->edid_buf_len = bytes_read; - return bytes_read; -} - -uint32_t dal_ddc_service_get_edid_buf_len(struct ddc_service *ddc) -{ - return ddc->edid_buf_len; -} - -void dal_ddc_service_get_edid_buf(struct ddc_service *ddc, uint8_t *edid_buf) -{ - memmove(edid_buf, - ddc->edid_buf, ddc->edid_buf_len); -} - void dal_ddc_service_i2c_query_dp_dual_mode_adaptor( struct ddc_service *ddc, struct display_sink_capability *sink_cap) @@ -960,12 +635,14 @@ bool dal_ddc_service_query_ddc_data( enum ddc_result dal_ddc_service_read_dpcd_data( struct ddc_service *ddc, + bool i2c, + enum i2c_mot_mode mot, uint32_t address, uint8_t *data, uint32_t len) { struct aux_payload read_payload = { - .i2c_over_aux = false, + .i2c_over_aux = i2c, .write = false, .address = address, .length = len, @@ -976,6 +653,7 @@ enum ddc_result dal_ddc_service_read_dpcd_data( .number_of_payloads = 1, .defer_delay = 0, .max_defer_write_retry = 0, + .mot = mot }; if (len > DEFAULT_AUX_MAX_DATA_SIZE) { @@ -994,12 +672,14 @@ enum ddc_result dal_ddc_service_read_dpcd_data( enum ddc_result dal_ddc_service_write_dpcd_data( struct ddc_service *ddc, + bool i2c, + enum i2c_mot_mode mot, uint32_t address, const uint8_t *data, uint32_t len) { struct aux_payload write_payload = { - .i2c_over_aux = false, + .i2c_over_aux = i2c, .write = true, .address = address, .length = len, @@ -1010,6 +690,7 @@ enum ddc_result dal_ddc_service_write_dpcd_data( .number_of_payloads = 1, .defer_delay = 0, .max_defer_write_retry = 0, + .mot = mot }; if (len > DEFAULT_AUX_MAX_DATA_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 b8c40e8bee5a..9f12ba87827a 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 @@ -1481,22 +1481,25 @@ static bool handle_hpd_irq_psr_sink(const struct core_link *link) if (link->public.psr_caps.psr_version == 0) return false; - dal_ddc_service_read_dpcd_data( - link->ddc, - 368 /*DpcdAddress_PSR_Enable_Cfg*/, - &psr_configuration.raw, - sizeof(psr_configuration.raw)); + dm_helpers_dp_read_dpcd( + link->ctx, + &link->public, + 368,/*DpcdAddress_PSR_Enable_Cfg*/ + &psr_configuration.raw, + sizeof(psr_configuration.raw)); + if (psr_configuration.bits.ENABLE) { unsigned char dpcdbuf[3] = {0}; union psr_error_status psr_error_status; union psr_sink_psr_status psr_sink_psr_status; - dal_ddc_service_read_dpcd_data( - link->ddc, - 0x2006 /*DpcdAddress_PSR_Error_Status*/, - (unsigned char *) dpcdbuf, - sizeof(dpcdbuf)); + dm_helpers_dp_read_dpcd( + link->ctx, + &link->public, + 0x2006, /*DpcdAddress_PSR_Error_Status*/ + (unsigned char *) dpcdbuf, + sizeof(dpcdbuf)); /*DPCD 2006h ERROR STATUS*/ psr_error_status.raw = dpcdbuf[0]; @@ -1506,9 +1509,10 @@ static bool handle_hpd_irq_psr_sink(const struct core_link *link) if (psr_error_status.bits.LINK_CRC_ERROR || psr_error_status.bits.RFB_STORAGE_ERROR) { /* Acknowledge and clear error bits */ - dal_ddc_service_write_dpcd_data( - link->ddc, - 8198 /*DpcdAddress_PSR_Error_Status*/, + dm_helpers_dp_write_dpcd( + link->ctx, + &link->public, + 8198,/*DpcdAddress_PSR_Error_Status*/ &psr_error_status.raw, sizeof(psr_error_status.raw)); diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index d2960552c78e..a27a6aba0df1 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -594,6 +594,7 @@ struct dc_link { union compliance_test_state compliance_test_state; void *priv; + bool aux_mode; }; struct dpcd_caps { @@ -788,20 +789,36 @@ const struct ddc_service *dc_get_ddc_at_index( * DPCD access interfaces */ -bool dc_read_dpcd( +bool dc_read_aux_dpcd( struct dc *dc, uint32_t link_index, uint32_t address, uint8_t *data, uint32_t size); -bool dc_write_dpcd( +bool dc_write_aux_dpcd( struct dc *dc, uint32_t link_index, uint32_t address, const uint8_t *data, uint32_t size); +bool dc_read_aux_i2c( + struct dc *dc, + uint32_t link_index, + enum i2c_mot_mode mot, + uint32_t address, + uint8_t *data, + uint32_t size); + +bool dc_write_aux_i2c( + struct dc *dc, + uint32_t link_index, + enum i2c_mot_mode mot, + uint32_t address, + const uint8_t *data, + uint32_t size); + bool dc_query_ddc_data( struct dc *dc, uint32_t link_index, diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 242dd7b3b6b1..e0436e317341 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -489,4 +489,10 @@ struct psr_caps { unsigned int psr_sdp_transmit_line_num_deadline; }; +enum i2c_mot_mode { + I2C_MOT_UNDEF, + I2C_MOT_TRUE, + I2C_MOT_FALSE +}; + #endif /* DC_TYPES_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dm_helpers.h b/drivers/gpu/drm/amd/display/dc/dm_helpers.h index d6c52d31f0f0..c15a25ce8049 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_helpers.h +++ b/drivers/gpu/drm/amd/display/dc/dm_helpers.h @@ -98,4 +98,14 @@ bool dm_helpers_submit_i2c( struct i2c_command *cmd); + + + + +enum dc_edid_status dm_helpers_read_local_edid( + struct dc_context *ctx, + struct dc_link *link, + struct dc_sink *sink); + + #endif /* __DM_HELPERS__ */ diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c index bd84b932aaae..0743265e933c 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c @@ -185,6 +185,7 @@ bool dal_i2caux_submit_aux_command( struct aux_engine *engine; uint8_t index_of_payload = 0; bool result; + bool mot; if (!ddc) { BREAK_TO_DEBUGGER(); @@ -207,12 +208,14 @@ bool dal_i2caux_submit_aux_command( result = true; while (index_of_payload < cmd->number_of_payloads) { - bool mot = (index_of_payload != cmd->number_of_payloads - 1); - struct aux_payload *payload = cmd->payloads + index_of_payload; - struct i2caux_transaction_request request = { 0 }; + if (cmd->mot == I2C_MOT_UNDEF) + mot = (index_of_payload != cmd->number_of_payloads - 1); + else + mot = (cmd->mot == I2C_MOT_TRUE); + request.operation = payload->write ? I2CAUX_TRANSACTION_WRITE : I2CAUX_TRANSACTION_READ; diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h index 830fc3d039c9..9c2f670c3dc3 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h @@ -31,6 +31,23 @@ #define EDID_SEGMENT_SIZE 256 +/* Address range from 0x00 to 0x1F.*/ +#define DP_ADAPTOR_TYPE2_SIZE 0x20 +#define DP_ADAPTOR_TYPE2_REG_ID 0x10 +#define DP_ADAPTOR_TYPE2_REG_MAX_TMDS_CLK 0x1D +/* Identifies adaptor as Dual-mode adaptor */ +#define DP_ADAPTOR_TYPE2_ID 0xA0 +/* MHz*/ +#define DP_ADAPTOR_TYPE2_MAX_TMDS_CLK 600 +/* MHz*/ +#define DP_ADAPTOR_TYPE2_MIN_TMDS_CLK 25 +/* kHZ*/ +#define DP_ADAPTOR_DVI_MAX_TMDS_CLK 165000 +/* kHZ*/ +#define DP_ADAPTOR_HDMI_SAFE_MAX_TMDS_CLK 165000 + +#define DDC_I2C_COMMAND_ENGINE I2C_COMMAND_ENGINE_SW + struct ddc_service; struct graphics_object_id; enum ddc_result; @@ -83,12 +100,6 @@ void dal_ddc_service_set_transaction_type( bool dal_ddc_service_is_in_aux_transaction_mode(struct ddc_service *ddc); -uint32_t dal_ddc_service_edid_query(struct ddc_service *ddc); - -uint32_t dal_ddc_service_get_edid_buf_len(struct ddc_service *ddc); - -void dal_ddc_service_get_edid_buf(struct ddc_service *ddc, uint8_t *edid_buf); - void dal_ddc_service_i2c_query_dp_dual_mode_adaptor( struct ddc_service *ddc, struct display_sink_capability *sink_cap); @@ -103,12 +114,16 @@ bool dal_ddc_service_query_ddc_data( enum ddc_result dal_ddc_service_read_dpcd_data( struct ddc_service *ddc, + bool i2c, + enum i2c_mot_mode mot, uint32_t address, uint8_t *data, uint32_t len); enum ddc_result dal_ddc_service_write_dpcd_data( struct ddc_service *ddc, + bool i2c, + enum i2c_mot_mode mot, uint32_t address, const uint8_t *data, uint32_t len); @@ -130,16 +145,7 @@ void dal_ddc_service_set_ddc_pin( struct ddc *dal_ddc_service_get_ddc_pin(struct ddc_service *ddc_service); -enum ddc_result dal_ddc_service_read_dpcd_data( - struct ddc_service *ddc, - uint32_t address, - uint8_t *data, - uint32_t len); -enum ddc_result dal_ddc_service_write_dpcd_data( - struct ddc_service *ddc, - uint32_t address, - const uint8_t *data, - uint32_t len); +uint32_t get_defer_delay(struct ddc_service *ddc); #endif /* __DAL_DDC_SERVICE_H__ */ diff --git a/drivers/gpu/drm/amd/display/include/ddc_service_types.h b/drivers/gpu/drm/amd/display/include/ddc_service_types.h index effe03b8f418..0ff2a899b8f7 100644 --- a/drivers/gpu/drm/amd/display/include/ddc_service_types.h +++ b/drivers/gpu/drm/amd/display/include/ddc_service_types.h @@ -115,34 +115,6 @@ struct av_sync_data { uint8_t aud_del_ins3;/* DPCD 0002Dh */ }; -/** EDID retrieval related constants, also used by MstMgr **/ - -#define DDC_EDID_SEGMENT_SIZE 256 -#define DDC_EDID_BLOCK_SIZE 128 -#define DDC_EDID_BLOCKS_PER_SEGMENT \ - (DDC_EDID_SEGMENT_SIZE / DDC_EDID_BLOCK_SIZE) - -#define DDC_EDID_EXT_COUNT_OFFSET 0x7E - -#define DDC_EDID_ADDRESS_START 0x50 -#define DDC_EDID_ADDRESS_END 0x52 -#define DDC_EDID_SEGMENT_ADDRESS 0x30 - -/* signatures for Edid 1x */ -#define DDC_EDID1X_VENDORID_SIGNATURE_OFFSET 8 -#define DDC_EDID1X_VENDORID_SIGNATURE_LEN 4 -#define DDC_EDID1X_EXT_CNT_AND_CHECKSUM_OFFSET 126 -#define DDC_EDID1X_EXT_CNT_AND_CHECKSUM_LEN 2 -#define DDC_EDID1X_CHECKSUM_OFFSET 127 -/* signatures for Edid 20*/ -#define DDC_EDID_20_SIGNATURE_OFFSET 0 -#define DDC_EDID_20_SIGNATURE 0x20 - -#define DDC_EDID20_VENDORID_SIGNATURE_OFFSET 1 -#define DDC_EDID20_VENDORID_SIGNATURE_LEN 4 -#define DDC_EDID20_CHECKSUM_OFFSET 255 -#define DDC_EDID20_CHECKSUM_LEN 1 - /*DP to VGA converter*/ static const uint8_t DP_VGA_CONVERTER_ID_1[] = "mVGAa"; /*DP to Dual link DVI converter*/ diff --git a/drivers/gpu/drm/amd/display/include/i2caux_interface.h b/drivers/gpu/drm/amd/display/include/i2caux_interface.h index d2ec04d1c592..13a3c82d118f 100644 --- a/drivers/gpu/drm/amd/display/include/i2caux_interface.h +++ b/drivers/gpu/drm/amd/display/include/i2caux_interface.h @@ -26,6 +26,7 @@ #ifndef __DAL_I2CAUX_INTERFACE_H__ #define __DAL_I2CAUX_INTERFACE_H__ +#include "dc_types.h" #include "gpio_service_interface.h" @@ -54,6 +55,8 @@ struct aux_command { /* zero means "use default value" */ uint32_t max_defer_write_retry; + + enum i2c_mot_mode mot; }; union aux_config { -- cgit From 6848e9896b9c9a26a44ac6764ca4bb7351ae573e Mon Sep 17 00:00:00 2001 From: Amy Zhang Date: Thu, 30 Mar 2017 11:39:47 -0400 Subject: drm/amd/display: PSR Aux Channel and Static Screen Support Fix - Correct the aux channel selection according to DAL3 Signed-off-by: Amy Zhang Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 0f825f6326ab..b878fb9697d7 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1482,8 +1482,6 @@ bool dc_link_setup_psr(const struct dc_link *dc_link, sizeof(psr_configuration.raw)); psr_context.channel = link->ddc->ddc_pin->hw_info.ddc_channel; - if (psr_context.channel == 0) - psr_context.channel = 1; psr_context.transmitterId = link->link_enc->transmitter; psr_context.engineId = link->link_enc->preferred_engine; -- cgit From 28f72454320d2084cc082c8509135bdfd4012c10 Mon Sep 17 00:00:00 2001 From: Jordan Lazare Date: Thu, 30 Mar 2017 13:08:34 -0400 Subject: drm/amd/display: Fill in vrefresh and min_vblank_time for dce8/dce10 PPLib is now calling into DC to get vrefresh and min_vblank_time, but since full bandwidth calcs are missing for those generations, the pplib structures were never being filled. This change fills the currently required fields to prevent screen corruption. Signed-off-by: Jordan Lazare Acked-by: Harry Wentland Reviewed-by: Jordan Lazare Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dce100/dce100_hw_sequencer.c | 21 +++++++++++++++++++++ .../drm/amd/display/dc/dce100/dce100_hw_sequencer.h | 5 +++++ .../drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 8 ++++---- .../drm/amd/display/dc/dce110/dce110_hw_sequencer.h | 8 ++++++++ .../drm/amd/display/dc/dce80/dce80_hw_sequencer.c | 2 ++ 5 files changed, 40 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c index bd8e19f1038b..f11044e0245c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c @@ -104,6 +104,26 @@ static bool dce100_enable_display_power_gating( return false; } +void dce100_pplib_apply_display_requirements( + struct core_dc *dc, + struct validate_context *context) +{ + struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg; + + pp_display_cfg->avail_mclk_switch_time_us = + dce110_get_min_vblank_time_us(context); + + dce110_fill_display_configs(context, pp_display_cfg); + + if (memcmp(&dc->prev_display_config, pp_display_cfg, sizeof( + struct dm_pp_display_configuration)) != 0) + dm_pp_apply_display_requirements(dc->ctx, pp_display_cfg); + + dc->prev_display_config = *pp_display_cfg; +} + + + static void set_displaymarks( const struct core_dc *dc, struct validate_context *context) { @@ -116,6 +136,7 @@ static void set_bandwidth( bool decrease_allowed) { dc->hwss.set_displaymarks(dc, context); + dce100_pplib_apply_display_requirements(dc, context); } diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h index cf497ea605c8..f51d04a66a49 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h @@ -29,8 +29,13 @@ #include "core_types.h" struct core_dc; +struct validate_context; bool dce100_hw_sequencer_construct(struct core_dc *dc); +void dce100_pplib_apply_display_requirements( + struct core_dc *dc, + struct validate_context *context); + #endif /* __DC_HWSS_DCE100_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 2a3a39e31717..839c34409c63 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -2097,7 +2097,7 @@ static void init_hw(struct core_dc *dc) } } -static void fill_display_configs( +void dce110_fill_display_configs( const struct validate_context *context, struct dm_pp_display_configuration *pp_display_cfg) { @@ -2146,7 +2146,7 @@ static void fill_display_configs( pp_display_cfg->display_count = num_cfgs; } -static uint32_t get_min_vblank_time_us(const struct validate_context *context) +uint32_t dce110_get_min_vblank_time_us(const struct validate_context *context) { uint8_t j; uint32_t min_vertical_blank_time = -1; @@ -2224,13 +2224,13 @@ static void pplib_apply_display_requirements( = context->bw_results.required_sclk_deep_sleep; pp_display_cfg->avail_mclk_switch_time_us = - get_min_vblank_time_us(context); + dce110_get_min_vblank_time_us(context); /* TODO: dce11.2*/ pp_display_cfg->avail_mclk_switch_time_in_disp_active_us = 0; pp_display_cfg->disp_clk_khz = context->dispclk_khz; - fill_display_configs(context, pp_display_cfg); + dce110_fill_display_configs(context, pp_display_cfg); /* TODO: is this still applicable?*/ if (pp_display_cfg->display_count == 1) { diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h index a6b4d0d2429f..52462c17b2e9 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h @@ -30,6 +30,8 @@ #define GAMMA_HW_POINTS_NUM 256 struct core_dc; +struct validate_context; +struct dm_pp_display_configuration; bool dce110_hw_sequencer_construct(struct core_dc *dc); @@ -58,5 +60,11 @@ void dce110_power_down(struct core_dc *dc); void dce110_update_pending_status(struct pipe_ctx *pipe_ctx); +void dce110_fill_display_configs( + const struct validate_context *context, + struct dm_pp_display_configuration *pp_display_cfg); + +uint32_t dce110_get_min_vblank_time_us(const struct validate_context *context); + #endif /* __DC_HWSS_DCE110_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c index 85a54d963f8d..9d4e7d8b836e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c @@ -31,6 +31,7 @@ #include "dce/dce_hwseq.h" #include "dce110/dce110_hw_sequencer.h" +#include "dce100/dce100_hw_sequencer.h" /* include DCE8 register header files */ #include "dce/dce_8_0_d.h" @@ -118,6 +119,7 @@ static void set_bandwidth( bool decrease_allowed) { dc->hwss.set_displaymarks(dc, context); + dce100_pplib_apply_display_requirements(dc, context); } -- cgit From dd3f348f0013f2cb2508f72adb35285a34b2baf7 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Fri, 31 Mar 2017 13:53:42 -0400 Subject: drm/amd/display: Ignore visible flag when check surface update type. Signed-off-by: Yongqiang Sun Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 40a800155fe6..9a3507e743cf 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1046,10 +1046,10 @@ static enum surface_update_type get_plane_info_update_type( temp_plane_info.rotation = u->surface->rotation; temp_plane_info.stereo_format = u->surface->stereo_format; temp_plane_info.tiling_info = u->surface->tiling_info; - temp_plane_info.visible = u->surface->visible; /* Special Validation parameters */ temp_plane_info.format = u->plane_info->format; + temp_plane_info.visible = u->plane_info->visible; if (memcmp(u->plane_info, &temp_plane_info, sizeof(struct dc_plane_info)) != 0) -- cgit From 7160c74cd00bc0a5f143c24096e1a45c51f3d202 Mon Sep 17 00:00:00 2001 From: Jordan Lazare Date: Fri, 31 Mar 2017 17:14:20 -0400 Subject: drm/amd/display: Log clock source in error condition Signed-off-by: Jordan Lazare Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c index 17cdd70a2c27..34c18712970c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c @@ -187,6 +187,7 @@ void dce_crtc_switch_to_clk_src(struct dce_hwseq *hws, REG_UPDATE(PHYPLL_PIXEL_RATE_CNTL[tg_inst], PIXEL_RATE_PLL_SOURCE, 1); } else { - DC_ERR("unknown clock source"); + DC_ERR("Unknown clock source. clk_src id: %d, TG_inst: %d", + clk_src->id, tg_inst); } } -- cgit From 9faa423716b17b0c9ba92fd12737968de6918d88 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Fri, 31 Mar 2017 14:15:31 -0400 Subject: drm/amd/display: Fix s3 hang on resume. Avoid enabling CRTC_VERTICAL_INTERRUPT0 twice on resume. It's enabled once from within manage_dm_interrupts in mode set and another explicitly from amdgpu_dm_irq_resume_late. Seems it lead to CRTC hang. Signed-off-by: Andrey Grodzovsky Acked-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c | 16 +++++++++++----- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h | 2 +- 3 files changed, 13 insertions(+), 7 deletions(-) (limited to 'drivers/gpu') 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 1077af91884f..30148b4eabae 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -575,7 +575,7 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev ) ret = drm_atomic_helper_resume(ddev, adev->dm.cached_state); - amdgpu_dm_irq_resume(adev); + amdgpu_dm_irq_resume_late(adev); return ret; } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c index 682e9c3ad8e5..4aee146a848f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c @@ -504,8 +504,11 @@ int amdgpu_dm_irq_suspend( DRM_DEBUG_KMS("DM_IRQ: suspend\n"); - /* disable HW interrupt */ - for (src = DC_IRQ_SOURCE_HPD1; src < DAL_IRQ_SOURCES_NUMBER; src++) { + /** + * Disable HW interrupt for HPD and HPDRX only since FLIP and VBLANK + * will be disabled from manage_dm_interrupts on disable CRTC. + */ + for (src = DC_IRQ_SOURCE_HPD1; src < DC_IRQ_SOURCE_HPD6RX; src++) { hnd_list_l = &adev->dm.irq_handler_list_low_tab[src].head; hnd_list_h = &adev->dm.irq_handler_list_high_tab[src]; if (!list_empty(hnd_list_l) || !list_empty(hnd_list_h)) @@ -544,7 +547,7 @@ int amdgpu_dm_irq_resume_early(struct amdgpu_device *adev) return 0; } -int amdgpu_dm_irq_resume(struct amdgpu_device *adev) +int amdgpu_dm_irq_resume_late(struct amdgpu_device *adev) { int src; struct list_head *hnd_list_h, *hnd_list_l; @@ -554,8 +557,11 @@ int amdgpu_dm_irq_resume(struct amdgpu_device *adev) DRM_DEBUG_KMS("DM_IRQ: resume\n"); - /* re-enable HW interrupt */ - for (src = DC_IRQ_SOURCE_HPD1; src < DAL_IRQ_SOURCES_NUMBER; src++) { + /** + * Renable HW interrupt for HPD and only since FLIP and VBLANK + * will be enabled from manage_dm_interrupts on enable CRTC. + */ + for (src = DC_IRQ_SOURCE_HPD1; src < DC_IRQ_SOURCE_HPD6; src++) { hnd_list_l = &adev->dm.irq_handler_list_low_tab[src].head; hnd_list_h = &adev->dm.irq_handler_list_high_tab[src]; if (!list_empty(hnd_list_l) || !list_empty(hnd_list_h)) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h index 9339861c8897..9d3007634266 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h @@ -117,6 +117,6 @@ int amdgpu_dm_irq_suspend(struct amdgpu_device *adev); * */ int amdgpu_dm_irq_resume_early(struct amdgpu_device *adev); -int amdgpu_dm_irq_resume(struct amdgpu_device *adev); +int amdgpu_dm_irq_resume_late(struct amdgpu_device *adev); #endif /* __AMDGPU_DM_IRQ_H__ */ -- cgit From 6f43fd6297c478995b6a9e61482272137ec36260 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 15 Jun 2017 16:25:11 -0400 Subject: drm/amd/display: fix nullptr on vega initialization Signed-off-by: Jordan Lazare Reviewed-by: Tony Cheng Reviewed-by: Roman Li Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu') 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 30148b4eabae..a9b4eb0099ac 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1427,6 +1427,7 @@ static int dm_early_init(void *handle) adev->mode_info.num_crtc = 6; adev->mode_info.num_hpd = 6; adev->mode_info.num_dig = 6; + adev->mode_info.plane_type = dm_surfaces_type_default; break; default: DRM_ERROR("Usupported ASIC type: 0x%X\n", adev->asic_type); -- cgit From 7df498fa4c241610ee22cfcfa648628d2ef908fd Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 10 Apr 2017 15:37:32 -0400 Subject: drm/amd/display: Allow planes on all crtcs 4.9 kernel will always add the assigned crtc to possible_crtcs on a plane. This is no longer the case on newer kernels. Make sure we allow any plane on any crtc. Signed-off-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') 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 a9b4eb0099ac..1b39bf9b4278 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1090,7 +1090,7 @@ int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) goto fail_free_planes; } mode_info->planes[i]->plane_type = mode_info->plane_type[i]; - if (amdgpu_dm_plane_init(dm, mode_info->planes[i], 1)) { + if (amdgpu_dm_plane_init(dm, mode_info->planes[i], 0xff)) { DRM_ERROR("KMS: Failed to initialize plane\n"); goto fail_free_planes; } -- cgit From 664a2ed115f62422475a783e6db453483a316a80 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Fri, 27 Jan 2017 10:55:20 -0500 Subject: drm/amd/display: Fallback on legacy properties in atomic_get_properties We still rely on legacy properties. Fallback on legacy properties until we get to pull these into some atomic state. Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 40 +++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 345df1b6d82b..2c48408849d8 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -1246,6 +1246,43 @@ struct drm_connector_state *amdgpu_dm_connector_atomic_duplicate_state( return NULL; } + +/** + * amdgpu_dm_atomic_get_property - fetch connector property value + * @connector: connector to fetch property for + * @state: state containing the property value + * @property: property to look up + * @val: pointer to write property value into + * + * The DRM core does not store shadow copies of properties for + * atomic-capable drivers. This entrypoint is used to fetch + * the current value of a driver-specific connector property. + */ +int amdgpu_dm_connector_atomic_get_property(struct drm_connector *connector, + const struct drm_connector_state *state, + struct drm_property *property, + uint64_t *val) +{ + int i; + + /* + * TODO: Get properties from atomic state or objs. Until it's ready, + * continue to look up all property values in the DRM's shadow copy + * in obj->properties->values[]. + * + * When the crtc/connector state work matures, this function should + * be updated to read the values out of the state structure instead. + */ + for (i = 0; i < connector->base.properties->count; i++) { + if (connector->base.properties->properties[i] == property) { + *val = connector->base.properties->values[i]; + return 0; + } + } + + return -EINVAL; +} + static const struct drm_connector_funcs amdgpu_dm_connector_funcs = { .reset = amdgpu_dm_connector_funcs_reset, .detect = amdgpu_dm_connector_detect, @@ -1253,7 +1290,8 @@ static const struct drm_connector_funcs amdgpu_dm_connector_funcs = { .destroy = amdgpu_dm_connector_destroy, .atomic_duplicate_state = amdgpu_dm_connector_atomic_duplicate_state, .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, - .atomic_set_property = amdgpu_dm_connector_atomic_set_property + .atomic_set_property = amdgpu_dm_connector_atomic_set_property, + .atomic_get_property = amdgpu_dm_connector_atomic_get_property, }; static struct drm_encoder *best_encoder(struct drm_connector *connector) -- cgit From 32a1892a86a8f40c6f24807a9a0da31a322e4874 Mon Sep 17 00:00:00 2001 From: Pratik Vishwakarma Date: Thu, 6 Apr 2017 13:18:20 +0530 Subject: drm/amd/display: get_atomic_property missing for drm_connector_funcs DRM_IOCTL_MODE_GETCONNECTOR fails with EINVAL on enabling DRIVER_ATOMIC With this DRM_IOCTL_MODE_GETCONNECTOR returns all the connector properties. freesync_property and freesync_capable_property return 0 currently. TESTS(On Chromium OS on Stoney Only) * Builds without compilation errors. * 'atomictest' proceeds after applying patch and fails with vblank event timed out. * Chromium OS ui comes up. Signed-off-by: Pratik Vishwakarma Reviewed-by: Tony Cheng Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 81 ++++++++++++---------- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.h | 6 ++ 2 files changed, 49 insertions(+), 38 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 2c48408849d8..ba1f3d40771a 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -1184,6 +1184,48 @@ int amdgpu_dm_connector_atomic_set_property( return ret; } +int amdgpu_dm_connector_atomic_get_property( + struct drm_connector *connector, + const struct drm_connector_state *state, + struct drm_property *property, + uint64_t *val) +{ + struct drm_device *dev = connector->dev; + struct amdgpu_device *adev = dev->dev_private; + struct dm_connector_state *dm_state = + to_dm_connector_state(state); + int ret = -EINVAL; + + if (property == dev->mode_config.scaling_mode_property) { + switch (dm_state->scaling) { + case RMX_CENTER: + *val = DRM_MODE_SCALE_CENTER; + break; + case RMX_ASPECT: + *val = DRM_MODE_SCALE_ASPECT; + break; + case RMX_FULL: + *val = DRM_MODE_SCALE_FULLSCREEN; + break; + case RMX_OFF: + default: + *val = DRM_MODE_SCALE_NONE; + break; + } + ret = 0; + } else if (property == adev->mode_info.underscan_hborder_property) { + *val = dm_state->underscan_hborder; + ret = 0; + } else if (property == adev->mode_info.underscan_vborder_property) { + *val = dm_state->underscan_vborder; + ret = 0; + } else if (property == adev->mode_info.underscan_property) { + *val = dm_state->underscan_enable; + ret = 0; + } + return ret; +} + void amdgpu_dm_connector_destroy(struct drm_connector *connector) { struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); @@ -1246,43 +1288,6 @@ struct drm_connector_state *amdgpu_dm_connector_atomic_duplicate_state( return NULL; } - -/** - * amdgpu_dm_atomic_get_property - fetch connector property value - * @connector: connector to fetch property for - * @state: state containing the property value - * @property: property to look up - * @val: pointer to write property value into - * - * The DRM core does not store shadow copies of properties for - * atomic-capable drivers. This entrypoint is used to fetch - * the current value of a driver-specific connector property. - */ -int amdgpu_dm_connector_atomic_get_property(struct drm_connector *connector, - const struct drm_connector_state *state, - struct drm_property *property, - uint64_t *val) -{ - int i; - - /* - * TODO: Get properties from atomic state or objs. Until it's ready, - * continue to look up all property values in the DRM's shadow copy - * in obj->properties->values[]. - * - * When the crtc/connector state work matures, this function should - * be updated to read the values out of the state structure instead. - */ - for (i = 0; i < connector->base.properties->count; i++) { - if (connector->base.properties->properties[i] == property) { - *val = connector->base.properties->values[i]; - return 0; - } - } - - return -EINVAL; -} - static const struct drm_connector_funcs amdgpu_dm_connector_funcs = { .reset = amdgpu_dm_connector_funcs_reset, .detect = amdgpu_dm_connector_detect, @@ -1291,7 +1296,7 @@ static const struct drm_connector_funcs amdgpu_dm_connector_funcs = { .atomic_duplicate_state = amdgpu_dm_connector_atomic_duplicate_state, .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, .atomic_set_property = amdgpu_dm_connector_atomic_set_property, - .atomic_get_property = amdgpu_dm_connector_atomic_get_property, + .atomic_get_property = amdgpu_dm_connector_atomic_get_property }; static struct drm_encoder *best_encoder(struct drm_connector *connector) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h index ab6d51dbbf4b..b69c86826b1a 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h @@ -71,6 +71,12 @@ int amdgpu_dm_connector_atomic_set_property( struct drm_property *property, uint64_t val); +int amdgpu_dm_connector_atomic_get_property( + struct drm_connector *connector, + const struct drm_connector_state *state, + struct drm_property *property, + uint64_t *val); + int amdgpu_dm_get_encoder_crtc_mask(struct amdgpu_device *adev); void amdgpu_dm_connector_init_helper( -- cgit From 753c66c91b5430816eedb67138017fd4e2143d52 Mon Sep 17 00:00:00 2001 From: Mario Kleiner Date: Mon, 24 Apr 2017 11:46:44 +0200 Subject: drm/amd/display: Fix race between vblank irq and pageflip irq. (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since DC now uses CRTC_VERTICAL_INTERRUPT0 as VBLANK irq trigger and vblank interrupts actually happen earliest at start of vblank, instead of a bit before vblank, we no longer need some of the fudging logic to deal with too early vblank irq handling (grep for lb_vblank_lead_lines). This itself fixes a pageflip scheduling bug in DC, caused by uninitialized use of lb_vblank_lead_lines, with a wrong startup value of 0. Thanks to the new vblank irq trigger this value of zero is now actually correct for DC :). A new problem is that vblank irq's race against pflip irq's, and as both can fire at first line of vblank, it is no longer guaranteed that vblank irq handling (therefore -> drm_handle_vblank() -> drm_update_vblank_count()) executes before pflip irq handling for a given vblank interval when a pageflip completes. Therefore the vblank count and timestamps emitted to user-space as part of the pageflip completion event will be often stale and cause new timestamping and swap scheduling errors in user-space. This was observed with large frequency on R9 380 Tonga Pro. Fix this by enforcing a vblank count+timestamp update right before emitting the pageflip completion event from the pflip irq handler. The logic in core drm_update_vblank_count() makes sure that no redundant or conflicting updates happen, iow. the call turns into a no-op if it wasn't needed for that vblank, burning a few microseconds of cpu time though. Successfully tested on AMD R9 380 "Tonga Pro" (VI/DCE 10) with DC enabled on the current DC staging branch. Independent measurement of pageflip completion timing with special hardware measurement equipment now confirms correct pageflip timestamps and counts in the pageflip completion events. v2: Review comments by Michel, drop outdated paragraph about problem already fixed in 2nd patch of the series. Add acked/r-b by Harry and Michel. Signed-off-by: Mario Kleiner Acked-by: Harry Wentland (v1) Reviewed-by: Michel Dänzer Cc: Andrey Grodzovsky Cc: Alex Deucher Cc: Michel Dänzer Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpu') 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 1b39bf9b4278..93f10bc772c4 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -202,6 +202,9 @@ static void dm_pflip_high_irq(void *interrupt_params) if (amdgpu_crtc->event && amdgpu_crtc->event->event.base.type == DRM_EVENT_FLIP_COMPLETE) { + /* Update to correct count/ts if racing with vblank irq */ + drm_crtc_accurate_vblank_count(&amdgpu_crtc->base); + drm_crtc_send_vblank_event(&amdgpu_crtc->base, amdgpu_crtc->event); /* page flip completed. clean up */ amdgpu_crtc->event = NULL; -- cgit From 00d7930c5189a439ea4f3c1af071beb3134856d6 Mon Sep 17 00:00:00 2001 From: Mario Kleiner Date: Mon, 24 Apr 2017 18:54:20 +0200 Subject: drm/amd/display: Prevent premature pageflip when comitting in vblank. (v3) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make sure we do not program a hw pageflip inside vblank 'n' iff the atomic flip is comitted while inside the same vblank 'n'. We must defer such a flip by one refresh cycle to vblank 'n+1', unless this is a DRM_MODE_PAGE_FLIP_ASYNC async pageflip, which must always execute as soon as possible. Without this, pageflips programmed via X11 GLX_OML_sync_control extensions glXSwapBuffersMscOML(..., target_msc, ...); call and/or via DRI3/Present PresentPixmap(..., target_msc, ...); request will complete one vblank too early whenever target_msc > current_msc + 1, ie. more than 1 vblank in the future. In such a case, the call of the pageflip ioctl() would be triggered by a queued drmWaitVblank() vblank event, which itself gets dispatched inside the vblank one frame before the target_msc vblank. Testing with this patch does no longer show any problems with OML_sync_control swap scheduling or flip completion timestamps. Tested on R9 380 Tonga. v2: Add acked/r-b by Harry and Michel. v3: Feedback from Andrey: Must not wait an extra frame for DRM_MODE_PAGE_FLIP_ASYNC flips. Signed-off-by: Mario Kleiner Acked-by: Harry Wentland (v1) Reviewed-by: Michel Dänzer Reviewed-by: Andrey Grodzovsky Cc: Harry Wentland Cc: Alex Deucher Cc: Michel Dänzer Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index ba1f3d40771a..4b0fc6b56969 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2305,6 +2305,9 @@ static void amdgpu_dm_do_flip( struct amdgpu_device *adev = crtc->dev->dev_private; bool async_flip = (acrtc->flip_flags & DRM_MODE_PAGE_FLIP_ASYNC) != 0; + /* Prepare wait for target vblank early - before the fence-waits */ + target_vblank = target - drm_crtc_vblank_count(crtc) + + amdgpu_get_vblank_counter_kms(crtc->dev, acrtc->crtc_id); /*TODO This might fail and hence better not used, wait * explicitly on fences instead @@ -2323,13 +2326,9 @@ static void amdgpu_dm_do_flip( amdgpu_bo_unreserve(abo); - /* Wait for target vblank */ /* Wait until we're out of the vertical blank period before the one * targeted by the flip */ - target_vblank = target - drm_crtc_vblank_count(crtc) + - amdgpu_get_vblank_counter_kms(crtc->dev, acrtc->crtc_id); - while ((acrtc->enabled && (amdgpu_get_crtc_scanoutpos(adev->ddev, acrtc->crtc_id, 0, &vpos, &hpos, NULL, NULL, @@ -2605,14 +2604,15 @@ void amdgpu_dm_atomic_commit_tail( pflip_needed = !state->allow_modeset; if (pflip_needed) { + wait_for_vblank = + acrtc->flip_flags & DRM_MODE_PAGE_FLIP_ASYNC ? + false : true; + amdgpu_dm_do_flip( - crtc, - fb, - drm_crtc_vblank_count(crtc)); + crtc, + fb, + drm_crtc_vblank_count(crtc) + wait_for_vblank); - wait_for_vblank = - acrtc->flip_flags & DRM_MODE_PAGE_FLIP_ASYNC ? - false : true; /*clean up the flags for next usage*/ acrtc->flip_flags = 0; } -- cgit From 035e0fe5485fc1881a3c24eaac86832d804242e9 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Fri, 31 Mar 2017 17:40:15 -0400 Subject: drm/amd/display: adding FCLK and DPPCLK clock types Signed-off-by: Charlene Liu Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dm_services_types.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dm_services_types.h b/drivers/gpu/drm/amd/display/dc/dm_services_types.h index f89395e0c107..408141c6776e 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services_types.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services_types.h @@ -71,7 +71,9 @@ enum dm_pp_clock_type { DM_PP_CLOCK_TYPE_DCFCLK, DM_PP_CLOCK_TYPE_SOCCLK, DM_PP_CLOCK_TYPE_PIXELCLK, - DM_PP_CLOCK_TYPE_DISPLAYPHYCLK + DM_PP_CLOCK_TYPE_DISPLAYPHYCLK, + DM_PP_CLOCK_TYPE_DPPCLK, + DM_PP_CLOCK_TYPE_FCLK, }; #define DC_DECODE_PP_CLOCK_TYPE(clk_type) \ -- cgit From 632550d71fcf78d495cfd1d321427e634b662f23 Mon Sep 17 00:00:00 2001 From: Zeyu Fan Date: Mon, 3 Apr 2017 11:54:11 -0400 Subject: drm/amd/display: Fix hotspot programming during set cursor position. - Remove x,y hotspot from dc_cursor_attributes. Only program it through setPosition. Signed-off-by: Zeyu Fan Acked-by: Harry Wentland Reviewed-by: Zeyu Fan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 5 ----- drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 7 ------- drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_cursor.c | 11 ++++------- drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp_cursor.c | 15 ++++----------- 4 files changed, 8 insertions(+), 30 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 4b0fc6b56969..58fda20f6b97 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -90,8 +90,6 @@ static void dm_set_cursor( attributes.address.low_part = lower_32_bits(gpu_addr); attributes.width = width; attributes.height = height; - attributes.x_hot = 0; - attributes.y_hot = 0; attributes.color_format = CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA; attributes.rotation_angle = 0; attributes.attribute_flags.value = 0; @@ -118,7 +116,6 @@ static void dm_set_cursor( position.x = x; position.y = y; - position.hot_spot_enable = true; position.x_hotspot = xorigin; position.y_hotspot = yorigin; @@ -260,7 +257,6 @@ static int dm_crtc_cursor_set( position.enable = false; position.x = 0; position.y = 0; - position.hot_spot_enable = false; if (amdgpu_crtc->stream) { /*set cursor visible false*/ @@ -344,7 +340,6 @@ static int dm_crtc_cursor_move(struct drm_crtc *crtc, position.x = x; position.y = y; - position.hot_spot_enable = true; position.x_hotspot = xorigin; position.y_hotspot = yorigin; diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index 568b7f0569f8..b785dd7b3a97 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -395,11 +395,6 @@ struct dc_cursor_position { */ bool enable; - /* - * This parameter indicates whether cursor hot spot should be - * programmed - */ - bool hot_spot_enable; }; struct dc_cursor_mi_param { @@ -464,8 +459,6 @@ struct dc_cursor_attributes { /* Width and height should correspond to cursor surface width x heigh */ uint32_t width; uint32_t height; - uint32_t x_hot; - uint32_t y_hot; enum dc_cursor_color_format color_format; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_cursor.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_cursor.c index 1cab12ba8447..5b230b17fc5c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_cursor.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_cursor.c @@ -86,11 +86,10 @@ void dce110_ipp_cursor_set_position( program_position(ipp110, position->x, position->y); - if (position->hot_spot_enable) - program_hotspot( - ipp110, - position->x_hotspot, - position->y_hotspot); + program_hotspot( + ipp110, + position->x_hotspot, + position->y_hotspot); /* unlock cursor registers */ lock(ipp110, false); @@ -111,8 +110,6 @@ bool dce110_ipp_cursor_set_attributes( attributes->attribute_flags.bits.ENABLE_MAGNIFICATION, attributes->attribute_flags.bits.INVERSE_TRANSPARENT_CLAMPING); - /* Program hot spot coordinates */ - program_hotspot(ipp110, attributes->x_hot, attributes->y_hot); /* * Program cursor size -- NOTE: HW spec specifies that HW register diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp_cursor.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp_cursor.c index d520b5d7aa81..15671fd2cb9c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp_cursor.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp_cursor.c @@ -151,11 +151,10 @@ void dce120_ipp_cursor_set_position( CURSOR_X_POSITION, position->x, CURSOR_Y_POSITION, position->y); - if (position->hot_spot_enable) - DCP_REG_SET_2( - DCP0_CUR_HOT_SPOT, - CURSOR_HOT_SPOT_X, position->x_hotspot, - CURSOR_HOT_SPOT_Y, position->y_hotspot); + DCP_REG_SET_2( + DCP0_CUR_HOT_SPOT, + CURSOR_HOT_SPOT_X, position->x_hotspot, + CURSOR_HOT_SPOT_Y, position->y_hotspot); /* unlock cursor registers */ lock(ipp110, false); @@ -176,12 +175,6 @@ bool dce120_ipp_cursor_set_attributes( attributes->attribute_flags.bits.ENABLE_MAGNIFICATION, attributes->attribute_flags.bits.INVERSE_TRANSPARENT_CLAMPING); - /* Program hot spot coordinates */ - DCP_REG_SET_2( - DCP0_CUR_HOT_SPOT, - CURSOR_HOT_SPOT_X, attributes->x_hot, - CURSOR_HOT_SPOT_Y, attributes->y_hot); - /* * Program cursor size -- NOTE: HW spec specifies that HW register * stores size as (height - 1, width - 1) -- cgit From 6e5d1c829ba6a53bdd0f18a872a5178e9620ecab Mon Sep 17 00:00:00 2001 From: Leon Elazar Date: Tue, 4 Apr 2017 10:01:07 -0400 Subject: drm/amd/display: Memory was freed twice during disable 1. get_ss_info_from_atombios function was allocating the memory populating the provided pointer but them freeing the memory. Since the pointer was return as a valid value, we are trying to free the same memory during clock resource destruction Signed-off-by: Leon Elazar Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index 8ddad3a877d6..bd4524ef3a37 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -1035,7 +1035,6 @@ static void get_ss_info_from_atombios( } *spread_spectrum_data = ss_data; - dm_free(ss_data); dm_free(ss_info); return; -- cgit From 8b32076c27227cf5bed0c925c7a1a9680748424a Mon Sep 17 00:00:00 2001 From: Sylvia Tsai Date: Tue, 4 Apr 2017 17:28:17 -0400 Subject: drm/amd/display: Adding dm controlled signal type in dc_stream - Adding dm controlled signal type in dc_stream - Adding fallback to dvi signal when output signal is hdmi and the connector type is not Signed-off-by: Sylvia Tsai Acked-by: Harry Wentland Reviewed-by: Sylvia Tsai Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 30 +++++++++++------------ drivers/gpu/drm/amd/display/dc/dc.h | 1 + 2 files changed, 16 insertions(+), 15 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 069f588a9e02..2d40864b7b48 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1237,22 +1237,22 @@ static struct audio *find_first_free_audio(struct resource_context *res_ctx) static void update_stream_signal(struct core_stream *stream) { - const struct dc_sink *dc_sink = stream->public.sink; - - if (dc_sink->sink_signal == SIGNAL_TYPE_NONE) - stream->signal = stream->sink->link->public.connector_signal; - else if (dc_sink->sink_signal == SIGNAL_TYPE_DVI_SINGLE_LINK || - dc_sink->sink_signal == SIGNAL_TYPE_DVI_DUAL_LINK) - /* For asic supports dual link DVI, we should adjust signal type - * based on timing pixel clock. If pixel clock more than 165Mhz, - * signal is dual link, otherwise, single link. - */ - if (stream->public.timing.pix_clk_khz > TMDS_MAX_PIXEL_CLOCK_IN_KHZ) - stream->signal = SIGNAL_TYPE_DVI_DUAL_LINK; + if (stream->public.output_signal == SIGNAL_TYPE_NONE) { + const struct dc_sink *dc_sink = stream->public.sink; + + if (dc_sink->sink_signal == SIGNAL_TYPE_NONE) + stream->signal = + stream->sink->link-> + public.connector_signal; else - stream->signal = SIGNAL_TYPE_DVI_SINGLE_LINK; - else - stream->signal = dc_sink->sink_signal; + stream->signal = dc_sink->sink_signal; + } else { + stream->signal = stream->public.output_signal; + } + + if (stream->signal == SIGNAL_TYPE_DVI_SINGLE_LINK && + stream->public.timing.pix_clk_khz > TMDS_MAX_PIXEL_CLOCK_IN_KHZ) + stream->signal = SIGNAL_TYPE_DVI_DUAL_LINK; } bool resource_is_stream_unchanged( diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index a27a6aba0df1..97af8f63eec3 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -411,6 +411,7 @@ enum surface_update_type { struct dc_stream { const struct dc_sink *sink; struct dc_crtc_timing timing; + enum signal_type output_signal; enum dc_color_space output_color_space; -- cgit From 313bf4ff0180107b687dbd10dde8fd021247cd37 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Thu, 6 Apr 2017 16:21:58 -0400 Subject: drm/amd/display: Add same check as reset pipes for programing backend regs. Signed-off-by: Yongqiang Sun Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 839c34409c63..7430be502efd 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1689,6 +1689,10 @@ enum dc_status dce110_apply_ctx_to_hw( if (pipe_ctx->stream == pipe_ctx_old->stream) continue; + if (pipe_ctx->stream && pipe_ctx_old->stream + && !pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) + continue; + if (pipe_ctx->top_pipe) continue; -- cgit From fb9611d2167d73b7a7af66edb30893d22de9382d Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Thu, 6 Apr 2017 16:23:14 -0400 Subject: drm/amd/display: change mpo surface update check condition. Signed-off-by: Yongqiang Sun Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 9a3507e743cf..203cb9d0c89d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1024,7 +1024,8 @@ static unsigned int pixel_format_to_bpp(enum surface_pixel_format format) } static enum surface_update_type get_plane_info_update_type( - const struct dc_surface_update *u) + const struct dc_surface_update *u, + int surface_index) { struct dc_plane_info temp_plane_info = { { { { 0 } } } }; @@ -1049,7 +1050,11 @@ static enum surface_update_type get_plane_info_update_type( /* Special Validation parameters */ temp_plane_info.format = u->plane_info->format; - temp_plane_info.visible = u->plane_info->visible; + + if (surface_index == 0) + temp_plane_info.visible = u->plane_info->visible; + else + temp_plane_info.visible = u->surface->visible; if (memcmp(u->plane_info, &temp_plane_info, sizeof(struct dc_plane_info)) != 0) @@ -1111,7 +1116,8 @@ static enum surface_update_type get_scaling_info_update_type( static enum surface_update_type det_surface_update( const struct core_dc *dc, - const struct dc_surface_update *u) + const struct dc_surface_update *u, + int surface_index) { const struct validate_context *context = dc->current_context; enum surface_update_type type = UPDATE_TYPE_FAST; @@ -1120,7 +1126,7 @@ static enum surface_update_type det_surface_update( if (!is_surface_in_context(context, u->surface)) return UPDATE_TYPE_FULL; - type = get_plane_info_update_type(u); + type = get_plane_info_update_type(u, surface_index); if (overall_type < type) overall_type = type; @@ -1157,7 +1163,7 @@ enum surface_update_type dc_check_update_surfaces_for_stream( for (i = 0 ; i < surface_count; i++) { enum surface_update_type type = - det_surface_update(core_dc, &updates[i]); + det_surface_update(core_dc, &updates[i], i); if (type == UPDATE_TYPE_FULL) return type; -- cgit From b64875feb18a734739929e2af8a625b186bb6ec0 Mon Sep 17 00:00:00 2001 From: Leon Elazar Date: Mon, 10 Apr 2017 09:37:11 -0400 Subject: drm/amd/display: set NULL value during removal for remoteSink In MST case during removal of remote sink its descriptor pointer wasn't freed corectly. Signed-off-by: Leon Elazar Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 203cb9d0c89d..70dc02cf4dbb 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1787,7 +1787,7 @@ void dc_link_remove_remote_sink(const struct dc_link *link, const struct dc_sink dc_link->remote_sinks[i] = dc_link->remote_sinks[i+1]; i++; } - + dc_link->remote_sinks[i] = NULL; dc_link->sink_count--; return; } -- cgit From 07c84c7ad388c28ce69303182e06644ef30d3ac3 Mon Sep 17 00:00:00 2001 From: Ding Wang Date: Mon, 10 Apr 2017 14:02:23 -0400 Subject: drm/amd/display: Fix for tile MST - Set stream signal type to be SST when setting non-tile timing on MST tiled display. - Disable MST on sink after disabling MST link. - Enable MST on sink before enabling MST link. Signed-off-by: Ding Wang Acked-by: Harry Wentland Reviewed-by: Jun Lei Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 3 +++ drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 13 +++++++++++++ drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 3 +++ drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h | 2 ++ 4 files changed, 21 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index b878fb9697d7..426f7f8187a6 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1250,6 +1250,9 @@ static enum dc_status enable_link_dp_mst(struct pipe_ctx *pipe_ctx) if (link->public.cur_link_settings.lane_count != LANE_COUNT_UNKNOWN) return DC_OK; + /* set the sink to MST mode before enabling the link */ + dp_enable_mst_on_sink(link, true); + return enable_link_dp(pipe_ctx); } 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 9f12ba87827a..913b01cd7159 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 @@ -2453,3 +2453,16 @@ bool dc_link_dp_set_test_pattern( return true; } + +void dp_enable_mst_on_sink(struct core_link *link, bool enable) +{ + unsigned char mstmCntl; + + core_link_read_dpcd(link, DP_MSTM_CTRL, &mstmCntl, 1); + if (enable) + mstmCntl |= DP_MST_EN; + else + mstmCntl &= (~DP_MST_EN); + + core_link_write_dpcd(link, DP_MSTM_CTRL, &mstmCntl, 1); +} diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 3b814592fd70..316df150c1d9 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -129,6 +129,9 @@ void dp_disable_link_phy_mst(struct core_link *link, enum signal_type signal) return; dp_disable_link_phy(link, signal); + + /* set the sink to SST mode after disabling the link */ + dp_enable_mst_on_sink(link, false); } bool dp_set_hw_training_pattern( diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h index b0cf8e00059c..92c56e6f7588 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h @@ -57,4 +57,6 @@ void detect_dp_sink_caps(struct core_link *link); bool is_dp_active_dongle(const struct core_link *link); +void dp_enable_mst_on_sink(struct core_link *link, bool enable); + #endif /* __DC_LINK_DP_H__ */ -- cgit From 209a885be018435a062403a08063672c9d77d8d1 Mon Sep 17 00:00:00 2001 From: Jordan Lazare Date: Tue, 11 Apr 2017 11:40:18 -0400 Subject: drm/amd/display: Fix missing irq refactor causing potential i2c race Signed-off-by: Jordan Lazare Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 58fda20f6b97..57560a83fda9 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -32,8 +32,10 @@ #include #include + #include "amdgpu.h" #include "amdgpu_pm.h" +#include "dm_helpers.h" #include "dm_services_types.h" // We need to #undef FRAME_SIZE and DEPRECATED because they conflict @@ -3075,13 +3077,16 @@ static bool is_dp_capable_without_timing_msa( { uint8_t dpcd_data; bool capable = false; + if (amdgpu_connector->dc_link && - dc_read_aux_dpcd( - dc, - amdgpu_connector->dc_link->link_index, - DP_DOWN_STREAM_PORT_COUNT, - &dpcd_data, sizeof(dpcd_data))) + dm_helpers_dp_read_dpcd( + NULL, + amdgpu_connector->dc_link, + DP_DOWN_STREAM_PORT_COUNT, + &dpcd_data, + sizeof(dpcd_data))) { capable = (dpcd_data & DP_MSA_TIMING_PAR_IGNORED) ? true:false; + } return capable; } -- cgit From 1ce71fcd5dddf4a3198a96e422122edc210847e9 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Tue, 11 Apr 2017 22:24:44 -0400 Subject: drm/amd/display: use full surface update when stream is NULL Signed-off-by: Charlene Liu Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 2 +- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 70dc02cf4dbb..6576137ee189 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1155,7 +1155,7 @@ enum surface_update_type dc_check_update_surfaces_for_stream( int i; enum surface_update_type overall_type = UPDATE_TYPE_FAST; - if (stream_status->surface_count != surface_count) + if (stream_status == NULL || stream_status->surface_count != surface_count) return UPDATE_TYPE_FULL; if (stream_update) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 7430be502efd..1401331080c5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1599,11 +1599,11 @@ enum dc_status dce110_apply_ctx_to_hw( apply_min_clocks(dc, context, &clocks_state, true); if (context->dispclk_khz - > dc->current_context->dispclk_khz) + > dc->current_context->dispclk_khz) { context->res_ctx.pool->display_clock->funcs->set_clock( context->res_ctx.pool->display_clock, context->dispclk_khz * 115 / 100); - + } /* program audio wall clock. use HDMI as clock source if HDMI * audio active. Otherwise, use DP as clock source * first, loop to find any HDMI audio, if not, loop find DP audio -- cgit From 81c509633aa93442d58b895f773892b3e8d936cf Mon Sep 17 00:00:00 2001 From: Sylvia Tsai Date: Tue, 11 Apr 2017 15:15:28 -0400 Subject: drm/amd/display: Parse scanline registers They could differ between ASIC generations Signed-off-by: Sylvia Tsai Signed-off-by: Harry Wentland Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 15 +++++- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 21 ++++++--- drivers/gpu/drm/amd/display/dc/dc.h | 7 ++- .../display/dc/dce110/dce110_timing_generator.c | 54 ++++++++++------------ .../display/dc/dce110/dce110_timing_generator.h | 8 ++-- .../display/dc/dce120/dce120_timing_generator.c | 42 ++++++++--------- .../drm/amd/display/dc/inc/hw/timing_generator.h | 8 ++-- 7 files changed, 89 insertions(+), 66 deletions(-) (limited to 'drivers/gpu') 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 93f10bc772c4..84995a48ec61 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -103,6 +103,8 @@ static u32 dm_vblank_get_counter(struct amdgpu_device *adev, int crtc) static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc, u32 *vbl, u32 *position) { + uint32_t v_blank_start, v_blank_end, h_position, v_position; + if ((crtc < 0) || (crtc >= adev->mode_info.num_crtc)) return -EINVAL; else { @@ -113,7 +115,18 @@ static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc, return 0; } - return dc_stream_get_scanoutpos(acrtc->stream, vbl, position); + /* + * TODO rework base driver to use values directly. + * for now parse it back into reg-format + */ + dc_stream_get_scanoutpos(acrtc->stream, + &v_blank_start, + &v_blank_end, + &h_position, + &v_position); + + *position = (v_position) || (h_position << 16); + *vbl = (v_blank_start) || (v_blank_end << 16); } return 0; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index bf209f7bbf98..3dbd6c0885d8 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -282,12 +282,14 @@ uint32_t dc_stream_get_vblank_counter(const struct dc_stream *dc_stream) return 0; } -uint32_t dc_stream_get_scanoutpos( - const struct dc_stream *dc_stream, - uint32_t *vbl, - uint32_t *position) +bool dc_stream_get_scanoutpos(const struct dc_stream *dc_stream, + uint32_t *v_blank_start, + uint32_t *v_blank_end, + uint32_t *h_position, + uint32_t *v_position) { uint8_t i; + bool ret = false; struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); struct core_dc *core_dc = DC_TO_CORE(stream->ctx->dc); struct resource_context *res_ctx = @@ -299,10 +301,17 @@ uint32_t dc_stream_get_scanoutpos( if (res_ctx->pipe_ctx[i].stream != stream) continue; - return tg->funcs->get_scanoutpos(tg, vbl, position); + tg->funcs->get_scanoutpos(tg, + v_blank_start, + v_blank_end, + h_position, + v_position); + + ret = true; + break; } - return 0; + return ret; } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 97af8f63eec3..7d548b4d0299 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -484,8 +484,11 @@ uint32_t dc_stream_get_vblank_counter(const struct dc_stream *stream); * This has a dependency on the caller (amdgpu_get_crtc_scanoutpos) * being refactored properly to be dce-specific */ -uint32_t dc_stream_get_scanoutpos( - const struct dc_stream *stream, uint32_t *vbl, uint32_t *position); +bool dc_stream_get_scanoutpos(const struct dc_stream *stream, + uint32_t *v_blank_start, + uint32_t *v_blank_end, + uint32_t *h_position, + uint32_t *v_position); /* * Structure to store surface/stream associations for validation diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c index 006412be7a02..7070aaf9e433 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c @@ -574,29 +574,26 @@ void dce110_timing_generator_get_crtc_positions( * @param [out] vpos, hpos ***************************************************************************** */ -uint32_t dce110_timing_generator_get_crtc_scanoutpos( +void dce110_timing_generator_get_crtc_scanoutpos( struct timing_generator *tg, - uint32_t *vbl, - uint32_t *position) + uint32_t *v_blank_start, + uint32_t *v_blank_end, + uint32_t *h_position, + uint32_t *v_position) { struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); - /* TODO 1: Update the implementation once caller is updated - * WARNING!! This function is returning the whole register value - * because the caller is expecting it instead of proper vertical and - * horizontal position. This should be a temporary implementation - * until the caller is updated. */ - /* TODO 2: re-use dce110_timing_generator_get_crtc_positions() */ - - *vbl = dm_read_reg(tg->ctx, + uint32_t v_blank_start_end = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_V_BLANK_START_END)); - *position = dm_read_reg(tg->ctx, - CRTC_REG(mmCRTC_STATUS_POSITION)); + *v_blank_start = get_reg_field_value(v_blank_start_end, + CRTC_V_BLANK_START_END, + CRTC_V_BLANK_START); + *v_blank_end = get_reg_field_value(v_blank_start_end, + CRTC_V_BLANK_START_END, + CRTC_V_BLANK_END); - /* @TODO: return value should indicate if current - * crtc is inside vblank*/ - return 0; + dce110_timing_generator_get_crtc_positions(tg, h_position, v_position); } /* TODO: is it safe to assume that mask/shift of Primary and Underlay @@ -1875,34 +1872,31 @@ void dce110_tg_set_colors(struct timing_generator *tg, bool dce110_arm_vert_intr(struct timing_generator *tg, uint8_t width) { struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); - uint32_t vbl = 0; + uint32_t v_blank_start = 0; + uint32_t v_blank_end = 0; uint32_t val = 0; - uint32_t position, vbl_start; + uint32_t h_position, v_position; tg->funcs->get_scanoutpos( tg, - &vbl, - &position); + &v_blank_start, + &v_blank_end, + &h_position, + &v_position); - if (vbl == 0) + if (v_blank_start == 0 || v_blank_end == 0) return false; - vbl_start = - get_reg_field_value( - vbl, - CRTC_V_BLANK_START_END, - CRTC_V_BLANK_START); - set_reg_field_value( val, - vbl_start, + v_blank_start, CRTC_VERTICAL_INTERRUPT0_POSITION, CRTC_VERTICAL_INTERRUPT0_LINE_START); - /* Set interaval width for interrupt to fire to 1 scanline */ + /* Set interval width for interrupt to fire to 1 scanline */ set_reg_field_value( val, - vbl_start + width, + v_blank_start + width, CRTC_VERTICAL_INTERRUPT0_POSITION, CRTC_VERTICAL_INTERRUPT0_LINE_END); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h index ca387b40fc67..f14a4d91cd8e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h @@ -230,10 +230,12 @@ void dce110_timing_generator_set_static_screen_control( struct timing_generator *tg, uint32_t value); -uint32_t dce110_timing_generator_get_crtc_scanoutpos( +void dce110_timing_generator_get_crtc_scanoutpos( struct timing_generator *tg, - uint32_t *vbl, - uint32_t *position); + uint32_t *v_blank_start, + uint32_t *v_blank_end, + uint32_t *h_position, + uint32_t *v_position); void dce110_timing_generator_enable_advanced_request( struct timing_generator *tg, diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c index 95cb1768aeb5..1318df7ed47e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c @@ -576,24 +576,28 @@ void dce120_timing_generator_set_drr( } } -uint32_t dce120_timing_generator_get_crtc_scanoutpos( +void dce120_timing_generator_get_crtc_scanoutpos( struct timing_generator *tg, - uint32_t *vbl, - uint32_t *position) + uint32_t *v_blank_start, + uint32_t *v_blank_end, + uint32_t *h_position, + uint32_t *v_position) { struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); - *vbl = dm_read_reg_soc15( + uint32_t v_blank_start_end = dm_read_reg_soc15( tg->ctx, mmCRTC0_CRTC_V_BLANK_START_END, tg110->offsets.crtc); - *position = dm_read_reg_soc15( - tg->ctx, - mmCRTC0_CRTC_STATUS_POSITION, - tg110->offsets.crtc); + *v_blank_start = get_reg_field_value(v_blank_start_end, + CRTC0_CRTC_V_BLANK_START_END, + CRTC_V_BLANK_START); + *v_blank_end = get_reg_field_value(v_blank_start_end, + CRTC0_CRTC_V_BLANK_START_END, + CRTC_V_BLANK_END); - return 0; + dce120_timing_generator_get_crtc_positions(tg, h_position, v_position); } void dce120_timing_generator_enable_advanced_request( @@ -1044,26 +1048,22 @@ static bool dce120_arm_vert_intr( uint8_t width) { struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); - uint32_t vbl, position, vbl_start; + uint32_t v_blank_start, v_blank_end, h_position, v_position; tg->funcs->get_scanoutpos( tg, - &vbl, - &position); + &v_blank_start, + &v_blank_end, + &h_position, + &v_position); - if (vbl == 0) + if (v_blank_start == 0 || v_blank_end == 0) return false; - vbl_start = - get_reg_field_value( - vbl, - CRTC0_CRTC_V_BLANK_START_END, - CRTC_V_BLANK_START); - CRTC_REG_SET_2( CRTC0_CRTC_VERTICAL_INTERRUPT0_POSITION, - CRTC_VERTICAL_INTERRUPT0_LINE_START, vbl_start, - CRTC_VERTICAL_INTERRUPT0_LINE_END, vbl_start + width); + CRTC_VERTICAL_INTERRUPT0_LINE_START, v_blank_start, + CRTC_VERTICAL_INTERRUPT0_LINE_END, v_blank_start + width); return true; } diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h index 51902a4f8798..b3deaf2d8173 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h @@ -120,10 +120,12 @@ struct timing_generator_funcs { int32_t *h_position, int32_t *v_position); uint32_t (*get_frame_count)(struct timing_generator *tg); - uint32_t (*get_scanoutpos)( + void (*get_scanoutpos)( struct timing_generator *tg, - uint32_t *vbl, - uint32_t *position); + uint32_t *v_blank_start, + uint32_t *v_blank_end, + uint32_t *h_position, + uint32_t *v_position); void (*set_early_control)(struct timing_generator *tg, uint32_t early_cntl); void (*wait_for_state)(struct timing_generator *tg, -- cgit From ab3c179893fd44953008d1b1442973ecb1bb5c7e Mon Sep 17 00:00:00 2001 From: Vitaly Prosyak Date: Fri, 31 Mar 2017 15:25:04 -0500 Subject: drm/amd/display: Add support for programming stereo sync Signed-off-by: Vitaly Prosyak Acked-by: Harry Wentland Reviewed-by: Charlene Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_opp.h | 11 ++++++++--- drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c | 12 ++++++++++++ drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h | 14 ++++++++++++-- .../gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 7 +++++++ drivers/gpu/drm/amd/display/dc/inc/hw/opp.h | 5 +++++ drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h | 5 +++++ 6 files changed, 49 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h index 03ce9ba50b64..e5045d21a05c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h @@ -174,7 +174,8 @@ enum dce110_opp_reg_type { OPP_SF(DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, mask_sh),\ OPP_SF(DCFE_MEM_PWR_STATUS, DCP_REGAMMA_MEM_PWR_STATE, mask_sh),\ OPP_SF(FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, mask_sh),\ - OPP_SF(FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, mask_sh) + OPP_SF(FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, mask_sh),\ + OPP_SF(FMT_CONTROL, FMT_STEREOSYNC_OVERRIDE, mask_sh) #define OPP_COMMON_MASK_SH_LIST_DCE_100(mask_sh)\ OPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh),\ @@ -182,7 +183,8 @@ enum dce110_opp_reg_type { OPP_SF(DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, mask_sh),\ OPP_SF(DCFE_MEM_PWR_STATUS, DCP_REGAMMA_MEM_PWR_STATE, mask_sh),\ OPP_SF(FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, mask_sh),\ - OPP_SF(FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, mask_sh) + OPP_SF(FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, mask_sh),\ + OPP_SF(FMT_CONTROL, FMT_STEREOSYNC_OVERRIDE, mask_sh) #define OPP_COMMON_MASK_SH_LIST_DCE_112(mask_sh)\ OPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh),\ @@ -195,7 +197,8 @@ enum dce110_opp_reg_type { OPP_SF(FMT_CONTROL, FMT_420_PIXEL_PHASE_LOCKED, mask_sh),\ OPP_SF(FMT_CONTROL, FMT_CBCR_BIT_REDUCTION_BYPASS, mask_sh),\ OPP_SF(FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, mask_sh),\ - OPP_SF(FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, mask_sh) + OPP_SF(FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, mask_sh),\ + OPP_SF(FMT_CONTROL, FMT_STEREOSYNC_OVERRIDE, mask_sh) #define OPP_COMMON_MASK_SH_LIST_DCE_80(mask_sh)\ OPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh),\ @@ -244,6 +247,7 @@ enum dce110_opp_reg_type { OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_EN, mask_sh),\ OPP_SF(FMT0_FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, mask_sh),\ OPP_SF(FMT0_FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, mask_sh),\ + OPP_SF(FMT0_FMT_CONTROL, FMT_STEREOSYNC_OVERRIDE, mask_sh),\ OPP_SF(FMT0_FMT_DITHER_RAND_R_SEED, FMT_RAND_R_SEED, mask_sh),\ OPP_SF(FMT0_FMT_DITHER_RAND_G_SEED, FMT_RAND_G_SEED, mask_sh),\ OPP_SF(FMT0_FMT_DITHER_RAND_B_SEED, FMT_RAND_B_SEED, mask_sh),\ @@ -308,6 +312,7 @@ enum dce110_opp_reg_type { type FMT_RGB_RANDOM_ENABLE; \ type FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX; \ type FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP; \ + type FMT_STEREOSYNC_OVERRIDE; \ type FMT_RAND_R_SEED; \ type FMT_RAND_G_SEED; \ type FMT_RAND_B_SEED; \ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c index f3e1a293351f..9713def6e481 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c @@ -1286,6 +1286,17 @@ void dce110_se_hdmi_audio_disable( dce110_se_enable_audio_clock(enc, false); } + +static void setup_stereo_sync( + struct stream_encoder *enc, + int tg_inst, bool enable) +{ + struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); + REG_UPDATE(DIG_FE_CNTL, DIG_STEREOSYNC_SELECT, tg_inst); + REG_UPDATE(DIG_FE_CNTL, DIG_STEREOSYNC_GATE_EN, !enable); +} + + static const struct stream_encoder_funcs dce110_str_enc_funcs = { .dp_set_stream_attribute = dce110_stream_encoder_dp_set_stream_attribute, @@ -1316,6 +1327,7 @@ static const struct stream_encoder_funcs dce110_str_enc_funcs = { .hdmi_audio_setup = dce110_se_hdmi_audio_setup, .hdmi_audio_disable = dce110_se_hdmi_audio_disable, + .setup_stereo_sync = setup_stereo_sync, }; bool dce110_stream_encoder_construct( diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h index c2f4050fc6dc..850e12a8db61 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h @@ -151,6 +151,8 @@ SE_SF(DP_VID_N, DP_VID_N, mask_sh),\ SE_SF(DP_VID_M, DP_VID_M, mask_sh),\ SE_SF(DIG_FE_CNTL, DIG_START, mask_sh),\ + SE_SF(DIG_FE_CNTL, DIG_STEREOSYNC_SELECT, mask_sh),\ + SE_SF(DIG_FE_CNTL, DIG_STEREOSYNC_GATE_EN, mask_sh),\ SE_SF(AFMT_AUDIO_SRC_CONTROL, AFMT_AUDIO_SRC_SELECT, mask_sh),\ SE_SF(AFMT_AUDIO_PACKET_CONTROL2, AFMT_AUDIO_CHANNEL_ENABLE, mask_sh),\ SE_SF(HDMI_AUDIO_PACKET_CONTROL, HDMI_AUDIO_PACKETS_PER_LINE, mask_sh),\ @@ -265,7 +267,9 @@ SE_SF(DIG0_AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, mask_sh),\ SE_SF(DIG0_HDMI_CONTROL, HDMI_CLOCK_CHANNEL_RATE, mask_sh),\ SE_SF(DIG0_DIG_FE_CNTL, TMDS_PIXEL_ENCODING, mask_sh),\ - SE_SF(DIG0_DIG_FE_CNTL, TMDS_COLOR_FORMAT, mask_sh) + SE_SF(DIG0_DIG_FE_CNTL, TMDS_COLOR_FORMAT, mask_sh),\ + SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_SELECT, mask_sh),\ + SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_GATE_EN, mask_sh) #define SE_COMMON_MASK_SH_LIST_SOC(mask_sh)\ SE_COMMON_MASK_SH_LIST_SOC_BASE(mask_sh) @@ -281,7 +285,9 @@ SE_SF(HDMI_CONTROL, HDMI_CLOCK_CHANNEL_RATE, mask_sh),\ SE_SF(HDMI_CONTROL, HDMI_DATA_SCRAMBLE_EN, mask_sh),\ SE_SF(DIG_FE_CNTL, TMDS_PIXEL_ENCODING, mask_sh),\ - SE_SF(DIG_FE_CNTL, TMDS_COLOR_FORMAT, mask_sh) + SE_SF(DIG_FE_CNTL, TMDS_COLOR_FORMAT, mask_sh),\ + SE_SF(DIG_FE_CNTL, DIG_STEREOSYNC_SELECT, mask_sh),\ + SE_SF(DIG_FE_CNTL, DIG_STEREOSYNC_GATE_EN, mask_sh) #define SE_COMMON_MASK_SH_LIST_DCE112(mask_sh)\ SE_COMMON_MASK_SH_LIST_DCE_COMMON(mask_sh),\ @@ -416,6 +422,8 @@ struct dce_stream_encoder_shift { uint8_t AFMT_AUDIO_CLOCK_EN; uint8_t TMDS_PIXEL_ENCODING; uint8_t TMDS_COLOR_FORMAT; + uint8_t DIG_STEREOSYNC_SELECT; + uint8_t DIG_STEREOSYNC_GATE_EN; uint8_t DP_DB_DISABLE; uint8_t DP_MSA_MISC0; uint8_t DP_MSA_HTOTAL; @@ -543,6 +551,8 @@ struct dce_stream_encoder_mask { uint32_t AFMT_AUDIO_SAMPLE_SEND; uint32_t AFMT_AUDIO_CLOCK_EN; uint32_t TMDS_PIXEL_ENCODING; + uint32_t DIG_STEREOSYNC_SELECT; + uint32_t DIG_STEREOSYNC_GATE_EN; uint32_t TMDS_COLOR_FORMAT; uint32_t DP_DB_DISABLE; uint32_t DP_MSA_MISC0; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 1401331080c5..6bf03d680314 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1056,6 +1056,13 @@ static enum dc_status apply_single_controller_ctx_to_hw( stream->sink->link->link_enc, pipe_ctx->stream->signal); + if (pipe_ctx->stream->signal != SIGNAL_TYPE_VIRTUAL) + pipe_ctx->stream_enc->funcs->setup_stereo_sync( + pipe_ctx->stream_enc, + pipe_ctx->tg->inst, + stream->public.timing.timing_3d_format != TIMING_3D_FORMAT_NONE); + + /*vbios crtc_source_selection and encoder_setup will override fmt_C*/ pipe_ctx->opp->funcs->opp_program_fmt( pipe_ctx->opp, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h index e01b831a7e7f..521bd21eb5df 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h @@ -316,6 +316,11 @@ struct opp_funcs { struct hw_adjustment_range *range); void (*opp_destroy)(struct output_pixel_processor **opp); + + void (*opp_set_stereo_polarity)( + struct output_pixel_processor *opp, + bool enable, + bool rightEyePolarity); }; #endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h index 674bebfe3bd2..9fb27bd360ac 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h @@ -118,6 +118,11 @@ struct stream_encoder_funcs { void (*hdmi_audio_disable) ( struct stream_encoder *enc); + + void (*setup_stereo_sync) ( + struct stream_encoder *enc, + int tg_inst, + bool enable); }; #endif /* STREAM_ENCODER_H_ */ -- cgit From 09e2d07f9d4d30f7d219b562d656d7c7611e2b65 Mon Sep 17 00:00:00 2001 From: Eric Cook Date: Wed, 12 Apr 2017 11:05:08 -0400 Subject: drm/amd/display: FreeSync LFC MIN/MAX update on current frame - Update BTR/LFC logic so that V_TOTAL_MIN/MAX will take affect on current frame - Add in FreeSync update to MPO code path Signed-off-by: Eric Cook Acked-by: Harry Wentland Reviewed-by: Anthony Koo Signed-off-by: Alex Deucher --- .../drm/amd/display/modules/freesync/freesync.c | 67 +++++++++++++--------- 1 file changed, 39 insertions(+), 28 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index 7a0731e2dbb0..94566c0a0e62 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -641,7 +641,8 @@ static void set_static_ramp_variables(struct core_freesync *core_freesync, void mod_freesync_handle_v_update(struct mod_freesync *mod_freesync, const struct dc_stream **streams, int num_streams) { - unsigned int index, v_total = 0; + unsigned int index, v_total, inserted_frame_v_total = 0; + unsigned int min_frame_duration_in_ns, vmax, vmin = 0; struct freesync_state *state; struct core_freesync *core_freesync = NULL; @@ -665,19 +666,48 @@ void mod_freesync_handle_v_update(struct mod_freesync *mod_freesync, /* Only execute if in fullscreen mode */ if (state->fullscreen == true && - core_freesync->map[index].user_enable.enable_for_gaming) { + core_freesync->map[index].user_enable.enable_for_gaming && + core_freesync->map[index].caps->btr_supported && + state->btr.btr_active) { + + /* TODO: pass in flag for Pre-DCE12 ASIC + * in order for frame variable duration to take affect, + * it needs to be done one VSYNC early, which is at + * frameCounter == 1. + * For DCE12 and newer updates to V_TOTAL_MIN/MAX + * will take affect on current frame + */ + if (state->btr.frames_to_insert == state->btr.frame_counter) { + + min_frame_duration_in_ns = ((unsigned int) (div64_u64( + (1000000000ULL * 1000000), + state->nominal_refresh_rate_in_micro_hz))); + + calc_vmin_vmax(core_freesync, *streams, &vmin, &vmax); - if (state->btr.btr_active) - if (state->btr.frame_counter > 0) + inserted_frame_v_total = vmin; - state->btr.frame_counter--; + if (min_frame_duration_in_ns / 1000) + inserted_frame_v_total = + state->btr.inserted_frame_duration_in_us * + vmin / (min_frame_duration_in_ns / 1000); - if (state->btr.frame_counter == 1) { + /* Set length of inserted frames as v_total_max*/ + vmax = inserted_frame_v_total; + vmin = inserted_frame_v_total; - /* Restore FreeSync */ - set_freesync_on_streams(core_freesync, streams, - num_streams); + /* Program V_TOTAL */ + core_freesync->dc->stream_funcs.adjust_vmin_vmax( + core_freesync->dc, streams, + num_streams, vmin, vmax); } + + if (state->btr.frame_counter > 0) + state->btr.frame_counter--; + + /* Restore FreeSync */ + if (state->btr.frame_counter == 0) + set_freesync_on_streams(core_freesync, streams, num_streams); } /* If in fullscreen freesync mode or in video, do not program @@ -1022,8 +1052,6 @@ static void apply_below_the_range(struct core_freesync *core_freesync, unsigned int delta_from_mid_point_in_us_1 = 0xFFFFFFFF; unsigned int delta_from_mid_point_in_us_2 = 0xFFFFFFFF; unsigned int frames_to_insert = 0; - unsigned int inserted_frame_v_total = 0; - unsigned int vmin = 0, vmax = 0; unsigned int min_frame_duration_in_ns = 0; struct freesync_state *state = &core_freesync->map[map_index].state; @@ -1101,23 +1129,6 @@ static void apply_below_the_range(struct core_freesync *core_freesync, inserted_frame_duration_in_us = state->time.min_render_time_in_us; - /* We need the v_total_min from capability */ - calc_vmin_vmax(core_freesync, stream, &vmin, &vmax); - - inserted_frame_v_total = vmin; - if (min_frame_duration_in_ns / 1000) - inserted_frame_v_total = inserted_frame_duration_in_us * - vmin / (min_frame_duration_in_ns / 1000); - - /* Set length of inserted frames as v_total_max*/ - vmax = inserted_frame_v_total; - - /* Program V_TOTAL */ - core_freesync->dc->stream_funcs.adjust_vmin_vmax( - core_freesync->dc, &stream, - 1, vmin, - vmax); - /* Cache the calculated variables */ state->btr.inserted_frame_duration_in_us = inserted_frame_duration_in_us; -- cgit From 03e4173b44d514818c98555bc709a931ff9300ce Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 6 Apr 2017 16:48:48 -0400 Subject: drm/amd/display: Remove unused scratch_val_ctx Signed-off-by: Harry Wentland Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 3 --- drivers/gpu/drm/amd/display/dc/inc/core_dc.h | 1 - 2 files changed, 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 6576137ee189..7b0b7356ae89 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -411,8 +411,6 @@ static void destruct(struct core_dc *dc) dc->current_context = NULL; dm_free(dc->temp_flip_context); dc->temp_flip_context = NULL; - dm_free(dc->scratch_val_ctx); - dc->scratch_val_ctx = NULL; dm_free(dc->ctx); dc->ctx = NULL; @@ -432,7 +430,6 @@ static bool construct(struct core_dc *dc, dc->current_context = dm_alloc(sizeof(*dc->current_context)); dc->temp_flip_context = dm_alloc(sizeof(*dc->temp_flip_context)); - dc->scratch_val_ctx = dm_alloc(sizeof(*dc->scratch_val_ctx)); if (!dc->current_context || !dc->temp_flip_context) { dm_error("%s: failed to create validate ctx\n", __func__); diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_dc.h b/drivers/gpu/drm/amd/display/dc/inc/core_dc.h index 8d87f490dc1c..ec3edbe20d85 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_dc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_dc.h @@ -23,7 +23,6 @@ struct core_dc { struct validate_context *current_context; struct validate_context *temp_flip_context; - struct validate_context *scratch_val_ctx; struct resource_pool *res_pool; /* Display Engine Clock levels */ -- cgit From 6d9501e4ad2df6fc631e99d3cfd2afa09542393a Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 6 Apr 2017 17:05:53 -0400 Subject: drm/amd/display: Get rid of temp_flip_context If we need to update our context we can allocate memory. No need to keep temporary memory for this. Signed-off-by: Harry Wentland Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 26 +++++++++++++------------- drivers/gpu/drm/amd/display/dc/inc/core_dc.h | 1 - 2 files changed, 13 insertions(+), 14 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 7b0b7356ae89..e8499e744595 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -409,8 +409,6 @@ static void destruct(struct core_dc *dc) dm_free(dc->current_context); dc->current_context = NULL; - dm_free(dc->temp_flip_context); - dc->temp_flip_context = NULL; dm_free(dc->ctx); dc->ctx = NULL; @@ -429,9 +427,8 @@ static bool construct(struct core_dc *dc, } dc->current_context = dm_alloc(sizeof(*dc->current_context)); - dc->temp_flip_context = dm_alloc(sizeof(*dc->temp_flip_context)); - if (!dc->current_context || !dc->temp_flip_context) { + if (!dc->current_context) { dm_error("%s: failed to create validate ctx\n", __func__); goto val_ctx_fail; } @@ -874,13 +871,9 @@ bool dc_commit_streams( } resource_validate_ctx_destruct(core_dc->current_context); + dm_free(core_dc->current_context); - if (core_dc->temp_flip_context != core_dc->current_context) { - dm_free(core_dc->temp_flip_context); - core_dc->temp_flip_context = core_dc->current_context; - } core_dc->current_context = context; - memset(core_dc->temp_flip_context, 0, sizeof(*core_dc->temp_flip_context)); return (result == DC_OK); @@ -1212,7 +1205,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, new_surfaces[i] = srf_updates[i].surface; /* initialize scratch memory for building context */ - context = core_dc->temp_flip_context; + context = dm_alloc(sizeof(*context)); resource_validate_ctx_copy_construct( core_dc->current_context, context); @@ -1220,7 +1213,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, if (!resource_attach_surfaces_to_context( new_surfaces, surface_count, dc_stream, context)) { BREAK_TO_DEBUGGER(); - return; + goto fail; } } else { context = core_dc->current_context; @@ -1326,7 +1319,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, if (update_type == UPDATE_TYPE_FULL) { if (!core_dc->res_pool->funcs->validate_bandwidth(core_dc, context)) { BREAK_TO_DEBUGGER(); - return; + goto fail; } else core_dc->hwss.set_bandwidth(core_dc, context, false); } @@ -1418,10 +1411,17 @@ void dc_update_surfaces_and_stream(struct dc *dc, if (core_dc->current_context != context) { resource_validate_ctx_destruct(core_dc->current_context); - core_dc->temp_flip_context = core_dc->current_context; + dm_free(core_dc->current_context); core_dc->current_context = context; } + return; + +fail: + if (core_dc->current_context != context) { + resource_validate_ctx_destruct(context); + dm_free(context); + } } uint8_t dc_get_current_stream_count(const struct dc *dc) diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_dc.h b/drivers/gpu/drm/amd/display/dc/inc/core_dc.h index ec3edbe20d85..f9363f642f92 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_dc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_dc.h @@ -22,7 +22,6 @@ struct core_dc { struct core_link *links[MAX_PIPES * 2]; struct validate_context *current_context; - struct validate_context *temp_flip_context; struct resource_pool *res_pool; /* Display Engine Clock levels */ -- cgit From 2180e7cca4d5b93b9f150a83d83e27b7fb82a72f Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Mon, 17 Apr 2017 11:39:19 -0400 Subject: drm/amd/display: update dce8 & 10 bw programming Signed-off-by: Dmytro Laktyushkin Acked-by: Harry Wentland Reviewed-by: Jordan Lazare Signed-off-by: Alex Deucher --- .../amd/display/dc/dce100/dce100_hw_sequencer.c | 28 +++++++++++----------- .../amd/display/dc/dce100/dce100_hw_sequencer.h | 7 +++--- .../drm/amd/display/dc/dce100/dce100_resource.c | 1 + .../amd/display/dc/dce110/dce110_hw_sequencer.c | 3 +-- .../drm/amd/display/dc/dce80/dce80_hw_sequencer.c | 19 +-------------- drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 4 ---- 6 files changed, 21 insertions(+), 41 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c index f11044e0245c..dd6f0b1bd8ae 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c @@ -28,6 +28,8 @@ #include "core_types.h" #include "hw_sequencer.h" #include "dce100_hw_sequencer.h" +#include "resource.h" + #include "dce110/dce110_hw_sequencer.h" /* include DCE10 register header files */ @@ -104,7 +106,7 @@ static bool dce100_enable_display_power_gating( return false; } -void dce100_pplib_apply_display_requirements( +static void dce100_pplib_apply_display_requirements( struct core_dc *dc, struct validate_context *context) { @@ -112,6 +114,8 @@ void dce100_pplib_apply_display_requirements( pp_display_cfg->avail_mclk_switch_time_us = dce110_get_min_vblank_time_us(context); + pp_display_cfg->min_memory_clock_khz = context->bw_results.required_yclk + / MEMORY_TYPE_MULTIPLIER; dce110_fill_display_configs(context, pp_display_cfg); @@ -122,20 +126,18 @@ void dce100_pplib_apply_display_requirements( dc->prev_display_config = *pp_display_cfg; } - - -static void set_displaymarks( - const struct core_dc *dc, struct validate_context *context) -{ - /* Do nothing until we have proper bandwitdth calcs */ -} - -static void set_bandwidth( +void dce100_set_bandwidth( struct core_dc *dc, struct validate_context *context, bool decrease_allowed) { - dc->hwss.set_displaymarks(dc, context); + if (decrease_allowed || context->dispclk_khz > dc->current_context->dispclk_khz) { + context->res_ctx.pool->display_clock->funcs->set_clock( + context->res_ctx.pool->display_clock, + context->dispclk_khz * 115 / 100); + dc->current_context->bw_results.dispclk_khz = context->dispclk_khz; + dc->current_context->dispclk_khz = context->dispclk_khz; + } dce100_pplib_apply_display_requirements(dc, context); } @@ -146,10 +148,8 @@ bool dce100_hw_sequencer_construct(struct core_dc *dc) { dce110_hw_sequencer_construct(dc); - /* TODO: dce80 is empty implementation at the moment*/ dc->hwss.enable_display_power_gating = dce100_enable_display_power_gating; - dc->hwss.set_displaymarks = set_displaymarks; - dc->hwss.set_bandwidth = set_bandwidth; + dc->hwss.set_bandwidth = dce100_set_bandwidth; return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h index f51d04a66a49..24433f0e770b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h @@ -33,9 +33,10 @@ struct validate_context; bool dce100_hw_sequencer_construct(struct core_dc *dc); -void dce100_pplib_apply_display_requirements( - struct core_dc *dc, - struct validate_context *context); +void dce100_set_bandwidth( + struct core_dc *dc, + struct validate_context *context, + bool decrease_allowed); #endif /* __DC_HWSS_DCE100_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 7fae8537e18a..9b365597cec5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -771,6 +771,7 @@ bool dce100_validate_bandwidth( { /* TODO implement when needed but for now hardcode max value*/ context->dispclk_khz = 681000; + context->bw_results.required_yclk = 250000 * MEMORY_TYPE_MULTIPLIER; return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 6bf03d680314..2fbf6ddcf3be 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -2266,7 +2266,7 @@ static void dce110_set_bandwidth( struct validate_context *context, bool decrease_allowed) { - dc->hwss.set_displaymarks(dc, context); + dce110_set_displaymarks(dc, context); if (decrease_allowed || context->dispclk_khz > dc->current_context->dispclk_khz) { context->res_ctx.pool->display_clock->funcs->set_clock( @@ -2468,7 +2468,6 @@ static const struct hw_sequencer_funcs dce110_funcs = { .enable_display_power_gating = dce110_enable_display_power_gating, .power_down_front_end = dce110_power_down_fe, .pipe_control_lock = dce_pipe_control_lock, - .set_displaymarks = dce110_set_displaymarks, .set_bandwidth = dce110_set_bandwidth, .set_drr = set_drr, .set_static_screen_control = set_static_screen_control, diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c index 9d4e7d8b836e..4cba80ff6ca4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c @@ -107,30 +107,13 @@ static bool dce80_enable_display_power_gating( return false; } -static void set_displaymarks( - const struct core_dc *dc, struct validate_context *context) -{ - /* Do nothing until we have proper bandwitdth calcs */ -} - -static void set_bandwidth( - struct core_dc *dc, - struct validate_context *context, - bool decrease_allowed) -{ - dc->hwss.set_displaymarks(dc, context); - dce100_pplib_apply_display_requirements(dc, context); -} - - bool dce80_hw_sequencer_construct(struct core_dc *dc) { dce110_hw_sequencer_construct(dc); dc->hwss.enable_display_power_gating = dce80_enable_display_power_gating; dc->hwss.pipe_control_lock = dce_pipe_control_lock; - dc->hwss.set_displaymarks = set_displaymarks; - dc->hwss.set_bandwidth = set_bandwidth; + dc->hwss.set_bandwidth = dce100_set_bandwidth; return true; } diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 077dc7573c52..9bfaaad09bea 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -123,10 +123,6 @@ struct hw_sequencer_funcs { struct pipe_ctx *pipe, bool lock); - void (*set_displaymarks)( - const struct core_dc *dc, - struct validate_context *context); - void (*set_bandwidth)( struct core_dc *dc, struct validate_context *context, -- cgit From 129eed72823d25fa57aaf64a1cef6488fd21d0cd Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 6 Apr 2017 16:22:33 -0400 Subject: drm/amd/display: pull commit_surfaces out of atomic_commit into helper function This should make things simpler when we try to rework this later when we pass validate_context from atomic_check to atomic_commit. Signed-off-by: Harry Wentland Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 113 +++++++++++---------- 1 file changed, 62 insertions(+), 51 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 57560a83fda9..d8718e2ac207 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2350,6 +2350,67 @@ static void amdgpu_dm_do_flip( acrtc->crtc_id); } +void dc_commit_surfaces(struct drm_atomic_state *state, + struct drm_device *dev, struct amdgpu_display_manager *dm) +{ + uint32_t i; + struct drm_plane *plane; + struct drm_plane_state *old_plane_state; + + /* update planes when needed */ + for_each_plane_in_state(state, plane, old_plane_state, i) { + struct drm_plane_state *plane_state = plane->state; + struct drm_crtc *crtc = plane_state->crtc; + struct drm_framebuffer *fb = plane_state->fb; + struct drm_connector *connector; + struct dm_connector_state *dm_state = NULL; + enum dm_commit_action action; + bool pflip_needed; + + if (!fb || !crtc || !crtc->state->active) + continue; + + action = get_dm_commit_action(crtc->state); + + /* Surfaces are created under two scenarios: + * 1. This commit is not a page flip. + * 2. This commit is a page flip, and streams are created. + */ + pflip_needed = !state->allow_modeset; + if (!pflip_needed || action == DM_COMMIT_ACTION_DPMS_ON + || action == DM_COMMIT_ACTION_SET) { + list_for_each_entry(connector, + &dev->mode_config.connector_list, + head) { + if (connector->state->crtc == crtc) { + dm_state = to_dm_connector_state( + connector->state); + break; + } + } + + /* + * This situation happens in the following case: + * we are about to get set mode for connector who's only + * possible crtc (in encoder crtc mask) is used by + * another connector, that is why it will try to + * re-assing crtcs in order to make configuration + * supported. For our implementation we need to make all + * encoders support all crtcs, then this issue will + * never arise again. But to guard code from this issue + * check is left. + * + * Also it should be needed when used with actual + * drm_atomic_commit ioctl in future + */ + if (!dm_state) + continue; + + dm_dc_surface_commit(dm->dc, crtc); + } + } +} + void amdgpu_dm_atomic_commit_tail( struct drm_atomic_state *state) { @@ -2521,57 +2582,7 @@ void amdgpu_dm_atomic_commit_tail( } /* update planes when needed */ - for_each_plane_in_state(state, plane, old_plane_state, i) { - struct drm_plane_state *plane_state = plane->state; - struct drm_crtc *crtc = plane_state->crtc; - struct drm_framebuffer *fb = plane_state->fb; - struct drm_connector *connector; - struct dm_connector_state *dm_state = NULL; - enum dm_commit_action action; - bool pflip_needed; - - if (!fb || !crtc || !crtc->state->active) - continue; - - action = get_dm_commit_action(crtc->state); - - /* Surfaces are created under two scenarios: - * 1. This commit is not a page flip. - * 2. This commit is a page flip, and streams are created. - */ - pflip_needed = !state->allow_modeset; - if (!pflip_needed || - action == DM_COMMIT_ACTION_DPMS_ON || - action == DM_COMMIT_ACTION_SET) { - list_for_each_entry(connector, - &dev->mode_config.connector_list, head) { - if (connector->state->crtc == crtc) { - dm_state = to_dm_connector_state( - connector->state); - break; - } - } - - /* - * This situation happens in the following case: - * we are about to get set mode for connector who's only - * possible crtc (in encoder crtc mask) is used by - * another connector, that is why it will try to - * re-assing crtcs in order to make configuration - * supported. For our implementation we need to make all - * encoders support all crtcs, then this issue will - * never arise again. But to guard code from this issue - * check is left. - * - * Also it should be needed when used with actual - * drm_atomic_commit ioctl in future - */ - if (!dm_state) - continue; - - dm_dc_surface_commit(dm->dc, crtc); - } - } + dc_commit_surfaces(state, dev, dm); for (i = 0; i < new_crtcs_count; i++) { /* -- cgit From 927f6eff2aa40e73528619818374c271ddfadd3d Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 6 Apr 2017 18:57:05 -0400 Subject: drm/amd/display: Copy ctx to current_context instead of assign Signed-off-by: Harry Wentland Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index e8499e744595..0d870e9c7c99 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -906,13 +906,13 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) resource_validate_ctx_copy_construct(core_dc->current_context, context); post_surface_trace(dc); - for (i = 0; i < context->res_ctx.pool->pipe_count; i++) if (context->res_ctx.pipe_ctx[i].stream == NULL) { context->res_ctx.pipe_ctx[i].pipe_idx = i; core_dc->hwss.power_down_front_end( core_dc, &context->res_ctx.pipe_ctx[i]); } + if (!core_dc->res_pool->funcs->validate_bandwidth(core_dc, context)) { BREAK_TO_DEBUGGER(); return false; @@ -920,11 +920,10 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) core_dc->hwss.set_bandwidth(core_dc, context, true); - resource_validate_ctx_destruct(core_dc->current_context); - if (core_dc->current_context) - dm_free(core_dc->current_context); + resource_validate_ctx_copy_construct(context, core_dc->current_context); - core_dc->current_context = context; + resource_validate_ctx_destruct(context); + dm_free(context); return true; } -- cgit From 8122a253b34aec75a1fdc3fe61c97b9026a0bff6 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Wed, 29 Mar 2017 11:15:14 -0400 Subject: drm/amd/display: Move resource_validate_ctx_destruct to dc.h This will be needed to clean up context once we add it to private atomic state. Signed-off-by: Harry Wentland Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 22 +++++++++++----------- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 4 ++-- drivers/gpu/drm/amd/display/dc/dc.h | 6 ++++++ drivers/gpu/drm/amd/display/dc/inc/resource.h | 6 ------ 4 files changed, 19 insertions(+), 19 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 0d870e9c7c99..5620fe361173 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -389,7 +389,7 @@ static void allocate_dc_stream_funcs(struct core_dc *core_dc) static void destruct(struct core_dc *dc) { - resource_validate_ctx_destruct(dc->current_context); + dc_resource_validate_ctx_destruct(dc->current_context); destroy_links(dc); @@ -654,7 +654,7 @@ bool dc_validate_resources( result = core_dc->res_pool->funcs->validate_with_context( core_dc, set, set_count, context); - resource_validate_ctx_destruct(context); + dc_resource_validate_ctx_destruct(context); dm_free(context); context_alloc_fail: @@ -684,7 +684,7 @@ bool dc_validate_guaranteed( result = core_dc->res_pool->funcs->validate_guaranteed( core_dc, stream, context); - resource_validate_ctx_destruct(context); + dc_resource_validate_ctx_destruct(context); dm_free(context); context_alloc_fail: @@ -838,7 +838,7 @@ bool dc_commit_streams( __func__, result); BREAK_TO_DEBUGGER(); - resource_validate_ctx_destruct(context); + dc_resource_validate_ctx_destruct(context); goto fail; } @@ -870,7 +870,7 @@ bool dc_commit_streams( context->streams[i]->public.timing.pix_clk_khz); } - resource_validate_ctx_destruct(core_dc->current_context); + dc_resource_validate_ctx_destruct(core_dc->current_context); dm_free(core_dc->current_context); core_dc->current_context = context; @@ -903,7 +903,7 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) dm_error("%s: failed to create validate ctx\n", __func__); return false; } - resource_validate_ctx_copy_construct(core_dc->current_context, context); + dc_resource_validate_ctx_copy_construct(core_dc->current_context, context); post_surface_trace(dc); for (i = 0; i < context->res_ctx.pool->pipe_count; i++) @@ -920,9 +920,9 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) core_dc->hwss.set_bandwidth(core_dc, context, true); - resource_validate_ctx_copy_construct(context, core_dc->current_context); + dc_resource_validate_ctx_copy_construct(context, core_dc->current_context); - resource_validate_ctx_destruct(context); + dc_resource_validate_ctx_destruct(context); dm_free(context); return true; @@ -1205,7 +1205,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, /* initialize scratch memory for building context */ context = dm_alloc(sizeof(*context)); - resource_validate_ctx_copy_construct( + dc_resource_validate_ctx_copy_construct( core_dc->current_context, context); /* add surface to context */ @@ -1409,7 +1409,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, } if (core_dc->current_context != context) { - resource_validate_ctx_destruct(core_dc->current_context); + dc_resource_validate_ctx_destruct(core_dc->current_context); dm_free(core_dc->current_context); core_dc->current_context = context; @@ -1418,7 +1418,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, fail: if (core_dc->current_context != context) { - resource_validate_ctx_destruct(context); + dc_resource_validate_ctx_destruct(context); dm_free(context); } } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 2d40864b7b48..2e12a0ba5ddf 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -2050,7 +2050,7 @@ static void set_vsc_info_packet( /*TODO: stereo 3D support and extend pixel encoding colorimetry*/ } -void resource_validate_ctx_destruct(struct validate_context *context) +void dc_resource_validate_ctx_destruct(struct validate_context *context) { int i, j; @@ -2069,7 +2069,7 @@ void resource_validate_ctx_destruct(struct validate_context *context) * Copy src_ctx into dst_ctx and retain all surfaces and streams referenced * by the src_ctx */ -void resource_validate_ctx_copy_construct( +void dc_resource_validate_ctx_copy_construct( const struct validate_context *src_ctx, struct validate_context *dst_ctx) { diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 7d548b4d0299..7de2080e13ed 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -522,6 +522,12 @@ bool dc_validate_guaranteed( const struct dc *dc, const struct dc_stream *stream); +void dc_resource_validate_ctx_copy_construct( + const struct validate_context *src_ctx, + struct validate_context *dst_ctx); + +void dc_resource_validate_ctx_destruct(struct validate_context *context); + /* * Set up streams and links associated to drive sinks * The streams parameter is an absolute set of all active streams. diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index eb9c96634578..b1987cab9751 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -141,12 +141,6 @@ void resource_validate_ctx_update_pointer_after_copy( const struct validate_context *src_ctx, struct validate_context *dst_ctx); -void resource_validate_ctx_copy_construct( - const struct validate_context *src_ctx, - struct validate_context *dst_ctx); - -void resource_validate_ctx_destruct(struct validate_context *context); - enum dc_status resource_map_clock_resources( const struct core_dc *dc, struct validate_context *context); -- cgit From 07d72b39bc861b644ea8f6037e0c6a9836050306 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Wed, 29 Mar 2017 11:22:05 -0400 Subject: drm/amd/display: Return context from validate_context This will allow us to carry it from check to commit Signed-off-by: Harry Wentland Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 26 +++++++++++----- drivers/gpu/drm/amd/display/dc/core/dc.c | 36 +++++++++++++++++----- drivers/gpu/drm/amd/display/dc/dc.h | 5 +++ 3 files changed, 52 insertions(+), 15 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index d8718e2ac207..fb3cc57c98d5 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -1384,6 +1384,7 @@ int amdgpu_dm_connector_mode_valid( /* TODO: Unhardcode stream count */ struct dc_stream *stream; struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + struct validate_context *context; if ((mode->flags & DRM_MODE_FLAG_INTERLACE) || (mode->flags & DRM_MODE_FLAG_DBLSCAN)) @@ -1418,8 +1419,13 @@ int amdgpu_dm_connector_mode_valid( stream->src.height = mode->vdisplay; stream->dst = stream->src; - if (dc_validate_resources(adev->dm.dc, &val_set, 1)) + context = dc_get_validate_context(adev->dm.dc, &val_set, 1); + + if (context) { result = MODE_OK; + dc_resource_validate_ctx_destruct(context); + dm_free(context); + } dc_stream_release(stream); @@ -2842,6 +2848,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, struct amdgpu_device *adev = dev->dev_private; struct dc *dc = adev->dm.dc; bool need_to_validate = false; + struct validate_context *context; ret = drm_atomic_helper_check(dev, state); @@ -3064,15 +3071,20 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, } } - if (need_to_validate == false || set_count == 0 || - dc_validate_resources(dc, set, set_count)) + context = dc_get_validate_context(dc, set, set_count); + + if (need_to_validate == false || set_count == 0 || context) ret = 0; - for (i = 0; i < set_count; i++) { - for (j = 0; j < set[i].surface_count; j++) { - dc_surface_release(set[i].surfaces[j]); - } + if (context) { + dc_resource_validate_ctx_destruct(context); + dm_free(context); } + + for (i = 0; i < set_count; i++) + for (j = 0; j < set[i].surface_count; j++) + dc_surface_release(set[i].surfaces[j]); + for (i = 0; i < new_stream_count; i++) dc_stream_release(new_streams[i]); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 5620fe361173..64b5216fb920 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -635,7 +635,7 @@ static bool is_validation_required( return false; } -bool dc_validate_resources( +struct validate_context *dc_get_validate_context( const struct dc *dc, const struct dc_validation_set set[], uint8_t set_count) @@ -644,31 +644,51 @@ bool dc_validate_resources( enum dc_status result = DC_ERROR_UNEXPECTED; struct validate_context *context; - if (!is_validation_required(core_dc, set, set_count)) - return true; - context = dm_alloc(sizeof(struct validate_context)); if(context == NULL) goto context_alloc_fail; + if (!is_validation_required(core_dc, set, set_count)) { + dc_resource_validate_ctx_copy_construct(core_dc->current_context, context); + return context; + } + result = core_dc->res_pool->funcs->validate_with_context( core_dc, set, set_count, context); - dc_resource_validate_ctx_destruct(context); - dm_free(context); - context_alloc_fail: if (result != DC_OK) { dm_logger_write(core_dc->ctx->logger, LOG_WARNING, "%s:resource validation failed, dc_status:%d\n", __func__, result); + + dc_resource_validate_ctx_destruct(context); + dm_free(context); + context = NULL; } - return (result == DC_OK); + return context; } +bool dc_validate_resources( + const struct dc *dc, + const struct dc_validation_set set[], + uint8_t set_count) +{ + struct validate_context *ctx; + + ctx = dc_get_validate_context(dc, set, set_count); + if (ctx) { + dc_resource_validate_ctx_destruct(ctx); + dm_free(ctx); + return true; + } + + return false; +} + bool dc_validate_guaranteed( const struct dc *dc, const struct dc_stream *stream) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 7de2080e13ed..1b3fd79ce624 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -505,6 +505,11 @@ struct dc_validation_set { * After this call: * No hardware is programmed for call. Only validation is done. */ +struct validate_context *dc_get_validate_context( + const struct dc *dc, + const struct dc_validation_set set[], + uint8_t set_count); + bool dc_validate_resources( const struct dc *dc, const struct dc_validation_set set[], -- cgit From e6fbd5df0e4e1cf644ddfd50d1df27e5e4ad2220 Mon Sep 17 00:00:00 2001 From: Shirish S Date: Wed, 26 Apr 2017 22:36:01 -0400 Subject: drm/amd/display: initialize YUV plane capabilities This patch populates the YUV surface configurations. Tests: (On Chromium OS for Stoney Only) builds without any errors. Signed-off-by: Shirish S Reviewed-by: Tony Cheng Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 62 ++++++++++++++++------ 1 file changed, 45 insertions(+), 17 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index fb3cc57c98d5..225b8e6b673f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -462,9 +462,6 @@ static void fill_plane_attributes_from_fb( &tiling_flags, addReq == true ? &fb_location:NULL); - surface->address.type = PLN_ADDR_TYPE_GRAPHICS; - surface->address.grph.addr.low_part = lower_32_bits(fb_location); - surface->address.grph.addr.high_part = upper_32_bits(fb_location); switch (fb->format->format) { case DRM_FORMAT_C8: @@ -485,12 +482,55 @@ static void fill_plane_attributes_from_fb( case DRM_FORMAT_ABGR2101010: surface->format = SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010; break; + case DRM_FORMAT_YUV420: + surface->format = SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr; + break; + case DRM_FORMAT_YVU420: + surface->format = SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb; + break; default: DRM_ERROR("Unsupported screen format %s\n", drm_get_format_name(fb->format->format, &format_name)); return; } + if (surface->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) { + surface->address.type = PLN_ADDR_TYPE_GRAPHICS; + surface->address.grph.addr.low_part = lower_32_bits(fb_location); + surface->address.grph.addr.high_part = upper_32_bits(fb_location); + surface->plane_size.grph.surface_size.x = 0; + surface->plane_size.grph.surface_size.y = 0; + surface->plane_size.grph.surface_size.width = fb->width; + surface->plane_size.grph.surface_size.height = fb->height; + surface->plane_size.grph.surface_pitch = + fb->pitches[0] / fb->format->cpp[0]; + /* TODO: unhardcode */ + surface->color_space = COLOR_SPACE_SRGB; + + } else { + surface->address.type = PLN_ADDR_TYPE_VIDEO_PROGRESSIVE; + surface->address.video_progressive.luma_addr.low_part + = lower_32_bits(fb_location); + surface->address.video_progressive.chroma_addr.high_part + = upper_32_bits(fb_location); + surface->plane_size.video.luma_size.x = 0; + surface->plane_size.video.luma_size.y = 0; + surface->plane_size.video.luma_size.width = fb->width; + surface->plane_size.video.luma_size.height = fb->height; + /* TODO: unhardcode */ + surface->plane_size.video.luma_pitch = fb->pitches[0] / 4; + + surface->plane_size.video.chroma_size.x = 0; + surface->plane_size.video.chroma_size.y = 0; + surface->plane_size.video.chroma_size.width = fb->width; + surface->plane_size.video.chroma_size.height = fb->height; + surface->plane_size.video.chroma_pitch = + fb->pitches[0] / 4; + + /* TODO: unhardcode */ + surface->color_space = COLOR_SPACE_YCBCR709; + } + memset(&surface->tiling_info, 0, sizeof(surface->tiling_info)); /* Fill GFX params */ @@ -541,20 +581,10 @@ static void fill_plane_attributes_from_fb( surface->tiling_info.gfx9.shaderEnable = 1; } - - surface->plane_size.grph.surface_size.x = 0; - surface->plane_size.grph.surface_size.y = 0; - surface->plane_size.grph.surface_size.width = fb->width; - surface->plane_size.grph.surface_size.height = fb->height; - surface->plane_size.grph.surface_pitch = - fb->pitches[0] / fb->format->cpp[0]; - surface->visible = true; surface->scaling_quality.h_taps_c = 0; surface->scaling_quality.v_taps_c = 0; - /* TODO: unhardcode */ - surface->color_space = COLOR_SPACE_SRGB; /* is this needed? is surface zeroed at allocation? */ surface->scaling_quality.h_taps = 0; surface->scaling_quality.v_taps = 0; @@ -1670,10 +1700,8 @@ static uint32_t rgb_formats[] = { }; static uint32_t yuv_formats[] = { - DRM_FORMAT_YUYV, - DRM_FORMAT_YVYU, - DRM_FORMAT_UYVY, - DRM_FORMAT_VYUY, + DRM_FORMAT_YUV420, + DRM_FORMAT_YVU420, }; int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, -- cgit From 110ff5439a3e1d19acf02ec5b819e6802c4b8b83 Mon Sep 17 00:00:00 2001 From: Shirish S Date: Tue, 25 Apr 2017 12:26:57 +0530 Subject: drm/amd/display: update the YUV plane offsets This patch updates the planes default offsets to the appropriate ones, and aligns the pitch to 64 bits. BUG=SWDEV-119421 TEST=Boots to UI on jadeite TEST= plane_test --format AR24 --size 500x50 -p --format YV12 --size 500x500 plane_test --format AR24 --size 500x50 -p --format YV12 --size 1280x720 plane_test --format AR24 --size 500x50 -p --format YV12 --size 1366x768 Signed-off-by: Shirish S Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 225b8e6b673f..851fbd32fc8d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -511,21 +511,21 @@ static void fill_plane_attributes_from_fb( surface->address.type = PLN_ADDR_TYPE_VIDEO_PROGRESSIVE; surface->address.video_progressive.luma_addr.low_part = lower_32_bits(fb_location); - surface->address.video_progressive.chroma_addr.high_part - = upper_32_bits(fb_location); + surface->address.video_progressive.chroma_addr.low_part + = lower_32_bits(fb_location) + + (fb->width * fb->height); surface->plane_size.video.luma_size.x = 0; surface->plane_size.video.luma_size.y = 0; surface->plane_size.video.luma_size.width = fb->width; surface->plane_size.video.luma_size.height = fb->height; /* TODO: unhardcode */ - surface->plane_size.video.luma_pitch = fb->pitches[0] / 4; + surface->plane_size.video.luma_pitch = ALIGN(fb->width, 64); surface->plane_size.video.chroma_size.x = 0; surface->plane_size.video.chroma_size.y = 0; - surface->plane_size.video.chroma_size.width = fb->width; - surface->plane_size.video.chroma_size.height = fb->height; - surface->plane_size.video.chroma_pitch = - fb->pitches[0] / 4; + surface->plane_size.video.chroma_size.width = fb->width / 2; + surface->plane_size.video.chroma_size.height = fb->height / 2; + surface->plane_size.video.chroma_pitch = ALIGN(fb->width, 64) / 2; /* TODO: unhardcode */ surface->color_space = COLOR_SPACE_YCBCR709; -- cgit From 0430d52b7680fd093c0db8cf41e6ee1d58bae96e Mon Sep 17 00:00:00 2001 From: Shirish S Date: Wed, 12 Apr 2017 16:23:25 +0530 Subject: drm/amd/display: make dc_commit_surfaces_to_stream() re-entrant dc_commit_surfaces_to_stream() function currently is handle's only one plane at a time. This will not work if multiple planes have to be set to a crtc. The functionality of dc_commit_surfaces_to_stream() with this patch is slit into 1. Accumulate and initialise all the surfaces that needs to be set to a crtc. 2. Update the intialised set of surfaces to the steam in one go. Hence dc_commit_surfaces_to_stream() is renamed to init_surfaces(). Once all the planes requested by user space are initialised, dc_commit_surfaces_to_stream() shall sequentially populates *updates, *flip_addr, *plane_info and *scaling_info for all surfaces. BUG: SWDEV-119421 TEST: (On Chromium OS for Stoney Only) * Chromium UI comes up, on both eDP & DP. * 'new_surface_count' now changes as per user input for e.g for all below run tests its 2, without this patch for the below tests it used to be 1 * Executed below tests to see YUV(underlay) & RGB planes on eDP plane_test --format XR24 --size 500x100 -p --format YV12 --size 500x500 plane_test --format AR24 --size 500x50 -p --format YV12 --size 150x150 plane_test --format AR24 --size 500x50 -p --format YV12 --size 1366x768 Signed-off-by: Harry Wentland Signed-off-by: Shirish S Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 71 ++++++++++++++-------- 1 file changed, 44 insertions(+), 27 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 851fbd32fc8d..0f09e8b903d3 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -730,19 +730,20 @@ static void update_stream_scaling_settings( } -static void dm_dc_surface_commit( - struct dc *dc, - struct drm_crtc *crtc) +static void add_surface(struct dc *dc, + struct drm_crtc *crtc, + struct drm_plane *plane, + const struct dc_surface **dc_surfaces) { struct dc_surface *dc_surface; - const struct dc_surface *dc_surfaces[1]; struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); const struct dc_stream *dc_stream = acrtc->stream; unsigned long flags; spin_lock_irqsave(&crtc->dev->event_lock, flags); if (acrtc->pflip_status != AMDGPU_FLIP_NONE) { - DRM_ERROR("dm_dc_surface_commit: acrtc %d, already busy\n", acrtc->crtc_id); + DRM_ERROR("add_surface: acrtc %d, already busy\n", + acrtc->crtc_id); spin_unlock_irqrestore(&crtc->dev->event_lock, flags); /* In comit tail framework this cannot happen */ BUG_ON(0); @@ -770,22 +771,11 @@ static void dm_dc_surface_commit( fill_plane_attributes( crtc->dev->dev_private, dc_surface, - crtc->primary->state, + plane->state, true); - dc_surfaces[0] = dc_surface; - - if (false == dc_commit_surfaces_to_stream( - dc, - dc_surfaces, - 1, - dc_stream)) { - dm_error( - "%s: Failed to attach surface!\n", - __func__); - } + *dc_surfaces = dc_surface; - dc_surface_release(dc_surface); fail: return; } @@ -2385,11 +2375,16 @@ static void amdgpu_dm_do_flip( } void dc_commit_surfaces(struct drm_atomic_state *state, - struct drm_device *dev, struct amdgpu_display_manager *dm) + struct drm_device *dev, + struct amdgpu_display_manager *dm, + struct drm_crtc *pcrtc) { uint32_t i; struct drm_plane *plane; struct drm_plane_state *old_plane_state; + const struct dc_stream *dc_stream_attach; + const struct dc_surface *dc_surfaces_constructed[MAX_SURFACES]; + int planes_count = 0; /* update planes when needed */ for_each_plane_in_state(state, plane, old_plane_state, i) { @@ -2398,6 +2393,7 @@ void dc_commit_surfaces(struct drm_atomic_state *state, struct drm_framebuffer *fb = plane_state->fb; struct drm_connector *connector; struct dm_connector_state *dm_state = NULL; + struct amdgpu_crtc *acrtc_attach; enum dm_commit_action action; bool pflip_needed; @@ -2439,9 +2435,26 @@ void dc_commit_surfaces(struct drm_atomic_state *state, */ if (!dm_state) continue; + if (crtc == pcrtc) { + add_surface(dm->dc, crtc, plane, + &dc_surfaces_constructed[planes_count]); + acrtc_attach = to_amdgpu_crtc(crtc); + dc_stream_attach = acrtc_attach->stream; + planes_count++; + } + } + } - dm_dc_surface_commit(dm->dc, crtc); + if (planes_count) { + if (false == dc_commit_surfaces_to_stream(dm->dc, + dc_surfaces_constructed, + planes_count, + dc_stream_attach)) { + dm_error("%s: Failed to attach surface!\n", __func__); + return; } + for (i = 0; i < planes_count; i++) + dc_surface_release(dc_surfaces_constructed[i]); } } @@ -2453,10 +2466,10 @@ void amdgpu_dm_atomic_commit_tail( struct amdgpu_display_manager *dm = &adev->dm; struct drm_plane *plane; struct drm_plane_state *old_plane_state; - uint32_t i; + uint32_t i, j; uint32_t commit_streams_count = 0; uint32_t new_crtcs_count = 0; - struct drm_crtc *crtc; + struct drm_crtc *crtc, *pcrtc; struct drm_crtc_state *old_crtc_state; const struct dc_stream *commit_streams[MAX_STREAMS]; struct amdgpu_crtc *new_crtcs[MAX_STREAMS]; @@ -2615,8 +2628,9 @@ void amdgpu_dm_atomic_commit_tail( dc_stream_get_status(acrtc->stream)->primary_otg_inst; } - /* update planes when needed */ - dc_commit_surfaces(state, dev, dm); + /* update planes when needed per crtc*/ + for_each_crtc_in_state(state, pcrtc, old_crtc_state, j) + dc_commit_surfaces(state, dev, dm, pcrtc); for (i = 0; i < new_crtcs_count; i++) { /* @@ -2793,15 +2807,18 @@ static uint32_t add_val_sets_surface( const struct dc_stream *stream, const struct dc_surface *surface) { - uint32_t i = 0; + uint32_t i = 0, j = 0; while (i < set_count) { - if (val_sets[i].stream == stream) + if (val_sets[i].stream == stream) { + while (val_sets[i].surfaces[j]) + j++; break; + } ++i; } - val_sets[i].surfaces[val_sets[i].surface_count] = surface; + val_sets[i].surfaces[j] = surface; val_sets[i].surface_count++; return val_sets[i].surface_count; -- cgit From 89aed24c180be9be215923136faebcda0aa344a1 Mon Sep 17 00:00:00 2001 From: Zeyu Fan Date: Mon, 17 Apr 2017 19:02:19 -0400 Subject: drm/amd/display: Block YCbCr formats for eDP. Revert previous change. Signed-off-by: Zeyu Fan Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 1a84ee0105da..812c29982a2e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -1026,9 +1026,13 @@ bool dce110_link_encoder_validate_output_with_stream( break; case SIGNAL_TYPE_DISPLAY_PORT: case SIGNAL_TYPE_DISPLAY_PORT_MST: - case SIGNAL_TYPE_EDP: is_valid = dce110_link_encoder_validate_dp_output( - enc110, &stream->public.timing); + enc110, &stream->public.timing); + break; + case SIGNAL_TYPE_EDP: + is_valid = + (stream->public.timing. + pixel_encoding == PIXEL_ENCODING_RGB) ? true : false; break; case SIGNAL_TYPE_VIRTUAL: is_valid = true; -- cgit From 50f27269b8dd81d73c787dd18ba19a08bec128d3 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 18 Apr 2017 15:43:22 -0400 Subject: drm/amd/display: Fix memory leak in post_update_surfaces Signed-off-by: Harry Wentland Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 64b5216fb920..b1f0a50171af 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -918,6 +918,7 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) int i; struct core_dc *core_dc = DC_TO_CORE(dc); struct validate_context *context = dm_alloc(sizeof(struct validate_context)); + bool result = true; if (!context) { dm_error("%s: failed to create validate ctx\n", __func__); @@ -935,17 +936,19 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) if (!core_dc->res_pool->funcs->validate_bandwidth(core_dc, context)) { BREAK_TO_DEBUGGER(); - return false; + result = false; + goto cleanup; } core_dc->hwss.set_bandwidth(core_dc, context, true); dc_resource_validate_ctx_copy_construct(context, core_dc->current_context); +cleanup: dc_resource_validate_ctx_destruct(context); dm_free(context); - return true; + return result; } bool dc_commit_surfaces_to_stream( -- cgit From 974db151d48b6793fc2b708d1c3f9ceee735fc5a Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Tue, 18 Apr 2017 16:51:39 -0400 Subject: drm/amd/display: remove unnecessary allocation for regamma_params inside opp Signed-off-by: Dmytro Laktyushkin Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_opp.c | 10 +--------- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 6 +++--- drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c | 4 ---- drivers/gpu/drm/amd/display/dc/inc/hw/opp.h | 2 +- 4 files changed, 5 insertions(+), 17 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c index 121ccbb1ad2d..f716a9e8784e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c @@ -987,10 +987,6 @@ bool dce110_opp_construct(struct dce110_opp *opp110, opp110->base.inst = inst; - opp110->base.regamma_params = dm_alloc(sizeof(struct pwl_params)); - if (opp110->base.regamma_params == NULL) - return false; - opp110->regs = regs; opp110->opp_shift = opp_shift; opp110->opp_mask = opp_mask; @@ -1000,12 +996,8 @@ bool dce110_opp_construct(struct dce110_opp *opp110, void dce110_opp_destroy(struct output_pixel_processor **opp) { - if (*opp) { - if ((*opp)->regamma_params) - dm_free((*opp)->regamma_params); - (*opp)->regamma_params = NULL; + if (*opp) dm_free(FROM_DCE11_OPP(*opp)); - } *opp = NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 2fbf6ddcf3be..6b249f5bf1da 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -637,7 +637,7 @@ static bool dce110_set_output_transfer_func( struct output_pixel_processor *opp = pipe_ctx->opp; opp->funcs->opp_power_on_regamma_lut(opp, true); - opp->regamma_params->hw_points_num = GAMMA_HW_POINTS_NUM; + opp->regamma_params.hw_points_num = GAMMA_HW_POINTS_NUM; if (stream->public.out_transfer_func && stream->public.out_transfer_func->type == @@ -646,8 +646,8 @@ static bool dce110_set_output_transfer_func( TRANSFER_FUNCTION_SRGB) { opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_SRGB); } else if (dce110_translate_regamma_to_hw_format( - stream->public.out_transfer_func, opp->regamma_params)) { - opp->funcs->opp_program_regamma_pwl(opp, opp->regamma_params); + stream->public.out_transfer_func, &opp->regamma_params)) { + opp->funcs->opp_program_regamma_pwl(opp, &opp->regamma_params); opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_USER); } else { opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_BYPASS); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c index 95b3d2eb8428..6f8b414cabbc 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c @@ -56,10 +56,6 @@ bool dce110_opp_v_construct(struct dce110_opp *opp110, opp110->base.ctx = ctx; - opp110->base.regamma_params = dm_alloc(sizeof(struct pwl_params)); - if (opp110->base.regamma_params == NULL) - return false; - return true; } diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h index 521bd21eb5df..92c99c3b9002 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h @@ -203,7 +203,7 @@ enum opp_regamma { struct output_pixel_processor { struct dc_context *ctx; uint32_t inst; - struct pwl_params *regamma_params; + struct pwl_params regamma_params; const struct opp_funcs *funcs; }; -- cgit From d4e745e3dbf43ad14759615d0236f6378db1ad4a Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Tue, 18 Apr 2017 15:35:27 -0400 Subject: drm/amd/display: set correct v_total_min and v_total_max for dce. Signed-off-by: Yongqiang Sun Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c | 4 ++-- drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c index 7070aaf9e433..69ae3a83d2fe 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c @@ -393,12 +393,12 @@ void dce110_timing_generator_set_drr( params->vertical_total_min > 0) { set_reg_field_value(v_total_max, - params->vertical_total_max - 1, + params->vertical_total_max, CRTC_V_TOTAL_MAX, CRTC_V_TOTAL_MAX); set_reg_field_value(v_total_min, - params->vertical_total_min - 1, + params->vertical_total_min, CRTC_V_TOTAL_MIN, CRTC_V_TOTAL_MIN); diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c index 1318df7ed47e..6e3e7b6bc58c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c @@ -540,10 +540,10 @@ void dce120_timing_generator_set_drr( CRTC_REG_UPDATE( CRTC0_CRTC_V_TOTAL_MIN, - CRTC_V_TOTAL_MIN, params->vertical_total_min - 1); + CRTC_V_TOTAL_MIN, params->vertical_total_min); CRTC_REG_UPDATE( CRTC0_CRTC_V_TOTAL_MAX, - CRTC_V_TOTAL_MAX, params->vertical_total_max - 1); + CRTC_V_TOTAL_MAX, params->vertical_total_max); CRTC_REG_SET_N(CRTC0_CRTC_V_TOTAL_CONTROL, 6, FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MIN_SEL), 1, FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MAX_SEL), 1, -- cgit From de37e273df49dd015f6c308668f223327f6cf8fc Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Tue, 18 Apr 2017 17:31:46 -0400 Subject: drm/amd/display: fix memory leak Signed-off-by: Dmytro Laktyushkin Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index b1f0a50171af..1dd9c736aedc 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -918,7 +918,6 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) int i; struct core_dc *core_dc = DC_TO_CORE(dc); struct validate_context *context = dm_alloc(sizeof(struct validate_context)); - bool result = true; if (!context) { dm_error("%s: failed to create validate ctx\n", __func__); @@ -927,28 +926,29 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) dc_resource_validate_ctx_copy_construct(core_dc->current_context, context); post_surface_trace(dc); + for (i = 0; i < context->res_ctx.pool->pipe_count; i++) if (context->res_ctx.pipe_ctx[i].stream == NULL) { context->res_ctx.pipe_ctx[i].pipe_idx = i; core_dc->hwss.power_down_front_end( core_dc, &context->res_ctx.pipe_ctx[i]); } - if (!core_dc->res_pool->funcs->validate_bandwidth(core_dc, context)) { BREAK_TO_DEBUGGER(); - result = false; - goto cleanup; + dc_resource_validate_ctx_destruct(context); + dm_free(context); + return false; } core_dc->hwss.set_bandwidth(core_dc, context, true); - dc_resource_validate_ctx_copy_construct(context, core_dc->current_context); - -cleanup: - dc_resource_validate_ctx_destruct(context); - dm_free(context); + if (core_dc->current_context) { + dc_resource_validate_ctx_destruct(core_dc->current_context); + dm_free(core_dc->current_context); + } + core_dc->current_context = context; - return result; + return true; } bool dc_commit_surfaces_to_stream( @@ -1440,10 +1440,8 @@ void dc_update_surfaces_and_stream(struct dc *dc, return; fail: - if (core_dc->current_context != context) { - dc_resource_validate_ctx_destruct(context); - dm_free(context); - } + dc_resource_validate_ctx_destruct(context); + dm_free(context); } uint8_t dc_get_current_stream_count(const struct dc *dc) -- cgit From 15350179f2fc3c3b28774b4abcd35c45a5449052 Mon Sep 17 00:00:00 2001 From: Amy Zhang Date: Tue, 18 Apr 2017 17:43:09 -0400 Subject: drm/amd/display: always retrieve PSR cap Signed-off-by: Amy Zhang Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/gpu') 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 913b01cd7159..4ef3fec44d2d 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 @@ -2169,8 +2169,7 @@ static void retrieve_link_cap(struct core_link *link) CONN_DATA_DETECT(link, dpcd_data, sizeof(dpcd_data), "Rx Caps: "); /* TODO: Confirm if need retrieve_psr_link_cap */ - if (link->public.reported_link_cap.link_rate < LINK_RATE_HIGH2) - retrieve_psr_link_cap(link, link->edp_revision); + retrieve_psr_link_cap(link, link->edp_revision); } void detect_dp_sink_caps(struct core_link *link) -- cgit From 6c626ffb1bfa2705e71376fe20bcdc6b89aace85 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Fri, 21 Apr 2017 11:00:43 -0400 Subject: drm/amd/display: Make sure v_total_min and max not less than v_total. Signed-off-by: Yongqiang Sun Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c | 4 ++-- .../gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c | 4 ++-- drivers/gpu/drm/amd/display/modules/freesync/freesync.c | 12 ++++++++++++ 3 files changed, 16 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c index 69ae3a83d2fe..7070aaf9e433 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c @@ -393,12 +393,12 @@ void dce110_timing_generator_set_drr( params->vertical_total_min > 0) { set_reg_field_value(v_total_max, - params->vertical_total_max, + params->vertical_total_max - 1, CRTC_V_TOTAL_MAX, CRTC_V_TOTAL_MAX); set_reg_field_value(v_total_min, - params->vertical_total_min, + params->vertical_total_min - 1, CRTC_V_TOTAL_MIN, CRTC_V_TOTAL_MIN); diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c index 6e3e7b6bc58c..1318df7ed47e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c @@ -540,10 +540,10 @@ void dce120_timing_generator_set_drr( CRTC_REG_UPDATE( CRTC0_CRTC_V_TOTAL_MIN, - CRTC_V_TOTAL_MIN, params->vertical_total_min); + CRTC_V_TOTAL_MIN, params->vertical_total_min - 1); CRTC_REG_UPDATE( CRTC0_CRTC_V_TOTAL_MAX, - CRTC_V_TOTAL_MAX, params->vertical_total_max); + CRTC_V_TOTAL_MAX, params->vertical_total_max - 1); CRTC_REG_SET_N(CRTC0_CRTC_V_TOTAL_CONTROL, 6, FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MIN_SEL), 1, FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MAX_SEL), 1, diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index 94566c0a0e62..5c6de723da5d 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -347,6 +347,7 @@ static void calc_vmin_vmax(struct core_freesync *core_freesync, { unsigned int min_frame_duration_in_ns = 0, max_frame_duration_in_ns = 0; unsigned int index = map_index_from_stream(core_freesync, stream); + uint32_t vtotal = stream->timing.v_total; min_frame_duration_in_ns = ((unsigned int) (div64_u64( (1000000000ULL * 1000000), @@ -362,6 +363,17 @@ static void calc_vmin_vmax(struct core_freesync *core_freesync, *vmin = div64_u64(div64_u64(((unsigned long long)( min_frame_duration_in_ns) * stream->timing.pix_clk_khz), stream->timing.h_total), 1000000); + + /* In case of 4k free sync monitor, vmin or vmax cannot be less than vtotal */ + if (*vmin < vtotal) { + ASSERT(false); + *vmin = vtotal; + } + + if (*vmax < vtotal) { + ASSERT(false); + *vmax = vtotal; + } } static void calc_v_total_from_duration(const struct dc_stream *stream, -- cgit From 03f5c686c3900f74853539cdebe4c25190106402 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Fri, 21 Apr 2017 17:15:40 -0400 Subject: drm/amd/display: USB-c DP-HDMI dongle shows garbage on Sony TV Signed-off-by: Charlene Liu Acked-by: Harry Wentland Reviewed-by: Charlene Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 21 ++++++++++++++++++++- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- drivers/gpu/drm/amd/display/dc/dc_dp_types.h | 8 ++++++-- drivers/gpu/drm/amd/display/dc/dc_types.h | 20 ++++++++++++++++++++ 4 files changed, 47 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') 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 4ef3fec44d2d..953e201dc6bc 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 @@ -1951,14 +1951,33 @@ static void get_active_converter_info( link->dpcd_caps.dongle_type = DISPLAY_DONGLE_DP_HDMI_CONVERTER; + link->dpcd_caps.dongle_caps.dongle_type = link->dpcd_caps.dongle_type; if (ds_port.fields.DETAILED_CAPS) { union dwnstream_port_caps_byte3_hdmi hdmi_caps = {.raw = det_caps[3] }; + union dwnstream_port_caps_byte1 + hdmi_color_caps = {.raw = det_caps[2] }; + link->dpcd_caps.dongle_caps.dp_hdmi_max_pixel_clk = + det_caps[1] * 25000; - link->dpcd_caps.is_dp_hdmi_s3d_converter = + link->dpcd_caps.dongle_caps.is_dp_hdmi_s3d_converter = hdmi_caps.bits.FRAME_SEQ_TO_FRAME_PACK; + link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr422_pass_through = + hdmi_caps.bits.YCrCr422_PASS_THROUGH; + link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr420_pass_through = + hdmi_caps.bits.YCrCr420_PASS_THROUGH; + link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr422_converter = + hdmi_caps.bits.YCrCr422_CONVERSION; + link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr420_converter = + hdmi_caps.bits.YCrCr420_CONVERSION; + + link->dpcd_caps.dongle_caps.dp_hdmi_max_bpc = + hdmi_color_caps.bits.MAX_BITS_PER_COLOR_COMPONENT; + + link->dpcd_caps.dongle_caps.extendedCapValid = true; } + break; } } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 1b3fd79ce624..d35fa01024f8 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -623,7 +623,7 @@ struct dpcd_caps { union sink_count sink_count; /* If dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER, indicates 'Frame Sequential-to-lllFrame Pack' conversion capability.*/ - bool is_dp_hdmi_s3d_converter; + struct dc_dongle_caps dongle_caps; bool allow_invalid_MSA_timing_param; bool panel_mode_edp; diff --git a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h index cd2323a71760..77e2de69cca3 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h @@ -255,7 +255,7 @@ enum dpcd_downstream_port_detailed_type { DOWN_STREAM_DETAILED_DP_PLUS_PLUS }; -union dwnstream_port_caps_byte2 { +union dwnstream_port_caps_byte1 { struct { uint8_t MAX_BITS_PER_COLOR_COMPONENT:2; uint8_t RESERVED:6; @@ -287,7 +287,11 @@ union dwnstream_port_caps_byte3_dvi { union dwnstream_port_caps_byte3_hdmi { struct { uint8_t FRAME_SEQ_TO_FRAME_PACK:1; - uint8_t RESERVED:7; + uint8_t YCrCr422_PASS_THROUGH:1; + uint8_t YCrCr420_PASS_THROUGH:1; + uint8_t YCrCr422_CONVERSION:1; + uint8_t YCrCr420_CONVERSION:1; + uint8_t RESERVED:3; } bits; uint8_t raw; }; diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index e0436e317341..2ba02b50bc18 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -338,6 +338,26 @@ enum { LAYER_INDEX_PRIMARY = -1, }; +enum dpcd_downstream_port_max_bpc { + DOWN_STREAM_MAX_8BPC = 0, + DOWN_STREAM_MAX_10BPC, + DOWN_STREAM_MAX_12BPC, + DOWN_STREAM_MAX_16BPC +}; +struct dc_dongle_caps { + /* dongle type (DP converter, CV smart dongle) */ + enum display_dongle_type dongle_type; + bool extendedCapValid; + /* If dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER, + indicates 'Frame Sequential-to-lllFrame Pack' conversion capability.*/ + bool is_dp_hdmi_s3d_converter; + bool is_dp_hdmi_ycbcr422_pass_through; + bool is_dp_hdmi_ycbcr420_pass_through; + bool is_dp_hdmi_ycbcr422_converter; + bool is_dp_hdmi_ycbcr420_converter; + uint32_t dp_hdmi_max_bpc; + uint32_t dp_hdmi_max_pixel_clk; +}; /* Scaling format */ enum scaling_transformation { SCALING_TRANSFORMATION_UNINITIALIZED, -- cgit From beb16b6a0f921f66472e4946a4955f07942fa9d8 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 21 Apr 2017 09:34:09 -0400 Subject: drm/amd/display: improve cursor programming reliability This change will cache cursor attributes and reprogram them when enabling cursor after power gating if the attributes were not yet reprogrammed Signed-off-by: Dmytro Laktyushkin Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 55 ++++++++++------------ drivers/gpu/drm/amd/display/dc/dc.h | 2 +- drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h | 2 +- .../drm/amd/display/dc/dce110/dce110_ipp_cursor.c | 4 +- drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp.h | 2 +- .../drm/amd/display/dc/dce120/dce120_ipp_cursor.c | 4 +- drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h | 4 +- 7 files changed, 32 insertions(+), 41 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 3dbd6c0885d8..23627b14c16c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -182,7 +182,6 @@ bool dc_stream_set_cursor_attributes( struct core_stream *stream; struct core_dc *core_dc; struct resource_context *res_ctx; - bool ret = false; if (NULL == dc_stream) { dm_error("DC: dc_stream is NULL!\n"); @@ -200,28 +199,26 @@ bool dc_stream_set_cursor_attributes( for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; - if ((pipe_ctx->stream == stream) && - (pipe_ctx->ipp != NULL)) { - struct input_pixel_processor *ipp = pipe_ctx->ipp; + if (pipe_ctx->stream != stream || !pipe_ctx->ipp) + continue; + if (pipe_ctx->top_pipe && pipe_ctx->surface != pipe_ctx->top_pipe->surface) + continue; - if (ipp->funcs->ipp_cursor_set_attributes( - ipp, attributes)) - ret = true; - } + pipe_ctx->ipp->funcs->ipp_cursor_set_attributes( + pipe_ctx->ipp, attributes); } - return ret; + return true; } bool dc_stream_set_cursor_position( const struct dc_stream *dc_stream, - struct dc_cursor_position *position) + const struct dc_cursor_position *position) { int i; struct core_stream *stream; struct core_dc *core_dc; struct resource_context *res_ctx; - bool ret = false; if (NULL == dc_stream) { dm_error("DC: dc_stream is NULL!\n"); @@ -239,27 +236,27 @@ bool dc_stream_set_cursor_position( for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; + struct input_pixel_processor *ipp = pipe_ctx->ipp; + struct dc_cursor_position pos_cpy = *position; + struct dc_cursor_mi_param param = { + .pixel_clk_khz = dc_stream->timing.pix_clk_khz, + .ref_clk_khz = res_ctx->pool->ref_clock_inKhz, + .viewport_x_start = pipe_ctx->scl_data.viewport.x, + .viewport_width = pipe_ctx->scl_data.viewport.width, + .h_scale_ratio = pipe_ctx->scl_data.ratios.horz + }; + + if (pipe_ctx->stream != stream || + !pipe_ctx->ipp || !pipe_ctx->surface) + continue; - if (pipe_ctx->stream == stream && - pipe_ctx->ipp && pipe_ctx->surface) { - struct input_pixel_processor *ipp = pipe_ctx->ipp; - struct dc_cursor_mi_param param = { - .pixel_clk_khz = dc_stream->timing.pix_clk_khz, - .ref_clk_khz = res_ctx->pool->ref_clock_inKhz, - .viewport_x_start = pipe_ctx->scl_data.viewport.x, - .viewport_width = pipe_ctx->scl_data.viewport.width, - .h_scale_ratio = pipe_ctx->scl_data.ratios.horz, - }; - - if (pipe_ctx->top_pipe && pipe_ctx->surface != pipe_ctx->top_pipe->surface) - position->enable = false; - - ipp->funcs->ipp_cursor_set_position(ipp, position, ¶m); - ret = true; - } + if (pipe_ctx->top_pipe && pipe_ctx->surface != pipe_ctx->top_pipe->surface) + pos_cpy.enable = false; + + ipp->funcs->ipp_cursor_set_position(ipp, &pos_cpy, ¶m); } - return ret; + return true; } uint32_t dc_stream_get_vblank_counter(const struct dc_stream *dc_stream) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index d35fa01024f8..5629e3ca6336 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -764,7 +764,7 @@ bool dc_stream_set_cursor_attributes( bool dc_stream_set_cursor_position( const struct dc_stream *stream, - struct dc_cursor_position *position); + const struct dc_cursor_position *position); /* Newer interfaces */ struct dc_cursor { diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h index a374ef2c9d0b..434fe2f5a9d7 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h @@ -54,7 +54,7 @@ void dce110_ipp_cursor_set_position( const struct dc_cursor_position *position, const struct dc_cursor_mi_param *param); -bool dce110_ipp_cursor_set_attributes( +void dce110_ipp_cursor_set_attributes( struct input_pixel_processor *ipp, const struct dc_cursor_attributes *attributes); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_cursor.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_cursor.c index 5b230b17fc5c..f712916563b9 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_cursor.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_cursor.c @@ -95,7 +95,7 @@ void dce110_ipp_cursor_set_position( lock(ipp110, false); } -bool dce110_ipp_cursor_set_attributes( +void dce110_ipp_cursor_set_attributes( struct input_pixel_processor *ipp, const struct dc_cursor_attributes *attributes) { @@ -122,8 +122,6 @@ bool dce110_ipp_cursor_set_attributes( /* Unlock Cursor registers. */ lock(ipp110, false); - - return true; } static void enable( diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp.h b/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp.h index 4b326bcb4600..7f645fde7064 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp.h +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp.h @@ -42,7 +42,7 @@ void dce120_ipp_cursor_set_position( const struct dc_cursor_position *position, const struct dc_cursor_mi_param *param); -bool dce120_ipp_cursor_set_attributes( +void dce120_ipp_cursor_set_attributes( struct input_pixel_processor *ipp, const struct dc_cursor_attributes *attributes); diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp_cursor.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp_cursor.c index 15671fd2cb9c..dc81d320f6e5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp_cursor.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp_cursor.c @@ -160,7 +160,7 @@ void dce120_ipp_cursor_set_position( lock(ipp110, false); } -bool dce120_ipp_cursor_set_attributes( +void dce120_ipp_cursor_set_attributes( struct input_pixel_processor *ipp, const struct dc_cursor_attributes *attributes) { @@ -189,7 +189,5 @@ bool dce120_ipp_cursor_set_attributes( /* Unlock Cursor registers. */ lock(ipp110, false); - - return true; } diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h index 0457bc7a44d4..7928e230eefb 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h @@ -37,8 +37,6 @@ struct input_pixel_processor { struct dc_context *ctx; unsigned int inst; const struct ipp_funcs *funcs; - - unsigned int cusor_width; }; enum ipp_prescale_mode { @@ -88,7 +86,7 @@ struct ipp_funcs { const struct dc_cursor_position *position, const struct dc_cursor_mi_param *param); - bool (*ipp_cursor_set_attributes)( + void (*ipp_cursor_set_attributes)( struct input_pixel_processor *ipp, const struct dc_cursor_attributes *attributes); -- cgit From d27383a2b5719be60ac86deae30e89755f868a07 Mon Sep 17 00:00:00 2001 From: Zeyu Fan Date: Fri, 21 Apr 2017 10:55:01 -0400 Subject: drm/amd/display: Make dc_link param const in set_drive_settings Signed-off-by: Zeyu Fan Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 2 +- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') 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 953e201dc6bc..17286465e850 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 @@ -605,7 +605,7 @@ static bool is_max_vs_reached( } void dc_link_dp_set_drive_settings( - struct dc_link *link, + const struct dc_link *link, struct link_training_settings *lt_settings) { struct core_link *core_link = DC_LINK_TO_CORE(link); diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 5629e3ca6336..a2a9e4ed393c 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -691,7 +691,7 @@ void dc_link_remove_remote_sink( void dc_link_set_sink(const struct dc_link *link, struct dc_sink *sink); void dc_link_dp_set_drive_settings( - struct dc_link *link, + const struct dc_link *link, struct link_training_settings *lt_settings); bool dc_link_dp_perform_link_training( -- cgit From 94267b3df7ee00f21fa0ff7d618ca7e0574db5ed Mon Sep 17 00:00:00 2001 From: Sylvia Tsai Date: Fri, 21 Apr 2017 15:29:55 -0400 Subject: drm/amd/display: PSR Refactor - Refacotr PSR to follow correct module pattern - fix eDP only working on sink index 0. Signed-off-by: Sylvia Tsai Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 74 +++++++++------------- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 22 +++---- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 53 +--------------- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/dc.h | 17 +++-- drivers/gpu/drm/amd/display/dc/dc_types.h | 24 +++---- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 18 +++++- .../display/dc/dce110/dce110_timing_generator.c | 16 ----- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 1 + drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 2 +- .../drm/amd/display/modules/freesync/freesync.c | 14 +++- 11 files changed, 93 insertions(+), 150 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 1dd9c736aedc..93c936d92f5a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -199,6 +199,32 @@ static bool set_gamut_remap(struct dc *dc, return ret; } +static void set_static_screen_events(struct dc *dc, + const struct dc_stream **stream, + int num_streams, + const struct dc_static_screen_events *events) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + int i = 0; + int j = 0; + struct pipe_ctx *pipes_affected[MAX_PIPES]; + int num_pipes_affected = 0; + + for (i = 0; i < num_streams; i++) { + struct core_stream *core_stream = DC_STREAM_TO_CORE(stream[i]); + + for (j = 0; j < MAX_PIPES; j++) { + if (core_dc->current_context->res_ctx.pipe_ctx[j].stream + == core_stream) { + pipes_affected[num_pipes_affected++] = + &core_dc->current_context->res_ctx.pipe_ctx[j]; + } + } + } + + core_dc->hwss.set_static_screen_control(pipes_affected, num_pipes_affected, events); +} + /* This function is not expected to fail, proper implementation of * validation will prevent this from ever being called for unsupported * configurations. @@ -240,45 +266,6 @@ static void stream_update_scaling( } } -static bool set_psr_enable(struct dc *dc, bool enable) -{ - struct core_dc *core_dc = DC_TO_CORE(dc); - int i; - - for (i = 0; i < core_dc->link_count; i++) - dc_link_set_psr_enable(&core_dc->links[i]->public, - enable); - - return true; -} - - -static bool setup_psr(struct dc *dc, const struct dc_stream *stream) -{ - struct core_dc *core_dc = DC_TO_CORE(dc); - struct core_stream *core_stream = DC_STREAM_TO_CORE(stream); - struct pipe_ctx *pipes; - int i; - unsigned int underlay_idx = core_dc->res_pool->underlay_pipe_index; - - for (i = 0; i < core_dc->link_count; i++) { - if (core_stream->sink->link == core_dc->links[i]) - dc_link_setup_psr(&core_dc->links[i]->public, - stream); - } - - for (i = 0; i < MAX_PIPES; i++) { - if (core_dc->current_context->res_ctx.pipe_ctx[i].stream - == core_stream && i != underlay_idx) { - pipes = &core_dc->current_context->res_ctx.pipe_ctx[i]; - core_dc->hwss.set_static_screen_control(&pipes, 1, - 0x182); - } - } - - return true; -} - static void set_drive_settings(struct dc *dc, struct link_training_settings *lt_settings, const struct dc_link *link) @@ -359,15 +346,12 @@ static void allocate_dc_stream_funcs(struct core_dc *core_dc) stream_adjust_vmin_vmax; } + core_dc->public.stream_funcs.set_static_screen_events = + set_static_screen_events; + core_dc->public.stream_funcs.set_gamut_remap = set_gamut_remap; - core_dc->public.stream_funcs.set_psr_enable = - set_psr_enable; - - core_dc->public.stream_funcs.setup_psr = - setup_psr; - core_dc->public.link_funcs.set_drive_settings = set_drive_settings; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 426f7f8187a6..6f78403e2d64 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1430,14 +1430,14 @@ bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable) struct core_dc *core_dc = DC_TO_CORE(ctx->dc); struct dmcu *dmcu = core_dc->res_pool->dmcu; - if (dmcu != NULL && dc_link->psr_caps.psr_version > 0) + if (dmcu != NULL && link->psr_enabled) dmcu->funcs->set_psr_enable(dmcu, enable); return true; } bool dc_link_setup_psr(const struct dc_link *dc_link, - const struct dc_stream *stream) + const struct dc_stream *stream, struct psr_config *psr_config) { struct core_link *link = DC_LINK_TO_CORE(dc_link); struct dc_context *ctx = link->ctx; @@ -1449,10 +1449,8 @@ bool dc_link_setup_psr(const struct dc_link *dc_link, psr_context.controllerId = CONTROLLER_ID_UNDEFINED; - if (dc_link != NULL && - dmcu != NULL && - dc_link->psr_caps.psr_version > 0) { + dmcu != NULL) { /* updateSinkPsrDpcdConfig*/ union dpcd_psr_configuration psr_configuration; @@ -1461,10 +1459,10 @@ bool dc_link_setup_psr(const struct dc_link *dc_link, psr_configuration.bits.ENABLE = 1; psr_configuration.bits.CRC_VERIFICATION = 1; psr_configuration.bits.FRAME_CAPTURE_INDICATION = - dc_link->psr_caps.psr_frame_capture_indication_req; + psr_config->psr_frame_capture_indication_req; /* Check for PSR v2*/ - if (dc_link->psr_caps.psr_version == 0x2) { + if (psr_config->psr_version == 0x2) { /* For PSR v2 selective update. * Indicates whether sink should start capturing * immediately following active scan line, @@ -1512,14 +1510,13 @@ bool dc_link_setup_psr(const struct dc_link *dc_link, stream->timing.v_total), stream->timing.h_total); - psr_context.psrSupportedDisplayConfig = - (dc_link->psr_caps.psr_version > 0) ? true : false; + psr_context.psrSupportedDisplayConfig = true; psr_context.psrExitLinkTrainingRequired = - dc_link->psr_caps.psr_exit_link_training_required; + psr_config->psr_exit_link_training_required; psr_context.sdpTransmitLineNumDeadline = - dc_link->psr_caps.psr_sdp_transmit_line_num_deadline; + psr_config->psr_sdp_transmit_line_num_deadline; psr_context.psrFrameCaptureIndicationReq = - dc_link->psr_caps.psr_frame_capture_indication_req; + psr_config->psr_frame_capture_indication_req; psr_context.skipPsrWaitForPllLock = 0; /* only = 1 in KV */ @@ -1550,6 +1547,7 @@ bool dc_link_setup_psr(const struct dc_link *dc_link, */ psr_context.frame_delay = 0; + link->psr_enabled = true; dmcu->funcs->setup_psr(dmcu, link, &psr_context); return true; } else 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 17286465e850..f883fdb820c8 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 @@ -1478,7 +1478,7 @@ static bool handle_hpd_irq_psr_sink(const struct core_link *link) { union dpcd_psr_configuration psr_configuration; - if (link->public.psr_caps.psr_version == 0) + if (!link->psr_enabled) return false; dm_helpers_dp_read_dpcd( @@ -2060,36 +2060,6 @@ static void dp_wa_power_up_0010FA(struct core_link *link, uint8_t *dpcd_data, link->wa_flags.dp_keep_receiver_powered = false; } -static void retrieve_psr_link_cap(struct core_link *link, - enum edp_revision edp_revision) -{ - if (edp_revision >= EDP_REVISION_13) { - core_link_read_dpcd(link, - DP_PSR_SUPPORT, - (uint8_t *)(&link->public.psr_caps), - sizeof(link->public.psr_caps)); - if (link->public.psr_caps.psr_version != 0) { - unsigned char psr_capability = 0; - - core_link_read_dpcd(link, - DP_PSR_CAPS, - &psr_capability, - sizeof(psr_capability)); - /* Bit 0 determines whether fast link training is - * required on PSR exit. If set to 0, link training - * is required. If set to 1, sink must lock within - * five Idle Patterns after Main Link is turned on. - */ - link->public.psr_caps.psr_exit_link_training_required - = !(psr_capability & 0x1); - - psr_capability = (psr_capability >> 1) & 0x7; - link->public.psr_caps.psr_rfb_setup_time = - 55 * (6 - psr_capability); - } - } -} - static void retrieve_link_cap(struct core_link *link) { uint8_t dpcd_data[DP_TRAINING_AUX_RD_INTERVAL - DP_DPCD_REV + 1]; @@ -2157,38 +2127,17 @@ static void retrieve_link_cap(struct core_link *link) link->dpcd_caps.panel_mode_edp = edp_config_cap.bits.ALT_SCRAMBLER_RESET; - link->edp_revision = EDP_REVISION_11; - link->public.test_pattern_enabled = false; link->public.compliance_test_state.raw = 0; - link->public.psr_caps.psr_exit_link_training_required = false; - link->public.psr_caps.psr_frame_capture_indication_req = false; - link->public.psr_caps.psr_rfb_setup_time = 0; - link->public.psr_caps.psr_sdp_transmit_line_num_deadline = 0; - link->public.psr_caps.psr_version = 0; - /* read sink count */ core_link_read_dpcd(link, DP_SINK_COUNT, &link->dpcd_caps.sink_count.raw, sizeof(link->dpcd_caps.sink_count.raw)); - /* Display control registers starting at DPCD 700h are only valid and - * enabled if this eDP config cap bit is set. */ - if (edp_config_cap.bits.DPCD_DISPLAY_CONTROL_CAPABLE) { - /* Read the Panel's eDP revision at DPCD 700h. */ - core_link_read_dpcd(link, - DP_EDP_DPCD_REV, - (uint8_t *)(&link->edp_revision), - sizeof(link->edp_revision)); - } - /* Connectivity log: detection */ CONN_DATA_DETECT(link, dpcd_data, sizeof(dpcd_data), "Rx Caps: "); - - /* TODO: Confirm if need retrieve_psr_link_cap */ - retrieve_psr_link_cap(link, link->edp_revision); } void detect_dp_sink_caps(struct core_link *link) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 2e12a0ba5ddf..cdb98d5f7caa 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -2015,7 +2015,7 @@ static void set_vsc_info_packet( unsigned int vscPacketRevision = 0; unsigned int i; - if (stream->sink->link->public.psr_caps.psr_version != 0) { + if (stream->sink->link->psr_enabled) { vscPacketRevision = 2; } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index a2a9e4ed393c..d12aa726164e 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -82,6 +82,12 @@ struct dc_surface_dcc_cap { }; }; +struct dc_static_screen_events { + bool cursor_update; + bool surface_update; + bool overlay_update; +}; + /* Forward declaration*/ struct dc; struct dc_surface; @@ -102,10 +108,14 @@ struct dc_stream_funcs { const struct dc_stream *dc_stream, const struct rect *src, const struct rect *dst); + bool (*set_gamut_remap)(struct dc *dc, const struct dc_stream **stream, int num_streams); - bool (*set_psr_enable)(struct dc *dc, bool enable); - bool (*setup_psr)(struct dc *dc, const struct dc_stream *stream); + + void (*set_static_screen_events)(struct dc *dc, + const struct dc_stream **stream, + int num_streams, + const struct dc_static_screen_events *events); }; struct link_training_settings; @@ -604,7 +614,6 @@ struct dc_link { uint8_t ddc_hw_inst; uint8_t link_enc_hw_inst; - struct psr_caps psr_caps; bool test_pattern_enabled; union compliance_test_state compliance_test_state; @@ -657,7 +666,7 @@ bool dc_link_set_backlight_level(const struct dc_link *dc_link, uint32_t level, bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable); bool dc_link_setup_psr(const struct dc_link *dc_link, - const struct dc_stream *stream); + const struct dc_stream *stream, struct psr_config *psr_config); /* Request DC to detect if there is a Panel connected. * boot - If this call is during initial boot. diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 2ba02b50bc18..d2f3b9fd7a30 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -484,6 +484,15 @@ struct freesync_context { unsigned int nominal_refresh_in_micro_hz; }; +struct psr_config { + unsigned char psr_version; + unsigned int psr_rfb_setup_time; + bool psr_exit_link_training_required; + + bool psr_frame_capture_indication_req; + unsigned int psr_sdp_transmit_line_num_deadline; +}; + struct colorspace_transform { struct fixed31_32 matrix[12]; bool enable_remap; @@ -494,21 +503,6 @@ struct csc_transform { bool enable_adjustment; }; -struct psr_caps { - /* These parameters are from PSR capabilities reported by Sink DPCD */ - unsigned char psr_version; - unsigned int psr_rfb_setup_time; - bool psr_exit_link_training_required; - - /* These parameters are calculated in Driver, - * based on display timing and Sink capabilities. - * If VBLANK region is too small and Sink takes a long time - * to set up RFB, it may take an extra frame to enter PSR state. - */ - bool psr_frame_capture_indication_req; - unsigned int psr_sdp_transmit_line_num_deadline; -}; - enum i2c_mot_mode { I2C_MOT_UNDEF, I2C_MOT_TRUE, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 6b249f5bf1da..6a93c96b9b26 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1005,6 +1005,10 @@ static enum dc_status dce110_prog_pixclk_crtc_otg( pipe_ctx->tg, &stream->public.timing, true); + + pipe_ctx->tg->funcs->set_static_screen_control( + pipe_ctx->tg, + 0x182); } if (!pipe_ctx_old->stream) { @@ -1015,6 +1019,8 @@ static enum dc_status dce110_prog_pixclk_crtc_otg( } } + + return DC_OK; } @@ -1114,6 +1120,8 @@ static enum dc_status apply_single_controller_ctx_to_hw( stream->public.timing.pix_clk_khz, context->stream_count); + pipe_ctx->stream->sink->link->psr_enabled = false; + return DC_OK; } @@ -1355,9 +1363,17 @@ static void set_drr(struct pipe_ctx **pipe_ctx, } static void set_static_screen_control(struct pipe_ctx **pipe_ctx, - int num_pipes, int value) + int num_pipes, const struct dc_static_screen_events *events) { unsigned int i; + unsigned int value = 0; + + if (events->overlay_update) + value |= 0x100; + if (events->surface_update) + value |= 0x80; + if (events->cursor_update) + value |= 0x2; for (i = 0; i < num_pipes; i++) pipe_ctx[i]->tg->funcs-> diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c index 7070aaf9e433..23760727f000 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c @@ -371,7 +371,6 @@ void dce110_timing_generator_set_drr( uint32_t v_total_min = 0; uint32_t v_total_max = 0; uint32_t v_total_cntl = 0; - uint32_t static_screen_cntl = 0; struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); uint32_t addr = 0; @@ -385,9 +384,6 @@ void dce110_timing_generator_set_drr( addr = CRTC_REG(mmCRTC_V_TOTAL_CONTROL); v_total_cntl = dm_read_reg(tg->ctx, addr); - addr = CRTC_REG(mmCRTC_STATIC_SCREEN_CONTROL); - static_screen_cntl = dm_read_reg(tg->ctx, addr); - if (params != NULL && params->vertical_total_max > 0 && params->vertical_total_min > 0) { @@ -430,20 +426,11 @@ void dce110_timing_generator_set_drr( 0, CRTC_V_TOTAL_CONTROL, CRTC_SET_V_TOTAL_MIN_MASK); - - set_reg_field_value(static_screen_cntl, - 0x180, - CRTC_STATIC_SCREEN_CONTROL, - CRTC_STATIC_SCREEN_EVENT_MASK); } else { set_reg_field_value(v_total_cntl, 0, CRTC_V_TOTAL_CONTROL, CRTC_SET_V_TOTAL_MIN_MASK); - set_reg_field_value(static_screen_cntl, - 0, - CRTC_STATIC_SCREEN_CONTROL, - CRTC_STATIC_SCREEN_EVENT_MASK); set_reg_field_value(v_total_min, 0, CRTC_V_TOTAL_MIN, @@ -478,9 +465,6 @@ void dce110_timing_generator_set_drr( addr = CRTC_REG(mmCRTC_V_TOTAL_CONTROL); dm_write_reg(tg->ctx, addr, v_total_cntl); - - addr = CRTC_REG(mmCRTC_STATIC_SCREEN_CONTROL); - dm_write_reg(tg->ctx, addr, static_screen_cntl); } void dce110_timing_generator_set_static_screen_control( diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 405608318ccc..2b43e18c65f5 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -156,6 +156,7 @@ struct core_link { unsigned int dpcd_sink_count; enum edp_revision edp_revision; + bool psr_enabled; /* MST record stream using this link */ struct link_flags { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 9bfaaad09bea..b42e4a0ef18a 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -132,7 +132,7 @@ struct hw_sequencer_funcs { int vmin, int vmax); void (*set_static_screen_control)(struct pipe_ctx **pipe_ctx, - int num_pipes, int value); + int num_pipes, const struct dc_static_screen_events *events); enum dc_status (*prog_pixclk_crtc_otg)( struct pipe_ctx *pipe_ctx, diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index 5c6de723da5d..78b4f28d862c 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -264,10 +264,10 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, enable_for_video = false; } - temp = core_stream->public.timing.pix_clk_khz; + temp = stream->timing.pix_clk_khz; temp *= 1000ULL * 1000ULL * 1000ULL; - temp = div_u64(temp, core_stream->public.timing.h_total); - temp = div_u64(temp, core_stream->public.timing.v_total); + temp = div_u64(temp, stream->timing.h_total); + temp = div_u64(temp, stream->timing.v_total); nom_refresh_rate_micro_hz = (unsigned int) temp; @@ -657,6 +657,7 @@ void mod_freesync_handle_v_update(struct mod_freesync *mod_freesync, unsigned int min_frame_duration_in_ns, vmax, vmin = 0; struct freesync_state *state; struct core_freesync *core_freesync = NULL; + struct dc_static_screen_events triggers = {0}; if (mod_freesync == NULL) return; @@ -749,6 +750,13 @@ void mod_freesync_handle_v_update(struct mod_freesync *mod_freesync, core_freesync->dc, streams, num_streams, v_total, v_total); + + triggers.overlay_update = true; + triggers.surface_update = true; + + core_freesync->dc->stream_funcs.set_static_screen_events( + core_freesync->dc, streams, num_streams, + &triggers); } } -- cgit From e91b57334a4ef9355ffa397d767e8c3a2c690f22 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Sun, 23 Apr 2017 10:46:02 -0400 Subject: drm/amd/display: move tg_color to dc_hw_types Signed-off-by: Tony Cheng Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 12 ++++++------ drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h | 12 ------------ 2 files changed, 6 insertions(+), 18 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index b785dd7b3a97..64d43dba8fd6 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -641,12 +641,12 @@ struct dc_crtc_timing { struct dc_crtc_timing_flags flags; }; -struct _dlg_otg_param { - int vstartup_start; - int vupdate_offset; - int vupdate_width; - int vready_offset; - enum signal_type signal; +#define MAX_TG_COLOR_VALUE 0x3FF +struct tg_color { + /* Maximum 10 bits color value */ + uint16_t color_r_cr; + uint16_t color_g_y; + uint16_t color_b_cb; }; #endif /* DC_HW_TYPES_H */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h index b3deaf2d8173..235cfe8d1ad4 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h @@ -28,18 +28,6 @@ struct dc_bios; -/** - * These parameters are required as input when doing blanking/Unblanking -*/ -#define MAX_TG_COLOR_VALUE 0x3FF - -struct tg_color { - /* Maximum 10 bits color value */ - uint16_t color_r_cr; - uint16_t color_g_y; - uint16_t color_b_cb; -}; - /* Contains CRTC vertical/horizontal pixel counters */ struct crtc_position { uint32_t vertical_count; -- cgit From 50db413d557c39de9a976e2c9826d4e86e721c7c Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Sun, 23 Apr 2017 23:33:26 -0400 Subject: drm/amd/display: clarify delay param for REG_WAIT Signed-off-by: Tony Cheng Acked-by: Harry Wentland Reviewed-by: Dmytro Laktyushkin Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/inc/reg_helper.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h b/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h index b595b94d2b69..96fba1fb7697 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h +++ b/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h @@ -185,10 +185,10 @@ /* macro to poll and wait for a register field to read back given value */ -#define REG_WAIT(reg_name, field, val, delay, max_try) \ +#define REG_WAIT(reg_name, field, val, delay_between_poll_us, max_try) \ generic_reg_wait(CTX, \ REG(reg_name), FN(reg_name, field), val,\ - delay, max_try, __func__) + delay_between_poll_us, max_try, __func__) /* macro to update (read, modify, write) register fields */ -- cgit From 86b6a203b966ea54e3225b49e53769cf4c116905 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Mon, 24 Apr 2017 15:20:24 -0400 Subject: drm/amd/display: dce120 to dce ipp refactor Signed-off-by: Dmytro Laktyushkin Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/Makefile | 2 +- drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c | 252 +++++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dce/dce_ipp.h | 226 ++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dce/dce_transform.h | 2 +- drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h | 2 +- .../drm/amd/display/dc/dce110/dce110_ipp_gamma.c | 4 +- drivers/gpu/drm/amd/display/dc/dce120/Makefile | 1 - drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp.c | 58 ----- drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp.h | 62 ----- .../drm/amd/display/dc/dce120/dce120_ipp_cursor.c | 193 ---------------- .../drm/amd/display/dc/dce120/dce120_ipp_gamma.c | 167 -------------- .../drm/amd/display/dc/dce120/dce120_resource.c | 69 +++--- drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h | 3 + drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h | 5 +- 14 files changed, 521 insertions(+), 525 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_ipp.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp_cursor.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp_gamma.c (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/Makefile b/drivers/gpu/drm/amd/display/dc/dce/Makefile index 05562553b656..8abec0bed379 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dce/Makefile @@ -7,7 +7,7 @@ DCE = dce_audio.o dce_stream_encoder.o dce_link_encoder.o dce_hwseq.o \ dce_mem_input.o dce_clock_source.o dce_scl_filters.o dce_transform.o \ -dce_clocks.o dce_opp.o dce_dmcu.o dce_abm.o +dce_clocks.o dce_opp.o dce_dmcu.o dce_abm.o dce_ipp.o AMD_DAL_DCE = $(addprefix $(AMDDALPATH)/dc/dce/,$(DCE)) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c new file mode 100644 index 000000000000..d6bf6067a309 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c @@ -0,0 +1,252 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dce_ipp.h" +#include "reg_helper.h" +#include "dm_services.h" + +#define REG(reg) \ + (ipp_dce->regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + ipp_dce->ipp_shift->field_name, ipp_dce->ipp_mask->field_name + +#define CTX \ + ipp_dce->base.ctx + +static void dce_ipp_cursor_set_position( + struct input_pixel_processor *ipp, + const struct dc_cursor_position *position, + const struct dc_cursor_mi_param *param) +{ + struct dce_ipp *ipp_dce = TO_DCE_IPP(ipp); + + /* lock cursor registers */ + REG_UPDATE(CUR_UPDATE, CURSOR_UPDATE_LOCK, true); + + /* Flag passed in structure differentiates cursor enable/disable. */ + /* Update if it differs from cached state. */ + REG_UPDATE(CUR_CONTROL, CURSOR_EN, position->enable); + + REG_SET_2(CUR_POSITION, 0, + CURSOR_X_POSITION, position->x, + CURSOR_Y_POSITION, position->y); + + REG_SET_2(CUR_HOT_SPOT, 0, + CURSOR_HOT_SPOT_X, position->x_hotspot, + CURSOR_HOT_SPOT_Y, position->y_hotspot); + + /* unlock cursor registers */ + REG_UPDATE(CUR_UPDATE, CURSOR_UPDATE_LOCK, false); +} + +static void dce_ipp_cursor_set_attributes( + struct input_pixel_processor *ipp, + const struct dc_cursor_attributes *attributes) +{ + struct dce_ipp *ipp_dce = TO_DCE_IPP(ipp); + int mode; + + /* Lock cursor registers */ + REG_UPDATE(CUR_UPDATE, CURSOR_UPDATE_LOCK, true); + + /* Program cursor control */ + switch (attributes->color_format) { + case CURSOR_MODE_MONO: + mode = 0; + break; + case CURSOR_MODE_COLOR_1BIT_AND: + mode = 1; + break; + case CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA: + mode = 2; + break; + case CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA: + mode = 3; + break; + default: + BREAK_TO_DEBUGGER(); /* unsupported */ + mode = 0; + } + + REG_UPDATE_3(CUR_CONTROL, + CURSOR_MODE, mode, + CURSOR_2X_MAGNIFY, attributes->attribute_flags.bits.ENABLE_MAGNIFICATION, + CUR_INV_TRANS_CLAMP, attributes->attribute_flags.bits.INVERSE_TRANSPARENT_CLAMPING); + + if (attributes->color_format == CURSOR_MODE_MONO) { + REG_SET_3(CUR_COLOR1, 0, + CUR_COLOR1_BLUE, 0, + CUR_COLOR1_GREEN, 0, + CUR_COLOR1_RED, 0); + + REG_SET_3(CUR_COLOR2, 0, + CUR_COLOR2_BLUE, 0xff, + CUR_COLOR2_GREEN, 0xff, + CUR_COLOR2_RED, 0xff); + } + + /* + * Program cursor size -- NOTE: HW spec specifies that HW register + * stores size as (height - 1, width - 1) + */ + REG_SET_2(CUR_SIZE, 0, + CURSOR_WIDTH, attributes->width-1, + CURSOR_HEIGHT, attributes->height-1); + + /* Program cursor surface address */ + /* SURFACE_ADDRESS_HIGH: Higher order bits (39:32) of hardware cursor + * surface base address in byte. It is 4K byte aligned. + * The correct way to program cursor surface address is to first write + * to CUR_SURFACE_ADDRESS_HIGH, and then write to CUR_SURFACE_ADDRESS + */ + REG_SET(CUR_SURFACE_ADDRESS_HIGH, 0, + CURSOR_SURFACE_ADDRESS_HIGH, attributes->address.high_part); + + REG_SET(CUR_SURFACE_ADDRESS, 0, + CURSOR_SURFACE_ADDRESS, attributes->address.low_part); + + /* Unlock Cursor registers. */ + REG_UPDATE(CUR_UPDATE, CURSOR_UPDATE_LOCK, false); +} + +static void dce_ipp_program_prescale( + struct input_pixel_processor *ipp, + struct ipp_prescale_params *params) +{ + struct dce_ipp *ipp_dce = TO_DCE_IPP(ipp); + + /* set to bypass mode first before change */ + REG_UPDATE(PRESCALE_GRPH_CONTROL, + GRPH_PRESCALE_BYPASS, + 1); + + REG_SET_2(PRESCALE_VALUES_GRPH_R, 0, + GRPH_PRESCALE_SCALE_R, params->scale, + GRPH_PRESCALE_BIAS_R, params->bias); + + REG_SET_2(PRESCALE_VALUES_GRPH_G, 0, + GRPH_PRESCALE_SCALE_G, params->scale, + GRPH_PRESCALE_BIAS_G, params->bias); + + REG_SET_2(PRESCALE_VALUES_GRPH_B, 0, + GRPH_PRESCALE_SCALE_B, params->scale, + GRPH_PRESCALE_BIAS_B, params->bias); + + if (params->mode != IPP_PRESCALE_MODE_BYPASS) { + REG_UPDATE(PRESCALE_GRPH_CONTROL, + GRPH_PRESCALE_BYPASS, 0); + + /* If prescale is in use, then legacy lut should be bypassed */ + REG_UPDATE(INPUT_GAMMA_CONTROL, + GRPH_INPUT_GAMMA_MODE, 1); + } +} + +static void dce_ipp_program_input_lut( + struct input_pixel_processor *ipp, + const struct dc_gamma *gamma) +{ + int i; + struct dce_ipp *ipp_dce = TO_DCE_IPP(ipp); + + /* power on LUT memory */ + REG_SET(DCFE_MEM_PWR_CTRL, 0, DCP_LUT_MEM_PWR_DIS, 1); + + /* enable all */ + REG_SET(DC_LUT_WRITE_EN_MASK, 0, DC_LUT_WRITE_EN_MASK, 0x7); + + /* 256 entry mode */ + REG_UPDATE(DC_LUT_RW_MODE, DC_LUT_RW_MODE, 0); + + /* LUT-256, unsigned, integer, new u0.12 format */ + REG_SET_3(DC_LUT_CONTROL, 0, + DC_LUT_DATA_R_FORMAT, 3, + DC_LUT_DATA_G_FORMAT, 3, + DC_LUT_DATA_B_FORMAT, 3); + + /* start from index 0 */ + REG_SET(DC_LUT_RW_INDEX, 0, + DC_LUT_RW_INDEX, 0); + + for (i = 0; i < INPUT_LUT_ENTRIES; i++) { + REG_SET(DC_LUT_SEQ_COLOR, 0, DC_LUT_SEQ_COLOR, gamma->red[i]); + REG_SET(DC_LUT_SEQ_COLOR, 0, DC_LUT_SEQ_COLOR, gamma->green[i]); + REG_SET(DC_LUT_SEQ_COLOR, 0, DC_LUT_SEQ_COLOR, gamma->blue[i]); + } + + /* power off LUT memory */ + REG_SET(DCFE_MEM_PWR_CTRL, 0, DCP_LUT_MEM_PWR_DIS, 0); + + /* bypass prescale, enable legacy LUT */ + REG_UPDATE(PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_BYPASS, 1); + REG_UPDATE(INPUT_GAMMA_CONTROL, GRPH_INPUT_GAMMA_MODE, 0); +} + +static void dce_ipp_set_degamma( + struct input_pixel_processor *ipp, + enum ipp_degamma_mode mode) +{ + struct dce_ipp *ipp_dce = TO_DCE_IPP(ipp); + uint32_t degamma_type = (mode == IPP_DEGAMMA_MODE_HW_sRGB) ? 1 : 0; + + ASSERT(mode == IPP_DEGAMMA_MODE_BYPASS || + mode == IPP_DEGAMMA_MODE_HW_sRGB); + + REG_SET_3(DEGAMMA_CONTROL, 0, + GRPH_DEGAMMA_MODE, degamma_type, + CURSOR_DEGAMMA_MODE, degamma_type, + CURSOR2_DEGAMMA_MODE, degamma_type); +} + +static const struct ipp_funcs dce_ipp_funcs = { + .ipp_cursor_set_attributes = dce_ipp_cursor_set_attributes, + .ipp_cursor_set_position = dce_ipp_cursor_set_position, + .ipp_program_prescale = dce_ipp_program_prescale, + .ipp_program_input_lut = dce_ipp_program_input_lut, + .ipp_set_degamma = dce_ipp_set_degamma +}; + +/*****************************************/ +/* Constructor, Destructor */ +/*****************************************/ + +void dce_ipp_construct( + struct dce_ipp *ipp_dce, + struct dc_context *ctx, + int inst, + const struct dce_ipp_registers *regs, + const struct dce_ipp_shift *ipp_shift, + const struct dce_ipp_mask *ipp_mask) +{ + ipp_dce->base.ctx = ctx; + ipp_dce->base.inst = inst; + ipp_dce->base.funcs = &dce_ipp_funcs; + + ipp_dce->regs = regs; + ipp_dce->ipp_shift = ipp_shift; + ipp_dce->ipp_mask = ipp_mask; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.h b/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.h new file mode 100644 index 000000000000..23f25b1b0e64 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.h @@ -0,0 +1,226 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef _DCE_DCE_IPP_H_ +#define _DCE_DCE_IPP_H_ + +#include "ipp.h" + +#define TO_DCE_IPP(ipp)\ + container_of(ipp, struct dce_ipp, base) + +#define IPP_COMMON_REG_LIST_DCE_BASE(id) \ + SRI(CUR_UPDATE, DCP, id), \ + SRI(CUR_CONTROL, DCP, id), \ + SRI(CUR_POSITION, DCP, id), \ + SRI(CUR_HOT_SPOT, DCP, id), \ + SRI(CUR_COLOR1, DCP, id), \ + SRI(CUR_COLOR2, DCP, id), \ + SRI(CUR_SIZE, DCP, id), \ + SRI(CUR_SURFACE_ADDRESS_HIGH, DCP, id), \ + SRI(CUR_SURFACE_ADDRESS, DCP, id), \ + SRI(PRESCALE_GRPH_CONTROL, DCP, id), \ + SRI(PRESCALE_VALUES_GRPH_R, DCP, id), \ + SRI(PRESCALE_VALUES_GRPH_G, DCP, id), \ + SRI(PRESCALE_VALUES_GRPH_B, DCP, id), \ + SRI(INPUT_GAMMA_CONTROL, DCP, id), \ + SRI(DCFE_MEM_PWR_CTRL, DCFE, id), \ + SRI(DC_LUT_WRITE_EN_MASK, DCP, id), \ + SRI(DC_LUT_RW_MODE, DCP, id), \ + SRI(DC_LUT_CONTROL, DCP, id), \ + SRI(DC_LUT_RW_INDEX, DCP, id), \ + SRI(DC_LUT_SEQ_COLOR, DCP, id), \ + SRI(DEGAMMA_CONTROL, DCP, id) + +#define IPP_SF(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define IPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh) \ + IPP_SF(CUR_UPDATE, CURSOR_UPDATE_LOCK, mask_sh), \ + IPP_SF(CUR_CONTROL, CURSOR_EN, mask_sh), \ + IPP_SF(CUR_CONTROL, CURSOR_MODE, mask_sh), \ + IPP_SF(CUR_CONTROL, CURSOR_2X_MAGNIFY, mask_sh), \ + IPP_SF(CUR_CONTROL, CUR_INV_TRANS_CLAMP, mask_sh), \ + IPP_SF(CUR_POSITION, CURSOR_X_POSITION, mask_sh), \ + IPP_SF(CUR_POSITION, CURSOR_Y_POSITION, mask_sh), \ + IPP_SF(CUR_HOT_SPOT, CURSOR_HOT_SPOT_X, mask_sh), \ + IPP_SF(CUR_HOT_SPOT, CURSOR_HOT_SPOT_Y, mask_sh), \ + IPP_SF(CUR_COLOR1, CUR_COLOR1_BLUE, mask_sh), \ + IPP_SF(CUR_COLOR1, CUR_COLOR1_GREEN, mask_sh), \ + IPP_SF(CUR_COLOR1, CUR_COLOR1_RED, mask_sh), \ + IPP_SF(CUR_COLOR2, CUR_COLOR2_BLUE, mask_sh), \ + IPP_SF(CUR_COLOR2, CUR_COLOR2_GREEN, mask_sh), \ + IPP_SF(CUR_COLOR2, CUR_COLOR2_RED, mask_sh), \ + IPP_SF(CUR_SIZE, CURSOR_WIDTH, mask_sh), \ + IPP_SF(CUR_SIZE, CURSOR_HEIGHT, mask_sh), \ + IPP_SF(CUR_SURFACE_ADDRESS_HIGH, CURSOR_SURFACE_ADDRESS_HIGH, mask_sh), \ + IPP_SF(CUR_SURFACE_ADDRESS, CURSOR_SURFACE_ADDRESS, mask_sh), \ + IPP_SF(PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_BYPASS, mask_sh), \ + IPP_SF(PRESCALE_VALUES_GRPH_R, GRPH_PRESCALE_SCALE_R, mask_sh), \ + IPP_SF(PRESCALE_VALUES_GRPH_R, GRPH_PRESCALE_BIAS_R, mask_sh), \ + IPP_SF(PRESCALE_VALUES_GRPH_G, GRPH_PRESCALE_SCALE_G, mask_sh), \ + IPP_SF(PRESCALE_VALUES_GRPH_G, GRPH_PRESCALE_BIAS_G, mask_sh), \ + IPP_SF(PRESCALE_VALUES_GRPH_B, GRPH_PRESCALE_SCALE_B, mask_sh), \ + IPP_SF(PRESCALE_VALUES_GRPH_B, GRPH_PRESCALE_BIAS_B, mask_sh), \ + IPP_SF(INPUT_GAMMA_CONTROL, GRPH_INPUT_GAMMA_MODE, mask_sh), \ + IPP_SF(DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, mask_sh), \ + IPP_SF(DC_LUT_WRITE_EN_MASK, DC_LUT_WRITE_EN_MASK, mask_sh), \ + IPP_SF(DC_LUT_RW_MODE, DC_LUT_RW_MODE, mask_sh), \ + IPP_SF(DC_LUT_CONTROL, DC_LUT_DATA_R_FORMAT, mask_sh), \ + IPP_SF(DC_LUT_CONTROL, DC_LUT_DATA_G_FORMAT, mask_sh), \ + IPP_SF(DC_LUT_CONTROL, DC_LUT_DATA_B_FORMAT, mask_sh), \ + IPP_SF(DC_LUT_RW_INDEX, DC_LUT_RW_INDEX, mask_sh), \ + IPP_SF(DC_LUT_SEQ_COLOR, DC_LUT_SEQ_COLOR, mask_sh), \ + IPP_SF(DEGAMMA_CONTROL, GRPH_DEGAMMA_MODE, mask_sh), \ + IPP_SF(DEGAMMA_CONTROL, CURSOR_DEGAMMA_MODE, mask_sh), \ + IPP_SF(DEGAMMA_CONTROL, CURSOR2_DEGAMMA_MODE, mask_sh) + +#define IPP_COMMON_MASK_SH_LIST_SOC_BASE(mask_sh) \ + IPP_SF(DCP0_CUR_UPDATE, CURSOR_UPDATE_LOCK, mask_sh), \ + IPP_SF(DCP0_CUR_CONTROL, CURSOR_EN, mask_sh), \ + IPP_SF(DCP0_CUR_CONTROL, CURSOR_MODE, mask_sh), \ + IPP_SF(DCP0_CUR_CONTROL, CURSOR_2X_MAGNIFY, mask_sh), \ + IPP_SF(DCP0_CUR_CONTROL, CUR_INV_TRANS_CLAMP, mask_sh), \ + IPP_SF(DCP0_CUR_POSITION, CURSOR_X_POSITION, mask_sh), \ + IPP_SF(DCP0_CUR_POSITION, CURSOR_Y_POSITION, mask_sh), \ + IPP_SF(DCP0_CUR_HOT_SPOT, CURSOR_HOT_SPOT_X, mask_sh), \ + IPP_SF(DCP0_CUR_HOT_SPOT, CURSOR_HOT_SPOT_Y, mask_sh), \ + IPP_SF(DCP0_CUR_COLOR1, CUR_COLOR1_BLUE, mask_sh), \ + IPP_SF(DCP0_CUR_COLOR1, CUR_COLOR1_GREEN, mask_sh), \ + IPP_SF(DCP0_CUR_COLOR1, CUR_COLOR1_RED, mask_sh), \ + IPP_SF(DCP0_CUR_COLOR2, CUR_COLOR2_BLUE, mask_sh), \ + IPP_SF(DCP0_CUR_COLOR2, CUR_COLOR2_GREEN, mask_sh), \ + IPP_SF(DCP0_CUR_COLOR2, CUR_COLOR2_RED, mask_sh), \ + IPP_SF(DCP0_CUR_SIZE, CURSOR_WIDTH, mask_sh), \ + IPP_SF(DCP0_CUR_SIZE, CURSOR_HEIGHT, mask_sh), \ + IPP_SF(DCP0_CUR_SURFACE_ADDRESS_HIGH, CURSOR_SURFACE_ADDRESS_HIGH, mask_sh), \ + IPP_SF(DCP0_CUR_SURFACE_ADDRESS, CURSOR_SURFACE_ADDRESS, mask_sh), \ + IPP_SF(DCP0_PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_BYPASS, mask_sh), \ + IPP_SF(DCP0_PRESCALE_VALUES_GRPH_R, GRPH_PRESCALE_SCALE_R, mask_sh), \ + IPP_SF(DCP0_PRESCALE_VALUES_GRPH_R, GRPH_PRESCALE_BIAS_R, mask_sh), \ + IPP_SF(DCP0_PRESCALE_VALUES_GRPH_G, GRPH_PRESCALE_SCALE_G, mask_sh), \ + IPP_SF(DCP0_PRESCALE_VALUES_GRPH_G, GRPH_PRESCALE_BIAS_G, mask_sh), \ + IPP_SF(DCP0_PRESCALE_VALUES_GRPH_B, GRPH_PRESCALE_SCALE_B, mask_sh), \ + IPP_SF(DCP0_PRESCALE_VALUES_GRPH_B, GRPH_PRESCALE_BIAS_B, mask_sh), \ + IPP_SF(DCP0_INPUT_GAMMA_CONTROL, GRPH_INPUT_GAMMA_MODE, mask_sh), \ + IPP_SF(DCFE0_DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, mask_sh), \ + IPP_SF(DCP0_DC_LUT_WRITE_EN_MASK, DC_LUT_WRITE_EN_MASK, mask_sh), \ + IPP_SF(DCP0_DC_LUT_RW_MODE, DC_LUT_RW_MODE, mask_sh), \ + IPP_SF(DCP0_DC_LUT_CONTROL, DC_LUT_DATA_R_FORMAT, mask_sh), \ + IPP_SF(DCP0_DC_LUT_CONTROL, DC_LUT_DATA_G_FORMAT, mask_sh), \ + IPP_SF(DCP0_DC_LUT_CONTROL, DC_LUT_DATA_B_FORMAT, mask_sh), \ + IPP_SF(DCP0_DC_LUT_RW_INDEX, DC_LUT_RW_INDEX, mask_sh), \ + IPP_SF(DCP0_DC_LUT_SEQ_COLOR, DC_LUT_SEQ_COLOR, mask_sh), \ + IPP_SF(DCP0_DEGAMMA_CONTROL, GRPH_DEGAMMA_MODE, mask_sh), \ + IPP_SF(DCP0_DEGAMMA_CONTROL, CURSOR_DEGAMMA_MODE, mask_sh), \ + IPP_SF(DCP0_DEGAMMA_CONTROL, CURSOR2_DEGAMMA_MODE, mask_sh) + +#define IPP_REG_FIELD_LIST(type) \ + type CURSOR_UPDATE_LOCK; \ + type CURSOR_EN; \ + type CURSOR_X_POSITION; \ + type CURSOR_Y_POSITION; \ + type CURSOR_HOT_SPOT_X; \ + type CURSOR_HOT_SPOT_Y; \ + type CURSOR_MODE; \ + type CURSOR_2X_MAGNIFY; \ + type CUR_INV_TRANS_CLAMP; \ + type CUR_COLOR1_BLUE; \ + type CUR_COLOR1_GREEN; \ + type CUR_COLOR1_RED; \ + type CUR_COLOR2_BLUE; \ + type CUR_COLOR2_GREEN; \ + type CUR_COLOR2_RED; \ + type CURSOR_WIDTH; \ + type CURSOR_HEIGHT; \ + type CURSOR_SURFACE_ADDRESS_HIGH; \ + type CURSOR_SURFACE_ADDRESS; \ + type GRPH_PRESCALE_BYPASS; \ + type GRPH_PRESCALE_SCALE_R; \ + type GRPH_PRESCALE_BIAS_R; \ + type GRPH_PRESCALE_SCALE_G; \ + type GRPH_PRESCALE_BIAS_G; \ + type GRPH_PRESCALE_SCALE_B; \ + type GRPH_PRESCALE_BIAS_B; \ + type GRPH_INPUT_GAMMA_MODE; \ + type DCP_LUT_MEM_PWR_DIS; \ + type DC_LUT_WRITE_EN_MASK; \ + type DC_LUT_RW_MODE; \ + type DC_LUT_DATA_R_FORMAT; \ + type DC_LUT_DATA_G_FORMAT; \ + type DC_LUT_DATA_B_FORMAT; \ + type DC_LUT_RW_INDEX; \ + type DC_LUT_SEQ_COLOR; \ + type GRPH_DEGAMMA_MODE; \ + type CURSOR_DEGAMMA_MODE; \ + type CURSOR2_DEGAMMA_MODE + +struct dce_ipp_shift { + IPP_REG_FIELD_LIST(uint8_t); +}; + +struct dce_ipp_mask { + IPP_REG_FIELD_LIST(uint32_t); +}; + +struct dce_ipp_registers { + uint32_t CUR_UPDATE; + uint32_t CUR_CONTROL; + uint32_t CUR_POSITION; + uint32_t CUR_HOT_SPOT; + uint32_t CUR_COLOR1; + uint32_t CUR_COLOR2; + uint32_t CUR_SIZE; + uint32_t CUR_SURFACE_ADDRESS_HIGH; + uint32_t CUR_SURFACE_ADDRESS; + uint32_t PRESCALE_GRPH_CONTROL; + uint32_t PRESCALE_VALUES_GRPH_R; + uint32_t PRESCALE_VALUES_GRPH_G; + uint32_t PRESCALE_VALUES_GRPH_B; + uint32_t INPUT_GAMMA_CONTROL; + uint32_t DCFE_MEM_PWR_CTRL; + uint32_t DC_LUT_WRITE_EN_MASK; + uint32_t DC_LUT_RW_MODE; + uint32_t DC_LUT_CONTROL; + uint32_t DC_LUT_RW_INDEX; + uint32_t DC_LUT_SEQ_COLOR; + uint32_t DEGAMMA_CONTROL; +}; + +struct dce_ipp { + struct input_pixel_processor base; + const struct dce_ipp_registers *regs; + const struct dce_ipp_shift *ipp_shift; + const struct dce_ipp_mask *ipp_mask; +}; + +void dce_ipp_construct(struct dce_ipp *ipp_dce, + struct dc_context *ctx, + int inst, + const struct dce_ipp_registers *regs, + const struct dce_ipp_shift *ipp_shift, + const struct dce_ipp_mask *ipp_mask); + +#endif /* _DCE_DCE_IPP_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h index da2a02434665..ca6c621151b2 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h @@ -369,7 +369,7 @@ struct dce_transform { bool prescaler_on; }; -bool dce_transform_construct(struct dce_transform *xfm110, +bool dce_transform_construct(struct dce_transform *xfm_dce, struct dc_context *ctx, uint32_t inst, const struct dce_transform_registers *regs, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h index 434fe2f5a9d7..8684e6a0ef4b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h @@ -59,7 +59,7 @@ void dce110_ipp_cursor_set_attributes( const struct dc_cursor_attributes *attributes); /* DEGAMMA RELATED */ -bool dce110_ipp_set_degamma( +void dce110_ipp_set_degamma( struct input_pixel_processor *ipp, enum ipp_degamma_mode mode); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_gamma.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_gamma.c index f05cc9e981f3..0bcd8a68d5e5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_gamma.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_gamma.c @@ -66,7 +66,7 @@ -bool dce110_ipp_set_degamma( +void dce110_ipp_set_degamma( struct input_pixel_processor *ipp, enum ipp_degamma_mode mode) { @@ -82,8 +82,6 @@ bool dce110_ipp_set_degamma( GRPH_DEGAMMA_MODE, degamma_type, CURSOR_DEGAMMA_MODE, degamma_type, CURSOR2_DEGAMMA_MODE, degamma_type); - - return true; } void dce110_ipp_program_prescale( diff --git a/drivers/gpu/drm/amd/display/dc/dce120/Makefile b/drivers/gpu/drm/amd/display/dc/dce120/Makefile index 3c6b3fa98ddc..826c12ee368c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dce120/Makefile @@ -4,7 +4,6 @@ DCE120 = dce120_resource.o dce120_timing_generator.o \ -dce120_ipp.o dce120_ipp_cursor.o dce120_ipp_gamma.o \ dce120_mem_input.o dce120_hw_sequencer.o AMD_DAL_DCE120 = $(addprefix $(AMDDALPATH)/dc/dce120/,$(DCE120)) diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp.c deleted file mode 100644 index f4505690e01a..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" -#include "include/logger_interface.h" - -#include "vega10/DC/dce_12_0_offset.h" -#include "vega10/DC/dce_12_0_sh_mask.h" -#include "vega10/soc15ip.h" - -#include "dce120_ipp.h" - -static const struct ipp_funcs funcs = { - .ipp_cursor_set_attributes = dce120_ipp_cursor_set_attributes, - .ipp_cursor_set_position = dce120_ipp_cursor_set_position, - .ipp_program_prescale = dce120_ipp_program_prescale, - .ipp_program_input_lut = dce120_ipp_program_input_lut, - .ipp_set_degamma = dce120_ipp_set_degamma, -}; - -bool dce120_ipp_construct( - struct dce110_ipp *ipp, - struct dc_context *ctx, - uint32_t inst, - const struct dce110_ipp_reg_offsets *offset) -{ - if (!dce110_ipp_construct(ipp, ctx, inst, offset)) { - ASSERT_CRITICAL(false); - return false; - } - - ipp->base.funcs = &funcs; - - return true; -} - diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp.h b/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp.h deleted file mode 100644 index 7f645fde7064..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DC_IPP_DCE120_H__ -#define __DC_IPP_DCE120_H__ - -#include "ipp.h" -#include "../dce110/dce110_ipp.h" - - -bool dce120_ipp_construct( - struct dce110_ipp *ipp, - struct dc_context *ctx, - enum controller_id id, - const struct dce110_ipp_reg_offsets *offset); - -/* CURSOR RELATED */ -void dce120_ipp_cursor_set_position( - struct input_pixel_processor *ipp, - const struct dc_cursor_position *position, - const struct dc_cursor_mi_param *param); - -void dce120_ipp_cursor_set_attributes( - struct input_pixel_processor *ipp, - const struct dc_cursor_attributes *attributes); - -/* DEGAMMA RELATED */ -bool dce120_ipp_set_degamma( - struct input_pixel_processor *ipp, - enum ipp_degamma_mode mode); - -void dce120_ipp_program_prescale( - struct input_pixel_processor *ipp, - struct ipp_prescale_params *params); - -void dce120_ipp_program_input_lut( - struct input_pixel_processor *ipp, - const struct dc_gamma *gamma); - -#endif /*__DC_IPP_DCE120_H__*/ diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp_cursor.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp_cursor.c deleted file mode 100644 index dc81d320f6e5..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp_cursor.c +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" -#include "include/logger_interface.h" - -#include "vega10/DC/dce_12_0_offset.h" -#include "vega10/DC/dce_12_0_sh_mask.h" -#include "vega10/soc15ip.h" - -#include "../dce110/dce110_ipp.h" - - -#define DCP_REG_UPDATE_N(reg_name, n, ...) \ - generic_reg_update_soc15(ipp110->base.ctx, ipp110->offsets.dcp_offset, reg_name, n, __VA_ARGS__) - -#define DCP_REG_SET_N(reg_name, n, ...) \ - generic_reg_set_soc15(ipp110->base.ctx, ipp110->offsets.dcp_offset, reg_name, n, __VA_ARGS__) - -#define DCP_REG_UPDATE(reg, field, val) \ - DCP_REG_UPDATE_N(reg, 1, FD(reg##__##field), val) - -#define DCP_REG_UPDATE_2(reg, field1, val1, field2, val2) \ - DCP_REG_UPDATE_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) - -#define DCP_REG_UPDATE_3(reg, field1, val1, field2, val2, field3, val3) \ - DCP_REG_UPDATE_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3) - -#define DCP_REG_SET(reg, field, val) \ - DCP_REG_SET_N(reg, 1, FD(reg##__##field), val) - -#define DCP_REG_SET_2(reg, field1, val1, field2, val2) \ - DCP_REG_SET_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) - -#define DCP_REG_SET_3(reg, field1, val1, field2, val2, field3, val3) \ - DCP_REG_SET_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3) - -/* TODO: DAL3 does not implement cursor memory control - * MCIF_MEM_CONTROL, DMIF_CURSOR_MEM_CONTROL - */ -static void lock( - struct dce110_ipp *ipp110, bool lock) -{ - DCP_REG_UPDATE(DCP0_CUR_UPDATE, CURSOR_UPDATE_LOCK, lock); -} - -static bool program_control( - struct dce110_ipp *ipp110, - enum dc_cursor_color_format color_format, - bool enable_magnification, - bool inverse_transparent_clamping) -{ - uint32_t mode = 0; - - switch (color_format) { - case CURSOR_MODE_MONO: - mode = 0; - break; - case CURSOR_MODE_COLOR_1BIT_AND: - mode = 1; - break; - case CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA: - mode = 2; - break; - case CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA: - mode = 3; - break; - default: - return false; - } - - DCP_REG_UPDATE_3( - DCP0_CUR_CONTROL, - CURSOR_MODE, mode, - CURSOR_2X_MAGNIFY, enable_magnification, - CUR_INV_TRANS_CLAMP, inverse_transparent_clamping); - - if (color_format == CURSOR_MODE_MONO) { - DCP_REG_SET_3( - DCP0_CUR_COLOR1, - CUR_COLOR1_BLUE, 0, - CUR_COLOR1_GREEN, 0, - CUR_COLOR1_RED, 0); - - DCP_REG_SET_3( - DCP0_CUR_COLOR2, - CUR_COLOR2_BLUE, 0xff, - CUR_COLOR2_GREEN, 0xff, - CUR_COLOR2_RED, 0xff); - } - return true; -} - -static void program_address( - struct dce110_ipp *ipp110, - PHYSICAL_ADDRESS_LOC address) -{ - /* SURFACE_ADDRESS_HIGH: Higher order bits (39:32) of hardware cursor - * surface base address in byte. It is 4K byte aligned. - * The correct way to program cursor surface address is to first write - * to CUR_SURFACE_ADDRESS_HIGH, and then write to CUR_SURFACE_ADDRESS - */ - - DCP_REG_SET( - DCP0_CUR_SURFACE_ADDRESS_HIGH, - CURSOR_SURFACE_ADDRESS_HIGH, address.high_part); - - DCP_REG_SET( - DCP0_CUR_SURFACE_ADDRESS, - CURSOR_SURFACE_ADDRESS, address.low_part); -} - -void dce120_ipp_cursor_set_position( - struct input_pixel_processor *ipp, - const struct dc_cursor_position *position, - const struct dc_cursor_mi_param *param) -{ - struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); - - /* lock cursor registers */ - lock(ipp110, true); - - /* Flag passed in structure differentiates cursor enable/disable. */ - /* Update if it differs from cached state. */ - DCP_REG_UPDATE(DCP0_CUR_CONTROL, CURSOR_EN, position->enable); - - DCP_REG_SET_2( - DCP0_CUR_POSITION, - CURSOR_X_POSITION, position->x, - CURSOR_Y_POSITION, position->y); - - DCP_REG_SET_2( - DCP0_CUR_HOT_SPOT, - CURSOR_HOT_SPOT_X, position->x_hotspot, - CURSOR_HOT_SPOT_Y, position->y_hotspot); - - /* unlock cursor registers */ - lock(ipp110, false); -} - -void dce120_ipp_cursor_set_attributes( - struct input_pixel_processor *ipp, - const struct dc_cursor_attributes *attributes) -{ - struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); - /* Lock cursor registers */ - lock(ipp110, true); - - /* Program cursor control */ - program_control( - ipp110, - attributes->color_format, - attributes->attribute_flags.bits.ENABLE_MAGNIFICATION, - attributes->attribute_flags.bits.INVERSE_TRANSPARENT_CLAMPING); - - /* - * Program cursor size -- NOTE: HW spec specifies that HW register - * stores size as (height - 1, width - 1) - */ - DCP_REG_SET_2( - DCP0_CUR_SIZE, - CURSOR_WIDTH, attributes->width-1, - CURSOR_HEIGHT, attributes->height-1); - - /* Program cursor surface address */ - program_address(ipp110, attributes->address); - - /* Unlock Cursor registers. */ - lock(ipp110, false); -} - diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp_gamma.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp_gamma.c deleted file mode 100644 index 7aa5a49c01e2..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp_gamma.c +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" -#include "include/logger_interface.h" -#include "include/fixed31_32.h" -#include "basics/conversion.h" - -#include "vega10/DC/dce_12_0_offset.h" -#include "vega10/DC/dce_12_0_sh_mask.h" -#include "vega10/soc15ip.h" - -#include "../dce110/dce110_ipp.h" - -#define DCP_REG_UPDATE_N(reg_name, n, ...) \ - generic_reg_update_soc15(ipp110->base.ctx, ipp110->offsets.dcp_offset, reg_name, n, __VA_ARGS__) - -#define DCP_REG_SET_N(reg_name, n, ...) \ - generic_reg_set_soc15(ipp110->base.ctx, ipp110->offsets.dcp_offset, reg_name, n, __VA_ARGS__) - -#define DCP_REG_UPDATE(reg, field, val) \ - DCP_REG_UPDATE_N(reg, 1, FD(reg##__##field), val) - -#define DCP_REG_UPDATE_2(reg, field1, val1, field2, val2) \ - DCP_REG_UPDATE_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) - -#define DCP_REG_UPDATE_3(reg, field1, val1, field2, val2, field3, val3) \ - DCP_REG_UPDATE_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3) - -#define DCP_REG_SET(reg, field, val) \ - DCP_REG_SET_N(reg, 1, FD(reg##__##field), val) - -#define DCP_REG_SET_2(reg, field1, val1, field2, val2) \ - DCP_REG_SET_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) - -#define DCP_REG_SET_3(reg, field1, val1, field2, val2, field3, val3) \ - DCP_REG_SET_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3) - - -bool dce120_ipp_set_degamma( - struct input_pixel_processor *ipp, - enum ipp_degamma_mode mode) -{ - struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); - uint32_t degamma_type = (mode == IPP_DEGAMMA_MODE_HW_sRGB) ? 1 : 0; - - ASSERT(mode == IPP_DEGAMMA_MODE_BYPASS || - mode == IPP_DEGAMMA_MODE_HW_sRGB); - - DCP_REG_SET_3( - DCP0_DEGAMMA_CONTROL, - GRPH_DEGAMMA_MODE, degamma_type, - CURSOR_DEGAMMA_MODE, degamma_type, - CURSOR2_DEGAMMA_MODE, degamma_type); - - return true; -} - -void dce120_ipp_program_prescale( - struct input_pixel_processor *ipp, - struct ipp_prescale_params *params) -{ - struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); - - /* set to bypass mode first before change */ - DCP_REG_UPDATE( - DCP0_PRESCALE_GRPH_CONTROL, - GRPH_PRESCALE_BYPASS, - 1); - - DCP_REG_SET_2( - DCP0_PRESCALE_VALUES_GRPH_R, - GRPH_PRESCALE_SCALE_R, params->scale, - GRPH_PRESCALE_BIAS_R, params->bias); - - DCP_REG_SET_2( - DCP0_PRESCALE_VALUES_GRPH_G, - GRPH_PRESCALE_SCALE_G, params->scale, - GRPH_PRESCALE_BIAS_G, params->bias); - - DCP_REG_SET_2( - DCP0_PRESCALE_VALUES_GRPH_B, - GRPH_PRESCALE_SCALE_B, params->scale, - GRPH_PRESCALE_BIAS_B, params->bias); - - if (params->mode != IPP_PRESCALE_MODE_BYPASS) { - DCP_REG_UPDATE(DCP0_PRESCALE_GRPH_CONTROL, - GRPH_PRESCALE_BYPASS, 0); - - /* If prescale is in use, then legacy lut should be bypassed */ - DCP_REG_UPDATE(DCP0_INPUT_GAMMA_CONTROL, - GRPH_INPUT_GAMMA_MODE, 1); - } -} - -static void dce120_helper_select_lut(struct dce110_ipp *ipp110) -{ - /* enable all */ - DCP_REG_SET( - DCP0_DC_LUT_WRITE_EN_MASK, - DC_LUT_WRITE_EN_MASK, - 0x7); - - /* 256 entry mode */ - DCP_REG_UPDATE(DCP0_DC_LUT_RW_MODE, DC_LUT_RW_MODE, 0); - - /* LUT-256, unsigned, integer, new u0.12 format */ - DCP_REG_SET_3( - DCP0_DC_LUT_CONTROL, - DC_LUT_DATA_R_FORMAT, 3, - DC_LUT_DATA_G_FORMAT, 3, - DC_LUT_DATA_B_FORMAT, 3); - - /* start from index 0 */ - DCP_REG_SET( - DCP0_DC_LUT_RW_INDEX, - DC_LUT_RW_INDEX, - 0); -} - -void dce120_ipp_program_input_lut( - struct input_pixel_processor *ipp, - const struct dc_gamma *gamma) -{ - int i; - struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); - - /* power on LUT memory */ - DCP_REG_SET(DCFE0_DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, 1); - - dce120_helper_select_lut(ipp110); - - for (i = 0; i < INPUT_LUT_ENTRIES; i++) { - DCP_REG_SET(DCP0_DC_LUT_SEQ_COLOR, DC_LUT_SEQ_COLOR, gamma->red[i]); - DCP_REG_SET(DCP0_DC_LUT_SEQ_COLOR, DC_LUT_SEQ_COLOR, gamma->green[i]); - DCP_REG_SET(DCP0_DC_LUT_SEQ_COLOR, DC_LUT_SEQ_COLOR, gamma->blue[i]); - } - - /* power off LUT memory */ - DCP_REG_SET(DCFE0_DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, 0); - - /* bypass prescale, enable legacy LUT */ - DCP_REG_UPDATE(DCP0_PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_BYPASS, 1); - DCP_REG_UPDATE(DCP0_INPUT_GAMMA_CONTROL, GRPH_INPUT_GAMMA_MODE, 0); -} diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index f677a77ca6e0..207d07b29e81 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -40,7 +40,7 @@ #include "dce/dce_opp.h" #include "dce/dce_clock_source.h" #include "dce/dce_clocks.h" -#include "dce120_ipp.h" +#include "dce/dce_ipp.h" #include "dce110/dce110_mem_input.h" #include "dce120/dce120_mem_input.h" @@ -174,6 +174,28 @@ static const struct dce_abm_mask abm_mask = { ABM_MASK_SH_LIST_DCE110(_MASK) }; +#define ipp_regs(id)\ +[id] = {\ + IPP_COMMON_REG_LIST_DCE_BASE(id)\ +} + +static const struct dce_ipp_registers ipp_regs[] = { + ipp_regs(0), + ipp_regs(1), + ipp_regs(2), + ipp_regs(3), + ipp_regs(4), + ipp_regs(5) +}; + +static const struct dce_ipp_shift ipp_shift = { + IPP_COMMON_MASK_SH_LIST_SOC_BASE(__SHIFT) +}; + +static const struct dce_ipp_mask ipp_mask = { + IPP_COMMON_MASK_SH_LIST_SOC_BASE(_MASK) +}; + #define transform_regs(id)\ [id] = {\ XFM_COMMON_REG_LIST_DCE110(id)\ @@ -354,27 +376,6 @@ struct output_pixel_processor *dce120_opp_create( return NULL; } -static const struct dce110_ipp_reg_offsets dce120_ipp_reg_offsets[] = { - { - .dcp_offset = (mmDCP0_CUR_CONTROL - mmDCP0_CUR_CONTROL), - }, - { - .dcp_offset = (mmDCP1_CUR_CONTROL - mmDCP0_CUR_CONTROL), - }, - { - .dcp_offset = (mmDCP2_CUR_CONTROL - mmDCP0_CUR_CONTROL), - }, - { - .dcp_offset = (mmDCP3_CUR_CONTROL - mmDCP0_CUR_CONTROL), - }, - { - .dcp_offset = (mmDCP4_CUR_CONTROL - mmDCP0_CUR_CONTROL), - }, - { - .dcp_offset = (mmDCP5_CUR_CONTROL - mmDCP0_CUR_CONTROL), - } -}; - static const struct dce110_mem_input_reg_offsets dce120_mi_reg_offsets[] = { { .dcp = (mmDCP0_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), @@ -498,7 +499,7 @@ static struct timing_generator *dce120_timing_generator_create( static void dce120_ipp_destroy(struct input_pixel_processor **ipp) { - dm_free(TO_DCE110_IPP(*ipp)); + dm_free(TO_DCE_IPP(*ipp)); *ipp = NULL; } @@ -622,21 +623,18 @@ struct link_encoder *dce120_link_encoder_create( } static struct input_pixel_processor *dce120_ipp_create( - struct dc_context *ctx, - uint32_t inst, - const struct dce110_ipp_reg_offsets *offset) + struct dc_context *ctx, uint32_t inst) { - struct dce110_ipp *ipp = dm_alloc(sizeof(struct dce110_ipp)); + struct dce_ipp *ipp = dm_alloc(sizeof(struct dce_ipp)); - if (!ipp) + if (!ipp) { + BREAK_TO_DEBUGGER(); return NULL; + } - if (dce120_ipp_construct(ipp, ctx, inst, offset)) - return &ipp->base; - - BREAK_TO_DEBUGGER(); - dm_free(ipp); - return NULL; + dce_ipp_construct(ipp, ctx, inst, + &ipp_regs[inst], &ipp_shift, &ipp_mask); + return &ipp->base; } static struct stream_encoder *dce120_stream_encoder_create( @@ -1025,8 +1023,7 @@ static bool construct( goto controller_create_fail; } - pool->base.ipps[i] = dce120_ipp_create(ctx, i, - &dce120_ipp_reg_offsets[i]); + pool->base.ipps[i] = dce120_ipp_create(ctx, i); if (pool->base.ipps[i] == NULL) { BREAK_TO_DEBUGGER(); dm_error( diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h index dfe590198a33..907e0a9a8474 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h @@ -26,6 +26,9 @@ #ifndef __DAL_HW_SHARED_H__ #define __DAL_HW_SHARED_H__ +#include "os_types.h" +#include "fixed31_32.h" + /****************************************************************************** * Data types shared between different Virtual HW blocks ******************************************************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h index 7928e230eefb..2f3dc2e7f17a 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h @@ -1,5 +1,5 @@ /* - * Copyright 2015 Advanced Micro Devices, Inc. + * Copyright 2017 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -27,6 +27,7 @@ #define __DAL_IPP_H__ #include "hw_shared.h" +#include "dc_hw_types.h" #define MAXTRIX_COEFFICIENTS_NUMBER 12 #define MAXTRIX_COEFFICIENTS_WRAP_NUMBER (MAXTRIX_COEFFICIENTS_NUMBER + 4) @@ -113,7 +114,7 @@ struct ipp_funcs { const struct dc_gamma *gamma); /*** DEGAMMA RELATED ***/ - bool (*ipp_set_degamma)( + void (*ipp_set_degamma)( struct input_pixel_processor *ipp, enum ipp_degamma_mode mode); -- cgit From e6303950ea7221e49cabb240383fa4e2bd035b0c Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Mon, 24 Apr 2017 16:30:58 -0400 Subject: drm/amd/display: dce80, 100, 110 and 112 to dce ipp refactor Signed-off-by: Dmytro Laktyushkin Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c | 12 +- drivers/gpu/drm/amd/display/dc/dce/dce_ipp.h | 24 +- .../drm/amd/display/dc/dce100/dce100_resource.c | 73 +++--- drivers/gpu/drm/amd/display/dc/dce110/Makefile | 4 +- drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.c | 63 ------ drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h | 74 ------ .../drm/amd/display/dc/dce110/dce110_ipp_cursor.c | 249 --------------------- .../drm/amd/display/dc/dce110/dce110_ipp_gamma.c | 159 ------------- .../drm/amd/display/dc/dce110/dce110_resource.c | 70 +++--- .../drm/amd/display/dc/dce112/dce112_resource.c | 81 +++---- .../drm/amd/display/dc/dce120/dce120_resource.c | 14 +- drivers/gpu/drm/amd/display/dc/dce80/Makefile | 2 +- drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.c | 65 ------ drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.h | 45 ---- .../gpu/drm/amd/display/dc/dce80/dce80_resource.c | 84 ++++--- 15 files changed, 171 insertions(+), 848 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_cursor.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_gamma.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c index d6bf6067a309..9e8f0a3593a2 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c @@ -174,7 +174,8 @@ static void dce_ipp_program_input_lut( struct dce_ipp *ipp_dce = TO_DCE_IPP(ipp); /* power on LUT memory */ - REG_SET(DCFE_MEM_PWR_CTRL, 0, DCP_LUT_MEM_PWR_DIS, 1); + if (REG(DCFE_MEM_PWR_CTRL)) + REG_SET(DCFE_MEM_PWR_CTRL, 0, DCP_LUT_MEM_PWR_DIS, 1); /* enable all */ REG_SET(DC_LUT_WRITE_EN_MASK, 0, DC_LUT_WRITE_EN_MASK, 0x7); @@ -199,7 +200,8 @@ static void dce_ipp_program_input_lut( } /* power off LUT memory */ - REG_SET(DCFE_MEM_PWR_CTRL, 0, DCP_LUT_MEM_PWR_DIS, 0); + if (REG(DCFE_MEM_PWR_CTRL)) + REG_SET(DCFE_MEM_PWR_CTRL, 0, DCP_LUT_MEM_PWR_DIS, 0); /* bypass prescale, enable legacy LUT */ REG_UPDATE(PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_BYPASS, 1); @@ -250,3 +252,9 @@ void dce_ipp_construct( ipp_dce->ipp_shift = ipp_shift; ipp_dce->ipp_mask = ipp_mask; } + +void dce_ipp_destroy(struct input_pixel_processor **ipp) +{ + dm_free(TO_DCE_IPP(*ipp)); + *ipp = NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.h b/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.h index 23f25b1b0e64..ca04e97d44c3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.h @@ -23,8 +23,8 @@ * */ -#ifndef _DCE_DCE_IPP_H_ -#define _DCE_DCE_IPP_H_ +#ifndef _DCE_IPP_H_ +#define _DCE_IPP_H_ #include "ipp.h" @@ -46,7 +46,6 @@ SRI(PRESCALE_VALUES_GRPH_G, DCP, id), \ SRI(PRESCALE_VALUES_GRPH_B, DCP, id), \ SRI(INPUT_GAMMA_CONTROL, DCP, id), \ - SRI(DCFE_MEM_PWR_CTRL, DCFE, id), \ SRI(DC_LUT_WRITE_EN_MASK, DCP, id), \ SRI(DC_LUT_RW_MODE, DCP, id), \ SRI(DC_LUT_CONTROL, DCP, id), \ @@ -54,6 +53,14 @@ SRI(DC_LUT_SEQ_COLOR, DCP, id), \ SRI(DEGAMMA_CONTROL, DCP, id) +#define IPP_DCE100_REG_LIST_DCE_BASE(id) \ + IPP_COMMON_REG_LIST_DCE_BASE(id), \ + SRI(DCFE_MEM_PWR_CTRL, CRTC, id) + +#define IPP_DCE110_REG_LIST_DCE_BASE(id) \ + IPP_COMMON_REG_LIST_DCE_BASE(id), \ + SRI(DCFE_MEM_PWR_CTRL, DCFE, id) + #define IPP_SF(reg_name, field_name, post_fix)\ .field_name = reg_name ## __ ## field_name ## post_fix @@ -85,7 +92,6 @@ IPP_SF(PRESCALE_VALUES_GRPH_B, GRPH_PRESCALE_SCALE_B, mask_sh), \ IPP_SF(PRESCALE_VALUES_GRPH_B, GRPH_PRESCALE_BIAS_B, mask_sh), \ IPP_SF(INPUT_GAMMA_CONTROL, GRPH_INPUT_GAMMA_MODE, mask_sh), \ - IPP_SF(DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, mask_sh), \ IPP_SF(DC_LUT_WRITE_EN_MASK, DC_LUT_WRITE_EN_MASK, mask_sh), \ IPP_SF(DC_LUT_RW_MODE, DC_LUT_RW_MODE, mask_sh), \ IPP_SF(DC_LUT_CONTROL, DC_LUT_DATA_R_FORMAT, mask_sh), \ @@ -97,7 +103,11 @@ IPP_SF(DEGAMMA_CONTROL, CURSOR_DEGAMMA_MODE, mask_sh), \ IPP_SF(DEGAMMA_CONTROL, CURSOR2_DEGAMMA_MODE, mask_sh) -#define IPP_COMMON_MASK_SH_LIST_SOC_BASE(mask_sh) \ +#define IPP_DCE100_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh) \ + IPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh), \ + IPP_SF(DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, mask_sh) + +#define IPP_DCE120_MASK_SH_LIST_SOC_BASE(mask_sh) \ IPP_SF(DCP0_CUR_UPDATE, CURSOR_UPDATE_LOCK, mask_sh), \ IPP_SF(DCP0_CUR_CONTROL, CURSOR_EN, mask_sh), \ IPP_SF(DCP0_CUR_CONTROL, CURSOR_MODE, mask_sh), \ @@ -223,4 +233,6 @@ void dce_ipp_construct(struct dce_ipp *ipp_dce, const struct dce_ipp_shift *ipp_shift, const struct dce_ipp_mask *ipp_mask); -#endif /* _DCE_DCE_IPP_H_ */ +void dce_ipp_destroy(struct input_pixel_processor **ipp); + +#endif /* _DCE_IPP_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 9b365597cec5..f65b785220e2 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -37,7 +37,7 @@ #include "dce/dce_stream_encoder.h" #include "dce110/dce110_mem_input.h" #include "dce110/dce110_mem_input_v.h" -#include "dce110/dce110_ipp.h" +#include "dce/dce_ipp.h" #include "dce/dce_transform.h" #include "dce/dce_opp.h" #include "dce/dce_clocks.h" @@ -168,30 +168,6 @@ static const struct dce110_mem_input_reg_offsets dce100_mi_reg_offsets[] = { } }; - -static const struct dce110_ipp_reg_offsets dce100_ipp_reg_offsets[] = { -{ - .dcp_offset = (mmDCP0_CUR_CONTROL - mmCUR_CONTROL), -}, -{ - .dcp_offset = (mmDCP1_CUR_CONTROL - mmCUR_CONTROL), -}, -{ - .dcp_offset = (mmDCP2_CUR_CONTROL - mmCUR_CONTROL), -}, -{ - .dcp_offset = (mmDCP3_CUR_CONTROL - mmCUR_CONTROL), -}, -{ - .dcp_offset = (mmDCP4_CUR_CONTROL - mmCUR_CONTROL), -}, -{ - .dcp_offset = (mmDCP5_CUR_CONTROL - mmCUR_CONTROL), -} -}; - - - /* set register offset */ #define SR(reg_name)\ .reg_name = mm ## reg_name @@ -213,6 +189,28 @@ static const struct dce_disp_clk_mask disp_clk_mask = { CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) }; +#define ipp_regs(id)\ +[id] = {\ + IPP_DCE100_REG_LIST_DCE_BASE(id)\ +} + +static const struct dce_ipp_registers ipp_regs[] = { + ipp_regs(0), + ipp_regs(1), + ipp_regs(2), + ipp_regs(3), + ipp_regs(4), + ipp_regs(5) +}; + +static const struct dce_ipp_shift ipp_shift = { + IPP_DCE100_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) +}; + +static const struct dce_ipp_mask ipp_mask = { + IPP_DCE100_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) +}; + #define transform_regs(id)\ [id] = {\ XFM_COMMON_REG_LIST_DCE100(id)\ @@ -563,22 +561,18 @@ static struct transform *dce100_transform_create( } static struct input_pixel_processor *dce100_ipp_create( - struct dc_context *ctx, - uint32_t inst, - const struct dce110_ipp_reg_offsets *offsets) + struct dc_context *ctx, uint32_t inst) { - struct dce110_ipp *ipp = - dm_alloc(sizeof(struct dce110_ipp)); + struct dce_ipp *ipp = dm_alloc(sizeof(struct dce_ipp)); - if (!ipp) + if (!ipp) { + BREAK_TO_DEBUGGER(); return NULL; + } - if (dce110_ipp_construct(ipp, ctx, inst, offsets)) - return &ipp->base; - - BREAK_TO_DEBUGGER(); - dm_free(ipp); - return NULL; + dce_ipp_construct(ipp, ctx, inst, + &ipp_regs[inst], &ipp_shift, &ipp_mask); + return &ipp->base; } static const struct encoder_feature_support link_enc_feature = { @@ -674,7 +668,7 @@ static void destruct(struct dce110_resource_pool *pool) dce100_transform_destroy(&pool->base.transforms[i]); if (pool->base.ipps[i] != NULL) - dce110_ipp_destroy(&pool->base.ipps[i]); + dce_ipp_destroy(&pool->base.ipps[i]); if (pool->base.mis[i] != NULL) { dm_free(TO_DCE110_MEM_INPUT(pool->base.mis[i])); @@ -1005,8 +999,7 @@ static bool construct( goto res_create_fail; } - pool->base.ipps[i] = dce100_ipp_create(ctx, i, - &dce100_ipp_reg_offsets[i]); + pool->base.ipps[i] = dce100_ipp_create(ctx, i); if (pool->base.ipps[i] == NULL) { BREAK_TO_DEBUGGER(); dm_error( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/Makefile b/drivers/gpu/drm/amd/display/dc/dce110/Makefile index 9c42afcac325..c54bf0330701 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dce110/Makefile @@ -2,9 +2,7 @@ # Makefile for the 'controller' sub-component of DAL. # It provides the control and status of HW CRTC block. -DCE110 = dce110_ipp.o dce110_ipp_cursor.o \ -dce110_ipp_gamma.o \ -dce110_timing_generator.o \ +DCE110 = dce110_timing_generator.o \ dce110_compressor.o dce110_mem_input.o dce110_hw_sequencer.o \ dce110_resource.o \ dce110_opp_regamma_v.o dce110_opp_csc_v.o dce110_timing_generator_v.o \ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.c deleted file mode 100644 index 86fa7657a756..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.c +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" -#include "include/logger_interface.h" - -#include "dce/dce_11_0_d.h" -#include "dce/dce_11_0_sh_mask.h" - -#include "dce110_ipp.h" - -static const struct ipp_funcs funcs = { - .ipp_cursor_set_attributes = dce110_ipp_cursor_set_attributes, - .ipp_cursor_set_position = dce110_ipp_cursor_set_position, - .ipp_program_prescale = dce110_ipp_program_prescale, - .ipp_program_input_lut = dce110_ipp_program_input_lut, - .ipp_set_degamma = dce110_ipp_set_degamma, -}; - -bool dce110_ipp_construct( - struct dce110_ipp* ipp, - struct dc_context *ctx, - uint32_t inst, - const struct dce110_ipp_reg_offsets *offset) -{ - ipp->base.ctx = ctx; - - ipp->base.inst = inst; - - ipp->offsets = *offset; - - ipp->base.funcs = &funcs; - - return true; -} - -void dce110_ipp_destroy(struct input_pixel_processor **ipp) -{ - dm_free(TO_DCE110_IPP(*ipp)); - *ipp = NULL; -} diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h deleted file mode 100644 index 8684e6a0ef4b..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DC_IPP_DCE110_H__ -#define __DC_IPP_DCE110_H__ - -#include "ipp.h" - -#define TO_DCE110_IPP(input_pixel_processor)\ - container_of(input_pixel_processor, struct dce110_ipp, base) - -struct dce110_ipp_reg_offsets { - uint32_t dcp_offset; -}; - -struct dce110_ipp { - struct input_pixel_processor base; - struct dce110_ipp_reg_offsets offsets; -}; - -bool dce110_ipp_construct( - struct dce110_ipp* ipp, - struct dc_context *ctx, - enum controller_id id, - const struct dce110_ipp_reg_offsets *offset); - -void dce110_ipp_destroy(struct input_pixel_processor **ipp); - -/* CURSOR RELATED */ -void dce110_ipp_cursor_set_position( - struct input_pixel_processor *ipp, - const struct dc_cursor_position *position, - const struct dc_cursor_mi_param *param); - -void dce110_ipp_cursor_set_attributes( - struct input_pixel_processor *ipp, - const struct dc_cursor_attributes *attributes); - -/* DEGAMMA RELATED */ -void dce110_ipp_set_degamma( - struct input_pixel_processor *ipp, - enum ipp_degamma_mode mode); - -void dce110_ipp_program_prescale( - struct input_pixel_processor *ipp, - struct ipp_prescale_params *params); - -void dce110_ipp_program_input_lut( - struct input_pixel_processor *ipp, - const struct dc_gamma *gamma); - -#endif /*__DC_IPP_DCE110_H__*/ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_cursor.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_cursor.c deleted file mode 100644 index f712916563b9..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_cursor.c +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" -#include "include/logger_interface.h" - -#include "dce/dce_11_0_d.h" -#include "dce/dce_11_0_sh_mask.h" - -#include "dce110_ipp.h" - -#define CURSOR_COLOR_BLACK 0x00000000 -#define CURSOR_COLOR_WHITE 0xFFFFFFFF - -#define DCP_REG(reg)\ - (reg + ipp110->offsets.dcp_offset) - -static void enable( - struct dce110_ipp *ipp110, - bool enable); - -static void lock( - struct dce110_ipp *ipp110, - bool enable); - -static void program_position( - struct dce110_ipp *ipp110, - uint32_t x, - uint32_t y); - -static bool program_control( - struct dce110_ipp *ipp110, - enum dc_cursor_color_format color_format, - bool enable_magnification, - bool inverse_transparent_clamping); - -static void program_hotspot( - struct dce110_ipp *ipp110, - uint32_t x, - uint32_t y); - -static void program_size( - struct dce110_ipp *ipp110, - uint32_t width, - uint32_t height); - -static void program_address( - struct dce110_ipp *ipp110, - PHYSICAL_ADDRESS_LOC address); - -void dce110_ipp_cursor_set_position( - struct input_pixel_processor *ipp, - const struct dc_cursor_position *position, - const struct dc_cursor_mi_param *param) -{ - struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); - - /* lock cursor registers */ - lock(ipp110, true); - - /* Flag passed in structure differentiates cursor enable/disable. */ - /* Update if it differs from cached state. */ - enable(ipp110, position->enable); - - program_position(ipp110, position->x, position->y); - - program_hotspot( - ipp110, - position->x_hotspot, - position->y_hotspot); - - /* unlock cursor registers */ - lock(ipp110, false); -} - -void dce110_ipp_cursor_set_attributes( - struct input_pixel_processor *ipp, - const struct dc_cursor_attributes *attributes) -{ - struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); - /* Lock cursor registers */ - lock(ipp110, true); - - /* Program cursor control */ - program_control( - ipp110, - attributes->color_format, - attributes->attribute_flags.bits.ENABLE_MAGNIFICATION, - attributes->attribute_flags.bits.INVERSE_TRANSPARENT_CLAMPING); - - - /* - * Program cursor size -- NOTE: HW spec specifies that HW register - * stores size as (height - 1, width - 1) - */ - program_size(ipp110, attributes->width-1, attributes->height-1); - - /* Program cursor surface address */ - program_address(ipp110, attributes->address); - - /* Unlock Cursor registers. */ - lock(ipp110, false); -} - -static void enable( - struct dce110_ipp *ipp110, bool enable) -{ - uint32_t value = 0; - uint32_t addr = DCP_REG(mmCUR_CONTROL); - - value = dm_read_reg(ipp110->base.ctx, addr); - set_reg_field_value(value, enable, CUR_CONTROL, CURSOR_EN); - dm_write_reg(ipp110->base.ctx, addr, value); -} - -static void lock( - struct dce110_ipp *ipp110, bool lock) -{ - uint32_t value = 0; - uint32_t addr = DCP_REG(mmCUR_UPDATE); - - value = dm_read_reg(ipp110->base.ctx, addr); - set_reg_field_value(value, lock, CUR_UPDATE, CURSOR_UPDATE_LOCK); - dm_write_reg(ipp110->base.ctx, addr, value); -} - -static void program_position( - struct dce110_ipp *ipp110, - uint32_t x, - uint32_t y) -{ - uint32_t value = 0; - uint32_t addr = DCP_REG(mmCUR_POSITION); - - value = dm_read_reg(ipp110->base.ctx, addr); - set_reg_field_value(value, x, CUR_POSITION, CURSOR_X_POSITION); - set_reg_field_value(value, y, CUR_POSITION, CURSOR_Y_POSITION); - dm_write_reg(ipp110->base.ctx, addr, value); -} - -static bool program_control( - struct dce110_ipp *ipp110, - enum dc_cursor_color_format color_format, - bool enable_magnification, - bool inverse_transparent_clamping) -{ - uint32_t value = 0; - uint32_t addr = DCP_REG(mmCUR_CONTROL); - uint32_t mode = 0; - - switch (color_format) { - case CURSOR_MODE_MONO: - mode = 0; - break; - case CURSOR_MODE_COLOR_1BIT_AND: - mode = 1; - break; - case CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA: - mode = 2; - break; - case CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA: - mode = 3; - break; - default: - return false; - } - - set_reg_field_value(value, mode, CUR_CONTROL, CURSOR_MODE); - set_reg_field_value(value, enable_magnification, - CUR_CONTROL, CURSOR_2X_MAGNIFY); - set_reg_field_value(value, inverse_transparent_clamping, - CUR_CONTROL, CUR_INV_TRANS_CLAMP); - dm_write_reg(ipp110->base.ctx, addr, value); - - if (color_format == CURSOR_MODE_MONO) { - addr = DCP_REG(mmCUR_COLOR1); - dm_write_reg(ipp110->base.ctx, addr, CURSOR_COLOR_BLACK); - addr = DCP_REG(mmCUR_COLOR2); - dm_write_reg(ipp110->base.ctx, addr, CURSOR_COLOR_WHITE); - } - return true; -} - -static void program_hotspot( - struct dce110_ipp *ipp110, - uint32_t x, - uint32_t y) -{ - uint32_t value = 0; - uint32_t addr = DCP_REG(mmCUR_HOT_SPOT); - - value = dm_read_reg(ipp110->base.ctx, addr); - set_reg_field_value(value, x, CUR_HOT_SPOT, CURSOR_HOT_SPOT_X); - set_reg_field_value(value, y, CUR_HOT_SPOT, CURSOR_HOT_SPOT_Y); - dm_write_reg(ipp110->base.ctx, addr, value); -} - -static void program_size( - struct dce110_ipp *ipp110, - uint32_t width, - uint32_t height) -{ - uint32_t value = 0; - uint32_t addr = DCP_REG(mmCUR_SIZE); - - value = dm_read_reg(ipp110->base.ctx, addr); - set_reg_field_value(value, width, CUR_SIZE, CURSOR_WIDTH); - set_reg_field_value(value, height, CUR_SIZE, CURSOR_HEIGHT); - dm_write_reg(ipp110->base.ctx, addr, value); -} - -static void program_address( - struct dce110_ipp *ipp110, - PHYSICAL_ADDRESS_LOC address) -{ - uint32_t addr = DCP_REG(mmCUR_SURFACE_ADDRESS_HIGH); - /* SURFACE_ADDRESS_HIGH: Higher order bits (39:32) of hardware cursor - * surface base address in byte. It is 4K byte aligned. - * The correct way to program cursor surface address is to first write - * to CUR_SURFACE_ADDRESS_HIGH, and then write to CUR_SURFACE_ADDRESS */ - - dm_write_reg(ipp110->base.ctx, addr, address.high_part); - - addr = DCP_REG(mmCUR_SURFACE_ADDRESS); - dm_write_reg(ipp110->base.ctx, addr, address.low_part); -} - diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_gamma.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_gamma.c deleted file mode 100644 index 0bcd8a68d5e5..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_gamma.c +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" -#include "include/logger_interface.h" -#include "include/fixed31_32.h" -#include "basics/conversion.h" - -#include "dce/dce_11_0_d.h" -#include "dce/dce_11_0_sh_mask.h" - -#include "dce110_ipp.h" - -#define DCP_REG(reg)\ - (mm##reg + ipp110->offsets.dcp_offset) - -#define DCP_REG_SET_N(reg_name, n, ...) \ - generic_reg_update_ex(ipp110->base.ctx, \ - DCP_REG(reg_name), \ - 0, n, __VA_ARGS__) - -#define DCP_REG_SET(reg, field1, val1) \ - DCP_REG_SET_N(reg, 1, FD(reg##__##field1), val1) - -#define DCP_REG_SET_2(reg, field1, val1, field2, val2) \ - DCP_REG_SET_N(reg, 2, \ - FD(reg##__##field1), val1, \ - FD(reg##__##field2), val2) - -#define DCP_REG_SET_3(reg, field1, val1, field2, val2, field3, val3) \ - DCP_REG_SET_N(reg, 3, \ - FD(reg##__##field1), val1, \ - FD(reg##__##field2), val2, \ - FD(reg##__##field3), val3) - -#define DCP_REG_UPDATE_N(reg_name, n, ...) \ - generic_reg_update_ex(ipp110->base.ctx, \ - DCP_REG(reg_name), \ - dm_read_reg(ipp110->base.ctx, DCP_REG(reg_name)), \ - n, __VA_ARGS__) - -#define DCP_REG_UPDATE(reg, field, val) \ - DCP_REG_UPDATE_N(reg, 1, FD(reg##__##field), val) - - - -void dce110_ipp_set_degamma( - struct input_pixel_processor *ipp, - enum ipp_degamma_mode mode) -{ - struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); - - uint32_t degamma_type = (mode == IPP_DEGAMMA_MODE_HW_sRGB) ? 1 : 0; - - ASSERT(mode == IPP_DEGAMMA_MODE_BYPASS || - mode == IPP_DEGAMMA_MODE_HW_sRGB); - - DCP_REG_SET_3( - DEGAMMA_CONTROL, - GRPH_DEGAMMA_MODE, degamma_type, - CURSOR_DEGAMMA_MODE, degamma_type, - CURSOR2_DEGAMMA_MODE, degamma_type); -} - -void dce110_ipp_program_prescale( - struct input_pixel_processor *ipp, - struct ipp_prescale_params *params) -{ - struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); - - /* set to bypass mode first before change */ - DCP_REG_UPDATE(PRESCALE_GRPH_CONTROL, - GRPH_PRESCALE_BYPASS, 1); - - DCP_REG_SET_2(PRESCALE_VALUES_GRPH_R, - GRPH_PRESCALE_SCALE_R, params->scale, - GRPH_PRESCALE_BIAS_R, params->bias); - - DCP_REG_SET_2(PRESCALE_VALUES_GRPH_G, - GRPH_PRESCALE_SCALE_G, params->scale, - GRPH_PRESCALE_BIAS_G, params->bias); - - DCP_REG_SET_2(PRESCALE_VALUES_GRPH_B, - GRPH_PRESCALE_SCALE_B, params->scale, - GRPH_PRESCALE_BIAS_B, params->bias); - - if (params->mode != IPP_PRESCALE_MODE_BYPASS) { - /* If prescale is in use, then legacy lut should be bypassed */ - DCP_REG_UPDATE(PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_BYPASS, 0); - DCP_REG_UPDATE(INPUT_GAMMA_CONTROL, GRPH_INPUT_GAMMA_MODE, 1); - } -} - -static void dce110_helper_select_lut(struct dce110_ipp *ipp110) -{ - /* enable all */ - DCP_REG_SET(DC_LUT_WRITE_EN_MASK, DC_LUT_WRITE_EN_MASK, 0x7); - - /* 256 entry mode */ - DCP_REG_UPDATE(DC_LUT_RW_MODE, DC_LUT_RW_MODE, 0); - - /* LUT-256, unsigned, integer, new u0.12 format */ - DCP_REG_SET_3(DC_LUT_CONTROL, - DC_LUT_DATA_R_FORMAT, 3, - DC_LUT_DATA_G_FORMAT, 3, - DC_LUT_DATA_B_FORMAT, 3); - - /* start from index 0 */ - DCP_REG_SET(DC_LUT_RW_INDEX, DC_LUT_RW_INDEX, 0); -} - -void dce110_ipp_program_input_lut( - struct input_pixel_processor *ipp, - const struct dc_gamma *gamma) -{ - int i; - struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); - - dce110_helper_select_lut(ipp110); - - /* power on LUT memory and give it time to settle */ - DCP_REG_SET(DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, 1); - udelay(10); - - for (i = 0; i < INPUT_LUT_ENTRIES; i++) { - DCP_REG_SET(DC_LUT_SEQ_COLOR, DC_LUT_SEQ_COLOR, gamma->red[i]); - DCP_REG_SET(DC_LUT_SEQ_COLOR, DC_LUT_SEQ_COLOR, gamma->green[i]); - DCP_REG_SET(DC_LUT_SEQ_COLOR, DC_LUT_SEQ_COLOR, gamma->blue[i]); - } - - /* power off LUT memory */ - DCP_REG_SET(DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, 0); - - /* bypass prescale, enable legacy LUT */ - DCP_REG_UPDATE(PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_BYPASS, 1); - DCP_REG_UPDATE(INPUT_GAMMA_CONTROL, GRPH_INPUT_GAMMA_MODE, 0); -} diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index b4ab438e1c97..8dec9a5602a9 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -40,7 +40,7 @@ #include "dce/dce_stream_encoder.h" #include "dce110/dce110_mem_input.h" #include "dce110/dce110_mem_input_v.h" -#include "dce110/dce110_ipp.h" +#include "dce/dce_ipp.h" #include "dce/dce_transform.h" #include "dce110/dce110_transform_v.h" #include "dce/dce_opp.h" @@ -157,31 +157,6 @@ static const struct dce110_mem_input_reg_offsets dce110_mi_reg_offsets[] = { } }; - -static const struct dce110_ipp_reg_offsets dce110_ipp_reg_offsets[] = { -{ - .dcp_offset = (mmDCP0_CUR_CONTROL - mmCUR_CONTROL), -}, -{ - .dcp_offset = (mmDCP1_CUR_CONTROL - mmCUR_CONTROL), -}, -{ - .dcp_offset = (mmDCP2_CUR_CONTROL - mmCUR_CONTROL), -}, -{ - .dcp_offset = (mmDCP3_CUR_CONTROL - mmCUR_CONTROL), -}, -{ - .dcp_offset = (mmDCP4_CUR_CONTROL - mmCUR_CONTROL), -}, -{ - .dcp_offset = (mmDCP5_CUR_CONTROL - mmCUR_CONTROL), -} -}; - - - - /* set register offset */ #define SR(reg_name)\ .reg_name = mm ## reg_name @@ -226,6 +201,25 @@ static const struct dce_abm_mask abm_mask = { ABM_MASK_SH_LIST_DCE110(_MASK) }; +#define ipp_regs(id)\ +[id] = {\ + IPP_DCE110_REG_LIST_DCE_BASE(id)\ +} + +static const struct dce_ipp_registers ipp_regs[] = { + ipp_regs(0), + ipp_regs(1), + ipp_regs(2) +}; + +static const struct dce_ipp_shift ipp_shift = { + IPP_DCE100_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) +}; + +static const struct dce_ipp_mask ipp_mask = { + IPP_DCE100_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) +}; + #define transform_regs(id)\ [id] = {\ XFM_COMMON_REG_LIST_DCE110(id)\ @@ -578,22 +572,18 @@ static struct transform *dce110_transform_create( } static struct input_pixel_processor *dce110_ipp_create( - struct dc_context *ctx, - uint32_t inst, - const struct dce110_ipp_reg_offsets *offsets) + struct dc_context *ctx, uint32_t inst) { - struct dce110_ipp *ipp = - dm_alloc(sizeof(struct dce110_ipp)); + struct dce_ipp *ipp = dm_alloc(sizeof(struct dce_ipp)); - if (!ipp) + if (!ipp) { + BREAK_TO_DEBUGGER(); return NULL; + } - if (dce110_ipp_construct(ipp, ctx, inst, offsets)) - return &ipp->base; - - BREAK_TO_DEBUGGER(); - dm_free(ipp); - return NULL; + dce_ipp_construct(ipp, ctx, inst, + &ipp_regs[inst], &ipp_shift, &ipp_mask); + return &ipp->base; } static const struct encoder_feature_support link_enc_feature = { @@ -705,7 +695,7 @@ static void destruct(struct dce110_resource_pool *pool) dce110_transform_destroy(&pool->base.transforms[i]); if (pool->base.ipps[i] != NULL) - dce110_ipp_destroy(&pool->base.ipps[i]); + dce_ipp_destroy(&pool->base.ipps[i]); if (pool->base.mis[i] != NULL) { dm_free(TO_DCE110_MEM_INPUT(pool->base.mis[i])); @@ -1414,7 +1404,7 @@ static bool construct( goto res_create_fail; } - pool->base.ipps[i] = dce110_ipp_create(ctx, i, &dce110_ipp_reg_offsets[i]); + pool->base.ipps[i] = dce110_ipp_create(ctx, i); if (pool->base.ipps[i] == NULL) { BREAK_TO_DEBUGGER(); dm_error( diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 0a1ad2808129..4bf75afd5721 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -40,7 +40,7 @@ #include "dce/dce_stream_encoder.h" #include "dce/dce_audio.h" #include "dce/dce_opp.h" -#include "dce110/dce110_ipp.h" +#include "dce/dce_ipp.h" #include "dce/dce_clocks.h" #include "dce/dce_clock_source.h" @@ -177,28 +177,6 @@ static const struct dce110_mem_input_reg_offsets dce112_mi_reg_offsets[] = { } }; -static const struct dce110_ipp_reg_offsets ipp_reg_offsets[] = { -{ - .dcp_offset = (mmDCP0_CUR_CONTROL - mmCUR_CONTROL), -}, -{ - .dcp_offset = (mmDCP1_CUR_CONTROL - mmCUR_CONTROL), -}, -{ - .dcp_offset = (mmDCP2_CUR_CONTROL - mmCUR_CONTROL), -}, -{ - .dcp_offset = (mmDCP3_CUR_CONTROL - mmCUR_CONTROL), -}, -{ - .dcp_offset = (mmDCP4_CUR_CONTROL - mmCUR_CONTROL), -}, -{ - .dcp_offset = (mmDCP5_CUR_CONTROL - mmCUR_CONTROL), -} -}; - - /* set register offset */ #define SR(reg_name)\ .reg_name = mm ## reg_name @@ -244,6 +222,28 @@ static const struct dce_abm_mask abm_mask = { ABM_MASK_SH_LIST_DCE110(_MASK) }; +#define ipp_regs(id)\ +[id] = {\ + IPP_DCE110_REG_LIST_DCE_BASE(id)\ +} + +static const struct dce_ipp_registers ipp_regs[] = { + ipp_regs(0), + ipp_regs(1), + ipp_regs(2), + ipp_regs(3), + ipp_regs(4), + ipp_regs(5) +}; + +static const struct dce_ipp_shift ipp_shift = { + IPP_DCE100_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) +}; + +static const struct dce_ipp_mask ipp_mask = { + IPP_DCE100_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) +}; + #define transform_regs(id)\ [id] = {\ XFM_COMMON_REG_LIST_DCE110(id)\ @@ -627,29 +627,19 @@ struct link_encoder *dce112_link_encoder_create( return NULL; } -struct input_pixel_processor *dce112_ipp_create( - struct dc_context *ctx, - uint32_t inst, - const struct dce110_ipp_reg_offsets *offset) +static struct input_pixel_processor *dce112_ipp_create( + struct dc_context *ctx, uint32_t inst) { - struct dce110_ipp *ipp = - dm_alloc(sizeof(struct dce110_ipp)); + struct dce_ipp *ipp = dm_alloc(sizeof(struct dce_ipp)); - if (!ipp) + if (!ipp) { + BREAK_TO_DEBUGGER(); return NULL; + } - if (dce110_ipp_construct(ipp, ctx, inst, offset)) - return &ipp->base; - - BREAK_TO_DEBUGGER(); - dm_free(ipp); - return NULL; -} - -void dce112_ipp_destroy(struct input_pixel_processor **ipp) -{ - dm_free(TO_DCE110_IPP(*ipp)); - *ipp = NULL; + dce_ipp_construct(ipp, ctx, inst, + &ipp_regs[inst], &ipp_shift, &ipp_mask); + return &ipp->base; } struct output_pixel_processor *dce112_opp_create( @@ -712,7 +702,7 @@ static void destruct(struct dce110_resource_pool *pool) dce112_transform_destroy(&pool->base.transforms[i]); if (pool->base.ipps[i] != NULL) - dce112_ipp_destroy(&pool->base.ipps[i]); + dce_ipp_destroy(&pool->base.ipps[i]); if (pool->base.mis[i] != NULL) { dm_free(TO_DCE110_MEM_INPUT(pool->base.mis[i])); @@ -1370,10 +1360,7 @@ static bool construct( goto res_create_fail; } - pool->base.ipps[i] = dce112_ipp_create( - ctx, - i, - &ipp_reg_offsets[i]); + pool->base.ipps[i] = dce112_ipp_create(ctx, i); if (pool->base.ipps[i] == NULL) { BREAK_TO_DEBUGGER(); dm_error( diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index 207d07b29e81..b6bdd1d52922 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -176,7 +176,7 @@ static const struct dce_abm_mask abm_mask = { #define ipp_regs(id)\ [id] = {\ - IPP_COMMON_REG_LIST_DCE_BASE(id)\ + IPP_DCE110_REG_LIST_DCE_BASE(id)\ } static const struct dce_ipp_registers ipp_regs[] = { @@ -189,11 +189,11 @@ static const struct dce_ipp_registers ipp_regs[] = { }; static const struct dce_ipp_shift ipp_shift = { - IPP_COMMON_MASK_SH_LIST_SOC_BASE(__SHIFT) + IPP_DCE120_MASK_SH_LIST_SOC_BASE(__SHIFT) }; static const struct dce_ipp_mask ipp_mask = { - IPP_COMMON_MASK_SH_LIST_SOC_BASE(_MASK) + IPP_DCE120_MASK_SH_LIST_SOC_BASE(_MASK) }; #define transform_regs(id)\ @@ -497,12 +497,6 @@ static struct timing_generator *dce120_timing_generator_create( return NULL; } -static void dce120_ipp_destroy(struct input_pixel_processor **ipp) -{ - dm_free(TO_DCE_IPP(*ipp)); - *ipp = NULL; -} - static void dce120_transform_destroy(struct transform **xfm) { dm_free(TO_DCE_TRANSFORM(*xfm)); @@ -521,7 +515,7 @@ static void destruct(struct dce110_resource_pool *pool) dce120_transform_destroy(&pool->base.transforms[i]); if (pool->base.ipps[i] != NULL) - dce120_ipp_destroy(&pool->base.ipps[i]); + dce_ipp_destroy(&pool->base.ipps[i]); if (pool->base.mis[i] != NULL) { dm_free(TO_DCE110_MEM_INPUT(pool->base.mis[i])); diff --git a/drivers/gpu/drm/amd/display/dc/dce80/Makefile b/drivers/gpu/drm/amd/display/dc/dce80/Makefile index 8d2c3dbfced1..1d54d5fa0fd2 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dce80/Makefile @@ -2,7 +2,7 @@ # Makefile for the 'controller' sub-component of DAL. # It provides the control and status of HW CRTC block. -DCE80 = dce80_ipp.o dce80_timing_generator.o \ +DCE80 = dce80_timing_generator.o \ dce80_compressor.o dce80_mem_input.o dce80_hw_sequencer.o \ dce80_resource.o diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.c deleted file mode 100644 index c195acb6e1a6..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" -#include "include/logger_interface.h" - -#include "dce/dce_8_0_d.h" -#include "dce/dce_8_0_sh_mask.h" - -#include "dce80_ipp.h" - -#include "dce110/dce110_ipp.h" - -static const struct ipp_funcs funcs = { - .ipp_cursor_set_attributes = dce110_ipp_cursor_set_attributes, - .ipp_cursor_set_position = dce110_ipp_cursor_set_position, - .ipp_program_prescale = dce110_ipp_program_prescale, - .ipp_program_input_lut = dce110_ipp_program_input_lut, - .ipp_set_degamma = dce110_ipp_set_degamma, -}; - -bool dce80_ipp_construct( - struct dce110_ipp *ipp, - struct dc_context *ctx, - uint32_t inst, - const struct dce110_ipp_reg_offsets *offset) -{ - ipp->base.ctx = ctx; - - ipp->base.inst = inst; - - ipp->offsets = *offset; - - ipp->base.funcs = &funcs; - - return true; -} - -void dce80_ipp_destroy(struct input_pixel_processor **ipp) -{ - dm_free(TO_DCE80_IPP(*ipp)); - *ipp = NULL; -} diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.h b/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.h deleted file mode 100644 index 06e8598d395f..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DC_IPP_DCE80_H__ -#define __DC_IPP_DCE80_H__ - -#include "ipp.h" - -#define TO_DCE80_IPP(input_pixel_processor)\ - container_of(input_pixel_processor, struct dce110_ipp, base) - -struct dce110_ipp; -struct dce110_ipp_reg_offsets; - -bool dce80_ipp_construct( - struct dce110_ipp *ipp, - struct dc_context *ctx, - uint32_t inst, - const struct dce110_ipp_reg_offsets *offset); - -void dce80_ipp_destroy(struct input_pixel_processor **ipp); - -#endif /*__DC_IPP_DCE80_H__*/ diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index ab8cee3e734e..d49092986d54 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -41,10 +41,9 @@ #include "dce/dce_link_encoder.h" #include "dce/dce_stream_encoder.h" #include "dce80/dce80_mem_input.h" -#include "dce80/dce80_ipp.h" +#include "dce/dce_ipp.h" #include "dce/dce_transform.h" #include "dce/dce_opp.h" -#include "dce110/dce110_ipp.h" #include "dce/dce_clocks.h" #include "dce/dce_clock_source.h" #include "dce/dce_audio.h" @@ -187,27 +186,6 @@ static const struct dce110_mem_input_reg_offsets dce80_mi_reg_offsets[] = { } }; -static const struct dce110_ipp_reg_offsets ipp_reg_offsets[] = { -{ - .dcp_offset = (mmDCP0_CUR_CONTROL - mmDCP0_CUR_CONTROL), -}, -{ - .dcp_offset = (mmDCP1_CUR_CONTROL - mmDCP0_CUR_CONTROL), -}, -{ - .dcp_offset = (mmDCP2_CUR_CONTROL - mmDCP0_CUR_CONTROL), -}, -{ - .dcp_offset = (mmDCP3_CUR_CONTROL - mmDCP0_CUR_CONTROL), -}, -{ - .dcp_offset = (mmDCP4_CUR_CONTROL - mmDCP0_CUR_CONTROL), -}, -{ - .dcp_offset = (mmDCP5_CUR_CONTROL - mmDCP0_CUR_CONTROL), -} -}; - /* set register offset */ #define SR(reg_name)\ .reg_name = mm ## reg_name @@ -229,6 +207,28 @@ static const struct dce_disp_clk_mask disp_clk_mask = { CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) }; +#define ipp_regs(id)\ +[id] = {\ + IPP_COMMON_REG_LIST_DCE_BASE(id)\ +} + +static const struct dce_ipp_registers ipp_regs[] = { + ipp_regs(0), + ipp_regs(1), + ipp_regs(2), + ipp_regs(3), + ipp_regs(4), + ipp_regs(5) +}; + +static const struct dce_ipp_shift ipp_shift = { + IPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) +}; + +static const struct dce_ipp_mask ipp_mask = { + IPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) +}; + #define transform_regs(id)\ [id] = {\ XFM_COMMON_REG_LIST_DCE_BASE(id)\ @@ -592,25 +592,6 @@ static struct transform *dce80_transform_create( return NULL; } -static struct input_pixel_processor *dce80_ipp_create( - struct dc_context *ctx, - uint32_t inst, - const struct dce110_ipp_reg_offsets *offset) -{ - struct dce110_ipp *ipp = - dm_alloc(sizeof(struct dce110_ipp)); - - if (!ipp) - return NULL; - - if (dce80_ipp_construct(ipp, ctx, inst, offset)) - return &ipp->base; - - BREAK_TO_DEBUGGER(); - dm_free(ipp); - return NULL; -} - static const struct encoder_feature_support link_enc_feature = { .max_hdmi_deep_color = COLOR_DEPTH_121212, .max_hdmi_pixel_clock = 297000, @@ -673,6 +654,21 @@ void dce80_clock_source_destroy(struct clock_source **clk_src) *clk_src = NULL; } +static struct input_pixel_processor *dce80_ipp_create( + struct dc_context *ctx, uint32_t inst) +{ + struct dce_ipp *ipp = dm_alloc(sizeof(struct dce_ipp)); + + if (!ipp) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dce_ipp_construct(ipp, ctx, inst, + &ipp_regs[inst], &ipp_shift, &ipp_mask); + return &ipp->base; +} + static void destruct(struct dce110_resource_pool *pool) { unsigned int i; @@ -685,7 +681,7 @@ static void destruct(struct dce110_resource_pool *pool) dce80_transform_destroy(&pool->base.transforms[i]); if (pool->base.ipps[i] != NULL) - dce80_ipp_destroy(&pool->base.ipps[i]); + dce_ipp_destroy(&pool->base.ipps[i]); if (pool->base.mis[i] != NULL) { dm_free(TO_DCE110_MEM_INPUT(pool->base.mis[i])); @@ -1016,7 +1012,7 @@ static bool construct( goto res_create_fail; } - pool->base.ipps[i] = dce80_ipp_create(ctx, i, &ipp_reg_offsets[i]); + pool->base.ipps[i] = dce80_ipp_create(ctx, i); if (pool->base.ipps[i] == NULL) { BREAK_TO_DEBUGGER(); dm_error("DC: failed to create input pixel processor!\n"); -- cgit From 84f6739fc4d348440cd5684113260f728778312a Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Mon, 24 Apr 2017 17:42:22 -0400 Subject: drm/amd/display: no need for return value from ipp_program_degamma_pwl Signed-off-by: Dmytro Laktyushkin Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h index 2f3dc2e7f17a..2d472d8ef555 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h @@ -118,7 +118,7 @@ struct ipp_funcs { struct input_pixel_processor *ipp, enum ipp_degamma_mode mode); - bool (*ipp_program_degamma_pwl)( + void (*ipp_program_degamma_pwl)( struct input_pixel_processor *ipp, const struct pwl_params *params); -- cgit From 72ada5f76939ed00c07c584be7691a29d3c2c3da Mon Sep 17 00:00:00 2001 From: Eric Cook Date: Tue, 18 Apr 2017 15:24:50 -0400 Subject: drm/amd/display: FreeSync Auto Sweep Support Implement core support to allow for FreeSync Auto Sweep to work Signed-off-by: Eric Cook Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 28 +++ drivers/gpu/drm/amd/display/dc/core/dc_debug.c | 5 +- drivers/gpu/drm/amd/display/dc/dc.h | 6 + .../amd/display/dc/dce110/dce110_hw_sequencer.c | 13 ++ .../display/dc/dce110/dce110_timing_generator.c | 61 +++--- .../display/dc/dce110/dce110_timing_generator.h | 9 +- .../display/dc/dce110/dce110_timing_generator_v.c | 23 +-- .../display/dc/dce120/dce120_timing_generator.c | 73 ++++++- .../amd/display/dc/dce80/dce80_timing_generator.c | 2 +- .../drm/amd/display/dc/inc/hw/timing_generator.h | 10 +- drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 3 + .../drm/amd/display/modules/freesync/freesync.c | 227 ++++++++++++++++----- .../gpu/drm/amd/display/modules/inc/mod_freesync.h | 20 ++ 13 files changed, 357 insertions(+), 123 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 93c936d92f5a..2e74faef68e7 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -175,6 +175,31 @@ static bool stream_adjust_vmin_vmax(struct dc *dc, return ret; } +static bool stream_get_crtc_position(struct dc *dc, + const struct dc_stream **stream, int num_streams, + unsigned int *v_pos, unsigned int *nom_v_pos) +{ + /* TODO: Support multiple streams */ + struct core_dc *core_dc = DC_TO_CORE(dc); + struct core_stream *core_stream = DC_STREAM_TO_CORE(stream[0]); + int i = 0; + bool ret = false; + struct crtc_position position; + + for (i = 0; i < MAX_PIPES; i++) { + struct pipe_ctx *pipe = + &core_dc->current_context->res_ctx.pipe_ctx[i]; + + if (pipe->stream == core_stream && pipe->stream_enc) { + core_dc->hwss.get_position(&pipe, 1, &position); + + *v_pos = position.vertical_count; + *nom_v_pos = position.nominal_vcount; + ret = true; + } + } + return ret; +} static bool set_gamut_remap(struct dc *dc, const struct dc_stream **stream, int num_streams) @@ -349,6 +374,9 @@ static void allocate_dc_stream_funcs(struct core_dc *core_dc) core_dc->public.stream_funcs.set_static_screen_events = set_static_screen_events; + core_dc->public.stream_funcs.get_crtc_position = + stream_get_crtc_position; + core_dc->public.stream_funcs.set_gamut_remap = set_gamut_remap; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c index fb48b8909e7f..ee840e75ee1f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c @@ -287,6 +287,7 @@ void context_timing_trace( struct core_dc *core_dc = DC_TO_CORE(dc); struct dal_logger *logger = core_dc->ctx->logger; int h_pos[MAX_PIPES], v_pos[MAX_PIPES]; + struct crtc_position position; for (i = 0; i < core_dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; @@ -294,7 +295,9 @@ void context_timing_trace( if (pipe_ctx->stream == NULL) continue; - pipe_ctx->tg->funcs->get_position(pipe_ctx->tg, &h_pos[i], &v_pos[i]); + pipe_ctx->tg->funcs->get_position(pipe_ctx->tg, &position); + h_pos[i] = position.horizontal_count; + v_pos[i] = position.vertical_count; } for (i = 0; i < core_dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index d12aa726164e..647c095e0ae9 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -103,6 +103,12 @@ struct dc_stream_funcs { int num_streams, int vmin, int vmax); + bool (*get_crtc_position)(struct dc *dc, + const struct dc_stream **stream, + int num_streams, + unsigned int *v_pos, + unsigned int *nom_v_pos); + void (*stream_update_scaling)(const struct dc *dc, const struct dc_stream *dc_stream, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 6a93c96b9b26..0e69aceb0bad 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1362,6 +1362,18 @@ static void set_drr(struct pipe_ctx **pipe_ctx, } } +static void get_position(struct pipe_ctx **pipe_ctx, + int num_pipes, + struct crtc_position *position) +{ + int i = 0; + + /* TODO: handle pipes > 1 + */ + for (i = 0; i < num_pipes; i++) + pipe_ctx[i]->tg->funcs->get_position(pipe_ctx[i]->tg, position); +} + static void set_static_screen_control(struct pipe_ctx **pipe_ctx, int num_pipes, const struct dc_static_screen_events *events) { @@ -2486,6 +2498,7 @@ static const struct hw_sequencer_funcs dce110_funcs = { .pipe_control_lock = dce_pipe_control_lock, .set_bandwidth = dce110_set_bandwidth, .set_drr = set_drr, + .get_position = get_position, .set_static_screen_control = set_static_screen_control, .reset_hw_ctx_wrap = reset_hw_ctx_wrap, .prog_pixclk_crtc_otg = dce110_prog_pixclk_crtc_otg, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c index 23760727f000..ec599276ed2e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c @@ -518,34 +518,38 @@ uint32_t dce110_timing_generator_get_vblank_counter(struct timing_generator *tg) /** ***************************************************************************** - * Function: dce110_get_crtc_positions + * Function: dce110_timing_generator_get_position * * @brief * Returns CRTC vertical/horizontal counters * - * @param [out] v_position, h_position + * @param [out] position ***************************************************************************** */ - -void dce110_timing_generator_get_crtc_positions( - struct timing_generator *tg, - int32_t *h_position, - int32_t *v_position) +void dce110_timing_generator_get_position(struct timing_generator *tg, + struct crtc_position *position) { uint32_t value; struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_STATUS_POSITION)); - *h_position = get_reg_field_value( + position->horizontal_count = get_reg_field_value( value, CRTC_STATUS_POSITION, CRTC_HORZ_COUNT); - *v_position = get_reg_field_value( + position->vertical_count = get_reg_field_value( value, CRTC_STATUS_POSITION, CRTC_VERT_COUNT); + + value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_NOM_VERT_POSITION)); + + position->nominal_vcount = get_reg_field_value( + value, + CRTC_NOM_VERT_POSITION, + CRTC_VERT_COUNT_NOM); } /** @@ -566,18 +570,23 @@ void dce110_timing_generator_get_crtc_scanoutpos( uint32_t *v_position) { struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + struct crtc_position position; - uint32_t v_blank_start_end = dm_read_reg(tg->ctx, + uint32_t value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_V_BLANK_START_END)); - *v_blank_start = get_reg_field_value(v_blank_start_end, + *v_blank_start = get_reg_field_value(value, CRTC_V_BLANK_START_END, CRTC_V_BLANK_START); - *v_blank_end = get_reg_field_value(v_blank_start_end, + *v_blank_end = get_reg_field_value(value, CRTC_V_BLANK_START_END, CRTC_V_BLANK_END); - dce110_timing_generator_get_crtc_positions(tg, h_position, v_position); + dce110_timing_generator_get_position( + tg, &position); + + *h_position = position.horizontal_count; + *v_position = position.vertical_count; } /* TODO: is it safe to assume that mask/shift of Primary and Underlay @@ -1344,15 +1353,13 @@ void dce110_timing_generator_tear_down_global_swap_lock( */ bool dce110_timing_generator_is_counter_moving(struct timing_generator *tg) { - uint32_t h1 = 0; - uint32_t h2 = 0; - uint32_t v1 = 0; - uint32_t v2 = 0; + struct crtc_position position1, position2; - tg->funcs->get_position(tg, &h1, &v1); - tg->funcs->get_position(tg, &h2, &v2); + tg->funcs->get_position(tg, &position1); + tg->funcs->get_position(tg, &position2); - if (h1 == h2 && v1 == v2) + if (position1.horizontal_count == position2.horizontal_count && + position1.vertical_count == position2.vertical_count) return false; else return true; @@ -1750,18 +1757,6 @@ void dce110_tg_set_overscan_color(struct timing_generator *tg, dm_write_reg(ctx, addr, value); } -void dce110_tg_get_position(struct timing_generator *tg, - struct crtc_position *position) -{ - int32_t h_position; - int32_t v_position; - - dce110_timing_generator_get_crtc_positions(tg, &h_position, &v_position); - - position->horizontal_count = (uint32_t)h_position; - position->vertical_count = (uint32_t)v_position; -} - void dce110_tg_program_timing(struct timing_generator *tg, const struct dc_crtc_timing *timing, bool use_vbios) @@ -1895,7 +1890,7 @@ static const struct timing_generator_funcs dce110_tg_funcs = { .enable_crtc = dce110_timing_generator_enable_crtc, .disable_crtc = dce110_timing_generator_disable_crtc, .is_counter_moving = dce110_timing_generator_is_counter_moving, - .get_position = dce110_timing_generator_get_crtc_positions, + .get_position = dce110_timing_generator_get_position, .get_frame_count = dce110_timing_generator_get_vblank_counter, .get_scanoutpos = dce110_timing_generator_get_crtc_scanoutpos, .set_early_control = dce110_timing_generator_set_early_control, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h index f14a4d91cd8e..a5d63c626ada 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h @@ -151,11 +151,9 @@ void dce110_timing_generator_set_early_control( uint32_t dce110_timing_generator_get_vblank_counter( struct timing_generator *tg); -/* Get current H and V position */ -void dce110_timing_generator_get_crtc_positions( +void dce110_timing_generator_get_position( struct timing_generator *tg, - int32_t *h_position, - int32_t *v_position); + struct crtc_position *position); /* return true if TG counter is moving. false if TG is stopped */ bool dce110_timing_generator_is_counter_moving(struct timing_generator *tg); @@ -251,9 +249,6 @@ void dce110_tg_program_blank_color(struct timing_generator *tg, void dce110_tg_set_overscan_color(struct timing_generator *tg, const struct tg_color *overscan_color); -void dce110_tg_get_position(struct timing_generator *tg, - struct crtc_position *position); - void dce110_tg_program_timing(struct timing_generator *tg, const struct dc_crtc_timing *timing, bool use_vbios); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c index c95b69446ced..759c55bb4d15 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c @@ -570,24 +570,11 @@ static void dce110_timing_generator_v_set_early_control( dm_write_reg(tg->ctx, address, regval); } -static void dce110_timing_generator_v_get_crtc_positions( - struct timing_generator *tg, - int32_t *h_position, - int32_t *v_position) +static void dce110_timing_generator_get_underlay_position(struct timing_generator *tg, + struct crtc_position *position) { - uint32_t value; - - value = dm_read_reg(tg->ctx, mmCRTCV_STATUS_POSITION); - - *h_position = get_reg_field_value( - value, - CRTCV_STATUS_POSITION, - CRTC_HORZ_COUNT); - - *v_position = get_reg_field_value( - value, - CRTCV_STATUS_POSITION, - CRTC_VERT_COUNT); + //Should never hit this case + ASSERT(false); } static uint32_t dce110_timing_generator_v_get_vblank_counter(struct timing_generator *tg) @@ -665,7 +652,7 @@ static const struct timing_generator_funcs dce110_tg_v_funcs = { .enable_crtc = dce110_timing_generator_v_enable_crtc, .disable_crtc = dce110_timing_generator_v_disable_crtc, .is_counter_moving = dce110_timing_generator_v_is_counter_moving, - .get_position = dce110_timing_generator_v_get_crtc_positions, + .get_position = dce110_timing_generator_get_underlay_position, .get_frame_count = dce110_timing_generator_v_get_vblank_counter, .set_early_control = dce110_timing_generator_v_set_early_control, .wait_for_state = dce110_timing_generator_v_wait_for_state, diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c index 1318df7ed47e..245356e72b36 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c @@ -180,10 +180,9 @@ uint32_t dce120_timing_generator_get_vblank_counter( } /* Get current H and V position */ -void dce120_timing_generator_get_crtc_positions( +void dce120_timing_generator_get_crtc_position( struct timing_generator *tg, - int32_t *h_position, - int32_t *v_position) + struct crtc_position *position) { struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); uint32_t value = dm_read_reg_soc15( @@ -191,11 +190,19 @@ void dce120_timing_generator_get_crtc_positions( mmCRTC0_CRTC_STATUS_POSITION, tg110->offsets.crtc); - *h_position = get_reg_field_value( - value, CRTC0_CRTC_STATUS_POSITION, CRTC_HORZ_COUNT); + position->horizontal_count = get_reg_field_value(value, + CRTC0_CRTC_STATUS_POSITION, CRTC_HORZ_COUNT); - *v_position = get_reg_field_value( - value, CRTC0_CRTC_STATUS_POSITION, CRTC_VERT_COUNT); + position->vertical_count = get_reg_field_value(value, + CRTC0_CRTC_STATUS_POSITION, CRTC_VERT_COUNT); + + value = dm_read_reg_soc15( + tg->ctx, + mmCRTC0_CRTC_NOM_VERT_POSITION, + tg110->offsets.crtc); + + position->nominal_vcount = get_reg_field_value(value, + CRTC0_CRTC_NOM_VERT_POSITION, CRTC_VERT_COUNT_NOM); } /* wait until TG is in beginning of vertical blank region */ @@ -576,6 +583,49 @@ void dce120_timing_generator_set_drr( } } +/** + ***************************************************************************** + * Function: dce120_timing_generator_get_position + * + * @brief + * Returns CRTC vertical/horizontal counters + * + * @param [out] position + ***************************************************************************** + */ +void dce120_timing_generator_get_position(struct timing_generator *tg, + struct crtc_position *position) +{ + uint32_t value; + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + value = dm_read_reg_soc15( + tg->ctx, + mmCRTC0_CRTC_STATUS_POSITION, + tg110->offsets.crtc); + + position->horizontal_count = get_reg_field_value( + value, + CRTC0_CRTC_STATUS_POSITION, + CRTC_HORZ_COUNT); + + position->vertical_count = get_reg_field_value( + value, + CRTC0_CRTC_STATUS_POSITION, + CRTC_VERT_COUNT); + + value = dm_read_reg_soc15( + tg->ctx, + mmCRTC0_CRTC_NOM_VERT_POSITION, + tg110->offsets.crtc); + + position->nominal_vcount = get_reg_field_value( + value, + CRTC0_CRTC_NOM_VERT_POSITION, + CRTC_VERT_COUNT_NOM); +} + + void dce120_timing_generator_get_crtc_scanoutpos( struct timing_generator *tg, uint32_t *v_blank_start, @@ -584,6 +634,7 @@ void dce120_timing_generator_get_crtc_scanoutpos( uint32_t *v_position) { struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + struct crtc_position position; uint32_t v_blank_start_end = dm_read_reg_soc15( tg->ctx, @@ -597,7 +648,11 @@ void dce120_timing_generator_get_crtc_scanoutpos( CRTC0_CRTC_V_BLANK_START_END, CRTC_V_BLANK_END); - dce120_timing_generator_get_crtc_positions(tg, h_position, v_position); + dce120_timing_generator_get_crtc_position( + tg, &position); + + *h_position = position.horizontal_count; + *v_position = position.vertical_count; } void dce120_timing_generator_enable_advanced_request( @@ -1076,7 +1131,7 @@ static struct timing_generator_funcs dce120_tg_funcs = { /* used by enable_timing_synchronization. Not need for FPGA */ .is_counter_moving = dce110_timing_generator_is_counter_moving, /* never be called */ - .get_position = dce120_timing_generator_get_crtc_positions, + .get_position = dce120_timing_generator_get_crtc_position, .get_frame_count = dce120_timing_generator_get_vblank_counter, .get_scanoutpos = dce120_timing_generator_get_crtc_scanoutpos, .set_early_control = dce120_timing_generator_set_early_control, diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c index 1198f2fbf9c7..179a6d604838 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c @@ -121,7 +121,7 @@ static const struct timing_generator_funcs dce80_tg_funcs = { .enable_crtc = dce110_timing_generator_enable_crtc, .disable_crtc = dce110_timing_generator_disable_crtc, .is_counter_moving = dce110_timing_generator_is_counter_moving, - .get_position = dce110_timing_generator_get_crtc_positions, + .get_position = dce110_timing_generator_get_position, .get_frame_count = dce110_timing_generator_get_vblank_counter, .get_scanoutpos = dce110_timing_generator_get_crtc_scanoutpos, .set_early_control = dce110_timing_generator_set_early_control, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h index 235cfe8d1ad4..2c4a9d02b3c1 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h @@ -30,9 +30,9 @@ struct dc_bios; /* Contains CRTC vertical/horizontal pixel counters */ struct crtc_position { - uint32_t vertical_count; - uint32_t horizontal_count; - uint32_t nominal_vcount; + int32_t vertical_count; + int32_t horizontal_count; + int32_t nominal_vcount; }; struct dcp_gsl_params { @@ -105,8 +105,8 @@ struct timing_generator_funcs { bool (*disable_crtc)(struct timing_generator *tg); bool (*is_counter_moving)(struct timing_generator *tg); void (*get_position)(struct timing_generator *tg, - int32_t *h_position, - int32_t *v_position); + struct crtc_position *position); + uint32_t (*get_frame_count)(struct timing_generator *tg); void (*get_scanoutpos)( struct timing_generator *tg, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index b42e4a0ef18a..afdb8605a30f 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -131,6 +131,9 @@ struct hw_sequencer_funcs { void (*set_drr)(struct pipe_ctx **pipe_ctx, int num_pipes, int vmin, int vmax); + void (*get_position)(struct pipe_ctx **pipe_ctx, int num_pipes, + struct crtc_position *position); + void (*set_static_screen_control)(struct pipe_ctx **pipe_ctx, int num_pipes, const struct dc_static_screen_events *events); diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index 78b4f28d862c..f6223e6b3536 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -76,6 +76,16 @@ struct fixed_refresh { bool program_fixed_refresh; }; +struct freesync_range { + unsigned int min_refresh; + unsigned int max_frame_duration; + unsigned int vmax; + + unsigned int max_refresh; + unsigned int min_frame_duration; + unsigned int vmin; +}; + struct freesync_state { bool fullscreen; bool static_screen; @@ -89,6 +99,7 @@ struct freesync_state { struct gradual_static_ramp static_ramp; struct below_the_range btr; struct fixed_refresh fixed_refresh; + struct freesync_range freesync_range; }; struct freesync_entity { @@ -342,8 +353,11 @@ static void update_stream(struct core_freesync *core_freesync, } } -static void calc_vmin_vmax(struct core_freesync *core_freesync, - const struct dc_stream *stream, int *vmin, int *vmax) +static void calc_freesync_range(struct core_freesync *core_freesync, + const struct dc_stream *stream, + struct freesync_state *state, + unsigned int min_refresh_in_uhz, + unsigned int max_refresh_in_uhz) { unsigned int min_frame_duration_in_ns = 0, max_frame_duration_in_ns = 0; unsigned int index = map_index_from_stream(core_freesync, stream); @@ -351,29 +365,50 @@ static void calc_vmin_vmax(struct core_freesync *core_freesync, min_frame_duration_in_ns = ((unsigned int) (div64_u64( (1000000000ULL * 1000000), - core_freesync->map[index].state. - nominal_refresh_rate_in_micro_hz))); + max_refresh_in_uhz))); max_frame_duration_in_ns = ((unsigned int) (div64_u64( - (1000000000ULL * 1000000), - core_freesync->map[index].caps->min_refresh_in_micro_hz))); + (1000000000ULL * 1000000), + min_refresh_in_uhz))); + + state->freesync_range.min_refresh = min_refresh_in_uhz; + state->freesync_range.max_refresh = max_refresh_in_uhz; - *vmax = div64_u64(div64_u64(((unsigned long long)( - max_frame_duration_in_ns) * stream->timing.pix_clk_khz), - stream->timing.h_total), 1000000); - *vmin = div64_u64(div64_u64(((unsigned long long)( - min_frame_duration_in_ns) * stream->timing.pix_clk_khz), - stream->timing.h_total), 1000000); + state->freesync_range.max_frame_duration = max_frame_duration_in_ns; + state->freesync_range.min_frame_duration = min_frame_duration_in_ns; + + state->freesync_range.vmax = div64_u64(div64_u64(((unsigned long long)( + max_frame_duration_in_ns) * stream->timing.pix_clk_khz), + stream->timing.h_total), 1000000); + state->freesync_range.vmin = div64_u64(div64_u64(((unsigned long long)( + min_frame_duration_in_ns) * stream->timing.pix_clk_khz), + stream->timing.h_total), 1000000); /* In case of 4k free sync monitor, vmin or vmax cannot be less than vtotal */ - if (*vmin < vtotal) { + if (state->freesync_range.vmin < vtotal) { ASSERT(false); - *vmin = vtotal; + state->freesync_range.vmin = vtotal; } - if (*vmax < vtotal) { + if (state->freesync_range.vmax < vtotal) { ASSERT(false); - *vmax = vtotal; + state->freesync_range.vmax = vtotal; } + + /* Determine whether BTR can be supported */ + if (max_frame_duration_in_ns >= + 2 * min_frame_duration_in_ns) + core_freesync->map[index].caps->btr_supported = true; + else + core_freesync->map[index].caps->btr_supported = false; + + /* Cache the time variables */ + state->time.max_render_time_in_us = + max_frame_duration_in_ns / 1000; + state->time.min_render_time_in_us = + min_frame_duration_in_ns / 1000; + state->btr.mid_point_in_us = + (max_frame_duration_in_ns + + min_frame_duration_in_ns) / 2000; } static void calc_v_total_from_duration(const struct dc_stream *stream, @@ -518,9 +553,8 @@ static bool set_freesync_on_streams(struct core_freesync *core_freesync, state->fixed_refresh.fixed_refresh_active == false) { /* Enable freesync */ - calc_vmin_vmax(core_freesync, - streams[stream_idx], - &v_total_min, &v_total_max); + v_total_min = state->freesync_range.vmin; + v_total_max = state->freesync_range.vmax; /* Update the freesync context for the stream */ update_stream_freesync_context(core_freesync, @@ -696,7 +730,7 @@ void mod_freesync_handle_v_update(struct mod_freesync *mod_freesync, (1000000000ULL * 1000000), state->nominal_refresh_rate_in_micro_hz))); - calc_vmin_vmax(core_freesync, *streams, &vmin, &vmax); + vmin = state->freesync_range.vmin; inserted_frame_v_total = vmin; @@ -941,11 +975,120 @@ bool mod_freesync_get_user_enable(struct mod_freesync *mod_freesync, return true; } +bool mod_freesync_override_min_max(struct mod_freesync *mod_freesync, + const struct dc_stream *streams, + unsigned int min_refresh, + unsigned int max_refresh) +{ + unsigned int index = 0; + struct core_freesync *core_freesync; + struct freesync_state *state; + + if (mod_freesync == NULL) + return false; + + core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync); + index = map_index_from_stream(core_freesync, streams); + state = &core_freesync->map[index].state; + + if (min_refresh == 0 || max_refresh == 0) { + /* Restore defaults */ + calc_freesync_range(core_freesync, streams, state, + core_freesync->map[index].caps-> + min_refresh_in_micro_hz, + state->nominal_refresh_rate_in_micro_hz); + } else { + calc_freesync_range(core_freesync, streams, + state, + min_refresh, + max_refresh); + + /* Program vtotal min/max */ + core_freesync->dc->stream_funcs.adjust_vmin_vmax( + core_freesync->dc, &streams, 1, + state->freesync_range.vmin, + state->freesync_range.vmax); + } + + return true; +} + +bool mod_freesync_get_min_max(struct mod_freesync *mod_freesync, + const struct dc_stream *stream, + unsigned int *min_refresh, + unsigned int *max_refresh) +{ + unsigned int index = 0; + struct core_freesync *core_freesync = NULL; + + if (mod_freesync == NULL) + return false; + + core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync); + index = map_index_from_stream(core_freesync, stream); + + *min_refresh = + core_freesync->map[index].state.freesync_range.min_refresh; + *max_refresh = + core_freesync->map[index].state.freesync_range.max_refresh; + + return true; +} + +bool mod_freesync_get_vmin_vmax(struct mod_freesync *mod_freesync, + const struct dc_stream *stream, + unsigned int *vmin, + unsigned int *vmax) +{ + unsigned int index = 0; + struct core_freesync *core_freesync = NULL; + + if (mod_freesync == NULL) + return false; + + core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync); + index = map_index_from_stream(core_freesync, stream); + + *vmin = + core_freesync->map[index].state.freesync_range.vmin; + *vmax = + core_freesync->map[index].state.freesync_range.vmax; + + return true; +} + +bool mod_freesync_get_v_position(struct mod_freesync *mod_freesync, + const struct dc_stream *stream, + unsigned int *nom_v_pos, + unsigned int *v_pos) +{ + unsigned int index = 0; + struct core_freesync *core_freesync = NULL; + struct crtc_position position; + + if (mod_freesync == NULL) + return false; + + core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync); + index = map_index_from_stream(core_freesync, stream); + + if (core_freesync->dc->stream_funcs.get_crtc_position( + core_freesync->dc, &stream, 1, + &position.vertical_count, &position.nominal_vcount)) { + + *nom_v_pos = position.vertical_count; + *v_pos = position.nominal_vcount; + + return true; + } + + return false; +} + void mod_freesync_notify_mode_change(struct mod_freesync *mod_freesync, const struct dc_stream **streams, int num_streams) { unsigned int stream_index, map_index; - unsigned min_frame_duration_in_ns, max_frame_duration_in_ns; struct freesync_state *state; struct core_freesync *core_freesync = NULL; @@ -965,37 +1108,23 @@ void mod_freesync_notify_mode_change(struct mod_freesync *mod_freesync, unsigned long long temp; temp = streams[stream_index]->timing.pix_clk_khz; temp *= 1000ULL * 1000ULL * 1000ULL; - temp = div_u64(temp, streams[stream_index]->timing.h_total); - temp = div_u64(temp, streams[stream_index]->timing.v_total); - state->nominal_refresh_rate_in_micro_hz = (unsigned int) temp; + temp = div_u64(temp, + streams[stream_index]->timing.h_total); + temp = div_u64(temp, + streams[stream_index]->timing.v_total); + state->nominal_refresh_rate_in_micro_hz = + (unsigned int) temp; /* Update the stream */ update_stream(core_freesync, streams[stream_index]); - /* Determine whether BTR can be supported */ - min_frame_duration_in_ns = ((unsigned int) (div64_u64( - (1000000000ULL * 1000000), - state->nominal_refresh_rate_in_micro_hz))); - - max_frame_duration_in_ns = ((unsigned int) (div64_u64( - (1000000000ULL * 1000000), - core_freesync->map[map_index].caps->min_refresh_in_micro_hz))); - - if (max_frame_duration_in_ns >= - 2 * min_frame_duration_in_ns) - core_freesync->map[map_index].caps->btr_supported = true; - else - core_freesync->map[map_index].caps->btr_supported = false; - - /* Cache the time variables */ - state->time.max_render_time_in_us = - max_frame_duration_in_ns / 1000; - state->time.min_render_time_in_us = - min_frame_duration_in_ns / 1000; - state->btr.mid_point_in_us = - (max_frame_duration_in_ns + - min_frame_duration_in_ns) / 2000; - + /* Calculate vmin/vmax and refresh rate for + * current mode + */ + calc_freesync_range(core_freesync, *streams, state, + core_freesync->map[stream_index].caps-> + min_refresh_in_micro_hz, + state->nominal_refresh_rate_in_micro_hz); } } @@ -1178,7 +1307,7 @@ static void apply_fixed_refresh(struct core_freesync *core_freesync, /* Fixed Refresh set to "active" so engage (fix to max) */ } else { - calc_vmin_vmax(core_freesync, stream, &vmin, &vmax); + vmin = state->freesync_range.vmin; vmax = vmin; diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h b/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h index 783ff2ef3bee..3947cc412ad7 100644 --- a/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h +++ b/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h @@ -129,6 +129,26 @@ bool mod_freesync_get_user_enable(struct mod_freesync *mod_freesync, const struct dc_stream *stream, struct mod_freesync_user_enable *user_enable); +bool mod_freesync_override_min_max(struct mod_freesync *mod_freesync, + const struct dc_stream *streams, + unsigned int min_refresh, + unsigned int max_refresh); + +bool mod_freesync_get_min_max(struct mod_freesync *mod_freesync, + const struct dc_stream *stream, + unsigned int *min_refresh, + unsigned int *max_refresh); + +bool mod_freesync_get_vmin_vmax(struct mod_freesync *mod_freesync, + const struct dc_stream *stream, + unsigned int *vmin, + unsigned int *vmax); + +bool mod_freesync_get_v_position(struct mod_freesync *mod_freesync, + const struct dc_stream *stream, + unsigned int *nom_v_pos, + unsigned int *v_pos); + void mod_freesync_handle_v_update(struct mod_freesync *mod_freesync, const struct dc_stream **streams, int num_streams); -- cgit From a2b8659db9b435853cb0dc78d225a492e7ee69d0 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Sat, 22 Apr 2017 14:17:51 -0400 Subject: drm/amd/display: decouple resource_pool from resource_context to avoid null access in case res_ctx is used to access res_pool before it's fully constructed also make it clear which function has dependency on resource_pool Signed-off-by: Tony Cheng Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 19 ++- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 143 ++++++++++++--------- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_surface.c | 3 +- .../amd/display/dc/dce100/dce100_hw_sequencer.c | 4 +- .../drm/amd/display/dc/dce100/dce100_resource.c | 8 +- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 42 +++--- .../drm/amd/display/dc/dce110/dce110_resource.c | 25 ++-- .../drm/amd/display/dc/dce112/dce112_resource.c | 35 +++-- .../gpu/drm/amd/display/dc/dce80/dce80_resource.c | 8 +- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 2 +- drivers/gpu/drm/amd/display/dc/inc/resource.h | 15 ++- 13 files changed, 161 insertions(+), 147 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 2e74faef68e7..37986632f025 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -736,7 +736,7 @@ static void program_timing_sync( { int i, j; int group_index = 0; - int pipe_count = ctx->res_ctx.pool->pipe_count; + int pipe_count = core_dc->res_pool->pipe_count; struct pipe_ctx *unsynced_pipes[MAX_PIPES] = { NULL }; for (i = 0; i < pipe_count; i++) { @@ -939,7 +939,7 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) post_surface_trace(dc); - for (i = 0; i < context->res_ctx.pool->pipe_count; i++) + for (i = 0; i < core_dc->res_pool->pipe_count; i++) if (context->res_ctx.pipe_ctx[i].stream == NULL) { context->res_ctx.pipe_ctx[i].pipe_idx = i; core_dc->hwss.power_down_front_end( @@ -1015,7 +1015,7 @@ static bool is_surface_in_context( { int j; - for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { + for (j = 0; j < MAX_PIPES; j++) { const struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; if (surface == &pipe_ctx->surface->public) { @@ -1245,7 +1245,8 @@ void dc_update_surfaces_and_stream(struct dc *dc, /* add surface to context */ if (!resource_attach_surfaces_to_context( - new_surfaces, surface_count, dc_stream, context)) { + new_surfaces, surface_count, dc_stream, + context, core_dc->res_pool)) { BREAK_TO_DEBUGGER(); goto fail; } @@ -1304,7 +1305,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, /* not sure if we still need this */ if (update_type == UPDATE_TYPE_FULL) { - for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { + for (j = 0; j < core_dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; if (pipe_ctx->surface != surface) @@ -1365,7 +1366,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, for (i = 0; i < surface_count; i++) { struct core_surface *surface = DC_SURFACE_TO_CORE(srf_updates[i].surface); - for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { + for (j = 0; j < core_dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; if (pipe_ctx->surface != surface) @@ -1389,7 +1390,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, context_timing_trace(dc, &context->res_ctx); } - for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { + for (j = 0; j < core_dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; struct pipe_ctx *cur_pipe_ctx; bool is_new_pipe_surface = true; @@ -1427,7 +1428,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, } /* Unlock pipes */ - for (i = context->res_ctx.pool->pipe_count - 1; i >= 0; i--) { + for (i = core_dc->res_pool->pipe_count - 1; i >= 0; i--) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; for (j = 0; j < surface_count; j++) { @@ -1571,8 +1572,6 @@ void dc_set_power_state( memset(core_dc->current_context, 0, sizeof(*core_dc->current_context)); - core_dc->current_context->res_ctx.pool = core_dc->res_pool; - break; } 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 f883fdb820c8..4b9d3f12406f 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 @@ -2245,7 +2245,7 @@ static void set_crtc_test_pattern(struct core_link *link, case DP_TEST_PATTERN_VIDEO_MODE: { /* restore bitdepth reduction */ - link->dc->current_context->res_ctx.pool->funcs-> + link->dc->res_pool->funcs-> build_bit_depth_reduction_params(pipe_ctx->stream, ¶ms); pipe_ctx->stream->bit_depth_params = params; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index cdb98d5f7caa..43e5758719ca 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -233,11 +233,12 @@ bool resource_construct( void resource_unreference_clock_source( struct resource_context *res_ctx, + const struct resource_pool *pool, struct clock_source **clock_source) { int i; - for (i = 0; i < res_ctx->pool->clk_src_count; i++) { - if (res_ctx->pool->clock_sources[i] != *clock_source) + for (i = 0; i < pool->clk_src_count; i++) { + if (pool->clock_sources[i] != *clock_source) continue; res_ctx->clock_source_ref_count[i]--; @@ -248,7 +249,7 @@ void resource_unreference_clock_source( break; } - if (res_ctx->pool->dp_clock_source == *clock_source) { + if (pool->dp_clock_source == *clock_source) { res_ctx->dp_clock_source_ref_count--; if (res_ctx->dp_clock_source_ref_count == 0) @@ -259,18 +260,19 @@ void resource_unreference_clock_source( void resource_reference_clock_source( struct resource_context *res_ctx, + const struct resource_pool *pool, struct clock_source *clock_source) { int i; - for (i = 0; i < res_ctx->pool->clk_src_count; i++) { - if (res_ctx->pool->clock_sources[i] != clock_source) + for (i = 0; i < pool->clk_src_count; i++) { + if (pool->clock_sources[i] != clock_source) continue; res_ctx->clock_source_ref_count[i]++; break; } - if (res_ctx->pool->dp_clock_source == clock_source) + if (pool->dp_clock_source == clock_source) res_ctx->dp_clock_source_ref_count++; } @@ -861,12 +863,13 @@ enum dc_status resource_build_scaling_params_for_context( static void detach_surfaces_for_stream( struct validate_context *context, + const struct resource_pool *pool, const struct dc_stream *dc_stream) { int i; struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); - for (i = 0; i < context->res_ctx.pool->pipe_count; i++) { + for (i = 0; i < pool->pipe_count; i++) { struct pipe_ctx *cur_pipe = &context->res_ctx.pipe_ctx[i]; if (cur_pipe->stream == stream) { cur_pipe->surface = NULL; @@ -876,7 +879,9 @@ static void detach_surfaces_for_stream( } } -struct pipe_ctx *find_idle_secondary_pipe(struct resource_context *res_ctx) +struct pipe_ctx *find_idle_secondary_pipe( + struct resource_context *res_ctx, + const struct resource_pool *pool) { int i; struct pipe_ctx *secondary_pipe = NULL; @@ -886,7 +891,7 @@ struct pipe_ctx *find_idle_secondary_pipe(struct resource_context *res_ctx) * assignment more consistent */ - for (i = res_ctx->pool->pipe_count - 1; i >= 0; i--) { + for (i = pool->pipe_count - 1; i >= 0; i--) { if (res_ctx->pipe_ctx[i].stream == NULL) { secondary_pipe = &res_ctx->pipe_ctx[i]; secondary_pipe->pipe_idx = i; @@ -903,7 +908,7 @@ struct pipe_ctx *resource_get_head_pipe_for_stream( const struct core_stream *stream) { int i; - for (i = 0; i < res_ctx->pool->pipe_count; i++) { + for (i = 0; i < MAX_PIPES; i++) { if (res_ctx->pipe_ctx[i].stream == stream && res_ctx->pipe_ctx[i].stream_enc) { return &res_ctx->pipe_ctx[i]; @@ -919,6 +924,7 @@ struct pipe_ctx *resource_get_head_pipe_for_stream( */ static struct pipe_ctx *acquire_free_pipe_for_stream( struct validate_context *context, + const struct resource_pool *pool, const struct dc_stream *dc_stream) { int i; @@ -938,7 +944,7 @@ static struct pipe_ctx *acquire_free_pipe_for_stream( return head_pipe; /* Re-use pipe already acquired for this stream if available*/ - for (i = res_ctx->pool->pipe_count - 1; i >= 0; i--) { + for (i = pool->pipe_count - 1; i >= 0; i--) { if (res_ctx->pipe_ctx[i].stream == stream && !res_ctx->pipe_ctx[i].surface) { return &res_ctx->pipe_ctx[i]; @@ -950,10 +956,10 @@ static struct pipe_ctx *acquire_free_pipe_for_stream( * to acquire an idle one to satisfy the request */ - if(!res_ctx->pool->funcs->acquire_idle_pipe_for_layer) + if (!pool->funcs->acquire_idle_pipe_for_layer) return NULL; - return res_ctx->pool->funcs->acquire_idle_pipe_for_layer(context, stream); + return pool->funcs->acquire_idle_pipe_for_layer(context, pool, stream); } @@ -964,7 +970,7 @@ static void release_free_pipes_for_stream( int i; struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); - for (i = res_ctx->pool->pipe_count - 1; i >= 0; i--) { + for (i = MAX_PIPES - 1; i >= 0; i--) { if (res_ctx->pipe_ctx[i].stream == stream && !res_ctx->pipe_ctx[i].surface) { res_ctx->pipe_ctx[i].stream = NULL; @@ -976,7 +982,8 @@ bool resource_attach_surfaces_to_context( const struct dc_surface * const *surfaces, int surface_count, const struct dc_stream *dc_stream, - struct validate_context *context) + struct validate_context *context, + const struct resource_pool *pool) { int i; struct pipe_ctx *tail_pipe; @@ -1003,7 +1010,7 @@ bool resource_attach_surfaces_to_context( for (i = 0; i < surface_count; i++) dc_surface_retain(surfaces[i]); - detach_surfaces_for_stream(context, dc_stream); + detach_surfaces_for_stream(context, pool, dc_stream); /* release existing surfaces*/ for (i = 0; i < stream_status->surface_count; i++) @@ -1020,7 +1027,8 @@ bool resource_attach_surfaces_to_context( tail_pipe = NULL; for (i = 0; i < surface_count; i++) { struct core_surface *surface = DC_SURFACE_TO_CORE(surfaces[i]); - struct pipe_ctx *free_pipe = acquire_free_pipe_for_stream(context, dc_stream); + struct pipe_ctx *free_pipe = acquire_free_pipe_for_stream( + context, pool, dc_stream); if (!free_pipe) { stream_status->surfaces[i] = NULL; @@ -1101,7 +1109,8 @@ bool resource_validate_attach_surfaces( const struct dc_validation_set set[], int set_count, const struct validate_context *old_context, - struct validate_context *context) + struct validate_context *context, + const struct resource_pool *pool) { int i, j; @@ -1114,7 +1123,7 @@ bool resource_validate_attach_surfaces( old_context->stream_status[j].surfaces, old_context->stream_status[j].surface_count, &context->streams[i]->public, - context)) + context, pool)) return false; context->stream_status[i] = old_context->stream_status[j]; } @@ -1123,7 +1132,7 @@ bool resource_validate_attach_surfaces( set[i].surfaces, set[i].surface_count, &context->streams[i]->public, - context)) + context, pool)) return false; } @@ -1136,12 +1145,13 @@ bool resource_validate_attach_surfaces( static void set_stream_engine_in_use( struct resource_context *res_ctx, + const struct resource_pool *pool, struct stream_encoder *stream_enc) { int i; - for (i = 0; i < res_ctx->pool->stream_enc_count; i++) { - if (res_ctx->pool->stream_enc[i] == stream_enc) + for (i = 0; i < pool->stream_enc_count; i++) { + if (pool->stream_enc[i] == stream_enc) res_ctx->is_stream_enc_acquired[i] = true; } } @@ -1149,32 +1159,33 @@ static void set_stream_engine_in_use( /* TODO: release audio object */ static void set_audio_in_use( struct resource_context *res_ctx, + const struct resource_pool *pool, struct audio *audio) { int i; - for (i = 0; i < res_ctx->pool->audio_count; i++) { - if (res_ctx->pool->audios[i] == audio) { + for (i = 0; i < pool->audio_count; i++) { + if (pool->audios[i] == audio) res_ctx->is_audio_acquired[i] = true; - } } } static int acquire_first_free_pipe( struct resource_context *res_ctx, + const struct resource_pool *pool, struct core_stream *stream) { int i; - for (i = 0; i < res_ctx->pool->pipe_count; i++) { + for (i = 0; i < pool->pipe_count; i++) { if (!res_ctx->pipe_ctx[i].stream) { struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; - pipe_ctx->tg = res_ctx->pool->timing_generators[i]; - pipe_ctx->mi = res_ctx->pool->mis[i]; - pipe_ctx->ipp = res_ctx->pool->ipps[i]; - pipe_ctx->xfm = res_ctx->pool->transforms[i]; - pipe_ctx->opp = res_ctx->pool->opps[i]; - pipe_ctx->dis_clk = res_ctx->pool->display_clock; + pipe_ctx->tg = pool->timing_generators[i]; + pipe_ctx->mi = pool->mis[i]; + pipe_ctx->ipp = pool->ipps[i]; + pipe_ctx->xfm = pool->transforms[i]; + pipe_ctx->opp = pool->opps[i]; + pipe_ctx->dis_clk = pool->display_clock; pipe_ctx->pipe_idx = i; pipe_ctx->stream = stream; @@ -1186,21 +1197,22 @@ static int acquire_first_free_pipe( static struct stream_encoder *find_first_free_match_stream_enc_for_link( struct resource_context *res_ctx, + const struct resource_pool *pool, struct core_stream *stream) { int i; int j = -1; struct core_link *link = stream->sink->link; - for (i = 0; i < res_ctx->pool->stream_enc_count; i++) { + for (i = 0; i < pool->stream_enc_count; i++) { if (!res_ctx->is_stream_enc_acquired[i] && - res_ctx->pool->stream_enc[i]) { + pool->stream_enc[i]) { /* Store first available for MST second display * in daisy chain use case */ j = i; - if (res_ctx->pool->stream_enc[i]->id == + if (pool->stream_enc[i]->id == link->link_enc->preferred_engine) - return res_ctx->pool->stream_enc[i]; + return pool->stream_enc[i]; } } @@ -1218,17 +1230,19 @@ static struct stream_encoder *find_first_free_match_stream_enc_for_link( */ if (j >= 0 && dc_is_dp_signal(stream->signal)) - return res_ctx->pool->stream_enc[j]; + return pool->stream_enc[j]; return NULL; } -static struct audio *find_first_free_audio(struct resource_context *res_ctx) +static struct audio *find_first_free_audio( + struct resource_context *res_ctx, + const struct resource_pool *pool) { int i; - for (i = 0; i < res_ctx->pool->audio_count; i++) { + for (i = 0; i < pool->audio_count; i++) { if (res_ctx->is_audio_acquired[i] == false) { - return res_ctx->pool->audios[i]; + return pool->audios[i]; } } @@ -1358,6 +1372,7 @@ enum dc_status resource_map_pool_resources( const struct core_dc *dc, struct validate_context *context) { + const struct resource_pool *pool = dc->res_pool; int i, j; calculate_phy_pix_clks(dc, context); @@ -1370,12 +1385,12 @@ enum dc_status resource_map_pool_resources( stream->bit_depth_params = dc->current_context->streams[i]->bit_depth_params; stream->clamping = dc->current_context->streams[i]->clamping; - continue; + continue; + } } - } /* mark resources used for stream that is already active */ - for (j = 0; j < MAX_PIPES; j++) { + for (j = 0; j < pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; const struct pipe_ctx *old_pipe_ctx = @@ -1395,7 +1410,7 @@ enum dc_status resource_map_pool_resources( continue; set_stream_engine_in_use( - &context->res_ctx, + &context->res_ctx, pool, pipe_ctx->stream_enc); /* Switch to dp clock source only if there is @@ -1404,15 +1419,14 @@ enum dc_status resource_map_pool_resources( */ if (dc_is_dp_signal(pipe_ctx->stream->signal) && !find_pll_sharable_stream(stream, context)) - pipe_ctx->clock_source = - context->res_ctx.pool->dp_clock_source; + pipe_ctx->clock_source = pool->dp_clock_source; resource_reference_clock_source( - &context->res_ctx, + &context->res_ctx, pool, pipe_ctx->clock_source); - set_audio_in_use(&context->res_ctx, - pipe_ctx->audio); + set_audio_in_use(&context->res_ctx, pool, + pipe_ctx->audio); } } @@ -1424,22 +1438,22 @@ enum dc_status resource_map_pool_resources( if (resource_is_stream_unchanged(dc->current_context, stream)) continue; /* acquire new resources */ - pipe_idx = acquire_first_free_pipe(&context->res_ctx, stream); + pipe_idx = acquire_first_free_pipe( + &context->res_ctx, pool, stream); if (pipe_idx < 0) return DC_NO_CONTROLLER_RESOURCE; - pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx]; pipe_ctx->stream_enc = find_first_free_match_stream_enc_for_link( - &context->res_ctx, stream); + &context->res_ctx, pool, stream); if (!pipe_ctx->stream_enc) return DC_NO_STREAM_ENG_RESOURCE; set_stream_engine_in_use( - &context->res_ctx, + &context->res_ctx, pool, pipe_ctx->stream_enc); /* TODO: Add check if ASIC support and EDID audio */ @@ -1447,7 +1461,7 @@ enum dc_status resource_map_pool_resources( dc_is_audio_capable_signal(pipe_ctx->stream->signal) && stream->public.audio_info.mode_count) { pipe_ctx->audio = find_first_free_audio( - &context->res_ctx); + &context->res_ctx, pool); /* * Audio assigned in order first come first get. @@ -1456,7 +1470,7 @@ enum dc_status resource_map_pool_resources( */ if (pipe_ctx->audio) set_audio_in_use( - &context->res_ctx, + &context->res_ctx, pool, pipe_ctx->audio); } @@ -2077,7 +2091,7 @@ void dc_resource_validate_ctx_copy_construct( *dst_ctx = *src_ctx; - for (i = 0; i < dst_ctx->res_ctx.pool->pipe_count; i++) { + for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *cur_pipe = &dst_ctx->res_ctx.pipe_ctx[i]; if (cur_pipe->top_pipe) @@ -2097,13 +2111,14 @@ void dc_resource_validate_ctx_copy_construct( } struct clock_source *dc_resource_find_first_free_pll( - struct resource_context *res_ctx) + struct resource_context *res_ctx, + const struct resource_pool *pool) { int i; - for (i = 0; i < res_ctx->pool->clk_src_count; ++i) { + for (i = 0; i < pool->clk_src_count; ++i) { if (res_ctx->clock_source_ref_count[i] == 0) - return res_ctx->pool->clock_sources[i]; + return pool->clock_sources[i]; } return NULL; @@ -2151,6 +2166,7 @@ enum dc_status resource_map_clock_resources( struct validate_context *context) { int i, j; + const struct resource_pool *pool = dc->res_pool; /* acquire new resources */ for (i = 0; i < context->stream_count; i++) { @@ -2168,8 +2184,7 @@ enum dc_status resource_map_clock_resources( if (dc_is_dp_signal(pipe_ctx->stream->signal) || pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL) - pipe_ctx->clock_source = - context->res_ctx.pool->dp_clock_source; + pipe_ctx->clock_source = pool->dp_clock_source; else { pipe_ctx->clock_source = NULL; @@ -2180,14 +2195,16 @@ enum dc_status resource_map_clock_resources( if (pipe_ctx->clock_source == NULL) pipe_ctx->clock_source = - dc_resource_find_first_free_pll(&context->res_ctx); + dc_resource_find_first_free_pll( + &context->res_ctx, + pool); } if (pipe_ctx->clock_source == NULL) return DC_NO_CLOCK_SOURCE_RESOURCE; resource_reference_clock_source( - &context->res_ctx, + &context->res_ctx, pool, pipe_ctx->clock_source); /* only one cs per stream regardless of mpo */ diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 23627b14c16c..99b6a1695f26 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -240,7 +240,7 @@ bool dc_stream_set_cursor_position( struct dc_cursor_position pos_cpy = *position; struct dc_cursor_mi_param param = { .pixel_clk_khz = dc_stream->timing.pix_clk_khz, - .ref_clk_khz = res_ctx->pool->ref_clock_inKhz, + .ref_clk_khz = core_dc->res_pool->ref_clock_inKhz, .viewport_x_start = pipe_ctx->scl_data.viewport.x, .viewport_width = pipe_ctx->scl_data.viewport.width, .h_scale_ratio = pipe_ctx->scl_data.ratios.horz diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index 943895faee49..aa6ac9596235 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -138,8 +138,7 @@ const struct dc_surface_status *dc_surface_get_status( if (core_dc->current_context == NULL) return NULL; - for (i = 0; i < core_dc->current_context->res_ctx.pool->pipe_count; - i++) { + for (i = 0; i < core_dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = &core_dc->current_context->res_ctx.pipe_ctx[i]; diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c index dd6f0b1bd8ae..30c197f378dc 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c @@ -132,8 +132,8 @@ void dce100_set_bandwidth( bool decrease_allowed) { if (decrease_allowed || context->dispclk_khz > dc->current_context->dispclk_khz) { - context->res_ctx.pool->display_clock->funcs->set_clock( - context->res_ctx.pool->display_clock, + dc->res_pool->display_clock->funcs->set_clock( + dc->res_pool->display_clock, context->dispclk_khz * 115 / 100); dc->current_context->bw_results.dispclk_khz = context->dispclk_khz; dc->current_context->dispclk_khz = context->dispclk_khz; diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index f65b785220e2..f0700706d7c9 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -804,8 +804,6 @@ enum dc_status dce100_validate_with_context( if (!dce100_validate_surface_sets(set, set_count)) return DC_FAIL_SURFACE_VALIDATE; - context->res_ctx.pool = dc->res_pool; - for (i = 0; i < set_count; i++) { context->streams[i] = DC_STREAM_TO_CORE(set[i].stream); dc_stream_retain(&context->streams[i]->public); @@ -817,8 +815,8 @@ enum dc_status dce100_validate_with_context( if (result == DC_OK) result = resource_map_clock_resources(dc, context); - if (!resource_validate_attach_surfaces( - set, set_count, dc->current_context, context)) { + if (!resource_validate_attach_surfaces(set, set_count, + dc->current_context, context, dc->res_pool)) { DC_ERROR("Failed to attach surface to stream!\n"); return DC_FAIL_ATTACH_SURFACES; } @@ -843,8 +841,6 @@ enum dc_status dce100_validate_guaranteed( { enum dc_status result = DC_ERROR_UNEXPECTED; - context->res_ctx.pool = dc->res_pool; - context->streams[0] = DC_STREAM_TO_CORE(dc_stream); dc_stream_retain(&context->streams[0]->public); context->stream_count++; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 0e69aceb0bad..dc4c16416370 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1260,10 +1260,12 @@ void dce110_set_displaymarks( } } -static void set_safe_displaymarks(struct resource_context *res_ctx) +static void set_safe_displaymarks( + struct resource_context *res_ctx, + const struct resource_pool *pool) { int i; - int underlay_idx = res_ctx->pool->underlay_pipe_index; + int underlay_idx = pool->underlay_pipe_index; struct bw_watermarks max_marks = { MAX_WATERMARK, MAX_WATERMARK, MAX_WATERMARK, MAX_WATERMARK }; struct bw_watermarks nbp_marks = { @@ -1308,9 +1310,11 @@ static void switch_dp_clock_sources( if (clk_src && clk_src != pipe_ctx->clock_source) { resource_unreference_clock_source( - res_ctx, &pipe_ctx->clock_source); + res_ctx, dc->res_pool, + &pipe_ctx->clock_source); pipe_ctx->clock_source = clk_src; - resource_reference_clock_source(res_ctx, clk_src); + resource_reference_clock_source( + res_ctx, dc->res_pool, clk_src); dce_crtc_switch_to_clk_src(dc->hwseq, clk_src, i); } @@ -1336,8 +1340,8 @@ static void reset_single_pipe_hw_ctx( pipe_ctx->tg->funcs->disable_crtc(pipe_ctx->tg); pipe_ctx->mi->funcs->free_mem_input( pipe_ctx->mi, context->stream_count); - resource_unreference_clock_source( - &context->res_ctx, &pipe_ctx->clock_source); + resource_unreference_clock_source(&context->res_ctx, dc->res_pool, + &pipe_ctx->clock_source); dc->hwss.power_down_front_end((struct core_dc *)dc, pipe_ctx); @@ -1530,7 +1534,7 @@ static enum dc_status apply_ctx_to_hw_fpga( enum dc_status status = DC_ERROR_UNEXPECTED; int i; - for (i = 0; i < context->res_ctx.pool->pipe_count; i++) { + for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe_ctx_old = &dc->current_context->res_ctx.pipe_ctx[i]; struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; @@ -1561,7 +1565,7 @@ static void reset_hw_ctx_wrap( /* Reset old context */ /* look up the targets that have been removed since last commit */ - for (i = 0; i < context->res_ctx.pool->pipe_count; i++) { + for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe_ctx_old = &dc->current_context->res_ctx.pipe_ctx[i]; struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; @@ -1609,7 +1613,7 @@ enum dc_status dce110_apply_ctx_to_hw( dcb->funcs->set_scratch_critical_state(dcb, true); /* below is for real asic only */ - for (i = 0; i < context->res_ctx.pool->pipe_count; i++) { + for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx_old = &dc->current_context->res_ctx.pipe_ctx[i]; struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; @@ -1629,14 +1633,14 @@ enum dc_status dce110_apply_ctx_to_hw( PIPE_GATING_CONTROL_DISABLE); } - set_safe_displaymarks(&context->res_ctx); + set_safe_displaymarks(&context->res_ctx, dc->res_pool); /*TODO: when pplib works*/ apply_min_clocks(dc, context, &clocks_state, true); if (context->dispclk_khz > dc->current_context->dispclk_khz) { - context->res_ctx.pool->display_clock->funcs->set_clock( - context->res_ctx.pool->display_clock, + dc->res_pool->display_clock->funcs->set_clock( + dc->res_pool->display_clock, context->dispclk_khz * 115 / 100); } /* program audio wall clock. use HDMI as clock source if HDMI @@ -1658,7 +1662,7 @@ enum dc_status dce110_apply_ctx_to_hw( * find first available pipe with audio, setup audio wall DTO per topology * instead of per pipe. */ - for (i = 0; i < context->res_ctx.pool->pipe_count; i++) { + for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; if (pipe_ctx->stream == NULL) @@ -1685,8 +1689,8 @@ enum dc_status dce110_apply_ctx_to_hw( } /* no HDMI audio is found, try DP audio */ - if (i == context->res_ctx.pool->pipe_count) { - for (i = 0; i < context->res_ctx.pool->pipe_count; i++) { + if (i == dc->res_pool->pipe_count) { + for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; if (pipe_ctx->stream == NULL) @@ -1713,7 +1717,7 @@ enum dc_status dce110_apply_ctx_to_hw( } } - for (i = 0; i < context->res_ctx.pool->pipe_count; i++) { + for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx_old = &dc->current_context->res_ctx.pipe_ctx[i]; struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; @@ -2297,8 +2301,8 @@ static void dce110_set_bandwidth( dce110_set_displaymarks(dc, context); if (decrease_allowed || context->dispclk_khz > dc->current_context->dispclk_khz) { - context->res_ctx.pool->display_clock->funcs->set_clock( - context->res_ctx.pool->display_clock, + dc->res_pool->display_clock->funcs->set_clock( + dc->res_pool->display_clock, context->dispclk_khz * 115 / 100); dc->current_context->bw_results.dispclk_khz = context->dispclk_khz; dc->current_context->dispclk_khz = context->dispclk_khz; @@ -2446,7 +2450,7 @@ static void dce110_apply_ctx_for_surface( if (!surface) return; - for (i = 0; i < context->res_ctx.pool->pipe_count; i++) { + for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; if (pipe_ctx->surface != surface) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 8dec9a5602a9..122f2d03afc0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -866,7 +866,7 @@ static enum dc_status validate_mapped_resource( continue; if (!is_surface_pixel_format_supported(pipe_ctx, - context->res_ctx.pool->underlay_pipe_index)) + dc->res_pool->underlay_pipe_index)) return DC_SURFACE_PIXEL_FORMAT_UNSUPPORTED; if (!pipe_ctx->tg->funcs->validate_timing( @@ -918,7 +918,7 @@ bool dce110_validate_bandwidth( &dc->bw_dceip, &dc->bw_vbios, context->res_ctx.pipe_ctx, - context->res_ctx.pool->pipe_count, + dc->res_pool->pipe_count, &context->bw_results)) result = true; context->dispclk_khz = context->bw_results.dispclk_khz; @@ -1030,8 +1030,6 @@ enum dc_status dce110_validate_with_context( if (!dce110_validate_surface_sets(set, set_count)) return DC_FAIL_SURFACE_VALIDATE; - context->res_ctx.pool = dc->res_pool; - for (i = 0; i < set_count; i++) { context->streams[i] = DC_STREAM_TO_CORE(set[i].stream); dc_stream_retain(&context->streams[i]->public); @@ -1043,8 +1041,8 @@ enum dc_status dce110_validate_with_context( if (result == DC_OK) result = resource_map_clock_resources(dc, context); - if (!resource_validate_attach_surfaces( - set, set_count, dc->current_context, context)) { + if (!resource_validate_attach_surfaces(set, set_count, + dc->current_context, context, dc->res_pool)) { DC_ERROR("Failed to attach surface to stream!\n"); return DC_FAIL_ATTACH_SURFACES; } @@ -1069,8 +1067,6 @@ enum dc_status dce110_validate_guaranteed( { enum dc_status result = DC_ERROR_UNEXPECTED; - context->res_ctx.pool = dc->res_pool; - context->streams[0] = DC_STREAM_TO_CORE(dc_stream); dc_stream_retain(&context->streams[0]->public); context->stream_count++; @@ -1098,22 +1094,23 @@ enum dc_status dce110_validate_guaranteed( static struct pipe_ctx *dce110_acquire_underlay( struct validate_context *context, + const struct resource_pool *pool, struct core_stream *stream) { struct core_dc *dc = DC_TO_CORE(stream->ctx->dc); struct resource_context *res_ctx = &context->res_ctx; - unsigned int underlay_idx = res_ctx->pool->underlay_pipe_index; + unsigned int underlay_idx = pool->underlay_pipe_index; struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[underlay_idx]; if (res_ctx->pipe_ctx[underlay_idx].stream) return NULL; - pipe_ctx->tg = res_ctx->pool->timing_generators[underlay_idx]; - pipe_ctx->mi = res_ctx->pool->mis[underlay_idx]; + pipe_ctx->tg = pool->timing_generators[underlay_idx]; + pipe_ctx->mi = pool->mis[underlay_idx]; /*pipe_ctx->ipp = res_ctx->pool->ipps[underlay_idx];*/ - pipe_ctx->xfm = res_ctx->pool->transforms[underlay_idx]; - pipe_ctx->opp = res_ctx->pool->opps[underlay_idx]; - pipe_ctx->dis_clk = res_ctx->pool->display_clock; + pipe_ctx->xfm = pool->transforms[underlay_idx]; + pipe_ctx->opp = pool->opps[underlay_idx]; + pipe_ctx->dis_clk = pool->display_clock; pipe_ctx->pipe_idx = underlay_idx; pipe_ctx->stream = stream; diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 4bf75afd5721..4de51a86c9ea 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -749,22 +749,24 @@ static void destruct(struct dce110_resource_pool *pool) } } -static struct clock_source *find_matching_pll(struct resource_context *res_ctx, +static struct clock_source *find_matching_pll( + struct resource_context *res_ctx, + const struct resource_pool *pool, const struct core_stream *const stream) { switch (stream->sink->link->link_enc->transmitter) { case TRANSMITTER_UNIPHY_A: - return res_ctx->pool->clock_sources[DCE112_CLK_SRC_PLL0]; + return pool->clock_sources[DCE112_CLK_SRC_PLL0]; case TRANSMITTER_UNIPHY_B: - return res_ctx->pool->clock_sources[DCE112_CLK_SRC_PLL1]; + return pool->clock_sources[DCE112_CLK_SRC_PLL1]; case TRANSMITTER_UNIPHY_C: - return res_ctx->pool->clock_sources[DCE112_CLK_SRC_PLL2]; + return pool->clock_sources[DCE112_CLK_SRC_PLL2]; case TRANSMITTER_UNIPHY_D: - return res_ctx->pool->clock_sources[DCE112_CLK_SRC_PLL3]; + return pool->clock_sources[DCE112_CLK_SRC_PLL3]; case TRANSMITTER_UNIPHY_E: - return res_ctx->pool->clock_sources[DCE112_CLK_SRC_PLL4]; + return pool->clock_sources[DCE112_CLK_SRC_PLL4]; case TRANSMITTER_UNIPHY_F: - return res_ctx->pool->clock_sources[DCE112_CLK_SRC_PLL5]; + return pool->clock_sources[DCE112_CLK_SRC_PLL5]; default: return NULL; }; @@ -842,7 +844,7 @@ bool dce112_validate_bandwidth( &dc->bw_dceip, &dc->bw_vbios, context->res_ctx.pipe_ctx, - context->res_ctx.pool->pipe_count, + dc->res_pool->pipe_count, &context->bw_results)) result = true; context->dispclk_khz = context->bw_results.dispclk_khz; @@ -928,17 +930,18 @@ enum dc_status resource_map_phy_clock_resources( if (dc_is_dp_signal(pipe_ctx->stream->signal) || pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL) pipe_ctx->clock_source = - context->res_ctx.pool->dp_clock_source; + dc->res_pool->dp_clock_source; else - pipe_ctx->clock_source = - find_matching_pll(&context->res_ctx, - stream); + pipe_ctx->clock_source = find_matching_pll( + &context->res_ctx, dc->res_pool, + stream); if (pipe_ctx->clock_source == NULL) return DC_NO_CLOCK_SOURCE_RESOURCE; resource_reference_clock_source( &context->res_ctx, + dc->res_pool, pipe_ctx->clock_source); /* only one cs per stream regardless of mpo */ @@ -983,8 +986,6 @@ enum dc_status dce112_validate_with_context( if (!dce112_validate_surface_sets(set, set_count)) return DC_FAIL_SURFACE_VALIDATE; - context->res_ctx.pool = dc->res_pool; - for (i = 0; i < set_count; i++) { context->streams[i] = DC_STREAM_TO_CORE(set[i].stream); dc_stream_retain(&context->streams[i]->public); @@ -996,8 +997,8 @@ enum dc_status dce112_validate_with_context( if (result == DC_OK) result = resource_map_phy_clock_resources(dc, context); - if (!resource_validate_attach_surfaces( - set, set_count, dc->current_context, context)) { + if (!resource_validate_attach_surfaces(set, set_count, + dc->current_context, context, dc->res_pool)) { DC_ERROR("Failed to attach surface to stream!\n"); return DC_FAIL_ATTACH_SURFACES; } @@ -1022,8 +1023,6 @@ enum dc_status dce112_validate_guaranteed( { enum dc_status result = DC_ERROR_UNEXPECTED; - context->res_ctx.pool = dc->res_pool; - context->streams[0] = DC_STREAM_TO_CORE(dc_stream); dc_stream_retain(&context->streams[0]->public); context->stream_count++; diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index d49092986d54..0aa128e5ed84 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -821,8 +821,6 @@ enum dc_status dce80_validate_with_context( if (!dce80_validate_surface_sets(set, set_count)) return DC_FAIL_SURFACE_VALIDATE; - context->res_ctx.pool = dc->res_pool; - for (i = 0; i < set_count; i++) { context->streams[i] = DC_STREAM_TO_CORE(set[i].stream); dc_stream_retain(&context->streams[i]->public); @@ -834,8 +832,8 @@ enum dc_status dce80_validate_with_context( if (result == DC_OK) result = resource_map_clock_resources(dc, context); - if (!resource_validate_attach_surfaces( - set, set_count, dc->current_context, context)) { + if (!resource_validate_attach_surfaces(set, set_count, + dc->current_context, context, dc->res_pool)) { DC_ERROR("Failed to attach surface to stream!\n"); return DC_FAIL_ATTACH_SURFACES; } @@ -859,8 +857,6 @@ enum dc_status dce80_validate_guaranteed( { enum dc_status result = DC_ERROR_UNEXPECTED; - context->res_ctx.pool = dc->res_pool; - context->streams[0] = DC_STREAM_TO_CORE(dc_stream); dc_stream_retain(&context->streams[0]->public); context->stream_count++; diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 2b43e18c65f5..f3fe850ffa13 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -212,6 +212,7 @@ struct resource_funcs { struct pipe_ctx *(*acquire_idle_pipe_for_layer)( struct validate_context *context, + const struct resource_pool *pool, struct core_stream *stream); void (*build_bit_depth_reduction_params)( @@ -293,7 +294,6 @@ struct pipe_ctx { }; struct resource_context { - const struct resource_pool *pool; struct pipe_ctx pipe_ctx[MAX_PIPES]; bool is_stream_enc_acquired[MAX_PIPES * 2]; bool is_audio_acquired[MAX_PIPES]; diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index b1987cab9751..89d34bed131b 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -92,10 +92,12 @@ void resource_build_info_frame(struct pipe_ctx *pipe_ctx); void resource_unreference_clock_source( struct resource_context *res_ctx, + const struct resource_pool *pool, struct clock_source **clock_source); void resource_reference_clock_source( struct resource_context *res_ctx, + const struct resource_pool *pool, struct clock_source *clock_source); bool resource_are_streams_timing_synchronizable( @@ -107,7 +109,8 @@ struct clock_source *resource_find_used_clk_src_for_sharing( struct pipe_ctx *pipe_ctx); struct clock_source *dc_resource_find_first_free_pll( - struct resource_context *res_ctx); + struct resource_context *res_ctx, + const struct resource_pool *pool); struct pipe_ctx *resource_get_head_pipe_for_stream( struct resource_context *res_ctx, @@ -117,9 +120,12 @@ bool resource_attach_surfaces_to_context( const struct dc_surface *const *surfaces, int surface_count, const struct dc_stream *dc_stream, - struct validate_context *context); + struct validate_context *context, + const struct resource_pool *pool); -struct pipe_ctx *find_idle_secondary_pipe(struct resource_context *res_ctx); +struct pipe_ctx *find_idle_secondary_pipe( + struct resource_context *res_ctx, + const struct resource_pool *pool); bool resource_is_stream_unchanged( const struct validate_context *old_context, const struct core_stream *stream); @@ -131,7 +137,8 @@ bool resource_validate_attach_surfaces( const struct dc_validation_set set[], int set_count, const struct validate_context *old_context, - struct validate_context *context); + struct validate_context *context, + const struct resource_pool *pool); void validate_guaranteed_copy_streams( struct validate_context *context, -- cgit From b92033b67879380baee9ebd14da78c7dc36e1ea5 Mon Sep 17 00:00:00 2001 From: Ding Wang Date: Wed, 12 Apr 2017 15:29:13 -0400 Subject: drm/amd/display: Define dithering options Signed-off-by: Ding Wang Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 29 ++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 647c095e0ae9..dd8902d28ee1 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -430,6 +430,7 @@ struct dc_stream { enum signal_type output_signal; enum dc_color_space output_color_space; + enum dc_dither_option dither_option; struct rect src; /* composition area */ struct rect dst; /* stream addressable area */ @@ -444,7 +445,6 @@ struct dc_stream { struct colorspace_transform gamut_remap_matrix; struct csc_transform csc_color_matrix; - /* TODO: dithering */ /* TODO: custom INFO packets */ /* TODO: ABM info (DMCU) */ /* TODO: PSR info */ diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index 64d43dba8fd6..1a7ce061258f 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -484,6 +484,35 @@ enum dc_color_space { COLOR_SPACE_ADOBERGB, }; +enum dc_dither_option { + DITHER_OPTION_DEFAULT, + DITHER_OPTION_DISABLE, + DITHER_OPTION_FM6, + DITHER_OPTION_FM8, + DITHER_OPTION_FM10, + DITHER_OPTION_SPATIAL6_FRAME_RANDOM, + DITHER_OPTION_SPATIAL8_FRAME_RANDOM, + DITHER_OPTION_SPATIAL10_FRAME_RANDOM, + DITHER_OPTION_SPATIAL6, + DITHER_OPTION_SPATIAL8, + DITHER_OPTION_SPATIAL10, + DITHER_OPTION_TRUN6, + DITHER_OPTION_TRUN8, + DITHER_OPTION_TRUN10, + DITHER_OPTION_TRUN10_SPATIAL8, + DITHER_OPTION_TRUN10_SPATIAL6, + DITHER_OPTION_TRUN10_FM8, + DITHER_OPTION_TRUN10_FM6, + DITHER_OPTION_TRUN10_SPATIAL8_FM6, + DITHER_OPTION_SPATIAL10_FM8, + DITHER_OPTION_SPATIAL10_FM6, + DITHER_OPTION_TRUN8_SPATIAL6, + DITHER_OPTION_TRUN8_FM6, + DITHER_OPTION_SPATIAL8_FM6, + DITHER_OPTION_MAX = DITHER_OPTION_SPATIAL8_FM6, + DITHER_OPTION_INVALID +}; + enum dc_quantization_range { QUANTIZATION_RANGE_UNKNOWN, QUANTIZATION_RANGE_FULL, -- cgit From 1c29313b96fbe9606ecaab540800d20f2ae88adc Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 26 Apr 2017 10:54:45 -0400 Subject: drm/amd/display: fix crash caused by incorrect index being used for array Signed-off-by: Dmytro Laktyushkin Acked-by: Harry Wentland Reviewed-by: Anthony Koo Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/modules/freesync/freesync.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index f6223e6b3536..d3d57008271b 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -1122,7 +1122,7 @@ void mod_freesync_notify_mode_change(struct mod_freesync *mod_freesync, * current mode */ calc_freesync_range(core_freesync, *streams, state, - core_freesync->map[stream_index].caps-> + core_freesync->map[map_index].caps-> min_refresh_in_micro_hz, state->nominal_refresh_rate_in_micro_hz); } -- cgit From 7cc9e7a68abef8d1303700bac6f58ab76bc9db7b Mon Sep 17 00:00:00 2001 From: Eric Cook Date: Wed, 26 Apr 2017 11:51:38 -0400 Subject: drm/amd/display: Check for Zero Range in FreeSync Calc -check for min/max range in freesync calculation and handle it accordingly Signed-off-by: Eric Acked-by: Harry Wentland Reviewed-by: Anthony Koo Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/modules/freesync/freesync.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index d3d57008271b..009cb797bcfa 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -363,6 +363,21 @@ static void calc_freesync_range(struct core_freesync *core_freesync, unsigned int index = map_index_from_stream(core_freesync, stream); uint32_t vtotal = stream->timing.v_total; + if ((min_refresh_in_uhz == 0) || (max_refresh_in_uhz == 0)) { + state->freesync_range.min_refresh = + state->nominal_refresh_rate_in_micro_hz; + state->freesync_range.max_refresh = + state->nominal_refresh_rate_in_micro_hz; + + state->freesync_range.max_frame_duration = 0; + state->freesync_range.min_frame_duration = 0; + + state->freesync_range.vmax = vtotal; + state->freesync_range.vmin = vtotal; + + return; + } + min_frame_duration_in_ns = ((unsigned int) (div64_u64( (1000000000ULL * 1000000), max_refresh_in_uhz))); -- cgit From 529cad0f945c9e60569e902062d2f2741e4fd71a Mon Sep 17 00:00:00 2001 From: Ding Wang Date: Tue, 25 Apr 2017 10:03:27 -0400 Subject: drm/amd/display: Add function to set dither option Signed-off-by: Ding Wang Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 41 ++++++++ drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 4 +- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 110 +++++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dc.h | 3 + .../drm/amd/display/dc/dce110/dce110_resource.c | 48 +-------- .../drm/amd/display/dc/dce110/dce110_resource.h | 4 - .../drm/amd/display/dc/dce112/dce112_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 4 - drivers/gpu/drm/amd/display/dc/inc/resource.h | 2 + 9 files changed, 160 insertions(+), 58 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 37986632f025..738acf0cc7db 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -363,6 +363,44 @@ static void set_test_pattern( cust_pattern_size); } +void set_dither_option(const struct dc_stream *dc_stream, + enum dc_dither_option option) +{ + struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); + struct bit_depth_reduction_params params; + struct core_link *core_link = DC_LINK_TO_CORE(stream->status.link); + struct pipe_ctx *pipes = + core_link->dc->current_context->res_ctx.pipe_ctx; + + memset(¶ms, 0, sizeof(params)); + if (!stream) + return; + if (option > DITHER_OPTION_MAX) + return; + if (option == DITHER_OPTION_DEFAULT) { + switch (stream->public.timing.display_color_depth) { + case COLOR_DEPTH_666: + stream->public.dither_option = DITHER_OPTION_SPATIAL6; + break; + case COLOR_DEPTH_888: + stream->public.dither_option = DITHER_OPTION_SPATIAL8; + break; + case COLOR_DEPTH_101010: + stream->public.dither_option = DITHER_OPTION_SPATIAL10; + break; + default: + option = DITHER_OPTION_DISABLE; + } + } else { + stream->public.dither_option = option; + } + resource_build_bit_depth_reduction_params(stream, + ¶ms); + stream->bit_depth_params = params; + pipes->opp->funcs-> + opp_program_bit_depth_reduction(pipes->opp, ¶ms); +} + static void allocate_dc_stream_funcs(struct core_dc *core_dc) { core_dc->public.stream_funcs.stream_update_scaling = stream_update_scaling; @@ -380,6 +418,9 @@ static void allocate_dc_stream_funcs(struct core_dc *core_dc) core_dc->public.stream_funcs.set_gamut_remap = set_gamut_remap; + core_dc->public.stream_funcs.set_dither_option = + set_dither_option; + core_dc->public.link_funcs.set_drive_settings = set_drive_settings; 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 4b9d3f12406f..a0d192774a22 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 @@ -11,6 +11,7 @@ #include "dpcd_defs.h" #include "core_dc.h" +#include "resource.h" /* maximum pre emphasis level allowed for each voltage swing level*/ static const enum dc_pre_emphasis voltage_swing_to_pre_emphasis[] = { @@ -2245,8 +2246,7 @@ static void set_crtc_test_pattern(struct core_link *link, case DP_TEST_PATTERN_VIDEO_MODE: { /* restore bitdepth reduction */ - link->dc->res_pool->funcs-> - build_bit_depth_reduction_params(pipe_ctx->stream, + resource_build_bit_depth_reduction_params(pipe_ctx->stream, ¶ms); pipe_ctx->stream->bit_depth_params = params; pipe_ctx->opp->funcs-> diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 43e5758719ca..2de86f8364a3 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -2246,3 +2246,113 @@ bool pipe_need_reprogram( return false; } + +void resource_build_bit_depth_reduction_params(const struct core_stream *stream, + struct bit_depth_reduction_params *fmt_bit_depth) +{ + enum dc_dither_option option = stream->public.dither_option; + enum dc_pixel_encoding pixel_encoding = + stream->public.timing.pixel_encoding; + + memset(fmt_bit_depth, 0, sizeof(*fmt_bit_depth)); + + if (option == DITHER_OPTION_DISABLE) + return; + + if (option == DITHER_OPTION_TRUN6) { + fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; + fmt_bit_depth->flags.TRUNCATE_DEPTH = 0; + } else if (option == DITHER_OPTION_TRUN8 || + option == DITHER_OPTION_TRUN8_SPATIAL6 || + option == DITHER_OPTION_TRUN8_FM6) { + fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; + fmt_bit_depth->flags.TRUNCATE_DEPTH = 1; + } else if (option == DITHER_OPTION_TRUN10 || + option == DITHER_OPTION_TRUN10_SPATIAL6 || + option == DITHER_OPTION_TRUN10_SPATIAL8 || + option == DITHER_OPTION_TRUN10_FM8 || + option == DITHER_OPTION_TRUN10_FM6 || + option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) { + fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; + fmt_bit_depth->flags.TRUNCATE_DEPTH = 2; + } + + /* special case - Formatter can only reduce by 4 bits at most. + * When reducing from 12 to 6 bits, + * HW recommends we use trunc with round mode + * (if we did nothing, trunc to 10 bits would be used) + * note that any 12->10 bit reduction is ignored prior to DCE8, + * as the input was 10 bits. + */ + if (option == DITHER_OPTION_SPATIAL6_FRAME_RANDOM || + option == DITHER_OPTION_SPATIAL6 || + option == DITHER_OPTION_FM6) { + fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; + fmt_bit_depth->flags.TRUNCATE_DEPTH = 2; + fmt_bit_depth->flags.TRUNCATE_MODE = 1; + } + + /* spatial dither + * note that spatial modes 1-3 are never used + */ + if (option == DITHER_OPTION_SPATIAL6_FRAME_RANDOM || + option == DITHER_OPTION_SPATIAL6 || + option == DITHER_OPTION_TRUN10_SPATIAL6 || + option == DITHER_OPTION_TRUN8_SPATIAL6) { + fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; + fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 0; + fmt_bit_depth->flags.HIGHPASS_RANDOM = 1; + fmt_bit_depth->flags.RGB_RANDOM = + (pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0; + } else if (option == DITHER_OPTION_SPATIAL8_FRAME_RANDOM || + option == DITHER_OPTION_SPATIAL8 || + option == DITHER_OPTION_SPATIAL8_FM6 || + option == DITHER_OPTION_TRUN10_SPATIAL8 || + option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) { + fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; + fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 1; + fmt_bit_depth->flags.HIGHPASS_RANDOM = 1; + fmt_bit_depth->flags.RGB_RANDOM = + (pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0; + } else if (option == DITHER_OPTION_SPATIAL10_FRAME_RANDOM || + option == DITHER_OPTION_SPATIAL10 || + option == DITHER_OPTION_SPATIAL10_FM8 || + option == DITHER_OPTION_SPATIAL10_FM6) { + fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; + fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 2; + fmt_bit_depth->flags.HIGHPASS_RANDOM = 1; + fmt_bit_depth->flags.RGB_RANDOM = + (pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0; + } + + if (option == DITHER_OPTION_SPATIAL6 || + option == DITHER_OPTION_SPATIAL8 || + option == DITHER_OPTION_SPATIAL10) { + fmt_bit_depth->flags.FRAME_RANDOM = 0; + } else { + fmt_bit_depth->flags.FRAME_RANDOM = 1; + } + + ////////////////////// + //// temporal dither + ////////////////////// + if (option == DITHER_OPTION_FM6 || + option == DITHER_OPTION_SPATIAL8_FM6 || + option == DITHER_OPTION_SPATIAL10_FM6 || + option == DITHER_OPTION_TRUN10_FM6 || + option == DITHER_OPTION_TRUN8_FM6 || + option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) { + fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1; + fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 0; + } else if (option == DITHER_OPTION_FM8 || + option == DITHER_OPTION_SPATIAL10_FM8 || + option == DITHER_OPTION_TRUN10_FM8) { + fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1; + fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 1; + } else if (option == DITHER_OPTION_FM10) { + fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1; + fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 2; + } + + fmt_bit_depth->pixel_encoding = pixel_encoding; +} diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index dd8902d28ee1..87675f032949 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -122,6 +122,9 @@ struct dc_stream_funcs { const struct dc_stream **stream, int num_streams, const struct dc_static_screen_events *events); + + void (*set_dither_option)(const struct dc_stream *stream, + enum dc_dither_option option); }; struct link_training_settings; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 122f2d03afc0..5b2b41efa5f0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -775,50 +775,6 @@ static void get_pixel_clock_parameters( } } -void dce110_resource_build_bit_depth_reduction_params( - const struct core_stream *stream, - struct bit_depth_reduction_params *fmt_bit_depth) -{ - memset(fmt_bit_depth, 0, sizeof(*fmt_bit_depth)); - - /*TODO: Need to un-hardcode, refer to function with same name - * in dal2 hw_sequencer*/ - - fmt_bit_depth->flags.TRUNCATE_ENABLED = 0; - fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 0; - fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 0; - - /* Diagnostics need consistent CRC of the image, that means - * dithering should not be enabled for Diagnostics. */ - if (IS_DIAG_DC(stream->ctx->dce_environment) == false) { - switch (stream->public.timing.display_color_depth) { - case COLOR_DEPTH_666: - fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; - fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 0; - break; - case COLOR_DEPTH_888: - fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; - fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 1; - break; - case COLOR_DEPTH_101010: - fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; - fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 2; - break; - default: - break; - } - fmt_bit_depth->flags.RGB_RANDOM = 1; - fmt_bit_depth->flags.HIGHPASS_RANDOM = 1; - fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; - fmt_bit_depth->flags.TRUNCATE_DEPTH = 2; - - fmt_bit_depth->pixel_encoding = - stream->public.timing.pixel_encoding; - } - - return; -} - enum dc_status dce110_resource_build_pipe_hw_param(struct pipe_ctx *pipe_ctx) { get_pixel_clock_parameters(pipe_ctx, &pipe_ctx->pix_clk_params); @@ -826,7 +782,7 @@ enum dc_status dce110_resource_build_pipe_hw_param(struct pipe_ctx *pipe_ctx) pipe_ctx->clock_source, &pipe_ctx->pix_clk_params, &pipe_ctx->pll_settings); - dce110_resource_build_bit_depth_reduction_params(pipe_ctx->stream, + resource_build_bit_depth_reduction_params(pipe_ctx->stream, &pipe_ctx->stream->bit_depth_params); pipe_ctx->stream->clamping.pixel_encoding = pipe_ctx->stream->public.timing.pixel_encoding; @@ -1171,8 +1127,6 @@ static const struct resource_funcs dce110_res_pool_funcs = { .validate_guaranteed = dce110_validate_guaranteed, .validate_bandwidth = dce110_validate_bandwidth, .acquire_idle_pipe_for_layer = dce110_acquire_underlay, - .build_bit_depth_reduction_params = - dce110_resource_build_bit_depth_reduction_params }; static bool underlay_create(struct dc_context *ctx, struct resource_pool *pool) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.h index 0c357fdfa8bc..8e2e85dd30b9 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.h @@ -40,10 +40,6 @@ struct dce110_resource_pool { enum dc_status dce110_resource_build_pipe_hw_param(struct pipe_ctx *pipe_ctx); -void dce110_resource_build_bit_depth_reduction_params( - const struct core_stream *stream, - struct bit_depth_reduction_params *fmt_bit_depth); - struct resource_pool *dce110_create_resource_pool( uint8_t num_virtual_links, struct core_dc *dc, diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 4de51a86c9ea..18c1b89a52be 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -1062,7 +1062,7 @@ static const struct resource_funcs dce112_res_pool_funcs = { .link_enc_create = dce112_link_encoder_create, .validate_with_context = dce112_validate_with_context, .validate_guaranteed = dce112_validate_guaranteed, - .validate_bandwidth = dce112_validate_bandwidth + .validate_bandwidth = dce112_validate_bandwidth, }; static void bw_calcs_data_update_from_pplib(struct core_dc *dc) diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index f3fe850ffa13..9e5e0ba5b10b 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -214,10 +214,6 @@ struct resource_funcs { struct validate_context *context, const struct resource_pool *pool, struct core_stream *stream); - - void (*build_bit_depth_reduction_params)( - const struct core_stream *stream, - struct bit_depth_reduction_params *fmt_bit_depth); }; struct audio_support{ diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index 89d34bed131b..4e07b9fea669 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -160,5 +160,7 @@ bool pipe_need_reprogram( struct pipe_ctx *pipe_ctx_old, struct pipe_ctx *pipe_ctx); +void resource_build_bit_depth_reduction_params(const struct core_stream *stream, + struct bit_depth_reduction_params *fmt_bit_depth); #endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_RESOURCE_H_ */ -- cgit From 9e594f4c3f30c8ba43a1601268e82177fbd737c1 Mon Sep 17 00:00:00 2001 From: Eric Cook Date: Thu, 27 Apr 2017 12:20:34 -0400 Subject: drm/amd/display: Add support for FreeSync on eDP to module Signed-off-by: Eric Acked-by: Harry Wentland Reviewed-by: Anthony Koo Signed-off-by: Alex Deucher --- .../drm/amd/display/modules/freesync/freesync.c | 42 +++++++++++++++++----- 1 file changed, 33 insertions(+), 9 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index 009cb797bcfa..82086a129a3b 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -109,11 +109,16 @@ struct freesync_entity { struct mod_freesync_user_enable user_enable; }; +struct freesync_registry_options { + unsigned int min_refresh_from_edid; +}; + struct core_freesync { struct mod_freesync public; struct dc *dc; struct freesync_entity *map; int num_entities; + struct freesync_registry_options opts; }; #define MOD_FREESYNC_TO_CORE(mod_freesync)\ @@ -136,7 +141,7 @@ struct mod_freesync *mod_freesync_create(struct dc *dc) struct persistent_data_flag flag; - int i = 0; + int i, data = 0; if (core_freesync == NULL) goto fail_alloc_context; @@ -165,6 +170,12 @@ struct mod_freesync *mod_freesync_create(struct dc *dc) flag.save_per_link = false; dm_write_persistent_data(core_dc->ctx, NULL, FREESYNC_REGISTRY_NAME, NULL, NULL, 0, &flag); + flag.save_per_edid = false; + flag.save_per_link = false; + if (dm_read_persistent_data(core_dc->ctx, NULL, NULL, + "DalDrrSupport", &data, sizeof(data), &flag)) { + core_freesync->opts.min_refresh_from_edid = data; + } return &core_freesync->public; @@ -219,7 +230,7 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, struct core_stream *core_stream = NULL; struct core_dc *core_dc = NULL; struct core_freesync *core_freesync = NULL; - int persistent_freesync_enable = 0; + int persistent_freesync_enable, stream_index = 0; struct persistent_data_flag flag; unsigned int nom_refresh_rate_micro_hz; unsigned long long temp; @@ -238,6 +249,26 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, dc_stream_retain(stream); + stream_index = map_index_from_stream(core_freesync, stream); + + temp = stream->timing.pix_clk_khz; + temp *= 1000ULL * 1000ULL * 1000ULL; + temp = div_u64(temp, stream->timing.h_total); + temp = div_u64(temp, stream->timing.v_total); + + nom_refresh_rate_micro_hz = (unsigned int) temp; + + if (core_freesync->opts.min_refresh_from_edid != 0 && + dc_is_embedded_signal( + stream[stream_index].sink->sink_signal)) { + caps->supported = true; + caps->min_refresh_in_micro_hz = + core_freesync->opts.min_refresh_from_edid * + 1000000; + caps->max_refresh_in_micro_hz = + nom_refresh_rate_micro_hz; + } + core_freesync->map[core_freesync->num_entities].stream = stream; core_freesync->map[core_freesync->num_entities].caps = caps; @@ -275,13 +306,6 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, enable_for_video = false; } - temp = stream->timing.pix_clk_khz; - temp *= 1000ULL * 1000ULL * 1000ULL; - temp = div_u64(temp, stream->timing.h_total); - temp = div_u64(temp, stream->timing.v_total); - - nom_refresh_rate_micro_hz = (unsigned int) temp; - if (caps->supported && nom_refresh_rate_micro_hz >= caps->min_refresh_in_micro_hz && nom_refresh_rate_micro_hz <= caps->max_refresh_in_micro_hz) -- cgit From cf4cde2b0b678ca1cf56d7b397c78b1bc3d3155b Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Fri, 28 Apr 2017 09:56:08 -0400 Subject: drm/amd/display: Disable cursor on video surface. Signed-off-by: Yongqiang Sun Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 99b6a1695f26..4ba446de4d00 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -250,6 +250,10 @@ bool dc_stream_set_cursor_position( !pipe_ctx->ipp || !pipe_ctx->surface) continue; + if (pipe_ctx->surface->public.address.type + == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE) + pos_cpy.enable = false; + if (pipe_ctx->top_pipe && pipe_ctx->surface != pipe_ctx->top_pipe->surface) pos_cpy.enable = false; -- cgit From 9c3b2b50b3f03e876d5df1cf8940a79013091e9d Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Fri, 28 Apr 2017 07:54:34 -0400 Subject: drm/amd/display: move drr_params definition to TG Signed-off-by: Tony Cheng Acked-by: Harry Wentland Reviewed-by: Dmytro Laktyushkin Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h | 7 +++++++ drivers/gpu/drm/amd/display/include/hw_sequencer_types.h | 11 ----------- 2 files changed, 7 insertions(+), 11 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h index 2c4a9d02b3c1..00cdaaae455c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h @@ -40,6 +40,13 @@ struct dcp_gsl_params { int gsl_master; }; +/* define the structure of Dynamic Refresh Mode */ +struct drr_params { + uint32_t vertical_total_min; + uint32_t vertical_total_max; + bool immediate_flip; +}; + #define LEFT_EYE_3D_PRIMARY_SURFACE 1 #define RIGHT_EYE_3D_PRIMARY_SURFACE 0 diff --git a/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h b/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h index 065a91a7002f..8ba9f65276f5 100644 --- a/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h +++ b/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h @@ -30,15 +30,4 @@ #include "grph_object_defs.h" #include "link_service_types.h" -/* define the structure of Dynamic Refresh Mode */ -struct drr_params { - /* defines the minimum possible vertical dimension of display timing - * for CRTC as supported by the panel */ - uint32_t vertical_total_min; - /* defines the maximum possible vertical dimension of display timing - * for CRTC as supported by the panel */ - uint32_t vertical_total_max; - bool immediate_flip; -}; - #endif -- cgit From 7d091f7a4466cd7d7b778c126072b3dc46d8141f Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Fri, 28 Apr 2017 16:21:38 -0400 Subject: drm/amd/display: Get dprefclk ss percentage from vbios Signed-off-by: Hersen Wu Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c | 40 +++++-------------- drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c | 46 ++++++++++++++++------ drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h | 13 +++--- 3 files changed, 51 insertions(+), 48 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c index 123942f4cbde..682fc9b9b3f2 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -1070,7 +1070,6 @@ static enum bp_result get_ss_info_v4_1( { enum bp_result result = BP_RESULT_OK; struct atom_display_controller_info_v4_1 *disp_cntl_tbl = NULL; - struct atom_smu_info_v3_1 *smu_tbl = NULL; if (!ss_info) return BP_RESULT_BADINPUT; @@ -1078,19 +1077,11 @@ static enum bp_result get_ss_info_v4_1( if (!DATA_TABLES(dce_info)) return BP_RESULT_BADBIOSTABLE; - if (!DATA_TABLES(smu_info)) - return BP_RESULT_BADBIOSTABLE; - disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_1, DATA_TABLES(dce_info)); if (!disp_cntl_tbl) return BP_RESULT_BADBIOSTABLE; - smu_tbl = GET_IMAGE(struct atom_smu_info_v3_1, DATA_TABLES(smu_info)); - if (!smu_tbl) - return BP_RESULT_BADBIOSTABLE; - - ss_info->type.STEP_AND_DELAY_INFO = false; ss_info->spread_percentage_divider = 1000; /* BIOS no longer uses target clock. Always enable for now */ @@ -1123,12 +1114,11 @@ static enum bp_result get_ss_info_v4_1( ss_info->type.CENTER_MODE = true; break; case AS_SIGNAL_TYPE_GPU_PLL: - ss_info->spread_spectrum_percentage = - smu_tbl->gpuclk_ss_percentage; - ss_info->spread_spectrum_range = - smu_tbl->gpuclk_ss_rate_10hz * 10; - if (smu_tbl->gpuclk_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE) - ss_info->type.CENTER_MODE = true; + /* atom_firmware: DAL only get data from dce_info table. + * if data within smu_info is needed for DAL, VBIOS should + * copy it into dce_info + */ + result = BP_RESULT_UNSUPPORTED; break; default: result = BP_RESULT_UNSUPPORTED; @@ -1145,7 +1135,6 @@ static enum bp_result get_ss_info_v4_2( { enum bp_result result = BP_RESULT_OK; struct atom_display_controller_info_v4_2 *disp_cntl_tbl = NULL; - struct atom_smu_info_v3_1 *smu_tbl = NULL; if (!ss_info) return BP_RESULT_BADINPUT; @@ -1153,19 +1142,11 @@ static enum bp_result get_ss_info_v4_2( if (!DATA_TABLES(dce_info)) return BP_RESULT_BADBIOSTABLE; - if (!DATA_TABLES(smu_info)) - return BP_RESULT_BADBIOSTABLE; - disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_2, DATA_TABLES(dce_info)); if (!disp_cntl_tbl) return BP_RESULT_BADBIOSTABLE; - smu_tbl = GET_IMAGE(struct atom_smu_info_v3_1, DATA_TABLES(smu_info)); - if (!smu_tbl) - return BP_RESULT_BADBIOSTABLE; - - ss_info->type.STEP_AND_DELAY_INFO = false; ss_info->spread_percentage_divider = 1000; /* BIOS no longer uses target clock. Always enable for now */ @@ -1198,12 +1179,11 @@ static enum bp_result get_ss_info_v4_2( ss_info->type.CENTER_MODE = true; break; case AS_SIGNAL_TYPE_GPU_PLL: - ss_info->spread_spectrum_percentage = - smu_tbl->gpuclk_ss_percentage; - ss_info->spread_spectrum_range = - smu_tbl->gpuclk_ss_rate_10hz * 10; - if (smu_tbl->gpuclk_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE) - ss_info->type.CENTER_MODE = true; + /* atom_firmware: DAL only get data from dce_info table. + * if data within smu_info is needed for DAL, VBIOS should + * copy it into dce_info + */ + result = BP_RESULT_UNSUPPORTED; break; default: result = BP_RESULT_UNSUPPORTED; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c index b4fd02219c2c..81cb138cdc38 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c @@ -218,11 +218,11 @@ static int dce_clocks_get_dp_ref_freq(struct display_clock *clk) (should not be case with CIK) then SW should program all rates generated according to average value (case as with previous ASICs) */ - if (clk_dce->ss_on_gpu_pll && clk_dce->gpu_pll_ss_divider != 0) { + if (clk_dce->ss_on_dprefclk && clk_dce->dprefclk_ss_divider != 0) { struct fixed32_32 ss_percentage = dal_fixed32_32_div_int( dal_fixed32_32_from_fraction( - clk_dce->gpu_pll_ss_percentage, - clk_dce->gpu_pll_ss_divider), 200); + clk_dce->dprefclk_ss_percentage, + clk_dce->dprefclk_ss_divider), 200); struct fixed32_32 adj_dp_ref_clk_khz; ss_percentage = dal_fixed32_32_sub(dal_fixed32_32_one, @@ -480,22 +480,44 @@ static void dce_clock_read_ss_info(struct dce_disp_clk *clk_dce) */ if (result == BP_RESULT_OK && info.spread_spectrum_percentage != 0) { - clk_dce->ss_on_gpu_pll = true; - clk_dce->gpu_pll_ss_divider = info.spread_percentage_divider; + clk_dce->ss_on_dprefclk = true; + clk_dce->dprefclk_ss_divider = info.spread_percentage_divider; if (info.type.CENTER_MODE == 0) { - /* Currently for DP Reference clock we + /* TODO: Currently for DP Reference clock we * need only SS percentage for * downspread */ - clk_dce->gpu_pll_ss_percentage = + clk_dce->dprefclk_ss_percentage = info.spread_spectrum_percentage; } + + return; } + result = bp->funcs->get_spread_spectrum_info( + bp, AS_SIGNAL_TYPE_DISPLAY_PORT, 0, &info); + + /* Based on VBIOS, VBIOS will keep entry for DPREFCLK SS + * even if SS not enabled and in that case + * SSInfo.spreadSpectrumPercentage !=0 would be sign + * that SS is enabled + */ + if (result == BP_RESULT_OK && + info.spread_spectrum_percentage != 0) { + clk_dce->ss_on_dprefclk = true; + clk_dce->dprefclk_ss_divider = info.spread_percentage_divider; + + if (info.type.CENTER_MODE == 0) { + /* Currently for DP Reference clock we + * need only SS percentage for + * downspread */ + clk_dce->dprefclk_ss_percentage = + info.spread_spectrum_percentage; + } + } } } - static bool dce_apply_clock_voltage_request( struct display_clock *clk, enum dm_pp_clock_type clocks_type, @@ -629,9 +651,11 @@ static void dce_disp_clk_construct( clk_dce->clk_mask = clk_mask; clk_dce->dfs_bypass_disp_clk = 0; - clk_dce->gpu_pll_ss_percentage = 0; - clk_dce->gpu_pll_ss_divider = 1000; - clk_dce->ss_on_gpu_pll = false; + + clk_dce->dprefclk_ss_percentage = 0; + clk_dce->dprefclk_ss_divider = 1000; + clk_dce->ss_on_dprefclk = false; + base->max_clks_state = DM_PP_CLOCKS_STATE_NOMINAL; base->cur_min_clks_state = DM_PP_CLOCKS_STATE_INVALID; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h index 2fd00e45395c..29ff470086e5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h @@ -116,13 +116,12 @@ struct dce_disp_clk { * This is basically "Crystal Frequency In KHz" (XTALIN) frequency */ int dfs_bypass_disp_clk; - /* Flag for Enabled SS on GPU PLL */ - bool ss_on_gpu_pll; - /* GPU PLL SS percentage (if down-spread enabled) */ - int gpu_pll_ss_percentage; - /* GPU PLL SS percentage Divider (100 or 1000) */ - int gpu_pll_ss_divider; - + /* Flag for Enabled SS on DPREFCLK */ + bool ss_on_dprefclk; + /* DPREFCLK SS percentage (if down-spread enabled) */ + int dprefclk_ss_percentage; + /* DPREFCLK SS percentage Divider (100 or 1000) */ + int dprefclk_ss_divider; /* max disp_clk from PPLIB for max validation display clock*/ int max_displ_clk_in_khz; -- cgit From ba624cddbc002816e376d588290a48f77ff4b06f Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Wed, 3 May 2017 13:58:45 -0400 Subject: drm/amd/display: Assign stream to map before we need it Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/modules/freesync/freesync.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index 82086a129a3b..c5330f3cc1de 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -230,7 +230,7 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, struct core_stream *core_stream = NULL; struct core_dc *core_dc = NULL; struct core_freesync *core_freesync = NULL; - int persistent_freesync_enable, stream_index = 0; + int persistent_freesync_enable = 0; struct persistent_data_flag flag; unsigned int nom_refresh_rate_micro_hz; unsigned long long temp; @@ -249,8 +249,6 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, dc_stream_retain(stream); - stream_index = map_index_from_stream(core_freesync, stream); - temp = stream->timing.pix_clk_khz; temp *= 1000ULL * 1000ULL * 1000ULL; temp = div_u64(temp, stream->timing.h_total); @@ -260,7 +258,7 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, if (core_freesync->opts.min_refresh_from_edid != 0 && dc_is_embedded_signal( - stream[stream_index].sink->sink_signal)) { + stream->sink->sink_signal)) { caps->supported = true; caps->min_refresh_in_micro_hz = core_freesync->opts.min_refresh_from_edid * -- cgit From 03ea364c8e156b2bb5c64465718e8ebd75e3df22 Mon Sep 17 00:00:00 2001 From: Arindam Nath Date: Wed, 26 Apr 2017 17:39:56 +0530 Subject: drm/amd/display: fix resume hang because of DP short pulse There is a hard hang observed during resume from S3 when the system receives a DP short pulse interrupt. This is because there are two code paths contending for GPIO access for AUX channel transactions. One such path is through amdgpu_dm_display_resume() function which is invoked from the regular system resume code path. The other path is through handle_hpd_rx_irq(), which is invoked in response to system receiving DP short pulse interrupt. handle_hpd_rx_irq() guards against conflicting GPIO access using hpd_lock, but the GPIO access from amdgpu_dm_display_resume() remains unguarded. This patch makes sure we use hpd_lock inside amdgpu_dm_display_resume() to avoid race conditions for GPIO access. Signed-off-by: Arindam Nath Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu') 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 84995a48ec61..74e32246ff30 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -580,9 +580,11 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev ) if (aconnector->mst_port) continue; + mutex_lock(&aconnector->hpd_lock); dc_link_detect(aconnector->dc_link, false); aconnector->dc_sink = NULL; amdgpu_dm_update_connector_after_detect(aconnector); + mutex_unlock(&aconnector->hpd_lock); } /* Force mode set in atomic comit */ -- cgit From 74c49c7ac14f3a7cc500be959709f3473a6a49e7 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 8 May 2017 15:17:39 -0400 Subject: drm/amdgpu/display: Add calcs code for DCN Bandwidth and scaling calculations for DCN. Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c | 3629 ++++++++++++++++++++ .../gpu/drm/amd/display/dc/calcs/dcn_calc_auto.h | 37 + .../gpu/drm/amd/display/dc/calcs/dcn_calc_math.c | 104 + .../gpu/drm/amd/display/dc/calcs/dcn_calc_math.h | 40 + drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 1366 ++++++++ drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h | 629 ++++ 6 files changed, 5805 insertions(+) create mode 100644 drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c create mode 100644 drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.h create mode 100644 drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.c create mode 100644 drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.h create mode 100644 drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c create mode 100644 drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c new file mode 100644 index 000000000000..21b83e403ef2 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c @@ -0,0 +1,3629 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "dcn_calc_auto.h" +#include "dcn_calc_math.h" + +/*REVISION#247*/ +void scaler_settings_calculation(struct dcn_bw_internal_vars *v) +{ + int k; + /*scaler settings calculation*/ + + /*scale ratio calculation*/ + + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->allow_different_hratio_vratio == dcn_bw_yes) { + if (v->source_scan[k] == dcn_bw_hor) { + v->h_ratio[k] = v->viewport_width[k] / v->scaler_rec_out_width[k]; + v->v_ratio[k] = v->viewport_height[k] / v->scaler_recout_height[k]; + } else { + v->h_ratio[k] = v->viewport_height[k] / v->scaler_rec_out_width[k]; + v->v_ratio[k] = v->viewport_width[k] / v->scaler_recout_height[k]; + } + } else { + if (v->source_scan[k] == dcn_bw_hor) { + v->h_ratio[k] = dcn_bw_max2( + v->viewport_width[k] / v->scaler_rec_out_width[k], + v->viewport_height[k] / v->scaler_recout_height[k]); + } else { + v->h_ratio[k] = dcn_bw_max2( + v->viewport_height[k] / v->scaler_rec_out_width[k], + v->viewport_width[k] / v->scaler_recout_height[k]); + } + v->v_ratio[k] = v->h_ratio[k]; + } + if (v->interlace_output[k] == 1.0) { + v->v_ratio[k] = 2.0 * v->v_ratio[k]; + } + if ((v->underscan_output[k] == 1.0)) { + v->h_ratio[k] = v->h_ratio[k] * v->under_scan_factor; + v->v_ratio[k] = v->v_ratio[k] * v->under_scan_factor; + } + } + /*scaler taps calculation*/ + + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->h_ratio[k] > 1.0) { + v->acceptable_quality_hta_ps = dcn_bw_min2( + v->max_hscl_taps, + 2.0 * dcn_bw_ceil2(v->h_ratio[k], 1.0)); + } else if (v->h_ratio[k] < 1.0) { + v->acceptable_quality_hta_ps = 4.0; + } else { + v->acceptable_quality_hta_ps = 1.0; + } + if (v->ta_pscalculation == dcn_bw_override) { + v->htaps[k] = v->override_hta_ps[k]; + } else { + v->htaps[k] = v->acceptable_quality_hta_ps; + } + if (v->v_ratio[k] > 1.0) { + v->acceptable_quality_vta_ps = dcn_bw_min2( + v->max_vscl_taps, + 2.0 * dcn_bw_ceil2(v->v_ratio[k], 1.0)); + } else if (v->v_ratio[k] < 1.0) { + v->acceptable_quality_vta_ps = 4.0; + } else { + v->acceptable_quality_vta_ps = 1.0; + } + if (v->ta_pscalculation == dcn_bw_override) { + v->vtaps[k] = v->override_vta_ps[k]; + } else { + v->vtaps[k] = v->acceptable_quality_vta_ps; + } + if (v->source_pixel_format[k] == dcn_bw_rgb_sub_64 + || v->source_pixel_format[k] == dcn_bw_rgb_sub_32 + || v->source_pixel_format[k] == dcn_bw_rgb_sub_16) { + v->vta_pschroma[k] = 0.0; + v->hta_pschroma[k] = 0.0; + } else { + if (v->ta_pscalculation == dcn_bw_override) { + v->vta_pschroma[k] = v->override_vta_pschroma[k]; + v->hta_pschroma[k] = v->override_hta_pschroma[k]; + } else { + v->vta_pschroma[k] = v->acceptable_quality_vta_ps; + v->hta_pschroma[k] = v->acceptable_quality_hta_ps; + } + } + } +} +void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v) +{ + int i, j, k; + /*mode support, voltage state and soc configuration*/ + + /*scale ratio support check*/ + + v->scale_ratio_support = dcn_bw_yes; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->h_ratio[k] > v->max_hscl_ratio || v->v_ratio[k] > v->max_vscl_ratio + || v->h_ratio[k] > v->htaps[k] || v->v_ratio[k] > v->vtaps[k] + || (v->source_pixel_format[k] != dcn_bw_rgb_sub_64 + && v->source_pixel_format[k] != dcn_bw_rgb_sub_32 + && v->source_pixel_format[k] != dcn_bw_rgb_sub_16 + && (v->h_ratio[k] / 2.0 > v->hta_pschroma[k] + || v->v_ratio[k] / 2.0 + > v->vta_pschroma[k]))) { + v->scale_ratio_support = dcn_bw_no; + } + } + /*source format, pixel format and scan support check*/ + + v->source_format_pixel_and_scan_support = dcn_bw_yes; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if ((v->source_surface_mode[k] == dcn_bw_sw_linear + && v->source_scan[k] != dcn_bw_hor) + || ((v->source_surface_mode[k] == dcn_bw_sw_4_kb_d + || v->source_surface_mode[k] == dcn_bw_sw_4_kb_d_x + || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d + || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_t + || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_x + || v->source_surface_mode[k] == dcn_bw_sw_var_d + || v->source_surface_mode[k] == dcn_bw_sw_var_d_x) + && v->source_pixel_format[k] != dcn_bw_rgb_sub_64)) { + v->source_format_pixel_and_scan_support = dcn_bw_no; + } + } + /*bandwidth support check*/ + + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->source_scan[k] == dcn_bw_hor) { + v->swath_width_ysingle_dpp[k] = v->viewport_width[k]; + } else { + v->swath_width_ysingle_dpp[k] = v->viewport_height[k]; + } + if (v->source_pixel_format[k] == dcn_bw_rgb_sub_64) { + v->byte_per_pixel_in_dety[k] = 8.0; + v->byte_per_pixel_in_detc[k] = 0.0; + } else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_32) { + v->byte_per_pixel_in_dety[k] = 4.0; + v->byte_per_pixel_in_detc[k] = 0.0; + } else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_16) { + v->byte_per_pixel_in_dety[k] = 2.0; + v->byte_per_pixel_in_detc[k] = 0.0; + } else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_8) { + v->byte_per_pixel_in_dety[k] = 1.0; + v->byte_per_pixel_in_detc[k] = 2.0; + } else { + v->byte_per_pixel_in_dety[k] = 4.0f / 3; + v->byte_per_pixel_in_detc[k] = 8.0f / 3; + } + } + v->total_read_bandwidth_consumed_gbyte_per_second = 0.0; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + v->read_bandwidth[k] = v->swath_width_ysingle_dpp[k] + * (dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) * v->v_ratio[k] + + dcn_bw_ceil2(v->byte_per_pixel_in_detc[k], 2.0) / 2.0 + * v->v_ratio[k] / 2) + / (v->htotal[k] / v->pixel_clock[k]); + if (v->dcc_enable[k] == dcn_bw_yes) { + v->read_bandwidth[k] = v->read_bandwidth[k] * (1 + 1 / 256); + } + if (v->pte_enable == dcn_bw_yes && v->source_scan[k] != dcn_bw_hor + && (v->source_surface_mode[k] == dcn_bw_sw_4_kb_s + || v->source_surface_mode[k] == dcn_bw_sw_4_kb_s_x + || v->source_surface_mode[k] == dcn_bw_sw_4_kb_d + || v->source_surface_mode[k] == dcn_bw_sw_4_kb_d_x)) { + v->read_bandwidth[k] = v->read_bandwidth[k] * (1 + 1 / 64); + } else if (v->pte_enable == dcn_bw_yes && v->source_scan[k] == dcn_bw_hor + && (v->source_pixel_format[k] == dcn_bw_rgb_sub_64 + || v->source_pixel_format[k] == dcn_bw_rgb_sub_32) + && (v->source_surface_mode[k] == dcn_bw_sw_64_kb_s + || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_t + || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_x + || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d + || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_t + || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_x)) { + v->read_bandwidth[k] = v->read_bandwidth[k] * (1 + 1 / 256); + } else if (v->pte_enable == dcn_bw_yes) { + v->read_bandwidth[k] = v->read_bandwidth[k] * (1 + 1 / 512); + } + v->total_read_bandwidth_consumed_gbyte_per_second = + v->total_read_bandwidth_consumed_gbyte_per_second + + v->read_bandwidth[k] / 1000.0; + } + v->total_write_bandwidth_consumed_gbyte_per_second = 0.0; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->output[k] == dcn_bw_writeback && v->output_format[k] == dcn_bw_444) { + v->write_bandwidth[k] = v->scaler_rec_out_width[k] + / (v->htotal[k] / v->pixel_clock[k]) * 4.0; + } else if (v->output[k] == dcn_bw_writeback) { + v->write_bandwidth[k] = v->scaler_rec_out_width[k] + / (v->htotal[k] / v->pixel_clock[k]) * 1.5; + } else { + v->write_bandwidth[k] = 0.0; + } + v->total_write_bandwidth_consumed_gbyte_per_second = + v->total_write_bandwidth_consumed_gbyte_per_second + + v->write_bandwidth[k] / 1000.0; + } + v->total_bandwidth_consumed_gbyte_per_second = + v->total_read_bandwidth_consumed_gbyte_per_second + + v->total_write_bandwidth_consumed_gbyte_per_second; + v->dcc_enabled_in_any_plane = dcn_bw_no; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->dcc_enable[k] == dcn_bw_yes) { + v->dcc_enabled_in_any_plane = dcn_bw_yes; + } + } + for (i = 0; i <= number_of_states_plus_one; i++) { + v->return_bw_todcn_per_state = + dcn_bw_min2( + v->return_bus_width * v->dcfclk_per_state[i], + v->fabric_and_dram_bandwidth_per_state[i] * 1000.0 + * v->percent_of_ideal_drambw_received_after_urg_latency + / 100.0); + v->return_bw_per_state[i] = v->return_bw_todcn_per_state; + if (v->dcc_enabled_in_any_plane == dcn_bw_yes + && v->return_bw_todcn_per_state + > v->dcfclk_per_state[i] * v->return_bus_width + / 4.0) { + v->return_bw_per_state[i] = + dcn_bw_min2( + v->return_bw_per_state[i], + v->return_bw_todcn_per_state * 4.0 + * (1.0 + - v->urgent_latency + / ((v->rob_buffer_size_in_kbyte + - v->pixel_chunk_size_in_kbyte) + * 1024.0 + / (v->return_bw_todcn_per_state + - v->dcfclk_per_state[i] + * v->return_bus_width + / 4.0) + + v->urgent_latency))); + } + v->critical_point = 2.0 * v->return_bus_width * v->dcfclk_per_state[i] + * v->urgent_latency + / (v->return_bw_todcn_per_state * v->urgent_latency + + (v->rob_buffer_size_in_kbyte + - v->pixel_chunk_size_in_kbyte) + * 1024.0); + if (v->dcc_enabled_in_any_plane == dcn_bw_yes && v->critical_point > 1.0 + && v->critical_point < 4.0) { + v->return_bw_per_state[i] = + dcn_bw_min2( + v->return_bw_per_state[i], + dcn_bw_pow( + 4.0 + * v->return_bw_todcn_per_state + * (v->rob_buffer_size_in_kbyte + - v->pixel_chunk_size_in_kbyte) + * 1024.0 + * v->return_bus_width + * v->dcfclk_per_state[i] + * v->urgent_latency + / (v->return_bw_todcn_per_state + * v->urgent_latency + + (v->rob_buffer_size_in_kbyte + - v->pixel_chunk_size_in_kbyte) + * 1024.0), + 2)); + } + v->return_bw_todcn_per_state = dcn_bw_min2( + v->return_bus_width * v->dcfclk_per_state[i], + v->fabric_and_dram_bandwidth_per_state[i] * 1000.0); + if (v->dcc_enabled_in_any_plane == dcn_bw_yes + && v->return_bw_todcn_per_state + > v->dcfclk_per_state[i] * v->return_bus_width + / 4.0) { + v->return_bw_per_state[i] = + dcn_bw_min2( + v->return_bw_per_state[i], + v->return_bw_todcn_per_state * 4.0 + * (1.0 + - v->urgent_latency + / ((v->rob_buffer_size_in_kbyte + - v->pixel_chunk_size_in_kbyte) + * 1024.0 + / (v->return_bw_todcn_per_state + - v->dcfclk_per_state[i] + * v->return_bus_width + / 4.0) + + v->urgent_latency))); + } + v->critical_point = 2.0 * v->return_bus_width * v->dcfclk_per_state[i] + * v->urgent_latency + / (v->return_bw_todcn_per_state * v->urgent_latency + + (v->rob_buffer_size_in_kbyte + - v->pixel_chunk_size_in_kbyte) + * 1024.0); + if (v->dcc_enabled_in_any_plane == dcn_bw_yes && v->critical_point > 1.0 + && v->critical_point < 4.0) { + v->return_bw_per_state[i] = + dcn_bw_min2( + v->return_bw_per_state[i], + dcn_bw_pow( + 4.0 + * v->return_bw_todcn_per_state + * (v->rob_buffer_size_in_kbyte + - v->pixel_chunk_size_in_kbyte) + * 1024.0 + * v->return_bus_width + * v->dcfclk_per_state[i] + * v->urgent_latency + / (v->return_bw_todcn_per_state + * v->urgent_latency + + (v->rob_buffer_size_in_kbyte + - v->pixel_chunk_size_in_kbyte) + * 1024.0), + 2)); + } + } + for (i = 0; i <= number_of_states_plus_one; i++) { + if ((v->total_read_bandwidth_consumed_gbyte_per_second * 1000.0 + <= v->return_bw_per_state[i]) + && (v->total_bandwidth_consumed_gbyte_per_second * 1000.0 + <= v->fabric_and_dram_bandwidth_per_state[i] + * 1000.0 + * v->percent_of_ideal_drambw_received_after_urg_latency + / 100.0)) { + v->bandwidth_support[i] = dcn_bw_yes; + } else { + v->bandwidth_support[i] = dcn_bw_no; + } + } + /*writeback latency support check*/ + + v->writeback_latency_support = dcn_bw_yes; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->output[k] == dcn_bw_writeback && v->output_format[k] == dcn_bw_444 + && v->scaler_rec_out_width[k] / (v->htotal[k] / v->pixel_clock[k]) + * 4.0 + > (v->writeback_luma_buffer_size + + v->writeback_chroma_buffer_size) + * 1024.0 / v->write_back_latency) { + v->writeback_latency_support = dcn_bw_no; + } else if (v->output[k] == dcn_bw_writeback + && v->scaler_rec_out_width[k] / (v->htotal[k] / v->pixel_clock[k]) + > dcn_bw_min2( + v->writeback_luma_buffer_size, + 2.0 + * v->writeback_chroma_buffer_size) + * 1024.0 / v->write_back_latency) { + v->writeback_latency_support = dcn_bw_no; + } + } + /*re-ordering buffer support check*/ + + for (i = 0; i <= number_of_states_plus_one; i++) { + v->urgent_round_trip_and_out_of_order_latency_per_state[i] = + (v->round_trip_ping_latency_cycles + 32.0) / v->dcfclk_per_state[i] + + v->urgent_out_of_order_return_per_channel + * v->number_of_channels + / v->return_bw_per_state[i]; + if ((v->rob_buffer_size_in_kbyte - v->pixel_chunk_size_in_kbyte) * 1024.0 + / v->return_bw_per_state[i] + > v->urgent_round_trip_and_out_of_order_latency_per_state[i]) { + v->rob_support[i] = dcn_bw_yes; + } else { + v->rob_support[i] = dcn_bw_no; + } + } + /*display io support check*/ + + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->output[k] == dcn_bw_dp && v->dsc_capability == dcn_bw_yes) { + if (v->output_format[k] == dcn_bw_420) { + v->required_output_bw = v->pixel_clock[k] / 2.0; + } else { + v->required_output_bw = v->pixel_clock[k]; + } + } else if (v->output_format[k] == dcn_bw_420) { + v->required_output_bw = v->pixel_clock[k] * 3.0 / 2.0; + } else { + v->required_output_bw = v->pixel_clock[k] * 3.0; + } + if (v->output[k] == dcn_bw_hdmi) { + v->required_phyclk[k] = v->required_output_bw / 3.0; + } else if (v->output[k] == dcn_bw_dp) { + v->required_phyclk[k] = v->required_output_bw / 4.0; + } else { + v->required_phyclk[k] = 0.0; + } + } + for (i = 0; i <= number_of_states_plus_one; i++) { + v->dio_support[i] = dcn_bw_yes; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->required_phyclk[k] > v->phyclk_per_state[i] + || (v->output[k] == dcn_bw_hdmi + && v->required_phyclk[k] > 600.0)) { + v->dio_support[i] = dcn_bw_no; + } + } + } + /*total available writeback support check*/ + + v->total_number_of_active_writeback = 0.0; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->output[k] == dcn_bw_writeback) { + v->total_number_of_active_writeback = v->total_number_of_active_writeback + + 1.0; + } + } + if (v->total_number_of_active_writeback <= v->max_num_writeback) { + v->total_available_writeback_support = dcn_bw_yes; + } else { + v->total_available_writeback_support = dcn_bw_no; + } + /*maximum dispclk/dppclk support check*/ + + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->h_ratio[k] > 1.0) { + v->pscl_factor[k] = dcn_bw_min2( + v->max_dchub_topscl_throughput, + v->max_pscl_tolb_throughput * v->h_ratio[k] + / dcn_bw_ceil2(v->htaps[k] / 6.0, 1.0)); + } else { + v->pscl_factor[k] = dcn_bw_min2( + v->max_dchub_topscl_throughput, + v->max_pscl_tolb_throughput); + } + if (v->byte_per_pixel_in_detc[k] == 0.0) { + v->pscl_factor_chroma[k] = 0.0; + v->min_dppclk_using_single_dpp[k] = + v->pixel_clock[k] + * dcn_bw_max3( + v->vtaps[k] / 6.0 + * dcn_bw_min2( + 1.0, + v->h_ratio[k]), + v->h_ratio[k] + * v->v_ratio[k] + / v->pscl_factor[k], + 1.0); + } else { + if (v->h_ratio[k] / 2.0 > 1.0) { + v->pscl_factor_chroma[k] = + dcn_bw_min2( + v->max_dchub_topscl_throughput, + v->max_pscl_tolb_throughput + * v->h_ratio[k] + / 2.0 + / dcn_bw_ceil2( + v->hta_pschroma[k] + / 6.0, + 1.0)); + } else { + v->pscl_factor_chroma[k] = dcn_bw_min2( + v->max_dchub_topscl_throughput, + v->max_pscl_tolb_throughput); + } + v->min_dppclk_using_single_dpp[k] = + v->pixel_clock[k] + * dcn_bw_max5( + v->vtaps[k] / 6.0 + * dcn_bw_min2( + 1.0, + v->h_ratio[k]), + v->h_ratio[k] + * v->v_ratio[k] + / v->pscl_factor[k], + v->vta_pschroma[k] / 6.0 + * dcn_bw_min2( + 1.0, + v->h_ratio[k] + / 2.0), + v->h_ratio[k] + * v->v_ratio[k] + / 4.0 + / v->pscl_factor_chroma[k], + 1.0); + } + } + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if ((v->source_pixel_format[k] == dcn_bw_rgb_sub_64 + || v->source_pixel_format[k] == dcn_bw_rgb_sub_32 + || v->source_pixel_format[k] == dcn_bw_rgb_sub_16)) { + if (v->source_surface_mode[k] == dcn_bw_sw_linear) { + v->read256_block_height_y[k] = 1.0; + } else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_64) { + v->read256_block_height_y[k] = 4.0; + } else { + v->read256_block_height_y[k] = 8.0; + } + v->read256_block_width_y[k] = 256.0 + / dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) + / v->read256_block_height_y[k]; + v->read256_block_height_c[k] = 0.0; + v->read256_block_width_c[k] = 0.0; + } else { + if (v->source_surface_mode[k] == dcn_bw_sw_linear) { + v->read256_block_height_y[k] = 1.0; + v->read256_block_height_c[k] = 1.0; + } else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_8) { + v->read256_block_height_y[k] = 16.0; + v->read256_block_height_c[k] = 8.0; + } else { + v->read256_block_height_y[k] = 8.0; + v->read256_block_height_c[k] = 8.0; + } + v->read256_block_width_y[k] = 256.0 + / dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) + / v->read256_block_height_y[k]; + v->read256_block_width_c[k] = 256.0 + / dcn_bw_ceil2(v->byte_per_pixel_in_detc[k], 2.0) + / v->read256_block_height_c[k]; + } + if (v->source_scan[k] == dcn_bw_hor) { + v->max_swath_height_y[k] = v->read256_block_height_y[k]; + v->max_swath_height_c[k] = v->read256_block_height_c[k]; + } else { + v->max_swath_height_y[k] = v->read256_block_width_y[k]; + v->max_swath_height_c[k] = v->read256_block_width_c[k]; + } + if ((v->source_pixel_format[k] == dcn_bw_rgb_sub_64 + || v->source_pixel_format[k] == dcn_bw_rgb_sub_32 + || v->source_pixel_format[k] == dcn_bw_rgb_sub_16)) { + if (v->source_surface_mode[k] == dcn_bw_sw_linear + || (v->source_pixel_format[k] == dcn_bw_rgb_sub_64 + && (v->source_surface_mode[k] + == dcn_bw_sw_4_kb_s + || v->source_surface_mode[k] + == dcn_bw_sw_4_kb_s_x + || v->source_surface_mode[k] + == dcn_bw_sw_64_kb_s + || v->source_surface_mode[k] + == dcn_bw_sw_64_kb_s_t + || v->source_surface_mode[k] + == dcn_bw_sw_64_kb_s_x + || v->source_surface_mode[k] + == dcn_bw_sw_var_s + || v->source_surface_mode[k] + == dcn_bw_sw_var_s_x) + && v->source_scan[k] == dcn_bw_hor)) { + v->min_swath_height_y[k] = v->max_swath_height_y[k]; + } else { + v->min_swath_height_y[k] = v->max_swath_height_y[k] / 2.0; + } + v->min_swath_height_c[k] = v->max_swath_height_c[k]; + } else { + if (v->source_surface_mode[k] == dcn_bw_sw_linear) { + v->min_swath_height_y[k] = v->max_swath_height_y[k]; + v->min_swath_height_c[k] = v->max_swath_height_c[k]; + } else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_8 + && v->source_scan[k] == dcn_bw_hor) { + v->min_swath_height_y[k] = v->max_swath_height_y[k] / 2.0; + if (v->bug_forcing_luma_and_chroma_request_to_same_size_fixed + == dcn_bw_yes) { + v->min_swath_height_c[k] = v->max_swath_height_c[k]; + } else { + v->min_swath_height_c[k] = v->max_swath_height_c[k] / 2.0; + } + } else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_10 + && v->source_scan[k] == dcn_bw_hor) { + v->min_swath_height_c[k] = v->max_swath_height_c[k] / 2.0; + if (v->bug_forcing_luma_and_chroma_request_to_same_size_fixed + == dcn_bw_yes) { + v->min_swath_height_y[k] = v->max_swath_height_y[k]; + } else { + v->min_swath_height_y[k] = v->max_swath_height_y[k] / 2.0; + } + } else { + v->min_swath_height_y[k] = v->max_swath_height_y[k]; + v->min_swath_height_c[k] = v->max_swath_height_c[k]; + } + } + if (v->source_surface_mode[k] == dcn_bw_sw_linear) { + v->maximum_swath_width = 8192.0; + } else { + v->maximum_swath_width = 5120.0; + } + v->number_of_dpp_required_for_det_size = + dcn_bw_ceil2( + v->swath_width_ysingle_dpp[k] + / dcn_bw_min2( + v->maximum_swath_width, + v->det_buffer_size_in_kbyte + * 1024.0 + / 2.0 + / (v->byte_per_pixel_in_dety[k] + * v->min_swath_height_y[k] + + v->byte_per_pixel_in_detc[k] + / 2.0 + * v->min_swath_height_c[k])), + 1.0); + if (v->byte_per_pixel_in_detc[k] == 0.0) { + v->number_of_dpp_required_for_lb_size = dcn_bw_ceil2( + (v->vtaps[k] + + dcn_bw_max2( + dcn_bw_ceil2(v->v_ratio[k], 1.0) + - 2, + 0.0)) + * v->swath_width_ysingle_dpp[k] + / dcn_bw_max2(v->h_ratio[k], 1.0) + * v->lb_bit_per_pixel[k] + / v->line_buffer_size, + 1.0); + } else { + v->number_of_dpp_required_for_lb_size = + dcn_bw_max2( + dcn_bw_ceil2( + (v->vtaps[k] + + dcn_bw_max2( + dcn_bw_ceil2( + v->v_ratio[k], + 1.0) + - 2, + 0.0)) + * v->swath_width_ysingle_dpp[k] + / dcn_bw_max2( + v->h_ratio[k], + 1.0) + * v->lb_bit_per_pixel[k] + / v->line_buffer_size, + 1.0), + dcn_bw_ceil2( + (v->vta_pschroma[k] + + dcn_bw_max2( + dcn_bw_ceil2( + v->v_ratio[k] + / 2.0, + 1.0) + - 2, + 0.0)) + * v->swath_width_ysingle_dpp[k] + / 2.0 + / dcn_bw_max2( + v->h_ratio[k] + / 2.0, + 1.0) + * v->lb_bit_per_pixel[k] + / v->line_buffer_size, + 1.0)); + } + v->number_of_dpp_required_for_det_and_lb_size[k] = dcn_bw_max2( + v->number_of_dpp_required_for_det_size, + v->number_of_dpp_required_for_lb_size); + } + for (i = 0; i <= number_of_states_plus_one; i++) { + for (j = 0; j <= 1; j++) { + v->total_number_of_active_dpp[i][j] = 0.0; + v->required_dispclk[i][j] = 0.0; + v->dispclk_dppclk_support[i][j] = dcn_bw_yes; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + v->min_dispclk_using_single_dpp = dcn_bw_max2( + v->pixel_clock[k], + v->min_dppclk_using_single_dpp[k] * (j + 1)) + * (1.0 + v->downspreading / 100.0); + if (v->odm_capability == dcn_bw_yes) { + v->min_dispclk_using_dual_dpp = dcn_bw_max2( + v->pixel_clock[k] / 2.0, + v->min_dppclk_using_single_dpp[k] / 2.0 + * (j + 1)) + * (1.0 + v->downspreading / 100.0); + } else { + v->min_dispclk_using_dual_dpp = dcn_bw_max2( + v->pixel_clock[k], + v->min_dppclk_using_single_dpp[k] / 2.0 + * (j + 1)) + * (1.0 + v->downspreading / 100.0); + } + if (i < number_of_states) { + v->min_dispclk_using_single_dpp = + v->min_dispclk_using_single_dpp + * (1.0 + + v->dispclk_ramping_margin + / 100.0); + v->min_dispclk_using_dual_dpp = + v->min_dispclk_using_dual_dpp + * (1.0 + + v->dispclk_ramping_margin + / 100.0); + } + if (v->min_dispclk_using_single_dpp + <= dcn_bw_min2( + v->max_dispclk[i], + (j + 1) * v->max_dppclk[i]) + && v->number_of_dpp_required_for_det_and_lb_size[k] + <= 1.0) { + v->no_of_dpp[i][j][k] = 1.0; + v->required_dispclk[i][j] = dcn_bw_max2( + v->required_dispclk[i][j], + v->min_dispclk_using_single_dpp); + } else if (v->min_dispclk_using_dual_dpp + <= dcn_bw_min2( + v->max_dispclk[i], + (j + 1) * v->max_dppclk[i])) { + v->no_of_dpp[i][j][k] = 2.0; + v->required_dispclk[i][j] = dcn_bw_max2( + v->required_dispclk[i][j], + v->min_dispclk_using_dual_dpp); + } else { + v->no_of_dpp[i][j][k] = 2.0; + v->required_dispclk[i][j] = dcn_bw_max2( + v->required_dispclk[i][j], + v->min_dispclk_using_dual_dpp); + v->dispclk_dppclk_support[i][j] = dcn_bw_no; + } + v->total_number_of_active_dpp[i][j] = + v->total_number_of_active_dpp[i][j] + + v->no_of_dpp[i][j][k]; + } + if (v->total_number_of_active_dpp[i][j] > v->max_num_dpp) { + v->total_number_of_active_dpp[i][j] = 0.0; + v->required_dispclk[i][j] = 0.0; + v->dispclk_dppclk_support[i][j] = dcn_bw_yes; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + v->min_dispclk_using_single_dpp = dcn_bw_max2( + v->pixel_clock[k], + v->min_dppclk_using_single_dpp[k] * (j + 1)) + * (1.0 + v->downspreading / 100.0); + v->min_dispclk_using_dual_dpp = dcn_bw_max2( + v->pixel_clock[k], + v->min_dppclk_using_single_dpp[k] / 2.0 + * (j + 1)) + * (1.0 + v->downspreading / 100.0); + if (i < number_of_states) { + v->min_dispclk_using_single_dpp = + v->min_dispclk_using_single_dpp + * (1.0 + + v->dispclk_ramping_margin + / 100.0); + v->min_dispclk_using_dual_dpp = + v->min_dispclk_using_dual_dpp + * (1.0 + + v->dispclk_ramping_margin + / 100.0); + } + if (v->number_of_dpp_required_for_det_and_lb_size[k] + <= 1.0) { + v->no_of_dpp[i][j][k] = 1.0; + v->required_dispclk[i][j] = dcn_bw_max2( + v->required_dispclk[i][j], + v->min_dispclk_using_single_dpp); + if (v->min_dispclk_using_single_dpp + > dcn_bw_min2( + v->max_dispclk[i], + (j + 1) + * v->max_dppclk[i])) { + v->dispclk_dppclk_support[i][j] = dcn_bw_no; + } + } else { + v->no_of_dpp[i][j][k] = 2.0; + v->required_dispclk[i][j] = dcn_bw_max2( + v->required_dispclk[i][j], + v->min_dispclk_using_dual_dpp); + if (v->min_dispclk_using_dual_dpp + > dcn_bw_min2( + v->max_dispclk[i], + (j + 1) + * v->max_dppclk[i])) { + v->dispclk_dppclk_support[i][j] = dcn_bw_no; + } + } + v->total_number_of_active_dpp[i][j] = + v->total_number_of_active_dpp[i][j] + + v->no_of_dpp[i][j][k]; + } + } + } + } + /*viewport size check*/ + + v->viewport_size_support = dcn_bw_yes; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->number_of_dpp_required_for_det_and_lb_size[k] > 2.0) { + v->viewport_size_support = dcn_bw_no; + } + } + /*total available pipes support check*/ + + for (i = 0; i <= number_of_states_plus_one; i++) { + for (j = 0; j <= 1; j++) { + if (v->total_number_of_active_dpp[i][j] <= v->max_num_dpp) { + v->total_available_pipes_support[i][j] = dcn_bw_yes; + } else { + v->total_available_pipes_support[i][j] = dcn_bw_no; + } + } + } + /*urgent latency support check*/ + + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + for (i = 0; i <= number_of_states_plus_one; i++) { + for (j = 0; j <= 1; j++) { + v->swath_width_yper_state[i][j][k] = v->swath_width_ysingle_dpp[k] + / v->no_of_dpp[i][j][k]; + v->swath_width_granularity_y = 256.0 + / dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) + / v->max_swath_height_y[k]; + v->rounded_up_max_swath_size_bytes_y = (dcn_bw_ceil2( + v->swath_width_yper_state[i][j][k] - 1.0, + v->swath_width_granularity_y) + + v->swath_width_granularity_y) + * v->byte_per_pixel_in_dety[k] + * v->max_swath_height_y[k]; + if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_10) { + v->rounded_up_max_swath_size_bytes_y = dcn_bw_ceil2( + v->rounded_up_max_swath_size_bytes_y, + 256.0) + 256; + } + if (v->max_swath_height_c[k] > 0.0) { + v->swath_width_granularity_c = + 256.0 + / dcn_bw_ceil2( + v->byte_per_pixel_in_detc[k], + 2.0) + / v->max_swath_height_c[k]; + } + v->rounded_up_max_swath_size_bytes_c = (dcn_bw_ceil2( + v->swath_width_yper_state[i][j][k] / 2.0 - 1.0, + v->swath_width_granularity_c) + + v->swath_width_granularity_c) + * v->byte_per_pixel_in_detc[k] + * v->max_swath_height_c[k]; + if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_10) { + v->rounded_up_max_swath_size_bytes_c = dcn_bw_ceil2( + v->rounded_up_max_swath_size_bytes_c, + 256.0) + 256; + } + if (v->rounded_up_max_swath_size_bytes_y + + v->rounded_up_max_swath_size_bytes_c + <= v->det_buffer_size_in_kbyte * 1024.0 / 2.0) { + v->swath_height_yper_state[i][j][k] = + v->max_swath_height_y[k]; + v->swath_height_cper_state[i][j][k] = + v->max_swath_height_c[k]; + } else { + v->swath_height_yper_state[i][j][k] = + v->min_swath_height_y[k]; + v->swath_height_cper_state[i][j][k] = + v->min_swath_height_c[k]; + } + if (v->byte_per_pixel_in_detc[k] == 0.0) { + v->lines_in_det_luma = v->det_buffer_size_in_kbyte * 1024.0 + / v->byte_per_pixel_in_dety[k] + / v->swath_width_yper_state[i][j][k]; + v->lines_in_det_chroma = 0.0; + } else if (v->swath_height_yper_state[i][j][k] + <= v->swath_height_cper_state[i][j][k]) { + v->lines_in_det_luma = v->det_buffer_size_in_kbyte * 1024.0 + / 2.0 / v->byte_per_pixel_in_dety[k] + / v->swath_width_yper_state[i][j][k]; + v->lines_in_det_chroma = + v->det_buffer_size_in_kbyte * 1024.0 / 2.0 + / v->byte_per_pixel_in_detc[k] + / (v->swath_width_yper_state[i][j][k] + / 2.0); + } else { + v->lines_in_det_luma = v->det_buffer_size_in_kbyte * 1024.0 + * 2.0 / 3.0 / v->byte_per_pixel_in_dety[k] + / v->swath_width_yper_state[i][j][k]; + v->lines_in_det_chroma = + v->det_buffer_size_in_kbyte * 1024.0 / 3.0 + / v->byte_per_pixel_in_dety[k] + / (v->swath_width_yper_state[i][j][k] + / 2.0); + } + v->effective_lb_latency_hiding_source_lines_luma = + dcn_bw_min2( + v->max_line_buffer_lines, + dcn_bw_floor2( + v->line_buffer_size + / v->lb_bit_per_pixel[k] + / (v->swath_width_yper_state[i][j][k] + / dcn_bw_max2( + v->h_ratio[k], + 1.0)), + 1.0)) + - (v->vtaps[k] - 1.0); + v->effective_lb_latency_hiding_source_lines_chroma = + dcn_bw_min2( + v->max_line_buffer_lines, + dcn_bw_floor2( + v->line_buffer_size + / v->lb_bit_per_pixel[k] + / (v->swath_width_yper_state[i][j][k] + / 2.0 + / dcn_bw_max2( + v->h_ratio[k] + / 2.0, + 1.0)), + 1.0)) + - (v->vta_pschroma[k] - 1.0); + v->effective_detlb_lines_luma = + dcn_bw_floor2( + v->lines_in_det_luma + + dcn_bw_min2( + v->lines_in_det_luma + * v->required_dispclk[i][j] + * v->byte_per_pixel_in_dety[k] + * v->pscl_factor[k] + / v->return_bw_per_state[i], + v->effective_lb_latency_hiding_source_lines_luma), + v->swath_height_yper_state[i][j][k]); + v->effective_detlb_lines_chroma = + dcn_bw_floor2( + v->lines_in_det_chroma + + dcn_bw_min2( + v->lines_in_det_chroma + * v->required_dispclk[i][j] + * v->byte_per_pixel_in_detc[k] + * v->pscl_factor_chroma[k] + / v->return_bw_per_state[i], + v->effective_lb_latency_hiding_source_lines_chroma), + v->swath_height_cper_state[i][j][k]); + if (v->byte_per_pixel_in_detc[k] == 0.0) { + v->urgent_latency_support_us_per_state[i][j][k] = + v->effective_detlb_lines_luma + * (v->htotal[k] + / v->pixel_clock[k]) + / v->v_ratio[k] + - v->effective_detlb_lines_luma + * v->swath_width_yper_state[i][j][k] + * dcn_bw_ceil2( + v->byte_per_pixel_in_dety[k], + 1.0) + / (v->return_bw_per_state[i] + / v->no_of_dpp[i][j][k]); + } else { + v->urgent_latency_support_us_per_state[i][j][k] = + dcn_bw_min2( + v->effective_detlb_lines_luma + * (v->htotal[k] + / v->pixel_clock[k]) + / v->v_ratio[k] + - v->effective_detlb_lines_luma + * v->swath_width_yper_state[i][j][k] + * dcn_bw_ceil2( + v->byte_per_pixel_in_dety[k], + 1.0) + / (v->return_bw_per_state[i] + / v->no_of_dpp[i][j][k]), + v->effective_detlb_lines_chroma + * (v->htotal[k] + / v->pixel_clock[k]) + / (v->v_ratio[k] + / 2.0) + - v->effective_detlb_lines_chroma + * v->swath_width_yper_state[i][j][k] + / 2.0 + * dcn_bw_ceil2( + v->byte_per_pixel_in_detc[k], + 2.0) + / (v->return_bw_per_state[i] + / v->no_of_dpp[i][j][k])); + } + } + } + } + for (i = 0; i <= number_of_states_plus_one; i++) { + for (j = 0; j <= 1; j++) { + v->urgent_latency_support[i][j] = dcn_bw_yes; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->urgent_latency_support_us_per_state[i][j][k] + < v->urgent_latency / 1.0) { + v->urgent_latency_support[i][j] = dcn_bw_no; + } + } + } + } + /*prefetch check*/ + + for (i = 0; i <= number_of_states_plus_one; i++) { + for (j = 0; j <= 1; j++) { + v->total_number_of_dcc_active_dpp[i][j] = 0.0; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->dcc_enable[k] == dcn_bw_yes) { + v->total_number_of_dcc_active_dpp[i][j] = + v->total_number_of_dcc_active_dpp[i][j] + + v->no_of_dpp[i][j][k]; + } + } + } + } + for (i = 0; i <= number_of_states_plus_one; i++) { + for (j = 0; j <= 1; j++) { + v->projected_dcfclk_deep_sleep = 8.0; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + v->projected_dcfclk_deep_sleep = dcn_bw_max2( + v->projected_dcfclk_deep_sleep, + v->pixel_clock[k] / 16.0); + if (v->byte_per_pixel_in_detc[k] == 0.0) { + if (v->v_ratio[k] <= 1.0) { + v->projected_dcfclk_deep_sleep = + dcn_bw_max2( + v->projected_dcfclk_deep_sleep, + 1.1 + * dcn_bw_ceil2( + v->byte_per_pixel_in_dety[k], + 1.0) + / 64.0 + * v->h_ratio[k] + * v->pixel_clock[k] + / v->no_of_dpp[i][j][k]); + } else { + v->projected_dcfclk_deep_sleep = + dcn_bw_max2( + v->projected_dcfclk_deep_sleep, + 1.1 + * dcn_bw_ceil2( + v->byte_per_pixel_in_dety[k], + 1.0) + / 64.0 + * v->pscl_factor[k] + * v->required_dispclk[i][j] + / (1 + + j)); + } + } else { + if (v->v_ratio[k] <= 1.0) { + v->projected_dcfclk_deep_sleep = + dcn_bw_max2( + v->projected_dcfclk_deep_sleep, + 1.1 + * dcn_bw_ceil2( + v->byte_per_pixel_in_dety[k], + 1.0) + / 32.0 + * v->h_ratio[k] + * v->pixel_clock[k] + / v->no_of_dpp[i][j][k]); + } else { + v->projected_dcfclk_deep_sleep = + dcn_bw_max2( + v->projected_dcfclk_deep_sleep, + 1.1 + * dcn_bw_ceil2( + v->byte_per_pixel_in_dety[k], + 1.0) + / 32.0 + * v->pscl_factor[k] + * v->required_dispclk[i][j] + / (1 + + j)); + } + if (v->v_ratio[k] / 2.0 <= 1.0) { + v->projected_dcfclk_deep_sleep = + dcn_bw_max2( + v->projected_dcfclk_deep_sleep, + 1.1 + * dcn_bw_ceil2( + v->byte_per_pixel_in_detc[k], + 2.0) + / 32.0 + * v->h_ratio[k] + / 2.0 + * v->pixel_clock[k] + / v->no_of_dpp[i][j][k]); + } else { + v->projected_dcfclk_deep_sleep = + dcn_bw_max2( + v->projected_dcfclk_deep_sleep, + 1.1 + * dcn_bw_ceil2( + v->byte_per_pixel_in_detc[k], + 2.0) + / 32.0 + * v->pscl_factor_chroma[k] + * v->required_dispclk[i][j] + / (1 + + j)); + } + } + } + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->dcc_enable[k] == dcn_bw_yes) { + v->meta_req_height_y = 8.0 * v->read256_block_height_y[k]; + v->meta_req_width_y = + 64.0 * 256.0 + / dcn_bw_ceil2( + v->byte_per_pixel_in_dety[k], + 1.0) + / v->meta_req_height_y; + v->meta_surface_width_y = dcn_bw_ceil2( + v->viewport_width[k] / v->no_of_dpp[i][j][k] + - 1.0, + v->meta_req_width_y) + v->meta_req_width_y; + v->meta_surface_height_y = dcn_bw_ceil2( + v->viewport_height[k] - 1.0, + v->meta_req_height_y) + + v->meta_req_height_y; + if (v->pte_enable == dcn_bw_yes) { + v->meta_pte_bytes_per_frame_y = + (dcn_bw_ceil2( + (v->meta_surface_width_y + * v->meta_surface_height_y + * dcn_bw_ceil2( + v->byte_per_pixel_in_dety[k], + 1.0) + / 256.0 + - 4096.0) + / 8.0 + / 4096.0, + 1.0) + 1) * 64.0; + } else { + v->meta_pte_bytes_per_frame_y = 0.0; + } + if (v->source_scan[k] == dcn_bw_hor) { + v->meta_row_bytes_y = + v->meta_surface_width_y + * v->meta_req_height_y + * dcn_bw_ceil2( + v->byte_per_pixel_in_dety[k], + 1.0) + / 256.0; + } else { + v->meta_row_bytes_y = + v->meta_surface_height_y + * v->meta_req_width_y + * dcn_bw_ceil2( + v->byte_per_pixel_in_dety[k], + 1.0) + / 256.0; + } + } else { + v->meta_pte_bytes_per_frame_y = 0.0; + v->meta_row_bytes_y = 0.0; + } + if (v->pte_enable == dcn_bw_yes) { + if (v->source_surface_mode[k] == dcn_bw_sw_linear) { + v->macro_tile_block_size_bytes_y = 256.0; + v->macro_tile_block_height_y = 1.0; + } else if (v->source_surface_mode[k] == dcn_bw_sw_4_kb_s + || v->source_surface_mode[k] + == dcn_bw_sw_4_kb_s_x + || v->source_surface_mode[k] + == dcn_bw_sw_4_kb_d + || v->source_surface_mode[k] + == dcn_bw_sw_4_kb_d_x) { + v->macro_tile_block_size_bytes_y = 4096.0; + v->macro_tile_block_height_y = 4.0 + * v->read256_block_height_y[k]; + } else if (v->source_surface_mode[k] == dcn_bw_sw_64_kb_s + || v->source_surface_mode[k] + == dcn_bw_sw_64_kb_s_t + || v->source_surface_mode[k] + == dcn_bw_sw_64_kb_s_x + || v->source_surface_mode[k] + == dcn_bw_sw_64_kb_d + || v->source_surface_mode[k] + == dcn_bw_sw_64_kb_d_t + || v->source_surface_mode[k] + == dcn_bw_sw_64_kb_d_x) { + v->macro_tile_block_size_bytes_y = 64.0 * 1024; + v->macro_tile_block_height_y = 16.0 + * v->read256_block_height_y[k]; + } else { + v->macro_tile_block_size_bytes_y = 256.0 * 1024; + v->macro_tile_block_height_y = 32.0 + * v->read256_block_height_y[k]; + } + if (v->macro_tile_block_size_bytes_y <= 65536.0) { + v->data_pte_req_height_y = + v->macro_tile_block_height_y; + } else { + v->data_pte_req_height_y = 16.0 + * v->read256_block_height_y[k]; + } + v->data_pte_req_width_y = + 4096.0 + / dcn_bw_ceil2( + v->byte_per_pixel_in_dety[k], + 1.0) + / v->data_pte_req_height_y + * 8; + if (v->source_surface_mode[k] == dcn_bw_sw_linear) { + v->dpte_bytes_per_row_y = + 64.0 + * (dcn_bw_ceil2( + (v->viewport_width[k] + / v->no_of_dpp[i][j][k] + * dcn_bw_min2( + 128.0, + dcn_bw_pow( + 2.0, + dcn_bw_floor2( + dcn_bw_log( + v->pte_buffer_size_in_requests + * v->data_pte_req_width_y + / (v->viewport_width[k] + / v->no_of_dpp[i][j][k]), + 2.0), + 1.0))) + - 1.0) + / v->data_pte_req_width_y, + 1.0) + + 1); + } else if (v->source_scan[k] == dcn_bw_hor) { + v->dpte_bytes_per_row_y = + 64.0 + * (dcn_bw_ceil2( + (v->viewport_width[k] + / v->no_of_dpp[i][j][k] + - 1.0) + / v->data_pte_req_width_y, + 1.0) + + 1); + } else { + v->dpte_bytes_per_row_y = + 64.0 + * (dcn_bw_ceil2( + (v->viewport_height[k] + - 1.0) + / v->data_pte_req_height_y, + 1.0) + + 1); + } + } else { + v->dpte_bytes_per_row_y = 0.0; + } + if ((v->source_pixel_format[k] != dcn_bw_rgb_sub_64 + && v->source_pixel_format[k] != dcn_bw_rgb_sub_32 + && v->source_pixel_format[k] != dcn_bw_rgb_sub_16)) { + if (v->dcc_enable[k] == dcn_bw_yes) { + v->meta_req_height_c = 8.0 + * v->read256_block_height_c[k]; + v->meta_req_width_c = + 64.0 * 256.0 + / dcn_bw_ceil2( + v->byte_per_pixel_in_detc[k], + 2.0) + / v->meta_req_height_c; + v->meta_surface_width_c = + dcn_bw_ceil2( + v->viewport_width[k] + / v->no_of_dpp[i][j][k] + / 2.0 + - 1.0, + v->meta_req_width_c) + + v->meta_req_width_c; + v->meta_surface_height_c = dcn_bw_ceil2( + v->viewport_height[k] / 2.0 - 1.0, + v->meta_req_height_c) + + v->meta_req_height_c; + if (v->pte_enable == dcn_bw_yes) { + v->meta_pte_bytes_per_frame_c = + (dcn_bw_ceil2( + (v->meta_surface_width_c + * v->meta_surface_height_c + * dcn_bw_ceil2( + v->byte_per_pixel_in_detc[k], + 2.0) + / 256.0 + - 4096.0) + / 8.0 + / 4096.0, + 1.0) + 1) + * 64.0; + } else { + v->meta_pte_bytes_per_frame_c = 0.0; + } + if (v->source_scan[k] == dcn_bw_hor) { + v->meta_row_bytes_c = + v->meta_surface_width_c + * v->meta_req_height_c + * dcn_bw_ceil2( + v->byte_per_pixel_in_detc[k], + 2.0) + / 256.0; + } else { + v->meta_row_bytes_c = + v->meta_surface_height_c + * v->meta_req_width_c + * dcn_bw_ceil2( + v->byte_per_pixel_in_detc[k], + 2.0) + / 256.0; + } + } else { + v->meta_pte_bytes_per_frame_c = 0.0; + v->meta_row_bytes_c = 0.0; + } + if (v->pte_enable == dcn_bw_yes) { + if (v->source_surface_mode[k] == dcn_bw_sw_linear) { + v->macro_tile_block_size_bytes_c = 256.0; + v->macro_tile_block_height_c = 1.0; + } else if (v->source_surface_mode[k] + == dcn_bw_sw_4_kb_s + || v->source_surface_mode[k] + == dcn_bw_sw_4_kb_s_x + || v->source_surface_mode[k] + == dcn_bw_sw_4_kb_d + || v->source_surface_mode[k] + == dcn_bw_sw_4_kb_d_x) { + v->macro_tile_block_size_bytes_c = 4096.0; + v->macro_tile_block_height_c = + 4.0 + * v->read256_block_height_c[k]; + } else if (v->source_surface_mode[k] + == dcn_bw_sw_64_kb_s + || v->source_surface_mode[k] + == dcn_bw_sw_64_kb_s_t + || v->source_surface_mode[k] + == dcn_bw_sw_64_kb_s_x + || v->source_surface_mode[k] + == dcn_bw_sw_64_kb_d + || v->source_surface_mode[k] + == dcn_bw_sw_64_kb_d_t + || v->source_surface_mode[k] + == dcn_bw_sw_64_kb_d_x) { + v->macro_tile_block_size_bytes_c = 64.0 + * 1024; + v->macro_tile_block_height_c = + 16.0 + * v->read256_block_height_c[k]; + } else { + v->macro_tile_block_size_bytes_c = 256.0 + * 1024; + v->macro_tile_block_height_c = + 32.0 + * v->read256_block_height_c[k]; + } + v->macro_tile_block_width_c = + v->macro_tile_block_size_bytes_c + / dcn_bw_ceil2( + v->byte_per_pixel_in_detc[k], + 2.0) + / v->macro_tile_block_height_c; + if (v->macro_tile_block_size_bytes_c <= 65536.0) { + v->data_pte_req_height_c = + v->macro_tile_block_height_c; + } else { + v->data_pte_req_height_c = + 16.0 + * v->read256_block_height_c[k]; + } + v->data_pte_req_width_c = + 4096.0 + / dcn_bw_ceil2( + v->byte_per_pixel_in_detc[k], + 2.0) + / v->data_pte_req_height_c + * 8; + if (v->source_surface_mode[k] == dcn_bw_sw_linear) { + v->dpte_bytes_per_row_c = + 64.0 + * (dcn_bw_ceil2( + (v->viewport_width[k] + / v->no_of_dpp[i][j][k] + / 2.0 + * dcn_bw_min2( + 128.0, + dcn_bw_pow( + 2.0, + dcn_bw_floor2( + dcn_bw_log( + v->pte_buffer_size_in_requests + * v->data_pte_req_width_c + / (v->viewport_width[k] + / v->no_of_dpp[i][j][k] + / 2.0), + 2.0), + 1.0))) + - 1.0) + / v->data_pte_req_width_c, + 1.0) + + 1); + } else if (v->source_scan[k] == dcn_bw_hor) { + v->dpte_bytes_per_row_c = + 64.0 + * (dcn_bw_ceil2( + (v->viewport_width[k] + / v->no_of_dpp[i][j][k] + / 2.0 + - 1.0) + / v->data_pte_req_width_c, + 1.0) + + 1); + } else { + v->dpte_bytes_per_row_c = + 64.0 + * (dcn_bw_ceil2( + (v->viewport_height[k] + / 2.0 + - 1.0) + / v->data_pte_req_height_c, + 1.0) + + 1); + } + } else { + v->dpte_bytes_per_row_c = 0.0; + } + } else { + v->dpte_bytes_per_row_c = 0.0; + v->meta_pte_bytes_per_frame_c = 0.0; + v->meta_row_bytes_c = 0.0; + } + v->dpte_bytes_per_row[k] = v->dpte_bytes_per_row_y + + v->dpte_bytes_per_row_c; + v->meta_pte_bytes_per_frame[k] = v->meta_pte_bytes_per_frame_y + + v->meta_pte_bytes_per_frame_c; + v->meta_row_bytes[k] = v->meta_row_bytes_y + v->meta_row_bytes_c; + v->v_init_y = (v->v_ratio[k] + v->vtaps[k] + 1.0 + + v->interlace_output[k] * 0.5 * v->v_ratio[k]) + / 2.0; + v->prefill_y[k] = dcn_bw_floor2(v->v_init_y, 1.0); + v->max_num_sw_y[k] = + dcn_bw_ceil2( + (v->prefill_y[k] - 1.0) + / v->swath_height_yper_state[i][j][k], + 1.0) + 1; + if (v->prefill_y[k] > 1.0) { + v->max_partial_sw_y = dcn_bw_mod( + (v->prefill_y[k] - 2.0), + v->swath_height_yper_state[i][j][k]); + } else { + v->max_partial_sw_y = + dcn_bw_mod( + (v->prefill_y[k] + + v->swath_height_yper_state[i][j][k] + - 2.0), + v->swath_height_yper_state[i][j][k]); + } + v->max_partial_sw_y = dcn_bw_max2(1.0, v->max_partial_sw_y); + v->prefetch_lines_y[k] = v->max_num_sw_y[k] + * v->swath_height_yper_state[i][j][k] + + v->max_partial_sw_y; + if ((v->source_pixel_format[k] != dcn_bw_rgb_sub_64 + && v->source_pixel_format[k] != dcn_bw_rgb_sub_32 + && v->source_pixel_format[k] != dcn_bw_rgb_sub_16)) { + v->v_init_c = (v->v_ratio[k] / 2.0 + v->vtaps[k] + 1.0 + + v->interlace_output[k] * 0.5 + * v->v_ratio[k] / 2.0) + / 2.0; + v->prefill_c[k] = dcn_bw_floor2(v->v_init_c, 1.0); + v->max_num_sw_c[k] = + dcn_bw_ceil2( + (v->prefill_c[k] - 1.0) + / v->swath_height_cper_state[i][j][k], + 1.0) + 1; + if (v->prefill_c[k] > 1.0) { + v->max_partial_sw_c = + dcn_bw_mod( + (v->prefill_c[k] + - 2.0), + v->swath_height_cper_state[i][j][k]); + } else { + v->max_partial_sw_c = + dcn_bw_mod( + (v->prefill_c[k] + + v->swath_height_cper_state[i][j][k] + - 2.0), + v->swath_height_cper_state[i][j][k]); + } + v->max_partial_sw_c = dcn_bw_max2(1.0, v->max_partial_sw_c); + v->prefetch_lines_c[k] = v->max_num_sw_c[k] + * v->swath_height_cper_state[i][j][k] + + v->max_partial_sw_c; + } else { + v->prefetch_lines_c[k] = 0.0; + } + v->dst_x_after_scaler = 90.0 * v->pixel_clock[k] + / (v->required_dispclk[i][j] / (j + 1)) + + 42.0 * v->pixel_clock[k] + / v->required_dispclk[i][j]; + if (v->no_of_dpp[i][j][k] > 1.0) { + v->dst_x_after_scaler = v->dst_x_after_scaler + + v->scaler_rec_out_width[k] / 2.0; + } + if (v->output_format[k] == dcn_bw_420) { + v->dst_y_after_scaler = 1.0; + } else { + v->dst_y_after_scaler = 0.0; + } + v->time_calc = 24.0 / v->projected_dcfclk_deep_sleep; + v->v_update_offset[k] = dcn_bw_ceil2(v->htotal[k] / 4.0, 1.0); + v->total_repeater_delay = v->max_inter_dcn_tile_repeaters + * (2.0 / (v->required_dispclk[i][j] / (j + 1)) + + 3.0 / v->required_dispclk[i][j]); + v->v_update_width[k] = (14.0 / v->projected_dcfclk_deep_sleep + + 12.0 / (v->required_dispclk[i][j] / (j + 1)) + + v->total_repeater_delay) * v->pixel_clock[k]; + v->v_ready_offset[k] = + dcn_bw_max2( + 150.0 + / (v->required_dispclk[i][j] + / (j + + 1)), + v->total_repeater_delay + + 20.0 + / v->projected_dcfclk_deep_sleep + + 10.0 + / (v->required_dispclk[i][j] + / (j + + 1))) + * v->pixel_clock[k]; + v->time_setup = (v->v_update_offset[k] + v->v_update_width[k] + + v->v_ready_offset[k]) / v->pixel_clock[k]; + v->extra_latency = + v->urgent_round_trip_and_out_of_order_latency_per_state[i] + + (v->total_number_of_active_dpp[i][j] + * v->pixel_chunk_size_in_kbyte + + v->total_number_of_dcc_active_dpp[i][j] + * v->meta_chunk_size) + * 1024.0 + / v->return_bw_per_state[i]; + if (v->pte_enable == dcn_bw_yes) { + v->extra_latency = v->extra_latency + + v->total_number_of_active_dpp[i][j] + * v->pte_chunk_size * 1024.0 + / v->return_bw_per_state[i]; + } + if (v->can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one + == dcn_bw_yes) { + v->maximum_vstartup = v->vtotal[k] - v->vactive[k] - 1.0; + } else { + v->maximum_vstartup = v->v_sync_plus_back_porch[k] - 1.0; + } + v->line_times_for_prefetch[k] = v->maximum_vstartup + - v->urgent_latency + / (v->htotal[k] / v->pixel_clock[k]) + - (v->time_calc + v->time_setup) + / (v->htotal[k] / v->pixel_clock[k]) + - (v->dst_y_after_scaler + + v->dst_x_after_scaler + / v->htotal[k]); + v->line_times_for_prefetch[k] = dcn_bw_floor2( + 4.0 * (v->line_times_for_prefetch[k] + 0.125), + 1.0) / 4; + v->prefetch_bw[k] = + (v->meta_pte_bytes_per_frame[k] + + 2.0 * v->meta_row_bytes[k] + + 2.0 * v->dpte_bytes_per_row[k] + + v->prefetch_lines_y[k] + * v->swath_width_yper_state[i][j][k] + * dcn_bw_ceil2( + v->byte_per_pixel_in_dety[k], + 1.0) + + v->prefetch_lines_c[k] + * v->swath_width_yper_state[i][j][k] + / 2.0 + * dcn_bw_ceil2( + v->byte_per_pixel_in_detc[k], + 2.0)) + / (v->line_times_for_prefetch[k] + * v->htotal[k] + / v->pixel_clock[k]); + } + v->bw_available_for_immediate_flip = v->return_bw_per_state[i]; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + v->bw_available_for_immediate_flip = + v->bw_available_for_immediate_flip + - dcn_bw_max2( + v->read_bandwidth[k], + v->prefetch_bw[k]); + } + v->total_immediate_flip_bytes[k] = 0.0; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if ((v->source_pixel_format[k] != dcn_bw_yuv420_sub_8 + && v->source_pixel_format[k] != dcn_bw_yuv420_sub_10)) { + v->total_immediate_flip_bytes[k] = + v->total_immediate_flip_bytes[k] + + v->meta_pte_bytes_per_frame[k] + + v->meta_row_bytes[k] + + v->dpte_bytes_per_row[k]; + } + } + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->pte_enable == dcn_bw_yes && v->dcc_enable[k] == dcn_bw_yes) { + v->time_for_meta_pte_with_immediate_flip = + dcn_bw_max5( + v->meta_pte_bytes_per_frame[k] + / v->prefetch_bw[k], + v->meta_pte_bytes_per_frame[k] + * v->total_immediate_flip_bytes[k] + / (v->bw_available_for_immediate_flip + * (v->meta_pte_bytes_per_frame[k] + + v->meta_row_bytes[k] + + v->dpte_bytes_per_row[k])), + v->extra_latency, + v->urgent_latency, + v->htotal[k] + / v->pixel_clock[k] + / 4.0); + v->time_for_meta_pte_without_immediate_flip = dcn_bw_max3( + v->meta_pte_bytes_per_frame[k] + / v->prefetch_bw[k], + v->extra_latency, + v->htotal[k] / v->pixel_clock[k] / 4.0); + } else { + v->time_for_meta_pte_with_immediate_flip = v->htotal[k] + / v->pixel_clock[k] / 4.0; + v->time_for_meta_pte_without_immediate_flip = v->htotal[k] + / v->pixel_clock[k] / 4.0; + } + if (v->pte_enable == dcn_bw_yes || v->dcc_enable[k] == dcn_bw_yes) { + v->time_for_meta_and_dpte_row_with_immediate_flip = + dcn_bw_max5( + (v->meta_row_bytes[k] + + v->dpte_bytes_per_row[k]) + / v->prefetch_bw[k], + (v->meta_row_bytes[k] + + v->dpte_bytes_per_row[k]) + * v->total_immediate_flip_bytes[k] + / (v->bw_available_for_immediate_flip + * (v->meta_pte_bytes_per_frame[k] + + v->meta_row_bytes[k] + + v->dpte_bytes_per_row[k])), + v->htotal[k] + / v->pixel_clock[k] + - v->time_for_meta_pte_with_immediate_flip, + v->extra_latency, + 2.0 * v->urgent_latency); + v->time_for_meta_and_dpte_row_without_immediate_flip = + dcn_bw_max3( + (v->meta_row_bytes[k] + + v->dpte_bytes_per_row[k]) + / v->prefetch_bw[k], + v->htotal[k] + / v->pixel_clock[k] + - v->time_for_meta_pte_without_immediate_flip, + v->extra_latency); + } else { + v->time_for_meta_and_dpte_row_with_immediate_flip = + dcn_bw_max2( + v->htotal[k] + / v->pixel_clock[k] + - v->time_for_meta_pte_with_immediate_flip, + v->extra_latency + - v->time_for_meta_pte_with_immediate_flip); + v->time_for_meta_and_dpte_row_without_immediate_flip = + dcn_bw_max2( + v->htotal[k] + / v->pixel_clock[k] + - v->time_for_meta_pte_without_immediate_flip, + v->extra_latency + - v->time_for_meta_pte_without_immediate_flip); + } + v->lines_for_meta_pte_with_immediate_flip[k] = + dcn_bw_floor2( + 4.0 + * (v->time_for_meta_pte_with_immediate_flip + / (v->htotal[k] + / v->pixel_clock[k]) + + 0.125), + 1.0) / 4; + v->lines_for_meta_pte_without_immediate_flip[k] = + dcn_bw_floor2( + 4.0 + * (v->time_for_meta_pte_without_immediate_flip + / (v->htotal[k] + / v->pixel_clock[k]) + + 0.125), + 1.0) / 4; + v->lines_for_meta_and_dpte_row_with_immediate_flip[k] = + dcn_bw_floor2( + 4.0 + * (v->time_for_meta_and_dpte_row_with_immediate_flip + / (v->htotal[k] + / v->pixel_clock[k]) + + 0.125), + 1.0) / 4; + v->lines_for_meta_and_dpte_row_without_immediate_flip[k] = + dcn_bw_floor2( + 4.0 + * (v->time_for_meta_and_dpte_row_without_immediate_flip + / (v->htotal[k] + / v->pixel_clock[k]) + + 0.125), + 1.0) / 4; + v->line_times_to_request_prefetch_pixel_data_with_immediate_flip = + v->line_times_for_prefetch[k] + - v->lines_for_meta_pte_with_immediate_flip[k] + - v->lines_for_meta_and_dpte_row_with_immediate_flip[k]; + v->line_times_to_request_prefetch_pixel_data_without_immediate_flip = + v->line_times_for_prefetch[k] + - v->lines_for_meta_pte_without_immediate_flip[k] + - v->lines_for_meta_and_dpte_row_without_immediate_flip[k]; + if (v->line_times_to_request_prefetch_pixel_data_with_immediate_flip + > 0.0) { + v->v_ratio_pre_ywith_immediate_flip[i][j][k] = + v->prefetch_lines_y[k] + / v->line_times_to_request_prefetch_pixel_data_with_immediate_flip; + if ((v->swath_height_yper_state[i][j][k] > 4.0)) { + if (v->line_times_to_request_prefetch_pixel_data_with_immediate_flip + - (v->prefill_y[k] - 3.0) / 2.0 + > 0.0) { + v->v_ratio_pre_ywith_immediate_flip[i][j][k] = + dcn_bw_max2( + v->v_ratio_pre_ywith_immediate_flip[i][j][k], + (v->max_num_sw_y[k] + * v->swath_height_yper_state[i][j][k]) + / (v->line_times_to_request_prefetch_pixel_data_with_immediate_flip + - (v->prefill_y[k] + - 3.0) + / 2.0)); + } else { + v->v_ratio_pre_ywith_immediate_flip[i][j][k] = + 999999.0; + } + } + v->v_ratio_pre_cwith_immediate_flip[i][j][k] = + v->prefetch_lines_c[k] + / v->line_times_to_request_prefetch_pixel_data_with_immediate_flip; + if ((v->swath_height_cper_state[i][j][k] > 4.0)) { + if (v->line_times_to_request_prefetch_pixel_data_with_immediate_flip + - (v->prefill_c[k] - 3.0) / 2.0 + > 0.0) { + v->v_ratio_pre_cwith_immediate_flip[i][j][k] = + dcn_bw_max2( + v->v_ratio_pre_cwith_immediate_flip[i][j][k], + (v->max_num_sw_c[k] + * v->swath_height_cper_state[i][j][k]) + / (v->line_times_to_request_prefetch_pixel_data_with_immediate_flip + - (v->prefill_c[k] + - 3.0) + / 2.0)); + } else { + v->v_ratio_pre_cwith_immediate_flip[i][j][k] = + 999999.0; + } + } + v->required_prefetch_pixel_data_bw_with_immediate_flip[i][j][k] = + v->no_of_dpp[i][j][k] + * (v->prefetch_lines_y[k] + / v->line_times_to_request_prefetch_pixel_data_with_immediate_flip + * dcn_bw_ceil2( + v->byte_per_pixel_in_dety[k], + 1.0) + + v->prefetch_lines_c[k] + / v->line_times_to_request_prefetch_pixel_data_with_immediate_flip + * dcn_bw_ceil2( + v->byte_per_pixel_in_detc[k], + 2.0) + / 2.0) + * v->swath_width_yper_state[i][j][k] + / (v->htotal[k] + / v->pixel_clock[k]); + } else { + v->v_ratio_pre_ywith_immediate_flip[i][j][k] = 999999.0; + v->v_ratio_pre_cwith_immediate_flip[i][j][k] = 999999.0; + v->required_prefetch_pixel_data_bw_with_immediate_flip[i][j][k] = + 999999.0; + } + if (v->line_times_to_request_prefetch_pixel_data_without_immediate_flip + > 0.0) { + v->v_ratio_pre_ywithout_immediate_flip[i][j][k] = + v->prefetch_lines_y[k] + / v->line_times_to_request_prefetch_pixel_data_without_immediate_flip; + if ((v->swath_height_yper_state[i][j][k] > 4.0)) { + if (v->line_times_to_request_prefetch_pixel_data_without_immediate_flip + - (v->prefill_y[k] - 3.0) / 2.0 + > 0.0) { + v->v_ratio_pre_ywithout_immediate_flip[i][j][k] = + dcn_bw_max2( + v->v_ratio_pre_ywithout_immediate_flip[i][j][k], + (v->max_num_sw_y[k] + * v->swath_height_yper_state[i][j][k]) + / (v->line_times_to_request_prefetch_pixel_data_without_immediate_flip + - (v->prefill_y[k] + - 3.0) + / 2.0)); + } else { + v->v_ratio_pre_ywithout_immediate_flip[i][j][k] = + 999999.0; + } + } + v->v_ratio_pre_cwithout_immediate_flip[i][j][k] = + v->prefetch_lines_c[k] + / v->line_times_to_request_prefetch_pixel_data_without_immediate_flip; + if ((v->swath_height_cper_state[i][j][k] > 4.0)) { + if (v->line_times_to_request_prefetch_pixel_data_without_immediate_flip + - (v->prefill_c[k] - 3.0) / 2.0 + > 0.0) { + v->v_ratio_pre_cwithout_immediate_flip[i][j][k] = + dcn_bw_max2( + v->v_ratio_pre_cwithout_immediate_flip[i][j][k], + (v->max_num_sw_c[k] + * v->swath_height_cper_state[i][j][k]) + / (v->line_times_to_request_prefetch_pixel_data_without_immediate_flip + - (v->prefill_c[k] + - 3.0) + / 2.0)); + } else { + v->v_ratio_pre_cwithout_immediate_flip[i][j][k] = + 999999.0; + } + } + v->required_prefetch_pixel_data_bw_without_immediate_flip[i][j][k] = + v->no_of_dpp[i][j][k] + * (v->prefetch_lines_y[k] + / v->line_times_to_request_prefetch_pixel_data_without_immediate_flip + * dcn_bw_ceil2( + v->byte_per_pixel_in_dety[k], + 1.0) + + v->prefetch_lines_c[k] + / v->line_times_to_request_prefetch_pixel_data_without_immediate_flip + * dcn_bw_ceil2( + v->byte_per_pixel_in_detc[k], + 2.0) + / 2.0) + * v->swath_width_yper_state[i][j][k] + / (v->htotal[k] + / v->pixel_clock[k]); + } else { + v->v_ratio_pre_ywithout_immediate_flip[i][j][k] = 999999.0; + v->v_ratio_pre_cwithout_immediate_flip[i][j][k] = 999999.0; + v->required_prefetch_pixel_data_bw_without_immediate_flip[i][j][k] = + 999999.0; + } + } + v->maximum_read_bandwidth_with_prefetch_with_immediate_flip = 0.0; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if ((v->source_pixel_format[k] != dcn_bw_yuv420_sub_8 + && v->source_pixel_format[k] != dcn_bw_yuv420_sub_10)) { + v->maximum_read_bandwidth_with_prefetch_with_immediate_flip = + v->maximum_read_bandwidth_with_prefetch_with_immediate_flip + + dcn_bw_max2( + v->read_bandwidth[k], + v->required_prefetch_pixel_data_bw_with_immediate_flip[i][j][k]) + + dcn_bw_max2( + v->meta_pte_bytes_per_frame[k] + / (v->lines_for_meta_pte_with_immediate_flip[k] + * v->htotal[k] + / v->pixel_clock[k]), + (v->meta_row_bytes[k] + + v->dpte_bytes_per_row[k]) + / (v->lines_for_meta_and_dpte_row_with_immediate_flip[k] + * v->htotal[k] + / v->pixel_clock[k])); + } else { + v->maximum_read_bandwidth_with_prefetch_with_immediate_flip = + v->maximum_read_bandwidth_with_prefetch_with_immediate_flip + + dcn_bw_max2( + v->read_bandwidth[k], + v->required_prefetch_pixel_data_bw_without_immediate_flip[i][j][k]); + } + } + v->maximum_read_bandwidth_with_prefetch_without_immediate_flip = 0.0; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + v->maximum_read_bandwidth_with_prefetch_without_immediate_flip = + v->maximum_read_bandwidth_with_prefetch_without_immediate_flip + + dcn_bw_max2( + v->read_bandwidth[k], + v->required_prefetch_pixel_data_bw_without_immediate_flip[i][j][k]); + } + v->prefetch_supported_with_immediate_flip[i][j] = dcn_bw_yes; + if (v->maximum_read_bandwidth_with_prefetch_with_immediate_flip + > v->return_bw_per_state[i]) { + v->prefetch_supported_with_immediate_flip[i][j] = dcn_bw_no; + } + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->line_times_for_prefetch[k] < 2.0 + || v->lines_for_meta_pte_with_immediate_flip[k] + >= 8.0 + || v->lines_for_meta_and_dpte_row_with_immediate_flip[k] + >= 16.0) { + v->prefetch_supported_with_immediate_flip[i][j] = dcn_bw_no; + } + } + v->prefetch_supported_without_immediate_flip[i][j] = dcn_bw_yes; + if (v->maximum_read_bandwidth_with_prefetch_without_immediate_flip + > v->return_bw_per_state[i]) { + v->prefetch_supported_without_immediate_flip[i][j] = dcn_bw_no; + } + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->line_times_for_prefetch[k] < 2.0 + || v->lines_for_meta_pte_without_immediate_flip[k] + >= 8.0 + || v->lines_for_meta_and_dpte_row_without_immediate_flip[k] + >= 16.0) { + v->prefetch_supported_without_immediate_flip[i][j] = + dcn_bw_no; + } + } + } + } + for (i = 0; i <= number_of_states_plus_one; i++) { + for (j = 0; j <= 1; j++) { + v->v_ratio_in_prefetch_supported_with_immediate_flip[i][j] = dcn_bw_yes; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if ((((v->source_pixel_format[k] != dcn_bw_yuv420_sub_8 + && v->source_pixel_format[k] != dcn_bw_yuv420_sub_10) + && (v->v_ratio_pre_ywith_immediate_flip[i][j][k] + > 4.0 + || v->v_ratio_pre_cwith_immediate_flip[i][j][k] + > 4.0)) + || ((v->source_pixel_format[k] + == dcn_bw_yuv420_sub_8 + || v->source_pixel_format[k] + == dcn_bw_yuv420_sub_10) + && (v->v_ratio_pre_ywithout_immediate_flip[i][j][k] + > 4.0 + || v->v_ratio_pre_cwithout_immediate_flip[i][j][k] + > 4.0)))) { + v->v_ratio_in_prefetch_supported_with_immediate_flip[i][j] = + dcn_bw_no; + } + } + v->v_ratio_in_prefetch_supported_without_immediate_flip[i][j] = dcn_bw_yes; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if ((v->v_ratio_pre_ywithout_immediate_flip[i][j][k] > 4.0 + || v->v_ratio_pre_cwithout_immediate_flip[i][j][k] + > 4.0)) { + v->v_ratio_in_prefetch_supported_without_immediate_flip[i][j] = + dcn_bw_no; + } + } + } + } + /*mode support, voltage state and soc configuration*/ + + for (i = number_of_states_plus_one; i >= 0; i--) { + for (j = 0; j <= 1; j++) { + if (v->scale_ratio_support == dcn_bw_yes + && v->source_format_pixel_and_scan_support == dcn_bw_yes + && v->viewport_size_support == dcn_bw_yes + && v->bandwidth_support[i] == dcn_bw_yes + && v->dio_support[i] == dcn_bw_yes + && v->urgent_latency_support[i][j] == dcn_bw_yes + && v->rob_support[i] == dcn_bw_yes + && v->dispclk_dppclk_support[i][j] == dcn_bw_yes + && v->total_available_pipes_support[i][j] == dcn_bw_yes + && v->total_available_writeback_support == dcn_bw_yes + && v->writeback_latency_support == dcn_bw_yes) { + if (v->prefetch_supported_with_immediate_flip[i][j] == dcn_bw_yes + && v->v_ratio_in_prefetch_supported_with_immediate_flip[i][j] + == dcn_bw_yes) { + v->mode_support_with_immediate_flip[i][j] = dcn_bw_yes; + } else { + v->mode_support_with_immediate_flip[i][j] = dcn_bw_no; + } + if (v->prefetch_supported_without_immediate_flip[i][j] == dcn_bw_yes + && v->v_ratio_in_prefetch_supported_without_immediate_flip[i][j] + == dcn_bw_yes) { + v->mode_support_without_immediate_flip[i][j] = dcn_bw_yes; + } else { + v->mode_support_without_immediate_flip[i][j] = dcn_bw_no; + } + } else { + v->mode_support_with_immediate_flip[i][j] = dcn_bw_no; + v->mode_support_without_immediate_flip[i][j] = dcn_bw_no; + } + } + } + for (i = number_of_states_plus_one; i >= 0; i--) { + if ((i == number_of_states_plus_one + || v->mode_support_with_immediate_flip[i][1] == dcn_bw_yes + || v->mode_support_with_immediate_flip[i][0] == dcn_bw_yes) + && i >= v->voltage_override_level) { + v->voltage_level_with_immediate_flip = i; + } + } + for (i = number_of_states_plus_one; i >= 0; i--) { + if ((i == number_of_states_plus_one + || v->mode_support_without_immediate_flip[i][1] == dcn_bw_yes + || v->mode_support_without_immediate_flip[i][0] == dcn_bw_yes) + && i >= v->voltage_override_level) { + v->voltage_level_without_immediate_flip = i; + } + } + if (v->voltage_level_with_immediate_flip == number_of_states_plus_one) { + v->immediate_flip_supported = dcn_bw_no; + v->voltage_level = v->voltage_level_without_immediate_flip; + } else { + v->immediate_flip_supported = dcn_bw_yes; + v->voltage_level = v->voltage_level_with_immediate_flip; + } + v->dcfclk = v->dcfclk_per_state[v->voltage_level]; + v->fabric_and_dram_bandwidth = v->fabric_and_dram_bandwidth_per_state[v->voltage_level]; + for (j = 0; j <= 1; j++) { + v->required_dispclk_per_ratio[j] = v->required_dispclk[v->voltage_level][j]; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + v->dpp_per_plane_per_ratio[j][k] = v->no_of_dpp[v->voltage_level][j][k]; + } + v->dispclk_dppclk_support_per_ratio[j] = + v->dispclk_dppclk_support[v->voltage_level][j]; + } + v->max_phyclk = v->phyclk_per_state[v->voltage_level]; +} +void display_pipe_configuration(struct dcn_bw_internal_vars *v) +{ + int j, k; + /*display pipe configuration*/ + + for (j = 0; j <= 1; j++) { + v->total_number_of_active_dpp_per_ratio[j] = 0.0; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + v->total_number_of_active_dpp_per_ratio[j] = + v->total_number_of_active_dpp_per_ratio[j] + + v->dpp_per_plane_per_ratio[j][k]; + } + } + if ((v->dispclk_dppclk_support_per_ratio[0] == dcn_bw_yes + && v->dispclk_dppclk_support_per_ratio[1] == dcn_bw_no) + || (v->dispclk_dppclk_support_per_ratio[0] + == v->dispclk_dppclk_support_per_ratio[1] + && (v->total_number_of_active_dpp_per_ratio[0] + < v->total_number_of_active_dpp_per_ratio[1] + || (((v->total_number_of_active_dpp_per_ratio[0] + == v->total_number_of_active_dpp_per_ratio[1]) + && v->required_dispclk_per_ratio[0] + <= 0.5 + * v->required_dispclk_per_ratio[1]))))) { + v->dispclk_dppclk_ratio = 1; + v->final_error_message = v->error_message[0]; + } else { + v->dispclk_dppclk_ratio = 2; + v->final_error_message = v->error_message[1]; + } + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + v->dpp_per_plane[k] = v->dpp_per_plane_per_ratio[v->dispclk_dppclk_ratio - 1][k]; + } + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->source_pixel_format[k] == dcn_bw_rgb_sub_64) { + v->byte_per_pix_dety = 8.0; + v->byte_per_pix_detc = 0.0; + } else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_32) { + v->byte_per_pix_dety = 4.0; + v->byte_per_pix_detc = 0.0; + } else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_16) { + v->byte_per_pix_dety = 2.0; + v->byte_per_pix_detc = 0.0; + } else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_8) { + v->byte_per_pix_dety = 1.0; + v->byte_per_pix_detc = 2.0; + } else { + v->byte_per_pix_dety = 4.0f / 3; + v->byte_per_pix_detc = 8.0f / 3; + } + if ((v->source_pixel_format[k] == dcn_bw_rgb_sub_64 + || v->source_pixel_format[k] == dcn_bw_rgb_sub_32 + || v->source_pixel_format[k] == dcn_bw_rgb_sub_16)) { + if (v->source_surface_mode[k] == dcn_bw_sw_linear) { + v->read256_bytes_block_height_y = 1.0; + } else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_64) { + v->read256_bytes_block_height_y = 4.0; + } else { + v->read256_bytes_block_height_y = 8.0; + } + v->read256_bytes_block_width_y = 256.0 / dcn_bw_ceil2(v->byte_per_pix_dety, 1.0) + / v->read256_bytes_block_height_y; + v->read256_bytes_block_height_c = 0.0; + v->read256_bytes_block_width_c = 0.0; + } else { + if (v->source_surface_mode[k] == dcn_bw_sw_linear) { + v->read256_bytes_block_height_y = 1.0; + v->read256_bytes_block_height_c = 1.0; + } else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_8) { + v->read256_bytes_block_height_y = 16.0; + v->read256_bytes_block_height_c = 8.0; + } else { + v->read256_bytes_block_height_y = 8.0; + v->read256_bytes_block_height_c = 8.0; + } + v->read256_bytes_block_width_y = 256.0 / dcn_bw_ceil2(v->byte_per_pix_dety, 1.0) + / v->read256_bytes_block_height_y; + v->read256_bytes_block_width_c = 256.0 / dcn_bw_ceil2(v->byte_per_pix_detc, 2.0) + / v->read256_bytes_block_height_c; + } + if (v->source_scan[k] == dcn_bw_hor) { + v->maximum_swath_height_y = v->read256_bytes_block_height_y; + v->maximum_swath_height_c = v->read256_bytes_block_height_c; + } else { + v->maximum_swath_height_y = v->read256_bytes_block_width_y; + v->maximum_swath_height_c = v->read256_bytes_block_width_c; + } + if ((v->source_pixel_format[k] == dcn_bw_rgb_sub_64 + || v->source_pixel_format[k] == dcn_bw_rgb_sub_32 + || v->source_pixel_format[k] == dcn_bw_rgb_sub_16)) { + if (v->source_surface_mode[k] == dcn_bw_sw_linear + || (v->source_pixel_format[k] == dcn_bw_rgb_sub_64 + && (v->source_surface_mode[k] + == dcn_bw_sw_4_kb_s + || v->source_surface_mode[k] + == dcn_bw_sw_4_kb_s_x + || v->source_surface_mode[k] + == dcn_bw_sw_64_kb_s + || v->source_surface_mode[k] + == dcn_bw_sw_64_kb_s_t + || v->source_surface_mode[k] + == dcn_bw_sw_64_kb_s_x + || v->source_surface_mode[k] + == dcn_bw_sw_var_s + || v->source_surface_mode[k] + == dcn_bw_sw_var_s_x) + && v->source_scan[k] == dcn_bw_hor)) { + v->minimum_swath_height_y = v->maximum_swath_height_y; + } else { + v->minimum_swath_height_y = v->maximum_swath_height_y / 2.0; + } + v->minimum_swath_height_c = v->maximum_swath_height_c; + } else { + if (v->source_surface_mode[k] == dcn_bw_sw_linear) { + v->minimum_swath_height_y = v->maximum_swath_height_y; + v->minimum_swath_height_c = v->maximum_swath_height_c; + } else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_8 + && v->source_scan[k] == dcn_bw_hor) { + v->minimum_swath_height_y = v->maximum_swath_height_y / 2.0; + if (v->bug_forcing_luma_and_chroma_request_to_same_size_fixed + == dcn_bw_yes) { + v->minimum_swath_height_c = v->maximum_swath_height_c; + } else { + v->minimum_swath_height_c = v->maximum_swath_height_c / 2.0; + } + } else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_10 + && v->source_scan[k] == dcn_bw_hor) { + v->minimum_swath_height_c = v->maximum_swath_height_c / 2.0; + if (v->bug_forcing_luma_and_chroma_request_to_same_size_fixed + == dcn_bw_yes) { + v->minimum_swath_height_y = v->maximum_swath_height_y; + } else { + v->minimum_swath_height_y = v->maximum_swath_height_y / 2.0; + } + } else { + v->minimum_swath_height_y = v->maximum_swath_height_y; + v->minimum_swath_height_c = v->maximum_swath_height_c; + } + } + if (v->source_scan[k] == dcn_bw_hor) { + v->swath_width = v->viewport_width[k] / v->dpp_per_plane[k]; + } else { + v->swath_width = v->viewport_height[k] / v->dpp_per_plane[k]; + } + v->swath_width_granularity_y = 256.0 / dcn_bw_ceil2(v->byte_per_pix_dety, 1.0) + / v->maximum_swath_height_y; + v->rounded_up_max_swath_size_bytes_y = (dcn_bw_ceil2( + v->swath_width - 1.0, + v->swath_width_granularity_y) + v->swath_width_granularity_y) + * v->byte_per_pix_dety * v->maximum_swath_height_y; + if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_10) { + v->rounded_up_max_swath_size_bytes_y = dcn_bw_ceil2( + v->rounded_up_max_swath_size_bytes_y, + 256.0) + 256; + } + if (v->maximum_swath_height_c > 0.0) { + v->swath_width_granularity_c = 256.0 / dcn_bw_ceil2(v->byte_per_pix_detc, 2.0) + / v->maximum_swath_height_c; + } + v->rounded_up_max_swath_size_bytes_c = (dcn_bw_ceil2( + v->swath_width / 2.0 - 1.0, + v->swath_width_granularity_c) + v->swath_width_granularity_c) + * v->byte_per_pix_detc * v->maximum_swath_height_c; + if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_10) { + v->rounded_up_max_swath_size_bytes_c = dcn_bw_ceil2( + v->rounded_up_max_swath_size_bytes_c, + 256.0) + 256; + } + if (v->rounded_up_max_swath_size_bytes_y + v->rounded_up_max_swath_size_bytes_c + <= v->det_buffer_size_in_kbyte * 1024.0 / 2.0) { + v->swath_height_y[k] = v->maximum_swath_height_y; + v->swath_height_c[k] = v->maximum_swath_height_c; + } else { + v->swath_height_y[k] = v->minimum_swath_height_y; + v->swath_height_c[k] = v->minimum_swath_height_c; + } + if (v->swath_height_c[k] == 0.0) { + v->det_buffer_size_y[k] = v->det_buffer_size_in_kbyte * 1024.0; + v->det_buffer_size_c[k] = 0.0; + } else if (v->swath_height_y[k] <= v->swath_height_c[k]) { + v->det_buffer_size_y[k] = v->det_buffer_size_in_kbyte * 1024.0 / 2.0; + v->det_buffer_size_c[k] = v->det_buffer_size_in_kbyte * 1024.0 / 2.0; + } else { + v->det_buffer_size_y[k] = v->det_buffer_size_in_kbyte * 1024.0 * 2.0 / 3.0; + v->det_buffer_size_c[k] = v->det_buffer_size_in_kbyte * 1024.0 / 3.0; + } + } +} +void dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performance_calculation( + struct dcn_bw_internal_vars *v) +{ + int k; + /*dispclk and dppclk calculation*/ + + v->dispclk_with_ramping = 0.0; + v->dispclk_without_ramping = 0.0; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->h_ratio[k] > 1.0) { + v->pscl_throughput[k] = dcn_bw_min2( + v->max_dchub_topscl_throughput, + v->max_pscl_tolb_throughput * v->h_ratio[k] + / dcn_bw_ceil2(v->htaps[k] / 6.0, 1.0)); + } else { + v->pscl_throughput[k] = dcn_bw_min2( + v->max_dchub_topscl_throughput, + v->max_pscl_tolb_throughput); + } + v->dppclk_using_single_dpp_luma = v->pixel_clock[k] + * dcn_bw_max3( + v->vtaps[k] / 6.0 * dcn_bw_min2(1.0, v->h_ratio[k]), + v->h_ratio[k] * v->v_ratio[k] + / v->pscl_throughput[k], + 1.0); + if ((v->source_pixel_format[k] != dcn_bw_yuv420_sub_8 + && v->source_pixel_format[k] != dcn_bw_yuv420_sub_10)) { + v->pscl_throughput_chroma[k] = 0.0; + v->dppclk_using_single_dpp = v->dppclk_using_single_dpp_luma; + } else { + if (v->h_ratio[k] > 1.0) { + v->pscl_throughput_chroma[k] = + dcn_bw_min2( + v->max_dchub_topscl_throughput, + v->max_pscl_tolb_throughput + * v->h_ratio[k] + / 2.0 + / dcn_bw_ceil2( + v->hta_pschroma[k] + / 6.0, + 1.0)); + } else { + v->pscl_throughput_chroma[k] = dcn_bw_min2( + v->max_dchub_topscl_throughput, + v->max_pscl_tolb_throughput); + } + v->dppclk_using_single_dpp_chroma = + v->pixel_clock[k] + * dcn_bw_max3( + v->vta_pschroma[k] / 6.0 + * dcn_bw_min2( + 1.0, + v->h_ratio[k] + / 2.0), + v->h_ratio[k] + * v->v_ratio[k] + / 4.0 + / v->pscl_throughput_chroma[k], + 1.0); + v->dppclk_using_single_dpp = dcn_bw_max2( + v->dppclk_using_single_dpp_luma, + v->dppclk_using_single_dpp_chroma); + } + if (v->odm_capable == dcn_bw_yes) { + v->dispclk_with_ramping = + dcn_bw_max2( + v->dispclk_with_ramping, + dcn_bw_max2( + v->dppclk_using_single_dpp + / v->dpp_per_plane[k] + * v->dispclk_dppclk_ratio, + v->pixel_clock[k] + / v->dpp_per_plane[k]) + * (1.0 + + v->downspreading + / 100.0) + * (1.0 + + v->dispclk_ramping_margin + / 100.0)); + v->dispclk_without_ramping = dcn_bw_max2( + v->dispclk_without_ramping, + dcn_bw_max2( + v->dppclk_using_single_dpp + / v->dpp_per_plane[k] + * v->dispclk_dppclk_ratio, + v->pixel_clock[k] / v->dpp_per_plane[k]) + * (1.0 + v->downspreading / 100.0)); + } else { + v->dispclk_with_ramping = + dcn_bw_max2( + v->dispclk_with_ramping, + dcn_bw_max2( + v->dppclk_using_single_dpp + / v->dpp_per_plane[k] + * v->dispclk_dppclk_ratio, + v->pixel_clock[k]) + * (1.0 + + v->downspreading + / 100.0) + * (1.0 + + v->dispclk_ramping_margin + / 100.0)); + v->dispclk_without_ramping = dcn_bw_max2( + v->dispclk_without_ramping, + dcn_bw_max2( + v->dppclk_using_single_dpp + / v->dpp_per_plane[k] + * v->dispclk_dppclk_ratio, + v->pixel_clock[k]) + * (1.0 + v->downspreading / 100.0)); + } + } + if (v->dispclk_without_ramping > v->max_dispclk[number_of_states]) { + v->dispclk = v->dispclk_without_ramping; + } else if (v->dispclk_with_ramping > v->max_dispclk[number_of_states]) { + v->dispclk = v->max_dispclk[number_of_states]; + } else { + v->dispclk = v->dispclk_with_ramping; + } + v->dppclk = v->dispclk / v->dispclk_dppclk_ratio; + /*urgent watermark*/ + + v->return_bandwidth_to_dcn = dcn_bw_min2( + v->return_bus_width * v->dcfclk, + v->fabric_and_dram_bandwidth * 1000.0 + * v->percent_of_ideal_drambw_received_after_urg_latency + / 100.0); + v->dcc_enabled_any_plane = dcn_bw_no; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->dcc_enable[k] == dcn_bw_yes) { + v->dcc_enabled_any_plane = dcn_bw_yes; + } + } + v->return_bw = v->return_bandwidth_to_dcn; + if (v->dcc_enabled_any_plane == dcn_bw_yes + && v->return_bandwidth_to_dcn > v->dcfclk * v->return_bus_width / 4.0) { + v->return_bw = + dcn_bw_min2( + v->return_bw, + v->return_bandwidth_to_dcn * 4.0 + * (1.0 + - v->urgent_latency + / ((v->rob_buffer_size_in_kbyte + - v->pixel_chunk_size_in_kbyte) + * 1024.0 + / (v->return_bandwidth_to_dcn + - v->dcfclk + * v->return_bus_width + / 4.0) + + v->urgent_latency))); + } + v->critical_compression = 2.0 * v->return_bus_width * v->dcfclk * v->urgent_latency + / (v->return_bandwidth_to_dcn * v->urgent_latency + + (v->rob_buffer_size_in_kbyte + - v->pixel_chunk_size_in_kbyte) * 1024.0); + if (v->dcc_enabled_any_plane == dcn_bw_yes && v->critical_compression > 1.0 + && v->critical_compression < 4.0) { + v->return_bw = + dcn_bw_min2( + v->return_bw, + dcn_bw_pow( + 4.0 * v->return_bandwidth_to_dcn + * (v->rob_buffer_size_in_kbyte + - v->pixel_chunk_size_in_kbyte) + * 1024.0 + * v->return_bus_width + * v->dcfclk + * v->urgent_latency + / (v->return_bandwidth_to_dcn + * v->urgent_latency + + (v->rob_buffer_size_in_kbyte + - v->pixel_chunk_size_in_kbyte) + * 1024.0), + 2)); + } + v->return_bandwidth_to_dcn = dcn_bw_min2( + v->return_bus_width * v->dcfclk, + v->fabric_and_dram_bandwidth * 1000.0); + if (v->dcc_enabled_any_plane == dcn_bw_yes + && v->return_bandwidth_to_dcn > v->dcfclk * v->return_bus_width / 4.0) { + v->return_bw = + dcn_bw_min2( + v->return_bw, + v->return_bandwidth_to_dcn * 4.0 + * (1.0 + - v->urgent_latency + / ((v->rob_buffer_size_in_kbyte + - v->pixel_chunk_size_in_kbyte) + * 1024.0 + / (v->return_bandwidth_to_dcn + - v->dcfclk + * v->return_bus_width + / 4.0) + + v->urgent_latency))); + } + v->critical_compression = 2.0 * v->return_bus_width * v->dcfclk * v->urgent_latency + / (v->return_bandwidth_to_dcn * v->urgent_latency + + (v->rob_buffer_size_in_kbyte + - v->pixel_chunk_size_in_kbyte) * 1024.0); + if (v->dcc_enabled_any_plane == dcn_bw_yes && v->critical_compression > 1.0 + && v->critical_compression < 4.0) { + v->return_bw = + dcn_bw_min2( + v->return_bw, + dcn_bw_pow( + 4.0 * v->return_bandwidth_to_dcn + * (v->rob_buffer_size_in_kbyte + - v->pixel_chunk_size_in_kbyte) + * 1024.0 + * v->return_bus_width + * v->dcfclk + * v->urgent_latency + / (v->return_bandwidth_to_dcn + * v->urgent_latency + + (v->rob_buffer_size_in_kbyte + - v->pixel_chunk_size_in_kbyte) + * 1024.0), + 2)); + } + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->source_scan[k] == dcn_bw_hor) { + v->swath_width_y[k] = v->viewport_width[k] / v->dpp_per_plane[k]; + } else { + v->swath_width_y[k] = v->viewport_height[k] / v->dpp_per_plane[k]; + } + } + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->source_pixel_format[k] == dcn_bw_rgb_sub_64) { + v->byte_per_pixel_dety[k] = 8.0; + v->byte_per_pixel_detc[k] = 0.0; + } else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_32) { + v->byte_per_pixel_dety[k] = 4.0; + v->byte_per_pixel_detc[k] = 0.0; + } else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_16) { + v->byte_per_pixel_dety[k] = 2.0; + v->byte_per_pixel_detc[k] = 0.0; + } else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_8) { + v->byte_per_pixel_dety[k] = 1.0; + v->byte_per_pixel_detc[k] = 2.0; + } else { + v->byte_per_pixel_dety[k] = 4.0f / 3; + v->byte_per_pixel_detc[k] = 8.0f / 3; + } + } + v->total_data_read_bandwidth = 0.0; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + v->read_bandwidth_plane_luma[k] = v->swath_width_y[k] * v->dpp_per_plane[k] + * dcn_bw_ceil2(v->byte_per_pixel_dety[k], 1.0) + / (v->htotal[k] / v->pixel_clock[k]) * v->v_ratio[k]; + v->read_bandwidth_plane_chroma[k] = v->swath_width_y[k] / 2.0 * v->dpp_per_plane[k] + * dcn_bw_ceil2(v->byte_per_pixel_detc[k], 2.0) + / (v->htotal[k] / v->pixel_clock[k]) * v->v_ratio[k] / 2.0; + v->total_data_read_bandwidth = v->total_data_read_bandwidth + + v->read_bandwidth_plane_luma[k] + + v->read_bandwidth_plane_chroma[k]; + } + v->total_active_dpp = 0.0; + v->total_dcc_active_dpp = 0.0; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + v->total_active_dpp = v->total_active_dpp + v->dpp_per_plane[k]; + if (v->dcc_enable[k] == dcn_bw_yes) { + v->total_dcc_active_dpp = v->total_dcc_active_dpp + v->dpp_per_plane[k]; + } + } + v->urgent_round_trip_and_out_of_order_latency = (v->round_trip_ping_latency_cycles + 32.0) + / v->dcfclk + + v->urgent_out_of_order_return_per_channel * v->number_of_channels + / v->return_bw; + v->last_pixel_of_line_extra_watermark = 0.0; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->v_ratio[k] <= 1.0) { + v->display_pipe_line_delivery_time_luma[k] = v->swath_width_y[k] + * v->dpp_per_plane[k] / v->h_ratio[k] / v->pixel_clock[k]; + } else { + v->display_pipe_line_delivery_time_luma[k] = v->swath_width_y[k] + / v->pscl_throughput[k] / v->dppclk; + } + v->data_fabric_line_delivery_time_luma = + v->swath_width_y[k] * v->swath_height_y[k] + * dcn_bw_ceil2(v->byte_per_pixel_dety[k], 1.0) + / (v->return_bw * v->read_bandwidth_plane_luma[k] + / v->dpp_per_plane[k] + / v->total_data_read_bandwidth); + v->last_pixel_of_line_extra_watermark = dcn_bw_max2( + v->last_pixel_of_line_extra_watermark, + v->data_fabric_line_delivery_time_luma + - v->display_pipe_line_delivery_time_luma[k]); + if (v->byte_per_pixel_detc[k] == 0.0) { + v->display_pipe_line_delivery_time_chroma[k] = 0.0; + } else { + if (v->v_ratio[k] / 2.0 <= 1.0) { + v->display_pipe_line_delivery_time_chroma[k] = v->swath_width_y[k] + / 2.0 * v->dpp_per_plane[k] / (v->h_ratio[k] / 2.0) + / v->pixel_clock[k]; + } else { + v->display_pipe_line_delivery_time_chroma[k] = v->swath_width_y[k] + / 2.0 / v->pscl_throughput_chroma[k] / v->dppclk; + } + v->data_fabric_line_delivery_time_chroma = v->swath_width_y[k] / 2.0 + * v->swath_height_c[k] + * dcn_bw_ceil2(v->byte_per_pixel_detc[k], 2.0) + / (v->return_bw * v->read_bandwidth_plane_chroma[k] + / v->dpp_per_plane[k] + / v->total_data_read_bandwidth); + v->last_pixel_of_line_extra_watermark = + dcn_bw_max2( + v->last_pixel_of_line_extra_watermark, + v->data_fabric_line_delivery_time_chroma + - v->display_pipe_line_delivery_time_chroma[k]); + } + } + v->urgent_extra_latency = v->urgent_round_trip_and_out_of_order_latency + + (v->total_active_dpp * v->pixel_chunk_size_in_kbyte + + v->total_dcc_active_dpp * v->meta_chunk_size) * 1024.0 + / v->return_bw; + if (v->pte_enable == dcn_bw_yes) { + v->urgent_extra_latency = v->urgent_extra_latency + + v->total_active_dpp * v->pte_chunk_size * 1024.0 / v->return_bw; + } + v->urgent_watermark = v->urgent_latency + v->last_pixel_of_line_extra_watermark + + v->urgent_extra_latency; + v->ptemeta_urgent_watermark = v->urgent_watermark + 2.0 * v->urgent_latency; + /*nb p-state/dram clock change watermark*/ + + v->dram_clock_change_watermark = v->dram_clock_change_latency + v->urgent_watermark; + v->total_active_writeback = 0.0; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->output[k] == dcn_bw_writeback) { + v->total_active_writeback = v->total_active_writeback + 1.0; + } + } + if (v->total_active_writeback <= 1.0) { + v->writeback_dram_clock_change_watermark = v->dram_clock_change_latency + + v->write_back_latency; + } else { + v->writeback_dram_clock_change_watermark = v->dram_clock_change_latency + + v->write_back_latency + + v->writeback_chunk_size * 1024.0 / 32.0 / v->socclk; + } + /*stutter efficiency*/ + + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + v->lines_in_dety[k] = v->det_buffer_size_y[k] / v->byte_per_pixel_dety[k] + / v->swath_width_y[k]; + v->lines_in_dety_rounded_down_to_swath[k] = dcn_bw_floor2( + v->lines_in_dety[k], + v->swath_height_y[k]); + v->full_det_buffering_time_y[k] = v->lines_in_dety_rounded_down_to_swath[k] + * (v->htotal[k] / v->pixel_clock[k]) / v->v_ratio[k]; + if (v->byte_per_pixel_detc[k] > 0.0) { + v->lines_in_detc[k] = v->det_buffer_size_c[k] / v->byte_per_pixel_detc[k] + / (v->swath_width_y[k] / 2.0); + v->lines_in_detc_rounded_down_to_swath[k] = dcn_bw_floor2( + v->lines_in_detc[k], + v->swath_height_c[k]); + v->full_det_buffering_time_c[k] = v->lines_in_detc_rounded_down_to_swath[k] + * (v->htotal[k] / v->pixel_clock[k]) + / (v->v_ratio[k] / 2.0); + } else { + v->lines_in_detc[k] = 0.0; + v->lines_in_detc_rounded_down_to_swath[k] = 0.0; + v->full_det_buffering_time_c[k] = 999999.0; + } + } + v->min_full_det_buffering_time = 999999.0; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->full_det_buffering_time_y[k] < v->min_full_det_buffering_time) { + v->min_full_det_buffering_time = v->full_det_buffering_time_y[k]; + v->frame_time_for_min_full_det_buffering_time = v->vtotal[k] * v->htotal[k] + / v->pixel_clock[k]; + } + if (v->full_det_buffering_time_c[k] < v->min_full_det_buffering_time) { + v->min_full_det_buffering_time = v->full_det_buffering_time_c[k]; + v->frame_time_for_min_full_det_buffering_time = v->vtotal[k] * v->htotal[k] + / v->pixel_clock[k]; + } + } + v->average_read_bandwidth_gbyte_per_second = 0.0; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->dcc_enable[k] == dcn_bw_yes) { + v->average_read_bandwidth_gbyte_per_second = + v->average_read_bandwidth_gbyte_per_second + + v->read_bandwidth_plane_luma[k] + / v->dcc_rate[k] / 1000.0 + + v->read_bandwidth_plane_chroma[k] + / v->dcc_rate[k] / 1000.0; + } else { + v->average_read_bandwidth_gbyte_per_second = + v->average_read_bandwidth_gbyte_per_second + + v->read_bandwidth_plane_luma[k] / 1000.0 + + v->read_bandwidth_plane_chroma[k] + / 1000.0; + } + if (v->dcc_enable[k] == dcn_bw_yes) { + v->average_read_bandwidth_gbyte_per_second = + v->average_read_bandwidth_gbyte_per_second + + v->read_bandwidth_plane_luma[k] / 1000.0 + / 256.0 + + v->read_bandwidth_plane_chroma[k] / 1000.0 + / 256.0; + } + if (v->pte_enable == dcn_bw_yes) { + v->average_read_bandwidth_gbyte_per_second = + v->average_read_bandwidth_gbyte_per_second + + v->read_bandwidth_plane_luma[k] / 1000.0 + / 512.0 + + v->read_bandwidth_plane_chroma[k] / 1000.0 + / 512.0; + } + } + v->part_of_burst_that_fits_in_rob = dcn_bw_min2( + v->min_full_det_buffering_time * v->total_data_read_bandwidth, + v->rob_buffer_size_in_kbyte * 1024.0 * v->total_data_read_bandwidth + / (v->average_read_bandwidth_gbyte_per_second * 1000.0)); + v->stutter_burst_time = v->part_of_burst_that_fits_in_rob + * (v->average_read_bandwidth_gbyte_per_second * 1000.0) + / v->total_data_read_bandwidth / v->return_bw + + (v->min_full_det_buffering_time * v->total_data_read_bandwidth + - v->part_of_burst_that_fits_in_rob) / (v->dcfclk * 64.0); + if (v->total_active_writeback == 0.0) { + v->stutter_efficiency_not_including_vblank = (1.0 + - (v->sr_exit_time + v->stutter_burst_time) + / v->min_full_det_buffering_time) * 100.0; + } else { + v->stutter_efficiency_not_including_vblank = 0.0; + } + v->smallest_vblank = 999999.0; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->synchronized_vblank == dcn_bw_yes || v->number_of_active_planes == 1) { + v->v_blank_time = (v->vtotal[k] - v->vactive[k]) * v->htotal[k] + / v->pixel_clock[k]; + } else { + v->v_blank_time = 0.0; + } + v->smallest_vblank = dcn_bw_min2(v->smallest_vblank, v->v_blank_time); + } + v->stutter_efficiency = (v->stutter_efficiency_not_including_vblank / 100.0 + * (v->frame_time_for_min_full_det_buffering_time - v->smallest_vblank) + + v->smallest_vblank) / v->frame_time_for_min_full_det_buffering_time + * 100.0; + /*dcfclk deep sleep*/ + + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->byte_per_pixel_detc[k] > 0.0) { + v->dcfclk_deep_sleep_per_plane[k] = + dcn_bw_max2( + 1.1 * v->swath_width_y[k] + * dcn_bw_ceil2( + v->byte_per_pixel_dety[k], + 1.0) / 32.0 + / v->display_pipe_line_delivery_time_luma[k], + 1.1 * v->swath_width_y[k] / 2.0 + * dcn_bw_ceil2( + v->byte_per_pixel_detc[k], + 2.0) / 32.0 + / v->display_pipe_line_delivery_time_chroma[k]); + } else { + v->dcfclk_deep_sleep_per_plane[k] = 1.1 * v->swath_width_y[k] + * dcn_bw_ceil2(v->byte_per_pixel_dety[k], 1.0) / 64.0 + / v->display_pipe_line_delivery_time_luma[k]; + } + v->dcfclk_deep_sleep_per_plane[k] = dcn_bw_max2( + v->dcfclk_deep_sleep_per_plane[k], + v->pixel_clock[k] / 16.0); + } + v->dcf_clk_deep_sleep = 8.0; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + v->dcf_clk_deep_sleep = dcn_bw_max2( + v->dcf_clk_deep_sleep, + v->dcfclk_deep_sleep_per_plane[k]); + } + /*stutter watermark*/ + + v->stutter_exit_watermark = v->sr_exit_time + v->last_pixel_of_line_extra_watermark + + v->urgent_extra_latency + 10.0 / v->dcf_clk_deep_sleep; + v->stutter_enter_plus_exit_watermark = v->sr_enter_plus_exit_time + + v->last_pixel_of_line_extra_watermark + v->urgent_extra_latency; + /*urgent latency supported*/ + + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + v->effective_det_plus_lb_lines_luma = + dcn_bw_floor2( + v->lines_in_dety[k] + + dcn_bw_min2( + v->lines_in_dety[k] + * v->dppclk + * v->byte_per_pixel_dety[k] + * v->pscl_throughput[k] + / (v->return_bw + / v->dpp_per_plane[k]), + v->effective_lb_latency_hiding_source_lines_luma), + v->swath_height_y[k]); + v->urgent_latency_support_us_luma = v->effective_det_plus_lb_lines_luma + * (v->htotal[k] / v->pixel_clock[k]) / v->v_ratio[k] + - v->effective_det_plus_lb_lines_luma * v->swath_width_y[k] + * v->byte_per_pixel_dety[k] + / (v->return_bw / v->dpp_per_plane[k]); + if (v->byte_per_pixel_detc[k] > 0.0) { + v->effective_det_plus_lb_lines_chroma = + dcn_bw_floor2( + v->lines_in_detc[k] + + dcn_bw_min2( + v->lines_in_detc[k] + * v->dppclk + * v->byte_per_pixel_detc[k] + * v->pscl_throughput_chroma[k] + / (v->return_bw + / v->dpp_per_plane[k]), + v->effective_lb_latency_hiding_source_lines_chroma), + v->swath_height_c[k]); + v->urgent_latency_support_us_chroma = v->effective_det_plus_lb_lines_chroma + * (v->htotal[k] / v->pixel_clock[k]) / (v->v_ratio[k] / 2.0) + - v->effective_det_plus_lb_lines_chroma + * (v->swath_width_y[k] / 2.0) + * v->byte_per_pixel_detc[k] + / (v->return_bw / v->dpp_per_plane[k]); + v->urgent_latency_support_us[k] = dcn_bw_min2( + v->urgent_latency_support_us_luma, + v->urgent_latency_support_us_chroma); + } else { + v->urgent_latency_support_us[k] = v->urgent_latency_support_us_luma; + } + } + v->min_urgent_latency_support_us = 999999.0; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + v->min_urgent_latency_support_us = dcn_bw_min2( + v->min_urgent_latency_support_us, + v->urgent_latency_support_us[k]); + } + /*non-urgent latency tolerance*/ + + v->non_urgent_latency_tolerance = v->min_urgent_latency_support_us - v->urgent_watermark; + /*prefetch*/ + + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if ((v->source_pixel_format[k] == dcn_bw_rgb_sub_64 + || v->source_pixel_format[k] == dcn_bw_rgb_sub_32 + || v->source_pixel_format[k] == dcn_bw_rgb_sub_16)) { + if (v->source_surface_mode[k] == dcn_bw_sw_linear) { + v->block_height256_bytes_y = 1.0; + } else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_64) { + v->block_height256_bytes_y = 4.0; + } else { + v->block_height256_bytes_y = 8.0; + } + v->block_height256_bytes_c = 0.0; + } else { + if (v->source_surface_mode[k] == dcn_bw_sw_linear) { + v->block_height256_bytes_y = 1.0; + v->block_height256_bytes_c = 1.0; + } else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_8) { + v->block_height256_bytes_y = 16.0; + v->block_height256_bytes_c = 8.0; + } else { + v->block_height256_bytes_y = 8.0; + v->block_height256_bytes_c = 8.0; + } + } + if (v->dcc_enable[k] == dcn_bw_yes) { + v->meta_request_width_y = 64.0 * 256.0 + / dcn_bw_ceil2(v->byte_per_pixel_dety[k], 1.0) + / (8.0 * v->block_height256_bytes_y); + v->meta_surf_width_y = dcn_bw_ceil2( + v->swath_width_y[k] - 1.0, + v->meta_request_width_y) + v->meta_request_width_y; + v->meta_surf_height_y = dcn_bw_ceil2( + v->viewport_height[k] - 1.0, + 8.0 * v->block_height256_bytes_y) + + 8.0 * v->block_height256_bytes_y; + if (v->pte_enable == dcn_bw_yes) { + v->meta_pte_bytes_frame_y = + (dcn_bw_ceil2( + (v->meta_surf_width_y + * v->meta_surf_height_y + * dcn_bw_ceil2( + v->byte_per_pixel_dety[k], + 1.0) + / 256.0 - 4096.0) + / 8.0 / 4096.0, + 1.0) + 1) * 64.0; + } else { + v->meta_pte_bytes_frame_y = 0.0; + } + if (v->source_scan[k] == dcn_bw_hor) { + v->meta_row_byte_y = v->meta_surf_width_y * 8.0 + * v->block_height256_bytes_y + * dcn_bw_ceil2(v->byte_per_pixel_dety[k], 1.0) / 256.0; + } else { + v->meta_row_byte_y = v->meta_surf_height_y * v->meta_request_width_y + * dcn_bw_ceil2(v->byte_per_pixel_dety[k], 1.0) / 256.0; + } + } else { + v->meta_pte_bytes_frame_y = 0.0; + v->meta_row_byte_y = 0.0; + } + if (v->pte_enable == dcn_bw_yes) { + if (v->source_surface_mode[k] == dcn_bw_sw_linear) { + v->macro_tile_size_byte_y = 256.0; + v->macro_tile_height_y = 1.0; + } else if (v->source_surface_mode[k] == dcn_bw_sw_4_kb_s + || v->source_surface_mode[k] == dcn_bw_sw_4_kb_s_x + || v->source_surface_mode[k] == dcn_bw_sw_4_kb_d + || v->source_surface_mode[k] == dcn_bw_sw_4_kb_d_x) { + v->macro_tile_size_byte_y = 4096.0; + v->macro_tile_height_y = 4.0 * v->block_height256_bytes_y; + } else if (v->source_surface_mode[k] == dcn_bw_sw_64_kb_s + || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_t + || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_x + || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d + || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_t + || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_x) { + v->macro_tile_size_byte_y = 64.0 * 1024; + v->macro_tile_height_y = 16.0 * v->block_height256_bytes_y; + } else { + v->macro_tile_size_byte_y = 256.0 * 1024; + v->macro_tile_height_y = 32.0 * v->block_height256_bytes_y; + } + if (v->macro_tile_size_byte_y <= 65536.0) { + v->pixel_pte_req_height_y = v->macro_tile_height_y; + } else { + v->pixel_pte_req_height_y = 16.0 * v->block_height256_bytes_y; + } + v->pixel_pte_req_width_y = 4096.0 / dcn_bw_ceil2(v->byte_per_pixel_dety[k], 1.0) + / v->pixel_pte_req_height_y * 8; + if (v->source_surface_mode[k] == dcn_bw_sw_linear) { + v->pixel_pte_bytes_per_row_y = + 64.0 + * (dcn_bw_ceil2( + (v->swath_width_y[k] + * dcn_bw_min2( + 128.0, + dcn_bw_pow( + 2.0, + dcn_bw_floor2( + dcn_bw_log( + v->pte_buffer_size_in_requests + * v->pixel_pte_req_width_y + / v->swath_width_y[k], + 2.0), + 1.0))) + - 1.0) + / v->pixel_pte_req_width_y, + 1.0) + 1); + } else if (v->source_scan[k] == dcn_bw_hor) { + v->pixel_pte_bytes_per_row_y = + 64.0 + * (dcn_bw_ceil2( + (v->swath_width_y[k] + - 1.0) + / v->pixel_pte_req_width_y, + 1.0) + 1); + } else { + v->pixel_pte_bytes_per_row_y = + 64.0 + * (dcn_bw_ceil2( + (v->viewport_height[k] + - 1.0) + / v->pixel_pte_req_height_y, + 1.0) + 1); + } + } else { + v->pixel_pte_bytes_per_row_y = 0.0; + } + if ((v->source_pixel_format[k] != dcn_bw_rgb_sub_64 + && v->source_pixel_format[k] != dcn_bw_rgb_sub_32 + && v->source_pixel_format[k] != dcn_bw_rgb_sub_16)) { + if (v->dcc_enable[k] == dcn_bw_yes) { + v->meta_request_width_c = 64.0 * 256.0 + / dcn_bw_ceil2(v->byte_per_pixel_detc[k], 2.0) + / (8.0 * v->block_height256_bytes_c); + v->meta_surf_width_c = dcn_bw_ceil2( + v->swath_width_y[k] / 2.0 - 1.0, + v->meta_request_width_c) + v->meta_request_width_c; + v->meta_surf_height_c = dcn_bw_ceil2( + v->viewport_height[k] / 2.0 - 1.0, + 8.0 * v->block_height256_bytes_c) + + 8.0 * v->block_height256_bytes_c; + if (v->pte_enable == dcn_bw_yes) { + v->meta_pte_bytes_frame_c = + (dcn_bw_ceil2( + (v->meta_surf_width_c + * v->meta_surf_height_c + * dcn_bw_ceil2( + v->byte_per_pixel_detc[k], + 2.0) + / 256.0 + - 4096.0) + / 8.0 + / 4096.0, + 1.0) + 1) * 64.0; + } else { + v->meta_pte_bytes_frame_c = 0.0; + } + if (v->source_scan[k] == dcn_bw_hor) { + v->meta_row_byte_c = v->meta_surf_width_c * 8.0 + * v->block_height256_bytes_c + * dcn_bw_ceil2(v->byte_per_pixel_detc[k], 2.0) + / 256.0; + } else { + v->meta_row_byte_c = v->meta_surf_height_c + * v->meta_request_width_c + * dcn_bw_ceil2(v->byte_per_pixel_detc[k], 2.0) + / 256.0; + } + } else { + v->meta_pte_bytes_frame_c = 0.0; + v->meta_row_byte_c = 0.0; + } + if (v->pte_enable == dcn_bw_yes) { + if (v->source_surface_mode[k] == dcn_bw_sw_linear) { + v->macro_tile_size_bytes_c = 256.0; + v->macro_tile_height_c = 1.0; + } else if (v->source_surface_mode[k] == dcn_bw_sw_4_kb_s + || v->source_surface_mode[k] == dcn_bw_sw_4_kb_s_x + || v->source_surface_mode[k] == dcn_bw_sw_4_kb_d + || v->source_surface_mode[k] + == dcn_bw_sw_4_kb_d_x) { + v->macro_tile_size_bytes_c = 4096.0; + v->macro_tile_height_c = 4.0 * v->block_height256_bytes_c; + } else if (v->source_surface_mode[k] == dcn_bw_sw_64_kb_s + || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_t + || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_x + || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d + || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_t + || v->source_surface_mode[k] + == dcn_bw_sw_64_kb_d_x) { + v->macro_tile_size_bytes_c = 64.0 * 1024; + v->macro_tile_height_c = 16.0 * v->block_height256_bytes_c; + } else { + v->macro_tile_size_bytes_c = 256.0 * 1024; + v->macro_tile_height_c = 32.0 * v->block_height256_bytes_c; + } + if (v->macro_tile_size_bytes_c <= 65536.0) { + v->pixel_pte_req_height_c = v->macro_tile_height_c; + } else { + v->pixel_pte_req_height_c = 16.0 + * v->block_height256_bytes_c; + } + v->pixel_pte_req_width_c = 4096.0 + / dcn_bw_ceil2(v->byte_per_pixel_detc[k], 2.0) + / v->pixel_pte_req_height_c * 8; + if (v->source_surface_mode[k] == dcn_bw_sw_linear) { + v->pixel_pte_bytes_per_row_c = + 64.0 + * (dcn_bw_ceil2( + (v->swath_width_y[k] + / 2.0 + * dcn_bw_min2( + 128.0, + dcn_bw_pow( + 2.0, + dcn_bw_floor2( + dcn_bw_log( + v->pte_buffer_size_in_requests + * v->pixel_pte_req_width_c + / (v->swath_width_y[k] + / 2.0), + 2.0), + 1.0))) + - 1.0) + / v->pixel_pte_req_width_c, + 1.0) + 1); + } else if (v->source_scan[k] == dcn_bw_hor) { + v->pixel_pte_bytes_per_row_c = + 64.0 + * (dcn_bw_ceil2( + (v->swath_width_y[k] + / 2.0 + - 1.0) + / v->pixel_pte_req_width_c, + 1.0) + 1); + } else { + v->pixel_pte_bytes_per_row_c = + 64.0 + * (dcn_bw_ceil2( + (v->viewport_height[k] + / 2.0 + - 1.0) + / v->pixel_pte_req_height_c, + 1.0) + 1); + } + } else { + v->pixel_pte_bytes_per_row_c = 0.0; + } + } else { + v->pixel_pte_bytes_per_row_c = 0.0; + v->meta_pte_bytes_frame_c = 0.0; + v->meta_row_byte_c = 0.0; + } + v->pixel_pte_bytes_per_row[k] = v->pixel_pte_bytes_per_row_y + + v->pixel_pte_bytes_per_row_c; + v->meta_pte_bytes_frame[k] = v->meta_pte_bytes_frame_y + v->meta_pte_bytes_frame_c; + v->meta_row_byte[k] = v->meta_row_byte_y + v->meta_row_byte_c; + v->v_init_pre_fill_y[k] = dcn_bw_floor2( + (v->v_ratio[k] + v->vtaps[k] + 1.0 + + v->interlace_output[k] * 0.5 * v->v_ratio[k]) + / 2.0, + 1.0); + v->max_num_swath_y[k] = dcn_bw_ceil2( + (v->v_init_pre_fill_y[k] - 1.0) / v->swath_height_y[k], + 1.0) + 1; + if (v->v_init_pre_fill_y[k] > 1.0) { + v->max_partial_swath_y = dcn_bw_mod( + (v->v_init_pre_fill_y[k] - 2.0), + v->swath_height_y[k]); + } else { + v->max_partial_swath_y = dcn_bw_mod( + (v->v_init_pre_fill_y[k] + v->swath_height_y[k] - 2.0), + v->swath_height_y[k]); + } + v->max_partial_swath_y = dcn_bw_max2(1.0, v->max_partial_swath_y); + v->prefetch_source_lines_y[k] = v->max_num_swath_y[k] * v->swath_height_y[k] + + v->max_partial_swath_y; + if ((v->source_pixel_format[k] != dcn_bw_rgb_sub_64 + && v->source_pixel_format[k] != dcn_bw_rgb_sub_32 + && v->source_pixel_format[k] != dcn_bw_rgb_sub_16)) { + v->v_init_pre_fill_c[k] = dcn_bw_floor2( + (v->v_ratio[k] / 2.0 + v->vtaps[k] + 1.0 + + v->interlace_output[k] * 0.5 + * v->v_ratio[k] / 2.0) + / 2.0, + 1.0); + v->max_num_swath_c[k] = dcn_bw_ceil2( + (v->v_init_pre_fill_c[k] - 1.0) / v->swath_height_c[k], + 1.0) + 1; + if (v->v_init_pre_fill_c[k] > 1.0) { + v->max_partial_swath_c = dcn_bw_mod( + (v->v_init_pre_fill_c[k] - 2.0), + v->swath_height_c[k]); + } else { + v->max_partial_swath_c = dcn_bw_mod( + (v->v_init_pre_fill_c[k] + v->swath_height_c[k] + - 2.0), + v->swath_height_c[k]); + } + v->max_partial_swath_c = dcn_bw_max2(1.0, v->max_partial_swath_c); + } else { + v->max_num_swath_c[k] = 0.0; + v->max_partial_swath_c = 0.0; + } + v->prefetch_source_lines_c[k] = v->max_num_swath_c[k] * v->swath_height_c[k] + + v->max_partial_swath_c; + } + v->t_calc = 24.0 / v->dcf_clk_deep_sleep; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one + == dcn_bw_yes) { + v->max_vstartup_lines[k] = v->vtotal[k] - v->vactive[k] - 1.0; + } else { + v->max_vstartup_lines[k] = v->v_sync_plus_back_porch[k] - 1.0; + } + } + v->next_prefetch_mode = 0.0; + do { + v->v_startup_lines = 13.0; + do { + v->planes_with_room_to_increase_vstartup_prefetch_bw_less_than_active_bw = + dcn_bw_yes; + v->planes_with_room_to_increase_vstartup_vratio_prefetch_more_than4 = + dcn_bw_no; + v->planes_with_room_to_increase_vstartup_destination_line_times_for_prefetch_less_than2 = + dcn_bw_no; + v->v_ratio_prefetch_more_than4 = dcn_bw_no; + v->destination_line_times_for_prefetch_less_than2 = dcn_bw_no; + v->prefetch_mode = v->next_prefetch_mode; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + v->dstx_after_scaler = 90.0 * v->pixel_clock[k] / v->dppclk + + 42.0 * v->pixel_clock[k] / v->dispclk; + if (v->dpp_per_plane[k] > 1.0) { + v->dstx_after_scaler = v->dstx_after_scaler + + v->scaler_rec_out_width[k] / 2.0; + } + if (v->output_format[k] == dcn_bw_420) { + v->dsty_after_scaler = 1.0; + } else { + v->dsty_after_scaler = 0.0; + } + v->v_update_offset_pix = dcn_bw_ceil2(v->htotal[k] / 4.0, 1.0); + v->total_repeater_delay_time = v->max_inter_dcn_tile_repeaters + * (2.0 / v->dppclk + 3.0 / v->dispclk); + v->v_update_width_pix = (14.0 / v->dcf_clk_deep_sleep + + 12.0 / v->dppclk + v->total_repeater_delay_time) + * v->pixel_clock[k]; + v->v_ready_offset_pix = dcn_bw_max2( + 150.0 / v->dppclk, + v->total_repeater_delay_time + + 20.0 / v->dcf_clk_deep_sleep + + 10.0 / v->dppclk) + * v->pixel_clock[k]; + v->t_setup = (v->v_update_offset_pix + v->v_update_width_pix + + v->v_ready_offset_pix) / v->pixel_clock[k]; + v->v_startup[k] = dcn_bw_min2( + v->v_startup_lines, + v->max_vstartup_lines[k]); + if (v->prefetch_mode == 0.0) { + v->t_wait = dcn_bw_max3( + v->dram_clock_change_latency + + v->urgent_latency, + v->sr_enter_plus_exit_time, + v->urgent_latency); + } else if (v->prefetch_mode == 1.0) { + v->t_wait = dcn_bw_max2( + v->sr_enter_plus_exit_time, + v->urgent_latency); + } else { + v->t_wait = v->urgent_latency; + } + v->destination_lines_for_prefetch[k] = + dcn_bw_floor2( + 4.0 + * (v->v_startup[k] + - v->t_wait + / (v->htotal[k] + / v->pixel_clock[k]) + - (v->t_calc + + v->t_setup) + / (v->htotal[k] + / v->pixel_clock[k]) + - (v->dsty_after_scaler + + v->dstx_after_scaler + / v->htotal[k]) + + 0.125), + 1.0) / 4; + if (v->destination_lines_for_prefetch[k] > 0.0) { + v->prefetch_bandwidth[k] = + (v->meta_pte_bytes_frame[k] + + 2.0 * v->meta_row_byte[k] + + 2.0 + * v->pixel_pte_bytes_per_row[k] + + v->prefetch_source_lines_y[k] + * v->swath_width_y[k] + * dcn_bw_ceil2( + v->byte_per_pixel_dety[k], + 1.0) + + v->prefetch_source_lines_c[k] + * v->swath_width_y[k] + / 2.0 + * dcn_bw_ceil2( + v->byte_per_pixel_detc[k], + 2.0)) + / (v->destination_lines_for_prefetch[k] + * v->htotal[k] + / v->pixel_clock[k]); + } else { + v->prefetch_bandwidth[k] = 999999.0; + } + } + v->bandwidth_available_for_immediate_flip = v->return_bw; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + v->bandwidth_available_for_immediate_flip = + v->bandwidth_available_for_immediate_flip + - dcn_bw_max2( + v->read_bandwidth_plane_luma[k] + + v->read_bandwidth_plane_chroma[k], + v->prefetch_bandwidth[k]); + } + v->tot_immediate_flip_bytes = 0.0; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->immediate_flip_supported == dcn_bw_yes + && (v->source_pixel_format[k] != dcn_bw_yuv420_sub_8 + && v->source_pixel_format[k] + != dcn_bw_yuv420_sub_10)) { + v->tot_immediate_flip_bytes = v->tot_immediate_flip_bytes + + v->meta_pte_bytes_frame[k] + + v->meta_row_byte[k] + + v->pixel_pte_bytes_per_row[k]; + } + } + v->max_rd_bandwidth = 0.0; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->pte_enable == dcn_bw_yes && v->dcc_enable[k] == dcn_bw_yes) { + if (v->immediate_flip_supported == dcn_bw_yes + && (v->source_pixel_format[k] + != dcn_bw_yuv420_sub_8 + && v->source_pixel_format[k] + != dcn_bw_yuv420_sub_10)) { + v->time_for_fetching_meta_pte = + dcn_bw_max5( + v->meta_pte_bytes_frame[k] + / v->prefetch_bandwidth[k], + v->meta_pte_bytes_frame[k] + * v->tot_immediate_flip_bytes + / (v->bandwidth_available_for_immediate_flip + * (v->meta_pte_bytes_frame[k] + + v->meta_row_byte[k] + + v->pixel_pte_bytes_per_row[k])), + v->urgent_extra_latency, + v->urgent_latency, + v->htotal[k] + / v->pixel_clock[k] + / 4.0); + } else { + v->time_for_fetching_meta_pte = + dcn_bw_max3( + v->meta_pte_bytes_frame[k] + / v->prefetch_bandwidth[k], + v->urgent_extra_latency, + v->htotal[k] + / v->pixel_clock[k] + / 4.0); + } + } else { + v->time_for_fetching_meta_pte = v->htotal[k] + / v->pixel_clock[k] / 4.0; + } + v->destination_lines_to_request_vm_inv_blank[k] = + dcn_bw_floor2( + 4.0 + * (v->time_for_fetching_meta_pte + / (v->htotal[k] + / v->pixel_clock[k]) + + 0.125), + 1.0) / 4; + if ((v->pte_enable == dcn_bw_yes || v->dcc_enable[k] == dcn_bw_yes)) { + if (v->immediate_flip_supported == dcn_bw_yes + && (v->source_pixel_format[k] + != dcn_bw_yuv420_sub_8 + && v->source_pixel_format[k] + != dcn_bw_yuv420_sub_10)) { + v->time_for_fetching_row_in_vblank = + dcn_bw_max5( + (v->meta_row_byte[k] + + v->pixel_pte_bytes_per_row[k]) + / v->prefetch_bandwidth[k], + (v->meta_row_byte[k] + + v->pixel_pte_bytes_per_row[k]) + * v->tot_immediate_flip_bytes + / (v->bandwidth_available_for_immediate_flip + * (v->meta_pte_bytes_frame[k] + + v->meta_row_byte[k] + + v->pixel_pte_bytes_per_row[k])), + v->urgent_extra_latency, + 2.0 + * v->urgent_latency, + v->htotal[k] + / v->pixel_clock[k] + - v->time_for_fetching_meta_pte); + } else { + v->time_for_fetching_row_in_vblank = + dcn_bw_max3( + (v->meta_row_byte[k] + + v->pixel_pte_bytes_per_row[k]) + / v->prefetch_bandwidth[k], + v->urgent_extra_latency, + v->htotal[k] + / v->pixel_clock[k] + - v->time_for_fetching_meta_pte); + } + } else { + v->time_for_fetching_row_in_vblank = + dcn_bw_max2( + v->urgent_extra_latency + - v->time_for_fetching_meta_pte, + v->htotal[k] + / v->pixel_clock[k] + - v->time_for_fetching_meta_pte); + } + v->destination_lines_to_request_row_in_vblank[k] = + dcn_bw_floor2( + 4.0 + * (v->time_for_fetching_row_in_vblank + / (v->htotal[k] + / v->pixel_clock[k]) + + 0.125), + 1.0) / 4; + v->lines_to_request_prefetch_pixel_data = + v->destination_lines_for_prefetch[k] + - v->destination_lines_to_request_vm_inv_blank[k] + - v->destination_lines_to_request_row_in_vblank[k]; + if (v->lines_to_request_prefetch_pixel_data > 0.0) { + v->v_ratio_prefetch_y[k] = v->prefetch_source_lines_y[k] + / v->lines_to_request_prefetch_pixel_data; + if ((v->swath_height_y[k] > 4.0)) { + if (v->lines_to_request_prefetch_pixel_data + > (v->v_init_pre_fill_y[k] - 3.0) + / 2.0) { + v->v_ratio_prefetch_y[k] = + dcn_bw_max2( + v->v_ratio_prefetch_y[k], + v->max_num_swath_y[k] + * v->swath_height_y[k] + / (v->lines_to_request_prefetch_pixel_data + - (v->v_init_pre_fill_y[k] + - 3.0) + / 2.0)); + } else { + v->v_ratio_prefetch_y[k] = 999999.0; + } + } + } else { + v->v_ratio_prefetch_y[k] = 999999.0; + } + v->v_ratio_prefetch_y[k] = dcn_bw_max2(v->v_ratio_prefetch_y[k], 1.0); + if (v->lines_to_request_prefetch_pixel_data > 0.0) { + v->v_ratio_prefetch_c[k] = v->prefetch_source_lines_c[k] + / v->lines_to_request_prefetch_pixel_data; + if ((v->swath_height_c[k] > 4.0)) { + if (v->lines_to_request_prefetch_pixel_data + > (v->v_init_pre_fill_c[k] - 3.0) + / 2.0) { + v->v_ratio_prefetch_c[k] = + dcn_bw_max2( + v->v_ratio_prefetch_c[k], + v->max_num_swath_c[k] + * v->swath_height_c[k] + / (v->lines_to_request_prefetch_pixel_data + - (v->v_init_pre_fill_c[k] + - 3.0) + / 2.0)); + } else { + v->v_ratio_prefetch_c[k] = 999999.0; + } + } + } else { + v->v_ratio_prefetch_c[k] = 999999.0; + } + v->v_ratio_prefetch_c[k] = dcn_bw_max2(v->v_ratio_prefetch_c[k], 1.0); + if (v->lines_to_request_prefetch_pixel_data > 0.0) { + v->required_prefetch_pix_data_bw = + v->dpp_per_plane[k] + * (v->prefetch_source_lines_y[k] + / v->lines_to_request_prefetch_pixel_data + * dcn_bw_ceil2( + v->byte_per_pixel_dety[k], + 1.0) + + v->prefetch_source_lines_c[k] + / v->lines_to_request_prefetch_pixel_data + * dcn_bw_ceil2( + v->byte_per_pixel_detc[k], + 2.0) + / 2.0) + * v->swath_width_y[k] + / (v->htotal[k] + / v->pixel_clock[k]); + } else { + v->required_prefetch_pix_data_bw = 999999.0; + } + v->max_rd_bandwidth = + v->max_rd_bandwidth + + dcn_bw_max2( + v->read_bandwidth_plane_luma[k] + + v->read_bandwidth_plane_chroma[k], + v->required_prefetch_pix_data_bw); + if (v->immediate_flip_supported == dcn_bw_yes + && (v->source_pixel_format[k] != dcn_bw_yuv420_sub_8 + && v->source_pixel_format[k] + != dcn_bw_yuv420_sub_10)) { + v->max_rd_bandwidth = + v->max_rd_bandwidth + + dcn_bw_max2( + v->meta_pte_bytes_frame[k] + / (v->destination_lines_to_request_vm_inv_blank[k] + * v->htotal[k] + / v->pixel_clock[k]), + (v->meta_row_byte[k] + + v->pixel_pte_bytes_per_row[k]) + / (v->destination_lines_to_request_row_in_vblank[k] + * v->htotal[k] + / v->pixel_clock[k])); + } + if (v->v_ratio_prefetch_y[k] > 4.0 + || v->v_ratio_prefetch_c[k] > 4.0) { + v->v_ratio_prefetch_more_than4 = dcn_bw_yes; + } + if (v->destination_lines_for_prefetch[k] < 2.0) { + v->destination_line_times_for_prefetch_less_than2 = + dcn_bw_yes; + } + if (v->max_vstartup_lines[k] > v->v_startup_lines) { + if (v->required_prefetch_pix_data_bw + > (v->read_bandwidth_plane_luma[k] + + v->read_bandwidth_plane_chroma[k])) { + v->planes_with_room_to_increase_vstartup_prefetch_bw_less_than_active_bw = + dcn_bw_no; + } + if (v->v_ratio_prefetch_y[k] > 4.0 + || v->v_ratio_prefetch_c[k] > 4.0) { + v->planes_with_room_to_increase_vstartup_vratio_prefetch_more_than4 = + dcn_bw_yes; + } + if (v->destination_lines_for_prefetch[k] < 2.0) { + v->planes_with_room_to_increase_vstartup_destination_line_times_for_prefetch_less_than2 = + dcn_bw_yes; + } + } + } + if (v->max_rd_bandwidth <= v->return_bw + && v->v_ratio_prefetch_more_than4 == dcn_bw_no + && v->destination_line_times_for_prefetch_less_than2 + == dcn_bw_no) { + v->prefetch_mode_supported = dcn_bw_yes; + } else { + v->prefetch_mode_supported = dcn_bw_no; + } + v->v_startup_lines = v->v_startup_lines + 1.0; + } while (!(v->prefetch_mode_supported == dcn_bw_yes + || (v->planes_with_room_to_increase_vstartup_prefetch_bw_less_than_active_bw + == dcn_bw_yes + && v->planes_with_room_to_increase_vstartup_vratio_prefetch_more_than4 + == dcn_bw_no + && v->planes_with_room_to_increase_vstartup_destination_line_times_for_prefetch_less_than2 + == dcn_bw_no))); + v->next_prefetch_mode = v->next_prefetch_mode + 1.0; + } while (!(v->prefetch_mode_supported == dcn_bw_yes || v->prefetch_mode == 2.0)); + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->v_ratio_prefetch_y[k] <= 1.0) { + v->display_pipe_line_delivery_time_luma_prefetch[k] = v->swath_width_y[k] + * v->dpp_per_plane[k] / v->h_ratio[k] / v->pixel_clock[k]; + } else { + v->display_pipe_line_delivery_time_luma_prefetch[k] = v->swath_width_y[k] + / v->pscl_throughput[k] / v->dppclk; + } + if (v->byte_per_pixel_detc[k] == 0.0) { + v->display_pipe_line_delivery_time_chroma_prefetch[k] = 0.0; + } else { + if (v->v_ratio_prefetch_c[k] <= 1.0) { + v->display_pipe_line_delivery_time_chroma_prefetch[k] = + v->swath_width_y[k] * v->dpp_per_plane[k] + / v->h_ratio[k] / v->pixel_clock[k]; + } else { + v->display_pipe_line_delivery_time_chroma_prefetch[k] = + v->swath_width_y[k] / v->pscl_throughput[k] + / v->dppclk; + } + } + } + /*min ttuv_blank*/ + + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->prefetch_mode == 0.0) { + v->allow_dram_clock_change_during_vblank[k] = dcn_bw_yes; + v->allow_dram_self_refresh_during_vblank[k] = dcn_bw_yes; + v->min_ttuv_blank[k] = v->t_calc + + dcn_bw_max3( + v->dram_clock_change_watermark, + v->stutter_enter_plus_exit_watermark, + v->urgent_watermark); + } else if (v->prefetch_mode == 1.0) { + v->allow_dram_clock_change_during_vblank[k] = dcn_bw_no; + v->allow_dram_self_refresh_during_vblank[k] = dcn_bw_yes; + v->min_ttuv_blank[k] = v->t_calc + + dcn_bw_max2( + v->stutter_enter_plus_exit_watermark, + v->urgent_watermark); + } else { + v->allow_dram_clock_change_during_vblank[k] = dcn_bw_no; + v->allow_dram_self_refresh_during_vblank[k] = dcn_bw_no; + v->min_ttuv_blank[k] = v->t_calc + v->urgent_watermark; + } + } + /*nb p-state/dram clock change support*/ + + v->active_dp_ps = 0.0; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + v->active_dp_ps = v->active_dp_ps + v->dpp_per_plane[k]; + } + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + v->lb_latency_hiding_source_lines_y = + dcn_bw_min2( + v->max_line_buffer_lines, + dcn_bw_floor2( + v->line_buffer_size + / v->lb_bit_per_pixel[k] + / (v->swath_width_y[k] + / dcn_bw_max2( + v->h_ratio[k], + 1.0)), + 1.0)) - (v->vtaps[k] - 1.0); + v->lb_latency_hiding_source_lines_c = + dcn_bw_min2( + v->max_line_buffer_lines, + dcn_bw_floor2( + v->line_buffer_size + / v->lb_bit_per_pixel[k] + / (v->swath_width_y[k] + / 2.0 + / dcn_bw_max2( + v->h_ratio[k] + / 2.0, + 1.0)), + 1.0)) - (v->vta_pschroma[k] - 1.0); + v->effective_lb_latency_hiding_y = v->lb_latency_hiding_source_lines_y + / v->v_ratio[k] * (v->htotal[k] / v->pixel_clock[k]); + v->effective_lb_latency_hiding_c = v->lb_latency_hiding_source_lines_c + / (v->v_ratio[k] / 2.0) * (v->htotal[k] / v->pixel_clock[k]); + if (v->swath_width_y[k] > 2.0 * v->dpp_output_buffer_pixels) { + v->dpp_output_buffer_lines_y = v->dpp_output_buffer_pixels + / v->swath_width_y[k]; + } else if (v->swath_width_y[k] > v->dpp_output_buffer_pixels) { + v->dpp_output_buffer_lines_y = 0.5; + } else { + v->dpp_output_buffer_lines_y = 1.0; + } + if (v->swath_width_y[k] / 2.0 > 2.0 * v->dpp_output_buffer_pixels) { + v->dpp_output_buffer_lines_c = v->dpp_output_buffer_pixels + / (v->swath_width_y[k] / 2.0); + } else if (v->swath_width_y[k] / 2.0 > v->dpp_output_buffer_pixels) { + v->dpp_output_buffer_lines_c = 0.5; + } else { + v->dpp_output_buffer_lines_c = 1.0; + } + v->dppopp_buffering_y = (v->htotal[k] / v->pixel_clock[k]) + * (v->dpp_output_buffer_lines_y + v->opp_output_buffer_lines); + v->max_det_buffering_time_y = v->full_det_buffering_time_y[k] + + (v->lines_in_dety[k] - v->lines_in_dety_rounded_down_to_swath[k]) + / v->swath_height_y[k] + * (v->htotal[k] / v->pixel_clock[k]); + v->active_dram_clock_change_latency_margin_y = v->dppopp_buffering_y + + v->effective_lb_latency_hiding_y + v->max_det_buffering_time_y + - v->dram_clock_change_watermark; + if (v->active_dp_ps > 1.0) { + v->active_dram_clock_change_latency_margin_y = + v->active_dram_clock_change_latency_margin_y + - (1.0 - 1.0 / (v->active_dp_ps - 1.0)) + * v->swath_height_y[k] + * (v->htotal[k] + / v->pixel_clock[k]); + } + if (v->byte_per_pixel_detc[k] > 0.0) { + v->dppopp_buffering_c = + (v->htotal[k] / v->pixel_clock[k]) + * (v->dpp_output_buffer_lines_c + + v->opp_output_buffer_lines); + v->max_det_buffering_time_c = v->full_det_buffering_time_c[k] + + (v->lines_in_detc[k] + - v->lines_in_detc_rounded_down_to_swath[k]) + / v->swath_height_c[k] + * (v->htotal[k] / v->pixel_clock[k]); + v->active_dram_clock_change_latency_margin_c = v->dppopp_buffering_c + + v->effective_lb_latency_hiding_c + + v->max_det_buffering_time_c + - v->dram_clock_change_watermark; + if (v->active_dp_ps > 1.0) { + v->active_dram_clock_change_latency_margin_c = + v->active_dram_clock_change_latency_margin_c + - (1.0 + - 1.0 + / (v->active_dp_ps + - 1.0)) + * v->swath_height_c[k] + * (v->htotal[k] + / v->pixel_clock[k]); + } + v->active_dram_clock_change_latency_margin[k] = dcn_bw_min2( + v->active_dram_clock_change_latency_margin_y, + v->active_dram_clock_change_latency_margin_c); + } else { + v->active_dram_clock_change_latency_margin[k] = + v->active_dram_clock_change_latency_margin_y; + } + if (v->output_format[k] == dcn_bw_444) { + v->writeback_dram_clock_change_latency_margin = + (v->writeback_luma_buffer_size + + v->writeback_chroma_buffer_size) * 1024.0 + / (v->scaler_rec_out_width[k] + / (v->htotal[k] + / v->pixel_clock[k]) + * 4.0) + - v->writeback_dram_clock_change_watermark; + } else { + v->writeback_dram_clock_change_latency_margin = dcn_bw_min2( + v->writeback_luma_buffer_size, + 2.0 * v->writeback_chroma_buffer_size) * 1024.0 + / (v->scaler_rec_out_width[k] + / (v->htotal[k] / v->pixel_clock[k])) + - v->writeback_dram_clock_change_watermark; + } + if (v->output[k] == dcn_bw_writeback) { + v->active_dram_clock_change_latency_margin[k] = dcn_bw_min2( + v->active_dram_clock_change_latency_margin[k], + v->writeback_dram_clock_change_latency_margin); + } + } + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->allow_dram_clock_change_during_vblank[k] == dcn_bw_yes) { + v->v_blank_dram_clock_change_latency_margin[k] = (v->vtotal[k] + - v->scaler_recout_height[k]) + * (v->htotal[k] / v->pixel_clock[k]) + - dcn_bw_max2( + v->dram_clock_change_watermark, + v->writeback_dram_clock_change_watermark); + } else { + v->v_blank_dram_clock_change_latency_margin[k] = 0.0; + } + } + v->min_active_dram_clock_change_margin = 999999.0; + v->v_blank_of_min_active_dram_clock_change_margin = 999999.0; + v->second_min_active_dram_clock_change_margin = 999999.0; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->active_dram_clock_change_latency_margin[k] + < v->min_active_dram_clock_change_margin) { + v->second_min_active_dram_clock_change_margin = + v->min_active_dram_clock_change_margin; + v->min_active_dram_clock_change_margin = + v->active_dram_clock_change_latency_margin[k]; + v->v_blank_of_min_active_dram_clock_change_margin = + v->v_blank_dram_clock_change_latency_margin[k]; + } else if (v->active_dram_clock_change_latency_margin[k] + < v->second_min_active_dram_clock_change_margin) { + v->second_min_active_dram_clock_change_margin = + v->active_dram_clock_change_latency_margin[k]; + } + } + v->min_vblank_dram_clock_change_margin = 999999.0; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->min_vblank_dram_clock_change_margin + > v->v_blank_dram_clock_change_latency_margin[k]) { + v->min_vblank_dram_clock_change_margin = + v->v_blank_dram_clock_change_latency_margin[k]; + } + } + if (v->synchronized_vblank == dcn_bw_yes || v->number_of_active_planes == 1) { + v->dram_clock_change_margin = dcn_bw_max2( + v->min_active_dram_clock_change_margin, + v->min_vblank_dram_clock_change_margin); + } else if (v->v_blank_of_min_active_dram_clock_change_margin + > v->min_active_dram_clock_change_margin) { + v->dram_clock_change_margin = dcn_bw_min2( + v->second_min_active_dram_clock_change_margin, + v->v_blank_of_min_active_dram_clock_change_margin); + } else { + v->dram_clock_change_margin = v->min_active_dram_clock_change_margin; + } + if (v->min_active_dram_clock_change_margin > 0.0) { + v->dram_clock_change_support = dcn_bw_supported_in_v_active; + } else if (v->dram_clock_change_margin > 0.0) { + v->dram_clock_change_support = dcn_bw_supported_in_v_blank; + } else { + v->dram_clock_change_support = dcn_bw_not_supported; + } + /*maximum bandwidth used*/ + + v->wr_bandwidth = 0.0; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->output[k] == dcn_bw_writeback && v->output_format[k] == dcn_bw_444) { + v->wr_bandwidth = v->wr_bandwidth + + v->scaler_rec_out_width[k] + / (v->htotal[k] / v->pixel_clock[k]) * 4.0; + } else if (v->output[k] == dcn_bw_writeback) { + v->wr_bandwidth = v->wr_bandwidth + + v->scaler_rec_out_width[k] + / (v->htotal[k] / v->pixel_clock[k]) * 1.5; + } + } + v->max_used_bw = v->max_rd_bandwidth + v->wr_bandwidth; +} diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.h b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.h new file mode 100644 index 000000000000..03f06f682ead --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.h @@ -0,0 +1,37 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef _DCN_CALC_AUTO_H_ +#define _DCN_CALC_AUTO_H_ + +#include "dcn_calcs.h" + +void scaler_settings_calculation(struct dcn_bw_internal_vars *v); +void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v); +void display_pipe_configuration(struct dcn_bw_internal_vars *v); +void dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performance_calculation( + struct dcn_bw_internal_vars *v); + +#endif /* _DCN_CALC_AUTO_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.c new file mode 100644 index 000000000000..a18474437990 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.c @@ -0,0 +1,104 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dcn_calc_math.h" + +float dcn_bw_mod(const float arg1, const float arg2) +{ + return arg1 - arg1 * ((int) (arg1 / arg2)); +} + +float dcn_bw_min2(const float arg1, const float arg2) +{ + return arg1 < arg2 ? arg1 : arg2; +} + +unsigned int dcn_bw_max(const unsigned int arg1, const unsigned int arg2) +{ + return arg1 > arg2 ? arg1 : arg2; +} +float dcn_bw_max2(const float arg1, const float arg2) +{ + return arg1 > arg2 ? arg1 : arg2; +} + +float dcn_bw_floor2(const float arg, const float significance) +{ + if (significance == 0) + return 0; + return ((int) (arg / significance)) * significance; +} + +float dcn_bw_ceil2(const float arg, const float significance) +{ + float flr = dcn_bw_floor2(arg, significance); + if (significance == 0) + return 0; + return flr + 0.00001 >= arg ? arg : flr + significance; +} + +float dcn_bw_max3(float v1, float v2, float v3) +{ + return v3 > dcn_bw_max2(v1, v2) ? v3 : dcn_bw_max2(v1, v2); +} + +float dcn_bw_max5(float v1, float v2, float v3, float v4, float v5) +{ + return dcn_bw_max3(v1, v2, v3) > dcn_bw_max2(v4, v5) ? dcn_bw_max3(v1, v2, v3) : dcn_bw_max2(v4, v5); +} + +float dcn_bw_pow(float a, float exp) +{ + float temp; + /*ASSERT(exp == (int)exp);*/ + if ((int)exp == 0) + return 1; + temp = dcn_bw_pow(a, (int)(exp / 2)); + if (((int)exp % 2) == 0) { + return temp * temp; + } else { + if ((int)exp > 0) + return a * temp * temp; + else + return (temp * temp) / a; + } +} + +float dcn_bw_log(float a, float b) +{ + int * const exp_ptr = (int *)(&a); + int x = *exp_ptr; + const int log_2 = ((x >> 23) & 255) - 128; + x &= ~(255 << 23); + x += 127 << 23; + *exp_ptr = x; + + a = ((-1.0f / 3) * a + 2) * a - 2.0f / 3; + + if (b > 2.00001 || b < 1.99999) + return (a + log_2) / dcn_bw_log(b, 2); + else + return (a + log_2); +} diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.h b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.h new file mode 100644 index 000000000000..f46ab0e24ca1 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.h @@ -0,0 +1,40 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef _DCN_CALC_MATH_H_ +#define _DCN_CALC_MATH_H_ + +float dcn_bw_mod(const float arg1, const float arg2); +float dcn_bw_min2(const float arg1, const float arg2); +unsigned int dcn_bw_max(const unsigned int arg1, const unsigned int arg2); +float dcn_bw_max2(const float arg1, const float arg2); +float dcn_bw_floor2(const float arg, const float significance); +float dcn_bw_ceil2(const float arg, const float significance); +float dcn_bw_max3(float v1, float v2, float v3); +float dcn_bw_max5(float v1, float v2, float v3, float v4, float v5); +float dcn_bw_pow(float a, float exp); +float dcn_bw_log(float a, float b); + +#endif /* _DCN_CALC_MATH_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c new file mode 100644 index 000000000000..eb81edf3afa9 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -0,0 +1,1366 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "dcn_calcs.h" +#include "dcn_calc_auto.h" +#include "dc.h" +#include "core_dc.h" +#include "dal_asic_id.h" + +#include "resource.h" +#include "dcn10/dcn10_resource.h" +#include "dcn_calc_math.h" + +/* Defaults from spreadsheet rev#247 */ +const struct dcn_soc_bounding_box dcn10_soc_defaults = { + .sr_exit_time = 17, /*us*/ /*update based on HW Request for 118773*/ + .sr_enter_plus_exit_time = 19, /*us*/ + .urgent_latency = 4, /*us*/ + .write_back_latency = 12, /*us*/ + .percent_of_ideal_drambw_received_after_urg_latency = 80, /*%*/ + .max_request_size = 256, /*bytes*/ + .dcfclkv_max0p9 = 600, /*MHz*/ + .dcfclkv_nom0p8 = 600, /*MHz*/ + .dcfclkv_mid0p72 = 300, /*MHz*/ + .dcfclkv_min0p65 = 300, /*MHz*/ + .max_dispclk_vmax0p9 = 1086, /*MHz*/ + .max_dispclk_vnom0p8 = 661, /*MHz*/ + .max_dispclk_vmid0p72 = 608, /*MHz*/ + .max_dispclk_vmin0p65 = 608, /*MHz*/ + .max_dppclk_vmax0p9 = 661, /*MHz*/ + .max_dppclk_vnom0p8 = 661, /*MHz*/ + .max_dppclk_vmid0p72 = 435, /*MHz*/ + .max_dppclk_vmin0p65 = 435, /*MHz*/ + .socclk = 208, /*MHz*/ + .fabric_and_dram_bandwidth_vmax0p9 = 38.4f, /*GB/s*/ + .fabric_and_dram_bandwidth_vnom0p8 = 34.1f, /*GB/s*/ + .fabric_and_dram_bandwidth_vmid0p72 = 29.8f, /*GB/s*/ + .fabric_and_dram_bandwidth_vmin0p65 = 12.8f, /*GB/s*/ + .phyclkv_max0p9 = 810, /*MHz*/ + .phyclkv_nom0p8 = 810, /*MHz*/ + .phyclkv_mid0p72 = 540, /*MHz*/ + .phyclkv_min0p65 = 540, /*MHz*/ + .downspreading = 0.5f, /*%*/ + .round_trip_ping_latency_cycles = 128, /*DCFCLK Cycles*/ + .urgent_out_of_order_return_per_channel = 256, /*bytes*/ + .number_of_channels = 2, + .vmm_page_size = 4096, /*bytes*/ + .dram_clock_change_latency = 17, /*us*/ + .return_bus_width = 64, /*bytes*/ +}; + +const struct dcn_ip_params dcn10_ip_defaults = { + .rob_buffer_size_in_kbyte = 64, + .det_buffer_size_in_kbyte = 164, + .dpp_output_buffer_pixels = 2560, + .opp_output_buffer_lines = 1, + .pixel_chunk_size_in_kbyte = 8, + .pte_enable = dcn_bw_yes, + .pte_chunk_size = 2, /*kbytes*/ + .meta_chunk_size = 2, /*kbytes*/ + .writeback_chunk_size = 2, /*kbytes*/ + .odm_capability = dcn_bw_no, + .dsc_capability = dcn_bw_no, + .line_buffer_size = 589824, /*bit*/ + .max_line_buffer_lines = 12, + .is_line_buffer_bpp_fixed = dcn_bw_no, + .line_buffer_fixed_bpp = dcn_bw_na, + .writeback_luma_buffer_size = 12, /*kbytes*/ + .writeback_chroma_buffer_size = 8, /*kbytes*/ + .max_num_dpp = 4, + .max_num_writeback = 2, + .max_dchub_topscl_throughput = 4, /*pixels/dppclk*/ + .max_pscl_tolb_throughput = 2, /*pixels/dppclk*/ + .max_lb_tovscl_throughput = 4, /*pixels/dppclk*/ + .max_vscl_tohscl_throughput = 4, /*pixels/dppclk*/ + .max_hscl_ratio = 4, + .max_vscl_ratio = 4, + .max_hscl_taps = 8, + .max_vscl_taps = 8, + .pte_buffer_size_in_requests = 42, + .dispclk_ramping_margin = 1, /*%*/ + .under_scan_factor = 1.11f, + .max_inter_dcn_tile_repeaters = 8, + .can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one = dcn_bw_no, + .bug_forcing_luma_and_chroma_request_to_same_size_fixed = dcn_bw_no, + .dcfclk_cstate_latency = 10 /*TODO clone of something else? sr_enter_plus_exit_time?*/ +}; + +static enum dcn_bw_defs tl_sw_mode_to_bw_defs(enum swizzle_mode_values sw_mode) +{ + switch (sw_mode) { + case DC_SW_LINEAR: + return dcn_bw_sw_linear; + case DC_SW_4KB_S: + return dcn_bw_sw_4_kb_s; + case DC_SW_4KB_D: + return dcn_bw_sw_4_kb_d; + case DC_SW_64KB_S: + return dcn_bw_sw_64_kb_s; + case DC_SW_64KB_D: + return dcn_bw_sw_64_kb_d; + case DC_SW_VAR_S: + return dcn_bw_sw_var_s; + case DC_SW_VAR_D: + return dcn_bw_sw_var_d; + case DC_SW_64KB_S_T: + return dcn_bw_sw_64_kb_s_t; + case DC_SW_64KB_D_T: + return dcn_bw_sw_64_kb_d_t; + case DC_SW_4KB_S_X: + return dcn_bw_sw_4_kb_s_x; + case DC_SW_4KB_D_X: + return dcn_bw_sw_4_kb_d_x; + case DC_SW_64KB_S_X: + return dcn_bw_sw_64_kb_s_x; + case DC_SW_64KB_D_X: + return dcn_bw_sw_64_kb_d_x; + case DC_SW_VAR_S_X: + return dcn_bw_sw_var_s_x; + case DC_SW_VAR_D_X: + return dcn_bw_sw_var_d_x; + case DC_SW_256B_S: + case DC_SW_256_D: + case DC_SW_256_R: + case DC_SW_4KB_R: + case DC_SW_64KB_R: + case DC_SW_VAR_R: + case DC_SW_4KB_R_X: + case DC_SW_64KB_R_X: + case DC_SW_VAR_R_X: + default: + BREAK_TO_DEBUGGER(); /*not in formula*/ + return dcn_bw_sw_4_kb_s; + } +} + +static int tl_lb_bpp_to_int(enum lb_pixel_depth depth) +{ + switch (depth) { + case LB_PIXEL_DEPTH_18BPP: + return 18; + case LB_PIXEL_DEPTH_24BPP: + return 24; + case LB_PIXEL_DEPTH_30BPP: + return 30; + case LB_PIXEL_DEPTH_36BPP: + return 36; + default: + return 30; + } +} + +static enum dcn_bw_defs tl_pixel_format_to_bw_defs(enum surface_pixel_format format) +{ + switch (format) { + case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: + case SURFACE_PIXEL_FORMAT_GRPH_RGB565: + return dcn_bw_rgb_sub_16; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: + case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: + return dcn_bw_rgb_sub_32; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: + return dcn_bw_rgb_sub_64; + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: + return dcn_bw_yuv420_sub_8; + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: + return dcn_bw_yuv420_sub_10; + default: + return dcn_bw_rgb_sub_32; + } +} + +static void pipe_ctx_to_e2e_pipe_params ( + const struct pipe_ctx *pipe, + struct _vcs_dpi_display_pipe_params_st *input) +{ + input->src.is_hsplit = false; + if (pipe->top_pipe != NULL && pipe->top_pipe->surface == pipe->surface) + input->src.is_hsplit = true; + else if (pipe->bottom_pipe != NULL && pipe->bottom_pipe->surface == pipe->surface) + input->src.is_hsplit = true; + + input->src.dcc = pipe->surface->public.dcc.enable; + input->src.dcc_rate = 1; + input->src.meta_pitch = pipe->surface->public.dcc.grph.meta_pitch; + input->src.source_scan = dm_horz; + input->src.sw_mode = pipe->surface->public.tiling_info.gfx9.swizzle; + + input->src.viewport_width = pipe->scl_data.viewport.width; + input->src.viewport_height = pipe->scl_data.viewport.height; + input->src.data_pitch = pipe->scl_data.viewport.width; + input->src.data_pitch_c = pipe->scl_data.viewport.width; + input->src.cur0_src_width = 128; /* TODO: Cursor calcs, not curently stored */ + input->src.cur0_bpp = 32; + + switch (pipe->surface->public.tiling_info.gfx9.swizzle) { + /* for 4/8/16 high tiles */ + case DC_SW_LINEAR: + input->src.is_display_sw = 1; + input->src.macro_tile_size = dm_4k_tile; + break; + case DC_SW_4KB_S: + case DC_SW_4KB_S_X: + input->src.is_display_sw = 0; + input->src.macro_tile_size = dm_4k_tile; + break; + case DC_SW_64KB_S: + case DC_SW_64KB_S_X: + input->src.is_display_sw = 0; + input->src.macro_tile_size = dm_64k_tile; + break; + case DC_SW_VAR_S: + case DC_SW_VAR_S_X: + input->src.is_display_sw = 0; + input->src.macro_tile_size = dm_256k_tile; + break; + + /* For 64bpp 2 high tiles */ + case DC_SW_4KB_D: + case DC_SW_4KB_D_X: + input->src.is_display_sw = 1; + input->src.macro_tile_size = dm_4k_tile; + break; + case DC_SW_64KB_D: + case DC_SW_64KB_D_X: + input->src.is_display_sw = 1; + input->src.macro_tile_size = dm_64k_tile; + break; + case DC_SW_VAR_D: + case DC_SW_VAR_D_X: + input->src.is_display_sw = 1; + input->src.macro_tile_size = dm_256k_tile; + break; + + /* Unsupported swizzle modes for dcn */ + case DC_SW_256B_S: + default: + ASSERT(0); /* Not supported */ + break; + } + + switch (pipe->surface->public.rotation) { + case ROTATION_ANGLE_0: + case ROTATION_ANGLE_180: + input->src.source_scan = dm_horz; + break; + case ROTATION_ANGLE_90: + case ROTATION_ANGLE_270: + input->src.source_scan = dm_vert; + break; + default: + ASSERT(0); /* Not supported */ + break; + } + + /* TODO: Fix pixel format mappings */ + switch (pipe->surface->public.format) { + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: + input->src.source_format = dm_420_8; + input->src.viewport_width_c = input->src.viewport_width / 2; + input->src.viewport_height_c = input->src.viewport_height / 2; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: + input->src.source_format = dm_420_10; + input->src.viewport_width_c = input->src.viewport_width / 2; + input->src.viewport_height_c = input->src.viewport_height / 2; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: + input->src.source_format = dm_444_64; + input->src.viewport_width_c = input->src.viewport_width; + input->src.viewport_height_c = input->src.viewport_height; + break; + default: + input->src.source_format = dm_444_32; + input->src.viewport_width_c = input->src.viewport_width; + input->src.viewport_height_c = input->src.viewport_height; + break; + } + + input->scale_taps.htaps = pipe->scl_data.taps.h_taps; + input->scale_ratio_depth.hscl_ratio = pipe->scl_data.ratios.horz.value/4294967296.0; + input->scale_ratio_depth.vscl_ratio = pipe->scl_data.ratios.vert.value/4294967296.0; + input->scale_ratio_depth.vinit = pipe->scl_data.inits.v.value/4294967296.0; + if (input->scale_ratio_depth.vinit < 1.0) + input->scale_ratio_depth.vinit = 1; + input->scale_taps.vtaps = pipe->scl_data.taps.v_taps; + input->scale_taps.vtaps_c = pipe->scl_data.taps.v_taps_c; + input->scale_taps.htaps_c = pipe->scl_data.taps.h_taps_c; + input->scale_ratio_depth.hscl_ratio_c = pipe->scl_data.ratios.horz_c.value/4294967296.0; + input->scale_ratio_depth.vscl_ratio_c = pipe->scl_data.ratios.vert_c.value/4294967296.0; + input->scale_ratio_depth.vinit_c = pipe->scl_data.inits.v_c.value/4294967296.0; + if (input->scale_ratio_depth.vinit_c < 1.0) + input->scale_ratio_depth.vinit_c = 1; + switch (pipe->scl_data.lb_params.depth) { + case LB_PIXEL_DEPTH_30BPP: + input->scale_ratio_depth.lb_depth = 30; break; + case LB_PIXEL_DEPTH_36BPP: + input->scale_ratio_depth.lb_depth = 36; break; + default: + input->scale_ratio_depth.lb_depth = 24; break; + } + + + input->dest.vactive = pipe->stream->public.timing.v_addressable; + + input->dest.recout_width = pipe->scl_data.recout.width; + input->dest.recout_height = pipe->scl_data.recout.height; + + input->dest.full_recout_width = pipe->scl_data.recout.width; + input->dest.full_recout_height = pipe->scl_data.recout.height; + + input->dest.htotal = pipe->stream->public.timing.h_total; + input->dest.hblank_start = input->dest.htotal - pipe->stream->public.timing.h_front_porch; + input->dest.hblank_end = input->dest.hblank_start + - pipe->stream->public.timing.h_addressable + - pipe->stream->public.timing.h_border_left + - pipe->stream->public.timing.h_border_right; + + input->dest.vtotal = pipe->stream->public.timing.v_total; + input->dest.vblank_start = input->dest.vtotal - pipe->stream->public.timing.v_front_porch; + input->dest.vblank_end = input->dest.vblank_start + - pipe->stream->public.timing.v_addressable + - pipe->stream->public.timing.v_border_bottom + - pipe->stream->public.timing.v_border_top; + + input->dest.vsync_plus_back_porch = pipe->stream->public.timing.v_total + - pipe->stream->public.timing.v_addressable + - pipe->stream->public.timing.v_front_porch; + input->dest.pixel_rate_mhz = pipe->stream->public.timing.pix_clk_khz/1000.0; + input->dest.vstartup_start = pipe->pipe_dlg_param.vstartup_start; + input->dest.vupdate_offset = pipe->pipe_dlg_param.vupdate_offset; + input->dest.vupdate_offset = pipe->pipe_dlg_param.vupdate_offset; + input->dest.vupdate_width = pipe->pipe_dlg_param.vupdate_width; + +} + +static void dcn_bw_calc_rq_dlg_ttu( + const struct core_dc *dc, + const struct dcn_bw_internal_vars *v, + struct pipe_ctx *pipe) +{ + struct display_mode_lib *dml = (struct display_mode_lib *)(&dc->dml); + struct _vcs_dpi_display_dlg_regs_st *dlg_regs = &pipe->dlg_regs; + struct _vcs_dpi_display_ttu_regs_st *ttu_regs = &pipe->ttu_regs; + struct _vcs_dpi_display_rq_regs_st *rq_regs = &pipe->rq_regs; + struct _vcs_dpi_display_rq_params_st rq_param = {0}; + struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param = {0}; + struct _vcs_dpi_display_e2e_pipe_params_st input = { { { 0 } } }; + float total_active_bw = 0; + float total_prefetch_bw = 0; + int total_flip_bytes = 0; + int i; + + for (i = 0; i < number_of_planes; i++) { + total_active_bw += v->read_bandwidth[i]; + total_prefetch_bw += v->prefetch_bandwidth[i]; + total_flip_bytes += v->total_immediate_flip_bytes[i]; + } + dlg_sys_param.total_flip_bw = v->return_bw - dcn_bw_max2(total_active_bw, total_prefetch_bw); + if (dlg_sys_param.total_flip_bw < 0.0) + dlg_sys_param.total_flip_bw = 0; + + dlg_sys_param.t_mclk_wm_us = v->dram_clock_change_watermark; + dlg_sys_param.t_sr_wm_us = v->stutter_enter_plus_exit_watermark; + dlg_sys_param.t_urg_wm_us = v->urgent_watermark; + dlg_sys_param.t_extra_us = v->urgent_extra_latency; + dlg_sys_param.deepsleep_dcfclk_mhz = v->dcf_clk_deep_sleep; + dlg_sys_param.total_flip_bytes = total_flip_bytes; + + pipe_ctx_to_e2e_pipe_params(pipe, &input.pipe); + input.clks_cfg.dcfclk_mhz = v->dcfclk; + input.clks_cfg.dispclk_mhz = v->dispclk; + input.clks_cfg.dppclk_mhz = v->dppclk; + input.clks_cfg.refclk_mhz = dc->res_pool->ref_clock_inKhz/1000; + input.clks_cfg.socclk_mhz = v->socclk; + input.clks_cfg.voltage = v->voltage_level; +// dc->dml.logger = pool->base.logger; + + /*todo: soc->sr_enter_plus_exit_time??*/ + dlg_sys_param.t_srx_delay_us = dc->dcn_ip.dcfclk_cstate_latency / v->dcf_clk_deep_sleep; + + dml_rq_dlg_get_rq_params(dml, &rq_param, input.pipe.src); + extract_rq_regs(dml, rq_regs, rq_param); + dml_rq_dlg_get_dlg_params( + dml, + dlg_regs, + ttu_regs, + rq_param.dlg, + dlg_sys_param, + input, + true, + true, + v->pte_enable == dcn_bw_yes, + pipe->surface->public.flip_immediate); +} + +static void dcn_dml_wm_override( + const struct dcn_bw_internal_vars *v, + struct display_mode_lib *dml, + struct validate_context *context, + const struct resource_pool *pool) +{ + int i, in_idx, active_count; + + struct _vcs_dpi_display_e2e_pipe_params_st *input = dm_alloc(pool->pipe_count * + sizeof(struct _vcs_dpi_display_e2e_pipe_params_st)); + struct wm { + double urgent; + struct _vcs_dpi_cstate_pstate_watermarks_st cpstate; + double pte_meta_urgent; + } a; + + + for (i = 0, in_idx = 0; i < pool->pipe_count; i++) { + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; + + if (!pipe->stream || !pipe->surface) + continue; + + input[in_idx].clks_cfg.dcfclk_mhz = v->dcfclk; + input[in_idx].clks_cfg.dispclk_mhz = v->dispclk; + input[in_idx].clks_cfg.dppclk_mhz = v->dppclk; + input[in_idx].clks_cfg.refclk_mhz = pool->ref_clock_inKhz / 1000; + input[in_idx].clks_cfg.socclk_mhz = v->socclk; + input[in_idx].clks_cfg.voltage = v->voltage_level; + pipe_ctx_to_e2e_pipe_params(pipe, &input[in_idx].pipe); + dml_rq_dlg_get_rq_reg( + dml, + &pipe->rq_regs, + input[in_idx].pipe.src); + in_idx++; + } + active_count = in_idx; + + a.urgent = dml_wm_urgent_e2e(dml, input, active_count); + a.cpstate = dml_wm_cstate_pstate_e2e(dml, input, active_count); + a.pte_meta_urgent = dml_wm_pte_meta_urgent(dml, a.urgent); + + context->watermarks.a.cstate_pstate.cstate_exit_ns = + a.cpstate.cstate_exit_us * 1000; + context->watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns = + a.cpstate.cstate_enter_plus_exit_us * 1000; + context->watermarks.a.cstate_pstate.pstate_change_ns = + a.cpstate.pstate_change_us * 1000; + context->watermarks.a.pte_meta_urgent_ns = a.pte_meta_urgent * 1000; + context->watermarks.a.urgent_ns = a.urgent * 1000; + context->watermarks.b = context->watermarks.a; + context->watermarks.c = context->watermarks.a; + context->watermarks.d = context->watermarks.a; + + + for (i = 0, in_idx = 0; i < pool->pipe_count; i++) { + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; + + if (!pipe->stream || !pipe->surface) + continue; + + dml_rq_dlg_get_dlg_reg(dml, + &pipe->dlg_regs, + &pipe->ttu_regs, + input, active_count, + in_idx, + true, + true, + v->pte_enable == dcn_bw_yes, + pipe->surface->public.flip_immediate); + in_idx++; + } + dm_free(input); +} + +static void split_stream_across_pipes( + struct resource_context *res_ctx, + const struct resource_pool *pool, + struct pipe_ctx *primary_pipe, + struct pipe_ctx *secondary_pipe) +{ + if (!primary_pipe->surface) + return; + + secondary_pipe->stream = primary_pipe->stream; + secondary_pipe->tg = primary_pipe->tg; + + secondary_pipe->mi = pool->mis[secondary_pipe->pipe_idx]; + secondary_pipe->ipp = pool->ipps[secondary_pipe->pipe_idx]; + secondary_pipe->xfm = pool->transforms[secondary_pipe->pipe_idx]; + secondary_pipe->opp = pool->opps[secondary_pipe->pipe_idx]; + if (primary_pipe->bottom_pipe) { + secondary_pipe->bottom_pipe = primary_pipe->bottom_pipe; + secondary_pipe->bottom_pipe->top_pipe = secondary_pipe; + } + primary_pipe->bottom_pipe = secondary_pipe; + secondary_pipe->top_pipe = primary_pipe; + secondary_pipe->surface = primary_pipe->surface; + secondary_pipe->pipe_dlg_param = primary_pipe->pipe_dlg_param; + + resource_build_scaling_params(primary_pipe); + resource_build_scaling_params(secondary_pipe); +} + +static void calc_wm_sets_and_perf_params( + struct validate_context *context, + struct dcn_bw_internal_vars *v) +{ + /* Calculate set A last to keep internal var state consistent for required config */ + if (v->voltage_level < 2) { + v->fabric_and_dram_bandwidth_per_state[1] = v->fabric_and_dram_bandwidth_vnom0p8; + v->fabric_and_dram_bandwidth_per_state[0] = v->fabric_and_dram_bandwidth_vnom0p8; + v->fabric_and_dram_bandwidth = v->fabric_and_dram_bandwidth_vnom0p8; + dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performance_calculation(v); + + context->watermarks.b.cstate_pstate.cstate_exit_ns = + v->stutter_exit_watermark * 1000; + context->watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns = + v->stutter_enter_plus_exit_watermark * 1000; + context->watermarks.b.cstate_pstate.pstate_change_ns = + v->dram_clock_change_watermark * 1000; + context->watermarks.b.pte_meta_urgent_ns = v->ptemeta_urgent_watermark * 1000; + context->watermarks.b.urgent_ns = v->urgent_watermark * 1000; + + v->dcfclk_per_state[1] = v->dcfclkv_nom0p8; + v->dcfclk_per_state[0] = v->dcfclkv_nom0p8; + v->dcfclk = v->dcfclkv_nom0p8; + dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performance_calculation(v); + + context->watermarks.c.cstate_pstate.cstate_exit_ns = + v->stutter_exit_watermark * 1000; + context->watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns = + v->stutter_enter_plus_exit_watermark * 1000; + context->watermarks.c.cstate_pstate.pstate_change_ns = + v->dram_clock_change_watermark * 1000; + context->watermarks.c.pte_meta_urgent_ns = v->ptemeta_urgent_watermark * 1000; + context->watermarks.c.urgent_ns = v->urgent_watermark * 1000; + } + + if (v->voltage_level < 3) { + v->fabric_and_dram_bandwidth_per_state[2] = v->fabric_and_dram_bandwidth_vmax0p9; + v->fabric_and_dram_bandwidth_per_state[1] = v->fabric_and_dram_bandwidth_vmax0p9; + v->fabric_and_dram_bandwidth_per_state[0] = v->fabric_and_dram_bandwidth_vmax0p9; + v->fabric_and_dram_bandwidth = v->fabric_and_dram_bandwidth_vmax0p9; + v->dcfclk_per_state[2] = v->dcfclkv_max0p9; + v->dcfclk_per_state[1] = v->dcfclkv_max0p9; + v->dcfclk_per_state[0] = v->dcfclkv_max0p9; + v->dcfclk = v->dcfclkv_max0p9; + dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performance_calculation(v); + + context->watermarks.d.cstate_pstate.cstate_exit_ns = + v->stutter_exit_watermark * 1000; + context->watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns = + v->stutter_enter_plus_exit_watermark * 1000; + context->watermarks.d.cstate_pstate.pstate_change_ns = + v->dram_clock_change_watermark * 1000; + context->watermarks.d.pte_meta_urgent_ns = v->ptemeta_urgent_watermark * 1000; + context->watermarks.d.urgent_ns = v->urgent_watermark * 1000; + } + + v->fabric_and_dram_bandwidth_per_state[2] = v->fabric_and_dram_bandwidth_vnom0p8; + v->fabric_and_dram_bandwidth_per_state[1] = v->fabric_and_dram_bandwidth_vmid0p72; + v->fabric_and_dram_bandwidth_per_state[0] = v->fabric_and_dram_bandwidth_vmin0p65; + v->fabric_and_dram_bandwidth = v->fabric_and_dram_bandwidth_per_state[v->voltage_level]; + v->dcfclk_per_state[2] = v->dcfclkv_nom0p8; + v->dcfclk_per_state[1] = v->dcfclkv_mid0p72; + v->dcfclk_per_state[0] = v->dcfclkv_min0p65; + v->dcfclk = v->dcfclk_per_state[v->voltage_level]; + dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performance_calculation(v); + + context->watermarks.a.cstate_pstate.cstate_exit_ns = + v->stutter_exit_watermark * 1000; + context->watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns = + v->stutter_enter_plus_exit_watermark * 1000; + context->watermarks.a.cstate_pstate.pstate_change_ns = + v->dram_clock_change_watermark * 1000; + context->watermarks.a.pte_meta_urgent_ns = v->ptemeta_urgent_watermark * 1000; + context->watermarks.a.urgent_ns = v->urgent_watermark * 1000; + if (v->voltage_level >= 2) { + context->watermarks.b = context->watermarks.a; + context->watermarks.c = context->watermarks.a; + } + if (v->voltage_level >= 3) + context->watermarks.d = context->watermarks.a; +} + +static void dcn_bw_apply_registry_override(struct core_dc *dc) +{ + kernel_fpu_begin(); + if (dc->public.debug.sr_exit_time_ns) + dc->dcn_soc.sr_exit_time = dc->public.debug.sr_exit_time_ns / 1000.0; + if (dc->public.debug.sr_enter_plus_exit_time_ns) + dc->dcn_soc.sr_enter_plus_exit_time = + dc->public.debug.sr_enter_plus_exit_time_ns / 1000.0; + if (dc->public.debug.urgent_latency_ns) + dc->dcn_soc.urgent_latency = dc->public.debug.urgent_latency_ns / 1000.0; + if (dc->public.debug.percent_of_ideal_drambw) + dc->dcn_soc.percent_of_ideal_drambw_received_after_urg_latency = + dc->public.debug.percent_of_ideal_drambw; + if (dc->public.debug.dram_clock_change_latency_ns) + dc->dcn_soc.dram_clock_change_latency = + dc->public.debug.dram_clock_change_latency_ns / 1000.0; + kernel_fpu_end(); +} + +bool dcn_validate_bandwidth( + const struct core_dc *dc, + struct validate_context *context) +{ + const struct resource_pool *pool = dc->res_pool; + struct dcn_bw_internal_vars *v = &context->dcn_bw_vars; + int i, input_idx; + int vesa_sync_start, asic_blank_end, asic_blank_start; + + dcn_bw_apply_registry_override(DC_TO_CORE(&dc->public)); + + memset(v, 0, sizeof(*v)); + kernel_fpu_begin(); + v->sr_exit_time = dc->dcn_soc.sr_exit_time; + v->sr_enter_plus_exit_time = dc->dcn_soc.sr_enter_plus_exit_time; + v->urgent_latency = dc->dcn_soc.urgent_latency; + v->write_back_latency = dc->dcn_soc.write_back_latency; + v->percent_of_ideal_drambw_received_after_urg_latency = + dc->dcn_soc.percent_of_ideal_drambw_received_after_urg_latency; + + v->dcfclkv_min0p65 = dc->dcn_soc.dcfclkv_min0p65; + v->dcfclkv_mid0p72 = dc->dcn_soc.dcfclkv_mid0p72; + v->dcfclkv_nom0p8 = dc->dcn_soc.dcfclkv_nom0p8; + v->dcfclkv_max0p9 = dc->dcn_soc.dcfclkv_max0p9; + + v->max_dispclk_vmin0p65 = dc->dcn_soc.max_dispclk_vmin0p65; + v->max_dispclk_vmid0p72 = dc->dcn_soc.max_dispclk_vmid0p72; + v->max_dispclk_vnom0p8 = dc->dcn_soc.max_dispclk_vnom0p8; + v->max_dispclk_vmax0p9 = dc->dcn_soc.max_dispclk_vmax0p9; + + v->max_dppclk_vmin0p65 = dc->dcn_soc.max_dppclk_vmin0p65; + v->max_dppclk_vmid0p72 = dc->dcn_soc.max_dppclk_vmid0p72; + v->max_dppclk_vnom0p8 = dc->dcn_soc.max_dppclk_vnom0p8; + v->max_dppclk_vmax0p9 = dc->dcn_soc.max_dppclk_vmax0p9; + + v->socclk = dc->dcn_soc.socclk; + + v->fabric_and_dram_bandwidth_vmin0p65 = dc->dcn_soc.fabric_and_dram_bandwidth_vmin0p65; + v->fabric_and_dram_bandwidth_vmid0p72 = dc->dcn_soc.fabric_and_dram_bandwidth_vmid0p72; + v->fabric_and_dram_bandwidth_vnom0p8 = dc->dcn_soc.fabric_and_dram_bandwidth_vnom0p8; + v->fabric_and_dram_bandwidth_vmax0p9 = dc->dcn_soc.fabric_and_dram_bandwidth_vmax0p9; + + v->phyclkv_min0p65 = dc->dcn_soc.phyclkv_min0p65; + v->phyclkv_mid0p72 = dc->dcn_soc.phyclkv_mid0p72; + v->phyclkv_nom0p8 = dc->dcn_soc.phyclkv_nom0p8; + v->phyclkv_max0p9 = dc->dcn_soc.phyclkv_max0p9; + + v->downspreading = dc->dcn_soc.downspreading; + v->round_trip_ping_latency_cycles = dc->dcn_soc.round_trip_ping_latency_cycles; + v->urgent_out_of_order_return_per_channel = dc->dcn_soc.urgent_out_of_order_return_per_channel; + v->number_of_channels = dc->dcn_soc.number_of_channels; + v->vmm_page_size = dc->dcn_soc.vmm_page_size; + v->dram_clock_change_latency = dc->dcn_soc.dram_clock_change_latency; + v->return_bus_width = dc->dcn_soc.return_bus_width; + + v->rob_buffer_size_in_kbyte = dc->dcn_ip.rob_buffer_size_in_kbyte; + v->det_buffer_size_in_kbyte = dc->dcn_ip.det_buffer_size_in_kbyte; + v->dpp_output_buffer_pixels = dc->dcn_ip.dpp_output_buffer_pixels; + v->opp_output_buffer_lines = dc->dcn_ip.opp_output_buffer_lines; + v->pixel_chunk_size_in_kbyte = dc->dcn_ip.pixel_chunk_size_in_kbyte; + v->pte_enable = dc->dcn_ip.pte_enable; + v->pte_chunk_size = dc->dcn_ip.pte_chunk_size; + v->meta_chunk_size = dc->dcn_ip.meta_chunk_size; + v->writeback_chunk_size = dc->dcn_ip.writeback_chunk_size; + v->odm_capability = dc->dcn_ip.odm_capability; + v->dsc_capability = dc->dcn_ip.dsc_capability; + v->line_buffer_size = dc->dcn_ip.line_buffer_size; + v->is_line_buffer_bpp_fixed = dc->dcn_ip.is_line_buffer_bpp_fixed; + v->line_buffer_fixed_bpp = dc->dcn_ip.line_buffer_fixed_bpp; + v->max_line_buffer_lines = dc->dcn_ip.max_line_buffer_lines; + v->writeback_luma_buffer_size = dc->dcn_ip.writeback_luma_buffer_size; + v->writeback_chroma_buffer_size = dc->dcn_ip.writeback_chroma_buffer_size; + v->max_num_dpp = dc->dcn_ip.max_num_dpp; + v->max_num_writeback = dc->dcn_ip.max_num_writeback; + v->max_dchub_topscl_throughput = dc->dcn_ip.max_dchub_topscl_throughput; + v->max_pscl_tolb_throughput = dc->dcn_ip.max_pscl_tolb_throughput; + v->max_lb_tovscl_throughput = dc->dcn_ip.max_lb_tovscl_throughput; + v->max_vscl_tohscl_throughput = dc->dcn_ip.max_vscl_tohscl_throughput; + v->max_hscl_ratio = dc->dcn_ip.max_hscl_ratio; + v->max_vscl_ratio = dc->dcn_ip.max_vscl_ratio; + v->max_hscl_taps = dc->dcn_ip.max_hscl_taps; + v->max_vscl_taps = dc->dcn_ip.max_vscl_taps; + v->under_scan_factor = dc->dcn_ip.under_scan_factor; + v->pte_buffer_size_in_requests = dc->dcn_ip.pte_buffer_size_in_requests; + v->dispclk_ramping_margin = dc->dcn_ip.dispclk_ramping_margin; + v->max_inter_dcn_tile_repeaters = dc->dcn_ip.max_inter_dcn_tile_repeaters; + v->can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one = + dc->dcn_ip.can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one; + v->bug_forcing_luma_and_chroma_request_to_same_size_fixed = + dc->dcn_ip.bug_forcing_luma_and_chroma_request_to_same_size_fixed; + + v->voltage[5] = dcn_bw_no_support; + v->voltage[4] = dcn_bw_v_max0p9; + v->voltage[3] = dcn_bw_v_max0p9; + v->voltage[2] = dcn_bw_v_nom0p8; + v->voltage[1] = dcn_bw_v_mid0p72; + v->voltage[0] = dcn_bw_v_min0p65; + v->fabric_and_dram_bandwidth_per_state[5] = v->fabric_and_dram_bandwidth_vmax0p9; + v->fabric_and_dram_bandwidth_per_state[4] = v->fabric_and_dram_bandwidth_vmax0p9; + v->fabric_and_dram_bandwidth_per_state[3] = v->fabric_and_dram_bandwidth_vmax0p9; + v->fabric_and_dram_bandwidth_per_state[2] = v->fabric_and_dram_bandwidth_vnom0p8; + v->fabric_and_dram_bandwidth_per_state[1] = v->fabric_and_dram_bandwidth_vmid0p72; + v->fabric_and_dram_bandwidth_per_state[0] = v->fabric_and_dram_bandwidth_vmin0p65; + v->dcfclk_per_state[5] = v->dcfclkv_max0p9; + v->dcfclk_per_state[4] = v->dcfclkv_max0p9; + v->dcfclk_per_state[3] = v->dcfclkv_max0p9; + v->dcfclk_per_state[2] = v->dcfclkv_nom0p8; + v->dcfclk_per_state[1] = v->dcfclkv_mid0p72; + v->dcfclk_per_state[0] = v->dcfclkv_min0p65; + v->max_dispclk[5] = v->max_dispclk_vmax0p9; + v->max_dispclk[4] = v->max_dispclk_vmax0p9; + v->max_dispclk[3] = v->max_dispclk_vmax0p9; + v->max_dispclk[2] = v->max_dispclk_vnom0p8; + v->max_dispclk[1] = v->max_dispclk_vmid0p72; + v->max_dispclk[0] = v->max_dispclk_vmin0p65; + v->max_dppclk[5] = v->max_dppclk_vmax0p9; + v->max_dppclk[4] = v->max_dppclk_vmax0p9; + v->max_dppclk[3] = v->max_dppclk_vmax0p9; + v->max_dppclk[2] = v->max_dppclk_vnom0p8; + v->max_dppclk[1] = v->max_dppclk_vmid0p72; + v->max_dppclk[0] = v->max_dppclk_vmin0p65; + v->phyclk_per_state[5] = v->phyclkv_max0p9; + v->phyclk_per_state[4] = v->phyclkv_max0p9; + v->phyclk_per_state[3] = v->phyclkv_max0p9; + v->phyclk_per_state[2] = v->phyclkv_nom0p8; + v->phyclk_per_state[1] = v->phyclkv_mid0p72; + v->phyclk_per_state[0] = v->phyclkv_min0p65; + + if (dc->public.debug.use_max_voltage) { + v->max_dppclk[1] = v->max_dppclk_vnom0p8; + v->max_dppclk[0] = v->max_dppclk_vnom0p8; + } + + if (v->voltage_override == dcn_bw_v_max0p9) { + v->voltage_override_level = number_of_states - 1; + } else if (v->voltage_override == dcn_bw_v_nom0p8) { + v->voltage_override_level = number_of_states - 2; + } else if (v->voltage_override == dcn_bw_v_mid0p72) { + v->voltage_override_level = number_of_states - 3; + } else { + v->voltage_override_level = 0; + } + v->synchronized_vblank = dcn_bw_no; + v->ta_pscalculation = dcn_bw_override; + v->allow_different_hratio_vratio = dcn_bw_yes; + + + for (i = 0, input_idx = 0; i < pool->pipe_count; i++) { + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; + + if (!pipe->stream) + continue; + /* skip all but first of split pipes */ + if (pipe->top_pipe && pipe->top_pipe->surface == pipe->surface) + continue; + + v->underscan_output[input_idx] = false; /* taken care of in recout already*/ + v->interlace_output[input_idx] = false; + + v->htotal[input_idx] = pipe->stream->public.timing.h_total; + v->vtotal[input_idx] = pipe->stream->public.timing.v_total; + v->v_sync_plus_back_porch[input_idx] = pipe->stream->public.timing.v_total + - pipe->stream->public.timing.v_addressable + - pipe->stream->public.timing.v_front_porch; + v->vactive[input_idx] = pipe->stream->public.timing.v_addressable; + v->pixel_clock[input_idx] = pipe->stream->public.timing.pix_clk_khz / 1000.0f; + + + if (!pipe->surface){ + v->dcc_enable[input_idx] = dcn_bw_yes; + v->source_pixel_format[input_idx] = dcn_bw_rgb_sub_32; + v->source_surface_mode[input_idx] = dcn_bw_sw_4_kb_s; + v->lb_bit_per_pixel[input_idx] = 30; + v->viewport_width[input_idx] = pipe->stream->public.timing.h_addressable; + v->viewport_height[input_idx] = pipe->stream->public.timing.v_addressable; + v->scaler_rec_out_width[input_idx] = pipe->stream->public.timing.h_addressable; + v->scaler_recout_height[input_idx] = pipe->stream->public.timing.v_addressable; + v->override_hta_ps[input_idx] = 1; + v->override_vta_ps[input_idx] = 1; + v->override_hta_pschroma[input_idx] = 1; + v->override_vta_pschroma[input_idx] = 1; + v->source_scan[input_idx] = dcn_bw_hor; + + } else { + v->viewport_height[input_idx] = pipe->scl_data.viewport.height; + v->viewport_width[input_idx] = pipe->scl_data.viewport.width; + v->scaler_rec_out_width[input_idx] = pipe->scl_data.recout.width; + v->scaler_recout_height[input_idx] = pipe->scl_data.recout.height; + if (pipe->bottom_pipe && pipe->bottom_pipe->surface == pipe->surface) { + if (pipe->surface->public.rotation % 2 == 0) { + int viewport_end = pipe->scl_data.viewport.width + + pipe->scl_data.viewport.x; + int viewport_b_end = pipe->bottom_pipe->scl_data.viewport.width + + pipe->bottom_pipe->scl_data.viewport.x; + + if (viewport_end > viewport_b_end) + v->viewport_width[input_idx] = viewport_end + - pipe->bottom_pipe->scl_data.viewport.x; + else + v->viewport_width[input_idx] = viewport_b_end + - pipe->scl_data.viewport.x; + } else { + int viewport_end = pipe->scl_data.viewport.height + + pipe->scl_data.viewport.y; + int viewport_b_end = pipe->bottom_pipe->scl_data.viewport.height + + pipe->bottom_pipe->scl_data.viewport.y; + + if (viewport_end > viewport_b_end) + v->viewport_height[input_idx] = viewport_end + - pipe->bottom_pipe->scl_data.viewport.y; + else + v->viewport_height[input_idx] = viewport_b_end + - pipe->scl_data.viewport.y; + } + v->scaler_rec_out_width[input_idx] = pipe->scl_data.recout.width + + pipe->bottom_pipe->scl_data.recout.width; + } + + v->dcc_enable[input_idx] = pipe->surface->public.dcc.enable ? dcn_bw_yes : dcn_bw_no; + v->source_pixel_format[input_idx] = tl_pixel_format_to_bw_defs( + pipe->surface->public.format); + v->source_surface_mode[input_idx] = tl_sw_mode_to_bw_defs( + pipe->surface->public.tiling_info.gfx9.swizzle); + v->lb_bit_per_pixel[input_idx] = tl_lb_bpp_to_int(pipe->scl_data.lb_params.depth); + v->override_hta_ps[input_idx] = pipe->scl_data.taps.h_taps; + v->override_vta_ps[input_idx] = pipe->scl_data.taps.v_taps; + v->override_hta_pschroma[input_idx] = pipe->scl_data.taps.h_taps_c; + v->override_vta_pschroma[input_idx] = pipe->scl_data.taps.v_taps_c; + v->source_scan[input_idx] = (pipe->surface->public.rotation % 2) ? dcn_bw_vert : dcn_bw_hor; + } + if (v->is_line_buffer_bpp_fixed == dcn_bw_yes) + v->lb_bit_per_pixel[input_idx] = v->line_buffer_fixed_bpp; + v->dcc_rate[input_idx] = 1; /*TODO: Worst case? does this change?*/ + v->output_format[input_idx] = dcn_bw_444; + v->output[input_idx] = dcn_bw_dp; + + input_idx++; + } + v->number_of_active_planes = input_idx; + + scaler_settings_calculation(v); + mode_support_and_system_configuration(v); + + if (v->voltage_level != 5) { + float bw_consumed = v->total_bandwidth_consumed_gbyte_per_second; + if (bw_consumed < v->fabric_and_dram_bandwidth_vmin0p65) + bw_consumed = v->fabric_and_dram_bandwidth_vmin0p65; + else if (bw_consumed < v->fabric_and_dram_bandwidth_vmid0p72) + bw_consumed = v->fabric_and_dram_bandwidth_vmid0p72; + else if (bw_consumed < v->fabric_and_dram_bandwidth_vnom0p8) + bw_consumed = v->fabric_and_dram_bandwidth_vnom0p8; + else + bw_consumed = v->fabric_and_dram_bandwidth_vmax0p9; + + display_pipe_configuration(v); + calc_wm_sets_and_perf_params(context, v); + context->fclk_khz = (int)(bw_consumed * 1000000 / + (ddr4_dram_factor_single_Channel * v->number_of_channels)); + context->dram_ccm_us = (int)(v->dram_clock_change_margin); + context->min_active_dram_ccm_us = (int)(v->min_active_dram_clock_change_margin); + context->dcfclk_deep_sleep_khz = (int)(v->dcf_clk_deep_sleep * 1000); + context->dcfclk_khz = (int)(v->dcfclk * 1000); + context->dispclk_khz = (int)(v->dispclk * 1000); + if (dc->public.debug.max_disp_clk == true) + context->dispclk_khz = (int)(dc->dcn_soc.max_dispclk_vmax0p9 * 1000); + context->dppclk_khz = (int)(v->dppclk * 1000); + context->dppclk_div = (int)(v->dispclk_dppclk_ratio) == 2; + + for (i = 0, input_idx = 0; i < pool->pipe_count; i++) { + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; + + /* skip inactive pipe */ + if (!pipe->stream) + continue; + /* skip all but first of split pipes */ + if (pipe->top_pipe && pipe->top_pipe->surface == pipe->surface) + continue; + + pipe->pipe_dlg_param.vupdate_width = v->v_update_width[input_idx]; + pipe->pipe_dlg_param.vupdate_offset = v->v_update_offset[input_idx]; + pipe->pipe_dlg_param.vready_offset = v->v_ready_offset[input_idx]; + pipe->pipe_dlg_param.vstartup_start = v->v_startup[input_idx]; + + pipe->pipe_dlg_param.htotal = pipe->stream->public.timing.h_total; + pipe->pipe_dlg_param.vtotal = pipe->stream->public.timing.v_total; + vesa_sync_start = pipe->stream->public.timing.v_addressable + + pipe->stream->public.timing.v_border_bottom + + pipe->stream->public.timing.v_front_porch; + + asic_blank_end = (pipe->stream->public.timing.v_total - + vesa_sync_start - + pipe->stream->public.timing.v_border_top) + * (pipe->stream->public.timing.flags.INTERLACE ? 1 : 0); + + asic_blank_start = asic_blank_end + + (pipe->stream->public.timing.v_border_top + + pipe->stream->public.timing.v_addressable + + pipe->stream->public.timing.v_border_bottom) + * (pipe->stream->public.timing.flags.INTERLACE ? 1 : 0); + + pipe->pipe_dlg_param.vblank_start = asic_blank_start; + pipe->pipe_dlg_param.vblank_end = asic_blank_end; + + if (pipe->surface) { + struct pipe_ctx *hsplit_pipe = pipe->bottom_pipe; + + if (v->dpp_per_plane[input_idx] == 2 || + (pipe->stream->public.timing.timing_3d_format == TIMING_3D_FORMAT_TOP_AND_BOTTOM || + pipe->stream->public.timing.timing_3d_format == TIMING_3D_FORMAT_SIDE_BY_SIDE)) { + if (hsplit_pipe && hsplit_pipe->surface == pipe->surface) { + /* update previously split pipe */ + hsplit_pipe->pipe_dlg_param.vupdate_width = v->v_update_width[input_idx]; + hsplit_pipe->pipe_dlg_param.vupdate_offset = v->v_update_offset[input_idx]; + hsplit_pipe->pipe_dlg_param.vready_offset = v->v_ready_offset[input_idx]; + hsplit_pipe->pipe_dlg_param.vstartup_start = v->v_startup[input_idx]; + + hsplit_pipe->pipe_dlg_param.htotal = pipe->stream->public.timing.h_total; + hsplit_pipe->pipe_dlg_param.vtotal = pipe->stream->public.timing.v_total; + hsplit_pipe->pipe_dlg_param.vblank_start = pipe->pipe_dlg_param.vblank_start; + hsplit_pipe->pipe_dlg_param.vblank_end = pipe->pipe_dlg_param.vblank_end; + } else { + /* pipe not split previously needs split */ + hsplit_pipe = find_idle_secondary_pipe(&context->res_ctx, pool); + ASSERT(hsplit_pipe); + split_stream_across_pipes( + &context->res_ctx, pool, + pipe, hsplit_pipe); + } + + dcn_bw_calc_rq_dlg_ttu(dc, v, hsplit_pipe); + } else if (hsplit_pipe && hsplit_pipe->surface == pipe->surface) { + /* merge previously split pipe */ + if (pipe->bottom_pipe->bottom_pipe) + pipe->bottom_pipe->bottom_pipe->top_pipe = pipe; + memset(pipe->bottom_pipe, 0, sizeof(*pipe->bottom_pipe)); + pipe->bottom_pipe = pipe->bottom_pipe->bottom_pipe; + resource_build_scaling_params(pipe); + } + /* for now important to do this after pipe split for building e2e params */ + dcn_bw_calc_rq_dlg_ttu(dc, v, pipe); + } + + input_idx++; + } + if (dc->public.debug.use_dml_wm) + dcn_dml_wm_override(v, (struct display_mode_lib *) + &dc->dml, context, pool); + } + + kernel_fpu_end(); + return v->voltage_level != 5; +} + +unsigned int dcn_find_normalized_clock_vdd_Level( + const struct core_dc *dc, + enum dm_pp_clock_type clocks_type, + int clocks_in_khz) +{ + int vdd_level = dcn_bw_v_min0p65; + + if (clocks_in_khz == 0)/*todo some clock not in the considerations*/ + return vdd_level; + + switch (clocks_type) { + case DM_PP_CLOCK_TYPE_DISPLAY_CLK: + if (clocks_in_khz > dc->dcn_soc.max_dispclk_vmax0p9*1000) { + vdd_level = dcn_bw_v_max0p91; + BREAK_TO_DEBUGGER(); + } else if (clocks_in_khz > dc->dcn_soc.max_dispclk_vnom0p8*1000) { + vdd_level = dcn_bw_v_max0p9; + } else if (clocks_in_khz > dc->dcn_soc.max_dispclk_vmid0p72*1000) { + vdd_level = dcn_bw_v_nom0p8; + } else if (clocks_in_khz > dc->dcn_soc.max_dispclk_vmin0p65*1000) { + vdd_level = dcn_bw_v_mid0p72; + } else + vdd_level = dcn_bw_v_min0p65; + break; + case DM_PP_CLOCK_TYPE_DISPLAYPHYCLK: + if (clocks_in_khz > dc->dcn_soc.phyclkv_max0p9*1000) { + vdd_level = dcn_bw_v_max0p91; + BREAK_TO_DEBUGGER(); + } else if (clocks_in_khz > dc->dcn_soc.phyclkv_nom0p8*1000) { + vdd_level = dcn_bw_v_max0p9; + } else if (clocks_in_khz > dc->dcn_soc.phyclkv_mid0p72*1000) { + vdd_level = dcn_bw_v_nom0p8; + } else if (clocks_in_khz > dc->dcn_soc.phyclkv_min0p65*1000) { + vdd_level = dcn_bw_v_mid0p72; + } else + vdd_level = dcn_bw_v_min0p65; + break; + + case DM_PP_CLOCK_TYPE_DPPCLK: + if (clocks_in_khz > dc->dcn_soc.max_dppclk_vmax0p9*1000) { + vdd_level = dcn_bw_v_max0p91; + BREAK_TO_DEBUGGER(); + } else if (clocks_in_khz > dc->dcn_soc.max_dppclk_vnom0p8*1000) { + vdd_level = dcn_bw_v_max0p9; + } else if (clocks_in_khz > dc->dcn_soc.max_dppclk_vmid0p72*1000) { + vdd_level = dcn_bw_v_nom0p8; + } else if (clocks_in_khz > dc->dcn_soc.max_dppclk_vmin0p65*1000) { + vdd_level = dcn_bw_v_mid0p72; + } else + vdd_level = dcn_bw_v_min0p65; + break; + + case DM_PP_CLOCK_TYPE_MEMORY_CLK: + { + unsigned factor = (ddr4_dram_factor_single_Channel * dc->dcn_soc.number_of_channels); + if (clocks_in_khz > dc->dcn_soc.fabric_and_dram_bandwidth_vmax0p9*1000000/factor) { + vdd_level = dcn_bw_v_max0p91; + BREAK_TO_DEBUGGER(); + } else if (clocks_in_khz > dc->dcn_soc.fabric_and_dram_bandwidth_vnom0p8*1000000/factor) { + vdd_level = dcn_bw_v_max0p9; + } else if (clocks_in_khz > dc->dcn_soc.fabric_and_dram_bandwidth_vmid0p72*1000000/factor) { + vdd_level = dcn_bw_v_nom0p8; + } else if (clocks_in_khz > dc->dcn_soc.fabric_and_dram_bandwidth_vmin0p65*1000000/factor) { + vdd_level = dcn_bw_v_mid0p72; + } else + vdd_level = dcn_bw_v_min0p65; + } + break; + + case DM_PP_CLOCK_TYPE_DCFCLK: + if (clocks_in_khz > dc->dcn_soc.dcfclkv_max0p9*1000) { + vdd_level = dcn_bw_v_max0p91; + BREAK_TO_DEBUGGER(); + } else if (clocks_in_khz > dc->dcn_soc.dcfclkv_nom0p8*1000) { + vdd_level = dcn_bw_v_max0p9; + } else if (clocks_in_khz > dc->dcn_soc.dcfclkv_mid0p72*1000) { + vdd_level = dcn_bw_v_nom0p8; + } else if (clocks_in_khz > dc->dcn_soc.dcfclkv_min0p65*1000) { + vdd_level = dcn_bw_v_mid0p72; + } else + vdd_level = dcn_bw_v_min0p65; + break; + + default: + break; + } + return vdd_level; +} + +unsigned int dcn_find_dcfclk_suits_all( + const struct core_dc *dc, + struct clocks_value *clocks) +{ + unsigned vdd_level, vdd_level_temp; + unsigned dcf_clk; + + /*find a common supported voltage level*/ + vdd_level = dcn_find_normalized_clock_vdd_Level( + dc, DM_PP_CLOCK_TYPE_DISPLAY_CLK, clocks->dispclk_in_khz); + vdd_level_temp = dcn_find_normalized_clock_vdd_Level( + dc, DM_PP_CLOCK_TYPE_DISPLAYPHYCLK, clocks->phyclk_in_khz); + + vdd_level = dcn_bw_max(vdd_level, vdd_level_temp); + vdd_level_temp = dcn_find_normalized_clock_vdd_Level( + dc, DM_PP_CLOCK_TYPE_DPPCLK, clocks->dppclk_in_khz); + vdd_level = dcn_bw_max(vdd_level, vdd_level_temp); + + vdd_level_temp = dcn_find_normalized_clock_vdd_Level( + dc, DM_PP_CLOCK_TYPE_MEMORY_CLK, clocks->dcfclock_in_khz); + vdd_level = dcn_bw_max(vdd_level, vdd_level_temp); + vdd_level_temp = dcn_find_normalized_clock_vdd_Level( + dc, DM_PP_CLOCK_TYPE_DCFCLK, clocks->dcfclock_in_khz); + + /*find that level conresponding dcfclk*/ + vdd_level = dcn_bw_max(vdd_level, vdd_level_temp); + if (vdd_level == dcn_bw_v_max0p91) { + BREAK_TO_DEBUGGER(); + dcf_clk = dc->dcn_soc.dcfclkv_max0p9*1000; + } else if (vdd_level == dcn_bw_v_max0p9) + dcf_clk = dc->dcn_soc.dcfclkv_max0p9*1000; + else if (vdd_level == dcn_bw_v_nom0p8) + dcf_clk = dc->dcn_soc.dcfclkv_nom0p8*1000; + else if (vdd_level == dcn_bw_v_mid0p72) + dcf_clk = dc->dcn_soc.dcfclkv_mid0p72*1000; + else + dcf_clk = dc->dcn_soc.dcfclkv_min0p65*1000; + + dm_logger_write(dc->ctx->logger, LOG_HW_MARKS, + "\tdcf_clk for voltage = %d\n", dcf_clk); + return dcf_clk; +} + +void dcn_bw_update_from_pplib(struct core_dc *dc) +{ + struct dc_context *ctx = dc->ctx; + struct dm_pp_clock_levels_with_latency clks = {0}; + struct dm_pp_clock_levels_with_voltage clks2 = {0}; + + kernel_fpu_begin(); + dc->dcn_soc.number_of_channels = dc->ctx->asic_id.vram_width / ddr4_dram_width; + ASSERT(dc->dcn_soc.number_of_channels && dc->dcn_soc.number_of_channels < 3); + if (dc->dcn_soc.number_of_channels == 0)/*old sbios bug*/ + dc->dcn_soc.number_of_channels = 2; + + if (dm_pp_get_clock_levels_by_type_with_voltage( + ctx, DM_PP_CLOCK_TYPE_DISPLAY_CLK, &clks2) && + clks2.num_levels >= 3) { + dc->dcn_soc.max_dispclk_vmin0p65 = clks2.data[0].clocks_in_khz / 1000.0; + dc->dcn_soc.max_dispclk_vmid0p72 = clks2.data[clks2.num_levels - 3].clocks_in_khz / 1000.0; + dc->dcn_soc.max_dispclk_vnom0p8 = clks2.data[clks2.num_levels - 2].clocks_in_khz / 1000.0; + dc->dcn_soc.max_dispclk_vmax0p9 = clks2.data[clks2.num_levels - 1].clocks_in_khz / 1000.0; + } else + BREAK_TO_DEBUGGER(); +/* + if (dm_pp_get_clock_levels_by_type_with_latency( + ctx, DM_PP_CLOCK_TYPE_MEMORY_CLK, &clks) && + clks.num_levels != 0) { + //this is to get DRAM data_rate + //FabricAndDRAMBandwidth = min(64*FCLK , Data rate * single_Channel_Width * number of channels); + }*/ + if (dm_pp_get_clock_levels_by_type_with_latency( + ctx, DM_PP_CLOCK_TYPE_FCLK, &clks) && + clks.num_levels != 0) { + ASSERT(clks.num_levels >= 3); + dc->dcn_soc.fabric_and_dram_bandwidth_vmin0p65 = dc->dcn_soc.number_of_channels * + (clks.data[0].clocks_in_khz / 1000.0) * ddr4_dram_factor_single_Channel / 1000.0; + if (clks.num_levels > 2) { + dc->dcn_soc.fabric_and_dram_bandwidth_vmid0p72 = dc->dcn_soc.number_of_channels * + (clks.data[clks.num_levels - 3].clocks_in_khz / 1000.0) * ddr4_dram_factor_single_Channel / 1000.0; + } else { + dc->dcn_soc.fabric_and_dram_bandwidth_vmid0p72 = dc->dcn_soc.number_of_channels * + (clks.data[clks.num_levels - 2].clocks_in_khz / 1000.0) * ddr4_dram_factor_single_Channel / 1000.0; + } + dc->dcn_soc.fabric_and_dram_bandwidth_vnom0p8 = dc->dcn_soc.number_of_channels * + (clks.data[clks.num_levels - 2].clocks_in_khz / 1000.0) * ddr4_dram_factor_single_Channel / 1000.0; + dc->dcn_soc.fabric_and_dram_bandwidth_vmax0p9 = dc->dcn_soc.number_of_channels * + (clks.data[clks.num_levels - 1].clocks_in_khz / 1000.0) * ddr4_dram_factor_single_Channel / 1000.0; + } else + BREAK_TO_DEBUGGER(); + if (dm_pp_get_clock_levels_by_type_with_latency( + ctx, DM_PP_CLOCK_TYPE_DCFCLK, &clks) && + clks.num_levels >= 3) { + dc->dcn_soc.dcfclkv_min0p65 = clks.data[0].clocks_in_khz / 1000.0; + dc->dcn_soc.dcfclkv_mid0p72 = clks.data[clks.num_levels - 3].clocks_in_khz / 1000.0; + dc->dcn_soc.dcfclkv_nom0p8 = clks.data[clks.num_levels - 2].clocks_in_khz / 1000.0; + dc->dcn_soc.dcfclkv_max0p9 = clks.data[clks.num_levels - 1].clocks_in_khz / 1000.0; + } else + BREAK_TO_DEBUGGER(); + if (dm_pp_get_clock_levels_by_type_with_voltage( + ctx, DM_PP_CLOCK_TYPE_DISPLAYPHYCLK, &clks2) && + clks2.num_levels >= 3) { + dc->dcn_soc.phyclkv_min0p65 = clks2.data[0].clocks_in_khz / 1000.0; + dc->dcn_soc.phyclkv_mid0p72 = clks2.data[clks2.num_levels - 3].clocks_in_khz / 1000.0; + dc->dcn_soc.phyclkv_nom0p8 = clks2.data[clks2.num_levels - 2].clocks_in_khz / 1000.0; + dc->dcn_soc.phyclkv_max0p9 = clks2.data[clks2.num_levels - 1].clocks_in_khz / 1000.0; + } else + BREAK_TO_DEBUGGER(); + if (dm_pp_get_clock_levels_by_type_with_latency( + ctx, DM_PP_CLOCK_TYPE_DPPCLK, &clks) && + clks.num_levels >= 3) { + dc->dcn_soc.max_dppclk_vmin0p65 = clks.data[0].clocks_in_khz / 1000.0; + dc->dcn_soc.max_dppclk_vmid0p72 = clks.data[clks.num_levels - 3].clocks_in_khz / 1000.0; + dc->dcn_soc.max_dppclk_vnom0p8 = clks.data[clks.num_levels - 2].clocks_in_khz / 1000.0; + dc->dcn_soc.max_dppclk_vmax0p9 = clks.data[clks.num_levels - 1].clocks_in_khz / 1000.0; + } + + if (dm_pp_get_clock_levels_by_type_with_latency( + ctx, DM_PP_CLOCK_TYPE_SOCCLK, &clks) && + clks.num_levels >= 3) { + dc->dcn_soc.socclk = clks.data[0].clocks_in_khz / 1000.0; + } else + BREAK_TO_DEBUGGER(); + kernel_fpu_end(); +} + +void dcn_bw_notify_pplib_of_wm_ranges(struct core_dc *dc) +{ + struct dm_pp_wm_sets_with_clock_ranges_soc15 clk_ranges = {0}; + int max_fclk_khz, nom_fclk_khz, min_fclk_khz, max_dcfclk_khz, + nom_dcfclk_khz, min_dcfclk_khz, socclk_khz; + const int overdrive = 5000000; /* 5 GHz to cover Overdrive */ + unsigned factor = (ddr4_dram_factor_single_Channel * dc->dcn_soc.number_of_channels); + + kernel_fpu_begin(); + max_fclk_khz = dc->dcn_soc.fabric_and_dram_bandwidth_vmax0p9 * 1000000 / factor; + nom_fclk_khz = dc->dcn_soc.fabric_and_dram_bandwidth_vnom0p8 * 1000000 / factor; + min_fclk_khz = dc->dcn_soc.fabric_and_dram_bandwidth_vmin0p65 * 1000000 / factor; + max_dcfclk_khz = dc->dcn_soc.dcfclkv_max0p9 * 1000; + nom_dcfclk_khz = dc->dcn_soc.dcfclkv_nom0p8 * 1000; + min_dcfclk_khz = dc->dcn_soc.dcfclkv_min0p65 * 1000; + socclk_khz = dc->dcn_soc.socclk * 1000; + kernel_fpu_end(); + + /* Now notify PPLib/SMU about which Watermarks sets they should select + * depending on DPM state they are in. And update BW MGR GFX Engine and + * Memory clock member variables for Watermarks calculations for each + * Watermark Set + */ + /* SOCCLK does not affect anytihng but writeback for DCN so for now we dont + * care what the value is, hence min to overdrive level + */ + clk_ranges.num_wm_dmif_sets = 4; + clk_ranges.num_wm_mcif_sets = 4; + clk_ranges.wm_dmif_clocks_ranges[0].wm_set_id = WM_SET_A; + clk_ranges.wm_dmif_clocks_ranges[0].wm_min_dcfclk_clk_in_khz = min_dcfclk_khz; + clk_ranges.wm_dmif_clocks_ranges[0].wm_max_dcfclk_clk_in_khz = nom_dcfclk_khz - 1; + clk_ranges.wm_dmif_clocks_ranges[0].wm_min_memg_clk_in_khz = min_fclk_khz; + clk_ranges.wm_dmif_clocks_ranges[0].wm_max_mem_clk_in_khz = nom_fclk_khz - 1; + clk_ranges.wm_mcif_clocks_ranges[0].wm_set_id = WM_SET_A; + clk_ranges.wm_mcif_clocks_ranges[0].wm_min_socclk_clk_in_khz = socclk_khz; + clk_ranges.wm_mcif_clocks_ranges[0].wm_max_socclk_clk_in_khz = overdrive; + clk_ranges.wm_mcif_clocks_ranges[0].wm_min_memg_clk_in_khz = min_fclk_khz; + clk_ranges.wm_mcif_clocks_ranges[0].wm_max_mem_clk_in_khz = nom_fclk_khz - 1; + + clk_ranges.wm_dmif_clocks_ranges[1].wm_set_id = WM_SET_B; + clk_ranges.wm_dmif_clocks_ranges[1].wm_min_dcfclk_clk_in_khz = min_dcfclk_khz; + clk_ranges.wm_dmif_clocks_ranges[1].wm_max_dcfclk_clk_in_khz = nom_dcfclk_khz - 1; + clk_ranges.wm_dmif_clocks_ranges[1].wm_min_memg_clk_in_khz = nom_fclk_khz; + clk_ranges.wm_dmif_clocks_ranges[1].wm_max_mem_clk_in_khz = max_fclk_khz; + clk_ranges.wm_mcif_clocks_ranges[1].wm_set_id = WM_SET_B; + clk_ranges.wm_mcif_clocks_ranges[1].wm_min_socclk_clk_in_khz = socclk_khz; + clk_ranges.wm_mcif_clocks_ranges[1].wm_max_socclk_clk_in_khz = overdrive; + clk_ranges.wm_mcif_clocks_ranges[1].wm_min_memg_clk_in_khz = nom_fclk_khz; + clk_ranges.wm_mcif_clocks_ranges[1].wm_max_mem_clk_in_khz = max_fclk_khz; + + + clk_ranges.wm_dmif_clocks_ranges[2].wm_set_id = WM_SET_C; + clk_ranges.wm_dmif_clocks_ranges[2].wm_min_dcfclk_clk_in_khz = nom_dcfclk_khz; + clk_ranges.wm_dmif_clocks_ranges[2].wm_max_dcfclk_clk_in_khz = max_dcfclk_khz; + clk_ranges.wm_dmif_clocks_ranges[2].wm_min_memg_clk_in_khz = nom_fclk_khz; + clk_ranges.wm_dmif_clocks_ranges[2].wm_max_mem_clk_in_khz = max_fclk_khz; + clk_ranges.wm_mcif_clocks_ranges[2].wm_set_id = WM_SET_C; + clk_ranges.wm_mcif_clocks_ranges[2].wm_min_socclk_clk_in_khz = socclk_khz; + clk_ranges.wm_mcif_clocks_ranges[2].wm_max_socclk_clk_in_khz = overdrive; + clk_ranges.wm_mcif_clocks_ranges[2].wm_min_memg_clk_in_khz = nom_fclk_khz; + clk_ranges.wm_mcif_clocks_ranges[2].wm_max_mem_clk_in_khz = max_fclk_khz; + + clk_ranges.wm_dmif_clocks_ranges[3].wm_set_id = WM_SET_D; + clk_ranges.wm_dmif_clocks_ranges[3].wm_min_dcfclk_clk_in_khz = max_dcfclk_khz + 1; + clk_ranges.wm_dmif_clocks_ranges[3].wm_max_dcfclk_clk_in_khz = overdrive; + clk_ranges.wm_dmif_clocks_ranges[3].wm_min_memg_clk_in_khz = max_fclk_khz + 1; + clk_ranges.wm_dmif_clocks_ranges[3].wm_max_mem_clk_in_khz = overdrive; + clk_ranges.wm_mcif_clocks_ranges[3].wm_set_id = WM_SET_D; + clk_ranges.wm_mcif_clocks_ranges[3].wm_min_socclk_clk_in_khz = socclk_khz; + clk_ranges.wm_mcif_clocks_ranges[3].wm_max_socclk_clk_in_khz = overdrive; + clk_ranges.wm_mcif_clocks_ranges[3].wm_min_memg_clk_in_khz = max_fclk_khz + 1; + clk_ranges.wm_mcif_clocks_ranges[3].wm_max_mem_clk_in_khz = overdrive; + + /* Notify PP Lib/SMU which Watermarks to use for which clock ranges */ + dm_pp_notify_wm_clock_changes_soc15(dc->ctx, &clk_ranges); +} + +void dcn_bw_sync_calcs_and_dml(struct core_dc *dc) +{ + kernel_fpu_begin(); + dc->dml.soc.vmin.socclk_mhz = dc->dcn_soc.socclk; + dc->dml.soc.vmid.socclk_mhz = dc->dcn_soc.socclk; + dc->dml.soc.vnom.socclk_mhz = dc->dcn_soc.socclk; + dc->dml.soc.vmax.socclk_mhz = dc->dcn_soc.socclk; + + dc->dml.soc.vmin.dcfclk_mhz = dc->dcn_soc.dcfclkv_min0p65; + dc->dml.soc.vmid.dcfclk_mhz = dc->dcn_soc.dcfclkv_mid0p72; + dc->dml.soc.vnom.dcfclk_mhz = dc->dcn_soc.dcfclkv_nom0p8; + dc->dml.soc.vmax.dcfclk_mhz = dc->dcn_soc.dcfclkv_max0p9; + + dc->dml.soc.vmin.dispclk_mhz = dc->dcn_soc.max_dispclk_vmin0p65; + dc->dml.soc.vmid.dispclk_mhz = dc->dcn_soc.max_dispclk_vmid0p72; + dc->dml.soc.vnom.dispclk_mhz = dc->dcn_soc.max_dispclk_vnom0p8; + dc->dml.soc.vmax.dispclk_mhz = dc->dcn_soc.max_dispclk_vmax0p9; + + dc->dml.soc.vmin.dppclk_mhz = dc->dcn_soc.max_dppclk_vmin0p65; + dc->dml.soc.vmid.dppclk_mhz = dc->dcn_soc.max_dppclk_vmid0p72; + dc->dml.soc.vnom.dppclk_mhz = dc->dcn_soc.max_dppclk_vnom0p8; + dc->dml.soc.vmax.dppclk_mhz = dc->dcn_soc.max_dppclk_vmax0p9; + + dc->dml.soc.vmin.phyclk_mhz = dc->dcn_soc.phyclkv_min0p65; + dc->dml.soc.vmid.phyclk_mhz = dc->dcn_soc.phyclkv_mid0p72; + dc->dml.soc.vnom.phyclk_mhz = dc->dcn_soc.phyclkv_nom0p8; + dc->dml.soc.vmax.phyclk_mhz = dc->dcn_soc.phyclkv_max0p9; + + dc->dml.soc.vmin.dram_bw_per_chan_gbps = dc->dcn_soc.fabric_and_dram_bandwidth_vmin0p65; + dc->dml.soc.vmid.dram_bw_per_chan_gbps = dc->dcn_soc.fabric_and_dram_bandwidth_vmid0p72; + dc->dml.soc.vnom.dram_bw_per_chan_gbps = dc->dcn_soc.fabric_and_dram_bandwidth_vnom0p8; + dc->dml.soc.vmax.dram_bw_per_chan_gbps = dc->dcn_soc.fabric_and_dram_bandwidth_vmax0p9; + + dc->dml.soc.sr_exit_time_us = dc->dcn_soc.sr_exit_time; + dc->dml.soc.sr_enter_plus_exit_time_us = dc->dcn_soc.sr_enter_plus_exit_time; + dc->dml.soc.urgent_latency_us = dc->dcn_soc.urgent_latency; + dc->dml.soc.writeback_latency_us = dc->dcn_soc.write_back_latency; + dc->dml.soc.ideal_dram_bw_after_urgent_percent = + dc->dcn_soc.percent_of_ideal_drambw_received_after_urg_latency; + dc->dml.soc.max_request_size_bytes = dc->dcn_soc.max_request_size; + dc->dml.soc.downspread_percent = dc->dcn_soc.downspreading; + dc->dml.soc.round_trip_ping_latency_dcfclk_cycles = + dc->dcn_soc.round_trip_ping_latency_cycles; + dc->dml.soc.urgent_out_of_order_return_per_channel_bytes = + dc->dcn_soc.urgent_out_of_order_return_per_channel; + dc->dml.soc.num_chans = dc->dcn_soc.number_of_channels; + dc->dml.soc.vmm_page_size_bytes = dc->dcn_soc.vmm_page_size; + dc->dml.soc.dram_clock_change_latency_us = dc->dcn_soc.dram_clock_change_latency; + dc->dml.soc.return_bus_width_bytes = dc->dcn_soc.return_bus_width; + + dc->dml.ip.rob_buffer_size_kbytes = dc->dcn_ip.rob_buffer_size_in_kbyte; + dc->dml.ip.det_buffer_size_kbytes = dc->dcn_ip.det_buffer_size_in_kbyte; + dc->dml.ip.dpp_output_buffer_pixels = dc->dcn_ip.dpp_output_buffer_pixels; + dc->dml.ip.opp_output_buffer_lines = dc->dcn_ip.opp_output_buffer_lines; + dc->dml.ip.pixel_chunk_size_kbytes = dc->dcn_ip.pixel_chunk_size_in_kbyte; + dc->dml.ip.pte_enable = dc->dcn_ip.pte_enable == dcn_bw_yes; + dc->dml.ip.pte_chunk_size_kbytes = dc->dcn_ip.pte_chunk_size; + dc->dml.ip.meta_chunk_size_kbytes = dc->dcn_ip.meta_chunk_size; + dc->dml.ip.writeback_chunk_size_kbytes = dc->dcn_ip.writeback_chunk_size; + dc->dml.ip.line_buffer_size_bits = dc->dcn_ip.line_buffer_size; + dc->dml.ip.max_line_buffer_lines = dc->dcn_ip.max_line_buffer_lines; + dc->dml.ip.IsLineBufferBppFixed = dc->dcn_ip.is_line_buffer_bpp_fixed == dcn_bw_yes; + dc->dml.ip.LineBufferFixedBpp = dc->dcn_ip.line_buffer_fixed_bpp; + dc->dml.ip.writeback_luma_buffer_size_kbytes = dc->dcn_ip.writeback_luma_buffer_size; + dc->dml.ip.writeback_chroma_buffer_size_kbytes = dc->dcn_ip.writeback_chroma_buffer_size; + dc->dml.ip.max_num_dpp = dc->dcn_ip.max_num_dpp; + dc->dml.ip.max_num_wb = dc->dcn_ip.max_num_writeback; + dc->dml.ip.max_dchub_pscl_bw_pix_per_clk = dc->dcn_ip.max_dchub_topscl_throughput; + dc->dml.ip.max_pscl_lb_bw_pix_per_clk = dc->dcn_ip.max_pscl_tolb_throughput; + dc->dml.ip.max_lb_vscl_bw_pix_per_clk = dc->dcn_ip.max_lb_tovscl_throughput; + dc->dml.ip.max_vscl_hscl_bw_pix_per_clk = dc->dcn_ip.max_vscl_tohscl_throughput; + dc->dml.ip.max_hscl_ratio = dc->dcn_ip.max_hscl_ratio; + dc->dml.ip.max_vscl_ratio = dc->dcn_ip.max_vscl_ratio; + dc->dml.ip.max_hscl_taps = dc->dcn_ip.max_hscl_taps; + dc->dml.ip.max_vscl_taps = dc->dcn_ip.max_vscl_taps; + /*pte_buffer_size_in_requests missing in dml*/ + dc->dml.ip.dispclk_ramp_margin_percent = dc->dcn_ip.dispclk_ramping_margin; + dc->dml.ip.underscan_factor = dc->dcn_ip.under_scan_factor; + dc->dml.ip.max_inter_dcn_tile_repeaters = dc->dcn_ip.max_inter_dcn_tile_repeaters; + dc->dml.ip.can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one = + dc->dcn_ip.can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one == dcn_bw_yes; + dc->dml.ip.bug_forcing_LC_req_same_size_fixed = + dc->dcn_ip.bug_forcing_luma_and_chroma_request_to_same_size_fixed == dcn_bw_yes; + dc->dml.ip.dcfclk_cstate_latency = dc->dcn_ip.dcfclk_cstate_latency; + kernel_fpu_end(); +} diff --git a/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h b/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h new file mode 100644 index 000000000000..499bc1127696 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h @@ -0,0 +1,629 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +/** + * Bandwidth and Watermark calculations interface. + * (Refer to "DCEx_mode_support.xlsm" from Perforce.) + */ +#ifndef __DCN_CALCS_H__ +#define __DCN_CALCS_H__ + +#include "bw_fixed.h" +#include "display_clock.h" +#include "../dml/display_mode_lib.h" + +struct core_dc; +struct validate_context; + +/******************************************************************************* + * DCN data structures. + ******************************************************************************/ + +#define number_of_planes 6 +#define number_of_planes_minus_one 5 +#define number_of_states 4 +#define number_of_states_plus_one 5 + +#define ddr4_dram_width 64 +#define ddr4_dram_factor_single_Channel 16 +enum dcn_bw_defs { + dcn_bw_v_min0p65, + dcn_bw_v_mid0p72, + dcn_bw_v_nom0p8, + dcn_bw_v_max0p9, + dcn_bw_v_max0p91, + dcn_bw_no_support = 5, + dcn_bw_yes, + dcn_bw_hor, + dcn_bw_vert, + dcn_bw_override, + dcn_bw_rgb_sub_64, + dcn_bw_rgb_sub_32, + dcn_bw_rgb_sub_16, + dcn_bw_no, + dcn_bw_sw_linear, + dcn_bw_sw_4_kb_d, + dcn_bw_sw_4_kb_d_x, + dcn_bw_sw_64_kb_d, + dcn_bw_sw_64_kb_d_t, + dcn_bw_sw_64_kb_d_x, + dcn_bw_sw_var_d, + dcn_bw_sw_var_d_x, + dcn_bw_yuv420_sub_8, + dcn_bw_sw_4_kb_s, + dcn_bw_sw_4_kb_s_x, + dcn_bw_sw_64_kb_s, + dcn_bw_sw_64_kb_s_t, + dcn_bw_sw_64_kb_s_x, + dcn_bw_writeback, + dcn_bw_444, + dcn_bw_dp, + dcn_bw_420, + dcn_bw_hdmi, + dcn_bw_sw_var_s, + dcn_bw_sw_var_s_x, + dcn_bw_yuv420_sub_10, + dcn_bw_supported_in_v_active, + dcn_bw_supported_in_v_blank, + dcn_bw_not_supported, + dcn_bw_na, +}; + +/*bounding box parameters*/ +/*mode parameters*/ +/*system configuration*/ +/* display configuration*/ +struct dcn_bw_internal_vars { + float voltage[number_of_states_plus_one + 1]; + float max_dispclk[number_of_states_plus_one + 1]; + float max_dppclk[number_of_states_plus_one + 1]; + float dcfclk_per_state[number_of_states_plus_one + 1]; + float phyclk_per_state[number_of_states_plus_one + 1]; + float fabric_and_dram_bandwidth_per_state[number_of_states_plus_one + 1]; + float sr_exit_time; + float sr_enter_plus_exit_time; + float dram_clock_change_latency; + float urgent_latency; + float write_back_latency; + float percent_of_ideal_drambw_received_after_urg_latency; + float dcfclkv_max0p9; + float dcfclkv_nom0p8; + float dcfclkv_mid0p72; + float dcfclkv_min0p65; + float max_dispclk_vmax0p9; + float max_dppclk_vmax0p9; + float max_dispclk_vnom0p8; + float max_dppclk_vnom0p8; + float max_dispclk_vmid0p72; + float max_dppclk_vmid0p72; + float max_dispclk_vmin0p65; + float max_dppclk_vmin0p65; + float socclk; + float fabric_and_dram_bandwidth_vmax0p9; + float fabric_and_dram_bandwidth_vnom0p8; + float fabric_and_dram_bandwidth_vmid0p72; + float fabric_and_dram_bandwidth_vmin0p65; + float round_trip_ping_latency_cycles; + float urgent_out_of_order_return_per_channel; + float number_of_channels; + float vmm_page_size; + float return_bus_width; + float rob_buffer_size_in_kbyte; + float det_buffer_size_in_kbyte; + float dpp_output_buffer_pixels; + float opp_output_buffer_lines; + float pixel_chunk_size_in_kbyte; + float pte_chunk_size; + float meta_chunk_size; + float writeback_chunk_size; + enum dcn_bw_defs odm_capability; + enum dcn_bw_defs dsc_capability; + float line_buffer_size; + enum dcn_bw_defs is_line_buffer_bpp_fixed; + float line_buffer_fixed_bpp; + float max_line_buffer_lines; + float writeback_luma_buffer_size; + float writeback_chroma_buffer_size; + float max_num_dpp; + float max_num_writeback; + float max_dchub_topscl_throughput; + float max_pscl_tolb_throughput; + float max_lb_tovscl_throughput; + float max_vscl_tohscl_throughput; + float max_hscl_ratio; + float max_vscl_ratio; + float max_hscl_taps; + float max_vscl_taps; + float under_scan_factor; + float phyclkv_max0p9; + float phyclkv_nom0p8; + float phyclkv_mid0p72; + float phyclkv_min0p65; + float pte_buffer_size_in_requests; + float dispclk_ramping_margin; + float downspreading; + float max_inter_dcn_tile_repeaters; + enum dcn_bw_defs can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one; + enum dcn_bw_defs bug_forcing_luma_and_chroma_request_to_same_size_fixed; + int mode; + float viewport_width[number_of_planes_minus_one + 1]; + float htotal[number_of_planes_minus_one + 1]; + float vtotal[number_of_planes_minus_one + 1]; + float v_sync_plus_back_porch[number_of_planes_minus_one + 1]; + float vactive[number_of_planes_minus_one + 1]; + float pixel_clock[number_of_planes_minus_one + 1]; /*MHz*/ + float viewport_height[number_of_planes_minus_one + 1]; + enum dcn_bw_defs dcc_enable[number_of_planes_minus_one + 1]; + float dcc_rate[number_of_planes_minus_one + 1]; + enum dcn_bw_defs source_scan[number_of_planes_minus_one + 1]; + float lb_bit_per_pixel[number_of_planes_minus_one + 1]; + enum dcn_bw_defs source_pixel_format[number_of_planes_minus_one + 1]; + enum dcn_bw_defs source_surface_mode[number_of_planes_minus_one + 1]; + enum dcn_bw_defs output_format[number_of_planes_minus_one + 1]; + enum dcn_bw_defs output[number_of_planes_minus_one + 1]; + float scaler_rec_out_width[number_of_planes_minus_one + 1]; + float scaler_recout_height[number_of_planes_minus_one + 1]; + float underscan_output[number_of_planes_minus_one + 1]; + float interlace_output[number_of_planes_minus_one + 1]; + float override_hta_ps[number_of_planes_minus_one + 1]; + float override_vta_ps[number_of_planes_minus_one + 1]; + float override_hta_pschroma[number_of_planes_minus_one + 1]; + float override_vta_pschroma[number_of_planes_minus_one + 1]; + float urgent_latency_support_us[number_of_planes_minus_one + 1]; + float h_ratio[number_of_planes_minus_one + 1]; + float v_ratio[number_of_planes_minus_one + 1]; + float htaps[number_of_planes_minus_one + 1]; + float vtaps[number_of_planes_minus_one + 1]; + float hta_pschroma[number_of_planes_minus_one + 1]; + float vta_pschroma[number_of_planes_minus_one + 1]; + enum dcn_bw_defs pte_enable; + enum dcn_bw_defs synchronized_vblank; + enum dcn_bw_defs ta_pscalculation; + int voltage_override_level; + int number_of_active_planes; + int voltage_level; + enum dcn_bw_defs immediate_flip_supported; + float dcfclk; + float max_phyclk; + float fabric_and_dram_bandwidth; + float dpp_per_plane_per_ratio[1 + 1][number_of_planes_minus_one + 1]; + enum dcn_bw_defs dispclk_dppclk_support_per_ratio[1 + 1]; + float required_dispclk_per_ratio[1 + 1]; + enum dcn_bw_defs error_message[1 + 1]; + int dispclk_dppclk_ratio; + float dpp_per_plane[number_of_planes_minus_one + 1]; + float det_buffer_size_y[number_of_planes_minus_one + 1]; + float det_buffer_size_c[number_of_planes_minus_one + 1]; + float swath_height_y[number_of_planes_minus_one + 1]; + float swath_height_c[number_of_planes_minus_one + 1]; + enum dcn_bw_defs final_error_message; + float frequency; + float header_line; + float header; + enum dcn_bw_defs voltage_override; + enum dcn_bw_defs allow_different_hratio_vratio; + float acceptable_quality_hta_ps; + float acceptable_quality_vta_ps; + float no_of_dpp[number_of_states_plus_one + 1][1 + 1][number_of_planes_minus_one + 1]; + float swath_width_yper_state[number_of_states_plus_one + 1][1 + 1][number_of_planes_minus_one + 1]; + float swath_height_yper_state[number_of_states_plus_one + 1][1 + 1][number_of_planes_minus_one + 1]; + float swath_height_cper_state[number_of_states_plus_one + 1][1 + 1][number_of_planes_minus_one + 1]; + float urgent_latency_support_us_per_state[number_of_states_plus_one + 1][1 + 1][number_of_planes_minus_one + 1]; + float v_ratio_pre_ywith_immediate_flip[number_of_states_plus_one + 1][1 + 1][number_of_planes_minus_one + 1]; + float v_ratio_pre_cwith_immediate_flip[number_of_states_plus_one + 1][1 + 1][number_of_planes_minus_one + 1]; + float required_prefetch_pixel_data_bw_with_immediate_flip[number_of_states_plus_one + 1][1 + 1][number_of_planes_minus_one + 1]; + float v_ratio_pre_ywithout_immediate_flip[number_of_states_plus_one + 1][1 + 1][number_of_planes_minus_one + 1]; + float v_ratio_pre_cwithout_immediate_flip[number_of_states_plus_one + 1][1 + 1][number_of_planes_minus_one + 1]; + float required_prefetch_pixel_data_bw_without_immediate_flip[number_of_states_plus_one + 1][1 + 1][number_of_planes_minus_one + 1]; + enum dcn_bw_defs prefetch_supported_with_immediate_flip[number_of_states_plus_one + 1][1 + 1]; + enum dcn_bw_defs prefetch_supported_without_immediate_flip[number_of_states_plus_one + 1][1 + 1]; + enum dcn_bw_defs v_ratio_in_prefetch_supported_with_immediate_flip[number_of_states_plus_one + 1][1 + 1]; + enum dcn_bw_defs v_ratio_in_prefetch_supported_without_immediate_flip[number_of_states_plus_one + 1][1 + 1]; + float required_dispclk[number_of_states_plus_one + 1][1 + 1]; + enum dcn_bw_defs dispclk_dppclk_support[number_of_states_plus_one + 1][1 + 1]; + enum dcn_bw_defs total_available_pipes_support[number_of_states_plus_one + 1][1 + 1]; + float total_number_of_active_dpp[number_of_states_plus_one + 1][1 + 1]; + float total_number_of_dcc_active_dpp[number_of_states_plus_one + 1][1 + 1]; + enum dcn_bw_defs urgent_latency_support[number_of_states_plus_one + 1][1 + 1]; + enum dcn_bw_defs mode_support_with_immediate_flip[number_of_states_plus_one + 1][1 + 1]; + enum dcn_bw_defs mode_support_without_immediate_flip[number_of_states_plus_one + 1][1 + 1]; + float return_bw_per_state[number_of_states_plus_one + 1]; + enum dcn_bw_defs dio_support[number_of_states_plus_one + 1]; + float urgent_round_trip_and_out_of_order_latency_per_state[number_of_states_plus_one + 1]; + enum dcn_bw_defs rob_support[number_of_states_plus_one + 1]; + enum dcn_bw_defs bandwidth_support[number_of_states_plus_one + 1]; + float prefetch_bw[number_of_planes_minus_one + 1]; + float meta_pte_bytes_per_frame[number_of_planes_minus_one + 1]; + float meta_row_bytes[number_of_planes_minus_one + 1]; + float dpte_bytes_per_row[number_of_planes_minus_one + 1]; + float prefetch_lines_y[number_of_planes_minus_one + 1]; + float prefetch_lines_c[number_of_planes_minus_one + 1]; + float max_num_sw_y[number_of_planes_minus_one + 1]; + float max_num_sw_c[number_of_planes_minus_one + 1]; + float line_times_for_prefetch[number_of_planes_minus_one + 1]; + float lines_for_meta_pte_with_immediate_flip[number_of_planes_minus_one + 1]; + float lines_for_meta_pte_without_immediate_flip[number_of_planes_minus_one + 1]; + float lines_for_meta_and_dpte_row_with_immediate_flip[number_of_planes_minus_one + 1]; + float lines_for_meta_and_dpte_row_without_immediate_flip[number_of_planes_minus_one + 1]; + float min_dppclk_using_single_dpp[number_of_planes_minus_one + 1]; + float swath_width_ysingle_dpp[number_of_planes_minus_one + 1]; + float byte_per_pixel_in_dety[number_of_planes_minus_one + 1]; + float byte_per_pixel_in_detc[number_of_planes_minus_one + 1]; + float number_of_dpp_required_for_det_and_lb_size[number_of_planes_minus_one + 1]; + float required_phyclk[number_of_planes_minus_one + 1]; + float read256_block_height_y[number_of_planes_minus_one + 1]; + float read256_block_width_y[number_of_planes_minus_one + 1]; + float read256_block_height_c[number_of_planes_minus_one + 1]; + float read256_block_width_c[number_of_planes_minus_one + 1]; + float max_swath_height_y[number_of_planes_minus_one + 1]; + float max_swath_height_c[number_of_planes_minus_one + 1]; + float min_swath_height_y[number_of_planes_minus_one + 1]; + float min_swath_height_c[number_of_planes_minus_one + 1]; + float read_bandwidth[number_of_planes_minus_one + 1]; + float write_bandwidth[number_of_planes_minus_one + 1]; + float pscl_factor[number_of_planes_minus_one + 1]; + float pscl_factor_chroma[number_of_planes_minus_one + 1]; + enum dcn_bw_defs scale_ratio_support; + enum dcn_bw_defs source_format_pixel_and_scan_support; + float total_read_bandwidth_consumed_gbyte_per_second; + float total_write_bandwidth_consumed_gbyte_per_second; + float total_bandwidth_consumed_gbyte_per_second; + enum dcn_bw_defs dcc_enabled_in_any_plane; + float return_bw_todcn_per_state; + float critical_point; + enum dcn_bw_defs writeback_latency_support; + float required_output_bw; + float total_number_of_active_writeback; + enum dcn_bw_defs total_available_writeback_support; + float maximum_swath_width; + float number_of_dpp_required_for_det_size; + float number_of_dpp_required_for_lb_size; + float min_dispclk_using_single_dpp; + float min_dispclk_using_dual_dpp; + enum dcn_bw_defs viewport_size_support; + float swath_width_granularity_y; + float rounded_up_max_swath_size_bytes_y; + float swath_width_granularity_c; + float rounded_up_max_swath_size_bytes_c; + float lines_in_det_luma; + float lines_in_det_chroma; + float effective_lb_latency_hiding_source_lines_luma; + float effective_lb_latency_hiding_source_lines_chroma; + float effective_detlb_lines_luma; + float effective_detlb_lines_chroma; + float projected_dcfclk_deep_sleep; + float meta_req_height_y; + float meta_req_width_y; + float meta_surface_width_y; + float meta_surface_height_y; + float meta_pte_bytes_per_frame_y; + float meta_row_bytes_y; + float macro_tile_block_size_bytes_y; + float macro_tile_block_height_y; + float data_pte_req_height_y; + float data_pte_req_width_y; + float dpte_bytes_per_row_y; + float meta_req_height_c; + float meta_req_width_c; + float meta_surface_width_c; + float meta_surface_height_c; + float meta_pte_bytes_per_frame_c; + float meta_row_bytes_c; + float macro_tile_block_size_bytes_c; + float macro_tile_block_height_c; + float macro_tile_block_width_c; + float data_pte_req_height_c; + float data_pte_req_width_c; + float dpte_bytes_per_row_c; + float v_init_y; + float max_partial_sw_y; + float v_init_c; + float max_partial_sw_c; + float dst_x_after_scaler; + float dst_y_after_scaler; + float time_calc; + float v_update_offset[number_of_planes_minus_one + 1]; + float total_repeater_delay; + float v_update_width[number_of_planes_minus_one + 1]; + float v_ready_offset[number_of_planes_minus_one + 1]; + float time_setup; + float extra_latency; + float maximum_vstartup; + float bw_available_for_immediate_flip; + float total_immediate_flip_bytes[number_of_planes_minus_one + 1]; + float time_for_meta_pte_with_immediate_flip; + float time_for_meta_pte_without_immediate_flip; + float time_for_meta_and_dpte_row_with_immediate_flip; + float time_for_meta_and_dpte_row_without_immediate_flip; + float line_times_to_request_prefetch_pixel_data_with_immediate_flip; + float line_times_to_request_prefetch_pixel_data_without_immediate_flip; + float maximum_read_bandwidth_with_prefetch_with_immediate_flip; + float maximum_read_bandwidth_with_prefetch_without_immediate_flip; + float voltage_level_with_immediate_flip; + float voltage_level_without_immediate_flip; + float total_number_of_active_dpp_per_ratio[1 + 1]; + float byte_per_pix_dety; + float byte_per_pix_detc; + float read256_bytes_block_height_y; + float read256_bytes_block_width_y; + float read256_bytes_block_height_c; + float read256_bytes_block_width_c; + float maximum_swath_height_y; + float maximum_swath_height_c; + float minimum_swath_height_y; + float minimum_swath_height_c; + float swath_width; + float prefetch_bandwidth[number_of_planes_minus_one + 1]; + float v_init_pre_fill_y[number_of_planes_minus_one + 1]; + float v_init_pre_fill_c[number_of_planes_minus_one + 1]; + float max_num_swath_y[number_of_planes_minus_one + 1]; + float max_num_swath_c[number_of_planes_minus_one + 1]; + float prefill_y[number_of_planes_minus_one + 1]; + float prefill_c[number_of_planes_minus_one + 1]; + float v_startup[number_of_planes_minus_one + 1]; + enum dcn_bw_defs allow_dram_clock_change_during_vblank[number_of_planes_minus_one + 1]; + float allow_dram_self_refresh_during_vblank[number_of_planes_minus_one + 1]; + float v_ratio_prefetch_y[number_of_planes_minus_one + 1]; + float v_ratio_prefetch_c[number_of_planes_minus_one + 1]; + float destination_lines_for_prefetch[number_of_planes_minus_one + 1]; + float destination_lines_to_request_vm_inv_blank[number_of_planes_minus_one + 1]; + float destination_lines_to_request_row_in_vblank[number_of_planes_minus_one + 1]; + float min_ttuv_blank[number_of_planes_minus_one + 1]; + float byte_per_pixel_dety[number_of_planes_minus_one + 1]; + float byte_per_pixel_detc[number_of_planes_minus_one + 1]; + float swath_width_y[number_of_planes_minus_one + 1]; + float lines_in_dety[number_of_planes_minus_one + 1]; + float lines_in_dety_rounded_down_to_swath[number_of_planes_minus_one + 1]; + float lines_in_detc[number_of_planes_minus_one + 1]; + float lines_in_detc_rounded_down_to_swath[number_of_planes_minus_one + 1]; + float full_det_buffering_time_y[number_of_planes_minus_one + 1]; + float full_det_buffering_time_c[number_of_planes_minus_one + 1]; + float active_dram_clock_change_latency_margin[number_of_planes_minus_one + 1]; + float v_blank_dram_clock_change_latency_margin[number_of_planes_minus_one + 1]; + float dcfclk_deep_sleep_per_plane[number_of_planes_minus_one + 1]; + float read_bandwidth_plane_luma[number_of_planes_minus_one + 1]; + float read_bandwidth_plane_chroma[number_of_planes_minus_one + 1]; + float display_pipe_line_delivery_time_luma[number_of_planes_minus_one + 1]; + float display_pipe_line_delivery_time_chroma[number_of_planes_minus_one + 1]; + float display_pipe_line_delivery_time_luma_prefetch[number_of_planes_minus_one + 1]; + float display_pipe_line_delivery_time_chroma_prefetch[number_of_planes_minus_one + 1]; + float pixel_pte_bytes_per_row[number_of_planes_minus_one + 1]; + float meta_pte_bytes_frame[number_of_planes_minus_one + 1]; + float meta_row_byte[number_of_planes_minus_one + 1]; + float prefetch_source_lines_y[number_of_planes_minus_one + 1]; + float prefetch_source_lines_c[number_of_planes_minus_one + 1]; + float pscl_throughput[number_of_planes_minus_one + 1]; + float pscl_throughput_chroma[number_of_planes_minus_one + 1]; + float output_bpphdmi[number_of_planes_minus_one + 1]; + float output_bppdp4_lane_hbr[number_of_planes_minus_one + 1]; + float output_bppdp4_lane_hbr2[number_of_planes_minus_one + 1]; + float output_bppdp4_lane_hbr3[number_of_planes_minus_one + 1]; + float max_vstartup_lines[number_of_planes_minus_one + 1]; + float dispclk_with_ramping; + float dispclk_without_ramping; + float dppclk_using_single_dpp_luma; + float dppclk_using_single_dpp; + float dppclk_using_single_dpp_chroma; + enum dcn_bw_defs odm_capable; + float dispclk; + float dppclk; + float return_bandwidth_to_dcn; + enum dcn_bw_defs dcc_enabled_any_plane; + float return_bw; + float critical_compression; + float total_data_read_bandwidth; + float total_active_dpp; + float total_dcc_active_dpp; + float urgent_round_trip_and_out_of_order_latency; + float last_pixel_of_line_extra_watermark; + float data_fabric_line_delivery_time_luma; + float data_fabric_line_delivery_time_chroma; + float urgent_extra_latency; + float urgent_watermark; + float ptemeta_urgent_watermark; + float dram_clock_change_watermark; + float total_active_writeback; + float writeback_dram_clock_change_watermark; + float min_full_det_buffering_time; + float frame_time_for_min_full_det_buffering_time; + float average_read_bandwidth_gbyte_per_second; + float part_of_burst_that_fits_in_rob; + float stutter_burst_time; + float stutter_efficiency_not_including_vblank; + float smallest_vblank; + float v_blank_time; + float stutter_efficiency; + float dcf_clk_deep_sleep; + float stutter_exit_watermark; + float stutter_enter_plus_exit_watermark; + float effective_det_plus_lb_lines_luma; + float urgent_latency_support_us_luma; + float effective_det_plus_lb_lines_chroma; + float urgent_latency_support_us_chroma; + float min_urgent_latency_support_us; + float non_urgent_latency_tolerance; + float block_height256_bytes_y; + float block_height256_bytes_c; + float meta_request_width_y; + float meta_surf_width_y; + float meta_surf_height_y; + float meta_pte_bytes_frame_y; + float meta_row_byte_y; + float macro_tile_size_byte_y; + float macro_tile_height_y; + float pixel_pte_req_height_y; + float pixel_pte_req_width_y; + float pixel_pte_bytes_per_row_y; + float meta_request_width_c; + float meta_surf_width_c; + float meta_surf_height_c; + float meta_pte_bytes_frame_c; + float meta_row_byte_c; + float macro_tile_size_bytes_c; + float macro_tile_height_c; + float pixel_pte_req_height_c; + float pixel_pte_req_width_c; + float pixel_pte_bytes_per_row_c; + float max_partial_swath_y; + float max_partial_swath_c; + float t_calc; + float next_prefetch_mode; + float v_startup_lines; + enum dcn_bw_defs planes_with_room_to_increase_vstartup_prefetch_bw_less_than_active_bw; + enum dcn_bw_defs planes_with_room_to_increase_vstartup_vratio_prefetch_more_than4; + enum dcn_bw_defs planes_with_room_to_increase_vstartup_destination_line_times_for_prefetch_less_than2; + enum dcn_bw_defs v_ratio_prefetch_more_than4; + enum dcn_bw_defs destination_line_times_for_prefetch_less_than2; + float prefetch_mode; + float dstx_after_scaler; + float dsty_after_scaler; + float v_update_offset_pix; + float total_repeater_delay_time; + float v_update_width_pix; + float v_ready_offset_pix; + float t_setup; + float t_wait; + float bandwidth_available_for_immediate_flip; + float tot_immediate_flip_bytes; + float max_rd_bandwidth; + float time_for_fetching_meta_pte; + float time_for_fetching_row_in_vblank; + float lines_to_request_prefetch_pixel_data; + float required_prefetch_pix_data_bw; + enum dcn_bw_defs prefetch_mode_supported; + float active_dp_ps; + float lb_latency_hiding_source_lines_y; + float lb_latency_hiding_source_lines_c; + float effective_lb_latency_hiding_y; + float effective_lb_latency_hiding_c; + float dpp_output_buffer_lines_y; + float dpp_output_buffer_lines_c; + float dppopp_buffering_y; + float max_det_buffering_time_y; + float active_dram_clock_change_latency_margin_y; + float dppopp_buffering_c; + float max_det_buffering_time_c; + float active_dram_clock_change_latency_margin_c; + float writeback_dram_clock_change_latency_margin; + float min_active_dram_clock_change_margin; + float v_blank_of_min_active_dram_clock_change_margin; + float second_min_active_dram_clock_change_margin; + float min_vblank_dram_clock_change_margin; + float dram_clock_change_margin; + float dram_clock_change_support; + float wr_bandwidth; + float max_used_bw; +}; + +struct dcn_soc_bounding_box { + float sr_exit_time; /*us*/ + float sr_enter_plus_exit_time; /*us*/ + float urgent_latency; /*us*/ + float write_back_latency; /*us*/ + float percent_of_ideal_drambw_received_after_urg_latency; /*%*/ + int max_request_size; /*bytes*/ + float dcfclkv_max0p9; /*MHz*/ + float dcfclkv_nom0p8; /*MHz*/ + float dcfclkv_mid0p72; /*MHz*/ + float dcfclkv_min0p65; /*MHz*/ + float max_dispclk_vmax0p9; /*MHz*/ + float max_dispclk_vmid0p72; /*MHz*/ + float max_dispclk_vnom0p8; /*MHz*/ + float max_dispclk_vmin0p65; /*MHz*/ + float max_dppclk_vmax0p9; /*MHz*/ + float max_dppclk_vnom0p8; /*MHz*/ + float max_dppclk_vmid0p72; /*MHz*/ + float max_dppclk_vmin0p65; /*MHz*/ + float socclk; /*MHz*/ + float fabric_and_dram_bandwidth_vmax0p9; /*GB/s*/ + float fabric_and_dram_bandwidth_vnom0p8; /*GB/s*/ + float fabric_and_dram_bandwidth_vmid0p72; /*GB/s*/ + float fabric_and_dram_bandwidth_vmin0p65; /*GB/s*/ + float phyclkv_max0p9; /*MHz*/ + float phyclkv_nom0p8; /*MHz*/ + float phyclkv_mid0p72; /*MHz*/ + float phyclkv_min0p65; /*MHz*/ + float downspreading; /*%*/ + int round_trip_ping_latency_cycles; /*DCFCLK Cycles*/ + int urgent_out_of_order_return_per_channel; /*bytes*/ + int number_of_channels; + int vmm_page_size; /*bytes*/ + float dram_clock_change_latency; /*us*/ + int return_bus_width; /*bytes*/ +}; +extern const struct dcn_soc_bounding_box dcn10_soc_defaults; + +struct dcn_ip_params { + float rob_buffer_size_in_kbyte; + float det_buffer_size_in_kbyte; + float dpp_output_buffer_pixels; + float opp_output_buffer_lines; + float pixel_chunk_size_in_kbyte; + enum dcn_bw_defs pte_enable; + int pte_chunk_size; /*kbytes*/ + int meta_chunk_size; /*kbytes*/ + int writeback_chunk_size; /*kbytes*/ + enum dcn_bw_defs odm_capability; + enum dcn_bw_defs dsc_capability; + int line_buffer_size; /*bit*/ + int max_line_buffer_lines; + enum dcn_bw_defs is_line_buffer_bpp_fixed; + int line_buffer_fixed_bpp; + int writeback_luma_buffer_size; /*kbytes*/ + int writeback_chroma_buffer_size; /*kbytes*/ + int max_num_dpp; + int max_num_writeback; + int max_dchub_topscl_throughput; /*pixels/dppclk*/ + int max_pscl_tolb_throughput; /*pixels/dppclk*/ + int max_lb_tovscl_throughput; /*pixels/dppclk*/ + int max_vscl_tohscl_throughput; /*pixels/dppclk*/ + float max_hscl_ratio; + float max_vscl_ratio; + int max_hscl_taps; + int max_vscl_taps; + int pte_buffer_size_in_requests; + float dispclk_ramping_margin; /*%*/ + float under_scan_factor; + int max_inter_dcn_tile_repeaters; + enum dcn_bw_defs can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one; + enum dcn_bw_defs bug_forcing_luma_and_chroma_request_to_same_size_fixed; + int dcfclk_cstate_latency; +}; +extern const struct dcn_ip_params dcn10_ip_defaults; + +bool dcn_validate_bandwidth( + const struct core_dc *dc, + struct validate_context *context); + +unsigned int dcn_find_dcfclk_suits_all( + const struct core_dc *dc, + struct clocks_value *clocks); + +void dcn_bw_update_from_pplib(struct core_dc *dc); +void dcn_bw_notify_pplib_of_wm_ranges(struct core_dc *dc); +void dcn_bw_sync_calcs_and_dml(struct core_dc *dc); + +#endif /* __DCN_CALCS_H__ */ + -- cgit From 70ccab604049bbb995a57ab3b7fe8a3c2fdbb736 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 8 May 2017 15:19:06 -0400 Subject: drm/amdgpu/display: Add core dc support for DCN Core display support for DCN. Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/Makefile | 10 + .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 1866 ++++++++++++++++++++ .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h | 38 + drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c | 883 +++++++++ drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h | 549 ++++++ .../gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c | 1102 ++++++++++++ .../gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h | 553 ++++++ drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c | 376 ++++ drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h | 135 ++ drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c | 801 +++++++++ drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h | 622 +++++++ .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 1475 ++++++++++++++++ .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.h | 47 + .../amd/display/dc/dcn10/dcn10_timing_generator.c | 1202 +++++++++++++ .../amd/display/dc/dcn10/dcn10_timing_generator.h | 335 ++++ .../gpu/drm/amd/display/dc/dcn10/dcn10_transform.c | 1057 +++++++++++ .../gpu/drm/amd/display/dc/dcn10/dcn10_transform.h | 416 +++++ 17 files changed, 11467 insertions(+) create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/Makefile create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.h create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile new file mode 100644 index 000000000000..2c43ad7a6f3f --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile @@ -0,0 +1,10 @@ +# +# Makefile for DCN. + +DCN10 = dcn10_resource.o dcn10_ipp.o dcn10_hw_sequencer.o \ + dcn10_transform.o dcn10_opp.o dcn10_timing_generator.o \ + dcn10_mem_input.o dcn10_mpc.o + +AMD_DAL_DCN10 = $(addprefix $(AMDDALPATH)/dc/dcn10/,$(DCN10)) + +AMD_DISPLAY_FILES += $(AMD_DAL_DCN10) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c new file mode 100644 index 000000000000..fb4eb4364bc7 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -0,0 +1,1866 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "dc.h" +#include "core_dc.h" +#include "core_types.h" +#include "core_status.h" +#include "resource.h" +#include "hw_sequencer.h" +#include "dcn10_hw_sequencer.h" +#include "dce110/dce110_hw_sequencer.h" +#include "abm.h" + +#include "dcn10/dcn10_transform.h" +#include "dcn10/dcn10_mpc.h" +#include "dcn10/dcn10_timing_generator.h" + +#include "mem_input.h" +#include "timing_generator.h" +#include "opp.h" +#include "ipp.h" + +#include "dc_bios_types.h" + +#include "raven1/DCN/dcn_1_0_offset.h" +#include "raven1/DCN/dcn_1_0_sh_mask.h" +#include "vega10/soc15ip.h" + +#include "custom_float.h" + + +struct dcn10_hwseq_reg_offsets { + uint32_t dchubp; + uint32_t dpp; + uint32_t otg; + uint32_t vtg; + uint32_t fmt; +}; + +/* TODO: move to resource */ +static const struct dcn10_hwseq_reg_offsets reg_offsets[] = { + { + .dchubp = (mmHUBP0_DCHUBP_CNTL - mmHUBP0_DCHUBP_CNTL), + .dpp = (mmCM0_CM_DGAM_CONTROL - mmCM0_CM_DGAM_CONTROL), + .otg = (mmOTG0_OTG_CONTROL - mmOTG0_OTG_CONTROL), + .vtg = (mmVTG0_CONTROL - mmVTG0_CONTROL), + .fmt = (mmFMT0_FMT_BIT_DEPTH_CONTROL - + mmFMT0_FMT_BIT_DEPTH_CONTROL), + }, + { + .dchubp = (mmHUBP1_DCHUBP_CNTL - mmHUBP0_DCHUBP_CNTL), + .dpp = (mmCM1_CM_DGAM_CONTROL - mmCM0_CM_DGAM_CONTROL), + .otg = (mmOTG1_OTG_CONTROL - mmOTG0_OTG_CONTROL), + .vtg = (mmVTG1_CONTROL - mmVTG0_CONTROL), + .fmt = (mmFMT1_FMT_BIT_DEPTH_CONTROL - + mmFMT0_FMT_BIT_DEPTH_CONTROL), + }, + { + .dchubp = (mmHUBP2_DCHUBP_CNTL - mmHUBP0_DCHUBP_CNTL), + .dpp = (mmCM2_CM_DGAM_CONTROL - mmCM0_CM_DGAM_CONTROL), + .otg = (mmOTG2_OTG_CONTROL - mmOTG0_OTG_CONTROL), + .vtg = (mmVTG2_CONTROL - mmVTG0_CONTROL), + .fmt = (mmFMT2_FMT_BIT_DEPTH_CONTROL - + mmFMT0_FMT_BIT_DEPTH_CONTROL), + }, + { + .dchubp = (mmHUBP3_DCHUBP_CNTL - mmHUBP0_DCHUBP_CNTL), + .dpp = (mmCM3_CM_DGAM_CONTROL - mmCM0_CM_DGAM_CONTROL), + .otg = (mmOTG3_OTG_CONTROL - mmOTG0_OTG_CONTROL), + .vtg = (mmVTG3_CONTROL - mmVTG0_CONTROL), + .fmt = (mmFMT3_FMT_BIT_DEPTH_CONTROL - + mmFMT0_FMT_BIT_DEPTH_CONTROL), + } +}; + +#define HWSEQ_REG_UPDATE_N(reg_name, n, ...) \ + generic_reg_update_soc15(ctx, inst_offset, reg_name, n, __VA_ARGS__) + +#define HWSEQ_REG_SET_N(reg_name, n, ...) \ + generic_reg_set_soc15(ctx, inst_offset, reg_name, n, __VA_ARGS__) + +#define HWSEQ_REG_UPDATE(reg, field, val) \ + HWSEQ_REG_UPDATE_N(reg, 1, FD(reg##__##field), val) + +#define HWSEQ_REG_UPDATE_2(reg, field1, val1, field2, val2) \ + HWSEQ_REG_UPDATE_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) + +#define HWSEQ_REG_UPDATE_3(reg, field1, val1, field2, val2, field3, val3) \ + HWSEQ_REG_UPDATE_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3) + + +#define HWSEQ_REG_SET(reg, field, val) \ + HWSEQ_REG_SET_N(reg, 1, FD(reg##__##field), val) + +/* TODO should be moved to OTG */ +static void lock_otg_master_update( + struct dc_context *ctx, + uint8_t inst) +{ + uint32_t inst_offset = reg_offsets[inst].otg; + + HWSEQ_REG_UPDATE(OTG0_OTG_GLOBAL_CONTROL0, + OTG_MASTER_UPDATE_LOCK_SEL, inst); + + /* unlock master locker */ + HWSEQ_REG_UPDATE(OTG0_OTG_MASTER_UPDATE_LOCK, + OTG_MASTER_UPDATE_LOCK, 1); + + /* wait for unlock happens */ + if (!wait_reg(ctx, inst_offset, OTG0_OTG_MASTER_UPDATE_LOCK, UPDATE_LOCK_STATUS, 1)) + BREAK_TO_DEBUGGER(); + +} + +static bool unlock_master_tg_and_wait( + struct dc_context *ctx, + uint8_t inst) +{ + uint32_t inst_offset = reg_offsets[inst].otg; + + HWSEQ_REG_UPDATE(OTG0_OTG_GLOBAL_SYNC_STATUS, + VUPDATE_NO_LOCK_EVENT_CLEAR, 1); + HWSEQ_REG_UPDATE(OTG0_OTG_MASTER_UPDATE_LOCK, OTG_MASTER_UPDATE_LOCK, 0); + + if (!wait_reg(ctx, inst_offset, OTG0_OTG_GLOBAL_SYNC_STATUS, VUPDATE_NO_LOCK_EVENT_OCCURRED, 1)) { + dm_logger_write(ctx->logger, LOG_ERROR, + "wait for VUPDATE_NO_LOCK_EVENT_OCCURRED failed\n"); + BREAK_TO_DEBUGGER(); + return false; + } + return true; +} + +/* TODO: should be moved to OTG ? */ +static void unlock_otg_master( + struct dc_context *ctx, + uint8_t inst) +{ + uint32_t inst_offset = reg_offsets[inst].otg; + + /* unlock master locker */ + HWSEQ_REG_UPDATE(OTG0_OTG_MASTER_UPDATE_LOCK, + OTG_MASTER_UPDATE_LOCK, 0); +} + + +static void wait_no_outstanding_request( + struct dc_context *ctx, + uint8_t plane_id) +{ + uint32_t inst_offset = reg_offsets[plane_id].dchubp; + + if (!wait_reg(ctx, inst_offset, HUBP0_DCHUBP_CNTL, HUBP_NO_OUTSTANDING_REQ, 1)) + BREAK_TO_DEBUGGER(); +} + +static void disable_clocks( + struct dc_context *ctx, + uint8_t plane_id) +{ + uint32_t inst_offset = reg_offsets[plane_id].dchubp; + + generic_reg_update_soc15(ctx, inst_offset, HUBP0_HUBP_CLK_CNTL, 1, + FD(HUBP0_HUBP_CLK_CNTL__HUBP_CLOCK_ENABLE), 0); + + inst_offset = reg_offsets[plane_id].dpp; + generic_reg_update_soc15(ctx, inst_offset, DPP_TOP0_DPP_CONTROL, 1, + FD(DPP_TOP0_DPP_CONTROL__DPP_CLOCK_ENABLE), 0); +} + +/* TODO: This is one time program during system boot up, + * this should be done within BIOS or CAIL + */ +static void dchubp_map_fb_to_mc(struct dc_context *ctx) +{ + /* TODO: do not know where to program + * DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB + */ + /* + * TODO: For real ASIC, FB_OFFSET may be need change to the same value + * as FB_BASE. Need re-visit this for real ASIC. + */ + dm_write_reg_soc15(ctx, mmDCHUBBUB_SDPIF_FB_BASE, 0, 0x80); + dm_write_reg_soc15(ctx, mmDCHUBBUB_SDPIF_FB_OFFSET, 0, 0); + dm_write_reg_soc15(ctx, mmDCHUBBUB_SDPIF_FB_TOP, 0, 0xFF); + + generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_CFG0, 7, + FD(DCHUBBUB_SDPIF_CFG0__SDPIF_DATA_RESPONSE_STATUS_CLEAR), 0, + FD(DCHUBBUB_SDPIF_CFG0__SDPIF_REQ_CREDIT_ERROR_CLEAR), 0, + FD(DCHUBBUB_SDPIF_CFG0__SDPIF_FLUSH_REQ_CREDIT_EN), 0, + FD(DCHUBBUB_SDPIF_CFG0__SDPIF_REQ_CREDIT_EN), 0, + FD(DCHUBBUB_SDPIF_CFG0__SDPIF_PORT_CONTROL), 1, + FD(DCHUBBUB_SDPIF_CFG0__SDPIF_UNIT_ID_BITMASK), 0xd3, + FD(DCHUBBUB_SDPIF_CFG0__SDPIF_CREDIT_DISCONNECT_DELAY), 0xc); + + + generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_CFG1, 4, + FD(DCHUBBUB_SDPIF_CFG1__SDPIF_INSIDE_FB_IO), 0, + FD(DCHUBBUB_SDPIF_CFG1__SDPIF_INSIDE_FB_VC), 6, + FD(DCHUBBUB_SDPIF_CFG1__SDPIF_OUTSIDE_FB_IO), 1, + FD(DCHUBBUB_SDPIF_CFG1__SDPIF_OUTSIDE_FB_VC), 6); + + generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_FB_BASE, 1, + FD(DCHUBBUB_SDPIF_FB_BASE__SDPIF_FB_BASE), 0x000080); + + generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_FB_TOP, 1, + FD(DCHUBBUB_SDPIF_FB_TOP__SDPIF_FB_TOP), 0x0000ff); + + generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_AGP_BOT, 1, + FD(DCHUBBUB_SDPIF_AGP_BOT__SDPIF_AGP_BOT), 0x0000040); + + generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_AGP_TOP, 1, + FD(DCHUBBUB_SDPIF_AGP_TOP__SDPIF_AGP_TOP), 0x00001ff); + + generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_AGP_BASE, 1, + FD(DCHUBBUB_SDPIF_AGP_BASE__SDPIF_AGP_BASE), 0x0000080); + + generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_APER_TOP, 1, + FD(DCHUBBUB_SDPIF_APER_TOP__SDPIF_APER_TOP), 0x00007ff); + + generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_APER_DEF_0, 1, + FD(DCHUBBUB_SDPIF_APER_DEF_0__SDPIF_APER_DEF_0), 0xdeadbeef); + + generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_RELOC_LO_0, 2, + FD(DCHUBBUB_SDPIF_MARC_RELOC_LO_0__SDPIF_MARC_EN_0), 0, + FD(DCHUBBUB_SDPIF_MARC_RELOC_LO_0__SDPIF_MARC_RELOC_LO_0), 0x90000); + + generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_LENGTH_LO_0, 1, + FD(DCHUBBUB_SDPIF_MARC_LENGTH_LO_0__SDPIF_MARC_LENGTH_LO_0), 0x10000); + + generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_BASE_LO_1, 1, + FD(DCHUBBUB_SDPIF_MARC_BASE_LO_1__SDPIF_MARC_BASE_LO_1), 0x10000); + + generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_RELOC_LO_1, 2, + FD(DCHUBBUB_SDPIF_MARC_RELOC_LO_1__SDPIF_MARC_EN_1), 0, + FD(DCHUBBUB_SDPIF_MARC_RELOC_LO_1__SDPIF_MARC_RELOC_LO_1), 0xa0000); + + generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_LENGTH_LO_1, 1, + FD(DCHUBBUB_SDPIF_MARC_LENGTH_LO_1__SDPIF_MARC_LENGTH_LO_1), 0x10000); + + generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_BASE_LO_2, 1, + FD(DCHUBBUB_SDPIF_MARC_BASE_LO_2__SDPIF_MARC_BASE_LO_2), 0x20000); + + generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_RELOC_LO_2, 2, + FD(DCHUBBUB_SDPIF_MARC_RELOC_LO_2__SDPIF_MARC_EN_2), 0, + FD(DCHUBBUB_SDPIF_MARC_RELOC_LO_2__SDPIF_MARC_RELOC_LO_2), 0xb0000); + + generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_LENGTH_LO_2, 1, + FD(DCHUBBUB_SDPIF_MARC_LENGTH_LO_2__SDPIF_MARC_LENGTH_LO_2), 0x10000); + + generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_BASE_LO_3, 1, + FD(DCHUBBUB_SDPIF_MARC_BASE_LO_3__SDPIF_MARC_BASE_LO_3), 0x30000); + + generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_RELOC_LO_3, 2, + FD(DCHUBBUB_SDPIF_MARC_RELOC_LO_3__SDPIF_MARC_EN_3), 0, + FD(DCHUBBUB_SDPIF_MARC_RELOC_LO_3__SDPIF_MARC_RELOC_LO_3), 0xc0000); + + generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_LENGTH_LO_3, 1, + FD(DCHUBBUB_SDPIF_MARC_LENGTH_LO_3__SDPIF_MARC_LENGTH_LO_3), 0x10000); + + /* TODO: Is DCN_VM_SYSTEM_APERTURE address one time programming? + * Are all 4 hubp programmed with the same address? + */ + dm_write_reg_soc15(ctx, mmHUBPREQ0_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, 0, 0x80000); + dm_write_reg_soc15(ctx, mmHUBPREQ0_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, 0, 0); + dm_write_reg_soc15(ctx, mmHUBPREQ0_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, 0, 0x100000); + dm_write_reg_soc15(ctx, mmHUBPREQ0_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, 0, 0); + dm_write_reg_soc15(ctx, mmHUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, 0, 0x80000); + dm_write_reg_soc15(ctx, mmHUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, 0, 0); + + dm_write_reg_soc15(ctx, mmHUBPREQ1_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, 0, 0x80000); + dm_write_reg_soc15(ctx, mmHUBPREQ1_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, 0, 0); + dm_write_reg_soc15(ctx, mmHUBPREQ1_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, 0, 0x100000); + dm_write_reg_soc15(ctx, mmHUBPREQ1_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, 0, 0); + dm_write_reg_soc15(ctx, mmHUBPREQ1_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, 0, 0x80000); + dm_write_reg_soc15(ctx, mmHUBPREQ1_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, 0, 0); + + dm_write_reg_soc15(ctx, mmHUBPREQ2_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, 0, 0x80000); + dm_write_reg_soc15(ctx, mmHUBPREQ2_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, 0, 0); + dm_write_reg_soc15(ctx, mmHUBPREQ2_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, 0, 0x100000); + dm_write_reg_soc15(ctx, mmHUBPREQ2_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, 0, 0); + dm_write_reg_soc15(ctx, mmHUBPREQ2_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, 0, 0x80000); + dm_write_reg_soc15(ctx, mmHUBPREQ2_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, 0, 0); + + dm_write_reg_soc15(ctx, mmHUBPREQ3_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, 0, 0x80000); + dm_write_reg_soc15(ctx, mmHUBPREQ3_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, 0, 0); + dm_write_reg_soc15(ctx, mmHUBPREQ3_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, 0, 0x100000); + dm_write_reg_soc15(ctx, mmHUBPREQ3_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, 0, 0); + dm_write_reg_soc15(ctx, mmHUBPREQ3_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, 0, 0x80000); + dm_write_reg_soc15(ctx, mmHUBPREQ3_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, 0, 0); +} + +/* TODO: This is one time program during system boot up, + * this should be done within BIOS + */ +static void dchubup_setup_timer(struct dc_context *ctx) +{ + dm_write_reg_soc15(ctx, mmREFCLK_CNTL, 0, 0); + + generic_reg_update_soc15(ctx, 0, DCHUBBUB_GLOBAL_TIMER_CNTL, 1, + FD(DCHUBBUB_GLOBAL_TIMER_CNTL__DCHUBBUB_GLOBAL_TIMER_ENABLE), 1); +} + +/* TODO: Need input parameter to tell current DCHUB pipe tie to which OTG + * VTG is within DCHUBBUB which is commond block share by each pipe HUBP. + * VTG is 1:1 mapping with OTG. Each pipe HUBP will select which VTG + */ +static void select_vtg( + struct dc_context *ctx, + uint8_t plane_id, + uint8_t inst) +{ + uint32_t inst_offset = reg_offsets[plane_id].dchubp; + + HWSEQ_REG_UPDATE(HUBP0_DCHUBP_CNTL, HUBP_VTG_SEL, inst); +} + +static void enable_dcfclk( + struct dc_context *ctx, + uint8_t plane_id, + uint32_t requested_pix_clk, + bool dppclk_div) +{ + uint32_t inst_offset = reg_offsets[plane_id].dchubp; + + HWSEQ_REG_UPDATE(HUBP0_HUBP_CLK_CNTL, HUBP_CLOCK_ENABLE, 1); +} + +static void enable_dppclk( + struct dc_context *ctx, + uint8_t plane_id, + uint32_t requested_pix_clk, + bool dppclk_div) +{ + uint32_t inst_offset = reg_offsets[plane_id].dpp; + + dm_logger_write(ctx->logger, LOG_SURFACE, + "dppclk_rate_control for pipe %d programed to %d\n", + plane_id, + dppclk_div); + + /* TODO: find condition for DPP clock to DISPCLK or 1/2 DISPCLK */ + if (dppclk_div) { + /* 1/2 DISPCLK*/ + HWSEQ_REG_UPDATE_2(DPP_TOP0_DPP_CONTROL, + DPPCLK_RATE_CONTROL, 1, + DPP_CLOCK_ENABLE, 1); + } else { + /* DISPCLK */ + HWSEQ_REG_UPDATE_2(DPP_TOP0_DPP_CONTROL, + DPPCLK_RATE_CONTROL, 0, + DPP_CLOCK_ENABLE, 1); + } +} + +static void enable_power_gating_plane( + struct dc_context *ctx, + bool enable) +{ + uint32_t inst_offset = 0; /* each register only has one instance */ + bool force_on = 1; /* disable power gating */ + + if (enable) + force_on = 0; + + /* DCHUBP0/1/2/3 */ + HWSEQ_REG_UPDATE(DOMAIN0_PG_CONFIG, DOMAIN0_POWER_FORCEON, force_on); + HWSEQ_REG_UPDATE(DOMAIN2_PG_CONFIG, DOMAIN2_POWER_FORCEON, force_on); + HWSEQ_REG_UPDATE(DOMAIN4_PG_CONFIG, DOMAIN4_POWER_FORCEON, force_on); + HWSEQ_REG_UPDATE(DOMAIN6_PG_CONFIG, DOMAIN6_POWER_FORCEON, force_on); + + /* DPP0/1/2/3 */ + HWSEQ_REG_UPDATE(DOMAIN1_PG_CONFIG, DOMAIN1_POWER_FORCEON, force_on); + HWSEQ_REG_UPDATE(DOMAIN3_PG_CONFIG, DOMAIN3_POWER_FORCEON, force_on); + HWSEQ_REG_UPDATE(DOMAIN5_PG_CONFIG, DOMAIN5_POWER_FORCEON, force_on); + HWSEQ_REG_UPDATE(DOMAIN7_PG_CONFIG, DOMAIN7_POWER_FORCEON, force_on); + + if (ctx->dc->debug.disable_clock_gate) { + /* probably better to just write entire register to 0xffff to + * ensure all clock gating is disabled + */ + HWSEQ_REG_UPDATE_3(DCCG_GATE_DISABLE_CNTL, + DISPCLK_R_DCCG_GATE_DISABLE, 1, + DPREFCLK_R_DCCG_GATE_DISABLE, 1, + REFCLK_R_DIG_GATE_DISABLE, 1); + HWSEQ_REG_UPDATE(DCFCLK_CNTL, + DCFCLK_GATE_DIS, 1); + } + +} + +static void dpp_pg_control( + struct dc_context *ctx, + unsigned int dpp_inst, + bool power_on) +{ + uint32_t inst_offset = 0; + uint32_t power_gate = power_on ? 0 : 1; + uint32_t pwr_status = power_on ? 0 : 2; + + if (ctx->dc->debug.disable_dpp_power_gate) + return; + + switch (dpp_inst) { + case 0: /* DPP0 */ + HWSEQ_REG_UPDATE(DOMAIN1_PG_CONFIG, + DOMAIN1_POWER_GATE, power_gate); + + wait_reg(ctx, 0, DOMAIN1_PG_STATUS, + DOMAIN1_PGFSM_PWR_STATUS, pwr_status); + break; + case 1: /* DPP1 */ + HWSEQ_REG_UPDATE(DOMAIN3_PG_CONFIG, + DOMAIN3_POWER_GATE, power_gate); + + wait_reg(ctx, 0, DOMAIN3_PG_STATUS, + DOMAIN3_PGFSM_PWR_STATUS, pwr_status); + break; + case 2: /* DPP2 */ + HWSEQ_REG_UPDATE(DOMAIN5_PG_CONFIG, + DOMAIN5_POWER_GATE, power_gate); + + wait_reg(ctx, 0, DOMAIN5_PG_STATUS, + DOMAIN5_PGFSM_PWR_STATUS, pwr_status); + break; + case 3: /* DPP3 */ + HWSEQ_REG_UPDATE(DOMAIN7_PG_CONFIG, + DOMAIN7_POWER_GATE, power_gate); + + wait_reg(ctx, 0, DOMAIN7_PG_STATUS, + DOMAIN7_PGFSM_PWR_STATUS, pwr_status); + break; + default: + BREAK_TO_DEBUGGER(); + break; + } +} + +static void hubp_pg_control( + struct dc_context *ctx, + unsigned int hubp_inst, + bool power_on) +{ + uint32_t inst_offset = 0; + uint32_t power_gate = power_on ? 0 : 1; + uint32_t pwr_status = power_on ? 0 : 2; + + if (ctx->dc->debug.disable_hubp_power_gate) + return; + + switch (hubp_inst) { + case 0: /* DCHUBP0 */ + HWSEQ_REG_UPDATE(DOMAIN0_PG_CONFIG, + DOMAIN0_POWER_GATE, power_gate); + + wait_reg(ctx, 0, DOMAIN0_PG_STATUS, + DOMAIN0_PGFSM_PWR_STATUS, pwr_status); + break; + case 1: /* DCHUBP1 */ + HWSEQ_REG_UPDATE(DOMAIN2_PG_CONFIG, + DOMAIN2_POWER_GATE, power_gate); + + wait_reg(ctx, 0, DOMAIN2_PG_STATUS, + DOMAIN2_PGFSM_PWR_STATUS, pwr_status); + break; + case 2: /* DCHUBP2 */ + HWSEQ_REG_UPDATE(DOMAIN4_PG_CONFIG, + DOMAIN4_POWER_GATE, power_gate); + + wait_reg(ctx, 0, DOMAIN4_PG_STATUS, + DOMAIN4_PGFSM_PWR_STATUS, pwr_status); + break; + case 3: /* DCHUBP3 */ + HWSEQ_REG_UPDATE(DOMAIN6_PG_CONFIG, + DOMAIN6_POWER_GATE, power_gate); + + wait_reg(ctx, 0, DOMAIN6_PG_STATUS, + DOMAIN6_PGFSM_PWR_STATUS, pwr_status); + break; + default: + BREAK_TO_DEBUGGER(); + break; + } +} + +static void power_on_plane( + struct dc_context *ctx, + uint8_t plane_id, + uint8_t inst) +{ + uint32_t inst_offset = 0; + + /* disable clock power gating */ + + /* DCCG_GATE_DISABLE_CNTL only has one instance */ + HWSEQ_REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL, + DISPCLK_DCCG_GATE_DISABLE, 1, + DPPCLK_GATE_DISABLE, 1); + /* DCFCLK_CNTL only has one instance */ + HWSEQ_REG_UPDATE(DCFCLK_CNTL, + DCFCLK_GATE_DIS, 1); + + HWSEQ_REG_SET(DC_IP_REQUEST_CNTL, + IP_REQUEST_EN, 1); + dpp_pg_control(ctx, plane_id, true); + hubp_pg_control(ctx, plane_id, true); + HWSEQ_REG_SET(DC_IP_REQUEST_CNTL, + IP_REQUEST_EN, 0); + + if (ctx->dc->debug.disable_clock_gate) { + HWSEQ_REG_UPDATE(DCCG_GATE_DISABLE_CNTL, + DISPCLK_DCCG_GATE_DISABLE, 0); + } else { + /* DCCG_GATE_DISABLE_CNTL only has one instance. inst_offset = 0 */ + HWSEQ_REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL, + DISPCLK_DCCG_GATE_DISABLE, 0, + DPPCLK_GATE_DISABLE, 0); + /* DCFCLK_CNTL only has one instance. inst_offset = 0 */ + HWSEQ_REG_UPDATE(DCFCLK_CNTL, + DCFCLK_GATE_DIS, 0); + } +} + +/* fully check bios enabledisplaypowergating table. dal only need dce init + * other power, clock gate register will be handle by dal itself. + * further may be put within init_hw + */ +static bool dcn10_enable_display_power_gating( + struct core_dc *dc, + uint8_t controller_id, + struct dc_bios *dcb, + enum pipe_gating_control power_gating) +{ + /* TODOFPGA */ +#if 0 + if (power_gating != PIPE_GATING_CONTROL_ENABLE) + dce110_init_pte(ctx); +#endif + + return true; +} + +static void bios_golden_init(struct core_dc *dc) +{ + struct dc_bios *bp = dc->ctx->dc_bios; + int i; + + /* initialize dcn global */ + bp->funcs->enable_disp_power_gating(bp, + CONTROLLER_ID_D0, ASIC_PIPE_INIT); + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + /* initialize dcn per pipe */ + bp->funcs->enable_disp_power_gating(bp, + CONTROLLER_ID_D0 + i, ASIC_PIPE_DISABLE); + } +} + +static void init_hw(struct core_dc *dc) +{ + int i; + struct dc_bios *bp; + struct transform *xfm; + struct abm *abm; + + bp = dc->ctx->dc_bios; + + if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { + /* TODO: this will be moved to Diag or BIOS */ + dchubup_setup_timer(dc->ctx); + + /* TODO: dchubp_map_fb_to_mc will be moved to dchub interface + * between dc and kmd + */ + dchubp_map_fb_to_mc(dc->ctx); + + enable_power_gating_plane(dc->ctx, true); + return; + } + /* end of FPGA. Below if real ASIC */ + + bios_golden_init(dc); + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + xfm = dc->res_pool->transforms[i]; + xfm->funcs->transform_reset(xfm); + + /* TODOFPGA: may need later */ +#if 0 + xfm->funcs->transform_power_up(xfm); + dc->hwss.enable_display_pipe_clock_gating( + dc->ctx, + true); +#endif + } + /* TODOFPGA: light sleep */ +#if 0 + dc->hwss.clock_gating_power_up(dc->ctx, false); +#endif + + for (i = 0; i < dc->link_count; i++) { + /* Power up AND update implementation according to the + * required signal (which may be different from the + * default signal on connector). + */ + struct core_link *link = dc->links[i]; + + link->link_enc->funcs->hw_init(link->link_enc); + } + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct timing_generator *tg = + dc->res_pool->timing_generators[i]; + + tg->funcs->disable_vga(tg); + + /* Blank controller using driver code instead of + * command table. + */ + tg->funcs->set_blank(tg, true); + hwss_wait_for_blank_complete(tg); + } + + for (i = 0; i < dc->res_pool->audio_count; i++) { + struct audio *audio = dc->res_pool->audios[i]; + + audio->funcs->hw_init(audio); + } + + abm = dc->res_pool->abm; + if (abm != NULL) { + abm->funcs->init_backlight(abm); + abm->funcs->abm_init(abm); + } + + /* power AFMT HDMI memory TODO: may move to dis/en output save power*/ + generic_reg_set_soc15(dc->ctx, 0, DIO_MEM_PWR_CTRL, 7, + FD(DIO_MEM_PWR_CTRL__HDMI0_MEM_PWR_FORCE), 0, + FD(DIO_MEM_PWR_CTRL__HDMI1_MEM_PWR_FORCE), 0, + FD(DIO_MEM_PWR_CTRL__HDMI2_MEM_PWR_FORCE), 0, + FD(DIO_MEM_PWR_CTRL__HDMI3_MEM_PWR_FORCE), 0, + FD(DIO_MEM_PWR_CTRL__HDMI4_MEM_PWR_FORCE), 0, + FD(DIO_MEM_PWR_CTRL__HDMI5_MEM_PWR_FORCE), 0, + FD(DIO_MEM_PWR_CTRL__HDMI6_MEM_PWR_FORCE), 0); + + /* This power gating should be one-time program for DAL. + * It can only change by registry key + * TODO: new task will for this. + * if power gating is disable, power_on_plane and power_off_plane + * should be skip. Otherwise, hand will be met in power_off_plane + */ + + enable_power_gating_plane(dc->ctx, true); +} + +static enum dc_status dcn10_prog_pixclk_crtc_otg( + struct pipe_ctx *pipe_ctx, + struct validate_context *context, + struct core_dc *dc) +{ + struct core_stream *stream = pipe_ctx->stream; + enum dc_color_space color_space; + struct tg_color black_color = {0}; + bool enableStereo = stream->public.timing.timing_3d_format == TIMING_3D_FORMAT_NONE ? + false:true; + bool rightEyePolarity = stream->public.timing.flags.RIGHT_EYE_3D_POLARITY; + + + /* by upper caller loop, pipe0 is parent pipe and be called first. + * back end is set up by for pipe0. Other children pipe share back end + * with pipe 0. No program is needed. + */ + if (pipe_ctx->top_pipe != NULL) + return DC_OK; + + /* TODO check if timing_changed, disable stream if timing changed */ + + /* HW program guide assume display already disable + * by unplug sequence. OTG assume stop. + */ + pipe_ctx->tg->funcs->enable_optc_clock(pipe_ctx->tg, true); + + if (false == pipe_ctx->clock_source->funcs->program_pix_clk( + pipe_ctx->clock_source, + &pipe_ctx->pix_clk_params, + &pipe_ctx->pll_settings)) { + BREAK_TO_DEBUGGER(); + return DC_ERROR_UNEXPECTED; + } + pipe_ctx->tg->dlg_otg_param.vready_offset = pipe_ctx->pipe_dlg_param.vready_offset; + pipe_ctx->tg->dlg_otg_param.vstartup_start = pipe_ctx->pipe_dlg_param.vstartup_start; + pipe_ctx->tg->dlg_otg_param.vupdate_offset = pipe_ctx->pipe_dlg_param.vupdate_offset; + pipe_ctx->tg->dlg_otg_param.vupdate_width = pipe_ctx->pipe_dlg_param.vupdate_width; + + pipe_ctx->tg->dlg_otg_param.signal = pipe_ctx->stream->signal; + + pipe_ctx->tg->funcs->program_timing( + pipe_ctx->tg, + &stream->public.timing, + true); + + pipe_ctx->opp->funcs->opp_set_stereo_polarity( + pipe_ctx->opp, + enableStereo, + rightEyePolarity); + +#if 0 /* move to after enable_crtc */ + /* TODO: OPP FMT, ABM. etc. should be done here. */ + /* or FPGA now. instance 0 only. TODO: move to opp.c */ + + inst_offset = reg_offsets[pipe_ctx->tg->inst].fmt; + + pipe_ctx->opp->funcs->opp_program_fmt( + pipe_ctx->opp, + &stream->bit_depth_params, + &stream->clamping); +#endif + /* program otg blank color */ + color_space = stream->public.output_color_space; + color_space_to_black_color(dc, color_space, &black_color); + pipe_ctx->tg->funcs->set_blank_color( + pipe_ctx->tg, + &black_color); + + pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, true); + hwss_wait_for_blank_complete(pipe_ctx->tg); + + /* VTG is within DCHUB command block. DCFCLK is always on */ + if (false == pipe_ctx->tg->funcs->enable_crtc(pipe_ctx->tg)) { + BREAK_TO_DEBUGGER(); + return DC_ERROR_UNEXPECTED; + } + + /* TODO program crtc source select for non-virtual signal*/ + /* TODO program FMT */ + /* TODO setup link_enc */ + /* TODO set stream attributes */ + /* TODO program audio */ + /* TODO enable stream if timing changed */ + /* TODO unblank stream if DP */ + + return DC_OK; +} + +static void reset_back_end_for_pipe( + struct core_dc *dc, + struct pipe_ctx *pipe_ctx, + struct validate_context *context) +{ + int i; + struct dc_bios *bp; + + bp = dc->ctx->dc_bios; + + if (pipe_ctx->stream_enc == NULL) { + pipe_ctx->stream = NULL; + return; + } + + /* TODOFPGA break core_link_disable_stream into 2 functions: + * disable_stream and disable_link. disable_link will disable PHYPLL + * which is used by otg. Move disable_link after disable_crtc + */ + if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) + core_link_disable_stream(pipe_ctx); + + /* by upper caller loop, parent pipe: pipe0, will be reset last. + * back end share by all pipes and will be disable only when disable + * parent pipe. + */ + if (pipe_ctx->top_pipe == NULL) { + pipe_ctx->tg->funcs->disable_crtc(pipe_ctx->tg); + + pipe_ctx->tg->funcs->enable_optc_clock(pipe_ctx->tg, false); + } + + if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) + resource_unreference_clock_source( + &context->res_ctx, dc->res_pool, + &pipe_ctx->clock_source); + + for (i = 0; i < dc->res_pool->pipe_count; i++) + if (&dc->current_context->res_ctx.pipe_ctx[i] == pipe_ctx) + break; + + if (i == dc->res_pool->pipe_count) + return; + + pipe_ctx->stream = NULL; +} + +static void reset_front_end_for_pipe( + struct core_dc *dc, + struct pipe_ctx *pipe_ctx, + struct validate_context *context) +{ + struct dcn10_mpc *mpc = TO_DCN10_MPC(dc->res_pool->mpc); + struct mpc_tree_cfg *tree_cfg = NULL; + + if (!pipe_ctx->surface) + return; + + lock_otg_master_update(dc->ctx, pipe_ctx->tg->inst); + + /* TODO: build stream pipes group id. For now, use stream otg + * id as pipe group id + */ + tree_cfg = &context->res_ctx.mpc_tree[pipe_ctx->mpc_idx]; + + if (pipe_ctx->top_pipe == NULL) + dcn10_delete_mpc_tree(mpc, tree_cfg); + else { + if (dcn10_remove_dpp(mpc, tree_cfg, pipe_ctx->pipe_idx)) + pipe_ctx->top_pipe->bottom_pipe = NULL; + else { + dm_logger_write(dc->ctx->logger, LOG_RESOURCE, + "%s: failed to find dpp to be removed!\n", + __func__); + } + } + + pipe_ctx->top_pipe = NULL; + pipe_ctx->bottom_pipe = NULL; + pipe_ctx->mpc_idx = -1; + + unlock_master_tg_and_wait(dc->ctx, pipe_ctx->tg->inst); + + pipe_ctx->mi->funcs->disable_request(pipe_ctx->mi); + + wait_no_outstanding_request(dc->ctx, pipe_ctx->pipe_idx); + + wait_mpcc_idle(mpc, pipe_ctx->pipe_idx); + + disable_clocks(dc->ctx, pipe_ctx->pipe_idx); + + pipe_ctx->xfm->funcs->transform_reset(pipe_ctx->xfm); + + dm_logger_write(dc->ctx->logger, LOG_DC, + "Reset front end for pipe %d\n", + pipe_ctx->pipe_idx); + + pipe_ctx->surface = NULL; +} + +static void reset_hw_ctx(struct core_dc *dc, + struct validate_context *context, + void (*reset)(struct core_dc *dc, + struct pipe_ctx *pipe_ctx, + struct validate_context *context)) +{ + int i; + + for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) { + struct pipe_ctx *pipe_ctx_old = + &dc->current_context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + + if (!pipe_ctx_old->stream) + continue; + + if (!pipe_ctx->stream || + pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) + reset(dc, pipe_ctx_old, dc->current_context); + } +} + +static void reset_hw_ctx_wrap( + struct core_dc *dc, + struct validate_context *context) +{ + /* Reset Front End*/ + reset_hw_ctx(dc, context, reset_front_end_for_pipe); + /* Reset Back End*/ + reset_hw_ctx(dc, context, reset_back_end_for_pipe); + + memcpy(context->res_ctx.mpc_tree, + dc->current_context->res_ctx.mpc_tree, + sizeof(struct mpc_tree_cfg) * dc->res_pool->pipe_count); +} + +static bool patch_address_for_sbs_tb_stereo(struct pipe_ctx *pipe_ctx, + PHYSICAL_ADDRESS_LOC *addr) +{ + struct core_surface *surface = pipe_ctx->surface; + bool sec_split = pipe_ctx->top_pipe && + pipe_ctx->top_pipe->surface == pipe_ctx->surface; + if (sec_split && surface->public.address.type == PLN_ADDR_TYPE_GRPH_STEREO && + (pipe_ctx->stream->public.timing.timing_3d_format == + TIMING_3D_FORMAT_SIDE_BY_SIDE || + pipe_ctx->stream->public.timing.timing_3d_format == + TIMING_3D_FORMAT_TOP_AND_BOTTOM)) { + *addr = surface->public.address.grph_stereo.left_addr; + surface->public.address.grph_stereo.left_addr =\ + surface->public.address.grph_stereo.right_addr; + return true; + } + return false; +} + +static void update_plane_addr(const struct core_dc *dc, struct pipe_ctx *pipe_ctx) +{ + bool addr_patched = false; + PHYSICAL_ADDRESS_LOC addr; + struct core_surface *surface = pipe_ctx->surface; + + if (surface == NULL) + return; + addr_patched = patch_address_for_sbs_tb_stereo(pipe_ctx, &addr); + pipe_ctx->mi->funcs->mem_input_program_surface_flip_and_addr( + pipe_ctx->mi, + &surface->public.address, + surface->public.flip_immediate); + surface->status.requested_address = surface->public.address; + if (addr_patched) + pipe_ctx->surface->public.address.grph_stereo.left_addr = addr; +} + +static bool dcn10_set_input_transfer_func( + struct pipe_ctx *pipe_ctx, + const struct core_surface *surface) +{ + struct input_pixel_processor *ipp = pipe_ctx->ipp; + const struct core_transfer_func *tf = NULL; + bool result = true; + + if (ipp == NULL) + return false; + + if (surface->public.in_transfer_func) + tf = DC_TRANSFER_FUNC_TO_CORE(surface->public.in_transfer_func); + + if (tf == NULL) + ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS); + else if (tf->public.type == TF_TYPE_PREDEFINED) { + switch (tf->public.tf) { + case TRANSFER_FUNCTION_SRGB: + ipp->funcs->ipp_set_degamma(ipp, + IPP_DEGAMMA_MODE_HW_sRGB); + break; + case TRANSFER_FUNCTION_BT709: + ipp->funcs->ipp_set_degamma(ipp, + IPP_DEGAMMA_MODE_HW_xvYCC); + break; + case TRANSFER_FUNCTION_LINEAR: + ipp->funcs->ipp_set_degamma(ipp, + IPP_DEGAMMA_MODE_BYPASS); + break; + case TRANSFER_FUNCTION_PQ: + result = false; + break; + default: + result = false; + break; + } + } else if (tf->public.type == TF_TYPE_BYPASS) { + ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS); + } else { + /*TF_TYPE_DISTRIBUTED_POINTS*/ + result = false; + } + + return result; +} +/*modify the method to handle rgb for arr_points*/ +static bool convert_to_custom_float( + struct pwl_result_data *rgb_resulted, + struct curve_points *arr_points, + uint32_t hw_points_num) +{ + struct custom_float_format fmt; + + struct pwl_result_data *rgb = rgb_resulted; + + uint32_t i = 0; + + fmt.exponenta_bits = 6; + fmt.mantissa_bits = 12; + fmt.sign = false; + + if (!convert_to_custom_float_format( + arr_points[0].x, + &fmt, + &arr_points[0].custom_float_x)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + arr_points[0].offset, + &fmt, + &arr_points[0].custom_float_offset)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + arr_points[0].slope, + &fmt, + &arr_points[0].custom_float_slope)) { + BREAK_TO_DEBUGGER(); + return false; + } + + fmt.mantissa_bits = 10; + fmt.sign = false; + + if (!convert_to_custom_float_format( + arr_points[1].x, + &fmt, + &arr_points[1].custom_float_x)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + arr_points[1].y, + &fmt, + &arr_points[1].custom_float_y)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + arr_points[1].slope, + &fmt, + &arr_points[1].custom_float_slope)) { + BREAK_TO_DEBUGGER(); + return false; + } + + fmt.mantissa_bits = 12; + fmt.sign = true; + + while (i != hw_points_num) { + if (!convert_to_custom_float_format( + rgb->red, + &fmt, + &rgb->red_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + rgb->green, + &fmt, + &rgb->green_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + rgb->blue, + &fmt, + &rgb->blue_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + rgb->delta_red, + &fmt, + &rgb->delta_red_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + rgb->delta_green, + &fmt, + &rgb->delta_green_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + rgb->delta_blue, + &fmt, + &rgb->delta_blue_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + ++rgb; + ++i; + } + + return true; +} +#define MAX_REGIONS_NUMBER 34 +#define MAX_LOW_POINT 25 +#define NUMBER_SEGMENTS 32 + +static bool dcn10_translate_regamma_to_hw_format(const struct dc_transfer_func + *output_tf, struct pwl_params *regamma_params) +{ + struct curve_points *arr_points; + struct pwl_result_data *rgb_resulted; + struct pwl_result_data *rgb; + struct pwl_result_data *rgb_plus_1; + struct fixed31_32 y_r; + struct fixed31_32 y_g; + struct fixed31_32 y_b; + struct fixed31_32 y1_min; + struct fixed31_32 y3_max; + + int32_t segment_start, segment_end; + int32_t i; + uint32_t j, k, seg_distr[MAX_REGIONS_NUMBER], increment, start_index, hw_points; + + if (output_tf == NULL || regamma_params == NULL || + output_tf->type == TF_TYPE_BYPASS) + return false; + + arr_points = regamma_params->arr_points; + rgb_resulted = regamma_params->rgb_resulted; + hw_points = 0; + + memset(regamma_params, 0, sizeof(struct pwl_params)); + memset(seg_distr, 0, sizeof(seg_distr)); + + if (output_tf->tf == TRANSFER_FUNCTION_PQ) { + /* 32 segments + * segments are from 2^-25 to 2^7 + */ + for (i = 0; i < 32 ; i++) + seg_distr[i] = 3; + + segment_start = -25; + segment_end = 7; + } else { + /* 10 segments + * segment is from 2^-10 to 2^0 + * There are less than 256 points, for optimization + */ + seg_distr[0] = 3; + seg_distr[1] = 4; + seg_distr[2] = 4; + seg_distr[3] = 4; + seg_distr[4] = 4; + seg_distr[5] = 4; + seg_distr[6] = 4; + seg_distr[7] = 4; + seg_distr[8] = 5; + seg_distr[9] = 5; + + segment_start = -10; + segment_end = 0; + } + + for (i = segment_end - segment_start; i < MAX_REGIONS_NUMBER ; i++) + seg_distr[i] = -1; + + for (k = 0; k < MAX_REGIONS_NUMBER; k++) { + if (seg_distr[k] != -1) + hw_points += (1 << seg_distr[k]); + } + + j = 0; + for (k = 0; k < (segment_end - segment_start); k++) { + increment = NUMBER_SEGMENTS / (1 << seg_distr[k]); + start_index = (segment_start + k + MAX_LOW_POINT) * NUMBER_SEGMENTS; + for (i = start_index; i < start_index + NUMBER_SEGMENTS; i += increment) { + if (j == hw_points - 1) + break; + 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]; + j++; + } + } + + /* last point */ + start_index = (segment_end + MAX_LOW_POINT) * NUMBER_SEGMENTS; + rgb_resulted[hw_points - 1].red = + output_tf->tf_pts.red[start_index]; + rgb_resulted[hw_points - 1].green = + output_tf->tf_pts.green[start_index]; + rgb_resulted[hw_points - 1].blue = + output_tf->tf_pts.blue[start_index]; + + arr_points[0].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2), + dal_fixed31_32_from_int(segment_start)); + arr_points[1].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2), + dal_fixed31_32_from_int(segment_end)); + arr_points[2].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2), + dal_fixed31_32_from_int(segment_end)); + + y_r = rgb_resulted[0].red; + y_g = rgb_resulted[0].green; + y_b = rgb_resulted[0].blue; + + y1_min = dal_fixed31_32_min(y_r, dal_fixed31_32_min(y_g, y_b)); + + arr_points[0].y = y1_min; + arr_points[0].slope = dal_fixed31_32_div( + arr_points[0].y, + arr_points[0].x); + y_r = rgb_resulted[hw_points - 1].red; + y_g = rgb_resulted[hw_points - 1].green; + y_b = rgb_resulted[hw_points - 1].blue; + + /* see comment above, m_arrPoints[1].y should be the Y value for the + * region end (m_numOfHwPoints), not last HW point(m_numOfHwPoints - 1) + */ + y3_max = dal_fixed31_32_max(y_r, dal_fixed31_32_max(y_g, y_b)); + + arr_points[1].y = y3_max; + arr_points[2].y = y3_max; + + arr_points[1].slope = dal_fixed31_32_zero; + arr_points[2].slope = dal_fixed31_32_zero; + + if (output_tf->tf == TRANSFER_FUNCTION_PQ) { + /* for PQ, we want to have a straight line from last HW X point, + * and the slope to be such that we hit 1.0 at 10000 nits. + */ + const struct fixed31_32 end_value = + dal_fixed31_32_from_int(125); + + arr_points[1].slope = dal_fixed31_32_div( + dal_fixed31_32_sub(dal_fixed31_32_one, arr_points[1].y), + dal_fixed31_32_sub(end_value, arr_points[1].x)); + arr_points[2].slope = dal_fixed31_32_div( + dal_fixed31_32_sub(dal_fixed31_32_one, arr_points[1].y), + dal_fixed31_32_sub(end_value, arr_points[1].x)); + } + + regamma_params->hw_points_num = hw_points; + + i = 1; + for (k = 0; k < MAX_REGIONS_NUMBER && i < MAX_REGIONS_NUMBER; k++) { + if (seg_distr[k] != -1) { + regamma_params->arr_curve_points[k].segments_num = + seg_distr[k]; + regamma_params->arr_curve_points[i].offset = + regamma_params->arr_curve_points[k]. + offset + (1 << seg_distr[k]); + } + i++; + } + + if (seg_distr[k] != -1) + regamma_params->arr_curve_points[k].segments_num = + seg_distr[k]; + + rgb = rgb_resulted; + rgb_plus_1 = rgb_resulted + 1; + + i = 1; + + while (i != hw_points + 1) { + if (dal_fixed31_32_lt(rgb_plus_1->red, rgb->red)) + rgb_plus_1->red = rgb->red; + if (dal_fixed31_32_lt(rgb_plus_1->green, rgb->green)) + rgb_plus_1->green = rgb->green; + if (dal_fixed31_32_lt(rgb_plus_1->blue, rgb->blue)) + rgb_plus_1->blue = rgb->blue; + + rgb->delta_red = dal_fixed31_32_sub( + rgb_plus_1->red, + rgb->red); + rgb->delta_green = dal_fixed31_32_sub( + rgb_plus_1->green, + rgb->green); + rgb->delta_blue = dal_fixed31_32_sub( + rgb_plus_1->blue, + rgb->blue); + + ++rgb_plus_1; + ++rgb; + ++i; + } + + convert_to_custom_float(rgb_resulted, arr_points, hw_points); + + return true; +} + +static bool dcn10_set_output_transfer_func( + struct pipe_ctx *pipe_ctx, + const struct core_surface *surface, + const struct core_stream *stream) +{ + struct output_pixel_processor *opp = pipe_ctx->opp; + + opp->regamma_params.hw_points_num = GAMMA_HW_POINTS_NUM; + + if (stream->public.out_transfer_func && + stream->public.out_transfer_func->type == + TF_TYPE_PREDEFINED && + stream->public.out_transfer_func->tf == + TRANSFER_FUNCTION_SRGB) { + opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_SRGB); + } else if (dcn10_translate_regamma_to_hw_format( + stream->public.out_transfer_func, &opp->regamma_params)) { + opp->funcs->opp_program_regamma_pwl(opp, &opp->regamma_params); + opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_USER); + } else { + opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_BYPASS); + } + + return true; +} + +static void dcn10_pipe_control_lock( + struct core_dc *dc, + struct pipe_ctx *pipe, + bool lock) +{ + struct dce_hwseq *hws = hws = dc->hwseq; + + /* use TG master update lock to lock everything on the TG + * therefore only top pipe need to lock + */ + if (pipe->top_pipe) + return; + + if (lock) + dcn10_lock(pipe->tg); + else + dcn10_unlock(pipe->tg); +} + +static bool wait_for_reset_trigger_to_occur( + struct dc_context *dc_ctx, + struct timing_generator *tg) +{ + bool rc = false; + + /* To avoid endless loop we wait at most + * frames_to_wait_on_triggered_reset frames for the reset to occur. */ + const uint32_t frames_to_wait_on_triggered_reset = 10; + int i; + + for (i = 0; i < frames_to_wait_on_triggered_reset; i++) { + + if (!tg->funcs->is_counter_moving(tg)) { + DC_ERROR("TG counter is not moving!\n"); + break; + } + + if (tg->funcs->did_triggered_reset_occur(tg)) { + rc = true; + /* usually occurs at i=1 */ + DC_SYNC_INFO("GSL: reset occurred at wait count: %d\n", + i); + break; + } + + /* Wait for one frame. */ + tg->funcs->wait_for_state(tg, CRTC_STATE_VACTIVE); + tg->funcs->wait_for_state(tg, CRTC_STATE_VBLANK); + } + + if (false == rc) + DC_ERROR("GSL: Timeout on reset trigger!\n"); + + return rc; +} + +static void dcn10_enable_timing_synchronization( + struct core_dc *dc, + int group_index, + int group_size, + struct pipe_ctx *grouped_pipes[]) +{ + struct dc_context *dc_ctx = dc->ctx; + int i; + + DC_SYNC_INFO("Setting up OTG reset trigger\n"); + + for (i = 1; i < group_size; i++) + grouped_pipes[i]->tg->funcs->enable_reset_trigger( + grouped_pipes[i]->tg, grouped_pipes[0]->tg->inst); + + + DC_SYNC_INFO("Waiting for trigger\n"); + + /* Need to get only check 1 pipe for having reset as all the others are + * synchronized. Look at last pipe programmed to reset. + */ + wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[1]->tg); + for (i = 1; i < group_size; i++) + grouped_pipes[i]->tg->funcs->disable_reset_trigger( + grouped_pipes[i]->tg); + + DC_SYNC_INFO("Sync complete\n"); +} + +static void dcn10_power_on_fe( + struct core_dc *dc, + struct pipe_ctx *pipe_ctx, + struct validate_context *context) +{ + struct dc_surface *dc_surface = &pipe_ctx->surface->public; + + /* power up DCHUP and DPP from pseudo code pipe_move.c */ + /*TODO: function: power_on_plane. If already power up, skip + */ + { + power_on_plane(dc->ctx, + pipe_ctx->pipe_idx, pipe_ctx->tg->inst); + + /* enable DCFCLK current DCHUB */ + enable_dcfclk(dc->ctx, + pipe_ctx->pipe_idx, + pipe_ctx->pix_clk_params.requested_pix_clk, + context->dppclk_div); + + if (dc_surface) { + dm_logger_write(dc->ctx->logger, LOG_DC, + "Pipe:%d 0x%x: addr hi:0x%x, " + "addr low:0x%x, " + "src: %d, %d, %d," + " %d; dst: %d, %d, %d, %d;\n", + pipe_ctx->pipe_idx, + dc_surface, + dc_surface->address.grph.addr.high_part, + dc_surface->address.grph.addr.low_part, + dc_surface->src_rect.x, + dc_surface->src_rect.y, + dc_surface->src_rect.width, + dc_surface->src_rect.height, + dc_surface->dst_rect.x, + dc_surface->dst_rect.y, + dc_surface->dst_rect.width, + dc_surface->dst_rect.height); + + dm_logger_write(dc->ctx->logger, LOG_HW_SET_MODE, + "Pipe %d: width, height, x, y\n" + "viewport:%d, %d, %d, %d\n" + "recout: %d, %d, %d, %d\n", + pipe_ctx->pipe_idx, + pipe_ctx->scl_data.viewport.width, + pipe_ctx->scl_data.viewport.height, + pipe_ctx->scl_data.viewport.x, + pipe_ctx->scl_data.viewport.y, + pipe_ctx->scl_data.recout.width, + pipe_ctx->scl_data.recout.height, + pipe_ctx->scl_data.recout.x, + pipe_ctx->scl_data.recout.y); + } + } + +} + +static void program_gamut_remap(struct pipe_ctx *pipe_ctx) +{ + struct xfm_grph_csc_adjustment adjust; + memset(&adjust, 0, sizeof(adjust)); + adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS; + + + if (pipe_ctx->stream->public.gamut_remap_matrix.enable_remap == true) { + adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW; + adjust.temperature_matrix[0] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[0]; + adjust.temperature_matrix[1] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[1]; + adjust.temperature_matrix[2] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[2]; + adjust.temperature_matrix[3] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[4]; + adjust.temperature_matrix[4] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[5]; + adjust.temperature_matrix[5] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[6]; + adjust.temperature_matrix[6] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[8]; + adjust.temperature_matrix[7] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[9]; + adjust.temperature_matrix[8] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[10]; + } + + pipe_ctx->xfm->funcs->transform_set_gamut_remap(pipe_ctx->xfm, &adjust); +} + +static void update_dchubp_dpp( + struct core_dc *dc, + struct pipe_ctx *pipe_ctx, + struct validate_context *context) +{ + struct mem_input *mi = pipe_ctx->mi; + struct input_pixel_processor *ipp = pipe_ctx->ipp; + struct core_surface *surface = pipe_ctx->surface; + union plane_size size = surface->public.plane_size; + struct mpc_tree_cfg *tree_cfg = NULL; + struct default_adjustment ocsc = {0}; + enum dc_color_space color_space; + struct tg_color black_color = {0}; + struct dcn10_mpc *mpc = TO_DCN10_MPC(dc->res_pool->mpc); + + /* depends on DML calculation, DPP clock value may change dynamically */ + enable_dppclk( + dc->ctx, + pipe_ctx->pipe_idx, + pipe_ctx->pix_clk_params.requested_pix_clk, + context->dppclk_div); + + select_vtg(dc->ctx, pipe_ctx->pipe_idx, pipe_ctx->tg->inst); + + update_plane_addr(dc, pipe_ctx); + + mi->funcs->mem_input_setup( + mi, + &pipe_ctx->dlg_regs, + &pipe_ctx->ttu_regs, + &pipe_ctx->rq_regs, + &pipe_ctx->pipe_dlg_param); + + size.grph.surface_size = pipe_ctx->scl_data.viewport; + + if (dc->public.config.gpu_vm_support) + mi->funcs->mem_input_program_pte_vm( + pipe_ctx->mi, + surface->public.format, + &surface->public.tiling_info, + surface->public.rotation); + + ipp->funcs->ipp_setup(ipp, + surface->public.format, + 1, + IPP_OUTPUT_FORMAT_12_BIT_FIX); + + /* mpc TODO un-hardcode object ids + * for pseudo code pipe_move.c : + * add_plane_mpcc(added_plane_inst, mpcc_inst, ...); + * Do we want to cache the tree_cfg? + */ + + /* TODO: build stream pipes group id. For now, use stream otg + * id as pipe group id + */ + pipe_ctx->mpc_idx = pipe_ctx->tg->inst; + tree_cfg = &context->res_ctx.mpc_tree[pipe_ctx->mpc_idx]; + /* enable when bottom pipe is present and + * it does not share a surface with current pipe + */ + if (pipe_ctx->bottom_pipe && surface != pipe_ctx->bottom_pipe->surface) { + pipe_ctx->scl_data.lb_params.alpha_en = 1; + tree_cfg->mode = TOP_BLND; + } else { + pipe_ctx->scl_data.lb_params.alpha_en = 0; + tree_cfg->mode = TOP_PASSTHRU; + } + if (!pipe_ctx->top_pipe) { + /* primary pipe, set mpc tree index 0 only */ + tree_cfg->num_pipes = 1; + tree_cfg->opp_id = pipe_ctx->tg->inst; + tree_cfg->dpp[0] = pipe_ctx->pipe_idx; + tree_cfg->mpcc[0] = pipe_ctx->pipe_idx; + dcn10_set_mpc_tree(mpc, tree_cfg); + } else { + /* TODO: add position is hard code to 1 for now + * If more than 2 pipes are supported, calculate position + */ + dcn10_add_dpp(mpc, tree_cfg, + pipe_ctx->pipe_idx, pipe_ctx->pipe_idx, 1); + } + + color_space = pipe_ctx->stream->public.output_color_space; + color_space_to_black_color(dc, color_space, &black_color); + dcn10_set_mpc_background_color(mpc, pipe_ctx->pipe_idx, &black_color); + + pipe_ctx->scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; + /* scaler configuration */ + pipe_ctx->xfm->funcs->transform_set_scaler( + pipe_ctx->xfm, &pipe_ctx->scl_data); + + /*gamut remap*/ + program_gamut_remap(pipe_ctx); + + /*TODO add adjustments parameters*/ + ocsc.out_color_space = pipe_ctx->stream->public.output_color_space; + pipe_ctx->opp->funcs->opp_set_csc_default(pipe_ctx->opp, &ocsc); + + mi->funcs->mem_input_program_surface_config( + mi, + surface->public.format, + &surface->public.tiling_info, + &size, + surface->public.rotation, + &surface->public.dcc, + surface->public.horizontal_mirror, + surface->public.visible); + + /* Only support one plane for now. */ + pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, !surface->public.visible); + +} + +static void program_all_pipe_in_tree( + struct core_dc *dc, + struct pipe_ctx *pipe_ctx, + struct validate_context *context) +{ + unsigned int ref_clk_mhz = dc->res_pool->ref_clock_inKhz/1000; + + if (pipe_ctx->surface->public.visible || pipe_ctx->top_pipe == NULL) { + dcn10_power_on_fe(dc, pipe_ctx, context); + + /* lock otg_master_update to process all pipes associated with + * this OTG. this is done only one time. + */ + if (pipe_ctx->top_pipe == NULL) { + /* watermark is for all pipes */ + pipe_ctx->mi->funcs->program_watermarks( + pipe_ctx->mi, &context->watermarks, ref_clk_mhz); + lock_otg_master_update(dc->ctx, pipe_ctx->tg->inst); + } + pipe_ctx->tg->dlg_otg_param.vready_offset = pipe_ctx->pipe_dlg_param.vready_offset; + pipe_ctx->tg->dlg_otg_param.vstartup_start = pipe_ctx->pipe_dlg_param.vstartup_start; + pipe_ctx->tg->dlg_otg_param.vupdate_offset = pipe_ctx->pipe_dlg_param.vupdate_offset; + pipe_ctx->tg->dlg_otg_param.vupdate_width = pipe_ctx->pipe_dlg_param.vupdate_width; + pipe_ctx->tg->dlg_otg_param.signal = pipe_ctx->stream->signal; + pipe_ctx->tg->funcs->program_global_sync( + pipe_ctx->tg); + update_dchubp_dpp(dc, pipe_ctx, context); + } + + if (pipe_ctx->bottom_pipe != NULL) + program_all_pipe_in_tree(dc, pipe_ctx->bottom_pipe, context); +} + +static void dcn10_pplib_apply_display_requirements( + struct core_dc *dc, + struct validate_context *context) +{ + struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg; + + pp_display_cfg->all_displays_in_sync = false;/*todo*/ + pp_display_cfg->nb_pstate_switch_disable = false; + pp_display_cfg->min_engine_clock_khz = context->dcfclk_khz; + pp_display_cfg->min_memory_clock_khz = context->fclk_khz; + pp_display_cfg->min_engine_clock_deep_sleep_khz = context->dcfclk_deep_sleep_khz; + pp_display_cfg->min_dcfc_deep_sleep_clock_khz = context->dcfclk_deep_sleep_khz; + pp_display_cfg->avail_mclk_switch_time_us = + context->dram_ccm_us > 0 ? context->dram_ccm_us : 0; + pp_display_cfg->avail_mclk_switch_time_in_disp_active_us = + context->min_active_dram_ccm_us > 0 ? context->min_active_dram_ccm_us : 0; + pp_display_cfg->min_dcfclock_khz = context->dcfclk_khz; + pp_display_cfg->disp_clk_khz = context->dispclk_khz; + dce110_fill_display_configs(context, pp_display_cfg); + + if (memcmp(&dc->prev_display_config, pp_display_cfg, sizeof( + struct dm_pp_display_configuration)) != 0) + dm_pp_apply_display_requirements(dc->ctx, pp_display_cfg); + + dc->prev_display_config = *pp_display_cfg; +} + +static void dcn10_apply_ctx_for_surface( + struct core_dc *dc, + struct core_surface *surface, + struct validate_context *context) +{ + int i; + + memcpy(context->res_ctx.mpc_tree, + dc->current_context->res_ctx.mpc_tree, + sizeof(struct mpc_tree_cfg) * dc->res_pool->pipe_count); + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + + if (!pipe_ctx->surface) + continue; + + /* looking for top pipe to program */ + if (!pipe_ctx->top_pipe) + program_all_pipe_in_tree(dc, pipe_ctx, context); + } + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + + if (!pipe_ctx->surface || pipe_ctx->top_pipe) + continue; + + /* unlock master update lock */ + unlock_otg_master(dc->ctx, pipe_ctx->tg->inst); + } + + /* reset unused pipe */ + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *old_pipe_ctx = + &dc->current_context->res_ctx.pipe_ctx[i]; + + if ((!pipe_ctx->surface && old_pipe_ctx->surface) + || (!pipe_ctx->stream && old_pipe_ctx->stream)) + reset_front_end_for_pipe(dc, + old_pipe_ctx, dc->current_context); + } +} + +static void dcn10_set_bandwidth( + struct core_dc *dc, + struct validate_context *context, + bool decrease_allowed) +{ + struct dm_pp_clock_for_voltage_req clock; + + if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) + return; + + if (decrease_allowed || context->dispclk_khz > dc->current_context->dispclk_khz) { + dc->res_pool->display_clock->funcs->set_clock( + dc->res_pool->display_clock, + context->dispclk_khz); + dc->current_context->dispclk_khz = context->dispclk_khz; + } + if (decrease_allowed || context->dcfclk_khz > dc->current_context->dcfclk_khz) { + clock.clk_type = DM_PP_CLOCK_TYPE_DCFCLK; + clock.clocks_in_khz = context->dcfclk_khz; + dm_pp_apply_clock_for_voltage_request(dc->ctx, &clock); + } + if (decrease_allowed || context->fclk_khz > dc->current_context->fclk_khz) { + clock.clk_type = DM_PP_CLOCK_TYPE_FCLK; + clock.clocks_in_khz = context->fclk_khz; + dm_pp_apply_clock_for_voltage_request(dc->ctx, &clock); + dc->current_context->fclk_khz = clock.clocks_in_khz ; + } + dcn10_pplib_apply_display_requirements(dc, context); +} + +static void dcn10_power_down_fe(struct core_dc *dc, struct pipe_ctx *pipe) +{ + struct dc_context *ctx = dc->ctx; + uint32_t inst_offset = 0; + + HWSEQ_REG_SET(DC_IP_REQUEST_CNTL, + IP_REQUEST_EN, 1); + dpp_pg_control(ctx, pipe->pipe_idx, false); + hubp_pg_control(ctx, pipe->pipe_idx, false); + HWSEQ_REG_SET(DC_IP_REQUEST_CNTL, + IP_REQUEST_EN, 0); + + if (pipe->xfm) + pipe->xfm->funcs->transform_reset(pipe->xfm); + memset(&pipe->scl_data, 0, sizeof(pipe->scl_data)); +} + +static void set_drr(struct pipe_ctx **pipe_ctx, + int num_pipes, int vmin, int vmax) +{ + int i = 0; + struct drr_params params = {0}; + + params.vertical_total_max = vmax; + params.vertical_total_min = vmin; + + /* TODO: If multiple pipes are to be supported, you need + * some GSL stuff + */ + for (i = 0; i < num_pipes; i++) { + pipe_ctx[i]->tg->funcs->set_drr(pipe_ctx[i]->tg, ¶ms); + } +} + +static void get_position(struct pipe_ctx **pipe_ctx, + int num_pipes, + struct crtc_position *position) +{ + int i = 0; + + /* TODO: handle pipes > 1 + */ + for (i = 0; i < num_pipes; i++) + pipe_ctx[i]->tg->funcs->get_position(pipe_ctx[i]->tg, position); +} + +static void set_static_screen_control(struct pipe_ctx **pipe_ctx, + int num_pipes, const struct dc_static_screen_events *events) +{ + unsigned int i; + unsigned int value = 0; + + if (events->surface_update) + value |= 0x80; + if (events->cursor_update) + value |= 0x2; + + for (i = 0; i < num_pipes; i++) + pipe_ctx[i]->tg->funcs-> + set_static_screen_control(pipe_ctx[i]->tg, value); +} + +static void set_plane_config( + const struct core_dc *dc, + struct pipe_ctx *pipe_ctx, + struct resource_context *res_ctx) +{ + /* TODO */ + program_gamut_remap(pipe_ctx); +} + +static const struct hw_sequencer_funcs dcn10_funcs = { + .init_hw = init_hw, + .apply_ctx_to_hw = dce110_apply_ctx_to_hw, + .apply_ctx_for_surface = dcn10_apply_ctx_for_surface, + .set_plane_config = set_plane_config, + .update_plane_addr = update_plane_addr, + .update_pending_status = dce110_update_pending_status, + .set_input_transfer_func = dcn10_set_input_transfer_func, + .set_output_transfer_func = dcn10_set_output_transfer_func, + .power_down = dce110_power_down, + .enable_accelerated_mode = dce110_enable_accelerated_mode, + .enable_timing_synchronization = dcn10_enable_timing_synchronization, + .update_info_frame = dce110_update_info_frame, + .enable_stream = dce110_enable_stream, + .disable_stream = dce110_disable_stream, + .unblank_stream = dce110_unblank_stream, + .enable_display_pipe_clock_gating = NULL, /* TODOFPGA */ + .enable_display_power_gating = dcn10_enable_display_power_gating, + .power_down_front_end = dcn10_power_down_fe, + .power_on_front_end = dcn10_power_on_fe, + .pipe_control_lock = dcn10_pipe_control_lock, + .set_bandwidth = dcn10_set_bandwidth, + .reset_hw_ctx_wrap = reset_hw_ctx_wrap, + .prog_pixclk_crtc_otg = dcn10_prog_pixclk_crtc_otg, + .set_drr = set_drr, + .get_position = get_position, + .set_static_screen_control = set_static_screen_control +}; + + +bool dcn10_hw_sequencer_construct(struct core_dc *dc) +{ + dc->hwss = dcn10_funcs; + return true; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h new file mode 100644 index 000000000000..c3aff2eb8d68 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h @@ -0,0 +1,38 @@ +/* +* Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_HWSS_DCN10_H__ +#define __DC_HWSS_DCN10_H__ + +#include "core_types.h" + +struct core_dc; + +bool dcn10_hw_sequencer_construct(struct core_dc *dc); +extern void fill_display_configs( + const struct validate_context *context, + struct dm_pp_display_configuration *pp_display_cfg); + +#endif /* __DC_HWSS_DCN10_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c new file mode 100644 index 000000000000..3062b7de4fe2 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c @@ -0,0 +1,883 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "dcn10_ipp.h" +#include "reg_helper.h" + +#define REG(reg) \ + (ippn10->regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + ippn10->ipp_shift->field_name, ippn10->ipp_mask->field_name + +#define CTX \ + ippn10->base.ctx + + +struct dcn10_input_csc_matrix { + enum dc_color_space color_space; + uint32_t regval[12]; +}; + +static const struct dcn10_input_csc_matrix dcn10_input_csc_matrix[] = { + {COLOR_SPACE_SRGB, + {0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} }, + {COLOR_SPACE_SRGB_LIMITED, + {0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} }, + {COLOR_SPACE_YCBCR601, + {0x2cdd, 0x2000, 0, 0xe991, 0xe926, 0x2000, 0xf4fd, 0x10ef, + 0, 0x2000, 0x38b4, 0xe3a6} }, + {COLOR_SPACE_YCBCR601_LIMITED, + {0x3353, 0x2568, 0, 0xe400, 0xe5dc, 0x2568, 0xf367, 0x1108, + 0, 0x2568, 0x40de, 0xdd3a} }, + {COLOR_SPACE_YCBCR709, + {0x3265, 0x2000, 0, 0xe6ce, 0xf105, 0x2000, 0xfa01, 0xa7d, 0, + 0x2000, 0x3b61, 0xe24f} }, + + {COLOR_SPACE_YCBCR709_LIMITED, + {0x39a6, 0x2568, 0, 0xe0d6, 0xeedd, 0x2568, 0xf925, 0x9a8, 0, + 0x2568, 0x43ee, 0xdbb2} } +}; + +enum dcn10_input_csc_select { + INPUT_CSC_SELECT_BYPASS = 0, + INPUT_CSC_SELECT_ICSC, + INPUT_CSC_SELECT_COMA +}; + +static void dcn10_program_input_csc( + struct input_pixel_processor *ipp, + enum dc_color_space color_space, + enum dcn10_input_csc_select select) +{ + struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); + int i; + int arr_size = sizeof(dcn10_input_csc_matrix)/sizeof(struct dcn10_input_csc_matrix); + const uint32_t *regval = NULL; + uint32_t selection = 1; + + if (select == INPUT_CSC_SELECT_BYPASS) { + REG_SET(CM_ICSC_CONTROL, 0, CM_ICSC_MODE, 0); + return; + } + + for (i = 0; i < arr_size; i++) + if (dcn10_input_csc_matrix[i].color_space == color_space) { + regval = dcn10_input_csc_matrix[i].regval; + break; + } + + if (regval == NULL) { + BREAK_TO_DEBUGGER(); + return; + } + + if (select == INPUT_CSC_SELECT_COMA) + selection = 2; + REG_SET(CM_ICSC_CONTROL, 0, + CM_ICSC_MODE, selection); + + if (select == INPUT_CSC_SELECT_ICSC) { + /*R*/ + REG_SET_2(CM_ICSC_C11_C12, 0, + CM_ICSC_C11, regval[0], + CM_ICSC_C12, regval[1]); + regval += 2; + REG_SET_2(CM_ICSC_C13_C14, 0, + CM_ICSC_C13, regval[0], + CM_ICSC_C14, regval[1]); + /*G*/ + regval += 2; + REG_SET_2(CM_ICSC_C21_C22, 0, + CM_ICSC_C21, regval[0], + CM_ICSC_C22, regval[1]); + regval += 2; + REG_SET_2(CM_ICSC_C23_C24, 0, + CM_ICSC_C23, regval[0], + CM_ICSC_C24, regval[1]); + /*B*/ + regval += 2; + REG_SET_2(CM_ICSC_C31_C32, 0, + CM_ICSC_C31, regval[0], + CM_ICSC_C32, regval[1]); + regval += 2; + REG_SET_2(CM_ICSC_C33_C34, 0, + CM_ICSC_C33, regval[0], + CM_ICSC_C34, regval[1]); + } else { + /*R*/ + REG_SET_2(CM_COMA_C11_C12, 0, + CM_COMA_C11, regval[0], + CM_COMA_C12, regval[1]); + regval += 2; + REG_SET_2(CM_COMA_C13_C14, 0, + CM_COMA_C13, regval[0], + CM_COMA_C14, regval[1]); + /*G*/ + regval += 2; + REG_SET_2(CM_COMA_C21_C22, 0, + CM_COMA_C21, regval[0], + CM_COMA_C22, regval[1]); + regval += 2; + REG_SET_2(CM_COMA_C23_C24, 0, + CM_COMA_C23, regval[0], + CM_COMA_C24, regval[1]); + /*B*/ + regval += 2; + REG_SET_2(CM_COMA_C31_C32, 0, + CM_COMA_C31, regval[0], + CM_COMA_C32, regval[1]); + regval += 2; + REG_SET_2(CM_COMA_C33_C34, 0, + CM_COMA_C33, regval[0], + CM_COMA_C34, regval[1]); + } +} + +/*program de gamma RAM B*/ +static void dcn10_ipp_program_degamma_lutb_settings( + struct input_pixel_processor *ipp, + const struct pwl_params *params) +{ + const struct gamma_curve *curve; + struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); + + REG_SET_2(CM_DGAM_RAMB_START_CNTL_B, 0, + CM_DGAM_RAMB_EXP_REGION_START_B, params->arr_points[0].custom_float_x, + CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_B, 0); + + REG_SET_2(CM_DGAM_RAMB_START_CNTL_G, 0, + CM_DGAM_RAMB_EXP_REGION_START_G, params->arr_points[0].custom_float_x, + CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_G, 0); + + REG_SET_2(CM_DGAM_RAMB_START_CNTL_R, 0, + CM_DGAM_RAMB_EXP_REGION_START_R, params->arr_points[0].custom_float_x, + CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_R, 0); + + REG_SET(CM_DGAM_RAMB_SLOPE_CNTL_B, 0, + CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B, params->arr_points[0].custom_float_slope); + + REG_SET(CM_DGAM_RAMB_SLOPE_CNTL_G, 0, + CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_G, params->arr_points[0].custom_float_slope); + + REG_SET(CM_DGAM_RAMB_SLOPE_CNTL_R, 0, + CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_R, params->arr_points[0].custom_float_slope); + + REG_SET(CM_DGAM_RAMB_END_CNTL1_B, 0, + CM_DGAM_RAMB_EXP_REGION_END_B, params->arr_points[1].custom_float_x); + + REG_SET_2(CM_DGAM_RAMB_END_CNTL2_B, 0, + CM_DGAM_RAMB_EXP_REGION_END_SLOPE_B, params->arr_points[1].custom_float_y, + CM_DGAM_RAMB_EXP_REGION_END_BASE_B, params->arr_points[2].custom_float_slope); + + REG_SET(CM_DGAM_RAMB_END_CNTL1_G, 0, + CM_DGAM_RAMB_EXP_REGION_END_G, params->arr_points[1].custom_float_x); + + REG_SET_2(CM_DGAM_RAMB_END_CNTL2_G, 0, + CM_DGAM_RAMB_EXP_REGION_END_SLOPE_G, params->arr_points[1].custom_float_y, + CM_DGAM_RAMB_EXP_REGION_END_BASE_G, params->arr_points[2].custom_float_slope); + + REG_SET(CM_DGAM_RAMB_END_CNTL1_R, 0, + CM_DGAM_RAMB_EXP_REGION_END_R, params->arr_points[1].custom_float_x); + + REG_SET_2(CM_DGAM_RAMB_END_CNTL2_R, 0, + CM_DGAM_RAMB_EXP_REGION_END_SLOPE_R, params->arr_points[1].custom_float_y, + CM_DGAM_RAMB_EXP_REGION_END_BASE_R, params->arr_points[2].custom_float_slope); + + curve = params->arr_curve_points; + REG_SET_4(CM_DGAM_RAMB_REGION_0_1, 0, + CM_DGAM_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMB_REGION_2_3, 0, + CM_DGAM_RAMB_EXP_REGION2_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMB_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMB_EXP_REGION3_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMB_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMB_REGION_4_5, 0, + CM_DGAM_RAMB_EXP_REGION4_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMB_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMB_EXP_REGION5_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMB_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMB_REGION_6_7, 0, + CM_DGAM_RAMB_EXP_REGION6_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMB_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMB_EXP_REGION7_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMB_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMB_REGION_8_9, 0, + CM_DGAM_RAMB_EXP_REGION8_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMB_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMB_EXP_REGION9_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMB_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMB_REGION_10_11, 0, + CM_DGAM_RAMB_EXP_REGION10_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMB_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMB_EXP_REGION11_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMB_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMB_REGION_12_13, 0, + CM_DGAM_RAMB_EXP_REGION12_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMB_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMB_EXP_REGION13_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMB_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMB_REGION_14_15, 0, + CM_DGAM_RAMB_EXP_REGION14_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMB_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMB_EXP_REGION15_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMB_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num); +} + +/*program de gamma RAM A*/ +static void dcn10_ipp_program_degamma_luta_settings( + struct input_pixel_processor *ipp, + const struct pwl_params *params) +{ + const struct gamma_curve *curve; + struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); + + REG_SET_2(CM_DGAM_RAMA_START_CNTL_B, 0, + CM_DGAM_RAMA_EXP_REGION_START_B, params->arr_points[0].custom_float_x, + CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_B, 0); + + REG_SET_2(CM_DGAM_RAMA_START_CNTL_G, 0, + CM_DGAM_RAMA_EXP_REGION_START_G, params->arr_points[0].custom_float_x, + CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_G, 0); + + REG_SET_2(CM_DGAM_RAMA_START_CNTL_R, 0, + CM_DGAM_RAMA_EXP_REGION_START_R, params->arr_points[0].custom_float_x, + CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_R, 0); + + REG_SET(CM_DGAM_RAMA_SLOPE_CNTL_B, 0, + CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B, params->arr_points[0].custom_float_slope); + + REG_SET(CM_DGAM_RAMA_SLOPE_CNTL_G, 0, + CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G, params->arr_points[0].custom_float_slope); + + REG_SET(CM_DGAM_RAMA_SLOPE_CNTL_R, 0, + CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R, params->arr_points[0].custom_float_slope); + + REG_SET(CM_DGAM_RAMA_END_CNTL1_B, 0, + CM_DGAM_RAMA_EXP_REGION_END_B, params->arr_points[1].custom_float_x); + + REG_SET_2(CM_DGAM_RAMA_END_CNTL2_B, 0, + CM_DGAM_RAMA_EXP_REGION_END_SLOPE_B, params->arr_points[1].custom_float_y, + CM_DGAM_RAMA_EXP_REGION_END_BASE_B, params->arr_points[2].custom_float_slope); + + REG_SET(CM_DGAM_RAMA_END_CNTL1_G, 0, + CM_DGAM_RAMA_EXP_REGION_END_G, params->arr_points[1].custom_float_x); + + REG_SET_2(CM_DGAM_RAMA_END_CNTL2_G, 0, + CM_DGAM_RAMA_EXP_REGION_END_SLOPE_G, params->arr_points[1].custom_float_y, + CM_DGAM_RAMA_EXP_REGION_END_BASE_G, params->arr_points[2].custom_float_slope); + + REG_SET(CM_DGAM_RAMA_END_CNTL1_R, 0, + CM_DGAM_RAMA_EXP_REGION_END_R, params->arr_points[1].custom_float_x); + + REG_SET_2(CM_DGAM_RAMA_END_CNTL2_R, 0, + CM_DGAM_RAMA_EXP_REGION_END_SLOPE_R, params->arr_points[1].custom_float_y, + CM_DGAM_RAMA_EXP_REGION_END_BASE_R, params->arr_points[2].custom_float_slope); + + curve = params->arr_curve_points; + REG_SET_4(CM_DGAM_RAMA_REGION_0_1, 0, + CM_DGAM_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMA_REGION_2_3, 0, + CM_DGAM_RAMA_EXP_REGION2_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMA_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMA_EXP_REGION3_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMA_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMA_REGION_4_5, 0, + CM_DGAM_RAMA_EXP_REGION4_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMA_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMA_EXP_REGION5_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMA_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMA_REGION_6_7, 0, + CM_DGAM_RAMA_EXP_REGION6_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMA_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMA_EXP_REGION7_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMA_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMA_REGION_8_9, 0, + CM_DGAM_RAMA_EXP_REGION8_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMA_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMA_EXP_REGION9_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMA_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMA_REGION_10_11, 0, + CM_DGAM_RAMA_EXP_REGION10_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMA_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMA_EXP_REGION11_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMA_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMA_REGION_12_13, 0, + CM_DGAM_RAMA_EXP_REGION12_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMA_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMA_EXP_REGION13_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMA_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMA_REGION_14_15, 0, + CM_DGAM_RAMA_EXP_REGION14_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMA_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMA_EXP_REGION15_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMA_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num); +} + +static void ipp_power_on_degamma_lut( + struct input_pixel_processor *ipp, + bool power_on) +{ + struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); + + REG_SET(CM_MEM_PWR_CTRL, 0, + SHARED_MEM_PWR_DIS, power_on == true ? 0:1); + +} + +static void ipp_program_degamma_lut( + struct input_pixel_processor *ipp, + const struct pwl_result_data *rgb, + uint32_t num, + bool is_ram_a) +{ + uint32_t i; + + struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); + REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_HOST_EN, 0); + REG_UPDATE(CM_DGAM_LUT_WRITE_EN_MASK, + CM_DGAM_LUT_WRITE_EN_MASK, 7); + REG_UPDATE(CM_DGAM_LUT_WRITE_EN_MASK, CM_DGAM_LUT_WRITE_SEL, + is_ram_a == true ? 0:1); + + REG_SET(CM_DGAM_LUT_INDEX, 0, CM_DGAM_LUT_INDEX, 0); + for (i = 0 ; i < num; i++) { + REG_SET(CM_DGAM_LUT_DATA, 0, CM_DGAM_LUT_DATA, rgb[i].red_reg); + REG_SET(CM_DGAM_LUT_DATA, 0, CM_DGAM_LUT_DATA, rgb[i].green_reg); + REG_SET(CM_DGAM_LUT_DATA, 0, CM_DGAM_LUT_DATA, rgb[i].blue_reg); + + REG_SET(CM_DGAM_LUT_DATA, 0, + CM_DGAM_LUT_DATA, rgb[i].delta_red_reg); + REG_SET(CM_DGAM_LUT_DATA, 0, + CM_DGAM_LUT_DATA, rgb[i].delta_green_reg); + REG_SET(CM_DGAM_LUT_DATA, 0, + CM_DGAM_LUT_DATA, rgb[i].delta_blue_reg); + + } + +} + +static void dcn10_ipp_enable_cm_block( + struct input_pixel_processor *ipp) +{ + struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); + + REG_UPDATE(DPP_CONTROL, DPP_CLOCK_ENABLE, 1); + REG_UPDATE(CM_CONTROL, CM_BYPASS_EN, 0); +} + + +static void dcn10_ipp_full_bypass(struct input_pixel_processor *ipp) +{ + struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); + + /* Input pixel format: ARGB8888 */ + REG_SET(CNVC_SURFACE_PIXEL_FORMAT, 0, + CNVC_SURFACE_PIXEL_FORMAT, 0x8); + + /* Zero expansion */ + REG_SET_3(FORMAT_CONTROL, 0, + CNVC_BYPASS, 0, + ALPHA_EN, 0, + FORMAT_EXPANSION_MODE, 0); + + /* COLOR_KEYER_CONTROL.COLOR_KEYER_EN = 0 this should be default */ + REG_SET(CM_CONTROL, 0, CM_BYPASS_EN, 1); + + /* Setting degamma bypass for now */ + REG_SET(CM_DGAM_CONTROL, 0, CM_DGAM_LUT_MODE, 0); + REG_SET(CM_IGAM_CONTROL, 0, CM_IGAM_LUT_MODE, 0); +} + +static void dcn10_ipp_set_degamma( + struct input_pixel_processor *ipp, + enum ipp_degamma_mode mode) +{ + struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); + dcn10_ipp_enable_cm_block(ipp); + + switch (mode) { + case IPP_DEGAMMA_MODE_BYPASS: + /* Setting de gamma bypass for now */ + REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 0); + break; + case IPP_DEGAMMA_MODE_HW_sRGB: + REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 1); + break; + case IPP_DEGAMMA_MODE_HW_xvYCC: + REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 2); + break; + default: + BREAK_TO_DEBUGGER(); + break; + } +} + +static bool dcn10_cursor_program_control( + struct dcn10_ipp *ippn10, + bool pixel_data_invert, + enum dc_cursor_color_format color_format) +{ + REG_SET_2(CURSOR_SETTINS, 0, + /* no shift of the cursor HDL schedule */ + CURSOR0_DST_Y_OFFSET, 0, + /* used to shift the cursor chunk request deadline */ + CURSOR0_CHUNK_HDL_ADJUST, 3); + + REG_UPDATE_2(CURSOR0_CONTROL, + CUR0_MODE, color_format, + CUR0_INVERT_MODE, 0); + + if (color_format == CURSOR_MODE_MONO) { + /* todo: clarify what to program these to */ + REG_UPDATE(CURSOR0_COLOR0, + CUR0_COLOR0, 0x00000000); + REG_UPDATE(CURSOR0_COLOR1, + CUR0_COLOR1, 0xFFFFFFFF); + } + + /* TODO: Fixed vs float */ + + REG_UPDATE_3(FORMAT_CONTROL, + CNVC_BYPASS, 0, + ALPHA_EN, 1, + FORMAT_EXPANSION_MODE, 0); + + REG_UPDATE(CURSOR0_CONTROL, + CUR0_EXPANSION_MODE, 0); + + if (0 /*attributes->attribute_flags.bits.MIN_MAX_INVERT*/) { + REG_UPDATE(CURSOR0_CONTROL, + CUR0_MAX, + 0 /* TODO */); + REG_UPDATE(CURSOR0_CONTROL, + CUR0_MIN, + 0 /* TODO */); + } + + return true; +} + +enum cursor_pitch { + CURSOR_PITCH_64_PIXELS = 0, + CURSOR_PITCH_128_PIXELS, + CURSOR_PITCH_256_PIXELS +}; + +enum cursor_lines_per_chunk { + CURSOR_LINE_PER_CHUNK_2 = 1, + CURSOR_LINE_PER_CHUNK_4, + CURSOR_LINE_PER_CHUNK_8, + CURSOR_LINE_PER_CHUNK_16 +}; + +static enum cursor_pitch dcn10_get_cursor_pitch( + unsigned int pitch) +{ + enum cursor_pitch hw_pitch; + + switch (pitch) { + case 64: + hw_pitch = CURSOR_PITCH_64_PIXELS; + break; + case 128: + hw_pitch = CURSOR_PITCH_128_PIXELS; + break; + case 256: + hw_pitch = CURSOR_PITCH_256_PIXELS; + break; + default: + DC_ERR("Invalid cursor pitch of %d. " + "Only 64/128/256 is supported on DCN.\n", pitch); + hw_pitch = CURSOR_PITCH_64_PIXELS; + break; + } + return hw_pitch; +} + +static enum cursor_lines_per_chunk dcn10_get_lines_per_chunk( + unsigned int cur_width, + enum dc_cursor_color_format format) +{ + enum cursor_lines_per_chunk line_per_chunk; + + if (format == CURSOR_MODE_MONO) + /* impl B. expansion in CUR Buffer reader */ + line_per_chunk = CURSOR_LINE_PER_CHUNK_16; + else if (cur_width <= 32) + line_per_chunk = CURSOR_LINE_PER_CHUNK_16; + else if (cur_width <= 64) + line_per_chunk = CURSOR_LINE_PER_CHUNK_8; + else if (cur_width <= 128) + line_per_chunk = CURSOR_LINE_PER_CHUNK_4; + else + line_per_chunk = CURSOR_LINE_PER_CHUNK_2; + + return line_per_chunk; +} + +static void dcn10_cursor_set_attributes( + struct input_pixel_processor *ipp, + const struct dc_cursor_attributes *attr) +{ + struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); + enum cursor_pitch hw_pitch = dcn10_get_cursor_pitch(attr->pitch); + enum cursor_lines_per_chunk lpc = dcn10_get_lines_per_chunk( + attr->width, attr->color_format); + + ippn10->curs_attr = *attr; + + REG_UPDATE(CURSOR_SURFACE_ADDRESS_HIGH, + CURSOR_SURFACE_ADDRESS_HIGH, attr->address.high_part); + REG_UPDATE(CURSOR_SURFACE_ADDRESS, + CURSOR_SURFACE_ADDRESS, attr->address.low_part); + + REG_UPDATE_2(CURSOR_SIZE, + CURSOR_WIDTH, attr->width, + CURSOR_HEIGHT, attr->height); + + REG_UPDATE_3(CURSOR_CONTROL, + CURSOR_MODE, attr->color_format, + CURSOR_PITCH, hw_pitch, + CURSOR_LINES_PER_CHUNK, lpc); + + dcn10_cursor_program_control(ippn10, + attr->attribute_flags.bits.INVERT_PIXEL_DATA, + attr->color_format); +} + +static void dcn10_cursor_set_position( + struct input_pixel_processor *ipp, + const struct dc_cursor_position *pos, + const struct dc_cursor_mi_param *param) +{ + struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); + int src_x_offset = pos->x - pos->x_hotspot - param->viewport_x_start; + uint32_t cur_en = pos->enable ? 1 : 0; + uint32_t dst_x_offset = (src_x_offset >= 0) ? src_x_offset : 0; + + dst_x_offset *= param->ref_clk_khz; + dst_x_offset /= param->pixel_clk_khz; + + ASSERT(param->h_scale_ratio.value); + + if (param->h_scale_ratio.value) + dst_x_offset = dal_fixed31_32_floor(dal_fixed31_32_div( + dal_fixed31_32_from_int(dst_x_offset), + param->h_scale_ratio)); + + if (src_x_offset >= (int)param->viewport_width) + cur_en = 0; /* not visible beyond right edge*/ + + if (src_x_offset + (int)ippn10->curs_attr.width < 0) + cur_en = 0; /* not visible beyond left edge*/ + + if (cur_en && REG_READ(CURSOR_SURFACE_ADDRESS) == 0) + dcn10_cursor_set_attributes(ipp, &ippn10->curs_attr); + REG_UPDATE(CURSOR_CONTROL, + CURSOR_ENABLE, cur_en); + REG_UPDATE(CURSOR0_CONTROL, + CUR0_ENABLE, cur_en); + + REG_SET_2(CURSOR_POSITION, 0, + CURSOR_X_POSITION, pos->x, + CURSOR_Y_POSITION, pos->y); + + REG_SET_2(CURSOR_HOT_SPOT, 0, + CURSOR_HOT_SPOT_X, pos->x_hotspot, + CURSOR_HOT_SPOT_Y, pos->y_hotspot); + + REG_SET(CURSOR_DST_OFFSET, 0, + CURSOR_DST_X_OFFSET, dst_x_offset); + /* TODO Handle surface pixel formats other than 4:4:4 */ +} + +enum pixel_format_description { + PIXEL_FORMAT_FIXED = 0, + PIXEL_FORMAT_FIXED16, + PIXEL_FORMAT_FLOAT + +}; + +static void dcn10_setup_format_flags(enum surface_pixel_format input_format,\ + enum pixel_format_description *fmt) +{ + + if (input_format == SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F || + input_format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F) + *fmt = PIXEL_FORMAT_FLOAT; + else if (input_format == SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616) + *fmt = PIXEL_FORMAT_FIXED16; + else + *fmt = PIXEL_FORMAT_FIXED; +} + +static void dcn10_ipp_set_degamma_format_float(struct input_pixel_processor *ipp, + bool is_float) +{ + struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); + + if (is_float) { + REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_INPUT_FORMAT, 3); + REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, 1); + } else { + REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_INPUT_FORMAT, 2); + REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, 0); + } +} + + +static void dcn10_ipp_cnv_setup ( + struct input_pixel_processor *ipp, + enum surface_pixel_format input_format, + enum expansion_mode mode, + enum ipp_output_format cnv_out_format) +{ + uint32_t pixel_format; + uint32_t alpha_en; + enum pixel_format_description fmt ; + enum dc_color_space color_space; + enum dcn10_input_csc_select select; + bool is_float; + struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); + bool force_disable_cursor = false; + + dcn10_setup_format_flags(input_format, &fmt); + alpha_en = 1; + pixel_format = 0; + color_space = COLOR_SPACE_SRGB; + select = INPUT_CSC_SELECT_BYPASS; + is_float = false; + + switch (fmt) { + case PIXEL_FORMAT_FIXED: + case PIXEL_FORMAT_FIXED16: + /*when output is float then FORMAT_CONTROL__OUTPUT_FP=1*/ + REG_SET_3(FORMAT_CONTROL, 0, + CNVC_BYPASS, 0, + FORMAT_EXPANSION_MODE, mode, + OUTPUT_FP, 0); + break; + case PIXEL_FORMAT_FLOAT: + REG_SET_3(FORMAT_CONTROL, 0, + CNVC_BYPASS, 0, + FORMAT_EXPANSION_MODE, mode, + OUTPUT_FP, 1); + is_float = true; + break; + default: + + break; + } + + dcn10_ipp_set_degamma_format_float(ipp, is_float); + + switch (input_format) { + case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: + pixel_format = 1; + break; + case SURFACE_PIXEL_FORMAT_GRPH_RGB565: + pixel_format = 3; + alpha_en = 0; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: + pixel_format = 8; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: + pixel_format = 10; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: + force_disable_cursor = false; + pixel_format = 65; + color_space = COLOR_SPACE_YCBCR709; + select = INPUT_CSC_SELECT_ICSC; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: + force_disable_cursor = true; + pixel_format = 64; + color_space = COLOR_SPACE_YCBCR709; + select = INPUT_CSC_SELECT_ICSC; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: + force_disable_cursor = true; + pixel_format = 67; + color_space = COLOR_SPACE_YCBCR709; + select = INPUT_CSC_SELECT_ICSC; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: + force_disable_cursor = true; + pixel_format = 66; + color_space = COLOR_SPACE_YCBCR709; + select = INPUT_CSC_SELECT_ICSC; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: + pixel_format = 22; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: + pixel_format = 24; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: + pixel_format = 25; + break; + default: + break; + } + REG_SET(CNVC_SURFACE_PIXEL_FORMAT, 0, + CNVC_SURFACE_PIXEL_FORMAT, pixel_format); + REG_UPDATE(FORMAT_CONTROL, ALPHA_EN, alpha_en); + + dcn10_program_input_csc(ipp, color_space, select); + + if (force_disable_cursor) { + REG_UPDATE(CURSOR_CONTROL, + CURSOR_ENABLE, 0); + REG_UPDATE(CURSOR0_CONTROL, + CUR0_ENABLE, 0); + } +} + + +static bool dcn10_degamma_ram_inuse(struct input_pixel_processor *ipp, + bool *ram_a_inuse) +{ + bool ret = false; + uint32_t status_reg = 0; + struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); + + status_reg = (REG_READ(CM_IGAM_LUT_RW_CONTROL) & 0x0F00) >>16; + if (status_reg == 9) { + *ram_a_inuse = true; + ret = true; + } else if (status_reg == 10) { + *ram_a_inuse = false; + ret = true; + } + return ret; +} + +static void dcn10_degamma_ram_select(struct input_pixel_processor *ipp, + bool use_ram_a) +{ + struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); + + if (use_ram_a) + REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 3); + else + REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 4); + +} + +static void dcn10_ipp_set_degamma_pwl(struct input_pixel_processor *ipp, + const struct pwl_params *params) +{ + bool is_ram_a = true; + + ipp_power_on_degamma_lut(ipp, true); + dcn10_ipp_enable_cm_block(ipp); + dcn10_degamma_ram_inuse(ipp, &is_ram_a); + if (is_ram_a == true) + dcn10_ipp_program_degamma_lutb_settings(ipp, params); + else + dcn10_ipp_program_degamma_luta_settings(ipp, params); + + ipp_program_degamma_lut(ipp, params->rgb_resulted, + params->hw_points_num, !is_ram_a); + dcn10_degamma_ram_select(ipp, !is_ram_a); +} + +/*****************************************/ +/* Constructor, Destructor */ +/*****************************************/ + +static void dcn10_ipp_destroy(struct input_pixel_processor **ipp) +{ + dm_free(TO_DCN10_IPP(*ipp)); + *ipp = NULL; +} + +static const struct ipp_funcs dcn10_ipp_funcs = { + .ipp_cursor_set_attributes = dcn10_cursor_set_attributes, + .ipp_cursor_set_position = dcn10_cursor_set_position, + .ipp_set_degamma = dcn10_ipp_set_degamma, + .ipp_full_bypass = dcn10_ipp_full_bypass, + .ipp_setup = dcn10_ipp_cnv_setup, + .ipp_program_degamma_pwl = dcn10_ipp_set_degamma_pwl, + .ipp_destroy = dcn10_ipp_destroy +}; + +void dcn10_ipp_construct( + struct dcn10_ipp *ippn10, + struct dc_context *ctx, + int inst, + const struct dcn10_ipp_registers *regs, + const struct dcn10_ipp_shift *ipp_shift, + const struct dcn10_ipp_mask *ipp_mask) +{ + ippn10->base.ctx = ctx; + ippn10->base.inst = inst; + ippn10->base.funcs = &dcn10_ipp_funcs; + + ippn10->regs = regs; + ippn10->ipp_shift = ipp_shift; + ippn10->ipp_mask = ipp_mask; +} diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h new file mode 100644 index 000000000000..a4ea4e774c72 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h @@ -0,0 +1,549 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef _DCN10_IPP_H_ +#define _DCN10_IPP_H_ + +#include "ipp.h" + +#define TO_DCN10_IPP(ipp)\ + container_of(ipp, struct dcn10_ipp, base) + +#define IPP_DCN10_REG_LIST(id) \ + SRI(CM_ICSC_CONTROL, CM, id), \ + SRI(CM_ICSC_C11_C12, CM, id), \ + SRI(CM_ICSC_C13_C14, CM, id), \ + SRI(CM_ICSC_C21_C22, CM, id), \ + SRI(CM_ICSC_C23_C24, CM, id), \ + SRI(CM_ICSC_C31_C32, CM, id), \ + SRI(CM_ICSC_C33_C34, CM, id), \ + SRI(CM_COMA_C11_C12, CM, id), \ + SRI(CM_COMA_C13_C14, CM, id), \ + SRI(CM_COMA_C21_C22, CM, id), \ + SRI(CM_COMA_C23_C24, CM, id), \ + SRI(CM_COMA_C31_C32, CM, id), \ + SRI(CM_COMA_C33_C34, CM, id), \ + SRI(CM_DGAM_RAMB_START_CNTL_B, CM, id), \ + SRI(CM_DGAM_RAMB_START_CNTL_G, CM, id), \ + SRI(CM_DGAM_RAMB_START_CNTL_R, CM, id), \ + SRI(CM_DGAM_RAMB_SLOPE_CNTL_B, CM, id), \ + SRI(CM_DGAM_RAMB_SLOPE_CNTL_G, CM, id), \ + SRI(CM_DGAM_RAMB_SLOPE_CNTL_R, CM, id), \ + SRI(CM_DGAM_RAMB_END_CNTL1_B, CM, id), \ + SRI(CM_DGAM_RAMB_END_CNTL2_B, CM, id), \ + SRI(CM_DGAM_RAMB_END_CNTL1_G, CM, id), \ + SRI(CM_DGAM_RAMB_END_CNTL2_G, CM, id), \ + SRI(CM_DGAM_RAMB_END_CNTL1_R, CM, id), \ + SRI(CM_DGAM_RAMB_END_CNTL2_R, CM, id), \ + SRI(CM_DGAM_RAMB_REGION_0_1, CM, id), \ + SRI(CM_DGAM_RAMB_REGION_2_3, CM, id), \ + SRI(CM_DGAM_RAMB_REGION_4_5, CM, id), \ + SRI(CM_DGAM_RAMB_REGION_6_7, CM, id), \ + SRI(CM_DGAM_RAMB_REGION_8_9, CM, id), \ + SRI(CM_DGAM_RAMB_REGION_10_11, CM, id), \ + SRI(CM_DGAM_RAMB_REGION_12_13, CM, id), \ + SRI(CM_DGAM_RAMB_REGION_14_15, CM, id), \ + SRI(CM_DGAM_RAMA_START_CNTL_B, CM, id), \ + SRI(CM_DGAM_RAMA_START_CNTL_G, CM, id), \ + SRI(CM_DGAM_RAMA_START_CNTL_R, CM, id), \ + SRI(CM_DGAM_RAMA_SLOPE_CNTL_B, CM, id), \ + SRI(CM_DGAM_RAMA_SLOPE_CNTL_G, CM, id), \ + SRI(CM_DGAM_RAMA_SLOPE_CNTL_R, CM, id), \ + SRI(CM_DGAM_RAMA_END_CNTL1_B, CM, id), \ + SRI(CM_DGAM_RAMA_END_CNTL2_B, CM, id), \ + SRI(CM_DGAM_RAMA_END_CNTL1_G, CM, id), \ + SRI(CM_DGAM_RAMA_END_CNTL2_G, CM, id), \ + SRI(CM_DGAM_RAMA_END_CNTL1_R, CM, id), \ + SRI(CM_DGAM_RAMA_END_CNTL2_R, CM, id), \ + SRI(CM_DGAM_RAMA_REGION_0_1, CM, id), \ + SRI(CM_DGAM_RAMA_REGION_2_3, CM, id), \ + SRI(CM_DGAM_RAMA_REGION_4_5, CM, id), \ + SRI(CM_DGAM_RAMA_REGION_6_7, CM, id), \ + SRI(CM_DGAM_RAMA_REGION_8_9, CM, id), \ + SRI(CM_DGAM_RAMA_REGION_10_11, CM, id), \ + SRI(CM_DGAM_RAMA_REGION_12_13, CM, id), \ + SRI(CM_DGAM_RAMA_REGION_14_15, CM, id), \ + SRI(CM_MEM_PWR_CTRL, CM, id), \ + SRI(CM_IGAM_LUT_RW_CONTROL, CM, id), \ + SRI(CM_DGAM_LUT_WRITE_EN_MASK, CM, id), \ + SRI(CM_DGAM_LUT_INDEX, CM, id), \ + SRI(CM_DGAM_LUT_DATA, CM, id), \ + SRI(CM_CONTROL, CM, id), \ + SRI(CM_DGAM_CONTROL, CM, id), \ + SRI(CM_IGAM_CONTROL, CM, id), \ + SRI(DPP_CONTROL, DPP_TOP, id), \ + SRI(CURSOR_SETTINS, HUBPREQ, id), \ + SRI(CNVC_SURFACE_PIXEL_FORMAT, CNVC_CFG, id), \ + SRI(CURSOR0_CONTROL, CNVC_CUR, id), \ + SRI(CURSOR0_COLOR0, CNVC_CUR, id), \ + SRI(CURSOR0_COLOR1, CNVC_CUR, id), \ + SRI(FORMAT_CONTROL, CNVC_CFG, id), \ + SRI(CURSOR_SURFACE_ADDRESS_HIGH, CURSOR, id), \ + SRI(CURSOR_SURFACE_ADDRESS, CURSOR, id), \ + SRI(CURSOR_SIZE, CURSOR, id), \ + SRI(CURSOR_CONTROL, CURSOR, id), \ + SRI(CURSOR_POSITION, CURSOR, id), \ + SRI(CURSOR_HOT_SPOT, CURSOR, id), \ + SRI(CURSOR_DST_OFFSET, CURSOR, id) + +#define IPP_SF(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define IPP_DCN10_MASK_SH_LIST(mask_sh) \ + IPP_SF(CM0_CM_ICSC_CONTROL, CM_ICSC_MODE, mask_sh), \ + IPP_SF(CM0_CM_ICSC_C11_C12, CM_ICSC_C11, mask_sh), \ + IPP_SF(CM0_CM_ICSC_C11_C12, CM_ICSC_C12, mask_sh), \ + IPP_SF(CM0_CM_ICSC_C13_C14, CM_ICSC_C13, mask_sh), \ + IPP_SF(CM0_CM_ICSC_C13_C14, CM_ICSC_C14, mask_sh), \ + IPP_SF(CM0_CM_ICSC_C21_C22, CM_ICSC_C21, mask_sh), \ + IPP_SF(CM0_CM_ICSC_C21_C22, CM_ICSC_C22, mask_sh), \ + IPP_SF(CM0_CM_ICSC_C23_C24, CM_ICSC_C23, mask_sh), \ + IPP_SF(CM0_CM_ICSC_C23_C24, CM_ICSC_C24, mask_sh), \ + IPP_SF(CM0_CM_ICSC_C31_C32, CM_ICSC_C31, mask_sh), \ + IPP_SF(CM0_CM_ICSC_C31_C32, CM_ICSC_C32, mask_sh), \ + IPP_SF(CM0_CM_ICSC_C33_C34, CM_ICSC_C33, mask_sh), \ + IPP_SF(CM0_CM_ICSC_C33_C34, CM_ICSC_C34, mask_sh), \ + IPP_SF(CM0_CM_COMA_C11_C12, CM_COMA_C11, mask_sh), \ + IPP_SF(CM0_CM_COMA_C11_C12, CM_COMA_C12, mask_sh), \ + IPP_SF(CM0_CM_COMA_C13_C14, CM_COMA_C13, mask_sh), \ + IPP_SF(CM0_CM_COMA_C13_C14, CM_COMA_C14, mask_sh), \ + IPP_SF(CM0_CM_COMA_C21_C22, CM_COMA_C21, mask_sh), \ + IPP_SF(CM0_CM_COMA_C21_C22, CM_COMA_C22, mask_sh), \ + IPP_SF(CM0_CM_COMA_C23_C24, CM_COMA_C23, mask_sh), \ + IPP_SF(CM0_CM_COMA_C23_C24, CM_COMA_C24, mask_sh), \ + IPP_SF(CM0_CM_COMA_C31_C32, CM_COMA_C31, mask_sh), \ + IPP_SF(CM0_CM_COMA_C31_C32, CM_COMA_C32, mask_sh), \ + IPP_SF(CM0_CM_COMA_C33_C34, CM_COMA_C33, mask_sh), \ + IPP_SF(CM0_CM_COMA_C33_C34, CM_COMA_C34, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_START_CNTL_B, CM_DGAM_RAMB_EXP_REGION_START_B, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_START_CNTL_B, CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_B, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_START_CNTL_G, CM_DGAM_RAMB_EXP_REGION_START_G, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_START_CNTL_G, CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_G, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_START_CNTL_R, CM_DGAM_RAMB_EXP_REGION_START_R, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_START_CNTL_R, CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_R, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_SLOPE_CNTL_B, CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_SLOPE_CNTL_G, CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_G, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_SLOPE_CNTL_R, CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_R, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_END_CNTL1_B, CM_DGAM_RAMB_EXP_REGION_END_B, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_END_CNTL2_B, CM_DGAM_RAMB_EXP_REGION_END_SLOPE_B, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_END_CNTL2_B, CM_DGAM_RAMB_EXP_REGION_END_BASE_B, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_END_CNTL1_G, CM_DGAM_RAMB_EXP_REGION_END_G, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_END_CNTL2_G, CM_DGAM_RAMB_EXP_REGION_END_SLOPE_G, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_END_CNTL2_G, CM_DGAM_RAMB_EXP_REGION_END_BASE_G, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_END_CNTL1_R, CM_DGAM_RAMB_EXP_REGION_END_R, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_END_CNTL2_R, CM_DGAM_RAMB_EXP_REGION_END_SLOPE_R, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_END_CNTL2_R, CM_DGAM_RAMB_EXP_REGION_END_BASE_R, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_0_1, CM_DGAM_RAMB_EXP_REGION0_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_0_1, CM_DGAM_RAMB_EXP_REGION0_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_0_1, CM_DGAM_RAMB_EXP_REGION1_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_0_1, CM_DGAM_RAMB_EXP_REGION1_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_2_3, CM_DGAM_RAMB_EXP_REGION2_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_2_3, CM_DGAM_RAMB_EXP_REGION2_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_2_3, CM_DGAM_RAMB_EXP_REGION3_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_2_3, CM_DGAM_RAMB_EXP_REGION3_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_4_5, CM_DGAM_RAMB_EXP_REGION4_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_4_5, CM_DGAM_RAMB_EXP_REGION4_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_4_5, CM_DGAM_RAMB_EXP_REGION5_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_4_5, CM_DGAM_RAMB_EXP_REGION5_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_6_7, CM_DGAM_RAMB_EXP_REGION6_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_6_7, CM_DGAM_RAMB_EXP_REGION6_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_6_7, CM_DGAM_RAMB_EXP_REGION7_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_6_7, CM_DGAM_RAMB_EXP_REGION7_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_8_9, CM_DGAM_RAMB_EXP_REGION8_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_8_9, CM_DGAM_RAMB_EXP_REGION8_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_8_9, CM_DGAM_RAMB_EXP_REGION9_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_8_9, CM_DGAM_RAMB_EXP_REGION9_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_10_11, CM_DGAM_RAMB_EXP_REGION10_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_10_11, CM_DGAM_RAMB_EXP_REGION10_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_10_11, CM_DGAM_RAMB_EXP_REGION11_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_10_11, CM_DGAM_RAMB_EXP_REGION11_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_12_13, CM_DGAM_RAMB_EXP_REGION12_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_12_13, CM_DGAM_RAMB_EXP_REGION12_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_12_13, CM_DGAM_RAMB_EXP_REGION13_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_12_13, CM_DGAM_RAMB_EXP_REGION13_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_14_15, CM_DGAM_RAMB_EXP_REGION14_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_14_15, CM_DGAM_RAMB_EXP_REGION14_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_14_15, CM_DGAM_RAMB_EXP_REGION15_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_14_15, CM_DGAM_RAMB_EXP_REGION15_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_START_CNTL_B, CM_DGAM_RAMA_EXP_REGION_START_B, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_START_CNTL_B, CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_B, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_START_CNTL_G, CM_DGAM_RAMA_EXP_REGION_START_G, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_START_CNTL_G, CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_G, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_START_CNTL_R, CM_DGAM_RAMA_EXP_REGION_START_R, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_START_CNTL_R, CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_R, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_SLOPE_CNTL_B, CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_SLOPE_CNTL_G, CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_SLOPE_CNTL_R, CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_END_CNTL1_B, CM_DGAM_RAMA_EXP_REGION_END_B, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_END_CNTL2_B, CM_DGAM_RAMA_EXP_REGION_END_SLOPE_B, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_END_CNTL2_B, CM_DGAM_RAMA_EXP_REGION_END_BASE_B, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_END_CNTL1_G, CM_DGAM_RAMA_EXP_REGION_END_G, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_END_CNTL2_G, CM_DGAM_RAMA_EXP_REGION_END_SLOPE_G, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_END_CNTL2_G, CM_DGAM_RAMA_EXP_REGION_END_BASE_G, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_END_CNTL1_R, CM_DGAM_RAMA_EXP_REGION_END_R, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_END_CNTL2_R, CM_DGAM_RAMA_EXP_REGION_END_SLOPE_R, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_END_CNTL2_R, CM_DGAM_RAMA_EXP_REGION_END_BASE_R, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_0_1, CM_DGAM_RAMA_EXP_REGION0_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_0_1, CM_DGAM_RAMA_EXP_REGION0_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_0_1, CM_DGAM_RAMA_EXP_REGION1_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_0_1, CM_DGAM_RAMA_EXP_REGION1_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_2_3, CM_DGAM_RAMA_EXP_REGION2_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_2_3, CM_DGAM_RAMA_EXP_REGION2_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_2_3, CM_DGAM_RAMA_EXP_REGION3_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_2_3, CM_DGAM_RAMA_EXP_REGION3_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_4_5, CM_DGAM_RAMA_EXP_REGION4_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_4_5, CM_DGAM_RAMA_EXP_REGION4_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_4_5, CM_DGAM_RAMA_EXP_REGION5_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_4_5, CM_DGAM_RAMA_EXP_REGION5_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_6_7, CM_DGAM_RAMA_EXP_REGION6_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_6_7, CM_DGAM_RAMA_EXP_REGION6_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_6_7, CM_DGAM_RAMA_EXP_REGION7_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_6_7, CM_DGAM_RAMA_EXP_REGION7_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_8_9, CM_DGAM_RAMA_EXP_REGION8_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_8_9, CM_DGAM_RAMA_EXP_REGION8_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_8_9, CM_DGAM_RAMA_EXP_REGION9_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_8_9, CM_DGAM_RAMA_EXP_REGION9_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_10_11, CM_DGAM_RAMA_EXP_REGION10_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_10_11, CM_DGAM_RAMA_EXP_REGION10_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_10_11, CM_DGAM_RAMA_EXP_REGION11_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_10_11, CM_DGAM_RAMA_EXP_REGION11_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_12_13, CM_DGAM_RAMA_EXP_REGION12_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_12_13, CM_DGAM_RAMA_EXP_REGION12_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_12_13, CM_DGAM_RAMA_EXP_REGION13_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_12_13, CM_DGAM_RAMA_EXP_REGION13_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_14_15, CM_DGAM_RAMA_EXP_REGION14_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_14_15, CM_DGAM_RAMA_EXP_REGION14_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_14_15, CM_DGAM_RAMA_EXP_REGION15_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_14_15, CM_DGAM_RAMA_EXP_REGION15_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_MEM_PWR_CTRL, SHARED_MEM_PWR_DIS, mask_sh), \ + IPP_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_HOST_EN, mask_sh), \ + IPP_SF(CM0_CM_DGAM_LUT_WRITE_EN_MASK, CM_DGAM_LUT_WRITE_EN_MASK, mask_sh), \ + IPP_SF(CM0_CM_DGAM_LUT_WRITE_EN_MASK, CM_DGAM_LUT_WRITE_SEL, mask_sh), \ + IPP_SF(CM0_CM_DGAM_LUT_INDEX, CM_DGAM_LUT_INDEX, mask_sh), \ + IPP_SF(CM0_CM_DGAM_LUT_DATA, CM_DGAM_LUT_DATA, mask_sh), \ + IPP_SF(DPP_TOP0_DPP_CONTROL, DPP_CLOCK_ENABLE, mask_sh), \ + IPP_SF(CM0_CM_CONTROL, CM_BYPASS_EN, mask_sh), \ + IPP_SF(CNVC_CFG0_CNVC_SURFACE_PIXEL_FORMAT, CNVC_SURFACE_PIXEL_FORMAT, mask_sh), \ + IPP_SF(CNVC_CFG0_FORMAT_CONTROL, CNVC_BYPASS, mask_sh), \ + IPP_SF(CNVC_CFG0_FORMAT_CONTROL, ALPHA_EN, mask_sh), \ + IPP_SF(CNVC_CFG0_FORMAT_CONTROL, FORMAT_EXPANSION_MODE, mask_sh), \ + IPP_SF(CM0_CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, mask_sh), \ + IPP_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, mask_sh), \ + IPP_SF(HUBPREQ0_CURSOR_SETTINS, CURSOR0_DST_Y_OFFSET, mask_sh), \ + IPP_SF(HUBPREQ0_CURSOR_SETTINS, CURSOR0_CHUNK_HDL_ADJUST, mask_sh), \ + IPP_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_MODE, mask_sh), \ + IPP_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_INVERT_MODE, mask_sh), \ + IPP_SF(CNVC_CUR0_CURSOR0_COLOR0, CUR0_COLOR0, mask_sh), \ + IPP_SF(CNVC_CUR0_CURSOR0_COLOR1, CUR0_COLOR1, mask_sh), \ + IPP_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_EXPANSION_MODE, mask_sh), \ + IPP_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_MAX, mask_sh), \ + IPP_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_MIN, mask_sh), \ + IPP_SF(CURSOR0_CURSOR_SURFACE_ADDRESS_HIGH, CURSOR_SURFACE_ADDRESS_HIGH, mask_sh), \ + IPP_SF(CURSOR0_CURSOR_SURFACE_ADDRESS, CURSOR_SURFACE_ADDRESS, mask_sh), \ + IPP_SF(CURSOR0_CURSOR_SIZE, CURSOR_WIDTH, mask_sh), \ + IPP_SF(CURSOR0_CURSOR_SIZE, CURSOR_HEIGHT, mask_sh), \ + IPP_SF(CURSOR0_CURSOR_CONTROL, CURSOR_MODE, mask_sh), \ + IPP_SF(CURSOR0_CURSOR_CONTROL, CURSOR_PITCH, mask_sh), \ + IPP_SF(CURSOR0_CURSOR_CONTROL, CURSOR_LINES_PER_CHUNK, mask_sh), \ + IPP_SF(CURSOR0_CURSOR_CONTROL, CURSOR_ENABLE, mask_sh), \ + IPP_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_ENABLE, mask_sh), \ + IPP_SF(CURSOR0_CURSOR_POSITION, CURSOR_X_POSITION, mask_sh), \ + IPP_SF(CURSOR0_CURSOR_POSITION, CURSOR_Y_POSITION, mask_sh), \ + IPP_SF(CURSOR0_CURSOR_HOT_SPOT, CURSOR_HOT_SPOT_X, mask_sh), \ + IPP_SF(CURSOR0_CURSOR_HOT_SPOT, CURSOR_HOT_SPOT_Y, mask_sh), \ + IPP_SF(CURSOR0_CURSOR_DST_OFFSET, CURSOR_DST_X_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_INPUT_FORMAT, mask_sh), \ + IPP_SF(CNVC_CFG0_FORMAT_CONTROL, OUTPUT_FP, mask_sh) + +#define IPP_DCN10_REG_FIELD_LIST(type) \ + type CM_ICSC_MODE; \ + type CM_ICSC_C11; \ + type CM_ICSC_C12; \ + type CM_ICSC_C13; \ + type CM_ICSC_C14; \ + type CM_ICSC_C21; \ + type CM_ICSC_C22; \ + type CM_ICSC_C23; \ + type CM_ICSC_C24; \ + type CM_ICSC_C31; \ + type CM_ICSC_C32; \ + type CM_ICSC_C33; \ + type CM_ICSC_C34; \ + type CM_COMA_C11; \ + type CM_COMA_C12; \ + type CM_COMA_C13; \ + type CM_COMA_C14; \ + type CM_COMA_C21; \ + type CM_COMA_C22; \ + type CM_COMA_C23; \ + type CM_COMA_C24; \ + type CM_COMA_C31; \ + type CM_COMA_C32; \ + type CM_COMA_C33; \ + type CM_COMA_C34; \ + type CM_DGAM_RAMB_EXP_REGION_START_B; \ + type CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_B; \ + type CM_DGAM_RAMB_EXP_REGION_START_G; \ + type CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_G; \ + type CM_DGAM_RAMB_EXP_REGION_START_R; \ + type CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_R; \ + type CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B; \ + type CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_G; \ + type CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_R; \ + type CM_DGAM_RAMB_EXP_REGION_END_B; \ + type CM_DGAM_RAMB_EXP_REGION_END_SLOPE_B; \ + type CM_DGAM_RAMB_EXP_REGION_END_BASE_B; \ + type CM_DGAM_RAMB_EXP_REGION_END_G; \ + type CM_DGAM_RAMB_EXP_REGION_END_SLOPE_G; \ + type CM_DGAM_RAMB_EXP_REGION_END_BASE_G; \ + type CM_DGAM_RAMB_EXP_REGION_END_R; \ + type CM_DGAM_RAMB_EXP_REGION_END_SLOPE_R; \ + type CM_DGAM_RAMB_EXP_REGION_END_BASE_R; \ + type CM_DGAM_RAMB_EXP_REGION0_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION0_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION1_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION1_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION2_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION2_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION3_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION3_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION4_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION4_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION5_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION5_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION6_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION6_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION7_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION7_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION8_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION8_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION9_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION9_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION10_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION10_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION11_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION11_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION12_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION12_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION13_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION13_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION14_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION14_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION15_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION15_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION_START_B; \ + type CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_B; \ + type CM_DGAM_RAMA_EXP_REGION_START_G; \ + type CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_G; \ + type CM_DGAM_RAMA_EXP_REGION_START_R; \ + type CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_R; \ + type CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B; \ + type CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G; \ + type CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R; \ + type CM_DGAM_RAMA_EXP_REGION_END_B; \ + type CM_DGAM_RAMA_EXP_REGION_END_SLOPE_B; \ + type CM_DGAM_RAMA_EXP_REGION_END_BASE_B; \ + type CM_DGAM_RAMA_EXP_REGION_END_G; \ + type CM_DGAM_RAMA_EXP_REGION_END_SLOPE_G; \ + type CM_DGAM_RAMA_EXP_REGION_END_BASE_G; \ + type CM_DGAM_RAMA_EXP_REGION_END_R; \ + type CM_DGAM_RAMA_EXP_REGION_END_SLOPE_R; \ + type CM_DGAM_RAMA_EXP_REGION_END_BASE_R; \ + type CM_DGAM_RAMA_EXP_REGION0_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION0_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION1_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION1_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION2_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION2_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION3_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION3_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION4_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION4_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION5_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION5_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION6_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION6_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION7_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION7_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION8_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION8_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION9_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION9_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION10_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION10_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION11_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION11_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION12_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION12_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION13_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION13_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION14_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION14_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION15_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION15_NUM_SEGMENTS; \ + type SHARED_MEM_PWR_DIS; \ + type CM_IGAM_LUT_HOST_EN; \ + type CM_DGAM_LUT_WRITE_EN_MASK; \ + type CM_DGAM_LUT_WRITE_SEL; \ + type CM_DGAM_LUT_INDEX; \ + type CM_DGAM_LUT_DATA; \ + type DPP_CLOCK_ENABLE; \ + type CM_BYPASS_EN; \ + type CNVC_SURFACE_PIXEL_FORMAT; \ + type CNVC_BYPASS; \ + type ALPHA_EN; \ + type FORMAT_EXPANSION_MODE; \ + type CM_DGAM_LUT_MODE; \ + type CM_IGAM_LUT_MODE; \ + type CURSOR0_DST_Y_OFFSET; \ + type CURSOR0_CHUNK_HDL_ADJUST; \ + type CUR0_MODE; \ + type CUR0_INVERT_MODE; \ + type CUR0_COLOR0; \ + type CUR0_COLOR1; \ + type CUR0_EXPANSION_MODE; \ + type CUR0_MAX; \ + type CUR0_MIN; \ + type CURSOR_SURFACE_ADDRESS_HIGH; \ + type CURSOR_SURFACE_ADDRESS; \ + type CURSOR_WIDTH; \ + type CURSOR_HEIGHT; \ + type CURSOR_MODE; \ + type CURSOR_PITCH; \ + type CURSOR_LINES_PER_CHUNK; \ + type CURSOR_ENABLE; \ + type CUR0_ENABLE; \ + type CURSOR_X_POSITION; \ + type CURSOR_Y_POSITION; \ + type CURSOR_HOT_SPOT_X; \ + type CURSOR_HOT_SPOT_Y; \ + type CURSOR_DST_X_OFFSET; \ + type CM_IGAM_INPUT_FORMAT; \ + type OUTPUT_FP + +struct dcn10_ipp_shift { + IPP_DCN10_REG_FIELD_LIST(uint8_t); +}; + +struct dcn10_ipp_mask { + IPP_DCN10_REG_FIELD_LIST(uint32_t); +}; + +struct dcn10_ipp_registers { + uint32_t CM_ICSC_CONTROL; + uint32_t CM_ICSC_C11_C12; + uint32_t CM_ICSC_C13_C14; + uint32_t CM_ICSC_C21_C22; + uint32_t CM_ICSC_C23_C24; + uint32_t CM_ICSC_C31_C32; + uint32_t CM_ICSC_C33_C34; + uint32_t CM_COMA_C11_C12; + uint32_t CM_COMA_C13_C14; + uint32_t CM_COMA_C21_C22; + uint32_t CM_COMA_C23_C24; + uint32_t CM_COMA_C31_C32; + uint32_t CM_COMA_C33_C34; + uint32_t CM_DGAM_RAMB_START_CNTL_B; + uint32_t CM_DGAM_RAMB_START_CNTL_G; + uint32_t CM_DGAM_RAMB_START_CNTL_R; + uint32_t CM_DGAM_RAMB_SLOPE_CNTL_B; + uint32_t CM_DGAM_RAMB_SLOPE_CNTL_G; + uint32_t CM_DGAM_RAMB_SLOPE_CNTL_R; + uint32_t CM_DGAM_RAMB_END_CNTL1_B; + uint32_t CM_DGAM_RAMB_END_CNTL2_B; + uint32_t CM_DGAM_RAMB_END_CNTL1_G; + uint32_t CM_DGAM_RAMB_END_CNTL2_G; + uint32_t CM_DGAM_RAMB_END_CNTL1_R; + uint32_t CM_DGAM_RAMB_END_CNTL2_R; + uint32_t CM_DGAM_RAMB_REGION_0_1; + uint32_t CM_DGAM_RAMB_REGION_2_3; + uint32_t CM_DGAM_RAMB_REGION_4_5; + uint32_t CM_DGAM_RAMB_REGION_6_7; + uint32_t CM_DGAM_RAMB_REGION_8_9; + uint32_t CM_DGAM_RAMB_REGION_10_11; + uint32_t CM_DGAM_RAMB_REGION_12_13; + uint32_t CM_DGAM_RAMB_REGION_14_15; + uint32_t CM_DGAM_RAMA_START_CNTL_B; + uint32_t CM_DGAM_RAMA_START_CNTL_G; + uint32_t CM_DGAM_RAMA_START_CNTL_R; + uint32_t CM_DGAM_RAMA_SLOPE_CNTL_B; + uint32_t CM_DGAM_RAMA_SLOPE_CNTL_G; + uint32_t CM_DGAM_RAMA_SLOPE_CNTL_R; + uint32_t CM_DGAM_RAMA_END_CNTL1_B; + uint32_t CM_DGAM_RAMA_END_CNTL2_B; + uint32_t CM_DGAM_RAMA_END_CNTL1_G; + uint32_t CM_DGAM_RAMA_END_CNTL2_G; + uint32_t CM_DGAM_RAMA_END_CNTL1_R; + uint32_t CM_DGAM_RAMA_END_CNTL2_R; + uint32_t CM_DGAM_RAMA_REGION_0_1; + uint32_t CM_DGAM_RAMA_REGION_2_3; + uint32_t CM_DGAM_RAMA_REGION_4_5; + uint32_t CM_DGAM_RAMA_REGION_6_7; + uint32_t CM_DGAM_RAMA_REGION_8_9; + uint32_t CM_DGAM_RAMA_REGION_10_11; + uint32_t CM_DGAM_RAMA_REGION_12_13; + uint32_t CM_DGAM_RAMA_REGION_14_15; + uint32_t CM_MEM_PWR_CTRL; + uint32_t CM_IGAM_LUT_RW_CONTROL; + uint32_t CM_DGAM_LUT_WRITE_EN_MASK; + uint32_t CM_DGAM_LUT_INDEX; + uint32_t CM_DGAM_LUT_DATA; + uint32_t CM_CONTROL; + uint32_t CM_DGAM_CONTROL; + uint32_t CM_IGAM_CONTROL; + uint32_t DPP_CONTROL; + uint32_t CURSOR_SETTINS; + uint32_t CNVC_SURFACE_PIXEL_FORMAT; + uint32_t CURSOR0_CONTROL; + uint32_t CURSOR0_COLOR0; + uint32_t CURSOR0_COLOR1; + uint32_t FORMAT_CONTROL; + uint32_t CURSOR_SURFACE_ADDRESS_HIGH; + uint32_t CURSOR_SURFACE_ADDRESS; + uint32_t CURSOR_SIZE; + uint32_t CURSOR_CONTROL; + uint32_t CURSOR_POSITION; + uint32_t CURSOR_HOT_SPOT; + uint32_t CURSOR_DST_OFFSET; +}; + +struct dcn10_ipp { + struct input_pixel_processor base; + + const struct dcn10_ipp_registers *regs; + const struct dcn10_ipp_shift *ipp_shift; + const struct dcn10_ipp_mask *ipp_mask; + + struct dc_cursor_attributes curs_attr; +}; + +void dcn10_ipp_construct(struct dcn10_ipp *ippn10, + struct dc_context *ctx, + int inst, + const struct dcn10_ipp_registers *regs, + const struct dcn10_ipp_shift *ipp_shift, + const struct dcn10_ipp_mask *ipp_mask); + +#endif /* _DCN10_IPP_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c new file mode 100644 index 000000000000..bf89608b30e4 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -0,0 +1,1102 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#include "dm_services.h" +#include "dce_calcs.h" +#include "dcn10_mem_input.h" +#include "reg_helper.h" +#include "basics/conversion.h" + +#define REG(reg)\ + mi->mi_regs->reg + +#define CTX \ + mi->base.ctx + +#undef FN +#define FN(reg_name, field_name) \ + mi->mi_shift->field_name, mi->mi_mask->field_name + +static void set_blank(struct dcn10_mem_input *mi, bool blank) +{ + uint32_t blank_en = blank ? 1 : 0; + + REG_UPDATE_2(DCHUBP_CNTL, + HUBP_BLANK_EN, blank_en, + HUBP_TTU_DISABLE, blank_en); +} + + +static void disable_request(struct mem_input *mem_input) +{ + struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + + /* To disable the requestors, set blank_en to 1 */ + set_blank(mi, true); +} + +static void vready_workaround(struct mem_input *mem_input, + struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest) +{ + uint32_t value = 0; + struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + + /* set HBUBREQ_DEBUG_DB[12] = 1 */ + value = REG_READ(HUBPREQ_DEBUG_DB); + + /* hack mode disable */ + value |= 0x100; + value &= ~0x1000; + + if ((pipe_dest->vstartup_start - 2*(pipe_dest->vready_offset+pipe_dest->vupdate_width + + pipe_dest->vupdate_offset) / pipe_dest->htotal) <= pipe_dest->vblank_end) { + /* if (eco_fix_needed(otg_global_sync_timing) + * set HBUBREQ_DEBUG_DB[12] = 1 */ + value |= 0x1000; + } + + REG_WRITE(HUBPREQ_DEBUG_DB, value); +} + +static void program_tiling( + struct dcn10_mem_input *mi, + const union dc_tiling_info *info, + const enum surface_pixel_format pixel_format) +{ + REG_UPDATE_6(DCSURF_ADDR_CONFIG, + NUM_PIPES, log_2(info->gfx9.num_pipes), + NUM_BANKS, log_2(info->gfx9.num_banks), + PIPE_INTERLEAVE, info->gfx9.pipe_interleave, + NUM_SE, log_2(info->gfx9.num_shader_engines), + NUM_RB_PER_SE, log_2(info->gfx9.num_rb_per_se), + MAX_COMPRESSED_FRAGS, log_2(info->gfx9.max_compressed_frags)); + + REG_UPDATE_4(DCSURF_TILING_CONFIG, + SW_MODE, info->gfx9.swizzle, + META_LINEAR, info->gfx9.meta_linear, + RB_ALIGNED, info->gfx9.rb_aligned, + PIPE_ALIGNED, info->gfx9.pipe_aligned); +} + +static void program_size_and_rotation( + struct dcn10_mem_input *mi, + enum dc_rotation_angle rotation, + enum surface_pixel_format format, + const union plane_size *plane_size, + struct dc_plane_dcc_param *dcc, + bool horizontal_mirror) +{ + uint32_t pitch, meta_pitch, pitch_c, meta_pitch_c, mirror; + + /* Program data and meta surface pitch (calculation from addrlib) + * 444 or 420 luma + */ + if (format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) { + pitch = plane_size->video.luma_pitch - 1; + meta_pitch = dcc->video.meta_pitch_l - 1; + pitch_c = plane_size->video.chroma_pitch - 1; + meta_pitch_c = dcc->video.meta_pitch_c - 1; + } else { + pitch = plane_size->grph.surface_pitch - 1; + meta_pitch = dcc->grph.meta_pitch - 1; + pitch_c = 0; + meta_pitch_c = 0; + } + + if (!dcc->enable) { + meta_pitch = 0; + meta_pitch_c = 0; + } + + REG_UPDATE_2(DCSURF_SURFACE_PITCH, + PITCH, pitch, META_PITCH, meta_pitch); + + if (format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) + REG_UPDATE_2(DCSURF_SURFACE_PITCH_C, + PITCH_C, pitch_c, META_PITCH_C, meta_pitch_c); + + if (horizontal_mirror) + mirror = 1; + else + mirror = 0; + + + /* Program rotation angle and horz mirror - no mirror */ + if (rotation == ROTATION_ANGLE_0) + REG_UPDATE_2(DCSURF_SURFACE_CONFIG, + ROTATION_ANGLE, 0, + H_MIRROR_EN, mirror); + else if (rotation == ROTATION_ANGLE_90) + REG_UPDATE_2(DCSURF_SURFACE_CONFIG, + ROTATION_ANGLE, 1, + H_MIRROR_EN, mirror); + else if (rotation == ROTATION_ANGLE_180) + REG_UPDATE_2(DCSURF_SURFACE_CONFIG, + ROTATION_ANGLE, 2, + H_MIRROR_EN, mirror); + else if (rotation == ROTATION_ANGLE_270) + REG_UPDATE_2(DCSURF_SURFACE_CONFIG, + ROTATION_ANGLE, 3, + H_MIRROR_EN, mirror); +} + +static void program_pixel_format( + struct dcn10_mem_input *mi, + enum surface_pixel_format format) +{ + uint32_t red_bar = 3; + uint32_t blue_bar = 2; + + /* swap for ABGR format */ + if (format == SURFACE_PIXEL_FORMAT_GRPH_ABGR8888 + || format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010 + || format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS + || format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F) { + red_bar = 2; + blue_bar = 3; + } + + REG_UPDATE_2(HUBPRET_CONTROL, + CROSSBAR_SRC_CB_B, blue_bar, + CROSSBAR_SRC_CR_R, red_bar); + + /* Mapping is same as ipp programming (cnvc) */ + + switch (format) { + case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: + REG_UPDATE(DCSURF_SURFACE_CONFIG, + SURFACE_PIXEL_FORMAT, 1); + break; + case SURFACE_PIXEL_FORMAT_GRPH_RGB565: + REG_UPDATE(DCSURF_SURFACE_CONFIG, + SURFACE_PIXEL_FORMAT, 3); + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: + REG_UPDATE(DCSURF_SURFACE_CONFIG, + SURFACE_PIXEL_FORMAT, 8); + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: + REG_UPDATE(DCSURF_SURFACE_CONFIG, + SURFACE_PIXEL_FORMAT, 10); + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: + REG_UPDATE(DCSURF_SURFACE_CONFIG, + SURFACE_PIXEL_FORMAT, 22); + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:/*we use crossbar already*/ + REG_UPDATE(DCSURF_SURFACE_CONFIG, + SURFACE_PIXEL_FORMAT, 24); + break; + + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: + REG_UPDATE(DCSURF_SURFACE_CONFIG, + SURFACE_PIXEL_FORMAT, 65); + break; + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: + REG_UPDATE(DCSURF_SURFACE_CONFIG, + SURFACE_PIXEL_FORMAT, 64); + break; + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: + REG_UPDATE(DCSURF_SURFACE_CONFIG, + SURFACE_PIXEL_FORMAT, 67); + break; + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: + REG_UPDATE(DCSURF_SURFACE_CONFIG, + SURFACE_PIXEL_FORMAT, 66); + break; + default: + BREAK_TO_DEBUGGER(); + break; + } + + /* don't see the need of program the xbar in DCN 1.0 */ +} + +static bool mem_input_program_surface_flip_and_addr( + struct mem_input *mem_input, + const struct dc_plane_address *address, + bool flip_immediate) +{ + struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + + /* program flip type */ + + REG_UPDATE(DCSURF_FLIP_CONTROL, + SURFACE_FLIP_TYPE, flip_immediate); + + /* REG_UPDATE(FLIP_CONTROL, SURFACE_UPDATE_LOCK, 1); */ + + + /* program high first and then the low addr, order matters! */ + switch (address->type) { + case PLN_ADDR_TYPE_GRAPHICS: + if (address->grph.addr.quad_part == 0) + break; + + if (address->grph.meta_addr.quad_part != 0) { + + REG_UPDATE(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, + PRIMARY_META_SURFACE_ADDRESS_HIGH, + address->grph.meta_addr.high_part); + + REG_UPDATE(DCSURF_PRIMARY_META_SURFACE_ADDRESS, + PRIMARY_META_SURFACE_ADDRESS, + address->grph.meta_addr.low_part); + } + + REG_UPDATE(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, + PRIMARY_SURFACE_ADDRESS_HIGH, + address->grph.addr.high_part); + + REG_UPDATE(DCSURF_PRIMARY_SURFACE_ADDRESS, + PRIMARY_SURFACE_ADDRESS, + address->grph.addr.low_part); + + + /* DCN1.0 does not support const color + * TODO: program DCHUBBUB_RET_PATH_DCC_CFGx_0/1 + * base on address->grph.dcc_const_color + * x = 0, 2, 4, 6 for pipe 0, 1, 2, 3 for rgb and luma + * x = 1, 3, 5, 7 for pipe 0, 1, 2, 3 for chroma + */ + break; + case PLN_ADDR_TYPE_VIDEO_PROGRESSIVE: + if (address->video_progressive.luma_addr.quad_part == 0 + || address->video_progressive.chroma_addr.quad_part == 0) + break; + + if (address->video_progressive.luma_meta_addr.quad_part != 0) { + + REG_UPDATE(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, + PRIMARY_META_SURFACE_ADDRESS_HIGH, + address->video_progressive.luma_meta_addr.high_part); + + REG_UPDATE(DCSURF_PRIMARY_META_SURFACE_ADDRESS, + PRIMARY_META_SURFACE_ADDRESS, + address->video_progressive.luma_meta_addr.low_part); + + REG_UPDATE(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C, + PRIMARY_META_SURFACE_ADDRESS_HIGH_C, + address->video_progressive.chroma_meta_addr.high_part); + + REG_UPDATE(DCSURF_PRIMARY_META_SURFACE_ADDRESS_C, + PRIMARY_META_SURFACE_ADDRESS_C, + address->video_progressive.chroma_meta_addr.low_part); + } + + REG_UPDATE(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, + PRIMARY_SURFACE_ADDRESS_HIGH, + address->video_progressive.luma_addr.high_part); + + REG_UPDATE(DCSURF_PRIMARY_SURFACE_ADDRESS, + PRIMARY_SURFACE_ADDRESS, + address->video_progressive.luma_addr.low_part); + + REG_UPDATE(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C, + PRIMARY_SURFACE_ADDRESS_HIGH_C, + address->video_progressive.chroma_addr.high_part); + + REG_UPDATE(DCSURF_PRIMARY_SURFACE_ADDRESS_C, + PRIMARY_SURFACE_ADDRESS_C, + address->video_progressive.chroma_addr.low_part); + + break; + case PLN_ADDR_TYPE_GRPH_STEREO: + if (address->grph_stereo.left_addr.quad_part == 0) + break; + if (address->grph_stereo.right_addr.quad_part == 0) + break; + if (address->grph_stereo.right_meta_addr.quad_part != 0) { + + REG_UPDATE(DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH, + SECONDARY_META_SURFACE_ADDRESS_HIGH, + address->grph_stereo.right_meta_addr.high_part); + + REG_UPDATE(DCSURF_SECONDARY_META_SURFACE_ADDRESS, + SECONDARY_META_SURFACE_ADDRESS, + address->grph_stereo.right_meta_addr.low_part); + } + if (address->grph_stereo.left_meta_addr.quad_part != 0) { + + REG_UPDATE(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, + PRIMARY_META_SURFACE_ADDRESS_HIGH, + address->grph_stereo.left_meta_addr.high_part); + + REG_UPDATE(DCSURF_PRIMARY_META_SURFACE_ADDRESS, + PRIMARY_META_SURFACE_ADDRESS, + address->grph_stereo.left_meta_addr.low_part); + } + + REG_UPDATE(DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH, + SECONDARY_SURFACE_ADDRESS_HIGH, + address->grph_stereo.right_addr.high_part); + + REG_UPDATE(DCSURF_SECONDARY_SURFACE_ADDRESS, + SECONDARY_SURFACE_ADDRESS, + address->grph_stereo.right_addr.low_part); + + + REG_UPDATE(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, + PRIMARY_SURFACE_ADDRESS_HIGH, + address->grph_stereo.left_addr.high_part); + + REG_UPDATE(DCSURF_PRIMARY_SURFACE_ADDRESS, + PRIMARY_SURFACE_ADDRESS, + address->grph_stereo.left_addr.low_part); + break; + default: + BREAK_TO_DEBUGGER(); + break; + } + /* REG_UPDATE(FLIP_CONTROL, SURFACE_UPDATE_LOCK, 0); */ + + mem_input->request_address = *address; + + if (flip_immediate) + mem_input->current_address = *address; + + return true; +} + +static void program_control(struct dcn10_mem_input *mi, + struct dc_plane_dcc_param *dcc) +{ + uint32_t dcc_en = dcc->enable ? 1 : 0; + uint32_t dcc_ind_64b_blk = dcc->grph.independent_64b_blks ? 1 : 0; + + REG_UPDATE_2(DCSURF_SURFACE_CONTROL, + PRIMARY_SURFACE_DCC_EN, dcc_en, + PRIMARY_SURFACE_DCC_IND_64B_BLK, dcc_ind_64b_blk); + +} + +static void mem_input_program_surface_config( + struct mem_input *mem_input, + enum surface_pixel_format format, + union dc_tiling_info *tiling_info, + union plane_size *plane_size, + enum dc_rotation_angle rotation, + struct dc_plane_dcc_param *dcc, + bool horizontal_mirror, + bool visible) +{ + struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + + program_control(mi, dcc); + program_tiling(mi, tiling_info, format); + program_size_and_rotation( + mi, rotation, format, plane_size, dcc, horizontal_mirror); + program_pixel_format(mi, format); + + set_blank(mi, !visible); +} + +static void program_requestor( + struct mem_input *mem_input, + struct _vcs_dpi_display_rq_regs_st *rq_regs) +{ + + struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + + REG_UPDATE(HUBPRET_CONTROL, + DET_BUF_PLANE1_BASE_ADDRESS, rq_regs->plane1_base_address); + REG_SET_4(DCN_EXPANSION_MODE, 0, + DRQ_EXPANSION_MODE, rq_regs->drq_expansion_mode, + PRQ_EXPANSION_MODE, rq_regs->prq_expansion_mode, + MRQ_EXPANSION_MODE, rq_regs->mrq_expansion_mode, + CRQ_EXPANSION_MODE, rq_regs->crq_expansion_mode); + REG_SET_8(DCHUBP_REQ_SIZE_CONFIG, 0, + CHUNK_SIZE, rq_regs->rq_regs_l.chunk_size, + MIN_CHUNK_SIZE, rq_regs->rq_regs_l.min_chunk_size, + META_CHUNK_SIZE, rq_regs->rq_regs_l.meta_chunk_size, + MIN_META_CHUNK_SIZE, rq_regs->rq_regs_l.min_meta_chunk_size, + DPTE_GROUP_SIZE, rq_regs->rq_regs_l.dpte_group_size, + MPTE_GROUP_SIZE, rq_regs->rq_regs_l.mpte_group_size, + SWATH_HEIGHT, rq_regs->rq_regs_l.swath_height, + PTE_ROW_HEIGHT_LINEAR, rq_regs->rq_regs_l.pte_row_height_linear); + REG_SET_8(DCHUBP_REQ_SIZE_CONFIG_C, 0, + CHUNK_SIZE_C, rq_regs->rq_regs_c.chunk_size, + MIN_CHUNK_SIZE_C, rq_regs->rq_regs_c.min_chunk_size, + META_CHUNK_SIZE_C, rq_regs->rq_regs_c.meta_chunk_size, + MIN_META_CHUNK_SIZE_C, rq_regs->rq_regs_c.min_meta_chunk_size, + DPTE_GROUP_SIZE_C, rq_regs->rq_regs_c.dpte_group_size, + MPTE_GROUP_SIZE_C, rq_regs->rq_regs_c.mpte_group_size, + SWATH_HEIGHT_C, rq_regs->rq_regs_c.swath_height, + PTE_ROW_HEIGHT_LINEAR_C, rq_regs->rq_regs_c.pte_row_height_linear); +} + + +static void program_deadline( + struct mem_input *mem_input, + struct _vcs_dpi_display_dlg_regs_st *dlg_attr, + struct _vcs_dpi_display_ttu_regs_st *ttu_attr) +{ + struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + + /* DLG - Per hubp */ + REG_SET_2(BLANK_OFFSET_0, 0, + REFCYC_H_BLANK_END, dlg_attr->refcyc_h_blank_end, + DLG_V_BLANK_END, dlg_attr->dlg_vblank_end); + + REG_SET(BLANK_OFFSET_1, 0, + MIN_DST_Y_NEXT_START, dlg_attr->min_dst_y_next_start); + + REG_SET(DST_DIMENSIONS, 0, + REFCYC_PER_HTOTAL, dlg_attr->refcyc_per_htotal); + + REG_SET_2(DST_AFTER_SCALER, 0, + REFCYC_X_AFTER_SCALER, dlg_attr->refcyc_x_after_scaler, + DST_Y_AFTER_SCALER, dlg_attr->dst_y_after_scaler); + + REG_SET_2(PREFETCH_SETTINS, 0, + DST_Y_PREFETCH, dlg_attr->dst_y_prefetch, + VRATIO_PREFETCH, dlg_attr->vratio_prefetch); + + REG_SET_2(VBLANK_PARAMETERS_0, 0, + DST_Y_PER_VM_VBLANK, dlg_attr->dst_y_per_vm_vblank, + DST_Y_PER_ROW_VBLANK, dlg_attr->dst_y_per_row_vblank); + + REG_SET(REF_FREQ_TO_PIX_FREQ, 0, + REF_FREQ_TO_PIX_FREQ, dlg_attr->ref_freq_to_pix_freq); + + /* DLG - Per luma/chroma */ + REG_SET(VBLANK_PARAMETERS_1, 0, + REFCYC_PER_PTE_GROUP_VBLANK_L, dlg_attr->refcyc_per_pte_group_vblank_l); + + REG_SET(VBLANK_PARAMETERS_3, 0, + REFCYC_PER_META_CHUNK_VBLANK_L, dlg_attr->refcyc_per_meta_chunk_vblank_l); + + REG_SET(NOM_PARAMETERS_0, 0, + DST_Y_PER_PTE_ROW_NOM_L, dlg_attr->dst_y_per_pte_row_nom_l); + + REG_SET(NOM_PARAMETERS_1, 0, + REFCYC_PER_PTE_GROUP_NOM_L, dlg_attr->refcyc_per_pte_group_nom_l); + + REG_SET(NOM_PARAMETERS_4, 0, + DST_Y_PER_META_ROW_NOM_L, dlg_attr->dst_y_per_meta_row_nom_l); + + REG_SET(NOM_PARAMETERS_5, 0, + REFCYC_PER_META_CHUNK_NOM_L, dlg_attr->refcyc_per_meta_chunk_nom_l); + + REG_SET_2(PER_LINE_DELIVERY_PRE, 0, + REFCYC_PER_LINE_DELIVERY_PRE_L, dlg_attr->refcyc_per_line_delivery_pre_l, + REFCYC_PER_LINE_DELIVERY_PRE_C, dlg_attr->refcyc_per_line_delivery_pre_c); + + REG_SET_2(PER_LINE_DELIVERY, 0, + REFCYC_PER_LINE_DELIVERY_L, dlg_attr->refcyc_per_line_delivery_l, + REFCYC_PER_LINE_DELIVERY_C, dlg_attr->refcyc_per_line_delivery_c); + + REG_SET(PREFETCH_SETTINS_C, 0, + VRATIO_PREFETCH_C, dlg_attr->vratio_prefetch_c); + + REG_SET(VBLANK_PARAMETERS_2, 0, + REFCYC_PER_PTE_GROUP_VBLANK_C, dlg_attr->refcyc_per_pte_group_vblank_c); + + REG_SET(VBLANK_PARAMETERS_4, 0, + REFCYC_PER_META_CHUNK_VBLANK_C, dlg_attr->refcyc_per_meta_chunk_vblank_c); + + REG_SET(NOM_PARAMETERS_2, 0, + DST_Y_PER_PTE_ROW_NOM_C, dlg_attr->dst_y_per_pte_row_nom_c); + + REG_SET(NOM_PARAMETERS_3, 0, + REFCYC_PER_PTE_GROUP_NOM_C, dlg_attr->refcyc_per_pte_group_nom_c); + + REG_SET(NOM_PARAMETERS_6, 0, + DST_Y_PER_META_ROW_NOM_C, dlg_attr->dst_y_per_meta_row_nom_c); + + REG_SET(NOM_PARAMETERS_7, 0, + REFCYC_PER_META_CHUNK_NOM_C, dlg_attr->refcyc_per_meta_chunk_nom_c); + + /* TTU - per hubp */ + REG_SET_2(DCN_TTU_QOS_WM, 0, + QoS_LEVEL_LOW_WM, ttu_attr->qos_level_low_wm, + QoS_LEVEL_HIGH_WM, ttu_attr->qos_level_high_wm); + + REG_SET_2(DCN_GLOBAL_TTU_CNTL, 0, + MIN_TTU_VBLANK, ttu_attr->min_ttu_vblank, + QoS_LEVEL_FLIP, ttu_attr->qos_level_flip); + + /* TTU - per luma/chroma */ + /* Assumed surf0 is luma and 1 is chroma */ + + REG_SET_3(DCN_SURF0_TTU_CNTL0, 0, + REFCYC_PER_REQ_DELIVERY, ttu_attr->refcyc_per_req_delivery_l, + QoS_LEVEL_FIXED, ttu_attr->qos_level_fixed_l, + QoS_RAMP_DISABLE, ttu_attr->qos_ramp_disable_l); + + REG_SET(DCN_SURF0_TTU_CNTL1, 0, + REFCYC_PER_REQ_DELIVERY_PRE, + ttu_attr->refcyc_per_req_delivery_pre_l); + + REG_SET_3(DCN_SURF1_TTU_CNTL0, 0, + REFCYC_PER_REQ_DELIVERY, ttu_attr->refcyc_per_req_delivery_c, + QoS_LEVEL_FIXED, ttu_attr->qos_level_fixed_c, + QoS_RAMP_DISABLE, ttu_attr->qos_ramp_disable_c); + + REG_SET(DCN_SURF1_TTU_CNTL1, 0, + REFCYC_PER_REQ_DELIVERY_PRE, + ttu_attr->refcyc_per_req_delivery_pre_c); +} + +static void mem_input_setup( + struct mem_input *mem_input, + struct _vcs_dpi_display_dlg_regs_st *dlg_attr, + struct _vcs_dpi_display_ttu_regs_st *ttu_attr, + struct _vcs_dpi_display_rq_regs_st *rq_regs, + struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest) +{ + /* otg is locked when this func is called. Register are double buffered. + * disable the requestors is not needed + */ + /* disable_request(mem_input); */ + program_requestor(mem_input, rq_regs); + program_deadline(mem_input, dlg_attr, ttu_attr); + vready_workaround(mem_input, pipe_dest); +} + +static uint32_t convert_and_clamp( + uint32_t wm_ns, + uint32_t refclk_mhz, + uint32_t clamp_value) +{ + uint32_t ret_val = 0; + ret_val = wm_ns * refclk_mhz; + ret_val /= 1000; + + if (ret_val > clamp_value) + ret_val = clamp_value; + + return ret_val; +} + +static void program_watermarks( + struct mem_input *mem_input, + struct dcn_watermark_set *watermarks, + unsigned int refclk_mhz) +{ + struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + /* + * Need to clamp to max of the register values (i.e. no wrap) + * for dcn1, all wm registers are 21-bit wide + */ + uint32_t prog_wm_value; + + /* Repeat for water mark set A, B, C and D. */ + /* clock state A */ + prog_wm_value = convert_and_clamp(watermarks->a.urgent_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, prog_wm_value); + + dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, + "URGENCY_WATERMARK_A calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->a.urgent_ns, prog_wm_value); + + prog_wm_value = convert_and_clamp(watermarks->a.pte_meta_urgent_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A, prog_wm_value); + dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, + "PTE_META_URGENCY_WATERMARK_A calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->a.pte_meta_urgent_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, + refclk_mhz, 0x1fffff); + + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, prog_wm_value); + dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, + "SR_ENTER_EXIT_WATERMARK_A calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->a.cstate_pstate.cstate_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value); + dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, + "SR_EXIT_WATERMARK_A calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->a.cstate_pstate.cstate_exit_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->a.cstate_pstate.pstate_change_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, prog_wm_value); + dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, + "DRAM_CLK_CHANGE_WATERMARK_A calculated =%d\n" + "HW register value = 0x%x\n\n", + watermarks->a.cstate_pstate.pstate_change_ns, prog_wm_value); + + + /* clock state B */ + prog_wm_value = convert_and_clamp( + watermarks->b.urgent_ns, refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, prog_wm_value); + dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, + "URGENCY_WATERMARK_B calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->b.urgent_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->b.pte_meta_urgent_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B, prog_wm_value); + dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, + "PTE_META_URGENCY_WATERMARK_B calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->b.pte_meta_urgent_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, prog_wm_value); + dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, + "SR_ENTER_WATERMARK_B calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->b.cstate_pstate.cstate_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, prog_wm_value); + dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, + "SR_EXIT_WATERMARK_B calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->b.cstate_pstate.cstate_exit_ns, prog_wm_value); + + prog_wm_value = convert_and_clamp( + watermarks->b.cstate_pstate.pstate_change_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, prog_wm_value); + dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, + "DRAM_CLK_CHANGE_WATERMARK_B calculated =%d\n\n" + "HW register value = 0x%x\n", + watermarks->b.cstate_pstate.pstate_change_ns, prog_wm_value); + + /* clock state C */ + prog_wm_value = convert_and_clamp( + watermarks->c.urgent_ns, refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, prog_wm_value); + dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, + "URGENCY_WATERMARK_C calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->c.urgent_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->c.pte_meta_urgent_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C, prog_wm_value); + dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, + "PTE_META_URGENCY_WATERMARK_C calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->c.pte_meta_urgent_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, prog_wm_value); + dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, + "SR_ENTER_WATERMARK_C calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->c.cstate_pstate.cstate_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, prog_wm_value); + dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, + "SR_EXIT_WATERMARK_C calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->c.cstate_pstate.cstate_exit_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->c.cstate_pstate.pstate_change_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, prog_wm_value); + dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, + "DRAM_CLK_CHANGE_WATERMARK_C calculated =%d\n\n" + "HW register value = 0x%x\n", + watermarks->c.cstate_pstate.pstate_change_ns, prog_wm_value); + + /* clock state D */ + prog_wm_value = convert_and_clamp( + watermarks->d.urgent_ns, refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, prog_wm_value); + dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, + "URGENCY_WATERMARK_D calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->d.urgent_ns, prog_wm_value); + + prog_wm_value = convert_and_clamp( + watermarks->d.pte_meta_urgent_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D, prog_wm_value); + dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, + "PTE_META_URGENCY_WATERMARK_D calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->d.pte_meta_urgent_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, prog_wm_value); + dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, + "SR_ENTER_WATERMARK_D calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->d.cstate_pstate.cstate_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, prog_wm_value); + dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, + "SR_EXIT_WATERMARK_D calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->d.cstate_pstate.cstate_exit_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->d.cstate_pstate.pstate_change_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, prog_wm_value); + dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, + "DRAM_CLK_CHANGE_WATERMARK_D calculated =%d\n" + "HW register value = 0x%x\n\n", + watermarks->d.cstate_pstate.pstate_change_ns, prog_wm_value); + + REG_UPDATE(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, + DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, 1); + REG_UPDATE(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, + DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, 0); + REG_UPDATE(DCHUBBUB_ARB_SAT_LEVEL, + DCHUBBUB_ARB_SAT_LEVEL, 60 * refclk_mhz); + REG_UPDATE(DCHUBBUB_ARB_DF_REQ_OUTSTAND, + DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 68); + +#if 0 + REG_UPDATE_2(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, + DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE, 1, + DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, 1); +#endif +} + +static void mem_input_program_display_marks( + struct mem_input *mem_input, + struct bw_watermarks nbp, + struct bw_watermarks stutter, + struct bw_watermarks urgent, + uint32_t total_dest_line_time_ns) +{ + /* only for dce + * dcn use only program_watermarks + */ +} + +bool mem_input_is_flip_pending(struct mem_input *mem_input) +{ + uint32_t update_pending = 0; + struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + + REG_GET(DCSURF_FLIP_CONTROL, + SURFACE_UPDATE_PENDING, &update_pending); + + if (update_pending) + return true; + + mem_input->current_address = mem_input->request_address; + return false; +} + +static void mem_input_update_dchub( + struct mem_input *mem_input, + struct dchub_init_data *dh_data) +{ + struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + /* TODO: port code from dal2 */ + switch (dh_data->fb_mode) { + case FRAME_BUFFER_MODE_ZFB_ONLY: + /*For ZFB case need to put DCHUB FB BASE and TOP upside down to indicate ZFB mode*/ + REG_UPDATE(DCHUBBUB_SDPIF_FB_TOP, + SDPIF_FB_TOP, 0); + + REG_UPDATE(DCHUBBUB_SDPIF_FB_BASE, + SDPIF_FB_BASE, 0x0FFFF); + + REG_UPDATE(DCHUBBUB_SDPIF_AGP_BASE, + SDPIF_AGP_BASE, dh_data->zfb_phys_addr_base >> 22); + + REG_UPDATE(DCHUBBUB_SDPIF_AGP_BOT, + SDPIF_AGP_BOT, dh_data->zfb_mc_base_addr >> 22); + + REG_UPDATE(DCHUBBUB_SDPIF_AGP_TOP, + SDPIF_AGP_TOP, (dh_data->zfb_mc_base_addr + + dh_data->zfb_size_in_byte - 1) >> 22); + break; + case FRAME_BUFFER_MODE_MIXED_ZFB_AND_LOCAL: + /*Should not touch FB LOCATION (done by VBIOS on AsicInit table)*/ + + REG_UPDATE(DCHUBBUB_SDPIF_AGP_BASE, + SDPIF_AGP_BASE, dh_data->zfb_phys_addr_base >> 22); + + REG_UPDATE(DCHUBBUB_SDPIF_AGP_BOT, + SDPIF_AGP_BOT, dh_data->zfb_mc_base_addr >> 22); + + REG_UPDATE(DCHUBBUB_SDPIF_AGP_TOP, + SDPIF_AGP_TOP, (dh_data->zfb_mc_base_addr + + dh_data->zfb_size_in_byte - 1) >> 22); + break; + case FRAME_BUFFER_MODE_LOCAL_ONLY: + /*Should not touch FB LOCATION (done by VBIOS on AsicInit table)*/ + REG_UPDATE(DCHUBBUB_SDPIF_AGP_BASE, + SDPIF_AGP_BASE, 0); + + REG_UPDATE(DCHUBBUB_SDPIF_AGP_BOT, + SDPIF_AGP_BOT, 0X03FFFF); + + REG_UPDATE(DCHUBBUB_SDPIF_AGP_TOP, + SDPIF_AGP_TOP, 0); + break; + default: + break; + } + + dh_data->dchub_initialzied = true; + dh_data->dchub_info_valid = false; +} + +struct vm_system_aperture_param { + PHYSICAL_ADDRESS_LOC sys_default; + PHYSICAL_ADDRESS_LOC sys_low; + PHYSICAL_ADDRESS_LOC sys_high; +}; + +static void read_vm_system_aperture_settings(struct dcn10_mem_input *mi, + struct vm_system_aperture_param *apt) +{ + PHYSICAL_ADDRESS_LOC physical_page_number; + uint32_t logical_addr_low; + uint32_t logical_addr_high; + + REG_GET(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, + PHYSICAL_PAGE_NUMBER_MSB, &physical_page_number.high_part); + REG_GET(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, + PHYSICAL_PAGE_NUMBER_LSB, &physical_page_number.low_part); + + REG_GET(MC_VM_SYSTEM_APERTURE_LOW_ADDR, + LOGICAL_ADDR, &logical_addr_low); + + REG_GET(MC_VM_SYSTEM_APERTURE_HIGH_ADDR, + LOGICAL_ADDR, &logical_addr_high); + + apt->sys_default.quad_part = physical_page_number.quad_part << 12; + apt->sys_low.quad_part = (int64_t)logical_addr_low << 18; + apt->sys_high.quad_part = (int64_t)logical_addr_high << 18; +} + +static void set_vm_system_aperture_settings(struct dcn10_mem_input *mi, + struct vm_system_aperture_param *apt) +{ + PHYSICAL_ADDRESS_LOC mc_vm_apt_default; + PHYSICAL_ADDRESS_LOC mc_vm_apt_low; + PHYSICAL_ADDRESS_LOC mc_vm_apt_high; + + mc_vm_apt_default.quad_part = apt->sys_default.quad_part >> 12; + mc_vm_apt_low.quad_part = apt->sys_low.quad_part >> 12; + mc_vm_apt_high.quad_part = apt->sys_high.quad_part >> 12; + + REG_SET_2(DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, 0, + MC_VM_SYSTEM_APERTURE_DEFAULT_SYSTEM, 1, /* 1 = system physical memory */ + MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, mc_vm_apt_default.high_part); + REG_SET(DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, 0, + MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, mc_vm_apt_default.low_part); + + REG_SET(DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, 0, + MC_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, mc_vm_apt_low.high_part); + REG_SET(DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, 0, + MC_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, mc_vm_apt_low.low_part); + + REG_SET(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, 0, + MC_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, mc_vm_apt_high.high_part); + REG_SET(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, 0, + MC_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, mc_vm_apt_high.low_part); +} + +struct vm_context0_param { + PHYSICAL_ADDRESS_LOC pte_base; + PHYSICAL_ADDRESS_LOC pte_start; + PHYSICAL_ADDRESS_LOC pte_end; + PHYSICAL_ADDRESS_LOC fault_default; +}; + +/* Temporary read settings, future will get values from kmd directly */ +static void read_vm_context0_settings(struct dcn10_mem_input *mi, + struct vm_context0_param *vm0) +{ + PHYSICAL_ADDRESS_LOC fb_base; + PHYSICAL_ADDRESS_LOC fb_offset; + uint32_t fb_base_value; + uint32_t fb_offset_value; + + REG_GET(DCHUBBUB_SDPIF_FB_BASE, SDPIF_FB_BASE, &fb_base_value); + REG_GET(DCHUBBUB_SDPIF_FB_OFFSET, SDPIF_FB_OFFSET, &fb_offset_value); + + REG_GET(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32, + PAGE_DIRECTORY_ENTRY_HI32, &vm0->pte_base.high_part); + REG_GET(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32, + PAGE_DIRECTORY_ENTRY_LO32, &vm0->pte_base.low_part); + + REG_GET(VM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32, + LOGICAL_PAGE_NUMBER_HI4, &vm0->pte_start.high_part); + REG_GET(VM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32, + LOGICAL_PAGE_NUMBER_LO32, &vm0->pte_start.low_part); + + REG_GET(VM_CONTEXT0_PAGE_TABLE_END_ADDR_HI32, + LOGICAL_PAGE_NUMBER_HI4, &vm0->pte_end.high_part); + REG_GET(VM_CONTEXT0_PAGE_TABLE_END_ADDR_LO32, + LOGICAL_PAGE_NUMBER_LO32, &vm0->pte_end.low_part); + + REG_GET(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_HI32, + PHYSICAL_PAGE_ADDR_HI4, &vm0->fault_default.high_part); + REG_GET(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32, + PHYSICAL_PAGE_ADDR_LO32, &vm0->fault_default.low_part); + + /* + * The values in VM_CONTEXT0_PAGE_TABLE_BASE_ADDR is in UMA space. + * Therefore we need to do + * DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR = VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + * - DCHUBBUB_SDPIF_FB_OFFSET + DCHUBBUB_SDPIF_FB_BASE + */ + fb_base.quad_part = (uint64_t)fb_base_value << 24; + fb_offset.quad_part = (uint64_t)fb_offset_value << 24; + vm0->pte_base.quad_part += fb_base.quad_part; + vm0->pte_base.quad_part -= fb_offset.quad_part; +} + +static void set_vm_context0_settings(struct dcn10_mem_input *mi, + const struct vm_context0_param *vm0) +{ + /* pte base */ + REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, 0, + VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, vm0->pte_base.high_part); + REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB, 0, + VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB, vm0->pte_base.low_part); + + /* pte start */ + REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB, 0, + VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB, vm0->pte_start.high_part); + REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_LSB, 0, + VM_CONTEXT0_PAGE_TABLE_START_ADDR_LSB, vm0->pte_start.low_part); + + /* pte end */ + REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB, 0, + VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB, vm0->pte_end.high_part); + REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB, 0, + VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB, vm0->pte_end.low_part); + + /* fault handling */ + REG_SET(DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, 0, + VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB, vm0->fault_default.high_part); + /* VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_SYSTEM, 0 */ + REG_SET(DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, 0, + VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, vm0->fault_default.low_part); +} + +void dcn_mem_input_program_pte_vm(struct mem_input *mem_input, + enum surface_pixel_format format, + union dc_tiling_info *tiling_info, + enum dc_rotation_angle rotation) +{ + struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + struct vm_system_aperture_param apt = { {{ 0 } } }; + struct vm_context0_param vm0 = { { { 0 } } }; + + + read_vm_system_aperture_settings(mi, &apt); + read_vm_context0_settings(mi, &vm0); + + set_vm_system_aperture_settings(mi, &apt); + set_vm_context0_settings(mi, &vm0); + + /* control: enable VM PTE*/ + REG_SET_2(DCN_VM_MX_L1_TLB_CNTL, 0, + ENABLE_L1_TLB, 1, + SYSTEM_ACCESS_MODE, 3); +} + +static struct mem_input_funcs dcn10_mem_input_funcs = { + .mem_input_program_display_marks = mem_input_program_display_marks, + .allocate_mem_input = NULL, + .free_mem_input = NULL, + .disable_request = disable_request, + .mem_input_program_surface_flip_and_addr = + mem_input_program_surface_flip_and_addr, + .mem_input_program_surface_config = + mem_input_program_surface_config, + .mem_input_is_flip_pending = mem_input_is_flip_pending, + .mem_input_setup = mem_input_setup, + .program_watermarks = program_watermarks, + .mem_input_update_dchub = mem_input_update_dchub, + .mem_input_program_pte_vm = dcn_mem_input_program_pte_vm, +}; + + +/*****************************************/ +/* Constructor, Destructor */ +/*****************************************/ + +bool dcn10_mem_input_construct( + struct dcn10_mem_input *mi, + struct dc_context *ctx, + uint32_t inst, + const struct dcn_mi_registers *mi_regs, + const struct dcn_mi_shift *mi_shift, + const struct dcn_mi_mask *mi_mask) +{ + mi->base.funcs = &dcn10_mem_input_funcs; + mi->base.ctx = ctx; + mi->mi_regs = mi_regs; + mi->mi_shift = mi_shift; + mi->mi_mask = mi_mask; + mi->base.inst = inst; + + return true; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h new file mode 100644 index 000000000000..4a5eb6ae3524 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h @@ -0,0 +1,553 @@ +/* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_MEM_INPUT_DCN10_H__ +#define __DC_MEM_INPUT_DCN10_H__ + +#include "mem_input.h" + +#define TO_DCN10_MEM_INPUT(mi)\ + container_of(mi, struct dcn10_mem_input, base) + + +#define MI_DCN10_REG_LIST(id)\ + SRI(DCHUBP_CNTL, HUBP, id),\ + SRI(HUBPREQ_DEBUG_DB, HUBP, id),\ + SRI(DCSURF_ADDR_CONFIG, HUBP, id),\ + SRI(DCSURF_TILING_CONFIG, HUBP, id),\ + SRI(DCSURF_SURFACE_PITCH, HUBPREQ, id),\ + SRI(DCSURF_SURFACE_PITCH_C, HUBPREQ, id),\ + SRI(DCSURF_SURFACE_CONFIG, HUBP, id),\ + SRI(DCSURF_FLIP_CONTROL, HUBPREQ, id),\ + SRI(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, HUBPREQ, id),\ + SRI(DCSURF_PRIMARY_SURFACE_ADDRESS, HUBPREQ, id),\ + SRI(DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH, HUBPREQ, id),\ + SRI(DCSURF_SECONDARY_SURFACE_ADDRESS, HUBPREQ, id),\ + SRI(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, HUBPREQ, id),\ + SRI(DCSURF_PRIMARY_META_SURFACE_ADDRESS, HUBPREQ, id),\ + SRI(DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH, HUBPREQ, id),\ + SRI(DCSURF_SECONDARY_META_SURFACE_ADDRESS, HUBPREQ, id),\ + SRI(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C, HUBPREQ, id),\ + SRI(DCSURF_PRIMARY_SURFACE_ADDRESS_C, HUBPREQ, id),\ + SRI(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C, HUBPREQ, id),\ + SRI(DCSURF_PRIMARY_META_SURFACE_ADDRESS_C, HUBPREQ, id),\ + SRI(DCSURF_SURFACE_CONTROL, HUBPREQ, id),\ + SRI(HUBPRET_CONTROL, HUBPRET, id),\ + SRI(DCN_EXPANSION_MODE, HUBPREQ, id),\ + SRI(DCHUBP_REQ_SIZE_CONFIG, HUBP, id),\ + SRI(DCHUBP_REQ_SIZE_CONFIG_C, HUBP, id),\ + SRI(BLANK_OFFSET_0, HUBPREQ, id),\ + SRI(BLANK_OFFSET_1, HUBPREQ, id),\ + SRI(DST_DIMENSIONS, HUBPREQ, id),\ + SRI(DST_AFTER_SCALER, HUBPREQ, id),\ + SRI(PREFETCH_SETTINS, HUBPREQ, id),\ + SRI(VBLANK_PARAMETERS_0, HUBPREQ, id),\ + SRI(REF_FREQ_TO_PIX_FREQ, HUBPREQ, id),\ + SRI(VBLANK_PARAMETERS_1, HUBPREQ, id),\ + SRI(VBLANK_PARAMETERS_3, HUBPREQ, id),\ + SRI(NOM_PARAMETERS_0, HUBPREQ, id),\ + SRI(NOM_PARAMETERS_1, HUBPREQ, id),\ + SRI(NOM_PARAMETERS_4, HUBPREQ, id),\ + SRI(NOM_PARAMETERS_5, HUBPREQ, id),\ + SRI(PER_LINE_DELIVERY_PRE, HUBPREQ, id),\ + SRI(PER_LINE_DELIVERY, HUBPREQ, id),\ + SRI(PREFETCH_SETTINS_C, HUBPREQ, id),\ + SRI(VBLANK_PARAMETERS_2, HUBPREQ, id),\ + SRI(VBLANK_PARAMETERS_4, HUBPREQ, id),\ + SRI(NOM_PARAMETERS_2, HUBPREQ, id),\ + SRI(NOM_PARAMETERS_3, HUBPREQ, id),\ + SRI(NOM_PARAMETERS_6, HUBPREQ, id),\ + SRI(NOM_PARAMETERS_7, HUBPREQ, id),\ + SRI(DCN_TTU_QOS_WM, HUBPREQ, id),\ + SRI(DCN_GLOBAL_TTU_CNTL, HUBPREQ, id),\ + SRI(DCN_SURF0_TTU_CNTL0, HUBPREQ, id),\ + SRI(DCN_SURF0_TTU_CNTL1, HUBPREQ, id),\ + SRI(DCN_SURF1_TTU_CNTL0, HUBPREQ, id),\ + SRI(DCN_SURF1_TTU_CNTL1, HUBPREQ, id),\ + SRI(DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, HUBPREQ, id),\ + SRI(DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB, HUBPREQ, id),\ + SRI(DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB, HUBPREQ, id),\ + SRI(DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_LSB, HUBPREQ, id),\ + SRI(DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB, HUBPREQ, id),\ + SRI(DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB, HUBPREQ, id),\ + SRI(DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, HUBPREQ, id),\ + SRI(DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, HUBPREQ, id),\ + SRI(DCN_VM_MX_L1_TLB_CNTL, HUBPREQ, id),\ + SRI(DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, HUBPREQ, id),\ + SRI(DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, HUBPREQ, id),\ + SRI(DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, HUBPREQ, id),\ + SRI(DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, HUBPREQ, id),\ + SRI(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, HUBPREQ, id),\ + SRI(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, HUBPREQ, id),\ + SR(DCHUBBUB_SDPIF_FB_TOP),\ + SR(DCHUBBUB_SDPIF_FB_BASE),\ + SR(DCHUBBUB_SDPIF_FB_OFFSET),\ + SR(DCHUBBUB_SDPIF_AGP_BASE),\ + SR(DCHUBBUB_SDPIF_AGP_BOT),\ + SR(DCHUBBUB_SDPIF_AGP_TOP),\ + SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A),\ + SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A),\ + SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A),\ + SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A),\ + SR(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A),\ + SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B),\ + SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B),\ + SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B),\ + SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B),\ + SR(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B),\ + SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C),\ + SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C),\ + SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C),\ + SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C),\ + SR(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C),\ + SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D),\ + SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D),\ + SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D),\ + SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D),\ + SR(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D),\ + SR(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL),\ + SR(DCHUBBUB_ARB_SAT_LEVEL),\ + SR(DCHUBBUB_ARB_DF_REQ_OUTSTAND),\ + /* todo: get these from GVM instead of reading registers ourselves */\ + GC_SR(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32),\ + GC_SR(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32),\ + GC_SR(VM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32),\ + GC_SR(VM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32),\ + GC_SR(VM_CONTEXT0_PAGE_TABLE_END_ADDR_HI32),\ + GC_SR(VM_CONTEXT0_PAGE_TABLE_END_ADDR_LO32),\ + GC_SR(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_HI32),\ + GC_SR(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32),\ + GC_SR(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB),\ + GC_SR(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB),\ + GC_SR(MC_VM_SYSTEM_APERTURE_LOW_ADDR),\ + GC_SR(MC_VM_SYSTEM_APERTURE_HIGH_ADDR) + +struct dcn_mi_registers { + uint32_t DCHUBP_CNTL; + uint32_t HUBPREQ_DEBUG_DB; + uint32_t DCSURF_ADDR_CONFIG; + uint32_t DCSURF_TILING_CONFIG; + uint32_t DCSURF_SURFACE_PITCH; + uint32_t DCSURF_SURFACE_PITCH_C; + uint32_t DCSURF_SURFACE_CONFIG; + uint32_t DCSURF_FLIP_CONTROL; + uint32_t DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH; + uint32_t DCSURF_PRIMARY_SURFACE_ADDRESS; + uint32_t DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH; + uint32_t DCSURF_SECONDARY_SURFACE_ADDRESS; + uint32_t DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH; + uint32_t DCSURF_PRIMARY_META_SURFACE_ADDRESS; + uint32_t DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH; + uint32_t DCSURF_SECONDARY_META_SURFACE_ADDRESS; + uint32_t DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C; + uint32_t DCSURF_PRIMARY_SURFACE_ADDRESS_C; + uint32_t DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C; + uint32_t DCSURF_PRIMARY_META_SURFACE_ADDRESS_C; + uint32_t DCSURF_SURFACE_CONTROL; + uint32_t HUBPRET_CONTROL; + uint32_t DCN_EXPANSION_MODE; + uint32_t DCHUBP_REQ_SIZE_CONFIG; + uint32_t DCHUBP_REQ_SIZE_CONFIG_C; + uint32_t BLANK_OFFSET_0; + uint32_t BLANK_OFFSET_1; + uint32_t DST_DIMENSIONS; + uint32_t DST_AFTER_SCALER; + uint32_t PREFETCH_SETTINS; + uint32_t VBLANK_PARAMETERS_0; + uint32_t REF_FREQ_TO_PIX_FREQ; + uint32_t VBLANK_PARAMETERS_1; + uint32_t VBLANK_PARAMETERS_3; + uint32_t NOM_PARAMETERS_0; + uint32_t NOM_PARAMETERS_1; + uint32_t NOM_PARAMETERS_4; + uint32_t NOM_PARAMETERS_5; + uint32_t PER_LINE_DELIVERY_PRE; + uint32_t PER_LINE_DELIVERY; + uint32_t PREFETCH_SETTINS_C; + uint32_t VBLANK_PARAMETERS_2; + uint32_t VBLANK_PARAMETERS_4; + uint32_t NOM_PARAMETERS_2; + uint32_t NOM_PARAMETERS_3; + uint32_t NOM_PARAMETERS_6; + uint32_t NOM_PARAMETERS_7; + uint32_t DCN_TTU_QOS_WM; + uint32_t DCN_GLOBAL_TTU_CNTL; + uint32_t DCN_SURF0_TTU_CNTL0; + uint32_t DCN_SURF0_TTU_CNTL1; + uint32_t DCN_SURF1_TTU_CNTL0; + uint32_t DCN_SURF1_TTU_CNTL1; + uint32_t DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB; + uint32_t DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB; + uint32_t DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB; + uint32_t DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_LSB; + uint32_t DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB; + uint32_t DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB; + uint32_t DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB; + uint32_t DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB; + uint32_t DCN_VM_MX_L1_TLB_CNTL; + uint32_t DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB; + uint32_t DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB; + uint32_t DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB; + uint32_t DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB; + uint32_t DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB; + uint32_t DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB; + uint32_t DCHUBBUB_SDPIF_FB_TOP; + uint32_t DCHUBBUB_SDPIF_FB_BASE; + uint32_t DCHUBBUB_SDPIF_FB_OFFSET; + uint32_t DCHUBBUB_SDPIF_AGP_BASE; + uint32_t DCHUBBUB_SDPIF_AGP_BOT; + uint32_t DCHUBBUB_SDPIF_AGP_TOP; + uint32_t DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A; + uint32_t DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A; + uint32_t DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A; + uint32_t DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A; + uint32_t DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A; + uint32_t DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B; + uint32_t DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B; + uint32_t DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B; + uint32_t DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B; + uint32_t DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B; + uint32_t DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C; + uint32_t DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C; + uint32_t DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C; + uint32_t DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C; + uint32_t DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C; + uint32_t DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D; + uint32_t DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D; + uint32_t DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D; + uint32_t DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D; + uint32_t DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D; + uint32_t DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL; + uint32_t DCHUBBUB_ARB_SAT_LEVEL; + uint32_t DCHUBBUB_ARB_DF_REQ_OUTSTAND; + + /* GC registers. read only. temporary hack */ + uint32_t VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32; + uint32_t VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32; + uint32_t VM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32; + uint32_t VM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32; + uint32_t VM_CONTEXT0_PAGE_TABLE_END_ADDR_HI32; + uint32_t VM_CONTEXT0_PAGE_TABLE_END_ADDR_LO32; + uint32_t VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_HI32; + uint32_t VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32; + uint32_t MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB; + uint32_t MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB; + uint32_t MC_VM_SYSTEM_APERTURE_LOW_ADDR; + uint32_t MC_VM_SYSTEM_APERTURE_HIGH_ADDR; +}; + +#define MI_SF(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define MI_DCN10_MASK_SH_LIST(mask_sh)\ + MI_SF(HUBP0_DCHUBP_CNTL, HUBP_BLANK_EN, mask_sh),\ + MI_SF(HUBP0_DCHUBP_CNTL, HUBP_TTU_DISABLE, mask_sh),\ + MI_SF(HUBP0_DCSURF_ADDR_CONFIG, NUM_PIPES, mask_sh),\ + MI_SF(HUBP0_DCSURF_ADDR_CONFIG, NUM_BANKS, mask_sh),\ + MI_SF(HUBP0_DCSURF_ADDR_CONFIG, PIPE_INTERLEAVE, mask_sh),\ + MI_SF(HUBP0_DCSURF_ADDR_CONFIG, NUM_SE, mask_sh),\ + MI_SF(HUBP0_DCSURF_ADDR_CONFIG, NUM_RB_PER_SE, mask_sh),\ + MI_SF(HUBP0_DCSURF_ADDR_CONFIG, MAX_COMPRESSED_FRAGS, mask_sh),\ + MI_SF(HUBP0_DCSURF_TILING_CONFIG, SW_MODE, mask_sh),\ + MI_SF(HUBP0_DCSURF_TILING_CONFIG, META_LINEAR, mask_sh),\ + MI_SF(HUBP0_DCSURF_TILING_CONFIG, RB_ALIGNED, mask_sh),\ + MI_SF(HUBP0_DCSURF_TILING_CONFIG, PIPE_ALIGNED, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SURFACE_PITCH, PITCH, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SURFACE_PITCH, META_PITCH, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SURFACE_PITCH_C, PITCH_C, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SURFACE_PITCH_C, META_PITCH_C, mask_sh),\ + MI_SF(HUBP0_DCSURF_SURFACE_CONFIG, ROTATION_ANGLE, mask_sh),\ + MI_SF(HUBP0_DCSURF_SURFACE_CONFIG, H_MIRROR_EN, mask_sh),\ + MI_SF(HUBP0_DCSURF_SURFACE_CONFIG, SURFACE_PIXEL_FORMAT, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_FLIP_CONTROL, SURFACE_FLIP_TYPE, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_FLIP_CONTROL, SURFACE_UPDATE_PENDING, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, PRIMARY_SURFACE_ADDRESS_HIGH, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_PRIMARY_SURFACE_ADDRESS, PRIMARY_SURFACE_ADDRESS, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH, SECONDARY_SURFACE_ADDRESS_HIGH, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SECONDARY_SURFACE_ADDRESS, SECONDARY_SURFACE_ADDRESS, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, PRIMARY_META_SURFACE_ADDRESS_HIGH, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_PRIMARY_META_SURFACE_ADDRESS, PRIMARY_META_SURFACE_ADDRESS, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH, SECONDARY_META_SURFACE_ADDRESS_HIGH, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SECONDARY_META_SURFACE_ADDRESS, SECONDARY_META_SURFACE_ADDRESS, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C, PRIMARY_SURFACE_ADDRESS_HIGH_C, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_PRIMARY_SURFACE_ADDRESS_C, PRIMARY_SURFACE_ADDRESS_C, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C, PRIMARY_META_SURFACE_ADDRESS_HIGH_C, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_PRIMARY_META_SURFACE_ADDRESS_C, PRIMARY_META_SURFACE_ADDRESS_C, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, PRIMARY_SURFACE_DCC_EN, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, PRIMARY_SURFACE_DCC_IND_64B_BLK, mask_sh),\ + MI_SF(HUBPRET0_HUBPRET_CONTROL, DET_BUF_PLANE1_BASE_ADDRESS, mask_sh),\ + MI_SF(HUBPRET0_HUBPRET_CONTROL, CROSSBAR_SRC_CB_B, mask_sh),\ + MI_SF(HUBPRET0_HUBPRET_CONTROL, CROSSBAR_SRC_CR_R, mask_sh),\ + MI_SF(HUBPREQ0_DCN_EXPANSION_MODE, DRQ_EXPANSION_MODE, mask_sh),\ + MI_SF(HUBPREQ0_DCN_EXPANSION_MODE, PRQ_EXPANSION_MODE, mask_sh),\ + MI_SF(HUBPREQ0_DCN_EXPANSION_MODE, MRQ_EXPANSION_MODE, mask_sh),\ + MI_SF(HUBPREQ0_DCN_EXPANSION_MODE, CRQ_EXPANSION_MODE, mask_sh),\ + MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, CHUNK_SIZE, mask_sh),\ + MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, MIN_CHUNK_SIZE, mask_sh),\ + MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, META_CHUNK_SIZE, mask_sh),\ + MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, MIN_META_CHUNK_SIZE, mask_sh),\ + MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, DPTE_GROUP_SIZE, mask_sh),\ + MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, MPTE_GROUP_SIZE, mask_sh),\ + MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, SWATH_HEIGHT, mask_sh),\ + MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, PTE_ROW_HEIGHT_LINEAR, mask_sh),\ + MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, CHUNK_SIZE_C, mask_sh),\ + MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, MIN_CHUNK_SIZE_C, mask_sh),\ + MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, META_CHUNK_SIZE_C, mask_sh),\ + MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, MIN_META_CHUNK_SIZE_C, mask_sh),\ + MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, DPTE_GROUP_SIZE_C, mask_sh),\ + MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, MPTE_GROUP_SIZE_C, mask_sh),\ + MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, SWATH_HEIGHT_C, mask_sh),\ + MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, PTE_ROW_HEIGHT_LINEAR_C, mask_sh),\ + MI_SF(HUBPREQ0_BLANK_OFFSET_0, REFCYC_H_BLANK_END, mask_sh),\ + MI_SF(HUBPREQ0_BLANK_OFFSET_0, DLG_V_BLANK_END, mask_sh),\ + MI_SF(HUBPREQ0_BLANK_OFFSET_1, MIN_DST_Y_NEXT_START, mask_sh),\ + MI_SF(HUBPREQ0_DST_DIMENSIONS, REFCYC_PER_HTOTAL, mask_sh),\ + MI_SF(HUBPREQ0_DST_AFTER_SCALER, REFCYC_X_AFTER_SCALER, mask_sh),\ + MI_SF(HUBPREQ0_DST_AFTER_SCALER, DST_Y_AFTER_SCALER, mask_sh),\ + MI_SF(HUBPREQ0_PREFETCH_SETTINS, DST_Y_PREFETCH, mask_sh),\ + MI_SF(HUBPREQ0_PREFETCH_SETTINS, VRATIO_PREFETCH, mask_sh),\ + MI_SF(HUBPREQ0_VBLANK_PARAMETERS_0, DST_Y_PER_VM_VBLANK, mask_sh),\ + MI_SF(HUBPREQ0_VBLANK_PARAMETERS_0, DST_Y_PER_ROW_VBLANK, mask_sh),\ + MI_SF(HUBPREQ0_REF_FREQ_TO_PIX_FREQ, REF_FREQ_TO_PIX_FREQ, mask_sh),\ + MI_SF(HUBPREQ0_VBLANK_PARAMETERS_1, REFCYC_PER_PTE_GROUP_VBLANK_L, mask_sh),\ + MI_SF(HUBPREQ0_VBLANK_PARAMETERS_3, REFCYC_PER_META_CHUNK_VBLANK_L, mask_sh),\ + MI_SF(HUBPREQ0_NOM_PARAMETERS_0, DST_Y_PER_PTE_ROW_NOM_L, mask_sh),\ + MI_SF(HUBPREQ0_NOM_PARAMETERS_1, REFCYC_PER_PTE_GROUP_NOM_L, mask_sh),\ + MI_SF(HUBPREQ0_NOM_PARAMETERS_4, DST_Y_PER_META_ROW_NOM_L, mask_sh),\ + MI_SF(HUBPREQ0_NOM_PARAMETERS_5, REFCYC_PER_META_CHUNK_NOM_L, mask_sh),\ + MI_SF(HUBPREQ0_PER_LINE_DELIVERY_PRE, REFCYC_PER_LINE_DELIVERY_PRE_L, mask_sh),\ + MI_SF(HUBPREQ0_PER_LINE_DELIVERY_PRE, REFCYC_PER_LINE_DELIVERY_PRE_C, mask_sh),\ + MI_SF(HUBPREQ0_PER_LINE_DELIVERY, REFCYC_PER_LINE_DELIVERY_L, mask_sh),\ + MI_SF(HUBPREQ0_PER_LINE_DELIVERY, REFCYC_PER_LINE_DELIVERY_C, mask_sh),\ + MI_SF(HUBPREQ0_PREFETCH_SETTINS_C, VRATIO_PREFETCH_C, mask_sh),\ + MI_SF(HUBPREQ0_VBLANK_PARAMETERS_2, REFCYC_PER_PTE_GROUP_VBLANK_C, mask_sh),\ + MI_SF(HUBPREQ0_VBLANK_PARAMETERS_4, REFCYC_PER_META_CHUNK_VBLANK_C, mask_sh),\ + MI_SF(HUBPREQ0_NOM_PARAMETERS_2, DST_Y_PER_PTE_ROW_NOM_C, mask_sh),\ + MI_SF(HUBPREQ0_NOM_PARAMETERS_3, REFCYC_PER_PTE_GROUP_NOM_C, mask_sh),\ + MI_SF(HUBPREQ0_NOM_PARAMETERS_6, DST_Y_PER_META_ROW_NOM_C, mask_sh),\ + MI_SF(HUBPREQ0_NOM_PARAMETERS_7, REFCYC_PER_META_CHUNK_NOM_C, mask_sh),\ + MI_SF(HUBPREQ0_DCN_TTU_QOS_WM, QoS_LEVEL_LOW_WM, mask_sh),\ + MI_SF(HUBPREQ0_DCN_TTU_QOS_WM, QoS_LEVEL_HIGH_WM, mask_sh),\ + MI_SF(HUBPREQ0_DCN_GLOBAL_TTU_CNTL, MIN_TTU_VBLANK, mask_sh),\ + MI_SF(HUBPREQ0_DCN_GLOBAL_TTU_CNTL, QoS_LEVEL_FLIP, mask_sh),\ + MI_SF(HUBPREQ0_DCN_SURF0_TTU_CNTL0, REFCYC_PER_REQ_DELIVERY, mask_sh),\ + MI_SF(HUBPREQ0_DCN_SURF0_TTU_CNTL0, QoS_LEVEL_FIXED, mask_sh),\ + MI_SF(HUBPREQ0_DCN_SURF0_TTU_CNTL0, QoS_RAMP_DISABLE, mask_sh),\ + MI_SF(HUBPREQ0_DCN_SURF0_TTU_CNTL1, REFCYC_PER_REQ_DELIVERY_PRE, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB, VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB, VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_LSB, VM_CONTEXT0_PAGE_TABLE_START_ADDR_LSB, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB, VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB, VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_MX_L1_TLB_CNTL, ENABLE_L1_TLB, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_MX_L1_TLB_CNTL, SYSTEM_ACCESS_MODE, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, MC_VM_SYSTEM_APERTURE_DEFAULT_SYSTEM, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, MC_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, MC_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, MC_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, MC_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, mask_sh),\ + MI_SF(DCHUBBUB_SDPIF_FB_TOP, SDPIF_FB_TOP, mask_sh),\ + MI_SF(DCHUBBUB_SDPIF_FB_BASE, SDPIF_FB_BASE, mask_sh),\ + MI_SF(DCHUBBUB_SDPIF_FB_OFFSET, SDPIF_FB_OFFSET, mask_sh),\ + MI_SF(DCHUBBUB_SDPIF_AGP_BASE, SDPIF_AGP_BASE, mask_sh),\ + MI_SF(DCHUBBUB_SDPIF_AGP_BOT, SDPIF_AGP_BOT, mask_sh),\ + MI_SF(DCHUBBUB_SDPIF_AGP_TOP, SDPIF_AGP_TOP, mask_sh),\ + MI_SF(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, mask_sh),\ + MI_SF(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE, mask_sh),\ + MI_SF(DCHUBBUB_ARB_SAT_LEVEL, DCHUBBUB_ARB_SAT_LEVEL, mask_sh),\ + MI_SF(DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MIN_REQ_OUTSTAND, mask_sh),\ + /* todo: get these from GVM instead of reading registers ourselves */\ + MI_SF(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32, PAGE_DIRECTORY_ENTRY_HI32, mask_sh),\ + MI_SF(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32, PAGE_DIRECTORY_ENTRY_LO32, mask_sh),\ + MI_SF(VM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32, LOGICAL_PAGE_NUMBER_HI4, mask_sh),\ + MI_SF(VM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32, LOGICAL_PAGE_NUMBER_LO32, mask_sh),\ + MI_SF(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_HI32, PHYSICAL_PAGE_ADDR_HI4, mask_sh),\ + MI_SF(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32, PHYSICAL_PAGE_ADDR_LO32, mask_sh),\ + MI_SF(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, PHYSICAL_PAGE_NUMBER_MSB, mask_sh),\ + MI_SF(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, PHYSICAL_PAGE_NUMBER_LSB, mask_sh),\ + MI_SF(MC_VM_SYSTEM_APERTURE_LOW_ADDR, LOGICAL_ADDR, mask_sh) + +#define DCN_MI_REG_FIELD_LIST(type) \ + type HUBP_BLANK_EN;\ + type HUBP_TTU_DISABLE;\ + type NUM_PIPES;\ + type NUM_BANKS;\ + type PIPE_INTERLEAVE;\ + type NUM_SE;\ + type NUM_RB_PER_SE;\ + type MAX_COMPRESSED_FRAGS;\ + type SW_MODE;\ + type META_LINEAR;\ + type RB_ALIGNED;\ + type PIPE_ALIGNED;\ + type PITCH;\ + type META_PITCH;\ + type PITCH_C;\ + type META_PITCH_C;\ + type ROTATION_ANGLE;\ + type H_MIRROR_EN;\ + type SURFACE_PIXEL_FORMAT;\ + type SURFACE_FLIP_TYPE;\ + type SURFACE_UPDATE_PENDING;\ + type PRIMARY_SURFACE_ADDRESS_HIGH;\ + type PRIMARY_SURFACE_ADDRESS;\ + type SECONDARY_SURFACE_ADDRESS_HIGH;\ + type SECONDARY_SURFACE_ADDRESS;\ + type PRIMARY_META_SURFACE_ADDRESS_HIGH;\ + type PRIMARY_META_SURFACE_ADDRESS;\ + type SECONDARY_META_SURFACE_ADDRESS_HIGH;\ + type SECONDARY_META_SURFACE_ADDRESS;\ + type PRIMARY_SURFACE_ADDRESS_HIGH_C;\ + type PRIMARY_SURFACE_ADDRESS_C;\ + type PRIMARY_META_SURFACE_ADDRESS_HIGH_C;\ + type PRIMARY_META_SURFACE_ADDRESS_C;\ + type PRIMARY_SURFACE_DCC_EN;\ + type PRIMARY_SURFACE_DCC_IND_64B_BLK;\ + type DET_BUF_PLANE1_BASE_ADDRESS;\ + type CROSSBAR_SRC_CB_B;\ + type CROSSBAR_SRC_CR_R;\ + type DRQ_EXPANSION_MODE;\ + type PRQ_EXPANSION_MODE;\ + type MRQ_EXPANSION_MODE;\ + type CRQ_EXPANSION_MODE;\ + type CHUNK_SIZE;\ + type MIN_CHUNK_SIZE;\ + type META_CHUNK_SIZE;\ + type MIN_META_CHUNK_SIZE;\ + type DPTE_GROUP_SIZE;\ + type MPTE_GROUP_SIZE;\ + type SWATH_HEIGHT;\ + type PTE_ROW_HEIGHT_LINEAR;\ + type CHUNK_SIZE_C;\ + type MIN_CHUNK_SIZE_C;\ + type META_CHUNK_SIZE_C;\ + type MIN_META_CHUNK_SIZE_C;\ + type DPTE_GROUP_SIZE_C;\ + type MPTE_GROUP_SIZE_C;\ + type SWATH_HEIGHT_C;\ + type PTE_ROW_HEIGHT_LINEAR_C;\ + type REFCYC_H_BLANK_END;\ + type DLG_V_BLANK_END;\ + type MIN_DST_Y_NEXT_START;\ + type REFCYC_PER_HTOTAL;\ + type REFCYC_X_AFTER_SCALER;\ + type DST_Y_AFTER_SCALER;\ + type DST_Y_PREFETCH;\ + type VRATIO_PREFETCH;\ + type DST_Y_PER_VM_VBLANK;\ + type DST_Y_PER_ROW_VBLANK;\ + type REF_FREQ_TO_PIX_FREQ;\ + type REFCYC_PER_PTE_GROUP_VBLANK_L;\ + type REFCYC_PER_META_CHUNK_VBLANK_L;\ + type DST_Y_PER_PTE_ROW_NOM_L;\ + type REFCYC_PER_PTE_GROUP_NOM_L;\ + type DST_Y_PER_META_ROW_NOM_L;\ + type REFCYC_PER_META_CHUNK_NOM_L;\ + type REFCYC_PER_LINE_DELIVERY_PRE_L;\ + type REFCYC_PER_LINE_DELIVERY_PRE_C;\ + type REFCYC_PER_LINE_DELIVERY_L;\ + type REFCYC_PER_LINE_DELIVERY_C;\ + type VRATIO_PREFETCH_C;\ + type REFCYC_PER_PTE_GROUP_VBLANK_C;\ + type REFCYC_PER_META_CHUNK_VBLANK_C;\ + type DST_Y_PER_PTE_ROW_NOM_C;\ + type REFCYC_PER_PTE_GROUP_NOM_C;\ + type DST_Y_PER_META_ROW_NOM_C;\ + type REFCYC_PER_META_CHUNK_NOM_C;\ + type QoS_LEVEL_LOW_WM;\ + type QoS_LEVEL_HIGH_WM;\ + type MIN_TTU_VBLANK;\ + type QoS_LEVEL_FLIP;\ + type REFCYC_PER_REQ_DELIVERY;\ + type QoS_LEVEL_FIXED;\ + type QoS_RAMP_DISABLE;\ + type REFCYC_PER_REQ_DELIVERY_PRE;\ + type VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB;\ + type VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB;\ + type VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB;\ + type VM_CONTEXT0_PAGE_TABLE_START_ADDR_LSB;\ + type VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB;\ + type VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB;\ + type VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB;\ + type VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB;\ + type ENABLE_L1_TLB;\ + type SYSTEM_ACCESS_MODE;\ + type MC_VM_SYSTEM_APERTURE_DEFAULT_SYSTEM;\ + type MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB;\ + type MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB;\ + type MC_VM_SYSTEM_APERTURE_LOW_ADDR_MSB;\ + type MC_VM_SYSTEM_APERTURE_LOW_ADDR_LSB;\ + type MC_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB;\ + type MC_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB;\ + type SDPIF_FB_TOP;\ + type SDPIF_FB_BASE;\ + type SDPIF_FB_OFFSET;\ + type SDPIF_AGP_BASE;\ + type SDPIF_AGP_BOT;\ + type SDPIF_AGP_TOP;\ + type DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST;\ + type DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE;\ + type DCHUBBUB_ARB_SAT_LEVEL;\ + type DCHUBBUB_ARB_MIN_REQ_OUTSTAND;\ + /* todo: get these from GVM instead of reading registers ourselves */\ + type PAGE_DIRECTORY_ENTRY_HI32;\ + type PAGE_DIRECTORY_ENTRY_LO32;\ + type LOGICAL_PAGE_NUMBER_HI4;\ + type LOGICAL_PAGE_NUMBER_LO32;\ + type PHYSICAL_PAGE_ADDR_HI4;\ + type PHYSICAL_PAGE_ADDR_LO32;\ + type PHYSICAL_PAGE_NUMBER_MSB;\ + type PHYSICAL_PAGE_NUMBER_LSB;\ + type LOGICAL_ADDR + +struct dcn_mi_shift { + DCN_MI_REG_FIELD_LIST(uint8_t); +}; + +struct dcn_mi_mask { + DCN_MI_REG_FIELD_LIST(uint32_t); +}; + +struct dcn10_mem_input { + struct mem_input base; + const struct dcn_mi_registers *mi_regs; + const struct dcn_mi_shift *mi_shift; + const struct dcn_mi_mask *mi_mask; +}; + +bool dcn10_mem_input_construct( + struct dcn10_mem_input *mi, + struct dc_context *ctx, + uint32_t inst, + const struct dcn_mi_registers *mi_regs, + const struct dcn_mi_shift *mi_shift, + const struct dcn_mi_mask *mi_mask); + + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c new file mode 100644 index 000000000000..cb22cd130e1a --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c @@ -0,0 +1,376 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "reg_helper.h" +#include "dcn10_mpc.h" + +#define REG(reg)\ + mpc->mpc_regs->reg + +#define CTX \ + mpc->base.ctx + +#undef FN +#define FN(reg_name, field_name) \ + mpc->mpc_shift->field_name, mpc->mpc_mask->field_name + +/* Internal function to set mpc output mux */ +static void set_output_mux(struct dcn10_mpc *mpc, + uint8_t opp_id, + uint8_t mpcc_id) +{ + if (mpcc_id != 0xf) + REG_UPDATE(OPP_PIPE_CONTROL[opp_id], + OPP_PIPE_CLOCK_EN, 1); + + REG_SET(MUX[opp_id], 0, + MPC_OUT_MUX, mpcc_id); + +/* TODO: Move to post when ready. + if (mpcc_id == 0xf) { + MPCC_REG_UPDATE(OPP_PIPE0_OPP_PIPE_CONTROL, + OPP_PIPE_CLOCK_EN, 0); + } +*/ +} + +static void set_blend_mode(struct dcn10_mpc *mpc, + enum blend_mode mode, + uint8_t mpcc_id) +{ + /* Enable per-pixel alpha on this pipe */ + if (mode == TOP_BLND) + REG_UPDATE_3(MPCC_CONTROL[mpcc_id], + MPCC_ALPHA_BLND_MODE, 0, + MPCC_ALPHA_MULTIPLIED_MODE, 0, + MPCC_BLND_ACTIVE_OVERLAP_ONLY, 0); + else + REG_UPDATE_3(MPCC_CONTROL[mpcc_id], + MPCC_ALPHA_BLND_MODE, 0, + MPCC_ALPHA_MULTIPLIED_MODE, 1, + MPCC_BLND_ACTIVE_OVERLAP_ONLY, 1); +} + +void dcn10_set_mpc_background_color(struct dcn10_mpc *mpc, + unsigned int mpcc_inst, + struct tg_color *bg_color) +{ + /* mpc color is 12 bit. tg_color is 10 bit */ + /* todo: might want to use 16 bit to represent color and have each + * hw block translate to correct color depth. + */ + uint32_t bg_r_cr = bg_color->color_r_cr << 2; + uint32_t bg_g_y = bg_color->color_g_y << 2; + uint32_t bg_b_cb = bg_color->color_b_cb << 2; + + REG_SET(MPCC_BG_R_CR[mpcc_inst], 0, + MPCC_BG_R_CR, bg_r_cr); + REG_SET(MPCC_BG_G_Y[mpcc_inst], 0, + MPCC_BG_G_Y, bg_g_y); + REG_SET(MPCC_BG_B_CB[mpcc_inst], 0, + MPCC_BG_B_CB, bg_b_cb); +} + +/* This function programs MPC tree configuration + * Assume it is the initial time to setup MPC tree_configure, means + * the instance of dpp/mpcc/opp specified in structure tree_cfg are + * in idle status. + * Before invoke this function, ensure that master lock of OPTC specified + * by opp_id is set. + * + * tree_cfg[in] - new MPC_TREE_CFG + */ + +void dcn10_set_mpc_tree(struct dcn10_mpc *mpc, + struct mpc_tree_cfg *tree_cfg) +{ + int i; + + for (i = 0; i < tree_cfg->num_pipes; i++) { + uint8_t mpcc_inst = tree_cfg->mpcc[i]; + + REG_SET(MPCC_OPP_ID[mpcc_inst], 0, + MPCC_OPP_ID, tree_cfg->opp_id); + + REG_SET(MPCC_TOP_SEL[mpcc_inst], 0, + MPCC_TOP_SEL, tree_cfg->dpp[i]); + + if (i == tree_cfg->num_pipes-1) { + REG_SET(MPCC_BOT_SEL[mpcc_inst], 0, + MPCC_BOT_SEL, 0xF); + + /* MPCC_CONTROL->MPCC_MODE */ + REG_UPDATE(MPCC_CONTROL[mpcc_inst], + MPCC_MODE, tree_cfg->mode); + } else { + REG_SET(MPCC_BOT_SEL[mpcc_inst], 0, + MPCC_BOT_SEL, tree_cfg->dpp[i+1]); + + /* MPCC_CONTROL->MPCC_MODE */ + REG_UPDATE(MPCC_CONTROL[mpcc_inst], + MPCC_MODE, 3); + } + + if (i == 0) + set_output_mux( + mpc, tree_cfg->opp_id, mpcc_inst); + + set_blend_mode(mpc, tree_cfg->mode, mpcc_inst); + } +} + +void dcn10_set_mpc_passthrough(struct dcn10_mpc *mpc, + uint8_t dpp_idx, + uint8_t mpcc_idx, + uint8_t opp_idx) +{ + struct mpc_tree_cfg tree_cfg = { 0 }; + + tree_cfg.num_pipes = 1; + tree_cfg.opp_id = opp_idx; + tree_cfg.mode = TOP_PASSTHRU; + /* TODO: FPGA bring up one MPC has only 1 DPP and 1 MPCC + * For blend case, need fill mode DPP and cascade MPCC + */ + tree_cfg.dpp[0] = dpp_idx; + tree_cfg.mpcc[0] = mpcc_idx; + dcn10_set_mpc_tree(mpc, &tree_cfg); +} + +/* + * This is the function to remove current MPC tree specified by tree_cfg + * Before invoke this function, ensure that master lock of OPTC specified + * by opp_id is set. + * + *tree_cfg[in/out] - current MPC_TREE_CFG + */ +void dcn10_delete_mpc_tree(struct dcn10_mpc *mpc, + struct mpc_tree_cfg *tree_cfg) +{ + int i; + + for (i = 0; i < tree_cfg->num_pipes; i++) { + uint8_t mpcc_inst = tree_cfg->mpcc[i]; + + REG_SET(MPCC_OPP_ID[mpcc_inst], 0, + MPCC_OPP_ID, 0xf); + + REG_SET(MPCC_TOP_SEL[mpcc_inst], 0, + MPCC_TOP_SEL, 0xf); + + REG_SET(MPCC_BOT_SEL[mpcc_inst], 0, + MPCC_BOT_SEL, 0xF); + + /* add remove dpp/mpcc pair into pending list + * TODO FPGA AddToPendingList if empty from pseudo code + */ + tree_cfg->dpp[i] = 0xf; + tree_cfg->mpcc[i] = 0xf; + } + set_output_mux(mpc, tree_cfg->opp_id, 0xf); + tree_cfg->opp_id = 0xf; + tree_cfg->num_pipes = 0; +} + +/* TODO FPGA: how to handle DPP? + * Function to remove one of pipe from MPC configure tree by dpp idx + * Before invoke this function, ensure that master lock of OPTC specified + * by opp_id is set + * This function can be invoke multiple times to remove more than 1 dpps. + * + * tree_cfg[in/out] - current MPC_TREE_CFG + * idx[in] - index of dpp from tree_cfg to be removed. + */ +bool dcn10_remove_dpp(struct dcn10_mpc *mpc, + struct mpc_tree_cfg *tree_cfg, + uint8_t idx) +{ + int i; + bool found = false; + + /* find dpp_idx from dpp array of tree_cfg */ + for (i = 0; i < tree_cfg->num_pipes; i++) { + if (tree_cfg->dpp[i] == idx) { + found = true; + break; + } + } + + if (found) { + /* add remove dpp/mpcc pair into pending list */ + + /* TODO FPGA AddToPendingList if empty from pseudo code + * AddToPendingList(tree_cfg->dpp[i],tree_cfg->mpcc[i]); + */ + uint8_t mpcc_inst = tree_cfg->mpcc[i]; + + REG_SET(MPCC_OPP_ID[mpcc_inst], 0, + MPCC_OPP_ID, 0xf); + + REG_SET(MPCC_TOP_SEL[mpcc_inst], 0, + MPCC_TOP_SEL, 0xf); + + REG_SET(MPCC_BOT_SEL[mpcc_inst], 0, + MPCC_BOT_SEL, 0xF); + + if (i == 0) { + if (tree_cfg->num_pipes > 1) + set_output_mux(mpc, + tree_cfg->opp_id, tree_cfg->mpcc[i+1]); + else + set_output_mux(mpc, tree_cfg->opp_id, 0xf); + } else if (i == tree_cfg->num_pipes-1) { + mpcc_inst = tree_cfg->mpcc[i - 1]; + + REG_SET(MPCC_BOT_SEL[mpcc_inst], 0, + MPCC_BOT_SEL, 0xF); + + REG_UPDATE(MPCC_CONTROL[mpcc_inst], + MPCC_MODE, tree_cfg->mode); + } else { + mpcc_inst = tree_cfg->mpcc[i - 1]; + + REG_SET(MPCC_BOT_SEL[mpcc_inst], 0, + MPCC_BOT_SEL, tree_cfg->mpcc[i+1]); + } + set_blend_mode(mpc, tree_cfg->mode, mpcc_inst); + + /* update tree_cfg structure */ + while (i < tree_cfg->num_pipes - 1) { + tree_cfg->dpp[i] = tree_cfg->dpp[i+1]; + tree_cfg->mpcc[i] = tree_cfg->mpcc[i+1]; + i++; + } + tree_cfg->num_pipes--; + } + return found; +} + +/* TODO FPGA: how to handle DPP? + * Function to add DPP/MPCC pair into MPC configure tree by position. + * Before invoke this function, ensure that master lock of OPTC specified + * by opp_id is set + * This function can be invoke multiple times to add more than 1 pipes. + * + * tree_cfg[in/out] - current MPC_TREE_CFG + * dpp_idx[in] - index of an idle dpp insatnce to be added. + * mpcc_idx[in] - index of an idle mpcc instance to be added. + * poistion[in] - position of dpp/mpcc pair to be added into current tree_cfg + * 0 means insert to the most top layer of MPC tree + */ +void dcn10_add_dpp(struct dcn10_mpc *mpc, + struct mpc_tree_cfg *tree_cfg, + uint8_t dpp_idx, + uint8_t mpcc_idx, + uint8_t position) +{ + uint8_t temp; + uint8_t temp1; + + REG_SET(MPCC_OPP_ID[mpcc_idx], 0, + MPCC_OPP_ID, tree_cfg->opp_id); + + REG_SET(MPCC_TOP_SEL[mpcc_idx], 0, + MPCC_TOP_SEL, dpp_idx); + + if (position == 0) { + /* idle dpp/mpcc is added to the top layer of tree */ + REG_SET(MPCC_BOT_SEL[mpcc_idx], 0, + MPCC_BOT_SEL, tree_cfg->mpcc[0]); + REG_UPDATE(MPCC_CONTROL[mpcc_idx], + MPCC_MODE, 3); + + /* opp will get new output. from new added mpcc */ + set_output_mux(mpc, tree_cfg->opp_id, mpcc_idx); + + set_blend_mode(mpc, tree_cfg->mode, mpcc_idx); + + } else if (position == tree_cfg->num_pipes) { + /* idle dpp/mpcc is added to the bottom layer of tree */ + + /* get instance of previous bottom mpcc, set to middle layer */ + temp = tree_cfg->mpcc[tree_cfg->num_pipes - 1]; + + REG_SET(MPCC_BOT_SEL[temp], 0, + MPCC_BOT_SEL, mpcc_idx); + + REG_UPDATE(MPCC_CONTROL[temp], + MPCC_MODE, 3); + + /* mpcc_idx become new bottom mpcc*/ + REG_SET(MPCC_BOT_SEL[mpcc_idx], 0, + MPCC_BOT_SEL, 0xf); + + REG_UPDATE(MPCC_CONTROL[mpcc_idx], + MPCC_MODE, tree_cfg->mode); + + set_blend_mode(mpc, tree_cfg->mode, mpcc_idx); + } else { + /* idle dpp/mpcc is added to middle of tree */ + temp = tree_cfg->mpcc[position - 1]; + temp1 = tree_cfg->mpcc[position]; + + /* new mpcc instance temp1 is added right after temp*/ + REG_SET(MPCC_BOT_SEL[temp], 0, + MPCC_BOT_SEL, mpcc_idx); + + /* mpcc_idx connect previous temp+1 to new mpcc */ + REG_SET(MPCC_BOT_SEL[mpcc_idx], 0, + MPCC_BOT_SEL, temp1); + + /* temp TODO: may not need*/ + REG_UPDATE(MPCC_CONTROL[temp], + MPCC_MODE, 3); + + set_blend_mode(mpc, tree_cfg->mode, temp); + } + + /* update tree_cfg structure */ + temp = tree_cfg->num_pipes - 1; + + /* + * iterating from the last mpc/dpp pair to the one being added, shift + * them down one position + */ + while (temp > position) { + tree_cfg->dpp[temp + 1] = tree_cfg->dpp[temp]; + tree_cfg->mpcc[temp + 1] = tree_cfg->mpcc[temp]; + temp--; + } + + /* insert the new mpc/dpp pair into the tree_cfg*/ + tree_cfg->dpp[position] = dpp_idx; + tree_cfg->mpcc[position] = mpcc_idx; + tree_cfg->num_pipes++; +} + +void wait_mpcc_idle(struct dcn10_mpc *mpc, + uint8_t mpcc_id) +{ + REG_WAIT(MPCC_STATUS[mpcc_id], + MPCC_IDLE, 1, + 1000, 1000); +} + diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h new file mode 100644 index 000000000000..6550b93c9254 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h @@ -0,0 +1,135 @@ +/* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_MPC_DCN10_H__ +#define __DC_MPC_DCN10_H__ + +#include "mpc.h" + +#define TO_DCN10_MPC(mpc_base)\ + container_of(mpc_base, struct dcn10_mpc, base) + +#define MAX_MPCC 4 +#define MAX_MPC_OUT 4 +#define MAX_OPP 4 + +#define MPC_COMMON_REG_LIST_DCN1_0(inst) \ + SRII(MPCC_TOP_SEL, MPCC, inst),\ + SRII(MPCC_BOT_SEL, MPCC, inst),\ + SRII(MPCC_CONTROL, MPCC, inst),\ + SRII(MPCC_STATUS, MPCC, inst),\ + SRII(MPCC_OPP_ID, MPCC, inst),\ + SRII(MPCC_BG_G_Y, MPCC, inst),\ + SRII(MPCC_BG_R_CR, MPCC, inst),\ + SRII(MPCC_BG_B_CB, MPCC, inst),\ + SRII(MPCC_BG_B_CB, MPCC, inst),\ + SRII(MUX, MPC_OUT, inst),\ + SRII(OPP_PIPE_CONTROL, OPP_PIPE, inst) + +struct dcn_mpc_registers { + uint32_t MPCC_TOP_SEL[MAX_MPCC]; + uint32_t MPCC_BOT_SEL[MAX_MPCC]; + uint32_t MPCC_CONTROL[MAX_MPCC]; + uint32_t MPCC_STATUS[MAX_MPCC]; + uint32_t MPCC_OPP_ID[MAX_MPCC]; + uint32_t MPCC_BG_G_Y[MAX_MPCC]; + uint32_t MPCC_BG_R_CR[MAX_MPCC]; + uint32_t MPCC_BG_B_CB[MAX_MPCC]; + uint32_t MUX[MAX_MPC_OUT]; + uint32_t OPP_PIPE_CONTROL[MAX_OPP]; +}; + +#define MPC_COMMON_MASK_SH_LIST_DCN1_0(mask_sh)\ + SF(MPCC0_MPCC_TOP_SEL, MPCC_TOP_SEL, mask_sh),\ + SF(MPCC0_MPCC_BOT_SEL, MPCC_BOT_SEL, mask_sh),\ + SF(MPCC0_MPCC_CONTROL, MPCC_MODE, mask_sh),\ + SF(MPCC0_MPCC_CONTROL, MPCC_ALPHA_BLND_MODE, mask_sh),\ + SF(MPCC0_MPCC_CONTROL, MPCC_ALPHA_MULTIPLIED_MODE, mask_sh),\ + SF(MPCC0_MPCC_CONTROL, MPCC_BLND_ACTIVE_OVERLAP_ONLY, mask_sh),\ + SF(MPCC0_MPCC_STATUS, MPCC_IDLE, mask_sh),\ + SF(MPCC0_MPCC_OPP_ID, MPCC_OPP_ID, mask_sh),\ + SF(MPCC0_MPCC_BG_G_Y, MPCC_BG_G_Y, mask_sh),\ + SF(MPCC0_MPCC_BG_R_CR, MPCC_BG_R_CR, mask_sh),\ + SF(MPCC0_MPCC_BG_B_CB, MPCC_BG_B_CB, mask_sh),\ + SF(MPC_OUT0_MUX, MPC_OUT_MUX, mask_sh),\ + SF(OPP_PIPE0_OPP_PIPE_CONTROL, OPP_PIPE_CLOCK_EN, mask_sh) + +#define MPC_REG_FIELD_LIST(type) \ + type MPCC_TOP_SEL;\ + type MPCC_BOT_SEL;\ + type MPCC_MODE;\ + type MPCC_ALPHA_BLND_MODE;\ + type MPCC_ALPHA_MULTIPLIED_MODE;\ + type MPCC_BLND_ACTIVE_OVERLAP_ONLY;\ + type MPCC_IDLE;\ + type MPCC_OPP_ID;\ + type MPCC_BG_G_Y;\ + type MPCC_BG_R_CR;\ + type MPCC_BG_B_CB;\ + type MPC_OUT_MUX;\ + type OPP_PIPE_CLOCK_EN;\ + +struct dcn_mpc_shift { + MPC_REG_FIELD_LIST(uint8_t) +}; + +struct dcn_mpc_mask { + MPC_REG_FIELD_LIST(uint32_t) +}; + +struct dcn10_mpc { + struct mpc base; + const struct dcn_mpc_registers *mpc_regs; + const struct dcn_mpc_shift *mpc_shift; + const struct dcn_mpc_mask *mpc_mask; +}; + +void dcn10_set_mpc_passthrough(struct dcn10_mpc *mpc, + uint8_t dpp_idx, + uint8_t mpcc_idx, + uint8_t opp_idx); + +void dcn10_delete_mpc_tree(struct dcn10_mpc *mpc, + struct mpc_tree_cfg *tree_cfg); + +bool dcn10_remove_dpp(struct dcn10_mpc *mpc, + struct mpc_tree_cfg *tree_cfg, + uint8_t idx); + +void dcn10_add_dpp(struct dcn10_mpc *mpc, + struct mpc_tree_cfg *tree_cfg, + uint8_t dpp_idx, + uint8_t mpcc_idx, + uint8_t position); + +void wait_mpcc_idle(struct dcn10_mpc *mpc, + uint8_t mpcc_id); + +void dcn10_set_mpc_tree(struct dcn10_mpc *mpc, + struct mpc_tree_cfg *tree_cfg); + +void dcn10_set_mpc_background_color(struct dcn10_mpc *mpc, + unsigned int mpcc_inst, + struct tg_color *bg_color); +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c new file mode 100644 index 000000000000..fce08e5235e6 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c @@ -0,0 +1,801 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "dcn10_opp.h" +#include "reg_helper.h" + +#define REG(reg) \ + (oppn10->regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + oppn10->opp_shift->field_name, oppn10->opp_mask->field_name + +#define CTX \ + oppn10->base.ctx + +static void opp_set_regamma_mode( + struct output_pixel_processor *opp, + enum opp_regamma mode) +{ + struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); + uint32_t re_mode = 0; + uint32_t obuf_bypass = 0; /* need for pipe split */ + uint32_t obuf_hupscale = 0; + + switch (mode) { + case OPP_REGAMMA_BYPASS: + re_mode = 0; + break; + case OPP_REGAMMA_SRGB: + re_mode = 1; + break; + case OPP_REGAMMA_3_6: + re_mode = 2; + break; + case OPP_REGAMMA_USER: + re_mode = oppn10->is_write_to_ram_a_safe ? 3 : 4; + oppn10->is_write_to_ram_a_safe = !oppn10->is_write_to_ram_a_safe; + break; + default: + break; + } + + REG_SET(CM_RGAM_CONTROL, 0, CM_RGAM_LUT_MODE, re_mode); + REG_UPDATE_2(OBUF_CONTROL, + OBUF_BYPASS, obuf_bypass, + OBUF_H_2X_UPSCALE_EN, obuf_hupscale); +} + +/************* FORMATTER ************/ + +/** + * set_truncation + * 1) set truncation depth: 0 for 18 bpp or 1 for 24 bpp + * 2) enable truncation + * 3) HW remove 12bit FMT support for DCE11 power saving reason. + */ +static void set_truncation( + struct dcn10_opp *oppn10, + const struct bit_depth_reduction_params *params) +{ + REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, + FMT_TRUNCATE_EN, params->flags.TRUNCATE_ENABLED, + FMT_TRUNCATE_DEPTH, params->flags.TRUNCATE_DEPTH, + FMT_TRUNCATE_MODE, params->flags.TRUNCATE_MODE); +} + +static void set_spatial_dither( + struct dcn10_opp *oppn10, + const struct bit_depth_reduction_params *params) +{ + /*Disable spatial (random) dithering*/ + REG_UPDATE_7(FMT_BIT_DEPTH_CONTROL, + FMT_SPATIAL_DITHER_EN, 0, + FMT_SPATIAL_DITHER_MODE, 0, + FMT_SPATIAL_DITHER_DEPTH, 0, + FMT_TEMPORAL_DITHER_EN, 0, + FMT_HIGHPASS_RANDOM_ENABLE, 0, + FMT_FRAME_RANDOM_ENABLE, 0, + FMT_RGB_RANDOM_ENABLE, 0); + + + /* only use FRAME_COUNTER_MAX if frameRandom == 1*/ + if (params->flags.FRAME_RANDOM == 1) { + if (params->flags.SPATIAL_DITHER_DEPTH == 0 || params->flags.SPATIAL_DITHER_DEPTH == 1) { + REG_UPDATE_2(FMT_CONTROL, + FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 15, + FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 2); + } else if (params->flags.SPATIAL_DITHER_DEPTH == 2) { + REG_UPDATE_2(FMT_CONTROL, + FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 3, + FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 1); + } else { + return; + } + } else { + REG_UPDATE_2(FMT_CONTROL, + FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 0, + FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 0); + } + + /*Set seed for random values for + * spatial dithering for R,G,B channels*/ + + REG_SET(FMT_DITHER_RAND_R_SEED, 0, + FMT_RAND_R_SEED, params->r_seed_value); + + REG_SET(FMT_DITHER_RAND_G_SEED, 0, + FMT_RAND_G_SEED, params->g_seed_value); + + REG_SET(FMT_DITHER_RAND_B_SEED, 0, + FMT_RAND_B_SEED, params->b_seed_value); + + /* FMT_OFFSET_R_Cr 31:16 0x0 Setting the zero + * offset for the R/Cr channel, lower 4LSB + * is forced to zeros. Typically set to 0 + * RGB and 0x80000 YCbCr. + */ + /* FMT_OFFSET_G_Y 31:16 0x0 Setting the zero + * offset for the G/Y channel, lower 4LSB is + * forced to zeros. Typically set to 0 RGB + * and 0x80000 YCbCr. + */ + /* FMT_OFFSET_B_Cb 31:16 0x0 Setting the zero + * offset for the B/Cb channel, lower 4LSB is + * forced to zeros. Typically set to 0 RGB and + * 0x80000 YCbCr. + */ + + REG_UPDATE_6(FMT_BIT_DEPTH_CONTROL, + /*Enable spatial dithering*/ + FMT_SPATIAL_DITHER_EN, params->flags.SPATIAL_DITHER_ENABLED, + /* Set spatial dithering mode + * (default is Seed patterrn AAAA...) + */ + FMT_SPATIAL_DITHER_MODE, params->flags.SPATIAL_DITHER_MODE, + /*Set spatial dithering bit depth*/ + FMT_SPATIAL_DITHER_DEPTH, params->flags.SPATIAL_DITHER_DEPTH, + /*Disable High pass filter*/ + FMT_HIGHPASS_RANDOM_ENABLE, params->flags.HIGHPASS_RANDOM, + /*Reset only at startup*/ + FMT_FRAME_RANDOM_ENABLE, params->flags.FRAME_RANDOM, + /*Set RGB data dithered with x^28+x^3+1*/ + FMT_RGB_RANDOM_ENABLE, params->flags.RGB_RANDOM); +} + +static void opp_program_bit_depth_reduction( + struct output_pixel_processor *opp, + const struct bit_depth_reduction_params *params) +{ + struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); + + set_truncation(oppn10, params); + set_spatial_dither(oppn10, params); + /* TODO + * set_temporal_dither(oppn10, params); + */ +} + +/** + * set_pixel_encoding + * + * Set Pixel Encoding + * 0: RGB 4:4:4 or YCbCr 4:4:4 or YOnly + * 1: YCbCr 4:2:2 + */ +static void set_pixel_encoding( + struct dcn10_opp *oppn10, + const struct clamping_and_pixel_encoding_params *params) +{ + switch (params->pixel_encoding) { + + case PIXEL_ENCODING_RGB: + case PIXEL_ENCODING_YCBCR444: + REG_UPDATE(FMT_CONTROL, FMT_PIXEL_ENCODING, 0); + break; + case PIXEL_ENCODING_YCBCR422: + REG_UPDATE(FMT_CONTROL, FMT_PIXEL_ENCODING, 1); + break; + case PIXEL_ENCODING_YCBCR420: + REG_UPDATE(FMT_CONTROL, FMT_PIXEL_ENCODING, 2); + break; + default: + break; + } +} + +/** + * Set Clamping + * 1) Set clamping format based on bpc - 0 for 6bpc (No clamping) + * 1 for 8 bpc + * 2 for 10 bpc + * 3 for 12 bpc + * 7 for programable + * 2) Enable clamp if Limited range requested + */ +static void opp_set_clamping( + struct dcn10_opp *oppn10, + const struct clamping_and_pixel_encoding_params *params) +{ + REG_UPDATE_2(FMT_CLAMP_CNTL, + FMT_CLAMP_DATA_EN, 0, + FMT_CLAMP_COLOR_FORMAT, 0); + + switch (params->clamping_level) { + case CLAMPING_FULL_RANGE: + REG_UPDATE_2(FMT_CLAMP_CNTL, + FMT_CLAMP_DATA_EN, 1, + FMT_CLAMP_COLOR_FORMAT, 0); + break; + case CLAMPING_LIMITED_RANGE_8BPC: + REG_UPDATE_2(FMT_CLAMP_CNTL, + FMT_CLAMP_DATA_EN, 1, + FMT_CLAMP_COLOR_FORMAT, 1); + break; + case CLAMPING_LIMITED_RANGE_10BPC: + REG_UPDATE_2(FMT_CLAMP_CNTL, + FMT_CLAMP_DATA_EN, 1, + FMT_CLAMP_COLOR_FORMAT, 2); + + break; + case CLAMPING_LIMITED_RANGE_12BPC: + REG_UPDATE_2(FMT_CLAMP_CNTL, + FMT_CLAMP_DATA_EN, 1, + FMT_CLAMP_COLOR_FORMAT, 3); + break; + case CLAMPING_LIMITED_RANGE_PROGRAMMABLE: + /* TODO */ + default: + break; + } + +} + +static void opp_set_dyn_expansion( + struct output_pixel_processor *opp, + enum dc_color_space color_sp, + enum dc_color_depth color_dpth, + enum signal_type signal) +{ + struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); + + REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL, + FMT_DYNAMIC_EXP_EN, 0, + FMT_DYNAMIC_EXP_MODE, 0); + + /*00 - 10-bit -> 12-bit dynamic expansion*/ + /*01 - 8-bit -> 12-bit dynamic expansion*/ + if (signal == SIGNAL_TYPE_HDMI_TYPE_A || + signal == SIGNAL_TYPE_DISPLAY_PORT || + signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { + switch (color_dpth) { + case COLOR_DEPTH_888: + REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL, + FMT_DYNAMIC_EXP_EN, 1, + FMT_DYNAMIC_EXP_MODE, 1); + break; + case COLOR_DEPTH_101010: + REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL, + FMT_DYNAMIC_EXP_EN, 1, + FMT_DYNAMIC_EXP_MODE, 0); + break; + case COLOR_DEPTH_121212: + REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL, + FMT_DYNAMIC_EXP_EN, 1,/*otherwise last two bits are zero*/ + FMT_DYNAMIC_EXP_MODE, 0); + break; + default: + break; + } + } +} + +static void opp_program_clamping_and_pixel_encoding( + struct output_pixel_processor *opp, + const struct clamping_and_pixel_encoding_params *params) +{ + struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); + + opp_set_clamping(oppn10, params); + set_pixel_encoding(oppn10, params); +} + +static void opp_program_fmt( + struct output_pixel_processor *opp, + struct bit_depth_reduction_params *fmt_bit_depth, + struct clamping_and_pixel_encoding_params *clamping) +{ + struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); + + if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420) + REG_UPDATE(FMT_MAP420_MEMORY_CONTROL, FMT_MAP420MEM_PWR_FORCE, 0); + + /* dithering is affected by , hence should be + * programmed afterwards */ + opp_program_bit_depth_reduction( + opp, + fmt_bit_depth); + + opp_program_clamping_and_pixel_encoding( + opp, + clamping); + + return; +} + +static void opp_set_output_csc_default( + struct output_pixel_processor *opp, + const struct default_adjustment *default_adjust) +{ + + struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); + uint32_t ocsc_mode = 0; + + if (default_adjust != NULL) { + switch (default_adjust->out_color_space) { + case COLOR_SPACE_SRGB: + ocsc_mode = 0; + break; + case COLOR_SPACE_SRGB_LIMITED: + ocsc_mode = 1; + break; + case COLOR_SPACE_YCBCR601: + case COLOR_SPACE_YCBCR601_LIMITED: + ocsc_mode = 2; + break; + case COLOR_SPACE_YCBCR709: + case COLOR_SPACE_YCBCR709_LIMITED: + ocsc_mode = 3; + break; + case COLOR_SPACE_UNKNOWN: + default: + break; + } + } + + REG_SET(CM_OCSC_CONTROL, 0, CM_OCSC_MODE, ocsc_mode); + +} +/*program re gamma RAM B*/ +static void opp_program_regamma_lutb_settings( + struct output_pixel_processor *opp, + const struct pwl_params *params) +{ + const struct gamma_curve *curve; + struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); + + REG_SET_2(CM_RGAM_RAMB_START_CNTL_B, 0, + CM_RGAM_RAMB_EXP_REGION_START_B, params->arr_points[0].custom_float_x, + CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B, 0); + REG_SET_2(CM_RGAM_RAMB_START_CNTL_G, 0, + CM_RGAM_RAMB_EXP_REGION_START_G, params->arr_points[0].custom_float_x, + CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_G, 0); + REG_SET_2(CM_RGAM_RAMB_START_CNTL_R, 0, + CM_RGAM_RAMB_EXP_REGION_START_R, params->arr_points[0].custom_float_x, + CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_R, 0); + + REG_SET(CM_RGAM_RAMB_SLOPE_CNTL_B, 0, + CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B, params->arr_points[0].custom_float_slope); + REG_SET(CM_RGAM_RAMB_SLOPE_CNTL_G, 0, + CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_G, params->arr_points[0].custom_float_slope); + REG_SET(CM_RGAM_RAMB_SLOPE_CNTL_R, 0, + CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_R, params->arr_points[0].custom_float_slope); + + REG_SET(CM_RGAM_RAMB_END_CNTL1_B, 0, + CM_RGAM_RAMB_EXP_REGION_END_B, params->arr_points[1].custom_float_x); + REG_SET_2(CM_RGAM_RAMB_END_CNTL2_B, 0, + CM_RGAM_RAMB_EXP_REGION_END_SLOPE_B, params->arr_points[1].custom_float_slope, + CM_RGAM_RAMB_EXP_REGION_END_BASE_B, params->arr_points[1].custom_float_y); + + REG_SET(CM_RGAM_RAMB_END_CNTL1_G, 0, + CM_RGAM_RAMB_EXP_REGION_END_G, params->arr_points[1].custom_float_x); + REG_SET_2(CM_RGAM_RAMB_END_CNTL2_G, 0, + CM_RGAM_RAMB_EXP_REGION_END_SLOPE_G, params->arr_points[1].custom_float_slope, + CM_RGAM_RAMB_EXP_REGION_END_BASE_G, params->arr_points[1].custom_float_y); + + REG_SET(CM_RGAM_RAMB_END_CNTL1_R, 0, + CM_RGAM_RAMB_EXP_REGION_END_R, params->arr_points[1].custom_float_x); + REG_SET_2(CM_RGAM_RAMB_END_CNTL2_R, 0, + CM_RGAM_RAMB_EXP_REGION_END_SLOPE_R, params->arr_points[1].custom_float_slope, + CM_RGAM_RAMB_EXP_REGION_END_BASE_R, params->arr_points[1].custom_float_y); + + curve = params->arr_curve_points; + REG_SET_4(CM_RGAM_RAMB_REGION_0_1, 0, + CM_RGAM_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_2_3, 0, + CM_RGAM_RAMB_EXP_REGION2_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION3_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_4_5, 0, + CM_RGAM_RAMB_EXP_REGION4_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION5_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_6_7, 0, + CM_RGAM_RAMB_EXP_REGION6_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION7_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_8_9, 0, + CM_RGAM_RAMB_EXP_REGION8_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION9_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_10_11, 0, + CM_RGAM_RAMB_EXP_REGION10_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION11_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_12_13, 0, + CM_RGAM_RAMB_EXP_REGION12_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION13_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_14_15, 0, + CM_RGAM_RAMB_EXP_REGION14_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION15_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_16_17, 0, + CM_RGAM_RAMB_EXP_REGION16_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION16_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION17_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION17_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_18_19, 0, + CM_RGAM_RAMB_EXP_REGION18_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION18_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION19_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION19_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_20_21, 0, + CM_RGAM_RAMB_EXP_REGION20_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION20_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION21_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION21_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_22_23, 0, + CM_RGAM_RAMB_EXP_REGION22_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION22_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION23_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION23_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_24_25, 0, + CM_RGAM_RAMB_EXP_REGION24_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION24_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION25_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION25_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_26_27, 0, + CM_RGAM_RAMB_EXP_REGION26_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION26_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION27_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION27_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_28_29, 0, + CM_RGAM_RAMB_EXP_REGION28_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION28_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION29_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION29_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_30_31, 0, + CM_RGAM_RAMB_EXP_REGION30_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION30_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION31_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION31_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_32_33, 0, + CM_RGAM_RAMB_EXP_REGION32_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION32_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION33_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION33_NUM_SEGMENTS, curve[1].segments_num); + +} + +/*program re gamma RAM A*/ +static void opp_program_regamma_luta_settings( + struct output_pixel_processor *opp, + const struct pwl_params *params) +{ + const struct gamma_curve *curve; + struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); + + REG_SET_2(CM_RGAM_RAMA_START_CNTL_B, 0, + CM_RGAM_RAMA_EXP_REGION_START_B, params->arr_points[0].custom_float_x, + CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_B, 0); + REG_SET_2(CM_RGAM_RAMA_START_CNTL_G, 0, + CM_RGAM_RAMA_EXP_REGION_START_G, params->arr_points[0].custom_float_x, + CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_G, 0); + REG_SET_2(CM_RGAM_RAMA_START_CNTL_R, 0, + CM_RGAM_RAMA_EXP_REGION_START_R, params->arr_points[0].custom_float_x, + CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_R, 0); + + REG_SET(CM_RGAM_RAMA_SLOPE_CNTL_B, 0, + CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B, params->arr_points[0].custom_float_slope); + REG_SET(CM_RGAM_RAMA_SLOPE_CNTL_G, 0, + CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G, params->arr_points[0].custom_float_slope); + REG_SET(CM_RGAM_RAMA_SLOPE_CNTL_R, 0, + CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R, params->arr_points[0].custom_float_slope); + + REG_SET(CM_RGAM_RAMA_END_CNTL1_B, 0, + CM_RGAM_RAMA_EXP_REGION_END_B, params->arr_points[1].custom_float_x); + REG_SET_2(CM_RGAM_RAMA_END_CNTL2_B, 0, + CM_RGAM_RAMA_EXP_REGION_END_SLOPE_B, params->arr_points[1].custom_float_slope, + CM_RGAM_RAMA_EXP_REGION_END_BASE_B, params->arr_points[1].custom_float_y); + + REG_SET(CM_RGAM_RAMA_END_CNTL1_G, 0, + CM_RGAM_RAMA_EXP_REGION_END_G, params->arr_points[1].custom_float_x); + REG_SET_2(CM_RGAM_RAMA_END_CNTL2_G, 0, + CM_RGAM_RAMA_EXP_REGION_END_SLOPE_G, params->arr_points[1].custom_float_slope, + CM_RGAM_RAMA_EXP_REGION_END_BASE_G, params->arr_points[1].custom_float_y); + + REG_SET(CM_RGAM_RAMA_END_CNTL1_R, 0, + CM_RGAM_RAMA_EXP_REGION_END_R, params->arr_points[1].custom_float_x); + REG_SET_2(CM_RGAM_RAMA_END_CNTL2_R, 0, + CM_RGAM_RAMA_EXP_REGION_END_SLOPE_R, params->arr_points[1].custom_float_slope, + CM_RGAM_RAMA_EXP_REGION_END_BASE_R, params->arr_points[1].custom_float_y); + + curve = params->arr_curve_points; + REG_SET_4(CM_RGAM_RAMA_REGION_0_1, 0, + CM_RGAM_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_2_3, 0, + CM_RGAM_RAMA_EXP_REGION2_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION3_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_4_5, 0, + CM_RGAM_RAMA_EXP_REGION4_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION5_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_6_7, 0, + CM_RGAM_RAMA_EXP_REGION6_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION7_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_8_9, 0, + CM_RGAM_RAMA_EXP_REGION8_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION9_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_10_11, 0, + CM_RGAM_RAMA_EXP_REGION10_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION11_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_12_13, 0, + CM_RGAM_RAMA_EXP_REGION12_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION13_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_14_15, 0, + CM_RGAM_RAMA_EXP_REGION14_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION15_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_16_17, 0, + CM_RGAM_RAMA_EXP_REGION16_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION16_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION17_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION17_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_18_19, 0, + CM_RGAM_RAMA_EXP_REGION18_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION18_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION19_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION19_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_20_21, 0, + CM_RGAM_RAMA_EXP_REGION20_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION20_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION21_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION21_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_22_23, 0, + CM_RGAM_RAMA_EXP_REGION22_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION22_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION23_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION23_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_24_25, 0, + CM_RGAM_RAMA_EXP_REGION24_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION24_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION25_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION25_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_26_27, 0, + CM_RGAM_RAMA_EXP_REGION26_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION26_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION27_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION27_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_28_29, 0, + CM_RGAM_RAMA_EXP_REGION28_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION28_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION29_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION29_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_30_31, 0, + CM_RGAM_RAMA_EXP_REGION30_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION30_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION31_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION31_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_32_33, 0, + CM_RGAM_RAMA_EXP_REGION32_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION32_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION33_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION33_NUM_SEGMENTS, curve[1].segments_num); +} + +static void opp_configure_regamma_lut( + struct output_pixel_processor *opp, + bool is_ram_a) +{ + struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); + + REG_UPDATE(CM_RGAM_LUT_WRITE_EN_MASK, + CM_RGAM_LUT_WRITE_EN_MASK, 7); + REG_UPDATE(CM_RGAM_LUT_WRITE_EN_MASK, + CM_RGAM_LUT_WRITE_SEL, is_ram_a == true ? 0:1); + REG_SET(CM_RGAM_LUT_INDEX, 0, CM_RGAM_LUT_INDEX, 0); +} + +static void opp_power_on_regamma_lut( + struct output_pixel_processor *opp, + bool power_on) +{ + struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); + REG_SET(CM_MEM_PWR_CTRL, 0, + RGAM_MEM_PWR_FORCE, power_on == true ? 0:1); + +} + +static void opp_program_regamma_lut( + struct output_pixel_processor *opp, + const struct pwl_result_data *rgb, + uint32_t num) +{ + uint32_t i; + struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); + for (i = 0 ; i < num; i++) { + REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].red_reg); + REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].green_reg); + REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].blue_reg); + + REG_SET(CM_RGAM_LUT_DATA, 0, + CM_RGAM_LUT_DATA, rgb[i].delta_red_reg); + REG_SET(CM_RGAM_LUT_DATA, 0, + CM_RGAM_LUT_DATA, rgb[i].delta_green_reg); + REG_SET(CM_RGAM_LUT_DATA, 0, + CM_RGAM_LUT_DATA, rgb[i].delta_blue_reg); + + } + +} + +static bool opp_set_regamma_pwl( + struct output_pixel_processor *opp, const struct pwl_params *params) +{ + struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); + + opp_power_on_regamma_lut(opp, true); + opp_configure_regamma_lut(opp, oppn10->is_write_to_ram_a_safe); + + if (oppn10->is_write_to_ram_a_safe) + opp_program_regamma_luta_settings(opp, params); + else + opp_program_regamma_lutb_settings(opp, params); + + opp_program_regamma_lut( + opp, params->rgb_resulted, params->hw_points_num); + + return true; +} + +static void opp_set_stereo_polarity( + struct output_pixel_processor *opp, + bool enable, bool rightEyePolarity) +{ + struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); + + REG_UPDATE(FMT_CONTROL, FMT_STEREOSYNC_OVERRIDE, enable); +} + +/*****************************************/ +/* Constructor, Destructor */ +/*****************************************/ + +static void dcn10_opp_destroy(struct output_pixel_processor **opp) +{ + dm_free(TO_DCN10_OPP(*opp)); + *opp = NULL; +} + +static struct opp_funcs dcn10_opp_funcs = { + .opp_power_on_regamma_lut = opp_power_on_regamma_lut, + .opp_set_csc_adjustment = NULL, + .opp_set_csc_default = opp_set_output_csc_default, + .opp_set_dyn_expansion = opp_set_dyn_expansion, + .opp_program_regamma_pwl = opp_set_regamma_pwl, + .opp_set_regamma_mode = opp_set_regamma_mode, + .opp_program_fmt = opp_program_fmt, + .opp_program_bit_depth_reduction = opp_program_bit_depth_reduction, + .opp_set_stereo_polarity = opp_set_stereo_polarity, + .opp_destroy = dcn10_opp_destroy +}; + +void dcn10_opp_construct(struct dcn10_opp *oppn10, + struct dc_context *ctx, + uint32_t inst, + const struct dcn10_opp_registers *regs, + const struct dcn10_opp_shift *opp_shift, + const struct dcn10_opp_mask *opp_mask) +{ + oppn10->base.ctx = ctx; + oppn10->base.inst = inst; + oppn10->base.funcs = &dcn10_opp_funcs; + + oppn10->regs = regs; + oppn10->opp_shift = opp_shift; + oppn10->opp_mask = opp_mask; +} diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h new file mode 100644 index 000000000000..113e0bc349c3 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h @@ -0,0 +1,622 @@ +/* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_OPP_DCN10_H__ +#define __DC_OPP_DCN10_H__ + +#include "opp.h" + +#define TO_DCN10_OPP(opp)\ + container_of(opp, struct dcn10_opp, base) + +#define OPP_SF(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define OPP_DCN10_REG_LIST(id) \ + SRI(CM_RGAM_LUT_WRITE_EN_MASK, CM, id), \ + SRI(CM_RGAM_CONTROL, CM, id), \ + SRI(OBUF_CONTROL, DSCL, id), \ + SRI(FMT_BIT_DEPTH_CONTROL, FMT, id), \ + SRI(FMT_CONTROL, FMT, id), \ + SRI(FMT_DITHER_RAND_R_SEED, FMT, id), \ + SRI(FMT_DITHER_RAND_G_SEED, FMT, id), \ + SRI(FMT_DITHER_RAND_B_SEED, FMT, id), \ + SRI(FMT_CLAMP_CNTL, FMT, id), \ + SRI(FMT_DYNAMIC_EXP_CNTL, FMT, id), \ + SRI(FMT_MAP420_MEMORY_CONTROL, FMT, id), \ + SRI(CM_OCSC_CONTROL, CM, id), \ + SRI(CM_RGAM_RAMB_START_CNTL_B, CM, id), \ + SRI(CM_RGAM_RAMB_START_CNTL_G, CM, id), \ + SRI(CM_RGAM_RAMB_START_CNTL_R, CM, id), \ + SRI(CM_RGAM_RAMB_SLOPE_CNTL_B, CM, id), \ + SRI(CM_RGAM_RAMB_SLOPE_CNTL_G, CM, id), \ + SRI(CM_RGAM_RAMB_SLOPE_CNTL_R, CM, id), \ + SRI(CM_RGAM_RAMB_END_CNTL1_B, CM, id), \ + SRI(CM_RGAM_RAMB_END_CNTL2_B, CM, id), \ + SRI(CM_RGAM_RAMB_END_CNTL1_G, CM, id), \ + SRI(CM_RGAM_RAMB_END_CNTL2_G, CM, id), \ + SRI(CM_RGAM_RAMB_END_CNTL1_R, CM, id), \ + SRI(CM_RGAM_RAMB_END_CNTL2_R, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_0_1, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_2_3, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_4_5, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_6_7, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_8_9, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_10_11, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_12_13, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_14_15, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_16_17, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_18_19, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_20_21, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_22_23, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_24_25, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_26_27, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_28_29, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_30_31, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_32_33, CM, id), \ + SRI(CM_RGAM_RAMA_START_CNTL_B, CM, id), \ + SRI(CM_RGAM_RAMA_START_CNTL_G, CM, id), \ + SRI(CM_RGAM_RAMA_START_CNTL_R, CM, id), \ + SRI(CM_RGAM_RAMA_SLOPE_CNTL_B, CM, id), \ + SRI(CM_RGAM_RAMA_SLOPE_CNTL_G, CM, id), \ + SRI(CM_RGAM_RAMA_SLOPE_CNTL_R, CM, id), \ + SRI(CM_RGAM_RAMA_END_CNTL1_B, CM, id), \ + SRI(CM_RGAM_RAMA_END_CNTL2_B, CM, id), \ + SRI(CM_RGAM_RAMA_END_CNTL1_G, CM, id), \ + SRI(CM_RGAM_RAMA_END_CNTL2_G, CM, id), \ + SRI(CM_RGAM_RAMA_END_CNTL1_R, CM, id), \ + SRI(CM_RGAM_RAMA_END_CNTL2_R, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_0_1, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_2_3, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_4_5, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_6_7, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_8_9, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_10_11, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_12_13, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_14_15, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_16_17, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_18_19, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_20_21, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_22_23, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_24_25, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_26_27, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_28_29, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_30_31, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_32_33, CM, id), \ + SRI(CM_RGAM_LUT_INDEX, CM, id), \ + SRI(CM_MEM_PWR_CTRL, CM, id), \ + SRI(CM_RGAM_LUT_DATA, CM, id) + +#define OPP_DCN10_MASK_SH_LIST(mask_sh) \ + OPP_SF(CM0_CM_RGAM_CONTROL, CM_RGAM_LUT_MODE, mask_sh), \ + OPP_SF(DSCL0_OBUF_CONTROL, OBUF_BYPASS, mask_sh), \ + OPP_SF(DSCL0_OBUF_CONTROL, OBUF_H_2X_UPSCALE_EN, mask_sh), \ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN, mask_sh), \ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_DEPTH, mask_sh), \ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_MODE, mask_sh), \ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_EN, mask_sh), \ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_MODE, mask_sh), \ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_DEPTH, mask_sh), \ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_EN, mask_sh), \ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_HIGHPASS_RANDOM_ENABLE, mask_sh), \ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_FRAME_RANDOM_ENABLE, mask_sh), \ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_RGB_RANDOM_ENABLE, mask_sh), \ + OPP_SF(FMT0_FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, mask_sh), \ + OPP_SF(FMT0_FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, mask_sh), \ + OPP_SF(FMT0_FMT_DITHER_RAND_R_SEED, FMT_RAND_R_SEED, mask_sh), \ + OPP_SF(FMT0_FMT_DITHER_RAND_G_SEED, FMT_RAND_G_SEED, mask_sh), \ + OPP_SF(FMT0_FMT_DITHER_RAND_B_SEED, FMT_RAND_B_SEED, mask_sh), \ + OPP_SF(FMT0_FMT_CONTROL, FMT_PIXEL_ENCODING, mask_sh), \ + OPP_SF(FMT0_FMT_CLAMP_CNTL, FMT_CLAMP_DATA_EN, mask_sh), \ + OPP_SF(FMT0_FMT_CLAMP_CNTL, FMT_CLAMP_COLOR_FORMAT, mask_sh), \ + OPP_SF(FMT0_FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN, mask_sh), \ + OPP_SF(FMT0_FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE, mask_sh), \ + OPP_SF(FMT0_FMT_MAP420_MEMORY_CONTROL, FMT_MAP420MEM_PWR_FORCE, mask_sh), \ + OPP_SF(CM0_CM_OCSC_CONTROL, CM_OCSC_MODE, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_START_CNTL_B, CM_RGAM_RAMB_EXP_REGION_START_B, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_START_CNTL_B, CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_START_CNTL_G, CM_RGAM_RAMB_EXP_REGION_START_G, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_START_CNTL_G, CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_G, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_START_CNTL_R, CM_RGAM_RAMB_EXP_REGION_START_R, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_START_CNTL_R, CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_R, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_SLOPE_CNTL_B, CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_SLOPE_CNTL_G, CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_G, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_SLOPE_CNTL_R, CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_R, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_END_CNTL1_B, CM_RGAM_RAMB_EXP_REGION_END_B, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_END_CNTL2_B, CM_RGAM_RAMB_EXP_REGION_END_SLOPE_B, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_END_CNTL2_B, CM_RGAM_RAMB_EXP_REGION_END_BASE_B, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_END_CNTL1_G, CM_RGAM_RAMB_EXP_REGION_END_G, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_END_CNTL2_G, CM_RGAM_RAMB_EXP_REGION_END_SLOPE_G, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_END_CNTL2_G, CM_RGAM_RAMB_EXP_REGION_END_BASE_G, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_END_CNTL1_R, CM_RGAM_RAMB_EXP_REGION_END_R, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_END_CNTL2_R, CM_RGAM_RAMB_EXP_REGION_END_SLOPE_R, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_END_CNTL2_R, CM_RGAM_RAMB_EXP_REGION_END_BASE_R, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_0_1, CM_RGAM_RAMB_EXP_REGION0_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_0_1, CM_RGAM_RAMB_EXP_REGION0_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_0_1, CM_RGAM_RAMB_EXP_REGION1_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_0_1, CM_RGAM_RAMB_EXP_REGION1_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_2_3, CM_RGAM_RAMB_EXP_REGION2_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_2_3, CM_RGAM_RAMB_EXP_REGION2_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_2_3, CM_RGAM_RAMB_EXP_REGION3_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_2_3, CM_RGAM_RAMB_EXP_REGION3_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_4_5, CM_RGAM_RAMB_EXP_REGION4_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_4_5, CM_RGAM_RAMB_EXP_REGION4_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_4_5, CM_RGAM_RAMB_EXP_REGION5_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_4_5, CM_RGAM_RAMB_EXP_REGION5_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_6_7, CM_RGAM_RAMB_EXP_REGION6_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_6_7, CM_RGAM_RAMB_EXP_REGION6_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_6_7, CM_RGAM_RAMB_EXP_REGION7_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_6_7, CM_RGAM_RAMB_EXP_REGION7_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_8_9, CM_RGAM_RAMB_EXP_REGION8_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_8_9, CM_RGAM_RAMB_EXP_REGION8_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_8_9, CM_RGAM_RAMB_EXP_REGION9_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_8_9, CM_RGAM_RAMB_EXP_REGION9_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_10_11, CM_RGAM_RAMB_EXP_REGION10_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_10_11, CM_RGAM_RAMB_EXP_REGION10_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_10_11, CM_RGAM_RAMB_EXP_REGION11_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_10_11, CM_RGAM_RAMB_EXP_REGION11_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_12_13, CM_RGAM_RAMB_EXP_REGION12_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_12_13, CM_RGAM_RAMB_EXP_REGION12_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_12_13, CM_RGAM_RAMB_EXP_REGION13_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_12_13, CM_RGAM_RAMB_EXP_REGION13_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_14_15, CM_RGAM_RAMB_EXP_REGION14_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_14_15, CM_RGAM_RAMB_EXP_REGION14_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_14_15, CM_RGAM_RAMB_EXP_REGION15_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_14_15, CM_RGAM_RAMB_EXP_REGION15_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_16_17, CM_RGAM_RAMB_EXP_REGION16_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_16_17, CM_RGAM_RAMB_EXP_REGION16_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_16_17, CM_RGAM_RAMB_EXP_REGION17_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_16_17, CM_RGAM_RAMB_EXP_REGION17_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_18_19, CM_RGAM_RAMB_EXP_REGION18_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_18_19, CM_RGAM_RAMB_EXP_REGION18_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_18_19, CM_RGAM_RAMB_EXP_REGION19_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_18_19, CM_RGAM_RAMB_EXP_REGION19_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_20_21, CM_RGAM_RAMB_EXP_REGION20_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_20_21, CM_RGAM_RAMB_EXP_REGION20_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_20_21, CM_RGAM_RAMB_EXP_REGION21_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_20_21, CM_RGAM_RAMB_EXP_REGION21_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_22_23, CM_RGAM_RAMB_EXP_REGION22_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_22_23, CM_RGAM_RAMB_EXP_REGION22_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_22_23, CM_RGAM_RAMB_EXP_REGION23_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_22_23, CM_RGAM_RAMB_EXP_REGION23_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_24_25, CM_RGAM_RAMB_EXP_REGION24_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_24_25, CM_RGAM_RAMB_EXP_REGION24_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_24_25, CM_RGAM_RAMB_EXP_REGION25_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_24_25, CM_RGAM_RAMB_EXP_REGION25_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_26_27, CM_RGAM_RAMB_EXP_REGION26_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_26_27, CM_RGAM_RAMB_EXP_REGION26_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_26_27, CM_RGAM_RAMB_EXP_REGION27_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_26_27, CM_RGAM_RAMB_EXP_REGION27_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_28_29, CM_RGAM_RAMB_EXP_REGION28_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_28_29, CM_RGAM_RAMB_EXP_REGION28_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_28_29, CM_RGAM_RAMB_EXP_REGION29_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_28_29, CM_RGAM_RAMB_EXP_REGION29_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_30_31, CM_RGAM_RAMB_EXP_REGION30_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_30_31, CM_RGAM_RAMB_EXP_REGION30_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_30_31, CM_RGAM_RAMB_EXP_REGION31_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_30_31, CM_RGAM_RAMB_EXP_REGION31_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_32_33, CM_RGAM_RAMB_EXP_REGION32_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_32_33, CM_RGAM_RAMB_EXP_REGION32_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_32_33, CM_RGAM_RAMB_EXP_REGION33_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_32_33, CM_RGAM_RAMB_EXP_REGION33_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_START_CNTL_B, CM_RGAM_RAMA_EXP_REGION_START_B, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_START_CNTL_B, CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_B, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_START_CNTL_G, CM_RGAM_RAMA_EXP_REGION_START_G, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_START_CNTL_G, CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_G, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_START_CNTL_R, CM_RGAM_RAMA_EXP_REGION_START_R, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_START_CNTL_R, CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_R, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_SLOPE_CNTL_B, CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_SLOPE_CNTL_G, CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_SLOPE_CNTL_R, CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_END_CNTL1_B, CM_RGAM_RAMA_EXP_REGION_END_B, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_END_CNTL2_B, CM_RGAM_RAMA_EXP_REGION_END_SLOPE_B, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_END_CNTL2_B, CM_RGAM_RAMA_EXP_REGION_END_BASE_B, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_END_CNTL1_G, CM_RGAM_RAMA_EXP_REGION_END_G, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_END_CNTL2_G, CM_RGAM_RAMA_EXP_REGION_END_SLOPE_G, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_END_CNTL2_G, CM_RGAM_RAMA_EXP_REGION_END_BASE_G, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_END_CNTL1_R, CM_RGAM_RAMA_EXP_REGION_END_R, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_END_CNTL2_R, CM_RGAM_RAMA_EXP_REGION_END_SLOPE_R, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_END_CNTL2_R, CM_RGAM_RAMA_EXP_REGION_END_BASE_R, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_0_1, CM_RGAM_RAMA_EXP_REGION0_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_0_1, CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_0_1, CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_0_1, CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_2_3, CM_RGAM_RAMA_EXP_REGION2_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_2_3, CM_RGAM_RAMA_EXP_REGION2_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_2_3, CM_RGAM_RAMA_EXP_REGION3_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_2_3, CM_RGAM_RAMA_EXP_REGION3_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_4_5, CM_RGAM_RAMA_EXP_REGION4_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_4_5, CM_RGAM_RAMA_EXP_REGION4_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_4_5, CM_RGAM_RAMA_EXP_REGION5_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_4_5, CM_RGAM_RAMA_EXP_REGION5_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_6_7, CM_RGAM_RAMA_EXP_REGION6_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_6_7, CM_RGAM_RAMA_EXP_REGION6_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_6_7, CM_RGAM_RAMA_EXP_REGION7_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_6_7, CM_RGAM_RAMA_EXP_REGION7_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_8_9, CM_RGAM_RAMA_EXP_REGION8_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_8_9, CM_RGAM_RAMA_EXP_REGION8_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_8_9, CM_RGAM_RAMA_EXP_REGION9_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_8_9, CM_RGAM_RAMA_EXP_REGION9_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_10_11, CM_RGAM_RAMA_EXP_REGION10_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_10_11, CM_RGAM_RAMA_EXP_REGION10_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_10_11, CM_RGAM_RAMA_EXP_REGION11_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_10_11, CM_RGAM_RAMA_EXP_REGION11_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_12_13, CM_RGAM_RAMA_EXP_REGION12_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_12_13, CM_RGAM_RAMA_EXP_REGION12_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_12_13, CM_RGAM_RAMA_EXP_REGION13_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_12_13, CM_RGAM_RAMA_EXP_REGION13_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_14_15, CM_RGAM_RAMA_EXP_REGION14_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_14_15, CM_RGAM_RAMA_EXP_REGION14_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_14_15, CM_RGAM_RAMA_EXP_REGION15_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_14_15, CM_RGAM_RAMA_EXP_REGION15_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_16_17, CM_RGAM_RAMA_EXP_REGION16_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_16_17, CM_RGAM_RAMA_EXP_REGION16_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_16_17, CM_RGAM_RAMA_EXP_REGION17_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_16_17, CM_RGAM_RAMA_EXP_REGION17_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_18_19, CM_RGAM_RAMA_EXP_REGION18_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_18_19, CM_RGAM_RAMA_EXP_REGION18_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_18_19, CM_RGAM_RAMA_EXP_REGION19_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_18_19, CM_RGAM_RAMA_EXP_REGION19_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_20_21, CM_RGAM_RAMA_EXP_REGION20_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_20_21, CM_RGAM_RAMA_EXP_REGION20_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_20_21, CM_RGAM_RAMA_EXP_REGION21_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_20_21, CM_RGAM_RAMA_EXP_REGION21_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_22_23, CM_RGAM_RAMA_EXP_REGION22_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_22_23, CM_RGAM_RAMA_EXP_REGION22_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_22_23, CM_RGAM_RAMA_EXP_REGION23_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_22_23, CM_RGAM_RAMA_EXP_REGION23_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_24_25, CM_RGAM_RAMA_EXP_REGION24_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_24_25, CM_RGAM_RAMA_EXP_REGION24_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_24_25, CM_RGAM_RAMA_EXP_REGION25_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_24_25, CM_RGAM_RAMA_EXP_REGION25_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_26_27, CM_RGAM_RAMA_EXP_REGION26_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_26_27, CM_RGAM_RAMA_EXP_REGION26_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_26_27, CM_RGAM_RAMA_EXP_REGION27_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_26_27, CM_RGAM_RAMA_EXP_REGION27_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_28_29, CM_RGAM_RAMA_EXP_REGION28_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_28_29, CM_RGAM_RAMA_EXP_REGION28_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_28_29, CM_RGAM_RAMA_EXP_REGION29_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_28_29, CM_RGAM_RAMA_EXP_REGION29_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_30_31, CM_RGAM_RAMA_EXP_REGION30_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_30_31, CM_RGAM_RAMA_EXP_REGION30_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_30_31, CM_RGAM_RAMA_EXP_REGION31_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_30_31, CM_RGAM_RAMA_EXP_REGION31_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_32_33, CM_RGAM_RAMA_EXP_REGION32_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_32_33, CM_RGAM_RAMA_EXP_REGION32_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_32_33, CM_RGAM_RAMA_EXP_REGION33_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_32_33, CM_RGAM_RAMA_EXP_REGION33_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_LUT_WRITE_EN_MASK, CM_RGAM_LUT_WRITE_EN_MASK, mask_sh), \ + OPP_SF(CM0_CM_RGAM_LUT_WRITE_EN_MASK, CM_RGAM_LUT_WRITE_SEL, mask_sh), \ + OPP_SF(CM0_CM_RGAM_LUT_INDEX, CM_RGAM_LUT_INDEX, mask_sh), \ + OPP_SF(CM0_CM_MEM_PWR_CTRL, RGAM_MEM_PWR_FORCE, mask_sh), \ + OPP_SF(CM0_CM_RGAM_LUT_DATA, CM_RGAM_LUT_DATA, mask_sh), \ + OPP_SF(FMT0_FMT_CONTROL, FMT_STEREOSYNC_OVERRIDE, mask_sh) + +#define OPP_DCN10_REG_FIELD_LIST(type) \ + type CM_RGAM_LUT_MODE; \ + type OBUF_BYPASS; \ + type OBUF_H_2X_UPSCALE_EN; \ + type FMT_TRUNCATE_EN; \ + type FMT_TRUNCATE_DEPTH; \ + type FMT_TRUNCATE_MODE; \ + type FMT_SPATIAL_DITHER_EN; \ + type FMT_SPATIAL_DITHER_MODE; \ + type FMT_SPATIAL_DITHER_DEPTH; \ + type FMT_TEMPORAL_DITHER_EN; \ + type FMT_HIGHPASS_RANDOM_ENABLE; \ + type FMT_FRAME_RANDOM_ENABLE; \ + type FMT_RGB_RANDOM_ENABLE; \ + type FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX; \ + type FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP; \ + type FMT_RAND_R_SEED; \ + type FMT_RAND_G_SEED; \ + type FMT_RAND_B_SEED; \ + type FMT_PIXEL_ENCODING; \ + type FMT_CLAMP_DATA_EN; \ + type FMT_CLAMP_COLOR_FORMAT; \ + type FMT_DYNAMIC_EXP_EN; \ + type FMT_DYNAMIC_EXP_MODE; \ + type FMT_MAP420MEM_PWR_FORCE; \ + type CM_OCSC_MODE; \ + type CM_RGAM_RAMB_EXP_REGION_START_B; \ + type CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B; \ + type CM_RGAM_RAMB_EXP_REGION_START_G; \ + type CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_G; \ + type CM_RGAM_RAMB_EXP_REGION_START_R; \ + type CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_R; \ + type CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B; \ + type CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_G; \ + type CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_R; \ + type CM_RGAM_RAMB_EXP_REGION_END_B; \ + type CM_RGAM_RAMB_EXP_REGION_END_SLOPE_B; \ + type CM_RGAM_RAMB_EXP_REGION_END_BASE_B; \ + type CM_RGAM_RAMB_EXP_REGION_END_G; \ + type CM_RGAM_RAMB_EXP_REGION_END_SLOPE_G; \ + type CM_RGAM_RAMB_EXP_REGION_END_BASE_G; \ + type CM_RGAM_RAMB_EXP_REGION_END_R; \ + type CM_RGAM_RAMB_EXP_REGION_END_SLOPE_R; \ + type CM_RGAM_RAMB_EXP_REGION_END_BASE_R; \ + type CM_RGAM_RAMB_EXP_REGION0_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION0_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION1_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION1_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION2_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION2_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION3_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION3_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION4_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION4_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION5_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION5_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION6_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION6_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION7_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION7_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION8_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION8_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION9_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION9_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION10_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION10_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION11_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION11_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION12_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION12_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION13_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION13_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION14_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION14_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION15_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION15_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION16_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION16_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION17_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION17_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION18_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION18_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION19_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION19_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION20_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION20_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION21_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION21_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION22_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION22_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION23_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION23_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION24_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION24_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION25_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION25_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION26_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION26_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION27_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION27_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION28_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION28_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION29_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION29_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION30_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION30_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION31_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION31_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION32_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION32_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION33_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION33_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION_START_B; \ + type CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_B; \ + type CM_RGAM_RAMA_EXP_REGION_START_G; \ + type CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_G; \ + type CM_RGAM_RAMA_EXP_REGION_START_R; \ + type CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_R; \ + type CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B; \ + type CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G; \ + type CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R; \ + type CM_RGAM_RAMA_EXP_REGION_END_B; \ + type CM_RGAM_RAMA_EXP_REGION_END_SLOPE_B; \ + type CM_RGAM_RAMA_EXP_REGION_END_BASE_B; \ + type CM_RGAM_RAMA_EXP_REGION_END_G; \ + type CM_RGAM_RAMA_EXP_REGION_END_SLOPE_G; \ + type CM_RGAM_RAMA_EXP_REGION_END_BASE_G; \ + type CM_RGAM_RAMA_EXP_REGION_END_R; \ + type CM_RGAM_RAMA_EXP_REGION_END_SLOPE_R; \ + type CM_RGAM_RAMA_EXP_REGION_END_BASE_R; \ + type CM_RGAM_RAMA_EXP_REGION0_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION2_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION2_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION3_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION3_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION4_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION4_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION5_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION5_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION6_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION6_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION7_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION7_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION8_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION8_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION9_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION9_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION10_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION10_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION11_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION11_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION12_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION12_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION13_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION13_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION14_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION14_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION15_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION15_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION16_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION16_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION17_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION17_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION18_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION18_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION19_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION19_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION20_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION20_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION21_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION21_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION22_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION22_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION23_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION23_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION24_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION24_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION25_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION25_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION26_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION26_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION27_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION27_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION28_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION28_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION29_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION29_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION30_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION30_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION31_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION31_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION32_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION32_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION33_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION33_NUM_SEGMENTS; \ + type CM_RGAM_LUT_WRITE_EN_MASK; \ + type CM_RGAM_LUT_WRITE_SEL; \ + type CM_RGAM_LUT_INDEX; \ + type RGAM_MEM_PWR_FORCE; \ + type CM_RGAM_LUT_DATA; \ + type FMT_STEREOSYNC_OVERRIDE + +struct dcn10_opp_shift { + OPP_DCN10_REG_FIELD_LIST(uint8_t); +}; + +struct dcn10_opp_mask { + OPP_DCN10_REG_FIELD_LIST(uint32_t); +}; + +struct dcn10_opp_registers { + uint32_t CM_RGAM_LUT_WRITE_EN_MASK; + uint32_t CM_RGAM_CONTROL; + uint32_t OBUF_CONTROL; + uint32_t FMT_BIT_DEPTH_CONTROL; + uint32_t FMT_CONTROL; + uint32_t FMT_DITHER_RAND_R_SEED; + uint32_t FMT_DITHER_RAND_G_SEED; + uint32_t FMT_DITHER_RAND_B_SEED; + uint32_t FMT_CLAMP_CNTL; + uint32_t FMT_DYNAMIC_EXP_CNTL; + uint32_t FMT_MAP420_MEMORY_CONTROL; + uint32_t CM_OCSC_CONTROL; + uint32_t CM_RGAM_RAMB_START_CNTL_B; + uint32_t CM_RGAM_RAMB_START_CNTL_G; + uint32_t CM_RGAM_RAMB_START_CNTL_R; + uint32_t CM_RGAM_RAMB_SLOPE_CNTL_B; + uint32_t CM_RGAM_RAMB_SLOPE_CNTL_G; + uint32_t CM_RGAM_RAMB_SLOPE_CNTL_R; + uint32_t CM_RGAM_RAMB_END_CNTL1_B; + uint32_t CM_RGAM_RAMB_END_CNTL2_B; + uint32_t CM_RGAM_RAMB_END_CNTL1_G; + uint32_t CM_RGAM_RAMB_END_CNTL2_G; + uint32_t CM_RGAM_RAMB_END_CNTL1_R; + uint32_t CM_RGAM_RAMB_END_CNTL2_R; + uint32_t CM_RGAM_RAMB_REGION_0_1; + uint32_t CM_RGAM_RAMB_REGION_2_3; + uint32_t CM_RGAM_RAMB_REGION_4_5; + uint32_t CM_RGAM_RAMB_REGION_6_7; + uint32_t CM_RGAM_RAMB_REGION_8_9; + uint32_t CM_RGAM_RAMB_REGION_10_11; + uint32_t CM_RGAM_RAMB_REGION_12_13; + uint32_t CM_RGAM_RAMB_REGION_14_15; + uint32_t CM_RGAM_RAMB_REGION_16_17; + uint32_t CM_RGAM_RAMB_REGION_18_19; + uint32_t CM_RGAM_RAMB_REGION_20_21; + uint32_t CM_RGAM_RAMB_REGION_22_23; + uint32_t CM_RGAM_RAMB_REGION_24_25; + uint32_t CM_RGAM_RAMB_REGION_26_27; + uint32_t CM_RGAM_RAMB_REGION_28_29; + uint32_t CM_RGAM_RAMB_REGION_30_31; + uint32_t CM_RGAM_RAMB_REGION_32_33; + uint32_t CM_RGAM_RAMA_START_CNTL_B; + uint32_t CM_RGAM_RAMA_START_CNTL_G; + uint32_t CM_RGAM_RAMA_START_CNTL_R; + uint32_t CM_RGAM_RAMA_SLOPE_CNTL_B; + uint32_t CM_RGAM_RAMA_SLOPE_CNTL_G; + uint32_t CM_RGAM_RAMA_SLOPE_CNTL_R; + uint32_t CM_RGAM_RAMA_END_CNTL1_B; + uint32_t CM_RGAM_RAMA_END_CNTL2_B; + uint32_t CM_RGAM_RAMA_END_CNTL1_G; + uint32_t CM_RGAM_RAMA_END_CNTL2_G; + uint32_t CM_RGAM_RAMA_END_CNTL1_R; + uint32_t CM_RGAM_RAMA_END_CNTL2_R; + uint32_t CM_RGAM_RAMA_REGION_0_1; + uint32_t CM_RGAM_RAMA_REGION_2_3; + uint32_t CM_RGAM_RAMA_REGION_4_5; + uint32_t CM_RGAM_RAMA_REGION_6_7; + uint32_t CM_RGAM_RAMA_REGION_8_9; + uint32_t CM_RGAM_RAMA_REGION_10_11; + uint32_t CM_RGAM_RAMA_REGION_12_13; + uint32_t CM_RGAM_RAMA_REGION_14_15; + uint32_t CM_RGAM_RAMA_REGION_16_17; + uint32_t CM_RGAM_RAMA_REGION_18_19; + uint32_t CM_RGAM_RAMA_REGION_20_21; + uint32_t CM_RGAM_RAMA_REGION_22_23; + uint32_t CM_RGAM_RAMA_REGION_24_25; + uint32_t CM_RGAM_RAMA_REGION_26_27; + uint32_t CM_RGAM_RAMA_REGION_28_29; + uint32_t CM_RGAM_RAMA_REGION_30_31; + uint32_t CM_RGAM_RAMA_REGION_32_33; + uint32_t CM_RGAM_LUT_INDEX; + uint32_t CM_MEM_PWR_CTRL; + uint32_t CM_RGAM_LUT_DATA; +}; + +struct dcn10_opp { + struct output_pixel_processor base; + + const struct dcn10_opp_registers *regs; + const struct dcn10_opp_shift *opp_shift; + const struct dcn10_opp_mask *opp_mask; + + bool is_write_to_ram_a_safe; +}; + +void dcn10_opp_construct(struct dcn10_opp *oppn10, + struct dc_context *ctx, + uint32_t inst, + const struct dcn10_opp_registers *regs, + const struct dcn10_opp_shift *opp_shift, + const struct dcn10_opp_mask *opp_mask); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c new file mode 100644 index 000000000000..7aa438cd2b1a --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -0,0 +1,1475 @@ +/* +* Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "dc.h" + +#include "resource.h" +#include "include/irq_service_interface.h" +#include "dcn10/dcn10_resource.h" + +#include "dcn10/dcn10_ipp.h" +#include "dcn10/dcn10_mpc.h" +#include "irq/dcn10/irq_service_dcn10.h" +#include "dcn10/dcn10_transform.h" +#include "dcn10/dcn10_timing_generator.h" +#include "dcn10/dcn10_hw_sequencer.h" +#include "dce110/dce110_hw_sequencer.h" +#include "dcn10/dcn10_opp.h" +#include "dce/dce_link_encoder.h" +#include "dce/dce_stream_encoder.h" +#include "dce/dce_clocks.h" +#include "dce/dce_clock_source.h" +#include "dcn10/dcn10_mem_input.h" +#include "dce/dce_audio.h" +#include "dce/dce_hwseq.h" +#include "../virtual/virtual_stream_encoder.h" +#include "dce110/dce110_resource.h" + +#include "vega10/soc15ip.h" + +#include "raven1/DCN/dcn_1_0_offset.h" +#include "raven1/DCN/dcn_1_0_sh_mask.h" + +#include "raven1/NBIO/nbio_7_0_offset.h" + +#include "raven1/MMHUB/mmhub_9_1_offset.h" +#include "raven1/MMHUB/mmhub_9_1_sh_mask.h" + +#include "reg_helper.h" +#include "dce/dce_abm.h" +#include "dce/dce_dmcu.h" + +#ifndef mmDP0_DP_DPHY_INTERNAL_CTRL + #define mmDP0_DP_DPHY_INTERNAL_CTRL 0x210f + #define mmDP0_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 + #define mmDP1_DP_DPHY_INTERNAL_CTRL 0x220f + #define mmDP1_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 + #define mmDP2_DP_DPHY_INTERNAL_CTRL 0x230f + #define mmDP2_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 + #define mmDP3_DP_DPHY_INTERNAL_CTRL 0x240f + #define mmDP3_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 + #define mmDP4_DP_DPHY_INTERNAL_CTRL 0x250f + #define mmDP4_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 + #define mmDP5_DP_DPHY_INTERNAL_CTRL 0x260f + #define mmDP5_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 + #define mmDP6_DP_DPHY_INTERNAL_CTRL 0x270f + #define mmDP6_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 +#endif + + +enum dcn10_clk_src_array_id { + DCN10_CLK_SRC_PLL0, + DCN10_CLK_SRC_PLL1, + DCN10_CLK_SRC_PLL2, + DCN10_CLK_SRC_PLL3, + DCN10_CLK_SRC_TOTAL +}; + +/* begin ********************* + * macros to expend register list macro defined in HW object header file */ + +/* DCN */ +#define BASE_INNER(seg) \ + DCE_BASE__INST0_SEG ## seg + +#define BASE(seg) \ + BASE_INNER(seg) + +#define SR(reg_name)\ + .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + \ + mm ## reg_name + +#define SRI(reg_name, block, id)\ + .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + + +#define SRII(reg_name, block, id)\ + .reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +/* NBIO */ +#define NBIO_BASE_INNER(seg) \ + NBIF_BASE__INST0_SEG ## seg + +#define NBIO_BASE(seg) \ + NBIO_BASE_INNER(seg) + +#define NBIO_SR(reg_name)\ + .reg_name = NBIO_BASE(mm ## reg_name ## _BASE_IDX) + \ + mm ## reg_name + +/* GC */ +#define GC_BASE_INNER(seg) \ + GC_BASE__INST0_SEG ## seg + +#define GC_BASE(seg) \ + GC_BASE_INNER(seg) + +#define GC_SR(reg_name)\ + .reg_name = GC_BASE(mm ## reg_name ## _BASE_IDX) + \ + mm ## reg_name + +/* macros to expend register list macro defined in HW object header file + * end *********************/ + +static const struct dce_disp_clk_registers disp_clk_regs = { + CLK_DCN10_REG_LIST() +}; + +static const struct dce_disp_clk_shift disp_clk_shift = { + CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) +}; + +static const struct dce_disp_clk_mask disp_clk_mask = { + CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) +}; + +static const struct dce_dmcu_registers dmcu_regs = { + DMCU_DCN10_REG_LIST() +}; + +static const struct dce_dmcu_shift dmcu_shift = { + DMCU_MASK_SH_LIST_DCN10(__SHIFT) +}; + +static const struct dce_dmcu_mask dmcu_mask = { + DMCU_MASK_SH_LIST_DCN10(_MASK) +}; + +static const struct dce_abm_registers abm_regs = { + ABM_DCN10_REG_LIST(0) +}; + +static const struct dce_abm_shift abm_shift = { + ABM_MASK_SH_LIST_DCN10(__SHIFT) +}; + +static const struct dce_abm_mask abm_mask = { + ABM_MASK_SH_LIST_DCN10(_MASK) +}; + +#define stream_enc_regs(id)\ +[id] = {\ + SE_DCN_REG_LIST(id),\ + .TMDS_CNTL = 0,\ + .AFMT_AVI_INFO0 = 0,\ + .AFMT_AVI_INFO1 = 0,\ + .AFMT_AVI_INFO2 = 0,\ + .AFMT_AVI_INFO3 = 0,\ +} + +static const struct dce110_stream_enc_registers stream_enc_regs[] = { + stream_enc_regs(0), + stream_enc_regs(1), + stream_enc_regs(2), + stream_enc_regs(3), +}; + +static const struct dce_stream_encoder_shift se_shift = { + SE_COMMON_MASK_SH_LIST_DCN10(__SHIFT) +}; + +static const struct dce_stream_encoder_mask se_mask = { + SE_COMMON_MASK_SH_LIST_DCN10(_MASK), + .AFMT_GENERIC0_UPDATE = 0, + .AFMT_GENERIC2_UPDATE = 0, + .DP_DYN_RANGE = 0, + .DP_YCBCR_RANGE = 0, + .HDMI_AVI_INFO_SEND = 0, + .HDMI_AVI_INFO_CONT = 0, + .HDMI_AVI_INFO_LINE = 0, + .DP_SEC_AVI_ENABLE = 0, + .AFMT_AVI_INFO_VERSION = 0 +}; + +#define audio_regs(id)\ +[id] = {\ + AUD_COMMON_REG_LIST(id)\ +} + +static const struct dce_audio_registers audio_regs[] = { + audio_regs(0), + audio_regs(1), + audio_regs(2), + audio_regs(3), +}; + +#define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\ + SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\ + SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\ + AUD_COMMON_MASK_SH_LIST_BASE(mask_sh) + +static const struct dce_audio_shift audio_shift = { + DCE120_AUD_COMMON_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_aduio_mask audio_mask = { + DCE120_AUD_COMMON_MASK_SH_LIST(_MASK) +}; + +#define aux_regs(id)\ +[id] = {\ + AUX_REG_LIST(id)\ +} + +static const struct dce110_link_enc_aux_registers link_enc_aux_regs[] = { + aux_regs(0), + aux_regs(1), + aux_regs(2), + aux_regs(3), + aux_regs(4), + aux_regs(5) +}; + +#define hpd_regs(id)\ +[id] = {\ + HPD_REG_LIST(id)\ +} + +static const struct dce110_link_enc_hpd_registers link_enc_hpd_regs[] = { + hpd_regs(0), + hpd_regs(1), + hpd_regs(2), + hpd_regs(3), + hpd_regs(4), + hpd_regs(5) +}; + +#define link_regs(id)\ +[id] = {\ + LE_DCN10_REG_LIST(id), \ + SRI(DP_DPHY_INTERNAL_CTRL, DP, id) \ +} + +static const struct dce110_link_enc_registers link_enc_regs[] = { + link_regs(0), + link_regs(1), + link_regs(2), + link_regs(3), + link_regs(4), + link_regs(5), + link_regs(6), +}; + +#define ipp_regs(id)\ +[id] = {\ + IPP_DCN10_REG_LIST(id),\ +} + +static const struct dcn10_ipp_registers ipp_regs[] = { + ipp_regs(0), + ipp_regs(1), + ipp_regs(2), + ipp_regs(3), +}; + +static const struct dcn10_ipp_shift ipp_shift = { + IPP_DCN10_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn10_ipp_mask ipp_mask = { + IPP_DCN10_MASK_SH_LIST(_MASK), +}; + +#define opp_regs(id)\ +[id] = {\ + OPP_DCN10_REG_LIST(id),\ +} + +static const struct dcn10_opp_registers opp_regs[] = { + opp_regs(0), + opp_regs(1), + opp_regs(2), + opp_regs(3), +}; + +static const struct dcn10_opp_shift opp_shift = { + OPP_DCN10_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn10_opp_mask opp_mask = { + OPP_DCN10_MASK_SH_LIST(_MASK), +}; + +#define tf_regs(id)\ +[id] = {\ + TF_REG_LIST_DCN(id),\ +} + +static const struct dcn_transform_registers tf_regs[] = { + tf_regs(0), + tf_regs(1), + tf_regs(2), + tf_regs(3), +}; + +static const struct dcn_transform_shift tf_shift = { + TF_REG_LIST_SH_MASK_DCN(__SHIFT) +}; + +static const struct dcn_transform_mask tf_mask = { + TF_REG_LIST_SH_MASK_DCN(_MASK), +}; + + +static const struct dcn_mpc_registers mpc_regs = { + MPC_COMMON_REG_LIST_DCN1_0(0), + MPC_COMMON_REG_LIST_DCN1_0(1), + MPC_COMMON_REG_LIST_DCN1_0(2), + MPC_COMMON_REG_LIST_DCN1_0(3), +}; + +static const struct dcn_mpc_shift mpc_shift = { + MPC_COMMON_MASK_SH_LIST_DCN1_0(__SHIFT) +}; + +static const struct dcn_mpc_mask mpc_mask = { + MPC_COMMON_MASK_SH_LIST_DCN1_0(_MASK), +}; + +#define tg_regs(id)\ +[id] = {TG_COMMON_REG_LIST_DCN1_0(id)} + +static const struct dcn_tg_registers tg_regs[] = { + tg_regs(0), + tg_regs(1), + tg_regs(2), + tg_regs(3), +}; + +static const struct dcn_tg_shift tg_shift = { + TG_COMMON_MASK_SH_LIST_DCN1_0(__SHIFT) +}; + +static const struct dcn_tg_mask tg_mask = { + TG_COMMON_MASK_SH_LIST_DCN1_0(_MASK) +}; + + +static const struct bios_registers bios_regs = { + NBIO_SR(BIOS_SCRATCH_6) +}; + +#define mi_regs(id)\ +[id] = {\ + MI_DCN10_REG_LIST(id)\ +} + + +static const struct dcn_mi_registers mi_regs[] = { + mi_regs(0), + mi_regs(1), + mi_regs(2), + mi_regs(3), +}; + +static const struct dcn_mi_shift mi_shift = { + MI_DCN10_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn_mi_mask mi_mask = { + MI_DCN10_MASK_SH_LIST(_MASK) +}; + +#define clk_src_regs(index, pllid)\ +[index] = {\ + CS_COMMON_REG_LIST_DCN1_0(index, pllid),\ +} + +static const struct dce110_clk_src_regs clk_src_regs[] = { + clk_src_regs(0, A), + clk_src_regs(1, B), + clk_src_regs(2, C), + clk_src_regs(3, D) +}; + +static const struct dce110_clk_src_shift cs_shift = { + CS_COMMON_MASK_SH_LIST_DCN1_0(__SHIFT) +}; + +static const struct dce110_clk_src_mask cs_mask = { + CS_COMMON_MASK_SH_LIST_DCN1_0(_MASK) +}; + + +static const struct resource_caps res_cap = { + .num_timing_generator = 4, + .num_video_plane = 4, + .num_audio = 4, + .num_stream_encoder = 4, + .num_pll = 4, +}; + +static const struct dc_debug debug_defaults_drv = { + .disable_dcc = false, + .disable_dpp_power_gate = false, + .disable_hubp_power_gate = false, + .disable_dmcu = true, + .force_abm_enable = false, + .timing_trace = false, + .disable_pplib_clock_request = true, + .disable_pplib_wm_range = true, +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + .use_dml_wm = false, + .use_max_voltage = true +#endif +}; + +static const struct dc_debug debug_defaults_diags = { + .disable_dpp_power_gate = false, + .disable_hubp_power_gate = false, + .disable_clock_gate = true, + .disable_dmcu = true, + .force_abm_enable = false, + .timing_trace = true, +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + .disable_pplib_clock_request = true, + .disable_pplib_wm_range = true, + .use_dml_wm = false, + .use_max_voltage = false +#endif +}; + +static void dcn10_transform_destroy(struct transform **xfm) +{ + dm_free(TO_DCN10_TRANSFORM(*xfm)); + *xfm = NULL; +} + +static struct transform *dcn10_transform_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn10_transform *transform = + dm_alloc(sizeof(struct dcn10_transform)); + + if (!transform) + return NULL; + + if (dcn10_transform_construct(transform, ctx, + &tf_regs[inst], &tf_shift, &tf_mask)) + return &transform->base; + + BREAK_TO_DEBUGGER(); + dm_free(transform); + return NULL; +} + +static struct input_pixel_processor *dcn10_ipp_create( + struct dc_context *ctx, uint32_t inst) +{ + struct dcn10_ipp *ipp = + dm_alloc(sizeof(struct dcn10_ipp)); + + if (!ipp) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dcn10_ipp_construct(ipp, ctx, inst, + &ipp_regs[inst], &ipp_shift, &ipp_mask); + return &ipp->base; +} + + +static struct output_pixel_processor *dcn10_opp_create( + struct dc_context *ctx, uint32_t inst) +{ + struct dcn10_opp *opp = + dm_alloc(sizeof(struct dcn10_opp)); + + if (!opp) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dcn10_opp_construct(opp, ctx, inst, + &opp_regs[inst], &opp_shift, &opp_mask); + return &opp->base; +} + +static struct mpc *dcn10_mpc_create( + struct dc_context *ctx) +{ + struct dcn10_mpc *mpc = dm_alloc(sizeof(struct dcn10_mpc)); + + if (!mpc) + return NULL; + + mpc->base.ctx = ctx; + mpc->mpc_regs = &mpc_regs; + mpc->mpc_shift = &mpc_shift; + mpc->mpc_mask = &mpc_mask; + + return &mpc->base; +} + +static void dcn10_mpc_destroy(struct mpc **mpc_base) +{ + if (*mpc_base) + dm_free(TO_DCN10_MPC(*mpc_base)); + + *mpc_base = NULL; +} + +static struct timing_generator *dcn10_timing_generator_create( + struct dc_context *ctx, + uint32_t instance) +{ + struct dcn10_timing_generator *tgn10 = + dm_alloc(sizeof(struct dcn10_timing_generator)); + + if (!tgn10) + return NULL; + + tgn10->base.inst = instance; + tgn10->base.ctx = ctx; + + tgn10->tg_regs = &tg_regs[instance]; + tgn10->tg_shift = &tg_shift; + tgn10->tg_mask = &tg_mask; + + dcn10_timing_generator_init(tgn10); + + return &tgn10->base; +} + +static const struct encoder_feature_support link_enc_feature = { + .max_hdmi_deep_color = COLOR_DEPTH_121212, + .max_hdmi_pixel_clock = 600000, + .ycbcr420_supported = true, + .flags.bits.IS_HBR2_CAPABLE = true, + .flags.bits.IS_HBR3_CAPABLE = true, + .flags.bits.IS_TPS3_CAPABLE = true, + .flags.bits.IS_TPS4_CAPABLE = true, + .flags.bits.IS_YCBCR_CAPABLE = true +}; + +struct link_encoder *dcn10_link_encoder_create( + const struct encoder_init_data *enc_init_data) +{ + struct dce110_link_encoder *enc110 = + dm_alloc(sizeof(struct dce110_link_encoder)); + + if (!enc110) + return NULL; + + if (dce110_link_encoder_construct( + enc110, + enc_init_data, + &link_enc_feature, + &link_enc_regs[enc_init_data->transmitter], + &link_enc_aux_regs[enc_init_data->channel - 1], + &link_enc_hpd_regs[enc_init_data->hpd_source])) { + + return &enc110->base; + } + + BREAK_TO_DEBUGGER(); + dm_free(enc110); + return NULL; +} + +struct clock_source *dcn10_clock_source_create( + struct dc_context *ctx, + struct dc_bios *bios, + enum clock_source_id id, + const struct dce110_clk_src_regs *regs, + bool dp_clk_src) +{ + struct dce110_clk_src *clk_src = + dm_alloc(sizeof(struct dce110_clk_src)); + + if (!clk_src) + return NULL; + + if (dce110_clk_src_construct(clk_src, ctx, bios, id, + regs, &cs_shift, &cs_mask)) { + clk_src->base.dp_clk_src = dp_clk_src; + return &clk_src->base; + } + + BREAK_TO_DEBUGGER(); + return NULL; +} + +static void read_dce_straps( + struct dc_context *ctx, + struct resource_straps *straps) +{ + /* TODO: Registers are missing */ + /*REG_GET_2(CC_DC_HDMI_STRAPS, + HDMI_DISABLE, &straps->hdmi_disable, + AUDIO_STREAM_NUMBER, &straps->audio_stream_number); + + REG_GET(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO, &straps->dc_pinstraps_audio);*/ +} + +static struct audio *create_audio( + struct dc_context *ctx, unsigned int inst) +{ + return dce_audio_create(ctx, inst, + &audio_regs[inst], &audio_shift, &audio_mask); +} + +static struct stream_encoder *dcn10_stream_encoder_create( + enum engine_id eng_id, + struct dc_context *ctx) +{ + struct dce110_stream_encoder *enc110 = + dm_alloc(sizeof(struct dce110_stream_encoder)); + + if (!enc110) + return NULL; + + if (dce110_stream_encoder_construct( + enc110, ctx, ctx->dc_bios, eng_id, + &stream_enc_regs[eng_id], &se_shift, &se_mask)) + return &enc110->base; + + BREAK_TO_DEBUGGER(); + dm_free(enc110); + return NULL; +} + +static const struct dce_hwseq_registers hwseq_reg = { + HWSEQ_DCN1_REG_LIST() +}; + +static const struct dce_hwseq_shift hwseq_shift = { + HWSEQ_DCN1_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_hwseq_mask hwseq_mask = { + HWSEQ_DCN1_MASK_SH_LIST(_MASK) +}; + +static struct dce_hwseq *dcn10_hwseq_create( + struct dc_context *ctx) +{ + struct dce_hwseq *hws = dm_alloc(sizeof(struct dce_hwseq)); + + if (hws) { + hws->ctx = ctx; + hws->regs = &hwseq_reg; + hws->shifts = &hwseq_shift; + hws->masks = &hwseq_mask; + } + return hws; +} + +static const struct resource_create_funcs res_create_funcs = { + .read_dce_straps = read_dce_straps, + .create_audio = create_audio, + .create_stream_encoder = dcn10_stream_encoder_create, + .create_hwseq = dcn10_hwseq_create, +}; + +static const struct resource_create_funcs res_create_maximus_funcs = { + .read_dce_straps = NULL, + .create_audio = NULL, + .create_stream_encoder = NULL, + .create_hwseq = dcn10_hwseq_create, +}; + +void dcn10_clock_source_destroy(struct clock_source **clk_src) +{ + dm_free(TO_DCE110_CLK_SRC(*clk_src)); + *clk_src = NULL; +} + +static void destruct(struct dcn10_resource_pool *pool) +{ + unsigned int i; + + for (i = 0; i < pool->base.stream_enc_count; i++) { + if (pool->base.stream_enc[i] != NULL) { + /* TODO: free dcn version of stream encoder once implemented + * rather than using virtual stream encoder + */ + dm_free(pool->base.stream_enc[i]); + pool->base.stream_enc[i] = NULL; + } + } + + for (i = 0; i < pool->base.pipe_count; i++) { + if (pool->base.opps[i] != NULL) + pool->base.opps[i]->funcs->opp_destroy(&pool->base.opps[i]); + + if (pool->base.transforms[i] != NULL) + dcn10_transform_destroy(&pool->base.transforms[i]); + + if (pool->base.ipps[i] != NULL) + pool->base.ipps[i]->funcs->ipp_destroy(&pool->base.ipps[i]); + + if (pool->base.mis[i] != NULL) { + dm_free(TO_DCN10_MEM_INPUT(pool->base.mis[i])); + pool->base.mis[i] = NULL; + } + + if (pool->base.irqs != NULL) { + dal_irq_service_destroy(&pool->base.irqs); + } + + if (pool->base.timing_generators[i] != NULL) { + dm_free(DCN10TG_FROM_TG(pool->base.timing_generators[i])); + pool->base.timing_generators[i] = NULL; + } + } + + for (i = 0; i < pool->base.stream_enc_count; i++) { + if (pool->base.stream_enc[i] != NULL) + dm_free(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); + } + + for (i = 0; i < pool->base.audio_count; i++) { + if (pool->base.audios[i]) + dce_aud_destroy(&pool->base.audios[i]); + } + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] != NULL) { + dcn10_clock_source_destroy(&pool->base.clock_sources[i]); + pool->base.clock_sources[i] = NULL; + } + } + + if (pool->base.dp_clock_source != NULL) { + dcn10_clock_source_destroy(&pool->base.dp_clock_source); + pool->base.dp_clock_source = NULL; + } + + if (pool->base.mpc != NULL) + dcn10_mpc_destroy(&pool->base.mpc); + + if (pool->base.abm != NULL) + dce_abm_destroy(&pool->base.abm); + + if (pool->base.dmcu != NULL) + dce_dmcu_destroy(&pool->base.dmcu); + + if (pool->base.display_clock != NULL) + dce_disp_clk_destroy(&pool->base.display_clock); +} + +static struct mem_input *dcn10_mem_input_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn10_mem_input *mem_inputn10 = + dm_alloc(sizeof(struct dcn10_mem_input)); + + if (!mem_inputn10) + return NULL; + + if (dcn10_mem_input_construct(mem_inputn10, ctx, inst, + &mi_regs[inst], &mi_shift, &mi_mask)) + return &mem_inputn10->base; + + BREAK_TO_DEBUGGER(); + dm_free(mem_inputn10); + return NULL; +} + +static void get_pixel_clock_parameters( + const struct pipe_ctx *pipe_ctx, + struct pixel_clk_params *pixel_clk_params) +{ + const struct core_stream *stream = pipe_ctx->stream; + pixel_clk_params->requested_pix_clk = stream->public.timing.pix_clk_khz; + pixel_clk_params->encoder_object_id = stream->sink->link->link_enc->id; + pixel_clk_params->signal_type = pipe_ctx->stream->signal; + pixel_clk_params->controller_id = pipe_ctx->pipe_idx + 1; + /* TODO: un-hardcode*/ + pixel_clk_params->requested_sym_clk = LINK_RATE_LOW * + LINK_RATE_REF_FREQ_IN_KHZ; + pixel_clk_params->flags.ENABLE_SS = 0; + pixel_clk_params->color_depth = + stream->public.timing.display_color_depth; + pixel_clk_params->flags.DISPLAY_BLANKED = 1; + pixel_clk_params->pixel_encoding = stream->public.timing.pixel_encoding; + + if (stream->public.timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) + pixel_clk_params->color_depth = COLOR_DEPTH_888; + + if (stream->public.timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) + pixel_clk_params->requested_pix_clk /= 2; + + if (stream->public.timing. timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING || + stream->public.timing. timing_3d_format == TIMING_3D_FORMAT_SW_FRAME_PACKING || + stream->public.timing. timing_3d_format == TIMING_3D_FORMAT_DP_HDMI_INBAND_FA) + pixel_clk_params->requested_pix_clk *= 2; +} + +static void build_clamping_params(struct core_stream *stream) +{ + stream->clamping.clamping_level = CLAMPING_FULL_RANGE; + stream->clamping.c_depth = stream->public.timing.display_color_depth; + stream->clamping.pixel_encoding = stream->public.timing.pixel_encoding; +} + +static enum dc_status build_pipe_hw_param(struct pipe_ctx *pipe_ctx) +{ + + get_pixel_clock_parameters(pipe_ctx, &pipe_ctx->pix_clk_params); + + pipe_ctx->clock_source->funcs->get_pix_clk_dividers( + pipe_ctx->clock_source, + &pipe_ctx->pix_clk_params, + &pipe_ctx->pll_settings); + + pipe_ctx->stream->clamping.pixel_encoding = pipe_ctx->stream->public.timing.pixel_encoding; + + resource_build_bit_depth_reduction_params(pipe_ctx->stream, + &pipe_ctx->stream->bit_depth_params); + build_clamping_params(pipe_ctx->stream); + + return DC_OK; +} + +static enum dc_status validate_mapped_resource( + const struct core_dc *dc, + struct validate_context *context) +{ + enum dc_status status = DC_OK; + uint8_t i, j; + + for (i = 0; i < context->stream_count; i++) { + struct core_stream *stream = context->streams[i]; + struct core_link *link = stream->sink->link; + + if (resource_is_stream_unchanged(dc->current_context, stream)) { + if (stream != NULL && dc->current_context->streams[i] != NULL) { + /* todo: shouldn't have to copy missing parameter here */ + resource_build_bit_depth_reduction_params(stream, + &stream->bit_depth_params); + stream->clamping.pixel_encoding = + stream->public.timing.pixel_encoding; + + resource_build_bit_depth_reduction_params(stream, + &stream->bit_depth_params); + build_clamping_params(stream); + + continue; + } + } + + for (j = 0; j < dc->res_pool->pipe_count ; j++) { + struct pipe_ctx *pipe_ctx = + &context->res_ctx.pipe_ctx[j]; + + if (context->res_ctx.pipe_ctx[j].stream != stream) + continue; + + + if (!pipe_ctx->tg->funcs->validate_timing( + pipe_ctx->tg, &stream->public.timing)) + return DC_FAIL_CONTROLLER_VALIDATE; + + status = build_pipe_hw_param(pipe_ctx); + + if (status != DC_OK) + return status; + + if (!link->link_enc->funcs->validate_output_with_stream( + link->link_enc, pipe_ctx)) + return DC_FAIL_ENC_VALIDATE; + + /* TODO: validate audio ASIC caps, encoder */ + + status = dc_link_validate_mode_timing( + stream, link, &stream->public.timing); + + if (status != DC_OK) + return status; + + + /* do not need to validate non root pipes */ + break; + } + } + + return DC_OK; +} + +enum dc_status dcn10_validate_with_context( + const struct core_dc *dc, + const struct dc_validation_set set[], + int set_count, + struct validate_context *context) +{ + enum dc_status result = DC_OK; + int i; + + if (set_count == 0) + return result; + + for (i = 0; i < set_count; i++) { + context->streams[i] = DC_STREAM_TO_CORE(set[i].stream); + dc_stream_retain(&context->streams[i]->public); + context->stream_count++; + } + + result = resource_map_pool_resources(dc, context); + if (result != DC_OK) + return result; + + result = resource_map_phy_clock_resources(dc, context); + if (result != DC_OK) + return result; + + result = validate_mapped_resource(dc, context); + if (result != DC_OK) + return result; + + if (!resource_validate_attach_surfaces(set, set_count, + dc->current_context, context, dc->res_pool)) + return DC_FAIL_ATTACH_SURFACES; + + result = resource_build_scaling_params_for_context(dc, context); + if (result != DC_OK) + return result; + + if (!dcn_validate_bandwidth(dc, context)) + return DC_FAIL_BANDWIDTH_VALIDATE; + + return result; +} + +enum dc_status dcn10_validate_guaranteed( + const struct core_dc *dc, + const struct dc_stream *dc_stream, + struct validate_context *context) +{ + enum dc_status result = DC_ERROR_UNEXPECTED; + + context->streams[0] = DC_STREAM_TO_CORE(dc_stream); + dc_stream_retain(&context->streams[0]->public); + context->stream_count++; + + result = resource_map_pool_resources(dc, context); + + if (result == DC_OK) + result = resource_map_phy_clock_resources(dc, context); + + if (result == DC_OK) + result = validate_mapped_resource(dc, context); + + if (result == DC_OK) { + validate_guaranteed_copy_streams( + context, dc->public.caps.max_streams); + result = resource_build_scaling_params_for_context(dc, context); + } + if (result == DC_OK && !dcn_validate_bandwidth(dc, context)) + return DC_FAIL_BANDWIDTH_VALIDATE; + + return result; +} + +static struct pipe_ctx *dcn10_acquire_idle_pipe_for_layer( + struct validate_context *context, + const struct resource_pool *pool, + struct core_stream *stream) +{ + struct resource_context *res_ctx = &context->res_ctx; + struct pipe_ctx *head_pipe = resource_get_head_pipe_for_stream(res_ctx, stream); + struct pipe_ctx *idle_pipe = find_idle_secondary_pipe(res_ctx, pool); + + if (!head_pipe) + ASSERT(0); + + if (!idle_pipe) + return false; + + idle_pipe->stream = head_pipe->stream; + idle_pipe->tg = head_pipe->tg; + + idle_pipe->mi = pool->mis[idle_pipe->pipe_idx]; + idle_pipe->ipp = pool->ipps[idle_pipe->pipe_idx]; + idle_pipe->xfm = pool->transforms[idle_pipe->pipe_idx]; + idle_pipe->opp = pool->opps[idle_pipe->pipe_idx]; + + return idle_pipe; +} + +enum dcc_control { + dcc_control__256_256_xxx, + dcc_control__128_128_xxx, + dcc_control__256_64_64, +}; + +enum segment_order { + segment_order__na, + segment_order__contiguous, + segment_order__non_contiguous, +}; + +static bool dcc_support_pixel_format( + enum surface_pixel_format format, + unsigned int *bytes_per_element) +{ + /* DML: get_bytes_per_element */ + switch (format) { + case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: + case SURFACE_PIXEL_FORMAT_GRPH_RGB565: + *bytes_per_element = 2; + return true; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: + case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: + *bytes_per_element = 4; + return true; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: + *bytes_per_element = 8; + return true; + default: + return false; + } +} + +static bool dcc_support_swizzle( + enum swizzle_mode_values swizzle, + unsigned int bytes_per_element, + enum segment_order *segment_order_horz, + enum segment_order *segment_order_vert) +{ + bool standard_swizzle = false; + bool display_swizzle = false; + + switch (swizzle) { + case DC_SW_4KB_S: + case DC_SW_64KB_S: + case DC_SW_VAR_S: + case DC_SW_4KB_S_X: + case DC_SW_64KB_S_X: + case DC_SW_VAR_S_X: + standard_swizzle = true; + break; + case DC_SW_4KB_D: + case DC_SW_64KB_D: + case DC_SW_VAR_D: + case DC_SW_4KB_D_X: + case DC_SW_64KB_D_X: + case DC_SW_VAR_D_X: + display_swizzle = true; + break; + default: + break; + }; + + if (bytes_per_element == 1 && standard_swizzle) { + *segment_order_horz = segment_order__contiguous; + *segment_order_vert = segment_order__na; + return true; + } + if (bytes_per_element == 2 && standard_swizzle) { + *segment_order_horz = segment_order__non_contiguous; + *segment_order_vert = segment_order__contiguous; + return true; + } + if (bytes_per_element == 4 && standard_swizzle) { + *segment_order_horz = segment_order__non_contiguous; + *segment_order_vert = segment_order__contiguous; + return true; + } + if (bytes_per_element == 8 && standard_swizzle) { + *segment_order_horz = segment_order__na; + *segment_order_vert = segment_order__contiguous; + return true; + } + if (bytes_per_element == 8 && display_swizzle) { + *segment_order_horz = segment_order__contiguous; + *segment_order_vert = segment_order__non_contiguous; + return true; + } + + return false; +} + +static void get_blk256_size(unsigned int *blk256_width, unsigned int *blk256_height, + unsigned int bytes_per_element) +{ + /* copied from DML. might want to refactor DML to leverage from DML */ + /* DML : get_blk256_size */ + if (bytes_per_element == 1) { + *blk256_width = 16; + *blk256_height = 16; + } else if (bytes_per_element == 2) { + *blk256_width = 16; + *blk256_height = 8; + } else if (bytes_per_element == 4) { + *blk256_width = 8; + *blk256_height = 8; + } else if (bytes_per_element == 8) { + *blk256_width = 8; + *blk256_height = 4; + } +} + +static void det_request_size( + unsigned int height, + unsigned int width, + unsigned int bpe, + bool *req128_horz_wc, + bool *req128_vert_wc) +{ + unsigned int detile_buf_size = 164 * 1024; /* 164KB for DCN1.0 */ + + unsigned int blk256_height = 0; + unsigned int blk256_width = 0; + unsigned int swath_bytes_horz_wc, swath_bytes_vert_wc; + + get_blk256_size(&blk256_width, &blk256_height, bpe); + + swath_bytes_horz_wc = height * blk256_height * bpe; + swath_bytes_vert_wc = width * blk256_width * bpe; + + *req128_horz_wc = (2 * swath_bytes_horz_wc <= detile_buf_size) ? + false : /* full 256B request */ + true; /* half 128b request */ + + *req128_vert_wc = (2 * swath_bytes_vert_wc <= detile_buf_size) ? + false : /* full 256B request */ + true; /* half 128b request */ +} + +static bool get_dcc_compression_cap(const struct dc *dc, + const struct dc_dcc_surface_param *input, + struct dc_surface_dcc_cap *output) +{ + /* implement section 1.6.2.1 of DCN1_Programming_Guide.docx */ + enum dcc_control dcc_control; + unsigned int bpe; + enum segment_order segment_order_horz, segment_order_vert; + bool req128_horz_wc, req128_vert_wc; + + memset(output, 0, sizeof(*output)); + + if (dc->debug.disable_dcc) + return false; + + if (!dcc_support_pixel_format(input->format, + &bpe)) + return false; + + if (!dcc_support_swizzle(input->swizzle_mode, bpe, + &segment_order_horz, &segment_order_vert)) + return false; + + det_request_size(input->surface_size.height, input->surface_size.width, + bpe, &req128_horz_wc, &req128_vert_wc); + + if (!req128_horz_wc && !req128_vert_wc) { + dcc_control = dcc_control__256_256_xxx; + } else if (input->scan == SCAN_DIRECTION_HORIZONTAL) { + if (!req128_horz_wc) + dcc_control = dcc_control__256_256_xxx; + else if (segment_order_horz == segment_order__contiguous) + dcc_control = dcc_control__128_128_xxx; + else + dcc_control = dcc_control__256_64_64; + } else if (input->scan == SCAN_DIRECTION_VERTICAL) { + if (!req128_vert_wc) + dcc_control = dcc_control__256_256_xxx; + else if (segment_order_vert == segment_order__contiguous) + dcc_control = dcc_control__128_128_xxx; + else + dcc_control = dcc_control__256_64_64; + } else { + if ((req128_horz_wc && + segment_order_horz == segment_order__non_contiguous) || + (req128_vert_wc && + segment_order_vert == segment_order__non_contiguous)) + /* access_dir not known, must use most constraining */ + dcc_control = dcc_control__256_64_64; + else + /* reg128 is true for either horz and vert + * but segment_order is contiguous + */ + dcc_control = dcc_control__128_128_xxx; + } + + switch (dcc_control) { + case dcc_control__256_256_xxx: + output->grph.rgb.max_uncompressed_blk_size = 256; + output->grph.rgb.max_compressed_blk_size = 256; + output->grph.rgb.independent_64b_blks = false; + break; + case dcc_control__128_128_xxx: + output->grph.rgb.max_uncompressed_blk_size = 128; + output->grph.rgb.max_compressed_blk_size = 128; + output->grph.rgb.independent_64b_blks = false; + break; + case dcc_control__256_64_64: + output->grph.rgb.max_uncompressed_blk_size = 256; + output->grph.rgb.max_compressed_blk_size = 64; + output->grph.rgb.independent_64b_blks = true; + break; + } + output->capable = true; + output->const_color_support = false; + + return true; +} + + +static void dcn10_destroy_resource_pool(struct resource_pool **pool) +{ + struct dcn10_resource_pool *dcn10_pool = TO_DCN10_RES_POOL(*pool); + + destruct(dcn10_pool); + dm_free(dcn10_pool); + *pool = NULL; +} + + +static struct dc_cap_funcs cap_funcs = { + .get_dcc_compression_cap = get_dcc_compression_cap +}; + +static struct resource_funcs dcn10_res_pool_funcs = { + .destroy = dcn10_destroy_resource_pool, + .link_enc_create = dcn10_link_encoder_create, + .validate_with_context = dcn10_validate_with_context, + .validate_guaranteed = dcn10_validate_guaranteed, + .validate_bandwidth = dcn_validate_bandwidth, + .acquire_idle_pipe_for_layer = dcn10_acquire_idle_pipe_for_layer, +}; + +static bool construct( + uint8_t num_virtual_links, + struct core_dc *dc, + struct dcn10_resource_pool *pool) +{ + int i; + struct dc_context *ctx = dc->ctx; + + ctx->dc_bios->regs = &bios_regs; + + pool->base.res_cap = &res_cap; + pool->base.funcs = &dcn10_res_pool_funcs; + + /* + * TODO fill in from actual raven resource when we create + * more than virtual encoder + */ + + /************************************************* + * Resource + asic cap harcoding * + *************************************************/ + pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + + /* TODO: Hardcode to correct number of functional controllers */ + pool->base.pipe_count = 4; + dc->public.caps.max_downscale_ratio = 200; + dc->public.caps.i2c_speed_in_khz = 100; + dc->public.caps.max_cursor_size = 256; + + if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) + dc->public.debug = debug_defaults_drv; + else + dc->public.debug = debug_defaults_diags; + + /************************************************* + * Create resources * + *************************************************/ + + pool->base.clock_sources[DCN10_CLK_SRC_PLL0] = + dcn10_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL0, + &clk_src_regs[0], false); + pool->base.clock_sources[DCN10_CLK_SRC_PLL1] = + dcn10_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL1, + &clk_src_regs[1], false); + pool->base.clock_sources[DCN10_CLK_SRC_PLL2] = + dcn10_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL2, + &clk_src_regs[2], false); + pool->base.clock_sources[DCN10_CLK_SRC_PLL3] = + dcn10_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL3, + &clk_src_regs[3], false); + + pool->base.clk_src_count = DCN10_CLK_SRC_TOTAL; + + pool->base.dp_clock_source = + dcn10_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_ID_DP_DTO, + /* todo: not reuse phy_pll registers */ + &clk_src_regs[0], true); + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] == NULL) { + dm_error("DC: failed to create clock sources!\n"); + BREAK_TO_DEBUGGER(); + goto clock_source_create_fail; + } + } + + if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { + pool->base.display_clock = dce120_disp_clk_create(ctx, + &disp_clk_regs, + &disp_clk_shift, + &disp_clk_mask); + if (pool->base.display_clock == NULL) { + dm_error("DC: failed to create display clock!\n"); + BREAK_TO_DEBUGGER(); + goto disp_clk_create_fail; + } + } + + pool->base.dmcu = dcn10_dmcu_create(ctx, + &dmcu_regs, + &dmcu_shift, + &dmcu_mask); + if (pool->base.dmcu == NULL) { + dm_error("DC: failed to create dmcu!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + pool->base.abm = dce_abm_create(ctx, + &abm_regs, + &abm_shift, + &abm_mask); + if (pool->base.abm == NULL) { + dm_error("DC: failed to create abm!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + dml_init_instance(&dc->dml, DML_PROJECT_RAVEN1); + dc->dcn_ip = dcn10_ip_defaults; + dc->dcn_soc = dcn10_soc_defaults; + if (!dc->public.debug.disable_pplib_clock_request) + dcn_bw_update_from_pplib(dc); + dcn_bw_sync_calcs_and_dml(dc); + if (!dc->public.debug.disable_pplib_wm_range) + dcn_bw_notify_pplib_of_wm_ranges(dc); + + { + #if defined(CONFIG_DRM_AMD_DC_DCN1_0) + struct irq_service_init_data init_data; + init_data.ctx = dc->ctx; + pool->base.irqs = dal_irq_service_dcn10_create(&init_data); + if (!pool->base.irqs) + goto irqs_create_fail; + #endif + } + + /* mem input -> ipp -> transform -> opp -> TG */ + for (i = 0; i < pool->base.pipe_count; i++) { + pool->base.mis[i] = dcn10_mem_input_create(ctx, i); + if (pool->base.mis[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create memory input!\n"); + goto mi_create_fail; + } + + pool->base.ipps[i] = dcn10_ipp_create(ctx, i); + if (pool->base.ipps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create input pixel processor!\n"); + goto ipp_create_fail; + } + + pool->base.transforms[i] = dcn10_transform_create(ctx, i); + if (pool->base.transforms[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create transform!\n"); + goto transform_create_fail; + } + + pool->base.opps[i] = dcn10_opp_create(ctx, i); + if (pool->base.opps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create output pixel processor!\n"); + goto opp_create_fail; + } + + pool->base.timing_generators[i] = dcn10_timing_generator_create( + ctx, i); + if (pool->base.timing_generators[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create tg!\n"); + goto otg_create_fail; + } + } + + pool->base.mpc = dcn10_mpc_create(ctx); + + if (!resource_construct(num_virtual_links, dc, &pool->base, + (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) ? + &res_create_funcs : &res_create_maximus_funcs))) + goto res_create_fail; + + dcn10_hw_sequencer_construct(dc); + dc->public.caps.max_surfaces = pool->base.pipe_count; + + dc->public.cap_funcs = cap_funcs; + + return true; + +disp_clk_create_fail: +otg_create_fail: +opp_create_fail: +transform_create_fail: +ipp_create_fail: +mi_create_fail: +irqs_create_fail: +res_create_fail: +clock_source_create_fail: + + destruct(pool); + + return false; +} + +struct resource_pool *dcn10_create_resource_pool( + uint8_t num_virtual_links, + struct core_dc *dc) +{ + struct dcn10_resource_pool *pool = + dm_alloc(sizeof(struct dcn10_resource_pool)); + + if (!pool) + return NULL; + + if (construct(num_virtual_links, dc, pool)) + return &pool->base; + + BREAK_TO_DEBUGGER(); + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.h new file mode 100644 index 000000000000..5f84dbd0bdea --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.h @@ -0,0 +1,47 @@ +/* +* Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_RESOURCE_DCN10_H__ +#define __DC_RESOURCE_DCN10_H__ + +#include "core_types.h" + +#define TO_DCN10_RES_POOL(pool)\ + container_of(pool, struct dcn10_resource_pool, base) + +struct core_dc; +struct resource_pool; +struct _vcs_dpi_display_pipe_params_st; + +struct dcn10_resource_pool { + struct resource_pool base; +}; +struct resource_pool *dcn10_create_resource_pool( + uint8_t num_virtual_links, + struct core_dc *dc); + + +#endif /* __DC_RESOURCE_DCN10_H__ */ + diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c new file mode 100644 index 000000000000..d7072132d456 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c @@ -0,0 +1,1202 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "reg_helper.h" +#include "dcn10_timing_generator.h" + +#define REG(reg)\ + tgn10->tg_regs->reg + +#define CTX \ + tgn10->base.ctx + +#undef FN +#define FN(reg_name, field_name) \ + tgn10->tg_shift->field_name, tgn10->tg_mask->field_name + +#define STATIC_SCREEN_EVENT_MASK_RANGETIMING_DOUBLE_BUFFER_UPDATE_EN 0x100 + +/** +* apply_front_porch_workaround TODO FPGA still need? +* +* This is a workaround for a bug that has existed since R5xx and has not been +* fixed keep Front porch at minimum 2 for Interlaced mode or 1 for progressive. +*/ +static void tg_apply_front_porch_workaround( + struct timing_generator *tg, + struct dc_crtc_timing *timing) +{ + if (timing->flags.INTERLACE == 1) { + if (timing->v_front_porch < 2) + timing->v_front_porch = 2; + } else { + if (timing->v_front_porch < 1) + timing->v_front_porch = 1; + } +} + +static void dcn10_program_global_sync( + struct timing_generator *tg) +{ + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + + if (tg->dlg_otg_param.vstartup_start == 0) { + BREAK_TO_DEBUGGER(); + return; + } + + REG_SET(OTG_VSTARTUP_PARAM, 0, + VSTARTUP_START, tg->dlg_otg_param.vstartup_start); + + REG_SET_2(OTG_VUPDATE_PARAM, 0, + VUPDATE_OFFSET, tg->dlg_otg_param.vupdate_offset, + VUPDATE_WIDTH, tg->dlg_otg_param.vupdate_width); + + REG_SET(OTG_VREADY_PARAM, 0, + VREADY_OFFSET, tg->dlg_otg_param.vready_offset); +} + +struct crtc_stereo_flags { + uint8_t PROGRAM_STEREO :1; + uint8_t PROGRAM_POLARITY :1; + uint8_t RIGHT_EYE_POLARITY :1; + uint8_t FRAME_PACKED :1; + uint8_t DISABLE_STEREO_DP_SYNC :1; +}; + +static void dcn10_enable_stereo(struct timing_generator *tg, + const struct crtc_stereo_flags *flags, + const struct dc_crtc_timing *timing) +{ + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + + uint32_t active_width = timing->h_addressable; + uint32_t space1_size = timing->v_total - timing->v_addressable; + + if (flags) { + uint32_t stereo_en = flags->FRAME_PACKED == 0 ? 1 : 0; + + if (flags->PROGRAM_STEREO) + REG_UPDATE_3(OTG_STEREO_CONTROL, + OTG_STEREO_EN, stereo_en, + OTG_STEREO_SYNC_OUTPUT_LINE_NUM, 0, + OTG_STEREO_SYNC_OUTPUT_POLARITY, 0); + + if (flags->PROGRAM_POLARITY) + REG_UPDATE(OTG_STEREO_CONTROL, + OTG_STEREO_EYE_FLAG_POLARITY, + flags->RIGHT_EYE_POLARITY == 0 ? 0:1); + + if (flags->DISABLE_STEREO_DP_SYNC) + REG_UPDATE(OTG_STEREO_CONTROL, + OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP, 1); + + if (flags->PROGRAM_STEREO && flags->FRAME_PACKED) + REG_UPDATE_3(OTG_3D_STRUCTURE_CONTROL, + OTG_3D_STRUCTURE_EN, 1, + OTG_3D_STRUCTURE_V_UPDATE_MODE, 1, + OTG_3D_STRUCTURE_STEREO_SEL_OVR, 1); + + } + + REG_UPDATE(OPPBUF_CONTROL, + OPPBUF_ACTIVE_WIDTH, active_width); + + REG_UPDATE(OPPBUF_3D_PARAMETERS_0, + OPPBUF_3D_VACT_SPACE1_SIZE, space1_size); + + return; +} + +static void dcn10_disable_stereo(struct timing_generator *tg) +{ + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + + REG_SET(OTG_STEREO_CONTROL, 0, + OTG_STEREO_EN, 0); + + REG_SET_3(OTG_3D_STRUCTURE_CONTROL, 0, + OTG_3D_STRUCTURE_EN, 0, + OTG_3D_STRUCTURE_V_UPDATE_MODE, 0, + OTG_3D_STRUCTURE_STEREO_SEL_OVR, 0); + + REG_UPDATE(OPPBUF_CONTROL, + OPPBUF_ACTIVE_WIDTH, 0); + REG_UPDATE(OPPBUF_3D_PARAMETERS_0, + OPPBUF_3D_VACT_SPACE1_SIZE, 0); + return; +} + +static bool is_frame_alternate_stereo(enum dc_timing_3d_format fmt) +{ + bool ret = false; + if (fmt == TIMING_3D_FORMAT_FRAME_ALTERNATE || + fmt == TIMING_3D_FORMAT_INBAND_FA || + fmt == TIMING_3D_FORMAT_DP_HDMI_INBAND_FA || + fmt == TIMING_3D_FORMAT_SIDEBAND_FA) + ret = true; + return ret; +} + +static void dcn10_do_stereo(struct timing_generator *tg, + const struct dc_crtc_timing *dc_crtc_timing) +{ + struct crtc_stereo_flags stereo_flags = {0}; + if (dc_crtc_timing->timing_3d_format == TIMING_3D_FORMAT_NONE || + dc_crtc_timing->timing_3d_format == TIMING_3D_FORMAT_SIDE_BY_SIDE || + dc_crtc_timing->timing_3d_format == TIMING_3D_FORMAT_TOP_AND_BOTTOM) + dcn10_disable_stereo(tg); + else { + stereo_flags.PROGRAM_STEREO = 1; + stereo_flags.PROGRAM_POLARITY = 1; + stereo_flags.DISABLE_STEREO_DP_SYNC = 0; + stereo_flags.RIGHT_EYE_POLARITY = + dc_crtc_timing->flags.RIGHT_EYE_3D_POLARITY; + if (dc_crtc_timing->timing_3d_format == + TIMING_3D_FORMAT_HW_FRAME_PACKING) + stereo_flags.FRAME_PACKED = 1; + + if (is_frame_alternate_stereo( + dc_crtc_timing->timing_3d_format) || + dc_crtc_timing->timing_3d_format == + TIMING_3D_FORMAT_HW_FRAME_PACKING) + dcn10_enable_stereo(tg, &stereo_flags, dc_crtc_timing); + } +} + +/** + * program_timing_generator used by mode timing set + * Program CRTC Timing Registers - OTG_H_*, OTG_V_*, Pixel repetition. + * Including SYNC. Call BIOS command table to program Timings. + */ +static void tg_program_timing_generator( + struct timing_generator *tg, + const struct dc_crtc_timing *dc_crtc_timing) +{ + struct dc_crtc_timing patched_crtc_timing; + uint32_t vesa_sync_start; + uint32_t asic_blank_end; + uint32_t asic_blank_start; + uint32_t v_total; + uint32_t v_sync_end; + uint32_t v_init, v_fp2; + uint32_t h_sync_polarity, v_sync_polarity; + uint32_t interlace_factor; + uint32_t start_point = 0; + uint32_t field_num = 0; + uint32_t h_div_2; + + + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + + patched_crtc_timing = *dc_crtc_timing; + tg_apply_front_porch_workaround(tg, &patched_crtc_timing); + + /* Load horizontal timing */ + + /* CRTC_H_TOTAL = vesa.h_total - 1 */ + REG_SET(OTG_H_TOTAL, 0, + OTG_H_TOTAL, patched_crtc_timing.h_total - 1); + + /* h_sync_start = 0, h_sync_end = vesa.h_sync_width */ + REG_UPDATE_2(OTG_H_SYNC_A, + OTG_H_SYNC_A_START, 0, + OTG_H_SYNC_A_END, patched_crtc_timing.h_sync_width); + + /* asic_h_blank_end = HsyncWidth + HbackPorch = + * vesa. usHorizontalTotal - vesa. usHorizontalSyncStart - + * vesa.h_left_border + */ + vesa_sync_start = patched_crtc_timing.h_addressable + + patched_crtc_timing.h_border_right + + patched_crtc_timing.h_front_porch; + + asic_blank_end = patched_crtc_timing.h_total - + vesa_sync_start - + patched_crtc_timing.h_border_left; + + /* h_blank_start = v_blank_end + v_active */ + asic_blank_start = asic_blank_end + + patched_crtc_timing.h_border_left + + patched_crtc_timing.h_addressable + + patched_crtc_timing.h_border_right; + + REG_UPDATE_2(OTG_H_BLANK_START_END, + OTG_H_BLANK_START, asic_blank_start, + OTG_H_BLANK_END, asic_blank_end); + + /* h_sync polarity */ + h_sync_polarity = patched_crtc_timing.flags.HSYNC_POSITIVE_POLARITY ? + 0 : 1; + + REG_UPDATE(OTG_H_SYNC_A_CNTL, + OTG_H_SYNC_A_POL, h_sync_polarity); + + /* Load vertical timing */ + + /* CRTC_V_TOTAL = v_total - 1 */ + if (patched_crtc_timing.flags.INTERLACE) { + interlace_factor = 2; + v_total = 2 * patched_crtc_timing.v_total; + } else { + interlace_factor = 1; + v_total = patched_crtc_timing.v_total - 1; + } + REG_SET(OTG_V_TOTAL, 0, + OTG_V_TOTAL, v_total); + + /* v_sync_start = 0, v_sync_end = v_sync_width */ + v_sync_end = patched_crtc_timing.v_sync_width * interlace_factor; + + REG_UPDATE_2(OTG_V_SYNC_A, + OTG_V_SYNC_A_START, 0, + OTG_V_SYNC_A_END, v_sync_end); + + vesa_sync_start = patched_crtc_timing.v_addressable + + patched_crtc_timing.v_border_bottom + + patched_crtc_timing.v_front_porch; + + asic_blank_end = (patched_crtc_timing.v_total - + vesa_sync_start - + patched_crtc_timing.v_border_top) + * interlace_factor; + + /* v_blank_start = v_blank_end + v_active */ + asic_blank_start = asic_blank_end + + (patched_crtc_timing.v_border_top + + patched_crtc_timing.v_addressable + + patched_crtc_timing.v_border_bottom) + * interlace_factor; + + REG_UPDATE_2(OTG_V_BLANK_START_END, + OTG_V_BLANK_START, asic_blank_start, + OTG_V_BLANK_END, asic_blank_end); + + + /* v_sync polarity */ + v_sync_polarity = patched_crtc_timing.flags.VSYNC_POSITIVE_POLARITY ? + 0 : 1; + + REG_UPDATE(OTG_V_SYNC_A_CNTL, + OTG_V_SYNC_A_POL, v_sync_polarity); + + v_init = asic_blank_start; + if (tg->dlg_otg_param.signal == SIGNAL_TYPE_DISPLAY_PORT || + tg->dlg_otg_param.signal == SIGNAL_TYPE_DISPLAY_PORT_MST || + tg->dlg_otg_param.signal == SIGNAL_TYPE_EDP) { + v_init = asic_blank_start; + start_point = 1; + if (patched_crtc_timing.flags.INTERLACE == 1) + field_num = 1; + } + if (v_init < 0) + v_init = 0; + v_fp2 = 0; + if (tg->dlg_otg_param.vstartup_start > asic_blank_end) + v_fp2 = tg->dlg_otg_param.vstartup_start > asic_blank_end; + + /* Interlace */ + if (patched_crtc_timing.flags.INTERLACE == 1) { + REG_UPDATE(OTG_INTERLACE_CONTROL, + OTG_INTERLACE_ENABLE, 1); + v_init = v_init / 2; + if ((tg->dlg_otg_param.vstartup_start/2)*2 > asic_blank_end) + v_fp2 = v_fp2 / 2; + } + else + REG_UPDATE(OTG_INTERLACE_CONTROL, + OTG_INTERLACE_ENABLE, 0); + + + /* VTG enable set to 0 first VInit */ + REG_UPDATE(CONTROL, + VTG0_ENABLE, 0); + + REG_UPDATE_2(CONTROL, + VTG0_FP2, v_fp2, + VTG0_VCOUNT_INIT, v_init); + + /* original code is using VTG offset to address OTG reg, seems wrong */ + REG_UPDATE_2(OTG_CONTROL, + OTG_START_POINT_CNTL, start_point, + OTG_FIELD_NUMBER_CNTL, field_num); + + dcn10_program_global_sync(tg); + + /* TODO + * patched_crtc_timing.flags.HORZ_COUNT_BY_TWO == 1 + * program_horz_count_by_2 + * for DVI 30bpp mode, 0 otherwise + * program_horz_count_by_2(tg, &patched_crtc_timing); + */ + + /* Enable stereo - only when we need to pack 3D frame. Other types + * of stereo handled in explicit call + */ + h_div_2 = (dc_crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) ? + 1 : 0; + + REG_UPDATE(OTG_H_TIMING_CNTL, + OTG_H_TIMING_DIV_BY2, h_div_2); + + /* Enable crtc stereo frame pack tested... todo more + */ + dcn10_do_stereo(tg, &patched_crtc_timing); +} + +/** tg_program_blanking + * Only programmed part of OTG_H, OTG_V register for set_plane_config + * Assume other OTG registers are programmed by video mode set already. + * This function is for underlay. DCN will have new sequence. + * This function will be removed. Need remove it from set_plane_config + */ + +static void tg_program_timing(struct timing_generator *tg, + const struct dc_crtc_timing *timing, + bool use_vbios) +{ + tg_program_timing_generator(tg, timing); +} + +/** + * unblank_crtc + * Call ASIC Control Object to UnBlank CRTC. + */ +static void tg_unblank_crtc(struct timing_generator *tg) +{ + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + + REG_UPDATE_2(OTG_BLANK_CONTROL, + OTG_BLANK_DATA_EN, 0, + OTG_BLANK_DE_MODE, 0); +} + +/** + * blank_crtc + * Call ASIC Control Object to Blank CRTC. + */ + +static void tg_blank_crtc(struct timing_generator *tg) +{ + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + + REG_UPDATE_2(OTG_BLANK_CONTROL, + OTG_BLANK_DATA_EN, 1, + OTG_BLANK_DE_MODE, 0); + + /* todo: why are we waiting for BLANK_DATA_EN? shouldn't we be waiting + * for status? + */ + REG_WAIT(OTG_BLANK_CONTROL, + OTG_BLANK_DATA_EN, 1, + 20000, 200000); + + REG_UPDATE(OTG_DOUBLE_BUFFER_CONTROL, + OTG_BLANK_DATA_DOUBLE_BUFFER_EN, 0); +} + +static void tg_set_blank(struct timing_generator *tg, + bool enable_blanking) +{ + if (enable_blanking) + tg_blank_crtc(tg); + else + tg_unblank_crtc(tg); +} + +static bool tg_is_blanked(struct timing_generator *tg) +{ + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + uint32_t blank_en; + uint32_t blank_state; + + REG_GET_2(OTG_BLANK_CONTROL, + OTG_BLANK_DATA_EN, &blank_en, + OTG_CURRENT_BLANK_STATE, &blank_state); + + return blank_en && blank_state; +} + +static void enable_optc_clock(struct timing_generator *tg, bool enable) +{ + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + + if (enable) { + REG_UPDATE(OPTC_INPUT_CLOCK_CONTROL, + OPTC_INPUT_CLK_EN, 1); + + REG_WAIT(OPTC_INPUT_CLOCK_CONTROL, + OPTC_INPUT_CLK_ON, 1, + 20000, 200000); + + /* Enable clock */ + REG_UPDATE(OTG_CLOCK_CONTROL, + OTG_CLOCK_EN, 1); + + REG_WAIT(OTG_CLOCK_CONTROL, + OTG_CLOCK_ON, 1, + 20000, 200000); + } else { + REG_UPDATE_2(OTG_CLOCK_CONTROL, + OTG_CLOCK_GATE_DIS, 0, + OTG_CLOCK_EN, 0); + + REG_WAIT(OTG_CLOCK_CONTROL, + OTG_CLOCK_ON, 0, + 20000, 200000); + + REG_UPDATE_2(OPTC_INPUT_CLOCK_CONTROL, + OPTC_INPUT_CLK_GATE_DIS, 0, + OPTC_INPUT_CLK_EN, 0); + + REG_WAIT(OPTC_INPUT_CLOCK_CONTROL, + OPTC_INPUT_CLK_ON, 0, + 20000, 200000); + } +} + +/** + * Enable CRTC + * Enable CRTC - call ASIC Control Object to enable Timing generator. + */ +static bool tg_enable_crtc(struct timing_generator *tg) +{ + /* TODO FPGA wait for answer + * OTG_MASTER_UPDATE_MODE != CRTC_MASTER_UPDATE_MODE + * OTG_MASTER_UPDATE_LOCK != CRTC_MASTER_UPDATE_LOCK + */ + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + + /* opp instance for OTG. For DCN1.0, ODM is remoed. + * OPP and OPTC should 1:1 mapping + */ + REG_UPDATE(OPTC_DATA_SOURCE_SELECT, + OPTC_SRC_SEL, tg->inst); + + /* VTG enable first is for HW workaround */ + REG_UPDATE(CONTROL, + VTG0_ENABLE, 1); + + /* Enable CRTC */ + REG_UPDATE_2(OTG_CONTROL, + OTG_DISABLE_POINT_CNTL, 3, + OTG_MASTER_EN, 1); + + return true; +} + +/* disable_crtc - call ASIC Control Object to disable Timing generator. */ +static bool tg_disable_crtc(struct timing_generator *tg) +{ + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + + /* disable otg request until end of the first line + * in the vertical blank region + */ + REG_UPDATE_2(OTG_CONTROL, + OTG_DISABLE_POINT_CNTL, 3, + OTG_MASTER_EN, 0); + + REG_UPDATE(CONTROL, + VTG0_ENABLE, 0); + + /* CRTC disabled, so disable clock. */ + REG_WAIT(OTG_CLOCK_CONTROL, + OTG_BUSY, 0, + 2000, 20000); + + return true; +} + + +static void tg_program_blank_color( + struct timing_generator *tg, + const struct tg_color *black_color) +{ + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + + REG_SET_3(OTG_BLACK_COLOR, 0, + OTG_BLACK_COLOR_B_CB, black_color->color_b_cb, + OTG_BLACK_COLOR_G_Y, black_color->color_g_y, + OTG_BLACK_COLOR_R_CR, black_color->color_r_cr); +} + +/** + * dcn10_dcn10_timing_generator_disable_vga + * Turn OFF VGA Mode and Timing - DxVGA_CONTROL + * VGA Mode and VGA Timing is used by VBIOS on CRT Monitors; + */ +/* TODO FPGA FPGA setup is done by Diag which does not enable VGA mode. + * VGA is disable by ASIC default. This function is not needed for + * FPGA story. + * usage: + * init_hw within dc.c + * disable_vga_and_power_gate_all_controllers within dce110_hw_sequencer.c + * We may move init_hw into DC specific so that we can remove + * .disable_vga from upper layer stack + */ +static void dcn10_timing_generator_disable_vga( + struct timing_generator *tg) +{ + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + + switch (tgn10->base.inst) { + case 0: + REG_WRITE(D1VGA_CONTROL, 0); + break; + case 1: + REG_WRITE(D2VGA_CONTROL, 0); + break; + case 2: + REG_WRITE(D2VGA_CONTROL, 0); + break; + case 3: + REG_WRITE(D4VGA_CONTROL, 0); + break; + default: + break; + } +} + +static bool tg_validate_timing( + struct timing_generator *tg, + const struct dc_crtc_timing *timing) +{ + uint32_t interlace_factor; + uint32_t v_blank; + uint32_t h_blank; + uint32_t min_v_blank; + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + + ASSERT(timing != NULL); + + interlace_factor = timing->flags.INTERLACE ? 2 : 1; + v_blank = (timing->v_total - timing->v_addressable - + timing->v_border_top - timing->v_border_bottom) * + interlace_factor; + + h_blank = (timing->h_total - timing->h_addressable - + timing->h_border_right - + timing->h_border_left); + + if (timing->timing_3d_format != TIMING_3D_FORMAT_NONE && + timing->timing_3d_format != TIMING_3D_FORMAT_HW_FRAME_PACKING && + timing->timing_3d_format != TIMING_3D_FORMAT_TOP_AND_BOTTOM && + timing->timing_3d_format != TIMING_3D_FORMAT_SIDE_BY_SIDE && + timing->timing_3d_format != TIMING_3D_FORMAT_FRAME_ALTERNATE) + return false; + + /* Temporarily blocking interlacing mode until it's supported */ + if (timing->flags.INTERLACE == 1) + return false; + + /* Check maximum number of pixels supported by Timing Generator + * (Currently will never fail, in order to fail needs display which + * needs more than 8192 horizontal and + * more than 8192 vertical total pixels) + */ + if (timing->h_total > tgn10->max_h_total || + timing->v_total > tgn10->max_v_total) + return false; + + + if (h_blank < tgn10->min_h_blank) + return false; + + if (timing->h_sync_width < tgn10->min_h_sync_width || + timing->v_sync_width < tgn10->min_v_sync_width) + return false; + + min_v_blank = timing->flags.INTERLACE?tgn10->min_v_blank_interlace:tgn10->min_v_blank; + + if (v_blank < min_v_blank) + return false; + + return true; + +} + +/* + * get_vblank_counter + * + * @brief + * Get counter for vertical blanks. use register CRTC_STATUS_FRAME_COUNT which + * holds the counter of frames. + * + * @param + * struct timing_generator *tg - [in] timing generator which controls the + * desired CRTC + * + * @return + * Counter of frames, which should equal to number of vblanks. + */ +static uint32_t tg_get_vblank_counter(struct timing_generator *tg) +{ + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + uint32_t frame_count; + + REG_GET(OTG_STATUS_FRAME_COUNT, + OTG_FRAME_COUNT, &frame_count); + + return frame_count; +} + +void dcn10_lock(struct timing_generator *tg) +{ + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + + REG_SET(OTG_MASTER_UPDATE_LOCK, 0, + OTG_MASTER_UPDATE_LOCK, 1); +} + +void dcn10_unlock(struct timing_generator *tg) +{ + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + + REG_SET(OTG_MASTER_UPDATE_LOCK, 0, + OTG_MASTER_UPDATE_LOCK, 0); + + /* why are we waiting here? */ + REG_WAIT(OTG_DOUBLE_BUFFER_CONTROL, + OTG_UPDATE_PENDING, 0, + 20000, 200000); +} + +static void dcn10_get_position(struct timing_generator *tg, + struct crtc_position *position) +{ + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + + REG_GET_2(OTG_STATUS_POSITION, + OTG_HORZ_COUNT, &position->horizontal_count, + OTG_VERT_COUNT, &position->vertical_count); + + REG_GET(OTG_NOM_VERT_POSITION, + OTG_VERT_COUNT_NOM, &position->nominal_vcount); +} + +bool dcn10_is_counter_moving(struct timing_generator *tg) +{ + struct crtc_position position1, position2; + + tg->funcs->get_position(tg, &position1); + tg->funcs->get_position(tg, &position2); + + if (position1.horizontal_count == position2.horizontal_count && + position1.vertical_count == position2.vertical_count) + return false; + else + return true; +} + +static bool dcn10_did_triggered_reset_occur( + struct timing_generator *tg) +{ + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + uint32_t occurred; + + REG_GET(OTG_FORCE_COUNT_NOW_CNTL, + OTG_FORCE_COUNT_NOW_OCCURRED, &occurred); + + return occurred != 0; +} + +static void dcn10_enable_reset_trigger(struct timing_generator *tg, int source_tg_inst) +{ + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + uint32_t falling_edge; + + REG_GET(OTG_V_SYNC_A_CNTL, + OTG_V_SYNC_A_POL, &falling_edge); + + if (falling_edge) + REG_SET_3(OTG_TRIGA_CNTL, 0, + /* vsync signal from selected OTG pipe based + * on OTG_TRIG_SOURCE_PIPE_SELECT setting + */ + OTG_TRIGA_SOURCE_SELECT, 20, + OTG_TRIGA_SOURCE_PIPE_SELECT, source_tg_inst, + /* always detect falling edge */ + OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, 1); + else + REG_SET_3(OTG_TRIGA_CNTL, 0, + /* vsync signal from selected OTG pipe based + * on OTG_TRIG_SOURCE_PIPE_SELECT setting + */ + OTG_TRIGA_SOURCE_SELECT, 20, + OTG_TRIGA_SOURCE_PIPE_SELECT, source_tg_inst, + /* always detect rising edge */ + OTG_TRIGA_RISING_EDGE_DETECT_CNTL, 1); + + REG_SET(OTG_FORCE_COUNT_NOW_CNTL, 0, + /* force H count to H_TOTAL and V count to V_TOTAL in + * progressive mode and V_TOTAL-1 in interlaced mode + */ + OTG_FORCE_COUNT_NOW_MODE, 2); +} + +static void dcn10_disable_reset_trigger(struct timing_generator *tg) +{ + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + + REG_WRITE(OTG_TRIGA_CNTL, 0); + + REG_SET(OTG_FORCE_COUNT_NOW_CNTL, 0, + OTG_FORCE_COUNT_NOW_CLEAR, 1); +} + +static void dcn10_wait_for_state(struct timing_generator *tg, + enum crtc_state state) +{ + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + + switch (state) { + case CRTC_STATE_VBLANK: + REG_WAIT(OTG_STATUS, + OTG_V_BLANK, 1, + 100, 100000); /* 1 vupdate at 10hz */ + break; + + case CRTC_STATE_VACTIVE: + REG_WAIT(OTG_STATUS, + OTG_V_ACTIVE_DISP, 1, + 100, 100000); /* 1 vupdate at 10hz */ + break; + + default: + break; + } +} + +static void set_early_control( + struct timing_generator *tg, + uint32_t early_cntl) +{ + /* asic design change, do not need this control + * empty for share caller logic + */ +} + + +static void set_static_screen_control( + struct timing_generator *tg, + uint32_t value) +{ + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + + /* Bit 8 is no longer applicable in RV for PSR case, + * set bit 8 to 0 if given + */ + if ((value & STATIC_SCREEN_EVENT_MASK_RANGETIMING_DOUBLE_BUFFER_UPDATE_EN) + != 0) + value = value & + ~STATIC_SCREEN_EVENT_MASK_RANGETIMING_DOUBLE_BUFFER_UPDATE_EN; + + REG_SET_2(OTG_STATIC_SCREEN_CONTROL, 0, + OTG_STATIC_SCREEN_EVENT_MASK, value, + OTG_STATIC_SCREEN_FRAME_COUNT, 2); +} + + +/** + ***************************************************************************** + * Function: set_drr + * + * @brief + * Program dynamic refresh rate registers m_OTGx_OTG_V_TOTAL_*. + * + ***************************************************************************** + */ +void dcn10_timing_generator_set_drr( + struct timing_generator *tg, + const struct drr_params *params) +{ + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + + if (params != NULL && + params->vertical_total_max > 0 && + params->vertical_total_min > 0) { + + REG_SET(OTG_V_TOTAL_MAX, 0, + OTG_V_TOTAL_MAX, params->vertical_total_max - 1); + + REG_SET(OTG_V_TOTAL_MIN, 0, + OTG_V_TOTAL_MIN, params->vertical_total_min - 1); + + REG_UPDATE_5(OTG_V_TOTAL_CONTROL, + OTG_V_TOTAL_MIN_SEL, 1, + OTG_V_TOTAL_MAX_SEL, 1, + OTG_FORCE_LOCK_ON_EVENT, 0, + OTG_SET_V_TOTAL_MIN_MASK_EN, 0, + OTG_SET_V_TOTAL_MIN_MASK, 0); + } else { + REG_SET(OTG_V_TOTAL_MIN, 0, + OTG_V_TOTAL_MIN, 0); + + REG_SET(OTG_V_TOTAL_MAX, 0, + OTG_V_TOTAL_MAX, 0); + + REG_UPDATE_4(OTG_V_TOTAL_CONTROL, + OTG_SET_V_TOTAL_MIN_MASK, 0, + OTG_V_TOTAL_MIN_SEL, 0, + OTG_V_TOTAL_MAX_SEL, 0, + OTG_FORCE_LOCK_ON_EVENT, 0); + } +} + +static void dcn10_timing_generator_set_test_pattern( + struct timing_generator *tg, + /* TODO: replace 'controller_dp_test_pattern' by 'test_pattern_mode' + * because this is not DP-specific (which is probably somewhere in DP + * encoder) */ + enum controller_dp_test_pattern test_pattern, + enum dc_color_depth color_depth) +{ + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + enum test_pattern_color_format bit_depth; + enum test_pattern_dyn_range dyn_range; + enum test_pattern_mode mode; + uint32_t pattern_mask; + uint32_t pattern_data; + /* color ramp generator mixes 16-bits color */ + uint32_t src_bpc = 16; + /* requested bpc */ + uint32_t dst_bpc; + uint32_t index; + /* RGB values of the color bars. + * Produce two RGB colors: RGB0 - white (all Fs) + * and RGB1 - black (all 0s) + * (three RGB components for two colors) + */ + uint16_t src_color[6] = {0xFFFF, 0xFFFF, 0xFFFF, 0x0000, + 0x0000, 0x0000}; + /* dest color (converted to the specified color format) */ + uint16_t dst_color[6]; + uint32_t inc_base; + + /* translate to bit depth */ + switch (color_depth) { + case COLOR_DEPTH_666: + bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_6; + break; + case COLOR_DEPTH_888: + bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8; + break; + case COLOR_DEPTH_101010: + bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_10; + break; + case COLOR_DEPTH_121212: + bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_12; + break; + default: + bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8; + break; + } + + switch (test_pattern) { + case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES: + case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA: + { + dyn_range = (test_pattern == + CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA ? + TEST_PATTERN_DYN_RANGE_CEA : + TEST_PATTERN_DYN_RANGE_VESA); + mode = TEST_PATTERN_MODE_COLORSQUARES_RGB; + + REG_UPDATE_2(OTG_TEST_PATTERN_PARAMETERS, + OTG_TEST_PATTERN_VRES, 6, + OTG_TEST_PATTERN_HRES, 6); + + REG_UPDATE_4(OTG_TEST_PATTERN_CONTROL, + OTG_TEST_PATTERN_EN, 1, + OTG_TEST_PATTERN_MODE, mode, + OTG_TEST_PATTERN_DYNAMIC_RANGE, dyn_range, + OTG_TEST_PATTERN_COLOR_FORMAT, bit_depth); + } + break; + + case CONTROLLER_DP_TEST_PATTERN_VERTICALBARS: + case CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS: + { + mode = (test_pattern == + CONTROLLER_DP_TEST_PATTERN_VERTICALBARS ? + TEST_PATTERN_MODE_VERTICALBARS : + TEST_PATTERN_MODE_HORIZONTALBARS); + + switch (bit_depth) { + case TEST_PATTERN_COLOR_FORMAT_BPC_6: + dst_bpc = 6; + break; + case TEST_PATTERN_COLOR_FORMAT_BPC_8: + dst_bpc = 8; + break; + case TEST_PATTERN_COLOR_FORMAT_BPC_10: + dst_bpc = 10; + break; + default: + dst_bpc = 8; + break; + } + + /* adjust color to the required colorFormat */ + for (index = 0; index < 6; index++) { + /* dst = 2^dstBpc * src / 2^srcBpc = src >> + * (srcBpc - dstBpc); + */ + dst_color[index] = + src_color[index] >> (src_bpc - dst_bpc); + /* CRTC_TEST_PATTERN_DATA has 16 bits, + * lowest 6 are hardwired to ZERO + * color bits should be left aligned aligned to MSB + * XXXXXXXXXX000000 for 10 bit, + * XXXXXXXX00000000 for 8 bit and XXXXXX0000000000 for 6 + */ + dst_color[index] <<= (16 - dst_bpc); + } + + REG_WRITE(OTG_TEST_PATTERN_PARAMETERS, 0); + + /* We have to write the mask before data, similar to pipeline. + * For example, for 8 bpc, if we want RGB0 to be magenta, + * and RGB1 to be cyan, + * we need to make 7 writes: + * MASK DATA + * 000001 00000000 00000000 set mask to R0 + * 000010 11111111 00000000 R0 255, 0xFF00, set mask to G0 + * 000100 00000000 00000000 G0 0, 0x0000, set mask to B0 + * 001000 11111111 00000000 B0 255, 0xFF00, set mask to R1 + * 010000 00000000 00000000 R1 0, 0x0000, set mask to G1 + * 100000 11111111 00000000 G1 255, 0xFF00, set mask to B1 + * 100000 11111111 00000000 B1 255, 0xFF00 + * + * we will make a loop of 6 in which we prepare the mask, + * then write, then prepare the color for next write. + * first iteration will write mask only, + * but each next iteration color prepared in + * previous iteration will be written within new mask, + * the last component will written separately, + * mask is not changing between 6th and 7th write + * and color will be prepared by last iteration + */ + + /* write color, color values mask in CRTC_TEST_PATTERN_MASK + * is B1, G1, R1, B0, G0, R0 + */ + pattern_data = 0; + for (index = 0; index < 6; index++) { + /* prepare color mask, first write PATTERN_DATA + * will have all zeros + */ + pattern_mask = (1 << index); + + /* write color component */ + REG_SET_2(OTG_TEST_PATTERN_COLOR, 0, + OTG_TEST_PATTERN_MASK, pattern_mask, + OTG_TEST_PATTERN_DATA, pattern_data); + + /* prepare next color component, + * will be written in the next iteration + */ + pattern_data = dst_color[index]; + } + /* write last color component, + * it's been already prepared in the loop + */ + REG_SET_2(OTG_TEST_PATTERN_COLOR, 0, + OTG_TEST_PATTERN_MASK, pattern_mask, + OTG_TEST_PATTERN_DATA, pattern_data); + + /* enable test pattern */ + REG_UPDATE_4(OTG_TEST_PATTERN_CONTROL, + OTG_TEST_PATTERN_EN, 1, + OTG_TEST_PATTERN_MODE, mode, + OTG_TEST_PATTERN_DYNAMIC_RANGE, 0, + OTG_TEST_PATTERN_COLOR_FORMAT, bit_depth); + } + break; + + case CONTROLLER_DP_TEST_PATTERN_COLORRAMP: + { + mode = (bit_depth == + TEST_PATTERN_COLOR_FORMAT_BPC_10 ? + TEST_PATTERN_MODE_DUALRAMP_RGB : + TEST_PATTERN_MODE_SINGLERAMP_RGB); + + switch (bit_depth) { + case TEST_PATTERN_COLOR_FORMAT_BPC_6: + dst_bpc = 6; + break; + case TEST_PATTERN_COLOR_FORMAT_BPC_8: + dst_bpc = 8; + break; + case TEST_PATTERN_COLOR_FORMAT_BPC_10: + dst_bpc = 10; + break; + default: + dst_bpc = 8; + break; + } + + /* increment for the first ramp for one color gradation + * 1 gradation for 6-bit color is 2^10 + * gradations in 16-bit color + */ + inc_base = (src_bpc - dst_bpc); + + switch (bit_depth) { + case TEST_PATTERN_COLOR_FORMAT_BPC_6: + { + REG_UPDATE_5(OTG_TEST_PATTERN_PARAMETERS, + OTG_TEST_PATTERN_INC0, inc_base, + OTG_TEST_PATTERN_INC1, 0, + OTG_TEST_PATTERN_HRES, 6, + OTG_TEST_PATTERN_VRES, 6, + OTG_TEST_PATTERN_RAMP0_OFFSET, 0); + } + break; + case TEST_PATTERN_COLOR_FORMAT_BPC_8: + { + REG_UPDATE_5(OTG_TEST_PATTERN_PARAMETERS, + OTG_TEST_PATTERN_INC0, inc_base, + OTG_TEST_PATTERN_INC1, 0, + OTG_TEST_PATTERN_HRES, 8, + OTG_TEST_PATTERN_VRES, 6, + OTG_TEST_PATTERN_RAMP0_OFFSET, 0); + } + break; + case TEST_PATTERN_COLOR_FORMAT_BPC_10: + { + REG_UPDATE_5(OTG_TEST_PATTERN_PARAMETERS, + OTG_TEST_PATTERN_INC0, inc_base, + OTG_TEST_PATTERN_INC1, inc_base + 2, + OTG_TEST_PATTERN_HRES, 8, + OTG_TEST_PATTERN_VRES, 5, + OTG_TEST_PATTERN_RAMP0_OFFSET, 384 << 6); + } + break; + default: + break; + } + + REG_WRITE(OTG_TEST_PATTERN_COLOR, 0); + + /* enable test pattern */ + REG_WRITE(OTG_TEST_PATTERN_CONTROL, 0); + + REG_SET_4(OTG_TEST_PATTERN_CONTROL, 0, + OTG_TEST_PATTERN_EN, 1, + OTG_TEST_PATTERN_MODE, mode, + OTG_TEST_PATTERN_DYNAMIC_RANGE, 0, + OTG_TEST_PATTERN_COLOR_FORMAT, bit_depth); + } + break; + case CONTROLLER_DP_TEST_PATTERN_VIDEOMODE: + { + REG_WRITE(OTG_TEST_PATTERN_CONTROL, 0); + REG_WRITE(OTG_TEST_PATTERN_COLOR, 0); + REG_WRITE(OTG_TEST_PATTERN_PARAMETERS, 0); + } + break; + default: + break; + + } +} + +void dcn10_timing_generator_get_crtc_scanoutpos( + struct timing_generator *tg, + uint32_t *v_blank_start, + uint32_t *v_blank_end, + uint32_t *h_position, + uint32_t *v_position) +{ + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct crtc_position position; + + REG_GET_2(OTG_V_BLANK_START_END, + OTG_V_BLANK_START, v_blank_start, + OTG_V_BLANK_END, v_blank_end); + + dcn10_get_position(tg, &position); + + *h_position = position.horizontal_count; + *v_position = position.vertical_count; +} + +static struct timing_generator_funcs dcn10_tg_funcs = { + .validate_timing = tg_validate_timing, + .program_timing = tg_program_timing, + .program_global_sync = dcn10_program_global_sync, + .enable_crtc = tg_enable_crtc, + .disable_crtc = tg_disable_crtc, + /* used by enable_timing_synchronization. Not need for FPGA */ + .is_counter_moving = dcn10_is_counter_moving, + /* never be called */ + .get_position = dcn10_get_position, + .get_frame_count = tg_get_vblank_counter, + .get_scanoutpos = dcn10_timing_generator_get_crtc_scanoutpos, + .set_early_control = set_early_control, + /* used by enable_timing_synchronization. Not need for FPGA */ + .wait_for_state = dcn10_wait_for_state, + .set_blank = tg_set_blank, + .is_blanked = tg_is_blanked, + /* never be called */ + .set_colors = NULL, + /* this function will be called by .progam_scaler. dcn and dce + * scaler top level functions are different. .program_scaler is + * not need for dcn. within program_scaler, dcn will return + * early before set_overscan_blank_color is reached + */ + .set_overscan_blank_color = NULL, + .set_blank_color = tg_program_blank_color, + /* dcn10_timing_generator_disable_vga */ + .disable_vga = dcn10_timing_generator_disable_vga, + .did_triggered_reset_occur = dcn10_did_triggered_reset_occur, + .enable_reset_trigger = dcn10_enable_reset_trigger, + .disable_reset_trigger = dcn10_disable_reset_trigger, + .lock = dcn10_lock, + .unlock = dcn10_unlock, + /* dcn10_timing_generator_enable_advanced_request*/ + .enable_advanced_request = NULL, + .enable_optc_clock = enable_optc_clock, + .set_drr = dcn10_timing_generator_set_drr, + .set_static_screen_control = set_static_screen_control, + .set_test_pattern = dcn10_timing_generator_set_test_pattern +}; + +void dcn10_timing_generator_init(struct dcn10_timing_generator *tgn10) +{ + tgn10->base.funcs = &dcn10_tg_funcs; + + tgn10->max_h_total = tgn10->tg_mask->OTG_H_TOTAL + 1; + tgn10->max_v_total = tgn10->tg_mask->OTG_V_TOTAL + 1; + + tgn10->min_h_blank = 32; + tgn10->min_v_blank = 3; + tgn10->min_v_blank_interlace = 5; + tgn10->min_h_sync_width = 8; + tgn10->min_v_sync_width = 1; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h new file mode 100644 index 000000000000..85a763af1956 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h @@ -0,0 +1,335 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_TIMING_GENERATOR_DCN10_H__ +#define __DC_TIMING_GENERATOR_DCN10_H__ + +#include "timing_generator.h" + +#define DCN10TG_FROM_TG(tg)\ + container_of(tg, struct dcn10_timing_generator, base) + +#define TG_COMMON_REG_LIST_DCN1_0(inst) \ + SRI(OTG_VSTARTUP_PARAM, OTG, inst),\ + SRI(OTG_VUPDATE_PARAM, OTG, inst),\ + SRI(OTG_VREADY_PARAM, OTG, inst),\ + SRI(OTG_BLANK_CONTROL, OTG, inst),\ + SRI(OTG_MASTER_UPDATE_LOCK, OTG, inst),\ + SRI(OTG_DOUBLE_BUFFER_CONTROL, OTG, inst),\ + SRI(OTG_H_TOTAL, OTG, inst),\ + SRI(OTG_H_BLANK_START_END, OTG, inst),\ + SRI(OTG_H_SYNC_A, OTG, inst),\ + SRI(OTG_H_SYNC_A_CNTL, OTG, inst),\ + SRI(OTG_H_TIMING_CNTL, OTG, inst),\ + SRI(OTG_V_TOTAL, OTG, inst),\ + SRI(OTG_V_BLANK_START_END, OTG, inst),\ + SRI(OTG_V_SYNC_A, OTG, inst),\ + SRI(OTG_V_SYNC_A_CNTL, OTG, inst),\ + SRI(OTG_INTERLACE_CONTROL, OTG, inst),\ + SRI(OTG_CONTROL, OTG, inst),\ + SRI(OTG_STEREO_CONTROL, OTG, inst),\ + SRI(OTG_3D_STRUCTURE_CONTROL, OTG, inst),\ + SRI(OTG_V_TOTAL_MAX, OTG, inst),\ + SRI(OTG_V_TOTAL_MIN, OTG, inst),\ + SRI(OTG_V_TOTAL_CONTROL, OTG, inst),\ + SRI(OTG_TRIGA_CNTL, OTG, inst),\ + SRI(OTG_FORCE_COUNT_NOW_CNTL, OTG, inst),\ + SRI(OTG_STATIC_SCREEN_CONTROL, OTG, inst),\ + SRI(OTG_STATUS_FRAME_COUNT, OTG, inst),\ + SRI(OTG_STATUS, OTG, inst),\ + SRI(OTG_STATUS_POSITION, OTG, inst),\ + SRI(OTG_NOM_VERT_POSITION, OTG, inst),\ + SRI(OTG_BLACK_COLOR, OTG, inst),\ + SRI(OTG_TEST_PATTERN_PARAMETERS, OTG, inst),\ + SRI(OTG_TEST_PATTERN_CONTROL, OTG, inst),\ + SRI(OTG_TEST_PATTERN_COLOR, OTG, inst),\ + SRI(OTG_CLOCK_CONTROL, OTG, inst),\ + SRI(OPTC_INPUT_CLOCK_CONTROL, ODM, inst),\ + SRI(OPTC_DATA_SOURCE_SELECT, ODM, inst),\ + SRI(OPPBUF_CONTROL, OPPBUF, inst),\ + SRI(OPPBUF_3D_PARAMETERS_0, OPPBUF, inst),\ + SRI(CONTROL, VTG, inst),\ + SR(D1VGA_CONTROL),\ + SR(D2VGA_CONTROL),\ + SR(D3VGA_CONTROL),\ + SR(D4VGA_CONTROL),\ + +struct dcn_tg_registers { + uint32_t OTG_VSTARTUP_PARAM; + uint32_t OTG_VUPDATE_PARAM; + uint32_t OTG_VREADY_PARAM; + uint32_t OTG_BLANK_CONTROL; + uint32_t OTG_MASTER_UPDATE_LOCK; + uint32_t OTG_DOUBLE_BUFFER_CONTROL; + uint32_t OTG_H_TOTAL; + uint32_t OTG_H_BLANK_START_END; + uint32_t OTG_H_SYNC_A; + uint32_t OTG_H_SYNC_A_CNTL; + uint32_t OTG_H_TIMING_CNTL; + uint32_t OTG_V_TOTAL; + uint32_t OTG_V_BLANK_START_END; + uint32_t OTG_V_SYNC_A; + uint32_t OTG_V_SYNC_A_CNTL; + uint32_t OTG_INTERLACE_CONTROL; + uint32_t OTG_CONTROL; + uint32_t OTG_STEREO_CONTROL; + uint32_t OTG_3D_STRUCTURE_CONTROL; + uint32_t OTG_V_TOTAL_MAX; + uint32_t OTG_V_TOTAL_MIN; + uint32_t OTG_V_TOTAL_CONTROL; + uint32_t OTG_TRIGA_CNTL; + uint32_t OTG_FORCE_COUNT_NOW_CNTL; + uint32_t OTG_STATIC_SCREEN_CONTROL; + uint32_t OTG_STATUS_FRAME_COUNT; + uint32_t OTG_STATUS; + uint32_t OTG_STATUS_POSITION; + uint32_t OTG_NOM_VERT_POSITION; + uint32_t OTG_BLACK_COLOR; + uint32_t OTG_TEST_PATTERN_PARAMETERS; + uint32_t OTG_TEST_PATTERN_CONTROL; + uint32_t OTG_TEST_PATTERN_COLOR; + uint32_t OTG_CLOCK_CONTROL; + uint32_t OPTC_INPUT_CLOCK_CONTROL; + uint32_t OPTC_DATA_SOURCE_SELECT; + uint32_t OPPBUF_CONTROL; + uint32_t OPPBUF_3D_PARAMETERS_0; + uint32_t CONTROL; + /*todo: move VGA to HWSS */ + uint32_t D1VGA_CONTROL; + uint32_t D2VGA_CONTROL; + uint32_t D3VGA_CONTROL; + uint32_t D4VGA_CONTROL; +}; + +#define TG_COMMON_MASK_SH_LIST_DCN1_0(mask_sh)\ + SF(OTG0_OTG_VSTARTUP_PARAM, VSTARTUP_START, mask_sh),\ + SF(OTG0_OTG_VUPDATE_PARAM, VUPDATE_OFFSET, mask_sh),\ + SF(OTG0_OTG_VUPDATE_PARAM, VUPDATE_WIDTH, mask_sh),\ + SF(OTG0_OTG_VREADY_PARAM, VREADY_OFFSET, mask_sh),\ + SF(OTG0_OTG_BLANK_CONTROL, OTG_BLANK_DATA_EN, mask_sh),\ + SF(OTG0_OTG_BLANK_CONTROL, OTG_BLANK_DE_MODE, mask_sh),\ + SF(OTG0_OTG_BLANK_CONTROL, OTG_CURRENT_BLANK_STATE, mask_sh),\ + SF(OTG0_OTG_MASTER_UPDATE_LOCK, OTG_MASTER_UPDATE_LOCK, mask_sh),\ + SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_UPDATE_PENDING, mask_sh),\ + SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_BLANK_DATA_DOUBLE_BUFFER_EN, mask_sh),\ + SF(OTG0_OTG_H_TOTAL, OTG_H_TOTAL, mask_sh),\ + SF(OTG0_OTG_H_BLANK_START_END, OTG_H_BLANK_START, mask_sh),\ + SF(OTG0_OTG_H_BLANK_START_END, OTG_H_BLANK_END, mask_sh),\ + SF(OTG0_OTG_H_SYNC_A, OTG_H_SYNC_A_START, mask_sh),\ + SF(OTG0_OTG_H_SYNC_A, OTG_H_SYNC_A_END, mask_sh),\ + SF(OTG0_OTG_H_SYNC_A_CNTL, OTG_H_SYNC_A_POL, mask_sh),\ + SF(OTG0_OTG_H_TIMING_CNTL, OTG_H_TIMING_DIV_BY2, mask_sh),\ + SF(OTG0_OTG_V_TOTAL, OTG_V_TOTAL, mask_sh),\ + SF(OTG0_OTG_V_BLANK_START_END, OTG_V_BLANK_START, mask_sh),\ + SF(OTG0_OTG_V_BLANK_START_END, OTG_V_BLANK_END, mask_sh),\ + SF(OTG0_OTG_V_SYNC_A, OTG_V_SYNC_A_START, mask_sh),\ + SF(OTG0_OTG_V_SYNC_A, OTG_V_SYNC_A_END, mask_sh),\ + SF(OTG0_OTG_V_SYNC_A_CNTL, OTG_V_SYNC_A_POL, mask_sh),\ + SF(OTG0_OTG_INTERLACE_CONTROL, OTG_INTERLACE_ENABLE, mask_sh),\ + SF(OTG0_OTG_CONTROL, OTG_MASTER_EN, mask_sh),\ + SF(OTG0_OTG_CONTROL, OTG_START_POINT_CNTL, mask_sh),\ + SF(OTG0_OTG_CONTROL, OTG_DISABLE_POINT_CNTL, mask_sh),\ + SF(OTG0_OTG_CONTROL, OTG_FIELD_NUMBER_CNTL, mask_sh),\ + SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_EN, mask_sh),\ + SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_SYNC_OUTPUT_LINE_NUM, mask_sh),\ + SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_SYNC_OUTPUT_POLARITY, mask_sh),\ + SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_EYE_FLAG_POLARITY, mask_sh),\ + SF(OTG0_OTG_STEREO_CONTROL, OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP, mask_sh),\ + SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_EN, mask_sh),\ + SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_V_UPDATE_MODE, mask_sh),\ + SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_STEREO_SEL_OVR, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_MAX, OTG_V_TOTAL_MAX, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_MIN, OTG_V_TOTAL_MIN, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_V_TOTAL_MIN_SEL, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_V_TOTAL_MAX_SEL, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_FORCE_LOCK_ON_EVENT, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_SET_V_TOTAL_MIN_MASK_EN, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_SET_V_TOTAL_MIN_MASK, mask_sh),\ + SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_CLEAR, mask_sh),\ + SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_MODE, mask_sh),\ + SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_OCCURRED, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_SOURCE_SELECT, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_SOURCE_PIPE_SELECT, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_RISING_EDGE_DETECT_CNTL, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, mask_sh),\ + SF(OTG0_OTG_STATIC_SCREEN_CONTROL, OTG_STATIC_SCREEN_EVENT_MASK, mask_sh),\ + SF(OTG0_OTG_STATIC_SCREEN_CONTROL, OTG_STATIC_SCREEN_FRAME_COUNT, mask_sh),\ + SF(OTG0_OTG_STATUS_FRAME_COUNT, OTG_FRAME_COUNT, mask_sh),\ + SF(OTG0_OTG_STATUS, OTG_V_BLANK, mask_sh),\ + SF(OTG0_OTG_STATUS, OTG_V_ACTIVE_DISP, mask_sh),\ + SF(OTG0_OTG_STATUS_POSITION, OTG_HORZ_COUNT, mask_sh),\ + SF(OTG0_OTG_STATUS_POSITION, OTG_VERT_COUNT, mask_sh),\ + SF(OTG0_OTG_NOM_VERT_POSITION, OTG_VERT_COUNT_NOM, mask_sh),\ + SF(OTG0_OTG_BLACK_COLOR, OTG_BLACK_COLOR_B_CB, mask_sh),\ + SF(OTG0_OTG_BLACK_COLOR, OTG_BLACK_COLOR_G_Y, mask_sh),\ + SF(OTG0_OTG_BLACK_COLOR, OTG_BLACK_COLOR_R_CR, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_PARAMETERS, OTG_TEST_PATTERN_INC0, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_PARAMETERS, OTG_TEST_PATTERN_INC1, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_PARAMETERS, OTG_TEST_PATTERN_VRES, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_PARAMETERS, OTG_TEST_PATTERN_HRES, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_PARAMETERS, OTG_TEST_PATTERN_RAMP0_OFFSET, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_CONTROL, OTG_TEST_PATTERN_EN, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_CONTROL, OTG_TEST_PATTERN_MODE, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_CONTROL, OTG_TEST_PATTERN_DYNAMIC_RANGE, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_CONTROL, OTG_TEST_PATTERN_COLOR_FORMAT, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_COLOR, OTG_TEST_PATTERN_MASK, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_COLOR, OTG_TEST_PATTERN_DATA, mask_sh),\ + SF(OTG0_OTG_CLOCK_CONTROL, OTG_BUSY, mask_sh),\ + SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_EN, mask_sh),\ + SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_ON, mask_sh),\ + SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_GATE_DIS, mask_sh),\ + SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_EN, mask_sh),\ + SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_ON, mask_sh),\ + SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_GATE_DIS, mask_sh),\ + SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SRC_SEL, mask_sh),\ + SF(OPPBUF0_OPPBUF_CONTROL, OPPBUF_ACTIVE_WIDTH, mask_sh),\ + SF(OPPBUF0_OPPBUF_3D_PARAMETERS_0, OPPBUF_3D_VACT_SPACE1_SIZE, mask_sh),\ + SF(VTG0_CONTROL, VTG0_ENABLE, mask_sh),\ + SF(VTG0_CONTROL, VTG0_FP2, mask_sh),\ + SF(VTG0_CONTROL, VTG0_VCOUNT_INIT, mask_sh),\ + +#define TG_REG_FIELD_LIST(type) \ + type VSTARTUP_START;\ + type VUPDATE_OFFSET;\ + type VUPDATE_WIDTH;\ + type VREADY_OFFSET;\ + type OTG_BLANK_DATA_EN;\ + type OTG_BLANK_DE_MODE;\ + type OTG_CURRENT_BLANK_STATE;\ + type OTG_MASTER_UPDATE_LOCK;\ + type OTG_UPDATE_PENDING;\ + type OTG_BLANK_DATA_DOUBLE_BUFFER_EN;\ + type OTG_H_TOTAL;\ + type OTG_H_BLANK_START;\ + type OTG_H_BLANK_END;\ + type OTG_H_SYNC_A_START;\ + type OTG_H_SYNC_A_END;\ + type OTG_H_SYNC_A_POL;\ + type OTG_H_TIMING_DIV_BY2;\ + type OTG_V_TOTAL;\ + type OTG_V_BLANK_START;\ + type OTG_V_BLANK_END;\ + type OTG_V_SYNC_A_START;\ + type OTG_V_SYNC_A_END;\ + type OTG_V_SYNC_A_POL;\ + type OTG_INTERLACE_ENABLE;\ + type OTG_MASTER_EN;\ + type OTG_START_POINT_CNTL;\ + type OTG_DISABLE_POINT_CNTL;\ + type OTG_FIELD_NUMBER_CNTL;\ + type OTG_STEREO_EN;\ + type OTG_STEREO_SYNC_OUTPUT_LINE_NUM;\ + type OTG_STEREO_SYNC_OUTPUT_POLARITY;\ + type OTG_STEREO_EYE_FLAG_POLARITY;\ + type OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP;\ + type OTG_3D_STRUCTURE_EN;\ + type OTG_3D_STRUCTURE_V_UPDATE_MODE;\ + type OTG_3D_STRUCTURE_STEREO_SEL_OVR;\ + type OTG_V_TOTAL_MAX;\ + type OTG_V_TOTAL_MIN;\ + type OTG_V_TOTAL_MIN_SEL;\ + type OTG_V_TOTAL_MAX_SEL;\ + type OTG_FORCE_LOCK_ON_EVENT;\ + type OTG_SET_V_TOTAL_MIN_MASK_EN;\ + type OTG_SET_V_TOTAL_MIN_MASK;\ + type OTG_FORCE_COUNT_NOW_CLEAR;\ + type OTG_FORCE_COUNT_NOW_MODE;\ + type OTG_FORCE_COUNT_NOW_OCCURRED;\ + type OTG_TRIGA_SOURCE_SELECT;\ + type OTG_TRIGA_SOURCE_PIPE_SELECT;\ + type OTG_TRIGA_RISING_EDGE_DETECT_CNTL;\ + type OTG_TRIGA_FALLING_EDGE_DETECT_CNTL;\ + type OTG_STATIC_SCREEN_EVENT_MASK;\ + type OTG_STATIC_SCREEN_FRAME_COUNT;\ + type OTG_FRAME_COUNT;\ + type OTG_V_BLANK;\ + type OTG_V_ACTIVE_DISP;\ + type OTG_HORZ_COUNT;\ + type OTG_VERT_COUNT;\ + type OTG_VERT_COUNT_NOM;\ + type OTG_BLACK_COLOR_B_CB;\ + type OTG_BLACK_COLOR_G_Y;\ + type OTG_BLACK_COLOR_R_CR;\ + type OTG_TEST_PATTERN_INC0;\ + type OTG_TEST_PATTERN_INC1;\ + type OTG_TEST_PATTERN_VRES;\ + type OTG_TEST_PATTERN_HRES;\ + type OTG_TEST_PATTERN_RAMP0_OFFSET;\ + type OTG_TEST_PATTERN_EN;\ + type OTG_TEST_PATTERN_MODE;\ + type OTG_TEST_PATTERN_DYNAMIC_RANGE;\ + type OTG_TEST_PATTERN_COLOR_FORMAT;\ + type OTG_TEST_PATTERN_MASK;\ + type OTG_TEST_PATTERN_DATA;\ + type OTG_BUSY;\ + type OTG_CLOCK_EN;\ + type OTG_CLOCK_ON;\ + type OTG_CLOCK_GATE_DIS;\ + type OPTC_INPUT_CLK_EN;\ + type OPTC_INPUT_CLK_ON;\ + type OPTC_INPUT_CLK_GATE_DIS;\ + type OPTC_SRC_SEL;\ + type OPPBUF_ACTIVE_WIDTH;\ + type OPPBUF_3D_VACT_SPACE1_SIZE;\ + type VTG0_ENABLE;\ + type VTG0_FP2;\ + type VTG0_VCOUNT_INIT;\ + +struct dcn_tg_shift { + TG_REG_FIELD_LIST(uint8_t) +}; + +struct dcn_tg_mask { + TG_REG_FIELD_LIST(uint32_t) +}; + +struct dcn10_timing_generator { + struct timing_generator base; + + const struct dcn_tg_registers *tg_regs; + const struct dcn_tg_shift *tg_shift; + const struct dcn_tg_mask *tg_mask; + + enum controller_id controller_id; + + uint32_t max_h_total; + uint32_t max_v_total; + + uint32_t min_h_blank; + + uint32_t min_h_sync_width; + uint32_t min_v_sync_width; + uint32_t min_v_blank; + uint32_t min_v_blank_interlace; +}; + +void dcn10_timing_generator_init(struct dcn10_timing_generator *tg); + +void dcn10_timing_generator_set_drr(struct timing_generator *tg, + const struct drr_params *params); + +void dcn10_unlock(struct timing_generator *tg); +void dcn10_lock(struct timing_generator *tg); +#endif /* __DC_TIMING_GENERATOR_DCN10_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c new file mode 100644 index 000000000000..3718fb5a3238 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c @@ -0,0 +1,1057 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "core_types.h" + +#include "include/grph_object_id.h" +#include "include/fixed31_32.h" +#include "include/logger_interface.h" + +#include "reg_helper.h" +#include "dcn10_transform.h" +#include "basics/conversion.h" + +#define NUM_PHASES 64 +#define HORZ_MAX_TAPS 8 +#define VERT_MAX_TAPS 8 + +#define BLACK_OFFSET_RGB_Y 0x0 +#define BLACK_OFFSET_CBCR 0x8000 + +#define REG(reg)\ + xfm->tf_regs->reg + +#define CTX \ + xfm->base.ctx + +#undef FN +#define FN(reg_name, field_name) \ + xfm->tf_shift->field_name, xfm->tf_mask->field_name + + +enum dcn10_coef_filter_type_sel { + SCL_COEF_LUMA_VERT_FILTER = 0, + SCL_COEF_LUMA_HORZ_FILTER = 1, + SCL_COEF_CHROMA_VERT_FILTER = 2, + SCL_COEF_CHROMA_HORZ_FILTER = 3, + SCL_COEF_ALPHA_VERT_FILTER = 4, + SCL_COEF_ALPHA_HORZ_FILTER = 5 +}; + +enum lb_memory_config { + /* Enable all 3 pieces of memory */ + LB_MEMORY_CONFIG_0 = 0, + + /* Enable only the first piece of memory */ + LB_MEMORY_CONFIG_1 = 1, + + /* Enable only the second piece of memory */ + LB_MEMORY_CONFIG_2 = 2, + + /* Only applicable in 4:2:0 mode, enable all 3 pieces of memory and the + * last piece of chroma memory used for the luma storage + */ + LB_MEMORY_CONFIG_3 = 3 +}; + +enum dscl_autocal_mode { + AUTOCAL_MODE_OFF = 0, + + /* Autocal calculate the scaling ratio and initial phase and the + * DSCL_MODE_SEL must be set to 1 + */ + AUTOCAL_MODE_AUTOSCALE = 1, + /* Autocal perform auto centering without replication and the + * DSCL_MODE_SEL must be set to 0 + */ + AUTOCAL_MODE_AUTOCENTER = 2, + /* Autocal perform auto centering and auto replication and the + * DSCL_MODE_SEL must be set to 0 + */ + AUTOCAL_MODE_AUTOREPLICATE = 3 +}; + +enum dscl_mode_sel { + DSCL_MODE_SCALING_444_BYPASS = 0, + DSCL_MODE_SCALING_444_RGB_ENABLE = 1, + DSCL_MODE_SCALING_444_YCBCR_ENABLE = 2, + DSCL_MODE_SCALING_420_YCBCR_ENABLE = 3, + DSCL_MODE_SCALING_420_LUMA_BYPASS = 4, + DSCL_MODE_SCALING_420_CHROMA_BYPASS = 5, + DSCL_MODE_DSCL_BYPASS = 6 +}; + +enum gamut_remap_select { + GAMUT_REMAP_BYPASS = 0, + GAMUT_REMAP_COEFF, + GAMUT_REMAP_COMA_COEFF, + GAMUT_REMAP_COMB_COEFF +}; + +static void transform_set_overscan( + struct dcn10_transform *xfm, + const struct scaler_data *data) +{ + uint32_t left = data->recout.x; + uint32_t top = data->recout.y; + + int right = data->h_active - data->recout.x - data->recout.width; + int bottom = data->v_active - data->recout.y - data->recout.height; + + if (right < 0) { + BREAK_TO_DEBUGGER(); + right = 0; + } + if (bottom < 0) { + BREAK_TO_DEBUGGER(); + bottom = 0; + } + + REG_SET_2(DSCL_EXT_OVERSCAN_LEFT_RIGHT, 0, + EXT_OVERSCAN_LEFT, left, + EXT_OVERSCAN_RIGHT, right); + + REG_SET_2(DSCL_EXT_OVERSCAN_TOP_BOTTOM, 0, + EXT_OVERSCAN_BOTTOM, bottom, + EXT_OVERSCAN_TOP, top); +} + +static void transform_set_otg_blank( + struct dcn10_transform *xfm, const struct scaler_data *data) +{ + uint32_t h_blank_start = data->h_active; + uint32_t h_blank_end = 0; + uint32_t v_blank_start = data->v_active; + uint32_t v_blank_end = 0; + + REG_SET_2(OTG_H_BLANK, 0, + OTG_H_BLANK_START, h_blank_start, + OTG_H_BLANK_END, h_blank_end); + + REG_SET_2(OTG_V_BLANK, 0, + OTG_V_BLANK_START, v_blank_start, + OTG_V_BLANK_END, v_blank_end); +} + +static enum dscl_mode_sel get_dscl_mode(const struct scaler_data *data) +{ + const long long one = dal_fixed31_32_one.value; + bool ycbcr = false; + bool format420 = false; + + if (data->format == PIXEL_FORMAT_FP16) + return DSCL_MODE_DSCL_BYPASS; + + if (data->format >= PIXEL_FORMAT_VIDEO_BEGIN + && data->format <= PIXEL_FORMAT_VIDEO_END) + ycbcr = true; + + if (data->format == PIXEL_FORMAT_420BPP12 || + data->format == PIXEL_FORMAT_420BPP15) + format420 = true; + + if (data->ratios.horz.value == one + && data->ratios.vert.value == one + && data->ratios.horz_c.value == one + && data->ratios.vert_c.value == one) + return DSCL_MODE_SCALING_444_BYPASS; + + if (!format420) { + if (ycbcr) + return DSCL_MODE_SCALING_444_YCBCR_ENABLE; + else + return DSCL_MODE_SCALING_444_RGB_ENABLE; + } + if (data->ratios.horz.value == one && data->ratios.vert.value == one) + return DSCL_MODE_SCALING_420_LUMA_BYPASS; + if (data->ratios.horz_c.value == one && data->ratios.vert_c.value == one) + return DSCL_MODE_SCALING_420_CHROMA_BYPASS; + + return DSCL_MODE_SCALING_420_YCBCR_ENABLE; +} + +static int get_pixel_depth_val(enum lb_pixel_depth depth) +{ + if (depth == LB_PIXEL_DEPTH_30BPP) + return 0; /* 10 bpc */ + else if (depth == LB_PIXEL_DEPTH_24BPP) + return 1; /* 8 bpc */ + else if (depth == LB_PIXEL_DEPTH_18BPP) + return 2; /* 6 bpc */ + else if (depth == LB_PIXEL_DEPTH_36BPP) + return 3; /* 12 bpc */ + else { + ASSERT(0); + return -1; /* Unsupported */ + } +} + +static void transform_set_lb( + struct dcn10_transform *xfm, + const struct line_buffer_params *lb_params, + enum lb_memory_config mem_size_config) +{ + uint32_t pixel_depth = get_pixel_depth_val(lb_params->depth); + uint32_t dyn_pix_depth = lb_params->dynamic_pixel_depth; + REG_SET_7(LB_DATA_FORMAT, 0, + PIXEL_DEPTH, pixel_depth, /* Pixel depth stored in LB */ + PIXEL_EXPAN_MODE, lb_params->pixel_expan_mode, /* Pixel expansion mode */ + PIXEL_REDUCE_MODE, 1, /* Pixel reduction mode: Rounding */ + DYNAMIC_PIXEL_DEPTH, dyn_pix_depth, /* Dynamic expansion pixel depth */ + DITHER_EN, 0, /* Dithering enable: Disabled */ + INTERLEAVE_EN, lb_params->interleave_en, /* Interleave source enable */ + ALPHA_EN, lb_params->alpha_en); /* Alpha enable */ + + REG_SET_2(LB_MEMORY_CTRL, 0, + MEMORY_CONFIG, mem_size_config, + LB_MAX_PARTITIONS, 63); +} + +static void transform_set_scaler_filter( + struct dcn10_transform *xfm, + uint32_t taps, + enum dcn10_coef_filter_type_sel filter_type, + const uint16_t *filter) +{ + const int tap_pairs = (taps + 1) / 2; + int phase; + int pair; + uint16_t odd_coef, even_coef; + + REG_SET_3(SCL_COEF_RAM_TAP_SELECT, 0, + SCL_COEF_RAM_TAP_PAIR_IDX, 0, + SCL_COEF_RAM_PHASE, 0, + SCL_COEF_RAM_FILTER_TYPE, filter_type); + + for (phase = 0; phase < (NUM_PHASES / 2 + 1); phase++) { + for (pair = 0; pair < tap_pairs; pair++) { + even_coef = filter[phase * taps + 2 * pair]; + if ((pair * 2 + 1) < taps) + odd_coef = filter[phase * taps + 2 * pair + 1]; + else + odd_coef = 0; + + REG_SET_4(SCL_COEF_RAM_TAP_DATA, 0, + /* Even tap coefficient (bits 1:0 fixed to 0) */ + SCL_COEF_RAM_EVEN_TAP_COEF, even_coef, + /* Write/read control for even coefficient */ + SCL_COEF_RAM_EVEN_TAP_COEF_EN, 1, + /* Odd tap coefficient (bits 1:0 fixed to 0) */ + SCL_COEF_RAM_ODD_TAP_COEF, odd_coef, + /* Write/read control for odd coefficient */ + SCL_COEF_RAM_ODD_TAP_COEF_EN, 1); + } + } + +} + +#if 0 +bool transform_set_pixel_storage_depth( + struct transform *xfm, + enum lb_pixel_depth depth, + const struct bit_depth_reduction_params *bit_depth_params) +{ + struct dcn10_transform *xfm110 = TO_DCN10_TRANSFORM(xfm); + bool ret = true; + uint32_t value; + enum dc_color_depth color_depth; + + value = dm_read_reg(xfm->ctx, LB_REG(mmLB_DATA_FORMAT)); + switch (depth) { + case LB_PIXEL_DEPTH_18BPP: + color_depth = COLOR_DEPTH_666; + set_reg_field_value(value, 2, LB_DATA_FORMAT, PIXEL_DEPTH); + set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_EXPAN_MODE); + break; + case LB_PIXEL_DEPTH_24BPP: + color_depth = COLOR_DEPTH_888; + set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_DEPTH); + set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_EXPAN_MODE); + break; + case LB_PIXEL_DEPTH_30BPP: + color_depth = COLOR_DEPTH_101010; + set_reg_field_value(value, 0, LB_DATA_FORMAT, PIXEL_DEPTH); + set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_EXPAN_MODE); + break; + case LB_PIXEL_DEPTH_36BPP: + color_depth = COLOR_DEPTH_121212; + set_reg_field_value(value, 3, LB_DATA_FORMAT, PIXEL_DEPTH); + set_reg_field_value(value, 0, LB_DATA_FORMAT, PIXEL_EXPAN_MODE); + break; + default: + ret = false; + break; + } + + if (ret == true) { + set_denormalization(xfm110, color_depth); + ret = program_bit_depth_reduction(xfm110, color_depth, + bit_depth_params); + + set_reg_field_value(value, 0, LB_DATA_FORMAT, ALPHA_EN); + dm_write_reg(xfm->ctx, LB_REG(mmLB_DATA_FORMAT), value); + if (!(xfm110->lb_pixel_depth_supported & depth)) { + /* We should use unsupported capabilities + * unless it is required by w/a + */ + dm_logger_write(xfm->ctx->logger, LOG_WARNING, + "%s: Capability not supported", + __func__); + } + } + + return ret; +} +#endif + +static const uint16_t *get_filter_coeffs_64p(int taps, struct fixed31_32 ratio) +{ + if (taps == 8) + return get_filter_8tap_64p(ratio); + else if (taps == 7) + return get_filter_7tap_64p(ratio); + else if (taps == 6) + return get_filter_6tap_64p(ratio); + else if (taps == 5) + return get_filter_5tap_64p(ratio); + else if (taps == 4) + return get_filter_4tap_64p(ratio); + else if (taps == 3) + return get_filter_3tap_64p(ratio); + else if (taps == 2) + return filter_2tap_64p; + else if (taps == 1) + return NULL; + else { + /* should never happen, bug */ + BREAK_TO_DEBUGGER(); + return NULL; + } +} + +static void transform_set_scl_filter( + struct dcn10_transform *xfm, + const struct scaler_data *scl_data, + bool chroma_coef_mode) +{ + bool h_2tap_hardcode_coef_en = false; + bool v_2tap_hardcode_coef_en = false; + bool h_2tap_sharp_en = false; + bool v_2tap_sharp_en = false; + uint32_t h_2tap_sharp_factor = scl_data->sharpness.horz; + uint32_t v_2tap_sharp_factor = scl_data->sharpness.vert; + bool coef_ram_current; + const uint16_t *filter_h = NULL; + const uint16_t *filter_v = NULL; + const uint16_t *filter_h_c = NULL; + const uint16_t *filter_v_c = NULL; + + h_2tap_hardcode_coef_en = scl_data->taps.h_taps < 3 + && scl_data->taps.h_taps_c < 3 + && (scl_data->taps.h_taps > 1 || scl_data->taps.h_taps_c > 1); + v_2tap_hardcode_coef_en = scl_data->taps.v_taps < 3 + && scl_data->taps.v_taps_c < 3 + && (scl_data->taps.v_taps > 1 || scl_data->taps.v_taps_c > 1); + + h_2tap_sharp_en = h_2tap_hardcode_coef_en && h_2tap_sharp_factor != 0; + v_2tap_sharp_en = v_2tap_hardcode_coef_en && v_2tap_sharp_factor != 0; + + REG_UPDATE_6(DSCL_2TAP_CONTROL, + SCL_H_2TAP_HARDCODE_COEF_EN, h_2tap_hardcode_coef_en, + SCL_H_2TAP_SHARP_EN, h_2tap_sharp_en, + SCL_H_2TAP_SHARP_FACTOR, h_2tap_sharp_factor, + SCL_V_2TAP_HARDCODE_COEF_EN, v_2tap_hardcode_coef_en, + SCL_V_2TAP_SHARP_EN, v_2tap_sharp_en, + SCL_V_2TAP_SHARP_FACTOR, v_2tap_sharp_factor); + + if (!v_2tap_hardcode_coef_en || !h_2tap_hardcode_coef_en) { + bool filter_updated = false; + + filter_h = get_filter_coeffs_64p( + scl_data->taps.h_taps, scl_data->ratios.horz); + filter_v = get_filter_coeffs_64p( + scl_data->taps.v_taps, scl_data->ratios.vert); + + filter_updated = (filter_h && (filter_h != xfm->filter_h)) + || (filter_v && (filter_v != xfm->filter_v)); + + if (chroma_coef_mode) { + filter_h_c = get_filter_coeffs_64p( + scl_data->taps.h_taps_c, scl_data->ratios.horz_c); + filter_v_c = get_filter_coeffs_64p( + scl_data->taps.v_taps_c, scl_data->ratios.vert_c); + filter_updated = filter_updated || (filter_h_c && (filter_h_c != xfm->filter_h_c)) + || (filter_v_c && (filter_v_c != xfm->filter_v_c)); + } + + if (filter_updated) { + uint32_t scl_mode = REG_READ(SCL_MODE); + + if (!h_2tap_hardcode_coef_en && filter_h) { + transform_set_scaler_filter( + xfm, scl_data->taps.h_taps, + SCL_COEF_LUMA_HORZ_FILTER, filter_h); + } + xfm->filter_h = filter_h; + if (!v_2tap_hardcode_coef_en && filter_v) { + transform_set_scaler_filter( + xfm, scl_data->taps.v_taps, + SCL_COEF_LUMA_VERT_FILTER, filter_v); + } + xfm->filter_v = filter_v; + if (chroma_coef_mode) { + if (!h_2tap_hardcode_coef_en && filter_h_c) { + transform_set_scaler_filter( + xfm, scl_data->taps.h_taps_c, + SCL_COEF_CHROMA_HORZ_FILTER, filter_h_c); + } + if (!v_2tap_hardcode_coef_en && filter_v_c) { + transform_set_scaler_filter( + xfm, scl_data->taps.v_taps_c, + SCL_COEF_CHROMA_VERT_FILTER, filter_v_c); + } + } + xfm->filter_h_c = filter_h_c; + xfm->filter_v_c = filter_v_c; + + coef_ram_current = get_reg_field_value_ex( + scl_mode, xfm->tf_mask->SCL_COEF_RAM_SELECT_CURRENT, + xfm->tf_shift->SCL_COEF_RAM_SELECT_CURRENT); + + /* Swap coefficient RAM and set chroma coefficient mode */ + REG_SET_2(SCL_MODE, scl_mode, + SCL_COEF_RAM_SELECT, !coef_ram_current, + SCL_CHROMA_COEF_MODE, chroma_coef_mode); + } + } +} + +static void transform_set_viewport( + struct dcn10_transform *xfm, + const struct rect *viewport, + const struct rect *viewport_c) +{ + REG_SET_2(DCSURF_PRI_VIEWPORT_DIMENSION, 0, + PRI_VIEWPORT_WIDTH, viewport->width, + PRI_VIEWPORT_HEIGHT, viewport->height); + + REG_SET_2(DCSURF_PRI_VIEWPORT_START, 0, + PRI_VIEWPORT_X_START, viewport->x, + PRI_VIEWPORT_Y_START, viewport->y); + + /*for stereo*/ + REG_SET_2(DCSURF_SEC_VIEWPORT_DIMENSION, 0, + SEC_VIEWPORT_WIDTH, viewport->width, + SEC_VIEWPORT_HEIGHT, viewport->height); + + REG_SET_2(DCSURF_SEC_VIEWPORT_START, 0, + SEC_VIEWPORT_X_START, viewport->x, + SEC_VIEWPORT_Y_START, viewport->y); + + /* DC supports NV12 only at the moment */ + REG_SET_2(DCSURF_PRI_VIEWPORT_DIMENSION_C, 0, + PRI_VIEWPORT_WIDTH_C, viewport_c->width, + PRI_VIEWPORT_HEIGHT_C, viewport_c->height); + + REG_SET_2(DCSURF_PRI_VIEWPORT_START_C, 0, + PRI_VIEWPORT_X_START_C, viewport_c->x, + PRI_VIEWPORT_Y_START_C, viewport_c->y); +} + +static int get_lb_depth_bpc(enum lb_pixel_depth depth) +{ + if (depth == LB_PIXEL_DEPTH_30BPP) + return 10; + else if (depth == LB_PIXEL_DEPTH_24BPP) + return 8; + else if (depth == LB_PIXEL_DEPTH_18BPP) + return 6; + else if (depth == LB_PIXEL_DEPTH_36BPP) + return 12; + else { + BREAK_TO_DEBUGGER(); + return -1; /* Unsupported */ + } +} + +static void calc_lb_num_partitions( + const struct scaler_data *scl_data, + enum lb_memory_config lb_config, + int *num_part_y, + int *num_part_c) +{ + int line_size = scl_data->viewport.width < scl_data->recout.width ? + scl_data->viewport.width : scl_data->recout.width; + int line_size_c = scl_data->viewport_c.width < scl_data->recout.width ? + scl_data->viewport_c.width : scl_data->recout.width; + int lb_bpc = get_lb_depth_bpc(scl_data->lb_params.depth); + int memory_line_size_y = (line_size * lb_bpc + 71) / 72; /* +71 to ceil */ + int memory_line_size_c = (line_size_c * lb_bpc + 71) / 72; /* +71 to ceil */ + int memory_line_size_a = (line_size + 5) / 6; /* +5 to ceil */ + int lb_memory_size, lb_memory_size_c, lb_memory_size_a, num_partitions_a; + + if (lb_config == LB_MEMORY_CONFIG_1) { + lb_memory_size = 816; + lb_memory_size_c = 816; + lb_memory_size_a = 984; + } else if (lb_config == LB_MEMORY_CONFIG_2) { + lb_memory_size = 1088; + lb_memory_size_c = 1088; + lb_memory_size_a = 1312; + } else if (lb_config == LB_MEMORY_CONFIG_3) { + lb_memory_size = 816 + 1088 + 848 + 848 + 848; + lb_memory_size_c = 816 + 1088; + lb_memory_size_a = 984 + 1312 + 456; + } else { + lb_memory_size = 816 + 1088 + 848; + lb_memory_size_c = 816 + 1088 + 848; + lb_memory_size_a = 984 + 1312 + 456; + } + *num_part_y = lb_memory_size / memory_line_size_y; + *num_part_c = lb_memory_size_c / memory_line_size_c; + num_partitions_a = lb_memory_size_a / memory_line_size_a; + + if (scl_data->lb_params.alpha_en + && (num_partitions_a < *num_part_y)) + *num_part_y = num_partitions_a; + + if (*num_part_y > 64) + *num_part_y = 64; + if (*num_part_c > 64) + *num_part_c = 64; + +} + +static bool is_lb_conf_valid(int ceil_vratio, int num_partitions, int vtaps) +{ + if (ceil_vratio > 2) + return vtaps <= (num_partitions - ceil_vratio + 2); + else + return vtaps <= num_partitions; +} + +/*find first match configuration which meets the min required lb size*/ +static enum lb_memory_config find_lb_memory_config(const struct scaler_data *scl_data) +{ + int num_part_y, num_part_c; + int vtaps = scl_data->taps.v_taps; + int vtaps_c = scl_data->taps.v_taps_c; + int ceil_vratio = dal_fixed31_32_ceil(scl_data->ratios.vert); + int ceil_vratio_c = dal_fixed31_32_ceil(scl_data->ratios.vert_c); + + calc_lb_num_partitions( + scl_data, LB_MEMORY_CONFIG_1, &num_part_y, &num_part_c); + + if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) + && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)) + return LB_MEMORY_CONFIG_1; + + calc_lb_num_partitions( + scl_data, LB_MEMORY_CONFIG_2, &num_part_y, &num_part_c); + + if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) + && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)) + return LB_MEMORY_CONFIG_2; + + if (scl_data->format == PIXEL_FORMAT_420BPP12 + || scl_data->format == PIXEL_FORMAT_420BPP15) { + calc_lb_num_partitions( + scl_data, LB_MEMORY_CONFIG_3, &num_part_y, &num_part_c); + + if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) + && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)) + return LB_MEMORY_CONFIG_3; + } + + calc_lb_num_partitions( + scl_data, LB_MEMORY_CONFIG_0, &num_part_y, &num_part_c); + + /*Ensure we can support the requested number of vtaps*/ + ASSERT(is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) + && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)); + + return LB_MEMORY_CONFIG_0; +} + +void transform_set_scaler_auto_scale( + struct transform *xfm_base, + const struct scaler_data *scl_data) +{ + enum lb_memory_config lb_config; + struct dcn10_transform *xfm = TO_DCN10_TRANSFORM(xfm_base); + enum dscl_mode_sel dscl_mode = get_dscl_mode(scl_data); + bool ycbcr = scl_data->format >= PIXEL_FORMAT_VIDEO_BEGIN + && scl_data->format <= PIXEL_FORMAT_VIDEO_END; + + transform_set_overscan(xfm, scl_data); + + transform_set_otg_blank(xfm, scl_data); + + REG_UPDATE(SCL_MODE, DSCL_MODE, get_dscl_mode(scl_data)); + + transform_set_viewport(xfm, &scl_data->viewport, &scl_data->viewport_c); + + if (dscl_mode == DSCL_MODE_DSCL_BYPASS) + return; + + lb_config = find_lb_memory_config(scl_data); + transform_set_lb(xfm, &scl_data->lb_params, lb_config); + + if (dscl_mode == DSCL_MODE_SCALING_444_BYPASS) + return; + + /* TODO: v_min */ + REG_SET_3(DSCL_AUTOCAL, 0, + AUTOCAL_MODE, AUTOCAL_MODE_AUTOSCALE, + AUTOCAL_NUM_PIPE, 0, + AUTOCAL_PIPE_ID, 0); + + /* Black offsets */ + if (ycbcr) + REG_SET_2(SCL_BLACK_OFFSET, 0, + SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y, + SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_CBCR); + else + + REG_SET_2(SCL_BLACK_OFFSET, 0, + SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y, + SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_RGB_Y); + + REG_SET_4(SCL_TAP_CONTROL, 0, + SCL_V_NUM_TAPS, scl_data->taps.v_taps - 1, + SCL_H_NUM_TAPS, scl_data->taps.h_taps - 1, + SCL_V_NUM_TAPS_C, scl_data->taps.v_taps_c - 1, + SCL_H_NUM_TAPS_C, scl_data->taps.h_taps_c - 1); + + transform_set_scl_filter(xfm, scl_data, ycbcr); +} + +/* Program gamut remap in bypass mode */ +void transform_set_gamut_remap_bypass(struct dcn10_transform *xfm) +{ + REG_SET(CM_GAMUT_REMAP_CONTROL, 0, + CM_GAMUT_REMAP_MODE, 0); + /* Gamut remap in bypass */ +} + +static void transform_set_recout( + struct dcn10_transform *xfm, const struct rect *recout) +{ + REG_SET_2(RECOUT_START, 0, + /* First pixel of RECOUT */ + RECOUT_START_X, recout->x, + /* First line of RECOUT */ + RECOUT_START_Y, recout->y); + + REG_SET_2(RECOUT_SIZE, 0, + /* Number of RECOUT horizontal pixels */ + RECOUT_WIDTH, recout->width, + /* Number of RECOUT vertical lines */ + RECOUT_HEIGHT, recout->height + - xfm->base.ctx->dc->debug.surface_visual_confirm * 2); +} + +static void transform_set_manual_ratio_init( + struct dcn10_transform *xfm, const struct scaler_data *data) +{ + uint32_t init_frac = 0; + uint32_t init_int = 0; + + REG_SET(SCL_HORZ_FILTER_SCALE_RATIO, 0, + SCL_H_SCALE_RATIO, dal_fixed31_32_u2d19(data->ratios.horz) << 5); + + REG_SET(SCL_VERT_FILTER_SCALE_RATIO, 0, + SCL_V_SCALE_RATIO, dal_fixed31_32_u2d19(data->ratios.vert) << 5); + + REG_SET(SCL_HORZ_FILTER_SCALE_RATIO_C, 0, + SCL_H_SCALE_RATIO_C, dal_fixed31_32_u2d19(data->ratios.horz_c) << 5); + + REG_SET(SCL_VERT_FILTER_SCALE_RATIO_C, 0, + SCL_V_SCALE_RATIO_C, dal_fixed31_32_u2d19(data->ratios.vert_c) << 5); + + /* + * 0.24 format for fraction, first five bits zeroed + */ + init_frac = dal_fixed31_32_u0d19(data->inits.h) << 5; + init_int = dal_fixed31_32_floor(data->inits.h); + REG_SET_2(SCL_HORZ_FILTER_INIT, 0, + SCL_H_INIT_FRAC, init_frac, + SCL_H_INIT_INT, init_int); + + init_frac = dal_fixed31_32_u0d19(data->inits.h_c) << 5; + init_int = dal_fixed31_32_floor(data->inits.h_c); + REG_SET_2(SCL_HORZ_FILTER_INIT_C, 0, + SCL_H_INIT_FRAC_C, init_frac, + SCL_H_INIT_INT_C, init_int); + + init_frac = dal_fixed31_32_u0d19(data->inits.v) << 5; + init_int = dal_fixed31_32_floor(data->inits.v); + REG_SET_2(SCL_VERT_FILTER_INIT, 0, + SCL_V_INIT_FRAC, init_frac, + SCL_V_INIT_INT, init_int); + + init_frac = dal_fixed31_32_u0d19(data->inits.v_bot) << 5; + init_int = dal_fixed31_32_floor(data->inits.v_bot); + REG_SET_2(SCL_VERT_FILTER_INIT_BOT, 0, + SCL_V_INIT_FRAC_BOT, init_frac, + SCL_V_INIT_INT_BOT, init_int); + + init_frac = dal_fixed31_32_u0d19(data->inits.v_c) << 5; + init_int = dal_fixed31_32_floor(data->inits.v_c); + REG_SET_2(SCL_VERT_FILTER_INIT_C, 0, + SCL_V_INIT_FRAC_C, init_frac, + SCL_V_INIT_INT_C, init_int); + + init_frac = dal_fixed31_32_u0d19(data->inits.v_c_bot) << 5; + init_int = dal_fixed31_32_floor(data->inits.v_c_bot); + REG_SET_2(SCL_VERT_FILTER_INIT_BOT_C, 0, + SCL_V_INIT_FRAC_BOT_C, init_frac, + SCL_V_INIT_INT_BOT_C, init_int); +} + +/* Main function to program scaler and line buffer in manual scaling mode */ +static void transform_set_scaler_manual_scale( + struct transform *xfm_base, + const struct scaler_data *scl_data) +{ + enum lb_memory_config lb_config; + struct dcn10_transform *xfm = TO_DCN10_TRANSFORM(xfm_base); + enum dscl_mode_sel dscl_mode = get_dscl_mode(scl_data); + bool ycbcr = scl_data->format >= PIXEL_FORMAT_VIDEO_BEGIN + && scl_data->format <= PIXEL_FORMAT_VIDEO_END; + + /* Recout */ + transform_set_recout(xfm, &scl_data->recout); + + /* MPC Size */ + REG_SET_2(MPC_SIZE, 0, + /* Number of horizontal pixels of MPC */ + MPC_WIDTH, scl_data->h_active, + /* Number of vertical lines of MPC */ + MPC_HEIGHT, scl_data->v_active); + + /* SCL mode */ + REG_UPDATE(SCL_MODE, DSCL_MODE, dscl_mode); + + /* Viewport */ + transform_set_viewport(xfm, &scl_data->viewport, &scl_data->viewport_c); + + if (dscl_mode == DSCL_MODE_DSCL_BYPASS) + return; + /* LB */ + lb_config = find_lb_memory_config(scl_data); + transform_set_lb(xfm, &scl_data->lb_params, lb_config); + + if (dscl_mode == DSCL_MODE_SCALING_444_BYPASS) + return; + + /* Autocal off */ + REG_SET_3(DSCL_AUTOCAL, 0, + AUTOCAL_MODE, AUTOCAL_MODE_OFF, + AUTOCAL_NUM_PIPE, 0, + AUTOCAL_PIPE_ID, 0); + + /* Black offsets */ + if (ycbcr) + REG_SET_2(SCL_BLACK_OFFSET, 0, + SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y, + SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_CBCR); + else + + REG_SET_2(SCL_BLACK_OFFSET, 0, + SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y, + SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_RGB_Y); + + /* Manually calculate scale ratio and init values */ + transform_set_manual_ratio_init(xfm, scl_data); + + /* HTaps/VTaps */ + REG_SET_4(SCL_TAP_CONTROL, 0, + SCL_V_NUM_TAPS, scl_data->taps.v_taps - 1, + SCL_H_NUM_TAPS, scl_data->taps.h_taps - 1, + SCL_V_NUM_TAPS_C, scl_data->taps.v_taps_c - 1, + SCL_H_NUM_TAPS_C, scl_data->taps.h_taps_c - 1); + + transform_set_scl_filter(xfm, scl_data, ycbcr); +} + +#define IDENTITY_RATIO(ratio) (dal_fixed31_32_u2d19(ratio) == (1 << 19)) + + +static bool transform_get_optimal_number_of_taps( + struct transform *xfm, + struct scaler_data *scl_data, + const struct scaling_taps *in_taps) +{ + uint32_t pixel_width; + + if (scl_data->viewport.width > scl_data->recout.width) + pixel_width = scl_data->recout.width; + else + pixel_width = scl_data->viewport.width; + + /* TODO: add lb check */ + + /* No support for programming ratio of 4, drop to 3.99999.. */ + if (scl_data->ratios.horz.value == (4ll << 32)) + scl_data->ratios.horz.value--; + if (scl_data->ratios.vert.value == (4ll << 32)) + scl_data->ratios.vert.value--; + if (scl_data->ratios.horz_c.value == (4ll << 32)) + scl_data->ratios.horz_c.value--; + if (scl_data->ratios.vert_c.value == (4ll << 32)) + scl_data->ratios.vert_c.value--; + + /* Set default taps if none are provided */ + if (in_taps->h_taps == 0) + scl_data->taps.h_taps = 4; + else + scl_data->taps.h_taps = in_taps->h_taps; + if (in_taps->v_taps == 0) + scl_data->taps.v_taps = 4; + else + scl_data->taps.v_taps = in_taps->v_taps; + if (in_taps->v_taps_c == 0) + scl_data->taps.v_taps_c = 2; + else + scl_data->taps.v_taps_c = in_taps->v_taps_c; + if (in_taps->h_taps_c == 0) + scl_data->taps.h_taps_c = 2; + /* Only 1 and even h_taps_c are supported by hw */ + else if ((in_taps->h_taps_c % 2) != 0 && in_taps->h_taps_c != 1) + scl_data->taps.h_taps_c = in_taps->h_taps_c - 1; + else + scl_data->taps.h_taps_c = in_taps->h_taps_c; + + if (IDENTITY_RATIO(scl_data->ratios.horz)) + scl_data->taps.h_taps = 1; + if (IDENTITY_RATIO(scl_data->ratios.vert)) + scl_data->taps.v_taps = 1; + if (IDENTITY_RATIO(scl_data->ratios.horz_c)) + scl_data->taps.h_taps_c = 1; + if (IDENTITY_RATIO(scl_data->ratios.vert_c)) + scl_data->taps.v_taps_c = 1; + + return true; +} + +static void transform_reset(struct transform *xfm_base) +{ + struct dcn10_transform *xfm = TO_DCN10_TRANSFORM(xfm_base); + + xfm->filter_h_c = NULL; + xfm->filter_v_c = NULL; + xfm->filter_h = NULL; + xfm->filter_v = NULL; + + /* set boundary mode to 0 */ + REG_SET(DSCL_CONTROL, 0, SCL_BOUNDARY_MODE, 0); +} + +static void program_gamut_remap( + struct dcn10_transform *xfm, + const uint16_t *regval, + enum gamut_remap_select select) +{ + uint16_t selection = 0; + + if (regval == NULL || select == GAMUT_REMAP_BYPASS) { + REG_SET(CM_GAMUT_REMAP_CONTROL, 0, + CM_GAMUT_REMAP_MODE, 0); + return; + } + switch (select) { + case GAMUT_REMAP_COEFF: + selection = 1; + break; + case GAMUT_REMAP_COMA_COEFF: + selection = 2; + break; + case GAMUT_REMAP_COMB_COEFF: + selection = 3; + break; + default: + break; + } + + + if (select == GAMUT_REMAP_COEFF) { + + REG_SET_2(CM_GAMUT_REMAP_C11_C12, 0, + CM_GAMUT_REMAP_C11, regval[0], + CM_GAMUT_REMAP_C12, regval[1]); + regval += 2; + REG_SET_2(CM_GAMUT_REMAP_C13_C14, 0, + CM_GAMUT_REMAP_C13, regval[0], + CM_GAMUT_REMAP_C14, regval[1]); + regval += 2; + REG_SET_2(CM_GAMUT_REMAP_C21_C22, 0, + CM_GAMUT_REMAP_C21, regval[0], + CM_GAMUT_REMAP_C22, regval[1]); + regval += 2; + REG_SET_2(CM_GAMUT_REMAP_C23_C24, 0, + CM_GAMUT_REMAP_C23, regval[0], + CM_GAMUT_REMAP_C24, regval[1]); + regval += 2; + REG_SET_2(CM_GAMUT_REMAP_C31_C32, 0, + CM_GAMUT_REMAP_C31, regval[0], + CM_GAMUT_REMAP_C32, regval[1]); + regval += 2; + REG_SET_2(CM_GAMUT_REMAP_C33_C34, 0, + CM_GAMUT_REMAP_C33, regval[0], + CM_GAMUT_REMAP_C34, regval[1]); + + } else if (select == GAMUT_REMAP_COMA_COEFF) { + REG_SET_2(CM_COMA_C11_C12, 0, + CM_COMA_C11, regval[0], + CM_COMA_C12, regval[1]); + regval += 2; + REG_SET_2(CM_COMA_C13_C14, 0, + CM_COMA_C13, regval[0], + CM_COMA_C14, regval[1]); + regval += 2; + REG_SET_2(CM_COMA_C21_C22, 0, + CM_COMA_C21, regval[0], + CM_COMA_C22, regval[1]); + regval += 2; + REG_SET_2(CM_COMA_C23_C24, 0, + CM_COMA_C23, regval[0], + CM_COMA_C24, regval[1]); + regval += 2; + REG_SET_2(CM_COMA_C31_C32, 0, + CM_COMA_C31, regval[0], + CM_COMA_C32, regval[1]); + regval += 2; + REG_SET_2(CM_COMA_C33_C34, 0, + CM_COMA_C33, regval[0], + CM_COMA_C34, regval[1]); + + } else { + REG_SET_2(CM_COMB_C11_C12, 0, + CM_COMB_C11, regval[0], + CM_COMB_C12, regval[1]); + regval += 2; + REG_SET_2(CM_COMB_C13_C14, 0, + CM_COMB_C13, regval[0], + CM_COMB_C14, regval[1]); + regval += 2; + REG_SET_2(CM_COMB_C21_C22, 0, + CM_COMB_C21, regval[0], + CM_COMB_C22, regval[1]); + regval += 2; + REG_SET_2(CM_COMB_C23_C24, 0, + CM_COMB_C23, regval[0], + CM_COMB_C24, regval[1]); + regval += 2; + REG_SET_2(CM_COMB_C31_C32, 0, + CM_COMB_C31, regval[0], + CM_COMB_C32, regval[1]); + regval += 2; + REG_SET_2(CM_COMB_C33_C34, 0, + CM_COMB_C33, regval[0], + CM_COMB_C34, regval[1]); + } + + REG_SET( + CM_GAMUT_REMAP_CONTROL, 0, + CM_GAMUT_REMAP_MODE, selection); + +} + +static void dcn_transform_set_gamut_remap( + struct transform *xfm, + const struct xfm_grph_csc_adjustment *adjust) +{ + struct dcn10_transform *dcn_xfm = TO_DCN10_TRANSFORM(xfm); + + if (adjust->gamut_adjust_type != GRAPHICS_GAMUT_ADJUST_TYPE_SW) + /* Bypass if type is bypass or hw */ + program_gamut_remap(dcn_xfm, NULL, GAMUT_REMAP_BYPASS); + else { + struct fixed31_32 arr_matrix[12]; + uint16_t arr_reg_val[12]; + + arr_matrix[0] = adjust->temperature_matrix[0]; + arr_matrix[1] = adjust->temperature_matrix[1]; + arr_matrix[2] = adjust->temperature_matrix[2]; + arr_matrix[3] = dal_fixed31_32_zero; + + arr_matrix[4] = adjust->temperature_matrix[3]; + arr_matrix[5] = adjust->temperature_matrix[4]; + arr_matrix[6] = adjust->temperature_matrix[5]; + arr_matrix[7] = dal_fixed31_32_zero; + + arr_matrix[8] = adjust->temperature_matrix[6]; + arr_matrix[9] = adjust->temperature_matrix[7]; + arr_matrix[10] = adjust->temperature_matrix[8]; + arr_matrix[11] = dal_fixed31_32_zero; + + convert_float_matrix( + arr_reg_val, arr_matrix, 12); + + program_gamut_remap(dcn_xfm, arr_reg_val, GAMUT_REMAP_COEFF); + } +} + +static struct transform_funcs dcn10_transform_funcs = { + + .transform_reset = transform_reset, + .transform_set_scaler = transform_set_scaler_manual_scale, + .transform_get_optimal_number_of_taps = + transform_get_optimal_number_of_taps, + .transform_set_gamut_remap = dcn_transform_set_gamut_remap +}; + +/*****************************************/ +/* Constructor, Destructor */ +/*****************************************/ + +bool dcn10_transform_construct( + struct dcn10_transform *xfm, + struct dc_context *ctx, + const struct dcn_transform_registers *tf_regs, + const struct dcn_transform_shift *tf_shift, + const struct dcn_transform_mask *tf_mask) +{ + xfm->base.ctx = ctx; + + xfm->base.funcs = &dcn10_transform_funcs; + + xfm->tf_regs = tf_regs; + xfm->tf_shift = tf_shift; + xfm->tf_mask = tf_mask; + + xfm->lb_pixel_depth_supported = + LB_PIXEL_DEPTH_18BPP | + LB_PIXEL_DEPTH_24BPP | + LB_PIXEL_DEPTH_30BPP; + + xfm->lb_bits_per_entry = LB_BITS_PER_ENTRY; + xfm->lb_memory_size = LB_TOTAL_NUMBER_OF_ENTRIES; /*0x1404*/ + + return true; +} diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.h new file mode 100644 index 000000000000..7c0089d4293b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.h @@ -0,0 +1,416 @@ +/* Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_TRANSFORM_DCN10_H__ +#define __DAL_TRANSFORM_DCN10_H__ + +#include "transform.h" + +#define TO_DCN10_TRANSFORM(transform)\ + container_of(transform, struct dcn10_transform, base) + +/* TODO: Use correct number of taps. Using polaris values for now */ +#define LB_TOTAL_NUMBER_OF_ENTRIES 5124 +#define LB_BITS_PER_ENTRY 144 + +#define TF_SF(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define TF_REG_LIST_DCN(id) \ + SRI(DSCL_EXT_OVERSCAN_LEFT_RIGHT, DSCL, id), \ + SRI(DSCL_EXT_OVERSCAN_TOP_BOTTOM, DSCL, id), \ + SRI(OTG_H_BLANK, DSCL, id), \ + SRI(OTG_V_BLANK, DSCL, id), \ + SRI(SCL_MODE, DSCL, id), \ + SRI(LB_DATA_FORMAT, DSCL, id), \ + SRI(LB_MEMORY_CTRL, DSCL, id), \ + SRI(DSCL_AUTOCAL, DSCL, id), \ + SRI(SCL_BLACK_OFFSET, DSCL, id), \ + SRI(DSCL_CONTROL, DSCL, id), \ + SRI(SCL_TAP_CONTROL, DSCL, id), \ + SRI(SCL_COEF_RAM_TAP_SELECT, DSCL, id), \ + SRI(SCL_COEF_RAM_TAP_DATA, DSCL, id), \ + SRI(DSCL_2TAP_CONTROL, DSCL, id), \ + SRI(DCSURF_PRI_VIEWPORT_DIMENSION, HUBP, id), \ + SRI(DCSURF_PRI_VIEWPORT_START, HUBP, id), \ + SRI(DCSURF_SEC_VIEWPORT_DIMENSION, HUBP, id), \ + SRI(DCSURF_SEC_VIEWPORT_START, HUBP, id), \ + SRI(DCSURF_PRI_VIEWPORT_DIMENSION_C, HUBP, id), \ + SRI(DCSURF_PRI_VIEWPORT_START_C, HUBP, id), \ + SRI(CM_GAMUT_REMAP_CONTROL, CM, id), \ + SRI(MPC_SIZE, DSCL, id), \ + SRI(SCL_HORZ_FILTER_SCALE_RATIO, DSCL, id), \ + SRI(SCL_VERT_FILTER_SCALE_RATIO, DSCL, id), \ + SRI(SCL_HORZ_FILTER_SCALE_RATIO_C, DSCL, id), \ + SRI(SCL_VERT_FILTER_SCALE_RATIO_C, DSCL, id), \ + SRI(SCL_HORZ_FILTER_INIT, DSCL, id), \ + SRI(SCL_HORZ_FILTER_INIT_C, DSCL, id), \ + SRI(SCL_VERT_FILTER_INIT, DSCL, id), \ + SRI(SCL_VERT_FILTER_INIT_BOT, DSCL, id), \ + SRI(SCL_VERT_FILTER_INIT_C, DSCL, id), \ + SRI(SCL_VERT_FILTER_INIT_BOT_C, DSCL, id), \ + SRI(RECOUT_START, DSCL, id), \ + SRI(RECOUT_SIZE, DSCL, id), \ + SRI(CM_GAMUT_REMAP_CONTROL, CM, id),\ + SRI(CM_GAMUT_REMAP_C11_C12, CM, id),\ + SRI(CM_GAMUT_REMAP_C13_C14, CM, id),\ + SRI(CM_GAMUT_REMAP_C21_C22, CM, id),\ + SRI(CM_GAMUT_REMAP_C23_C24, CM, id),\ + SRI(CM_GAMUT_REMAP_C31_C32, CM, id),\ + SRI(CM_GAMUT_REMAP_C33_C34, CM, id),\ + SRI(CM_COMA_C11_C12, CM, id),\ + SRI(CM_COMA_C13_C14, CM, id),\ + SRI(CM_COMA_C21_C22, CM, id),\ + SRI(CM_COMA_C23_C24, CM, id),\ + SRI(CM_COMA_C31_C32, CM, id),\ + SRI(CM_COMA_C33_C34, CM, id),\ + SRI(CM_COMB_C11_C12, CM, id),\ + SRI(CM_COMB_C13_C14, CM, id),\ + SRI(CM_COMB_C21_C22, CM, id),\ + SRI(CM_COMB_C23_C24, CM, id),\ + SRI(CM_COMB_C31_C32, CM, id),\ + SRI(CM_COMB_C33_C34, CM, id) + + + +#define TF_REG_LIST_SH_MASK_DCN(mask_sh)\ + TF_SF(DSCL0_DSCL_EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_LEFT, mask_sh),\ + TF_SF(DSCL0_DSCL_EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_RIGHT, mask_sh),\ + TF_SF(DSCL0_DSCL_EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_BOTTOM, mask_sh),\ + TF_SF(DSCL0_DSCL_EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_TOP, mask_sh),\ + TF_SF(DSCL0_OTG_H_BLANK, OTG_H_BLANK_START, mask_sh),\ + TF_SF(DSCL0_OTG_H_BLANK, OTG_H_BLANK_END, mask_sh),\ + TF_SF(DSCL0_OTG_V_BLANK, OTG_V_BLANK_START, mask_sh),\ + TF_SF(DSCL0_OTG_V_BLANK, OTG_V_BLANK_END, mask_sh),\ + TF_SF(DSCL0_LB_DATA_FORMAT, PIXEL_DEPTH, mask_sh),\ + TF_SF(DSCL0_LB_DATA_FORMAT, PIXEL_EXPAN_MODE, mask_sh),\ + TF_SF(DSCL0_LB_DATA_FORMAT, PIXEL_REDUCE_MODE, mask_sh),\ + TF_SF(DSCL0_LB_DATA_FORMAT, DYNAMIC_PIXEL_DEPTH, mask_sh),\ + TF_SF(DSCL0_LB_DATA_FORMAT, DITHER_EN, mask_sh),\ + TF_SF(DSCL0_LB_DATA_FORMAT, INTERLEAVE_EN, mask_sh),\ + TF_SF(DSCL0_LB_DATA_FORMAT, ALPHA_EN, mask_sh),\ + TF_SF(DSCL0_LB_MEMORY_CTRL, MEMORY_CONFIG, mask_sh),\ + TF_SF(DSCL0_LB_MEMORY_CTRL, LB_MAX_PARTITIONS, mask_sh),\ + TF_SF(DSCL0_DSCL_AUTOCAL, AUTOCAL_MODE, mask_sh),\ + TF_SF(DSCL0_DSCL_AUTOCAL, AUTOCAL_NUM_PIPE, mask_sh),\ + TF_SF(DSCL0_DSCL_AUTOCAL, AUTOCAL_PIPE_ID, mask_sh),\ + TF_SF(DSCL0_SCL_BLACK_OFFSET, SCL_BLACK_OFFSET_RGB_Y, mask_sh),\ + TF_SF(DSCL0_SCL_BLACK_OFFSET, SCL_BLACK_OFFSET_CBCR, mask_sh),\ + TF_SF(DSCL0_DSCL_CONTROL, SCL_BOUNDARY_MODE, mask_sh),\ + TF_SF(DSCL0_SCL_TAP_CONTROL, SCL_V_NUM_TAPS, mask_sh),\ + TF_SF(DSCL0_SCL_TAP_CONTROL, SCL_H_NUM_TAPS, mask_sh),\ + TF_SF(DSCL0_SCL_TAP_CONTROL, SCL_V_NUM_TAPS_C, mask_sh),\ + TF_SF(DSCL0_SCL_TAP_CONTROL, SCL_H_NUM_TAPS_C, mask_sh),\ + TF_SF(DSCL0_SCL_COEF_RAM_TAP_SELECT, SCL_COEF_RAM_TAP_PAIR_IDX, mask_sh),\ + TF_SF(DSCL0_SCL_COEF_RAM_TAP_SELECT, SCL_COEF_RAM_PHASE, mask_sh),\ + TF_SF(DSCL0_SCL_COEF_RAM_TAP_SELECT, SCL_COEF_RAM_FILTER_TYPE, mask_sh),\ + TF_SF(DSCL0_SCL_COEF_RAM_TAP_DATA, SCL_COEF_RAM_EVEN_TAP_COEF, mask_sh),\ + TF_SF(DSCL0_SCL_COEF_RAM_TAP_DATA, SCL_COEF_RAM_EVEN_TAP_COEF_EN, mask_sh),\ + TF_SF(DSCL0_SCL_COEF_RAM_TAP_DATA, SCL_COEF_RAM_ODD_TAP_COEF, mask_sh),\ + TF_SF(DSCL0_SCL_COEF_RAM_TAP_DATA, SCL_COEF_RAM_ODD_TAP_COEF_EN, mask_sh),\ + TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_H_2TAP_HARDCODE_COEF_EN, mask_sh),\ + TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_H_2TAP_SHARP_EN, mask_sh),\ + TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_H_2TAP_SHARP_FACTOR, mask_sh),\ + TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_V_2TAP_HARDCODE_COEF_EN, mask_sh),\ + TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_V_2TAP_SHARP_EN, mask_sh),\ + TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_V_2TAP_SHARP_FACTOR, mask_sh),\ + TF_SF(DSCL0_SCL_MODE, SCL_COEF_RAM_SELECT, mask_sh),\ + TF_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION, PRI_VIEWPORT_WIDTH, mask_sh),\ + TF_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION, PRI_VIEWPORT_HEIGHT, mask_sh),\ + TF_SF(HUBP0_DCSURF_PRI_VIEWPORT_START, PRI_VIEWPORT_X_START, mask_sh),\ + TF_SF(HUBP0_DCSURF_PRI_VIEWPORT_START, PRI_VIEWPORT_Y_START, mask_sh),\ + TF_SF(HUBP0_DCSURF_SEC_VIEWPORT_DIMENSION, SEC_VIEWPORT_WIDTH, mask_sh),\ + TF_SF(HUBP0_DCSURF_SEC_VIEWPORT_DIMENSION, SEC_VIEWPORT_HEIGHT, mask_sh),\ + TF_SF(HUBP0_DCSURF_SEC_VIEWPORT_START, SEC_VIEWPORT_X_START, mask_sh),\ + TF_SF(HUBP0_DCSURF_SEC_VIEWPORT_START, SEC_VIEWPORT_Y_START, mask_sh),\ + TF_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION_C, PRI_VIEWPORT_WIDTH_C, mask_sh),\ + TF_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION_C, PRI_VIEWPORT_HEIGHT_C, mask_sh),\ + TF_SF(HUBP0_DCSURF_PRI_VIEWPORT_START_C, PRI_VIEWPORT_X_START_C, mask_sh),\ + TF_SF(HUBP0_DCSURF_PRI_VIEWPORT_START_C, PRI_VIEWPORT_Y_START_C, mask_sh),\ + TF_SF(DSCL0_SCL_MODE, DSCL_MODE, mask_sh),\ + TF_SF(DSCL0_RECOUT_START, RECOUT_START_X, mask_sh),\ + TF_SF(DSCL0_RECOUT_START, RECOUT_START_Y, mask_sh),\ + TF_SF(DSCL0_RECOUT_SIZE, RECOUT_WIDTH, mask_sh),\ + TF_SF(DSCL0_RECOUT_SIZE, RECOUT_HEIGHT, mask_sh),\ + TF_SF(DSCL0_MPC_SIZE, MPC_WIDTH, mask_sh),\ + TF_SF(DSCL0_MPC_SIZE, MPC_HEIGHT, mask_sh),\ + TF_SF(DSCL0_SCL_HORZ_FILTER_SCALE_RATIO, SCL_H_SCALE_RATIO, mask_sh),\ + TF_SF(DSCL0_SCL_VERT_FILTER_SCALE_RATIO, SCL_V_SCALE_RATIO, mask_sh),\ + TF_SF(DSCL0_SCL_HORZ_FILTER_SCALE_RATIO_C, SCL_H_SCALE_RATIO_C, mask_sh),\ + TF_SF(DSCL0_SCL_VERT_FILTER_SCALE_RATIO_C, SCL_V_SCALE_RATIO_C, mask_sh),\ + TF_SF(DSCL0_SCL_HORZ_FILTER_INIT, SCL_H_INIT_FRAC, mask_sh),\ + TF_SF(DSCL0_SCL_HORZ_FILTER_INIT, SCL_H_INIT_INT, mask_sh),\ + TF_SF(DSCL0_SCL_HORZ_FILTER_INIT_C, SCL_H_INIT_FRAC_C, mask_sh),\ + TF_SF(DSCL0_SCL_HORZ_FILTER_INIT_C, SCL_H_INIT_INT_C, mask_sh),\ + TF_SF(DSCL0_SCL_VERT_FILTER_INIT, SCL_V_INIT_FRAC, mask_sh),\ + TF_SF(DSCL0_SCL_VERT_FILTER_INIT, SCL_V_INIT_INT, mask_sh),\ + TF_SF(DSCL0_SCL_VERT_FILTER_INIT_BOT, SCL_V_INIT_FRAC_BOT, mask_sh),\ + TF_SF(DSCL0_SCL_VERT_FILTER_INIT_BOT, SCL_V_INIT_INT_BOT, mask_sh),\ + TF_SF(DSCL0_SCL_VERT_FILTER_INIT_C, SCL_V_INIT_FRAC_C, mask_sh),\ + TF_SF(DSCL0_SCL_VERT_FILTER_INIT_C, SCL_V_INIT_INT_C, mask_sh),\ + TF_SF(DSCL0_SCL_VERT_FILTER_INIT_BOT_C, SCL_V_INIT_FRAC_BOT_C, mask_sh),\ + TF_SF(DSCL0_SCL_VERT_FILTER_INIT_BOT_C, SCL_V_INIT_INT_BOT_C, mask_sh),\ + TF_SF(DSCL0_SCL_MODE, SCL_CHROMA_COEF_MODE, mask_sh),\ + TF_SF(DSCL0_SCL_MODE, SCL_COEF_RAM_SELECT_CURRENT, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_CONTROL, CM_GAMUT_REMAP_MODE, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C11_C12, CM_GAMUT_REMAP_C11, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C11_C12, CM_GAMUT_REMAP_C12, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C13_C14, CM_GAMUT_REMAP_C13, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C13_C14, CM_GAMUT_REMAP_C14, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C21_C22, CM_GAMUT_REMAP_C21, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C21_C22, CM_GAMUT_REMAP_C22, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C23_C24, CM_GAMUT_REMAP_C23, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C23_C24, CM_GAMUT_REMAP_C24, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C31_C32, CM_GAMUT_REMAP_C31, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C31_C32, CM_GAMUT_REMAP_C32, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C33_C34, CM_GAMUT_REMAP_C33, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C33_C34, CM_GAMUT_REMAP_C34, mask_sh),\ + TF_SF(CM0_CM_COMA_C11_C12, CM_COMA_C11, mask_sh),\ + TF_SF(CM0_CM_COMA_C11_C12, CM_COMA_C12, mask_sh),\ + TF_SF(CM0_CM_COMA_C13_C14, CM_COMA_C13, mask_sh),\ + TF_SF(CM0_CM_COMA_C13_C14, CM_COMA_C14, mask_sh),\ + TF_SF(CM0_CM_COMA_C21_C22, CM_COMA_C21, mask_sh),\ + TF_SF(CM0_CM_COMA_C21_C22, CM_COMA_C22, mask_sh),\ + TF_SF(CM0_CM_COMA_C23_C24, CM_COMA_C23, mask_sh),\ + TF_SF(CM0_CM_COMA_C23_C24, CM_COMA_C24, mask_sh),\ + TF_SF(CM0_CM_COMA_C31_C32, CM_COMA_C31, mask_sh),\ + TF_SF(CM0_CM_COMA_C31_C32, CM_COMA_C32, mask_sh),\ + TF_SF(CM0_CM_COMA_C33_C34, CM_COMA_C33, mask_sh),\ + TF_SF(CM0_CM_COMA_C33_C34, CM_COMA_C34, mask_sh),\ + TF_SF(CM0_CM_COMB_C11_C12, CM_COMB_C11, mask_sh),\ + TF_SF(CM0_CM_COMB_C11_C12, CM_COMB_C12, mask_sh),\ + TF_SF(CM0_CM_COMB_C13_C14, CM_COMB_C13, mask_sh),\ + TF_SF(CM0_CM_COMB_C13_C14, CM_COMB_C14, mask_sh),\ + TF_SF(CM0_CM_COMB_C21_C22, CM_COMB_C21, mask_sh),\ + TF_SF(CM0_CM_COMB_C21_C22, CM_COMB_C22, mask_sh),\ + TF_SF(CM0_CM_COMB_C23_C24, CM_COMB_C23, mask_sh),\ + TF_SF(CM0_CM_COMB_C23_C24, CM_COMB_C24, mask_sh),\ + TF_SF(CM0_CM_COMB_C31_C32, CM_COMB_C31, mask_sh),\ + TF_SF(CM0_CM_COMB_C33_C34, CM_COMB_C33, mask_sh),\ + TF_SF(CM0_CM_COMB_C31_C32, CM_COMB_C32, mask_sh),\ + TF_SF(CM0_CM_COMB_C33_C34, CM_COMB_C34, mask_sh) + + +#define TF_REG_FIELD_LIST(type) \ + type EXT_OVERSCAN_LEFT; \ + type EXT_OVERSCAN_RIGHT; \ + type EXT_OVERSCAN_BOTTOM; \ + type EXT_OVERSCAN_TOP; \ + type OTG_H_BLANK_START; \ + type OTG_H_BLANK_END; \ + type OTG_V_BLANK_START; \ + type OTG_V_BLANK_END; \ + type PIXEL_DEPTH; \ + type PIXEL_EXPAN_MODE; \ + type PIXEL_REDUCE_MODE; \ + type DYNAMIC_PIXEL_DEPTH; \ + type DITHER_EN; \ + type INTERLEAVE_EN; \ + type ALPHA_EN; \ + type MEMORY_CONFIG; \ + type LB_MAX_PARTITIONS; \ + type AUTOCAL_MODE; \ + type AUTOCAL_NUM_PIPE; \ + type AUTOCAL_PIPE_ID; \ + type SCL_BLACK_OFFSET_RGB_Y; \ + type SCL_BLACK_OFFSET_CBCR; \ + type SCL_BOUNDARY_MODE; \ + type SCL_V_NUM_TAPS; \ + type SCL_H_NUM_TAPS; \ + type SCL_V_NUM_TAPS_C; \ + type SCL_H_NUM_TAPS_C; \ + type SCL_COEF_RAM_TAP_PAIR_IDX; \ + type SCL_COEF_RAM_PHASE; \ + type SCL_COEF_RAM_FILTER_TYPE; \ + type SCL_COEF_RAM_EVEN_TAP_COEF; \ + type SCL_COEF_RAM_EVEN_TAP_COEF_EN; \ + type SCL_COEF_RAM_ODD_TAP_COEF; \ + type SCL_COEF_RAM_ODD_TAP_COEF_EN; \ + type SCL_H_2TAP_HARDCODE_COEF_EN; \ + type SCL_H_2TAP_SHARP_EN; \ + type SCL_H_2TAP_SHARP_FACTOR; \ + type SCL_V_2TAP_HARDCODE_COEF_EN; \ + type SCL_V_2TAP_SHARP_EN; \ + type SCL_V_2TAP_SHARP_FACTOR; \ + type SCL_COEF_RAM_SELECT; \ + type PRI_VIEWPORT_WIDTH; \ + type PRI_VIEWPORT_HEIGHT; \ + type PRI_VIEWPORT_X_START; \ + type PRI_VIEWPORT_Y_START; \ + type SEC_VIEWPORT_WIDTH; \ + type SEC_VIEWPORT_HEIGHT; \ + type SEC_VIEWPORT_X_START; \ + type SEC_VIEWPORT_Y_START; \ + type PRI_VIEWPORT_WIDTH_C; \ + type PRI_VIEWPORT_HEIGHT_C; \ + type PRI_VIEWPORT_X_START_C; \ + type PRI_VIEWPORT_Y_START_C; \ + type DSCL_MODE; \ + type RECOUT_START_X; \ + type RECOUT_START_Y; \ + type RECOUT_WIDTH; \ + type RECOUT_HEIGHT; \ + type MPC_WIDTH; \ + type MPC_HEIGHT; \ + type SCL_H_SCALE_RATIO; \ + type SCL_V_SCALE_RATIO; \ + type SCL_H_SCALE_RATIO_C; \ + type SCL_V_SCALE_RATIO_C; \ + type SCL_H_INIT_FRAC; \ + type SCL_H_INIT_INT; \ + type SCL_H_INIT_FRAC_C; \ + type SCL_H_INIT_INT_C; \ + type SCL_V_INIT_FRAC; \ + type SCL_V_INIT_INT; \ + type SCL_V_INIT_FRAC_BOT; \ + type SCL_V_INIT_INT_BOT; \ + type SCL_V_INIT_FRAC_C; \ + type SCL_V_INIT_INT_C; \ + type SCL_V_INIT_FRAC_BOT_C; \ + type SCL_V_INIT_INT_BOT_C; \ + type SCL_CHROMA_COEF_MODE; \ + type SCL_COEF_RAM_SELECT_CURRENT; \ + type CM_GAMUT_REMAP_MODE; \ + type CM_GAMUT_REMAP_C11; \ + type CM_GAMUT_REMAP_C12; \ + type CM_GAMUT_REMAP_C13; \ + type CM_GAMUT_REMAP_C14; \ + type CM_GAMUT_REMAP_C21; \ + type CM_GAMUT_REMAP_C22; \ + type CM_GAMUT_REMAP_C23; \ + type CM_GAMUT_REMAP_C24; \ + type CM_GAMUT_REMAP_C31; \ + type CM_GAMUT_REMAP_C32; \ + type CM_GAMUT_REMAP_C33; \ + type CM_GAMUT_REMAP_C34; \ + type CM_COMA_C11; \ + type CM_COMA_C12; \ + type CM_COMA_C13; \ + type CM_COMA_C14; \ + type CM_COMA_C21; \ + type CM_COMA_C22; \ + type CM_COMA_C23; \ + type CM_COMA_C24; \ + type CM_COMA_C31; \ + type CM_COMA_C32; \ + type CM_COMA_C33; \ + type CM_COMA_C34; \ + type CM_COMB_C11; \ + type CM_COMB_C12; \ + type CM_COMB_C13; \ + type CM_COMB_C14; \ + type CM_COMB_C21; \ + type CM_COMB_C22; \ + type CM_COMB_C23; \ + type CM_COMB_C24; \ + type CM_COMB_C31; \ + type CM_COMB_C32; \ + type CM_COMB_C33; \ + type CM_COMB_C34 + +struct dcn_transform_shift { + TF_REG_FIELD_LIST(uint8_t); +}; + +struct dcn_transform_mask { + TF_REG_FIELD_LIST(uint32_t); +}; + +struct dcn_transform_registers { + uint32_t DSCL_EXT_OVERSCAN_LEFT_RIGHT; + uint32_t DSCL_EXT_OVERSCAN_TOP_BOTTOM; + uint32_t OTG_H_BLANK; + uint32_t OTG_V_BLANK; + uint32_t SCL_MODE; + uint32_t LB_DATA_FORMAT; + uint32_t LB_MEMORY_CTRL; + uint32_t DSCL_AUTOCAL; + uint32_t SCL_BLACK_OFFSET; + uint32_t DSCL_CONTROL; + uint32_t SCL_TAP_CONTROL; + uint32_t SCL_COEF_RAM_TAP_SELECT; + uint32_t SCL_COEF_RAM_TAP_DATA; + uint32_t DSCL_2TAP_CONTROL; + uint32_t DCSURF_PRI_VIEWPORT_DIMENSION; + uint32_t DCSURF_PRI_VIEWPORT_START; + uint32_t DCSURF_SEC_VIEWPORT_DIMENSION; + uint32_t DCSURF_SEC_VIEWPORT_START; + uint32_t DCSURF_PRI_VIEWPORT_DIMENSION_C; + uint32_t DCSURF_PRI_VIEWPORT_START_C; + uint32_t MPC_SIZE; + uint32_t SCL_HORZ_FILTER_SCALE_RATIO; + uint32_t SCL_VERT_FILTER_SCALE_RATIO; + uint32_t SCL_HORZ_FILTER_SCALE_RATIO_C; + uint32_t SCL_VERT_FILTER_SCALE_RATIO_C; + uint32_t SCL_HORZ_FILTER_INIT; + uint32_t SCL_HORZ_FILTER_INIT_C; + uint32_t SCL_VERT_FILTER_INIT; + uint32_t SCL_VERT_FILTER_INIT_BOT; + uint32_t SCL_VERT_FILTER_INIT_C; + uint32_t SCL_VERT_FILTER_INIT_BOT_C; + uint32_t RECOUT_START; + uint32_t RECOUT_SIZE; + uint32_t CM_GAMUT_REMAP_CONTROL; + uint32_t CM_GAMUT_REMAP_C11_C12; + uint32_t CM_GAMUT_REMAP_C13_C14; + uint32_t CM_GAMUT_REMAP_C21_C22; + uint32_t CM_GAMUT_REMAP_C23_C24; + uint32_t CM_GAMUT_REMAP_C31_C32; + uint32_t CM_GAMUT_REMAP_C33_C34; + uint32_t CM_COMA_C11_C12; + uint32_t CM_COMA_C13_C14; + uint32_t CM_COMA_C21_C22; + uint32_t CM_COMA_C23_C24; + uint32_t CM_COMA_C31_C32; + uint32_t CM_COMA_C33_C34; + uint32_t CM_COMB_C11_C12; + uint32_t CM_COMB_C13_C14; + uint32_t CM_COMB_C21_C22; + uint32_t CM_COMB_C23_C24; + uint32_t CM_COMB_C31_C32; + uint32_t CM_COMB_C33_C34; +}; + +struct dcn10_transform { + struct transform base; + + const struct dcn_transform_registers *tf_regs; + const struct dcn_transform_shift *tf_shift; + const struct dcn_transform_mask *tf_mask; + + const uint16_t *filter_v; + const uint16_t *filter_h; + const uint16_t *filter_v_c; + const uint16_t *filter_h_c; + int lb_pixel_depth_supported; + int lb_memory_size; + int lb_bits_per_entry; +}; + +bool dcn10_transform_construct(struct dcn10_transform *xfm110, + struct dc_context *ctx, + const struct dcn_transform_registers *tf_regs, + const struct dcn_transform_shift *tf_shift, + const struct dcn_transform_mask *tf_mask); +#endif -- cgit From 061bfa06a42a9f6cd192bae61a4bf0e746eccb39 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 8 May 2017 15:20:38 -0400 Subject: drm/amdgpu/display: Add dml support for DCN Display mode lib handles clock, watermark, and bandwidth calculations for DCN. Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/Makefile | 22 + drivers/gpu/drm/amd/display/dc/dml/dc_features.h | 557 +++++ .../drm/amd/display/dc/dml/display_mode_enums.h | 111 + .../gpu/drm/amd/display/dc/dml/display_mode_lib.c | 147 ++ .../gpu/drm/amd/display/dc/dml/display_mode_lib.h | 52 + .../drm/amd/display/dc/dml/display_mode_structs.h | 429 ++++ .../drm/amd/display/dc/dml/display_mode_support.c | 2326 ++++++++++++++++++++ .../drm/amd/display/dc/dml/display_mode_support.h | 199 ++ .../drm/amd/display/dc/dml/display_pipe_clocks.c | 367 +++ .../drm/amd/display/dc/dml/display_pipe_clocks.h | 41 + .../drm/amd/display/dc/dml/display_rq_dlg_calc.c | 2254 +++++++++++++++++++ .../drm/amd/display/dc/dml/display_rq_dlg_calc.h | 139 ++ .../amd/display/dc/dml/display_rq_dlg_helpers.c | 320 +++ .../amd/display/dc/dml/display_rq_dlg_helpers.h | 66 + .../gpu/drm/amd/display/dc/dml/display_watermark.c | 1281 +++++++++++ .../gpu/drm/amd/display/dc/dml/display_watermark.h | 98 + .../gpu/drm/amd/display/dc/dml/dml_common_defs.c | 148 ++ .../gpu/drm/amd/display/dc/dml/dml_common_defs.h | 51 + .../gpu/drm/amd/display/dc/dml/soc_bounding_box.c | 73 + .../gpu/drm/amd/display/dc/dml/soc_bounding_box.h | 36 + 20 files changed, 8717 insertions(+) create mode 100644 drivers/gpu/drm/amd/display/dc/dml/Makefile create mode 100644 drivers/gpu/drm/amd/display/dc/dml/dc_features.h create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_mode_support.h create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.c create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.h create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.h create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.h create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_watermark.c create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_watermark.h create mode 100644 drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c create mode 100644 drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h create mode 100644 drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c create mode 100644 drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dml/Makefile b/drivers/gpu/drm/amd/display/dc/dml/Makefile new file mode 100644 index 000000000000..9d7791d00e97 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/Makefile @@ -0,0 +1,22 @@ +# +# Makefile for the 'utils' sub-component of DAL. +# It provides the general basic services required by other DAL +# subcomponents. + +CFLAGS_display_mode_lib.o := -mhard-float -msse -mpreferred-stack-boundary=4 +CFLAGS_display_pipe_clocks.o := -mhard-float -msse -mpreferred-stack-boundary=4 +CFLAGS_display_rq_dlg_calc.o := -mhard-float -msse -mpreferred-stack-boundary=4 +CFLAGS_display_rq_dlg_helpers.o := -mhard-float -msse -mpreferred-stack-boundary=4 +CFLAGS_display_watermark.o := -mhard-float -msse -mpreferred-stack-boundary=4 +CFLAGS_soc_bounding_box.o := -mhard-float -msse -mpreferred-stack-boundary=4 +CFLAGS_dml_common_defs.o := -mhard-float -msse -mpreferred-stack-boundary=4 +CFLAGS_display_mode_support.o := -mhard-float -msse -mpreferred-stack-boundary=4 + + +DML = display_mode_lib.o display_pipe_clocks.o display_rq_dlg_calc.o \ + display_rq_dlg_helpers.o display_watermark.o \ + soc_bounding_box.o dml_common_defs.o display_mode_support.o + +AMD_DAL_DML = $(addprefix $(AMDDALPATH)/dc/dml/,$(DML)) + +AMD_DISPLAY_FILES += $(AMD_DAL_DML) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dc_features.h b/drivers/gpu/drm/amd/display/dc/dml/dc_features.h new file mode 100644 index 000000000000..745c04cb764a --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/dc_features.h @@ -0,0 +1,557 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef __DC_FEATURES_H__ +#define __DC_FEATURES_H__ + +#define DC__PRESENT 1 +#define DC__PRESENT__1 1 +#define DC__NUM_DPP 4 +#define DC__NUM_DPP__4 1 +#define DC__NUM_DPP__0_PRESENT 1 +#define DC__NUM_DPP__1_PRESENT 1 +#define DC__NUM_DPP__2_PRESENT 1 +#define DC__NUM_DPP__3_PRESENT 1 +#define DC__NUM_DPP__MAX 8 +#define DC__NUM_DPP__MAX__8 1 +#define DC__PIPE_10BIT 0 +#define DC__PIPE_10BIT__0 1 +#define DC__PIPE_10BIT__MAX 1 +#define DC__PIPE_10BIT__MAX__1 1 +#define DC__NUM_OPP 4 +#define DC__NUM_OPP__4 1 +#define DC__NUM_OPP__0_PRESENT 1 +#define DC__NUM_OPP__1_PRESENT 1 +#define DC__NUM_OPP__2_PRESENT 1 +#define DC__NUM_OPP__3_PRESENT 1 +#define DC__NUM_OPP__MAX 6 +#define DC__NUM_OPP__MAX__6 1 +#define DC__NUM_DSC 0 +#define DC__NUM_DSC__0 1 +#define DC__NUM_DSC__MAX 6 +#define DC__NUM_DSC__MAX__6 1 +#define DC__NUM_ABM 1 +#define DC__NUM_ABM__1 1 +#define DC__NUM_ABM__0_PRESENT 1 +#define DC__NUM_ABM__MAX 2 +#define DC__NUM_ABM__MAX__2 1 +#define DC__ODM_PRESENT 0 +#define DC__ODM_PRESENT__0 1 +#define DC__NUM_OTG 4 +#define DC__NUM_OTG__4 1 +#define DC__NUM_OTG__0_PRESENT 1 +#define DC__NUM_OTG__1_PRESENT 1 +#define DC__NUM_OTG__2_PRESENT 1 +#define DC__NUM_OTG__3_PRESENT 1 +#define DC__NUM_OTG__MAX 6 +#define DC__NUM_OTG__MAX__6 1 +#define DC__NUM_DWB 2 +#define DC__NUM_DWB__2 1 +#define DC__NUM_DWB__0_PRESENT 1 +#define DC__NUM_DWB__1_PRESENT 1 +#define DC__NUM_DWB__MAX 2 +#define DC__NUM_DWB__MAX__2 1 +#define DC__NUM_DIG 4 +#define DC__NUM_DIG__4 1 +#define DC__NUM_DIG__0_PRESENT 1 +#define DC__NUM_DIG__1_PRESENT 1 +#define DC__NUM_DIG__2_PRESENT 1 +#define DC__NUM_DIG__3_PRESENT 1 +#define DC__NUM_DIG__MAX 6 +#define DC__NUM_DIG__MAX__6 1 +#define DC__NUM_AUX 4 +#define DC__NUM_AUX__4 1 +#define DC__NUM_AUX__0_PRESENT 1 +#define DC__NUM_AUX__1_PRESENT 1 +#define DC__NUM_AUX__2_PRESENT 1 +#define DC__NUM_AUX__3_PRESENT 1 +#define DC__NUM_AUX__MAX 6 +#define DC__NUM_AUX__MAX__6 1 +#define DC__NUM_AUDIO_STREAMS 4 +#define DC__NUM_AUDIO_STREAMS__4 1 +#define DC__NUM_AUDIO_STREAMS__0_PRESENT 1 +#define DC__NUM_AUDIO_STREAMS__1_PRESENT 1 +#define DC__NUM_AUDIO_STREAMS__2_PRESENT 1 +#define DC__NUM_AUDIO_STREAMS__3_PRESENT 1 +#define DC__NUM_AUDIO_STREAMS__MAX 8 +#define DC__NUM_AUDIO_STREAMS__MAX__8 1 +#define DC__NUM_AUDIO_ENDPOINTS 6 +#define DC__NUM_AUDIO_ENDPOINTS__6 1 +#define DC__NUM_AUDIO_ENDPOINTS__0_PRESENT 1 +#define DC__NUM_AUDIO_ENDPOINTS__1_PRESENT 1 +#define DC__NUM_AUDIO_ENDPOINTS__2_PRESENT 1 +#define DC__NUM_AUDIO_ENDPOINTS__3_PRESENT 1 +#define DC__NUM_AUDIO_ENDPOINTS__4_PRESENT 1 +#define DC__NUM_AUDIO_ENDPOINTS__5_PRESENT 1 +#define DC__NUM_AUDIO_ENDPOINTS__MAX 8 +#define DC__NUM_AUDIO_ENDPOINTS__MAX__8 1 +#define DC__NUM_AUDIO_INPUT_STREAMS 0 +#define DC__NUM_AUDIO_INPUT_STREAMS__0 1 +#define DC__NUM_AUDIO_INPUT_STREAMS__MAX 8 +#define DC__NUM_AUDIO_INPUT_STREAMS__MAX__8 1 +#define DC__NUM_AUDIO_INPUT_ENDPOINTS 0 +#define DC__NUM_AUDIO_INPUT_ENDPOINTS__0 1 +#define DC__NUM_AUDIO_INPUT_ENDPOINTS__MAX 8 +#define DC__NUM_AUDIO_INPUT_ENDPOINTS__MAX__8 1 +#define DC__NUM_CURSOR 1 +#define DC__NUM_CURSOR__1 1 +#define DC__NUM_CURSOR__0_PRESENT 1 +#define DC__NUM_CURSOR__MAX 2 +#define DC__NUM_CURSOR__MAX__2 1 +#define DC__DIGITAL_BYPASS_PRESENT 0 +#define DC__DIGITAL_BYPASS_PRESENT__0 1 +#define DC__HCID_HWMAJVER 1 +#define DC__HCID_HWMAJVER__1 1 +#define DC__HCID_HWMINVER 0 +#define DC__HCID_HWMINVER__0 1 +#define DC__HCID_HWREV 0 +#define DC__HCID_HWREV__0 1 +#define DC__ROMSTRAP_PRESENT 0 +#define DC__ROMSTRAP_PRESENT__0 1 +#define DC__NUM_RBBMIF_DECODES 30 +#define DC__NUM_RBBMIF_DECODES__30 1 +#define DC__NUM_DBG_REGS 36 +#define DC__NUM_DBG_REGS__36 1 +#define DC__NUM_PIPES_UNDERLAY 0 +#define DC__NUM_PIPES_UNDERLAY__0 1 +#define DC__NUM_PIPES_UNDERLAY__MAX 2 +#define DC__NUM_PIPES_UNDERLAY__MAX__2 1 +#define DC__NUM_VCE_ENGINE 1 +#define DC__NUM_VCE_ENGINE__1 1 +#define DC__NUM_VCE_ENGINE__0_PRESENT 1 +#define DC__NUM_VCE_ENGINE__MAX 2 +#define DC__NUM_VCE_ENGINE__MAX__2 1 +#define DC__OTG_EXTERNAL_SYNC_PRESENT 0 +#define DC__OTG_EXTERNAL_SYNC_PRESENT__0 1 +#define DC__OTG_CRC_PRESENT 1 +#define DC__OTG_CRC_PRESENT__1 1 +#define DC__VIP_PRESENT 0 +#define DC__VIP_PRESENT__0 1 +#define DC__DTMTEST_PRESENT 0 +#define DC__DTMTEST_PRESENT__0 1 +#define DC__POWER_GATE_PRESENT 1 +#define DC__POWER_GATE_PRESENT__1 1 +#define DC__MEM_PG 1 +#define DC__MEM_PG__1 1 +#define DC__FMT_SRC_SEL_PRESENT 0 +#define DC__FMT_SRC_SEL_PRESENT__0 1 +#define DC__DIG_FEATURES__HDMI_PRESENT 1 +#define DC__DIG_FEATURES__HDMI_PRESENT__1 1 +#define DC__DIG_FEATURES__DP_PRESENT 1 +#define DC__DIG_FEATURES__DP_PRESENT__1 1 +#define DC__DIG_FEATURES__DP_MST_PRESENT 1 +#define DC__DIG_FEATURES__DP_MST_PRESENT__1 1 +#define DC__DIG_LP_FEATURES__HDMI_PRESENT 0 +#define DC__DIG_LP_FEATURES__HDMI_PRESENT__0 1 +#define DC__DIG_LP_FEATURES__DP_PRESENT 1 +#define DC__DIG_LP_FEATURES__DP_PRESENT__1 1 +#define DC__DIG_LP_FEATURES__DP_MST_PRESENT 0 +#define DC__DIG_LP_FEATURES__DP_MST_PRESENT__0 1 +#define DC__DIG_RESYNC_FIFO_SIZE 14 +#define DC__DIG_RESYNC_FIFO_SIZE__14 1 +#define DC__DIG_RESYNC_FIFO_SIZE__0_PRESENT 1 +#define DC__DIG_RESYNC_FIFO_SIZE__1_PRESENT 1 +#define DC__DIG_RESYNC_FIFO_SIZE__2_PRESENT 1 +#define DC__DIG_RESYNC_FIFO_SIZE__3_PRESENT 1 +#define DC__DIG_RESYNC_FIFO_SIZE__4_PRESENT 1 +#define DC__DIG_RESYNC_FIFO_SIZE__5_PRESENT 1 +#define DC__DIG_RESYNC_FIFO_SIZE__6_PRESENT 1 +#define DC__DIG_RESYNC_FIFO_SIZE__7_PRESENT 1 +#define DC__DIG_RESYNC_FIFO_SIZE__8_PRESENT 1 +#define DC__DIG_RESYNC_FIFO_SIZE__9_PRESENT 1 +#define DC__DIG_RESYNC_FIFO_SIZE__10_PRESENT 1 +#define DC__DIG_RESYNC_FIFO_SIZE__11_PRESENT 1 +#define DC__DIG_RESYNC_FIFO_SIZE__12_PRESENT 1 +#define DC__DIG_RESYNC_FIFO_SIZE__13_PRESENT 1 +#define DC__DIG_RESYNC_FIFO_SIZE__MAX 16 +#define DC__DIG_RESYNC_FIFO_SIZE__MAX__16 1 +#define DC__DAC_RESYNC_FIFO_SIZE 12 +#define DC__DAC_RESYNC_FIFO_SIZE__12 1 +#define DC__DAC_RESYNC_FIFO_SIZE__0_PRESENT 1 +#define DC__DAC_RESYNC_FIFO_SIZE__1_PRESENT 1 +#define DC__DAC_RESYNC_FIFO_SIZE__2_PRESENT 1 +#define DC__DAC_RESYNC_FIFO_SIZE__3_PRESENT 1 +#define DC__DAC_RESYNC_FIFO_SIZE__4_PRESENT 1 +#define DC__DAC_RESYNC_FIFO_SIZE__5_PRESENT 1 +#define DC__DAC_RESYNC_FIFO_SIZE__6_PRESENT 1 +#define DC__DAC_RESYNC_FIFO_SIZE__7_PRESENT 1 +#define DC__DAC_RESYNC_FIFO_SIZE__8_PRESENT 1 +#define DC__DAC_RESYNC_FIFO_SIZE__9_PRESENT 1 +#define DC__DAC_RESYNC_FIFO_SIZE__10_PRESENT 1 +#define DC__DAC_RESYNC_FIFO_SIZE__11_PRESENT 1 +#define DC__DAC_RESYNC_FIFO_SIZE__MAX 16 +#define DC__DAC_RESYNC_FIFO_SIZE__MAX__16 1 +#define DC__DVO_RESYNC_FIFO_SIZE 12 +#define DC__DVO_RESYNC_FIFO_SIZE__12 1 +#define DC__DVO_RESYNC_FIFO_SIZE__0_PRESENT 1 +#define DC__DVO_RESYNC_FIFO_SIZE__1_PRESENT 1 +#define DC__DVO_RESYNC_FIFO_SIZE__2_PRESENT 1 +#define DC__DVO_RESYNC_FIFO_SIZE__3_PRESENT 1 +#define DC__DVO_RESYNC_FIFO_SIZE__4_PRESENT 1 +#define DC__DVO_RESYNC_FIFO_SIZE__5_PRESENT 1 +#define DC__DVO_RESYNC_FIFO_SIZE__6_PRESENT 1 +#define DC__DVO_RESYNC_FIFO_SIZE__7_PRESENT 1 +#define DC__DVO_RESYNC_FIFO_SIZE__8_PRESENT 1 +#define DC__DVO_RESYNC_FIFO_SIZE__9_PRESENT 1 +#define DC__DVO_RESYNC_FIFO_SIZE__10_PRESENT 1 +#define DC__DVO_RESYNC_FIFO_SIZE__11_PRESENT 1 +#define DC__DVO_RESYNC_FIFO_SIZE__MAX 16 +#define DC__DVO_RESYNC_FIFO_SIZE__MAX__16 1 +#define DC__MEM_CDC_PRESENT 1 +#define DC__MEM_CDC_PRESENT__1 1 +#define DC__NUM_HPD 4 +#define DC__NUM_HPD__4 1 +#define DC__NUM_HPD__0_PRESENT 1 +#define DC__NUM_HPD__1_PRESENT 1 +#define DC__NUM_HPD__2_PRESENT 1 +#define DC__NUM_HPD__3_PRESENT 1 +#define DC__NUM_HPD__MAX 6 +#define DC__NUM_HPD__MAX__6 1 +#define DC__NUM_DDC_PAIRS 4 +#define DC__NUM_DDC_PAIRS__4 1 +#define DC__NUM_DDC_PAIRS__0_PRESENT 1 +#define DC__NUM_DDC_PAIRS__1_PRESENT 1 +#define DC__NUM_DDC_PAIRS__2_PRESENT 1 +#define DC__NUM_DDC_PAIRS__3_PRESENT 1 +#define DC__NUM_DDC_PAIRS__MAX 6 +#define DC__NUM_DDC_PAIRS__MAX__6 1 +#define DC__NUM_AUDIO_PLL 0 +#define DC__NUM_AUDIO_PLL__0 1 +#define DC__NUM_AUDIO_PLL__MAX 2 +#define DC__NUM_AUDIO_PLL__MAX__2 1 +#define DC__NUM_PIXEL_PLL 1 +#define DC__NUM_PIXEL_PLL__1 1 +#define DC__NUM_PIXEL_PLL__0_PRESENT 1 +#define DC__NUM_PIXEL_PLL__MAX 4 +#define DC__NUM_PIXEL_PLL__MAX__4 1 +#define DC__NUM_CASCADED_PLL 0 +#define DC__NUM_CASCADED_PLL__0 1 +#define DC__NUM_CASCADED_PLL__MAX 3 +#define DC__NUM_CASCADED_PLL__MAX__3 1 +#define DC__PIXCLK_FROM_PHYPLL 1 +#define DC__PIXCLK_FROM_PHYPLL__1 1 +#define DC__NB_STUTTER_MODE_PRESENT 0 +#define DC__NB_STUTTER_MODE_PRESENT__0 1 +#define DC__I2S0_AND_SPDIF0_PRESENT 0 +#define DC__I2S0_AND_SPDIF0_PRESENT__0 1 +#define DC__I2S1_PRESENT 0 +#define DC__I2S1_PRESENT__0 1 +#define DC__SPDIF1_PRESENT 0 +#define DC__SPDIF1_PRESENT__0 1 +#define DC__DSI_PRESENT 0 +#define DC__DSI_PRESENT__0 1 +#define DC__DACA_PRESENT 0 +#define DC__DACA_PRESENT__0 1 +#define DC__DACB_PRESENT 0 +#define DC__DACB_PRESENT__0 1 +#define DC__NUM_PIPES 4 +#define DC__NUM_PIPES__4 1 +#define DC__NUM_PIPES__0_PRESENT 1 +#define DC__NUM_PIPES__1_PRESENT 1 +#define DC__NUM_PIPES__2_PRESENT 1 +#define DC__NUM_PIPES__3_PRESENT 1 +#define DC__NUM_PIPES__MAX 6 +#define DC__NUM_PIPES__MAX__6 1 +#define DC__NUM_DIG_LP 0 +#define DC__NUM_DIG_LP__0 1 +#define DC__NUM_DIG_LP__MAX 2 +#define DC__NUM_DIG_LP__MAX__2 1 +#define DC__DPDEBUG_PRESENT 0 +#define DC__DPDEBUG_PRESENT__0 1 +#define DC__DISPLAY_WB_PRESENT 1 +#define DC__DISPLAY_WB_PRESENT__1 1 +#define DC__NUM_CWB 0 +#define DC__NUM_CWB__0 1 +#define DC__NUM_CWB__MAX 2 +#define DC__NUM_CWB__MAX__2 1 +#define DC__MVP_PRESENT 0 +#define DC__MVP_PRESENT__0 1 +#define DC__DVO_PRESENT 0 +#define DC__DVO_PRESENT__0 1 +#define DC__ABM_PRESENT 0 +#define DC__ABM_PRESENT__0 1 +#define DC__BPHYC_PLL_PRESENT 0 +#define DC__BPHYC_PLL_PRESENT__0 1 +#define DC__BPHYC_UNIPHY_PRESENT 0 +#define DC__BPHYC_UNIPHY_PRESENT__0 1 +#define DC__PHY_BROADCAST_PRESENT 0 +#define DC__PHY_BROADCAST_PRESENT__0 1 +#define DC__NUM_OF_DCRX_SD 0 +#define DC__NUM_OF_DCRX_SD__0 1 +#define DC__DVO_17BIT_MAPPING 0 +#define DC__DVO_17BIT_MAPPING__0 1 +#define DC__AVSYNC_PRESENT 0 +#define DC__AVSYNC_PRESENT__0 1 +#define DC__NUM_OF_DCRX_PORTS 0 +#define DC__NUM_OF_DCRX_PORTS__0 1 +#define DC__NUM_OF_DCRX_PORTS__MAX 1 +#define DC__NUM_OF_DCRX_PORTS__MAX__1 1 +#define DC__NUM_PHY 4 +#define DC__NUM_PHY__4 1 +#define DC__NUM_PHY__0_PRESENT 1 +#define DC__NUM_PHY__1_PRESENT 1 +#define DC__NUM_PHY__2_PRESENT 1 +#define DC__NUM_PHY__3_PRESENT 1 +#define DC__NUM_PHY__MAX 7 +#define DC__NUM_PHY__MAX__7 1 +#define DC__NUM_PHY_LP 0 +#define DC__NUM_PHY_LP__0 1 +#define DC__NUM_PHY_LP__MAX 2 +#define DC__NUM_PHY_LP__MAX__2 1 +#define DC__SYNC_CELL vid_sync_gf14lpp +#define DC__SYNC_CELL__VID_SYNC_GF14LPP 1 +#define DC__USE_NEW_VSS 1 +#define DC__USE_NEW_VSS__1 1 +#define DC__SYNC_CELL_DISPCLK_NUM_LATCHES 6 +#define DC__SYNC_CELL_DISPCLK_NUM_LATCHES__6 1 +#define DC__SYNC_CELL_DVOCLK_NUM_LATCHES 6 +#define DC__SYNC_CELL_DVOCLK_NUM_LATCHES__6 1 +#define DC__SYNC_CELL_PIXCLK_NUM_LATCHES 6 +#define DC__SYNC_CELL_PIXCLK_NUM_LATCHES__6 1 +#define DC__SYNC_CELL_SYMCLK_NUM_LATCHES 6 +#define DC__SYNC_CELL_SYMCLK_NUM_LATCHES__6 1 +#define DC__SYNC_CELL_DPPCLK_NUM_LATCHES 6 +#define DC__SYNC_CELL_DPPCLK_NUM_LATCHES__6 1 +#define DC__SYNC_CELL_DPREFCLK_NUM_LATCHES 6 +#define DC__SYNC_CELL_DPREFCLK_NUM_LATCHES__6 1 +#define DC__SYNC_CELL_REFCLK_NUM_LATCHES 6 +#define DC__SYNC_CELL_REFCLK_NUM_LATCHES__6 1 +#define DC__SYNC_CELL_PCIE_REFCLK_NUM_LATCHES 6 +#define DC__SYNC_CELL_PCIE_REFCLK_NUM_LATCHES__6 1 +#define DC__SYNC_CELL_MVPCLK_NUM_LATCHES 6 +#define DC__SYNC_CELL_MVPCLK_NUM_LATCHES__6 1 +#define DC__SYNC_CELL_SCLK_NUM_LATCHES 6 +#define DC__SYNC_CELL_SCLK_NUM_LATCHES__6 1 +#define DC__SYNC_CELL_DCEFCLK_NUM_LATCHES 6 +#define DC__SYNC_CELL_DCEFCLK_NUM_LATCHES__6 1 +#define DC__SYNC_CELL_AMCLK_NUM_LATCHES 6 +#define DC__SYNC_CELL_AMCLK_NUM_LATCHES__6 1 +#define DC__SYNC_CELL_DSICLK_NUM_LATCHES 6 +#define DC__SYNC_CELL_DSICLK_NUM_LATCHES__6 1 +#define DC__SYNC_CELL_BYTECLK_NUM_LATCHES 6 +#define DC__SYNC_CELL_BYTECLK_NUM_LATCHES__6 1 +#define DC__SYNC_CELL_ESCCLK_NUM_LATCHES 6 +#define DC__SYNC_CELL_ESCCLK_NUM_LATCHES__6 1 +#define DC__SYNC_CELL_DB_CLK_NUM_LATCHES 6 +#define DC__SYNC_CELL_DB_CLK_NUM_LATCHES__6 1 +#define UNIPHYA_PRESENT 1 +#define UNIPHYA_PRESENT__1 1 +#define DC__UNIPHYA_PRESENT 1 +#define DC__UNIPHYA_PRESENT__1 1 +#define UNIPHYB_PRESENT 1 +#define UNIPHYB_PRESENT__1 1 +#define DC__UNIPHYB_PRESENT 1 +#define DC__UNIPHYB_PRESENT__1 1 +#define UNIPHYC_PRESENT 1 +#define UNIPHYC_PRESENT__1 1 +#define DC__UNIPHYC_PRESENT 1 +#define DC__UNIPHYC_PRESENT__1 1 +#define UNIPHYD_PRESENT 1 +#define UNIPHYD_PRESENT__1 1 +#define DC__UNIPHYD_PRESENT 1 +#define DC__UNIPHYD_PRESENT__1 1 +#define UNIPHYE_PRESENT 0 +#define UNIPHYE_PRESENT__0 1 +#define DC__UNIPHYE_PRESENT 0 +#define DC__UNIPHYE_PRESENT__0 1 +#define UNIPHYF_PRESENT 0 +#define UNIPHYF_PRESENT__0 1 +#define DC__UNIPHYF_PRESENT 0 +#define DC__UNIPHYF_PRESENT__0 1 +#define UNIPHYG_PRESENT 0 +#define UNIPHYG_PRESENT__0 1 +#define DC__UNIPHYG_PRESENT 0 +#define DC__UNIPHYG_PRESENT__0 1 +#define DC__TMDS_LINK tmds_link_dual +#define DC__TMDS_LINK__TMDS_LINK_DUAL 1 +#define DC__WBSCL_PIXBW 8 +#define DC__WBSCL_PIXBW__8 1 +#define DC__DWB_CSC_PRESENT 0 +#define DC__DWB_CSC_PRESENT__0 1 +#define DC__DWB_LUMA_SCL_PRESENT 0 +#define DC__DWB_LUMA_SCL_PRESENT__0 1 +#define DC__DENTIST_INTERFACE_PRESENT 1 +#define DC__DENTIST_INTERFACE_PRESENT__1 1 +#define DC__GENERICA_PRESENT 1 +#define DC__GENERICA_PRESENT__1 1 +#define DC__GENERICB_PRESENT 1 +#define DC__GENERICB_PRESENT__1 1 +#define DC__GENERICC_PRESENT 0 +#define DC__GENERICC_PRESENT__0 1 +#define DC__GENERICD_PRESENT 0 +#define DC__GENERICD_PRESENT__0 1 +#define DC__GENERICE_PRESENT 0 +#define DC__GENERICE_PRESENT__0 1 +#define DC__GENERICF_PRESENT 0 +#define DC__GENERICF_PRESENT__0 1 +#define DC__GENERICG_PRESENT 0 +#define DC__GENERICG_PRESENT__0 1 +#define DC__UNIPHY_VOLTAGE_MODE 1 +#define DC__UNIPHY_VOLTAGE_MODE__1 1 +#define DC__BLON_TYPE dedicated +#define DC__BLON_TYPE__DEDICATED 1 +#define DC__UNIPHY_STAGGER_CH_PRESENT 1 +#define DC__UNIPHY_STAGGER_CH_PRESENT__1 1 +#define DC__XDMA_PRESENT 0 +#define DC__XDMA_PRESENT__0 1 +#define XDMA__PRESENT 0 +#define XDMA__PRESENT__0 1 +#define DC__DP_MEM_PG 0 +#define DC__DP_MEM_PG__0 1 +#define DP__MEM_PG 0 +#define DP__MEM_PG__0 1 +#define DC__AFMT_MEM_PG 0 +#define DC__AFMT_MEM_PG__0 1 +#define AFMT__MEM_PG 0 +#define AFMT__MEM_PG__0 1 +#define DC__HDMI_MEM_PG 0 +#define DC__HDMI_MEM_PG__0 1 +#define HDMI__MEM_PG 0 +#define HDMI__MEM_PG__0 1 +#define DC__I2C_MEM_PG 0 +#define DC__I2C_MEM_PG__0 1 +#define I2C__MEM_PG 0 +#define I2C__MEM_PG__0 1 +#define DC__DSCL_MEM_PG 0 +#define DC__DSCL_MEM_PG__0 1 +#define DSCL__MEM_PG 0 +#define DSCL__MEM_PG__0 1 +#define DC__CM_MEM_PG 0 +#define DC__CM_MEM_PG__0 1 +#define CM__MEM_PG 0 +#define CM__MEM_PG__0 1 +#define DC__OBUF_MEM_PG 0 +#define DC__OBUF_MEM_PG__0 1 +#define OBUF__MEM_PG 0 +#define OBUF__MEM_PG__0 1 +#define DC__WBIF_MEM_PG 1 +#define DC__WBIF_MEM_PG__1 1 +#define WBIF__MEM_PG 1 +#define WBIF__MEM_PG__1 1 +#define DC__VGA_MEM_PG 0 +#define DC__VGA_MEM_PG__0 1 +#define VGA__MEM_PG 0 +#define VGA__MEM_PG__0 1 +#define DC__FMT_MEM_PG 0 +#define DC__FMT_MEM_PG__0 1 +#define FMT__MEM_PG 0 +#define FMT__MEM_PG__0 1 +#define DC__ODM_MEM_PG 0 +#define DC__ODM_MEM_PG__0 1 +#define ODM__MEM_PG 0 +#define ODM__MEM_PG__0 1 +#define DC__DSI_MEM_PG 0 +#define DC__DSI_MEM_PG__0 1 +#define DSI__MEM_PG 0 +#define DSI__MEM_PG__0 1 +#define DC__AZ_MEM_PG 1 +#define DC__AZ_MEM_PG__1 1 +#define AZ__MEM_PG 1 +#define AZ__MEM_PG__1 1 +#define DC__WBSCL_MEM1P1024X64QS_MEM_PG 1 +#define DC__WBSCL_MEM1P1024X64QS_MEM_PG__1 1 +#define WBSCL_MEM1P1024X64QS__MEM_PG 1 +#define WBSCL_MEM1P1024X64QS__MEM_PG__1 1 +#define DC__WBSCL_MEM1P528X64QS_MEM_PG 1 +#define DC__WBSCL_MEM1P528X64QS_MEM_PG__1 1 +#define WBSCL_MEM1P528X64QS__MEM_PG 1 +#define WBSCL_MEM1P528X64QS__MEM_PG__1 1 +#define DC__DMCU_MEM1P1024X32BQS_MEM_PG 1 +#define DC__DMCU_MEM1P1024X32BQS_MEM_PG__1 1 +#define DMCU_MEM1P1024X32BQS__MEM_PG 1 +#define DMCU_MEM1P1024X32BQS__MEM_PG__1 1 +#define DC__HUBBUB_SDP_TAG_INT_MEM_PG 0 +#define DC__HUBBUB_SDP_TAG_INT_MEM_PG__0 1 +#define HUBBUB_SDP_TAG_INT__MEM_PG 0 +#define HUBBUB_SDP_TAG_INT__MEM_PG__0 1 +#define DC__HUBBUB_SDP_TAG_EXT_MEM_PG 0 +#define DC__HUBBUB_SDP_TAG_EXT_MEM_PG__0 1 +#define HUBBUB_SDP_TAG_EXT__MEM_PG 0 +#define HUBBUB_SDP_TAG_EXT__MEM_PG__0 1 +#define DC__HUBBUB_RET_ZERO_MEM_PG 0 +#define DC__HUBBUB_RET_ZERO_MEM_PG__0 1 +#define HUBBUB_RET_ZERO__MEM_PG 0 +#define HUBBUB_RET_ZERO__MEM_PG__0 1 +#define DC__HUBBUB_RET_ROB_MEM_PG 0 +#define DC__HUBBUB_RET_ROB_MEM_PG__0 1 +#define HUBBUB_RET_ROB__MEM_PG 0 +#define HUBBUB_RET_ROB__MEM_PG__0 1 +#define DC__HUBPRET_CUR_ROB_MEM_PG 0 +#define DC__HUBPRET_CUR_ROB_MEM_PG__0 1 +#define HUBPRET_CUR_ROB__MEM_PG 0 +#define HUBPRET_CUR_ROB__MEM_PG__0 1 +#define DC__HUBPRET_CUR_CDC_MEM_PG 0 +#define DC__HUBPRET_CUR_CDC_MEM_PG__0 1 +#define HUBPRET_CUR_CDC__MEM_PG 0 +#define HUBPRET_CUR_CDC__MEM_PG__0 1 +#define DC__HUBPREQ_MPTE_MEM_PG 0 +#define DC__HUBPREQ_MPTE_MEM_PG__0 1 +#define HUBPREQ_MPTE__MEM_PG 0 +#define HUBPREQ_MPTE__MEM_PG__0 1 +#define DC__HUBPREQ_META_MEM_PG 0 +#define DC__HUBPREQ_META_MEM_PG__0 1 +#define HUBPREQ_META__MEM_PG 0 +#define HUBPREQ_META__MEM_PG__0 1 +#define DC__HUBPREQ_DPTE_MEM_PG 0 +#define DC__HUBPREQ_DPTE_MEM_PG__0 1 +#define HUBPREQ_DPTE__MEM_PG 0 +#define HUBPREQ_DPTE__MEM_PG__0 1 +#define DC__HUBPRET_DET_MEM_PG 0 +#define DC__HUBPRET_DET_MEM_PG__0 1 +#define HUBPRET_DET__MEM_PG 0 +#define HUBPRET_DET__MEM_PG__0 1 +#define DC__HUBPRET_PIX_CDC_MEM_PG 0 +#define DC__HUBPRET_PIX_CDC_MEM_PG__0 1 +#define HUBPRET_PIX_CDC__MEM_PG 0 +#define HUBPRET_PIX_CDC__MEM_PG__0 1 +#define DC__TOP_BLKS__DCCG 1 +#define DC__TOP_BLKS__DCHUBBUB 1 +#define DC__TOP_BLKS__DCHUBP 1 +#define DC__TOP_BLKS__HDA 1 +#define DC__TOP_BLKS__DIO 1 +#define DC__TOP_BLKS__DCIO 1 +#define DC__TOP_BLKS__DMU 1 +#define DC__TOP_BLKS__DPP 1 +#define DC__TOP_BLKS__MPC 1 +#define DC__TOP_BLKS__OPP 1 +#define DC__TOP_BLKS__OPTC 1 +#define DC__TOP_BLKS__MMHUBBUB 1 +#define DC__TOP_BLKS__WB 1 +#define DC__TOP_BLKS__MAX 13 +#define DC__TOP_BLKS__MAX__13 1 +#define DC__DCHUBP_DPP_SF_PIXEL_CREDITS 9 +#define DC__DCHUBP_DPP_SF_PIXEL_CREDITS__9 1 +#define DC__DPP_MPC_SF_PIXEL_CREDITS 9 +#define DC__DPP_MPC_SF_PIXEL_CREDITS__9 1 +#define DC__MPC_OPP_SF_PIXEL_CREDITS 8 +#define DC__MPC_OPP_SF_PIXEL_CREDITS__8 1 +#define DC__OPP_OPTC_SF_PIXEL_CREDITS 8 +#define DC__OPP_OPTC_SF_PIXEL_CREDITS__8 1 +#define DC__SFR_SFT_ROUND_TRIP_DELAY 5 +#define DC__SFR_SFT_ROUND_TRIP_DELAY__5 1 +#define DC__REPEATER_PROJECT_MAX 8 +#define DC__REPEATER_PROJECT_MAX__8 1 +#define DC__SURFACE_422_CAPABLE 0 +#define DC__SURFACE_422_CAPABLE__0 1 +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h new file mode 100644 index 000000000000..143a3d418de0 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h @@ -0,0 +1,111 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef __DISPLAY_MODE_ENUMS_H__ +#define __DISPLAY_MODE_ENUMS_H__ +enum output_encoder_class { + dm_dp = 0, + dm_hdmi = 1, + dm_wb = 2 +}; +enum output_format_class { + dm_444 = 0, + dm_420 = 1 +}; +enum source_format_class { + dm_444_16 = 0, + dm_444_32 = 1, + dm_444_64 = 2, + dm_420_8 = 3, + dm_420_10 = 4, + dm_422_8 = 5, + dm_422_10 = 6 +}; +enum output_bpc_class { + dm_out_6 = 0, + dm_out_8 = 1, + dm_out_10 = 2, + dm_out_12 = 3, + dm_out_16 = 4 +}; +enum scan_direction_class { + dm_horz = 0, + dm_vert = 1 +}; +enum dm_swizzle_mode { + dm_sw_linear = 0, + dm_sw_256b_s = 1, + dm_sw_256b_d = 2, + dm_sw_SPARE_0 = 3, + dm_sw_SPARE_1 = 4, + dm_sw_4kb_s = 5, + dm_sw_4kb_d = 6, + dm_sw_SPARE_2 = 7, + dm_sw_SPARE_3 = 8, + dm_sw_64kb_s = 9, + dm_sw_64kb_d = 10, + dm_sw_SPARE_4 = 11, + dm_sw_SPARE_5 = 12, + dm_sw_var_s = 13, + dm_sw_var_d = 14, + dm_sw_SPARE_6 = 15, + dm_sw_SPARE_7 = 16, + dm_sw_64kb_s_t = 17, + dm_sw_64kb_d_t = 18, + dm_sw_SPARE_10 = 19, + dm_sw_SPARE_11 = 20, + dm_sw_4kb_s_x = 21, + dm_sw_4kb_d_x = 22, + dm_sw_SPARE_12 = 23, + dm_sw_SPARE_13 = 24, + dm_sw_64kb_s_x = 25, + dm_sw_64kb_d_x = 26, + dm_sw_SPARE_14 = 27, + dm_sw_SPARE_15 = 28, + dm_sw_var_s_x = 29, + dm_sw_var_d_x = 30 +}; +enum lb_depth { + dm_lb_10 = 30, + dm_lb_8 = 24, + dm_lb_6 = 18, + dm_lb_12 = 36 +}; +enum voltage_state { + dm_vmin = 0, + dm_vmid = 1, + dm_vnom = 2, + dm_vmax = 3, + dm_vmax_exceeded = 4 +}; +enum source_macro_tile_size { + dm_4k_tile = 0, + dm_64k_tile = 1, + dm_256k_tile = 2 +}; +enum cursor_bpp { + dm_cur_2bit = 0, + dm_cur_32bit = 1 +}; +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c new file mode 100644 index 000000000000..c02c5522613b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c @@ -0,0 +1,147 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "display_mode_lib.h" + +static void set_soc_bounding_box(struct _vcs_dpi_soc_bounding_box_st *soc, enum dml_project project) +{ + if (project == DML_PROJECT_RAVEN1) { + soc->sr_exit_time_us = 9.0; + soc->sr_enter_plus_exit_time_us = 11.0; + soc->urgent_latency_us = 4.0; + soc->writeback_latency_us = 12.0; + soc->ideal_dram_bw_after_urgent_percent = 80.0; + soc->max_request_size_bytes = 256; + + soc->vmin.dcfclk_mhz = 300.0; + soc->vmin.dispclk_mhz = 608.0; + soc->vmin.dppclk_mhz = 435.0; + soc->vmin.dram_bw_per_chan_gbps = 12.8; + soc->vmin.phyclk_mhz = 540.0; + soc->vmin.socclk_mhz = 208.0; + + soc->vmid.dcfclk_mhz = 600.0; + soc->vmid.dispclk_mhz = 661.0; + soc->vmid.dppclk_mhz = 661.0; + soc->vmid.dram_bw_per_chan_gbps = 12.8; + soc->vmid.phyclk_mhz = 540.0; + soc->vmid.socclk_mhz = 208.0; + + soc->vnom.dcfclk_mhz = 600.0; + soc->vnom.dispclk_mhz = 661.0; + soc->vnom.dppclk_mhz = 661.0; + soc->vnom.dram_bw_per_chan_gbps = 38.4; + soc->vnom.phyclk_mhz = 810; + soc->vnom.socclk_mhz = 208.0; + + soc->vmax.dcfclk_mhz = 600.0; + soc->vmax.dispclk_mhz = 1086.0; + soc->vmax.dppclk_mhz = 661.0; + soc->vmax.dram_bw_per_chan_gbps = 38.4; + soc->vmax.phyclk_mhz = 810.0; + soc->vmax.socclk_mhz = 208.0; + + soc->downspread_percent = 0.5; + soc->dram_page_open_time_ns = 50.0; + soc->dram_rw_turnaround_time_ns = 17.5; + soc->dram_return_buffer_per_channel_bytes = 8192; + soc->round_trip_ping_latency_dcfclk_cycles = 128; + soc->urgent_out_of_order_return_per_channel_bytes = 256; + soc->channel_interleave_bytes = 256; + soc->num_banks = 8; + soc->num_chans = 2; + soc->vmm_page_size_bytes = 4096; + soc->dram_clock_change_latency_us = 17.0; + soc->writeback_dram_clock_change_latency_us = 23.0; + soc->return_bus_width_bytes = 64; + } else { + BREAK_TO_DEBUGGER(); /* Invalid Project Specified */ + } +} + +static void set_ip_params(struct _vcs_dpi_ip_params_st *ip, enum dml_project project) +{ + if (project == DML_PROJECT_RAVEN1) { + ip->rob_buffer_size_kbytes = 64; + ip->det_buffer_size_kbytes = 164; + ip->dpte_buffer_size_in_pte_reqs = 42; + ip->dpp_output_buffer_pixels = 2560; + ip->opp_output_buffer_lines = 1; + ip->pixel_chunk_size_kbytes = 8; + ip->pte_enable = 1; + ip->pte_chunk_size_kbytes = 2; + ip->meta_chunk_size_kbytes = 2; + ip->writeback_chunk_size_kbytes = 2; + ip->line_buffer_size_bits = 589824; + ip->max_line_buffer_lines = 12; + ip->IsLineBufferBppFixed = 0; + ip->LineBufferFixedBpp = -1; + ip->writeback_luma_buffer_size_kbytes = 12; + ip->writeback_chroma_buffer_size_kbytes = 8; + ip->max_num_dpp = 4; + ip->max_num_wb = 2; + ip->max_dchub_pscl_bw_pix_per_clk = 4; + ip->max_pscl_lb_bw_pix_per_clk = 2; + ip->max_lb_vscl_bw_pix_per_clk = 4; + ip->max_vscl_hscl_bw_pix_per_clk = 4; + ip->max_hscl_ratio = 4; + ip->max_vscl_ratio = 4; + ip->hscl_mults = 4; + ip->vscl_mults = 4; + ip->max_hscl_taps = 8; + ip->max_vscl_taps = 8; + ip->dispclk_ramp_margin_percent = 1; + ip->underscan_factor = 1.10; + ip->min_vblank_lines = 14; + ip->dppclk_delay_subtotal = 90; + ip->dispclk_delay_subtotal = 42; + ip->dcfclk_cstate_latency = 10; + ip->max_inter_dcn_tile_repeaters = 8; + ip->can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one = 0; + ip->bug_forcing_LC_req_same_size_fixed = 0; + } else { + BREAK_TO_DEBUGGER(); /* Invalid Project Specified */ + } +} + +static void set_mode_evaluation(struct _vcs_dpi_mode_evaluation_st *me, enum dml_project project) +{ + if (project == DML_PROJECT_RAVEN1) { + me->voltage_override = dm_vmin; + } else { + BREAK_TO_DEBUGGER(); /* Invalid Project Specified */ + } +} + +void dml_init_instance(struct display_mode_lib *lib, enum dml_project project) +{ + if (lib->project != project) { + set_soc_bounding_box(&lib->soc, project); + set_ip_params(&lib->ip, project); + set_mode_evaluation(&lib->me, project); + lib->project = project; + } +} + diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h new file mode 100644 index 000000000000..e2e311138358 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h @@ -0,0 +1,52 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef __DISPLAY_MODE_LIB_H__ +#define __DISPLAY_MODE_LIB_H__ + +#include "dml_common_defs.h" +#include "soc_bounding_box.h" +#include "display_watermark.h" +#include "display_pipe_clocks.h" +#include "display_rq_dlg_calc.h" +#include "display_mode_support.h" + +enum dml_project { + DML_PROJECT_UNDEFINED, + DML_PROJECT_RAVEN1 +}; + +struct display_mode_lib { + struct _vcs_dpi_ip_params_st ip; + struct _vcs_dpi_soc_bounding_box_st soc; + struct _vcs_dpi_mode_evaluation_st me; + enum dml_project project; + struct dml_ms_internal_vars vars; + struct _vcs_dpi_wm_calc_pipe_params_st wm_param[DC__NUM_PIPES__MAX]; + struct dal_logger *logger; +}; + +void dml_init_instance(struct display_mode_lib *lib, enum dml_project project); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h new file mode 100644 index 000000000000..e589a5eadb6a --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h @@ -0,0 +1,429 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef __DISPLAY_MODE_STRUCTS_H__ +#define __DISPLAY_MODE_STRUCTS_H__ + +struct _vcs_dpi_voltage_scaling_st { + double dcfclk_mhz; + double dispclk_mhz; + double dppclk_mhz; + double dram_bw_per_chan_gbps; + double phyclk_mhz; + double socclk_mhz; +}; + +struct _vcs_dpi_soc_bounding_box_st { + double sr_exit_time_us; + double sr_enter_plus_exit_time_us; + double urgent_latency_us; + double writeback_latency_us; + double ideal_dram_bw_after_urgent_percent; + unsigned int max_request_size_bytes; + struct _vcs_dpi_voltage_scaling_st vmin; + struct _vcs_dpi_voltage_scaling_st vmid; + struct _vcs_dpi_voltage_scaling_st vnom; + struct _vcs_dpi_voltage_scaling_st vmax; + double downspread_percent; + double dram_page_open_time_ns; + double dram_rw_turnaround_time_ns; + double dram_return_buffer_per_channel_bytes; + unsigned int round_trip_ping_latency_dcfclk_cycles; + unsigned int urgent_out_of_order_return_per_channel_bytes; + unsigned int channel_interleave_bytes; + unsigned int num_banks; + unsigned int num_chans; + unsigned int vmm_page_size_bytes; + double dram_clock_change_latency_us; + double writeback_dram_clock_change_latency_us; + unsigned int return_bus_width_bytes; +}; + +struct _vcs_dpi_ip_params_st { + unsigned int rob_buffer_size_kbytes; + unsigned int det_buffer_size_kbytes; + unsigned int dpte_buffer_size_in_pte_reqs; + unsigned int dpp_output_buffer_pixels; + unsigned int opp_output_buffer_lines; + unsigned int pixel_chunk_size_kbytes; + unsigned char pte_enable; + unsigned int pte_chunk_size_kbytes; + unsigned int meta_chunk_size_kbytes; + unsigned int writeback_chunk_size_kbytes; + unsigned int line_buffer_size_bits; + unsigned int max_line_buffer_lines; + unsigned int IsLineBufferBppFixed; + unsigned int LineBufferFixedBpp; + unsigned int writeback_luma_buffer_size_kbytes; + unsigned int writeback_chroma_buffer_size_kbytes; + unsigned int max_num_dpp; + unsigned int max_num_wb; + unsigned int max_dchub_pscl_bw_pix_per_clk; + unsigned int max_pscl_lb_bw_pix_per_clk; + unsigned int max_lb_vscl_bw_pix_per_clk; + unsigned int max_vscl_hscl_bw_pix_per_clk; + double max_hscl_ratio; + double max_vscl_ratio; + unsigned int hscl_mults; + unsigned int vscl_mults; + unsigned int max_hscl_taps; + unsigned int max_vscl_taps; + double dispclk_ramp_margin_percent; + double underscan_factor; + unsigned int min_vblank_lines; + unsigned int dppclk_delay_subtotal; + unsigned int dispclk_delay_subtotal; + unsigned int dcfclk_cstate_latency; + unsigned int max_inter_dcn_tile_repeaters; + unsigned int can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one; + unsigned int bug_forcing_LC_req_same_size_fixed; +}; + +struct _vcs_dpi_display_pipe_source_params_st { + int source_format; + unsigned char dcc; + unsigned int dcc_rate; + unsigned char vm; + int source_scan; + int sw_mode; + int macro_tile_size; + unsigned char is_display_sw; + unsigned int viewport_width; + unsigned int viewport_height; + unsigned int viewport_width_c; + unsigned int viewport_height_c; + unsigned int data_pitch; + unsigned int data_pitch_c; + unsigned int meta_pitch; + unsigned int meta_pitch_c; + unsigned int cur0_src_width; + int cur0_bpp; + unsigned char is_hsplit; + unsigned int hsplit_grp; +}; + +struct _vcs_dpi_display_output_params_st { + int output_bpc; + int output_type; + int output_format; + int output_standard; +}; + +struct _vcs_dpi_display_bandwidth_st { + double total_bw_consumed_gbps; + double guaranteed_urgent_return_bw_gbps; +}; + +struct _vcs_dpi_scaler_ratio_depth_st { + double hscl_ratio; + double vscl_ratio; + double hscl_ratio_c; + double vscl_ratio_c; + double vinit; + double vinit_c; + double vinit_bot; + double vinit_bot_c; + int lb_depth; +}; + +struct _vcs_dpi_scaler_taps_st { + unsigned int htaps; + unsigned int vtaps; + unsigned int htaps_c; + unsigned int vtaps_c; +}; + +struct _vcs_dpi_display_pipe_dest_params_st { + unsigned int recout_width; + unsigned int recout_height; + unsigned int full_recout_width; + unsigned int full_recout_height; + unsigned int hblank_start; + unsigned int hblank_end; + unsigned int vblank_start; + unsigned int vblank_end; + unsigned int htotal; + unsigned int vtotal; + unsigned int vactive; + unsigned int vstartup_start; + unsigned int vupdate_offset; + unsigned int vupdate_width; + unsigned int vready_offset; + unsigned int vsync_plus_back_porch; + unsigned char interlaced; + unsigned char underscan; + double pixel_rate_mhz; + unsigned char syncronized_vblank_all_planes; +}; + +struct _vcs_dpi_display_pipe_params_st { + struct _vcs_dpi_display_pipe_source_params_st src; + struct _vcs_dpi_display_pipe_dest_params_st dest; + struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth; + struct _vcs_dpi_scaler_taps_st scale_taps; +}; + +struct _vcs_dpi_display_clocks_and_cfg_st { + int voltage; + double dppclk_mhz; + double refclk_mhz; + double dispclk_mhz; + double dcfclk_mhz; + double socclk_mhz; +}; + +struct _vcs_dpi_display_e2e_pipe_params_st { + struct _vcs_dpi_display_pipe_params_st pipe; + struct _vcs_dpi_display_output_params_st dout; + struct _vcs_dpi_display_clocks_and_cfg_st clks_cfg; +}; + +struct _vcs_dpi_dchub_buffer_sizing_st { + unsigned int swath_width_y; + unsigned int swath_height_y; + unsigned int swath_height_c; + unsigned int detail_buffer_size_y; +}; + +struct _vcs_dpi_watermarks_perf_st { + double stutter_eff_in_active_region_percent; + double urgent_latency_supported_us; + double non_urgent_latency_supported_us; + double dram_clock_change_margin_us; + double dram_access_eff_percent; +}; + +struct _vcs_dpi_cstate_pstate_watermarks_st { + double cstate_exit_us; + double cstate_enter_plus_exit_us; + double pstate_change_us; +}; + +struct _vcs_dpi_wm_calc_pipe_params_st { + unsigned int num_dpp; + int voltage; + int output_type; + double dcfclk_mhz; + double socclk_mhz; + double dppclk_mhz; + double pixclk_mhz; + unsigned char interlace_en; + unsigned char pte_enable; + unsigned char dcc_enable; + double dcc_rate; + double bytes_per_pixel_c; + double bytes_per_pixel_y; + unsigned int swath_width_y; + unsigned int swath_height_y; + unsigned int swath_height_c; + unsigned int det_buffer_size_y; + double h_ratio; + double v_ratio; + unsigned int h_taps; + unsigned int h_total; + unsigned int v_total; + unsigned int v_active; + unsigned int e2e_index; + double display_pipe_line_delivery_time; + double read_bw; + unsigned int lines_in_det_y; + unsigned int lines_in_det_y_rounded_down_to_swath; + double full_det_buffering_time; + double dcfclk_deepsleep_mhz_per_plane; +}; + +struct _vcs_dpi_vratio_pre_st { + double vratio_pre_l; + double vratio_pre_c; +}; + +struct _vcs_dpi_display_data_rq_misc_params_st { + unsigned int full_swath_bytes; + unsigned int stored_swath_bytes; + unsigned int blk256_height; + unsigned int blk256_width; + unsigned int req_height; + unsigned int req_width; +}; + +struct _vcs_dpi_display_data_rq_sizing_params_st { + unsigned int chunk_bytes; + unsigned int min_chunk_bytes; + unsigned int meta_chunk_bytes; + unsigned int min_meta_chunk_bytes; + unsigned int mpte_group_bytes; + unsigned int dpte_group_bytes; +}; + +struct _vcs_dpi_display_data_rq_dlg_params_st { + unsigned int swath_width_ub; + unsigned int swath_height; + unsigned int req_per_swath_ub; + unsigned int meta_pte_bytes_per_frame_ub; + unsigned int dpte_req_per_row_ub; + unsigned int dpte_groups_per_row_ub; + unsigned int dpte_row_height; + unsigned int dpte_bytes_per_row_ub; + unsigned int meta_chunks_per_row_ub; + unsigned int meta_req_per_row_ub; + unsigned int meta_row_height; + unsigned int meta_bytes_per_row_ub; +}; + +struct _vcs_dpi_display_cur_rq_dlg_params_st { + unsigned char enable; + unsigned int swath_height; + unsigned int req_per_line; +}; + +struct _vcs_dpi_display_rq_dlg_params_st { + struct _vcs_dpi_display_data_rq_dlg_params_st rq_l; + struct _vcs_dpi_display_data_rq_dlg_params_st rq_c; + struct _vcs_dpi_display_cur_rq_dlg_params_st rq_cur0; +}; + +struct _vcs_dpi_display_rq_sizing_params_st { + struct _vcs_dpi_display_data_rq_sizing_params_st rq_l; + struct _vcs_dpi_display_data_rq_sizing_params_st rq_c; +}; + +struct _vcs_dpi_display_rq_misc_params_st { + struct _vcs_dpi_display_data_rq_misc_params_st rq_l; + struct _vcs_dpi_display_data_rq_misc_params_st rq_c; +}; + +struct _vcs_dpi_display_rq_params_st { + unsigned char yuv420; + unsigned char yuv420_10bpc; + struct _vcs_dpi_display_rq_misc_params_st misc; + struct _vcs_dpi_display_rq_sizing_params_st sizing; + struct _vcs_dpi_display_rq_dlg_params_st dlg; +}; + +struct _vcs_dpi_display_dlg_regs_st { + unsigned int refcyc_h_blank_end; + unsigned int dlg_vblank_end; + unsigned int min_dst_y_next_start; + unsigned int refcyc_per_htotal; + unsigned int refcyc_x_after_scaler; + unsigned int dst_y_after_scaler; + unsigned int dst_y_prefetch; + unsigned int dst_y_per_vm_vblank; + unsigned int dst_y_per_row_vblank; + unsigned int ref_freq_to_pix_freq; + unsigned int vratio_prefetch; + unsigned int vratio_prefetch_c; + unsigned int refcyc_per_pte_group_vblank_l; + unsigned int refcyc_per_pte_group_vblank_c; + unsigned int refcyc_per_meta_chunk_vblank_l; + unsigned int refcyc_per_meta_chunk_vblank_c; + unsigned int dst_y_per_pte_row_nom_l; + unsigned int dst_y_per_pte_row_nom_c; + unsigned int refcyc_per_pte_group_nom_l; + unsigned int refcyc_per_pte_group_nom_c; + unsigned int dst_y_per_meta_row_nom_l; + unsigned int dst_y_per_meta_row_nom_c; + unsigned int refcyc_per_meta_chunk_nom_l; + unsigned int refcyc_per_meta_chunk_nom_c; + unsigned int refcyc_per_line_delivery_pre_l; + unsigned int refcyc_per_line_delivery_pre_c; + unsigned int refcyc_per_line_delivery_l; + unsigned int refcyc_per_line_delivery_c; + unsigned int chunk_hdl_adjust_cur0; +}; + +struct _vcs_dpi_display_ttu_regs_st { + unsigned int qos_level_low_wm; + unsigned int qos_level_high_wm; + unsigned int min_ttu_vblank; + unsigned int qos_level_flip; + unsigned int refcyc_per_req_delivery_l; + unsigned int refcyc_per_req_delivery_c; + unsigned int refcyc_per_req_delivery_cur0; + unsigned int refcyc_per_req_delivery_pre_l; + unsigned int refcyc_per_req_delivery_pre_c; + unsigned int refcyc_per_req_delivery_pre_cur0; + unsigned int qos_level_fixed_l; + unsigned int qos_level_fixed_c; + unsigned int qos_level_fixed_cur0; + unsigned int qos_ramp_disable_l; + unsigned int qos_ramp_disable_c; + unsigned int qos_ramp_disable_cur0; +}; + +struct _vcs_dpi_display_data_rq_regs_st { + unsigned int chunk_size; + unsigned int min_chunk_size; + unsigned int meta_chunk_size; + unsigned int min_meta_chunk_size; + unsigned int dpte_group_size; + unsigned int mpte_group_size; + unsigned int swath_height; + unsigned int pte_row_height_linear; +}; + +struct _vcs_dpi_display_rq_regs_st { + struct _vcs_dpi_display_data_rq_regs_st rq_regs_l; + struct _vcs_dpi_display_data_rq_regs_st rq_regs_c; + unsigned int drq_expansion_mode; + unsigned int prq_expansion_mode; + unsigned int mrq_expansion_mode; + unsigned int crq_expansion_mode; + unsigned int plane1_base_address; +}; + +struct _vcs_dpi_display_dlg_sys_params_st { + double t_mclk_wm_us; + double t_urg_wm_us; + double t_sr_wm_us; + double t_extra_us; + double t_srx_delay_us; + double deepsleep_dcfclk_mhz; + double total_flip_bw; + unsigned int total_flip_bytes; +}; + +struct _vcs_dpi_display_dlg_prefetch_param_st { + double prefetch_bw; + unsigned int flip_bytes; +}; + +struct _vcs_dpi_display_pipe_clock_st { + double dcfclk_mhz; + double dispclk_mhz; + double dppclk_mhz[4]; + unsigned char dppclk_div[4]; +}; + +struct _vcs_dpi_display_arb_params_st { + int max_req_outstanding; + int min_req_outstanding; + int sat_level_us; +}; + +struct _vcs_dpi_mode_evaluation_st { + int voltage_override; +}; + +#endif /*__DISPLAY_MODE_STRUCTS_H__*/ diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c new file mode 100644 index 000000000000..3b4ee74527f5 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c @@ -0,0 +1,2326 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "display_mode_support.h" +#include "display_mode_lib.h" + +int dml_ms_check( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + int num_pipes) +{ + struct _vcs_dpi_ip_params_st *ip; + struct _vcs_dpi_soc_bounding_box_st *soc; + struct _vcs_dpi_mode_evaluation_st *me; + struct dml_ms_internal_vars *v; + int num_planes, i, j, ij, k, ijk; + + ip = &(mode_lib->ip); + soc = &(mode_lib->soc); + me = &(mode_lib->me); + v = &(mode_lib->vars); + num_planes = dml_wm_e2e_to_wm(mode_lib, e2e, num_pipes, v->planes); + + //instantiating variables to zero + v->MacroTileBlockWidthC = 0; + v->SwathWidthGranularityC = 0; + + v->DCFCLKPerState[5] = 0; + v->DCFCLKPerState[4] = 0; + v->DCFCLKPerState[3] = 0; + v->DCFCLKPerState[2] = 0; + v->DCFCLKPerState[1] = 0; + v->DCFCLKPerState[0] = 0; + + if (soc->vmin.dcfclk_mhz > 0) { + v->DCFCLKPerState[5] = soc->vmin.dcfclk_mhz; + v->DCFCLKPerState[4] = soc->vmin.dcfclk_mhz; + v->DCFCLKPerState[3] = soc->vmin.dcfclk_mhz; + v->DCFCLKPerState[2] = soc->vmin.dcfclk_mhz; + v->DCFCLKPerState[1] = soc->vmin.dcfclk_mhz; + v->DCFCLKPerState[0] = soc->vmin.dcfclk_mhz; + } + + if (soc->vmid.dcfclk_mhz > 0) { + v->DCFCLKPerState[5] = soc->vmid.dcfclk_mhz; + v->DCFCLKPerState[4] = soc->vmid.dcfclk_mhz; + v->DCFCLKPerState[3] = soc->vmid.dcfclk_mhz; + v->DCFCLKPerState[2] = soc->vmid.dcfclk_mhz; + v->DCFCLKPerState[1] = soc->vmid.dcfclk_mhz; + } + + if (soc->vnom.dcfclk_mhz > 0) { + v->DCFCLKPerState[5] = soc->vnom.dcfclk_mhz; + v->DCFCLKPerState[4] = soc->vnom.dcfclk_mhz; + v->DCFCLKPerState[3] = soc->vnom.dcfclk_mhz; + v->DCFCLKPerState[2] = soc->vnom.dcfclk_mhz; + } + + if (soc->vmax.dcfclk_mhz > 0) { + v->DCFCLKPerState[5] = soc->vmax.dcfclk_mhz; + v->DCFCLKPerState[4] = soc->vmax.dcfclk_mhz; + v->DCFCLKPerState[3] = soc->vmax.dcfclk_mhz; + } + + v->FabricAndDRAMBandwidthPerState[5] = 0; + v->FabricAndDRAMBandwidthPerState[4] = 0; + v->FabricAndDRAMBandwidthPerState[3] = 0; + v->FabricAndDRAMBandwidthPerState[2] = 0; + v->FabricAndDRAMBandwidthPerState[1] = 0; + v->FabricAndDRAMBandwidthPerState[0] = 0; + + if (soc->vmin.dram_bw_per_chan_gbps > 0) { + v->FabricAndDRAMBandwidthPerState[5] = soc->vmin.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[4] = soc->vmin.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[3] = soc->vmin.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[2] = soc->vmin.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[1] = soc->vmin.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[0] = soc->vmin.dram_bw_per_chan_gbps; + } + + if (soc->vmid.dram_bw_per_chan_gbps > 0) { + v->FabricAndDRAMBandwidthPerState[5] = soc->vmid.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[4] = soc->vmid.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[3] = soc->vmid.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[2] = soc->vmid.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[1] = soc->vmid.dram_bw_per_chan_gbps; + } + + if (soc->vnom.dram_bw_per_chan_gbps > 0) { + v->FabricAndDRAMBandwidthPerState[5] = soc->vnom.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[4] = soc->vnom.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[3] = soc->vnom.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[2] = soc->vnom.dram_bw_per_chan_gbps; + } + + if (soc->vmax.dram_bw_per_chan_gbps > 0) { + v->FabricAndDRAMBandwidthPerState[5] = soc->vmax.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[4] = soc->vmax.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[3] = soc->vmax.dram_bw_per_chan_gbps; + } + + v->PHYCLKPerState[5] = 0; + v->PHYCLKPerState[4] = 0; + v->PHYCLKPerState[3] = 0; + v->PHYCLKPerState[2] = 0; + v->PHYCLKPerState[1] = 0; + v->PHYCLKPerState[0] = 0; + + if (soc->vmin.phyclk_mhz > 0) { + v->PHYCLKPerState[5] = soc->vmin.phyclk_mhz; + v->PHYCLKPerState[4] = soc->vmin.phyclk_mhz; + v->PHYCLKPerState[3] = soc->vmin.phyclk_mhz; + v->PHYCLKPerState[2] = soc->vmin.phyclk_mhz; + v->PHYCLKPerState[1] = soc->vmin.phyclk_mhz; + v->PHYCLKPerState[0] = soc->vmin.phyclk_mhz; + } + + if (soc->vmid.phyclk_mhz > 0) { + v->PHYCLKPerState[5] = soc->vmid.phyclk_mhz; + v->PHYCLKPerState[4] = soc->vmid.phyclk_mhz; + v->PHYCLKPerState[3] = soc->vmid.phyclk_mhz; + v->PHYCLKPerState[2] = soc->vmid.phyclk_mhz; + v->PHYCLKPerState[1] = soc->vmid.phyclk_mhz; + } + + if (soc->vnom.phyclk_mhz > 0) { + v->PHYCLKPerState[5] = soc->vnom.phyclk_mhz; + v->PHYCLKPerState[4] = soc->vnom.phyclk_mhz; + v->PHYCLKPerState[3] = soc->vnom.phyclk_mhz; + v->PHYCLKPerState[2] = soc->vnom.phyclk_mhz; + } + + if (soc->vmax.phyclk_mhz > 0) { + v->PHYCLKPerState[5] = soc->vmax.phyclk_mhz; + v->PHYCLKPerState[4] = soc->vmax.phyclk_mhz; + v->PHYCLKPerState[3] = soc->vmax.phyclk_mhz; + } + + v->MaxDispclk[5] = 0; + v->MaxDispclk[4] = 0; + v->MaxDispclk[3] = 0; + v->MaxDispclk[2] = 0; + v->MaxDispclk[1] = 0; + v->MaxDispclk[0] = 0; + + if (soc->vmin.dispclk_mhz > 0) { + v->MaxDispclk[5] = soc->vmin.dispclk_mhz; + v->MaxDispclk[4] = soc->vmin.dispclk_mhz; + v->MaxDispclk[3] = soc->vmin.dispclk_mhz; + v->MaxDispclk[2] = soc->vmin.dispclk_mhz; + v->MaxDispclk[1] = soc->vmin.dispclk_mhz; + v->MaxDispclk[0] = soc->vmin.dispclk_mhz; + } + + if (soc->vmid.dispclk_mhz > 0) { + v->MaxDispclk[5] = soc->vmid.dispclk_mhz; + v->MaxDispclk[4] = soc->vmid.dispclk_mhz; + v->MaxDispclk[3] = soc->vmid.dispclk_mhz; + v->MaxDispclk[2] = soc->vmid.dispclk_mhz; + v->MaxDispclk[1] = soc->vmid.dispclk_mhz; + } + + if (soc->vnom.dispclk_mhz > 0) { + v->MaxDispclk[5] = soc->vnom.dispclk_mhz; + v->MaxDispclk[4] = soc->vnom.dispclk_mhz; + v->MaxDispclk[3] = soc->vnom.dispclk_mhz; + v->MaxDispclk[2] = soc->vnom.dispclk_mhz; + } + + if (soc->vmax.dispclk_mhz > 0) { + v->MaxDispclk[5] = soc->vmax.dispclk_mhz; + v->MaxDispclk[4] = soc->vmax.dispclk_mhz; + v->MaxDispclk[3] = soc->vmax.dispclk_mhz; + } + + v->MaxDppclk[5] = 0; + v->MaxDppclk[4] = 0; + v->MaxDppclk[3] = 0; + v->MaxDppclk[2] = 0; + v->MaxDppclk[1] = 0; + v->MaxDppclk[0] = 0; + + if (soc->vmin.dppclk_mhz > 0) { + v->MaxDppclk[5] = soc->vmin.dppclk_mhz; + v->MaxDppclk[4] = soc->vmin.dppclk_mhz; + v->MaxDppclk[3] = soc->vmin.dppclk_mhz; + v->MaxDppclk[2] = soc->vmin.dppclk_mhz; + v->MaxDppclk[1] = soc->vmin.dppclk_mhz; + v->MaxDppclk[0] = soc->vmin.dppclk_mhz; + } + + if (soc->vmid.dppclk_mhz > 0) { + v->MaxDppclk[5] = soc->vmid.dppclk_mhz; + v->MaxDppclk[4] = soc->vmid.dppclk_mhz; + v->MaxDppclk[3] = soc->vmid.dppclk_mhz; + v->MaxDppclk[2] = soc->vmid.dppclk_mhz; + v->MaxDppclk[1] = soc->vmid.dppclk_mhz; + } + + if (soc->vnom.dppclk_mhz > 0) { + v->MaxDppclk[5] = soc->vnom.dppclk_mhz; + v->MaxDppclk[4] = soc->vnom.dppclk_mhz; + v->MaxDppclk[3] = soc->vnom.dppclk_mhz; + v->MaxDppclk[2] = soc->vnom.dppclk_mhz; + } + + if (soc->vmax.dppclk_mhz > 0) { + v->MaxDppclk[5] = soc->vmax.dppclk_mhz; + v->MaxDppclk[4] = soc->vmax.dppclk_mhz; + v->MaxDppclk[3] = soc->vmax.dppclk_mhz; + } + + if (me->voltage_override == dm_vmax) { + v->VoltageOverrideLevel = NumberOfStates - 1; + } else if (me->voltage_override == dm_vnom) { + v->VoltageOverrideLevel = NumberOfStates - 2; + } else if (me->voltage_override == dm_vmid) { + v->VoltageOverrideLevel = NumberOfStates - 3; + } else { + v->VoltageOverrideLevel = 0; + } + + // Scale Ratio Support Check + + v->ScaleRatioSupport = 1; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = + e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; + struct _vcs_dpi_scaler_taps_st scale_taps = + e2e[v->planes[k].e2e_index].pipe.scale_taps; + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + + if (scale_ratio_depth.hscl_ratio > ip->max_hscl_ratio + || scale_ratio_depth.vscl_ratio > ip->max_vscl_ratio + || scale_ratio_depth.hscl_ratio > scale_taps.htaps + || scale_ratio_depth.vscl_ratio > scale_taps.vtaps + || (src.source_format != dm_444_64 && src.source_format != dm_444_32 + && src.source_format != dm_444_16 + && ((scale_ratio_depth.hscl_ratio / 2 + > scale_taps.htaps_c) + || (scale_ratio_depth.vscl_ratio / 2 + > scale_taps.vtaps_c)))) + + { + v->ScaleRatioSupport = 0; + } + } + + // Source Format, Pixel Format and Scan Support Check + + v->SourceFormatPixelAndScanSupport = 1; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + + if ((src.sw_mode == dm_sw_linear && src.source_scan != dm_horz) + || ((src.sw_mode == dm_sw_4kb_d || src.sw_mode == dm_sw_4kb_d_x + || src.sw_mode == dm_sw_64kb_d + || src.sw_mode == dm_sw_64kb_d_t + || src.sw_mode == dm_sw_64kb_d_x + || src.sw_mode == dm_sw_var_d + || src.sw_mode == dm_sw_var_d_x) + && (src.source_format != dm_444_64))) { + v->SourceFormatPixelAndScanSupport = 0; + } + } + + // Bandwidth Support Check + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + + if (src.source_scan == dm_horz) { + v->SwathWidthYSingleDPP[k] = src.viewport_width; + } else { + v->SwathWidthYSingleDPP[k] = src.viewport_height; + } + + if (src.source_format == dm_444_64) { + v->BytePerPixelInDETY[k] = 8; + v->BytePerPixelInDETC[k] = 0; + } else if (src.source_format == dm_444_32) { + v->BytePerPixelInDETY[k] = 4; + v->BytePerPixelInDETC[k] = 0; + } else if (src.source_format == dm_444_16) { + v->BytePerPixelInDETY[k] = 2; + v->BytePerPixelInDETC[k] = 0; + } else if (src.source_format == dm_420_8) { + v->BytePerPixelInDETY[k] = 1; + v->BytePerPixelInDETC[k] = 2; + } else { + v->BytePerPixelInDETY[k] = 4.00 / 3.00; + v->BytePerPixelInDETC[k] = 8.00 / 3.00; + } + } + + v->TotalReadBandwidthConsumedGBytePerSecond = 0; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = + e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; + + v->ReadBandwidth[k] = + v->SwathWidthYSingleDPP[k] + * (dml_ceil_ex(v->BytePerPixelInDETY[k], 1) + * scale_ratio_depth.vscl_ratio + + (dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) / 2) + * (scale_ratio_depth.vscl_ratio + / 2)) + / (dest.htotal / dest.pixel_rate_mhz); + + if (src.dcc == 1) { + v->ReadBandwidth[k] = v->ReadBandwidth[k] * (1 + 1 / 256); + } + + if (ip->pte_enable == 1 && src.source_scan != dm_horz + && (src.sw_mode == dm_sw_4kb_s || src.sw_mode == dm_sw_4kb_s_x + || src.sw_mode == dm_sw_4kb_d + || src.sw_mode == dm_sw_4kb_d_x)) { + v->ReadBandwidth[k] = v->ReadBandwidth[k] * (1 + 1 / 64); + } else if (ip->pte_enable == 1 && src.source_scan == dm_horz + && (src.source_format == dm_444_64 || src.source_format == dm_444_32) + && (src.sw_mode == dm_sw_64kb_s || src.sw_mode == dm_sw_64kb_s_t + || src.sw_mode == dm_sw_64kb_s_x + || src.sw_mode == dm_sw_64kb_d + || src.sw_mode == dm_sw_64kb_d_t + || src.sw_mode == dm_sw_64kb_d_x)) { + v->ReadBandwidth[k] = v->ReadBandwidth[k] * (1 + 1 / 256); + } else if (ip->pte_enable == 1) { + v->ReadBandwidth[k] = v->ReadBandwidth[k] * (1 + 1 / 512); + } + + v->TotalReadBandwidthConsumedGBytePerSecond = + v->TotalReadBandwidthConsumedGBytePerSecond + + v->ReadBandwidth[k] / 1000; + } + + v->TotalWriteBandwidthConsumedGBytePerSecond = 0; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + struct _vcs_dpi_display_output_params_st dout = e2e[v->planes[k].e2e_index].dout; + + if (dout.output_type == dm_wb && dout.output_format == dm_444) { + v->WriteBandwidth[k] = dest.recout_width + / (dest.htotal / dest.pixel_rate_mhz) * 4; + } else if (dout.output_type == dm_wb) { + v->WriteBandwidth[k] = dest.recout_width + / (dest.htotal / dest.pixel_rate_mhz) * 1.5; + } else { + v->WriteBandwidth[k] = 0; + } + + v->TotalWriteBandwidthConsumedGBytePerSecond = + v->TotalWriteBandwidthConsumedGBytePerSecond + + v->WriteBandwidth[k] / 1000; + } + + v->TotalBandwidthConsumedGBytePerSecond = v->TotalReadBandwidthConsumedGBytePerSecond + + v->TotalWriteBandwidthConsumedGBytePerSecond; + + v->DCCEnabledInAnyPlane = 0; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + + if (src.dcc == 1) { + v->DCCEnabledInAnyPlane = 1; + } + } + + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + v->ReturnBWToDCNPerState = dml_min( + soc->return_bus_width_bytes * v->DCFCLKPerState[i], + v->FabricAndDRAMBandwidthPerState[i] * 1000 + * soc->ideal_dram_bw_after_urgent_percent / 100); + + v->ReturnBWPerState[i] = v->ReturnBWToDCNPerState; + + if (v->DCCEnabledInAnyPlane == 1 + && v->ReturnBWToDCNPerState + > (v->DCFCLKPerState[i] + * soc->return_bus_width_bytes / 4)) { + v->ReturnBWPerState[i] = + dml_min( + v->ReturnBWPerState[i], + v->ReturnBWToDCNPerState * 4 + * (1 + - soc->urgent_latency_us + / ((ip->rob_buffer_size_kbytes + - ip->pixel_chunk_size_kbytes) + * 1024 + / (v->ReturnBWToDCNPerState + - v->DCFCLKPerState[i] + * soc->return_bus_width_bytes + / 4) + + soc->urgent_latency_us))); + } + + v->CriticalPoint = 2 * soc->return_bus_width_bytes * v->DCFCLKPerState[i] + * soc->urgent_latency_us + / (v->ReturnBWToDCNPerState * soc->urgent_latency_us + + (ip->rob_buffer_size_kbytes + - ip->pixel_chunk_size_kbytes) + * 1024); + + if (v->DCCEnabledInAnyPlane == 1 && v->CriticalPoint > 1 && v->CriticalPoint < 4) { + v->ReturnBWPerState[i] = + dml_min( + v->ReturnBWPerState[i], + 4 * v->ReturnBWToDCNPerState + * (ip->rob_buffer_size_kbytes + - ip->pixel_chunk_size_kbytes) + * 1024 + * soc->return_bus_width_bytes + * v->DCFCLKPerState[i] + * soc->urgent_latency_us + / dml_pow( + (v->ReturnBWToDCNPerState + * soc->urgent_latency_us + + (ip->rob_buffer_size_kbytes + - ip->pixel_chunk_size_kbytes) + * 1024), + 2)); + } + + v->ReturnBWToDCNPerState = dml_min( + soc->return_bus_width_bytes * v->DCFCLKPerState[i], + v->FabricAndDRAMBandwidthPerState[i] * 1000); + + if (v->DCCEnabledInAnyPlane == 1 + && v->ReturnBWToDCNPerState + > (v->DCFCLKPerState[i] + * soc->return_bus_width_bytes / 4)) { + v->ReturnBWPerState[i] = + dml_min( + v->ReturnBWPerState[i], + v->ReturnBWToDCNPerState * 4 + * (1 + - soc->urgent_latency_us + / ((ip->rob_buffer_size_kbytes + - ip->pixel_chunk_size_kbytes) + * 1024 + / (v->ReturnBWToDCNPerState + - v->DCFCLKPerState[i] + * soc->return_bus_width_bytes + / 4) + + soc->urgent_latency_us))); + } + + v->CriticalPoint = 2 * soc->return_bus_width_bytes * v->DCFCLKPerState[i] + * soc->urgent_latency_us + / (v->ReturnBWToDCNPerState * soc->urgent_latency_us + + (ip->rob_buffer_size_kbytes + - ip->pixel_chunk_size_kbytes) + * 1024); + + if (v->DCCEnabledInAnyPlane == 1 && v->CriticalPoint > 1 && v->CriticalPoint < 4) { + v->ReturnBWPerState[i] = + dml_min( + v->ReturnBWPerState[i], + 4 * v->ReturnBWToDCNPerState + * (ip->rob_buffer_size_kbytes + - ip->pixel_chunk_size_kbytes) + * 1024 + * soc->return_bus_width_bytes + * v->DCFCLKPerState[i] + * soc->urgent_latency_us + / dml_pow( + (v->ReturnBWToDCNPerState + * soc->urgent_latency_us + + (ip->rob_buffer_size_kbytes + - ip->pixel_chunk_size_kbytes) + * 1024), + 2)); + } + } + + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + if ((v->TotalReadBandwidthConsumedGBytePerSecond * 1000 <= v->ReturnBWPerState[i]) + && (v->TotalBandwidthConsumedGBytePerSecond * 1000 + <= v->FabricAndDRAMBandwidthPerState[i] * 1000 + * soc->ideal_dram_bw_after_urgent_percent + / 100)) { + v->BandwidthSupport[i] = 1; + } else { + v->BandwidthSupport[i] = 0; + } + } + + // Writeback Latency support check + + v->WritebackLatencySupport = 1; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + struct _vcs_dpi_display_output_params_st dout = e2e[v->planes[k].e2e_index].dout; + + if (dout.output_type == dm_wb && dout.output_format == dm_444 + && (dest.recout_width / (dest.htotal / dest.pixel_rate_mhz) * 4) + > ((ip->writeback_luma_buffer_size_kbytes + + ip->writeback_chroma_buffer_size_kbytes) + * 1024 / soc->writeback_latency_us)) { + v->WritebackLatencySupport = 0; + } else if (dout.output_type == dm_wb + && (dest.recout_width / (dest.htotal / dest.pixel_rate_mhz)) + > (dml_min( + ip->writeback_luma_buffer_size_kbytes, + 2 + * ip->writeback_chroma_buffer_size_kbytes) + * 1024 / soc->writeback_latency_us)) { + v->WritebackLatencySupport = 0; + } + } + + // Re-ordering Buffer Support Check + + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + v->UrgentRoundTripAndOutOfOrderLatencyPerState[i] = + (soc->round_trip_ping_latency_dcfclk_cycles + 32) + / v->DCFCLKPerState[i] + + soc->urgent_out_of_order_return_per_channel_bytes + * soc->num_chans + / v->ReturnBWPerState[i]; + + if ((ip->rob_buffer_size_kbytes - ip->pixel_chunk_size_kbytes) * 1024 + / v->ReturnBWPerState[i] + > v->UrgentRoundTripAndOutOfOrderLatencyPerState[i]) { + v->ROBSupport[i] = 1; + } else { + v->ROBSupport[i] = 0; + } + } + + // Display IO Support Check + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + struct _vcs_dpi_display_output_params_st dout = e2e[v->planes[k].e2e_index].dout; + + if (dout.output_format == dm_420) { + v->RequiredOutputBW = dest.pixel_rate_mhz * 3 / 2; + } else { + v->RequiredOutputBW = dest.pixel_rate_mhz * 3; + } + + if (dout.output_type == dm_hdmi) { + v->RequiredPHYCLK[k] = v->RequiredOutputBW / 3; + } else if (dout.output_type == dm_dp) { + v->RequiredPHYCLK[k] = v->RequiredOutputBW / 4; + } else { + v->RequiredPHYCLK[k] = 0; + } + } + + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + v->DIOSupport[i] = 1; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_output_params_st dout = + e2e[v->planes[k].e2e_index].dout; + + if ((v->RequiredPHYCLK[k] > v->PHYCLKPerState[i]) + || (dout.output_type == dm_hdmi + && v->RequiredPHYCLK[k] > 600)) { + v->DIOSupport[i] = 0; + } + } + } + + // Total Available Writeback Support Check + + v->TotalNumberOfActiveWriteback = 0; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_output_params_st dout = e2e[v->planes[k].e2e_index].dout; + + if (dout.output_type == dm_wb) { + v->TotalNumberOfActiveWriteback = v->TotalNumberOfActiveWriteback + 1; + } + } + + if (v->TotalNumberOfActiveWriteback <= ip->max_num_wb) { + v->TotalAvailableWritebackSupport = 1; + } else { + v->TotalAvailableWritebackSupport = 0; + } + + // Maximum DISPCLK/DPPCLK Support check + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = + e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; + struct _vcs_dpi_scaler_taps_st scale_taps = + e2e[v->planes[k].e2e_index].pipe.scale_taps; + + if (scale_ratio_depth.hscl_ratio > 1) { + v->PSCL_FACTOR[k] = dml_min( + ip->max_dchub_pscl_bw_pix_per_clk, + ip->max_pscl_lb_bw_pix_per_clk + * scale_ratio_depth.hscl_ratio + / dml_ceil_ex(scale_taps.htaps / 6, 1)); + } else { + v->PSCL_FACTOR[k] = dml_min( + ip->max_dchub_pscl_bw_pix_per_clk, + ip->max_pscl_lb_bw_pix_per_clk); + } + + if (v->BytePerPixelInDETC[k] == 0) { + v->PSCL_FACTOR_CHROMA[k] = 0; + v->MinDPPCLKUsingSingleDPP[k] = + dest.pixel_rate_mhz + * dml_max( + scale_taps.vtaps / 6 + * dml_min( + 1, + scale_ratio_depth.hscl_ratio), + dml_max( + scale_ratio_depth.hscl_ratio + * scale_ratio_depth.vscl_ratio + / v->PSCL_FACTOR[k], + 1)); + + } else { + if (scale_ratio_depth.hscl_ratio / 2 > 1) { + v->PSCL_FACTOR_CHROMA[k] = dml_min( + ip->max_dchub_pscl_bw_pix_per_clk, + ip->max_pscl_lb_bw_pix_per_clk + * scale_ratio_depth.hscl_ratio / 2 + / dml_ceil_ex( + scale_taps.htaps_c + / 6, + 1)); + } else { + v->PSCL_FACTOR_CHROMA[k] = dml_min( + ip->max_dchub_pscl_bw_pix_per_clk, + ip->max_pscl_lb_bw_pix_per_clk); + } + v->MinDPPCLKUsingSingleDPP[k] = + dest.pixel_rate_mhz + * dml_max( + dml_max( + scale_taps.vtaps + / 6 + * dml_min( + 1, + scale_ratio_depth.hscl_ratio), + scale_ratio_depth.hscl_ratio + * scale_ratio_depth.vscl_ratio + / v->PSCL_FACTOR[k]), + dml_max( + dml_max( + scale_taps.vtaps_c + / 6 + * dml_min( + 1, + scale_ratio_depth.hscl_ratio + / 2), + scale_ratio_depth.hscl_ratio + * scale_ratio_depth.vscl_ratio + / 4 + / v->PSCL_FACTOR_CHROMA[k]), + 1)); + + } + } + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = + e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; + struct _vcs_dpi_scaler_taps_st scale_taps = + e2e[v->planes[k].e2e_index].pipe.scale_taps; + + if (src.source_format == dm_444_64 || src.source_format == dm_444_32 + || src.source_format == dm_444_16) { + if (src.sw_mode == dm_sw_linear) { + v->Read256BlockHeightY[k] = 1; + } else if (src.source_format == dm_444_64) { + v->Read256BlockHeightY[k] = 4; + } else { + v->Read256BlockHeightY[k] = 8; + } + + v->Read256BlockWidthY[k] = 256 / dml_ceil_ex(v->BytePerPixelInDETY[k], 1) + / v->Read256BlockHeightY[k]; + v->Read256BlockHeightC[k] = 0; + v->Read256BlockWidthC[k] = 0; + } else { + if (src.sw_mode == dm_sw_linear) { + v->Read256BlockHeightY[k] = 1; + v->Read256BlockHeightC[k] = 1; + } else if (src.source_format == dm_420_8) { + v->Read256BlockHeightY[k] = 16; + v->Read256BlockHeightC[k] = 8; + } else { + v->Read256BlockHeightY[k] = 8; + v->Read256BlockHeightC[k] = 8; + } + + v->Read256BlockWidthY[k] = 256 / dml_ceil_ex(v->BytePerPixelInDETY[k], 1) + / v->Read256BlockHeightY[k]; + v->Read256BlockWidthC[k] = 256 / dml_ceil_ex(v->BytePerPixelInDETC[k], 2) + / v->Read256BlockHeightC[k]; + } + + if (src.source_scan == dm_horz) { + v->MaxSwathHeightY[k] = v->Read256BlockHeightY[k]; + v->MaxSwathHeightC[k] = v->Read256BlockHeightC[k]; + } else { + v->MaxSwathHeightY[k] = v->Read256BlockWidthY[k]; + v->MaxSwathHeightC[k] = v->Read256BlockWidthC[k]; + } + + if (src.source_format == dm_444_64 || src.source_format == dm_444_32 + || src.source_format == dm_444_16) { + if (src.sw_mode == dm_sw_linear + || (src.source_format == dm_444_64 + && (src.sw_mode == dm_sw_4kb_s + || src.sw_mode + == dm_sw_4kb_s_x + || src.sw_mode + == dm_sw_64kb_s + || src.sw_mode + == dm_sw_64kb_s_t + || src.sw_mode + == dm_sw_64kb_s_x + || src.sw_mode + == dm_sw_var_s + || src.sw_mode + == dm_sw_var_s_x) + && src.source_scan == dm_horz)) { + v->MinSwathHeightY[k] = v->MaxSwathHeightY[k]; + } else { + v->MinSwathHeightY[k] = v->MaxSwathHeightY[k] / 2; + } + v->MinSwathHeightC[k] = v->MaxSwathHeightC[k]; + } else { + if (src.sw_mode == dm_sw_linear) { + v->MinSwathHeightY[k] = v->MaxSwathHeightY[k]; + v->MinSwathHeightC[k] = v->MaxSwathHeightC[k]; + } else if (src.source_format == dm_420_8 && src.source_scan == dm_horz) { + v->MinSwathHeightY[k] = v->MaxSwathHeightY[k] / 2; + if (ip->bug_forcing_LC_req_same_size_fixed == 1) { + v->MinSwathHeightC[k] = v->MaxSwathHeightC[k]; + } else { + v->MinSwathHeightC[k] = v->MaxSwathHeightC[k] / 2; + } + } else if (src.source_format == dm_420_10 && src.source_scan == dm_horz) { + v->MinSwathHeightC[k] = v->MaxSwathHeightC[k] / 2; + if (ip->bug_forcing_LC_req_same_size_fixed == 1) { + v->MinSwathHeightY[k] = v->MaxSwathHeightY[k]; + } else { + v->MinSwathHeightY[k] = v->MaxSwathHeightY[k] / 2; + } + } else { + v->MinSwathHeightY[k] = v->MaxSwathHeightY[k]; + v->MinSwathHeightC[k] = v->MaxSwathHeightC[k]; + } + } + + if (src.sw_mode == dm_sw_linear) { + v->MaximumSwathWidth = 8192; + } else { + v->MaximumSwathWidth = 5120; + } + + v->NumberOfDPPRequiredForDETSize = + dml_ceil_ex( + v->SwathWidthYSingleDPP[k] + / dml_min( + v->MaximumSwathWidth, + ip->det_buffer_size_kbytes + * 1024 + / 2 + / (v->BytePerPixelInDETY[k] + * v->MinSwathHeightY[k] + + v->BytePerPixelInDETC[k] + / 2 + * v->MinSwathHeightC[k])), + 1); + + if (v->BytePerPixelInDETC[k] == 0) { + v->NumberOfDPPRequiredForLBSize = + dml_ceil_ex( + (scale_taps.vtaps + + dml_max( + dml_ceil_ex( + scale_ratio_depth.vscl_ratio, + 1) + - 2, + 0)) + * v->SwathWidthYSingleDPP[k] + / dml_max( + scale_ratio_depth.hscl_ratio, + 1) + * scale_ratio_depth.lb_depth + / ip->line_buffer_size_bits, + 1); + } else { + v->NumberOfDPPRequiredForLBSize = + dml_max( + dml_ceil_ex( + (scale_taps.vtaps + + dml_max( + dml_ceil_ex( + scale_ratio_depth.vscl_ratio, + 1) + - 2, + 0)) + * v->SwathWidthYSingleDPP[k] + / dml_max( + scale_ratio_depth.hscl_ratio, + 1) + * scale_ratio_depth.lb_depth + / ip->line_buffer_size_bits, + 1), + dml_ceil_ex( + (scale_taps.vtaps_c + + dml_max( + dml_ceil_ex( + scale_ratio_depth.vscl_ratio + / 2, + 1) + - 2, + 0)) + * v->SwathWidthYSingleDPP[k] + / 2 + / dml_max( + scale_ratio_depth.hscl_ratio + / 2, + 1) + * scale_ratio_depth.lb_depth + / ip->line_buffer_size_bits, + 1)); + } + + v->NumberOfDPPRequiredForDETAndLBSize[k] = dml_max( + v->NumberOfDPPRequiredForDETSize, + v->NumberOfDPPRequiredForLBSize); + + } + + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + for (j = 0; j < 2; j++) { + v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] = 0; + v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = 0; + v->DISPCLK_DPPCLK_Support[j * NumberOfStatesPlusTwo + i] = 1; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + v->MinDispclkUsingSingleDPP = dml_max( + dest.pixel_rate_mhz, + v->MinDPPCLKUsingSingleDPP[k] * (j + 1)) + * (1 + soc->downspread_percent / 100); + v->MinDispclkUsingDualDPP = dml_max( + dest.pixel_rate_mhz, + v->MinDPPCLKUsingSingleDPP[k] / 2 * (j + 1)) + * (1 + soc->downspread_percent / 100); + + if (i < NumberOfStates) { + v->MinDispclkUsingSingleDPP = + v->MinDispclkUsingSingleDPP + * (1 + + ip->dispclk_ramp_margin_percent + / 100); + v->MinDispclkUsingDualDPP = + v->MinDispclkUsingDualDPP + * (1 + + ip->dispclk_ramp_margin_percent + / 100); + } + + if (v->MinDispclkUsingSingleDPP + <= dml_min( + v->MaxDispclk[i], + (j + 1) * v->MaxDppclk[i]) + && v->NumberOfDPPRequiredForDETAndLBSize[k] <= 1) { + v->NoOfDPP[ijk] = 1; + v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = dml_max( + v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + + i], + v->MinDispclkUsingSingleDPP); + } else if (v->MinDispclkUsingDualDPP + <= dml_min( + v->MaxDispclk[i], + (j + 1) * v->MaxDppclk[i])) { + v->NoOfDPP[ijk] = 2; + v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = dml_max( + v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + + i], + v->MinDispclkUsingDualDPP); + } else { + v->NoOfDPP[ijk] = 2; + v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = dml_max( + v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + + i], + v->MinDispclkUsingDualDPP); + v->DISPCLK_DPPCLK_Support[j * NumberOfStatesPlusTwo + i] = + 0; + } + + v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] = + v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + + i] + v->NoOfDPP[ijk]; + } + + if (v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] + > ip->max_num_dpp) { + v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] = 0; + v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = 0; + v->DISPCLK_DPPCLK_Support[j * NumberOfStatesPlusTwo + i] = 1; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + ijk = k * 2 * NumberOfStatesPlusTwo + + j * NumberOfStatesPlusTwo + i; + + v->MinDispclkUsingSingleDPP = dml_max( + dest.pixel_rate_mhz, + v->MinDPPCLKUsingSingleDPP[k] * (j + 1)) + * (1 + soc->downspread_percent / 100); + v->MinDispclkUsingDualDPP = dml_max( + dest.pixel_rate_mhz, + v->MinDPPCLKUsingSingleDPP[k] / 2 * (j + 1)) + * (1 + soc->downspread_percent / 100); + + if (i < NumberOfStates) { + v->MinDispclkUsingSingleDPP = + v->MinDispclkUsingSingleDPP + * (1 + + ip->dispclk_ramp_margin_percent + / 100); + v->MinDispclkUsingDualDPP = + v->MinDispclkUsingDualDPP + * (1 + + ip->dispclk_ramp_margin_percent + / 100); + } + + if (v->NumberOfDPPRequiredForDETAndLBSize[k] <= 1) { + v->NoOfDPP[ijk] = 1; + v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = + dml_max( + v->RequiredDISPCLK[j + * NumberOfStatesPlusTwo + + i], + v->MinDispclkUsingSingleDPP); + if (v->MinDispclkUsingSingleDPP + > dml_min( + v->MaxDispclk[i], + (j + 1) + * v->MaxDppclk[i])) { + v->DISPCLK_DPPCLK_Support[j + * NumberOfStatesPlusTwo + i] = + 0; + } + } else { + v->NoOfDPP[ijk] = 2; + v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = + dml_max( + v->RequiredDISPCLK[j + * NumberOfStatesPlusTwo + + i], + v->MinDispclkUsingDualDPP); + if (v->MinDispclkUsingDualDPP + > dml_min( + v->MaxDispclk[i], + (j + 1) + * v->MaxDppclk[i])) { + v->DISPCLK_DPPCLK_Support[j + * NumberOfStatesPlusTwo + i] = + 0; + } + } + v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] = + v->TotalNumberOfActiveDPP[j + * NumberOfStatesPlusTwo + i] + + v->NoOfDPP[ijk]; + } + } + } + } + + // Viewport Size Check + + v->ViewportSizeSupport = 1; + + for (k = 0; k < num_planes; k++) { + if (v->NumberOfDPPRequiredForDETAndLBSize[k] > 2) { + v->ViewportSizeSupport = 0; + } + } + + // Total Available Pipes Support Check + + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + for (j = 0; j < 2; j++) { + if (v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] + <= ip->max_num_dpp) { + v->TotalAvailablePipesSupport[j * NumberOfStatesPlusTwo + i] = 1; + } else { + v->TotalAvailablePipesSupport[j * NumberOfStatesPlusTwo + i] = 0; + } + } + } + + // Urgent Latency Support Check + + for (j = 0; j < 2; j++) { + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + ij = j * NumberOfStatesPlusTwo + i; + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = + e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; + struct _vcs_dpi_scaler_taps_st scale_taps = + e2e[v->planes[k].e2e_index].pipe.scale_taps; + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + v->SwathWidthYPerState[ijk] = v->SwathWidthYSingleDPP[k] + / v->NoOfDPP[ijk]; + + v->SwathWidthGranularityY = 256 + / dml_ceil_ex(v->BytePerPixelInDETY[k], 1) + / v->MaxSwathHeightY[k]; + v->RoundedUpMaxSwathSizeBytesY = (dml_ceil_ex( + v->SwathWidthYPerState[ijk] - 1, + v->SwathWidthGranularityY) + + v->SwathWidthGranularityY) + * v->BytePerPixelInDETY[k] * v->MaxSwathHeightY[k]; + if (src.source_format == dm_420_10) { + v->RoundedUpMaxSwathSizeBytesY = dml_ceil_ex( + v->RoundedUpMaxSwathSizeBytesY, + 256) + 256; + } + if (v->MaxSwathHeightC[k] > 0) { + v->SwathWidthGranularityC = 256 + / dml_ceil_ex(v->BytePerPixelInDETC[k], 2) + / v->MaxSwathHeightC[k]; + } + v->RoundedUpMaxSwathSizeBytesC = (dml_ceil_ex( + v->SwathWidthYPerState[ijk] / 2 - 1, + v->SwathWidthGranularityC) + + v->SwathWidthGranularityC) + * v->BytePerPixelInDETC[k] * v->MaxSwathHeightC[k]; + if (src.source_format == dm_420_10) { + v->RoundedUpMaxSwathSizeBytesC = dml_ceil_ex( + v->RoundedUpMaxSwathSizeBytesC, + 256) + 256; + } + + if (v->RoundedUpMaxSwathSizeBytesY + v->RoundedUpMaxSwathSizeBytesC + <= ip->det_buffer_size_kbytes * 1024 / 2) { + v->SwathHeightYPerState[ijk] = v->MaxSwathHeightY[k]; + v->SwathHeightCPerState[ijk] = v->MaxSwathHeightC[k]; + } else { + v->SwathHeightYPerState[ijk] = v->MinSwathHeightY[k]; + v->SwathHeightCPerState[ijk] = v->MinSwathHeightC[k]; + } + + if (v->BytePerPixelInDETC[k] == 0) { + v->LinesInDETLuma = ip->det_buffer_size_kbytes * 1024 + / v->BytePerPixelInDETY[k] + / v->SwathWidthYPerState[ijk]; + + v->LinesInDETChroma = 0; + } else if (v->SwathHeightYPerState[ijk] + <= v->SwathHeightCPerState[ijk]) { + v->LinesInDETLuma = ip->det_buffer_size_kbytes * 1024 / 2 + / v->BytePerPixelInDETY[k] + / v->SwathWidthYPerState[ijk]; + v->LinesInDETChroma = ip->det_buffer_size_kbytes * 1024 / 2 + / v->BytePerPixelInDETC[k] + / (v->SwathWidthYPerState[ijk] / 2); + } else { + v->LinesInDETLuma = ip->det_buffer_size_kbytes * 1024 * 2 + / 3 / v->BytePerPixelInDETY[k] + / v->SwathWidthYPerState[ijk]; + v->LinesInDETChroma = ip->det_buffer_size_kbytes * 1024 / 3 + / v->BytePerPixelInDETY[k] + / (v->SwathWidthYPerState[ijk] / 2); + } + + v->EffectiveLBLatencyHidingSourceLinesLuma = + dml_min( + ip->max_line_buffer_lines, + dml_floor_ex( + ip->line_buffer_size_bits + / scale_ratio_depth.lb_depth + / (v->SwathWidthYPerState[ijk] + / dml_max( + scale_ratio_depth.hscl_ratio, + 1)), + 1)) + - (scale_taps.vtaps - 1); + + v->EffectiveLBLatencyHidingSourceLinesChroma = + dml_min( + ip->max_line_buffer_lines, + dml_floor_ex( + ip->line_buffer_size_bits + / scale_ratio_depth.lb_depth + / (v->SwathWidthYPerState[ijk] + / 2 + / dml_max( + scale_ratio_depth.hscl_ratio + / 2, + 1)), + 1)) + - (scale_taps.vtaps_c - 1); + + v->EffectiveDETLBLinesLuma = + dml_floor_ex( + v->LinesInDETLuma + + dml_min( + v->LinesInDETLuma + * v->RequiredDISPCLK[ij] + * v->BytePerPixelInDETY[k] + * v->PSCL_FACTOR[k] + / v->ReturnBWPerState[i], + v->EffectiveLBLatencyHidingSourceLinesLuma), + v->SwathHeightYPerState[ijk]); + + v->EffectiveDETLBLinesChroma = + dml_floor_ex( + v->LinesInDETChroma + + dml_min( + v->LinesInDETChroma + * v->RequiredDISPCLK[ij] + * v->BytePerPixelInDETC[k] + * v->PSCL_FACTOR_CHROMA[k] + / v->ReturnBWPerState[i], + v->EffectiveLBLatencyHidingSourceLinesChroma), + v->SwathHeightCPerState[ijk]); + + if (v->BytePerPixelInDETC[k] == 0) { + v->UrgentLatencySupportUsPerState[ijk] = + v->EffectiveDETLBLinesLuma + * (dest.htotal + / dest.pixel_rate_mhz) + / scale_ratio_depth.vscl_ratio + - v->EffectiveDETLBLinesLuma + * v->SwathWidthYPerState[ijk] + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + / (v->ReturnBWPerState[i] + / v->NoOfDPP[ijk]); + } else { + v->UrgentLatencySupportUsPerState[ijk] = + dml_min( + v->EffectiveDETLBLinesLuma + * (dest.htotal + / dest.pixel_rate_mhz) + / scale_ratio_depth.vscl_ratio + - v->EffectiveDETLBLinesLuma + * v->SwathWidthYPerState[ijk] + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + / (v->ReturnBWPerState[i] + / v->NoOfDPP[ijk]), + v->EffectiveDETLBLinesChroma + * (dest.htotal + / dest.pixel_rate_mhz) + / (scale_ratio_depth.vscl_ratio + / 2) + - v->EffectiveDETLBLinesChroma + * v->SwathWidthYPerState[ijk] + / 2 + * dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / (v->ReturnBWPerState[i] + / v->NoOfDPP[ijk])); + } + + } + } + } + + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + for (j = 0; j < 2; j++) { + ij = j * NumberOfStatesPlusTwo + i; + + v->UrgentLatencySupport[ij] = 1; + for (k = 0; k < num_planes; k++) { + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + if (v->UrgentLatencySupportUsPerState[ijk] + < soc->urgent_latency_us / 1) { + v->UrgentLatencySupport[ij] = 0; + } + } + } + } + + // Prefetch Check + + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + for (j = 0; j < 2; j++) { + ij = j * NumberOfStatesPlusTwo + i; + + v->TotalNumberOfDCCActiveDPP[ij] = 0; + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + if (src.dcc == 1) { + v->TotalNumberOfDCCActiveDPP[ij] = + v->TotalNumberOfDCCActiveDPP[ij] + + v->NoOfDPP[ijk]; + } + } + } + } + + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + for (j = 0; j < 2; j++) { + ij = j * NumberOfStatesPlusTwo + i; + + v->ProjectedDCFCLKDeepSleep = 8; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = + e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + v->ProjectedDCFCLKDeepSleep = dml_max( + v->ProjectedDCFCLKDeepSleep, + dest.pixel_rate_mhz / 16); + if (v->BytePerPixelInDETC[k] == 0) { + if (scale_ratio_depth.vscl_ratio <= 1) { + v->ProjectedDCFCLKDeepSleep = + dml_max( + v->ProjectedDCFCLKDeepSleep, + 1.1 + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + / 64 + * scale_ratio_depth.hscl_ratio + * dest.pixel_rate_mhz + / v->NoOfDPP[ijk]); + } else { + v->ProjectedDCFCLKDeepSleep = + dml_max( + v->ProjectedDCFCLKDeepSleep, + 1.1 + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + / 64 + * v->PSCL_FACTOR[k] + * v->RequiredDISPCLK[ij] + / (1 + + j)); + } + + } else { + if (scale_ratio_depth.vscl_ratio <= 1) { + v->ProjectedDCFCLKDeepSleep = + dml_max( + v->ProjectedDCFCLKDeepSleep, + 1.1 + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + / 32 + * scale_ratio_depth.hscl_ratio + * dest.pixel_rate_mhz + / v->NoOfDPP[ijk]); + } else { + v->ProjectedDCFCLKDeepSleep = + dml_max( + v->ProjectedDCFCLKDeepSleep, + 1.1 + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + / 32 + * v->PSCL_FACTOR[k] + * v->RequiredDISPCLK[ij] + / (1 + + j)); + } + if ((scale_ratio_depth.vscl_ratio / 2) <= 1) { + v->ProjectedDCFCLKDeepSleep = + dml_max( + v->ProjectedDCFCLKDeepSleep, + 1.1 + * dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / 32 + * scale_ratio_depth.hscl_ratio + / 2 + * dest.pixel_rate_mhz + / v->NoOfDPP[ijk]); + } else { + v->ProjectedDCFCLKDeepSleep = + dml_max( + v->ProjectedDCFCLKDeepSleep, + 1.1 + * dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / 32 + * v->PSCL_FACTOR_CHROMA[k] + * v->RequiredDISPCLK[ij] + / (1 + + j)); + } + + } + } + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = + e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; + struct _vcs_dpi_scaler_taps_st scale_taps = + e2e[v->planes[k].e2e_index].pipe.scale_taps; + struct _vcs_dpi_display_output_params_st dout = + e2e[v->planes[k].e2e_index].dout; + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + if (src.dcc == 1) { + v->MetaReqHeightY = 8 * v->Read256BlockHeightY[k]; + v->MetaReqWidthY = 64 * 256 + / dml_ceil_ex(v->BytePerPixelInDETY[k], 1) + / v->MetaReqHeightY; + v->MetaSurfaceWidthY = dml_ceil_ex( + src.viewport_width / v->NoOfDPP[ijk] - 1, + v->MetaReqWidthY) + v->MetaReqWidthY; + v->MetaSurfaceHeightY = dml_ceil_ex( + src.viewport_height - 1, + v->MetaReqHeightY) + v->MetaReqHeightY; + if (ip->pte_enable == 1) { + v->MetaPteBytesPerFrameY = + (dml_ceil_ex( + (v->MetaSurfaceWidthY + * v->MetaSurfaceHeightY + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + / 256.0 + - 4096) + / 8 + / 4096, + 1) + 1) * 64; + } else { + v->MetaPteBytesPerFrameY = 0; + } + if (src.source_scan == dm_horz) { + v->MetaRowBytesY = + v->MetaSurfaceWidthY + * v->MetaReqHeightY + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + / 256; + } else { + v->MetaRowBytesY = + v->MetaSurfaceHeightY + * v->MetaReqWidthY + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + / 256; + } + } else { + v->MetaPteBytesPerFrameY = 0; + v->MetaRowBytesY = 0; + } + + if (ip->pte_enable == 1) { + if (src.sw_mode == dm_sw_linear) { + v->MacroTileBlockSizeBytesY = 256; + v->MacroTileBlockHeightY = 1; + } else if (src.sw_mode == dm_sw_4kb_s + || src.sw_mode == dm_sw_4kb_s_x + || src.sw_mode == dm_sw_4kb_d + || src.sw_mode == dm_sw_4kb_d_x) { + v->MacroTileBlockSizeBytesY = 4096; + v->MacroTileBlockHeightY = 4 + * v->Read256BlockHeightY[k]; + } else if (src.sw_mode == dm_sw_64kb_s + || src.sw_mode == dm_sw_64kb_s_t + || src.sw_mode == dm_sw_64kb_s_x + || src.sw_mode == dm_sw_64kb_d + || src.sw_mode == dm_sw_64kb_d_t + || src.sw_mode == dm_sw_64kb_d_x) { + v->MacroTileBlockSizeBytesY = 64 * 1024; + v->MacroTileBlockHeightY = 16 + * v->Read256BlockHeightY[k]; + } else { + v->MacroTileBlockSizeBytesY = 256 * 1024; + v->MacroTileBlockHeightY = 32 + * v->Read256BlockHeightY[k]; + } + if (v->MacroTileBlockSizeBytesY <= 65536) { + v->DataPTEReqHeightY = v->MacroTileBlockHeightY; + } else { + v->DataPTEReqHeightY = 16 + * v->Read256BlockHeightY[k]; + } + v->DataPTEReqWidthY = 4096 + / dml_ceil_ex(v->BytePerPixelInDETY[k], 1) + / v->DataPTEReqHeightY * 8; + if (src.sw_mode == dm_sw_linear) { + v->DPTEBytesPerRowY = + 64 + * (dml_ceil_ex( + (src.viewport_width + / v->NoOfDPP[ijk] + * dml_min( + 128, + dml_pow( + 2, + dml_floor_ex( + dml_log( + ip->dpte_buffer_size_in_pte_reqs + * v->DataPTEReqWidthY + / (src.viewport_width + / v->NoOfDPP[ijk]), + 2), + 1))) + - 1) + / v->DataPTEReqWidthY, + 1) + + 1); + } else if (src.source_scan == dm_horz) { + v->DPTEBytesPerRowY = + 64 + * (dml_ceil_ex( + (src.viewport_width + / v->NoOfDPP[ijk] + - 1) + / v->DataPTEReqWidthY, + 1) + + 1); + } else { + v->DPTEBytesPerRowY = + 64 + * (dml_ceil_ex( + (src.viewport_height + - 1) + / v->DataPTEReqHeightY, + 1) + + 1); + } + } else { + v->DPTEBytesPerRowY = 0; + } + + if (src.source_format != dm_444_64 && src.source_format != dm_444_32 + && src.source_format != dm_444_16) { + if (src.dcc == 1) { + v->MetaReqHeightC = 8 * v->Read256BlockHeightC[k]; + v->MetaReqWidthC = + 64 * 256 + / dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / v->MetaReqHeightC; + v->MetaSurfaceWidthC = dml_ceil_ex( + src.viewport_width / v->NoOfDPP[ijk] + / 2 - 1, + v->MetaReqWidthC) + + v->MetaReqWidthC; + v->MetaSurfaceHeightC = dml_ceil_ex( + src.viewport_height / 2 - 1, + v->MetaReqHeightC) + + v->MetaReqHeightC; + if (ip->pte_enable == 1) { + v->MetaPteBytesPerFrameC = + (dml_ceil_ex( + (v->MetaSurfaceWidthC + * v->MetaSurfaceHeightC + * dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / 256.0 + - 4096) + / 8 + / 4096, + 1) + 1) + * 64; + } else { + v->MetaPteBytesPerFrameC = 0; + } + if (src.source_scan == dm_horz) { + v->MetaRowBytesC = + v->MetaSurfaceWidthC + * v->MetaReqHeightC + * dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / 256; + } else { + v->MetaRowBytesC = + v->MetaSurfaceHeightC + * v->MetaReqWidthC + * dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / 256; + } + } else { + v->MetaPteBytesPerFrameC = 0; + v->MetaRowBytesC = 0; + } + + if (ip->pte_enable == 1) { + if (src.sw_mode == dm_sw_linear) { + v->MacroTileBlockSizeBytesC = 256; + v->MacroTileBlockHeightC = 1; + } else if (src.sw_mode == dm_sw_4kb_s + || src.sw_mode == dm_sw_4kb_s_x + || src.sw_mode == dm_sw_4kb_d + || src.sw_mode == dm_sw_4kb_d_x) { + v->MacroTileBlockSizeBytesC = 4096; + v->MacroTileBlockHeightC = 4 + * v->Read256BlockHeightC[k]; + } else if (src.sw_mode == dm_sw_64kb_s + || src.sw_mode == dm_sw_64kb_s_t + || src.sw_mode == dm_sw_64kb_s_x + || src.sw_mode == dm_sw_64kb_d + || src.sw_mode == dm_sw_64kb_d_t + || src.sw_mode == dm_sw_64kb_d_x) { + v->MacroTileBlockSizeBytesC = 64 * 1024; + v->MacroTileBlockHeightC = 16 + * v->Read256BlockHeightC[k]; + } else { + v->MacroTileBlockSizeBytesC = 256 * 1024; + v->MacroTileBlockHeightC = 32 + * v->Read256BlockHeightC[k]; + } + v->MacroTileBlockWidthC = + v->MacroTileBlockSizeBytesC + / dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / v->MacroTileBlockHeightC; + if (v->MacroTileBlockSizeBytesC <= 65536) { + v->DataPTEReqHeightC = + v->MacroTileBlockHeightC; + } else { + v->DataPTEReqHeightC = 16 + * v->Read256BlockHeightC[k]; + } + v->DataPTEReqWidthC = + 4096 + / dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / v->DataPTEReqHeightC + * 8; + if (src.sw_mode == dm_sw_linear) { + v->DPTEBytesPerRowC = + 64 + * (dml_ceil_ex( + (src.viewport_width + / v->NoOfDPP[ijk] + / 2 + * dml_min( + 128, + dml_pow( + 2, + dml_floor_ex( + dml_log( + ip->dpte_buffer_size_in_pte_reqs + * v->DataPTEReqWidthC + / (src.viewport_width + / v->NoOfDPP[ijk] + / 2), + 2), + 1))) + - 1) + / v->DataPTEReqWidthC, + 1) + + 1); + } else if (src.source_scan == dm_horz) { + v->DPTEBytesPerRowC = + 64 + * (dml_ceil_ex( + (src.viewport_width + / v->NoOfDPP[ijk] + / 2 + - 1) + / v->DataPTEReqWidthC, + 1) + + 1); + } else { + v->DPTEBytesPerRowC = + 64 + * (dml_ceil_ex( + (src.viewport_height + / 2 + - 1) + / v->DataPTEReqHeightC, + 1) + + 1); + } + } else { + v->DPTEBytesPerRowC = 0; + } + } else { + v->DPTEBytesPerRowC = 0; + v->MetaPteBytesPerFrameC = 0; + v->MetaRowBytesC = 0; + } + + v->DPTEBytesPerRow[k] = v->DPTEBytesPerRowY + v->DPTEBytesPerRowC; + v->MetaPTEBytesPerFrame[k] = v->MetaPteBytesPerFrameY + + v->MetaPteBytesPerFrameC; + v->MetaRowBytes[k] = v->MetaRowBytesY + v->MetaRowBytesC; + + v->VInitY = (scale_ratio_depth.vscl_ratio + scale_taps.vtaps + 1 + + dest.interlaced * 0.5 + * scale_ratio_depth.vscl_ratio) + / 2.0; + v->PrefillY[k] = dml_floor_ex(v->VInitY, 1); + v->MaxNumSwY[k] = dml_ceil_ex( + (v->PrefillY[k] - 1.0) + / v->SwathHeightYPerState[ijk], + 1) + 1.0; + + if (v->PrefillY[k] > 1) { + v->MaxPartialSwY = ((int) (v->PrefillY[k] - 2)) + % ((int) v->SwathHeightYPerState[ijk]); + } else { + v->MaxPartialSwY = ((int) (v->PrefillY[k] + + v->SwathHeightYPerState[ijk] - 2)) + % ((int) v->SwathHeightYPerState[ijk]); + } + v->MaxPartialSwY = dml_max(1, v->MaxPartialSwY); + + v->PrefetchLinesY[k] = v->MaxNumSwY[k] + * v->SwathHeightYPerState[ijk] + v->MaxPartialSwY; + + if (src.source_format != dm_444_64 && src.source_format != dm_444_32 + && src.source_format != dm_444_16) { + v->VInitC = + (scale_ratio_depth.vscl_ratio / 2 + + scale_taps.vtaps + 1 + + dest.interlaced * 0.5 + * scale_ratio_depth.vscl_ratio + / 2) / 2.0; + v->PrefillC[k] = dml_floor_ex(v->VInitC, 1); + v->MaxNumSwC[k] = + dml_ceil_ex( + (v->PrefillC[k] - 1.0) + / v->SwathHeightCPerState[ijk], + 1) + 1.0; + if (v->PrefillC[k] > 1) { + v->MaxPartialSwC = + ((int) (v->PrefillC[k] - 2)) + % ((int) v->SwathHeightCPerState[ijk]); + } else { + v->MaxPartialSwC = + ((int) (v->PrefillC[k] + + v->SwathHeightCPerState[ijk] + - 2)) + % ((int) v->SwathHeightCPerState[ijk]); + } + v->MaxPartialSwC = dml_max(1, v->MaxPartialSwC); + + v->PrefetchLinesC[k] = v->MaxNumSwC[k] + * v->SwathHeightCPerState[ijk] + + v->MaxPartialSwC; + } else { + v->PrefetchLinesC[k] = 0; + } + + v->dst_x_after_scaler = 90 * dest.pixel_rate_mhz + / (v->RequiredDISPCLK[ij] / (j + 1)) + + 42 * dest.pixel_rate_mhz / v->RequiredDISPCLK[ij]; + if (v->NoOfDPP[ijk] > 1) { + v->dst_x_after_scaler = v->dst_x_after_scaler + + dest.recout_width / 2.0; + } + + if (dout.output_format == dm_420) { + v->dst_y_after_scaler = 1; + } else { + v->dst_y_after_scaler = 0; + } + + v->TimeCalc = 24 / v->ProjectedDCFCLKDeepSleep; + + v->VUpdateOffset = dml_ceil_ex(dest.htotal / 4, 1); + v->TotalRepeaterDelay = ip->max_inter_dcn_tile_repeaters + * (2 / (v->RequiredDISPCLK[ij] / (j + 1)) + + 3 / v->RequiredDISPCLK[ij]); + v->VUpdateWidth = (14 / v->ProjectedDCFCLKDeepSleep + + 12 / (v->RequiredDISPCLK[ij] / (j + 1)) + + v->TotalRepeaterDelay) * dest.pixel_rate_mhz; + v->VReadyOffset = + dml_max( + 150 + / (v->RequiredDISPCLK[ij] + / (j + + 1)), + v->TotalRepeaterDelay + + 20 + / v->ProjectedDCFCLKDeepSleep + + 10 + / (v->RequiredDISPCLK[ij] + / (j + + 1))) + * dest.pixel_rate_mhz; + + v->TimeSetup = + (v->VUpdateOffset + v->VUpdateWidth + + v->VReadyOffset) + / dest.pixel_rate_mhz; + + v->ExtraLatency = + v->UrgentRoundTripAndOutOfOrderLatencyPerState[i] + + (v->TotalNumberOfActiveDPP[ij] + * ip->pixel_chunk_size_kbytes + + v->TotalNumberOfDCCActiveDPP[ij] + * ip->meta_chunk_size_kbytes) + * 1024 + / v->ReturnBWPerState[i]; + + if (ip->pte_enable == 1) { + v->ExtraLatency = v->ExtraLatency + + v->TotalNumberOfActiveDPP[ij] + * ip->pte_chunk_size_kbytes + * 1024 + / v->ReturnBWPerState[i]; + } + + if (ip->can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one + == 1) { + v->MaximumVStartup = dest.vtotal - dest.vactive - 1; + } else { + v->MaximumVStartup = dest.vsync_plus_back_porch - 1; + } + + v->LineTimesForPrefetch[k] = + v->MaximumVStartup + - soc->urgent_latency_us + / (dest.htotal + / dest.pixel_rate_mhz) + - (v->TimeCalc + v->TimeSetup) + / (dest.htotal + / dest.pixel_rate_mhz) + - (v->dst_y_after_scaler + + v->dst_x_after_scaler + / dest.htotal); + + v->LineTimesForPrefetch[k] = dml_floor_ex( + 4.0 * (v->LineTimesForPrefetch[k] + 0.125), + 1) / 4; + + v->PrefetchBW[k] = + (v->MetaPTEBytesPerFrame[k] + 2 * v->MetaRowBytes[k] + + 2 * v->DPTEBytesPerRow[k] + + v->PrefetchLinesY[k] + * v->SwathWidthYPerState[ijk] + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + + v->PrefetchLinesC[k] + * v->SwathWidthYPerState[ijk] + / 2 + * dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2)) + / (v->LineTimesForPrefetch[k] + * dest.htotal + / dest.pixel_rate_mhz); + } + + v->BWAvailableForImmediateFlip = v->ReturnBWPerState[i]; + + for (k = 0; k < num_planes; k++) { + v->BWAvailableForImmediateFlip = v->BWAvailableForImmediateFlip + - dml_max(v->ReadBandwidth[k], v->PrefetchBW[k]); + } + + v->TotalImmediateFlipBytes = 0; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + + if (src.source_format != dm_420_8 + && src.source_format != dm_420_10) { + v->TotalImmediateFlipBytes = v->TotalImmediateFlipBytes + + v->MetaPTEBytesPerFrame[k] + + v->MetaRowBytes[k] + + v->DPTEBytesPerRow[k]; + } + } + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + if (ip->pte_enable == 1 && src.dcc == 1) { + v->TimeForMetaPTEWithImmediateFlip = + dml_max( + v->MetaPTEBytesPerFrame[k] + / v->PrefetchBW[k], + dml_max( + v->MetaPTEBytesPerFrame[k] + * v->TotalImmediateFlipBytes + / (v->BWAvailableForImmediateFlip + * (v->MetaPTEBytesPerFrame[k] + + v->MetaRowBytes[k] + + v->DPTEBytesPerRow[k])), + dml_max( + v->ExtraLatency, + dml_max( + soc->urgent_latency_us, + dest.htotal + / dest.pixel_rate_mhz + / 4)))); + + v->TimeForMetaPTEWithoutImmediateFlip = + dml_max( + v->MetaPTEBytesPerFrame[k] + / v->PrefetchBW[k], + dml_max( + v->ExtraLatency, + dest.htotal + / dest.pixel_rate_mhz + / 4)); + } else { + v->TimeForMetaPTEWithImmediateFlip = dest.htotal + / dest.pixel_rate_mhz / 4; + v->TimeForMetaPTEWithoutImmediateFlip = dest.htotal + / dest.pixel_rate_mhz / 4; + } + + if (ip->pte_enable == 1 || src.dcc == 1) { + v->TimeForMetaAndDPTERowWithImmediateFlip = + dml_max( + (v->MetaRowBytes[k] + + v->DPTEBytesPerRow[k]) + / v->PrefetchBW[k], + dml_max( + (v->MetaRowBytes[k] + + v->DPTEBytesPerRow[k]) + * v->TotalImmediateFlipBytes + / (v->BWAvailableForImmediateFlip + * (v->MetaPTEBytesPerFrame[k] + + v->MetaRowBytes[k] + + v->DPTEBytesPerRow[k])), + dml_max( + dest.htotal + / dest.pixel_rate_mhz + - v->TimeForMetaPTEWithImmediateFlip, + dml_max( + v->ExtraLatency, + 2 + * soc->urgent_latency_us)))); + + v->TimeForMetaAndDPTERowWithoutImmediateFlip = + dml_max( + (v->MetaRowBytes[k] + + v->DPTEBytesPerRow[k]) + / v->PrefetchBW[k], + dml_max( + dest.htotal + / dest.pixel_rate_mhz + - v->TimeForMetaPTEWithoutImmediateFlip, + v->ExtraLatency)); + } else { + v->TimeForMetaAndDPTERowWithImmediateFlip = + dml_max( + dest.htotal + / dest.pixel_rate_mhz + - v->TimeForMetaPTEWithImmediateFlip, + v->ExtraLatency + - v->TimeForMetaPTEWithImmediateFlip); + v->TimeForMetaAndDPTERowWithoutImmediateFlip = + dml_max( + dest.htotal + / dest.pixel_rate_mhz + - v->TimeForMetaPTEWithoutImmediateFlip, + v->ExtraLatency + - v->TimeForMetaPTEWithoutImmediateFlip); + } + + v->LinesForMetaPTEWithImmediateFlip[k] = + dml_floor_ex( + 4.0 + * (v->TimeForMetaPTEWithImmediateFlip + / (dest.htotal + / dest.pixel_rate_mhz) + + 0.125), + 1) / 4.0; + + v->LinesForMetaPTEWithoutImmediateFlip[k] = + dml_floor_ex( + 4.0 + * (v->TimeForMetaPTEWithoutImmediateFlip + / (dest.htotal + / dest.pixel_rate_mhz) + + 0.125), + 1) / 4.0; + + v->LinesForMetaAndDPTERowWithImmediateFlip[k] = + dml_floor_ex( + 4.0 + * (v->TimeForMetaAndDPTERowWithImmediateFlip + / (dest.htotal + / dest.pixel_rate_mhz) + + 0.125), + 1) / 4.0; + + v->LinesForMetaAndDPTERowWithoutImmediateFlip[k] = + dml_floor_ex( + 4.0 + * (v->TimeForMetaAndDPTERowWithoutImmediateFlip + / (dest.htotal + / dest.pixel_rate_mhz) + + 0.125), + 1) / 4.0; + + v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip = + v->LineTimesForPrefetch[k] + - v->LinesForMetaPTEWithImmediateFlip[k] + - v->LinesForMetaAndDPTERowWithImmediateFlip[k]; + + v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip = + v->LineTimesForPrefetch[k] + - v->LinesForMetaPTEWithoutImmediateFlip[k] + - v->LinesForMetaAndDPTERowWithoutImmediateFlip[k]; + + if (v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip > 0) { + v->VRatioPreYWithImmediateFlip[ijk] = + v->PrefetchLinesY[k] + / v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip; + if (v->SwathHeightYPerState[ijk] > 4) { + if (v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip + - (v->PrefillY[k] - 3.0) / 2.0 + > 0) { + v->VRatioPreYWithImmediateFlip[ijk] = + dml_max( + v->VRatioPreYWithImmediateFlip[ijk], + (v->MaxNumSwY[k] + * v->SwathHeightYPerState[ijk]) + / (v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip + - (v->PrefillY[k] + - 3.0) + / 2.0)); + } else { + v->VRatioPreYWithImmediateFlip[ijk] = + 999999; + } + } + v->VRatioPreCWithImmediateFlip[ijk] = + v->PrefetchLinesC[k] + / v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip; + if (v->SwathHeightCPerState[ijk] > 4) { + if (v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip + - (v->PrefillC[k] - 3.0) / 2.0 + > 0) { + v->VRatioPreCWithImmediateFlip[ijk] = + dml_max( + v->VRatioPreCWithImmediateFlip[ijk], + (v->MaxNumSwC[k] + * v->SwathHeightCPerState[ijk]) + / (v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip + - (v->PrefillC[k] + - 3.0) + / 2.0)); + } else { + v->VRatioPreCWithImmediateFlip[ijk] = + 999999; + } + } + + v->RequiredPrefetchPixelDataBWWithImmediateFlip[ijk] = + v->NoOfDPP[ijk] + * (v->PrefetchLinesY[k] + / v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + + v->PrefetchLinesC[k] + / v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip + * dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / 2) + * v->SwathWidthYPerState[ijk] + / (dest.htotal + / dest.pixel_rate_mhz); + } else { + v->VRatioPreYWithImmediateFlip[ijk] = 999999; + v->VRatioPreCWithImmediateFlip[ijk] = 999999; + v->RequiredPrefetchPixelDataBWWithImmediateFlip[ijk] = + 999999; + } + + if (v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip + > 0) { + v->VRatioPreYWithoutImmediateFlip[ijk] = + v->PrefetchLinesY[k] + / v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip; + if (v->SwathHeightYPerState[ijk] > 4) { + if (v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip + - (v->PrefillY[k] - 3.0) / 2.0 + > 0) { + v->VRatioPreYWithoutImmediateFlip[ijk] = + dml_max( + v->VRatioPreYWithoutImmediateFlip[ijk], + (v->MaxNumSwY[k] + * v->SwathHeightYPerState[ijk]) + / (v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip + - (v->PrefillY[k] + - 3.0) + / 2.0)); + } else { + v->VRatioPreYWithoutImmediateFlip[ijk] = + 999999; + } + } + v->VRatioPreCWithoutImmediateFlip[ijk] = + v->PrefetchLinesC[k] + / v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip; + if (v->SwathHeightCPerState[ijk] > 4) { + if (v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip + - (v->PrefillC[k] - 3.0) / 2.0 + > 0) { + v->VRatioPreCWithoutImmediateFlip[ijk] = + dml_max( + v->VRatioPreCWithoutImmediateFlip[ijk], + (v->MaxNumSwC[k] + * v->SwathHeightCPerState[ijk]) + / (v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip + - (v->PrefillC[k] + - 3.0) + / 2.0)); + } else { + v->VRatioPreCWithoutImmediateFlip[ijk] = + 999999; + } + } + + v->RequiredPrefetchPixelDataBWWithoutImmediateFlip[ijk] = + v->NoOfDPP[ijk] + * (v->PrefetchLinesY[k] + / v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + + v->PrefetchLinesC[k] + / v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip + * dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / 2) + * v->SwathWidthYPerState[ijk] + / (dest.htotal + / dest.pixel_rate_mhz); + } else { + v->VRatioPreYWithoutImmediateFlip[ijk] = 999999; + v->VRatioPreCWithoutImmediateFlip[ijk] = 999999; + v->RequiredPrefetchPixelDataBWWithoutImmediateFlip[ijk] = + 999999; + } + } + + v->MaximumReadBandwidthWithPrefetchWithImmediateFlip = 0; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + if (src.source_format != dm_420_8 + && src.source_format != dm_420_10) { + v->MaximumReadBandwidthWithPrefetchWithImmediateFlip = + v->MaximumReadBandwidthWithPrefetchWithImmediateFlip + + dml_max( + v->ReadBandwidth[k], + v->RequiredPrefetchPixelDataBWWithImmediateFlip[ijk]) + + dml_max( + v->MetaPTEBytesPerFrame[k] + / (v->LinesForMetaPTEWithImmediateFlip[k] + * dest.htotal + / dest.pixel_rate_mhz), + (v->MetaRowBytes[k] + + v->DPTEBytesPerRow[k]) + / (v->LinesForMetaAndDPTERowWithImmediateFlip[k] + * dest.htotal + / dest.pixel_rate_mhz)); + } else { + v->MaximumReadBandwidthWithPrefetchWithImmediateFlip = + v->MaximumReadBandwidthWithPrefetchWithImmediateFlip + + dml_max( + v->ReadBandwidth[k], + v->RequiredPrefetchPixelDataBWWithoutImmediateFlip[ijk]); + } + } + + v->MaximumReadBandwidthWithPrefetchWithoutImmediateFlip = 0; + + for (k = 0; k < num_planes; k++) { + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + v->MaximumReadBandwidthWithPrefetchWithoutImmediateFlip = + v->MaximumReadBandwidthWithPrefetchWithoutImmediateFlip + + dml_max( + v->ReadBandwidth[k], + v->RequiredPrefetchPixelDataBWWithoutImmediateFlip[ijk]); + } + + v->PrefetchSupportedWithImmediateFlip[ij] = 1; + if (v->MaximumReadBandwidthWithPrefetchWithImmediateFlip + > v->ReturnBWPerState[i]) { + v->PrefetchSupportedWithImmediateFlip[ij] = 0; + } + for (k = 0; k < num_planes; k++) { + if (v->LineTimesForPrefetch[k] < 2 + || v->LinesForMetaPTEWithImmediateFlip[k] >= 8 + || v->LinesForMetaAndDPTERowWithImmediateFlip[k] + >= 16) { + v->PrefetchSupportedWithImmediateFlip[ij] = 0; + } + } + + v->PrefetchSupportedWithoutImmediateFlip[ij] = 1; + if (v->MaximumReadBandwidthWithPrefetchWithoutImmediateFlip + > v->ReturnBWPerState[i]) { + v->PrefetchSupportedWithoutImmediateFlip[ij] = 0; + } + for (k = 0; k < num_planes; k++) { + if (v->LineTimesForPrefetch[k] < 2 + || v->LinesForMetaPTEWithoutImmediateFlip[k] >= 8 + || v->LinesForMetaAndDPTERowWithoutImmediateFlip[k] + >= 16) { + v->PrefetchSupportedWithoutImmediateFlip[ij] = 0; + } + } + } + } + + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + for (j = 0; j < 2; j++) { + ij = j * NumberOfStatesPlusTwo + i; + + v->VRatioInPrefetchSupportedWithImmediateFlip[ij] = 1; + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + if (((src.source_format != dm_420_8 + && src.source_format != dm_420_10) + && (v->VRatioPreYWithImmediateFlip[ijk] > 4 + || v->VRatioPreCWithImmediateFlip[ijk] + > 4)) + || ((src.source_format == dm_420_8 + || src.source_format == dm_420_10) + && (v->VRatioPreYWithoutImmediateFlip[ijk] + > 4 + || v->VRatioPreCWithoutImmediateFlip[ijk] + > 4))) { + v->VRatioInPrefetchSupportedWithImmediateFlip[ij] = 0; + } + } + v->VRatioInPrefetchSupportedWithoutImmediateFlip[ij] = 1; + for (k = 0; k < num_planes; k++) { + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + if (v->VRatioPreYWithoutImmediateFlip[ijk] > 4 + || v->VRatioPreCWithoutImmediateFlip[ijk] > 4) { + v->VRatioInPrefetchSupportedWithoutImmediateFlip[ij] = 0; + } + } + } + } + + // Mode Support, Voltage State and SOC Configuration + + for (i = (NumberOfStatesPlusTwo - 1); i >= 0; i--) // use int type here + { + for (j = 0; j < 2; j++) { + ij = j * NumberOfStatesPlusTwo + i; + + if (v->ScaleRatioSupport == 1 && v->SourceFormatPixelAndScanSupport == 1 + && v->ViewportSizeSupport == 1 + && v->BandwidthSupport[i] == 1 && v->DIOSupport[i] == 1 + && v->UrgentLatencySupport[ij] == 1 && v->ROBSupport[i] == 1 + && v->DISPCLK_DPPCLK_Support[ij] == 1 + && v->TotalAvailablePipesSupport[ij] == 1 + && v->TotalAvailableWritebackSupport == 1 + && v->WritebackLatencySupport == 1) { + if (v->PrefetchSupportedWithImmediateFlip[ij] == 1 + && v->VRatioInPrefetchSupportedWithImmediateFlip[ij] + == 1) { + v->ModeSupportWithImmediateFlip[ij] = 1; + } else { + v->ModeSupportWithImmediateFlip[ij] = 0; + } + if (v->PrefetchSupportedWithoutImmediateFlip[ij] == 1 + && v->VRatioInPrefetchSupportedWithoutImmediateFlip[ij] + == 1) { + v->ModeSupportWithoutImmediateFlip[ij] = 1; + } else { + v->ModeSupportWithoutImmediateFlip[ij] = 0; + } + } else { + v->ModeSupportWithImmediateFlip[ij] = 0; + v->ModeSupportWithoutImmediateFlip[ij] = 0; + } + } + } + + for (i = (NumberOfStatesPlusTwo - 1); i >= 0; i--) // use int type here + { + if ((i == (NumberOfStatesPlusTwo - 1) + || v->ModeSupportWithImmediateFlip[1 * NumberOfStatesPlusTwo + i] + == 1 + || v->ModeSupportWithImmediateFlip[0 * NumberOfStatesPlusTwo + i] + == 1) && i >= v->VoltageOverrideLevel) { + v->VoltageLevelWithImmediateFlip = i; + } + } + + for (i = (NumberOfStatesPlusTwo - 1); i >= 0; i--) // use int type here + { + if ((i == (NumberOfStatesPlusTwo - 1) + || v->ModeSupportWithoutImmediateFlip[1 * NumberOfStatesPlusTwo + i] + == 1 + || v->ModeSupportWithoutImmediateFlip[0 * NumberOfStatesPlusTwo + i] + == 1) && i >= v->VoltageOverrideLevel) { + v->VoltageLevelWithoutImmediateFlip = i; + } + } + + if (v->VoltageLevelWithImmediateFlip == (NumberOfStatesPlusTwo - 1)) { + v->ImmediateFlipSupported = 0; + v->VoltageLevel = v->VoltageLevelWithoutImmediateFlip; + } else { + v->ImmediateFlipSupported = 1; + v->VoltageLevel = v->VoltageLevelWithImmediateFlip; + } + + v->DCFCLK = v->DCFCLKPerState[(int) v->VoltageLevel]; + v->FabricAndDRAMBandwidth = v->FabricAndDRAMBandwidthPerState[(int) v->VoltageLevel]; + + for (j = 0; j < 2; j++) { + v->RequiredDISPCLKPerRatio[j] = v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + + (int) v->VoltageLevel]; + for (k = 0; k < num_planes; k++) { + v->DPPPerPlanePerRatio[k * 2 + j] = v->NoOfDPP[k * 2 * NumberOfStatesPlusTwo + + j * NumberOfStatesPlusTwo + (int) v->VoltageLevel]; + } + v->DISPCLK_DPPCLK_SupportPerRatio[j] = v->DISPCLK_DPPCLK_Support[j + * NumberOfStatesPlusTwo + (int) v->VoltageLevel]; + } + + ASSERT(v->ImmediateFlipSupported || v->MacroTileBlockWidthC || v->DCFCLK || v->FabricAndDRAMBandwidth); + + return (v->VoltageLevel); +} + diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.h new file mode 100644 index 000000000000..ead4942f998c --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.h @@ -0,0 +1,199 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef __DISPLAY_MODE_SUPPORT_H__ +#define __DISPLAY_MODE_SUPPORT_H__ + +#include "dml_common_defs.h" + +struct display_mode_lib; + +#define NumberOfStates 4 +#define NumberOfStatesPlusTwo (NumberOfStates+2) + +struct dml_ms_internal_vars { + double ScaleRatioSupport; + double SourceFormatPixelAndScanSupport; + double TotalReadBandwidthConsumedGBytePerSecond; + double TotalWriteBandwidthConsumedGBytePerSecond; + double TotalBandwidthConsumedGBytePerSecond; + double DCCEnabledInAnyPlane; + double ReturnBWToDCNPerState; + double CriticalPoint; + double WritebackLatencySupport; + double RequiredOutputBW; + double TotalNumberOfActiveWriteback; + double TotalAvailableWritebackSupport; + double MaximumSwathWidth; + double NumberOfDPPRequiredForDETSize; + double NumberOfDPPRequiredForLBSize; + double MinDispclkUsingSingleDPP; + double MinDispclkUsingDualDPP; + double ViewportSizeSupport; + double SwathWidthGranularityY; + double RoundedUpMaxSwathSizeBytesY; + double SwathWidthGranularityC; + double RoundedUpMaxSwathSizeBytesC; + double LinesInDETLuma; + double LinesInDETChroma; + double EffectiveLBLatencyHidingSourceLinesLuma; + double EffectiveLBLatencyHidingSourceLinesChroma; + double EffectiveDETLBLinesLuma; + double EffectiveDETLBLinesChroma; + double ProjectedDCFCLKDeepSleep; + double MetaReqHeightY; + double MetaReqWidthY; + double MetaSurfaceWidthY; + double MetaSurfaceHeightY; + double MetaPteBytesPerFrameY; + double MetaRowBytesY; + double MacroTileBlockSizeBytesY; + double MacroTileBlockHeightY; + double DataPTEReqHeightY; + double DataPTEReqWidthY; + double DPTEBytesPerRowY; + double MetaReqHeightC; + double MetaReqWidthC; + double MetaSurfaceWidthC; + double MetaSurfaceHeightC; + double MetaPteBytesPerFrameC; + double MetaRowBytesC; + double MacroTileBlockSizeBytesC; + double MacroTileBlockHeightC; + double MacroTileBlockWidthC; + double DataPTEReqHeightC; + double DataPTEReqWidthC; + double DPTEBytesPerRowC; + double VInitY; + double MaxPartialSwY; + double VInitC; + double MaxPartialSwC; + double dst_x_after_scaler; + double dst_y_after_scaler; + double TimeCalc; + double VUpdateOffset; + double TotalRepeaterDelay; + double VUpdateWidth; + double VReadyOffset; + double TimeSetup; + double ExtraLatency; + double MaximumVStartup; + double BWAvailableForImmediateFlip; + double TotalImmediateFlipBytes; + double TimeForMetaPTEWithImmediateFlip; + double TimeForMetaPTEWithoutImmediateFlip; + double TimeForMetaAndDPTERowWithImmediateFlip; + double TimeForMetaAndDPTERowWithoutImmediateFlip; + double LineTimesToRequestPrefetchPixelDataWithImmediateFlip; + double LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip; + double MaximumReadBandwidthWithPrefetchWithImmediateFlip; + double MaximumReadBandwidthWithPrefetchWithoutImmediateFlip; + double VoltageOverrideLevel; + double VoltageLevelWithImmediateFlip; + double VoltageLevelWithoutImmediateFlip; + double ImmediateFlipSupported; + double VoltageLevel; + double DCFCLK; + double FabricAndDRAMBandwidth; + double SwathWidthYSingleDPP[DC__NUM_PIPES__MAX]; + double BytePerPixelInDETY[DC__NUM_PIPES__MAX]; + double BytePerPixelInDETC[DC__NUM_PIPES__MAX]; + double ReadBandwidth[DC__NUM_PIPES__MAX]; + double WriteBandwidth[DC__NUM_PIPES__MAX]; + double DCFCLKPerState[NumberOfStatesPlusTwo]; + double FabricAndDRAMBandwidthPerState[NumberOfStatesPlusTwo]; + double ReturnBWPerState[NumberOfStatesPlusTwo]; + double BandwidthSupport[NumberOfStatesPlusTwo]; + double UrgentRoundTripAndOutOfOrderLatencyPerState[NumberOfStatesPlusTwo]; + double ROBSupport[NumberOfStatesPlusTwo]; + double RequiredPHYCLK[DC__NUM_PIPES__MAX]; + double DIOSupport[NumberOfStatesPlusTwo]; + double PHYCLKPerState[NumberOfStatesPlusTwo]; + double PSCL_FACTOR[DC__NUM_PIPES__MAX]; + double PSCL_FACTOR_CHROMA[DC__NUM_PIPES__MAX]; + double MinDPPCLKUsingSingleDPP[DC__NUM_PIPES__MAX]; + double Read256BlockHeightY[DC__NUM_PIPES__MAX]; + double Read256BlockWidthY[DC__NUM_PIPES__MAX]; + double Read256BlockHeightC[DC__NUM_PIPES__MAX]; + double Read256BlockWidthC[DC__NUM_PIPES__MAX]; + double MaxSwathHeightY[DC__NUM_PIPES__MAX]; + double MaxSwathHeightC[DC__NUM_PIPES__MAX]; + double MinSwathHeightY[DC__NUM_PIPES__MAX]; + double MinSwathHeightC[DC__NUM_PIPES__MAX]; + double NumberOfDPPRequiredForDETAndLBSize[DC__NUM_PIPES__MAX]; + double TotalNumberOfActiveDPP[NumberOfStatesPlusTwo * 2]; + double RequiredDISPCLK[NumberOfStatesPlusTwo * 2]; + double DISPCLK_DPPCLK_Support[NumberOfStatesPlusTwo * 2]; + double MaxDispclk[NumberOfStatesPlusTwo]; + double MaxDppclk[NumberOfStatesPlusTwo]; + double NoOfDPP[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; + double TotalAvailablePipesSupport[NumberOfStatesPlusTwo * 2]; + double SwathWidthYPerState[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; + double SwathHeightYPerState[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; + double SwathHeightCPerState[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; + double DETBufferSizeYPerState[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; + double UrgentLatencySupportUsPerState[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; + double UrgentLatencySupport[NumberOfStatesPlusTwo * 2]; + double TotalNumberOfDCCActiveDPP[NumberOfStatesPlusTwo * 2]; + double DPTEBytesPerRow[DC__NUM_PIPES__MAX]; + double MetaPTEBytesPerFrame[DC__NUM_PIPES__MAX]; + double MetaRowBytes[DC__NUM_PIPES__MAX]; + double PrefillY[DC__NUM_PIPES__MAX]; + double MaxNumSwY[DC__NUM_PIPES__MAX]; + double PrefetchLinesY[DC__NUM_PIPES__MAX]; + double PrefillC[DC__NUM_PIPES__MAX]; + double MaxNumSwC[DC__NUM_PIPES__MAX]; + double PrefetchLinesC[DC__NUM_PIPES__MAX]; + double LineTimesForPrefetch[DC__NUM_PIPES__MAX]; + double PrefetchBW[DC__NUM_PIPES__MAX]; + double LinesForMetaPTEWithImmediateFlip[DC__NUM_PIPES__MAX]; + double LinesForMetaPTEWithoutImmediateFlip[DC__NUM_PIPES__MAX]; + double LinesForMetaAndDPTERowWithImmediateFlip[DC__NUM_PIPES__MAX]; + double LinesForMetaAndDPTERowWithoutImmediateFlip[DC__NUM_PIPES__MAX]; + double VRatioPreYWithImmediateFlip[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; + double VRatioPreCWithImmediateFlip[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; + double RequiredPrefetchPixelDataBWWithImmediateFlip[NumberOfStatesPlusTwo * 2 + * DC__NUM_PIPES__MAX]; + double VRatioPreYWithoutImmediateFlip[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; + double VRatioPreCWithoutImmediateFlip[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; + double RequiredPrefetchPixelDataBWWithoutImmediateFlip[NumberOfStatesPlusTwo * 2 + * DC__NUM_PIPES__MAX]; + double PrefetchSupportedWithImmediateFlip[NumberOfStatesPlusTwo * 2]; + double PrefetchSupportedWithoutImmediateFlip[NumberOfStatesPlusTwo * 2]; + double VRatioInPrefetchSupportedWithImmediateFlip[NumberOfStatesPlusTwo * 2]; + double VRatioInPrefetchSupportedWithoutImmediateFlip[NumberOfStatesPlusTwo * 2]; + double ModeSupportWithImmediateFlip[NumberOfStatesPlusTwo * 2]; + double ModeSupportWithoutImmediateFlip[NumberOfStatesPlusTwo * 2]; + double RequiredDISPCLKPerRatio[2]; + double DPPPerPlanePerRatio[2 * DC__NUM_PIPES__MAX]; + double DISPCLK_DPPCLK_SupportPerRatio[2]; + struct _vcs_dpi_wm_calc_pipe_params_st planes[DC__NUM_PIPES__MAX]; +}; + +int dml_ms_check( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + int num_pipes); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.c b/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.c new file mode 100644 index 000000000000..2e4dc57cafa0 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.c @@ -0,0 +1,367 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "display_pipe_clocks.h" +#include "display_mode_lib.h" +#include "soc_bounding_box.h" + +static enum voltage_state power_state( + struct display_mode_lib *mode_lib, + double dispclk, + double dppclk) +{ + enum voltage_state state1; + enum voltage_state state2; + + if (dispclk <= mode_lib->soc.vmin.dispclk_mhz) + state1 = dm_vmin; + else if (dispclk <= mode_lib->soc.vnom.dispclk_mhz) + state1 = dm_vnom; + else if (dispclk <= mode_lib->soc.vmax.dispclk_mhz) + state1 = dm_vmax; + else + state1 = dm_vmax_exceeded; + + if (dppclk <= mode_lib->soc.vmin.dppclk_mhz) + state2 = dm_vmin; + else if (dppclk <= mode_lib->soc.vnom.dppclk_mhz) + state2 = dm_vnom; + else if (dppclk <= mode_lib->soc.vmax.dppclk_mhz) + state2 = dm_vmax; + else + state2 = dm_vmax_exceeded; + + if (state1 > state2) + return state1; + else + return state2; +} + +static unsigned int dpp_in_grp( + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_pipes, + unsigned int hsplit_grp) +{ + unsigned int num_dpp = 0; + unsigned int i; + + for (i = 0; i < num_pipes; i++) { + if (e2e[i].pipe.src.is_hsplit) { + if (e2e[i].pipe.src.hsplit_grp == hsplit_grp) { + num_dpp++; + } + } + } + + if (0 == num_dpp) + num_dpp = 1; + + return num_dpp; +} + +static void calculate_pipe_clk_requirement( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_dpp_in_grp, + double *dppclk, + double *dispclk, + bool *dppdiv) +{ + double pscl_throughput = 0.0; + double max_hratio = e2e->pipe.scale_ratio_depth.hscl_ratio; + double max_vratio = e2e->pipe.scale_ratio_depth.vscl_ratio; + double max_htaps = e2e->pipe.scale_taps.htaps; + double max_vtaps = e2e->pipe.scale_taps.vtaps; + double dpp_clock_divider = (double) num_dpp_in_grp; + double dispclk_dppclk_ratio; + double dispclk_ramp_margin_percent; + + if (max_hratio > 1.0) { + double pscl_to_lb = ((double) mode_lib->ip.max_pscl_lb_bw_pix_per_clk * max_hratio) + / dml_ceil(max_htaps / 6.0); + pscl_throughput = dml_min( + pscl_to_lb, + (double) mode_lib->ip.max_dchub_pscl_bw_pix_per_clk); + } else { + pscl_throughput = dml_min( + (double) mode_lib->ip.max_pscl_lb_bw_pix_per_clk, + (double) mode_lib->ip.max_dchub_pscl_bw_pix_per_clk); + } + + DTRACE("pscl_throughput: %f pix per clk", pscl_throughput); + DTRACE("vtaps: %f hratio: %f vratio: %f", max_vtaps, max_hratio, max_vratio); + *dppclk = dml_max( + max_vtaps / 6.0 * dml_min(1.0, max_hratio), + max_hratio * max_vratio / pscl_throughput); + DTRACE("pixel rate multiplier: %f", *dppclk); + *dppclk = dml_max(*dppclk, 1.0); + DTRACE("pixel rate multiplier clamped: %f", *dppclk); + *dppclk = *dppclk * e2e->pipe.dest.pixel_rate_mhz; + + *dppclk = *dppclk / dpp_clock_divider; + DTRACE("dppclk after split: %f", *dppclk); + + if (dpp_clock_divider > 1.0 && (*dppclk < e2e->pipe.dest.pixel_rate_mhz)) { + dispclk_dppclk_ratio = 2.0; + *dppdiv = true; + } else { + dispclk_dppclk_ratio = 1.0; + *dppdiv = false; + } + + dispclk_ramp_margin_percent = mode_lib->ip.dispclk_ramp_margin_percent; + + /* Comment this out because of Gabes possible bug in spreadsheet, + * just to make other cases evident during debug + * + *if(e2e->clks_cfg.voltage == dm_vmax) + * dispclk_ramp_margin_percent = 0.0; + */ + + /* account for ramping margin and downspread */ + *dispclk = dml_max(*dppclk * dispclk_dppclk_ratio, e2e->pipe.dest.pixel_rate_mhz) + * (1.0 + (double) mode_lib->soc.downspread_percent / 100.0) + * (1.0 + (double) dispclk_ramp_margin_percent / 100.0); + + return; +} + +bool dml_clks_pipe_clock_requirement_fit_power_constraint( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_dpp_in_grp) +{ + double dppclk = 0; + double dispclk = 0; + bool dppdiv = 0; + + calculate_pipe_clk_requirement(mode_lib, e2e, num_dpp_in_grp, &dppclk, &dispclk, &dppdiv); + + if (power_state(mode_lib, dispclk, dppclk) > e2e->clks_cfg.voltage) { + return false; + } + + return true; +} + +static void get_plane_clks( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_pipes, + double *dppclks, + double *dispclks, + bool *dppdiv) +{ + /* it is assumed that the scale ratios passed into the e2e pipe params have already been calculated + * for any split pipe configurations, where extra pixels inthe overlap region do not contribute to + * the scale ratio. This means that we can simply calculate the dppclk for each dpp independently + * and we would expect the same result on any split pipes, which would be handled + */ + unsigned int i; + + for (i = 0; i < num_pipes; i++) { + double num_dpp_in_grp; + double dispclk_ramp_margin_percent; + double dispclk_margined; + + if (e2e[i].pipe.src.is_hsplit) + num_dpp_in_grp = (double) dpp_in_grp( + e2e, + num_pipes, + e2e[i].pipe.src.hsplit_grp); + else + num_dpp_in_grp = 1; + + calculate_pipe_clk_requirement( + mode_lib, + &e2e[i], + num_dpp_in_grp, + &dppclks[i], + &dispclks[i], + &dppdiv[i]); + + dispclk_ramp_margin_percent = mode_lib->ip.dispclk_ramp_margin_percent; + + dispclk_margined = e2e[i].pipe.dest.pixel_rate_mhz + * (1.0 + (double) mode_lib->soc.downspread_percent / 100.0) + * (1.0 + (double) dispclk_ramp_margin_percent / 100.0); + + DTRACE("p%d: requested power state: %d", i, (int) e2e[0].clks_cfg.voltage); + + if (power_state(mode_lib, dispclks[i], dppclks[i]) + > power_state(mode_lib, dispclk_margined, dispclk_margined) + && dispclk_margined > dppclks[i]) { + if (power_state(mode_lib, dispclks[i], dppclks[i]) + > e2e[0].clks_cfg.voltage) { + dispclks[i] = dispclk_margined; + dppclks[i] = dispclk_margined; + dppdiv[i] = false; + } + } + + DTRACE("p%d: dispclk: %f", i, dispclks[i]); + } +} + +static void get_dcfclk( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_pipes, + double *dcfclk_mhz) +{ + double bytes_per_pixel_det_y[DC__NUM_PIPES__MAX]; + double bytes_per_pixel_det_c[DC__NUM_PIPES__MAX]; + double swath_width_y[DC__NUM_PIPES__MAX]; + unsigned int i; + double total_read_bandwidth_gbps = 0.0; + + for (i = 0; i < num_pipes; i++) { + if (e2e[i].pipe.src.source_scan == dm_horz) { + swath_width_y[i] = e2e[i].pipe.src.viewport_width * 1.0; + } else { + swath_width_y[i] = e2e[i].pipe.src.viewport_height * 1.0; + } + + switch (e2e[i].pipe.src.source_format) { + case dm_444_64: + bytes_per_pixel_det_y[i] = 8.0; + bytes_per_pixel_det_c[i] = 0.0; + break; + case dm_444_32: + bytes_per_pixel_det_y[i] = 4.0; + bytes_per_pixel_det_c[i] = 0.0; + break; + case dm_444_16: + bytes_per_pixel_det_y[i] = 2.0; + bytes_per_pixel_det_c[i] = 0.0; + break; + case dm_422_8: + bytes_per_pixel_det_y[i] = 2.0; + bytes_per_pixel_det_c[i] = 0.0; + break; + case dm_422_10: + bytes_per_pixel_det_y[i] = 4.0; + bytes_per_pixel_det_c[i] = 0.0; + break; + case dm_420_8: + bytes_per_pixel_det_y[i] = 1.0; + bytes_per_pixel_det_c[i] = 2.0; + break; + case dm_420_10: + bytes_per_pixel_det_y[i] = 4.0 / 3.0; + bytes_per_pixel_det_c[i] = 8.0 / 3.0; + break; + default: + BREAK_TO_DEBUGGER(); /* invalid src_format in get_dcfclk */ + } + } + + for (i = 0; i < num_pipes; i++) { + double read_bandwidth_plane_mbps = 0.0; + read_bandwidth_plane_mbps = (double) swath_width_y[i] + * ((double) bytes_per_pixel_det_y[i] + + (double) bytes_per_pixel_det_c[i] / 2.0) + / ((double) e2e[i].pipe.dest.htotal + / (double) e2e[i].pipe.dest.pixel_rate_mhz) + * e2e[i].pipe.scale_ratio_depth.vscl_ratio; + + if (e2e[i].pipe.src.dcc) { + read_bandwidth_plane_mbps += (read_bandwidth_plane_mbps / 1000.0 / 256.0); + } + + if (e2e[i].pipe.src.vm) { + read_bandwidth_plane_mbps += (read_bandwidth_plane_mbps / 1000.0 / 512.0); + } + + total_read_bandwidth_gbps = total_read_bandwidth_gbps + + read_bandwidth_plane_mbps / 1000.0; + } + + DTRACE("total bandwidth = %f gbps", total_read_bandwidth_gbps); + + (*dcfclk_mhz) = (total_read_bandwidth_gbps * 1000.0) / mode_lib->soc.return_bus_width_bytes; + + DTRACE( + "minimum theoretical dcfclk without stutter and full utilization = %f MHz", + (*dcfclk_mhz)); + +} + +struct _vcs_dpi_display_pipe_clock_st dml_clks_get_pipe_clocks( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_pipes) +{ + struct _vcs_dpi_display_pipe_clock_st clocks; + double max_dispclk = 0.0; + double dcfclk; + double dispclks[DC__NUM_PIPES__MAX]; + double dppclks[DC__NUM_PIPES__MAX]; + bool dppdiv[DC__NUM_PIPES__MAX]; + unsigned int i; + + DTRACE("Calculating pipe clocks..."); + + /* this is the theoretical minimum, have to adjust based on valid values for soc */ + get_dcfclk(mode_lib, e2e, num_pipes, &dcfclk); + + /* if(dcfclk > soc.vnom.dcfclk_mhz) + * dcfclk = soc.vmax.dcfclk_mhz; + * else if(dcfclk > soc.vmin.dcfclk_mhz) + * dcfclk = soc.vnom.dcfclk_mhz; + * else + * dcfclk = soc.vmin.dcfclk_mhz; + */ + + dcfclk = dml_socbb_voltage_scaling( + &mode_lib->soc, + (enum voltage_state) e2e[0].clks_cfg.voltage).dcfclk_mhz; + clocks.dcfclk_mhz = dcfclk; + + get_plane_clks(mode_lib, e2e, num_pipes, dppclks, dispclks, dppdiv); + + for (i = 0; i < num_pipes; i++) { + max_dispclk = dml_max(max_dispclk, dispclks[i]); + } + + clocks.dispclk_mhz = max_dispclk; + DTRACE("dispclk: %f Mhz", clocks.dispclk_mhz); + DTRACE("dcfclk: %f Mhz", clocks.dcfclk_mhz); + + for (i = 0; i < num_pipes; i++) { + if (dppclks[i] * 2 < max_dispclk) + dppdiv[i] = 1; + + if (dppdiv[i]) + clocks.dppclk_div[i] = 1; + else + clocks.dppclk_div[i] = 0; + + clocks.dppclk_mhz[i] = max_dispclk / ((dppdiv[i]) ? 2.0 : 1.0); + DTRACE("dppclk%d: %f Mhz", i, clocks.dppclk_mhz[i]); + } + + return clocks; +} diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.h b/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.h new file mode 100644 index 000000000000..aed5f33bb04f --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.h @@ -0,0 +1,41 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef __DISPLAY_PIPE_CLOCKS_H__ +#define __DISPLAY_PIPE_CLOCKS_H__ + +#include "dml_common_defs.h" + +struct display_mode_lib; + +struct _vcs_dpi_display_pipe_clock_st dml_clks_get_pipe_clocks( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_pipes); + +bool dml_clks_pipe_clock_requirement_fit_power_constraint( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_dpp_in_grp); +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c new file mode 100644 index 000000000000..9fccbbffe129 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c @@ -0,0 +1,2254 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#include "display_rq_dlg_calc.h" +#include "display_mode_lib.h" + +static unsigned int get_bytes_per_element(enum source_format_class source_format, bool is_chroma) +{ + unsigned int ret_val = 0; + + if (source_format == dm_444_16) { + if (!is_chroma) + ret_val = 2; + } else if (source_format == dm_444_32) { + if (!is_chroma) + ret_val = 4; + } else if (source_format == dm_444_64) { + if (!is_chroma) + ret_val = 8; + } else if (source_format == dm_420_8) { + if (is_chroma) + ret_val = 2; + else + ret_val = 1; + } else if (source_format == dm_420_10) { + if (is_chroma) + ret_val = 4; + else + ret_val = 2; + } + return ret_val; +} + +static bool is_dual_plane(enum source_format_class source_format) +{ + bool ret_val = 0; + + if ((source_format == dm_420_8) || (source_format == dm_420_10)) + ret_val = 1; + + return ret_val; +} + +static void get_blk256_size( + unsigned int *blk256_width, + unsigned int *blk256_height, + unsigned int bytes_per_element) +{ + if (bytes_per_element == 1) { + *blk256_width = 16; + *blk256_height = 16; + } else if (bytes_per_element == 2) { + *blk256_width = 16; + *blk256_height = 8; + } else if (bytes_per_element == 4) { + *blk256_width = 8; + *blk256_height = 8; + } else if (bytes_per_element == 8) { + *blk256_width = 8; + *blk256_height = 4; + } +} + +static double get_refcyc_per_delivery( + struct display_mode_lib *mode_lib, + double refclk_freq_in_mhz, + double pclk_freq_in_mhz, + int unsigned recout_width, + double vratio, + double hscale_pixel_rate, + int unsigned delivery_width, + int unsigned req_per_swath_ub) +{ + double refcyc_per_delivery = 0.0; + if (vratio <= 1.0) { + refcyc_per_delivery = (double) refclk_freq_in_mhz * (double) recout_width + / pclk_freq_in_mhz / (double) req_per_swath_ub; + } else { + refcyc_per_delivery = (double) refclk_freq_in_mhz * (double) delivery_width + / (double) hscale_pixel_rate / (double) req_per_swath_ub; + } + + DTRACE("DLG: %s: refclk_freq_in_mhz = %3.2f", __func__, refclk_freq_in_mhz); + DTRACE("DLG: %s: pclk_freq_in_mhz = %3.2f", __func__, pclk_freq_in_mhz); + DTRACE("DLG: %s: recout_width = %d", __func__, recout_width); + DTRACE("DLG: %s: vratio = %3.2f", __func__, vratio); + DTRACE("DLG: %s: req_per_swath_ub = %d", __func__, req_per_swath_ub); + DTRACE("DLG: %s: refcyc_per_delivery= %3.2f", __func__, refcyc_per_delivery); + + return refcyc_per_delivery; + +} + +static double get_vratio_pre( + struct display_mode_lib *mode_lib, + unsigned int max_num_sw, + unsigned int max_partial_sw, + unsigned int swath_height, + double vinit, + double l_sw) +{ + double prefill = dml_floor(vinit); + double vratio_pre = 1.0; + + vratio_pre = (max_num_sw * swath_height + max_partial_sw) / l_sw; + + if (swath_height > 4) { + double tmp0 = (max_num_sw * swath_height) / (l_sw - (prefill - 3.0) / 2.0); + if (tmp0 > vratio_pre) + vratio_pre = tmp0; + } + + DTRACE("DLG: %s: max_num_sw = %0d", __func__, max_num_sw); + DTRACE("DLG: %s: max_partial_sw = %0d", __func__, max_partial_sw); + DTRACE("DLG: %s: swath_height = %0d", __func__, swath_height); + DTRACE("DLG: %s: vinit = %3.2f", __func__, vinit); + DTRACE("DLG: %s: vratio_pre = %3.2f", __func__, vratio_pre); + + if (vratio_pre < 1.0) { + DTRACE("WARNING_DLG: %s: vratio_pre=%3.2f < 1.0, set to 1.0", __func__, vratio_pre); + vratio_pre = 1.0; + } + + if (vratio_pre > 4.0) { + DTRACE( + "WARNING_DLG: %s: vratio_pre=%3.2f > 4.0 (max scaling ratio). set to 4.0", + __func__, + vratio_pre); + vratio_pre = 4.0; + } + + return vratio_pre; +} + +static void get_swath_need( + struct display_mode_lib *mode_lib, + unsigned int *max_num_sw, + unsigned int *max_partial_sw, + unsigned int swath_height, + double vinit) +{ + double prefill = dml_floor(vinit); + unsigned int max_partial_sw_int; + + DTRACE("DLG: %s: swath_height = %0d", __func__, swath_height); + DTRACE("DLG: %s: vinit = %3.2f", __func__, vinit); + + ASSERT(prefill > 0.0 && prefill <= 8.0); + + *max_num_sw = (int unsigned) (dml_ceil((prefill - 1.0) / (double) swath_height) + 1.0); /* prefill has to be >= 1 */ + max_partial_sw_int = + (prefill == 1) ? + (swath_height - 1) : + ((int unsigned) (prefill - 2.0) % swath_height); + *max_partial_sw = (max_partial_sw_int < 1) ? 1 : max_partial_sw_int; /* ensure minimum of 1 is used */ + + DTRACE("DLG: %s: max_num_sw = %0d", __func__, *max_num_sw); + DTRACE("DLG: %s: max_partial_sw = %0d", __func__, *max_partial_sw); +} + +static unsigned int get_blk_size_bytes(const enum source_macro_tile_size tile_size) +{ + if (tile_size == dm_256k_tile) + return (256 * 1024); + else if (tile_size == dm_64k_tile) + return (64 * 1024); + else + return (4 * 1024); +} + +static void extract_rq_sizing_regs( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_data_rq_regs_st *rq_regs, + const struct _vcs_dpi_display_data_rq_sizing_params_st rq_sizing) +{ + DTRACE("DLG: %s: rq_sizing param", __func__); + print__data_rq_sizing_params_st(mode_lib, rq_sizing); + + rq_regs->chunk_size = dml_log2(rq_sizing.chunk_bytes) - 10; + + if (rq_sizing.min_chunk_bytes == 0) + rq_regs->min_chunk_size = 0; + else + rq_regs->min_chunk_size = dml_log2(rq_sizing.min_chunk_bytes) - 8 + 1; + + rq_regs->meta_chunk_size = dml_log2(rq_sizing.meta_chunk_bytes) - 10; + if (rq_sizing.min_meta_chunk_bytes == 0) + rq_regs->min_meta_chunk_size = 0; + else + rq_regs->min_meta_chunk_size = dml_log2(rq_sizing.min_meta_chunk_bytes) - 6 + 1; + + rq_regs->dpte_group_size = dml_log2(rq_sizing.dpte_group_bytes) - 6; + rq_regs->mpte_group_size = dml_log2(rq_sizing.mpte_group_bytes) - 6; +} + +void extract_rq_regs( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_regs_st *rq_regs, + const struct _vcs_dpi_display_rq_params_st rq_param) +{ + unsigned int detile_buf_size_in_bytes = mode_lib->ip.det_buffer_size_kbytes * 1024; + unsigned int detile_buf_plane1_addr = 0; + + extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_l), rq_param.sizing.rq_l); + if (rq_param.yuv420) + extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_c), rq_param.sizing.rq_c); + + rq_regs->rq_regs_l.swath_height = dml_log2(rq_param.dlg.rq_l.swath_height); + rq_regs->rq_regs_c.swath_height = dml_log2(rq_param.dlg.rq_c.swath_height); + + /* FIXME: take the max between luma, chroma chunk size? + * okay for now, as we are setting chunk_bytes to 8kb anyways + */ + if (rq_param.sizing.rq_l.chunk_bytes >= 32 * 1024) { /*32kb */ + rq_regs->drq_expansion_mode = 0; + } else { + rq_regs->drq_expansion_mode = 2; + } + rq_regs->prq_expansion_mode = 1; + rq_regs->mrq_expansion_mode = 1; + rq_regs->crq_expansion_mode = 1; + + if (rq_param.yuv420) { + if ((double) rq_param.misc.rq_l.stored_swath_bytes + / (double) rq_param.misc.rq_c.stored_swath_bytes <= 1.5) { + detile_buf_plane1_addr = (detile_buf_size_in_bytes / 2.0 / 64.0); /* half to chroma */ + } else { + detile_buf_plane1_addr = dml_round_to_multiple( + (unsigned int) ((2.0 * detile_buf_size_in_bytes) / 3.0), + 256, + 0) / 64.0; /* 2/3 to chroma */ + } + } + rq_regs->plane1_base_address = detile_buf_plane1_addr; +} + +static void handle_det_buf_split( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_params_st *rq_param, + const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param) +{ + unsigned int total_swath_bytes = 0; + unsigned int swath_bytes_l = 0; + unsigned int swath_bytes_c = 0; + unsigned int full_swath_bytes_packed_l = 0; + unsigned int full_swath_bytes_packed_c = 0; + bool req128_l = 0; + bool req128_c = 0; + bool surf_linear = (pipe_src_param.sw_mode == dm_sw_linear); + bool surf_vert = (pipe_src_param.source_scan == dm_vert); + unsigned int log2_swath_height_l = 0; + unsigned int log2_swath_height_c = 0; + unsigned int detile_buf_size_in_bytes = mode_lib->ip.det_buffer_size_kbytes * 1024; + + full_swath_bytes_packed_l = rq_param->misc.rq_l.full_swath_bytes; + full_swath_bytes_packed_c = rq_param->misc.rq_c.full_swath_bytes; + + if (rq_param->yuv420_10bpc) { + full_swath_bytes_packed_l = dml_round_to_multiple( + rq_param->misc.rq_l.full_swath_bytes * 2 / 3, + 256, + 1) + 256; + full_swath_bytes_packed_c = dml_round_to_multiple( + rq_param->misc.rq_c.full_swath_bytes * 2 / 3, + 256, + 1) + 256; + } + + if (rq_param->yuv420) { + total_swath_bytes = 2 * full_swath_bytes_packed_l + 2 * full_swath_bytes_packed_c; + + if (total_swath_bytes <= detile_buf_size_in_bytes) { /*full 256b request */ + req128_l = 0; + req128_c = 0; + swath_bytes_l = full_swath_bytes_packed_l; + swath_bytes_c = full_swath_bytes_packed_c; + } else { /*128b request (for luma only for yuv420 8bpc) */ + req128_l = 1; + req128_c = 0; + swath_bytes_l = full_swath_bytes_packed_l / 2; + swath_bytes_c = full_swath_bytes_packed_c; + } + + /* Bug workaround, luma and chroma req size needs to be the same. (see: DEGVIDCN10-137) + * TODO: Remove after rtl fix + */ + if (req128_l == 1) { + req128_c = 1; + DTRACE("DLG: %s: bug workaround DEGVIDCN10-137", __func__); + } + + /* Note: assumption, the config that pass in will fit into + * the detiled buffer. + */ + } else { + total_swath_bytes = 2 * full_swath_bytes_packed_l; + + if (total_swath_bytes <= detile_buf_size_in_bytes) + req128_l = 0; + else + req128_l = 1; + + swath_bytes_l = total_swath_bytes; + swath_bytes_c = 0; + } + rq_param->misc.rq_l.stored_swath_bytes = swath_bytes_l; + rq_param->misc.rq_c.stored_swath_bytes = swath_bytes_c; + + if (surf_linear) { + log2_swath_height_l = 0; + log2_swath_height_c = 0; + } else if (!surf_vert) { + log2_swath_height_l = dml_log2(rq_param->misc.rq_l.blk256_height) - req128_l; + log2_swath_height_c = dml_log2(rq_param->misc.rq_c.blk256_height) - req128_c; + } else { + log2_swath_height_l = dml_log2(rq_param->misc.rq_l.blk256_width) - req128_l; + log2_swath_height_c = dml_log2(rq_param->misc.rq_c.blk256_width) - req128_c; + } + rq_param->dlg.rq_l.swath_height = 1 << log2_swath_height_l; + rq_param->dlg.rq_c.swath_height = 1 << log2_swath_height_c; + + DTRACE("DLG: %s: req128_l = %0d", __func__, req128_l); + DTRACE("DLG: %s: req128_c = %0d", __func__, req128_c); + DTRACE("DLG: %s: full_swath_bytes_packed_l = %0d", __func__, full_swath_bytes_packed_l); + DTRACE("DLG: %s: full_swath_bytes_packed_c = %0d", __func__, full_swath_bytes_packed_c); +} + +/* Need refactor. */ +void dml_rq_dlg_get_row_heights( + struct display_mode_lib *mode_lib, + unsigned int *o_dpte_row_height, + unsigned int *o_meta_row_height, + unsigned int vp_width, + unsigned int data_pitch, + int source_format, + int tiling, + int macro_tile_size, + int source_scan, + int is_chroma) +{ + bool surf_linear = (tiling == dm_sw_linear); + bool surf_vert = (source_scan == dm_vert); + + unsigned int bytes_per_element = get_bytes_per_element( + (enum source_format_class) source_format, + is_chroma); + unsigned int log2_bytes_per_element = dml_log2(bytes_per_element); + unsigned int blk256_width = 0; + unsigned int blk256_height = 0; + + unsigned int log2_blk256_height; + unsigned int blk_bytes; + unsigned int log2_blk_bytes; + unsigned int log2_blk_height; + unsigned int log2_blk_width; + unsigned int log2_meta_req_bytes; + unsigned int log2_meta_req_height; + unsigned int log2_meta_req_width; + unsigned int log2_meta_row_height; + unsigned int log2_vmpg_bytes; + unsigned int dpte_buf_in_pte_reqs; + unsigned int log2_vmpg_height; + unsigned int log2_vmpg_width; + unsigned int log2_dpte_req_height_ptes; + unsigned int log2_dpte_req_width_ptes; + unsigned int log2_dpte_req_height; + unsigned int log2_dpte_req_width; + unsigned int log2_dpte_row_height_linear; + unsigned int log2_dpte_row_height; + unsigned int dpte_req_width; + + if (surf_linear) { + blk256_width = 256; + blk256_height = 1; + } else { + get_blk256_size(&blk256_width, &blk256_height, bytes_per_element); + } + + log2_blk256_height = dml_log2((double) blk256_height); + blk_bytes = surf_linear ? + 256 : get_blk_size_bytes((enum source_macro_tile_size) macro_tile_size); + log2_blk_bytes = dml_log2((double) blk_bytes); + log2_blk_height = 0; + log2_blk_width = 0; + + /* remember log rule + * "+" in log is multiply + * "-" in log is divide + * "/2" is like square root + * blk is vertical biased + */ + if (tiling != dm_sw_linear) + log2_blk_height = log2_blk256_height + + dml_ceil((double) (log2_blk_bytes - 8) / 2.0); + else + log2_blk_height = 0; /* blk height of 1 */ + + log2_blk_width = log2_blk_bytes - log2_bytes_per_element - log2_blk_height; + + /* ------- */ + /* meta */ + /* ------- */ + log2_meta_req_bytes = 6; /* meta request is 64b and is 8x8byte meta element */ + + /* each 64b meta request for dcn is 8x8 meta elements and + * a meta element covers one 256b block of the the data surface. + */ + log2_meta_req_height = log2_blk256_height + 3; /* meta req is 8x8 */ + log2_meta_req_width = log2_meta_req_bytes + 8 - log2_bytes_per_element + - log2_meta_req_height; + log2_meta_row_height = 0; + + /* the dimensions of a meta row are meta_row_width x meta_row_height in elements. + * calculate upper bound of the meta_row_width + */ + if (!surf_vert) + log2_meta_row_height = log2_meta_req_height; + else + log2_meta_row_height = log2_meta_req_width; + + *o_meta_row_height = 1 << log2_meta_row_height; + + /* ------ */ + /* dpte */ + /* ------ */ + log2_vmpg_bytes = dml_log2(mode_lib->soc.vmm_page_size_bytes); + dpte_buf_in_pte_reqs = mode_lib->ip.dpte_buffer_size_in_pte_reqs; + + log2_vmpg_height = 0; + log2_vmpg_width = 0; + log2_dpte_req_height_ptes = 0; + log2_dpte_req_width_ptes = 0; + log2_dpte_req_height = 0; + log2_dpte_req_width = 0; + log2_dpte_row_height_linear = 0; + log2_dpte_row_height = 0; + dpte_req_width = 0; /* 64b dpte req width in data element */ + + if (surf_linear) { + log2_vmpg_height = 0; /* one line high */ + } else { + log2_vmpg_height = (log2_vmpg_bytes - 8) / 2 + log2_blk256_height; + } + log2_vmpg_width = log2_vmpg_bytes - log2_bytes_per_element - log2_vmpg_height; + + /* only 3 possible shapes for dpte request in dimensions of ptes: 8x1, 4x2, 2x4. */ + if (log2_blk_bytes <= log2_vmpg_bytes) + log2_dpte_req_height_ptes = 0; + else if (log2_blk_height - log2_vmpg_height >= 2) + log2_dpte_req_height_ptes = 2; + else + log2_dpte_req_height_ptes = log2_blk_height - log2_vmpg_height; + log2_dpte_req_width_ptes = 3 - log2_dpte_req_height_ptes; + + ASSERT((log2_dpte_req_width_ptes == 3 && log2_dpte_req_height_ptes == 0) || /* 8x1 */ + (log2_dpte_req_width_ptes == 2 && log2_dpte_req_height_ptes == 1) || /* 4x2 */ + (log2_dpte_req_width_ptes == 1 && log2_dpte_req_height_ptes == 2)); /* 2x4 */ + + /* the dpte request dimensions in data elements is dpte_req_width x dpte_req_height + * log2_wmpg_width is how much 1 pte represent, now trying to calculate how much 64b pte req represent + */ + log2_dpte_req_height = log2_vmpg_height + log2_dpte_req_height_ptes; + log2_dpte_req_width = log2_vmpg_width + log2_dpte_req_width_ptes; + dpte_req_width = 1 << log2_dpte_req_width; + + /* calculate pitch dpte row buffer can hold + * round the result down to a power of two. + */ + if (surf_linear) { + log2_dpte_row_height_linear = dml_floor( + dml_log2(dpte_buf_in_pte_reqs * dpte_req_width / data_pitch)); + + ASSERT(log2_dpte_row_height_linear >= 3); + + if (log2_dpte_row_height_linear > 7) + log2_dpte_row_height_linear = 7; + + log2_dpte_row_height = log2_dpte_row_height_linear; + } else { + /* the upper bound of the dpte_row_width without dependency on viewport position follows. */ + if (!surf_vert) { + log2_dpte_row_height = log2_dpte_req_height; + } else { + log2_dpte_row_height = + (log2_blk_width < log2_dpte_req_width) ? + log2_blk_width : log2_dpte_req_width; + } + } + + /* From programming guide: + * There is a special case of saving only half of ptes returned due to buffer space limits. + * this case applies to 4 and 8bpe in horizontal access of a vp_width greater than 2560+16 + * when the pte request is 2x4 ptes (which happens when vmpg_bytes =4kb and tile blk_bytes >=64kb). + */ + if (!surf_vert && vp_width > (2560 + 16) && bytes_per_element >= 4 && log2_vmpg_bytes == 12 + && log2_blk_bytes >= 16) { + log2_dpte_row_height = log2_dpte_row_height - 1; /*half of the full height */ + } + + *o_dpte_row_height = 1 << log2_dpte_row_height; +} + +static void get_surf_rq_param( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_data_rq_sizing_params_st *rq_sizing_param, + struct _vcs_dpi_display_data_rq_dlg_params_st *rq_dlg_param, + struct _vcs_dpi_display_data_rq_misc_params_st *rq_misc_param, + const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param, + bool is_chroma) +{ + bool mode_422 = 0; + unsigned int vp_width = 0; + unsigned int vp_height = 0; + unsigned int data_pitch = 0; + unsigned int meta_pitch = 0; + unsigned int ppe = mode_422 ? 2 : 1; + bool surf_linear; + bool surf_vert; + unsigned int bytes_per_element; + unsigned int log2_bytes_per_element; + unsigned int blk256_width; + unsigned int blk256_height; + unsigned int log2_blk256_width; + unsigned int log2_blk256_height; + unsigned int blk_bytes; + unsigned int log2_blk_bytes; + unsigned int log2_blk_height; + unsigned int log2_blk_width; + unsigned int log2_meta_req_bytes; + unsigned int log2_meta_req_height; + unsigned int log2_meta_req_width; + unsigned int meta_req_width; + unsigned int meta_req_height; + unsigned int log2_meta_row_height; + unsigned int meta_row_width_ub; + unsigned int log2_meta_chunk_bytes; + unsigned int log2_meta_chunk_height; + unsigned int log2_meta_chunk_width; + unsigned int log2_min_meta_chunk_bytes; + unsigned int min_meta_chunk_width; + unsigned int meta_chunk_width; + unsigned int meta_chunk_per_row_int; + unsigned int meta_row_remainder; + unsigned int meta_chunk_threshold; + unsigned int meta_blk_bytes; + unsigned int meta_blk_height; + unsigned int meta_blk_width; + unsigned int meta_surface_bytes; + unsigned int vmpg_bytes; + unsigned int meta_pte_req_per_frame_ub; + unsigned int meta_pte_bytes_per_frame_ub; + unsigned int log2_vmpg_bytes; + unsigned int dpte_buf_in_pte_reqs; + unsigned int log2_vmpg_height; + unsigned int log2_vmpg_width; + unsigned int log2_dpte_req_height_ptes; + unsigned int log2_dpte_req_width_ptes; + unsigned int log2_dpte_req_height; + unsigned int log2_dpte_req_width; + unsigned int log2_dpte_row_height_linear; + unsigned int log2_dpte_row_height; + unsigned int log2_dpte_group_width; + unsigned int dpte_row_width_ub; + unsigned int dpte_row_height; + unsigned int dpte_req_height; + unsigned int dpte_req_width; + unsigned int dpte_group_width; + unsigned int log2_dpte_group_bytes; + unsigned int log2_dpte_group_length; + unsigned int func_meta_row_height, func_dpte_row_height; + + /* FIXME check if ppe apply for both luma and chroma in 422 case */ + if (is_chroma) { + vp_width = pipe_src_param.viewport_width_c / ppe; + vp_height = pipe_src_param.viewport_height_c; + data_pitch = pipe_src_param.data_pitch_c; + meta_pitch = pipe_src_param.meta_pitch_c; + } else { + vp_width = pipe_src_param.viewport_width / ppe; + vp_height = pipe_src_param.viewport_height; + data_pitch = pipe_src_param.data_pitch; + meta_pitch = pipe_src_param.meta_pitch; + } + + rq_sizing_param->chunk_bytes = 8192; + + if (rq_sizing_param->chunk_bytes == 64 * 1024) + rq_sizing_param->min_chunk_bytes = 0; + else + rq_sizing_param->min_chunk_bytes = 1024; + + rq_sizing_param->meta_chunk_bytes = 2048; + rq_sizing_param->min_meta_chunk_bytes = 256; + + rq_sizing_param->mpte_group_bytes = 2048; + + surf_linear = (pipe_src_param.sw_mode == dm_sw_linear); + surf_vert = (pipe_src_param.source_scan == dm_vert); + + bytes_per_element = get_bytes_per_element( + (enum source_format_class) pipe_src_param.source_format, + is_chroma); + log2_bytes_per_element = dml_log2(bytes_per_element); + blk256_width = 0; + blk256_height = 0; + + if (surf_linear) { + blk256_width = 256 / bytes_per_element; + blk256_height = 1; + } else { + get_blk256_size(&blk256_width, &blk256_height, bytes_per_element); + } + + DTRACE("DLG: %s: surf_linear = %d", __func__, surf_linear); + DTRACE("DLG: %s: surf_vert = %d", __func__, surf_vert); + DTRACE("DLG: %s: blk256_width = %d", __func__, blk256_width); + DTRACE("DLG: %s: blk256_height = %d", __func__, blk256_height); + + log2_blk256_width = dml_log2((double) blk256_width); + log2_blk256_height = dml_log2((double) blk256_height); + blk_bytes = + surf_linear ? 256 : get_blk_size_bytes( + (enum source_macro_tile_size) pipe_src_param.macro_tile_size); + log2_blk_bytes = dml_log2((double) blk_bytes); + log2_blk_height = 0; + log2_blk_width = 0; + + /* remember log rule + * "+" in log is multiply + * "-" in log is divide + * "/2" is like square root + * blk is vertical biased + */ + if (pipe_src_param.sw_mode != dm_sw_linear) + log2_blk_height = log2_blk256_height + + dml_ceil((double) (log2_blk_bytes - 8) / 2.0); + else + log2_blk_height = 0; /* blk height of 1 */ + + log2_blk_width = log2_blk_bytes - log2_bytes_per_element - log2_blk_height; + + if (!surf_vert) { + rq_dlg_param->swath_width_ub = dml_round_to_multiple(vp_width - 1, blk256_width, 1) + + blk256_width; + rq_dlg_param->req_per_swath_ub = rq_dlg_param->swath_width_ub >> log2_blk256_width; + } else { + rq_dlg_param->swath_width_ub = dml_round_to_multiple( + vp_height - 1, + blk256_height, + 1) + blk256_height; + rq_dlg_param->req_per_swath_ub = rq_dlg_param->swath_width_ub >> log2_blk256_height; + } + + if (!surf_vert) + rq_misc_param->full_swath_bytes = rq_dlg_param->swath_width_ub * blk256_height + * bytes_per_element; + else + rq_misc_param->full_swath_bytes = rq_dlg_param->swath_width_ub * blk256_width + * bytes_per_element; + + rq_misc_param->blk256_height = blk256_height; + rq_misc_param->blk256_width = blk256_width; + + /* ------- */ + /* meta */ + /* ------- */ + log2_meta_req_bytes = 6; /* meta request is 64b and is 8x8byte meta element */ + + /* each 64b meta request for dcn is 8x8 meta elements and + * a meta element covers one 256b block of the the data surface. + */ + log2_meta_req_height = log2_blk256_height + 3; /* meta req is 8x8 byte, each byte represent 1 blk256 */ + log2_meta_req_width = log2_meta_req_bytes + 8 - log2_bytes_per_element + - log2_meta_req_height; + meta_req_width = 1 << log2_meta_req_width; + meta_req_height = 1 << log2_meta_req_height; + log2_meta_row_height = 0; + meta_row_width_ub = 0; + + /* the dimensions of a meta row are meta_row_width x meta_row_height in elements. + * calculate upper bound of the meta_row_width + */ + if (!surf_vert) { + log2_meta_row_height = log2_meta_req_height; + meta_row_width_ub = dml_round_to_multiple(vp_width - 1, meta_req_width, 1) + + meta_req_width; + rq_dlg_param->meta_req_per_row_ub = meta_row_width_ub / meta_req_width; + } else { + log2_meta_row_height = log2_meta_req_width; + meta_row_width_ub = dml_round_to_multiple(vp_height - 1, meta_req_height, 1) + + meta_req_height; + rq_dlg_param->meta_req_per_row_ub = meta_row_width_ub / meta_req_height; + } + rq_dlg_param->meta_bytes_per_row_ub = rq_dlg_param->meta_req_per_row_ub * 64; + + log2_meta_chunk_bytes = dml_log2(rq_sizing_param->meta_chunk_bytes); + log2_meta_chunk_height = log2_meta_row_height; + + /*full sized meta chunk width in unit of data elements */ + log2_meta_chunk_width = log2_meta_chunk_bytes + 8 - log2_bytes_per_element + - log2_meta_chunk_height; + log2_min_meta_chunk_bytes = dml_log2(rq_sizing_param->min_meta_chunk_bytes); + min_meta_chunk_width = 1 + << (log2_min_meta_chunk_bytes + 8 - log2_bytes_per_element + - log2_meta_chunk_height); + meta_chunk_width = 1 << log2_meta_chunk_width; + meta_chunk_per_row_int = (unsigned int) (meta_row_width_ub / meta_chunk_width); + meta_row_remainder = meta_row_width_ub % meta_chunk_width; + meta_chunk_threshold = 0; + meta_blk_bytes = 4096; + meta_blk_height = blk256_height * 64; + meta_blk_width = meta_blk_bytes * 256 / bytes_per_element / meta_blk_height; + meta_surface_bytes = meta_pitch + * (dml_round_to_multiple(vp_height - 1, meta_blk_height, 1) + + meta_blk_height) * bytes_per_element / 256; + vmpg_bytes = mode_lib->soc.vmm_page_size_bytes; + meta_pte_req_per_frame_ub = (dml_round_to_multiple( + meta_surface_bytes - vmpg_bytes, + 8 * vmpg_bytes, + 1) + 8 * vmpg_bytes) / (8 * vmpg_bytes); + meta_pte_bytes_per_frame_ub = meta_pte_req_per_frame_ub * 64; /*64B mpte request */ + rq_dlg_param->meta_pte_bytes_per_frame_ub = meta_pte_bytes_per_frame_ub; + + DTRACE("DLG: %s: meta_blk_height = %d", __func__, meta_blk_height); + DTRACE("DLG: %s: meta_blk_width = %d", __func__, meta_blk_width); + DTRACE("DLG: %s: meta_surface_bytes = %d", __func__, meta_surface_bytes); + DTRACE("DLG: %s: meta_pte_req_per_frame_ub = %d", __func__, meta_pte_req_per_frame_ub); + DTRACE("DLG: %s: meta_pte_bytes_per_frame_ub = %d", __func__, meta_pte_bytes_per_frame_ub); + + if (!surf_vert) + meta_chunk_threshold = 2 * min_meta_chunk_width - meta_req_width; + else + meta_chunk_threshold = 2 * min_meta_chunk_width - meta_req_height; + + if (meta_row_remainder <= meta_chunk_threshold) + rq_dlg_param->meta_chunks_per_row_ub = meta_chunk_per_row_int + 1; + else + rq_dlg_param->meta_chunks_per_row_ub = meta_chunk_per_row_int + 2; + + rq_dlg_param->meta_row_height = 1 << log2_meta_row_height; + + /* ------ */ + /* dpte */ + /* ------ */ + log2_vmpg_bytes = dml_log2(mode_lib->soc.vmm_page_size_bytes); + dpte_buf_in_pte_reqs = mode_lib->ip.dpte_buffer_size_in_pte_reqs; + + log2_vmpg_height = 0; + log2_vmpg_width = 0; + log2_dpte_req_height_ptes = 0; + log2_dpte_req_width_ptes = 0; + log2_dpte_req_height = 0; + log2_dpte_req_width = 0; + log2_dpte_row_height_linear = 0; + log2_dpte_row_height = 0; + log2_dpte_group_width = 0; + dpte_row_width_ub = 0; + dpte_row_height = 0; + dpte_req_height = 0; /* 64b dpte req height in data element */ + dpte_req_width = 0; /* 64b dpte req width in data element */ + dpte_group_width = 0; + log2_dpte_group_bytes = 0; + log2_dpte_group_length = 0; + + if (surf_linear) { + log2_vmpg_height = 0; /* one line high */ + } else { + log2_vmpg_height = (log2_vmpg_bytes - 8) / 2 + log2_blk256_height; + } + log2_vmpg_width = log2_vmpg_bytes - log2_bytes_per_element - log2_vmpg_height; + + /* only 3 possible shapes for dpte request in dimensions of ptes: 8x1, 4x2, 2x4. */ + if (log2_blk_bytes <= log2_vmpg_bytes) + log2_dpte_req_height_ptes = 0; + else if (log2_blk_height - log2_vmpg_height >= 2) + log2_dpte_req_height_ptes = 2; + else + log2_dpte_req_height_ptes = log2_blk_height - log2_vmpg_height; + log2_dpte_req_width_ptes = 3 - log2_dpte_req_height_ptes; + + /* Ensure we only have the 3 shapes */ + ASSERT((log2_dpte_req_width_ptes == 3 && log2_dpte_req_height_ptes == 0) || /* 8x1 */ + (log2_dpte_req_width_ptes == 2 && log2_dpte_req_height_ptes == 1) || /* 4x2 */ + (log2_dpte_req_width_ptes == 1 && log2_dpte_req_height_ptes == 2)); /* 2x4 */ + + /* The dpte request dimensions in data elements is dpte_req_width x dpte_req_height + * log2_vmpg_width is how much 1 pte represent, now calculating how much a 64b pte req represent + * That depends on the pte shape (i.e. 8x1, 4x2, 2x4) + */ + log2_dpte_req_height = log2_vmpg_height + log2_dpte_req_height_ptes; + log2_dpte_req_width = log2_vmpg_width + log2_dpte_req_width_ptes; + dpte_req_height = 1 << log2_dpte_req_height; + dpte_req_width = 1 << log2_dpte_req_width; + + /* calculate pitch dpte row buffer can hold + * round the result down to a power of two. + */ + if (surf_linear) { + log2_dpte_row_height_linear = dml_floor( + dml_log2(dpte_buf_in_pte_reqs * dpte_req_width / data_pitch)); + + ASSERT(log2_dpte_row_height_linear >= 3); + + if (log2_dpte_row_height_linear > 7) + log2_dpte_row_height_linear = 7; + + log2_dpte_row_height = log2_dpte_row_height_linear; + rq_dlg_param->dpte_row_height = 1 << log2_dpte_row_height; + + /* For linear, the dpte row is pitch dependent and the pte requests wrap at the pitch boundary. + * the dpte_row_width_ub is the upper bound of data_pitch*dpte_row_height in elements with this unique buffering. + */ + dpte_row_width_ub = dml_round_to_multiple( + data_pitch * dpte_row_height - 1, + dpte_req_width, + 1) + dpte_req_width; + rq_dlg_param->dpte_req_per_row_ub = dpte_row_width_ub / dpte_req_width; + } else { + /* for tiled mode, row height is the same as req height and row store up to vp size upper bound */ + if (!surf_vert) { + log2_dpte_row_height = log2_dpte_req_height; + dpte_row_width_ub = dml_round_to_multiple(vp_width - 1, dpte_req_width, 1) + + dpte_req_width; + rq_dlg_param->dpte_req_per_row_ub = dpte_row_width_ub / dpte_req_width; + } else { + log2_dpte_row_height = + (log2_blk_width < log2_dpte_req_width) ? + log2_blk_width : log2_dpte_req_width; + dpte_row_width_ub = dml_round_to_multiple(vp_height - 1, dpte_req_height, 1) + + dpte_req_height; + rq_dlg_param->dpte_req_per_row_ub = dpte_row_width_ub / dpte_req_height; + } + rq_dlg_param->dpte_row_height = 1 << log2_dpte_row_height; + } + rq_dlg_param->dpte_bytes_per_row_ub = rq_dlg_param->dpte_req_per_row_ub * 64; + + /* From programming guide: + * There is a special case of saving only half of ptes returned due to buffer space limits. + * this case applies to 4 and 8bpe in horizontal access of a vp_width greater than 2560+16 + * when the pte request is 2x4 ptes (which happens when vmpg_bytes =4kb and tile blk_bytes >=64kb). + */ + if (!surf_vert && vp_width > (2560 + 16) && bytes_per_element >= 4 && log2_vmpg_bytes == 12 + && log2_blk_bytes >= 16) { + log2_dpte_row_height = log2_dpte_row_height - 1; /*half of the full height */ + rq_dlg_param->dpte_row_height = 1 << log2_dpte_row_height; + } + + /* the dpte_group_bytes is reduced for the specific case of vertical + * access of a tile surface that has dpte request of 8x1 ptes. + */ + if (!surf_linear & (log2_dpte_req_height_ptes == 0) & surf_vert) /*reduced, in this case, will have page fault within a group */ + rq_sizing_param->dpte_group_bytes = 512; + else + /*full size */ + rq_sizing_param->dpte_group_bytes = 2048; + + /*since pte request size is 64byte, the number of data pte requests per full sized group is as follows. */ + log2_dpte_group_bytes = dml_log2(rq_sizing_param->dpte_group_bytes); + log2_dpte_group_length = log2_dpte_group_bytes - 6; /*length in 64b requests */ + + /* full sized data pte group width in elements */ + if (!surf_vert) + log2_dpte_group_width = log2_dpte_group_length + log2_dpte_req_width; + else + log2_dpte_group_width = log2_dpte_group_length + log2_dpte_req_height; + + dpte_group_width = 1 << log2_dpte_group_width; + + /* since dpte groups are only aligned to dpte_req_width and not dpte_group_width, + * the upper bound for the dpte groups per row is as follows. + */ + rq_dlg_param->dpte_groups_per_row_ub = dml_ceil( + (double) dpte_row_width_ub / dpte_group_width); + + dml_rq_dlg_get_row_heights( + mode_lib, + &func_dpte_row_height, + &func_meta_row_height, + vp_width, + data_pitch, + pipe_src_param.source_format, + pipe_src_param.sw_mode, + pipe_src_param.macro_tile_size, + pipe_src_param.source_scan, + is_chroma); + + /* Just a check to make sure this function and the new one give the same + * result. The standalone get_row_heights() function is based off of the + * code in this function so the same changes need to be made to both. + */ + if (rq_dlg_param->meta_row_height != func_meta_row_height) { + DTRACE( + "MISMATCH: rq_dlg_param->meta_row_height = %d", + rq_dlg_param->meta_row_height); + DTRACE("MISMATCH: func_meta_row_height = %d", func_meta_row_height); + ASSERT(0); + } + + if (rq_dlg_param->dpte_row_height != func_dpte_row_height) { + DTRACE( + "MISMATCH: rq_dlg_param->dpte_row_height = %d", + rq_dlg_param->dpte_row_height); + DTRACE("MISMATCH: func_dpte_row_height = %d", func_dpte_row_height); + ASSERT(0); + } +} + +void dml_rq_dlg_get_rq_params( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_params_st *rq_param, + const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param) +{ + /* get param for luma surface */ + rq_param->yuv420 = pipe_src_param.source_format == dm_420_8 + || pipe_src_param.source_format == dm_420_10; + rq_param->yuv420_10bpc = pipe_src_param.source_format == dm_420_10; + + get_surf_rq_param( + mode_lib, + &(rq_param->sizing.rq_l), + &(rq_param->dlg.rq_l), + &(rq_param->misc.rq_l), + pipe_src_param, + 0); + + if (is_dual_plane((enum source_format_class) pipe_src_param.source_format)) { + /* get param for chroma surface */ + get_surf_rq_param( + mode_lib, + &(rq_param->sizing.rq_c), + &(rq_param->dlg.rq_c), + &(rq_param->misc.rq_c), + pipe_src_param, + 1); + } + + /* calculate how to split the det buffer space between luma and chroma */ + handle_det_buf_split(mode_lib, rq_param, pipe_src_param); + print__rq_params_st(mode_lib, *rq_param); +} + +void dml_rq_dlg_get_rq_reg( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_regs_st *rq_regs, + const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param) +{ + struct _vcs_dpi_display_rq_params_st rq_param = {0}; + + memset(rq_regs, 0, sizeof(*rq_regs)); + + dml_rq_dlg_get_rq_params(mode_lib, &rq_param, pipe_src_param); + extract_rq_regs(mode_lib, rq_regs, rq_param); + + print__rq_regs_st(mode_lib, *rq_regs); +} + +/* TODO: Need refactor, so this is used by dml_rq_dlg_get_dlg_params as well + * The problem is that there are some intermediate terms that would need by + * some dlg calculation (i.e. rest of prefetch and active prog guide calculation) + */ +void dml_rq_dlg_get_dlg_params_prefetch( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_dlg_prefetch_param_st *prefetch_param, + struct _vcs_dpi_display_rq_dlg_params_st rq_dlg_param, + struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param, + struct _vcs_dpi_display_e2e_pipe_params_st e2e_pipe_param, + const bool cstate_en, + const bool pstate_en, + const bool vm_en) +{ + /* Prefetch */ + unsigned int htotal = e2e_pipe_param.pipe.dest.htotal; + bool interlaced = e2e_pipe_param.pipe.dest.interlaced; + unsigned int min_vblank = mode_lib->ip.min_vblank_lines; + const double prefetch_xy_calc_in_dcfclk = 24.0; /* FIXME: ip_param */ + double min_dcfclk_mhz = dlg_sys_param.deepsleep_dcfclk_mhz; + double t_calc_us = prefetch_xy_calc_in_dcfclk / min_dcfclk_mhz; + + bool dcc_en = e2e_pipe_param.pipe.src.dcc; + bool dual_plane = is_dual_plane( + (enum source_format_class) e2e_pipe_param.pipe.src.source_format); + unsigned int bytes_per_element_l = get_bytes_per_element( + (enum source_format_class) e2e_pipe_param.pipe.src.source_format, + 0); + unsigned int bytes_per_element_c = get_bytes_per_element( + (enum source_format_class) e2e_pipe_param.pipe.src.source_format, + 1); + + double pclk_freq_in_mhz = e2e_pipe_param.pipe.dest.pixel_rate_mhz; + double dppclk_freq_in_mhz = e2e_pipe_param.clks_cfg.dppclk_mhz; + double dispclk_freq_in_mhz = e2e_pipe_param.clks_cfg.dispclk_mhz; + + double line_time_in_us = (htotal / pclk_freq_in_mhz); + double vinit_l = e2e_pipe_param.pipe.scale_ratio_depth.vinit; + double vinit_c = e2e_pipe_param.pipe.scale_ratio_depth.vinit_c; + double vinit_bot_l = e2e_pipe_param.pipe.scale_ratio_depth.vinit_bot; + double vinit_bot_c = e2e_pipe_param.pipe.scale_ratio_depth.vinit_bot_c; + + unsigned int swath_height_l = rq_dlg_param.rq_l.swath_height; + unsigned int swath_width_ub_l = rq_dlg_param.rq_l.swath_width_ub; + unsigned int dpte_bytes_per_row_ub_l = rq_dlg_param.rq_l.dpte_bytes_per_row_ub; + unsigned int meta_pte_bytes_per_frame_ub_l = rq_dlg_param.rq_l.meta_pte_bytes_per_frame_ub; + unsigned int meta_bytes_per_row_ub_l = rq_dlg_param.rq_l.meta_bytes_per_row_ub; + + unsigned int swath_height_c = rq_dlg_param.rq_c.swath_height; + unsigned int swath_width_ub_c = rq_dlg_param.rq_c.swath_width_ub; + unsigned int dpte_bytes_per_row_ub_c = rq_dlg_param.rq_c.dpte_bytes_per_row_ub; + unsigned int vupdate_offset = e2e_pipe_param.pipe.dest.vupdate_offset; + unsigned int vupdate_width = e2e_pipe_param.pipe.dest.vupdate_width; + unsigned int vready_offset = e2e_pipe_param.pipe.dest.vready_offset; + + const unsigned int dppclk_delay_subtotal = mode_lib->ip.dppclk_delay_subtotal; + const unsigned int dispclk_delay_subtotal = mode_lib->ip.dispclk_delay_subtotal; + unsigned int pixel_rate_delay_subtotal = dppclk_delay_subtotal * pclk_freq_in_mhz + / dppclk_freq_in_mhz + + dispclk_delay_subtotal * pclk_freq_in_mhz / dispclk_freq_in_mhz; + unsigned int dst_y_after_scaler = 0; + unsigned int dst_x_after_scaler = 0; + + unsigned int vstartup_start = e2e_pipe_param.pipe.dest.vstartup_start; + + double line_wait; + double line_o; + double line_setup; + double line_calc; + double dst_y_prefetch; + double t_pre_us; + int unsigned vm_bytes; + int unsigned meta_row_bytes; + int unsigned max_num_sw_l; + int unsigned max_num_sw_c; + int unsigned max_partial_sw_l; + int unsigned max_partial_sw_c; + + double max_vinit_l; + double max_vinit_c; + int unsigned lsw_l; + int unsigned lsw_c; + int unsigned sw_bytes_ub_l; + int unsigned sw_bytes_ub_c; + int unsigned sw_bytes; + int unsigned dpte_row_bytes; + + if (interlaced) + vstartup_start = vstartup_start / 2; + + if (vstartup_start >= min_vblank) { + min_vblank = vstartup_start + 1; + DTRACE( + "WARNING_DLG: %s: vstartup_start=%d should be less than min_vblank=%d", + __func__, + vstartup_start, + min_vblank); + } + + if (e2e_pipe_param.pipe.src.is_hsplit) + dst_x_after_scaler = pixel_rate_delay_subtotal + + e2e_pipe_param.pipe.dest.recout_width; + else + dst_x_after_scaler = pixel_rate_delay_subtotal; + + if (e2e_pipe_param.dout.output_format == dm_420) + dst_y_after_scaler = 1; + else + dst_y_after_scaler = 0; + + if (dst_x_after_scaler >= htotal) { + dst_x_after_scaler = dst_x_after_scaler - htotal; + dst_y_after_scaler = dst_y_after_scaler + 1; + } + + DTRACE("DLG: %s: htotal = %d", __func__, htotal); + DTRACE( + "DLG: %s: pixel_rate_delay_subtotal = %d", + __func__, + pixel_rate_delay_subtotal); + DTRACE("DLG: %s: dst_x_after_scaler = %d", __func__, dst_x_after_scaler); + DTRACE("DLG: %s: dst_y_after_scaler = %d", __func__, dst_y_after_scaler); + + line_wait = mode_lib->soc.urgent_latency_us; + if (cstate_en) + line_wait = dml_max(mode_lib->soc.sr_enter_plus_exit_time_us, line_wait); + if (pstate_en) + line_wait = dml_max( + mode_lib->soc.dram_clock_change_latency_us + + mode_lib->soc.urgent_latency_us, + line_wait); + line_wait = line_wait / line_time_in_us; + + line_o = (double) dst_y_after_scaler + dst_x_after_scaler / (double) htotal; + line_setup = (double) (vupdate_offset + vupdate_width + vready_offset) / (double) htotal; + line_calc = t_calc_us / line_time_in_us; + + DTRACE( + "DLG: %s: soc.sr_enter_plus_exit_time_us = %3.2f", + __func__, + (double) mode_lib->soc.sr_enter_plus_exit_time_us); + DTRACE( + "DLG: %s: soc.dram_clock_change_latency_us = %3.2f", + __func__, + (double) mode_lib->soc.dram_clock_change_latency_us); + + DTRACE("DLG: %s: urgent_latency_us = %3.2f", __func__, mode_lib->soc.urgent_latency_us); + DTRACE( + "DLG: %s: t_srx_delay_us = %3.2f", + __func__, + (double) dlg_sys_param.t_srx_delay_us); + DTRACE("DLG: %s: line_time_in_us = %3.2f", __func__, (double) line_time_in_us); + DTRACE("DLG: %s: vupdate_offset = %d", __func__, vupdate_offset); + DTRACE("DLG: %s: vupdate_width = %d", __func__, vupdate_width); + DTRACE("DLG: %s: vready_offset = %d", __func__, vready_offset); + DTRACE("DLG: %s: line_wait = %3.2f", __func__, line_wait); + DTRACE("DLG: %s: line_o = %3.2f", __func__, line_o); + DTRACE("DLG: %s: line_setup = %3.2f", __func__, line_setup); + DTRACE("DLG: %s: line_calc = %3.2f", __func__, line_calc); + + dst_y_prefetch = ((double) min_vblank - 1.0) + - (line_setup + line_calc + line_wait + line_o); + DTRACE("DLG: %s: dst_y_prefetch (before rnd) = %3.2f", __func__, dst_y_prefetch); + ASSERT(dst_y_prefetch >= 2.0); + + dst_y_prefetch = dml_floor(4.0 * (dst_y_prefetch + 0.125)) / 4; + DTRACE("DLG: %s: dst_y_prefetch (after rnd) = %3.2f", __func__, dst_y_prefetch); + + t_pre_us = dst_y_prefetch * line_time_in_us; + vm_bytes = 0; + meta_row_bytes = 0; + + if (dcc_en && vm_en) + vm_bytes = meta_pte_bytes_per_frame_ub_l; + if (dcc_en) + meta_row_bytes = meta_bytes_per_row_ub_l; + + max_num_sw_l = 0; + max_num_sw_c = 0; + max_partial_sw_l = 0; + max_partial_sw_c = 0; + + max_vinit_l = interlaced ? dml_max(vinit_l, vinit_bot_l) : vinit_l; + max_vinit_c = interlaced ? dml_max(vinit_c, vinit_bot_c) : vinit_c; + + get_swath_need(mode_lib, &max_num_sw_l, &max_partial_sw_l, swath_height_l, max_vinit_l); + if (dual_plane) + get_swath_need( + mode_lib, + &max_num_sw_c, + &max_partial_sw_c, + swath_height_c, + max_vinit_c); + + lsw_l = max_num_sw_l * swath_height_l + max_partial_sw_l; + lsw_c = max_num_sw_c * swath_height_c + max_partial_sw_c; + sw_bytes_ub_l = lsw_l * swath_width_ub_l * bytes_per_element_l; + sw_bytes_ub_c = lsw_c * swath_width_ub_c * bytes_per_element_c; + sw_bytes = 0; + dpte_row_bytes = 0; + + if (vm_en) { + if (dual_plane) + dpte_row_bytes = dpte_bytes_per_row_ub_l + dpte_bytes_per_row_ub_c; + else + dpte_row_bytes = dpte_bytes_per_row_ub_l; + } else { + dpte_row_bytes = 0; + } + + if (dual_plane) + sw_bytes = sw_bytes_ub_l + sw_bytes_ub_c; + else + sw_bytes = sw_bytes_ub_l; + + DTRACE("DLG: %s: sw_bytes_ub_l = %d", __func__, sw_bytes_ub_l); + DTRACE("DLG: %s: sw_bytes_ub_c = %d", __func__, sw_bytes_ub_c); + DTRACE("DLG: %s: sw_bytes = %d", __func__, sw_bytes); + DTRACE("DLG: %s: vm_bytes = %d", __func__, vm_bytes); + DTRACE("DLG: %s: meta_row_bytes = %d", __func__, meta_row_bytes); + DTRACE("DLG: %s: dpte_row_bytes = %d", __func__, dpte_row_bytes); + + prefetch_param->prefetch_bw = + (vm_bytes + 2 * dpte_row_bytes + 2 * meta_row_bytes + sw_bytes) / t_pre_us; + prefetch_param->flip_bytes = (vm_bytes + dpte_row_bytes + meta_row_bytes); +} + +/* Note: currently taken in as is. + * Nice to decouple code from hw register implement and extract code that are repeated for luma and chroma. + */ +void dml_rq_dlg_get_dlg_params( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_dlg_regs_st *disp_dlg_regs, + struct _vcs_dpi_display_ttu_regs_st *disp_ttu_regs, + const struct _vcs_dpi_display_rq_dlg_params_st rq_dlg_param, + const struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param, + const struct _vcs_dpi_display_e2e_pipe_params_st e2e_pipe_param, + const bool cstate_en, + const bool pstate_en, + const bool vm_en, + const bool iflip_en) +{ + /* Timing */ + unsigned int htotal = e2e_pipe_param.pipe.dest.htotal; + unsigned int hblank_end = e2e_pipe_param.pipe.dest.hblank_end; + unsigned int vblank_start = e2e_pipe_param.pipe.dest.vblank_start; + unsigned int vblank_end = e2e_pipe_param.pipe.dest.vblank_end; + bool interlaced = e2e_pipe_param.pipe.dest.interlaced; + unsigned int min_vblank = mode_lib->ip.min_vblank_lines; + + double pclk_freq_in_mhz = e2e_pipe_param.pipe.dest.pixel_rate_mhz; + double refclk_freq_in_mhz = e2e_pipe_param.clks_cfg.refclk_mhz; + double dppclk_freq_in_mhz = e2e_pipe_param.clks_cfg.dppclk_mhz; + double dispclk_freq_in_mhz = e2e_pipe_param.clks_cfg.dispclk_mhz; + + double ref_freq_to_pix_freq; + double prefetch_xy_calc_in_dcfclk; + double min_dcfclk_mhz; + double t_calc_us; + double min_ttu_vblank; + double min_dst_y_ttu_vblank; + int unsigned dlg_vblank_start; + bool dcc_en; + bool dual_plane; + bool mode_422; + unsigned int access_dir; + unsigned int bytes_per_element_l; + unsigned int bytes_per_element_c; + unsigned int vp_height_l; + unsigned int vp_width_l; + unsigned int vp_height_c; + unsigned int vp_width_c; + unsigned int htaps_l; + unsigned int htaps_c; + double hratios_l; + double hratios_c; + double vratio_l; + double vratio_c; + double line_time_in_us; + double vinit_l; + double vinit_c; + double vinit_bot_l; + double vinit_bot_c; + unsigned int swath_height_l; + unsigned int swath_width_ub_l; + unsigned int dpte_bytes_per_row_ub_l; + unsigned int dpte_groups_per_row_ub_l; + unsigned int meta_pte_bytes_per_frame_ub_l; + unsigned int meta_bytes_per_row_ub_l; + unsigned int swath_height_c; + unsigned int swath_width_ub_c; + unsigned int dpte_bytes_per_row_ub_c; + unsigned int dpte_groups_per_row_ub_c; + unsigned int meta_chunks_per_row_ub_l; + unsigned int vupdate_offset; + unsigned int vupdate_width; + unsigned int vready_offset; + unsigned int dppclk_delay_subtotal; + unsigned int dispclk_delay_subtotal; + unsigned int pixel_rate_delay_subtotal; + unsigned int vstartup_start; + unsigned int dst_x_after_scaler; + unsigned int dst_y_after_scaler; + double line_wait; + double line_o; + double line_setup; + double line_calc; + double dst_y_prefetch; + double t_pre_us; + int unsigned vm_bytes; + int unsigned meta_row_bytes; + int unsigned max_num_sw_l; + int unsigned max_num_sw_c; + int unsigned max_partial_sw_l; + int unsigned max_partial_sw_c; + double max_vinit_l; + double max_vinit_c; + int unsigned lsw_l; + int unsigned lsw_c; + int unsigned sw_bytes_ub_l; + int unsigned sw_bytes_ub_c; + int unsigned sw_bytes; + int unsigned dpte_row_bytes; + double prefetch_bw; + double flip_bw; + double t_vm_us; + double t_r0_us; + double dst_y_per_vm_vblank; + double dst_y_per_row_vblank; + double min_dst_y_per_vm_vblank; + double min_dst_y_per_row_vblank; + double lsw; + double vratio_pre_l; + double vratio_pre_c; + unsigned int req_per_swath_ub_l; + unsigned int req_per_swath_ub_c; + unsigned int meta_row_height_l; + unsigned int swath_width_pixels_ub_l; + unsigned int swath_width_pixels_ub_c; + unsigned int scaler_rec_in_width_l; + unsigned int scaler_rec_in_width_c; + unsigned int dpte_row_height_l; + unsigned int dpte_row_height_c; + double hscale_pixel_rate_l; + double hscale_pixel_rate_c; + double min_hratio_fact_l; + double min_hratio_fact_c; + double refcyc_per_line_delivery_pre_l; + double refcyc_per_line_delivery_pre_c; + double refcyc_per_line_delivery_l; + double refcyc_per_line_delivery_c; + double refcyc_per_req_delivery_pre_l; + double refcyc_per_req_delivery_pre_c; + double refcyc_per_req_delivery_l; + double refcyc_per_req_delivery_c; + double refcyc_per_req_delivery_pre_cur0; + double refcyc_per_req_delivery_cur0; + int unsigned full_recout_width; + double hratios_cur0; + unsigned int cur0_src_width; + enum cursor_bpp cur0_bpp; + unsigned int cur0_req_size; + unsigned int cur0_req_width; + double cur0_width_ub; + double cur0_req_per_width; + double hactive_cur0; + + memset(disp_dlg_regs, 0, sizeof(*disp_dlg_regs)); + memset(disp_ttu_regs, 0, sizeof(*disp_ttu_regs)); + + DTRACE("DLG: %s: cstate_en = %d", __func__, cstate_en); + DTRACE("DLG: %s: pstate_en = %d", __func__, pstate_en); + DTRACE("DLG: %s: vm_en = %d", __func__, vm_en); + DTRACE("DLG: %s: iflip_en = %d", __func__, iflip_en); + + /* ------------------------- */ + /* Section 1.5.2.1: OTG dependent Params */ + /* ------------------------- */ + DTRACE("DLG: %s: dppclk_freq_in_mhz = %3.2f", __func__, dppclk_freq_in_mhz); + DTRACE("DLG: %s: dispclk_freq_in_mhz = %3.2f", __func__, dispclk_freq_in_mhz); + DTRACE("DLG: %s: refclk_freq_in_mhz = %3.2f", __func__, refclk_freq_in_mhz); + DTRACE("DLG: %s: pclk_freq_in_mhz = %3.2f", __func__, pclk_freq_in_mhz); + DTRACE("DLG: %s: interlaced = %d", __func__, interlaced); + + ref_freq_to_pix_freq = refclk_freq_in_mhz / pclk_freq_in_mhz; + ASSERT(ref_freq_to_pix_freq < 4.0); + disp_dlg_regs->ref_freq_to_pix_freq = + (unsigned int) (ref_freq_to_pix_freq * dml_pow(2, 19)); + disp_dlg_regs->refcyc_per_htotal = (unsigned int) (ref_freq_to_pix_freq * (double) htotal + * dml_pow(2, 8)); + disp_dlg_regs->refcyc_h_blank_end = (unsigned int) ((double) hblank_end + * (double) ref_freq_to_pix_freq); + ASSERT(disp_dlg_regs->refcyc_h_blank_end < (unsigned int) dml_pow(2, 13)); + disp_dlg_regs->dlg_vblank_end = interlaced ? (vblank_end / 2) : vblank_end; /* 15 bits */ + + prefetch_xy_calc_in_dcfclk = 24.0; /* FIXME: ip_param */ + min_dcfclk_mhz = dlg_sys_param.deepsleep_dcfclk_mhz; + t_calc_us = prefetch_xy_calc_in_dcfclk / min_dcfclk_mhz; + min_ttu_vblank = dlg_sys_param.t_urg_wm_us; + if (cstate_en) + min_ttu_vblank = dml_max(dlg_sys_param.t_sr_wm_us, min_ttu_vblank); + if (pstate_en) + min_ttu_vblank = dml_max(dlg_sys_param.t_mclk_wm_us, min_ttu_vblank); + min_ttu_vblank = min_ttu_vblank + t_calc_us; + + min_dst_y_ttu_vblank = min_ttu_vblank * pclk_freq_in_mhz / (double) htotal; + dlg_vblank_start = interlaced ? (vblank_start / 2) : vblank_start; + + disp_dlg_regs->min_dst_y_next_start = (unsigned int) (((double) dlg_vblank_start + + min_dst_y_ttu_vblank) * dml_pow(2, 2)); + ASSERT(disp_dlg_regs->min_dst_y_next_start < (unsigned int) dml_pow(2, 18)); + + DTRACE("DLG: %s: min_dcfclk_mhz = %3.2f", __func__, min_dcfclk_mhz); + DTRACE("DLG: %s: min_ttu_vblank = %3.2f", __func__, min_ttu_vblank); + DTRACE( + "DLG: %s: min_dst_y_ttu_vblank = %3.2f", + __func__, + min_dst_y_ttu_vblank); + DTRACE("DLG: %s: t_calc_us = %3.2f", __func__, t_calc_us); + DTRACE( + "DLG: %s: disp_dlg_regs->min_dst_y_next_start = 0x%0x", + __func__, + disp_dlg_regs->min_dst_y_next_start); + DTRACE( + "DLG: %s: ref_freq_to_pix_freq = %3.2f", + __func__, + ref_freq_to_pix_freq); + + /* ------------------------- */ + /* Section 1.5.2.2: Prefetch, Active and TTU */ + /* ------------------------- */ + /* Prefetch Calc */ + /* Source */ + dcc_en = e2e_pipe_param.pipe.src.dcc; + dual_plane = is_dual_plane( + (enum source_format_class) e2e_pipe_param.pipe.src.source_format); + mode_422 = 0; /* FIXME */ + access_dir = (e2e_pipe_param.pipe.src.source_scan == dm_vert); /* vp access direction: horizontal or vertical accessed */ + bytes_per_element_l = get_bytes_per_element( + (enum source_format_class) e2e_pipe_param.pipe.src.source_format, + 0); + bytes_per_element_c = get_bytes_per_element( + (enum source_format_class) e2e_pipe_param.pipe.src.source_format, + 1); + vp_height_l = e2e_pipe_param.pipe.src.viewport_height; + vp_width_l = e2e_pipe_param.pipe.src.viewport_width; + vp_height_c = e2e_pipe_param.pipe.src.viewport_height_c; + vp_width_c = e2e_pipe_param.pipe.src.viewport_width_c; + + /* Scaling */ + htaps_l = e2e_pipe_param.pipe.scale_taps.htaps; + htaps_c = e2e_pipe_param.pipe.scale_taps.htaps_c; + hratios_l = e2e_pipe_param.pipe.scale_ratio_depth.hscl_ratio; + hratios_c = e2e_pipe_param.pipe.scale_ratio_depth.hscl_ratio_c; + vratio_l = e2e_pipe_param.pipe.scale_ratio_depth.vscl_ratio; + vratio_c = e2e_pipe_param.pipe.scale_ratio_depth.vscl_ratio_c; + + line_time_in_us = (htotal / pclk_freq_in_mhz); + vinit_l = e2e_pipe_param.pipe.scale_ratio_depth.vinit; + vinit_c = e2e_pipe_param.pipe.scale_ratio_depth.vinit_c; + vinit_bot_l = e2e_pipe_param.pipe.scale_ratio_depth.vinit_bot; + vinit_bot_c = e2e_pipe_param.pipe.scale_ratio_depth.vinit_bot_c; + + swath_height_l = rq_dlg_param.rq_l.swath_height; + swath_width_ub_l = rq_dlg_param.rq_l.swath_width_ub; + dpte_bytes_per_row_ub_l = rq_dlg_param.rq_l.dpte_bytes_per_row_ub; + dpte_groups_per_row_ub_l = rq_dlg_param.rq_l.dpte_groups_per_row_ub; + meta_pte_bytes_per_frame_ub_l = rq_dlg_param.rq_l.meta_pte_bytes_per_frame_ub; + meta_bytes_per_row_ub_l = rq_dlg_param.rq_l.meta_bytes_per_row_ub; + + swath_height_c = rq_dlg_param.rq_c.swath_height; + swath_width_ub_c = rq_dlg_param.rq_c.swath_width_ub; + dpte_bytes_per_row_ub_c = rq_dlg_param.rq_c.dpte_bytes_per_row_ub; + dpte_groups_per_row_ub_c = rq_dlg_param.rq_c.dpte_groups_per_row_ub; + + meta_chunks_per_row_ub_l = rq_dlg_param.rq_l.meta_chunks_per_row_ub; + vupdate_offset = e2e_pipe_param.pipe.dest.vupdate_offset; + vupdate_width = e2e_pipe_param.pipe.dest.vupdate_width; + vready_offset = e2e_pipe_param.pipe.dest.vready_offset; + + dppclk_delay_subtotal = mode_lib->ip.dppclk_delay_subtotal; + dispclk_delay_subtotal = mode_lib->ip.dispclk_delay_subtotal; + pixel_rate_delay_subtotal = dppclk_delay_subtotal * pclk_freq_in_mhz / dppclk_freq_in_mhz + + dispclk_delay_subtotal * pclk_freq_in_mhz / dispclk_freq_in_mhz; + + vstartup_start = e2e_pipe_param.pipe.dest.vstartup_start; + + if (interlaced) + vstartup_start = vstartup_start / 2; + + if (vstartup_start >= min_vblank) { + DTRACE( + "WARNING_DLG: %s: vblank_start=%d vblank_end=%d", + __func__, + vblank_start, + vblank_end); + DTRACE( + "WARNING_DLG: %s: vstartup_start=%d should be less than min_vblank=%d", + __func__, + vstartup_start, + min_vblank); + min_vblank = vstartup_start + 1; + DTRACE( + "WARNING_DLG: %s: vstartup_start=%d should be less than min_vblank=%d", + __func__, + vstartup_start, + min_vblank); + } + + dst_x_after_scaler = 0; + dst_y_after_scaler = 0; + + if (e2e_pipe_param.pipe.src.is_hsplit) + dst_x_after_scaler = pixel_rate_delay_subtotal + + e2e_pipe_param.pipe.dest.recout_width; + else + dst_x_after_scaler = pixel_rate_delay_subtotal; + + if (e2e_pipe_param.dout.output_format == dm_420) + dst_y_after_scaler = 1; + else + dst_y_after_scaler = 0; + + if (dst_x_after_scaler >= htotal) { + dst_x_after_scaler = dst_x_after_scaler - htotal; + dst_y_after_scaler = dst_y_after_scaler + 1; + } + + DTRACE("DLG: %s: htotal = %d", __func__, htotal); + DTRACE( + "DLG: %s: pixel_rate_delay_subtotal = %d", + __func__, + pixel_rate_delay_subtotal); + DTRACE("DLG: %s: dst_x_after_scaler = %d", __func__, dst_x_after_scaler); + DTRACE("DLG: %s: dst_y_after_scaler = %d", __func__, dst_y_after_scaler); + + line_wait = mode_lib->soc.urgent_latency_us; + if (cstate_en) + line_wait = dml_max(mode_lib->soc.sr_enter_plus_exit_time_us, line_wait); + if (pstate_en) + line_wait = dml_max( + mode_lib->soc.dram_clock_change_latency_us + + mode_lib->soc.urgent_latency_us, + line_wait); + line_wait = line_wait / line_time_in_us; + + line_o = (double) dst_y_after_scaler + dst_x_after_scaler / (double) htotal; + line_setup = (double) (vupdate_offset + vupdate_width + vready_offset) / (double) htotal; + line_calc = t_calc_us / line_time_in_us; + + DTRACE( + "DLG: %s: soc.sr_enter_plus_exit_time_us = %3.2f", + __func__, + (double) mode_lib->soc.sr_enter_plus_exit_time_us); + DTRACE( + "DLG: %s: soc.dram_clock_change_latency_us = %3.2f", + __func__, + (double) mode_lib->soc.dram_clock_change_latency_us); + DTRACE( + "DLG: %s: soc.urgent_latency_us = %3.2f", + __func__, + mode_lib->soc.urgent_latency_us); + + DTRACE("DLG: %s: swath_height_l = %d", __func__, swath_height_l); + if (dual_plane) + DTRACE("DLG: %s: swath_height_c = %d", __func__, swath_height_c); + + DTRACE( + "DLG: %s: t_srx_delay_us = %3.2f", + __func__, + (double) dlg_sys_param.t_srx_delay_us); + DTRACE("DLG: %s: line_time_in_us = %3.2f", __func__, (double) line_time_in_us); + DTRACE("DLG: %s: vupdate_offset = %d", __func__, vupdate_offset); + DTRACE("DLG: %s: vupdate_width = %d", __func__, vupdate_width); + DTRACE("DLG: %s: vready_offset = %d", __func__, vready_offset); + DTRACE("DLG: %s: line_time_in_us = %3.2f", __func__, line_time_in_us); + DTRACE("DLG: %s: line_wait = %3.2f", __func__, line_wait); + DTRACE("DLG: %s: line_o = %3.2f", __func__, line_o); + DTRACE("DLG: %s: line_setup = %3.2f", __func__, line_setup); + DTRACE("DLG: %s: line_calc = %3.2f", __func__, line_calc); + + dst_y_prefetch = ((double) min_vblank - 1.0) + - (line_setup + line_calc + line_wait + line_o); + DTRACE("DLG: %s: dst_y_prefetch (before rnd) = %3.2f", __func__, dst_y_prefetch); + ASSERT(dst_y_prefetch >= 2.0); + + dst_y_prefetch = dml_floor(4.0 * (dst_y_prefetch + 0.125)) / 4; + DTRACE("DLG: %s: dst_y_prefetch (after rnd) = %3.2f", __func__, dst_y_prefetch); + + t_pre_us = dst_y_prefetch * line_time_in_us; + vm_bytes = 0; + meta_row_bytes = 0; + + if (dcc_en && vm_en) + vm_bytes = meta_pte_bytes_per_frame_ub_l; + if (dcc_en) + meta_row_bytes = meta_bytes_per_row_ub_l; + + max_num_sw_l = 0; + max_num_sw_c = 0; + max_partial_sw_l = 0; + max_partial_sw_c = 0; + + max_vinit_l = interlaced ? dml_max(vinit_l, vinit_bot_l) : vinit_l; + max_vinit_c = interlaced ? dml_max(vinit_c, vinit_bot_c) : vinit_c; + + get_swath_need(mode_lib, &max_num_sw_l, &max_partial_sw_l, swath_height_l, max_vinit_l); + if (dual_plane) + get_swath_need( + mode_lib, + &max_num_sw_c, + &max_partial_sw_c, + swath_height_c, + max_vinit_c); + + lsw_l = max_num_sw_l * swath_height_l + max_partial_sw_l; + lsw_c = max_num_sw_c * swath_height_c + max_partial_sw_c; + sw_bytes_ub_l = lsw_l * swath_width_ub_l * bytes_per_element_l; + sw_bytes_ub_c = lsw_c * swath_width_ub_c * bytes_per_element_c; + sw_bytes = 0; + dpte_row_bytes = 0; + + if (vm_en) { + if (dual_plane) + dpte_row_bytes = dpte_bytes_per_row_ub_l + dpte_bytes_per_row_ub_c; + else + dpte_row_bytes = dpte_bytes_per_row_ub_l; + } else { + dpte_row_bytes = 0; + } + + if (dual_plane) + sw_bytes = sw_bytes_ub_l + sw_bytes_ub_c; + else + sw_bytes = sw_bytes_ub_l; + + DTRACE("DLG: %s: sw_bytes_ub_l = %d", __func__, sw_bytes_ub_l); + DTRACE("DLG: %s: sw_bytes_ub_c = %d", __func__, sw_bytes_ub_c); + DTRACE("DLG: %s: sw_bytes = %d", __func__, sw_bytes); + DTRACE("DLG: %s: vm_bytes = %d", __func__, vm_bytes); + DTRACE("DLG: %s: meta_row_bytes = %d", __func__, meta_row_bytes); + DTRACE("DLG: %s: dpte_row_bytes = %d", __func__, dpte_row_bytes); + + prefetch_bw = (vm_bytes + 2 * dpte_row_bytes + 2 * meta_row_bytes + sw_bytes) / t_pre_us; + flip_bw = ((vm_bytes + dpte_row_bytes + meta_row_bytes) * dlg_sys_param.total_flip_bw) + / (double) dlg_sys_param.total_flip_bytes; + t_vm_us = line_time_in_us / 4.0; + if (vm_en && dcc_en) { + t_vm_us = dml_max( + dlg_sys_param.t_extra_us, + dml_max((double) vm_bytes / prefetch_bw, t_vm_us)); + + if (iflip_en && !dual_plane) { + t_vm_us = dml_max(mode_lib->soc.urgent_latency_us, t_vm_us); + if (flip_bw > 0.) + t_vm_us = dml_max(vm_bytes / flip_bw, t_vm_us); + } + } + + t_r0_us = dml_max(dlg_sys_param.t_extra_us - t_vm_us, line_time_in_us - t_vm_us); + + if (vm_en || dcc_en) { + t_r0_us = dml_max( + (double) (dpte_row_bytes + meta_row_bytes) / prefetch_bw, + dlg_sys_param.t_extra_us); + t_r0_us = dml_max((double) (line_time_in_us - t_vm_us), t_r0_us); + + if (iflip_en && !dual_plane) { + t_r0_us = dml_max(mode_lib->soc.urgent_latency_us * 2.0, t_r0_us); + if (flip_bw > 0.) + t_r0_us = dml_max( + (dpte_row_bytes + meta_row_bytes) / flip_bw, + t_r0_us); + } + } + + disp_dlg_regs->dst_y_after_scaler = dst_y_after_scaler; /* in terms of line */ + disp_dlg_regs->refcyc_x_after_scaler = dst_x_after_scaler * ref_freq_to_pix_freq; /* in terms of refclk */ + ASSERT(disp_dlg_regs->refcyc_x_after_scaler < (unsigned int) dml_pow(2, 13)); + DTRACE( + "DLG: %s: disp_dlg_regs->dst_y_after_scaler = 0x%0x", + __func__, + disp_dlg_regs->dst_y_after_scaler); + DTRACE( + "DLG: %s: disp_dlg_regs->refcyc_x_after_scaler = 0x%0x", + __func__, + disp_dlg_regs->refcyc_x_after_scaler); + + disp_dlg_regs->dst_y_prefetch = (unsigned int) (dst_y_prefetch * dml_pow(2, 2)); + DTRACE( + "DLG: %s: disp_dlg_regs->dst_y_prefetch = %d", + __func__, + disp_dlg_regs->dst_y_prefetch); + + dst_y_per_vm_vblank = 0.0; + dst_y_per_row_vblank = 0.0; + + dst_y_per_vm_vblank = t_vm_us / line_time_in_us; + dst_y_per_vm_vblank = dml_floor(4.0 * (dst_y_per_vm_vblank + 0.125)) / 4.0; + disp_dlg_regs->dst_y_per_vm_vblank = (unsigned int) (dst_y_per_vm_vblank * dml_pow(2, 2)); + + dst_y_per_row_vblank = t_r0_us / line_time_in_us; + dst_y_per_row_vblank = dml_floor(4.0 * (dst_y_per_row_vblank + 0.125)) / 4.0; + disp_dlg_regs->dst_y_per_row_vblank = (unsigned int) (dst_y_per_row_vblank * dml_pow(2, 2)); + + DTRACE("DLG: %s: lsw_l = %d", __func__, lsw_l); + DTRACE("DLG: %s: lsw_c = %d", __func__, lsw_c); + DTRACE("DLG: %s: dpte_bytes_per_row_ub_l = %d", __func__, dpte_bytes_per_row_ub_l); + DTRACE("DLG: %s: dpte_bytes_per_row_ub_c = %d", __func__, dpte_bytes_per_row_ub_c); + + DTRACE("DLG: %s: prefetch_bw = %3.2f", __func__, prefetch_bw); + DTRACE("DLG: %s: flip_bw = %3.2f", __func__, flip_bw); + DTRACE("DLG: %s: t_pre_us = %3.2f", __func__, t_pre_us); + DTRACE("DLG: %s: t_vm_us = %3.2f", __func__, t_vm_us); + DTRACE("DLG: %s: t_r0_us = %3.2f", __func__, t_r0_us); + DTRACE("DLG: %s: dst_y_per_vm_vblank = %3.2f", __func__, dst_y_per_vm_vblank); + DTRACE("DLG: %s: dst_y_per_row_vblank = %3.2f", __func__, dst_y_per_row_vblank); + DTRACE("DLG: %s: dst_y_prefetch = %3.2f", __func__, dst_y_prefetch); + + min_dst_y_per_vm_vblank = 8.0; + min_dst_y_per_row_vblank = 16.0; + if (htotal <= 75) { + min_vblank = 300; + min_dst_y_per_vm_vblank = 100.0; + min_dst_y_per_row_vblank = 100.0; + } + + ASSERT(dst_y_per_vm_vblank < min_dst_y_per_vm_vblank); + ASSERT(dst_y_per_row_vblank < min_dst_y_per_row_vblank); + + ASSERT(dst_y_prefetch > (dst_y_per_vm_vblank + dst_y_per_row_vblank)); + lsw = dst_y_prefetch - (dst_y_per_vm_vblank + dst_y_per_row_vblank); + + DTRACE("DLG: %s: lsw = %3.2f", __func__, lsw); + + vratio_pre_l = get_vratio_pre( + mode_lib, + max_num_sw_l, + max_partial_sw_l, + swath_height_l, + max_vinit_l, + lsw); + vratio_pre_c = 1.0; + if (dual_plane) + vratio_pre_c = get_vratio_pre( + mode_lib, + max_num_sw_c, + max_partial_sw_c, + swath_height_c, + max_vinit_c, + lsw); + + DTRACE("DLG: %s: vratio_pre_l=%3.2f", __func__, vratio_pre_l); + DTRACE("DLG: %s: vratio_pre_c=%3.2f", __func__, vratio_pre_c); + + ASSERT(vratio_pre_l <= 4.0); + if (vratio_pre_l >= 4.0) + disp_dlg_regs->vratio_prefetch = (unsigned int) dml_pow(2, 21) - 1; + else + disp_dlg_regs->vratio_prefetch = (unsigned int) (vratio_pre_l * dml_pow(2, 19)); + + ASSERT(vratio_pre_c <= 4.0); + if (vratio_pre_c >= 4.0) + disp_dlg_regs->vratio_prefetch_c = (unsigned int) dml_pow(2, 21) - 1; + else + disp_dlg_regs->vratio_prefetch_c = (unsigned int) (vratio_pre_c * dml_pow(2, 19)); + + disp_dlg_regs->refcyc_per_pte_group_vblank_l = + (unsigned int) (dst_y_per_row_vblank * (double) htotal + * ref_freq_to_pix_freq / (double) dpte_groups_per_row_ub_l); + ASSERT(disp_dlg_regs->refcyc_per_pte_group_vblank_l < (unsigned int) dml_pow(2, 13)); + + disp_dlg_regs->refcyc_per_pte_group_vblank_c = + (unsigned int) (dst_y_per_row_vblank * (double) htotal + * ref_freq_to_pix_freq / (double) dpte_groups_per_row_ub_c); + ASSERT(disp_dlg_regs->refcyc_per_pte_group_vblank_c < (unsigned int) dml_pow(2, 13)); + + disp_dlg_regs->refcyc_per_meta_chunk_vblank_l = + (unsigned int) (dst_y_per_row_vblank * (double) htotal + * ref_freq_to_pix_freq / (double) meta_chunks_per_row_ub_l); + ASSERT(disp_dlg_regs->refcyc_per_meta_chunk_vblank_l < (unsigned int) dml_pow(2, 13)); + + disp_dlg_regs->refcyc_per_meta_chunk_vblank_c = + disp_dlg_regs->refcyc_per_meta_chunk_vblank_l;/* dcc for 4:2:0 is not supported in dcn1.0. assigned to be the same as _l for now */ + + /* Active */ + req_per_swath_ub_l = rq_dlg_param.rq_l.req_per_swath_ub; + req_per_swath_ub_c = rq_dlg_param.rq_c.req_per_swath_ub; + meta_row_height_l = rq_dlg_param.rq_l.meta_row_height; + swath_width_pixels_ub_l = 0; + swath_width_pixels_ub_c = 0; + scaler_rec_in_width_l = 0; + scaler_rec_in_width_c = 0; + dpte_row_height_l = rq_dlg_param.rq_l.dpte_row_height; + dpte_row_height_c = rq_dlg_param.rq_c.dpte_row_height; + + disp_dlg_regs->dst_y_per_pte_row_nom_l = (unsigned int) ((double) dpte_row_height_l + / (double) vratio_l * dml_pow(2, 2)); + ASSERT(disp_dlg_regs->dst_y_per_pte_row_nom_l < (unsigned int) dml_pow(2, 17)); + + disp_dlg_regs->dst_y_per_pte_row_nom_c = (unsigned int) ((double) dpte_row_height_c + / (double) vratio_c * dml_pow(2, 2)); + ASSERT(disp_dlg_regs->dst_y_per_pte_row_nom_c < (unsigned int) dml_pow(2, 17)); + + disp_dlg_regs->dst_y_per_meta_row_nom_l = (unsigned int) ((double) meta_row_height_l + / (double) vratio_l * dml_pow(2, 2)); + ASSERT(disp_dlg_regs->dst_y_per_meta_row_nom_l < (unsigned int) dml_pow(2, 17)); + + disp_dlg_regs->dst_y_per_meta_row_nom_c = disp_dlg_regs->dst_y_per_meta_row_nom_l; /* dcc for 4:2:0 is not supported in dcn1.0. assigned to be the same as _l for now */ + + disp_dlg_regs->refcyc_per_pte_group_nom_l = (unsigned int) ((double) dpte_row_height_l + / (double) vratio_l * (double) htotal * ref_freq_to_pix_freq + / (double) dpte_groups_per_row_ub_l); + if (disp_dlg_regs->refcyc_per_pte_group_nom_l >= (unsigned int) dml_pow(2, 23)) + disp_dlg_regs->refcyc_per_pte_group_nom_l = dml_pow(2, 23) - 1; + + disp_dlg_regs->refcyc_per_pte_group_nom_c = (unsigned int) ((double) dpte_row_height_c + / (double) vratio_c * (double) htotal * ref_freq_to_pix_freq + / (double) dpte_groups_per_row_ub_c); + if (disp_dlg_regs->refcyc_per_pte_group_nom_c >= (unsigned int) dml_pow(2, 23)) + disp_dlg_regs->refcyc_per_pte_group_nom_c = dml_pow(2, 23) - 1; + + disp_dlg_regs->refcyc_per_meta_chunk_nom_l = (unsigned int) ((double) meta_row_height_l + / (double) vratio_l * (double) htotal * ref_freq_to_pix_freq + / (double) meta_chunks_per_row_ub_l); + if (disp_dlg_regs->refcyc_per_meta_chunk_nom_l >= (unsigned int) dml_pow(2, 23)) + disp_dlg_regs->refcyc_per_meta_chunk_nom_l = dml_pow(2, 23) - 1; + + if (mode_422) { + swath_width_pixels_ub_l = swath_width_ub_l * 2; /* *2 for 2 pixel per element */ + swath_width_pixels_ub_c = swath_width_ub_c * 2; + } else { + swath_width_pixels_ub_l = swath_width_ub_l * 1; + swath_width_pixels_ub_c = swath_width_ub_c * 1; + } + + hscale_pixel_rate_l = 0.; + hscale_pixel_rate_c = 0.; + min_hratio_fact_l = 1.0; + min_hratio_fact_c = 1.0; + + if (htaps_l <= 1) + min_hratio_fact_l = 2.0; + else if (htaps_l <= 6) { + if ((hratios_l * 2.0) > 4.0) + min_hratio_fact_l = 4.0; + else + min_hratio_fact_l = hratios_l * 2.0; + } else { + if (hratios_l > 4.0) + min_hratio_fact_l = 4.0; + else + min_hratio_fact_l = hratios_l; + } + + hscale_pixel_rate_l = min_hratio_fact_l * dppclk_freq_in_mhz; + + if (htaps_c <= 1) + min_hratio_fact_c = 2.0; + else if (htaps_c <= 6) { + if ((hratios_c * 2.0) > 4.0) + min_hratio_fact_c = 4.0; + else + min_hratio_fact_c = hratios_c * 2.0; + } else { + if (hratios_c > 4.0) + min_hratio_fact_c = 4.0; + else + min_hratio_fact_c = hratios_c; + } + + hscale_pixel_rate_c = min_hratio_fact_c * dppclk_freq_in_mhz; + + refcyc_per_line_delivery_pre_l = 0.; + refcyc_per_line_delivery_pre_c = 0.; + refcyc_per_line_delivery_l = 0.; + refcyc_per_line_delivery_c = 0.; + + refcyc_per_req_delivery_pre_l = 0.; + refcyc_per_req_delivery_pre_c = 0.; + refcyc_per_req_delivery_l = 0.; + refcyc_per_req_delivery_c = 0.; + refcyc_per_req_delivery_pre_cur0 = 0.; + refcyc_per_req_delivery_cur0 = 0.; + + full_recout_width = 0; + if (e2e_pipe_param.pipe.src.is_hsplit) { + if (e2e_pipe_param.pipe.dest.full_recout_width == 0) { + DTRACE("DLG: %s: Warningfull_recout_width not set in hsplit mode", __func__); + full_recout_width = e2e_pipe_param.pipe.dest.recout_width * 2; /* assume half split for dcn1 */ + } else + full_recout_width = e2e_pipe_param.pipe.dest.full_recout_width; + } else + full_recout_width = e2e_pipe_param.pipe.dest.recout_width; + + refcyc_per_line_delivery_pre_l = get_refcyc_per_delivery( + mode_lib, + refclk_freq_in_mhz, + pclk_freq_in_mhz, + full_recout_width, + vratio_pre_l, + hscale_pixel_rate_l, + swath_width_pixels_ub_l, + 1); /* per line */ + + refcyc_per_line_delivery_l = get_refcyc_per_delivery( + mode_lib, + refclk_freq_in_mhz, + pclk_freq_in_mhz, + full_recout_width, + vratio_l, + hscale_pixel_rate_l, + swath_width_pixels_ub_l, + 1); /* per line */ + + DTRACE("DLG: %s: full_recout_width = %d", __func__, full_recout_width); + DTRACE("DLG: %s: hscale_pixel_rate_l = %3.2f", __func__, hscale_pixel_rate_l); + DTRACE( + "DLG: %s: refcyc_per_line_delivery_pre_l = %3.2f", + __func__, + refcyc_per_line_delivery_pre_l); + DTRACE( + "DLG: %s: refcyc_per_line_delivery_l = %3.2f", + __func__, + refcyc_per_line_delivery_l); + + disp_dlg_regs->refcyc_per_line_delivery_pre_l = (unsigned int) dml_floor( + refcyc_per_line_delivery_pre_l); + disp_dlg_regs->refcyc_per_line_delivery_l = (unsigned int) dml_floor( + refcyc_per_line_delivery_l); + ASSERT(disp_dlg_regs->refcyc_per_line_delivery_pre_l < (unsigned int) dml_pow(2, 13)); + ASSERT(disp_dlg_regs->refcyc_per_line_delivery_l < (unsigned int) dml_pow(2, 13)); + + if (dual_plane) { + refcyc_per_line_delivery_pre_c = get_refcyc_per_delivery( + mode_lib, + refclk_freq_in_mhz, + pclk_freq_in_mhz, + full_recout_width, + vratio_pre_c, + hscale_pixel_rate_c, + swath_width_pixels_ub_c, + 1); /* per line */ + + refcyc_per_line_delivery_c = get_refcyc_per_delivery( + mode_lib, + refclk_freq_in_mhz, + pclk_freq_in_mhz, + full_recout_width, + vratio_c, + hscale_pixel_rate_c, + swath_width_pixels_ub_c, + 1); /* per line */ + + DTRACE( + "DLG: %s: refcyc_per_line_delivery_pre_c = %3.2f", + __func__, + refcyc_per_line_delivery_pre_c); + DTRACE( + "DLG: %s: refcyc_per_line_delivery_c = %3.2f", + __func__, + refcyc_per_line_delivery_c); + + disp_dlg_regs->refcyc_per_line_delivery_pre_c = (unsigned int) dml_floor( + refcyc_per_line_delivery_pre_c); + disp_dlg_regs->refcyc_per_line_delivery_c = (unsigned int) dml_floor( + refcyc_per_line_delivery_c); + ASSERT(disp_dlg_regs->refcyc_per_line_delivery_pre_c < (unsigned int) dml_pow(2, 13)); ASSERT(disp_dlg_regs->refcyc_per_line_delivery_c < (unsigned int) dml_pow(2, 13)); + } + disp_dlg_regs->chunk_hdl_adjust_cur0 = 3; + + /* TTU - Luma / Chroma */ + if (access_dir) { /* vertical access */ + scaler_rec_in_width_l = vp_height_l; + scaler_rec_in_width_c = vp_height_c; + } else { + scaler_rec_in_width_l = vp_width_l; + scaler_rec_in_width_c = vp_width_c; + } + + refcyc_per_req_delivery_pre_l = get_refcyc_per_delivery( + mode_lib, + refclk_freq_in_mhz, + pclk_freq_in_mhz, + full_recout_width, + vratio_pre_l, + hscale_pixel_rate_l, + scaler_rec_in_width_l, + req_per_swath_ub_l); /* per req */ + refcyc_per_req_delivery_l = get_refcyc_per_delivery( + mode_lib, + refclk_freq_in_mhz, + pclk_freq_in_mhz, + full_recout_width, + vratio_l, + hscale_pixel_rate_l, + scaler_rec_in_width_l, + req_per_swath_ub_l); /* per req */ + + DTRACE( + "DLG: %s: refcyc_per_req_delivery_pre_l = %3.2f", + __func__, + refcyc_per_req_delivery_pre_l); + DTRACE( + "DLG: %s: refcyc_per_req_delivery_l = %3.2f", + __func__, + refcyc_per_req_delivery_l); + + disp_ttu_regs->refcyc_per_req_delivery_pre_l = (unsigned int) (refcyc_per_req_delivery_pre_l + * dml_pow(2, 10)); + disp_ttu_regs->refcyc_per_req_delivery_l = (unsigned int) (refcyc_per_req_delivery_l + * dml_pow(2, 10)); + + ASSERT(refcyc_per_req_delivery_pre_l < dml_pow(2, 13)); + ASSERT(refcyc_per_req_delivery_l < dml_pow(2, 13)); + + if (dual_plane) { + refcyc_per_req_delivery_pre_c = get_refcyc_per_delivery( + mode_lib, + refclk_freq_in_mhz, + pclk_freq_in_mhz, + full_recout_width, + vratio_pre_c, + hscale_pixel_rate_c, + scaler_rec_in_width_c, + req_per_swath_ub_c); /* per req */ + refcyc_per_req_delivery_c = get_refcyc_per_delivery( + mode_lib, + refclk_freq_in_mhz, + pclk_freq_in_mhz, + full_recout_width, + vratio_c, + hscale_pixel_rate_c, + scaler_rec_in_width_c, + req_per_swath_ub_c); /* per req */ + + DTRACE( + "DLG: %s: refcyc_per_req_delivery_pre_c = %3.2f", + __func__, + refcyc_per_req_delivery_pre_c); + DTRACE( + "DLG: %s: refcyc_per_req_delivery_c = %3.2f", + __func__, + refcyc_per_req_delivery_c); + + disp_ttu_regs->refcyc_per_req_delivery_pre_c = + (unsigned int) (refcyc_per_req_delivery_pre_c * dml_pow(2, 10)); + disp_ttu_regs->refcyc_per_req_delivery_c = (unsigned int) (refcyc_per_req_delivery_c + * dml_pow(2, 10)); + + ASSERT(refcyc_per_req_delivery_pre_c < dml_pow(2, 13)); + ASSERT(refcyc_per_req_delivery_c < dml_pow(2, 13)); + } + + /* TTU - Cursor */ + hratios_cur0 = e2e_pipe_param.pipe.scale_ratio_depth.hscl_ratio; + cur0_src_width = e2e_pipe_param.pipe.src.cur0_src_width; /* cursor source width */ + cur0_bpp = (enum cursor_bpp) e2e_pipe_param.pipe.src.cur0_bpp; + cur0_req_size = 0; + cur0_req_width = 0; + cur0_width_ub = 0.0; + cur0_req_per_width = 0.0; + hactive_cur0 = 0.0; + + ASSERT(cur0_src_width <= 256); + + if (cur0_src_width > 0) { + unsigned int cur0_bit_per_pixel = 0; + + if (cur0_bpp == dm_cur_2bit) { + cur0_req_size = 64; /* byte */ + cur0_bit_per_pixel = 2; + } else { /* 32bit */ + cur0_bit_per_pixel = 32; + if (cur0_src_width >= 1 && cur0_src_width <= 16) + cur0_req_size = 64; + else if (cur0_src_width >= 17 && cur0_src_width <= 31) + cur0_req_size = 128; + else + cur0_req_size = 256; + } + + cur0_req_width = (double) cur0_req_size / ((double) cur0_bit_per_pixel / 8.0); + cur0_width_ub = dml_ceil((double) cur0_src_width / (double) cur0_req_width) + * (double) cur0_req_width; + cur0_req_per_width = cur0_width_ub / (double) cur0_req_width; + hactive_cur0 = (double) cur0_src_width / hratios_cur0; /* FIXME: oswin to think about what to do for cursor */ + + if (vratio_pre_l <= 1.0) { + refcyc_per_req_delivery_pre_cur0 = hactive_cur0 * ref_freq_to_pix_freq + / (double) cur0_req_per_width; + } else { + refcyc_per_req_delivery_pre_cur0 = (double) refclk_freq_in_mhz + * (double) cur0_src_width / hscale_pixel_rate_l + / (double) cur0_req_per_width; + } + + disp_ttu_regs->refcyc_per_req_delivery_pre_cur0 = + (unsigned int) (refcyc_per_req_delivery_pre_cur0 * dml_pow(2, 10)); + ASSERT(refcyc_per_req_delivery_pre_cur0 < dml_pow(2, 13)); + + if (vratio_l <= 1.0) { + refcyc_per_req_delivery_cur0 = hactive_cur0 * ref_freq_to_pix_freq + / (double) cur0_req_per_width; + } else { + refcyc_per_req_delivery_cur0 = (double) refclk_freq_in_mhz + * (double) cur0_src_width / hscale_pixel_rate_l + / (double) cur0_req_per_width; + } + + DTRACE("DLG: %s: cur0_req_width = %d", __func__, cur0_req_width); + DTRACE( + "DLG: %s: cur0_width_ub = %3.2f", + __func__, + cur0_width_ub); + DTRACE( + "DLG: %s: cur0_req_per_width = %3.2f", + __func__, + cur0_req_per_width); + DTRACE( + "DLG: %s: hactive_cur0 = %3.2f", + __func__, + hactive_cur0); + DTRACE( + "DLG: %s: refcyc_per_req_delivery_pre_cur0 = %3.2f", + __func__, + refcyc_per_req_delivery_pre_cur0); + DTRACE( + "DLG: %s: refcyc_per_req_delivery_cur0 = %3.2f", + __func__, + refcyc_per_req_delivery_cur0); + + disp_ttu_regs->refcyc_per_req_delivery_cur0 = + (unsigned int) (refcyc_per_req_delivery_cur0 * dml_pow(2, 10)); + ASSERT(refcyc_per_req_delivery_cur0 < dml_pow(2, 13)); + } else { + disp_ttu_regs->refcyc_per_req_delivery_pre_cur0 = 0; + disp_ttu_regs->refcyc_per_req_delivery_cur0 = 0; + } + + /* TTU - Misc */ + disp_ttu_regs->qos_level_low_wm = 0; + ASSERT(disp_ttu_regs->qos_level_low_wm < dml_pow(2, 14)); + disp_ttu_regs->qos_level_high_wm = (unsigned int) (4.0 * (double) htotal + * ref_freq_to_pix_freq); + ASSERT(disp_ttu_regs->qos_level_high_wm < dml_pow(2, 14)); + + disp_ttu_regs->qos_level_flip = 14; + disp_ttu_regs->qos_level_fixed_l = 8; + disp_ttu_regs->qos_level_fixed_c = 8; + disp_ttu_regs->qos_level_fixed_cur0 = 8; + disp_ttu_regs->qos_ramp_disable_l = 0; + disp_ttu_regs->qos_ramp_disable_c = 0; + disp_ttu_regs->qos_ramp_disable_cur0 = 0; + + disp_ttu_regs->min_ttu_vblank = min_ttu_vblank * refclk_freq_in_mhz; + ASSERT(disp_ttu_regs->min_ttu_vblank < dml_pow(2, 24)); + + print__ttu_regs_st(mode_lib, *disp_ttu_regs); + print__dlg_regs_st(mode_lib, *disp_dlg_regs); +} + +void dml_rq_dlg_get_dlg_reg( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_dlg_regs_st *dlg_regs, + struct _vcs_dpi_display_ttu_regs_st *ttu_regs, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e_pipe_param, + const int unsigned num_pipes, + const int unsigned pipe_idx, + const bool cstate_en, + const bool pstate_en, + const bool vm_en, + const bool iflip_en) +{ + struct _vcs_dpi_display_rq_params_st rq_param = {0}; + struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param = {0}; + struct _vcs_dpi_wm_calc_pipe_params_st *wm_param = mode_lib->wm_param; + struct _vcs_dpi_cstate_pstate_watermarks_st cstate_pstate_wm; + struct _vcs_dpi_display_dlg_prefetch_param_st prefetch_param; + double total_ret_bw; + double total_active_bw; + double total_prefetch_bw; + int unsigned total_flip_bytes; + int unsigned num_planes; + int i; + + memset(wm_param, 0, sizeof(mode_lib->wm_param)); + + /* Get watermark and Tex. */ + DTRACE("DLG: Start calculating system setting related parameters. num_pipes=%d", num_pipes); + num_planes = dml_wm_e2e_to_wm(mode_lib, e2e_pipe_param, num_pipes, wm_param); + + cstate_pstate_wm = dml_wm_cstate_pstate_e2e(mode_lib, e2e_pipe_param, num_pipes); + dlg_sys_param.t_mclk_wm_us = cstate_pstate_wm.pstate_change_us; + dlg_sys_param.t_sr_wm_us = cstate_pstate_wm.cstate_enter_plus_exit_us; + dlg_sys_param.t_urg_wm_us = dml_wm_urgent_e2e(mode_lib, e2e_pipe_param, num_pipes); + dlg_sys_param.t_srx_delay_us = mode_lib->ip.dcfclk_cstate_latency + / dml_wm_dcfclk_deepsleep_mhz_e2e(mode_lib, e2e_pipe_param, num_pipes); + dlg_sys_param.t_extra_us = dml_wm_urgent_extra(mode_lib, wm_param, num_planes); + dlg_sys_param.deepsleep_dcfclk_mhz = dml_wm_dcfclk_deepsleep_mhz_e2e( + mode_lib, + e2e_pipe_param, + num_pipes); + + print__dlg_sys_params_st(mode_lib, dlg_sys_param); + + DTRACE("DLG: Start calculating total prefetch bw. num_planes=%d", num_planes); + total_ret_bw = dml_wm_calc_return_bw(mode_lib, wm_param, num_planes); + total_active_bw = dml_wm_calc_total_data_read_bw(mode_lib, wm_param, num_planes); + total_prefetch_bw = 0.0; + total_flip_bytes = 0; + + for (i = 0; i < num_pipes; i++) { + dml_rq_dlg_get_rq_params(mode_lib, &rq_param, e2e_pipe_param[i].pipe.src); + dml_rq_dlg_get_dlg_params_prefetch( + mode_lib, + &prefetch_param, + rq_param.dlg, + dlg_sys_param, + e2e_pipe_param[i], + cstate_en, + pstate_en, + vm_en); + total_prefetch_bw += prefetch_param.prefetch_bw; + total_flip_bytes += prefetch_param.flip_bytes; + DTRACE( + "DLG: pipe=%d, total_prefetch_bw=%3.2f total_flip_bytes=%d", + i, + total_prefetch_bw, + total_flip_bytes); + } + + dlg_sys_param.total_flip_bw = total_ret_bw - dml_max(total_active_bw, total_prefetch_bw); + + DTRACE("DLG: Done calculating total prefetch bw"); + DTRACE("DLG: num_pipes = %d", num_pipes); + DTRACE("DLG: total_ret_bw = %3.2f", total_ret_bw); + DTRACE("DLG: total_active_bw = %3.2f", total_active_bw); + DTRACE("DLG: total_prefetch_bw = %3.2f", total_prefetch_bw); + DTRACE("DLG: total_flip_bw = %3.2f", dlg_sys_param.total_flip_bw); + + if (dlg_sys_param.total_flip_bw < 0.0 && iflip_en) { + DTRACE("WARNING_DLG Insufficient bw for immediate flip!"); + dlg_sys_param.total_flip_bw = 0; + } + + dlg_sys_param.total_flip_bytes = total_flip_bytes; + DTRACE("DLG: total_flip_bytes = %d", dlg_sys_param.total_flip_bytes); + DTRACE("DLG: Done calculating system setting related parameters."); + + /* system parameter calculation done */ + + DTRACE("DLG: Calculation for pipe[%d] start", pipe_idx); + dml_rq_dlg_get_rq_params(mode_lib, &rq_param, e2e_pipe_param[pipe_idx].pipe.src); + dml_rq_dlg_get_dlg_params( + mode_lib, + dlg_regs, + ttu_regs, + rq_param.dlg, + dlg_sys_param, + e2e_pipe_param[pipe_idx], + cstate_en, + pstate_en, + vm_en, + iflip_en); + DTRACE("DLG: Calculation for pipe[%d] end", pipe_idx); +} + +void dml_rq_dlg_get_arb_params( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_arb_params_st *arb_param) +{ + memset(arb_param, 0, sizeof(*arb_param)); + arb_param->max_req_outstanding = 256; + arb_param->min_req_outstanding = 68; + arb_param->sat_level_us = 60; +} diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.h b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.h new file mode 100644 index 000000000000..e63b13fb2887 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.h @@ -0,0 +1,139 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef __DISPLAY_RQ_DLG_CALC_H__ +#define __DISPLAY_RQ_DLG_CALC_H__ + +#include "dml_common_defs.h" +#include "display_rq_dlg_helpers.h" + +struct display_mode_lib; + +void extract_rq_regs( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_regs_st *rq_regs, + const struct _vcs_dpi_display_rq_params_st rq_param); +/* Function: dml_rq_dlg_get_rq_params + * Calculate requestor related parameters that register definition agnostic + * (i.e. this layer does try to separate real values from register defintion) + * Input: + * pipe_src_param - pipe source configuration (e.g. vp, pitch, etc.) + * Output: + * rq_param - values that can be used to setup RQ (e.g. swath_height, plane1_addr, etc.) + */ +void dml_rq_dlg_get_rq_params( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_params_st *rq_param, + const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param); + +/* Function: dml_rq_dlg_get_rq_reg + * Main entry point for test to get the register values out of this DML class. + * This function calls and fucntions to calculate + * and then populate the rq_regs struct + * Input: + * pipe_src_param - pipe source configuration (e.g. vp, pitch, etc.) + * Output: + * rq_regs - struct that holds all the RQ registers field value. + * See also: + */ +void dml_rq_dlg_get_rq_reg( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_regs_st *rq_regs, + const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param); + +/* Function: dml_rq_dlg_get_dlg_params + * Calculate deadline related parameters + */ +void dml_rq_dlg_get_dlg_params( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_dlg_regs_st *dlg_regs, + struct _vcs_dpi_display_ttu_regs_st *ttu_regs, + const struct _vcs_dpi_display_rq_dlg_params_st rq_dlg_param, + const struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param, + const struct _vcs_dpi_display_e2e_pipe_params_st e2e_pipe_param, + const bool cstate_en, + const bool pstate_en, + const bool vm_en, + const bool iflip_en); + +/* Function: dml_rq_dlg_get_dlg_param_prefetch + * For flip_bw programming guide change, now dml needs to calculate the flip_bytes and prefetch_bw + * for ALL pipes and use this info to calculate the prefetch programming. + * Output: prefetch_param.prefetch_bw and flip_bytes + */ +void dml_rq_dlg_get_dlg_params_prefetch( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_dlg_prefetch_param_st *prefetch_param, + struct _vcs_dpi_display_rq_dlg_params_st rq_dlg_param, + struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param, + struct _vcs_dpi_display_e2e_pipe_params_st e2e_pipe_param, + const bool cstate_en, + const bool pstate_en, + const bool vm_en); + +/* Function: dml_rq_dlg_get_dlg_reg + * Calculate and return DLG and TTU register struct given the system setting + * Output: + * dlg_regs - output DLG register struct + * ttu_regs - output DLG TTU register struct + * Input: + * e2e_pipe_param - "compacted" array of e2e pipe param struct + * num_pipes - num of active "pipe" or "route" + * pipe_idx - index that identifies the e2e_pipe_param that corresponding to this dlg + * cstate - 0: when calculate min_ttu_vblank it is assumed cstate is not required. 1: Normal mode, cstate is considered. + * Added for legacy or unrealistic timing tests. + */ +void dml_rq_dlg_get_dlg_reg( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_dlg_regs_st *dlg_regs, + struct _vcs_dpi_display_ttu_regs_st *ttu_regs, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e_pipe_param, + const unsigned int num_pipes, + const unsigned int pipe_idx, + const bool cstate_en, + const bool pstate_en, + const bool vm_en, + const bool iflip_en); + +/* Function: dml_rq_dlg_get_row_heights + * Calculate dpte and meta row heights + */ +void dml_rq_dlg_get_row_heights( + struct display_mode_lib *mode_lib, + unsigned int *o_dpte_row_height, + unsigned int *o_meta_row_height, + unsigned int vp_width, + unsigned int data_pitch, + int source_format, + int tiling, + int macro_tile_size, + int source_scan, + int is_chroma); + +/* Function: dml_rq_dlg_get_arb_params */ +void dml_rq_dlg_get_arb_params( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_arb_params_st *arb_param); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c new file mode 100644 index 000000000000..3dc11366cd36 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c @@ -0,0 +1,320 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "display_rq_dlg_helpers.h" + +void print__rq_params_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_params_st rq_param) +{ + DTRACE("RQ_DLG_CALC: *************************** "); + DTRACE("RQ_DLG_CALC: DISPLAY_RQ_PARAM_ST"); + DTRACE("RQ_DLG_CALC: "); + print__data_rq_sizing_params_st(mode_lib, rq_param.sizing.rq_l); + DTRACE("RQ_DLG_CALC: === "); + print__data_rq_sizing_params_st(mode_lib, rq_param.sizing.rq_c); + + DTRACE("RQ_DLG_CALC: "); + print__data_rq_dlg_params_st(mode_lib, rq_param.dlg.rq_l); + DTRACE("RQ_DLG_CALC: "); + print__data_rq_dlg_params_st(mode_lib, rq_param.dlg.rq_c); + + DTRACE("RQ_DLG_CALC: "); + print__data_rq_misc_params_st(mode_lib, rq_param.misc.rq_l); + DTRACE("RQ_DLG_CALC: "); + print__data_rq_misc_params_st(mode_lib, rq_param.misc.rq_c); + DTRACE("RQ_DLG_CALC: *************************** "); +} + +void print__data_rq_sizing_params_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_data_rq_sizing_params_st rq_sizing) +{ + DTRACE("RQ_DLG_CALC: ===================================== "); + DTRACE("RQ_DLG_CALC: DISPLAY_DATA_RQ_SIZING_PARAM_ST"); + DTRACE("RQ_DLG_CALC: chunk_bytes = %0d", rq_sizing.chunk_bytes); + DTRACE("RQ_DLG_CALC: min_chunk_bytes = %0d", rq_sizing.min_chunk_bytes); + DTRACE("RQ_DLG_CALC: meta_chunk_bytes = %0d", rq_sizing.meta_chunk_bytes); + DTRACE("RQ_DLG_CALC: min_meta_chunk_bytes = %0d", rq_sizing.min_meta_chunk_bytes); + DTRACE("RQ_DLG_CALC: mpte_group_bytes = %0d", rq_sizing.mpte_group_bytes); + DTRACE("RQ_DLG_CALC: dpte_group_bytes = %0d", rq_sizing.dpte_group_bytes); + DTRACE("RQ_DLG_CALC: ===================================== "); +} + +void print__data_rq_dlg_params_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_data_rq_dlg_params_st rq_dlg_param) +{ + DTRACE("RQ_DLG_CALC: ===================================== "); + DTRACE("RQ_DLG_CALC: DISPLAY_DATA_RQ_DLG_PARAM_ST"); + DTRACE("RQ_DLG_CALC: swath_width_ub = %0d", rq_dlg_param.swath_width_ub); + DTRACE("RQ_DLG_CALC: swath_height = %0d", rq_dlg_param.swath_height); + DTRACE("RQ_DLG_CALC: req_per_swath_ub = %0d", rq_dlg_param.req_per_swath_ub); + DTRACE( + "RQ_DLG_CALC: meta_pte_bytes_per_frame_ub = %0d", + rq_dlg_param.meta_pte_bytes_per_frame_ub); + DTRACE( + "RQ_DLG_CALC: dpte_req_per_row_ub = %0d", + rq_dlg_param.dpte_req_per_row_ub); + DTRACE( + "RQ_DLG_CALC: dpte_groups_per_row_ub = %0d", + rq_dlg_param.dpte_groups_per_row_ub); + DTRACE("RQ_DLG_CALC: dpte_row_height = %0d", rq_dlg_param.dpte_row_height); + DTRACE( + "RQ_DLG_CALC: dpte_bytes_per_row_ub = %0d", + rq_dlg_param.dpte_bytes_per_row_ub); + DTRACE( + "RQ_DLG_CALC: meta_chunks_per_row_ub = %0d", + rq_dlg_param.meta_chunks_per_row_ub); + DTRACE( + "RQ_DLG_CALC: meta_req_per_row_ub = %0d", + rq_dlg_param.meta_req_per_row_ub); + DTRACE("RQ_DLG_CALC: meta_row_height = %0d", rq_dlg_param.meta_row_height); + DTRACE( + "RQ_DLG_CALC: meta_bytes_per_row_ub = %0d", + rq_dlg_param.meta_bytes_per_row_ub); + DTRACE("RQ_DLG_CALC: ===================================== "); +} + +void print__data_rq_misc_params_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_data_rq_misc_params_st rq_misc_param) +{ + DTRACE("RQ_DLG_CALC: ===================================== "); + DTRACE("RQ_DLG_CALC: DISPLAY_DATA_RQ_MISC_PARAM_ST"); + DTRACE("RQ_DLG_CALC: full_swath_bytes = %0d", rq_misc_param.full_swath_bytes); + DTRACE("RQ_DLG_CALC: stored_swath_bytes = %0d", rq_misc_param.stored_swath_bytes); + DTRACE("RQ_DLG_CALC: blk256_width = %0d", rq_misc_param.blk256_width); + DTRACE("RQ_DLG_CALC: blk256_height = %0d", rq_misc_param.blk256_height); + DTRACE("RQ_DLG_CALC: req_width = %0d", rq_misc_param.req_width); + DTRACE("RQ_DLG_CALC: req_height = %0d", rq_misc_param.req_height); + DTRACE("RQ_DLG_CALC: ===================================== "); +} + +void print__rq_dlg_params_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_dlg_params_st rq_dlg_param) +{ + DTRACE("RQ_DLG_CALC: ===================================== "); + DTRACE("RQ_DLG_CALC: DISPLAY_RQ_DLG_PARAM_ST"); + DTRACE("RQ_DLG_CALC: "); + print__data_rq_dlg_params_st(mode_lib, rq_dlg_param.rq_l); + DTRACE("RQ_DLG_CALC: "); + print__data_rq_dlg_params_st(mode_lib, rq_dlg_param.rq_c); + DTRACE("RQ_DLG_CALC: ===================================== "); +} + +void print__dlg_sys_params_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param) +{ + DTRACE("RQ_DLG_CALC: ===================================== "); + DTRACE("RQ_DLG_CALC: DISPLAY_RQ_DLG_PARAM_ST"); + DTRACE("RQ_DLG_CALC: t_mclk_wm_us = %3.2f", dlg_sys_param.t_mclk_wm_us); + DTRACE("RQ_DLG_CALC: t_urg_wm_us = %3.2f", dlg_sys_param.t_urg_wm_us); + DTRACE("RQ_DLG_CALC: t_sr_wm_us = %3.2f", dlg_sys_param.t_sr_wm_us); + DTRACE("RQ_DLG_CALC: t_extra_us = %3.2f", dlg_sys_param.t_extra_us); + DTRACE("RQ_DLG_CALC: t_srx_delay_us = %3.2f", dlg_sys_param.t_srx_delay_us); + DTRACE("RQ_DLG_CALC: deepsleep_dcfclk_mhz = %3.2f", dlg_sys_param.deepsleep_dcfclk_mhz); + DTRACE("RQ_DLG_CALC: ===================================== "); +} + +void print__data_rq_regs_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_data_rq_regs_st rq_regs) +{ + DTRACE("RQ_DLG_CALC: ===================================== "); + DTRACE("RQ_DLG_CALC: DISPLAY_DATA_RQ_REGS_ST"); + DTRACE("RQ_DLG_CALC: chunk_size = 0x%0x", rq_regs.chunk_size); + DTRACE("RQ_DLG_CALC: min_chunk_size = 0x%0x", rq_regs.min_chunk_size); + DTRACE("RQ_DLG_CALC: meta_chunk_size = 0x%0x", rq_regs.meta_chunk_size); + DTRACE("RQ_DLG_CALC: min_meta_chunk_size = 0x%0x", rq_regs.min_meta_chunk_size); + DTRACE("RQ_DLG_CALC: dpte_group_size = 0x%0x", rq_regs.dpte_group_size); + DTRACE("RQ_DLG_CALC: mpte_group_size = 0x%0x", rq_regs.mpte_group_size); + DTRACE("RQ_DLG_CALC: swath_height = 0x%0x", rq_regs.swath_height); + DTRACE("RQ_DLG_CALC: pte_row_height_linear = 0x%0x", rq_regs.pte_row_height_linear); + DTRACE("RQ_DLG_CALC: ===================================== "); +} + +void print__rq_regs_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_regs_st rq_regs) +{ + DTRACE("RQ_DLG_CALC: ===================================== "); + DTRACE("RQ_DLG_CALC: DISPLAY_RQ_REGS_ST"); + DTRACE("RQ_DLG_CALC: "); + print__data_rq_regs_st(mode_lib, rq_regs.rq_regs_l); + DTRACE("RQ_DLG_CALC: "); + print__data_rq_regs_st(mode_lib, rq_regs.rq_regs_c); + DTRACE("RQ_DLG_CALC: drq_expansion_mode = 0x%0x", rq_regs.drq_expansion_mode); + DTRACE("RQ_DLG_CALC: prq_expansion_mode = 0x%0x", rq_regs.prq_expansion_mode); + DTRACE("RQ_DLG_CALC: mrq_expansion_mode = 0x%0x", rq_regs.mrq_expansion_mode); + DTRACE("RQ_DLG_CALC: crq_expansion_mode = 0x%0x", rq_regs.crq_expansion_mode); + DTRACE("RQ_DLG_CALC: plane1_base_address = 0x%0x", rq_regs.plane1_base_address); + DTRACE("RQ_DLG_CALC: ===================================== "); +} + +void print__dlg_regs_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_dlg_regs_st dlg_regs) +{ + DTRACE("RQ_DLG_CALC: ===================================== "); + DTRACE("RQ_DLG_CALC: DISPLAY_DLG_REGS_ST "); + DTRACE( + "RQ_DLG_CALC: refcyc_h_blank_end = 0x%0x", + dlg_regs.refcyc_h_blank_end); + DTRACE("RQ_DLG_CALC: dlg_vblank_end = 0x%0x", dlg_regs.dlg_vblank_end); + DTRACE( + "RQ_DLG_CALC: min_dst_y_next_start = 0x%0x", + dlg_regs.min_dst_y_next_start); + DTRACE( + "RQ_DLG_CALC: refcyc_per_htotal = 0x%0x", + dlg_regs.refcyc_per_htotal); + DTRACE( + "RQ_DLG_CALC: refcyc_x_after_scaler = 0x%0x", + dlg_regs.refcyc_x_after_scaler); + DTRACE( + "RQ_DLG_CALC: dst_y_after_scaler = 0x%0x", + dlg_regs.dst_y_after_scaler); + DTRACE("RQ_DLG_CALC: dst_y_prefetch = 0x%0x", dlg_regs.dst_y_prefetch); + DTRACE( + "RQ_DLG_CALC: dst_y_per_vm_vblank = 0x%0x", + dlg_regs.dst_y_per_vm_vblank); + DTRACE( + "RQ_DLG_CALC: dst_y_per_row_vblank = 0x%0x", + dlg_regs.dst_y_per_row_vblank); + DTRACE( + "RQ_DLG_CALC: ref_freq_to_pix_freq = 0x%0x", + dlg_regs.ref_freq_to_pix_freq); + DTRACE("RQ_DLG_CALC: vratio_prefetch = 0x%0x", dlg_regs.vratio_prefetch); + DTRACE( + "RQ_DLG_CALC: vratio_prefetch_c = 0x%0x", + dlg_regs.vratio_prefetch_c); + DTRACE( + "RQ_DLG_CALC: refcyc_per_pte_group_vblank_l = 0x%0x", + dlg_regs.refcyc_per_pte_group_vblank_l); + DTRACE( + "RQ_DLG_CALC: refcyc_per_pte_group_vblank_c = 0x%0x", + dlg_regs.refcyc_per_pte_group_vblank_c); + DTRACE( + "RQ_DLG_CALC: refcyc_per_meta_chunk_vblank_l = 0x%0x", + dlg_regs.refcyc_per_meta_chunk_vblank_l); + DTRACE( + "RQ_DLG_CALC: refcyc_per_meta_chunk_vblank_c = 0x%0x", + dlg_regs.refcyc_per_meta_chunk_vblank_c); + DTRACE( + "RQ_DLG_CALC: dst_y_per_pte_row_nom_l = 0x%0x", + dlg_regs.dst_y_per_pte_row_nom_l); + DTRACE( + "RQ_DLG_CALC: dst_y_per_pte_row_nom_c = 0x%0x", + dlg_regs.dst_y_per_pte_row_nom_c); + DTRACE( + "RQ_DLG_CALC: refcyc_per_pte_group_nom_l = 0x%0x", + dlg_regs.refcyc_per_pte_group_nom_l); + DTRACE( + "RQ_DLG_CALC: refcyc_per_pte_group_nom_c = 0x%0x", + dlg_regs.refcyc_per_pte_group_nom_c); + DTRACE( + "RQ_DLG_CALC: dst_y_per_meta_row_nom_l = 0x%0x", + dlg_regs.dst_y_per_meta_row_nom_l); + DTRACE( + "RQ_DLG_CALC: dst_y_per_meta_row_nom_c = 0x%0x", + dlg_regs.dst_y_per_meta_row_nom_c); + DTRACE( + "RQ_DLG_CALC: refcyc_per_meta_chunk_nom_l = 0x%0x", + dlg_regs.refcyc_per_meta_chunk_nom_l); + DTRACE( + "RQ_DLG_CALC: refcyc_per_meta_chunk_nom_c = 0x%0x", + dlg_regs.refcyc_per_meta_chunk_nom_c); + DTRACE( + "RQ_DLG_CALC: refcyc_per_line_delivery_pre_l = 0x%0x", + dlg_regs.refcyc_per_line_delivery_pre_l); + DTRACE( + "RQ_DLG_CALC: refcyc_per_line_delivery_pre_c = 0x%0x", + dlg_regs.refcyc_per_line_delivery_pre_c); + DTRACE( + "RQ_DLG_CALC: refcyc_per_line_delivery_l = 0x%0x", + dlg_regs.refcyc_per_line_delivery_l); + DTRACE( + "RQ_DLG_CALC: refcyc_per_line_delivery_c = 0x%0x", + dlg_regs.refcyc_per_line_delivery_c); + DTRACE( + "RQ_DLG_CALC: chunk_hdl_adjust_cur0 = 0x%0x", + dlg_regs.chunk_hdl_adjust_cur0); + DTRACE("RQ_DLG_CALC: ===================================== "); +} + +void print__ttu_regs_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_ttu_regs_st ttu_regs) +{ + DTRACE("RQ_DLG_CALC: ===================================== "); + DTRACE("RQ_DLG_CALC: DISPLAY_TTU_REGS_ST "); + DTRACE( + "RQ_DLG_CALC: qos_level_low_wm = 0x%0x", + ttu_regs.qos_level_low_wm); + DTRACE( + "RQ_DLG_CALC: qos_level_high_wm = 0x%0x", + ttu_regs.qos_level_high_wm); + DTRACE("RQ_DLG_CALC: min_ttu_vblank = 0x%0x", ttu_regs.min_ttu_vblank); + DTRACE("RQ_DLG_CALC: qos_level_flip = 0x%0x", ttu_regs.qos_level_flip); + DTRACE( + "RQ_DLG_CALC: refcyc_per_req_delivery_pre_l = 0x%0x", + ttu_regs.refcyc_per_req_delivery_pre_l); + DTRACE( + "RQ_DLG_CALC: refcyc_per_req_delivery_l = 0x%0x", + ttu_regs.refcyc_per_req_delivery_l); + DTRACE( + "RQ_DLG_CALC: refcyc_per_req_delivery_pre_c = 0x%0x", + ttu_regs.refcyc_per_req_delivery_pre_c); + DTRACE( + "RQ_DLG_CALC: refcyc_per_req_delivery_c = 0x%0x", + ttu_regs.refcyc_per_req_delivery_c); + DTRACE( + "RQ_DLG_CALC: refcyc_per_req_delivery_cur0 = 0x%0x", + ttu_regs.refcyc_per_req_delivery_cur0); + DTRACE( + "RQ_DLG_CALC: refcyc_per_req_delivery_pre_cur0 = 0x%0x", + ttu_regs.refcyc_per_req_delivery_pre_cur0); + DTRACE( + "RQ_DLG_CALC: qos_level_fixed_l = 0x%0x", + ttu_regs.qos_level_fixed_l); + DTRACE( + "RQ_DLG_CALC: qos_ramp_disable_l = 0x%0x", + ttu_regs.qos_ramp_disable_l); + DTRACE( + "RQ_DLG_CALC: qos_level_fixed_c = 0x%0x", + ttu_regs.qos_level_fixed_c); + DTRACE( + "RQ_DLG_CALC: qos_ramp_disable_c = 0x%0x", + ttu_regs.qos_ramp_disable_c); + DTRACE( + "RQ_DLG_CALC: qos_level_fixed_cur0 = 0x%0x", + ttu_regs.qos_level_fixed_cur0); + DTRACE( + "RQ_DLG_CALC: qos_ramp_disable_cur0 = 0x%0x", + ttu_regs.qos_ramp_disable_cur0); + DTRACE("RQ_DLG_CALC: ===================================== "); +} diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.h b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.h new file mode 100644 index 000000000000..7403ccaf637b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.h @@ -0,0 +1,66 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef __DISPLAY_RQ_DLG_HELPERS_H__ +#define __DISPLAY_RQ_DLG_HELPERS_H__ + +#include "dml_common_defs.h" +#include "display_mode_lib.h" + +/* Function: Printer functions + * Print various struct + */ +void print__rq_params_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_params_st rq_param); +void print__data_rq_sizing_params_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_data_rq_sizing_params_st rq_sizing); +void print__data_rq_dlg_params_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_data_rq_dlg_params_st rq_dlg_param); +void print__data_rq_misc_params_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_data_rq_misc_params_st rq_misc_param); +void print__rq_dlg_params_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_dlg_params_st rq_dlg_param); +void print__dlg_sys_params_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param); + +void print__data_rq_regs_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_data_rq_regs_st data_rq_regs); +void print__rq_regs_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_regs_st rq_regs); +void print__dlg_regs_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_dlg_regs_st dlg_regs); +void print__ttu_regs_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_ttu_regs_st ttu_regs); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_watermark.c b/drivers/gpu/drm/amd/display/dc/dml/display_watermark.c new file mode 100644 index 000000000000..390f09391433 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_watermark.c @@ -0,0 +1,1281 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#include "display_watermark.h" +#include "display_mode_lib.h" + +static void get_bytes_per_pixel( + enum source_format_class format, + struct _vcs_dpi_wm_calc_pipe_params_st *plane) +{ + switch (format) { + case dm_444_64: + plane->bytes_per_pixel_y = 8.0; + plane->bytes_per_pixel_c = 0.0; + break; + case dm_444_32: + plane->bytes_per_pixel_y = 4.0; + plane->bytes_per_pixel_c = 0.0; + break; + case dm_444_16: + plane->bytes_per_pixel_y = 2.0; + plane->bytes_per_pixel_c = 0.0; + break; + case dm_422_10: + plane->bytes_per_pixel_y = 4.0; + plane->bytes_per_pixel_c = 0.0; + break; + case dm_422_8: + plane->bytes_per_pixel_y = 2.0; + plane->bytes_per_pixel_c = 0.0; + break; + case dm_420_8: + plane->bytes_per_pixel_y = 1.0; + plane->bytes_per_pixel_c = 2.0; + break; + case dm_420_10: + plane->bytes_per_pixel_y = 4.0 / 3; + plane->bytes_per_pixel_c = 8.0 / 3; + break; + default: + BREAK_TO_DEBUGGER(); /* invalid format in get_bytes_per_pixel */ + } +} + +static unsigned int get_swath_width_y( + struct _vcs_dpi_display_pipe_source_params_st *src_param, + unsigned int num_dpp) +{ + unsigned int val; + + /* note that we don't divide by num_dpp here because we have an interface which has already split + * any viewports + */ + if (src_param->source_scan == dm_horz) { + val = src_param->viewport_width; + } else { + val = src_param->viewport_height; + } + + return val; +} + +static void get_swath_height( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_pipe_source_params_st *src_param, + struct _vcs_dpi_wm_calc_pipe_params_st *plane, + unsigned int swath_width_y) +{ + double buffer_width; + + if (src_param->source_format == dm_444_64 || src_param->source_format == dm_444_32 + || src_param->source_format == dm_444_16) { + if (src_param->sw_mode == dm_sw_linear) { + plane->swath_height_y = 1; + } else if (src_param->source_format == dm_444_64) { + plane->swath_height_y = 4; + } else { + plane->swath_height_y = 8; + } + + if (src_param->source_scan != dm_horz) { + plane->swath_height_y = 256 / (unsigned int) plane->bytes_per_pixel_y + / plane->swath_height_y; + } + + plane->swath_height_c = 0; + + } else { + if (src_param->sw_mode == dm_sw_linear) { + plane->swath_height_y = 1; + plane->swath_height_c = 1; + } else if (src_param->source_format == dm_420_8) { + plane->swath_height_y = 16; + plane->swath_height_c = 8; + } else { + plane->swath_height_y = 8; + plane->swath_height_c = 8; + } + + if (src_param->source_scan != dm_horz) { + double bytes_per_pixel_c_ceil; + + plane->swath_height_y = 256 / dml_ceil(plane->bytes_per_pixel_y) + / plane->swath_height_y; + + bytes_per_pixel_c_ceil = dml_ceil_2(plane->bytes_per_pixel_c); + + plane->swath_height_c = 256 / bytes_per_pixel_c_ceil + / plane->swath_height_c; + } + } + + /* use swath height min if buffer isn't big enough */ + + buffer_width = ((double) mode_lib->ip.det_buffer_size_kbytes * 1024.0 / 2.0) + / (plane->bytes_per_pixel_y * (double) plane->swath_height_y + + (plane->bytes_per_pixel_c / 2.0 + * (double) plane->swath_height_c)); + + if ((double) swath_width_y <= buffer_width) { + /* do nothing, just keep code structure from Gabes vba */ + } else { + /* substitute swath height with swath height min */ + if (src_param->source_format == dm_444_64 || src_param->source_format == dm_444_32 + || src_param->source_format == dm_444_16) { + if ((src_param->sw_mode == dm_sw_linear) + || (src_param->source_format == dm_444_64 + && (src_param->sw_mode == dm_sw_4kb_s + || src_param->sw_mode + == dm_sw_4kb_s_x + || src_param->sw_mode + == dm_sw_64kb_s + || src_param->sw_mode + == dm_sw_64kb_s_t + || src_param->sw_mode + == dm_sw_64kb_s_x + || src_param->sw_mode + == dm_sw_var_s + || src_param->sw_mode + == dm_sw_var_s_x) + && src_param->source_scan == dm_horz)) { + /* do nothing, just keep code structure from Gabes vba */ + } else { + plane->swath_height_y = plane->swath_height_y / 2; + } + } else { + if (src_param->sw_mode == dm_sw_linear) { + /* do nothing, just keep code structure from Gabes vba */ + } else if (src_param->source_format == dm_420_8 + && src_param->source_scan == dm_horz) { + plane->swath_height_y = plane->swath_height_y / 2; + } else if (src_param->source_format == dm_420_10 + && src_param->source_scan == dm_horz) { + plane->swath_height_c = plane->swath_height_c / 2; + } + } + } + + if (plane->swath_height_c == 0) { + plane->det_buffer_size_y = mode_lib->ip.det_buffer_size_kbytes * 1024.0; + } else if (plane->swath_height_c <= plane->swath_height_y) { + plane->det_buffer_size_y = mode_lib->ip.det_buffer_size_kbytes * 1024.0 / 2.0; + } else { + plane->det_buffer_size_y = mode_lib->ip.det_buffer_size_kbytes * 1024.0 * 2.0 / 3.0; + } +} + +static void calc_display_pipe_line_delivery_time( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *planes, + unsigned int num_planes) +{ + unsigned int i; + + for (i = 0; i < num_planes; i++) { + if (planes[i].v_ratio <= 1.0) { + planes[i].display_pipe_line_delivery_time = planes[i].swath_width_y + * planes[i].num_dpp / planes[i].h_ratio + / planes[i].pixclk_mhz; + } else { + double dchub_pscl_bw_per_clk; + + if (planes[i].h_ratio > 1) { + double num_hscl_kernels; + + num_hscl_kernels = dml_ceil((double) planes[i].h_taps / 6); + dchub_pscl_bw_per_clk = + dml_min( + (double) mode_lib->ip.max_dchub_pscl_bw_pix_per_clk, + mode_lib->ip.max_pscl_lb_bw_pix_per_clk + * planes[i].h_ratio + / num_hscl_kernels); + } else { + dchub_pscl_bw_per_clk = + dml_min( + (double) mode_lib->ip.max_dchub_pscl_bw_pix_per_clk, + (double) mode_lib->ip.max_pscl_lb_bw_pix_per_clk); + } + + planes[i].display_pipe_line_delivery_time = planes[i].swath_width_y + / dchub_pscl_bw_per_clk / planes[i].dppclk_mhz; + } + } +} + +static double calc_total_data_read_bw( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *planes, + unsigned int num_planes) +{ + double val = 0.0; + unsigned int i; + + for (i = 0; i < num_planes; i++) { + double swath_width_y_plane = planes[i].swath_width_y * planes[i].num_dpp; + + planes[i].read_bw = swath_width_y_plane + * (dml_ceil(planes[i].bytes_per_pixel_y) + + dml_ceil_2(planes[i].bytes_per_pixel_c) / 2) + / (planes[i].h_total / planes[i].pixclk_mhz) * planes[i].v_ratio; + + val += planes[i].read_bw; + + DTRACE("plane[%d] start", i); + DTRACE("read_bw = %f", planes[i].read_bw); + DTRACE("plane[%d] end", i); + } + + return val; +} + +double dml_wm_calc_total_data_read_bw( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *planes, + unsigned int num_planes) +{ + return calc_total_data_read_bw(mode_lib, planes, num_planes); +} + +static double calc_dcfclk_mhz( + struct _vcs_dpi_wm_calc_pipe_params_st *planes, + unsigned int num_planes) +{ + double dcfclk_mhz = -1.0; + unsigned int i; + + for (i = 0; i < num_planes; i++) { + /* voltage and dcfclk must be the same for all pipes */ + ASSERT(dcfclk_mhz == -1.0 || dcfclk_mhz == planes[i].dcfclk_mhz); + dcfclk_mhz = planes[i].dcfclk_mhz; + } + + return dcfclk_mhz; +} + +static enum voltage_state find_voltage( + struct _vcs_dpi_wm_calc_pipe_params_st *planes, + unsigned int num_planes) +{ + int voltage = -1; + unsigned int i; + + for (i = 0; i < num_planes; i++) { + ASSERT(voltage == -1 || voltage == planes[i].voltage); + voltage = planes[i].voltage; + } + + return (enum voltage_state) voltage; +} + +static bool find_dcc_enable(struct _vcs_dpi_wm_calc_pipe_params_st *planes, unsigned int num_planes) +{ + unsigned int i; + + for (i = 0; i < num_planes; i++) { + if (planes[i].dcc_enable) { + return true; + } + } + + return false; +} + +static double calc_return_bw( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *planes, + unsigned int num_planes) +{ + struct _vcs_dpi_soc_bounding_box_st *soc; + double return_bw_mbps; + double dcfclk_mhz; + double return_bus_bw; + enum voltage_state voltage; + double return_bw_to_dcn; + bool dcc_enable; + double rob_chunk_diff; + double urgent_latency_traffic; + double critical_compression; + struct _vcs_dpi_voltage_scaling_st state; + + soc = &mode_lib->soc; + + dcfclk_mhz = calc_dcfclk_mhz(planes, num_planes); + return_bus_bw = dcfclk_mhz * soc->return_bus_width_bytes; + + DTRACE("INTERMEDIATE dcfclk_mhz = %f", dcfclk_mhz); + DTRACE("INTERMEDIATE return_bus_bw = %f", return_bus_bw); + + voltage = find_voltage(planes, num_planes); + return_bw_to_dcn = dml_socbb_return_bw_mhz(soc, voltage); + + dcc_enable = find_dcc_enable(planes, num_planes); + + return_bw_mbps = return_bw_to_dcn; + DTRACE("INTERMEDIATE return_bw_mbps = %f", return_bw_mbps); + + rob_chunk_diff = + (mode_lib->ip.rob_buffer_size_kbytes - mode_lib->ip.pixel_chunk_size_kbytes) + * 1024.0; + DTRACE("INTERMEDIATE rob_chunk_diff = %f", rob_chunk_diff); + + if (dcc_enable && return_bw_to_dcn > return_bus_bw / 4) { + double dcc_return_bw = + return_bw_to_dcn * 4.0 + * (1.0 + - soc->urgent_latency_us + / (rob_chunk_diff + / (return_bw_to_dcn + - return_bus_bw + / 4.0) + + soc->urgent_latency_us)); + return_bw_mbps = dml_min(return_bw_mbps, dcc_return_bw); + DTRACE("INTERMEDIATE dcc_return_bw = %f", dcc_return_bw); + } + + urgent_latency_traffic = return_bus_bw * soc->urgent_latency_us; + DTRACE("INTERMEDIATE urgent_latency_traffic = %f", urgent_latency_traffic); + critical_compression = 2.0 * urgent_latency_traffic + / (return_bw_to_dcn * soc->urgent_latency_us + rob_chunk_diff); + DTRACE("INTERMEDIATE critical_compression = %f", critical_compression); + + if (dcc_enable && critical_compression > 1.0 && critical_compression < 4.0) { + double crit_return_bw = (4 * return_bw_to_dcn * rob_chunk_diff + * urgent_latency_traffic); + crit_return_bw = crit_return_bw + / dml_pow( + return_bw_to_dcn * soc->urgent_latency_us + + rob_chunk_diff, + 2); + DTRACE("INTERMEDIATE critical_return_bw = %f", crit_return_bw); + return_bw_mbps = dml_min(return_bw_mbps, crit_return_bw); + } + + /* Gabe does this again for some reason using the value of return_bw_mpbs from the previous calculation + * and a lightly different return_bw_to_dcn + */ + + state = dml_socbb_voltage_scaling(soc, voltage); + return_bw_to_dcn = dml_min( + soc->return_bus_width_bytes * dcfclk_mhz, + state.dram_bw_per_chan_gbps * 1000.0 * (double) soc->num_chans); + + DTRACE("INTERMEDIATE rob_chunk_diff = %f", rob_chunk_diff); + + if (dcc_enable && return_bw_to_dcn > return_bus_bw / 4) { + double dcc_return_bw = + return_bw_to_dcn * 4.0 + * (1.0 + - soc->urgent_latency_us + / (rob_chunk_diff + / (return_bw_to_dcn + - return_bus_bw + / 4.0) + + soc->urgent_latency_us)); + return_bw_mbps = dml_min(return_bw_mbps, dcc_return_bw); + DTRACE("INTERMEDIATE dcc_return_bw = %f", dcc_return_bw); + } + + urgent_latency_traffic = return_bus_bw * soc->urgent_latency_us; + DTRACE("INTERMEDIATE urgent_latency_traffic = %f", urgent_latency_traffic); + critical_compression = 2.0 * urgent_latency_traffic + / (return_bw_to_dcn * soc->urgent_latency_us + rob_chunk_diff); + DTRACE("INTERMEDIATE critical_compression = %f", critical_compression); + + /* problem here? */ + if (dcc_enable && critical_compression > 1.0 && critical_compression < 4.0) { + double crit_return_bw = (4 * return_bw_to_dcn * rob_chunk_diff + * urgent_latency_traffic); + crit_return_bw = crit_return_bw + / dml_pow( + return_bw_to_dcn * soc->urgent_latency_us + + rob_chunk_diff, + 2); + DTRACE("INTERMEDIATE critical_return_bw = %f", crit_return_bw); + DTRACE("INTERMEDIATE return_bw_to_dcn = %f", return_bw_to_dcn); + DTRACE("INTERMEDIATE rob_chunk_diff = %f", rob_chunk_diff); + DTRACE("INTERMEDIATE urgent_latency_traffic = %f", urgent_latency_traffic); + + return_bw_mbps = dml_min(return_bw_mbps, crit_return_bw); + } + + DTRACE("INTERMEDIATE final return_bw_mbps = %f", return_bw_mbps); + return return_bw_mbps; +} + +double dml_wm_calc_return_bw( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *planes, + unsigned int num_planes) +{ + return calc_return_bw(mode_lib, planes, num_planes); +} + +static double calc_last_pixel_of_line_extra_wm_us( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *planes, + unsigned int num_planes) +{ + double val = 0.0; + double total_data_read_bw = calc_total_data_read_bw(mode_lib, planes, num_planes); + int voltage = -1; + unsigned int i; + double return_bw_mbps; + + for (i = 0; i < num_planes; i++) { + /* voltage mode must be the same for all pipes */ + ASSERT(voltage == -1 || voltage == planes[i].voltage); + voltage = planes[i].voltage; + } + return_bw_mbps = calc_return_bw(mode_lib, planes, num_planes); + + for (i = 0; i < num_planes; i++) { + double bytes_pp_y = dml_ceil(planes[i].bytes_per_pixel_y); + double bytes_pp_c = dml_ceil_2(planes[i].bytes_per_pixel_c); + double swath_bytes_y = (double) planes[i].swath_width_y + * (double) planes[i].swath_height_y * (double) bytes_pp_y; + double swath_bytes_c = ((double) planes[i].swath_width_y / 2.0) + * (double) planes[i].swath_height_c * (double) bytes_pp_c; + double data_fabric_line_delivery_time = (swath_bytes_y + swath_bytes_c) + / (return_bw_mbps * planes[i].read_bw / (double) planes[i].num_dpp + / total_data_read_bw); + + DTRACE( + "bytes_pp_y = %f, swath_width_y = %f, swath_height_y = %f, swath_bytes_y = %f", + bytes_pp_y, + (double) planes[i].swath_width_y, + (double) planes[i].swath_height_y, + swath_bytes_y); + DTRACE( + "bytes_pp_c = %f, swath_width_c = %f, swath_height_c = %f, swath_bytes_c = %f", + bytes_pp_c, + ((double) planes[i].swath_width_y / 2.0), + (double) planes[i].swath_height_c, + swath_bytes_c); + DTRACE( + "return_bw_mbps = %f, read_bw = %f, num_dpp = %d, total_data_read_bw = %f", + return_bw_mbps, + planes[i].read_bw, + planes[i].num_dpp, + total_data_read_bw); + DTRACE("data_fabric_line_delivery_time = %f", data_fabric_line_delivery_time); + DTRACE( + "display_pipe_line_delivery_time = %f", + planes[i].display_pipe_line_delivery_time); + + val = dml_max( + val, + data_fabric_line_delivery_time + - planes[i].display_pipe_line_delivery_time); + } + + DTRACE("last_pixel_of_line_extra_wm is %f us", val); + return val; +} + +static bool calc_pte_enable(struct _vcs_dpi_wm_calc_pipe_params_st *planes, unsigned int num_planes) +{ + unsigned int i; + + for (i = 0; i < num_planes; i++) { + if (planes[i].pte_enable) { + return true; + } + } + + return false; +} + +static void calc_lines_in_det_y(struct _vcs_dpi_wm_calc_pipe_params_st *plane) +{ + plane->lines_in_det_y = plane->det_buffer_size_y / plane->bytes_per_pixel_y + / plane->swath_width_y; + plane->lines_in_det_y_rounded_down_to_swath = dml_floor( + (double) plane->lines_in_det_y / plane->swath_height_y) + * plane->swath_height_y; + plane->full_det_buffering_time = plane->lines_in_det_y_rounded_down_to_swath + * (plane->h_total / plane->pixclk_mhz); +} + +/* CHECKME: not obviously 1:1 with calculation described in architectural + * document or spreadsheet */ +static void calc_dcfclk_deepsleep_mhz_per_plane( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *plane) +{ + double bus_width_per_pixel; + + if (plane->swath_height_c == 0) { + bus_width_per_pixel = dml_ceil(plane->bytes_per_pixel_y) / 64; + } else { + double bus_width_per_pixel_c; + + bus_width_per_pixel = dml_ceil(plane->bytes_per_pixel_y) / 32; + bus_width_per_pixel_c = dml_ceil(plane->bytes_per_pixel_c) / 32; + if (bus_width_per_pixel < bus_width_per_pixel_c) + bus_width_per_pixel = bus_width_per_pixel_c; + } + + if (plane->v_ratio <= 1) { + plane->dcfclk_deepsleep_mhz_per_plane = 1.1 * plane->pixclk_mhz / plane->num_dpp + * plane->h_ratio * bus_width_per_pixel; + } else if (plane->h_ratio > 1) { + double num_hscl_kernels = dml_ceil((double) plane->h_taps / 6); + double dchub_pscl_bw_per_clk = dml_min( + (double) mode_lib->ip.max_dchub_pscl_bw_pix_per_clk, + mode_lib->ip.max_pscl_lb_bw_pix_per_clk * plane->h_ratio + / num_hscl_kernels); + + plane->dcfclk_deepsleep_mhz_per_plane = 1.1 * plane->dppclk_mhz + * dchub_pscl_bw_per_clk * bus_width_per_pixel; + } else { + double dchub_pscl_bw_per_clk = dml_min( + (double) mode_lib->ip.max_dchub_pscl_bw_pix_per_clk, + (double) mode_lib->ip.max_pscl_lb_bw_pix_per_clk); + + plane->dcfclk_deepsleep_mhz_per_plane = 1.1 * plane->dppclk_mhz + * dchub_pscl_bw_per_clk * bus_width_per_pixel; + } + + plane->dcfclk_deepsleep_mhz_per_plane = dml_max( + plane->dcfclk_deepsleep_mhz_per_plane, + plane->pixclk_mhz / 16); +} + +/* Implementation of expected stutter efficiency from DCN1_Display_Mode.docx */ +double dml_wm_expected_stutter_eff_e2e( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_pipes) +{ + double min_full_det_buffering_time_us; + double frame_time_for_min_full_det_buffering_time_us = 0.0; + struct _vcs_dpi_wm_calc_pipe_params_st *planes = mode_lib->wm_param; + unsigned int num_planes; + unsigned int i; + double total_data_read_bw_mbps; + double average_read_bw_gbps; + double min_full_det_buffer_size_bytes; + double rob_fill_size_bytes; + double part_of_burst_that_fits_in_rob; + int voltage; + double dcfclk_mhz; + unsigned int total_writeback; + double return_bw_mbps; + double stutter_burst_time_us; + double stutter_eff_not_including_vblank; + double smallest_vblank_us; + double stutter_eff; + + memset(mode_lib->wm_param, 0, sizeof(mode_lib->wm_param)); + DTRACE("calculating expected stutter efficiency"); + + num_planes = dml_wm_e2e_to_wm(mode_lib, e2e, num_pipes, planes); + + for (i = 0; i < num_planes; i++) { + calc_lines_in_det_y(&planes[i]); + + DTRACE("swath width y plane %d = %d", i, planes[i].swath_width_y); + DTRACE("swath height y plane %d = %d", i, planes[i].swath_height_y); + DTRACE( + "bytes per pixel det y plane %d = %f", + i, + planes[i].bytes_per_pixel_y); + DTRACE( + "bytes per pixel det c plane %d = %f", + i, + planes[i].bytes_per_pixel_c); + DTRACE( + "det buffer size plane %d = %d", + i, + planes[i].det_buffer_size_y); + DTRACE("lines in det plane %d = %d", i, planes[i].lines_in_det_y); + DTRACE( + "lines in det rounded to swaths plane %d = %d", + i, + planes[i].lines_in_det_y_rounded_down_to_swath); + } + + min_full_det_buffering_time_us = 9999.0; + for (i = 0; i < num_planes; i++) { + if (planes[i].full_det_buffering_time < min_full_det_buffering_time_us) { + min_full_det_buffering_time_us = planes[i].full_det_buffering_time; + frame_time_for_min_full_det_buffering_time_us = (double) planes[i].v_total + * planes[i].h_total / planes[i].pixclk_mhz; + } + } + + DTRACE("INTERMEDIATE: min_full_det_buffering_time_us = %f", min_full_det_buffering_time_us); + + total_data_read_bw_mbps = calc_total_data_read_bw(mode_lib, planes, num_planes); + + average_read_bw_gbps = 0.0; + + for (i = 0; i < num_planes; i++) { + if (planes[i].dcc_enable) { + average_read_bw_gbps += planes[i].read_bw / planes[i].dcc_rate / 1000; + } else { + average_read_bw_gbps += planes[i].read_bw / 1000; + } + + if (planes[i].dcc_enable) { + average_read_bw_gbps += planes[i].read_bw / 1000 / 256; + } + + if (planes[i].pte_enable) { + average_read_bw_gbps += planes[i].read_bw / 1000 / 512; + } + } + + min_full_det_buffer_size_bytes = min_full_det_buffering_time_us * total_data_read_bw_mbps; + rob_fill_size_bytes = mode_lib->ip.rob_buffer_size_kbytes * 1024 * total_data_read_bw_mbps + / (average_read_bw_gbps * 1000); + part_of_burst_that_fits_in_rob = dml_min( + min_full_det_buffer_size_bytes, + rob_fill_size_bytes); + + voltage = -1; + dcfclk_mhz = -1.0; + total_writeback = 0; + + for (i = 0; i < num_pipes; i++) { + /* voltage and dcfclk must be the same for all pipes */ + ASSERT(voltage == -1 || voltage == e2e[i].clks_cfg.voltage); + voltage = e2e[i].clks_cfg.voltage; + ASSERT(dcfclk_mhz == -1.0 || dcfclk_mhz == e2e[i].clks_cfg.dcfclk_mhz); + dcfclk_mhz = e2e[i].clks_cfg.dcfclk_mhz; + + if (e2e[i].dout.output_type == dm_wb) + total_writeback++; + } + + return_bw_mbps = calc_return_bw(mode_lib, planes, num_planes); + + DTRACE("INTERMEDIATE: part_of_burst_that_fits_in_rob = %f", part_of_burst_that_fits_in_rob); + DTRACE("INTERMEDIATE: average_read_bw_gbps = %f", average_read_bw_gbps); + DTRACE("INTERMEDIATE: total_data_read_bw_mbps = %f", total_data_read_bw_mbps); + DTRACE("INTERMEDIATE: return_bw_mbps = %f", return_bw_mbps); + + stutter_burst_time_us = part_of_burst_that_fits_in_rob * (average_read_bw_gbps * 1000) + / total_data_read_bw_mbps / return_bw_mbps + + (min_full_det_buffering_time_us * total_data_read_bw_mbps + - part_of_burst_that_fits_in_rob) / (dcfclk_mhz * 64); + DTRACE("INTERMEDIATE: stutter_burst_time_us = %f", stutter_burst_time_us); + + if (total_writeback == 0) { + stutter_eff_not_including_vblank = (1.0 + - ((mode_lib->soc.sr_exit_time_us + stutter_burst_time_us) + / min_full_det_buffering_time_us)) * 100.0; + } else { + stutter_eff_not_including_vblank = 0.0; + } + + DTRACE("stutter_efficiency_not_including_vblank = %f", stutter_eff_not_including_vblank); + + smallest_vblank_us = 9999.0; + + for (i = 0; i < num_pipes; i++) { + double vblank_us; + if (e2e[i].pipe.dest.syncronized_vblank_all_planes != 0 || num_pipes == 1) { + vblank_us = (double) (e2e[i].pipe.dest.vtotal + 1 + - e2e[i].pipe.dest.vblank_start + + e2e[i].pipe.dest.vblank_end * e2e[i].pipe.dest.htotal) + / e2e[i].pipe.dest.pixel_rate_mhz; + } else { + vblank_us = 0.0; + } + + smallest_vblank_us = dml_min(smallest_vblank_us, vblank_us); + } + + DTRACE("smallest vblank = %f us", smallest_vblank_us); + + stutter_eff = 100.0 + * (((stutter_eff_not_including_vblank / 100.0) + * (frame_time_for_min_full_det_buffering_time_us + - smallest_vblank_us) + smallest_vblank_us) + / frame_time_for_min_full_det_buffering_time_us); + + DTRACE("stutter_efficiency = %f", stutter_eff); + + return stutter_eff_not_including_vblank; +} + +double dml_wm_expected_stutter_eff_e2e_with_vblank( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_pipes) +{ + double min_full_det_buffering_time_us; + double frame_time_for_min_full_det_buffering_time_us = 0.0; + struct _vcs_dpi_wm_calc_pipe_params_st *planes = mode_lib->wm_param; + unsigned int num_planes; + unsigned int i; + double total_data_read_bw_mbps; + double average_read_bw_gbps; + double min_full_det_buffer_size_bytes; + double rob_fill_size_bytes; + double part_of_burst_that_fits_in_rob; + int voltage; + double dcfclk_mhz; + unsigned int total_writeback; + double return_bw_mbps; + double stutter_burst_time_us; + double stutter_eff_not_including_vblank; + double smallest_vblank_us; + double stutter_eff; + + memset(mode_lib->wm_param, 0, sizeof(mode_lib->wm_param)); + num_planes = dml_wm_e2e_to_wm(mode_lib, e2e, num_pipes, planes); + + for (i = 0; i < num_planes; i++) { + calc_lines_in_det_y(&planes[i]); + } + + min_full_det_buffering_time_us = 9999.0; + for (i = 0; i < num_planes; i++) { + if (planes[i].full_det_buffering_time < min_full_det_buffering_time_us) { + min_full_det_buffering_time_us = planes[i].full_det_buffering_time; + frame_time_for_min_full_det_buffering_time_us = (double) planes[i].v_total + * planes[i].h_total / planes[i].pixclk_mhz; + } + } + + total_data_read_bw_mbps = calc_total_data_read_bw(mode_lib, planes, num_planes); + average_read_bw_gbps = 0.0; + + for (i = 0; i < num_planes; i++) { + if (planes[i].dcc_enable) { + average_read_bw_gbps += planes[i].read_bw / planes[i].dcc_rate / 1000; + } else { + average_read_bw_gbps += planes[i].read_bw / 1000; + } + + if (planes[i].dcc_enable) { + average_read_bw_gbps += planes[i].read_bw / 1000 / 256; + } + + if (planes[i].pte_enable) { + average_read_bw_gbps += planes[i].read_bw / 1000 / 512; + } + } + + min_full_det_buffer_size_bytes = min_full_det_buffering_time_us * total_data_read_bw_mbps; + rob_fill_size_bytes = mode_lib->ip.rob_buffer_size_kbytes * 1024 * total_data_read_bw_mbps + / (average_read_bw_gbps * 1000); + part_of_burst_that_fits_in_rob = dml_min( + min_full_det_buffer_size_bytes, + rob_fill_size_bytes); + + voltage = -1; + dcfclk_mhz = -1.0; + total_writeback = 0; + + for (i = 0; i < num_pipes; i++) { + /* voltage and dcfclk must be the same for all pipes */ + ASSERT(voltage == -1 || voltage == e2e[i].clks_cfg.voltage); + voltage = e2e[i].clks_cfg.voltage; + ASSERT(dcfclk_mhz == -1.0 || dcfclk_mhz == e2e[i].clks_cfg.dcfclk_mhz); + dcfclk_mhz = e2e[i].clks_cfg.dcfclk_mhz; + + if (e2e[i].dout.output_type == dm_wb) + total_writeback++; + } + + return_bw_mbps = calc_return_bw(mode_lib, planes, num_planes); + + stutter_burst_time_us = part_of_burst_that_fits_in_rob * (average_read_bw_gbps * 1000) + / total_data_read_bw_mbps / return_bw_mbps + + (min_full_det_buffering_time_us * total_data_read_bw_mbps + - part_of_burst_that_fits_in_rob) / (dcfclk_mhz * 64); + + if (total_writeback == 0) { + stutter_eff_not_including_vblank = (1.0 + - ((mode_lib->soc.sr_exit_time_us + stutter_burst_time_us) + / min_full_det_buffering_time_us)) * 100.0; + } else { + stutter_eff_not_including_vblank = 0.0; + } + + smallest_vblank_us = 9999.0; + + for (i = 0; i < num_pipes; i++) { + double vblank_us; + if (e2e[i].pipe.dest.syncronized_vblank_all_planes != 0 || num_pipes == 1) { + vblank_us = (double) (e2e[i].pipe.dest.vtotal + 1 + - e2e[i].pipe.dest.vblank_start + + e2e[i].pipe.dest.vblank_end * e2e[i].pipe.dest.htotal) + / e2e[i].pipe.dest.pixel_rate_mhz; + } else { + vblank_us = 0.0; + } + + smallest_vblank_us = dml_min(smallest_vblank_us, vblank_us); + } + + stutter_eff = 100.0 + * (((stutter_eff_not_including_vblank / 100.0) + * (frame_time_for_min_full_det_buffering_time_us + - smallest_vblank_us) + smallest_vblank_us) + / frame_time_for_min_full_det_buffering_time_us); + + + return stutter_eff; +} + +double urgent_extra_calc( + struct display_mode_lib *mode_lib, + double dcfclk_mhz, + double return_bw_mbps, + unsigned int total_active_dpp, + unsigned int total_dcc_active_dpp) +{ + double urgent_extra_latency_us = 0.0; + double urgent_round_trip_ooo_latency_us; + + urgent_round_trip_ooo_latency_us = + (((double) mode_lib->soc.round_trip_ping_latency_dcfclk_cycles + 32) + / dcfclk_mhz) + + (((double) (mode_lib->soc.urgent_out_of_order_return_per_channel_bytes + * mode_lib->soc.num_chans)) / return_bw_mbps); + + DTRACE( + "INTERMEDIATE round_trip_ping_latency_dcfclk_cycles = %d", + mode_lib->soc.round_trip_ping_latency_dcfclk_cycles); + DTRACE("INTERMEDIATE dcfclk_mhz = %f", dcfclk_mhz); + DTRACE( + "INTERMEDIATE urgent_out_of_order_return_per_channel_bytes = %d", + mode_lib->soc.urgent_out_of_order_return_per_channel_bytes); + + urgent_extra_latency_us = urgent_round_trip_ooo_latency_us + + ((double) total_active_dpp * mode_lib->ip.pixel_chunk_size_kbytes + + (double) total_dcc_active_dpp + * mode_lib->ip.meta_chunk_size_kbytes) + * 1024.0 / return_bw_mbps; /* to us */ + + DTRACE( + "INTERMEDIATE urgent_round_trip_ooo_latency_us = %f", + urgent_round_trip_ooo_latency_us); + DTRACE("INTERMEDIATE total_active_dpp = %d", total_active_dpp); + DTRACE( + "INTERMEDIATE pixel_chunk_size_kbytes = %d", + mode_lib->ip.pixel_chunk_size_kbytes); + DTRACE("INTERMEDIATE total_dcc_active_dpp = %d", total_dcc_active_dpp); + DTRACE( + "INTERMEDIATE meta_chunk_size_kbyte = %d", + mode_lib->ip.meta_chunk_size_kbytes); + DTRACE("INTERMEDIATE return_bw_mbps = %f", return_bw_mbps); + + return urgent_extra_latency_us; +} + +double dml_wm_urgent_extra_max(struct display_mode_lib *mode_lib) +{ + unsigned int total_active_dpp = DC__NUM_DPP; + unsigned int total_dcc_active_dpp = total_active_dpp; + double urgent_extra_latency_us = 0.0; + double dcfclk_mhz = 0.0; + double return_bw_mbps = 0.0; + int voltage = dm_vmin; + + /* use minimum voltage */ + return_bw_mbps = dml_socbb_return_bw_mhz(&mode_lib->soc, (enum voltage_state) voltage); + /* use minimum dcfclk */ + dcfclk_mhz = mode_lib->soc.vmin.dcfclk_mhz; + /* use max dpps and dpps with dcc */ + + urgent_extra_latency_us = urgent_extra_calc( + mode_lib, + dcfclk_mhz, + return_bw_mbps, + total_active_dpp, + total_dcc_active_dpp); + + DTRACE("urgent extra max = %f", urgent_extra_latency_us); + return urgent_extra_latency_us; +} + +double dml_wm_urgent_extra( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *pipes, + unsigned int num_pipes) +{ + unsigned int total_active_dpp = 0; + unsigned int total_dcc_active_dpp = 0; + double urgent_extra_latency_us = 0.0; + double dcfclk_mhz = 0.0; + double return_bw_mbps = 0.0; + int voltage = -1; + bool pte_enable = false; + unsigned int i; + + for (i = 0; i < num_pipes; i++) { + /* num_dpp must be greater than 0 */ + ASSERT(pipes[i].num_dpp > 0); + + /* voltage mode must be the same for all pipes */ + ASSERT(voltage == -1 || voltage == pipes[i].voltage); + voltage = pipes[i].voltage; + + /* dcfclk for all pipes must be the same */ + ASSERT(dcfclk_mhz == 0.0 || dcfclk_mhz == pipes[i].dcfclk_mhz); + dcfclk_mhz = pipes[i].dcfclk_mhz; + + total_active_dpp += pipes[i].num_dpp; + + if (pipes[i].dcc_enable) { + total_dcc_active_dpp += pipes[i].num_dpp; + } + } + + DTRACE("total active dpps %d", total_active_dpp); + DTRACE("total active dpps with dcc %d", total_dcc_active_dpp); + DTRACE("voltage state is %d", voltage); + + return_bw_mbps = calc_return_bw(mode_lib, pipes, num_pipes); + + DTRACE("return_bandwidth is %f MBps", return_bw_mbps); + + pte_enable = calc_pte_enable(pipes, num_pipes); + + /* calculate the maximum extra latency just for comparison purposes */ + /* dml_wm_urgent_extra_max(); */ + urgent_extra_latency_us = urgent_extra_calc( + mode_lib, + dcfclk_mhz, + return_bw_mbps, + total_active_dpp, + total_dcc_active_dpp); + + DTRACE("INTERMEDIATE urgent_extra_latency_us_before_pte = %f", urgent_extra_latency_us); + + if (pte_enable) { + urgent_extra_latency_us += total_active_dpp * mode_lib->ip.pte_chunk_size_kbytes + * 1024.0 / return_bw_mbps; + + DTRACE("INTERMEDIATE pte_enable = true"); + DTRACE("INTERMEDIATE total_active_dpp = %d", total_active_dpp); + DTRACE( + "INTERMEDIATE pte_chunk_size_kbytes = %d", + mode_lib->ip.pte_chunk_size_kbytes); + DTRACE("INTERMEDIATE return_bw_mbps = %f", return_bw_mbps); + } + + return urgent_extra_latency_us; +} + +double dml_wm_urgent_e2e( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *pipes, + unsigned int num_pipes) +{ + struct _vcs_dpi_wm_calc_pipe_params_st *wm = mode_lib->wm_param; + unsigned int combined_pipes; + double urgent_wm; + + memset(mode_lib->wm_param, 0, sizeof(mode_lib->wm_param)); + combined_pipes = dml_wm_e2e_to_wm(mode_lib, pipes, num_pipes, wm); + + urgent_wm = dml_wm_urgent(mode_lib, wm, combined_pipes); + + return urgent_wm; +} + +double dml_wm_urgent( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *planes, + unsigned int num_planes) +{ + double urgent_watermark; + double urgent_extra_latency_us; + double last_pixel_of_line_extra_wm_us = 0.0; + + DTRACE("calculating urgent watermark"); + calc_display_pipe_line_delivery_time(mode_lib, planes, num_planes); + urgent_extra_latency_us = dml_wm_urgent_extra(mode_lib, planes, num_planes); + + last_pixel_of_line_extra_wm_us = calc_last_pixel_of_line_extra_wm_us( + mode_lib, + planes, + num_planes); + + urgent_watermark = mode_lib->soc.urgent_latency_us + last_pixel_of_line_extra_wm_us + + urgent_extra_latency_us; + + DTRACE("INTERMEDIATE urgent_latency_us = %f", mode_lib->soc.urgent_latency_us); + DTRACE("INTERMEDIATE last_pixel_of_line_extra_wm_us = %f", last_pixel_of_line_extra_wm_us); + DTRACE("INTERMEDIATE urgent_extra_latency_us = %f", urgent_extra_latency_us); + + DTRACE("urgent_watermark_us = %f", urgent_watermark); + return urgent_watermark; +} + +double dml_wm_pte_meta_urgent(struct display_mode_lib *mode_lib, double urgent_wm_us) +{ + double val; + + val = urgent_wm_us + 2.0 * mode_lib->soc.urgent_latency_us; + DTRACE("pte_meta_urgent_watermark_us = %f", val); + + return val; +} + +double dml_wm_dcfclk_deepsleep_mhz_e2e( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *pipes, + unsigned int num_pipes) +{ + struct _vcs_dpi_wm_calc_pipe_params_st *planes = mode_lib->wm_param; + unsigned int num_planes; + double val; + + memset(mode_lib->wm_param, 0, sizeof(mode_lib->wm_param)); + num_planes = dml_wm_e2e_to_wm(mode_lib, pipes, num_pipes, planes); + + val = dml_wm_dcfclk_deepsleep_mhz(mode_lib, planes, num_planes); + + return val; +} + +double dml_wm_dcfclk_deepsleep_mhz( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *planes, + unsigned int num_planes) +{ + double val = 8.0; + unsigned int i; + + for (i = 0; i < num_planes; i++) { + calc_dcfclk_deepsleep_mhz_per_plane(mode_lib, &planes[i]); + + if (val < planes[i].dcfclk_deepsleep_mhz_per_plane) { + val = planes[i].dcfclk_deepsleep_mhz_per_plane; + } + + DTRACE("plane[%d] start", i); + DTRACE("dcfclk_deepsleep_per_plane = %f", planes[i].dcfclk_deepsleep_mhz_per_plane); + DTRACE("plane[%d] end", i); + } + + DTRACE("dcfclk_deepsleep_mhz = %f", val); + + return val; +} + +struct _vcs_dpi_cstate_pstate_watermarks_st dml_wm_cstate_pstate_e2e( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *pipes, + unsigned int num_pipes) +{ + struct _vcs_dpi_wm_calc_pipe_params_st *wm = mode_lib->wm_param; + unsigned int combined_pipes; + struct _vcs_dpi_cstate_pstate_watermarks_st cstate_pstate_wm; + + memset(mode_lib->wm_param, 0, sizeof(mode_lib->wm_param)); + combined_pipes = dml_wm_e2e_to_wm(mode_lib, pipes, num_pipes, wm); + cstate_pstate_wm = dml_wm_cstate_pstate(mode_lib, wm, combined_pipes); + + + return cstate_pstate_wm; +} + +struct _vcs_dpi_cstate_pstate_watermarks_st dml_wm_cstate_pstate( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *pipes, + unsigned int num_pipes) +{ + struct _vcs_dpi_cstate_pstate_watermarks_st wm; + double urgent_extra_latency_us; + double urgent_watermark_us; + double last_pixel_of_line_extra_wm_us; + double dcfclk_deepsleep_freq; + + DTRACE("calculating cstate and pstate watermarks"); + urgent_extra_latency_us = dml_wm_urgent_extra(mode_lib, pipes, num_pipes); + urgent_watermark_us = dml_wm_urgent(mode_lib, pipes, num_pipes); + + last_pixel_of_line_extra_wm_us = calc_last_pixel_of_line_extra_wm_us( + mode_lib, + pipes, + num_pipes); + dcfclk_deepsleep_freq = dml_wm_dcfclk_deepsleep_mhz(mode_lib, pipes, num_pipes); + + wm.cstate_exit_us = mode_lib->soc.sr_exit_time_us + last_pixel_of_line_extra_wm_us + + urgent_extra_latency_us + + mode_lib->ip.dcfclk_cstate_latency / dcfclk_deepsleep_freq; + wm.cstate_enter_plus_exit_us = mode_lib->soc.sr_enter_plus_exit_time_us + + last_pixel_of_line_extra_wm_us + urgent_extra_latency_us; + wm.pstate_change_us = mode_lib->soc.dram_clock_change_latency_us + urgent_watermark_us; + + DTRACE("stutter_exit_watermark_us = %f", wm.cstate_exit_us); + DTRACE("stutter_enter_plus_exit_watermark_us = %f", wm.cstate_enter_plus_exit_us); + DTRACE("dram_clock_change_watermark_us = %f", wm.pstate_change_us); + + return wm; +} + +double dml_wm_writeback_pstate_e2e( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *pipes, + unsigned int num_pipes) +{ + struct _vcs_dpi_wm_calc_pipe_params_st *wm = mode_lib->wm_param; + unsigned int combined_pipes; + + memset(mode_lib->wm_param, 0, sizeof(mode_lib->wm_param)); + combined_pipes = dml_wm_e2e_to_wm(mode_lib, pipes, num_pipes, wm); + + + return dml_wm_writeback_pstate(mode_lib, wm, combined_pipes); +} + +double dml_wm_writeback_pstate( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *pipes, + unsigned int num_pipes) +{ + unsigned int total_active_wb = 0; + double wm = 0.0; + double socclk_mhz = 0.0; + unsigned int i; + + DTRACE("calculating wb pstate watermark"); + for (i = 0; i < num_pipes; i++) { + if (pipes[i].output_type == dm_wb) + total_active_wb++; + ASSERT(socclk_mhz == 0.0 || socclk_mhz == pipes[i].socclk_mhz); + socclk_mhz = pipes[i].socclk_mhz; + } + + DTRACE("total wb outputs %d", total_active_wb); + DTRACE("socclk frequency %f Mhz", socclk_mhz); + + if (total_active_wb <= 1) { + wm = mode_lib->soc.writeback_dram_clock_change_latency_us; + } else { + wm = mode_lib->soc.writeback_dram_clock_change_latency_us + + (mode_lib->ip.writeback_chunk_size_kbytes * 1024.0) / 32.0 + / socclk_mhz; + } + + DTRACE("wb pstate watermark %f us", wm); + return wm; +} + +unsigned int dml_wm_e2e_to_wm( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_pipes, + struct _vcs_dpi_wm_calc_pipe_params_st *wm) +{ + unsigned int num_planes = 0; + bool visited[DC__NUM_PIPES]; + unsigned int i, j; + + for (i = 0; i < num_pipes; i++) { + visited[i] = false; + } + + for (i = 0; i < num_pipes; i++) { + unsigned int num_dpp = 1; + + if (visited[i]) { + continue; + } + + visited[i] = true; + + if (e2e[i].pipe.src.is_hsplit) { + for (j = i + 1; j < num_pipes; j++) { + if (e2e[j].pipe.src.is_hsplit && !visited[j] + && (e2e[i].pipe.src.hsplit_grp + == e2e[j].pipe.src.hsplit_grp)) { + num_dpp++; + visited[j] = true; + } + } + } + + wm[num_planes].num_dpp = num_dpp; + wm[num_planes].voltage = e2e[i].clks_cfg.voltage; + wm[num_planes].output_type = e2e[i].dout.output_type; + wm[num_planes].dcfclk_mhz = e2e[i].clks_cfg.dcfclk_mhz; + wm[num_planes].socclk_mhz = e2e[i].clks_cfg.socclk_mhz; + wm[num_planes].dppclk_mhz = e2e[i].clks_cfg.dppclk_mhz; + wm[num_planes].pixclk_mhz = e2e[i].pipe.dest.pixel_rate_mhz; + + wm[num_planes].pte_enable = e2e[i].pipe.src.vm; + wm[num_planes].dcc_enable = e2e[i].pipe.src.dcc; + wm[num_planes].dcc_rate = e2e[i].pipe.src.dcc_rate; + + get_bytes_per_pixel( + (enum source_format_class) e2e[i].pipe.src.source_format, + &wm[num_planes]); + wm[num_planes].swath_width_y = get_swath_width_y(&e2e[i].pipe.src, num_dpp); + get_swath_height( + mode_lib, + &e2e[i].pipe.src, + &wm[num_planes], + wm[num_planes].swath_width_y); + + wm[num_planes].interlace_en = e2e[i].pipe.dest.interlaced; + wm[num_planes].h_ratio = e2e[i].pipe.scale_ratio_depth.hscl_ratio; + wm[num_planes].v_ratio = e2e[i].pipe.scale_ratio_depth.vscl_ratio; + if (wm[num_planes].interlace_en) { + wm[num_planes].v_ratio = 2 * wm[num_planes].v_ratio; + } + wm[num_planes].h_taps = e2e[i].pipe.scale_taps.htaps; + wm[num_planes].h_total = e2e[i].pipe.dest.htotal; + wm[num_planes].v_total = e2e[i].pipe.dest.vtotal; + wm[num_planes].v_active = e2e[i].pipe.dest.vactive; + wm[num_planes].e2e_index = i; + num_planes++; + } + + for (i = 0; i < num_planes; i++) { + DTRACE("plane[%d] start", i); + DTRACE("voltage = %d", wm[i].voltage); + DTRACE("v_active = %d", wm[i].v_active); + DTRACE("h_total = %d", wm[i].h_total); + DTRACE("v_total = %d", wm[i].v_total); + DTRACE("pixclk_mhz = %f", wm[i].pixclk_mhz); + DTRACE("dcfclk_mhz = %f", wm[i].dcfclk_mhz); + DTRACE("dppclk_mhz = %f", wm[i].dppclk_mhz); + DTRACE("h_ratio = %f", wm[i].h_ratio); + DTRACE("v_ratio = %f", wm[i].v_ratio); + DTRACE("interlaced = %d", wm[i].interlace_en); + DTRACE("h_taps = %d", wm[i].h_taps); + DTRACE("num_dpp = %d", wm[i].num_dpp); + DTRACE("swath_width_y = %d", wm[i].swath_width_y); + DTRACE("swath_height_y = %d", wm[i].swath_height_y); + DTRACE("swath_height_c = %d", wm[i].swath_height_c); + DTRACE("det_buffer_size_y = %d", wm[i].det_buffer_size_y); + DTRACE("dcc_rate = %f", wm[i].dcc_rate); + DTRACE("dcc_enable = %s", wm[i].dcc_enable ? "true" : "false"); + DTRACE("pte_enable = %s", wm[i].pte_enable ? "true" : "false"); + DTRACE("plane[%d] end", i); + } + + return num_planes; +} diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_watermark.h b/drivers/gpu/drm/amd/display/dc/dml/display_watermark.h new file mode 100644 index 000000000000..94cde8b55e08 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_watermark.h @@ -0,0 +1,98 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef __DISPLAY_WATERMARK_H__ +#define __DISPLAY_WATERMARK_H__ + +#include "dml_common_defs.h" + +struct display_mode_lib; + +double dml_wm_urgent_extra( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *pipes, + unsigned int num_pipes); +double dml_wm_urgent_extra_max(struct display_mode_lib *mode_lib); + +double dml_wm_urgent_e2e( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *pipes, + unsigned int num_pipes); +double dml_wm_urgent( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *planes, + unsigned int num_planes); +double dml_wm_pte_meta_urgent(struct display_mode_lib *mode_lib, double urgent_wm_us); +double dml_wm_dcfclk_deepsleep_mhz_e2e( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *pipes, + unsigned int num_pipes); +double dml_wm_dcfclk_deepsleep_mhz( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *planes, + unsigned int num_planes); + +struct _vcs_dpi_cstate_pstate_watermarks_st dml_wm_cstate_pstate_e2e( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *pipes, + unsigned int num_pipes); +struct _vcs_dpi_cstate_pstate_watermarks_st dml_wm_cstate_pstate( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *pipes, + unsigned int num_pipes); + +double dml_wm_writeback_pstate_e2e( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *pipes, + unsigned int num_pipes); +double dml_wm_writeback_pstate( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *pipes, + unsigned int num_pipes); + +double dml_wm_expected_stutter_eff_e2e( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_pipes); +double dml_wm_expected_stutter_eff_e2e_with_vblank( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_pipes); + +unsigned int dml_wm_e2e_to_wm( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_pipes, + struct _vcs_dpi_wm_calc_pipe_params_st *wm); + +double dml_wm_calc_total_data_read_bw( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *planes, + unsigned int num_planes); +double dml_wm_calc_return_bw( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *planes, + unsigned int num_planes); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c new file mode 100644 index 000000000000..21349a022de3 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c @@ -0,0 +1,148 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dml_common_defs.h" +#include "../calcs/dcn_calc_math.h" + +double dml_min(double a, double b) +{ + return (double) dcn_bw_min2(a, b); +} + +double dml_max(double a, double b) +{ + return (double) dcn_bw_max2(a, b); +} + +double dml_ceil(double a) +{ + return (double) dcn_bw_ceil2(a, 1); +} + +double dml_floor(double a) +{ + return (double) dcn_bw_floor2(a, 1); +} + +double dml_round(double a) +{ + double round_pt = 0.5; + double ceil = dml_ceil(a); + double floor = dml_floor(a); + + if (a - floor >= round_pt) + return ceil; + else + return floor; +} + +int dml_log2(double x) +{ + return dml_round((double)dcn_bw_log(x, 2)); +} + +double dml_pow(double a, int exp) +{ + return (double) dcn_bw_pow(a, exp); +} + +unsigned int dml_round_to_multiple( + unsigned int num, + unsigned int multiple, + bool up) +{ + unsigned int remainder; + + if (multiple == 0) + return num; + + remainder = num % multiple; + + if (remainder == 0) + return num; + + if (up) + return (num + multiple - remainder); + else + return (num - remainder); +} + +double dml_fmod(double f, int val) +{ + return (double) dcn_bw_mod(f, val); +} + +double dml_ceil_2(double f) +{ + return (double) dcn_bw_ceil2(f, 2); +} + +bool dml_util_is_420(enum source_format_class sorce_format) +{ + bool val = false; + + switch (sorce_format) { + case dm_444_16: + val = false; + break; + case dm_444_32: + val = false; + break; + case dm_444_64: + val = false; + break; + case dm_420_8: + val = true; + break; + case dm_420_10: + val = true; + break; + case dm_422_8: + val = false; + break; + case dm_422_10: + val = false; + break; + default: + BREAK_TO_DEBUGGER(); + } + + return val; +} + +double dml_ceil_ex(double x, double granularity) +{ + return (double) dcn_bw_ceil2(x, granularity); +} + +double dml_floor_ex(double x, double granularity) +{ + return (double) dcn_bw_floor2(x, granularity); +} + +double dml_log(double x, double base) +{ + return (double) dcn_bw_log(x, base); +} diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h new file mode 100644 index 000000000000..c5340d41eedb --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h @@ -0,0 +1,51 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef __DC_COMMON_DEFS_H__ +#define __DC_COMMON_DEFS_H__ + +#include "dm_services.h" +#include "dc_features.h" +#include "display_mode_structs.h" +#include "display_mode_enums.h" + +#define DTRACE(str, ...) dm_logger_write(mode_lib->logger, LOG_DML, str, ##__VA_ARGS__); + +double dml_min(double a, double b); +double dml_max(double a, double b); +bool dml_util_is_420(enum source_format_class sorce_format); +double dml_ceil_ex(double x, double granularity); +double dml_floor_ex(double x, double granularity); +double dml_log(double x, double base); +double dml_ceil(double a); +double dml_floor(double a); +double dml_round(double a); +int dml_log2(double x); +double dml_pow(double a, int exp); +unsigned int dml_round_to_multiple( + unsigned int num, unsigned int multiple, bool up); +double dml_fmod(double f, int val); +double dml_ceil_2(double f); + +#endif /* __DC_COMMON_DEFS_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c b/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c new file mode 100644 index 000000000000..cb143d3d40f0 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c @@ -0,0 +1,73 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#include "soc_bounding_box.h" +#include "display_mode_lib.h" + +void dml_socbb_set_latencies( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_soc_bounding_box_st *from_box) +{ + struct _vcs_dpi_soc_bounding_box_st *to_box = &mode_lib->soc; + + to_box->dram_clock_change_latency_us = from_box->dram_clock_change_latency_us; + to_box->sr_exit_time_us = from_box->sr_exit_time_us; + to_box->sr_enter_plus_exit_time_us = from_box->sr_enter_plus_exit_time_us; + to_box->urgent_latency_us = from_box->urgent_latency_us; + to_box->writeback_latency_us = from_box->writeback_latency_us; + DTRACE("box.dram_clock_change_latency_us: %f", from_box->dram_clock_change_latency_us); + DTRACE("box.sr_exit_time_us: %f", from_box->sr_exit_time_us); + DTRACE("box.sr_enter_plus_exit_time_us: %f", from_box->sr_enter_plus_exit_time_us); + DTRACE("box.urgent_latency_us: %f", from_box->urgent_latency_us); + DTRACE("box.writeback_latency_us: %f", from_box->writeback_latency_us); + +} + +struct _vcs_dpi_voltage_scaling_st dml_socbb_voltage_scaling( + struct _vcs_dpi_soc_bounding_box_st *box, + enum voltage_state voltage) +{ + switch (voltage) { + case dm_vmin: + return box->vmin; + case dm_vnom: + return box->vnom; + case dm_vmax: + default: + return box->vmax; + } +} + +double dml_socbb_return_bw_mhz(struct _vcs_dpi_soc_bounding_box_st *box, enum voltage_state voltage) +{ + double return_bw; + + struct _vcs_dpi_voltage_scaling_st state = dml_socbb_voltage_scaling(box, voltage); + + return_bw = dml_min( + ((double) box->return_bus_width_bytes) * state.dcfclk_mhz, + state.dram_bw_per_chan_gbps * 1000.0 * (double) box->num_chans + * box->ideal_dram_bw_after_urgent_percent / 100.0); + return return_bw; +} diff --git a/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.h b/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.h new file mode 100644 index 000000000000..7bbae33f163e --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.h @@ -0,0 +1,36 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef __SOC_BOUNDING_BOX_H__ +#define __SOC_BOUNDING_BOX_H__ + +#include "dml_common_defs.h" + +struct display_mode_lib; + +void dml_socbb_set_latencies(struct display_mode_lib *mode_lib, struct _vcs_dpi_soc_bounding_box_st *from_box); +struct _vcs_dpi_voltage_scaling_st dml_socbb_voltage_scaling(struct _vcs_dpi_soc_bounding_box_st *box, enum voltage_state voltage); +double dml_socbb_return_bw_mhz(struct _vcs_dpi_soc_bounding_box_st *box, enum voltage_state voltage); + +#endif -- cgit From 981ab3f1dc3949b45e317e343dfc232a102847aa Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 8 May 2017 15:21:44 -0400 Subject: drm/amdgpu/display: Add gpio support for DCN GPIOs are used for i2c and other things. Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/gpio/dcn10/hw_factory_dcn10.c | 192 ++++++++++ .../amd/display/dc/gpio/dcn10/hw_factory_dcn10.h | 32 ++ .../amd/display/dc/gpio/dcn10/hw_translate_dcn10.c | 408 +++++++++++++++++++++ .../amd/display/dc/gpio/dcn10/hw_translate_dcn10.h | 34 ++ 4 files changed, 666 insertions(+) create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dcn10/hw_factory_dcn10.c create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dcn10/hw_factory_dcn10.h create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dcn10/hw_translate_dcn10.c create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dcn10/hw_translate_dcn10.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dcn10/hw_factory_dcn10.c b/drivers/gpu/drm/amd/display/dc/gpio/dcn10/hw_factory_dcn10.c new file mode 100644 index 000000000000..409763c70ce5 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/dcn10/hw_factory_dcn10.c @@ -0,0 +1,192 @@ +/* + * Copyright 2013-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "include/gpio_types.h" +#include "../hw_factory.h" + + +#include "../hw_gpio.h" +#include "../hw_ddc.h" +#include "../hw_hpd.h" + +#include "hw_factory_dcn10.h" + +#include "raven1/DCN/dcn_1_0_offset.h" +#include "raven1/DCN/dcn_1_0_sh_mask.h" +#include "vega10/soc15ip.h" + +#define block HPD +#define reg_num 0 + +/* set field name */ +#define SF_HPD(reg_name, field_name, post_fix)\ + .field_name = HPD0_ ## reg_name ## __ ## field_name ## post_fix + +#define BASE_INNER(seg) \ + DCE_BASE__INST0_SEG ## seg + +/* compile time expand base address. */ +#define BASE(seg) \ + BASE_INNER(seg) + +#define REG(reg_name)\ + BASE(mm ## reg_name ## _BASE_IDX) + mm ## reg_name + +#define REGI(reg_name, block, id)\ + BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +#include "reg_helper.h" +#include "../hpd_regs.h" + +#define hpd_regs(id) \ +{\ + HPD_REG_LIST(id)\ +} + +static const struct hpd_registers hpd_regs[] = { + hpd_regs(0), + hpd_regs(1), + hpd_regs(2), + hpd_regs(3), + hpd_regs(4), + hpd_regs(5) +}; + +static const struct hpd_sh_mask hpd_shift = { + HPD_MASK_SH_LIST(__SHIFT) +}; + +static const struct hpd_sh_mask hpd_mask = { + HPD_MASK_SH_LIST(_MASK) +}; + +#include "../ddc_regs.h" + + /* set field name */ +#define SF_DDC(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +static const struct ddc_registers ddc_data_regs[] = { + ddc_data_regs(1), + ddc_data_regs(2), + ddc_data_regs(3), + ddc_data_regs(4), + ddc_data_regs(5), + ddc_data_regs(6), + ddc_vga_data_regs, + ddc_i2c_data_regs +}; + +static const struct ddc_registers ddc_clk_regs[] = { + ddc_clk_regs(1), + ddc_clk_regs(2), + ddc_clk_regs(3), + ddc_clk_regs(4), + ddc_clk_regs(5), + ddc_clk_regs(6), + ddc_vga_clk_regs, + ddc_i2c_clk_regs +}; + +static const struct ddc_sh_mask ddc_shift = { + DDC_MASK_SH_LIST(__SHIFT) +}; + +static const struct ddc_sh_mask ddc_mask = { + DDC_MASK_SH_LIST(_MASK) +}; + +static void define_ddc_registers( + struct hw_gpio_pin *pin, + uint32_t en) +{ + struct hw_ddc *ddc = HW_DDC_FROM_BASE(pin); + + switch (pin->id) { + case GPIO_ID_DDC_DATA: + ddc->regs = &ddc_data_regs[en]; + ddc->base.regs = &ddc_data_regs[en].gpio; + break; + case GPIO_ID_DDC_CLOCK: + ddc->regs = &ddc_clk_regs[en]; + ddc->base.regs = &ddc_clk_regs[en].gpio; + break; + default: + ASSERT_CRITICAL(false); + return; + } + + ddc->shifts = &ddc_shift; + ddc->masks = &ddc_mask; + +} + +static void define_hpd_registers(struct hw_gpio_pin *pin, uint32_t en) +{ + struct hw_hpd *hpd = HW_HPD_FROM_BASE(pin); + + hpd->regs = &hpd_regs[en]; + hpd->shifts = &hpd_shift; + hpd->masks = &hpd_mask; + hpd->base.regs = &hpd_regs[en].gpio; +} + + +/* fucntion table */ +static const struct hw_factory_funcs funcs = { + .create_ddc_data = dal_hw_ddc_create, + .create_ddc_clock = dal_hw_ddc_create, + .create_generic = NULL, + .create_hpd = dal_hw_hpd_create, + .create_sync = NULL, + .create_gsl = NULL, + .define_hpd_registers = define_hpd_registers, + .define_ddc_registers = define_ddc_registers +}; +/* + * dal_hw_factory_dcn10_init + * + * @brief + * Initialize HW factory function pointers and pin info + * + * @param + * struct hw_factory *factory - [out] struct of function pointers + */ +void dal_hw_factory_dcn10_init(struct hw_factory *factory) +{ + /*TODO check ASIC CAPs*/ + factory->number_of_pins[GPIO_ID_DDC_DATA] = 8; + factory->number_of_pins[GPIO_ID_DDC_CLOCK] = 8; + factory->number_of_pins[GPIO_ID_GENERIC] = 7; + factory->number_of_pins[GPIO_ID_HPD] = 6; + factory->number_of_pins[GPIO_ID_GPIO_PAD] = 31; + factory->number_of_pins[GPIO_ID_VIP_PAD] = 0; + factory->number_of_pins[GPIO_ID_SYNC] = 2; + factory->number_of_pins[GPIO_ID_GSL] = 4; + + factory->funcs = &funcs; +} diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dcn10/hw_factory_dcn10.h b/drivers/gpu/drm/amd/display/dc/gpio/dcn10/hw_factory_dcn10.h new file mode 100644 index 000000000000..2cc7a585b1f8 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/dcn10/hw_factory_dcn10.h @@ -0,0 +1,32 @@ +/* + * Copyright 2013-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_HW_FACTORY_DCN10_H__ +#define __DAL_HW_FACTORY_DCN10_H__ + +/* Initialize HW factory function pointers and pin info */ +void dal_hw_factory_dcn10_init(struct hw_factory *factory); + +#endif /* __DAL_HW_FACTORY_DCN10_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dcn10/hw_translate_dcn10.c b/drivers/gpu/drm/amd/display/dc/gpio/dcn10/hw_translate_dcn10.c new file mode 100644 index 000000000000..64a6915b846b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/dcn10/hw_translate_dcn10.c @@ -0,0 +1,408 @@ +/* + * Copyright 2013-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +/* + * Pre-requisites: headers required by header of this unit + */ + +#include "hw_translate_dcn10.h" + +#include "dm_services.h" +#include "include/gpio_types.h" +#include "../hw_translate.h" + +#include "raven1/DCN/dcn_1_0_offset.h" +#include "raven1/DCN/dcn_1_0_sh_mask.h" +#include "vega10/soc15ip.h" + +/* begin ********************* + * macros to expend register list macro defined in HW object header file */ + +#define BASE_INNER(seg) \ + DCE_BASE__INST0_SEG ## seg + +/* compile time expand base address. */ +#define BASE(seg) \ + BASE_INNER(seg) + +#define REG(reg_name)\ + BASE(mm ## reg_name ## _BASE_IDX) + mm ## reg_name + +#define REGI(reg_name, block, id)\ + BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +/* macros to expend register list macro defined in HW object header file + * end *********************/ + +static bool offset_to_id( + uint32_t offset, + uint32_t mask, + enum gpio_id *id, + uint32_t *en) +{ + switch (offset) { + /* GENERIC */ + case REG(DC_GPIO_GENERIC_A): + *id = GPIO_ID_GENERIC; + switch (mask) { + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICA_A_MASK: + *en = GPIO_GENERIC_A; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICB_A_MASK: + *en = GPIO_GENERIC_B; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICC_A_MASK: + *en = GPIO_GENERIC_C; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICD_A_MASK: + *en = GPIO_GENERIC_D; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICE_A_MASK: + *en = GPIO_GENERIC_E; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICF_A_MASK: + *en = GPIO_GENERIC_F; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICG_A_MASK: + *en = GPIO_GENERIC_G; + return true; + default: + ASSERT_CRITICAL(false); + return false; + } + break; + /* HPD */ + case REG(DC_GPIO_HPD_A): + *id = GPIO_ID_HPD; + switch (mask) { + case DC_GPIO_HPD_A__DC_GPIO_HPD1_A_MASK: + *en = GPIO_HPD_1; + return true; + case DC_GPIO_HPD_A__DC_GPIO_HPD2_A_MASK: + *en = GPIO_HPD_2; + return true; + case DC_GPIO_HPD_A__DC_GPIO_HPD3_A_MASK: + *en = GPIO_HPD_3; + return true; + case DC_GPIO_HPD_A__DC_GPIO_HPD4_A_MASK: + *en = GPIO_HPD_4; + return true; + case DC_GPIO_HPD_A__DC_GPIO_HPD5_A_MASK: + *en = GPIO_HPD_5; + return true; + case DC_GPIO_HPD_A__DC_GPIO_HPD6_A_MASK: + *en = GPIO_HPD_6; + return true; + default: + ASSERT_CRITICAL(false); + return false; + } + break; + /* SYNCA */ + case REG(DC_GPIO_SYNCA_A): + *id = GPIO_ID_SYNC; + switch (mask) { + case DC_GPIO_SYNCA_A__DC_GPIO_HSYNCA_A_MASK: + *en = GPIO_SYNC_HSYNC_A; + return true; + case DC_GPIO_SYNCA_A__DC_GPIO_VSYNCA_A_MASK: + *en = GPIO_SYNC_VSYNC_A; + return true; + default: + ASSERT_CRITICAL(false); + return false; + } + break; + /* REG(DC_GPIO_GENLK_MASK */ + case REG(DC_GPIO_GENLK_A): + *id = GPIO_ID_GSL; + switch (mask) { + case DC_GPIO_GENLK_A__DC_GPIO_GENLK_CLK_A_MASK: + *en = GPIO_GSL_GENLOCK_CLOCK; + return true; + case DC_GPIO_GENLK_A__DC_GPIO_GENLK_VSYNC_A_MASK: + *en = GPIO_GSL_GENLOCK_VSYNC; + return true; + case DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_A_A_MASK: + *en = GPIO_GSL_SWAPLOCK_A; + return true; + case DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_B_A_MASK: + *en = GPIO_GSL_SWAPLOCK_B; + return true; + default: + ASSERT_CRITICAL(false); + return false; + } + break; + /* DDC */ + /* we don't care about the GPIO_ID for DDC + * in DdcHandle it will use GPIO_ID_DDC_DATA/GPIO_ID_DDC_CLOCK + * directly in the create method */ + case REG(DC_GPIO_DDC1_A): + *en = GPIO_DDC_LINE_DDC1; + return true; + case REG(DC_GPIO_DDC2_A): + *en = GPIO_DDC_LINE_DDC2; + return true; + case REG(DC_GPIO_DDC3_A): + *en = GPIO_DDC_LINE_DDC3; + return true; + case REG(DC_GPIO_DDC4_A): + *en = GPIO_DDC_LINE_DDC4; + return true; + case REG(DC_GPIO_DDC5_A): + *en = GPIO_DDC_LINE_DDC5; + return true; + case REG(DC_GPIO_DDC6_A): + *en = GPIO_DDC_LINE_DDC6; + return true; + case REG(DC_GPIO_DDCVGA_A): + *en = GPIO_DDC_LINE_DDC_VGA; + return true; + /* GPIO_I2CPAD */ + case REG(DC_GPIO_I2CPAD_A): + *en = GPIO_DDC_LINE_I2C_PAD; + return true; + /* Not implemented */ + case REG(DC_GPIO_PWRSEQ_A): + case REG(DC_GPIO_PAD_STRENGTH_1): + case REG(DC_GPIO_PAD_STRENGTH_2): + case REG(DC_GPIO_DEBUG): + return false; + /* UNEXPECTED */ + default: + ASSERT_CRITICAL(false); + return false; + } +} + +static bool id_to_offset( + enum gpio_id id, + uint32_t en, + struct gpio_pin_info *info) +{ + bool result = true; + + switch (id) { + case GPIO_ID_DDC_DATA: + info->mask = DC_GPIO_DDC6_A__DC_GPIO_DDC6DATA_A_MASK; + switch (en) { + case GPIO_DDC_LINE_DDC1: + info->offset = REG(DC_GPIO_DDC1_A); + break; + case GPIO_DDC_LINE_DDC2: + info->offset = REG(DC_GPIO_DDC2_A); + break; + case GPIO_DDC_LINE_DDC3: + info->offset = REG(DC_GPIO_DDC3_A); + break; + case GPIO_DDC_LINE_DDC4: + info->offset = REG(DC_GPIO_DDC4_A); + break; + case GPIO_DDC_LINE_DDC5: + info->offset = REG(DC_GPIO_DDC5_A); + break; + case GPIO_DDC_LINE_DDC6: + info->offset = REG(DC_GPIO_DDC6_A); + break; + case GPIO_DDC_LINE_DDC_VGA: + info->offset = REG(DC_GPIO_DDCVGA_A); + break; + case GPIO_DDC_LINE_I2C_PAD: + info->offset = REG(DC_GPIO_I2CPAD_A); + break; + default: + ASSERT_CRITICAL(false); + result = false; + } + break; + case GPIO_ID_DDC_CLOCK: + info->mask = DC_GPIO_DDC6_A__DC_GPIO_DDC6CLK_A_MASK; + switch (en) { + case GPIO_DDC_LINE_DDC1: + info->offset = REG(DC_GPIO_DDC1_A); + break; + case GPIO_DDC_LINE_DDC2: + info->offset = REG(DC_GPIO_DDC2_A); + break; + case GPIO_DDC_LINE_DDC3: + info->offset = REG(DC_GPIO_DDC3_A); + break; + case GPIO_DDC_LINE_DDC4: + info->offset = REG(DC_GPIO_DDC4_A); + break; + case GPIO_DDC_LINE_DDC5: + info->offset = REG(DC_GPIO_DDC5_A); + break; + case GPIO_DDC_LINE_DDC6: + info->offset = REG(DC_GPIO_DDC6_A); + break; + case GPIO_DDC_LINE_DDC_VGA: + info->offset = REG(DC_GPIO_DDCVGA_A); + break; + case GPIO_DDC_LINE_I2C_PAD: + info->offset = REG(DC_GPIO_I2CPAD_A); + break; + default: + ASSERT_CRITICAL(false); + result = false; + } + break; + case GPIO_ID_GENERIC: + info->offset = REG(DC_GPIO_GENERIC_A); + switch (en) { + case GPIO_GENERIC_A: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICA_A_MASK; + break; + case GPIO_GENERIC_B: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICB_A_MASK; + break; + case GPIO_GENERIC_C: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICC_A_MASK; + break; + case GPIO_GENERIC_D: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICD_A_MASK; + break; + case GPIO_GENERIC_E: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICE_A_MASK; + break; + case GPIO_GENERIC_F: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICF_A_MASK; + break; + case GPIO_GENERIC_G: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICG_A_MASK; + break; + default: + ASSERT_CRITICAL(false); + result = false; + } + break; + case GPIO_ID_HPD: + info->offset = REG(DC_GPIO_HPD_A); + switch (en) { + case GPIO_HPD_1: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD1_A_MASK; + break; + case GPIO_HPD_2: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD2_A_MASK; + break; + case GPIO_HPD_3: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD3_A_MASK; + break; + case GPIO_HPD_4: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD4_A_MASK; + break; + case GPIO_HPD_5: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD5_A_MASK; + break; + case GPIO_HPD_6: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD6_A_MASK; + break; + default: + ASSERT_CRITICAL(false); + result = false; + } + break; + case GPIO_ID_SYNC: + switch (en) { + case GPIO_SYNC_HSYNC_A: + info->offset = REG(DC_GPIO_SYNCA_A); + info->mask = DC_GPIO_SYNCA_A__DC_GPIO_HSYNCA_A_MASK; + break; + case GPIO_SYNC_VSYNC_A: + info->offset = REG(DC_GPIO_SYNCA_A); + info->mask = DC_GPIO_SYNCA_A__DC_GPIO_VSYNCA_A_MASK; + break; + case GPIO_SYNC_HSYNC_B: + case GPIO_SYNC_VSYNC_B: + default: + ASSERT_CRITICAL(false); + result = false; + } + break; + case GPIO_ID_GSL: + switch (en) { + case GPIO_GSL_GENLOCK_CLOCK: + info->offset = REG(DC_GPIO_GENLK_A); + info->mask = DC_GPIO_GENLK_A__DC_GPIO_GENLK_CLK_A_MASK; + break; + case GPIO_GSL_GENLOCK_VSYNC: + info->offset = REG(DC_GPIO_GENLK_A); + info->mask = + DC_GPIO_GENLK_A__DC_GPIO_GENLK_VSYNC_A_MASK; + break; + case GPIO_GSL_SWAPLOCK_A: + info->offset = REG(DC_GPIO_GENLK_A); + info->mask = DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_A_A_MASK; + break; + case GPIO_GSL_SWAPLOCK_B: + info->offset = REG(DC_GPIO_GENLK_A); + info->mask = DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_B_A_MASK; + break; + default: + ASSERT_CRITICAL(false); + result = false; + } + break; + case GPIO_ID_VIP_PAD: + default: + ASSERT_CRITICAL(false); + result = false; + } + + if (result) { + info->offset_y = info->offset + 2; + info->offset_en = info->offset + 1; + info->offset_mask = info->offset - 1; + + info->mask_y = info->mask; + info->mask_en = info->mask; + info->mask_mask = info->mask; + } + + return result; +} + +/* function table */ +static const struct hw_translate_funcs funcs = { + .offset_to_id = offset_to_id, + .id_to_offset = id_to_offset, +}; + +/* + * dal_hw_translate_dcn10_init + * + * @brief + * Initialize Hw translate function pointers. + * + * @param + * struct hw_translate *tr - [out] struct of function pointers + * + */ +void dal_hw_translate_dcn10_init(struct hw_translate *tr) +{ + tr->funcs = &funcs; +} diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dcn10/hw_translate_dcn10.h b/drivers/gpu/drm/amd/display/dc/gpio/dcn10/hw_translate_dcn10.h new file mode 100644 index 000000000000..9edef53c80a0 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/dcn10/hw_translate_dcn10.h @@ -0,0 +1,34 @@ +/* + * Copyright 2013-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_HW_TRANSLATE_DCN10_H__ +#define __DAL_HW_TRANSLATE_DCN10_H__ + +struct hw_translate; + +/* Initialize Hw translate function pointers */ +void dal_hw_translate_dcn10_init(struct hw_translate *tr); + +#endif /* __DAL_HW_TRANSLATE_DCN10_H__ */ -- cgit From f690b1d58002f3adf8c6a3e5b59c637a1cfe3361 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 8 May 2017 15:26:37 -0400 Subject: drm/amdgpu/display: Add i2c/aux support for DCN Implement support for i2c and aux on DCN. Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.c | 125 +++++++++++++++++++++ .../drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.h | 32 ++++++ 2 files changed, 157 insertions(+) create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.c create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.c b/drivers/gpu/drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.c new file mode 100644 index 000000000000..9f17d2e4376b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.c @@ -0,0 +1,125 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "include/i2caux_interface.h" +#include "../i2caux.h" +#include "../engine.h" +#include "../i2c_engine.h" +#include "../i2c_sw_engine.h" +#include "../i2c_hw_engine.h" + +#include "../dce110/aux_engine_dce110.h" +#include "../dce110/i2c_hw_engine_dce110.h" +#include "../dce110/i2caux_dce110.h" + +#include "raven1/DCN/dcn_1_0_offset.h" +#include "raven1/DCN/dcn_1_0_sh_mask.h" +#include "vega10/soc15ip.h" + +/* begin ********************* + * macros to expend register list macro defined in HW object header file */ + +#define BASE_INNER(seg) \ + DCE_BASE__INST0_SEG ## seg + +/* compile time expand base address. */ +#define BASE(seg) \ + BASE_INNER(seg) + +#define SR(reg_name)\ + .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + \ + mm ## reg_name + +#define SRI(reg_name, block, id)\ + .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name +/* macros to expend register list macro defined in HW object header file + * end *********************/ + +#define aux_regs(id)\ +[id] = {\ + AUX_COMMON_REG_LIST(id), \ + .AUX_RESET_MASK = DP_AUX0_AUX_CONTROL__AUX_RESET_MASK \ +} + +#define hw_engine_regs(id)\ +{\ + I2C_HW_ENGINE_COMMON_REG_LIST(id) \ +} + +static const struct dce110_aux_registers dcn10_aux_regs[] = { + aux_regs(0), + aux_regs(1), + aux_regs(2), + aux_regs(3), + aux_regs(4), + aux_regs(5), +}; + +static const struct dce110_i2c_hw_engine_registers dcn10_hw_engine_regs[] = { + hw_engine_regs(1), + hw_engine_regs(2), + hw_engine_regs(3), + hw_engine_regs(4), + hw_engine_regs(5), + hw_engine_regs(6) +}; + +static const struct dce110_i2c_hw_engine_shift i2c_shift = { + I2C_COMMON_MASK_SH_LIST_DCE110(__SHIFT) +}; + +static const struct dce110_i2c_hw_engine_mask i2c_mask = { + I2C_COMMON_MASK_SH_LIST_DCE110(_MASK) +}; + +struct i2caux *dal_i2caux_dcn10_create( + struct dc_context *ctx) +{ + struct i2caux_dce110 *i2caux_dce110 = + dm_alloc(sizeof(struct i2caux_dce110)); + + if (!i2caux_dce110) { + ASSERT_CRITICAL(false); + return NULL; + } + + if (dal_i2caux_dce110_construct( + i2caux_dce110, + ctx, + dcn10_aux_regs, + dcn10_hw_engine_regs, + &i2c_shift, + &i2c_mask)) + return &i2caux_dce110->base; + + ASSERT_CRITICAL(false); + + dm_free(i2caux_dce110); + + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.h b/drivers/gpu/drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.h new file mode 100644 index 000000000000..aeb4a86463d4 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.h @@ -0,0 +1,32 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_I2C_AUX_DCN10_H__ +#define __DAL_I2C_AUX_DCN10_H__ + +struct i2caux *dal_i2caux_dcn10_create( + struct dc_context *ctx); + +#endif /* __DAL_I2C_AUX_DCN10_H__ */ -- cgit From 1909bed5b4ff407130fb9d896565661add3bcdee Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 8 May 2017 15:28:56 -0400 Subject: drm/amdgpu/display: Add irq support for DCN DCN code for display interrupts. Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/irq/dcn10/irq_service_dcn10.c | 361 +++++++++++++++++++++ .../amd/display/dc/irq/dcn10/irq_service_dcn10.h | 34 ++ 2 files changed, 395 insertions(+) create mode 100644 drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c create mode 100644 drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c b/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c new file mode 100644 index 000000000000..7577e2903787 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c @@ -0,0 +1,361 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "include/logger_interface.h" + +#include "../dce110/irq_service_dce110.h" + +#include "raven1/DCN/dcn_1_0_offset.h" +#include "raven1/DCN/dcn_1_0_sh_mask.h" +#include "vega10/soc15ip.h" + +#include "irq_service_dcn10.h" + +#include "ivsrcid/irqsrcs_dcn_1_0.h" + +enum dc_irq_source to_dal_irq_source_dcn10( + struct irq_service *irq_service, + uint32_t src_id, + uint32_t ext_id) +{ + switch (src_id) { + case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP: + return DC_IRQ_SOURCE_VBLANK1; + case DCN_1_0__SRCID__DC_D2_OTG_VSTARTUP: + return DC_IRQ_SOURCE_VBLANK2; + case DCN_1_0__SRCID__DC_D3_OTG_VSTARTUP: + return DC_IRQ_SOURCE_VBLANK3; + case DCN_1_0__SRCID__DC_D4_OTG_VSTARTUP: + return DC_IRQ_SOURCE_VBLANK4; + case DCN_1_0__SRCID__DC_D5_OTG_VSTARTUP: + return DC_IRQ_SOURCE_VBLANK5; + case DCN_1_0__SRCID__DC_D6_OTG_VSTARTUP: + return DC_IRQ_SOURCE_VBLANK6; + case DCN_1_0__SRCID__HUBP0_FLIP_INTERRUPT: + return DC_IRQ_SOURCE_PFLIP1; + case DCN_1_0__SRCID__HUBP1_FLIP_INTERRUPT: + return DC_IRQ_SOURCE_PFLIP2; + case DCN_1_0__SRCID__HUBP2_FLIP_INTERRUPT: + return DC_IRQ_SOURCE_PFLIP3; + case DCN_1_0__SRCID__HUBP3_FLIP_INTERRUPT: + return DC_IRQ_SOURCE_PFLIP4; + case DCN_1_0__SRCID__HUBP4_FLIP_INTERRUPT: + return DC_IRQ_SOURCE_PFLIP5; + case DCN_1_0__SRCID__HUBP5_FLIP_INTERRUPT: + return DC_IRQ_SOURCE_PFLIP6; + + case DCN_1_0__SRCID__DC_HPD1_INT: + /* generic src_id for all HPD and HPDRX interrupts */ + switch (ext_id) { + case DCN_1_0__CTXID__DC_HPD1_INT: + return DC_IRQ_SOURCE_HPD1; + case DCN_1_0__CTXID__DC_HPD2_INT: + return DC_IRQ_SOURCE_HPD2; + case DCN_1_0__CTXID__DC_HPD3_INT: + return DC_IRQ_SOURCE_HPD3; + case DCN_1_0__CTXID__DC_HPD4_INT: + return DC_IRQ_SOURCE_HPD4; + case DCN_1_0__CTXID__DC_HPD5_INT: + return DC_IRQ_SOURCE_HPD5; + case DCN_1_0__CTXID__DC_HPD6_INT: + return DC_IRQ_SOURCE_HPD6; + case DCN_1_0__CTXID__DC_HPD1_RX_INT: + return DC_IRQ_SOURCE_HPD1RX; + case DCN_1_0__CTXID__DC_HPD2_RX_INT: + return DC_IRQ_SOURCE_HPD2RX; + case DCN_1_0__CTXID__DC_HPD3_RX_INT: + return DC_IRQ_SOURCE_HPD3RX; + case DCN_1_0__CTXID__DC_HPD4_RX_INT: + return DC_IRQ_SOURCE_HPD4RX; + case DCN_1_0__CTXID__DC_HPD5_RX_INT: + return DC_IRQ_SOURCE_HPD5RX; + case DCN_1_0__CTXID__DC_HPD6_RX_INT: + return DC_IRQ_SOURCE_HPD6RX; + default: + return DC_IRQ_SOURCE_INVALID; + } + break; + + default: + return DC_IRQ_SOURCE_INVALID; + } +} + +static bool hpd_ack( + struct irq_service *irq_service, + const struct irq_source_info *info) +{ + uint32_t addr = info->status_reg; + uint32_t value = dm_read_reg(irq_service->ctx, addr); + uint32_t current_status = + get_reg_field_value( + value, + HPD0_DC_HPD_INT_STATUS, + DC_HPD_SENSE_DELAYED); + + dal_irq_service_ack_generic(irq_service, info); + + value = dm_read_reg(irq_service->ctx, info->enable_reg); + + set_reg_field_value( + value, + current_status ? 0 : 1, + HPD0_DC_HPD_INT_CONTROL, + DC_HPD_INT_POLARITY); + + dm_write_reg(irq_service->ctx, info->enable_reg, value); + + return true; +} + +static const struct irq_source_info_funcs hpd_irq_info_funcs = { + .set = NULL, + .ack = hpd_ack +}; + +static const struct irq_source_info_funcs hpd_rx_irq_info_funcs = { + .set = NULL, + .ack = NULL +}; + +static const struct irq_source_info_funcs pflip_irq_info_funcs = { + .set = NULL, + .ack = NULL +}; + +static const struct irq_source_info_funcs vblank_irq_info_funcs = { + .set = NULL, + .ack = NULL +}; + +#define BASE_INNER(seg) \ + DCE_BASE__INST0_SEG ## seg + +#define BASE(seg) \ + BASE_INNER(seg) + +#define SRI(reg_name, block, id)\ + BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + + +#define IRQ_REG_ENTRY(block, reg_num, reg1, mask1, reg2, mask2)\ + .enable_reg = SRI(reg1, block, reg_num),\ + .enable_mask = \ + block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\ + .enable_value = {\ + block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\ + ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \ + },\ + .ack_reg = SRI(reg2, block, reg_num),\ + .ack_mask = \ + block ## reg_num ## _ ## reg2 ## __ ## mask2 ## _MASK,\ + .ack_value = \ + block ## reg_num ## _ ## reg2 ## __ ## mask2 ## _MASK \ + +#define hpd_int_entry(reg_num)\ + [DC_IRQ_SOURCE_HPD1 + reg_num] = {\ + IRQ_REG_ENTRY(HPD, reg_num,\ + DC_HPD_INT_CONTROL, DC_HPD_INT_EN,\ + DC_HPD_INT_CONTROL, DC_HPD_INT_ACK),\ + .status_reg = SRI(DC_HPD_INT_STATUS, HPD, reg_num),\ + .funcs = &hpd_irq_info_funcs\ + } + +#define hpd_rx_int_entry(reg_num)\ + [DC_IRQ_SOURCE_HPD1RX + reg_num] = {\ + IRQ_REG_ENTRY(HPD, reg_num,\ + DC_HPD_INT_CONTROL, DC_HPD_RX_INT_EN,\ + DC_HPD_INT_CONTROL, DC_HPD_RX_INT_ACK),\ + .status_reg = SRI(DC_HPD_INT_STATUS, HPD, reg_num),\ + .funcs = &hpd_rx_irq_info_funcs\ + } +#define pflip_int_entry(reg_num)\ + [DC_IRQ_SOURCE_PFLIP1 + reg_num] = {\ + IRQ_REG_ENTRY(HUBPREQ, reg_num,\ + DCSURF_SURFACE_FLIP_INTERRUPT, SURFACE_FLIP_INT_MASK,\ + DCSURF_SURFACE_FLIP_INTERRUPT, SURFACE_FLIP_CLEAR),\ + .funcs = &pflip_irq_info_funcs\ + } + +#define vupdate_int_entry(reg_num)\ + [DC_IRQ_SOURCE_VUPDATE1 + reg_num] = {\ + IRQ_REG_ENTRY(OTG, reg_num,\ + OTG_GLOBAL_SYNC_STATUS, VUPDATE_INT_EN,\ + OTG_GLOBAL_SYNC_STATUS, VUPDATE_EVENT_CLEAR),\ + .funcs = &vblank_irq_info_funcs\ + } + +#define vblank_int_entry(reg_num)\ + [DC_IRQ_SOURCE_VBLANK1 + reg_num] = {\ + IRQ_REG_ENTRY(OTG, reg_num,\ + OTG_GLOBAL_SYNC_STATUS, VSTARTUP_INT_EN,\ + OTG_GLOBAL_SYNC_STATUS, VSTARTUP_EVENT_CLEAR),\ + .funcs = &vblank_irq_info_funcs\ + } + +#define dummy_irq_entry() \ + {\ + .funcs = &dummy_irq_info_funcs\ + } + +#define i2c_int_entry(reg_num) \ + [DC_IRQ_SOURCE_I2C_DDC ## reg_num] = dummy_irq_entry() + +#define dp_sink_int_entry(reg_num) \ + [DC_IRQ_SOURCE_DPSINK ## reg_num] = dummy_irq_entry() + +#define gpio_pad_int_entry(reg_num) \ + [DC_IRQ_SOURCE_GPIOPAD ## reg_num] = dummy_irq_entry() + +#define dc_underflow_int_entry(reg_num) \ + [DC_IRQ_SOURCE_DC ## reg_num ## UNDERFLOW] = dummy_irq_entry() + +static const struct irq_source_info_funcs dummy_irq_info_funcs = { + .set = dal_irq_service_dummy_set, + .ack = dal_irq_service_dummy_ack +}; + +static const struct irq_source_info +irq_source_info_dcn10[DAL_IRQ_SOURCES_NUMBER] = { + [DC_IRQ_SOURCE_INVALID] = dummy_irq_entry(), + hpd_int_entry(0), + hpd_int_entry(1), + hpd_int_entry(2), + hpd_int_entry(3), + hpd_int_entry(4), + hpd_int_entry(5), + hpd_rx_int_entry(0), + hpd_rx_int_entry(1), + hpd_rx_int_entry(2), + hpd_rx_int_entry(3), + hpd_rx_int_entry(4), + hpd_rx_int_entry(5), + i2c_int_entry(1), + i2c_int_entry(2), + i2c_int_entry(3), + i2c_int_entry(4), + i2c_int_entry(5), + i2c_int_entry(6), + dp_sink_int_entry(1), + dp_sink_int_entry(2), + dp_sink_int_entry(3), + dp_sink_int_entry(4), + dp_sink_int_entry(5), + dp_sink_int_entry(6), + [DC_IRQ_SOURCE_TIMER] = dummy_irq_entry(), + pflip_int_entry(0), + pflip_int_entry(1), + pflip_int_entry(2), + pflip_int_entry(3), + [DC_IRQ_SOURCE_PFLIP4] = dummy_irq_entry(), + [DC_IRQ_SOURCE_PFLIP5] = dummy_irq_entry(), + [DC_IRQ_SOURCE_PFLIP_UNDERLAY0] = dummy_irq_entry(), + gpio_pad_int_entry(0), + gpio_pad_int_entry(1), + gpio_pad_int_entry(2), + gpio_pad_int_entry(3), + gpio_pad_int_entry(4), + gpio_pad_int_entry(5), + gpio_pad_int_entry(6), + gpio_pad_int_entry(7), + gpio_pad_int_entry(8), + gpio_pad_int_entry(9), + gpio_pad_int_entry(10), + gpio_pad_int_entry(11), + gpio_pad_int_entry(12), + gpio_pad_int_entry(13), + gpio_pad_int_entry(14), + gpio_pad_int_entry(15), + gpio_pad_int_entry(16), + gpio_pad_int_entry(17), + gpio_pad_int_entry(18), + gpio_pad_int_entry(19), + gpio_pad_int_entry(20), + gpio_pad_int_entry(21), + gpio_pad_int_entry(22), + gpio_pad_int_entry(23), + gpio_pad_int_entry(24), + gpio_pad_int_entry(25), + gpio_pad_int_entry(26), + gpio_pad_int_entry(27), + gpio_pad_int_entry(28), + gpio_pad_int_entry(29), + gpio_pad_int_entry(30), + dc_underflow_int_entry(1), + dc_underflow_int_entry(2), + dc_underflow_int_entry(3), + dc_underflow_int_entry(4), + dc_underflow_int_entry(5), + dc_underflow_int_entry(6), + [DC_IRQ_SOURCE_DMCU_SCP] = dummy_irq_entry(), + [DC_IRQ_SOURCE_VBIOS_SW] = dummy_irq_entry(), + vupdate_int_entry(0), + vupdate_int_entry(1), + vupdate_int_entry(2), + vupdate_int_entry(3), + vupdate_int_entry(4), + vupdate_int_entry(5), + vblank_int_entry(0), + vblank_int_entry(1), + vblank_int_entry(2), + vblank_int_entry(3), + vblank_int_entry(4), + vblank_int_entry(5), +}; + +static const struct irq_service_funcs irq_service_funcs_dcn10 = { + .to_dal_irq_source = to_dal_irq_source_dcn10 +}; + +static bool construct( + struct irq_service *irq_service, + struct irq_service_init_data *init_data) +{ + if (!dal_irq_service_construct(irq_service, init_data)) + return false; + + irq_service->info = irq_source_info_dcn10; + irq_service->funcs = &irq_service_funcs_dcn10; + + return true; +} + +struct irq_service *dal_irq_service_dcn10_create( + struct irq_service_init_data *init_data) +{ + struct irq_service *irq_service = dm_alloc(sizeof(*irq_service)); + + if (!irq_service) + return NULL; + + if (construct(irq_service, init_data)) + return irq_service; + + dm_free(irq_service); + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.h b/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.h new file mode 100644 index 000000000000..fd2ca4d0c316 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.h @@ -0,0 +1,34 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_IRQ_SERVICE_DCN10_H__ +#define __DAL_IRQ_SERVICE_DCN10_H__ + +#include "../irq_service.h" + +struct irq_service *dal_irq_service_dcn10_create( + struct irq_service_init_data *init_data); + +#endif -- cgit From ff5ef99248662ef98a64c11c5370ecd9fbbf57a6 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 15 Jun 2017 16:27:42 -0400 Subject: drm/amdgpu/display: Enable DCN in DC Enable DCN in DC. Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/Kconfig | 7 + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 115 ++++++++- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 3 +- drivers/gpu/drm/amd/display/dc/Makefile | 5 + .../amd/display/dc/bios/command_table_helper2.c | 5 + drivers/gpu/drm/amd/display/dc/calcs/Makefile | 8 + drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 19 ++ drivers/gpu/drm/amd/display/dc/dc.h | 18 ++ drivers/gpu/drm/amd/display/dc/dce/dce_abm.h | 49 ++++ .../gpu/drm/amd/display/dc/dce/dce_clock_source.c | 31 +++ .../gpu/drm/amd/display/dc/dce/dce_clock_source.h | 21 ++ drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c | 15 ++ drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h | 9 + drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c | 245 +++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h | 21 ++ drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h | 15 ++ .../gpu/drm/amd/display/dc/dce/dce_link_encoder.h | 16 +- .../drm/amd/display/dc/dce/dce_stream_encoder.c | 264 +++++++++++++++++++++ .../drm/amd/display/dc/dce/dce_stream_encoder.h | 69 ++++++ .../amd/display/dc/dce110/dce110_hw_sequencer.c | 29 +++ drivers/gpu/drm/amd/display/dc/dm_services.h | 4 + drivers/gpu/drm/amd/display/dc/dm_services_types.h | 1 + drivers/gpu/drm/amd/display/dc/gpio/Makefile | 11 + drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c | 9 +- drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c | 9 + drivers/gpu/drm/amd/display/dc/i2caux/Makefile | 11 + drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c | 8 + drivers/gpu/drm/amd/display/dc/inc/core_dc.h | 5 + drivers/gpu/drm/amd/display/dc/inc/core_types.h | 26 ++ .../gpu/drm/amd/display/dc/inc/hw/display_clock.h | 7 + drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h | 1 + drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h | 41 ++++ drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h | 110 +++++++++ drivers/gpu/drm/amd/display/dc/inc/hw/opp.h | 1 + .../drm/amd/display/dc/inc/hw/timing_generator.h | 16 ++ drivers/gpu/drm/amd/display/dc/irq/Makefile | 10 + drivers/gpu/drm/amd/display/dc/irq/irq_service.c | 5 + drivers/gpu/drm/amd/display/include/dal_asic_id.h | 13 + drivers/gpu/drm/amd/display/include/dal_types.h | 5 +- 39 files changed, 1250 insertions(+), 7 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/Kconfig b/drivers/gpu/drm/amd/display/Kconfig index 47c8e2940a91..5c3bb3581842 100644 --- a/drivers/gpu/drm/amd/display/Kconfig +++ b/drivers/gpu/drm/amd/display/Kconfig @@ -17,6 +17,13 @@ config DRM_AMD_DC_PRE_VEGA by default. This includes Polaris, Carrizo, Tonga, Bonaire, and Hawaii. +config DRM_AMD_DC_DCN1_0 + bool "DCN 1.0 Raven family" + depends on DRM_AMD_DC + help + Choose this option if you want to have + RV family for display engine + config DEBUG_KERNEL_DC bool "Enable kgdb break in DC" depends on DRM_AMD_DC 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 74e32246ff30..4ec86ed5622f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -49,6 +49,16 @@ #include "modules/inc/mod_freesync.h" +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +#include "ivsrcid/irqsrcs_dcn_1_0.h" + +#include "raven1/DCN/dcn_1_0_offset.h" +#include "raven1/DCN/dcn_1_0_sh_mask.h" +#include "vega10/soc15ip.h" + +#include "soc15_common.h" +#endif + static enum drm_plane_type dm_surfaces_type_default[AMDGPU_MAX_PLANES] = { DRM_PLANE_TYPE_PRIMARY, DRM_PLANE_TYPE_PRIMARY, @@ -930,7 +940,8 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev) int i; unsigned client_id = AMDGPU_IH_CLIENTID_LEGACY; - if (adev->asic_type == CHIP_VEGA10) + if (adev->asic_type == CHIP_VEGA10 || + adev->asic_type == CHIP_RAVEN) client_id = AMDGPU_IH_CLIENTID_DCE; int_params.requested_polarity = INTERRUPT_POLARITY_DEFAULT; @@ -1003,6 +1014,92 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev) return 0; } +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +/* Register IRQ sources and initialize IRQ callbacks */ +static int dcn10_register_irq_handlers(struct amdgpu_device *adev) +{ + struct dc *dc = adev->dm.dc; + struct common_irq_params *c_irq_params; + struct dc_interrupt_params int_params = {0}; + int r; + int i; + + int_params.requested_polarity = INTERRUPT_POLARITY_DEFAULT; + int_params.current_polarity = INTERRUPT_POLARITY_DEFAULT; + + /* Actions of amdgpu_irq_add_id(): + * 1. Register a set() function with base driver. + * Base driver will call set() function to enable/disable an + * interrupt in DC hardware. + * 2. Register amdgpu_dm_irq_handler(). + * Base driver will call amdgpu_dm_irq_handler() for ALL interrupts + * coming from DC hardware. + * amdgpu_dm_irq_handler() will re-direct the interrupt to DC + * for acknowledging and handling. + * */ + + /* Use VSTARTUP interrupt */ + for (i = DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP; + i <= DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP + adev->mode_info.num_crtc - 1; + i++) { + r = amdgpu_irq_add_id(adev, AMDGPU_IH_CLIENTID_DCE, i, &adev->crtc_irq); + + if (r) { + DRM_ERROR("Failed to add crtc irq id!\n"); + return r; + } + + int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT; + int_params.irq_source = + dc_interrupt_to_irq_source(dc, i, 0); + + c_irq_params = &adev->dm.vblank_params[int_params.irq_source - DC_IRQ_SOURCE_VBLANK1]; + + c_irq_params->adev = adev; + c_irq_params->irq_src = int_params.irq_source; + + amdgpu_dm_irq_register_interrupt(adev, &int_params, + dm_crtc_high_irq, c_irq_params); + } + + /* Use GRPH_PFLIP interrupt */ + for (i = DCN_1_0__SRCID__HUBP0_FLIP_INTERRUPT; + i <= DCN_1_0__SRCID__HUBP0_FLIP_INTERRUPT + adev->mode_info.num_crtc - 1; + i++) { + r = amdgpu_irq_add_id(adev, AMDGPU_IH_CLIENTID_DCE, i, &adev->pageflip_irq); + if (r) { + DRM_ERROR("Failed to add page flip irq id!\n"); + return r; + } + + int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT; + int_params.irq_source = + dc_interrupt_to_irq_source(dc, i, 0); + + c_irq_params = &adev->dm.pflip_params[int_params.irq_source - DC_IRQ_SOURCE_PFLIP_FIRST]; + + c_irq_params->adev = adev; + c_irq_params->irq_src = int_params.irq_source; + + amdgpu_dm_irq_register_interrupt(adev, &int_params, + dm_pflip_high_irq, c_irq_params); + + } + + /* HPD */ + r = amdgpu_irq_add_id(adev, AMDGPU_IH_CLIENTID_DCE, DCN_1_0__SRCID__DC_HPD1_INT, + &adev->hpd_irq); + if (r) { + DRM_ERROR("Failed to add hpd irq id!\n"); + return r; + } + + register_hpd_handlers(adev); + + return 0; +} +#endif + static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev) { int r; @@ -1172,6 +1269,14 @@ int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) goto fail_free_encoder; } break; +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + case CHIP_RAVEN: + if (dcn10_register_irq_handlers(dm->adev)) { + DRM_ERROR("DM: Failed to initialize IRQ\n"); + goto fail_free_encoder; + } + break; +#endif default: DRM_ERROR("Usupported ASIC type: 0x%X\n", adev->asic_type); goto fail_free_encoder; @@ -1447,6 +1552,14 @@ static int dm_early_init(void *handle) adev->mode_info.num_dig = 6; adev->mode_info.plane_type = dm_surfaces_type_default; break; +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + case CHIP_RAVEN: + adev->mode_info.num_crtc = 4; + adev->mode_info.num_hpd = 4; + adev->mode_info.num_dig = 4; + adev->mode_info.plane_type = dm_surfaces_type_default; + break; +#endif default: DRM_ERROR("Usupported ASIC type: 0x%X\n", adev->asic_type); return -EINVAL; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 0f09e8b903d3..bca6769e7481 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -562,7 +562,8 @@ static void fill_plane_attributes_from_fb( surface->tiling_info.gfx8.pipe_config = AMDGPU_TILING_GET(tiling_flags, PIPE_CONFIG); - if (adev->asic_type == CHIP_VEGA10) { + if (adev->asic_type == CHIP_VEGA10 || + adev->asic_type == CHIP_RAVEN) { /* Fill GFX9 params */ surface->tiling_info.gfx9.num_pipes = adev->gfx.config.gb_addr_config_fields.num_pipes; diff --git a/drivers/gpu/drm/amd/display/dc/Makefile b/drivers/gpu/drm/amd/display/dc/Makefile index 1a79762425ea..4f83e3011743 100644 --- a/drivers/gpu/drm/amd/display/dc/Makefile +++ b/drivers/gpu/drm/amd/display/dc/Makefile @@ -4,7 +4,12 @@ DC_LIBS = basics bios calcs dce gpio i2caux irq virtual +ifdef CONFIG_DRM_AMD_DC_DCN1_0 +DC_LIBS += dcn10 dml +endif + DC_LIBS += dce120 + DC_LIBS += dce112 DC_LIBS += dce110 DC_LIBS += dce100 diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c index 1cc3df1d5698..84b1f515aa47 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c @@ -53,6 +53,11 @@ bool dal_bios_parser_init_cmd_tbl_helper2( case DCE_VERSION_11_2: *h = dal_cmd_tbl_helper_dce112_get_table2(); return true; +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + case DCN_VERSION_1_0: + *h = dal_cmd_tbl_helper_dce112_get_table2(); + return true; +#endif case DCE_VERSION_12_0: *h = dal_cmd_tbl_helper_dce112_get_table2(); return true; diff --git a/drivers/gpu/drm/amd/display/dc/calcs/Makefile b/drivers/gpu/drm/amd/display/dc/calcs/Makefile index 63a0edbc32e7..a095472bf4b5 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/Makefile +++ b/drivers/gpu/drm/amd/display/dc/calcs/Makefile @@ -3,8 +3,16 @@ # It calculates Bandwidth and Watermarks values for HW programming # +CFLAGS_dcn_calcs.o := -mhard-float -msse -mpreferred-stack-boundary=4 +CFLAGS_dcn_calc_auto.o := -mhard-float -msse -mpreferred-stack-boundary=4 +CFLAGS_dcn_calc_math.o := -mhard-float -msse -mpreferred-stack-boundary=4 + BW_CALCS = dce_calcs.o bw_fixed.o custom_float.o +ifdef CONFIG_DRM_AMD_DC_DCN1_0 +BW_CALCS += dcn_calcs.o dcn_calc_math.o dcn_calc_auto.o +endif + AMD_DAL_BW_CALCS = $(addprefix $(AMDDALPATH)/dc/calcs/,$(BW_CALCS)) AMD_DISPLAY_FILES += $(AMD_DAL_BW_CALCS) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 2de86f8364a3..ae8b221c85aa 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -39,6 +39,9 @@ #include "dce100/dce100_resource.h" #include "dce110/dce110_resource.h" #include "dce112/dce112_resource.h" +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +#include "dcn10/dcn10_resource.h" +#endif #include "dce120/dce120_resource.h" enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id) @@ -69,6 +72,11 @@ enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id) case FAMILY_AI: dc_version = DCE_VERSION_12_0; break; +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + case FAMILY_RV: + dc_version = DCN_VERSION_1_0; + break; +#endif default: dc_version = DCE_VERSION_UNKNOWN; break; @@ -105,6 +113,13 @@ struct resource_pool *dc_create_resource_pool( res_pool = dce120_create_resource_pool( num_virtual_links, dc); break; + +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + case DCN_VERSION_1_0: + res_pool = dcn10_create_resource_pool( + num_virtual_links, dc); + break; +#endif default: break; } @@ -1188,6 +1203,10 @@ static int acquire_first_free_pipe( pipe_ctx->dis_clk = pool->display_clock; pipe_ctx->pipe_idx = i; +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + pipe_ctx->mpc_idx = -1; +#endif + pipe_ctx->stream = stream; return i; } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 87675f032949..d74bbdce1090 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -94,7 +94,13 @@ struct dc_surface; struct validate_context; struct dc_cap_funcs { +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + bool (*get_dcc_compression_cap)(const struct dc *dc, + const struct dc_dcc_surface_param *input, + struct dc_surface_dcc_cap *output); +#else int i; +#endif }; struct dc_stream_funcs { @@ -164,6 +170,18 @@ struct dc_debug { bool disable_stutter; bool disable_dcc; bool disable_dfs_bypass; +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + bool disable_dpp_power_gate; + bool disable_hubp_power_gate; + bool disable_pplib_wm_range; + bool use_dml_wm; + bool use_max_voltage; + int sr_exit_time_ns; + int sr_enter_plus_exit_time_ns; + int urgent_latency_ns; + int percent_of_ideal_drambw; + int dram_clock_change_latency_ns; +#endif bool disable_pplib_clock_request; bool disable_clock_gate; bool disable_dmcu; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h index 56087b36bdeb..e0abd2d49370 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h @@ -54,6 +54,22 @@ SR(DC_ABM1_HGLS_REG_READ_PROGRESS), \ SR(BIOS_SCRATCH_2) +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + #define ABM_DCN10_REG_LIST(id)\ + ABM_COMMON_REG_LIST_DCE_BASE(), \ + SRI(DC_ABM1_HG_SAMPLE_RATE, ABM, id), \ + SRI(DC_ABM1_LS_SAMPLE_RATE, ABM, id), \ + SRI(BL1_PWM_BL_UPDATE_SAMPLE_RATE, ABM, id), \ + SRI(DC_ABM1_HG_MISC_CTRL, ABM, id), \ + SRI(DC_ABM1_IPCSC_COEFF_SEL, ABM, id), \ + SRI(BL1_PWM_CURRENT_ABM_LEVEL, ABM, id), \ + SRI(BL1_PWM_TARGET_ABM_LEVEL, ABM, id), \ + SRI(BL1_PWM_USER_LEVEL, ABM, id), \ + SRI(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, ABM, id), \ + SRI(DC_ABM1_HGLS_REG_READ_PROGRESS, ABM, id), \ + NBIO_SR(BIOS_SCRATCH_2) +#endif + #define ABM_SF(reg_name, field_name, post_fix)\ .field_name = reg_name ## __ ## field_name ## post_fix @@ -105,6 +121,39 @@ ABM1_BL_REG_READ_MISSED_FRAME_CLEAR, mask_sh) +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + #define ABM_MASK_SH_LIST_DCN10(mask_sh) \ + ABM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh), \ + ABM_SF(ABM0_DC_ABM1_HG_MISC_CTRL, \ + ABM1_HG_NUM_OF_BINS_SEL, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_HG_MISC_CTRL, \ + ABM1_HG_VMAX_SEL, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_HG_MISC_CTRL, \ + ABM1_HG_BIN_BITWIDTH_SIZE_SEL, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_IPCSC_COEFF_SEL, \ + ABM1_IPCSC_COEFF_SEL_R, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_IPCSC_COEFF_SEL, \ + ABM1_IPCSC_COEFF_SEL_G, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_IPCSC_COEFF_SEL, \ + ABM1_IPCSC_COEFF_SEL_B, mask_sh), \ + ABM_SF(ABM0_BL1_PWM_CURRENT_ABM_LEVEL, \ + BL1_PWM_CURRENT_ABM_LEVEL, mask_sh), \ + ABM_SF(ABM0_BL1_PWM_TARGET_ABM_LEVEL, \ + BL1_PWM_TARGET_ABM_LEVEL, mask_sh), \ + ABM_SF(ABM0_BL1_PWM_USER_LEVEL, \ + BL1_PWM_USER_LEVEL, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, \ + ABM1_LS_MIN_PIXEL_VALUE_THRES, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, \ + ABM1_LS_MAX_PIXEL_VALUE_THRES, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_HGLS_REG_READ_PROGRESS, \ + ABM1_HG_REG_READ_MISSED_FRAME_CLEAR, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_HGLS_REG_READ_PROGRESS, \ + ABM1_LS_REG_READ_MISSED_FRAME_CLEAR, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_HGLS_REG_READ_PROGRESS, \ + ABM1_BL_REG_READ_MISSED_FRAME_CLEAR, mask_sh) +#endif + #define ABM_REG_FIELD_LIST(type) \ type ABM1_HG_NUM_OF_BINS_SEL; \ type ABM1_HG_VMAX_SEL; \ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index bd4524ef3a37..142b3a01c204 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -586,6 +586,9 @@ static uint32_t dce110_get_pix_clk_dividers( break; case DCE_VERSION_11_2: case DCE_VERSION_12_0: +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + case DCN_VERSION_1_0: +#endif dce112_get_pix_clk_dividers_helper(clk_src, pll_settings, pix_clk_params); break; @@ -815,6 +818,31 @@ static bool dce110_program_pix_clk( struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source); struct bp_pixel_clock_parameters bp_pc_params = {0}; +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + if (IS_FPGA_MAXIMUS_DC(clock_source->ctx->dce_environment)) { + unsigned int inst = pix_clk_params->controller_id - CONTROLLER_ID_D0; + unsigned dp_dto_ref_kHz = 600000; + /* DPREF clock from FPGA TODO: Does FPGA have this value? */ + unsigned clock_kHz = pll_settings->actual_pix_clk; + + /* For faster simulation, if mode pixe clock less than 290MHz, + * pixel clock can be hard coded to 290Mhz. For 4K mode, pixel clock + * is greater than 500Mhz, need real pixel clock + * clock_kHz = 290000; + */ + /* TODO: un-hardcode when we can set display clock properly*/ + /*clock_kHz = pix_clk_params->requested_pix_clk;*/ + clock_kHz = 290000; + + /* Set DTO values: phase = target clock, modulo = reference clock */ + REG_WRITE(PHASE[inst], clock_kHz); + REG_WRITE(MODULO[inst], dp_dto_ref_kHz); + + /* Enable DTO */ + REG_UPDATE(PIXEL_RATE_CNTL[inst], DP_DTO0_ENABLE, 1); + return true; + } +#endif /* First disable SS * ATOMBIOS will enable by default SS on PLL for DP, * do not disable it here @@ -870,6 +898,9 @@ static bool dce110_program_pix_clk( break; case DCE_VERSION_11_2: case DCE_VERSION_12_0: +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + case DCN_VERSION_1_0: +#endif if (clock_source->id != CLOCK_SOURCE_ID_DP_DTO) { bp_pc_params.flags.SET_GENLOCK_REF_DIV_SRC = pll_settings->use_external_clk; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h index 28984c79fc46..e8bc98b3b622 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h @@ -55,6 +55,27 @@ CS_SF(PHYPLLA_PIXCLK_RESYNC_CNTL, PHYPLLA_DCCG_DEEP_COLOR_CNTL, mask_sh),\ CS_SF(PHYPLLA_PIXCLK_RESYNC_CNTL, PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE, mask_sh) +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +#define CS_COMMON_REG_LIST_DCN1_0(index, pllid) \ + SRI(PIXCLK_RESYNC_CNTL, PHYPLL, pllid),\ + SRII(PHASE, DP_DTO, 0),\ + SRII(PHASE, DP_DTO, 1),\ + SRII(PHASE, DP_DTO, 2),\ + SRII(PHASE, DP_DTO, 3),\ + SRII(MODULO, DP_DTO, 0),\ + SRII(MODULO, DP_DTO, 1),\ + SRII(MODULO, DP_DTO, 2),\ + SRII(MODULO, DP_DTO, 3),\ + SRII(PIXEL_RATE_CNTL, OTG, 0), \ + SRII(PIXEL_RATE_CNTL, OTG, 1), \ + SRII(PIXEL_RATE_CNTL, OTG, 2), \ + SRII(PIXEL_RATE_CNTL, OTG, 3) + +#define CS_COMMON_MASK_SH_LIST_DCN1_0(mask_sh)\ + CS_SF(PHYPLLA_PIXCLK_RESYNC_CNTL, PHYPLLA_DCCG_DEEP_COLOR_CNTL, mask_sh),\ + CS_SF(OTG0_PIXEL_RATE_CNTL, DP_DTO0_ENABLE, mask_sh) +#endif + #define CS_REG_FIELD_LIST(type) \ type PLL_REF_DIV_SRC; \ type DCCG_DEEP_COLOR_CNTL1; \ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c index 81cb138cdc38..6e56d8308d66 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c @@ -29,6 +29,10 @@ #include "fixed32_32.h" #include "bios_parser_interface.h" #include "dc.h" +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +#include "dcn_calcs.h" +#include "core_dc.h" +#endif #define TO_DCE_CLOCKS(clocks)\ container_of(clocks, struct dce_disp_clk, base) @@ -400,6 +404,10 @@ static void dce112_set_clock( bp->funcs->set_dce_clock(bp, &dce_clk_params); +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + dce_psr_wait_loop(clk_dce, requested_clk_khz); +#endif + } static void dce_clock_read_integrated_info(struct dce_disp_clk *clk_dce) @@ -596,6 +604,13 @@ static bool dce_apply_clock_voltage_request( } } if (send_request) { +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + struct core_dc *core_dc = DC_TO_CORE(clk->ctx->dc); + /*use dcfclk request voltage*/ + clock_voltage_req.clk_type = DM_PP_CLOCK_TYPE_DCFCLK; + clock_voltage_req.clocks_in_khz = + dcn_find_dcfclk_suits_all(core_dc, &clk->cur_clocks_value); +#endif dm_pp_apply_clock_for_voltage_request( clk->ctx, &clock_voltage_req); } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h index 29ff470086e5..103e905291a3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h @@ -45,6 +45,15 @@ CLK_SF(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, mask_sh), \ CLK_SF(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, mask_sh) +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +#define CLK_DCN10_REG_LIST()\ + SR(DPREFCLK_CNTL), \ + SR(DENTIST_DISPCLK_CNTL), \ + SR(MASTER_COMM_DATA_REG1), \ + SR(MASTER_COMM_CMD_REG), \ + SR(MASTER_COMM_CNTL_REG) +#endif + #define CLK_COMMON_MASK_SH_LIST_SOC_BASE(mask_sh) \ CLK_SF(DCCG_DFS_DPREFCLK_CNTL, DPREFCLK_SRC_SEL, mask_sh), \ CLK_SF(DCCG_DFS_DENTIST_DISPCLK_CNTL, DENTIST_DPREFCLK_WDIVIDER, mask_sh), \ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c index da7f86b61de4..c58328cd787b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c @@ -252,12 +252,234 @@ static void dce_dmcu_setup_psr(struct dmcu *dmcu, REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); } +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +bool dcn10_dmcu_load_iram(struct dmcu *dmcu, + unsigned int start_offset, + const char *src, + unsigned int bytes) +{ + struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); + unsigned int count = 0; + + REG_UPDATE(DMCU_CTRL, DMCU_ENABLE, 1); + + /* Enable write access to IRAM */ + REG_UPDATE_2(DMCU_RAM_ACCESS_CTRL, + IRAM_HOST_ACCESS_EN, 1, + IRAM_WR_ADDR_AUTO_INC, 1); + + REG_WAIT(DMU_MEM_PWR_CNTL, DMCU_IRAM_MEM_PWR_STATE, 0, 2, 10); + + REG_WRITE(DMCU_IRAM_WR_CTRL, start_offset); + + for (count = 0; count < bytes; count++) + REG_WRITE(DMCU_IRAM_WR_DATA, src[count]); + + /* Disable write access to IRAM to allow dynamic sleep state */ + REG_UPDATE_2(DMCU_RAM_ACCESS_CTRL, + IRAM_HOST_ACCESS_EN, 0, + IRAM_WR_ADDR_AUTO_INC, 0); + + return true; +} + +static void dcn10_get_dmcu_psr_state(struct dmcu *dmcu, uint32_t *psr_state) +{ + struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); + + uint32_t psrStateOffset = 0xf0; + + /* Enable write access to IRAM */ + REG_UPDATE(DMCU_RAM_ACCESS_CTRL, IRAM_HOST_ACCESS_EN, 1); + + REG_WAIT(DMU_MEM_PWR_CNTL, DMCU_IRAM_MEM_PWR_STATE, 0, 2, 10); + + /* Write address to IRAM_RD_ADDR in DMCU_IRAM_RD_CTRL */ + REG_WRITE(DMCU_IRAM_RD_CTRL, psrStateOffset); + + /* Read data from IRAM_RD_DATA in DMCU_IRAM_RD_DATA*/ + *psr_state = REG_READ(DMCU_IRAM_RD_DATA); + + /* Disable write access to IRAM after finished using IRAM + * in order to allow dynamic sleep state + */ + REG_UPDATE(DMCU_RAM_ACCESS_CTRL, IRAM_HOST_ACCESS_EN, 0); +} + +static void dcn10_dmcu_set_psr_enable(struct dmcu *dmcu, bool enable) +{ + struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); + unsigned int dmcu_max_retry_on_wait_reg_ready = 801; + unsigned int dmcu_wait_reg_ready_interval = 100; + + unsigned int retryCount; + uint32_t psr_state = 0; + + /* waitDMCUReadyForCmd */ + REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, + dmcu_wait_reg_ready_interval, + dmcu_max_retry_on_wait_reg_ready); + + /* setDMCUParam_Cmd */ + if (enable) + REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, + PSR_ENABLE); + else + REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, + PSR_EXIT); + + /* notifyDMCUMsg */ + REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); + + /* Below loops 1000 x 500us = 500 ms. + * Exit PSR may need to wait 1-2 frames to power up. Timeout after at + * least a few frames. Should never hit the max retry assert below. + */ + for (retryCount = 0; retryCount <= 1000; retryCount++) { + dcn10_get_dmcu_psr_state(dmcu, &psr_state); + if (enable) { + if (psr_state != 0) + break; + } else { + if (psr_state == 0) + break; + } + dm_delay_in_microseconds(dmcu->ctx, 500); + } + + /* assert if max retry hit */ + ASSERT(retryCount <= 1000); +} + +static void dcn10_dmcu_setup_psr(struct dmcu *dmcu, + struct core_link *link, + struct psr_context *psr_context) +{ + struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); + + unsigned int dmcu_max_retry_on_wait_reg_ready = 801; + unsigned int dmcu_wait_reg_ready_interval = 100; + + union dce_dmcu_psr_config_data_reg1 masterCmdData1; + union dce_dmcu_psr_config_data_reg2 masterCmdData2; + union dce_dmcu_psr_config_data_reg3 masterCmdData3; + + link->link_enc->funcs->psr_program_dp_dphy_fast_training(link->link_enc, + psr_context->psrExitLinkTrainingRequired); + + /* Enable static screen interrupts for PSR supported display */ + /* Disable the interrupt coming from other displays. */ + REG_UPDATE_4(DMCU_INTERRUPT_TO_UC_EN_MASK, + STATIC_SCREEN1_INT_TO_UC_EN, 0, + STATIC_SCREEN2_INT_TO_UC_EN, 0, + STATIC_SCREEN3_INT_TO_UC_EN, 0, + STATIC_SCREEN4_INT_TO_UC_EN, 0); + + switch (psr_context->controllerId) { + /* Driver uses case 1 for unconfigured */ + case 1: + REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK, + STATIC_SCREEN1_INT_TO_UC_EN, 1); + break; + case 2: + REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK, + STATIC_SCREEN2_INT_TO_UC_EN, 1); + break; + case 3: + REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK, + STATIC_SCREEN3_INT_TO_UC_EN, 1); + break; + case 4: + REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK, + STATIC_SCREEN4_INT_TO_UC_EN, 1); + break; + case 5: + /* CZ/NL only has 4 CRTC!! + * really valid. + * There is no interrupt enable mask for these instances. + */ + break; + case 6: + /* CZ/NL only has 4 CRTC!! + * These are here because they are defined in HW regspec, + * but not really valid. There is no interrupt enable mask + * for these instances. + */ + break; + default: + REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK, + STATIC_SCREEN1_INT_TO_UC_EN, 1); + break; + } + + link->link_enc->funcs->psr_program_secondary_packet(link->link_enc, + psr_context->sdpTransmitLineNumDeadline); + + if (psr_context->psr_level.bits.SKIP_SMU_NOTIFICATION) + REG_UPDATE(SMU_INTERRUPT_CONTROL, DC_SMU_INT_ENABLE, 1); + + /* waitDMCUReadyForCmd */ + REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, + dmcu_wait_reg_ready_interval, + dmcu_max_retry_on_wait_reg_ready); + + /* setDMCUParam_PSRHostConfigData */ + masterCmdData1.u32All = 0; + masterCmdData1.bits.timehyst_frames = psr_context->timehyst_frames; + masterCmdData1.bits.hyst_lines = psr_context->hyst_lines; + masterCmdData1.bits.rfb_update_auto_en = + psr_context->rfb_update_auto_en; + masterCmdData1.bits.dp_port_num = psr_context->transmitterId; + masterCmdData1.bits.dcp_sel = psr_context->controllerId; + masterCmdData1.bits.phy_type = psr_context->phyType; + masterCmdData1.bits.frame_cap_ind = + psr_context->psrFrameCaptureIndicationReq; + masterCmdData1.bits.aux_chan = psr_context->channel; + masterCmdData1.bits.aux_repeat = psr_context->aux_repeats; + dm_write_reg(dmcu->ctx, REG(MASTER_COMM_DATA_REG1), + masterCmdData1.u32All); + + masterCmdData2.u32All = 0; + masterCmdData2.bits.dig_fe = psr_context->engineId; + masterCmdData2.bits.dig_be = psr_context->transmitterId; + masterCmdData2.bits.skip_wait_for_pll_lock = + psr_context->skipPsrWaitForPllLock; + masterCmdData2.bits.frame_delay = psr_context->frame_delay; + masterCmdData2.bits.smu_phy_id = psr_context->smuPhyId; + masterCmdData2.bits.num_of_controllers = + psr_context->numberOfControllers; + dm_write_reg(dmcu->ctx, REG(MASTER_COMM_DATA_REG2), + masterCmdData2.u32All); + + masterCmdData3.u32All = 0; + masterCmdData3.bits.psr_level = psr_context->psr_level.u32all; + dm_write_reg(dmcu->ctx, REG(MASTER_COMM_DATA_REG3), + masterCmdData3.u32All); + + /* setDMCUParam_Cmd */ + REG_UPDATE(MASTER_COMM_CMD_REG, + MASTER_COMM_CMD_REG_BYTE0, PSR_SET); + + /* notifyDMCUMsg */ + REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); +} + +#endif + static const struct dmcu_funcs dce_funcs = { .load_iram = dce_dmcu_load_iram, .set_psr_enable = dce_dmcu_set_psr_enable, .setup_psr = dce_dmcu_setup_psr, }; +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +static const struct dmcu_funcs dcn10_funcs = { + .load_iram = dcn10_dmcu_load_iram, + .set_psr_enable = dcn10_dmcu_set_psr_enable, + .setup_psr = dcn10_dmcu_setup_psr, +}; +#endif + static void dce_dmcu_construct( struct dce_dmcu *dmcu_dce, struct dc_context *ctx, @@ -296,6 +518,29 @@ struct dmcu *dce_dmcu_create( return &dmcu_dce->base; } +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +struct dmcu *dcn10_dmcu_create( + struct dc_context *ctx, + const struct dce_dmcu_registers *regs, + const struct dce_dmcu_shift *dmcu_shift, + const struct dce_dmcu_mask *dmcu_mask) +{ + struct dce_dmcu *dmcu_dce = dm_alloc(sizeof(*dmcu_dce)); + + if (dmcu_dce == NULL) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dce_dmcu_construct( + dmcu_dce, ctx, regs, dmcu_shift, dmcu_mask); + + dmcu_dce->base.funcs = &dcn10_funcs; + + return &dmcu_dce->base; +} +#endif + void dce_dmcu_destroy(struct dmcu **dmcu) { struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(*dmcu); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h index 7dc25386c2bf..584682ba1f77 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h @@ -48,6 +48,12 @@ DMCU_COMMON_REG_LIST_DCE_BASE(), \ SR(DCI_MEM_PWR_STATUS) +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + #define DMCU_DCN10_REG_LIST()\ + DMCU_COMMON_REG_LIST_DCE_BASE(), \ + SR(DMU_MEM_PWR_CNTL) +#endif + #define DMCU_SF(reg_name, field_name, post_fix)\ .field_name = reg_name ## __ ## field_name ## post_fix @@ -76,6 +82,13 @@ DMCU_SF(DCI_MEM_PWR_STATUS, \ DMCU_IRAM_MEM_PWR_STATE, mask_sh) +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + #define DMCU_MASK_SH_LIST_DCN10(mask_sh) \ + DMCU_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh), \ + DMCU_SF(DMU_MEM_PWR_CNTL, \ + DMCU_IRAM_MEM_PWR_STATE, mask_sh) +#endif + #define DMCU_REG_FIELD_LIST(type) \ type DMCU_IRAM_MEM_PWR_STATE; \ type IRAM_HOST_ACCESS_EN; \ @@ -190,6 +203,14 @@ struct dmcu *dce_dmcu_create( const struct dce_dmcu_shift *dmcu_shift, const struct dce_dmcu_mask *dmcu_mask); +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +struct dmcu *dcn10_dmcu_create( + struct dc_context *ctx, + const struct dce_dmcu_registers *regs, + const struct dce_dmcu_shift *dmcu_shift, + const struct dce_dmcu_mask *dmcu_mask); +#endif + void dce_dmcu_destroy(struct dmcu **dmcu); #endif /* _DCE_ABM_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index c66585188ecd..dd13f47b6446 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -121,6 +121,12 @@ HWSEQ_PIXEL_RATE_REG_LIST(CRTC), \ HWSEQ_PHYPLL_REG_LIST(CRTC) +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +#define HWSEQ_DCN1_REG_LIST()\ + HWSEQ_PIXEL_RATE_REG_LIST(OTG), \ + HWSEQ_PHYPLL_REG_LIST(OTG) +#endif + struct dce_hwseq_registers { uint32_t DCFE_CLOCK_CONTROL[6]; uint32_t DCFEV_CLOCK_CONTROL; @@ -129,6 +135,9 @@ struct dce_hwseq_registers { uint32_t BLND_CONTROL[6]; uint32_t BLNDV_CONTROL; +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + /* DCE + DCN */ +#endif uint32_t CRTC_H_BLANK_START_END[6]; uint32_t PIXEL_RATE_CNTL[6]; uint32_t PHYPLL_PIXEL_RATE_CNTL[6]; @@ -192,6 +201,12 @@ struct dce_hwseq_registers { HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_),\ HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, CRTC0_) +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +#define HWSEQ_DCN1_MASK_SH_LIST(mask_sh)\ + HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, OTG0_),\ + HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, OTG0_) +#endif + #define HWSEQ_REG_FIED_LIST(type) \ type DCFE_CLOCK_ENABLE; \ type DCFEV_CLOCK_ENABLE; \ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h index 4e0b5d965355..8b04996d5b89 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h @@ -78,6 +78,10 @@ SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ SR(DCI_MEM_PWR_STATUS) +#define LE_DCE80_REG_LIST(id)\ + SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ + LE_COMMON_REG_LIST_BASE(id) + #define LE_DCE100_REG_LIST(id)\ LE_COMMON_REG_LIST_BASE(id), \ SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ @@ -97,9 +101,15 @@ SRI(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id), \ SR(DCI_MEM_PWR_STATUS) -#define LE_DCE80_REG_LIST(id)\ - SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ - LE_COMMON_REG_LIST_BASE(id) +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + #define LE_DCN10_REG_LIST(id)\ + LE_COMMON_REG_LIST_BASE(id), \ + SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ + SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ + SRI(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id), \ + SR(DMU_MEM_PWR_CNTL) +#endif + struct dce110_link_enc_aux_registers { uint32_t AUX_CONTROL; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c index 9713def6e481..a065e4ae6cba 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c @@ -147,6 +147,46 @@ static void dce110_update_generic_info_packet( AFMT_GENERIC0_UPDATE, (packet_index == 0), AFMT_GENERIC2_UPDATE, (packet_index == 2)); } +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + if (REG(AFMT_VBI_PACKET_CONTROL1)) { + switch (packet_index) { + case 0: + REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, + AFMT_GENERIC0_FRAME_UPDATE, 1); + break; + case 1: + REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, + AFMT_GENERIC1_FRAME_UPDATE, 1); + break; + case 2: + REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, + AFMT_GENERIC2_FRAME_UPDATE, 1); + break; + case 3: + REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, + AFMT_GENERIC3_FRAME_UPDATE, 1); + break; + case 4: + REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, + AFMT_GENERIC4_FRAME_UPDATE, 1); + break; + case 5: + REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, + AFMT_GENERIC5_FRAME_UPDATE, 1); + break; + case 6: + REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, + AFMT_GENERIC6_FRAME_UPDATE, 1); + break; + case 7: + REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, + AFMT_GENERIC7_FRAME_UPDATE, 1); + break; + default: + break; + } + } +#endif } static void dce110_update_hdmi_info_packet( @@ -202,6 +242,36 @@ static void dce110_update_hdmi_info_packet( HDMI_GENERIC1_SEND, send, HDMI_GENERIC1_LINE, line); break; +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + case 4: + if (REG(HDMI_GENERIC_PACKET_CONTROL2)) + REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL2, + HDMI_GENERIC0_CONT, cont, + HDMI_GENERIC0_SEND, send, + HDMI_GENERIC0_LINE, line); + break; + case 5: + if (REG(HDMI_GENERIC_PACKET_CONTROL2)) + REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL2, + HDMI_GENERIC1_CONT, cont, + HDMI_GENERIC1_SEND, send, + HDMI_GENERIC1_LINE, line); + break; + case 6: + if (REG(HDMI_GENERIC_PACKET_CONTROL3)) + REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL3, + HDMI_GENERIC0_CONT, cont, + HDMI_GENERIC0_SEND, send, + HDMI_GENERIC0_LINE, line); + break; + case 7: + if (REG(HDMI_GENERIC_PACKET_CONTROL3)) + REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL3, + HDMI_GENERIC1_CONT, cont, + HDMI_GENERIC1_SEND, send, + HDMI_GENERIC1_LINE, line); + break; +#endif default: /* invalid HW packet index */ dm_logger_write( @@ -218,9 +288,24 @@ static void dce110_stream_encoder_dp_set_stream_attribute( struct dc_crtc_timing *crtc_timing, enum dc_color_space output_color_space) { +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + uint32_t h_active_start; + uint32_t v_active_start; + uint32_t misc0 = 0; + uint32_t misc1 = 0; + uint32_t h_blank; + uint32_t h_back_porch; + uint8_t synchronous_clock = 0; /* asynchronous mode */ + uint8_t colorimetry_bpc; +#endif struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + if (REG(DP_DB_CNTL)) + REG_UPDATE(DP_DB_CNTL, DP_DB_DISABLE, 1); +#endif + /* set pixel encoding */ switch (crtc_timing->pixel_encoding) { case PIXEL_ENCODING_YCBCR422: @@ -249,6 +334,10 @@ static void dce110_stream_encoder_dp_set_stream_attribute( if (enc110->se_mask->DP_VID_M_DOUBLE_VALUE_EN) REG_UPDATE(DP_VID_TIMING, DP_VID_M_DOUBLE_VALUE_EN, 1); +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + if (enc110->se_mask->DP_VID_N_MUL) + REG_UPDATE(DP_VID_TIMING, DP_VID_N_MUL, 1); +#endif break; default: REG_UPDATE(DP_PIXEL_FORMAT, DP_PIXEL_ENCODING, @@ -256,6 +345,11 @@ static void dce110_stream_encoder_dp_set_stream_attribute( break; } +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + if (REG(DP_MSA_MISC)) + misc1 = REG_READ(DP_MSA_MISC); +#endif + /* set color depth */ switch (crtc_timing->display_color_depth) { @@ -289,6 +383,128 @@ static void dce110_stream_encoder_dp_set_stream_attribute( DP_DYN_RANGE, 0, DP_YCBCR_RANGE, 0); +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + switch (crtc_timing->display_color_depth) { + case COLOR_DEPTH_666: + colorimetry_bpc = 0; + break; + case COLOR_DEPTH_888: + colorimetry_bpc = 1; + break; + case COLOR_DEPTH_101010: + colorimetry_bpc = 2; + break; + case COLOR_DEPTH_121212: + colorimetry_bpc = 3; + break; + default: + colorimetry_bpc = 0; + break; + } + + misc0 = misc0 | synchronous_clock; + misc0 = colorimetry_bpc << 5; + + if (REG(DP_MSA_TIMING_PARAM1)) { + switch (output_color_space) { + case COLOR_SPACE_SRGB: + misc0 = misc0 | 0x0;; + misc1 = misc1 & ~0x80; /* bit7 = 0*/ + break; + case COLOR_SPACE_SRGB_LIMITED: + misc0 = misc0 | 0x8; /* bit3=1 */ + misc1 = misc1 & ~0x80; /* bit7 = 0*/ + break; + case COLOR_SPACE_YCBCR601: + misc0 = misc0 | 0x8; /* bit3=1, bit4=0 */ + misc1 = misc1 & ~0x80; /* bit7 = 0*/; + if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) + misc0 = misc0 | 0x2; /* bit2=0, bit1=1 */ + else if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR444) + misc0 = misc0 | 0x4; /* bit2=1, bit1=0 */ + break; + case COLOR_SPACE_YCBCR709: + misc0 = misc0 | 0x18; /* bit3=1, bit4=1 */ + misc1 = misc1 & ~0x80; /* bit7 = 0*/ + if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) + misc0 = misc0 | 0x2; /* bit2=0, bit1=1 */ + else if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR444) + misc0 = misc0 | 0x4; /* bit2=1, bit1=0 */ + break; + case COLOR_SPACE_2020_RGB_FULLRANGE: + case COLOR_SPACE_2020_RGB_LIMITEDRANGE: + case COLOR_SPACE_2020_YCBCR: + case COLOR_SPACE_ADOBERGB: + case COLOR_SPACE_UNKNOWN: + case COLOR_SPACE_YCBCR601_LIMITED: + case COLOR_SPACE_YCBCR709_LIMITED: + /* do nothing */ + break; + } + +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + if (REG(DP_MSA_COLORIMETRY)) + REG_SET(DP_MSA_COLORIMETRY, 0, DP_MSA_MISC0, misc0); + + if (REG(DP_MSA_MISC)) + REG_WRITE(DP_MSA_MISC, misc1); /* MSA_MISC1 */ + + /* dcn new register + * dc_crtc_timing is vesa dmt struct. data from edid + */ + if (REG(DP_MSA_TIMING_PARAM1)) + REG_SET_2(DP_MSA_TIMING_PARAM1, 0, + DP_MSA_HTOTAL, crtc_timing->h_total, + DP_MSA_VTOTAL, crtc_timing->v_total); +#endif + + /* calcuate from vesa timing parameters + * h_active_start related to leading edge of sync + */ + + h_blank = crtc_timing->h_total - crtc_timing->h_border_left - + crtc_timing->h_addressable - crtc_timing->h_border_right; + + h_back_porch = h_blank - crtc_timing->h_front_porch - + crtc_timing->h_sync_width; + + /* start at begining of left border */ + h_active_start = crtc_timing->h_sync_width + h_back_porch; + + + v_active_start = crtc_timing->v_total - crtc_timing->v_border_top - + crtc_timing->v_addressable - crtc_timing->v_border_bottom - + crtc_timing->v_front_porch; + + +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + /* start at begining of left border */ + if (REG(DP_MSA_TIMING_PARAM2)) + REG_SET_2(DP_MSA_TIMING_PARAM2, 0, + DP_MSA_HSTART, h_active_start, + DP_MSA_VSTART, v_active_start); + + if (REG(DP_MSA_TIMING_PARAM3)) + REG_SET_4(DP_MSA_TIMING_PARAM3, 0, + DP_MSA_HSYNCWIDTH, + crtc_timing->h_sync_width, + DP_MSA_HSYNCPOLARITY, + !crtc_timing->flags.HSYNC_POSITIVE_POLARITY, + DP_MSA_VSYNCWIDTH, + crtc_timing->v_sync_width, + DP_MSA_VSYNCPOLARITY, + !crtc_timing->flags.VSYNC_POSITIVE_POLARITY); + + /* HWDITH include border or overscan */ + if (REG(DP_MSA_TIMING_PARAM4)) + REG_SET_2(DP_MSA_TIMING_PARAM4, 0, + DP_MSA_HWIDTH, crtc_timing->h_border_left + + crtc_timing->h_addressable + crtc_timing->h_border_right, + DP_MSA_VHEIGHT, crtc_timing->v_border_top + + crtc_timing->v_addressable + crtc_timing->v_border_bottom); +#endif + } +#endif } static void dce110_stream_encoder_set_stream_attribute_helper( @@ -533,6 +749,19 @@ static void dce110_stream_encoder_update_hdmi_info_packets( dce110_update_hdmi_info_packet(enc110, 3, &info_frame->hdrsmd); } +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + if (enc110->se_mask->HDMI_DB_DISABLE) { + /* for bring up, disable dp double TODO */ + if (REG(HDMI_DB_CONTROL)) + REG_UPDATE(HDMI_DB_CONTROL, HDMI_DB_DISABLE, 1); + + dce110_update_hdmi_info_packet(enc110, 0, &info_frame->avi); + dce110_update_hdmi_info_packet(enc110, 1, &info_frame->vendor); + dce110_update_hdmi_info_packet(enc110, 2, &info_frame->gamut); + dce110_update_hdmi_info_packet(enc110, 3, &info_frame->spd); + dce110_update_hdmi_info_packet(enc110, 4, &info_frame->hdrsmd); + } +#endif } static void dce110_stream_encoder_stop_hdmi_info_packets( @@ -558,6 +787,26 @@ static void dce110_stream_encoder_stop_hdmi_info_packets( HDMI_GENERIC1_LINE, 0, HDMI_GENERIC1_SEND, 0); +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + /* stop generic packets 2 & 3 on HDMI */ + if (REG(HDMI_GENERIC_PACKET_CONTROL2)) + REG_SET_6(HDMI_GENERIC_PACKET_CONTROL2, 0, + HDMI_GENERIC0_CONT, 0, + HDMI_GENERIC0_LINE, 0, + HDMI_GENERIC0_SEND, 0, + HDMI_GENERIC1_CONT, 0, + HDMI_GENERIC1_LINE, 0, + HDMI_GENERIC1_SEND, 0); + + if (REG(HDMI_GENERIC_PACKET_CONTROL3)) + REG_SET_6(HDMI_GENERIC_PACKET_CONTROL3, 0, + HDMI_GENERIC0_CONT, 0, + HDMI_GENERIC0_LINE, 0, + HDMI_GENERIC0_SEND, 0, + HDMI_GENERIC1_CONT, 0, + HDMI_GENERIC1_LINE, 0, + HDMI_GENERIC1_SEND, 0); +#endif } static void dce110_stream_encoder_update_dp_info_packets( @@ -621,6 +870,21 @@ static void dce110_stream_encoder_stop_dp_info_packets( DP_SEC_STREAM_ENABLE, 0); } +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + if (enc110->se_mask->DP_SEC_GSP7_ENABLE) { + REG_SET_10(DP_SEC_CNTL, 0, + DP_SEC_GSP0_ENABLE, 0, + DP_SEC_GSP1_ENABLE, 0, + DP_SEC_GSP2_ENABLE, 0, + DP_SEC_GSP3_ENABLE, 0, + DP_SEC_GSP4_ENABLE, 0, + DP_SEC_GSP5_ENABLE, 0, + DP_SEC_GSP6_ENABLE, 0, + DP_SEC_GSP7_ENABLE, 0, + DP_SEC_MPG_ENABLE, 0, + DP_SEC_STREAM_ENABLE, 0); + } +#endif /* this register shared with audio info frame. * therefore we need to keep master enabled * if at least one of the fields is not 0 */ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h index 850e12a8db61..0b548cb3af14 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h @@ -97,6 +97,23 @@ SE_COMMON_REG_LIST_DCE_BASE(id), \ SRI(AFMT_CNTL, DIG, id) +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +#define SE_DCN_REG_LIST(id)\ + SE_COMMON_REG_LIST_BASE(id),\ + SRI(AFMT_CNTL, DIG, id),\ + SRI(AFMT_VBI_PACKET_CONTROL1, DIG, id),\ + SRI(HDMI_GENERIC_PACKET_CONTROL2, DIG, id), \ + SRI(HDMI_GENERIC_PACKET_CONTROL3, DIG, id), \ + SRI(DP_DB_CNTL, DP, id), \ + SRI(DP_MSA_MISC, DP, id), \ + SRI(DP_MSA_COLORIMETRY, DP, id), \ + SRI(DP_MSA_TIMING_PARAM1, DP, id), \ + SRI(DP_MSA_TIMING_PARAM2, DP, id), \ + SRI(DP_MSA_TIMING_PARAM3, DP, id), \ + SRI(DP_MSA_TIMING_PARAM4, DP, id), \ + SRI(HDMI_DB_CONTROL, DIG, id) +#endif + #define SE_SF(reg_name, field_name, post_fix)\ .field_name = reg_name ## __ ## field_name ## post_fix @@ -311,6 +328,48 @@ SE_SF(DIG0_AFMT_AVI_INFO3, AFMT_AVI_INFO_VERSION, mask_sh),\ SE_SF(DP0_DP_VID_TIMING, DP_VID_M_DOUBLE_VALUE_EN, mask_sh) +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +#define SE_COMMON_MASK_SH_LIST_DCN10(mask_sh)\ + SE_COMMON_MASK_SH_LIST_SOC(mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_LOCK_STATUS, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT_CLR, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC0_FRAME_UPDATE_PENDING, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC1_FRAME_UPDATE_PENDING, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC2_FRAME_UPDATE_PENDING, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC3_FRAME_UPDATE_PENDING, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC4_FRAME_UPDATE_PENDING, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC5_FRAME_UPDATE_PENDING, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC6_FRAME_UPDATE_PENDING, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC7_FRAME_UPDATE_PENDING, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC0_FRAME_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC1_FRAME_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC2_FRAME_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC3_FRAME_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC4_FRAME_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC5_FRAME_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC6_FRAME_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC7_FRAME_UPDATE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP4_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP5_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP6_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP7_ENABLE, mask_sh),\ + SE_SF(DP0_DP_DB_CNTL, DP_DB_DISABLE, mask_sh),\ + SE_SF(DP0_DP_MSA_COLORIMETRY, DP_MSA_MISC0, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM1, DP_MSA_HTOTAL, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM1, DP_MSA_VTOTAL, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM2, DP_MSA_HSTART, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM2, DP_MSA_VSTART, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_HSYNCWIDTH, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_HSYNCPOLARITY, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_VSYNCWIDTH, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_VSYNCPOLARITY, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM4, DP_MSA_HWIDTH, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM4, DP_MSA_VHEIGHT, mask_sh),\ + SE_SF(DIG0_HDMI_DB_CONTROL, HDMI_DB_DISABLE, mask_sh),\ + SE_SF(DP0_DP_VID_TIMING, DP_VID_N_MUL, mask_sh) +#endif + struct dce_stream_encoder_shift { uint8_t AFMT_GENERIC_INDEX; uint8_t AFMT_GENERIC0_UPDATE; @@ -625,6 +684,16 @@ struct dce110_stream_enc_registers { uint32_t HDMI_ACR_48_0; uint32_t HDMI_ACR_48_1; uint32_t TMDS_CNTL; +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + uint32_t DP_DB_CNTL; + uint32_t DP_MSA_MISC; + uint32_t DP_MSA_COLORIMETRY; + uint32_t DP_MSA_TIMING_PARAM1; + uint32_t DP_MSA_TIMING_PARAM2; + uint32_t DP_MSA_TIMING_PARAM3; + uint32_t DP_MSA_TIMING_PARAM4; + uint32_t HDMI_DB_CONTROL; +#endif }; struct dce110_stream_encoder { diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index dc4c16416370..c89df8acb458 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -947,6 +947,12 @@ static void program_scaler(const struct core_dc *dc, { struct tg_color color = {0}; +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + /* TOFPGA */ + if (pipe_ctx->xfm->funcs->transform_set_pixel_storage_depth == NULL) + return; +#endif + if (dc->public.debug.surface_visual_confirm) get_surface_visual_confirm_color(pipe_ctx, &color); else @@ -1113,6 +1119,9 @@ static enum dc_status apply_single_controller_ctx_to_hw( program_scaler(dc, pipe_ctx); /* mst support - use total stream count */ +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + if (pipe_ctx->mi->funcs->allocate_mem_input != NULL) +#endif pipe_ctx->mi->funcs->allocate_mem_input( pipe_ctx->mi, stream->public.timing.h_total, @@ -1637,6 +1646,26 @@ enum dc_status dce110_apply_ctx_to_hw( /*TODO: when pplib works*/ apply_min_clocks(dc, context, &clocks_state, true); +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + if (context->fclk_khz + > dc->current_context->fclk_khz) { + struct dm_pp_clock_for_voltage_req clock; + + clock.clk_type = DM_PP_CLOCK_TYPE_FCLK; + clock.clocks_in_khz = context->fclk_khz; + dm_pp_apply_clock_for_voltage_request(dc->ctx, &clock); + dc->current_context->fclk_khz = clock.clocks_in_khz; + } + if (context->dcfclk_khz + > dc->current_context->dcfclk_khz) { + struct dm_pp_clock_for_voltage_req clock; + + clock.clk_type = DM_PP_CLOCK_TYPE_DCFCLK; + clock.clocks_in_khz = context->dcfclk_khz; + dm_pp_apply_clock_for_voltage_request(dc->ctx, &clock); + dc->current_context->dcfclk_khz = clock.clocks_in_khz; + } +#endif if (context->dispclk_khz > dc->current_context->dispclk_khz) { dc->res_pool->display_clock->funcs->set_clock( diff --git a/drivers/gpu/drm/amd/display/dc/dm_services.h b/drivers/gpu/drm/amd/display/dc/dm_services.h index cf6ecfcadd5e..fb61e333aefd 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services.h @@ -75,6 +75,10 @@ BREAK_TO_DEBUGGER(); \ } while (0) +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +#include +#endif + #define dm_alloc(size) kzalloc(size, GFP_KERNEL) #define dm_realloc(ptr, size) krealloc(ptr, size, GFP_KERNEL) #define dm_free(ptr) kfree(ptr) diff --git a/drivers/gpu/drm/amd/display/dc/dm_services_types.h b/drivers/gpu/drm/amd/display/dc/dm_services_types.h index 408141c6776e..b28304531d8a 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services_types.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services_types.h @@ -69,6 +69,7 @@ enum dm_pp_clock_type { DM_PP_CLOCK_TYPE_ENGINE_CLK, /* System clock */ DM_PP_CLOCK_TYPE_MEMORY_CLK, DM_PP_CLOCK_TYPE_DCFCLK, + DM_PP_CLOCK_TYPE_DCEFCLK, DM_PP_CLOCK_TYPE_SOCCLK, DM_PP_CLOCK_TYPE_PIXELCLK, DM_PP_CLOCK_TYPE_DISPLAYPHYCLK, diff --git a/drivers/gpu/drm/amd/display/dc/gpio/Makefile b/drivers/gpu/drm/amd/display/dc/gpio/Makefile index 5e831aff4830..70d01a9e9676 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/Makefile +++ b/drivers/gpu/drm/amd/display/dc/gpio/Makefile @@ -37,6 +37,17 @@ AMD_DAL_GPIO_DCE120 = $(addprefix $(AMDDALPATH)/dc/gpio/dce120/,$(GPIO_DCE120)) AMD_DISPLAY_FILES += $(AMD_DAL_GPIO_DCE120) +############################################################################### +# DCN 1x +############################################################################### +ifdef CONFIG_DRM_AMD_DC_DCN1_0 +GPIO_DCN10 = hw_translate_dcn10.o hw_factory_dcn10.o + +AMD_DAL_GPIO_DCN10 = $(addprefix $(AMDDALPATH)/dc/gpio/dcn10/,$(GPIO_DCN10)) + +AMD_DISPLAY_FILES += $(AMD_DAL_GPIO_DCN10) +endif + ############################################################################### # Diagnostics on FPGA ############################################################################### diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c index 29ba83d2c211..8a8b619a60a8 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c @@ -43,8 +43,10 @@ #include "dce80/hw_factory_dce80.h" #include "dce110/hw_factory_dce110.h" - #include "dce120/hw_factory_dce120.h" +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +#include "dcn10/hw_factory_dcn10.h" +#endif #include "diagnostics/hw_factory_diag.h" @@ -77,6 +79,11 @@ bool dal_hw_factory_init( case DCE_VERSION_12_0: dal_hw_factory_dce120_init(factory); return true; +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + case DCN_VERSION_1_0: + dal_hw_factory_dcn10_init(factory); + return true; +#endif default: ASSERT_CRITICAL(false); return false; diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c index 872edda54536..36c082bda4ae 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c @@ -43,6 +43,10 @@ #include "dce80/hw_translate_dce80.h" #include "dce110/hw_translate_dce110.h" #include "dce120/hw_translate_dce120.h" +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +#include "dcn10/hw_translate_dcn10.h" +#endif + #include "diagnostics/hw_translate_diag.h" /* @@ -71,6 +75,11 @@ bool dal_hw_translate_init( case DCE_VERSION_12_0: dal_hw_translate_dce120_init(translate); return true; +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + case DCN_VERSION_1_0: + dal_hw_translate_dcn10_init(translate); + return true; +#endif default: BREAK_TO_DEBUGGER(); return false; diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/Makefile b/drivers/gpu/drm/amd/display/dc/i2caux/Makefile index a636768d06d5..55603400acd9 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/Makefile +++ b/drivers/gpu/drm/amd/display/dc/i2caux/Makefile @@ -47,6 +47,17 @@ AMD_DAL_I2CAUX_DCE112 = $(addprefix $(AMDDALPATH)/dc/i2caux/dce112/,$(I2CAUX_DCE AMD_DISPLAY_FILES += $(AMD_DAL_I2CAUX_DCE112) +############################################################################### +# DCN 1.0 family +############################################################################### +ifdef CONFIG_DRM_AMD_DC_DCN1_0 +I2CAUX_DCN1 = i2caux_dcn10.o + +AMD_DAL_I2CAUX_DCN1 = $(addprefix $(AMDDALPATH)/dc/i2caux/dcn10/,$(I2CAUX_DCN1)) + +AMD_DISPLAY_FILES += $(AMD_DAL_I2CAUX_DCN1) +endif + ############################################################################### # DCE 120 family ############################################################################### diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c index 0743265e933c..983645b1be78 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c @@ -59,6 +59,10 @@ #include "dce120/i2caux_dce120.h" +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +#include "dcn10/i2caux_dcn10.h" +#endif + #include "diagnostics/i2caux_diag.h" /* @@ -84,6 +88,10 @@ struct i2caux *dal_i2caux_create( return dal_i2caux_dce100_create(ctx); case DCE_VERSION_12_0: return dal_i2caux_dce120_create(ctx); + #if defined(CONFIG_DRM_AMD_DC_DCN1_0) + case DCN_VERSION_1_0: + return dal_i2caux_dcn10_create(ctx); + #endif default: BREAK_TO_DEBUGGER(); return NULL; diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_dc.h b/drivers/gpu/drm/amd/display/dc/inc/core_dc.h index f9363f642f92..392cff2cd558 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_dc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_dc.h @@ -30,6 +30,11 @@ struct core_dc { /* Inputs into BW and WM calculations. */ struct bw_calcs_dceip bw_dceip; struct bw_calcs_vbios bw_vbios; +#ifdef CONFIG_DRM_AMD_DC_DCN1_0 + struct dcn_soc_bounding_box dcn_soc; + struct dcn_ip_params dcn_ip; + struct display_mode_lib dml; +#endif /* HW functions */ struct hw_sequencer_funcs hwss; diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 9e5e0ba5b10b..c1273d6142c4 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -28,8 +28,11 @@ #include "dc.h" #include "dce_calcs.h" +#include "dcn_calcs.h" #include "ddc_service_types.h" #include "dc_bios_types.h" +#include "mem_input.h" +#include "mpc.h" struct core_stream; @@ -254,6 +257,7 @@ struct resource_pool { struct abm *abm; struct dmcu *dmcu; + struct mpc *mpc; const struct resource_funcs *funcs; const struct resource_caps *res_cap; @@ -287,10 +291,20 @@ struct pipe_ctx { struct pipe_ctx *top_pipe; struct pipe_ctx *bottom_pipe; +#ifdef CONFIG_DRM_AMD_DC_DCN1_0 + uint8_t mpc_idx; + struct _vcs_dpi_display_dlg_regs_st dlg_regs; + struct _vcs_dpi_display_ttu_regs_st ttu_regs; + struct _vcs_dpi_display_rq_regs_st rq_regs; + struct _vcs_dpi_display_pipe_dest_params_st pipe_dlg_param; +#endif }; struct resource_context { struct pipe_ctx pipe_ctx[MAX_PIPES]; +#ifdef CONFIG_DRM_AMD_DC_DCN1_0 + struct mpc_tree_cfg mpc_tree[MAX_PIPES]; +#endif bool is_stream_enc_acquired[MAX_PIPES * 2]; bool is_audio_acquired[MAX_PIPES]; uint8_t clock_source_ref_count[MAX_CLOCK_SOURCES]; @@ -309,6 +323,18 @@ struct validate_context { /* Note: these are big structures, do *not* put on stack! */ struct dm_pp_display_configuration pp_display_cfg; int dispclk_khz; +#ifdef CONFIG_DRM_AMD_DC_DCN1_0 + int dppclk_khz; + bool dppclk_div; + int dcfclk_khz; + int dcfclk_deep_sleep_khz; + int socclk_khz; + int fclk_khz; + int dram_ccm_us; + int min_active_dram_ccm_us; + struct dcn_watermark_set watermarks; + struct dcn_bw_internal_vars dcn_bw_vars; +#endif }; #endif /* _CORE_TYPES_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h b/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h index 97f26b55535f..240ab11d1d30 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h @@ -37,6 +37,13 @@ struct clocks_value { bool dispclk_notify_pplib_done; bool pixelclk_notify_pplib_done; bool phyclk_notigy_pplib_done; +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + int dcfclock_in_khz; + int dppclk_in_khz; + int mclk_in_khz; + int phyclk_in_khz; + int common_vdd_level; +#endif }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h index 2d472d8ef555..0f952e5b3ae8 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h @@ -122,6 +122,7 @@ struct ipp_funcs { struct input_pixel_processor *ipp, const struct pwl_params *params); + void (*ipp_destroy)(struct input_pixel_processor **ipp); }; #endif /* __DAL_IPP_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h index 179f5ad70f48..0880ce98c90c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h @@ -31,6 +31,30 @@ #include "dce/dce_mem_input.h" /* temporary */ +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +#include "dml/display_mode_structs.h" + +struct cstate_pstate_watermarks_st { + uint32_t cstate_exit_ns; + uint32_t cstate_enter_plus_exit_ns; + uint32_t pstate_change_ns; +}; + +struct dcn_watermarks { + uint32_t pte_meta_urgent_ns; + uint32_t urgent_ns; + struct cstate_pstate_watermarks_st cstate_pstate; +}; + +struct dcn_watermark_set { + struct dcn_watermarks a; + struct dcn_watermarks b; + struct dcn_watermarks c; + struct dcn_watermarks d; +}; + +#endif + struct stutter_modes { bool enhanced; bool quad_dmif_buffer; @@ -52,6 +76,23 @@ struct mem_input { }; struct mem_input_funcs { +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + void (*program_watermarks)( + struct mem_input *mem_input, + struct dcn_watermark_set *watermarks, + unsigned int refclk_period_ns); + + void (*mem_input_setup)( + struct mem_input *mem_input, + struct _vcs_dpi_display_dlg_regs_st *dlg_regs, + struct _vcs_dpi_display_ttu_regs_st *ttu_regs, + struct _vcs_dpi_display_rq_regs_st *rq_regs, + struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest); + + void (*disable_request)(struct mem_input *mem_input); + +#endif + void (*mem_input_program_display_marks)( struct mem_input *mem_input, struct bw_watermarks nbp, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h new file mode 100644 index 000000000000..2e86ebe5eeda --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h @@ -0,0 +1,110 @@ +/* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_MPC_H__ +#define __DC_MPC_H__ + +/* define the maximum number of pipes + * MAX_NUM_PIPPES = MAX_PIPES defined in core_type.h + */ +enum { + MAX_NUM_PIPPES = 6 +}; + +enum blend_mode { + DIGI_BYPASS = 0, /* digital bypass */ + TOP_PASSTHRU, /* top layer pass through */ + TOP_BLND /* top layer blend */ +}; + +/* This structure define the mpc tree configuration + * num_pipes - number of pipes of the tree + * opp_id - instance id of OPP to drive MPC + * dpp- array of DPP index + * mpcc - array of MPCC index + * mode - the most bottom layer MPCC mode control. + * All other layers need to be program to 3 + * + * The connection will be: + * mpcc[num_pipes-1]->mpcc[num_pipes-2]->...->mpcc[1]->mpcc[0]->OPP[opp_id] + * dpp[0]->mpcc[0] + * dpp[1]->mpcc[1] + * ... + * dpp[num_pipes-1]->mpcc[num_pipes-1] + * mpcc[0] is the most top layer of MPC tree, + * mpcc[num_pipes-1] is the most bottom layer. + */ + +struct mpc_tree_cfg { + uint8_t num_pipes; + uint8_t opp_id; + /* dpp pipes for blend */ + uint8_t dpp[MAX_NUM_PIPPES]; + /* mpcc insatnces for blend */ + uint8_t mpcc[MAX_NUM_PIPPES]; + enum blend_mode mode; +}; + +struct mpcc_blnd_cfg { + /* 0- perpixel alpha, 1- perpixel alpha combined with global gain, + * 2- global alpha + */ + uint8_t alpha_mode; + uint8_t global_gain; + uint8_t global_alpha; + bool overlap_only; + bool pre_multiplied_alpha; +}; + +struct mpcc_sm_cfg { + bool enable; + /* 0-single plane, 2-row subsampling, 4-column subsampling, + * 6-checkboard subsampling + */ + uint8_t sm_mode; + bool frame_alt; /* 0- disable, 1- enable */ + bool field_alt; /* 0- disable, 1- enable */ + /* 0-no force, 2-force frame polarity from top, + * 3-force frame polarity from bottom + */ + uint8_t force_next_frame_porlarity; + /* 0-no force, 2-force field polarity from top, + * 3-force field polarity from bottom + */ + uint8_t force_next_field_polarity; +}; + +struct mpcc_vupdate_lock_cfg { + bool cfg_lock; + bool adr_lock; + bool adr_cfg_lock; + bool cur0_lock; + bool cur1_lock; +}; + +struct mpc { + struct dc_context *ctx; +}; + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h index 92c99c3b9002..64d43257db96 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h @@ -27,6 +27,7 @@ #define __DAL_OPP_H__ #include "hw_shared.h" +#include "dc_hw_types.h" #include "transform.h" struct fixed31_32; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h index 00cdaaae455c..9f130affb31c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h @@ -91,10 +91,22 @@ enum crtc_state { CRTC_STATE_VBLANK = 0, CRTC_STATE_VACTIVE }; +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +struct _dlg_otg_param { + int vstartup_start; + int vupdate_offset; + int vupdate_width; + int vready_offset; + enum signal_type signal; +}; +#endif struct timing_generator { const struct timing_generator_funcs *funcs; struct dc_bios *bp; struct dc_context *ctx; +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + struct _dlg_otg_param dlg_otg_param; +#endif int inst; }; @@ -155,6 +167,10 @@ struct timing_generator_funcs { bool (*arm_vert_intr)(struct timing_generator *tg, uint8_t width); +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + void (*program_global_sync)(struct timing_generator *tg); + void (*enable_optc_clock)(struct timing_generator *tg, bool enable); +#endif }; #endif diff --git a/drivers/gpu/drm/amd/display/dc/irq/Makefile b/drivers/gpu/drm/amd/display/dc/irq/Makefile index 222f36e3074f..c7e93f7223bd 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/Makefile +++ b/drivers/gpu/drm/amd/display/dc/irq/Makefile @@ -36,3 +36,13 @@ AMD_DAL_IRQ_DCE12 = $(addprefix $(AMDDALPATH)/dc/irq/dce120/,$(IRQ_DCE12)) AMD_DISPLAY_FILES += $(AMD_DAL_IRQ_DCE12) +############################################################################### +# DCN 1x +############################################################################### +ifdef CONFIG_DRM_AMD_DC_DCN1_0 +IRQ_DCN1 = irq_service_dcn10.o + +AMD_DAL_IRQ_DCN1 = $(addprefix $(AMDDALPATH)/dc/irq/dcn10/,$(IRQ_DCN1)) + +AMD_DISPLAY_FILES += $(AMD_DAL_IRQ_DCN1) +endif diff --git a/drivers/gpu/drm/amd/display/dc/irq/irq_service.c b/drivers/gpu/drm/amd/display/dc/irq/irq_service.c index 5255c14254df..0a1fae4ef83a 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/irq_service.c +++ b/drivers/gpu/drm/amd/display/dc/irq/irq_service.c @@ -35,6 +35,11 @@ #include "dce120/irq_service_dce120.h" + +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +#include "dcn10/irq_service_dcn10.h" +#endif + #include "reg_helper.h" #include "irq_service.h" diff --git a/drivers/gpu/drm/amd/display/include/dal_asic_id.h b/drivers/gpu/drm/amd/display/include/dal_asic_id.h index 6dab058f8f3c..3d2ed5c83734 100644 --- a/drivers/gpu/drm/amd/display/include/dal_asic_id.h +++ b/drivers/gpu/drm/amd/display/include/dal_asic_id.h @@ -109,6 +109,19 @@ #define ASIC_REV_IS_STONEY(rev) \ ((rev >= STONEY_A0) && (rev < CZ_UNKNOWN)) +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +/* DCN1_0 */ +#define INTERNAL_REV_RAVEN_A0 0x00 /* First spin of Raven */ +#define RAVEN_A0 0x01 +#define RAVEN_UNKNOWN 0xFF + +#define ASIC_REV_IS_RAVEN(eChipRev) ((eChipRev >= RAVEN_A0) && eChipRev < RAVEN_UNKNOWN) +#endif + +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +#define FAMILY_RV 142 /* DCN 1*/ +#endif + /* * ASIC chip ID */ diff --git a/drivers/gpu/drm/amd/display/include/dal_types.h b/drivers/gpu/drm/amd/display/include/dal_types.h index 0cefde14aa02..50a2a3ebf36d 100644 --- a/drivers/gpu/drm/amd/display/include/dal_types.h +++ b/drivers/gpu/drm/amd/display/include/dal_types.h @@ -39,7 +39,10 @@ enum dce_version { DCE_VERSION_11_0, DCE_VERSION_11_2, DCE_VERSION_12_0, - DCE_VERSION_MAX, +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + DCN_VERSION_1_0, +#endif + DCN_VERSION_MAX }; #endif /* __DAL_TYPES_H__ */ -- cgit From fd187853857d46dce082e8bca210795a5f2d38a5 Mon Sep 17 00:00:00 2001 From: Hawking Zhang Date: Mon, 6 Mar 2017 14:01:11 +0800 Subject: drm/amdgpu: enable dcn1.0 dc support on raven Signed-off-by: Hawking Zhang Reviewed-by: Chunming Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index df95dd8439b6..27d46a907bd9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1993,6 +1993,10 @@ bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type) #else return amdgpu_dc > 0; #endif +#endif +#if defined(CONFIG_DRM_AMD_DC) && defined(CONFIG_DRM_AMD_DC_DCN1_0) + case CHIP_RAVEN: + return amdgpu_dc != 0; #endif default: return false; -- cgit From 8e863620aaecdb86920035c6d8863a4642147c35 Mon Sep 17 00:00:00 2001 From: kbuild test robot Date: Thu, 11 May 2017 09:48:31 +0800 Subject: drm/amdgpu/display: fix semicolon.cocci warnings drivers/gpu/drm/amd/amdgpu/../display/dc/dce/dce_stream_encoder.c:411:23-24: Unneeded semicolon drivers/gpu/drm/amd/amdgpu/../display/dc/dce/dce_stream_encoder.c:420:39-40: Unneeded semicolon Remove unneeded semicolon. Generated by: scripts/coccinelle/misc/semicolon.cocci CC: Harry Wentland Signed-off-by: Fengguang Wu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c index a065e4ae6cba..daab81bd1773 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c @@ -408,7 +408,7 @@ static void dce110_stream_encoder_dp_set_stream_attribute( if (REG(DP_MSA_TIMING_PARAM1)) { switch (output_color_space) { case COLOR_SPACE_SRGB: - misc0 = misc0 | 0x0;; + misc0 = misc0 | 0x0; misc1 = misc1 & ~0x80; /* bit7 = 0*/ break; case COLOR_SPACE_SRGB_LIMITED: @@ -417,7 +417,7 @@ static void dce110_stream_encoder_dp_set_stream_attribute( break; case COLOR_SPACE_YCBCR601: misc0 = misc0 | 0x8; /* bit3=1, bit4=0 */ - misc1 = misc1 & ~0x80; /* bit7 = 0*/; + misc1 = misc1 & ~0x80; /* bit7 = 0*/ if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) misc0 = misc0 | 0x2; /* bit2=0, bit1=1 */ else if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR444) -- cgit From 2801b0a84ef66604fed6754d8d7858b45e2a443a Mon Sep 17 00:00:00 2001 From: kbuild test robot Date: Thu, 11 May 2017 09:48:31 +0800 Subject: drm/amdgpu/display: fix semicolon.cocci warnings drivers/gpu/drm/amd/amdgpu/../display/dc/dcn10/dcn10_resource.c:1085:2-3: Unneeded semicolon Remove unneeded semicolon. Generated by: scripts/coccinelle/misc/semicolon.cocci CC: Harry Wentland Signed-off-by: Fengguang Wu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 7aa438cd2b1a..121eb3009445 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -1082,7 +1082,7 @@ static bool dcc_support_swizzle( break; default: break; - }; + } if (bytes_per_element == 1 && standard_swizzle) { *segment_order_horz = segment_order__contiguous; -- cgit From 15a27de250a5e5a2dec7c0bf004db0511353e3f3 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Wed, 10 May 2017 15:56:17 -0400 Subject: drm/amd/display: Don't call PSR func if DMCU is off Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 8 -------- drivers/gpu/drm/amd/display/dc/dce/dce_abm.c | 23 +++++++++++++++-------- drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c | 11 ++++++++--- drivers/gpu/drm/amd/display/dc/inc/hw/abm.h | 1 + 4 files changed, 24 insertions(+), 19 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 6f78403e2d64..95d042a15409 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -46,14 +46,6 @@ #include "dce/dce_11_0_enum.h" #include "dce/dce_11_0_sh_mask.h" -#ifndef mmDMCU_STATUS__UC_IN_RESET__SHIFT -#define mmDMCU_STATUS__UC_IN_RESET__SHIFT 0x0 -#endif - -#ifndef mmDMCU_STATUS__UC_IN_RESET_MASK -#define mmDMCU_STATUS__UC_IN_RESET_MASK 0x00000001L -#endif - #define LINK_INFO(...) \ dm_logger_write(dc_ctx->logger, LOG_HW_HOTPLUG, \ __VA_ARGS__) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c index 45a3079c0973..393c43559825 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c @@ -366,6 +366,16 @@ static bool dce_abm_init_backlight(struct abm *abm) return true; } +static bool is_dmcu_initialized(struct abm *abm) +{ + struct dce_abm *abm_dce = TO_DCE_ABM(abm); + unsigned int dmcu_uc_reset; + + REG_GET(DMCU_STATUS, UC_IN_RESET, &dmcu_uc_reset); + + return !dmcu_uc_reset; +} + static bool dce_abm_set_backlight_level( struct abm *abm, unsigned int backlight_level, @@ -373,23 +383,19 @@ static bool dce_abm_set_backlight_level( unsigned int controller_id) { struct dce_abm *abm_dce = TO_DCE_ABM(abm); - unsigned int dmcu_uc_reset; dm_logger_write(abm->ctx->logger, LOG_BACKLIGHT, "New Backlight level: %d (0x%X)\n", backlight_level, backlight_level); - REG_GET(DMCU_STATUS, UC_IN_RESET, &dmcu_uc_reset); - /* If DMCU is in reset state, DMCU is uninitialized */ - if (dmcu_uc_reset) { - driver_set_backlight_level(abm_dce, backlight_level); - } else { + if (is_dmcu_initialized(abm)) dmcu_set_backlight_level(abm_dce, backlight_level, frame_ramp, controller_id); - } + else + driver_set_backlight_level(abm_dce, backlight_level); return true; } @@ -398,7 +404,8 @@ static const struct abm_funcs dce_funcs = { .abm_init = dce_abm_init, .set_abm_level = dce_abm_set_level, .init_backlight = dce_abm_init_backlight, - .set_backlight_level = dce_abm_set_backlight_level + .set_backlight_level = dce_abm_set_backlight_level, + .is_dmcu_initialized = is_dmcu_initialized }; static void dce_abm_construct( diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c index 6e56d8308d66..8bc0d0ff3a2e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c @@ -29,11 +29,15 @@ #include "fixed32_32.h" #include "bios_parser_interface.h" #include "dc.h" +#include "core_dc.h" +#include "dce_abm.h" #if defined(CONFIG_DRM_AMD_DC_DCN1_0) #include "dcn_calcs.h" #include "core_dc.h" #endif + + #define TO_DCE_CLOCKS(clocks)\ container_of(clocks, struct dce_disp_clk, base) @@ -374,6 +378,8 @@ static void dce112_set_clock( struct dce_disp_clk *clk_dce = TO_DCE_CLOCKS(clk); struct bp_set_dce_clock_parameters dce_clk_params; struct dc_bios *bp = clk->ctx->dc_bios; + struct core_dc *core_dc = DC_TO_CORE(clk->ctx->dc); + struct abm *abm = core_dc->res_pool->abm; /* Prepare to program display clock*/ memset(&dce_clk_params, 0, sizeof(dce_clk_params)); @@ -404,9 +410,8 @@ static void dce112_set_clock( bp->funcs->set_dce_clock(bp, &dce_clk_params); -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) - dce_psr_wait_loop(clk_dce, requested_clk_khz); -#endif + if (abm->funcs->is_dmcu_initialized(abm)) + dce_psr_wait_loop(clk_dce, requested_clk_khz); } diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h b/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h index 7d07b7922391..ceabbd3bf5f8 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h @@ -40,6 +40,7 @@ struct abm_funcs { unsigned int backlight_level, unsigned int frame_ramp, unsigned int controller_id); + bool (*is_dmcu_initialized)(struct abm *abm); }; #endif -- cgit From 46df790c6b569faffb4cc93889745a7827283749 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Sun, 30 Apr 2017 09:20:55 -0400 Subject: drm/amd/display: i2c/aux Remove link index. Link index is an unnecessery level of inderection when calling from kernel i2c/aux transfer into DAL. Signed-off-by: Andrey Grodzovsky Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 6 ++-- .../amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 38 +++++++++++----------- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 22 +++++++++---- drivers/gpu/drm/amd/display/dc/core/dc.c | 19 ++++------- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 28 ++++++++-------- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 4 +-- drivers/gpu/drm/amd/display/dc/dc.h | 9 ++--- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 1 - 8 files changed, 61 insertions(+), 66 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index bdae70e128c4..be51ac56552c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -546,13 +546,13 @@ enum amdgpu_connector_dither { struct amdgpu_dm_dp_aux { struct drm_dp_aux aux; - uint32_t link_index; + struct ddc_service *ddc_service; }; struct amdgpu_i2c_adapter { struct i2c_adapter base; - struct amdgpu_display_manager *dm; - uint32_t link_index; + + struct ddc_service *ddc_service; }; #define TO_DM_AUX(x) container_of((x), struct amdgpu_dm_dp_aux, aux) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 187464ac27b3..77907baa522a 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -33,6 +33,8 @@ #include "dc.h" #include "dm_helpers.h" +#include "dc_link_ddc.h" + /* #define TRACE_DPCD */ #ifdef TRACE_DPCD @@ -77,43 +79,41 @@ void log_dpcd(uint8_t type, static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) { - struct pci_dev *pdev = to_pci_dev(aux->dev); - struct drm_device *drm_dev = pci_get_drvdata(pdev); - struct amdgpu_device *adev = drm_dev->dev_private; - struct dc *dc = adev->dm.dc; enum i2c_mot_mode mot = (msg->request & DP_AUX_I2C_MOT) ? I2C_MOT_TRUE : I2C_MOT_FALSE; - bool res; + enum ddc_result res; switch (msg->request & ~DP_AUX_I2C_MOT) { case DP_AUX_NATIVE_READ: - res = dc_read_aux_dpcd( - dc, - TO_DM_AUX(aux)->link_index, + res = dal_ddc_service_read_dpcd_data( + TO_DM_AUX(aux)->ddc_service, + false, + I2C_MOT_UNDEF, msg->address, msg->buffer, msg->size); break; case DP_AUX_NATIVE_WRITE: - res = dc_write_aux_dpcd( - dc, - TO_DM_AUX(aux)->link_index, + res = dal_ddc_service_write_dpcd_data( + TO_DM_AUX(aux)->ddc_service, + false, + I2C_MOT_UNDEF, msg->address, msg->buffer, msg->size); break; case DP_AUX_I2C_READ: - res = dc_read_aux_i2c( - dc, - TO_DM_AUX(aux)->link_index, + res = dal_ddc_service_read_dpcd_data( + TO_DM_AUX(aux)->ddc_service, + true, mot, msg->address, msg->buffer, msg->size); break; case DP_AUX_I2C_WRITE: - res = dc_write_aux_i2c( - dc, - TO_DM_AUX(aux)->link_index, + res = dal_ddc_service_write_dpcd_data( + TO_DM_AUX(aux)->ddc_service, + true, mot, msg->address, msg->buffer, @@ -128,7 +128,7 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg msg->address, msg->buffer, msg->size, - res); + r == DDC_RESULT_SUCESSFULL); #endif return msg->size; @@ -444,7 +444,7 @@ void amdgpu_dm_initialize_dp_connector( aconnector->dm_dp_aux.aux.name = "dmdc"; aconnector->dm_dp_aux.aux.dev = dm->adev->dev; aconnector->dm_dp_aux.aux.transfer = dm_dp_aux_transfer; - aconnector->dm_dp_aux.link_index = aconnector->connector_id; + aconnector->dm_dp_aux.ddc_service = aconnector->dc_link->ddc; drm_dp_aux_register(&aconnector->dm_dp_aux.aux); aconnector->mst_mgr.cbs = &dm_mst_cbs; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index bca6769e7481..6bd8048ba21e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -50,6 +50,8 @@ #include "modules/inc/mod_freesync.h" +#include "i2caux_interface.h" + struct dm_connector_state { struct drm_connector_state base; @@ -1999,6 +2001,7 @@ int amdgpu_dm_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num) { struct amdgpu_i2c_adapter *i2c = i2c_get_adapdata(i2c_adap); + struct ddc_service *ddc_service = i2c->ddc_service; struct i2c_command cmd; int i; int result = -EIO; @@ -2019,11 +2022,13 @@ int amdgpu_dm_i2c_xfer(struct i2c_adapter *i2c_adap, cmd.payloads[i].data = msgs[i].buf; } - if (dc_submit_i2c(i2c->dm->dc, i2c->link_index, &cmd)) + if (dal_i2caux_submit_i2c_command( + ddc_service->ctx->i2caux, + ddc_service->ddc_pin, + &cmd)) result = num; kfree(cmd.payloads); - return result; } @@ -2037,19 +2042,22 @@ static const struct i2c_algorithm amdgpu_dm_i2c_algo = { .functionality = amdgpu_dm_i2c_func, }; -struct amdgpu_i2c_adapter *create_i2c(unsigned int link_index, struct amdgpu_display_manager *dm, int *res) +static struct amdgpu_i2c_adapter *create_i2c( + struct ddc_service *ddc_service, + int link_index, + int *res) { + struct amdgpu_device *adev = ddc_service->ctx->driver_context; struct amdgpu_i2c_adapter *i2c; i2c = kzalloc(sizeof (struct amdgpu_i2c_adapter), GFP_KERNEL); - i2c->dm = dm; i2c->base.owner = THIS_MODULE; i2c->base.class = I2C_CLASS_DDC; - i2c->base.dev.parent = &dm->adev->pdev->dev; + i2c->base.dev.parent = &adev->pdev->dev; i2c->base.algo = &amdgpu_dm_i2c_algo; snprintf(i2c->base.name, sizeof (i2c->base.name), "AMDGPU DM i2c hw bus %d", link_index); - i2c->link_index = link_index; i2c_set_adapdata(&i2c->base, i2c); + i2c->ddc_service = ddc_service; return i2c; } @@ -2071,7 +2079,7 @@ int amdgpu_dm_connector_init( DRM_DEBUG_KMS("%s()\n", __func__); - i2c = create_i2c(link->link_index, dm, &res); + i2c = create_i2c(link->ddc, link->link_index, &res); aconnector->i2c = i2c; res = i2c_add_adapter(&i2c->base); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 738acf0cc7db..d063a252ccd9 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1525,13 +1525,6 @@ const struct graphics_object_id dc_get_link_id_at_index( return core_dc->links[link_index]->link_id; } -const struct ddc_service *dc_get_ddc_at_index( - struct dc *dc, uint32_t link_index) -{ - struct core_dc *core_dc = DC_TO_CORE(dc); - return core_dc->links[link_index]->ddc; -} - enum dc_irq_source dc_get_hpd_irq_source_at_index( struct dc *dc, uint32_t link_index) { @@ -1639,7 +1632,7 @@ bool dc_read_aux_dpcd( struct core_link *link = core_dc->links[link_index]; enum ddc_result r = dal_ddc_service_read_dpcd_data( - link->ddc, + link->public.ddc, false, I2C_MOT_UNDEF, address, @@ -1659,7 +1652,7 @@ bool dc_write_aux_dpcd( struct core_link *link = core_dc->links[link_index]; enum ddc_result r = dal_ddc_service_write_dpcd_data( - link->ddc, + link->public.ddc, false, I2C_MOT_UNDEF, address, @@ -1680,7 +1673,7 @@ bool dc_read_aux_i2c( struct core_link *link = core_dc->links[link_index]; enum ddc_result r = dal_ddc_service_read_dpcd_data( - link->ddc, + link->public.ddc, true, mot, address, @@ -1701,7 +1694,7 @@ bool dc_write_aux_i2c( struct core_link *link = core_dc->links[link_index]; enum ddc_result r = dal_ddc_service_write_dpcd_data( - link->ddc, + link->public.ddc, true, mot, address, @@ -1724,7 +1717,7 @@ bool dc_query_ddc_data( struct core_link *link = core_dc->links[link_index]; bool result = dal_ddc_service_query_ddc_data( - link->ddc, + link->public.ddc, address, write_buf, write_size, @@ -1742,7 +1735,7 @@ bool dc_submit_i2c( struct core_dc *core_dc = DC_TO_CORE(dc); struct core_link *link = core_dc->links[link_index]; - struct ddc_service *ddc = link->ddc; + struct ddc_service *ddc = link->public.ddc; return dal_i2caux_submit_i2c_command( ddc->ctx->i2caux, diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 95d042a15409..97cfd5bd3853 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -66,8 +66,8 @@ static void destruct(struct core_link *link) { int i; - if (link->ddc) - dal_ddc_service_destroy(&link->ddc); + if (link->public.ddc) + dal_ddc_service_destroy(&link->public.ddc); if(link->link_enc) link->link_enc->funcs->destroy(&link->link_enc); @@ -320,7 +320,7 @@ static bool is_dp_sink_present(struct core_link *link) ((connector_id == CONNECTOR_ID_DISPLAY_PORT) || (connector_id == CONNECTOR_ID_EDP)); - ddc = dal_ddc_service_get_ddc_pin(link->ddc); + ddc = dal_ddc_service_get_ddc_pin(link->public.ddc); if (!ddc) { BREAK_TO_DEBUGGER(); @@ -526,7 +526,7 @@ static void detect_dp( } } else { /* DP passive dongles */ - sink_caps->signal = dp_passive_dongle_detection(link->ddc, + sink_caps->signal = dp_passive_dongle_detection(link->public.ddc, sink_caps, audio_support); } @@ -629,11 +629,11 @@ bool dc_link_detect(const struct dc_link *dc_link, bool boot) link->dpcd_sink_count = 1; dal_ddc_service_set_transaction_type( - link->ddc, + link->public.ddc, sink_caps.transaction_type); link->public.aux_mode = dal_ddc_service_is_in_aux_transaction_mode( - link->ddc); + link->public.ddc); sink_init_data.link = &link->public; sink_init_data.sink_signal = sink_caps.signal; @@ -784,7 +784,7 @@ static enum channel_id get_ddc_line(struct core_link *link) struct ddc *ddc; enum channel_id channel = CHANNEL_ID_UNKNOWN; - ddc = dal_ddc_service_get_ddc_pin(link->ddc); + ddc = dal_ddc_service_get_ddc_pin(link->public.ddc); if (ddc) { switch (dal_ddc_get_line(ddc)) { @@ -971,16 +971,16 @@ static bool construct( ddc_service_init_data.ctx = link->ctx; ddc_service_init_data.id = link->link_id; ddc_service_init_data.link = link; - link->ddc = dal_ddc_service_create(&ddc_service_init_data); + link->public.ddc = dal_ddc_service_create(&ddc_service_init_data); - if (NULL == link->ddc) { + if (link->public.ddc == NULL) { DC_ERROR("Failed to create ddc_service!\n"); goto ddc_create_fail; } link->public.ddc_hw_inst = dal_ddc_get_line( - dal_ddc_service_get_ddc_pin(link->ddc)); + dal_ddc_service_get_ddc_pin(link->public.ddc)); enc_init_data.ctx = dc_ctx; bp_funcs->get_src_obj(dc_ctx->dc_bios, link->link_id, 0, &enc_init_data.encoder); @@ -1049,7 +1049,7 @@ static bool construct( device_tag_fail: link->link_enc->funcs->destroy(&link->link_enc); link_enc_create_fail: - dal_ddc_service_destroy(&link->ddc); + dal_ddc_service_destroy(&link->public.ddc); ddc_create_fail: create_fail: @@ -1256,7 +1256,7 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) dal_ddc_service_write_scdc_data( - stream->sink->link->ddc, + stream->sink->link->public.ddc, stream->phy_pix_clk, stream->public.timing.flags.LTE_340MCSC_SCRAMBLE); @@ -1276,7 +1276,7 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) stream->phy_pix_clk); if (pipe_ctx->stream->signal == SIGNAL_TYPE_HDMI_TYPE_A) - dal_ddc_service_read_scdc_data(link->ddc); + dal_ddc_service_read_scdc_data(link->public.ddc); } /****************************enable_link***********************************/ @@ -1474,7 +1474,7 @@ bool dc_link_setup_psr(const struct dc_link *dc_link, &psr_configuration.raw, sizeof(psr_configuration.raw)); - psr_context.channel = link->ddc->ddc_pin->hw_info.ddc_channel; + psr_context.channel = link->public.ddc->ddc_pin->hw_info.ddc_channel; psr_context.transmitterId = link->link_enc->transmitter; psr_context.engineId = link->link_enc->preferred_engine; 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 a0d192774a22..98048fe6239e 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 @@ -1913,7 +1913,7 @@ static void get_active_converter_info( /* decode converter info*/ if (!ds_port.fields.PORT_PRESENT) { link->dpcd_caps.dongle_type = DISPLAY_DONGLE_NONE; - ddc_service_set_dongle_type(link->ddc, + ddc_service_set_dongle_type(link->public.ddc, link->dpcd_caps.dongle_type); return; } @@ -1983,7 +1983,7 @@ static void get_active_converter_info( } } - ddc_service_set_dongle_type(link->ddc, link->dpcd_caps.dongle_type); + ddc_service_set_dongle_type(link->public.ddc, link->dpcd_caps.dongle_type); { struct dp_device_vendor_id dp_id; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index d74bbdce1090..c7e503a91f45 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -646,6 +646,8 @@ struct dc_link { void *priv; bool aux_mode; + + struct ddc_service *ddc; }; struct dpcd_caps { @@ -829,13 +831,6 @@ void dc_set_power_state( enum dc_acpi_cm_power_state power_state); void dc_resume(const struct dc *dc); -/******************************************************************************* - * DDC Interfaces - ******************************************************************************/ - -const struct ddc_service *dc_get_ddc_at_index( - struct dc *dc, uint32_t link_index); - /* * DPCD access interfaces */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index c1273d6142c4..fcda3c7db818 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -151,7 +151,6 @@ struct core_link { struct dc_context *ctx; /* TODO: AUTO remove 'dal' when DC is complete*/ struct link_encoder *link_enc; - struct ddc_service *ddc; struct graphics_object_id link_id; union ddi_channel_mapping ddi_channel_mapping; struct connector_device_tag_info device_tag; -- cgit From 56dcade33fd3c1681a43ebc250523249be3adbb0 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 9 May 2017 10:41:42 -0400 Subject: drm/amd/display: Keep DVI_SINGLE_LINK signal if low clk If user is using DVI->HDMI dongle dual link signal might pose a problem. Keep single link signal type if clk is lower than max tmds clk. Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index ae8b221c85aa..9588217e0220 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1283,9 +1283,12 @@ static void update_stream_signal(struct core_stream *stream) stream->signal = stream->public.output_signal; } - if (stream->signal == SIGNAL_TYPE_DVI_SINGLE_LINK && - stream->public.timing.pix_clk_khz > TMDS_MAX_PIXEL_CLOCK_IN_KHZ) - stream->signal = SIGNAL_TYPE_DVI_DUAL_LINK; + if (dc_is_dvi_signal(stream->signal)) { + if (stream->public.timing.pix_clk_khz > TMDS_MAX_PIXEL_CLOCK_IN_KHZ) + stream->signal = SIGNAL_TYPE_DVI_DUAL_LINK; + else + stream->signal = SIGNAL_TYPE_DVI_SINGLE_LINK; + } } bool resource_is_stream_unchanged( -- cgit From 64b44524d4b28349217718ff641b02ec5ecf7b26 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Tue, 2 May 2017 16:58:39 -0400 Subject: drm/amd/display: bw debug options now apply to dml as well Signed-off-by: Dmytro Laktyushkin Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 41 ++++++++++++++++++++---- 1 file changed, 34 insertions(+), 7 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index eb81edf3afa9..22d98ef69a77 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -614,23 +614,49 @@ static void calc_wm_sets_and_perf_params( context->watermarks.d = context->watermarks.a; } -static void dcn_bw_apply_registry_override(struct core_dc *dc) +static bool dcn_bw_apply_registry_override(struct core_dc *dc) { + bool updated = false; + kernel_fpu_begin(); - if (dc->public.debug.sr_exit_time_ns) + if ((int)(dc->dcn_soc.sr_exit_time * 1000) != dc->public.debug.sr_exit_time_ns + && dc->public.debug.sr_exit_time_ns) { + updated = true; dc->dcn_soc.sr_exit_time = dc->public.debug.sr_exit_time_ns / 1000.0; - if (dc->public.debug.sr_enter_plus_exit_time_ns) + } + + if ((int)(dc->dcn_soc.sr_enter_plus_exit_time * 1000) + != dc->public.debug.sr_enter_plus_exit_time_ns + && dc->public.debug.sr_enter_plus_exit_time_ns) { + updated = true; dc->dcn_soc.sr_enter_plus_exit_time = dc->public.debug.sr_enter_plus_exit_time_ns / 1000.0; - if (dc->public.debug.urgent_latency_ns) + } + + if ((int)(dc->dcn_soc.urgent_latency * 1000) != dc->public.debug.urgent_latency_ns + && dc->public.debug.urgent_latency_ns) { + updated = true; dc->dcn_soc.urgent_latency = dc->public.debug.urgent_latency_ns / 1000.0; - if (dc->public.debug.percent_of_ideal_drambw) + } + + if ((int)(dc->dcn_soc.percent_of_ideal_drambw_received_after_urg_latency * 1000) + != dc->public.debug.percent_of_ideal_drambw + && dc->public.debug.percent_of_ideal_drambw) { + updated = true; dc->dcn_soc.percent_of_ideal_drambw_received_after_urg_latency = dc->public.debug.percent_of_ideal_drambw; - if (dc->public.debug.dram_clock_change_latency_ns) + } + + if ((int)(dc->dcn_soc.dram_clock_change_latency * 1000) + != dc->public.debug.dram_clock_change_latency_ns + && dc->public.debug.dram_clock_change_latency_ns) { + updated = true; dc->dcn_soc.dram_clock_change_latency = dc->public.debug.dram_clock_change_latency_ns / 1000.0; + } kernel_fpu_end(); + + return updated; } bool dcn_validate_bandwidth( @@ -642,7 +668,8 @@ bool dcn_validate_bandwidth( int i, input_idx; int vesa_sync_start, asic_blank_end, asic_blank_start; - dcn_bw_apply_registry_override(DC_TO_CORE(&dc->public)); + if (dcn_bw_apply_registry_override(DC_TO_CORE(&dc->public))) + dcn_bw_sync_calcs_and_dml(DC_TO_CORE(&dc->public)); memset(v, 0, sizeof(*v)); kernel_fpu_begin(); -- cgit From 8d1b404744d0040d2d85c1ff7737a38f29770826 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Wed, 3 May 2017 10:25:51 -0400 Subject: drm/amd/display: Only apply ctx for specific surface. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index fb4eb4364bc7..ece8c96f3636 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1689,19 +1689,21 @@ static void dcn10_apply_ctx_for_surface( { int i; - memcpy(context->res_ctx.mpc_tree, - dc->current_context->res_ctx.mpc_tree, - sizeof(struct mpc_tree_cfg) * dc->res_pool->pipe_count); - for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; - if (!pipe_ctx->surface) + if (!pipe_ctx->surface || pipe_ctx->surface != surface) continue; + /* looking for top pipe to program */ - if (!pipe_ctx->top_pipe) + if (!pipe_ctx->top_pipe) { + memcpy(context->res_ctx.mpc_tree, + dc->current_context->res_ctx.mpc_tree, + sizeof(struct mpc_tree_cfg) * dc->res_pool->pipe_count); + program_all_pipe_in_tree(dc, pipe_ctx, context); + } } for (i = 0; i < dc->res_pool->pipe_count; i++) { -- cgit From a90fbf78a617901181c09aa670e6d9f46f9d13ce Mon Sep 17 00:00:00 2001 From: Leon Elazar Date: Fri, 24 Mar 2017 15:46:24 -0400 Subject: drm/amd/display: Allow MPO on Raven Signed-off-by: Leon Elazar Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 121eb3009445..41613ab5ca69 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -1292,6 +1292,8 @@ static bool construct( dc->public.caps.i2c_speed_in_khz = 100; dc->public.caps.max_cursor_size = 256; + dc->public.caps.max_slave_planes = 1; + if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) dc->public.debug = debug_defaults_drv; else -- cgit From c282ca3390d3327e0f8004d33acb9b022245a958 Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Wed, 3 May 2017 15:19:07 -0400 Subject: drm/amd/display: use signal type to decide whether to set backlight Signed-off-by: Anthony Koo Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 97cfd5bd3853..5d374cb8128b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1389,7 +1389,7 @@ bool dc_link_set_backlight_level(const struct dc_link *dc_link, uint32_t level, dm_logger_write(link->ctx->logger, LOG_BACKLIGHT, "New Backlight level: %d (0x%X)\n", level, level); - if (link->device_tag.dev_id.device_type == DEVICE_TYPE_LCD) { + if (dc_is_embedded_signal(dc_link->connector_signal)) { if (stream != NULL) { core_stream = DC_STREAM_TO_CORE(stream); for (i = 0; i < MAX_PIPES; i++) { -- cgit From cbfd33fd976eb2679c154e44fa34428a43ac8b44 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Tue, 2 May 2017 17:01:10 -0400 Subject: drm/amd/display: do not set_mpc_tree if tree is already setup Signed-off-by: Tony Cheng Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 30 +++++++++++++++++----- 1 file changed, 23 insertions(+), 7 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index ece8c96f3636..41a6fa507982 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -828,7 +828,7 @@ static void reset_front_end_for_pipe( /* TODO: build stream pipes group id. For now, use stream otg * id as pipe group id */ - tree_cfg = &context->res_ctx.mpc_tree[pipe_ctx->mpc_idx]; + tree_cfg = &dc->current_context->res_ctx.mpc_tree[pipe_ctx->mpc_idx]; if (pipe_ctx->top_pipe == NULL) dcn10_delete_mpc_tree(mpc, tree_cfg); @@ -1523,6 +1523,8 @@ static void update_dchubp_dpp( struct tg_color black_color = {0}; struct dcn10_mpc *mpc = TO_DCN10_MPC(dc->res_pool->mpc); + struct pipe_ctx *cur_pipe_ctx = &dc->current_context->res_ctx.pipe_ctx[pipe_ctx->pipe_idx]; + /* depends on DML calculation, DPP clock value may change dynamically */ enable_dppclk( dc->ctx, @@ -1566,6 +1568,7 @@ static void update_dchubp_dpp( */ pipe_ctx->mpc_idx = pipe_ctx->tg->inst; tree_cfg = &context->res_ctx.mpc_tree[pipe_ctx->mpc_idx]; + /* enable when bottom pipe is present and * it does not share a surface with current pipe */ @@ -1576,21 +1579,29 @@ static void update_dchubp_dpp( pipe_ctx->scl_data.lb_params.alpha_en = 0; tree_cfg->mode = TOP_PASSTHRU; } - if (!pipe_ctx->top_pipe) { + if (!pipe_ctx->top_pipe && !cur_pipe_ctx->bottom_pipe) { /* primary pipe, set mpc tree index 0 only */ tree_cfg->num_pipes = 1; tree_cfg->opp_id = pipe_ctx->tg->inst; tree_cfg->dpp[0] = pipe_ctx->pipe_idx; tree_cfg->mpcc[0] = pipe_ctx->pipe_idx; - dcn10_set_mpc_tree(mpc, tree_cfg); - } else { - /* TODO: add position is hard code to 1 for now - * If more than 2 pipes are supported, calculate position - */ + } + + if (!cur_pipe_ctx->top_pipe && !pipe_ctx->top_pipe) { + + if (!cur_pipe_ctx->bottom_pipe) + dcn10_set_mpc_tree(mpc, tree_cfg); + + } else if (!cur_pipe_ctx->top_pipe && pipe_ctx->top_pipe) { + dcn10_add_dpp(mpc, tree_cfg, pipe_ctx->pipe_idx, pipe_ctx->pipe_idx, 1); + } else { + /* nothing to be done here */ + ASSERT(cur_pipe_ctx->top_pipe && pipe_ctx->top_pipe); } + color_space = pipe_ctx->stream->public.output_color_space; color_space_to_black_color(dc, color_space, &black_color); dcn10_set_mpc_background_color(mpc, pipe_ctx->pipe_idx, &black_color); @@ -1641,13 +1652,18 @@ static void program_all_pipe_in_tree( pipe_ctx->mi, &context->watermarks, ref_clk_mhz); lock_otg_master_update(dc->ctx, pipe_ctx->tg->inst); } + pipe_ctx->tg->dlg_otg_param.vready_offset = pipe_ctx->pipe_dlg_param.vready_offset; pipe_ctx->tg->dlg_otg_param.vstartup_start = pipe_ctx->pipe_dlg_param.vstartup_start; pipe_ctx->tg->dlg_otg_param.vupdate_offset = pipe_ctx->pipe_dlg_param.vupdate_offset; pipe_ctx->tg->dlg_otg_param.vupdate_width = pipe_ctx->pipe_dlg_param.vupdate_width; pipe_ctx->tg->dlg_otg_param.signal = pipe_ctx->stream->signal; + pipe_ctx->tg->funcs->program_global_sync( pipe_ctx->tg); + + + update_dchubp_dpp(dc, pipe_ctx, context); } -- cgit From c0ba5ec70eff5cf0e4337b3864c94fa6b128c8d7 Mon Sep 17 00:00:00 2001 From: Ken Chalmers Date: Thu, 4 May 2017 13:34:55 -0400 Subject: drm/amd/display: Continue with stream enable if DP link training fails. Not necessarily a fatal problem - some monitors will recover and show the stream anyway if link training fails. Signed-off-by: Ken Chalmers Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 21 +++++++++++++++++---- drivers/gpu/drm/amd/display/dc/inc/core_status.h | 1 + 2 files changed, 18 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 5d374cb8128b..ffc0eeaad175 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1225,7 +1225,7 @@ static enum dc_status enable_link_dp(struct pipe_ctx *pipe_ctx) status = DC_OK; } else - status = DC_ERROR_UNEXPECTED; + status = DC_FAIL_DP_LINK_TRAINING; enable_stream_features(pipe_ctx); @@ -1833,9 +1833,22 @@ void core_link_enable_stream(struct pipe_ctx *pipe_ctx) { struct core_dc *core_dc = DC_TO_CORE(pipe_ctx->stream->ctx->dc); - if (DC_OK != enable_link(pipe_ctx)) { - BREAK_TO_DEBUGGER(); - return; + enum dc_status status = enable_link(pipe_ctx); + + if (status != DC_OK) { + dm_logger_write(pipe_ctx->stream->ctx->logger, + LOG_WARNING, "enabling link %u failed: %d\n", + pipe_ctx->stream->sink->link->public.link_index, + status); + + /* Abort stream enable *unless* the failure was due to + * DP link training - some DP monitors will recover and + * show the stream anyway. + */ + if (status != DC_FAIL_DP_LINK_TRAINING) { + BREAK_TO_DEBUGGER(); + return; + } } /* turn off otg test pattern if enable */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_status.h b/drivers/gpu/drm/amd/display/dc/inc/core_status.h index 128617dabc4a..b5759c0e5a2f 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_status.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_status.h @@ -41,6 +41,7 @@ enum dc_status { DC_SURFACE_PIXEL_FORMAT_UNSUPPORTED = 11, DC_FAIL_BANDWIDTH_VALIDATE = 12, /* BW and Watermark validation */ DC_FAIL_SCALING = 13, + DC_FAIL_DP_LINK_TRAINING = 14, DC_ERROR_UNEXPECTED = -1 }; -- cgit From fe626734711b5f402fca9df5d33cb0663b6c2fe5 Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Thu, 4 May 2017 14:09:09 -0400 Subject: drm/amd/display: Implement support for backlight optimization - Add functionality to get real hw backlight level as opposed to user level, meaning the level that takes into account backlight ramping over time and backlight reduction due to Varibright - Add backlight optimization which allows for a second OS state that is able to control ABM Signed-off-by: Anthony Koo Reviewed-by: Aric Cyr Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_abm.c | 13 +++++++++++-- drivers/gpu/drm/amd/display/dc/inc/hw/abm.h | 1 + 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c index 393c43559825..cefffe164fe0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c @@ -60,7 +60,7 @@ struct abm_backlight_registers { static struct abm_backlight_registers stored_backlight_registers = {0}; -static unsigned int get_current_backlight(struct dce_abm *abm_dce) +static unsigned int get_current_backlight_16_bit(struct dce_abm *abm_dce) { uint64_t current_backlight; uint32_t round_result; @@ -252,7 +252,7 @@ static void dmcu_set_backlight_level( static void dce_abm_init(struct abm *abm) { struct dce_abm *abm_dce = TO_DCE_ABM(abm); - unsigned int backlight = get_current_backlight(abm_dce); + unsigned int backlight = get_current_backlight_16_bit(abm_dce); REG_WRITE(DC_ABM1_HG_SAMPLE_RATE, 0x103); REG_WRITE(DC_ABM1_HG_SAMPLE_RATE, 0x101); @@ -289,6 +289,14 @@ static void dce_abm_init(struct abm *abm) ABM1_BL_REG_READ_MISSED_FRAME_CLEAR, 1); } +static unsigned int dce_abm_get_current_backlight_8_bit(struct abm *abm) +{ + struct dce_abm *abm_dce = TO_DCE_ABM(abm); + unsigned int backlight = REG_READ(BL1_PWM_CURRENT_ABM_LEVEL); + + return (backlight >> 8); +} + static bool dce_abm_set_level(struct abm *abm, uint32_t level) { struct dce_abm *abm_dce = TO_DCE_ABM(abm); @@ -405,6 +413,7 @@ static const struct abm_funcs dce_funcs = { .set_abm_level = dce_abm_set_level, .init_backlight = dce_abm_init_backlight, .set_backlight_level = dce_abm_set_backlight_level, + .get_current_backlight_8_bit = dce_abm_get_current_backlight_8_bit, .is_dmcu_initialized = is_dmcu_initialized }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h b/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h index ceabbd3bf5f8..da465b3e98e8 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h @@ -40,6 +40,7 @@ struct abm_funcs { unsigned int backlight_level, unsigned int frame_ramp, unsigned int controller_id); + unsigned int (*get_current_backlight_8_bit)(struct abm *abm); bool (*is_dmcu_initialized)(struct abm *abm); }; -- cgit From f3e4341871bee5c91ffbf9d90c4f5af380759e33 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Wed, 3 May 2017 14:21:37 -0400 Subject: drm/amd/display: ifdef some code only needed for DCN Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 4 ++++ drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h | 2 ++ drivers/gpu/drm/amd/display/dc/inc/hw/opp.h | 2 ++ 3 files changed, 8 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index fcda3c7db818..919c6632ee3e 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -31,8 +31,10 @@ #include "dcn_calcs.h" #include "ddc_service_types.h" #include "dc_bios_types.h" +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) #include "mem_input.h" #include "mpc.h" +#endif struct core_stream; @@ -256,7 +258,9 @@ struct resource_pool { struct abm *abm; struct dmcu *dmcu; +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) struct mpc *mpc; +#endif const struct resource_funcs *funcs; const struct resource_caps *res_cap; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h index 0f952e5b3ae8..1298d306db69 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h @@ -122,7 +122,9 @@ struct ipp_funcs { struct input_pixel_processor *ipp, const struct pwl_params *params); +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) void (*ipp_destroy)(struct input_pixel_processor **ipp); +#endif }; #endif /* __DAL_IPP_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h index 64d43257db96..a101f4b5e0c7 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h @@ -27,7 +27,9 @@ #define __DAL_OPP_H__ #include "hw_shared.h" +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) #include "dc_hw_types.h" +#endif #include "transform.h" struct fixed31_32; -- cgit From 3273d3bfe58094d9c7b52448399e20f496475afe Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Fri, 5 May 2017 11:30:06 -0400 Subject: drm/amd/display: Fix race. Problem : A race between two adjecent page flips makes the earlier one to release an alocated frame buffer for the subsequent one - since there are 2 frambuffer swapped back and forth between flips, the 'new' fb of the later flip is actually the 'previous' fb for the earlier flip. Fix: Don't set fb->address = 0 in cleanup hook, this is unnecessery and erases the newly cached adress that was set in prepare_fb of the second flip. Signed-off-by: Andrey Grodzovsky Reviewed-by: Andrey Grodzovsky Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 6bd8048ba21e..9c0dc9d07626 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -1622,9 +1622,7 @@ static void dm_plane_helper_cleanup_fb( amdgpu_bo_unpin(rbo); amdgpu_bo_unreserve(rbo); amdgpu_bo_unref(&rbo); - } - - afb->address = 0; + }; } int dm_create_validation_set_for_connector(struct drm_connector *connector, -- cgit From ac5c294719909bd5d2d3f8c74f894bdda5744916 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 5 May 2017 15:07:55 -0400 Subject: drm/amd/display: prevent assert on error of 1 in calc_freesync_range Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/modules/freesync/freesync.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index c5330f3cc1de..05a086c7b31a 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -422,12 +422,14 @@ static void calc_freesync_range(struct core_freesync *core_freesync, /* In case of 4k free sync monitor, vmin or vmax cannot be less than vtotal */ if (state->freesync_range.vmin < vtotal) { - ASSERT(false); + /* Error of 1 is permissible */ + ASSERT((state->freesync_range.vmin + 1) >= vtotal); state->freesync_range.vmin = vtotal; } if (state->freesync_range.vmax < vtotal) { - ASSERT(false); + /* Error of 1 is permissible */ + ASSERT((state->freesync_range.vmax + 1) >= vtotal); state->freesync_range.vmax = vtotal; } -- cgit From 9037d802a97812cb8d614b48f817a5532cf1558c Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Tue, 2 May 2017 17:29:48 -0400 Subject: drm/amd/display: refactor bw related variable structure in val_ctx Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c | 18 ++--- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 79 +++++++++++----------- drivers/gpu/drm/amd/display/dc/core/dc.c | 20 +----- drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c | 6 +- drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h | 12 ++-- .../amd/display/dc/dce100/dce100_hw_sequencer.c | 9 ++- .../drm/amd/display/dc/dce100/dce100_resource.c | 4 +- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 65 +++++++++--------- .../drm/amd/display/dc/dce110/dce110_mem_input.c | 12 ++-- .../drm/amd/display/dc/dce110/dce110_mem_input.h | 6 +- .../drm/amd/display/dc/dce110/dce110_mem_input_v.c | 30 ++++---- .../drm/amd/display/dc/dce110/dce110_mem_input_v.h | 6 +- .../drm/amd/display/dc/dce110/dce110_resource.c | 63 +++++++++-------- .../drm/amd/display/dc/dce112/dce112_resource.c | 63 +++++++++-------- .../gpu/drm/amd/display/dc/dce80/dce80_resource.c | 4 +- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 38 +++++------ .../gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c | 6 +- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 58 ++++++++++++---- drivers/gpu/drm/amd/display/dc/inc/dce_calcs.h | 29 +------- drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h | 20 ++++-- 20 files changed, 270 insertions(+), 278 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c index 627b7582394a..87666987429e 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c @@ -2557,7 +2557,7 @@ void bw_calcs_init(struct bw_calcs_dceip *bw_dceip, */ static bool is_display_configuration_supported( const struct bw_calcs_vbios *vbios, - const struct bw_calcs_output *calcs_output) + const struct dce_bw_output *calcs_output) { uint32_t int_max_clk; @@ -2568,7 +2568,7 @@ static bool is_display_configuration_supported( int_max_clk = bw_fixed_to_int(vbios->high_sclk); int_max_clk *= 1000; /* MHz to kHz */ - if (calcs_output->required_sclk > int_max_clk) + if (calcs_output->sclk_khz > int_max_clk) return false; return true; @@ -2790,7 +2790,7 @@ bool bw_calcs(struct dc_context *ctx, const struct bw_calcs_vbios *vbios, const struct pipe_ctx pipe[], int pipe_count, - struct bw_calcs_output *calcs_output) + struct dce_bw_output *calcs_output) { struct bw_calcs_data *data = dm_alloc(sizeof(struct bw_calcs_data)); @@ -2831,20 +2831,20 @@ bool bw_calcs(struct dc_context *ctx, bw_int_to_fixed(1000))); calcs_output->blackout_recovery_time_us = bw_fixed_to_int(data->blackout_recovery_time); - calcs_output->required_sclk = + calcs_output->sclk_khz = bw_fixed_to_int(bw_mul(data->required_sclk, bw_int_to_fixed(1000))); - calcs_output->required_sclk_deep_sleep = + calcs_output->sclk_deep_sleep_khz = bw_fixed_to_int(bw_mul(data->sclk_deep_sleep, bw_int_to_fixed(1000))); if (yclk_lvl == 0) - calcs_output->required_yclk = bw_fixed_to_int( + calcs_output->yclk_khz = bw_fixed_to_int( bw_mul(low_yclk, bw_int_to_fixed(1000))); else if (yclk_lvl == 1) - calcs_output->required_yclk = bw_fixed_to_int( + calcs_output->yclk_khz = bw_fixed_to_int( bw_mul(mid_yclk, bw_int_to_fixed(1000))); else - calcs_output->required_yclk = bw_fixed_to_int( + calcs_output->yclk_khz = bw_fixed_to_int( bw_mul(high_yclk, bw_int_to_fixed(1000))); /* units: nanosecond, 16bit storage. */ @@ -3245,7 +3245,7 @@ bool bw_calcs(struct dc_context *ctx, calcs_output->cpup_state_change_enable = true; calcs_output->stutter_mode_enable = true; calcs_output->dispclk_khz = 0; - calcs_output->required_sclk = 0; + calcs_output->sclk_khz = 0; } dm_free(data); diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 22d98ef69a77..1b9edfda2b98 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -470,17 +470,17 @@ static void dcn_dml_wm_override( a.cpstate = dml_wm_cstate_pstate_e2e(dml, input, active_count); a.pte_meta_urgent = dml_wm_pte_meta_urgent(dml, a.urgent); - context->watermarks.a.cstate_pstate.cstate_exit_ns = + context->bw.dcn.watermarks.a.cstate_pstate.cstate_exit_ns = a.cpstate.cstate_exit_us * 1000; - context->watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns = + context->bw.dcn.watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns = a.cpstate.cstate_enter_plus_exit_us * 1000; - context->watermarks.a.cstate_pstate.pstate_change_ns = + context->bw.dcn.watermarks.a.cstate_pstate.pstate_change_ns = a.cpstate.pstate_change_us * 1000; - context->watermarks.a.pte_meta_urgent_ns = a.pte_meta_urgent * 1000; - context->watermarks.a.urgent_ns = a.urgent * 1000; - context->watermarks.b = context->watermarks.a; - context->watermarks.c = context->watermarks.a; - context->watermarks.d = context->watermarks.a; + context->bw.dcn.watermarks.a.pte_meta_urgent_ns = a.pte_meta_urgent * 1000; + context->bw.dcn.watermarks.a.urgent_ns = a.urgent * 1000; + context->bw.dcn.watermarks.b = context->bw.dcn.watermarks.a; + context->bw.dcn.watermarks.c = context->bw.dcn.watermarks.a; + context->bw.dcn.watermarks.d = context->bw.dcn.watermarks.a; for (i = 0, in_idx = 0; i < pool->pipe_count; i++) { @@ -543,28 +543,28 @@ static void calc_wm_sets_and_perf_params( v->fabric_and_dram_bandwidth = v->fabric_and_dram_bandwidth_vnom0p8; dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performance_calculation(v); - context->watermarks.b.cstate_pstate.cstate_exit_ns = + context->bw.dcn.watermarks.b.cstate_pstate.cstate_exit_ns = v->stutter_exit_watermark * 1000; - context->watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns = + context->bw.dcn.watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns = v->stutter_enter_plus_exit_watermark * 1000; - context->watermarks.b.cstate_pstate.pstate_change_ns = + context->bw.dcn.watermarks.b.cstate_pstate.pstate_change_ns = v->dram_clock_change_watermark * 1000; - context->watermarks.b.pte_meta_urgent_ns = v->ptemeta_urgent_watermark * 1000; - context->watermarks.b.urgent_ns = v->urgent_watermark * 1000; + context->bw.dcn.watermarks.b.pte_meta_urgent_ns = v->ptemeta_urgent_watermark * 1000; + context->bw.dcn.watermarks.b.urgent_ns = v->urgent_watermark * 1000; v->dcfclk_per_state[1] = v->dcfclkv_nom0p8; v->dcfclk_per_state[0] = v->dcfclkv_nom0p8; v->dcfclk = v->dcfclkv_nom0p8; dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performance_calculation(v); - context->watermarks.c.cstate_pstate.cstate_exit_ns = + context->bw.dcn.watermarks.c.cstate_pstate.cstate_exit_ns = v->stutter_exit_watermark * 1000; - context->watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns = + context->bw.dcn.watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns = v->stutter_enter_plus_exit_watermark * 1000; - context->watermarks.c.cstate_pstate.pstate_change_ns = + context->bw.dcn.watermarks.c.cstate_pstate.pstate_change_ns = v->dram_clock_change_watermark * 1000; - context->watermarks.c.pte_meta_urgent_ns = v->ptemeta_urgent_watermark * 1000; - context->watermarks.c.urgent_ns = v->urgent_watermark * 1000; + context->bw.dcn.watermarks.c.pte_meta_urgent_ns = v->ptemeta_urgent_watermark * 1000; + context->bw.dcn.watermarks.c.urgent_ns = v->urgent_watermark * 1000; } if (v->voltage_level < 3) { @@ -578,14 +578,14 @@ static void calc_wm_sets_and_perf_params( v->dcfclk = v->dcfclkv_max0p9; dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performance_calculation(v); - context->watermarks.d.cstate_pstate.cstate_exit_ns = + context->bw.dcn.watermarks.d.cstate_pstate.cstate_exit_ns = v->stutter_exit_watermark * 1000; - context->watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns = + context->bw.dcn.watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns = v->stutter_enter_plus_exit_watermark * 1000; - context->watermarks.d.cstate_pstate.pstate_change_ns = + context->bw.dcn.watermarks.d.cstate_pstate.pstate_change_ns = v->dram_clock_change_watermark * 1000; - context->watermarks.d.pte_meta_urgent_ns = v->ptemeta_urgent_watermark * 1000; - context->watermarks.d.urgent_ns = v->urgent_watermark * 1000; + context->bw.dcn.watermarks.d.pte_meta_urgent_ns = v->ptemeta_urgent_watermark * 1000; + context->bw.dcn.watermarks.d.urgent_ns = v->urgent_watermark * 1000; } v->fabric_and_dram_bandwidth_per_state[2] = v->fabric_and_dram_bandwidth_vnom0p8; @@ -598,20 +598,20 @@ static void calc_wm_sets_and_perf_params( v->dcfclk = v->dcfclk_per_state[v->voltage_level]; dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performance_calculation(v); - context->watermarks.a.cstate_pstate.cstate_exit_ns = + context->bw.dcn.watermarks.a.cstate_pstate.cstate_exit_ns = v->stutter_exit_watermark * 1000; - context->watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns = + context->bw.dcn.watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns = v->stutter_enter_plus_exit_watermark * 1000; - context->watermarks.a.cstate_pstate.pstate_change_ns = + context->bw.dcn.watermarks.a.cstate_pstate.pstate_change_ns = v->dram_clock_change_watermark * 1000; - context->watermarks.a.pte_meta_urgent_ns = v->ptemeta_urgent_watermark * 1000; - context->watermarks.a.urgent_ns = v->urgent_watermark * 1000; + context->bw.dcn.watermarks.a.pte_meta_urgent_ns = v->ptemeta_urgent_watermark * 1000; + context->bw.dcn.watermarks.a.urgent_ns = v->urgent_watermark * 1000; if (v->voltage_level >= 2) { - context->watermarks.b = context->watermarks.a; - context->watermarks.c = context->watermarks.a; + context->bw.dcn.watermarks.b = context->bw.dcn.watermarks.a; + context->bw.dcn.watermarks.c = context->bw.dcn.watermarks.a; } if (v->voltage_level >= 3) - context->watermarks.d = context->watermarks.a; + context->bw.dcn.watermarks.d = context->bw.dcn.watermarks.a; } static bool dcn_bw_apply_registry_override(struct core_dc *dc) @@ -916,17 +916,16 @@ bool dcn_validate_bandwidth( display_pipe_configuration(v); calc_wm_sets_and_perf_params(context, v); - context->fclk_khz = (int)(bw_consumed * 1000000 / + context->bw.dcn.calc_clk.fclk_khz = (int)(bw_consumed * 1000000 / (ddr4_dram_factor_single_Channel * v->number_of_channels)); - context->dram_ccm_us = (int)(v->dram_clock_change_margin); - context->min_active_dram_ccm_us = (int)(v->min_active_dram_clock_change_margin); - context->dcfclk_deep_sleep_khz = (int)(v->dcf_clk_deep_sleep * 1000); - context->dcfclk_khz = (int)(v->dcfclk * 1000); - context->dispclk_khz = (int)(v->dispclk * 1000); + context->bw.dcn.calc_clk.dram_ccm_us = (int)(v->dram_clock_change_margin); + context->bw.dcn.calc_clk.min_active_dram_ccm_us = (int)(v->min_active_dram_clock_change_margin); + context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz = (int)(v->dcf_clk_deep_sleep * 1000); + context->bw.dcn.calc_clk.dcfclk_khz = (int)(v->dcfclk * 1000); + context->bw.dcn.calc_clk.dispclk_khz = (int)(v->dispclk * 1000); if (dc->public.debug.max_disp_clk == true) - context->dispclk_khz = (int)(dc->dcn_soc.max_dispclk_vmax0p9 * 1000); - context->dppclk_khz = (int)(v->dppclk * 1000); - context->dppclk_div = (int)(v->dispclk_dppclk_ratio) == 2; + context->bw.dcn.calc_clk.dispclk_khz = (int)(dc->dcn_soc.max_dispclk_vmax0p9 * 1000); + context->bw.dcn.calc_clk.dppclk_div = (int)(v->dispclk_dppclk_ratio) == 2; for (i = 0, input_idx = 0; i < pool->pipe_count; i++) { struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index d063a252ccd9..b30d4bc7b040 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -970,13 +970,7 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) { int i; struct core_dc *core_dc = DC_TO_CORE(dc); - struct validate_context *context = dm_alloc(sizeof(struct validate_context)); - - if (!context) { - dm_error("%s: failed to create validate ctx\n", __func__); - return false; - } - dc_resource_validate_ctx_copy_construct(core_dc->current_context, context); + struct validate_context *context = core_dc->current_context; post_surface_trace(dc); @@ -986,21 +980,9 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) core_dc->hwss.power_down_front_end( core_dc, &context->res_ctx.pipe_ctx[i]); } - if (!core_dc->res_pool->funcs->validate_bandwidth(core_dc, context)) { - BREAK_TO_DEBUGGER(); - dc_resource_validate_ctx_destruct(context); - dm_free(context); - return false; - } core_dc->hwss.set_bandwidth(core_dc, context, true); - if (core_dc->current_context) { - dc_resource_validate_ctx_destruct(core_dc->current_context); - dm_free(core_dc->current_context); - } - core_dc->current_context = context; - return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c index 884f453d91b0..9da539db287c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c @@ -218,9 +218,9 @@ static void program_stutter_watermark(struct mem_input *mi, } void dce_mem_input_program_display_marks(struct mem_input *mi, - struct bw_watermarks nbp, - struct bw_watermarks stutter, - struct bw_watermarks urgent, + struct dce_watermarks nbp, + struct dce_watermarks stutter, + struct dce_watermarks urgent, uint32_t total_dest_line_time_ns) { uint32_t stutter_en = mi->ctx->dc->debug.disable_stutter ? 0 : 1; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h index 6af533bdf98c..be37f52e9ba1 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h @@ -25,6 +25,10 @@ #ifndef __DCE_MEM_INPUT_H__ #define __DCE_MEM_INPUT_H__ +#include "dc_hw_types.h" +struct dce_watermarks; +struct mem_input; + #define MI_DCE_BASE_REG_LIST(id)\ SRI(GRPH_ENABLE, DCP, id),\ SRI(GRPH_CONTROL, DCP, id),\ @@ -262,8 +266,6 @@ struct dce_mem_input_wa { uint8_t single_head_rdreq_dmif_limit; }; -struct mem_input; - void dce_mem_input_program_pte_vm(struct mem_input *mi, enum surface_pixel_format format, union dc_tiling_info *tiling_info, @@ -288,9 +290,9 @@ void dce_mem_input_free_dmif(struct mem_input *mi, uint32_t total_stream_num); void dce_mem_input_program_display_marks(struct mem_input *mi, - struct bw_watermarks nbp, - struct bw_watermarks stutter, - struct bw_watermarks urgent, + struct dce_watermarks nbp, + struct dce_watermarks stutter, + struct dce_watermarks urgent, uint32_t total_dest_line_time_ns); #endif /*__DCE_MEM_INPUT_H__*/ diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c index 30c197f378dc..843f50a08e21 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c @@ -114,7 +114,7 @@ static void dce100_pplib_apply_display_requirements( pp_display_cfg->avail_mclk_switch_time_us = dce110_get_min_vblank_time_us(context); - pp_display_cfg->min_memory_clock_khz = context->bw_results.required_yclk + pp_display_cfg->min_memory_clock_khz = context->bw.dce.yclk_khz / MEMORY_TYPE_MULTIPLIER; dce110_fill_display_configs(context, pp_display_cfg); @@ -131,12 +131,11 @@ void dce100_set_bandwidth( struct validate_context *context, bool decrease_allowed) { - if (decrease_allowed || context->dispclk_khz > dc->current_context->dispclk_khz) { + if (decrease_allowed || context->bw.dce.dispclk_khz > dc->current_context->bw.dce.dispclk_khz) { dc->res_pool->display_clock->funcs->set_clock( dc->res_pool->display_clock, - context->dispclk_khz * 115 / 100); - dc->current_context->bw_results.dispclk_khz = context->dispclk_khz; - dc->current_context->dispclk_khz = context->dispclk_khz; + context->bw.dce.dispclk_khz * 115 / 100); + dc->current_context->bw.dce.dispclk_khz = context->bw.dce.dispclk_khz; } dce100_pplib_apply_display_requirements(dc, context); } diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index f0700706d7c9..254f9e4d0fc8 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -764,8 +764,8 @@ bool dce100_validate_bandwidth( struct validate_context *context) { /* TODO implement when needed but for now hardcode max value*/ - context->dispclk_khz = 681000; - context->bw_results.required_yclk = 250000 * MEMORY_TYPE_MULTIPLIER; + context->bw.dce.dispclk_khz = 681000; + context->bw.dce.yclk_khz = 250000 * MEMORY_TYPE_MULTIPLIER; return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index c89df8acb458..41aeceba5ae5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1252,17 +1252,17 @@ void dce110_set_displaymarks( dc->bw_vbios.blackout_duration, pipe_ctx->stream); pipe_ctx->mi->funcs->mem_input_program_display_marks( pipe_ctx->mi, - context->bw_results.nbp_state_change_wm_ns[num_pipes], - context->bw_results.stutter_exit_wm_ns[num_pipes], - context->bw_results.urgent_wm_ns[num_pipes], + context->bw.dce.nbp_state_change_wm_ns[num_pipes], + context->bw.dce.stutter_exit_wm_ns[num_pipes], + context->bw.dce.urgent_wm_ns[num_pipes], total_dest_line_time_ns); if (i == underlay_idx) { num_pipes++; pipe_ctx->mi->funcs->mem_input_program_chroma_display_marks( pipe_ctx->mi, - context->bw_results.nbp_state_change_wm_ns[num_pipes], - context->bw_results.stutter_exit_wm_ns[num_pipes], - context->bw_results.urgent_wm_ns[num_pipes], + context->bw.dce.nbp_state_change_wm_ns[num_pipes], + context->bw.dce.stutter_exit_wm_ns[num_pipes], + context->bw.dce.urgent_wm_ns[num_pipes], total_dest_line_time_ns); } num_pipes++; @@ -1275,9 +1275,9 @@ static void set_safe_displaymarks( { int i; int underlay_idx = pool->underlay_pipe_index; - struct bw_watermarks max_marks = { + struct dce_watermarks max_marks = { MAX_WATERMARK, MAX_WATERMARK, MAX_WATERMARK, MAX_WATERMARK }; - struct bw_watermarks nbp_marks = { + struct dce_watermarks nbp_marks = { SAFE_NBP_MARK, SAFE_NBP_MARK, SAFE_NBP_MARK, SAFE_NBP_MARK }; for (i = 0; i < MAX_PIPES; i++) { @@ -1502,7 +1502,7 @@ static void apply_min_clocks( /* get the required state based on state dependent clocks: * display clock and pixel clock */ - req_clocks.display_clk_khz = context->dispclk_khz; + req_clocks.display_clk_khz = context->bw.dce.dispclk_khz; req_clocks.pixel_clk_khz = get_max_pixel_clock_for_all_paths( dc, context, true); @@ -1647,30 +1647,30 @@ enum dc_status dce110_apply_ctx_to_hw( apply_min_clocks(dc, context, &clocks_state, true); #if defined(CONFIG_DRM_AMD_DC_DCN1_0) - if (context->fclk_khz - > dc->current_context->fclk_khz) { + if (context->bw.dcn.calc_clk.fclk_khz + > dc->current_context->bw.dcn.calc_clk.fclk_khz) { struct dm_pp_clock_for_voltage_req clock; clock.clk_type = DM_PP_CLOCK_TYPE_FCLK; - clock.clocks_in_khz = context->fclk_khz; + clock.clocks_in_khz = context->bw.dcn.calc_clk.fclk_khz; dm_pp_apply_clock_for_voltage_request(dc->ctx, &clock); - dc->current_context->fclk_khz = clock.clocks_in_khz; + dc->current_context->bw.dcn.calc_clk.fclk_khz = clock.clocks_in_khz; } - if (context->dcfclk_khz - > dc->current_context->dcfclk_khz) { + if (context->bw.dcn.calc_clk.dcfclk_khz + > dc->current_context->bw.dcn.calc_clk.dcfclk_khz) { struct dm_pp_clock_for_voltage_req clock; clock.clk_type = DM_PP_CLOCK_TYPE_DCFCLK; - clock.clocks_in_khz = context->dcfclk_khz; + clock.clocks_in_khz = context->bw.dcn.calc_clk.dcfclk_khz; dm_pp_apply_clock_for_voltage_request(dc->ctx, &clock); - dc->current_context->dcfclk_khz = clock.clocks_in_khz; + dc->current_context->bw.dcn.calc_clk.dcfclk_khz = clock.clocks_in_khz; } #endif - if (context->dispclk_khz - > dc->current_context->dispclk_khz) { + if (context->bw.dce.dispclk_khz + > dc->current_context->bw.dce.dispclk_khz) { dc->res_pool->display_clock->funcs->set_clock( dc->res_pool->display_clock, - context->dispclk_khz * 115 / 100); + context->bw.dce.dispclk_khz * 115 / 100); } /* program audio wall clock. use HDMI as clock source if HDMI * audio active. Otherwise, use DP as clock source @@ -2275,32 +2275,32 @@ static void pplib_apply_display_requirements( struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg; pp_display_cfg->all_displays_in_sync = - context->bw_results.all_displays_in_sync; + context->bw.dce.all_displays_in_sync; pp_display_cfg->nb_pstate_switch_disable = - context->bw_results.nbp_state_change_enable == false; + context->bw.dce.nbp_state_change_enable == false; pp_display_cfg->cpu_cc6_disable = - context->bw_results.cpuc_state_change_enable == false; + context->bw.dce.cpuc_state_change_enable == false; pp_display_cfg->cpu_pstate_disable = - context->bw_results.cpup_state_change_enable == false; + context->bw.dce.cpup_state_change_enable == false; pp_display_cfg->cpu_pstate_separation_time = - context->bw_results.blackout_recovery_time_us; + context->bw.dce.blackout_recovery_time_us; - pp_display_cfg->min_memory_clock_khz = context->bw_results.required_yclk + pp_display_cfg->min_memory_clock_khz = context->bw.dce.yclk_khz / MEMORY_TYPE_MULTIPLIER; pp_display_cfg->min_engine_clock_khz = determine_sclk_from_bounding_box( dc, - context->bw_results.required_sclk); + context->bw.dce.sclk_khz); pp_display_cfg->min_engine_clock_deep_sleep_khz - = context->bw_results.required_sclk_deep_sleep; + = context->bw.dce.sclk_deep_sleep_khz; pp_display_cfg->avail_mclk_switch_time_us = dce110_get_min_vblank_time_us(context); /* TODO: dce11.2*/ pp_display_cfg->avail_mclk_switch_time_in_disp_active_us = 0; - pp_display_cfg->disp_clk_khz = context->dispclk_khz; + pp_display_cfg->disp_clk_khz = context->bw.dce.dispclk_khz; dce110_fill_display_configs(context, pp_display_cfg); @@ -2329,12 +2329,11 @@ static void dce110_set_bandwidth( { dce110_set_displaymarks(dc, context); - if (decrease_allowed || context->dispclk_khz > dc->current_context->dispclk_khz) { + if (decrease_allowed || context->bw.dce.dispclk_khz > dc->current_context->bw.dce.dispclk_khz) { dc->res_pool->display_clock->funcs->set_clock( dc->res_pool->display_clock, - context->dispclk_khz * 115 / 100); - dc->current_context->bw_results.dispclk_khz = context->dispclk_khz; - dc->current_context->dispclk_khz = context->dispclk_khz; + context->bw.dce.dispclk_khz * 115 / 100); + dc->current_context->bw.dce.dispclk_khz = context->bw.dce.dispclk_khz; } pplib_apply_display_requirements(dc, context); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c index a20feaedfca4..45e1a8d15d9b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c @@ -166,7 +166,7 @@ bool dce110_mem_input_program_surface_flip_and_addr( static void program_urgency_watermark( const struct dc_context *ctx, const uint32_t offset, - struct bw_watermarks marks_low, + struct dce_watermarks marks_low, uint32_t total_dest_line_time_ns) { /* register value */ @@ -224,7 +224,7 @@ static void program_urgency_watermark( static void program_stutter_watermark( const struct dc_context *ctx, const uint32_t offset, - struct bw_watermarks marks) + struct dce_watermarks marks) { /* register value */ uint32_t stutter_cntl = 0; @@ -289,7 +289,7 @@ static void program_stutter_watermark( static void program_nbp_watermark( const struct dc_context *ctx, const uint32_t offset, - struct bw_watermarks marks) + struct dce_watermarks marks) { uint32_t value; uint32_t addr; @@ -372,9 +372,9 @@ static void program_nbp_watermark( void dce110_mem_input_program_display_marks( struct mem_input *mem_input, - struct bw_watermarks nbp, - struct bw_watermarks stutter, - struct bw_watermarks urgent, + struct dce_watermarks nbp, + struct dce_watermarks stutter, + struct dce_watermarks urgent, uint32_t total_dest_line_time_ns) { struct dce110_mem_input *bm_dce110 = TO_DCE110_MEM_INPUT(mem_input); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.h index 4aec18c94c49..5f10f266f096 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.h @@ -55,9 +55,9 @@ bool dce110_mem_input_construct( */ void dce110_mem_input_program_display_marks( struct mem_input *mem_input, - struct bw_watermarks nbp, - struct bw_watermarks stutter, - struct bw_watermarks urgent, + struct dce_watermarks nbp, + struct dce_watermarks stutter, + struct dce_watermarks urgent, uint32_t total_dest_line_time_ns); /* diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c index 9c32b5bbdff5..02739d3efa97 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c @@ -679,7 +679,7 @@ static void program_urgency_watermark( const struct dc_context *ctx, const uint32_t urgency_addr, const uint32_t wm_addr, - struct bw_watermarks marks_low, + struct dce_watermarks marks_low, uint32_t total_dest_line_time_ns) { /* register value */ @@ -734,7 +734,7 @@ static void program_urgency_watermark( static void program_urgency_watermark_l( const struct dc_context *ctx, - struct bw_watermarks marks_low, + struct dce_watermarks marks_low, uint32_t total_dest_line_time_ns) { program_urgency_watermark( @@ -747,7 +747,7 @@ static void program_urgency_watermark_l( static void program_urgency_watermark_c( const struct dc_context *ctx, - struct bw_watermarks marks_low, + struct dce_watermarks marks_low, uint32_t total_dest_line_time_ns) { program_urgency_watermark( @@ -762,7 +762,7 @@ static void program_stutter_watermark( const struct dc_context *ctx, const uint32_t stutter_addr, const uint32_t wm_addr, - struct bw_watermarks marks) + struct dce_watermarks marks) { /* register value */ uint32_t stutter_cntl = 0; @@ -822,7 +822,7 @@ static void program_stutter_watermark( static void program_stutter_watermark_l( const struct dc_context *ctx, - struct bw_watermarks marks) + struct dce_watermarks marks) { program_stutter_watermark(ctx, mmDPGV0_PIPE_STUTTER_CONTROL, @@ -832,7 +832,7 @@ static void program_stutter_watermark_l( static void program_stutter_watermark_c( const struct dc_context *ctx, - struct bw_watermarks marks) + struct dce_watermarks marks) { program_stutter_watermark(ctx, mmDPGV1_PIPE_STUTTER_CONTROL, @@ -844,7 +844,7 @@ static void program_nbp_watermark( const struct dc_context *ctx, const uint32_t wm_mask_ctrl_addr, const uint32_t nbp_pstate_ctrl_addr, - struct bw_watermarks marks) + struct dce_watermarks marks) { uint32_t value; @@ -926,7 +926,7 @@ static void program_nbp_watermark( static void program_nbp_watermark_l( const struct dc_context *ctx, - struct bw_watermarks marks) + struct dce_watermarks marks) { program_nbp_watermark(ctx, mmDPGV0_WATERMARK_MASK_CONTROL, @@ -936,7 +936,7 @@ static void program_nbp_watermark_l( static void program_nbp_watermark_c( const struct dc_context *ctx, - struct bw_watermarks marks) + struct dce_watermarks marks) { program_nbp_watermark(ctx, mmDPGV1_WATERMARK_MASK_CONTROL, @@ -946,9 +946,9 @@ static void program_nbp_watermark_c( void dce110_mem_input_v_program_display_marks( struct mem_input *mem_input, - struct bw_watermarks nbp, - struct bw_watermarks stutter, - struct bw_watermarks urgent, + struct dce_watermarks nbp, + struct dce_watermarks stutter, + struct dce_watermarks urgent, uint32_t total_dest_line_time_ns) { program_urgency_watermark_l( @@ -968,9 +968,9 @@ void dce110_mem_input_v_program_display_marks( void dce110_mem_input_program_chroma_display_marks( struct mem_input *mem_input, - struct bw_watermarks nbp, - struct bw_watermarks stutter, - struct bw_watermarks urgent, + struct dce_watermarks nbp, + struct dce_watermarks stutter, + struct dce_watermarks urgent, uint32_t total_dest_line_time_ns) { program_urgency_watermark_c( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.h index 44cf066279c0..b2667eefa3d0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.h @@ -38,9 +38,9 @@ bool dce110_mem_input_v_construct( */ void dce110_mem_input_v_program_display_marks( struct mem_input *mem_input, - struct bw_watermarks nbp, - struct bw_watermarks stutter, - struct bw_watermarks urgent, + struct dce_watermarks nbp, + struct dce_watermarks stutter, + struct dce_watermarks urgent, uint32_t total_dest_line_time_ns); /* diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 5b2b41efa5f0..041d11968566 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -875,9 +875,8 @@ bool dce110_validate_bandwidth( &dc->bw_vbios, context->res_ctx.pipe_ctx, dc->res_pool->pipe_count, - &context->bw_results)) + &context->bw.dce)) result = true; - context->dispclk_khz = context->bw_results.dispclk_khz; if (!result) dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_VALIDATION, @@ -887,8 +886,8 @@ bool dce110_validate_bandwidth( context->streams[0]->public.timing.v_addressable, context->streams[0]->public.timing.pix_clk_khz); - if (memcmp(&dc->current_context->bw_results, - &context->bw_results, sizeof(context->bw_results))) { + if (memcmp(&dc->current_context->bw.dce, + &context->bw.dce, sizeof(context->bw.dce))) { struct log_entry log_entry; dm_logger_open( dc->ctx->logger, @@ -898,43 +897,43 @@ bool dce110_validate_bandwidth( "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n" "stutMark_b: %d stutMark_a: %d\n", __func__, - context->bw_results.nbp_state_change_wm_ns[0].b_mark, - context->bw_results.nbp_state_change_wm_ns[0].a_mark, - context->bw_results.urgent_wm_ns[0].b_mark, - context->bw_results.urgent_wm_ns[0].a_mark, - context->bw_results.stutter_exit_wm_ns[0].b_mark, - context->bw_results.stutter_exit_wm_ns[0].a_mark); + context->bw.dce.nbp_state_change_wm_ns[0].b_mark, + context->bw.dce.nbp_state_change_wm_ns[0].a_mark, + context->bw.dce.urgent_wm_ns[0].b_mark, + context->bw.dce.urgent_wm_ns[0].a_mark, + context->bw.dce.stutter_exit_wm_ns[0].b_mark, + context->bw.dce.stutter_exit_wm_ns[0].a_mark); dm_logger_append(&log_entry, "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n" "stutMark_b: %d stutMark_a: %d\n", - context->bw_results.nbp_state_change_wm_ns[1].b_mark, - context->bw_results.nbp_state_change_wm_ns[1].a_mark, - context->bw_results.urgent_wm_ns[1].b_mark, - context->bw_results.urgent_wm_ns[1].a_mark, - context->bw_results.stutter_exit_wm_ns[1].b_mark, - context->bw_results.stutter_exit_wm_ns[1].a_mark); + context->bw.dce.nbp_state_change_wm_ns[1].b_mark, + context->bw.dce.nbp_state_change_wm_ns[1].a_mark, + context->bw.dce.urgent_wm_ns[1].b_mark, + context->bw.dce.urgent_wm_ns[1].a_mark, + context->bw.dce.stutter_exit_wm_ns[1].b_mark, + context->bw.dce.stutter_exit_wm_ns[1].a_mark); dm_logger_append(&log_entry, "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n" "stutMark_b: %d stutMark_a: %d stutter_mode_enable: %d\n", - context->bw_results.nbp_state_change_wm_ns[2].b_mark, - context->bw_results.nbp_state_change_wm_ns[2].a_mark, - context->bw_results.urgent_wm_ns[2].b_mark, - context->bw_results.urgent_wm_ns[2].a_mark, - context->bw_results.stutter_exit_wm_ns[2].b_mark, - context->bw_results.stutter_exit_wm_ns[2].a_mark, - context->bw_results.stutter_mode_enable); + context->bw.dce.nbp_state_change_wm_ns[2].b_mark, + context->bw.dce.nbp_state_change_wm_ns[2].a_mark, + context->bw.dce.urgent_wm_ns[2].b_mark, + context->bw.dce.urgent_wm_ns[2].a_mark, + context->bw.dce.stutter_exit_wm_ns[2].b_mark, + context->bw.dce.stutter_exit_wm_ns[2].a_mark, + context->bw.dce.stutter_mode_enable); dm_logger_append(&log_entry, "cstate: %d pstate: %d nbpstate: %d sync: %d dispclk: %d\n" "sclk: %d sclk_sleep: %d yclk: %d blackout_recovery_time_us: %d\n", - context->bw_results.cpuc_state_change_enable, - context->bw_results.cpup_state_change_enable, - context->bw_results.nbp_state_change_enable, - context->bw_results.all_displays_in_sync, - context->bw_results.dispclk_khz, - context->bw_results.required_sclk, - context->bw_results.required_sclk_deep_sleep, - context->bw_results.required_yclk, - context->bw_results.blackout_recovery_time_us); + context->bw.dce.cpuc_state_change_enable, + context->bw.dce.cpup_state_change_enable, + context->bw.dce.nbp_state_change_enable, + context->bw.dce.all_displays_in_sync, + context->bw.dce.dispclk_khz, + context->bw.dce.sclk_khz, + context->bw.dce.sclk_deep_sleep_khz, + context->bw.dce.yclk_khz, + context->bw.dce.blackout_recovery_time_us); dm_logger_close(&log_entry); } return result; diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 18c1b89a52be..0ed2616dd5cd 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -845,17 +845,16 @@ bool dce112_validate_bandwidth( &dc->bw_vbios, context->res_ctx.pipe_ctx, dc->res_pool->pipe_count, - &context->bw_results)) + &context->bw.dce)) result = true; - context->dispclk_khz = context->bw_results.dispclk_khz; if (!result) dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_VALIDATION, "%s: Bandwidth validation failed!", __func__); - if (memcmp(&dc->current_context->bw_results, - &context->bw_results, sizeof(context->bw_results))) { + if (memcmp(&dc->current_context->bw.dce, + &context->bw.dce, sizeof(context->bw.dce))) { struct log_entry log_entry; dm_logger_open( dc->ctx->logger, @@ -865,43 +864,43 @@ bool dce112_validate_bandwidth( "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n" "stutMark_b: %d stutMark_a: %d\n", __func__, - context->bw_results.nbp_state_change_wm_ns[0].b_mark, - context->bw_results.nbp_state_change_wm_ns[0].a_mark, - context->bw_results.urgent_wm_ns[0].b_mark, - context->bw_results.urgent_wm_ns[0].a_mark, - context->bw_results.stutter_exit_wm_ns[0].b_mark, - context->bw_results.stutter_exit_wm_ns[0].a_mark); + context->bw.dce.nbp_state_change_wm_ns[0].b_mark, + context->bw.dce.nbp_state_change_wm_ns[0].a_mark, + context->bw.dce.urgent_wm_ns[0].b_mark, + context->bw.dce.urgent_wm_ns[0].a_mark, + context->bw.dce.stutter_exit_wm_ns[0].b_mark, + context->bw.dce.stutter_exit_wm_ns[0].a_mark); dm_logger_append(&log_entry, "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n" "stutMark_b: %d stutMark_a: %d\n", - context->bw_results.nbp_state_change_wm_ns[1].b_mark, - context->bw_results.nbp_state_change_wm_ns[1].a_mark, - context->bw_results.urgent_wm_ns[1].b_mark, - context->bw_results.urgent_wm_ns[1].a_mark, - context->bw_results.stutter_exit_wm_ns[1].b_mark, - context->bw_results.stutter_exit_wm_ns[1].a_mark); + context->bw.dce.nbp_state_change_wm_ns[1].b_mark, + context->bw.dce.nbp_state_change_wm_ns[1].a_mark, + context->bw.dce.urgent_wm_ns[1].b_mark, + context->bw.dce.urgent_wm_ns[1].a_mark, + context->bw.dce.stutter_exit_wm_ns[1].b_mark, + context->bw.dce.stutter_exit_wm_ns[1].a_mark); dm_logger_append(&log_entry, "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n" "stutMark_b: %d stutMark_a: %d stutter_mode_enable: %d\n", - context->bw_results.nbp_state_change_wm_ns[2].b_mark, - context->bw_results.nbp_state_change_wm_ns[2].a_mark, - context->bw_results.urgent_wm_ns[2].b_mark, - context->bw_results.urgent_wm_ns[2].a_mark, - context->bw_results.stutter_exit_wm_ns[2].b_mark, - context->bw_results.stutter_exit_wm_ns[2].a_mark, - context->bw_results.stutter_mode_enable); + context->bw.dce.nbp_state_change_wm_ns[2].b_mark, + context->bw.dce.nbp_state_change_wm_ns[2].a_mark, + context->bw.dce.urgent_wm_ns[2].b_mark, + context->bw.dce.urgent_wm_ns[2].a_mark, + context->bw.dce.stutter_exit_wm_ns[2].b_mark, + context->bw.dce.stutter_exit_wm_ns[2].a_mark, + context->bw.dce.stutter_mode_enable); dm_logger_append(&log_entry, "cstate: %d pstate: %d nbpstate: %d sync: %d dispclk: %d\n" "sclk: %d sclk_sleep: %d yclk: %d blackout_recovery_time_us: %d\n", - context->bw_results.cpuc_state_change_enable, - context->bw_results.cpup_state_change_enable, - context->bw_results.nbp_state_change_enable, - context->bw_results.all_displays_in_sync, - context->bw_results.dispclk_khz, - context->bw_results.required_sclk, - context->bw_results.required_sclk_deep_sleep, - context->bw_results.required_yclk, - context->bw_results.blackout_recovery_time_us); + context->bw.dce.cpuc_state_change_enable, + context->bw.dce.cpup_state_change_enable, + context->bw.dce.nbp_state_change_enable, + context->bw.dce.all_displays_in_sync, + context->bw.dce.dispclk_khz, + context->bw.dce.sclk_khz, + context->bw.dce.sclk_deep_sleep_khz, + context->bw.dce.yclk_khz, + context->bw.dce.blackout_recovery_time_us); dm_logger_close(&log_entry); } return result; diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 0aa128e5ed84..5735914a8737 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -781,8 +781,8 @@ bool dce80_validate_bandwidth( struct validate_context *context) { /* TODO implement when needed but for now hardcode max value*/ - context->dispclk_khz = 681000; - context->bw_results.required_yclk = 250000 * MEMORY_TYPE_MULTIPLIER; + context->bw.dce.dispclk_khz = 681000; + context->bw.dce.yclk_khz = 250000 * MEMORY_TYPE_MULTIPLIER; return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 41a6fa507982..a62c4e72f21a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1428,7 +1428,7 @@ static void dcn10_power_on_fe( enable_dcfclk(dc->ctx, pipe_ctx->pipe_idx, pipe_ctx->pix_clk_params.requested_pix_clk, - context->dppclk_div); + context->bw.dcn.calc_clk.dppclk_div); if (dc_surface) { dm_logger_write(dc->ctx->logger, LOG_DC, @@ -1530,7 +1530,7 @@ static void update_dchubp_dpp( dc->ctx, pipe_ctx->pipe_idx, pipe_ctx->pix_clk_params.requested_pix_clk, - context->dppclk_div); + context->bw.dcn.calc_clk.dppclk_div); select_vtg(dc->ctx, pipe_ctx->pipe_idx, pipe_ctx->tg->inst); @@ -1649,7 +1649,7 @@ static void program_all_pipe_in_tree( if (pipe_ctx->top_pipe == NULL) { /* watermark is for all pipes */ pipe_ctx->mi->funcs->program_watermarks( - pipe_ctx->mi, &context->watermarks, ref_clk_mhz); + pipe_ctx->mi, &context->bw.dcn.watermarks, ref_clk_mhz); lock_otg_master_update(dc->ctx, pipe_ctx->tg->inst); } @@ -1679,16 +1679,16 @@ static void dcn10_pplib_apply_display_requirements( pp_display_cfg->all_displays_in_sync = false;/*todo*/ pp_display_cfg->nb_pstate_switch_disable = false; - pp_display_cfg->min_engine_clock_khz = context->dcfclk_khz; - pp_display_cfg->min_memory_clock_khz = context->fclk_khz; - pp_display_cfg->min_engine_clock_deep_sleep_khz = context->dcfclk_deep_sleep_khz; - pp_display_cfg->min_dcfc_deep_sleep_clock_khz = context->dcfclk_deep_sleep_khz; + pp_display_cfg->min_engine_clock_khz = context->bw.dcn.calc_clk.dcfclk_khz; + pp_display_cfg->min_memory_clock_khz = context->bw.dcn.calc_clk.fclk_khz; + pp_display_cfg->min_engine_clock_deep_sleep_khz = context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz; + pp_display_cfg->min_dcfc_deep_sleep_clock_khz = context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz; pp_display_cfg->avail_mclk_switch_time_us = - context->dram_ccm_us > 0 ? context->dram_ccm_us : 0; + context->bw.dcn.calc_clk.dram_ccm_us > 0 ? context->bw.dcn.calc_clk.dram_ccm_us : 0; pp_display_cfg->avail_mclk_switch_time_in_disp_active_us = - context->min_active_dram_ccm_us > 0 ? context->min_active_dram_ccm_us : 0; - pp_display_cfg->min_dcfclock_khz = context->dcfclk_khz; - pp_display_cfg->disp_clk_khz = context->dispclk_khz; + context->bw.dcn.calc_clk.min_active_dram_ccm_us > 0 ? context->bw.dcn.calc_clk.min_active_dram_ccm_us : 0; + pp_display_cfg->min_dcfclock_khz = context->bw.dcn.calc_clk.dcfclk_khz; + pp_display_cfg->disp_clk_khz = context->bw.dcn.calc_clk.dispclk_khz; dce110_fill_display_configs(context, pp_display_cfg); if (memcmp(&dc->prev_display_config, pp_display_cfg, sizeof( @@ -1755,22 +1755,22 @@ static void dcn10_set_bandwidth( if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) return; - if (decrease_allowed || context->dispclk_khz > dc->current_context->dispclk_khz) { + if (decrease_allowed || context->bw.dcn.calc_clk.dispclk_khz > dc->current_context->bw.dcn.calc_clk.dispclk_khz) { dc->res_pool->display_clock->funcs->set_clock( dc->res_pool->display_clock, - context->dispclk_khz); - dc->current_context->dispclk_khz = context->dispclk_khz; + context->bw.dcn.calc_clk.dispclk_khz); + dc->current_context->bw.dcn.calc_clk.dispclk_khz = context->bw.dcn.calc_clk.dispclk_khz; } - if (decrease_allowed || context->dcfclk_khz > dc->current_context->dcfclk_khz) { + if (decrease_allowed || context->bw.dcn.calc_clk.dcfclk_khz > dc->current_context->bw.dcn.calc_clk.dcfclk_khz) { clock.clk_type = DM_PP_CLOCK_TYPE_DCFCLK; - clock.clocks_in_khz = context->dcfclk_khz; + clock.clocks_in_khz = context->bw.dcn.calc_clk.dcfclk_khz; dm_pp_apply_clock_for_voltage_request(dc->ctx, &clock); } - if (decrease_allowed || context->fclk_khz > dc->current_context->fclk_khz) { + if (decrease_allowed || context->bw.dcn.calc_clk.fclk_khz > dc->current_context->bw.dcn.calc_clk.fclk_khz) { clock.clk_type = DM_PP_CLOCK_TYPE_FCLK; - clock.clocks_in_khz = context->fclk_khz; + clock.clocks_in_khz = context->bw.dcn.calc_clk.fclk_khz; dm_pp_apply_clock_for_voltage_request(dc->ctx, &clock); - dc->current_context->fclk_khz = clock.clocks_in_khz ; + dc->current_context->bw.dcn.calc_clk.fclk_khz = clock.clocks_in_khz; } dcn10_pplib_apply_display_requirements(dc, context); } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index bf89608b30e4..50b24456d495 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -820,9 +820,9 @@ static void program_watermarks( static void mem_input_program_display_marks( struct mem_input *mem_input, - struct bw_watermarks nbp, - struct bw_watermarks stutter, - struct bw_watermarks urgent, + struct dce_watermarks nbp, + struct dce_watermarks stutter, + struct dce_watermarks urgent, uint32_t total_dest_line_time_ns) { /* only for dce diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 919c6632ee3e..46bd0318e6be 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -31,8 +31,8 @@ #include "dcn_calcs.h" #include "ddc_service_types.h" #include "dc_bios_types.h" -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) #include "mem_input.h" +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) #include "mpc.h" #endif @@ -312,7 +312,48 @@ struct resource_context { bool is_audio_acquired[MAX_PIPES]; uint8_t clock_source_ref_count[MAX_CLOCK_SOURCES]; uint8_t dp_clock_source_ref_count; - }; +}; + +struct dce_bw_output { + bool cpuc_state_change_enable; + bool cpup_state_change_enable; + bool stutter_mode_enable; + bool nbp_state_change_enable; + bool all_displays_in_sync; + struct dce_watermarks urgent_wm_ns[MAX_PIPES]; + struct dce_watermarks stutter_exit_wm_ns[MAX_PIPES]; + struct dce_watermarks nbp_state_change_wm_ns[MAX_PIPES]; + int sclk_khz; + int sclk_deep_sleep_khz; + int yclk_khz; + int dispclk_khz; + int blackout_recovery_time_us; +}; + +#ifdef CONFIG_DRM_AMD_DC_DCN1_0 +struct dcn_bw_clocks { + int dispclk_khz; + bool dppclk_div; + int dcfclk_khz; + int dcfclk_deep_sleep_khz; + int fclk_khz; + int dram_ccm_us; + int min_active_dram_ccm_us; +}; + +struct dcn_bw_output { + struct dcn_bw_clocks cur_clk; + struct dcn_bw_clocks calc_clk; + struct dcn_watermark_set watermarks; +}; +#endif + +union bw_context { +#ifdef CONFIG_DRM_AMD_DC_DCN1_0 + struct dcn_bw_output dcn; +#endif + struct dce_bw_output dce; +}; struct validate_context { struct core_stream *streams[MAX_PIPES]; @@ -322,20 +363,11 @@ struct validate_context { struct resource_context res_ctx; /* The output from BW and WM calculations. */ - struct bw_calcs_output bw_results; + union bw_context bw; + /* Note: these are big structures, do *not* put on stack! */ struct dm_pp_display_configuration pp_display_cfg; - int dispclk_khz; #ifdef CONFIG_DRM_AMD_DC_DCN1_0 - int dppclk_khz; - bool dppclk_div; - int dcfclk_khz; - int dcfclk_deep_sleep_khz; - int socclk_khz; - int fclk_khz; - int dram_ccm_us; - int min_active_dram_ccm_us; - struct dcn_watermark_set watermarks; struct dcn_bw_internal_vars dcn_bw_vars; #endif }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/dce_calcs.h b/drivers/gpu/drm/amd/display/dc/inc/dce_calcs.h index 580dee95e57a..36c48f7d3f56 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dce_calcs.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dce_calcs.h @@ -35,6 +35,7 @@ struct pipe_ctx; struct core_dc; struct validate_context; +struct dce_bw_output; enum bw_calcs_version { BW_CALCS_VERSION_INVALID, @@ -454,32 +455,6 @@ struct bw_calcs_data { struct bw_fixed dmif_required_sclk_for_urgent_latency[6]; }; -/******************************************************************************* - * Output data structures. - ******************************************************************************/ -struct bw_watermarks { - uint32_t a_mark; - uint32_t b_mark; - uint32_t c_mark; - uint32_t d_mark; -}; - -struct bw_calcs_output { - bool cpuc_state_change_enable; - bool cpup_state_change_enable; - bool stutter_mode_enable; - bool nbp_state_change_enable; - bool all_displays_in_sync; - struct bw_watermarks urgent_wm_ns[6]; - struct bw_watermarks stutter_exit_wm_ns[6]; - struct bw_watermarks nbp_state_change_wm_ns[6]; - uint32_t required_sclk; - uint32_t required_sclk_deep_sleep; - uint32_t required_yclk; - uint32_t dispclk_khz; - int blackout_recovery_time_us; -}; - /** * Initialize structures with data which will NOT change at runtime. */ @@ -500,7 +475,7 @@ bool bw_calcs( const struct bw_calcs_vbios *vbios, const struct pipe_ctx *pipe, int pipe_count, - struct bw_calcs_output *calcs_output); + struct dce_bw_output *calcs_output); #endif /* __BANDWIDTH_CALCS_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h index 0880ce98c90c..c4aea24d4574 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h @@ -27,7 +27,6 @@ #include "dc.h" #include "include/grph_object_id.h" -#include "inc/dce_calcs.h" #include "dce/dce_mem_input.h" /* temporary */ @@ -55,6 +54,13 @@ struct dcn_watermark_set { #endif +struct dce_watermarks { + int a_mark; + int b_mark; + int c_mark; + int d_mark; +}; + struct stutter_modes { bool enhanced; bool quad_dmif_buffer; @@ -95,16 +101,16 @@ struct mem_input_funcs { void (*mem_input_program_display_marks)( struct mem_input *mem_input, - struct bw_watermarks nbp, - struct bw_watermarks stutter, - struct bw_watermarks urgent, + struct dce_watermarks nbp, + struct dce_watermarks stutter, + struct dce_watermarks urgent, uint32_t total_dest_line_time_ns); void (*mem_input_program_chroma_display_marks)( struct mem_input *mem_input, - struct bw_watermarks nbp, - struct bw_watermarks stutter, - struct bw_watermarks urgent, + struct dce_watermarks nbp, + struct dce_watermarks stutter, + struct dce_watermarks urgent, uint32_t total_dest_line_time_ns); void (*allocate_mem_input)( -- cgit From c66a54dc4a8403ab269568b3f964b0efd4052932 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 3 May 2017 11:40:40 -0400 Subject: drm/amd/display: switch to using calc_clk and cur_clk for dcn bw setting Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 50 +++++++++++------- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 59 +++++++++++++++++----- 2 files changed, 79 insertions(+), 30 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 41aeceba5ae5..150c8a4e7b61 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1647,24 +1647,38 @@ enum dc_status dce110_apply_ctx_to_hw( apply_min_clocks(dc, context, &clocks_state, true); #if defined(CONFIG_DRM_AMD_DC_DCN1_0) - if (context->bw.dcn.calc_clk.fclk_khz - > dc->current_context->bw.dcn.calc_clk.fclk_khz) { - struct dm_pp_clock_for_voltage_req clock; - - clock.clk_type = DM_PP_CLOCK_TYPE_FCLK; - clock.clocks_in_khz = context->bw.dcn.calc_clk.fclk_khz; - dm_pp_apply_clock_for_voltage_request(dc->ctx, &clock); - dc->current_context->bw.dcn.calc_clk.fclk_khz = clock.clocks_in_khz; - } - if (context->bw.dcn.calc_clk.dcfclk_khz - > dc->current_context->bw.dcn.calc_clk.dcfclk_khz) { - struct dm_pp_clock_for_voltage_req clock; - - clock.clk_type = DM_PP_CLOCK_TYPE_DCFCLK; - clock.clocks_in_khz = context->bw.dcn.calc_clk.dcfclk_khz; - dm_pp_apply_clock_for_voltage_request(dc->ctx, &clock); - dc->current_context->bw.dcn.calc_clk.dcfclk_khz = clock.clocks_in_khz; - } + if (resource_parse_asic_id(dc->ctx->asic_id) == DCN_VERSION_1_0) { + if (context->bw.dcn.calc_clk.fclk_khz + > dc->current_context->bw.dcn.cur_clk.fclk_khz) { + struct dm_pp_clock_for_voltage_req clock; + + clock.clk_type = DM_PP_CLOCK_TYPE_FCLK; + clock.clocks_in_khz = context->bw.dcn.calc_clk.fclk_khz; + dm_pp_apply_clock_for_voltage_request(dc->ctx, &clock); + dc->current_context->bw.dcn.cur_clk.fclk_khz = clock.clocks_in_khz; + context->bw.dcn.cur_clk.fclk_khz = clock.clocks_in_khz; + } + if (context->bw.dcn.calc_clk.dcfclk_khz + > dc->current_context->bw.dcn.cur_clk.dcfclk_khz) { + struct dm_pp_clock_for_voltage_req clock; + + clock.clk_type = DM_PP_CLOCK_TYPE_DCFCLK; + clock.clocks_in_khz = context->bw.dcn.calc_clk.dcfclk_khz; + dm_pp_apply_clock_for_voltage_request(dc->ctx, &clock); + dc->current_context->bw.dcn.cur_clk.dcfclk_khz = clock.clocks_in_khz; + context->bw.dcn.cur_clk.dcfclk_khz = clock.clocks_in_khz; + } + if (context->bw.dcn.calc_clk.dispclk_khz + > dc->current_context->bw.dcn.cur_clk.dispclk_khz) { + dc->res_pool->display_clock->funcs->set_clock( + dc->res_pool->display_clock, + context->bw.dcn.calc_clk.dispclk_khz); + dc->current_context->bw.dcn.cur_clk.dispclk_khz = + context->bw.dcn.calc_clk.dispclk_khz; + context->bw.dcn.cur_clk.dispclk_khz = + context->bw.dcn.calc_clk.dispclk_khz; + } + } else #endif if (context->bw.dce.dispclk_khz > dc->current_context->bw.dce.dispclk_khz) { diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index a62c4e72f21a..f5638ad6e9fc 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1429,6 +1429,9 @@ static void dcn10_power_on_fe( pipe_ctx->pipe_idx, pipe_ctx->pix_clk_params.requested_pix_clk, context->bw.dcn.calc_clk.dppclk_div); + dc->current_context->bw.dcn.cur_clk.dppclk_div = + context->bw.dcn.calc_clk.dppclk_div; + context->bw.dcn.cur_clk.dppclk_div = context->bw.dcn.calc_clk.dppclk_div; if (dc_surface) { dm_logger_write(dc->ctx->logger, LOG_DC, @@ -1531,6 +1534,9 @@ static void update_dchubp_dpp( pipe_ctx->pipe_idx, pipe_ctx->pix_clk_params.requested_pix_clk, context->bw.dcn.calc_clk.dppclk_div); + dc->current_context->bw.dcn.cur_clk.dppclk_div = + context->bw.dcn.calc_clk.dppclk_div; + context->bw.dcn.cur_clk.dppclk_div = context->bw.dcn.calc_clk.dppclk_div; select_vtg(dc->ctx, pipe_ctx->pipe_idx, pipe_ctx->tg->inst); @@ -1679,16 +1685,16 @@ static void dcn10_pplib_apply_display_requirements( pp_display_cfg->all_displays_in_sync = false;/*todo*/ pp_display_cfg->nb_pstate_switch_disable = false; - pp_display_cfg->min_engine_clock_khz = context->bw.dcn.calc_clk.dcfclk_khz; - pp_display_cfg->min_memory_clock_khz = context->bw.dcn.calc_clk.fclk_khz; - pp_display_cfg->min_engine_clock_deep_sleep_khz = context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz; - pp_display_cfg->min_dcfc_deep_sleep_clock_khz = context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz; + pp_display_cfg->min_engine_clock_khz = context->bw.dcn.cur_clk.dcfclk_khz; + pp_display_cfg->min_memory_clock_khz = context->bw.dcn.cur_clk.fclk_khz; + pp_display_cfg->min_engine_clock_deep_sleep_khz = context->bw.dcn.cur_clk.dcfclk_deep_sleep_khz; + pp_display_cfg->min_dcfc_deep_sleep_clock_khz = context->bw.dcn.cur_clk.dcfclk_deep_sleep_khz; pp_display_cfg->avail_mclk_switch_time_us = - context->bw.dcn.calc_clk.dram_ccm_us > 0 ? context->bw.dcn.calc_clk.dram_ccm_us : 0; + context->bw.dcn.cur_clk.dram_ccm_us > 0 ? context->bw.dcn.cur_clk.dram_ccm_us : 0; pp_display_cfg->avail_mclk_switch_time_in_disp_active_us = - context->bw.dcn.calc_clk.min_active_dram_ccm_us > 0 ? context->bw.dcn.calc_clk.min_active_dram_ccm_us : 0; - pp_display_cfg->min_dcfclock_khz = context->bw.dcn.calc_clk.dcfclk_khz; - pp_display_cfg->disp_clk_khz = context->bw.dcn.calc_clk.dispclk_khz; + context->bw.dcn.cur_clk.min_active_dram_ccm_us > 0 ? context->bw.dcn.cur_clk.min_active_dram_ccm_us : 0; + pp_display_cfg->min_dcfclock_khz = context->bw.dcn.cur_clk.dcfclk_khz; + pp_display_cfg->disp_clk_khz = context->bw.dcn.cur_clk.dispclk_khz; dce110_fill_display_configs(context, pp_display_cfg); if (memcmp(&dc->prev_display_config, pp_display_cfg, sizeof( @@ -1755,22 +1761,51 @@ static void dcn10_set_bandwidth( if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) return; - if (decrease_allowed || context->bw.dcn.calc_clk.dispclk_khz > dc->current_context->bw.dcn.calc_clk.dispclk_khz) { + if (decrease_allowed || context->bw.dcn.calc_clk.dispclk_khz + > dc->current_context->bw.dcn.cur_clk.dispclk_khz) { dc->res_pool->display_clock->funcs->set_clock( dc->res_pool->display_clock, context->bw.dcn.calc_clk.dispclk_khz); - dc->current_context->bw.dcn.calc_clk.dispclk_khz = context->bw.dcn.calc_clk.dispclk_khz; + dc->current_context->bw.dcn.cur_clk.dispclk_khz = + context->bw.dcn.calc_clk.dispclk_khz; } - if (decrease_allowed || context->bw.dcn.calc_clk.dcfclk_khz > dc->current_context->bw.dcn.calc_clk.dcfclk_khz) { + if (decrease_allowed || context->bw.dcn.calc_clk.dcfclk_khz + > dc->current_context->bw.dcn.cur_clk.dcfclk_khz) { clock.clk_type = DM_PP_CLOCK_TYPE_DCFCLK; clock.clocks_in_khz = context->bw.dcn.calc_clk.dcfclk_khz; dm_pp_apply_clock_for_voltage_request(dc->ctx, &clock); + dc->current_context->bw.dcn.cur_clk.dcfclk_khz = clock.clocks_in_khz; + context->bw.dcn.cur_clk.dcfclk_khz = clock.clocks_in_khz; } - if (decrease_allowed || context->bw.dcn.calc_clk.fclk_khz > dc->current_context->bw.dcn.calc_clk.fclk_khz) { + if (decrease_allowed || context->bw.dcn.calc_clk.fclk_khz + > dc->current_context->bw.dcn.cur_clk.fclk_khz) { clock.clk_type = DM_PP_CLOCK_TYPE_FCLK; clock.clocks_in_khz = context->bw.dcn.calc_clk.fclk_khz; dm_pp_apply_clock_for_voltage_request(dc->ctx, &clock); dc->current_context->bw.dcn.calc_clk.fclk_khz = clock.clocks_in_khz; + context->bw.dcn.cur_clk.fclk_khz = clock.clocks_in_khz; + } + if (decrease_allowed || context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz + > dc->current_context->bw.dcn.cur_clk.dcfclk_deep_sleep_khz) { + dc->current_context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz = + context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz; + context->bw.dcn.cur_clk.dcfclk_deep_sleep_khz = + context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz; + } + /* Decrease in freq is increase in period so opposite comparison for dram_ccm */ + if (decrease_allowed || context->bw.dcn.calc_clk.dram_ccm_us + < dc->current_context->bw.dcn.cur_clk.dram_ccm_us) { + dc->current_context->bw.dcn.calc_clk.dram_ccm_us = + context->bw.dcn.calc_clk.dram_ccm_us; + context->bw.dcn.cur_clk.dram_ccm_us = + context->bw.dcn.calc_clk.dram_ccm_us; + } + if (decrease_allowed || context->bw.dcn.calc_clk.min_active_dram_ccm_us + < dc->current_context->bw.dcn.cur_clk.min_active_dram_ccm_us) { + dc->current_context->bw.dcn.calc_clk.min_active_dram_ccm_us = + context->bw.dcn.calc_clk.min_active_dram_ccm_us; + context->bw.dcn.cur_clk.min_active_dram_ccm_us = + context->bw.dcn.calc_clk.min_active_dram_ccm_us; } dcn10_pplib_apply_display_requirements(dc, context); } -- cgit From d4b4597384eac0e2d293912cf4cebded27246301 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Fri, 5 May 2017 16:33:11 -0400 Subject: drm/amd/display: Add 64KB_S_T and 64KB_D_T swizzle mode. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 1b9edfda2b98..26587bcdba96 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -236,6 +236,7 @@ static void pipe_ctx_to_e2e_pipe_params ( break; case DC_SW_64KB_S: case DC_SW_64KB_S_X: + case DC_SW_64KB_S_T: input->src.is_display_sw = 0; input->src.macro_tile_size = dm_64k_tile; break; @@ -253,6 +254,7 @@ static void pipe_ctx_to_e2e_pipe_params ( break; case DC_SW_64KB_D: case DC_SW_64KB_D_X: + case DC_SW_64KB_D_T: input->src.is_display_sw = 1; input->src.macro_tile_size = dm_64k_tile; break; -- cgit From e61a04f1af6187caebcad69ff72b571179b3dde9 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 27 Apr 2017 17:13:34 -0400 Subject: drm/amd/display: Use MED update type if clip position changes Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index b30d4bc7b040..3c2554381a25 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1143,7 +1143,7 @@ static enum surface_update_type get_scaling_info_update_type( return UPDATE_TYPE_FULL; /* Check Clip rectangles if not equal - * difference is in offsets == > UPDATE_TYPE_FAST + * difference is in offsets == > UPDATE_TYPE_MED * difference is in dimensions == > UPDATE_TYPE_FULL */ if (memcmp(&u->scaling_info->clip_rect, @@ -1152,7 +1152,7 @@ static enum surface_update_type get_scaling_info_update_type( u->surface->clip_rect.height) && (u->scaling_info->clip_rect.width == u->surface->clip_rect.width)) { - return UPDATE_TYPE_FAST; + return UPDATE_TYPE_MED; } else { return UPDATE_TYPE_FULL; } @@ -1326,8 +1326,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, srf_updates[i].plane_info->dcc; } - /* not sure if we still need this */ - if (update_type == UPDATE_TYPE_FULL) { + if (update_type >= UPDATE_TYPE_MED) { for (j = 0; j < core_dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; -- cgit From ca3cba9c605348988223f69a83d1c1e7dde7583a Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Mon, 8 May 2017 17:46:57 -0400 Subject: drm/amd/display: single channel bandwidth verses dual channel bandwidth DPM0, FCLK=MCLK, single channel bandwidth = dual channel bandwidth for the rest of the DPM levels, single channel bandwidth = 1/2 dual channel bandwidth Signed-off-by: Charlene Liu Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 26587bcdba96..6d8bc6c74a73 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -920,6 +920,10 @@ bool dcn_validate_bandwidth( calc_wm_sets_and_perf_params(context, v); context->bw.dcn.calc_clk.fclk_khz = (int)(bw_consumed * 1000000 / (ddr4_dram_factor_single_Channel * v->number_of_channels)); + if (bw_consumed == v->fabric_and_dram_bandwidth_vmin0p65) { + context->bw.dcn.calc_clk.fclk_khz = (int)(bw_consumed * 1000000 / 32); + } + context->bw.dcn.calc_clk.dram_ccm_us = (int)(v->dram_clock_change_margin); context->bw.dcn.calc_clk.min_active_dram_ccm_us = (int)(v->min_active_dram_clock_change_margin); context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz = (int)(v->dcf_clk_deep_sleep * 1000); @@ -1178,8 +1182,7 @@ void dcn_bw_update_from_pplib(struct core_dc *dc) ctx, DM_PP_CLOCK_TYPE_FCLK, &clks) && clks.num_levels != 0) { ASSERT(clks.num_levels >= 3); - dc->dcn_soc.fabric_and_dram_bandwidth_vmin0p65 = dc->dcn_soc.number_of_channels * - (clks.data[0].clocks_in_khz / 1000.0) * ddr4_dram_factor_single_Channel / 1000.0; + dc->dcn_soc.fabric_and_dram_bandwidth_vmin0p65 = 32 * (clks.data[0].clocks_in_khz / 1000.0) / 1000.0; if (clks.num_levels > 2) { dc->dcn_soc.fabric_and_dram_bandwidth_vmid0p72 = dc->dcn_soc.number_of_channels * (clks.data[clks.num_levels - 3].clocks_in_khz / 1000.0) * ddr4_dram_factor_single_Channel / 1000.0; @@ -1240,7 +1243,7 @@ void dcn_bw_notify_pplib_of_wm_ranges(struct core_dc *dc) kernel_fpu_begin(); max_fclk_khz = dc->dcn_soc.fabric_and_dram_bandwidth_vmax0p9 * 1000000 / factor; nom_fclk_khz = dc->dcn_soc.fabric_and_dram_bandwidth_vnom0p8 * 1000000 / factor; - min_fclk_khz = dc->dcn_soc.fabric_and_dram_bandwidth_vmin0p65 * 1000000 / factor; + min_fclk_khz = dc->dcn_soc.fabric_and_dram_bandwidth_vmin0p65 * 1000000 / 32; max_dcfclk_khz = dc->dcn_soc.dcfclkv_max0p9 * 1000; nom_dcfclk_khz = dc->dcn_soc.dcfclkv_nom0p8 * 1000; min_dcfclk_khz = dc->dcn_soc.dcfclkv_min0p65 * 1000; -- cgit From d5c40d5368876d701811faa65c341198cb958cb0 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Mon, 8 May 2017 11:26:43 -0400 Subject: drm/amd/display: enable watermark range reporting to pplib Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 41613ab5ca69..4e5b225a2a08 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -432,7 +432,7 @@ static const struct dc_debug debug_defaults_drv = { .force_abm_enable = false, .timing_trace = false, .disable_pplib_clock_request = true, - .disable_pplib_wm_range = true, + .disable_pplib_wm_range = false, #if defined(CONFIG_DRM_AMD_DC_DCN1_0) .use_dml_wm = false, .use_max_voltage = true -- cgit From 6838161c723d061c85e20057dbf0a2a9378c4e59 Mon Sep 17 00:00:00 2001 From: Corbin McElhanney Date: Tue, 9 May 2017 12:00:24 -0400 Subject: drm/amd/display: fix freesync not working on raven Signed-off-by: Corbin McElhanney Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/modules/freesync/freesync.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index 05a086c7b31a..9a073bc55144 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -1130,6 +1130,7 @@ void mod_freesync_notify_mode_change(struct mod_freesync *mod_freesync, unsigned int stream_index, map_index; struct freesync_state *state; struct core_freesync *core_freesync = NULL; + struct dc_static_screen_events triggers = {0}; if (mod_freesync == NULL) return; @@ -1157,6 +1158,7 @@ void mod_freesync_notify_mode_change(struct mod_freesync *mod_freesync, /* Update the stream */ update_stream(core_freesync, streams[stream_index]); + /* Calculate vmin/vmax and refresh rate for * current mode */ @@ -1164,6 +1166,14 @@ void mod_freesync_notify_mode_change(struct mod_freesync *mod_freesync, core_freesync->map[map_index].caps-> min_refresh_in_micro_hz, state->nominal_refresh_rate_in_micro_hz); + + /* Update mask */ + triggers.overlay_update = true; + triggers.surface_update = true; + + core_freesync->dc->stream_funcs.set_static_screen_events( + core_freesync->dc, streams, num_streams, + &triggers); } } -- cgit From f46661dd42f3648b92eca73ba2c48f5d9a418b1b Mon Sep 17 00:00:00 2001 From: Amy Zhang Date: Tue, 9 May 2017 14:45:54 -0400 Subject: drm/amd/display: Move output transfer function to stream updates Signed-off-by: Amy Zhang Reviewed-by: Anthony Koo Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 46 ++++++++++++++-------- drivers/gpu/drm/amd/display/dc/dc.h | 14 +++---- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 1 - .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 4 +- drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 1 - 5 files changed, 37 insertions(+), 29 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 3c2554381a25..1e6952bde25b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -201,11 +201,10 @@ static bool stream_get_crtc_position(struct dc *dc, return ret; } -static bool set_gamut_remap(struct dc *dc, - const struct dc_stream **stream, int num_streams) +static bool set_gamut_remap(struct dc *dc, const struct dc_stream *stream) { struct core_dc *core_dc = DC_TO_CORE(dc); - struct core_stream *core_stream = DC_STREAM_TO_CORE(stream[0]); + struct core_stream *core_stream = DC_STREAM_TO_CORE(stream); int i = 0; bool ret = false; struct pipe_ctx *pipes; @@ -1182,7 +1181,6 @@ static enum surface_update_type det_surface_update( overall_type = type; if (u->in_transfer_func || - u->out_transfer_func || u->hdr_static_metadata) { if (overall_type < UPDATE_TYPE_MED) overall_type = UPDATE_TYPE_MED; @@ -1279,8 +1277,28 @@ void dc_update_surfaces_and_stream(struct dc *dc, /* update current stream with the new updates */ if (stream_update) { - stream->public.src = stream_update->src; - stream->public.dst = stream_update->dst; + if ((stream_update->src.height != 0) && + (stream_update->src.width != 0)) + stream->public.src = stream_update->src; + + if ((stream_update->dst.height != 0) && + (stream_update->dst.width != 0)) + stream->public.dst = stream_update->dst; + + if (stream_update->out_transfer_func && + stream_update->out_transfer_func != + dc_stream->out_transfer_func) { + if (stream_update->out_transfer_func->type != + TF_TYPE_UNKNOWN) { + if (dc_stream->out_transfer_func != NULL) + dc_transfer_func_release + (dc_stream->out_transfer_func); + dc_transfer_func_retain(stream_update-> + out_transfer_func); + stream->public.out_transfer_func = + stream_update->out_transfer_func; + } + } } /* save update parameters into surface */ @@ -1361,13 +1379,6 @@ void dc_update_surfaces_and_stream(struct dc *dc, srf_updates[i].in_transfer_func; } - if (srf_updates[i].out_transfer_func && - srf_updates[i].out_transfer_func != dc_stream->out_transfer_func) { - if (dc_stream->out_transfer_func != NULL) - dc_transfer_func_release(dc_stream->out_transfer_func); - dc_transfer_func_retain(srf_updates[i].out_transfer_func); - stream->public.out_transfer_func = srf_updates[i].out_transfer_func; - } if (srf_updates[i].hdr_static_metadata) surface->public.hdr_static_ctx = *(srf_updates[i].hdr_static_metadata); @@ -1436,11 +1447,12 @@ void dc_update_surfaces_and_stream(struct dc *dc, pipe_ctx, pipe_ctx->surface); if (is_new_pipe_surface || - srf_updates[i].out_transfer_func) + (stream_update != NULL && + stream_update->out_transfer_func != + NULL)) { core_dc->hwss.set_output_transfer_func( - pipe_ctx, - pipe_ctx->surface, - pipe_ctx->stream); + pipe_ctx, pipe_ctx->stream); + } if (srf_updates[i].hdr_static_metadata) { resource_build_info_frame(pipe_ctx); diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index c7e503a91f45..7dd145b6e927 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -122,7 +122,7 @@ struct dc_stream_funcs { const struct rect *dst); bool (*set_gamut_remap)(struct dc *dc, - const struct dc_stream **stream, int num_streams); + const struct dc_stream *stream); void (*set_static_screen_events)(struct dc *dc, const struct dc_stream **stream, @@ -265,7 +265,8 @@ struct dc_hdr_static_metadata { enum dc_transfer_func_type { TF_TYPE_PREDEFINED, TF_TYPE_DISTRIBUTED_POINTS, - TF_TYPE_BYPASS + TF_TYPE_BYPASS, + TF_TYPE_UNKNOWN }; struct dc_transfer_func_distributed_points { @@ -349,11 +350,8 @@ struct dc_surface_update { */ /* gamma TO BE REMOVED */ struct dc_gamma *gamma; - struct dc_hdr_static_metadata *hdr_static_metadata; struct dc_transfer_func *in_transfer_func; - struct dc_transfer_func *out_transfer_func; - - + struct dc_hdr_static_metadata *hdr_static_metadata; }; /* * This structure is filled in by dc_surface_get_status and contains @@ -473,11 +471,9 @@ struct dc_stream { }; struct dc_stream_update { - struct rect src; - struct rect dst; - + struct dc_transfer_func *out_transfer_func; }; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 150c8a4e7b61..8a663003017c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -631,7 +631,6 @@ static bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func static bool dce110_set_output_transfer_func( struct pipe_ctx *pipe_ctx, - const struct core_surface *surface, /* Surface - To be removed */ const struct core_stream *stream) { struct output_pixel_processor *opp = pipe_ctx->opp; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index f5638ad6e9fc..6cb3924225da 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1301,11 +1301,13 @@ static bool dcn10_translate_regamma_to_hw_format(const struct dc_transfer_func static bool dcn10_set_output_transfer_func( struct pipe_ctx *pipe_ctx, - const struct core_surface *surface, const struct core_stream *stream) { struct output_pixel_processor *opp = pipe_ctx->opp; + if (opp == NULL) + return false; + opp->regamma_params.hw_points_num = GAMMA_HW_POINTS_NUM; if (stream->public.out_transfer_func && diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index afdb8605a30f..b53e1206dfb3 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -80,7 +80,6 @@ struct hw_sequencer_funcs { bool (*set_output_transfer_func)( struct pipe_ctx *pipe_ctx, - const struct core_surface *surface, const struct core_stream *stream); void (*power_down)(struct core_dc *dc); -- cgit From 6a4c32dac559a90b83c5f268b02c1a94df411159 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Fri, 5 May 2017 14:57:12 -0400 Subject: drm/amd/display: DCE12 num_timing_generators should be 6 We should also use it to determine pipe count. Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index b6bdd1d52922..b13abb025e1b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -426,7 +426,7 @@ static const struct bios_registers bios_regs = { }; static const struct resource_caps res_cap = { - .num_timing_generator = 3, + .num_timing_generator = 6, .num_audio = 7, .num_stream_encoder = 6, .num_pll = 6, @@ -909,7 +909,7 @@ static bool construct( pool->base.funcs = &dce120_res_pool_funcs; /* TODO: Fill more data from GreenlandAsicCapability.cpp */ - pool->base.pipe_count = 6; + pool->base.pipe_count = res_cap.num_timing_generator; pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; dc->public.caps.max_downscale_ratio = 200; -- cgit From 86006a7f54c7fb59ccb3061d7a3dcd3c0443b4fe Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Tue, 9 May 2017 16:39:26 -0400 Subject: drm/amd/display: fix scaling calculation for proper surface input format Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 60 +++++++++++++++-------- drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 20 ++++---- 2 files changed, 49 insertions(+), 31 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 9588217e0220..7ca03d1ad163 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -431,6 +431,7 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) const struct dc_surface *surface = &pipe_ctx->surface->public; const struct dc_stream *stream = &pipe_ctx->stream->public; struct scaler_data *data = &pipe_ctx->scl_data; + struct rect surf_src = surface->src_rect; struct rect clip = { 0 }; int vpc_div = (data->format == PIXEL_FORMAT_420BPP12 || data->format == PIXEL_FORMAT_420BPP15) ? 2 : 1; @@ -444,6 +445,11 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) pri_split = false; sec_split = false; } + + if (pipe_ctx->surface->public.rotation == ROTATION_ANGLE_90 || + pipe_ctx->surface->public.rotation == ROTATION_ANGLE_270) + rect_swap_helper(&surf_src); + /* The actual clip is an intersection between stream * source and surface clip */ @@ -463,18 +469,18 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) stream->src.y + stream->src.height - clip.y : surface->clip_rect.y + surface->clip_rect.height - clip.y ; - /* offset = src.ofs + (clip.ofs - surface->dst_rect.ofs) * scl_ratio + /* offset = surf_src.ofs + (clip.ofs - surface->dst_rect.ofs) * scl_ratio * num_pixels = clip.num_pix * scl_ratio */ - data->viewport.x = surface->src_rect.x + (clip.x - surface->dst_rect.x) * - surface->src_rect.width / surface->dst_rect.width; + data->viewport.x = surf_src.x + (clip.x - surface->dst_rect.x) * + surf_src.width / surface->dst_rect.width; data->viewport.width = clip.width * - surface->src_rect.width / surface->dst_rect.width; + surf_src.width / surface->dst_rect.width; - data->viewport.y = surface->src_rect.y + (clip.y - surface->dst_rect.y) * - surface->src_rect.height / surface->dst_rect.height; + data->viewport.y = surf_src.y + (clip.y - surface->dst_rect.y) * + surf_src.height / surface->dst_rect.height; data->viewport.height = clip.height * - surface->src_rect.height / surface->dst_rect.height; + surf_src.height / surface->dst_rect.height; /* Round down, compensate in init */ data->viewport_c.x = data->viewport.x / vpc_div; @@ -523,16 +529,21 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip { const struct dc_surface *surface = &pipe_ctx->surface->public; struct core_stream *stream = pipe_ctx->stream; - struct rect clip = surface->clip_rect; + struct rect surf_src = surface->src_rect; + struct rect surf_clip = surface->clip_rect; int recout_full_x, recout_full_y; + if (pipe_ctx->surface->public.rotation == ROTATION_ANGLE_90 || + pipe_ctx->surface->public.rotation == ROTATION_ANGLE_270) + rect_swap_helper(&surf_src); + pipe_ctx->scl_data.recout.x = stream->public.dst.x; - if (stream->public.src.x < clip.x) - pipe_ctx->scl_data.recout.x += (clip.x + if (stream->public.src.x < surf_clip.x) + pipe_ctx->scl_data.recout.x += (surf_clip.x - stream->public.src.x) * stream->public.dst.width / stream->public.src.width; - pipe_ctx->scl_data.recout.width = clip.width * + pipe_ctx->scl_data.recout.width = surf_clip.width * stream->public.dst.width / stream->public.src.width; if (pipe_ctx->scl_data.recout.width + pipe_ctx->scl_data.recout.x > stream->public.dst.x + stream->public.dst.width) @@ -541,12 +552,12 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip - pipe_ctx->scl_data.recout.x; pipe_ctx->scl_data.recout.y = stream->public.dst.y; - if (stream->public.src.y < clip.y) - pipe_ctx->scl_data.recout.y += (clip.y + if (stream->public.src.y < surf_clip.y) + pipe_ctx->scl_data.recout.y += (surf_clip.y - stream->public.src.y) * stream->public.dst.height / stream->public.src.height; - pipe_ctx->scl_data.recout.height = clip.height * + pipe_ctx->scl_data.recout.height = surf_clip.height * stream->public.dst.height / stream->public.src.height; if (pipe_ctx->scl_data.recout.height + pipe_ctx->scl_data.recout.y > stream->public.dst.y + stream->public.dst.height) @@ -569,7 +580,7 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip pipe_ctx->scl_data.recout.width += pipe_ctx->scl_data.recout.width % 2; } } else if (pipe_ctx->bottom_pipe && - pipe_ctx->bottom_pipe->surface == pipe_ctx->surface) { + pipe_ctx->bottom_pipe->surface == pipe_ctx->surface) { if (stream->public.timing.timing_3d_format == TIMING_3D_FORMAT_TOP_AND_BOTTOM) pipe_ctx->scl_data.recout.height /= 2; @@ -577,17 +588,17 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip pipe_ctx->scl_data.recout.width /= 2; } - /* Unclipped recout offset = stream dst offset + ((surf dst offset - stream src offset) - * * 1/ stream scaling ratio) - (surf src offset * 1/ full scl + /* Unclipped recout offset = stream dst offset + ((surf dst offset - stream surf_src offset) + * * 1/ stream scaling ratio) - (surf surf_src offset * 1/ full scl * ratio) */ recout_full_x = stream->public.dst.x + (surface->dst_rect.x - stream->public.src.x) * stream->public.dst.width / stream->public.src.width - - surface->src_rect.x * surface->dst_rect.width / surface->src_rect.width + surf_src.x * surface->dst_rect.width / surf_src.width * stream->public.dst.width / stream->public.src.width; recout_full_y = stream->public.dst.y + (surface->dst_rect.y - stream->public.src.y) * stream->public.dst.height / stream->public.src.height - - surface->src_rect.y * surface->dst_rect.height / surface->src_rect.height + surf_src.y * surface->dst_rect.height / surf_src.height * stream->public.dst.height / stream->public.src.height; recout_skip->width = pipe_ctx->scl_data.recout.x - recout_full_x; @@ -598,16 +609,21 @@ static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) { const struct dc_surface *surface = &pipe_ctx->surface->public; struct core_stream *stream = pipe_ctx->stream; + struct rect surf_src = surface->src_rect; const int in_w = stream->public.src.width; const int in_h = stream->public.src.height; const int out_w = stream->public.dst.width; const int out_h = stream->public.dst.height; + if (pipe_ctx->surface->public.rotation == ROTATION_ANGLE_90 || + pipe_ctx->surface->public.rotation == ROTATION_ANGLE_270) + rect_swap_helper(&surf_src); + pipe_ctx->scl_data.ratios.horz = dal_fixed31_32_from_fraction( - surface->src_rect.width, + surf_src.width, surface->dst_rect.width); pipe_ctx->scl_data.ratios.vert = dal_fixed31_32_from_fraction( - surface->src_rect.height, + surf_src.height, surface->dst_rect.height); if (surface->stereo_format == PLANE_STEREO_FORMAT_SIDE_BY_SIDE) @@ -637,8 +653,10 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *r int vpc_div = (data->format == PIXEL_FORMAT_420BPP12 || data->format == PIXEL_FORMAT_420BPP15) ? 2 : 1; + if (pipe_ctx->surface->public.rotation == ROTATION_ANGLE_90 || pipe_ctx->surface->public.rotation == ROTATION_ANGLE_270) { + rect_swap_helper(&src); rect_swap_helper(&data->viewport_c); rect_swap_helper(&data->viewport); } diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index 1a7ce061258f..58a3bcd5131f 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -99,15 +99,15 @@ struct dc_plane_address { }; struct dc_size { - uint32_t width; - uint32_t height; + int width; + int height; }; struct rect { int x; int y; - uint32_t width; - uint32_t height; + int width; + int height; }; union plane_size { @@ -123,7 +123,7 @@ union plane_size { * In LINEAR_GENERAL mode, pitch * is 32 pixel aligned. */ - uint32_t surface_pitch; + int surface_pitch; } grph; struct { @@ -132,14 +132,14 @@ union plane_size { * In LINEAR_GENERAL mode, pitch is * 32 pixel aligned. */ - uint32_t luma_pitch; + int luma_pitch; struct rect chroma_size; /* Graphic surface pitch in pixels. * In LINEAR_GENERAL mode, pitch is * 32 pixel aligned. */ - uint32_t chroma_pitch; + int chroma_pitch; } video; }; @@ -148,15 +148,15 @@ struct dc_plane_dcc_param { union { struct { - uint32_t meta_pitch; + int meta_pitch; bool independent_64b_blks; } grph; struct { - uint32_t meta_pitch_l; + int meta_pitch_l; bool independent_64b_blks_l; - uint32_t meta_pitch_c; + int meta_pitch_c; bool independent_64b_blks_c; } video; }; -- cgit From 0e12c3f6a0a4e73c6b6d11b7aebf20b7026ef18f Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 10 May 2017 11:35:07 -0400 Subject: drm/amd/display: add yuv pixel formats to pixel_format_to_bpp() Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 1e6952bde25b..bc9808180346 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1051,8 +1051,13 @@ static bool is_surface_in_context( static unsigned int pixel_format_to_bpp(enum surface_pixel_format format) { switch (format) { + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: + return 12; case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: case SURFACE_PIXEL_FORMAT_GRPH_RGB565: + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: return 16; case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: -- cgit From b71a061801cb431d23854e0b6a6b7c04fa1f4c83 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 10 May 2017 18:05:02 -0400 Subject: drm/amd/display: fix scaling info based surface update type check Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 47 +++++++++----------------------- 1 file changed, 13 insertions(+), 34 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index bc9808180346..6d56cb0c29cc 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1122,45 +1122,24 @@ static enum surface_update_type get_plane_info_update_type( static enum surface_update_type get_scaling_info_update_type( const struct dc_surface_update *u) { - struct dc_scaling_info temp_scaling_info = { { 0 } }; - if (!u->scaling_info) return UPDATE_TYPE_FAST; - /* Copy all parameters that will cause a full update - * from current surface, the rest of the parameters - * from provided plane configuration. - * Perform memory compare and special validation - * for those that can cause fast/medium updates - */ - - /* Full Update Parameters */ - temp_scaling_info.dst_rect = u->surface->dst_rect; - temp_scaling_info.src_rect = u->surface->src_rect; - temp_scaling_info.scaling_quality = u->surface->scaling_quality; - - /* Special validation required */ - temp_scaling_info.clip_rect = u->scaling_info->clip_rect; - - if (memcmp(u->scaling_info, &temp_scaling_info, - sizeof(struct dc_scaling_info)) != 0) + if (u->scaling_info->src_rect.width != u->surface->src_rect.width + || u->scaling_info->src_rect.height != u->surface->src_rect.height + || u->scaling_info->clip_rect.width != u->surface->clip_rect.width + || u->scaling_info->clip_rect.height != u->surface->clip_rect.height + || u->scaling_info->dst_rect.width != u->surface->dst_rect.width + || u->scaling_info->dst_rect.height != u->surface->dst_rect.height) return UPDATE_TYPE_FULL; - /* Check Clip rectangles if not equal - * difference is in offsets == > UPDATE_TYPE_MED - * difference is in dimensions == > UPDATE_TYPE_FULL - */ - if (memcmp(&u->scaling_info->clip_rect, - &u->surface->clip_rect, sizeof(struct rect)) != 0) { - if ((u->scaling_info->clip_rect.height == - u->surface->clip_rect.height) && - (u->scaling_info->clip_rect.width == - u->surface->clip_rect.width)) { - return UPDATE_TYPE_MED; - } else { - return UPDATE_TYPE_FULL; - } - } + if (u->scaling_info->src_rect.x != u->surface->src_rect.x + || u->scaling_info->src_rect.y != u->surface->src_rect.y + || u->scaling_info->clip_rect.x != u->surface->clip_rect.x + || u->scaling_info->clip_rect.y != u->surface->clip_rect.y + || u->scaling_info->dst_rect.x != u->surface->dst_rect.x + || u->scaling_info->dst_rect.y != u->surface->dst_rect.y) + return UPDATE_TYPE_MED; return UPDATE_TYPE_FAST; } -- cgit From 81e2b2de3d9eb1313aae3f8ddcd1952c39fb8d97 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 10 May 2017 18:24:24 -0400 Subject: drm/amd/display: add explanation for surface_update_type Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 7dd145b6e927..9a19d6f5a6a3 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -434,9 +434,35 @@ bool dc_post_update_surfaces_to_stream( void dc_update_surfaces_for_stream(struct dc *dc, struct dc_surface_update *updates, int surface_count, const struct dc_stream *stream); +/* Surface update type is used by dc_update_surfaces_and_stream + * The update type is determined at the very beginning of the function based + * on parameters passed in and decides how much programming (or updating) is + * going to be done during the call. + * + * UPDATE_TYPE_FAST is used for really fast updates that do not require much + * logical calculations or hardware register programming. This update MUST be + * ISR safe on windows. Currently fast update will only be used to flip surface + * address. + * + * UPDATE_TYPE_MED is used for slower updates which require significant hw + * re-programming however do not affect bandwidth consumption or clock + * requirements. At present, this is the level at which front end updates + * that do not require us to run bw_calcs happen. These are in/out transfer func + * updates, viewport offset changes, recout size changes and pixel depth changes. + * This update can be done at ISR, but we want to minimize how often this happens. + * + * UPDATE_TYPE_FULL is slow. Really slow. This requires us to recalculate our + * bandwidth and clocks, possibly rearrange some pipes and reprogram anything front + * end related. Any time viewport dimensions, recout dimensions, scaling ratios or + * gamma need to be adjusted or pipe needs to be turned on (or disconnected) we do + * a full update. This cannot be done at ISR level and should be a rare event. + * Unless someone is stress testing mpo enter/exit, playing with colour or adjusting + * underscan we don't expect to see this call at all. + */ + enum surface_update_type { UPDATE_TYPE_FAST, /* super fast, safe to execute in isr */ - UPDATE_TYPE_MED, /* a lot of programming needed. may need to alloc */ + UPDATE_TYPE_MED, /* ISR safe, most of programming needed, no bw/clk change*/ UPDATE_TYPE_FULL, /* may need to shuffle resources */ }; -- cgit From ce923dc323afa7274364d2af84a708442f9c9b59 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 15 May 2017 14:23:09 -0400 Subject: drm/amd/display: Remove duplicate entry from log_mask As pointed out by kbuild test robot and Julia Lawall. CC: Julia Lawall CC: Alex Deucher Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/basics/logger.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/basics/logger.c b/drivers/gpu/drm/amd/display/dc/basics/logger.c index 8f4497332bda..4be83703b809 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/logger.c +++ b/drivers/gpu/drm/amd/display/dc/basics/logger.c @@ -81,7 +81,6 @@ static const struct dc_log_type_info log_type_info_tbl[] = { (1 << LOG_SYNC) | \ (1 << LOG_BANDWIDTH_VALIDATION) | \ (1 << LOG_MST) | \ - (1 << LOG_DETECTION_EDID_PARSER) | \ (1 << LOG_DETECTION_DP_CAPS) | \ (1 << LOG_BACKLIGHT)) | \ (1 << LOG_I2C_AUX) | \ -- cgit From 747be97f4ea7de8078739f04e241b5819015f035 Mon Sep 17 00:00:00 2001 From: Amy Zhang Date: Thu, 11 May 2017 17:13:20 -0400 Subject: drm/amd/display: Program CSC Mode For BT2020 - Add BT2020 color space in the set output csc default Signed-off-by: Amy Zhang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c index fce08e5235e6..148e192f5f76 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c @@ -338,9 +338,11 @@ static void opp_set_output_csc_default( if (default_adjust != NULL) { switch (default_adjust->out_color_space) { case COLOR_SPACE_SRGB: + case COLOR_SPACE_2020_RGB_FULLRANGE: ocsc_mode = 0; break; case COLOR_SPACE_SRGB_LIMITED: + case COLOR_SPACE_2020_RGB_LIMITEDRANGE: ocsc_mode = 1; break; case COLOR_SPACE_YCBCR601: @@ -349,6 +351,7 @@ static void opp_set_output_csc_default( break; case COLOR_SPACE_YCBCR709: case COLOR_SPACE_YCBCR709_LIMITED: + case COLOR_SPACE_2020_YCBCR: ocsc_mode = 3; break; case COLOR_SPACE_UNKNOWN: -- cgit From 4b28b76bfe14430a91de74a5cf9215f3c108acf9 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Thu, 11 May 2017 17:15:14 -0400 Subject: drm/amd/display: fix mpo blanking out on one of planes being set not visible Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c | 3 +- drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h | 3 +- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 10 +++--- .../drm/amd/display/dc/dce110/dce110_mem_input_v.c | 3 +- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 41 ++++++++++++++++++---- .../gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c | 20 +++-------- drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h | 8 ++--- 7 files changed, 51 insertions(+), 37 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c index 9da539db287c..0552fc5f7ecc 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c @@ -403,8 +403,7 @@ void dce_mem_input_program_surface_config(struct mem_input *mi, union plane_size *plane_size, enum dc_rotation_angle rotation, struct dc_plane_dcc_param *dcc, - bool horizontal_mirror, - bool visible) + bool horizontal_mirror) { REG_UPDATE(GRPH_ENABLE, GRPH_ENABLE, 1); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h index be37f52e9ba1..4977f5f6e7e2 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h @@ -277,8 +277,7 @@ void dce_mem_input_program_surface_config(struct mem_input *mi, union plane_size *plane_size, enum dc_rotation_angle rotation, struct dc_plane_dcc_param *dcc, - bool horizontal_mirror, - bool visible); + bool horizontal_mirror); void dce_mem_input_allocate_dmif(struct mem_input *mi, uint32_t h_total, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 8a663003017c..20ad1cb263db 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1986,8 +1986,9 @@ static void set_plane_config( &surface->public.plane_size, surface->public.rotation, NULL, - false, - pipe_ctx->surface->public.visible); + false); + if (mi->funcs->set_blank) + mi->funcs->set_blank(mi, pipe_ctx->surface->public.visible); if (dc->public.config.gpu_vm_support) mi->funcs->mem_input_program_pte_vm( @@ -2432,8 +2433,9 @@ static void dce110_program_front_end_for_pipe( &surface->public.plane_size, surface->public.rotation, NULL, - false, - pipe_ctx->surface->public.visible); + false); + if (mi->funcs->set_blank) + mi->funcs->set_blank(mi, pipe_ctx->surface->public.visible); if (dc->public.config.gpu_vm_support) mi->funcs->mem_input_program_pte_vm( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c index 02739d3efa97..78dd3ae3af5f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c @@ -664,8 +664,7 @@ void dce110_mem_input_v_program_surface_config( union plane_size *plane_size, enum dc_rotation_angle rotation, struct dc_plane_dcc_param *dcc, - bool horizotal_mirror, - bool visible) + bool horizotal_mirror) { struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 6cb3924225da..28b47bed72cf 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -848,7 +848,7 @@ static void reset_front_end_for_pipe( unlock_master_tg_and_wait(dc->ctx, pipe_ctx->tg->inst); - pipe_ctx->mi->funcs->disable_request(pipe_ctx->mi); + pipe_ctx->mi->funcs->set_blank(pipe_ctx->mi, true); wait_no_outstanding_request(dc->ctx, pipe_ctx->pipe_idx); @@ -1513,6 +1513,35 @@ static void program_gamut_remap(struct pipe_ctx *pipe_ctx) pipe_ctx->xfm->funcs->transform_set_gamut_remap(pipe_ctx->xfm, &adjust); } +static bool is_lower_pipe_tree_visible(struct pipe_ctx *pipe_ctx) +{ + if (pipe_ctx->surface->public.visible) + return true; + if (pipe_ctx->bottom_pipe && is_lower_pipe_tree_visible(pipe_ctx->bottom_pipe)) + return true; + return false; +} + +static bool is_upper_pipe_tree_visible(struct pipe_ctx *pipe_ctx) +{ + if (pipe_ctx->surface->public.visible) + return true; + if (pipe_ctx->top_pipe && is_upper_pipe_tree_visible(pipe_ctx->top_pipe)) + return true; + return false; +} + +static bool is_pipe_tree_visible(struct pipe_ctx *pipe_ctx) +{ + if (pipe_ctx->surface->public.visible) + return true; + if (pipe_ctx->top_pipe && is_upper_pipe_tree_visible(pipe_ctx->top_pipe)) + return true; + if (pipe_ctx->bottom_pipe && is_lower_pipe_tree_visible(pipe_ctx->bottom_pipe)) + return true; + return false; +} + static void update_dchubp_dpp( struct core_dc *dc, struct pipe_ctx *pipe_ctx, @@ -1633,12 +1662,9 @@ static void update_dchubp_dpp( &size, surface->public.rotation, &surface->public.dcc, - surface->public.horizontal_mirror, - surface->public.visible); - - /* Only support one plane for now. */ - pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, !surface->public.visible); + surface->public.horizontal_mirror); + mi->funcs->set_blank(mi, !is_pipe_tree_visible(pipe_ctx)); } static void program_all_pipe_in_tree( @@ -1669,10 +1695,13 @@ static void program_all_pipe_in_tree( pipe_ctx->tg->funcs->program_global_sync( pipe_ctx->tg); + pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, !is_pipe_tree_visible(pipe_ctx)); update_dchubp_dpp(dc, pipe_ctx, context); + + /* Only support one plane for now. */ } if (pipe_ctx->bottom_pipe != NULL) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index 50b24456d495..587ded13140b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -38,8 +38,9 @@ #define FN(reg_name, field_name) \ mi->mi_shift->field_name, mi->mi_mask->field_name -static void set_blank(struct dcn10_mem_input *mi, bool blank) +static void dcn_mi_set_blank(struct mem_input *mem_input, bool blank) { + struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); uint32_t blank_en = blank ? 1 : 0; REG_UPDATE_2(DCHUBP_CNTL, @@ -47,15 +48,6 @@ static void set_blank(struct dcn10_mem_input *mi, bool blank) HUBP_TTU_DISABLE, blank_en); } - -static void disable_request(struct mem_input *mem_input) -{ - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); - - /* To disable the requestors, set blank_en to 1 */ - set_blank(mi, true); -} - static void vready_workaround(struct mem_input *mem_input, struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest) { @@ -402,8 +394,7 @@ static void mem_input_program_surface_config( union plane_size *plane_size, enum dc_rotation_angle rotation, struct dc_plane_dcc_param *dcc, - bool horizontal_mirror, - bool visible) + bool horizontal_mirror) { struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); @@ -412,8 +403,6 @@ static void mem_input_program_surface_config( program_size_and_rotation( mi, rotation, format, plane_size, dcc, horizontal_mirror); program_pixel_format(mi, format); - - set_blank(mi, !visible); } static void program_requestor( @@ -573,7 +562,6 @@ static void mem_input_setup( /* otg is locked when this func is called. Register are double buffered. * disable the requestors is not needed */ - /* disable_request(mem_input); */ program_requestor(mem_input, rq_regs); program_deadline(mem_input, dlg_attr, ttu_attr); vready_workaround(mem_input, pipe_dest); @@ -1065,7 +1053,6 @@ static struct mem_input_funcs dcn10_mem_input_funcs = { .mem_input_program_display_marks = mem_input_program_display_marks, .allocate_mem_input = NULL, .free_mem_input = NULL, - .disable_request = disable_request, .mem_input_program_surface_flip_and_addr = mem_input_program_surface_flip_and_addr, .mem_input_program_surface_config = @@ -1075,6 +1062,7 @@ static struct mem_input_funcs dcn10_mem_input_funcs = { .program_watermarks = program_watermarks, .mem_input_update_dchub = mem_input_update_dchub, .mem_input_program_pte_vm = dcn_mem_input_program_pte_vm, + .set_blank = dcn_mi_set_blank, }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h index c4aea24d4574..79fbc60e21c9 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h @@ -94,9 +94,6 @@ struct mem_input_funcs { struct _vcs_dpi_display_ttu_regs_st *ttu_regs, struct _vcs_dpi_display_rq_regs_st *rq_regs, struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest); - - void (*disable_request)(struct mem_input *mem_input); - #endif void (*mem_input_program_display_marks)( @@ -142,13 +139,14 @@ struct mem_input_funcs { union plane_size *plane_size, enum dc_rotation_angle rotation, struct dc_plane_dcc_param *dcc, - bool horizontal_mirror, - bool visible); + bool horizontal_mirror); bool (*mem_input_is_flip_pending)(struct mem_input *mem_input); void (*mem_input_update_dchub)(struct mem_input *mem_input, struct dchub_init_data *dh_data); + + void (*set_blank)(struct mem_input *mi, bool blank); }; #endif -- cgit From e806208dc1daebf3b236d0188709d943cf0d9f16 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Fri, 12 May 2017 16:19:15 -0400 Subject: drm/amd/display: Fix slow FPS. Typo in expresion. Signed-off-by: Andrey Grodzovsky Reviewed-by: Andrey Grodzovsky Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') 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 4ec86ed5622f..a2c00c0bf007 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -135,8 +135,8 @@ static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc, &h_position, &v_position); - *position = (v_position) || (h_position << 16); - *vbl = (v_blank_start) || (v_blank_end << 16); + *position = v_position | (h_position << 16); + *vbl = v_blank_start | (v_blank_end << 16); } return 0; -- cgit From aa7397dfd4cd2e31f007ad3adc08823afb40c25b Mon Sep 17 00:00:00 2001 From: Amy Zhang Date: Fri, 12 May 2017 15:54:29 -0400 Subject: drm/amd/display: Disable ABM when eDP is disabled - Add immediate ABM disable when eDP is disabled - Fix purple screen when ABM is mistakenly enabled on non eDP display Signed-off-by: Amy Zhang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 16 ++++++++++++++++ drivers/gpu/drm/amd/display/dc/dc.h | 2 ++ drivers/gpu/drm/amd/display/dc/dce/dce_abm.c | 21 +++++++++++++++++++++ drivers/gpu/drm/amd/display/dc/inc/hw/abm.h | 1 + 4 files changed, 40 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index ffc0eeaad175..59977640f938 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1415,6 +1415,22 @@ bool dc_link_set_backlight_level(const struct dc_link *dc_link, uint32_t level, return true; } + +bool dc_link_set_abm_disable(const struct dc_link *dc_link) +{ + struct core_link *link = DC_LINK_TO_CORE(dc_link); + struct core_dc *core_dc = DC_TO_CORE(link->ctx->dc); + struct abm *abm = core_dc->res_pool->abm; + + if ((abm == NULL) || (abm->funcs->set_backlight_level == NULL)) + return false; + + abm->funcs->set_abm_immediate_disable(abm); + + return true; +} + + bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable) { struct core_link *link = DC_LINK_TO_CORE(dc_link); diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 9a19d6f5a6a3..0610805cdb05 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -714,6 +714,8 @@ const struct graphics_object_id dc_get_link_id_at_index( bool dc_link_set_backlight_level(const struct dc_link *dc_link, uint32_t level, uint32_t frame_ramp, const struct dc_stream *stream); +bool dc_link_set_abm_disable(const struct dc_link *dc_link); + bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable); bool dc_link_setup_psr(const struct dc_link *dc_link, diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c index cefffe164fe0..b4fa78292ad2 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c @@ -49,6 +49,8 @@ #define MCP_ABM_PIPE_SET 0x66 #define MCP_BL_SET 0x67 +#define MCP_DISABLE_ABM_IMMEDIATELY 255 + struct abm_backlight_registers { unsigned int BL_PWM_CNTL; unsigned int BL_PWM_CNTL2; @@ -315,6 +317,24 @@ static bool dce_abm_set_level(struct abm *abm, uint32_t level) return true; } +static bool dce_abm_immediate_disable(struct abm *abm) +{ + struct dce_abm *abm_dce = TO_DCE_ABM(abm); + + REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, + 100, 800); + + /* setDMCUParam_ABMLevel */ + REG_UPDATE_2(MASTER_COMM_CMD_REG, + MASTER_COMM_CMD_REG_BYTE0, MCP_ABM_LEVEL_SET, + MASTER_COMM_CMD_REG_BYTE2, MCP_DISABLE_ABM_IMMEDIATELY); + + /* notifyDMCUMsg */ + REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); + + return true; +} + static bool dce_abm_init_backlight(struct abm *abm) { struct dce_abm *abm_dce = TO_DCE_ABM(abm); @@ -414,6 +434,7 @@ static const struct abm_funcs dce_funcs = { .init_backlight = dce_abm_init_backlight, .set_backlight_level = dce_abm_set_backlight_level, .get_current_backlight_8_bit = dce_abm_get_current_backlight_8_bit, + .set_abm_immediate_disable = dce_abm_immediate_disable, .is_dmcu_initialized = is_dmcu_initialized }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h b/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h index da465b3e98e8..c93b9b9a817c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h @@ -35,6 +35,7 @@ struct abm { struct abm_funcs { void (*abm_init)(struct abm *abm); bool (*set_abm_level)(struct abm *abm, unsigned int abm_level); + bool (*set_abm_immediate_disable)(struct abm *abm); bool (*init_backlight)(struct abm *abm); bool (*set_backlight_level)(struct abm *abm, unsigned int backlight_level, -- cgit From c34892144d38eddb4499ac425c24455b1e34dd61 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Mon, 15 May 2017 08:31:51 -0400 Subject: drm/amd/display: dce 8 - 12 mem_input refactor to new style Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c | 306 +++++++++++++-- drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h | 115 ++++-- .../drm/amd/display/dc/dce100/dce100_resource.c | 78 +--- drivers/gpu/drm/amd/display/dc/dce110/Makefile | 3 +- .../drm/amd/display/dc/dce110/dce110_mem_input.c | 437 --------------------- .../drm/amd/display/dc/dce110/dce110_mem_input.h | 121 ------ .../drm/amd/display/dc/dce110/dce110_mem_input_v.c | 155 +++----- .../drm/amd/display/dc/dce110/dce110_mem_input_v.h | 66 +--- .../drm/amd/display/dc/dce110/dce110_resource.c | 58 +-- drivers/gpu/drm/amd/display/dc/dce112/Makefile | 2 +- .../drm/amd/display/dc/dce112/dce112_mem_input.c | 54 --- .../drm/amd/display/dc/dce112/dce112_mem_input.h | 38 -- .../drm/amd/display/dc/dce112/dce112_resource.c | 77 +--- drivers/gpu/drm/amd/display/dc/dce120/Makefile | 2 +- .../drm/amd/display/dc/dce120/dce120_mem_input.c | 340 ---------------- .../drm/amd/display/dc/dce120/dce120_mem_input.h | 37 -- .../drm/amd/display/dc/dce120/dce120_resource.c | 75 +--- drivers/gpu/drm/amd/display/dc/dce80/Makefile | 3 +- .../gpu/drm/amd/display/dc/dce80/dce80_mem_input.c | 83 ---- .../gpu/drm/amd/display/dc/dce80/dce80_mem_input.h | 36 -- .../gpu/drm/amd/display/dc/dce80/dce80_resource.c | 78 +--- drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h | 8 - 22 files changed, 476 insertions(+), 1696 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dce112/dce112_mem_input.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dce112/dce112_mem_input.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dce120/dce120_mem_input.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dce120/dce120_mem_input.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c index 0552fc5f7ecc..718688c41f7b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c @@ -23,18 +23,18 @@ * */ -#include "mem_input.h" +#include "dce_mem_input.h" #include "reg_helper.h" #include "basics/conversion.h" #define CTX \ - mi->ctx + dce_mi->base.ctx #define REG(reg)\ - mi->regs->reg + dce_mi->regs->reg #undef FN #define FN(reg_name, field_name) \ - mi->shifts->field_name, mi->masks->field_name + dce_mi->shifts->field_name, dce_mi->masks->field_name struct pte_setting { unsigned int bpp; @@ -130,11 +130,13 @@ static bool is_vert_scan(enum dc_rotation_angle rotation) } } -void dce_mem_input_program_pte_vm(struct mem_input *mi, +static void dce_mi_program_pte_vm( + struct mem_input *mi, enum surface_pixel_format format, union dc_tiling_info *tiling_info, enum dc_rotation_angle rotation) { + struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi); enum mi_bits_per_pixel mi_bpp = get_mi_bpp(format); enum mi_tiling_format mi_tiling = get_mi_tiling(tiling_info); const struct pte_setting *pte = &pte_settings[mi_tiling][mi_bpp]; @@ -158,7 +160,8 @@ void dce_mem_input_program_pte_vm(struct mem_input *mi, DVMM_MAX_PTE_REQ_OUTSTANDING, 0xff); } -static void program_urgency_watermark(struct mem_input *mi, +static void program_urgency_watermark( + struct dce_mem_input *dce_mi, uint32_t wm_select, uint32_t urgency_low_wm, uint32_t urgency_high_wm) @@ -171,7 +174,8 @@ static void program_urgency_watermark(struct mem_input *mi, URGENCY_HIGH_WATERMARK, urgency_high_wm); } -static void program_nbp_watermark(struct mem_input *mi, +static void program_nbp_watermark( + struct dce_mem_input *dce_mi, uint32_t wm_select, uint32_t nbp_wm) { @@ -202,7 +206,8 @@ static void program_nbp_watermark(struct mem_input *mi, } } -static void program_stutter_watermark(struct mem_input *mi, +static void program_stutter_watermark( + struct dce_mem_input *dce_mi, uint32_t wm_select, uint32_t stutter_mark) { @@ -217,41 +222,67 @@ static void program_stutter_watermark(struct mem_input *mi, STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark); } -void dce_mem_input_program_display_marks(struct mem_input *mi, +static void dce_mi_program_display_marks( + struct mem_input *mi, struct dce_watermarks nbp, struct dce_watermarks stutter, struct dce_watermarks urgent, uint32_t total_dest_line_time_ns) { + struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi); uint32_t stutter_en = mi->ctx->dc->debug.disable_stutter ? 0 : 1; - program_urgency_watermark(mi, 0, /* set a */ + program_urgency_watermark(dce_mi, 2, /* set a */ urgent.a_mark, total_dest_line_time_ns); - program_urgency_watermark(mi, 1, /* set b */ + program_urgency_watermark(dce_mi, 1, /* set d */ + urgent.d_mark, total_dest_line_time_ns); + + REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL, + STUTTER_ENABLE, stutter_en, + STUTTER_IGNORE_FBC, 1); + program_nbp_watermark(dce_mi, 2, nbp.a_mark); /* set a */ + program_nbp_watermark(dce_mi, 1, nbp.d_mark); /* set d */ + + program_stutter_watermark(dce_mi, 2, stutter.a_mark); /* set a */ + program_stutter_watermark(dce_mi, 1, stutter.d_mark); /* set d */ +} + +static void dce120_mi_program_display_marks(struct mem_input *mi, + struct dce_watermarks nbp, + struct dce_watermarks stutter, + struct dce_watermarks urgent, + uint32_t total_dest_line_time_ns) +{ + struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi); + uint32_t stutter_en = mi->ctx->dc->debug.disable_stutter ? 0 : 1; + + program_urgency_watermark(dce_mi, 0, /* set a */ + urgent.a_mark, total_dest_line_time_ns); + program_urgency_watermark(dce_mi, 1, /* set b */ urgent.b_mark, total_dest_line_time_ns); - program_urgency_watermark(mi, 2, /* set c */ + program_urgency_watermark(dce_mi, 2, /* set c */ urgent.c_mark, total_dest_line_time_ns); - program_urgency_watermark(mi, 3, /* set d */ + program_urgency_watermark(dce_mi, 3, /* set d */ urgent.d_mark, total_dest_line_time_ns); REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL, STUTTER_ENABLE, stutter_en, STUTTER_IGNORE_FBC, 1); - program_nbp_watermark(mi, 0, nbp.a_mark); /* set a */ - program_nbp_watermark(mi, 1, nbp.b_mark); /* set b */ - program_nbp_watermark(mi, 2, nbp.c_mark); /* set c */ - program_nbp_watermark(mi, 3, nbp.d_mark); /* set d */ - - program_stutter_watermark(mi, 0, stutter.a_mark); /* set a */ - program_stutter_watermark(mi, 1, stutter.b_mark); /* set b */ - program_stutter_watermark(mi, 2, stutter.c_mark); /* set c */ - program_stutter_watermark(mi, 3, stutter.d_mark); /* set d */ + program_nbp_watermark(dce_mi, 0, nbp.a_mark); /* set a */ + program_nbp_watermark(dce_mi, 1, nbp.b_mark); /* set b */ + program_nbp_watermark(dce_mi, 2, nbp.c_mark); /* set c */ + program_nbp_watermark(dce_mi, 3, nbp.d_mark); /* set d */ + + program_stutter_watermark(dce_mi, 0, stutter.a_mark); /* set a */ + program_stutter_watermark(dce_mi, 1, stutter.b_mark); /* set b */ + program_stutter_watermark(dce_mi, 2, stutter.c_mark); /* set c */ + program_stutter_watermark(dce_mi, 3, stutter.d_mark); /* set d */ } -static void program_tiling(struct mem_input *mi, - const union dc_tiling_info *info) +static void program_tiling( + struct dce_mem_input *dce_mi, const union dc_tiling_info *info) { - if (mi->masks->GRPH_SW_MODE) { /* GFX9 */ + if (dce_mi->masks->GRPH_SW_MODE) { /* GFX9 */ REG_UPDATE_6(GRPH_CONTROL, GRPH_SW_MODE, info->gfx9.swizzle, GRPH_NUM_BANKS, log_2(info->gfx9.num_banks), @@ -265,7 +296,7 @@ static void program_tiling(struct mem_input *mi, */ } - if (mi->masks->GRPH_ARRAY_MODE) { /* GFX8 */ + if (dce_mi->masks->GRPH_ARRAY_MODE) { /* GFX8 */ REG_UPDATE_9(GRPH_CONTROL, GRPH_NUM_BANKS, info->gfx8.num_banks, GRPH_BANK_WIDTH, info->gfx8.bank_width, @@ -285,7 +316,7 @@ static void program_tiling(struct mem_input *mi, static void program_size_and_rotation( - struct mem_input *mi, + struct dce_mem_input *dce_mi, enum dc_rotation_angle rotation, const union plane_size *plane_size) { @@ -326,7 +357,7 @@ static void program_size_and_rotation( } static void program_grph_pixel_format( - struct mem_input *mi, + struct dce_mem_input *dce_mi, enum surface_pixel_format format) { uint32_t red_xbar = 0, blue_xbar = 0; /* no swap */ @@ -397,7 +428,8 @@ static void program_grph_pixel_format( GRPH_PRESCALE_B_SIGN, sign); } -void dce_mem_input_program_surface_config(struct mem_input *mi, +static void dce_mi_program_surface_config( + struct mem_input *mi, enum surface_pixel_format format, union dc_tiling_info *tiling_info, union plane_size *plane_size, @@ -405,14 +437,15 @@ void dce_mem_input_program_surface_config(struct mem_input *mi, struct dc_plane_dcc_param *dcc, bool horizontal_mirror) { + struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi); REG_UPDATE(GRPH_ENABLE, GRPH_ENABLE, 1); - program_tiling(mi, tiling_info); - program_size_and_rotation(mi, rotation, plane_size); + program_tiling(dce_mi, tiling_info); + program_size_and_rotation(dce_mi, rotation, plane_size); if (format >= SURFACE_PIXEL_FORMAT_GRPH_BEGIN && format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) - program_grph_pixel_format(mi, format); + program_grph_pixel_format(dce_mi, format); } static uint32_t get_dmif_switch_time_us( @@ -461,12 +494,14 @@ static uint32_t get_dmif_switch_time_us( return frame_time; } -void dce_mem_input_allocate_dmif(struct mem_input *mi, +static void dce_mi_allocate_dmif( + struct mem_input *mi, uint32_t h_total, uint32_t v_total, uint32_t pix_clk_khz, uint32_t total_stream_num) { + struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi); const uint32_t retry_delay = 10; uint32_t retry_count = get_dmif_switch_time_us( h_total, @@ -497,18 +532,20 @@ void dce_mem_input_allocate_dmif(struct mem_input *mi, PIXEL_DURATION, pix_dur); } - if (mi->wa.single_head_rdreq_dmif_limit) { + if (dce_mi->wa.single_head_rdreq_dmif_limit) { uint32_t eanble = (total_stream_num > 1) ? 0 : - mi->wa.single_head_rdreq_dmif_limit; + dce_mi->wa.single_head_rdreq_dmif_limit; REG_UPDATE(MC_HUB_RDREQ_DMIF_LIMIT, ENABLE, eanble); } } -void dce_mem_input_free_dmif(struct mem_input *mi, +static void dce_mi_free_dmif( + struct mem_input *mi, uint32_t total_stream_num) { + struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi); uint32_t buffers_allocated; uint32_t dmif_buffer_control; @@ -525,11 +562,204 @@ void dce_mem_input_free_dmif(struct mem_input *mi, DMIF_BUFFERS_ALLOCATION_COMPLETED, 1, 10, 3500); - if (mi->wa.single_head_rdreq_dmif_limit) { + if (dce_mi->wa.single_head_rdreq_dmif_limit) { uint32_t eanble = (total_stream_num > 1) ? 0 : - mi->wa.single_head_rdreq_dmif_limit; + dce_mi->wa.single_head_rdreq_dmif_limit; REG_UPDATE(MC_HUB_RDREQ_DMIF_LIMIT, ENABLE, eanble); } } + + +static void program_sec_addr( + struct dce_mem_input *dce_mi, + PHYSICAL_ADDRESS_LOC address) +{ + /*high register MUST be programmed first*/ + REG_SET(GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, 0, + GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, + address.high_part); + + REG_SET_2(GRPH_SECONDARY_SURFACE_ADDRESS, 0, + GRPH_SECONDARY_SURFACE_ADDRESS, address.low_part >> 8, + GRPH_SECONDARY_DFQ_ENABLE, 0); +} + +static void program_pri_addr( + struct dce_mem_input *dce_mi, + PHYSICAL_ADDRESS_LOC address) +{ + /*high register MUST be programmed first*/ + REG_SET(GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, 0, + GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, + address.high_part); + + REG_SET(GRPH_PRIMARY_SURFACE_ADDRESS, 0, + GRPH_PRIMARY_SURFACE_ADDRESS, + address.low_part >> 8); +} + + +static bool dce_mi_is_flip_pending(struct mem_input *mem_input) +{ + struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mem_input); + uint32_t update_pending; + + REG_GET(GRPH_UPDATE, GRPH_SURFACE_UPDATE_PENDING, &update_pending); + if (update_pending) + return true; + + mem_input->current_address = mem_input->request_address; + return false; +} + +static bool dce_mi_program_surface_flip_and_addr( + struct mem_input *mem_input, + const struct dc_plane_address *address, + bool flip_immediate) +{ + struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mem_input); + + /* TODO: Figure out if two modes are needed: + * non-XDMA Mode: GRPH_SURFACE_UPDATE_IMMEDIATE_EN = 1 + * XDMA Mode: GRPH_SURFACE_UPDATE_H_RETRACE_EN = 1 + */ + REG_UPDATE(GRPH_UPDATE, + GRPH_UPDATE_LOCK, 1); + + if (flip_immediate) { + REG_UPDATE_2(GRPH_FLIP_CONTROL, + GRPH_SURFACE_UPDATE_IMMEDIATE_EN, 0, + GRPH_SURFACE_UPDATE_H_RETRACE_EN, 1); + } else { + REG_UPDATE_2(GRPH_FLIP_CONTROL, + GRPH_SURFACE_UPDATE_IMMEDIATE_EN, 0, + GRPH_SURFACE_UPDATE_H_RETRACE_EN, 0); + } + + switch (address->type) { + case PLN_ADDR_TYPE_GRAPHICS: + if (address->grph.addr.quad_part == 0) + break; + program_pri_addr(dce_mi, address->grph.addr); + break; + case PLN_ADDR_TYPE_GRPH_STEREO: + if (address->grph_stereo.left_addr.quad_part == 0 + || address->grph_stereo.right_addr.quad_part == 0) + break; + program_pri_addr(dce_mi, address->grph_stereo.left_addr); + program_sec_addr(dce_mi, address->grph_stereo.right_addr); + break; + default: + /* not supported */ + BREAK_TO_DEBUGGER(); + break; + } + + mem_input->request_address = *address; + + if (flip_immediate) + mem_input->current_address = *address; + + REG_UPDATE(GRPH_UPDATE, + GRPH_UPDATE_LOCK, 0); + + return true; +} + +static void dce_mi_update_dchub(struct mem_input *mi, + struct dchub_init_data *dh_data) +{ + struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi); + /* TODO: port code from dal2 */ + switch (dh_data->fb_mode) { + case FRAME_BUFFER_MODE_ZFB_ONLY: + /*For ZFB case need to put DCHUB FB BASE and TOP upside down to indicate ZFB mode*/ + REG_UPDATE_2(DCHUB_FB_LOCATION, + FB_TOP, 0, + FB_BASE, 0x0FFFF); + + REG_UPDATE(DCHUB_AGP_BASE, + AGP_BASE, dh_data->zfb_phys_addr_base >> 22); + + REG_UPDATE(DCHUB_AGP_BOT, + AGP_BOT, dh_data->zfb_mc_base_addr >> 22); + + REG_UPDATE(DCHUB_AGP_TOP, + AGP_TOP, (dh_data->zfb_mc_base_addr + dh_data->zfb_size_in_byte - 1) >> 22); + break; + case FRAME_BUFFER_MODE_MIXED_ZFB_AND_LOCAL: + /*Should not touch FB LOCATION (done by VBIOS on AsicInit table)*/ + REG_UPDATE(DCHUB_AGP_BASE, + AGP_BASE, dh_data->zfb_phys_addr_base >> 22); + + REG_UPDATE(DCHUB_AGP_BOT, + AGP_BOT, dh_data->zfb_mc_base_addr >> 22); + + REG_UPDATE(DCHUB_AGP_TOP, + AGP_TOP, (dh_data->zfb_mc_base_addr + dh_data->zfb_size_in_byte - 1) >> 22); + break; + case FRAME_BUFFER_MODE_LOCAL_ONLY: + /*Should not touch FB LOCATION (done by VBIOS on AsicInit table)*/ + REG_UPDATE(DCHUB_AGP_BASE, + AGP_BASE, 0); + + REG_UPDATE(DCHUB_AGP_BOT, + AGP_BOT, 0x03FFFF); + + REG_UPDATE(DCHUB_AGP_TOP, + AGP_TOP, 0); + break; + default: + break; + } + + dh_data->dchub_initialzied = true; + dh_data->dchub_info_valid = false; +} + +static struct mem_input_funcs dce_mi_funcs = { + .mem_input_program_display_marks = dce_mi_program_display_marks, + .allocate_mem_input = dce_mi_allocate_dmif, + .free_mem_input = dce_mi_free_dmif, + .mem_input_program_surface_flip_and_addr = + dce_mi_program_surface_flip_and_addr, + .mem_input_program_pte_vm = dce_mi_program_pte_vm, + .mem_input_program_surface_config = + dce_mi_program_surface_config, + .mem_input_is_flip_pending = dce_mi_is_flip_pending, + .mem_input_update_dchub = dce_mi_update_dchub +}; + + +void dce_mem_input_construct( + struct dce_mem_input *dce_mi, + struct dc_context *ctx, + int inst, + const struct dce_mem_input_registers *regs, + const struct dce_mem_input_shift *mi_shift, + const struct dce_mem_input_mask *mi_mask) +{ + dce_mi->base.ctx = ctx; + + dce_mi->base.inst = inst; + dce_mi->base.funcs = &dce_mi_funcs; + + dce_mi->regs = regs; + dce_mi->shifts = mi_shift; + dce_mi->masks = mi_mask; + +} + +void dce112_mem_input_construct( + struct dce_mem_input *dce_mi, + struct dc_context *ctx, + int inst, + const struct dce_mem_input_registers *regs, + const struct dce_mem_input_shift *mi_shift, + const struct dce_mem_input_mask *mi_mask) +{ + dce_mem_input_construct(dce_mi, ctx, inst, regs, mi_shift, mi_mask); + dce_mi->base.funcs->mem_input_program_display_marks = dce120_mi_program_display_marks; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h index 4977f5f6e7e2..55481f5adcdf 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h @@ -26,8 +26,10 @@ #define __DCE_MEM_INPUT_H__ #include "dc_hw_types.h" -struct dce_watermarks; -struct mem_input; +#include "mem_input.h" + +#define TO_DCE_MEM_INPUT(mem_input)\ + container_of(mem_input, struct dce_mem_input, base) #define MI_DCE_BASE_REG_LIST(id)\ SRI(GRPH_ENABLE, DCP, id),\ @@ -40,6 +42,12 @@ struct mem_input; SRI(HW_ROTATION, DCP, id),\ SRI(GRPH_SWAP_CNTL, DCP, id),\ SRI(PRESCALE_GRPH_CONTROL, DCP, id),\ + SRI(GRPH_UPDATE, DCP, id),\ + SRI(GRPH_FLIP_CONTROL, DCP, id),\ + SRI(GRPH_PRIMARY_SURFACE_ADDRESS, DCP, id),\ + SRI(GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, DCP, id),\ + SRI(GRPH_SECONDARY_SURFACE_ADDRESS, DCP, id),\ + SRI(GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, DCP, id),\ SRI(DPG_PIPE_ARBITRATION_CONTROL1, DMIF_PG, id),\ SRI(DPG_WATERMARK_MASK_CONTROL, DMIF_PG, id),\ SRI(DPG_PIPE_URGENCY_CONTROL, DMIF_PG, id),\ @@ -67,7 +75,11 @@ struct mem_input; MI_DCE_PTE_REG_LIST(id),\ SRI(GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT, DCP, id),\ SRI(DPG_PIPE_STUTTER_CONTROL2, DMIF_PG, id),\ - SRI(DPG_PIPE_LOW_POWER_CONTROL, DMIF_PG, id) + SRI(DPG_PIPE_LOW_POWER_CONTROL, DMIF_PG, id),\ + SR(DCHUB_FB_LOCATION),\ + SR(DCHUB_AGP_BASE),\ + SR(DCHUB_AGP_BOT),\ + SR(DCHUB_AGP_TOP) struct dce_mem_input_registers { /* DCP */ @@ -84,6 +96,12 @@ struct dce_mem_input_registers { uint32_t GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT; uint32_t DVMM_PTE_CONTROL; uint32_t DVMM_PTE_ARB_CONTROL; + uint32_t GRPH_UPDATE; + uint32_t GRPH_FLIP_CONTROL; + uint32_t GRPH_PRIMARY_SURFACE_ADDRESS; + uint32_t GRPH_PRIMARY_SURFACE_ADDRESS_HIGH; + uint32_t GRPH_SECONDARY_SURFACE_ADDRESS; + uint32_t GRPH_SECONDARY_SURFACE_ADDRESS_HIGH; /* DMIF_PG */ uint32_t DPG_PIPE_ARBITRATION_CONTROL1; uint32_t DPG_WATERMARK_MASK_CONTROL; @@ -96,6 +114,11 @@ struct dce_mem_input_registers { uint32_t DMIF_BUFFER_CONTROL; /* MC_HUB */ uint32_t MC_HUB_RDREQ_DMIF_LIMIT; + /*DCHUB*/ + uint32_t DCHUB_FB_LOCATION; + uint32_t DCHUB_AGP_BASE; + uint32_t DCHUB_AGP_BOT; + uint32_t DCHUB_AGP_TOP; }; /* Set_Filed_for_Block */ @@ -129,9 +152,16 @@ struct dce_mem_input_registers { SFB(blk, PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_SELECT, mask_sh),\ SFB(blk, PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_R_SIGN, mask_sh),\ SFB(blk, PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_G_SIGN, mask_sh),\ - SFB(blk, PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_B_SIGN, mask_sh) + SFB(blk, PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_B_SIGN, mask_sh),\ + SFB(blk, GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, mask_sh),\ + SFB(blk, GRPH_SECONDARY_SURFACE_ADDRESS, GRPH_SECONDARY_SURFACE_ADDRESS, mask_sh),\ + SFB(blk, GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, mask_sh),\ + SFB(blk, GRPH_PRIMARY_SURFACE_ADDRESS, GRPH_PRIMARY_SURFACE_ADDRESS, mask_sh),\ + SFB(blk, GRPH_UPDATE, GRPH_SURFACE_UPDATE_PENDING, mask_sh),\ + SFB(blk, GRPH_FLIP_CONTROL, GRPH_SURFACE_UPDATE_H_RETRACE_EN, mask_sh) #define MI_DCP_DCE11_MASK_SH_LIST(mask_sh, blk)\ + SFB(blk, GRPH_FLIP_CONTROL, GRPH_SURFACE_UPDATE_IMMEDIATE_EN, mask_sh),\ SFB(blk, GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT, GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT, mask_sh) #define MI_DCP_PTE_MASK_SH_LIST(mask_sh, blk)\ @@ -189,13 +219,22 @@ struct dce_mem_input_registers { SFB(blk, DPG_PIPE_LOW_POWER_CONTROL, PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST, mask_sh),\ SFB(blk, DPG_PIPE_LOW_POWER_CONTROL, PSTATE_CHANGE_WATERMARK, mask_sh) +#define MI_GFX9_DCHUB_MASK_SH_LIST(mask_sh)\ + SF(DCHUB_FB_LOCATION, FB_TOP, mask_sh),\ + SF(DCHUB_FB_LOCATION, FB_BASE, mask_sh),\ + SF(DCHUB_AGP_BASE, AGP_BASE, mask_sh),\ + SF(DCHUB_AGP_BOT, AGP_BOT, mask_sh),\ + SF(DCHUB_AGP_TOP, AGP_TOP, mask_sh) + #define MI_DCE12_MASK_SH_LIST(mask_sh)\ MI_DCP_MASK_SH_LIST(mask_sh, DCP0_),\ + SF(DCP0_GRPH_SECONDARY_SURFACE_ADDRESS, GRPH_SECONDARY_DFQ_ENABLE, mask_sh),\ MI_DCP_DCE11_MASK_SH_LIST(mask_sh, DCP0_),\ MI_DCP_PTE_MASK_SH_LIST(mask_sh, DCP0_),\ MI_DMIF_PG_MASK_SH_LIST(mask_sh, DMIF_PG0_),\ MI_DCE12_DMIF_PG_MASK_SH_LIST(mask_sh, DMIF_PG0_),\ - MI_GFX9_TILE_MASK_SH_LIST(mask_sh, DCP0_) + MI_GFX9_TILE_MASK_SH_LIST(mask_sh, DCP0_),\ + MI_GFX9_DCHUB_MASK_SH_LIST(mask_sh) #define MI_REG_FIELD_LIST(type) \ type GRPH_ENABLE; \ @@ -232,6 +271,15 @@ struct dce_mem_input_registers { type GRPH_SE_ENABLE; \ type GRPH_NUM_SHADER_ENGINES; \ type GRPH_NUM_PIPES; \ + type GRPH_SECONDARY_SURFACE_ADDRESS_HIGH; \ + type GRPH_SECONDARY_SURFACE_ADDRESS; \ + type GRPH_SECONDARY_DFQ_ENABLE; \ + type GRPH_PRIMARY_SURFACE_ADDRESS_HIGH; \ + type GRPH_PRIMARY_SURFACE_ADDRESS; \ + type GRPH_SURFACE_UPDATE_PENDING; \ + type GRPH_SURFACE_UPDATE_IMMEDIATE_EN; \ + type GRPH_SURFACE_UPDATE_H_RETRACE_EN; \ + type GRPH_UPDATE_LOCK; \ type PIXEL_DURATION; \ type URGENCY_WATERMARK_MASK; \ type PSTATE_CHANGE_WATERMARK_MASK; \ @@ -253,6 +301,11 @@ struct dce_mem_input_registers { type DMIF_BUFFERS_ALLOCATED; \ type DMIF_BUFFERS_ALLOCATION_COMPLETED; \ type ENABLE; /* MC_HUB_RDREQ_DMIF_LIMIT */\ + type FB_BASE; \ + type FB_TOP; \ + type AGP_BASE; \ + type AGP_TOP; \ + type AGP_BOT; \ struct dce_mem_input_shift { MI_REG_FIELD_LIST(uint8_t) @@ -266,32 +319,30 @@ struct dce_mem_input_wa { uint8_t single_head_rdreq_dmif_limit; }; -void dce_mem_input_program_pte_vm(struct mem_input *mi, - enum surface_pixel_format format, - union dc_tiling_info *tiling_info, - enum dc_rotation_angle rotation); - -void dce_mem_input_program_surface_config(struct mem_input *mi, - enum surface_pixel_format format, - union dc_tiling_info *tiling_info, - union plane_size *plane_size, - enum dc_rotation_angle rotation, - struct dc_plane_dcc_param *dcc, - bool horizontal_mirror); - -void dce_mem_input_allocate_dmif(struct mem_input *mi, - uint32_t h_total, - uint32_t v_total, - uint32_t pix_clk_khz, - uint32_t total_stream_num); - -void dce_mem_input_free_dmif(struct mem_input *mi, - uint32_t total_stream_num); - -void dce_mem_input_program_display_marks(struct mem_input *mi, - struct dce_watermarks nbp, - struct dce_watermarks stutter, - struct dce_watermarks urgent, - uint32_t total_dest_line_time_ns); +struct dce_mem_input { + struct mem_input base; + + const struct dce_mem_input_registers *regs; + const struct dce_mem_input_shift *shifts; + const struct dce_mem_input_mask *masks; + + struct dce_mem_input_wa wa; +}; + +void dce_mem_input_construct( + struct dce_mem_input *dce_mi, + struct dc_context *ctx, + int inst, + const struct dce_mem_input_registers *regs, + const struct dce_mem_input_shift *mi_shift, + const struct dce_mem_input_mask *mi_mask); + +void dce112_mem_input_construct( + struct dce_mem_input *dce_mi, + struct dc_context *ctx, + int inst, + const struct dce_mem_input_registers *regs, + const struct dce_mem_input_shift *mi_shift, + const struct dce_mem_input_mask *mi_mask); #endif /*__DCE_MEM_INPUT_H__*/ diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 254f9e4d0fc8..8f1fe95dd76c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -35,8 +35,8 @@ #include "irq/dce110/irq_service_dce110.h" #include "dce/dce_link_encoder.h" #include "dce/dce_stream_encoder.h" -#include "dce110/dce110_mem_input.h" -#include "dce110/dce110_mem_input_v.h" + +#include "dce/dce_mem_input.h" #include "dce/dce_ipp.h" #include "dce/dce_transform.h" #include "dce/dce_opp.h" @@ -123,51 +123,6 @@ static const struct dce110_timing_generator_offsets dce100_tg_offsets[] = { } }; -static const struct dce110_mem_input_reg_offsets dce100_mi_reg_offsets[] = { - { - .dcp = (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE0_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - }, - { - .dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG1_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE1_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - }, - { - .dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG2_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE2_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - }, - { - .dcp = (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG3_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE3_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - }, - { - .dcp = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG4_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE4_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - }, - { - .dcp = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG5_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE5_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - } -}; - /* set register offset */ #define SR(reg_name)\ .reg_name = mm ## reg_name @@ -510,28 +465,18 @@ static const struct dce_mem_input_mask mi_masks = { static struct mem_input *dce100_mem_input_create( struct dc_context *ctx, - uint32_t inst, - const struct dce110_mem_input_reg_offsets *offset) + uint32_t inst) { - struct dce110_mem_input *mem_input110 = - dm_alloc(sizeof(struct dce110_mem_input)); + struct dce_mem_input *dce_mi = dm_alloc(sizeof(struct dce_mem_input)); - if (!mem_input110) + if (!dce_mi) { + BREAK_TO_DEBUGGER(); return NULL; - - if (dce110_mem_input_construct(mem_input110, ctx, inst, offset)) { - struct mem_input *mi = &mem_input110->base; - - mi->regs = &mi_regs[inst]; - mi->shifts = &mi_shifts; - mi->masks = &mi_masks; - mi->wa.single_head_rdreq_dmif_limit = 2; - return mi; } - BREAK_TO_DEBUGGER(); - dm_free(mem_input110); - return NULL; + dce_mem_input_construct(dce_mi, ctx, inst, &mi_regs[inst], &mi_shifts, &mi_masks); + dce_mi->wa.single_head_rdreq_dmif_limit = 2; + return &dce_mi->base; } static void dce100_transform_destroy(struct transform **xfm) @@ -671,7 +616,7 @@ static void destruct(struct dce110_resource_pool *pool) dce_ipp_destroy(&pool->base.ipps[i]); if (pool->base.mis[i] != NULL) { - dm_free(TO_DCE110_MEM_INPUT(pool->base.mis[i])); + dm_free(TO_DCE_MEM_INPUT(pool->base.mis[i])); pool->base.mis[i] = NULL; } @@ -986,8 +931,7 @@ static bool construct( goto res_create_fail; } - pool->base.mis[i] = dce100_mem_input_create(ctx, i, - &dce100_mi_reg_offsets[i]); + pool->base.mis[i] = dce100_mem_input_create(ctx, i); if (pool->base.mis[i] == NULL) { BREAK_TO_DEBUGGER(); dm_error( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/Makefile b/drivers/gpu/drm/amd/display/dc/dce110/Makefile index c54bf0330701..98d956e2f218 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dce110/Makefile @@ -3,8 +3,7 @@ # It provides the control and status of HW CRTC block. DCE110 = dce110_timing_generator.o \ -dce110_compressor.o dce110_mem_input.o dce110_hw_sequencer.o \ -dce110_resource.o \ +dce110_compressor.o dce110_hw_sequencer.o dce110_resource.o \ dce110_opp_regamma_v.o dce110_opp_csc_v.o dce110_timing_generator_v.o \ dce110_mem_input_v.o dce110_opp_v.o dce110_transform_v.o diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c deleted file mode 100644 index 45e1a8d15d9b..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c +++ /dev/null @@ -1,437 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ -#include "dm_services.h" - -#include "dce/dce_11_0_d.h" -#include "dce/dce_11_0_sh_mask.h" -/* TODO: this needs to be looked at, used by Stella's workaround*/ -#include "gmc/gmc_8_2_d.h" -#include "gmc/gmc_8_2_sh_mask.h" - -#include "include/logger_interface.h" - -#include "dce110_mem_input.h" - -#define DCP_REG(reg) (reg + mem_input110->offsets.dcp) -#define DMIF_REG(reg) (reg + mem_input110->offsets.dmif) -#define PIPE_REG(reg) (reg + mem_input110->offsets.pipe) - -static void program_sec_addr( - struct dce110_mem_input *mem_input110, - PHYSICAL_ADDRESS_LOC address) -{ - uint32_t value = 0; - uint32_t temp; - - /*high register MUST be programmed first*/ - temp = address.high_part & - GRPH_SECONDARY_SURFACE_ADDRESS_HIGH__GRPH_SECONDARY_SURFACE_ADDRESS_HIGH_MASK; - set_reg_field_value(value, temp, - GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, - GRPH_SECONDARY_SURFACE_ADDRESS_HIGH); - dm_write_reg(mem_input110->base.ctx, - DCP_REG(mmGRPH_SECONDARY_SURFACE_ADDRESS_HIGH), value); - - value = 0; - temp = address.low_part >> - GRPH_SECONDARY_SURFACE_ADDRESS__GRPH_SECONDARY_SURFACE_ADDRESS__SHIFT; - set_reg_field_value(value, temp, - GRPH_SECONDARY_SURFACE_ADDRESS, - GRPH_SECONDARY_SURFACE_ADDRESS); - dm_write_reg(mem_input110->base.ctx, - DCP_REG(mmGRPH_SECONDARY_SURFACE_ADDRESS), value); -} - -static void program_pri_addr( - struct dce110_mem_input *mem_input110, - PHYSICAL_ADDRESS_LOC address) -{ - uint32_t value = 0; - uint32_t temp; - - /*high register MUST be programmed first*/ - temp = address.high_part & - GRPH_PRIMARY_SURFACE_ADDRESS_HIGH__GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_MASK; - set_reg_field_value(value, temp, - GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, - GRPH_PRIMARY_SURFACE_ADDRESS_HIGH); - dm_write_reg(mem_input110->base.ctx, - DCP_REG(mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH), value); - - value = 0; - temp = address.low_part >> - GRPH_PRIMARY_SURFACE_ADDRESS__GRPH_PRIMARY_SURFACE_ADDRESS__SHIFT; - set_reg_field_value(value, temp, - GRPH_PRIMARY_SURFACE_ADDRESS, - GRPH_PRIMARY_SURFACE_ADDRESS); - dm_write_reg(mem_input110->base.ctx, - DCP_REG(mmGRPH_PRIMARY_SURFACE_ADDRESS), value); -} - -bool dce110_mem_input_is_flip_pending(struct mem_input *mem_input) -{ - struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input); - uint32_t value; - - value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmGRPH_UPDATE)); - - if (get_reg_field_value(value, GRPH_UPDATE, - GRPH_SURFACE_UPDATE_PENDING)) - return true; - - mem_input->current_address = mem_input->request_address; - return false; -} - -bool dce110_mem_input_program_surface_flip_and_addr( - struct mem_input *mem_input, - const struct dc_plane_address *address, - bool flip_immediate) -{ - struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input); - - uint32_t value = 0; - uint32_t value_old = 0; - uint32_t lock_value = 0; - - lock_value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmGRPH_UPDATE)); - set_reg_field_value(lock_value, 1, GRPH_UPDATE, GRPH_UPDATE_LOCK); - dm_write_reg(mem_input110->base.ctx, DCP_REG(mmGRPH_UPDATE), lock_value); - - value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmGRPH_FLIP_CONTROL)); - value_old = value; - if (flip_immediate) { - set_reg_field_value(value, 0, GRPH_FLIP_CONTROL, GRPH_SURFACE_UPDATE_IMMEDIATE_EN); - set_reg_field_value(value, 1, GRPH_FLIP_CONTROL, GRPH_SURFACE_UPDATE_H_RETRACE_EN); - } else { - set_reg_field_value(value, 0, GRPH_FLIP_CONTROL, GRPH_SURFACE_UPDATE_IMMEDIATE_EN); - set_reg_field_value(value, 0, GRPH_FLIP_CONTROL, GRPH_SURFACE_UPDATE_H_RETRACE_EN); - } - if (value != value_old) { - dm_write_reg(mem_input110->base.ctx, DCP_REG(mmGRPH_FLIP_CONTROL), value); - } - - switch (address->type) { - case PLN_ADDR_TYPE_GRAPHICS: - if (address->grph.addr.quad_part == 0) - break; - program_pri_addr(mem_input110, address->grph.addr); - break; - case PLN_ADDR_TYPE_GRPH_STEREO: - if (address->grph_stereo.left_addr.quad_part == 0 - || address->grph_stereo.right_addr.quad_part == 0) - break; - program_pri_addr(mem_input110, address->grph_stereo.left_addr); - program_sec_addr(mem_input110, address->grph_stereo.right_addr); - break; - default: - /* not supported */ - BREAK_TO_DEBUGGER(); - break; - } - - mem_input->request_address = *address; - if (flip_immediate) - mem_input->current_address = *address; - - lock_value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmGRPH_UPDATE)); - set_reg_field_value(lock_value, 0, GRPH_UPDATE, GRPH_UPDATE_LOCK); - dm_write_reg(mem_input110->base.ctx, DCP_REG(mmGRPH_UPDATE), lock_value); - - return true; -} - -static void program_urgency_watermark( - const struct dc_context *ctx, - const uint32_t offset, - struct dce_watermarks marks_low, - uint32_t total_dest_line_time_ns) -{ - /* register value */ - uint32_t urgency_cntl = 0; - uint32_t wm_mask_cntl = 0; - - uint32_t urgency_addr = offset + mmDPG_PIPE_URGENCY_CONTROL; - uint32_t wm_addr = offset + mmDPG_WATERMARK_MASK_CONTROL; - - /*Write mask to enable reading/writing of watermark set A*/ - wm_mask_cntl = dm_read_reg(ctx, wm_addr); - set_reg_field_value(wm_mask_cntl, - 1, - DPG_WATERMARK_MASK_CONTROL, - URGENCY_WATERMARK_MASK); - dm_write_reg(ctx, wm_addr, wm_mask_cntl); - - urgency_cntl = dm_read_reg(ctx, urgency_addr); - - set_reg_field_value( - urgency_cntl, - marks_low.d_mark, - DPG_PIPE_URGENCY_CONTROL, - URGENCY_LOW_WATERMARK); - - set_reg_field_value( - urgency_cntl, - total_dest_line_time_ns, - DPG_PIPE_URGENCY_CONTROL, - URGENCY_HIGH_WATERMARK); - dm_write_reg(ctx, urgency_addr, urgency_cntl); - - /*Write mask to enable reading/writing of watermark set B*/ - wm_mask_cntl = dm_read_reg(ctx, wm_addr); - set_reg_field_value(wm_mask_cntl, - 2, - DPG_WATERMARK_MASK_CONTROL, - URGENCY_WATERMARK_MASK); - dm_write_reg(ctx, wm_addr, wm_mask_cntl); - - urgency_cntl = dm_read_reg(ctx, urgency_addr); - - set_reg_field_value(urgency_cntl, - marks_low.a_mark, - DPG_PIPE_URGENCY_CONTROL, - URGENCY_LOW_WATERMARK); - - set_reg_field_value(urgency_cntl, - total_dest_line_time_ns, - DPG_PIPE_URGENCY_CONTROL, - URGENCY_HIGH_WATERMARK); - dm_write_reg(ctx, urgency_addr, urgency_cntl); -} - -static void program_stutter_watermark( - const struct dc_context *ctx, - const uint32_t offset, - struct dce_watermarks marks) -{ - /* register value */ - uint32_t stutter_cntl = 0; - uint32_t wm_mask_cntl = 0; - - uint32_t stutter_addr = offset + mmDPG_PIPE_STUTTER_CONTROL; - uint32_t wm_addr = offset + mmDPG_WATERMARK_MASK_CONTROL; - - /*Write mask to enable reading/writing of watermark set A*/ - - wm_mask_cntl = dm_read_reg(ctx, wm_addr); - set_reg_field_value(wm_mask_cntl, - 1, - DPG_WATERMARK_MASK_CONTROL, - STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK); - dm_write_reg(ctx, wm_addr, wm_mask_cntl); - - stutter_cntl = dm_read_reg(ctx, stutter_addr); - - if (ctx->dc->debug.disable_stutter) { - set_reg_field_value(stutter_cntl, - 0, - DPG_PIPE_STUTTER_CONTROL, - STUTTER_ENABLE); - } else { - set_reg_field_value(stutter_cntl, - 1, - DPG_PIPE_STUTTER_CONTROL, - STUTTER_ENABLE); - } - - set_reg_field_value(stutter_cntl, - 1, - DPG_PIPE_STUTTER_CONTROL, - STUTTER_IGNORE_FBC); - - /*Write watermark set A*/ - set_reg_field_value(stutter_cntl, - marks.d_mark, - DPG_PIPE_STUTTER_CONTROL, - STUTTER_EXIT_SELF_REFRESH_WATERMARK); - dm_write_reg(ctx, stutter_addr, stutter_cntl); - - /*Write mask to enable reading/writing of watermark set B*/ - wm_mask_cntl = dm_read_reg(ctx, wm_addr); - set_reg_field_value(wm_mask_cntl, - 2, - DPG_WATERMARK_MASK_CONTROL, - STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK); - dm_write_reg(ctx, wm_addr, wm_mask_cntl); - - stutter_cntl = dm_read_reg(ctx, stutter_addr); - - /*Write watermark set B*/ - set_reg_field_value(stutter_cntl, - marks.a_mark, - DPG_PIPE_STUTTER_CONTROL, - STUTTER_EXIT_SELF_REFRESH_WATERMARK); - dm_write_reg(ctx, stutter_addr, stutter_cntl); -} - -static void program_nbp_watermark( - const struct dc_context *ctx, - const uint32_t offset, - struct dce_watermarks marks) -{ - uint32_t value; - uint32_t addr; - /* Write mask to enable reading/writing of watermark set A */ - addr = offset + mmDPG_WATERMARK_MASK_CONTROL; - value = dm_read_reg(ctx, addr); - set_reg_field_value( - value, - 1, - DPG_WATERMARK_MASK_CONTROL, - NB_PSTATE_CHANGE_WATERMARK_MASK); - dm_write_reg(ctx, addr, value); - - addr = offset + mmDPG_PIPE_NB_PSTATE_CHANGE_CONTROL; - value = dm_read_reg(ctx, addr); - set_reg_field_value( - value, - 1, - DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, - NB_PSTATE_CHANGE_ENABLE); - set_reg_field_value( - value, - 1, - DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, - NB_PSTATE_CHANGE_URGENT_DURING_REQUEST); - set_reg_field_value( - value, - 1, - DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, - NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST); - dm_write_reg(ctx, addr, value); - - /* Write watermark set A */ - value = dm_read_reg(ctx, addr); - set_reg_field_value( - value, - marks.d_mark, - DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, - NB_PSTATE_CHANGE_WATERMARK); - dm_write_reg(ctx, addr, value); - - /* Write mask to enable reading/writing of watermark set B */ - addr = offset + mmDPG_WATERMARK_MASK_CONTROL; - value = dm_read_reg(ctx, addr); - set_reg_field_value( - value, - 2, - DPG_WATERMARK_MASK_CONTROL, - NB_PSTATE_CHANGE_WATERMARK_MASK); - dm_write_reg(ctx, addr, value); - - addr = offset + mmDPG_PIPE_NB_PSTATE_CHANGE_CONTROL; - value = dm_read_reg(ctx, addr); - set_reg_field_value( - value, - 1, - DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, - NB_PSTATE_CHANGE_ENABLE); - set_reg_field_value( - value, - 1, - DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, - NB_PSTATE_CHANGE_URGENT_DURING_REQUEST); - set_reg_field_value( - value, - 1, - DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, - NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST); - dm_write_reg(ctx, addr, value); - - /* Write watermark set B */ - value = dm_read_reg(ctx, addr); - set_reg_field_value( - value, - marks.a_mark, - DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, - NB_PSTATE_CHANGE_WATERMARK); - dm_write_reg(ctx, addr, value); -} - -void dce110_mem_input_program_display_marks( - struct mem_input *mem_input, - struct dce_watermarks nbp, - struct dce_watermarks stutter, - struct dce_watermarks urgent, - uint32_t total_dest_line_time_ns) -{ - struct dce110_mem_input *bm_dce110 = TO_DCE110_MEM_INPUT(mem_input); - - program_urgency_watermark( - mem_input->ctx, - bm_dce110->offsets.dmif, - urgent, - total_dest_line_time_ns); - - program_nbp_watermark( - mem_input->ctx, - bm_dce110->offsets.dmif, - nbp); - - program_stutter_watermark( - mem_input->ctx, - bm_dce110->offsets.dmif, - stutter); -} - -static struct mem_input_funcs dce110_mem_input_funcs = { - .mem_input_program_display_marks = - dce110_mem_input_program_display_marks, - .allocate_mem_input = dce_mem_input_allocate_dmif, - .free_mem_input = dce_mem_input_free_dmif, - .mem_input_program_surface_flip_and_addr = - dce110_mem_input_program_surface_flip_and_addr, - .mem_input_program_pte_vm = - dce_mem_input_program_pte_vm, - .mem_input_program_surface_config = - dce_mem_input_program_surface_config, - .mem_input_is_flip_pending = - dce110_mem_input_is_flip_pending, - .mem_input_update_dchub = NULL -}; -/*****************************************/ -/* Constructor, Destructor */ -/*****************************************/ - -bool dce110_mem_input_construct( - struct dce110_mem_input *mem_input110, - struct dc_context *ctx, - uint32_t inst, - const struct dce110_mem_input_reg_offsets *offsets) -{ - /* supported stutter method - * STUTTER_MODE_ENHANCED - * STUTTER_MODE_QUAD_DMIF_BUFFER - * STUTTER_MODE_WATERMARK_NBP_STATE - */ - mem_input110->base.funcs = &dce110_mem_input_funcs; - mem_input110->base.ctx = ctx; - - mem_input110->base.inst = inst; - - mem_input110->offsets = *offsets; - - return true; -} diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.h deleted file mode 100644 index 5f10f266f096..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.h +++ /dev/null @@ -1,121 +0,0 @@ -/* Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DC_MEM_INPUT_DCE110_H__ -#define __DC_MEM_INPUT_DCE110_H__ - -#include "mem_input.h" - -#define TO_DCE110_MEM_INPUT(mi)\ - container_of(mi, struct dce110_mem_input, base) - -struct dce110_mem_input_reg_offsets { - uint32_t dcp; - uint32_t dmif; - uint32_t pipe; -}; - -struct dce110_mem_input { - struct mem_input base; - struct dce110_mem_input_reg_offsets offsets; -}; - -bool dce110_mem_input_construct( - struct dce110_mem_input *mem_input110, - struct dc_context *ctx, - uint32_t inst, - const struct dce110_mem_input_reg_offsets *offsets); - -/* - * dce110_mem_input_program_display_marks - * - * This function will program nbp stutter and urgency watermarks to minimum - * allowable values - */ -void dce110_mem_input_program_display_marks( - struct mem_input *mem_input, - struct dce_watermarks nbp, - struct dce_watermarks stutter, - struct dce_watermarks urgent, - uint32_t total_dest_line_time_ns); - -/* - * dce110_allocate_mem_input - * - * This function will allocate a dmif buffer and program required - * pixel duration for pipe - */ -void dce110_allocate_mem_input( - struct mem_input *mem_input, - uint32_t h_total,/* for current stream */ - uint32_t v_total,/* for current stream */ - uint32_t pix_clk_khz,/* for current stream */ - uint32_t total_stream_num); - -/* - * dce110_free_mem_input - * - * This function will deallocate a dmif buffer from pipe - */ -void dce110_free_mem_input( - struct mem_input *mem_input, - uint32_t total_stream_num); - -/* - * dce110_mem_input_program_surface_flip_and_addr - * - * This function programs hsync/vsync mode and surface address - */ -bool dce110_mem_input_program_surface_flip_and_addr( - struct mem_input *mem_input, - const struct dc_plane_address *address, - bool flip_immediate); - -/* - * dce110_mem_input_program_surface_config - * - * This function will program surface tiling, size, rotation and pixel format - * to corresponding dcp registers. - */ -bool dce110_mem_input_program_surface_config( - struct mem_input *mem_input, - enum surface_pixel_format format, - union dc_tiling_info *tiling_info, - union plane_size *plane_size, - enum dc_rotation_angle rotation, - struct dc_plane_dcc_param *dcc, - bool horizontal_mirror, - bool visible); - -/* - * dce110_mem_input_is_flip_pending - * - * This function will wait until the surface update-pending bit is cleared. - * This is necessary when a flip immediate call is requested as we shouldn't - * return until the flip has actually occurred. - */ -bool dce110_mem_input_is_flip_pending( - struct mem_input *mem_input); - -#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c index 78dd3ae3af5f..9777a4d961d5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c @@ -33,29 +33,17 @@ #include "include/logger_interface.h" #include "inc/dce_calcs.h" -#include "dce110_mem_input.h" - -#define DCP_REG(reg) (reg + mem_input110->offsets.dcp) -/*#define DMIF_REG(reg) (reg + mem_input110->offsets.dmif)*/ -/*#define PIPE_REG(reg) (reg + mem_input110->offsets.pipe)*/ - -static const struct dce110_mem_input_reg_offsets dce110_mi_v_reg_offsets[] = { - { - .dcp = 0, - .dmif = 0, - .pipe = 0, - } -}; +#include "dce/dce_mem_input.h" static void set_flip_control( - struct dce110_mem_input *mem_input110, + struct dce_mem_input *mem_input110, bool immediate) { uint32_t value = 0; value = dm_read_reg( mem_input110->base.ctx, - DCP_REG(mmUNP_FLIP_CONTROL)); + mmUNP_FLIP_CONTROL); set_reg_field_value(value, 1, UNP_FLIP_CONTROL, @@ -63,13 +51,13 @@ static void set_flip_control( dm_write_reg( mem_input110->base.ctx, - DCP_REG(mmUNP_FLIP_CONTROL), + mmUNP_FLIP_CONTROL, value); } /* chroma part */ static void program_pri_addr_c( - struct dce110_mem_input *mem_input110, + struct dce_mem_input *mem_input110, PHYSICAL_ADDRESS_LOC address) { uint32_t value = 0; @@ -84,7 +72,7 @@ UNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C__GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C_MAS dm_write_reg( mem_input110->base.ctx, - DCP_REG(mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C), + mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C, value); temp = 0; @@ -98,13 +86,13 @@ UNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C__GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C_MAS dm_write_reg( mem_input110->base.ctx, - DCP_REG(mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_C), + mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_C, value); } /* luma part */ static void program_pri_addr_l( - struct dce110_mem_input *mem_input110, + struct dce_mem_input *mem_input110, PHYSICAL_ADDRESS_LOC address) { uint32_t value = 0; @@ -120,7 +108,7 @@ UNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L__GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L_MAS dm_write_reg( mem_input110->base.ctx, - DCP_REG(mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L), + mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L, value); temp = 0; @@ -134,12 +122,12 @@ UNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L__GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L_MAS dm_write_reg( mem_input110->base.ctx, - DCP_REG(mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_L), + mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_L, value); } static void program_addr( - struct dce110_mem_input *mem_input110, + struct dce_mem_input *mem_input110, const struct dc_plane_address *addr) { switch (addr->type) { @@ -162,19 +150,19 @@ static void program_addr( } } -static void enable(struct dce110_mem_input *mem_input110) +static void enable(struct dce_mem_input *mem_input110) { uint32_t value = 0; - value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmUNP_GRPH_ENABLE)); + value = dm_read_reg(mem_input110->base.ctx, mmUNP_GRPH_ENABLE); set_reg_field_value(value, 1, UNP_GRPH_ENABLE, GRPH_ENABLE); dm_write_reg(mem_input110->base.ctx, - DCP_REG(mmUNP_GRPH_ENABLE), + mmUNP_GRPH_ENABLE, value); } static void program_tiling( - struct dce110_mem_input *mem_input110, + struct dce_mem_input *mem_input110, const union dc_tiling_info *info, const enum surface_pixel_format pixel_format) { @@ -239,7 +227,7 @@ static void program_tiling( } static void program_size_and_rotation( - struct dce110_mem_input *mem_input110, + struct dce_mem_input *mem_input110, enum dc_rotation_angle rotation, const union plane_size *plane_size) { @@ -277,7 +265,7 @@ static void program_size_and_rotation( dm_write_reg( mem_input110->base.ctx, - DCP_REG(mmUNP_GRPH_PITCH_L), + mmUNP_GRPH_PITCH_L, value); value = 0; @@ -285,7 +273,7 @@ static void program_size_and_rotation( UNP_GRPH_PITCH_C, GRPH_PITCH_C); dm_write_reg( mem_input110->base.ctx, - DCP_REG(mmUNP_GRPH_PITCH_C), + mmUNP_GRPH_PITCH_C, value); value = 0; @@ -293,7 +281,7 @@ static void program_size_and_rotation( UNP_GRPH_X_START_L, GRPH_X_START_L); dm_write_reg( mem_input110->base.ctx, - DCP_REG(mmUNP_GRPH_X_START_L), + mmUNP_GRPH_X_START_L, value); value = 0; @@ -301,7 +289,7 @@ static void program_size_and_rotation( UNP_GRPH_X_START_C, GRPH_X_START_C); dm_write_reg( mem_input110->base.ctx, - DCP_REG(mmUNP_GRPH_X_START_C), + mmUNP_GRPH_X_START_C, value); value = 0; @@ -309,7 +297,7 @@ static void program_size_and_rotation( UNP_GRPH_Y_START_L, GRPH_Y_START_L); dm_write_reg( mem_input110->base.ctx, - DCP_REG(mmUNP_GRPH_Y_START_L), + mmUNP_GRPH_Y_START_L, value); value = 0; @@ -317,7 +305,7 @@ static void program_size_and_rotation( UNP_GRPH_Y_START_C, GRPH_Y_START_C); dm_write_reg( mem_input110->base.ctx, - DCP_REG(mmUNP_GRPH_Y_START_C), + mmUNP_GRPH_Y_START_C, value); value = 0; @@ -326,7 +314,7 @@ static void program_size_and_rotation( UNP_GRPH_X_END_L, GRPH_X_END_L); dm_write_reg( mem_input110->base.ctx, - DCP_REG(mmUNP_GRPH_X_END_L), + mmUNP_GRPH_X_END_L, value); value = 0; @@ -335,7 +323,7 @@ static void program_size_and_rotation( UNP_GRPH_X_END_C, GRPH_X_END_C); dm_write_reg( mem_input110->base.ctx, - DCP_REG(mmUNP_GRPH_X_END_C), + mmUNP_GRPH_X_END_C, value); value = 0; @@ -344,7 +332,7 @@ static void program_size_and_rotation( UNP_GRPH_Y_END_L, GRPH_Y_END_L); dm_write_reg( mem_input110->base.ctx, - DCP_REG(mmUNP_GRPH_Y_END_L), + mmUNP_GRPH_Y_END_L, value); value = 0; @@ -353,7 +341,7 @@ static void program_size_and_rotation( UNP_GRPH_Y_END_C, GRPH_Y_END_C); dm_write_reg( mem_input110->base.ctx, - DCP_REG(mmUNP_GRPH_Y_END_C), + mmUNP_GRPH_Y_END_C, value); value = 0; @@ -378,12 +366,12 @@ static void program_size_and_rotation( dm_write_reg( mem_input110->base.ctx, - DCP_REG(mmUNP_HW_ROTATION), + mmUNP_HW_ROTATION, value); } static void program_pixel_format( - struct dce110_mem_input *mem_input110, + struct dce_mem_input *mem_input110, enum surface_pixel_format format) { if (format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) { @@ -393,7 +381,7 @@ static void program_pixel_format( value = dm_read_reg( mem_input110->base.ctx, - DCP_REG(mmUNP_GRPH_CONTROL)); + mmUNP_GRPH_CONTROL); switch (format) { case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS: @@ -440,12 +428,12 @@ static void program_pixel_format( dm_write_reg( mem_input110->base.ctx, - DCP_REG(mmUNP_GRPH_CONTROL), + mmUNP_GRPH_CONTROL, value); value = dm_read_reg( mem_input110->base.ctx, - DCP_REG(mmUNP_GRPH_CONTROL_EXP)); + mmUNP_GRPH_CONTROL_EXP); /* VIDEO FORMAT 0 */ set_reg_field_value( @@ -455,7 +443,7 @@ static void program_pixel_format( VIDEO_FORMAT); dm_write_reg( mem_input110->base.ctx, - DCP_REG(mmUNP_GRPH_CONTROL_EXP), + mmUNP_GRPH_CONTROL_EXP, value); } else { @@ -465,7 +453,7 @@ static void program_pixel_format( value = dm_read_reg( mem_input110->base.ctx, - DCP_REG(mmUNP_GRPH_CONTROL_EXP)); + mmUNP_GRPH_CONTROL_EXP); switch (format) { case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: @@ -487,17 +475,17 @@ static void program_pixel_format( dm_write_reg( mem_input110->base.ctx, - DCP_REG(mmUNP_GRPH_CONTROL_EXP), + mmUNP_GRPH_CONTROL_EXP, value); } } -bool dce110_mem_input_v_is_surface_pending(struct mem_input *mem_input) +bool dce_mem_input_v_is_surface_pending(struct mem_input *mem_input) { - struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input); + struct dce_mem_input *mem_input110 = TO_DCE_MEM_INPUT(mem_input); uint32_t value; - value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmUNP_GRPH_UPDATE)); + value = dm_read_reg(mem_input110->base.ctx, mmUNP_GRPH_UPDATE); if (get_reg_field_value(value, UNP_GRPH_UPDATE, GRPH_SURFACE_UPDATE_PENDING)) @@ -507,12 +495,12 @@ bool dce110_mem_input_v_is_surface_pending(struct mem_input *mem_input) return false; } -bool dce110_mem_input_v_program_surface_flip_and_addr( +bool dce_mem_input_v_program_surface_flip_and_addr( struct mem_input *mem_input, const struct dc_plane_address *address, bool flip_immediate) { - struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input); + struct dce_mem_input *mem_input110 = TO_DCE_MEM_INPUT(mem_input); set_flip_control(mem_input110, flip_immediate); program_addr(mem_input110, @@ -584,13 +572,13 @@ static const unsigned int *get_dvmm_hw_setting( } } -void dce110_mem_input_v_program_pte_vm( +void dce_mem_input_v_program_pte_vm( struct mem_input *mem_input, enum surface_pixel_format format, union dc_tiling_info *tiling_info, enum dc_rotation_angle rotation) { - struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input); + struct dce_mem_input *mem_input110 = TO_DCE_MEM_INPUT(mem_input); const unsigned int *pte = get_dvmm_hw_setting(tiling_info, format, false); const unsigned int *pte_chroma = get_dvmm_hw_setting(tiling_info, format, true); @@ -628,36 +616,36 @@ void dce110_mem_input_v_program_pte_vm( break; } - value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmUNP_PIPE_OUTSTANDING_REQUEST_LIMIT)); + value = dm_read_reg(mem_input110->base.ctx, mmUNP_PIPE_OUTSTANDING_REQUEST_LIMIT); /* TODO: un-hardcode requestlimit */ set_reg_field_value(value, 0xff, UNP_PIPE_OUTSTANDING_REQUEST_LIMIT, UNP_PIPE_OUTSTANDING_REQUEST_LIMIT_L); set_reg_field_value(value, 0xff, UNP_PIPE_OUTSTANDING_REQUEST_LIMIT, UNP_PIPE_OUTSTANDING_REQUEST_LIMIT_C); - dm_write_reg(mem_input110->base.ctx, DCP_REG(mmUNP_PIPE_OUTSTANDING_REQUEST_LIMIT), value); + dm_write_reg(mem_input110->base.ctx, mmUNP_PIPE_OUTSTANDING_REQUEST_LIMIT, value); - value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmUNP_DVMM_PTE_CONTROL)); + value = dm_read_reg(mem_input110->base.ctx, mmUNP_DVMM_PTE_CONTROL); set_reg_field_value(value, page_width, UNP_DVMM_PTE_CONTROL, DVMM_PAGE_WIDTH); set_reg_field_value(value, page_height, UNP_DVMM_PTE_CONTROL, DVMM_PAGE_HEIGHT); set_reg_field_value(value, min_pte_before_flip, UNP_DVMM_PTE_CONTROL, DVMM_MIN_PTE_BEFORE_FLIP); - dm_write_reg(mem_input110->base.ctx, DCP_REG(mmUNP_DVMM_PTE_CONTROL), value); + dm_write_reg(mem_input110->base.ctx, mmUNP_DVMM_PTE_CONTROL, value); - value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmUNP_DVMM_PTE_ARB_CONTROL)); + value = dm_read_reg(mem_input110->base.ctx, mmUNP_DVMM_PTE_ARB_CONTROL); set_reg_field_value(value, pte[5], UNP_DVMM_PTE_ARB_CONTROL, DVMM_PTE_REQ_PER_CHUNK); set_reg_field_value(value, 0xff, UNP_DVMM_PTE_ARB_CONTROL, DVMM_MAX_PTE_REQ_OUTSTANDING); - dm_write_reg(mem_input110->base.ctx, DCP_REG(mmUNP_DVMM_PTE_ARB_CONTROL), value); + dm_write_reg(mem_input110->base.ctx, mmUNP_DVMM_PTE_ARB_CONTROL, value); - value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmUNP_DVMM_PTE_CONTROL_C)); + value = dm_read_reg(mem_input110->base.ctx, mmUNP_DVMM_PTE_CONTROL_C); set_reg_field_value(value, page_width_chroma, UNP_DVMM_PTE_CONTROL_C, DVMM_PAGE_WIDTH_C); set_reg_field_value(value, page_height_chroma, UNP_DVMM_PTE_CONTROL_C, DVMM_PAGE_HEIGHT_C); set_reg_field_value(value, min_pte_before_flip_chroma, UNP_DVMM_PTE_CONTROL_C, DVMM_MIN_PTE_BEFORE_FLIP_C); - dm_write_reg(mem_input110->base.ctx, DCP_REG(mmUNP_DVMM_PTE_CONTROL_C), value); + dm_write_reg(mem_input110->base.ctx, mmUNP_DVMM_PTE_CONTROL_C, value); - value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmUNP_DVMM_PTE_ARB_CONTROL_C)); + value = dm_read_reg(mem_input110->base.ctx, mmUNP_DVMM_PTE_ARB_CONTROL_C); set_reg_field_value(value, pte_chroma[5], UNP_DVMM_PTE_ARB_CONTROL_C, DVMM_PTE_REQ_PER_CHUNK_C); set_reg_field_value(value, 0xff, UNP_DVMM_PTE_ARB_CONTROL_C, DVMM_MAX_PTE_REQ_OUTSTANDING_C); - dm_write_reg(mem_input110->base.ctx, DCP_REG(mmUNP_DVMM_PTE_ARB_CONTROL_C), value); + dm_write_reg(mem_input110->base.ctx, mmUNP_DVMM_PTE_ARB_CONTROL_C, value); } -void dce110_mem_input_v_program_surface_config( +void dce_mem_input_v_program_surface_config( struct mem_input *mem_input, enum surface_pixel_format format, union dc_tiling_info *tiling_info, @@ -666,7 +654,7 @@ void dce110_mem_input_v_program_surface_config( struct dc_plane_dcc_param *dcc, bool horizotal_mirror) { - struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input); + struct dce_mem_input *mem_input110 = TO_DCE_MEM_INPUT(mem_input); enable(mem_input110); program_tiling(mem_input110, tiling_info, format); @@ -943,7 +931,7 @@ static void program_nbp_watermark_c( marks); } -void dce110_mem_input_v_program_display_marks( +void dce_mem_input_v_program_display_marks( struct mem_input *mem_input, struct dce_watermarks nbp, struct dce_watermarks stutter, @@ -965,7 +953,7 @@ void dce110_mem_input_v_program_display_marks( } -void dce110_mem_input_program_chroma_display_marks( +void dce_mem_input_program_chroma_display_marks( struct mem_input *mem_input, struct dce_watermarks nbp, struct dce_watermarks stutter, @@ -1036,42 +1024,29 @@ void dce110_free_mem_input_v( static struct mem_input_funcs dce110_mem_input_v_funcs = { .mem_input_program_display_marks = - dce110_mem_input_v_program_display_marks, + dce_mem_input_v_program_display_marks, .mem_input_program_chroma_display_marks = - dce110_mem_input_program_chroma_display_marks, + dce_mem_input_program_chroma_display_marks, .allocate_mem_input = dce110_allocate_mem_input_v, .free_mem_input = dce110_free_mem_input_v, .mem_input_program_surface_flip_and_addr = - dce110_mem_input_v_program_surface_flip_and_addr, + dce_mem_input_v_program_surface_flip_and_addr, .mem_input_program_pte_vm = - dce110_mem_input_v_program_pte_vm, + dce_mem_input_v_program_pte_vm, .mem_input_program_surface_config = - dce110_mem_input_v_program_surface_config, + dce_mem_input_v_program_surface_config, .mem_input_is_flip_pending = - dce110_mem_input_v_is_surface_pending + dce_mem_input_v_is_surface_pending }; /*****************************************/ /* Constructor, Destructor */ /*****************************************/ -bool dce110_mem_input_v_construct( - struct dce110_mem_input *mem_input110, +void dce110_mem_input_v_construct( + struct dce_mem_input *dce_mi, struct dc_context *ctx) { - mem_input110->base.funcs = &dce110_mem_input_v_funcs; - mem_input110->base.ctx = ctx; - - mem_input110->base.inst = 0; - - mem_input110->offsets = dce110_mi_v_reg_offsets[0]; - - return true; + dce_mi->base.funcs = &dce110_mem_input_v_funcs; + dce_mi->base.ctx = ctx; } -#if 0 -void dce110_mem_input_v_destroy(struct mem_input **mem_input) -{ - dm_free(TO_DCE110_MEM_INPUT(*mem_input)); - *mem_input = NULL; -} -#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.h index b2667eefa3d0..f01d4a607fea 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.h @@ -26,70 +26,10 @@ #define __DC_MEM_INPUT_V_DCE110_H__ #include "mem_input.h" -#include "dce110_mem_input.h" +#include "dce/dce_mem_input.h" -bool dce110_mem_input_v_construct( - struct dce110_mem_input *mem_input110, +void dce110_mem_input_v_construct( + struct dce_mem_input *dce_mi, struct dc_context *ctx); -/* - * This function will program nbp stutter and urgency watermarks to minimum - * allowable values - */ -void dce110_mem_input_v_program_display_marks( - struct mem_input *mem_input, - struct dce_watermarks nbp, - struct dce_watermarks stutter, - struct dce_watermarks urgent, - uint32_t total_dest_line_time_ns); - -/* - * This function will allocate a dmif buffer and program required - * pixel duration for pipe - */ -void dce110_allocate_mem_v_input( - struct mem_input *mem_input, - uint32_t h_total,/* for current stream */ - uint32_t v_total,/* for current stream */ - uint32_t pix_clk_khz,/* for current stream */ - uint32_t total_stream_num); - -/* - * This function will deallocate a dmif buffer from pipe - */ -void dce110_free_mem_v_input( - struct mem_input *mem_input, - uint32_t total_stream_num); - -/* - * This function programs hsync/vsync mode and surface address - */ -bool dce110_mem_input_v_program_surface_flip_and_addr( - struct mem_input *mem_input, - const struct dc_plane_address *address, - bool flip_immediate); - -/* - * dce110_mem_input_v_program_scatter_gather - * - * This function will program scatter gather registers. - */ -bool dce110_mem_input_v_program_pte_vm( - struct mem_input *mem_input, - enum surface_pixel_format format, - union dc_tiling_info *tiling_info, - enum dc_rotation_angle rotation); - -/* - * This function will program surface tiling, size, rotation and pixel format - * to corresponding dcp registers. - */ -bool dce110_mem_input_v_program_surface_config( - struct mem_input *mem_input, - enum surface_pixel_format format, - union dc_tiling_info *tiling_info, - union plane_size *plane_size, - enum dc_rotation_angle rotation, - bool visible); - #endif diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 041d11968566..3ed5b9445535 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -38,7 +38,7 @@ #include "dce110/dce110_timing_generator_v.h" #include "dce/dce_link_encoder.h" #include "dce/dce_stream_encoder.h" -#include "dce110/dce110_mem_input.h" +#include "dce/dce_mem_input.h" #include "dce110/dce110_mem_input_v.h" #include "dce/dce_ipp.h" #include "dce/dce_transform.h" @@ -133,30 +133,6 @@ static const struct dce110_timing_generator_offsets dce110_tg_offsets[] = { } }; -static const struct dce110_mem_input_reg_offsets dce110_mi_reg_offsets[] = { - { - .dcp = (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE0_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - }, - { - .dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG1_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE1_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - }, - { - .dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG2_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE2_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - } -}; - /* set register offset */ #define SR(reg_name)\ .reg_name = mm ## reg_name @@ -520,30 +496,21 @@ static const struct dce_mem_input_mask mi_masks = { .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE_MASK }; + static struct mem_input *dce110_mem_input_create( struct dc_context *ctx, - uint32_t inst, - const struct dce110_mem_input_reg_offsets *offset) + uint32_t inst) { - struct dce110_mem_input *mem_input110 = - dm_alloc(sizeof(struct dce110_mem_input)); + struct dce_mem_input *dce_mi = dm_alloc(sizeof(struct dce_mem_input)); - if (!mem_input110) + if (!dce_mi) { + BREAK_TO_DEBUGGER(); return NULL; - - if (dce110_mem_input_construct(mem_input110, ctx, inst, offset)) { - struct mem_input *mi = &mem_input110->base; - - mi->regs = &mi_regs[inst]; - mi->shifts = &mi_shifts; - mi->masks = &mi_masks; - mi->wa.single_head_rdreq_dmif_limit = 3; - return mi; } - BREAK_TO_DEBUGGER(); - dm_free(mem_input110); - return NULL; + dce_mem_input_construct(dce_mi, ctx, inst, &mi_regs[inst], &mi_shifts, &mi_masks); + dce_mi->wa.single_head_rdreq_dmif_limit = 3; + return &dce_mi->base; } static void dce110_transform_destroy(struct transform **xfm) @@ -698,7 +665,7 @@ static void destruct(struct dce110_resource_pool *pool) dce_ipp_destroy(&pool->base.ipps[i]); if (pool->base.mis[i] != NULL) { - dm_free(TO_DCE110_MEM_INPUT(pool->base.mis[i])); + dm_free(TO_DCE_MEM_INPUT(pool->base.mis[i])); pool->base.mis[i] = NULL; } @@ -1132,7 +1099,7 @@ static bool underlay_create(struct dc_context *ctx, struct resource_pool *pool) { struct dce110_timing_generator *dce110_tgv = dm_alloc(sizeof (*dce110_tgv)); struct dce_transform *dce110_xfmv = dm_alloc(sizeof (*dce110_xfmv)); - struct dce110_mem_input *dce110_miv = dm_alloc(sizeof (*dce110_miv)); + struct dce_mem_input *dce110_miv = dm_alloc(sizeof (*dce110_miv)); struct dce110_opp *dce110_oppv = dm_alloc(sizeof (*dce110_oppv)); if ((dce110_tgv == NULL) || @@ -1345,8 +1312,7 @@ static bool construct( goto res_create_fail; } - pool->base.mis[i] = dce110_mem_input_create(ctx, i, - &dce110_mi_reg_offsets[i]); + pool->base.mis[i] = dce110_mem_input_create(ctx, i); if (pool->base.mis[i] == NULL) { BREAK_TO_DEBUGGER(); dm_error( diff --git a/drivers/gpu/drm/amd/display/dc/dce112/Makefile b/drivers/gpu/drm/amd/display/dc/dce112/Makefile index 2d536fbc60c4..265ac4310d85 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dce112/Makefile @@ -3,7 +3,7 @@ # It provides the control and status of HW CRTC block. DCE112 = dce112_compressor.o dce112_hw_sequencer.o \ -dce112_resource.o dce112_mem_input.o +dce112_resource.o AMD_DAL_DCE112 = $(addprefix $(AMDDALPATH)/dc/dce112/,$(DCE112)) diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_mem_input.c deleted file mode 100644 index c29007dafe21..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_mem_input.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ -#include "dm_services.h" -#include "dce112_mem_input.h" - - -#include "dce/dce_11_2_d.h" -#include "dce/dce_11_2_sh_mask.h" - - -#define DCP_REG(reg) (reg + mem_input110->offsets.dcp) -#define DMIF_REG(reg) (reg + mem_input110->offsets.dmif) -#define PIPE_REG(reg) (reg + mem_input110->offsets.pipe) - -/*****************************************/ -/* Constructor, Destructor */ -/*****************************************/ - -bool dce112_mem_input_construct( - struct dce110_mem_input *mem_input110, - struct dc_context *ctx, - uint32_t inst, - const struct dce110_mem_input_reg_offsets *offsets) -{ - if (!dce110_mem_input_construct(mem_input110, ctx, inst, offsets)) - return false; - - mem_input110->base.funcs->mem_input_program_display_marks = - dce_mem_input_program_display_marks; - - return true; -} diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce112/dce112_mem_input.h deleted file mode 100644 index de2aaf0f9a8e..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_mem_input.h +++ /dev/null @@ -1,38 +0,0 @@ -/* Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DC_MEM_INPUT_DCE112_H__ -#define __DC_MEM_INPUT_DCE112_H__ - -#include "mem_input.h" -#include "dce110/dce110_mem_input.h" - -bool dce112_mem_input_construct( - struct dce110_mem_input *mem_input110, - struct dc_context *ctx, - uint32_t inst, - const struct dce110_mem_input_reg_offsets *offsets); - - -#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 0ed2616dd5cd..f405d6eecaa5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -32,9 +32,10 @@ #include "include/irq_service_interface.h" #include "dce110/dce110_resource.h" #include "dce110/dce110_timing_generator.h" -#include "dce112/dce112_mem_input.h" #include "irq/dce110/irq_service_dce110.h" + +#include "dce/dce_mem_input.h" #include "dce/dce_transform.h" #include "dce/dce_link_encoder.h" #include "dce/dce_stream_encoder.h" @@ -132,51 +133,6 @@ static const struct dce110_timing_generator_offsets dce112_tg_offsets[] = { } }; -static const struct dce110_mem_input_reg_offsets dce112_mi_reg_offsets[] = { - { - .dcp = (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE0_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - }, - { - .dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG1_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE1_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - }, - { - .dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG2_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE2_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - }, - { - .dcp = (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG3_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE3_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - }, - { - .dcp = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG4_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE4_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - }, - { - .dcp = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG5_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE5_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - } -}; - /* set register offset */ #define SR(reg_name)\ .reg_name = mm ## reg_name @@ -541,27 +497,17 @@ static const struct dce_mem_input_mask mi_masks = { static struct mem_input *dce112_mem_input_create( struct dc_context *ctx, - uint32_t inst, - const struct dce110_mem_input_reg_offsets *offset) + uint32_t inst) { - struct dce110_mem_input *mem_input110 = - dm_alloc(sizeof(struct dce110_mem_input)); + struct dce_mem_input *dce_mi = dm_alloc(sizeof(struct dce_mem_input)); - if (!mem_input110) + if (!dce_mi) { + BREAK_TO_DEBUGGER(); return NULL; - - if (dce112_mem_input_construct(mem_input110, ctx, inst, offset)) { - struct mem_input *mi = &mem_input110->base; - - mi->regs = &mi_regs[inst]; - mi->shifts = &mi_shifts; - mi->masks = &mi_masks; - return mi; } - BREAK_TO_DEBUGGER(); - dm_free(mem_input110); - return NULL; + dce112_mem_input_construct(dce_mi, ctx, inst, &mi_regs[inst], &mi_shifts, &mi_masks); + return &dce_mi->base; } static void dce112_transform_destroy(struct transform **xfm) @@ -705,7 +651,7 @@ static void destruct(struct dce110_resource_pool *pool) dce_ipp_destroy(&pool->base.ipps[i]); if (pool->base.mis[i] != NULL) { - dm_free(TO_DCE110_MEM_INPUT(pool->base.mis[i])); + dm_free(TO_DCE_MEM_INPUT(pool->base.mis[i])); pool->base.mis[i] = NULL; } @@ -1347,10 +1293,7 @@ static bool construct( goto res_create_fail; } - pool->base.mis[i] = dce112_mem_input_create( - ctx, - i, - &dce112_mi_reg_offsets[i]); + pool->base.mis[i] = dce112_mem_input_create(ctx, i); if (pool->base.mis[i] == NULL) { BREAK_TO_DEBUGGER(); dm_error( diff --git a/drivers/gpu/drm/amd/display/dc/dce120/Makefile b/drivers/gpu/drm/amd/display/dc/dce120/Makefile index 826c12ee368c..1779b963525c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dce120/Makefile @@ -4,7 +4,7 @@ DCE120 = dce120_resource.o dce120_timing_generator.o \ -dce120_mem_input.o dce120_hw_sequencer.o +dce120_hw_sequencer.o AMD_DAL_DCE120 = $(addprefix $(AMDDALPATH)/dc/dce120/,$(DCE120)) diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_mem_input.c deleted file mode 100644 index c0677211bd93..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_mem_input.c +++ /dev/null @@ -1,340 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ -#include "dm_services.h" -#include "dce120_mem_input.h" - - -#include "vega10/DC/dce_12_0_offset.h" -#include "vega10/DC/dce_12_0_sh_mask.h" -#include "vega10/soc15ip.h" - -#define GENERAL_REG_UPDATE_N(reg_name, n, ...) \ - generic_reg_update_soc15(mem_input110->base.ctx, 0, reg_name, n, __VA_ARGS__) - -#define GENERAL_REG_UPDATE(reg, field, val) \ - GENERAL_REG_UPDATE_N(reg, 1, FD(reg##__##field), val) - -#define GENERAL_REG_UPDATE_2(reg, field1, val1, field2, val2) \ - GENERAL_REG_UPDATE_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) - - - -#define DCP_REG_UPDATE_N(reg_name, n, ...) \ - generic_reg_update_soc15(mem_input110->base.ctx, mem_input110->offsets.dcp, reg_name, n, __VA_ARGS__) - -#define DCP_REG_SET_N(reg_name, n, ...) \ - generic_reg_set_soc15(mem_input110->base.ctx, mem_input110->offsets.dcp, reg_name, n, __VA_ARGS__) - -#define DCP_REG_UPDATE(reg, field, val) \ - DCP_REG_UPDATE_N(reg, 1, FD(reg##__##field), val) - -#define DCP_REG_UPDATE_2(reg, field1, val1, field2, val2) \ - DCP_REG_UPDATE_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) - -#define DCP_REG_UPDATE_3(reg, field1, val1, field2, val2, field3, val3) \ - DCP_REG_UPDATE_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3) - -#define DCP_REG_SET(reg, field, val) \ - DCP_REG_SET_N(reg, 1, FD(reg##__##field), val) - -#define DCP_REG_SET_2(reg, field1, val1, field2, val2) \ - DCP_REG_SET_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) - -#define DCP_REG_SET_3(reg, field1, val1, field2, val2, field3, val3) \ - DCP_REG_SET_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3) - - - -#define DMIF_REG_UPDATE_N(reg_name, n, ...) \ - generic_reg_update_soc15(mem_input110->base.ctx, mem_input110->offsets.dmif, reg_name, n, __VA_ARGS__) - -#define DMIF_REG_SET_N(reg_name, n, ...) \ - generic_reg_set_soc15(mem_input110->base.ctx, mem_input110->offsets.dmif, reg_name, n, __VA_ARGS__) - -#define DMIF_REG_UPDATE(reg, field, val) \ - DMIF_REG_UPDATE_N(reg, 1, FD(reg##__##field), val) - -#define DMIF_REG_UPDATE_2(reg, field1, val1, field2, val2) \ - DMIF_REG_UPDATE_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) - -#define DMIF_REG_UPDATE_3(reg, field1, val1, field2, val2, field3, val3) \ - DMIF_REG_UPDATE_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3) - -#define DMIF_REG_SET(reg, field, val) \ - DMIF_REG_SET_N(reg, 1, FD(reg##__##field), val) - -#define DMIF_REG_SET_2(reg, field1, val1, field2, val2) \ - DMIF_REG_SET_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) - -#define DMIF_REG_SET_3(reg, field1, val1, field2, val2, field3, val3) \ - DMIF_REG_SET_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3) - - - -#define PIPE_REG_UPDATE_N(reg_name, n, ...) \ - generic_reg_update_soc15(mem_input110->base.ctx, mem_input110->offsets.pipe, reg_name, n, __VA_ARGS__) - -#define PIPE_REG_SET_N(reg_name, n, ...) \ - generic_reg_set_soc15(mem_input110->base.ctx, mem_input110->offsets.pipe, reg_name, n, __VA_ARGS__) - -#define PIPE_REG_UPDATE(reg, field, val) \ - PIPE_REG_UPDATE_N(reg, 1, FD(reg##__##field), val) - -#define PIPE_REG_UPDATE_2(reg, field1, val1, field2, val2) \ - PIPE_REG_UPDATE_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) - -#define PIPE_REG_UPDATE_3(reg, field1, val1, field2, val2, field3, val3) \ - PIPE_REG_UPDATE_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3) - -#define PIPE_REG_SET(reg, field, val) \ - PIPE_REG_SET_N(reg, 1, FD(reg##__##field), val) - -#define PIPE_REG_SET_2(reg, field1, val1, field2, val2) \ - PIPE_REG_SET_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) - -#define PIPE_REG_SET_3(reg, field1, val1, field2, val2, field3, val3) \ - PIPE_REG_SET_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3) - - - -static void program_sec_addr( - struct dce110_mem_input *mem_input110, - PHYSICAL_ADDRESS_LOC address) -{ - uint32_t temp; - - /*high register MUST be programmed first*/ - temp = address.high_part & - DCP0_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH__GRPH_SECONDARY_SURFACE_ADDRESS_HIGH_MASK; - - DCP_REG_SET( - DCP0_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, - GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, - temp); - - temp = address.low_part >> - DCP0_GRPH_SECONDARY_SURFACE_ADDRESS__GRPH_SECONDARY_SURFACE_ADDRESS__SHIFT; - - DCP_REG_SET_2( - DCP0_GRPH_SECONDARY_SURFACE_ADDRESS, - GRPH_SECONDARY_SURFACE_ADDRESS, temp, - GRPH_SECONDARY_DFQ_ENABLE, 0); -} - -static void program_pri_addr( - struct dce110_mem_input *mem_input110, - PHYSICAL_ADDRESS_LOC address) -{ - uint32_t temp; - - /*high register MUST be programmed first*/ - temp = address.high_part & - DCP0_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH__GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_MASK; - - DCP_REG_SET( - DCP0_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, - GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, - temp); - - temp = address.low_part >> - DCP0_GRPH_PRIMARY_SURFACE_ADDRESS__GRPH_PRIMARY_SURFACE_ADDRESS__SHIFT; - - DCP_REG_SET( - DCP0_GRPH_PRIMARY_SURFACE_ADDRESS, - GRPH_PRIMARY_SURFACE_ADDRESS, - temp); -} - - -static bool mem_input_is_flip_pending(struct mem_input *mem_input) -{ - struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input); - uint32_t value; - - value = dm_read_reg_soc15(mem_input110->base.ctx, - mmDCP0_GRPH_UPDATE, mem_input110->offsets.dcp); - - if (get_reg_field_value(value, DCP0_GRPH_UPDATE, - GRPH_SURFACE_UPDATE_PENDING)) - return true; - - mem_input->current_address = mem_input->request_address; - return false; -} - -static bool mem_input_program_surface_flip_and_addr( - struct mem_input *mem_input, - const struct dc_plane_address *address, - bool flip_immediate) -{ - struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input); - - /* TODO: Figure out if two modes are needed: - * non-XDMA Mode: GRPH_SURFACE_UPDATE_IMMEDIATE_EN = 1 - * XDMA Mode: GRPH_SURFACE_UPDATE_H_RETRACE_EN = 1 - */ - DCP_REG_UPDATE(DCP0_GRPH_UPDATE, - GRPH_UPDATE_LOCK, 1); - - if (flip_immediate) { - DCP_REG_UPDATE_2( - DCP0_GRPH_FLIP_CONTROL, - GRPH_SURFACE_UPDATE_IMMEDIATE_EN, 0, - GRPH_SURFACE_UPDATE_H_RETRACE_EN, 1); - } else { - DCP_REG_UPDATE_2( - DCP0_GRPH_FLIP_CONTROL, - GRPH_SURFACE_UPDATE_IMMEDIATE_EN, 0, - GRPH_SURFACE_UPDATE_H_RETRACE_EN, 0); - } - - switch (address->type) { - case PLN_ADDR_TYPE_GRAPHICS: - if (address->grph.addr.quad_part == 0) - break; - program_pri_addr(mem_input110, address->grph.addr); - break; - case PLN_ADDR_TYPE_GRPH_STEREO: - if (address->grph_stereo.left_addr.quad_part == 0 - || address->grph_stereo.right_addr.quad_part == 0) - break; - program_pri_addr(mem_input110, address->grph_stereo.left_addr); - program_sec_addr(mem_input110, address->grph_stereo.right_addr); - break; - default: - /* not supported */ - BREAK_TO_DEBUGGER(); - break; - } - - mem_input->request_address = *address; - - if (flip_immediate) - mem_input->current_address = *address; - - DCP_REG_UPDATE(DCP0_GRPH_UPDATE, - GRPH_UPDATE_LOCK, 0); - - return true; -} - -static void mem_input_update_dchub(struct mem_input *mi, - struct dchub_init_data *dh_data) -{ - struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mi); - /* TODO: port code from dal2 */ - switch (dh_data->fb_mode) { - case FRAME_BUFFER_MODE_ZFB_ONLY: - /*For ZFB case need to put DCHUB FB BASE and TOP upside down to indicate ZFB mode*/ - GENERAL_REG_UPDATE_2( - DCHUB_FB_LOCATION, - FB_TOP, 0, - FB_BASE, 0x0FFFF); - - GENERAL_REG_UPDATE( - DCHUB_AGP_BASE, - AGP_BASE, dh_data->zfb_phys_addr_base >> 22); - - GENERAL_REG_UPDATE( - DCHUB_AGP_BOT, - AGP_BOT, dh_data->zfb_mc_base_addr >> 22); - - GENERAL_REG_UPDATE( - DCHUB_AGP_TOP, - AGP_TOP, (dh_data->zfb_mc_base_addr + dh_data->zfb_size_in_byte - 1) >> 22); - break; - case FRAME_BUFFER_MODE_MIXED_ZFB_AND_LOCAL: - /*Should not touch FB LOCATION (done by VBIOS on AsicInit table)*/ - GENERAL_REG_UPDATE( - DCHUB_AGP_BASE, - AGP_BASE, dh_data->zfb_phys_addr_base >> 22); - - GENERAL_REG_UPDATE( - DCHUB_AGP_BOT, - AGP_BOT, dh_data->zfb_mc_base_addr >> 22); - - GENERAL_REG_UPDATE( - DCHUB_AGP_TOP, - AGP_TOP, (dh_data->zfb_mc_base_addr + dh_data->zfb_size_in_byte - 1) >> 22); - break; - case FRAME_BUFFER_MODE_LOCAL_ONLY: - /*Should not touch FB LOCATION (done by VBIOS on AsicInit table)*/ - GENERAL_REG_UPDATE( - DCHUB_AGP_BASE, - AGP_BASE, 0); - - GENERAL_REG_UPDATE( - DCHUB_AGP_BOT, - AGP_BOT, 0x03FFFF); - - GENERAL_REG_UPDATE( - DCHUB_AGP_TOP, - AGP_TOP, 0); - break; - default: - break; - } - - dh_data->dchub_initialzied = true; - dh_data->dchub_info_valid = false; -} - -static struct mem_input_funcs dce120_mem_input_funcs = { - .mem_input_program_display_marks = dce_mem_input_program_display_marks, - .allocate_mem_input = dce_mem_input_allocate_dmif, - .free_mem_input = dce_mem_input_free_dmif, - .mem_input_program_surface_flip_and_addr = - mem_input_program_surface_flip_and_addr, - .mem_input_program_pte_vm = dce_mem_input_program_pte_vm, - .mem_input_program_surface_config = - dce_mem_input_program_surface_config, - .mem_input_is_flip_pending = mem_input_is_flip_pending, - .mem_input_update_dchub = mem_input_update_dchub -}; - -/*****************************************/ -/* Constructor, Destructor */ -/*****************************************/ - -bool dce120_mem_input_construct( - struct dce110_mem_input *mem_input110, - struct dc_context *ctx, - uint32_t inst, - const struct dce110_mem_input_reg_offsets *offsets) -{ - /* supported stutter method - * STUTTER_MODE_ENHANCED - * STUTTER_MODE_QUAD_DMIF_BUFFER - * STUTTER_MODE_WATERMARK_NBP_STATE - */ - - if (!dce110_mem_input_construct(mem_input110, ctx, inst, offsets)) - return false; - - mem_input110->base.funcs = &dce120_mem_input_funcs; - mem_input110->offsets = *offsets; - - return true; -} diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce120/dce120_mem_input.h deleted file mode 100644 index 379fd72155b9..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_mem_input.h +++ /dev/null @@ -1,37 +0,0 @@ -/* Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DC_MEM_INPUT_DCE120_H__ -#define __DC_MEM_INPUT_DCE120_H__ - -#include "mem_input.h" -#include "dce110/dce110_mem_input.h" - -bool dce120_mem_input_construct( - struct dce110_mem_input *mem_input110, - struct dc_context *ctx, - uint32_t inst, - const struct dce110_mem_input_reg_offsets *offsets); - -#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index b13abb025e1b..1276dabfb208 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -41,8 +41,7 @@ #include "dce/dce_clock_source.h" #include "dce/dce_clocks.h" #include "dce/dce_ipp.h" -#include "dce110/dce110_mem_input.h" -#include "dce120/dce120_mem_input.h" +#include "dce/dce_mem_input.h" #include "dce110/dce110_hw_sequencer.h" #include "dce120/dce120_hw_sequencer.h" @@ -376,51 +375,6 @@ struct output_pixel_processor *dce120_opp_create( return NULL; } -static const struct dce110_mem_input_reg_offsets dce120_mi_reg_offsets[] = { - { - .dcp = (mmDCP0_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), - .dmif = (mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL - - mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE0_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - }, - { - .dcp = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), - .dmif = (mmDMIF_PG1_DPG_WATERMARK_MASK_CONTROL - - mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE1_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - }, - { - .dcp = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), - .dmif = (mmDMIF_PG2_DPG_WATERMARK_MASK_CONTROL - - mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE2_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - }, - { - .dcp = (mmDCP3_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), - .dmif = (mmDMIF_PG3_DPG_WATERMARK_MASK_CONTROL - - mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE3_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - }, - { - .dcp = (mmDCP4_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), - .dmif = (mmDMIF_PG4_DPG_WATERMARK_MASK_CONTROL - - mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE4_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - }, - { - .dcp = (mmDCP5_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), - .dmif = (mmDMIF_PG5_DPG_WATERMARK_MASK_CONTROL - - mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE5_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - } -}; - static const struct bios_registers bios_regs = { .BIOS_SCRATCH_6 = mmBIOS_SCRATCH_6 + NBIO_BASE(mmBIOS_SCRATCH_6_BASE_IDX) }; @@ -518,7 +472,7 @@ static void destruct(struct dce110_resource_pool *pool) dce_ipp_destroy(&pool->base.ipps[i]); if (pool->base.mis[i] != NULL) { - dm_free(TO_DCE110_MEM_INPUT(pool->base.mis[i])); + dm_free(TO_DCE_MEM_INPUT(pool->base.mis[i])); pool->base.mis[i] = NULL; } @@ -708,27 +662,17 @@ static const struct dce_mem_input_mask mi_masks = { static struct mem_input *dce120_mem_input_create( struct dc_context *ctx, - uint32_t inst, - const struct dce110_mem_input_reg_offsets *offset) + uint32_t inst) { - struct dce110_mem_input *mem_input110 = - dm_alloc(sizeof(struct dce110_mem_input)); + struct dce_mem_input *dce_mi = dm_alloc(sizeof(struct dce_mem_input)); - if (!mem_input110) + if (!dce_mi) { + BREAK_TO_DEBUGGER(); return NULL; - - if (dce120_mem_input_construct(mem_input110, ctx, inst, offset)) { - struct mem_input *mi = &mem_input110->base; - - mi->regs = &mi_regs[inst]; - mi->shifts = &mi_shifts; - mi->masks = &mi_masks; - return mi; } - BREAK_TO_DEBUGGER(); - dm_free(mem_input110); - return NULL; + dce112_mem_input_construct(dce_mi, ctx, inst, &mi_regs[inst], &mi_shifts, &mi_masks); + return &dce_mi->base; } static struct transform *dce120_transform_create( @@ -1007,8 +951,7 @@ static bool construct( goto controller_create_fail; } - pool->base.mis[i] = dce120_mem_input_create(ctx, - i, &dce120_mi_reg_offsets[i]); + pool->base.mis[i] = dce120_mem_input_create(ctx, i); if (pool->base.mis[i] == NULL) { BREAK_TO_DEBUGGER(); diff --git a/drivers/gpu/drm/amd/display/dc/dce80/Makefile b/drivers/gpu/drm/amd/display/dc/dce80/Makefile index 1d54d5fa0fd2..c1105895e5fa 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dce80/Makefile @@ -2,8 +2,7 @@ # Makefile for the 'controller' sub-component of DAL. # It provides the control and status of HW CRTC block. -DCE80 = dce80_timing_generator.o \ - dce80_compressor.o dce80_mem_input.o dce80_hw_sequencer.o \ +DCE80 = dce80_timing_generator.o dce80_compressor.o dce80_hw_sequencer.o \ dce80_resource.o AMD_DAL_DCE80 = $(addprefix $(AMDDALPATH)/dc/dce80/,$(DCE80)) diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c deleted file mode 100644 index 933e3d819f27..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ -#include "dm_services.h" - -#include "dce/dce_8_0_d.h" -#include "dce/dce_8_0_sh_mask.h" -/* TODO: this needs to be looked at, used by Stella's workaround*/ -#include "gmc/gmc_7_1_d.h" -#include "gmc/gmc_7_1_sh_mask.h" - -#include "include/logger_interface.h" -#include "inc/dce_calcs.h" - -#include "../dce110/dce110_mem_input.h" -#include "dce80_mem_input.h" - -#define MAX_WATERMARK 0xFFFF -#define SAFE_NBP_MARK 0x7FFF - -#define DCP_REG(reg) (reg + mem_input80->offsets.dcp) -#define DMIF_REG(reg) (reg + mem_input80->offsets.dmif) -#define PIPE_REG(reg) (reg + mem_input80->offsets.pipe) - -static struct mem_input_funcs dce80_mem_input_funcs = { - .mem_input_program_display_marks = - dce110_mem_input_program_display_marks, - .allocate_mem_input = dce_mem_input_allocate_dmif, - .free_mem_input = dce_mem_input_free_dmif, - .mem_input_program_surface_flip_and_addr = - dce110_mem_input_program_surface_flip_and_addr, - .mem_input_program_surface_config = - dce_mem_input_program_surface_config, - .mem_input_is_flip_pending = - dce110_mem_input_is_flip_pending, - .mem_input_update_dchub = NULL -}; - -/*****************************************/ -/* Constructor, Destructor */ -/*****************************************/ - -bool dce80_mem_input_construct( - struct dce110_mem_input *mem_input80, - struct dc_context *ctx, - uint32_t inst, - const struct dce110_mem_input_reg_offsets *offsets) -{ - /* supported stutter method - * STUTTER_MODE_ENHANCED - * STUTTER_MODE_QUAD_DMIF_BUFFER - */ - mem_input80->base.funcs = &dce80_mem_input_funcs; - mem_input80->base.ctx = ctx; - - mem_input80->base.inst = inst; - - mem_input80->offsets = *offsets; - - return true; -} - diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.h deleted file mode 100644 index 357b9e2e9f1e..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.h +++ /dev/null @@ -1,36 +0,0 @@ -/* Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DC_MEM_INPUT_DCE80_H__ -#define __DC_MEM_INPUT_DCE80_H__ - -#include "mem_input.h" - -bool dce80_mem_input_construct( - struct dce110_mem_input *mem_input80, - struct dc_context *ctx, - uint32_t inst, - const struct dce110_mem_input_reg_offsets *offsets); - -#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 5735914a8737..095e437ce112 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -35,12 +35,12 @@ #include "include/irq_service_interface.h" #include "irq/dce80/irq_service_dce80.h" #include "dce110/dce110_timing_generator.h" -#include "dce110/dce110_mem_input.h" #include "dce110/dce110_resource.h" #include "dce80/dce80_timing_generator.h" +#include "dce/dce_mem_input.h" #include "dce/dce_link_encoder.h" #include "dce/dce_stream_encoder.h" -#include "dce80/dce80_mem_input.h" +#include "dce/dce_mem_input.h" #include "dce/dce_ipp.h" #include "dce/dce_transform.h" #include "dce/dce_opp.h" @@ -141,51 +141,6 @@ static const struct dce110_timing_generator_offsets dce80_tg_offsets[] = { } }; -static const struct dce110_mem_input_reg_offsets dce80_mi_reg_offsets[] = { - { - .dcp = (mmGRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE0_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - }, - { - .dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG1_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE1_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - }, - { - .dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG2_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE2_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - }, - { - .dcp = (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG3_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE3_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - }, - { - .dcp = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG4_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE4_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - }, - { - .dcp = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG5_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE5_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - } -}; - /* set register offset */ #define SR(reg_name)\ .reg_name = mm ## reg_name @@ -541,28 +496,18 @@ static const struct dce_mem_input_mask mi_masks = { static struct mem_input *dce80_mem_input_create( struct dc_context *ctx, - uint32_t inst, - const struct dce110_mem_input_reg_offsets *offsets) + uint32_t inst) { - struct dce110_mem_input *mem_input80 = - dm_alloc(sizeof(struct dce110_mem_input)); + struct dce_mem_input *dce_mi = dm_alloc(sizeof(struct dce_mem_input)); - if (!mem_input80) + if (!dce_mi) { + BREAK_TO_DEBUGGER(); return NULL; - - if (dce80_mem_input_construct(mem_input80, ctx, inst, offsets)) { - struct mem_input *mi = &mem_input80->base; - - mi->regs = &mi_regs[inst]; - mi->shifts = &mi_shifts; - mi->masks = &mi_masks; - mi->wa.single_head_rdreq_dmif_limit = 2; - return mi; } - BREAK_TO_DEBUGGER(); - dm_free(mem_input80); - return NULL; + dce_mem_input_construct(dce_mi, ctx, inst, &mi_regs[inst], &mi_shifts, &mi_masks); + dce_mi->wa.single_head_rdreq_dmif_limit = 2; + return &dce_mi->base; } static void dce80_transform_destroy(struct transform **xfm) @@ -684,7 +629,7 @@ static void destruct(struct dce110_resource_pool *pool) dce_ipp_destroy(&pool->base.ipps[i]); if (pool->base.mis[i] != NULL) { - dm_free(TO_DCE110_MEM_INPUT(pool->base.mis[i])); + dm_free(TO_DCE_MEM_INPUT(pool->base.mis[i])); pool->base.mis[i] = NULL; } @@ -1000,8 +945,7 @@ static bool construct( goto res_create_fail; } - pool->base.mis[i] = dce80_mem_input_create(ctx, i, - &dce80_mi_reg_offsets[i]); + pool->base.mis[i] = dce80_mem_input_create(ctx, i); if (pool->base.mis[i] == NULL) { BREAK_TO_DEBUGGER(); dm_error("DC: failed to create memory input!\n"); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h index 79fbc60e21c9..bd0dfeb2afa2 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h @@ -28,8 +28,6 @@ #include "dc.h" #include "include/grph_object_id.h" -#include "dce/dce_mem_input.h" /* temporary */ - #if defined(CONFIG_DRM_AMD_DC_DCN1_0) #include "dml/display_mode_structs.h" @@ -51,7 +49,6 @@ struct dcn_watermark_set { struct dcn_watermarks c; struct dcn_watermarks d; }; - #endif struct dce_watermarks { @@ -74,11 +71,6 @@ struct mem_input { struct dc_plane_address current_address; uint32_t inst; struct stutter_modes stutter_mode; - - const struct dce_mem_input_registers *regs; - const struct dce_mem_input_shift *shifts; - const struct dce_mem_input_mask *masks; - struct dce_mem_input_wa wa; }; struct mem_input_funcs { -- cgit From 3379da831b4032e3d7cac2cb199293e59f0c9e9f Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Mon, 15 May 2017 13:59:31 -0400 Subject: drm/amd/display: Use dc_update_surfaces_for_stream for flip. Today we use special interface for flip because of fear of cuncurency issues over dc->current_ctx. This should be no longer an issue when flipping on multiple CRTCs concurently since for fast update (as flip is) no new context is created and the exsisitng is not destroyed. For full updates case when removing or adding streams on once CRTC while flipping on another Adding all current active CRTC's states to the atomic commit in amdgpu_dm_atomic_check will garntee that any such full update commit will wait for completion of any outstanding flip. Signed-off-by: Andrey Grodzovsky Reviewed-by: Andrey Grodzovsky Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 9 ++++++--- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 23 +++++++++++++++++++++- 2 files changed, 28 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') 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 a2c00c0bf007..7e28f9870b86 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1349,6 +1349,7 @@ static void dm_page_flip(struct amdgpu_device *adev, struct amdgpu_crtc *acrtc; const struct dc_stream *stream; struct dc_flip_addrs addr = { {0} }; + struct dc_surface_update surface_updates[1] = { {0} }; /* * TODO risk of concurrency issues @@ -1411,9 +1412,11 @@ static void dm_page_flip(struct amdgpu_device *adev, acrtc->base.state->event = NULL; } - dc_flip_surface_addrs(adev->dm.dc, - dc_stream_get_status(stream)->surfaces, - &addr, 1); + surface_updates->surface = dc_stream_get_status(stream)->surfaces[0]; + surface_updates->flip_addr = &addr; + + + dc_update_surfaces_for_stream(adev->dm.dc, surface_updates, 1, stream); DRM_DEBUG_DRIVER("%s Flipping to hi: 0x%x, low: 0x%x \n", __func__, diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 9c0dc9d07626..7d989b6738e4 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2901,6 +2901,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, struct dc *dc = adev->dm.dc; bool need_to_validate = false; struct validate_context *context; + bool wait_4_prev_commits = false; ret = drm_atomic_helper_check(dev, state); @@ -2977,6 +2978,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, new_stream_count++; need_to_validate = true; + wait_4_prev_commits = true; break; } @@ -3022,6 +3024,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, new_stream_count++; need_to_validate = true; + wait_4_prev_commits = true; break; } @@ -3033,6 +3036,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, set, set_count, acrtc->stream); + wait_4_prev_commits = true; } break; } @@ -3125,9 +3129,26 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, context = dc_get_validate_context(dc, set, set_count); - if (need_to_validate == false || set_count == 0 || context) + if (need_to_validate == false || set_count == 0 || context) { + ret = 0; + if (wait_4_prev_commits) { + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + struct drm_crtc_state *crtc_state; + + if (acrtc->stream) { + crtc_state = drm_atomic_get_crtc_state(state, crtc); + if (IS_ERR(crtc_state)) { + ret = PTR_ERR(crtc_state); + break; + } + } + } + } + } + if (context) { dc_resource_validate_ctx_destruct(context); dm_free(context); -- cgit From b802acc7f3266e43905dfeee865bf1acc4e00bce Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Mon, 15 May 2017 14:47:02 -0400 Subject: drm/amd/display: Clean unused interface. Signed-off-by: Andrey Grodzovsky Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 26 -------------------------- drivers/gpu/drm/amd/display/dc/dc.h | 12 ------------ 2 files changed, 38 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 6d56cb0c29cc..b5ba822df55e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1515,32 +1515,6 @@ const struct audio **dc_get_audios(struct dc *dc) return (const struct audio **)core_dc->res_pool->audios; } -void dc_flip_surface_addrs( - struct dc *dc, - const struct dc_surface *const surfaces[], - struct dc_flip_addrs flip_addrs[], - uint32_t count) -{ - struct core_dc *core_dc = DC_TO_CORE(dc); - int i, j; - - for (i = 0; i < count; i++) { - struct core_surface *surface = DC_SURFACE_TO_CORE(surfaces[i]); - - surface->public.address = flip_addrs[i].address; - surface->public.flip_immediate = flip_addrs[i].flip_immediate; - - for (j = 0; j < core_dc->res_pool->pipe_count; j++) { - struct pipe_ctx *pipe_ctx = &core_dc->current_context->res_ctx.pipe_ctx[j]; - - if (pipe_ctx->surface != surface) - continue; - - core_dc->hwss.update_plane_addr(core_dc, pipe_ctx); - } - } -} - enum dc_irq_source dc_interrupt_to_irq_source( struct dc *dc, uint32_t src_id, diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 0610805cdb05..f2efa32fe4ac 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -393,18 +393,6 @@ struct dc_flip_addrs { /* TODO: add flip duration for FreeSync */ }; -/* - * Optimized flip address update function. - * - * After this call: - * Surface addresses and flip attributes are programmed. - * Surface flip occur at next configured time (h_sync or v_sync flip) - */ -void dc_flip_surface_addrs(struct dc *dc, - const struct dc_surface *const surfaces[], - struct dc_flip_addrs flip_addrs[], - uint32_t count); - /* * Set up surface attributes and associate to a stream * The surfaces parameter is an absolute set of all surface active for the stream. -- cgit From d3ec0562085918ba889af3d565b4104adcd4947f Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Tue, 16 May 2017 09:55:20 -0400 Subject: drm/amd/display: Fix dcn10 cursor set position hang Calling dcn10_cursor_set_position() before dcn10_cursor_set_attributes() with invalid (0-value) attributes can cause the ASIC to hang. This fix checks that address.quadpart is non-zero within set_position before calling set_attributes. Signed-off-by: Leo (Sunpeng) Li Reviewed-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c index 3062b7de4fe2..082c98c11293 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c @@ -614,6 +614,16 @@ static void dcn10_cursor_set_position( uint32_t cur_en = pos->enable ? 1 : 0; uint32_t dst_x_offset = (src_x_offset >= 0) ? src_x_offset : 0; + /* + * Guard aganst cursor_set_position() from being called with invalid + * attributes + * + * TODO: Look at combining cursor_set_position() and + * cursor_set_attributes() into cursor_update() + */ + if (ippn10->curs_attr.address.quad_part == 0) + return; + dst_x_offset *= param->ref_clk_khz; dst_x_offset /= param->pixel_clk_khz; -- cgit From 1185da086903e87259fd54c20c04098bcefa9da3 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 17 May 2017 10:59:53 -0400 Subject: drm/amd/display: add missing GRPH_UPDATE_LOCK field macro for dce_mem_input Signed-off-by: Dmytro Laktyushkin Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h index 55481f5adcdf..9d083cd79b4c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h @@ -158,6 +158,7 @@ struct dce_mem_input_registers { SFB(blk, GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, mask_sh),\ SFB(blk, GRPH_PRIMARY_SURFACE_ADDRESS, GRPH_PRIMARY_SURFACE_ADDRESS, mask_sh),\ SFB(blk, GRPH_UPDATE, GRPH_SURFACE_UPDATE_PENDING, mask_sh),\ + SFB(blk, GRPH_UPDATE, GRPH_UPDATE_LOCK, mask_sh),\ SFB(blk, GRPH_FLIP_CONTROL, GRPH_SURFACE_UPDATE_H_RETRACE_EN, mask_sh) #define MI_DCP_DCE11_MASK_SH_LIST(mask_sh, blk)\ -- cgit From bdc79f8e5dfaeb83dd3a1b609aff25712250cc1e Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Mon, 15 May 2017 18:55:38 -0400 Subject: drm/amd/display: Unify loop for surface update and page flip. Remove extra loop we have for page flips and do flips in same loop we do for surface create/update. Add documentation for synchronization between commits on different crtcs. Rename function to have DM prefix. Signed-off-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 88 +++++++++++----------- 1 file changed, 42 insertions(+), 46 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 7d989b6738e4..d6ea2d5726dd 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2381,10 +2381,11 @@ static void amdgpu_dm_do_flip( acrtc->crtc_id); } -void dc_commit_surfaces(struct drm_atomic_state *state, +static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, struct drm_device *dev, struct amdgpu_display_manager *dm, - struct drm_crtc *pcrtc) + struct drm_crtc *pcrtc, + bool *wait_for_vblank) { uint32_t i; struct drm_plane *plane; @@ -2397,10 +2398,11 @@ void dc_commit_surfaces(struct drm_atomic_state *state, for_each_plane_in_state(state, plane, old_plane_state, i) { struct drm_plane_state *plane_state = plane->state; struct drm_crtc *crtc = plane_state->crtc; + struct amdgpu_crtc *acrtc_attach = to_amdgpu_crtc(crtc); struct drm_framebuffer *fb = plane_state->fb; struct drm_connector *connector; struct dm_connector_state *dm_state = NULL; - struct amdgpu_crtc *acrtc_attach; + enum dm_commit_action action; bool pflip_needed; @@ -2409,13 +2411,13 @@ void dc_commit_surfaces(struct drm_atomic_state *state, action = get_dm_commit_action(crtc->state); - /* Surfaces are created under two scenarios: - * 1. This commit is not a page flip. - * 2. This commit is a page flip, and streams are created. + /* + * TODO - TO decide if it's a flip or surface update + * stop relying on allow_modeset flag and query DC + * using dc_check_update_surfaces_for_stream. */ pflip_needed = !state->allow_modeset; - if (!pflip_needed || action == DM_COMMIT_ACTION_DPMS_ON - || action == DM_COMMIT_ACTION_SET) { + if (!pflip_needed) { list_for_each_entry(connector, &dev->mode_config.connector_list, head) { @@ -2445,11 +2447,23 @@ void dc_commit_surfaces(struct drm_atomic_state *state, if (crtc == pcrtc) { add_surface(dm->dc, crtc, plane, &dc_surfaces_constructed[planes_count]); - acrtc_attach = to_amdgpu_crtc(crtc); dc_stream_attach = acrtc_attach->stream; planes_count++; } + } else if (crtc->state->planes_changed) { + *wait_for_vblank = + acrtc_attach->flip_flags & DRM_MODE_PAGE_FLIP_ASYNC ? + false : true; + + amdgpu_dm_do_flip( + crtc, + fb, + drm_crtc_vblank_count(crtc) + *wait_for_vblank); + + /*clean up the flags for next usage*/ + acrtc_attach->flip_flags = 0; } + } if (planes_count) { @@ -2471,8 +2485,6 @@ void amdgpu_dm_atomic_commit_tail( struct drm_device *dev = state->dev; struct amdgpu_device *adev = dev->dev_private; struct amdgpu_display_manager *dm = &adev->dm; - struct drm_plane *plane; - struct drm_plane_state *old_plane_state; uint32_t i, j; uint32_t commit_streams_count = 0; uint32_t new_crtcs_count = 0; @@ -2637,7 +2649,7 @@ void amdgpu_dm_atomic_commit_tail( /* update planes when needed per crtc*/ for_each_crtc_in_state(state, pcrtc, old_crtc_state, j) - dc_commit_surfaces(state, dev, dm, pcrtc); + amdgpu_dm_commit_surfaces(state, dev, dm, pcrtc, &wait_for_vblank); for (i = 0; i < new_crtcs_count; i++) { /* @@ -2651,34 +2663,6 @@ void amdgpu_dm_atomic_commit_tail( manage_dm_interrupts(adev, acrtc, true); dm_crtc_cursor_reset(&acrtc->base); - - } - - for_each_plane_in_state(state, plane, old_plane_state, i) { - struct drm_plane_state *plane_state = plane->state; - struct drm_crtc *crtc = plane_state->crtc; - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - struct drm_framebuffer *fb = plane_state->fb; - bool pflip_needed; - - if (!fb || !crtc || !crtc->state->planes_changed || - !crtc->state->active) - continue; - pflip_needed = !state->allow_modeset; - - if (pflip_needed) { - wait_for_vblank = - acrtc->flip_flags & DRM_MODE_PAGE_FLIP_ASYNC ? - false : true; - - amdgpu_dm_do_flip( - crtc, - fb, - drm_crtc_vblank_count(crtc) + wait_for_vblank); - - /*clean up the flags for next usage*/ - acrtc->flip_flags = 0; - } } @@ -2901,7 +2885,11 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, struct dc *dc = adev->dm.dc; bool need_to_validate = false; struct validate_context *context; - bool wait_4_prev_commits = false; + /* + * This bool will be set for true for any modeset/reset + * or surface update which implies non fast surfae update. + */ + bool wait_for_prev_commits = false; ret = drm_atomic_helper_check(dev, state); @@ -2978,7 +2966,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, new_stream_count++; need_to_validate = true; - wait_4_prev_commits = true; + wait_for_prev_commits = true; break; } @@ -3024,7 +3012,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, new_stream_count++; need_to_validate = true; - wait_4_prev_commits = true; + wait_for_prev_commits = true; break; } @@ -3036,7 +3024,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, set, set_count, acrtc->stream); - wait_4_prev_commits = true; + wait_for_prev_commits = true; } break; } @@ -3132,8 +3120,16 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, if (need_to_validate == false || set_count == 0 || context) { ret = 0; - - if (wait_4_prev_commits) { + /* + * For full updates case when + * removing/adding/updateding streams on once CRTC while flipping + * on another CRTC, + * Adding all current active CRTC's states to the atomic commit in + * amdgpu_dm_atomic_check will guarantee that any such full update commit + * will wait for completion of any outstanding flip using DRMs + * synchronization events. + */ + if (wait_for_prev_commits) { list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); struct drm_crtc_state *crtc_state; -- cgit From 1f7f3aec125724da30ff1c2f2d359340feb0d9e1 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Tue, 16 May 2017 21:27:01 -0400 Subject: drm/amd/display: read VM settings from MMHUB instead of GC, as after GFX off, GC can be power gated any time Signed-off-by: Tony Cheng Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h | 24 +++++++++++----------- .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 14 ++++++------- 2 files changed, 19 insertions(+), 19 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h index 4a5eb6ae3524..20bd0f5d7b17 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h @@ -130,18 +130,18 @@ SR(DCHUBBUB_ARB_SAT_LEVEL),\ SR(DCHUBBUB_ARB_DF_REQ_OUTSTAND),\ /* todo: get these from GVM instead of reading registers ourselves */\ - GC_SR(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32),\ - GC_SR(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32),\ - GC_SR(VM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32),\ - GC_SR(VM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32),\ - GC_SR(VM_CONTEXT0_PAGE_TABLE_END_ADDR_HI32),\ - GC_SR(VM_CONTEXT0_PAGE_TABLE_END_ADDR_LO32),\ - GC_SR(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_HI32),\ - GC_SR(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32),\ - GC_SR(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB),\ - GC_SR(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB),\ - GC_SR(MC_VM_SYSTEM_APERTURE_LOW_ADDR),\ - GC_SR(MC_VM_SYSTEM_APERTURE_HIGH_ADDR) + MMHUB_SR(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32),\ + MMHUB_SR(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32),\ + MMHUB_SR(VM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32),\ + MMHUB_SR(VM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32),\ + MMHUB_SR(VM_CONTEXT0_PAGE_TABLE_END_ADDR_HI32),\ + MMHUB_SR(VM_CONTEXT0_PAGE_TABLE_END_ADDR_LO32),\ + MMHUB_SR(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_HI32),\ + MMHUB_SR(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32),\ + MMHUB_SR(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB),\ + MMHUB_SR(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB),\ + MMHUB_SR(MC_VM_SYSTEM_APERTURE_LOW_ADDR),\ + MMHUB_SR(MC_VM_SYSTEM_APERTURE_HIGH_ADDR) struct dcn_mi_registers { uint32_t DCHUBP_CNTL; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 4e5b225a2a08..7fdc5860857b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -122,15 +122,15 @@ enum dcn10_clk_src_array_id { .reg_name = NBIO_BASE(mm ## reg_name ## _BASE_IDX) + \ mm ## reg_name -/* GC */ -#define GC_BASE_INNER(seg) \ - GC_BASE__INST0_SEG ## seg +/* MMHUB */ +#define MMHUB_BASE_INNER(seg) \ + MMHUB_BASE__INST0_SEG ## seg -#define GC_BASE(seg) \ - GC_BASE_INNER(seg) +#define MMHUB_BASE(seg) \ + MMHUB_BASE_INNER(seg) -#define GC_SR(reg_name)\ - .reg_name = GC_BASE(mm ## reg_name ## _BASE_IDX) + \ +#define MMHUB_SR(reg_name)\ + .reg_name = MMHUB_BASE(mm ## reg_name ## _BASE_IDX) + \ mm ## reg_name /* macros to expend register list macro defined in HW object header file -- cgit From ccaf31ec714b596d1edb92b1ed4ccc4abf1f645c Mon Sep 17 00:00:00 2001 From: Roman Li Date: Wed, 17 May 2017 12:07:30 -0400 Subject: drm/amd/display: Fix 5th display lightup on Vega10 - fixing bug in calculation of reg offset for D5VGA_CONTROL Signed-off-by: Roman Li Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c index 245356e72b36..dc8eeac6ac96 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c @@ -410,7 +410,7 @@ void dce120_timing_generator_disable_vga(struct timing_generator *tg) break; case CONTROLLER_ID_D4: addr = mmD1VGA_CONTROL; - offset = mmD1VGA_CONTROL - mmD1VGA_CONTROL; + offset = mmD5VGA_CONTROL - mmD1VGA_CONTROL; break; case CONTROLLER_ID_D5: addr = mmD6VGA_CONTROL; -- cgit From 430ef426bc43b59a7444c08d664e24a7cf89710e Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 17 May 2017 16:05:40 -0400 Subject: drm/amd/display: make dc_get_validate_context re-entrant Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 44 ++-------------------- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 30 +++++++-------- .../drm/amd/display/dc/dce100/dce100_resource.c | 22 ++++++----- .../drm/amd/display/dc/dce110/dce110_resource.c | 22 ++++++----- .../drm/amd/display/dc/dce112/dce112_resource.c | 27 +++++++------ .../drm/amd/display/dc/dce112/dce112_resource.h | 3 +- .../gpu/drm/amd/display/dc/dce80/dce80_resource.c | 22 ++++++----- .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 24 ++++++------ drivers/gpu/drm/amd/display/dc/inc/core_types.h | 3 +- drivers/gpu/drm/amd/display/dc/inc/resource.h | 9 +++-- 10 files changed, 92 insertions(+), 114 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index b5ba822df55e..0aafcc088284 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -653,40 +653,6 @@ void dc_destroy(struct dc **dc) *dc = NULL; } -static bool is_validation_required( - const struct core_dc *dc, - const struct dc_validation_set set[], - int set_count) -{ - const struct validate_context *context = dc->current_context; - int i, j; - - if (context->stream_count != set_count) - return true; - - for (i = 0; i < set_count; i++) { - - if (set[i].surface_count != context->stream_status[i].surface_count) - return true; - if (!is_stream_unchanged(DC_STREAM_TO_CORE(set[i].stream), context->streams[i])) - return true; - - for (j = 0; j < set[i].surface_count; j++) { - struct dc_surface temp_surf = { 0 }; - - temp_surf = *context->stream_status[i].surfaces[j]; - temp_surf.clip_rect = set[i].surfaces[j]->clip_rect; - temp_surf.dst_rect.x = set[i].surfaces[j]->dst_rect.x; - temp_surf.dst_rect.y = set[i].surfaces[j]->dst_rect.y; - - if (memcmp(&temp_surf, set[i].surfaces[j], sizeof(temp_surf)) != 0) - return true; - } - } - - return false; -} - struct validate_context *dc_get_validate_context( const struct dc *dc, const struct dc_validation_set set[], @@ -700,13 +666,8 @@ struct validate_context *dc_get_validate_context( if(context == NULL) goto context_alloc_fail; - if (!is_validation_required(core_dc, set, set_count)) { - dc_resource_validate_ctx_copy_construct(core_dc->current_context, context); - return context; - } - result = core_dc->res_pool->funcs->validate_with_context( - core_dc, set, set_count, context); + core_dc, set, set_count, context, NULL); context_alloc_fail: if (result != DC_OK) { @@ -903,7 +864,8 @@ bool dc_commit_streams( if (context == NULL) goto context_alloc_fail; - result = core_dc->res_pool->funcs->validate_with_context(core_dc, set, stream_count, context); + result = core_dc->res_pool->funcs->validate_with_context( + core_dc, set, stream_count, context, core_dc->current_context); if (result != DC_OK){ dm_logger_write(core_dc->ctx->logger, LOG_ERROR, "%s: Context validation failed! dc_status:%d\n", diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 7ca03d1ad163..ec5045734378 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1148,7 +1148,7 @@ bool resource_validate_attach_surfaces( int i, j; for (i = 0; i < set_count; i++) { - for (j = 0; j < old_context->stream_count; j++) + for (j = 0; old_context && j < old_context->stream_count; j++) if (is_stream_unchanged( old_context->streams[j], context->streams[i])) { @@ -1387,9 +1387,7 @@ static int get_norm_pix_clk(const struct dc_crtc_timing *timing) return normalized_pix_clk; } -static void calculate_phy_pix_clks( - const struct core_dc *dc, - struct validate_context *context) +static void calculate_phy_pix_clks(struct validate_context *context) { int i; @@ -1410,21 +1408,22 @@ static void calculate_phy_pix_clks( enum dc_status resource_map_pool_resources( const struct core_dc *dc, - struct validate_context *context) + struct validate_context *context, + struct validate_context *old_context) { const struct resource_pool *pool = dc->res_pool; int i, j; - calculate_phy_pix_clks(dc, context); + calculate_phy_pix_clks(context); - for (i = 0; i < context->stream_count; i++) { + for (i = 0; old_context && i < context->stream_count; i++) { struct core_stream *stream = context->streams[i]; - if (!resource_is_stream_unchanged(dc->current_context, stream)) { - if (stream != NULL && dc->current_context->streams[i] != NULL) { + if (!resource_is_stream_unchanged(old_context, stream)) { + if (stream != NULL && old_context->streams[i] != NULL) { stream->bit_depth_params = - dc->current_context->streams[i]->bit_depth_params; - stream->clamping = dc->current_context->streams[i]->clamping; + old_context->streams[i]->bit_depth_params; + stream->clamping = old_context->streams[i]->clamping; continue; } } @@ -1434,7 +1433,7 @@ enum dc_status resource_map_pool_resources( struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; const struct pipe_ctx *old_pipe_ctx = - &dc->current_context->res_ctx.pipe_ctx[j]; + &old_context->res_ctx.pipe_ctx[j]; if (!are_stream_backends_same(old_pipe_ctx->stream, stream)) continue; @@ -1475,7 +1474,7 @@ enum dc_status resource_map_pool_resources( struct pipe_ctx *pipe_ctx = NULL; int pipe_idx = -1; - if (resource_is_stream_unchanged(dc->current_context, stream)) + if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; /* acquire new resources */ pipe_idx = acquire_first_free_pipe( @@ -2203,7 +2202,8 @@ void resource_build_info_frame(struct pipe_ctx *pipe_ctx) enum dc_status resource_map_clock_resources( const struct core_dc *dc, - struct validate_context *context) + struct validate_context *context, + struct validate_context *old_context) { int i, j; const struct resource_pool *pool = dc->res_pool; @@ -2212,7 +2212,7 @@ enum dc_status resource_map_clock_resources( for (i = 0; i < context->stream_count; i++) { const struct core_stream *stream = context->streams[i]; - if (resource_is_stream_unchanged(dc->current_context, stream)) + if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; for (j = 0; j < MAX_PIPES; j++) { diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 8f1fe95dd76c..716f664f40ce 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -653,7 +653,8 @@ static void destruct(struct dce110_resource_pool *pool) static enum dc_status validate_mapped_resource( const struct core_dc *dc, - struct validate_context *context) + struct validate_context *context, + struct validate_context *old_context) { enum dc_status status = DC_OK; uint8_t i, j; @@ -662,7 +663,7 @@ static enum dc_status validate_mapped_resource( struct core_stream *stream = context->streams[i]; struct core_link *link = stream->sink->link; - if (resource_is_stream_unchanged(dc->current_context, stream)) + if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; for (j = 0; j < MAX_PIPES; j++) { @@ -740,7 +741,8 @@ enum dc_status dce100_validate_with_context( const struct core_dc *dc, const struct dc_validation_set set[], int set_count, - struct validate_context *context) + struct validate_context *context, + struct validate_context *old_context) { struct dc_context *dc_ctx = dc->ctx; enum dc_status result = DC_ERROR_UNEXPECTED; @@ -755,19 +757,19 @@ enum dc_status dce100_validate_with_context( context->stream_count++; } - result = resource_map_pool_resources(dc, context); + result = resource_map_pool_resources(dc, context, old_context); if (result == DC_OK) - result = resource_map_clock_resources(dc, context); + result = resource_map_clock_resources(dc, context, old_context); if (!resource_validate_attach_surfaces(set, set_count, - dc->current_context, context, dc->res_pool)) { + old_context, context, dc->res_pool)) { DC_ERROR("Failed to attach surface to stream!\n"); return DC_FAIL_ATTACH_SURFACES; } if (result == DC_OK) - result = validate_mapped_resource(dc, context); + result = validate_mapped_resource(dc, context, old_context); if (result == DC_OK) result = resource_build_scaling_params_for_context(dc, context); @@ -790,13 +792,13 @@ enum dc_status dce100_validate_guaranteed( dc_stream_retain(&context->streams[0]->public); context->stream_count++; - result = resource_map_pool_resources(dc, context); + result = resource_map_pool_resources(dc, context, NULL); if (result == DC_OK) - result = resource_map_clock_resources(dc, context); + result = resource_map_clock_resources(dc, context, NULL); if (result == DC_OK) - result = validate_mapped_resource(dc, context); + result = validate_mapped_resource(dc, context, NULL); if (result == DC_OK) { validate_guaranteed_copy_streams( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 3ed5b9445535..45759b9f15e5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -769,7 +769,8 @@ static bool is_surface_pixel_format_supported(struct pipe_ctx *pipe_ctx, unsigne static enum dc_status validate_mapped_resource( const struct core_dc *dc, - struct validate_context *context) + struct validate_context *context, + struct validate_context *old_context) { enum dc_status status = DC_OK; uint8_t i, j; @@ -778,7 +779,7 @@ static enum dc_status validate_mapped_resource( struct core_stream *stream = context->streams[i]; struct core_link *link = stream->sink->link; - if (resource_is_stream_unchanged(dc->current_context, stream)) + if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; for (j = 0; j < MAX_PIPES; j++) { @@ -943,7 +944,8 @@ enum dc_status dce110_validate_with_context( const struct core_dc *dc, const struct dc_validation_set set[], int set_count, - struct validate_context *context) + struct validate_context *context, + struct validate_context *old_context) { struct dc_context *dc_ctx = dc->ctx; enum dc_status result = DC_ERROR_UNEXPECTED; @@ -958,19 +960,19 @@ enum dc_status dce110_validate_with_context( context->stream_count++; } - result = resource_map_pool_resources(dc, context); + result = resource_map_pool_resources(dc, context, old_context); if (result == DC_OK) - result = resource_map_clock_resources(dc, context); + result = resource_map_clock_resources(dc, context, old_context); if (!resource_validate_attach_surfaces(set, set_count, - dc->current_context, context, dc->res_pool)) { + old_context, context, dc->res_pool)) { DC_ERROR("Failed to attach surface to stream!\n"); return DC_FAIL_ATTACH_SURFACES; } if (result == DC_OK) - result = validate_mapped_resource(dc, context); + result = validate_mapped_resource(dc, context, old_context); if (result == DC_OK) result = resource_build_scaling_params_for_context(dc, context); @@ -993,13 +995,13 @@ enum dc_status dce110_validate_guaranteed( dc_stream_retain(&context->streams[0]->public); context->stream_count++; - result = resource_map_pool_resources(dc, context); + result = resource_map_pool_resources(dc, context, NULL); if (result == DC_OK) - result = resource_map_clock_resources(dc, context); + result = resource_map_clock_resources(dc, context, NULL); if (result == DC_OK) - result = validate_mapped_resource(dc, context); + result = validate_mapped_resource(dc, context, NULL); if (result == DC_OK) { validate_guaranteed_copy_streams( diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index f405d6eecaa5..80f067343a91 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -722,7 +722,8 @@ static struct clock_source *find_matching_pll( static enum dc_status validate_mapped_resource( const struct core_dc *dc, - struct validate_context *context) + struct validate_context *context, + struct validate_context *old_context) { enum dc_status status = DC_OK; uint8_t i, j; @@ -731,7 +732,7 @@ static enum dc_status validate_mapped_resource( struct core_stream *stream = context->streams[i]; struct core_link *link = stream->sink->link; - if (resource_is_stream_unchanged(dc->current_context, stream)) + if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; for (j = 0; j < MAX_PIPES; j++) { @@ -854,7 +855,8 @@ bool dce112_validate_bandwidth( enum dc_status resource_map_phy_clock_resources( const struct core_dc *dc, - struct validate_context *context) + struct validate_context *context, + struct validate_context *old_context) { uint8_t i, j; @@ -862,7 +864,7 @@ enum dc_status resource_map_phy_clock_resources( for (i = 0; i < context->stream_count; i++) { struct core_stream *stream = context->streams[i]; - if (resource_is_stream_unchanged(dc->current_context, stream)) + if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; for (j = 0; j < MAX_PIPES; j++) { @@ -922,7 +924,8 @@ enum dc_status dce112_validate_with_context( const struct core_dc *dc, const struct dc_validation_set set[], int set_count, - struct validate_context *context) + struct validate_context *context, + struct validate_context *old_context) { struct dc_context *dc_ctx = dc->ctx; enum dc_status result = DC_ERROR_UNEXPECTED; @@ -937,19 +940,19 @@ enum dc_status dce112_validate_with_context( context->stream_count++; } - result = resource_map_pool_resources(dc, context); + result = resource_map_pool_resources(dc, context, old_context); if (result == DC_OK) - result = resource_map_phy_clock_resources(dc, context); + result = resource_map_phy_clock_resources(dc, context, old_context); if (!resource_validate_attach_surfaces(set, set_count, - dc->current_context, context, dc->res_pool)) { + old_context, context, dc->res_pool)) { DC_ERROR("Failed to attach surface to stream!\n"); return DC_FAIL_ATTACH_SURFACES; } if (result == DC_OK) - result = validate_mapped_resource(dc, context); + result = validate_mapped_resource(dc, context, old_context); if (result == DC_OK) result = resource_build_scaling_params_for_context(dc, context); @@ -972,13 +975,13 @@ enum dc_status dce112_validate_guaranteed( dc_stream_retain(&context->streams[0]->public); context->stream_count++; - result = resource_map_pool_resources(dc, context); + result = resource_map_pool_resources(dc, context, NULL); if (result == DC_OK) - result = resource_map_phy_clock_resources(dc, context); + result = resource_map_phy_clock_resources(dc, context, NULL); if (result == DC_OK) - result = validate_mapped_resource(dc, context); + result = validate_mapped_resource(dc, context, NULL); if (result == DC_OK) { validate_guaranteed_copy_streams( diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h index dc842aace766..c6c0bbac5335 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h @@ -39,7 +39,8 @@ enum dc_status dce112_validate_with_context( const struct core_dc *dc, const struct dc_validation_set set[], int set_count, - struct validate_context *context); + struct validate_context *context, + struct validate_context *old_context); enum dc_status dce112_validate_guaranteed( const struct core_dc *dc, diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 095e437ce112..5861b3fdf7d2 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -669,7 +669,8 @@ static void destruct(struct dce110_resource_pool *pool) static enum dc_status validate_mapped_resource( const struct core_dc *dc, - struct validate_context *context) + struct validate_context *context, + struct validate_context *old_context) { enum dc_status status = DC_OK; uint8_t i, j; @@ -678,7 +679,7 @@ static enum dc_status validate_mapped_resource( struct core_stream *stream = context->streams[i]; struct core_link *link = stream->sink->link; - if (resource_is_stream_unchanged(dc->current_context, stream)) + if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; for (j = 0; j < MAX_PIPES; j++) { @@ -757,7 +758,8 @@ enum dc_status dce80_validate_with_context( const struct core_dc *dc, const struct dc_validation_set set[], int set_count, - struct validate_context *context) + struct validate_context *context, + struct validate_context *old_context) { struct dc_context *dc_ctx = dc->ctx; enum dc_status result = DC_ERROR_UNEXPECTED; @@ -772,19 +774,19 @@ enum dc_status dce80_validate_with_context( context->stream_count++; } - result = resource_map_pool_resources(dc, context); + result = resource_map_pool_resources(dc, context, old_context); if (result == DC_OK) - result = resource_map_clock_resources(dc, context); + result = resource_map_clock_resources(dc, context, old_context); if (!resource_validate_attach_surfaces(set, set_count, - dc->current_context, context, dc->res_pool)) { + old_context, context, dc->res_pool)) { DC_ERROR("Failed to attach surface to stream!\n"); return DC_FAIL_ATTACH_SURFACES; } if (result == DC_OK) - result = validate_mapped_resource(dc, context); + result = validate_mapped_resource(dc, context, old_context); if (result == DC_OK) result = resource_build_scaling_params_for_context(dc, context); @@ -806,13 +808,13 @@ enum dc_status dce80_validate_guaranteed( dc_stream_retain(&context->streams[0]->public); context->stream_count++; - result = resource_map_pool_resources(dc, context); + result = resource_map_pool_resources(dc, context, NULL); if (result == DC_OK) - result = resource_map_clock_resources(dc, context); + result = resource_map_clock_resources(dc, context, NULL); if (result == DC_OK) - result = validate_mapped_resource(dc, context); + result = validate_mapped_resource(dc, context, NULL); if (result == DC_OK) { validate_guaranteed_copy_streams( diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 7fdc5860857b..94cd7a9b0b19 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -853,7 +853,8 @@ static enum dc_status build_pipe_hw_param(struct pipe_ctx *pipe_ctx) static enum dc_status validate_mapped_resource( const struct core_dc *dc, - struct validate_context *context) + struct validate_context *context, + struct validate_context *old_context) { enum dc_status status = DC_OK; uint8_t i, j; @@ -862,8 +863,8 @@ static enum dc_status validate_mapped_resource( struct core_stream *stream = context->streams[i]; struct core_link *link = stream->sink->link; - if (resource_is_stream_unchanged(dc->current_context, stream)) { - if (stream != NULL && dc->current_context->streams[i] != NULL) { + if (old_context && resource_is_stream_unchanged(old_context, stream)) { + if (stream != NULL && old_context->streams[i] != NULL) { /* todo: shouldn't have to copy missing parameter here */ resource_build_bit_depth_reduction_params(stream, &stream->bit_depth_params); @@ -920,7 +921,8 @@ enum dc_status dcn10_validate_with_context( const struct core_dc *dc, const struct dc_validation_set set[], int set_count, - struct validate_context *context) + struct validate_context *context, + struct validate_context *old_context) { enum dc_status result = DC_OK; int i; @@ -934,20 +936,20 @@ enum dc_status dcn10_validate_with_context( context->stream_count++; } - result = resource_map_pool_resources(dc, context); + result = resource_map_pool_resources(dc, context, old_context); if (result != DC_OK) return result; - result = resource_map_phy_clock_resources(dc, context); + result = resource_map_phy_clock_resources(dc, context, old_context); if (result != DC_OK) return result; - result = validate_mapped_resource(dc, context); + result = validate_mapped_resource(dc, context, old_context); if (result != DC_OK) return result; if (!resource_validate_attach_surfaces(set, set_count, - dc->current_context, context, dc->res_pool)) + old_context, context, dc->res_pool)) return DC_FAIL_ATTACH_SURFACES; result = resource_build_scaling_params_for_context(dc, context); @@ -971,13 +973,13 @@ enum dc_status dcn10_validate_guaranteed( dc_stream_retain(&context->streams[0]->public); context->stream_count++; - result = resource_map_pool_resources(dc, context); + result = resource_map_pool_resources(dc, context, NULL); if (result == DC_OK) - result = resource_map_phy_clock_resources(dc, context); + result = resource_map_phy_clock_resources(dc, context, NULL); if (result == DC_OK) - result = validate_mapped_resource(dc, context); + result = validate_mapped_resource(dc, context, NULL); if (result == DC_OK) { validate_guaranteed_copy_streams( diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 46bd0318e6be..d8a378dabb43 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -203,7 +203,8 @@ struct resource_funcs { const struct core_dc *dc, const struct dc_validation_set set[], int set_count, - struct validate_context *context); + struct validate_context *context, + struct validate_context *old_context); enum dc_status (*validate_guaranteed)( const struct core_dc *dc, diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index 4e07b9fea669..7cac24d4ae86 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -80,7 +80,8 @@ void dc_destroy_resource_pool(struct core_dc *dc); enum dc_status resource_map_pool_resources( const struct core_dc *dc, - struct validate_context *context); + struct validate_context *context, + struct validate_context *old_context); bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx); @@ -150,11 +151,13 @@ void resource_validate_ctx_update_pointer_after_copy( enum dc_status resource_map_clock_resources( const struct core_dc *dc, - struct validate_context *context); + struct validate_context *context, + struct validate_context *old_context); enum dc_status resource_map_phy_clock_resources( const struct core_dc *dc, - struct validate_context *context); + struct validate_context *context, + struct validate_context *old_context); bool pipe_need_reprogram( struct pipe_ctx *pipe_ctx_old, -- cgit From afc8935ef0fc04c87cd7e7749ff28c32be4f712a Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 17 May 2017 16:56:56 -0400 Subject: drm/amd/display: revert dc_get_validate_context re-entrancy fix Apply dc_get_validate_context re-entrancy fix to dc_validate_resources instead Signed-off-by: Dmytro Laktyushkin Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 71 ++++++++++++++++++++++++++++---- 1 file changed, 62 insertions(+), 9 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 0aafcc088284..773f0efc449b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -653,6 +653,40 @@ void dc_destroy(struct dc **dc) *dc = NULL; } +static bool is_validation_required( + const struct core_dc *dc, + const struct dc_validation_set set[], + int set_count) +{ + const struct validate_context *context = dc->current_context; + int i, j; + + if (context->stream_count != set_count) + return true; + + for (i = 0; i < set_count; i++) { + + if (set[i].surface_count != context->stream_status[i].surface_count) + return true; + if (!is_stream_unchanged(DC_STREAM_TO_CORE(set[i].stream), context->streams[i])) + return true; + + for (j = 0; j < set[i].surface_count; j++) { + struct dc_surface temp_surf = { 0 }; + + temp_surf = *context->stream_status[i].surfaces[j]; + temp_surf.clip_rect = set[i].surfaces[j]->clip_rect; + temp_surf.dst_rect.x = set[i].surfaces[j]->dst_rect.x; + temp_surf.dst_rect.y = set[i].surfaces[j]->dst_rect.y; + + if (memcmp(&temp_surf, set[i].surfaces[j], sizeof(temp_surf)) != 0) + return true; + } + } + + return false; +} + struct validate_context *dc_get_validate_context( const struct dc *dc, const struct dc_validation_set set[], @@ -663,11 +697,16 @@ struct validate_context *dc_get_validate_context( struct validate_context *context; context = dm_alloc(sizeof(struct validate_context)); - if(context == NULL) + if (context == NULL) goto context_alloc_fail; + if (!is_validation_required(core_dc, set, set_count)) { + dc_resource_validate_ctx_copy_construct(core_dc->current_context, context); + return context; + } + result = core_dc->res_pool->funcs->validate_with_context( - core_dc, set, set_count, context, NULL); + core_dc, set, set_count, context, core_dc->current_context); context_alloc_fail: if (result != DC_OK) { @@ -690,16 +729,30 @@ bool dc_validate_resources( const struct dc_validation_set set[], uint8_t set_count) { - struct validate_context *ctx; + struct core_dc *core_dc = DC_TO_CORE(dc); + enum dc_status result = DC_ERROR_UNEXPECTED; + struct validate_context *context; - ctx = dc_get_validate_context(dc, set, set_count); - if (ctx) { - dc_resource_validate_ctx_destruct(ctx); - dm_free(ctx); - return true; + context = dm_alloc(sizeof(struct validate_context)); + if (context == NULL) + goto context_alloc_fail; + + result = core_dc->res_pool->funcs->validate_with_context( + core_dc, set, set_count, context, NULL); + +context_alloc_fail: + if (result != DC_OK) { + dm_logger_write(core_dc->ctx->logger, LOG_WARNING, + "%s:resource validation failed, dc_status:%d\n", + __func__, + result); } - return false; + dc_resource_validate_ctx_destruct(context); + dm_free(context); + context = NULL; + + return result == DC_OK; } bool dc_validate_guaranteed( -- cgit From 98489c026edc48d9c783f783cc82f2e8811e0ee4 Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Tue, 16 May 2017 13:52:28 -0400 Subject: drm/amd/display: Refactor use_lut() from dce110 to dce use_lut() checks if the input surface's pixel format is compatible with a 256 entry LUT. This function can be used across different versions and not just dce11. Signed-off-by: Leo (Sunpeng) Li Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c | 12 ++++++++++++ drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h | 2 ++ .../gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 17 ++--------------- 3 files changed, 16 insertions(+), 15 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c index 34c18712970c..cc3178acfc54 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c @@ -191,3 +191,15 @@ void dce_crtc_switch_to_clk_src(struct dce_hwseq *hws, clk_src->id, tg_inst); } } + +/* Only use LUT for 8 bit formats */ +bool dce_use_lut(const struct core_surface *surface) +{ + switch (surface->public.format) { + case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: + return true; + default: + return false; + } +} diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index dd13f47b6446..112f9c85c142 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -256,4 +256,6 @@ void dce_clock_gating_power_up(struct dce_hwseq *hws, void dce_crtc_switch_to_clk_src(struct dce_hwseq *hws, struct clock_source *clk_src, unsigned int tg_inst); + +bool dce_use_lut(const struct core_surface *surface); #endif /*__DCE_HWSEQ_H__*/ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 20ad1cb263db..65c691569eb7 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -28,10 +28,10 @@ #include "core_types.h" #include "core_status.h" #include "resource.h" -#include "hw_sequencer.h" #include "dm_helpers.h" #include "dce110_hw_sequencer.h" #include "dce110_timing_generator.h" +#include "dce/dce_hwseq.h" #include "bios/bios_parser_helper.h" #include "timing_generator.h" @@ -233,19 +233,6 @@ static void build_prescale_params(struct ipp_prescale_params *prescale_params, } } - -/* Only use LUT for 8 bit formats */ -static bool use_lut(const struct core_surface *surface) -{ - switch (surface->public.format) { - case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: - case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: - return true; - default: - return false; - } -} - static bool dce110_set_input_transfer_func( struct pipe_ctx *pipe_ctx, const struct core_surface *surface) @@ -264,7 +251,7 @@ static bool dce110_set_input_transfer_func( build_prescale_params(&prescale_params, surface); ipp->funcs->ipp_program_prescale(ipp, &prescale_params); - if (surface->public.gamma_correction && use_lut(surface)) + if (surface->public.gamma_correction && dce_use_lut(surface)) ipp->funcs->ipp_program_input_lut(ipp, surface->public.gamma_correction); if (tf == NULL) { -- cgit From 5aff86c1b3259f1443e0b35b74eb6dfd5b35791b Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Tue, 16 May 2017 16:07:30 -0400 Subject: drm/amd/display: Implement input gamma LUT 1. Implemented dcn10_ipp_program_input_lut(), following the existing interface. 2. Added missing registers as needed 3. Change to REG_GET for *ram_select() funcs. 4. Removed gamma table init from DiagsDM::make_surface() for resolving CRC errors. Reason: Legacy LUT will be deprecated soon for Raven in favor of degamma/regamma. Signed-off-by: Leo (Sunpeng) Li Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 6 +- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c | 82 +++++++++++++++++++++- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h | 22 ++++++ 3 files changed, 108 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 28b47bed72cf..62a77f48d437 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -29,9 +29,9 @@ #include "core_types.h" #include "core_status.h" #include "resource.h" -#include "hw_sequencer.h" #include "dcn10_hw_sequencer.h" #include "dce110/dce110_hw_sequencer.h" +#include "dce/dce_hwseq.h" #include "abm.h" #include "dcn10/dcn10_transform.h" @@ -952,6 +952,10 @@ static bool dcn10_set_input_transfer_func( if (surface->public.in_transfer_func) tf = DC_TRANSFER_FUNC_TO_CORE(surface->public.in_transfer_func); + if (surface->public.gamma_correction && dce_use_lut(surface)) + ipp->funcs->ipp_program_input_lut(ipp, + surface->public.gamma_correction); + if (tf == NULL) ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS); else if (tf->public.type == TF_TYPE_PREDEFINED) { diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c index 082c98c11293..1e7a55d9e9ec 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c @@ -814,7 +814,9 @@ static bool dcn10_degamma_ram_inuse(struct input_pixel_processor *ipp, uint32_t status_reg = 0; struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); - status_reg = (REG_READ(CM_IGAM_LUT_RW_CONTROL) & 0x0F00) >>16; + REG_GET(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_DGAM_CONFIG_STATUS, + &status_reg); + if (status_reg == 9) { *ram_a_inuse = true; ret = true; @@ -825,6 +827,28 @@ static bool dcn10_degamma_ram_inuse(struct input_pixel_processor *ipp, return ret; } +static bool dcn10_ingamma_ram_inuse(struct input_pixel_processor *ipp, + bool *ram_a_inuse) +{ + bool in_use = false; + uint32_t status_reg = 0; + struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); + + REG_GET(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_DGAM_CONFIG_STATUS, + &status_reg); + + // 1 => IGAM_RAMA, 3 => IGAM_RAMA & DGAM_ROMA, 4 => IGAM_RAMA & DGAM_ROMB + if (status_reg == 1 || status_reg == 3 || status_reg == 4) { + *ram_a_inuse = true; + in_use = true; + // 2 => IGAM_RAMB, 5 => IGAM_RAMB & DGAM_ROMA, 6 => IGAM_RAMB & DGAM_ROMB + } else if (status_reg == 2 || status_reg == 5 || status_reg == 6) { + *ram_a_inuse = false; + in_use = true; + } + return in_use; +} + static void dcn10_degamma_ram_select(struct input_pixel_processor *ipp, bool use_ram_a) { @@ -855,6 +879,61 @@ static void dcn10_ipp_set_degamma_pwl(struct input_pixel_processor *ipp, dcn10_degamma_ram_select(ipp, !is_ram_a); } +/* + * Input gamma LUT currently supports 256 values only. This means input color + * can have a maximum of 8 bits per channel (= 256 possible values) in order to + * have a one-to-one mapping with the LUT. Truncation will occur with color + * values greater than 8 bits. + * + * In the future, this function should support additional input gamma methods, + * such as piecewise linear mapping, and input gamma bypass. + */ +void dcn10_ipp_program_input_lut( + struct input_pixel_processor *ipp, + const struct dc_gamma *gamma) +{ + int i; + struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); + bool rama_occupied = false; + uint32_t ram_num; + // Power on LUT memory. + REG_SET(CM_MEM_PWR_CTRL, 0, SHARED_MEM_PWR_DIS, 1); + dcn10_ipp_enable_cm_block(ipp); + // Determine whether to use RAM A or RAM B + dcn10_ingamma_ram_inuse(ipp, &rama_occupied); + if (!rama_occupied) + REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_SEL, 0); + else + REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_SEL, 1); + // RW mode is 256-entry LUT + REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_RW_MODE, 0); + // IGAM Input format should be 8 bits per channel. + REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_INPUT_FORMAT, 0); + // Do not mask any R,G,B values + REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_WRITE_EN_MASK, 7); + // LUT-256, unsigned, integer, new u0.12 format + REG_UPDATE_3( + CM_IGAM_CONTROL, + CM_IGAM_LUT_FORMAT_R, 3, + CM_IGAM_LUT_FORMAT_G, 3, + CM_IGAM_LUT_FORMAT_B, 3); + // Start at index 0 of IGAM LUT + REG_UPDATE(CM_IGAM_LUT_RW_INDEX, CM_IGAM_LUT_RW_INDEX, 0); + for (i = 0; i < INPUT_LUT_ENTRIES; i++) { + REG_SET(CM_IGAM_LUT_SEQ_COLOR, 0, CM_IGAM_LUT_SEQ_COLOR, + gamma->red[i]); + REG_SET(CM_IGAM_LUT_SEQ_COLOR, 0, CM_IGAM_LUT_SEQ_COLOR, + gamma->green[i]); + REG_SET(CM_IGAM_LUT_SEQ_COLOR, 0, CM_IGAM_LUT_SEQ_COLOR, + gamma->blue[i]); + } + // Power off LUT memory + REG_SET(CM_MEM_PWR_CTRL, 0, SHARED_MEM_PWR_DIS, 0); + // Enable IGAM LUT on ram we just wrote to. 2 => RAMA, 3 => RAMB + REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, rama_occupied ? 3 : 2); + REG_GET(CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, &ram_num); +} + /*****************************************/ /* Constructor, Destructor */ /*****************************************/ @@ -869,6 +948,7 @@ static const struct ipp_funcs dcn10_ipp_funcs = { .ipp_cursor_set_attributes = dcn10_cursor_set_attributes, .ipp_cursor_set_position = dcn10_cursor_set_position, .ipp_set_degamma = dcn10_ipp_set_degamma, + .ipp_program_input_lut = dcn10_ipp_program_input_lut, .ipp_full_bypass = dcn10_ipp_full_bypass, .ipp_setup = dcn10_ipp_cnv_setup, .ipp_program_degamma_pwl = dcn10_ipp_set_degamma_pwl, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h index a4ea4e774c72..511993519740 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h @@ -87,6 +87,8 @@ SRI(CM_DGAM_RAMA_REGION_14_15, CM, id), \ SRI(CM_MEM_PWR_CTRL, CM, id), \ SRI(CM_IGAM_LUT_RW_CONTROL, CM, id), \ + SRI(CM_IGAM_LUT_RW_INDEX, CM, id), \ + SRI(CM_IGAM_LUT_SEQ_COLOR, CM, id), \ SRI(CM_DGAM_LUT_WRITE_EN_MASK, CM, id), \ SRI(CM_DGAM_LUT_INDEX, CM, id), \ SRI(CM_DGAM_LUT_DATA, CM, id), \ @@ -238,7 +240,13 @@ IPP_SF(CM0_CM_DGAM_RAMA_REGION_14_15, CM_DGAM_RAMA_EXP_REGION15_LUT_OFFSET, mask_sh), \ IPP_SF(CM0_CM_DGAM_RAMA_REGION_14_15, CM_DGAM_RAMA_EXP_REGION15_NUM_SEGMENTS, mask_sh), \ IPP_SF(CM0_CM_MEM_PWR_CTRL, SHARED_MEM_PWR_DIS, mask_sh), \ + IPP_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_DGAM_CONFIG_STATUS, mask_sh), \ IPP_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_HOST_EN, mask_sh), \ + IPP_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_RW_MODE, mask_sh), \ + IPP_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_SEL, mask_sh), \ + IPP_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_WRITE_EN_MASK, mask_sh), \ + IPP_SF(CM0_CM_IGAM_LUT_RW_INDEX, CM_IGAM_LUT_RW_INDEX, mask_sh), \ + IPP_SF(CM0_CM_IGAM_LUT_SEQ_COLOR, CM_IGAM_LUT_SEQ_COLOR, mask_sh), \ IPP_SF(CM0_CM_DGAM_LUT_WRITE_EN_MASK, CM_DGAM_LUT_WRITE_EN_MASK, mask_sh), \ IPP_SF(CM0_CM_DGAM_LUT_WRITE_EN_MASK, CM_DGAM_LUT_WRITE_SEL, mask_sh), \ IPP_SF(CM0_CM_DGAM_LUT_INDEX, CM_DGAM_LUT_INDEX, mask_sh), \ @@ -251,6 +259,9 @@ IPP_SF(CNVC_CFG0_FORMAT_CONTROL, FORMAT_EXPANSION_MODE, mask_sh), \ IPP_SF(CM0_CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, mask_sh), \ IPP_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, mask_sh), \ + IPP_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_LUT_FORMAT_R, mask_sh), \ + IPP_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_LUT_FORMAT_G, mask_sh), \ + IPP_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_LUT_FORMAT_B, mask_sh), \ IPP_SF(HUBPREQ0_CURSOR_SETTINS, CURSOR0_DST_Y_OFFSET, mask_sh), \ IPP_SF(HUBPREQ0_CURSOR_SETTINS, CURSOR0_CHUNK_HDL_ADJUST, mask_sh), \ IPP_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_MODE, mask_sh), \ @@ -404,7 +415,16 @@ type CM_DGAM_RAMA_EXP_REGION15_LUT_OFFSET; \ type CM_DGAM_RAMA_EXP_REGION15_NUM_SEGMENTS; \ type SHARED_MEM_PWR_DIS; \ + type CM_IGAM_LUT_FORMAT_R; \ + type CM_IGAM_LUT_FORMAT_G; \ + type CM_IGAM_LUT_FORMAT_B; \ type CM_IGAM_LUT_HOST_EN; \ + type CM_IGAM_LUT_RW_INDEX; \ + type CM_IGAM_LUT_RW_MODE; \ + type CM_IGAM_LUT_WRITE_EN_MASK; \ + type CM_IGAM_LUT_SEL; \ + type CM_IGAM_LUT_SEQ_COLOR; \ + type CM_IGAM_DGAM_CONFIG_STATUS; \ type CM_DGAM_LUT_WRITE_EN_MASK; \ type CM_DGAM_LUT_WRITE_SEL; \ type CM_DGAM_LUT_INDEX; \ @@ -507,6 +527,8 @@ struct dcn10_ipp_registers { uint32_t CM_DGAM_RAMA_REGION_14_15; uint32_t CM_MEM_PWR_CTRL; uint32_t CM_IGAM_LUT_RW_CONTROL; + uint32_t CM_IGAM_LUT_RW_INDEX; + uint32_t CM_IGAM_LUT_SEQ_COLOR; uint32_t CM_DGAM_LUT_WRITE_EN_MASK; uint32_t CM_DGAM_LUT_INDEX; uint32_t CM_DGAM_LUT_DATA; -- cgit From 7b9454f51ec1e04f7842a9412df568f98371b01c Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Wed, 17 May 2017 18:05:36 -0400 Subject: drm/amd/display: Add missed wait_for_prev_commits. Signed-off-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index d6ea2d5726dd..b76f0f7e5594 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -3111,6 +3111,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, surface); need_to_validate = true; + wait_for_prev_commits = true; } } } -- cgit From 0a5c357a85e99eae6b1914272bc2cf8f49cf511b Mon Sep 17 00:00:00 2001 From: Ayyappa Chandolu Date: Fri, 12 May 2017 17:05:55 +0530 Subject: drm/amd/display: Fix ASSR enablement on DP to EDP converter ASSR mode is not enable when we connect eDP panel via DP to eDP converter. connector_signal is coming as SIGNAL_TYPE_DISPLAY_PORT. Present code ignoring panel_mode_edp for SIGNAL_TYPE_DISPLAY_PORT. Added checking panel_mode_edp for all signals. Signed-off-by: Ayyappa Chandolu Reviewed-by: Tony Cheng Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 316df150c1d9..4f46ff14fb69 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -203,10 +203,10 @@ enum dp_panel_mode dp_get_panel_mode(struct core_link *link) default: break; } + } - if (link->dpcd_caps.panel_mode_edp) { - return DP_PANEL_MODE_EDP; - } + if (link->dpcd_caps.panel_mode_edp) { + return DP_PANEL_MODE_EDP; } return DP_PANEL_MODE_DEFAULT; -- cgit From a4b0a5b84827b1bceb99c3c2aa354073cc5bfb53 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Tue, 16 May 2017 10:22:00 -0400 Subject: drm/amd/display: Tidy up dce120_timing_generator_enable_advanced_request() Simplify the function by removing identical looking code blocks. Signed-off-by: Tom St Denis Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../display/dc/dce120/dce120_timing_generator.c | 37 +++++++--------------- 1 file changed, 12 insertions(+), 25 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c index dc8eeac6ac96..13cc0d49e007 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c @@ -669,36 +669,23 @@ void dce120_timing_generator_enable_advanced_request( mmCRTC0_CRTC_START_LINE_CONTROL, tg110->offsets.crtc); - - if (enable) { - set_reg_field_value( - value, - 0, - CRTC0_CRTC_START_LINE_CONTROL, - CRTC_LEGACY_REQUESTOR_EN); - } else { - set_reg_field_value( - value, - 1, - CRTC0_CRTC_START_LINE_CONTROL, - CRTC_LEGACY_REQUESTOR_EN); - } + set_reg_field_value( + value, + enable ? 0 : 1, + CRTC0_CRTC_START_LINE_CONTROL, + CRTC_LEGACY_REQUESTOR_EN); /* Program advanced line position acc.to the best case from fetching data perspective to hide MC latency * and prefilling Line Buffer in V Blank (to 10 lines as LB can store max 10 lines) */ if (v_sync_width_and_b_porch > 10) - set_reg_field_value( - value, - 10, - CRTC0_CRTC_START_LINE_CONTROL, - CRTC_ADVANCED_START_LINE_POSITION); - else - set_reg_field_value( - value, - v_sync_width_and_b_porch, - CRTC0_CRTC_START_LINE_CONTROL, - CRTC_ADVANCED_START_LINE_POSITION); + v_sync_width_and_b_porch = 10; + + set_reg_field_value( + value, + v_sync_width_and_b_porch, + CRTC0_CRTC_START_LINE_CONTROL, + CRTC_ADVANCED_START_LINE_POSITION); dm_write_reg_soc15(tg->ctx, mmCRTC0_CRTC_START_LINE_CONTROL, -- cgit From 78178dea7a92a611262edad73a548ffe7087a347 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Tue, 16 May 2017 10:22:01 -0400 Subject: drm/amd/display: Fix indentation in dce120_tg_program_timing() Signed-off-by: Tom St Denis Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c index 13cc0d49e007..1c25dc66ff4f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c @@ -733,9 +733,9 @@ void dce120_tg_program_timing(struct timing_generator *tg, bool use_vbios) { if (use_vbios) - dce110_timing_generator_program_timing_generator(tg, timing); - else - dce120_timing_generator_program_blanking(tg, timing); + dce110_timing_generator_program_timing_generator(tg, timing); + else + dce120_timing_generator_program_blanking(tg, timing); } bool dce120_tg_is_blanked(struct timing_generator *tg) -- cgit From 7b7d68659e3007a30d04d51e1c8bbd1fa8b6de3e Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Tue, 16 May 2017 10:22:02 -0400 Subject: drm/amd/display: Make dce120_tg_is_blanked() more legible Signed-off-by: Tom St Denis Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dce120/dce120_timing_generator.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c index 1c25dc66ff4f..1e2843e5d97e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c @@ -746,15 +746,14 @@ bool dce120_tg_is_blanked(struct timing_generator *tg) mmCRTC0_CRTC_BLANK_CONTROL, tg110->offsets.crtc); - if ( - get_reg_field_value( - value, - CRTC0_CRTC_BLANK_CONTROL, - CRTC_BLANK_DATA_EN) == 1 && - get_reg_field_value( - value, - CRTC0_CRTC_BLANK_CONTROL, - CRTC_CURRENT_BLANK_STATE) == 1) + if (get_reg_field_value( + value, + CRTC0_CRTC_BLANK_CONTROL, + CRTC_BLANK_DATA_EN) == 1 && + get_reg_field_value( + value, + CRTC0_CRTC_BLANK_CONTROL, + CRTC_CURRENT_BLANK_STATE) == 1) return true; return false; -- cgit From cedaf3073a33a95e276371783b20a14e208e184c Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Tue, 16 May 2017 10:22:03 -0400 Subject: drm/amd/display: Clean up indentation in dce120_tg_set_blank() Signed-off-by: Tom St Denis Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dce120/dce120_timing_generator.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c index 1e2843e5d97e..c208196864ad 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c @@ -768,17 +768,11 @@ void dce120_tg_set_blank(struct timing_generator *tg, CRTC0_CRTC_DOUBLE_BUFFER_CONTROL, CRTC_BLANK_DATA_DOUBLE_BUFFER_EN, 0); - if (enable_blanking) { - CRTC_REG_SET( - CRTC0_CRTC_BLANK_CONTROL, - CRTC_BLANK_DATA_EN, 1); - - } else - dm_write_reg_soc15( - tg->ctx, - mmCRTC0_CRTC_BLANK_CONTROL, - tg110->offsets.crtc, - 0); + if (enable_blanking) + CRTC_REG_SET(CRTC0_CRTC_BLANK_CONTROL, CRTC_BLANK_DATA_EN, 1); + else + dm_write_reg_soc15(tg->ctx, mmCRTC0_CRTC_BLANK_CONTROL, + tg110->offsets.crtc, 0); } bool dce120_tg_validate_timing(struct timing_generator *tg, -- cgit From 76fd8eb8e2282c695c43683802772caa187bf41b Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Tue, 16 May 2017 10:22:04 -0400 Subject: drm/amd/display: Tidy up dce120_clock_source_create() Also change sizeof to be automatic based on type declaration. Signed-off-by: Tom St Denis Reviewed-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index 1276dabfb208..ec485353ea4f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -398,13 +398,13 @@ struct clock_source *dce120_clock_source_create( bool dp_clk_src) { struct dce110_clk_src *clk_src = - dm_alloc(sizeof(struct dce110_clk_src)); + dm_alloc(sizeof(*clk_src)); if (!clk_src) return NULL; if (dce110_clk_src_construct(clk_src, ctx, bios, id, - regs, &cs_shift, &cs_mask)) { + regs, &cs_shift, &cs_mask)) { clk_src->base.dp_clk_src = dp_clk_src; return &clk_src->base; } -- cgit From 0b3454b7c49bfc6aa7a1096d1aa9d059201a73a7 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Tue, 16 May 2017 10:22:05 -0400 Subject: drm/amd/display: Tidy up mem_input_program_surface_flip_and_addr() Signed-off-by: Tom St Denis Reviewed-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c | 25 ++++++++-------------- 1 file changed, 9 insertions(+), 16 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c index 718688c41f7b..673371e5f9f0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c @@ -625,18 +625,12 @@ static bool dce_mi_program_surface_flip_and_addr( * non-XDMA Mode: GRPH_SURFACE_UPDATE_IMMEDIATE_EN = 1 * XDMA Mode: GRPH_SURFACE_UPDATE_H_RETRACE_EN = 1 */ - REG_UPDATE(GRPH_UPDATE, - GRPH_UPDATE_LOCK, 1); - - if (flip_immediate) { - REG_UPDATE_2(GRPH_FLIP_CONTROL, - GRPH_SURFACE_UPDATE_IMMEDIATE_EN, 0, - GRPH_SURFACE_UPDATE_H_RETRACE_EN, 1); - } else { - REG_UPDATE_2(GRPH_FLIP_CONTROL, - GRPH_SURFACE_UPDATE_IMMEDIATE_EN, 0, - GRPH_SURFACE_UPDATE_H_RETRACE_EN, 0); - } + REG_UPDATE(GRPH_UPDATE, GRPH_UPDATE_LOCK, 1); + + REG_UPDATE_2( + GRPH_FLIP_CONTROL, + GRPH_SURFACE_UPDATE_IMMEDIATE_EN, 0, + GRPH_SURFACE_UPDATE_H_RETRACE_EN, flip_immediate ? 1 : 0); switch (address->type) { case PLN_ADDR_TYPE_GRAPHICS: @@ -645,8 +639,8 @@ static bool dce_mi_program_surface_flip_and_addr( program_pri_addr(dce_mi, address->grph.addr); break; case PLN_ADDR_TYPE_GRPH_STEREO: - if (address->grph_stereo.left_addr.quad_part == 0 - || address->grph_stereo.right_addr.quad_part == 0) + if (address->grph_stereo.left_addr.quad_part == 0 || + address->grph_stereo.right_addr.quad_part == 0) break; program_pri_addr(dce_mi, address->grph_stereo.left_addr); program_sec_addr(dce_mi, address->grph_stereo.right_addr); @@ -662,8 +656,7 @@ static bool dce_mi_program_surface_flip_and_addr( if (flip_immediate) mem_input->current_address = *address; - REG_UPDATE(GRPH_UPDATE, - GRPH_UPDATE_LOCK, 0); + REG_UPDATE(GRPH_UPDATE, GRPH_UPDATE_LOCK, 0); return true; } -- cgit From f1000642e48166322194529a6d0f2452934acf2a Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Thu, 18 May 2017 11:03:17 -0400 Subject: drm/amd/display: Query for update plane type. Use DC interface to query for plane update type so in case of FULL update you flush any outstanding commits. Signed-off-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 69 +++++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index b76f0f7e5594..a5b7c054d853 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2867,6 +2867,61 @@ static uint32_t remove_from_val_sets( return set_count; } + +static enum surface_update_type amdgpu_dm_check_surfaces_update_type( + struct dc *dc, + const struct dc_surface **new_surfaces, + uint8_t new_surface_count, + const struct dc_stream *dc_stream) +{ + struct dc_surface_update srf_updates[MAX_SURFACES]; + struct dc_flip_addrs flip_addr[MAX_SURFACES]; + struct dc_plane_info plane_info[MAX_SURFACES]; + struct dc_scaling_info scaling_info[MAX_SURFACES]; + int i; + const struct dc_stream_status *stream_status = + dc_stream_get_status(dc_stream); + enum surface_update_type update_type; + + ASSERT(stream_status); + + + memset(srf_updates, 0, sizeof(srf_updates)); + memset(flip_addr, 0, sizeof(flip_addr)); + memset(plane_info, 0, sizeof(plane_info)); + memset(scaling_info, 0, sizeof(scaling_info)); + + for (i = 0; i < new_surface_count; i++) { + srf_updates[i].surface = new_surfaces[i]; + srf_updates[i].gamma = + (struct dc_gamma *)new_surfaces[i]->gamma_correction; + flip_addr[i].address = new_surfaces[i]->address; + flip_addr[i].flip_immediate = new_surfaces[i]->flip_immediate; + plane_info[i].color_space = new_surfaces[i]->color_space; + plane_info[i].format = new_surfaces[i]->format; + plane_info[i].plane_size = new_surfaces[i]->plane_size; + plane_info[i].rotation = new_surfaces[i]->rotation; + plane_info[i].horizontal_mirror = new_surfaces[i]->horizontal_mirror; + plane_info[i].stereo_format = new_surfaces[i]->stereo_format; + plane_info[i].tiling_info = new_surfaces[i]->tiling_info; + plane_info[i].visible = new_surfaces[i]->visible; + plane_info[i].dcc = new_surfaces[i]->dcc; + scaling_info[i].scaling_quality = new_surfaces[i]->scaling_quality; + scaling_info[i].src_rect = new_surfaces[i]->src_rect; + scaling_info[i].dst_rect = new_surfaces[i]->dst_rect; + scaling_info[i].clip_rect = new_surfaces[i]->clip_rect; + + srf_updates[i].flip_addr = &flip_addr[i]; + srf_updates[i].plane_info = &plane_info[i]; + srf_updates[i].scaling_info = &scaling_info[i]; + } + + update_type = dc_check_update_surfaces_for_stream( + dc, srf_updates, new_surface_count, NULL, stream_status); + + return update_type; +} + int amdgpu_dm_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) { @@ -3111,13 +3166,25 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, surface); need_to_validate = true; - wait_for_prev_commits = true; } } } context = dc_get_validate_context(dc, set, set_count); + for (i = 0; i < set_count; i++) { + for (j = 0; j < set[i].surface_count; j++) { + if (amdgpu_dm_check_surfaces_update_type( + dc, + set[i].surfaces, + set[i].surface_count, + set[i].stream) > UPDATE_TYPE_MED) { + wait_for_prev_commits = true; + break; + } + } + } + if (need_to_validate == false || set_count == 0 || context) { ret = 0; -- cgit From 83dc211702cb18e62741379fef48f2629b1c983c Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Thu, 18 May 2017 13:35:22 -0400 Subject: drm/amd/display: Remove redundant condition. You cannot have modeset and flip in the same call for same CRTC, in such case it will be set mode and set plane, not a flip. Signed-off-by: Andrey Grodzovsky Reviewed-by: Andrey Grodzovsky Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index a5b7c054d853..b3a4605858c1 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -3115,15 +3115,9 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, action = get_dm_commit_action(crtc->state); - /* Surfaces are created under two scenarios: - * 1. This commit is not a page flip. - * 2. This commit is a page flip, and streams are created. - */ crtc_state = drm_atomic_get_crtc_state(state, crtc); pflip_needed = !state->allow_modeset; - if (!pflip_needed || - action == DM_COMMIT_ACTION_DPMS_ON || - action == DM_COMMIT_ACTION_SET) { + if (!pflip_needed) { struct dc_surface *surface; list_for_each_entry(connector, -- cgit From 89c872e595c48ccf357bbabcc9918bdef9de7ac8 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Thu, 18 May 2017 19:03:15 -0400 Subject: drm/amd/display: fix YUV surface address programming sequence need to program DCSURF_PRIMARY_SURFACE_ADDRESS last as HW automatically latch rest of addr regs on write when SURFACE_UPDATE_LOCK is not used Signed-off-by: Tony Cheng Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c | 42 +++++++++++----------- 1 file changed, 20 insertions(+), 22 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index 587ded13140b..a52c614ec5b4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -237,16 +237,23 @@ static bool mem_input_program_surface_flip_and_addr( struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); /* program flip type */ - REG_UPDATE(DCSURF_FLIP_CONTROL, SURFACE_FLIP_TYPE, flip_immediate); - /* REG_UPDATE(FLIP_CONTROL, SURFACE_UPDATE_LOCK, 1); */ - - - /* program high first and then the low addr, order matters! */ + /* HW automatically latch rest of address register on write to + * DCSURF_PRIMARY_SURFACE_ADDRESS if SURFACE_UPDATE_LOCK is not used + * + * program high first and then the low addr, order matters! + */ switch (address->type) { case PLN_ADDR_TYPE_GRAPHICS: + /* DCN1.0 does not support const color + * TODO: program DCHUBBUB_RET_PATH_DCC_CFGx_0/1 + * base on address->grph.dcc_const_color + * x = 0, 2, 4, 6 for pipe 0, 1, 2, 3 for rgb and luma + * x = 1, 3, 5, 7 for pipe 0, 1, 2, 3 for chroma + */ + if (address->grph.addr.quad_part == 0) break; @@ -268,14 +275,6 @@ static bool mem_input_program_surface_flip_and_addr( REG_UPDATE(DCSURF_PRIMARY_SURFACE_ADDRESS, PRIMARY_SURFACE_ADDRESS, address->grph.addr.low_part); - - - /* DCN1.0 does not support const color - * TODO: program DCHUBBUB_RET_PATH_DCC_CFGx_0/1 - * base on address->grph.dcc_const_color - * x = 0, 2, 4, 6 for pipe 0, 1, 2, 3 for rgb and luma - * x = 1, 3, 5, 7 for pipe 0, 1, 2, 3 for chroma - */ break; case PLN_ADDR_TYPE_VIDEO_PROGRESSIVE: if (address->video_progressive.luma_addr.quad_part == 0 @@ -301,14 +300,6 @@ static bool mem_input_program_surface_flip_and_addr( address->video_progressive.chroma_meta_addr.low_part); } - REG_UPDATE(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, - PRIMARY_SURFACE_ADDRESS_HIGH, - address->video_progressive.luma_addr.high_part); - - REG_UPDATE(DCSURF_PRIMARY_SURFACE_ADDRESS, - PRIMARY_SURFACE_ADDRESS, - address->video_progressive.luma_addr.low_part); - REG_UPDATE(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C, PRIMARY_SURFACE_ADDRESS_HIGH_C, address->video_progressive.chroma_addr.high_part); @@ -317,6 +308,14 @@ static bool mem_input_program_surface_flip_and_addr( PRIMARY_SURFACE_ADDRESS_C, address->video_progressive.chroma_addr.low_part); + REG_UPDATE(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, + PRIMARY_SURFACE_ADDRESS_HIGH, + address->video_progressive.luma_addr.high_part); + + REG_UPDATE(DCSURF_PRIMARY_SURFACE_ADDRESS, + PRIMARY_SURFACE_ADDRESS, + address->video_progressive.luma_addr.low_part); + break; case PLN_ADDR_TYPE_GRPH_STEREO: if (address->grph_stereo.left_addr.quad_part == 0) @@ -365,7 +364,6 @@ static bool mem_input_program_surface_flip_and_addr( BREAK_TO_DEBUGGER(); break; } - /* REG_UPDATE(FLIP_CONTROL, SURFACE_UPDATE_LOCK, 0); */ mem_input->request_address = *address; -- cgit From a7562ab35ee96810e9e4c41969a375f1c3f249ae Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Thu, 18 May 2017 17:02:43 -0400 Subject: drm/amd/display: remove GRPH_SURFACE_UPDATE_IMMEDIATE_EN field programming This is causing asserts for dce 8 and 10 since they do not contain this field. It is also unnecessary for later DCEs as it is left in it's default state of 0 Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c | 7 +------ drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h | 2 -- 2 files changed, 1 insertion(+), 8 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c index 673371e5f9f0..157f4e1680e3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c @@ -621,15 +621,10 @@ static bool dce_mi_program_surface_flip_and_addr( { struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mem_input); - /* TODO: Figure out if two modes are needed: - * non-XDMA Mode: GRPH_SURFACE_UPDATE_IMMEDIATE_EN = 1 - * XDMA Mode: GRPH_SURFACE_UPDATE_H_RETRACE_EN = 1 - */ REG_UPDATE(GRPH_UPDATE, GRPH_UPDATE_LOCK, 1); - REG_UPDATE_2( + REG_UPDATE( GRPH_FLIP_CONTROL, - GRPH_SURFACE_UPDATE_IMMEDIATE_EN, 0, GRPH_SURFACE_UPDATE_H_RETRACE_EN, flip_immediate ? 1 : 0); switch (address->type) { diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h index 9d083cd79b4c..05d39c0cbe87 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h @@ -162,7 +162,6 @@ struct dce_mem_input_registers { SFB(blk, GRPH_FLIP_CONTROL, GRPH_SURFACE_UPDATE_H_RETRACE_EN, mask_sh) #define MI_DCP_DCE11_MASK_SH_LIST(mask_sh, blk)\ - SFB(blk, GRPH_FLIP_CONTROL, GRPH_SURFACE_UPDATE_IMMEDIATE_EN, mask_sh),\ SFB(blk, GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT, GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT, mask_sh) #define MI_DCP_PTE_MASK_SH_LIST(mask_sh, blk)\ @@ -278,7 +277,6 @@ struct dce_mem_input_registers { type GRPH_PRIMARY_SURFACE_ADDRESS_HIGH; \ type GRPH_PRIMARY_SURFACE_ADDRESS; \ type GRPH_SURFACE_UPDATE_PENDING; \ - type GRPH_SURFACE_UPDATE_IMMEDIATE_EN; \ type GRPH_SURFACE_UPDATE_H_RETRACE_EN; \ type GRPH_UPDATE_LOCK; \ type PIXEL_DURATION; \ -- cgit From d9e8887860c93cf5b8785d7d35a411a1636cfcaf Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Thu, 18 May 2017 16:56:45 -0400 Subject: drm/amd/display: fix flip register write sequence Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c | 56 ++++++++++------------ .../gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h | 2 + 2 files changed, 28 insertions(+), 30 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index a52c614ec5b4..da2f99dcd766 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -237,7 +237,7 @@ static bool mem_input_program_surface_flip_and_addr( struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); /* program flip type */ - REG_UPDATE(DCSURF_FLIP_CONTROL, + REG_SET(DCSURF_FLIP_CONTROL, 0, SURFACE_FLIP_TYPE, flip_immediate); /* HW automatically latch rest of address register on write to @@ -258,21 +258,20 @@ static bool mem_input_program_surface_flip_and_addr( break; if (address->grph.meta_addr.quad_part != 0) { - - REG_UPDATE(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, 0, PRIMARY_META_SURFACE_ADDRESS_HIGH, address->grph.meta_addr.high_part); - REG_UPDATE(DCSURF_PRIMARY_META_SURFACE_ADDRESS, + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS, 0, PRIMARY_META_SURFACE_ADDRESS, address->grph.meta_addr.low_part); } - REG_UPDATE(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, 0, PRIMARY_SURFACE_ADDRESS_HIGH, address->grph.addr.high_part); - REG_UPDATE(DCSURF_PRIMARY_SURFACE_ADDRESS, + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS, 0, PRIMARY_SURFACE_ADDRESS, address->grph.addr.low_part); break; @@ -282,40 +281,38 @@ static bool mem_input_program_surface_flip_and_addr( break; if (address->video_progressive.luma_meta_addr.quad_part != 0) { + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C, 0, + PRIMARY_META_SURFACE_ADDRESS_HIGH_C, + address->video_progressive.chroma_meta_addr.high_part); - REG_UPDATE(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_C, 0, + PRIMARY_META_SURFACE_ADDRESS_C, + address->video_progressive.chroma_meta_addr.low_part); + + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, 0, PRIMARY_META_SURFACE_ADDRESS_HIGH, address->video_progressive.luma_meta_addr.high_part); - REG_UPDATE(DCSURF_PRIMARY_META_SURFACE_ADDRESS, + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS, 0, PRIMARY_META_SURFACE_ADDRESS, address->video_progressive.luma_meta_addr.low_part); - - REG_UPDATE(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C, - PRIMARY_META_SURFACE_ADDRESS_HIGH_C, - address->video_progressive.chroma_meta_addr.high_part); - - REG_UPDATE(DCSURF_PRIMARY_META_SURFACE_ADDRESS_C, - PRIMARY_META_SURFACE_ADDRESS_C, - address->video_progressive.chroma_meta_addr.low_part); } - REG_UPDATE(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C, + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C, 0, PRIMARY_SURFACE_ADDRESS_HIGH_C, address->video_progressive.chroma_addr.high_part); - REG_UPDATE(DCSURF_PRIMARY_SURFACE_ADDRESS_C, + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_C, 0, PRIMARY_SURFACE_ADDRESS_C, address->video_progressive.chroma_addr.low_part); - REG_UPDATE(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, 0, PRIMARY_SURFACE_ADDRESS_HIGH, address->video_progressive.luma_addr.high_part); - REG_UPDATE(DCSURF_PRIMARY_SURFACE_ADDRESS, + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS, 0, PRIMARY_SURFACE_ADDRESS, address->video_progressive.luma_addr.low_part); - break; case PLN_ADDR_TYPE_GRPH_STEREO: if (address->grph_stereo.left_addr.quad_part == 0) @@ -324,39 +321,38 @@ static bool mem_input_program_surface_flip_and_addr( break; if (address->grph_stereo.right_meta_addr.quad_part != 0) { - REG_UPDATE(DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH, + REG_SET(DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH, 0, SECONDARY_META_SURFACE_ADDRESS_HIGH, address->grph_stereo.right_meta_addr.high_part); - REG_UPDATE(DCSURF_SECONDARY_META_SURFACE_ADDRESS, + REG_SET(DCSURF_SECONDARY_META_SURFACE_ADDRESS, 0, SECONDARY_META_SURFACE_ADDRESS, address->grph_stereo.right_meta_addr.low_part); } if (address->grph_stereo.left_meta_addr.quad_part != 0) { - REG_UPDATE(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, 0, PRIMARY_META_SURFACE_ADDRESS_HIGH, address->grph_stereo.left_meta_addr.high_part); - REG_UPDATE(DCSURF_PRIMARY_META_SURFACE_ADDRESS, + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS, 0, PRIMARY_META_SURFACE_ADDRESS, address->grph_stereo.left_meta_addr.low_part); } - REG_UPDATE(DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH, + REG_SET(DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH, 0, SECONDARY_SURFACE_ADDRESS_HIGH, address->grph_stereo.right_addr.high_part); - REG_UPDATE(DCSURF_SECONDARY_SURFACE_ADDRESS, + REG_SET(DCSURF_SECONDARY_SURFACE_ADDRESS, 0, SECONDARY_SURFACE_ADDRESS, address->grph_stereo.right_addr.low_part); - - REG_UPDATE(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, 0, PRIMARY_SURFACE_ADDRESS_HIGH, address->grph_stereo.left_addr.high_part); - REG_UPDATE(DCSURF_PRIMARY_SURFACE_ADDRESS, + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS, 0, PRIMARY_SURFACE_ADDRESS, address->grph_stereo.left_addr.low_part); break; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h index 20bd0f5d7b17..48b313b213c0 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h @@ -282,6 +282,7 @@ struct dcn_mi_registers { MI_SF(HUBP0_DCSURF_SURFACE_CONFIG, SURFACE_PIXEL_FORMAT, mask_sh),\ MI_SF(HUBPREQ0_DCSURF_FLIP_CONTROL, SURFACE_FLIP_TYPE, mask_sh),\ MI_SF(HUBPREQ0_DCSURF_FLIP_CONTROL, SURFACE_UPDATE_PENDING, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_FLIP_CONTROL, SURFACE_UPDATE_LOCK, mask_sh),\ MI_SF(HUBPREQ0_DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, PRIMARY_SURFACE_ADDRESS_HIGH, mask_sh),\ MI_SF(HUBPREQ0_DCSURF_PRIMARY_SURFACE_ADDRESS, PRIMARY_SURFACE_ADDRESS, mask_sh),\ MI_SF(HUBPREQ0_DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH, SECONDARY_SURFACE_ADDRESS_HIGH, mask_sh),\ @@ -414,6 +415,7 @@ struct dcn_mi_registers { type H_MIRROR_EN;\ type SURFACE_PIXEL_FORMAT;\ type SURFACE_FLIP_TYPE;\ + type SURFACE_UPDATE_LOCK;\ type SURFACE_UPDATE_PENDING;\ type PRIMARY_SURFACE_ADDRESS_HIGH;\ type PRIMARY_SURFACE_ADDRESS;\ -- cgit From 5aa35c1a16d505c0aee7fa5bebf829f9bef32c34 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 18 May 2017 11:40:53 -0400 Subject: drm/amd/display: Remove unused addr var in TG Signed-off-by: Harry Wentland Reviewed-by: Sun peng Li Reviewed-by: Roman Li Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c index c208196864ad..03b21e9a1156 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c @@ -386,34 +386,27 @@ bool dce120_timing_generator_did_triggered_reset_occur( /* Move to enable accelerated mode */ void dce120_timing_generator_disable_vga(struct timing_generator *tg) { - uint32_t addr = 0; uint32_t offset = 0; uint32_t value = 0; struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); switch (tg110->controller_id) { case CONTROLLER_ID_D0: - addr = mmD1VGA_CONTROL; offset = 0; break; case CONTROLLER_ID_D1: - addr = mmD2VGA_CONTROL; offset = mmD2VGA_CONTROL - mmD1VGA_CONTROL; break; case CONTROLLER_ID_D2: - addr = mmD3VGA_CONTROL; offset = mmD3VGA_CONTROL - mmD1VGA_CONTROL; break; case CONTROLLER_ID_D3: - addr = mmD4VGA_CONTROL; offset = mmD4VGA_CONTROL - mmD1VGA_CONTROL; break; case CONTROLLER_ID_D4: - addr = mmD1VGA_CONTROL; offset = mmD5VGA_CONTROL - mmD1VGA_CONTROL; break; case CONTROLLER_ID_D5: - addr = mmD6VGA_CONTROL; offset = mmD6VGA_CONTROL - mmD1VGA_CONTROL; break; default: -- cgit From c14833c6728e587d33777d416a9d0c21d3785ff8 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Fri, 19 May 2017 17:15:23 -0400 Subject: drm/amd/display: No need to assert on stream_status This will be NULL on a new stream. DC handles it gracefully. Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index b3a4605858c1..3c1baa29f36f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2883,9 +2883,6 @@ static enum surface_update_type amdgpu_dm_check_surfaces_update_type( dc_stream_get_status(dc_stream); enum surface_update_type update_type; - ASSERT(stream_status); - - memset(srf_updates, 0, sizeof(srf_updates)); memset(flip_addr, 0, sizeof(flip_addr)); memset(plane_info, 0, sizeof(plane_info)); -- cgit From 21de3396b44a67429c6b6a3f2d697fb261c76054 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Mon, 22 May 2017 13:11:15 +0800 Subject: drm/amd/display: call amdgpu_dm_fini when hw_fini. to free up drm mode_config info. fix issue: unload amdgpu, can't load amdgpu again. [drm:drm_debugfs_init [drm]] *ERROR* Cannot create /sys/kernel/debug/dri/0 [drm:drm_minor_register [drm]] *ERROR* DRM: Failed to initialize /sys/kernel/debug/dri. Signed-off-by: Rex Zhu Acked-by: Alex Deucher Reviewed-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 5 ++--- drivers/gpu/drm/amd/display/dc/core/dc.c | 7 ++++++- 2 files changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') 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 7e28f9870b86..74415fdf7ed8 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -395,9 +395,8 @@ void amdgpu_dm_fini(struct amdgpu_device *adev) adev->dm.freesync_module = NULL; } /* DC Destroy TODO: Replace destroy DAL */ - { + if (adev->dm.dc) dc_destroy(&adev->dm.dc); - } return; } @@ -490,7 +489,7 @@ static int dm_hw_fini(void *handle) amdgpu_dm_hpd_fini(adev); amdgpu_dm_irq_fini(adev); - + amdgpu_dm_fini(adev); return 0; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 773f0efc449b..b428c7c6559b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1541,7 +1541,12 @@ enum dc_irq_source dc_interrupt_to_irq_source( void dc_interrupt_set(const struct dc *dc, enum dc_irq_source src, bool enable) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct core_dc *core_dc; + + if (dc == NULL) + return; + core_dc = DC_TO_CORE(dc); + dal_irq_service_set(core_dc->res_pool->irqs, src, enable); } -- cgit From 0bf954c154d7a8989afb6c138d63ca846bab47db Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 2 Jun 2017 14:54:26 -0400 Subject: drm/amdgpu/soc15: enable DC ip module for Raven Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/soc15.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c index 3d9a51d6e1aa..c2611eca8495 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15.c +++ b/drivers/gpu/drm/amd/amdgpu/soc15.c @@ -554,6 +554,12 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev) amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block); if (adev->enable_virtual_display || amdgpu_sriov_vf(adev)) amdgpu_ip_block_add(adev, &dce_virtual_ip_block); +#if defined(CONFIG_DRM_AMD_DC) + else if (amdgpu_device_has_dc_support(adev)) + amdgpu_ip_block_add(adev, &dm_ip_block); +#else +# warning "Enable CONFIG_DRM_AMD_DC for display support on SOC15." +#endif amdgpu_ip_block_add(adev, &gfx_v9_0_ip_block); amdgpu_ip_block_add(adev, &sdma_v4_0_ip_block); amdgpu_ip_block_add(adev, &vcn_v1_0_ip_block); -- cgit From 93b8ca9b8711ec2536060897f0f05db41dd810f5 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Tue, 30 May 2017 16:49:59 -0400 Subject: drm/amdgpu: Enable DRIVER_ATOMIC flag for DAL. This flag is needed to pass several of IGT test cases. Signed-off-by: Andrey Grodzovsky Acked-by: Alex Deucher Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 3 +++ drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 27d46a907bd9..a350fc9b2a70 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2071,6 +2071,9 @@ int amdgpu_device_init(struct amdgpu_device *adev, adev->audio_endpt_rreg = &amdgpu_block_invalid_rreg; adev->audio_endpt_wreg = &amdgpu_block_invalid_wreg; + if (amdgpu_device_has_dc_support(adev)) + adev->ddev->driver->driver_features |= DRIVER_ATOMIC; + DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X 0x%04X:0x%04X 0x%02X).\n", amdgpu_asic_name[adev->asic_type], pdev->vendor, pdev->device, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c index 2484dac08050..90fa8e8bc6fb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c @@ -348,7 +348,8 @@ int amdgpu_fbdev_init(struct amdgpu_device *adev) drm_fb_helper_single_add_all_connectors(&rfbdev->helper); /* disable all the possible outputs/crtcs before entering KMS mode */ - drm_helper_disable_unused_functions(adev->ddev); + if (!amdgpu_device_has_dc_support(adev)) + drm_helper_disable_unused_functions(adev->ddev); drm_fb_helper_initial_config(&rfbdev->helper, bpp_sel); return 0; -- cgit From e73b59b7e0cdecf0663b76f77b770c88b2d61604 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 19 May 2017 13:01:35 -0400 Subject: drm/amd/display: add always_scale debug flag to dc Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 1 + drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c | 14 +++++++++----- 2 files changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index f2efa32fe4ac..3b35487897b7 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -181,6 +181,7 @@ struct dc_debug { int urgent_latency_ns; int percent_of_ideal_drambw; int dram_clock_change_latency_ns; + int always_scale; #endif bool disable_pplib_clock_request; bool disable_clock_gate; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c index 3718fb5a3238..609805877508 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c @@ -157,7 +157,8 @@ static void transform_set_otg_blank( OTG_V_BLANK_END, v_blank_end); } -static enum dscl_mode_sel get_dscl_mode(const struct scaler_data *data) +static enum dscl_mode_sel get_dscl_mode( + const struct scaler_data *data, bool dbg_always_scale) { const long long one = dal_fixed31_32_one.value; bool ycbcr = false; @@ -177,7 +178,8 @@ static enum dscl_mode_sel get_dscl_mode(const struct scaler_data *data) if (data->ratios.horz.value == one && data->ratios.vert.value == one && data->ratios.horz_c.value == one - && data->ratios.vert_c.value == one) + && data->ratios.vert_c.value == one + && !dbg_always_scale) return DSCL_MODE_SCALING_444_BYPASS; if (!format420) { @@ -603,7 +605,8 @@ void transform_set_scaler_auto_scale( { enum lb_memory_config lb_config; struct dcn10_transform *xfm = TO_DCN10_TRANSFORM(xfm_base); - enum dscl_mode_sel dscl_mode = get_dscl_mode(scl_data); + enum dscl_mode_sel dscl_mode = get_dscl_mode( + scl_data, xfm_base->ctx->dc->debug.always_scale); bool ycbcr = scl_data->format >= PIXEL_FORMAT_VIDEO_BEGIN && scl_data->format <= PIXEL_FORMAT_VIDEO_END; @@ -611,7 +614,7 @@ void transform_set_scaler_auto_scale( transform_set_otg_blank(xfm, scl_data); - REG_UPDATE(SCL_MODE, DSCL_MODE, get_dscl_mode(scl_data)); + REG_UPDATE(SCL_MODE, DSCL_MODE, dscl_mode); transform_set_viewport(xfm, &scl_data->viewport, &scl_data->viewport_c); @@ -740,7 +743,8 @@ static void transform_set_scaler_manual_scale( { enum lb_memory_config lb_config; struct dcn10_transform *xfm = TO_DCN10_TRANSFORM(xfm_base); - enum dscl_mode_sel dscl_mode = get_dscl_mode(scl_data); + enum dscl_mode_sel dscl_mode = get_dscl_mode( + scl_data, xfm_base->ctx->dc->debug.always_scale); bool ycbcr = scl_data->format >= PIXEL_FORMAT_VIDEO_BEGIN && scl_data->format <= PIXEL_FORMAT_VIDEO_END; -- cgit From c1473558e617d886276e4a8b3c139b681d90d67c Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Fri, 19 May 2017 17:40:50 -0400 Subject: drm/amd/display: program scaler not called. Scaler code in case of UPDATE_TYPE_MED was not called since new pipe context and current context are the same. Signed-off-by: Andrey Grodzovsky Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 23 ++++++++++++++++++++-- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 6 ++---- 2 files changed, 23 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index b428c7c6559b..4900e8073c69 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1011,12 +1011,23 @@ bool dc_commit_surfaces_to_stream( struct dc_plane_info plane_info[MAX_SURFACES]; struct dc_scaling_info scaling_info[MAX_SURFACES]; int i; + bool ret; + struct dc_stream_update *stream_update = + dm_alloc(sizeof(struct dc_stream_update)); + + if (!stream_update) { + BREAK_TO_DEBUGGER(); + return false; + } memset(updates, 0, sizeof(updates)); memset(flip_addr, 0, sizeof(flip_addr)); memset(plane_info, 0, sizeof(plane_info)); memset(scaling_info, 0, sizeof(scaling_info)); + stream_update->src = dc_stream->src; + stream_update->dst = dc_stream->dst; + for (i = 0; i < new_surface_count; i++) { updates[i].surface = new_surfaces[i]; updates[i].gamma = @@ -1041,9 +1052,17 @@ bool dc_commit_surfaces_to_stream( updates[i].plane_info = &plane_info[i]; updates[i].scaling_info = &scaling_info[i]; } - dc_update_surfaces_for_stream(dc, updates, new_surface_count, dc_stream); - return dc_post_update_surfaces_to_stream(dc); + dc_update_surfaces_and_stream( + dc, + updates, + new_surface_count, + dc_stream, stream_update); + + ret = dc_post_update_surfaces_to_stream(dc); + + dm_free(stream_update); + return ret; } static bool is_surface_in_context( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 65c691569eb7..7dd4b02b5938 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -2408,10 +2408,8 @@ static void dce110_program_front_end_for_pipe( pipe_ctx->xfm->funcs->transform_set_gamut_remap(pipe_ctx->xfm, &adjust); pipe_ctx->scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; - if (old_pipe && memcmp(&old_pipe->scl_data, - &pipe_ctx->scl_data, - sizeof(struct scaler_data)) != 0) - program_scaler(dc, pipe_ctx); + + program_scaler(dc, pipe_ctx); mi->funcs->mem_input_program_surface_config( mi, -- cgit From bf2e2e2e0ea9ace6ed11423497664656943ec55f Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 18 May 2017 22:13:19 -0400 Subject: drm/amd/display: Limit DCN to x86 arch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DCN bw calcs currently rely on the following gcc options: -mhard-float -msse -mpreferred-stack-boundary=4 We probably shouldn't really try building this on architectures other than x86. CC: Alex Deucher CC: Christian König CC: Michel Dänzer CC: Tony Cheng CC: Dmytro Laktyushkin Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/Kconfig | 2 +- drivers/gpu/drm/amd/display/dc/calcs/Makefile | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/Kconfig b/drivers/gpu/drm/amd/display/Kconfig index 5c3bb3581842..89fc8e738668 100644 --- a/drivers/gpu/drm/amd/display/Kconfig +++ b/drivers/gpu/drm/amd/display/Kconfig @@ -19,7 +19,7 @@ config DRM_AMD_DC_PRE_VEGA config DRM_AMD_DC_DCN1_0 bool "DCN 1.0 Raven family" - depends on DRM_AMD_DC + depends on DRM_AMD_DC && X86 help Choose this option if you want to have RV family for display engine diff --git a/drivers/gpu/drm/amd/display/dc/calcs/Makefile b/drivers/gpu/drm/amd/display/dc/calcs/Makefile index a095472bf4b5..2e4ce0918c02 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/Makefile +++ b/drivers/gpu/drm/amd/display/dc/calcs/Makefile @@ -3,9 +3,11 @@ # It calculates Bandwidth and Watermarks values for HW programming # +ifeq ($(ARCH),x86) CFLAGS_dcn_calcs.o := -mhard-float -msse -mpreferred-stack-boundary=4 CFLAGS_dcn_calc_auto.o := -mhard-float -msse -mpreferred-stack-boundary=4 CFLAGS_dcn_calc_math.o := -mhard-float -msse -mpreferred-stack-boundary=4 +endif BW_CALCS = dce_calcs.o bw_fixed.o custom_float.o -- cgit From ccaa73897109c521a9fda82a50c988e9cba947e7 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Mon, 22 May 2017 17:55:38 -0400 Subject: drm/amd/display: Fix handling of scaling and underscan. Summury of changes: 1: Both in check and commit Connector properties were handled as part of for_each(crtc) loop while they shoud have been handled in a dedicated for_each(connector) loop since they are connector properties. Moved. 2: Removed hacky plane add in amdgpu_dm_connector_atomic_set_property to force iteration on plane forconnector property. This was causing double call to commit_surface_for_stream both in crtc loop and plane loop. 3: Remove middleman DC interface and call dc_commit_surfaces_to_stream directly to increase code clarity. Remove it from atomic_commit. Signed-off-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 205 ++++++++++----------- 1 file changed, 99 insertions(+), 106 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 3c1baa29f36f..4da5a7154cea 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -682,9 +682,8 @@ struct amdgpu_connector *aconnector_from_drm_crtc_id( static void update_stream_scaling_settings( const struct drm_display_mode *mode, const struct dm_connector_state *dm_state, - const struct dc_stream *stream) + struct dc_stream *stream) { - struct amdgpu_device *adev = dm_state->base.crtc->dev->dev_private; enum amdgpu_rmx_type rmx_type; struct rect src = { 0 }; /* viewport in composition space*/ @@ -726,7 +725,8 @@ static void update_stream_scaling_settings( dst.height -= dm_state->underscan_vborder; } - adev->dm.dc->stream_funcs.stream_update_scaling(adev->dm.dc, stream, &src, &dst); + stream->src = src; + stream->dst = dst; DRM_DEBUG_KMS("Destination Rectangle x:%d y:%d width:%d height:%d\n", dst.x, dst.y, dst.width, dst.height); @@ -1135,9 +1135,6 @@ int amdgpu_dm_connector_atomic_set_property( struct dm_connector_state *dm_new_state = to_dm_connector_state(connector_state); - struct drm_crtc_state *new_crtc_state; - struct drm_crtc *crtc; - int i; int ret = -EINVAL; if (property == dev->mode_config.scaling_mode_property) { @@ -1175,32 +1172,6 @@ int amdgpu_dm_connector_atomic_set_property( ret = 0; } - for_each_crtc_in_state( - connector_state->state, - crtc, - new_crtc_state, - i) { - - if (crtc == connector_state->crtc) { - struct drm_plane_state *plane_state; - - /* - * Bit of magic done here. We need to ensure - * that planes get update after mode is set. - * So, we need to add primary plane to state, - * and this way atomic_update would be called - * for it - */ - plane_state = - drm_atomic_get_plane_state( - connector_state->state, - crtc->primary); - - if (!plane_state) - return -EINVAL; - } - } - return ret; } @@ -2401,28 +2372,19 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, struct amdgpu_crtc *acrtc_attach = to_amdgpu_crtc(crtc); struct drm_framebuffer *fb = plane_state->fb; struct drm_connector *connector; - struct dm_connector_state *dm_state = NULL; - - enum dm_commit_action action; + struct dm_connector_state *con_state = NULL; bool pflip_needed; if (!fb || !crtc || !crtc->state->active) continue; - action = get_dm_commit_action(crtc->state); - - /* - * TODO - TO decide if it's a flip or surface update - * stop relying on allow_modeset flag and query DC - * using dc_check_update_surfaces_for_stream. - */ pflip_needed = !state->allow_modeset; if (!pflip_needed) { list_for_each_entry(connector, &dev->mode_config.connector_list, head) { if (connector->state->crtc == crtc) { - dm_state = to_dm_connector_state( + con_state = to_dm_connector_state( connector->state); break; } @@ -2442,8 +2404,10 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, * Also it should be needed when used with actual * drm_atomic_commit ioctl in future */ - if (!dm_state) + if (!con_state) continue; + + if (crtc == pcrtc) { add_surface(dm->dc, crtc, plane, &dc_surfaces_constructed[planes_count]); @@ -2495,7 +2459,8 @@ void amdgpu_dm_atomic_commit_tail( const struct dc_stream *new_stream; unsigned long flags; bool wait_for_vblank = true; - + struct drm_connector *connector; + struct drm_connector_state *old_conn_state; drm_atomic_helper_update_legacy_modeset_state(dev, state); @@ -2575,21 +2540,6 @@ void amdgpu_dm_atomic_commit_tail( break; } - - case DM_COMMIT_ACTION_NOTHING: { - struct dm_connector_state *dm_state = NULL; - - if (!aconnector) - break; - - dm_state = to_dm_connector_state(aconnector->base.state); - - /* Scaling update */ - update_stream_scaling_settings(&crtc->state->mode, - dm_state, acrtc->stream); - - break; - } case DM_COMMIT_ACTION_DPMS_OFF: case DM_COMMIT_ACTION_RESET: DRM_INFO("Atomic commit: RESET. crtc id %d:[%p]\n", acrtc->crtc_id, acrtc); @@ -2597,9 +2547,48 @@ void amdgpu_dm_atomic_commit_tail( if (acrtc->stream) remove_stream(adev, acrtc); break; + + /*TODO retire */ + case DM_COMMIT_ACTION_NOTHING: + continue; } /* switch() */ } /* for_each_crtc_in_state() */ + /* Handle scaling and undersacn changes*/ + for_each_connector_in_state(state, connector, old_conn_state, i) { + struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + struct dm_connector_state *con_new_state = + to_dm_connector_state(aconnector->base.state); + struct dm_connector_state *con_old_state = + to_dm_connector_state(old_conn_state); + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(con_new_state->base.crtc); + const struct dc_stream_status *status = NULL; + + /* Skip any modesets/resets */ + if (!acrtc || + get_dm_commit_action(acrtc->base.state) != DM_COMMIT_ACTION_NOTHING) + continue; + + /* Skip any thing not scale or underscan chnages */ + if (!is_scaling_state_different(con_new_state, con_old_state)) + continue; + + update_stream_scaling_settings(&con_new_state->base.crtc->mode, + con_new_state, (struct dc_stream *)acrtc->stream); + + status = dc_stream_get_status(acrtc->stream); + WARN_ON(!status); + WARN_ON(!status->surface_count); + + /*TODO How it works with MPO ?*/ + if (!dc_commit_surfaces_to_stream( + dm->dc, + (const struct dc_surface **)status->surfaces, + status->surface_count, + acrtc->stream)) + dm_error("%s: Failed to update stream scaling!\n", __func__); + } + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); @@ -2937,6 +2926,8 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, struct dc *dc = adev->dm.dc; bool need_to_validate = false; struct validate_context *context; + struct drm_connector *connector; + struct drm_connector_state *conn_state; /* * This bool will be set for true for any modeset/reset * or surface update which implies non fast surfae update. @@ -3022,52 +3013,6 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, break; } - case DM_COMMIT_ACTION_NOTHING: { - const struct drm_connector *drm_connector = NULL; - struct drm_connector_state *conn_state = NULL; - struct dm_connector_state *dm_state = NULL; - struct dm_connector_state *old_dm_state = NULL; - struct dc_stream *new_stream; - - if (!aconnector) - break; - - for_each_connector_in_state( - state, drm_connector, conn_state, j) { - if (&aconnector->base == drm_connector) - break; - } - - old_dm_state = to_dm_connector_state(drm_connector->state); - dm_state = to_dm_connector_state(conn_state); - - /* Support underscan adjustment*/ - if (!is_scaling_state_different(dm_state, old_dm_state)) - break; - - new_stream = create_stream_for_sink(aconnector, &crtc_state->mode, dm_state); - - if (!new_stream) { - DRM_ERROR("%s: Failed to create new stream for crtc %d\n", - __func__, acrtc->base.base.id); - break; - } - - new_streams[new_stream_count] = new_stream; - set_count = update_in_val_sets_stream( - set, - crtc_set, - set_count, - acrtc->stream, - new_stream, - crtc); - - new_stream_count++; - need_to_validate = true; - wait_for_prev_commits = true; - - break; - } case DM_COMMIT_ACTION_DPMS_OFF: case DM_COMMIT_ACTION_RESET: /* i.e. reset mode */ @@ -3079,6 +3024,10 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, wait_for_prev_commits = true; } break; + + /*TODO retire */ + case DM_COMMIT_ACTION_NOTHING: + continue; } /* @@ -3095,6 +3044,50 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, ret = -EINVAL; } + /* Check scaling and undersacn changes*/ + for_each_connector_in_state(state, connector, conn_state, i) { + struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + struct dm_connector_state *con_old_state = + to_dm_connector_state(aconnector->base.state); + struct dm_connector_state *con_new_state = + to_dm_connector_state(conn_state); + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(con_new_state->base.crtc); + struct dc_stream *new_stream; + + /* Skip any modesets/resets */ + if (!acrtc || + get_dm_commit_action(acrtc->base.state) != DM_COMMIT_ACTION_NOTHING) + continue; + + /* Skip any thing not scale or underscan chnages */ + if (!is_scaling_state_different(con_new_state, con_old_state)) + continue; + + new_stream = create_stream_for_sink( + aconnector, + &acrtc->base.state->mode, + con_new_state); + + if (!new_stream) { + DRM_ERROR("%s: Failed to create new stream for crtc %d\n", + __func__, acrtc->base.base.id); + continue; + } + + new_streams[new_stream_count] = new_stream; + set_count = update_in_val_sets_stream( + set, + crtc_set, + set_count, + acrtc->stream, + new_stream, + &acrtc->base); + + new_stream_count++; + need_to_validate = true; + wait_for_prev_commits = true; + } + for (i = 0; i < set_count; i++) { for_each_plane_in_state(state, plane, plane_state, j) { struct drm_crtc *crtc = plane_state->crtc; -- cgit From 893a2dd4a3ffceb3b3fa88353d8270de06195b10 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Mon, 22 May 2017 20:25:48 -0400 Subject: drm/amd/display: Clean unused interface. Signed-off-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 42 -------------------------------- drivers/gpu/drm/amd/display/dc/dc.h | 6 ----- 2 files changed, 48 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 4900e8073c69..f5349970b594 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -249,47 +249,6 @@ static void set_static_screen_events(struct dc *dc, core_dc->hwss.set_static_screen_control(pipes_affected, num_pipes_affected, events); } -/* This function is not expected to fail, proper implementation of - * validation will prevent this from ever being called for unsupported - * configurations. - */ -static void stream_update_scaling( - const struct dc *dc, - const struct dc_stream *dc_stream, - const struct rect *src, - const struct rect *dst) -{ - struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); - struct core_dc *core_dc = DC_TO_CORE(dc); - struct validate_context *cur_ctx = core_dc->current_context; - int i; - - if (src) - stream->public.src = *src; - - if (dst) - stream->public.dst = *dst; - - for (i = 0; i < cur_ctx->stream_count; i++) { - struct core_stream *cur_stream = cur_ctx->streams[i]; - - if (stream == cur_stream) { - struct dc_stream_status *status = &cur_ctx->stream_status[i]; - - if (status->surface_count) - if (!dc_commit_surfaces_to_stream( - &core_dc->public, - status->surfaces, - status->surface_count, - &cur_stream->public)) - /* Need to debug validation */ - BREAK_TO_DEBUGGER(); - - return; - } - } -} - static void set_drive_settings(struct dc *dc, struct link_training_settings *lt_settings, const struct dc_link *link) @@ -402,7 +361,6 @@ void set_dither_option(const struct dc_stream *dc_stream, static void allocate_dc_stream_funcs(struct core_dc *core_dc) { - core_dc->public.stream_funcs.stream_update_scaling = stream_update_scaling; if (core_dc->hwss.set_drr != NULL) { core_dc->public.stream_funcs.adjust_vmin_vmax = stream_adjust_vmin_vmax; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 3b35487897b7..0d3b73a37df1 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -115,12 +115,6 @@ struct dc_stream_funcs { unsigned int *v_pos, unsigned int *nom_v_pos); - - void (*stream_update_scaling)(const struct dc *dc, - const struct dc_stream *dc_stream, - const struct rect *src, - const struct rect *dst); - bool (*set_gamut_remap)(struct dc *dc, const struct dc_stream *stream); -- cgit From 29eba8e88f3665b5099d0c4ef7180b631846aa0b Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Tue, 23 May 2017 17:15:54 -0400 Subject: drm/amd/display: Add disable_psr debug flag Signed-off-by: Charlene Liu Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 0d3b73a37df1..ce052d12a104 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -180,6 +180,7 @@ struct dc_debug { bool disable_pplib_clock_request; bool disable_clock_gate; bool disable_dmcu; + bool disable_psr; bool force_abm_enable; }; -- cgit From c7dbdf1535a34741a8805d04a9ae75a887d8b581 Mon Sep 17 00:00:00 2001 From: Corbin McElhanney Date: Tue, 23 May 2017 15:26:57 -0400 Subject: drm/amd/display: Allow update stream without surface Passing NULL as surfaceUpdates to dc_update_surfaces_and_stream now updates just the stream. Code that is dependent on srf_updates was moved below the NULL check. Signed-off-by: Corbin McElhanney Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 58 +++++++++++++++++--------------- 1 file changed, 31 insertions(+), 27 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index f5349970b594..c33e31c9e3e1 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1223,33 +1223,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, if (!stream_status) return; /* Cannot commit surface to stream that is not committed */ - update_type = dc_check_update_surfaces_for_stream( - dc, srf_updates, surface_count, stream_update, stream_status); - - if (update_type >= update_surface_trace_level) - update_surface_trace(dc, srf_updates, surface_count); - - if (update_type >= UPDATE_TYPE_FULL) { - const struct dc_surface *new_surfaces[MAX_SURFACES] = { 0 }; - - for (i = 0; i < surface_count; i++) - new_surfaces[i] = srf_updates[i].surface; - - /* initialize scratch memory for building context */ - context = dm_alloc(sizeof(*context)); - dc_resource_validate_ctx_copy_construct( - core_dc->current_context, context); - - /* add surface to context */ - if (!resource_attach_surfaces_to_context( - new_surfaces, surface_count, dc_stream, - context, core_dc->res_pool)) { - BREAK_TO_DEBUGGER(); - goto fail; - } - } else { - context = core_dc->current_context; - } + context = core_dc->current_context; /* update current stream with the new updates */ if (stream_update) { @@ -1277,6 +1251,36 @@ void dc_update_surfaces_and_stream(struct dc *dc, } } + /* only proceed if we need to make a surface update */ + if (!srf_updates) + return; + + update_type = dc_check_update_surfaces_for_stream( + dc, srf_updates, surface_count, stream_update, stream_status); + + if (update_type >= update_surface_trace_level) + update_surface_trace(dc, srf_updates, surface_count); + + if (update_type >= UPDATE_TYPE_FULL) { + const struct dc_surface *new_surfaces[MAX_SURFACES] = { 0 }; + + for (i = 0; i < surface_count; i++) + new_surfaces[i] = srf_updates[i].surface; + + /* initialize scratch memory for building context */ + context = dm_alloc(sizeof(*context)); + dc_resource_validate_ctx_copy_construct( + core_dc->current_context, context); + + /* add surface to context */ + if (!resource_attach_surfaces_to_context( + new_surfaces, surface_count, dc_stream, + context, core_dc->res_pool)) { + BREAK_TO_DEBUGGER(); + goto fail; + } + } + /* save update parameters into surface */ for (i = 0; i < surface_count; i++) { struct core_surface *surface = -- cgit From 72dfad50179bb8c813d7c3a7ce149dafc4586fe6 Mon Sep 17 00:00:00 2001 From: Zeyu Fan Date: Fri, 19 May 2017 15:52:00 -0400 Subject: drm/amd/display: Add FORCE_HDR timing flag Signed-off-by: Zeyu Fan Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index 58a3bcd5131f..b6e677786cbc 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -635,6 +635,8 @@ struct dc_crtc_timing_flags { uint32_t YCBCR420 :1; /* TODO: shouldn't need this flag, should be a separate pixel format */ uint32_t DTD_COUNTER :5; /* values 1 to 16 */ + uint32_t FORCE_HDR :1; + /* HDMI 2.0 - Support scrambling for TMDS character * rates less than or equal to 340Mcsc */ uint32_t LTE_340MCSC_SCRAMBLE:1; -- cgit From ece22899a46551dcd8e9f3296ce1ec8ac9e07dc4 Mon Sep 17 00:00:00 2001 From: Amy Zhang Date: Wed, 24 May 2017 14:53:50 -0400 Subject: drm/amd/display: Disable PSR entry abort to prevent intermittent freezes Signed-off-by: Amy Zhang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 59977640f938..79f3947a3ee1 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1550,6 +1550,11 @@ bool dc_link_setup_psr(const struct dc_link *dc_link, */ psr_context.psr_level.bits.SKIP_SMU_NOTIFICATION = 1; + /* Complete PSR entry before aborting to prevent intermittent + * freezes on certain eDPs + */ + psr_context.psr_level.bits.DISABLE_PSR_ENTRY_ABORT = 1; + /* Controls additional delay after remote frame capture before * continuing power down, default = 0 */ -- cgit From afdbd4ccfd36eb18ce89b504d79bb3051cdab839 Mon Sep 17 00:00:00 2001 From: Jerry Zuo Date: Wed, 24 May 2017 11:01:32 -0400 Subject: drm/amd/display: fix NULL pointer in dm_commit_surfaces Check if adding surface is failed to prevent NULL pointer deref. Signed-off-by: Jerry Zuo Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 4da5a7154cea..810373480ed5 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2411,6 +2411,10 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, if (crtc == pcrtc) { add_surface(dm->dc, crtc, plane, &dc_surfaces_constructed[planes_count]); + if (dc_surfaces_constructed[planes_count] == NULL) { + dm_error("%s: Failed to add surface!\n", __func__); + continue; + } dc_stream_attach = acrtc_attach->stream; planes_count++; } -- cgit From 4c92c92d77cdbfb46925d498addf19e5aebe46b8 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Wed, 24 May 2017 11:59:39 -0400 Subject: drm/amd/display: Get rid of get_dm_commit_action Use drm_atomic_crtc_needs_modeset instead. Signed-off-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 127 +++++++-------------- 1 file changed, 44 insertions(+), 83 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 810373480ed5..3747c99f3a8d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2164,57 +2164,23 @@ int amdgpu_dm_encoder_init( return res; } -enum dm_commit_action { - DM_COMMIT_ACTION_NOTHING, - DM_COMMIT_ACTION_RESET, - DM_COMMIT_ACTION_DPMS_ON, - DM_COMMIT_ACTION_DPMS_OFF, - DM_COMMIT_ACTION_SET -}; - -static enum dm_commit_action get_dm_commit_action(struct drm_crtc_state *state) +static bool modeset_required(struct drm_crtc_state *crtc_state) { - /* mode changed means either actually mode changed or enabled changed */ - /* active changed means dpms changed */ - - DRM_DEBUG_KMS("crtc_state_flags: enable:%d, active:%d, planes_changed:%d, mode_changed:%d,active_changed:%d,connectors_changed:%d\n", - state->enable, - state->active, - state->planes_changed, - state->mode_changed, - state->active_changed, - state->connectors_changed); - - if (state->mode_changed) { - /* if it is got disabled - call reset mode */ - if (!state->enable) - return DM_COMMIT_ACTION_RESET; + if (!drm_atomic_crtc_needs_modeset(crtc_state)) + return false; - if (state->active) - return DM_COMMIT_ACTION_SET; - else - return DM_COMMIT_ACTION_RESET; - } else { - /* ! mode_changed */ + if (!crtc_state->enable) + return false; - /* if it is remain disable - skip it */ - if (!state->enable) - return DM_COMMIT_ACTION_NOTHING; + return crtc_state->active; +} - if (state->active && state->connectors_changed) - return DM_COMMIT_ACTION_SET; +static bool modereset_required(struct drm_crtc_state *crtc_state) +{ + if (!drm_atomic_crtc_needs_modeset(crtc_state)) + return false; - if (state->active_changed) { - if (state->active) { - return DM_COMMIT_ACTION_DPMS_ON; - } else { - return DM_COMMIT_ACTION_DPMS_OFF; - } - } else { - /* ! active_changed */ - return DM_COMMIT_ACTION_NOTHING; - } - } + return !crtc_state->enable || !crtc_state->active; } static void manage_dm_interrupts( @@ -2467,12 +2433,10 @@ void amdgpu_dm_atomic_commit_tail( struct drm_connector_state *old_conn_state; drm_atomic_helper_update_legacy_modeset_state(dev, state); - /* update changed items */ for_each_crtc_in_state(state, crtc, old_crtc_state, i) { struct amdgpu_crtc *acrtc; struct amdgpu_connector *aconnector = NULL; - enum dm_commit_action action; struct drm_crtc_state *new_state = crtc->state; acrtc = to_amdgpu_crtc(crtc); @@ -2483,15 +2447,23 @@ void amdgpu_dm_atomic_commit_tail( crtc, false); + DRM_DEBUG_KMS( + "amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, " + "planes_changed:%d, mode_changed:%d,active_changed:%d," + "connectors_changed:%d\n", + acrtc->crtc_id, + new_state->enable, + new_state->active, + new_state->planes_changed, + new_state->mode_changed, + new_state->active_changed, + new_state->connectors_changed); + /* handles headless hotplug case, updating new_state and * aconnector as needed */ - action = get_dm_commit_action(new_state); - - switch (action) { - case DM_COMMIT_ACTION_DPMS_ON: - case DM_COMMIT_ACTION_SET: { + if (modeset_required(new_state)) { struct dm_connector_state *dm_state = NULL; new_stream = NULL; @@ -2541,21 +2513,13 @@ void amdgpu_dm_atomic_commit_tail( acrtc->enabled = true; acrtc->hw_mode = crtc->state->mode; crtc->hwmode = crtc->state->mode; + } else if (modereset_required(new_state)) { - break; - } - case DM_COMMIT_ACTION_DPMS_OFF: - case DM_COMMIT_ACTION_RESET: DRM_INFO("Atomic commit: RESET. crtc id %d:[%p]\n", acrtc->crtc_id, acrtc); /* i.e. reset mode */ if (acrtc->stream) remove_stream(adev, acrtc); - break; - - /*TODO retire */ - case DM_COMMIT_ACTION_NOTHING: - continue; - } /* switch() */ + } } /* for_each_crtc_in_state() */ /* Handle scaling and undersacn changes*/ @@ -2569,8 +2533,7 @@ void amdgpu_dm_atomic_commit_tail( const struct dc_stream_status *status = NULL; /* Skip any modesets/resets */ - if (!acrtc || - get_dm_commit_action(acrtc->base.state) != DM_COMMIT_ACTION_NOTHING) + if (!acrtc || drm_atomic_crtc_needs_modeset(acrtc->base.state)) continue; /* Skip any thing not scale or underscan chnages */ @@ -2966,17 +2929,25 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, for_each_crtc_in_state(state, crtc, crtc_state, i) { struct amdgpu_crtc *acrtc = NULL; struct amdgpu_connector *aconnector = NULL; - enum dm_commit_action action; acrtc = to_amdgpu_crtc(crtc); aconnector = amdgpu_dm_find_first_crct_matching_connector(state, crtc, true); - action = get_dm_commit_action(crtc_state); + DRM_DEBUG_KMS( + "amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, " + "planes_changed:%d, mode_changed:%d,active_changed:%d," + "connectors_changed:%d\n", + acrtc->crtc_id, + crtc_state->enable, + crtc_state->active, + crtc_state->planes_changed, + crtc_state->mode_changed, + crtc_state->active_changed, + crtc_state->connectors_changed); + + if (modeset_required(crtc_state)) { - switch (action) { - case DM_COMMIT_ACTION_DPMS_ON: - case DM_COMMIT_ACTION_SET: { struct dc_stream *new_stream = NULL; struct drm_connector_state *conn_state = NULL; struct dm_connector_state *dm_state = NULL; @@ -3014,11 +2985,9 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, new_stream_count++; need_to_validate = true; wait_for_prev_commits = true; - break; - } - case DM_COMMIT_ACTION_DPMS_OFF: - case DM_COMMIT_ACTION_RESET: + } else if (modereset_required(crtc_state)) { + /* i.e. reset mode */ if (acrtc->stream) { set_count = remove_from_val_sets( @@ -3027,11 +2996,6 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, acrtc->stream); wait_for_prev_commits = true; } - break; - - /*TODO retire */ - case DM_COMMIT_ACTION_NOTHING: - continue; } /* @@ -3059,8 +3023,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, struct dc_stream *new_stream; /* Skip any modesets/resets */ - if (!acrtc || - get_dm_commit_action(acrtc->base.state) != DM_COMMIT_ACTION_NOTHING) + if (!acrtc || drm_atomic_crtc_needs_modeset(acrtc->base.state)) continue; /* Skip any thing not scale or underscan chnages */ @@ -3098,7 +3061,6 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, struct drm_framebuffer *fb = plane_state->fb; struct drm_connector *connector; struct dm_connector_state *dm_state = NULL; - enum dm_commit_action action; struct drm_crtc_state *crtc_state; bool pflip_needed; @@ -3107,7 +3069,6 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, !crtc->state->planes_changed || !crtc->state->active) continue; - action = get_dm_commit_action(crtc->state); crtc_state = drm_atomic_get_crtc_state(state, crtc); pflip_needed = !state->allow_modeset; -- cgit From 7fa4fcba7ab4f29f88b503e0e840f4c3bf774dc0 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 25 May 2017 11:44:53 -0400 Subject: drm/amd/display: Don't guard x86 in Makefile make-kpkg doesn't seem to like it Signed-off-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/Makefile | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/Makefile b/drivers/gpu/drm/amd/display/dc/calcs/Makefile index 2e4ce0918c02..a095472bf4b5 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/Makefile +++ b/drivers/gpu/drm/amd/display/dc/calcs/Makefile @@ -3,11 +3,9 @@ # It calculates Bandwidth and Watermarks values for HW programming # -ifeq ($(ARCH),x86) CFLAGS_dcn_calcs.o := -mhard-float -msse -mpreferred-stack-boundary=4 CFLAGS_dcn_calc_auto.o := -mhard-float -msse -mpreferred-stack-boundary=4 CFLAGS_dcn_calc_math.o := -mhard-float -msse -mpreferred-stack-boundary=4 -endif BW_CALCS = dce_calcs.o bw_fixed.o custom_float.o -- cgit From e4bf0a0eed7e0e3bb7f0be2788cf0a5ecc16b068 Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Thu, 25 May 2017 10:55:54 -0400 Subject: drm/amd/display: create_links bug with empty DDI slot Signed-off-by: Hersen Wu Reviewed-by: Hersen Wu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c | 7 ++++--- drivers/gpu/drm/amd/display/dc/core/dc.c | 3 +-- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c index 682fc9b9b3f2..fcd3b72287c8 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -410,6 +410,9 @@ enum generic_id generic_id_from_bios_object_id(uint32_t bios_object_id) return id; } +/* BIOS oject table displaypath is per connector. + * There is extra path not for connector. BIOS fill its encoderid as 0 + */ static uint8_t bios_parser_get_connectors_number(struct dc_bios *dcb) { struct bios_parser *bp = BP_FROM_DCB(dcb); @@ -417,9 +420,7 @@ static uint8_t bios_parser_get_connectors_number(struct dc_bios *dcb) unsigned int i; for (i = 0; i < bp->object_info_tbl.v1_4->number_of_path; i++) { - if (bp->object_info_tbl.v1_4->display_path[i].encoderobjid != 0 - && - bp->object_info_tbl.v1_4->display_path[i].display_objid != 0) + if (bp->object_info_tbl.v1_4->display_path[i].encoderobjid != 0) count++; } return count; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index c33e31c9e3e1..323a5e706908 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -97,6 +97,7 @@ static bool create_links( struct core_link *link; link_init_params.ctx = dc->ctx; + /* next BIOS object table connector */ link_init_params.connector_index = i; link_init_params.link_index = dc->link_count; link_init_params.dc = dc; @@ -106,8 +107,6 @@ static bool create_links( dc->links[dc->link_count] = link; link->dc = dc; ++dc->link_count; - } else { - dm_error("DC: failed to create link!\n"); } } -- cgit From 0a1c73ec8e4834d72441ae77f436869fd5179d8f Mon Sep 17 00:00:00 2001 From: Shirish S Date: Thu, 25 May 2017 14:40:21 +0530 Subject: drm/amd/display: re-order the luma chroma addres updation The DCE engine triggers scan as soon as the luma address is updated, since it is updated before chroma address the chroma data is not scanned out properly or in order. This patch fixes this by re-ordering the same. BUG: SWDEV-119421 TEST: (On Chromium OS for Stoney Only) * Executed below tests to see YUV(underlay) & RGB planes on eDP plane_test --format XR24 --size 500x100 -p --format NV12 --size 500x500 * Chroma data is scanned properly. Signed-off-by: Shirish S Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c index 9777a4d961d5..a06c6024deb4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c @@ -137,12 +137,12 @@ static void program_addr( addr->grph.addr); break; case PLN_ADDR_TYPE_VIDEO_PROGRESSIVE: - program_pri_addr_l( - mem_input110, - addr->video_progressive.luma_addr); program_pri_addr_c( mem_input110, addr->video_progressive.chroma_addr); + program_pri_addr_l( + mem_input110, + addr->video_progressive.luma_addr); break; default: /* not supported */ -- cgit From 630e3573853ff8644daf1ae32a503984110afe28 Mon Sep 17 00:00:00 2001 From: Jeff Smith Date: Fri, 19 May 2017 08:32:23 -0500 Subject: drm/amd/display: default spd packet to invalid Signed-off-by: Jeff Smith Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index ec5045734378..6202b4b3e597 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -2172,6 +2172,7 @@ void resource_build_info_frame(struct pipe_ctx *pipe_ctx) info->avi.valid = false; info->gamut.valid = false; info->vendor.valid = false; + info->spd.valid = false; info->hdrsmd.valid = false; info->vsc.valid = false; -- cgit From f0c16087fba728c36bc33fe462b35ca4ada7f5ca Mon Sep 17 00:00:00 2001 From: Shirish S Date: Thu, 25 May 2017 14:36:47 +0530 Subject: drm/amd/display: update NV12/NV21 as the YUV format This patch updates the YUV format supported to NV12 and NV21 and hence updates the offsets. BUG: SWDEV-119421 TEST: (On Chromium OS for Stoney Only) * Executed below tests to see YUV(underlay) & RGB planes on eDP plane_test --format XR24 --size 500x100 -p --format NV12 --size 500x500 Signed-off-by: Shirish S Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 3747c99f3a8d..1fc8bbfcb4b9 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -456,6 +456,7 @@ static void fill_plane_attributes_from_fb( { uint64_t tiling_flags; uint64_t fb_location = 0; + unsigned int awidth; const struct drm_framebuffer *fb = &amdgpu_fb->base; struct drm_format_name_buf format_name; @@ -484,10 +485,10 @@ static void fill_plane_attributes_from_fb( case DRM_FORMAT_ABGR2101010: surface->format = SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010; break; - case DRM_FORMAT_YUV420: + case DRM_FORMAT_NV21: surface->format = SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr; break; - case DRM_FORMAT_YVU420: + case DRM_FORMAT_NV12: surface->format = SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb; break; default: @@ -510,24 +511,25 @@ static void fill_plane_attributes_from_fb( surface->color_space = COLOR_SPACE_SRGB; } else { + awidth = ALIGN(fb->width, 64); surface->address.type = PLN_ADDR_TYPE_VIDEO_PROGRESSIVE; surface->address.video_progressive.luma_addr.low_part = lower_32_bits(fb_location); surface->address.video_progressive.chroma_addr.low_part = lower_32_bits(fb_location) + - (fb->width * fb->height); + (awidth * fb->height); surface->plane_size.video.luma_size.x = 0; surface->plane_size.video.luma_size.y = 0; - surface->plane_size.video.luma_size.width = fb->width; + surface->plane_size.video.luma_size.width = awidth; surface->plane_size.video.luma_size.height = fb->height; /* TODO: unhardcode */ - surface->plane_size.video.luma_pitch = ALIGN(fb->width, 64); + surface->plane_size.video.luma_pitch = awidth; surface->plane_size.video.chroma_size.x = 0; surface->plane_size.video.chroma_size.y = 0; - surface->plane_size.video.chroma_size.width = fb->width / 2; - surface->plane_size.video.chroma_size.height = fb->height / 2; - surface->plane_size.video.chroma_pitch = ALIGN(fb->width, 64) / 2; + surface->plane_size.video.chroma_size.width = awidth; + surface->plane_size.video.chroma_size.height = fb->height; + surface->plane_size.video.chroma_pitch = awidth / 2; /* TODO: unhardcode */ surface->color_space = COLOR_SPACE_YCBCR709; @@ -1662,8 +1664,8 @@ static uint32_t rgb_formats[] = { }; static uint32_t yuv_formats[] = { - DRM_FORMAT_YUV420, - DRM_FORMAT_YVU420, + DRM_FORMAT_NV12, + DRM_FORMAT_NV21, }; int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, -- cgit From 30406ff85324bc64bf8a9bf5b3f4e75c23ea4abf Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 25 May 2017 18:00:37 -0400 Subject: drm/amd/display: Don't commit surfaces if no stream Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 1fc8bbfcb4b9..7db04a487c21 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2549,6 +2549,9 @@ void amdgpu_dm_atomic_commit_tail( WARN_ON(!status); WARN_ON(!status->surface_count); + if (!acrtc->stream) + continue; + /*TODO How it works with MPO ?*/ if (!dc_commit_surfaces_to_stream( dm->dc, @@ -2606,8 +2609,12 @@ void amdgpu_dm_atomic_commit_tail( } /* update planes when needed per crtc*/ - for_each_crtc_in_state(state, pcrtc, old_crtc_state, j) - amdgpu_dm_commit_surfaces(state, dev, dm, pcrtc, &wait_for_vblank); + for_each_crtc_in_state(state, pcrtc, old_crtc_state, j) { + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(pcrtc); + + if (acrtc->stream) + amdgpu_dm_commit_surfaces(state, dev, dm, pcrtc, &wait_for_vblank); + } for (i = 0; i < new_crtcs_count; i++) { /* -- cgit From 259873e1ff3198d80f2dd50e3ab4249ad289e4c2 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Thu, 25 May 2017 18:39:49 -0400 Subject: drm/amd/display: stop adjusting scl taps when scl ratio is one on dcn Signed-off-by: Dmytro Laktyushkin Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c index 609805877508..d9815a991682 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c @@ -851,14 +851,16 @@ static bool transform_get_optimal_number_of_taps( else scl_data->taps.h_taps_c = in_taps->h_taps_c; - if (IDENTITY_RATIO(scl_data->ratios.horz)) - scl_data->taps.h_taps = 1; - if (IDENTITY_RATIO(scl_data->ratios.vert)) - scl_data->taps.v_taps = 1; - if (IDENTITY_RATIO(scl_data->ratios.horz_c)) - scl_data->taps.h_taps_c = 1; - if (IDENTITY_RATIO(scl_data->ratios.vert_c)) - scl_data->taps.v_taps_c = 1; + if (!xfm->ctx->dc->debug.always_scale) { + if (IDENTITY_RATIO(scl_data->ratios.horz)) + scl_data->taps.h_taps = 1; + if (IDENTITY_RATIO(scl_data->ratios.vert)) + scl_data->taps.v_taps = 1; + if (IDENTITY_RATIO(scl_data->ratios.horz_c)) + scl_data->taps.h_taps_c = 1; + if (IDENTITY_RATIO(scl_data->ratios.vert_c)) + scl_data->taps.v_taps_c = 1; + } return true; } -- cgit From 5d11e9fca5b45191b531d8fa3b9dd6de1156fc2b Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Mon, 29 May 2017 18:29:33 -0400 Subject: drm/amd/display: allow taking split pipes during resource mapping Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 43 +++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 6202b4b3e597..124fcac63eba 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1406,6 +1406,42 @@ static void calculate_phy_pix_clks(struct validate_context *context) } } +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +static int acquire_first_split_pipe( + struct resource_context *res_ctx, + const struct resource_pool *pool, + struct core_stream *stream) +{ + int i; + + for (i = 0; i < pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; + + if (pipe_ctx->top_pipe && + pipe_ctx->top_pipe->surface == pipe_ctx->surface) { + int mpc_idx = pipe_ctx->mpc_idx; + + pipe_ctx->top_pipe->bottom_pipe = pipe_ctx->bottom_pipe; + pipe_ctx->bottom_pipe->top_pipe = pipe_ctx->top_pipe; + + memset(pipe_ctx, 0, sizeof(*pipe_ctx)); + pipe_ctx->tg = pool->timing_generators[i]; + pipe_ctx->mi = pool->mis[i]; + pipe_ctx->ipp = pool->ipps[i]; + pipe_ctx->xfm = pool->transforms[i]; + pipe_ctx->opp = pool->opps[i]; + pipe_ctx->dis_clk = pool->display_clock; + pipe_ctx->pipe_idx = i; + pipe_ctx->mpc_idx = mpc_idx; + + pipe_ctx->stream = stream; + return i; + } + } + return -1; +} +#endif + enum dc_status resource_map_pool_resources( const struct core_dc *dc, struct validate_context *context, @@ -1477,8 +1513,11 @@ enum dc_status resource_map_pool_resources( if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; /* acquire new resources */ - pipe_idx = acquire_first_free_pipe( - &context->res_ctx, pool, stream); + pipe_idx = acquire_first_free_pipe(&context->res_ctx, pool, stream); +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + if (pipe_idx < 0) + acquire_first_split_pipe(&context->res_ctx, pool, stream); +#endif if (pipe_idx < 0) return DC_NO_CONTROLLER_RESOURCE; -- cgit From 05a19c39cb0adcb0f73b7418b9afead49d2406d4 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Mon, 29 May 2017 18:26:28 -0400 Subject: drm/amd/display: fix surface attachment handling of pipe split Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 35 +++++++---------------- 1 file changed, 10 insertions(+), 25 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 124fcac63eba..e6e3b181a3dc 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -894,24 +894,6 @@ enum dc_status resource_build_scaling_params_for_context( return DC_OK; } -static void detach_surfaces_for_stream( - struct validate_context *context, - const struct resource_pool *pool, - const struct dc_stream *dc_stream) -{ - int i; - struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); - - for (i = 0; i < pool->pipe_count; i++) { - struct pipe_ctx *cur_pipe = &context->res_ctx.pipe_ctx[i]; - if (cur_pipe->stream == stream) { - cur_pipe->surface = NULL; - cur_pipe->top_pipe = NULL; - cur_pipe->bottom_pipe = NULL; - } - } -} - struct pipe_ctx *find_idle_secondary_pipe( struct resource_context *res_ctx, const struct resource_pool *pool) @@ -1004,9 +986,11 @@ static void release_free_pipes_for_stream( struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); for (i = MAX_PIPES - 1; i >= 0; i--) { + /* never release the topmost pipe*/ if (res_ctx->pipe_ctx[i].stream == stream && + res_ctx->pipe_ctx[i].top_pipe && !res_ctx->pipe_ctx[i].surface) { - res_ctx->pipe_ctx[i].stream = NULL; + memset(&res_ctx->pipe_ctx[i], 0, sizeof(struct pipe_ctx)); } } } @@ -1021,6 +1005,7 @@ bool resource_attach_surfaces_to_context( int i; struct pipe_ctx *tail_pipe; struct dc_stream_status *stream_status = NULL; + struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); if (surface_count > MAX_SURFACE_NUM) { @@ -1043,7 +1028,12 @@ bool resource_attach_surfaces_to_context( for (i = 0; i < surface_count; i++) dc_surface_retain(surfaces[i]); - detach_surfaces_for_stream(context, pool, dc_stream); + /* detach surfaces from pipes */ + for (i = 0; i < pool->pipe_count; i++) + if (context->res_ctx.pipe_ctx[i].stream == stream) { + context->res_ctx.pipe_ctx[i].surface = NULL; + context->res_ctx.pipe_ctx[i].bottom_pipe = NULL; + } /* release existing surfaces*/ for (i = 0; i < stream_status->surface_count; i++) @@ -1052,11 +1042,6 @@ bool resource_attach_surfaces_to_context( for (i = surface_count; i < stream_status->surface_count; i++) stream_status->surfaces[i] = NULL; - stream_status->surface_count = 0; - - if (surface_count == 0) - return true; - tail_pipe = NULL; for (i = 0; i < surface_count; i++) { struct core_surface *surface = DC_SURFACE_TO_CORE(surfaces[i]); -- cgit From 0f9a536fe036eed82b563b0da5b2c57a9455b679 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Tue, 30 May 2017 13:38:10 -0400 Subject: drm/amd/display: fix mpo + split pipe aquisition failure Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 80 +++++++++++++---------- 1 file changed, 44 insertions(+), 36 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index e6e3b181a3dc..e4a6636fd829 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -995,6 +995,43 @@ static void release_free_pipes_for_stream( } } +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +static int acquire_first_split_pipe( + struct resource_context *res_ctx, + const struct resource_pool *pool, + struct core_stream *stream) +{ + int i; + + for (i = 0; i < pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; + + if (pipe_ctx->top_pipe && + pipe_ctx->top_pipe->surface == pipe_ctx->surface) { + int mpc_idx = pipe_ctx->mpc_idx; + + pipe_ctx->top_pipe->bottom_pipe = pipe_ctx->bottom_pipe; + if (pipe_ctx->bottom_pipe) + pipe_ctx->bottom_pipe->top_pipe = pipe_ctx->top_pipe; + + memset(pipe_ctx, 0, sizeof(*pipe_ctx)); + pipe_ctx->tg = pool->timing_generators[i]; + pipe_ctx->mi = pool->mis[i]; + pipe_ctx->ipp = pool->ipps[i]; + pipe_ctx->xfm = pool->transforms[i]; + pipe_ctx->opp = pool->opps[i]; + pipe_ctx->dis_clk = pool->display_clock; + pipe_ctx->pipe_idx = i; + pipe_ctx->mpc_idx = mpc_idx; + + pipe_ctx->stream = stream; + return i; + } + } + return -1; +} +#endif + bool resource_attach_surfaces_to_context( const struct dc_surface * const *surfaces, int surface_count, @@ -1048,6 +1085,13 @@ bool resource_attach_surfaces_to_context( struct pipe_ctx *free_pipe = acquire_free_pipe_for_stream( context, pool, dc_stream); +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + if (!free_pipe) { + int pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream); + if (pipe_idx >= 0) + free_pipe = &context->res_ctx.pipe_ctx[pipe_idx]; + } +#endif if (!free_pipe) { stream_status->surfaces[i] = NULL; return false; @@ -1391,42 +1435,6 @@ static void calculate_phy_pix_clks(struct validate_context *context) } } -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) -static int acquire_first_split_pipe( - struct resource_context *res_ctx, - const struct resource_pool *pool, - struct core_stream *stream) -{ - int i; - - for (i = 0; i < pool->pipe_count; i++) { - struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; - - if (pipe_ctx->top_pipe && - pipe_ctx->top_pipe->surface == pipe_ctx->surface) { - int mpc_idx = pipe_ctx->mpc_idx; - - pipe_ctx->top_pipe->bottom_pipe = pipe_ctx->bottom_pipe; - pipe_ctx->bottom_pipe->top_pipe = pipe_ctx->top_pipe; - - memset(pipe_ctx, 0, sizeof(*pipe_ctx)); - pipe_ctx->tg = pool->timing_generators[i]; - pipe_ctx->mi = pool->mis[i]; - pipe_ctx->ipp = pool->ipps[i]; - pipe_ctx->xfm = pool->transforms[i]; - pipe_ctx->opp = pool->opps[i]; - pipe_ctx->dis_clk = pool->display_clock; - pipe_ctx->pipe_idx = i; - pipe_ctx->mpc_idx = mpc_idx; - - pipe_ctx->stream = stream; - return i; - } - } - return -1; -} -#endif - enum dc_status resource_map_pool_resources( const struct core_dc *dc, struct validate_context *context, -- cgit From 2ea5e9a8bda7472037fb34b75f7033cfc4afa674 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Sun, 2 Apr 2017 11:55:41 -0400 Subject: drm/amd/display: Universal cursor plane hook-up. Switch from legacy cursor to DRM cursor plane. Cursor is not an actual plane but more of a subplane of each pipe. Bind a DRM cursor plane instance to each CRTC. Eliminate seperate FB object allocation for cursor and clean dm_crtc_cursor_set. Signed-off-by: Andrey Grodzovsky Signed-off-by: Leo (Sunpeng) Li Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 242 ++++++++------------- 1 file changed, 91 insertions(+), 151 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 7db04a487c21..068ed85bdc6d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -136,127 +136,27 @@ static void dm_set_cursor( } } -static int dm_crtc_unpin_cursor_bo_old( - struct amdgpu_crtc *amdgpu_crtc) -{ - struct amdgpu_bo *robj; - int ret = 0; - - if (NULL != amdgpu_crtc && NULL != amdgpu_crtc->cursor_bo) { - robj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo); - - ret = amdgpu_bo_reserve(robj, false); - - if (likely(ret == 0)) { - ret = amdgpu_bo_unpin(robj); - - if (unlikely(ret != 0)) { - DRM_ERROR( - "%s: unpin failed (ret=%d), bo %p\n", - __func__, - ret, - amdgpu_crtc->cursor_bo); - } - - amdgpu_bo_unreserve(robj); - } else { - DRM_ERROR( - "%s: reserve failed (ret=%d), bo %p\n", - __func__, - ret, - amdgpu_crtc->cursor_bo); - } - - drm_gem_object_unreference_unlocked(amdgpu_crtc->cursor_bo); - amdgpu_crtc->cursor_bo = NULL; - } - - return ret; -} - -static int dm_crtc_pin_cursor_bo_new( - struct drm_crtc *crtc, - struct drm_file *file_priv, - uint32_t handle, - struct amdgpu_bo **ret_obj) -{ - struct amdgpu_crtc *amdgpu_crtc; - struct amdgpu_bo *robj; - struct drm_gem_object *obj; - int ret = -EINVAL; - - if (NULL != crtc) { - struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; - uint64_t gpu_addr; - - amdgpu_crtc = to_amdgpu_crtc(crtc); - - obj = drm_gem_object_lookup(file_priv, handle); - - if (!obj) { - DRM_ERROR( - "Cannot find cursor object %x for crtc %d\n", - handle, - amdgpu_crtc->crtc_id); - goto release; - } - robj = gem_to_amdgpu_bo(obj); - - ret = amdgpu_bo_reserve(robj, false); - - if (unlikely(ret != 0)) { - drm_gem_object_unreference_unlocked(obj); - DRM_ERROR("dm_crtc_pin_cursor_bo_new ret %x, handle %x\n", - ret, handle); - goto release; - } - - ret = amdgpu_bo_pin_restricted(robj, AMDGPU_GEM_DOMAIN_VRAM, 0, - adev->mc.visible_vram_size, - &gpu_addr); - - if (ret == 0) { - amdgpu_crtc->cursor_addr = gpu_addr; - *ret_obj = robj; - } - amdgpu_bo_unreserve(robj); - if (ret) - drm_gem_object_unreference_unlocked(obj); - - } -release: - - return ret; -} - static int dm_crtc_cursor_set( struct drm_crtc *crtc, - struct drm_file *file_priv, - uint32_t handle, + uint64_t address, uint32_t width, uint32_t height) { - struct amdgpu_bo *new_cursor_bo; struct dc_cursor_position position; int ret; struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); - ret = EINVAL; - new_cursor_bo = NULL; DRM_DEBUG_KMS( - "%s: crtc_id=%d with handle %d and size %d to %d, bo_object %p\n", + "%s: crtc_id=%d with size %d to %d \n", __func__, amdgpu_crtc->crtc_id, - handle, width, - height, - amdgpu_crtc->cursor_bo); + height); - if (!handle) { + if (!address) { /* turn off cursor */ position.enable = false; position.x = 0; @@ -268,8 +168,6 @@ static int dm_crtc_cursor_set( amdgpu_crtc->stream, &position); } - /*unpin old cursor buffer and update cache*/ - ret = dm_crtc_unpin_cursor_bo_old(amdgpu_crtc); goto release; } @@ -283,21 +181,9 @@ static int dm_crtc_cursor_set( height); goto release; } - /*try to pin new cursor bo*/ - ret = dm_crtc_pin_cursor_bo_new(crtc, file_priv, handle, &new_cursor_bo); - /*if map not successful then return an error*/ - if (ret) - goto release; /*program new cursor bo to hardware*/ - dm_set_cursor(amdgpu_crtc, amdgpu_crtc->cursor_addr, width, height); - - /*un map old, not used anymore cursor bo , - * return memory and mapping back */ - dm_crtc_unpin_cursor_bo_old(amdgpu_crtc); - - /*assign new cursor bo to our internal cache*/ - amdgpu_crtc->cursor_bo = &new_cursor_bo->gem_base; + dm_set_cursor(amdgpu_crtc, address, width, height); release: return ret; @@ -359,23 +245,6 @@ static int dm_crtc_cursor_move(struct drm_crtc *crtc, return 0; } -static void dm_crtc_cursor_reset(struct drm_crtc *crtc) -{ - struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); - - DRM_DEBUG_KMS( - "%s: with cursor_bo %p\n", - __func__, - amdgpu_crtc->cursor_bo); - - if (amdgpu_crtc->cursor_bo && amdgpu_crtc->stream) { - dm_set_cursor( - amdgpu_crtc, - amdgpu_crtc->cursor_addr, - amdgpu_crtc->cursor_width, - amdgpu_crtc->cursor_height); - } -} static bool fill_rects_from_plane_state( const struct drm_plane_state *state, struct dc_surface *surface) @@ -1094,8 +963,6 @@ void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc) /* Implemented only the options currently availible for the driver */ static const struct drm_crtc_funcs amdgpu_dm_crtc_funcs = { .reset = drm_atomic_helper_crtc_reset, - .cursor_set = dm_crtc_cursor_set, - .cursor_move = dm_crtc_cursor_move, .destroy = amdgpu_dm_crtc_destroy, .gamma_set = drm_atomic_helper_legacy_gamma_set, .set_config = drm_atomic_helper_set_config, @@ -1571,6 +1438,18 @@ static int dm_plane_helper_prepare_fb( } amdgpu_bo_ref(rbo); + + /* It's a hack for s3 since in 4.9 kernel filter out cursor buffer + * prepare and cleanup in drm_atomic_helper_prepare_planes + * and drm_atomic_helper_cleanup_planes because fb doens't in s3. + * IN 4.10 kernel this code should be removed and amdgpu_device_suspend + * code touching fram buffers should be avoided for DC. + */ + if (plane->type == DRM_PLANE_TYPE_CURSOR) { + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(new_state->crtc); + + acrtc->cursor_bo = obj; + } return 0; } @@ -1668,6 +1547,10 @@ static uint32_t yuv_formats[] = { DRM_FORMAT_NV21, }; +static const u32 cursor_formats[] = { + DRM_FORMAT_ARGB8888 +}; + int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, struct amdgpu_plane *aplane, unsigned long possible_crtcs) @@ -1698,7 +1581,14 @@ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, NULL, aplane->plane_type, NULL); break; case DRM_PLANE_TYPE_CURSOR: - DRM_ERROR("KMS: Cursor plane not implemented."); + res = drm_universal_plane_init( + dm->adev->ddev, + &aplane->base, + possible_crtcs, + &dm_plane_funcs, + cursor_formats, + ARRAY_SIZE(cursor_formats), + NULL, aplane->plane_type, NULL); break; } @@ -1711,9 +1601,18 @@ int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, struct drm_plane *plane, uint32_t crtc_index) { - struct amdgpu_crtc *acrtc; + struct amdgpu_crtc *acrtc = NULL; + struct amdgpu_plane *cursor_plane; + int res = -ENOMEM; + cursor_plane = kzalloc(sizeof(*cursor_plane), GFP_KERNEL); + if (!cursor_plane) + goto fail; + + cursor_plane->base.type = DRM_PLANE_TYPE_CURSOR; + res = amdgpu_dm_plane_init(dm, cursor_plane, 0); + acrtc = kzalloc(sizeof(struct amdgpu_crtc), GFP_KERNEL); if (!acrtc) goto fail; @@ -1722,7 +1621,7 @@ int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, dm->ddev, &acrtc->base, plane, - NULL, + &cursor_plane->base, &amdgpu_dm_crtc_funcs, NULL); if (res) @@ -1740,12 +1639,17 @@ int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, drm_mode_crtc_set_gamma_size(&acrtc->base, 256); return 0; + fail: - kfree(acrtc); + if (acrtc) + kfree(acrtc); + if (cursor_plane) + kfree(cursor_plane); acrtc->crtc_id = -1; return res; } + static int to_drm_connector_type(enum signal_type st) { switch (st) { @@ -2252,6 +2156,34 @@ static void remove_stream(struct amdgpu_device *adev, struct amdgpu_crtc *acrtc) acrtc->enabled = false; } +static void handle_cursor_update( + struct drm_plane *plane, + struct drm_plane_state *old_plane_state) +{ + if (!plane->state->fb && !old_plane_state->fb) + return; + + /* Check if it's a cursor on/off update or just cursor move*/ + if (plane->state->fb == old_plane_state->fb) + dm_crtc_cursor_move( + plane->state->crtc, + plane->state->crtc_x, + plane->state->crtc_y); + else { + struct amdgpu_framebuffer *afb = + to_amdgpu_framebuffer(plane->state->fb); + dm_crtc_cursor_set( + (!!plane->state->fb) ? + plane->state->crtc : + old_plane_state->crtc, + (!!plane->state->fb) ? + afb->address : + 0, + plane->state->crtc_w, + plane->state->crtc_h); + } +} + /* * Executes flip @@ -2343,6 +2275,11 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, struct dm_connector_state *con_state = NULL; bool pflip_needed; + if (plane->type == DRM_PLANE_TYPE_CURSOR) { + handle_cursor_update(plane, old_plane_state); + continue; + } + if (!fb || !crtc || !crtc->state->active) continue; @@ -2627,7 +2564,6 @@ void amdgpu_dm_atomic_commit_tail( adev->dm.freesync_module, &acrtc->stream, 1); manage_dm_interrupts(adev, acrtc, true); - dm_crtc_cursor_reset(&acrtc->base); } @@ -3007,18 +2943,19 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, } } + /* - * TODO revisit when removing commit action - * and looking at atomic flags directly + * Hack: Commit needs planes right now, specifically for gamma + * TODO rework commit to check CRTC for gamma change */ + if (crtc_state->color_mgmt_changed) { - /* commit needs planes right now (for gamma, eg.) */ - /* TODO rework commit to chack crtc for gamma change */ - ret = drm_atomic_add_affected_planes(state, crtc); - if (ret) - return ret; + ret = drm_atomic_add_affected_planes(state, crtc); + if (ret) + return ret; - ret = -EINVAL; + ret = -EINVAL; + } } /* Check scaling and undersacn changes*/ @@ -3073,6 +3010,9 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, struct drm_crtc_state *crtc_state; bool pflip_needed; + /*TODO Implement atomic check for cursor plane */ + if (plane->type == DRM_PLANE_TYPE_CURSOR) + continue; if (!fb || !crtc || crtc_set[i] != crtc || !crtc->state->planes_changed || !crtc->state->active) -- cgit From 7db4dede6425fba7177468123e5149916dd45fd4 Mon Sep 17 00:00:00 2001 From: Amy Zhang Date: Tue, 30 May 2017 16:16:57 -0400 Subject: drm/amd/display: Add function to get PSR state Signed-off-by: Amy Zhang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 13 +++++++++++++ drivers/gpu/drm/amd/display/dc/dc.h | 2 ++ drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c | 2 ++ drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h | 1 + 4 files changed, 18 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 79f3947a3ee1..318aaa762f31 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1444,6 +1444,19 @@ bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable) return true; } +bool dc_link_get_psr_state(const struct dc_link *dc_link, uint32_t *psr_state) +{ + struct core_link *link = DC_LINK_TO_CORE(dc_link); + struct dc_context *ctx = link->ctx; + struct core_dc *core_dc = DC_TO_CORE(ctx->dc); + struct dmcu *dmcu = core_dc->res_pool->dmcu; + + if (dmcu != NULL && link->psr_enabled) + dmcu->funcs->get_psr_state(dmcu, psr_state); + + return true; +} + bool dc_link_setup_psr(const struct dc_link *dc_link, const struct dc_stream *stream, struct psr_config *psr_config) { diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index ce052d12a104..328bfcb7dbb8 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -702,6 +702,8 @@ bool dc_link_set_abm_disable(const struct dc_link *dc_link); bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable); +bool dc_link_get_psr_state(const struct dc_link *dc_link, uint32_t *psr_state); + bool dc_link_setup_psr(const struct dc_link *dc_link, const struct dc_stream *stream, struct psr_config *psr_config); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c index c58328cd787b..03b51e256e21 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c @@ -470,6 +470,7 @@ static const struct dmcu_funcs dce_funcs = { .load_iram = dce_dmcu_load_iram, .set_psr_enable = dce_dmcu_set_psr_enable, .setup_psr = dce_dmcu_setup_psr, + .get_psr_state = dce_get_dmcu_psr_state }; #if defined(CONFIG_DRM_AMD_DC_DCN1_0) @@ -477,6 +478,7 @@ static const struct dmcu_funcs dcn10_funcs = { .load_iram = dcn10_dmcu_load_iram, .set_psr_enable = dcn10_dmcu_set_psr_enable, .setup_psr = dcn10_dmcu_setup_psr, + .get_psr_state = dcn10_get_dmcu_psr_state }; #endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h index 656cfdc79891..dff0babb5cf7 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h @@ -41,6 +41,7 @@ struct dmcu_funcs { void (*setup_psr)(struct dmcu *dmcu, struct core_link *link, struct psr_context *psr_context); + void (*get_psr_state)(struct dmcu *dmcu, uint32_t *psr_state); }; #endif -- cgit From 1605b3bef8454a8906333f7a0ca0fb177422100d Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Wed, 5 Apr 2017 12:02:45 -0400 Subject: drm/amd/display: Remove redundant member from amdgpu_plane. Signed-off-by: Andrey Grodzovsky Signed-off-by: Leo (Sunpeng) Li Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') 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 74415fdf7ed8..6b25a7ba2f7d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1203,7 +1203,7 @@ int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) DRM_ERROR("KMS: Failed to allocate surface\n"); goto fail_free_planes; } - mode_info->planes[i]->plane_type = mode_info->plane_type[i]; + mode_info->planes[i]->base.type = mode_info->plane_type[i]; if (amdgpu_dm_plane_init(dm, mode_info->planes[i], 0xff)) { DRM_ERROR("KMS: Failed to initialize plane\n"); goto fail_free_planes; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 068ed85bdc6d..b99f6ef499d1 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -1557,7 +1557,7 @@ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, { int res = -EPERM; - switch (aplane->plane_type) { + switch (aplane->base.type) { case DRM_PLANE_TYPE_PRIMARY: aplane->base.format_default = true; @@ -1568,7 +1568,7 @@ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, &dm_plane_funcs, rgb_formats, ARRAY_SIZE(rgb_formats), - NULL, aplane->plane_type, NULL); + NULL, aplane->base.type, NULL); break; case DRM_PLANE_TYPE_OVERLAY: res = drm_universal_plane_init( @@ -1578,7 +1578,7 @@ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, &dm_plane_funcs, yuv_formats, ARRAY_SIZE(yuv_formats), - NULL, aplane->plane_type, NULL); + NULL, aplane->base.type, NULL); break; case DRM_PLANE_TYPE_CURSOR: res = drm_universal_plane_init( @@ -1588,7 +1588,7 @@ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, &dm_plane_funcs, cursor_formats, ARRAY_SIZE(cursor_formats), - NULL, aplane->plane_type, NULL); + NULL, aplane->base.type, NULL); break; } -- cgit From 5970f2aecc558ce2e04565ff082d9b78144fc714 Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Tue, 30 May 2017 15:26:14 -0400 Subject: drm/amd/display: Enable DCN clock gating Signed-off-by: Hersen Wu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 68 +++++++++++++++++----- .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 4 -- 2 files changed, 53 insertions(+), 19 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 62a77f48d437..24c1a0f5febe 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -516,12 +516,14 @@ static void power_on_plane( /* disable clock power gating */ /* DCCG_GATE_DISABLE_CNTL only has one instance */ - HWSEQ_REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL, - DISPCLK_DCCG_GATE_DISABLE, 1, - DPPCLK_GATE_DISABLE, 1); - /* DCFCLK_CNTL only has one instance */ - HWSEQ_REG_UPDATE(DCFCLK_CNTL, - DCFCLK_GATE_DIS, 1); + if (ctx->dc->debug.disable_clock_gate) { + HWSEQ_REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL, + DISPCLK_DCCG_GATE_DISABLE, 1, + DPPCLK_GATE_DISABLE, 1); + /* DCFCLK_CNTL only has one instance */ + HWSEQ_REG_UPDATE(DCFCLK_CNTL, + DCFCLK_GATE_DIS, 1); + } HWSEQ_REG_SET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, 1); @@ -533,14 +535,6 @@ static void power_on_plane( if (ctx->dc->debug.disable_clock_gate) { HWSEQ_REG_UPDATE(DCCG_GATE_DISABLE_CNTL, DISPCLK_DCCG_GATE_DISABLE, 0); - } else { - /* DCCG_GATE_DISABLE_CNTL only has one instance. inst_offset = 0 */ - HWSEQ_REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL, - DISPCLK_DCCG_GATE_DISABLE, 0, - DPPCLK_GATE_DISABLE, 0); - /* DCFCLK_CNTL only has one instance. inst_offset = 0 */ - HWSEQ_REG_UPDATE(DCFCLK_CNTL, - DCFCLK_GATE_DIS, 0); } } @@ -666,14 +660,58 @@ static void init_hw(struct core_dc *dc) FD(DIO_MEM_PWR_CTRL__HDMI5_MEM_PWR_FORCE), 0, FD(DIO_MEM_PWR_CTRL__HDMI6_MEM_PWR_FORCE), 0); + if (!dc->public.debug.disable_clock_gate) { + /* enable all DCN clock gating */ + generic_reg_set_soc15(dc->ctx, 0, DCCG_GATE_DISABLE_CNTL, 19, + FD(DCCG_GATE_DISABLE_CNTL__DISPCLK_DCCG_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL__DISPCLK_R_DCCG_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL__SOCCLK_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL__DPREFCLK_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL__DACACLK_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL__DVOACLK_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL__DPREFCLK_R_DCCG_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL__DPPCLK_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL__AOMCLK0_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL__AOMCLK1_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL__AOMCLK2_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL__AUDIO_DTO2_CLK_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL__DPREFCLK_GTC_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL__UNB_DB_CLK_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL__REFCLK_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL__REFCLK_R_DIG_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL__DSICLK_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL__BYTECLK_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL__ESCCLK_GATE_DISABLE), 0); + + generic_reg_set_soc15(dc->ctx, 0, DCCG_GATE_DISABLE_CNTL2, 14, + FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKA_FE_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKB_FE_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKC_FE_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKD_FE_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKE_FE_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKF_FE_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKG_FE_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKA_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKB_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKC_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKD_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKE_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKF_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKG_GATE_DISABLE), 0); + + generic_reg_update_soc15(dc->ctx, 0, DCFCLK_CNTL, 1, + FD(DCFCLK_CNTL__DCFCLK_GATE_DIS), 0); + } + /* This power gating should be one-time program for DAL. * It can only change by registry key * TODO: new task will for this. * if power gating is disable, power_on_plane and power_off_plane * should be skip. Otherwise, hand will be met in power_off_plane */ - enable_power_gating_plane(dc->ctx, true); + + } static enum dc_status dcn10_prog_pixclk_crtc_otg( diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 94cd7a9b0b19..660cb43fd3bc 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -426,8 +426,6 @@ static const struct resource_caps res_cap = { static const struct dc_debug debug_defaults_drv = { .disable_dcc = false, - .disable_dpp_power_gate = false, - .disable_hubp_power_gate = false, .disable_dmcu = true, .force_abm_enable = false, .timing_trace = false, @@ -440,8 +438,6 @@ static const struct dc_debug debug_defaults_drv = { }; static const struct dc_debug debug_defaults_diags = { - .disable_dpp_power_gate = false, - .disable_hubp_power_gate = false, .disable_clock_gate = true, .disable_dmcu = true, .force_abm_enable = false, -- cgit From 9c42df59e44fd44cd84fe9ccd64f9f2942164d0f Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Thu, 1 Jun 2017 15:29:42 -0400 Subject: drm/amd/display: Remove unsupported RGB formats Do not broadcast (to DRM) unsupported RGB formats. Signed-off-by: Leo (Sunpeng) Li Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index b99f6ef499d1..165f91fa1206 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -1527,11 +1527,6 @@ static const struct drm_plane_helper_funcs dm_plane_helper_funcs = { * check will succeed, and let DC to implement proper check */ static uint32_t rgb_formats[] = { - DRM_FORMAT_XRGB4444, - DRM_FORMAT_ARGB4444, - DRM_FORMAT_RGBA4444, - DRM_FORMAT_ARGB1555, - DRM_FORMAT_RGB565, DRM_FORMAT_RGB888, DRM_FORMAT_XRGB8888, DRM_FORMAT_ARGB8888, -- cgit From e7b1322e15ea66c135ff98c1eb15fc542ef79c89 Mon Sep 17 00:00:00 2001 From: Corbin McElhanney Date: Thu, 1 Jun 2017 15:40:04 -0400 Subject: drm/amd/display: Don't update surface if dimensions are 0 Signed-off-by: Corbin McElhanney Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 323a5e706908..976229eb2492 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1250,8 +1250,15 @@ void dc_update_surfaces_and_stream(struct dc *dc, } } - /* only proceed if we need to make a surface update */ - if (!srf_updates) + /* do not perform surface update if surface has invalid dimensions + * (all zero) and no scaling_info is provided + */ + if (surface_count > 0 && + srf_updates->surface->src_rect.width == 0 && + srf_updates->surface->src_rect.height == 0 && + srf_updates->surface->dst_rect.width == 0 && + srf_updates->surface->dst_rect.height == 0 && + !srf_updates->scaling_info) return; update_type = dc_check_update_surfaces_for_stream( -- cgit From dcf6c1456ef555c4a1c0d28326a7bac2fc6923de Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Thu, 1 Jun 2017 12:27:00 -0400 Subject: drm/amd/display: clean up mpc programing during fe reset Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 24c1a0f5febe..877e2b6a7dd5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -868,16 +868,10 @@ static void reset_front_end_for_pipe( */ tree_cfg = &dc->current_context->res_ctx.mpc_tree[pipe_ctx->mpc_idx]; - if (pipe_ctx->top_pipe == NULL) - dcn10_delete_mpc_tree(mpc, tree_cfg); - else { - if (dcn10_remove_dpp(mpc, tree_cfg, pipe_ctx->pipe_idx)) - pipe_ctx->top_pipe->bottom_pipe = NULL; - else { - dm_logger_write(dc->ctx->logger, LOG_RESOURCE, - "%s: failed to find dpp to be removed!\n", - __func__); - } + if (!dcn10_remove_dpp(mpc, tree_cfg, pipe_ctx->pipe_idx)) { + dm_logger_write(dc->ctx->logger, LOG_RESOURCE, + "%s: failed to find dpp to be removed!\n", + __func__); } pipe_ctx->top_pipe = NULL; -- cgit From 556ee1b75c94cd88710e2fa8c83e2dc22717fc4f Mon Sep 17 00:00:00 2001 From: Corbin McElhanney Date: Thu, 1 Jun 2017 16:54:53 -0400 Subject: drm/amd/display: Add assertion for invalid surface dimensions Signed-off-by: Corbin McElhanney Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 976229eb2492..f5102b644942 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1258,8 +1258,10 @@ void dc_update_surfaces_and_stream(struct dc *dc, srf_updates->surface->src_rect.height == 0 && srf_updates->surface->dst_rect.width == 0 && srf_updates->surface->dst_rect.height == 0 && - !srf_updates->scaling_info) + !srf_updates->scaling_info) { + ASSERT(false); return; + } update_type = dc_check_update_surfaces_for_stream( dc, srf_updates, surface_count, stream_update, stream_status); -- cgit From 1e25ed30796b89140653c60ac20ea1c8254c9e91 Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Thu, 1 Jun 2017 15:49:16 -0400 Subject: drm/amd/display: remove disable_clk_gate debug flag for DCN Signed-off-by: Hersen Wu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 30 ---------------------- .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 1 - 2 files changed, 31 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 877e2b6a7dd5..0e677f9db96a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -397,19 +397,6 @@ static void enable_power_gating_plane( HWSEQ_REG_UPDATE(DOMAIN3_PG_CONFIG, DOMAIN3_POWER_FORCEON, force_on); HWSEQ_REG_UPDATE(DOMAIN5_PG_CONFIG, DOMAIN5_POWER_FORCEON, force_on); HWSEQ_REG_UPDATE(DOMAIN7_PG_CONFIG, DOMAIN7_POWER_FORCEON, force_on); - - if (ctx->dc->debug.disable_clock_gate) { - /* probably better to just write entire register to 0xffff to - * ensure all clock gating is disabled - */ - HWSEQ_REG_UPDATE_3(DCCG_GATE_DISABLE_CNTL, - DISPCLK_R_DCCG_GATE_DISABLE, 1, - DPREFCLK_R_DCCG_GATE_DISABLE, 1, - REFCLK_R_DIG_GATE_DISABLE, 1); - HWSEQ_REG_UPDATE(DCFCLK_CNTL, - DCFCLK_GATE_DIS, 1); - } - } static void dpp_pg_control( @@ -513,29 +500,12 @@ static void power_on_plane( { uint32_t inst_offset = 0; - /* disable clock power gating */ - - /* DCCG_GATE_DISABLE_CNTL only has one instance */ - if (ctx->dc->debug.disable_clock_gate) { - HWSEQ_REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL, - DISPCLK_DCCG_GATE_DISABLE, 1, - DPPCLK_GATE_DISABLE, 1); - /* DCFCLK_CNTL only has one instance */ - HWSEQ_REG_UPDATE(DCFCLK_CNTL, - DCFCLK_GATE_DIS, 1); - } - HWSEQ_REG_SET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, 1); dpp_pg_control(ctx, plane_id, true); hubp_pg_control(ctx, plane_id, true); HWSEQ_REG_SET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, 0); - - if (ctx->dc->debug.disable_clock_gate) { - HWSEQ_REG_UPDATE(DCCG_GATE_DISABLE_CNTL, - DISPCLK_DCCG_GATE_DISABLE, 0); - } } /* fully check bios enabledisplaypowergating table. dal only need dce init diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 660cb43fd3bc..e527d10b3e1f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -438,7 +438,6 @@ static const struct dc_debug debug_defaults_drv = { }; static const struct dc_debug debug_defaults_diags = { - .disable_clock_gate = true, .disable_dmcu = true, .force_abm_enable = false, .timing_trace = true, -- cgit From 8eee20139a63c6b53abc71c9a937f2b2047176c2 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Fri, 2 Jun 2017 06:15:57 -0400 Subject: drm/amd/display: disable forced stutter disable after programming watermark vbios will disable stutter pre-OS. driver re-enable after programming watermark Signed-off-by: Tony Cheng Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c | 5 +++++ drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h | 6 ++++++ 2 files changed, 11 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index da2f99dcd766..3e3fcf2395ae 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -582,6 +582,7 @@ static void program_watermarks( unsigned int refclk_mhz) { struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + uint32_t force_en = mem_input->ctx->dc->debug.disable_stutter ? 1 : 0; /* * Need to clamp to max of the register values (i.e. no wrap) * for dcn1, all wm registers are 21-bit wide @@ -793,6 +794,10 @@ static void program_watermarks( REG_UPDATE(DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 68); + REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL, + DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE, 0, + DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, force_en); + #if 0 REG_UPDATE_2(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE, 1, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h index 48b313b213c0..37683d072b42 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h @@ -127,6 +127,7 @@ SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D),\ SR(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D),\ SR(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL),\ + SR(DCHUBBUB_ARB_DRAM_STATE_CNTL),\ SR(DCHUBBUB_ARB_SAT_LEVEL),\ SR(DCHUBBUB_ARB_DF_REQ_OUTSTAND),\ /* todo: get these from GVM instead of reading registers ourselves */\ @@ -239,6 +240,7 @@ struct dcn_mi_registers { uint32_t DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D; uint32_t DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D; uint32_t DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL; + uint32_t DCHUBBUB_ARB_DRAM_STATE_CNTL; uint32_t DCHUBBUB_ARB_SAT_LEVEL; uint32_t DCHUBBUB_ARB_DF_REQ_OUTSTAND; @@ -381,6 +383,8 @@ struct dcn_mi_registers { MI_SF(DCHUBBUB_SDPIF_AGP_TOP, SDPIF_AGP_TOP, mask_sh),\ MI_SF(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, mask_sh),\ MI_SF(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE, mask_sh),\ + MI_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE, mask_sh),\ + MI_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, mask_sh),\ MI_SF(DCHUBBUB_ARB_SAT_LEVEL, DCHUBBUB_ARB_SAT_LEVEL, mask_sh),\ MI_SF(DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MIN_REQ_OUTSTAND, mask_sh),\ /* todo: get these from GVM instead of reading registers ourselves */\ @@ -515,6 +519,8 @@ struct dcn_mi_registers { type SDPIF_AGP_TOP;\ type DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST;\ type DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE;\ + type DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE;\ + type DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE;\ type DCHUBBUB_ARB_SAT_LEVEL;\ type DCHUBBUB_ARB_MIN_REQ_OUTSTAND;\ /* todo: get these from GVM instead of reading registers ourselves */\ -- cgit From 1a2c82a2f161f68deb5f0519c315bfc92ede8e01 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 2 Jun 2017 19:00:45 -0400 Subject: drm/amd/display: fix mpc alpha programming Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 78 +++----- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c | 201 +++++++++------------ drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h | 6 +- drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h | 19 +- 4 files changed, 115 insertions(+), 189 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 0e677f9db96a..447f6bf4644c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -125,14 +125,8 @@ static void lock_otg_master_update( HWSEQ_REG_UPDATE(OTG0_OTG_GLOBAL_CONTROL0, OTG_MASTER_UPDATE_LOCK_SEL, inst); - /* unlock master locker */ HWSEQ_REG_UPDATE(OTG0_OTG_MASTER_UPDATE_LOCK, OTG_MASTER_UPDATE_LOCK, 1); - - /* wait for unlock happens */ - if (!wait_reg(ctx, inst_offset, OTG0_OTG_MASTER_UPDATE_LOCK, UPDATE_LOCK_STATUS, 1)) - BREAK_TO_DEBUGGER(); - } static bool unlock_master_tg_and_wait( @@ -1562,8 +1556,9 @@ static void update_dchubp_dpp( enum dc_color_space color_space; struct tg_color black_color = {0}; struct dcn10_mpc *mpc = TO_DCN10_MPC(dc->res_pool->mpc); - - struct pipe_ctx *cur_pipe_ctx = &dc->current_context->res_ctx.pipe_ctx[pipe_ctx->pipe_idx]; + struct pipe_ctx *temp_pipe; + int i; + int tree_pos = 0; /* depends on DML calculation, DPP clock value may change dynamically */ enable_dppclk( @@ -1609,41 +1604,30 @@ static void update_dchubp_dpp( /* TODO: build stream pipes group id. For now, use stream otg * id as pipe group id */ - pipe_ctx->mpc_idx = pipe_ctx->tg->inst; - tree_cfg = &context->res_ctx.mpc_tree[pipe_ctx->mpc_idx]; - - /* enable when bottom pipe is present and - * it does not share a surface with current pipe - */ - if (pipe_ctx->bottom_pipe && surface != pipe_ctx->bottom_pipe->surface) { + /*pipe_ctx->scl_data.lb_params.alpha_en = pipe_ctx->surface->public.per_pixel_alpha;*/ + if (pipe_ctx->bottom_pipe && surface != pipe_ctx->bottom_pipe->surface) pipe_ctx->scl_data.lb_params.alpha_en = 1; - tree_cfg->mode = TOP_BLND; - } else { + else pipe_ctx->scl_data.lb_params.alpha_en = 0; - tree_cfg->mode = TOP_PASSTHRU; - } - if (!pipe_ctx->top_pipe && !cur_pipe_ctx->bottom_pipe) { - /* primary pipe, set mpc tree index 0 only */ - tree_cfg->num_pipes = 1; + pipe_ctx->mpc_idx = pipe_ctx->tg->inst; + tree_cfg = &context->res_ctx.mpc_tree[pipe_ctx->mpc_idx]; + if (tree_cfg->num_pipes == 0) { tree_cfg->opp_id = pipe_ctx->tg->inst; - tree_cfg->dpp[0] = pipe_ctx->pipe_idx; - tree_cfg->mpcc[0] = pipe_ctx->pipe_idx; + for (i = 0; i < MAX_PIPES; i++) { + tree_cfg->dpp[i] = 0xf; + tree_cfg->mpcc[i] = 0xf; + } } - if (!cur_pipe_ctx->top_pipe && !pipe_ctx->top_pipe) { - - if (!cur_pipe_ctx->bottom_pipe) - dcn10_set_mpc_tree(mpc, tree_cfg); - - } else if (!cur_pipe_ctx->top_pipe && pipe_ctx->top_pipe) { - - dcn10_add_dpp(mpc, tree_cfg, - pipe_ctx->pipe_idx, pipe_ctx->pipe_idx, 1); - } else { - /* nothing to be done here */ - ASSERT(cur_pipe_ctx->top_pipe && pipe_ctx->top_pipe); - } + for (temp_pipe = pipe_ctx->top_pipe; + temp_pipe != NULL; temp_pipe = temp_pipe->top_pipe) + tree_pos++; + tree_cfg->dpp[tree_pos] = pipe_ctx->pipe_idx; + tree_cfg->mpcc[tree_pos] = pipe_ctx->pipe_idx; + tree_cfg->per_pixel_alpha[tree_pos] = pipe_ctx->scl_data.lb_params.alpha_en; + tree_cfg->num_pipes = tree_pos + 1; + dcn10_set_mpc_tree(mpc, tree_cfg); color_space = pipe_ctx->stream->public.output_color_space; color_space_to_black_color(dc, color_space, &black_color); @@ -1680,18 +1664,15 @@ static void program_all_pipe_in_tree( { unsigned int ref_clk_mhz = dc->res_pool->ref_clock_inKhz/1000; - if (pipe_ctx->surface->public.visible || pipe_ctx->top_pipe == NULL) { - dcn10_power_on_fe(dc, pipe_ctx, context); + if (pipe_ctx->top_pipe == NULL) { /* lock otg_master_update to process all pipes associated with * this OTG. this is done only one time. */ - if (pipe_ctx->top_pipe == NULL) { - /* watermark is for all pipes */ - pipe_ctx->mi->funcs->program_watermarks( - pipe_ctx->mi, &context->bw.dcn.watermarks, ref_clk_mhz); - lock_otg_master_update(dc->ctx, pipe_ctx->tg->inst); - } + /* watermark is for all pipes */ + pipe_ctx->mi->funcs->program_watermarks( + pipe_ctx->mi, &context->bw.dcn.watermarks, ref_clk_mhz); + lock_otg_master_update(dc->ctx, pipe_ctx->tg->inst); pipe_ctx->tg->dlg_otg_param.vready_offset = pipe_ctx->pipe_dlg_param.vready_offset; pipe_ctx->tg->dlg_otg_param.vstartup_start = pipe_ctx->pipe_dlg_param.vstartup_start; @@ -1702,12 +1683,11 @@ static void program_all_pipe_in_tree( pipe_ctx->tg->funcs->program_global_sync( pipe_ctx->tg); pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, !is_pipe_tree_visible(pipe_ctx)); + } - - + if (pipe_ctx->surface->public.visible) { + dcn10_power_on_fe(dc, pipe_ctx, context); update_dchubp_dpp(dc, pipe_ctx, context); - - /* Only support one plane for now. */ } if (pipe_ctx->bottom_pipe != NULL) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c index cb22cd130e1a..58f80114e36b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c @@ -36,6 +36,9 @@ #define FN(reg_name, field_name) \ mpc->mpc_shift->field_name, mpc->mpc_mask->field_name +#define MODE_TOP_ONLY 1 +#define MODE_BLEND 3 + /* Internal function to set mpc output mux */ static void set_output_mux(struct dcn10_mpc *mpc, uint8_t opp_id, @@ -45,32 +48,7 @@ static void set_output_mux(struct dcn10_mpc *mpc, REG_UPDATE(OPP_PIPE_CONTROL[opp_id], OPP_PIPE_CLOCK_EN, 1); - REG_SET(MUX[opp_id], 0, - MPC_OUT_MUX, mpcc_id); - -/* TODO: Move to post when ready. - if (mpcc_id == 0xf) { - MPCC_REG_UPDATE(OPP_PIPE0_OPP_PIPE_CONTROL, - OPP_PIPE_CLOCK_EN, 0); - } -*/ -} - -static void set_blend_mode(struct dcn10_mpc *mpc, - enum blend_mode mode, - uint8_t mpcc_id) -{ - /* Enable per-pixel alpha on this pipe */ - if (mode == TOP_BLND) - REG_UPDATE_3(MPCC_CONTROL[mpcc_id], - MPCC_ALPHA_BLND_MODE, 0, - MPCC_ALPHA_MULTIPLIED_MODE, 0, - MPCC_BLND_ACTIVE_OVERLAP_ONLY, 0); - else - REG_UPDATE_3(MPCC_CONTROL[mpcc_id], - MPCC_ALPHA_BLND_MODE, 0, - MPCC_ALPHA_MULTIPLIED_MODE, 1, - MPCC_BLND_ACTIVE_OVERLAP_ONLY, 1); + REG_SET(MUX[opp_id], 0, MPC_OUT_MUX, mpcc_id); } void dcn10_set_mpc_background_color(struct dcn10_mpc *mpc, @@ -121,44 +99,27 @@ void dcn10_set_mpc_tree(struct dcn10_mpc *mpc, REG_SET(MPCC_BOT_SEL[mpcc_inst], 0, MPCC_BOT_SEL, 0xF); - /* MPCC_CONTROL->MPCC_MODE */ REG_UPDATE(MPCC_CONTROL[mpcc_inst], - MPCC_MODE, tree_cfg->mode); + MPCC_MODE, MODE_TOP_ONLY); } else { REG_SET(MPCC_BOT_SEL[mpcc_inst], 0, MPCC_BOT_SEL, tree_cfg->dpp[i+1]); - /* MPCC_CONTROL->MPCC_MODE */ REG_UPDATE(MPCC_CONTROL[mpcc_inst], - MPCC_MODE, 3); + MPCC_MODE, MODE_BLEND); } if (i == 0) set_output_mux( mpc, tree_cfg->opp_id, mpcc_inst); - set_blend_mode(mpc, tree_cfg->mode, mpcc_inst); + REG_UPDATE_2(MPCC_CONTROL[mpcc_inst], + MPCC_ALPHA_BLND_MODE, + tree_cfg->per_pixel_alpha[i] ? 0 : 2, + MPCC_ALPHA_MULTIPLIED_MODE, 0); } } -void dcn10_set_mpc_passthrough(struct dcn10_mpc *mpc, - uint8_t dpp_idx, - uint8_t mpcc_idx, - uint8_t opp_idx) -{ - struct mpc_tree_cfg tree_cfg = { 0 }; - - tree_cfg.num_pipes = 1; - tree_cfg.opp_id = opp_idx; - tree_cfg.mode = TOP_PASSTHRU; - /* TODO: FPGA bring up one MPC has only 1 DPP and 1 MPCC - * For blend case, need fill mode DPP and cascade MPCC - */ - tree_cfg.dpp[0] = dpp_idx; - tree_cfg.mpcc[0] = mpcc_idx; - dcn10_set_mpc_tree(mpc, &tree_cfg); -} - /* * This is the function to remove current MPC tree specified by tree_cfg * Before invoke this function, ensure that master lock of OPTC specified @@ -188,6 +149,7 @@ void dcn10_delete_mpc_tree(struct dcn10_mpc *mpc, */ tree_cfg->dpp[i] = 0xf; tree_cfg->mpcc[i] = 0xf; + tree_cfg->per_pixel_alpha[i] = false; } set_output_mux(mpc, tree_cfg->opp_id, 0xf); tree_cfg->opp_id = 0xf; @@ -208,6 +170,7 @@ bool dcn10_remove_dpp(struct dcn10_mpc *mpc, uint8_t idx) { int i; + uint8_t mpcc_inst; bool found = false; /* find dpp_idx from dpp array of tree_cfg */ @@ -218,54 +181,53 @@ bool dcn10_remove_dpp(struct dcn10_mpc *mpc, } } - if (found) { - /* add remove dpp/mpcc pair into pending list */ + if (!found) { + BREAK_TO_DEBUGGER(); + return false; + } + mpcc_inst = tree_cfg->mpcc[i]; - /* TODO FPGA AddToPendingList if empty from pseudo code - * AddToPendingList(tree_cfg->dpp[i],tree_cfg->mpcc[i]); - */ - uint8_t mpcc_inst = tree_cfg->mpcc[i]; + REG_SET(MPCC_OPP_ID[mpcc_inst], 0, + MPCC_OPP_ID, 0xf); - REG_SET(MPCC_OPP_ID[mpcc_inst], 0, - MPCC_OPP_ID, 0xf); + REG_SET(MPCC_TOP_SEL[mpcc_inst], 0, + MPCC_TOP_SEL, 0xf); - REG_SET(MPCC_TOP_SEL[mpcc_inst], 0, - MPCC_TOP_SEL, 0xf); + REG_SET(MPCC_BOT_SEL[mpcc_inst], 0, + MPCC_BOT_SEL, 0xf); + + if (i == 0) { + if (tree_cfg->num_pipes > 1) + set_output_mux(mpc, + tree_cfg->opp_id, tree_cfg->mpcc[i+1]); + else + set_output_mux(mpc, tree_cfg->opp_id, 0xf); + } else if (i == tree_cfg->num_pipes-1) { + mpcc_inst = tree_cfg->mpcc[i - 1]; REG_SET(MPCC_BOT_SEL[mpcc_inst], 0, MPCC_BOT_SEL, 0xF); - if (i == 0) { - if (tree_cfg->num_pipes > 1) - set_output_mux(mpc, - tree_cfg->opp_id, tree_cfg->mpcc[i+1]); - else - set_output_mux(mpc, tree_cfg->opp_id, 0xf); - } else if (i == tree_cfg->num_pipes-1) { - mpcc_inst = tree_cfg->mpcc[i - 1]; - - REG_SET(MPCC_BOT_SEL[mpcc_inst], 0, - MPCC_BOT_SEL, 0xF); - - REG_UPDATE(MPCC_CONTROL[mpcc_inst], - MPCC_MODE, tree_cfg->mode); - } else { - mpcc_inst = tree_cfg->mpcc[i - 1]; + /* prev mpc is now last, set to top only*/ + REG_UPDATE(MPCC_CONTROL[mpcc_inst], + MPCC_MODE, MODE_TOP_ONLY); + } else { + mpcc_inst = tree_cfg->mpcc[i - 1]; - REG_SET(MPCC_BOT_SEL[mpcc_inst], 0, - MPCC_BOT_SEL, tree_cfg->mpcc[i+1]); - } - set_blend_mode(mpc, tree_cfg->mode, mpcc_inst); + REG_SET(MPCC_BOT_SEL[mpcc_inst], 0, + MPCC_BOT_SEL, tree_cfg->mpcc[i+1]); + } - /* update tree_cfg structure */ - while (i < tree_cfg->num_pipes - 1) { - tree_cfg->dpp[i] = tree_cfg->dpp[i+1]; - tree_cfg->mpcc[i] = tree_cfg->mpcc[i+1]; - i++; - } - tree_cfg->num_pipes--; + /* update tree_cfg structure */ + while (i < tree_cfg->num_pipes - 1) { + tree_cfg->dpp[i] = tree_cfg->dpp[i+1]; + tree_cfg->mpcc[i] = tree_cfg->mpcc[i+1]; + tree_cfg->per_pixel_alpha[i] = tree_cfg->per_pixel_alpha[i+1]; + i++; } - return found; + tree_cfg->num_pipes--; + + return true; } /* TODO FPGA: how to handle DPP? @@ -284,14 +246,14 @@ void dcn10_add_dpp(struct dcn10_mpc *mpc, struct mpc_tree_cfg *tree_cfg, uint8_t dpp_idx, uint8_t mpcc_idx, + uint8_t per_pixel_alpha, uint8_t position) { - uint8_t temp; - uint8_t temp1; + uint8_t prev; + uint8_t next; REG_SET(MPCC_OPP_ID[mpcc_idx], 0, MPCC_OPP_ID, tree_cfg->opp_id); - REG_SET(MPCC_TOP_SEL[mpcc_idx], 0, MPCC_TOP_SEL, dpp_idx); @@ -299,70 +261,71 @@ void dcn10_add_dpp(struct dcn10_mpc *mpc, /* idle dpp/mpcc is added to the top layer of tree */ REG_SET(MPCC_BOT_SEL[mpcc_idx], 0, MPCC_BOT_SEL, tree_cfg->mpcc[0]); - REG_UPDATE(MPCC_CONTROL[mpcc_idx], - MPCC_MODE, 3); + /* bottom mpc is always top only */ + REG_UPDATE(MPCC_CONTROL[mpcc_idx], + MPCC_MODE, MODE_TOP_ONLY); /* opp will get new output. from new added mpcc */ set_output_mux(mpc, tree_cfg->opp_id, mpcc_idx); - set_blend_mode(mpc, tree_cfg->mode, mpcc_idx); - } else if (position == tree_cfg->num_pipes) { /* idle dpp/mpcc is added to the bottom layer of tree */ /* get instance of previous bottom mpcc, set to middle layer */ - temp = tree_cfg->mpcc[tree_cfg->num_pipes - 1]; + prev = tree_cfg->mpcc[position - 1]; - REG_SET(MPCC_BOT_SEL[temp], 0, + REG_SET(MPCC_BOT_SEL[prev], 0, MPCC_BOT_SEL, mpcc_idx); - REG_UPDATE(MPCC_CONTROL[temp], - MPCC_MODE, 3); + /* all mpcs other than bottom need to blend */ + REG_UPDATE(MPCC_CONTROL[prev], + MPCC_MODE, MODE_BLEND); /* mpcc_idx become new bottom mpcc*/ REG_SET(MPCC_BOT_SEL[mpcc_idx], 0, MPCC_BOT_SEL, 0xf); + /* bottom mpc is always top only */ REG_UPDATE(MPCC_CONTROL[mpcc_idx], - MPCC_MODE, tree_cfg->mode); - - set_blend_mode(mpc, tree_cfg->mode, mpcc_idx); + MPCC_MODE, MODE_TOP_ONLY); } else { /* idle dpp/mpcc is added to middle of tree */ - temp = tree_cfg->mpcc[position - 1]; - temp1 = tree_cfg->mpcc[position]; + prev = tree_cfg->mpcc[position - 1]; /* mpc a */ + next = tree_cfg->mpcc[position]; /* mpc b */ - /* new mpcc instance temp1 is added right after temp*/ - REG_SET(MPCC_BOT_SEL[temp], 0, + /* connect mpc inserted below mpc a*/ + REG_SET(MPCC_BOT_SEL[prev], 0, MPCC_BOT_SEL, mpcc_idx); - /* mpcc_idx connect previous temp+1 to new mpcc */ - REG_SET(MPCC_BOT_SEL[mpcc_idx], 0, - MPCC_BOT_SEL, temp1); + /* blend on mpc being inserted */ + REG_UPDATE(MPCC_CONTROL[mpcc_idx], + MPCC_MODE, MODE_BLEND); - /* temp TODO: may not need*/ - REG_UPDATE(MPCC_CONTROL[temp], - MPCC_MODE, 3); + /* Connect mpc b below one inserted */ + REG_SET(MPCC_BOT_SEL[mpcc_idx], 0, + MPCC_BOT_SEL, next); - set_blend_mode(mpc, tree_cfg->mode, temp); } - - /* update tree_cfg structure */ - temp = tree_cfg->num_pipes - 1; + /* premultiplied mode only if alpha is on for the layer*/ + REG_UPDATE_2(MPCC_CONTROL[mpcc_idx], + MPCC_ALPHA_BLND_MODE, + tree_cfg->per_pixel_alpha[position] ? 0 : 2, + MPCC_ALPHA_MULTIPLIED_MODE, 0); /* * iterating from the last mpc/dpp pair to the one being added, shift * them down one position */ - while (temp > position) { - tree_cfg->dpp[temp + 1] = tree_cfg->dpp[temp]; - tree_cfg->mpcc[temp + 1] = tree_cfg->mpcc[temp]; - temp--; + for (next = tree_cfg->num_pipes; next > position; next--) { + tree_cfg->dpp[next] = tree_cfg->dpp[next - 1]; + tree_cfg->mpcc[next] = tree_cfg->mpcc[next - 1]; + tree_cfg->per_pixel_alpha[next] = tree_cfg->per_pixel_alpha[next - 1]; } /* insert the new mpc/dpp pair into the tree_cfg*/ tree_cfg->dpp[position] = dpp_idx; tree_cfg->mpcc[position] = mpcc_idx; + tree_cfg->per_pixel_alpha[position] = per_pixel_alpha; tree_cfg->num_pipes++; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h index 6550b93c9254..3e4eb655e913 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h @@ -105,11 +105,6 @@ struct dcn10_mpc { const struct dcn_mpc_mask *mpc_mask; }; -void dcn10_set_mpc_passthrough(struct dcn10_mpc *mpc, - uint8_t dpp_idx, - uint8_t mpcc_idx, - uint8_t opp_idx); - void dcn10_delete_mpc_tree(struct dcn10_mpc *mpc, struct mpc_tree_cfg *tree_cfg); @@ -121,6 +116,7 @@ void dcn10_add_dpp(struct dcn10_mpc *mpc, struct mpc_tree_cfg *tree_cfg, uint8_t dpp_idx, uint8_t mpcc_idx, + uint8_t per_pixel_alpha, uint8_t position); void wait_mpcc_idle(struct dcn10_mpc *mpc, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h index 2e86ebe5eeda..ec1a201747f2 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h @@ -25,19 +25,6 @@ #ifndef __DC_MPC_H__ #define __DC_MPC_H__ -/* define the maximum number of pipes - * MAX_NUM_PIPPES = MAX_PIPES defined in core_type.h - */ -enum { - MAX_NUM_PIPPES = 6 -}; - -enum blend_mode { - DIGI_BYPASS = 0, /* digital bypass */ - TOP_PASSTHRU, /* top layer pass through */ - TOP_BLND /* top layer blend */ -}; - /* This structure define the mpc tree configuration * num_pipes - number of pipes of the tree * opp_id - instance id of OPP to drive MPC @@ -60,10 +47,10 @@ struct mpc_tree_cfg { uint8_t num_pipes; uint8_t opp_id; /* dpp pipes for blend */ - uint8_t dpp[MAX_NUM_PIPPES]; + uint8_t dpp[6]; /* mpcc insatnces for blend */ - uint8_t mpcc[MAX_NUM_PIPPES]; - enum blend_mode mode; + uint8_t mpcc[6]; + bool per_pixel_alpha[6]; }; struct mpcc_blnd_cfg { -- cgit From 9f72f51d701cd2dd87a157d972650924fe91ec80 Mon Sep 17 00:00:00 2001 From: Amy Zhang Date: Wed, 31 May 2017 16:53:01 -0400 Subject: drm/amd/display: Refactor to call set PSR wait loop in dce_dmcu instead of dce_clocks Signed-off-by: Amy Zhang Reviewed-by: Anthony Koo Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 52 +++++------ drivers/gpu/drm/amd/display/dc/dc.h | 3 +- drivers/gpu/drm/amd/display/dc/dc_types.h | 101 +++++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c | 41 ++------- drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c | 66 +++++++++++++- drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h | 8 ++ drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h | 3 + .../gpu/drm/amd/display/dc/inc/hw/link_encoder.h | 101 --------------------- 8 files changed, 213 insertions(+), 162 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 318aaa762f31..b2c8b572d57f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1458,17 +1458,17 @@ bool dc_link_get_psr_state(const struct dc_link *dc_link, uint32_t *psr_state) } bool dc_link_setup_psr(const struct dc_link *dc_link, - const struct dc_stream *stream, struct psr_config *psr_config) + const struct dc_stream *stream, struct psr_config *psr_config, + struct psr_context *psr_context) { struct core_link *link = DC_LINK_TO_CORE(dc_link); struct dc_context *ctx = link->ctx; struct core_dc *core_dc = DC_TO_CORE(ctx->dc); struct dmcu *dmcu = core_dc->res_pool->dmcu; struct core_stream *core_stream = DC_STREAM_TO_CORE(stream); - struct psr_context psr_context = {0}; int i; - psr_context.controllerId = CONTROLLER_ID_UNDEFINED; + psr_context->controllerId = CONTROLLER_ID_UNDEFINED; if (dc_link != NULL && dmcu != NULL) { @@ -1503,9 +1503,9 @@ bool dc_link_setup_psr(const struct dc_link *dc_link, &psr_configuration.raw, sizeof(psr_configuration.raw)); - psr_context.channel = link->public.ddc->ddc_pin->hw_info.ddc_channel; - psr_context.transmitterId = link->link_enc->transmitter; - psr_context.engineId = link->link_enc->preferred_engine; + psr_context->channel = link->public.ddc->ddc_pin->hw_info.ddc_channel; + psr_context->transmitterId = link->link_enc->transmitter; + psr_context->engineId = link->link_enc->preferred_engine; for (i = 0; i < MAX_PIPES; i++) { if (core_dc->current_context->res_ctx.pipe_ctx[i].stream @@ -1513,7 +1513,7 @@ bool dc_link_setup_psr(const struct dc_link *dc_link, /* dmcu -1 for all controller id values, * therefore +1 here */ - psr_context.controllerId = + psr_context->controllerId = core_dc->current_context->res_ctx. pipe_ctx[i].tg->inst + 1; break; @@ -1521,60 +1521,60 @@ bool dc_link_setup_psr(const struct dc_link *dc_link, } /* Hardcoded for now. Can be Pcie or Uniphy (or Unknown)*/ - psr_context.phyType = PHY_TYPE_UNIPHY; + psr_context->phyType = PHY_TYPE_UNIPHY; /*PhyId is associated with the transmitter id*/ - psr_context.smuPhyId = link->link_enc->transmitter; + psr_context->smuPhyId = link->link_enc->transmitter; - psr_context.crtcTimingVerticalTotal = stream->timing.v_total; - psr_context.vsyncRateHz = div64_u64(div64_u64((stream-> + psr_context->crtcTimingVerticalTotal = stream->timing.v_total; + psr_context->vsyncRateHz = div64_u64(div64_u64((stream-> timing.pix_clk_khz * 1000), stream->timing.v_total), stream->timing.h_total); - psr_context.psrSupportedDisplayConfig = true; - psr_context.psrExitLinkTrainingRequired = + psr_context->psrSupportedDisplayConfig = true; + psr_context->psrExitLinkTrainingRequired = psr_config->psr_exit_link_training_required; - psr_context.sdpTransmitLineNumDeadline = + psr_context->sdpTransmitLineNumDeadline = psr_config->psr_sdp_transmit_line_num_deadline; - psr_context.psrFrameCaptureIndicationReq = + psr_context->psrFrameCaptureIndicationReq = psr_config->psr_frame_capture_indication_req; - psr_context.skipPsrWaitForPllLock = 0; /* only = 1 in KV */ + psr_context->skipPsrWaitForPllLock = 0; /* only = 1 in KV */ - psr_context.numberOfControllers = + psr_context->numberOfControllers = link->dc->res_pool->res_cap->num_timing_generator; - psr_context.rfb_update_auto_en = true; + psr_context->rfb_update_auto_en = true; /* 2 frames before enter PSR. */ - psr_context.timehyst_frames = 2; + psr_context->timehyst_frames = 2; /* half a frame * (units in 100 lines, i.e. a value of 1 represents 100 lines) */ - psr_context.hyst_lines = stream->timing.v_total / 2 / 100; - psr_context.aux_repeats = 10; + psr_context->hyst_lines = stream->timing.v_total / 2 / 100; + psr_context->aux_repeats = 10; - psr_context.psr_level.u32all = 0; + psr_context->psr_level.u32all = 0; /* SMU will perform additional powerdown sequence. * For unsupported ASICs, set psr_level flag to skip PSR * static screen notification to SMU. * (Always set for DAL2, did not check ASIC) */ - psr_context.psr_level.bits.SKIP_SMU_NOTIFICATION = 1; + psr_context->psr_level.bits.SKIP_SMU_NOTIFICATION = 1; /* Complete PSR entry before aborting to prevent intermittent * freezes on certain eDPs */ - psr_context.psr_level.bits.DISABLE_PSR_ENTRY_ABORT = 1; + psr_context->psr_level.bits.DISABLE_PSR_ENTRY_ABORT = 1; /* Controls additional delay after remote frame capture before * continuing power down, default = 0 */ - psr_context.frame_delay = 0; + psr_context->frame_delay = 0; link->psr_enabled = true; - dmcu->funcs->setup_psr(dmcu, link, &psr_context); + dmcu->funcs->setup_psr(dmcu, link, psr_context); return true; } else return false; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 328bfcb7dbb8..a20ba01d9e7b 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -705,7 +705,8 @@ bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable); bool dc_link_get_psr_state(const struct dc_link *dc_link, uint32_t *psr_state); bool dc_link_setup_psr(const struct dc_link *dc_link, - const struct dc_stream *stream, struct psr_config *psr_config); + const struct dc_stream *stream, struct psr_config *psr_config, + struct psr_context *psr_context); /* Request DC to detect if there is a Panel connected. * boot - If this call is during initial boot. diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index d2f3b9fd7a30..06354c36c499 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -31,6 +31,7 @@ #include "dc_dp_types.h" #include "dc_hw_types.h" #include "dal_types.h" +#include "grph_object_defs.h" /* forward declarations */ struct dc_surface; @@ -493,6 +494,106 @@ struct psr_config { unsigned int psr_sdp_transmit_line_num_deadline; }; +union dmcu_psr_level { + struct { + unsigned int SKIP_CRC:1; + unsigned int SKIP_DP_VID_STREAM_DISABLE:1; + unsigned int SKIP_PHY_POWER_DOWN:1; + unsigned int SKIP_AUX_ACK_CHECK:1; + unsigned int SKIP_CRTC_DISABLE:1; + unsigned int SKIP_AUX_RFB_CAPTURE_CHECK:1; + unsigned int SKIP_SMU_NOTIFICATION:1; + unsigned int SKIP_AUTO_STATE_ADVANCE:1; + unsigned int DISABLE_PSR_ENTRY_ABORT:1; + unsigned int RESERVED:23; + } bits; + unsigned int u32all; +}; + +enum physical_phy_id { + PHYLD_0, + PHYLD_1, + PHYLD_2, + PHYLD_3, + PHYLD_4, + PHYLD_5, + PHYLD_6, + PHYLD_7, + PHYLD_8, + PHYLD_9, + PHYLD_COUNT, + PHYLD_UNKNOWN = (-1L) +}; + +enum phy_type { + PHY_TYPE_UNKNOWN = 1, + PHY_TYPE_PCIE_PHY = 2, + PHY_TYPE_UNIPHY = 3, +}; + +struct psr_context { + /* ddc line */ + enum channel_id channel; + /* Transmitter id */ + enum transmitter transmitterId; + /* Engine Id is used for Dig Be source select */ + enum engine_id engineId; + /* Controller Id used for Dig Fe source select */ + enum controller_id controllerId; + /* Pcie or Uniphy */ + enum phy_type phyType; + /* Physical PHY Id used by SMU interpretation */ + enum physical_phy_id smuPhyId; + /* Vertical total pixels from crtc timing. + * This is used for static screen detection. + * ie. If we want to detect half a frame, + * we use this to determine the hyst lines. + */ + unsigned int crtcTimingVerticalTotal; + /* PSR supported from panel capabilities and + * current display configuration + */ + bool psrSupportedDisplayConfig; + /* Whether fast link training is supported by the panel */ + bool psrExitLinkTrainingRequired; + /* If RFB setup time is greater than the total VBLANK time, + * it is not possible for the sink to capture the video frame + * in the same frame the SDP is sent. In this case, + * the frame capture indication bit should be set and an extra + * static frame should be transmitted to the sink. + */ + bool psrFrameCaptureIndicationReq; + /* Set the last possible line SDP may be transmitted without violating + * the RFB setup time or entering the active video frame. + */ + unsigned int sdpTransmitLineNumDeadline; + /* The VSync rate in Hz used to calculate the + * step size for smooth brightness feature + */ + unsigned int vsyncRateHz; + unsigned int skipPsrWaitForPllLock; + unsigned int numberOfControllers; + /* Unused, for future use. To indicate that first changed frame from + * state3 shouldn't result in psr_inactive, but rather to perform + * an automatic single frame rfb_update. + */ + bool rfb_update_auto_en; + /* Number of frame before entering static screen */ + unsigned int timehyst_frames; + /* Partial frames before entering static screen */ + unsigned int hyst_lines; + /* # of repeated AUX transaction attempts to make before + * indicating failure to the driver + */ + unsigned int aux_repeats; + /* Controls hw blocks to power down during PSR active state */ + union dmcu_psr_level psr_level; + /* Controls additional delay after remote frame capture before + * continuing powerd own + */ + unsigned int frame_delay; +}; + struct colorspace_transform { struct fixed31_32 matrix[12]; bool enable_remap; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c index 8bc0d0ff3a2e..04cd70172cc7 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c @@ -31,6 +31,7 @@ #include "dc.h" #include "core_dc.h" #include "dce_abm.h" +#include "dmcu.h" #if defined(CONFIG_DRM_AMD_DC_DCN1_0) #include "dcn_calcs.h" #include "core_dc.h" @@ -331,44 +332,18 @@ static void dce_set_clock( clk->cur_min_clks_state = DM_PP_CLOCKS_STATE_NOMINAL; } -#define PSR_SET_WAITLOOP 0x31 - -union dce110_dmcu_psr_config_data_wait_loop_reg1 { - struct { - unsigned int wait_loop:16; /* [15:0] */ - unsigned int reserved:16; /* [31:16] */ - } bits; - unsigned int u32; -}; - -static void dce_psr_wait_loop( - struct dce_disp_clk *clk_dce, unsigned int display_clk_khz) -{ - struct dc_context *ctx = clk_dce->base.ctx; - union dce110_dmcu_psr_config_data_wait_loop_reg1 masterCmdData1; - - /* waitDMCUReadyForCmd */ - REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 100, 100); - - masterCmdData1.u32 = 0; - masterCmdData1.bits.wait_loop = display_clk_khz / 1000 / 7; - dm_write_reg(ctx, REG(MASTER_COMM_DATA_REG1), masterCmdData1.u32); - - /* setDMCUParam_Cmd */ - REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, PSR_SET_WAITLOOP); - - /* notifyDMCUMsg */ - REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); -} - static void dce_psr_set_clock( struct display_clock *clk, int requested_clk_khz) { struct dce_disp_clk *clk_dce = TO_DCE_CLOCKS(clk); + struct dc_context *ctx = clk_dce->base.ctx; + struct core_dc *core_dc = DC_TO_CORE(ctx->dc); + struct dmcu *dmcu = core_dc->res_pool->dmcu; dce_set_clock(clk, requested_clk_khz); - dce_psr_wait_loop(clk_dce, requested_clk_khz); + + dmcu->funcs->set_psr_wait_loop(dmcu, requested_clk_khz / 1000 / 7); } static void dce112_set_clock( @@ -380,6 +355,7 @@ static void dce112_set_clock( struct dc_bios *bp = clk->ctx->dc_bios; struct core_dc *core_dc = DC_TO_CORE(clk->ctx->dc); struct abm *abm = core_dc->res_pool->abm; + struct dmcu *dmcu = core_dc->res_pool->dmcu; /* Prepare to program display clock*/ memset(&dce_clk_params, 0, sizeof(dce_clk_params)); @@ -411,7 +387,8 @@ static void dce112_set_clock( bp->funcs->set_dce_clock(bp, &dce_clk_params); if (abm->funcs->is_dmcu_initialized(abm)) - dce_psr_wait_loop(clk_dce, requested_clk_khz); + dmcu->funcs->set_psr_wait_loop(dmcu, + requested_clk_khz / 1000 / 7); } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c index 03b51e256e21..0fe3ee8e29d3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c @@ -48,7 +48,9 @@ #define PSR_ENABLE 0x20 #define PSR_EXIT 0x21 #define PSR_SET 0x23 +#define PSR_SET_WAITLOOP 0x31 #define MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK 0x00000001L +unsigned int cached_wait_loop_number = 0; bool dce_dmcu_load_iram(struct dmcu *dmcu, unsigned int start_offset, @@ -252,6 +254,34 @@ static void dce_dmcu_setup_psr(struct dmcu *dmcu, REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); } +static void dce_psr_wait_loop( + struct dmcu *dmcu, + unsigned int wait_loop_number) +{ + struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); + union dce_dmcu_psr_config_data_wait_loop_reg1 masterCmdData1; + + /* waitDMCUReadyForCmd */ + REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 100, 100); + + masterCmdData1.u32 = 0; + masterCmdData1.bits.wait_loop = wait_loop_number; + cached_wait_loop_number = wait_loop_number; + dm_write_reg(dmcu->ctx, REG(MASTER_COMM_DATA_REG1), masterCmdData1.u32); + + /* setDMCUParam_Cmd */ + REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, PSR_SET_WAITLOOP); + + /* notifyDMCUMsg */ + REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); +} + +static void dce_get_psr_wait_loop(unsigned int *psr_wait_loop_number) +{ + *psr_wait_loop_number = cached_wait_loop_number; + return; +} + #if defined(CONFIG_DRM_AMD_DC_DCN1_0) bool dcn10_dmcu_load_iram(struct dmcu *dmcu, unsigned int start_offset, @@ -464,13 +494,43 @@ static void dcn10_dmcu_setup_psr(struct dmcu *dmcu, REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); } +static void dcn10_psr_wait_loop( + struct dmcu *dmcu, + unsigned int wait_loop_number) +{ + struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); + union dce_dmcu_psr_config_data_wait_loop_reg1 masterCmdData1; + + /* waitDMCUReadyForCmd */ + REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 100, 100); + + masterCmdData1.u32 = 0; + masterCmdData1.bits.wait_loop = wait_loop_number; + cached_wait_loop_number = wait_loop_number; + dm_write_reg(dmcu->ctx, REG(MASTER_COMM_DATA_REG1), masterCmdData1.u32); + + /* setDMCUParam_Cmd */ + REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, PSR_SET_WAITLOOP); + + /* notifyDMCUMsg */ + REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); +} + +static void dcn10_get_psr_wait_loop(unsigned int *psr_wait_loop_number) +{ + *psr_wait_loop_number = cached_wait_loop_number; + return; +} + #endif static const struct dmcu_funcs dce_funcs = { .load_iram = dce_dmcu_load_iram, .set_psr_enable = dce_dmcu_set_psr_enable, .setup_psr = dce_dmcu_setup_psr, - .get_psr_state = dce_get_dmcu_psr_state + .get_psr_state = dce_get_dmcu_psr_state, + .set_psr_wait_loop = dce_psr_wait_loop, + .get_psr_wait_loop = dce_get_psr_wait_loop }; #if defined(CONFIG_DRM_AMD_DC_DCN1_0) @@ -478,7 +538,9 @@ static const struct dmcu_funcs dcn10_funcs = { .load_iram = dcn10_dmcu_load_iram, .set_psr_enable = dcn10_dmcu_set_psr_enable, .setup_psr = dcn10_dmcu_setup_psr, - .get_psr_state = dcn10_get_dmcu_psr_state + .get_psr_state = dcn10_get_dmcu_psr_state, + .set_psr_wait_loop = dcn10_psr_wait_loop, + .get_psr_wait_loop = dcn10_get_psr_wait_loop }; #endif diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h index 584682ba1f77..c421a0250016 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h @@ -197,6 +197,14 @@ union dce_dmcu_psr_config_data_reg3 { unsigned int u32All; }; +union dce_dmcu_psr_config_data_wait_loop_reg1 { + struct { + unsigned int wait_loop:16; /* [15:0] */ + unsigned int reserved:16; /* [31:16] */ + } bits; + unsigned int u32; +}; + struct dmcu *dce_dmcu_create( struct dc_context *ctx, const struct dce_dmcu_registers *regs, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h index dff0babb5cf7..6067f464d805 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h @@ -42,6 +42,9 @@ struct dmcu_funcs { struct core_link *link, struct psr_context *psr_context); void (*get_psr_state)(struct dmcu *dmcu, uint32_t *psr_state); + void (*set_psr_wait_loop)(struct dmcu *dmcu, + unsigned int wait_loop_number); + void (*get_psr_wait_loop)(unsigned int *psr_wait_loop_number); }; #endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h index 7307f96c7679..d330d38aff16 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h @@ -47,43 +47,6 @@ struct encoder_feature_support { bool ycbcr420_supported; }; -enum physical_phy_id { - PHYLD_0, - PHYLD_1, - PHYLD_2, - PHYLD_3, - PHYLD_4, - PHYLD_5, - PHYLD_6, - PHYLD_7, - PHYLD_8, - PHYLD_9, - PHYLD_COUNT, - PHYLD_UNKNOWN = (-1L) -}; - -enum phy_type { - PHY_TYPE_UNKNOWN = 1, - PHY_TYPE_PCIE_PHY = 2, - PHY_TYPE_UNIPHY = 3, -}; - -union dmcu_psr_level { - struct { - unsigned int SKIP_CRC:1; - unsigned int SKIP_DP_VID_STREAM_DISABLE:1; - unsigned int SKIP_PHY_POWER_DOWN:1; - unsigned int SKIP_AUX_ACK_CHECK:1; - unsigned int SKIP_CRTC_DISABLE:1; - unsigned int SKIP_AUX_RFB_CAPTURE_CHECK:1; - unsigned int SKIP_SMU_NOTIFICATION:1; - unsigned int SKIP_AUTO_STATE_ADVANCE:1; - unsigned int DISABLE_PSR_ENTRY_ABORT:1; - unsigned int RESERVED:23; - } bits; - unsigned int u32all; -}; - union dpcd_psr_configuration { struct { unsigned char ENABLE : 1; @@ -116,70 +79,6 @@ union psr_sink_psr_status { unsigned char raw; }; -struct psr_context { - /* ddc line */ - enum channel_id channel; - /* Transmitter id */ - enum transmitter transmitterId; - /* Engine Id is used for Dig Be source select */ - enum engine_id engineId; - /* Controller Id used for Dig Fe source select */ - enum controller_id controllerId; - /* Pcie or Uniphy */ - enum phy_type phyType; - /* Physical PHY Id used by SMU interpretation */ - enum physical_phy_id smuPhyId; - /* Vertical total pixels from crtc timing. - * This is used for static screen detection. - * ie. If we want to detect half a frame, - * we use this to determine the hyst lines. - */ - unsigned int crtcTimingVerticalTotal; - /* PSR supported from panel capabilities and - * current display configuration - */ - bool psrSupportedDisplayConfig; - /* Whether fast link training is supported by the panel */ - bool psrExitLinkTrainingRequired; - /* If RFB setup time is greater than the total VBLANK time, - * it is not possible for the sink to capture the video frame - * in the same frame the SDP is sent. In this case, - * the frame capture indication bit should be set and an extra - * static frame should be transmitted to the sink. - */ - bool psrFrameCaptureIndicationReq; - /* Set the last possible line SDP may be transmitted without violating - * the RFB setup time or entering the active video frame. - */ - unsigned int sdpTransmitLineNumDeadline; - /* The VSync rate in Hz used to calculate the - * step size for smooth brightness feature - */ - unsigned int vsyncRateHz; - unsigned int skipPsrWaitForPllLock; - unsigned int numberOfControllers; - /* Unused, for future use. To indicate that first changed frame from - * state3 shouldn't result in psr_inactive, but rather to perform - * an automatic single frame rfb_update. - */ - bool rfb_update_auto_en; - /* Number of frame before entering static screen */ - unsigned int timehyst_frames; - /* Partial frames before entering static screen */ - unsigned int hyst_lines; - /* # of repeated AUX transaction attempts to make before - * indicating failure to the driver - */ - unsigned int aux_repeats; - /* Controls hw blocks to power down during PSR active state */ - union dmcu_psr_level psr_level; - /* Controls additional delay after remote frame capture before - * continuing powerd own - */ - unsigned int frame_delay; -}; - - struct link_encoder { const struct link_encoder_funcs *funcs; int32_t aux_channel_offset; -- cgit From fc82c5cb306d6f201cdee2c4c092ff49c6929634 Mon Sep 17 00:00:00 2001 From: Amy Zhang Date: Fri, 2 Jun 2017 16:33:47 -0400 Subject: drm/amd/display: Fix DRR Enable on Desktop - Block PSR in Full screen apps to prevent incorrect static screen curser events - Reprogram static screen events when update freesync state - Program static ramp variable active after other values are programmed - Correct wrong assigning of the nominal and current vcount Signed-off-by: Amy Zhang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/modules/freesync/freesync.c | 89 ++++++++++++++-------- .../gpu/drm/amd/display/modules/inc/mod_freesync.h | 3 +- 2 files changed, 61 insertions(+), 31 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index 9a073bc55144..f79c47951f90 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -257,8 +257,10 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, nom_refresh_rate_micro_hz = (unsigned int) temp; if (core_freesync->opts.min_refresh_from_edid != 0 && - dc_is_embedded_signal( - stream->sink->sink_signal)) { + dc_is_embedded_signal(stream->sink->sink_signal) + && (nom_refresh_rate_micro_hz - + core_freesync->opts.min_refresh_from_edid * + 1000000) >= 10000000) { caps->supported = true; caps->min_refresh_in_micro_hz = core_freesync->opts.min_refresh_from_edid * @@ -683,44 +685,47 @@ static void set_static_ramp_variables(struct core_freesync *core_freesync, unsigned int index, bool enable_static_screen) { unsigned int frame_duration = 0; - + unsigned int nominal_refresh_rate = core_freesync->map[index].state. + nominal_refresh_rate_in_micro_hz; + unsigned int min_refresh_rate= core_freesync->map[index].caps-> + min_refresh_in_micro_hz; struct gradual_static_ramp *static_ramp_variables = &core_freesync->map[index].state.static_ramp; + /* If we are ENABLING static screen, refresh rate should go DOWN. + * If we are DISABLING static screen, refresh rate should go UP. + */ + if (enable_static_screen) + static_ramp_variables->ramp_direction_is_up = false; + else + static_ramp_variables->ramp_direction_is_up = true; + /* If ramp is not active, set initial frame duration depending on * whether we are enabling/disabling static screen mode. If the ramp is * already active, ramp should continue in the opposite direction * starting with the current frame duration */ if (!static_ramp_variables->ramp_is_active) { - - static_ramp_variables->ramp_is_active = true; - if (enable_static_screen == true) { /* Going to lower refresh rate, so start from max * refresh rate (min frame duration) */ frame_duration = ((unsigned int) (div64_u64( (1000000000ULL * 1000000), - core_freesync->map[index].state. - nominal_refresh_rate_in_micro_hz))); + nominal_refresh_rate))); } else { /* Going to higher refresh rate, so start from min * refresh rate (max frame duration) */ frame_duration = ((unsigned int) (div64_u64( (1000000000ULL * 1000000), - core_freesync->map[index].caps->min_refresh_in_micro_hz))); + min_refresh_rate))); } - static_ramp_variables-> ramp_current_frame_duration_in_ns = frame_duration; - } - /* If we are ENABLING static screen, refresh rate should go DOWN. - * If we are DISABLING static screen, refresh rate should go UP. - */ - static_ramp_variables->ramp_direction_is_up = !enable_static_screen; + static_ramp_variables->ramp_is_active = true; + } } void mod_freesync_handle_v_update(struct mod_freesync *mod_freesync, @@ -841,6 +846,7 @@ void mod_freesync_update_state(struct mod_freesync *mod_freesync, unsigned int stream_index; struct freesync_state *state; struct core_freesync *core_freesync = NULL; + struct dc_static_screen_events triggers = {0}; if (mod_freesync == NULL) return; @@ -902,6 +908,14 @@ void mod_freesync_update_state(struct mod_freesync *mod_freesync, } } + /* Update mask */ + triggers.overlay_update = true; + triggers.surface_update = true; + + core_freesync->dc->stream_funcs.set_static_screen_events( + core_freesync->dc, streams, num_streams, + &triggers); + if (freesync_program_required) /* Program freesync according to current state*/ set_freesync_on_streams(core_freesync, streams, num_streams); @@ -1017,7 +1031,8 @@ bool mod_freesync_get_user_enable(struct mod_freesync *mod_freesync, bool mod_freesync_override_min_max(struct mod_freesync *mod_freesync, const struct dc_stream *streams, unsigned int min_refresh, - unsigned int max_refresh) + unsigned int max_refresh, + struct mod_freesync_caps *caps) { unsigned int index = 0; struct core_freesync *core_freesync; @@ -1030,7 +1045,10 @@ bool mod_freesync_override_min_max(struct mod_freesync *mod_freesync, index = map_index_from_stream(core_freesync, streams); state = &core_freesync->map[index].state; - if (min_refresh == 0 || max_refresh == 0) { + if (max_refresh == 0) + max_refresh = state->nominal_refresh_rate_in_micro_hz; + + if (min_refresh == 0) { /* Restore defaults */ calc_freesync_range(core_freesync, streams, state, core_freesync->map[index].caps-> @@ -1049,6 +1067,17 @@ bool mod_freesync_override_min_max(struct mod_freesync *mod_freesync, state->freesync_range.vmax); } + if (min_refresh != 0 && + dc_is_embedded_signal(streams->sink->sink_signal) && + (max_refresh - min_refresh >= 10000000)) { + caps->supported = true; + caps->min_refresh_in_micro_hz = min_refresh; + caps->max_refresh_in_micro_hz = max_refresh; + } + + /* Update the stream */ + update_stream(core_freesync, streams); + return true; } @@ -1115,8 +1144,8 @@ bool mod_freesync_get_v_position(struct mod_freesync *mod_freesync, core_freesync->dc, &stream, 1, &position.vertical_count, &position.nominal_vcount)) { - *nom_v_pos = position.vertical_count; - *v_pos = position.nominal_vcount; + *nom_v_pos = position.nominal_vcount; + *v_pos = position.vertical_count; return true; } @@ -1131,6 +1160,7 @@ void mod_freesync_notify_mode_change(struct mod_freesync *mod_freesync, struct freesync_state *state; struct core_freesync *core_freesync = NULL; struct dc_static_screen_events triggers = {0}; + unsigned long long temp = 0; if (mod_freesync == NULL) return; @@ -1143,22 +1173,21 @@ void mod_freesync_notify_mode_change(struct mod_freesync *mod_freesync, state = &core_freesync->map[map_index].state; + /* Update the field rate for new timing */ + temp = streams[stream_index]->timing.pix_clk_khz; + temp *= 1000ULL * 1000ULL * 1000ULL; + temp = div_u64(temp, + streams[stream_index]->timing.h_total); + temp = div_u64(temp, + streams[stream_index]->timing.v_total); + state->nominal_refresh_rate_in_micro_hz = + (unsigned int) temp; + if (core_freesync->map[map_index].caps->supported) { - /* Update the field rate for new timing */ - unsigned long long temp; - temp = streams[stream_index]->timing.pix_clk_khz; - temp *= 1000ULL * 1000ULL * 1000ULL; - temp = div_u64(temp, - streams[stream_index]->timing.h_total); - temp = div_u64(temp, - streams[stream_index]->timing.v_total); - state->nominal_refresh_rate_in_micro_hz = - (unsigned int) temp; /* Update the stream */ update_stream(core_freesync, streams[stream_index]); - /* Calculate vmin/vmax and refresh rate for * current mode */ diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h b/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h index 3947cc412ad7..f7f5a2cd7914 100644 --- a/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h +++ b/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h @@ -132,7 +132,8 @@ bool mod_freesync_get_user_enable(struct mod_freesync *mod_freesync, bool mod_freesync_override_min_max(struct mod_freesync *mod_freesync, const struct dc_stream *streams, unsigned int min_refresh, - unsigned int max_refresh); + unsigned int max_refresh, + struct mod_freesync_caps *caps); bool mod_freesync_get_min_max(struct mod_freesync *mod_freesync, const struct dc_stream *stream, -- cgit From 909e8c9e417945f313b68ed6c5a559fe5266be8b Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Mon, 5 Jun 2017 16:54:33 -0400 Subject: drm/amd/display: fix single link black screen Don't fall back to dual link DVI mode if the connector is single Link only. Signed-off-by: Charlene Liu Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index e4a6636fd829..b7f31b985b4f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1204,6 +1204,7 @@ bool resource_validate_attach_surfaces( /* Maximum TMDS single link pixel clock 165MHz */ #define TMDS_MAX_PIXEL_CLOCK_IN_KHZ 165000 +#define TMDS_MAX_PIXEL_CLOCK_IN_KHZ_UPMOST 297000 static void set_stream_engine_in_use( struct resource_context *res_ctx, @@ -1331,7 +1332,8 @@ static void update_stream_signal(struct core_stream *stream) } if (dc_is_dvi_signal(stream->signal)) { - if (stream->public.timing.pix_clk_khz > TMDS_MAX_PIXEL_CLOCK_IN_KHZ) + if (stream->public.timing.pix_clk_khz > TMDS_MAX_PIXEL_CLOCK_IN_KHZ_UPMOST && + stream->public.sink->sink_signal != SIGNAL_TYPE_DVI_SINGLE_LINK) stream->signal = SIGNAL_TYPE_DVI_DUAL_LINK; else stream->signal = SIGNAL_TYPE_DVI_SINGLE_LINK; -- cgit From a235bd9f1ea0c610a5cddfb79f98b651dc8dc5bd Mon Sep 17 00:00:00 2001 From: Zeyu Fan Date: Mon, 5 Jun 2017 17:56:05 -0400 Subject: drm/amd/display: Add function to log connectivity Signed-off-by: Zeyu Fan Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 6 ++++++ drivers/gpu/drm/amd/display/dc/basics/log_helpers.c | 3 +++ drivers/gpu/drm/amd/display/dc/dm_helpers.h | 4 ++++ 3 files changed, 13 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index 01d04fa2419e..64db62e609eb 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -322,6 +322,12 @@ bool dm_helpers_dp_mst_send_payload_allocation( return true; } +bool dm_helpers_dc_conn_log(struct dc_context*ctx, const char *msg) +{ + return true; +} + + bool dm_helpers_dp_mst_start_top_mgr( struct dc_context *ctx, const struct dc_link *link, diff --git a/drivers/gpu/drm/amd/display/dc/basics/log_helpers.c b/drivers/gpu/drm/amd/display/dc/basics/log_helpers.c index c4eddee8de1b..1268be9ebaf3 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/log_helpers.c +++ b/drivers/gpu/drm/amd/display/dc/basics/log_helpers.c @@ -26,6 +26,7 @@ #include "core_types.h" #include "logger.h" #include "include/logger_interface.h" +#include "dm_helpers.h" #define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0])) @@ -94,6 +95,8 @@ void dc_conn_log(struct dc_context *ctx, dm_logger_append(&entry, "%2.2X ", hex_data[i]); dm_logger_append(&entry, "^\n"); + dm_helpers_dc_conn_log(ctx, entry.buf); dm_logger_close(&entry); + va_end(args); } diff --git a/drivers/gpu/drm/amd/display/dc/dm_helpers.h b/drivers/gpu/drm/amd/display/dc/dm_helpers.h index c15a25ce8049..9fb606c49217 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_helpers.h +++ b/drivers/gpu/drm/amd/display/dc/dm_helpers.h @@ -68,6 +68,10 @@ bool dm_helpers_dp_mst_start_top_mgr( const struct dc_link *link, bool boot); +bool dm_helpers_dc_conn_log( + struct dc_context*ctx, + const char *msg); + void dm_helpers_dp_mst_stop_top_mgr( struct dc_context *ctx, const struct dc_link *link); -- cgit From 1bf56e62cc4fbff6d701b798da05a91f78aa12e9 Mon Sep 17 00:00:00 2001 From: Zeyu Fan Date: Fri, 2 Jun 2017 17:25:49 -0400 Subject: drm/amd/display: Call program_gamut explicitly instead of entire set_plane This fixes on boot crush on Vega, Polaris with Dal3. Signed-off-by: Zeyu Fan Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 3 +- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 42 ++++++++++++++++++++++ .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 1 + drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 3 ++ 4 files changed, 47 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index f5102b644942..657e10bae93f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -213,8 +213,7 @@ static bool set_gamut_remap(struct dc *dc, const struct dc_stream *stream) == core_stream) { pipes = &core_dc->current_context->res_ctx.pipe_ctx[i]; - core_dc->hwss.set_plane_config(core_dc, pipes, - &core_dc->current_context->res_ctx); + core_dc->hwss.program_gamut_remap(pipes); ret = true; } } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 7dd4b02b5938..616533e25534 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1894,6 +1894,47 @@ static void program_surface_visibility(const struct core_dc *dc, } +static void program_gamut_remap(struct pipe_ctx *pipe_ctx) +{ + struct xfm_grph_csc_adjustment adjust; + memset(&adjust, 0, sizeof(adjust)); + adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS; + + + if (pipe_ctx->stream->public.gamut_remap_matrix.enable_remap == true) { + adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW; + adjust.temperature_matrix[0] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[0]; + adjust.temperature_matrix[1] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[1]; + adjust.temperature_matrix[2] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[2]; + adjust.temperature_matrix[3] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[4]; + adjust.temperature_matrix[4] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[5]; + adjust.temperature_matrix[5] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[6]; + adjust.temperature_matrix[6] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[8]; + adjust.temperature_matrix[7] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[9]; + adjust.temperature_matrix[8] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[10]; + } + + pipe_ctx->xfm->funcs->transform_set_gamut_remap(pipe_ctx->xfm, &adjust); +} + /** * TODO REMOVE, USE UPDATE INSTEAD */ @@ -2509,6 +2550,7 @@ static void dce110_power_down_fe(struct core_dc *dc, struct pipe_ctx *pipe) } static const struct hw_sequencer_funcs dce110_funcs = { + .program_gamut_remap = program_gamut_remap, .init_hw = init_hw, .apply_ctx_to_hw = dce110_apply_ctx_to_hw, .apply_ctx_for_surface = dce110_apply_ctx_for_surface, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 447f6bf4644c..107f82df3053 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1899,6 +1899,7 @@ static void set_plane_config( } static const struct hw_sequencer_funcs dcn10_funcs = { + .program_gamut_remap = program_gamut_remap, .init_hw = init_hw, .apply_ctx_to_hw = dce110_apply_ctx_to_hw, .apply_ctx_for_surface = dcn10_apply_ctx_for_surface, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index b53e1206dfb3..6f8733ec9b16 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -67,6 +67,9 @@ struct hw_sequencer_funcs { struct pipe_ctx *pipe_ctx, struct resource_context *res_ctx); + void (*program_gamut_remap)( + struct pipe_ctx *pipe_ctx); + void (*update_plane_addr)( const struct core_dc *dc, struct pipe_ctx *pipe_ctx); -- cgit From ba326a9185f1c56d86e51dd89589e4eff42f02eb Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 2 Jun 2017 19:01:37 -0400 Subject: drm/amd/display: propagate surface alpha setting from OS to DC Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 6 +++++- drivers/gpu/drm/amd/display/dc/core/dc_debug.c | 6 ++++-- drivers/gpu/drm/amd/display/dc/dc.h | 2 ++ drivers/gpu/drm/amd/display/dc/dc_types.h | 2 +- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 10 ++++------ 5 files changed, 16 insertions(+), 10 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 657e10bae93f..fb5bacb50ebc 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -998,6 +998,7 @@ bool dc_commit_surfaces_to_stream( plane_info[i].stereo_format = new_surfaces[i]->stereo_format; plane_info[i].tiling_info = new_surfaces[i]->tiling_info; plane_info[i].visible = new_surfaces[i]->visible; + plane_info[i].per_pixel_alpha = new_surfaces[i]->per_pixel_alpha; plane_info[i].dcc = new_surfaces[i]->dcc; scaling_info[i].scaling_quality = new_surfaces[i]->scaling_quality; scaling_info[i].src_rect = new_surfaces[i]->src_rect; @@ -1068,7 +1069,7 @@ static enum surface_update_type get_plane_info_update_type( const struct dc_surface_update *u, int surface_index) { - struct dc_plane_info temp_plane_info = { { { { 0 } } } }; + struct dc_plane_info temp_plane_info = { 0 }; if (!u->plane_info) return UPDATE_TYPE_FAST; @@ -1091,6 +1092,7 @@ static enum surface_update_type get_plane_info_update_type( /* Special Validation parameters */ temp_plane_info.format = u->plane_info->format; + temp_plane_info.per_pixel_alpha = u->plane_info->per_pixel_alpha; if (surface_index == 0) temp_plane_info.visible = u->plane_info->visible; @@ -1327,6 +1329,8 @@ void dc_update_surfaces_and_stream(struct dc *dc, srf_updates[i].plane_info->tiling_info; surface->public.visible = srf_updates[i].plane_info->visible; + surface->public.per_pixel_alpha = + srf_updates[i].plane_info->per_pixel_alpha; surface->public.dcc = srf_updates[i].plane_info->dcc; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c index ee840e75ee1f..c60b59f41693 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c @@ -221,10 +221,12 @@ void update_surface_trace( SURFACE_TRACE( "plane_info->tiling_info.gfx8.pipe_config = %d;\n" "plane_info->tiling_info.gfx8.array_mode = %d;\n" - "plane_info->visible = %d;\n", + "plane_info->visible = %d;\n" + "plane_info->per_pixel_alpha = %d;\n", update->plane_info->tiling_info.gfx8.pipe_config, update->plane_info->tiling_info.gfx8.array_mode, - update->plane_info->visible); + update->plane_info->visible, + update->plane_info->per_pixel_alpha); SURFACE_TRACE("surface->tiling_info.gfx9.swizzle = %d;\n", update->plane_info->tiling_info.gfx9.swizzle); diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index a20ba01d9e7b..7191b2519334 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -290,6 +290,7 @@ struct dc_transfer_func { }; struct dc_surface { + bool per_pixel_alpha; bool visible; bool flip_immediate; struct dc_plane_address address; @@ -316,6 +317,7 @@ struct dc_surface { }; struct dc_plane_info { + bool per_pixel_alpha; union plane_size plane_size; union dc_tiling_info tiling_info; struct dc_plane_dcc_param dcc; diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 06354c36c499..5269796b2a8e 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -97,7 +97,7 @@ struct dc_context { #define MAX_EDID_BUFFER_SIZE 512 #define EDID_BLOCK_SIZE 128 -#define MAX_SURFACE_NUM 2 +#define MAX_SURFACE_NUM 4 #define NUM_PIXEL_FORMATS 10 #include "dc_ddc_types.h" diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 107f82df3053..0a346aafacce 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1559,7 +1559,9 @@ static void update_dchubp_dpp( struct pipe_ctx *temp_pipe; int i; int tree_pos = 0; + bool per_pixel_alpha = surface->public.per_pixel_alpha && pipe_ctx->bottom_pipe; + /* TODO: proper fix once fpga works */ /* depends on DML calculation, DPP clock value may change dynamically */ enable_dppclk( dc->ctx, @@ -1604,11 +1606,7 @@ static void update_dchubp_dpp( /* TODO: build stream pipes group id. For now, use stream otg * id as pipe group id */ - /*pipe_ctx->scl_data.lb_params.alpha_en = pipe_ctx->surface->public.per_pixel_alpha;*/ - if (pipe_ctx->bottom_pipe && surface != pipe_ctx->bottom_pipe->surface) - pipe_ctx->scl_data.lb_params.alpha_en = 1; - else - pipe_ctx->scl_data.lb_params.alpha_en = 0; + pipe_ctx->scl_data.lb_params.alpha_en = per_pixel_alpha; pipe_ctx->mpc_idx = pipe_ctx->tg->inst; tree_cfg = &context->res_ctx.mpc_tree[pipe_ctx->mpc_idx]; if (tree_cfg->num_pipes == 0) { @@ -1625,7 +1623,7 @@ static void update_dchubp_dpp( tree_cfg->dpp[tree_pos] = pipe_ctx->pipe_idx; tree_cfg->mpcc[tree_pos] = pipe_ctx->pipe_idx; - tree_cfg->per_pixel_alpha[tree_pos] = pipe_ctx->scl_data.lb_params.alpha_en; + tree_cfg->per_pixel_alpha[tree_pos] = per_pixel_alpha; tree_cfg->num_pipes = tree_pos + 1; dcn10_set_mpc_tree(mpc, tree_cfg); -- cgit From fea0f581ab529e194d424452a6f7ecd88c5a2116 Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Tue, 6 Jun 2017 16:30:51 -0400 Subject: drm/amd/display: Temporary disable BTR FreeSync support for now Reduce timer tick interval for the static screen Signed-off-by: Anthony Koo Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/modules/freesync/freesync.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index f79c47951f90..7109742bd67c 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -436,11 +436,14 @@ static void calc_freesync_range(struct core_freesync *core_freesync, } /* Determine whether BTR can be supported */ - if (max_frame_duration_in_ns >= - 2 * min_frame_duration_in_ns) - core_freesync->map[index].caps->btr_supported = true; - else - core_freesync->map[index].caps->btr_supported = false; + //if (max_frame_duration_in_ns >= + // 2 * min_frame_duration_in_ns) + // core_freesync->map[index].caps->btr_supported = true; + //else + // core_freesync->map[index].caps->btr_supported = false; + + /* Temp, keep btr disabled */ + core_freesync->map[index].caps->btr_supported = false; /* Cache the time variables */ state->time.max_render_time_in_us = -- cgit From 2f1e8efd10315c516f07ed80484be8a1de143a8d Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Tue, 6 Jun 2017 16:41:00 -0400 Subject: drm/amd/display: Use surface update inuse for pending check. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c | 10 +++++++ .../gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h | 32 ++++++++++++++++++++++ 2 files changed, 42 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index 3e3fcf2395ae..8ad70625a746 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -821,13 +821,23 @@ bool mem_input_is_flip_pending(struct mem_input *mem_input) { uint32_t update_pending = 0; struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + struct dc_plane_address earliest_inuse_address; REG_GET(DCSURF_FLIP_CONTROL, SURFACE_UPDATE_PENDING, &update_pending); + REG_GET(DCSURF_SURFACE_EARLIEST_INUSE, + SURFACE_EARLIEST_INUSE_ADDRESS, &earliest_inuse_address.grph.addr.low_part); + + REG_GET(DCSURF_SURFACE_EARLIEST_INUSE_HIGH, + SURFACE_EARLIEST_INUSE_ADDRESS_HIGH, &earliest_inuse_address.grph.addr.high_part); + if (update_pending) return true; + if (earliest_inuse_address.grph.addr.quad_part != mem_input->request_address.grph.addr.quad_part) + return true; + mem_input->current_address = mem_input->request_address; return false; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h index 37683d072b42..9e2f1bb69958 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h @@ -52,6 +52,14 @@ SRI(DCSURF_PRIMARY_SURFACE_ADDRESS_C, HUBPREQ, id),\ SRI(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C, HUBPREQ, id),\ SRI(DCSURF_PRIMARY_META_SURFACE_ADDRESS_C, HUBPREQ, id),\ + SRI(DCSURF_SURFACE_INUSE, HUBPREQ, id),\ + SRI(DCSURF_SURFACE_INUSE_HIGH, HUBPREQ, id),\ + SRI(DCSURF_SURFACE_INUSE_C, HUBPREQ, id),\ + SRI(DCSURF_SURFACE_INUSE_HIGH_C, HUBPREQ, id),\ + SRI(DCSURF_SURFACE_EARLIEST_INUSE, HUBPREQ, id),\ + SRI(DCSURF_SURFACE_EARLIEST_INUSE_HIGH, HUBPREQ, id),\ + SRI(DCSURF_SURFACE_EARLIEST_INUSE_C, HUBPREQ, id),\ + SRI(DCSURF_SURFACE_EARLIEST_INUSE_HIGH_C, HUBPREQ, id),\ SRI(DCSURF_SURFACE_CONTROL, HUBPREQ, id),\ SRI(HUBPRET_CONTROL, HUBPRET, id),\ SRI(DCN_EXPANSION_MODE, HUBPREQ, id),\ @@ -165,6 +173,14 @@ struct dcn_mi_registers { uint32_t DCSURF_PRIMARY_SURFACE_ADDRESS_C; uint32_t DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C; uint32_t DCSURF_PRIMARY_META_SURFACE_ADDRESS_C; + uint32_t DCSURF_SURFACE_INUSE; + uint32_t DCSURF_SURFACE_INUSE_HIGH; + uint32_t DCSURF_SURFACE_INUSE_C; + uint32_t DCSURF_SURFACE_INUSE_HIGH_C; + uint32_t DCSURF_SURFACE_EARLIEST_INUSE; + uint32_t DCSURF_SURFACE_EARLIEST_INUSE_HIGH; + uint32_t DCSURF_SURFACE_EARLIEST_INUSE_C; + uint32_t DCSURF_SURFACE_EARLIEST_INUSE_HIGH_C; uint32_t DCSURF_SURFACE_CONTROL; uint32_t HUBPRET_CONTROL; uint32_t DCN_EXPANSION_MODE; @@ -297,6 +313,14 @@ struct dcn_mi_registers { MI_SF(HUBPREQ0_DCSURF_PRIMARY_SURFACE_ADDRESS_C, PRIMARY_SURFACE_ADDRESS_C, mask_sh),\ MI_SF(HUBPREQ0_DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C, PRIMARY_META_SURFACE_ADDRESS_HIGH_C, mask_sh),\ MI_SF(HUBPREQ0_DCSURF_PRIMARY_META_SURFACE_ADDRESS_C, PRIMARY_META_SURFACE_ADDRESS_C, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SURFACE_INUSE, SURFACE_INUSE_ADDRESS, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SURFACE_INUSE_HIGH, SURFACE_INUSE_ADDRESS_HIGH, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SURFACE_INUSE_C, SURFACE_INUSE_ADDRESS_C, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SURFACE_INUSE_HIGH_C, SURFACE_INUSE_ADDRESS_HIGH_C, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SURFACE_EARLIEST_INUSE, SURFACE_EARLIEST_INUSE_ADDRESS, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SURFACE_EARLIEST_INUSE_HIGH, SURFACE_EARLIEST_INUSE_ADDRESS_HIGH, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SURFACE_EARLIEST_INUSE_C, SURFACE_EARLIEST_INUSE_ADDRESS_C, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SURFACE_EARLIEST_INUSE_HIGH_C, SURFACE_EARLIEST_INUSE_ADDRESS_HIGH_C, mask_sh),\ MI_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, PRIMARY_SURFACE_DCC_EN, mask_sh),\ MI_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, PRIMARY_SURFACE_DCC_IND_64B_BLK, mask_sh),\ MI_SF(HUBPRET0_HUBPRET_CONTROL, DET_BUF_PLANE1_BASE_ADDRESS, mask_sh),\ @@ -433,6 +457,14 @@ struct dcn_mi_registers { type PRIMARY_SURFACE_ADDRESS_C;\ type PRIMARY_META_SURFACE_ADDRESS_HIGH_C;\ type PRIMARY_META_SURFACE_ADDRESS_C;\ + type SURFACE_INUSE_ADDRESS;\ + type SURFACE_INUSE_ADDRESS_HIGH;\ + type SURFACE_INUSE_ADDRESS_C;\ + type SURFACE_INUSE_ADDRESS_HIGH_C;\ + type SURFACE_EARLIEST_INUSE_ADDRESS;\ + type SURFACE_EARLIEST_INUSE_ADDRESS_HIGH;\ + type SURFACE_EARLIEST_INUSE_ADDRESS_C;\ + type SURFACE_EARLIEST_INUSE_ADDRESS_HIGH_C;\ type PRIMARY_SURFACE_DCC_EN;\ type PRIMARY_SURFACE_DCC_IND_64B_BLK;\ type DET_BUF_PLANE1_BASE_ADDRESS;\ -- cgit From 11589813e6dfd72093d0e7f53114d6478f689d91 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 7 Jun 2017 15:02:34 -0400 Subject: drm/amd/display: fix enable_optc_clock reg_wait timeouts Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc_helper.c | 8 +++++++- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c | 8 ++++---- 2 files changed, 11 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc_helper.c b/drivers/gpu/drm/amd/display/dc/dc_helper.c index a950dd53bca4..87fd5b9c8a16 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_helper.c +++ b/drivers/gpu/drm/amd/display/dc/dc_helper.c @@ -135,6 +135,9 @@ uint32_t generic_reg_wait(const struct dc_context *ctx, uint32_t reg_val; int i; + if (ctx->dce_environment == DCE_ENV_FPGA_MAXIMUS) + time_out_num_tries *= 20; + for (i = 0; i <= time_out_num_tries; i++) { if (i) { if (0 < delay_between_poll_us && delay_between_poll_us < 1000) @@ -152,7 +155,10 @@ uint32_t generic_reg_wait(const struct dc_context *ctx, return reg_val; } - DC_ERR("REG_WAIT timeout %dus * %d tries - %s\n", + dm_error("REG_WAIT timeout %dus * %d tries - %s\n", delay_between_poll_us, time_out_num_tries, func_name); + if (ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS) + BREAK_TO_DEBUGGER(); + return reg_val; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c index d7072132d456..c5a636c750fa 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c @@ -449,7 +449,7 @@ static void enable_optc_clock(struct timing_generator *tg, bool enable) REG_WAIT(OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_ON, 1, - 20000, 200000); + 2000, 500); /* Enable clock */ REG_UPDATE(OTG_CLOCK_CONTROL, @@ -457,7 +457,7 @@ static void enable_optc_clock(struct timing_generator *tg, bool enable) REG_WAIT(OTG_CLOCK_CONTROL, OTG_CLOCK_ON, 1, - 20000, 200000); + 2000, 500); } else { REG_UPDATE_2(OTG_CLOCK_CONTROL, OTG_CLOCK_GATE_DIS, 0, @@ -465,7 +465,7 @@ static void enable_optc_clock(struct timing_generator *tg, bool enable) REG_WAIT(OTG_CLOCK_CONTROL, OTG_CLOCK_ON, 0, - 20000, 200000); + 2000, 500); REG_UPDATE_2(OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_GATE_DIS, 0, @@ -473,7 +473,7 @@ static void enable_optc_clock(struct timing_generator *tg, bool enable) REG_WAIT(OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_ON, 0, - 20000, 200000); + 2000, 500); } } -- cgit From c9742685c24acd6d71cdda3067bfc2f512fe2b7c Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 7 Jun 2017 13:53:30 -0400 Subject: drm/amd/display: add bw logging for dcn Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 138 +++++++++++ drivers/gpu/drm/amd/display/dc/core/dc.c | 4 +- drivers/gpu/drm/amd/display/dc/core/dc_debug.c | 38 +++ drivers/gpu/drm/amd/display/dc/dc.h | 1 + .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 260 +++++++++++++++++---- .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 2 + .../gpu/drm/amd/display/include/logger_interface.h | 4 + 7 files changed, 398 insertions(+), 49 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 6d8bc6c74a73..f0f688b99d37 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -1312,6 +1312,144 @@ void dcn_bw_notify_pplib_of_wm_ranges(struct core_dc *dc) void dcn_bw_sync_calcs_and_dml(struct core_dc *dc) { kernel_fpu_begin(); + dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_CALCS, + "sr_exit_time: %d ns\n" + "sr_enter_plus_exit_time: %d ns\n" + "urgent_latency: %d ns\n" + "write_back_latency: %d ns\n" + "percent_of_ideal_drambw_received_after_urg_latency: %d %\n" + "max_request_size: %d bytes\n" + "dcfclkv_max0p9: %d kHz\n" + "dcfclkv_nom0p8: %d kHz\n" + "dcfclkv_mid0p72: %d kHz\n" + "dcfclkv_min0p65: %d kHz\n" + "max_dispclk_vmax0p9: %d kHz\n" + "max_dispclk_vnom0p8: %d kHz\n" + "max_dispclk_vmid0p72: %d kHz\n" + "max_dispclk_vmin0p65: %d kHz\n" + "max_dppclk_vmax0p9: %d kHz\n" + "max_dppclk_vnom0p8: %d kHz\n" + "max_dppclk_vmid0p72: %d kHz\n" + "max_dppclk_vmin0p65: %d kHz\n" + "socclk: %d kHz\n" + "fabric_and_dram_bandwidth_vmax0p9: %d MB/s\n" + "fabric_and_dram_bandwidth_vnom0p8: %d MB/s\n" + "fabric_and_dram_bandwidth_vmid0p72: %d MB/s\n" + "fabric_and_dram_bandwidth_vmin0p65: %d MB/s\n" + "phyclkv_max0p9: %d kHz\n" + "phyclkv_nom0p8: %d kHz\n" + "phyclkv_mid0p72: %d kHz\n" + "phyclkv_min0p65: %d kHz\n" + "downspreading: %d %\n" + "round_trip_ping_latency_cycles: %d DCFCLK Cycles\n" + "urgent_out_of_order_return_per_channel: %d Bytes\n" + "number_of_channels: %d\n" + "vmm_page_size: %d Bytes\n" + "dram_clock_change_latency: %d ns\n" + "return_bus_width: %d Bytes\n", + dc->dcn_soc.sr_exit_time * 1000, + dc->dcn_soc.sr_enter_plus_exit_time * 1000, + dc->dcn_soc.urgent_latency * 1000, + dc->dcn_soc.write_back_latency * 1000, + dc->dcn_soc.percent_of_ideal_drambw_received_after_urg_latency, + dc->dcn_soc.max_request_size, + dc->dcn_soc.dcfclkv_max0p9 * 1000, + dc->dcn_soc.dcfclkv_nom0p8 * 1000, + dc->dcn_soc.dcfclkv_mid0p72 * 1000, + dc->dcn_soc.dcfclkv_min0p65 * 1000, + dc->dcn_soc.max_dispclk_vmax0p9 * 1000, + dc->dcn_soc.max_dispclk_vnom0p8 * 1000, + dc->dcn_soc.max_dispclk_vmid0p72 * 1000, + dc->dcn_soc.max_dispclk_vmin0p65 * 1000, + dc->dcn_soc.max_dppclk_vmax0p9 * 1000, + dc->dcn_soc.max_dppclk_vnom0p8 * 1000, + dc->dcn_soc.max_dppclk_vmid0p72 * 1000, + dc->dcn_soc.max_dppclk_vmin0p65 * 1000, + dc->dcn_soc.socclk * 1000, + dc->dcn_soc.fabric_and_dram_bandwidth_vmax0p9 * 1000, + dc->dcn_soc.fabric_and_dram_bandwidth_vnom0p8 * 1000, + dc->dcn_soc.fabric_and_dram_bandwidth_vmid0p72 * 1000, + dc->dcn_soc.fabric_and_dram_bandwidth_vmin0p65 * 1000, + dc->dcn_soc.phyclkv_max0p9 * 1000, + dc->dcn_soc.phyclkv_nom0p8 * 1000, + dc->dcn_soc.phyclkv_mid0p72 * 1000, + dc->dcn_soc.phyclkv_min0p65 * 1000, + dc->dcn_soc.downspreading * 100, + dc->dcn_soc.round_trip_ping_latency_cycles, + dc->dcn_soc.urgent_out_of_order_return_per_channel, + dc->dcn_soc.number_of_channels, + dc->dcn_soc.vmm_page_size, + dc->dcn_soc.dram_clock_change_latency * 1000, + dc->dcn_soc.return_bus_width); + dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_CALCS, + "rob_buffer_size_in_kbyte: %d\n" + "det_buffer_size_in_kbyte: %d\n" + "dpp_output_buffer_pixels: %d\n" + "opp_output_buffer_lines: %d\n" + "pixel_chunk_size_in_kbyte: %d\n" + "pte_enable: %d\n" + "pte_chunk_size: %d kbytes\n" + "meta_chunk_size: %d kbytes\n" + "writeback_chunk_size: %d kbytes\n" + "odm_capability: %d\n" + "dsc_capability: %d\n" + "line_buffer_size: %d bits\n" + "max_line_buffer_lines: %d\n" + "is_line_buffer_bpp_fixed: %d\n" + "line_buffer_fixed_bpp: %d\n" + "writeback_luma_buffer_size: %d kbytes\n" + "writeback_chroma_buffer_size: %d kbytes\n" + "max_num_dpp: %d\n" + "max_num_writeback: %d\n" + "max_dchub_topscl_throughput: %d pixels/dppclk\n" + "max_pscl_tolb_throughput: %d pixels/dppclk\n" + "max_lb_tovscl_throughput: %d pixels/dppclk\n" + "max_vscl_tohscl_throughput: %d pixels/dppclk\n" + "max_hscl_ratio: %d\n" + "max_vscl_ratio: %d\n" + "max_hscl_taps: %d\n" + "max_vscl_taps: %d\n" + "pte_buffer_size_in_requests: %d\n" + "dispclk_ramping_margin: %d %\n" + "under_scan_factor: %d %\n" + "max_inter_dcn_tile_repeaters: %d\n" + "can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one: %d\n" + "bug_forcing_luma_and_chroma_request_to_same_size_fixed: %d\n" + "dcfclk_cstate_latency: %d\n", + dc->dcn_ip.rob_buffer_size_in_kbyte, + dc->dcn_ip.det_buffer_size_in_kbyte, + dc->dcn_ip.dpp_output_buffer_pixels, + dc->dcn_ip.opp_output_buffer_lines, + dc->dcn_ip.pixel_chunk_size_in_kbyte, + dc->dcn_ip.pte_enable, + dc->dcn_ip.pte_chunk_size, + dc->dcn_ip.meta_chunk_size, + dc->dcn_ip.writeback_chunk_size, + dc->dcn_ip.odm_capability, + dc->dcn_ip.dsc_capability, + dc->dcn_ip.line_buffer_size, + dc->dcn_ip.max_line_buffer_lines, + dc->dcn_ip.is_line_buffer_bpp_fixed, + dc->dcn_ip.line_buffer_fixed_bpp, + dc->dcn_ip.writeback_luma_buffer_size, + dc->dcn_ip.writeback_chroma_buffer_size, + dc->dcn_ip.max_num_dpp, + dc->dcn_ip.max_num_writeback, + dc->dcn_ip.max_dchub_topscl_throughput, + dc->dcn_ip.max_pscl_tolb_throughput, + dc->dcn_ip.max_lb_tovscl_throughput, + dc->dcn_ip.max_vscl_tohscl_throughput, + dc->dcn_ip.max_hscl_ratio, + dc->dcn_ip.max_vscl_ratio, + dc->dcn_ip.max_hscl_taps, + dc->dcn_ip.max_vscl_taps, + dc->dcn_ip.pte_buffer_size_in_requests, + dc->dcn_ip.dispclk_ramping_margin, + dc->dcn_ip.under_scan_factor * 100, + dc->dcn_ip.max_inter_dcn_tile_repeaters, + dc->dcn_ip.can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one, + dc->dcn_ip.bug_forcing_luma_and_chroma_request_to_same_size_fixed, + dc->dcn_ip.dcfclk_cstate_latency); dc->dml.soc.vmin.socclk_mhz = dc->dcn_soc.socclk; dc->dml.soc.vmid.socclk_mhz = dc->dcn_soc.socclk; dc->dml.soc.vnom.socclk_mhz = dc->dcn_soc.socclk; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index fb5bacb50ebc..47870a640f37 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1379,8 +1379,10 @@ void dc_update_surfaces_and_stream(struct dc *dc, if (!core_dc->res_pool->funcs->validate_bandwidth(core_dc, context)) { BREAK_TO_DEBUGGER(); goto fail; - } else + } else { core_dc->hwss.set_bandwidth(core_dc, context, false); + context_clock_trace(dc, context); + } } if (!surface_count) /* reset */ diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c index c60b59f41693..ad556e9b0754 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c @@ -29,6 +29,13 @@ ##__VA_ARGS__); \ } while (0) +#define CLOCK_TRACE(...) do {\ + if (dc->debug.clock_trace) \ + dm_logger_write(logger, \ + LOG_BANDWIDTH_CALCS, \ + ##__VA_ARGS__); \ +} while (0) + void pre_surface_trace( const struct dc *dc, const struct dc_surface *const *surfaces, @@ -314,3 +321,34 @@ void context_timing_trace( h_pos[i], v_pos[i]); } } + +void context_clock_trace( + const struct dc *dc, + struct validate_context *context) +{ +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + struct core_dc *core_dc = DC_TO_CORE(dc); + struct dal_logger *logger = core_dc->ctx->logger; + + CLOCK_TRACE("Current: dispclk_khz:%d dppclk_div:%d dcfclk_khz:%d\n" + "dcfclk_deep_sleep_khz:%d fclk_khz:%d\n" + "dram_ccm_us:%d min_active_dram_ccm_us:%d\n", + context->bw.dcn.calc_clk.dispclk_khz, + context->bw.dcn.calc_clk.dppclk_div, + context->bw.dcn.calc_clk.dcfclk_khz, + context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz, + context->bw.dcn.calc_clk.fclk_khz, + context->bw.dcn.calc_clk.dram_ccm_us, + context->bw.dcn.calc_clk.min_active_dram_ccm_us); + CLOCK_TRACE("Calculated: dispclk_khz:%d dppclk_div:%d dcfclk_khz:%d\n" + "dcfclk_deep_sleep_khz:%d fclk_khz:%d\n" + "dram_ccm_us:%d min_active_dram_ccm_us:%d\n", + context->bw.dcn.calc_clk.dispclk_khz, + context->bw.dcn.calc_clk.dppclk_div, + context->bw.dcn.calc_clk.dcfclk_khz, + context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz, + context->bw.dcn.calc_clk.fclk_khz, + context->bw.dcn.calc_clk.dram_ccm_us, + context->bw.dcn.calc_clk.min_active_dram_ccm_us); +#endif +} diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 7191b2519334..e08e532cafb8 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -160,6 +160,7 @@ struct dc_debug { bool max_disp_clk; bool surface_trace; bool timing_trace; + bool clock_trace; bool validation_trace; bool disable_stutter; bool disable_dcc; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 0a346aafacce..93a34e2ef175 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1412,6 +1412,128 @@ static void dcn10_enable_timing_synchronization( DC_SYNC_INFO("Sync complete\n"); } +static void print_rq_dlg_ttu( + struct core_dc *core_dc, + struct pipe_ctx *pipe_ctx) +{ + dm_logger_write(core_dc->ctx->logger, LOG_BANDWIDTH_CALCS, + "\n============== DML TTU Output parameters [%d] ==============\n" + "qos_level_low_wm: %d, \n" + "qos_level_high_wm: %d, \n" + "min_ttu_vblank: %d, \n" + "qos_level_flip: %d, \n" + "refcyc_per_req_delivery_l: %d, \n" + "qos_level_fixed_l: %d, \n" + "qos_ramp_disable_l: %d, \n" + "refcyc_per_req_delivery_pre_l: %d, \n" + "refcyc_per_req_delivery_c: %d, \n" + "qos_level_fixed_c: %d, \n" + "qos_ramp_disable_c: %d, \n" + "refcyc_per_req_delivery_pre_c: %d\n" + "=============================================================\n", + pipe_ctx->pipe_idx, + pipe_ctx->ttu_regs.qos_level_low_wm, + pipe_ctx->ttu_regs.qos_level_high_wm, + pipe_ctx->ttu_regs.min_ttu_vblank, + pipe_ctx->ttu_regs.qos_level_flip, + pipe_ctx->ttu_regs.refcyc_per_req_delivery_l, + pipe_ctx->ttu_regs.qos_level_fixed_l, + pipe_ctx->ttu_regs.qos_ramp_disable_l, + pipe_ctx->ttu_regs.refcyc_per_req_delivery_pre_l, + pipe_ctx->ttu_regs.refcyc_per_req_delivery_c, + pipe_ctx->ttu_regs.qos_level_fixed_c, + pipe_ctx->ttu_regs.qos_ramp_disable_c, + pipe_ctx->ttu_regs.refcyc_per_req_delivery_pre_c + ); + + dm_logger_write(core_dc->ctx->logger, LOG_BANDWIDTH_CALCS, + "\n============== DML DLG Output parameters [%d] ==============\n" + "refcyc_h_blank_end: %d, \n" + "dlg_vblank_end: %d, \n" + "min_dst_y_next_start: %d, \n" + "refcyc_per_htotal: %d, \n" + "refcyc_x_after_scaler: %d, \n" + "dst_y_after_scaler: %d, \n" + "dst_y_prefetch: %d, \n" + "dst_y_per_vm_vblank: %d, \n" + "dst_y_per_row_vblank: %d, \n" + "ref_freq_to_pix_freq: %d, \n" + "vratio_prefetch: %d, \n" + "refcyc_per_pte_group_vblank_l: %d, \n" + "refcyc_per_meta_chunk_vblank_l: %d, \n" + "dst_y_per_pte_row_nom_l: %d, \n" + "refcyc_per_pte_group_nom_l: %d, \n", + pipe_ctx->pipe_idx, + pipe_ctx->dlg_regs.refcyc_h_blank_end, + pipe_ctx->dlg_regs.dlg_vblank_end, + pipe_ctx->dlg_regs.min_dst_y_next_start, + pipe_ctx->dlg_regs.refcyc_per_htotal, + pipe_ctx->dlg_regs.refcyc_x_after_scaler, + pipe_ctx->dlg_regs.dst_y_after_scaler, + pipe_ctx->dlg_regs.dst_y_prefetch, + pipe_ctx->dlg_regs.dst_y_per_vm_vblank, + pipe_ctx->dlg_regs.dst_y_per_row_vblank, + pipe_ctx->dlg_regs.ref_freq_to_pix_freq, + pipe_ctx->dlg_regs.vratio_prefetch, + pipe_ctx->dlg_regs.refcyc_per_pte_group_vblank_l, + pipe_ctx->dlg_regs.refcyc_per_meta_chunk_vblank_l, + pipe_ctx->dlg_regs.dst_y_per_pte_row_nom_l, + pipe_ctx->dlg_regs.refcyc_per_pte_group_nom_l + ); + + dm_logger_write(core_dc->ctx->logger, LOG_BANDWIDTH_CALCS, + "\ndst_y_per_meta_row_nom_l: %d, \n" + "refcyc_per_meta_chunk_nom_l: %d, \n" + "refcyc_per_line_delivery_pre_l: %d, \n" + "refcyc_per_line_delivery_l: %d, \n" + "vratio_prefetch_c: %d, \n" + "refcyc_per_pte_group_vblank_c: %d, \n" + "refcyc_per_meta_chunk_vblank_c: %d, \n" + "dst_y_per_pte_row_nom_c: %d, \n" + "refcyc_per_pte_group_nom_c: %d, \n" + "dst_y_per_meta_row_nom_c: %d, \n" + "refcyc_per_meta_chunk_nom_c: %d, \n" + "refcyc_per_line_delivery_pre_c: %d, \n" + "refcyc_per_line_delivery_c: %d \n" + "========================================================\n", + pipe_ctx->dlg_regs.dst_y_per_meta_row_nom_l, + pipe_ctx->dlg_regs.refcyc_per_meta_chunk_nom_l, + pipe_ctx->dlg_regs.refcyc_per_line_delivery_pre_l, + pipe_ctx->dlg_regs.refcyc_per_line_delivery_l, + pipe_ctx->dlg_regs.vratio_prefetch_c, + pipe_ctx->dlg_regs.refcyc_per_pte_group_vblank_c, + pipe_ctx->dlg_regs.refcyc_per_meta_chunk_vblank_c, + pipe_ctx->dlg_regs.dst_y_per_pte_row_nom_c, + pipe_ctx->dlg_regs.refcyc_per_pte_group_nom_c, + pipe_ctx->dlg_regs.dst_y_per_meta_row_nom_c, + pipe_ctx->dlg_regs.refcyc_per_meta_chunk_nom_c, + pipe_ctx->dlg_regs.refcyc_per_line_delivery_pre_c, + pipe_ctx->dlg_regs.refcyc_per_line_delivery_c + ); + + dm_logger_write(core_dc->ctx->logger, LOG_BANDWIDTH_CALCS, + "\n============== DML RQ Output parameters [%d] ==============\n" + "chunk_size: %d \n" + "min_chunk_size: %d \n" + "meta_chunk_size: %d \n" + "min_meta_chunk_size: %d \n" + "dpte_group_size: %d \n" + "mpte_group_size: %d \n" + "swath_height: %d \n" + "pte_row_height_linear: %d \n" + "========================================================\n", + pipe_ctx->pipe_idx, + pipe_ctx->rq_regs.rq_regs_l.chunk_size, + pipe_ctx->rq_regs.rq_regs_l.min_chunk_size, + pipe_ctx->rq_regs.rq_regs_l.meta_chunk_size, + pipe_ctx->rq_regs.rq_regs_l.min_meta_chunk_size, + pipe_ctx->rq_regs.rq_regs_l.dpte_group_size, + pipe_ctx->rq_regs.rq_regs_l.mpte_group_size, + pipe_ctx->rq_regs.rq_regs_l.swath_height, + pipe_ctx->rq_regs.rq_regs_l.pte_row_height_linear + ); +} + static void dcn10_power_on_fe( struct core_dc *dc, struct pipe_ctx *pipe_ctx, @@ -1419,57 +1541,52 @@ static void dcn10_power_on_fe( { struct dc_surface *dc_surface = &pipe_ctx->surface->public; - /* power up DCHUP and DPP from pseudo code pipe_move.c */ - /*TODO: function: power_on_plane. If already power up, skip - */ - { - power_on_plane(dc->ctx, - pipe_ctx->pipe_idx, pipe_ctx->tg->inst); + power_on_plane(dc->ctx, + pipe_ctx->pipe_idx, pipe_ctx->tg->inst); - /* enable DCFCLK current DCHUB */ - enable_dcfclk(dc->ctx, + /* enable DCFCLK current DCHUB */ + enable_dcfclk(dc->ctx, + pipe_ctx->pipe_idx, + pipe_ctx->pix_clk_params.requested_pix_clk, + context->bw.dcn.calc_clk.dppclk_div); + dc->current_context->bw.dcn.cur_clk.dppclk_div = + context->bw.dcn.calc_clk.dppclk_div; + context->bw.dcn.cur_clk.dppclk_div = context->bw.dcn.calc_clk.dppclk_div; + + if (dc_surface) { + dm_logger_write(dc->ctx->logger, LOG_DC, + "Pipe:%d 0x%x: addr hi:0x%x, " + "addr low:0x%x, " + "src: %d, %d, %d," + " %d; dst: %d, %d, %d, %d;\n", pipe_ctx->pipe_idx, - pipe_ctx->pix_clk_params.requested_pix_clk, - context->bw.dcn.calc_clk.dppclk_div); - dc->current_context->bw.dcn.cur_clk.dppclk_div = - context->bw.dcn.calc_clk.dppclk_div; - context->bw.dcn.cur_clk.dppclk_div = context->bw.dcn.calc_clk.dppclk_div; - - if (dc_surface) { - dm_logger_write(dc->ctx->logger, LOG_DC, - "Pipe:%d 0x%x: addr hi:0x%x, " - "addr low:0x%x, " - "src: %d, %d, %d," - " %d; dst: %d, %d, %d, %d;\n", - pipe_ctx->pipe_idx, - dc_surface, - dc_surface->address.grph.addr.high_part, - dc_surface->address.grph.addr.low_part, - dc_surface->src_rect.x, - dc_surface->src_rect.y, - dc_surface->src_rect.width, - dc_surface->src_rect.height, - dc_surface->dst_rect.x, - dc_surface->dst_rect.y, - dc_surface->dst_rect.width, - dc_surface->dst_rect.height); - - dm_logger_write(dc->ctx->logger, LOG_HW_SET_MODE, - "Pipe %d: width, height, x, y\n" - "viewport:%d, %d, %d, %d\n" - "recout: %d, %d, %d, %d\n", - pipe_ctx->pipe_idx, - pipe_ctx->scl_data.viewport.width, - pipe_ctx->scl_data.viewport.height, - pipe_ctx->scl_data.viewport.x, - pipe_ctx->scl_data.viewport.y, - pipe_ctx->scl_data.recout.width, - pipe_ctx->scl_data.recout.height, - pipe_ctx->scl_data.recout.x, - pipe_ctx->scl_data.recout.y); - } + dc_surface, + dc_surface->address.grph.addr.high_part, + dc_surface->address.grph.addr.low_part, + dc_surface->src_rect.x, + dc_surface->src_rect.y, + dc_surface->src_rect.width, + dc_surface->src_rect.height, + dc_surface->dst_rect.x, + dc_surface->dst_rect.y, + dc_surface->dst_rect.width, + dc_surface->dst_rect.height); + + dm_logger_write(dc->ctx->logger, LOG_HW_SET_MODE, + "Pipe %d: width, height, x, y\n" + "viewport:%d, %d, %d, %d\n" + "recout: %d, %d, %d, %d\n", + pipe_ctx->pipe_idx, + pipe_ctx->scl_data.viewport.width, + pipe_ctx->scl_data.viewport.height, + pipe_ctx->scl_data.viewport.x, + pipe_ctx->scl_data.viewport.y, + pipe_ctx->scl_data.recout.width, + pipe_ctx->scl_data.recout.height, + pipe_ctx->scl_data.recout.x, + pipe_ctx->scl_data.recout.y); + print_rq_dlg_ttu(dc, pipe_ctx); } - } static void program_gamut_remap(struct pipe_ctx *pipe_ctx) @@ -1743,6 +1860,53 @@ static void dcn10_apply_ctx_for_surface( } } + dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_CALCS, + "\n============== Watermark parameters ==============\n" + "a.urgent_ns: %d \n" + "a.cstate_enter_plus_exit: %d \n" + "a.cstate_exit: %d \n" + "a.pstate_change: %d \n" + "a.pte_meta_urgent: %d \n" + "b.urgent_ns: %d \n" + "b.cstate_enter_plus_exit: %d \n" + "b.cstate_exit: %d \n" + "b.pstate_change: %d \n" + "b.pte_meta_urgent: %d \n", + context->bw.dcn.watermarks.a.urgent_ns, + context->bw.dcn.watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns, + context->bw.dcn.watermarks.a.cstate_pstate.cstate_exit_ns, + context->bw.dcn.watermarks.a.cstate_pstate.pstate_change_ns, + context->bw.dcn.watermarks.a.pte_meta_urgent_ns, + context->bw.dcn.watermarks.b.urgent_ns, + context->bw.dcn.watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns, + context->bw.dcn.watermarks.b.cstate_pstate.cstate_exit_ns, + context->bw.dcn.watermarks.b.cstate_pstate.pstate_change_ns, + context->bw.dcn.watermarks.b.pte_meta_urgent_ns + ); + dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_CALCS, + "\nc.urgent_ns: %d \n" + "c.cstate_enter_plus_exit: %d \n" + "c.cstate_exit: %d \n" + "c.pstate_change: %d \n" + "c.pte_meta_urgent: %d \n" + "d.urgent_ns: %d \n" + "d.cstate_enter_plus_exit: %d \n" + "d.cstate_exit: %d \n" + "d.pstate_change: %d \n" + "d.pte_meta_urgent: %d \n" + "========================================================\n", + context->bw.dcn.watermarks.c.urgent_ns, + context->bw.dcn.watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns, + context->bw.dcn.watermarks.c.cstate_pstate.cstate_exit_ns, + context->bw.dcn.watermarks.c.cstate_pstate.pstate_change_ns, + context->bw.dcn.watermarks.c.pte_meta_urgent_ns, + context->bw.dcn.watermarks.d.urgent_ns, + context->bw.dcn.watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns, + context->bw.dcn.watermarks.d.cstate_pstate.cstate_exit_ns, + context->bw.dcn.watermarks.d.cstate_pstate.pstate_change_ns, + context->bw.dcn.watermarks.d.pte_meta_urgent_ns + ); + for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index e527d10b3e1f..6ada9a262721 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -429,6 +429,7 @@ static const struct dc_debug debug_defaults_drv = { .disable_dmcu = true, .force_abm_enable = false, .timing_trace = false, + .clock_trace = true, .disable_pplib_clock_request = true, .disable_pplib_wm_range = false, #if defined(CONFIG_DRM_AMD_DC_DCN1_0) @@ -441,6 +442,7 @@ static const struct dc_debug debug_defaults_diags = { .disable_dmcu = true, .force_abm_enable = false, .timing_trace = true, + .clock_trace = true, #if defined(CONFIG_DRM_AMD_DC_DCN1_0) .disable_pplib_clock_request = true, .disable_pplib_wm_range = true, diff --git a/drivers/gpu/drm/amd/display/include/logger_interface.h b/drivers/gpu/drm/amd/display/include/logger_interface.h index 08a6911d3a3a..b75c343f8680 100644 --- a/drivers/gpu/drm/amd/display/include/logger_interface.h +++ b/drivers/gpu/drm/amd/display/include/logger_interface.h @@ -32,6 +32,7 @@ struct dc_context; struct dc_link; struct dc_surface_update; struct resource_context; +struct validate_context; /* * @@ -90,6 +91,9 @@ void context_timing_trace( const struct dc *dc, struct resource_context *res_ctx); +void context_clock_trace( + const struct dc *dc, + struct validate_context *context); /* Any function which is empty or have incomplete implementation should be * marked by this macro. -- cgit From 9edba5574d8253b739f4c78d880c80f94578859b Mon Sep 17 00:00:00 2001 From: Vitaly Prosyak Date: Wed, 7 Jun 2017 12:23:59 -0500 Subject: drm/amd/display: RV stereo support HDMI frame pack and DP frame alternate in band Signed-off-by: Vitaly Prosyak Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 21 ++- .../amd/display/dc/dcn10/dcn10_timing_generator.c | 184 ++++++++++----------- .../amd/display/dc/dcn10/dcn10_timing_generator.h | 5 + .../drm/amd/display/dc/inc/hw/timing_generator.h | 12 ++ drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 4 + 5 files changed, 124 insertions(+), 102 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index e08e532cafb8..fb86808dd309 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -361,6 +361,7 @@ struct dc_surface_status { struct dc_plane_address requested_address; struct dc_plane_address current_address; bool is_flip_pending; + bool is_right_eye; }; /* @@ -476,7 +477,7 @@ struct dc_stream { const struct dc_transfer_func *out_transfer_func; struct colorspace_transform gamut_remap_matrix; struct csc_transform csc_color_matrix; - + enum view_3d_format view_format; /* TODO: custom INFO packets */ /* TODO: ABM info (DMCU) */ /* TODO: PSR info */ @@ -591,6 +592,15 @@ bool dc_commit_streams( struct dc *dc, const struct dc_stream *streams[], uint8_t stream_count); +/* + * Enable stereo when commit_streams is not required, + * for example, frame alternate. + */ +bool dc_enable_stereo( + struct dc *dc, + struct validate_context *context, + const struct dc_stream *streams[], + uint8_t stream_count); /** * Create a new default stream for the requested sink @@ -777,6 +787,14 @@ struct dc_container_id { unsigned short productCode; }; +struct stereo_3d_features { + bool supported ; + bool allTimings ; + bool cloneMode ; + bool scaling ; + bool singleFrameSWPacked; +}; + /* * The sink structure contains EDID and other display device properties */ @@ -788,6 +806,7 @@ struct dc_sink { uint32_t dongle_max_pix_clk; bool converter_disable_audio; void *priv; + struct stereo_3d_features features_3d[TIMING_3D_FORMAT_MAX]; }; void dc_sink_retain(const struct dc_sink *sink); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c index c5a636c750fa..bc3934d75b46 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c @@ -78,112 +78,22 @@ static void dcn10_program_global_sync( VREADY_OFFSET, tg->dlg_otg_param.vready_offset); } -struct crtc_stereo_flags { - uint8_t PROGRAM_STEREO :1; - uint8_t PROGRAM_POLARITY :1; - uint8_t RIGHT_EYE_POLARITY :1; - uint8_t FRAME_PACKED :1; - uint8_t DISABLE_STEREO_DP_SYNC :1; -}; - -static void dcn10_enable_stereo(struct timing_generator *tg, - const struct crtc_stereo_flags *flags, - const struct dc_crtc_timing *timing) -{ - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); - - uint32_t active_width = timing->h_addressable; - uint32_t space1_size = timing->v_total - timing->v_addressable; - - if (flags) { - uint32_t stereo_en = flags->FRAME_PACKED == 0 ? 1 : 0; - - if (flags->PROGRAM_STEREO) - REG_UPDATE_3(OTG_STEREO_CONTROL, - OTG_STEREO_EN, stereo_en, - OTG_STEREO_SYNC_OUTPUT_LINE_NUM, 0, - OTG_STEREO_SYNC_OUTPUT_POLARITY, 0); - - if (flags->PROGRAM_POLARITY) - REG_UPDATE(OTG_STEREO_CONTROL, - OTG_STEREO_EYE_FLAG_POLARITY, - flags->RIGHT_EYE_POLARITY == 0 ? 0:1); - - if (flags->DISABLE_STEREO_DP_SYNC) - REG_UPDATE(OTG_STEREO_CONTROL, - OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP, 1); - - if (flags->PROGRAM_STEREO && flags->FRAME_PACKED) - REG_UPDATE_3(OTG_3D_STRUCTURE_CONTROL, - OTG_3D_STRUCTURE_EN, 1, - OTG_3D_STRUCTURE_V_UPDATE_MODE, 1, - OTG_3D_STRUCTURE_STEREO_SEL_OVR, 1); - - } - - REG_UPDATE(OPPBUF_CONTROL, - OPPBUF_ACTIVE_WIDTH, active_width); - - REG_UPDATE(OPPBUF_3D_PARAMETERS_0, - OPPBUF_3D_VACT_SPACE1_SIZE, space1_size); - - return; -} - static void dcn10_disable_stereo(struct timing_generator *tg) { struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); REG_SET(OTG_STEREO_CONTROL, 0, - OTG_STEREO_EN, 0); + OTG_STEREO_EN, 0); REG_SET_3(OTG_3D_STRUCTURE_CONTROL, 0, - OTG_3D_STRUCTURE_EN, 0, - OTG_3D_STRUCTURE_V_UPDATE_MODE, 0, - OTG_3D_STRUCTURE_STEREO_SEL_OVR, 0); + OTG_3D_STRUCTURE_EN, 0, + OTG_3D_STRUCTURE_V_UPDATE_MODE, 0, + OTG_3D_STRUCTURE_STEREO_SEL_OVR, 0); REG_UPDATE(OPPBUF_CONTROL, - OPPBUF_ACTIVE_WIDTH, 0); + OPPBUF_ACTIVE_WIDTH, 0); REG_UPDATE(OPPBUF_3D_PARAMETERS_0, - OPPBUF_3D_VACT_SPACE1_SIZE, 0); - return; -} - -static bool is_frame_alternate_stereo(enum dc_timing_3d_format fmt) -{ - bool ret = false; - if (fmt == TIMING_3D_FORMAT_FRAME_ALTERNATE || - fmt == TIMING_3D_FORMAT_INBAND_FA || - fmt == TIMING_3D_FORMAT_DP_HDMI_INBAND_FA || - fmt == TIMING_3D_FORMAT_SIDEBAND_FA) - ret = true; - return ret; -} - -static void dcn10_do_stereo(struct timing_generator *tg, - const struct dc_crtc_timing *dc_crtc_timing) -{ - struct crtc_stereo_flags stereo_flags = {0}; - if (dc_crtc_timing->timing_3d_format == TIMING_3D_FORMAT_NONE || - dc_crtc_timing->timing_3d_format == TIMING_3D_FORMAT_SIDE_BY_SIDE || - dc_crtc_timing->timing_3d_format == TIMING_3D_FORMAT_TOP_AND_BOTTOM) - dcn10_disable_stereo(tg); - else { - stereo_flags.PROGRAM_STEREO = 1; - stereo_flags.PROGRAM_POLARITY = 1; - stereo_flags.DISABLE_STEREO_DP_SYNC = 0; - stereo_flags.RIGHT_EYE_POLARITY = - dc_crtc_timing->flags.RIGHT_EYE_3D_POLARITY; - if (dc_crtc_timing->timing_3d_format == - TIMING_3D_FORMAT_HW_FRAME_PACKING) - stereo_flags.FRAME_PACKED = 1; - - if (is_frame_alternate_stereo( - dc_crtc_timing->timing_3d_format) || - dc_crtc_timing->timing_3d_format == - TIMING_3D_FORMAT_HW_FRAME_PACKING) - dcn10_enable_stereo(tg, &stereo_flags, dc_crtc_timing); - } + OPPBUF_3D_VACT_SPACE1_SIZE, 0); } /** @@ -361,9 +271,8 @@ static void tg_program_timing_generator( REG_UPDATE(OTG_H_TIMING_CNTL, OTG_H_TIMING_DIV_BY2, h_div_2); - /* Enable crtc stereo frame pack tested... todo more - */ - dcn10_do_stereo(tg, &patched_crtc_timing); + dcn10_disable_stereo( tg); + } /** tg_program_blanking @@ -605,7 +514,8 @@ static bool tg_validate_timing( timing->timing_3d_format != TIMING_3D_FORMAT_HW_FRAME_PACKING && timing->timing_3d_format != TIMING_3D_FORMAT_TOP_AND_BOTTOM && timing->timing_3d_format != TIMING_3D_FORMAT_SIDE_BY_SIDE && - timing->timing_3d_format != TIMING_3D_FORMAT_FRAME_ALTERNATE) + timing->timing_3d_format != TIMING_3D_FORMAT_FRAME_ALTERNATE && + timing->timing_3d_format != TIMING_3D_FORMAT_INBAND_FA) return false; /* Temporarily blocking interlacing mode until it's supported */ @@ -1145,6 +1055,76 @@ void dcn10_timing_generator_get_crtc_scanoutpos( *v_position = position.vertical_count; } + + +static void dcn10_enable_stereo(struct timing_generator *tg, + const struct dc_crtc_timing *timing, struct crtc_stereo_flags *flags) +{ + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + + uint32_t active_width = timing->h_addressable; + uint32_t space1_size = timing->v_total - timing->v_addressable; + + if (flags) { + uint32_t stereo_en; + stereo_en = flags->FRAME_PACKED == 0 ? 1 : 0; + + if (flags->PROGRAM_STEREO) + REG_UPDATE_3(OTG_STEREO_CONTROL, + OTG_STEREO_EN, stereo_en, + OTG_STEREO_SYNC_OUTPUT_LINE_NUM, 0, + OTG_STEREO_SYNC_OUTPUT_POLARITY, 0); + + if (flags->PROGRAM_POLARITY) + REG_UPDATE(OTG_STEREO_CONTROL, + OTG_STEREO_EYE_FLAG_POLARITY, + flags->RIGHT_EYE_POLARITY == 0 ? 0 : 1); + + if (flags->DISABLE_STEREO_DP_SYNC) + REG_UPDATE(OTG_STEREO_CONTROL, + OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP, 1); + + if (flags->PROGRAM_STEREO && flags->FRAME_PACKED) + REG_UPDATE_3(OTG_3D_STRUCTURE_CONTROL, + OTG_3D_STRUCTURE_EN, 1, + OTG_3D_STRUCTURE_V_UPDATE_MODE, 1, + OTG_3D_STRUCTURE_STEREO_SEL_OVR, 1); + + } + + REG_UPDATE(OPPBUF_CONTROL, + OPPBUF_ACTIVE_WIDTH, active_width); + + REG_UPDATE(OPPBUF_3D_PARAMETERS_0, + OPPBUF_3D_VACT_SPACE1_SIZE, space1_size); +} + +static void dcn10_program_stereo(struct timing_generator *tg, + const struct dc_crtc_timing *timing, struct crtc_stereo_flags *flags) +{ + if (flags->PROGRAM_STEREO) + dcn10_enable_stereo(tg, timing, flags); + else + dcn10_disable_stereo(tg); +} + + +static bool dcn10_is_stereo_left_eye(struct timing_generator *tg) +{ + bool ret = false; + uint32_t left_eye = 0; + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + + REG_GET(OTG_STEREO_STATUS, + OTG_STEREO_CURRENT_EYE, &left_eye); + if (left_eye == 1) + ret = true; + else + ret = false; + + return ret; +} + static struct timing_generator_funcs dcn10_tg_funcs = { .validate_timing = tg_validate_timing, .program_timing = tg_program_timing, @@ -1183,7 +1163,9 @@ static struct timing_generator_funcs dcn10_tg_funcs = { .enable_optc_clock = enable_optc_clock, .set_drr = dcn10_timing_generator_set_drr, .set_static_screen_control = set_static_screen_control, - .set_test_pattern = dcn10_timing_generator_set_test_pattern + .set_test_pattern = dcn10_timing_generator_set_test_pattern, + .program_stereo = dcn10_program_stereo, + .is_stereo_left_eye = dcn10_is_stereo_left_eye }; void dcn10_timing_generator_init(struct dcn10_timing_generator *tgn10) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h index 85a763af1956..c880fa587790 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h @@ -51,6 +51,7 @@ SRI(OTG_CONTROL, OTG, inst),\ SRI(OTG_STEREO_CONTROL, OTG, inst),\ SRI(OTG_3D_STRUCTURE_CONTROL, OTG, inst),\ + SRI(OTG_STEREO_STATUS, OTG, inst),\ SRI(OTG_V_TOTAL_MAX, OTG, inst),\ SRI(OTG_V_TOTAL_MIN, OTG, inst),\ SRI(OTG_V_TOTAL_CONTROL, OTG, inst),\ @@ -96,6 +97,7 @@ struct dcn_tg_registers { uint32_t OTG_CONTROL; uint32_t OTG_STEREO_CONTROL; uint32_t OTG_3D_STRUCTURE_CONTROL; + uint32_t OTG_STEREO_STATUS; uint32_t OTG_V_TOTAL_MAX; uint32_t OTG_V_TOTAL_MIN; uint32_t OTG_V_TOTAL_CONTROL; @@ -157,6 +159,8 @@ struct dcn_tg_registers { SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_SYNC_OUTPUT_POLARITY, mask_sh),\ SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_EYE_FLAG_POLARITY, mask_sh),\ SF(OTG0_OTG_STEREO_CONTROL, OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP, mask_sh),\ + SF(OTG0_OTG_STEREO_CONTROL, OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP, mask_sh),\ + SF(OTG0_OTG_STEREO_STATUS, OTG_STEREO_CURRENT_EYE, mask_sh),\ SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_EN, mask_sh),\ SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_V_UPDATE_MODE, mask_sh),\ SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_STEREO_SEL_OVR, mask_sh),\ @@ -243,6 +247,7 @@ struct dcn_tg_registers { type OTG_STEREO_SYNC_OUTPUT_LINE_NUM;\ type OTG_STEREO_SYNC_OUTPUT_POLARITY;\ type OTG_STEREO_EYE_FLAG_POLARITY;\ + type OTG_STEREO_CURRENT_EYE;\ type OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP;\ type OTG_3D_STRUCTURE_EN;\ type OTG_3D_STRUCTURE_V_UPDATE_MODE;\ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h index 9f130affb31c..2b72d1d8012f 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h @@ -100,6 +100,15 @@ struct _dlg_otg_param { enum signal_type signal; }; #endif + +struct crtc_stereo_flags { + uint8_t PROGRAM_STEREO : 1; + uint8_t PROGRAM_POLARITY : 1; + uint8_t RIGHT_EYE_POLARITY : 1; + uint8_t FRAME_PACKED : 1; + uint8_t DISABLE_STEREO_DP_SYNC : 1; +}; + struct timing_generator { const struct timing_generator_funcs *funcs; struct dc_bios *bp; @@ -171,6 +180,9 @@ struct timing_generator_funcs { void (*program_global_sync)(struct timing_generator *tg); void (*enable_optc_clock)(struct timing_generator *tg, bool enable); #endif + void (*program_stereo)(struct timing_generator *tg, + const struct dc_crtc_timing *timing, struct crtc_stereo_flags *flags); + bool (*is_stereo_left_eye)(struct timing_generator *tg); }; #endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 6f8733ec9b16..52884815c67b 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -143,6 +143,10 @@ struct hw_sequencer_funcs { struct pipe_ctx *pipe_ctx, struct validate_context *context, struct core_dc *dc); + + void (*setup_stereo)( + struct pipe_ctx *pipe_ctx, + struct core_dc *dc); }; void color_space_to_black_color( -- cgit From 4c6e75989e8edd2bf9c22a70b2a838547cc6c6f3 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Thu, 8 Jun 2017 14:26:40 -0400 Subject: drm/amd/display: disable dcc when reset front end. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 2 ++ drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c | 15 +++++++++++---- drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h | 3 +++ 3 files changed, 16 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 93a34e2ef175..f2b581faa9b7 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -825,6 +825,8 @@ static void reset_front_end_for_pipe( if (!pipe_ctx->surface) return; + pipe_ctx->mi->funcs->dcc_control(pipe_ctx->mi, false, false); + lock_otg_master_update(dc->ctx, pipe_ctx->tg->inst); /* TODO: build stream pipes group id. For now, use stream otg diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index 8ad70625a746..a58993aa400f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -369,16 +369,22 @@ static bool mem_input_program_surface_flip_and_addr( return true; } -static void program_control(struct dcn10_mem_input *mi, - struct dc_plane_dcc_param *dcc) +static void dcc_control(struct mem_input *mem_input, bool enable, + bool independent_64b_blks) { - uint32_t dcc_en = dcc->enable ? 1 : 0; - uint32_t dcc_ind_64b_blk = dcc->grph.independent_64b_blks ? 1 : 0; + uint32_t dcc_en = enable ? 1 : 0; + uint32_t dcc_ind_64b_blk = independent_64b_blks ? 1 : 0; + struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); REG_UPDATE_2(DCSURF_SURFACE_CONTROL, PRIMARY_SURFACE_DCC_EN, dcc_en, PRIMARY_SURFACE_DCC_IND_64B_BLK, dcc_ind_64b_blk); +} +static void program_control(struct dcn10_mem_input *mi, + struct dc_plane_dcc_param *dcc) +{ + dcc_control(&mi->base, dcc->enable, dcc->grph.independent_64b_blks); } static void mem_input_program_surface_config( @@ -1072,6 +1078,7 @@ static struct mem_input_funcs dcn10_mem_input_funcs = { .mem_input_update_dchub = mem_input_update_dchub, .mem_input_program_pte_vm = dcn_mem_input_program_pte_vm, .set_blank = dcn_mi_set_blank, + .dcc_control = dcc_control, }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h index bd0dfeb2afa2..64b810d48d07 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h @@ -86,6 +86,9 @@ struct mem_input_funcs { struct _vcs_dpi_display_ttu_regs_st *ttu_regs, struct _vcs_dpi_display_rq_regs_st *rq_regs, struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest); + + void (*dcc_control)(struct mem_input *mem_input, bool enable, + bool independent_64b_blks); #endif void (*mem_input_program_display_marks)( -- cgit From f0558542a72e72919dae2ac2187847ec312c2bcb Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Thu, 1 Jun 2017 18:35:54 -0400 Subject: drm/amd/display: redesign mpc Signed-off-by: Dmytro Laktyushkin Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 1 + drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 10 +- drivers/gpu/drm/amd/display/dc/dc_helper.c | 10 +- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 105 +++---- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c | 336 +++++---------------- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h | 102 +++---- .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 73 +++-- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 12 +- drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h | 81 ++--- 9 files changed, 228 insertions(+), 502 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index f0f688b99d37..66f0595a4c20 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -517,6 +517,7 @@ static void split_stream_across_pipes( secondary_pipe->stream = primary_pipe->stream; secondary_pipe->tg = primary_pipe->tg; + secondary_pipe->mpcc = pool->mpcc[secondary_pipe->pipe_idx]; secondary_pipe->mi = pool->mis[secondary_pipe->pipe_idx]; secondary_pipe->ipp = pool->ipps[secondary_pipe->pipe_idx]; secondary_pipe->xfm = pool->transforms[secondary_pipe->pipe_idx]; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index b7f31b985b4f..c51ec617eff7 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1008,8 +1008,6 @@ static int acquire_first_split_pipe( if (pipe_ctx->top_pipe && pipe_ctx->top_pipe->surface == pipe_ctx->surface) { - int mpc_idx = pipe_ctx->mpc_idx; - pipe_ctx->top_pipe->bottom_pipe = pipe_ctx->bottom_pipe; if (pipe_ctx->bottom_pipe) pipe_ctx->bottom_pipe->top_pipe = pipe_ctx->top_pipe; @@ -1021,8 +1019,8 @@ static int acquire_first_split_pipe( pipe_ctx->xfm = pool->transforms[i]; pipe_ctx->opp = pool->opps[i]; pipe_ctx->dis_clk = pool->display_clock; + pipe_ctx->mpcc = pool->mpcc[i]; pipe_ctx->pipe_idx = i; - pipe_ctx->mpc_idx = mpc_idx; pipe_ctx->stream = stream; return i; @@ -1243,6 +1241,9 @@ static int acquire_first_free_pipe( if (!res_ctx->pipe_ctx[i].stream) { struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + pipe_ctx->mpcc = pool->mpcc[i]; +#endif pipe_ctx->tg = pool->timing_generators[i]; pipe_ctx->mi = pool->mis[i]; pipe_ctx->ipp = pool->ipps[i]; @@ -1251,9 +1252,6 @@ static int acquire_first_free_pipe( pipe_ctx->dis_clk = pool->display_clock; pipe_ctx->pipe_idx = i; -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) - pipe_ctx->mpc_idx = -1; -#endif pipe_ctx->stream = stream; return i; diff --git a/drivers/gpu/drm/amd/display/dc/dc_helper.c b/drivers/gpu/drm/amd/display/dc/dc_helper.c index 87fd5b9c8a16..8ed1440d2b01 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_helper.c +++ b/drivers/gpu/drm/amd/display/dc/dc_helper.c @@ -135,8 +135,11 @@ uint32_t generic_reg_wait(const struct dc_context *ctx, uint32_t reg_val; int i; - if (ctx->dce_environment == DCE_ENV_FPGA_MAXIMUS) - time_out_num_tries *= 20; + if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment)) { + /* 35 seconds */ + delay_between_poll_us = 35000; + time_out_num_tries = 1000; + } for (i = 0; i <= time_out_num_tries; i++) { if (i) { @@ -157,7 +160,8 @@ uint32_t generic_reg_wait(const struct dc_context *ctx, dm_error("REG_WAIT timeout %dus * %d tries - %s\n", delay_between_poll_us, time_out_num_tries, func_name); - if (ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS) + + if (!IS_FPGA_MAXIMUS_DC(ctx->dce_environment)) BREAK_TO_DEBUGGER(); return reg_val; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index f2b581faa9b7..f509dfd97f23 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -592,9 +592,19 @@ static void init_hw(struct core_dc *dc) for (i = 0; i < dc->res_pool->pipe_count; i++) { struct timing_generator *tg = dc->res_pool->timing_generators[i]; + struct mpcc *mpcc = + dc->res_pool->mpcc[i]; + struct mpcc_cfg mpcc_cfg; + + lock_otg_master_update(dc->ctx, tg->inst); + mpcc_cfg.opp_id = 0xf; + mpcc_cfg.top_dpp_id = 0xf; + mpcc_cfg.bot_mpcc_id = 0xf; + mpcc_cfg.top_of_tree = true; + mpcc->funcs->set(mpcc, &mpcc_cfg); + unlock_otg_master(dc->ctx, tg->inst); tg->funcs->disable_vga(tg); - /* Blank controller using driver code instead of * command table. */ @@ -819,8 +829,7 @@ static void reset_front_end_for_pipe( struct pipe_ctx *pipe_ctx, struct validate_context *context) { - struct dcn10_mpc *mpc = TO_DCN10_MPC(dc->res_pool->mpc); - struct mpc_tree_cfg *tree_cfg = NULL; + struct mpcc_cfg mpcc_cfg; if (!pipe_ctx->surface) return; @@ -829,20 +838,14 @@ static void reset_front_end_for_pipe( lock_otg_master_update(dc->ctx, pipe_ctx->tg->inst); - /* TODO: build stream pipes group id. For now, use stream otg - * id as pipe group id - */ - tree_cfg = &dc->current_context->res_ctx.mpc_tree[pipe_ctx->mpc_idx]; - - if (!dcn10_remove_dpp(mpc, tree_cfg, pipe_ctx->pipe_idx)) { - dm_logger_write(dc->ctx->logger, LOG_RESOURCE, - "%s: failed to find dpp to be removed!\n", - __func__); - } + mpcc_cfg.opp_id = 0xf; + mpcc_cfg.top_dpp_id = 0xf; + mpcc_cfg.bot_mpcc_id = 0xf; + mpcc_cfg.top_of_tree = !pipe_ctx->top_pipe; + pipe_ctx->mpcc->funcs->set(pipe_ctx->mpcc, &mpcc_cfg); pipe_ctx->top_pipe = NULL; pipe_ctx->bottom_pipe = NULL; - pipe_ctx->mpc_idx = -1; unlock_master_tg_and_wait(dc->ctx, pipe_ctx->tg->inst); @@ -850,8 +853,6 @@ static void reset_front_end_for_pipe( wait_no_outstanding_request(dc->ctx, pipe_ctx->pipe_idx); - wait_mpcc_idle(mpc, pipe_ctx->pipe_idx); - disable_clocks(dc->ctx, pipe_ctx->pipe_idx); pipe_ctx->xfm->funcs->transform_reset(pipe_ctx->xfm); @@ -893,14 +894,10 @@ static void reset_hw_ctx_wrap( reset_hw_ctx(dc, context, reset_front_end_for_pipe); /* Reset Back End*/ reset_hw_ctx(dc, context, reset_back_end_for_pipe); - - memcpy(context->res_ctx.mpc_tree, - dc->current_context->res_ctx.mpc_tree, - sizeof(struct mpc_tree_cfg) * dc->res_pool->pipe_count); } -static bool patch_address_for_sbs_tb_stereo(struct pipe_ctx *pipe_ctx, - PHYSICAL_ADDRESS_LOC *addr) +static bool patch_address_for_sbs_tb_stereo( + struct pipe_ctx *pipe_ctx, PHYSICAL_ADDRESS_LOC *addr) { struct core_surface *surface = pipe_ctx->surface; bool sec_split = pipe_ctx->top_pipe && @@ -1670,14 +1667,10 @@ static void update_dchubp_dpp( struct input_pixel_processor *ipp = pipe_ctx->ipp; struct core_surface *surface = pipe_ctx->surface; union plane_size size = surface->public.plane_size; - struct mpc_tree_cfg *tree_cfg = NULL; struct default_adjustment ocsc = {0}; - enum dc_color_space color_space; struct tg_color black_color = {0}; - struct dcn10_mpc *mpc = TO_DCN10_MPC(dc->res_pool->mpc); - struct pipe_ctx *temp_pipe; - int i; - int tree_pos = 0; + struct mpcc_cfg mpcc_cfg; + struct pipe_ctx *top_pipe; bool per_pixel_alpha = surface->public.per_pixel_alpha && pipe_ctx->bottom_pipe; /* TODO: proper fix once fpga works */ @@ -1716,39 +1709,23 @@ static void update_dchubp_dpp( 1, IPP_OUTPUT_FORMAT_12_BIT_FIX); - /* mpc TODO un-hardcode object ids - * for pseudo code pipe_move.c : - * add_plane_mpcc(added_plane_inst, mpcc_inst, ...); - * Do we want to cache the tree_cfg? - */ - - /* TODO: build stream pipes group id. For now, use stream otg - * id as pipe group id - */ pipe_ctx->scl_data.lb_params.alpha_en = per_pixel_alpha; - pipe_ctx->mpc_idx = pipe_ctx->tg->inst; - tree_cfg = &context->res_ctx.mpc_tree[pipe_ctx->mpc_idx]; - if (tree_cfg->num_pipes == 0) { - tree_cfg->opp_id = pipe_ctx->tg->inst; - for (i = 0; i < MAX_PIPES; i++) { - tree_cfg->dpp[i] = 0xf; - tree_cfg->mpcc[i] = 0xf; - } - } - - for (temp_pipe = pipe_ctx->top_pipe; - temp_pipe != NULL; temp_pipe = temp_pipe->top_pipe) - tree_pos++; - - tree_cfg->dpp[tree_pos] = pipe_ctx->pipe_idx; - tree_cfg->mpcc[tree_pos] = pipe_ctx->pipe_idx; - tree_cfg->per_pixel_alpha[tree_pos] = per_pixel_alpha; - tree_cfg->num_pipes = tree_pos + 1; - dcn10_set_mpc_tree(mpc, tree_cfg); + for (top_pipe = pipe_ctx; top_pipe != NULL; top_pipe = top_pipe->top_pipe) + mpcc_cfg.opp_id = top_pipe->opp->inst; + mpcc_cfg.top_dpp_id = pipe_ctx->pipe_idx; + if (pipe_ctx->bottom_pipe) + mpcc_cfg.bot_mpcc_id = pipe_ctx->bottom_pipe->mpcc->inst; + else + mpcc_cfg.bot_mpcc_id = 0xf; + mpcc_cfg.top_of_tree = !pipe_ctx->top_pipe; + mpcc_cfg.per_pixel_alpha = per_pixel_alpha; + if (!dc->current_context->res_ctx.pipe_ctx[pipe_ctx->pipe_idx].surface) + pipe_ctx->mpcc->funcs->wait_for_idle(pipe_ctx->mpcc); + pipe_ctx->mpcc->funcs->set(pipe_ctx->mpcc, &mpcc_cfg); - color_space = pipe_ctx->stream->public.output_color_space; - color_space_to_black_color(dc, color_space, &black_color); - dcn10_set_mpc_background_color(mpc, pipe_ctx->pipe_idx, &black_color); + color_space_to_black_color( + dc, pipe_ctx->stream->public.output_color_space, &black_color); + pipe_ctx->mpcc->funcs->set_bg_color(pipe_ctx->mpcc, &black_color); pipe_ctx->scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; /* scaler configuration */ @@ -1853,13 +1830,8 @@ static void dcn10_apply_ctx_for_surface( /* looking for top pipe to program */ - if (!pipe_ctx->top_pipe) { - memcpy(context->res_ctx.mpc_tree, - dc->current_context->res_ctx.mpc_tree, - sizeof(struct mpc_tree_cfg) * dc->res_pool->pipe_count); - + if (!pipe_ctx->top_pipe) program_all_pipe_in_tree(dc, pipe_ctx, context); - } } dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_CALCS, @@ -1927,8 +1899,7 @@ static void dcn10_apply_ctx_for_surface( if ((!pipe_ctx->surface && old_pipe_ctx->surface) || (!pipe_ctx->stream && old_pipe_ctx->stream)) - reset_front_end_for_pipe(dc, - old_pipe_ctx, dc->current_context); + reset_front_end_for_pipe(dc, old_pipe_ctx, dc->current_context); } } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c index 58f80114e36b..19af0ee86191 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c @@ -27,34 +27,26 @@ #include "dcn10_mpc.h" #define REG(reg)\ - mpc->mpc_regs->reg + mpcc10->mpcc_regs->reg #define CTX \ - mpc->base.ctx + mpcc10->base.ctx #undef FN #define FN(reg_name, field_name) \ - mpc->mpc_shift->field_name, mpc->mpc_mask->field_name + mpcc10->mpcc_shift->field_name, mpcc10->mpcc_mask->field_name #define MODE_TOP_ONLY 1 #define MODE_BLEND 3 +#define BLND_PP_ALPHA 0 +#define BLND_GLOBAL_ALPHA 2 -/* Internal function to set mpc output mux */ -static void set_output_mux(struct dcn10_mpc *mpc, - uint8_t opp_id, - uint8_t mpcc_id) -{ - if (mpcc_id != 0xf) - REG_UPDATE(OPP_PIPE_CONTROL[opp_id], - OPP_PIPE_CLOCK_EN, 1); - - REG_SET(MUX[opp_id], 0, MPC_OUT_MUX, mpcc_id); -} -void dcn10_set_mpc_background_color(struct dcn10_mpc *mpc, - unsigned int mpcc_inst, - struct tg_color *bg_color) +void dcn10_mpcc_set_bg_color( + struct mpcc *mpcc, + struct tg_color *bg_color) { + struct dcn10_mpcc *mpcc10 = TO_DCN10_MPCC(mpcc); /* mpc color is 12 bit. tg_color is 10 bit */ /* todo: might want to use 16 bit to represent color and have each * hw block translate to correct color depth. @@ -63,277 +55,89 @@ void dcn10_set_mpc_background_color(struct dcn10_mpc *mpc, uint32_t bg_g_y = bg_color->color_g_y << 2; uint32_t bg_b_cb = bg_color->color_b_cb << 2; - REG_SET(MPCC_BG_R_CR[mpcc_inst], 0, + REG_SET(MPCC_BG_R_CR, 0, MPCC_BG_R_CR, bg_r_cr); - REG_SET(MPCC_BG_G_Y[mpcc_inst], 0, + REG_SET(MPCC_BG_G_Y, 0, MPCC_BG_G_Y, bg_g_y); - REG_SET(MPCC_BG_B_CB[mpcc_inst], 0, + REG_SET(MPCC_BG_B_CB, 0, MPCC_BG_B_CB, bg_b_cb); } -/* This function programs MPC tree configuration - * Assume it is the initial time to setup MPC tree_configure, means - * the instance of dpp/mpcc/opp specified in structure tree_cfg are - * in idle status. - * Before invoke this function, ensure that master lock of OPTC specified - * by opp_id is set. - * - * tree_cfg[in] - new MPC_TREE_CFG - */ - -void dcn10_set_mpc_tree(struct dcn10_mpc *mpc, - struct mpc_tree_cfg *tree_cfg) +static void set_output_mux(struct dcn10_mpcc *mpcc10, int opp_id, int mpcc_id) { - int i; - - for (i = 0; i < tree_cfg->num_pipes; i++) { - uint8_t mpcc_inst = tree_cfg->mpcc[i]; - - REG_SET(MPCC_OPP_ID[mpcc_inst], 0, - MPCC_OPP_ID, tree_cfg->opp_id); - - REG_SET(MPCC_TOP_SEL[mpcc_inst], 0, - MPCC_TOP_SEL, tree_cfg->dpp[i]); - - if (i == tree_cfg->num_pipes-1) { - REG_SET(MPCC_BOT_SEL[mpcc_inst], 0, - MPCC_BOT_SEL, 0xF); - - REG_UPDATE(MPCC_CONTROL[mpcc_inst], - MPCC_MODE, MODE_TOP_ONLY); - } else { - REG_SET(MPCC_BOT_SEL[mpcc_inst], 0, - MPCC_BOT_SEL, tree_cfg->dpp[i+1]); - - REG_UPDATE(MPCC_CONTROL[mpcc_inst], - MPCC_MODE, MODE_BLEND); - } - - if (i == 0) - set_output_mux( - mpc, tree_cfg->opp_id, mpcc_inst); - - REG_UPDATE_2(MPCC_CONTROL[mpcc_inst], - MPCC_ALPHA_BLND_MODE, - tree_cfg->per_pixel_alpha[i] ? 0 : 2, - MPCC_ALPHA_MULTIPLIED_MODE, 0); - } + ASSERT(mpcc10->opp_id == 0xf || opp_id == mpcc10->opp_id); + mpcc10->opp_id = opp_id; + REG_UPDATE(OPP_PIPE_CONTROL[opp_id], OPP_PIPE_CLOCK_EN, 1); + REG_SET(MUX[opp_id], 0, MPC_OUT_MUX, mpcc_id); } -/* - * This is the function to remove current MPC tree specified by tree_cfg - * Before invoke this function, ensure that master lock of OPTC specified - * by opp_id is set. - * - *tree_cfg[in/out] - current MPC_TREE_CFG - */ -void dcn10_delete_mpc_tree(struct dcn10_mpc *mpc, - struct mpc_tree_cfg *tree_cfg) +static void reset_output_mux(struct dcn10_mpcc *mpcc10) { - int i; - - for (i = 0; i < tree_cfg->num_pipes; i++) { - uint8_t mpcc_inst = tree_cfg->mpcc[i]; - - REG_SET(MPCC_OPP_ID[mpcc_inst], 0, - MPCC_OPP_ID, 0xf); - - REG_SET(MPCC_TOP_SEL[mpcc_inst], 0, - MPCC_TOP_SEL, 0xf); - - REG_SET(MPCC_BOT_SEL[mpcc_inst], 0, - MPCC_BOT_SEL, 0xF); - - /* add remove dpp/mpcc pair into pending list - * TODO FPGA AddToPendingList if empty from pseudo code - */ - tree_cfg->dpp[i] = 0xf; - tree_cfg->mpcc[i] = 0xf; - tree_cfg->per_pixel_alpha[i] = false; - } - set_output_mux(mpc, tree_cfg->opp_id, 0xf); - tree_cfg->opp_id = 0xf; - tree_cfg->num_pipes = 0; + REG_SET(MUX[mpcc10->opp_id], 0, MPC_OUT_MUX, 0xf); + REG_UPDATE(OPP_PIPE_CONTROL[mpcc10->opp_id], OPP_PIPE_CLOCK_EN, 0); + mpcc10->opp_id = 0xf; } -/* TODO FPGA: how to handle DPP? - * Function to remove one of pipe from MPC configure tree by dpp idx - * Before invoke this function, ensure that master lock of OPTC specified - * by opp_id is set - * This function can be invoke multiple times to remove more than 1 dpps. - * - * tree_cfg[in/out] - current MPC_TREE_CFG - * idx[in] - index of dpp from tree_cfg to be removed. - */ -bool dcn10_remove_dpp(struct dcn10_mpc *mpc, - struct mpc_tree_cfg *tree_cfg, - uint8_t idx) +static void dcn10_mpcc_set(struct mpcc *mpcc, struct mpcc_cfg *cfg) { - int i; - uint8_t mpcc_inst; - bool found = false; - - /* find dpp_idx from dpp array of tree_cfg */ - for (i = 0; i < tree_cfg->num_pipes; i++) { - if (tree_cfg->dpp[i] == idx) { - found = true; - break; - } - } - - if (!found) { - BREAK_TO_DEBUGGER(); - return false; - } - mpcc_inst = tree_cfg->mpcc[i]; - - REG_SET(MPCC_OPP_ID[mpcc_inst], 0, - MPCC_OPP_ID, 0xf); - - REG_SET(MPCC_TOP_SEL[mpcc_inst], 0, - MPCC_TOP_SEL, 0xf); - - REG_SET(MPCC_BOT_SEL[mpcc_inst], 0, - MPCC_BOT_SEL, 0xf); - - if (i == 0) { - if (tree_cfg->num_pipes > 1) - set_output_mux(mpc, - tree_cfg->opp_id, tree_cfg->mpcc[i+1]); + struct dcn10_mpcc *mpcc10 = TO_DCN10_MPCC(mpcc); + int alpha_blnd_mode = cfg->per_pixel_alpha ? + BLND_PP_ALPHA : BLND_GLOBAL_ALPHA; + int mpcc_mode = cfg->bot_mpcc_id != 0xf ? + MODE_BLEND : MODE_TOP_ONLY; + + REG_SET(MPCC_OPP_ID, 0, + MPCC_OPP_ID, cfg->opp_id); + + REG_SET(MPCC_TOP_SEL, 0, + MPCC_TOP_SEL, cfg->top_dpp_id); + + REG_SET(MPCC_BOT_SEL, 0, + MPCC_BOT_SEL, cfg->bot_mpcc_id); + + REG_SET_4(MPCC_CONTROL, 0xffffffff, + MPCC_MODE, mpcc_mode, + MPCC_ALPHA_BLND_MODE, alpha_blnd_mode, + MPCC_ALPHA_MULTIPLIED_MODE, 0/*TODO: cfg->per_pixel_alpha*/, + MPCC_BLND_ACTIVE_OVERLAP_ONLY, cfg->top_of_tree); + + if (cfg->top_of_tree) { + if (cfg->opp_id != 0xf) + set_output_mux(mpcc10, cfg->opp_id, mpcc->inst); else - set_output_mux(mpc, tree_cfg->opp_id, 0xf); - } else if (i == tree_cfg->num_pipes-1) { - mpcc_inst = tree_cfg->mpcc[i - 1]; - - REG_SET(MPCC_BOT_SEL[mpcc_inst], 0, - MPCC_BOT_SEL, 0xF); - - /* prev mpc is now last, set to top only*/ - REG_UPDATE(MPCC_CONTROL[mpcc_inst], - MPCC_MODE, MODE_TOP_ONLY); - } else { - mpcc_inst = tree_cfg->mpcc[i - 1]; - - REG_SET(MPCC_BOT_SEL[mpcc_inst], 0, - MPCC_BOT_SEL, tree_cfg->mpcc[i+1]); + reset_output_mux(mpcc10); } - - /* update tree_cfg structure */ - while (i < tree_cfg->num_pipes - 1) { - tree_cfg->dpp[i] = tree_cfg->dpp[i+1]; - tree_cfg->mpcc[i] = tree_cfg->mpcc[i+1]; - tree_cfg->per_pixel_alpha[i] = tree_cfg->per_pixel_alpha[i+1]; - i++; - } - tree_cfg->num_pipes--; - - return true; } -/* TODO FPGA: how to handle DPP? - * Function to add DPP/MPCC pair into MPC configure tree by position. - * Before invoke this function, ensure that master lock of OPTC specified - * by opp_id is set - * This function can be invoke multiple times to add more than 1 pipes. - * - * tree_cfg[in/out] - current MPC_TREE_CFG - * dpp_idx[in] - index of an idle dpp insatnce to be added. - * mpcc_idx[in] - index of an idle mpcc instance to be added. - * poistion[in] - position of dpp/mpcc pair to be added into current tree_cfg - * 0 means insert to the most top layer of MPC tree - */ -void dcn10_add_dpp(struct dcn10_mpc *mpc, - struct mpc_tree_cfg *tree_cfg, - uint8_t dpp_idx, - uint8_t mpcc_idx, - uint8_t per_pixel_alpha, - uint8_t position) +static void dcn10_mpcc_wait_idle(struct mpcc *mpcc) { - uint8_t prev; - uint8_t next; - - REG_SET(MPCC_OPP_ID[mpcc_idx], 0, - MPCC_OPP_ID, tree_cfg->opp_id); - REG_SET(MPCC_TOP_SEL[mpcc_idx], 0, - MPCC_TOP_SEL, dpp_idx); - - if (position == 0) { - /* idle dpp/mpcc is added to the top layer of tree */ - REG_SET(MPCC_BOT_SEL[mpcc_idx], 0, - MPCC_BOT_SEL, tree_cfg->mpcc[0]); + struct dcn10_mpcc *mpcc10 = TO_DCN10_MPCC(mpcc); - /* bottom mpc is always top only */ - REG_UPDATE(MPCC_CONTROL[mpcc_idx], - MPCC_MODE, MODE_TOP_ONLY); - /* opp will get new output. from new added mpcc */ - set_output_mux(mpc, tree_cfg->opp_id, mpcc_idx); - - } else if (position == tree_cfg->num_pipes) { - /* idle dpp/mpcc is added to the bottom layer of tree */ - - /* get instance of previous bottom mpcc, set to middle layer */ - prev = tree_cfg->mpcc[position - 1]; - - REG_SET(MPCC_BOT_SEL[prev], 0, - MPCC_BOT_SEL, mpcc_idx); - - /* all mpcs other than bottom need to blend */ - REG_UPDATE(MPCC_CONTROL[prev], - MPCC_MODE, MODE_BLEND); - - /* mpcc_idx become new bottom mpcc*/ - REG_SET(MPCC_BOT_SEL[mpcc_idx], 0, - MPCC_BOT_SEL, 0xf); - - /* bottom mpc is always top only */ - REG_UPDATE(MPCC_CONTROL[mpcc_idx], - MPCC_MODE, MODE_TOP_ONLY); - } else { - /* idle dpp/mpcc is added to middle of tree */ - prev = tree_cfg->mpcc[position - 1]; /* mpc a */ - next = tree_cfg->mpcc[position]; /* mpc b */ - - /* connect mpc inserted below mpc a*/ - REG_SET(MPCC_BOT_SEL[prev], 0, - MPCC_BOT_SEL, mpcc_idx); + REG_WAIT(MPCC_STATUS, MPCC_IDLE, 1, 1000, 1000); +} - /* blend on mpc being inserted */ - REG_UPDATE(MPCC_CONTROL[mpcc_idx], - MPCC_MODE, MODE_BLEND); - /* Connect mpc b below one inserted */ - REG_SET(MPCC_BOT_SEL[mpcc_idx], 0, - MPCC_BOT_SEL, next); +const struct mpcc_funcs dcn10_mpcc_funcs = { + .set = dcn10_mpcc_set, + .wait_for_idle = dcn10_mpcc_wait_idle, + .set_bg_color = dcn10_mpcc_set_bg_color, +}; - } - /* premultiplied mode only if alpha is on for the layer*/ - REG_UPDATE_2(MPCC_CONTROL[mpcc_idx], - MPCC_ALPHA_BLND_MODE, - tree_cfg->per_pixel_alpha[position] ? 0 : 2, - MPCC_ALPHA_MULTIPLIED_MODE, 0); +void dcn10_mpcc_construct(struct dcn10_mpcc *mpcc10, + struct dc_context *ctx, + const struct dcn_mpcc_registers *mpcc_regs, + const struct dcn_mpcc_shift *mpcc_shift, + const struct dcn_mpcc_mask *mpcc_mask, + int inst) +{ + mpcc10->base.ctx = ctx; - /* - * iterating from the last mpc/dpp pair to the one being added, shift - * them down one position - */ - for (next = tree_cfg->num_pipes; next > position; next--) { - tree_cfg->dpp[next] = tree_cfg->dpp[next - 1]; - tree_cfg->mpcc[next] = tree_cfg->mpcc[next - 1]; - tree_cfg->per_pixel_alpha[next] = tree_cfg->per_pixel_alpha[next - 1]; - } + mpcc10->base.inst = inst; + mpcc10->base.funcs = &dcn10_mpcc_funcs; - /* insert the new mpc/dpp pair into the tree_cfg*/ - tree_cfg->dpp[position] = dpp_idx; - tree_cfg->mpcc[position] = mpcc_idx; - tree_cfg->per_pixel_alpha[position] = per_pixel_alpha; - tree_cfg->num_pipes++; -} + mpcc10->mpcc_regs = mpcc_regs; + mpcc10->mpcc_shift = mpcc_shift; + mpcc10->mpcc_mask = mpcc_mask; -void wait_mpcc_idle(struct dcn10_mpc *mpc, - uint8_t mpcc_id) -{ - REG_WAIT(MPCC_STATUS[mpcc_id], - MPCC_IDLE, 1, - 1000, 1000); + mpcc10->opp_id = inst; } - diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h index 3e4eb655e913..0f9f1b97d238 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h @@ -22,45 +22,45 @@ * */ -#ifndef __DC_MPC_DCN10_H__ -#define __DC_MPC_DCN10_H__ +#ifndef __DC_MPCC_DCN10_H__ +#define __DC_MPCC_DCN10_H__ #include "mpc.h" -#define TO_DCN10_MPC(mpc_base)\ - container_of(mpc_base, struct dcn10_mpc, base) +#define TO_DCN10_MPCC(mpcc_base) \ + container_of(mpcc_base, struct dcn10_mpcc, base) -#define MAX_MPCC 4 -#define MAX_MPC_OUT 4 #define MAX_OPP 4 #define MPC_COMMON_REG_LIST_DCN1_0(inst) \ - SRII(MPCC_TOP_SEL, MPCC, inst),\ - SRII(MPCC_BOT_SEL, MPCC, inst),\ - SRII(MPCC_CONTROL, MPCC, inst),\ - SRII(MPCC_STATUS, MPCC, inst),\ - SRII(MPCC_OPP_ID, MPCC, inst),\ - SRII(MPCC_BG_G_Y, MPCC, inst),\ - SRII(MPCC_BG_R_CR, MPCC, inst),\ - SRII(MPCC_BG_B_CB, MPCC, inst),\ - SRII(MPCC_BG_B_CB, MPCC, inst),\ SRII(MUX, MPC_OUT, inst),\ SRII(OPP_PIPE_CONTROL, OPP_PIPE, inst) -struct dcn_mpc_registers { - uint32_t MPCC_TOP_SEL[MAX_MPCC]; - uint32_t MPCC_BOT_SEL[MAX_MPCC]; - uint32_t MPCC_CONTROL[MAX_MPCC]; - uint32_t MPCC_STATUS[MAX_MPCC]; - uint32_t MPCC_OPP_ID[MAX_MPCC]; - uint32_t MPCC_BG_G_Y[MAX_MPCC]; - uint32_t MPCC_BG_R_CR[MAX_MPCC]; - uint32_t MPCC_BG_B_CB[MAX_MPCC]; - uint32_t MUX[MAX_MPC_OUT]; +#define MPCC_COMMON_REG_LIST_DCN1_0(inst) \ + SRI(MPCC_TOP_SEL, MPCC, inst),\ + SRI(MPCC_BOT_SEL, MPCC, inst),\ + SRI(MPCC_CONTROL, MPCC, inst),\ + SRI(MPCC_STATUS, MPCC, inst),\ + SRI(MPCC_OPP_ID, MPCC, inst),\ + SRI(MPCC_BG_G_Y, MPCC, inst),\ + SRI(MPCC_BG_R_CR, MPCC, inst),\ + SRI(MPCC_BG_B_CB, MPCC, inst),\ + SRI(MPCC_BG_B_CB, MPCC, inst) + +struct dcn_mpcc_registers { + uint32_t MPCC_TOP_SEL; + uint32_t MPCC_BOT_SEL; + uint32_t MPCC_CONTROL; + uint32_t MPCC_STATUS; + uint32_t MPCC_OPP_ID; + uint32_t MPCC_BG_G_Y; + uint32_t MPCC_BG_R_CR; + uint32_t MPCC_BG_B_CB; uint32_t OPP_PIPE_CONTROL[MAX_OPP]; + uint32_t MUX[MAX_OPP]; }; -#define MPC_COMMON_MASK_SH_LIST_DCN1_0(mask_sh)\ +#define MPCC_COMMON_MASK_SH_LIST_DCN1_0(mask_sh)\ SF(MPCC0_MPCC_TOP_SEL, MPCC_TOP_SEL, mask_sh),\ SF(MPCC0_MPCC_BOT_SEL, MPCC_BOT_SEL, mask_sh),\ SF(MPCC0_MPCC_CONTROL, MPCC_MODE, mask_sh),\ @@ -75,7 +75,7 @@ struct dcn_mpc_registers { SF(MPC_OUT0_MUX, MPC_OUT_MUX, mask_sh),\ SF(OPP_PIPE0_OPP_PIPE_CONTROL, OPP_PIPE_CLOCK_EN, mask_sh) -#define MPC_REG_FIELD_LIST(type) \ +#define MPCC_REG_FIELD_LIST(type) \ type MPCC_TOP_SEL;\ type MPCC_BOT_SEL;\ type MPCC_MODE;\ @@ -90,42 +90,28 @@ struct dcn_mpc_registers { type MPC_OUT_MUX;\ type OPP_PIPE_CLOCK_EN;\ -struct dcn_mpc_shift { - MPC_REG_FIELD_LIST(uint8_t) +struct dcn_mpcc_shift { + MPCC_REG_FIELD_LIST(uint8_t) }; -struct dcn_mpc_mask { - MPC_REG_FIELD_LIST(uint32_t) +struct dcn_mpcc_mask { + MPCC_REG_FIELD_LIST(uint32_t) }; -struct dcn10_mpc { - struct mpc base; - const struct dcn_mpc_registers *mpc_regs; - const struct dcn_mpc_shift *mpc_shift; - const struct dcn_mpc_mask *mpc_mask; -}; - -void dcn10_delete_mpc_tree(struct dcn10_mpc *mpc, - struct mpc_tree_cfg *tree_cfg); - -bool dcn10_remove_dpp(struct dcn10_mpc *mpc, - struct mpc_tree_cfg *tree_cfg, - uint8_t idx); +struct dcn10_mpcc { + struct mpcc base; + const struct dcn_mpcc_registers *mpcc_regs; + const struct dcn_mpcc_shift *mpcc_shift; + const struct dcn_mpcc_mask *mpcc_mask; -void dcn10_add_dpp(struct dcn10_mpc *mpc, - struct mpc_tree_cfg *tree_cfg, - uint8_t dpp_idx, - uint8_t mpcc_idx, - uint8_t per_pixel_alpha, - uint8_t position); - -void wait_mpcc_idle(struct dcn10_mpc *mpc, - uint8_t mpcc_id); + int opp_id; +}; -void dcn10_set_mpc_tree(struct dcn10_mpc *mpc, - struct mpc_tree_cfg *tree_cfg); +void dcn10_mpcc_construct(struct dcn10_mpcc *mpcc10, + struct dc_context *ctx, + const struct dcn_mpcc_registers *mpcc_regs, + const struct dcn_mpcc_shift *mpcc_shift, + const struct dcn_mpcc_mask *mpcc_mask, + int inst); -void dcn10_set_mpc_background_color(struct dcn10_mpc *mpc, - unsigned int mpcc_inst, - struct tg_color *bg_color); #endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 6ada9a262721..142ac0613d5b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -336,19 +336,28 @@ static const struct dcn_transform_mask tf_mask = { }; -static const struct dcn_mpc_registers mpc_regs = { - MPC_COMMON_REG_LIST_DCN1_0(0), - MPC_COMMON_REG_LIST_DCN1_0(1), - MPC_COMMON_REG_LIST_DCN1_0(2), - MPC_COMMON_REG_LIST_DCN1_0(3), +#define mpcc_regs(id)\ +[id] = {\ + MPCC_COMMON_REG_LIST_DCN1_0(id),\ + MPC_COMMON_REG_LIST_DCN1_0(0),\ + MPC_COMMON_REG_LIST_DCN1_0(1),\ + MPC_COMMON_REG_LIST_DCN1_0(2),\ + MPC_COMMON_REG_LIST_DCN1_0(3),\ +} + +static const struct dcn_mpcc_registers mpcc_regs[] = { + mpcc_regs(0), + mpcc_regs(1), + mpcc_regs(2), + mpcc_regs(3), }; -static const struct dcn_mpc_shift mpc_shift = { - MPC_COMMON_MASK_SH_LIST_DCN1_0(__SHIFT) +static const struct dcn_mpcc_shift mpcc_shift = { + MPCC_COMMON_MASK_SH_LIST_DCN1_0(__SHIFT) }; -static const struct dcn_mpc_mask mpc_mask = { - MPC_COMMON_MASK_SH_LIST_DCN1_0(_MASK), +static const struct dcn_mpcc_mask mpcc_mask = { + MPCC_COMMON_MASK_SH_LIST_DCN1_0(_MASK), }; #define tg_regs(id)\ @@ -509,28 +518,22 @@ static struct output_pixel_processor *dcn10_opp_create( return &opp->base; } -static struct mpc *dcn10_mpc_create( - struct dc_context *ctx) +static struct mpcc *dcn10_mpcc_create( + struct dc_context *ctx, + int inst) { - struct dcn10_mpc *mpc = dm_alloc(sizeof(struct dcn10_mpc)); + struct dcn10_mpcc *mpcc10 = dm_alloc(sizeof(struct dcn10_mpcc)); - if (!mpc) + if (!mpcc10) return NULL; - mpc->base.ctx = ctx; - mpc->mpc_regs = &mpc_regs; - mpc->mpc_shift = &mpc_shift; - mpc->mpc_mask = &mpc_mask; + dcn10_mpcc_construct(mpcc10, ctx, + &mpcc_regs[inst], + &mpcc_shift, + &mpcc_mask, + inst); - return &mpc->base; -} - -static void dcn10_mpc_destroy(struct mpc **mpc_base) -{ - if (*mpc_base) - dm_free(TO_DCN10_MPC(*mpc_base)); - - *mpc_base = NULL; + return &mpcc10->base; } static struct timing_generator *dcn10_timing_generator_create( @@ -736,6 +739,11 @@ static void destruct(struct dcn10_resource_pool *pool) dm_free(DCN10TG_FROM_TG(pool->base.timing_generators[i])); pool->base.timing_generators[i] = NULL; } + + if (pool->base.mpcc[i] != NULL) { + dm_free(TO_DCN10_MPCC(pool->base.mpcc[i])); + pool->base.mpcc[i] = NULL; + } } for (i = 0; i < pool->base.stream_enc_count; i++) { @@ -760,9 +768,6 @@ static void destruct(struct dcn10_resource_pool *pool) pool->base.dp_clock_source = NULL; } - if (pool->base.mpc != NULL) - dcn10_mpc_destroy(&pool->base.mpc); - if (pool->base.abm != NULL) dce_abm_destroy(&pool->base.abm); @@ -1007,6 +1012,7 @@ static struct pipe_ctx *dcn10_acquire_idle_pipe_for_layer( idle_pipe->stream = head_pipe->stream; idle_pipe->tg = head_pipe->tg; + idle_pipe->mpcc = pool->mpcc[idle_pipe->pipe_idx]; idle_pipe->mi = pool->mis[idle_pipe->pipe_idx]; idle_pipe->ipp = pool->ipps[idle_pipe->pipe_idx]; idle_pipe->xfm = pool->transforms[idle_pipe->pipe_idx]; @@ -1427,10 +1433,14 @@ static bool construct( dm_error("DC: failed to create tg!\n"); goto otg_create_fail; } + pool->base.mpcc[i] = dcn10_mpcc_create(ctx, i); + if (pool->base.mpcc[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create mpcc!\n"); + goto mpcc_create_fail; + } } - pool->base.mpc = dcn10_mpc_create(ctx); - if (!resource_construct(num_virtual_links, dc, &pool->base, (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) ? &res_create_funcs : &res_create_maximus_funcs))) @@ -1444,6 +1454,7 @@ static bool construct( return true; disp_clk_create_fail: +mpcc_create_fail: otg_create_fail: opp_create_fail: transform_create_fail: diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index d8a378dabb43..030841889803 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -236,6 +236,9 @@ struct resource_pool { struct output_pixel_processor *opps[MAX_PIPES]; struct timing_generator *timing_generators[MAX_PIPES]; struct stream_encoder *stream_enc[MAX_PIPES * 2]; +#ifdef CONFIG_DRM_AMD_DC_DCN1_0 + struct mpcc *mpcc[MAX_PIPES]; +#endif unsigned int pipe_count; unsigned int underlay_pipe_index; @@ -259,9 +262,6 @@ struct resource_pool { struct abm *abm; struct dmcu *dmcu; -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) - struct mpc *mpc; -#endif const struct resource_funcs *funcs; const struct resource_caps *res_cap; @@ -295,8 +295,9 @@ struct pipe_ctx { struct pipe_ctx *top_pipe; struct pipe_ctx *bottom_pipe; + #ifdef CONFIG_DRM_AMD_DC_DCN1_0 - uint8_t mpc_idx; + struct mpcc *mpcc; struct _vcs_dpi_display_dlg_regs_st dlg_regs; struct _vcs_dpi_display_ttu_regs_st ttu_regs; struct _vcs_dpi_display_rq_regs_st rq_regs; @@ -306,9 +307,6 @@ struct pipe_ctx { struct resource_context { struct pipe_ctx pipe_ctx[MAX_PIPES]; -#ifdef CONFIG_DRM_AMD_DC_DCN1_0 - struct mpc_tree_cfg mpc_tree[MAX_PIPES]; -#endif bool is_stream_enc_acquired[MAX_PIPES * 2]; bool is_audio_acquired[MAX_PIPES]; uint8_t clock_source_ref_count[MAX_CLOCK_SOURCES]; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h index ec1a201747f2..38d158746cc5 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h @@ -22,76 +22,29 @@ * */ -#ifndef __DC_MPC_H__ -#define __DC_MPC_H__ +#ifndef __DC_MPCC_H__ +#define __DC_MPCC_H__ -/* This structure define the mpc tree configuration - * num_pipes - number of pipes of the tree - * opp_id - instance id of OPP to drive MPC - * dpp- array of DPP index - * mpcc - array of MPCC index - * mode - the most bottom layer MPCC mode control. - * All other layers need to be program to 3 - * - * The connection will be: - * mpcc[num_pipes-1]->mpcc[num_pipes-2]->...->mpcc[1]->mpcc[0]->OPP[opp_id] - * dpp[0]->mpcc[0] - * dpp[1]->mpcc[1] - * ... - * dpp[num_pipes-1]->mpcc[num_pipes-1] - * mpcc[0] is the most top layer of MPC tree, - * mpcc[num_pipes-1] is the most bottom layer. - */ - -struct mpc_tree_cfg { - uint8_t num_pipes; - uint8_t opp_id; - /* dpp pipes for blend */ - uint8_t dpp[6]; - /* mpcc insatnces for blend */ - uint8_t mpcc[6]; - bool per_pixel_alpha[6]; -}; +#include "dc_hw_types.h" -struct mpcc_blnd_cfg { - /* 0- perpixel alpha, 1- perpixel alpha combined with global gain, - * 2- global alpha - */ - uint8_t alpha_mode; - uint8_t global_gain; - uint8_t global_alpha; - bool overlap_only; - bool pre_multiplied_alpha; +struct mpcc_cfg { + int top_dpp_id; + int bot_mpcc_id; + int opp_id; + bool per_pixel_alpha; + bool top_of_tree; }; -struct mpcc_sm_cfg { - bool enable; - /* 0-single plane, 2-row subsampling, 4-column subsampling, - * 6-checkboard subsampling - */ - uint8_t sm_mode; - bool frame_alt; /* 0- disable, 1- enable */ - bool field_alt; /* 0- disable, 1- enable */ - /* 0-no force, 2-force frame polarity from top, - * 3-force frame polarity from bottom - */ - uint8_t force_next_frame_porlarity; - /* 0-no force, 2-force field polarity from top, - * 3-force field polarity from bottom - */ - uint8_t force_next_field_polarity; -}; - -struct mpcc_vupdate_lock_cfg { - bool cfg_lock; - bool adr_lock; - bool adr_cfg_lock; - bool cur0_lock; - bool cur1_lock; +struct mpcc { + const struct mpcc_funcs *funcs; + struct dc_context *ctx; + int inst; }; -struct mpc { - struct dc_context *ctx; +struct mpcc_funcs { + void (*set)(struct mpcc *mpcc, struct mpcc_cfg *cfg); + void (*wait_for_idle)(struct mpcc *mpcc); + void (*set_bg_color)( struct mpcc *mpcc, struct tg_color *bg_color); }; #endif -- cgit From ad32734699da4dd185405637459bf915a4f4cff6 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Mon, 5 Jun 2017 15:08:10 -0400 Subject: drm/amd/display: w/a for ycbcr output pre-multiplied alpha corruption Signed-off-by: Dmytro Laktyushkin Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 28 ++++++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c | 2 +- drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h | 1 + 3 files changed, 30 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index f509dfd97f23..f41230013309 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1658,6 +1658,28 @@ static bool is_pipe_tree_visible(struct pipe_ctx *pipe_ctx) return false; } +static bool is_rgb_cspace(enum dc_color_space output_color_space) +{ + switch (output_color_space) { + case COLOR_SPACE_SRGB: + case COLOR_SPACE_SRGB_LIMITED: + case COLOR_SPACE_2020_RGB_FULLRANGE: + case COLOR_SPACE_2020_RGB_LIMITEDRANGE: + case COLOR_SPACE_ADOBERGB: + return true; + case COLOR_SPACE_YCBCR601: + case COLOR_SPACE_YCBCR709: + case COLOR_SPACE_YCBCR601_LIMITED: + case COLOR_SPACE_YCBCR709_LIMITED: + case COLOR_SPACE_2020_YCBCR: + return false; + default: + /* Add a case to switch */ + BREAK_TO_DEBUGGER(); + return false; + } +} + static void update_dchubp_dpp( struct core_dc *dc, struct pipe_ctx *pipe_ctx, @@ -1719,6 +1741,12 @@ static void update_dchubp_dpp( mpcc_cfg.bot_mpcc_id = 0xf; mpcc_cfg.top_of_tree = !pipe_ctx->top_pipe; mpcc_cfg.per_pixel_alpha = per_pixel_alpha; + /* DCN1.0 has output CM before MPC which seems to screw with + * pre-multiplied alpha. + */ + mpcc_cfg.pre_multiplied_alpha = is_rgb_cspace( + pipe_ctx->stream->public.output_color_space) + && per_pixel_alpha; if (!dc->current_context->res_ctx.pipe_ctx[pipe_ctx->pipe_idx].surface) pipe_ctx->mpcc->funcs->wait_for_idle(pipe_ctx->mpcc); pipe_ctx->mpcc->funcs->set(pipe_ctx->mpcc, &mpcc_cfg); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c index 19af0ee86191..b1c590d4f454 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c @@ -98,7 +98,7 @@ static void dcn10_mpcc_set(struct mpcc *mpcc, struct mpcc_cfg *cfg) REG_SET_4(MPCC_CONTROL, 0xffffffff, MPCC_MODE, mpcc_mode, MPCC_ALPHA_BLND_MODE, alpha_blnd_mode, - MPCC_ALPHA_MULTIPLIED_MODE, 0/*TODO: cfg->per_pixel_alpha*/, + MPCC_ALPHA_MULTIPLIED_MODE, cfg->pre_multiplied_alpha, MPCC_BLND_ACTIVE_OVERLAP_ONLY, cfg->top_of_tree); if (cfg->top_of_tree) { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h index 38d158746cc5..51bc8ef5ef79 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h @@ -32,6 +32,7 @@ struct mpcc_cfg { int bot_mpcc_id; int opp_id; bool per_pixel_alpha; + bool pre_multiplied_alpha; bool top_of_tree; }; -- cgit From 561f3a4db315d639b93adf86eedbb8405dd81fbe Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Mon, 29 May 2017 18:30:17 -0400 Subject: drm/amd/display: enable pipe split Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 142ac0613d5b..a2276803c0d0 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -443,7 +443,7 @@ static const struct dc_debug debug_defaults_drv = { .disable_pplib_wm_range = false, #if defined(CONFIG_DRM_AMD_DC_DCN1_0) .use_dml_wm = false, - .use_max_voltage = true + .use_max_voltage = false #endif }; -- cgit From aed8b319180f18402ed90929f85e2b3e5b81e71d Mon Sep 17 00:00:00 2001 From: Shirish S Date: Thu, 8 Jun 2017 11:55:06 +0530 Subject: drm/amd/display: remove get_position() of underlay get_position() returns CRTC vertical/horizontal counters, hence it is not applicable for underlay which is plane and not attached to one crtc. This patch hence removes the callback from dce110_tg_v_funcs and hence fixes a bug in dc_debug.c where in get_position() for underlay pipe is called un-conditionally. Witout this patch get_position() is called in case one has to update underlay plane's data, since callback implmented with an ASSERT(), the old_surface_count and new_surface_count mismatches; causing only one plane update which is not right and also assert makes the rendering slow. Signed-off-by: Shirish S Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_debug.c | 9 +++++++-- .../gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c | 9 +-------- 2 files changed, 8 insertions(+), 10 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c index ad556e9b0754..9a5df3a848b5 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c @@ -297,11 +297,16 @@ void context_timing_trace( struct dal_logger *logger = core_dc->ctx->logger; int h_pos[MAX_PIPES], v_pos[MAX_PIPES]; struct crtc_position position; + unsigned int underlay_idx = core_dc->res_pool->underlay_pipe_index; + for (i = 0; i < core_dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; - - if (pipe_ctx->stream == NULL) + /* get_position() returns CRTC vertical/horizontal counter + * hence not applicable for underlay pipe + */ + if (pipe_ctx->stream == NULL + || pipe_ctx->pipe_idx == underlay_idx) continue; pipe_ctx->tg->funcs->get_position(pipe_ctx->tg, &position); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c index 759c55bb4d15..93ca6ae48cb9 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c @@ -570,13 +570,6 @@ static void dce110_timing_generator_v_set_early_control( dm_write_reg(tg->ctx, address, regval); } -static void dce110_timing_generator_get_underlay_position(struct timing_generator *tg, - struct crtc_position *position) -{ - //Should never hit this case - ASSERT(false); -} - static uint32_t dce110_timing_generator_v_get_vblank_counter(struct timing_generator *tg) { uint32_t addr = mmCRTCV_STATUS_FRAME_COUNT; @@ -652,7 +645,7 @@ static const struct timing_generator_funcs dce110_tg_v_funcs = { .enable_crtc = dce110_timing_generator_v_enable_crtc, .disable_crtc = dce110_timing_generator_v_disable_crtc, .is_counter_moving = dce110_timing_generator_v_is_counter_moving, - .get_position = dce110_timing_generator_get_underlay_position, + .get_position = NULL, /* Not to be implemented for underlay*/ .get_frame_count = dce110_timing_generator_v_get_vblank_counter, .set_early_control = dce110_timing_generator_v_set_early_control, .wait_for_state = dce110_timing_generator_v_wait_for_state, -- cgit From 7f5c22d1652327b64375e88b184b0df502c7bdc7 Mon Sep 17 00:00:00 2001 From: Vitaly Prosyak Date: Thu, 8 Jun 2017 15:55:02 -0500 Subject: drm/amd/display: RV stereo support HDMI frame pack and DP frame alternate in band Signed-off-by: Vitaly Prosyak Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 4 +- drivers/gpu/drm/amd/display/dc/core/dc.c | 25 ++++++++ drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 14 ++--- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 6 ++ .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 69 +++++++++++++++++++++- .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 4 -- .../amd/display/dc/dcn10/dcn10_timing_generator.c | 2 - 7 files changed, 105 insertions(+), 19 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 66f0595a4c20..2b62efce73c5 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -972,9 +972,7 @@ bool dcn_validate_bandwidth( if (pipe->surface) { struct pipe_ctx *hsplit_pipe = pipe->bottom_pipe; - if (v->dpp_per_plane[input_idx] == 2 || - (pipe->stream->public.timing.timing_3d_format == TIMING_3D_FORMAT_TOP_AND_BOTTOM || - pipe->stream->public.timing.timing_3d_format == TIMING_3D_FORMAT_SIDE_BY_SIDE)) { + if (v->dpp_per_plane[input_idx] == 2) { if (hsplit_pipe && hsplit_pipe->surface == pipe->surface) { /* update previously split pipe */ hsplit_pipe->pipe_dlg_param.vupdate_width = v->v_update_width[input_idx]; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 47870a640f37..e518aeddfa58 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -832,6 +832,30 @@ static bool streams_changed( return false; } +bool dc_enable_stereo( + struct dc *dc, + struct validate_context *context, + const struct dc_stream *streams[], + uint8_t stream_count) +{ + bool ret = true; + int i, j; + struct pipe_ctx *pipe; + struct core_dc *core_dc = DC_TO_CORE(dc); + for (i = 0; i < MAX_PIPES; i++) { + if (context != NULL) + pipe = &context->res_ctx.pipe_ctx[i]; + else + pipe = &core_dc->current_context->res_ctx.pipe_ctx[i]; + for (j = 0 ; pipe && j < stream_count; j++) { + if (streams[j] && streams[j] == &pipe->stream->public && + core_dc->hwss.setup_stereo) + core_dc->hwss.setup_stereo(pipe, core_dc); + } + } + return ret; +} + bool dc_commit_streams( struct dc *dc, const struct dc_stream *streams[], @@ -903,6 +927,7 @@ bool dc_commit_streams( DC_SURFACE_TO_CORE(context->stream_status[i].surfaces[j]); core_dc->hwss.apply_ctx_for_surface(core_dc, surface, context); + dc_enable_stereo(dc, context, streams, stream_count); } CONN_MSG_MODE(sink->link, "{%dx%d, %dx%d@%dKhz}", diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index c51ec617eff7..90eb839f5414 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -440,8 +440,8 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) bool sec_split = pipe_ctx->top_pipe && pipe_ctx->top_pipe->surface == pipe_ctx->surface; - if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_SIDE_BY_SIDE || - stream->timing.timing_3d_format == TIMING_3D_FORMAT_TOP_AND_BOTTOM) { + if (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE || + stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) { pri_split = false; sec_split = false; } @@ -568,8 +568,7 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip /* Handle h & vsplit */ if (pipe_ctx->top_pipe && pipe_ctx->top_pipe->surface == pipe_ctx->surface) { - if (stream->public.timing.timing_3d_format == - TIMING_3D_FORMAT_TOP_AND_BOTTOM) { + if (stream->public.view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) { pipe_ctx->scl_data.recout.height /= 2; pipe_ctx->scl_data.recout.y += pipe_ctx->scl_data.recout.height; /* Floor primary pipe, ceil 2ndary pipe */ @@ -581,8 +580,7 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip } } else if (pipe_ctx->bottom_pipe && pipe_ctx->bottom_pipe->surface == pipe_ctx->surface) { - if (stream->public.timing.timing_3d_format == - TIMING_3D_FORMAT_TOP_AND_BOTTOM) + if (stream->public.view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) pipe_ctx->scl_data.recout.height /= 2; else pipe_ctx->scl_data.recout.width /= 2; @@ -626,7 +624,7 @@ static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) surf_src.height, surface->dst_rect.height); - if (surface->stereo_format == PLANE_STEREO_FORMAT_SIDE_BY_SIDE) + if (stream->public.view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE) pipe_ctx->scl_data.ratios.horz.value *= 2; else if (surface->stereo_format == PLANE_STEREO_FORMAT_TOP_AND_BOTTOM) pipe_ctx->scl_data.ratios.vert.value *= 2; @@ -1772,6 +1770,8 @@ static void set_vendor_info_packet( enum dc_timing_3d_format format; format = stream->public.timing.timing_3d_format; + if (stream->public.view_format == VIEW_3D_FORMAT_NONE) + format = TIMING_3D_FORMAT_NONE; /* Can be different depending on packet content */ length = 5; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 616533e25534..ac99d283bf0a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -2057,6 +2057,11 @@ void dce110_update_pending_status(struct pipe_ctx *pipe_ctx) pipe_ctx->mi->current_address = pipe_ctx->mi->request_address; surface->status.current_address = pipe_ctx->mi->current_address; + if (pipe_ctx->mi->current_address.type == PLN_ADDR_TYPE_GRPH_STEREO && + pipe_ctx->tg->funcs->is_stereo_left_eye) { + surface->status.is_right_eye =\ + !pipe_ctx->tg->funcs->is_stereo_left_eye(pipe_ctx->tg); + } } void dce110_power_down(struct core_dc *dc) @@ -2576,6 +2581,7 @@ static const struct hw_sequencer_funcs dce110_funcs = { .set_static_screen_control = set_static_screen_control, .reset_hw_ctx_wrap = reset_hw_ctx_wrap, .prog_pixclk_crtc_otg = dce110_prog_pixclk_crtc_otg, + .setup_stereo = NULL }; bool dce110_hw_sequencer_construct(struct core_dc *dc) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index f41230013309..edcd7369cf9d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -896,8 +896,9 @@ static void reset_hw_ctx_wrap( reset_hw_ctx(dc, context, reset_back_end_for_pipe); } -static bool patch_address_for_sbs_tb_stereo( - struct pipe_ctx *pipe_ctx, PHYSICAL_ADDRESS_LOC *addr) + +static bool patch_address_for_sbs_tb_stereo(struct pipe_ctx *pipe_ctx, + PHYSICAL_ADDRESS_LOC *addr) { struct core_surface *surface = pipe_ctx->surface; bool sec_split = pipe_ctx->top_pipe && @@ -912,6 +913,7 @@ static bool patch_address_for_sbs_tb_stereo( surface->public.address.grph_stereo.right_addr; return true; } + return false; } @@ -2061,6 +2063,66 @@ static void set_plane_config( program_gamut_remap(pipe_ctx); } +static void dcn10_config_stereo_parameters(struct core_stream *stream,\ + struct crtc_stereo_flags *flags) +{ + enum view_3d_format view_format = stream->public.view_format; + enum dc_timing_3d_format timing_3d_format =\ + stream->public.timing.timing_3d_format; + bool non_stereo_timing = false; + + if (timing_3d_format == TIMING_3D_FORMAT_NONE || + timing_3d_format == TIMING_3D_FORMAT_SIDE_BY_SIDE || + timing_3d_format == TIMING_3D_FORMAT_TOP_AND_BOTTOM) + non_stereo_timing = true; + + if (non_stereo_timing == false && + view_format == VIEW_3D_FORMAT_FRAME_SEQUENTIAL) { + + flags->PROGRAM_STEREO = 1; + flags->PROGRAM_POLARITY = 1; + if (timing_3d_format == TIMING_3D_FORMAT_INBAND_FA || + timing_3d_format == TIMING_3D_FORMAT_DP_HDMI_INBAND_FA || + timing_3d_format == TIMING_3D_FORMAT_SIDEBAND_FA) { + enum display_dongle_type dongle = \ + stream->sink->link->public.ddc->dongle_type; + if (dongle == DISPLAY_DONGLE_DP_VGA_CONVERTER || + dongle == DISPLAY_DONGLE_DP_DVI_CONVERTER || + dongle == DISPLAY_DONGLE_DP_HDMI_CONVERTER) + flags->DISABLE_STEREO_DP_SYNC = 1; + } + flags->RIGHT_EYE_POLARITY =\ + stream->public.timing.flags.RIGHT_EYE_3D_POLARITY; + if (timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING) + flags->FRAME_PACKED = 1; + } + + return; +} + +static void dcn10_setup_stereo(struct pipe_ctx *pipe_ctx, + struct core_dc *dc) +{ + struct crtc_stereo_flags flags = { 0 }; + struct core_stream *stream = pipe_ctx->stream; + + dcn10_config_stereo_parameters(stream, &flags); + + pipe_ctx->opp->funcs->opp_set_stereo_polarity( + pipe_ctx->opp, + flags.PROGRAM_STEREO == 1 ? true:false, + stream->public.timing.flags.RIGHT_EYE_3D_POLARITY == 1 ? true:false); + + pipe_ctx->tg->funcs->program_stereo( + pipe_ctx->tg, + &stream->public.timing, + &flags); + + + + return; +} + static const struct hw_sequencer_funcs dcn10_funcs = { .program_gamut_remap = program_gamut_remap, .init_hw = init_hw, @@ -2088,7 +2150,8 @@ static const struct hw_sequencer_funcs dcn10_funcs = { .prog_pixclk_crtc_otg = dcn10_prog_pixclk_crtc_otg, .set_drr = set_drr, .get_position = get_position, - .set_static_screen_control = set_static_screen_control + .set_static_screen_control = set_static_screen_control, + .setup_stereo = dcn10_setup_stereo }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index a2276803c0d0..77fc251d45ba 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -821,10 +821,6 @@ static void get_pixel_clock_parameters( if (stream->public.timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) pixel_clk_params->requested_pix_clk /= 2; - if (stream->public.timing. timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING || - stream->public.timing. timing_3d_format == TIMING_3D_FORMAT_SW_FRAME_PACKING || - stream->public.timing. timing_3d_format == TIMING_3D_FORMAT_DP_HDMI_INBAND_FA) - pixel_clk_params->requested_pix_clk *= 2; } static void build_clamping_params(struct core_stream *stream) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c index bc3934d75b46..83efbec77357 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c @@ -271,8 +271,6 @@ static void tg_program_timing_generator( REG_UPDATE(OTG_H_TIMING_CNTL, OTG_H_TIMING_DIV_BY2, h_div_2); - dcn10_disable_stereo( tg); - } /** tg_program_blanking -- cgit From 3f6d743598ef24002f0babd3aa06c7fe104b7dc5 Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Fri, 9 Jun 2017 11:32:06 -0400 Subject: drm/amd/display: DAL3 RV get DPREFCLK SpreadspectrumInfo from smu_info Signed-off-by: Hersen Wu Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c | 14 ++++++++--- drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c | 29 +++++++++++++++++++++- 2 files changed, 39 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c index fcd3b72287c8..3a69f9c5d20a 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -1136,6 +1136,7 @@ static enum bp_result get_ss_info_v4_2( { enum bp_result result = BP_RESULT_OK; struct atom_display_controller_info_v4_2 *disp_cntl_tbl = NULL; + struct atom_smu_info_v3_1 *smu_info = NULL; if (!ss_info) return BP_RESULT_BADINPUT; @@ -1143,11 +1144,18 @@ static enum bp_result get_ss_info_v4_2( if (!DATA_TABLES(dce_info)) return BP_RESULT_BADBIOSTABLE; + if (!DATA_TABLES(smu_info)) + return BP_RESULT_BADBIOSTABLE; + disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_2, DATA_TABLES(dce_info)); if (!disp_cntl_tbl) return BP_RESULT_BADBIOSTABLE; + smu_info = GET_IMAGE(struct atom_smu_info_v3_1, DATA_TABLES(smu_info)); + if (!smu_info) + return BP_RESULT_BADBIOSTABLE; + ss_info->type.STEP_AND_DELAY_INFO = false; ss_info->spread_percentage_divider = 1000; /* BIOS no longer uses target clock. Always enable for now */ @@ -1173,10 +1181,10 @@ static enum bp_result get_ss_info_v4_2( /* TODO LVDS not support anymore? */ case AS_SIGNAL_TYPE_DISPLAY_PORT: ss_info->spread_spectrum_percentage = - disp_cntl_tbl->dp_ss_percentage; + smu_info->gpuclk_ss_percentage; ss_info->spread_spectrum_range = - disp_cntl_tbl->dp_ss_rate_10hz * 10; - if (disp_cntl_tbl->dp_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE) + smu_info->gpuclk_ss_rate_10hz * 10; + if (smu_info->gpuclk_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE) ss_info->type.CENTER_MODE = true; break; case AS_SIGNAL_TYPE_GPU_PLL: diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c index 04cd70172cc7..84b0860190d7 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c @@ -246,6 +246,33 @@ static int dce_clocks_get_dp_ref_freq(struct display_clock *clk) return dp_ref_clk_khz; } +/* TODO: This is DCN DPREFCLK: it could be program by DENTIST by VBIOS + * or CLK0_CLK11 by SMU. For DCE120, it is wlays 600Mhz. Will re-visit + * clock implementation + */ +static int dce_clocks_get_dp_ref_freq_wrkaround(struct display_clock *clk) +{ + struct dce_disp_clk *clk_dce = TO_DCE_CLOCKS(clk); + int dp_ref_clk_khz = 600000; + + if (clk_dce->ss_on_dprefclk && clk_dce->dprefclk_ss_divider != 0) { + struct fixed32_32 ss_percentage = dal_fixed32_32_div_int( + dal_fixed32_32_from_fraction( + clk_dce->dprefclk_ss_percentage, + clk_dce->dprefclk_ss_divider), 200); + struct fixed32_32 adj_dp_ref_clk_khz; + + ss_percentage = dal_fixed32_32_sub(dal_fixed32_32_one, + ss_percentage); + adj_dp_ref_clk_khz = + dal_fixed32_32_mul_int( + ss_percentage, + dp_ref_clk_khz); + dp_ref_clk_khz = dal_fixed32_32_floor(adj_dp_ref_clk_khz); + } + + return dp_ref_clk_khz; +} static enum dm_pp_clocks_state dce_get_required_clocks_state( struct display_clock *clk, struct state_dependent_clocks *req_clocks) @@ -605,7 +632,7 @@ static bool dce_apply_clock_voltage_request( static const struct display_clock_funcs dce120_funcs = { - .get_dp_ref_clk_frequency = dce_clocks_get_dp_ref_freq, + .get_dp_ref_clk_frequency = dce_clocks_get_dp_ref_freq_wrkaround, .apply_clock_voltage_request = dce_apply_clock_voltage_request, .set_clock = dce112_set_clock }; -- cgit From 70470154104e935eed36478169550eda577dcdb3 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Sun, 4 Jun 2017 09:11:56 -0400 Subject: drm/amd/display: Get rid of seperate flip function. This code is remanant of pre atomic age when flip was a standalone IOCTL. Signed-off-by: Andrey Grodzovsky Reviewed-by: Tony Cheng Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 97 ---------------------- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 37 ++++++++- 2 files changed, 34 insertions(+), 100 deletions(-) (limited to 'drivers/gpu') 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 6b25a7ba2f7d..df4cccb4be7a 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1328,102 +1328,6 @@ static u8 dm_get_backlight_level(struct amdgpu_encoder *amdgpu_encoder) return 0; } -/****************************************************************************** - * Page Flip functions - ******************************************************************************/ - -/** - * dm_page_flip - called by amdgpu_flip_work_func(), which is triggered - * via DRM IOCTL, by user mode. - * - * @adev: amdgpu_device pointer - * @crtc_id: crtc to cleanup pageflip on - * @crtc_base: new address of the crtc (GPU MC address) - * - * Does the actual pageflip (surface address update). - */ -static void dm_page_flip(struct amdgpu_device *adev, - int crtc_id, u64 crtc_base, bool async) -{ - struct amdgpu_crtc *acrtc; - const struct dc_stream *stream; - struct dc_flip_addrs addr = { {0} }; - struct dc_surface_update surface_updates[1] = { {0} }; - - /* - * TODO risk of concurrency issues - * - * This should guarded by the dal_mutex but we can't do this since the - * caller uses a spin_lock on event_lock. - * - * If we wait on the dal_mutex a second page flip interrupt might come, - * spin on the event_lock, disabling interrupts while it does so. At - * this point the core can no longer be pre-empted and return to the - * thread that waited on the dal_mutex and we're deadlocked. - * - * With multiple cores the same essentially happens but might just take - * a little longer to lock up all cores. - * - * The reason we should lock on dal_mutex is so that we can be sure - * nobody messes with acrtc->stream after we read and check its value. - * - * We might be able to fix our concurrency issues with a work queue - * where we schedule all work items (mode_set, page_flip, etc.) and - * execute them one by one. Care needs to be taken to still deal with - * any potential concurrency issues arising from interrupt calls. - */ - - acrtc = adev->mode_info.crtcs[crtc_id]; - stream = acrtc->stream; - - - if (acrtc->pflip_status != AMDGPU_FLIP_NONE) { - DRM_ERROR("flip queue: acrtc %d, already busy\n", acrtc->crtc_id); - /* In commit tail framework this cannot happen */ - BUG_ON(0); - } - - - /* - * Received a page flip call after the display has been reset. - * Just return in this case. Everything should be clean-up on reset. - */ - - if (!stream) { - WARN_ON(1); - return; - } - - addr.address.grph.addr.low_part = lower_32_bits(crtc_base); - addr.address.grph.addr.high_part = upper_32_bits(crtc_base); - addr.flip_immediate = async; - - - if (acrtc->base.state->event && - acrtc->base.state->event->event.base.type == - DRM_EVENT_FLIP_COMPLETE) { - acrtc->event = acrtc->base.state->event; - - /* Set the flip status */ - acrtc->pflip_status = AMDGPU_FLIP_SUBMITTED; - - /* Mark this event as consumed */ - acrtc->base.state->event = NULL; - } - - surface_updates->surface = dc_stream_get_status(stream)->surfaces[0]; - surface_updates->flip_addr = &addr; - - - dc_update_surfaces_for_stream(adev->dm.dc, surface_updates, 1, stream); - - DRM_DEBUG_DRIVER("%s Flipping to hi: 0x%x, low: 0x%x \n", - __func__, - addr.address.grph.addr.high_part, - addr.address.grph.addr.low_part); - -} - static int amdgpu_notify_freesync(struct drm_device *dev, void *data, struct drm_file *filp) { @@ -1460,7 +1364,6 @@ static const struct amdgpu_display_funcs dm_display_funcs = { .hpd_sense = NULL,/* called unconditionally */ .hpd_set_polarity = NULL, /* called unconditionally */ .hpd_get_gpio_reg = NULL, /* VBIOS parsing. DAL does it. */ - .page_flip = dm_page_flip, /* called unconditionally */ .page_flip_get_scanoutpos = dm_crtc_get_scanoutpos,/* called unconditionally */ .add_encoder = NULL, /* VBIOS parsing. DAL does it. */ diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 165f91fa1206..6c4d0d1d4367 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2198,6 +2198,8 @@ static void amdgpu_dm_do_flip( struct amdgpu_bo *abo = gem_to_amdgpu_bo(afb->obj); struct amdgpu_device *adev = crtc->dev->dev_private; bool async_flip = (acrtc->flip_flags & DRM_MODE_PAGE_FLIP_ASYNC) != 0; + struct dc_flip_addrs addr = { {0} }; + struct dc_surface_update surface_updates[1] = { {0} }; /* Prepare wait for target vblank early - before the fence-waits */ target_vblank = target - drm_crtc_vblank_count(crtc) + @@ -2211,7 +2213,7 @@ static void amdgpu_dm_do_flip( r = amdgpu_bo_reserve(abo, true); if (unlikely(r != 0)) { DRM_ERROR("failed to reserve buffer before flip\n"); - BUG_ON(0); + WARN_ON(1); } /* Wait for all fences on this FB */ @@ -2239,8 +2241,37 @@ static void amdgpu_dm_do_flip( /* update crtc fb */ crtc->primary->fb = fb; - /* Do the flip (mmio) */ - adev->mode_info.funcs->page_flip(adev, acrtc->crtc_id, afb->address, async_flip); + WARN_ON(acrtc->pflip_status != AMDGPU_FLIP_NONE); + WARN_ON(!acrtc->stream); + + addr.address.grph.addr.low_part = lower_32_bits(afb->address); + addr.address.grph.addr.high_part = upper_32_bits(afb->address); + addr.flip_immediate = async_flip; + + + if (acrtc->base.state->event && + acrtc->base.state->event->event.base.type == + DRM_EVENT_FLIP_COMPLETE) { + acrtc->event = acrtc->base.state->event; + + /* Set the flip status */ + acrtc->pflip_status = AMDGPU_FLIP_SUBMITTED; + + /* Mark this event as consumed */ + acrtc->base.state->event = NULL; + } + + surface_updates->surface = dc_stream_get_status(acrtc->stream)->surfaces[0]; + surface_updates->flip_addr = &addr; + + + dc_update_surfaces_for_stream(adev->dm.dc, surface_updates, 1, acrtc->stream); + + DRM_DEBUG_DRIVER("%s Flipping to hi: 0x%x, low: 0x%x \n", + __func__, + addr.address.grph.addr.high_part, + addr.address.grph.addr.low_part); + spin_unlock_irqrestore(&crtc->dev->event_lock, flags); DRM_DEBUG_DRIVER("crtc:%d, pflip_stat:AMDGPU_FLIP_SUBMITTED\n", -- cgit From 1159898a88db33877bd8378714c6f647afab7f9b Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Wed, 7 Jun 2017 18:28:43 -0400 Subject: drm/amd/display: Handle commit plane with no FB. 1) Always call flip ISR, for any surface comit, not only for page flip. 2) For events not signaled in flip ISR, handle them in end of commit_tail. 3)Fix race condition between subsequent atomic calls by removing current state access AFTER drm_atomic_helper_commit_hw_done was called. After this call a pending next commit will swap in his own state into objects and proceed. Signed-off-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 6 +- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 127 +++++++++++---------- 2 files changed, 70 insertions(+), 63 deletions(-) (limited to 'drivers/gpu') 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 df4cccb4be7a..98e0dbe2a4de 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -222,15 +222,15 @@ static void dm_pflip_high_irq(void *interrupt_params) /* wakeup usersapce */ - if (amdgpu_crtc->event - && amdgpu_crtc->event->event.base.type - == DRM_EVENT_FLIP_COMPLETE) { + if (amdgpu_crtc->event) { /* Update to correct count/ts if racing with vblank irq */ drm_crtc_accurate_vblank_count(&amdgpu_crtc->base); drm_crtc_send_vblank_event(&amdgpu_crtc->base, amdgpu_crtc->event); + /* page flip completed. clean up */ amdgpu_crtc->event = NULL; + } else WARN_ON(1); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 6c4d0d1d4367..b19536d0e045 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2180,6 +2180,24 @@ static void handle_cursor_update( } +static void prepare_flip_isr(struct amdgpu_crtc *acrtc) +{ + + assert_spin_locked(&acrtc->base.dev->event_lock); + WARN_ON(acrtc->event); + + acrtc->event = acrtc->base.state->event; + + /* Set the flip status */ + acrtc->pflip_status = AMDGPU_FLIP_SUBMITTED; + + /* Mark this event as consumed */ + acrtc->base.state->event = NULL; + + DRM_DEBUG_DRIVER("crtc:%d, pflip_stat:AMDGPU_FLIP_SUBMITTED\n", + acrtc->crtc_id); +} + /* * Executes flip * @@ -2249,17 +2267,8 @@ static void amdgpu_dm_do_flip( addr.flip_immediate = async_flip; - if (acrtc->base.state->event && - acrtc->base.state->event->event.base.type == - DRM_EVENT_FLIP_COMPLETE) { - acrtc->event = acrtc->base.state->event; - - /* Set the flip status */ - acrtc->pflip_status = AMDGPU_FLIP_SUBMITTED; - - /* Mark this event as consumed */ - acrtc->base.state->event = NULL; - } + if (acrtc->base.state->event) + prepare_flip_isr(acrtc); surface_updates->surface = dc_stream_get_status(acrtc->stream)->surfaces[0]; surface_updates->flip_addr = &addr; @@ -2274,8 +2283,6 @@ static void amdgpu_dm_do_flip( spin_unlock_irqrestore(&crtc->dev->event_lock, flags); - DRM_DEBUG_DRIVER("crtc:%d, pflip_stat:AMDGPU_FLIP_SUBMITTED\n", - acrtc->crtc_id); } static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, @@ -2289,13 +2296,13 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, struct drm_plane_state *old_plane_state; const struct dc_stream *dc_stream_attach; const struct dc_surface *dc_surfaces_constructed[MAX_SURFACES]; + struct amdgpu_crtc *acrtc_attach = to_amdgpu_crtc(pcrtc); int planes_count = 0; /* update planes when needed */ for_each_plane_in_state(state, plane, old_plane_state, i) { struct drm_plane_state *plane_state = plane->state; struct drm_crtc *crtc = plane_state->crtc; - struct amdgpu_crtc *acrtc_attach = to_amdgpu_crtc(crtc); struct drm_framebuffer *fb = plane_state->fb; struct drm_connector *connector; struct dm_connector_state *con_state = NULL; @@ -2306,7 +2313,7 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, continue; } - if (!fb || !crtc || !crtc->state->active) + if (!fb || !crtc || pcrtc != crtc || !crtc->state->active) continue; pflip_needed = !state->allow_modeset; @@ -2339,17 +2346,21 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, continue; - if (crtc == pcrtc) { - add_surface(dm->dc, crtc, plane, - &dc_surfaces_constructed[planes_count]); - if (dc_surfaces_constructed[planes_count] == NULL) { - dm_error("%s: Failed to add surface!\n", __func__); - continue; - } - dc_stream_attach = acrtc_attach->stream; - planes_count++; + + add_surface(dm->dc, crtc, plane, + &dc_surfaces_constructed[planes_count]); + if (dc_surfaces_constructed[planes_count] == NULL) { + dm_error("%s: Failed to add surface!\n", __func__); + continue; } + dc_stream_attach = acrtc_attach->stream; + planes_count++; + } else if (crtc->state->planes_changed) { + /* Assume even ONE crtc with immediate flip means + * entire can't wait for VBLANK + * TODO Check if it's correct + */ *wait_for_vblank = acrtc_attach->flip_flags & DRM_MODE_PAGE_FLIP_ASYNC ? false : true; @@ -2359,6 +2370,8 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, fb, drm_crtc_vblank_count(crtc) + *wait_for_vblank); + /*TODO BUG remove ASAP in 4.12 to avoid race between worker and flip IOCTL */ + /*clean up the flags for next usage*/ acrtc_attach->flip_flags = 0; } @@ -2366,15 +2379,27 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, } if (planes_count) { + unsigned long flags; + + if (pcrtc->state->event) { + + drm_crtc_vblank_get(pcrtc); + + spin_lock_irqsave(&pcrtc->dev->event_lock, flags); + prepare_flip_isr(acrtc_attach); + spin_unlock_irqrestore(&pcrtc->dev->event_lock, flags); + } + if (false == dc_commit_surfaces_to_stream(dm->dc, dc_surfaces_constructed, planes_count, - dc_stream_attach)) { + dc_stream_attach)) dm_error("%s: Failed to attach surface!\n", __func__); - return; - } + for (i = 0; i < planes_count; i++) dc_surface_release(dc_surfaces_constructed[i]); + } else { + /*TODO BUG Here should go disable planes on CRTC. */ } } @@ -2405,7 +2430,6 @@ void amdgpu_dm_atomic_commit_tail( struct drm_crtc_state *new_state = crtc->state; acrtc = to_amdgpu_crtc(crtc); - aconnector = amdgpu_dm_find_first_crct_matching_connector( state, @@ -2571,14 +2595,6 @@ void amdgpu_dm_atomic_commit_tail( dc_stream_get_status(acrtc->stream)->primary_otg_inst; } - /* update planes when needed per crtc*/ - for_each_crtc_in_state(state, pcrtc, old_crtc_state, j) { - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(pcrtc); - - if (acrtc->stream) - amdgpu_dm_commit_surfaces(state, dev, dm, pcrtc, &wait_for_vblank); - } - for (i = 0; i < new_crtcs_count; i++) { /* * loop to enable interrupts on newly arrived crtc @@ -2592,19 +2608,27 @@ void amdgpu_dm_atomic_commit_tail( manage_dm_interrupts(adev, acrtc, true); } + /* update planes when needed per crtc*/ + for_each_crtc_in_state(state, pcrtc, old_crtc_state, j) { + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(pcrtc); + + if (acrtc->stream) + amdgpu_dm_commit_surfaces(state, dev, dm, pcrtc, &wait_for_vblank); + } + - /*TODO mark consumed event on all crtc assigned event - * in drm_atomic_helper_setup_commit just to signal completion + /* + * send vblank event on all events not handled in flip and + * mark consumed event for drm_atomic_helper_commit_hw_done */ spin_lock_irqsave(&adev->ddev->event_lock, flags); for_each_crtc_in_state(state, crtc, old_crtc_state, i) { struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - if (acrtc->base.state->event && - acrtc->base.state->event->event.base.type != DRM_EVENT_FLIP_COMPLETE) { - acrtc->event = acrtc->base.state->event; - acrtc->base.state->event = NULL; - } + if (acrtc->base.state->event) + drm_send_event_locked(dev, &crtc->state->event->base); + + acrtc->base.state->event = NULL; } spin_unlock_irqrestore(&adev->ddev->event_lock, flags); @@ -2614,23 +2638,6 @@ void amdgpu_dm_atomic_commit_tail( if (wait_for_vblank) drm_atomic_helper_wait_for_vblanks(dev, state); - /*TODO send vblank event on all crtc assigned event - * in drm_atomic_helper_setup_commit just to signal completion - */ - spin_lock_irqsave(&adev->ddev->event_lock, flags); - for_each_crtc_in_state(state, crtc, old_crtc_state, i) { - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - - if (acrtc->event && - acrtc->event->event.base.type != DRM_EVENT_FLIP_COMPLETE) { - drm_send_event_locked(dev, &acrtc->event->base); - acrtc->event = NULL; - } - } - spin_unlock_irqrestore(&adev->ddev->event_lock, flags); - - /*TODO Is it to early if actual flip haven't happened yet ?*/ - /* Release old FB */ drm_atomic_helper_cleanup_planes(dev, state); } -- cgit From c8210d5ae37b3c0e5dc2a91095dd1147c524977d Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Fri, 9 Jun 2017 10:12:36 -0400 Subject: drm/amd/display: Don't call DCN clk code for Vega Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c | 10 ++++++---- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c index 84b0860190d7..4e3f4e5e46a0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c @@ -614,11 +614,13 @@ static bool dce_apply_clock_voltage_request( } if (send_request) { #if defined(CONFIG_DRM_AMD_DC_DCN1_0) - struct core_dc *core_dc = DC_TO_CORE(clk->ctx->dc); - /*use dcfclk request voltage*/ - clock_voltage_req.clk_type = DM_PP_CLOCK_TYPE_DCFCLK; - clock_voltage_req.clocks_in_khz = + if (clk->ctx->dce_version == DCN_VERSION_1_0) { + struct core_dc *core_dc = DC_TO_CORE(clk->ctx->dc); + /*use dcfclk request voltage*/ + clock_voltage_req.clk_type = DM_PP_CLOCK_TYPE_DCFCLK; + clock_voltage_req.clocks_in_khz = dcn_find_dcfclk_suits_all(core_dc, &clk->cur_clocks_value); + } #endif dm_pp_apply_clock_for_voltage_request( clk->ctx, &clock_voltage_req); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index ac99d283bf0a..7c509811efa6 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1633,7 +1633,7 @@ enum dc_status dce110_apply_ctx_to_hw( apply_min_clocks(dc, context, &clocks_state, true); #if defined(CONFIG_DRM_AMD_DC_DCN1_0) - if (resource_parse_asic_id(dc->ctx->asic_id) == DCN_VERSION_1_0) { + if (dc->ctx->dce_version == DCN_VERSION_1_0) { if (context->bw.dcn.calc_clk.fclk_khz > dc->current_context->bw.dcn.cur_clk.fclk_khz) { struct dm_pp_clock_for_voltage_req clock; -- cgit From b6d6103bbb21ed51acf0168529d867df1ecde445 Mon Sep 17 00:00:00 2001 From: Vitaly Prosyak Date: Mon, 12 Jun 2017 11:03:26 -0500 Subject: drm/amd/display: RV stereo support Re-organize 3d declarations Signed-off-by: Vitaly Prosyak Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 8 +----- drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 43 +++++++++++++++------------- drivers/gpu/drm/amd/display/dc/dc_types.h | 9 ++++++ 3 files changed, 33 insertions(+), 27 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index fb86808dd309..a78af1ef1315 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -787,13 +787,7 @@ struct dc_container_id { unsigned short productCode; }; -struct stereo_3d_features { - bool supported ; - bool allTimings ; - bool cloneMode ; - bool scaling ; - bool singleFrameSWPacked; -}; + /* * The sink structure contains EDID and other display device properties diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index b6e677786cbc..94fb93066784 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -551,27 +551,7 @@ enum dc_timing_standard { TIMING_STANDARD_MAX }; -enum dc_timing_3d_format { - TIMING_3D_FORMAT_NONE, - TIMING_3D_FORMAT_FRAME_ALTERNATE, /* No stereosync at all*/ - TIMING_3D_FORMAT_INBAND_FA, /* Inband Frame Alternate (DVI/DP)*/ - TIMING_3D_FORMAT_DP_HDMI_INBAND_FA, /* Inband FA to HDMI Frame Pack*/ - /* for active DP-HDMI dongle*/ - TIMING_3D_FORMAT_SIDEBAND_FA, /* Sideband Frame Alternate (eDP)*/ - TIMING_3D_FORMAT_HW_FRAME_PACKING, - TIMING_3D_FORMAT_SW_FRAME_PACKING, - TIMING_3D_FORMAT_ROW_INTERLEAVE, - TIMING_3D_FORMAT_COLUMN_INTERLEAVE, - TIMING_3D_FORMAT_PIXEL_INTERLEAVE, - TIMING_3D_FORMAT_SIDE_BY_SIDE, - TIMING_3D_FORMAT_TOP_AND_BOTTOM, - TIMING_3D_FORMAT_SBS_SW_PACKED, - /* Side-by-side, packed by application/driver into 2D frame*/ - TIMING_3D_FORMAT_TB_SW_PACKED, - /* Top-and-bottom, packed by application/driver into 2D frame*/ - TIMING_3D_FORMAT_MAX, -}; enum dc_color_depth { COLOR_DEPTH_UNDEFINED, @@ -643,6 +623,29 @@ struct dc_crtc_timing_flags { }; +enum dc_timing_3d_format { + TIMING_3D_FORMAT_NONE, + TIMING_3D_FORMAT_FRAME_ALTERNATE, /* No stereosync at all*/ + TIMING_3D_FORMAT_INBAND_FA, /* Inband Frame Alternate (DVI/DP)*/ + TIMING_3D_FORMAT_DP_HDMI_INBAND_FA, /* Inband FA to HDMI Frame Pack*/ + /* for active DP-HDMI dongle*/ + TIMING_3D_FORMAT_SIDEBAND_FA, /* Sideband Frame Alternate (eDP)*/ + TIMING_3D_FORMAT_HW_FRAME_PACKING, + TIMING_3D_FORMAT_SW_FRAME_PACKING, + TIMING_3D_FORMAT_ROW_INTERLEAVE, + TIMING_3D_FORMAT_COLUMN_INTERLEAVE, + TIMING_3D_FORMAT_PIXEL_INTERLEAVE, + TIMING_3D_FORMAT_SIDE_BY_SIDE, + TIMING_3D_FORMAT_TOP_AND_BOTTOM, + TIMING_3D_FORMAT_SBS_SW_PACKED, + /* Side-by-side, packed by application/driver into 2D frame*/ + TIMING_3D_FORMAT_TB_SW_PACKED, + /* Top-and-bottom, packed by application/driver into 2D frame*/ + + TIMING_3D_FORMAT_MAX, +}; + + struct dc_crtc_timing { uint32_t h_total; diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 5269796b2a8e..9662f2c68f83 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -272,6 +272,15 @@ enum dc_timing_source { TIMING_SOURCE_COUNT }; + +struct stereo_3d_features { + bool supported ; + bool allTimings ; + bool cloneMode ; + bool scaling ; + bool singleFrameSWPacked; +}; + enum dc_timing_support_method { TIMING_SUPPORT_METHOD_UNDEFINED, TIMING_SUPPORT_METHOD_EXPLICIT, -- cgit From 7a0963345f859058fa866dd28fe13ca5eff22a87 Mon Sep 17 00:00:00 2001 From: Zeyu Fan Date: Tue, 13 Jun 2017 11:54:10 -0400 Subject: drm/amd/display: Save hpd_src for dc_link Signed-off-by: Zeyu Fan Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 3 +++ drivers/gpu/drm/amd/display/dc/dc.h | 3 +++ 2 files changed, 6 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index b2c8b572d57f..fed38fbab452 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -987,6 +987,9 @@ static bool construct( enc_init_data.connector = link->link_id; enc_init_data.channel = get_ddc_line(link); enc_init_data.hpd_source = get_hpd_line(link); + + link->public.hpd_src = enc_init_data.hpd_source; + enc_init_data.transmitter = translate_encoder_to_transmitter(enc_init_data.encoder); link->link_enc = link->dc->res_pool->funcs->link_enc_create( diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index a78af1ef1315..6d918391435a 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -658,6 +658,9 @@ struct dc_link { struct dc_lane_settings cur_lane_setting; uint8_t ddc_hw_inst; + + uint8_t hpd_src; + uint8_t link_enc_hw_inst; bool test_pattern_enabled; -- cgit From 80b4c5a8c1e1856848a440a63accbe029ea3b51b Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Tue, 13 Jun 2017 16:31:49 -0400 Subject: drm/amd/display: fix dc_check_update_surfaces_for_stream memcmp sequence Signed-off-by: Dmytro Laktyushkin Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index e518aeddfa58..f5f365b418c2 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1094,11 +1094,13 @@ static enum surface_update_type get_plane_info_update_type( const struct dc_surface_update *u, int surface_index) { - struct dc_plane_info temp_plane_info = { 0 }; + struct dc_plane_info temp_plane_info; if (!u->plane_info) return UPDATE_TYPE_FAST; + temp_plane_info = *u->plane_info; + /* Copy all parameters that will cause a full update * from current surface, the rest of the parameters * from provided plane configuration. @@ -1115,10 +1117,6 @@ static enum surface_update_type get_plane_info_update_type( temp_plane_info.stereo_format = u->surface->stereo_format; temp_plane_info.tiling_info = u->surface->tiling_info; - /* Special Validation parameters */ - temp_plane_info.format = u->plane_info->format; - temp_plane_info.per_pixel_alpha = u->plane_info->per_pixel_alpha; - if (surface_index == 0) temp_plane_info.visible = u->plane_info->visible; else -- cgit From ebf055f95b4782e681c0040461a33c0210e65a5d Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Wed, 14 Jun 2017 10:19:57 -0400 Subject: drm/amd/display: fix issues with incorrectly detecting UPDATE_TYPE_FULL This is due to how structures are being packed with padding added. Structure field initialization doesn't clear the padding bytes, which cause our memcmp to give incorrect result. Move smaller structure parameters to end of structure. Signed-off-by: Anthony Koo Reviewed-by: Aric Cyr Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 6 ++- drivers/gpu/drm/amd/display/dc/dc.h | 75 +++++++++++++++++--------------- 2 files changed, 44 insertions(+), 37 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index f5f365b418c2..a8f34a92cee2 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -628,7 +628,8 @@ static bool is_validation_required( return true; for (j = 0; j < set[i].surface_count; j++) { - struct dc_surface temp_surf = { 0 }; + struct dc_surface temp_surf; + memset(&temp_surf, 0, sizeof(temp_surf)); temp_surf = *context->stream_status[i].surfaces[j]; temp_surf.clip_rect = set[i].surfaces[j]->clip_rect; @@ -1095,6 +1096,7 @@ static enum surface_update_type get_plane_info_update_type( int surface_index) { struct dc_plane_info temp_plane_info; + memset(&temp_plane_info, 0, sizeof(temp_plane_info)); if (!u->plane_info) return UPDATE_TYPE_FAST; @@ -1294,7 +1296,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, update_surface_trace(dc, srf_updates, surface_count); if (update_type >= UPDATE_TYPE_FULL) { - const struct dc_surface *new_surfaces[MAX_SURFACES] = { 0 }; + const struct dc_surface *new_surfaces[MAX_SURFACES] = {0}; for (i = 0; i < surface_count; i++) new_surfaces[i] = srf_updates[i].surface; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 6d918391435a..36b3b123d3c7 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -54,8 +54,8 @@ struct dc_caps { struct dc_dcc_surface_param { - enum surface_pixel_format format; struct dc_size surface_size; + enum surface_pixel_format format; enum swizzle_mode_values swizzle_mode; enum dc_scan_direction scan; }; @@ -67,9 +67,6 @@ struct dc_dcc_setting { }; struct dc_surface_dcc_cap { - bool capable; - bool const_color_support; - union { struct { struct dc_dcc_setting rgb; @@ -80,6 +77,9 @@ struct dc_surface_dcc_cap { struct dc_dcc_setting chroma; } video; }; + + bool capable; + bool const_color_support; }; struct dc_static_screen_events { @@ -201,12 +201,12 @@ enum frame_buffer_mode { } ; struct dchub_init_data { - bool dchub_initialzied; - bool dchub_info_valid; int64_t zfb_phys_addr_base; int64_t zfb_mc_base_addr; uint64_t zfb_size_in_byte; enum frame_buffer_mode fb_mode; + bool dchub_initialzied; + bool dchub_info_valid; }; struct dc_init_data { @@ -240,9 +240,6 @@ enum { }; struct dc_hdr_static_metadata { - bool hdr_supported; - bool is_hdr; - /* display chromaticities and white point in units of 0.00001 */ unsigned int chromaticity_green_x; unsigned int chromaticity_green_y; @@ -257,6 +254,9 @@ struct dc_hdr_static_metadata { uint32_t max_luminance; uint32_t maximum_content_light_level; uint32_t maximum_frame_average_light_level; + + bool hdr_supported; + bool is_hdr; }; enum dc_transfer_func_type { @@ -285,15 +285,12 @@ enum dc_transfer_func_predefined { }; struct dc_transfer_func { + struct dc_transfer_func_distributed_points tf_pts; enum dc_transfer_func_type type; enum dc_transfer_func_predefined tf; - struct dc_transfer_func_distributed_points tf_pts; }; struct dc_surface { - bool per_pixel_alpha; - bool visible; - bool flip_immediate; struct dc_plane_address address; struct scaling_taps scaling_quality; @@ -303,38 +300,42 @@ struct dc_surface { union plane_size plane_size; union dc_tiling_info tiling_info; + struct dc_plane_dcc_param dcc; - enum dc_color_space color_space; + struct dc_hdr_static_metadata hdr_static_ctx; + + const struct dc_gamma *gamma_correction; + const struct dc_transfer_func *in_transfer_func; + enum dc_color_space color_space; enum surface_pixel_format format; enum dc_rotation_angle rotation; - bool horizontal_mirror; enum plane_stereo_format stereo_format; - struct dc_hdr_static_metadata hdr_static_ctx; - - const struct dc_gamma *gamma_correction; - const struct dc_transfer_func *in_transfer_func; + bool per_pixel_alpha; + bool visible; + bool flip_immediate; + bool horizontal_mirror; }; struct dc_plane_info { - bool per_pixel_alpha; union plane_size plane_size; union dc_tiling_info tiling_info; struct dc_plane_dcc_param dcc; enum surface_pixel_format format; enum dc_rotation_angle rotation; - bool horizontal_mirror; enum plane_stereo_format stereo_format; enum dc_color_space color_space; /*todo: wrong place, fits in scaling info*/ + bool horizontal_mirror; bool visible; + bool per_pixel_alpha; }; struct dc_scaling_info { - struct rect src_rect; - struct rect dst_rect; - struct rect clip_rect; - struct scaling_taps scaling_quality; + struct rect src_rect; + struct rect dst_rect; + struct rect clip_rect; + struct scaling_taps scaling_quality; }; struct dc_surface_update { @@ -460,24 +461,26 @@ enum surface_update_type { struct dc_stream { const struct dc_sink *sink; struct dc_crtc_timing timing; - enum signal_type output_signal; - - enum dc_color_space output_color_space; - enum dc_dither_option dither_option; struct rect src; /* composition area */ struct rect dst; /* stream addressable area */ struct audio_info audio_info; - bool ignore_msa_timing_param; - struct freesync_context freesync_ctx; const struct dc_transfer_func *out_transfer_func; struct colorspace_transform gamut_remap_matrix; struct csc_transform csc_color_matrix; + + enum signal_type output_signal; + + enum dc_color_space output_color_space; + enum dc_dither_option dither_option; + enum view_3d_format view_format; + + bool ignore_msa_timing_param; /* TODO: custom INFO packets */ /* TODO: ABM info (DMCU) */ /* TODO: PSR info */ @@ -667,9 +670,10 @@ struct dc_link { union compliance_test_state compliance_test_state; void *priv; - bool aux_mode; struct ddc_service *ddc; + + bool aux_mode; }; struct dpcd_caps { @@ -685,12 +689,13 @@ struct dpcd_caps { indicates 'Frame Sequential-to-lllFrame Pack' conversion capability.*/ struct dc_dongle_caps dongle_caps; - bool allow_invalid_MSA_timing_param; - bool panel_mode_edp; uint32_t sink_dev_id; uint32_t branch_dev_id; int8_t branch_dev_name[6]; int8_t branch_hw_revision; + + bool allow_invalid_MSA_timing_param; + bool panel_mode_edp; }; struct dc_link_status { @@ -801,9 +806,9 @@ struct dc_sink { struct dc_edid_caps edid_caps; /* parse display caps */ struct dc_container_id *dc_container_id; uint32_t dongle_max_pix_clk; - bool converter_disable_audio; void *priv; struct stereo_3d_features features_3d[TIMING_3D_FORMAT_MAX]; + bool converter_disable_audio; }; void dc_sink_retain(const struct dc_sink *sink); -- cgit From 7950f0f9815a2dc2e3e1cc2d341d486ac2ae8bae Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Tue, 13 Jun 2017 17:08:22 -0400 Subject: drm/amd/display: fix dc_post_update_surfaces_to_stream Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 35 ++++++++-------------- drivers/gpu/drm/amd/display/dc/dc.h | 9 +----- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 11 ++----- 3 files changed, 17 insertions(+), 38 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index a8f34a92cee2..909d38522361 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -953,15 +953,6 @@ context_alloc_fail: return (result == DC_OK); } -bool dc_pre_update_surfaces_to_stream( - struct dc *dc, - const struct dc_surface *const *new_surfaces, - uint8_t new_surface_count, - const struct dc_stream *dc_stream) -{ - return true; -} - bool dc_post_update_surfaces_to_stream(struct dc *dc) { int i; @@ -971,14 +962,19 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) post_surface_trace(dc); for (i = 0; i < core_dc->res_pool->pipe_count; i++) - if (context->res_ctx.pipe_ctx[i].stream == NULL) { + if (context->res_ctx.pipe_ctx[i].stream == NULL + || context->res_ctx.pipe_ctx[i].surface == NULL) { context->res_ctx.pipe_ctx[i].pipe_idx = i; core_dc->hwss.power_down_front_end( core_dc, &context->res_ctx.pipe_ctx[i]); } + /* 3rd param should be true, temp w/a for RV*/ +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + core_dc->hwss.set_bandwidth(core_dc, context, core_dc->ctx->dce_version != DCN_VERSION_1_0); +#else core_dc->hwss.set_bandwidth(core_dc, context, true); - +#endif return true; } @@ -1262,17 +1258,12 @@ void dc_update_surfaces_and_stream(struct dc *dc, if (stream_update->out_transfer_func && stream_update->out_transfer_func != - dc_stream->out_transfer_func) { - if (stream_update->out_transfer_func->type != - TF_TYPE_UNKNOWN) { - if (dc_stream->out_transfer_func != NULL) - dc_transfer_func_release - (dc_stream->out_transfer_func); - dc_transfer_func_retain(stream_update-> - out_transfer_func); - stream->public.out_transfer_func = - stream_update->out_transfer_func; - } + dc_stream->out_transfer_func) { + if (dc_stream->out_transfer_func != NULL) + dc_transfer_func_release(dc_stream->out_transfer_func); + dc_transfer_func_retain(stream_update->out_transfer_func); + stream->public.out_transfer_func = + stream_update->out_transfer_func; } } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 36b3b123d3c7..52c36007382f 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -262,8 +262,7 @@ struct dc_hdr_static_metadata { enum dc_transfer_func_type { TF_TYPE_PREDEFINED, TF_TYPE_DISTRIBUTED_POINTS, - TF_TYPE_BYPASS, - TF_TYPE_UNKNOWN + TF_TYPE_BYPASS }; struct dc_transfer_func_distributed_points { @@ -411,12 +410,6 @@ bool dc_commit_surfaces_to_stream( uint8_t surface_count, const struct dc_stream *stream); -bool dc_pre_update_surfaces_to_stream( - struct dc *dc, - const struct dc_surface *const *new_surfaces, - uint8_t new_surface_count, - const struct dc_stream *stream); - bool dc_post_update_surfaces_to_stream( struct dc *dc); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 7c509811efa6..a83d260cda45 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -2538,17 +2538,12 @@ static void dce110_apply_ctx_for_surface( static void dce110_power_down_fe(struct core_dc *dc, struct pipe_ctx *pipe) { - int i; - - for (i = 0; i < dc->res_pool->pipe_count; i++) - if (&dc->current_context->res_ctx.pipe_ctx[i] == pipe) - break; - - if (i == dc->res_pool->pipe_count) + /* Do not power down fe when stream is active on dce*/ + if (pipe->stream) return; dc->hwss.enable_display_power_gating( - dc, i, dc->ctx->dc_bios, PIPE_GATING_CONTROL_ENABLE); + dc, pipe->pipe_idx, dc->ctx->dc_bios, PIPE_GATING_CONTROL_ENABLE); if (pipe->xfm) pipe->xfm->funcs->transform_reset(pipe->xfm); memset(&pipe->scl_data, 0, sizeof(struct scaler_data)); -- cgit From f19d5f3520d67cee4a98721032c1b7aee7942f20 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Tue, 13 Jun 2017 17:14:51 -0400 Subject: drm/amd/display: do full fe reprogram on full update Fixes MPO entry in 2x4k scenario on raven Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 81 +++++++++++++++++++++----------- 1 file changed, 54 insertions(+), 27 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 909d38522361..18fde5081742 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1404,15 +1404,18 @@ void dc_update_surfaces_and_stream(struct dc *dc, if (!surface_count) /* reset */ core_dc->hwss.apply_ctx_for_surface(core_dc, NULL, context); - /* Lock pipes for provided surfaces */ + /* Lock pipes for provided surfaces, or all active if full update*/ for (i = 0; i < surface_count; i++) { struct core_surface *surface = DC_SURFACE_TO_CORE(srf_updates[i].surface); for (j = 0; j < core_dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - if (pipe_ctx->surface != surface) + if (update_type != UPDATE_TYPE_FULL && pipe_ctx->surface != surface) + continue; + if (!pipe_ctx->surface || pipe_ctx->top_pipe) continue; + if (!pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) { core_dc->hwss.pipe_control_lock( core_dc, @@ -1420,22 +1423,49 @@ void dc_update_surfaces_and_stream(struct dc *dc, true); } } + if (update_type == UPDATE_TYPE_FULL) + break; } + /* Full fe update*/ + for (j = 0; j < core_dc->res_pool->pipe_count; j++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; + struct pipe_ctx *cur_pipe_ctx = &core_dc->current_context->res_ctx.pipe_ctx[j]; + bool is_new_pipe_surface = cur_pipe_ctx->surface != pipe_ctx->surface; + struct dc_cursor_position position = { 0 }; + + if (update_type != UPDATE_TYPE_FULL || !pipe_ctx->surface) + continue; + + if (!pipe_ctx->top_pipe) + core_dc->hwss.apply_ctx_for_surface( + core_dc, pipe_ctx->surface, context); + + /* TODO: this is a hack w/a for switching from mpo to pipe split */ + dc_stream_set_cursor_position(&pipe_ctx->stream->public, &position); + + if (is_new_pipe_surface) { + core_dc->hwss.update_plane_addr(core_dc, pipe_ctx); + core_dc->hwss.set_input_transfer_func( + pipe_ctx, pipe_ctx->surface); + core_dc->hwss.set_output_transfer_func( + pipe_ctx, pipe_ctx->stream); + } + } + + if (update_type > UPDATE_TYPE_FAST) + context_timing_trace(dc, &context->res_ctx); + /* Perform requested Updates */ for (i = 0; i < surface_count; i++) { struct core_surface *surface = DC_SURFACE_TO_CORE(srf_updates[i].surface); - if (update_type >= UPDATE_TYPE_MED) { - core_dc->hwss.apply_ctx_for_surface( - core_dc, surface, context); - context_timing_trace(dc, &context->res_ctx); - } + if (update_type == UPDATE_TYPE_MED) + core_dc->hwss.apply_ctx_for_surface( + core_dc, surface, context); for (j = 0; j < core_dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - struct pipe_ctx *cur_pipe_ctx; - bool is_new_pipe_surface = true; if (pipe_ctx->surface != surface) continue; @@ -1446,19 +1476,12 @@ void dc_update_surfaces_and_stream(struct dc *dc, if (update_type == UPDATE_TYPE_FAST) continue; - cur_pipe_ctx = &core_dc->current_context->res_ctx.pipe_ctx[j]; - if (cur_pipe_ctx->surface == pipe_ctx->surface) - is_new_pipe_surface = false; - - if (is_new_pipe_surface || - srf_updates[i].in_transfer_func) + if (srf_updates[i].in_transfer_func) core_dc->hwss.set_input_transfer_func( pipe_ctx, pipe_ctx->surface); - if (is_new_pipe_surface || - (stream_update != NULL && - stream_update->out_transfer_func != - NULL)) { + if (stream_update != NULL && + stream_update->out_transfer_func != NULL) { core_dc->hwss.set_output_transfer_func( pipe_ctx, pipe_ctx->stream); } @@ -1475,15 +1498,19 @@ void dc_update_surfaces_and_stream(struct dc *dc, struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; for (j = 0; j < surface_count; j++) { - if (srf_updates[j].surface == &pipe_ctx->surface->public) { - if (!pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) { - core_dc->hwss.pipe_control_lock( - core_dc, - pipe_ctx, - false); - } - break; + if (update_type != UPDATE_TYPE_FULL && + srf_updates[j].surface != &pipe_ctx->surface->public) + continue; + if (!pipe_ctx->surface || pipe_ctx->top_pipe) + continue; + + if (!pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) { + core_dc->hwss.pipe_control_lock( + core_dc, + pipe_ctx, + false); } + break; } } -- cgit From 90f095c13efe2aed108ebd4754dd629946b68168 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 16 Jun 2017 11:27:59 -0400 Subject: drm/amd/display: add pipe split disable regkey Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 2 +- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 2b62efce73c5..0aa6662650cc 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -791,7 +791,7 @@ bool dcn_validate_bandwidth( v->phyclk_per_state[1] = v->phyclkv_mid0p72; v->phyclk_per_state[0] = v->phyclkv_min0p65; - if (dc->public.debug.use_max_voltage) { + if (dc->public.debug.disable_pipe_split) { v->max_dppclk[1] = v->max_dppclk_vnom0p8; v->max_dppclk[0] = v->max_dppclk_vnom0p8; } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 52c36007382f..62493c4a47d1 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -170,7 +170,7 @@ struct dc_debug { bool disable_hubp_power_gate; bool disable_pplib_wm_range; bool use_dml_wm; - bool use_max_voltage; + bool disable_pipe_split; int sr_exit_time_ns; int sr_enter_plus_exit_time_ns; int urgent_latency_ns; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 77fc251d45ba..c7840e0e3ae5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -443,7 +443,7 @@ static const struct dc_debug debug_defaults_drv = { .disable_pplib_wm_range = false, #if defined(CONFIG_DRM_AMD_DC_DCN1_0) .use_dml_wm = false, - .use_max_voltage = false + .disable_pipe_split = false #endif }; @@ -456,7 +456,7 @@ static const struct dc_debug debug_defaults_diags = { .disable_pplib_clock_request = true, .disable_pplib_wm_range = true, .use_dml_wm = false, - .use_max_voltage = false + .disable_pipe_split = false #endif }; -- cgit From 0604b36c77e31a05b1bd18d53cac2c9350500bcb Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Thu, 22 Jun 2017 17:37:22 -0400 Subject: drm/amd/display: Create dm_plane_state. Hook up dc_surface creation/destruction to dm_plane_state. Rename amdgpu_drm_plane_state to dm_plane_state and do minor cleanups. Signed-off-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 14 ++-- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 79 ++++++++++++++++------ 2 files changed, 67 insertions(+), 26 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index be51ac56552c..190905e08c38 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -59,6 +59,8 @@ struct amdgpu_hpd; #define to_amdgpu_framebuffer(x) container_of(x, struct amdgpu_framebuffer, base) #define to_amdgpu_plane(x) container_of(x, struct amdgpu_plane, base) +#define to_dm_plane_state(x) container_of(x, struct dm_plane_state, base); + #define AMDGPU_MAX_HPD_PINS 6 #define AMDGPU_MAX_CRTCS 6 #define AMDGPU_MAX_PLANES 6 @@ -440,16 +442,18 @@ struct amdgpu_crtc { struct drm_pending_vblank_event *event; }; -struct amdgpu_drm_plane_state { +/* TODO rename to dc_plane_state */ +struct dc_surface; + +struct dm_plane_state { struct drm_plane_state base; - unsigned int h_ratio; - unsigned int v_ratio; + struct dc_surface* dc_surface; }; -static inline struct amdgpu_drm_plane_state * +static inline struct dm_plane_state * to_amdgpu_plane_state(struct drm_plane_state *state) { - return container_of(state, struct amdgpu_drm_plane_state, base); + return container_of(state, struct dm_plane_state, base); } struct amdgpu_plane { diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index b19536d0e045..83baa48ba907 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -1356,45 +1356,82 @@ const struct drm_encoder_helper_funcs amdgpu_dm_encoder_helper_funcs = { static void dm_drm_plane_reset(struct drm_plane *plane) { - struct amdgpu_drm_plane_state *amdgpu_state; + struct dm_plane_state *amdgpu_state = NULL; + struct amdgpu_device *adev = plane->dev->dev_private; - if (plane->state) { - amdgpu_state = to_amdgpu_plane_state(plane->state); - if (amdgpu_state->base.fb) - drm_framebuffer_unreference(amdgpu_state->base.fb); - kfree(amdgpu_state); - plane->state = NULL; - } + if (plane->state) + plane->funcs->atomic_destroy_state(plane, plane->state); amdgpu_state = kzalloc(sizeof(*amdgpu_state), GFP_KERNEL); + if (amdgpu_state) { plane->state = &amdgpu_state->base; plane->state->plane = plane; + plane->state->rotation = DRM_MODE_ROTATE_0; + + amdgpu_state->dc_surface = dc_create_surface(adev->dm.dc); + WARN_ON(!amdgpu_state->dc_surface); } + else + WARN_ON(1); } static struct drm_plane_state * dm_drm_plane_duplicate_state(struct drm_plane *plane) { - struct amdgpu_drm_plane_state *amdgpu_state; - struct amdgpu_drm_plane_state *copy; + struct dm_plane_state *dm_plane_state, *old_dm_plane_state; + struct amdgpu_device *adev = plane->dev->dev_private; + + old_dm_plane_state = to_dm_plane_state(plane->state); + dm_plane_state = kzalloc(sizeof(*dm_plane_state), GFP_KERNEL); + if (!dm_plane_state) + return NULL; + + if (old_dm_plane_state->dc_surface) { + struct dc_surface *dc_surface = dc_create_surface(adev->dm.dc); + if (WARN_ON(!dc_surface)) + return NULL; + + __drm_atomic_helper_plane_duplicate_state(plane, &dm_plane_state->base); + + memcpy(dc_surface, old_dm_plane_state->dc_surface, sizeof(*dc_surface)); + + if (old_dm_plane_state->dc_surface->gamma_correction) + dc_gamma_retain(dc_surface->gamma_correction); - amdgpu_state = to_amdgpu_plane_state(plane->state); - copy = kzalloc(sizeof(*amdgpu_state), GFP_KERNEL); - if (!copy) + if (old_dm_plane_state->dc_surface->in_transfer_func) + dc_transfer_func_retain(dc_surface->in_transfer_func); + + dm_plane_state->dc_surface = dc_surface; + + /*TODO Check for inferred values to be reset */ + } + else { + WARN_ON(1); return NULL; + } - __drm_atomic_helper_plane_duplicate_state(plane, ©->base); - return ©->base; + return &dm_plane_state->base; } -static void dm_drm_plane_destroy_state(struct drm_plane *plane, - struct drm_plane_state *old_state) +void dm_drm_plane_destroy_state(struct drm_plane *plane, + struct drm_plane_state *state) { - struct amdgpu_drm_plane_state *old_amdgpu_state = - to_amdgpu_plane_state(old_state); - __drm_atomic_helper_plane_destroy_state(old_state); - kfree(old_amdgpu_state); + struct dm_plane_state *dm_plane_state = to_dm_plane_state(state); + + if (dm_plane_state->dc_surface) { + struct dc_surface *dc_surface = dm_plane_state->dc_surface; + + if (dc_surface->gamma_correction) + dc_gamma_release(&dc_surface->gamma_correction); + + if (dc_surface->in_transfer_func) + dc_transfer_func_release(dc_surface->in_transfer_func); + + dc_surface_release(dc_surface); + } + + drm_atomic_helper_plane_destroy_state(plane, state); } static const struct drm_plane_funcs dm_plane_funcs = { -- cgit From 80c62d3a112af59ada6c3a5fc1de16021d7ad790 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Mon, 19 Jun 2017 11:38:15 -0400 Subject: drm/amd/display: MST atomic_get_property missing. Missing function implementation was leading to EINVAL in UMD thus not adding MST connector to X topology and hence not getting set mode for it. Signed-off-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 77907baa522a..ec91a52c002f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -168,7 +168,8 @@ static const struct drm_connector_funcs dm_dp_mst_connector_funcs = { .reset = amdgpu_dm_connector_funcs_reset, .atomic_duplicate_state = amdgpu_dm_connector_atomic_duplicate_state, .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, - .atomic_set_property = amdgpu_dm_connector_atomic_set_property + .atomic_set_property = amdgpu_dm_connector_atomic_set_property, + .atomic_get_property = amdgpu_dm_connector_atomic_get_property }; static int dm_dp_mst_get_modes(struct drm_connector *connector) -- cgit From 03c8a5feeecf95ca1dfabb5b231016c0e76a187c Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Tue, 20 Jun 2017 10:42:33 -0400 Subject: drm/amd/display: Add global lock function. Signed-off-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 66 ++++++++++++++++------ 1 file changed, 49 insertions(+), 17 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 83baa48ba907..db38dd0a0c1f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2890,6 +2890,49 @@ static enum surface_update_type amdgpu_dm_check_surfaces_update_type( return update_type; } +/*` + * Grabs all modesetting locks to serialize against any blocking commits, + * Waits for completion of all non blocking commits. + */ +static void aquire_global_lock( + struct drm_device *dev, + struct drm_atomic_state *state) +{ + struct drm_crtc *crtc; + struct drm_crtc_commit *commit; + long ret; + + /* Adding all modeset locks to aquire_ctx will + * ensure that when the framework release it the + * extra locks we are locking here will get released to + */ + drm_modeset_lock_all_ctx(dev, state->acquire_ctx); + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + spin_lock(&crtc->commit_lock); + commit = list_first_entry_or_null(&crtc->commit_list, + struct drm_crtc_commit, commit_entry); + if (commit) + drm_crtc_commit_get(commit); + spin_unlock(&crtc->commit_lock); + + if (!commit) + continue; + + /* Make sure all pending HW programming completed and + * page flips done + */ + ret = wait_for_completion_timeout(&commit->hw_done, + 10*HZ); + ret = wait_for_completion_timeout(&commit->flip_done, + 10*HZ); + if (ret == 0) + DRM_ERROR("[CRTC:%d:%s] hw_done timed out\n", + crtc->base.id, crtc->name); + drm_crtc_commit_put(commit); + } +} + int amdgpu_dm_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) { @@ -3146,7 +3189,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, dc, set[i].surfaces, set[i].surface_count, - set[i].stream) > UPDATE_TYPE_MED) { + set[i].stream) > UPDATE_TYPE_FAST) { wait_for_prev_commits = true; break; } @@ -3160,25 +3203,14 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, * For full updates case when * removing/adding/updateding streams on once CRTC while flipping * on another CRTC, - * Adding all current active CRTC's states to the atomic commit in - * amdgpu_dm_atomic_check will guarantee that any such full update commit + * acquiring global lock will guarantee that any such full + * update commit * will wait for completion of any outstanding flip using DRMs * synchronization events. */ - if (wait_for_prev_commits) { - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - struct drm_crtc_state *crtc_state; - - if (acrtc->stream) { - crtc_state = drm_atomic_get_crtc_state(state, crtc); - if (IS_ERR(crtc_state)) { - ret = PTR_ERR(crtc_state); - break; - } - } - } - } + if (wait_for_prev_commits) + aquire_global_lock(dev, state); + } if (context) { -- cgit From 92af86fa7cba07aeec2f5f455b5ad981aff6013d Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Tue, 20 Jun 2017 10:56:35 -0400 Subject: drm/amd/display: Remove check update type function. Due to using dc_commit_surface_to_stream instead of build stream and surface updates any surface commit today is evlauted to full. Until we fix this and can corretly evluate type of surface update, anything which is not page flip or cursor update will be treted as full update chnage and global lock will be aquired. Signed-off-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 80 +++------------------- 1 file changed, 8 insertions(+), 72 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index db38dd0a0c1f..7e0e6b2f22f6 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2838,63 +2838,11 @@ static uint32_t remove_from_val_sets( return set_count; } - -static enum surface_update_type amdgpu_dm_check_surfaces_update_type( - struct dc *dc, - const struct dc_surface **new_surfaces, - uint8_t new_surface_count, - const struct dc_stream *dc_stream) -{ - struct dc_surface_update srf_updates[MAX_SURFACES]; - struct dc_flip_addrs flip_addr[MAX_SURFACES]; - struct dc_plane_info plane_info[MAX_SURFACES]; - struct dc_scaling_info scaling_info[MAX_SURFACES]; - int i; - const struct dc_stream_status *stream_status = - dc_stream_get_status(dc_stream); - enum surface_update_type update_type; - - memset(srf_updates, 0, sizeof(srf_updates)); - memset(flip_addr, 0, sizeof(flip_addr)); - memset(plane_info, 0, sizeof(plane_info)); - memset(scaling_info, 0, sizeof(scaling_info)); - - for (i = 0; i < new_surface_count; i++) { - srf_updates[i].surface = new_surfaces[i]; - srf_updates[i].gamma = - (struct dc_gamma *)new_surfaces[i]->gamma_correction; - flip_addr[i].address = new_surfaces[i]->address; - flip_addr[i].flip_immediate = new_surfaces[i]->flip_immediate; - plane_info[i].color_space = new_surfaces[i]->color_space; - plane_info[i].format = new_surfaces[i]->format; - plane_info[i].plane_size = new_surfaces[i]->plane_size; - plane_info[i].rotation = new_surfaces[i]->rotation; - plane_info[i].horizontal_mirror = new_surfaces[i]->horizontal_mirror; - plane_info[i].stereo_format = new_surfaces[i]->stereo_format; - plane_info[i].tiling_info = new_surfaces[i]->tiling_info; - plane_info[i].visible = new_surfaces[i]->visible; - plane_info[i].dcc = new_surfaces[i]->dcc; - scaling_info[i].scaling_quality = new_surfaces[i]->scaling_quality; - scaling_info[i].src_rect = new_surfaces[i]->src_rect; - scaling_info[i].dst_rect = new_surfaces[i]->dst_rect; - scaling_info[i].clip_rect = new_surfaces[i]->clip_rect; - - srf_updates[i].flip_addr = &flip_addr[i]; - srf_updates[i].plane_info = &plane_info[i]; - srf_updates[i].scaling_info = &scaling_info[i]; - } - - update_type = dc_check_update_surfaces_for_stream( - dc, srf_updates, new_surface_count, NULL, stream_status); - - return update_type; -} - /*` * Grabs all modesetting locks to serialize against any blocking commits, * Waits for completion of all non blocking commits. */ -static void aquire_global_lock( +static void do_aquire_global_lock( struct drm_device *dev, struct drm_atomic_state *state) { @@ -2957,7 +2905,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, * This bool will be set for true for any modeset/reset * or surface update which implies non fast surfae update. */ - bool wait_for_prev_commits = false; + bool aquire_global_lock = false; ret = drm_atomic_helper_check(dev, state); @@ -3042,7 +2990,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, new_stream_count++; need_to_validate = true; - wait_for_prev_commits = true; + aquire_global_lock = true; } else if (modereset_required(crtc_state)) { @@ -3052,7 +3000,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, set, set_count, acrtc->stream); - wait_for_prev_commits = true; + aquire_global_lock = true; } } @@ -3111,7 +3059,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, new_stream_count++; need_to_validate = true; - wait_for_prev_commits = true; + aquire_global_lock = true; } for (i = 0; i < set_count; i++) { @@ -3177,25 +3125,13 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, surface); need_to_validate = true; + aquire_global_lock = true; } } } context = dc_get_validate_context(dc, set, set_count); - for (i = 0; i < set_count; i++) { - for (j = 0; j < set[i].surface_count; j++) { - if (amdgpu_dm_check_surfaces_update_type( - dc, - set[i].surfaces, - set[i].surface_count, - set[i].stream) > UPDATE_TYPE_FAST) { - wait_for_prev_commits = true; - break; - } - } - } - if (need_to_validate == false || set_count == 0 || context) { ret = 0; @@ -3208,8 +3144,8 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, * will wait for completion of any outstanding flip using DRMs * synchronization events. */ - if (wait_for_prev_commits) - aquire_global_lock(dev, state); + if (aquire_global_lock) + do_aquire_global_lock(dev, state); } -- cgit From cb26f8925c50aa244ac34a72ac232e4c7dbd6f98 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Tue, 20 Jun 2017 17:24:23 -0400 Subject: drm/amd/display: use different sr latencies for dpm0 dcn bw calc Signed-off-by: Dmytro Laktyushkin Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 0aa6662650cc..9cb08365e2b6 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -906,6 +906,16 @@ bool dcn_validate_bandwidth( scaler_settings_calculation(v); mode_support_and_system_configuration(v); + if (v->voltage_level == 0) { + struct core_dc *dc_core = DC_TO_CORE(&dc->public); + + v->sr_enter_plus_exit_time = 9.466f; + v->sr_exit_time = 7.849f; + dc_core->dml.soc.sr_enter_plus_exit_time_us = v->sr_enter_plus_exit_time; + dc_core->dml.soc.sr_exit_time_us = v->sr_exit_time; + mode_support_and_system_configuration(v); + } + if (v->voltage_level != 5) { float bw_consumed = v->total_bandwidth_consumed_gbyte_per_second; if (bw_consumed < v->fabric_and_dram_bandwidth_vmin0p65) @@ -1013,6 +1023,14 @@ bool dcn_validate_bandwidth( &dc->dml, context, pool); } + if (v->voltage_level == 0) { + struct core_dc *dc_core = DC_TO_CORE(&dc->public); + + dc_core->dml.soc.sr_enter_plus_exit_time_us = + dc_core->dcn_soc.sr_enter_plus_exit_time; + dc_core->dml.soc.sr_exit_time_us = dc_core->dcn_soc.sr_exit_time; + } + kernel_fpu_end(); return v->voltage_level != 5; } -- cgit From 139cb65c5202ba5074d52226931a7d4aaa3307bc Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 21 Jun 2017 09:35:35 -0400 Subject: drm/amd/display: make variable latency into a regkey option Signed-off-by: Dmytro Laktyushkin Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 11 ++++++++--- drivers/gpu/drm/amd/display/dc/dc.h | 2 ++ 2 files changed, 10 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 9cb08365e2b6..3ec702fecfd1 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -906,11 +906,16 @@ bool dcn_validate_bandwidth( scaler_settings_calculation(v); mode_support_and_system_configuration(v); - if (v->voltage_level == 0) { + if (v->voltage_level == 0 && + (dc->public.debug.sr_exit_time_dpm0_ns + || dc->public.debug.sr_enter_plus_exit_time_dpm0_ns)) { struct core_dc *dc_core = DC_TO_CORE(&dc->public); - v->sr_enter_plus_exit_time = 9.466f; - v->sr_exit_time = 7.849f; + if (dc->public.debug.sr_enter_plus_exit_time_dpm0_ns) + v->sr_enter_plus_exit_time = + dc->public.debug.sr_enter_plus_exit_time_dpm0_ns / 1000.0f; + if (dc->public.debug.sr_exit_time_dpm0_ns) + v->sr_exit_time = dc->public.debug.sr_exit_time_dpm0_ns / 1000.0f; dc_core->dml.soc.sr_enter_plus_exit_time_us = v->sr_enter_plus_exit_time; dc_core->dml.soc.sr_exit_time_us = v->sr_exit_time; mode_support_and_system_configuration(v); diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 62493c4a47d1..cb70b6d8be10 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -171,6 +171,8 @@ struct dc_debug { bool disable_pplib_wm_range; bool use_dml_wm; bool disable_pipe_split; + int sr_exit_time_dpm0_ns; + int sr_enter_plus_exit_time_dpm0_ns; int sr_exit_time_ns; int sr_enter_plus_exit_time_ns; int urgent_latency_ns; -- cgit From 5634fb6078dd9b9f794e93eef2fef52150cdc827 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Thu, 15 Jun 2017 14:10:43 -0400 Subject: drm/amd/display: dcn bw_calc_auto update rev 247 to 250 Signed-off-by: Dmytro Laktyushkin Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c | 3535 +++++--------------- 1 file changed, 897 insertions(+), 2638 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c index 21b83e403ef2..bb2f8ad6a988 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c @@ -27,32 +27,27 @@ #include "dcn_calc_auto.h" #include "dcn_calc_math.h" -/*REVISION#247*/ +/*REVISION#250*/ void scaler_settings_calculation(struct dcn_bw_internal_vars *v) { int k; - /*scaler settings calculation*/ - - /*scale ratio calculation*/ - for (k = 0; k <= v->number_of_active_planes - 1; k++) { if (v->allow_different_hratio_vratio == dcn_bw_yes) { if (v->source_scan[k] == dcn_bw_hor) { v->h_ratio[k] = v->viewport_width[k] / v->scaler_rec_out_width[k]; v->v_ratio[k] = v->viewport_height[k] / v->scaler_recout_height[k]; - } else { + } + else { v->h_ratio[k] = v->viewport_height[k] / v->scaler_rec_out_width[k]; v->v_ratio[k] = v->viewport_width[k] / v->scaler_recout_height[k]; } - } else { + } + else { if (v->source_scan[k] == dcn_bw_hor) { - v->h_ratio[k] = dcn_bw_max2( - v->viewport_width[k] / v->scaler_rec_out_width[k], - v->viewport_height[k] / v->scaler_recout_height[k]); - } else { - v->h_ratio[k] = dcn_bw_max2( - v->viewport_height[k] / v->scaler_rec_out_width[k], - v->viewport_width[k] / v->scaler_recout_height[k]); + v->h_ratio[k] =dcn_bw_max2(v->viewport_width[k] / v->scaler_rec_out_width[k], v->viewport_height[k] / v->scaler_recout_height[k]); + } + else { + v->h_ratio[k] =dcn_bw_max2(v->viewport_height[k] / v->scaler_rec_out_width[k], v->viewport_width[k] / v->scaler_recout_height[k]); } v->v_ratio[k] = v->h_ratio[k]; } @@ -68,66 +63,64 @@ void scaler_settings_calculation(struct dcn_bw_internal_vars *v) for (k = 0; k <= v->number_of_active_planes - 1; k++) { if (v->h_ratio[k] > 1.0) { - v->acceptable_quality_hta_ps = dcn_bw_min2( - v->max_hscl_taps, - 2.0 * dcn_bw_ceil2(v->h_ratio[k], 1.0)); - } else if (v->h_ratio[k] < 1.0) { + v->acceptable_quality_hta_ps =dcn_bw_min2(v->max_hscl_taps, 2.0 *dcn_bw_ceil2(v->h_ratio[k], 1.0)); + } + else if (v->h_ratio[k] < 1.0) { v->acceptable_quality_hta_ps = 4.0; - } else { + } + else { v->acceptable_quality_hta_ps = 1.0; } if (v->ta_pscalculation == dcn_bw_override) { v->htaps[k] = v->override_hta_ps[k]; - } else { + } + else { v->htaps[k] = v->acceptable_quality_hta_ps; } if (v->v_ratio[k] > 1.0) { - v->acceptable_quality_vta_ps = dcn_bw_min2( - v->max_vscl_taps, - 2.0 * dcn_bw_ceil2(v->v_ratio[k], 1.0)); - } else if (v->v_ratio[k] < 1.0) { + v->acceptable_quality_vta_ps =dcn_bw_min2(v->max_vscl_taps, 2.0 *dcn_bw_ceil2(v->v_ratio[k], 1.0)); + } + else if (v->v_ratio[k] < 1.0) { v->acceptable_quality_vta_ps = 4.0; - } else { + } + else { v->acceptable_quality_vta_ps = 1.0; } if (v->ta_pscalculation == dcn_bw_override) { v->vtaps[k] = v->override_vta_ps[k]; - } else { + } + else { v->vtaps[k] = v->acceptable_quality_vta_ps; } - if (v->source_pixel_format[k] == dcn_bw_rgb_sub_64 - || v->source_pixel_format[k] == dcn_bw_rgb_sub_32 - || v->source_pixel_format[k] == dcn_bw_rgb_sub_16) { + if (v->source_pixel_format[k] == dcn_bw_rgb_sub_64 || v->source_pixel_format[k] == dcn_bw_rgb_sub_32 || v->source_pixel_format[k] == dcn_bw_rgb_sub_16) { v->vta_pschroma[k] = 0.0; v->hta_pschroma[k] = 0.0; - } else { + } + else { if (v->ta_pscalculation == dcn_bw_override) { v->vta_pschroma[k] = v->override_vta_pschroma[k]; v->hta_pschroma[k] = v->override_hta_pschroma[k]; - } else { + } + else { v->vta_pschroma[k] = v->acceptable_quality_vta_ps; v->hta_pschroma[k] = v->acceptable_quality_hta_ps; } } } } + void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v) { - int i, j, k; + int i; + int j; + int k; /*mode support, voltage state and soc configuration*/ /*scale ratio support check*/ v->scale_ratio_support = dcn_bw_yes; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - if (v->h_ratio[k] > v->max_hscl_ratio || v->v_ratio[k] > v->max_vscl_ratio - || v->h_ratio[k] > v->htaps[k] || v->v_ratio[k] > v->vtaps[k] - || (v->source_pixel_format[k] != dcn_bw_rgb_sub_64 - && v->source_pixel_format[k] != dcn_bw_rgb_sub_32 - && v->source_pixel_format[k] != dcn_bw_rgb_sub_16 - && (v->h_ratio[k] / 2.0 > v->hta_pschroma[k] - || v->v_ratio[k] / 2.0 - > v->vta_pschroma[k]))) { + if (v->h_ratio[k] > v->max_hscl_ratio || v->v_ratio[k] > v->max_vscl_ratio || v->h_ratio[k] > v->htaps[k] || v->v_ratio[k] > v->vtaps[k] || (v->source_pixel_format[k] != dcn_bw_rgb_sub_64 && v->source_pixel_format[k] != dcn_bw_rgb_sub_32 && v->source_pixel_format[k] != dcn_bw_rgb_sub_16 && (v->h_ratio[k] / 2.0 > v->hta_pschroma[k] || v->v_ratio[k] / 2.0 > v->vta_pschroma[k]))) { v->scale_ratio_support = dcn_bw_no; } } @@ -135,16 +128,7 @@ void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v) v->source_format_pixel_and_scan_support = dcn_bw_yes; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - if ((v->source_surface_mode[k] == dcn_bw_sw_linear - && v->source_scan[k] != dcn_bw_hor) - || ((v->source_surface_mode[k] == dcn_bw_sw_4_kb_d - || v->source_surface_mode[k] == dcn_bw_sw_4_kb_d_x - || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d - || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_t - || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_x - || v->source_surface_mode[k] == dcn_bw_sw_var_d - || v->source_surface_mode[k] == dcn_bw_sw_var_d_x) - && v->source_pixel_format[k] != dcn_bw_rgb_sub_64)) { + if ((v->source_surface_mode[k] == dcn_bw_sw_linear && !v->source_scan[k] == dcn_bw_hor) || ((v->source_surface_mode[k] == dcn_bw_sw_4_kb_d || v->source_surface_mode[k] == dcn_bw_sw_4_kb_d_x || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_t || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_x || v->source_surface_mode[k] == dcn_bw_sw_var_d || v->source_surface_mode[k] == dcn_bw_sw_var_d_x) && !v->source_pixel_format[k] == dcn_bw_rgb_sub_64)) { v->source_format_pixel_and_scan_support = dcn_bw_no; } } @@ -153,77 +137,62 @@ void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v) for (k = 0; k <= v->number_of_active_planes - 1; k++) { if (v->source_scan[k] == dcn_bw_hor) { v->swath_width_ysingle_dpp[k] = v->viewport_width[k]; - } else { + } + else { v->swath_width_ysingle_dpp[k] = v->viewport_height[k]; } if (v->source_pixel_format[k] == dcn_bw_rgb_sub_64) { v->byte_per_pixel_in_dety[k] = 8.0; v->byte_per_pixel_in_detc[k] = 0.0; - } else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_32) { + } + else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_32) { v->byte_per_pixel_in_dety[k] = 4.0; v->byte_per_pixel_in_detc[k] = 0.0; - } else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_16) { + } + else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_16) { v->byte_per_pixel_in_dety[k] = 2.0; v->byte_per_pixel_in_detc[k] = 0.0; - } else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_8) { + } + else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_8) { v->byte_per_pixel_in_dety[k] = 1.0; v->byte_per_pixel_in_detc[k] = 2.0; - } else { - v->byte_per_pixel_in_dety[k] = 4.0f / 3; - v->byte_per_pixel_in_detc[k] = 8.0f / 3; + } + else { + v->byte_per_pixel_in_dety[k] = 4.0f / 3.0f; + v->byte_per_pixel_in_detc[k] = 8.0f / 3.0f; } } v->total_read_bandwidth_consumed_gbyte_per_second = 0.0; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - v->read_bandwidth[k] = v->swath_width_ysingle_dpp[k] - * (dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) * v->v_ratio[k] - + dcn_bw_ceil2(v->byte_per_pixel_in_detc[k], 2.0) / 2.0 - * v->v_ratio[k] / 2) - / (v->htotal[k] / v->pixel_clock[k]); + v->read_bandwidth[k] = v->swath_width_ysingle_dpp[k] * (dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) * v->v_ratio[k] +dcn_bw_ceil2(v->byte_per_pixel_in_detc[k], 2.0) / 2.0 * v->v_ratio[k] / 2) / (v->htotal[k] / v->pixel_clock[k]); if (v->dcc_enable[k] == dcn_bw_yes) { v->read_bandwidth[k] = v->read_bandwidth[k] * (1 + 1 / 256); } - if (v->pte_enable == dcn_bw_yes && v->source_scan[k] != dcn_bw_hor - && (v->source_surface_mode[k] == dcn_bw_sw_4_kb_s - || v->source_surface_mode[k] == dcn_bw_sw_4_kb_s_x - || v->source_surface_mode[k] == dcn_bw_sw_4_kb_d - || v->source_surface_mode[k] == dcn_bw_sw_4_kb_d_x)) { + if (v->pte_enable == dcn_bw_yes && v->source_scan[k] != dcn_bw_hor && (v->source_surface_mode[k] == dcn_bw_sw_4_kb_s || v->source_surface_mode[k] == dcn_bw_sw_4_kb_s_x || v->source_surface_mode[k] == dcn_bw_sw_4_kb_d || v->source_surface_mode[k] == dcn_bw_sw_4_kb_d_x)) { v->read_bandwidth[k] = v->read_bandwidth[k] * (1 + 1 / 64); - } else if (v->pte_enable == dcn_bw_yes && v->source_scan[k] == dcn_bw_hor - && (v->source_pixel_format[k] == dcn_bw_rgb_sub_64 - || v->source_pixel_format[k] == dcn_bw_rgb_sub_32) - && (v->source_surface_mode[k] == dcn_bw_sw_64_kb_s - || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_t - || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_x - || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d - || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_t - || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_x)) { + } + else if (v->pte_enable == dcn_bw_yes && v->source_scan[k] == dcn_bw_hor && (v->source_pixel_format[k] == dcn_bw_rgb_sub_64 || v->source_pixel_format[k] == dcn_bw_rgb_sub_32) && (v->source_surface_mode[k] == dcn_bw_sw_64_kb_s || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_t || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_x || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_t || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_x)) { v->read_bandwidth[k] = v->read_bandwidth[k] * (1 + 1 / 256); - } else if (v->pte_enable == dcn_bw_yes) { + } + else if (v->pte_enable == dcn_bw_yes) { v->read_bandwidth[k] = v->read_bandwidth[k] * (1 + 1 / 512); } - v->total_read_bandwidth_consumed_gbyte_per_second = - v->total_read_bandwidth_consumed_gbyte_per_second - + v->read_bandwidth[k] / 1000.0; + v->total_read_bandwidth_consumed_gbyte_per_second = v->total_read_bandwidth_consumed_gbyte_per_second + v->read_bandwidth[k] / 1000.0; } v->total_write_bandwidth_consumed_gbyte_per_second = 0.0; for (k = 0; k <= v->number_of_active_planes - 1; k++) { if (v->output[k] == dcn_bw_writeback && v->output_format[k] == dcn_bw_444) { - v->write_bandwidth[k] = v->scaler_rec_out_width[k] - / (v->htotal[k] / v->pixel_clock[k]) * 4.0; - } else if (v->output[k] == dcn_bw_writeback) { - v->write_bandwidth[k] = v->scaler_rec_out_width[k] - / (v->htotal[k] / v->pixel_clock[k]) * 1.5; - } else { + v->write_bandwidth[k] = v->scaler_rec_out_width[k] / (v->htotal[k] / v->pixel_clock[k]) * 4.0; + } + else if (v->output[k] == dcn_bw_writeback) { + v->write_bandwidth[k] = v->scaler_rec_out_width[k] / (v->htotal[k] / v->pixel_clock[k]) * 1.5; + } + else { v->write_bandwidth[k] = 0.0; } - v->total_write_bandwidth_consumed_gbyte_per_second = - v->total_write_bandwidth_consumed_gbyte_per_second - + v->write_bandwidth[k] / 1000.0; + v->total_write_bandwidth_consumed_gbyte_per_second = v->total_write_bandwidth_consumed_gbyte_per_second + v->write_bandwidth[k] / 1000.0; } - v->total_bandwidth_consumed_gbyte_per_second = - v->total_read_bandwidth_consumed_gbyte_per_second - + v->total_write_bandwidth_consumed_gbyte_per_second; + v->total_bandwidth_consumed_gbyte_per_second = v->total_read_bandwidth_consumed_gbyte_per_second + v->total_write_bandwidth_consumed_gbyte_per_second; v->dcc_enabled_in_any_plane = dcn_bw_no; for (k = 0; k <= v->number_of_active_planes - 1; k++) { if (v->dcc_enable[k] == dcn_bw_yes) { @@ -231,119 +200,29 @@ void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v) } } for (i = 0; i <= number_of_states_plus_one; i++) { - v->return_bw_todcn_per_state = - dcn_bw_min2( - v->return_bus_width * v->dcfclk_per_state[i], - v->fabric_and_dram_bandwidth_per_state[i] * 1000.0 - * v->percent_of_ideal_drambw_received_after_urg_latency - / 100.0); + v->return_bw_todcn_per_state =dcn_bw_min2(v->return_bus_width * v->dcfclk_per_state[i], v->fabric_and_dram_bandwidth_per_state[i] * 1000.0 * v->percent_of_ideal_drambw_received_after_urg_latency / 100.0); v->return_bw_per_state[i] = v->return_bw_todcn_per_state; - if (v->dcc_enabled_in_any_plane == dcn_bw_yes - && v->return_bw_todcn_per_state - > v->dcfclk_per_state[i] * v->return_bus_width - / 4.0) { - v->return_bw_per_state[i] = - dcn_bw_min2( - v->return_bw_per_state[i], - v->return_bw_todcn_per_state * 4.0 - * (1.0 - - v->urgent_latency - / ((v->rob_buffer_size_in_kbyte - - v->pixel_chunk_size_in_kbyte) - * 1024.0 - / (v->return_bw_todcn_per_state - - v->dcfclk_per_state[i] - * v->return_bus_width - / 4.0) - + v->urgent_latency))); - } - v->critical_point = 2.0 * v->return_bus_width * v->dcfclk_per_state[i] - * v->urgent_latency - / (v->return_bw_todcn_per_state * v->urgent_latency - + (v->rob_buffer_size_in_kbyte - - v->pixel_chunk_size_in_kbyte) - * 1024.0); - if (v->dcc_enabled_in_any_plane == dcn_bw_yes && v->critical_point > 1.0 - && v->critical_point < 4.0) { - v->return_bw_per_state[i] = - dcn_bw_min2( - v->return_bw_per_state[i], - dcn_bw_pow( - 4.0 - * v->return_bw_todcn_per_state - * (v->rob_buffer_size_in_kbyte - - v->pixel_chunk_size_in_kbyte) - * 1024.0 - * v->return_bus_width - * v->dcfclk_per_state[i] - * v->urgent_latency - / (v->return_bw_todcn_per_state - * v->urgent_latency - + (v->rob_buffer_size_in_kbyte - - v->pixel_chunk_size_in_kbyte) - * 1024.0), - 2)); - } - v->return_bw_todcn_per_state = dcn_bw_min2( - v->return_bus_width * v->dcfclk_per_state[i], - v->fabric_and_dram_bandwidth_per_state[i] * 1000.0); - if (v->dcc_enabled_in_any_plane == dcn_bw_yes - && v->return_bw_todcn_per_state - > v->dcfclk_per_state[i] * v->return_bus_width - / 4.0) { - v->return_bw_per_state[i] = - dcn_bw_min2( - v->return_bw_per_state[i], - v->return_bw_todcn_per_state * 4.0 - * (1.0 - - v->urgent_latency - / ((v->rob_buffer_size_in_kbyte - - v->pixel_chunk_size_in_kbyte) - * 1024.0 - / (v->return_bw_todcn_per_state - - v->dcfclk_per_state[i] - * v->return_bus_width - / 4.0) - + v->urgent_latency))); - } - v->critical_point = 2.0 * v->return_bus_width * v->dcfclk_per_state[i] - * v->urgent_latency - / (v->return_bw_todcn_per_state * v->urgent_latency - + (v->rob_buffer_size_in_kbyte - - v->pixel_chunk_size_in_kbyte) - * 1024.0); - if (v->dcc_enabled_in_any_plane == dcn_bw_yes && v->critical_point > 1.0 - && v->critical_point < 4.0) { - v->return_bw_per_state[i] = - dcn_bw_min2( - v->return_bw_per_state[i], - dcn_bw_pow( - 4.0 - * v->return_bw_todcn_per_state - * (v->rob_buffer_size_in_kbyte - - v->pixel_chunk_size_in_kbyte) - * 1024.0 - * v->return_bus_width - * v->dcfclk_per_state[i] - * v->urgent_latency - / (v->return_bw_todcn_per_state - * v->urgent_latency - + (v->rob_buffer_size_in_kbyte - - v->pixel_chunk_size_in_kbyte) - * 1024.0), - 2)); + if (v->dcc_enabled_in_any_plane == dcn_bw_yes && v->return_bw_todcn_per_state > v->dcfclk_per_state[i] * v->return_bus_width / 4.0) { + v->return_bw_per_state[i] =dcn_bw_min2(v->return_bw_per_state[i], v->return_bw_todcn_per_state * 4.0 * (1.0 - v->urgent_latency / ((v->rob_buffer_size_in_kbyte - v->pixel_chunk_size_in_kbyte) * 1024.0 / (v->return_bw_todcn_per_state - v->dcfclk_per_state[i] * v->return_bus_width / 4.0) + v->urgent_latency))); + } + v->critical_point = 2.0 * v->return_bus_width * v->dcfclk_per_state[i] * v->urgent_latency / (v->return_bw_todcn_per_state * v->urgent_latency + (v->rob_buffer_size_in_kbyte - v->pixel_chunk_size_in_kbyte) * 1024.0); + if (v->dcc_enabled_in_any_plane == dcn_bw_yes && v->critical_point > 1.0 && v->critical_point < 4.0) { + v->return_bw_per_state[i] =dcn_bw_min2(v->return_bw_per_state[i], dcn_bw_pow(4.0 * v->return_bw_todcn_per_state * (v->rob_buffer_size_in_kbyte - v->pixel_chunk_size_in_kbyte) * 1024.0 * v->return_bus_width * v->dcfclk_per_state[i] * v->urgent_latency / (v->return_bw_todcn_per_state * v->urgent_latency + (v->rob_buffer_size_in_kbyte - v->pixel_chunk_size_in_kbyte) * 1024.0), 2)); + } + v->return_bw_todcn_per_state =dcn_bw_min2(v->return_bus_width * v->dcfclk_per_state[i], v->fabric_and_dram_bandwidth_per_state[i] * 1000.0); + if (v->dcc_enabled_in_any_plane == dcn_bw_yes && v->return_bw_todcn_per_state > v->dcfclk_per_state[i] * v->return_bus_width / 4.0) { + v->return_bw_per_state[i] =dcn_bw_min2(v->return_bw_per_state[i], v->return_bw_todcn_per_state * 4.0 * (1.0 - v->urgent_latency / ((v->rob_buffer_size_in_kbyte - v->pixel_chunk_size_in_kbyte) * 1024.0 / (v->return_bw_todcn_per_state - v->dcfclk_per_state[i] * v->return_bus_width / 4.0) + v->urgent_latency))); + } + v->critical_point = 2.0 * v->return_bus_width * v->dcfclk_per_state[i] * v->urgent_latency / (v->return_bw_todcn_per_state * v->urgent_latency + (v->rob_buffer_size_in_kbyte - v->pixel_chunk_size_in_kbyte) * 1024.0); + if (v->dcc_enabled_in_any_plane == dcn_bw_yes && v->critical_point > 1.0 && v->critical_point < 4.0) { + v->return_bw_per_state[i] =dcn_bw_min2(v->return_bw_per_state[i], dcn_bw_pow(4.0 * v->return_bw_todcn_per_state * (v->rob_buffer_size_in_kbyte - v->pixel_chunk_size_in_kbyte) * 1024.0 * v->return_bus_width * v->dcfclk_per_state[i] * v->urgent_latency / (v->return_bw_todcn_per_state * v->urgent_latency + (v->rob_buffer_size_in_kbyte - v->pixel_chunk_size_in_kbyte) * 1024.0), 2)); } } for (i = 0; i <= number_of_states_plus_one; i++) { - if ((v->total_read_bandwidth_consumed_gbyte_per_second * 1000.0 - <= v->return_bw_per_state[i]) - && (v->total_bandwidth_consumed_gbyte_per_second * 1000.0 - <= v->fabric_and_dram_bandwidth_per_state[i] - * 1000.0 - * v->percent_of_ideal_drambw_received_after_urg_latency - / 100.0)) { + if ((v->total_read_bandwidth_consumed_gbyte_per_second * 1000.0 <= v->return_bw_per_state[i]) && (v->total_bandwidth_consumed_gbyte_per_second * 1000.0 <= v->fabric_and_dram_bandwidth_per_state[i] * 1000.0 * v->percent_of_ideal_drambw_received_after_urg_latency / 100.0)) { v->bandwidth_support[i] = dcn_bw_yes; - } else { + } + else { v->bandwidth_support[i] = dcn_bw_no; } } @@ -351,36 +230,21 @@ void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v) v->writeback_latency_support = dcn_bw_yes; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - if (v->output[k] == dcn_bw_writeback && v->output_format[k] == dcn_bw_444 - && v->scaler_rec_out_width[k] / (v->htotal[k] / v->pixel_clock[k]) - * 4.0 - > (v->writeback_luma_buffer_size - + v->writeback_chroma_buffer_size) - * 1024.0 / v->write_back_latency) { + if (v->output[k] == dcn_bw_writeback && v->output_format[k] == dcn_bw_444 && v->scaler_rec_out_width[k] / (v->htotal[k] / v->pixel_clock[k]) * 4.0 > (v->writeback_luma_buffer_size + v->writeback_chroma_buffer_size) * 1024.0 / v->write_back_latency) { v->writeback_latency_support = dcn_bw_no; - } else if (v->output[k] == dcn_bw_writeback - && v->scaler_rec_out_width[k] / (v->htotal[k] / v->pixel_clock[k]) - > dcn_bw_min2( - v->writeback_luma_buffer_size, - 2.0 - * v->writeback_chroma_buffer_size) - * 1024.0 / v->write_back_latency) { + } + else if (v->output[k] == dcn_bw_writeback && v->scaler_rec_out_width[k] / (v->htotal[k] / v->pixel_clock[k]) >dcn_bw_min2(v->writeback_luma_buffer_size, 2.0 * v->writeback_chroma_buffer_size) * 1024.0 / v->write_back_latency) { v->writeback_latency_support = dcn_bw_no; } } /*re-ordering buffer support check*/ for (i = 0; i <= number_of_states_plus_one; i++) { - v->urgent_round_trip_and_out_of_order_latency_per_state[i] = - (v->round_trip_ping_latency_cycles + 32.0) / v->dcfclk_per_state[i] - + v->urgent_out_of_order_return_per_channel - * v->number_of_channels - / v->return_bw_per_state[i]; - if ((v->rob_buffer_size_in_kbyte - v->pixel_chunk_size_in_kbyte) * 1024.0 - / v->return_bw_per_state[i] - > v->urgent_round_trip_and_out_of_order_latency_per_state[i]) { + v->urgent_round_trip_and_out_of_order_latency_per_state[i] = (v->round_trip_ping_latency_cycles + 32.0) / v->dcfclk_per_state[i] + v->urgent_out_of_order_return_per_channel * v->number_of_channels / v->return_bw_per_state[i]; + if ((v->rob_buffer_size_in_kbyte - v->pixel_chunk_size_in_kbyte) * 1024.0 / v->return_bw_per_state[i] > v->urgent_round_trip_and_out_of_order_latency_per_state[i]) { v->rob_support[i] = dcn_bw_yes; - } else { + } + else { v->rob_support[i] = dcn_bw_no; } } @@ -390,28 +254,31 @@ void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v) if (v->output[k] == dcn_bw_dp && v->dsc_capability == dcn_bw_yes) { if (v->output_format[k] == dcn_bw_420) { v->required_output_bw = v->pixel_clock[k] / 2.0; - } else { + } + else { v->required_output_bw = v->pixel_clock[k]; } - } else if (v->output_format[k] == dcn_bw_420) { + } + else if (v->output_format[k] == dcn_bw_420) { v->required_output_bw = v->pixel_clock[k] * 3.0 / 2.0; - } else { + } + else { v->required_output_bw = v->pixel_clock[k] * 3.0; } if (v->output[k] == dcn_bw_hdmi) { v->required_phyclk[k] = v->required_output_bw / 3.0; - } else if (v->output[k] == dcn_bw_dp) { + } + else if (v->output[k] == dcn_bw_dp) { v->required_phyclk[k] = v->required_output_bw / 4.0; - } else { + } + else { v->required_phyclk[k] = 0.0; } } for (i = 0; i <= number_of_states_plus_one; i++) { v->dio_support[i] = dcn_bw_yes; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - if (v->required_phyclk[k] > v->phyclk_per_state[i] - || (v->output[k] == dcn_bw_hdmi - && v->required_phyclk[k] > 600.0)) { + if (v->required_phyclk[k] > v->phyclk_per_state[i] || (v->output[k] == dcn_bw_hdmi && v->required_phyclk[k] > 600.0)) { v->dio_support[i] = dcn_bw_no; } } @@ -421,244 +288,128 @@ void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v) v->total_number_of_active_writeback = 0.0; for (k = 0; k <= v->number_of_active_planes - 1; k++) { if (v->output[k] == dcn_bw_writeback) { - v->total_number_of_active_writeback = v->total_number_of_active_writeback - + 1.0; + v->total_number_of_active_writeback = v->total_number_of_active_writeback + 1.0; } } if (v->total_number_of_active_writeback <= v->max_num_writeback) { v->total_available_writeback_support = dcn_bw_yes; - } else { + } + else { v->total_available_writeback_support = dcn_bw_no; } /*maximum dispclk/dppclk support check*/ for (k = 0; k <= v->number_of_active_planes - 1; k++) { if (v->h_ratio[k] > 1.0) { - v->pscl_factor[k] = dcn_bw_min2( - v->max_dchub_topscl_throughput, - v->max_pscl_tolb_throughput * v->h_ratio[k] - / dcn_bw_ceil2(v->htaps[k] / 6.0, 1.0)); - } else { - v->pscl_factor[k] = dcn_bw_min2( - v->max_dchub_topscl_throughput, - v->max_pscl_tolb_throughput); + v->pscl_factor[k] =dcn_bw_min2(v->max_dchub_topscl_throughput, v->max_pscl_tolb_throughput * v->h_ratio[k] /dcn_bw_ceil2(v->htaps[k] / 6.0, 1.0)); + } + else { + v->pscl_factor[k] =dcn_bw_min2(v->max_dchub_topscl_throughput, v->max_pscl_tolb_throughput); } if (v->byte_per_pixel_in_detc[k] == 0.0) { v->pscl_factor_chroma[k] = 0.0; - v->min_dppclk_using_single_dpp[k] = - v->pixel_clock[k] - * dcn_bw_max3( - v->vtaps[k] / 6.0 - * dcn_bw_min2( - 1.0, - v->h_ratio[k]), - v->h_ratio[k] - * v->v_ratio[k] - / v->pscl_factor[k], - 1.0); - } else { + v->min_dppclk_using_single_dpp[k] = v->pixel_clock[k] *dcn_bw_max3(v->vtaps[k] / 6.0 *dcn_bw_min2(1.0, v->h_ratio[k]), v->h_ratio[k] * v->v_ratio[k] / v->pscl_factor[k], 1.0); + } + else { if (v->h_ratio[k] / 2.0 > 1.0) { - v->pscl_factor_chroma[k] = - dcn_bw_min2( - v->max_dchub_topscl_throughput, - v->max_pscl_tolb_throughput - * v->h_ratio[k] - / 2.0 - / dcn_bw_ceil2( - v->hta_pschroma[k] - / 6.0, - 1.0)); - } else { - v->pscl_factor_chroma[k] = dcn_bw_min2( - v->max_dchub_topscl_throughput, - v->max_pscl_tolb_throughput); - } - v->min_dppclk_using_single_dpp[k] = - v->pixel_clock[k] - * dcn_bw_max5( - v->vtaps[k] / 6.0 - * dcn_bw_min2( - 1.0, - v->h_ratio[k]), - v->h_ratio[k] - * v->v_ratio[k] - / v->pscl_factor[k], - v->vta_pschroma[k] / 6.0 - * dcn_bw_min2( - 1.0, - v->h_ratio[k] - / 2.0), - v->h_ratio[k] - * v->v_ratio[k] - / 4.0 - / v->pscl_factor_chroma[k], - 1.0); + v->pscl_factor_chroma[k] =dcn_bw_min2(v->max_dchub_topscl_throughput, v->max_pscl_tolb_throughput * v->h_ratio[k] / 2.0 /dcn_bw_ceil2(v->hta_pschroma[k] / 6.0, 1.0)); + } + else { + v->pscl_factor_chroma[k] =dcn_bw_min2(v->max_dchub_topscl_throughput, v->max_pscl_tolb_throughput); + } + v->min_dppclk_using_single_dpp[k] = v->pixel_clock[k] *dcn_bw_max5(v->vtaps[k] / 6.0 *dcn_bw_min2(1.0, v->h_ratio[k]), v->h_ratio[k] * v->v_ratio[k] / v->pscl_factor[k], v->vta_pschroma[k] / 6.0 *dcn_bw_min2(1.0, v->h_ratio[k] / 2.0), v->h_ratio[k] * v->v_ratio[k] / 4.0 / v->pscl_factor_chroma[k], 1.0); } } for (k = 0; k <= v->number_of_active_planes - 1; k++) { - if ((v->source_pixel_format[k] == dcn_bw_rgb_sub_64 - || v->source_pixel_format[k] == dcn_bw_rgb_sub_32 - || v->source_pixel_format[k] == dcn_bw_rgb_sub_16)) { + if ((v->source_pixel_format[k] == dcn_bw_rgb_sub_64 || v->source_pixel_format[k] == dcn_bw_rgb_sub_32 || v->source_pixel_format[k] == dcn_bw_rgb_sub_16)) { if (v->source_surface_mode[k] == dcn_bw_sw_linear) { v->read256_block_height_y[k] = 1.0; - } else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_64) { + } + else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_64) { v->read256_block_height_y[k] = 4.0; - } else { + } + else { v->read256_block_height_y[k] = 8.0; } - v->read256_block_width_y[k] = 256.0 - / dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) - / v->read256_block_height_y[k]; + v->read256_block_width_y[k] = 256.0 /dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) / v->read256_block_height_y[k]; v->read256_block_height_c[k] = 0.0; v->read256_block_width_c[k] = 0.0; - } else { + } + else { if (v->source_surface_mode[k] == dcn_bw_sw_linear) { v->read256_block_height_y[k] = 1.0; v->read256_block_height_c[k] = 1.0; - } else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_8) { + } + else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_8) { v->read256_block_height_y[k] = 16.0; v->read256_block_height_c[k] = 8.0; - } else { + } + else { v->read256_block_height_y[k] = 8.0; v->read256_block_height_c[k] = 8.0; } - v->read256_block_width_y[k] = 256.0 - / dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) - / v->read256_block_height_y[k]; - v->read256_block_width_c[k] = 256.0 - / dcn_bw_ceil2(v->byte_per_pixel_in_detc[k], 2.0) - / v->read256_block_height_c[k]; + v->read256_block_width_y[k] = 256.0 /dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) / v->read256_block_height_y[k]; + v->read256_block_width_c[k] = 256.0 /dcn_bw_ceil2(v->byte_per_pixel_in_detc[k], 2.0) / v->read256_block_height_c[k]; } if (v->source_scan[k] == dcn_bw_hor) { v->max_swath_height_y[k] = v->read256_block_height_y[k]; v->max_swath_height_c[k] = v->read256_block_height_c[k]; - } else { + } + else { v->max_swath_height_y[k] = v->read256_block_width_y[k]; v->max_swath_height_c[k] = v->read256_block_width_c[k]; } - if ((v->source_pixel_format[k] == dcn_bw_rgb_sub_64 - || v->source_pixel_format[k] == dcn_bw_rgb_sub_32 - || v->source_pixel_format[k] == dcn_bw_rgb_sub_16)) { - if (v->source_surface_mode[k] == dcn_bw_sw_linear - || (v->source_pixel_format[k] == dcn_bw_rgb_sub_64 - && (v->source_surface_mode[k] - == dcn_bw_sw_4_kb_s - || v->source_surface_mode[k] - == dcn_bw_sw_4_kb_s_x - || v->source_surface_mode[k] - == dcn_bw_sw_64_kb_s - || v->source_surface_mode[k] - == dcn_bw_sw_64_kb_s_t - || v->source_surface_mode[k] - == dcn_bw_sw_64_kb_s_x - || v->source_surface_mode[k] - == dcn_bw_sw_var_s - || v->source_surface_mode[k] - == dcn_bw_sw_var_s_x) - && v->source_scan[k] == dcn_bw_hor)) { + if ((v->source_pixel_format[k] == dcn_bw_rgb_sub_64 || v->source_pixel_format[k] == dcn_bw_rgb_sub_32 || v->source_pixel_format[k] == dcn_bw_rgb_sub_16)) { + if (v->source_surface_mode[k] == dcn_bw_sw_linear || (v->source_pixel_format[k] == dcn_bw_rgb_sub_64 && (v->source_surface_mode[k] == dcn_bw_sw_4_kb_s || v->source_surface_mode[k] == dcn_bw_sw_4_kb_s_x || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_t || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_x || v->source_surface_mode[k] == dcn_bw_sw_var_s || v->source_surface_mode[k] == dcn_bw_sw_var_s_x) && v->source_scan[k] == dcn_bw_hor)) { v->min_swath_height_y[k] = v->max_swath_height_y[k]; - } else { + } + else { v->min_swath_height_y[k] = v->max_swath_height_y[k] / 2.0; } v->min_swath_height_c[k] = v->max_swath_height_c[k]; - } else { + } + else { if (v->source_surface_mode[k] == dcn_bw_sw_linear) { v->min_swath_height_y[k] = v->max_swath_height_y[k]; v->min_swath_height_c[k] = v->max_swath_height_c[k]; - } else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_8 - && v->source_scan[k] == dcn_bw_hor) { + } + else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_8 && v->source_scan[k] == dcn_bw_hor) { v->min_swath_height_y[k] = v->max_swath_height_y[k] / 2.0; - if (v->bug_forcing_luma_and_chroma_request_to_same_size_fixed - == dcn_bw_yes) { + if (v->bug_forcing_luma_and_chroma_request_to_same_size_fixed == dcn_bw_yes) { v->min_swath_height_c[k] = v->max_swath_height_c[k]; - } else { + } + else { v->min_swath_height_c[k] = v->max_swath_height_c[k] / 2.0; } - } else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_10 - && v->source_scan[k] == dcn_bw_hor) { + } + else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_10 && v->source_scan[k] == dcn_bw_hor) { v->min_swath_height_c[k] = v->max_swath_height_c[k] / 2.0; - if (v->bug_forcing_luma_and_chroma_request_to_same_size_fixed - == dcn_bw_yes) { + if (v->bug_forcing_luma_and_chroma_request_to_same_size_fixed == dcn_bw_yes) { v->min_swath_height_y[k] = v->max_swath_height_y[k]; - } else { + } + else { v->min_swath_height_y[k] = v->max_swath_height_y[k] / 2.0; } - } else { + } + else { v->min_swath_height_y[k] = v->max_swath_height_y[k]; v->min_swath_height_c[k] = v->max_swath_height_c[k]; } } if (v->source_surface_mode[k] == dcn_bw_sw_linear) { v->maximum_swath_width = 8192.0; - } else { + } + else { v->maximum_swath_width = 5120.0; } - v->number_of_dpp_required_for_det_size = - dcn_bw_ceil2( - v->swath_width_ysingle_dpp[k] - / dcn_bw_min2( - v->maximum_swath_width, - v->det_buffer_size_in_kbyte - * 1024.0 - / 2.0 - / (v->byte_per_pixel_in_dety[k] - * v->min_swath_height_y[k] - + v->byte_per_pixel_in_detc[k] - / 2.0 - * v->min_swath_height_c[k])), - 1.0); + v->number_of_dpp_required_for_det_size =dcn_bw_ceil2(v->swath_width_ysingle_dpp[k] /dcn_bw_min2(v->maximum_swath_width, v->det_buffer_size_in_kbyte * 1024.0 / 2.0 / (v->byte_per_pixel_in_dety[k] * v->min_swath_height_y[k] + v->byte_per_pixel_in_detc[k] / 2.0 * v->min_swath_height_c[k])), 1.0); if (v->byte_per_pixel_in_detc[k] == 0.0) { - v->number_of_dpp_required_for_lb_size = dcn_bw_ceil2( - (v->vtaps[k] - + dcn_bw_max2( - dcn_bw_ceil2(v->v_ratio[k], 1.0) - - 2, - 0.0)) - * v->swath_width_ysingle_dpp[k] - / dcn_bw_max2(v->h_ratio[k], 1.0) - * v->lb_bit_per_pixel[k] - / v->line_buffer_size, - 1.0); - } else { - v->number_of_dpp_required_for_lb_size = - dcn_bw_max2( - dcn_bw_ceil2( - (v->vtaps[k] - + dcn_bw_max2( - dcn_bw_ceil2( - v->v_ratio[k], - 1.0) - - 2, - 0.0)) - * v->swath_width_ysingle_dpp[k] - / dcn_bw_max2( - v->h_ratio[k], - 1.0) - * v->lb_bit_per_pixel[k] - / v->line_buffer_size, - 1.0), - dcn_bw_ceil2( - (v->vta_pschroma[k] - + dcn_bw_max2( - dcn_bw_ceil2( - v->v_ratio[k] - / 2.0, - 1.0) - - 2, - 0.0)) - * v->swath_width_ysingle_dpp[k] - / 2.0 - / dcn_bw_max2( - v->h_ratio[k] - / 2.0, - 1.0) - * v->lb_bit_per_pixel[k] - / v->line_buffer_size, - 1.0)); - } - v->number_of_dpp_required_for_det_and_lb_size[k] = dcn_bw_max2( - v->number_of_dpp_required_for_det_size, - v->number_of_dpp_required_for_lb_size); + v->number_of_dpp_required_for_lb_size =dcn_bw_ceil2((v->vtaps[k] +dcn_bw_max2(dcn_bw_ceil2(v->v_ratio[k], 1.0) - 2, 0.0)) * v->swath_width_ysingle_dpp[k] /dcn_bw_max2(v->h_ratio[k], 1.0) * v->lb_bit_per_pixel[k] / v->line_buffer_size, 1.0); + } + else { + v->number_of_dpp_required_for_lb_size =dcn_bw_max2(dcn_bw_ceil2((v->vtaps[k] +dcn_bw_max2(dcn_bw_ceil2(v->v_ratio[k], 1.0) - 2, 0.0)) * v->swath_width_ysingle_dpp[k] /dcn_bw_max2(v->h_ratio[k], 1.0) * v->lb_bit_per_pixel[k] / v->line_buffer_size, 1.0),dcn_bw_ceil2((v->vta_pschroma[k] +dcn_bw_max2(dcn_bw_ceil2(v->v_ratio[k] / 2.0, 1.0) - 2, 0.0)) * v->swath_width_ysingle_dpp[k] / 2.0 /dcn_bw_max2(v->h_ratio[k] / 2.0, 1.0) * v->lb_bit_per_pixel[k] / v->line_buffer_size, 1.0)); + } + v->number_of_dpp_required_for_det_and_lb_size[k] =dcn_bw_max2(v->number_of_dpp_required_for_det_size, v->number_of_dpp_required_for_lb_size); } for (i = 0; i <= number_of_states_plus_one; i++) { for (j = 0; j <= 1; j++) { @@ -666,119 +417,58 @@ void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v) v->required_dispclk[i][j] = 0.0; v->dispclk_dppclk_support[i][j] = dcn_bw_yes; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - v->min_dispclk_using_single_dpp = dcn_bw_max2( - v->pixel_clock[k], - v->min_dppclk_using_single_dpp[k] * (j + 1)) - * (1.0 + v->downspreading / 100.0); + v->min_dispclk_using_single_dpp =dcn_bw_max2(v->pixel_clock[k], v->min_dppclk_using_single_dpp[k] * (j + 1)) * (1.0 + v->downspreading / 100.0); if (v->odm_capability == dcn_bw_yes) { - v->min_dispclk_using_dual_dpp = dcn_bw_max2( - v->pixel_clock[k] / 2.0, - v->min_dppclk_using_single_dpp[k] / 2.0 - * (j + 1)) - * (1.0 + v->downspreading / 100.0); - } else { - v->min_dispclk_using_dual_dpp = dcn_bw_max2( - v->pixel_clock[k], - v->min_dppclk_using_single_dpp[k] / 2.0 - * (j + 1)) - * (1.0 + v->downspreading / 100.0); + v->min_dispclk_using_dual_dpp =dcn_bw_max2(v->pixel_clock[k] / 2.0, v->min_dppclk_using_single_dpp[k] / 2.0 * (j + 1)) * (1.0 + v->downspreading / 100.0); + } + else { + v->min_dispclk_using_dual_dpp =dcn_bw_max2(v->pixel_clock[k], v->min_dppclk_using_single_dpp[k] / 2.0 * (j + 1)) * (1.0 + v->downspreading / 100.0); } if (i < number_of_states) { - v->min_dispclk_using_single_dpp = - v->min_dispclk_using_single_dpp - * (1.0 - + v->dispclk_ramping_margin - / 100.0); - v->min_dispclk_using_dual_dpp = - v->min_dispclk_using_dual_dpp - * (1.0 - + v->dispclk_ramping_margin - / 100.0); - } - if (v->min_dispclk_using_single_dpp - <= dcn_bw_min2( - v->max_dispclk[i], - (j + 1) * v->max_dppclk[i]) - && v->number_of_dpp_required_for_det_and_lb_size[k] - <= 1.0) { + v->min_dispclk_using_single_dpp = v->min_dispclk_using_single_dpp * (1.0 + v->dispclk_ramping_margin / 100.0); + v->min_dispclk_using_dual_dpp = v->min_dispclk_using_dual_dpp * (1.0 + v->dispclk_ramping_margin / 100.0); + } + if (v->min_dispclk_using_single_dpp <=dcn_bw_min2(v->max_dispclk[i], (j + 1) * v->max_dppclk[i]) && v->number_of_dpp_required_for_det_and_lb_size[k] <= 1.0) { v->no_of_dpp[i][j][k] = 1.0; - v->required_dispclk[i][j] = dcn_bw_max2( - v->required_dispclk[i][j], - v->min_dispclk_using_single_dpp); - } else if (v->min_dispclk_using_dual_dpp - <= dcn_bw_min2( - v->max_dispclk[i], - (j + 1) * v->max_dppclk[i])) { + v->required_dispclk[i][j] =dcn_bw_max2(v->required_dispclk[i][j], v->min_dispclk_using_single_dpp); + } + else if (v->min_dispclk_using_dual_dpp <=dcn_bw_min2(v->max_dispclk[i], (j + 1) * v->max_dppclk[i])) { v->no_of_dpp[i][j][k] = 2.0; - v->required_dispclk[i][j] = dcn_bw_max2( - v->required_dispclk[i][j], - v->min_dispclk_using_dual_dpp); - } else { + v->required_dispclk[i][j] =dcn_bw_max2(v->required_dispclk[i][j], v->min_dispclk_using_dual_dpp); + } + else { v->no_of_dpp[i][j][k] = 2.0; - v->required_dispclk[i][j] = dcn_bw_max2( - v->required_dispclk[i][j], - v->min_dispclk_using_dual_dpp); + v->required_dispclk[i][j] =dcn_bw_max2(v->required_dispclk[i][j], v->min_dispclk_using_dual_dpp); v->dispclk_dppclk_support[i][j] = dcn_bw_no; } - v->total_number_of_active_dpp[i][j] = - v->total_number_of_active_dpp[i][j] - + v->no_of_dpp[i][j][k]; + v->total_number_of_active_dpp[i][j] = v->total_number_of_active_dpp[i][j] + v->no_of_dpp[i][j][k]; } if (v->total_number_of_active_dpp[i][j] > v->max_num_dpp) { v->total_number_of_active_dpp[i][j] = 0.0; v->required_dispclk[i][j] = 0.0; v->dispclk_dppclk_support[i][j] = dcn_bw_yes; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - v->min_dispclk_using_single_dpp = dcn_bw_max2( - v->pixel_clock[k], - v->min_dppclk_using_single_dpp[k] * (j + 1)) - * (1.0 + v->downspreading / 100.0); - v->min_dispclk_using_dual_dpp = dcn_bw_max2( - v->pixel_clock[k], - v->min_dppclk_using_single_dpp[k] / 2.0 - * (j + 1)) - * (1.0 + v->downspreading / 100.0); + v->min_dispclk_using_single_dpp =dcn_bw_max2(v->pixel_clock[k], v->min_dppclk_using_single_dpp[k] * (j + 1)) * (1.0 + v->downspreading / 100.0); + v->min_dispclk_using_dual_dpp =dcn_bw_max2(v->pixel_clock[k], v->min_dppclk_using_single_dpp[k] / 2.0 * (j + 1)) * (1.0 + v->downspreading / 100.0); if (i < number_of_states) { - v->min_dispclk_using_single_dpp = - v->min_dispclk_using_single_dpp - * (1.0 - + v->dispclk_ramping_margin - / 100.0); - v->min_dispclk_using_dual_dpp = - v->min_dispclk_using_dual_dpp - * (1.0 - + v->dispclk_ramping_margin - / 100.0); + v->min_dispclk_using_single_dpp = v->min_dispclk_using_single_dpp * (1.0 + v->dispclk_ramping_margin / 100.0); + v->min_dispclk_using_dual_dpp = v->min_dispclk_using_dual_dpp * (1.0 + v->dispclk_ramping_margin / 100.0); } - if (v->number_of_dpp_required_for_det_and_lb_size[k] - <= 1.0) { + if (v->number_of_dpp_required_for_det_and_lb_size[k] <= 1.0) { v->no_of_dpp[i][j][k] = 1.0; - v->required_dispclk[i][j] = dcn_bw_max2( - v->required_dispclk[i][j], - v->min_dispclk_using_single_dpp); - if (v->min_dispclk_using_single_dpp - > dcn_bw_min2( - v->max_dispclk[i], - (j + 1) - * v->max_dppclk[i])) { + v->required_dispclk[i][j] =dcn_bw_max2(v->required_dispclk[i][j], v->min_dispclk_using_single_dpp); + if (v->min_dispclk_using_single_dpp >dcn_bw_min2(v->max_dispclk[i], (j + 1) * v->max_dppclk[i])) { v->dispclk_dppclk_support[i][j] = dcn_bw_no; } - } else { + } + else { v->no_of_dpp[i][j][k] = 2.0; - v->required_dispclk[i][j] = dcn_bw_max2( - v->required_dispclk[i][j], - v->min_dispclk_using_dual_dpp); - if (v->min_dispclk_using_dual_dpp - > dcn_bw_min2( - v->max_dispclk[i], - (j + 1) - * v->max_dppclk[i])) { + v->required_dispclk[i][j] =dcn_bw_max2(v->required_dispclk[i][j], v->min_dispclk_using_dual_dpp); + if (v->min_dispclk_using_dual_dpp >dcn_bw_min2(v->max_dispclk[i], (j + 1) * v->max_dppclk[i])) { v->dispclk_dppclk_support[i][j] = dcn_bw_no; } } - v->total_number_of_active_dpp[i][j] = - v->total_number_of_active_dpp[i][j] - + v->no_of_dpp[i][j][k]; + v->total_number_of_active_dpp[i][j] = v->total_number_of_active_dpp[i][j] + v->no_of_dpp[i][j][k]; } } } @@ -797,7 +487,8 @@ void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v) for (j = 0; j <= 1; j++) { if (v->total_number_of_active_dpp[i][j] <= v->max_num_dpp) { v->total_available_pipes_support[i][j] = dcn_bw_yes; - } else { + } + else { v->total_available_pipes_support[i][j] = dcn_bw_no; } } @@ -807,167 +498,48 @@ void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v) for (k = 0; k <= v->number_of_active_planes - 1; k++) { for (i = 0; i <= number_of_states_plus_one; i++) { for (j = 0; j <= 1; j++) { - v->swath_width_yper_state[i][j][k] = v->swath_width_ysingle_dpp[k] - / v->no_of_dpp[i][j][k]; - v->swath_width_granularity_y = 256.0 - / dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) - / v->max_swath_height_y[k]; - v->rounded_up_max_swath_size_bytes_y = (dcn_bw_ceil2( - v->swath_width_yper_state[i][j][k] - 1.0, - v->swath_width_granularity_y) - + v->swath_width_granularity_y) - * v->byte_per_pixel_in_dety[k] - * v->max_swath_height_y[k]; + v->swath_width_yper_state[i][j][k] = v->swath_width_ysingle_dpp[k] / v->no_of_dpp[i][j][k]; + v->swath_width_granularity_y = 256.0 /dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) / v->max_swath_height_y[k]; + v->rounded_up_max_swath_size_bytes_y = (dcn_bw_ceil2(v->swath_width_yper_state[i][j][k] - 1.0, v->swath_width_granularity_y) + v->swath_width_granularity_y) * v->byte_per_pixel_in_dety[k] * v->max_swath_height_y[k]; if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_10) { - v->rounded_up_max_swath_size_bytes_y = dcn_bw_ceil2( - v->rounded_up_max_swath_size_bytes_y, - 256.0) + 256; + v->rounded_up_max_swath_size_bytes_y =dcn_bw_ceil2(v->rounded_up_max_swath_size_bytes_y, 256.0) + 256; } if (v->max_swath_height_c[k] > 0.0) { - v->swath_width_granularity_c = - 256.0 - / dcn_bw_ceil2( - v->byte_per_pixel_in_detc[k], - 2.0) - / v->max_swath_height_c[k]; - } - v->rounded_up_max_swath_size_bytes_c = (dcn_bw_ceil2( - v->swath_width_yper_state[i][j][k] / 2.0 - 1.0, - v->swath_width_granularity_c) - + v->swath_width_granularity_c) - * v->byte_per_pixel_in_detc[k] - * v->max_swath_height_c[k]; + v->swath_width_granularity_c = 256.0 /dcn_bw_ceil2(v->byte_per_pixel_in_detc[k], 2.0) / v->max_swath_height_c[k]; + } + v->rounded_up_max_swath_size_bytes_c = (dcn_bw_ceil2(v->swath_width_yper_state[i][j][k] / 2.0 - 1.0, v->swath_width_granularity_c) + v->swath_width_granularity_c) * v->byte_per_pixel_in_detc[k] * v->max_swath_height_c[k]; if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_10) { - v->rounded_up_max_swath_size_bytes_c = dcn_bw_ceil2( - v->rounded_up_max_swath_size_bytes_c, - 256.0) + 256; - } - if (v->rounded_up_max_swath_size_bytes_y - + v->rounded_up_max_swath_size_bytes_c - <= v->det_buffer_size_in_kbyte * 1024.0 / 2.0) { - v->swath_height_yper_state[i][j][k] = - v->max_swath_height_y[k]; - v->swath_height_cper_state[i][j][k] = - v->max_swath_height_c[k]; - } else { - v->swath_height_yper_state[i][j][k] = - v->min_swath_height_y[k]; - v->swath_height_cper_state[i][j][k] = - v->min_swath_height_c[k]; + v->rounded_up_max_swath_size_bytes_c =dcn_bw_ceil2(v->rounded_up_max_swath_size_bytes_c, 256.0) + 256; + } + if (v->rounded_up_max_swath_size_bytes_y + v->rounded_up_max_swath_size_bytes_c <= v->det_buffer_size_in_kbyte * 1024.0 / 2.0) { + v->swath_height_yper_state[i][j][k] = v->max_swath_height_y[k]; + v->swath_height_cper_state[i][j][k] = v->max_swath_height_c[k]; + } + else { + v->swath_height_yper_state[i][j][k] = v->min_swath_height_y[k]; + v->swath_height_cper_state[i][j][k] = v->min_swath_height_c[k]; } if (v->byte_per_pixel_in_detc[k] == 0.0) { - v->lines_in_det_luma = v->det_buffer_size_in_kbyte * 1024.0 - / v->byte_per_pixel_in_dety[k] - / v->swath_width_yper_state[i][j][k]; + v->lines_in_det_luma = v->det_buffer_size_in_kbyte * 1024.0 / v->byte_per_pixel_in_dety[k] / v->swath_width_yper_state[i][j][k]; v->lines_in_det_chroma = 0.0; - } else if (v->swath_height_yper_state[i][j][k] - <= v->swath_height_cper_state[i][j][k]) { - v->lines_in_det_luma = v->det_buffer_size_in_kbyte * 1024.0 - / 2.0 / v->byte_per_pixel_in_dety[k] - / v->swath_width_yper_state[i][j][k]; - v->lines_in_det_chroma = - v->det_buffer_size_in_kbyte * 1024.0 / 2.0 - / v->byte_per_pixel_in_detc[k] - / (v->swath_width_yper_state[i][j][k] - / 2.0); - } else { - v->lines_in_det_luma = v->det_buffer_size_in_kbyte * 1024.0 - * 2.0 / 3.0 / v->byte_per_pixel_in_dety[k] - / v->swath_width_yper_state[i][j][k]; - v->lines_in_det_chroma = - v->det_buffer_size_in_kbyte * 1024.0 / 3.0 - / v->byte_per_pixel_in_dety[k] - / (v->swath_width_yper_state[i][j][k] - / 2.0); - } - v->effective_lb_latency_hiding_source_lines_luma = - dcn_bw_min2( - v->max_line_buffer_lines, - dcn_bw_floor2( - v->line_buffer_size - / v->lb_bit_per_pixel[k] - / (v->swath_width_yper_state[i][j][k] - / dcn_bw_max2( - v->h_ratio[k], - 1.0)), - 1.0)) - - (v->vtaps[k] - 1.0); - v->effective_lb_latency_hiding_source_lines_chroma = - dcn_bw_min2( - v->max_line_buffer_lines, - dcn_bw_floor2( - v->line_buffer_size - / v->lb_bit_per_pixel[k] - / (v->swath_width_yper_state[i][j][k] - / 2.0 - / dcn_bw_max2( - v->h_ratio[k] - / 2.0, - 1.0)), - 1.0)) - - (v->vta_pschroma[k] - 1.0); - v->effective_detlb_lines_luma = - dcn_bw_floor2( - v->lines_in_det_luma - + dcn_bw_min2( - v->lines_in_det_luma - * v->required_dispclk[i][j] - * v->byte_per_pixel_in_dety[k] - * v->pscl_factor[k] - / v->return_bw_per_state[i], - v->effective_lb_latency_hiding_source_lines_luma), - v->swath_height_yper_state[i][j][k]); - v->effective_detlb_lines_chroma = - dcn_bw_floor2( - v->lines_in_det_chroma - + dcn_bw_min2( - v->lines_in_det_chroma - * v->required_dispclk[i][j] - * v->byte_per_pixel_in_detc[k] - * v->pscl_factor_chroma[k] - / v->return_bw_per_state[i], - v->effective_lb_latency_hiding_source_lines_chroma), - v->swath_height_cper_state[i][j][k]); + } + else if (v->swath_height_yper_state[i][j][k] <= v->swath_height_cper_state[i][j][k]) { + v->lines_in_det_luma = v->det_buffer_size_in_kbyte * 1024.0 / 2.0 / v->byte_per_pixel_in_dety[k] / v->swath_width_yper_state[i][j][k]; + v->lines_in_det_chroma = v->det_buffer_size_in_kbyte * 1024.0 / 2.0 / v->byte_per_pixel_in_detc[k] / (v->swath_width_yper_state[i][j][k] / 2.0); + } + else { + v->lines_in_det_luma = v->det_buffer_size_in_kbyte * 1024.0 * 2.0 / 3.0 / v->byte_per_pixel_in_dety[k] / v->swath_width_yper_state[i][j][k]; + v->lines_in_det_chroma = v->det_buffer_size_in_kbyte * 1024.0 / 3.0 / v->byte_per_pixel_in_dety[k] / (v->swath_width_yper_state[i][j][k] / 2.0); + } + v->effective_lb_latency_hiding_source_lines_luma =dcn_bw_min2(v->max_line_buffer_lines,dcn_bw_floor2(v->line_buffer_size / v->lb_bit_per_pixel[k] / (v->swath_width_yper_state[i][j][k] /dcn_bw_max2(v->h_ratio[k], 1.0)), 1.0)) - (v->vtaps[k] - 1.0); + v->effective_lb_latency_hiding_source_lines_chroma =dcn_bw_min2(v->max_line_buffer_lines,dcn_bw_floor2(v->line_buffer_size / v->lb_bit_per_pixel[k] / (v->swath_width_yper_state[i][j][k] / 2.0 /dcn_bw_max2(v->h_ratio[k] / 2.0, 1.0)), 1.0)) - (v->vta_pschroma[k] - 1.0); + v->effective_detlb_lines_luma =dcn_bw_floor2(v->lines_in_det_luma +dcn_bw_min2(v->lines_in_det_luma * v->required_dispclk[i][j] * v->byte_per_pixel_in_dety[k] * v->pscl_factor[k] / v->return_bw_per_state[i], v->effective_lb_latency_hiding_source_lines_luma), v->swath_height_yper_state[i][j][k]); + v->effective_detlb_lines_chroma =dcn_bw_floor2(v->lines_in_det_chroma +dcn_bw_min2(v->lines_in_det_chroma * v->required_dispclk[i][j] * v->byte_per_pixel_in_detc[k] * v->pscl_factor_chroma[k] / v->return_bw_per_state[i], v->effective_lb_latency_hiding_source_lines_chroma), v->swath_height_cper_state[i][j][k]); if (v->byte_per_pixel_in_detc[k] == 0.0) { - v->urgent_latency_support_us_per_state[i][j][k] = - v->effective_detlb_lines_luma - * (v->htotal[k] - / v->pixel_clock[k]) - / v->v_ratio[k] - - v->effective_detlb_lines_luma - * v->swath_width_yper_state[i][j][k] - * dcn_bw_ceil2( - v->byte_per_pixel_in_dety[k], - 1.0) - / (v->return_bw_per_state[i] - / v->no_of_dpp[i][j][k]); - } else { - v->urgent_latency_support_us_per_state[i][j][k] = - dcn_bw_min2( - v->effective_detlb_lines_luma - * (v->htotal[k] - / v->pixel_clock[k]) - / v->v_ratio[k] - - v->effective_detlb_lines_luma - * v->swath_width_yper_state[i][j][k] - * dcn_bw_ceil2( - v->byte_per_pixel_in_dety[k], - 1.0) - / (v->return_bw_per_state[i] - / v->no_of_dpp[i][j][k]), - v->effective_detlb_lines_chroma - * (v->htotal[k] - / v->pixel_clock[k]) - / (v->v_ratio[k] - / 2.0) - - v->effective_detlb_lines_chroma - * v->swath_width_yper_state[i][j][k] - / 2.0 - * dcn_bw_ceil2( - v->byte_per_pixel_in_detc[k], - 2.0) - / (v->return_bw_per_state[i] - / v->no_of_dpp[i][j][k])); + v->urgent_latency_support_us_per_state[i][j][k] = v->effective_detlb_lines_luma * (v->htotal[k] / v->pixel_clock[k]) / v->v_ratio[k] - v->effective_detlb_lines_luma * v->swath_width_yper_state[i][j][k] *dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) / (v->return_bw_per_state[i] / v->no_of_dpp[i][j][k]); + } + else { + v->urgent_latency_support_us_per_state[i][j][k] =dcn_bw_min2(v->effective_detlb_lines_luma * (v->htotal[k] / v->pixel_clock[k]) / v->v_ratio[k] - v->effective_detlb_lines_luma * v->swath_width_yper_state[i][j][k] *dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) / (v->return_bw_per_state[i] / v->no_of_dpp[i][j][k]), v->effective_detlb_lines_chroma * (v->htotal[k] / v->pixel_clock[k]) / (v->v_ratio[k] / 2.0) - v->effective_detlb_lines_chroma * v->swath_width_yper_state[i][j][k] / 2.0 *dcn_bw_ceil2(v->byte_per_pixel_in_detc[k], 2.0) / (v->return_bw_per_state[i] / v->no_of_dpp[i][j][k])); } } } @@ -976,8 +548,7 @@ void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v) for (j = 0; j <= 1; j++) { v->urgent_latency_support[i][j] = dcn_bw_yes; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - if (v->urgent_latency_support_us_per_state[i][j][k] - < v->urgent_latency / 1.0) { + if (v->urgent_latency_support_us_per_state[i][j][k] < v->urgent_latency / 1.0) { v->urgent_latency_support[i][j] = dcn_bw_no; } } @@ -990,9 +561,7 @@ void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v) v->total_number_of_dcc_active_dpp[i][j] = 0.0; for (k = 0; k <= v->number_of_active_planes - 1; k++) { if (v->dcc_enable[k] == dcn_bw_yes) { - v->total_number_of_dcc_active_dpp[i][j] = - v->total_number_of_dcc_active_dpp[i][j] - + v->no_of_dpp[i][j][k]; + v->total_number_of_dcc_active_dpp[i][j] = v->total_number_of_dcc_active_dpp[i][j] + v->no_of_dpp[i][j][k]; } } } @@ -1001,143 +570,50 @@ void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v) for (j = 0; j <= 1; j++) { v->projected_dcfclk_deep_sleep = 8.0; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - v->projected_dcfclk_deep_sleep = dcn_bw_max2( - v->projected_dcfclk_deep_sleep, - v->pixel_clock[k] / 16.0); + v->projected_dcfclk_deep_sleep =dcn_bw_max2(v->projected_dcfclk_deep_sleep, v->pixel_clock[k] / 16.0); if (v->byte_per_pixel_in_detc[k] == 0.0) { if (v->v_ratio[k] <= 1.0) { - v->projected_dcfclk_deep_sleep = - dcn_bw_max2( - v->projected_dcfclk_deep_sleep, - 1.1 - * dcn_bw_ceil2( - v->byte_per_pixel_in_dety[k], - 1.0) - / 64.0 - * v->h_ratio[k] - * v->pixel_clock[k] - / v->no_of_dpp[i][j][k]); - } else { - v->projected_dcfclk_deep_sleep = - dcn_bw_max2( - v->projected_dcfclk_deep_sleep, - 1.1 - * dcn_bw_ceil2( - v->byte_per_pixel_in_dety[k], - 1.0) - / 64.0 - * v->pscl_factor[k] - * v->required_dispclk[i][j] - / (1 - + j)); + v->projected_dcfclk_deep_sleep =dcn_bw_max2(v->projected_dcfclk_deep_sleep, 1.1 *dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) / 64.0 * v->h_ratio[k] * v->pixel_clock[k] / v->no_of_dpp[i][j][k]); + } + else { + v->projected_dcfclk_deep_sleep =dcn_bw_max2(v->projected_dcfclk_deep_sleep, 1.1 *dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) / 64.0 * v->pscl_factor[k] * v->required_dispclk[i][j] / (1 + j)); } - } else { + } + else { if (v->v_ratio[k] <= 1.0) { - v->projected_dcfclk_deep_sleep = - dcn_bw_max2( - v->projected_dcfclk_deep_sleep, - 1.1 - * dcn_bw_ceil2( - v->byte_per_pixel_in_dety[k], - 1.0) - / 32.0 - * v->h_ratio[k] - * v->pixel_clock[k] - / v->no_of_dpp[i][j][k]); - } else { - v->projected_dcfclk_deep_sleep = - dcn_bw_max2( - v->projected_dcfclk_deep_sleep, - 1.1 - * dcn_bw_ceil2( - v->byte_per_pixel_in_dety[k], - 1.0) - / 32.0 - * v->pscl_factor[k] - * v->required_dispclk[i][j] - / (1 - + j)); + v->projected_dcfclk_deep_sleep =dcn_bw_max2(v->projected_dcfclk_deep_sleep, 1.1 *dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) / 32.0 * v->h_ratio[k] * v->pixel_clock[k] / v->no_of_dpp[i][j][k]); + } + else { + v->projected_dcfclk_deep_sleep =dcn_bw_max2(v->projected_dcfclk_deep_sleep, 1.1 *dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) / 32.0 * v->pscl_factor[k] * v->required_dispclk[i][j] / (1 + j)); } if (v->v_ratio[k] / 2.0 <= 1.0) { - v->projected_dcfclk_deep_sleep = - dcn_bw_max2( - v->projected_dcfclk_deep_sleep, - 1.1 - * dcn_bw_ceil2( - v->byte_per_pixel_in_detc[k], - 2.0) - / 32.0 - * v->h_ratio[k] - / 2.0 - * v->pixel_clock[k] - / v->no_of_dpp[i][j][k]); - } else { - v->projected_dcfclk_deep_sleep = - dcn_bw_max2( - v->projected_dcfclk_deep_sleep, - 1.1 - * dcn_bw_ceil2( - v->byte_per_pixel_in_detc[k], - 2.0) - / 32.0 - * v->pscl_factor_chroma[k] - * v->required_dispclk[i][j] - / (1 - + j)); + v->projected_dcfclk_deep_sleep =dcn_bw_max2(v->projected_dcfclk_deep_sleep, 1.1 *dcn_bw_ceil2(v->byte_per_pixel_in_detc[k], 2.0) / 32.0 * v->h_ratio[k] / 2.0 * v->pixel_clock[k] / v->no_of_dpp[i][j][k]); + } + else { + v->projected_dcfclk_deep_sleep =dcn_bw_max2(v->projected_dcfclk_deep_sleep, 1.1 *dcn_bw_ceil2(v->byte_per_pixel_in_detc[k], 2.0) / 32.0 * v->pscl_factor_chroma[k] * v->required_dispclk[i][j] / (1 + j)); } } } for (k = 0; k <= v->number_of_active_planes - 1; k++) { if (v->dcc_enable[k] == dcn_bw_yes) { v->meta_req_height_y = 8.0 * v->read256_block_height_y[k]; - v->meta_req_width_y = - 64.0 * 256.0 - / dcn_bw_ceil2( - v->byte_per_pixel_in_dety[k], - 1.0) - / v->meta_req_height_y; - v->meta_surface_width_y = dcn_bw_ceil2( - v->viewport_width[k] / v->no_of_dpp[i][j][k] - - 1.0, - v->meta_req_width_y) + v->meta_req_width_y; - v->meta_surface_height_y = dcn_bw_ceil2( - v->viewport_height[k] - 1.0, - v->meta_req_height_y) - + v->meta_req_height_y; + v->meta_req_width_y = 64.0 * 256.0 /dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) / v->meta_req_height_y; + v->meta_surface_width_y =dcn_bw_ceil2(v->viewport_width[k] / v->no_of_dpp[i][j][k] - 1.0, v->meta_req_width_y) + v->meta_req_width_y; + v->meta_surface_height_y =dcn_bw_ceil2(v->viewport_height[k] - 1.0, v->meta_req_height_y) + v->meta_req_height_y; if (v->pte_enable == dcn_bw_yes) { - v->meta_pte_bytes_per_frame_y = - (dcn_bw_ceil2( - (v->meta_surface_width_y - * v->meta_surface_height_y - * dcn_bw_ceil2( - v->byte_per_pixel_in_dety[k], - 1.0) - / 256.0 - - 4096.0) - / 8.0 - / 4096.0, - 1.0) + 1) * 64.0; - } else { + v->meta_pte_bytes_per_frame_y = (dcn_bw_ceil2((v->meta_surface_width_y * v->meta_surface_height_y *dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) / 256.0 - 4096.0) / 8.0 / 4096.0, 1.0) + 1) * 64.0; + } + else { v->meta_pte_bytes_per_frame_y = 0.0; } if (v->source_scan[k] == dcn_bw_hor) { - v->meta_row_bytes_y = - v->meta_surface_width_y - * v->meta_req_height_y - * dcn_bw_ceil2( - v->byte_per_pixel_in_dety[k], - 1.0) - / 256.0; - } else { - v->meta_row_bytes_y = - v->meta_surface_height_y - * v->meta_req_width_y - * dcn_bw_ceil2( - v->byte_per_pixel_in_dety[k], - 1.0) - / 256.0; + v->meta_row_bytes_y = v->meta_surface_width_y * v->meta_req_height_y *dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) / 256.0; } - } else { + else { + v->meta_row_bytes_y = v->meta_surface_height_y * v->meta_req_width_y *dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) / 256.0; + } + } + else { v->meta_pte_bytes_per_frame_y = 0.0; v->meta_row_bytes_y = 0.0; } @@ -1145,153 +621,59 @@ void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v) if (v->source_surface_mode[k] == dcn_bw_sw_linear) { v->macro_tile_block_size_bytes_y = 256.0; v->macro_tile_block_height_y = 1.0; - } else if (v->source_surface_mode[k] == dcn_bw_sw_4_kb_s - || v->source_surface_mode[k] - == dcn_bw_sw_4_kb_s_x - || v->source_surface_mode[k] - == dcn_bw_sw_4_kb_d - || v->source_surface_mode[k] - == dcn_bw_sw_4_kb_d_x) { + } + else if (v->source_surface_mode[k] == dcn_bw_sw_4_kb_s || v->source_surface_mode[k] == dcn_bw_sw_4_kb_s_x || v->source_surface_mode[k] == dcn_bw_sw_4_kb_d || v->source_surface_mode[k] == dcn_bw_sw_4_kb_d_x) { v->macro_tile_block_size_bytes_y = 4096.0; - v->macro_tile_block_height_y = 4.0 - * v->read256_block_height_y[k]; - } else if (v->source_surface_mode[k] == dcn_bw_sw_64_kb_s - || v->source_surface_mode[k] - == dcn_bw_sw_64_kb_s_t - || v->source_surface_mode[k] - == dcn_bw_sw_64_kb_s_x - || v->source_surface_mode[k] - == dcn_bw_sw_64_kb_d - || v->source_surface_mode[k] - == dcn_bw_sw_64_kb_d_t - || v->source_surface_mode[k] - == dcn_bw_sw_64_kb_d_x) { + v->macro_tile_block_height_y = 4.0 * v->read256_block_height_y[k]; + } + else if (v->source_surface_mode[k] == dcn_bw_sw_64_kb_s || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_t || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_x || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_t || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_x) { v->macro_tile_block_size_bytes_y = 64.0 * 1024; - v->macro_tile_block_height_y = 16.0 - * v->read256_block_height_y[k]; - } else { + v->macro_tile_block_height_y = 16.0 * v->read256_block_height_y[k]; + } + else { v->macro_tile_block_size_bytes_y = 256.0 * 1024; - v->macro_tile_block_height_y = 32.0 - * v->read256_block_height_y[k]; + v->macro_tile_block_height_y = 32.0 * v->read256_block_height_y[k]; } if (v->macro_tile_block_size_bytes_y <= 65536.0) { - v->data_pte_req_height_y = - v->macro_tile_block_height_y; - } else { - v->data_pte_req_height_y = 16.0 - * v->read256_block_height_y[k]; + v->data_pte_req_height_y = v->macro_tile_block_height_y; + } + else { + v->data_pte_req_height_y = 16.0 * v->read256_block_height_y[k]; } - v->data_pte_req_width_y = - 4096.0 - / dcn_bw_ceil2( - v->byte_per_pixel_in_dety[k], - 1.0) - / v->data_pte_req_height_y - * 8; + v->data_pte_req_width_y = 4096.0 /dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) / v->data_pte_req_height_y * 8; if (v->source_surface_mode[k] == dcn_bw_sw_linear) { - v->dpte_bytes_per_row_y = - 64.0 - * (dcn_bw_ceil2( - (v->viewport_width[k] - / v->no_of_dpp[i][j][k] - * dcn_bw_min2( - 128.0, - dcn_bw_pow( - 2.0, - dcn_bw_floor2( - dcn_bw_log( - v->pte_buffer_size_in_requests - * v->data_pte_req_width_y - / (v->viewport_width[k] - / v->no_of_dpp[i][j][k]), - 2.0), - 1.0))) - - 1.0) - / v->data_pte_req_width_y, - 1.0) - + 1); - } else if (v->source_scan[k] == dcn_bw_hor) { - v->dpte_bytes_per_row_y = - 64.0 - * (dcn_bw_ceil2( - (v->viewport_width[k] - / v->no_of_dpp[i][j][k] - - 1.0) - / v->data_pte_req_width_y, - 1.0) - + 1); - } else { - v->dpte_bytes_per_row_y = - 64.0 - * (dcn_bw_ceil2( - (v->viewport_height[k] - - 1.0) - / v->data_pte_req_height_y, - 1.0) - + 1); + v->dpte_bytes_per_row_y = 64.0 * (dcn_bw_ceil2((v->viewport_width[k] / v->no_of_dpp[i][j][k] *dcn_bw_min2(128.0, dcn_bw_pow(2.0,dcn_bw_floor2(dcn_bw_log(v->pte_buffer_size_in_requests * v->data_pte_req_width_y / (v->viewport_width[k] / v->no_of_dpp[i][j][k]), 2.0), 1.0))) - 1.0) / v->data_pte_req_width_y, 1.0) + 1); + } + else if (v->source_scan[k] == dcn_bw_hor) { + v->dpte_bytes_per_row_y = 64.0 * (dcn_bw_ceil2((v->viewport_width[k] / v->no_of_dpp[i][j][k] - 1.0) / v->data_pte_req_width_y, 1.0) + 1); + } + else { + v->dpte_bytes_per_row_y = 64.0 * (dcn_bw_ceil2((v->viewport_height[k] - 1.0) / v->data_pte_req_height_y, 1.0) + 1); } - } else { + } + else { v->dpte_bytes_per_row_y = 0.0; } - if ((v->source_pixel_format[k] != dcn_bw_rgb_sub_64 - && v->source_pixel_format[k] != dcn_bw_rgb_sub_32 - && v->source_pixel_format[k] != dcn_bw_rgb_sub_16)) { + if ((v->source_pixel_format[k] != dcn_bw_rgb_sub_64 && v->source_pixel_format[k] != dcn_bw_rgb_sub_32 && v->source_pixel_format[k] != dcn_bw_rgb_sub_16)) { if (v->dcc_enable[k] == dcn_bw_yes) { - v->meta_req_height_c = 8.0 - * v->read256_block_height_c[k]; - v->meta_req_width_c = - 64.0 * 256.0 - / dcn_bw_ceil2( - v->byte_per_pixel_in_detc[k], - 2.0) - / v->meta_req_height_c; - v->meta_surface_width_c = - dcn_bw_ceil2( - v->viewport_width[k] - / v->no_of_dpp[i][j][k] - / 2.0 - - 1.0, - v->meta_req_width_c) - + v->meta_req_width_c; - v->meta_surface_height_c = dcn_bw_ceil2( - v->viewport_height[k] / 2.0 - 1.0, - v->meta_req_height_c) - + v->meta_req_height_c; + v->meta_req_height_c = 8.0 * v->read256_block_height_c[k]; + v->meta_req_width_c = 64.0 * 256.0 /dcn_bw_ceil2(v->byte_per_pixel_in_detc[k], 2.0) / v->meta_req_height_c; + v->meta_surface_width_c =dcn_bw_ceil2(v->viewport_width[k] / v->no_of_dpp[i][j][k] / 2.0 - 1.0, v->meta_req_width_c) + v->meta_req_width_c; + v->meta_surface_height_c =dcn_bw_ceil2(v->viewport_height[k] / 2.0 - 1.0, v->meta_req_height_c) + v->meta_req_height_c; if (v->pte_enable == dcn_bw_yes) { - v->meta_pte_bytes_per_frame_c = - (dcn_bw_ceil2( - (v->meta_surface_width_c - * v->meta_surface_height_c - * dcn_bw_ceil2( - v->byte_per_pixel_in_detc[k], - 2.0) - / 256.0 - - 4096.0) - / 8.0 - / 4096.0, - 1.0) + 1) - * 64.0; - } else { + v->meta_pte_bytes_per_frame_c = (dcn_bw_ceil2((v->meta_surface_width_c * v->meta_surface_height_c *dcn_bw_ceil2(v->byte_per_pixel_in_detc[k], 2.0) / 256.0 - 4096.0) / 8.0 / 4096.0, 1.0) + 1) * 64.0; + } + else { v->meta_pte_bytes_per_frame_c = 0.0; } if (v->source_scan[k] == dcn_bw_hor) { - v->meta_row_bytes_c = - v->meta_surface_width_c - * v->meta_req_height_c - * dcn_bw_ceil2( - v->byte_per_pixel_in_detc[k], - 2.0) - / 256.0; - } else { - v->meta_row_bytes_c = - v->meta_surface_height_c - * v->meta_req_width_c - * dcn_bw_ceil2( - v->byte_per_pixel_in_detc[k], - 2.0) - / 256.0; + v->meta_row_bytes_c = v->meta_surface_width_c * v->meta_req_height_c *dcn_bw_ceil2(v->byte_per_pixel_in_detc[k], 2.0) / 256.0; } - } else { + else { + v->meta_row_bytes_c = v->meta_surface_height_c * v->meta_req_width_c *dcn_bw_ceil2(v->byte_per_pixel_in_detc[k], 2.0) / 256.0; + } + } + else { v->meta_pte_bytes_per_frame_c = 0.0; v->meta_row_bytes_c = 0.0; } @@ -1299,593 +681,221 @@ void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v) if (v->source_surface_mode[k] == dcn_bw_sw_linear) { v->macro_tile_block_size_bytes_c = 256.0; v->macro_tile_block_height_c = 1.0; - } else if (v->source_surface_mode[k] - == dcn_bw_sw_4_kb_s - || v->source_surface_mode[k] - == dcn_bw_sw_4_kb_s_x - || v->source_surface_mode[k] - == dcn_bw_sw_4_kb_d - || v->source_surface_mode[k] - == dcn_bw_sw_4_kb_d_x) { + } + else if (v->source_surface_mode[k] == dcn_bw_sw_4_kb_s || v->source_surface_mode[k] == dcn_bw_sw_4_kb_s_x || v->source_surface_mode[k] == dcn_bw_sw_4_kb_d || v->source_surface_mode[k] == dcn_bw_sw_4_kb_d_x) { v->macro_tile_block_size_bytes_c = 4096.0; - v->macro_tile_block_height_c = - 4.0 - * v->read256_block_height_c[k]; - } else if (v->source_surface_mode[k] - == dcn_bw_sw_64_kb_s - || v->source_surface_mode[k] - == dcn_bw_sw_64_kb_s_t - || v->source_surface_mode[k] - == dcn_bw_sw_64_kb_s_x - || v->source_surface_mode[k] - == dcn_bw_sw_64_kb_d - || v->source_surface_mode[k] - == dcn_bw_sw_64_kb_d_t - || v->source_surface_mode[k] - == dcn_bw_sw_64_kb_d_x) { - v->macro_tile_block_size_bytes_c = 64.0 - * 1024; - v->macro_tile_block_height_c = - 16.0 - * v->read256_block_height_c[k]; - } else { - v->macro_tile_block_size_bytes_c = 256.0 - * 1024; - v->macro_tile_block_height_c = - 32.0 - * v->read256_block_height_c[k]; + v->macro_tile_block_height_c = 4.0 * v->read256_block_height_c[k]; + } + else if (v->source_surface_mode[k] == dcn_bw_sw_64_kb_s || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_t || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_x || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_t || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_x) { + v->macro_tile_block_size_bytes_c = 64.0 * 1024; + v->macro_tile_block_height_c = 16.0 * v->read256_block_height_c[k]; } - v->macro_tile_block_width_c = - v->macro_tile_block_size_bytes_c - / dcn_bw_ceil2( - v->byte_per_pixel_in_detc[k], - 2.0) - / v->macro_tile_block_height_c; + else { + v->macro_tile_block_size_bytes_c = 256.0 * 1024; + v->macro_tile_block_height_c = 32.0 * v->read256_block_height_c[k]; + } + v->macro_tile_block_width_c = v->macro_tile_block_size_bytes_c /dcn_bw_ceil2(v->byte_per_pixel_in_detc[k], 2.0) / v->macro_tile_block_height_c; if (v->macro_tile_block_size_bytes_c <= 65536.0) { - v->data_pte_req_height_c = - v->macro_tile_block_height_c; - } else { - v->data_pte_req_height_c = - 16.0 - * v->read256_block_height_c[k]; + v->data_pte_req_height_c = v->macro_tile_block_height_c; + } + else { + v->data_pte_req_height_c = 16.0 * v->read256_block_height_c[k]; } - v->data_pte_req_width_c = - 4096.0 - / dcn_bw_ceil2( - v->byte_per_pixel_in_detc[k], - 2.0) - / v->data_pte_req_height_c - * 8; + v->data_pte_req_width_c = 4096.0 /dcn_bw_ceil2(v->byte_per_pixel_in_detc[k], 2.0) / v->data_pte_req_height_c * 8; if (v->source_surface_mode[k] == dcn_bw_sw_linear) { - v->dpte_bytes_per_row_c = - 64.0 - * (dcn_bw_ceil2( - (v->viewport_width[k] - / v->no_of_dpp[i][j][k] - / 2.0 - * dcn_bw_min2( - 128.0, - dcn_bw_pow( - 2.0, - dcn_bw_floor2( - dcn_bw_log( - v->pte_buffer_size_in_requests - * v->data_pte_req_width_c - / (v->viewport_width[k] - / v->no_of_dpp[i][j][k] - / 2.0), - 2.0), - 1.0))) - - 1.0) - / v->data_pte_req_width_c, - 1.0) - + 1); - } else if (v->source_scan[k] == dcn_bw_hor) { - v->dpte_bytes_per_row_c = - 64.0 - * (dcn_bw_ceil2( - (v->viewport_width[k] - / v->no_of_dpp[i][j][k] - / 2.0 - - 1.0) - / v->data_pte_req_width_c, - 1.0) - + 1); - } else { - v->dpte_bytes_per_row_c = - 64.0 - * (dcn_bw_ceil2( - (v->viewport_height[k] - / 2.0 - - 1.0) - / v->data_pte_req_height_c, - 1.0) - + 1); + v->dpte_bytes_per_row_c = 64.0 * (dcn_bw_ceil2((v->viewport_width[k] / v->no_of_dpp[i][j][k] / 2.0 * dcn_bw_min2(128.0, dcn_bw_pow(2.0,dcn_bw_floor2(dcn_bw_log(v->pte_buffer_size_in_requests * v->data_pte_req_width_c / (v->viewport_width[k] / v->no_of_dpp[i][j][k] / 2.0), 2.0), 1.0))) - 1.0) / v->data_pte_req_width_c, 1.0) + 1); } - } else { + else if (v->source_scan[k] == dcn_bw_hor) { + v->dpte_bytes_per_row_c = 64.0 * (dcn_bw_ceil2((v->viewport_width[k] / v->no_of_dpp[i][j][k] / 2.0 - 1.0) / v->data_pte_req_width_c, 1.0) + 1); + } + else { + v->dpte_bytes_per_row_c = 64.0 * (dcn_bw_ceil2((v->viewport_height[k] / 2.0 - 1.0) / v->data_pte_req_height_c, 1.0) + 1); + } + } + else { v->dpte_bytes_per_row_c = 0.0; } - } else { + } + else { v->dpte_bytes_per_row_c = 0.0; v->meta_pte_bytes_per_frame_c = 0.0; v->meta_row_bytes_c = 0.0; } - v->dpte_bytes_per_row[k] = v->dpte_bytes_per_row_y - + v->dpte_bytes_per_row_c; - v->meta_pte_bytes_per_frame[k] = v->meta_pte_bytes_per_frame_y - + v->meta_pte_bytes_per_frame_c; + v->dpte_bytes_per_row[k] = v->dpte_bytes_per_row_y + v->dpte_bytes_per_row_c; + v->meta_pte_bytes_per_frame[k] = v->meta_pte_bytes_per_frame_y + v->meta_pte_bytes_per_frame_c; v->meta_row_bytes[k] = v->meta_row_bytes_y + v->meta_row_bytes_c; - v->v_init_y = (v->v_ratio[k] + v->vtaps[k] + 1.0 - + v->interlace_output[k] * 0.5 * v->v_ratio[k]) - / 2.0; - v->prefill_y[k] = dcn_bw_floor2(v->v_init_y, 1.0); - v->max_num_sw_y[k] = - dcn_bw_ceil2( - (v->prefill_y[k] - 1.0) - / v->swath_height_yper_state[i][j][k], - 1.0) + 1; + v->v_init_y = (v->v_ratio[k] + v->vtaps[k] + 1.0 + v->interlace_output[k] * 0.5 * v->v_ratio[k]) / 2.0; + v->prefill_y[k] =dcn_bw_floor2(v->v_init_y, 1.0); + v->max_num_sw_y[k] =dcn_bw_ceil2((v->prefill_y[k] - 1.0) / v->swath_height_yper_state[i][j][k], 1.0) + 1; if (v->prefill_y[k] > 1.0) { - v->max_partial_sw_y = dcn_bw_mod( - (v->prefill_y[k] - 2.0), - v->swath_height_yper_state[i][j][k]); - } else { - v->max_partial_sw_y = - dcn_bw_mod( - (v->prefill_y[k] - + v->swath_height_yper_state[i][j][k] - - 2.0), - v->swath_height_yper_state[i][j][k]); - } - v->max_partial_sw_y = dcn_bw_max2(1.0, v->max_partial_sw_y); - v->prefetch_lines_y[k] = v->max_num_sw_y[k] - * v->swath_height_yper_state[i][j][k] - + v->max_partial_sw_y; - if ((v->source_pixel_format[k] != dcn_bw_rgb_sub_64 - && v->source_pixel_format[k] != dcn_bw_rgb_sub_32 - && v->source_pixel_format[k] != dcn_bw_rgb_sub_16)) { - v->v_init_c = (v->v_ratio[k] / 2.0 + v->vtaps[k] + 1.0 - + v->interlace_output[k] * 0.5 - * v->v_ratio[k] / 2.0) - / 2.0; - v->prefill_c[k] = dcn_bw_floor2(v->v_init_c, 1.0); - v->max_num_sw_c[k] = - dcn_bw_ceil2( - (v->prefill_c[k] - 1.0) - / v->swath_height_cper_state[i][j][k], - 1.0) + 1; + v->max_partial_sw_y =dcn_bw_mod((v->prefill_y[k] - 2.0), v->swath_height_yper_state[i][j][k]); + } + else { + v->max_partial_sw_y =dcn_bw_mod((v->prefill_y[k] + v->swath_height_yper_state[i][j][k] - 2.0), v->swath_height_yper_state[i][j][k]); + } + v->max_partial_sw_y =dcn_bw_max2(1.0, v->max_partial_sw_y); + v->prefetch_lines_y[k] = v->max_num_sw_y[k] * v->swath_height_yper_state[i][j][k] + v->max_partial_sw_y; + if ((v->source_pixel_format[k] != dcn_bw_rgb_sub_64 && v->source_pixel_format[k] != dcn_bw_rgb_sub_32 && v->source_pixel_format[k] != dcn_bw_rgb_sub_16)) { + v->v_init_c = (v->v_ratio[k] / 2.0 + v->vtaps[k] + 1.0 + v->interlace_output[k] * 0.5 * v->v_ratio[k] / 2.0) / 2.0; + v->prefill_c[k] =dcn_bw_floor2(v->v_init_c, 1.0); + v->max_num_sw_c[k] =dcn_bw_ceil2((v->prefill_c[k] - 1.0) / v->swath_height_cper_state[i][j][k], 1.0) + 1; if (v->prefill_c[k] > 1.0) { - v->max_partial_sw_c = - dcn_bw_mod( - (v->prefill_c[k] - - 2.0), - v->swath_height_cper_state[i][j][k]); - } else { - v->max_partial_sw_c = - dcn_bw_mod( - (v->prefill_c[k] - + v->swath_height_cper_state[i][j][k] - - 2.0), - v->swath_height_cper_state[i][j][k]); + v->max_partial_sw_c =dcn_bw_mod((v->prefill_c[k] - 2.0), v->swath_height_cper_state[i][j][k]); + } + else { + v->max_partial_sw_c =dcn_bw_mod((v->prefill_c[k] + v->swath_height_cper_state[i][j][k] - 2.0), v->swath_height_cper_state[i][j][k]); } - v->max_partial_sw_c = dcn_bw_max2(1.0, v->max_partial_sw_c); - v->prefetch_lines_c[k] = v->max_num_sw_c[k] - * v->swath_height_cper_state[i][j][k] - + v->max_partial_sw_c; - } else { + v->max_partial_sw_c =dcn_bw_max2(1.0, v->max_partial_sw_c); + v->prefetch_lines_c[k] = v->max_num_sw_c[k] * v->swath_height_cper_state[i][j][k] + v->max_partial_sw_c; + } + else { v->prefetch_lines_c[k] = 0.0; } - v->dst_x_after_scaler = 90.0 * v->pixel_clock[k] - / (v->required_dispclk[i][j] / (j + 1)) - + 42.0 * v->pixel_clock[k] - / v->required_dispclk[i][j]; + v->dst_x_after_scaler = 90.0 * v->pixel_clock[k] / (v->required_dispclk[i][j] / (j + 1)) + 42.0 * v->pixel_clock[k] / v->required_dispclk[i][j]; if (v->no_of_dpp[i][j][k] > 1.0) { - v->dst_x_after_scaler = v->dst_x_after_scaler - + v->scaler_rec_out_width[k] / 2.0; + v->dst_x_after_scaler = v->dst_x_after_scaler + v->scaler_rec_out_width[k] / 2.0; } if (v->output_format[k] == dcn_bw_420) { v->dst_y_after_scaler = 1.0; - } else { + } + else { v->dst_y_after_scaler = 0.0; } v->time_calc = 24.0 / v->projected_dcfclk_deep_sleep; - v->v_update_offset[k] = dcn_bw_ceil2(v->htotal[k] / 4.0, 1.0); - v->total_repeater_delay = v->max_inter_dcn_tile_repeaters - * (2.0 / (v->required_dispclk[i][j] / (j + 1)) - + 3.0 / v->required_dispclk[i][j]); - v->v_update_width[k] = (14.0 / v->projected_dcfclk_deep_sleep - + 12.0 / (v->required_dispclk[i][j] / (j + 1)) - + v->total_repeater_delay) * v->pixel_clock[k]; - v->v_ready_offset[k] = - dcn_bw_max2( - 150.0 - / (v->required_dispclk[i][j] - / (j - + 1)), - v->total_repeater_delay - + 20.0 - / v->projected_dcfclk_deep_sleep - + 10.0 - / (v->required_dispclk[i][j] - / (j - + 1))) - * v->pixel_clock[k]; - v->time_setup = (v->v_update_offset[k] + v->v_update_width[k] - + v->v_ready_offset[k]) / v->pixel_clock[k]; - v->extra_latency = - v->urgent_round_trip_and_out_of_order_latency_per_state[i] - + (v->total_number_of_active_dpp[i][j] - * v->pixel_chunk_size_in_kbyte - + v->total_number_of_dcc_active_dpp[i][j] - * v->meta_chunk_size) - * 1024.0 - / v->return_bw_per_state[i]; + v->v_update_offset[k] =dcn_bw_ceil2(v->htotal[k] / 4.0, 1.0); + v->total_repeater_delay = v->max_inter_dcn_tile_repeaters * (2.0 / (v->required_dispclk[i][j] / (j + 1)) + 3.0 / v->required_dispclk[i][j]); + v->v_update_width[k] = (14.0 / v->projected_dcfclk_deep_sleep + 12.0 / (v->required_dispclk[i][j] / (j + 1)) + v->total_repeater_delay) * v->pixel_clock[k]; + v->v_ready_offset[k] =dcn_bw_max2(150.0 / (v->required_dispclk[i][j] / (j + 1)), v->total_repeater_delay + 20.0 / v->projected_dcfclk_deep_sleep + 10.0 / (v->required_dispclk[i][j] / (j + 1))) * v->pixel_clock[k]; + v->time_setup = (v->v_update_offset[k] + v->v_update_width[k] + v->v_ready_offset[k]) / v->pixel_clock[k]; + v->extra_latency = v->urgent_round_trip_and_out_of_order_latency_per_state[i] + (v->total_number_of_active_dpp[i][j] * v->pixel_chunk_size_in_kbyte + v->total_number_of_dcc_active_dpp[i][j] * v->meta_chunk_size) * 1024.0 / v->return_bw_per_state[i]; if (v->pte_enable == dcn_bw_yes) { - v->extra_latency = v->extra_latency - + v->total_number_of_active_dpp[i][j] - * v->pte_chunk_size * 1024.0 - / v->return_bw_per_state[i]; + v->extra_latency = v->extra_latency + v->total_number_of_active_dpp[i][j] * v->pte_chunk_size * 1024.0 / v->return_bw_per_state[i]; } - if (v->can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one - == dcn_bw_yes) { + if (v->can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one == dcn_bw_yes) { v->maximum_vstartup = v->vtotal[k] - v->vactive[k] - 1.0; - } else { + } + else { v->maximum_vstartup = v->v_sync_plus_back_porch[k] - 1.0; } - v->line_times_for_prefetch[k] = v->maximum_vstartup - - v->urgent_latency - / (v->htotal[k] / v->pixel_clock[k]) - - (v->time_calc + v->time_setup) - / (v->htotal[k] / v->pixel_clock[k]) - - (v->dst_y_after_scaler - + v->dst_x_after_scaler - / v->htotal[k]); - v->line_times_for_prefetch[k] = dcn_bw_floor2( - 4.0 * (v->line_times_for_prefetch[k] + 0.125), - 1.0) / 4; - v->prefetch_bw[k] = - (v->meta_pte_bytes_per_frame[k] - + 2.0 * v->meta_row_bytes[k] - + 2.0 * v->dpte_bytes_per_row[k] - + v->prefetch_lines_y[k] - * v->swath_width_yper_state[i][j][k] - * dcn_bw_ceil2( - v->byte_per_pixel_in_dety[k], - 1.0) - + v->prefetch_lines_c[k] - * v->swath_width_yper_state[i][j][k] - / 2.0 - * dcn_bw_ceil2( - v->byte_per_pixel_in_detc[k], - 2.0)) - / (v->line_times_for_prefetch[k] - * v->htotal[k] - / v->pixel_clock[k]); + v->line_times_for_prefetch[k] = v->maximum_vstartup - v->urgent_latency / (v->htotal[k] / v->pixel_clock[k]) - (v->time_calc + v->time_setup) / (v->htotal[k] / v->pixel_clock[k]) - (v->dst_y_after_scaler + v->dst_x_after_scaler / v->htotal[k]); + v->line_times_for_prefetch[k] =dcn_bw_floor2(4.0 * (v->line_times_for_prefetch[k] + 0.125), 1.0) / 4; + v->prefetch_bw[k] = (v->meta_pte_bytes_per_frame[k] + 2.0 * v->meta_row_bytes[k] + 2.0 * v->dpte_bytes_per_row[k] + v->prefetch_lines_y[k] * v->swath_width_yper_state[i][j][k] *dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) + v->prefetch_lines_c[k] * v->swath_width_yper_state[i][j][k] / 2.0 *dcn_bw_ceil2(v->byte_per_pixel_in_detc[k], 2.0)) / (v->line_times_for_prefetch[k] * v->htotal[k] / v->pixel_clock[k]); } v->bw_available_for_immediate_flip = v->return_bw_per_state[i]; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - v->bw_available_for_immediate_flip = - v->bw_available_for_immediate_flip - - dcn_bw_max2( - v->read_bandwidth[k], - v->prefetch_bw[k]); + v->bw_available_for_immediate_flip = v->bw_available_for_immediate_flip -dcn_bw_max2(v->read_bandwidth[k], v->prefetch_bw[k]); } - v->total_immediate_flip_bytes[k] = 0.0; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - if ((v->source_pixel_format[k] != dcn_bw_yuv420_sub_8 - && v->source_pixel_format[k] != dcn_bw_yuv420_sub_10)) { - v->total_immediate_flip_bytes[k] = - v->total_immediate_flip_bytes[k] - + v->meta_pte_bytes_per_frame[k] - + v->meta_row_bytes[k] - + v->dpte_bytes_per_row[k]; + v->total_immediate_flip_bytes[k] = 0.0; + if ((v->source_pixel_format[k] != dcn_bw_yuv420_sub_8 && v->source_pixel_format[k] != dcn_bw_yuv420_sub_10)) { + v->total_immediate_flip_bytes[k] = v->total_immediate_flip_bytes[k] + v->meta_pte_bytes_per_frame[k] + v->meta_row_bytes[k] + v->dpte_bytes_per_row[k]; } } for (k = 0; k <= v->number_of_active_planes - 1; k++) { if (v->pte_enable == dcn_bw_yes && v->dcc_enable[k] == dcn_bw_yes) { - v->time_for_meta_pte_with_immediate_flip = - dcn_bw_max5( - v->meta_pte_bytes_per_frame[k] - / v->prefetch_bw[k], - v->meta_pte_bytes_per_frame[k] - * v->total_immediate_flip_bytes[k] - / (v->bw_available_for_immediate_flip - * (v->meta_pte_bytes_per_frame[k] - + v->meta_row_bytes[k] - + v->dpte_bytes_per_row[k])), - v->extra_latency, - v->urgent_latency, - v->htotal[k] - / v->pixel_clock[k] - / 4.0); - v->time_for_meta_pte_without_immediate_flip = dcn_bw_max3( - v->meta_pte_bytes_per_frame[k] - / v->prefetch_bw[k], - v->extra_latency, - v->htotal[k] / v->pixel_clock[k] / 4.0); - } else { - v->time_for_meta_pte_with_immediate_flip = v->htotal[k] - / v->pixel_clock[k] / 4.0; - v->time_for_meta_pte_without_immediate_flip = v->htotal[k] - / v->pixel_clock[k] / 4.0; + v->time_for_meta_pte_with_immediate_flip =dcn_bw_max5(v->meta_pte_bytes_per_frame[k] / v->prefetch_bw[k], v->meta_pte_bytes_per_frame[k] * v->total_immediate_flip_bytes[k] / (v->bw_available_for_immediate_flip * (v->meta_pte_bytes_per_frame[k] + v->meta_row_bytes[k] + v->dpte_bytes_per_row[k])), v->extra_latency, v->urgent_latency, v->htotal[k] / v->pixel_clock[k] / 4.0); + v->time_for_meta_pte_without_immediate_flip =dcn_bw_max3(v->meta_pte_bytes_per_frame[k] / v->prefetch_bw[k], v->extra_latency, v->htotal[k] / v->pixel_clock[k] / 4.0); + } + else { + v->time_for_meta_pte_with_immediate_flip = v->htotal[k] / v->pixel_clock[k] / 4.0; + v->time_for_meta_pte_without_immediate_flip = v->htotal[k] / v->pixel_clock[k] / 4.0; } if (v->pte_enable == dcn_bw_yes || v->dcc_enable[k] == dcn_bw_yes) { - v->time_for_meta_and_dpte_row_with_immediate_flip = - dcn_bw_max5( - (v->meta_row_bytes[k] - + v->dpte_bytes_per_row[k]) - / v->prefetch_bw[k], - (v->meta_row_bytes[k] - + v->dpte_bytes_per_row[k]) - * v->total_immediate_flip_bytes[k] - / (v->bw_available_for_immediate_flip - * (v->meta_pte_bytes_per_frame[k] - + v->meta_row_bytes[k] - + v->dpte_bytes_per_row[k])), - v->htotal[k] - / v->pixel_clock[k] - - v->time_for_meta_pte_with_immediate_flip, - v->extra_latency, - 2.0 * v->urgent_latency); - v->time_for_meta_and_dpte_row_without_immediate_flip = - dcn_bw_max3( - (v->meta_row_bytes[k] - + v->dpte_bytes_per_row[k]) - / v->prefetch_bw[k], - v->htotal[k] - / v->pixel_clock[k] - - v->time_for_meta_pte_without_immediate_flip, - v->extra_latency); - } else { - v->time_for_meta_and_dpte_row_with_immediate_flip = - dcn_bw_max2( - v->htotal[k] - / v->pixel_clock[k] - - v->time_for_meta_pte_with_immediate_flip, - v->extra_latency - - v->time_for_meta_pte_with_immediate_flip); - v->time_for_meta_and_dpte_row_without_immediate_flip = - dcn_bw_max2( - v->htotal[k] - / v->pixel_clock[k] - - v->time_for_meta_pte_without_immediate_flip, - v->extra_latency - - v->time_for_meta_pte_without_immediate_flip); - } - v->lines_for_meta_pte_with_immediate_flip[k] = - dcn_bw_floor2( - 4.0 - * (v->time_for_meta_pte_with_immediate_flip - / (v->htotal[k] - / v->pixel_clock[k]) - + 0.125), - 1.0) / 4; - v->lines_for_meta_pte_without_immediate_flip[k] = - dcn_bw_floor2( - 4.0 - * (v->time_for_meta_pte_without_immediate_flip - / (v->htotal[k] - / v->pixel_clock[k]) - + 0.125), - 1.0) / 4; - v->lines_for_meta_and_dpte_row_with_immediate_flip[k] = - dcn_bw_floor2( - 4.0 - * (v->time_for_meta_and_dpte_row_with_immediate_flip - / (v->htotal[k] - / v->pixel_clock[k]) - + 0.125), - 1.0) / 4; - v->lines_for_meta_and_dpte_row_without_immediate_flip[k] = - dcn_bw_floor2( - 4.0 - * (v->time_for_meta_and_dpte_row_without_immediate_flip - / (v->htotal[k] - / v->pixel_clock[k]) - + 0.125), - 1.0) / 4; - v->line_times_to_request_prefetch_pixel_data_with_immediate_flip = - v->line_times_for_prefetch[k] - - v->lines_for_meta_pte_with_immediate_flip[k] - - v->lines_for_meta_and_dpte_row_with_immediate_flip[k]; - v->line_times_to_request_prefetch_pixel_data_without_immediate_flip = - v->line_times_for_prefetch[k] - - v->lines_for_meta_pte_without_immediate_flip[k] - - v->lines_for_meta_and_dpte_row_without_immediate_flip[k]; - if (v->line_times_to_request_prefetch_pixel_data_with_immediate_flip - > 0.0) { - v->v_ratio_pre_ywith_immediate_flip[i][j][k] = - v->prefetch_lines_y[k] - / v->line_times_to_request_prefetch_pixel_data_with_immediate_flip; + v->time_for_meta_and_dpte_row_with_immediate_flip =dcn_bw_max5((v->meta_row_bytes[k] + v->dpte_bytes_per_row[k]) / v->prefetch_bw[k], (v->meta_row_bytes[k] + v->dpte_bytes_per_row[k]) * v->total_immediate_flip_bytes[k] / (v->bw_available_for_immediate_flip * (v->meta_pte_bytes_per_frame[k] + v->meta_row_bytes[k] + v->dpte_bytes_per_row[k])), v->htotal[k] / v->pixel_clock[k] - v->time_for_meta_pte_with_immediate_flip, v->extra_latency, 2.0 * v->urgent_latency); + v->time_for_meta_and_dpte_row_without_immediate_flip =dcn_bw_max3((v->meta_row_bytes[k] + v->dpte_bytes_per_row[k]) / v->prefetch_bw[k], v->htotal[k] / v->pixel_clock[k] - v->time_for_meta_pte_without_immediate_flip, v->extra_latency); + } + else { + v->time_for_meta_and_dpte_row_with_immediate_flip =dcn_bw_max2(v->htotal[k] / v->pixel_clock[k] - v->time_for_meta_pte_with_immediate_flip, v->extra_latency - v->time_for_meta_pte_with_immediate_flip); + v->time_for_meta_and_dpte_row_without_immediate_flip =dcn_bw_max2(v->htotal[k] / v->pixel_clock[k] - v->time_for_meta_pte_without_immediate_flip, v->extra_latency - v->time_for_meta_pte_without_immediate_flip); + } + v->lines_for_meta_pte_with_immediate_flip[k] =dcn_bw_floor2(4.0 * (v->time_for_meta_pte_with_immediate_flip / (v->htotal[k] / v->pixel_clock[k]) + 0.125), 1.0) / 4; + v->lines_for_meta_pte_without_immediate_flip[k] =dcn_bw_floor2(4.0 * (v->time_for_meta_pte_without_immediate_flip / (v->htotal[k] / v->pixel_clock[k]) + 0.125), 1.0) / 4; + v->lines_for_meta_and_dpte_row_with_immediate_flip[k] =dcn_bw_floor2(4.0 * (v->time_for_meta_and_dpte_row_with_immediate_flip / (v->htotal[k] / v->pixel_clock[k]) + 0.125), 1.0) / 4; + v->lines_for_meta_and_dpte_row_without_immediate_flip[k] =dcn_bw_floor2(4.0 * (v->time_for_meta_and_dpte_row_without_immediate_flip / (v->htotal[k] / v->pixel_clock[k]) + 0.125), 1.0) / 4; + v->line_times_to_request_prefetch_pixel_data_with_immediate_flip = v->line_times_for_prefetch[k] - v->lines_for_meta_pte_with_immediate_flip[k] - v->lines_for_meta_and_dpte_row_with_immediate_flip[k]; + v->line_times_to_request_prefetch_pixel_data_without_immediate_flip = v->line_times_for_prefetch[k] - v->lines_for_meta_pte_without_immediate_flip[k] - v->lines_for_meta_and_dpte_row_without_immediate_flip[k]; + if (v->line_times_to_request_prefetch_pixel_data_with_immediate_flip > 0.0) { + v->v_ratio_pre_ywith_immediate_flip[i][j][k] = v->prefetch_lines_y[k] / v->line_times_to_request_prefetch_pixel_data_with_immediate_flip; if ((v->swath_height_yper_state[i][j][k] > 4.0)) { - if (v->line_times_to_request_prefetch_pixel_data_with_immediate_flip - - (v->prefill_y[k] - 3.0) / 2.0 - > 0.0) { - v->v_ratio_pre_ywith_immediate_flip[i][j][k] = - dcn_bw_max2( - v->v_ratio_pre_ywith_immediate_flip[i][j][k], - (v->max_num_sw_y[k] - * v->swath_height_yper_state[i][j][k]) - / (v->line_times_to_request_prefetch_pixel_data_with_immediate_flip - - (v->prefill_y[k] - - 3.0) - / 2.0)); - } else { - v->v_ratio_pre_ywith_immediate_flip[i][j][k] = - 999999.0; + if (v->line_times_to_request_prefetch_pixel_data_with_immediate_flip - (v->prefill_y[k] - 3.0) / 2.0 > 0.0) { + v->v_ratio_pre_ywith_immediate_flip[i][j][k] =dcn_bw_max2(v->v_ratio_pre_ywith_immediate_flip[i][j][k], (v->max_num_sw_y[k] * v->swath_height_yper_state[i][j][k]) / (v->line_times_to_request_prefetch_pixel_data_with_immediate_flip - (v->prefill_y[k] - 3.0) / 2.0)); + } + else { + v->v_ratio_pre_ywith_immediate_flip[i][j][k] = 999999.0; } } - v->v_ratio_pre_cwith_immediate_flip[i][j][k] = - v->prefetch_lines_c[k] - / v->line_times_to_request_prefetch_pixel_data_with_immediate_flip; + v->v_ratio_pre_cwith_immediate_flip[i][j][k] = v->prefetch_lines_c[k] / v->line_times_to_request_prefetch_pixel_data_with_immediate_flip; if ((v->swath_height_cper_state[i][j][k] > 4.0)) { - if (v->line_times_to_request_prefetch_pixel_data_with_immediate_flip - - (v->prefill_c[k] - 3.0) / 2.0 - > 0.0) { - v->v_ratio_pre_cwith_immediate_flip[i][j][k] = - dcn_bw_max2( - v->v_ratio_pre_cwith_immediate_flip[i][j][k], - (v->max_num_sw_c[k] - * v->swath_height_cper_state[i][j][k]) - / (v->line_times_to_request_prefetch_pixel_data_with_immediate_flip - - (v->prefill_c[k] - - 3.0) - / 2.0)); - } else { - v->v_ratio_pre_cwith_immediate_flip[i][j][k] = - 999999.0; + if (v->line_times_to_request_prefetch_pixel_data_with_immediate_flip - (v->prefill_c[k] - 3.0) / 2.0 > 0.0) { + v->v_ratio_pre_cwith_immediate_flip[i][j][k] =dcn_bw_max2(v->v_ratio_pre_cwith_immediate_flip[i][j][k], (v->max_num_sw_c[k] * v->swath_height_cper_state[i][j][k]) / (v->line_times_to_request_prefetch_pixel_data_with_immediate_flip - (v->prefill_c[k] - 3.0) / 2.0)); + } + else { + v->v_ratio_pre_cwith_immediate_flip[i][j][k] = 999999.0; } } - v->required_prefetch_pixel_data_bw_with_immediate_flip[i][j][k] = - v->no_of_dpp[i][j][k] - * (v->prefetch_lines_y[k] - / v->line_times_to_request_prefetch_pixel_data_with_immediate_flip - * dcn_bw_ceil2( - v->byte_per_pixel_in_dety[k], - 1.0) - + v->prefetch_lines_c[k] - / v->line_times_to_request_prefetch_pixel_data_with_immediate_flip - * dcn_bw_ceil2( - v->byte_per_pixel_in_detc[k], - 2.0) - / 2.0) - * v->swath_width_yper_state[i][j][k] - / (v->htotal[k] - / v->pixel_clock[k]); - } else { + v->required_prefetch_pixel_data_bw_with_immediate_flip[i][j][k] = v->no_of_dpp[i][j][k] * (v->prefetch_lines_y[k] / v->line_times_to_request_prefetch_pixel_data_with_immediate_flip *dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) + v->prefetch_lines_c[k] / v->line_times_to_request_prefetch_pixel_data_with_immediate_flip *dcn_bw_ceil2(v->byte_per_pixel_in_detc[k], 2.0) / 2.0) * v->swath_width_yper_state[i][j][k] / (v->htotal[k] / v->pixel_clock[k]); + } + else { v->v_ratio_pre_ywith_immediate_flip[i][j][k] = 999999.0; v->v_ratio_pre_cwith_immediate_flip[i][j][k] = 999999.0; - v->required_prefetch_pixel_data_bw_with_immediate_flip[i][j][k] = - 999999.0; - } - if (v->line_times_to_request_prefetch_pixel_data_without_immediate_flip - > 0.0) { - v->v_ratio_pre_ywithout_immediate_flip[i][j][k] = - v->prefetch_lines_y[k] - / v->line_times_to_request_prefetch_pixel_data_without_immediate_flip; + v->required_prefetch_pixel_data_bw_with_immediate_flip[i][j][k] = 999999.0; + } + if (v->line_times_to_request_prefetch_pixel_data_without_immediate_flip > 0.0) { + v->v_ratio_pre_ywithout_immediate_flip[i][j][k] = v->prefetch_lines_y[k] / v->line_times_to_request_prefetch_pixel_data_without_immediate_flip; if ((v->swath_height_yper_state[i][j][k] > 4.0)) { - if (v->line_times_to_request_prefetch_pixel_data_without_immediate_flip - - (v->prefill_y[k] - 3.0) / 2.0 - > 0.0) { - v->v_ratio_pre_ywithout_immediate_flip[i][j][k] = - dcn_bw_max2( - v->v_ratio_pre_ywithout_immediate_flip[i][j][k], - (v->max_num_sw_y[k] - * v->swath_height_yper_state[i][j][k]) - / (v->line_times_to_request_prefetch_pixel_data_without_immediate_flip - - (v->prefill_y[k] - - 3.0) - / 2.0)); - } else { - v->v_ratio_pre_ywithout_immediate_flip[i][j][k] = - 999999.0; + if (v->line_times_to_request_prefetch_pixel_data_without_immediate_flip - (v->prefill_y[k] - 3.0) / 2.0 > 0.0) { + v->v_ratio_pre_ywithout_immediate_flip[i][j][k] =dcn_bw_max2(v->v_ratio_pre_ywithout_immediate_flip[i][j][k], (v->max_num_sw_y[k] * v->swath_height_yper_state[i][j][k]) / (v->line_times_to_request_prefetch_pixel_data_without_immediate_flip - (v->prefill_y[k] - 3.0) / 2.0)); + } + else { + v->v_ratio_pre_ywithout_immediate_flip[i][j][k] = 999999.0; } } - v->v_ratio_pre_cwithout_immediate_flip[i][j][k] = - v->prefetch_lines_c[k] - / v->line_times_to_request_prefetch_pixel_data_without_immediate_flip; + v->v_ratio_pre_cwithout_immediate_flip[i][j][k] = v->prefetch_lines_c[k] / v->line_times_to_request_prefetch_pixel_data_without_immediate_flip; if ((v->swath_height_cper_state[i][j][k] > 4.0)) { - if (v->line_times_to_request_prefetch_pixel_data_without_immediate_flip - - (v->prefill_c[k] - 3.0) / 2.0 - > 0.0) { - v->v_ratio_pre_cwithout_immediate_flip[i][j][k] = - dcn_bw_max2( - v->v_ratio_pre_cwithout_immediate_flip[i][j][k], - (v->max_num_sw_c[k] - * v->swath_height_cper_state[i][j][k]) - / (v->line_times_to_request_prefetch_pixel_data_without_immediate_flip - - (v->prefill_c[k] - - 3.0) - / 2.0)); - } else { - v->v_ratio_pre_cwithout_immediate_flip[i][j][k] = - 999999.0; + if (v->line_times_to_request_prefetch_pixel_data_without_immediate_flip - (v->prefill_c[k] - 3.0) / 2.0 > 0.0) { + v->v_ratio_pre_cwithout_immediate_flip[i][j][k] =dcn_bw_max2(v->v_ratio_pre_cwithout_immediate_flip[i][j][k], (v->max_num_sw_c[k] * v->swath_height_cper_state[i][j][k]) / (v->line_times_to_request_prefetch_pixel_data_without_immediate_flip - (v->prefill_c[k] - 3.0) / 2.0)); + } + else { + v->v_ratio_pre_cwithout_immediate_flip[i][j][k] = 999999.0; } } - v->required_prefetch_pixel_data_bw_without_immediate_flip[i][j][k] = - v->no_of_dpp[i][j][k] - * (v->prefetch_lines_y[k] - / v->line_times_to_request_prefetch_pixel_data_without_immediate_flip - * dcn_bw_ceil2( - v->byte_per_pixel_in_dety[k], - 1.0) - + v->prefetch_lines_c[k] - / v->line_times_to_request_prefetch_pixel_data_without_immediate_flip - * dcn_bw_ceil2( - v->byte_per_pixel_in_detc[k], - 2.0) - / 2.0) - * v->swath_width_yper_state[i][j][k] - / (v->htotal[k] - / v->pixel_clock[k]); - } else { + v->required_prefetch_pixel_data_bw_without_immediate_flip[i][j][k] = v->no_of_dpp[i][j][k] * (v->prefetch_lines_y[k] / v->line_times_to_request_prefetch_pixel_data_without_immediate_flip *dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) + v->prefetch_lines_c[k] / v->line_times_to_request_prefetch_pixel_data_without_immediate_flip *dcn_bw_ceil2(v->byte_per_pixel_in_detc[k], 2.0) / 2.0) * v->swath_width_yper_state[i][j][k] / (v->htotal[k] / v->pixel_clock[k]); + } + else { v->v_ratio_pre_ywithout_immediate_flip[i][j][k] = 999999.0; v->v_ratio_pre_cwithout_immediate_flip[i][j][k] = 999999.0; - v->required_prefetch_pixel_data_bw_without_immediate_flip[i][j][k] = - 999999.0; + v->required_prefetch_pixel_data_bw_without_immediate_flip[i][j][k] = 999999.0; } } v->maximum_read_bandwidth_with_prefetch_with_immediate_flip = 0.0; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - if ((v->source_pixel_format[k] != dcn_bw_yuv420_sub_8 - && v->source_pixel_format[k] != dcn_bw_yuv420_sub_10)) { - v->maximum_read_bandwidth_with_prefetch_with_immediate_flip = - v->maximum_read_bandwidth_with_prefetch_with_immediate_flip - + dcn_bw_max2( - v->read_bandwidth[k], - v->required_prefetch_pixel_data_bw_with_immediate_flip[i][j][k]) - + dcn_bw_max2( - v->meta_pte_bytes_per_frame[k] - / (v->lines_for_meta_pte_with_immediate_flip[k] - * v->htotal[k] - / v->pixel_clock[k]), - (v->meta_row_bytes[k] - + v->dpte_bytes_per_row[k]) - / (v->lines_for_meta_and_dpte_row_with_immediate_flip[k] - * v->htotal[k] - / v->pixel_clock[k])); - } else { - v->maximum_read_bandwidth_with_prefetch_with_immediate_flip = - v->maximum_read_bandwidth_with_prefetch_with_immediate_flip - + dcn_bw_max2( - v->read_bandwidth[k], - v->required_prefetch_pixel_data_bw_without_immediate_flip[i][j][k]); + if ((v->source_pixel_format[k] != dcn_bw_yuv420_sub_8 && v->source_pixel_format[k] != dcn_bw_yuv420_sub_10)) { + v->maximum_read_bandwidth_with_prefetch_with_immediate_flip = v->maximum_read_bandwidth_with_prefetch_with_immediate_flip +dcn_bw_max2(v->read_bandwidth[k], v->required_prefetch_pixel_data_bw_with_immediate_flip[i][j][k]) +dcn_bw_max2(v->meta_pte_bytes_per_frame[k] / (v->lines_for_meta_pte_with_immediate_flip[k] * v->htotal[k] / v->pixel_clock[k]), (v->meta_row_bytes[k] + v->dpte_bytes_per_row[k]) / (v->lines_for_meta_and_dpte_row_with_immediate_flip[k] * v->htotal[k] / v->pixel_clock[k])); + } + else { + v->maximum_read_bandwidth_with_prefetch_with_immediate_flip = v->maximum_read_bandwidth_with_prefetch_with_immediate_flip +dcn_bw_max2(v->read_bandwidth[k], v->required_prefetch_pixel_data_bw_without_immediate_flip[i][j][k]); } } v->maximum_read_bandwidth_with_prefetch_without_immediate_flip = 0.0; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - v->maximum_read_bandwidth_with_prefetch_without_immediate_flip = - v->maximum_read_bandwidth_with_prefetch_without_immediate_flip - + dcn_bw_max2( - v->read_bandwidth[k], - v->required_prefetch_pixel_data_bw_without_immediate_flip[i][j][k]); + v->maximum_read_bandwidth_with_prefetch_without_immediate_flip = v->maximum_read_bandwidth_with_prefetch_without_immediate_flip +dcn_bw_max2(v->read_bandwidth[k], v->required_prefetch_pixel_data_bw_without_immediate_flip[i][j][k]); } v->prefetch_supported_with_immediate_flip[i][j] = dcn_bw_yes; - if (v->maximum_read_bandwidth_with_prefetch_with_immediate_flip - > v->return_bw_per_state[i]) { + if (v->maximum_read_bandwidth_with_prefetch_with_immediate_flip > v->return_bw_per_state[i]) { v->prefetch_supported_with_immediate_flip[i][j] = dcn_bw_no; } for (k = 0; k <= v->number_of_active_planes - 1; k++) { - if (v->line_times_for_prefetch[k] < 2.0 - || v->lines_for_meta_pte_with_immediate_flip[k] - >= 8.0 - || v->lines_for_meta_and_dpte_row_with_immediate_flip[k] - >= 16.0) { + if (v->line_times_for_prefetch[k] < 2.0 || v->lines_for_meta_pte_with_immediate_flip[k] >= 8.0 || v->lines_for_meta_and_dpte_row_with_immediate_flip[k] >= 16.0) { v->prefetch_supported_with_immediate_flip[i][j] = dcn_bw_no; } } v->prefetch_supported_without_immediate_flip[i][j] = dcn_bw_yes; - if (v->maximum_read_bandwidth_with_prefetch_without_immediate_flip - > v->return_bw_per_state[i]) { + if (v->maximum_read_bandwidth_with_prefetch_without_immediate_flip > v->return_bw_per_state[i]) { v->prefetch_supported_without_immediate_flip[i][j] = dcn_bw_no; } for (k = 0; k <= v->number_of_active_planes - 1; k++) { - if (v->line_times_for_prefetch[k] < 2.0 - || v->lines_for_meta_pte_without_immediate_flip[k] - >= 8.0 - || v->lines_for_meta_and_dpte_row_without_immediate_flip[k] - >= 16.0) { - v->prefetch_supported_without_immediate_flip[i][j] = - dcn_bw_no; + if (v->line_times_for_prefetch[k] < 2.0 || v->lines_for_meta_pte_without_immediate_flip[k] >= 8.0 || v->lines_for_meta_and_dpte_row_without_immediate_flip[k] >= 16.0) { + v->prefetch_supported_without_immediate_flip[i][j] = dcn_bw_no; } } } @@ -1894,31 +904,14 @@ void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v) for (j = 0; j <= 1; j++) { v->v_ratio_in_prefetch_supported_with_immediate_flip[i][j] = dcn_bw_yes; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - if ((((v->source_pixel_format[k] != dcn_bw_yuv420_sub_8 - && v->source_pixel_format[k] != dcn_bw_yuv420_sub_10) - && (v->v_ratio_pre_ywith_immediate_flip[i][j][k] - > 4.0 - || v->v_ratio_pre_cwith_immediate_flip[i][j][k] - > 4.0)) - || ((v->source_pixel_format[k] - == dcn_bw_yuv420_sub_8 - || v->source_pixel_format[k] - == dcn_bw_yuv420_sub_10) - && (v->v_ratio_pre_ywithout_immediate_flip[i][j][k] - > 4.0 - || v->v_ratio_pre_cwithout_immediate_flip[i][j][k] - > 4.0)))) { - v->v_ratio_in_prefetch_supported_with_immediate_flip[i][j] = - dcn_bw_no; + if ((((v->source_pixel_format[k] != dcn_bw_yuv420_sub_8 && v->source_pixel_format[k] != dcn_bw_yuv420_sub_10) && (v->v_ratio_pre_ywith_immediate_flip[i][j][k] > 4.0 || v->v_ratio_pre_cwith_immediate_flip[i][j][k] > 4.0)) || ((v->source_pixel_format[k] == dcn_bw_yuv420_sub_8 || v->source_pixel_format[k] == dcn_bw_yuv420_sub_10) && (v->v_ratio_pre_ywithout_immediate_flip[i][j][k] > 4.0 || v->v_ratio_pre_cwithout_immediate_flip[i][j][k] > 4.0)))) { + v->v_ratio_in_prefetch_supported_with_immediate_flip[i][j] = dcn_bw_no; } } v->v_ratio_in_prefetch_supported_without_immediate_flip[i][j] = dcn_bw_yes; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - if ((v->v_ratio_pre_ywithout_immediate_flip[i][j][k] > 4.0 - || v->v_ratio_pre_cwithout_immediate_flip[i][j][k] - > 4.0)) { - v->v_ratio_in_prefetch_supported_without_immediate_flip[i][j] = - dcn_bw_no; + if ((v->v_ratio_pre_ywithout_immediate_flip[i][j][k] > 4.0 || v->v_ratio_pre_cwithout_immediate_flip[i][j][k] > 4.0)) { + v->v_ratio_in_prefetch_supported_without_immediate_flip[i][j] = dcn_bw_no; } } } @@ -1927,57 +920,41 @@ void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v) for (i = number_of_states_plus_one; i >= 0; i--) { for (j = 0; j <= 1; j++) { - if (v->scale_ratio_support == dcn_bw_yes - && v->source_format_pixel_and_scan_support == dcn_bw_yes - && v->viewport_size_support == dcn_bw_yes - && v->bandwidth_support[i] == dcn_bw_yes - && v->dio_support[i] == dcn_bw_yes - && v->urgent_latency_support[i][j] == dcn_bw_yes - && v->rob_support[i] == dcn_bw_yes - && v->dispclk_dppclk_support[i][j] == dcn_bw_yes - && v->total_available_pipes_support[i][j] == dcn_bw_yes - && v->total_available_writeback_support == dcn_bw_yes - && v->writeback_latency_support == dcn_bw_yes) { - if (v->prefetch_supported_with_immediate_flip[i][j] == dcn_bw_yes - && v->v_ratio_in_prefetch_supported_with_immediate_flip[i][j] - == dcn_bw_yes) { + if (v->scale_ratio_support == dcn_bw_yes && v->source_format_pixel_and_scan_support == dcn_bw_yes && v->viewport_size_support == dcn_bw_yes && v->bandwidth_support[i] == dcn_bw_yes && v->dio_support[i] == dcn_bw_yes && v->urgent_latency_support[i][j] == dcn_bw_yes && v->rob_support[i] == dcn_bw_yes && v->dispclk_dppclk_support[i][j] == dcn_bw_yes && v->total_available_pipes_support[i][j] == dcn_bw_yes && v->total_available_writeback_support == dcn_bw_yes && v->writeback_latency_support == dcn_bw_yes) { + if (v->prefetch_supported_with_immediate_flip[i][j] == dcn_bw_yes && v->v_ratio_in_prefetch_supported_with_immediate_flip[i][j] == dcn_bw_yes) { v->mode_support_with_immediate_flip[i][j] = dcn_bw_yes; - } else { + } + else { v->mode_support_with_immediate_flip[i][j] = dcn_bw_no; } - if (v->prefetch_supported_without_immediate_flip[i][j] == dcn_bw_yes - && v->v_ratio_in_prefetch_supported_without_immediate_flip[i][j] - == dcn_bw_yes) { + if (v->prefetch_supported_without_immediate_flip[i][j] == dcn_bw_yes && v->v_ratio_in_prefetch_supported_without_immediate_flip[i][j] == dcn_bw_yes) { v->mode_support_without_immediate_flip[i][j] = dcn_bw_yes; - } else { + } + else { v->mode_support_without_immediate_flip[i][j] = dcn_bw_no; } - } else { + } + else { v->mode_support_with_immediate_flip[i][j] = dcn_bw_no; v->mode_support_without_immediate_flip[i][j] = dcn_bw_no; } } } for (i = number_of_states_plus_one; i >= 0; i--) { - if ((i == number_of_states_plus_one - || v->mode_support_with_immediate_flip[i][1] == dcn_bw_yes - || v->mode_support_with_immediate_flip[i][0] == dcn_bw_yes) - && i >= v->voltage_override_level) { + if ((i == number_of_states_plus_one || v->mode_support_with_immediate_flip[i][1] == dcn_bw_yes || v->mode_support_with_immediate_flip[i][0] == dcn_bw_yes) && i >= v->voltage_override_level) { v->voltage_level_with_immediate_flip = i; } } for (i = number_of_states_plus_one; i >= 0; i--) { - if ((i == number_of_states_plus_one - || v->mode_support_without_immediate_flip[i][1] == dcn_bw_yes - || v->mode_support_without_immediate_flip[i][0] == dcn_bw_yes) - && i >= v->voltage_override_level) { + if ((i == number_of_states_plus_one || v->mode_support_without_immediate_flip[i][1] == dcn_bw_yes || v->mode_support_without_immediate_flip[i][0] == dcn_bw_yes) && i >= v->voltage_override_level) { v->voltage_level_without_immediate_flip = i; } } if (v->voltage_level_with_immediate_flip == number_of_states_plus_one) { v->immediate_flip_supported = dcn_bw_no; v->voltage_level = v->voltage_level_without_immediate_flip; - } else { + } + else { v->immediate_flip_supported = dcn_bw_yes; v->voltage_level = v->voltage_level_with_immediate_flip; } @@ -1988,38 +965,27 @@ void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v) for (k = 0; k <= v->number_of_active_planes - 1; k++) { v->dpp_per_plane_per_ratio[j][k] = v->no_of_dpp[v->voltage_level][j][k]; } - v->dispclk_dppclk_support_per_ratio[j] = - v->dispclk_dppclk_support[v->voltage_level][j]; + v->dispclk_dppclk_support_per_ratio[j] = v->dispclk_dppclk_support[v->voltage_level][j]; } v->max_phyclk = v->phyclk_per_state[v->voltage_level]; } void display_pipe_configuration(struct dcn_bw_internal_vars *v) { - int j, k; + int j; + int k; /*display pipe configuration*/ for (j = 0; j <= 1; j++) { v->total_number_of_active_dpp_per_ratio[j] = 0.0; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - v->total_number_of_active_dpp_per_ratio[j] = - v->total_number_of_active_dpp_per_ratio[j] - + v->dpp_per_plane_per_ratio[j][k]; - } - } - if ((v->dispclk_dppclk_support_per_ratio[0] == dcn_bw_yes - && v->dispclk_dppclk_support_per_ratio[1] == dcn_bw_no) - || (v->dispclk_dppclk_support_per_ratio[0] - == v->dispclk_dppclk_support_per_ratio[1] - && (v->total_number_of_active_dpp_per_ratio[0] - < v->total_number_of_active_dpp_per_ratio[1] - || (((v->total_number_of_active_dpp_per_ratio[0] - == v->total_number_of_active_dpp_per_ratio[1]) - && v->required_dispclk_per_ratio[0] - <= 0.5 - * v->required_dispclk_per_ratio[1]))))) { + v->total_number_of_active_dpp_per_ratio[j] = v->total_number_of_active_dpp_per_ratio[j] + v->dpp_per_plane_per_ratio[j][k]; + } + } + if ((v->dispclk_dppclk_support_per_ratio[0] == dcn_bw_yes && v->dispclk_dppclk_support_per_ratio[1] == dcn_bw_no) || (v->dispclk_dppclk_support_per_ratio[0] == v->dispclk_dppclk_support_per_ratio[1] && (v->total_number_of_active_dpp_per_ratio[0] < v->total_number_of_active_dpp_per_ratio[1] || (((v->total_number_of_active_dpp_per_ratio[0] == v->total_number_of_active_dpp_per_ratio[1]) && v->required_dispclk_per_ratio[0] <= 0.5 * v->required_dispclk_per_ratio[1]))))) { v->dispclk_dppclk_ratio = 1; v->final_error_message = v->error_message[0]; - } else { + } + else { v->dispclk_dppclk_ratio = 2; v->final_error_message = v->error_message[1]; } @@ -2030,159 +996,139 @@ void display_pipe_configuration(struct dcn_bw_internal_vars *v) if (v->source_pixel_format[k] == dcn_bw_rgb_sub_64) { v->byte_per_pix_dety = 8.0; v->byte_per_pix_detc = 0.0; - } else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_32) { + } + else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_32) { v->byte_per_pix_dety = 4.0; v->byte_per_pix_detc = 0.0; - } else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_16) { + } + else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_16) { v->byte_per_pix_dety = 2.0; v->byte_per_pix_detc = 0.0; - } else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_8) { + } + else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_8) { v->byte_per_pix_dety = 1.0; v->byte_per_pix_detc = 2.0; - } else { - v->byte_per_pix_dety = 4.0f / 3; - v->byte_per_pix_detc = 8.0f / 3; } - if ((v->source_pixel_format[k] == dcn_bw_rgb_sub_64 - || v->source_pixel_format[k] == dcn_bw_rgb_sub_32 - || v->source_pixel_format[k] == dcn_bw_rgb_sub_16)) { + else { + v->byte_per_pix_dety = 4.0f / 3.0f; + v->byte_per_pix_detc = 8.0f / 3.0f; + } + if ((v->source_pixel_format[k] == dcn_bw_rgb_sub_64 || v->source_pixel_format[k] == dcn_bw_rgb_sub_32 || v->source_pixel_format[k] == dcn_bw_rgb_sub_16)) { if (v->source_surface_mode[k] == dcn_bw_sw_linear) { v->read256_bytes_block_height_y = 1.0; - } else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_64) { + } + else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_64) { v->read256_bytes_block_height_y = 4.0; - } else { + } + else { v->read256_bytes_block_height_y = 8.0; } - v->read256_bytes_block_width_y = 256.0 / dcn_bw_ceil2(v->byte_per_pix_dety, 1.0) - / v->read256_bytes_block_height_y; + v->read256_bytes_block_width_y = 256.0 /dcn_bw_ceil2(v->byte_per_pix_dety, 1.0) / v->read256_bytes_block_height_y; v->read256_bytes_block_height_c = 0.0; v->read256_bytes_block_width_c = 0.0; - } else { + } + else { if (v->source_surface_mode[k] == dcn_bw_sw_linear) { v->read256_bytes_block_height_y = 1.0; v->read256_bytes_block_height_c = 1.0; - } else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_8) { + } + else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_8) { v->read256_bytes_block_height_y = 16.0; v->read256_bytes_block_height_c = 8.0; - } else { + } + else { v->read256_bytes_block_height_y = 8.0; v->read256_bytes_block_height_c = 8.0; } - v->read256_bytes_block_width_y = 256.0 / dcn_bw_ceil2(v->byte_per_pix_dety, 1.0) - / v->read256_bytes_block_height_y; - v->read256_bytes_block_width_c = 256.0 / dcn_bw_ceil2(v->byte_per_pix_detc, 2.0) - / v->read256_bytes_block_height_c; + v->read256_bytes_block_width_y = 256.0 /dcn_bw_ceil2(v->byte_per_pix_dety, 1.0) / v->read256_bytes_block_height_y; + v->read256_bytes_block_width_c = 256.0 /dcn_bw_ceil2(v->byte_per_pix_detc, 2.0) / v->read256_bytes_block_height_c; } if (v->source_scan[k] == dcn_bw_hor) { v->maximum_swath_height_y = v->read256_bytes_block_height_y; v->maximum_swath_height_c = v->read256_bytes_block_height_c; - } else { + } + else { v->maximum_swath_height_y = v->read256_bytes_block_width_y; v->maximum_swath_height_c = v->read256_bytes_block_width_c; } - if ((v->source_pixel_format[k] == dcn_bw_rgb_sub_64 - || v->source_pixel_format[k] == dcn_bw_rgb_sub_32 - || v->source_pixel_format[k] == dcn_bw_rgb_sub_16)) { - if (v->source_surface_mode[k] == dcn_bw_sw_linear - || (v->source_pixel_format[k] == dcn_bw_rgb_sub_64 - && (v->source_surface_mode[k] - == dcn_bw_sw_4_kb_s - || v->source_surface_mode[k] - == dcn_bw_sw_4_kb_s_x - || v->source_surface_mode[k] - == dcn_bw_sw_64_kb_s - || v->source_surface_mode[k] - == dcn_bw_sw_64_kb_s_t - || v->source_surface_mode[k] - == dcn_bw_sw_64_kb_s_x - || v->source_surface_mode[k] - == dcn_bw_sw_var_s - || v->source_surface_mode[k] - == dcn_bw_sw_var_s_x) - && v->source_scan[k] == dcn_bw_hor)) { + if ((v->source_pixel_format[k] == dcn_bw_rgb_sub_64 || v->source_pixel_format[k] == dcn_bw_rgb_sub_32 || v->source_pixel_format[k] == dcn_bw_rgb_sub_16)) { + if (v->source_surface_mode[k] == dcn_bw_sw_linear || (v->source_pixel_format[k] == dcn_bw_rgb_sub_64 && (v->source_surface_mode[k] == dcn_bw_sw_4_kb_s || v->source_surface_mode[k] == dcn_bw_sw_4_kb_s_x || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_t || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_x || v->source_surface_mode[k] == dcn_bw_sw_var_s || v->source_surface_mode[k] == dcn_bw_sw_var_s_x) && v->source_scan[k] == dcn_bw_hor)) { v->minimum_swath_height_y = v->maximum_swath_height_y; - } else { + } + else { v->minimum_swath_height_y = v->maximum_swath_height_y / 2.0; } v->minimum_swath_height_c = v->maximum_swath_height_c; - } else { + } + else { if (v->source_surface_mode[k] == dcn_bw_sw_linear) { v->minimum_swath_height_y = v->maximum_swath_height_y; v->minimum_swath_height_c = v->maximum_swath_height_c; - } else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_8 - && v->source_scan[k] == dcn_bw_hor) { + } + else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_8 && v->source_scan[k] == dcn_bw_hor) { v->minimum_swath_height_y = v->maximum_swath_height_y / 2.0; - if (v->bug_forcing_luma_and_chroma_request_to_same_size_fixed - == dcn_bw_yes) { + if (v->bug_forcing_luma_and_chroma_request_to_same_size_fixed == dcn_bw_yes) { v->minimum_swath_height_c = v->maximum_swath_height_c; - } else { + } + else { v->minimum_swath_height_c = v->maximum_swath_height_c / 2.0; } - } else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_10 - && v->source_scan[k] == dcn_bw_hor) { + } + else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_10 && v->source_scan[k] == dcn_bw_hor) { v->minimum_swath_height_c = v->maximum_swath_height_c / 2.0; - if (v->bug_forcing_luma_and_chroma_request_to_same_size_fixed - == dcn_bw_yes) { + if (v->bug_forcing_luma_and_chroma_request_to_same_size_fixed == dcn_bw_yes) { v->minimum_swath_height_y = v->maximum_swath_height_y; - } else { + } + else { v->minimum_swath_height_y = v->maximum_swath_height_y / 2.0; } - } else { + } + else { v->minimum_swath_height_y = v->maximum_swath_height_y; v->minimum_swath_height_c = v->maximum_swath_height_c; } } if (v->source_scan[k] == dcn_bw_hor) { v->swath_width = v->viewport_width[k] / v->dpp_per_plane[k]; - } else { + } + else { v->swath_width = v->viewport_height[k] / v->dpp_per_plane[k]; } - v->swath_width_granularity_y = 256.0 / dcn_bw_ceil2(v->byte_per_pix_dety, 1.0) - / v->maximum_swath_height_y; - v->rounded_up_max_swath_size_bytes_y = (dcn_bw_ceil2( - v->swath_width - 1.0, - v->swath_width_granularity_y) + v->swath_width_granularity_y) - * v->byte_per_pix_dety * v->maximum_swath_height_y; + v->swath_width_granularity_y = 256.0 /dcn_bw_ceil2(v->byte_per_pix_dety, 1.0) / v->maximum_swath_height_y; + v->rounded_up_max_swath_size_bytes_y = (dcn_bw_ceil2(v->swath_width - 1.0, v->swath_width_granularity_y) + v->swath_width_granularity_y) * v->byte_per_pix_dety * v->maximum_swath_height_y; if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_10) { - v->rounded_up_max_swath_size_bytes_y = dcn_bw_ceil2( - v->rounded_up_max_swath_size_bytes_y, - 256.0) + 256; + v->rounded_up_max_swath_size_bytes_y =dcn_bw_ceil2(v->rounded_up_max_swath_size_bytes_y, 256.0) + 256; } if (v->maximum_swath_height_c > 0.0) { - v->swath_width_granularity_c = 256.0 / dcn_bw_ceil2(v->byte_per_pix_detc, 2.0) - / v->maximum_swath_height_c; + v->swath_width_granularity_c = 256.0 /dcn_bw_ceil2(v->byte_per_pix_detc, 2.0) / v->maximum_swath_height_c; } - v->rounded_up_max_swath_size_bytes_c = (dcn_bw_ceil2( - v->swath_width / 2.0 - 1.0, - v->swath_width_granularity_c) + v->swath_width_granularity_c) - * v->byte_per_pix_detc * v->maximum_swath_height_c; + v->rounded_up_max_swath_size_bytes_c = (dcn_bw_ceil2(v->swath_width / 2.0 - 1.0, v->swath_width_granularity_c) + v->swath_width_granularity_c) * v->byte_per_pix_detc * v->maximum_swath_height_c; if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_10) { - v->rounded_up_max_swath_size_bytes_c = dcn_bw_ceil2( - v->rounded_up_max_swath_size_bytes_c, - 256.0) + 256; + v->rounded_up_max_swath_size_bytes_c =dcn_bw_ceil2(v->rounded_up_max_swath_size_bytes_c, 256.0) + 256; } - if (v->rounded_up_max_swath_size_bytes_y + v->rounded_up_max_swath_size_bytes_c - <= v->det_buffer_size_in_kbyte * 1024.0 / 2.0) { + if (v->rounded_up_max_swath_size_bytes_y + v->rounded_up_max_swath_size_bytes_c <= v->det_buffer_size_in_kbyte * 1024.0 / 2.0) { v->swath_height_y[k] = v->maximum_swath_height_y; v->swath_height_c[k] = v->maximum_swath_height_c; - } else { + } + else { v->swath_height_y[k] = v->minimum_swath_height_y; v->swath_height_c[k] = v->minimum_swath_height_c; } if (v->swath_height_c[k] == 0.0) { v->det_buffer_size_y[k] = v->det_buffer_size_in_kbyte * 1024.0; v->det_buffer_size_c[k] = 0.0; - } else if (v->swath_height_y[k] <= v->swath_height_c[k]) { + } + else if (v->swath_height_y[k] <= v->swath_height_c[k]) { v->det_buffer_size_y[k] = v->det_buffer_size_in_kbyte * 1024.0 / 2.0; v->det_buffer_size_c[k] = v->det_buffer_size_in_kbyte * 1024.0 / 2.0; - } else { + } + else { v->det_buffer_size_y[k] = v->det_buffer_size_in_kbyte * 1024.0 * 2.0 / 3.0; v->det_buffer_size_c[k] = v->det_buffer_size_in_kbyte * 1024.0 / 3.0; } } } -void dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performance_calculation( - struct dcn_bw_internal_vars *v) +void dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performance_calculation(struct dcn_bw_internal_vars *v) { int k; /*dispclk and dppclk calculation*/ @@ -2191,123 +1137,48 @@ void dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performan v->dispclk_without_ramping = 0.0; for (k = 0; k <= v->number_of_active_planes - 1; k++) { if (v->h_ratio[k] > 1.0) { - v->pscl_throughput[k] = dcn_bw_min2( - v->max_dchub_topscl_throughput, - v->max_pscl_tolb_throughput * v->h_ratio[k] - / dcn_bw_ceil2(v->htaps[k] / 6.0, 1.0)); - } else { - v->pscl_throughput[k] = dcn_bw_min2( - v->max_dchub_topscl_throughput, - v->max_pscl_tolb_throughput); - } - v->dppclk_using_single_dpp_luma = v->pixel_clock[k] - * dcn_bw_max3( - v->vtaps[k] / 6.0 * dcn_bw_min2(1.0, v->h_ratio[k]), - v->h_ratio[k] * v->v_ratio[k] - / v->pscl_throughput[k], - 1.0); - if ((v->source_pixel_format[k] != dcn_bw_yuv420_sub_8 - && v->source_pixel_format[k] != dcn_bw_yuv420_sub_10)) { + v->pscl_throughput[k] =dcn_bw_min2(v->max_dchub_topscl_throughput, v->max_pscl_tolb_throughput * v->h_ratio[k] /dcn_bw_ceil2(v->htaps[k] / 6.0, 1.0)); + } + else { + v->pscl_throughput[k] =dcn_bw_min2(v->max_dchub_topscl_throughput, v->max_pscl_tolb_throughput); + } + v->dppclk_using_single_dpp_luma = v->pixel_clock[k] *dcn_bw_max3(v->vtaps[k] / 6.0 *dcn_bw_min2(1.0, v->h_ratio[k]), v->h_ratio[k] * v->v_ratio[k] / v->pscl_throughput[k], 1.0); + if ((v->source_pixel_format[k] != dcn_bw_yuv420_sub_8 && v->source_pixel_format[k] != dcn_bw_yuv420_sub_10)) { v->pscl_throughput_chroma[k] = 0.0; v->dppclk_using_single_dpp = v->dppclk_using_single_dpp_luma; - } else { + } + else { if (v->h_ratio[k] > 1.0) { - v->pscl_throughput_chroma[k] = - dcn_bw_min2( - v->max_dchub_topscl_throughput, - v->max_pscl_tolb_throughput - * v->h_ratio[k] - / 2.0 - / dcn_bw_ceil2( - v->hta_pschroma[k] - / 6.0, - 1.0)); - } else { - v->pscl_throughput_chroma[k] = dcn_bw_min2( - v->max_dchub_topscl_throughput, - v->max_pscl_tolb_throughput); - } - v->dppclk_using_single_dpp_chroma = - v->pixel_clock[k] - * dcn_bw_max3( - v->vta_pschroma[k] / 6.0 - * dcn_bw_min2( - 1.0, - v->h_ratio[k] - / 2.0), - v->h_ratio[k] - * v->v_ratio[k] - / 4.0 - / v->pscl_throughput_chroma[k], - 1.0); - v->dppclk_using_single_dpp = dcn_bw_max2( - v->dppclk_using_single_dpp_luma, - v->dppclk_using_single_dpp_chroma); + v->pscl_throughput_chroma[k] =dcn_bw_min2(v->max_dchub_topscl_throughput, v->max_pscl_tolb_throughput * v->h_ratio[k] / 2.0 /dcn_bw_ceil2(v->hta_pschroma[k] / 6.0, 1.0)); + } + else { + v->pscl_throughput_chroma[k] =dcn_bw_min2(v->max_dchub_topscl_throughput, v->max_pscl_tolb_throughput); + } + v->dppclk_using_single_dpp_chroma = v->pixel_clock[k] *dcn_bw_max3(v->vta_pschroma[k] / 6.0 *dcn_bw_min2(1.0, v->h_ratio[k] / 2.0), v->h_ratio[k] * v->v_ratio[k] / 4.0 / v->pscl_throughput_chroma[k], 1.0); + v->dppclk_using_single_dpp =dcn_bw_max2(v->dppclk_using_single_dpp_luma, v->dppclk_using_single_dpp_chroma); } if (v->odm_capable == dcn_bw_yes) { - v->dispclk_with_ramping = - dcn_bw_max2( - v->dispclk_with_ramping, - dcn_bw_max2( - v->dppclk_using_single_dpp - / v->dpp_per_plane[k] - * v->dispclk_dppclk_ratio, - v->pixel_clock[k] - / v->dpp_per_plane[k]) - * (1.0 - + v->downspreading - / 100.0) - * (1.0 - + v->dispclk_ramping_margin - / 100.0)); - v->dispclk_without_ramping = dcn_bw_max2( - v->dispclk_without_ramping, - dcn_bw_max2( - v->dppclk_using_single_dpp - / v->dpp_per_plane[k] - * v->dispclk_dppclk_ratio, - v->pixel_clock[k] / v->dpp_per_plane[k]) - * (1.0 + v->downspreading / 100.0)); - } else { - v->dispclk_with_ramping = - dcn_bw_max2( - v->dispclk_with_ramping, - dcn_bw_max2( - v->dppclk_using_single_dpp - / v->dpp_per_plane[k] - * v->dispclk_dppclk_ratio, - v->pixel_clock[k]) - * (1.0 - + v->downspreading - / 100.0) - * (1.0 - + v->dispclk_ramping_margin - / 100.0)); - v->dispclk_without_ramping = dcn_bw_max2( - v->dispclk_without_ramping, - dcn_bw_max2( - v->dppclk_using_single_dpp - / v->dpp_per_plane[k] - * v->dispclk_dppclk_ratio, - v->pixel_clock[k]) - * (1.0 + v->downspreading / 100.0)); + v->dispclk_with_ramping =dcn_bw_max2(v->dispclk_with_ramping,dcn_bw_max2(v->dppclk_using_single_dpp / v->dpp_per_plane[k] * v->dispclk_dppclk_ratio, v->pixel_clock[k] / v->dpp_per_plane[k]) * (1.0 + v->downspreading / 100.0) * (1.0 + v->dispclk_ramping_margin / 100.0)); + v->dispclk_without_ramping =dcn_bw_max2(v->dispclk_without_ramping,dcn_bw_max2(v->dppclk_using_single_dpp / v->dpp_per_plane[k] * v->dispclk_dppclk_ratio, v->pixel_clock[k] / v->dpp_per_plane[k]) * (1.0 + v->downspreading / 100.0)); + } + else { + v->dispclk_with_ramping =dcn_bw_max2(v->dispclk_with_ramping,dcn_bw_max2(v->dppclk_using_single_dpp / v->dpp_per_plane[k] * v->dispclk_dppclk_ratio, v->pixel_clock[k]) * (1.0 + v->downspreading / 100.0) * (1.0 + v->dispclk_ramping_margin / 100.0)); + v->dispclk_without_ramping =dcn_bw_max2(v->dispclk_without_ramping,dcn_bw_max2(v->dppclk_using_single_dpp / v->dpp_per_plane[k] * v->dispclk_dppclk_ratio, v->pixel_clock[k]) * (1.0 + v->downspreading / 100.0)); } } if (v->dispclk_without_ramping > v->max_dispclk[number_of_states]) { v->dispclk = v->dispclk_without_ramping; - } else if (v->dispclk_with_ramping > v->max_dispclk[number_of_states]) { + } + else if (v->dispclk_with_ramping > v->max_dispclk[number_of_states]) { v->dispclk = v->max_dispclk[number_of_states]; - } else { + } + else { v->dispclk = v->dispclk_with_ramping; } v->dppclk = v->dispclk / v->dispclk_dppclk_ratio; /*urgent watermark*/ - v->return_bandwidth_to_dcn = dcn_bw_min2( - v->return_bus_width * v->dcfclk, - v->fabric_and_dram_bandwidth * 1000.0 - * v->percent_of_ideal_drambw_received_after_urg_latency - / 100.0); + v->return_bandwidth_to_dcn =dcn_bw_min2(v->return_bus_width * v->dcfclk, v->fabric_and_dram_bandwidth * 1000.0 * v->percent_of_ideal_drambw_received_after_urg_latency / 100.0); v->dcc_enabled_any_plane = dcn_bw_no; for (k = 0; k <= v->number_of_active_planes - 1; k++) { if (v->dcc_enable[k] == dcn_bw_yes) { @@ -2315,95 +1186,26 @@ void dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performan } } v->return_bw = v->return_bandwidth_to_dcn; - if (v->dcc_enabled_any_plane == dcn_bw_yes - && v->return_bandwidth_to_dcn > v->dcfclk * v->return_bus_width / 4.0) { - v->return_bw = - dcn_bw_min2( - v->return_bw, - v->return_bandwidth_to_dcn * 4.0 - * (1.0 - - v->urgent_latency - / ((v->rob_buffer_size_in_kbyte - - v->pixel_chunk_size_in_kbyte) - * 1024.0 - / (v->return_bandwidth_to_dcn - - v->dcfclk - * v->return_bus_width - / 4.0) - + v->urgent_latency))); - } - v->critical_compression = 2.0 * v->return_bus_width * v->dcfclk * v->urgent_latency - / (v->return_bandwidth_to_dcn * v->urgent_latency - + (v->rob_buffer_size_in_kbyte - - v->pixel_chunk_size_in_kbyte) * 1024.0); - if (v->dcc_enabled_any_plane == dcn_bw_yes && v->critical_compression > 1.0 - && v->critical_compression < 4.0) { - v->return_bw = - dcn_bw_min2( - v->return_bw, - dcn_bw_pow( - 4.0 * v->return_bandwidth_to_dcn - * (v->rob_buffer_size_in_kbyte - - v->pixel_chunk_size_in_kbyte) - * 1024.0 - * v->return_bus_width - * v->dcfclk - * v->urgent_latency - / (v->return_bandwidth_to_dcn - * v->urgent_latency - + (v->rob_buffer_size_in_kbyte - - v->pixel_chunk_size_in_kbyte) - * 1024.0), - 2)); - } - v->return_bandwidth_to_dcn = dcn_bw_min2( - v->return_bus_width * v->dcfclk, - v->fabric_and_dram_bandwidth * 1000.0); - if (v->dcc_enabled_any_plane == dcn_bw_yes - && v->return_bandwidth_to_dcn > v->dcfclk * v->return_bus_width / 4.0) { - v->return_bw = - dcn_bw_min2( - v->return_bw, - v->return_bandwidth_to_dcn * 4.0 - * (1.0 - - v->urgent_latency - / ((v->rob_buffer_size_in_kbyte - - v->pixel_chunk_size_in_kbyte) - * 1024.0 - / (v->return_bandwidth_to_dcn - - v->dcfclk - * v->return_bus_width - / 4.0) - + v->urgent_latency))); - } - v->critical_compression = 2.0 * v->return_bus_width * v->dcfclk * v->urgent_latency - / (v->return_bandwidth_to_dcn * v->urgent_latency - + (v->rob_buffer_size_in_kbyte - - v->pixel_chunk_size_in_kbyte) * 1024.0); - if (v->dcc_enabled_any_plane == dcn_bw_yes && v->critical_compression > 1.0 - && v->critical_compression < 4.0) { - v->return_bw = - dcn_bw_min2( - v->return_bw, - dcn_bw_pow( - 4.0 * v->return_bandwidth_to_dcn - * (v->rob_buffer_size_in_kbyte - - v->pixel_chunk_size_in_kbyte) - * 1024.0 - * v->return_bus_width - * v->dcfclk - * v->urgent_latency - / (v->return_bandwidth_to_dcn - * v->urgent_latency - + (v->rob_buffer_size_in_kbyte - - v->pixel_chunk_size_in_kbyte) - * 1024.0), - 2)); + if (v->dcc_enabled_any_plane == dcn_bw_yes && v->return_bandwidth_to_dcn > v->dcfclk * v->return_bus_width / 4.0) { + v->return_bw =dcn_bw_min2(v->return_bw, v->return_bandwidth_to_dcn * 4.0 * (1.0 - v->urgent_latency / ((v->rob_buffer_size_in_kbyte - v->pixel_chunk_size_in_kbyte) * 1024.0 / (v->return_bandwidth_to_dcn - v->dcfclk * v->return_bus_width / 4.0) + v->urgent_latency))); + } + v->critical_compression = 2.0 * v->return_bus_width * v->dcfclk * v->urgent_latency / (v->return_bandwidth_to_dcn * v->urgent_latency + (v->rob_buffer_size_in_kbyte - v->pixel_chunk_size_in_kbyte) * 1024.0); + if (v->dcc_enabled_any_plane == dcn_bw_yes && v->critical_compression > 1.0 && v->critical_compression < 4.0) { + v->return_bw =dcn_bw_min2(v->return_bw, dcn_bw_pow(4.0 * v->return_bandwidth_to_dcn * (v->rob_buffer_size_in_kbyte - v->pixel_chunk_size_in_kbyte) * 1024.0 * v->return_bus_width * v->dcfclk * v->urgent_latency / (v->return_bandwidth_to_dcn * v->urgent_latency + (v->rob_buffer_size_in_kbyte - v->pixel_chunk_size_in_kbyte) * 1024.0), 2)); + } + v->return_bandwidth_to_dcn =dcn_bw_min2(v->return_bus_width * v->dcfclk, v->fabric_and_dram_bandwidth * 1000.0); + if (v->dcc_enabled_any_plane == dcn_bw_yes && v->return_bandwidth_to_dcn > v->dcfclk * v->return_bus_width / 4.0) { + v->return_bw =dcn_bw_min2(v->return_bw, v->return_bandwidth_to_dcn * 4.0 * (1.0 - v->urgent_latency / ((v->rob_buffer_size_in_kbyte - v->pixel_chunk_size_in_kbyte) * 1024.0 / (v->return_bandwidth_to_dcn - v->dcfclk * v->return_bus_width / 4.0) + v->urgent_latency))); + } + v->critical_compression = 2.0 * v->return_bus_width * v->dcfclk * v->urgent_latency / (v->return_bandwidth_to_dcn * v->urgent_latency + (v->rob_buffer_size_in_kbyte - v->pixel_chunk_size_in_kbyte) * 1024.0); + if (v->dcc_enabled_any_plane == dcn_bw_yes && v->critical_compression > 1.0 && v->critical_compression < 4.0) { + v->return_bw =dcn_bw_min2(v->return_bw, dcn_bw_pow(4.0 * v->return_bandwidth_to_dcn * (v->rob_buffer_size_in_kbyte - v->pixel_chunk_size_in_kbyte) * 1024.0 * v->return_bus_width * v->dcfclk * v->urgent_latency / (v->return_bandwidth_to_dcn * v->urgent_latency + (v->rob_buffer_size_in_kbyte - v->pixel_chunk_size_in_kbyte) * 1024.0), 2)); } for (k = 0; k <= v->number_of_active_planes - 1; k++) { if (v->source_scan[k] == dcn_bw_hor) { v->swath_width_y[k] = v->viewport_width[k] / v->dpp_per_plane[k]; - } else { + } + else { v->swath_width_y[k] = v->viewport_height[k] / v->dpp_per_plane[k]; } } @@ -2411,31 +1213,29 @@ void dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performan if (v->source_pixel_format[k] == dcn_bw_rgb_sub_64) { v->byte_per_pixel_dety[k] = 8.0; v->byte_per_pixel_detc[k] = 0.0; - } else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_32) { + } + else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_32) { v->byte_per_pixel_dety[k] = 4.0; v->byte_per_pixel_detc[k] = 0.0; - } else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_16) { + } + else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_16) { v->byte_per_pixel_dety[k] = 2.0; v->byte_per_pixel_detc[k] = 0.0; - } else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_8) { + } + else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_8) { v->byte_per_pixel_dety[k] = 1.0; v->byte_per_pixel_detc[k] = 2.0; - } else { - v->byte_per_pixel_dety[k] = 4.0f / 3; - v->byte_per_pixel_detc[k] = 8.0f / 3; + } + else { + v->byte_per_pixel_dety[k] = 4.0f / 3.0f; + v->byte_per_pixel_detc[k] = 8.0f / 3.0f; } } v->total_data_read_bandwidth = 0.0; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - v->read_bandwidth_plane_luma[k] = v->swath_width_y[k] * v->dpp_per_plane[k] - * dcn_bw_ceil2(v->byte_per_pixel_dety[k], 1.0) - / (v->htotal[k] / v->pixel_clock[k]) * v->v_ratio[k]; - v->read_bandwidth_plane_chroma[k] = v->swath_width_y[k] / 2.0 * v->dpp_per_plane[k] - * dcn_bw_ceil2(v->byte_per_pixel_detc[k], 2.0) - / (v->htotal[k] / v->pixel_clock[k]) * v->v_ratio[k] / 2.0; - v->total_data_read_bandwidth = v->total_data_read_bandwidth - + v->read_bandwidth_plane_luma[k] - + v->read_bandwidth_plane_chroma[k]; + v->read_bandwidth_plane_luma[k] = v->swath_width_y[k] * v->dpp_per_plane[k] *dcn_bw_ceil2(v->byte_per_pixel_dety[k], 1.0) / (v->htotal[k] / v->pixel_clock[k]) * v->v_ratio[k]; + v->read_bandwidth_plane_chroma[k] = v->swath_width_y[k] / 2.0 * v->dpp_per_plane[k] *dcn_bw_ceil2(v->byte_per_pixel_detc[k], 2.0) / (v->htotal[k] / v->pixel_clock[k]) * v->v_ratio[k] / 2.0; + v->total_data_read_bandwidth = v->total_data_read_bandwidth + v->read_bandwidth_plane_luma[k] + v->read_bandwidth_plane_chroma[k]; } v->total_active_dpp = 0.0; v->total_dcc_active_dpp = 0.0; @@ -2445,63 +1245,36 @@ void dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performan v->total_dcc_active_dpp = v->total_dcc_active_dpp + v->dpp_per_plane[k]; } } - v->urgent_round_trip_and_out_of_order_latency = (v->round_trip_ping_latency_cycles + 32.0) - / v->dcfclk - + v->urgent_out_of_order_return_per_channel * v->number_of_channels - / v->return_bw; + v->urgent_round_trip_and_out_of_order_latency = (v->round_trip_ping_latency_cycles + 32.0) / v->dcfclk + v->urgent_out_of_order_return_per_channel * v->number_of_channels / v->return_bw; v->last_pixel_of_line_extra_watermark = 0.0; for (k = 0; k <= v->number_of_active_planes - 1; k++) { if (v->v_ratio[k] <= 1.0) { - v->display_pipe_line_delivery_time_luma[k] = v->swath_width_y[k] - * v->dpp_per_plane[k] / v->h_ratio[k] / v->pixel_clock[k]; - } else { - v->display_pipe_line_delivery_time_luma[k] = v->swath_width_y[k] - / v->pscl_throughput[k] / v->dppclk; - } - v->data_fabric_line_delivery_time_luma = - v->swath_width_y[k] * v->swath_height_y[k] - * dcn_bw_ceil2(v->byte_per_pixel_dety[k], 1.0) - / (v->return_bw * v->read_bandwidth_plane_luma[k] - / v->dpp_per_plane[k] - / v->total_data_read_bandwidth); - v->last_pixel_of_line_extra_watermark = dcn_bw_max2( - v->last_pixel_of_line_extra_watermark, - v->data_fabric_line_delivery_time_luma - - v->display_pipe_line_delivery_time_luma[k]); + v->display_pipe_line_delivery_time_luma[k] = v->swath_width_y[k] * v->dpp_per_plane[k] / v->h_ratio[k] / v->pixel_clock[k]; + } + else { + v->display_pipe_line_delivery_time_luma[k] = v->swath_width_y[k] / v->pscl_throughput[k] / v->dppclk; + } + v->data_fabric_line_delivery_time_luma = v->swath_width_y[k] * v->swath_height_y[k] *dcn_bw_ceil2(v->byte_per_pixel_dety[k], 1.0) / (v->return_bw * v->read_bandwidth_plane_luma[k] / v->dpp_per_plane[k] / v->total_data_read_bandwidth); + v->last_pixel_of_line_extra_watermark =dcn_bw_max2(v->last_pixel_of_line_extra_watermark, v->data_fabric_line_delivery_time_luma - v->display_pipe_line_delivery_time_luma[k]); if (v->byte_per_pixel_detc[k] == 0.0) { v->display_pipe_line_delivery_time_chroma[k] = 0.0; - } else { + } + else { if (v->v_ratio[k] / 2.0 <= 1.0) { - v->display_pipe_line_delivery_time_chroma[k] = v->swath_width_y[k] - / 2.0 * v->dpp_per_plane[k] / (v->h_ratio[k] / 2.0) - / v->pixel_clock[k]; - } else { - v->display_pipe_line_delivery_time_chroma[k] = v->swath_width_y[k] - / 2.0 / v->pscl_throughput_chroma[k] / v->dppclk; - } - v->data_fabric_line_delivery_time_chroma = v->swath_width_y[k] / 2.0 - * v->swath_height_c[k] - * dcn_bw_ceil2(v->byte_per_pixel_detc[k], 2.0) - / (v->return_bw * v->read_bandwidth_plane_chroma[k] - / v->dpp_per_plane[k] - / v->total_data_read_bandwidth); - v->last_pixel_of_line_extra_watermark = - dcn_bw_max2( - v->last_pixel_of_line_extra_watermark, - v->data_fabric_line_delivery_time_chroma - - v->display_pipe_line_delivery_time_chroma[k]); - } - } - v->urgent_extra_latency = v->urgent_round_trip_and_out_of_order_latency - + (v->total_active_dpp * v->pixel_chunk_size_in_kbyte - + v->total_dcc_active_dpp * v->meta_chunk_size) * 1024.0 - / v->return_bw; + v->display_pipe_line_delivery_time_chroma[k] = v->swath_width_y[k] / 2.0 * v->dpp_per_plane[k] / (v->h_ratio[k] / 2.0) / v->pixel_clock[k]; + } + else { + v->display_pipe_line_delivery_time_chroma[k] = v->swath_width_y[k] / 2.0 / v->pscl_throughput_chroma[k] / v->dppclk; + } + v->data_fabric_line_delivery_time_chroma = v->swath_width_y[k] / 2.0 * v->swath_height_c[k] *dcn_bw_ceil2(v->byte_per_pixel_detc[k], 2.0) / (v->return_bw * v->read_bandwidth_plane_chroma[k] / v->dpp_per_plane[k] / v->total_data_read_bandwidth); + v->last_pixel_of_line_extra_watermark =dcn_bw_max2(v->last_pixel_of_line_extra_watermark, v->data_fabric_line_delivery_time_chroma - v->display_pipe_line_delivery_time_chroma[k]); + } + } + v->urgent_extra_latency = v->urgent_round_trip_and_out_of_order_latency + (v->total_active_dpp * v->pixel_chunk_size_in_kbyte + v->total_dcc_active_dpp * v->meta_chunk_size) * 1024.0 / v->return_bw; if (v->pte_enable == dcn_bw_yes) { - v->urgent_extra_latency = v->urgent_extra_latency - + v->total_active_dpp * v->pte_chunk_size * 1024.0 / v->return_bw; + v->urgent_extra_latency = v->urgent_extra_latency + v->total_active_dpp * v->pte_chunk_size * 1024.0 / v->return_bw; } - v->urgent_watermark = v->urgent_latency + v->last_pixel_of_line_extra_watermark - + v->urgent_extra_latency; + v->urgent_watermark = v->urgent_latency + v->last_pixel_of_line_extra_watermark + v->urgent_extra_latency; v->ptemeta_urgent_watermark = v->urgent_watermark + 2.0 * v->urgent_latency; /*nb p-state/dram clock change watermark*/ @@ -2513,33 +1286,23 @@ void dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performan } } if (v->total_active_writeback <= 1.0) { - v->writeback_dram_clock_change_watermark = v->dram_clock_change_latency - + v->write_back_latency; - } else { - v->writeback_dram_clock_change_watermark = v->dram_clock_change_latency - + v->write_back_latency - + v->writeback_chunk_size * 1024.0 / 32.0 / v->socclk; + v->writeback_dram_clock_change_watermark = v->dram_clock_change_latency + v->write_back_latency; + } + else { + v->writeback_dram_clock_change_watermark = v->dram_clock_change_latency + v->write_back_latency + v->writeback_chunk_size * 1024.0 / 32.0 / v->socclk; } /*stutter efficiency*/ for (k = 0; k <= v->number_of_active_planes - 1; k++) { - v->lines_in_dety[k] = v->det_buffer_size_y[k] / v->byte_per_pixel_dety[k] - / v->swath_width_y[k]; - v->lines_in_dety_rounded_down_to_swath[k] = dcn_bw_floor2( - v->lines_in_dety[k], - v->swath_height_y[k]); - v->full_det_buffering_time_y[k] = v->lines_in_dety_rounded_down_to_swath[k] - * (v->htotal[k] / v->pixel_clock[k]) / v->v_ratio[k]; + v->lines_in_dety[k] = v->det_buffer_size_y[k] / v->byte_per_pixel_dety[k] / v->swath_width_y[k]; + v->lines_in_dety_rounded_down_to_swath[k] =dcn_bw_floor2(v->lines_in_dety[k], v->swath_height_y[k]); + v->full_det_buffering_time_y[k] = v->lines_in_dety_rounded_down_to_swath[k] * (v->htotal[k] / v->pixel_clock[k]) / v->v_ratio[k]; if (v->byte_per_pixel_detc[k] > 0.0) { - v->lines_in_detc[k] = v->det_buffer_size_c[k] / v->byte_per_pixel_detc[k] - / (v->swath_width_y[k] / 2.0); - v->lines_in_detc_rounded_down_to_swath[k] = dcn_bw_floor2( - v->lines_in_detc[k], - v->swath_height_c[k]); - v->full_det_buffering_time_c[k] = v->lines_in_detc_rounded_down_to_swath[k] - * (v->htotal[k] / v->pixel_clock[k]) - / (v->v_ratio[k] / 2.0); - } else { + v->lines_in_detc[k] = v->det_buffer_size_c[k] / v->byte_per_pixel_detc[k] / (v->swath_width_y[k] / 2.0); + v->lines_in_detc_rounded_down_to_swath[k] =dcn_bw_floor2(v->lines_in_detc[k], v->swath_height_c[k]); + v->full_det_buffering_time_c[k] = v->lines_in_detc_rounded_down_to_swath[k] * (v->htotal[k] / v->pixel_clock[k]) / (v->v_ratio[k] / 2.0); + } + else { v->lines_in_detc[k] = 0.0; v->lines_in_detc_rounded_down_to_swath[k] = 0.0; v->full_det_buffering_time_c[k] = 999999.0; @@ -2549,166 +1312,83 @@ void dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performan for (k = 0; k <= v->number_of_active_planes - 1; k++) { if (v->full_det_buffering_time_y[k] < v->min_full_det_buffering_time) { v->min_full_det_buffering_time = v->full_det_buffering_time_y[k]; - v->frame_time_for_min_full_det_buffering_time = v->vtotal[k] * v->htotal[k] - / v->pixel_clock[k]; + v->frame_time_for_min_full_det_buffering_time = v->vtotal[k] * v->htotal[k] / v->pixel_clock[k]; } if (v->full_det_buffering_time_c[k] < v->min_full_det_buffering_time) { v->min_full_det_buffering_time = v->full_det_buffering_time_c[k]; - v->frame_time_for_min_full_det_buffering_time = v->vtotal[k] * v->htotal[k] - / v->pixel_clock[k]; + v->frame_time_for_min_full_det_buffering_time = v->vtotal[k] * v->htotal[k] / v->pixel_clock[k]; } } v->average_read_bandwidth_gbyte_per_second = 0.0; for (k = 0; k <= v->number_of_active_planes - 1; k++) { if (v->dcc_enable[k] == dcn_bw_yes) { - v->average_read_bandwidth_gbyte_per_second = - v->average_read_bandwidth_gbyte_per_second - + v->read_bandwidth_plane_luma[k] - / v->dcc_rate[k] / 1000.0 - + v->read_bandwidth_plane_chroma[k] - / v->dcc_rate[k] / 1000.0; - } else { - v->average_read_bandwidth_gbyte_per_second = - v->average_read_bandwidth_gbyte_per_second - + v->read_bandwidth_plane_luma[k] / 1000.0 - + v->read_bandwidth_plane_chroma[k] - / 1000.0; + v->average_read_bandwidth_gbyte_per_second = v->average_read_bandwidth_gbyte_per_second + v->read_bandwidth_plane_luma[k] / v->dcc_rate[k] / 1000.0 + v->read_bandwidth_plane_chroma[k] / v->dcc_rate[k] / 1000.0; + } + else { + v->average_read_bandwidth_gbyte_per_second = v->average_read_bandwidth_gbyte_per_second + v->read_bandwidth_plane_luma[k] / 1000.0 + v->read_bandwidth_plane_chroma[k] / 1000.0; } if (v->dcc_enable[k] == dcn_bw_yes) { - v->average_read_bandwidth_gbyte_per_second = - v->average_read_bandwidth_gbyte_per_second - + v->read_bandwidth_plane_luma[k] / 1000.0 - / 256.0 - + v->read_bandwidth_plane_chroma[k] / 1000.0 - / 256.0; + v->average_read_bandwidth_gbyte_per_second = v->average_read_bandwidth_gbyte_per_second + v->read_bandwidth_plane_luma[k] / 1000.0 / 256.0 + v->read_bandwidth_plane_chroma[k] / 1000.0 / 256.0; } if (v->pte_enable == dcn_bw_yes) { - v->average_read_bandwidth_gbyte_per_second = - v->average_read_bandwidth_gbyte_per_second - + v->read_bandwidth_plane_luma[k] / 1000.0 - / 512.0 - + v->read_bandwidth_plane_chroma[k] / 1000.0 - / 512.0; - } - } - v->part_of_burst_that_fits_in_rob = dcn_bw_min2( - v->min_full_det_buffering_time * v->total_data_read_bandwidth, - v->rob_buffer_size_in_kbyte * 1024.0 * v->total_data_read_bandwidth - / (v->average_read_bandwidth_gbyte_per_second * 1000.0)); - v->stutter_burst_time = v->part_of_burst_that_fits_in_rob - * (v->average_read_bandwidth_gbyte_per_second * 1000.0) - / v->total_data_read_bandwidth / v->return_bw - + (v->min_full_det_buffering_time * v->total_data_read_bandwidth - - v->part_of_burst_that_fits_in_rob) / (v->dcfclk * 64.0); + v->average_read_bandwidth_gbyte_per_second = v->average_read_bandwidth_gbyte_per_second + v->read_bandwidth_plane_luma[k] / 1000.0 / 512.0 + v->read_bandwidth_plane_chroma[k] / 1000.0 / 512.0; + } + } + v->part_of_burst_that_fits_in_rob =dcn_bw_min2(v->min_full_det_buffering_time * v->total_data_read_bandwidth, v->rob_buffer_size_in_kbyte * 1024.0 * v->total_data_read_bandwidth / (v->average_read_bandwidth_gbyte_per_second * 1000.0)); + v->stutter_burst_time = v->part_of_burst_that_fits_in_rob * (v->average_read_bandwidth_gbyte_per_second * 1000.0) / v->total_data_read_bandwidth / v->return_bw + (v->min_full_det_buffering_time * v->total_data_read_bandwidth - v->part_of_burst_that_fits_in_rob) / (v->dcfclk * 64.0); if (v->total_active_writeback == 0.0) { - v->stutter_efficiency_not_including_vblank = (1.0 - - (v->sr_exit_time + v->stutter_burst_time) - / v->min_full_det_buffering_time) * 100.0; - } else { + v->stutter_efficiency_not_including_vblank = (1.0 - (v->sr_exit_time + v->stutter_burst_time) / v->min_full_det_buffering_time) * 100.0; + } + else { v->stutter_efficiency_not_including_vblank = 0.0; } v->smallest_vblank = 999999.0; for (k = 0; k <= v->number_of_active_planes - 1; k++) { if (v->synchronized_vblank == dcn_bw_yes || v->number_of_active_planes == 1) { - v->v_blank_time = (v->vtotal[k] - v->vactive[k]) * v->htotal[k] - / v->pixel_clock[k]; - } else { + v->v_blank_time = (v->vtotal[k] - v->vactive[k]) * v->htotal[k] / v->pixel_clock[k]; + } + else { v->v_blank_time = 0.0; } - v->smallest_vblank = dcn_bw_min2(v->smallest_vblank, v->v_blank_time); + v->smallest_vblank =dcn_bw_min2(v->smallest_vblank, v->v_blank_time); } - v->stutter_efficiency = (v->stutter_efficiency_not_including_vblank / 100.0 - * (v->frame_time_for_min_full_det_buffering_time - v->smallest_vblank) - + v->smallest_vblank) / v->frame_time_for_min_full_det_buffering_time - * 100.0; + v->stutter_efficiency = (v->stutter_efficiency_not_including_vblank / 100.0 * (v->frame_time_for_min_full_det_buffering_time - v->smallest_vblank) + v->smallest_vblank) / v->frame_time_for_min_full_det_buffering_time * 100.0; /*dcfclk deep sleep*/ for (k = 0; k <= v->number_of_active_planes - 1; k++) { if (v->byte_per_pixel_detc[k] > 0.0) { - v->dcfclk_deep_sleep_per_plane[k] = - dcn_bw_max2( - 1.1 * v->swath_width_y[k] - * dcn_bw_ceil2( - v->byte_per_pixel_dety[k], - 1.0) / 32.0 - / v->display_pipe_line_delivery_time_luma[k], - 1.1 * v->swath_width_y[k] / 2.0 - * dcn_bw_ceil2( - v->byte_per_pixel_detc[k], - 2.0) / 32.0 - / v->display_pipe_line_delivery_time_chroma[k]); - } else { - v->dcfclk_deep_sleep_per_plane[k] = 1.1 * v->swath_width_y[k] - * dcn_bw_ceil2(v->byte_per_pixel_dety[k], 1.0) / 64.0 - / v->display_pipe_line_delivery_time_luma[k]; - } - v->dcfclk_deep_sleep_per_plane[k] = dcn_bw_max2( - v->dcfclk_deep_sleep_per_plane[k], - v->pixel_clock[k] / 16.0); + v->dcfclk_deep_sleep_per_plane[k] =dcn_bw_max2(1.1 * v->swath_width_y[k] *dcn_bw_ceil2(v->byte_per_pixel_dety[k], 1.0) / 32.0 / v->display_pipe_line_delivery_time_luma[k], 1.1 * v->swath_width_y[k] / 2.0 *dcn_bw_ceil2(v->byte_per_pixel_detc[k], 2.0) / 32.0 / v->display_pipe_line_delivery_time_chroma[k]); + } + else { + v->dcfclk_deep_sleep_per_plane[k] = 1.1 * v->swath_width_y[k] *dcn_bw_ceil2(v->byte_per_pixel_dety[k], 1.0) / 64.0 / v->display_pipe_line_delivery_time_luma[k]; + } + v->dcfclk_deep_sleep_per_plane[k] =dcn_bw_max2(v->dcfclk_deep_sleep_per_plane[k], v->pixel_clock[k] / 16.0); } v->dcf_clk_deep_sleep = 8.0; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - v->dcf_clk_deep_sleep = dcn_bw_max2( - v->dcf_clk_deep_sleep, - v->dcfclk_deep_sleep_per_plane[k]); + v->dcf_clk_deep_sleep =dcn_bw_max2(v->dcf_clk_deep_sleep, v->dcfclk_deep_sleep_per_plane[k]); } /*stutter watermark*/ - v->stutter_exit_watermark = v->sr_exit_time + v->last_pixel_of_line_extra_watermark - + v->urgent_extra_latency + 10.0 / v->dcf_clk_deep_sleep; - v->stutter_enter_plus_exit_watermark = v->sr_enter_plus_exit_time - + v->last_pixel_of_line_extra_watermark + v->urgent_extra_latency; + v->stutter_exit_watermark = v->sr_exit_time + v->last_pixel_of_line_extra_watermark + v->urgent_extra_latency + 10.0 / v->dcf_clk_deep_sleep; + v->stutter_enter_plus_exit_watermark = v->sr_enter_plus_exit_time + v->last_pixel_of_line_extra_watermark + v->urgent_extra_latency; /*urgent latency supported*/ for (k = 0; k <= v->number_of_active_planes - 1; k++) { - v->effective_det_plus_lb_lines_luma = - dcn_bw_floor2( - v->lines_in_dety[k] - + dcn_bw_min2( - v->lines_in_dety[k] - * v->dppclk - * v->byte_per_pixel_dety[k] - * v->pscl_throughput[k] - / (v->return_bw - / v->dpp_per_plane[k]), - v->effective_lb_latency_hiding_source_lines_luma), - v->swath_height_y[k]); - v->urgent_latency_support_us_luma = v->effective_det_plus_lb_lines_luma - * (v->htotal[k] / v->pixel_clock[k]) / v->v_ratio[k] - - v->effective_det_plus_lb_lines_luma * v->swath_width_y[k] - * v->byte_per_pixel_dety[k] - / (v->return_bw / v->dpp_per_plane[k]); + v->effective_det_plus_lb_lines_luma =dcn_bw_floor2(v->lines_in_dety[k] +dcn_bw_min2(v->lines_in_dety[k] * v->dppclk * v->byte_per_pixel_dety[k] * v->pscl_throughput[k] / (v->return_bw / v->dpp_per_plane[k]), v->effective_lb_latency_hiding_source_lines_luma), v->swath_height_y[k]); + v->urgent_latency_support_us_luma = v->effective_det_plus_lb_lines_luma * (v->htotal[k] / v->pixel_clock[k]) / v->v_ratio[k] - v->effective_det_plus_lb_lines_luma * v->swath_width_y[k] * v->byte_per_pixel_dety[k] / (v->return_bw / v->dpp_per_plane[k]); if (v->byte_per_pixel_detc[k] > 0.0) { - v->effective_det_plus_lb_lines_chroma = - dcn_bw_floor2( - v->lines_in_detc[k] - + dcn_bw_min2( - v->lines_in_detc[k] - * v->dppclk - * v->byte_per_pixel_detc[k] - * v->pscl_throughput_chroma[k] - / (v->return_bw - / v->dpp_per_plane[k]), - v->effective_lb_latency_hiding_source_lines_chroma), - v->swath_height_c[k]); - v->urgent_latency_support_us_chroma = v->effective_det_plus_lb_lines_chroma - * (v->htotal[k] / v->pixel_clock[k]) / (v->v_ratio[k] / 2.0) - - v->effective_det_plus_lb_lines_chroma - * (v->swath_width_y[k] / 2.0) - * v->byte_per_pixel_detc[k] - / (v->return_bw / v->dpp_per_plane[k]); - v->urgent_latency_support_us[k] = dcn_bw_min2( - v->urgent_latency_support_us_luma, - v->urgent_latency_support_us_chroma); - } else { + v->effective_det_plus_lb_lines_chroma =dcn_bw_floor2(v->lines_in_detc[k] +dcn_bw_min2(v->lines_in_detc[k] * v->dppclk * v->byte_per_pixel_detc[k] * v->pscl_throughput_chroma[k] / (v->return_bw / v->dpp_per_plane[k]), v->effective_lb_latency_hiding_source_lines_chroma), v->swath_height_c[k]); + v->urgent_latency_support_us_chroma = v->effective_det_plus_lb_lines_chroma * (v->htotal[k] / v->pixel_clock[k]) / (v->v_ratio[k] / 2.0) - v->effective_det_plus_lb_lines_chroma * (v->swath_width_y[k] / 2.0) * v->byte_per_pixel_detc[k] / (v->return_bw / v->dpp_per_plane[k]); + v->urgent_latency_support_us[k] =dcn_bw_min2(v->urgent_latency_support_us_luma, v->urgent_latency_support_us_chroma); + } + else { v->urgent_latency_support_us[k] = v->urgent_latency_support_us_luma; } } v->min_urgent_latency_support_us = 999999.0; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - v->min_urgent_latency_support_us = dcn_bw_min2( - v->min_urgent_latency_support_us, - v->urgent_latency_support_us[k]); + v->min_urgent_latency_support_us =dcn_bw_min2(v->min_urgent_latency_support_us, v->urgent_latency_support_us[k]); } /*non-urgent latency tolerance*/ @@ -2716,63 +1396,50 @@ void dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performan /*prefetch*/ for (k = 0; k <= v->number_of_active_planes - 1; k++) { - if ((v->source_pixel_format[k] == dcn_bw_rgb_sub_64 - || v->source_pixel_format[k] == dcn_bw_rgb_sub_32 - || v->source_pixel_format[k] == dcn_bw_rgb_sub_16)) { + if ((v->source_pixel_format[k] == dcn_bw_rgb_sub_64 || v->source_pixel_format[k] == dcn_bw_rgb_sub_32 || v->source_pixel_format[k] == dcn_bw_rgb_sub_16)) { if (v->source_surface_mode[k] == dcn_bw_sw_linear) { v->block_height256_bytes_y = 1.0; - } else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_64) { + } + else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_64) { v->block_height256_bytes_y = 4.0; - } else { + } + else { v->block_height256_bytes_y = 8.0; } v->block_height256_bytes_c = 0.0; - } else { + } + else { if (v->source_surface_mode[k] == dcn_bw_sw_linear) { v->block_height256_bytes_y = 1.0; v->block_height256_bytes_c = 1.0; - } else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_8) { + } + else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_8) { v->block_height256_bytes_y = 16.0; v->block_height256_bytes_c = 8.0; - } else { + } + else { v->block_height256_bytes_y = 8.0; v->block_height256_bytes_c = 8.0; } } if (v->dcc_enable[k] == dcn_bw_yes) { - v->meta_request_width_y = 64.0 * 256.0 - / dcn_bw_ceil2(v->byte_per_pixel_dety[k], 1.0) - / (8.0 * v->block_height256_bytes_y); - v->meta_surf_width_y = dcn_bw_ceil2( - v->swath_width_y[k] - 1.0, - v->meta_request_width_y) + v->meta_request_width_y; - v->meta_surf_height_y = dcn_bw_ceil2( - v->viewport_height[k] - 1.0, - 8.0 * v->block_height256_bytes_y) - + 8.0 * v->block_height256_bytes_y; + v->meta_request_width_y = 64.0 * 256.0 /dcn_bw_ceil2(v->byte_per_pixel_dety[k], 1.0) / (8.0 * v->block_height256_bytes_y); + v->meta_surf_width_y =dcn_bw_ceil2(v->swath_width_y[k] - 1.0, v->meta_request_width_y) + v->meta_request_width_y; + v->meta_surf_height_y =dcn_bw_ceil2(v->viewport_height[k] - 1.0, 8.0 * v->block_height256_bytes_y) + 8.0 * v->block_height256_bytes_y; if (v->pte_enable == dcn_bw_yes) { - v->meta_pte_bytes_frame_y = - (dcn_bw_ceil2( - (v->meta_surf_width_y - * v->meta_surf_height_y - * dcn_bw_ceil2( - v->byte_per_pixel_dety[k], - 1.0) - / 256.0 - 4096.0) - / 8.0 / 4096.0, - 1.0) + 1) * 64.0; - } else { + v->meta_pte_bytes_frame_y = (dcn_bw_ceil2((v->meta_surf_width_y * v->meta_surf_height_y *dcn_bw_ceil2(v->byte_per_pixel_dety[k], 1.0) / 256.0 - 4096.0) / 8.0 / 4096.0, 1.0) + 1) * 64.0; + } + else { v->meta_pte_bytes_frame_y = 0.0; } if (v->source_scan[k] == dcn_bw_hor) { - v->meta_row_byte_y = v->meta_surf_width_y * 8.0 - * v->block_height256_bytes_y - * dcn_bw_ceil2(v->byte_per_pixel_dety[k], 1.0) / 256.0; - } else { - v->meta_row_byte_y = v->meta_surf_height_y * v->meta_request_width_y - * dcn_bw_ceil2(v->byte_per_pixel_dety[k], 1.0) / 256.0; - } - } else { + v->meta_row_byte_y = v->meta_surf_width_y * 8.0 * v->block_height256_bytes_y *dcn_bw_ceil2(v->byte_per_pixel_dety[k], 1.0) / 256.0; + } + else { + v->meta_row_byte_y = v->meta_surf_height_y * v->meta_request_width_y *dcn_bw_ceil2(v->byte_per_pixel_dety[k], 1.0) / 256.0; + } + } + else { v->meta_pte_bytes_frame_y = 0.0; v->meta_row_byte_y = 0.0; } @@ -2780,112 +1447,58 @@ void dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performan if (v->source_surface_mode[k] == dcn_bw_sw_linear) { v->macro_tile_size_byte_y = 256.0; v->macro_tile_height_y = 1.0; - } else if (v->source_surface_mode[k] == dcn_bw_sw_4_kb_s - || v->source_surface_mode[k] == dcn_bw_sw_4_kb_s_x - || v->source_surface_mode[k] == dcn_bw_sw_4_kb_d - || v->source_surface_mode[k] == dcn_bw_sw_4_kb_d_x) { + } + else if (v->source_surface_mode[k] == dcn_bw_sw_4_kb_s || v->source_surface_mode[k] == dcn_bw_sw_4_kb_s_x || v->source_surface_mode[k] == dcn_bw_sw_4_kb_d || v->source_surface_mode[k] == dcn_bw_sw_4_kb_d_x) { v->macro_tile_size_byte_y = 4096.0; v->macro_tile_height_y = 4.0 * v->block_height256_bytes_y; - } else if (v->source_surface_mode[k] == dcn_bw_sw_64_kb_s - || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_t - || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_x - || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d - || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_t - || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_x) { + } + else if (v->source_surface_mode[k] == dcn_bw_sw_64_kb_s || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_t || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_x || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_t || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_x) { v->macro_tile_size_byte_y = 64.0 * 1024; v->macro_tile_height_y = 16.0 * v->block_height256_bytes_y; - } else { + } + else { v->macro_tile_size_byte_y = 256.0 * 1024; v->macro_tile_height_y = 32.0 * v->block_height256_bytes_y; } if (v->macro_tile_size_byte_y <= 65536.0) { v->pixel_pte_req_height_y = v->macro_tile_height_y; - } else { + } + else { v->pixel_pte_req_height_y = 16.0 * v->block_height256_bytes_y; } - v->pixel_pte_req_width_y = 4096.0 / dcn_bw_ceil2(v->byte_per_pixel_dety[k], 1.0) - / v->pixel_pte_req_height_y * 8; + v->pixel_pte_req_width_y = 4096.0 /dcn_bw_ceil2(v->byte_per_pixel_dety[k], 1.0) / v->pixel_pte_req_height_y * 8; if (v->source_surface_mode[k] == dcn_bw_sw_linear) { - v->pixel_pte_bytes_per_row_y = - 64.0 - * (dcn_bw_ceil2( - (v->swath_width_y[k] - * dcn_bw_min2( - 128.0, - dcn_bw_pow( - 2.0, - dcn_bw_floor2( - dcn_bw_log( - v->pte_buffer_size_in_requests - * v->pixel_pte_req_width_y - / v->swath_width_y[k], - 2.0), - 1.0))) - - 1.0) - / v->pixel_pte_req_width_y, - 1.0) + 1); - } else if (v->source_scan[k] == dcn_bw_hor) { - v->pixel_pte_bytes_per_row_y = - 64.0 - * (dcn_bw_ceil2( - (v->swath_width_y[k] - - 1.0) - / v->pixel_pte_req_width_y, - 1.0) + 1); - } else { - v->pixel_pte_bytes_per_row_y = - 64.0 - * (dcn_bw_ceil2( - (v->viewport_height[k] - - 1.0) - / v->pixel_pte_req_height_y, - 1.0) + 1); - } - } else { + v->pixel_pte_bytes_per_row_y = 64.0 * (dcn_bw_ceil2((v->swath_width_y[k] *dcn_bw_min2(128.0, dcn_bw_pow(2.0,dcn_bw_floor2(dcn_bw_log(v->pte_buffer_size_in_requests * v->pixel_pte_req_width_y / v->swath_width_y[k], 2.0), 1.0))) - 1.0) / v->pixel_pte_req_width_y, 1.0) + 1); + } + else if (v->source_scan[k] == dcn_bw_hor) { + v->pixel_pte_bytes_per_row_y = 64.0 * (dcn_bw_ceil2((v->swath_width_y[k] - 1.0) / v->pixel_pte_req_width_y, 1.0) + 1); + } + else { + v->pixel_pte_bytes_per_row_y = 64.0 * (dcn_bw_ceil2((v->viewport_height[k] - 1.0) / v->pixel_pte_req_height_y, 1.0) + 1); + } + } + else { v->pixel_pte_bytes_per_row_y = 0.0; } - if ((v->source_pixel_format[k] != dcn_bw_rgb_sub_64 - && v->source_pixel_format[k] != dcn_bw_rgb_sub_32 - && v->source_pixel_format[k] != dcn_bw_rgb_sub_16)) { + if ((v->source_pixel_format[k] != dcn_bw_rgb_sub_64 && v->source_pixel_format[k] != dcn_bw_rgb_sub_32 && v->source_pixel_format[k] != dcn_bw_rgb_sub_16)) { if (v->dcc_enable[k] == dcn_bw_yes) { - v->meta_request_width_c = 64.0 * 256.0 - / dcn_bw_ceil2(v->byte_per_pixel_detc[k], 2.0) - / (8.0 * v->block_height256_bytes_c); - v->meta_surf_width_c = dcn_bw_ceil2( - v->swath_width_y[k] / 2.0 - 1.0, - v->meta_request_width_c) + v->meta_request_width_c; - v->meta_surf_height_c = dcn_bw_ceil2( - v->viewport_height[k] / 2.0 - 1.0, - 8.0 * v->block_height256_bytes_c) - + 8.0 * v->block_height256_bytes_c; + v->meta_request_width_c = 64.0 * 256.0 /dcn_bw_ceil2(v->byte_per_pixel_detc[k], 2.0) / (8.0 * v->block_height256_bytes_c); + v->meta_surf_width_c =dcn_bw_ceil2(v->swath_width_y[k] / 2.0 - 1.0, v->meta_request_width_c) + v->meta_request_width_c; + v->meta_surf_height_c =dcn_bw_ceil2(v->viewport_height[k] / 2.0 - 1.0, 8.0 * v->block_height256_bytes_c) + 8.0 * v->block_height256_bytes_c; if (v->pte_enable == dcn_bw_yes) { - v->meta_pte_bytes_frame_c = - (dcn_bw_ceil2( - (v->meta_surf_width_c - * v->meta_surf_height_c - * dcn_bw_ceil2( - v->byte_per_pixel_detc[k], - 2.0) - / 256.0 - - 4096.0) - / 8.0 - / 4096.0, - 1.0) + 1) * 64.0; - } else { + v->meta_pte_bytes_frame_c = (dcn_bw_ceil2((v->meta_surf_width_c * v->meta_surf_height_c *dcn_bw_ceil2(v->byte_per_pixel_detc[k], 2.0) / 256.0 - 4096.0) / 8.0 / 4096.0, 1.0) + 1) * 64.0; + } + else { v->meta_pte_bytes_frame_c = 0.0; } if (v->source_scan[k] == dcn_bw_hor) { - v->meta_row_byte_c = v->meta_surf_width_c * 8.0 - * v->block_height256_bytes_c - * dcn_bw_ceil2(v->byte_per_pixel_detc[k], 2.0) - / 256.0; - } else { - v->meta_row_byte_c = v->meta_surf_height_c - * v->meta_request_width_c - * dcn_bw_ceil2(v->byte_per_pixel_detc[k], 2.0) - / 256.0; - } - } else { + v->meta_row_byte_c = v->meta_surf_width_c * 8.0 * v->block_height256_bytes_c *dcn_bw_ceil2(v->byte_per_pixel_detc[k], 2.0) / 256.0; + } + else { + v->meta_row_byte_c = v->meta_surf_height_c * v->meta_request_width_c *dcn_bw_ceil2(v->byte_per_pixel_detc[k], 2.0) / 256.0; + } + } + else { v->meta_pte_bytes_frame_c = 0.0; v->meta_row_byte_c = 0.0; } @@ -2893,143 +1506,81 @@ void dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performan if (v->source_surface_mode[k] == dcn_bw_sw_linear) { v->macro_tile_size_bytes_c = 256.0; v->macro_tile_height_c = 1.0; - } else if (v->source_surface_mode[k] == dcn_bw_sw_4_kb_s - || v->source_surface_mode[k] == dcn_bw_sw_4_kb_s_x - || v->source_surface_mode[k] == dcn_bw_sw_4_kb_d - || v->source_surface_mode[k] - == dcn_bw_sw_4_kb_d_x) { + } + else if (v->source_surface_mode[k] == dcn_bw_sw_4_kb_s || v->source_surface_mode[k] == dcn_bw_sw_4_kb_s_x || v->source_surface_mode[k] == dcn_bw_sw_4_kb_d || v->source_surface_mode[k] == dcn_bw_sw_4_kb_d_x) { v->macro_tile_size_bytes_c = 4096.0; v->macro_tile_height_c = 4.0 * v->block_height256_bytes_c; - } else if (v->source_surface_mode[k] == dcn_bw_sw_64_kb_s - || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_t - || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_x - || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d - || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_t - || v->source_surface_mode[k] - == dcn_bw_sw_64_kb_d_x) { + } + else if (v->source_surface_mode[k] == dcn_bw_sw_64_kb_s || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_t || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_x || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_t || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_x) { v->macro_tile_size_bytes_c = 64.0 * 1024; v->macro_tile_height_c = 16.0 * v->block_height256_bytes_c; - } else { + } + else { v->macro_tile_size_bytes_c = 256.0 * 1024; v->macro_tile_height_c = 32.0 * v->block_height256_bytes_c; } if (v->macro_tile_size_bytes_c <= 65536.0) { v->pixel_pte_req_height_c = v->macro_tile_height_c; - } else { - v->pixel_pte_req_height_c = 16.0 - * v->block_height256_bytes_c; } - v->pixel_pte_req_width_c = 4096.0 - / dcn_bw_ceil2(v->byte_per_pixel_detc[k], 2.0) - / v->pixel_pte_req_height_c * 8; + else { + v->pixel_pte_req_height_c = 16.0 * v->block_height256_bytes_c; + } + v->pixel_pte_req_width_c = 4096.0 /dcn_bw_ceil2(v->byte_per_pixel_detc[k], 2.0) / v->pixel_pte_req_height_c * 8; if (v->source_surface_mode[k] == dcn_bw_sw_linear) { - v->pixel_pte_bytes_per_row_c = - 64.0 - * (dcn_bw_ceil2( - (v->swath_width_y[k] - / 2.0 - * dcn_bw_min2( - 128.0, - dcn_bw_pow( - 2.0, - dcn_bw_floor2( - dcn_bw_log( - v->pte_buffer_size_in_requests - * v->pixel_pte_req_width_c - / (v->swath_width_y[k] - / 2.0), - 2.0), - 1.0))) - - 1.0) - / v->pixel_pte_req_width_c, - 1.0) + 1); - } else if (v->source_scan[k] == dcn_bw_hor) { - v->pixel_pte_bytes_per_row_c = - 64.0 - * (dcn_bw_ceil2( - (v->swath_width_y[k] - / 2.0 - - 1.0) - / v->pixel_pte_req_width_c, - 1.0) + 1); - } else { - v->pixel_pte_bytes_per_row_c = - 64.0 - * (dcn_bw_ceil2( - (v->viewport_height[k] - / 2.0 - - 1.0) - / v->pixel_pte_req_height_c, - 1.0) + 1); - } - } else { + v->pixel_pte_bytes_per_row_c = 64.0 * (dcn_bw_ceil2((v->swath_width_y[k] / 2.0 * dcn_bw_min2(128.0, dcn_bw_pow(2.0,dcn_bw_floor2(dcn_bw_log(v->pte_buffer_size_in_requests * v->pixel_pte_req_width_c / (v->swath_width_y[k] / 2.0), 2.0), 1.0))) - 1.0) / v->pixel_pte_req_width_c, 1.0) + 1); + } + else if (v->source_scan[k] == dcn_bw_hor) { + v->pixel_pte_bytes_per_row_c = 64.0 * (dcn_bw_ceil2((v->swath_width_y[k] / 2.0 - 1.0) / v->pixel_pte_req_width_c, 1.0) + 1); + } + else { + v->pixel_pte_bytes_per_row_c = 64.0 * (dcn_bw_ceil2((v->viewport_height[k] / 2.0 - 1.0) / v->pixel_pte_req_height_c, 1.0) + 1); + } + } + else { v->pixel_pte_bytes_per_row_c = 0.0; } - } else { + } + else { v->pixel_pte_bytes_per_row_c = 0.0; v->meta_pte_bytes_frame_c = 0.0; v->meta_row_byte_c = 0.0; } - v->pixel_pte_bytes_per_row[k] = v->pixel_pte_bytes_per_row_y - + v->pixel_pte_bytes_per_row_c; + v->pixel_pte_bytes_per_row[k] = v->pixel_pte_bytes_per_row_y + v->pixel_pte_bytes_per_row_c; v->meta_pte_bytes_frame[k] = v->meta_pte_bytes_frame_y + v->meta_pte_bytes_frame_c; v->meta_row_byte[k] = v->meta_row_byte_y + v->meta_row_byte_c; - v->v_init_pre_fill_y[k] = dcn_bw_floor2( - (v->v_ratio[k] + v->vtaps[k] + 1.0 - + v->interlace_output[k] * 0.5 * v->v_ratio[k]) - / 2.0, - 1.0); - v->max_num_swath_y[k] = dcn_bw_ceil2( - (v->v_init_pre_fill_y[k] - 1.0) / v->swath_height_y[k], - 1.0) + 1; + v->v_init_pre_fill_y[k] =dcn_bw_floor2((v->v_ratio[k] + v->vtaps[k] + 1.0 + v->interlace_output[k] * 0.5 * v->v_ratio[k]) / 2.0, 1.0); + v->max_num_swath_y[k] =dcn_bw_ceil2((v->v_init_pre_fill_y[k] - 1.0) / v->swath_height_y[k], 1.0) + 1; if (v->v_init_pre_fill_y[k] > 1.0) { - v->max_partial_swath_y = dcn_bw_mod( - (v->v_init_pre_fill_y[k] - 2.0), - v->swath_height_y[k]); - } else { - v->max_partial_swath_y = dcn_bw_mod( - (v->v_init_pre_fill_y[k] + v->swath_height_y[k] - 2.0), - v->swath_height_y[k]); - } - v->max_partial_swath_y = dcn_bw_max2(1.0, v->max_partial_swath_y); - v->prefetch_source_lines_y[k] = v->max_num_swath_y[k] * v->swath_height_y[k] - + v->max_partial_swath_y; - if ((v->source_pixel_format[k] != dcn_bw_rgb_sub_64 - && v->source_pixel_format[k] != dcn_bw_rgb_sub_32 - && v->source_pixel_format[k] != dcn_bw_rgb_sub_16)) { - v->v_init_pre_fill_c[k] = dcn_bw_floor2( - (v->v_ratio[k] / 2.0 + v->vtaps[k] + 1.0 - + v->interlace_output[k] * 0.5 - * v->v_ratio[k] / 2.0) - / 2.0, - 1.0); - v->max_num_swath_c[k] = dcn_bw_ceil2( - (v->v_init_pre_fill_c[k] - 1.0) / v->swath_height_c[k], - 1.0) + 1; + v->max_partial_swath_y =dcn_bw_mod((v->v_init_pre_fill_y[k] - 2.0), v->swath_height_y[k]); + } + else { + v->max_partial_swath_y =dcn_bw_mod((v->v_init_pre_fill_y[k] + v->swath_height_y[k] - 2.0), v->swath_height_y[k]); + } + v->max_partial_swath_y =dcn_bw_max2(1.0, v->max_partial_swath_y); + v->prefetch_source_lines_y[k] = v->max_num_swath_y[k] * v->swath_height_y[k] + v->max_partial_swath_y; + if ((v->source_pixel_format[k] != dcn_bw_rgb_sub_64 && v->source_pixel_format[k] != dcn_bw_rgb_sub_32 && v->source_pixel_format[k] != dcn_bw_rgb_sub_16)) { + v->v_init_pre_fill_c[k] =dcn_bw_floor2((v->v_ratio[k] / 2.0 + v->vtaps[k] + 1.0 + v->interlace_output[k] * 0.5 * v->v_ratio[k] / 2.0) / 2.0, 1.0); + v->max_num_swath_c[k] =dcn_bw_ceil2((v->v_init_pre_fill_c[k] - 1.0) / v->swath_height_c[k], 1.0) + 1; if (v->v_init_pre_fill_c[k] > 1.0) { - v->max_partial_swath_c = dcn_bw_mod( - (v->v_init_pre_fill_c[k] - 2.0), - v->swath_height_c[k]); - } else { - v->max_partial_swath_c = dcn_bw_mod( - (v->v_init_pre_fill_c[k] + v->swath_height_c[k] - - 2.0), - v->swath_height_c[k]); - } - v->max_partial_swath_c = dcn_bw_max2(1.0, v->max_partial_swath_c); - } else { + v->max_partial_swath_c =dcn_bw_mod((v->v_init_pre_fill_c[k] - 2.0), v->swath_height_c[k]); + } + else { + v->max_partial_swath_c =dcn_bw_mod((v->v_init_pre_fill_c[k] + v->swath_height_c[k] - 2.0), v->swath_height_c[k]); + } + v->max_partial_swath_c =dcn_bw_max2(1.0, v->max_partial_swath_c); + } + else { v->max_num_swath_c[k] = 0.0; v->max_partial_swath_c = 0.0; } - v->prefetch_source_lines_c[k] = v->max_num_swath_c[k] * v->swath_height_c[k] - + v->max_partial_swath_c; + v->prefetch_source_lines_c[k] = v->max_num_swath_c[k] * v->swath_height_c[k] + v->max_partial_swath_c; } v->t_calc = 24.0 / v->dcf_clk_deep_sleep; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - if (v->can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one - == dcn_bw_yes) { + if (v->can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one == dcn_bw_yes) { v->max_vstartup_lines[k] = v->vtotal[k] - v->vactive[k] - 1.0; - } else { + } + else { v->max_vstartup_lines[k] = v->v_sync_plus_back_porch[k] - 1.0; } } @@ -3037,373 +1588,167 @@ void dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performan do { v->v_startup_lines = 13.0; do { - v->planes_with_room_to_increase_vstartup_prefetch_bw_less_than_active_bw = - dcn_bw_yes; - v->planes_with_room_to_increase_vstartup_vratio_prefetch_more_than4 = - dcn_bw_no; - v->planes_with_room_to_increase_vstartup_destination_line_times_for_prefetch_less_than2 = - dcn_bw_no; + v->planes_with_room_to_increase_vstartup_prefetch_bw_less_than_active_bw = dcn_bw_yes; + v->planes_with_room_to_increase_vstartup_vratio_prefetch_more_than4 = dcn_bw_no; + v->planes_with_room_to_increase_vstartup_destination_line_times_for_prefetch_less_than2 = dcn_bw_no; v->v_ratio_prefetch_more_than4 = dcn_bw_no; v->destination_line_times_for_prefetch_less_than2 = dcn_bw_no; v->prefetch_mode = v->next_prefetch_mode; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - v->dstx_after_scaler = 90.0 * v->pixel_clock[k] / v->dppclk - + 42.0 * v->pixel_clock[k] / v->dispclk; + v->dstx_after_scaler = 90.0 * v->pixel_clock[k] / v->dppclk + 42.0 * v->pixel_clock[k] / v->dispclk; if (v->dpp_per_plane[k] > 1.0) { - v->dstx_after_scaler = v->dstx_after_scaler - + v->scaler_rec_out_width[k] / 2.0; + v->dstx_after_scaler = v->dstx_after_scaler + v->scaler_rec_out_width[k] / 2.0; } if (v->output_format[k] == dcn_bw_420) { v->dsty_after_scaler = 1.0; - } else { + } + else { v->dsty_after_scaler = 0.0; } - v->v_update_offset_pix = dcn_bw_ceil2(v->htotal[k] / 4.0, 1.0); - v->total_repeater_delay_time = v->max_inter_dcn_tile_repeaters - * (2.0 / v->dppclk + 3.0 / v->dispclk); - v->v_update_width_pix = (14.0 / v->dcf_clk_deep_sleep - + 12.0 / v->dppclk + v->total_repeater_delay_time) - * v->pixel_clock[k]; - v->v_ready_offset_pix = dcn_bw_max2( - 150.0 / v->dppclk, - v->total_repeater_delay_time - + 20.0 / v->dcf_clk_deep_sleep - + 10.0 / v->dppclk) - * v->pixel_clock[k]; - v->t_setup = (v->v_update_offset_pix + v->v_update_width_pix - + v->v_ready_offset_pix) / v->pixel_clock[k]; - v->v_startup[k] = dcn_bw_min2( - v->v_startup_lines, - v->max_vstartup_lines[k]); + v->v_update_offset_pix =dcn_bw_ceil2(v->htotal[k] / 4.0, 1.0); + v->total_repeater_delay_time = v->max_inter_dcn_tile_repeaters * (2.0 / v->dppclk + 3.0 / v->dispclk); + v->v_update_width_pix = (14.0 / v->dcf_clk_deep_sleep + 12.0 / v->dppclk + v->total_repeater_delay_time) * v->pixel_clock[k]; + v->v_ready_offset_pix =dcn_bw_max2(150.0 / v->dppclk, v->total_repeater_delay_time + 20.0 / v->dcf_clk_deep_sleep + 10.0 / v->dppclk) * v->pixel_clock[k]; + v->t_setup = (v->v_update_offset_pix + v->v_update_width_pix + v->v_ready_offset_pix) / v->pixel_clock[k]; + v->v_startup[k] =dcn_bw_min2(v->v_startup_lines, v->max_vstartup_lines[k]); if (v->prefetch_mode == 0.0) { - v->t_wait = dcn_bw_max3( - v->dram_clock_change_latency - + v->urgent_latency, - v->sr_enter_plus_exit_time, - v->urgent_latency); - } else if (v->prefetch_mode == 1.0) { - v->t_wait = dcn_bw_max2( - v->sr_enter_plus_exit_time, - v->urgent_latency); - } else { + v->t_wait =dcn_bw_max3(v->dram_clock_change_latency + v->urgent_latency, v->sr_enter_plus_exit_time, v->urgent_latency); + } + else if (v->prefetch_mode == 1.0) { + v->t_wait =dcn_bw_max2(v->sr_enter_plus_exit_time, v->urgent_latency); + } + else { v->t_wait = v->urgent_latency; } - v->destination_lines_for_prefetch[k] = - dcn_bw_floor2( - 4.0 - * (v->v_startup[k] - - v->t_wait - / (v->htotal[k] - / v->pixel_clock[k]) - - (v->t_calc - + v->t_setup) - / (v->htotal[k] - / v->pixel_clock[k]) - - (v->dsty_after_scaler - + v->dstx_after_scaler - / v->htotal[k]) - + 0.125), - 1.0) / 4; + v->destination_lines_for_prefetch[k] =dcn_bw_floor2(4.0 * (v->v_startup[k] - v->t_wait / (v->htotal[k] / v->pixel_clock[k]) - (v->t_calc + v->t_setup) / (v->htotal[k] / v->pixel_clock[k]) - (v->dsty_after_scaler + v->dstx_after_scaler / v->htotal[k]) + 0.125), 1.0) / 4; if (v->destination_lines_for_prefetch[k] > 0.0) { - v->prefetch_bandwidth[k] = - (v->meta_pte_bytes_frame[k] - + 2.0 * v->meta_row_byte[k] - + 2.0 - * v->pixel_pte_bytes_per_row[k] - + v->prefetch_source_lines_y[k] - * v->swath_width_y[k] - * dcn_bw_ceil2( - v->byte_per_pixel_dety[k], - 1.0) - + v->prefetch_source_lines_c[k] - * v->swath_width_y[k] - / 2.0 - * dcn_bw_ceil2( - v->byte_per_pixel_detc[k], - 2.0)) - / (v->destination_lines_for_prefetch[k] - * v->htotal[k] - / v->pixel_clock[k]); - } else { + v->prefetch_bandwidth[k] = (v->meta_pte_bytes_frame[k] + 2.0 * v->meta_row_byte[k] + 2.0 * v->pixel_pte_bytes_per_row[k] + v->prefetch_source_lines_y[k] * v->swath_width_y[k] *dcn_bw_ceil2(v->byte_per_pixel_dety[k], 1.0) + v->prefetch_source_lines_c[k] * v->swath_width_y[k] / 2.0 *dcn_bw_ceil2(v->byte_per_pixel_detc[k], 2.0)) / (v->destination_lines_for_prefetch[k] * v->htotal[k] / v->pixel_clock[k]); + } + else { v->prefetch_bandwidth[k] = 999999.0; } } v->bandwidth_available_for_immediate_flip = v->return_bw; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - v->bandwidth_available_for_immediate_flip = - v->bandwidth_available_for_immediate_flip - - dcn_bw_max2( - v->read_bandwidth_plane_luma[k] - + v->read_bandwidth_plane_chroma[k], - v->prefetch_bandwidth[k]); + v->bandwidth_available_for_immediate_flip = v->bandwidth_available_for_immediate_flip -dcn_bw_max2(v->read_bandwidth_plane_luma[k] + v->read_bandwidth_plane_chroma[k], v->prefetch_bandwidth[k]); } v->tot_immediate_flip_bytes = 0.0; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - if (v->immediate_flip_supported == dcn_bw_yes - && (v->source_pixel_format[k] != dcn_bw_yuv420_sub_8 - && v->source_pixel_format[k] - != dcn_bw_yuv420_sub_10)) { - v->tot_immediate_flip_bytes = v->tot_immediate_flip_bytes - + v->meta_pte_bytes_frame[k] - + v->meta_row_byte[k] - + v->pixel_pte_bytes_per_row[k]; + if (v->immediate_flip_supported == dcn_bw_yes && (v->source_pixel_format[k] != dcn_bw_yuv420_sub_8 && v->source_pixel_format[k] != dcn_bw_yuv420_sub_10)) { + v->tot_immediate_flip_bytes = v->tot_immediate_flip_bytes + v->meta_pte_bytes_frame[k] + v->meta_row_byte[k] + v->pixel_pte_bytes_per_row[k]; } } v->max_rd_bandwidth = 0.0; for (k = 0; k <= v->number_of_active_planes - 1; k++) { if (v->pte_enable == dcn_bw_yes && v->dcc_enable[k] == dcn_bw_yes) { - if (v->immediate_flip_supported == dcn_bw_yes - && (v->source_pixel_format[k] - != dcn_bw_yuv420_sub_8 - && v->source_pixel_format[k] - != dcn_bw_yuv420_sub_10)) { - v->time_for_fetching_meta_pte = - dcn_bw_max5( - v->meta_pte_bytes_frame[k] - / v->prefetch_bandwidth[k], - v->meta_pte_bytes_frame[k] - * v->tot_immediate_flip_bytes - / (v->bandwidth_available_for_immediate_flip - * (v->meta_pte_bytes_frame[k] - + v->meta_row_byte[k] - + v->pixel_pte_bytes_per_row[k])), - v->urgent_extra_latency, - v->urgent_latency, - v->htotal[k] - / v->pixel_clock[k] - / 4.0); - } else { - v->time_for_fetching_meta_pte = - dcn_bw_max3( - v->meta_pte_bytes_frame[k] - / v->prefetch_bandwidth[k], - v->urgent_extra_latency, - v->htotal[k] - / v->pixel_clock[k] - / 4.0); + if (v->immediate_flip_supported == dcn_bw_yes && (v->source_pixel_format[k] != dcn_bw_yuv420_sub_8 && v->source_pixel_format[k] != dcn_bw_yuv420_sub_10)) { + v->time_for_fetching_meta_pte =dcn_bw_max5(v->meta_pte_bytes_frame[k] / v->prefetch_bandwidth[k], v->meta_pte_bytes_frame[k] * v->tot_immediate_flip_bytes / (v->bandwidth_available_for_immediate_flip * (v->meta_pte_bytes_frame[k] + v->meta_row_byte[k] + v->pixel_pte_bytes_per_row[k])), v->urgent_extra_latency, v->urgent_latency, v->htotal[k] / v->pixel_clock[k] / 4.0); + } + else { + v->time_for_fetching_meta_pte =dcn_bw_max3(v->meta_pte_bytes_frame[k] / v->prefetch_bandwidth[k], v->urgent_extra_latency, v->htotal[k] / v->pixel_clock[k] / 4.0); } - } else { - v->time_for_fetching_meta_pte = v->htotal[k] - / v->pixel_clock[k] / 4.0; - } - v->destination_lines_to_request_vm_inv_blank[k] = - dcn_bw_floor2( - 4.0 - * (v->time_for_fetching_meta_pte - / (v->htotal[k] - / v->pixel_clock[k]) - + 0.125), - 1.0) / 4; + } + else { + v->time_for_fetching_meta_pte = v->htotal[k] / v->pixel_clock[k] / 4.0; + } + v->destination_lines_to_request_vm_inv_blank[k] =dcn_bw_floor2(4.0 * (v->time_for_fetching_meta_pte / (v->htotal[k] / v->pixel_clock[k]) + 0.125), 1.0) / 4; if ((v->pte_enable == dcn_bw_yes || v->dcc_enable[k] == dcn_bw_yes)) { - if (v->immediate_flip_supported == dcn_bw_yes - && (v->source_pixel_format[k] - != dcn_bw_yuv420_sub_8 - && v->source_pixel_format[k] - != dcn_bw_yuv420_sub_10)) { - v->time_for_fetching_row_in_vblank = - dcn_bw_max5( - (v->meta_row_byte[k] - + v->pixel_pte_bytes_per_row[k]) - / v->prefetch_bandwidth[k], - (v->meta_row_byte[k] - + v->pixel_pte_bytes_per_row[k]) - * v->tot_immediate_flip_bytes - / (v->bandwidth_available_for_immediate_flip - * (v->meta_pte_bytes_frame[k] - + v->meta_row_byte[k] - + v->pixel_pte_bytes_per_row[k])), - v->urgent_extra_latency, - 2.0 - * v->urgent_latency, - v->htotal[k] - / v->pixel_clock[k] - - v->time_for_fetching_meta_pte); - } else { - v->time_for_fetching_row_in_vblank = - dcn_bw_max3( - (v->meta_row_byte[k] - + v->pixel_pte_bytes_per_row[k]) - / v->prefetch_bandwidth[k], - v->urgent_extra_latency, - v->htotal[k] - / v->pixel_clock[k] - - v->time_for_fetching_meta_pte); + if (v->immediate_flip_supported == dcn_bw_yes && (v->source_pixel_format[k] != dcn_bw_yuv420_sub_8 && v->source_pixel_format[k] != dcn_bw_yuv420_sub_10)) { + v->time_for_fetching_row_in_vblank =dcn_bw_max5((v->meta_row_byte[k] + v->pixel_pte_bytes_per_row[k]) / v->prefetch_bandwidth[k], (v->meta_row_byte[k] + v->pixel_pte_bytes_per_row[k]) * v->tot_immediate_flip_bytes / (v->bandwidth_available_for_immediate_flip * (v->meta_pte_bytes_frame[k] + v->meta_row_byte[k] + v->pixel_pte_bytes_per_row[k])), v->urgent_extra_latency, 2.0 * v->urgent_latency, v->htotal[k] / v->pixel_clock[k] - v->time_for_fetching_meta_pte); + } + else { + v->time_for_fetching_row_in_vblank =dcn_bw_max3((v->meta_row_byte[k] + v->pixel_pte_bytes_per_row[k]) / v->prefetch_bandwidth[k], v->urgent_extra_latency, v->htotal[k] / v->pixel_clock[k] - v->time_for_fetching_meta_pte); } - } else { - v->time_for_fetching_row_in_vblank = - dcn_bw_max2( - v->urgent_extra_latency - - v->time_for_fetching_meta_pte, - v->htotal[k] - / v->pixel_clock[k] - - v->time_for_fetching_meta_pte); - } - v->destination_lines_to_request_row_in_vblank[k] = - dcn_bw_floor2( - 4.0 - * (v->time_for_fetching_row_in_vblank - / (v->htotal[k] - / v->pixel_clock[k]) - + 0.125), - 1.0) / 4; - v->lines_to_request_prefetch_pixel_data = - v->destination_lines_for_prefetch[k] - - v->destination_lines_to_request_vm_inv_blank[k] - - v->destination_lines_to_request_row_in_vblank[k]; + } + else { + v->time_for_fetching_row_in_vblank =dcn_bw_max2(v->urgent_extra_latency - v->time_for_fetching_meta_pte, v->htotal[k] / v->pixel_clock[k] - v->time_for_fetching_meta_pte); + } + v->destination_lines_to_request_row_in_vblank[k] =dcn_bw_floor2(4.0 * (v->time_for_fetching_row_in_vblank / (v->htotal[k] / v->pixel_clock[k]) + 0.125), 1.0) / 4; + v->lines_to_request_prefetch_pixel_data = v->destination_lines_for_prefetch[k] - v->destination_lines_to_request_vm_inv_blank[k] - v->destination_lines_to_request_row_in_vblank[k]; if (v->lines_to_request_prefetch_pixel_data > 0.0) { - v->v_ratio_prefetch_y[k] = v->prefetch_source_lines_y[k] - / v->lines_to_request_prefetch_pixel_data; + v->v_ratio_prefetch_y[k] = v->prefetch_source_lines_y[k] / v->lines_to_request_prefetch_pixel_data; if ((v->swath_height_y[k] > 4.0)) { - if (v->lines_to_request_prefetch_pixel_data - > (v->v_init_pre_fill_y[k] - 3.0) - / 2.0) { - v->v_ratio_prefetch_y[k] = - dcn_bw_max2( - v->v_ratio_prefetch_y[k], - v->max_num_swath_y[k] - * v->swath_height_y[k] - / (v->lines_to_request_prefetch_pixel_data - - (v->v_init_pre_fill_y[k] - - 3.0) - / 2.0)); - } else { + if (v->lines_to_request_prefetch_pixel_data > (v->v_init_pre_fill_y[k] - 3.0) / 2.0) { + v->v_ratio_prefetch_y[k] =dcn_bw_max2(v->v_ratio_prefetch_y[k], v->max_num_swath_y[k] * v->swath_height_y[k] / (v->lines_to_request_prefetch_pixel_data - (v->v_init_pre_fill_y[k] - 3.0) / 2.0)); + } + else { v->v_ratio_prefetch_y[k] = 999999.0; } } - } else { + } + else { v->v_ratio_prefetch_y[k] = 999999.0; } - v->v_ratio_prefetch_y[k] = dcn_bw_max2(v->v_ratio_prefetch_y[k], 1.0); + v->v_ratio_prefetch_y[k] =dcn_bw_max2(v->v_ratio_prefetch_y[k], 1.0); if (v->lines_to_request_prefetch_pixel_data > 0.0) { - v->v_ratio_prefetch_c[k] = v->prefetch_source_lines_c[k] - / v->lines_to_request_prefetch_pixel_data; + v->v_ratio_prefetch_c[k] = v->prefetch_source_lines_c[k] / v->lines_to_request_prefetch_pixel_data; if ((v->swath_height_c[k] > 4.0)) { - if (v->lines_to_request_prefetch_pixel_data - > (v->v_init_pre_fill_c[k] - 3.0) - / 2.0) { - v->v_ratio_prefetch_c[k] = - dcn_bw_max2( - v->v_ratio_prefetch_c[k], - v->max_num_swath_c[k] - * v->swath_height_c[k] - / (v->lines_to_request_prefetch_pixel_data - - (v->v_init_pre_fill_c[k] - - 3.0) - / 2.0)); - } else { + if (v->lines_to_request_prefetch_pixel_data > (v->v_init_pre_fill_c[k] - 3.0) / 2.0) { + v->v_ratio_prefetch_c[k] =dcn_bw_max2(v->v_ratio_prefetch_c[k], v->max_num_swath_c[k] * v->swath_height_c[k] / (v->lines_to_request_prefetch_pixel_data - (v->v_init_pre_fill_c[k] - 3.0) / 2.0)); + } + else { v->v_ratio_prefetch_c[k] = 999999.0; } } - } else { + } + else { v->v_ratio_prefetch_c[k] = 999999.0; } - v->v_ratio_prefetch_c[k] = dcn_bw_max2(v->v_ratio_prefetch_c[k], 1.0); + v->v_ratio_prefetch_c[k] =dcn_bw_max2(v->v_ratio_prefetch_c[k], 1.0); if (v->lines_to_request_prefetch_pixel_data > 0.0) { - v->required_prefetch_pix_data_bw = - v->dpp_per_plane[k] - * (v->prefetch_source_lines_y[k] - / v->lines_to_request_prefetch_pixel_data - * dcn_bw_ceil2( - v->byte_per_pixel_dety[k], - 1.0) - + v->prefetch_source_lines_c[k] - / v->lines_to_request_prefetch_pixel_data - * dcn_bw_ceil2( - v->byte_per_pixel_detc[k], - 2.0) - / 2.0) - * v->swath_width_y[k] - / (v->htotal[k] - / v->pixel_clock[k]); - } else { + v->required_prefetch_pix_data_bw = v->dpp_per_plane[k] * (v->prefetch_source_lines_y[k] / v->lines_to_request_prefetch_pixel_data *dcn_bw_ceil2(v->byte_per_pixel_dety[k], 1.0) + v->prefetch_source_lines_c[k] / v->lines_to_request_prefetch_pixel_data *dcn_bw_ceil2(v->byte_per_pixel_detc[k], 2.0) / 2.0) * v->swath_width_y[k] / (v->htotal[k] / v->pixel_clock[k]); + } + else { v->required_prefetch_pix_data_bw = 999999.0; } - v->max_rd_bandwidth = - v->max_rd_bandwidth - + dcn_bw_max2( - v->read_bandwidth_plane_luma[k] - + v->read_bandwidth_plane_chroma[k], - v->required_prefetch_pix_data_bw); - if (v->immediate_flip_supported == dcn_bw_yes - && (v->source_pixel_format[k] != dcn_bw_yuv420_sub_8 - && v->source_pixel_format[k] - != dcn_bw_yuv420_sub_10)) { - v->max_rd_bandwidth = - v->max_rd_bandwidth - + dcn_bw_max2( - v->meta_pte_bytes_frame[k] - / (v->destination_lines_to_request_vm_inv_blank[k] - * v->htotal[k] - / v->pixel_clock[k]), - (v->meta_row_byte[k] - + v->pixel_pte_bytes_per_row[k]) - / (v->destination_lines_to_request_row_in_vblank[k] - * v->htotal[k] - / v->pixel_clock[k])); - } - if (v->v_ratio_prefetch_y[k] > 4.0 - || v->v_ratio_prefetch_c[k] > 4.0) { + v->max_rd_bandwidth = v->max_rd_bandwidth +dcn_bw_max2(v->read_bandwidth_plane_luma[k] + v->read_bandwidth_plane_chroma[k], v->required_prefetch_pix_data_bw); + if (v->immediate_flip_supported == dcn_bw_yes && (v->source_pixel_format[k] != dcn_bw_yuv420_sub_8 && v->source_pixel_format[k] != dcn_bw_yuv420_sub_10)) { + v->max_rd_bandwidth = v->max_rd_bandwidth +dcn_bw_max2(v->meta_pte_bytes_frame[k] / (v->destination_lines_to_request_vm_inv_blank[k] * v->htotal[k] / v->pixel_clock[k]), (v->meta_row_byte[k] + v->pixel_pte_bytes_per_row[k]) / (v->destination_lines_to_request_row_in_vblank[k] * v->htotal[k] / v->pixel_clock[k])); + } + if (v->v_ratio_prefetch_y[k] > 4.0 || v->v_ratio_prefetch_c[k] > 4.0) { v->v_ratio_prefetch_more_than4 = dcn_bw_yes; } if (v->destination_lines_for_prefetch[k] < 2.0) { - v->destination_line_times_for_prefetch_less_than2 = - dcn_bw_yes; + v->destination_line_times_for_prefetch_less_than2 = dcn_bw_yes; } if (v->max_vstartup_lines[k] > v->v_startup_lines) { - if (v->required_prefetch_pix_data_bw - > (v->read_bandwidth_plane_luma[k] - + v->read_bandwidth_plane_chroma[k])) { - v->planes_with_room_to_increase_vstartup_prefetch_bw_less_than_active_bw = - dcn_bw_no; + if (v->required_prefetch_pix_data_bw > (v->read_bandwidth_plane_luma[k] + v->read_bandwidth_plane_chroma[k])) { + v->planes_with_room_to_increase_vstartup_prefetch_bw_less_than_active_bw = dcn_bw_no; } - if (v->v_ratio_prefetch_y[k] > 4.0 - || v->v_ratio_prefetch_c[k] > 4.0) { - v->planes_with_room_to_increase_vstartup_vratio_prefetch_more_than4 = - dcn_bw_yes; + if (v->v_ratio_prefetch_y[k] > 4.0 || v->v_ratio_prefetch_c[k] > 4.0) { + v->planes_with_room_to_increase_vstartup_vratio_prefetch_more_than4 = dcn_bw_yes; } if (v->destination_lines_for_prefetch[k] < 2.0) { - v->planes_with_room_to_increase_vstartup_destination_line_times_for_prefetch_less_than2 = - dcn_bw_yes; + v->planes_with_room_to_increase_vstartup_destination_line_times_for_prefetch_less_than2 = dcn_bw_yes; } } } - if (v->max_rd_bandwidth <= v->return_bw - && v->v_ratio_prefetch_more_than4 == dcn_bw_no - && v->destination_line_times_for_prefetch_less_than2 - == dcn_bw_no) { + if (v->max_rd_bandwidth <= v->return_bw && v->v_ratio_prefetch_more_than4 == dcn_bw_no && v->destination_line_times_for_prefetch_less_than2 == dcn_bw_no) { v->prefetch_mode_supported = dcn_bw_yes; - } else { + } + else { v->prefetch_mode_supported = dcn_bw_no; } v->v_startup_lines = v->v_startup_lines + 1.0; - } while (!(v->prefetch_mode_supported == dcn_bw_yes - || (v->planes_with_room_to_increase_vstartup_prefetch_bw_less_than_active_bw - == dcn_bw_yes - && v->planes_with_room_to_increase_vstartup_vratio_prefetch_more_than4 - == dcn_bw_no - && v->planes_with_room_to_increase_vstartup_destination_line_times_for_prefetch_less_than2 - == dcn_bw_no))); + } while (!(v->prefetch_mode_supported == dcn_bw_yes || (v->planes_with_room_to_increase_vstartup_prefetch_bw_less_than_active_bw == dcn_bw_yes && v->planes_with_room_to_increase_vstartup_vratio_prefetch_more_than4 == dcn_bw_no && v->planes_with_room_to_increase_vstartup_destination_line_times_for_prefetch_less_than2 == dcn_bw_no))); v->next_prefetch_mode = v->next_prefetch_mode + 1.0; } while (!(v->prefetch_mode_supported == dcn_bw_yes || v->prefetch_mode == 2.0)); for (k = 0; k <= v->number_of_active_planes - 1; k++) { if (v->v_ratio_prefetch_y[k] <= 1.0) { - v->display_pipe_line_delivery_time_luma_prefetch[k] = v->swath_width_y[k] - * v->dpp_per_plane[k] / v->h_ratio[k] / v->pixel_clock[k]; - } else { - v->display_pipe_line_delivery_time_luma_prefetch[k] = v->swath_width_y[k] - / v->pscl_throughput[k] / v->dppclk; + v->display_pipe_line_delivery_time_luma_prefetch[k] = v->swath_width_y[k] * v->dpp_per_plane[k] / v->h_ratio[k] / v->pixel_clock[k]; + } + else { + v->display_pipe_line_delivery_time_luma_prefetch[k] = v->swath_width_y[k] / v->pscl_throughput[k] / v->dppclk; } if (v->byte_per_pixel_detc[k] == 0.0) { v->display_pipe_line_delivery_time_chroma_prefetch[k] = 0.0; - } else { + } + else { if (v->v_ratio_prefetch_c[k] <= 1.0) { - v->display_pipe_line_delivery_time_chroma_prefetch[k] = - v->swath_width_y[k] * v->dpp_per_plane[k] - / v->h_ratio[k] / v->pixel_clock[k]; - } else { - v->display_pipe_line_delivery_time_chroma_prefetch[k] = - v->swath_width_y[k] / v->pscl_throughput[k] - / v->dppclk; + v->display_pipe_line_delivery_time_chroma_prefetch[k] = v->swath_width_y[k] * v->dpp_per_plane[k] / v->h_ratio[k] / v->pixel_clock[k]; + } + else { + v->display_pipe_line_delivery_time_chroma_prefetch[k] = v->swath_width_y[k] / v->pscl_throughput[k] / v->dppclk; } } } @@ -3413,19 +1758,14 @@ void dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performan if (v->prefetch_mode == 0.0) { v->allow_dram_clock_change_during_vblank[k] = dcn_bw_yes; v->allow_dram_self_refresh_during_vblank[k] = dcn_bw_yes; - v->min_ttuv_blank[k] = v->t_calc - + dcn_bw_max3( - v->dram_clock_change_watermark, - v->stutter_enter_plus_exit_watermark, - v->urgent_watermark); - } else if (v->prefetch_mode == 1.0) { + v->min_ttuv_blank[k] = v->t_calc +dcn_bw_max3(v->dram_clock_change_watermark, v->stutter_enter_plus_exit_watermark, v->urgent_watermark); + } + else if (v->prefetch_mode == 1.0) { v->allow_dram_clock_change_during_vblank[k] = dcn_bw_no; v->allow_dram_self_refresh_during_vblank[k] = dcn_bw_yes; - v->min_ttuv_blank[k] = v->t_calc - + dcn_bw_max2( - v->stutter_enter_plus_exit_watermark, - v->urgent_watermark); - } else { + v->min_ttuv_blank[k] = v->t_calc +dcn_bw_max2(v->stutter_enter_plus_exit_watermark, v->urgent_watermark); + } + else { v->allow_dram_clock_change_during_vblank[k] = dcn_bw_no; v->allow_dram_self_refresh_during_vblank[k] = dcn_bw_no; v->min_ttuv_blank[k] = v->t_calc + v->urgent_watermark; @@ -3438,131 +1778,61 @@ void dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performan v->active_dp_ps = v->active_dp_ps + v->dpp_per_plane[k]; } for (k = 0; k <= v->number_of_active_planes - 1; k++) { - v->lb_latency_hiding_source_lines_y = - dcn_bw_min2( - v->max_line_buffer_lines, - dcn_bw_floor2( - v->line_buffer_size - / v->lb_bit_per_pixel[k] - / (v->swath_width_y[k] - / dcn_bw_max2( - v->h_ratio[k], - 1.0)), - 1.0)) - (v->vtaps[k] - 1.0); - v->lb_latency_hiding_source_lines_c = - dcn_bw_min2( - v->max_line_buffer_lines, - dcn_bw_floor2( - v->line_buffer_size - / v->lb_bit_per_pixel[k] - / (v->swath_width_y[k] - / 2.0 - / dcn_bw_max2( - v->h_ratio[k] - / 2.0, - 1.0)), - 1.0)) - (v->vta_pschroma[k] - 1.0); - v->effective_lb_latency_hiding_y = v->lb_latency_hiding_source_lines_y - / v->v_ratio[k] * (v->htotal[k] / v->pixel_clock[k]); - v->effective_lb_latency_hiding_c = v->lb_latency_hiding_source_lines_c - / (v->v_ratio[k] / 2.0) * (v->htotal[k] / v->pixel_clock[k]); + v->lb_latency_hiding_source_lines_y =dcn_bw_min2(v->max_line_buffer_lines,dcn_bw_floor2(v->line_buffer_size / v->lb_bit_per_pixel[k] / (v->swath_width_y[k] /dcn_bw_max2(v->h_ratio[k], 1.0)), 1.0)) - (v->vtaps[k] - 1.0); + v->lb_latency_hiding_source_lines_c =dcn_bw_min2(v->max_line_buffer_lines,dcn_bw_floor2(v->line_buffer_size / v->lb_bit_per_pixel[k] / (v->swath_width_y[k] / 2.0 /dcn_bw_max2(v->h_ratio[k] / 2.0, 1.0)), 1.0)) - (v->vta_pschroma[k] - 1.0); + v->effective_lb_latency_hiding_y = v->lb_latency_hiding_source_lines_y / v->v_ratio[k] * (v->htotal[k] / v->pixel_clock[k]); + v->effective_lb_latency_hiding_c = v->lb_latency_hiding_source_lines_c / (v->v_ratio[k] / 2.0) * (v->htotal[k] / v->pixel_clock[k]); if (v->swath_width_y[k] > 2.0 * v->dpp_output_buffer_pixels) { - v->dpp_output_buffer_lines_y = v->dpp_output_buffer_pixels - / v->swath_width_y[k]; - } else if (v->swath_width_y[k] > v->dpp_output_buffer_pixels) { + v->dpp_output_buffer_lines_y = v->dpp_output_buffer_pixels / v->swath_width_y[k]; + } + else if (v->swath_width_y[k] > v->dpp_output_buffer_pixels) { v->dpp_output_buffer_lines_y = 0.5; - } else { + } + else { v->dpp_output_buffer_lines_y = 1.0; } if (v->swath_width_y[k] / 2.0 > 2.0 * v->dpp_output_buffer_pixels) { - v->dpp_output_buffer_lines_c = v->dpp_output_buffer_pixels - / (v->swath_width_y[k] / 2.0); - } else if (v->swath_width_y[k] / 2.0 > v->dpp_output_buffer_pixels) { + v->dpp_output_buffer_lines_c = v->dpp_output_buffer_pixels / (v->swath_width_y[k] / 2.0); + } + else if (v->swath_width_y[k] / 2.0 > v->dpp_output_buffer_pixels) { v->dpp_output_buffer_lines_c = 0.5; - } else { + } + else { v->dpp_output_buffer_lines_c = 1.0; } - v->dppopp_buffering_y = (v->htotal[k] / v->pixel_clock[k]) - * (v->dpp_output_buffer_lines_y + v->opp_output_buffer_lines); - v->max_det_buffering_time_y = v->full_det_buffering_time_y[k] - + (v->lines_in_dety[k] - v->lines_in_dety_rounded_down_to_swath[k]) - / v->swath_height_y[k] - * (v->htotal[k] / v->pixel_clock[k]); - v->active_dram_clock_change_latency_margin_y = v->dppopp_buffering_y - + v->effective_lb_latency_hiding_y + v->max_det_buffering_time_y - - v->dram_clock_change_watermark; + v->dppopp_buffering_y = (v->htotal[k] / v->pixel_clock[k]) * (v->dpp_output_buffer_lines_y + v->opp_output_buffer_lines); + v->max_det_buffering_time_y = v->full_det_buffering_time_y[k] + (v->lines_in_dety[k] - v->lines_in_dety_rounded_down_to_swath[k]) / v->swath_height_y[k] * (v->htotal[k] / v->pixel_clock[k]); + v->active_dram_clock_change_latency_margin_y = v->dppopp_buffering_y + v->effective_lb_latency_hiding_y + v->max_det_buffering_time_y - v->dram_clock_change_watermark; if (v->active_dp_ps > 1.0) { - v->active_dram_clock_change_latency_margin_y = - v->active_dram_clock_change_latency_margin_y - - (1.0 - 1.0 / (v->active_dp_ps - 1.0)) - * v->swath_height_y[k] - * (v->htotal[k] - / v->pixel_clock[k]); + v->active_dram_clock_change_latency_margin_y = v->active_dram_clock_change_latency_margin_y - (1.0 - 1.0 / (v->active_dp_ps - 1.0)) * v->swath_height_y[k] * (v->htotal[k] / v->pixel_clock[k]); } if (v->byte_per_pixel_detc[k] > 0.0) { - v->dppopp_buffering_c = - (v->htotal[k] / v->pixel_clock[k]) - * (v->dpp_output_buffer_lines_c - + v->opp_output_buffer_lines); - v->max_det_buffering_time_c = v->full_det_buffering_time_c[k] - + (v->lines_in_detc[k] - - v->lines_in_detc_rounded_down_to_swath[k]) - / v->swath_height_c[k] - * (v->htotal[k] / v->pixel_clock[k]); - v->active_dram_clock_change_latency_margin_c = v->dppopp_buffering_c - + v->effective_lb_latency_hiding_c - + v->max_det_buffering_time_c - - v->dram_clock_change_watermark; + v->dppopp_buffering_c = (v->htotal[k] / v->pixel_clock[k]) * (v->dpp_output_buffer_lines_c + v->opp_output_buffer_lines); + v->max_det_buffering_time_c = v->full_det_buffering_time_c[k] + (v->lines_in_detc[k] - v->lines_in_detc_rounded_down_to_swath[k]) / v->swath_height_c[k] * (v->htotal[k] / v->pixel_clock[k]); + v->active_dram_clock_change_latency_margin_c = v->dppopp_buffering_c + v->effective_lb_latency_hiding_c + v->max_det_buffering_time_c - v->dram_clock_change_watermark; if (v->active_dp_ps > 1.0) { - v->active_dram_clock_change_latency_margin_c = - v->active_dram_clock_change_latency_margin_c - - (1.0 - - 1.0 - / (v->active_dp_ps - - 1.0)) - * v->swath_height_c[k] - * (v->htotal[k] - / v->pixel_clock[k]); - } - v->active_dram_clock_change_latency_margin[k] = dcn_bw_min2( - v->active_dram_clock_change_latency_margin_y, - v->active_dram_clock_change_latency_margin_c); - } else { - v->active_dram_clock_change_latency_margin[k] = - v->active_dram_clock_change_latency_margin_y; + v->active_dram_clock_change_latency_margin_c = v->active_dram_clock_change_latency_margin_c - (1.0 - 1.0 / (v->active_dp_ps - 1.0)) * v->swath_height_c[k] * (v->htotal[k] / v->pixel_clock[k]); + } + v->active_dram_clock_change_latency_margin[k] =dcn_bw_min2(v->active_dram_clock_change_latency_margin_y, v->active_dram_clock_change_latency_margin_c); + } + else { + v->active_dram_clock_change_latency_margin[k] = v->active_dram_clock_change_latency_margin_y; } if (v->output_format[k] == dcn_bw_444) { - v->writeback_dram_clock_change_latency_margin = - (v->writeback_luma_buffer_size - + v->writeback_chroma_buffer_size) * 1024.0 - / (v->scaler_rec_out_width[k] - / (v->htotal[k] - / v->pixel_clock[k]) - * 4.0) - - v->writeback_dram_clock_change_watermark; - } else { - v->writeback_dram_clock_change_latency_margin = dcn_bw_min2( - v->writeback_luma_buffer_size, - 2.0 * v->writeback_chroma_buffer_size) * 1024.0 - / (v->scaler_rec_out_width[k] - / (v->htotal[k] / v->pixel_clock[k])) - - v->writeback_dram_clock_change_watermark; + v->writeback_dram_clock_change_latency_margin = (v->writeback_luma_buffer_size + v->writeback_chroma_buffer_size) * 1024.0 / (v->scaler_rec_out_width[k] / (v->htotal[k] / v->pixel_clock[k]) * 4.0) - v->writeback_dram_clock_change_watermark; + } + else { + v->writeback_dram_clock_change_latency_margin =dcn_bw_min2(v->writeback_luma_buffer_size, 2.0 * v->writeback_chroma_buffer_size) * 1024.0 / (v->scaler_rec_out_width[k] / (v->htotal[k] / v->pixel_clock[k])) - v->writeback_dram_clock_change_watermark; } if (v->output[k] == dcn_bw_writeback) { - v->active_dram_clock_change_latency_margin[k] = dcn_bw_min2( - v->active_dram_clock_change_latency_margin[k], - v->writeback_dram_clock_change_latency_margin); + v->active_dram_clock_change_latency_margin[k] =dcn_bw_min2(v->active_dram_clock_change_latency_margin[k], v->writeback_dram_clock_change_latency_margin); } } for (k = 0; k <= v->number_of_active_planes - 1; k++) { if (v->allow_dram_clock_change_during_vblank[k] == dcn_bw_yes) { - v->v_blank_dram_clock_change_latency_margin[k] = (v->vtotal[k] - - v->scaler_recout_height[k]) - * (v->htotal[k] / v->pixel_clock[k]) - - dcn_bw_max2( - v->dram_clock_change_watermark, - v->writeback_dram_clock_change_watermark); - } else { + v->v_blank_dram_clock_change_latency_margin[k] = (v->vtotal[k] - v->scaler_recout_height[k]) * (v->htotal[k] / v->pixel_clock[k]) -dcn_bw_max2(v->dram_clock_change_watermark, v->writeback_dram_clock_change_watermark); + } + else { v->v_blank_dram_clock_change_latency_margin[k] = 0.0; } } @@ -3570,45 +1840,37 @@ void dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performan v->v_blank_of_min_active_dram_clock_change_margin = 999999.0; v->second_min_active_dram_clock_change_margin = 999999.0; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - if (v->active_dram_clock_change_latency_margin[k] - < v->min_active_dram_clock_change_margin) { - v->second_min_active_dram_clock_change_margin = - v->min_active_dram_clock_change_margin; - v->min_active_dram_clock_change_margin = - v->active_dram_clock_change_latency_margin[k]; - v->v_blank_of_min_active_dram_clock_change_margin = - v->v_blank_dram_clock_change_latency_margin[k]; - } else if (v->active_dram_clock_change_latency_margin[k] - < v->second_min_active_dram_clock_change_margin) { - v->second_min_active_dram_clock_change_margin = - v->active_dram_clock_change_latency_margin[k]; + if (v->active_dram_clock_change_latency_margin[k] < v->min_active_dram_clock_change_margin) { + v->second_min_active_dram_clock_change_margin = v->min_active_dram_clock_change_margin; + v->min_active_dram_clock_change_margin = v->active_dram_clock_change_latency_margin[k]; + v->v_blank_of_min_active_dram_clock_change_margin = v->v_blank_dram_clock_change_latency_margin[k]; + } + else if (v->active_dram_clock_change_latency_margin[k] < v->second_min_active_dram_clock_change_margin) { + v->second_min_active_dram_clock_change_margin = v->active_dram_clock_change_latency_margin[k]; } } v->min_vblank_dram_clock_change_margin = 999999.0; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - if (v->min_vblank_dram_clock_change_margin - > v->v_blank_dram_clock_change_latency_margin[k]) { - v->min_vblank_dram_clock_change_margin = - v->v_blank_dram_clock_change_latency_margin[k]; + if (v->min_vblank_dram_clock_change_margin > v->v_blank_dram_clock_change_latency_margin[k]) { + v->min_vblank_dram_clock_change_margin = v->v_blank_dram_clock_change_latency_margin[k]; } } if (v->synchronized_vblank == dcn_bw_yes || v->number_of_active_planes == 1) { - v->dram_clock_change_margin = dcn_bw_max2( - v->min_active_dram_clock_change_margin, - v->min_vblank_dram_clock_change_margin); - } else if (v->v_blank_of_min_active_dram_clock_change_margin - > v->min_active_dram_clock_change_margin) { - v->dram_clock_change_margin = dcn_bw_min2( - v->second_min_active_dram_clock_change_margin, - v->v_blank_of_min_active_dram_clock_change_margin); - } else { + v->dram_clock_change_margin =dcn_bw_max2(v->min_active_dram_clock_change_margin, v->min_vblank_dram_clock_change_margin); + } + else if (v->v_blank_of_min_active_dram_clock_change_margin > v->min_active_dram_clock_change_margin) { + v->dram_clock_change_margin =dcn_bw_min2(v->second_min_active_dram_clock_change_margin, v->v_blank_of_min_active_dram_clock_change_margin); + } + else { v->dram_clock_change_margin = v->min_active_dram_clock_change_margin; } if (v->min_active_dram_clock_change_margin > 0.0) { v->dram_clock_change_support = dcn_bw_supported_in_v_active; - } else if (v->dram_clock_change_margin > 0.0) { + } + else if (v->dram_clock_change_margin > 0.0) { v->dram_clock_change_support = dcn_bw_supported_in_v_blank; - } else { + } + else { v->dram_clock_change_support = dcn_bw_not_supported; } /*maximum bandwidth used*/ @@ -3616,13 +1878,10 @@ void dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performan v->wr_bandwidth = 0.0; for (k = 0; k <= v->number_of_active_planes - 1; k++) { if (v->output[k] == dcn_bw_writeback && v->output_format[k] == dcn_bw_444) { - v->wr_bandwidth = v->wr_bandwidth - + v->scaler_rec_out_width[k] - / (v->htotal[k] / v->pixel_clock[k]) * 4.0; - } else if (v->output[k] == dcn_bw_writeback) { - v->wr_bandwidth = v->wr_bandwidth - + v->scaler_rec_out_width[k] - / (v->htotal[k] / v->pixel_clock[k]) * 1.5; + v->wr_bandwidth = v->wr_bandwidth + v->scaler_rec_out_width[k] / (v->htotal[k] / v->pixel_clock[k]) * 4.0; + } + else if (v->output[k] == dcn_bw_writeback) { + v->wr_bandwidth = v->wr_bandwidth + v->scaler_rec_out_width[k] / (v->htotal[k] / v->pixel_clock[k]) * 1.5; } } v->max_used_bw = v->max_rd_bandwidth + v->wr_bandwidth; -- cgit From f0129a537b52da851abd26f8296f3ffd1e5dc424 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Wed, 21 Jun 2017 15:44:23 -0400 Subject: drm/amd/display: Refine globallock. Switch to wait_for_completion_interruptible_timeout wait since the lock is called from IOCTL context and can be interrupted by a signal. Global lock function might return EDEADLK or EINTR which is not an error and just singals to user mode to restart the call. Signed-off-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 35 +++++++++++++++------- 1 file changed, 24 insertions(+), 11 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 7e0e6b2f22f6..0b7786d11995 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2842,7 +2842,7 @@ static uint32_t remove_from_val_sets( * Grabs all modesetting locks to serialize against any blocking commits, * Waits for completion of all non blocking commits. */ -static void do_aquire_global_lock( +static int do_aquire_global_lock( struct drm_device *dev, struct drm_atomic_state *state) { @@ -2854,7 +2854,9 @@ static void do_aquire_global_lock( * ensure that when the framework release it the * extra locks we are locking here will get released to */ - drm_modeset_lock_all_ctx(dev, state->acquire_ctx); + ret = drm_modeset_lock_all_ctx(dev, state->acquire_ctx); + if (ret) + return ret; list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { spin_lock(&crtc->commit_lock); @@ -2870,15 +2872,20 @@ static void do_aquire_global_lock( /* Make sure all pending HW programming completed and * page flips done */ - ret = wait_for_completion_timeout(&commit->hw_done, - 10*HZ); - ret = wait_for_completion_timeout(&commit->flip_done, - 10*HZ); + ret = wait_for_completion_interruptible_timeout(&commit->hw_done, 10*HZ); + + if (ret > 0) + ret = wait_for_completion_interruptible_timeout( + &commit->flip_done, 10*HZ); + if (ret == 0) - DRM_ERROR("[CRTC:%d:%s] hw_done timed out\n", - crtc->base.id, crtc->name); + DRM_ERROR("[CRTC:%d:%s] cleanup_done or flip_done " + "timed out\n", crtc->base.id, crtc->name); + drm_crtc_commit_put(commit); } + + return ret < 0 ? ret : 0; } int amdgpu_dm_atomic_check(struct drm_device *dev, @@ -3145,7 +3152,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, * synchronization events. */ if (aquire_global_lock) - do_aquire_global_lock(dev, state); + ret = do_aquire_global_lock(dev, state); } @@ -3161,8 +3168,14 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, for (i = 0; i < new_stream_count; i++) dc_stream_release(new_streams[i]); - if (ret != 0) - DRM_ERROR("Atomic check failed.\n"); + if (ret != 0) { + if (ret == -EDEADLK) + DRM_DEBUG_KMS("Atomic check stopped due to to deadlock, retrying.\n"); + else if (ret == -EINTR || ret == -EAGAIN || ret == -ERESTARTSYS) + DRM_DEBUG_KMS("Atomic check stopped due to to signal, retrying.\n"); + else + DRM_ERROR("Atomic check failed.\n"); + } return ret; } -- cgit From afa80d64d20ac13528c261e1233ac3982609fd2f Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 21 Jun 2017 17:27:59 -0400 Subject: drm/amd/display: fix bw_calc_auto translation error The compiler was warning about conditions that will never evaluate to true. The problem was that the VBA translater didn't translate the conditions correctly. Signed-off-by: Dmytro Laktyushkin Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c index bb2f8ad6a988..fb5d8db33a82 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c @@ -128,7 +128,7 @@ void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v) v->source_format_pixel_and_scan_support = dcn_bw_yes; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - if ((v->source_surface_mode[k] == dcn_bw_sw_linear && !v->source_scan[k] == dcn_bw_hor) || ((v->source_surface_mode[k] == dcn_bw_sw_4_kb_d || v->source_surface_mode[k] == dcn_bw_sw_4_kb_d_x || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_t || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_x || v->source_surface_mode[k] == dcn_bw_sw_var_d || v->source_surface_mode[k] == dcn_bw_sw_var_d_x) && !v->source_pixel_format[k] == dcn_bw_rgb_sub_64)) { + if ((v->source_surface_mode[k] == dcn_bw_sw_linear && v->source_scan[k] != dcn_bw_hor) || ((v->source_surface_mode[k] == dcn_bw_sw_4_kb_d || v->source_surface_mode[k] == dcn_bw_sw_4_kb_d_x || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_t || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_x || v->source_surface_mode[k] == dcn_bw_sw_var_d || v->source_surface_mode[k] == dcn_bw_sw_var_d_x) && v->source_pixel_format[k] != dcn_bw_rgb_sub_64)) { v->source_format_pixel_and_scan_support = dcn_bw_no; } } -- cgit From 92f3ac403d132400b7147bb4262fea4ad254aa3d Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Fri, 16 Jun 2017 15:59:17 -0400 Subject: drm/amd/display: Workaround IGT multiplane restriction IGT currently does not properly commit changes on planes with multiple possible CRTC's. Set one valid CRTC for each plane for now, plus one underlay plane on Carizzo and Stoney that is valid for all CRTCs. Signed-off-by: Leo (Sunpeng) Li Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') 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 98e0dbe2a4de..f018de2e7dfe 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1189,6 +1189,7 @@ int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) struct amdgpu_encoder *aencoder = NULL; struct amdgpu_mode_info *mode_info = &adev->mode_info; uint32_t link_cnt; + unsigned long possible_crtcs; link_cnt = dm->dc->caps.max_links; if (amdgpu_dm_mode_config_init(dm->adev)) { @@ -1204,7 +1205,18 @@ int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) goto fail_free_planes; } mode_info->planes[i]->base.type = mode_info->plane_type[i]; - if (amdgpu_dm_plane_init(dm, mode_info->planes[i], 0xff)) { + + /* + * HACK: IGT tests expect that each plane can only have one + * one possible CRTC. For now, set one CRTC for each + * plane that is not an underlay, but still allow multiple + * CRTCs for underlay planes. + */ + possible_crtcs = 1 << i; + if (i >= dm->dc->caps.max_streams) + possible_crtcs = 0xff; + + if (amdgpu_dm_plane_init(dm, mode_info->planes[i], possible_crtcs)) { DRM_ERROR("KMS: Failed to initialize plane\n"); goto fail_free_planes; } -- cgit From 4c0732bf7f37f488a37111051ebca388135bf7b5 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Thu, 22 Jun 2017 11:45:13 -0400 Subject: drm/amd/display: Global lock typos fix. Fix typos. Signed-off-by: Andrey Grodzovsky Reviewed-by: Roman Li Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 0b7786d11995..6f08fab1cce7 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2879,7 +2879,7 @@ static int do_aquire_global_lock( &commit->flip_done, 10*HZ); if (ret == 0) - DRM_ERROR("[CRTC:%d:%s] cleanup_done or flip_done " + DRM_ERROR("[CRTC:%d:%s] hw_done or flip_done " "timed out\n", crtc->base.id, crtc->name); drm_crtc_commit_put(commit); @@ -3170,9 +3170,9 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, if (ret != 0) { if (ret == -EDEADLK) - DRM_DEBUG_KMS("Atomic check stopped due to to deadlock, retrying.\n"); + DRM_DEBUG_KMS("Atomic check stopped due to to deadlock.\n"); else if (ret == -EINTR || ret == -EAGAIN || ret == -ERESTARTSYS) - DRM_DEBUG_KMS("Atomic check stopped due to to signal, retrying.\n"); + DRM_DEBUG_KMS("Atomic check stopped due to to signal.\n"); else DRM_ERROR("Atomic check failed.\n"); } -- cgit From a95e7d737e1bc20eb311548f4e307e2155c5ca64 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Fri, 23 Jun 2017 13:56:55 -0400 Subject: drm/amd/display: Disable pipe split. Signed-off-by: Yongqiang Sun Reviewed-by: Hersen Wu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index c7840e0e3ae5..eebaffca8e75 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -443,7 +443,7 @@ static const struct dc_debug debug_defaults_drv = { .disable_pplib_wm_range = false, #if defined(CONFIG_DRM_AMD_DC_DCN1_0) .use_dml_wm = false, - .disable_pipe_split = false + .disable_pipe_split = true #endif }; -- cgit From 866294f80582e252913c72b5e0f1792f6133424d Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Wed, 21 Jun 2017 16:48:06 -0400 Subject: drm/amd/display: Don't program scaler if we have no surface If we don't have a surface in dc_commit_streams scl_data won't get populated in resource_build_scaling_params_for_context. In this case we shouldn't attempt to program the scaler. Signed-off-by: Harry Wentland Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index a83d260cda45..0bab85b27a85 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1099,10 +1099,12 @@ static enum dc_status apply_single_controller_ctx_to_hw( pipe_ctx->scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; /* program_scaler and allocate_mem_input are not new asic */ - if (!pipe_ctx_old || memcmp(&pipe_ctx_old->scl_data, - &pipe_ctx->scl_data, - sizeof(struct scaler_data)) != 0) + if ((!pipe_ctx_old || + memcmp(&pipe_ctx_old->scl_data, &pipe_ctx->scl_data, + sizeof(struct scaler_data)) != 0) && + pipe_ctx->surface) { program_scaler(dc, pipe_ctx); + } /* mst support - use total stream count */ #if defined(CONFIG_DRM_AMD_DC_DCN1_0) -- cgit From e5f2038ef12cf5606ec3d7c79e2539cafcb409dd Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Sat, 24 Jun 2017 16:01:37 -0400 Subject: drm/amd/display: w/a no color space info for HDMI when build AVI Signed-off-by: Charlene Liu Reviewed-by: Aric Cyr Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 90eb839f5414..f0183d5f0d0d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1605,6 +1605,9 @@ static void set_avi_info_frame( union hdmi_info_packet *hdmi_info = &info_frame.avi_info_packet.info_packet_hdmi; color_space = pipe_ctx->stream->public.output_color_space; + if (color_space == COLOR_SPACE_UNKNOWN) + color_space = (stream->public.timing.pixel_encoding == PIXEL_ENCODING_RGB)? + COLOR_SPACE_SRGB:COLOR_SPACE_YCBCR709; /* Initialize header */ hdmi_info->bits.header.info_frame_type = HDMI_INFOFRAME_TYPE_AVI; -- cgit From 2782488ae6c0b53d57435aa6dc358e61550393d2 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Tue, 27 Jun 2017 10:02:48 -0400 Subject: drm/amd/display: Clean up unused function. Signed-off-by: Andrey Grodzovsky Reviewed-by: Leo Li Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index 190905e08c38..2d34f9bb5d47 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -450,12 +450,6 @@ struct dm_plane_state { struct dc_surface* dc_surface; }; -static inline struct dm_plane_state * -to_amdgpu_plane_state(struct drm_plane_state *state) -{ - return container_of(state, struct dm_plane_state, base); -} - struct amdgpu_plane { struct drm_plane base; enum drm_plane_type plane_type; -- cgit From cf5a4c11a1561db5c31a2783611aa6d5dbb67225 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Wed, 28 Jun 2017 11:03:11 -0400 Subject: drm/amd/display: Move dm_plane_state definition to DAL header. Signed-off-by: Andrey Grodzovsky Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 8 -------- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h | 6 ++++++ 2 files changed, 6 insertions(+), 8 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index 2d34f9bb5d47..2bb2fc2a6566 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -442,14 +442,6 @@ struct amdgpu_crtc { struct drm_pending_vblank_event *event; }; -/* TODO rename to dc_plane_state */ -struct dc_surface; - -struct dm_plane_state { - struct drm_plane_state base; - struct dc_surface* dc_surface; -}; - struct amdgpu_plane { struct drm_plane base; enum drm_plane_type plane_type; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h index b69c86826b1a..6411dd1819dd 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h @@ -33,6 +33,12 @@ struct amdgpu_display_manager; struct dc_validation_set; struct dc_surface; +struct dm_plane_state { + struct drm_plane_state base; + struct dc_surface *dc_surface; +}; + + /*TODO Jodan Hersen use the one in amdgpu_dm*/ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, struct amdgpu_plane *aplane, -- cgit From d7ec53d9dd0086644aa97d22463976b04b51307e Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Tue, 4 Jul 2017 13:28:57 -0400 Subject: drm/amd/display: Move kms_atomic support flag to dm_early_init. Signed-off-by: Andrey Grodzovsky Reviewed-by: Jordan Lazare Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 4 ---- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 1 + 2 files changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index a350fc9b2a70..2368792b7d67 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2071,10 +2071,6 @@ int amdgpu_device_init(struct amdgpu_device *adev, adev->audio_endpt_rreg = &amdgpu_block_invalid_rreg; adev->audio_endpt_wreg = &amdgpu_block_invalid_wreg; - if (amdgpu_device_has_dc_support(adev)) - adev->ddev->driver->driver_features |= DRIVER_ATOMIC; - - DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X 0x%04X:0x%04X 0x%02X).\n", amdgpu_asic_name[adev->asic_type], pdev->vendor, pdev->device, pdev->subsystem_vendor, pdev->subsystem_device, pdev->revision); 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 f018de2e7dfe..8062f8c18114 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1421,6 +1421,7 @@ static int dm_early_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; + adev->ddev->driver->driver_features |= DRIVER_ATOMIC; amdgpu_dm_set_irq_funcs(adev); switch (adev->asic_type) { -- cgit From a67297d4c8d0bfac39a0fa166e98dcf54db1d7c2 Mon Sep 17 00:00:00 2001 From: Xiaojie Yuan Date: Tue, 4 Jul 2017 14:21:58 +0800 Subject: drm/amd/display: Fix misuse of plane state destroy helper drm_plane_state is subclassed by dm_plane_state, so atomic driver should use __drm_atomic_helper_plane_destroy_state() to destroy a state. drm_atomic_helper_plane_destroy_state() frees drm_plane_state which is allocated inside dm_plane_state, this is problematic. Fixes: 95ae03a ("drm/amd/display: Create dm_plane_state.") Signed-off-by: Xiaojie Yuan Reviewed-by: Andrey Grodzovsky Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 6f08fab1cce7..64cb635b4137 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -1431,7 +1431,8 @@ void dm_drm_plane_destroy_state(struct drm_plane *plane, dc_surface_release(dc_surface); } - drm_atomic_helper_plane_destroy_state(plane, state); + __drm_atomic_helper_plane_destroy_state(state); + kfree(dm_plane_state); } static const struct drm_plane_funcs dm_plane_funcs = { -- cgit From 061d34994597284b4228b7468762772fbdbcfa4c Mon Sep 17 00:00:00 2001 From: Ken Chalmers Date: Mon, 26 Jun 2017 13:02:30 -0400 Subject: drm/amd/display: RV stereo support Fix moving directly from frame packed to frame sequential mode: disable OTG_3D_STRUCTURE_EN if the stereo mode is not frame packed. Signed-off-by: Ken Chalmers Reviewed-by: Vitaly Prosyak Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c index 83efbec77357..58fb29ff5677 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c @@ -1082,11 +1082,11 @@ static void dcn10_enable_stereo(struct timing_generator *tg, REG_UPDATE(OTG_STEREO_CONTROL, OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP, 1); - if (flags->PROGRAM_STEREO && flags->FRAME_PACKED) + if (flags->PROGRAM_STEREO) REG_UPDATE_3(OTG_3D_STRUCTURE_CONTROL, - OTG_3D_STRUCTURE_EN, 1, - OTG_3D_STRUCTURE_V_UPDATE_MODE, 1, - OTG_3D_STRUCTURE_STEREO_SEL_OVR, 1); + OTG_3D_STRUCTURE_EN, flags->FRAME_PACKED, + OTG_3D_STRUCTURE_V_UPDATE_MODE, flags->FRAME_PACKED, + OTG_3D_STRUCTURE_STEREO_SEL_OVR, flags->FRAME_PACKED); } -- cgit From e29088b2932a11db6155212ca19c75029bc137aa Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Tue, 25 Jul 2017 18:00:44 -0400 Subject: drm/amd/display: Move drm_get_vblank from legacy code Previously, we assumed that allow_modeset=false => page flip. This assumption breaks when an atomic commit is submitted with allow_modeset set to false, since the legacy flip code is never called (the legacy code grabs the vblank reference). Fix: Move drm_vblank_get() from amdgpu_atomic_helper_page_flip() to amdgpu_dm_commit_surfaces(). Signed-off-by: Leo (Sunpeng) Li Reviewed-by: Andrey Grodzovsky Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 64cb635b4137..0978fe3e5663 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2383,8 +2383,6 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, if (!con_state) continue; - - add_surface(dm->dc, crtc, plane, &dc_surfaces_constructed[planes_count]); if (dc_surfaces_constructed[planes_count] == NULL) { @@ -2403,6 +2401,10 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, acrtc_attach->flip_flags & DRM_MODE_PAGE_FLIP_ASYNC ? false : true; + /* TODO: Needs rework for multiplane flip */ + if (plane->type == DRM_PLANE_TYPE_PRIMARY) + drm_crtc_vblank_get(crtc); + amdgpu_dm_do_flip( crtc, fb, -- cgit From b3663f705a522b7807a1916c94a24448c6a40abc Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 27 Jun 2017 11:12:37 -0400 Subject: drm/amd/display: Make mode_config_funcs const Signed-off-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/gpu') 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 8062f8c18114..353165c6da1e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -634,8 +634,7 @@ const struct amdgpu_ip_block_version dm_ip_block = .funcs = &amdgpu_dm_funcs, }; -/* TODO: it is temporary non-const, should fixed later */ -static struct drm_mode_config_funcs amdgpu_dm_mode_funcs = { +static const struct drm_mode_config_funcs amdgpu_dm_mode_funcs = { .fb_create = amdgpu_user_framebuffer_create, .output_poll_changed = amdgpu_output_poll_changed, .atomic_check = amdgpu_dm_atomic_check, -- cgit From ba6bf832b25ca7369ed3d4c0b0651bb43c9e644a Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Tue, 27 Jun 2017 17:24:00 -0400 Subject: drm/amd/display: Create dm_crtc_state stubs. These stubs are initial only since we need to flatten DC objects (steran at least) to implement deep copy. Signed-off-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 74 +++++++++++++++++++++- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.h | 10 +++ 2 files changed, 81 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 0978fe3e5663..3711176bd070 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -960,15 +960,83 @@ void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc) kfree(crtc); } +static void dm_crtc_destroy_state(struct drm_crtc *crtc, + struct drm_crtc_state *state) +{ + struct dm_crtc_state *cur = to_dm_crtc_state(state); + + if (cur->dc_stream) { + /* TODO Destroy dc_stream objects are stream object is flattened */ + dm_free(cur->dc_stream); + } else + WARN_ON(1); + + __drm_atomic_helper_crtc_destroy_state(state); + + + kfree(state); +} + +static void dm_crtc_reset_state(struct drm_crtc *crtc) +{ + struct dm_crtc_state *state; + + if (crtc->state) + dm_crtc_destroy_state(crtc, crtc->state); + + state = kzalloc(sizeof(*state), GFP_KERNEL); + if (WARN_ON(!state)) + return; + + + crtc->state = &state->base; + crtc->state->crtc = crtc; + + state->dc_stream = dm_alloc(sizeof(*state->dc_stream)); + WARN_ON(!state->dc_stream); +} + +static struct drm_crtc_state * +dm_crtc_duplicate_state(struct drm_crtc *crtc) +{ + struct dm_crtc_state *state, *cur; + struct dc_stream *dc_stream; + + if (WARN_ON(!crtc->state)) + return NULL; + + cur = to_dm_crtc_state(crtc->state); + if (WARN_ON(!cur->dc_stream)) + return NULL; + + dc_stream = dm_alloc(sizeof(*dc_stream)); + if (WARN_ON(!dc_stream)) + return NULL; + + state = dm_alloc(sizeof(*state)); + if (WARN_ON(!state)) { + dm_free(dc_stream); + return NULL; + } + + __drm_atomic_helper_crtc_duplicate_state(crtc, &state->base); + + state->dc_stream = dc_stream; + + /* TODO Duplicate dc_stream after objects are stream object is flattened */ + + return &state->base; +} + /* Implemented only the options currently availible for the driver */ static const struct drm_crtc_funcs amdgpu_dm_crtc_funcs = { - .reset = drm_atomic_helper_crtc_reset, + .reset = dm_crtc_reset_state, .destroy = amdgpu_dm_crtc_destroy, .gamma_set = drm_atomic_helper_legacy_gamma_set, .set_config = drm_atomic_helper_set_config, .page_flip = drm_atomic_helper_page_flip, - .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, - .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, + .atomic_duplicate_state = dm_crtc_duplicate_state, + .atomic_destroy_state = dm_crtc_destroy_state, }; static enum drm_connector_status diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h index 6411dd1819dd..109172576499 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h @@ -32,6 +32,16 @@ struct amdgpu_framebuffer; struct amdgpu_display_manager; struct dc_validation_set; struct dc_surface; +/* TODO rename to dc_stream_state */ +struct dc_stream; + + +struct dm_crtc_state { + struct drm_crtc_state base; + struct dc_stream *dc_stream; +}; + +#define to_dm_crtc_state(x) container_of(x, struct dm_crtc_state, base) struct dm_plane_state { struct drm_plane_state base; -- cgit From f71f2772cb001d087e260c96f46d1fde022d2e03 Mon Sep 17 00:00:00 2001 From: Corbin McElhanney Date: Mon, 26 Jun 2017 16:47:27 -0400 Subject: drm/amd/display: Add clock info struct Signed-off-by: Corbin McElhanney Reviewed-by: Logatharshan Thothiralingam Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dm_services_types.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dm_services_types.h b/drivers/gpu/drm/amd/display/dc/dm_services_types.h index b28304531d8a..4c04ec587308 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services_types.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services_types.h @@ -271,4 +271,10 @@ struct dm_pp_static_clock_info { enum dm_pp_clocks_state max_clocks_state; }; +struct dtn_min_clk_info { + uint32_t disp_clk_khz; + uint32_t min_engine_clock_khz; + uint32_t min_memory_clock_khz; +}; + #endif -- cgit From 7f524a0d838d8d9334003b956b73729f27a1315a Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Fri, 23 Jun 2017 13:35:53 -0400 Subject: drm/amd/display: remove unneeded FBC hw programming code - Removed uneeded FBC code. - Initial placeholder for FBC implementation on stoney/carrizo Signed-off-by: Bhawanpreet Lakha Reviewed-by: Roman Li Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dce110/dce110_compressor.c | 534 ++++----------------- .../drm/amd/display/dc/dce110/dce110_compressor.h | 3 + drivers/gpu/drm/amd/display/dc/inc/compressor.h | 46 +- 3 files changed, 137 insertions(+), 446 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c index 518150a414e2..5fe83045d1a6 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c @@ -94,199 +94,8 @@ enum fbc_idle_force { FBC_IDLE_FORCE_CG_STATIC_SCREEN_IS_INACTIVE = 0x20000000, }; -static uint32_t lpt_size_alignment(struct dce110_compressor *cp110) -{ - /*LPT_ALIGNMENT (in bytes) = ROW_SIZE * #BANKS * # DRAM CHANNELS. */ - return cp110->base.raw_size * cp110->base.banks_num * - cp110->base.dram_channels_num; -} - -static uint32_t lpt_memory_control_config(struct dce110_compressor *cp110, - uint32_t lpt_control) -{ - /*LPT MC Config */ - if (cp110->base.options.bits.LPT_MC_CONFIG == 1) { - /* POSSIBLE VALUES for LPT NUM_PIPES (DRAM CHANNELS): - * 00 - 1 CHANNEL - * 01 - 2 CHANNELS - * 02 - 4 OR 6 CHANNELS - * (Only for discrete GPU, N/A for CZ) - * 03 - 8 OR 12 CHANNELS - * (Only for discrete GPU, N/A for CZ) */ - switch (cp110->base.dram_channels_num) { - case 2: - set_reg_field_value( - lpt_control, - 1, - LOW_POWER_TILING_CONTROL, - LOW_POWER_TILING_NUM_PIPES); - break; - case 1: - set_reg_field_value( - lpt_control, - 0, - LOW_POWER_TILING_CONTROL, - LOW_POWER_TILING_NUM_PIPES); - break; - default: - dm_logger_write( - cp110->base.ctx->logger, LOG_WARNING, - "%s: Invalid LPT NUM_PIPES!!!", - __func__); - break; - } - - /* The mapping for LPT NUM_BANKS is in - * GRPH_CONTROL.GRPH_NUM_BANKS register field - * Specifies the number of memory banks for tiling - * purposes. Only applies to 2D and 3D tiling modes. - * POSSIBLE VALUES: - * 00 - DCP_GRPH_NUM_BANKS_2BANK: ADDR_SURF_2_BANK - * 01 - DCP_GRPH_NUM_BANKS_4BANK: ADDR_SURF_4_BANK - * 02 - DCP_GRPH_NUM_BANKS_8BANK: ADDR_SURF_8_BANK - * 03 - DCP_GRPH_NUM_BANKS_16BANK: ADDR_SURF_16_BANK */ - switch (cp110->base.banks_num) { - case 16: - set_reg_field_value( - lpt_control, - 3, - LOW_POWER_TILING_CONTROL, - LOW_POWER_TILING_NUM_BANKS); - break; - case 8: - set_reg_field_value( - lpt_control, - 2, - LOW_POWER_TILING_CONTROL, - LOW_POWER_TILING_NUM_BANKS); - break; - case 4: - set_reg_field_value( - lpt_control, - 1, - LOW_POWER_TILING_CONTROL, - LOW_POWER_TILING_NUM_BANKS); - break; - case 2: - set_reg_field_value( - lpt_control, - 0, - LOW_POWER_TILING_CONTROL, - LOW_POWER_TILING_NUM_BANKS); - break; - default: - dm_logger_write( - cp110->base.ctx->logger, LOG_WARNING, - "%s: Invalid LPT NUM_BANKS!!!", - __func__); - break; - } - - /* The mapping is in DMIF_ADDR_CALC. - * ADDR_CONFIG_PIPE_INTERLEAVE_SIZE register field for - * Carrizo specifies the memory interleave per pipe. - * It effectively specifies the location of pipe bits in - * the memory address. - * POSSIBLE VALUES: - * 00 - ADDR_CONFIG_PIPE_INTERLEAVE_256B: 256 byte - * interleave - * 01 - ADDR_CONFIG_PIPE_INTERLEAVE_512B: 512 byte - * interleave - */ - switch (cp110->base.channel_interleave_size) { - case 256: /*256B */ - set_reg_field_value( - lpt_control, - 0, - LOW_POWER_TILING_CONTROL, - LOW_POWER_TILING_PIPE_INTERLEAVE_SIZE); - break; - case 512: /*512B */ - set_reg_field_value( - lpt_control, - 1, - LOW_POWER_TILING_CONTROL, - LOW_POWER_TILING_PIPE_INTERLEAVE_SIZE); - break; - default: - dm_logger_write( - cp110->base.ctx->logger, LOG_WARNING, - "%s: Invalid LPT INTERLEAVE_SIZE!!!", - __func__); - break; - } - /* The mapping for LOW_POWER_TILING_ROW_SIZE is in - * DMIF_ADDR_CALC.ADDR_CONFIG_ROW_SIZE register field - * for Carrizo. Specifies the size of dram row in bytes. - * This should match up with NOOFCOLS field in - * MC_ARB_RAMCFG (ROW_SIZE = 4 * 2 ^^ columns). - * This register DMIF_ADDR_CALC is not used by the - * hardware as it is only used for addrlib assertions. - * POSSIBLE VALUES: - * 00 - ADDR_CONFIG_1KB_ROW: Treat 1KB as DRAM row - * boundary - * 01 - ADDR_CONFIG_2KB_ROW: Treat 2KB as DRAM row - * boundary - * 02 - ADDR_CONFIG_4KB_ROW: Treat 4KB as DRAM row - * boundary */ - switch (cp110->base.raw_size) { - case 4096: /*4 KB */ - set_reg_field_value( - lpt_control, - 2, - LOW_POWER_TILING_CONTROL, - LOW_POWER_TILING_ROW_SIZE); - break; - case 2048: - set_reg_field_value( - lpt_control, - 1, - LOW_POWER_TILING_CONTROL, - LOW_POWER_TILING_ROW_SIZE); - break; - case 1024: - set_reg_field_value( - lpt_control, - 0, - LOW_POWER_TILING_CONTROL, - LOW_POWER_TILING_ROW_SIZE); - break; - default: - dm_logger_write( - cp110->base.ctx->logger, LOG_WARNING, - "%s: Invalid LPT ROW_SIZE!!!", - __func__); - break; - } - } else { - dm_logger_write( - cp110->base.ctx->logger, LOG_WARNING, - "%s: LPT MC Configuration is not provided", - __func__); - } - - return lpt_control; -} - -static bool is_source_bigger_than_epanel_size( - struct dce110_compressor *cp110, - uint32_t source_view_width, - uint32_t source_view_height) -{ - if (cp110->base.embedded_panel_h_size != 0 && - cp110->base.embedded_panel_v_size != 0 && - ((source_view_width * source_view_height) > - (cp110->base.embedded_panel_h_size * - cp110->base.embedded_panel_v_size))) - return true; - - return false; -} - -static uint32_t align_to_chunks_number_per_line( - struct dce110_compressor *cp110, - uint32_t pixels) +static uint32_t align_to_chunks_number_per_line(uint32_t pixels) { return 256 * ((pixels + 255) / 256); } @@ -372,25 +181,11 @@ void dce110_compressor_enable_fbc( struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor); if (compressor->options.bits.FBC_SUPPORT && - (compressor->options.bits.DUMMY_BACKEND == 0) && - (!dce110_compressor_is_fbc_enabled_in_hw(compressor, NULL)) && - (!is_source_bigger_than_epanel_size( - cp110, - params->source_view_width, - params->source_view_height))) { + (!dce110_compressor_is_fbc_enabled_in_hw(compressor, NULL))) { uint32_t addr; uint32_t value; - /* Before enabling FBC first need to enable LPT if applicable - * LPT state should always be changed (enable/disable) while FBC - * is disabled */ - if (compressor->options.bits.LPT_SUPPORT && (paths_num < 2) && - (params->source_view_width * - params->source_view_height <= - dce11_one_lpt_channel_max_resolution)) { - dce110_compressor_enable_lpt(compressor); - } addr = mmFBC_CNTL; value = dm_read_reg(compressor->ctx, addr); @@ -432,11 +227,6 @@ void dce110_compressor_disable_fbc(struct compressor *compressor) compressor->attached_inst = 0; compressor->is_enabled = false; - /* Whenever disabling FBC make sure LPT is disabled if LPT - * supported */ - if (compressor->options.bits.LPT_SUPPORT) - dce110_compressor_disable_lpt(compressor); - wait_for_fbc_state_changed(cp110, false); } } @@ -469,17 +259,6 @@ bool dce110_compressor_is_fbc_enabled_in_hw( return false; } -bool dce110_compressor_is_lpt_enabled_in_hw(struct compressor *compressor) -{ - /* Check the hardware register */ - uint32_t value = dm_read_reg(compressor->ctx, - mmLOW_POWER_TILING_CONTROL); - - return get_reg_field_value( - value, - LOW_POWER_TILING_CONTROL, - LOW_POWER_TILING_ENABLE); -} void dce110_compressor_program_compressed_surface_address_and_pitch( struct compressor *compressor, @@ -499,17 +278,6 @@ void dce110_compressor_program_compressed_surface_address_and_pitch( dm_write_reg(compressor->ctx, DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS), 0); - if (compressor->options.bits.LPT_SUPPORT) { - uint32_t lpt_alignment = lpt_size_alignment(cp110); - - if (lpt_alignment != 0) { - compressed_surf_address_low_part = - ((compressed_surf_address_low_part - + (lpt_alignment - 1)) / lpt_alignment) - * lpt_alignment; - } - } - /* Write address, HIGH has to be first. */ dm_write_reg(compressor->ctx, DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS_HIGH), @@ -518,9 +286,7 @@ void dce110_compressor_program_compressed_surface_address_and_pitch( DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS), compressed_surf_address_low_part); - fbc_pitch = align_to_chunks_number_per_line( - cp110, - params->source_view_width); + fbc_pitch = align_to_chunks_number_per_line(params->source_view_width); if (compressor->min_compress_ratio == FBC_COMPRESS_RATIO_1TO1) fbc_pitch = fbc_pitch / 8; @@ -543,197 +309,6 @@ void dce110_compressor_program_compressed_surface_address_and_pitch( } -void dce110_compressor_disable_lpt(struct compressor *compressor) -{ - struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor); - uint32_t value; - uint32_t addr; - uint32_t inx; - - /* Disable all pipes LPT Stutter */ - for (inx = 0; inx < 3; inx++) { - value = - dm_read_reg( - compressor->ctx, - DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH)); - set_reg_field_value( - value, - 0, - DPG_PIPE_STUTTER_CONTROL_NONLPTCH, - STUTTER_ENABLE_NONLPTCH); - dm_write_reg( - compressor->ctx, - DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH), - value); - } - /* Disable Underlay pipe LPT Stutter */ - addr = mmDPGV0_PIPE_STUTTER_CONTROL_NONLPTCH; - value = dm_read_reg(compressor->ctx, addr); - set_reg_field_value( - value, - 0, - DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH, - STUTTER_ENABLE_NONLPTCH); - dm_write_reg(compressor->ctx, addr, value); - - /* Disable LPT */ - addr = mmLOW_POWER_TILING_CONTROL; - value = dm_read_reg(compressor->ctx, addr); - set_reg_field_value( - value, - 0, - LOW_POWER_TILING_CONTROL, - LOW_POWER_TILING_ENABLE); - dm_write_reg(compressor->ctx, addr, value); - - /* Clear selection of Channel(s) containing Compressed Surface */ - addr = mmGMCON_LPT_TARGET; - value = dm_read_reg(compressor->ctx, addr); - set_reg_field_value( - value, - 0xFFFFFFFF, - GMCON_LPT_TARGET, - STCTRL_LPT_TARGET); - dm_write_reg(compressor->ctx, mmGMCON_LPT_TARGET, value); -} - -void dce110_compressor_enable_lpt(struct compressor *compressor) -{ - struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor); - uint32_t value; - uint32_t addr; - uint32_t value_control; - uint32_t channels; - - /* Enable LPT Stutter from Display pipe */ - value = dm_read_reg(compressor->ctx, - DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH)); - set_reg_field_value( - value, - 1, - DPG_PIPE_STUTTER_CONTROL_NONLPTCH, - STUTTER_ENABLE_NONLPTCH); - dm_write_reg(compressor->ctx, - DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH), value); - - /* Enable Underlay pipe LPT Stutter */ - addr = mmDPGV0_PIPE_STUTTER_CONTROL_NONLPTCH; - value = dm_read_reg(compressor->ctx, addr); - set_reg_field_value( - value, - 1, - DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH, - STUTTER_ENABLE_NONLPTCH); - dm_write_reg(compressor->ctx, addr, value); - - /* Selection of Channel(s) containing Compressed Surface: 0xfffffff - * will disable LPT. - * STCTRL_LPT_TARGETn corresponds to channel n. */ - addr = mmLOW_POWER_TILING_CONTROL; - value_control = dm_read_reg(compressor->ctx, addr); - channels = get_reg_field_value(value_control, - LOW_POWER_TILING_CONTROL, - LOW_POWER_TILING_MODE); - - addr = mmGMCON_LPT_TARGET; - value = dm_read_reg(compressor->ctx, addr); - set_reg_field_value( - value, - channels + 1, /* not mentioned in programming guide, - but follow DCE8.1 */ - GMCON_LPT_TARGET, - STCTRL_LPT_TARGET); - dm_write_reg(compressor->ctx, addr, value); - - /* Enable LPT */ - addr = mmLOW_POWER_TILING_CONTROL; - value = dm_read_reg(compressor->ctx, addr); - set_reg_field_value( - value, - 1, - LOW_POWER_TILING_CONTROL, - LOW_POWER_TILING_ENABLE); - dm_write_reg(compressor->ctx, addr, value); -} - -void dce110_compressor_program_lpt_control( - struct compressor *compressor, - struct compr_addr_and_pitch_params *params) -{ - struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor); - uint32_t rows_per_channel; - uint32_t lpt_alignment; - uint32_t source_view_width; - uint32_t source_view_height; - uint32_t lpt_control = 0; - - if (!compressor->options.bits.LPT_SUPPORT) - return; - - lpt_control = dm_read_reg(compressor->ctx, - mmLOW_POWER_TILING_CONTROL); - - /* POSSIBLE VALUES for Low Power Tiling Mode: - * 00 - Use channel 0 - * 01 - Use Channel 0 and 1 - * 02 - Use Channel 0,1,2,3 - * 03 - reserved */ - switch (compressor->lpt_channels_num) { - /* case 2: - * Use Channel 0 & 1 / Not used for DCE 11 */ - case 1: - /*Use Channel 0 for LPT for DCE 11 */ - set_reg_field_value( - lpt_control, - 0, - LOW_POWER_TILING_CONTROL, - LOW_POWER_TILING_MODE); - break; - default: - dm_logger_write( - compressor->ctx->logger, LOG_WARNING, - "%s: Invalid selected DRAM channels for LPT!!!", - __func__); - break; - } - - lpt_control = lpt_memory_control_config(cp110, lpt_control); - - /* Program LOW_POWER_TILING_ROWS_PER_CHAN field which depends on - * FBC compressed surface pitch. - * LOW_POWER_TILING_ROWS_PER_CHAN = Roundup ((Surface Height * - * Surface Pitch) / (Row Size * Number of Channels * - * Number of Banks)). */ - rows_per_channel = 0; - lpt_alignment = lpt_size_alignment(cp110); - source_view_width = - align_to_chunks_number_per_line( - cp110, - params->source_view_width); - source_view_height = (params->source_view_height + 1) & (~0x1); - - if (lpt_alignment != 0) { - rows_per_channel = source_view_width * source_view_height * 4; - rows_per_channel = - (rows_per_channel % lpt_alignment) ? - (rows_per_channel / lpt_alignment + 1) : - rows_per_channel / lpt_alignment; - } - - set_reg_field_value( - lpt_control, - rows_per_channel, - LOW_POWER_TILING_CONTROL, - LOW_POWER_TILING_ROWS_PER_CHAN); - - dm_write_reg(compressor->ctx, - mmLOW_POWER_TILING_CONTROL, lpt_control); -} - -/* - * DCE 11 Frame Buffer Compression Implementation - */ - void dce110_compressor_set_fbc_invalidation_triggers( struct compressor *compressor, uint32_t fbc_trigger) @@ -792,21 +367,20 @@ void dce110_compressor_set_fbc_invalidation_triggers( } bool dce110_compressor_construct(struct dce110_compressor *compressor, - struct dc_context *ctx) + struct dc_context *ctx) { - struct dc_bios *bp = ctx->dc_bios; - struct embedded_panel_info panel_info; compressor->base.options.bits.FBC_SUPPORT = true; - compressor->base.options.bits.LPT_SUPPORT = true; - /* For DCE 11 always use one DRAM channel for LPT */ + + /* for dce 11 always use one dram channel for lpt */ compressor->base.lpt_channels_num = 1; compressor->base.options.bits.DUMMY_BACKEND = false; - /* Check if this system has more than 1 DRAM channel; if only 1 then LPT - * should not be supported */ - if (compressor->base.memory_bus_width == 64) - compressor->base.options.bits.LPT_SUPPORT = false; + /* + * check if this system has more than 1 dram channel; if only 1 then lpt + * should not be supported + */ + compressor->base.options.bits.CLK_GATING_DISABLED = false; @@ -826,13 +400,6 @@ bool dce110_compressor_construct(struct dce110_compressor *compressor, compressor->base.attached_inst = 0; compressor->base.is_enabled = false; - if (BP_RESULT_OK == - bp->funcs->get_embedded_panel_info(bp, &panel_info)) { - compressor->base.embedded_panel_h_size = - panel_info.lcd_timing.horizontal_addressable; - compressor->base.embedded_panel_v_size = - panel_info.lcd_timing.vertical_addressable; - } return true; } @@ -857,3 +424,82 @@ void dce110_compressor_destroy(struct compressor **compressor) dm_free(TO_DCE110_COMPRESSOR(*compressor)); *compressor = NULL; } + +bool dce110_get_required_compressed_surfacesize(struct fbc_input_info fbc_input_info, + struct fbc_requested_compressed_size size) +{ + bool result = false; + + unsigned int max_x = FBC_MAX_X, max_y = FBC_MAX_Y; + + get_max_support_fbc_buffersize(&max_x, &max_y); + + if (fbc_input_info.dynamic_fbc_buffer_alloc == 0) { + /* + * For DCE11 here use Max HW supported size: HW Support up to 3840x2400 resolution + * or 18000 chunks. + */ + size.preferred_size = size.min_size = align_to_chunks_number_per_line(max_x) * max_y * 4; /* (For FBC when LPT not supported). */ + size.preferred_size_alignment = size.min_size_alignment = 0x100; /* For FBC when LPT not supported */ + size.bits.preferred_must_be_framebuffer_pool = 1; + size.bits.min_must_be_framebuffer_pool = 1; + + result = true; + } + /* + * Maybe to add registry key support with optional size here to override above + * for debugging purposes + */ + + return result; +} + + +void get_max_support_fbc_buffersize(unsigned int *max_x, unsigned int *max_y) +{ + *max_x = FBC_MAX_X; + *max_y = FBC_MAX_Y; + + /* if (m_smallLocalFrameBufferMemory == 1) + * { + * *max_x = FBC_MAX_X_SG; + * *max_y = FBC_MAX_Y_SG; + * } + */ +} + + +unsigned int controller_id_to_index(enum controller_id controller_id) +{ + unsigned int index = 0; + + switch (controller_id) { + case CONTROLLER_ID_D0: + index = 0; + break; + case CONTROLLER_ID_D1: + index = 1; + break; + case CONTROLLER_ID_D2: + index = 2; + break; + case CONTROLLER_ID_D3: + index = 3; + break; + default: + break; + } + return index; +} + + +static const struct compressor_funcs dce110_compressor_funcs = { + .power_up_fbc = dce110_compressor_power_up_fbc, + .enable_fbc = dce110_compressor_enable_fbc, + .disable_fbc = dce110_compressor_disable_fbc, + .set_fbc_invalidation_triggers = dce110_compressor_set_fbc_invalidation_triggers, + .surface_address_and_pitch = dce110_compressor_program_compressed_surface_address_and_pitch, + .is_fbc_enabled_in_hw = dce110_compressor_is_fbc_enabled_in_hw +}; + + diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.h index 22af5be51581..ff21c86df828 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.h @@ -75,4 +75,7 @@ void dce110_compressor_program_lpt_control(struct compressor *cp, bool dce110_compressor_is_lpt_enabled_in_hw(struct compressor *cp); +void get_max_support_fbc_buffersize(unsigned int *max_x, unsigned int *max_y); + #endif + diff --git a/drivers/gpu/drm/amd/display/dc/inc/compressor.h b/drivers/gpu/drm/amd/display/dc/inc/compressor.h index af292596b101..5fdc2fc10231 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/compressor.h +++ b/drivers/gpu/drm/amd/display/dc/inc/compressor.h @@ -45,6 +45,7 @@ union fbc_physical_address { }; struct compr_addr_and_pitch_params { + enum controller_id controller_id; uint32_t inst; uint32_t source_view_width; uint32_t source_view_height; @@ -52,14 +53,32 @@ struct compr_addr_and_pitch_params { enum fbc_hw_max_resolution_supported { FBC_MAX_X = 3840, - FBC_MAX_Y = 2400 + FBC_MAX_Y = 2400, + FBC_MAX_X_SG = 1920, + FBC_MAX_Y_SG = 1080, }; +struct compressor; + +struct compressor_funcs { + + void (*power_up_fbc)(struct compressor *cp); + void (*enable_fbc)(struct compressor *cp, uint32_t paths_num, + struct compr_addr_and_pitch_params *params); + void (*disable_fbc)(struct compressor *cp); + void (*set_fbc_invalidation_triggers)(struct compressor *cp, + uint32_t fbc_trigger); + void (*surface_address_and_pitch)( + struct compressor *cp, + struct compr_addr_and_pitch_params *params); + bool (*is_fbc_enabled_in_hw)(struct compressor *cp, + uint32_t *fbc_mapped_crtc_id); +}; struct compressor { struct dc_context *ctx; uint32_t attached_inst; bool is_enabled; - + const struct compressor_funcs funcs; union { uint32_t raw; struct { @@ -90,4 +109,27 @@ struct compressor { enum fbc_compress_ratio min_compress_ratio; }; +struct fbc_input_info { + bool dynamic_fbc_buffer_alloc; + unsigned int source_view_width; + unsigned int source_view_height; + unsigned int num_of_active_targets; +}; + + +struct fbc_requested_compressed_size { + unsigned int preferred_size; + unsigned int preferred_size_alignment; + unsigned int min_size; + unsigned int min_size_alignment; + union { + struct { + /* Above preferedSize must be allocated in FB pool */ + unsigned int preferred_must_be_framebuffer_pool : 1; + /* Above minSize must be allocated in FB pool */ + unsigned int min_must_be_framebuffer_pool : 1; + } bits; + unsigned int flags; + }; +}; #endif -- cgit From cfe4645e17f8dbe680c35c439d000313f2648482 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 14 Jun 2017 18:58:04 -0400 Subject: drm/amd/display: fix dcn pipe reset sequence This change fixes dcn10 front end reset sequence. Previously we would reset front end during flip which led to issues in certain MPO and 4k/5k scenarios. We would also never properly power gate our front end. Signed-off-by: Dmytro Laktyushkin Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 2 +- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 19 +- drivers/gpu/drm/amd/display/dc/core/dc.c | 22 +- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 7 + drivers/gpu/drm/amd/display/dc/dc.h | 3 - .../amd/display/dc/dce110/dce110_hw_sequencer.c | 17 +- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 226 ++++++++++----------- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c | 17 +- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h | 4 +- .../amd/display/dc/dcn10/dcn10_timing_generator.c | 6 +- .../amd/display/dc/dcn10/dcn10_timing_generator.h | 4 + drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h | 1 + drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 2 +- 13 files changed, 155 insertions(+), 175 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 3711176bd070..a6f27ceaf4af 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2380,7 +2380,7 @@ static void amdgpu_dm_do_flip( surface_updates->flip_addr = &addr; - dc_update_surfaces_for_stream(adev->dm.dc, surface_updates, 1, acrtc->stream); + dc_update_surfaces_and_stream(adev->dm.dc, surface_updates, 1, acrtc->stream, NULL); DRM_DEBUG_DRIVER("%s Flipping to hi: 0x%x, low: 0x%x \n", __func__, diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 3ec702fecfd1..00961bc37200 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -511,12 +511,14 @@ static void split_stream_across_pipes( struct pipe_ctx *primary_pipe, struct pipe_ctx *secondary_pipe) { + int pipe_idx = secondary_pipe->pipe_idx; + if (!primary_pipe->surface) return; - secondary_pipe->stream = primary_pipe->stream; - secondary_pipe->tg = primary_pipe->tg; + *secondary_pipe = *primary_pipe; + secondary_pipe->pipe_idx = pipe_idx; secondary_pipe->mpcc = pool->mpcc[secondary_pipe->pipe_idx]; secondary_pipe->mi = pool->mis[secondary_pipe->pipe_idx]; secondary_pipe->ipp = pool->ipps[secondary_pipe->pipe_idx]; @@ -528,8 +530,6 @@ static void split_stream_across_pipes( } primary_pipe->bottom_pipe = secondary_pipe; secondary_pipe->top_pipe = primary_pipe; - secondary_pipe->surface = primary_pipe->surface; - secondary_pipe->pipe_dlg_param = primary_pipe->pipe_dlg_param; resource_build_scaling_params(primary_pipe); resource_build_scaling_params(secondary_pipe); @@ -1011,10 +1011,13 @@ bool dcn_validate_bandwidth( dcn_bw_calc_rq_dlg_ttu(dc, v, hsplit_pipe); } else if (hsplit_pipe && hsplit_pipe->surface == pipe->surface) { /* merge previously split pipe */ - if (pipe->bottom_pipe->bottom_pipe) - pipe->bottom_pipe->bottom_pipe->top_pipe = pipe; - memset(pipe->bottom_pipe, 0, sizeof(*pipe->bottom_pipe)); - pipe->bottom_pipe = pipe->bottom_pipe->bottom_pipe; + pipe->bottom_pipe = hsplit_pipe->bottom_pipe; + if (hsplit_pipe->bottom_pipe) + hsplit_pipe->bottom_pipe->top_pipe = pipe; + hsplit_pipe->surface = NULL; + hsplit_pipe->stream = NULL; + hsplit_pipe->top_pipe = NULL; + hsplit_pipe->bottom_pipe = NULL; resource_build_scaling_params(pipe); } /* for now important to do this after pipe split for building e2e params */ diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 18fde5081742..2f481ef55490 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -963,11 +963,8 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) for (i = 0; i < core_dc->res_pool->pipe_count; i++) if (context->res_ctx.pipe_ctx[i].stream == NULL - || context->res_ctx.pipe_ctx[i].surface == NULL) { - context->res_ctx.pipe_ctx[i].pipe_idx = i; - core_dc->hwss.power_down_front_end( - core_dc, &context->res_ctx.pipe_ctx[i]); - } + || context->res_ctx.pipe_ctx[i].surface == NULL) + core_dc->hwss.power_down_front_end(core_dc, i); /* 3rd param should be true, temp w/a for RV*/ #if defined(CONFIG_DRM_AMD_DC_DCN1_0) @@ -989,7 +986,6 @@ bool dc_commit_surfaces_to_stream( struct dc_plane_info plane_info[MAX_SURFACES]; struct dc_scaling_info scaling_info[MAX_SURFACES]; int i; - bool ret; struct dc_stream_update *stream_update = dm_alloc(sizeof(struct dc_stream_update)); @@ -1038,10 +1034,10 @@ bool dc_commit_surfaces_to_stream( new_surface_count, dc_stream, stream_update); - ret = dc_post_update_surfaces_to_stream(dc); + dc_post_update_surfaces_to_stream(dc); dm_free(stream_update); - return ret; + return true; } static bool is_surface_in_context( @@ -1217,14 +1213,6 @@ enum surface_update_type dc_check_update_surfaces_for_stream( return overall_type; } -void dc_update_surfaces_for_stream(struct dc *dc, - struct dc_surface_update *surface_updates, int surface_count, - const struct dc_stream *dc_stream) -{ - dc_update_surfaces_and_stream(dc, surface_updates, surface_count, - dc_stream, NULL); -} - enum surface_update_type update_surface_trace_level = UPDATE_TYPE_FULL; void dc_update_surfaces_and_stream(struct dc *dc, @@ -1401,7 +1389,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, } } - if (!surface_count) /* reset */ + if (surface_count == 0) core_dc->hwss.apply_ctx_for_surface(core_dc, NULL, context); /* Lock pipes for provided surfaces, or all active if full update*/ diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index f0183d5f0d0d..fb033b69e2bf 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1096,6 +1096,10 @@ bool resource_attach_surfaces_to_context( free_pipe->surface = surface; if (tail_pipe) { + free_pipe->tg = tail_pipe->tg; + free_pipe->stream_enc = tail_pipe->stream_enc; + free_pipe->audio = tail_pipe->audio; + free_pipe->clock_source = tail_pipe->clock_source; free_pipe->top_pipe = tail_pipe; tail_pipe->bottom_pipe = free_pipe; } @@ -2300,6 +2304,9 @@ bool pipe_need_reprogram( struct pipe_ctx *pipe_ctx_old, struct pipe_ctx *pipe_ctx) { + if (!pipe_ctx_old->stream) + return false; + if (pipe_ctx_old->stream->sink != pipe_ctx->stream->sink) return true; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index cb70b6d8be10..18f6858e4992 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -415,9 +415,6 @@ bool dc_commit_surfaces_to_stream( bool dc_post_update_surfaces_to_stream( struct dc *dc); -void dc_update_surfaces_for_stream(struct dc *dc, struct dc_surface_update *updates, - int surface_count, const struct dc_stream *stream); - /* Surface update type is used by dc_update_surfaces_and_stream * The update type is determined at the very beginning of the function based * on parameters passed in and decides how much programming (or updating) is diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 0bab85b27a85..fd1cb7fe45bc 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1185,8 +1185,7 @@ static void disable_vga_and_power_gate_all_controllers( enable_display_pipe_clock_gating(ctx, true); - dc->hwss.power_down_front_end( - dc, &dc->current_context->res_ctx.pipe_ctx[i]); + dc->hwss.power_down_front_end(dc, i); } } @@ -1340,7 +1339,7 @@ static void reset_single_pipe_hw_ctx( resource_unreference_clock_source(&context->res_ctx, dc->res_pool, &pipe_ctx->clock_source); - dc->hwss.power_down_front_end((struct core_dc *)dc, pipe_ctx); + dc->hwss.power_down_front_end((struct core_dc *)dc, pipe_ctx->pipe_idx); pipe_ctx->stream = NULL; } @@ -2538,17 +2537,17 @@ static void dce110_apply_ctx_for_surface( } } -static void dce110_power_down_fe(struct core_dc *dc, struct pipe_ctx *pipe) +static void dce110_power_down_fe(struct core_dc *dc, int fe_idx) { /* Do not power down fe when stream is active on dce*/ - if (pipe->stream) + if (dc->current_context->res_ctx.pipe_ctx[fe_idx].stream) return; dc->hwss.enable_display_power_gating( - dc, pipe->pipe_idx, dc->ctx->dc_bios, PIPE_GATING_CONTROL_ENABLE); - if (pipe->xfm) - pipe->xfm->funcs->transform_reset(pipe->xfm); - memset(&pipe->scl_data, 0, sizeof(struct scaler_data)); + dc, fe_idx, dc->ctx->dc_bios, PIPE_GATING_CONTROL_ENABLE); + + dc->res_pool->transforms[fe_idx]->funcs->transform_reset( + dc->res_pool->transforms[fe_idx]); } static const struct hw_sequencer_funcs dce110_funcs = { diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index edcd7369cf9d..d0bddfd64c67 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -116,18 +116,6 @@ static const struct dcn10_hwseq_reg_offsets reg_offsets[] = { HWSEQ_REG_SET_N(reg, 1, FD(reg##__##field), val) /* TODO should be moved to OTG */ -static void lock_otg_master_update( - struct dc_context *ctx, - uint8_t inst) -{ - uint32_t inst_offset = reg_offsets[inst].otg; - - HWSEQ_REG_UPDATE(OTG0_OTG_GLOBAL_CONTROL0, - OTG_MASTER_UPDATE_LOCK_SEL, inst); - - HWSEQ_REG_UPDATE(OTG0_OTG_MASTER_UPDATE_LOCK, - OTG_MASTER_UPDATE_LOCK, 1); -} static bool unlock_master_tg_and_wait( struct dc_context *ctx, @@ -148,19 +136,6 @@ static bool unlock_master_tg_and_wait( return true; } -/* TODO: should be moved to OTG ? */ -static void unlock_otg_master( - struct dc_context *ctx, - uint8_t inst) -{ - uint32_t inst_offset = reg_offsets[inst].otg; - - /* unlock master locker */ - HWSEQ_REG_UPDATE(OTG0_OTG_MASTER_UPDATE_LOCK, - OTG_MASTER_UPDATE_LOCK, 0); -} - - static void wait_no_outstanding_request( struct dc_context *ctx, uint8_t plane_id) @@ -489,8 +464,7 @@ static void hubp_pg_control( static void power_on_plane( struct dc_context *ctx, - uint8_t plane_id, - uint8_t inst) + int plane_id) { uint32_t inst_offset = 0; @@ -500,6 +474,8 @@ static void power_on_plane( hubp_pg_control(ctx, plane_id, true); HWSEQ_REG_SET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, 0); + dm_logger_write(ctx->logger, LOG_DC, + "Un-gated front end for pipe %d\n", plane_id); } /* fully check bios enabledisplaypowergating table. dal only need dce init @@ -596,13 +572,13 @@ static void init_hw(struct core_dc *dc) dc->res_pool->mpcc[i]; struct mpcc_cfg mpcc_cfg; - lock_otg_master_update(dc->ctx, tg->inst); + tg->funcs->lock(tg); mpcc_cfg.opp_id = 0xf; mpcc_cfg.top_dpp_id = 0xf; mpcc_cfg.bot_mpcc_id = 0xf; mpcc_cfg.top_of_tree = true; mpcc->funcs->set(mpcc, &mpcc_cfg); - unlock_otg_master(dc->ctx, tg->inst); + tg->funcs->unlock(tg); tg->funcs->disable_vga(tg); /* Blank controller using driver code instead of @@ -822,56 +798,85 @@ static void reset_back_end_for_pipe( return; pipe_ctx->stream = NULL; + dm_logger_write(dc->ctx->logger, LOG_DC, + "Reset back end for pipe %d, tg:%d\n", + pipe_ctx->pipe_idx, pipe_ctx->tg->inst); } -static void reset_front_end_for_pipe( +static void reset_front_end( struct core_dc *dc, - struct pipe_ctx *pipe_ctx, - struct validate_context *context) + int fe_idx) { struct mpcc_cfg mpcc_cfg; + struct mem_input *mi = dc->res_pool->mis[fe_idx]; + struct transform *xfm = dc->res_pool->transforms[fe_idx]; + struct mpcc *mpcc = dc->res_pool->mpcc[fe_idx]; + struct timing_generator *tg = dc->res_pool->timing_generators[mpcc->opp_id]; - if (!pipe_ctx->surface) + /*Already reset*/ + if (mpcc->opp_id == 0xf) return; - pipe_ctx->mi->funcs->dcc_control(pipe_ctx->mi, false, false); - - lock_otg_master_update(dc->ctx, pipe_ctx->tg->inst); + mi->funcs->dcc_control(mi, false, false); + tg->funcs->lock(tg); mpcc_cfg.opp_id = 0xf; mpcc_cfg.top_dpp_id = 0xf; mpcc_cfg.bot_mpcc_id = 0xf; - mpcc_cfg.top_of_tree = !pipe_ctx->top_pipe; - pipe_ctx->mpcc->funcs->set(pipe_ctx->mpcc, &mpcc_cfg); - - pipe_ctx->top_pipe = NULL; - pipe_ctx->bottom_pipe = NULL; + mpcc_cfg.top_of_tree = tg->inst == mpcc->inst; + mpcc->funcs->set(mpcc, &mpcc_cfg); - unlock_master_tg_and_wait(dc->ctx, pipe_ctx->tg->inst); + unlock_master_tg_and_wait(dc->ctx, tg->inst); + mpcc->funcs->wait_for_idle(mpcc); + mi->funcs->set_blank(mi, true); + wait_no_outstanding_request(dc->ctx, fe_idx); + disable_clocks(dc->ctx, fe_idx); - pipe_ctx->mi->funcs->set_blank(pipe_ctx->mi, true); + xfm->funcs->transform_reset(xfm); - wait_no_outstanding_request(dc->ctx, pipe_ctx->pipe_idx); + dm_logger_write(dc->ctx->logger, LOG_DC, + "Reset front end %d\n", + fe_idx); +} - disable_clocks(dc->ctx, pipe_ctx->pipe_idx); +static void dcn10_power_down_fe(struct core_dc *dc, int fe_idx) +{ + struct dc_context *ctx = dc->ctx; + uint32_t inst_offset = 0; - pipe_ctx->xfm->funcs->transform_reset(pipe_ctx->xfm); + reset_front_end(dc, fe_idx); + HWSEQ_REG_SET(DC_IP_REQUEST_CNTL, + IP_REQUEST_EN, 1); + dpp_pg_control(ctx, fe_idx, false); + hubp_pg_control(ctx, fe_idx, false); + HWSEQ_REG_SET(DC_IP_REQUEST_CNTL, + IP_REQUEST_EN, 0); dm_logger_write(dc->ctx->logger, LOG_DC, - "Reset front end for pipe %d\n", - pipe_ctx->pipe_idx); - - pipe_ctx->surface = NULL; + "Power gated front end %d\n", fe_idx); } -static void reset_hw_ctx(struct core_dc *dc, - struct validate_context *context, - void (*reset)(struct core_dc *dc, - struct pipe_ctx *pipe_ctx, - struct validate_context *context)) +static void reset_hw_ctx_wrap( + struct core_dc *dc, + struct validate_context *context) { int i; + /* Reset Front End*/ + for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) { + struct pipe_ctx *pipe_ctx_old = + &dc->current_context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + + /*if (!pipe_ctx_old->stream) + continue;*/ + + if (!pipe_ctx->stream || !pipe_ctx->surface) + dcn10_power_down_fe(dc, i); + else if (pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) + reset_front_end(dc, i); + } + /* Reset Back End*/ for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) { struct pipe_ctx *pipe_ctx_old = &dc->current_context->res_ctx.pipe_ctx[i]; @@ -882,23 +887,13 @@ static void reset_hw_ctx(struct core_dc *dc, if (!pipe_ctx->stream || pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) - reset(dc, pipe_ctx_old, dc->current_context); + reset_back_end_for_pipe(dc, pipe_ctx_old, dc->current_context); } } -static void reset_hw_ctx_wrap( - struct core_dc *dc, - struct validate_context *context) -{ - /* Reset Front End*/ - reset_hw_ctx(dc, context, reset_front_end_for_pipe); - /* Reset Back End*/ - reset_hw_ctx(dc, context, reset_back_end_for_pipe); -} - -static bool patch_address_for_sbs_tb_stereo(struct pipe_ctx *pipe_ctx, - PHYSICAL_ADDRESS_LOC *addr) +static bool patch_address_for_sbs_tb_stereo( + struct pipe_ctx *pipe_ctx, PHYSICAL_ADDRESS_LOC *addr) { struct core_surface *surface = pipe_ctx->surface; bool sec_split = pipe_ctx->top_pipe && @@ -936,8 +931,7 @@ static void update_plane_addr(const struct core_dc *dc, struct pipe_ctx *pipe_ct } static bool dcn10_set_input_transfer_func( - struct pipe_ctx *pipe_ctx, - const struct core_surface *surface) + struct pipe_ctx *pipe_ctx, const struct core_surface *surface) { struct input_pixel_processor *ipp = pipe_ctx->ipp; const struct core_transfer_func *tf = NULL; @@ -950,8 +944,8 @@ static bool dcn10_set_input_transfer_func( tf = DC_TRANSFER_FUNC_TO_CORE(surface->public.in_transfer_func); if (surface->public.gamma_correction && dce_use_lut(surface)) - ipp->funcs->ipp_program_input_lut(ipp, - surface->public.gamma_correction); + ipp->funcs->ipp_program_input_lut(ipp, + surface->public.gamma_correction); if (tf == NULL) ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS); @@ -1333,8 +1327,6 @@ static void dcn10_pipe_control_lock( struct pipe_ctx *pipe, bool lock) { - struct dce_hwseq *hws = hws = dc->hwseq; - /* use TG master update lock to lock everything on the TG * therefore only top pipe need to lock */ @@ -1342,9 +1334,9 @@ static void dcn10_pipe_control_lock( return; if (lock) - dcn10_lock(pipe->tg); + pipe->tg->funcs->lock(pipe->tg); else - dcn10_unlock(pipe->tg); + pipe->tg->funcs->unlock(pipe->tg); } static bool wait_for_reset_trigger_to_occur( @@ -1543,7 +1535,7 @@ static void dcn10_power_on_fe( struct dc_surface *dc_surface = &pipe_ctx->surface->public; power_on_plane(dc->ctx, - pipe_ctx->pipe_idx, pipe_ctx->tg->inst); + pipe_ctx->pipe_idx); /* enable DCFCLK current DCHUB */ enable_dcfclk(dc->ctx, @@ -1694,7 +1686,6 @@ static void update_dchubp_dpp( struct default_adjustment ocsc = {0}; struct tg_color black_color = {0}; struct mpcc_cfg mpcc_cfg; - struct pipe_ctx *top_pipe; bool per_pixel_alpha = surface->public.per_pixel_alpha && pipe_ctx->bottom_pipe; /* TODO: proper fix once fpga works */ @@ -1734,14 +1725,13 @@ static void update_dchubp_dpp( IPP_OUTPUT_FORMAT_12_BIT_FIX); pipe_ctx->scl_data.lb_params.alpha_en = per_pixel_alpha; - for (top_pipe = pipe_ctx; top_pipe != NULL; top_pipe = top_pipe->top_pipe) - mpcc_cfg.opp_id = top_pipe->opp->inst; mpcc_cfg.top_dpp_id = pipe_ctx->pipe_idx; if (pipe_ctx->bottom_pipe) mpcc_cfg.bot_mpcc_id = pipe_ctx->bottom_pipe->mpcc->inst; else mpcc_cfg.bot_mpcc_id = 0xf; - mpcc_cfg.top_of_tree = !pipe_ctx->top_pipe; + mpcc_cfg.opp_id = pipe_ctx->tg->inst; + mpcc_cfg.top_of_tree = pipe_ctx->pipe_idx == pipe_ctx->tg->inst; mpcc_cfg.per_pixel_alpha = per_pixel_alpha; /* DCN1.0 has output CM before MPC which seems to screw with * pre-multiplied alpha. @@ -1749,8 +1739,6 @@ static void update_dchubp_dpp( mpcc_cfg.pre_multiplied_alpha = is_rgb_cspace( pipe_ctx->stream->public.output_color_space) && per_pixel_alpha; - if (!dc->current_context->res_ctx.pipe_ctx[pipe_ctx->pipe_idx].surface) - pipe_ctx->mpcc->funcs->wait_for_idle(pipe_ctx->mpcc); pipe_ctx->mpcc->funcs->set(pipe_ctx->mpcc, &mpcc_cfg); color_space_to_black_color( @@ -1796,7 +1784,7 @@ static void program_all_pipe_in_tree( /* watermark is for all pipes */ pipe_ctx->mi->funcs->program_watermarks( pipe_ctx->mi, &context->bw.dcn.watermarks, ref_clk_mhz); - lock_otg_master_update(dc->ctx, pipe_ctx->tg->inst); + pipe_ctx->tg->funcs->lock(pipe_ctx->tg); pipe_ctx->tg->dlg_otg_param.vready_offset = pipe_ctx->pipe_dlg_param.vready_offset; pipe_ctx->tg->dlg_otg_param.vstartup_start = pipe_ctx->pipe_dlg_param.vstartup_start; @@ -1852,13 +1840,41 @@ static void dcn10_apply_ctx_for_surface( { int i; + /* reset unused mpcc */ + /*for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *old_pipe_ctx = + &dc->current_context->res_ctx.pipe_ctx[i]; + + if ((!pipe_ctx->surface && old_pipe_ctx->surface) + || (!pipe_ctx->stream && old_pipe_ctx->stream)) { + struct mpcc_cfg mpcc_cfg; + + mpcc_cfg.opp_id = 0xf; + mpcc_cfg.top_dpp_id = 0xf; + mpcc_cfg.bot_mpcc_id = 0xf; + mpcc_cfg.top_of_tree = !old_pipe_ctx->top_pipe; + old_pipe_ctx->mpcc->funcs->set(old_pipe_ctx->mpcc, &mpcc_cfg); + + old_pipe_ctx->top_pipe = NULL; + old_pipe_ctx->bottom_pipe = NULL; + old_pipe_ctx->surface = NULL; + + dm_logger_write(dc->ctx->logger, LOG_DC, + "Reset mpcc for pipe %d\n", + old_pipe_ctx->pipe_idx); + } + }*/ + + if (!surface) + return; + for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; - if (!pipe_ctx->surface || pipe_ctx->surface != surface) + if (pipe_ctx->surface != surface) continue; - /* looking for top pipe to program */ if (!pipe_ctx->top_pipe) program_all_pipe_in_tree(dc, pipe_ctx, context); @@ -1910,27 +1926,6 @@ static void dcn10_apply_ctx_for_surface( context->bw.dcn.watermarks.d.cstate_pstate.pstate_change_ns, context->bw.dcn.watermarks.d.pte_meta_urgent_ns ); - - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; - - if (!pipe_ctx->surface || pipe_ctx->top_pipe) - continue; - - /* unlock master update lock */ - unlock_otg_master(dc->ctx, pipe_ctx->tg->inst); - } - - /* reset unused pipe */ - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; - struct pipe_ctx *old_pipe_ctx = - &dc->current_context->res_ctx.pipe_ctx[i]; - - if ((!pipe_ctx->surface && old_pipe_ctx->surface) - || (!pipe_ctx->stream && old_pipe_ctx->stream)) - reset_front_end_for_pipe(dc, old_pipe_ctx, dc->current_context); - } } static void dcn10_set_bandwidth( @@ -1992,23 +1987,6 @@ static void dcn10_set_bandwidth( dcn10_pplib_apply_display_requirements(dc, context); } -static void dcn10_power_down_fe(struct core_dc *dc, struct pipe_ctx *pipe) -{ - struct dc_context *ctx = dc->ctx; - uint32_t inst_offset = 0; - - HWSEQ_REG_SET(DC_IP_REQUEST_CNTL, - IP_REQUEST_EN, 1); - dpp_pg_control(ctx, pipe->pipe_idx, false); - hubp_pg_control(ctx, pipe->pipe_idx, false); - HWSEQ_REG_SET(DC_IP_REQUEST_CNTL, - IP_REQUEST_EN, 0); - - if (pipe->xfm) - pipe->xfm->funcs->transform_reset(pipe->xfm); - memset(&pipe->scl_data, 0, sizeof(pipe->scl_data)); -} - static void set_drr(struct pipe_ctx **pipe_ctx, int num_pipes, int vmin, int vmax) { diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c index b1c590d4f454..7af04bce3599 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c @@ -65,17 +65,17 @@ void dcn10_mpcc_set_bg_color( static void set_output_mux(struct dcn10_mpcc *mpcc10, int opp_id, int mpcc_id) { - ASSERT(mpcc10->opp_id == 0xf || opp_id == mpcc10->opp_id); - mpcc10->opp_id = opp_id; + ASSERT(mpcc10->base.opp_id == 0xf || opp_id == mpcc10->base.opp_id); + mpcc10->base.opp_id = opp_id; REG_UPDATE(OPP_PIPE_CONTROL[opp_id], OPP_PIPE_CLOCK_EN, 1); REG_SET(MUX[opp_id], 0, MPC_OUT_MUX, mpcc_id); } static void reset_output_mux(struct dcn10_mpcc *mpcc10) { - REG_SET(MUX[mpcc10->opp_id], 0, MPC_OUT_MUX, 0xf); - REG_UPDATE(OPP_PIPE_CONTROL[mpcc10->opp_id], OPP_PIPE_CLOCK_EN, 0); - mpcc10->opp_id = 0xf; + REG_SET(MUX[mpcc10->base.opp_id], 0, MPC_OUT_MUX, 0xf); + REG_UPDATE(OPP_PIPE_CONTROL[mpcc10->base.opp_id], OPP_PIPE_CLOCK_EN, 0); + mpcc10->base.opp_id = 0xf; } static void dcn10_mpcc_set(struct mpcc *mpcc, struct mpcc_cfg *cfg) @@ -104,16 +104,17 @@ static void dcn10_mpcc_set(struct mpcc *mpcc, struct mpcc_cfg *cfg) if (cfg->top_of_tree) { if (cfg->opp_id != 0xf) set_output_mux(mpcc10, cfg->opp_id, mpcc->inst); - else + else if (mpcc->opp_id != 0xf) reset_output_mux(mpcc10); } + mpcc10->base.opp_id = cfg->opp_id; } static void dcn10_mpcc_wait_idle(struct mpcc *mpcc) { struct dcn10_mpcc *mpcc10 = TO_DCN10_MPCC(mpcc); - REG_WAIT(MPCC_STATUS, MPCC_IDLE, 1, 1000, 1000); + REG_WAIT(MPCC_STATUS, MPCC_BUSY, 0, 1000, 1000); } @@ -139,5 +140,5 @@ void dcn10_mpcc_construct(struct dcn10_mpcc *mpcc10, mpcc10->mpcc_shift = mpcc_shift; mpcc10->mpcc_mask = mpcc_mask; - mpcc10->opp_id = inst; + mpcc10->base.opp_id = inst; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h index 0f9f1b97d238..fff267455a3d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h @@ -68,6 +68,7 @@ struct dcn_mpcc_registers { SF(MPCC0_MPCC_CONTROL, MPCC_ALPHA_MULTIPLIED_MODE, mask_sh),\ SF(MPCC0_MPCC_CONTROL, MPCC_BLND_ACTIVE_OVERLAP_ONLY, mask_sh),\ SF(MPCC0_MPCC_STATUS, MPCC_IDLE, mask_sh),\ + SF(MPCC0_MPCC_STATUS, MPCC_BUSY, mask_sh),\ SF(MPCC0_MPCC_OPP_ID, MPCC_OPP_ID, mask_sh),\ SF(MPCC0_MPCC_BG_G_Y, MPCC_BG_G_Y, mask_sh),\ SF(MPCC0_MPCC_BG_R_CR, MPCC_BG_R_CR, mask_sh),\ @@ -83,6 +84,7 @@ struct dcn_mpcc_registers { type MPCC_ALPHA_MULTIPLIED_MODE;\ type MPCC_BLND_ACTIVE_OVERLAP_ONLY;\ type MPCC_IDLE;\ + type MPCC_BUSY;\ type MPCC_OPP_ID;\ type MPCC_BG_G_Y;\ type MPCC_BG_R_CR;\ @@ -103,8 +105,6 @@ struct dcn10_mpcc { const struct dcn_mpcc_registers *mpcc_regs; const struct dcn_mpcc_shift *mpcc_shift; const struct dcn_mpcc_mask *mpcc_mask; - - int opp_id; }; void dcn10_mpcc_construct(struct dcn10_mpcc *mpcc10, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c index 58fb29ff5677..802ace2e5212 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c @@ -575,6 +575,8 @@ void dcn10_lock(struct timing_generator *tg) { struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + REG_SET(OTG_GLOBAL_CONTROL0, 0, + OTG_MASTER_UPDATE_LOCK_SEL, tg->inst); REG_SET(OTG_MASTER_UPDATE_LOCK, 0, OTG_MASTER_UPDATE_LOCK, 1); } @@ -587,9 +589,9 @@ void dcn10_unlock(struct timing_generator *tg) OTG_MASTER_UPDATE_LOCK, 0); /* why are we waiting here? */ - REG_WAIT(OTG_DOUBLE_BUFFER_CONTROL, + /*REG_WAIT(OTG_DOUBLE_BUFFER_CONTROL, OTG_UPDATE_PENDING, 0, - 20000, 200000); + 20000, 200000);*/ } static void dcn10_get_position(struct timing_generator *tg, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h index c880fa587790..3b2a20a4b957 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h @@ -37,6 +37,7 @@ SRI(OTG_VREADY_PARAM, OTG, inst),\ SRI(OTG_BLANK_CONTROL, OTG, inst),\ SRI(OTG_MASTER_UPDATE_LOCK, OTG, inst),\ + SRI(OTG_GLOBAL_CONTROL0, OTG, inst),\ SRI(OTG_DOUBLE_BUFFER_CONTROL, OTG, inst),\ SRI(OTG_H_TOTAL, OTG, inst),\ SRI(OTG_H_BLANK_START_END, OTG, inst),\ @@ -83,6 +84,7 @@ struct dcn_tg_registers { uint32_t OTG_VREADY_PARAM; uint32_t OTG_BLANK_CONTROL; uint32_t OTG_MASTER_UPDATE_LOCK; + uint32_t OTG_GLOBAL_CONTROL0; uint32_t OTG_DOUBLE_BUFFER_CONTROL; uint32_t OTG_H_TOTAL; uint32_t OTG_H_BLANK_START_END; @@ -134,6 +136,7 @@ struct dcn_tg_registers { SF(OTG0_OTG_BLANK_CONTROL, OTG_BLANK_DE_MODE, mask_sh),\ SF(OTG0_OTG_BLANK_CONTROL, OTG_CURRENT_BLANK_STATE, mask_sh),\ SF(OTG0_OTG_MASTER_UPDATE_LOCK, OTG_MASTER_UPDATE_LOCK, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL0, OTG_MASTER_UPDATE_LOCK_SEL, mask_sh),\ SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_UPDATE_PENDING, mask_sh),\ SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_BLANK_DATA_DOUBLE_BUFFER_EN, mask_sh),\ SF(OTG0_OTG_H_TOTAL, OTG_H_TOTAL, mask_sh),\ @@ -224,6 +227,7 @@ struct dcn_tg_registers { type OTG_CURRENT_BLANK_STATE;\ type OTG_MASTER_UPDATE_LOCK;\ type OTG_UPDATE_PENDING;\ + type OTG_MASTER_UPDATE_LOCK_SEL;\ type OTG_BLANK_DATA_DOUBLE_BUFFER_EN;\ type OTG_H_TOTAL;\ type OTG_H_BLANK_START;\ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h index 51bc8ef5ef79..55c9c305a259 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h @@ -40,6 +40,7 @@ struct mpcc { const struct mpcc_funcs *funcs; struct dc_context *ctx; int inst; + int opp_id; }; struct mpcc_funcs { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 52884815c67b..642ae5e4ee1c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -105,7 +105,7 @@ struct hw_sequencer_funcs { struct dc_bios *dcb, enum pipe_gating_control power_gating); - void (*power_down_front_end)(struct core_dc *dc, struct pipe_ctx *pipe); + void (*power_down_front_end)(struct core_dc *dc, int fe_idx); void (*power_on_front_end)(struct core_dc *dc, struct pipe_ctx *pipe, -- cgit From dc0ea008168bfbc61a7915eb6ffb1cc48ce5e9cc Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Wed, 28 Jun 2017 11:05:00 -0400 Subject: drm/amd/display: Move dm_plane_state to DAL header. Signed-off-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h index 109172576499..bf20d57a99e0 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h @@ -36,6 +36,11 @@ struct dc_surface; struct dc_stream; +struct dm_plane_state { + struct drm_plane_state base; + struct dc_surface *dc_surface; +}; + struct dm_crtc_state { struct drm_crtc_state base; struct dc_stream *dc_stream; @@ -43,12 +48,6 @@ struct dm_crtc_state { #define to_dm_crtc_state(x) container_of(x, struct dm_crtc_state, base) -struct dm_plane_state { - struct drm_plane_state base; - struct dc_surface *dc_surface; -}; - - /*TODO Jodan Hersen use the one in amdgpu_dm*/ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, struct amdgpu_plane *aplane, -- cgit From d09fec0f94376b1c0048215e14838295730ed6d3 Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Tue, 27 Jun 2017 13:27:00 -0400 Subject: drm/amd/display: add hyst frames for fixed refresh Signed-off-by: Anthony Koo Reviewed-by: Anthony Koo Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/modules/freesync/freesync.c | 56 ++++++++++++++-------- 1 file changed, 36 insertions(+), 20 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index 7109742bd67c..c7da90f2d8e7 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -37,6 +37,9 @@ #define RENDER_TIMES_MAX_COUNT 20 /* Threshold to exit BTR (to avoid frequent enter-exits at the lower limit) */ #define BTR_EXIT_MARGIN 2000 +/* Number of consecutive frames to check before entering/exiting fixed refresh*/ +#define FIXED_REFRESH_ENTER_FRAME_COUNT 5 +#define FIXED_REFRESH_EXIT_FRAME_COUNT 5 #define FREESYNC_REGISTRY_NAME "freesync_v1" @@ -72,8 +75,9 @@ struct below_the_range { }; struct fixed_refresh { - bool fixed_refresh_active; - bool program_fixed_refresh; + bool fixed_active; + bool program_fixed; + unsigned int frame_counter; }; struct freesync_range { @@ -168,8 +172,8 @@ struct mod_freesync *mod_freesync_create(struct dc *dc) /* Create initial module folder in registry for freesync enable data */ flag.save_per_edid = true; flag.save_per_link = false; - dm_write_persistent_data(core_dc->ctx, NULL, FREESYNC_REGISTRY_NAME, NULL, NULL, - 0, &flag); + dm_write_persistent_data(core_dc->ctx, NULL, FREESYNC_REGISTRY_NAME, + NULL, NULL, 0, &flag); flag.save_per_edid = false; flag.save_per_link = false; if (dm_read_persistent_data(core_dc->ctx, NULL, NULL, @@ -422,7 +426,7 @@ static void calc_freesync_range(struct core_freesync *core_freesync, min_frame_duration_in_ns) * stream->timing.pix_clk_khz), stream->timing.h_total), 1000000); - /* In case of 4k free sync monitor, vmin or vmax cannot be less than vtotal */ + /* vmin/vmax cannot be less than vtotal */ if (state->freesync_range.vmin < vtotal) { /* Error of 1 is permissible */ ASSERT((state->freesync_range.vmin + 1) >= vtotal); @@ -553,8 +557,8 @@ static void reset_freesync_state_variables(struct freesync_state* state) state->btr.inserted_frame_duration_in_us = 0; state->btr.program_btr = false; - state->fixed_refresh.fixed_refresh_active = false; - state->fixed_refresh.program_fixed_refresh = false; + state->fixed_refresh.fixed_active = false; + state->fixed_refresh.program_fixed = false; } /* * Sets freesync mode on a stream depending on current freesync state. @@ -594,7 +598,7 @@ static bool set_freesync_on_streams(struct core_freesync *core_freesync, if (core_freesync->map[map_index].user_enable. enable_for_gaming == true && state->fullscreen == true && - state->fixed_refresh.fixed_refresh_active == false) { + state->fixed_refresh.fixed_active == false) { /* Enable freesync */ v_total_min = state->freesync_range.vmin; @@ -1240,29 +1244,39 @@ static void update_timestamps(struct core_freesync *core_freesync, state->btr.frame_counter = 0; /* Exit Fixed Refresh mode */ - } else if (state->fixed_refresh.fixed_refresh_active) { + } else if (state->fixed_refresh.fixed_active) { - state->fixed_refresh.program_fixed_refresh = true; - state->fixed_refresh.fixed_refresh_active = false; + state->fixed_refresh.frame_counter++; + if (state->fixed_refresh.frame_counter > + FIXED_REFRESH_EXIT_FRAME_COUNT) { + state->fixed_refresh.frame_counter = 0; + state->fixed_refresh.program_fixed = true; + state->fixed_refresh.fixed_active = false; + } } } else if (last_render_time_in_us > state->time.max_render_time_in_us) { /* Enter Below the Range */ if (!state->btr.btr_active && - core_freesync->map[map_index].caps->btr_supported) { + core_freesync->map[map_index].caps->btr_supported) { state->btr.program_btr = true; state->btr.btr_active = true; /* Enter Fixed Refresh mode */ - } else if (!state->fixed_refresh.fixed_refresh_active && + } else if (!state->fixed_refresh.fixed_active && !core_freesync->map[map_index].caps->btr_supported) { - state->fixed_refresh.program_fixed_refresh = true; - state->fixed_refresh.fixed_refresh_active = true; + state->fixed_refresh.frame_counter++; + if (state->fixed_refresh.frame_counter > + FIXED_REFRESH_ENTER_FRAME_COUNT) { + state->fixed_refresh.frame_counter = 0; + state->fixed_refresh.program_fixed = true; + state->fixed_refresh.fixed_active = true; + } } } @@ -1316,7 +1330,8 @@ static void apply_below_the_range(struct core_freesync *core_freesync, frame_time_in_us = last_render_time_in_us / mid_point_frames_ceil; - delta_from_mid_point_in_us_1 = (state->btr.mid_point_in_us > + delta_from_mid_point_in_us_1 = + (state->btr.mid_point_in_us > frame_time_in_us) ? (state->btr.mid_point_in_us - frame_time_in_us): (frame_time_in_us - state->btr.mid_point_in_us); @@ -1332,7 +1347,8 @@ static void apply_below_the_range(struct core_freesync *core_freesync, frame_time_in_us = last_render_time_in_us / mid_point_frames_floor; - delta_from_mid_point_in_us_2 = (state->btr.mid_point_in_us > + delta_from_mid_point_in_us_2 = + (state->btr.mid_point_in_us > frame_time_in_us) ? (state->btr.mid_point_in_us - frame_time_in_us): (frame_time_in_us - state->btr.mid_point_in_us); @@ -1374,15 +1390,15 @@ static void apply_fixed_refresh(struct core_freesync *core_freesync, unsigned int vmin = 0, vmax = 0; struct freesync_state *state = &core_freesync->map[map_index].state; - if (!state->fixed_refresh.program_fixed_refresh) + if (!state->fixed_refresh.program_fixed) return; - state->fixed_refresh.program_fixed_refresh = false; + state->fixed_refresh.program_fixed = false; /* Program Fixed Refresh */ /* Fixed Refresh set to "not active" so disengage */ - if (!state->fixed_refresh.fixed_refresh_active) { + if (!state->fixed_refresh.fixed_active) { set_freesync_on_streams(core_freesync, &stream, 1); /* Fixed Refresh set to "active" so engage (fix to max) */ -- cgit From 1663ae1c4288da81b9f1668d204aa8ed55ebf849 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Tue, 27 Jun 2017 16:34:27 -0400 Subject: drm/amd/display: Connect DC resource to FBC compressor - Connected DC resource to FBC compressor, - Initial Implementation of FBC for Stoney/Carrizo - Code is currently guarded with "ENABLE_FBC" compile time flag Signed-off-by: Bhawanpreet Lakha Reviewed-by: Roman Li Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 19 ++++++ .../drm/amd/display/dc/dce110/dce110_compressor.c | 78 +++++++++++----------- .../drm/amd/display/dc/dce110/dce110_compressor.h | 2 +- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 15 +++++ .../drm/amd/display/dc/dce110/dce110_resource.c | 10 +++ drivers/gpu/drm/amd/display/dc/inc/compressor.h | 6 +- drivers/gpu/drm/amd/display/dc/inc/core_dc.h | 6 ++ 7 files changed, 94 insertions(+), 42 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 2f481ef55490..51e4cb30f858 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -843,6 +843,11 @@ bool dc_enable_stereo( int i, j; struct pipe_ctx *pipe; struct core_dc *core_dc = DC_TO_CORE(dc); + +#ifdef ENABLE_FBC + struct compressor *fbc_compressor = core_dc->fbc_compressor; +#endif + for (i = 0; i < MAX_PIPES; i++) { if (context != NULL) pipe = &context->res_ctx.pipe_ctx[i]; @@ -854,6 +859,14 @@ bool dc_enable_stereo( core_dc->hwss.setup_stereo(pipe, core_dc); } } + +#ifdef ENABLE_FBC + if (fbc_compressor != NULL && + fbc_compressor->funcs->is_fbc_enabled_in_hw(core_dc->fbc_compressor, + &pipe->tg->inst)) + fbc_compressor->funcs->disable_fbc(fbc_compressor); + +#endif return ret; } @@ -1232,6 +1245,12 @@ void dc_update_surfaces_and_stream(struct dc *dc, if (!stream_status) return; /* Cannot commit surface to stream that is not committed */ +#ifdef ENABLE_FBC + if (srf_updates->flip_addr) { + if (srf_updates->flip_addr->address.grph.addr.low_part == 0) + ASSERT(0); + } +#endif context = core_dc->current_context; /* update current stream with the new updates */ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c index 5fe83045d1a6..1e59f4e31a6a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c @@ -175,7 +175,6 @@ void dce110_compressor_power_up_fbc(struct compressor *compressor) void dce110_compressor_enable_fbc( struct compressor *compressor, - uint32_t paths_num, struct compr_addr_and_pitch_params *params) { struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor); @@ -366,43 +365,6 @@ void dce110_compressor_set_fbc_invalidation_triggers( dm_write_reg(compressor->ctx, addr, value); } -bool dce110_compressor_construct(struct dce110_compressor *compressor, - struct dc_context *ctx) -{ - - compressor->base.options.bits.FBC_SUPPORT = true; - - /* for dce 11 always use one dram channel for lpt */ - compressor->base.lpt_channels_num = 1; - compressor->base.options.bits.DUMMY_BACKEND = false; - - /* - * check if this system has more than 1 dram channel; if only 1 then lpt - * should not be supported - */ - - - compressor->base.options.bits.CLK_GATING_DISABLED = false; - - compressor->base.ctx = ctx; - compressor->base.embedded_panel_h_size = 0; - compressor->base.embedded_panel_v_size = 0; - compressor->base.memory_bus_width = ctx->asic_id.vram_width; - compressor->base.allocated_size = 0; - compressor->base.preferred_requested_size = 0; - compressor->base.min_compress_ratio = FBC_COMPRESS_RATIO_INVALID; - compressor->base.options.raw = 0; - compressor->base.banks_num = 0; - compressor->base.raw_size = 0; - compressor->base.channel_interleave_size = 0; - compressor->base.dram_channels_num = 0; - compressor->base.lpt_channels_num = 0; - compressor->base.attached_inst = 0; - compressor->base.is_enabled = false; - - return true; -} - struct compressor *dce110_compressor_create(struct dc_context *ctx) { struct dce110_compressor *cp110 = @@ -503,3 +465,43 @@ static const struct compressor_funcs dce110_compressor_funcs = { }; +bool dce110_compressor_construct(struct dce110_compressor *compressor, + struct dc_context *ctx) +{ + + compressor->base.options.bits.FBC_SUPPORT = true; + + /* for dce 11 always use one dram channel for lpt */ + compressor->base.lpt_channels_num = 1; + compressor->base.options.bits.DUMMY_BACKEND = false; + + /* + * check if this system has more than 1 dram channel; if only 1 then lpt + * should not be supported + */ + + + compressor->base.options.bits.CLK_GATING_DISABLED = false; + + compressor->base.ctx = ctx; + compressor->base.embedded_panel_h_size = 0; + compressor->base.embedded_panel_v_size = 0; + compressor->base.memory_bus_width = ctx->asic_id.vram_width; + compressor->base.allocated_size = 0; + compressor->base.preferred_requested_size = 0; + compressor->base.min_compress_ratio = FBC_COMPRESS_RATIO_INVALID; + compressor->base.options.raw = 0; + compressor->base.banks_num = 0; + compressor->base.raw_size = 0; + compressor->base.channel_interleave_size = 0; + compressor->base.dram_channels_num = 0; + compressor->base.lpt_channels_num = 0; + compressor->base.attached_inst = 0; + compressor->base.is_enabled = false; +#ifdef ENABLE_FBC + compressor->base.funcs = &dce110_compressor_funcs; + +#endif + return true; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.h index ff21c86df828..460cb77b8d75 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.h @@ -50,7 +50,7 @@ void dce110_compressor_destroy(struct compressor **cp); /* FBC RELATED */ void dce110_compressor_power_up_fbc(struct compressor *cp); -void dce110_compressor_enable_fbc(struct compressor *cp, uint32_t paths_num, +void dce110_compressor_enable_fbc(struct compressor *cp, struct compr_addr_and_pitch_params *params); void dce110_compressor_disable_fbc(struct compressor *cp); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index fd1cb7fe45bc..72d5f753949d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -33,6 +33,10 @@ #include "dce110_timing_generator.h" #include "dce/dce_hwseq.h" +#ifdef ENABLE_FBC +#include "dce110_compressor.h" +#endif + #include "bios/bios_parser_helper.h" #include "timing_generator.h" #include "mem_input.h" @@ -1166,6 +1170,10 @@ static void power_down_all_hw_blocks(struct core_dc *dc) power_down_controllers(dc); power_down_clock_sources(dc); + +#ifdef ENABLE_FBC + dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); +#endif } static void disable_vga_and_power_gate_all_controllers( @@ -1630,6 +1638,10 @@ enum dc_status dce110_apply_ctx_to_hw( } set_safe_displaymarks(&context->res_ctx, dc->res_pool); + +#ifdef ENABLE_FBC + dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); +#endif /*TODO: when pplib works*/ apply_min_clocks(dc, context, &clocks_state, true); @@ -2215,6 +2227,9 @@ static void init_hw(struct core_dc *dc) abm->funcs->init_backlight(abm); abm->funcs->abm_init(abm); } +#ifdef ENABLE_FBC + dc->fbc_compressor->funcs->power_up_fbc(dc->fbc_compressor); +#endif } void dce110_fill_display_configs( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 45759b9f15e5..8b7bc1cc2b7b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -52,6 +52,10 @@ #include "dce/dce_abm.h" #include "dce/dce_dmcu.h" +#ifdef ENABLE_FBC +#include "dce110/dce110_compressor.h" +#endif + #include "reg_helper.h" #include "dce/dce_11_0_d.h" @@ -1347,6 +1351,12 @@ static bool construct( } } +#ifdef ENABLE_FBC + dc->fbc_compressor = dce110_compressor_create(ctx); + + + +#endif if (!underlay_create(ctx, &pool->base)) goto res_create_fail; diff --git a/drivers/gpu/drm/amd/display/dc/inc/compressor.h b/drivers/gpu/drm/amd/display/dc/inc/compressor.h index 5fdc2fc10231..24cca18f3c8f 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/compressor.h +++ b/drivers/gpu/drm/amd/display/dc/inc/compressor.h @@ -45,7 +45,7 @@ union fbc_physical_address { }; struct compr_addr_and_pitch_params { - enum controller_id controller_id; + /* enum controller_id controller_id; */ uint32_t inst; uint32_t source_view_width; uint32_t source_view_height; @@ -63,7 +63,7 @@ struct compressor; struct compressor_funcs { void (*power_up_fbc)(struct compressor *cp); - void (*enable_fbc)(struct compressor *cp, uint32_t paths_num, + void (*enable_fbc)(struct compressor *cp, struct compr_addr_and_pitch_params *params); void (*disable_fbc)(struct compressor *cp); void (*set_fbc_invalidation_triggers)(struct compressor *cp, @@ -78,7 +78,7 @@ struct compressor { struct dc_context *ctx; uint32_t attached_inst; bool is_enabled; - const struct compressor_funcs funcs; + const struct compressor_funcs *funcs; union { uint32_t raw; struct { diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_dc.h b/drivers/gpu/drm/amd/display/dc/inc/core_dc.h index 392cff2cd558..785236a44aee 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_dc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_dc.h @@ -10,6 +10,7 @@ #include "core_types.h" #include "hw_sequencer.h" +#include "compressor.h" #define DC_TO_CORE(dc)\ container_of(dc, struct core_dc, public) @@ -44,6 +45,11 @@ struct core_dc { * to compare to see if display config changed */ struct dm_pp_display_configuration prev_display_config; + + /* FBC compressor */ +#ifdef ENABLE_FBC + struct compressor *fbc_compressor; +#endif }; #endif /* __CORE_DC_H__ */ -- cgit From 9ff1bb090b40949cddfbb904e613395ad2633fc7 Mon Sep 17 00:00:00 2001 From: Corbin McElhanney Date: Fri, 23 Jun 2017 17:45:50 -0400 Subject: drm/amd/display: Add extra mode and clock info to DTN logs Adds some additional information to logs in dc_commit_streams to better match Dal2. Also adds a new function, dc_raw_log, that has the same functionality as dc_conn_log, but does not attach display specific prefixes to the log output. Finally, adds a new DC log type, LOG_DTN, that logs to LogMinor_DispConnect_dtn in DM. This new log type and dc_raw_log are used to generate clock info in the logs to match Dal2. Signed-off-by: Corbin McElhanney Reviewed-by: Aric Cyr Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 2 +- .../gpu/drm/amd/display/dc/basics/log_helpers.c | 30 +++++++++++++++++++++- drivers/gpu/drm/amd/display/dc/basics/logger.c | 6 +++-- drivers/gpu/drm/amd/display/dc/core/dc.c | 7 ++++- drivers/gpu/drm/amd/display/dc/dm_helpers.h | 3 ++- .../gpu/drm/amd/display/include/logger_interface.h | 5 ++++ drivers/gpu/drm/amd/display/include/logger_types.h | 1 + 7 files changed, 48 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index 64db62e609eb..df4d221e46c1 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -322,7 +322,7 @@ bool dm_helpers_dp_mst_send_payload_allocation( return true; } -bool dm_helpers_dc_conn_log(struct dc_context*ctx, const char *msg) +bool dm_helpers_dc_conn_log(struct dc_context *ctx, struct log_entry *entry, enum dc_log_type event) { return true; } diff --git a/drivers/gpu/drm/amd/display/dc/basics/log_helpers.c b/drivers/gpu/drm/amd/display/dc/basics/log_helpers.c index 1268be9ebaf3..070ae6f680e1 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/log_helpers.c +++ b/drivers/gpu/drm/amd/display/dc/basics/log_helpers.c @@ -95,7 +95,35 @@ void dc_conn_log(struct dc_context *ctx, dm_logger_append(&entry, "%2.2X ", hex_data[i]); dm_logger_append(&entry, "^\n"); - dm_helpers_dc_conn_log(ctx, entry.buf); + dm_helpers_dc_conn_log(ctx, &entry, event); + dm_logger_close(&entry); + + va_end(args); +} + +void dc_raw_log(struct dc_context *ctx, + enum dc_log_type event, + const char *msg, + ...) +{ + va_list args; + struct log_entry entry = { 0 }; + + dm_logger_open(ctx->logger, &entry, event); + + va_start(args, msg); + entry.buf_offset += dm_log_to_buffer( + &entry.buf[entry.buf_offset], + LOG_MAX_LINE_SIZE - entry.buf_offset, + msg, args); + + if (entry.buf[strlen(entry.buf) - 1] == '\n') { + entry.buf[strlen(entry.buf) - 1] = '\0'; + entry.buf_offset--; + } + + dm_logger_append(&entry, "^\n"); + dm_helpers_dc_conn_log(ctx, &entry, event); dm_logger_close(&entry); va_end(args); diff --git a/drivers/gpu/drm/amd/display/dc/basics/logger.c b/drivers/gpu/drm/amd/display/dc/basics/logger.c index 4be83703b809..0b17374b1535 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/logger.c +++ b/drivers/gpu/drm/amd/display/dc/basics/logger.c @@ -59,7 +59,8 @@ static const struct dc_log_type_info log_type_info_tbl[] = { {LOG_EVENT_LINK_TRAINING, "LKTN"}, {LOG_EVENT_LINK_LOSS, "LinkLoss"}, {LOG_EVENT_UNDERFLOW, "Underflow"}, - {LOG_IF_TRACE, "InterfaceTrace"} + {LOG_IF_TRACE, "InterfaceTrace"}, + {LOG_DTN, "DTN"} }; @@ -84,7 +85,8 @@ static const struct dc_log_type_info log_type_info_tbl[] = { (1 << LOG_DETECTION_DP_CAPS) | \ (1 << LOG_BACKLIGHT)) | \ (1 << LOG_I2C_AUX) | \ - (1 << LOG_IF_TRACE) /* | \ + (1 << LOG_IF_TRACE) | \ + (1 << LOG_DTN) /* | \ (1 << LOG_DEBUG) | \ (1 << LOG_BIOS) | \ (1 << LOG_SURFACE) | \ diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 51e4cb30f858..c113c1a259d4 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -944,9 +944,14 @@ bool dc_commit_streams( dc_enable_stereo(dc, context, streams, stream_count); } - CONN_MSG_MODE(sink->link, "{%dx%d, %dx%d@%dKhz}", + CONN_MSG_MODE(sink->link, "{%ux%u, %ux%u@%u, %ux%u@%uKhz}", + context->streams[i]->public.src.width, + context->streams[i]->public.src.height, context->streams[i]->public.timing.h_addressable, context->streams[i]->public.timing.v_addressable, + context->streams[i]->public.timing.pix_clk_khz * 1000 / + context->streams[i]->public.timing.h_total / + context->streams[i]->public.timing.v_total, // Refresh rate context->streams[i]->public.timing.h_total, context->streams[i]->public.timing.v_total, context->streams[i]->public.timing.pix_clk_khz); diff --git a/drivers/gpu/drm/amd/display/dc/dm_helpers.h b/drivers/gpu/drm/amd/display/dc/dm_helpers.h index 9fb606c49217..a831421c7ea0 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_helpers.h +++ b/drivers/gpu/drm/amd/display/dc/dm_helpers.h @@ -70,7 +70,8 @@ bool dm_helpers_dp_mst_start_top_mgr( bool dm_helpers_dc_conn_log( struct dc_context*ctx, - const char *msg); + struct log_entry *entry, + enum dc_log_type event); void dm_helpers_dp_mst_stop_top_mgr( struct dc_context *ctx, diff --git a/drivers/gpu/drm/amd/display/include/logger_interface.h b/drivers/gpu/drm/amd/display/include/logger_interface.h index b75c343f8680..ce5fef243b09 100644 --- a/drivers/gpu/drm/amd/display/include/logger_interface.h +++ b/drivers/gpu/drm/amd/display/include/logger_interface.h @@ -70,6 +70,11 @@ void dc_conn_log(struct dc_context *ctx, const char *msg, ...); +void dc_raw_log(struct dc_context *ctx, + enum dc_log_type event, + const char *msg, + ...); + void logger_write(struct dal_logger *logger, enum dc_log_type log_type, const char *msg, diff --git a/drivers/gpu/drm/amd/display/include/logger_types.h b/drivers/gpu/drm/amd/display/include/logger_types.h index dfc0f102b33d..42ffb93e3172 100644 --- a/drivers/gpu/drm/amd/display/include/logger_types.h +++ b/drivers/gpu/drm/amd/display/include/logger_types.h @@ -37,6 +37,7 @@ enum dc_log_type { LOG_WARNING, LOG_DEBUG, LOG_DC, + LOG_DTN, LOG_SURFACE, LOG_HW_HOTPLUG, LOG_HW_LINK_TRAINING, -- cgit From b1a4eb992c1712981f36bb0213879c426d524f76 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Mon, 26 Jun 2017 15:13:18 -0400 Subject: drm/amd/display: enable diags compilation Signed-off-by: Dmytro Laktyushkin Reviewed-by: Jordan Lazare Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c | 8 ++--- drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h | 41 ++++------------------ .../drm/amd/display/dc/dce120/dce120_resource.c | 17 +-------- .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 22 +++--------- .../gpu/drm/amd/display/dc/dcn10/dcn10_transform.h | 23 ++++++------ drivers/gpu/drm/amd/display/dc/inc/resource.h | 1 + 6 files changed, 27 insertions(+), 85 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c index 4e3f4e5e46a0..f30cd4dff554 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c @@ -781,11 +781,7 @@ struct display_clock *dce112_disp_clk_create( return &clk_dce->base; } -struct display_clock *dce120_disp_clk_create( - struct dc_context *ctx, - const struct dce_disp_clk_registers *regs, - const struct dce_disp_clk_shift *clk_shift, - const struct dce_disp_clk_mask *clk_mask) +struct display_clock *dce120_disp_clk_create(struct dc_context *ctx) { struct dce_disp_clk *clk_dce = dm_alloc(sizeof(*clk_dce)); struct dm_pp_clock_levels_with_voltage clk_level_info = {0}; @@ -800,7 +796,7 @@ struct display_clock *dce120_disp_clk_create( sizeof(dce120_max_clks_by_state)); dce_disp_clk_construct( - clk_dce, ctx, regs, clk_shift, clk_mask); + clk_dce, ctx, NULL, NULL, NULL); clk_dce->base.funcs = &dce120_funcs; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h index 103e905291a3..0e717e0dc8f0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h @@ -31,55 +31,30 @@ #define CLK_COMMON_REG_LIST_DCE_BASE() \ .DPREFCLK_CNTL = mmDPREFCLK_CNTL, \ - .DENTIST_DISPCLK_CNTL = mmDENTIST_DISPCLK_CNTL, \ - .MASTER_COMM_DATA_REG1 = mmMASTER_COMM_DATA_REG1, \ - .MASTER_COMM_CMD_REG = mmMASTER_COMM_CMD_REG, \ - .MASTER_COMM_CNTL_REG = mmMASTER_COMM_CNTL_REG + .DENTIST_DISPCLK_CNTL = mmDENTIST_DISPCLK_CNTL #define CLK_SF(reg_name, field_name, post_fix)\ .field_name = reg_name ## __ ## field_name ## post_fix #define CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh) \ CLK_SF(DPREFCLK_CNTL, DPREFCLK_SRC_SEL, mask_sh), \ - CLK_SF(DENTIST_DISPCLK_CNTL, DENTIST_DPREFCLK_WDIVIDER, mask_sh), \ - CLK_SF(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, mask_sh), \ - CLK_SF(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, mask_sh) - -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) -#define CLK_DCN10_REG_LIST()\ - SR(DPREFCLK_CNTL), \ - SR(DENTIST_DISPCLK_CNTL), \ - SR(MASTER_COMM_DATA_REG1), \ - SR(MASTER_COMM_CMD_REG), \ - SR(MASTER_COMM_CNTL_REG) -#endif - -#define CLK_COMMON_MASK_SH_LIST_SOC_BASE(mask_sh) \ - CLK_SF(DCCG_DFS_DPREFCLK_CNTL, DPREFCLK_SRC_SEL, mask_sh), \ - CLK_SF(DCCG_DFS_DENTIST_DISPCLK_CNTL, DENTIST_DPREFCLK_WDIVIDER, mask_sh), \ - CLK_SF(DCCG_DFS_MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, mask_sh), \ - CLK_SF(DCCG_DFS_MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, mask_sh) + CLK_SF(DENTIST_DISPCLK_CNTL, DENTIST_DPREFCLK_WDIVIDER, mask_sh) #define CLK_REG_FIELD_LIST(type) \ type DPREFCLK_SRC_SEL; \ - type DENTIST_DPREFCLK_WDIVIDER; \ - type MASTER_COMM_CMD_REG_BYTE0; \ - type MASTER_COMM_INTERRUPT + type DENTIST_DPREFCLK_WDIVIDER; struct dce_disp_clk_shift { - CLK_REG_FIELD_LIST(uint8_t); + CLK_REG_FIELD_LIST(uint8_t) }; struct dce_disp_clk_mask { - CLK_REG_FIELD_LIST(uint32_t); + CLK_REG_FIELD_LIST(uint32_t) }; struct dce_disp_clk_registers { uint32_t DPREFCLK_CNTL; uint32_t DENTIST_DISPCLK_CNTL; - uint32_t MASTER_COMM_DATA_REG1; - uint32_t MASTER_COMM_CMD_REG; - uint32_t MASTER_COMM_CNTL_REG; }; /* Array identifiers and count for the divider ranges.*/ @@ -155,11 +130,7 @@ struct display_clock *dce112_disp_clk_create( const struct dce_disp_clk_shift *clk_shift, const struct dce_disp_clk_mask *clk_mask); -struct display_clock *dce120_disp_clk_create( - struct dc_context *ctx, - const struct dce_disp_clk_registers *regs, - const struct dce_disp_clk_shift *clk_shift, - const struct dce_disp_clk_mask *clk_mask); +struct display_clock *dce120_disp_clk_create(struct dc_context *ctx); void dce_disp_clk_destroy(struct display_clock **disp_clk); diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index ec485353ea4f..82481247a812 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -137,18 +137,6 @@ static const struct dce110_timing_generator_offsets dce120_tg_offsets[] = { * end *********************/ -static const struct dce_disp_clk_registers disp_clk_regs = { - CLK_COMMON_REG_LIST_DCE_BASE() -}; - -static const struct dce_disp_clk_shift disp_clk_shift = { - CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) -}; - -static const struct dce_disp_clk_mask disp_clk_mask = { - CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) -}; - static const struct dce_dmcu_registers dmcu_regs = { DMCU_DCE110_COMMON_REG_LIST() }; @@ -904,10 +892,7 @@ static bool construct( } } - pool->base.display_clock = dce120_disp_clk_create(ctx, - &disp_clk_regs, - &disp_clk_shift, - &disp_clk_mask); + pool->base.display_clock = dce120_disp_clk_create(ctx); if (pool->base.display_clock == NULL) { dm_error("DC: failed to create display clock!\n"); BREAK_TO_DEBUGGER(); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index eebaffca8e75..a0dd75dc1c6d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -136,17 +136,6 @@ enum dcn10_clk_src_array_id { /* macros to expend register list macro defined in HW object header file * end *********************/ -static const struct dce_disp_clk_registers disp_clk_regs = { - CLK_DCN10_REG_LIST() -}; - -static const struct dce_disp_clk_shift disp_clk_shift = { - CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) -}; - -static const struct dce_disp_clk_mask disp_clk_mask = { - CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) -}; static const struct dce_dmcu_registers dmcu_regs = { DMCU_DCN10_REG_LIST() @@ -317,7 +306,7 @@ static const struct dcn10_opp_mask opp_mask = { #define tf_regs(id)\ [id] = {\ - TF_REG_LIST_DCN(id),\ + TF_REG_LIST_DCN10(id),\ } static const struct dcn_transform_registers tf_regs[] = { @@ -328,11 +317,11 @@ static const struct dcn_transform_registers tf_regs[] = { }; static const struct dcn_transform_shift tf_shift = { - TF_REG_LIST_SH_MASK_DCN(__SHIFT) + TF_REG_LIST_SH_MASK_DCN10(__SHIFT) }; static const struct dcn_transform_mask tf_mask = { - TF_REG_LIST_SH_MASK_DCN(_MASK), + TF_REG_LIST_SH_MASK_DCN10(_MASK), }; @@ -1338,10 +1327,7 @@ static bool construct( } if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { - pool->base.display_clock = dce120_disp_clk_create(ctx, - &disp_clk_regs, - &disp_clk_shift, - &disp_clk_mask); + pool->base.display_clock = dce120_disp_clk_create(ctx); if (pool->base.display_clock == NULL) { dm_error("DC: failed to create display clock!\n"); BREAK_TO_DEBUGGER(); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.h index 7c0089d4293b..cd312bd7055b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.h @@ -58,7 +58,6 @@ SRI(DCSURF_SEC_VIEWPORT_START, HUBP, id), \ SRI(DCSURF_PRI_VIEWPORT_DIMENSION_C, HUBP, id), \ SRI(DCSURF_PRI_VIEWPORT_START_C, HUBP, id), \ - SRI(CM_GAMUT_REMAP_CONTROL, CM, id), \ SRI(MPC_SIZE, DSCL, id), \ SRI(SCL_HORZ_FILTER_SCALE_RATIO, DSCL, id), \ SRI(SCL_VERT_FILTER_SCALE_RATIO, DSCL, id), \ @@ -71,7 +70,10 @@ SRI(SCL_VERT_FILTER_INIT_C, DSCL, id), \ SRI(SCL_VERT_FILTER_INIT_BOT_C, DSCL, id), \ SRI(RECOUT_START, DSCL, id), \ - SRI(RECOUT_SIZE, DSCL, id), \ + SRI(RECOUT_SIZE, DSCL, id) + +#define TF_REG_LIST_DCN10(id) \ + TF_REG_LIST_DCN(id), \ SRI(CM_GAMUT_REMAP_CONTROL, CM, id),\ SRI(CM_GAMUT_REMAP_C11_C12, CM, id),\ SRI(CM_GAMUT_REMAP_C13_C14, CM, id),\ @@ -92,8 +94,6 @@ SRI(CM_COMB_C31_C32, CM, id),\ SRI(CM_COMB_C33_C34, CM, id) - - #define TF_REG_LIST_SH_MASK_DCN(mask_sh)\ TF_SF(DSCL0_DSCL_EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_LEFT, mask_sh),\ TF_SF(DSCL0_DSCL_EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_RIGHT, mask_sh),\ @@ -103,11 +103,6 @@ TF_SF(DSCL0_OTG_H_BLANK, OTG_H_BLANK_END, mask_sh),\ TF_SF(DSCL0_OTG_V_BLANK, OTG_V_BLANK_START, mask_sh),\ TF_SF(DSCL0_OTG_V_BLANK, OTG_V_BLANK_END, mask_sh),\ - TF_SF(DSCL0_LB_DATA_FORMAT, PIXEL_DEPTH, mask_sh),\ - TF_SF(DSCL0_LB_DATA_FORMAT, PIXEL_EXPAN_MODE, mask_sh),\ - TF_SF(DSCL0_LB_DATA_FORMAT, PIXEL_REDUCE_MODE, mask_sh),\ - TF_SF(DSCL0_LB_DATA_FORMAT, DYNAMIC_PIXEL_DEPTH, mask_sh),\ - TF_SF(DSCL0_LB_DATA_FORMAT, DITHER_EN, mask_sh),\ TF_SF(DSCL0_LB_DATA_FORMAT, INTERLEAVE_EN, mask_sh),\ TF_SF(DSCL0_LB_DATA_FORMAT, ALPHA_EN, mask_sh),\ TF_SF(DSCL0_LB_MEMORY_CTRL, MEMORY_CONFIG, mask_sh),\ @@ -172,7 +167,15 @@ TF_SF(DSCL0_SCL_VERT_FILTER_INIT_BOT_C, SCL_V_INIT_FRAC_BOT_C, mask_sh),\ TF_SF(DSCL0_SCL_VERT_FILTER_INIT_BOT_C, SCL_V_INIT_INT_BOT_C, mask_sh),\ TF_SF(DSCL0_SCL_MODE, SCL_CHROMA_COEF_MODE, mask_sh),\ - TF_SF(DSCL0_SCL_MODE, SCL_COEF_RAM_SELECT_CURRENT, mask_sh),\ + TF_SF(DSCL0_SCL_MODE, SCL_COEF_RAM_SELECT_CURRENT, mask_sh) + +#define TF_REG_LIST_SH_MASK_DCN10(mask_sh)\ + TF_REG_LIST_SH_MASK_DCN(mask_sh),\ + TF_SF(DSCL0_LB_DATA_FORMAT, PIXEL_DEPTH, mask_sh),\ + TF_SF(DSCL0_LB_DATA_FORMAT, PIXEL_EXPAN_MODE, mask_sh),\ + TF_SF(DSCL0_LB_DATA_FORMAT, PIXEL_REDUCE_MODE, mask_sh),\ + TF_SF(DSCL0_LB_DATA_FORMAT, DYNAMIC_PIXEL_DEPTH, mask_sh),\ + TF_SF(DSCL0_LB_DATA_FORMAT, DITHER_EN, mask_sh),\ TF_SF(CM0_CM_GAMUT_REMAP_CONTROL, CM_GAMUT_REMAP_MODE, mask_sh),\ TF_SF(CM0_CM_GAMUT_REMAP_C11_C12, CM_GAMUT_REMAP_C11, mask_sh),\ TF_SF(CM0_CM_GAMUT_REMAP_C11_C12, CM_GAMUT_REMAP_C12, mask_sh),\ diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index 7cac24d4ae86..04e5fd1d8c89 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -42,6 +42,7 @@ struct resource_caps { int num_audio; int num_stream_encoder; int num_pll; + int num_dwb; }; struct resource_straps { -- cgit From 1c604cd862d4f069cb3bbafb4e35db614a57b096 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 28 Jun 2017 14:27:18 -0400 Subject: drm/amd/display: Change max OPP Signed-off-by: Dmytro Laktyushkin Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h index fff267455a3d..6a90a8bc09f8 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h @@ -30,7 +30,7 @@ #define TO_DCN10_MPCC(mpcc_base) \ container_of(mpcc_base, struct dcn10_mpcc, base) -#define MAX_OPP 4 +#define MAX_OPP 6 #define MPC_COMMON_REG_LIST_DCN1_0(inst) \ SRII(MUX, MPC_OUT, inst),\ -- cgit From abe07e80836fb25a5bcfda573413a68be82439c6 Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Wed, 28 Jun 2017 17:21:42 -0400 Subject: drm/amd/display: Add DC interface for custom CSC matrix Signed-off-by: Yue Hin Lau Reviewed-by: Vitaly Prosyak Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 26 +++++ drivers/gpu/drm/amd/display/dc/dc.h | 3 + .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 23 ++++ drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c | 117 ++++++++++++++++++++- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h | 76 +++++++++++++ .../gpu/drm/amd/display/dc/dcn10/dcn10_transform.c | 5 +- drivers/gpu/drm/amd/display/dc/inc/hw/transform.h | 1 + drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 5 + 8 files changed, 252 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index c113c1a259d4..a9ddd0756b3b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -221,6 +221,29 @@ static bool set_gamut_remap(struct dc *dc, const struct dc_stream *stream) return ret; } +static bool program_csc_matrix(struct dc *dc, const struct dc_stream *stream) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + struct core_stream *core_stream = DC_STREAM_TO_CORE(stream); + int i = 0; + bool ret = false; + struct pipe_ctx *pipes; + + for (i = 0; i < MAX_PIPES; i++) { + if (core_dc->current_context->res_ctx.pipe_ctx[i].stream + == core_stream) { + + pipes = &core_dc->current_context->res_ctx.pipe_ctx[i]; + core_dc->hwss.program_csc_matrix(pipes, + core_stream->public.output_color_space, + core_stream->public.csc_color_matrix.matrix); + ret = true; + } + } + + return ret; +} + static void set_static_screen_events(struct dc *dc, const struct dc_stream **stream, int num_streams, @@ -373,6 +396,9 @@ static void allocate_dc_stream_funcs(struct core_dc *core_dc) core_dc->public.stream_funcs.set_gamut_remap = set_gamut_remap; + core_dc->public.stream_funcs.program_csc_matrix = + program_csc_matrix; + core_dc->public.stream_funcs.set_dither_option = set_dither_option; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 18f6858e4992..3e2ed3d15379 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -118,6 +118,9 @@ struct dc_stream_funcs { bool (*set_gamut_remap)(struct dc *dc, const struct dc_stream *stream); + bool (*program_csc_matrix)(struct dc *dc, + const struct dc_stream *stream); + void (*set_static_screen_events)(struct dc *dc, const struct dc_stream **stream, int num_streams, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index d0bddfd64c67..f404e4e5e4ea 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1623,6 +1623,28 @@ static void program_gamut_remap(struct pipe_ctx *pipe_ctx) pipe_ctx->xfm->funcs->transform_set_gamut_remap(pipe_ctx->xfm, &adjust); } + +static void program_csc_matrix(struct pipe_ctx *pipe_ctx, + enum dc_color_space colorspace, + uint16_t *matrix) +{ + int i; + struct out_csc_color_matrix tbl_entry; + + if (pipe_ctx->stream->public.csc_color_matrix.enable_adjustment + == true) { + enum dc_color_space color_space = + pipe_ctx->stream->public.output_color_space; + + //uint16_t matrix[12]; + for (i = 0; i < 12; i++) + tbl_entry.regval[i] = pipe_ctx->stream->public.csc_color_matrix.matrix[i]; + + tbl_entry.color_space = color_space; + //tbl_entry.regval = matrix; + pipe_ctx->opp->funcs->opp_set_csc_adjustment(pipe_ctx->opp, &tbl_entry); + } +} static bool is_lower_pipe_tree_visible(struct pipe_ctx *pipe_ctx) { if (pipe_ctx->surface->public.visible) @@ -2103,6 +2125,7 @@ static void dcn10_setup_stereo(struct pipe_ctx *pipe_ctx, static const struct hw_sequencer_funcs dcn10_funcs = { .program_gamut_remap = program_gamut_remap, + .program_csc_matrix = program_csc_matrix, .init_hw = init_hw, .apply_ctx_to_hw = dce110_apply_ctx_to_hw, .apply_ctx_for_surface = dcn10_apply_ctx_for_surface, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c index 148e192f5f76..a07401004f44 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c @@ -713,6 +713,48 @@ static void opp_power_on_regamma_lut( } +void opp_set_output_csc_adjustment( + struct output_pixel_processor *opp, + const struct out_csc_color_matrix *tbl_entry) +{ + + struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); + //enum csc_color_mode config = CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; + + + uint32_t ocsc_mode = 4; + + /** + *if (tbl_entry != NULL) { + * switch (tbl_entry->color_space) { + * case COLOR_SPACE_SRGB: + * case COLOR_SPACE_2020_RGB_FULLRANGE: + * ocsc_mode = 0; + * break; + * case COLOR_SPACE_SRGB_LIMITED: + * case COLOR_SPACE_2020_RGB_LIMITEDRANGE: + * ocsc_mode = 1; + * break; + * case COLOR_SPACE_YCBCR601: + * case COLOR_SPACE_YCBCR601_LIMITED: + * ocsc_mode = 2; + * break; + * case COLOR_SPACE_YCBCR709: + * case COLOR_SPACE_YCBCR709_LIMITED: + * case COLOR_SPACE_2020_YCBCR: + * ocsc_mode = 3; + * break; + * case COLOR_SPACE_UNKNOWN: + * default: + * break; + * } + *} + */ + + REG_SET(CM_OCSC_CONTROL, 0, CM_OCSC_MODE, ocsc_mode); + program_color_matrix(oppn10, tbl_entry); +} + static void opp_program_regamma_lut( struct output_pixel_processor *opp, const struct pwl_result_data *rgb, @@ -736,6 +778,8 @@ static void opp_program_regamma_lut( } + + static bool opp_set_regamma_pwl( struct output_pixel_processor *opp, const struct pwl_params *params) { @@ -776,7 +820,7 @@ static void dcn10_opp_destroy(struct output_pixel_processor **opp) static struct opp_funcs dcn10_opp_funcs = { .opp_power_on_regamma_lut = opp_power_on_regamma_lut, - .opp_set_csc_adjustment = NULL, + .opp_set_csc_adjustment = opp_set_output_csc_adjustment, .opp_set_csc_default = opp_set_output_csc_default, .opp_set_dyn_expansion = opp_set_dyn_expansion, .opp_program_regamma_pwl = opp_set_regamma_pwl, @@ -802,3 +846,74 @@ void dcn10_opp_construct(struct dcn10_opp *oppn10, oppn10->opp_shift = opp_shift; oppn10->opp_mask = opp_mask; } + + +void program_color_matrix(struct dcn10_opp *oppn10, + const struct out_csc_color_matrix *tbl_entry) +{ + uint32_t mode; + + REG_GET(CM_OCSC_CONTROL, CM_OCSC_MODE, &mode); + + if (tbl_entry == NULL) { + BREAK_TO_DEBUGGER(); + return; + } + + + if (mode == 4) { + /*R*/ + REG_SET_2(CM_OCSC_C11_C12, 0, + CM_OCSC_C11, tbl_entry->regval[0], + CM_OCSC_C12, tbl_entry->regval[1]); + + REG_SET_2(CM_OCSC_C13_C14, 0, + CM_OCSC_C13, tbl_entry->regval[2], + CM_OCSC_C14, tbl_entry->regval[3]); + + /*G*/ + REG_SET_2(CM_OCSC_C21_C22, 0, + CM_OCSC_C21, tbl_entry->regval[4], + CM_OCSC_C22, tbl_entry->regval[5]); + + REG_SET_2(CM_OCSC_C23_C24, 0, + CM_OCSC_C23, tbl_entry->regval[6], + CM_OCSC_C24, tbl_entry->regval[7]); + + /*B*/ + REG_SET_2(CM_OCSC_C31_C32, 0, + CM_OCSC_C31, tbl_entry->regval[8], + CM_OCSC_C32, tbl_entry->regval[9]); + + REG_SET_2(CM_OCSC_C33_C34, 0, + CM_OCSC_C33, tbl_entry->regval[10], + CM_OCSC_C34, tbl_entry->regval[11]); + } else { + /*R*/ + REG_SET_2(CM_COMB_C11_C12, 0, + CM_COMB_C11, tbl_entry->regval[0], + CM_COMB_C12, tbl_entry->regval[1]); + + REG_SET_2(CM_COMB_C13_C14, 0, + CM_COMB_C13, tbl_entry->regval[2], + CM_COMB_C14, tbl_entry->regval[3]); + + /*G*/ + REG_SET_2(CM_COMB_C21_C22, 0, + CM_COMB_C21, tbl_entry->regval[4], + CM_COMB_C22, tbl_entry->regval[5]); + + REG_SET_2(CM_COMB_C23_C24, 0, + CM_COMB_C23, tbl_entry->regval[6], + CM_COMB_C24, tbl_entry->regval[7]); + + /*B*/ + REG_SET_2(CM_COMB_C31_C32, 0, + CM_COMB_C31, tbl_entry->regval[8], + CM_COMB_C32, tbl_entry->regval[9]); + + REG_SET_2(CM_COMB_C33_C34, 0, + CM_COMB_C33, tbl_entry->regval[10], + CM_COMB_C34, tbl_entry->regval[11]); + } +} diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h index 113e0bc349c3..9cc4c5feaddf 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h @@ -34,6 +34,18 @@ .field_name = reg_name ## __ ## field_name ## post_fix #define OPP_DCN10_REG_LIST(id) \ + SRI(CM_OCSC_C11_C12, CM, id), \ + SRI(CM_OCSC_C13_C14, CM, id), \ + SRI(CM_OCSC_C21_C22, CM, id), \ + SRI(CM_OCSC_C23_C24, CM, id), \ + SRI(CM_OCSC_C31_C32, CM, id), \ + SRI(CM_OCSC_C33_C34, CM, id), \ + SRI(CM_COMB_C11_C12, CM, id), \ + SRI(CM_COMB_C13_C14, CM, id), \ + SRI(CM_COMB_C21_C22, CM, id), \ + SRI(CM_COMB_C23_C24, CM, id), \ + SRI(CM_COMB_C31_C32, CM, id), \ + SRI(CM_COMB_C33_C34, CM, id), \ SRI(CM_RGAM_LUT_WRITE_EN_MASK, CM, id), \ SRI(CM_RGAM_CONTROL, CM, id), \ SRI(OBUF_CONTROL, DSCL, id), \ @@ -109,6 +121,30 @@ SRI(CM_RGAM_LUT_DATA, CM, id) #define OPP_DCN10_MASK_SH_LIST(mask_sh) \ + OPP_SF(CM0_CM_OCSC_C11_C12, CM_OCSC_C11, mask_sh), \ + OPP_SF(CM0_CM_OCSC_C11_C12, CM_OCSC_C12, mask_sh), \ + OPP_SF(CM0_CM_OCSC_C13_C14, CM_OCSC_C13, mask_sh), \ + OPP_SF(CM0_CM_OCSC_C13_C14, CM_OCSC_C14, mask_sh), \ + OPP_SF(CM0_CM_OCSC_C21_C22, CM_OCSC_C21, mask_sh), \ + OPP_SF(CM0_CM_OCSC_C21_C22, CM_OCSC_C22, mask_sh), \ + OPP_SF(CM0_CM_OCSC_C23_C24, CM_OCSC_C23, mask_sh), \ + OPP_SF(CM0_CM_OCSC_C23_C24, CM_OCSC_C24, mask_sh), \ + OPP_SF(CM0_CM_OCSC_C31_C32, CM_OCSC_C31, mask_sh), \ + OPP_SF(CM0_CM_OCSC_C31_C32, CM_OCSC_C32, mask_sh), \ + OPP_SF(CM0_CM_OCSC_C33_C34, CM_OCSC_C33, mask_sh), \ + OPP_SF(CM0_CM_OCSC_C33_C34, CM_OCSC_C34, mask_sh), \ + OPP_SF(CM0_CM_COMB_C11_C12, CM_COMB_C11, mask_sh), \ + OPP_SF(CM0_CM_COMB_C11_C12, CM_COMB_C12, mask_sh), \ + OPP_SF(CM0_CM_COMB_C13_C14, CM_COMB_C13, mask_sh), \ + OPP_SF(CM0_CM_COMB_C13_C14, CM_COMB_C14, mask_sh), \ + OPP_SF(CM0_CM_COMB_C21_C22, CM_COMB_C21, mask_sh), \ + OPP_SF(CM0_CM_COMB_C21_C22, CM_COMB_C22, mask_sh), \ + OPP_SF(CM0_CM_COMB_C23_C24, CM_COMB_C23, mask_sh), \ + OPP_SF(CM0_CM_COMB_C23_C24, CM_COMB_C24, mask_sh), \ + OPP_SF(CM0_CM_COMB_C31_C32, CM_COMB_C31, mask_sh), \ + OPP_SF(CM0_CM_COMB_C31_C32, CM_COMB_C32, mask_sh), \ + OPP_SF(CM0_CM_COMB_C33_C34, CM_COMB_C33, mask_sh), \ + OPP_SF(CM0_CM_COMB_C33_C34, CM_COMB_C34, mask_sh), \ OPP_SF(CM0_CM_RGAM_CONTROL, CM_RGAM_LUT_MODE, mask_sh), \ OPP_SF(DSCL0_OBUF_CONTROL, OBUF_BYPASS, mask_sh), \ OPP_SF(DSCL0_OBUF_CONTROL, OBUF_H_2X_UPSCALE_EN, mask_sh), \ @@ -314,6 +350,30 @@ OPP_SF(FMT0_FMT_CONTROL, FMT_STEREOSYNC_OVERRIDE, mask_sh) #define OPP_DCN10_REG_FIELD_LIST(type) \ + type CM_OCSC_C11; \ + type CM_OCSC_C12; \ + type CM_OCSC_C13; \ + type CM_OCSC_C14; \ + type CM_OCSC_C21; \ + type CM_OCSC_C22; \ + type CM_OCSC_C23; \ + type CM_OCSC_C24; \ + type CM_OCSC_C31; \ + type CM_OCSC_C32; \ + type CM_OCSC_C33; \ + type CM_OCSC_C34; \ + type CM_COMB_C11; \ + type CM_COMB_C12; \ + type CM_COMB_C13; \ + type CM_COMB_C14; \ + type CM_COMB_C21; \ + type CM_COMB_C22; \ + type CM_COMB_C23; \ + type CM_COMB_C24; \ + type CM_COMB_C31; \ + type CM_COMB_C32; \ + type CM_COMB_C33; \ + type CM_COMB_C34; \ type CM_RGAM_LUT_MODE; \ type OBUF_BYPASS; \ type OBUF_H_2X_UPSCALE_EN; \ @@ -527,6 +587,18 @@ struct dcn10_opp_mask { }; struct dcn10_opp_registers { + uint32_t CM_OCSC_C11_C12; + uint32_t CM_OCSC_C13_C14; + uint32_t CM_OCSC_C21_C22; + uint32_t CM_OCSC_C23_C24; + uint32_t CM_OCSC_C31_C32; + uint32_t CM_OCSC_C33_C34; + uint32_t CM_COMB_C11_C12; + uint32_t CM_COMB_C13_C14; + uint32_t CM_COMB_C21_C22; + uint32_t CM_COMB_C23_C24; + uint32_t CM_COMB_C31_C32; + uint32_t CM_COMB_C33_C34; uint32_t CM_RGAM_LUT_WRITE_EN_MASK; uint32_t CM_RGAM_CONTROL; uint32_t OBUF_CONTROL; @@ -619,4 +691,8 @@ void dcn10_opp_construct(struct dcn10_opp *oppn10, const struct dcn10_opp_shift *opp_shift, const struct dcn10_opp_mask *opp_mask); +void program_color_matrix( + struct dcn10_opp *oppn10, + const struct out_csc_color_matrix *tbl_entry); + #endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c index d9815a991682..92322b75d868 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c @@ -1027,9 +1027,8 @@ static struct transform_funcs dcn10_transform_funcs = { .transform_reset = transform_reset, .transform_set_scaler = transform_set_scaler_manual_scale, - .transform_get_optimal_number_of_taps = - transform_get_optimal_number_of_taps, - .transform_set_gamut_remap = dcn_transform_set_gamut_remap + .transform_get_optimal_number_of_taps = transform_get_optimal_number_of_taps, + .transform_set_gamut_remap = dcn_transform_set_gamut_remap, }; /*****************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h index 8325a0a47179..b4862c376b41 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h @@ -180,6 +180,7 @@ struct transform_funcs { struct transform *xfm, const struct xfm_grph_csc_adjustment *adjust); + void (*transform_set_pixel_storage_depth)( struct transform *xfm, enum lb_pixel_depth depth, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 642ae5e4ee1c..97dbd259f66c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -70,6 +70,11 @@ struct hw_sequencer_funcs { void (*program_gamut_remap)( struct pipe_ctx *pipe_ctx); + void (*program_csc_matrix)( + struct pipe_ctx *pipe_ctx, + enum dc_color_space colorspace, + uint16_t *matrix); + void (*update_plane_addr)( const struct core_dc *dc, struct pipe_ctx *pipe_ctx); -- cgit From 1a87fbfee0a0f96e8b482c2ac7eae113c9ca2497 Mon Sep 17 00:00:00 2001 From: Amy Zhang Date: Wed, 28 Jun 2017 18:14:09 -0400 Subject: drm/amd/display: Re-enable Vsync Interrupts for Gradual Refresh Ramp - Make sure Vsync interrupts are disabled in static screen case and enabled when not to save power - Create no_static_for_external_dp debug option Signed-off-by: Amy Zhang Reviewed-by: Anthony Koo Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 1 + .../drm/amd/display/modules/freesync/freesync.c | 38 ++++++++++++++++------ .../gpu/drm/amd/display/modules/inc/mod_freesync.h | 5 +++ 3 files changed, 34 insertions(+), 10 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 3e2ed3d15379..93aff8269778 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -188,6 +188,7 @@ struct dc_debug { bool disable_dmcu; bool disable_psr; bool force_abm_enable; + bool no_static_for_external_dp; }; struct dc { diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index c7da90f2d8e7..4df79f7147f8 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -440,14 +440,11 @@ static void calc_freesync_range(struct core_freesync *core_freesync, } /* Determine whether BTR can be supported */ - //if (max_frame_duration_in_ns >= - // 2 * min_frame_duration_in_ns) - // core_freesync->map[index].caps->btr_supported = true; - //else - // core_freesync->map[index].caps->btr_supported = false; - - /* Temp, keep btr disabled */ - core_freesync->map[index].caps->btr_supported = false; + if (max_frame_duration_in_ns >= + 2 * min_frame_duration_in_ns) + core_freesync->map[index].caps->btr_supported = true; + else + core_freesync->map[index].caps->btr_supported = false; /* Cache the time variables */ state->time.max_render_time_in_us = @@ -882,8 +879,10 @@ void mod_freesync_update_state(struct mod_freesync *mod_freesync, * panels. Also change core variables only if there * is a change. */ - if (dc_is_embedded_signal( - streams[stream_index]->sink->sink_signal) && + if ((dc_is_embedded_signal( + streams[stream_index]->sink->sink_signal) || + core_freesync->map[map_index].caps-> + no_static_for_external_dp == false) && state->static_screen != freesync_params->enable) { @@ -1035,6 +1034,25 @@ bool mod_freesync_get_user_enable(struct mod_freesync *mod_freesync, return true; } +bool mod_freesync_get_static_ramp_active(struct mod_freesync *mod_freesync, + const struct dc_stream *stream, + bool *is_ramp_active) +{ + unsigned int index = 0; + struct core_freesync *core_freesync = NULL; + + if (mod_freesync == NULL) + return false; + + core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync); + index = map_index_from_stream(core_freesync, stream); + + *is_ramp_active = + core_freesync->map[index].state.static_ramp.ramp_is_active; + + return true; +} + bool mod_freesync_override_min_max(struct mod_freesync *mod_freesync, const struct dc_stream *streams, unsigned int min_refresh, diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h b/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h index f7f5a2cd7914..eae1b348b0dd 100644 --- a/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h +++ b/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h @@ -88,6 +88,7 @@ struct mod_freesync_caps { unsigned int max_refresh_in_micro_hz; bool btr_supported; + bool no_static_for_external_dp; }; struct mod_freesync_params { @@ -129,6 +130,10 @@ bool mod_freesync_get_user_enable(struct mod_freesync *mod_freesync, const struct dc_stream *stream, struct mod_freesync_user_enable *user_enable); +bool mod_freesync_get_static_ramp_active(struct mod_freesync *mod_freesync, + const struct dc_stream *stream, + bool *is_ramp_active); + bool mod_freesync_override_min_max(struct mod_freesync *mod_freesync, const struct dc_stream *streams, unsigned int min_refresh, -- cgit From 46239f739aa64c797938e9a14b03fd2c1b8ce0e6 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Thu, 29 Jun 2017 20:25:23 -0400 Subject: drm/amd/display: Enabling VSR on 4K display causes black screen Signed-off-by: Charlene Liu Reviewed-by: Anthony Koo Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index f404e4e5e4ea..cc67707b56d0 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1819,7 +1819,7 @@ static void program_all_pipe_in_tree( pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, !is_pipe_tree_visible(pipe_ctx)); } - if (pipe_ctx->surface->public.visible) { + if (pipe_ctx->surface != NULL) { dcn10_power_on_fe(dc, pipe_ctx, context); update_dchubp_dpp(dc, pipe_ctx, context); } -- cgit From cdc5e04888cec337e44049f9b51d8894364ad52a Mon Sep 17 00:00:00 2001 From: Vitaly Prosyak Date: Wed, 28 Jun 2017 13:36:25 -0500 Subject: drm/amd/display: Fix for hdmi frame pack stereo Signed-off-by: Vitaly Prosyak Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 10 +++++++++- drivers/gpu/drm/amd/display/dc/core/dc.c | 3 +-- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 11 ++++++++--- 4 files changed, 19 insertions(+), 7 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 00961bc37200..4486121e3986 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -987,7 +987,15 @@ bool dcn_validate_bandwidth( if (pipe->surface) { struct pipe_ctx *hsplit_pipe = pipe->bottom_pipe; - if (v->dpp_per_plane[input_idx] == 2) { + if (v->dpp_per_plane[input_idx] == 2 || + ((pipe->stream->public.view_format == + VIEW_3D_FORMAT_SIDE_BY_SIDE || + pipe->stream->public.view_format == + VIEW_3D_FORMAT_TOP_AND_BOTTOM) && + (pipe->stream->public.timing.timing_3d_format == + TIMING_3D_FORMAT_TOP_AND_BOTTOM || + pipe->stream->public.timing.timing_3d_format == + TIMING_3D_FORMAT_SIDE_BY_SIDE))) { if (hsplit_pipe && hsplit_pipe->surface == pipe->surface) { /* update previously split pipe */ hsplit_pipe->pipe_dlg_param.vupdate_width = v->v_update_width[input_idx]; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index a9ddd0756b3b..1d2e421e8d0a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -967,7 +967,6 @@ bool dc_commit_streams( DC_SURFACE_TO_CORE(context->stream_status[i].surfaces[j]); core_dc->hwss.apply_ctx_for_surface(core_dc, surface, context); - dc_enable_stereo(dc, context, streams, stream_count); } CONN_MSG_MODE(sink->link, "{%ux%u, %ux%u@%u, %ux%u@%uKhz}", @@ -982,7 +981,7 @@ bool dc_commit_streams( context->streams[i]->public.timing.v_total, context->streams[i]->public.timing.pix_clk_khz); } - + dc_enable_stereo(dc, context, streams, stream_count); dc_resource_validate_ctx_destruct(core_dc->current_context); dm_free(core_dc->current_context); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index fb033b69e2bf..ddf032214dc3 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -626,7 +626,7 @@ static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) if (stream->public.view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE) pipe_ctx->scl_data.ratios.horz.value *= 2; - else if (surface->stereo_format == PLANE_STEREO_FORMAT_TOP_AND_BOTTOM) + else if (stream->public.view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) pipe_ctx->scl_data.ratios.vert.value *= 2; pipe_ctx->scl_data.ratios.vert.value = div64_s64( diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index cc67707b56d0..d38570e6d4d2 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -891,7 +891,6 @@ static void reset_hw_ctx_wrap( } } - static bool patch_address_for_sbs_tb_stereo( struct pipe_ctx *pipe_ctx, PHYSICAL_ADDRESS_LOC *addr) { @@ -904,11 +903,17 @@ static bool patch_address_for_sbs_tb_stereo( pipe_ctx->stream->public.timing.timing_3d_format == TIMING_3D_FORMAT_TOP_AND_BOTTOM)) { *addr = surface->public.address.grph_stereo.left_addr; - surface->public.address.grph_stereo.left_addr =\ + surface->public.address.grph_stereo.left_addr = surface->public.address.grph_stereo.right_addr; return true; + } else { + if (pipe_ctx->stream->public.view_format != VIEW_3D_FORMAT_NONE && + surface->public.address.type != PLN_ADDR_TYPE_GRPH_STEREO) { + surface->public.address.type = PLN_ADDR_TYPE_GRPH_STEREO; + surface->public.address.grph_stereo.right_addr = + surface->public.address.grph_stereo.left_addr; + } } - return false; } -- cgit From c3aa1d67295c8fc87364dfe8920c9e30775fd124 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Fri, 30 Jun 2017 15:19:55 -0400 Subject: drm/amd/display: Set static screen register for stoney/carrizo -Set CRTC_STATIC_SCREEN_EVENT for stoney/carrizo for FBC implementation -Code is currently guarded with "ENABLE_FBC" compile time flag Signed-off-by: Bhawanpreet Lakha Reviewed-by: Roman Li Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 72d5f753949d..8778af76f4e0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1395,6 +1395,10 @@ static void set_static_screen_control(struct pipe_ctx **pipe_ctx, if (events->cursor_update) value |= 0x2; +#ifdef ENABLE_FBC + value |= 0x84; +#endif + for (i = 0; i < num_pipes; i++) pipe_ctx[i]->tg->funcs-> set_static_screen_control(pipe_ctx[i]->tg, value); -- cgit From 62a3213aca0bf519457545f22c41154a4848e390 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 28 Jun 2017 14:33:29 -0400 Subject: drm/amd/display: Rename DCN TG specific function prefixes to tg Signed-off-by: Dmytro Laktyushkin Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/dcn10/dcn10_timing_generator.c | 159 +++++++++------------ .../amd/display/dc/dcn10/dcn10_timing_generator.h | 53 +++---- 2 files changed, 94 insertions(+), 118 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c index 802ace2e5212..5927478b9044 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c @@ -44,7 +44,7 @@ * This is a workaround for a bug that has existed since R5xx and has not been * fixed keep Front porch at minimum 2 for Interlaced mode or 1 for progressive. */ -static void tg_apply_front_porch_workaround( +static void tgn10_apply_front_porch_workaround( struct timing_generator *tg, struct dc_crtc_timing *timing) { @@ -57,7 +57,7 @@ static void tg_apply_front_porch_workaround( } } -static void dcn10_program_global_sync( +static void tgn10_program_global_sync( struct timing_generator *tg) { struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); @@ -78,7 +78,7 @@ static void dcn10_program_global_sync( VREADY_OFFSET, tg->dlg_otg_param.vready_offset); } -static void dcn10_disable_stereo(struct timing_generator *tg) +static void tgn10_disable_stereo(struct timing_generator *tg) { struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); @@ -101,9 +101,10 @@ static void dcn10_disable_stereo(struct timing_generator *tg) * Program CRTC Timing Registers - OTG_H_*, OTG_V_*, Pixel repetition. * Including SYNC. Call BIOS command table to program Timings. */ -static void tg_program_timing_generator( +static void tgn10_program_timing( struct timing_generator *tg, - const struct dc_crtc_timing *dc_crtc_timing) + const struct dc_crtc_timing *dc_crtc_timing, + bool use_vbios) { struct dc_crtc_timing patched_crtc_timing; uint32_t vesa_sync_start; @@ -118,11 +119,10 @@ static void tg_program_timing_generator( uint32_t field_num = 0; uint32_t h_div_2; - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); patched_crtc_timing = *dc_crtc_timing; - tg_apply_front_porch_workaround(tg, &patched_crtc_timing); + tgn10_apply_front_porch_workaround(tg, &patched_crtc_timing); /* Load horizontal timing */ @@ -253,7 +253,7 @@ static void tg_program_timing_generator( OTG_START_POINT_CNTL, start_point, OTG_FIELD_NUMBER_CNTL, field_num); - dcn10_program_global_sync(tg); + tgn10_program_global_sync(tg); /* TODO * patched_crtc_timing.flags.HORZ_COUNT_BY_TWO == 1 @@ -273,25 +273,11 @@ static void tg_program_timing_generator( } -/** tg_program_blanking - * Only programmed part of OTG_H, OTG_V register for set_plane_config - * Assume other OTG registers are programmed by video mode set already. - * This function is for underlay. DCN will have new sequence. - * This function will be removed. Need remove it from set_plane_config - */ - -static void tg_program_timing(struct timing_generator *tg, - const struct dc_crtc_timing *timing, - bool use_vbios) -{ - tg_program_timing_generator(tg, timing); -} - /** * unblank_crtc * Call ASIC Control Object to UnBlank CRTC. */ -static void tg_unblank_crtc(struct timing_generator *tg) +static void tgn10_unblank_crtc(struct timing_generator *tg) { struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); @@ -305,7 +291,7 @@ static void tg_unblank_crtc(struct timing_generator *tg) * Call ASIC Control Object to Blank CRTC. */ -static void tg_blank_crtc(struct timing_generator *tg) +static void tgn10_blank_crtc(struct timing_generator *tg) { struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); @@ -324,16 +310,16 @@ static void tg_blank_crtc(struct timing_generator *tg) OTG_BLANK_DATA_DOUBLE_BUFFER_EN, 0); } -static void tg_set_blank(struct timing_generator *tg, +static void tgn10_set_blank(struct timing_generator *tg, bool enable_blanking) { if (enable_blanking) - tg_blank_crtc(tg); + tgn10_blank_crtc(tg); else - tg_unblank_crtc(tg); + tgn10_unblank_crtc(tg); } -static bool tg_is_blanked(struct timing_generator *tg) +static bool tgn10_is_blanked(struct timing_generator *tg) { struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); uint32_t blank_en; @@ -346,7 +332,7 @@ static bool tg_is_blanked(struct timing_generator *tg) return blank_en && blank_state; } -static void enable_optc_clock(struct timing_generator *tg, bool enable) +static void tgn10_enable_optc_clock(struct timing_generator *tg, bool enable) { struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); @@ -388,7 +374,7 @@ static void enable_optc_clock(struct timing_generator *tg, bool enable) * Enable CRTC * Enable CRTC - call ASIC Control Object to enable Timing generator. */ -static bool tg_enable_crtc(struct timing_generator *tg) +static bool tgn10_enable_crtc(struct timing_generator *tg) { /* TODO FPGA wait for answer * OTG_MASTER_UPDATE_MODE != CRTC_MASTER_UPDATE_MODE @@ -415,7 +401,7 @@ static bool tg_enable_crtc(struct timing_generator *tg) } /* disable_crtc - call ASIC Control Object to disable Timing generator. */ -static bool tg_disable_crtc(struct timing_generator *tg) +static bool tgn10_disable_crtc(struct timing_generator *tg) { struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); @@ -438,7 +424,7 @@ static bool tg_disable_crtc(struct timing_generator *tg) } -static void tg_program_blank_color( +static void tgn10_program_blank_color( struct timing_generator *tg, const struct tg_color *black_color) { @@ -464,7 +450,7 @@ static void tg_program_blank_color( * We may move init_hw into DC specific so that we can remove * .disable_vga from upper layer stack */ -static void dcn10_timing_generator_disable_vga( +static void tgn10_disable_vga( struct timing_generator *tg) { struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); @@ -487,7 +473,7 @@ static void dcn10_timing_generator_disable_vga( } } -static bool tg_validate_timing( +static bool tgn10_validate_timing( struct timing_generator *tg, const struct dc_crtc_timing *timing) { @@ -560,7 +546,7 @@ static bool tg_validate_timing( * @return * Counter of frames, which should equal to number of vblanks. */ -static uint32_t tg_get_vblank_counter(struct timing_generator *tg) +static uint32_t tgn10_get_vblank_counter(struct timing_generator *tg) { struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); uint32_t frame_count; @@ -571,7 +557,7 @@ static uint32_t tg_get_vblank_counter(struct timing_generator *tg) return frame_count; } -void dcn10_lock(struct timing_generator *tg) +static void tgn10_lock(struct timing_generator *tg) { struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); @@ -581,7 +567,7 @@ void dcn10_lock(struct timing_generator *tg) OTG_MASTER_UPDATE_LOCK, 1); } -void dcn10_unlock(struct timing_generator *tg) +static void tgn10_unlock(struct timing_generator *tg) { struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); @@ -594,7 +580,7 @@ void dcn10_unlock(struct timing_generator *tg) 20000, 200000);*/ } -static void dcn10_get_position(struct timing_generator *tg, +static void tgn10_get_position(struct timing_generator *tg, struct crtc_position *position) { struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); @@ -607,7 +593,7 @@ static void dcn10_get_position(struct timing_generator *tg, OTG_VERT_COUNT_NOM, &position->nominal_vcount); } -bool dcn10_is_counter_moving(struct timing_generator *tg) +static bool tgn10_is_counter_moving(struct timing_generator *tg) { struct crtc_position position1, position2; @@ -621,7 +607,7 @@ bool dcn10_is_counter_moving(struct timing_generator *tg) return true; } -static bool dcn10_did_triggered_reset_occur( +static bool tgn10_did_triggered_reset_occur( struct timing_generator *tg) { struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); @@ -633,7 +619,7 @@ static bool dcn10_did_triggered_reset_occur( return occurred != 0; } -static void dcn10_enable_reset_trigger(struct timing_generator *tg, int source_tg_inst) +static void tgn10_enable_reset_trigger(struct timing_generator *tg, int source_tg_inst) { struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); uint32_t falling_edge; @@ -667,7 +653,7 @@ static void dcn10_enable_reset_trigger(struct timing_generator *tg, int source_t OTG_FORCE_COUNT_NOW_MODE, 2); } -static void dcn10_disable_reset_trigger(struct timing_generator *tg) +static void tgn10_disable_reset_trigger(struct timing_generator *tg) { struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); @@ -677,7 +663,7 @@ static void dcn10_disable_reset_trigger(struct timing_generator *tg) OTG_FORCE_COUNT_NOW_CLEAR, 1); } -static void dcn10_wait_for_state(struct timing_generator *tg, +static void tgn10_wait_for_state(struct timing_generator *tg, enum crtc_state state) { struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); @@ -700,7 +686,7 @@ static void dcn10_wait_for_state(struct timing_generator *tg, } } -static void set_early_control( +static void tgn10_set_early_control( struct timing_generator *tg, uint32_t early_cntl) { @@ -710,7 +696,7 @@ static void set_early_control( } -static void set_static_screen_control( +static void tgn10_set_static_screen_control( struct timing_generator *tg, uint32_t value) { @@ -739,7 +725,7 @@ static void set_static_screen_control( * ***************************************************************************** */ -void dcn10_timing_generator_set_drr( +static void tgn10_set_drr( struct timing_generator *tg, const struct drr_params *params) { @@ -776,7 +762,7 @@ void dcn10_timing_generator_set_drr( } } -static void dcn10_timing_generator_set_test_pattern( +static void tgn10_set_test_pattern( struct timing_generator *tg, /* TODO: replace 'controller_dp_test_pattern' by 'test_pattern_mode' * because this is not DP-specific (which is probably somewhere in DP @@ -1035,7 +1021,7 @@ static void dcn10_timing_generator_set_test_pattern( } } -void dcn10_timing_generator_get_crtc_scanoutpos( +static void tgn10_get_crtc_scanoutpos( struct timing_generator *tg, uint32_t *v_blank_start, uint32_t *v_blank_end, @@ -1049,7 +1035,7 @@ void dcn10_timing_generator_get_crtc_scanoutpos( OTG_V_BLANK_START, v_blank_start, OTG_V_BLANK_END, v_blank_end); - dcn10_get_position(tg, &position); + tgn10_get_position(tg, &position); *h_position = position.horizontal_count; *v_position = position.vertical_count; @@ -1057,7 +1043,7 @@ void dcn10_timing_generator_get_crtc_scanoutpos( -static void dcn10_enable_stereo(struct timing_generator *tg, +static void tgn10_enable_stereo(struct timing_generator *tg, const struct dc_crtc_timing *timing, struct crtc_stereo_flags *flags) { struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); @@ -1099,17 +1085,17 @@ static void dcn10_enable_stereo(struct timing_generator *tg, OPPBUF_3D_VACT_SPACE1_SIZE, space1_size); } -static void dcn10_program_stereo(struct timing_generator *tg, +static void tgn10_program_stereo(struct timing_generator *tg, const struct dc_crtc_timing *timing, struct crtc_stereo_flags *flags) { if (flags->PROGRAM_STEREO) - dcn10_enable_stereo(tg, timing, flags); + tgn10_enable_stereo(tg, timing, flags); else - dcn10_disable_stereo(tg); + tgn10_disable_stereo(tg); } -static bool dcn10_is_stereo_left_eye(struct timing_generator *tg) +static bool tgn10_is_stereo_left_eye(struct timing_generator *tg) { bool ret = false; uint32_t left_eye = 0; @@ -1126,46 +1112,34 @@ static bool dcn10_is_stereo_left_eye(struct timing_generator *tg) } static struct timing_generator_funcs dcn10_tg_funcs = { - .validate_timing = tg_validate_timing, - .program_timing = tg_program_timing, - .program_global_sync = dcn10_program_global_sync, - .enable_crtc = tg_enable_crtc, - .disable_crtc = tg_disable_crtc, + .validate_timing = tgn10_validate_timing, + .program_timing = tgn10_program_timing, + .program_global_sync = tgn10_program_global_sync, + .enable_crtc = tgn10_enable_crtc, + .disable_crtc = tgn10_disable_crtc, /* used by enable_timing_synchronization. Not need for FPGA */ - .is_counter_moving = dcn10_is_counter_moving, - /* never be called */ - .get_position = dcn10_get_position, - .get_frame_count = tg_get_vblank_counter, - .get_scanoutpos = dcn10_timing_generator_get_crtc_scanoutpos, - .set_early_control = set_early_control, + .is_counter_moving = tgn10_is_counter_moving, + .get_position = tgn10_get_position, + .get_frame_count = tgn10_get_vblank_counter, + .get_scanoutpos = tgn10_get_crtc_scanoutpos, + .set_early_control = tgn10_set_early_control, /* used by enable_timing_synchronization. Not need for FPGA */ - .wait_for_state = dcn10_wait_for_state, - .set_blank = tg_set_blank, - .is_blanked = tg_is_blanked, - /* never be called */ - .set_colors = NULL, - /* this function will be called by .progam_scaler. dcn and dce - * scaler top level functions are different. .program_scaler is - * not need for dcn. within program_scaler, dcn will return - * early before set_overscan_blank_color is reached - */ - .set_overscan_blank_color = NULL, - .set_blank_color = tg_program_blank_color, - /* dcn10_timing_generator_disable_vga */ - .disable_vga = dcn10_timing_generator_disable_vga, - .did_triggered_reset_occur = dcn10_did_triggered_reset_occur, - .enable_reset_trigger = dcn10_enable_reset_trigger, - .disable_reset_trigger = dcn10_disable_reset_trigger, - .lock = dcn10_lock, - .unlock = dcn10_unlock, - /* dcn10_timing_generator_enable_advanced_request*/ - .enable_advanced_request = NULL, - .enable_optc_clock = enable_optc_clock, - .set_drr = dcn10_timing_generator_set_drr, - .set_static_screen_control = set_static_screen_control, - .set_test_pattern = dcn10_timing_generator_set_test_pattern, - .program_stereo = dcn10_program_stereo, - .is_stereo_left_eye = dcn10_is_stereo_left_eye + .wait_for_state = tgn10_wait_for_state, + .set_blank = tgn10_set_blank, + .is_blanked = tgn10_is_blanked, + .set_blank_color = tgn10_program_blank_color, + .disable_vga = tgn10_disable_vga, + .did_triggered_reset_occur = tgn10_did_triggered_reset_occur, + .enable_reset_trigger = tgn10_enable_reset_trigger, + .disable_reset_trigger = tgn10_disable_reset_trigger, + .lock = tgn10_lock, + .unlock = tgn10_unlock, + .enable_optc_clock = tgn10_enable_optc_clock, + .set_drr = tgn10_set_drr, + .set_static_screen_control = tgn10_set_static_screen_control, + .set_test_pattern = tgn10_set_test_pattern, + .program_stereo = tgn10_program_stereo, + .is_stereo_left_eye = tgn10_is_stereo_left_eye }; void dcn10_timing_generator_init(struct dcn10_timing_generator *tgn10) @@ -1181,4 +1155,3 @@ void dcn10_timing_generator_init(struct dcn10_timing_generator *tgn10) tgn10->min_h_sync_width = 8; tgn10->min_v_sync_width = 1; } - diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h index 3b2a20a4b957..e287b2babdc4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h @@ -31,7 +31,7 @@ #define DCN10TG_FROM_TG(tg)\ container_of(tg, struct dcn10_timing_generator, base) -#define TG_COMMON_REG_LIST_DCN1_0(inst) \ +#define TG_COMMON_REG_LIST_DCN(inst) \ SRI(OTG_VSTARTUP_PARAM, OTG, inst),\ SRI(OTG_VUPDATE_PARAM, OTG, inst),\ SRI(OTG_VREADY_PARAM, OTG, inst),\ @@ -64,9 +64,6 @@ SRI(OTG_STATUS_POSITION, OTG, inst),\ SRI(OTG_NOM_VERT_POSITION, OTG, inst),\ SRI(OTG_BLACK_COLOR, OTG, inst),\ - SRI(OTG_TEST_PATTERN_PARAMETERS, OTG, inst),\ - SRI(OTG_TEST_PATTERN_CONTROL, OTG, inst),\ - SRI(OTG_TEST_PATTERN_COLOR, OTG, inst),\ SRI(OTG_CLOCK_CONTROL, OTG, inst),\ SRI(OPTC_INPUT_CLOCK_CONTROL, ODM, inst),\ SRI(OPTC_DATA_SOURCE_SELECT, ODM, inst),\ @@ -76,7 +73,14 @@ SR(D1VGA_CONTROL),\ SR(D2VGA_CONTROL),\ SR(D3VGA_CONTROL),\ - SR(D4VGA_CONTROL),\ + SR(D4VGA_CONTROL) + +#define TG_COMMON_REG_LIST_DCN1_0(inst) \ + TG_COMMON_REG_LIST_DCN(inst),\ + SRI(OTG_TEST_PATTERN_PARAMETERS, OTG, inst),\ + SRI(OTG_TEST_PATTERN_CONTROL, OTG, inst),\ + SRI(OTG_TEST_PATTERN_COLOR, OTG, inst) + struct dcn_tg_registers { uint32_t OTG_VSTARTUP_PARAM; @@ -127,7 +131,7 @@ struct dcn_tg_registers { uint32_t D4VGA_CONTROL; }; -#define TG_COMMON_MASK_SH_LIST_DCN1_0(mask_sh)\ +#define TG_COMMON_MASK_SH_LIST_DCN(mask_sh)\ SF(OTG0_OTG_VSTARTUP_PARAM, VSTARTUP_START, mask_sh),\ SF(OTG0_OTG_VUPDATE_PARAM, VUPDATE_OFFSET, mask_sh),\ SF(OTG0_OTG_VUPDATE_PARAM, VUPDATE_WIDTH, mask_sh),\ @@ -192,17 +196,6 @@ struct dcn_tg_registers { SF(OTG0_OTG_BLACK_COLOR, OTG_BLACK_COLOR_B_CB, mask_sh),\ SF(OTG0_OTG_BLACK_COLOR, OTG_BLACK_COLOR_G_Y, mask_sh),\ SF(OTG0_OTG_BLACK_COLOR, OTG_BLACK_COLOR_R_CR, mask_sh),\ - SF(OTG0_OTG_TEST_PATTERN_PARAMETERS, OTG_TEST_PATTERN_INC0, mask_sh),\ - SF(OTG0_OTG_TEST_PATTERN_PARAMETERS, OTG_TEST_PATTERN_INC1, mask_sh),\ - SF(OTG0_OTG_TEST_PATTERN_PARAMETERS, OTG_TEST_PATTERN_VRES, mask_sh),\ - SF(OTG0_OTG_TEST_PATTERN_PARAMETERS, OTG_TEST_PATTERN_HRES, mask_sh),\ - SF(OTG0_OTG_TEST_PATTERN_PARAMETERS, OTG_TEST_PATTERN_RAMP0_OFFSET, mask_sh),\ - SF(OTG0_OTG_TEST_PATTERN_CONTROL, OTG_TEST_PATTERN_EN, mask_sh),\ - SF(OTG0_OTG_TEST_PATTERN_CONTROL, OTG_TEST_PATTERN_MODE, mask_sh),\ - SF(OTG0_OTG_TEST_PATTERN_CONTROL, OTG_TEST_PATTERN_DYNAMIC_RANGE, mask_sh),\ - SF(OTG0_OTG_TEST_PATTERN_CONTROL, OTG_TEST_PATTERN_COLOR_FORMAT, mask_sh),\ - SF(OTG0_OTG_TEST_PATTERN_COLOR, OTG_TEST_PATTERN_MASK, mask_sh),\ - SF(OTG0_OTG_TEST_PATTERN_COLOR, OTG_TEST_PATTERN_DATA, mask_sh),\ SF(OTG0_OTG_CLOCK_CONTROL, OTG_BUSY, mask_sh),\ SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_EN, mask_sh),\ SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_ON, mask_sh),\ @@ -210,12 +203,26 @@ struct dcn_tg_registers { SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_EN, mask_sh),\ SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_ON, mask_sh),\ SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_GATE_DIS, mask_sh),\ - SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SRC_SEL, mask_sh),\ SF(OPPBUF0_OPPBUF_CONTROL, OPPBUF_ACTIVE_WIDTH, mask_sh),\ SF(OPPBUF0_OPPBUF_3D_PARAMETERS_0, OPPBUF_3D_VACT_SPACE1_SIZE, mask_sh),\ SF(VTG0_CONTROL, VTG0_ENABLE, mask_sh),\ SF(VTG0_CONTROL, VTG0_FP2, mask_sh),\ - SF(VTG0_CONTROL, VTG0_VCOUNT_INIT, mask_sh),\ + SF(VTG0_CONTROL, VTG0_VCOUNT_INIT, mask_sh) + +#define TG_COMMON_MASK_SH_LIST_DCN1_0(mask_sh)\ + TG_COMMON_MASK_SH_LIST_DCN(mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_PARAMETERS, OTG_TEST_PATTERN_INC0, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_PARAMETERS, OTG_TEST_PATTERN_INC1, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_PARAMETERS, OTG_TEST_PATTERN_VRES, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_PARAMETERS, OTG_TEST_PATTERN_HRES, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_PARAMETERS, OTG_TEST_PATTERN_RAMP0_OFFSET, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_CONTROL, OTG_TEST_PATTERN_EN, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_CONTROL, OTG_TEST_PATTERN_MODE, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_CONTROL, OTG_TEST_PATTERN_DYNAMIC_RANGE, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_CONTROL, OTG_TEST_PATTERN_COLOR_FORMAT, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_COLOR, OTG_TEST_PATTERN_MASK, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_COLOR, OTG_TEST_PATTERN_DATA, mask_sh),\ + SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SRC_SEL, mask_sh) #define TG_REG_FIELD_LIST(type) \ type VSTARTUP_START;\ @@ -300,11 +307,12 @@ struct dcn_tg_registers { type OPTC_INPUT_CLK_ON;\ type OPTC_INPUT_CLK_GATE_DIS;\ type OPTC_SRC_SEL;\ + type OPTC_SEG0_SRC_SEL;\ type OPPBUF_ACTIVE_WIDTH;\ type OPPBUF_3D_VACT_SPACE1_SIZE;\ type VTG0_ENABLE;\ type VTG0_FP2;\ - type VTG0_VCOUNT_INIT;\ + type VTG0_VCOUNT_INIT; struct dcn_tg_shift { TG_REG_FIELD_LIST(uint8_t) @@ -336,9 +344,4 @@ struct dcn10_timing_generator { void dcn10_timing_generator_init(struct dcn10_timing_generator *tg); -void dcn10_timing_generator_set_drr(struct timing_generator *tg, - const struct drr_params *params); - -void dcn10_unlock(struct timing_generator *tg); -void dcn10_lock(struct timing_generator *tg); #endif /* __DC_TIMING_GENERATOR_DCN10_H__ */ -- cgit From db3bc05034a4b025651ec17d67d50ea581f6612e Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 28 Jun 2017 16:31:58 -0400 Subject: drm/amd/display: Rename DCN mem input specific function prefixes to min. Also updated relevant registers. Signed-off-by: Dmytro Laktyushkin Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c | 96 ++++++++++------------ .../gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h | 93 +++++++++++++-------- .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 6 +- 3 files changed, 104 insertions(+), 91 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index a58993aa400f..b7ecfad4a8f2 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -38,7 +38,7 @@ #define FN(reg_name, field_name) \ mi->mi_shift->field_name, mi->mi_mask->field_name -static void dcn_mi_set_blank(struct mem_input *mem_input, bool blank) +static void min10_set_blank(struct mem_input *mem_input, bool blank) { struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); uint32_t blank_en = blank ? 1 : 0; @@ -48,7 +48,7 @@ static void dcn_mi_set_blank(struct mem_input *mem_input, bool blank) HUBP_TTU_DISABLE, blank_en); } -static void vready_workaround(struct mem_input *mem_input, +static void min10_vready_workaround(struct mem_input *mem_input, struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest) { uint32_t value = 0; @@ -71,7 +71,7 @@ static void vready_workaround(struct mem_input *mem_input, REG_WRITE(HUBPREQ_DEBUG_DB, value); } -static void program_tiling( +static void min10_program_tiling( struct dcn10_mem_input *mi, const union dc_tiling_info *info, const enum surface_pixel_format pixel_format) @@ -91,7 +91,7 @@ static void program_tiling( PIPE_ALIGNED, info->gfx9.pipe_aligned); } -static void program_size_and_rotation( +static void min10_program_size_and_rotation( struct dcn10_mem_input *mi, enum dc_rotation_angle rotation, enum surface_pixel_format format, @@ -153,7 +153,7 @@ static void program_size_and_rotation( H_MIRROR_EN, mirror); } -static void program_pixel_format( +static void min10_program_pixel_format( struct dcn10_mem_input *mi, enum surface_pixel_format format) { @@ -229,7 +229,7 @@ static void program_pixel_format( /* don't see the need of program the xbar in DCN 1.0 */ } -static bool mem_input_program_surface_flip_and_addr( +static bool min10_program_surface_flip_and_addr( struct mem_input *mem_input, const struct dc_plane_address *address, bool flip_immediate) @@ -369,7 +369,7 @@ static bool mem_input_program_surface_flip_and_addr( return true; } -static void dcc_control(struct mem_input *mem_input, bool enable, +static void min10_dcc_control(struct mem_input *mem_input, bool enable, bool independent_64b_blks) { uint32_t dcc_en = enable ? 1 : 0; @@ -381,13 +381,7 @@ static void dcc_control(struct mem_input *mem_input, bool enable, PRIMARY_SURFACE_DCC_IND_64B_BLK, dcc_ind_64b_blk); } -static void program_control(struct dcn10_mem_input *mi, - struct dc_plane_dcc_param *dcc) -{ - dcc_control(&mi->base, dcc->enable, dcc->grph.independent_64b_blks); -} - -static void mem_input_program_surface_config( +static void min10_program_surface_config( struct mem_input *mem_input, enum surface_pixel_format format, union dc_tiling_info *tiling_info, @@ -398,14 +392,14 @@ static void mem_input_program_surface_config( { struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); - program_control(mi, dcc); - program_tiling(mi, tiling_info, format); - program_size_and_rotation( + min10_dcc_control(mem_input, dcc->enable, dcc->grph.independent_64b_blks); + min10_program_tiling(mi, tiling_info, format); + min10_program_size_and_rotation( mi, rotation, format, plane_size, dcc, horizontal_mirror); - program_pixel_format(mi, format); + min10_program_pixel_format(mi, format); } -static void program_requestor( +static void min10_program_requestor( struct mem_input *mem_input, struct _vcs_dpi_display_rq_regs_st *rq_regs) { @@ -440,7 +434,7 @@ static void program_requestor( } -static void program_deadline( +static void min10_program_deadline( struct mem_input *mem_input, struct _vcs_dpi_display_dlg_regs_st *dlg_attr, struct _vcs_dpi_display_ttu_regs_st *ttu_attr) @@ -552,7 +546,7 @@ static void program_deadline( ttu_attr->refcyc_per_req_delivery_pre_c); } -static void mem_input_setup( +static void min10_setup( struct mem_input *mem_input, struct _vcs_dpi_display_dlg_regs_st *dlg_attr, struct _vcs_dpi_display_ttu_regs_st *ttu_attr, @@ -562,9 +556,9 @@ static void mem_input_setup( /* otg is locked when this func is called. Register are double buffered. * disable the requestors is not needed */ - program_requestor(mem_input, rq_regs); - program_deadline(mem_input, dlg_attr, ttu_attr); - vready_workaround(mem_input, pipe_dest); + min10_program_requestor(mem_input, rq_regs); + min10_program_deadline(mem_input, dlg_attr, ttu_attr); + min10_vready_workaround(mem_input, pipe_dest); } static uint32_t convert_and_clamp( @@ -582,7 +576,7 @@ static uint32_t convert_and_clamp( return ret_val; } -static void program_watermarks( +static void min10_program_watermarks( struct mem_input *mem_input, struct dcn_watermark_set *watermarks, unsigned int refclk_mhz) @@ -811,7 +805,7 @@ static void program_watermarks( #endif } -static void mem_input_program_display_marks( +static void min10_program_display_marks( struct mem_input *mem_input, struct dce_watermarks nbp, struct dce_watermarks stutter, @@ -823,14 +817,14 @@ static void mem_input_program_display_marks( */ } -bool mem_input_is_flip_pending(struct mem_input *mem_input) +static bool min10_is_flip_pending(struct mem_input *mem_input) { - uint32_t update_pending = 0; + uint32_t flip_pending = 0; struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); struct dc_plane_address earliest_inuse_address; REG_GET(DCSURF_FLIP_CONTROL, - SURFACE_UPDATE_PENDING, &update_pending); + SURFACE_FLIP_PENDING, &flip_pending); REG_GET(DCSURF_SURFACE_EARLIEST_INUSE, SURFACE_EARLIEST_INUSE_ADDRESS, &earliest_inuse_address.grph.addr.low_part); @@ -838,7 +832,7 @@ bool mem_input_is_flip_pending(struct mem_input *mem_input) REG_GET(DCSURF_SURFACE_EARLIEST_INUSE_HIGH, SURFACE_EARLIEST_INUSE_ADDRESS_HIGH, &earliest_inuse_address.grph.addr.high_part); - if (update_pending) + if (flip_pending) return true; if (earliest_inuse_address.grph.addr.quad_part != mem_input->request_address.grph.addr.quad_part) @@ -848,7 +842,7 @@ bool mem_input_is_flip_pending(struct mem_input *mem_input) return false; } -static void mem_input_update_dchub( +static void min10_update_dchub( struct mem_input *mem_input, struct dchub_init_data *dh_data) { @@ -911,7 +905,7 @@ struct vm_system_aperture_param { PHYSICAL_ADDRESS_LOC sys_high; }; -static void read_vm_system_aperture_settings(struct dcn10_mem_input *mi, +static void min10_read_vm_system_aperture_settings(struct dcn10_mem_input *mi, struct vm_system_aperture_param *apt) { PHYSICAL_ADDRESS_LOC physical_page_number; @@ -934,7 +928,7 @@ static void read_vm_system_aperture_settings(struct dcn10_mem_input *mi, apt->sys_high.quad_part = (int64_t)logical_addr_high << 18; } -static void set_vm_system_aperture_settings(struct dcn10_mem_input *mi, +static void min10_set_vm_system_aperture_settings(struct dcn10_mem_input *mi, struct vm_system_aperture_param *apt) { PHYSICAL_ADDRESS_LOC mc_vm_apt_default; @@ -970,7 +964,7 @@ struct vm_context0_param { }; /* Temporary read settings, future will get values from kmd directly */ -static void read_vm_context0_settings(struct dcn10_mem_input *mi, +static void min10_read_vm_context0_settings(struct dcn10_mem_input *mi, struct vm_context0_param *vm0) { PHYSICAL_ADDRESS_LOC fb_base; @@ -1013,7 +1007,7 @@ static void read_vm_context0_settings(struct dcn10_mem_input *mi, vm0->pte_base.quad_part -= fb_offset.quad_part; } -static void set_vm_context0_settings(struct dcn10_mem_input *mi, +static void min10_set_vm_context0_settings(struct dcn10_mem_input *mi, const struct vm_context0_param *vm0) { /* pte base */ @@ -1042,7 +1036,7 @@ static void set_vm_context0_settings(struct dcn10_mem_input *mi, VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, vm0->fault_default.low_part); } -void dcn_mem_input_program_pte_vm(struct mem_input *mem_input, +static void min10_program_pte_vm(struct mem_input *mem_input, enum surface_pixel_format format, union dc_tiling_info *tiling_info, enum dc_rotation_angle rotation) @@ -1052,11 +1046,11 @@ void dcn_mem_input_program_pte_vm(struct mem_input *mem_input, struct vm_context0_param vm0 = { { { 0 } } }; - read_vm_system_aperture_settings(mi, &apt); - read_vm_context0_settings(mi, &vm0); + min10_read_vm_system_aperture_settings(mi, &apt); + min10_read_vm_context0_settings(mi, &vm0); - set_vm_system_aperture_settings(mi, &apt); - set_vm_context0_settings(mi, &vm0); + min10_set_vm_system_aperture_settings(mi, &apt); + min10_set_vm_context0_settings(mi, &vm0); /* control: enable VM PTE*/ REG_SET_2(DCN_VM_MX_L1_TLB_CNTL, 0, @@ -1065,20 +1059,18 @@ void dcn_mem_input_program_pte_vm(struct mem_input *mem_input, } static struct mem_input_funcs dcn10_mem_input_funcs = { - .mem_input_program_display_marks = mem_input_program_display_marks, - .allocate_mem_input = NULL, - .free_mem_input = NULL, + .mem_input_program_display_marks = min10_program_display_marks, .mem_input_program_surface_flip_and_addr = - mem_input_program_surface_flip_and_addr, + min10_program_surface_flip_and_addr, .mem_input_program_surface_config = - mem_input_program_surface_config, - .mem_input_is_flip_pending = mem_input_is_flip_pending, - .mem_input_setup = mem_input_setup, - .program_watermarks = program_watermarks, - .mem_input_update_dchub = mem_input_update_dchub, - .mem_input_program_pte_vm = dcn_mem_input_program_pte_vm, - .set_blank = dcn_mi_set_blank, - .dcc_control = dcc_control, + min10_program_surface_config, + .mem_input_is_flip_pending = min10_is_flip_pending, + .mem_input_setup = min10_setup, + .program_watermarks = min10_program_watermarks, + .mem_input_update_dchub = min10_update_dchub, + .mem_input_program_pte_vm = min10_program_pte_vm, + .set_blank = min10_set_blank, + .dcc_control = min10_dcc_control, }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h index 9e2f1bb69958..c3f18bdc2157 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h @@ -31,7 +31,7 @@ container_of(mi, struct dcn10_mem_input, base) -#define MI_DCN10_REG_LIST(id)\ +#define MI_REG_LIST_DCN(id)\ SRI(DCHUBP_CNTL, HUBP, id),\ SRI(HUBPREQ_DEBUG_DB, HUBP, id),\ SRI(DCSURF_ADDR_CONFIG, HUBP, id),\ @@ -93,27 +93,7 @@ SRI(DCN_SURF0_TTU_CNTL1, HUBPREQ, id),\ SRI(DCN_SURF1_TTU_CNTL0, HUBPREQ, id),\ SRI(DCN_SURF1_TTU_CNTL1, HUBPREQ, id),\ - SRI(DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, HUBPREQ, id),\ - SRI(DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB, HUBPREQ, id),\ - SRI(DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB, HUBPREQ, id),\ - SRI(DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_LSB, HUBPREQ, id),\ - SRI(DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB, HUBPREQ, id),\ - SRI(DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB, HUBPREQ, id),\ - SRI(DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, HUBPREQ, id),\ - SRI(DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, HUBPREQ, id),\ SRI(DCN_VM_MX_L1_TLB_CNTL, HUBPREQ, id),\ - SRI(DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, HUBPREQ, id),\ - SRI(DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, HUBPREQ, id),\ - SRI(DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, HUBPREQ, id),\ - SRI(DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, HUBPREQ, id),\ - SRI(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, HUBPREQ, id),\ - SRI(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, HUBPREQ, id),\ - SR(DCHUBBUB_SDPIF_FB_TOP),\ - SR(DCHUBBUB_SDPIF_FB_BASE),\ - SR(DCHUBBUB_SDPIF_FB_OFFSET),\ - SR(DCHUBBUB_SDPIF_AGP_BASE),\ - SR(DCHUBBUB_SDPIF_AGP_BOT),\ - SR(DCHUBBUB_SDPIF_AGP_TOP),\ SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A),\ SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A),\ SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A),\ @@ -152,6 +132,29 @@ MMHUB_SR(MC_VM_SYSTEM_APERTURE_LOW_ADDR),\ MMHUB_SR(MC_VM_SYSTEM_APERTURE_HIGH_ADDR) +#define MI_REG_LIST_DCN10(id)\ + MI_REG_LIST_DCN(id),\ + SRI(DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, HUBPREQ, id),\ + SRI(DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB, HUBPREQ, id),\ + SRI(DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB, HUBPREQ, id),\ + SRI(DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_LSB, HUBPREQ, id),\ + SRI(DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB, HUBPREQ, id),\ + SRI(DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB, HUBPREQ, id),\ + SRI(DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, HUBPREQ, id),\ + SRI(DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, HUBPREQ, id),\ + SRI(DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, HUBPREQ, id),\ + SRI(DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, HUBPREQ, id),\ + SRI(DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, HUBPREQ, id),\ + SRI(DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, HUBPREQ, id),\ + SRI(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, HUBPREQ, id),\ + SRI(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, HUBPREQ, id),\ + SR(DCHUBBUB_SDPIF_FB_TOP),\ + SR(DCHUBBUB_SDPIF_FB_BASE),\ + SR(DCHUBBUB_SDPIF_FB_OFFSET),\ + SR(DCHUBBUB_SDPIF_AGP_BASE),\ + SR(DCHUBBUB_SDPIF_AGP_BOT),\ + SR(DCHUBBUB_SDPIF_AGP_TOP) + struct dcn_mi_registers { uint32_t DCHUBP_CNTL; uint32_t HUBPREQ_DEBUG_DB; @@ -229,12 +232,20 @@ struct dcn_mi_registers { uint32_t DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB; uint32_t DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB; uint32_t DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB; + uint32_t DCN_VM_SYSTEM_APERTURE_LOW_ADDR; + uint32_t DCN_VM_SYSTEM_APERTURE_HIGH_ADDR; uint32_t DCHUBBUB_SDPIF_FB_TOP; uint32_t DCHUBBUB_SDPIF_FB_BASE; uint32_t DCHUBBUB_SDPIF_FB_OFFSET; uint32_t DCHUBBUB_SDPIF_AGP_BASE; uint32_t DCHUBBUB_SDPIF_AGP_BOT; uint32_t DCHUBBUB_SDPIF_AGP_TOP; + uint32_t DCN_VM_FB_LOCATION_TOP; + uint32_t DCN_VM_FB_LOCATION_BASE; + uint32_t DCN_VM_FB_OFFSET; + uint32_t DCN_VM_AGP_BASE; + uint32_t DCN_VM_AGP_BOT; + uint32_t DCN_VM_AGP_TOP; uint32_t DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A; uint32_t DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A; uint32_t DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A; @@ -278,7 +289,7 @@ struct dcn_mi_registers { #define MI_SF(reg_name, field_name, post_fix)\ .field_name = reg_name ## __ ## field_name ## post_fix -#define MI_DCN10_MASK_SH_LIST(mask_sh)\ +#define MI_MASK_SH_LIST_DCN(mask_sh)\ MI_SF(HUBP0_DCHUBP_CNTL, HUBP_BLANK_EN, mask_sh),\ MI_SF(HUBP0_DCHUBP_CNTL, HUBP_TTU_DISABLE, mask_sh),\ MI_SF(HUBP0_DCSURF_ADDR_CONFIG, NUM_PIPES, mask_sh),\ @@ -299,7 +310,7 @@ struct dcn_mi_registers { MI_SF(HUBP0_DCSURF_SURFACE_CONFIG, H_MIRROR_EN, mask_sh),\ MI_SF(HUBP0_DCSURF_SURFACE_CONFIG, SURFACE_PIXEL_FORMAT, mask_sh),\ MI_SF(HUBPREQ0_DCSURF_FLIP_CONTROL, SURFACE_FLIP_TYPE, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_FLIP_CONTROL, SURFACE_UPDATE_PENDING, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_FLIP_CONTROL, SURFACE_FLIP_PENDING, mask_sh),\ MI_SF(HUBPREQ0_DCSURF_FLIP_CONTROL, SURFACE_UPDATE_LOCK, mask_sh),\ MI_SF(HUBPREQ0_DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, PRIMARY_SURFACE_ADDRESS_HIGH, mask_sh),\ MI_SF(HUBPREQ0_DCSURF_PRIMARY_SURFACE_ADDRESS, PRIMARY_SURFACE_ADDRESS, mask_sh),\ @@ -382,6 +393,17 @@ struct dcn_mi_registers { MI_SF(HUBPREQ0_DCN_SURF0_TTU_CNTL0, QoS_LEVEL_FIXED, mask_sh),\ MI_SF(HUBPREQ0_DCN_SURF0_TTU_CNTL0, QoS_RAMP_DISABLE, mask_sh),\ MI_SF(HUBPREQ0_DCN_SURF0_TTU_CNTL1, REFCYC_PER_REQ_DELIVERY_PRE, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_MX_L1_TLB_CNTL, ENABLE_L1_TLB, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_MX_L1_TLB_CNTL, SYSTEM_ACCESS_MODE, mask_sh),\ + MI_SF(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, mask_sh),\ + MI_SF(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE, mask_sh),\ + MI_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE, mask_sh),\ + MI_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, mask_sh),\ + MI_SF(DCHUBBUB_ARB_SAT_LEVEL, DCHUBBUB_ARB_SAT_LEVEL, mask_sh),\ + MI_SF(DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MIN_REQ_OUTSTAND, mask_sh) + +#define MI_MASK_SH_LIST_DCN10(mask_sh)\ + MI_MASK_SH_LIST_DCN(mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB, VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB, VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB, mask_sh),\ @@ -390,11 +412,6 @@ struct dcn_mi_registers { MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB, VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_MX_L1_TLB_CNTL, ENABLE_L1_TLB, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_MX_L1_TLB_CNTL, SYSTEM_ACCESS_MODE, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, MC_VM_SYSTEM_APERTURE_DEFAULT_SYSTEM, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, MC_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, MC_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, MC_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, mask_sh),\ @@ -405,12 +422,9 @@ struct dcn_mi_registers { MI_SF(DCHUBBUB_SDPIF_AGP_BASE, SDPIF_AGP_BASE, mask_sh),\ MI_SF(DCHUBBUB_SDPIF_AGP_BOT, SDPIF_AGP_BOT, mask_sh),\ MI_SF(DCHUBBUB_SDPIF_AGP_TOP, SDPIF_AGP_TOP, mask_sh),\ - MI_SF(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, mask_sh),\ - MI_SF(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE, mask_sh),\ - MI_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE, mask_sh),\ - MI_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, mask_sh),\ - MI_SF(DCHUBBUB_ARB_SAT_LEVEL, DCHUBBUB_ARB_SAT_LEVEL, mask_sh),\ - MI_SF(DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MIN_REQ_OUTSTAND, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, MC_VM_SYSTEM_APERTURE_DEFAULT_SYSTEM, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, mask_sh),\ /* todo: get these from GVM instead of reading registers ourselves */\ MI_SF(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32, PAGE_DIRECTORY_ENTRY_HI32, mask_sh),\ MI_SF(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32, PAGE_DIRECTORY_ENTRY_LO32, mask_sh),\ @@ -444,7 +458,7 @@ struct dcn_mi_registers { type SURFACE_PIXEL_FORMAT;\ type SURFACE_FLIP_TYPE;\ type SURFACE_UPDATE_LOCK;\ - type SURFACE_UPDATE_PENDING;\ + type SURFACE_FLIP_PENDING;\ type PRIMARY_SURFACE_ADDRESS_HIGH;\ type PRIMARY_SURFACE_ADDRESS;\ type SECONDARY_SURFACE_ADDRESS_HIGH;\ @@ -543,12 +557,20 @@ struct dcn_mi_registers { type MC_VM_SYSTEM_APERTURE_LOW_ADDR_LSB;\ type MC_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB;\ type MC_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB;\ + type MC_VM_SYSTEM_APERTURE_LOW_ADDR;\ + type MC_VM_SYSTEM_APERTURE_HIGH_ADDR;\ type SDPIF_FB_TOP;\ type SDPIF_FB_BASE;\ type SDPIF_FB_OFFSET;\ type SDPIF_AGP_BASE;\ type SDPIF_AGP_BOT;\ type SDPIF_AGP_TOP;\ + type FB_TOP;\ + type FB_BASE;\ + type FB_OFFSET;\ + type AGP_BASE;\ + type AGP_BOT;\ + type AGP_TOP;\ type DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST;\ type DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE;\ type DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE;\ @@ -589,5 +611,4 @@ bool dcn10_mem_input_construct( const struct dcn_mi_shift *mi_shift, const struct dcn_mi_mask *mi_mask); - #endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index a0dd75dc1c6d..b0888a86b2ec 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -374,7 +374,7 @@ static const struct bios_registers bios_regs = { #define mi_regs(id)\ [id] = {\ - MI_DCN10_REG_LIST(id)\ + MI_REG_LIST_DCN10(id)\ } @@ -386,11 +386,11 @@ static const struct dcn_mi_registers mi_regs[] = { }; static const struct dcn_mi_shift mi_shift = { - MI_DCN10_MASK_SH_LIST(__SHIFT) + MI_MASK_SH_LIST_DCN10(__SHIFT) }; static const struct dcn_mi_mask mi_mask = { - MI_DCN10_MASK_SH_LIST(_MASK) + MI_MASK_SH_LIST_DCN10(_MASK) }; #define clk_src_regs(index, pllid)\ -- cgit From 13066f9f648084b5016cebfa7930ce4c056ab9d6 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 28 Jun 2017 18:41:22 -0400 Subject: drm/amd/display: Rename DCN opp specific function prefixes to oppn10 Also update relevant registers. Signed-off-by: Dmytro Laktyushkin Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c | 189 ++++++++++----------- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h | 79 ++++----- .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 6 +- 3 files changed, 138 insertions(+), 136 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c index a07401004f44..e6f2220415e8 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c @@ -37,7 +37,7 @@ #define CTX \ oppn10->base.ctx -static void opp_set_regamma_mode( +static void oppn10_set_regamma_mode( struct output_pixel_processor *opp, enum opp_regamma mode) { @@ -167,7 +167,7 @@ static void set_spatial_dither( FMT_RGB_RANDOM_ENABLE, params->flags.RGB_RANDOM); } -static void opp_program_bit_depth_reduction( +static void oppn10_program_bit_depth_reduction( struct output_pixel_processor *opp, const struct bit_depth_reduction_params *params) { @@ -255,7 +255,7 @@ static void opp_set_clamping( } -static void opp_set_dyn_expansion( +static void oppn10_set_dyn_expansion( struct output_pixel_processor *opp, enum dc_color_space color_sp, enum dc_color_depth color_dpth, @@ -304,7 +304,7 @@ static void opp_program_clamping_and_pixel_encoding( set_pixel_encoding(oppn10, params); } -static void opp_program_fmt( +static void oppn10_program_fmt( struct output_pixel_processor *opp, struct bit_depth_reduction_params *fmt_bit_depth, struct clamping_and_pixel_encoding_params *clamping) @@ -316,7 +316,7 @@ static void opp_program_fmt( /* dithering is affected by , hence should be * programmed afterwards */ - opp_program_bit_depth_reduction( + oppn10_program_bit_depth_reduction( opp, fmt_bit_depth); @@ -327,7 +327,7 @@ static void opp_program_fmt( return; } -static void opp_set_output_csc_default( +static void oppn10_set_output_csc_default( struct output_pixel_processor *opp, const struct default_adjustment *default_adjust) { @@ -703,7 +703,7 @@ static void opp_configure_regamma_lut( REG_SET(CM_RGAM_LUT_INDEX, 0, CM_RGAM_LUT_INDEX, 0); } -static void opp_power_on_regamma_lut( +static void oppn10_power_on_regamma_lut( struct output_pixel_processor *opp, bool power_on) { @@ -713,7 +713,78 @@ static void opp_power_on_regamma_lut( } -void opp_set_output_csc_adjustment( + +static void oppn10_program_color_matrix(struct dcn10_opp *oppn10, + const struct out_csc_color_matrix *tbl_entry) +{ + uint32_t mode; + + REG_GET(CM_OCSC_CONTROL, CM_OCSC_MODE, &mode); + + if (tbl_entry == NULL) { + BREAK_TO_DEBUGGER(); + return; + } + + + if (mode == 4) { + /*R*/ + REG_SET_2(CM_OCSC_C11_C12, 0, + CM_OCSC_C11, tbl_entry->regval[0], + CM_OCSC_C12, tbl_entry->regval[1]); + + REG_SET_2(CM_OCSC_C13_C14, 0, + CM_OCSC_C13, tbl_entry->regval[2], + CM_OCSC_C14, tbl_entry->regval[3]); + + /*G*/ + REG_SET_2(CM_OCSC_C21_C22, 0, + CM_OCSC_C21, tbl_entry->regval[4], + CM_OCSC_C22, tbl_entry->regval[5]); + + REG_SET_2(CM_OCSC_C23_C24, 0, + CM_OCSC_C23, tbl_entry->regval[6], + CM_OCSC_C24, tbl_entry->regval[7]); + + /*B*/ + REG_SET_2(CM_OCSC_C31_C32, 0, + CM_OCSC_C31, tbl_entry->regval[8], + CM_OCSC_C32, tbl_entry->regval[9]); + + REG_SET_2(CM_OCSC_C33_C34, 0, + CM_OCSC_C33, tbl_entry->regval[10], + CM_OCSC_C34, tbl_entry->regval[11]); + } else { + /*R*/ + REG_SET_2(CM_COMB_C11_C12, 0, + CM_COMB_C11, tbl_entry->regval[0], + CM_COMB_C12, tbl_entry->regval[1]); + + REG_SET_2(CM_COMB_C13_C14, 0, + CM_COMB_C13, tbl_entry->regval[2], + CM_COMB_C14, tbl_entry->regval[3]); + + /*G*/ + REG_SET_2(CM_COMB_C21_C22, 0, + CM_COMB_C21, tbl_entry->regval[4], + CM_COMB_C22, tbl_entry->regval[5]); + + REG_SET_2(CM_COMB_C23_C24, 0, + CM_COMB_C23, tbl_entry->regval[6], + CM_COMB_C24, tbl_entry->regval[7]); + + /*B*/ + REG_SET_2(CM_COMB_C31_C32, 0, + CM_COMB_C31, tbl_entry->regval[8], + CM_COMB_C32, tbl_entry->regval[9]); + + REG_SET_2(CM_COMB_C33_C34, 0, + CM_COMB_C33, tbl_entry->regval[10], + CM_COMB_C34, tbl_entry->regval[11]); + } +} + +void oppn10_set_output_csc_adjustment( struct output_pixel_processor *opp, const struct out_csc_color_matrix *tbl_entry) { @@ -752,7 +823,7 @@ void opp_set_output_csc_adjustment( */ REG_SET(CM_OCSC_CONTROL, 0, CM_OCSC_MODE, ocsc_mode); - program_color_matrix(oppn10, tbl_entry); + oppn10_program_color_matrix(oppn10, tbl_entry); } static void opp_program_regamma_lut( @@ -778,20 +849,18 @@ static void opp_program_regamma_lut( } - - -static bool opp_set_regamma_pwl( +static bool oppn10_set_regamma_pwl( struct output_pixel_processor *opp, const struct pwl_params *params) { struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); - opp_power_on_regamma_lut(opp, true); + oppn10_power_on_regamma_lut(opp, true); opp_configure_regamma_lut(opp, oppn10->is_write_to_ram_a_safe); if (oppn10->is_write_to_ram_a_safe) - opp_program_regamma_luta_settings(opp, params); + opp_program_regamma_luta_settings(opp, params); else - opp_program_regamma_lutb_settings(opp, params); + opp_program_regamma_lutb_settings(opp, params); opp_program_regamma_lut( opp, params->rgb_resulted, params->hw_points_num); @@ -799,7 +868,7 @@ static bool opp_set_regamma_pwl( return true; } -static void opp_set_stereo_polarity( +static void oppn10_set_stereo_polarity( struct output_pixel_processor *opp, bool enable, bool rightEyePolarity) { @@ -819,15 +888,15 @@ static void dcn10_opp_destroy(struct output_pixel_processor **opp) } static struct opp_funcs dcn10_opp_funcs = { - .opp_power_on_regamma_lut = opp_power_on_regamma_lut, - .opp_set_csc_adjustment = opp_set_output_csc_adjustment, - .opp_set_csc_default = opp_set_output_csc_default, - .opp_set_dyn_expansion = opp_set_dyn_expansion, - .opp_program_regamma_pwl = opp_set_regamma_pwl, - .opp_set_regamma_mode = opp_set_regamma_mode, - .opp_program_fmt = opp_program_fmt, - .opp_program_bit_depth_reduction = opp_program_bit_depth_reduction, - .opp_set_stereo_polarity = opp_set_stereo_polarity, + .opp_power_on_regamma_lut = oppn10_power_on_regamma_lut, + .opp_set_csc_adjustment = oppn10_set_output_csc_adjustment, + .opp_set_csc_default = oppn10_set_output_csc_default, + .opp_set_dyn_expansion = oppn10_set_dyn_expansion, + .opp_program_regamma_pwl = oppn10_set_regamma_pwl, + .opp_set_regamma_mode = oppn10_set_regamma_mode, + .opp_program_fmt = oppn10_program_fmt, + .opp_program_bit_depth_reduction = oppn10_program_bit_depth_reduction, + .opp_set_stereo_polarity = oppn10_set_stereo_polarity, .opp_destroy = dcn10_opp_destroy }; @@ -847,73 +916,3 @@ void dcn10_opp_construct(struct dcn10_opp *oppn10, oppn10->opp_mask = opp_mask; } - -void program_color_matrix(struct dcn10_opp *oppn10, - const struct out_csc_color_matrix *tbl_entry) -{ - uint32_t mode; - - REG_GET(CM_OCSC_CONTROL, CM_OCSC_MODE, &mode); - - if (tbl_entry == NULL) { - BREAK_TO_DEBUGGER(); - return; - } - - - if (mode == 4) { - /*R*/ - REG_SET_2(CM_OCSC_C11_C12, 0, - CM_OCSC_C11, tbl_entry->regval[0], - CM_OCSC_C12, tbl_entry->regval[1]); - - REG_SET_2(CM_OCSC_C13_C14, 0, - CM_OCSC_C13, tbl_entry->regval[2], - CM_OCSC_C14, tbl_entry->regval[3]); - - /*G*/ - REG_SET_2(CM_OCSC_C21_C22, 0, - CM_OCSC_C21, tbl_entry->regval[4], - CM_OCSC_C22, tbl_entry->regval[5]); - - REG_SET_2(CM_OCSC_C23_C24, 0, - CM_OCSC_C23, tbl_entry->regval[6], - CM_OCSC_C24, tbl_entry->regval[7]); - - /*B*/ - REG_SET_2(CM_OCSC_C31_C32, 0, - CM_OCSC_C31, tbl_entry->regval[8], - CM_OCSC_C32, tbl_entry->regval[9]); - - REG_SET_2(CM_OCSC_C33_C34, 0, - CM_OCSC_C33, tbl_entry->regval[10], - CM_OCSC_C34, tbl_entry->regval[11]); - } else { - /*R*/ - REG_SET_2(CM_COMB_C11_C12, 0, - CM_COMB_C11, tbl_entry->regval[0], - CM_COMB_C12, tbl_entry->regval[1]); - - REG_SET_2(CM_COMB_C13_C14, 0, - CM_COMB_C13, tbl_entry->regval[2], - CM_COMB_C14, tbl_entry->regval[3]); - - /*G*/ - REG_SET_2(CM_COMB_C21_C22, 0, - CM_COMB_C21, tbl_entry->regval[4], - CM_COMB_C22, tbl_entry->regval[5]); - - REG_SET_2(CM_COMB_C23_C24, 0, - CM_COMB_C23, tbl_entry->regval[6], - CM_COMB_C24, tbl_entry->regval[7]); - - /*B*/ - REG_SET_2(CM_COMB_C31_C32, 0, - CM_COMB_C31, tbl_entry->regval[8], - CM_COMB_C32, tbl_entry->regval[9]); - - REG_SET_2(CM_COMB_C33_C34, 0, - CM_COMB_C33, tbl_entry->regval[10], - CM_COMB_C34, tbl_entry->regval[11]); - } -} diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h index 9cc4c5feaddf..eb99c311104f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h @@ -33,7 +33,19 @@ #define OPP_SF(reg_name, field_name, post_fix)\ .field_name = reg_name ## __ ## field_name ## post_fix -#define OPP_DCN10_REG_LIST(id) \ +#define OPP_REG_LIST_DCN(id) \ + SRI(OBUF_CONTROL, DSCL, id), \ + SRI(FMT_BIT_DEPTH_CONTROL, FMT, id), \ + SRI(FMT_CONTROL, FMT, id), \ + SRI(FMT_DITHER_RAND_R_SEED, FMT, id), \ + SRI(FMT_DITHER_RAND_G_SEED, FMT, id), \ + SRI(FMT_DITHER_RAND_B_SEED, FMT, id), \ + SRI(FMT_CLAMP_CNTL, FMT, id), \ + SRI(FMT_DYNAMIC_EXP_CNTL, FMT, id), \ + SRI(FMT_MAP420_MEMORY_CONTROL, FMT, id) + +#define OPP_REG_LIST_DCN10(id) \ + OPP_REG_LIST_DCN(id), \ SRI(CM_OCSC_C11_C12, CM, id), \ SRI(CM_OCSC_C13_C14, CM, id), \ SRI(CM_OCSC_C21_C22, CM, id), \ @@ -48,15 +60,6 @@ SRI(CM_COMB_C33_C34, CM, id), \ SRI(CM_RGAM_LUT_WRITE_EN_MASK, CM, id), \ SRI(CM_RGAM_CONTROL, CM, id), \ - SRI(OBUF_CONTROL, DSCL, id), \ - SRI(FMT_BIT_DEPTH_CONTROL, FMT, id), \ - SRI(FMT_CONTROL, FMT, id), \ - SRI(FMT_DITHER_RAND_R_SEED, FMT, id), \ - SRI(FMT_DITHER_RAND_G_SEED, FMT, id), \ - SRI(FMT_DITHER_RAND_B_SEED, FMT, id), \ - SRI(FMT_CLAMP_CNTL, FMT, id), \ - SRI(FMT_DYNAMIC_EXP_CNTL, FMT, id), \ - SRI(FMT_MAP420_MEMORY_CONTROL, FMT, id), \ SRI(CM_OCSC_CONTROL, CM, id), \ SRI(CM_RGAM_RAMB_START_CNTL_B, CM, id), \ SRI(CM_RGAM_RAMB_START_CNTL_G, CM, id), \ @@ -120,7 +123,34 @@ SRI(CM_MEM_PWR_CTRL, CM, id), \ SRI(CM_RGAM_LUT_DATA, CM, id) -#define OPP_DCN10_MASK_SH_LIST(mask_sh) \ + +#define OPP_MASK_SH_LIST_DCN(mask_sh) \ + OPP_SF(DSCL0_OBUF_CONTROL, OBUF_BYPASS, mask_sh), \ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN, mask_sh), \ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_DEPTH, mask_sh), \ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_MODE, mask_sh), \ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_EN, mask_sh), \ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_MODE, mask_sh), \ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_DEPTH, mask_sh), \ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_EN, mask_sh), \ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_HIGHPASS_RANDOM_ENABLE, mask_sh), \ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_FRAME_RANDOM_ENABLE, mask_sh), \ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_RGB_RANDOM_ENABLE, mask_sh), \ + OPP_SF(FMT0_FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, mask_sh), \ + OPP_SF(FMT0_FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, mask_sh), \ + OPP_SF(FMT0_FMT_DITHER_RAND_R_SEED, FMT_RAND_R_SEED, mask_sh), \ + OPP_SF(FMT0_FMT_DITHER_RAND_G_SEED, FMT_RAND_G_SEED, mask_sh), \ + OPP_SF(FMT0_FMT_DITHER_RAND_B_SEED, FMT_RAND_B_SEED, mask_sh), \ + OPP_SF(FMT0_FMT_CONTROL, FMT_PIXEL_ENCODING, mask_sh), \ + OPP_SF(FMT0_FMT_CLAMP_CNTL, FMT_CLAMP_DATA_EN, mask_sh), \ + OPP_SF(FMT0_FMT_CLAMP_CNTL, FMT_CLAMP_COLOR_FORMAT, mask_sh), \ + OPP_SF(FMT0_FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN, mask_sh), \ + OPP_SF(FMT0_FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE, mask_sh), \ + OPP_SF(FMT0_FMT_MAP420_MEMORY_CONTROL, FMT_MAP420MEM_PWR_FORCE, mask_sh) + +#define OPP_MASK_SH_LIST_DCN10(mask_sh) \ + OPP_MASK_SH_LIST_DCN(mask_sh), \ + OPP_SF(DSCL0_OBUF_CONTROL, OBUF_H_2X_UPSCALE_EN, mask_sh), \ OPP_SF(CM0_CM_OCSC_C11_C12, CM_OCSC_C11, mask_sh), \ OPP_SF(CM0_CM_OCSC_C11_C12, CM_OCSC_C12, mask_sh), \ OPP_SF(CM0_CM_OCSC_C13_C14, CM_OCSC_C13, mask_sh), \ @@ -146,29 +176,6 @@ OPP_SF(CM0_CM_COMB_C33_C34, CM_COMB_C33, mask_sh), \ OPP_SF(CM0_CM_COMB_C33_C34, CM_COMB_C34, mask_sh), \ OPP_SF(CM0_CM_RGAM_CONTROL, CM_RGAM_LUT_MODE, mask_sh), \ - OPP_SF(DSCL0_OBUF_CONTROL, OBUF_BYPASS, mask_sh), \ - OPP_SF(DSCL0_OBUF_CONTROL, OBUF_H_2X_UPSCALE_EN, mask_sh), \ - OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN, mask_sh), \ - OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_DEPTH, mask_sh), \ - OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_MODE, mask_sh), \ - OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_EN, mask_sh), \ - OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_MODE, mask_sh), \ - OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_DEPTH, mask_sh), \ - OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_EN, mask_sh), \ - OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_HIGHPASS_RANDOM_ENABLE, mask_sh), \ - OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_FRAME_RANDOM_ENABLE, mask_sh), \ - OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_RGB_RANDOM_ENABLE, mask_sh), \ - OPP_SF(FMT0_FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, mask_sh), \ - OPP_SF(FMT0_FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, mask_sh), \ - OPP_SF(FMT0_FMT_DITHER_RAND_R_SEED, FMT_RAND_R_SEED, mask_sh), \ - OPP_SF(FMT0_FMT_DITHER_RAND_G_SEED, FMT_RAND_G_SEED, mask_sh), \ - OPP_SF(FMT0_FMT_DITHER_RAND_B_SEED, FMT_RAND_B_SEED, mask_sh), \ - OPP_SF(FMT0_FMT_CONTROL, FMT_PIXEL_ENCODING, mask_sh), \ - OPP_SF(FMT0_FMT_CLAMP_CNTL, FMT_CLAMP_DATA_EN, mask_sh), \ - OPP_SF(FMT0_FMT_CLAMP_CNTL, FMT_CLAMP_COLOR_FORMAT, mask_sh), \ - OPP_SF(FMT0_FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN, mask_sh), \ - OPP_SF(FMT0_FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE, mask_sh), \ - OPP_SF(FMT0_FMT_MAP420_MEMORY_CONTROL, FMT_MAP420MEM_PWR_FORCE, mask_sh), \ OPP_SF(CM0_CM_OCSC_CONTROL, CM_OCSC_MODE, mask_sh), \ OPP_SF(CM0_CM_RGAM_RAMB_START_CNTL_B, CM_RGAM_RAMB_EXP_REGION_START_B, mask_sh), \ OPP_SF(CM0_CM_RGAM_RAMB_START_CNTL_B, CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B, mask_sh), \ @@ -691,8 +698,4 @@ void dcn10_opp_construct(struct dcn10_opp *oppn10, const struct dcn10_opp_shift *opp_shift, const struct dcn10_opp_mask *opp_mask); -void program_color_matrix( - struct dcn10_opp *oppn10, - const struct out_csc_color_matrix *tbl_entry); - #endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index b0888a86b2ec..898b618798d5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -286,7 +286,7 @@ static const struct dcn10_ipp_mask ipp_mask = { #define opp_regs(id)\ [id] = {\ - OPP_DCN10_REG_LIST(id),\ + OPP_REG_LIST_DCN10(id),\ } static const struct dcn10_opp_registers opp_regs[] = { @@ -297,11 +297,11 @@ static const struct dcn10_opp_registers opp_regs[] = { }; static const struct dcn10_opp_shift opp_shift = { - OPP_DCN10_MASK_SH_LIST(__SHIFT) + OPP_MASK_SH_LIST_DCN10(__SHIFT) }; static const struct dcn10_opp_mask opp_mask = { - OPP_DCN10_MASK_SH_LIST(_MASK), + OPP_MASK_SH_LIST_DCN10(_MASK), }; #define tf_regs(id)\ -- cgit From 35ce37d6a4d140ba7e2870d7c0bc4a6b866f1d8d Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 28 Jun 2017 18:58:27 -0400 Subject: drm/amd/display: Enable ipp compilation Update relevant registers Signed-off-by: Dmytro Laktyushkin Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c | 19 ++--- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h | 91 +++++++++++----------- .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 6 +- 3 files changed, 54 insertions(+), 62 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c index 1e7a55d9e9ec..a09226c0d903 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c @@ -421,7 +421,10 @@ static void dcn10_ipp_enable_cm_block( struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); REG_UPDATE(DPP_CONTROL, DPP_CLOCK_ENABLE, 1); - REG_UPDATE(CM_CONTROL, CM_BYPASS_EN, 0); + if (ippn10->ipp_mask->CM_BYPASS_EN) + REG_UPDATE(CM_CONTROL, CM_BYPASS_EN, 0); + else + REG_UPDATE(CM_CONTROL, CM_BYPASS, 0); } @@ -484,7 +487,7 @@ static bool dcn10_cursor_program_control( REG_UPDATE_2(CURSOR0_CONTROL, CUR0_MODE, color_format, - CUR0_INVERT_MODE, 0); + CUR0_EXPANSION_MODE, 0); if (color_format == CURSOR_MODE_MONO) { /* todo: clarify what to program these to */ @@ -501,18 +504,6 @@ static bool dcn10_cursor_program_control( ALPHA_EN, 1, FORMAT_EXPANSION_MODE, 0); - REG_UPDATE(CURSOR0_CONTROL, - CUR0_EXPANSION_MODE, 0); - - if (0 /*attributes->attribute_flags.bits.MIN_MAX_INVERT*/) { - REG_UPDATE(CURSOR0_CONTROL, - CUR0_MAX, - 0 /* TODO */); - REG_UPDATE(CURSOR0_CONTROL, - CUR0_MIN, - 0 /* TODO */); - } - return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h index 511993519740..d608abf0e822 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h @@ -31,7 +31,7 @@ #define TO_DCN10_IPP(ipp)\ container_of(ipp, struct dcn10_ipp, base) -#define IPP_DCN10_REG_LIST(id) \ +#define IPP_REG_LIST_DCN(id) \ SRI(CM_ICSC_CONTROL, CM, id), \ SRI(CM_ICSC_C11_C12, CM, id), \ SRI(CM_ICSC_C13_C14, CM, id), \ @@ -39,12 +39,6 @@ SRI(CM_ICSC_C23_C24, CM, id), \ SRI(CM_ICSC_C31_C32, CM, id), \ SRI(CM_ICSC_C33_C34, CM, id), \ - SRI(CM_COMA_C11_C12, CM, id), \ - SRI(CM_COMA_C13_C14, CM, id), \ - SRI(CM_COMA_C21_C22, CM, id), \ - SRI(CM_COMA_C23_C24, CM, id), \ - SRI(CM_COMA_C31_C32, CM, id), \ - SRI(CM_COMA_C33_C34, CM, id), \ SRI(CM_DGAM_RAMB_START_CNTL_B, CM, id), \ SRI(CM_DGAM_RAMB_START_CNTL_G, CM, id), \ SRI(CM_DGAM_RAMB_START_CNTL_R, CM, id), \ @@ -86,22 +80,31 @@ SRI(CM_DGAM_RAMA_REGION_12_13, CM, id), \ SRI(CM_DGAM_RAMA_REGION_14_15, CM, id), \ SRI(CM_MEM_PWR_CTRL, CM, id), \ - SRI(CM_IGAM_LUT_RW_CONTROL, CM, id), \ - SRI(CM_IGAM_LUT_RW_INDEX, CM, id), \ - SRI(CM_IGAM_LUT_SEQ_COLOR, CM, id), \ SRI(CM_DGAM_LUT_WRITE_EN_MASK, CM, id), \ SRI(CM_DGAM_LUT_INDEX, CM, id), \ SRI(CM_DGAM_LUT_DATA, CM, id), \ SRI(CM_CONTROL, CM, id), \ SRI(CM_DGAM_CONTROL, CM, id), \ - SRI(CM_IGAM_CONTROL, CM, id), \ + SRI(FORMAT_CONTROL, CNVC_CFG, id), \ SRI(DPP_CONTROL, DPP_TOP, id), \ SRI(CURSOR_SETTINS, HUBPREQ, id), \ SRI(CNVC_SURFACE_PIXEL_FORMAT, CNVC_CFG, id), \ SRI(CURSOR0_CONTROL, CNVC_CUR, id), \ SRI(CURSOR0_COLOR0, CNVC_CUR, id), \ - SRI(CURSOR0_COLOR1, CNVC_CUR, id), \ - SRI(FORMAT_CONTROL, CNVC_CFG, id), \ + SRI(CURSOR0_COLOR1, CNVC_CUR, id) + +#define IPP_REG_LIST_DCN10(id) \ + IPP_REG_LIST_DCN(id), \ + SRI(CM_IGAM_CONTROL, CM, id), \ + SRI(CM_COMA_C11_C12, CM, id), \ + SRI(CM_COMA_C13_C14, CM, id), \ + SRI(CM_COMA_C21_C22, CM, id), \ + SRI(CM_COMA_C23_C24, CM, id), \ + SRI(CM_COMA_C31_C32, CM, id), \ + SRI(CM_COMA_C33_C34, CM, id), \ + SRI(CM_IGAM_LUT_RW_CONTROL, CM, id), \ + SRI(CM_IGAM_LUT_RW_INDEX, CM, id), \ + SRI(CM_IGAM_LUT_SEQ_COLOR, CM, id), \ SRI(CURSOR_SURFACE_ADDRESS_HIGH, CURSOR, id), \ SRI(CURSOR_SURFACE_ADDRESS, CURSOR, id), \ SRI(CURSOR_SIZE, CURSOR, id), \ @@ -113,7 +116,7 @@ #define IPP_SF(reg_name, field_name, post_fix)\ .field_name = reg_name ## __ ## field_name ## post_fix -#define IPP_DCN10_MASK_SH_LIST(mask_sh) \ +#define IPP_MASK_SH_LIST_DCN(mask_sh) \ IPP_SF(CM0_CM_ICSC_CONTROL, CM_ICSC_MODE, mask_sh), \ IPP_SF(CM0_CM_ICSC_C11_C12, CM_ICSC_C11, mask_sh), \ IPP_SF(CM0_CM_ICSC_C11_C12, CM_ICSC_C12, mask_sh), \ @@ -127,18 +130,6 @@ IPP_SF(CM0_CM_ICSC_C31_C32, CM_ICSC_C32, mask_sh), \ IPP_SF(CM0_CM_ICSC_C33_C34, CM_ICSC_C33, mask_sh), \ IPP_SF(CM0_CM_ICSC_C33_C34, CM_ICSC_C34, mask_sh), \ - IPP_SF(CM0_CM_COMA_C11_C12, CM_COMA_C11, mask_sh), \ - IPP_SF(CM0_CM_COMA_C11_C12, CM_COMA_C12, mask_sh), \ - IPP_SF(CM0_CM_COMA_C13_C14, CM_COMA_C13, mask_sh), \ - IPP_SF(CM0_CM_COMA_C13_C14, CM_COMA_C14, mask_sh), \ - IPP_SF(CM0_CM_COMA_C21_C22, CM_COMA_C21, mask_sh), \ - IPP_SF(CM0_CM_COMA_C21_C22, CM_COMA_C22, mask_sh), \ - IPP_SF(CM0_CM_COMA_C23_C24, CM_COMA_C23, mask_sh), \ - IPP_SF(CM0_CM_COMA_C23_C24, CM_COMA_C24, mask_sh), \ - IPP_SF(CM0_CM_COMA_C31_C32, CM_COMA_C31, mask_sh), \ - IPP_SF(CM0_CM_COMA_C31_C32, CM_COMA_C32, mask_sh), \ - IPP_SF(CM0_CM_COMA_C33_C34, CM_COMA_C33, mask_sh), \ - IPP_SF(CM0_CM_COMA_C33_C34, CM_COMA_C34, mask_sh), \ IPP_SF(CM0_CM_DGAM_RAMB_START_CNTL_B, CM_DGAM_RAMB_EXP_REGION_START_B, mask_sh), \ IPP_SF(CM0_CM_DGAM_RAMB_START_CNTL_B, CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_B, mask_sh), \ IPP_SF(CM0_CM_DGAM_RAMB_START_CNTL_G, CM_DGAM_RAMB_EXP_REGION_START_G, mask_sh), \ @@ -240,37 +231,46 @@ IPP_SF(CM0_CM_DGAM_RAMA_REGION_14_15, CM_DGAM_RAMA_EXP_REGION15_LUT_OFFSET, mask_sh), \ IPP_SF(CM0_CM_DGAM_RAMA_REGION_14_15, CM_DGAM_RAMA_EXP_REGION15_NUM_SEGMENTS, mask_sh), \ IPP_SF(CM0_CM_MEM_PWR_CTRL, SHARED_MEM_PWR_DIS, mask_sh), \ - IPP_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_DGAM_CONFIG_STATUS, mask_sh), \ - IPP_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_HOST_EN, mask_sh), \ - IPP_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_RW_MODE, mask_sh), \ - IPP_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_SEL, mask_sh), \ - IPP_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_WRITE_EN_MASK, mask_sh), \ - IPP_SF(CM0_CM_IGAM_LUT_RW_INDEX, CM_IGAM_LUT_RW_INDEX, mask_sh), \ - IPP_SF(CM0_CM_IGAM_LUT_SEQ_COLOR, CM_IGAM_LUT_SEQ_COLOR, mask_sh), \ IPP_SF(CM0_CM_DGAM_LUT_WRITE_EN_MASK, CM_DGAM_LUT_WRITE_EN_MASK, mask_sh), \ IPP_SF(CM0_CM_DGAM_LUT_WRITE_EN_MASK, CM_DGAM_LUT_WRITE_SEL, mask_sh), \ IPP_SF(CM0_CM_DGAM_LUT_INDEX, CM_DGAM_LUT_INDEX, mask_sh), \ IPP_SF(CM0_CM_DGAM_LUT_DATA, CM_DGAM_LUT_DATA, mask_sh), \ IPP_SF(DPP_TOP0_DPP_CONTROL, DPP_CLOCK_ENABLE, mask_sh), \ - IPP_SF(CM0_CM_CONTROL, CM_BYPASS_EN, mask_sh), \ IPP_SF(CNVC_CFG0_CNVC_SURFACE_PIXEL_FORMAT, CNVC_SURFACE_PIXEL_FORMAT, mask_sh), \ IPP_SF(CNVC_CFG0_FORMAT_CONTROL, CNVC_BYPASS, mask_sh), \ IPP_SF(CNVC_CFG0_FORMAT_CONTROL, ALPHA_EN, mask_sh), \ IPP_SF(CNVC_CFG0_FORMAT_CONTROL, FORMAT_EXPANSION_MODE, mask_sh), \ IPP_SF(CM0_CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, mask_sh), \ - IPP_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, mask_sh), \ - IPP_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_LUT_FORMAT_R, mask_sh), \ - IPP_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_LUT_FORMAT_G, mask_sh), \ - IPP_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_LUT_FORMAT_B, mask_sh), \ IPP_SF(HUBPREQ0_CURSOR_SETTINS, CURSOR0_DST_Y_OFFSET, mask_sh), \ IPP_SF(HUBPREQ0_CURSOR_SETTINS, CURSOR0_CHUNK_HDL_ADJUST, mask_sh), \ IPP_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_MODE, mask_sh), \ - IPP_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_INVERT_MODE, mask_sh), \ IPP_SF(CNVC_CUR0_CURSOR0_COLOR0, CUR0_COLOR0, mask_sh), \ IPP_SF(CNVC_CUR0_CURSOR0_COLOR1, CUR0_COLOR1, mask_sh), \ IPP_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_EXPANSION_MODE, mask_sh), \ - IPP_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_MAX, mask_sh), \ - IPP_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_MIN, mask_sh), \ + IPP_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_ENABLE, mask_sh) + +#define IPP_MASK_SH_LIST_DCN10(mask_sh) \ + IPP_MASK_SH_LIST_DCN(mask_sh),\ + IPP_SF(CM0_CM_COMA_C11_C12, CM_COMA_C11, mask_sh), \ + IPP_SF(CM0_CM_COMA_C11_C12, CM_COMA_C12, mask_sh), \ + IPP_SF(CM0_CM_COMA_C13_C14, CM_COMA_C13, mask_sh), \ + IPP_SF(CM0_CM_COMA_C13_C14, CM_COMA_C14, mask_sh), \ + IPP_SF(CM0_CM_COMA_C21_C22, CM_COMA_C21, mask_sh), \ + IPP_SF(CM0_CM_COMA_C21_C22, CM_COMA_C22, mask_sh), \ + IPP_SF(CM0_CM_COMA_C23_C24, CM_COMA_C23, mask_sh), \ + IPP_SF(CM0_CM_COMA_C23_C24, CM_COMA_C24, mask_sh), \ + IPP_SF(CM0_CM_COMA_C31_C32, CM_COMA_C31, mask_sh), \ + IPP_SF(CM0_CM_COMA_C31_C32, CM_COMA_C32, mask_sh), \ + IPP_SF(CM0_CM_COMA_C33_C34, CM_COMA_C33, mask_sh), \ + IPP_SF(CM0_CM_COMA_C33_C34, CM_COMA_C34, mask_sh), \ + IPP_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_DGAM_CONFIG_STATUS, mask_sh), \ + IPP_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_HOST_EN, mask_sh), \ + IPP_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_RW_MODE, mask_sh), \ + IPP_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_SEL, mask_sh), \ + IPP_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_WRITE_EN_MASK, mask_sh), \ + IPP_SF(CM0_CM_IGAM_LUT_RW_INDEX, CM_IGAM_LUT_RW_INDEX, mask_sh), \ + IPP_SF(CM0_CM_IGAM_LUT_SEQ_COLOR, CM_IGAM_LUT_SEQ_COLOR, mask_sh), \ + IPP_SF(CM0_CM_CONTROL, CM_BYPASS_EN, mask_sh), \ IPP_SF(CURSOR0_CURSOR_SURFACE_ADDRESS_HIGH, CURSOR_SURFACE_ADDRESS_HIGH, mask_sh), \ IPP_SF(CURSOR0_CURSOR_SURFACE_ADDRESS, CURSOR_SURFACE_ADDRESS, mask_sh), \ IPP_SF(CURSOR0_CURSOR_SIZE, CURSOR_WIDTH, mask_sh), \ @@ -279,12 +279,15 @@ IPP_SF(CURSOR0_CURSOR_CONTROL, CURSOR_PITCH, mask_sh), \ IPP_SF(CURSOR0_CURSOR_CONTROL, CURSOR_LINES_PER_CHUNK, mask_sh), \ IPP_SF(CURSOR0_CURSOR_CONTROL, CURSOR_ENABLE, mask_sh), \ - IPP_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_ENABLE, mask_sh), \ IPP_SF(CURSOR0_CURSOR_POSITION, CURSOR_X_POSITION, mask_sh), \ IPP_SF(CURSOR0_CURSOR_POSITION, CURSOR_Y_POSITION, mask_sh), \ IPP_SF(CURSOR0_CURSOR_HOT_SPOT, CURSOR_HOT_SPOT_X, mask_sh), \ IPP_SF(CURSOR0_CURSOR_HOT_SPOT, CURSOR_HOT_SPOT_Y, mask_sh), \ IPP_SF(CURSOR0_CURSOR_DST_OFFSET, CURSOR_DST_X_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, mask_sh), \ + IPP_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_LUT_FORMAT_R, mask_sh), \ + IPP_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_LUT_FORMAT_G, mask_sh), \ + IPP_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_LUT_FORMAT_B, mask_sh), \ IPP_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_INPUT_FORMAT, mask_sh), \ IPP_SF(CNVC_CFG0_FORMAT_CONTROL, OUTPUT_FP, mask_sh) @@ -431,6 +434,7 @@ type CM_DGAM_LUT_DATA; \ type DPP_CLOCK_ENABLE; \ type CM_BYPASS_EN; \ + type CM_BYPASS; \ type CNVC_SURFACE_PIXEL_FORMAT; \ type CNVC_BYPASS; \ type ALPHA_EN; \ @@ -440,12 +444,9 @@ type CURSOR0_DST_Y_OFFSET; \ type CURSOR0_CHUNK_HDL_ADJUST; \ type CUR0_MODE; \ - type CUR0_INVERT_MODE; \ type CUR0_COLOR0; \ type CUR0_COLOR1; \ type CUR0_EXPANSION_MODE; \ - type CUR0_MAX; \ - type CUR0_MIN; \ type CURSOR_SURFACE_ADDRESS_HIGH; \ type CURSOR_SURFACE_ADDRESS; \ type CURSOR_WIDTH; \ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 898b618798d5..fcea49e9f665 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -266,7 +266,7 @@ static const struct dce110_link_enc_registers link_enc_regs[] = { #define ipp_regs(id)\ [id] = {\ - IPP_DCN10_REG_LIST(id),\ + IPP_REG_LIST_DCN10(id),\ } static const struct dcn10_ipp_registers ipp_regs[] = { @@ -277,11 +277,11 @@ static const struct dcn10_ipp_registers ipp_regs[] = { }; static const struct dcn10_ipp_shift ipp_shift = { - IPP_DCN10_MASK_SH_LIST(__SHIFT) + IPP_MASK_SH_LIST_DCN10(__SHIFT) }; static const struct dcn10_ipp_mask ipp_mask = { - IPP_DCN10_MASK_SH_LIST(_MASK), + IPP_MASK_SH_LIST_DCN10(_MASK), }; #define opp_regs(id)\ -- cgit From 7a8368e6f521871976f3d173f837dd921d06130d Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Thu, 29 Jun 2017 18:01:35 -0400 Subject: drm/amd/display: Remove SMU_INTERRUPT_CONTROL Signed-off-by: Dmytro Laktyushkin Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h index 8b04996d5b89..fd6ba7efc0f9 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h @@ -50,7 +50,6 @@ SR(DMCU_IRAM_RD_CTRL), \ SR(DMCU_IRAM_RD_DATA), \ SR(DMCU_INTERRUPT_TO_UC_EN_MASK), \ - SR(SMU_INTERRUPT_CONTROL), \ SRI(DIG_BE_CNTL, DIG, id), \ SRI(DIG_BE_EN_CNTL, DIG, id), \ SRI(DP_CONFIG, DP, id), \ @@ -137,7 +136,6 @@ struct dce110_link_enc_registers { uint32_t DMCU_IRAM_RD_CTRL; uint32_t DMCU_IRAM_RD_DATA; uint32_t DMCU_INTERRUPT_TO_UC_EN_MASK; - uint32_t SMU_INTERRUPT_CONTROL; /* Common DP registers */ uint32_t DIG_BE_CNTL; -- cgit From 97416d4cbb9efab2eea7740fa4ce86b317da06c5 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Mon, 26 Jun 2017 16:25:10 -0400 Subject: drm/amd/display: set drr during program timing. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/dce110/dce110_timing_generator.c | 21 +++++++++++++++++++++ .../amd/display/dc/dce120/dce120_timing_generator.c | 19 ++++++++++++++++--- .../amd/display/dc/dcn10/dcn10_timing_generator.c | 8 ++++++++ 3 files changed, 45 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c index ec599276ed2e..7f93d6d83cfd 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c @@ -629,6 +629,27 @@ void dce110_timing_generator_program_blanking( CRTC_V_TOTAL); dm_write_reg(ctx, addr, value); + /* In case of V_TOTAL_CONTROL is on, make sure V_TOTAL_MAX and + * V_TOTAL_MIN are equal to V_TOTAL. + */ + addr = CRTC_REG(mmCRTC_V_TOTAL_MAX); + value = dm_read_reg(ctx, addr); + set_reg_field_value( + value, + timing->v_total - 1, + CRTC_V_TOTAL_MAX, + CRTC_V_TOTAL_MAX); + dm_write_reg(ctx, addr, value); + + addr = CRTC_REG(mmCRTC_V_TOTAL_MIN); + value = dm_read_reg(ctx, addr); + set_reg_field_value( + value, + timing->v_total - 1, + CRTC_V_TOTAL_MIN, + CRTC_V_TOTAL_MIN); + dm_write_reg(ctx, addr, value); + addr = CRTC_REG(mmCRTC_H_BLANK_START_END); value = dm_read_reg(ctx, addr); diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c index 03b21e9a1156..58a070debd58 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c @@ -441,15 +441,28 @@ void dce120_timing_generator_program_blanking( struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); CRTC_REG_UPDATE( - CRTC0_CRTC_H_TOTAL, - CRTC_H_TOTAL, - timing->h_total - 1); + CRTC0_CRTC_H_TOTAL, + CRTC_H_TOTAL, + timing->h_total - 1); CRTC_REG_UPDATE( CRTC0_CRTC_V_TOTAL, CRTC_V_TOTAL, timing->v_total - 1); + /* In case of V_TOTAL_CONTROL is on, make sure V_TOTAL_MAX and + * V_TOTAL_MIN are equal to V_TOTAL. + */ + CRTC_REG_UPDATE( + CRTC0_CRTC_V_TOTAL_MAX, + CRTC_V_TOTAL_MAX, + timing->v_total - 1); + + CRTC_REG_UPDATE( + CRTC0_CRTC_V_TOTAL_MIN, + CRTC_V_TOTAL_MIN, + timing->v_total - 1); + tmp1 = timing->h_total - (h_sync_start + timing->h_border_left); tmp2 = tmp1 + timing->h_addressable + diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c index 5927478b9044..e1899f5fb083 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c @@ -177,6 +177,14 @@ static void tgn10_program_timing( REG_SET(OTG_V_TOTAL, 0, OTG_V_TOTAL, v_total); + /* In case of V_TOTAL_CONTROL is on, make sure OTG_V_TOTAL_MAX and + * OTG_V_TOTAL_MIN are equal to V_TOTAL. + */ + REG_SET(OTG_V_TOTAL_MAX, 0, + OTG_V_TOTAL_MAX, v_total); + REG_SET(OTG_V_TOTAL_MIN, 0, + OTG_V_TOTAL_MIN, v_total); + /* v_sync_start = 0, v_sync_end = v_sync_width */ v_sync_end = patched_crtc_timing.v_sync_width * interlace_factor; -- cgit From ca3268c45b85d61365ba74939650ae519ecff572 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 27 Jun 2017 11:55:43 -0400 Subject: drm/amd/display: Create dm_atomic_state We really want to use the new private_atomic_state but can't right now as we have to maintain some backward compatibility to older kernels. For now let's follow Intel's approach and extend the drm_atomic_state. Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 37 +++++++++++++++++++++- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.h | 8 +++++ 2 files changed, 44 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') 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 353165c6da1e..a95c9ba64235 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -634,11 +634,46 @@ const struct amdgpu_ip_block_version dm_ip_block = .funcs = &amdgpu_dm_funcs, }; + +struct drm_atomic_state * +dm_atomic_state_alloc(struct drm_device *dev) +{ + struct dm_atomic_state *state = kzalloc(sizeof(*state), GFP_KERNEL); + + if (!state || drm_atomic_state_init(dev, &state->base) < 0) { + kfree(state); + return NULL; + } + + return &state->base; +} + +void dm_atomic_state_clear(struct drm_atomic_state *s) +{ + struct dm_atomic_state *state = to_dm_atomic_state(s); + drm_atomic_state_default_clear(&state->base); +} + + +static void dm_atomic_state_free(struct drm_atomic_state *state) +{ + struct dm_atomic_state *dm_state = to_dm_atomic_state(state); + + drm_atomic_state_default_release(state); + + kfree(dm_state); +} + + + static const struct drm_mode_config_funcs amdgpu_dm_mode_funcs = { .fb_create = amdgpu_user_framebuffer_create, .output_poll_changed = amdgpu_output_poll_changed, .atomic_check = amdgpu_dm_atomic_check, - .atomic_commit = drm_atomic_helper_commit + .atomic_commit = drm_atomic_helper_commit, + .atomic_state_alloc = dm_atomic_state_alloc, + .atomic_state_clear = dm_atomic_state_clear, + .atomic_state_free = dm_atomic_state_free, }; static struct drm_mode_config_helper_funcs amdgpu_dm_mode_config_helperfuncs = { diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h index bf20d57a99e0..9ba7fdd20519 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h @@ -27,6 +27,7 @@ #define __AMDGPU_DM_TYPES_H__ #include +#include struct amdgpu_framebuffer; struct amdgpu_display_manager; @@ -48,6 +49,13 @@ struct dm_crtc_state { #define to_dm_crtc_state(x) container_of(x, struct dm_crtc_state, base) +struct dm_atomic_state { + struct drm_atomic_state base; +}; + +#define to_dm_atomic_state(x) container_of(x, struct dm_atomic_state, base) + + /*TODO Jodan Hersen use the one in amdgpu_dm*/ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, struct amdgpu_plane *aplane, -- cgit From a6818a32317114387dbadf769275275dd56cc624 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 27 Jun 2017 14:35:17 -0400 Subject: drm/amd/display: Hook dm private state into atomic_check Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 64 +++++++++++----------- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.h | 5 ++ 2 files changed, 37 insertions(+), 32 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index a6f27ceaf4af..751dd13b54e3 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2962,15 +2962,14 @@ static int do_aquire_global_lock( int amdgpu_dm_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) { + struct dm_atomic_state *dm_state; struct drm_crtc *crtc; struct drm_crtc_state *crtc_state; struct drm_plane *plane; struct drm_plane_state *plane_state; int i, j; int ret; - int set_count; int new_stream_count; - struct dc_validation_set set[MAX_STREAMS] = {{ 0 }}; struct dc_stream *new_streams[MAX_STREAMS] = { 0 }; struct drm_crtc *crtc_set[MAX_STREAMS] = { 0 }; struct amdgpu_device *adev = dev->dev_private; @@ -2995,17 +2994,19 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, ret = -EINVAL; + dm_state = to_dm_atomic_state(state); + /* copy existing configuration */ new_stream_count = 0; - set_count = 0; + dm_state->set_count = 0; list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); if (acrtc->stream) { - set[set_count].stream = acrtc->stream; - crtc_set[set_count] = crtc; - ++set_count; + dm_state->set[dm_state->set_count].stream = acrtc->stream; + crtc_set[dm_state->set_count] = crtc; + ++dm_state->set_count; } } @@ -3034,16 +3035,16 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, struct dc_stream *new_stream = NULL; struct drm_connector_state *conn_state = NULL; - struct dm_connector_state *dm_state = NULL; + struct dm_connector_state *dm_conn_state = NULL; if (aconnector) { conn_state = drm_atomic_get_connector_state(state, &aconnector->base); if (IS_ERR(conn_state)) return ret; - dm_state = to_dm_connector_state(conn_state); + dm_conn_state = to_dm_connector_state(conn_state); } - new_stream = create_stream_for_sink(aconnector, &crtc_state->mode, dm_state); + new_stream = create_stream_for_sink(aconnector, &crtc_state->mode, dm_conn_state); /* * we can have no stream on ACTION_SET if a display @@ -3058,10 +3059,10 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, } new_streams[new_stream_count] = new_stream; - set_count = update_in_val_sets_stream( - set, + dm_state->set_count = update_in_val_sets_stream( + dm_state->set, crtc_set, - set_count, + dm_state->set_count, acrtc->stream, new_stream, crtc); @@ -3074,9 +3075,9 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, /* i.e. reset mode */ if (acrtc->stream) { - set_count = remove_from_val_sets( - set, - set_count, + dm_state->set_count = remove_from_val_sets( + dm_state->set, + dm_state->set_count, acrtc->stream); aquire_global_lock = true; } @@ -3127,10 +3128,10 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, } new_streams[new_stream_count] = new_stream; - set_count = update_in_val_sets_stream( - set, + dm_state->set_count = update_in_val_sets_stream( + dm_state->set, crtc_set, - set_count, + dm_state->set_count, acrtc->stream, new_stream, &acrtc->base); @@ -3140,12 +3141,12 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, aquire_global_lock = true; } - for (i = 0; i < set_count; i++) { + for (i = 0; i < dm_state->set_count; i++) { for_each_plane_in_state(state, plane, plane_state, j) { struct drm_crtc *crtc = plane_state->crtc; struct drm_framebuffer *fb = plane_state->fb; struct drm_connector *connector; - struct dm_connector_state *dm_state = NULL; + struct dm_connector_state *dm_conn_state = NULL; struct drm_crtc_state *crtc_state; bool pflip_needed; @@ -3166,7 +3167,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, list_for_each_entry(connector, &dev->mode_config.connector_list, head) { if (connector->state->crtc == crtc) { - dm_state = to_dm_connector_state( + dm_conn_state = to_dm_connector_state( connector->state); break; } @@ -3186,7 +3187,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, * Also it should be needed when used with actual * drm_atomic_commit ioctl in future */ - if (!dm_state) + if (!dm_conn_state) continue; surface = dc_create_surface(dc); @@ -3196,11 +3197,10 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, plane_state, false); - add_val_sets_surface( - set, - set_count, - set[i].stream, - surface); + add_val_sets_surface(dm_state->set, + dm_state->set_count, + dm_state->set[i].stream, + surface); need_to_validate = true; aquire_global_lock = true; @@ -3208,9 +3208,9 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, } } - context = dc_get_validate_context(dc, set, set_count); + context = dc_get_validate_context(dc, dm_state->set, dm_state->set_count); - if (need_to_validate == false || set_count == 0 || context) { + if (need_to_validate == false || dm_state->set_count == 0 || context) { ret = 0; /* @@ -3232,9 +3232,9 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, dm_free(context); } - for (i = 0; i < set_count; i++) - for (j = 0; j < set[i].surface_count; j++) - dc_surface_release(set[i].surfaces[j]); + for (i = 0; i < dm_state->set_count; i++) + for (j = 0; j < dm_state->set[i].surface_count; j++) + dc_surface_release(dm_state->set[i].surfaces[j]); for (i = 0; i < new_stream_count; i++) dc_stream_release(new_streams[i]); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h index 9ba7fdd20519..a7adf8dbd067 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h @@ -28,6 +28,7 @@ #include #include +#include "dc.h" struct amdgpu_framebuffer; struct amdgpu_display_manager; @@ -51,6 +52,10 @@ struct dm_crtc_state { struct dm_atomic_state { struct drm_atomic_state base; + + struct dc_validation_set set[MAX_STREAMS]; + int set_count; + }; #define to_dm_atomic_state(x) container_of(x, struct dm_atomic_state, base) -- cgit From b29fc8661d5c732a5689afa751983ee27141ad37 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Fri, 3 Mar 2017 14:50:00 -0500 Subject: drm/amd/display: Add correct retain/release Needed by objs in dm_atomic_state Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 10 ++++++++++ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 6 ++++++ 2 files changed, 16 insertions(+) (limited to 'drivers/gpu') 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 a95c9ba64235..ba20a8cce7df 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -658,9 +658,19 @@ void dm_atomic_state_clear(struct drm_atomic_state *s) static void dm_atomic_state_free(struct drm_atomic_state *state) { struct dm_atomic_state *dm_state = to_dm_atomic_state(state); + int i, j; drm_atomic_state_default_release(state); + for (i = 0; i < dm_state->set_count; i++) { + for (j = 0; j < dm_state->set[i].surface_count; j++) { + dc_surface_release(dm_state->set[i].surfaces[j]); + } + } + + for (i = 0; i < dm_state->set_count; i++) + dc_stream_release(dm_state->set[i].stream); + kfree(dm_state); } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 751dd13b54e3..54d31f474d76 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2874,11 +2874,15 @@ static uint32_t update_in_val_sets_stream( } val_sets[i].stream = new_stream; + dc_stream_retain(new_stream); crtcs[i] = crtc; if (i == set_count) { /* nothing found. add new one to the end */ return set_count + 1; + } else { + /* update. relase old stream */ + dc_stream_release(old_stream); } return set_count; @@ -2900,6 +2904,7 @@ static uint32_t remove_from_val_sets( return set_count; } + dc_stream_release(stream); set_count--; for (; i < set_count; i++) { @@ -3004,6 +3009,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); if (acrtc->stream) { + dc_stream_retain(acrtc->stream); dm_state->set[dm_state->set_count].stream = acrtc->stream; crtc_set[dm_state->set_count] = crtc; ++dm_state->set_count; -- cgit From 7cf2c840c6b5ee98195d249e3748bb90c9bcb831 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 6 Mar 2017 09:43:30 -0500 Subject: drm/amd/display: Commit validation set from state Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 32 +++--- drivers/gpu/drm/amd/display/dc/core/dc.c | 118 +++++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dc.h | 16 +++ 3 files changed, 151 insertions(+), 15 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 54d31f474d76..c77f35bcacac 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2517,12 +2517,11 @@ void amdgpu_dm_atomic_commit_tail( struct drm_device *dev = state->dev; struct amdgpu_device *adev = dev->dev_private; struct amdgpu_display_manager *dm = &adev->dm; + struct dm_atomic_state *dm_state; uint32_t i, j; - uint32_t commit_streams_count = 0; uint32_t new_crtcs_count = 0; struct drm_crtc *crtc, *pcrtc; struct drm_crtc_state *old_crtc_state; - const struct dc_stream *commit_streams[MAX_STREAMS]; struct amdgpu_crtc *new_crtcs[MAX_STREAMS]; const struct dc_stream *new_stream; unsigned long flags; @@ -2531,6 +2530,9 @@ void amdgpu_dm_atomic_commit_tail( struct drm_connector_state *old_conn_state; drm_atomic_helper_update_legacy_modeset_state(dev, state); + + dm_state = to_dm_atomic_state(state); + /* update changed items */ for_each_crtc_in_state(state, crtc, old_crtc_state, i) { struct amdgpu_crtc *acrtc; @@ -2561,16 +2563,16 @@ void amdgpu_dm_atomic_commit_tail( */ if (modeset_required(new_state)) { - struct dm_connector_state *dm_state = NULL; + struct dm_connector_state *dm_conn_state = NULL; new_stream = NULL; if (aconnector) - dm_state = to_dm_connector_state(aconnector->base.state); + dm_conn_state = to_dm_connector_state(aconnector->base.state); new_stream = create_stream_for_sink( aconnector, &crtc->state->mode, - dm_state); + dm_conn_state); DRM_INFO("Atomic commit: SET crtc id %d: [%p]\n", acrtc->crtc_id, acrtc); @@ -2598,6 +2600,13 @@ void amdgpu_dm_atomic_commit_tail( if (acrtc->stream) remove_stream(adev, acrtc); + /* TODO clean this stupid hack */ + for (j = 0; j < dm_state->set_count; j++) + if (dm_state->set[j].stream->priv == acrtc) { + ASSERT(acrtc->stream == NULL); + new_stream = dm_state->set[j].stream; + break; + } /* * this loop saves set mode crtcs * we needed to enable vblanks once all @@ -2656,15 +2665,6 @@ void amdgpu_dm_atomic_commit_tail( dm_error("%s: Failed to update stream scaling!\n", __func__); } - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - - if (acrtc->stream) { - commit_streams[commit_streams_count] = acrtc->stream; - ++commit_streams_count; - } - } /* * Add streams after required streams from new and replaced streams @@ -2693,7 +2693,8 @@ void amdgpu_dm_atomic_commit_tail( } /* DC is optimized not to do anything if 'streams' didn't change. */ - WARN_ON(!dc_commit_streams(dm->dc, commit_streams, commit_streams_count)); + WARN_ON(!dc_commit_validation_set(dm->dc, dm_state->set, + dm_state->set_count)); list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); @@ -3051,6 +3052,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, } new_stream = create_stream_for_sink(aconnector, &crtc_state->mode, dm_conn_state); + new_stream->priv = acrtc; /* * we can have no stream on ACTION_SET if a display diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 1d2e421e8d0a..b50fc0dae28c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -841,6 +841,24 @@ static void program_timing_sync( } } +static bool set_changed( + struct core_dc *dc, + const struct dc_validation_set set[], + uint8_t set_count) +{ + uint8_t i; + + if (set_count != dc->current_context->stream_count) + return true; + + for (i = 0; i < dc->current_context->stream_count; i++) { + if (&dc->current_context->streams[i]->public != set[i].stream) + return true; + } + + return false; +} + static bool streams_changed( struct core_dc *dc, const struct dc_stream *streams[], @@ -896,6 +914,106 @@ bool dc_enable_stereo( return ret; } +/* TODO operate on validation set (or something like it) */ +bool dc_commit_validation_set( + const struct dc *dc, + const struct dc_validation_set set[], + uint8_t set_count) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc_bios *dcb = core_dc->ctx->dc_bios; + enum dc_status result = DC_ERROR_UNEXPECTED; + struct validate_context *context; + struct pipe_ctx *pipe; + int i, j, k, l; + + /* TODO check validation set changed */ + if (false == set_changed(core_dc, set, set_count)) + return DC_OK; + + dm_logger_write(core_dc->ctx->logger, LOG_DC, "%s: %d streams\n", + __func__, set_count); + + for (i = 0; i < set_count; i++) + dc_stream_log(set[i].stream, + core_dc->ctx->logger, + LOG_DC); + + context = dm_alloc(sizeof(struct validate_context)); + if (context == NULL) + goto context_alloc_fail; + + /* TODO no need for validation. just rebuild context */ + /* TODO check context is created deterministically */ + result = core_dc->res_pool->funcs->validate_with_context(core_dc, set, + set_count, + context, + core_dc->current_context); + if (result != DC_OK) { + dm_logger_write(core_dc->ctx->logger, LOG_ERROR, + "%s: Context validation failed! dc_status:%d\n", + __func__, + result); + BREAK_TO_DEBUGGER(); + dc_resource_validate_ctx_destruct(context); + goto fail; + } + + if (!dcb->funcs->is_accelerated_mode(dcb)) + core_dc->hwss.enable_accelerated_mode(core_dc); + + if (result == DC_OK) + result = core_dc->hwss.apply_ctx_to_hw(core_dc, context); + + program_timing_sync(core_dc, context); + + for (i = 0; i < context->stream_count; i++) { + const struct core_sink *sink = context->streams[i]->sink; + + for (j = 0; j < context->stream_status[i].surface_count; j++) { + struct core_surface *surface = + DC_SURFACE_TO_CORE(context->stream_status[i].surfaces[j]); + + core_dc->hwss.apply_ctx_for_surface(core_dc, surface, context); + + /* + * enable stereo + * TODO rework dc_enable_stereo call to work with validation sets? + */ + for (k = 0; k < MAX_PIPES; k++) { + pipe = &context->res_ctx.pipe_ctx[k]; + + for (l = 0 ; pipe && l < context->stream_count; l++) { + if (context->streams[l] && + context->streams[l] == pipe->stream && + core_dc->hwss.setup_stereo) + core_dc->hwss.setup_stereo(pipe, core_dc); + } + } + } + + CONN_MSG_MODE(sink->link, "{%dx%d, %dx%d@%dKhz}", + context->streams[i]->public.timing.h_addressable, + context->streams[i]->public.timing.v_addressable, + context->streams[i]->public.timing.h_total, + context->streams[i]->public.timing.v_total, + context->streams[i]->public.timing.pix_clk_khz); + } + + dc_resource_validate_ctx_destruct(core_dc->current_context); + dm_free(core_dc->current_context); + + core_dc->current_context = context; + + return (result == DC_OK); + +fail: + dm_free(context); + +context_alloc_fail: + return (result == DC_OK); +} + bool dc_commit_streams( struct dc *dc, const struct dc_stream *streams[], diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 93aff8269778..5487fb100a9f 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -481,6 +481,8 @@ struct dc_stream { /* TODO: ABM info (DMCU) */ /* TODO: PSR info */ /* TODO: CEA VIC */ + + void *priv; }; struct dc_stream_update { @@ -579,6 +581,20 @@ void dc_resource_validate_ctx_copy_construct( void dc_resource_validate_ctx_destruct(struct validate_context *context); +/* + * TODO update to make it about validation sets + * Set up streams and links associated to drive sinks + * The streams parameter is an absolute set of all active streams. + * + * After this call: + * Phy, Encoder, Timing Generator are programmed and enabled. + * New streams are enabled with blank stream; no memory read. + */ +bool dc_commit_validation_set( + const struct dc *dc, + const struct dc_validation_set set[], + uint8_t set_count); + /* * Set up streams and links associated to drive sinks * The streams parameter is an absolute set of all active streams. -- cgit From bf8aef2ec439673cd43ef6d0edace96aa36c5e7c Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Wed, 29 Mar 2017 11:25:24 -0400 Subject: drm/amd/display: Add validate_context to atomic_state Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 18 ++---------------- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h | 2 +- 2 files changed, 3 insertions(+), 17 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index c77f35bcacac..f2a87cd3507b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2981,7 +2981,6 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, struct amdgpu_device *adev = dev->dev_private; struct dc *dc = adev->dm.dc; bool need_to_validate = false; - struct validate_context *context; struct drm_connector *connector; struct drm_connector_state *conn_state; /* @@ -3216,10 +3215,9 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, } } - context = dc_get_validate_context(dc, dm_state->set, dm_state->set_count); - - if (need_to_validate == false || dm_state->set_count == 0 || context) { + dm_state->context = dc_get_validate_context(dc, dm_state->set, dm_state->set_count); + if (need_to_validate == false || dm_state->set_count == 0 || dm_state->context) { ret = 0; /* * For full updates case when @@ -3235,18 +3233,6 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, } - if (context) { - dc_resource_validate_ctx_destruct(context); - dm_free(context); - } - - for (i = 0; i < dm_state->set_count; i++) - for (j = 0; j < dm_state->set[i].surface_count; j++) - dc_surface_release(dm_state->set[i].surfaces[j]); - - for (i = 0; i < new_stream_count; i++) - dc_stream_release(new_streams[i]); - if (ret != 0) { if (ret == -EDEADLK) DRM_DEBUG_KMS("Atomic check stopped due to to deadlock.\n"); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h index a7adf8dbd067..1e444cb5123d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h @@ -55,7 +55,7 @@ struct dm_atomic_state { struct dc_validation_set set[MAX_STREAMS]; int set_count; - + struct validate_context *context; }; #define to_dm_atomic_state(x) container_of(x, struct dm_atomic_state, base) -- cgit From e2c7bb1228bec5b1224b235e90ffa1def8e3900e Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Wed, 28 Jun 2017 13:23:04 -0400 Subject: drm/amd/display: Use validate_context from atomic_check in commit Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 18 ++++-- drivers/gpu/drm/amd/display/dc/core/dc.c | 71 +++++++--------------- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 6 +- drivers/gpu/drm/amd/display/dc/dc.h | 5 +- 4 files changed, 40 insertions(+), 60 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index f2a87cd3507b..ab07a9f0934d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2607,6 +2607,7 @@ void amdgpu_dm_atomic_commit_tail( new_stream = dm_state->set[j].stream; break; } + /* * this loop saves set mode crtcs * we needed to enable vblanks once all @@ -2665,7 +2666,6 @@ void amdgpu_dm_atomic_commit_tail( dm_error("%s: Failed to update stream scaling!\n", __func__); } - /* * Add streams after required streams from new and replaced streams * are removed from freesync module @@ -2693,15 +2693,19 @@ void amdgpu_dm_atomic_commit_tail( } /* DC is optimized not to do anything if 'streams' didn't change. */ - WARN_ON(!dc_commit_validation_set(dm->dc, dm_state->set, - dm_state->set_count)); + WARN_ON(!dc_commit_context(dm->dc, dm_state->context)); list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - if (acrtc->stream != NULL) - acrtc->otg_inst = - dc_stream_get_status(acrtc->stream)->primary_otg_inst; + if (acrtc->stream != NULL) { + const struct dc_stream_status *status = dc_stream_get_status(acrtc->stream); + + if (!status) + DC_ERR("got no status for stream %p on acrtc%p\n", acrtc->stream, acrtc); + else + acrtc->otg_inst = status->primary_otg_inst; + } } for (i = 0; i < new_crtcs_count; i++) { @@ -2884,6 +2888,7 @@ static uint32_t update_in_val_sets_stream( } else { /* update. relase old stream */ dc_stream_release(old_stream); + } return set_count; @@ -3064,6 +3069,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, __func__, acrtc->base.base.id); break; } + new_stream->priv = acrtc; new_streams[new_stream_count] = new_stream; dm_state->set_count = update_in_val_sets_stream( diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index b50fc0dae28c..90a31509edd6 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -841,18 +841,17 @@ static void program_timing_sync( } } -static bool set_changed( +static bool context_changed( struct core_dc *dc, - const struct dc_validation_set set[], - uint8_t set_count) + struct validate_context *context) { uint8_t i; - if (set_count != dc->current_context->stream_count) + if (context->stream_count != dc->current_context->stream_count) return true; for (i = 0; i < dc->current_context->stream_count; i++) { - if (&dc->current_context->streams[i]->public != set[i].stream) + if (&dc->current_context->streams[i]->public != &context->streams[i]->public) return true; } @@ -915,55 +914,37 @@ bool dc_enable_stereo( } /* TODO operate on validation set (or something like it) */ -bool dc_commit_validation_set( - const struct dc *dc, - const struct dc_validation_set set[], - uint8_t set_count) +bool dc_commit_context(struct dc *dc, struct validate_context *context) { struct core_dc *core_dc = DC_TO_CORE(dc); struct dc_bios *dcb = core_dc->ctx->dc_bios; enum dc_status result = DC_ERROR_UNEXPECTED; - struct validate_context *context; struct pipe_ctx *pipe; int i, j, k, l; - /* TODO check validation set changed */ - if (false == set_changed(core_dc, set, set_count)) + if (!context) + dm_logger_write(core_dc->ctx->logger, LOG_ERROR, + "%s: dc_commit_context with no context!\n", + __func__); + + if (false == context_changed(core_dc, context)) return DC_OK; dm_logger_write(core_dc->ctx->logger, LOG_DC, "%s: %d streams\n", - __func__, set_count); - - for (i = 0; i < set_count; i++) - dc_stream_log(set[i].stream, - core_dc->ctx->logger, - LOG_DC); + __func__, context->stream_count); - context = dm_alloc(sizeof(struct validate_context)); - if (context == NULL) - goto context_alloc_fail; + for (i = 0; i < context->stream_count; i++) { + const struct dc_stream *stream = &context->streams[i]->public; - /* TODO no need for validation. just rebuild context */ - /* TODO check context is created deterministically */ - result = core_dc->res_pool->funcs->validate_with_context(core_dc, set, - set_count, - context, - core_dc->current_context); - if (result != DC_OK) { - dm_logger_write(core_dc->ctx->logger, LOG_ERROR, - "%s: Context validation failed! dc_status:%d\n", - __func__, - result); - BREAK_TO_DEBUGGER(); - dc_resource_validate_ctx_destruct(context); - goto fail; + dc_stream_log(stream, + core_dc->ctx->logger, + LOG_DC); } if (!dcb->funcs->is_accelerated_mode(dcb)) core_dc->hwss.enable_accelerated_mode(core_dc); - if (result == DC_OK) - result = core_dc->hwss.apply_ctx_to_hw(core_dc, context); + result = core_dc->hwss.apply_ctx_to_hw(core_dc, context); program_timing_sync(core_dc, context); @@ -1000,17 +981,8 @@ bool dc_commit_validation_set( context->streams[i]->public.timing.pix_clk_khz); } - dc_resource_validate_ctx_destruct(core_dc->current_context); - dm_free(core_dc->current_context); - - core_dc->current_context = context; - - return (result == DC_OK); - -fail: - dm_free(context); + dc_resource_validate_ctx_copy_construct(context, core_dc->current_context); -context_alloc_fail: return (result == DC_OK); } @@ -1631,7 +1603,10 @@ void dc_update_surfaces_and_stream(struct dc *dc, if (update_type == UPDATE_TYPE_FAST) continue; - if (srf_updates[i].in_transfer_func) + /* TODO find out why check is false */ + /* TODO with this still not programming some color stuff... panel is dark-ish */ + /*if (is_new_pipe_surface || + srf_updates[i].in_transfer_func)*/ core_dc->hwss.set_input_transfer_func( pipe_ctx, pipe_ctx->surface); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 4ba446de4d00..ead7b63caab7 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -164,9 +164,11 @@ const struct dc_stream_status *dc_stream_get_status( struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); struct core_dc *dc = DC_TO_CORE(stream->ctx->dc); - for (i = 0; i < dc->current_context->stream_count; i++) - if (stream == dc->current_context->streams[i]) + for (i = 0; i < dc->current_context->stream_count; i++) { + if (stream == dc->current_context->streams[i]) { return &dc->current_context->stream_status[i]; + } + } return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 5487fb100a9f..5d65416304b0 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -590,10 +590,7 @@ void dc_resource_validate_ctx_destruct(struct validate_context *context); * Phy, Encoder, Timing Generator are programmed and enabled. * New streams are enabled with blank stream; no memory read. */ -bool dc_commit_validation_set( - const struct dc *dc, - const struct dc_validation_set set[], - uint8_t set_count); +bool dc_commit_context(struct dc *dc, struct validate_context *context); /* * Set up streams and links associated to drive sinks -- cgit From 89a1fc5924cc7c315117be79878f2a6d2d69b576 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Thu, 29 Jun 2017 10:41:17 -0400 Subject: drm/amd/display: Update atomic state hooks. Reimplement atomic_state_alloc and atomic_state_clear to release validate_ctx. Signed-off-by: Andrey Grodzovsky Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 25 +++++++++------------- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 2 +- 2 files changed, 11 insertions(+), 16 deletions(-) (limited to 'drivers/gpu') 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 ba20a8cce7df..2cfc1846f4c4 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -648,33 +648,29 @@ dm_atomic_state_alloc(struct drm_device *dev) return &state->base; } -void dm_atomic_state_clear(struct drm_atomic_state *s) -{ - struct dm_atomic_state *state = to_dm_atomic_state(s); - drm_atomic_state_default_clear(&state->base); -} - -static void dm_atomic_state_free(struct drm_atomic_state *state) +void dm_atomic_state_clear(struct drm_atomic_state *state) { struct dm_atomic_state *dm_state = to_dm_atomic_state(state); int i, j; - drm_atomic_state_default_release(state); - for (i = 0; i < dm_state->set_count; i++) { for (j = 0; j < dm_state->set[i].surface_count; j++) { dc_surface_release(dm_state->set[i].surfaces[j]); + dm_state->set[i].surfaces[j] = NULL; } - } - for (i = 0; i < dm_state->set_count; i++) dc_stream_release(dm_state->set[i].stream); + dm_state->set[i].stream = NULL; + } + dm_state->set_count = 0; - kfree(dm_state); -} - + dc_resource_validate_ctx_destruct(dm_state->context); + dm_free(dm_state->context); + dm_state->context = NULL; + drm_atomic_state_default_clear(state); +} static const struct drm_mode_config_funcs amdgpu_dm_mode_funcs = { .fb_create = amdgpu_user_framebuffer_create, @@ -683,7 +679,6 @@ static const struct drm_mode_config_funcs amdgpu_dm_mode_funcs = { .atomic_commit = drm_atomic_helper_commit, .atomic_state_alloc = dm_atomic_state_alloc, .atomic_state_clear = dm_atomic_state_clear, - .atomic_state_free = dm_atomic_state_free, }; static struct drm_mode_config_helper_funcs amdgpu_dm_mode_config_helperfuncs = { diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index ab07a9f0934d..10e4823968c8 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2695,6 +2695,7 @@ void amdgpu_dm_atomic_commit_tail( /* DC is optimized not to do anything if 'streams' didn't change. */ WARN_ON(!dc_commit_context(dm->dc, dm_state->context)); + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); @@ -3069,7 +3070,6 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, __func__, acrtc->base.base.id); break; } - new_stream->priv = acrtc; new_streams[new_stream_count] = new_stream; dm_state->set_count = update_in_val_sets_stream( -- cgit From da5c47f682abe61eb81291cb663b77828fda0688 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Thu, 29 Jun 2017 12:03:59 -0400 Subject: drm/amd/display: Remove acrtc->stream Remove acrtc->stream and move it into dm_crtc_state. This allows to get rid of dm_atomic_state->dm_set. Also reuse streams created in atomic_check during commit. Signed-off-by: Andrey Grodzovsky Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 33 +- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 403 +++++++++++---------- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.h | 9 +- drivers/gpu/drm/amd/display/dc/dc.h | 2 - 4 files changed, 226 insertions(+), 221 deletions(-) (limited to 'drivers/gpu') 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 2cfc1846f4c4..4b844e5c5dcd 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -100,13 +100,16 @@ static u32 dm_vblank_get_counter(struct amdgpu_device *adev, int crtc) return 0; else { struct amdgpu_crtc *acrtc = adev->mode_info.crtcs[crtc]; + struct dm_crtc_state *acrtc_state = to_dm_crtc_state( + acrtc->base.state); - if (NULL == acrtc->stream) { + + if (acrtc_state->stream == NULL) { DRM_ERROR("dc_stream is NULL for crtc '%d'!\n", crtc); return 0; } - return dc_stream_get_vblank_counter(acrtc->stream); + return dc_stream_get_vblank_counter(acrtc_state->stream); } } @@ -119,8 +122,10 @@ static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc, return -EINVAL; else { struct amdgpu_crtc *acrtc = adev->mode_info.crtcs[crtc]; + struct dm_crtc_state *acrtc_state = to_dm_crtc_state( + acrtc->base.state); - if (NULL == acrtc->stream) { + if (acrtc_state->stream == NULL) { DRM_ERROR("dc_stream is NULL for crtc '%d'!\n", crtc); return 0; } @@ -129,7 +134,7 @@ static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc, * TODO rework base driver to use values directly. * for now parse it back into reg-format */ - dc_stream_get_scanoutpos(acrtc->stream, + dc_stream_get_scanoutpos(acrtc_state->stream, &v_blank_start, &v_blank_end, &h_position, @@ -652,22 +657,12 @@ dm_atomic_state_alloc(struct drm_device *dev) void dm_atomic_state_clear(struct drm_atomic_state *state) { struct dm_atomic_state *dm_state = to_dm_atomic_state(state); - int i, j; - - for (i = 0; i < dm_state->set_count; i++) { - for (j = 0; j < dm_state->set[i].surface_count; j++) { - dc_surface_release(dm_state->set[i].surfaces[j]); - dm_state->set[i].surfaces[j] = NULL; - } - dc_stream_release(dm_state->set[i].stream); - dm_state->set[i].stream = NULL; + if (dm_state->context) { + dc_resource_validate_ctx_destruct(dm_state->context); + dm_free(dm_state->context); + dm_state->context = NULL; } - dm_state->set_count = 0; - - dc_resource_validate_ctx_destruct(dm_state->context); - dm_free(dm_state->context); - dm_state->context = NULL; drm_atomic_state_default_clear(state); } @@ -676,7 +671,7 @@ static const struct drm_mode_config_funcs amdgpu_dm_mode_funcs = { .fb_create = amdgpu_user_framebuffer_create, .output_poll_changed = amdgpu_output_poll_changed, .atomic_check = amdgpu_dm_atomic_check, - .atomic_commit = drm_atomic_helper_commit, + .atomic_commit = amdgpu_dm_atomic_commit, .atomic_state_alloc = dm_atomic_state_alloc, .atomic_state_clear = dm_atomic_state_clear, }; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 10e4823968c8..c222cdb59ac1 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -86,6 +86,7 @@ static void dm_set_cursor( struct drm_crtc *crtc = &amdgpu_crtc->base; int x, y; int xorigin = 0, yorigin = 0; + struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state); amdgpu_crtc->cursor_width = width; amdgpu_crtc->cursor_height = height; @@ -124,13 +125,13 @@ static void dm_set_cursor( position.y_hotspot = yorigin; if (!dc_stream_set_cursor_attributes( - amdgpu_crtc->stream, + acrtc_state->stream, &attributes)) { DRM_ERROR("DC failed to set cursor attributes\n"); } if (!dc_stream_set_cursor_position( - amdgpu_crtc->stream, + acrtc_state->stream, &position)) { DRM_ERROR("DC failed to set cursor position\n"); } @@ -143,6 +144,7 @@ static int dm_crtc_cursor_set( uint32_t height) { struct dc_cursor_position position; + struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state); int ret; @@ -162,10 +164,10 @@ static int dm_crtc_cursor_set( position.x = 0; position.y = 0; - if (amdgpu_crtc->stream) { + if (acrtc_state->stream) { /*set cursor visible false*/ dc_stream_set_cursor_position( - amdgpu_crtc->stream, + acrtc_state->stream, &position); } goto release; @@ -196,6 +198,7 @@ static int dm_crtc_cursor_move(struct drm_crtc *crtc, struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); int xorigin = 0, yorigin = 0; struct dc_cursor_position position; + struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state); amdgpu_crtc->cursor_x = x; amdgpu_crtc->cursor_y = y; @@ -233,9 +236,9 @@ static int dm_crtc_cursor_move(struct drm_crtc *crtc, position.x_hotspot = xorigin; position.y_hotspot = yorigin; - if (amdgpu_crtc->stream) { + if (acrtc_state->stream) { if (!dc_stream_set_cursor_position( - amdgpu_crtc->stream, + acrtc_state->stream, &position)) { DRM_ERROR("DC failed to set cursor position\n"); return -EINVAL; @@ -611,7 +614,8 @@ static void add_surface(struct dc *dc, { struct dc_surface *dc_surface; struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - const struct dc_stream *dc_stream = acrtc->stream; + struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state); + const struct dc_stream *dc_stream = acrtc_state->stream; unsigned long flags; spin_lock_irqsave(&crtc->dev->event_lock, flags); @@ -965,11 +969,10 @@ static void dm_crtc_destroy_state(struct drm_crtc *crtc, { struct dm_crtc_state *cur = to_dm_crtc_state(state); - if (cur->dc_stream) { - /* TODO Destroy dc_stream objects are stream object is flattened */ - dm_free(cur->dc_stream); - } else - WARN_ON(1); + /* TODO Destroy dc_stream objects are stream object is flattened */ + if (cur->stream) + dc_stream_release(cur->stream); + __drm_atomic_helper_crtc_destroy_state(state); @@ -988,40 +991,29 @@ static void dm_crtc_reset_state(struct drm_crtc *crtc) if (WARN_ON(!state)) return; - crtc->state = &state->base; crtc->state->crtc = crtc; - state->dc_stream = dm_alloc(sizeof(*state->dc_stream)); - WARN_ON(!state->dc_stream); } static struct drm_crtc_state * dm_crtc_duplicate_state(struct drm_crtc *crtc) { struct dm_crtc_state *state, *cur; - struct dc_stream *dc_stream; - - if (WARN_ON(!crtc->state)) - return NULL; cur = to_dm_crtc_state(crtc->state); - if (WARN_ON(!cur->dc_stream)) - return NULL; - dc_stream = dm_alloc(sizeof(*dc_stream)); - if (WARN_ON(!dc_stream)) + if (WARN_ON(!crtc->state)) return NULL; state = dm_alloc(sizeof(*state)); - if (WARN_ON(!state)) { - dm_free(dc_stream); - return NULL; - } __drm_atomic_helper_crtc_duplicate_state(crtc, &state->base); - state->dc_stream = dc_stream; + if (cur->stream) { + state->stream = cur->stream; + dc_stream_retain(state->stream); + } /* TODO Duplicate dc_stream after objects are stream object is flattened */ @@ -2238,21 +2230,15 @@ static bool is_scaling_state_different( return false; } -static void remove_stream(struct amdgpu_device *adev, struct amdgpu_crtc *acrtc) +static void remove_stream( + struct amdgpu_device *adev, + struct amdgpu_crtc *acrtc, + const struct dc_stream *stream) { - /* - * we evade vblanks and pflips on crtc that - * should be changed - */ - manage_dm_interrupts(adev, acrtc, false); - /* this is the update mode case */ if (adev->dm.freesync_module) - mod_freesync_remove_stream(adev->dm.freesync_module, - acrtc->stream); + mod_freesync_remove_stream(adev->dm.freesync_module, stream); - dc_stream_release(acrtc->stream); - acrtc->stream = NULL; acrtc->otg_inst = -1; acrtc->enabled = false; } @@ -2324,6 +2310,8 @@ static void amdgpu_dm_do_flip( bool async_flip = (acrtc->flip_flags & DRM_MODE_PAGE_FLIP_ASYNC) != 0; struct dc_flip_addrs addr = { {0} }; struct dc_surface_update surface_updates[1] = { {0} }; + struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state); + /* Prepare wait for target vblank early - before the fence-waits */ target_vblank = target - drm_crtc_vblank_count(crtc) + @@ -2366,7 +2354,7 @@ static void amdgpu_dm_do_flip( crtc->primary->fb = fb; WARN_ON(acrtc->pflip_status != AMDGPU_FLIP_NONE); - WARN_ON(!acrtc->stream); + WARN_ON(!acrtc_state->stream); addr.address.grph.addr.low_part = lower_32_bits(afb->address); addr.address.grph.addr.high_part = upper_32_bits(afb->address); @@ -2376,11 +2364,11 @@ static void amdgpu_dm_do_flip( if (acrtc->base.state->event) prepare_flip_isr(acrtc); - surface_updates->surface = dc_stream_get_status(acrtc->stream)->surfaces[0]; + surface_updates->surface = dc_stream_get_status(acrtc_state->stream)->surfaces[0]; surface_updates->flip_addr = &addr; - dc_update_surfaces_and_stream(adev->dm.dc, surface_updates, 1, acrtc->stream, NULL); + dc_update_surfaces_and_stream(adev->dm.dc, surface_updates, 1, acrtc_state->stream, NULL); DRM_DEBUG_DRIVER("%s Flipping to hi: 0x%x, low: 0x%x \n", __func__, @@ -2403,6 +2391,7 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, const struct dc_stream *dc_stream_attach; const struct dc_surface *dc_surfaces_constructed[MAX_SURFACES]; struct amdgpu_crtc *acrtc_attach = to_amdgpu_crtc(pcrtc); + struct dm_crtc_state *acrtc_state = to_dm_crtc_state(pcrtc->state); int planes_count = 0; /* update planes when needed */ @@ -2457,7 +2446,7 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, dm_error("%s: Failed to add surface!\n", __func__); continue; } - dc_stream_attach = acrtc_attach->stream; + dc_stream_attach = acrtc_state->stream; planes_count++; } else if (crtc->state->planes_changed) { @@ -2511,6 +2500,37 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, } } + +int amdgpu_dm_atomic_commit( + struct drm_device *dev, + struct drm_atomic_state *state, + bool nonblock) +{ + struct drm_crtc *crtc; + struct drm_crtc_state *new_state; + struct amdgpu_device *adev = dev->dev_private; + int i; + + /* + * We evade vblanks and pflips on crtc that + * should be changed. We do it here to flush & disable + * interrupts before drm_swap_state is called in drm_atomic_helper_commit + * it will update crtc->dm_crtc_state->stream pointer which is used in + * the ISRs. + */ + for_each_crtc_in_state(state, crtc, new_state, i) { + struct dm_crtc_state *old_acrtc_state = to_dm_crtc_state(crtc->state); + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + + if (drm_atomic_crtc_needs_modeset(new_state) && old_acrtc_state->stream) + manage_dm_interrupts(adev, acrtc, false); + } + + return drm_atomic_helper_commit(dev, state, nonblock); + + /*TODO Handle EINTR, reenable IRQ*/ +} + void amdgpu_dm_atomic_commit_tail( struct drm_atomic_state *state) { @@ -2528,6 +2548,7 @@ void amdgpu_dm_atomic_commit_tail( bool wait_for_vblank = true; struct drm_connector *connector; struct drm_connector_state *old_conn_state; + struct dm_crtc_state *old_acrtc_state, *new_acrtc_state; drm_atomic_helper_update_legacy_modeset_state(dev, state); @@ -2535,16 +2556,10 @@ void amdgpu_dm_atomic_commit_tail( /* update changed items */ for_each_crtc_in_state(state, crtc, old_crtc_state, i) { - struct amdgpu_crtc *acrtc; - struct amdgpu_connector *aconnector = NULL; + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); struct drm_crtc_state *new_state = crtc->state; - - acrtc = to_amdgpu_crtc(crtc); - aconnector = - amdgpu_dm_find_first_crct_matching_connector( - state, - crtc, - false); + new_acrtc_state = to_dm_crtc_state(new_state); + old_acrtc_state = to_dm_crtc_state(old_crtc_state); DRM_DEBUG_KMS( "amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, " @@ -2563,109 +2578,60 @@ void amdgpu_dm_atomic_commit_tail( */ if (modeset_required(new_state)) { - struct dm_connector_state *dm_conn_state = NULL; - new_stream = NULL; - - if (aconnector) - dm_conn_state = to_dm_connector_state(aconnector->base.state); - - new_stream = create_stream_for_sink( - aconnector, - &crtc->state->mode, - dm_conn_state); DRM_INFO("Atomic commit: SET crtc id %d: [%p]\n", acrtc->crtc_id, acrtc); - if (!new_stream) { + if (!new_acrtc_state->stream) { /* - * this could happen because of issues with - * userspace notifications delivery. - * In this case userspace tries to set mode on - * display which is disconnect in fact. - * dc_sink in NULL in this case on aconnector. - * We expect reset mode will come soon. - * - * This can also happen when unplug is done - * during resume sequence ended - * - * In this case, we want to pretend we still - * have a sink to keep the pipe running so that - * hw state is consistent with the sw state - */ + * this could happen because of issues with + * userspace notifications delivery. + * In this case userspace tries to set mode on + * display which is disconnect in fact. + * dc_sink in NULL in this case on aconnector. + * We expect reset mode will come soon. + * + * This can also happen when unplug is done + * during resume sequence ended + * + * In this case, we want to pretend we still + * have a sink to keep the pipe running so that + * hw state is consistent with the sw state + */ DRM_DEBUG_KMS("%s: Failed to create new stream for crtc %d\n", __func__, acrtc->base.base.id); - break; + continue; } - if (acrtc->stream) - remove_stream(adev, acrtc); - /* TODO clean this stupid hack */ - for (j = 0; j < dm_state->set_count; j++) - if (dm_state->set[j].stream->priv == acrtc) { - ASSERT(acrtc->stream == NULL); - new_stream = dm_state->set[j].stream; - break; - } + if (old_acrtc_state->stream) + remove_stream(adev, acrtc, old_acrtc_state->stream); + /* * this loop saves set mode crtcs * we needed to enable vblanks once all * resources acquired in dc after dc_commit_streams */ + + /*TODO move all this into dm_crtc_state, get rid of + * new_crtcs array and use old and new atomic states + * instead + */ new_crtcs[new_crtcs_count] = acrtc; new_crtcs_count++; - acrtc->stream = new_stream; acrtc->enabled = true; acrtc->hw_mode = crtc->state->mode; crtc->hwmode = crtc->state->mode; } else if (modereset_required(new_state)) { - DRM_INFO("Atomic commit: RESET. crtc id %d:[%p]\n", acrtc->crtc_id, acrtc); + /* i.e. reset mode */ - if (acrtc->stream) - remove_stream(adev, acrtc); + if (old_acrtc_state->stream) + remove_stream(adev, acrtc, old_acrtc_state->stream); } } /* for_each_crtc_in_state() */ - /* Handle scaling and undersacn changes*/ - for_each_connector_in_state(state, connector, old_conn_state, i) { - struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); - struct dm_connector_state *con_new_state = - to_dm_connector_state(aconnector->base.state); - struct dm_connector_state *con_old_state = - to_dm_connector_state(old_conn_state); - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(con_new_state->base.crtc); - const struct dc_stream_status *status = NULL; - - /* Skip any modesets/resets */ - if (!acrtc || drm_atomic_crtc_needs_modeset(acrtc->base.state)) - continue; - - /* Skip any thing not scale or underscan chnages */ - if (!is_scaling_state_different(con_new_state, con_old_state)) - continue; - - update_stream_scaling_settings(&con_new_state->base.crtc->mode, - con_new_state, (struct dc_stream *)acrtc->stream); - - status = dc_stream_get_status(acrtc->stream); - WARN_ON(!status); - WARN_ON(!status->surface_count); - - if (!acrtc->stream) - continue; - - /*TODO How it works with MPO ?*/ - if (!dc_commit_surfaces_to_stream( - dm->dc, - (const struct dc_surface **)status->surfaces, - status->surface_count, - acrtc->stream)) - dm_error("%s: Failed to update stream scaling!\n", __func__); - } - /* * Add streams after required streams from new and replaced streams * are removed from freesync module @@ -2673,7 +2639,9 @@ void amdgpu_dm_atomic_commit_tail( if (adev->dm.freesync_module) { for (i = 0; i < new_crtcs_count; i++) { struct amdgpu_connector *aconnector = NULL; - new_stream = new_crtcs[i]->stream; + new_acrtc_state = to_dm_crtc_state(new_crtcs[i]->base.state); + + new_stream = new_acrtc_state->stream; aconnector = amdgpu_dm_find_first_crct_matching_connector( state, @@ -2698,35 +2666,77 @@ void amdgpu_dm_atomic_commit_tail( list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + new_acrtc_state = to_dm_crtc_state(crtc->state); - if (acrtc->stream != NULL) { - const struct dc_stream_status *status = dc_stream_get_status(acrtc->stream); + if (new_acrtc_state->stream != NULL) { + const struct dc_stream_status *status = + dc_stream_get_status(new_acrtc_state->stream); if (!status) - DC_ERR("got no status for stream %p on acrtc%p\n", acrtc->stream, acrtc); + DC_ERR("got no status for stream %p on acrtc%p\n", new_acrtc_state->stream, acrtc); else acrtc->otg_inst = status->primary_otg_inst; } } + /* Handle scaling and undersacn changes*/ + for_each_connector_in_state(state, connector, old_conn_state, i) { + struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + struct dm_connector_state *con_new_state = + to_dm_connector_state(aconnector->base.state); + struct dm_connector_state *con_old_state = + to_dm_connector_state(old_conn_state); + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(con_new_state->base.crtc); + const struct dc_stream_status *status = NULL; + + /* Skip any modesets/resets */ + if (!acrtc || drm_atomic_crtc_needs_modeset(acrtc->base.state)) + continue; + + /* Skip any thing not scale or underscan changes */ + if (!is_scaling_state_different(con_new_state, con_old_state)) + continue; + + new_acrtc_state = to_dm_crtc_state(acrtc->base.state); + + update_stream_scaling_settings(&con_new_state->base.crtc->mode, + con_new_state, (struct dc_stream *)new_acrtc_state->stream); + + status = dc_stream_get_status(new_acrtc_state->stream); + WARN_ON(!status); + WARN_ON(!status->surface_count); + + if (!new_acrtc_state->stream) + continue; + + /*TODO How it works with MPO ?*/ + if (!dc_commit_surfaces_to_stream( + dm->dc, + (const struct dc_surface **)status->surfaces, + status->surface_count, + new_acrtc_state->stream)) + dm_error("%s: Failed to update stream scaling!\n", __func__); + } + for (i = 0; i < new_crtcs_count; i++) { /* * loop to enable interrupts on newly arrived crtc */ struct amdgpu_crtc *acrtc = new_crtcs[i]; + new_acrtc_state = to_dm_crtc_state(acrtc->base.state); if (adev->dm.freesync_module) mod_freesync_notify_mode_change( - adev->dm.freesync_module, &acrtc->stream, 1); + adev->dm.freesync_module, &new_acrtc_state->stream, 1); manage_dm_interrupts(adev, acrtc, true); } /* update planes when needed per crtc*/ for_each_crtc_in_state(state, pcrtc, old_crtc_state, j) { - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(pcrtc); + new_acrtc_state = to_dm_crtc_state(pcrtc->state); - if (acrtc->stream) + if (new_acrtc_state->stream) amdgpu_dm_commit_surfaces(state, dev, dm, pcrtc, &wait_for_vblank); } @@ -2822,13 +2832,15 @@ void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector { struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); struct amdgpu_crtc *disconnected_acrtc; + struct dm_crtc_state *acrtc_state; if (!aconnector->dc_sink || !connector->state || !connector->encoder) return; disconnected_acrtc = to_amdgpu_crtc(connector->encoder->crtc); + acrtc_state = to_dm_crtc_state(disconnected_acrtc->base.state); - if (!disconnected_acrtc || !disconnected_acrtc->stream) + if (!disconnected_acrtc || !acrtc_state->stream) return; /* @@ -2836,7 +2848,7 @@ void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector * we deduce we are in a state where we can not rely on usermode call * to turn on the display, so we do it here */ - if (disconnected_acrtc->stream->sink != aconnector->dc_sink) + if (acrtc_state->stream->sink != aconnector->dc_sink) dm_force_atomic_commit(&aconnector->base); } @@ -2880,17 +2892,11 @@ static uint32_t update_in_val_sets_stream( } val_sets[i].stream = new_stream; - dc_stream_retain(new_stream); crtcs[i] = crtc; - if (i == set_count) { + if (i == set_count) /* nothing found. add new one to the end */ return set_count + 1; - } else { - /* update. relase old stream */ - dc_stream_release(old_stream); - - } return set_count; } @@ -2911,7 +2917,6 @@ static uint32_t remove_from_val_sets( return set_count; } - dc_stream_release(stream); set_count--; for (; i < set_count; i++) { @@ -2981,14 +2986,16 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, struct drm_plane_state *plane_state; int i, j; int ret; - int new_stream_count; - struct dc_stream *new_streams[MAX_STREAMS] = { 0 }; struct drm_crtc *crtc_set[MAX_STREAMS] = { 0 }; struct amdgpu_device *adev = dev->dev_private; struct dc *dc = adev->dm.dc; bool need_to_validate = false; struct drm_connector *connector; struct drm_connector_state *conn_state; + int set_count; + struct dc_validation_set set[MAX_STREAMS] = { { 0 } }; + struct dm_crtc_state *old_acrtc_state, *new_acrtc_state; + /* * This bool will be set for true for any modeset/reset * or surface update which implies non fast surfae update. @@ -3008,17 +3015,16 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, dm_state = to_dm_atomic_state(state); /* copy existing configuration */ - new_stream_count = 0; - dm_state->set_count = 0; + set_count = 0; list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + old_acrtc_state = to_dm_crtc_state(crtc->state); - if (acrtc->stream) { - dc_stream_retain(acrtc->stream); - dm_state->set[dm_state->set_count].stream = acrtc->stream; - crtc_set[dm_state->set_count] = crtc; - ++dm_state->set_count; + if (old_acrtc_state->stream) { + dc_stream_retain(old_acrtc_state->stream); + set[set_count].stream = old_acrtc_state->stream; + crtc_set[set_count] = crtc; + ++set_count; } } @@ -3026,7 +3032,8 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, for_each_crtc_in_state(state, crtc, crtc_state, i) { struct amdgpu_crtc *acrtc = NULL; struct amdgpu_connector *aconnector = NULL; - + old_acrtc_state = to_dm_crtc_state(crtc->state); + new_acrtc_state = to_dm_crtc_state(crtc_state); acrtc = to_amdgpu_crtc(crtc); aconnector = amdgpu_dm_find_first_crct_matching_connector(state, crtc, true); @@ -3057,7 +3064,6 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, } new_stream = create_stream_for_sink(aconnector, &crtc_state->mode, dm_conn_state); - new_stream->priv = acrtc; /* * we can have no stream on ACTION_SET if a display @@ -3071,27 +3077,33 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, break; } - new_streams[new_stream_count] = new_stream; - dm_state->set_count = update_in_val_sets_stream( - dm_state->set, + if (new_acrtc_state->stream) + dc_stream_release(new_acrtc_state->stream); + new_acrtc_state->stream = new_stream; + + set_count = update_in_val_sets_stream( + set, crtc_set, - dm_state->set_count, - acrtc->stream, - new_stream, + set_count, + old_acrtc_state->stream, + new_acrtc_state->stream, crtc); - new_stream_count++; need_to_validate = true; aquire_global_lock = true; } else if (modereset_required(crtc_state)) { /* i.e. reset mode */ - if (acrtc->stream) { - dm_state->set_count = remove_from_val_sets( - dm_state->set, - dm_state->set_count, - acrtc->stream); + if (new_acrtc_state->stream) { + set_count = remove_from_val_sets( + set, + set_count, + new_acrtc_state->stream); + + dc_stream_release(new_acrtc_state->stream); + new_acrtc_state->stream = NULL; + aquire_global_lock = true; } } @@ -3112,6 +3124,10 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, } /* Check scaling and undersacn changes*/ + /*TODO Removed scaling changes validation due to inability to commit + * new stream into context w\o causing full reset. Need to + * decide how to handle. + */ for_each_connector_in_state(state, connector, conn_state, i) { struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); struct dm_connector_state *con_old_state = @@ -3119,7 +3135,6 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, struct dm_connector_state *con_new_state = to_dm_connector_state(conn_state); struct amdgpu_crtc *acrtc = to_amdgpu_crtc(con_new_state->base.crtc); - struct dc_stream *new_stream; /* Skip any modesets/resets */ if (!acrtc || drm_atomic_crtc_needs_modeset(acrtc->base.state)) @@ -3129,32 +3144,11 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, if (!is_scaling_state_different(con_new_state, con_old_state)) continue; - new_stream = create_stream_for_sink( - aconnector, - &acrtc->base.state->mode, - con_new_state); - - if (!new_stream) { - DRM_ERROR("%s: Failed to create new stream for crtc %d\n", - __func__, acrtc->base.base.id); - continue; - } - - new_streams[new_stream_count] = new_stream; - dm_state->set_count = update_in_val_sets_stream( - dm_state->set, - crtc_set, - dm_state->set_count, - acrtc->stream, - new_stream, - &acrtc->base); - - new_stream_count++; need_to_validate = true; aquire_global_lock = true; } - for (i = 0; i < dm_state->set_count; i++) { + for (i = 0; i < set_count; i++) { for_each_plane_in_state(state, plane, plane_state, j) { struct drm_crtc *crtc = plane_state->crtc; struct drm_framebuffer *fb = plane_state->fb; @@ -3210,9 +3204,9 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, plane_state, false); - add_val_sets_surface(dm_state->set, - dm_state->set_count, - dm_state->set[i].stream, + add_val_sets_surface(set, + set_count, + set[i].stream, surface); need_to_validate = true; @@ -3221,9 +3215,9 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, } } - dm_state->context = dc_get_validate_context(dc, dm_state->set, dm_state->set_count); + dm_state->context = dc_get_validate_context(dc, set, set_count); - if (need_to_validate == false || dm_state->set_count == 0 || dm_state->context) { + if (need_to_validate == false || set_count == 0 || dm_state->context) { ret = 0; /* * For full updates case when @@ -3239,6 +3233,21 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, } + /* TODO until surfaces are moved into dm_plane_state release them + * here + */ + for (i = 0; i < set_count; i++) + for (j = 0; j < set[i].surface_count; j++) + dc_surface_release(set[i].surfaces[j]); + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + old_acrtc_state = to_dm_crtc_state(crtc->state); + + if (old_acrtc_state->stream) + dc_stream_release(old_acrtc_state->stream); + } + + if (ret != 0) { if (ret == -EDEADLK) DRM_DEBUG_KMS("Atomic check stopped due to to deadlock.\n"); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h index 1e444cb5123d..36cb1c840810 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h @@ -45,7 +45,7 @@ struct dm_plane_state { struct dm_crtc_state { struct drm_crtc_state base; - struct dc_stream *dc_stream; + const struct dc_stream *stream; }; #define to_dm_crtc_state(x) container_of(x, struct dm_crtc_state, base) @@ -53,8 +53,6 @@ struct dm_crtc_state { struct dm_atomic_state { struct drm_atomic_state base; - struct dc_validation_set set[MAX_STREAMS]; - int set_count; struct validate_context *context; }; @@ -83,6 +81,11 @@ void amdgpu_dm_encoder_destroy(struct drm_encoder *encoder); int amdgpu_dm_connector_get_modes(struct drm_connector *connector); +int amdgpu_dm_atomic_commit( + struct drm_device *dev, + struct drm_atomic_state *state, + bool nonblock); + void amdgpu_dm_atomic_commit_tail( struct drm_atomic_state *state); diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 5d65416304b0..42c1aa8d68af 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -481,8 +481,6 @@ struct dc_stream { /* TODO: ABM info (DMCU) */ /* TODO: PSR info */ /* TODO: CEA VIC */ - - void *priv; }; struct dc_stream_update { -- cgit From f9ea47cec22ff332c2206249a18851c7eb68d832 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Wed, 5 Jul 2017 13:28:24 -0400 Subject: drm/amd/display: Undo dc_update_surfaces_and_stream change. Restoring conditional call to in_transfer_func since no reason to call it unconditionally. Signed-off-by: Andrey Grodzovsky Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 90a31509edd6..2f93f0e9ba84 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1603,10 +1603,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, if (update_type == UPDATE_TYPE_FAST) continue; - /* TODO find out why check is false */ - /* TODO with this still not programming some color stuff... panel is dark-ish */ - /*if (is_new_pipe_surface || - srf_updates[i].in_transfer_func)*/ + if (srf_updates[i].in_transfer_func) core_dc->hwss.set_input_transfer_func( pipe_ctx, pipe_ctx->surface); -- cgit From d5d4e09f5de96c986a47dc1ced334d6dc47a9959 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Sun, 4 Jun 2017 12:50:20 -0400 Subject: drm/amd/display: update DPM bounding box value based on STA target aligned to FCLK for SS corners with 10% margin also - group all latency together - group all voltage state related together Signed-off-by: Tony Cheng Reviewed-by: Eric Yang Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 71 ++++++++++++++++-------- 1 file changed, 48 insertions(+), 23 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 4486121e3986..58a4b2e90c15 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -36,40 +36,65 @@ /* Defaults from spreadsheet rev#247 */ const struct dcn_soc_bounding_box dcn10_soc_defaults = { - .sr_exit_time = 17, /*us*/ /*update based on HW Request for 118773*/ + /* latencies */ + .sr_exit_time = 17, /*us*/ .sr_enter_plus_exit_time = 19, /*us*/ .urgent_latency = 4, /*us*/ + .dram_clock_change_latency = 17, /*us*/ .write_back_latency = 12, /*us*/ .percent_of_ideal_drambw_received_after_urg_latency = 80, /*%*/ - .max_request_size = 256, /*bytes*/ - .dcfclkv_max0p9 = 600, /*MHz*/ - .dcfclkv_nom0p8 = 600, /*MHz*/ - .dcfclkv_mid0p72 = 300, /*MHz*/ - .dcfclkv_min0p65 = 300, /*MHz*/ - .max_dispclk_vmax0p9 = 1086, /*MHz*/ - .max_dispclk_vnom0p8 = 661, /*MHz*/ - .max_dispclk_vmid0p72 = 608, /*MHz*/ - .max_dispclk_vmin0p65 = 608, /*MHz*/ - .max_dppclk_vmax0p9 = 661, /*MHz*/ - .max_dppclk_vnom0p8 = 661, /*MHz*/ - .max_dppclk_vmid0p72 = 435, /*MHz*/ - .max_dppclk_vmin0p65 = 435, /*MHz*/ - .socclk = 208, /*MHz*/ + + /* below default clocks derived from STA target base on + * slow-slow corner + 10% margin with voltages aligned to FCLK. + * + * Use these value if fused value doesn't make sense as earlier + * part don't have correct value fused */ + /* default DCF CLK DPM on RV*/ + .dcfclkv_max0p9 = 655, /* MHz, = 3600/5.5 */ + .dcfclkv_nom0p8 = 626, /* MHz, = 3600/5.75 */ + .dcfclkv_mid0p72 = 600, /* MHz, = 3600/6, bypass */ + .dcfclkv_min0p65 = 300, /* MHz, = 3600/12, bypass */ + + /* default DISP CLK voltage state on RV */ + .max_dispclk_vmax0p9 = 1108, /* MHz, = 3600/3.25 */ + .max_dispclk_vnom0p8 = 1029, /* MHz, = 3600/3.5 */ + .max_dispclk_vmid0p72 = 960, /* MHz, = 3600/3.75 */ + .max_dispclk_vmin0p65 = 626, /* MHz, = 3600/5.75 */ + + /* default DPP CLK voltage state on RV */ + .max_dppclk_vmax0p9 = 720, /* MHz, = 3600/5 */ + .max_dppclk_vnom0p8 = 686, /* MHz, = 3600/5.25 */ + .max_dppclk_vmid0p72 = 626, /* MHz, = 3600/5.75 */ + .max_dppclk_vmin0p65 = 400, /* MHz, = 3600/9 */ + + /* default PHY CLK voltage state on RV */ + .phyclkv_max0p9 = 900, /*MHz*/ + .phyclkv_nom0p8 = 847, /*MHz*/ + .phyclkv_mid0p72 = 800, /*MHz*/ + .phyclkv_min0p65 = 600, /*MHz*/ + + /* BW depend on FCLK, MCLK, # of channels */ + /* dual channel BW */ .fabric_and_dram_bandwidth_vmax0p9 = 38.4f, /*GB/s*/ - .fabric_and_dram_bandwidth_vnom0p8 = 34.1f, /*GB/s*/ - .fabric_and_dram_bandwidth_vmid0p72 = 29.8f, /*GB/s*/ + .fabric_and_dram_bandwidth_vnom0p8 = 34.133f, /*GB/s*/ + .fabric_and_dram_bandwidth_vmid0p72 = 29.866f, /*GB/s*/ .fabric_and_dram_bandwidth_vmin0p65 = 12.8f, /*GB/s*/ - .phyclkv_max0p9 = 810, /*MHz*/ - .phyclkv_nom0p8 = 810, /*MHz*/ - .phyclkv_mid0p72 = 540, /*MHz*/ - .phyclkv_min0p65 = 540, /*MHz*/ + /* single channel BW + .fabric_and_dram_bandwidth_vmax0p9 = 19.2f, + .fabric_and_dram_bandwidth_vnom0p8 = 17.066f, + .fabric_and_dram_bandwidth_vmid0p72 = 14.933f, + .fabric_and_dram_bandwidth_vmin0p65 = 12.8f, + */ + + .number_of_channels = 2, + + .socclk = 208, /*MHz*/ .downspreading = 0.5f, /*%*/ .round_trip_ping_latency_cycles = 128, /*DCFCLK Cycles*/ .urgent_out_of_order_return_per_channel = 256, /*bytes*/ - .number_of_channels = 2, .vmm_page_size = 4096, /*bytes*/ - .dram_clock_change_latency = 17, /*us*/ .return_bus_width = 64, /*bytes*/ + .max_request_size = 256, /*bytes*/ }; const struct dcn_ip_params dcn10_ip_defaults = { -- cgit From f42485bb6d1171272d5ecb5b6213505b14294472 Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Tue, 4 Jul 2017 14:13:25 -0400 Subject: drm/amd/display: move number of memory channel calc out of pplib call Move number of memory channel calculation out of dcn_bw_update_from_pplib Fill in fabric_and_dram_bandwidth for single channel case. Signed-off-by: Eric Yang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 4 ---- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 13 +++++++++++++ 2 files changed, 13 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 58a4b2e90c15..93384a3f3525 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -1215,10 +1215,6 @@ void dcn_bw_update_from_pplib(struct core_dc *dc) struct dm_pp_clock_levels_with_voltage clks2 = {0}; kernel_fpu_begin(); - dc->dcn_soc.number_of_channels = dc->ctx->asic_id.vram_width / ddr4_dram_width; - ASSERT(dc->dcn_soc.number_of_channels && dc->dcn_soc.number_of_channels < 3); - if (dc->dcn_soc.number_of_channels == 0)/*old sbios bug*/ - dc->dcn_soc.number_of_channels = 2; if (dm_pp_get_clock_levels_by_type_with_voltage( ctx, DM_PP_CLOCK_TYPE_DISPLAY_CLK, &clks2) && diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index fcea49e9f665..66b5d3027336 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -1358,6 +1358,19 @@ static bool construct( dml_init_instance(&dc->dml, DML_PROJECT_RAVEN1); dc->dcn_ip = dcn10_ip_defaults; dc->dcn_soc = dcn10_soc_defaults; + + dc->dcn_soc.number_of_channels = dc->ctx->asic_id.vram_width / ddr4_dram_width; + ASSERT(dc->dcn_soc.number_of_channels < 3); + if (dc->dcn_soc.number_of_channels == 0)/*old sbios bug*/ + dc->dcn_soc.number_of_channels = 2; + + if (dc->dcn_soc.number_of_channels == 1) { + dc->dcn_soc.fabric_and_dram_bandwidth_vmax0p9 = 19.2f; + dc->dcn_soc.fabric_and_dram_bandwidth_vnom0p8 = 17.066f; + dc->dcn_soc.fabric_and_dram_bandwidth_vmid0p72 = 14.933f; + dc->dcn_soc.fabric_and_dram_bandwidth_vmin0p65 = 12.8f; + } + if (!dc->public.debug.disable_pplib_clock_request) dcn_bw_update_from_pplib(dc); dcn_bw_sync_calcs_and_dml(dc); -- cgit From 966443b592753f6498f896b4afc7c2df1352af72 Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Tue, 27 Jun 2017 12:09:01 -0400 Subject: drm/amd/display: block modes that require read bw greater than 30% Signed-off-by: Eric Yang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 18 +++++++++++++++++- drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h | 1 + 2 files changed, 18 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 93384a3f3525..24f8c4496a61 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -95,6 +95,9 @@ const struct dcn_soc_bounding_box dcn10_soc_defaults = { .vmm_page_size = 4096, /*bytes*/ .return_bus_width = 64, /*bytes*/ .max_request_size = 256, /*bytes*/ + + /* Depends on user class (client vs embedded, workstation, etc) */ + .percent_disp_bw_limit = 0.3f /*%*/ }; const struct dcn_ip_params dcn10_ip_defaults = { @@ -695,6 +698,8 @@ bool dcn_validate_bandwidth( struct dcn_bw_internal_vars *v = &context->dcn_bw_vars; int i, input_idx; int vesa_sync_start, asic_blank_end, asic_blank_start; + bool bw_limit_pass; + float bw_limit; if (dcn_bw_apply_registry_override(DC_TO_CORE(&dc->public))) dcn_bw_sync_calcs_and_dml(DC_TO_CORE(&dc->public)); @@ -1072,8 +1077,19 @@ bool dcn_validate_bandwidth( dc_core->dml.soc.sr_exit_time_us = dc_core->dcn_soc.sr_exit_time; } + /* + * BW limit is set to prevent display from impacting other system functions + */ + + bw_limit = dc->dcn_soc.percent_disp_bw_limit * v->fabric_and_dram_bandwidth_vmax0p9; + bw_limit_pass = (v->total_data_read_bandwidth / 1000.0) < bw_limit; + kernel_fpu_end(); - return v->voltage_level != 5; + + if (bw_limit_pass && v->voltage_level != 5) + return true; + else + return false; } unsigned int dcn_find_normalized_clock_vdd_Level( diff --git a/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h b/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h index 499bc1127696..b6cc07450f1f 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h @@ -572,6 +572,7 @@ struct dcn_soc_bounding_box { int vmm_page_size; /*bytes*/ float dram_clock_change_latency; /*us*/ int return_bus_width; /*bytes*/ + float percent_disp_bw_limit; /*%*/ }; extern const struct dcn_soc_bounding_box dcn10_soc_defaults; -- cgit From 133e8e1b35c7772f4903d367035e33e02becbb2d Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Wed, 5 Jul 2017 15:30:18 -0400 Subject: drm/amd/display: Change how we disable pipe split Before this change, pipe split was disabled by bumping up dpp clock bounding box for DPM level 0 and 1, this allows validation to pass without splitting at a lower DPM level. This change reverts this and instead lowers display clock at DPM level 0, this forces configurations that need pipe split at DPM level 0 to go to DPM level 1, where they can be driven without split. Signed-off-by: Eric Yang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 24f8c4496a61..3118c248409f 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -822,8 +822,7 @@ bool dcn_validate_bandwidth( v->phyclk_per_state[0] = v->phyclkv_min0p65; if (dc->public.debug.disable_pipe_split) { - v->max_dppclk[1] = v->max_dppclk_vnom0p8; - v->max_dppclk[0] = v->max_dppclk_vnom0p8; + v->max_dispclk[0] = v->max_dppclk_vmin0p65; } if (v->voltage_override == dcn_bw_v_max0p9) { -- cgit From b884a2ec5863c863a625ef4ee0efee59f969142d Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Thu, 6 Jul 2017 14:20:25 -0400 Subject: drm/amd/display: call pplib to update clocks Allow pplib to update fclk and dcfclk for different voltage levels. PPlib's values for dispclk and phyclk is not correct, so we are not getting it from them. fclk is currently not used correctly, although does not effect the actual fclk we request. Signed-off-by: Eric Yang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 46 +++--------------------- 1 file changed, 4 insertions(+), 42 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 3118c248409f..a1eabc47558e 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -1226,28 +1226,13 @@ unsigned int dcn_find_dcfclk_suits_all( void dcn_bw_update_from_pplib(struct core_dc *dc) { struct dc_context *ctx = dc->ctx; - struct dm_pp_clock_levels_with_latency clks = {0}; - struct dm_pp_clock_levels_with_voltage clks2 = {0}; + struct dm_pp_clock_levels_with_voltage clks = {0}; kernel_fpu_begin(); + /* TODO: This is not the proper way to obtain fabric_and_dram_bandwidth, should be min(fclk, memclk) */ + if (dm_pp_get_clock_levels_by_type_with_voltage( - ctx, DM_PP_CLOCK_TYPE_DISPLAY_CLK, &clks2) && - clks2.num_levels >= 3) { - dc->dcn_soc.max_dispclk_vmin0p65 = clks2.data[0].clocks_in_khz / 1000.0; - dc->dcn_soc.max_dispclk_vmid0p72 = clks2.data[clks2.num_levels - 3].clocks_in_khz / 1000.0; - dc->dcn_soc.max_dispclk_vnom0p8 = clks2.data[clks2.num_levels - 2].clocks_in_khz / 1000.0; - dc->dcn_soc.max_dispclk_vmax0p9 = clks2.data[clks2.num_levels - 1].clocks_in_khz / 1000.0; - } else - BREAK_TO_DEBUGGER(); -/* - if (dm_pp_get_clock_levels_by_type_with_latency( - ctx, DM_PP_CLOCK_TYPE_MEMORY_CLK, &clks) && - clks.num_levels != 0) { - //this is to get DRAM data_rate - //FabricAndDRAMBandwidth = min(64*FCLK , Data rate * single_Channel_Width * number of channels); - }*/ - if (dm_pp_get_clock_levels_by_type_with_latency( ctx, DM_PP_CLOCK_TYPE_FCLK, &clks) && clks.num_levels != 0) { ASSERT(clks.num_levels >= 3); @@ -1265,7 +1250,7 @@ void dcn_bw_update_from_pplib(struct core_dc *dc) (clks.data[clks.num_levels - 1].clocks_in_khz / 1000.0) * ddr4_dram_factor_single_Channel / 1000.0; } else BREAK_TO_DEBUGGER(); - if (dm_pp_get_clock_levels_by_type_with_latency( + if (dm_pp_get_clock_levels_by_type_with_voltage( ctx, DM_PP_CLOCK_TYPE_DCFCLK, &clks) && clks.num_levels >= 3) { dc->dcn_soc.dcfclkv_min0p65 = clks.data[0].clocks_in_khz / 1000.0; @@ -1274,30 +1259,7 @@ void dcn_bw_update_from_pplib(struct core_dc *dc) dc->dcn_soc.dcfclkv_max0p9 = clks.data[clks.num_levels - 1].clocks_in_khz / 1000.0; } else BREAK_TO_DEBUGGER(); - if (dm_pp_get_clock_levels_by_type_with_voltage( - ctx, DM_PP_CLOCK_TYPE_DISPLAYPHYCLK, &clks2) && - clks2.num_levels >= 3) { - dc->dcn_soc.phyclkv_min0p65 = clks2.data[0].clocks_in_khz / 1000.0; - dc->dcn_soc.phyclkv_mid0p72 = clks2.data[clks2.num_levels - 3].clocks_in_khz / 1000.0; - dc->dcn_soc.phyclkv_nom0p8 = clks2.data[clks2.num_levels - 2].clocks_in_khz / 1000.0; - dc->dcn_soc.phyclkv_max0p9 = clks2.data[clks2.num_levels - 1].clocks_in_khz / 1000.0; - } else - BREAK_TO_DEBUGGER(); - if (dm_pp_get_clock_levels_by_type_with_latency( - ctx, DM_PP_CLOCK_TYPE_DPPCLK, &clks) && - clks.num_levels >= 3) { - dc->dcn_soc.max_dppclk_vmin0p65 = clks.data[0].clocks_in_khz / 1000.0; - dc->dcn_soc.max_dppclk_vmid0p72 = clks.data[clks.num_levels - 3].clocks_in_khz / 1000.0; - dc->dcn_soc.max_dppclk_vnom0p8 = clks.data[clks.num_levels - 2].clocks_in_khz / 1000.0; - dc->dcn_soc.max_dppclk_vmax0p9 = clks.data[clks.num_levels - 1].clocks_in_khz / 1000.0; - } - if (dm_pp_get_clock_levels_by_type_with_latency( - ctx, DM_PP_CLOCK_TYPE_SOCCLK, &clks) && - clks.num_levels >= 3) { - dc->dcn_soc.socclk = clks.data[0].clocks_in_khz / 1000.0; - } else - BREAK_TO_DEBUGGER(); kernel_fpu_end(); } -- cgit From fa6ecfc67a4a0f96b5e4b6d5437602f2d5b191ac Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Thu, 6 Jul 2017 13:53:15 -0400 Subject: drm/amd/display: Refactor dc_commit_streams Change it to sue dc_commit_context. dc_commit_context is used directly from Linux DM. Signed-off-by: Andrey Grodzovsky Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 99 +++++++++++++------------------- 1 file changed, 41 insertions(+), 58 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 2f93f0e9ba84..52077d39b30a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -913,33 +913,22 @@ bool dc_enable_stereo( return ret; } -/* TODO operate on validation set (or something like it) */ -bool dc_commit_context(struct dc *dc, struct validate_context *context) + +/* + * Applies given context to HW and copy it into current context. + * It's up to the user to release the src context afterwards. + */ +static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *context) { struct core_dc *core_dc = DC_TO_CORE(dc); struct dc_bios *dcb = core_dc->ctx->dc_bios; enum dc_status result = DC_ERROR_UNEXPECTED; struct pipe_ctx *pipe; int i, j, k, l; + const struct dc_stream *dc_streams[MAX_STREAMS] = {0}; - if (!context) - dm_logger_write(core_dc->ctx->logger, LOG_ERROR, - "%s: dc_commit_context with no context!\n", - __func__); - - if (false == context_changed(core_dc, context)) - return DC_OK; - - dm_logger_write(core_dc->ctx->logger, LOG_DC, "%s: %d streams\n", - __func__, context->stream_count); - - for (i = 0; i < context->stream_count; i++) { - const struct dc_stream *stream = &context->streams[i]->public; - - dc_stream_log(stream, - core_dc->ctx->logger, - LOG_DC); - } + for (i = 0; i < context->stream_count; i++) + dc_streams[i] = &context->streams[i]->public; if (!dcb->funcs->is_accelerated_mode(dcb)) core_dc->hwss.enable_accelerated_mode(core_dc); @@ -981,22 +970,49 @@ bool dc_commit_context(struct dc *dc, struct validate_context *context) context->streams[i]->public.timing.pix_clk_khz); } + dc_enable_stereo(dc, context, dc_streams, context->stream_count); + dc_resource_validate_ctx_copy_construct(context, core_dc->current_context); return (result == DC_OK); } +bool dc_commit_context(struct dc *dc, struct validate_context *context) +{ + enum dc_status result = DC_ERROR_UNEXPECTED; + struct core_dc *core_dc = DC_TO_CORE(dc); + int i; + + if (false == context_changed(core_dc, context)) + return DC_OK; + + dm_logger_write(core_dc->ctx->logger, LOG_DC, "%s: %d streams\n", + __func__, context->stream_count); + + for (i = 0; i < context->stream_count; i++) { + const struct dc_stream *stream = &context->streams[i]->public; + + dc_stream_log(stream, + core_dc->ctx->logger, + LOG_DC); + } + + result = dc_commit_context_no_check(dc, context); + + return (result == DC_OK); +} + + bool dc_commit_streams( struct dc *dc, const struct dc_stream *streams[], uint8_t stream_count) { struct core_dc *core_dc = DC_TO_CORE(dc); - struct dc_bios *dcb = core_dc->ctx->dc_bios; enum dc_status result = DC_ERROR_UNEXPECTED; struct validate_context *context; struct dc_validation_set set[MAX_STREAMS] = { {0, {0} } }; - int i, j; + int i; if (false == streams_changed(core_dc, streams, stream_count)) return DC_OK; @@ -1039,43 +1055,10 @@ bool dc_commit_streams( goto fail; } - if (!dcb->funcs->is_accelerated_mode(dcb)) { - core_dc->hwss.enable_accelerated_mode(core_dc); - } - - if (result == DC_OK) { - result = core_dc->hwss.apply_ctx_to_hw(core_dc, context); - } - - program_timing_sync(core_dc, context); - - for (i = 0; i < context->stream_count; i++) { - const struct core_sink *sink = context->streams[i]->sink; - - for (j = 0; j < context->stream_status[i].surface_count; j++) { - struct core_surface *surface = - DC_SURFACE_TO_CORE(context->stream_status[i].surfaces[j]); - - core_dc->hwss.apply_ctx_for_surface(core_dc, surface, context); - } + result = dc_commit_context_no_check(dc, context); - CONN_MSG_MODE(sink->link, "{%ux%u, %ux%u@%u, %ux%u@%uKhz}", - context->streams[i]->public.src.width, - context->streams[i]->public.src.height, - context->streams[i]->public.timing.h_addressable, - context->streams[i]->public.timing.v_addressable, - context->streams[i]->public.timing.pix_clk_khz * 1000 / - context->streams[i]->public.timing.h_total / - context->streams[i]->public.timing.v_total, // Refresh rate - context->streams[i]->public.timing.h_total, - context->streams[i]->public.timing.v_total, - context->streams[i]->public.timing.pix_clk_khz); - } - dc_enable_stereo(dc, context, streams, stream_count); - dc_resource_validate_ctx_destruct(core_dc->current_context); - dm_free(core_dc->current_context); - - core_dc->current_context = context; + dc_resource_validate_ctx_destruct(context); + dm_free(context); return (result == DC_OK); -- cgit From 184debdbd80bd9d47eb68304417adb6580ff09e4 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 5 Jul 2017 06:57:49 -0400 Subject: drm/amd/display: refactor dcn10 hw_sequencer to new reg access style Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h | 177 ++++++- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 530 +++++---------------- drivers/gpu/drm/amd/display/dc/inc/reg_helper.h | 66 ++- 3 files changed, 343 insertions(+), 430 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index 112f9c85c142..761dba3562b2 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -122,11 +122,56 @@ HWSEQ_PHYPLL_REG_LIST(CRTC) #if defined(CONFIG_DRM_AMD_DC_DCN1_0) -#define HWSEQ_DCN1_REG_LIST()\ +#define HWSEQ_DCN_REG_LIST()\ HWSEQ_PIXEL_RATE_REG_LIST(OTG), \ - HWSEQ_PHYPLL_REG_LIST(OTG) + HWSEQ_PHYPLL_REG_LIST(OTG), \ + SRII(OTG_GLOBAL_SYNC_STATUS, OTG, 0), \ + SRII(OTG_GLOBAL_SYNC_STATUS, OTG, 1), \ + SRII(OTG_GLOBAL_SYNC_STATUS, OTG, 2), \ + SRII(OTG_GLOBAL_SYNC_STATUS, OTG, 3), \ + SRII(DCHUBP_CNTL, HUBP, 0), \ + SRII(DCHUBP_CNTL, HUBP, 1), \ + SRII(DCHUBP_CNTL, HUBP, 2), \ + SRII(DCHUBP_CNTL, HUBP, 3), \ + SRII(HUBP_CLK_CNTL, HUBP, 0), \ + SRII(HUBP_CLK_CNTL, HUBP, 1), \ + SRII(HUBP_CLK_CNTL, HUBP, 2), \ + SRII(HUBP_CLK_CNTL, HUBP, 3), \ + SRII(DPP_CONTROL, DPP_TOP, 0), \ + SRII(DPP_CONTROL, DPP_TOP, 1), \ + SRII(DPP_CONTROL, DPP_TOP, 2), \ + SRII(DPP_CONTROL, DPP_TOP, 3), \ + SR(REFCLK_CNTL), \ + SR(DCHUBBUB_GLOBAL_TIMER_CNTL), \ + SR(DC_IP_REQUEST_CNTL), \ + SR(DOMAIN0_PG_CONFIG), \ + SR(DOMAIN1_PG_CONFIG), \ + SR(DOMAIN2_PG_CONFIG), \ + SR(DOMAIN3_PG_CONFIG), \ + SR(DOMAIN4_PG_CONFIG), \ + SR(DOMAIN5_PG_CONFIG), \ + SR(DOMAIN6_PG_CONFIG), \ + SR(DOMAIN7_PG_CONFIG), \ + SR(DOMAIN0_PG_STATUS), \ + SR(DOMAIN1_PG_STATUS), \ + SR(DOMAIN2_PG_STATUS), \ + SR(DOMAIN3_PG_STATUS), \ + SR(DOMAIN4_PG_STATUS), \ + SR(DOMAIN5_PG_STATUS), \ + SR(DOMAIN6_PG_STATUS), \ + SR(DOMAIN7_PG_STATUS), \ + SR(DIO_MEM_PWR_CTRL), \ + SR(DCCG_GATE_DISABLE_CNTL), \ + SR(DCCG_GATE_DISABLE_CNTL2), \ + SR(DCFCLK_CNTL) +#endif + +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +#define HWSEQ_DCN1_REG_LIST()\ + HWSEQ_DCN_REG_LIST() #endif + struct dce_hwseq_registers { uint32_t DCFE_CLOCK_CONTROL[6]; uint32_t DCFEV_CLOCK_CONTROL; @@ -134,13 +179,39 @@ struct dce_hwseq_registers { uint32_t BLND_V_UPDATE_LOCK[6]; uint32_t BLND_CONTROL[6]; uint32_t BLNDV_CONTROL; - -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) - /* DCE + DCN */ -#endif uint32_t CRTC_H_BLANK_START_END[6]; uint32_t PIXEL_RATE_CNTL[6]; uint32_t PHYPLL_PIXEL_RATE_CNTL[6]; + +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + uint32_t OTG_GLOBAL_SYNC_STATUS[4]; + uint32_t DCHUBP_CNTL[4]; + uint32_t HUBP_CLK_CNTL[4]; + uint32_t DPP_CONTROL[4]; + uint32_t REFCLK_CNTL; + uint32_t DCHUBBUB_GLOBAL_TIMER_CNTL; + uint32_t DC_IP_REQUEST_CNTL; + uint32_t DOMAIN0_PG_CONFIG; + uint32_t DOMAIN1_PG_CONFIG; + uint32_t DOMAIN2_PG_CONFIG; + uint32_t DOMAIN3_PG_CONFIG; + uint32_t DOMAIN4_PG_CONFIG; + uint32_t DOMAIN5_PG_CONFIG; + uint32_t DOMAIN6_PG_CONFIG; + uint32_t DOMAIN7_PG_CONFIG; + uint32_t DOMAIN0_PG_STATUS; + uint32_t DOMAIN1_PG_STATUS; + uint32_t DOMAIN2_PG_STATUS; + uint32_t DOMAIN3_PG_STATUS; + uint32_t DOMAIN4_PG_STATUS; + uint32_t DOMAIN5_PG_STATUS; + uint32_t DOMAIN6_PG_STATUS; + uint32_t DOMAIN7_PG_STATUS; + uint32_t DIO_MEM_PWR_CTRL; + uint32_t DCCG_GATE_DISABLE_CNTL; + uint32_t DCCG_GATE_DISABLE_CNTL2; + uint32_t DCFCLK_CNTL; +#endif }; /* set field name */ #define HWS_SF(blk_name, reg_name, field_name, post_fix)\ @@ -202,12 +273,52 @@ struct dce_hwseq_registers { HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, CRTC0_) #if defined(CONFIG_DRM_AMD_DC_DCN1_0) -#define HWSEQ_DCN1_MASK_SH_LIST(mask_sh)\ +#define HWSEQ_DCN_MASK_SH_LIST(mask_sh)\ HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, OTG0_),\ - HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, OTG0_) + HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, OTG0_),\ + HWS_SF(OTG0_, OTG_GLOBAL_SYNC_STATUS, VUPDATE_NO_LOCK_EVENT_CLEAR, mask_sh), \ + HWS_SF(OTG0_, OTG_GLOBAL_SYNC_STATUS, VUPDATE_NO_LOCK_EVENT_OCCURRED, mask_sh), \ + HWS_SF(HUBP0_, DCHUBP_CNTL, HUBP_NO_OUTSTANDING_REQ, mask_sh), \ + HWS_SF(HUBP0_, DCHUBP_CNTL, HUBP_VTG_SEL, mask_sh), \ + HWS_SF(HUBP0_, HUBP_CLK_CNTL, HUBP_CLOCK_ENABLE, mask_sh), \ + HWS_SF(DPP_TOP0_, DPP_CONTROL, DPP_CLOCK_ENABLE, mask_sh), \ + HWS_SF(, DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, mask_sh), \ + HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh), \ + HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN0_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN0_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN1_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN1_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN2_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN2_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN3_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN3_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN4_PG_CONFIG, DOMAIN4_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN4_PG_CONFIG, DOMAIN4_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN5_PG_CONFIG, DOMAIN5_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN5_PG_CONFIG, DOMAIN5_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN6_PG_CONFIG, DOMAIN6_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN6_PG_CONFIG, DOMAIN6_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN7_PG_CONFIG, DOMAIN7_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN7_PG_CONFIG, DOMAIN7_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN0_PG_STATUS, DOMAIN0_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN1_PG_STATUS, DOMAIN1_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN2_PG_STATUS, DOMAIN2_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN3_PG_STATUS, DOMAIN3_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN4_PG_STATUS, DOMAIN4_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN5_PG_STATUS, DOMAIN5_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN6_PG_STATUS, DOMAIN6_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN7_PG_STATUS, DOMAIN7_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DCFCLK_CNTL, DCFCLK_GATE_DIS, mask_sh) +#endif + +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +#define HWSEQ_DCN1_MASK_SH_LIST(mask_sh)\ + HWSEQ_DCN_MASK_SH_LIST(mask_sh), \ + HWS_SF1(OTG0_, PHYPLL_PIXEL_RATE_CNTL, PIXEL_RATE_PLL_SOURCE, mask_sh), \ + HWS_SF(DPP_TOP0_, DPP_CONTROL, DPPCLK_RATE_CONTROL, mask_sh) #endif -#define HWSEQ_REG_FIED_LIST(type) \ +#define HWSEQ_REG_FIELD_LIST(type) \ type DCFE_CLOCK_ENABLE; \ type DCFEV_CLOCK_ENABLE; \ type DC_MEM_GLOBAL_PWR_REQ_DIS; \ @@ -225,12 +336,56 @@ struct dce_hwseq_registers { type PHYPLL_PIXEL_RATE_SOURCE; \ type PIXEL_RATE_PLL_SOURCE; \ +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +#define HWSEQ_DCN_REG_FIELD_LIST(type) \ + type VUPDATE_NO_LOCK_EVENT_CLEAR; \ + type VUPDATE_NO_LOCK_EVENT_OCCURRED; \ + type HUBP_NO_OUTSTANDING_REQ; \ + type HUBP_VTG_SEL; \ + type HUBP_CLOCK_ENABLE; \ + type DPP_CLOCK_ENABLE; \ + type DPPCLK_RATE_CONTROL; \ + type DCHUBBUB_GLOBAL_TIMER_ENABLE; \ + type IP_REQUEST_EN; \ + type DOMAIN0_POWER_FORCEON; \ + type DOMAIN0_POWER_GATE; \ + type DOMAIN1_POWER_FORCEON; \ + type DOMAIN1_POWER_GATE; \ + type DOMAIN2_POWER_FORCEON; \ + type DOMAIN2_POWER_GATE; \ + type DOMAIN3_POWER_FORCEON; \ + type DOMAIN3_POWER_GATE; \ + type DOMAIN4_POWER_FORCEON; \ + type DOMAIN4_POWER_GATE; \ + type DOMAIN5_POWER_FORCEON; \ + type DOMAIN5_POWER_GATE; \ + type DOMAIN6_POWER_FORCEON; \ + type DOMAIN6_POWER_GATE; \ + type DOMAIN7_POWER_FORCEON; \ + type DOMAIN7_POWER_GATE; \ + type DOMAIN0_PGFSM_PWR_STATUS; \ + type DOMAIN1_PGFSM_PWR_STATUS; \ + type DOMAIN2_PGFSM_PWR_STATUS; \ + type DOMAIN3_PGFSM_PWR_STATUS; \ + type DOMAIN4_PGFSM_PWR_STATUS; \ + type DOMAIN5_PGFSM_PWR_STATUS; \ + type DOMAIN6_PGFSM_PWR_STATUS; \ + type DOMAIN7_PGFSM_PWR_STATUS; \ + type DCFCLK_GATE_DIS; +#endif + struct dce_hwseq_shift { - HWSEQ_REG_FIED_LIST(uint8_t) + HWSEQ_REG_FIELD_LIST(uint8_t) +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + HWSEQ_DCN_REG_FIELD_LIST(uint8_t) +#endif }; struct dce_hwseq_mask { - HWSEQ_REG_FIED_LIST(uint32_t) + HWSEQ_REG_FIELD_LIST(uint32_t) +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + HWSEQ_DCN_REG_FIELD_LIST(uint32_t) +#endif }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index d38570e6d4d2..fb326316b08b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -33,381 +33,120 @@ #include "dce110/dce110_hw_sequencer.h" #include "dce/dce_hwseq.h" #include "abm.h" - -#include "dcn10/dcn10_transform.h" -#include "dcn10/dcn10_mpc.h" -#include "dcn10/dcn10_timing_generator.h" - #include "mem_input.h" #include "timing_generator.h" #include "opp.h" #include "ipp.h" - #include "dc_bios_types.h" - #include "raven1/DCN/dcn_1_0_offset.h" #include "raven1/DCN/dcn_1_0_sh_mask.h" #include "vega10/soc15ip.h" - #include "custom_float.h" +#include "reg_helper.h" +#define CTX \ + hws->ctx +#define REG(reg)\ + hws->regs->reg -struct dcn10_hwseq_reg_offsets { - uint32_t dchubp; - uint32_t dpp; - uint32_t otg; - uint32_t vtg; - uint32_t fmt; -}; - -/* TODO: move to resource */ -static const struct dcn10_hwseq_reg_offsets reg_offsets[] = { - { - .dchubp = (mmHUBP0_DCHUBP_CNTL - mmHUBP0_DCHUBP_CNTL), - .dpp = (mmCM0_CM_DGAM_CONTROL - mmCM0_CM_DGAM_CONTROL), - .otg = (mmOTG0_OTG_CONTROL - mmOTG0_OTG_CONTROL), - .vtg = (mmVTG0_CONTROL - mmVTG0_CONTROL), - .fmt = (mmFMT0_FMT_BIT_DEPTH_CONTROL - - mmFMT0_FMT_BIT_DEPTH_CONTROL), - }, - { - .dchubp = (mmHUBP1_DCHUBP_CNTL - mmHUBP0_DCHUBP_CNTL), - .dpp = (mmCM1_CM_DGAM_CONTROL - mmCM0_CM_DGAM_CONTROL), - .otg = (mmOTG1_OTG_CONTROL - mmOTG0_OTG_CONTROL), - .vtg = (mmVTG1_CONTROL - mmVTG0_CONTROL), - .fmt = (mmFMT1_FMT_BIT_DEPTH_CONTROL - - mmFMT0_FMT_BIT_DEPTH_CONTROL), - }, - { - .dchubp = (mmHUBP2_DCHUBP_CNTL - mmHUBP0_DCHUBP_CNTL), - .dpp = (mmCM2_CM_DGAM_CONTROL - mmCM0_CM_DGAM_CONTROL), - .otg = (mmOTG2_OTG_CONTROL - mmOTG0_OTG_CONTROL), - .vtg = (mmVTG2_CONTROL - mmVTG0_CONTROL), - .fmt = (mmFMT2_FMT_BIT_DEPTH_CONTROL - - mmFMT0_FMT_BIT_DEPTH_CONTROL), - }, - { - .dchubp = (mmHUBP3_DCHUBP_CNTL - mmHUBP0_DCHUBP_CNTL), - .dpp = (mmCM3_CM_DGAM_CONTROL - mmCM0_CM_DGAM_CONTROL), - .otg = (mmOTG3_OTG_CONTROL - mmOTG0_OTG_CONTROL), - .vtg = (mmVTG3_CONTROL - mmVTG0_CONTROL), - .fmt = (mmFMT3_FMT_BIT_DEPTH_CONTROL - - mmFMT0_FMT_BIT_DEPTH_CONTROL), - } -}; - -#define HWSEQ_REG_UPDATE_N(reg_name, n, ...) \ - generic_reg_update_soc15(ctx, inst_offset, reg_name, n, __VA_ARGS__) - -#define HWSEQ_REG_SET_N(reg_name, n, ...) \ - generic_reg_set_soc15(ctx, inst_offset, reg_name, n, __VA_ARGS__) - -#define HWSEQ_REG_UPDATE(reg, field, val) \ - HWSEQ_REG_UPDATE_N(reg, 1, FD(reg##__##field), val) - -#define HWSEQ_REG_UPDATE_2(reg, field1, val1, field2, val2) \ - HWSEQ_REG_UPDATE_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) - -#define HWSEQ_REG_UPDATE_3(reg, field1, val1, field2, val2, field3, val3) \ - HWSEQ_REG_UPDATE_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3) - - -#define HWSEQ_REG_SET(reg, field, val) \ - HWSEQ_REG_SET_N(reg, 1, FD(reg##__##field), val) - -/* TODO should be moved to OTG */ - -static bool unlock_master_tg_and_wait( - struct dc_context *ctx, - uint8_t inst) -{ - uint32_t inst_offset = reg_offsets[inst].otg; - - HWSEQ_REG_UPDATE(OTG0_OTG_GLOBAL_SYNC_STATUS, - VUPDATE_NO_LOCK_EVENT_CLEAR, 1); - HWSEQ_REG_UPDATE(OTG0_OTG_MASTER_UPDATE_LOCK, OTG_MASTER_UPDATE_LOCK, 0); - - if (!wait_reg(ctx, inst_offset, OTG0_OTG_GLOBAL_SYNC_STATUS, VUPDATE_NO_LOCK_EVENT_OCCURRED, 1)) { - dm_logger_write(ctx->logger, LOG_ERROR, - "wait for VUPDATE_NO_LOCK_EVENT_OCCURRED failed\n"); - BREAK_TO_DEBUGGER(); - return false; - } - return true; -} - -static void wait_no_outstanding_request( - struct dc_context *ctx, - uint8_t plane_id) -{ - uint32_t inst_offset = reg_offsets[plane_id].dchubp; - - if (!wait_reg(ctx, inst_offset, HUBP0_DCHUBP_CNTL, HUBP_NO_OUTSTANDING_REQ, 1)) - BREAK_TO_DEBUGGER(); -} +#undef FN +#define FN(reg_name, field_name) \ + hws->shifts->field_name, hws->masks->field_name static void disable_clocks( - struct dc_context *ctx, + struct dce_hwseq *hws, uint8_t plane_id) { - uint32_t inst_offset = reg_offsets[plane_id].dchubp; - - generic_reg_update_soc15(ctx, inst_offset, HUBP0_HUBP_CLK_CNTL, 1, - FD(HUBP0_HUBP_CLK_CNTL__HUBP_CLOCK_ENABLE), 0); + REG_UPDATE(HUBP_CLK_CNTL[plane_id], HUBP_CLOCK_ENABLE, 0); - inst_offset = reg_offsets[plane_id].dpp; - generic_reg_update_soc15(ctx, inst_offset, DPP_TOP0_DPP_CONTROL, 1, - FD(DPP_TOP0_DPP_CONTROL__DPP_CLOCK_ENABLE), 0); -} - -/* TODO: This is one time program during system boot up, - * this should be done within BIOS or CAIL - */ -static void dchubp_map_fb_to_mc(struct dc_context *ctx) -{ - /* TODO: do not know where to program - * DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB - */ - /* - * TODO: For real ASIC, FB_OFFSET may be need change to the same value - * as FB_BASE. Need re-visit this for real ASIC. - */ - dm_write_reg_soc15(ctx, mmDCHUBBUB_SDPIF_FB_BASE, 0, 0x80); - dm_write_reg_soc15(ctx, mmDCHUBBUB_SDPIF_FB_OFFSET, 0, 0); - dm_write_reg_soc15(ctx, mmDCHUBBUB_SDPIF_FB_TOP, 0, 0xFF); - - generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_CFG0, 7, - FD(DCHUBBUB_SDPIF_CFG0__SDPIF_DATA_RESPONSE_STATUS_CLEAR), 0, - FD(DCHUBBUB_SDPIF_CFG0__SDPIF_REQ_CREDIT_ERROR_CLEAR), 0, - FD(DCHUBBUB_SDPIF_CFG0__SDPIF_FLUSH_REQ_CREDIT_EN), 0, - FD(DCHUBBUB_SDPIF_CFG0__SDPIF_REQ_CREDIT_EN), 0, - FD(DCHUBBUB_SDPIF_CFG0__SDPIF_PORT_CONTROL), 1, - FD(DCHUBBUB_SDPIF_CFG0__SDPIF_UNIT_ID_BITMASK), 0xd3, - FD(DCHUBBUB_SDPIF_CFG0__SDPIF_CREDIT_DISCONNECT_DELAY), 0xc); - - - generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_CFG1, 4, - FD(DCHUBBUB_SDPIF_CFG1__SDPIF_INSIDE_FB_IO), 0, - FD(DCHUBBUB_SDPIF_CFG1__SDPIF_INSIDE_FB_VC), 6, - FD(DCHUBBUB_SDPIF_CFG1__SDPIF_OUTSIDE_FB_IO), 1, - FD(DCHUBBUB_SDPIF_CFG1__SDPIF_OUTSIDE_FB_VC), 6); - - generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_FB_BASE, 1, - FD(DCHUBBUB_SDPIF_FB_BASE__SDPIF_FB_BASE), 0x000080); - - generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_FB_TOP, 1, - FD(DCHUBBUB_SDPIF_FB_TOP__SDPIF_FB_TOP), 0x0000ff); - - generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_AGP_BOT, 1, - FD(DCHUBBUB_SDPIF_AGP_BOT__SDPIF_AGP_BOT), 0x0000040); - - generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_AGP_TOP, 1, - FD(DCHUBBUB_SDPIF_AGP_TOP__SDPIF_AGP_TOP), 0x00001ff); - - generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_AGP_BASE, 1, - FD(DCHUBBUB_SDPIF_AGP_BASE__SDPIF_AGP_BASE), 0x0000080); - - generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_APER_TOP, 1, - FD(DCHUBBUB_SDPIF_APER_TOP__SDPIF_APER_TOP), 0x00007ff); - - generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_APER_DEF_0, 1, - FD(DCHUBBUB_SDPIF_APER_DEF_0__SDPIF_APER_DEF_0), 0xdeadbeef); - - generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_RELOC_LO_0, 2, - FD(DCHUBBUB_SDPIF_MARC_RELOC_LO_0__SDPIF_MARC_EN_0), 0, - FD(DCHUBBUB_SDPIF_MARC_RELOC_LO_0__SDPIF_MARC_RELOC_LO_0), 0x90000); - - generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_LENGTH_LO_0, 1, - FD(DCHUBBUB_SDPIF_MARC_LENGTH_LO_0__SDPIF_MARC_LENGTH_LO_0), 0x10000); - - generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_BASE_LO_1, 1, - FD(DCHUBBUB_SDPIF_MARC_BASE_LO_1__SDPIF_MARC_BASE_LO_1), 0x10000); - - generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_RELOC_LO_1, 2, - FD(DCHUBBUB_SDPIF_MARC_RELOC_LO_1__SDPIF_MARC_EN_1), 0, - FD(DCHUBBUB_SDPIF_MARC_RELOC_LO_1__SDPIF_MARC_RELOC_LO_1), 0xa0000); - - generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_LENGTH_LO_1, 1, - FD(DCHUBBUB_SDPIF_MARC_LENGTH_LO_1__SDPIF_MARC_LENGTH_LO_1), 0x10000); - - generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_BASE_LO_2, 1, - FD(DCHUBBUB_SDPIF_MARC_BASE_LO_2__SDPIF_MARC_BASE_LO_2), 0x20000); - - generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_RELOC_LO_2, 2, - FD(DCHUBBUB_SDPIF_MARC_RELOC_LO_2__SDPIF_MARC_EN_2), 0, - FD(DCHUBBUB_SDPIF_MARC_RELOC_LO_2__SDPIF_MARC_RELOC_LO_2), 0xb0000); - - generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_LENGTH_LO_2, 1, - FD(DCHUBBUB_SDPIF_MARC_LENGTH_LO_2__SDPIF_MARC_LENGTH_LO_2), 0x10000); - - generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_BASE_LO_3, 1, - FD(DCHUBBUB_SDPIF_MARC_BASE_LO_3__SDPIF_MARC_BASE_LO_3), 0x30000); - - generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_RELOC_LO_3, 2, - FD(DCHUBBUB_SDPIF_MARC_RELOC_LO_3__SDPIF_MARC_EN_3), 0, - FD(DCHUBBUB_SDPIF_MARC_RELOC_LO_3__SDPIF_MARC_RELOC_LO_3), 0xc0000); - - generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_LENGTH_LO_3, 1, - FD(DCHUBBUB_SDPIF_MARC_LENGTH_LO_3__SDPIF_MARC_LENGTH_LO_3), 0x10000); - - /* TODO: Is DCN_VM_SYSTEM_APERTURE address one time programming? - * Are all 4 hubp programmed with the same address? - */ - dm_write_reg_soc15(ctx, mmHUBPREQ0_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, 0, 0x80000); - dm_write_reg_soc15(ctx, mmHUBPREQ0_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, 0, 0); - dm_write_reg_soc15(ctx, mmHUBPREQ0_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, 0, 0x100000); - dm_write_reg_soc15(ctx, mmHUBPREQ0_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, 0, 0); - dm_write_reg_soc15(ctx, mmHUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, 0, 0x80000); - dm_write_reg_soc15(ctx, mmHUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, 0, 0); - - dm_write_reg_soc15(ctx, mmHUBPREQ1_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, 0, 0x80000); - dm_write_reg_soc15(ctx, mmHUBPREQ1_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, 0, 0); - dm_write_reg_soc15(ctx, mmHUBPREQ1_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, 0, 0x100000); - dm_write_reg_soc15(ctx, mmHUBPREQ1_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, 0, 0); - dm_write_reg_soc15(ctx, mmHUBPREQ1_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, 0, 0x80000); - dm_write_reg_soc15(ctx, mmHUBPREQ1_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, 0, 0); - - dm_write_reg_soc15(ctx, mmHUBPREQ2_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, 0, 0x80000); - dm_write_reg_soc15(ctx, mmHUBPREQ2_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, 0, 0); - dm_write_reg_soc15(ctx, mmHUBPREQ2_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, 0, 0x100000); - dm_write_reg_soc15(ctx, mmHUBPREQ2_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, 0, 0); - dm_write_reg_soc15(ctx, mmHUBPREQ2_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, 0, 0x80000); - dm_write_reg_soc15(ctx, mmHUBPREQ2_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, 0, 0); - - dm_write_reg_soc15(ctx, mmHUBPREQ3_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, 0, 0x80000); - dm_write_reg_soc15(ctx, mmHUBPREQ3_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, 0, 0); - dm_write_reg_soc15(ctx, mmHUBPREQ3_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, 0, 0x100000); - dm_write_reg_soc15(ctx, mmHUBPREQ3_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, 0, 0); - dm_write_reg_soc15(ctx, mmHUBPREQ3_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, 0, 0x80000); - dm_write_reg_soc15(ctx, mmHUBPREQ3_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, 0, 0); -} - -/* TODO: This is one time program during system boot up, - * this should be done within BIOS - */ -static void dchubup_setup_timer(struct dc_context *ctx) -{ - dm_write_reg_soc15(ctx, mmREFCLK_CNTL, 0, 0); - - generic_reg_update_soc15(ctx, 0, DCHUBBUB_GLOBAL_TIMER_CNTL, 1, - FD(DCHUBBUB_GLOBAL_TIMER_CNTL__DCHUBBUB_GLOBAL_TIMER_ENABLE), 1); -} - -/* TODO: Need input parameter to tell current DCHUB pipe tie to which OTG - * VTG is within DCHUBBUB which is commond block share by each pipe HUBP. - * VTG is 1:1 mapping with OTG. Each pipe HUBP will select which VTG - */ -static void select_vtg( - struct dc_context *ctx, - uint8_t plane_id, - uint8_t inst) -{ - uint32_t inst_offset = reg_offsets[plane_id].dchubp; - - HWSEQ_REG_UPDATE(HUBP0_DCHUBP_CNTL, HUBP_VTG_SEL, inst); -} - -static void enable_dcfclk( - struct dc_context *ctx, - uint8_t plane_id, - uint32_t requested_pix_clk, - bool dppclk_div) -{ - uint32_t inst_offset = reg_offsets[plane_id].dchubp; - - HWSEQ_REG_UPDATE(HUBP0_HUBP_CLK_CNTL, HUBP_CLOCK_ENABLE, 1); + REG_UPDATE(DPP_CONTROL[plane_id], DPP_CLOCK_ENABLE, 0); } static void enable_dppclk( - struct dc_context *ctx, + struct dce_hwseq *hws, uint8_t plane_id, uint32_t requested_pix_clk, bool dppclk_div) { - uint32_t inst_offset = reg_offsets[plane_id].dpp; - - dm_logger_write(ctx->logger, LOG_SURFACE, + dm_logger_write(hws->ctx->logger, LOG_SURFACE, "dppclk_rate_control for pipe %d programed to %d\n", plane_id, dppclk_div); - /* TODO: find condition for DPP clock to DISPCLK or 1/2 DISPCLK */ if (dppclk_div) { /* 1/2 DISPCLK*/ - HWSEQ_REG_UPDATE_2(DPP_TOP0_DPP_CONTROL, + REG_UPDATE_2(DPP_CONTROL[plane_id], DPPCLK_RATE_CONTROL, 1, DPP_CLOCK_ENABLE, 1); } else { /* DISPCLK */ - HWSEQ_REG_UPDATE_2(DPP_TOP0_DPP_CONTROL, + REG_UPDATE_2(DPP_CONTROL[plane_id], DPPCLK_RATE_CONTROL, 0, DPP_CLOCK_ENABLE, 1); } } static void enable_power_gating_plane( - struct dc_context *ctx, + struct dce_hwseq *hws, bool enable) { - uint32_t inst_offset = 0; /* each register only has one instance */ bool force_on = 1; /* disable power gating */ if (enable) force_on = 0; /* DCHUBP0/1/2/3 */ - HWSEQ_REG_UPDATE(DOMAIN0_PG_CONFIG, DOMAIN0_POWER_FORCEON, force_on); - HWSEQ_REG_UPDATE(DOMAIN2_PG_CONFIG, DOMAIN2_POWER_FORCEON, force_on); - HWSEQ_REG_UPDATE(DOMAIN4_PG_CONFIG, DOMAIN4_POWER_FORCEON, force_on); - HWSEQ_REG_UPDATE(DOMAIN6_PG_CONFIG, DOMAIN6_POWER_FORCEON, force_on); + REG_UPDATE(DOMAIN0_PG_CONFIG, DOMAIN0_POWER_FORCEON, force_on); + REG_UPDATE(DOMAIN2_PG_CONFIG, DOMAIN2_POWER_FORCEON, force_on); + REG_UPDATE(DOMAIN4_PG_CONFIG, DOMAIN4_POWER_FORCEON, force_on); + REG_UPDATE(DOMAIN6_PG_CONFIG, DOMAIN6_POWER_FORCEON, force_on); /* DPP0/1/2/3 */ - HWSEQ_REG_UPDATE(DOMAIN1_PG_CONFIG, DOMAIN1_POWER_FORCEON, force_on); - HWSEQ_REG_UPDATE(DOMAIN3_PG_CONFIG, DOMAIN3_POWER_FORCEON, force_on); - HWSEQ_REG_UPDATE(DOMAIN5_PG_CONFIG, DOMAIN5_POWER_FORCEON, force_on); - HWSEQ_REG_UPDATE(DOMAIN7_PG_CONFIG, DOMAIN7_POWER_FORCEON, force_on); + REG_UPDATE(DOMAIN1_PG_CONFIG, DOMAIN1_POWER_FORCEON, force_on); + REG_UPDATE(DOMAIN3_PG_CONFIG, DOMAIN3_POWER_FORCEON, force_on); + REG_UPDATE(DOMAIN5_PG_CONFIG, DOMAIN5_POWER_FORCEON, force_on); + REG_UPDATE(DOMAIN7_PG_CONFIG, DOMAIN7_POWER_FORCEON, force_on); } static void dpp_pg_control( - struct dc_context *ctx, + struct dce_hwseq *hws, unsigned int dpp_inst, bool power_on) { - uint32_t inst_offset = 0; uint32_t power_gate = power_on ? 0 : 1; uint32_t pwr_status = power_on ? 0 : 2; - if (ctx->dc->debug.disable_dpp_power_gate) + if (hws->ctx->dc->debug.disable_dpp_power_gate) return; switch (dpp_inst) { case 0: /* DPP0 */ - HWSEQ_REG_UPDATE(DOMAIN1_PG_CONFIG, + REG_UPDATE(DOMAIN1_PG_CONFIG, DOMAIN1_POWER_GATE, power_gate); - wait_reg(ctx, 0, DOMAIN1_PG_STATUS, - DOMAIN1_PGFSM_PWR_STATUS, pwr_status); + REG_WAIT(DOMAIN1_PG_STATUS, + DOMAIN1_PGFSM_PWR_STATUS, pwr_status, 20000, 200000); break; case 1: /* DPP1 */ - HWSEQ_REG_UPDATE(DOMAIN3_PG_CONFIG, + REG_UPDATE(DOMAIN3_PG_CONFIG, DOMAIN3_POWER_GATE, power_gate); - wait_reg(ctx, 0, DOMAIN3_PG_STATUS, - DOMAIN3_PGFSM_PWR_STATUS, pwr_status); + REG_WAIT(DOMAIN3_PG_STATUS, + DOMAIN3_PGFSM_PWR_STATUS, pwr_status, 20000, 200000); break; case 2: /* DPP2 */ - HWSEQ_REG_UPDATE(DOMAIN5_PG_CONFIG, + REG_UPDATE(DOMAIN5_PG_CONFIG, DOMAIN5_POWER_GATE, power_gate); - wait_reg(ctx, 0, DOMAIN5_PG_STATUS, - DOMAIN5_PGFSM_PWR_STATUS, pwr_status); + REG_WAIT(DOMAIN5_PG_STATUS, + DOMAIN5_PGFSM_PWR_STATUS, pwr_status, 20000, 200000); break; case 3: /* DPP3 */ - HWSEQ_REG_UPDATE(DOMAIN7_PG_CONFIG, + REG_UPDATE(DOMAIN7_PG_CONFIG, DOMAIN7_POWER_GATE, power_gate); - wait_reg(ctx, 0, DOMAIN7_PG_STATUS, - DOMAIN7_PGFSM_PWR_STATUS, pwr_status); + REG_WAIT(DOMAIN7_PG_STATUS, + DOMAIN7_PGFSM_PWR_STATUS, pwr_status, 20000, 200000); break; default: BREAK_TO_DEBUGGER(); @@ -416,45 +155,44 @@ static void dpp_pg_control( } static void hubp_pg_control( - struct dc_context *ctx, + struct dce_hwseq *hws, unsigned int hubp_inst, bool power_on) { - uint32_t inst_offset = 0; uint32_t power_gate = power_on ? 0 : 1; uint32_t pwr_status = power_on ? 0 : 2; - if (ctx->dc->debug.disable_hubp_power_gate) + if (hws->ctx->dc->debug.disable_hubp_power_gate) return; switch (hubp_inst) { case 0: /* DCHUBP0 */ - HWSEQ_REG_UPDATE(DOMAIN0_PG_CONFIG, + REG_UPDATE(DOMAIN0_PG_CONFIG, DOMAIN0_POWER_GATE, power_gate); - wait_reg(ctx, 0, DOMAIN0_PG_STATUS, - DOMAIN0_PGFSM_PWR_STATUS, pwr_status); + REG_WAIT(DOMAIN0_PG_STATUS, + DOMAIN0_PGFSM_PWR_STATUS, pwr_status, 20000, 200000); break; case 1: /* DCHUBP1 */ - HWSEQ_REG_UPDATE(DOMAIN2_PG_CONFIG, + REG_UPDATE(DOMAIN2_PG_CONFIG, DOMAIN2_POWER_GATE, power_gate); - wait_reg(ctx, 0, DOMAIN2_PG_STATUS, - DOMAIN2_PGFSM_PWR_STATUS, pwr_status); + REG_WAIT(DOMAIN2_PG_STATUS, + DOMAIN2_PGFSM_PWR_STATUS, pwr_status, 20000, 200000); break; case 2: /* DCHUBP2 */ - HWSEQ_REG_UPDATE(DOMAIN4_PG_CONFIG, + REG_UPDATE(DOMAIN4_PG_CONFIG, DOMAIN4_POWER_GATE, power_gate); - wait_reg(ctx, 0, DOMAIN4_PG_STATUS, - DOMAIN4_PGFSM_PWR_STATUS, pwr_status); + REG_WAIT(DOMAIN4_PG_STATUS, + DOMAIN4_PGFSM_PWR_STATUS, pwr_status, 20000, 200000); break; case 3: /* DCHUBP3 */ - HWSEQ_REG_UPDATE(DOMAIN6_PG_CONFIG, + REG_UPDATE(DOMAIN6_PG_CONFIG, DOMAIN6_POWER_GATE, power_gate); - wait_reg(ctx, 0, DOMAIN6_PG_STATUS, - DOMAIN6_PGFSM_PWR_STATUS, pwr_status); + REG_WAIT(DOMAIN6_PG_STATUS, + DOMAIN6_PGFSM_PWR_STATUS, pwr_status, 20000, 200000); break; default: BREAK_TO_DEBUGGER(); @@ -463,18 +201,16 @@ static void hubp_pg_control( } static void power_on_plane( - struct dc_context *ctx, + struct dce_hwseq *hws, int plane_id) { - uint32_t inst_offset = 0; - - HWSEQ_REG_SET(DC_IP_REQUEST_CNTL, + REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1); - dpp_pg_control(ctx, plane_id, true); - hubp_pg_control(ctx, plane_id, true); - HWSEQ_REG_SET(DC_IP_REQUEST_CNTL, + dpp_pg_control(hws, plane_id, true); + hubp_pg_control(hws, plane_id, true); + REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0); - dm_logger_write(ctx->logger, LOG_DC, + dm_logger_write(hws->ctx->logger, LOG_DC, "Un-gated front end for pipe %d\n", plane_id); } @@ -513,47 +249,54 @@ static void bios_golden_init(struct core_dc *dc) } } +/* + * This should be done within BIOS, we are doing it for maximus only + */ +static void dchubup_setup_timer(struct dce_hwseq *hws) +{ + REG_WRITE(REFCLK_CNTL, 0); + + REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1); +} + static void init_hw(struct core_dc *dc) { int i; - struct dc_bios *bp; struct transform *xfm; struct abm *abm; + struct dce_hwseq *hws = dc->hwseq; - bp = dc->ctx->dc_bios; - +#if 1 if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { - /* TODO: this will be moved to Diag or BIOS */ - dchubup_setup_timer(dc->ctx); + dchubup_setup_timer(dc->hwseq); /* TODO: dchubp_map_fb_to_mc will be moved to dchub interface * between dc and kmd */ - dchubp_map_fb_to_mc(dc->ctx); + /*dchubp_map_fb_to_mc(dc->hwseq);*/ + REG_WRITE(DIO_MEM_PWR_CTRL, 0); + + if (!dc->public.debug.disable_clock_gate) { + /* enable all DCN clock gating */ + REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0); - enable_power_gating_plane(dc->ctx, true); + REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0); + + REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0); + } + + enable_power_gating_plane(dc->hwseq, true); return; } /* end of FPGA. Below if real ASIC */ +#endif bios_golden_init(dc); for (i = 0; i < dc->res_pool->pipe_count; i++) { xfm = dc->res_pool->transforms[i]; xfm->funcs->transform_reset(xfm); - - /* TODOFPGA: may need later */ -#if 0 - xfm->funcs->transform_power_up(xfm); - dc->hwss.enable_display_pipe_clock_gating( - dc->ctx, - true); -#endif } - /* TODOFPGA: light sleep */ -#if 0 - dc->hwss.clock_gating_power_up(dc->ctx, false); -#endif for (i = 0; i < dc->link_count; i++) { /* Power up AND update implementation according to the @@ -601,67 +344,18 @@ static void init_hw(struct core_dc *dc) } /* power AFMT HDMI memory TODO: may move to dis/en output save power*/ - generic_reg_set_soc15(dc->ctx, 0, DIO_MEM_PWR_CTRL, 7, - FD(DIO_MEM_PWR_CTRL__HDMI0_MEM_PWR_FORCE), 0, - FD(DIO_MEM_PWR_CTRL__HDMI1_MEM_PWR_FORCE), 0, - FD(DIO_MEM_PWR_CTRL__HDMI2_MEM_PWR_FORCE), 0, - FD(DIO_MEM_PWR_CTRL__HDMI3_MEM_PWR_FORCE), 0, - FD(DIO_MEM_PWR_CTRL__HDMI4_MEM_PWR_FORCE), 0, - FD(DIO_MEM_PWR_CTRL__HDMI5_MEM_PWR_FORCE), 0, - FD(DIO_MEM_PWR_CTRL__HDMI6_MEM_PWR_FORCE), 0); + REG_WRITE(DIO_MEM_PWR_CTRL, 0); if (!dc->public.debug.disable_clock_gate) { /* enable all DCN clock gating */ - generic_reg_set_soc15(dc->ctx, 0, DCCG_GATE_DISABLE_CNTL, 19, - FD(DCCG_GATE_DISABLE_CNTL__DISPCLK_DCCG_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL__DISPCLK_R_DCCG_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL__SOCCLK_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL__DPREFCLK_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL__DACACLK_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL__DVOACLK_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL__DPREFCLK_R_DCCG_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL__DPPCLK_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL__AOMCLK0_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL__AOMCLK1_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL__AOMCLK2_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL__AUDIO_DTO2_CLK_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL__DPREFCLK_GTC_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL__UNB_DB_CLK_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL__REFCLK_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL__REFCLK_R_DIG_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL__DSICLK_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL__BYTECLK_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL__ESCCLK_GATE_DISABLE), 0); - - generic_reg_set_soc15(dc->ctx, 0, DCCG_GATE_DISABLE_CNTL2, 14, - FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKA_FE_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKB_FE_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKC_FE_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKD_FE_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKE_FE_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKF_FE_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKG_FE_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKA_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKB_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKC_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKD_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKE_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKF_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKG_GATE_DISABLE), 0); - - generic_reg_update_soc15(dc->ctx, 0, DCFCLK_CNTL, 1, - FD(DCFCLK_CNTL__DCFCLK_GATE_DIS), 0); - } + REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0); - /* This power gating should be one-time program for DAL. - * It can only change by registry key - * TODO: new task will for this. - * if power gating is disable, power_on_plane and power_off_plane - * should be skip. Otherwise, hand will be met in power_off_plane - */ - enable_power_gating_plane(dc->ctx, true); + REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0); + REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0); + } + enable_power_gating_plane(dc->hwseq, true); } static enum dc_status dcn10_prog_pixclk_crtc_otg( @@ -759,9 +453,6 @@ static void reset_back_end_for_pipe( struct validate_context *context) { int i; - struct dc_bios *bp; - - bp = dc->ctx->dc_bios; if (pipe_ctx->stream_enc == NULL) { pipe_ctx->stream = NULL; @@ -807,6 +498,7 @@ static void reset_front_end( struct core_dc *dc, int fe_idx) { + struct dce_hwseq *hws = dc->hwseq; struct mpcc_cfg mpcc_cfg; struct mem_input *mi = dc->res_pool->mis[fe_idx]; struct transform *xfm = dc->res_pool->transforms[fe_idx]; @@ -826,11 +518,14 @@ static void reset_front_end( mpcc_cfg.top_of_tree = tg->inst == mpcc->inst; mpcc->funcs->set(mpcc, &mpcc_cfg); - unlock_master_tg_and_wait(dc->ctx, tg->inst); + REG_UPDATE(OTG_GLOBAL_SYNC_STATUS[tg->inst], VUPDATE_NO_LOCK_EVENT_CLEAR, 1); + tg->funcs->unlock(tg); + REG_WAIT(OTG_GLOBAL_SYNC_STATUS[tg->inst], VUPDATE_NO_LOCK_EVENT_OCCURRED, 1, 20000, 200000); + mpcc->funcs->wait_for_idle(mpcc); mi->funcs->set_blank(mi, true); - wait_no_outstanding_request(dc->ctx, fe_idx); - disable_clocks(dc->ctx, fe_idx); + REG_WAIT(DCHUBP_CNTL[fe_idx], HUBP_NO_OUTSTANDING_REQ, 1, 20000, 200000); + disable_clocks(dc->hwseq, fe_idx); xfm->funcs->transform_reset(xfm); @@ -841,16 +536,15 @@ static void reset_front_end( static void dcn10_power_down_fe(struct core_dc *dc, int fe_idx) { - struct dc_context *ctx = dc->ctx; - uint32_t inst_offset = 0; + struct dce_hwseq *hws = dc->hwseq; reset_front_end(dc, fe_idx); - HWSEQ_REG_SET(DC_IP_REQUEST_CNTL, + REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1); - dpp_pg_control(ctx, fe_idx, false); - hubp_pg_control(ctx, fe_idx, false); - HWSEQ_REG_SET(DC_IP_REQUEST_CNTL, + dpp_pg_control(hws, fe_idx, false); + hubp_pg_control(hws, fe_idx, false); + REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0); dm_logger_write(dc->ctx->logger, LOG_DC, "Power gated front end %d\n", fe_idx); @@ -1538,18 +1232,13 @@ static void dcn10_power_on_fe( struct validate_context *context) { struct dc_surface *dc_surface = &pipe_ctx->surface->public; + struct dce_hwseq *hws = dc->hwseq; - power_on_plane(dc->ctx, + power_on_plane(dc->hwseq, pipe_ctx->pipe_idx); /* enable DCFCLK current DCHUB */ - enable_dcfclk(dc->ctx, - pipe_ctx->pipe_idx, - pipe_ctx->pix_clk_params.requested_pix_clk, - context->bw.dcn.calc_clk.dppclk_div); - dc->current_context->bw.dcn.cur_clk.dppclk_div = - context->bw.dcn.calc_clk.dppclk_div; - context->bw.dcn.cur_clk.dppclk_div = context->bw.dcn.calc_clk.dppclk_div; + REG_UPDATE(HUBP_CLK_CNTL[pipe_ctx->pipe_idx], HUBP_CLOCK_ENABLE, 1); if (dc_surface) { dm_logger_write(dc->ctx->logger, LOG_DC, @@ -1706,6 +1395,7 @@ static void update_dchubp_dpp( struct pipe_ctx *pipe_ctx, struct validate_context *context) { + struct dce_hwseq *hws = dc->hwseq; struct mem_input *mi = pipe_ctx->mi; struct input_pixel_processor *ipp = pipe_ctx->ipp; struct core_surface *surface = pipe_ctx->surface; @@ -1718,7 +1408,7 @@ static void update_dchubp_dpp( /* TODO: proper fix once fpga works */ /* depends on DML calculation, DPP clock value may change dynamically */ enable_dppclk( - dc->ctx, + dc->hwseq, pipe_ctx->pipe_idx, pipe_ctx->pix_clk_params.requested_pix_clk, context->bw.dcn.calc_clk.dppclk_div); @@ -1726,7 +1416,11 @@ static void update_dchubp_dpp( context->bw.dcn.calc_clk.dppclk_div; context->bw.dcn.cur_clk.dppclk_div = context->bw.dcn.calc_clk.dppclk_div; - select_vtg(dc->ctx, pipe_ctx->pipe_idx, pipe_ctx->tg->inst); + /* TODO: Need input parameter to tell current DCHUB pipe tie to which OTG + * VTG is within DCHUBBUB which is commond block share by each pipe HUBP. + * VTG is 1:1 mapping with OTG. Each pipe HUBP will select which VTG + */ + REG_UPDATE(DCHUBP_CNTL[pipe_ctx->pipe_idx], HUBP_VTG_SEL, pipe_ctx->tg->inst); update_plane_addr(dc, pipe_ctx); diff --git a/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h b/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h index 96fba1fb7697..1828d288c6bc 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h +++ b/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h @@ -270,7 +270,7 @@ FN(reg, f8), v8, \ FN(reg, f9), v9) -#define REG_UPDATE_10(reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10, v10) \ +#define REG_UPDATE_10(reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10, v10)\ REG_UPDATE_N(reg, 10, \ FN(reg, f1), v1,\ FN(reg, f2), v2, \ @@ -283,6 +283,70 @@ FN(reg, f9), v9, \ FN(reg, f10), v10) +#define REG_UPDATE_14(reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10,\ + v10, f11, v11, f12, v12, f13, v13, f14, v14)\ + REG_UPDATE_N(reg, 14, \ + FN(reg, f1), v1,\ + FN(reg, f2), v2, \ + FN(reg, f3), v3, \ + FN(reg, f4), v4, \ + FN(reg, f5), v5, \ + FN(reg, f6), v6, \ + FN(reg, f7), v7, \ + FN(reg, f8), v8, \ + FN(reg, f9), v9, \ + FN(reg, f10), v10, \ + FN(reg, f11), v11, \ + FN(reg, f12), v12, \ + FN(reg, f13), v13, \ + FN(reg, f14), v14) + +#define REG_UPDATE_19(reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10,\ + v10, f11, v11, f12, v12, f13, v13, f14, v14, f15, v15, f16, v16, f17, v17, f18, v18, f19, v19)\ + REG_UPDATE_N(reg, 19, \ + FN(reg, f1), v1,\ + FN(reg, f2), v2, \ + FN(reg, f3), v3, \ + FN(reg, f4), v4, \ + FN(reg, f5), v5, \ + FN(reg, f6), v6, \ + FN(reg, f7), v7, \ + FN(reg, f8), v8, \ + FN(reg, f9), v9, \ + FN(reg, f10), v10, \ + FN(reg, f11), v11, \ + FN(reg, f12), v12, \ + FN(reg, f13), v13, \ + FN(reg, f14), v14, \ + FN(reg, f15), v15, \ + FN(reg, f16), v16, \ + FN(reg, f17), v17, \ + FN(reg, f18), v18, \ + FN(reg, f19), v19) + +#define REG_UPDATE_20(reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10,\ + v10, f11, v11, f12, v12, f13, v13, f14, v14, f15, v15, f16, v16, f17, v17, f18, v18, f19, v19, f20, v20)\ + REG_UPDATE_N(reg, 20, \ + FN(reg, f1), v1,\ + FN(reg, f2), v2, \ + FN(reg, f3), v3, \ + FN(reg, f4), v4, \ + FN(reg, f5), v5, \ + FN(reg, f6), v6, \ + FN(reg, f7), v7, \ + FN(reg, f8), v8, \ + FN(reg, f9), v9, \ + FN(reg, f10), v10, \ + FN(reg, f11), v11, \ + FN(reg, f12), v12, \ + FN(reg, f13), v13, \ + FN(reg, f14), v14, \ + FN(reg, f15), v15, \ + FN(reg, f16), v16, \ + FN(reg, f17), v17, \ + FN(reg, f18), v18, \ + FN(reg, f19), v19, \ + FN(reg, f20), v20) /* macro to update a register field to specified values in given sequences. * useful when toggling bits */ -- cgit From 87449a90c2545eaed5757153770346563378463b Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Thu, 6 Jul 2017 14:27:49 -0400 Subject: drm/amd/display: Fix MPO visual confirm 1. Need to blend non-active area to show visual confirm borders 2. Set number of Visual Confirm lines based on pipe instance 3. Set Different colors representing surface format of bottom most plan Signed-off-by: Anthony Koo Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_hw_sequencer.c | 6 --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 16 ++++---- drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 8 ++-- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 8 +++- .../drm/amd/display/dc/dce110/dce110_transform_v.c | 4 +- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 45 +++++++++++++++++++++- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c | 5 ++- .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 2 +- .../gpu/drm/amd/display/dc/dcn10/dcn10_transform.c | 13 ++++--- .../gpu/drm/amd/display/dc/dcn10/dcn10_transform.h | 1 + 10 files changed, 77 insertions(+), 31 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c index 6cd1e93b5084..7b1f2493cbc9 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c @@ -59,12 +59,6 @@ void color_space_to_black_color( enum dc_color_space colorspace, struct tg_color *black_color) { - if (dc->public.debug.surface_visual_confirm) { - *black_color = - black_color_format[BLACK_COLOR_FORMAT_DEBUG]; - return; - } - switch (colorspace) { case COLOR_SPACE_YCBCR601: case COLOR_SPACE_YCBCR709: diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index ddf032214dc3..5a5ed37474bf 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -399,11 +399,11 @@ static enum pixel_format convert_pixel_format_to_dalsurface( break; case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: - dal_pixel_format = PIXEL_FORMAT_420BPP12; + dal_pixel_format = PIXEL_FORMAT_420BPP8; break; case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: - dal_pixel_format = PIXEL_FORMAT_420BPP15; + dal_pixel_format = PIXEL_FORMAT_420BPP10; break; case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: default: @@ -433,8 +433,8 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) struct scaler_data *data = &pipe_ctx->scl_data; struct rect surf_src = surface->src_rect; struct rect clip = { 0 }; - int vpc_div = (data->format == PIXEL_FORMAT_420BPP12 - || data->format == PIXEL_FORMAT_420BPP15) ? 2 : 1; + int vpc_div = (data->format == PIXEL_FORMAT_420BPP8 + || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1; bool pri_split = pipe_ctx->bottom_pipe && pipe_ctx->bottom_pipe->surface == pipe_ctx->surface; bool sec_split = pipe_ctx->top_pipe && @@ -637,8 +637,8 @@ static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) pipe_ctx->scl_data.ratios.horz_c = pipe_ctx->scl_data.ratios.horz; pipe_ctx->scl_data.ratios.vert_c = pipe_ctx->scl_data.ratios.vert; - if (pipe_ctx->scl_data.format == PIXEL_FORMAT_420BPP12 - || pipe_ctx->scl_data.format == PIXEL_FORMAT_420BPP15) { + if (pipe_ctx->scl_data.format == PIXEL_FORMAT_420BPP8 + || pipe_ctx->scl_data.format == PIXEL_FORMAT_420BPP10) { pipe_ctx->scl_data.ratios.horz_c.value /= 2; pipe_ctx->scl_data.ratios.vert_c.value /= 2; } @@ -648,8 +648,8 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *r { struct scaler_data *data = &pipe_ctx->scl_data; struct rect src = pipe_ctx->surface->public.src_rect; - int vpc_div = (data->format == PIXEL_FORMAT_420BPP12 - || data->format == PIXEL_FORMAT_420BPP15) ? 2 : 1; + int vpc_div = (data->format == PIXEL_FORMAT_420BPP8 + || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1; if (pipe_ctx->surface->public.rotation == ROTATION_ANGLE_90 || diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index 94fb93066784..05f030ee8cf0 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -214,15 +214,15 @@ enum pixel_format { PIXEL_FORMAT_ARGB2101010_XRBIAS, PIXEL_FORMAT_FP16, /*video*/ - PIXEL_FORMAT_420BPP12, - PIXEL_FORMAT_420BPP15, + PIXEL_FORMAT_420BPP8, + PIXEL_FORMAT_420BPP10, /*end of pixel format definition*/ PIXEL_FORMAT_INVALID, PIXEL_FORMAT_GRPH_BEGIN = PIXEL_FORMAT_INDEX8, PIXEL_FORMAT_GRPH_END = PIXEL_FORMAT_FP16, - PIXEL_FORMAT_VIDEO_BEGIN = PIXEL_FORMAT_420BPP12, - PIXEL_FORMAT_VIDEO_END = PIXEL_FORMAT_420BPP15, + PIXEL_FORMAT_VIDEO_BEGIN = PIXEL_FORMAT_420BPP8, + PIXEL_FORMAT_VIDEO_END = PIXEL_FORMAT_420BPP10, PIXEL_FORMAT_UNKNOWN }; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 8778af76f4e0..d3c84dc36b80 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -916,11 +916,15 @@ static void get_surface_visual_confirm_color(const struct pipe_ctx *pipe_ctx, /* set boarder color to blue */ color->color_b_cb = color_value; break; - case PIXEL_FORMAT_420BPP12: - case PIXEL_FORMAT_420BPP15: + case PIXEL_FORMAT_420BPP8: /* set boarder color to green */ color->color_g_y = color_value; break; + case PIXEL_FORMAT_420BPP10: + /* set boarder color to yellow */ + color->color_g_y = color_value; + color->color_r_cr = color_value; + break; case PIXEL_FORMAT_FP16: /* set boarder color to white */ color->color_r_cr = color_value; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c index 28963996693c..8548248d4b19 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c @@ -59,7 +59,7 @@ static void calculate_viewport( chroma_viewport->height = luma_viewport->height; chroma_viewport->width = luma_viewport->width; - if (scl_data->format == PIXEL_FORMAT_420BPP12) { + if (scl_data->format == PIXEL_FORMAT_420BPP8) { luma_viewport->height += luma_viewport->height % 2; luma_viewport->width += luma_viewport->width % 2; /*for 420 video chroma is 1/4 the area of luma, scaled @@ -184,7 +184,7 @@ static bool setup_scaling_configuration( set_reg_field_value(value, 1, SCLV_MODE, SCL_MODE_C); set_reg_field_value(value, 1, SCLV_MODE, SCL_PSCL_EN_C); is_scaling_needed = true; - } else if (data->format != PIXEL_FORMAT_420BPP12) { + } else if (data->format != PIXEL_FORMAT_420BPP8) { set_reg_field_value( value, get_reg_field_value(value, SCLV_MODE, SCL_MODE), diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index fb326316b08b..5e275239341d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1390,6 +1390,42 @@ static bool is_rgb_cspace(enum dc_color_space output_color_space) } } +static void dcn10_get_surface_visual_confirm_color( + const struct pipe_ctx *pipe_ctx, + struct tg_color *color) +{ + uint32_t color_value = MAX_TG_COLOR_VALUE; + + switch (pipe_ctx->scl_data.format) { + case PIXEL_FORMAT_ARGB8888: + /* set boarder color to red */ + color->color_r_cr = color_value; + break; + + case PIXEL_FORMAT_ARGB2101010: + /* set boarder color to blue */ + color->color_b_cb = color_value; + break; + case PIXEL_FORMAT_420BPP8: + /* set boarder color to green */ + color->color_g_y = color_value; + break; + case PIXEL_FORMAT_420BPP10: + /* set boarder color to yellow */ + color->color_g_y = color_value; + color->color_r_cr = color_value; + break; + case PIXEL_FORMAT_FP16: + /* set boarder color to white */ + color->color_r_cr = color_value; + color->color_b_cb = color_value; + color->color_g_y = color_value; + break; + default: + break; + } +} + static void update_dchubp_dpp( struct core_dc *dc, struct pipe_ctx *pipe_ctx, @@ -1462,8 +1498,13 @@ static void update_dchubp_dpp( && per_pixel_alpha; pipe_ctx->mpcc->funcs->set(pipe_ctx->mpcc, &mpcc_cfg); - color_space_to_black_color( - dc, pipe_ctx->stream->public.output_color_space, &black_color); + if (dc->public.debug.surface_visual_confirm) { + dcn10_get_surface_visual_confirm_color(pipe_ctx, &black_color); + } else { + color_space_to_black_color( + dc, pipe_ctx->stream->public.output_color_space, + &black_color); + } pipe_ctx->mpcc->funcs->set_bg_color(pipe_ctx->mpcc, &black_color); pipe_ctx->scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c index 7af04bce3599..1c9d5e96ab55 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c @@ -25,6 +25,7 @@ #include "reg_helper.h" #include "dcn10_mpc.h" +#include "dc.h" #define REG(reg)\ mpcc10->mpcc_regs->reg @@ -85,6 +86,8 @@ static void dcn10_mpcc_set(struct mpcc *mpcc, struct mpcc_cfg *cfg) BLND_PP_ALPHA : BLND_GLOBAL_ALPHA; int mpcc_mode = cfg->bot_mpcc_id != 0xf ? MODE_BLEND : MODE_TOP_ONLY; + bool blend_active_only = cfg->top_of_tree && + !mpcc->ctx->dc->debug.surface_visual_confirm; REG_SET(MPCC_OPP_ID, 0, MPCC_OPP_ID, cfg->opp_id); @@ -99,7 +102,7 @@ static void dcn10_mpcc_set(struct mpcc *mpcc, struct mpcc_cfg *cfg) MPCC_MODE, mpcc_mode, MPCC_ALPHA_BLND_MODE, alpha_blnd_mode, MPCC_ALPHA_MULTIPLIED_MODE, cfg->pre_multiplied_alpha, - MPCC_BLND_ACTIVE_OVERLAP_ONLY, cfg->top_of_tree); + MPCC_BLND_ACTIVE_OVERLAP_ONLY, blend_active_only); if (cfg->top_of_tree) { if (cfg->opp_id != 0xf) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 66b5d3027336..75ad37e81738 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -465,7 +465,7 @@ static struct transform *dcn10_transform_create( if (!transform) return NULL; - if (dcn10_transform_construct(transform, ctx, + if (dcn10_transform_construct(transform, ctx, inst, &tf_regs[inst], &tf_shift, &tf_mask)) return &transform->base; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c index 92322b75d868..398af229f2a7 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c @@ -171,8 +171,8 @@ static enum dscl_mode_sel get_dscl_mode( && data->format <= PIXEL_FORMAT_VIDEO_END) ycbcr = true; - if (data->format == PIXEL_FORMAT_420BPP12 || - data->format == PIXEL_FORMAT_420BPP15) + if (data->format == PIXEL_FORMAT_420BPP8 || + data->format == PIXEL_FORMAT_420BPP10) format420 = true; if (data->ratios.horz.value == one @@ -579,8 +579,8 @@ static enum lb_memory_config find_lb_memory_config(const struct scaler_data *scl && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)) return LB_MEMORY_CONFIG_2; - if (scl_data->format == PIXEL_FORMAT_420BPP12 - || scl_data->format == PIXEL_FORMAT_420BPP15) { + if (scl_data->format == PIXEL_FORMAT_420BPP8 + || scl_data->format == PIXEL_FORMAT_420BPP10) { calc_lb_num_partitions( scl_data, LB_MEMORY_CONFIG_3, &num_part_y, &num_part_c); @@ -675,7 +675,8 @@ static void transform_set_recout( RECOUT_WIDTH, recout->width, /* Number of RECOUT vertical lines */ RECOUT_HEIGHT, recout->height - - xfm->base.ctx->dc->debug.surface_visual_confirm * 2); + - xfm->base.ctx->dc->debug.surface_visual_confirm * 4 * + (xfm->base.inst + 1)); } static void transform_set_manual_ratio_init( @@ -1038,12 +1039,14 @@ static struct transform_funcs dcn10_transform_funcs = { bool dcn10_transform_construct( struct dcn10_transform *xfm, struct dc_context *ctx, + uint32_t inst, const struct dcn_transform_registers *tf_regs, const struct dcn_transform_shift *tf_shift, const struct dcn_transform_mask *tf_mask) { xfm->base.ctx = ctx; + xfm->base.inst = inst; xfm->base.funcs = &dcn10_transform_funcs; xfm->tf_regs = tf_regs; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.h index cd312bd7055b..880a554886b8 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.h @@ -413,6 +413,7 @@ struct dcn10_transform { bool dcn10_transform_construct(struct dcn10_transform *xfm110, struct dc_context *ctx, + uint32_t inst, const struct dcn_transform_registers *tf_regs, const struct dcn_transform_shift *tf_shift, const struct dcn_transform_mask *tf_mask); -- cgit From 0b6ab57e7ffad05ca266fed9764119cf1807b81b Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 5 Jul 2017 12:00:28 -0400 Subject: drm/amd/display: get dal1.1 to run Signed-off-by: Dmytro Laktyushkin Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h | 2 +- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index 761dba3562b2..6985a4607bd3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -275,7 +275,7 @@ struct dce_hwseq_registers { #if defined(CONFIG_DRM_AMD_DC_DCN1_0) #define HWSEQ_DCN_MASK_SH_LIST(mask_sh)\ HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, OTG0_),\ - HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, OTG0_),\ + HWS_SF1(OTG0_, PHYPLL_PIXEL_RATE_CNTL, PHYPLL_PIXEL_RATE_SOURCE, mask_sh), \ HWS_SF(OTG0_, OTG_GLOBAL_SYNC_STATUS, VUPDATE_NO_LOCK_EVENT_CLEAR, mask_sh), \ HWS_SF(OTG0_, OTG_GLOBAL_SYNC_STATUS, VUPDATE_NO_LOCK_EVENT_OCCURRED, mask_sh), \ HWS_SF(HUBP0_, DCHUBP_CNTL, HUBP_NO_OUTSTANDING_REQ, mask_sh), \ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c index e6f2220415e8..669ac4b67ea9 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c @@ -784,7 +784,7 @@ static void oppn10_program_color_matrix(struct dcn10_opp *oppn10, } } -void oppn10_set_output_csc_adjustment( +static void oppn10_set_output_csc_adjustment( struct output_pixel_processor *opp, const struct out_csc_color_matrix *tbl_entry) { -- cgit From 4fac6da2cb93cd6cabfaeb6de2eb0401bbcc805b Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Thu, 6 Jul 2017 15:42:04 -0400 Subject: drm/amd/display: minor dcn10_hwseq clean up/refactor Signed-off-by: Dmytro Laktyushkin Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 49 ++++++---------------- 1 file changed, 12 insertions(+), 37 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 5e275239341d..223bb79bc8b8 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -53,15 +53,6 @@ #define FN(reg_name, field_name) \ hws->shifts->field_name, hws->masks->field_name -static void disable_clocks( - struct dce_hwseq *hws, - uint8_t plane_id) -{ - REG_UPDATE(HUBP_CLK_CNTL[plane_id], HUBP_CLOCK_ENABLE, 0); - - REG_UPDATE(DPP_CONTROL[plane_id], DPP_CLOCK_ENABLE, 0); -} - static void enable_dppclk( struct dce_hwseq *hws, uint8_t plane_id, @@ -214,25 +205,6 @@ static void power_on_plane( "Un-gated front end for pipe %d\n", plane_id); } -/* fully check bios enabledisplaypowergating table. dal only need dce init - * other power, clock gate register will be handle by dal itself. - * further may be put within init_hw - */ -static bool dcn10_enable_display_power_gating( - struct core_dc *dc, - uint8_t controller_id, - struct dc_bios *dcb, - enum pipe_gating_control power_gating) -{ - /* TODOFPGA */ -#if 0 - if (power_gating != PIPE_GATING_CONTROL_ENABLE) - dce110_init_pte(ctx); -#endif - - return true; -} - static void bios_golden_init(struct core_dc *dc) { struct dc_bios *bp = dc->ctx->dc_bios; @@ -525,7 +497,8 @@ static void reset_front_end( mpcc->funcs->wait_for_idle(mpcc); mi->funcs->set_blank(mi, true); REG_WAIT(DCHUBP_CNTL[fe_idx], HUBP_NO_OUTSTANDING_REQ, 1, 20000, 200000); - disable_clocks(dc->hwseq, fe_idx); + REG_UPDATE(HUBP_CLK_CNTL[fe_idx], HUBP_CLOCK_ENABLE, 0); + REG_UPDATE(DPP_CONTROL[fe_idx], DPP_CLOCK_ENABLE, 0); xfm->funcs->transform_reset(xfm); @@ -1803,8 +1776,8 @@ static void set_plane_config( program_gamut_remap(pipe_ctx); } -static void dcn10_config_stereo_parameters(struct core_stream *stream,\ - struct crtc_stereo_flags *flags) +static void dcn10_config_stereo_parameters( + struct core_stream *stream, struct crtc_stereo_flags *flags) { enum view_3d_format view_format = stream->public.view_format; enum dc_timing_3d_format timing_3d_format =\ @@ -1840,8 +1813,7 @@ static void dcn10_config_stereo_parameters(struct core_stream *stream,\ return; } -static void dcn10_setup_stereo(struct pipe_ctx *pipe_ctx, - struct core_dc *dc) +static void dcn10_setup_stereo(struct pipe_ctx *pipe_ctx, struct core_dc *dc) { struct crtc_stereo_flags flags = { 0 }; struct core_stream *stream = pipe_ctx->stream; @@ -1858,11 +1830,15 @@ static void dcn10_setup_stereo(struct pipe_ctx *pipe_ctx, &stream->public.timing, &flags); - - return; } +static bool dcn10_dummy_display_power_gating( + struct core_dc *dc, + uint8_t controller_id, + struct dc_bios *dcb, + enum pipe_gating_control power_gating) {return true; } + static const struct hw_sequencer_funcs dcn10_funcs = { .program_gamut_remap = program_gamut_remap, .program_csc_matrix = program_csc_matrix, @@ -1881,8 +1857,7 @@ static const struct hw_sequencer_funcs dcn10_funcs = { .enable_stream = dce110_enable_stream, .disable_stream = dce110_disable_stream, .unblank_stream = dce110_unblank_stream, - .enable_display_pipe_clock_gating = NULL, /* TODOFPGA */ - .enable_display_power_gating = dcn10_enable_display_power_gating, + .enable_display_power_gating = dcn10_dummy_display_power_gating, .power_down_front_end = dcn10_power_down_fe, .power_on_front_end = dcn10_power_on_fe, .pipe_control_lock = dcn10_pipe_control_lock, -- cgit From ea658f7552583b27fd5f4351caf8a139cb554b50 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Thu, 6 Jul 2017 15:58:25 -0400 Subject: drm/amd/display: dal1.1 opp prog update Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h index eb99c311104f..de0b631736bb 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h @@ -138,10 +138,11 @@ OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_RGB_RANDOM_ENABLE, mask_sh), \ OPP_SF(FMT0_FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, mask_sh), \ OPP_SF(FMT0_FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, mask_sh), \ + OPP_SF(FMT0_FMT_CONTROL, FMT_PIXEL_ENCODING, mask_sh), \ + OPP_SF(FMT0_FMT_CONTROL, FMT_STEREOSYNC_OVERRIDE, mask_sh), \ OPP_SF(FMT0_FMT_DITHER_RAND_R_SEED, FMT_RAND_R_SEED, mask_sh), \ OPP_SF(FMT0_FMT_DITHER_RAND_G_SEED, FMT_RAND_G_SEED, mask_sh), \ OPP_SF(FMT0_FMT_DITHER_RAND_B_SEED, FMT_RAND_B_SEED, mask_sh), \ - OPP_SF(FMT0_FMT_CONTROL, FMT_PIXEL_ENCODING, mask_sh), \ OPP_SF(FMT0_FMT_CLAMP_CNTL, FMT_CLAMP_DATA_EN, mask_sh), \ OPP_SF(FMT0_FMT_CLAMP_CNTL, FMT_CLAMP_COLOR_FORMAT, mask_sh), \ OPP_SF(FMT0_FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN, mask_sh), \ @@ -353,8 +354,7 @@ OPP_SF(CM0_CM_RGAM_LUT_WRITE_EN_MASK, CM_RGAM_LUT_WRITE_SEL, mask_sh), \ OPP_SF(CM0_CM_RGAM_LUT_INDEX, CM_RGAM_LUT_INDEX, mask_sh), \ OPP_SF(CM0_CM_MEM_PWR_CTRL, RGAM_MEM_PWR_FORCE, mask_sh), \ - OPP_SF(CM0_CM_RGAM_LUT_DATA, CM_RGAM_LUT_DATA, mask_sh), \ - OPP_SF(FMT0_FMT_CONTROL, FMT_STEREOSYNC_OVERRIDE, mask_sh) + OPP_SF(CM0_CM_RGAM_LUT_DATA, CM_RGAM_LUT_DATA, mask_sh) #define OPP_DCN10_REG_FIELD_LIST(type) \ type CM_OCSC_C11; \ -- cgit From a3ac9dad7494c946d323fd461df03bed9507157e Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Thu, 6 Jul 2017 17:35:17 -0400 Subject: drm/amd/display: dal1.1 ipp prog update Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c | 99 +++++++++++------------- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h | 1 + 2 files changed, 48 insertions(+), 52 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c index a09226c0d903..4910d4c59b31 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c @@ -69,7 +69,7 @@ enum dcn10_input_csc_select { INPUT_CSC_SELECT_COMA }; -static void dcn10_program_input_csc( +static void ippn10_program_input_csc( struct input_pixel_processor *ipp, enum dc_color_space color_space, enum dcn10_input_csc_select select) @@ -159,7 +159,7 @@ static void dcn10_program_input_csc( } /*program de gamma RAM B*/ -static void dcn10_ipp_program_degamma_lutb_settings( +static void ippn10_program_degamma_lutb_settings( struct input_pixel_processor *ipp, const struct pwl_params *params) { @@ -266,7 +266,7 @@ static void dcn10_ipp_program_degamma_lutb_settings( } /*program de gamma RAM A*/ -static void dcn10_ipp_program_degamma_luta_settings( +static void ippn10_program_degamma_luta_settings( struct input_pixel_processor *ipp, const struct pwl_params *params) { @@ -372,7 +372,7 @@ static void dcn10_ipp_program_degamma_luta_settings( CM_DGAM_RAMA_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num); } -static void ipp_power_on_degamma_lut( +static void ippn10_power_on_degamma_lut( struct input_pixel_processor *ipp, bool power_on) { @@ -383,7 +383,7 @@ static void ipp_power_on_degamma_lut( } -static void ipp_program_degamma_lut( +static void ippn10_program_degamma_lut( struct input_pixel_processor *ipp, const struct pwl_result_data *rgb, uint32_t num, @@ -410,25 +410,19 @@ static void ipp_program_degamma_lut( CM_DGAM_LUT_DATA, rgb[i].delta_green_reg); REG_SET(CM_DGAM_LUT_DATA, 0, CM_DGAM_LUT_DATA, rgb[i].delta_blue_reg); - } - } -static void dcn10_ipp_enable_cm_block( +static void ippn10_enable_cm_block( struct input_pixel_processor *ipp) { struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); REG_UPDATE(DPP_CONTROL, DPP_CLOCK_ENABLE, 1); - if (ippn10->ipp_mask->CM_BYPASS_EN) - REG_UPDATE(CM_CONTROL, CM_BYPASS_EN, 0); - else - REG_UPDATE(CM_CONTROL, CM_BYPASS, 0); + REG_UPDATE(CM_CONTROL, CM_BYPASS_EN, 0); } - -static void dcn10_ipp_full_bypass(struct input_pixel_processor *ipp) +static void ippn10_full_bypass(struct input_pixel_processor *ipp) { struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); @@ -450,12 +444,12 @@ static void dcn10_ipp_full_bypass(struct input_pixel_processor *ipp) REG_SET(CM_IGAM_CONTROL, 0, CM_IGAM_LUT_MODE, 0); } -static void dcn10_ipp_set_degamma( +static void ippn10_set_degamma( struct input_pixel_processor *ipp, enum ipp_degamma_mode mode) { struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); - dcn10_ipp_enable_cm_block(ipp); + ippn10_enable_cm_block(ipp); switch (mode) { case IPP_DEGAMMA_MODE_BYPASS: @@ -474,7 +468,7 @@ static void dcn10_ipp_set_degamma( } } -static bool dcn10_cursor_program_control( +static bool ippn10_cursor_program_control( struct dcn10_ipp *ippn10, bool pixel_data_invert, enum dc_cursor_color_format color_format) @@ -520,7 +514,7 @@ enum cursor_lines_per_chunk { CURSOR_LINE_PER_CHUNK_16 }; -static enum cursor_pitch dcn10_get_cursor_pitch( +static enum cursor_pitch ippn10_get_cursor_pitch( unsigned int pitch) { enum cursor_pitch hw_pitch; @@ -544,7 +538,7 @@ static enum cursor_pitch dcn10_get_cursor_pitch( return hw_pitch; } -static enum cursor_lines_per_chunk dcn10_get_lines_per_chunk( +static enum cursor_lines_per_chunk ippn10_get_lines_per_chunk( unsigned int cur_width, enum dc_cursor_color_format format) { @@ -565,13 +559,13 @@ static enum cursor_lines_per_chunk dcn10_get_lines_per_chunk( return line_per_chunk; } -static void dcn10_cursor_set_attributes( +static void ippn10_cursor_set_attributes( struct input_pixel_processor *ipp, const struct dc_cursor_attributes *attr) { struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); - enum cursor_pitch hw_pitch = dcn10_get_cursor_pitch(attr->pitch); - enum cursor_lines_per_chunk lpc = dcn10_get_lines_per_chunk( + enum cursor_pitch hw_pitch = ippn10_get_cursor_pitch(attr->pitch); + enum cursor_lines_per_chunk lpc = ippn10_get_lines_per_chunk( attr->width, attr->color_format); ippn10->curs_attr = *attr; @@ -590,12 +584,12 @@ static void dcn10_cursor_set_attributes( CURSOR_PITCH, hw_pitch, CURSOR_LINES_PER_CHUNK, lpc); - dcn10_cursor_program_control(ippn10, + ippn10_cursor_program_control(ippn10, attr->attribute_flags.bits.INVERT_PIXEL_DATA, attr->color_format); } -static void dcn10_cursor_set_position( +static void ippn10_cursor_set_position( struct input_pixel_processor *ipp, const struct dc_cursor_position *pos, const struct dc_cursor_mi_param *param) @@ -632,7 +626,7 @@ static void dcn10_cursor_set_position( cur_en = 0; /* not visible beyond left edge*/ if (cur_en && REG_READ(CURSOR_SURFACE_ADDRESS) == 0) - dcn10_cursor_set_attributes(ipp, &ippn10->curs_attr); + ippn10_cursor_set_attributes(ipp, &ippn10->curs_attr); REG_UPDATE(CURSOR_CONTROL, CURSOR_ENABLE, cur_en); REG_UPDATE(CURSOR0_CONTROL, @@ -658,7 +652,7 @@ enum pixel_format_description { }; -static void dcn10_setup_format_flags(enum surface_pixel_format input_format,\ +static void ippn10_setup_format_flags(enum surface_pixel_format input_format,\ enum pixel_format_description *fmt) { @@ -671,7 +665,7 @@ static void dcn10_setup_format_flags(enum surface_pixel_format input_format,\ *fmt = PIXEL_FORMAT_FIXED; } -static void dcn10_ipp_set_degamma_format_float(struct input_pixel_processor *ipp, +static void ippn10_set_degamma_format_float(struct input_pixel_processor *ipp, bool is_float) { struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); @@ -686,7 +680,7 @@ static void dcn10_ipp_set_degamma_format_float(struct input_pixel_processor *ipp } -static void dcn10_ipp_cnv_setup ( +static void ippn10_cnv_setup ( struct input_pixel_processor *ipp, enum surface_pixel_format input_format, enum expansion_mode mode, @@ -701,7 +695,7 @@ static void dcn10_ipp_cnv_setup ( struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); bool force_disable_cursor = false; - dcn10_setup_format_flags(input_format, &fmt); + ippn10_setup_format_flags(input_format, &fmt); alpha_en = 1; pixel_format = 0; color_space = COLOR_SPACE_SRGB; @@ -729,7 +723,7 @@ static void dcn10_ipp_cnv_setup ( break; } - dcn10_ipp_set_degamma_format_float(ipp, is_float); + ippn10_set_degamma_format_float(ipp, is_float); switch (input_format) { case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: @@ -787,7 +781,7 @@ static void dcn10_ipp_cnv_setup ( CNVC_SURFACE_PIXEL_FORMAT, pixel_format); REG_UPDATE(FORMAT_CONTROL, ALPHA_EN, alpha_en); - dcn10_program_input_csc(ipp, color_space, select); + ippn10_program_input_csc(ipp, color_space, select); if (force_disable_cursor) { REG_UPDATE(CURSOR_CONTROL, @@ -798,7 +792,7 @@ static void dcn10_ipp_cnv_setup ( } -static bool dcn10_degamma_ram_inuse(struct input_pixel_processor *ipp, +static bool ippn10_degamma_ram_inuse(struct input_pixel_processor *ipp, bool *ram_a_inuse) { bool ret = false; @@ -818,7 +812,7 @@ static bool dcn10_degamma_ram_inuse(struct input_pixel_processor *ipp, return ret; } -static bool dcn10_ingamma_ram_inuse(struct input_pixel_processor *ipp, +static bool ippn10_ingamma_ram_inuse(struct input_pixel_processor *ipp, bool *ram_a_inuse) { bool in_use = false; @@ -840,7 +834,7 @@ static bool dcn10_ingamma_ram_inuse(struct input_pixel_processor *ipp, return in_use; } -static void dcn10_degamma_ram_select(struct input_pixel_processor *ipp, +static void ippn10_degamma_ram_select(struct input_pixel_processor *ipp, bool use_ram_a) { struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); @@ -852,22 +846,22 @@ static void dcn10_degamma_ram_select(struct input_pixel_processor *ipp, } -static void dcn10_ipp_set_degamma_pwl(struct input_pixel_processor *ipp, +static void ippn10_set_degamma_pwl(struct input_pixel_processor *ipp, const struct pwl_params *params) { bool is_ram_a = true; - ipp_power_on_degamma_lut(ipp, true); - dcn10_ipp_enable_cm_block(ipp); - dcn10_degamma_ram_inuse(ipp, &is_ram_a); + ippn10_power_on_degamma_lut(ipp, true); + ippn10_enable_cm_block(ipp); + ippn10_degamma_ram_inuse(ipp, &is_ram_a); if (is_ram_a == true) - dcn10_ipp_program_degamma_lutb_settings(ipp, params); + ippn10_program_degamma_lutb_settings(ipp, params); else - dcn10_ipp_program_degamma_luta_settings(ipp, params); + ippn10_program_degamma_luta_settings(ipp, params); - ipp_program_degamma_lut(ipp, params->rgb_resulted, + ippn10_program_degamma_lut(ipp, params->rgb_resulted, params->hw_points_num, !is_ram_a); - dcn10_degamma_ram_select(ipp, !is_ram_a); + ippn10_degamma_ram_select(ipp, !is_ram_a); } /* @@ -879,7 +873,7 @@ static void dcn10_ipp_set_degamma_pwl(struct input_pixel_processor *ipp, * In the future, this function should support additional input gamma methods, * such as piecewise linear mapping, and input gamma bypass. */ -void dcn10_ipp_program_input_lut( +static void ippn10_program_input_lut( struct input_pixel_processor *ipp, const struct dc_gamma *gamma) { @@ -889,9 +883,9 @@ void dcn10_ipp_program_input_lut( uint32_t ram_num; // Power on LUT memory. REG_SET(CM_MEM_PWR_CTRL, 0, SHARED_MEM_PWR_DIS, 1); - dcn10_ipp_enable_cm_block(ipp); + ippn10_enable_cm_block(ipp); // Determine whether to use RAM A or RAM B - dcn10_ingamma_ram_inuse(ipp, &rama_occupied); + ippn10_ingamma_ram_inuse(ipp, &rama_occupied); if (!rama_occupied) REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_SEL, 0); else @@ -936,13 +930,13 @@ static void dcn10_ipp_destroy(struct input_pixel_processor **ipp) } static const struct ipp_funcs dcn10_ipp_funcs = { - .ipp_cursor_set_attributes = dcn10_cursor_set_attributes, - .ipp_cursor_set_position = dcn10_cursor_set_position, - .ipp_set_degamma = dcn10_ipp_set_degamma, - .ipp_program_input_lut = dcn10_ipp_program_input_lut, - .ipp_full_bypass = dcn10_ipp_full_bypass, - .ipp_setup = dcn10_ipp_cnv_setup, - .ipp_program_degamma_pwl = dcn10_ipp_set_degamma_pwl, + .ipp_cursor_set_attributes = ippn10_cursor_set_attributes, + .ipp_cursor_set_position = ippn10_cursor_set_position, + .ipp_set_degamma = ippn10_set_degamma, + .ipp_program_input_lut = ippn10_program_input_lut, + .ipp_full_bypass = ippn10_full_bypass, + .ipp_setup = ippn10_cnv_setup, + .ipp_program_degamma_pwl = ippn10_set_degamma_pwl, .ipp_destroy = dcn10_ipp_destroy }; @@ -962,3 +956,4 @@ void dcn10_ipp_construct( ippn10->ipp_shift = ipp_shift; ippn10->ipp_mask = ipp_mask; } + diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h index d608abf0e822..1703589623b0 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h @@ -292,6 +292,7 @@ IPP_SF(CNVC_CFG0_FORMAT_CONTROL, OUTPUT_FP, mask_sh) #define IPP_DCN10_REG_FIELD_LIST(type) \ + type CM_DGAM_CONFIG_STATUS; \ type CM_ICSC_MODE; \ type CM_ICSC_C11; \ type CM_ICSC_C12; \ -- cgit From 7dbeaae2a554c479120836bb02a97d602e5ad4a3 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 7 Jul 2017 10:37:46 -0400 Subject: drm/amd/display: dal1.1 xfm prog update Signed-off-by: Dmytro Laktyushkin Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn10/dcn10_transform.c | 10 ++--- .../gpu/drm/amd/display/dc/dcn10/dcn10_transform.h | 43 +++++++++++----------- 2 files changed, 27 insertions(+), 26 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c index 398af229f2a7..59ba2d250d6d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c @@ -212,7 +212,7 @@ static int get_pixel_depth_val(enum lb_pixel_depth depth) } } -static void transform_set_lb( +static void xfmn10_set_lb( struct dcn10_transform *xfm, const struct line_buffer_params *lb_params, enum lb_memory_config mem_size_config) @@ -622,7 +622,7 @@ void transform_set_scaler_auto_scale( return; lb_config = find_lb_memory_config(scl_data); - transform_set_lb(xfm, &scl_data->lb_params, lb_config); + xfmn10_set_lb(xfm, &scl_data->lb_params, lb_config); if (dscl_mode == DSCL_MODE_SCALING_444_BYPASS) return; @@ -738,7 +738,7 @@ static void transform_set_manual_ratio_init( } /* Main function to program scaler and line buffer in manual scaling mode */ -static void transform_set_scaler_manual_scale( +static void xfmn10_set_scaler_manual_scale( struct transform *xfm_base, const struct scaler_data *scl_data) { @@ -769,7 +769,7 @@ static void transform_set_scaler_manual_scale( return; /* LB */ lb_config = find_lb_memory_config(scl_data); - transform_set_lb(xfm, &scl_data->lb_params, lb_config); + xfmn10_set_lb(xfm, &scl_data->lb_params, lb_config); if (dscl_mode == DSCL_MODE_SCALING_444_BYPASS) return; @@ -1027,7 +1027,7 @@ static void dcn_transform_set_gamut_remap( static struct transform_funcs dcn10_transform_funcs = { .transform_reset = transform_reset, - .transform_set_scaler = transform_set_scaler_manual_scale, + .transform_set_scaler = xfmn10_set_scaler_manual_scale, .transform_get_optimal_number_of_taps = transform_get_optimal_number_of_taps, .transform_set_gamut_remap = dcn_transform_set_gamut_remap, }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.h index 880a554886b8..8df74cc153f5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.h @@ -38,6 +38,13 @@ .field_name = reg_name ## __ ## field_name ## post_fix #define TF_REG_LIST_DCN(id) \ + SRI(CM_GAMUT_REMAP_CONTROL, CM, id),\ + SRI(CM_GAMUT_REMAP_C11_C12, CM, id),\ + SRI(CM_GAMUT_REMAP_C13_C14, CM, id),\ + SRI(CM_GAMUT_REMAP_C21_C22, CM, id),\ + SRI(CM_GAMUT_REMAP_C23_C24, CM, id),\ + SRI(CM_GAMUT_REMAP_C31_C32, CM, id),\ + SRI(CM_GAMUT_REMAP_C33_C34, CM, id),\ SRI(DSCL_EXT_OVERSCAN_LEFT_RIGHT, DSCL, id), \ SRI(DSCL_EXT_OVERSCAN_TOP_BOTTOM, DSCL, id), \ SRI(OTG_H_BLANK, DSCL, id), \ @@ -74,13 +81,6 @@ #define TF_REG_LIST_DCN10(id) \ TF_REG_LIST_DCN(id), \ - SRI(CM_GAMUT_REMAP_CONTROL, CM, id),\ - SRI(CM_GAMUT_REMAP_C11_C12, CM, id),\ - SRI(CM_GAMUT_REMAP_C13_C14, CM, id),\ - SRI(CM_GAMUT_REMAP_C21_C22, CM, id),\ - SRI(CM_GAMUT_REMAP_C23_C24, CM, id),\ - SRI(CM_GAMUT_REMAP_C31_C32, CM, id),\ - SRI(CM_GAMUT_REMAP_C33_C34, CM, id),\ SRI(CM_COMA_C11_C12, CM, id),\ SRI(CM_COMA_C13_C14, CM, id),\ SRI(CM_COMA_C21_C22, CM, id),\ @@ -95,6 +95,19 @@ SRI(CM_COMB_C33_C34, CM, id) #define TF_REG_LIST_SH_MASK_DCN(mask_sh)\ + TF_SF(CM0_CM_GAMUT_REMAP_CONTROL, CM_GAMUT_REMAP_MODE, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C11_C12, CM_GAMUT_REMAP_C11, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C11_C12, CM_GAMUT_REMAP_C12, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C13_C14, CM_GAMUT_REMAP_C13, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C13_C14, CM_GAMUT_REMAP_C14, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C21_C22, CM_GAMUT_REMAP_C21, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C21_C22, CM_GAMUT_REMAP_C22, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C23_C24, CM_GAMUT_REMAP_C23, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C23_C24, CM_GAMUT_REMAP_C24, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C31_C32, CM_GAMUT_REMAP_C31, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C31_C32, CM_GAMUT_REMAP_C32, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C33_C34, CM_GAMUT_REMAP_C33, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C33_C34, CM_GAMUT_REMAP_C34, mask_sh),\ TF_SF(DSCL0_DSCL_EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_LEFT, mask_sh),\ TF_SF(DSCL0_DSCL_EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_RIGHT, mask_sh),\ TF_SF(DSCL0_DSCL_EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_BOTTOM, mask_sh),\ @@ -176,19 +189,6 @@ TF_SF(DSCL0_LB_DATA_FORMAT, PIXEL_REDUCE_MODE, mask_sh),\ TF_SF(DSCL0_LB_DATA_FORMAT, DYNAMIC_PIXEL_DEPTH, mask_sh),\ TF_SF(DSCL0_LB_DATA_FORMAT, DITHER_EN, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_CONTROL, CM_GAMUT_REMAP_MODE, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C11_C12, CM_GAMUT_REMAP_C11, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C11_C12, CM_GAMUT_REMAP_C12, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C13_C14, CM_GAMUT_REMAP_C13, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C13_C14, CM_GAMUT_REMAP_C14, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C21_C22, CM_GAMUT_REMAP_C21, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C21_C22, CM_GAMUT_REMAP_C22, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C23_C24, CM_GAMUT_REMAP_C23, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C23_C24, CM_GAMUT_REMAP_C24, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C31_C32, CM_GAMUT_REMAP_C31, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C31_C32, CM_GAMUT_REMAP_C32, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C33_C34, CM_GAMUT_REMAP_C33, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C33_C34, CM_GAMUT_REMAP_C34, mask_sh),\ TF_SF(CM0_CM_COMA_C11_C12, CM_COMA_C11, mask_sh),\ TF_SF(CM0_CM_COMA_C11_C12, CM_COMA_C12, mask_sh),\ TF_SF(CM0_CM_COMA_C13_C14, CM_COMA_C13, mask_sh),\ @@ -411,10 +411,11 @@ struct dcn10_transform { int lb_bits_per_entry; }; -bool dcn10_transform_construct(struct dcn10_transform *xfm110, +bool dcn10_transform_construct(struct dcn10_transform *xfmn10, struct dc_context *ctx, uint32_t inst, const struct dcn_transform_registers *tf_regs, const struct dcn_transform_shift *tf_shift, const struct dcn_transform_mask *tf_mask); + #endif -- cgit From 4e5095ca06a00fda50e2fcc721b1f923478778a8 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 7 Jul 2017 11:24:13 -0400 Subject: drm/amd/display: dal1.1 hwseq prog update Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 223bb79bc8b8..4c39bf052d08 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -64,17 +64,13 @@ static void enable_dppclk( plane_id, dppclk_div); - if (dppclk_div) { - /* 1/2 DISPCLK*/ + if (hws->shifts->DPPCLK_RATE_CONTROL) REG_UPDATE_2(DPP_CONTROL[plane_id], - DPPCLK_RATE_CONTROL, 1, + DPPCLK_RATE_CONTROL, dppclk_div, DPP_CLOCK_ENABLE, 1); - } else { - /* DISPCLK */ - REG_UPDATE_2(DPP_CONTROL[plane_id], - DPPCLK_RATE_CONTROL, 0, + else + REG_UPDATE(DPP_CONTROL[plane_id], DPP_CLOCK_ENABLE, 1); - } } static void enable_power_gating_plane( -- cgit From a85c205ae3d183c196d0af7df336b1315e95faf7 Mon Sep 17 00:00:00 2001 From: Corbin McElhanney Date: Mon, 10 Jul 2017 15:52:10 -0400 Subject: drm/amd/display: Fix context copy memory leak This change corrects an error introduced in 355f123f. Instead of using the copy constructor to assign the new context, we swap the pointer. Signed-off-by: Corbin McElhanney Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 52077d39b30a..4f9302901a62 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -972,7 +972,9 @@ static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *c dc_enable_stereo(dc, context, dc_streams, context->stream_count); - dc_resource_validate_ctx_copy_construct(context, core_dc->current_context); + dc_resource_validate_ctx_destruct(core_dc->current_context); + dm_free(core_dc->current_context); + core_dc->current_context = context; return (result == DC_OK); } @@ -1057,9 +1059,6 @@ bool dc_commit_streams( result = dc_commit_context_no_check(dc, context); - dc_resource_validate_ctx_destruct(context); - dm_free(context); - return (result == DC_OK); fail: -- cgit From adef2ce36e6ad76888159ea6225da54019d0ff0e Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Mon, 10 Jul 2017 16:24:42 -0400 Subject: drm/amd/display: Leave all validate_ctx life cycle management to DC. Follow DC fix. Signed-off-by: Andrey Grodzovsky Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 15 --------------- 1 file changed, 15 deletions(-) (limited to 'drivers/gpu') 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 4b844e5c5dcd..63d23c6e7574 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -653,27 +653,12 @@ dm_atomic_state_alloc(struct drm_device *dev) return &state->base; } - -void dm_atomic_state_clear(struct drm_atomic_state *state) -{ - struct dm_atomic_state *dm_state = to_dm_atomic_state(state); - - if (dm_state->context) { - dc_resource_validate_ctx_destruct(dm_state->context); - dm_free(dm_state->context); - dm_state->context = NULL; - } - - drm_atomic_state_default_clear(state); -} - static const struct drm_mode_config_funcs amdgpu_dm_mode_funcs = { .fb_create = amdgpu_user_framebuffer_create, .output_poll_changed = amdgpu_output_poll_changed, .atomic_check = amdgpu_dm_atomic_check, .atomic_commit = amdgpu_dm_atomic_commit, .atomic_state_alloc = dm_atomic_state_alloc, - .atomic_state_clear = dm_atomic_state_clear, }; static struct drm_mode_config_helper_funcs amdgpu_dm_mode_config_helperfuncs = { -- cgit From 3d21a662500fdcc2760ec7d936692bb9efa06c67 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Tue, 25 Jul 2017 18:11:18 -0400 Subject: drm/amd/display: Clean dm_plane_state hooks. New surface is created in check only, in duplicate we just reference exsisting surface and in destroy we release it. Signed-off-by: Andrey Grodzovsky Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 43 +++------------------- 1 file changed, 6 insertions(+), 37 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index c222cdb59ac1..0439f75fb24d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -1417,7 +1417,6 @@ const struct drm_encoder_helper_funcs amdgpu_dm_encoder_helper_funcs = { static void dm_drm_plane_reset(struct drm_plane *plane) { struct dm_plane_state *amdgpu_state = NULL; - struct amdgpu_device *adev = plane->dev->dev_private; if (plane->state) plane->funcs->atomic_destroy_state(plane, plane->state); @@ -1428,9 +1427,6 @@ static void dm_drm_plane_reset(struct drm_plane *plane) plane->state = &amdgpu_state->base; plane->state->plane = plane; plane->state->rotation = DRM_MODE_ROTATE_0; - - amdgpu_state->dc_surface = dc_create_surface(adev->dm.dc); - WARN_ON(!amdgpu_state->dc_surface); } else WARN_ON(1); @@ -1440,35 +1436,17 @@ static struct drm_plane_state * dm_drm_plane_duplicate_state(struct drm_plane *plane) { struct dm_plane_state *dm_plane_state, *old_dm_plane_state; - struct amdgpu_device *adev = plane->dev->dev_private; old_dm_plane_state = to_dm_plane_state(plane->state); dm_plane_state = kzalloc(sizeof(*dm_plane_state), GFP_KERNEL); if (!dm_plane_state) return NULL; - if (old_dm_plane_state->dc_surface) { - struct dc_surface *dc_surface = dc_create_surface(adev->dm.dc); - if (WARN_ON(!dc_surface)) - return NULL; - - __drm_atomic_helper_plane_duplicate_state(plane, &dm_plane_state->base); - - memcpy(dc_surface, old_dm_plane_state->dc_surface, sizeof(*dc_surface)); + __drm_atomic_helper_plane_duplicate_state(plane, &dm_plane_state->base); - if (old_dm_plane_state->dc_surface->gamma_correction) - dc_gamma_retain(dc_surface->gamma_correction); - - if (old_dm_plane_state->dc_surface->in_transfer_func) - dc_transfer_func_retain(dc_surface->in_transfer_func); - - dm_plane_state->dc_surface = dc_surface; - - /*TODO Check for inferred values to be reset */ - } - else { - WARN_ON(1); - return NULL; + if (old_dm_plane_state->dc_surface) { + dm_plane_state->dc_surface = old_dm_plane_state->dc_surface; + dc_surface_retain(dm_plane_state->dc_surface); } return &dm_plane_state->base; @@ -1479,17 +1457,8 @@ void dm_drm_plane_destroy_state(struct drm_plane *plane, { struct dm_plane_state *dm_plane_state = to_dm_plane_state(state); - if (dm_plane_state->dc_surface) { - struct dc_surface *dc_surface = dm_plane_state->dc_surface; - - if (dc_surface->gamma_correction) - dc_gamma_release(&dc_surface->gamma_correction); - - if (dc_surface->in_transfer_func) - dc_transfer_func_release(dc_surface->in_transfer_func); - - dc_surface_release(dc_surface); - } + if (dm_plane_state->dc_surface) + dc_surface_release(dm_plane_state->dc_surface); __drm_atomic_helper_plane_destroy_state(state); kfree(dm_plane_state); -- cgit From d7e3316cf492d950f086e7fe5d3eb643c9e84be4 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Fri, 7 Jul 2017 16:14:12 -0400 Subject: drm/amd/display: Attach surface to dm_plane_state. Attach surface to state. Remove Create surface from commit. Propogate any surface creation and initialization error back to atomic_check caller. clean outdated code in check and commit. Signed-off-by: Andrey Grodzovsky Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 348 +++++++++------------ .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.h | 2 +- 2 files changed, 147 insertions(+), 203 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 0439f75fb24d..b56150a29502 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -299,16 +299,16 @@ static bool fill_rects_from_plane_state( return true; } -static bool get_fb_info( +static int get_fb_info( const struct amdgpu_framebuffer *amdgpu_fb, uint64_t *tiling_flags, uint64_t *fb_location) { struct amdgpu_bo *rbo = gem_to_amdgpu_bo(amdgpu_fb->obj); int r = amdgpu_bo_reserve(rbo, false); - if (unlikely(r != 0)){ + if (unlikely(r)) { DRM_ERROR("Unable to reserve buffer\n"); - return false; + return r; } if (fb_location) @@ -319,9 +319,10 @@ static bool get_fb_info( amdgpu_bo_unreserve(rbo); - return true; + return r; } -static void fill_plane_attributes_from_fb( + +static int fill_plane_attributes_from_fb( struct amdgpu_device *adev, struct dc_surface *surface, const struct amdgpu_framebuffer *amdgpu_fb, bool addReq) @@ -330,13 +331,16 @@ static void fill_plane_attributes_from_fb( uint64_t fb_location = 0; unsigned int awidth; const struct drm_framebuffer *fb = &amdgpu_fb->base; + int ret = 0; struct drm_format_name_buf format_name; - get_fb_info( + ret = get_fb_info( amdgpu_fb, &tiling_flags, addReq == true ? &fb_location:NULL); + if (ret) + return ret; switch (fb->format->format) { case DRM_FORMAT_C8: @@ -366,7 +370,7 @@ static void fill_plane_attributes_from_fb( default: DRM_ERROR("Unsupported screen format %s\n", drm_get_format_name(fb->format->format, &format_name)); - return; + return -EINVAL; } if (surface->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) { @@ -467,23 +471,26 @@ static void fill_plane_attributes_from_fb( surface->scaling_quality.v_taps = 0; surface->stereo_format = PLANE_STEREO_FORMAT_NONE; + return ret; + } #define NUM_OF_RAW_GAMMA_RAMP_RGB_256 256 -static void fill_gamma_from_crtc( - const struct drm_crtc *crtc, +static void fill_gamma_from_crtc_state( + const struct drm_crtc_state *crtc_state, struct dc_surface *dc_surface) { int i; struct dc_gamma *gamma; - struct drm_crtc_state *state = crtc->state; - struct drm_color_lut *lut = (struct drm_color_lut *) state->gamma_lut->data; + struct drm_color_lut *lut = (struct drm_color_lut *) crtc_state->gamma_lut->data; gamma = dc_create_gamma(); - if (gamma == NULL) + if (gamma == NULL) { + WARN_ON(1); return; + } for (i = 0; i < NUM_OF_RAW_GAMMA_RAMP_RGB_256; i++) { gamma->red[i] = lut[i].red; @@ -494,27 +501,35 @@ static void fill_gamma_from_crtc( dc_surface->gamma_correction = gamma; } -static void fill_plane_attributes( +static int fill_plane_attributes( struct amdgpu_device *adev, struct dc_surface *surface, - struct drm_plane_state *state, bool addrReq) + struct drm_plane_state *plane_state, + struct drm_crtc_state *crtc_state, + bool addrReq) { const struct amdgpu_framebuffer *amdgpu_fb = - to_amdgpu_framebuffer(state->fb); - const struct drm_crtc *crtc = state->crtc; + to_amdgpu_framebuffer(plane_state->fb); + const struct drm_crtc *crtc = plane_state->crtc; struct dc_transfer_func *input_tf; + int ret = 0; + + if (!fill_rects_from_plane_state(plane_state, surface)) + return -EINVAL; - fill_rects_from_plane_state(state, surface); - fill_plane_attributes_from_fb( + ret = fill_plane_attributes_from_fb( crtc->dev->dev_private, surface, amdgpu_fb, addrReq); + if (ret) + return ret; + input_tf = dc_create_transfer_func(); if (input_tf == NULL) - return; + return -ENOMEM; input_tf->type = TF_TYPE_PREDEFINED; input_tf->tf = TRANSFER_FUNCTION_SRGB; @@ -522,9 +537,10 @@ static void fill_plane_attributes( surface->in_transfer_func = input_tf; /* In case of gamma set, update gamma value */ - if (state->crtc->state->gamma_lut) { - fill_gamma_from_crtc(crtc, surface); - } + if (crtc_state->gamma_lut) + fill_gamma_from_crtc_state(crtc_state, surface); + + return ret; } /*****************************************************************************/ @@ -607,57 +623,6 @@ static void update_stream_scaling_settings( } -static void add_surface(struct dc *dc, - struct drm_crtc *crtc, - struct drm_plane *plane, - const struct dc_surface **dc_surfaces) -{ - struct dc_surface *dc_surface; - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state); - const struct dc_stream *dc_stream = acrtc_state->stream; - unsigned long flags; - - spin_lock_irqsave(&crtc->dev->event_lock, flags); - if (acrtc->pflip_status != AMDGPU_FLIP_NONE) { - DRM_ERROR("add_surface: acrtc %d, already busy\n", - acrtc->crtc_id); - spin_unlock_irqrestore(&crtc->dev->event_lock, flags); - /* In comit tail framework this cannot happen */ - BUG_ON(0); - } - spin_unlock_irqrestore(&crtc->dev->event_lock, flags); - - if (!dc_stream) { - dm_error( - "%s: Failed to obtain stream on crtc (%d)!\n", - __func__, - acrtc->crtc_id); - goto fail; - } - - dc_surface = dc_create_surface(dc); - - if (!dc_surface) { - dm_error( - "%s: Failed to create a surface!\n", - __func__); - goto fail; - } - - /* Surface programming */ - fill_plane_attributes( - crtc->dev->dev_private, - dc_surface, - plane->state, - true); - - *dc_surfaces = dc_surface; - -fail: - return; -} - static enum dc_color_depth convert_color_depth_from_display_info( const struct drm_connector *connector) { @@ -1444,9 +1409,9 @@ dm_drm_plane_duplicate_state(struct drm_plane *plane) __drm_atomic_helper_plane_duplicate_state(plane, &dm_plane_state->base); - if (old_dm_plane_state->dc_surface) { - dm_plane_state->dc_surface = old_dm_plane_state->dc_surface; - dc_surface_retain(dm_plane_state->dc_surface); + if (old_dm_plane_state->surface) { + dm_plane_state->surface = old_dm_plane_state->surface; + dc_surface_retain(dm_plane_state->surface); } return &dm_plane_state->base; @@ -1457,8 +1422,8 @@ void dm_drm_plane_destroy_state(struct drm_plane *plane, { struct dm_plane_state *dm_plane_state = to_dm_plane_state(state); - if (dm_plane_state->dc_surface) - dc_surface_release(dm_plane_state->dc_surface); + if (dm_plane_state->surface) + dc_surface_release(dm_plane_state->surface); __drm_atomic_helper_plane_destroy_state(state); kfree(dm_plane_state); @@ -1481,6 +1446,11 @@ static int dm_plane_helper_prepare_fb( struct drm_gem_object *obj; struct amdgpu_bo *rbo; int r; + struct dm_plane_state *dm_plane_state_new, *dm_plane_state_old; + unsigned int awidth; + + dm_plane_state_old = to_dm_plane_state(plane->state); + dm_plane_state_new = to_dm_plane_state(new_state); if (!new_state->fb) { DRM_DEBUG_KMS("No FB bound\n"); @@ -1497,6 +1467,7 @@ static int dm_plane_helper_prepare_fb( r = amdgpu_bo_pin(rbo, AMDGPU_GEM_DOMAIN_VRAM, &afb->address); + amdgpu_bo_unreserve(rbo); if (unlikely(r != 0)) { @@ -1506,6 +1477,23 @@ static int dm_plane_helper_prepare_fb( amdgpu_bo_ref(rbo); + if (dm_plane_state_new->surface && + dm_plane_state_old->surface != dm_plane_state_new->surface) { + struct dc_surface *surface = dm_plane_state_new->surface; + + if (surface->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) { + surface->address.grph.addr.low_part = lower_32_bits(afb->address); + surface->address.grph.addr.high_part = upper_32_bits(afb->address); + } else { + awidth = ALIGN(new_state->fb->width, 64); + surface->address.video_progressive.luma_addr.low_part + = lower_32_bits(afb->address); + surface->address.video_progressive.chroma_addr.low_part + = lower_32_bits(afb->address) + + (awidth * new_state->fb->height); + } + } + /* It's a hack for s3 since in 4.9 kernel filter out cursor buffer * prepare and cleanup in drm_atomic_helper_prepare_planes * and drm_atomic_helper_cleanup_planes because fb doens't in s3. @@ -2362,59 +2350,43 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, struct amdgpu_crtc *acrtc_attach = to_amdgpu_crtc(pcrtc); struct dm_crtc_state *acrtc_state = to_dm_crtc_state(pcrtc->state); int planes_count = 0; + unsigned long flags; /* update planes when needed */ for_each_plane_in_state(state, plane, old_plane_state, i) { struct drm_plane_state *plane_state = plane->state; struct drm_crtc *crtc = plane_state->crtc; struct drm_framebuffer *fb = plane_state->fb; - struct drm_connector *connector; - struct dm_connector_state *con_state = NULL; bool pflip_needed; + struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state); if (plane->type == DRM_PLANE_TYPE_CURSOR) { handle_cursor_update(plane, old_plane_state); continue; } - if (!fb || !crtc || pcrtc != crtc || !crtc->state->active) + if (!fb || !crtc || pcrtc != crtc || !crtc->state->active || + (!crtc->state->planes_changed && + !pcrtc->state->color_mgmt_changed)) continue; pflip_needed = !state->allow_modeset; + + spin_lock_irqsave(&crtc->dev->event_lock, flags); + if (acrtc_attach->pflip_status != AMDGPU_FLIP_NONE) { + DRM_ERROR("add_surface: acrtc %d, already busy\n", + acrtc_attach->crtc_id); + spin_unlock_irqrestore(&crtc->dev->event_lock, flags); + /* In comit tail framework this cannot happen */ + WARN_ON(1); + } + spin_unlock_irqrestore(&crtc->dev->event_lock, flags); + if (!pflip_needed) { - list_for_each_entry(connector, - &dev->mode_config.connector_list, - head) { - if (connector->state->crtc == crtc) { - con_state = to_dm_connector_state( - connector->state); - break; - } - } + WARN_ON(!dm_plane_state->surface); - /* - * This situation happens in the following case: - * we are about to get set mode for connector who's only - * possible crtc (in encoder crtc mask) is used by - * another connector, that is why it will try to - * re-assing crtcs in order to make configuration - * supported. For our implementation we need to make all - * encoders support all crtcs, then this issue will - * never arise again. But to guard code from this issue - * check is left. - * - * Also it should be needed when used with actual - * drm_atomic_commit ioctl in future - */ - if (!con_state) - continue; + dc_surfaces_constructed[planes_count] = dm_plane_state->surface; - add_surface(dm->dc, crtc, plane, - &dc_surfaces_constructed[planes_count]); - if (dc_surfaces_constructed[planes_count] == NULL) { - dm_error("%s: Failed to add surface!\n", __func__); - continue; - } dc_stream_attach = acrtc_state->stream; planes_count++; @@ -2461,9 +2433,6 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, planes_count, dc_stream_attach)) dm_error("%s: Failed to attach surface!\n", __func__); - - for (i = 0; i < planes_count; i++) - dc_surface_release(dc_surfaces_constructed[i]); } else { /*TODO BUG Here should go disable planes on CRTC. */ } @@ -2846,7 +2815,6 @@ static uint32_t add_val_sets_surface( static uint32_t update_in_val_sets_stream( struct dc_validation_set *val_sets, - struct drm_crtc **crtcs, uint32_t set_count, const struct dc_stream *old_stream, const struct dc_stream *new_stream, @@ -2861,7 +2829,6 @@ static uint32_t update_in_val_sets_stream( } val_sets[i].stream = new_stream; - crtcs[i] = crtc; if (i == set_count) /* nothing found. add new one to the end */ @@ -2955,10 +2922,8 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, struct drm_plane_state *plane_state; int i, j; int ret; - struct drm_crtc *crtc_set[MAX_STREAMS] = { 0 }; struct amdgpu_device *adev = dev->dev_private; struct dc *dc = adev->dm.dc; - bool need_to_validate = false; struct drm_connector *connector; struct drm_connector_state *conn_state; int set_count; @@ -2974,13 +2939,10 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, ret = drm_atomic_helper_check(dev, state); if (ret) { - DRM_ERROR("Atomic state validation failed with error :%d !\n", - ret); + DRM_ERROR("Atomic state validation failed with error :%d !\n", ret); return ret; } - ret = -EINVAL; - dm_state = to_dm_atomic_state(state); /* copy existing configuration */ @@ -2992,7 +2954,6 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, if (old_acrtc_state->stream) { dc_stream_retain(old_acrtc_state->stream); set[set_count].stream = old_acrtc_state->stream; - crtc_set[set_count] = crtc; ++set_count; } } @@ -3027,8 +2988,11 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, if (aconnector) { conn_state = drm_atomic_get_connector_state(state, &aconnector->base); - if (IS_ERR(conn_state)) - return ret; + if (IS_ERR(conn_state)) { + ret = PTR_ERR_OR_ZERO(conn_state); + goto fail_crtcs; + } + dm_conn_state = to_dm_connector_state(conn_state); } @@ -3048,17 +3012,16 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, if (new_acrtc_state->stream) dc_stream_release(new_acrtc_state->stream); + new_acrtc_state->stream = new_stream; set_count = update_in_val_sets_stream( set, - crtc_set, set_count, old_acrtc_state->stream, new_acrtc_state->stream, crtc); - need_to_validate = true; aquire_global_lock = true; } else if (modereset_required(crtc_state)) { @@ -3086,9 +3049,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, ret = drm_atomic_add_affected_planes(state, crtc); if (ret) - return ret; - - ret = -EINVAL; + goto fail_crtcs; } } @@ -3113,118 +3074,101 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, if (!is_scaling_state_different(con_new_state, con_old_state)) continue; - need_to_validate = true; aquire_global_lock = true; } - for (i = 0; i < set_count; i++) { + for_each_crtc_in_state(state, crtc, crtc_state, i) { + new_acrtc_state = to_dm_crtc_state(crtc_state); + for_each_plane_in_state(state, plane, plane_state, j) { - struct drm_crtc *crtc = plane_state->crtc; + struct drm_crtc *plane_crtc = plane_state->crtc; struct drm_framebuffer *fb = plane_state->fb; - struct drm_connector *connector; - struct dm_connector_state *dm_conn_state = NULL; - struct drm_crtc_state *crtc_state; bool pflip_needed; + struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state); /*TODO Implement atomic check for cursor plane */ if (plane->type == DRM_PLANE_TYPE_CURSOR) continue; - if (!fb || !crtc || crtc_set[i] != crtc || - !crtc->state->planes_changed || !crtc->state->active) + if (!fb || !plane_crtc || crtc != plane_crtc || + (!crtc_state->planes_changed && + !crtc_state->color_mgmt_changed) || + !crtc_state->active) continue; + WARN_ON(!new_acrtc_state->stream); - crtc_state = drm_atomic_get_crtc_state(state, crtc); pflip_needed = !state->allow_modeset; if (!pflip_needed) { struct dc_surface *surface; - list_for_each_entry(connector, - &dev->mode_config.connector_list, head) { - if (connector->state->crtc == crtc) { - dm_conn_state = to_dm_connector_state( - connector->state); - break; - } - } - - /* - * This situation happens in the following case: - * we are about to get set mode for connector who's only - * possible crtc (in encoder crtc mask) is used by - * another connector, that is why it will try to - * re-assing crtcs in order to make configuration - * supported. For our implementation we need to make all - * encoders support all crtcs, then this issue will - * never arise again. But to guard code from this issue - * check is left. - * - * Also it should be needed when used with actual - * drm_atomic_commit ioctl in future - */ - if (!dm_conn_state) - continue; - surface = dc_create_surface(dc); - fill_plane_attributes( - crtc->dev->dev_private, + + ret = fill_plane_attributes( + plane_crtc->dev->dev_private, surface, plane_state, + crtc_state, false); + if (ret) + goto fail_planes; + + + if (dm_plane_state->surface) + dc_surface_release(dm_plane_state->surface); + + dm_plane_state->surface = surface; add_val_sets_surface(set, set_count, - set[i].stream, + new_acrtc_state->stream, surface); - need_to_validate = true; aquire_global_lock = true; } } } dm_state->context = dc_get_validate_context(dc, set, set_count); - - if (need_to_validate == false || set_count == 0 || dm_state->context) { - ret = 0; - /* - * For full updates case when - * removing/adding/updateding streams on once CRTC while flipping - * on another CRTC, - * acquiring global lock will guarantee that any such full - * update commit - * will wait for completion of any outstanding flip using DRMs - * synchronization events. - */ - if (aquire_global_lock) - ret = do_aquire_global_lock(dev, state); - + if (!dm_state->context) { + ret = -EINVAL; + goto fail_planes; } - /* TODO until surfaces are moved into dm_plane_state release them - * here + /* + * For full updates case when + * removing/adding/updating streams on once CRTC while flipping + * on another CRTC, + * acquiring global lock will guarantee that any such full + * update commit + * will wait for completion of any outstanding flip using DRMs + * synchronization events. */ + if (aquire_global_lock) { + ret = do_aquire_global_lock(dev, state); + if (ret) + goto fail_planes; + } + + /* Must be success */ + WARN_ON(ret); + return ret; + +fail_planes: for (i = 0; i < set_count; i++) for (j = 0; j < set[i].surface_count; j++) dc_surface_release(set[i].surfaces[j]); - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - old_acrtc_state = to_dm_crtc_state(crtc->state); - - if (old_acrtc_state->stream) - dc_stream_release(old_acrtc_state->stream); - } - +fail_crtcs: + for (i = 0; i < set_count; i++) + dc_stream_release(set[i].stream); - if (ret != 0) { - if (ret == -EDEADLK) - DRM_DEBUG_KMS("Atomic check stopped due to to deadlock.\n"); - else if (ret == -EINTR || ret == -EAGAIN || ret == -ERESTARTSYS) - DRM_DEBUG_KMS("Atomic check stopped due to to signal.\n"); - else - DRM_ERROR("Atomic check failed.\n"); - } + if (ret == -EDEADLK) + DRM_DEBUG_KMS("Atomic check stopped due to to deadlock.\n"); + else if (ret == -EINTR || ret == -EAGAIN || ret == -ERESTARTSYS) + DRM_DEBUG_KMS("Atomic check stopped due to to signal.\n"); + else + DRM_ERROR("Atomic check failed with err: %d .\n", ret); return ret; } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h index 36cb1c840810..115d9081d964 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h @@ -40,7 +40,7 @@ struct dc_stream; struct dm_plane_state { struct drm_plane_state base; - struct dc_surface *dc_surface; + struct dc_surface *surface; }; struct dm_crtc_state { -- cgit From 7b0c470fcb44b7dbe63db5b5fb52b6123ebe335f Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Mon, 10 Jul 2017 14:04:21 -0400 Subject: drm/amd/display: Flattening to dc_transfer_func Flattening dc transfer functions in the following manner: transfer_func > core_transfer_func > dc_transfer_func References to deleted structs are updated as needed. Signed-off-by: Leo (Sunpeng) Li Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_surface.c | 19 ++++--------------- drivers/gpu/drm/amd/display/dc/dc.h | 10 ++++++---- .../drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 10 +++++----- .../gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 10 +++++----- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 8 -------- 5 files changed, 20 insertions(+), 37 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index aa6ac9596235..d44ddfb85748 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -45,18 +45,11 @@ struct gamma { int ref_count; }; -struct transfer_func { - struct core_transfer_func protected; - int ref_count; -}; - #define DC_SURFACE_TO_SURFACE(dc_surface) container_of(dc_surface, struct surface, protected.public) #define CORE_SURFACE_TO_SURFACE(core_surface) container_of(core_surface, struct surface, protected) #define DC_GAMMA_TO_GAMMA(dc_gamma) \ container_of(dc_gamma, struct gamma, protected.public) -#define DC_TRANSFER_FUNC_TO_TRANSFER_FUNC(dc_tf) \ - container_of(dc_tf, struct transfer_func, protected.public) #define CORE_GAMMA_TO_GAMMA(core_gamma) \ container_of(core_gamma, struct gamma, protected) @@ -208,18 +201,14 @@ alloc_fail: return NULL; } -void dc_transfer_func_retain(const struct dc_transfer_func *dc_tf) +void dc_transfer_func_retain(struct dc_transfer_func *tf) { - struct transfer_func *tf = DC_TRANSFER_FUNC_TO_TRANSFER_FUNC(dc_tf); - ASSERT(tf->ref_count > 0); ++tf->ref_count; } -void dc_transfer_func_release(const struct dc_transfer_func *dc_tf) +void dc_transfer_func_release(struct dc_transfer_func *tf) { - struct transfer_func *tf = DC_TRANSFER_FUNC_TO_TRANSFER_FUNC(dc_tf); - ASSERT(tf->ref_count > 0); --tf->ref_count; @@ -229,14 +218,14 @@ void dc_transfer_func_release(const struct dc_transfer_func *dc_tf) struct dc_transfer_func *dc_create_transfer_func() { - struct transfer_func *tf = dm_alloc(sizeof(*tf)); + struct dc_transfer_func *tf = dm_alloc(sizeof(*tf)); if (tf == NULL) goto alloc_fail; ++tf->ref_count; - return &tf->protected.public; + return tf; alloc_fail: return NULL; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 42c1aa8d68af..1fad03cdeb9d 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -293,6 +293,8 @@ struct dc_transfer_func { struct dc_transfer_func_distributed_points tf_pts; enum dc_transfer_func_type type; enum dc_transfer_func_predefined tf; + struct dc_context *ctx; + int ref_count; }; struct dc_surface { @@ -310,7 +312,7 @@ struct dc_surface { struct dc_hdr_static_metadata hdr_static_ctx; const struct dc_gamma *gamma_correction; - const struct dc_transfer_func *in_transfer_func; + struct dc_transfer_func *in_transfer_func; enum dc_color_space color_space; enum surface_pixel_format format; @@ -384,8 +386,8 @@ void dc_gamma_retain(const struct dc_gamma *dc_gamma); void dc_gamma_release(const struct dc_gamma **dc_gamma); struct dc_gamma *dc_create_gamma(void); -void dc_transfer_func_retain(const struct dc_transfer_func *dc_tf); -void dc_transfer_func_release(const struct dc_transfer_func *dc_tf); +void dc_transfer_func_retain(struct dc_transfer_func *dc_tf); +void dc_transfer_func_release(struct dc_transfer_func *dc_tf); struct dc_transfer_func *dc_create_transfer_func(void); /* @@ -465,7 +467,7 @@ struct dc_stream { struct freesync_context freesync_ctx; - const struct dc_transfer_func *out_transfer_func; + struct dc_transfer_func *out_transfer_func; struct colorspace_transform gamut_remap_matrix; struct csc_transform csc_color_matrix; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index d3c84dc36b80..5d64611eb6a6 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -242,7 +242,7 @@ static bool dce110_set_input_transfer_func( const struct core_surface *surface) { struct input_pixel_processor *ipp = pipe_ctx->ipp; - const struct core_transfer_func *tf = NULL; + const struct dc_transfer_func *tf = NULL; struct ipp_prescale_params prescale_params = { 0 }; bool result = true; @@ -250,7 +250,7 @@ static bool dce110_set_input_transfer_func( return false; if (surface->public.in_transfer_func) - tf = DC_TRANSFER_FUNC_TO_CORE(surface->public.in_transfer_func); + tf = surface->public.in_transfer_func; build_prescale_params(&prescale_params, surface); ipp->funcs->ipp_program_prescale(ipp, &prescale_params); @@ -262,8 +262,8 @@ static bool dce110_set_input_transfer_func( /* Default case if no input transfer function specified */ ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_HW_sRGB); - } else if (tf->public.type == TF_TYPE_PREDEFINED) { - switch (tf->public.tf) { + } else if (tf->type == TF_TYPE_PREDEFINED) { + switch (tf->tf) { case TRANSFER_FUNCTION_SRGB: ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_HW_sRGB); @@ -283,7 +283,7 @@ static bool dce110_set_input_transfer_func( result = false; break; } - } else if (tf->public.type == TF_TYPE_BYPASS) { + } else if (tf->type == TF_TYPE_BYPASS) { ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS); } else { /*TF_TYPE_DISTRIBUTED_POINTS - Not supported in DCE 11*/ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 4c39bf052d08..ac0d62c10da2 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -602,14 +602,14 @@ static bool dcn10_set_input_transfer_func( struct pipe_ctx *pipe_ctx, const struct core_surface *surface) { struct input_pixel_processor *ipp = pipe_ctx->ipp; - const struct core_transfer_func *tf = NULL; + const struct dc_transfer_func *tf = NULL; bool result = true; if (ipp == NULL) return false; if (surface->public.in_transfer_func) - tf = DC_TRANSFER_FUNC_TO_CORE(surface->public.in_transfer_func); + tf = surface->public.in_transfer_func; if (surface->public.gamma_correction && dce_use_lut(surface)) ipp->funcs->ipp_program_input_lut(ipp, @@ -617,8 +617,8 @@ static bool dcn10_set_input_transfer_func( if (tf == NULL) ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS); - else if (tf->public.type == TF_TYPE_PREDEFINED) { - switch (tf->public.tf) { + else if (tf->type == TF_TYPE_PREDEFINED) { + switch (tf->tf) { case TRANSFER_FUNCTION_SRGB: ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_HW_sRGB); @@ -638,7 +638,7 @@ static bool dcn10_set_input_transfer_func( result = false; break; } - } else if (tf->public.type == TF_TYPE_BYPASS) { + } else if (tf->type == TF_TYPE_BYPASS) { ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS); } else { /*TF_TYPE_DISTRIBUTED_POINTS*/ diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 030841889803..3e9a0ccca3b4 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -49,9 +49,6 @@ struct core_stream; #define DC_GAMMA_TO_CORE(dc_gamma) \ container_of(dc_gamma, struct core_gamma, public) -#define DC_TRANSFER_FUNC_TO_CORE(dc_transfer_func) \ - container_of(dc_transfer_func, struct core_transfer_func, public) - struct core_surface { struct dc_surface public; struct dc_surface_status status; @@ -63,11 +60,6 @@ struct core_gamma { struct dc_context *ctx; }; -struct core_transfer_func { - struct dc_transfer_func public; - struct dc_context *ctx; -}; - void enable_surface_flip_reporting(struct dc_surface *dc_surface, uint32_t controller_id); -- cgit From 2ebad8eb19f68638c5f5dee385e05aa466e810e5 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Tue, 11 Jul 2017 13:40:52 -0400 Subject: drm/amd/display: change non_dpm0 state's default SR latency Signed-off-by: Charlene Liu Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index a1eabc47558e..0ea0dab49e0f 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -37,8 +37,8 @@ /* Defaults from spreadsheet rev#247 */ const struct dcn_soc_bounding_box dcn10_soc_defaults = { /* latencies */ - .sr_exit_time = 17, /*us*/ - .sr_enter_plus_exit_time = 19, /*us*/ + .sr_exit_time = 13, /*us*/ + .sr_enter_plus_exit_time = 15, /*us*/ .urgent_latency = 4, /*us*/ .dram_clock_change_latency = 17, /*us*/ .write_back_latency = 12, /*us*/ -- cgit From 8a76708ec4be2e9d63131e3769f17a04d8a82c87 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Tue, 11 Jul 2017 14:41:51 -0400 Subject: drm/amd/display: Introduce refcount for dc_validate_context Linux requires to be able to release allocated context in case it was never commited. Signed-off-by: Andrey Grodzovsky Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 64 ++++++++++++++++++------- drivers/gpu/drm/amd/display/dc/dc.h | 4 ++ drivers/gpu/drm/amd/display/dc/inc/core_types.h | 2 + 3 files changed, 54 insertions(+), 16 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 4f9302901a62..e81c9d57b3d1 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -423,7 +423,7 @@ static void allocate_dc_stream_funcs(struct core_dc *core_dc) static void destruct(struct core_dc *dc) { - dc_resource_validate_ctx_destruct(dc->current_context); + dc_release_validate_context(dc->current_context); destroy_links(dc); @@ -467,6 +467,8 @@ static bool construct(struct core_dc *dc, goto val_ctx_fail; } + dc->current_context->ref_count++; + dc_ctx->cgs_device = init_params->cgs_device; dc_ctx->driver_context = init_params->driver; dc_ctx->dc = &dc->public; @@ -683,6 +685,8 @@ struct validate_context *dc_get_validate_context( if (context == NULL) goto context_alloc_fail; + ++context->ref_count; + if (!is_validation_required(core_dc, set, set_count)) { dc_resource_validate_ctx_copy_construct(core_dc->current_context, context); return context; @@ -698,8 +702,7 @@ context_alloc_fail: __func__, result); - dc_resource_validate_ctx_destruct(context); - dm_free(context); + dc_release_validate_context(context); context = NULL; } @@ -720,6 +723,8 @@ bool dc_validate_resources( if (context == NULL) goto context_alloc_fail; + ++context->ref_count; + result = core_dc->res_pool->funcs->validate_with_context( core_dc, set, set_count, context, NULL); @@ -731,8 +736,7 @@ context_alloc_fail: result); } - dc_resource_validate_ctx_destruct(context); - dm_free(context); + dc_release_validate_context(context); context = NULL; return result == DC_OK; @@ -750,11 +754,12 @@ bool dc_validate_guaranteed( if (context == NULL) goto context_alloc_fail; + ++context->ref_count; + result = core_dc->res_pool->funcs->validate_guaranteed( core_dc, stream, context); - dc_resource_validate_ctx_destruct(context); - dm_free(context); + dc_release_validate_context(context); context_alloc_fail: if (result != DC_OK) { @@ -972,8 +977,10 @@ static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *c dc_enable_stereo(dc, context, dc_streams, context->stream_count); - dc_resource_validate_ctx_destruct(core_dc->current_context); - dm_free(core_dc->current_context); + dc_release_validate_context(core_dc->current_context); + + dc_retain_validate_context(context); + core_dc->current_context = context; return (result == DC_OK); @@ -1045,6 +1052,8 @@ bool dc_commit_streams( if (context == NULL) goto context_alloc_fail; + ++context->ref_count; + result = core_dc->res_pool->funcs->validate_with_context( core_dc, set, stream_count, context, core_dc->current_context); if (result != DC_OK){ @@ -1053,7 +1062,6 @@ bool dc_commit_streams( __func__, result); BREAK_TO_DEBUGGER(); - dc_resource_validate_ctx_destruct(context); goto fail; } @@ -1062,7 +1070,7 @@ bool dc_commit_streams( return (result == DC_OK); fail: - dm_free(context); + dc_release_validate_context(context); context_alloc_fail: return (result == DC_OK); @@ -1155,6 +1163,23 @@ bool dc_commit_surfaces_to_stream( return true; } +void dc_retain_validate_context(struct validate_context *context) +{ + ASSERT(context->ref_count > 0); + ++context->ref_count; +} + +void dc_release_validate_context(struct validate_context *context) +{ + ASSERT(context->ref_count > 0); + --context->ref_count; + + if (context->ref_count == 0) { + dc_resource_validate_ctx_destruct(context); + dm_free(context); + } +} + static bool is_surface_in_context( const struct validate_context *context, const struct dc_surface *surface) @@ -1341,6 +1366,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, enum surface_update_type update_type; const struct dc_stream_status *stream_status; struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); + struct dc_context *dc_ctx = core_dc->ctx; stream_status = dc_stream_get_status(dc_stream); ASSERT(stream_status); @@ -1403,6 +1429,11 @@ void dc_update_surfaces_and_stream(struct dc *dc, /* initialize scratch memory for building context */ context = dm_alloc(sizeof(*context)); + if (context == NULL) + goto context_alloc_fail; + + ++context->ref_count; + dc_resource_validate_ctx_copy_construct( core_dc->current_context, context); @@ -1624,16 +1655,17 @@ void dc_update_surfaces_and_stream(struct dc *dc, } if (core_dc->current_context != context) { - dc_resource_validate_ctx_destruct(core_dc->current_context); - dm_free(core_dc->current_context); - + dc_release_validate_context(core_dc->current_context); + dc_retain_validate_context(context); core_dc->current_context = context; } return; fail: - dc_resource_validate_ctx_destruct(context); - dm_free(context); + dc_release_validate_context(context); + +context_alloc_fail: + DC_ERROR("Failed to allocate new validate context!\n"); } uint8_t dc_get_current_stream_count(const struct dc *dc) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 1fad03cdeb9d..cd8981469fe9 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -643,6 +643,10 @@ enum surface_update_type dc_check_update_surfaces_for_stream( struct dc_stream_update *stream_update, const struct dc_stream_status *stream_status); + +void dc_retain_validate_context(struct validate_context *context); +void dc_release_validate_context(struct validate_context *context); + /******************************************************************************* * Link Interfaces ******************************************************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 3e9a0ccca3b4..d216522a9989 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -361,6 +361,8 @@ struct validate_context { #ifdef CONFIG_DRM_AMD_DC_DCN1_0 struct dcn_bw_internal_vars dcn_bw_vars; #endif + + int ref_count; }; #endif /* _CORE_TYPES_H_ */ -- cgit From 3b42a1c09568ac6b65bfa40931600c5fe49d31e2 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Tue, 11 Jul 2017 13:45:57 -0400 Subject: drm/amd/display: Skip DC validation for flips and cursor. Nothing to validate in DC in this case. Skip it. Signed-off-by: Andrey Grodzovsky Reviewed-by: Roman Li Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 35 +++++++++++----------- 1 file changed, 18 insertions(+), 17 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index b56150a29502..248b397a6a7d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -1311,8 +1311,7 @@ int amdgpu_dm_connector_mode_valid( if (context) { result = MODE_OK; - dc_resource_validate_ctx_destruct(context); - dm_free(context); + dc_release_validate_context(context); } dc_stream_release(stream); @@ -2598,8 +2597,8 @@ void amdgpu_dm_atomic_commit_tail( } } - /* DC is optimized not to do anything if 'streams' didn't change. */ - WARN_ON(!dc_commit_context(dm->dc, dm_state->context)); + if (dm_state->context) + WARN_ON(!dc_commit_context(dm->dc, dm_state->context)); list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { @@ -2932,9 +2931,9 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, /* * This bool will be set for true for any modeset/reset - * or surface update which implies non fast surfae update. + * or surface update which implies non fast surface update. */ - bool aquire_global_lock = false; + bool lock_and_validation_needed = false; ret = drm_atomic_helper_check(dev, state); @@ -3022,7 +3021,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, new_acrtc_state->stream, crtc); - aquire_global_lock = true; + lock_and_validation_needed = true; } else if (modereset_required(crtc_state)) { @@ -3036,7 +3035,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, dc_stream_release(new_acrtc_state->stream); new_acrtc_state->stream = NULL; - aquire_global_lock = true; + lock_and_validation_needed = true; } } @@ -3074,7 +3073,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, if (!is_scaling_state_different(con_new_state, con_old_state)) continue; - aquire_global_lock = true; + lock_and_validation_needed = true; } for_each_crtc_in_state(state, crtc, crtc_state, i) { @@ -3124,17 +3123,11 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, new_acrtc_state->stream, surface); - aquire_global_lock = true; + lock_and_validation_needed = true; } } } - dm_state->context = dc_get_validate_context(dc, set, set_count); - if (!dm_state->context) { - ret = -EINVAL; - goto fail_planes; - } - /* * For full updates case when * removing/adding/updating streams on once CRTC while flipping @@ -3144,10 +3137,18 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, * will wait for completion of any outstanding flip using DRMs * synchronization events. */ - if (aquire_global_lock) { + + if (lock_and_validation_needed) { + ret = do_aquire_global_lock(dev, state); if (ret) goto fail_planes; + + dm_state->context = dc_get_validate_context(dc, set, set_count); + if (!dm_state->context) { + ret = -EINVAL; + goto fail_planes; + } } /* Must be success */ -- cgit From 0a323b84fab27fe51d35a4c55c73484c45c50f14 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Tue, 11 Jul 2017 14:42:57 -0400 Subject: drm/amd/display: Release dm_state->context when state is cleared. Handling a use case of TEST_ONLY request from DRM where commit is not goiing to be called. We need to release the allocated dc_validate_context in this case. Signed-off-by: Andrey Grodzovsky Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 23 ++++++++++++++++++++++ .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 1 + 2 files changed, 24 insertions(+) (limited to 'drivers/gpu') 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 63d23c6e7574..e16e87173db3 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -653,12 +653,35 @@ dm_atomic_state_alloc(struct drm_device *dev) return &state->base; } +static void +dm_atomic_state_clear(struct drm_atomic_state *state) +{ + struct dm_atomic_state *dm_state = to_dm_atomic_state(state); + + if (dm_state->context) { + dc_release_validate_context(dm_state->context); + dm_state->context = NULL; + } + + drm_atomic_state_default_clear(state); +} + +static void +dm_atomic_state_alloc_free(struct drm_atomic_state *state) +{ + struct dm_atomic_state *dm_state = to_dm_atomic_state(state); + drm_atomic_state_default_release(state); + kfree(dm_state); +} + static const struct drm_mode_config_funcs amdgpu_dm_mode_funcs = { .fb_create = amdgpu_user_framebuffer_create, .output_poll_changed = amdgpu_output_poll_changed, .atomic_check = amdgpu_dm_atomic_check, .atomic_commit = amdgpu_dm_atomic_commit, .atomic_state_alloc = dm_atomic_state_alloc, + .atomic_state_clear = dm_atomic_state_clear, + .atomic_state_free = dm_atomic_state_alloc_free }; static struct drm_mode_config_helper_funcs amdgpu_dm_mode_config_helperfuncs = { diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 248b397a6a7d..af4de578dadb 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -3144,6 +3144,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, if (ret) goto fail_planes; + WARN_ON(dm_state->context); dm_state->context = dc_get_validate_context(dc, set, set_count); if (!dm_state->context) { ret = -EINVAL; -- cgit From ef347b3b80c2f973140553db41224f886ef3b9da Mon Sep 17 00:00:00 2001 From: John Wu Date: Wed, 12 Jul 2017 14:25:52 +0800 Subject: drm/amd/display: Fix eDP power isn't off when lid close Signed-off-by: John Wu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 4f46ff14fb69..0092e70b9efd 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -112,8 +112,10 @@ void dp_disable_link_phy(struct core_link *link, enum signal_type signal) if (!link->wa_flags.dp_keep_receiver_powered) dp_receiver_power_ctrl(link, false); - if (signal == SIGNAL_TYPE_EDP) + if (signal == SIGNAL_TYPE_EDP) { link->link_enc->funcs->backlight_control(link->link_enc, false); + link->link_enc->funcs->power_control(link->link_enc, false); + } link->link_enc->funcs->disable_output(link->link_enc, signal); -- cgit From 189f73e32e9a7fc5ac62f244b66f8b41a78803c7 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Wed, 12 Jul 2017 09:02:54 -0400 Subject: drm/amd/display: change order of HUBP and MPC disable according to HW guide blank hubp first before disconnect MPC Signed-off-by: Tony Cheng Reviewed-by: Eric Yang Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 10 +++++++--- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c | 4 +++- 2 files changed, 10 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index ac0d62c10da2..0e90e6cc4930 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -477,9 +477,14 @@ static void reset_front_end( if (mpcc->opp_id == 0xf) return; - mi->funcs->dcc_control(mi, false, false); tg->funcs->lock(tg); + mi->funcs->dcc_control(mi, false, false); + mi->funcs->set_blank(mi, true); + REG_WAIT(DCHUBP_CNTL[fe_idx], + HUBP_NO_OUTSTANDING_REQ, 1, + 1, 200); + mpcc_cfg.opp_id = 0xf; mpcc_cfg.top_dpp_id = 0xf; mpcc_cfg.bot_mpcc_id = 0xf; @@ -491,8 +496,7 @@ static void reset_front_end( REG_WAIT(OTG_GLOBAL_SYNC_STATUS[tg->inst], VUPDATE_NO_LOCK_EVENT_OCCURRED, 1, 20000, 200000); mpcc->funcs->wait_for_idle(mpcc); - mi->funcs->set_blank(mi, true); - REG_WAIT(DCHUBP_CNTL[fe_idx], HUBP_NO_OUTSTANDING_REQ, 1, 20000, 200000); + REG_UPDATE(HUBP_CLK_CNTL[fe_idx], HUBP_CLOCK_ENABLE, 0); REG_UPDATE(DPP_CONTROL[fe_idx], DPP_CLOCK_ENABLE, 0); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c index 1c9d5e96ab55..9875d812e185 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c @@ -117,7 +117,9 @@ static void dcn10_mpcc_wait_idle(struct mpcc *mpcc) { struct dcn10_mpcc *mpcc10 = TO_DCN10_MPCC(mpcc); - REG_WAIT(MPCC_STATUS, MPCC_BUSY, 0, 1000, 1000); + REG_WAIT(MPCC_STATUS, + MPCC_BUSY, 0, + 1000, 1000); } -- cgit From 9a3afbb3ea37b9a6bc16b9d6e4a51b183724158d Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Tue, 11 Jul 2017 18:36:42 -0400 Subject: drm/amd/display: dc_validate_ctx refocunt fixes. In dc_resource_validate_ctx_copy_construct don't override dst context refcount. Remove extra retain to new ctx in dc_update_surfaces_and_stream Signed-off-by: Andrey Grodzovsky Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 5 +---- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 5 +++++ 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index e81c9d57b3d1..8e580ac91b2a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -424,6 +424,7 @@ static void allocate_dc_stream_funcs(struct core_dc *core_dc) static void destruct(struct core_dc *dc) { dc_release_validate_context(dc->current_context); + dc->current_context = NULL; destroy_links(dc); @@ -441,9 +442,6 @@ static void destruct(struct core_dc *dc) if (dc->ctx->logger) dal_logger_destroy(&dc->ctx->logger); - dm_free(dc->current_context); - dc->current_context = NULL; - dm_free(dc->ctx); dc->ctx = NULL; } @@ -1656,7 +1654,6 @@ void dc_update_surfaces_and_stream(struct dc *dc, if (core_dc->current_context != context) { dc_release_validate_context(core_dc->current_context); - dc_retain_validate_context(context); core_dc->current_context = context; } return; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 5a5ed37474bf..78ba5c6d9ac2 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -2166,6 +2166,7 @@ void dc_resource_validate_ctx_copy_construct( struct validate_context *dst_ctx) { int i, j; + int ref_count = dst_ctx->ref_count; *dst_ctx = *src_ctx; @@ -2186,6 +2187,10 @@ void dc_resource_validate_ctx_copy_construct( dc_surface_retain( dst_ctx->stream_status[i].surfaces[j]); } + + /* context refcount should not be overridden */ + dst_ctx->ref_count = ref_count; + } struct clock_source *dc_resource_find_first_free_pll( -- cgit From d21becbe0225de0e2582d17d4fbc73fbd103b1f7 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Wed, 12 Jul 2017 11:54:10 -0400 Subject: drm/amd/display: avoid disabling opp clk before hubp is blanked. Signed-off-by: Tony Cheng Reviewed-by: Eric Yang Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h | 7 +++++++ .../gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 18 ++++++++++++++---- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c | 2 -- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h | 8 ++------ 4 files changed, 23 insertions(+), 12 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index 6985a4607bd3..4da9142351fa 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -141,6 +141,10 @@ SRII(DPP_CONTROL, DPP_TOP, 1), \ SRII(DPP_CONTROL, DPP_TOP, 2), \ SRII(DPP_CONTROL, DPP_TOP, 3), \ + SRII(OPP_PIPE_CONTROL, OPP_PIPE, 0), \ + SRII(OPP_PIPE_CONTROL, OPP_PIPE, 1), \ + SRII(OPP_PIPE_CONTROL, OPP_PIPE, 2), \ + SRII(OPP_PIPE_CONTROL, OPP_PIPE, 3), \ SR(REFCLK_CNTL), \ SR(DCHUBBUB_GLOBAL_TIMER_CNTL), \ SR(DC_IP_REQUEST_CNTL), \ @@ -188,6 +192,7 @@ struct dce_hwseq_registers { uint32_t DCHUBP_CNTL[4]; uint32_t HUBP_CLK_CNTL[4]; uint32_t DPP_CONTROL[4]; + uint32_t OPP_PIPE_CONTROL[4]; uint32_t REFCLK_CNTL; uint32_t DCHUBBUB_GLOBAL_TIMER_CNTL; uint32_t DC_IP_REQUEST_CNTL; @@ -282,6 +287,7 @@ struct dce_hwseq_registers { HWS_SF(HUBP0_, DCHUBP_CNTL, HUBP_VTG_SEL, mask_sh), \ HWS_SF(HUBP0_, HUBP_CLK_CNTL, HUBP_CLOCK_ENABLE, mask_sh), \ HWS_SF(DPP_TOP0_, DPP_CONTROL, DPP_CLOCK_ENABLE, mask_sh), \ + HWS_SF(OPP_PIPE0_, OPP_PIPE_CONTROL, OPP_PIPE_CLOCK_EN, mask_sh),\ HWS_SF(, DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, mask_sh), \ HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh), \ HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN0_POWER_FORCEON, mask_sh), \ @@ -346,6 +352,7 @@ struct dce_hwseq_registers { type DPP_CLOCK_ENABLE; \ type DPPCLK_RATE_CONTROL; \ type DCHUBBUB_GLOBAL_TIMER_ENABLE; \ + type OPP_PIPE_CLOCK_EN;\ type IP_REQUEST_EN; \ type DOMAIN0_POWER_FORCEON; \ type DOMAIN0_POWER_GATE; \ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 0e90e6cc4930..18686be20004 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -472,9 +472,10 @@ static void reset_front_end( struct transform *xfm = dc->res_pool->transforms[fe_idx]; struct mpcc *mpcc = dc->res_pool->mpcc[fe_idx]; struct timing_generator *tg = dc->res_pool->timing_generators[mpcc->opp_id]; + unsigned int opp_id = mpcc->opp_id; /*Already reset*/ - if (mpcc->opp_id == 0xf) + if (opp_id == 0xf) return; tg->funcs->lock(tg); @@ -497,8 +498,12 @@ static void reset_front_end( mpcc->funcs->wait_for_idle(mpcc); - REG_UPDATE(HUBP_CLK_CNTL[fe_idx], HUBP_CLOCK_ENABLE, 0); - REG_UPDATE(DPP_CONTROL[fe_idx], DPP_CLOCK_ENABLE, 0); + REG_UPDATE(HUBP_CLK_CNTL[fe_idx], + HUBP_CLOCK_ENABLE, 0); + REG_UPDATE(DPP_CONTROL[fe_idx], + DPP_CLOCK_ENABLE, 0); + REG_UPDATE(OPP_PIPE_CONTROL[opp_id], + OPP_PIPE_CLOCK_EN, 0); xfm->funcs->transform_reset(xfm); @@ -1211,7 +1216,12 @@ static void dcn10_power_on_fe( pipe_ctx->pipe_idx); /* enable DCFCLK current DCHUB */ - REG_UPDATE(HUBP_CLK_CNTL[pipe_ctx->pipe_idx], HUBP_CLOCK_ENABLE, 1); + REG_UPDATE(HUBP_CLK_CNTL[pipe_ctx->pipe_idx], + HUBP_CLOCK_ENABLE, 1); + + /* make sure OPP_PIPE_CLOCK_EN = 1 */ + REG_UPDATE(OPP_PIPE_CONTROL[pipe_ctx->tg->inst], + OPP_PIPE_CLOCK_EN, 1); if (dc_surface) { dm_logger_write(dc->ctx->logger, LOG_DC, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c index 9875d812e185..de3341d572be 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c @@ -68,14 +68,12 @@ static void set_output_mux(struct dcn10_mpcc *mpcc10, int opp_id, int mpcc_id) { ASSERT(mpcc10->base.opp_id == 0xf || opp_id == mpcc10->base.opp_id); mpcc10->base.opp_id = opp_id; - REG_UPDATE(OPP_PIPE_CONTROL[opp_id], OPP_PIPE_CLOCK_EN, 1); REG_SET(MUX[opp_id], 0, MPC_OUT_MUX, mpcc_id); } static void reset_output_mux(struct dcn10_mpcc *mpcc10) { REG_SET(MUX[mpcc10->base.opp_id], 0, MPC_OUT_MUX, 0xf); - REG_UPDATE(OPP_PIPE_CONTROL[mpcc10->base.opp_id], OPP_PIPE_CLOCK_EN, 0); mpcc10->base.opp_id = 0xf; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h index 6a90a8bc09f8..2985c5d5a0e3 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h @@ -33,8 +33,7 @@ #define MAX_OPP 6 #define MPC_COMMON_REG_LIST_DCN1_0(inst) \ - SRII(MUX, MPC_OUT, inst),\ - SRII(OPP_PIPE_CONTROL, OPP_PIPE, inst) + SRII(MUX, MPC_OUT, inst) #define MPCC_COMMON_REG_LIST_DCN1_0(inst) \ SRI(MPCC_TOP_SEL, MPCC, inst),\ @@ -56,7 +55,6 @@ struct dcn_mpcc_registers { uint32_t MPCC_BG_G_Y; uint32_t MPCC_BG_R_CR; uint32_t MPCC_BG_B_CB; - uint32_t OPP_PIPE_CONTROL[MAX_OPP]; uint32_t MUX[MAX_OPP]; }; @@ -73,8 +71,7 @@ struct dcn_mpcc_registers { SF(MPCC0_MPCC_BG_G_Y, MPCC_BG_G_Y, mask_sh),\ SF(MPCC0_MPCC_BG_R_CR, MPCC_BG_R_CR, mask_sh),\ SF(MPCC0_MPCC_BG_B_CB, MPCC_BG_B_CB, mask_sh),\ - SF(MPC_OUT0_MUX, MPC_OUT_MUX, mask_sh),\ - SF(OPP_PIPE0_OPP_PIPE_CONTROL, OPP_PIPE_CLOCK_EN, mask_sh) + SF(MPC_OUT0_MUX, MPC_OUT_MUX, mask_sh) #define MPCC_REG_FIELD_LIST(type) \ type MPCC_TOP_SEL;\ @@ -90,7 +87,6 @@ struct dcn_mpcc_registers { type MPCC_BG_R_CR;\ type MPCC_BG_B_CB;\ type MPC_OUT_MUX;\ - type OPP_PIPE_CLOCK_EN;\ struct dcn_mpcc_shift { MPCC_REG_FIELD_LIST(uint8_t) -- cgit From 9294c7763fdc3da62dbf74a279921120c8f76721 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Wed, 12 Jul 2017 15:49:46 -0400 Subject: drm/amd/display: fix 4k@30 with 10bit deep color and avi for BT2020 Signed-off-by: Charlene Liu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 78ba5c6d9ac2..9d0128e95767 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1661,7 +1661,8 @@ static void set_avi_info_frame( /* C0, C1 : Colorimetry */ if (color_space == COLOR_SPACE_YCBCR709 || - color_space == COLOR_SPACE_YCBCR709_LIMITED) + color_space == COLOR_SPACE_YCBCR709_LIMITED || + color_space == COLOR_SPACE_2020_YCBCR) hdmi_info->bits.C0_C1 = COLORIMETRY_ITU709; else if (color_space == COLOR_SPACE_YCBCR601 || color_space == COLOR_SPACE_YCBCR601_LIMITED) -- cgit From 38917a1eb2748021fc0fd2ed4fd9b7f583713916 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Wed, 12 Jul 2017 09:00:14 -0400 Subject: drm/amd/display: ensure OTG is locked before proceeding also remove tg lock at init_hw as not all OTG is running Signed-off-by: Tony Cheng Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 2 -- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c | 4 ++++ drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h | 2 ++ 3 files changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 18686be20004..82a96de2843f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -283,13 +283,11 @@ static void init_hw(struct core_dc *dc) dc->res_pool->mpcc[i]; struct mpcc_cfg mpcc_cfg; - tg->funcs->lock(tg); mpcc_cfg.opp_id = 0xf; mpcc_cfg.top_dpp_id = 0xf; mpcc_cfg.bot_mpcc_id = 0xf; mpcc_cfg.top_of_tree = true; mpcc->funcs->set(mpcc, &mpcc_cfg); - tg->funcs->unlock(tg); tg->funcs->disable_vga(tg); /* Blank controller using driver code instead of diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c index e1899f5fb083..12d7f3570cfa 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c @@ -573,6 +573,10 @@ static void tgn10_lock(struct timing_generator *tg) OTG_MASTER_UPDATE_LOCK_SEL, tg->inst); REG_SET(OTG_MASTER_UPDATE_LOCK, 0, OTG_MASTER_UPDATE_LOCK, 1); + + REG_WAIT(OTG_MASTER_UPDATE_LOCK, + UPDATE_LOCK_STATUS, 1, + 1, 100); } static void tgn10_unlock(struct timing_generator *tg) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h index e287b2babdc4..747e8211e507 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h @@ -140,6 +140,7 @@ struct dcn_tg_registers { SF(OTG0_OTG_BLANK_CONTROL, OTG_BLANK_DE_MODE, mask_sh),\ SF(OTG0_OTG_BLANK_CONTROL, OTG_CURRENT_BLANK_STATE, mask_sh),\ SF(OTG0_OTG_MASTER_UPDATE_LOCK, OTG_MASTER_UPDATE_LOCK, mask_sh),\ + SF(OTG0_OTG_MASTER_UPDATE_LOCK, UPDATE_LOCK_STATUS, mask_sh),\ SF(OTG0_OTG_GLOBAL_CONTROL0, OTG_MASTER_UPDATE_LOCK_SEL, mask_sh),\ SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_UPDATE_PENDING, mask_sh),\ SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_BLANK_DATA_DOUBLE_BUFFER_EN, mask_sh),\ @@ -233,6 +234,7 @@ struct dcn_tg_registers { type OTG_BLANK_DE_MODE;\ type OTG_CURRENT_BLANK_STATE;\ type OTG_MASTER_UPDATE_LOCK;\ + type UPDATE_LOCK_STATUS;\ type OTG_UPDATE_PENDING;\ type OTG_MASTER_UPDATE_LOCK_SEL;\ type OTG_BLANK_DATA_DOUBLE_BUFFER_EN;\ -- cgit From 71a2f23e9101887de251ef1dcd35219d4e4f5e93 Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Wed, 12 Jul 2017 18:38:04 -0400 Subject: drm/amd/display: fix mpo exit hang Signed-off-by: Eric Yang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 82a96de2843f..dbf9cea2e418 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -500,8 +500,10 @@ static void reset_front_end( HUBP_CLOCK_ENABLE, 0); REG_UPDATE(DPP_CONTROL[fe_idx], DPP_CLOCK_ENABLE, 0); - REG_UPDATE(OPP_PIPE_CONTROL[opp_id], - OPP_PIPE_CLOCK_EN, 0); + + if (mpcc_cfg.top_of_tree) + REG_UPDATE(OPP_PIPE_CONTROL[opp_id], + OPP_PIPE_CLOCK_EN, 0); xfm->funcs->transform_reset(xfm); @@ -1584,7 +1586,7 @@ static void dcn10_apply_ctx_for_surface( int i; /* reset unused mpcc */ - /*for (i = 0; i < dc->res_pool->pipe_count; i++) { + for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; struct pipe_ctx *old_pipe_ctx = &dc->current_context->res_ctx.pipe_ctx[i]; @@ -1593,7 +1595,12 @@ static void dcn10_apply_ctx_for_surface( || (!pipe_ctx->stream && old_pipe_ctx->stream)) { struct mpcc_cfg mpcc_cfg; - mpcc_cfg.opp_id = 0xf; + if (!old_pipe_ctx->top_pipe) { + ASSERT(0); + continue; + } + + mpcc_cfg.opp_id = old_pipe_ctx->mpcc->opp_id; mpcc_cfg.top_dpp_id = 0xf; mpcc_cfg.bot_mpcc_id = 0xf; mpcc_cfg.top_of_tree = !old_pipe_ctx->top_pipe; @@ -1607,7 +1614,7 @@ static void dcn10_apply_ctx_for_surface( "Reset mpcc for pipe %d\n", old_pipe_ctx->pipe_idx); } - }*/ + } if (!surface) return; -- cgit From 587cdfe9463e6b66186c3c70fe7e63790cf4d148 Mon Sep 17 00:00:00 2001 From: Vitaly Prosyak Date: Wed, 5 Jul 2017 17:03:04 -0500 Subject: drm/amd/display: Rename trasnform to dpp for dcn's Signed-off-by: Vitaly Prosyak Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/Makefile | 2 +- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c | 1064 +++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h | 419 ++++++++ .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 2 + .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 38 +- .../gpu/drm/amd/display/dc/dcn10/dcn10_transform.c | 1065 -------------------- .../gpu/drm/amd/display/dc/dcn10/dcn10_transform.h | 421 -------- 7 files changed, 1505 insertions(+), 1506 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile index 2c43ad7a6f3f..9ba1bfc30146 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile @@ -2,7 +2,7 @@ # Makefile for DCN. DCN10 = dcn10_resource.o dcn10_ipp.o dcn10_hw_sequencer.o \ - dcn10_transform.o dcn10_opp.o dcn10_timing_generator.o \ + dcn10_dpp.o dcn10_opp.o dcn10_timing_generator.o \ dcn10_mem_input.o dcn10_mpc.o AMD_DAL_DCN10 = $(addprefix $(AMDDALPATH)/dc/dcn10/,$(DCN10)) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c new file mode 100644 index 000000000000..85d3ca31daf5 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c @@ -0,0 +1,1064 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "core_types.h" + +#include "include/grph_object_id.h" +#include "include/fixed31_32.h" +#include "include/logger_interface.h" + +#include "reg_helper.h" +#include "dcn10_dpp.h" +#include "basics/conversion.h" + +#define NUM_PHASES 64 +#define HORZ_MAX_TAPS 8 +#define VERT_MAX_TAPS 8 + +#define BLACK_OFFSET_RGB_Y 0x0 +#define BLACK_OFFSET_CBCR 0x8000 + +#define REG(reg)\ + xfm->tf_regs->reg + +#define CTX \ + xfm->base.ctx + +#undef FN +#define FN(reg_name, field_name) \ + xfm->tf_shift->field_name, xfm->tf_mask->field_name + + +enum dcn10_coef_filter_type_sel { + SCL_COEF_LUMA_VERT_FILTER = 0, + SCL_COEF_LUMA_HORZ_FILTER = 1, + SCL_COEF_CHROMA_VERT_FILTER = 2, + SCL_COEF_CHROMA_HORZ_FILTER = 3, + SCL_COEF_ALPHA_VERT_FILTER = 4, + SCL_COEF_ALPHA_HORZ_FILTER = 5 +}; + +enum lb_memory_config { + /* Enable all 3 pieces of memory */ + LB_MEMORY_CONFIG_0 = 0, + + /* Enable only the first piece of memory */ + LB_MEMORY_CONFIG_1 = 1, + + /* Enable only the second piece of memory */ + LB_MEMORY_CONFIG_2 = 2, + + /* Only applicable in 4:2:0 mode, enable all 3 pieces of memory and the + * last piece of chroma memory used for the luma storage + */ + LB_MEMORY_CONFIG_3 = 3 +}; + +enum dscl_autocal_mode { + AUTOCAL_MODE_OFF = 0, + + /* Autocal calculate the scaling ratio and initial phase and the + * DSCL_MODE_SEL must be set to 1 + */ + AUTOCAL_MODE_AUTOSCALE = 1, + /* Autocal perform auto centering without replication and the + * DSCL_MODE_SEL must be set to 0 + */ + AUTOCAL_MODE_AUTOCENTER = 2, + /* Autocal perform auto centering and auto replication and the + * DSCL_MODE_SEL must be set to 0 + */ + AUTOCAL_MODE_AUTOREPLICATE = 3 +}; + +enum dscl_mode_sel { + DSCL_MODE_SCALING_444_BYPASS = 0, + DSCL_MODE_SCALING_444_RGB_ENABLE = 1, + DSCL_MODE_SCALING_444_YCBCR_ENABLE = 2, + DSCL_MODE_SCALING_420_YCBCR_ENABLE = 3, + DSCL_MODE_SCALING_420_LUMA_BYPASS = 4, + DSCL_MODE_SCALING_420_CHROMA_BYPASS = 5, + DSCL_MODE_DSCL_BYPASS = 6 +}; + +enum gamut_remap_select { + GAMUT_REMAP_BYPASS = 0, + GAMUT_REMAP_COEFF, + GAMUT_REMAP_COMA_COEFF, + GAMUT_REMAP_COMB_COEFF +}; + +static void dpp_set_overscan( + struct dcn10_dpp *xfm, + const struct scaler_data *data) +{ + uint32_t left = data->recout.x; + uint32_t top = data->recout.y; + + int right = data->h_active - data->recout.x - data->recout.width; + int bottom = data->v_active - data->recout.y - data->recout.height; + + if (right < 0) { + BREAK_TO_DEBUGGER(); + right = 0; + } + if (bottom < 0) { + BREAK_TO_DEBUGGER(); + bottom = 0; + } + + REG_SET_2(DSCL_EXT_OVERSCAN_LEFT_RIGHT, 0, + EXT_OVERSCAN_LEFT, left, + EXT_OVERSCAN_RIGHT, right); + + REG_SET_2(DSCL_EXT_OVERSCAN_TOP_BOTTOM, 0, + EXT_OVERSCAN_BOTTOM, bottom, + EXT_OVERSCAN_TOP, top); +} + +static void dpp_set_otg_blank( + struct dcn10_dpp *xfm, const struct scaler_data *data) +{ + uint32_t h_blank_start = data->h_active; + uint32_t h_blank_end = 0; + uint32_t v_blank_start = data->v_active; + uint32_t v_blank_end = 0; + + REG_SET_2(OTG_H_BLANK, 0, + OTG_H_BLANK_START, h_blank_start, + OTG_H_BLANK_END, h_blank_end); + + REG_SET_2(OTG_V_BLANK, 0, + OTG_V_BLANK_START, v_blank_start, + OTG_V_BLANK_END, v_blank_end); +} + +static enum dscl_mode_sel get_dscl_mode( + const struct scaler_data *data, bool dbg_always_scale) +{ + const long long one = dal_fixed31_32_one.value; + bool ycbcr = false; + bool format420 = false; + + if (data->format == PIXEL_FORMAT_FP16) + return DSCL_MODE_DSCL_BYPASS; + + if (data->format >= PIXEL_FORMAT_VIDEO_BEGIN + && data->format <= PIXEL_FORMAT_VIDEO_END) + ycbcr = true; + + if (data->format == PIXEL_FORMAT_420BPP8 || + data->format == PIXEL_FORMAT_420BPP10) + format420 = true; + + if (data->ratios.horz.value == one + && data->ratios.vert.value == one + && data->ratios.horz_c.value == one + && data->ratios.vert_c.value == one + && !dbg_always_scale) + return DSCL_MODE_SCALING_444_BYPASS; + + if (!format420) { + if (ycbcr) + return DSCL_MODE_SCALING_444_YCBCR_ENABLE; + else + return DSCL_MODE_SCALING_444_RGB_ENABLE; + } + if (data->ratios.horz.value == one && data->ratios.vert.value == one) + return DSCL_MODE_SCALING_420_LUMA_BYPASS; + if (data->ratios.horz_c.value == one && data->ratios.vert_c.value == one) + return DSCL_MODE_SCALING_420_CHROMA_BYPASS; + + return DSCL_MODE_SCALING_420_YCBCR_ENABLE; +} + +static int get_pixel_depth_val(enum lb_pixel_depth depth) +{ + if (depth == LB_PIXEL_DEPTH_30BPP) + return 0; /* 10 bpc */ + else if (depth == LB_PIXEL_DEPTH_24BPP) + return 1; /* 8 bpc */ + else if (depth == LB_PIXEL_DEPTH_18BPP) + return 2; /* 6 bpc */ + else if (depth == LB_PIXEL_DEPTH_36BPP) + return 3; /* 12 bpc */ + else { + ASSERT(0); + return -1; /* Unsupported */ + } +} + +static void dpp_set_lb( + struct dcn10_dpp *xfm, + const struct line_buffer_params *lb_params, + enum lb_memory_config mem_size_config) +{ + uint32_t pixel_depth = get_pixel_depth_val(lb_params->depth); + uint32_t dyn_pix_depth = lb_params->dynamic_pixel_depth; + REG_SET_7(LB_DATA_FORMAT, 0, + PIXEL_DEPTH, pixel_depth, /* Pixel depth stored in LB */ + PIXEL_EXPAN_MODE, lb_params->pixel_expan_mode, /* Pixel expansion mode */ + PIXEL_REDUCE_MODE, 1, /* Pixel reduction mode: Rounding */ + DYNAMIC_PIXEL_DEPTH, dyn_pix_depth, /* Dynamic expansion pixel depth */ + DITHER_EN, 0, /* Dithering enable: Disabled */ + INTERLEAVE_EN, lb_params->interleave_en, /* Interleave source enable */ + ALPHA_EN, lb_params->alpha_en); /* Alpha enable */ + + REG_SET_2(LB_MEMORY_CTRL, 0, + MEMORY_CONFIG, mem_size_config, + LB_MAX_PARTITIONS, 63); +} + +static void dpp_set_scaler_filter( + struct dcn10_dpp *xfm, + uint32_t taps, + enum dcn10_coef_filter_type_sel filter_type, + const uint16_t *filter) +{ + const int tap_pairs = (taps + 1) / 2; + int phase; + int pair; + uint16_t odd_coef, even_coef; + + REG_SET_3(SCL_COEF_RAM_TAP_SELECT, 0, + SCL_COEF_RAM_TAP_PAIR_IDX, 0, + SCL_COEF_RAM_PHASE, 0, + SCL_COEF_RAM_FILTER_TYPE, filter_type); + + for (phase = 0; phase < (NUM_PHASES / 2 + 1); phase++) { + for (pair = 0; pair < tap_pairs; pair++) { + even_coef = filter[phase * taps + 2 * pair]; + if ((pair * 2 + 1) < taps) + odd_coef = filter[phase * taps + 2 * pair + 1]; + else + odd_coef = 0; + + REG_SET_4(SCL_COEF_RAM_TAP_DATA, 0, + /* Even tap coefficient (bits 1:0 fixed to 0) */ + SCL_COEF_RAM_EVEN_TAP_COEF, even_coef, + /* Write/read control for even coefficient */ + SCL_COEF_RAM_EVEN_TAP_COEF_EN, 1, + /* Odd tap coefficient (bits 1:0 fixed to 0) */ + SCL_COEF_RAM_ODD_TAP_COEF, odd_coef, + /* Write/read control for odd coefficient */ + SCL_COEF_RAM_ODD_TAP_COEF_EN, 1); + } + } + +} + +#if 0 +bool dpp_set_pixel_storage_depth( + struct dpp *xfm, + enum lb_pixel_depth depth, + const struct bit_depth_reduction_params *bit_depth_params) +{ + struct dcn10_dpp *xfm110 = TO_DCN10_DPP(xfm); + bool ret = true; + uint32_t value; + enum dc_color_depth color_depth; + + value = dm_read_reg(xfm->ctx, LB_REG(mmLB_DATA_FORMAT)); + switch (depth) { + case LB_PIXEL_DEPTH_18BPP: + color_depth = COLOR_DEPTH_666; + set_reg_field_value(value, 2, LB_DATA_FORMAT, PIXEL_DEPTH); + set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_EXPAN_MODE); + break; + case LB_PIXEL_DEPTH_24BPP: + color_depth = COLOR_DEPTH_888; + set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_DEPTH); + set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_EXPAN_MODE); + break; + case LB_PIXEL_DEPTH_30BPP: + color_depth = COLOR_DEPTH_101010; + set_reg_field_value(value, 0, LB_DATA_FORMAT, PIXEL_DEPTH); + set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_EXPAN_MODE); + break; + case LB_PIXEL_DEPTH_36BPP: + color_depth = COLOR_DEPTH_121212; + set_reg_field_value(value, 3, LB_DATA_FORMAT, PIXEL_DEPTH); + set_reg_field_value(value, 0, LB_DATA_FORMAT, PIXEL_EXPAN_MODE); + break; + default: + ret = false; + break; + } + + if (ret == true) { + set_denormalization(xfm110, color_depth); + ret = program_bit_depth_reduction(xfm110, color_depth, + bit_depth_params); + + set_reg_field_value(value, 0, LB_DATA_FORMAT, ALPHA_EN); + dm_write_reg(xfm->ctx, LB_REG(mmLB_DATA_FORMAT), value); + if (!(xfm110->lb_pixel_depth_supported & depth)) { + /* We should use unsupported capabilities + * unless it is required by w/a + */ + dm_logger_write(xfm->ctx->logger, LOG_WARNING, + "%s: Capability not supported", + __func__); + } + } + + return ret; +} +#endif + +static const uint16_t *get_filter_coeffs_64p(int taps, struct fixed31_32 ratio) +{ + if (taps == 8) + return get_filter_8tap_64p(ratio); + else if (taps == 7) + return get_filter_7tap_64p(ratio); + else if (taps == 6) + return get_filter_6tap_64p(ratio); + else if (taps == 5) + return get_filter_5tap_64p(ratio); + else if (taps == 4) + return get_filter_4tap_64p(ratio); + else if (taps == 3) + return get_filter_3tap_64p(ratio); + else if (taps == 2) + return filter_2tap_64p; + else if (taps == 1) + return NULL; + else { + /* should never happen, bug */ + BREAK_TO_DEBUGGER(); + return NULL; + } +} + +static void dpp_set_scl_filter( + struct dcn10_dpp *xfm, + const struct scaler_data *scl_data, + bool chroma_coef_mode) +{ + bool h_2tap_hardcode_coef_en = false; + bool v_2tap_hardcode_coef_en = false; + bool h_2tap_sharp_en = false; + bool v_2tap_sharp_en = false; + uint32_t h_2tap_sharp_factor = scl_data->sharpness.horz; + uint32_t v_2tap_sharp_factor = scl_data->sharpness.vert; + bool coef_ram_current; + const uint16_t *filter_h = NULL; + const uint16_t *filter_v = NULL; + const uint16_t *filter_h_c = NULL; + const uint16_t *filter_v_c = NULL; + + h_2tap_hardcode_coef_en = scl_data->taps.h_taps < 3 + && scl_data->taps.h_taps_c < 3 + && (scl_data->taps.h_taps > 1 || scl_data->taps.h_taps_c > 1); + v_2tap_hardcode_coef_en = scl_data->taps.v_taps < 3 + && scl_data->taps.v_taps_c < 3 + && (scl_data->taps.v_taps > 1 || scl_data->taps.v_taps_c > 1); + + h_2tap_sharp_en = h_2tap_hardcode_coef_en && h_2tap_sharp_factor != 0; + v_2tap_sharp_en = v_2tap_hardcode_coef_en && v_2tap_sharp_factor != 0; + + REG_UPDATE_6(DSCL_2TAP_CONTROL, + SCL_H_2TAP_HARDCODE_COEF_EN, h_2tap_hardcode_coef_en, + SCL_H_2TAP_SHARP_EN, h_2tap_sharp_en, + SCL_H_2TAP_SHARP_FACTOR, h_2tap_sharp_factor, + SCL_V_2TAP_HARDCODE_COEF_EN, v_2tap_hardcode_coef_en, + SCL_V_2TAP_SHARP_EN, v_2tap_sharp_en, + SCL_V_2TAP_SHARP_FACTOR, v_2tap_sharp_factor); + + if (!v_2tap_hardcode_coef_en || !h_2tap_hardcode_coef_en) { + bool filter_updated = false; + + filter_h = get_filter_coeffs_64p( + scl_data->taps.h_taps, scl_data->ratios.horz); + filter_v = get_filter_coeffs_64p( + scl_data->taps.v_taps, scl_data->ratios.vert); + + filter_updated = (filter_h && (filter_h != xfm->filter_h)) + || (filter_v && (filter_v != xfm->filter_v)); + + if (chroma_coef_mode) { + filter_h_c = get_filter_coeffs_64p( + scl_data->taps.h_taps_c, scl_data->ratios.horz_c); + filter_v_c = get_filter_coeffs_64p( + scl_data->taps.v_taps_c, scl_data->ratios.vert_c); + filter_updated = filter_updated || (filter_h_c && (filter_h_c != xfm->filter_h_c)) + || (filter_v_c && (filter_v_c != xfm->filter_v_c)); + } + + if (filter_updated) { + uint32_t scl_mode = REG_READ(SCL_MODE); + + if (!h_2tap_hardcode_coef_en && filter_h) { + dpp_set_scaler_filter( + xfm, scl_data->taps.h_taps, + SCL_COEF_LUMA_HORZ_FILTER, filter_h); + } + xfm->filter_h = filter_h; + if (!v_2tap_hardcode_coef_en && filter_v) { + dpp_set_scaler_filter( + xfm, scl_data->taps.v_taps, + SCL_COEF_LUMA_VERT_FILTER, filter_v); + } + xfm->filter_v = filter_v; + if (chroma_coef_mode) { + if (!h_2tap_hardcode_coef_en && filter_h_c) { + dpp_set_scaler_filter( + xfm, scl_data->taps.h_taps_c, + SCL_COEF_CHROMA_HORZ_FILTER, filter_h_c); + } + if (!v_2tap_hardcode_coef_en && filter_v_c) { + dpp_set_scaler_filter( + xfm, scl_data->taps.v_taps_c, + SCL_COEF_CHROMA_VERT_FILTER, filter_v_c); + } + } + xfm->filter_h_c = filter_h_c; + xfm->filter_v_c = filter_v_c; + + coef_ram_current = get_reg_field_value_ex( + scl_mode, xfm->tf_mask->SCL_COEF_RAM_SELECT_CURRENT, + xfm->tf_shift->SCL_COEF_RAM_SELECT_CURRENT); + + /* Swap coefficient RAM and set chroma coefficient mode */ + REG_SET_2(SCL_MODE, scl_mode, + SCL_COEF_RAM_SELECT, !coef_ram_current, + SCL_CHROMA_COEF_MODE, chroma_coef_mode); + } + } +} + +static void dpp_set_viewport( + struct dcn10_dpp *xfm, + const struct rect *viewport, + const struct rect *viewport_c) +{ + REG_SET_2(DCSURF_PRI_VIEWPORT_DIMENSION, 0, + PRI_VIEWPORT_WIDTH, viewport->width, + PRI_VIEWPORT_HEIGHT, viewport->height); + + REG_SET_2(DCSURF_PRI_VIEWPORT_START, 0, + PRI_VIEWPORT_X_START, viewport->x, + PRI_VIEWPORT_Y_START, viewport->y); + + /*for stereo*/ + REG_SET_2(DCSURF_SEC_VIEWPORT_DIMENSION, 0, + SEC_VIEWPORT_WIDTH, viewport->width, + SEC_VIEWPORT_HEIGHT, viewport->height); + + REG_SET_2(DCSURF_SEC_VIEWPORT_START, 0, + SEC_VIEWPORT_X_START, viewport->x, + SEC_VIEWPORT_Y_START, viewport->y); + + /* DC supports NV12 only at the moment */ + REG_SET_2(DCSURF_PRI_VIEWPORT_DIMENSION_C, 0, + PRI_VIEWPORT_WIDTH_C, viewport_c->width, + PRI_VIEWPORT_HEIGHT_C, viewport_c->height); + + REG_SET_2(DCSURF_PRI_VIEWPORT_START_C, 0, + PRI_VIEWPORT_X_START_C, viewport_c->x, + PRI_VIEWPORT_Y_START_C, viewport_c->y); +} + +static int get_lb_depth_bpc(enum lb_pixel_depth depth) +{ + if (depth == LB_PIXEL_DEPTH_30BPP) + return 10; + else if (depth == LB_PIXEL_DEPTH_24BPP) + return 8; + else if (depth == LB_PIXEL_DEPTH_18BPP) + return 6; + else if (depth == LB_PIXEL_DEPTH_36BPP) + return 12; + else { + BREAK_TO_DEBUGGER(); + return -1; /* Unsupported */ + } +} + +static void calc_lb_num_partitions( + const struct scaler_data *scl_data, + enum lb_memory_config lb_config, + int *num_part_y, + int *num_part_c) +{ + int line_size = scl_data->viewport.width < scl_data->recout.width ? + scl_data->viewport.width : scl_data->recout.width; + int line_size_c = scl_data->viewport_c.width < scl_data->recout.width ? + scl_data->viewport_c.width : scl_data->recout.width; + int lb_bpc = get_lb_depth_bpc(scl_data->lb_params.depth); + int memory_line_size_y = (line_size * lb_bpc + 71) / 72; /* +71 to ceil */ + int memory_line_size_c = (line_size_c * lb_bpc + 71) / 72; /* +71 to ceil */ + int memory_line_size_a = (line_size + 5) / 6; /* +5 to ceil */ + int lb_memory_size, lb_memory_size_c, lb_memory_size_a, num_partitions_a; + + if (lb_config == LB_MEMORY_CONFIG_1) { + lb_memory_size = 816; + lb_memory_size_c = 816; + lb_memory_size_a = 984; + } else if (lb_config == LB_MEMORY_CONFIG_2) { + lb_memory_size = 1088; + lb_memory_size_c = 1088; + lb_memory_size_a = 1312; + } else if (lb_config == LB_MEMORY_CONFIG_3) { + lb_memory_size = 816 + 1088 + 848 + 848 + 848; + lb_memory_size_c = 816 + 1088; + lb_memory_size_a = 984 + 1312 + 456; + } else { + lb_memory_size = 816 + 1088 + 848; + lb_memory_size_c = 816 + 1088 + 848; + lb_memory_size_a = 984 + 1312 + 456; + } + *num_part_y = lb_memory_size / memory_line_size_y; + *num_part_c = lb_memory_size_c / memory_line_size_c; + num_partitions_a = lb_memory_size_a / memory_line_size_a; + + if (scl_data->lb_params.alpha_en + && (num_partitions_a < *num_part_y)) + *num_part_y = num_partitions_a; + + if (*num_part_y > 64) + *num_part_y = 64; + if (*num_part_c > 64) + *num_part_c = 64; + +} + +static bool is_lb_conf_valid(int ceil_vratio, int num_partitions, int vtaps) +{ + if (ceil_vratio > 2) + return vtaps <= (num_partitions - ceil_vratio + 2); + else + return vtaps <= num_partitions; +} + +/*find first match configuration which meets the min required lb size*/ +static enum lb_memory_config find_lb_memory_config(const struct scaler_data *scl_data) +{ + int num_part_y, num_part_c; + int vtaps = scl_data->taps.v_taps; + int vtaps_c = scl_data->taps.v_taps_c; + int ceil_vratio = dal_fixed31_32_ceil(scl_data->ratios.vert); + int ceil_vratio_c = dal_fixed31_32_ceil(scl_data->ratios.vert_c); + + calc_lb_num_partitions( + scl_data, LB_MEMORY_CONFIG_1, &num_part_y, &num_part_c); + + if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) + && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)) + return LB_MEMORY_CONFIG_1; + + calc_lb_num_partitions( + scl_data, LB_MEMORY_CONFIG_2, &num_part_y, &num_part_c); + + if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) + && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)) + return LB_MEMORY_CONFIG_2; + + if (scl_data->format == PIXEL_FORMAT_420BPP8 + || scl_data->format == PIXEL_FORMAT_420BPP10) { + calc_lb_num_partitions( + scl_data, LB_MEMORY_CONFIG_3, &num_part_y, &num_part_c); + + if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) + && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)) + return LB_MEMORY_CONFIG_3; + } + + calc_lb_num_partitions( + scl_data, LB_MEMORY_CONFIG_0, &num_part_y, &num_part_c); + + /*Ensure we can support the requested number of vtaps*/ + ASSERT(is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) + && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)); + + return LB_MEMORY_CONFIG_0; +} + +void dpp_set_scaler_auto_scale( + struct transform *xfm_base, + const struct scaler_data *scl_data) +{ + enum lb_memory_config lb_config; + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + enum dscl_mode_sel dscl_mode = get_dscl_mode( + scl_data, xfm_base->ctx->dc->debug.always_scale); + bool ycbcr = scl_data->format >= PIXEL_FORMAT_VIDEO_BEGIN + && scl_data->format <= PIXEL_FORMAT_VIDEO_END; + + dpp_set_overscan(xfm, scl_data); + + dpp_set_otg_blank(xfm, scl_data); + + REG_UPDATE(SCL_MODE, DSCL_MODE, dscl_mode); + + dpp_set_viewport(xfm, &scl_data->viewport, &scl_data->viewport_c); + + if (dscl_mode == DSCL_MODE_DSCL_BYPASS) + return; + + lb_config = find_lb_memory_config(scl_data); + dpp_set_lb(xfm, &scl_data->lb_params, lb_config); + + if (dscl_mode == DSCL_MODE_SCALING_444_BYPASS) + return; + + /* TODO: v_min */ + REG_SET_3(DSCL_AUTOCAL, 0, + AUTOCAL_MODE, AUTOCAL_MODE_AUTOSCALE, + AUTOCAL_NUM_PIPE, 0, + AUTOCAL_PIPE_ID, 0); + + /* Black offsets */ + if (ycbcr) + REG_SET_2(SCL_BLACK_OFFSET, 0, + SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y, + SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_CBCR); + else + + REG_SET_2(SCL_BLACK_OFFSET, 0, + SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y, + SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_RGB_Y); + + REG_SET_4(SCL_TAP_CONTROL, 0, + SCL_V_NUM_TAPS, scl_data->taps.v_taps - 1, + SCL_H_NUM_TAPS, scl_data->taps.h_taps - 1, + SCL_V_NUM_TAPS_C, scl_data->taps.v_taps_c - 1, + SCL_H_NUM_TAPS_C, scl_data->taps.h_taps_c - 1); + + dpp_set_scl_filter(xfm, scl_data, ycbcr); +} + +/* Program gamut remap in bypass mode */ +void dpp_set_gamut_remap_bypass(struct dcn10_dpp *xfm) +{ + REG_SET(CM_GAMUT_REMAP_CONTROL, 0, + CM_GAMUT_REMAP_MODE, 0); + /* Gamut remap in bypass */ +} + +static void dpp_set_recout( + struct dcn10_dpp *xfm, const struct rect *recout) +{ + REG_SET_2(RECOUT_START, 0, + /* First pixel of RECOUT */ + RECOUT_START_X, recout->x, + /* First line of RECOUT */ + RECOUT_START_Y, recout->y); + + REG_SET_2(RECOUT_SIZE, 0, + /* Number of RECOUT horizontal pixels */ + RECOUT_WIDTH, recout->width, + /* Number of RECOUT vertical lines */ + RECOUT_HEIGHT, recout->height + - xfm->base.ctx->dc->debug.surface_visual_confirm * 4 * + (xfm->base.inst + 1)); +} + +static void dpp_set_manual_ratio_init( + struct dcn10_dpp *xfm, const struct scaler_data *data) +{ + uint32_t init_frac = 0; + uint32_t init_int = 0; + + REG_SET(SCL_HORZ_FILTER_SCALE_RATIO, 0, + SCL_H_SCALE_RATIO, dal_fixed31_32_u2d19(data->ratios.horz) << 5); + + REG_SET(SCL_VERT_FILTER_SCALE_RATIO, 0, + SCL_V_SCALE_RATIO, dal_fixed31_32_u2d19(data->ratios.vert) << 5); + + REG_SET(SCL_HORZ_FILTER_SCALE_RATIO_C, 0, + SCL_H_SCALE_RATIO_C, dal_fixed31_32_u2d19(data->ratios.horz_c) << 5); + + REG_SET(SCL_VERT_FILTER_SCALE_RATIO_C, 0, + SCL_V_SCALE_RATIO_C, dal_fixed31_32_u2d19(data->ratios.vert_c) << 5); + + /* + * 0.24 format for fraction, first five bits zeroed + */ + init_frac = dal_fixed31_32_u0d19(data->inits.h) << 5; + init_int = dal_fixed31_32_floor(data->inits.h); + REG_SET_2(SCL_HORZ_FILTER_INIT, 0, + SCL_H_INIT_FRAC, init_frac, + SCL_H_INIT_INT, init_int); + + init_frac = dal_fixed31_32_u0d19(data->inits.h_c) << 5; + init_int = dal_fixed31_32_floor(data->inits.h_c); + REG_SET_2(SCL_HORZ_FILTER_INIT_C, 0, + SCL_H_INIT_FRAC_C, init_frac, + SCL_H_INIT_INT_C, init_int); + + init_frac = dal_fixed31_32_u0d19(data->inits.v) << 5; + init_int = dal_fixed31_32_floor(data->inits.v); + REG_SET_2(SCL_VERT_FILTER_INIT, 0, + SCL_V_INIT_FRAC, init_frac, + SCL_V_INIT_INT, init_int); + + init_frac = dal_fixed31_32_u0d19(data->inits.v_bot) << 5; + init_int = dal_fixed31_32_floor(data->inits.v_bot); + REG_SET_2(SCL_VERT_FILTER_INIT_BOT, 0, + SCL_V_INIT_FRAC_BOT, init_frac, + SCL_V_INIT_INT_BOT, init_int); + + init_frac = dal_fixed31_32_u0d19(data->inits.v_c) << 5; + init_int = dal_fixed31_32_floor(data->inits.v_c); + REG_SET_2(SCL_VERT_FILTER_INIT_C, 0, + SCL_V_INIT_FRAC_C, init_frac, + SCL_V_INIT_INT_C, init_int); + + init_frac = dal_fixed31_32_u0d19(data->inits.v_c_bot) << 5; + init_int = dal_fixed31_32_floor(data->inits.v_c_bot); + REG_SET_2(SCL_VERT_FILTER_INIT_BOT_C, 0, + SCL_V_INIT_FRAC_BOT_C, init_frac, + SCL_V_INIT_INT_BOT_C, init_int); +} + +/* Main function to program scaler and line buffer in manual scaling mode */ +static void dpp_set_scaler_manual_scale( + struct transform *xfm_base, + const struct scaler_data *scl_data) +{ + enum lb_memory_config lb_config; + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + enum dscl_mode_sel dscl_mode = get_dscl_mode( + scl_data, xfm_base->ctx->dc->debug.always_scale); + bool ycbcr = scl_data->format >= PIXEL_FORMAT_VIDEO_BEGIN + && scl_data->format <= PIXEL_FORMAT_VIDEO_END; + + /* Recout */ + dpp_set_recout(xfm, &scl_data->recout); + + /* MPC Size */ + REG_SET_2(MPC_SIZE, 0, + /* Number of horizontal pixels of MPC */ + MPC_WIDTH, scl_data->h_active, + /* Number of vertical lines of MPC */ + MPC_HEIGHT, scl_data->v_active); + + /* SCL mode */ + REG_UPDATE(SCL_MODE, DSCL_MODE, dscl_mode); + + /* Viewport */ + dpp_set_viewport(xfm, &scl_data->viewport, &scl_data->viewport_c); + + if (dscl_mode == DSCL_MODE_DSCL_BYPASS) + return; + /* LB */ + lb_config = find_lb_memory_config(scl_data); + dpp_set_lb(xfm, &scl_data->lb_params, lb_config); + + if (dscl_mode == DSCL_MODE_SCALING_444_BYPASS) + return; + + /* Autocal off */ + REG_SET_3(DSCL_AUTOCAL, 0, + AUTOCAL_MODE, AUTOCAL_MODE_OFF, + AUTOCAL_NUM_PIPE, 0, + AUTOCAL_PIPE_ID, 0); + + /* Black offsets */ + if (ycbcr) + REG_SET_2(SCL_BLACK_OFFSET, 0, + SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y, + SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_CBCR); + else + + REG_SET_2(SCL_BLACK_OFFSET, 0, + SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y, + SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_RGB_Y); + + /* Manually calculate scale ratio and init values */ + dpp_set_manual_ratio_init(xfm, scl_data); + + /* HTaps/VTaps */ + REG_SET_4(SCL_TAP_CONTROL, 0, + SCL_V_NUM_TAPS, scl_data->taps.v_taps - 1, + SCL_H_NUM_TAPS, scl_data->taps.h_taps - 1, + SCL_V_NUM_TAPS_C, scl_data->taps.v_taps_c - 1, + SCL_H_NUM_TAPS_C, scl_data->taps.h_taps_c - 1); + + dpp_set_scl_filter(xfm, scl_data, ycbcr); +} + +#define IDENTITY_RATIO(ratio) (dal_fixed31_32_u2d19(ratio) == (1 << 19)) + + +static bool dpp_get_optimal_number_of_taps( + struct transform *xfm, + struct scaler_data *scl_data, + const struct scaling_taps *in_taps) +{ + uint32_t pixel_width; + + if (scl_data->viewport.width > scl_data->recout.width) + pixel_width = scl_data->recout.width; + else + pixel_width = scl_data->viewport.width; + + /* TODO: add lb check */ + + /* No support for programming ratio of 4, drop to 3.99999.. */ + if (scl_data->ratios.horz.value == (4ll << 32)) + scl_data->ratios.horz.value--; + if (scl_data->ratios.vert.value == (4ll << 32)) + scl_data->ratios.vert.value--; + if (scl_data->ratios.horz_c.value == (4ll << 32)) + scl_data->ratios.horz_c.value--; + if (scl_data->ratios.vert_c.value == (4ll << 32)) + scl_data->ratios.vert_c.value--; + + /* Set default taps if none are provided */ + if (in_taps->h_taps == 0) + scl_data->taps.h_taps = 4; + else + scl_data->taps.h_taps = in_taps->h_taps; + if (in_taps->v_taps == 0) + scl_data->taps.v_taps = 4; + else + scl_data->taps.v_taps = in_taps->v_taps; + if (in_taps->v_taps_c == 0) + scl_data->taps.v_taps_c = 2; + else + scl_data->taps.v_taps_c = in_taps->v_taps_c; + if (in_taps->h_taps_c == 0) + scl_data->taps.h_taps_c = 2; + /* Only 1 and even h_taps_c are supported by hw */ + else if ((in_taps->h_taps_c % 2) != 0 && in_taps->h_taps_c != 1) + scl_data->taps.h_taps_c = in_taps->h_taps_c - 1; + else + scl_data->taps.h_taps_c = in_taps->h_taps_c; + + if (!xfm->ctx->dc->debug.always_scale) { + if (IDENTITY_RATIO(scl_data->ratios.horz)) + scl_data->taps.h_taps = 1; + if (IDENTITY_RATIO(scl_data->ratios.vert)) + scl_data->taps.v_taps = 1; + if (IDENTITY_RATIO(scl_data->ratios.horz_c)) + scl_data->taps.h_taps_c = 1; + if (IDENTITY_RATIO(scl_data->ratios.vert_c)) + scl_data->taps.v_taps_c = 1; + } + + return true; +} + +static void dpp_reset(struct transform *xfm_base) +{ + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + + xfm->filter_h_c = NULL; + xfm->filter_v_c = NULL; + xfm->filter_h = NULL; + xfm->filter_v = NULL; + + /* set boundary mode to 0 */ + REG_SET(DSCL_CONTROL, 0, SCL_BOUNDARY_MODE, 0); +} + +static void program_gamut_remap( + struct dcn10_dpp *xfm, + const uint16_t *regval, + enum gamut_remap_select select) +{ + uint16_t selection = 0; + + if (regval == NULL || select == GAMUT_REMAP_BYPASS) { + REG_SET(CM_GAMUT_REMAP_CONTROL, 0, + CM_GAMUT_REMAP_MODE, 0); + return; + } + switch (select) { + case GAMUT_REMAP_COEFF: + selection = 1; + break; + case GAMUT_REMAP_COMA_COEFF: + selection = 2; + break; + case GAMUT_REMAP_COMB_COEFF: + selection = 3; + break; + default: + break; + } + + + if (select == GAMUT_REMAP_COEFF) { + + REG_SET_2(CM_GAMUT_REMAP_C11_C12, 0, + CM_GAMUT_REMAP_C11, regval[0], + CM_GAMUT_REMAP_C12, regval[1]); + regval += 2; + REG_SET_2(CM_GAMUT_REMAP_C13_C14, 0, + CM_GAMUT_REMAP_C13, regval[0], + CM_GAMUT_REMAP_C14, regval[1]); + regval += 2; + REG_SET_2(CM_GAMUT_REMAP_C21_C22, 0, + CM_GAMUT_REMAP_C21, regval[0], + CM_GAMUT_REMAP_C22, regval[1]); + regval += 2; + REG_SET_2(CM_GAMUT_REMAP_C23_C24, 0, + CM_GAMUT_REMAP_C23, regval[0], + CM_GAMUT_REMAP_C24, regval[1]); + regval += 2; + REG_SET_2(CM_GAMUT_REMAP_C31_C32, 0, + CM_GAMUT_REMAP_C31, regval[0], + CM_GAMUT_REMAP_C32, regval[1]); + regval += 2; + REG_SET_2(CM_GAMUT_REMAP_C33_C34, 0, + CM_GAMUT_REMAP_C33, regval[0], + CM_GAMUT_REMAP_C34, regval[1]); + + } else if (select == GAMUT_REMAP_COMA_COEFF) { + REG_SET_2(CM_COMA_C11_C12, 0, + CM_COMA_C11, regval[0], + CM_COMA_C12, regval[1]); + regval += 2; + REG_SET_2(CM_COMA_C13_C14, 0, + CM_COMA_C13, regval[0], + CM_COMA_C14, regval[1]); + regval += 2; + REG_SET_2(CM_COMA_C21_C22, 0, + CM_COMA_C21, regval[0], + CM_COMA_C22, regval[1]); + regval += 2; + REG_SET_2(CM_COMA_C23_C24, 0, + CM_COMA_C23, regval[0], + CM_COMA_C24, regval[1]); + regval += 2; + REG_SET_2(CM_COMA_C31_C32, 0, + CM_COMA_C31, regval[0], + CM_COMA_C32, regval[1]); + regval += 2; + REG_SET_2(CM_COMA_C33_C34, 0, + CM_COMA_C33, regval[0], + CM_COMA_C34, regval[1]); + + } else { + REG_SET_2(CM_COMB_C11_C12, 0, + CM_COMB_C11, regval[0], + CM_COMB_C12, regval[1]); + regval += 2; + REG_SET_2(CM_COMB_C13_C14, 0, + CM_COMB_C13, regval[0], + CM_COMB_C14, regval[1]); + regval += 2; + REG_SET_2(CM_COMB_C21_C22, 0, + CM_COMB_C21, regval[0], + CM_COMB_C22, regval[1]); + regval += 2; + REG_SET_2(CM_COMB_C23_C24, 0, + CM_COMB_C23, regval[0], + CM_COMB_C24, regval[1]); + regval += 2; + REG_SET_2(CM_COMB_C31_C32, 0, + CM_COMB_C31, regval[0], + CM_COMB_C32, regval[1]); + regval += 2; + REG_SET_2(CM_COMB_C33_C34, 0, + CM_COMB_C33, regval[0], + CM_COMB_C34, regval[1]); + } + + REG_SET( + CM_GAMUT_REMAP_CONTROL, 0, + CM_GAMUT_REMAP_MODE, selection); + +} + +static void dcn_dpp_set_gamut_remap( + struct transform *xfm, + const struct xfm_grph_csc_adjustment *adjust) +{ + struct dcn10_dpp *dcn_xfm = TO_DCN10_DPP(xfm); + + if (adjust->gamut_adjust_type != GRAPHICS_GAMUT_ADJUST_TYPE_SW) + /* Bypass if type is bypass or hw */ + program_gamut_remap(dcn_xfm, NULL, GAMUT_REMAP_BYPASS); + else { + struct fixed31_32 arr_matrix[12]; + uint16_t arr_reg_val[12]; + + arr_matrix[0] = adjust->temperature_matrix[0]; + arr_matrix[1] = adjust->temperature_matrix[1]; + arr_matrix[2] = adjust->temperature_matrix[2]; + arr_matrix[3] = dal_fixed31_32_zero; + + arr_matrix[4] = adjust->temperature_matrix[3]; + arr_matrix[5] = adjust->temperature_matrix[4]; + arr_matrix[6] = adjust->temperature_matrix[5]; + arr_matrix[7] = dal_fixed31_32_zero; + + arr_matrix[8] = adjust->temperature_matrix[6]; + arr_matrix[9] = adjust->temperature_matrix[7]; + arr_matrix[10] = adjust->temperature_matrix[8]; + arr_matrix[11] = dal_fixed31_32_zero; + + convert_float_matrix( + arr_reg_val, arr_matrix, 12); + + program_gamut_remap(dcn_xfm, arr_reg_val, GAMUT_REMAP_COEFF); + } +} + +static struct transform_funcs dcn10_dpp_funcs = { + .transform_reset = dpp_reset, + .transform_set_scaler = dpp_set_scaler_manual_scale, + .transform_get_optimal_number_of_taps = dpp_get_optimal_number_of_taps, + .transform_set_gamut_remap = dcn_dpp_set_gamut_remap, +}; + +/*****************************************/ +/* Constructor, Destructor */ +/*****************************************/ + +bool dcn10_dpp_construct( + struct dcn10_dpp *xfm, + struct dc_context *ctx, + uint32_t inst, + const struct dcn_dpp_registers *tf_regs, + const struct dcn_dpp_shift *tf_shift, + const struct dcn_dpp_mask *tf_mask) +{ + xfm->base.ctx = ctx; + + xfm->base.inst = inst; + xfm->base.funcs = &dcn10_dpp_funcs; + + xfm->tf_regs = tf_regs; + xfm->tf_shift = tf_shift; + xfm->tf_mask = tf_mask; + + xfm->lb_pixel_depth_supported = + LB_PIXEL_DEPTH_18BPP | + LB_PIXEL_DEPTH_24BPP | + LB_PIXEL_DEPTH_30BPP; + + xfm->lb_bits_per_entry = LB_BITS_PER_ENTRY; + xfm->lb_memory_size = LB_TOTAL_NUMBER_OF_ENTRIES; /*0x1404*/ + + return true; +} diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h new file mode 100644 index 000000000000..993643552aff --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h @@ -0,0 +1,419 @@ +/* Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_DPP_DCN10_H__ +#define __DAL_DPP_DCN10_H__ + +#include "transform.h" + +#define TO_DCN10_DPP(transform)\ + container_of(transform, struct dcn10_dpp, base) + +/* TODO: Use correct number of taps. Using polaris values for now */ +#define LB_TOTAL_NUMBER_OF_ENTRIES 5124 +#define LB_BITS_PER_ENTRY 144 + +#define TF_SF(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define TF_REG_LIST_DCN(id) \ + SRI(CM_GAMUT_REMAP_CONTROL, CM, id),\ + SRI(CM_GAMUT_REMAP_C11_C12, CM, id),\ + SRI(CM_GAMUT_REMAP_C13_C14, CM, id),\ + SRI(CM_GAMUT_REMAP_C21_C22, CM, id),\ + SRI(CM_GAMUT_REMAP_C23_C24, CM, id),\ + SRI(CM_GAMUT_REMAP_C31_C32, CM, id),\ + SRI(CM_GAMUT_REMAP_C33_C34, CM, id),\ + SRI(DSCL_EXT_OVERSCAN_LEFT_RIGHT, DSCL, id), \ + SRI(DSCL_EXT_OVERSCAN_TOP_BOTTOM, DSCL, id), \ + SRI(OTG_H_BLANK, DSCL, id), \ + SRI(OTG_V_BLANK, DSCL, id), \ + SRI(SCL_MODE, DSCL, id), \ + SRI(LB_DATA_FORMAT, DSCL, id), \ + SRI(LB_MEMORY_CTRL, DSCL, id), \ + SRI(DSCL_AUTOCAL, DSCL, id), \ + SRI(SCL_BLACK_OFFSET, DSCL, id), \ + SRI(DSCL_CONTROL, DSCL, id), \ + SRI(SCL_TAP_CONTROL, DSCL, id), \ + SRI(SCL_COEF_RAM_TAP_SELECT, DSCL, id), \ + SRI(SCL_COEF_RAM_TAP_DATA, DSCL, id), \ + SRI(DSCL_2TAP_CONTROL, DSCL, id), \ + SRI(DCSURF_PRI_VIEWPORT_DIMENSION, HUBP, id), \ + SRI(DCSURF_PRI_VIEWPORT_START, HUBP, id), \ + SRI(DCSURF_SEC_VIEWPORT_DIMENSION, HUBP, id), \ + SRI(DCSURF_SEC_VIEWPORT_START, HUBP, id), \ + SRI(DCSURF_PRI_VIEWPORT_DIMENSION_C, HUBP, id), \ + SRI(DCSURF_PRI_VIEWPORT_START_C, HUBP, id), \ + SRI(MPC_SIZE, DSCL, id), \ + SRI(SCL_HORZ_FILTER_SCALE_RATIO, DSCL, id), \ + SRI(SCL_VERT_FILTER_SCALE_RATIO, DSCL, id), \ + SRI(SCL_HORZ_FILTER_SCALE_RATIO_C, DSCL, id), \ + SRI(SCL_VERT_FILTER_SCALE_RATIO_C, DSCL, id), \ + SRI(SCL_HORZ_FILTER_INIT, DSCL, id), \ + SRI(SCL_HORZ_FILTER_INIT_C, DSCL, id), \ + SRI(SCL_VERT_FILTER_INIT, DSCL, id), \ + SRI(SCL_VERT_FILTER_INIT_BOT, DSCL, id), \ + SRI(SCL_VERT_FILTER_INIT_C, DSCL, id), \ + SRI(SCL_VERT_FILTER_INIT_BOT_C, DSCL, id), \ + SRI(RECOUT_START, DSCL, id), \ + SRI(RECOUT_SIZE, DSCL, id) + +#define TF_REG_LIST_DCN10(id) \ + TF_REG_LIST_DCN(id), \ + SRI(CM_COMA_C11_C12, CM, id),\ + SRI(CM_COMA_C13_C14, CM, id),\ + SRI(CM_COMA_C21_C22, CM, id),\ + SRI(CM_COMA_C23_C24, CM, id),\ + SRI(CM_COMA_C31_C32, CM, id),\ + SRI(CM_COMA_C33_C34, CM, id),\ + SRI(CM_COMB_C11_C12, CM, id),\ + SRI(CM_COMB_C13_C14, CM, id),\ + SRI(CM_COMB_C21_C22, CM, id),\ + SRI(CM_COMB_C23_C24, CM, id),\ + SRI(CM_COMB_C31_C32, CM, id),\ + SRI(CM_COMB_C33_C34, CM, id) + +#define TF_REG_LIST_SH_MASK_DCN(mask_sh)\ + TF_SF(CM0_CM_GAMUT_REMAP_CONTROL, CM_GAMUT_REMAP_MODE, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C11_C12, CM_GAMUT_REMAP_C11, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C11_C12, CM_GAMUT_REMAP_C12, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C13_C14, CM_GAMUT_REMAP_C13, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C13_C14, CM_GAMUT_REMAP_C14, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C21_C22, CM_GAMUT_REMAP_C21, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C21_C22, CM_GAMUT_REMAP_C22, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C23_C24, CM_GAMUT_REMAP_C23, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C23_C24, CM_GAMUT_REMAP_C24, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C31_C32, CM_GAMUT_REMAP_C31, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C31_C32, CM_GAMUT_REMAP_C32, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C33_C34, CM_GAMUT_REMAP_C33, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C33_C34, CM_GAMUT_REMAP_C34, mask_sh),\ + TF_SF(DSCL0_DSCL_EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_LEFT, mask_sh),\ + TF_SF(DSCL0_DSCL_EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_RIGHT, mask_sh),\ + TF_SF(DSCL0_DSCL_EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_BOTTOM, mask_sh),\ + TF_SF(DSCL0_DSCL_EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_TOP, mask_sh),\ + TF_SF(DSCL0_OTG_H_BLANK, OTG_H_BLANK_START, mask_sh),\ + TF_SF(DSCL0_OTG_H_BLANK, OTG_H_BLANK_END, mask_sh),\ + TF_SF(DSCL0_OTG_V_BLANK, OTG_V_BLANK_START, mask_sh),\ + TF_SF(DSCL0_OTG_V_BLANK, OTG_V_BLANK_END, mask_sh),\ + TF_SF(DSCL0_LB_DATA_FORMAT, INTERLEAVE_EN, mask_sh),\ + TF_SF(DSCL0_LB_DATA_FORMAT, ALPHA_EN, mask_sh),\ + TF_SF(DSCL0_LB_MEMORY_CTRL, MEMORY_CONFIG, mask_sh),\ + TF_SF(DSCL0_LB_MEMORY_CTRL, LB_MAX_PARTITIONS, mask_sh),\ + TF_SF(DSCL0_DSCL_AUTOCAL, AUTOCAL_MODE, mask_sh),\ + TF_SF(DSCL0_DSCL_AUTOCAL, AUTOCAL_NUM_PIPE, mask_sh),\ + TF_SF(DSCL0_DSCL_AUTOCAL, AUTOCAL_PIPE_ID, mask_sh),\ + TF_SF(DSCL0_SCL_BLACK_OFFSET, SCL_BLACK_OFFSET_RGB_Y, mask_sh),\ + TF_SF(DSCL0_SCL_BLACK_OFFSET, SCL_BLACK_OFFSET_CBCR, mask_sh),\ + TF_SF(DSCL0_DSCL_CONTROL, SCL_BOUNDARY_MODE, mask_sh),\ + TF_SF(DSCL0_SCL_TAP_CONTROL, SCL_V_NUM_TAPS, mask_sh),\ + TF_SF(DSCL0_SCL_TAP_CONTROL, SCL_H_NUM_TAPS, mask_sh),\ + TF_SF(DSCL0_SCL_TAP_CONTROL, SCL_V_NUM_TAPS_C, mask_sh),\ + TF_SF(DSCL0_SCL_TAP_CONTROL, SCL_H_NUM_TAPS_C, mask_sh),\ + TF_SF(DSCL0_SCL_COEF_RAM_TAP_SELECT, SCL_COEF_RAM_TAP_PAIR_IDX, mask_sh),\ + TF_SF(DSCL0_SCL_COEF_RAM_TAP_SELECT, SCL_COEF_RAM_PHASE, mask_sh),\ + TF_SF(DSCL0_SCL_COEF_RAM_TAP_SELECT, SCL_COEF_RAM_FILTER_TYPE, mask_sh),\ + TF_SF(DSCL0_SCL_COEF_RAM_TAP_DATA, SCL_COEF_RAM_EVEN_TAP_COEF, mask_sh),\ + TF_SF(DSCL0_SCL_COEF_RAM_TAP_DATA, SCL_COEF_RAM_EVEN_TAP_COEF_EN, mask_sh),\ + TF_SF(DSCL0_SCL_COEF_RAM_TAP_DATA, SCL_COEF_RAM_ODD_TAP_COEF, mask_sh),\ + TF_SF(DSCL0_SCL_COEF_RAM_TAP_DATA, SCL_COEF_RAM_ODD_TAP_COEF_EN, mask_sh),\ + TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_H_2TAP_HARDCODE_COEF_EN, mask_sh),\ + TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_H_2TAP_SHARP_EN, mask_sh),\ + TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_H_2TAP_SHARP_FACTOR, mask_sh),\ + TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_V_2TAP_HARDCODE_COEF_EN, mask_sh),\ + TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_V_2TAP_SHARP_EN, mask_sh),\ + TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_V_2TAP_SHARP_FACTOR, mask_sh),\ + TF_SF(DSCL0_SCL_MODE, SCL_COEF_RAM_SELECT, mask_sh),\ + TF_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION, PRI_VIEWPORT_WIDTH, mask_sh),\ + TF_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION, PRI_VIEWPORT_HEIGHT, mask_sh),\ + TF_SF(HUBP0_DCSURF_PRI_VIEWPORT_START, PRI_VIEWPORT_X_START, mask_sh),\ + TF_SF(HUBP0_DCSURF_PRI_VIEWPORT_START, PRI_VIEWPORT_Y_START, mask_sh),\ + TF_SF(HUBP0_DCSURF_SEC_VIEWPORT_DIMENSION, SEC_VIEWPORT_WIDTH, mask_sh),\ + TF_SF(HUBP0_DCSURF_SEC_VIEWPORT_DIMENSION, SEC_VIEWPORT_HEIGHT, mask_sh),\ + TF_SF(HUBP0_DCSURF_SEC_VIEWPORT_START, SEC_VIEWPORT_X_START, mask_sh),\ + TF_SF(HUBP0_DCSURF_SEC_VIEWPORT_START, SEC_VIEWPORT_Y_START, mask_sh),\ + TF_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION_C, PRI_VIEWPORT_WIDTH_C, mask_sh),\ + TF_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION_C, PRI_VIEWPORT_HEIGHT_C, mask_sh),\ + TF_SF(HUBP0_DCSURF_PRI_VIEWPORT_START_C, PRI_VIEWPORT_X_START_C, mask_sh),\ + TF_SF(HUBP0_DCSURF_PRI_VIEWPORT_START_C, PRI_VIEWPORT_Y_START_C, mask_sh),\ + TF_SF(DSCL0_SCL_MODE, DSCL_MODE, mask_sh),\ + TF_SF(DSCL0_RECOUT_START, RECOUT_START_X, mask_sh),\ + TF_SF(DSCL0_RECOUT_START, RECOUT_START_Y, mask_sh),\ + TF_SF(DSCL0_RECOUT_SIZE, RECOUT_WIDTH, mask_sh),\ + TF_SF(DSCL0_RECOUT_SIZE, RECOUT_HEIGHT, mask_sh),\ + TF_SF(DSCL0_MPC_SIZE, MPC_WIDTH, mask_sh),\ + TF_SF(DSCL0_MPC_SIZE, MPC_HEIGHT, mask_sh),\ + TF_SF(DSCL0_SCL_HORZ_FILTER_SCALE_RATIO, SCL_H_SCALE_RATIO, mask_sh),\ + TF_SF(DSCL0_SCL_VERT_FILTER_SCALE_RATIO, SCL_V_SCALE_RATIO, mask_sh),\ + TF_SF(DSCL0_SCL_HORZ_FILTER_SCALE_RATIO_C, SCL_H_SCALE_RATIO_C, mask_sh),\ + TF_SF(DSCL0_SCL_VERT_FILTER_SCALE_RATIO_C, SCL_V_SCALE_RATIO_C, mask_sh),\ + TF_SF(DSCL0_SCL_HORZ_FILTER_INIT, SCL_H_INIT_FRAC, mask_sh),\ + TF_SF(DSCL0_SCL_HORZ_FILTER_INIT, SCL_H_INIT_INT, mask_sh),\ + TF_SF(DSCL0_SCL_HORZ_FILTER_INIT_C, SCL_H_INIT_FRAC_C, mask_sh),\ + TF_SF(DSCL0_SCL_HORZ_FILTER_INIT_C, SCL_H_INIT_INT_C, mask_sh),\ + TF_SF(DSCL0_SCL_VERT_FILTER_INIT, SCL_V_INIT_FRAC, mask_sh),\ + TF_SF(DSCL0_SCL_VERT_FILTER_INIT, SCL_V_INIT_INT, mask_sh),\ + TF_SF(DSCL0_SCL_VERT_FILTER_INIT_BOT, SCL_V_INIT_FRAC_BOT, mask_sh),\ + TF_SF(DSCL0_SCL_VERT_FILTER_INIT_BOT, SCL_V_INIT_INT_BOT, mask_sh),\ + TF_SF(DSCL0_SCL_VERT_FILTER_INIT_C, SCL_V_INIT_FRAC_C, mask_sh),\ + TF_SF(DSCL0_SCL_VERT_FILTER_INIT_C, SCL_V_INIT_INT_C, mask_sh),\ + TF_SF(DSCL0_SCL_VERT_FILTER_INIT_BOT_C, SCL_V_INIT_FRAC_BOT_C, mask_sh),\ + TF_SF(DSCL0_SCL_VERT_FILTER_INIT_BOT_C, SCL_V_INIT_INT_BOT_C, mask_sh),\ + TF_SF(DSCL0_SCL_MODE, SCL_CHROMA_COEF_MODE, mask_sh),\ + TF_SF(DSCL0_SCL_MODE, SCL_COEF_RAM_SELECT_CURRENT, mask_sh) + +#define TF_REG_LIST_SH_MASK_DCN10(mask_sh)\ + TF_REG_LIST_SH_MASK_DCN(mask_sh),\ + TF_SF(DSCL0_LB_DATA_FORMAT, PIXEL_DEPTH, mask_sh),\ + TF_SF(DSCL0_LB_DATA_FORMAT, PIXEL_EXPAN_MODE, mask_sh),\ + TF_SF(DSCL0_LB_DATA_FORMAT, PIXEL_REDUCE_MODE, mask_sh),\ + TF_SF(DSCL0_LB_DATA_FORMAT, DYNAMIC_PIXEL_DEPTH, mask_sh),\ + TF_SF(DSCL0_LB_DATA_FORMAT, DITHER_EN, mask_sh),\ + TF_SF(CM0_CM_COMA_C11_C12, CM_COMA_C11, mask_sh),\ + TF_SF(CM0_CM_COMA_C11_C12, CM_COMA_C12, mask_sh),\ + TF_SF(CM0_CM_COMA_C13_C14, CM_COMA_C13, mask_sh),\ + TF_SF(CM0_CM_COMA_C13_C14, CM_COMA_C14, mask_sh),\ + TF_SF(CM0_CM_COMA_C21_C22, CM_COMA_C21, mask_sh),\ + TF_SF(CM0_CM_COMA_C21_C22, CM_COMA_C22, mask_sh),\ + TF_SF(CM0_CM_COMA_C23_C24, CM_COMA_C23, mask_sh),\ + TF_SF(CM0_CM_COMA_C23_C24, CM_COMA_C24, mask_sh),\ + TF_SF(CM0_CM_COMA_C31_C32, CM_COMA_C31, mask_sh),\ + TF_SF(CM0_CM_COMA_C31_C32, CM_COMA_C32, mask_sh),\ + TF_SF(CM0_CM_COMA_C33_C34, CM_COMA_C33, mask_sh),\ + TF_SF(CM0_CM_COMA_C33_C34, CM_COMA_C34, mask_sh),\ + TF_SF(CM0_CM_COMB_C11_C12, CM_COMB_C11, mask_sh),\ + TF_SF(CM0_CM_COMB_C11_C12, CM_COMB_C12, mask_sh),\ + TF_SF(CM0_CM_COMB_C13_C14, CM_COMB_C13, mask_sh),\ + TF_SF(CM0_CM_COMB_C13_C14, CM_COMB_C14, mask_sh),\ + TF_SF(CM0_CM_COMB_C21_C22, CM_COMB_C21, mask_sh),\ + TF_SF(CM0_CM_COMB_C21_C22, CM_COMB_C22, mask_sh),\ + TF_SF(CM0_CM_COMB_C23_C24, CM_COMB_C23, mask_sh),\ + TF_SF(CM0_CM_COMB_C23_C24, CM_COMB_C24, mask_sh),\ + TF_SF(CM0_CM_COMB_C31_C32, CM_COMB_C31, mask_sh),\ + TF_SF(CM0_CM_COMB_C33_C34, CM_COMB_C33, mask_sh),\ + TF_SF(CM0_CM_COMB_C31_C32, CM_COMB_C32, mask_sh),\ + TF_SF(CM0_CM_COMB_C33_C34, CM_COMB_C34, mask_sh) + + +#define TF_REG_FIELD_LIST(type) \ + type EXT_OVERSCAN_LEFT; \ + type EXT_OVERSCAN_RIGHT; \ + type EXT_OVERSCAN_BOTTOM; \ + type EXT_OVERSCAN_TOP; \ + type OTG_H_BLANK_START; \ + type OTG_H_BLANK_END; \ + type OTG_V_BLANK_START; \ + type OTG_V_BLANK_END; \ + type PIXEL_DEPTH; \ + type PIXEL_EXPAN_MODE; \ + type PIXEL_REDUCE_MODE; \ + type DYNAMIC_PIXEL_DEPTH; \ + type DITHER_EN; \ + type INTERLEAVE_EN; \ + type ALPHA_EN; \ + type MEMORY_CONFIG; \ + type LB_MAX_PARTITIONS; \ + type AUTOCAL_MODE; \ + type AUTOCAL_NUM_PIPE; \ + type AUTOCAL_PIPE_ID; \ + type SCL_BLACK_OFFSET_RGB_Y; \ + type SCL_BLACK_OFFSET_CBCR; \ + type SCL_BOUNDARY_MODE; \ + type SCL_V_NUM_TAPS; \ + type SCL_H_NUM_TAPS; \ + type SCL_V_NUM_TAPS_C; \ + type SCL_H_NUM_TAPS_C; \ + type SCL_COEF_RAM_TAP_PAIR_IDX; \ + type SCL_COEF_RAM_PHASE; \ + type SCL_COEF_RAM_FILTER_TYPE; \ + type SCL_COEF_RAM_EVEN_TAP_COEF; \ + type SCL_COEF_RAM_EVEN_TAP_COEF_EN; \ + type SCL_COEF_RAM_ODD_TAP_COEF; \ + type SCL_COEF_RAM_ODD_TAP_COEF_EN; \ + type SCL_H_2TAP_HARDCODE_COEF_EN; \ + type SCL_H_2TAP_SHARP_EN; \ + type SCL_H_2TAP_SHARP_FACTOR; \ + type SCL_V_2TAP_HARDCODE_COEF_EN; \ + type SCL_V_2TAP_SHARP_EN; \ + type SCL_V_2TAP_SHARP_FACTOR; \ + type SCL_COEF_RAM_SELECT; \ + type PRI_VIEWPORT_WIDTH; \ + type PRI_VIEWPORT_HEIGHT; \ + type PRI_VIEWPORT_X_START; \ + type PRI_VIEWPORT_Y_START; \ + type SEC_VIEWPORT_WIDTH; \ + type SEC_VIEWPORT_HEIGHT; \ + type SEC_VIEWPORT_X_START; \ + type SEC_VIEWPORT_Y_START; \ + type PRI_VIEWPORT_WIDTH_C; \ + type PRI_VIEWPORT_HEIGHT_C; \ + type PRI_VIEWPORT_X_START_C; \ + type PRI_VIEWPORT_Y_START_C; \ + type DSCL_MODE; \ + type RECOUT_START_X; \ + type RECOUT_START_Y; \ + type RECOUT_WIDTH; \ + type RECOUT_HEIGHT; \ + type MPC_WIDTH; \ + type MPC_HEIGHT; \ + type SCL_H_SCALE_RATIO; \ + type SCL_V_SCALE_RATIO; \ + type SCL_H_SCALE_RATIO_C; \ + type SCL_V_SCALE_RATIO_C; \ + type SCL_H_INIT_FRAC; \ + type SCL_H_INIT_INT; \ + type SCL_H_INIT_FRAC_C; \ + type SCL_H_INIT_INT_C; \ + type SCL_V_INIT_FRAC; \ + type SCL_V_INIT_INT; \ + type SCL_V_INIT_FRAC_BOT; \ + type SCL_V_INIT_INT_BOT; \ + type SCL_V_INIT_FRAC_C; \ + type SCL_V_INIT_INT_C; \ + type SCL_V_INIT_FRAC_BOT_C; \ + type SCL_V_INIT_INT_BOT_C; \ + type SCL_CHROMA_COEF_MODE; \ + type SCL_COEF_RAM_SELECT_CURRENT; \ + type CM_GAMUT_REMAP_MODE; \ + type CM_GAMUT_REMAP_C11; \ + type CM_GAMUT_REMAP_C12; \ + type CM_GAMUT_REMAP_C13; \ + type CM_GAMUT_REMAP_C14; \ + type CM_GAMUT_REMAP_C21; \ + type CM_GAMUT_REMAP_C22; \ + type CM_GAMUT_REMAP_C23; \ + type CM_GAMUT_REMAP_C24; \ + type CM_GAMUT_REMAP_C31; \ + type CM_GAMUT_REMAP_C32; \ + type CM_GAMUT_REMAP_C33; \ + type CM_GAMUT_REMAP_C34; \ + type CM_COMA_C11; \ + type CM_COMA_C12; \ + type CM_COMA_C13; \ + type CM_COMA_C14; \ + type CM_COMA_C21; \ + type CM_COMA_C22; \ + type CM_COMA_C23; \ + type CM_COMA_C24; \ + type CM_COMA_C31; \ + type CM_COMA_C32; \ + type CM_COMA_C33; \ + type CM_COMA_C34; \ + type CM_COMB_C11; \ + type CM_COMB_C12; \ + type CM_COMB_C13; \ + type CM_COMB_C14; \ + type CM_COMB_C21; \ + type CM_COMB_C22; \ + type CM_COMB_C23; \ + type CM_COMB_C24; \ + type CM_COMB_C31; \ + type CM_COMB_C32; \ + type CM_COMB_C33; \ + type CM_COMB_C34 + +struct dcn_dpp_shift { + TF_REG_FIELD_LIST(uint8_t); +}; + +struct dcn_dpp_mask { + TF_REG_FIELD_LIST(uint32_t); +}; + +struct dcn_dpp_registers { + uint32_t DSCL_EXT_OVERSCAN_LEFT_RIGHT; + uint32_t DSCL_EXT_OVERSCAN_TOP_BOTTOM; + uint32_t OTG_H_BLANK; + uint32_t OTG_V_BLANK; + uint32_t SCL_MODE; + uint32_t LB_DATA_FORMAT; + uint32_t LB_MEMORY_CTRL; + uint32_t DSCL_AUTOCAL; + uint32_t SCL_BLACK_OFFSET; + uint32_t DSCL_CONTROL; + uint32_t SCL_TAP_CONTROL; + uint32_t SCL_COEF_RAM_TAP_SELECT; + uint32_t SCL_COEF_RAM_TAP_DATA; + uint32_t DSCL_2TAP_CONTROL; + uint32_t DCSURF_PRI_VIEWPORT_DIMENSION; + uint32_t DCSURF_PRI_VIEWPORT_START; + uint32_t DCSURF_SEC_VIEWPORT_DIMENSION; + uint32_t DCSURF_SEC_VIEWPORT_START; + uint32_t DCSURF_PRI_VIEWPORT_DIMENSION_C; + uint32_t DCSURF_PRI_VIEWPORT_START_C; + uint32_t MPC_SIZE; + uint32_t SCL_HORZ_FILTER_SCALE_RATIO; + uint32_t SCL_VERT_FILTER_SCALE_RATIO; + uint32_t SCL_HORZ_FILTER_SCALE_RATIO_C; + uint32_t SCL_VERT_FILTER_SCALE_RATIO_C; + uint32_t SCL_HORZ_FILTER_INIT; + uint32_t SCL_HORZ_FILTER_INIT_C; + uint32_t SCL_VERT_FILTER_INIT; + uint32_t SCL_VERT_FILTER_INIT_BOT; + uint32_t SCL_VERT_FILTER_INIT_C; + uint32_t SCL_VERT_FILTER_INIT_BOT_C; + uint32_t RECOUT_START; + uint32_t RECOUT_SIZE; + uint32_t CM_GAMUT_REMAP_CONTROL; + uint32_t CM_GAMUT_REMAP_C11_C12; + uint32_t CM_GAMUT_REMAP_C13_C14; + uint32_t CM_GAMUT_REMAP_C21_C22; + uint32_t CM_GAMUT_REMAP_C23_C24; + uint32_t CM_GAMUT_REMAP_C31_C32; + uint32_t CM_GAMUT_REMAP_C33_C34; + uint32_t CM_COMA_C11_C12; + uint32_t CM_COMA_C13_C14; + uint32_t CM_COMA_C21_C22; + uint32_t CM_COMA_C23_C24; + uint32_t CM_COMA_C31_C32; + uint32_t CM_COMA_C33_C34; + uint32_t CM_COMB_C11_C12; + uint32_t CM_COMB_C13_C14; + uint32_t CM_COMB_C21_C22; + uint32_t CM_COMB_C23_C24; + uint32_t CM_COMB_C31_C32; + uint32_t CM_COMB_C33_C34; +}; + +struct dcn10_dpp { + struct transform base; + + const struct dcn_dpp_registers *tf_regs; + const struct dcn_dpp_shift *tf_shift; + const struct dcn_dpp_mask *tf_mask; + + const uint16_t *filter_v; + const uint16_t *filter_h; + const uint16_t *filter_v_c; + const uint16_t *filter_h_c; + int lb_pixel_depth_supported; + int lb_memory_size; + int lb_bits_per_entry; +}; +bool dcn10_dpp_construct(struct dcn10_dpp *xfm110, + struct dc_context *ctx, + uint32_t inst, + const struct dcn_dpp_registers *tf_regs, + const struct dcn_dpp_shift *tf_shift, + const struct dcn_dpp_mask *tf_mask); +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index dbf9cea2e418..fc46c84aea67 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -33,6 +33,8 @@ #include "dce110/dce110_hw_sequencer.h" #include "dce/dce_hwseq.h" #include "abm.h" +#include "dcn10/dcn10_dpp.h" +#include "dcn10/dcn10_mpc.h" #include "mem_input.h" #include "timing_generator.h" #include "opp.h" diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 75ad37e81738..4a996f9ae468 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -33,7 +33,7 @@ #include "dcn10/dcn10_ipp.h" #include "dcn10/dcn10_mpc.h" #include "irq/dcn10/irq_service_dcn10.h" -#include "dcn10/dcn10_transform.h" +#include "dcn10/dcn10_dpp.h" #include "dcn10/dcn10_timing_generator.h" #include "dcn10/dcn10_hw_sequencer.h" #include "dce110/dce110_hw_sequencer.h" @@ -309,18 +309,18 @@ static const struct dcn10_opp_mask opp_mask = { TF_REG_LIST_DCN10(id),\ } -static const struct dcn_transform_registers tf_regs[] = { +static const struct dcn_dpp_registers tf_regs[] = { tf_regs(0), tf_regs(1), tf_regs(2), tf_regs(3), }; -static const struct dcn_transform_shift tf_shift = { +static const struct dcn_dpp_shift tf_shift = { TF_REG_LIST_SH_MASK_DCN10(__SHIFT) }; -static const struct dcn_transform_mask tf_mask = { +static const struct dcn_dpp_mask tf_mask = { TF_REG_LIST_SH_MASK_DCN10(_MASK), }; @@ -449,28 +449,28 @@ static const struct dc_debug debug_defaults_diags = { #endif }; -static void dcn10_transform_destroy(struct transform **xfm) +static void dcn10_dpp_destroy(struct transform **xfm) { - dm_free(TO_DCN10_TRANSFORM(*xfm)); + dm_free(TO_DCN10_DPP(*xfm)); *xfm = NULL; } -static struct transform *dcn10_transform_create( +static struct transform *dcn10_dpp_create( struct dc_context *ctx, uint32_t inst) { - struct dcn10_transform *transform = - dm_alloc(sizeof(struct dcn10_transform)); + struct dcn10_dpp *dpp = + dm_alloc(sizeof(struct dcn10_dpp)); - if (!transform) + if (!dpp) return NULL; - if (dcn10_transform_construct(transform, ctx, inst, + if (dcn10_dpp_construct(dpp, ctx, inst, &tf_regs[inst], &tf_shift, &tf_mask)) - return &transform->base; + return &dpp->base; BREAK_TO_DEBUGGER(); - dm_free(transform); + dm_free(dpp); return NULL; } @@ -710,7 +710,7 @@ static void destruct(struct dcn10_resource_pool *pool) pool->base.opps[i]->funcs->opp_destroy(&pool->base.opps[i]); if (pool->base.transforms[i] != NULL) - dcn10_transform_destroy(&pool->base.transforms[i]); + dcn10_dpp_destroy(&pool->base.transforms[i]); if (pool->base.ipps[i] != NULL) pool->base.ipps[i]->funcs->ipp_destroy(&pool->base.ipps[i]); @@ -1387,7 +1387,7 @@ static bool construct( #endif } - /* mem input -> ipp -> transform -> opp -> TG */ + /* mem input -> ipp -> dpp -> opp -> TG */ for (i = 0; i < pool->base.pipe_count; i++) { pool->base.mis[i] = dcn10_mem_input_create(ctx, i); if (pool->base.mis[i] == NULL) { @@ -1405,12 +1405,12 @@ static bool construct( goto ipp_create_fail; } - pool->base.transforms[i] = dcn10_transform_create(ctx, i); + pool->base.transforms[i] = dcn10_dpp_create(ctx, i); if (pool->base.transforms[i] == NULL) { BREAK_TO_DEBUGGER(); dm_error( - "DC: failed to create transform!\n"); - goto transform_create_fail; + "DC: failed to create dpp!\n"); + goto dpp_create_fail; } pool->base.opps[i] = dcn10_opp_create(ctx, i); @@ -1452,7 +1452,7 @@ disp_clk_create_fail: mpcc_create_fail: otg_create_fail: opp_create_fail: -transform_create_fail: +dpp_create_fail: ipp_create_fail: mi_create_fail: irqs_create_fail: diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c deleted file mode 100644 index 59ba2d250d6d..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c +++ /dev/null @@ -1,1065 +0,0 @@ -/* - * Copyright 2016 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" - -#include "core_types.h" - -#include "include/grph_object_id.h" -#include "include/fixed31_32.h" -#include "include/logger_interface.h" - -#include "reg_helper.h" -#include "dcn10_transform.h" -#include "basics/conversion.h" - -#define NUM_PHASES 64 -#define HORZ_MAX_TAPS 8 -#define VERT_MAX_TAPS 8 - -#define BLACK_OFFSET_RGB_Y 0x0 -#define BLACK_OFFSET_CBCR 0x8000 - -#define REG(reg)\ - xfm->tf_regs->reg - -#define CTX \ - xfm->base.ctx - -#undef FN -#define FN(reg_name, field_name) \ - xfm->tf_shift->field_name, xfm->tf_mask->field_name - - -enum dcn10_coef_filter_type_sel { - SCL_COEF_LUMA_VERT_FILTER = 0, - SCL_COEF_LUMA_HORZ_FILTER = 1, - SCL_COEF_CHROMA_VERT_FILTER = 2, - SCL_COEF_CHROMA_HORZ_FILTER = 3, - SCL_COEF_ALPHA_VERT_FILTER = 4, - SCL_COEF_ALPHA_HORZ_FILTER = 5 -}; - -enum lb_memory_config { - /* Enable all 3 pieces of memory */ - LB_MEMORY_CONFIG_0 = 0, - - /* Enable only the first piece of memory */ - LB_MEMORY_CONFIG_1 = 1, - - /* Enable only the second piece of memory */ - LB_MEMORY_CONFIG_2 = 2, - - /* Only applicable in 4:2:0 mode, enable all 3 pieces of memory and the - * last piece of chroma memory used for the luma storage - */ - LB_MEMORY_CONFIG_3 = 3 -}; - -enum dscl_autocal_mode { - AUTOCAL_MODE_OFF = 0, - - /* Autocal calculate the scaling ratio and initial phase and the - * DSCL_MODE_SEL must be set to 1 - */ - AUTOCAL_MODE_AUTOSCALE = 1, - /* Autocal perform auto centering without replication and the - * DSCL_MODE_SEL must be set to 0 - */ - AUTOCAL_MODE_AUTOCENTER = 2, - /* Autocal perform auto centering and auto replication and the - * DSCL_MODE_SEL must be set to 0 - */ - AUTOCAL_MODE_AUTOREPLICATE = 3 -}; - -enum dscl_mode_sel { - DSCL_MODE_SCALING_444_BYPASS = 0, - DSCL_MODE_SCALING_444_RGB_ENABLE = 1, - DSCL_MODE_SCALING_444_YCBCR_ENABLE = 2, - DSCL_MODE_SCALING_420_YCBCR_ENABLE = 3, - DSCL_MODE_SCALING_420_LUMA_BYPASS = 4, - DSCL_MODE_SCALING_420_CHROMA_BYPASS = 5, - DSCL_MODE_DSCL_BYPASS = 6 -}; - -enum gamut_remap_select { - GAMUT_REMAP_BYPASS = 0, - GAMUT_REMAP_COEFF, - GAMUT_REMAP_COMA_COEFF, - GAMUT_REMAP_COMB_COEFF -}; - -static void transform_set_overscan( - struct dcn10_transform *xfm, - const struct scaler_data *data) -{ - uint32_t left = data->recout.x; - uint32_t top = data->recout.y; - - int right = data->h_active - data->recout.x - data->recout.width; - int bottom = data->v_active - data->recout.y - data->recout.height; - - if (right < 0) { - BREAK_TO_DEBUGGER(); - right = 0; - } - if (bottom < 0) { - BREAK_TO_DEBUGGER(); - bottom = 0; - } - - REG_SET_2(DSCL_EXT_OVERSCAN_LEFT_RIGHT, 0, - EXT_OVERSCAN_LEFT, left, - EXT_OVERSCAN_RIGHT, right); - - REG_SET_2(DSCL_EXT_OVERSCAN_TOP_BOTTOM, 0, - EXT_OVERSCAN_BOTTOM, bottom, - EXT_OVERSCAN_TOP, top); -} - -static void transform_set_otg_blank( - struct dcn10_transform *xfm, const struct scaler_data *data) -{ - uint32_t h_blank_start = data->h_active; - uint32_t h_blank_end = 0; - uint32_t v_blank_start = data->v_active; - uint32_t v_blank_end = 0; - - REG_SET_2(OTG_H_BLANK, 0, - OTG_H_BLANK_START, h_blank_start, - OTG_H_BLANK_END, h_blank_end); - - REG_SET_2(OTG_V_BLANK, 0, - OTG_V_BLANK_START, v_blank_start, - OTG_V_BLANK_END, v_blank_end); -} - -static enum dscl_mode_sel get_dscl_mode( - const struct scaler_data *data, bool dbg_always_scale) -{ - const long long one = dal_fixed31_32_one.value; - bool ycbcr = false; - bool format420 = false; - - if (data->format == PIXEL_FORMAT_FP16) - return DSCL_MODE_DSCL_BYPASS; - - if (data->format >= PIXEL_FORMAT_VIDEO_BEGIN - && data->format <= PIXEL_FORMAT_VIDEO_END) - ycbcr = true; - - if (data->format == PIXEL_FORMAT_420BPP8 || - data->format == PIXEL_FORMAT_420BPP10) - format420 = true; - - if (data->ratios.horz.value == one - && data->ratios.vert.value == one - && data->ratios.horz_c.value == one - && data->ratios.vert_c.value == one - && !dbg_always_scale) - return DSCL_MODE_SCALING_444_BYPASS; - - if (!format420) { - if (ycbcr) - return DSCL_MODE_SCALING_444_YCBCR_ENABLE; - else - return DSCL_MODE_SCALING_444_RGB_ENABLE; - } - if (data->ratios.horz.value == one && data->ratios.vert.value == one) - return DSCL_MODE_SCALING_420_LUMA_BYPASS; - if (data->ratios.horz_c.value == one && data->ratios.vert_c.value == one) - return DSCL_MODE_SCALING_420_CHROMA_BYPASS; - - return DSCL_MODE_SCALING_420_YCBCR_ENABLE; -} - -static int get_pixel_depth_val(enum lb_pixel_depth depth) -{ - if (depth == LB_PIXEL_DEPTH_30BPP) - return 0; /* 10 bpc */ - else if (depth == LB_PIXEL_DEPTH_24BPP) - return 1; /* 8 bpc */ - else if (depth == LB_PIXEL_DEPTH_18BPP) - return 2; /* 6 bpc */ - else if (depth == LB_PIXEL_DEPTH_36BPP) - return 3; /* 12 bpc */ - else { - ASSERT(0); - return -1; /* Unsupported */ - } -} - -static void xfmn10_set_lb( - struct dcn10_transform *xfm, - const struct line_buffer_params *lb_params, - enum lb_memory_config mem_size_config) -{ - uint32_t pixel_depth = get_pixel_depth_val(lb_params->depth); - uint32_t dyn_pix_depth = lb_params->dynamic_pixel_depth; - REG_SET_7(LB_DATA_FORMAT, 0, - PIXEL_DEPTH, pixel_depth, /* Pixel depth stored in LB */ - PIXEL_EXPAN_MODE, lb_params->pixel_expan_mode, /* Pixel expansion mode */ - PIXEL_REDUCE_MODE, 1, /* Pixel reduction mode: Rounding */ - DYNAMIC_PIXEL_DEPTH, dyn_pix_depth, /* Dynamic expansion pixel depth */ - DITHER_EN, 0, /* Dithering enable: Disabled */ - INTERLEAVE_EN, lb_params->interleave_en, /* Interleave source enable */ - ALPHA_EN, lb_params->alpha_en); /* Alpha enable */ - - REG_SET_2(LB_MEMORY_CTRL, 0, - MEMORY_CONFIG, mem_size_config, - LB_MAX_PARTITIONS, 63); -} - -static void transform_set_scaler_filter( - struct dcn10_transform *xfm, - uint32_t taps, - enum dcn10_coef_filter_type_sel filter_type, - const uint16_t *filter) -{ - const int tap_pairs = (taps + 1) / 2; - int phase; - int pair; - uint16_t odd_coef, even_coef; - - REG_SET_3(SCL_COEF_RAM_TAP_SELECT, 0, - SCL_COEF_RAM_TAP_PAIR_IDX, 0, - SCL_COEF_RAM_PHASE, 0, - SCL_COEF_RAM_FILTER_TYPE, filter_type); - - for (phase = 0; phase < (NUM_PHASES / 2 + 1); phase++) { - for (pair = 0; pair < tap_pairs; pair++) { - even_coef = filter[phase * taps + 2 * pair]; - if ((pair * 2 + 1) < taps) - odd_coef = filter[phase * taps + 2 * pair + 1]; - else - odd_coef = 0; - - REG_SET_4(SCL_COEF_RAM_TAP_DATA, 0, - /* Even tap coefficient (bits 1:0 fixed to 0) */ - SCL_COEF_RAM_EVEN_TAP_COEF, even_coef, - /* Write/read control for even coefficient */ - SCL_COEF_RAM_EVEN_TAP_COEF_EN, 1, - /* Odd tap coefficient (bits 1:0 fixed to 0) */ - SCL_COEF_RAM_ODD_TAP_COEF, odd_coef, - /* Write/read control for odd coefficient */ - SCL_COEF_RAM_ODD_TAP_COEF_EN, 1); - } - } - -} - -#if 0 -bool transform_set_pixel_storage_depth( - struct transform *xfm, - enum lb_pixel_depth depth, - const struct bit_depth_reduction_params *bit_depth_params) -{ - struct dcn10_transform *xfm110 = TO_DCN10_TRANSFORM(xfm); - bool ret = true; - uint32_t value; - enum dc_color_depth color_depth; - - value = dm_read_reg(xfm->ctx, LB_REG(mmLB_DATA_FORMAT)); - switch (depth) { - case LB_PIXEL_DEPTH_18BPP: - color_depth = COLOR_DEPTH_666; - set_reg_field_value(value, 2, LB_DATA_FORMAT, PIXEL_DEPTH); - set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_EXPAN_MODE); - break; - case LB_PIXEL_DEPTH_24BPP: - color_depth = COLOR_DEPTH_888; - set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_DEPTH); - set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_EXPAN_MODE); - break; - case LB_PIXEL_DEPTH_30BPP: - color_depth = COLOR_DEPTH_101010; - set_reg_field_value(value, 0, LB_DATA_FORMAT, PIXEL_DEPTH); - set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_EXPAN_MODE); - break; - case LB_PIXEL_DEPTH_36BPP: - color_depth = COLOR_DEPTH_121212; - set_reg_field_value(value, 3, LB_DATA_FORMAT, PIXEL_DEPTH); - set_reg_field_value(value, 0, LB_DATA_FORMAT, PIXEL_EXPAN_MODE); - break; - default: - ret = false; - break; - } - - if (ret == true) { - set_denormalization(xfm110, color_depth); - ret = program_bit_depth_reduction(xfm110, color_depth, - bit_depth_params); - - set_reg_field_value(value, 0, LB_DATA_FORMAT, ALPHA_EN); - dm_write_reg(xfm->ctx, LB_REG(mmLB_DATA_FORMAT), value); - if (!(xfm110->lb_pixel_depth_supported & depth)) { - /* We should use unsupported capabilities - * unless it is required by w/a - */ - dm_logger_write(xfm->ctx->logger, LOG_WARNING, - "%s: Capability not supported", - __func__); - } - } - - return ret; -} -#endif - -static const uint16_t *get_filter_coeffs_64p(int taps, struct fixed31_32 ratio) -{ - if (taps == 8) - return get_filter_8tap_64p(ratio); - else if (taps == 7) - return get_filter_7tap_64p(ratio); - else if (taps == 6) - return get_filter_6tap_64p(ratio); - else if (taps == 5) - return get_filter_5tap_64p(ratio); - else if (taps == 4) - return get_filter_4tap_64p(ratio); - else if (taps == 3) - return get_filter_3tap_64p(ratio); - else if (taps == 2) - return filter_2tap_64p; - else if (taps == 1) - return NULL; - else { - /* should never happen, bug */ - BREAK_TO_DEBUGGER(); - return NULL; - } -} - -static void transform_set_scl_filter( - struct dcn10_transform *xfm, - const struct scaler_data *scl_data, - bool chroma_coef_mode) -{ - bool h_2tap_hardcode_coef_en = false; - bool v_2tap_hardcode_coef_en = false; - bool h_2tap_sharp_en = false; - bool v_2tap_sharp_en = false; - uint32_t h_2tap_sharp_factor = scl_data->sharpness.horz; - uint32_t v_2tap_sharp_factor = scl_data->sharpness.vert; - bool coef_ram_current; - const uint16_t *filter_h = NULL; - const uint16_t *filter_v = NULL; - const uint16_t *filter_h_c = NULL; - const uint16_t *filter_v_c = NULL; - - h_2tap_hardcode_coef_en = scl_data->taps.h_taps < 3 - && scl_data->taps.h_taps_c < 3 - && (scl_data->taps.h_taps > 1 || scl_data->taps.h_taps_c > 1); - v_2tap_hardcode_coef_en = scl_data->taps.v_taps < 3 - && scl_data->taps.v_taps_c < 3 - && (scl_data->taps.v_taps > 1 || scl_data->taps.v_taps_c > 1); - - h_2tap_sharp_en = h_2tap_hardcode_coef_en && h_2tap_sharp_factor != 0; - v_2tap_sharp_en = v_2tap_hardcode_coef_en && v_2tap_sharp_factor != 0; - - REG_UPDATE_6(DSCL_2TAP_CONTROL, - SCL_H_2TAP_HARDCODE_COEF_EN, h_2tap_hardcode_coef_en, - SCL_H_2TAP_SHARP_EN, h_2tap_sharp_en, - SCL_H_2TAP_SHARP_FACTOR, h_2tap_sharp_factor, - SCL_V_2TAP_HARDCODE_COEF_EN, v_2tap_hardcode_coef_en, - SCL_V_2TAP_SHARP_EN, v_2tap_sharp_en, - SCL_V_2TAP_SHARP_FACTOR, v_2tap_sharp_factor); - - if (!v_2tap_hardcode_coef_en || !h_2tap_hardcode_coef_en) { - bool filter_updated = false; - - filter_h = get_filter_coeffs_64p( - scl_data->taps.h_taps, scl_data->ratios.horz); - filter_v = get_filter_coeffs_64p( - scl_data->taps.v_taps, scl_data->ratios.vert); - - filter_updated = (filter_h && (filter_h != xfm->filter_h)) - || (filter_v && (filter_v != xfm->filter_v)); - - if (chroma_coef_mode) { - filter_h_c = get_filter_coeffs_64p( - scl_data->taps.h_taps_c, scl_data->ratios.horz_c); - filter_v_c = get_filter_coeffs_64p( - scl_data->taps.v_taps_c, scl_data->ratios.vert_c); - filter_updated = filter_updated || (filter_h_c && (filter_h_c != xfm->filter_h_c)) - || (filter_v_c && (filter_v_c != xfm->filter_v_c)); - } - - if (filter_updated) { - uint32_t scl_mode = REG_READ(SCL_MODE); - - if (!h_2tap_hardcode_coef_en && filter_h) { - transform_set_scaler_filter( - xfm, scl_data->taps.h_taps, - SCL_COEF_LUMA_HORZ_FILTER, filter_h); - } - xfm->filter_h = filter_h; - if (!v_2tap_hardcode_coef_en && filter_v) { - transform_set_scaler_filter( - xfm, scl_data->taps.v_taps, - SCL_COEF_LUMA_VERT_FILTER, filter_v); - } - xfm->filter_v = filter_v; - if (chroma_coef_mode) { - if (!h_2tap_hardcode_coef_en && filter_h_c) { - transform_set_scaler_filter( - xfm, scl_data->taps.h_taps_c, - SCL_COEF_CHROMA_HORZ_FILTER, filter_h_c); - } - if (!v_2tap_hardcode_coef_en && filter_v_c) { - transform_set_scaler_filter( - xfm, scl_data->taps.v_taps_c, - SCL_COEF_CHROMA_VERT_FILTER, filter_v_c); - } - } - xfm->filter_h_c = filter_h_c; - xfm->filter_v_c = filter_v_c; - - coef_ram_current = get_reg_field_value_ex( - scl_mode, xfm->tf_mask->SCL_COEF_RAM_SELECT_CURRENT, - xfm->tf_shift->SCL_COEF_RAM_SELECT_CURRENT); - - /* Swap coefficient RAM and set chroma coefficient mode */ - REG_SET_2(SCL_MODE, scl_mode, - SCL_COEF_RAM_SELECT, !coef_ram_current, - SCL_CHROMA_COEF_MODE, chroma_coef_mode); - } - } -} - -static void transform_set_viewport( - struct dcn10_transform *xfm, - const struct rect *viewport, - const struct rect *viewport_c) -{ - REG_SET_2(DCSURF_PRI_VIEWPORT_DIMENSION, 0, - PRI_VIEWPORT_WIDTH, viewport->width, - PRI_VIEWPORT_HEIGHT, viewport->height); - - REG_SET_2(DCSURF_PRI_VIEWPORT_START, 0, - PRI_VIEWPORT_X_START, viewport->x, - PRI_VIEWPORT_Y_START, viewport->y); - - /*for stereo*/ - REG_SET_2(DCSURF_SEC_VIEWPORT_DIMENSION, 0, - SEC_VIEWPORT_WIDTH, viewport->width, - SEC_VIEWPORT_HEIGHT, viewport->height); - - REG_SET_2(DCSURF_SEC_VIEWPORT_START, 0, - SEC_VIEWPORT_X_START, viewport->x, - SEC_VIEWPORT_Y_START, viewport->y); - - /* DC supports NV12 only at the moment */ - REG_SET_2(DCSURF_PRI_VIEWPORT_DIMENSION_C, 0, - PRI_VIEWPORT_WIDTH_C, viewport_c->width, - PRI_VIEWPORT_HEIGHT_C, viewport_c->height); - - REG_SET_2(DCSURF_PRI_VIEWPORT_START_C, 0, - PRI_VIEWPORT_X_START_C, viewport_c->x, - PRI_VIEWPORT_Y_START_C, viewport_c->y); -} - -static int get_lb_depth_bpc(enum lb_pixel_depth depth) -{ - if (depth == LB_PIXEL_DEPTH_30BPP) - return 10; - else if (depth == LB_PIXEL_DEPTH_24BPP) - return 8; - else if (depth == LB_PIXEL_DEPTH_18BPP) - return 6; - else if (depth == LB_PIXEL_DEPTH_36BPP) - return 12; - else { - BREAK_TO_DEBUGGER(); - return -1; /* Unsupported */ - } -} - -static void calc_lb_num_partitions( - const struct scaler_data *scl_data, - enum lb_memory_config lb_config, - int *num_part_y, - int *num_part_c) -{ - int line_size = scl_data->viewport.width < scl_data->recout.width ? - scl_data->viewport.width : scl_data->recout.width; - int line_size_c = scl_data->viewport_c.width < scl_data->recout.width ? - scl_data->viewport_c.width : scl_data->recout.width; - int lb_bpc = get_lb_depth_bpc(scl_data->lb_params.depth); - int memory_line_size_y = (line_size * lb_bpc + 71) / 72; /* +71 to ceil */ - int memory_line_size_c = (line_size_c * lb_bpc + 71) / 72; /* +71 to ceil */ - int memory_line_size_a = (line_size + 5) / 6; /* +5 to ceil */ - int lb_memory_size, lb_memory_size_c, lb_memory_size_a, num_partitions_a; - - if (lb_config == LB_MEMORY_CONFIG_1) { - lb_memory_size = 816; - lb_memory_size_c = 816; - lb_memory_size_a = 984; - } else if (lb_config == LB_MEMORY_CONFIG_2) { - lb_memory_size = 1088; - lb_memory_size_c = 1088; - lb_memory_size_a = 1312; - } else if (lb_config == LB_MEMORY_CONFIG_3) { - lb_memory_size = 816 + 1088 + 848 + 848 + 848; - lb_memory_size_c = 816 + 1088; - lb_memory_size_a = 984 + 1312 + 456; - } else { - lb_memory_size = 816 + 1088 + 848; - lb_memory_size_c = 816 + 1088 + 848; - lb_memory_size_a = 984 + 1312 + 456; - } - *num_part_y = lb_memory_size / memory_line_size_y; - *num_part_c = lb_memory_size_c / memory_line_size_c; - num_partitions_a = lb_memory_size_a / memory_line_size_a; - - if (scl_data->lb_params.alpha_en - && (num_partitions_a < *num_part_y)) - *num_part_y = num_partitions_a; - - if (*num_part_y > 64) - *num_part_y = 64; - if (*num_part_c > 64) - *num_part_c = 64; - -} - -static bool is_lb_conf_valid(int ceil_vratio, int num_partitions, int vtaps) -{ - if (ceil_vratio > 2) - return vtaps <= (num_partitions - ceil_vratio + 2); - else - return vtaps <= num_partitions; -} - -/*find first match configuration which meets the min required lb size*/ -static enum lb_memory_config find_lb_memory_config(const struct scaler_data *scl_data) -{ - int num_part_y, num_part_c; - int vtaps = scl_data->taps.v_taps; - int vtaps_c = scl_data->taps.v_taps_c; - int ceil_vratio = dal_fixed31_32_ceil(scl_data->ratios.vert); - int ceil_vratio_c = dal_fixed31_32_ceil(scl_data->ratios.vert_c); - - calc_lb_num_partitions( - scl_data, LB_MEMORY_CONFIG_1, &num_part_y, &num_part_c); - - if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) - && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)) - return LB_MEMORY_CONFIG_1; - - calc_lb_num_partitions( - scl_data, LB_MEMORY_CONFIG_2, &num_part_y, &num_part_c); - - if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) - && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)) - return LB_MEMORY_CONFIG_2; - - if (scl_data->format == PIXEL_FORMAT_420BPP8 - || scl_data->format == PIXEL_FORMAT_420BPP10) { - calc_lb_num_partitions( - scl_data, LB_MEMORY_CONFIG_3, &num_part_y, &num_part_c); - - if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) - && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)) - return LB_MEMORY_CONFIG_3; - } - - calc_lb_num_partitions( - scl_data, LB_MEMORY_CONFIG_0, &num_part_y, &num_part_c); - - /*Ensure we can support the requested number of vtaps*/ - ASSERT(is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) - && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)); - - return LB_MEMORY_CONFIG_0; -} - -void transform_set_scaler_auto_scale( - struct transform *xfm_base, - const struct scaler_data *scl_data) -{ - enum lb_memory_config lb_config; - struct dcn10_transform *xfm = TO_DCN10_TRANSFORM(xfm_base); - enum dscl_mode_sel dscl_mode = get_dscl_mode( - scl_data, xfm_base->ctx->dc->debug.always_scale); - bool ycbcr = scl_data->format >= PIXEL_FORMAT_VIDEO_BEGIN - && scl_data->format <= PIXEL_FORMAT_VIDEO_END; - - transform_set_overscan(xfm, scl_data); - - transform_set_otg_blank(xfm, scl_data); - - REG_UPDATE(SCL_MODE, DSCL_MODE, dscl_mode); - - transform_set_viewport(xfm, &scl_data->viewport, &scl_data->viewport_c); - - if (dscl_mode == DSCL_MODE_DSCL_BYPASS) - return; - - lb_config = find_lb_memory_config(scl_data); - xfmn10_set_lb(xfm, &scl_data->lb_params, lb_config); - - if (dscl_mode == DSCL_MODE_SCALING_444_BYPASS) - return; - - /* TODO: v_min */ - REG_SET_3(DSCL_AUTOCAL, 0, - AUTOCAL_MODE, AUTOCAL_MODE_AUTOSCALE, - AUTOCAL_NUM_PIPE, 0, - AUTOCAL_PIPE_ID, 0); - - /* Black offsets */ - if (ycbcr) - REG_SET_2(SCL_BLACK_OFFSET, 0, - SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y, - SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_CBCR); - else - - REG_SET_2(SCL_BLACK_OFFSET, 0, - SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y, - SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_RGB_Y); - - REG_SET_4(SCL_TAP_CONTROL, 0, - SCL_V_NUM_TAPS, scl_data->taps.v_taps - 1, - SCL_H_NUM_TAPS, scl_data->taps.h_taps - 1, - SCL_V_NUM_TAPS_C, scl_data->taps.v_taps_c - 1, - SCL_H_NUM_TAPS_C, scl_data->taps.h_taps_c - 1); - - transform_set_scl_filter(xfm, scl_data, ycbcr); -} - -/* Program gamut remap in bypass mode */ -void transform_set_gamut_remap_bypass(struct dcn10_transform *xfm) -{ - REG_SET(CM_GAMUT_REMAP_CONTROL, 0, - CM_GAMUT_REMAP_MODE, 0); - /* Gamut remap in bypass */ -} - -static void transform_set_recout( - struct dcn10_transform *xfm, const struct rect *recout) -{ - REG_SET_2(RECOUT_START, 0, - /* First pixel of RECOUT */ - RECOUT_START_X, recout->x, - /* First line of RECOUT */ - RECOUT_START_Y, recout->y); - - REG_SET_2(RECOUT_SIZE, 0, - /* Number of RECOUT horizontal pixels */ - RECOUT_WIDTH, recout->width, - /* Number of RECOUT vertical lines */ - RECOUT_HEIGHT, recout->height - - xfm->base.ctx->dc->debug.surface_visual_confirm * 4 * - (xfm->base.inst + 1)); -} - -static void transform_set_manual_ratio_init( - struct dcn10_transform *xfm, const struct scaler_data *data) -{ - uint32_t init_frac = 0; - uint32_t init_int = 0; - - REG_SET(SCL_HORZ_FILTER_SCALE_RATIO, 0, - SCL_H_SCALE_RATIO, dal_fixed31_32_u2d19(data->ratios.horz) << 5); - - REG_SET(SCL_VERT_FILTER_SCALE_RATIO, 0, - SCL_V_SCALE_RATIO, dal_fixed31_32_u2d19(data->ratios.vert) << 5); - - REG_SET(SCL_HORZ_FILTER_SCALE_RATIO_C, 0, - SCL_H_SCALE_RATIO_C, dal_fixed31_32_u2d19(data->ratios.horz_c) << 5); - - REG_SET(SCL_VERT_FILTER_SCALE_RATIO_C, 0, - SCL_V_SCALE_RATIO_C, dal_fixed31_32_u2d19(data->ratios.vert_c) << 5); - - /* - * 0.24 format for fraction, first five bits zeroed - */ - init_frac = dal_fixed31_32_u0d19(data->inits.h) << 5; - init_int = dal_fixed31_32_floor(data->inits.h); - REG_SET_2(SCL_HORZ_FILTER_INIT, 0, - SCL_H_INIT_FRAC, init_frac, - SCL_H_INIT_INT, init_int); - - init_frac = dal_fixed31_32_u0d19(data->inits.h_c) << 5; - init_int = dal_fixed31_32_floor(data->inits.h_c); - REG_SET_2(SCL_HORZ_FILTER_INIT_C, 0, - SCL_H_INIT_FRAC_C, init_frac, - SCL_H_INIT_INT_C, init_int); - - init_frac = dal_fixed31_32_u0d19(data->inits.v) << 5; - init_int = dal_fixed31_32_floor(data->inits.v); - REG_SET_2(SCL_VERT_FILTER_INIT, 0, - SCL_V_INIT_FRAC, init_frac, - SCL_V_INIT_INT, init_int); - - init_frac = dal_fixed31_32_u0d19(data->inits.v_bot) << 5; - init_int = dal_fixed31_32_floor(data->inits.v_bot); - REG_SET_2(SCL_VERT_FILTER_INIT_BOT, 0, - SCL_V_INIT_FRAC_BOT, init_frac, - SCL_V_INIT_INT_BOT, init_int); - - init_frac = dal_fixed31_32_u0d19(data->inits.v_c) << 5; - init_int = dal_fixed31_32_floor(data->inits.v_c); - REG_SET_2(SCL_VERT_FILTER_INIT_C, 0, - SCL_V_INIT_FRAC_C, init_frac, - SCL_V_INIT_INT_C, init_int); - - init_frac = dal_fixed31_32_u0d19(data->inits.v_c_bot) << 5; - init_int = dal_fixed31_32_floor(data->inits.v_c_bot); - REG_SET_2(SCL_VERT_FILTER_INIT_BOT_C, 0, - SCL_V_INIT_FRAC_BOT_C, init_frac, - SCL_V_INIT_INT_BOT_C, init_int); -} - -/* Main function to program scaler and line buffer in manual scaling mode */ -static void xfmn10_set_scaler_manual_scale( - struct transform *xfm_base, - const struct scaler_data *scl_data) -{ - enum lb_memory_config lb_config; - struct dcn10_transform *xfm = TO_DCN10_TRANSFORM(xfm_base); - enum dscl_mode_sel dscl_mode = get_dscl_mode( - scl_data, xfm_base->ctx->dc->debug.always_scale); - bool ycbcr = scl_data->format >= PIXEL_FORMAT_VIDEO_BEGIN - && scl_data->format <= PIXEL_FORMAT_VIDEO_END; - - /* Recout */ - transform_set_recout(xfm, &scl_data->recout); - - /* MPC Size */ - REG_SET_2(MPC_SIZE, 0, - /* Number of horizontal pixels of MPC */ - MPC_WIDTH, scl_data->h_active, - /* Number of vertical lines of MPC */ - MPC_HEIGHT, scl_data->v_active); - - /* SCL mode */ - REG_UPDATE(SCL_MODE, DSCL_MODE, dscl_mode); - - /* Viewport */ - transform_set_viewport(xfm, &scl_data->viewport, &scl_data->viewport_c); - - if (dscl_mode == DSCL_MODE_DSCL_BYPASS) - return; - /* LB */ - lb_config = find_lb_memory_config(scl_data); - xfmn10_set_lb(xfm, &scl_data->lb_params, lb_config); - - if (dscl_mode == DSCL_MODE_SCALING_444_BYPASS) - return; - - /* Autocal off */ - REG_SET_3(DSCL_AUTOCAL, 0, - AUTOCAL_MODE, AUTOCAL_MODE_OFF, - AUTOCAL_NUM_PIPE, 0, - AUTOCAL_PIPE_ID, 0); - - /* Black offsets */ - if (ycbcr) - REG_SET_2(SCL_BLACK_OFFSET, 0, - SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y, - SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_CBCR); - else - - REG_SET_2(SCL_BLACK_OFFSET, 0, - SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y, - SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_RGB_Y); - - /* Manually calculate scale ratio and init values */ - transform_set_manual_ratio_init(xfm, scl_data); - - /* HTaps/VTaps */ - REG_SET_4(SCL_TAP_CONTROL, 0, - SCL_V_NUM_TAPS, scl_data->taps.v_taps - 1, - SCL_H_NUM_TAPS, scl_data->taps.h_taps - 1, - SCL_V_NUM_TAPS_C, scl_data->taps.v_taps_c - 1, - SCL_H_NUM_TAPS_C, scl_data->taps.h_taps_c - 1); - - transform_set_scl_filter(xfm, scl_data, ycbcr); -} - -#define IDENTITY_RATIO(ratio) (dal_fixed31_32_u2d19(ratio) == (1 << 19)) - - -static bool transform_get_optimal_number_of_taps( - struct transform *xfm, - struct scaler_data *scl_data, - const struct scaling_taps *in_taps) -{ - uint32_t pixel_width; - - if (scl_data->viewport.width > scl_data->recout.width) - pixel_width = scl_data->recout.width; - else - pixel_width = scl_data->viewport.width; - - /* TODO: add lb check */ - - /* No support for programming ratio of 4, drop to 3.99999.. */ - if (scl_data->ratios.horz.value == (4ll << 32)) - scl_data->ratios.horz.value--; - if (scl_data->ratios.vert.value == (4ll << 32)) - scl_data->ratios.vert.value--; - if (scl_data->ratios.horz_c.value == (4ll << 32)) - scl_data->ratios.horz_c.value--; - if (scl_data->ratios.vert_c.value == (4ll << 32)) - scl_data->ratios.vert_c.value--; - - /* Set default taps if none are provided */ - if (in_taps->h_taps == 0) - scl_data->taps.h_taps = 4; - else - scl_data->taps.h_taps = in_taps->h_taps; - if (in_taps->v_taps == 0) - scl_data->taps.v_taps = 4; - else - scl_data->taps.v_taps = in_taps->v_taps; - if (in_taps->v_taps_c == 0) - scl_data->taps.v_taps_c = 2; - else - scl_data->taps.v_taps_c = in_taps->v_taps_c; - if (in_taps->h_taps_c == 0) - scl_data->taps.h_taps_c = 2; - /* Only 1 and even h_taps_c are supported by hw */ - else if ((in_taps->h_taps_c % 2) != 0 && in_taps->h_taps_c != 1) - scl_data->taps.h_taps_c = in_taps->h_taps_c - 1; - else - scl_data->taps.h_taps_c = in_taps->h_taps_c; - - if (!xfm->ctx->dc->debug.always_scale) { - if (IDENTITY_RATIO(scl_data->ratios.horz)) - scl_data->taps.h_taps = 1; - if (IDENTITY_RATIO(scl_data->ratios.vert)) - scl_data->taps.v_taps = 1; - if (IDENTITY_RATIO(scl_data->ratios.horz_c)) - scl_data->taps.h_taps_c = 1; - if (IDENTITY_RATIO(scl_data->ratios.vert_c)) - scl_data->taps.v_taps_c = 1; - } - - return true; -} - -static void transform_reset(struct transform *xfm_base) -{ - struct dcn10_transform *xfm = TO_DCN10_TRANSFORM(xfm_base); - - xfm->filter_h_c = NULL; - xfm->filter_v_c = NULL; - xfm->filter_h = NULL; - xfm->filter_v = NULL; - - /* set boundary mode to 0 */ - REG_SET(DSCL_CONTROL, 0, SCL_BOUNDARY_MODE, 0); -} - -static void program_gamut_remap( - struct dcn10_transform *xfm, - const uint16_t *regval, - enum gamut_remap_select select) -{ - uint16_t selection = 0; - - if (regval == NULL || select == GAMUT_REMAP_BYPASS) { - REG_SET(CM_GAMUT_REMAP_CONTROL, 0, - CM_GAMUT_REMAP_MODE, 0); - return; - } - switch (select) { - case GAMUT_REMAP_COEFF: - selection = 1; - break; - case GAMUT_REMAP_COMA_COEFF: - selection = 2; - break; - case GAMUT_REMAP_COMB_COEFF: - selection = 3; - break; - default: - break; - } - - - if (select == GAMUT_REMAP_COEFF) { - - REG_SET_2(CM_GAMUT_REMAP_C11_C12, 0, - CM_GAMUT_REMAP_C11, regval[0], - CM_GAMUT_REMAP_C12, regval[1]); - regval += 2; - REG_SET_2(CM_GAMUT_REMAP_C13_C14, 0, - CM_GAMUT_REMAP_C13, regval[0], - CM_GAMUT_REMAP_C14, regval[1]); - regval += 2; - REG_SET_2(CM_GAMUT_REMAP_C21_C22, 0, - CM_GAMUT_REMAP_C21, regval[0], - CM_GAMUT_REMAP_C22, regval[1]); - regval += 2; - REG_SET_2(CM_GAMUT_REMAP_C23_C24, 0, - CM_GAMUT_REMAP_C23, regval[0], - CM_GAMUT_REMAP_C24, regval[1]); - regval += 2; - REG_SET_2(CM_GAMUT_REMAP_C31_C32, 0, - CM_GAMUT_REMAP_C31, regval[0], - CM_GAMUT_REMAP_C32, regval[1]); - regval += 2; - REG_SET_2(CM_GAMUT_REMAP_C33_C34, 0, - CM_GAMUT_REMAP_C33, regval[0], - CM_GAMUT_REMAP_C34, regval[1]); - - } else if (select == GAMUT_REMAP_COMA_COEFF) { - REG_SET_2(CM_COMA_C11_C12, 0, - CM_COMA_C11, regval[0], - CM_COMA_C12, regval[1]); - regval += 2; - REG_SET_2(CM_COMA_C13_C14, 0, - CM_COMA_C13, regval[0], - CM_COMA_C14, regval[1]); - regval += 2; - REG_SET_2(CM_COMA_C21_C22, 0, - CM_COMA_C21, regval[0], - CM_COMA_C22, regval[1]); - regval += 2; - REG_SET_2(CM_COMA_C23_C24, 0, - CM_COMA_C23, regval[0], - CM_COMA_C24, regval[1]); - regval += 2; - REG_SET_2(CM_COMA_C31_C32, 0, - CM_COMA_C31, regval[0], - CM_COMA_C32, regval[1]); - regval += 2; - REG_SET_2(CM_COMA_C33_C34, 0, - CM_COMA_C33, regval[0], - CM_COMA_C34, regval[1]); - - } else { - REG_SET_2(CM_COMB_C11_C12, 0, - CM_COMB_C11, regval[0], - CM_COMB_C12, regval[1]); - regval += 2; - REG_SET_2(CM_COMB_C13_C14, 0, - CM_COMB_C13, regval[0], - CM_COMB_C14, regval[1]); - regval += 2; - REG_SET_2(CM_COMB_C21_C22, 0, - CM_COMB_C21, regval[0], - CM_COMB_C22, regval[1]); - regval += 2; - REG_SET_2(CM_COMB_C23_C24, 0, - CM_COMB_C23, regval[0], - CM_COMB_C24, regval[1]); - regval += 2; - REG_SET_2(CM_COMB_C31_C32, 0, - CM_COMB_C31, regval[0], - CM_COMB_C32, regval[1]); - regval += 2; - REG_SET_2(CM_COMB_C33_C34, 0, - CM_COMB_C33, regval[0], - CM_COMB_C34, regval[1]); - } - - REG_SET( - CM_GAMUT_REMAP_CONTROL, 0, - CM_GAMUT_REMAP_MODE, selection); - -} - -static void dcn_transform_set_gamut_remap( - struct transform *xfm, - const struct xfm_grph_csc_adjustment *adjust) -{ - struct dcn10_transform *dcn_xfm = TO_DCN10_TRANSFORM(xfm); - - if (adjust->gamut_adjust_type != GRAPHICS_GAMUT_ADJUST_TYPE_SW) - /* Bypass if type is bypass or hw */ - program_gamut_remap(dcn_xfm, NULL, GAMUT_REMAP_BYPASS); - else { - struct fixed31_32 arr_matrix[12]; - uint16_t arr_reg_val[12]; - - arr_matrix[0] = adjust->temperature_matrix[0]; - arr_matrix[1] = adjust->temperature_matrix[1]; - arr_matrix[2] = adjust->temperature_matrix[2]; - arr_matrix[3] = dal_fixed31_32_zero; - - arr_matrix[4] = adjust->temperature_matrix[3]; - arr_matrix[5] = adjust->temperature_matrix[4]; - arr_matrix[6] = adjust->temperature_matrix[5]; - arr_matrix[7] = dal_fixed31_32_zero; - - arr_matrix[8] = adjust->temperature_matrix[6]; - arr_matrix[9] = adjust->temperature_matrix[7]; - arr_matrix[10] = adjust->temperature_matrix[8]; - arr_matrix[11] = dal_fixed31_32_zero; - - convert_float_matrix( - arr_reg_val, arr_matrix, 12); - - program_gamut_remap(dcn_xfm, arr_reg_val, GAMUT_REMAP_COEFF); - } -} - -static struct transform_funcs dcn10_transform_funcs = { - - .transform_reset = transform_reset, - .transform_set_scaler = xfmn10_set_scaler_manual_scale, - .transform_get_optimal_number_of_taps = transform_get_optimal_number_of_taps, - .transform_set_gamut_remap = dcn_transform_set_gamut_remap, -}; - -/*****************************************/ -/* Constructor, Destructor */ -/*****************************************/ - -bool dcn10_transform_construct( - struct dcn10_transform *xfm, - struct dc_context *ctx, - uint32_t inst, - const struct dcn_transform_registers *tf_regs, - const struct dcn_transform_shift *tf_shift, - const struct dcn_transform_mask *tf_mask) -{ - xfm->base.ctx = ctx; - - xfm->base.inst = inst; - xfm->base.funcs = &dcn10_transform_funcs; - - xfm->tf_regs = tf_regs; - xfm->tf_shift = tf_shift; - xfm->tf_mask = tf_mask; - - xfm->lb_pixel_depth_supported = - LB_PIXEL_DEPTH_18BPP | - LB_PIXEL_DEPTH_24BPP | - LB_PIXEL_DEPTH_30BPP; - - xfm->lb_bits_per_entry = LB_BITS_PER_ENTRY; - xfm->lb_memory_size = LB_TOTAL_NUMBER_OF_ENTRIES; /*0x1404*/ - - return true; -} diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.h deleted file mode 100644 index 8df74cc153f5..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.h +++ /dev/null @@ -1,421 +0,0 @@ -/* Copyright 2016 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DAL_TRANSFORM_DCN10_H__ -#define __DAL_TRANSFORM_DCN10_H__ - -#include "transform.h" - -#define TO_DCN10_TRANSFORM(transform)\ - container_of(transform, struct dcn10_transform, base) - -/* TODO: Use correct number of taps. Using polaris values for now */ -#define LB_TOTAL_NUMBER_OF_ENTRIES 5124 -#define LB_BITS_PER_ENTRY 144 - -#define TF_SF(reg_name, field_name, post_fix)\ - .field_name = reg_name ## __ ## field_name ## post_fix - -#define TF_REG_LIST_DCN(id) \ - SRI(CM_GAMUT_REMAP_CONTROL, CM, id),\ - SRI(CM_GAMUT_REMAP_C11_C12, CM, id),\ - SRI(CM_GAMUT_REMAP_C13_C14, CM, id),\ - SRI(CM_GAMUT_REMAP_C21_C22, CM, id),\ - SRI(CM_GAMUT_REMAP_C23_C24, CM, id),\ - SRI(CM_GAMUT_REMAP_C31_C32, CM, id),\ - SRI(CM_GAMUT_REMAP_C33_C34, CM, id),\ - SRI(DSCL_EXT_OVERSCAN_LEFT_RIGHT, DSCL, id), \ - SRI(DSCL_EXT_OVERSCAN_TOP_BOTTOM, DSCL, id), \ - SRI(OTG_H_BLANK, DSCL, id), \ - SRI(OTG_V_BLANK, DSCL, id), \ - SRI(SCL_MODE, DSCL, id), \ - SRI(LB_DATA_FORMAT, DSCL, id), \ - SRI(LB_MEMORY_CTRL, DSCL, id), \ - SRI(DSCL_AUTOCAL, DSCL, id), \ - SRI(SCL_BLACK_OFFSET, DSCL, id), \ - SRI(DSCL_CONTROL, DSCL, id), \ - SRI(SCL_TAP_CONTROL, DSCL, id), \ - SRI(SCL_COEF_RAM_TAP_SELECT, DSCL, id), \ - SRI(SCL_COEF_RAM_TAP_DATA, DSCL, id), \ - SRI(DSCL_2TAP_CONTROL, DSCL, id), \ - SRI(DCSURF_PRI_VIEWPORT_DIMENSION, HUBP, id), \ - SRI(DCSURF_PRI_VIEWPORT_START, HUBP, id), \ - SRI(DCSURF_SEC_VIEWPORT_DIMENSION, HUBP, id), \ - SRI(DCSURF_SEC_VIEWPORT_START, HUBP, id), \ - SRI(DCSURF_PRI_VIEWPORT_DIMENSION_C, HUBP, id), \ - SRI(DCSURF_PRI_VIEWPORT_START_C, HUBP, id), \ - SRI(MPC_SIZE, DSCL, id), \ - SRI(SCL_HORZ_FILTER_SCALE_RATIO, DSCL, id), \ - SRI(SCL_VERT_FILTER_SCALE_RATIO, DSCL, id), \ - SRI(SCL_HORZ_FILTER_SCALE_RATIO_C, DSCL, id), \ - SRI(SCL_VERT_FILTER_SCALE_RATIO_C, DSCL, id), \ - SRI(SCL_HORZ_FILTER_INIT, DSCL, id), \ - SRI(SCL_HORZ_FILTER_INIT_C, DSCL, id), \ - SRI(SCL_VERT_FILTER_INIT, DSCL, id), \ - SRI(SCL_VERT_FILTER_INIT_BOT, DSCL, id), \ - SRI(SCL_VERT_FILTER_INIT_C, DSCL, id), \ - SRI(SCL_VERT_FILTER_INIT_BOT_C, DSCL, id), \ - SRI(RECOUT_START, DSCL, id), \ - SRI(RECOUT_SIZE, DSCL, id) - -#define TF_REG_LIST_DCN10(id) \ - TF_REG_LIST_DCN(id), \ - SRI(CM_COMA_C11_C12, CM, id),\ - SRI(CM_COMA_C13_C14, CM, id),\ - SRI(CM_COMA_C21_C22, CM, id),\ - SRI(CM_COMA_C23_C24, CM, id),\ - SRI(CM_COMA_C31_C32, CM, id),\ - SRI(CM_COMA_C33_C34, CM, id),\ - SRI(CM_COMB_C11_C12, CM, id),\ - SRI(CM_COMB_C13_C14, CM, id),\ - SRI(CM_COMB_C21_C22, CM, id),\ - SRI(CM_COMB_C23_C24, CM, id),\ - SRI(CM_COMB_C31_C32, CM, id),\ - SRI(CM_COMB_C33_C34, CM, id) - -#define TF_REG_LIST_SH_MASK_DCN(mask_sh)\ - TF_SF(CM0_CM_GAMUT_REMAP_CONTROL, CM_GAMUT_REMAP_MODE, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C11_C12, CM_GAMUT_REMAP_C11, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C11_C12, CM_GAMUT_REMAP_C12, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C13_C14, CM_GAMUT_REMAP_C13, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C13_C14, CM_GAMUT_REMAP_C14, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C21_C22, CM_GAMUT_REMAP_C21, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C21_C22, CM_GAMUT_REMAP_C22, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C23_C24, CM_GAMUT_REMAP_C23, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C23_C24, CM_GAMUT_REMAP_C24, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C31_C32, CM_GAMUT_REMAP_C31, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C31_C32, CM_GAMUT_REMAP_C32, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C33_C34, CM_GAMUT_REMAP_C33, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C33_C34, CM_GAMUT_REMAP_C34, mask_sh),\ - TF_SF(DSCL0_DSCL_EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_LEFT, mask_sh),\ - TF_SF(DSCL0_DSCL_EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_RIGHT, mask_sh),\ - TF_SF(DSCL0_DSCL_EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_BOTTOM, mask_sh),\ - TF_SF(DSCL0_DSCL_EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_TOP, mask_sh),\ - TF_SF(DSCL0_OTG_H_BLANK, OTG_H_BLANK_START, mask_sh),\ - TF_SF(DSCL0_OTG_H_BLANK, OTG_H_BLANK_END, mask_sh),\ - TF_SF(DSCL0_OTG_V_BLANK, OTG_V_BLANK_START, mask_sh),\ - TF_SF(DSCL0_OTG_V_BLANK, OTG_V_BLANK_END, mask_sh),\ - TF_SF(DSCL0_LB_DATA_FORMAT, INTERLEAVE_EN, mask_sh),\ - TF_SF(DSCL0_LB_DATA_FORMAT, ALPHA_EN, mask_sh),\ - TF_SF(DSCL0_LB_MEMORY_CTRL, MEMORY_CONFIG, mask_sh),\ - TF_SF(DSCL0_LB_MEMORY_CTRL, LB_MAX_PARTITIONS, mask_sh),\ - TF_SF(DSCL0_DSCL_AUTOCAL, AUTOCAL_MODE, mask_sh),\ - TF_SF(DSCL0_DSCL_AUTOCAL, AUTOCAL_NUM_PIPE, mask_sh),\ - TF_SF(DSCL0_DSCL_AUTOCAL, AUTOCAL_PIPE_ID, mask_sh),\ - TF_SF(DSCL0_SCL_BLACK_OFFSET, SCL_BLACK_OFFSET_RGB_Y, mask_sh),\ - TF_SF(DSCL0_SCL_BLACK_OFFSET, SCL_BLACK_OFFSET_CBCR, mask_sh),\ - TF_SF(DSCL0_DSCL_CONTROL, SCL_BOUNDARY_MODE, mask_sh),\ - TF_SF(DSCL0_SCL_TAP_CONTROL, SCL_V_NUM_TAPS, mask_sh),\ - TF_SF(DSCL0_SCL_TAP_CONTROL, SCL_H_NUM_TAPS, mask_sh),\ - TF_SF(DSCL0_SCL_TAP_CONTROL, SCL_V_NUM_TAPS_C, mask_sh),\ - TF_SF(DSCL0_SCL_TAP_CONTROL, SCL_H_NUM_TAPS_C, mask_sh),\ - TF_SF(DSCL0_SCL_COEF_RAM_TAP_SELECT, SCL_COEF_RAM_TAP_PAIR_IDX, mask_sh),\ - TF_SF(DSCL0_SCL_COEF_RAM_TAP_SELECT, SCL_COEF_RAM_PHASE, mask_sh),\ - TF_SF(DSCL0_SCL_COEF_RAM_TAP_SELECT, SCL_COEF_RAM_FILTER_TYPE, mask_sh),\ - TF_SF(DSCL0_SCL_COEF_RAM_TAP_DATA, SCL_COEF_RAM_EVEN_TAP_COEF, mask_sh),\ - TF_SF(DSCL0_SCL_COEF_RAM_TAP_DATA, SCL_COEF_RAM_EVEN_TAP_COEF_EN, mask_sh),\ - TF_SF(DSCL0_SCL_COEF_RAM_TAP_DATA, SCL_COEF_RAM_ODD_TAP_COEF, mask_sh),\ - TF_SF(DSCL0_SCL_COEF_RAM_TAP_DATA, SCL_COEF_RAM_ODD_TAP_COEF_EN, mask_sh),\ - TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_H_2TAP_HARDCODE_COEF_EN, mask_sh),\ - TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_H_2TAP_SHARP_EN, mask_sh),\ - TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_H_2TAP_SHARP_FACTOR, mask_sh),\ - TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_V_2TAP_HARDCODE_COEF_EN, mask_sh),\ - TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_V_2TAP_SHARP_EN, mask_sh),\ - TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_V_2TAP_SHARP_FACTOR, mask_sh),\ - TF_SF(DSCL0_SCL_MODE, SCL_COEF_RAM_SELECT, mask_sh),\ - TF_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION, PRI_VIEWPORT_WIDTH, mask_sh),\ - TF_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION, PRI_VIEWPORT_HEIGHT, mask_sh),\ - TF_SF(HUBP0_DCSURF_PRI_VIEWPORT_START, PRI_VIEWPORT_X_START, mask_sh),\ - TF_SF(HUBP0_DCSURF_PRI_VIEWPORT_START, PRI_VIEWPORT_Y_START, mask_sh),\ - TF_SF(HUBP0_DCSURF_SEC_VIEWPORT_DIMENSION, SEC_VIEWPORT_WIDTH, mask_sh),\ - TF_SF(HUBP0_DCSURF_SEC_VIEWPORT_DIMENSION, SEC_VIEWPORT_HEIGHT, mask_sh),\ - TF_SF(HUBP0_DCSURF_SEC_VIEWPORT_START, SEC_VIEWPORT_X_START, mask_sh),\ - TF_SF(HUBP0_DCSURF_SEC_VIEWPORT_START, SEC_VIEWPORT_Y_START, mask_sh),\ - TF_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION_C, PRI_VIEWPORT_WIDTH_C, mask_sh),\ - TF_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION_C, PRI_VIEWPORT_HEIGHT_C, mask_sh),\ - TF_SF(HUBP0_DCSURF_PRI_VIEWPORT_START_C, PRI_VIEWPORT_X_START_C, mask_sh),\ - TF_SF(HUBP0_DCSURF_PRI_VIEWPORT_START_C, PRI_VIEWPORT_Y_START_C, mask_sh),\ - TF_SF(DSCL0_SCL_MODE, DSCL_MODE, mask_sh),\ - TF_SF(DSCL0_RECOUT_START, RECOUT_START_X, mask_sh),\ - TF_SF(DSCL0_RECOUT_START, RECOUT_START_Y, mask_sh),\ - TF_SF(DSCL0_RECOUT_SIZE, RECOUT_WIDTH, mask_sh),\ - TF_SF(DSCL0_RECOUT_SIZE, RECOUT_HEIGHT, mask_sh),\ - TF_SF(DSCL0_MPC_SIZE, MPC_WIDTH, mask_sh),\ - TF_SF(DSCL0_MPC_SIZE, MPC_HEIGHT, mask_sh),\ - TF_SF(DSCL0_SCL_HORZ_FILTER_SCALE_RATIO, SCL_H_SCALE_RATIO, mask_sh),\ - TF_SF(DSCL0_SCL_VERT_FILTER_SCALE_RATIO, SCL_V_SCALE_RATIO, mask_sh),\ - TF_SF(DSCL0_SCL_HORZ_FILTER_SCALE_RATIO_C, SCL_H_SCALE_RATIO_C, mask_sh),\ - TF_SF(DSCL0_SCL_VERT_FILTER_SCALE_RATIO_C, SCL_V_SCALE_RATIO_C, mask_sh),\ - TF_SF(DSCL0_SCL_HORZ_FILTER_INIT, SCL_H_INIT_FRAC, mask_sh),\ - TF_SF(DSCL0_SCL_HORZ_FILTER_INIT, SCL_H_INIT_INT, mask_sh),\ - TF_SF(DSCL0_SCL_HORZ_FILTER_INIT_C, SCL_H_INIT_FRAC_C, mask_sh),\ - TF_SF(DSCL0_SCL_HORZ_FILTER_INIT_C, SCL_H_INIT_INT_C, mask_sh),\ - TF_SF(DSCL0_SCL_VERT_FILTER_INIT, SCL_V_INIT_FRAC, mask_sh),\ - TF_SF(DSCL0_SCL_VERT_FILTER_INIT, SCL_V_INIT_INT, mask_sh),\ - TF_SF(DSCL0_SCL_VERT_FILTER_INIT_BOT, SCL_V_INIT_FRAC_BOT, mask_sh),\ - TF_SF(DSCL0_SCL_VERT_FILTER_INIT_BOT, SCL_V_INIT_INT_BOT, mask_sh),\ - TF_SF(DSCL0_SCL_VERT_FILTER_INIT_C, SCL_V_INIT_FRAC_C, mask_sh),\ - TF_SF(DSCL0_SCL_VERT_FILTER_INIT_C, SCL_V_INIT_INT_C, mask_sh),\ - TF_SF(DSCL0_SCL_VERT_FILTER_INIT_BOT_C, SCL_V_INIT_FRAC_BOT_C, mask_sh),\ - TF_SF(DSCL0_SCL_VERT_FILTER_INIT_BOT_C, SCL_V_INIT_INT_BOT_C, mask_sh),\ - TF_SF(DSCL0_SCL_MODE, SCL_CHROMA_COEF_MODE, mask_sh),\ - TF_SF(DSCL0_SCL_MODE, SCL_COEF_RAM_SELECT_CURRENT, mask_sh) - -#define TF_REG_LIST_SH_MASK_DCN10(mask_sh)\ - TF_REG_LIST_SH_MASK_DCN(mask_sh),\ - TF_SF(DSCL0_LB_DATA_FORMAT, PIXEL_DEPTH, mask_sh),\ - TF_SF(DSCL0_LB_DATA_FORMAT, PIXEL_EXPAN_MODE, mask_sh),\ - TF_SF(DSCL0_LB_DATA_FORMAT, PIXEL_REDUCE_MODE, mask_sh),\ - TF_SF(DSCL0_LB_DATA_FORMAT, DYNAMIC_PIXEL_DEPTH, mask_sh),\ - TF_SF(DSCL0_LB_DATA_FORMAT, DITHER_EN, mask_sh),\ - TF_SF(CM0_CM_COMA_C11_C12, CM_COMA_C11, mask_sh),\ - TF_SF(CM0_CM_COMA_C11_C12, CM_COMA_C12, mask_sh),\ - TF_SF(CM0_CM_COMA_C13_C14, CM_COMA_C13, mask_sh),\ - TF_SF(CM0_CM_COMA_C13_C14, CM_COMA_C14, mask_sh),\ - TF_SF(CM0_CM_COMA_C21_C22, CM_COMA_C21, mask_sh),\ - TF_SF(CM0_CM_COMA_C21_C22, CM_COMA_C22, mask_sh),\ - TF_SF(CM0_CM_COMA_C23_C24, CM_COMA_C23, mask_sh),\ - TF_SF(CM0_CM_COMA_C23_C24, CM_COMA_C24, mask_sh),\ - TF_SF(CM0_CM_COMA_C31_C32, CM_COMA_C31, mask_sh),\ - TF_SF(CM0_CM_COMA_C31_C32, CM_COMA_C32, mask_sh),\ - TF_SF(CM0_CM_COMA_C33_C34, CM_COMA_C33, mask_sh),\ - TF_SF(CM0_CM_COMA_C33_C34, CM_COMA_C34, mask_sh),\ - TF_SF(CM0_CM_COMB_C11_C12, CM_COMB_C11, mask_sh),\ - TF_SF(CM0_CM_COMB_C11_C12, CM_COMB_C12, mask_sh),\ - TF_SF(CM0_CM_COMB_C13_C14, CM_COMB_C13, mask_sh),\ - TF_SF(CM0_CM_COMB_C13_C14, CM_COMB_C14, mask_sh),\ - TF_SF(CM0_CM_COMB_C21_C22, CM_COMB_C21, mask_sh),\ - TF_SF(CM0_CM_COMB_C21_C22, CM_COMB_C22, mask_sh),\ - TF_SF(CM0_CM_COMB_C23_C24, CM_COMB_C23, mask_sh),\ - TF_SF(CM0_CM_COMB_C23_C24, CM_COMB_C24, mask_sh),\ - TF_SF(CM0_CM_COMB_C31_C32, CM_COMB_C31, mask_sh),\ - TF_SF(CM0_CM_COMB_C33_C34, CM_COMB_C33, mask_sh),\ - TF_SF(CM0_CM_COMB_C31_C32, CM_COMB_C32, mask_sh),\ - TF_SF(CM0_CM_COMB_C33_C34, CM_COMB_C34, mask_sh) - - -#define TF_REG_FIELD_LIST(type) \ - type EXT_OVERSCAN_LEFT; \ - type EXT_OVERSCAN_RIGHT; \ - type EXT_OVERSCAN_BOTTOM; \ - type EXT_OVERSCAN_TOP; \ - type OTG_H_BLANK_START; \ - type OTG_H_BLANK_END; \ - type OTG_V_BLANK_START; \ - type OTG_V_BLANK_END; \ - type PIXEL_DEPTH; \ - type PIXEL_EXPAN_MODE; \ - type PIXEL_REDUCE_MODE; \ - type DYNAMIC_PIXEL_DEPTH; \ - type DITHER_EN; \ - type INTERLEAVE_EN; \ - type ALPHA_EN; \ - type MEMORY_CONFIG; \ - type LB_MAX_PARTITIONS; \ - type AUTOCAL_MODE; \ - type AUTOCAL_NUM_PIPE; \ - type AUTOCAL_PIPE_ID; \ - type SCL_BLACK_OFFSET_RGB_Y; \ - type SCL_BLACK_OFFSET_CBCR; \ - type SCL_BOUNDARY_MODE; \ - type SCL_V_NUM_TAPS; \ - type SCL_H_NUM_TAPS; \ - type SCL_V_NUM_TAPS_C; \ - type SCL_H_NUM_TAPS_C; \ - type SCL_COEF_RAM_TAP_PAIR_IDX; \ - type SCL_COEF_RAM_PHASE; \ - type SCL_COEF_RAM_FILTER_TYPE; \ - type SCL_COEF_RAM_EVEN_TAP_COEF; \ - type SCL_COEF_RAM_EVEN_TAP_COEF_EN; \ - type SCL_COEF_RAM_ODD_TAP_COEF; \ - type SCL_COEF_RAM_ODD_TAP_COEF_EN; \ - type SCL_H_2TAP_HARDCODE_COEF_EN; \ - type SCL_H_2TAP_SHARP_EN; \ - type SCL_H_2TAP_SHARP_FACTOR; \ - type SCL_V_2TAP_HARDCODE_COEF_EN; \ - type SCL_V_2TAP_SHARP_EN; \ - type SCL_V_2TAP_SHARP_FACTOR; \ - type SCL_COEF_RAM_SELECT; \ - type PRI_VIEWPORT_WIDTH; \ - type PRI_VIEWPORT_HEIGHT; \ - type PRI_VIEWPORT_X_START; \ - type PRI_VIEWPORT_Y_START; \ - type SEC_VIEWPORT_WIDTH; \ - type SEC_VIEWPORT_HEIGHT; \ - type SEC_VIEWPORT_X_START; \ - type SEC_VIEWPORT_Y_START; \ - type PRI_VIEWPORT_WIDTH_C; \ - type PRI_VIEWPORT_HEIGHT_C; \ - type PRI_VIEWPORT_X_START_C; \ - type PRI_VIEWPORT_Y_START_C; \ - type DSCL_MODE; \ - type RECOUT_START_X; \ - type RECOUT_START_Y; \ - type RECOUT_WIDTH; \ - type RECOUT_HEIGHT; \ - type MPC_WIDTH; \ - type MPC_HEIGHT; \ - type SCL_H_SCALE_RATIO; \ - type SCL_V_SCALE_RATIO; \ - type SCL_H_SCALE_RATIO_C; \ - type SCL_V_SCALE_RATIO_C; \ - type SCL_H_INIT_FRAC; \ - type SCL_H_INIT_INT; \ - type SCL_H_INIT_FRAC_C; \ - type SCL_H_INIT_INT_C; \ - type SCL_V_INIT_FRAC; \ - type SCL_V_INIT_INT; \ - type SCL_V_INIT_FRAC_BOT; \ - type SCL_V_INIT_INT_BOT; \ - type SCL_V_INIT_FRAC_C; \ - type SCL_V_INIT_INT_C; \ - type SCL_V_INIT_FRAC_BOT_C; \ - type SCL_V_INIT_INT_BOT_C; \ - type SCL_CHROMA_COEF_MODE; \ - type SCL_COEF_RAM_SELECT_CURRENT; \ - type CM_GAMUT_REMAP_MODE; \ - type CM_GAMUT_REMAP_C11; \ - type CM_GAMUT_REMAP_C12; \ - type CM_GAMUT_REMAP_C13; \ - type CM_GAMUT_REMAP_C14; \ - type CM_GAMUT_REMAP_C21; \ - type CM_GAMUT_REMAP_C22; \ - type CM_GAMUT_REMAP_C23; \ - type CM_GAMUT_REMAP_C24; \ - type CM_GAMUT_REMAP_C31; \ - type CM_GAMUT_REMAP_C32; \ - type CM_GAMUT_REMAP_C33; \ - type CM_GAMUT_REMAP_C34; \ - type CM_COMA_C11; \ - type CM_COMA_C12; \ - type CM_COMA_C13; \ - type CM_COMA_C14; \ - type CM_COMA_C21; \ - type CM_COMA_C22; \ - type CM_COMA_C23; \ - type CM_COMA_C24; \ - type CM_COMA_C31; \ - type CM_COMA_C32; \ - type CM_COMA_C33; \ - type CM_COMA_C34; \ - type CM_COMB_C11; \ - type CM_COMB_C12; \ - type CM_COMB_C13; \ - type CM_COMB_C14; \ - type CM_COMB_C21; \ - type CM_COMB_C22; \ - type CM_COMB_C23; \ - type CM_COMB_C24; \ - type CM_COMB_C31; \ - type CM_COMB_C32; \ - type CM_COMB_C33; \ - type CM_COMB_C34 - -struct dcn_transform_shift { - TF_REG_FIELD_LIST(uint8_t); -}; - -struct dcn_transform_mask { - TF_REG_FIELD_LIST(uint32_t); -}; - -struct dcn_transform_registers { - uint32_t DSCL_EXT_OVERSCAN_LEFT_RIGHT; - uint32_t DSCL_EXT_OVERSCAN_TOP_BOTTOM; - uint32_t OTG_H_BLANK; - uint32_t OTG_V_BLANK; - uint32_t SCL_MODE; - uint32_t LB_DATA_FORMAT; - uint32_t LB_MEMORY_CTRL; - uint32_t DSCL_AUTOCAL; - uint32_t SCL_BLACK_OFFSET; - uint32_t DSCL_CONTROL; - uint32_t SCL_TAP_CONTROL; - uint32_t SCL_COEF_RAM_TAP_SELECT; - uint32_t SCL_COEF_RAM_TAP_DATA; - uint32_t DSCL_2TAP_CONTROL; - uint32_t DCSURF_PRI_VIEWPORT_DIMENSION; - uint32_t DCSURF_PRI_VIEWPORT_START; - uint32_t DCSURF_SEC_VIEWPORT_DIMENSION; - uint32_t DCSURF_SEC_VIEWPORT_START; - uint32_t DCSURF_PRI_VIEWPORT_DIMENSION_C; - uint32_t DCSURF_PRI_VIEWPORT_START_C; - uint32_t MPC_SIZE; - uint32_t SCL_HORZ_FILTER_SCALE_RATIO; - uint32_t SCL_VERT_FILTER_SCALE_RATIO; - uint32_t SCL_HORZ_FILTER_SCALE_RATIO_C; - uint32_t SCL_VERT_FILTER_SCALE_RATIO_C; - uint32_t SCL_HORZ_FILTER_INIT; - uint32_t SCL_HORZ_FILTER_INIT_C; - uint32_t SCL_VERT_FILTER_INIT; - uint32_t SCL_VERT_FILTER_INIT_BOT; - uint32_t SCL_VERT_FILTER_INIT_C; - uint32_t SCL_VERT_FILTER_INIT_BOT_C; - uint32_t RECOUT_START; - uint32_t RECOUT_SIZE; - uint32_t CM_GAMUT_REMAP_CONTROL; - uint32_t CM_GAMUT_REMAP_C11_C12; - uint32_t CM_GAMUT_REMAP_C13_C14; - uint32_t CM_GAMUT_REMAP_C21_C22; - uint32_t CM_GAMUT_REMAP_C23_C24; - uint32_t CM_GAMUT_REMAP_C31_C32; - uint32_t CM_GAMUT_REMAP_C33_C34; - uint32_t CM_COMA_C11_C12; - uint32_t CM_COMA_C13_C14; - uint32_t CM_COMA_C21_C22; - uint32_t CM_COMA_C23_C24; - uint32_t CM_COMA_C31_C32; - uint32_t CM_COMA_C33_C34; - uint32_t CM_COMB_C11_C12; - uint32_t CM_COMB_C13_C14; - uint32_t CM_COMB_C21_C22; - uint32_t CM_COMB_C23_C24; - uint32_t CM_COMB_C31_C32; - uint32_t CM_COMB_C33_C34; -}; - -struct dcn10_transform { - struct transform base; - - const struct dcn_transform_registers *tf_regs; - const struct dcn_transform_shift *tf_shift; - const struct dcn_transform_mask *tf_mask; - - const uint16_t *filter_v; - const uint16_t *filter_h; - const uint16_t *filter_v_c; - const uint16_t *filter_h_c; - int lb_pixel_depth_supported; - int lb_memory_size; - int lb_bits_per_entry; -}; - -bool dcn10_transform_construct(struct dcn10_transform *xfmn10, - struct dc_context *ctx, - uint32_t inst, - const struct dcn_transform_registers *tf_regs, - const struct dcn_transform_shift *tf_shift, - const struct dcn_transform_mask *tf_mask); - -#endif -- cgit From 60bf1860d29f4f459e8b195dc73fcb2d980500d0 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Thu, 13 Jul 2017 10:52:47 -0400 Subject: drm/amd/display: Preserve refcount for S3 case. Curent_context is zerroed out for suspend, keep the refcount. Minor code move in dc_commit_context_no_check Signed-off-by: Andrey Grodzovsky Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 8e580ac91b2a..20f41991f94d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -977,10 +977,10 @@ static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *c dc_release_validate_context(core_dc->current_context); - dc_retain_validate_context(context); - core_dc->current_context = context; + dc_retain_validate_context(core_dc->current_context); + return (result == DC_OK); } @@ -1065,8 +1065,6 @@ bool dc_commit_streams( result = dc_commit_context_no_check(dc, context); - return (result == DC_OK); - fail: dc_release_validate_context(context); @@ -1736,6 +1734,7 @@ void dc_set_power_state( enum dc_acpi_cm_power_state power_state) { struct core_dc *core_dc = DC_TO_CORE(dc); + int ref_count; switch (power_state) { case DC_ACPI_CM_POWER_STATE_D0: @@ -1749,8 +1748,13 @@ void dc_set_power_state( * clean state, and dc hw programming optimizations will not * cause any trouble. */ + + /* Preserve refcount */ + ref_count = core_dc->current_context->ref_count; + dc_resource_validate_ctx_destruct(core_dc->current_context); memset(core_dc->current_context, 0, sizeof(*core_dc->current_context)); + core_dc->current_context->ref_count = ref_count; break; } -- cgit From 0a214e2fb6b0a56519b6d5efab4b21475c233ee0 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Thu, 13 Jul 2017 10:56:48 -0400 Subject: drm/amd/display: Release cached atomic state in S3. Fixes memory leak. Signed-off-by: Andrey Grodzovsky Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/gpu') 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 e16e87173db3..a41d271f21a3 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -508,6 +508,7 @@ static int dm_suspend(void *handle) amdgpu_dm_irq_suspend(adev); + WARN_ON(adev->dm.cached_state); adev->dm.cached_state = drm_atomic_helper_suspend(adev->ddev); dc_set_power_state( @@ -607,6 +608,9 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev ) ret = drm_atomic_helper_resume(ddev, adev->dm.cached_state); + drm_atomic_state_put(adev->dm.cached_state); + adev->dm.cached_state = NULL; + amdgpu_dm_irq_resume_late(adev); return ret; -- cgit From daf6b57dd736ec93b2e1769b90514b015feed3c1 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Tue, 11 Jul 2017 13:48:17 -0400 Subject: drm/amd/display: add line number to reg_wait timeout print Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc_helper.c | 6 +++--- drivers/gpu/drm/amd/display/dc/dm_services.h | 2 +- drivers/gpu/drm/amd/display/dc/inc/reg_helper.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc_helper.c b/drivers/gpu/drm/amd/display/dc/dc_helper.c index 8ed1440d2b01..87b7f6f8870e 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_helper.c +++ b/drivers/gpu/drm/amd/display/dc/dc_helper.c @@ -129,7 +129,7 @@ uint32_t generic_reg_get(const struct dc_context *ctx, uint32_t generic_reg_wait(const struct dc_context *ctx, uint32_t addr, uint32_t shift, uint32_t mask, uint32_t condition_value, unsigned int delay_between_poll_us, unsigned int time_out_num_tries, - const char *func_name) + const char *func_name, int line) { uint32_t field_value; uint32_t reg_val; @@ -158,8 +158,8 @@ uint32_t generic_reg_wait(const struct dc_context *ctx, return reg_val; } - dm_error("REG_WAIT timeout %dus * %d tries - %s\n", - delay_between_poll_us, time_out_num_tries, func_name); + dm_error("REG_WAIT timeout %dus * %d tries - %s line:%d\n", + delay_between_poll_us, time_out_num_tries, func_name, line); if (!IS_FPGA_MAXIMUS_DC(ctx->dce_environment)) BREAK_TO_DEBUGGER(); diff --git a/drivers/gpu/drm/amd/display/dc/dm_services.h b/drivers/gpu/drm/amd/display/dc/dm_services.h index fb61e333aefd..ea494a71a80b 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services.h @@ -194,7 +194,7 @@ uint32_t generic_reg_update_ex(const struct dc_context *ctx, unsigned int generic_reg_wait(const struct dc_context *ctx, uint32_t addr, uint32_t mask, uint32_t shift, uint32_t condition_value, unsigned int delay_between_poll_us, unsigned int time_out_num_tries, - const char *func_name); + const char *func_name, int line); /* These macros need to be used with soc15 registers in order to retrieve diff --git a/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h b/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h index 1828d288c6bc..77eb72874e90 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h +++ b/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h @@ -188,7 +188,7 @@ #define REG_WAIT(reg_name, field, val, delay_between_poll_us, max_try) \ generic_reg_wait(CTX, \ REG(reg_name), FN(reg_name, field), val,\ - delay_between_poll_us, max_try, __func__) + delay_between_poll_us, max_try, __func__, __LINE__) /* macro to update (read, modify, write) register fields */ -- cgit From b02c3b055fe27cb37969c68cd81db767a16af43b Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 7 Jul 2017 17:21:45 -0400 Subject: drm/amd/display: hwseq init sequence update Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h | 8 +++- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 51 +++++----------------- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h | 2 +- .../gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c | 1 - 4 files changed, 20 insertions(+), 42 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index 4da9142351fa..7e1d46fdcc76 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -216,6 +216,11 @@ struct dce_hwseq_registers { uint32_t DCCG_GATE_DISABLE_CNTL; uint32_t DCCG_GATE_DISABLE_CNTL2; uint32_t DCFCLK_CNTL; + uint32_t MICROSECOND_TIME_BASE_DIV; + uint32_t MILLISECOND_TIME_BASE_DIV; + uint32_t DISPCLK_FREQ_CHANGE_CNTL; + uint32_t RBBMIF_TIMEOUT_DIS; + uint32_t RBBMIF_TIMEOUT_DIS_2; #endif }; /* set field name */ @@ -378,7 +383,8 @@ struct dce_hwseq_registers { type DOMAIN5_PGFSM_PWR_STATUS; \ type DOMAIN6_PGFSM_PWR_STATUS; \ type DOMAIN7_PGFSM_PWR_STATUS; \ - type DCFCLK_GATE_DIS; + type DCFCLK_GATE_DIS; \ + type DCHUBBUB_GLOBAL_TIMER_REFDIV; #endif struct dce_hwseq_shift { diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index fc46c84aea67..eca0d53eedff 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -24,11 +24,9 @@ */ #include "dm_services.h" -#include "dc.h" -#include "core_dc.h" #include "core_types.h" -#include "core_status.h" #include "resource.h" +#include "custom_float.h" #include "dcn10_hw_sequencer.h" #include "dce110/dce110_hw_sequencer.h" #include "dce/dce_hwseq.h" @@ -39,11 +37,10 @@ #include "timing_generator.h" #include "opp.h" #include "ipp.h" -#include "dc_bios_types.h" +#include "mpc.h" #include "raven1/DCN/dcn_1_0_offset.h" #include "raven1/DCN/dcn_1_0_sh_mask.h" #include "vega10/soc15ip.h" -#include "custom_float.h" #include "reg_helper.h" #define CTX \ @@ -219,31 +216,15 @@ static void bios_golden_init(struct core_dc *dc) } } -/* - * This should be done within BIOS, we are doing it for maximus only - */ -static void dchubup_setup_timer(struct dce_hwseq *hws) -{ - REG_WRITE(REFCLK_CNTL, 0); - - REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1); -} - -static void init_hw(struct core_dc *dc) +static void dcn10_init_hw(struct core_dc *dc) { int i; - struct transform *xfm; - struct abm *abm; + struct abm *abm = dc->res_pool->abm; struct dce_hwseq *hws = dc->hwseq; -#if 1 if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { - dchubup_setup_timer(dc->hwseq); - - /* TODO: dchubp_map_fb_to_mc will be moved to dchub interface - * between dc and kmd - */ - /*dchubp_map_fb_to_mc(dc->hwseq);*/ + REG_WRITE(REFCLK_CNTL, 0); + REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1); REG_WRITE(DIO_MEM_PWR_CTRL, 0); if (!dc->public.debug.disable_clock_gate) { @@ -259,15 +240,9 @@ static void init_hw(struct core_dc *dc) return; } /* end of FPGA. Below if real ASIC */ -#endif bios_golden_init(dc); - for (i = 0; i < dc->res_pool->pipe_count; i++) { - xfm = dc->res_pool->transforms[i]; - xfm->funcs->transform_reset(xfm); - } - for (i = 0; i < dc->link_count; i++) { /* Power up AND update implementation according to the * required signal (which may be different from the @@ -279,12 +254,12 @@ static void init_hw(struct core_dc *dc) } for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct timing_generator *tg = - dc->res_pool->timing_generators[i]; - struct mpcc *mpcc = - dc->res_pool->mpcc[i]; + struct transform *xfm = dc->res_pool->transforms[i]; + struct timing_generator *tg = dc->res_pool->timing_generators[i]; + struct mpcc *mpcc = dc->res_pool->mpcc[i]; struct mpcc_cfg mpcc_cfg; + xfm->funcs->transform_reset(xfm); mpcc_cfg.opp_id = 0xf; mpcc_cfg.top_dpp_id = 0xf; mpcc_cfg.bot_mpcc_id = 0xf; @@ -305,7 +280,6 @@ static void init_hw(struct core_dc *dc) audio->funcs->hw_init(audio); } - abm = dc->res_pool->abm; if (abm != NULL) { abm->funcs->init_backlight(abm); abm->funcs->abm_init(abm); @@ -1859,7 +1833,7 @@ static bool dcn10_dummy_display_power_gating( static const struct hw_sequencer_funcs dcn10_funcs = { .program_gamut_remap = program_gamut_remap, .program_csc_matrix = program_csc_matrix, - .init_hw = init_hw, + .init_hw = dcn10_init_hw, .apply_ctx_to_hw = dce110_apply_ctx_to_hw, .apply_ctx_for_surface = dcn10_apply_ctx_for_surface, .set_plane_config = set_plane_config, @@ -1888,9 +1862,8 @@ static const struct hw_sequencer_funcs dcn10_funcs = { }; -bool dcn10_hw_sequencer_construct(struct core_dc *dc) +void dcn10_hw_sequencer_construct(struct core_dc *dc) { dc->hwss = dcn10_funcs; - return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h index c3aff2eb8d68..28218dc43522 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h @@ -30,7 +30,7 @@ struct core_dc; -bool dcn10_hw_sequencer_construct(struct core_dc *dc); +void dcn10_hw_sequencer_construct(struct core_dc *dc); extern void fill_display_configs( const struct validate_context *context, struct dm_pp_display_configuration *pp_display_cfg); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index b7ecfad4a8f2..4e723a017b97 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -403,7 +403,6 @@ static void min10_program_requestor( struct mem_input *mem_input, struct _vcs_dpi_display_rq_regs_st *rq_regs) { - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); REG_UPDATE(HUBPRET_CONTROL, -- cgit From 4bd3ae5fb5156eb47b4d7f4f12d8467d9c4a8623 Mon Sep 17 00:00:00 2001 From: Vitaly Prosyak Date: Thu, 13 Jul 2017 15:42:58 -0500 Subject: drm/amd/display: Move view port registers and programming to memory input. Signed-off-by: Vitaly Prosyak Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c | 36 --------------------- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h | 36 --------------------- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 2 ++ .../gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c | 37 +++++++++++++++++++++- .../gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h | 36 +++++++++++++++++++++ drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h | 4 +++ 6 files changed, 78 insertions(+), 73 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c index 85d3ca31daf5..fff81a14b21c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c @@ -452,37 +452,6 @@ static void dpp_set_scl_filter( } } -static void dpp_set_viewport( - struct dcn10_dpp *xfm, - const struct rect *viewport, - const struct rect *viewport_c) -{ - REG_SET_2(DCSURF_PRI_VIEWPORT_DIMENSION, 0, - PRI_VIEWPORT_WIDTH, viewport->width, - PRI_VIEWPORT_HEIGHT, viewport->height); - - REG_SET_2(DCSURF_PRI_VIEWPORT_START, 0, - PRI_VIEWPORT_X_START, viewport->x, - PRI_VIEWPORT_Y_START, viewport->y); - - /*for stereo*/ - REG_SET_2(DCSURF_SEC_VIEWPORT_DIMENSION, 0, - SEC_VIEWPORT_WIDTH, viewport->width, - SEC_VIEWPORT_HEIGHT, viewport->height); - - REG_SET_2(DCSURF_SEC_VIEWPORT_START, 0, - SEC_VIEWPORT_X_START, viewport->x, - SEC_VIEWPORT_Y_START, viewport->y); - - /* DC supports NV12 only at the moment */ - REG_SET_2(DCSURF_PRI_VIEWPORT_DIMENSION_C, 0, - PRI_VIEWPORT_WIDTH_C, viewport_c->width, - PRI_VIEWPORT_HEIGHT_C, viewport_c->height); - - REG_SET_2(DCSURF_PRI_VIEWPORT_START_C, 0, - PRI_VIEWPORT_X_START_C, viewport_c->x, - PRI_VIEWPORT_Y_START_C, viewport_c->y); -} static int get_lb_depth_bpc(enum lb_pixel_depth depth) { @@ -616,8 +585,6 @@ void dpp_set_scaler_auto_scale( REG_UPDATE(SCL_MODE, DSCL_MODE, dscl_mode); - dpp_set_viewport(xfm, &scl_data->viewport, &scl_data->viewport_c); - if (dscl_mode == DSCL_MODE_DSCL_BYPASS) return; @@ -762,9 +729,6 @@ static void dpp_set_scaler_manual_scale( /* SCL mode */ REG_UPDATE(SCL_MODE, DSCL_MODE, dscl_mode); - /* Viewport */ - dpp_set_viewport(xfm, &scl_data->viewport, &scl_data->viewport_c); - if (dscl_mode == DSCL_MODE_DSCL_BYPASS) return; /* LB */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h index 993643552aff..c1124e962d0e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h @@ -59,12 +59,6 @@ SRI(SCL_COEF_RAM_TAP_SELECT, DSCL, id), \ SRI(SCL_COEF_RAM_TAP_DATA, DSCL, id), \ SRI(DSCL_2TAP_CONTROL, DSCL, id), \ - SRI(DCSURF_PRI_VIEWPORT_DIMENSION, HUBP, id), \ - SRI(DCSURF_PRI_VIEWPORT_START, HUBP, id), \ - SRI(DCSURF_SEC_VIEWPORT_DIMENSION, HUBP, id), \ - SRI(DCSURF_SEC_VIEWPORT_START, HUBP, id), \ - SRI(DCSURF_PRI_VIEWPORT_DIMENSION_C, HUBP, id), \ - SRI(DCSURF_PRI_VIEWPORT_START_C, HUBP, id), \ SRI(MPC_SIZE, DSCL, id), \ SRI(SCL_HORZ_FILTER_SCALE_RATIO, DSCL, id), \ SRI(SCL_VERT_FILTER_SCALE_RATIO, DSCL, id), \ @@ -144,18 +138,6 @@ TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_V_2TAP_SHARP_EN, mask_sh),\ TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_V_2TAP_SHARP_FACTOR, mask_sh),\ TF_SF(DSCL0_SCL_MODE, SCL_COEF_RAM_SELECT, mask_sh),\ - TF_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION, PRI_VIEWPORT_WIDTH, mask_sh),\ - TF_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION, PRI_VIEWPORT_HEIGHT, mask_sh),\ - TF_SF(HUBP0_DCSURF_PRI_VIEWPORT_START, PRI_VIEWPORT_X_START, mask_sh),\ - TF_SF(HUBP0_DCSURF_PRI_VIEWPORT_START, PRI_VIEWPORT_Y_START, mask_sh),\ - TF_SF(HUBP0_DCSURF_SEC_VIEWPORT_DIMENSION, SEC_VIEWPORT_WIDTH, mask_sh),\ - TF_SF(HUBP0_DCSURF_SEC_VIEWPORT_DIMENSION, SEC_VIEWPORT_HEIGHT, mask_sh),\ - TF_SF(HUBP0_DCSURF_SEC_VIEWPORT_START, SEC_VIEWPORT_X_START, mask_sh),\ - TF_SF(HUBP0_DCSURF_SEC_VIEWPORT_START, SEC_VIEWPORT_Y_START, mask_sh),\ - TF_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION_C, PRI_VIEWPORT_WIDTH_C, mask_sh),\ - TF_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION_C, PRI_VIEWPORT_HEIGHT_C, mask_sh),\ - TF_SF(HUBP0_DCSURF_PRI_VIEWPORT_START_C, PRI_VIEWPORT_X_START_C, mask_sh),\ - TF_SF(HUBP0_DCSURF_PRI_VIEWPORT_START_C, PRI_VIEWPORT_Y_START_C, mask_sh),\ TF_SF(DSCL0_SCL_MODE, DSCL_MODE, mask_sh),\ TF_SF(DSCL0_RECOUT_START, RECOUT_START_X, mask_sh),\ TF_SF(DSCL0_RECOUT_START, RECOUT_START_Y, mask_sh),\ @@ -257,18 +239,6 @@ type SCL_V_2TAP_SHARP_EN; \ type SCL_V_2TAP_SHARP_FACTOR; \ type SCL_COEF_RAM_SELECT; \ - type PRI_VIEWPORT_WIDTH; \ - type PRI_VIEWPORT_HEIGHT; \ - type PRI_VIEWPORT_X_START; \ - type PRI_VIEWPORT_Y_START; \ - type SEC_VIEWPORT_WIDTH; \ - type SEC_VIEWPORT_HEIGHT; \ - type SEC_VIEWPORT_X_START; \ - type SEC_VIEWPORT_Y_START; \ - type PRI_VIEWPORT_WIDTH_C; \ - type PRI_VIEWPORT_HEIGHT_C; \ - type PRI_VIEWPORT_X_START_C; \ - type PRI_VIEWPORT_Y_START_C; \ type DSCL_MODE; \ type RECOUT_START_X; \ type RECOUT_START_Y; \ @@ -355,12 +325,6 @@ struct dcn_dpp_registers { uint32_t SCL_COEF_RAM_TAP_SELECT; uint32_t SCL_COEF_RAM_TAP_DATA; uint32_t DSCL_2TAP_CONTROL; - uint32_t DCSURF_PRI_VIEWPORT_DIMENSION; - uint32_t DCSURF_PRI_VIEWPORT_START; - uint32_t DCSURF_SEC_VIEWPORT_DIMENSION; - uint32_t DCSURF_SEC_VIEWPORT_START; - uint32_t DCSURF_PRI_VIEWPORT_DIMENSION_C; - uint32_t DCSURF_PRI_VIEWPORT_START_C; uint32_t MPC_SIZE; uint32_t SCL_HORZ_FILTER_SCALE_RATIO; uint32_t SCL_VERT_FILTER_SCALE_RATIO; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index eca0d53eedff..d714422ef979 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1470,6 +1470,8 @@ static void update_dchubp_dpp( /* scaler configuration */ pipe_ctx->xfm->funcs->transform_set_scaler( pipe_ctx->xfm, &pipe_ctx->scl_data); + mi->funcs->mem_program_viewport(mi, + &pipe_ctx->scl_data.viewport, &pipe_ctx->scl_data.viewport_c); /*gamut remap*/ program_gamut_remap(pipe_ctx); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index 4e723a017b97..efa02d160d1a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -1057,6 +1057,41 @@ static void min10_program_pte_vm(struct mem_input *mem_input, SYSTEM_ACCESS_MODE, 3); } +static void min_set_viewport( + struct mem_input *mem_input, + const struct rect *viewport, + const struct rect *viewport_c) +{ + struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + + REG_SET_2(DCSURF_PRI_VIEWPORT_DIMENSION, 0, + PRI_VIEWPORT_WIDTH, viewport->width, + PRI_VIEWPORT_HEIGHT, viewport->height); + + REG_SET_2(DCSURF_PRI_VIEWPORT_START, 0, + PRI_VIEWPORT_X_START, viewport->x, + PRI_VIEWPORT_Y_START, viewport->y); + + /*for stereo*/ + REG_SET_2(DCSURF_SEC_VIEWPORT_DIMENSION, 0, + SEC_VIEWPORT_WIDTH, viewport->width, + SEC_VIEWPORT_HEIGHT, viewport->height); + + REG_SET_2(DCSURF_SEC_VIEWPORT_START, 0, + SEC_VIEWPORT_X_START, viewport->x, + SEC_VIEWPORT_Y_START, viewport->y); + + /* DC supports NV12 only at the moment */ + REG_SET_2(DCSURF_PRI_VIEWPORT_DIMENSION_C, 0, + PRI_VIEWPORT_WIDTH_C, viewport_c->width, + PRI_VIEWPORT_HEIGHT_C, viewport_c->height); + + REG_SET_2(DCSURF_PRI_VIEWPORT_START_C, 0, + PRI_VIEWPORT_X_START_C, viewport_c->x, + PRI_VIEWPORT_Y_START_C, viewport_c->y); +} + + static struct mem_input_funcs dcn10_mem_input_funcs = { .mem_input_program_display_marks = min10_program_display_marks, .mem_input_program_surface_flip_and_addr = @@ -1070,9 +1105,9 @@ static struct mem_input_funcs dcn10_mem_input_funcs = { .mem_input_program_pte_vm = min10_program_pte_vm, .set_blank = min10_set_blank, .dcc_control = min10_dcc_control, + .mem_program_viewport = min_set_viewport, }; - /*****************************************/ /* Constructor, Destructor */ /*****************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h index c3f18bdc2157..7efa857b8710 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h @@ -40,6 +40,12 @@ SRI(DCSURF_SURFACE_PITCH_C, HUBPREQ, id),\ SRI(DCSURF_SURFACE_CONFIG, HUBP, id),\ SRI(DCSURF_FLIP_CONTROL, HUBPREQ, id),\ + SRI(DCSURF_PRI_VIEWPORT_DIMENSION, HUBP, id), \ + SRI(DCSURF_PRI_VIEWPORT_START, HUBP, id), \ + SRI(DCSURF_SEC_VIEWPORT_DIMENSION, HUBP, id), \ + SRI(DCSURF_SEC_VIEWPORT_START, HUBP, id), \ + SRI(DCSURF_PRI_VIEWPORT_DIMENSION_C, HUBP, id), \ + SRI(DCSURF_PRI_VIEWPORT_START_C, HUBP, id), \ SRI(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, HUBPREQ, id),\ SRI(DCSURF_PRIMARY_SURFACE_ADDRESS, HUBPREQ, id),\ SRI(DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH, HUBPREQ, id),\ @@ -164,6 +170,12 @@ struct dcn_mi_registers { uint32_t DCSURF_SURFACE_PITCH_C; uint32_t DCSURF_SURFACE_CONFIG; uint32_t DCSURF_FLIP_CONTROL; + uint32_t DCSURF_PRI_VIEWPORT_DIMENSION; + uint32_t DCSURF_PRI_VIEWPORT_START; + uint32_t DCSURF_SEC_VIEWPORT_DIMENSION; + uint32_t DCSURF_SEC_VIEWPORT_START; + uint32_t DCSURF_PRI_VIEWPORT_DIMENSION_C; + uint32_t DCSURF_PRI_VIEWPORT_START_C; uint32_t DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH; uint32_t DCSURF_PRIMARY_SURFACE_ADDRESS; uint32_t DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH; @@ -312,6 +324,18 @@ struct dcn_mi_registers { MI_SF(HUBPREQ0_DCSURF_FLIP_CONTROL, SURFACE_FLIP_TYPE, mask_sh),\ MI_SF(HUBPREQ0_DCSURF_FLIP_CONTROL, SURFACE_FLIP_PENDING, mask_sh),\ MI_SF(HUBPREQ0_DCSURF_FLIP_CONTROL, SURFACE_UPDATE_LOCK, mask_sh),\ + MI_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION, PRI_VIEWPORT_WIDTH, mask_sh),\ + MI_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION, PRI_VIEWPORT_HEIGHT, mask_sh),\ + MI_SF(HUBP0_DCSURF_PRI_VIEWPORT_START, PRI_VIEWPORT_X_START, mask_sh),\ + MI_SF(HUBP0_DCSURF_PRI_VIEWPORT_START, PRI_VIEWPORT_Y_START, mask_sh),\ + MI_SF(HUBP0_DCSURF_SEC_VIEWPORT_DIMENSION, SEC_VIEWPORT_WIDTH, mask_sh),\ + MI_SF(HUBP0_DCSURF_SEC_VIEWPORT_DIMENSION, SEC_VIEWPORT_HEIGHT, mask_sh),\ + MI_SF(HUBP0_DCSURF_SEC_VIEWPORT_START, SEC_VIEWPORT_X_START, mask_sh),\ + MI_SF(HUBP0_DCSURF_SEC_VIEWPORT_START, SEC_VIEWPORT_Y_START, mask_sh),\ + MI_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION_C, PRI_VIEWPORT_WIDTH_C, mask_sh),\ + MI_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION_C, PRI_VIEWPORT_HEIGHT_C, mask_sh),\ + MI_SF(HUBP0_DCSURF_PRI_VIEWPORT_START_C, PRI_VIEWPORT_X_START_C, mask_sh),\ + MI_SF(HUBP0_DCSURF_PRI_VIEWPORT_START_C, PRI_VIEWPORT_Y_START_C, mask_sh),\ MI_SF(HUBPREQ0_DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, PRIMARY_SURFACE_ADDRESS_HIGH, mask_sh),\ MI_SF(HUBPREQ0_DCSURF_PRIMARY_SURFACE_ADDRESS, PRIMARY_SURFACE_ADDRESS, mask_sh),\ MI_SF(HUBPREQ0_DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH, SECONDARY_SURFACE_ADDRESS_HIGH, mask_sh),\ @@ -459,6 +483,18 @@ struct dcn_mi_registers { type SURFACE_FLIP_TYPE;\ type SURFACE_UPDATE_LOCK;\ type SURFACE_FLIP_PENDING;\ + type PRI_VIEWPORT_WIDTH; \ + type PRI_VIEWPORT_HEIGHT; \ + type PRI_VIEWPORT_X_START; \ + type PRI_VIEWPORT_Y_START; \ + type SEC_VIEWPORT_WIDTH; \ + type SEC_VIEWPORT_HEIGHT; \ + type SEC_VIEWPORT_X_START; \ + type SEC_VIEWPORT_Y_START; \ + type PRI_VIEWPORT_WIDTH_C; \ + type PRI_VIEWPORT_HEIGHT_C; \ + type PRI_VIEWPORT_X_START_C; \ + type PRI_VIEWPORT_Y_START_C; \ type PRIMARY_SURFACE_ADDRESS_HIGH;\ type PRIMARY_SURFACE_ADDRESS;\ type SECONDARY_SURFACE_ADDRESS_HIGH;\ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h index 64b810d48d07..1b7d151a66f8 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h @@ -89,6 +89,10 @@ struct mem_input_funcs { void (*dcc_control)(struct mem_input *mem_input, bool enable, bool independent_64b_blks); + void (*mem_program_viewport)( + struct mem_input *mem_input, + const struct rect *viewport, + const struct rect *viewport_c); #endif void (*mem_input_program_display_marks)( -- cgit From 90114434772321881c8d11133b634e710e4e1f06 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Thu, 13 Jul 2017 16:27:08 -0400 Subject: drm/amd/display: Fix S3 gamma corruption. On S3 resume gamma is corrupted since no gamma programming took place. Signed-off-by: Andrey Grodzovsky Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 20f41991f94d..eda36c7a5c57 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1120,11 +1120,13 @@ bool dc_commit_surfaces_to_stream( stream_update->src = dc_stream->src; stream_update->dst = dc_stream->dst; + stream_update->out_transfer_func = dc_stream->out_transfer_func; for (i = 0; i < new_surface_count; i++) { updates[i].surface = new_surfaces[i]; updates[i].gamma = (struct dc_gamma *)new_surfaces[i]->gamma_correction; + updates[i].in_transfer_func = new_surfaces[i]->in_transfer_func; flip_addr[i].address = new_surfaces[i]->address; flip_addr[i].flip_immediate = new_surfaces[i]->flip_immediate; plane_info[i].color_space = new_surfaces[i]->color_space; -- cgit From 820e3935489c85d7dc3024eec709b016ba75b376 Mon Sep 17 00:00:00 2001 From: Ding Wang Date: Thu, 13 Jul 2017 12:09:57 -0400 Subject: drm/amd/display: link training fallback actions Signed-off-by: Ding Wang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 239 +++++++++++++++++---- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h | 8 + .../drm/amd/display/include/link_service_types.h | 9 + 4 files changed, 215 insertions(+), 43 deletions(-) (limited to 'drivers/gpu') 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 98048fe6239e..dd3f57fce834 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 @@ -731,7 +731,7 @@ static enum hw_dp_training_pattern get_supported_tp(struct core_link *link) return HW_DP_TRAINING_PATTERN_2; } -static bool perform_channel_equalization_sequence( +static enum link_training_result perform_channel_equalization_sequence( struct core_link *link, struct link_training_settings *lt_settings) { @@ -777,19 +777,19 @@ static bool perform_channel_equalization_sequence( /* 5. check CR done*/ if (!is_cr_done(lane_count, dpcd_lane_status)) - return false; + return LINK_TRAINING_EQ_FAIL_CR; /* 6. check CHEQ done*/ if (is_ch_eq_done(lane_count, dpcd_lane_status, &dpcd_lane_status_updated)) - return true; + return LINK_TRAINING_SUCCESS; /* 7. update VS/PE/PC2 in lt_settings*/ update_drive_settings(lt_settings, req_settings); } - return false; + return LINK_TRAINING_EQ_FAIL_EQ; } @@ -943,18 +943,17 @@ static inline bool perform_link_training_int( return status; } -bool dc_link_dp_perform_link_training( +enum link_training_result dc_link_dp_perform_link_training( struct dc_link *link, const struct dc_link_settings *link_setting, bool skip_video_pattern) { + enum link_training_result status = LINK_TRAINING_SUCCESS; struct core_link *core_link = DC_LINK_TO_CORE(link); - bool status; char *link_rate = "Unknown"; struct link_training_settings lt_settings; - status = false; memset(<_settings, '\0', sizeof(lt_settings)); lt_settings.link_settings.link_rate = link_setting->link_rate; @@ -976,16 +975,23 @@ bool dc_link_dp_perform_link_training( /* 2. perform link training (set link training done * to false is done as well)*/ - if (perform_clock_recovery_sequence(core_link, <_settings)) { - - if (perform_channel_equalization_sequence(core_link, - <_settings)) - status = true; + if (!perform_clock_recovery_sequence(core_link, <_settings)) { + status = LINK_TRAINING_CR_FAIL; + } else { + status = perform_channel_equalization_sequence(core_link, + <_settings); } - if (status || !skip_video_pattern) - status = perform_link_training_int(core_link, - <_settings, status); + if ((status == LINK_TRAINING_SUCCESS) || !skip_video_pattern) { + if (!perform_link_training_int(core_link, + <_settings, + status == LINK_TRAINING_SUCCESS)) { + /* the next link training setting in this case + * would be the same as CR failure case. + */ + status = LINK_TRAINING_CR_FAIL; + } + } /* 6. print status message*/ switch (lt_settings.link_settings.link_rate) { @@ -1013,7 +1019,9 @@ bool dc_link_dp_perform_link_training( CONN_MSG_LT(core_link, "%sx%d %s VS=%d, PE=%d", link_rate, lt_settings.link_settings.lane_count, - status ? "pass" : "fail", + (status == LINK_TRAINING_SUCCESS) ? "pass" : + ((status == LINK_TRAINING_CR_FAIL) ? "CR failed" : + "EQ failed"), lt_settings.lane_settings[0].VOLTAGE_SWING, lt_settings.lane_settings[0].PRE_EMPHASIS); @@ -1035,7 +1043,7 @@ bool perform_link_training_with_retries( if (dc_link_dp_perform_link_training( &link->public, link_setting, - skip_video_pattern)) + skip_video_pattern) == LINK_TRAINING_SUCCESS) return true; msleep(delay_between_attempts); @@ -1068,15 +1076,6 @@ static const struct dc_link_settings *get_link_training_fallback_table( return &link_training_fallback_table[i]; } -static bool exceeded_limit_link_setting( - const struct dc_link_settings *link_setting, - const struct dc_link_settings *limit_link_setting) -{ - return (link_setting->lane_count * link_setting->link_rate - > limit_link_setting->lane_count * limit_link_setting->link_rate ? - true : false); -} - static struct dc_link_settings get_max_link_cap(struct core_link *link) { /* Set Default link settings */ @@ -1109,13 +1108,15 @@ bool dp_hbr_verify_link_cap( struct dc_link_settings *known_limit_link_setting) { struct dc_link_settings max_link_cap = {0}; + struct dc_link_settings cur_link_setting = {0}; + struct dc_link_settings *cur = &cur_link_setting; + struct dc_link_settings initial_link_settings = {0}; bool success; bool skip_link_training; - const struct dc_link_settings *cur; bool skip_video_pattern; - uint32_t i; struct clock_source *dp_cs; enum clock_source_id dp_cs_id = CLOCK_SOURCE_ID_EXTERNAL; + enum link_training_result status; success = false; skip_link_training = false; @@ -1142,19 +1143,16 @@ bool dp_hbr_verify_link_cap( ASSERT(dp_cs); } - for (i = 0; i < get_link_training_fallback_table_len(link) && - !success; i++) { - cur = get_link_training_fallback_table(link, i); - - if (known_limit_link_setting->lane_count != LANE_COUNT_UNKNOWN && - exceeded_limit_link_setting(cur, - known_limit_link_setting)) - continue; - - if (!is_link_setting_supported(cur, &max_link_cap)) - continue; - + /* link training starts with the maximum common settings + * supported by both sink and ASIC. + */ + initial_link_settings = get_common_supported_link_settings( + *known_limit_link_setting, + max_link_cap); + cur_link_setting = initial_link_settings; + do { skip_video_pattern = true; + if (cur->link_rate == LINK_RATE_LOW) skip_video_pattern = false; @@ -1167,10 +1165,12 @@ bool dp_hbr_verify_link_cap( if (skip_link_training) success = true; else { - success = dc_link_dp_perform_link_training( + status = dc_link_dp_perform_link_training( &link->public, cur, skip_video_pattern); + if (status == LINK_TRAINING_SUCCESS) + success = true; } if (success) @@ -1181,7 +1181,8 @@ bool dp_hbr_verify_link_cap( * based on the actual mode we're driving */ dp_disable_link_phy(link, link->public.connector_signal); - } + } while (!success && decide_fallback_link_setting( + initial_link_settings, cur, status)); /* Link Training failed for all Link Settings * (Lane Count is still unknown) @@ -1202,6 +1203,160 @@ bool dp_hbr_verify_link_cap( return success; } +struct dc_link_settings get_common_supported_link_settings ( + struct dc_link_settings link_setting_a, + struct dc_link_settings link_setting_b) +{ + struct dc_link_settings link_settings = {0}; + + link_settings.lane_count = + (link_setting_a.lane_count <= + link_setting_b.lane_count) ? + link_setting_a.lane_count : + link_setting_b.lane_count; + link_settings.link_rate = + (link_setting_a.link_rate <= + link_setting_b.link_rate) ? + link_setting_a.link_rate : + link_setting_b.link_rate; + link_settings.link_spread = LINK_SPREAD_DISABLED; + + /* in DP compliance test, DPR-120 may have + * a random value in its MAX_LINK_BW dpcd field. + * We map it to the maximum supported link rate that + * is smaller than MAX_LINK_BW in this case. + */ + if (link_settings.link_rate > LINK_RATE_HIGH3) { + link_settings.link_rate = LINK_RATE_HIGH3; + } else if (link_settings.link_rate < LINK_RATE_HIGH3 + && link_settings.link_rate > LINK_RATE_HIGH2) { + link_settings.link_rate = LINK_RATE_HIGH2; + } else if (link_settings.link_rate < LINK_RATE_HIGH2 + && link_settings.link_rate > LINK_RATE_HIGH) { + link_settings.link_rate = LINK_RATE_HIGH; + } else if (link_settings.link_rate < LINK_RATE_HIGH + && link_settings.link_rate > LINK_RATE_LOW) { + link_settings.link_rate = LINK_RATE_LOW; + } else if (link_settings.link_rate < LINK_RATE_LOW) { + link_settings.link_rate = LINK_RATE_UNKNOWN; + } + + return link_settings; +} + +bool reached_minimum_lane_count(enum dc_lane_count lane_count) +{ + return lane_count <= LANE_COUNT_ONE; +} + +bool reached_minimum_link_rate(enum dc_link_rate link_rate) +{ + return link_rate <= LINK_RATE_LOW; +} + +enum dc_lane_count reduce_lane_count(enum dc_lane_count lane_count) +{ + switch (lane_count) { + case LANE_COUNT_FOUR: + return LANE_COUNT_TWO; + case LANE_COUNT_TWO: + return LANE_COUNT_ONE; + case LANE_COUNT_ONE: + return LANE_COUNT_UNKNOWN; + default: + return LANE_COUNT_UNKNOWN; + } +} + +enum dc_link_rate reduce_link_rate(enum dc_link_rate link_rate) +{ + switch (link_rate) { + case LINK_RATE_HIGH3: + return LINK_RATE_HIGH2; + case LINK_RATE_HIGH2: + return LINK_RATE_HIGH; + case LINK_RATE_HIGH: + return LINK_RATE_LOW; + case LINK_RATE_LOW: + return LINK_RATE_UNKNOWN; + default: + return LINK_RATE_UNKNOWN; + } +} + +/* + * function: set link rate and lane count fallback based + * on current link setting and last link training result + * return value: + * true - link setting could be set + * false - has reached minimum setting + * and no further fallback could be done + */ +bool decide_fallback_link_setting( + struct dc_link_settings initial_link_settings, + struct dc_link_settings *current_link_setting, + enum link_training_result training_result) +{ + if (!current_link_setting) + return false; + + switch (training_result) { + case LINK_TRAINING_CR_FAIL: + { + if (!reached_minimum_link_rate + (current_link_setting->link_rate)) { + current_link_setting->link_rate = + reduce_link_rate( + current_link_setting->link_rate); + } else if (!reached_minimum_lane_count + (current_link_setting->lane_count)) { + current_link_setting->link_rate = + initial_link_settings.link_rate; + current_link_setting->lane_count = + reduce_lane_count( + current_link_setting->lane_count); + } else { + return false; + } + break; + } + case LINK_TRAINING_EQ_FAIL_EQ: + { + if (!reached_minimum_lane_count + (current_link_setting->lane_count)) { + current_link_setting->lane_count = + reduce_lane_count( + current_link_setting->lane_count); + } else if (!reached_minimum_link_rate + (current_link_setting->link_rate)) { + current_link_setting->lane_count = + initial_link_settings.lane_count; + current_link_setting->link_rate = + reduce_link_rate( + current_link_setting->link_rate); + } else { + return false; + } + break; + } + case LINK_TRAINING_EQ_FAIL_CR: + { + if (!reached_minimum_link_rate + (current_link_setting->link_rate)) { + current_link_setting->link_rate = + reduce_link_rate( + current_link_setting->link_rate); + } else { + return false; + } + break; + } + default: + return false; + } + return true; +} + static uint32_t bandwidth_in_kbps_from_timing( const struct dc_crtc_timing *timing) { diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index cd8981469fe9..6a22c91cbcef 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -777,7 +777,7 @@ void dc_link_dp_set_drive_settings( const struct dc_link *link, struct link_training_settings *lt_settings); -bool dc_link_dp_perform_link_training( +enum link_training_result dc_link_dp_perform_link_training( struct dc_link *link, const struct dc_link_settings *link_setting, bool skip_video_pattern); diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h index 92c56e6f7588..b6ef1bfd267c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h @@ -37,6 +37,14 @@ bool dp_hbr_verify_link_cap( struct core_link *link, struct dc_link_settings *known_limit_link_setting); +bool decide_fallback_link_setting(struct dc_link_settings link_setting_init, + struct dc_link_settings *link_setting_current, + enum link_training_result training_result); + +struct dc_link_settings get_common_supported_link_settings ( + struct dc_link_settings link_setting_a, + struct dc_link_settings link_setting_b); + bool dp_validate_mode_timing( struct core_link *link, const struct dc_crtc_timing *timing); diff --git a/drivers/gpu/drm/amd/display/include/link_service_types.h b/drivers/gpu/drm/amd/display/include/link_service_types.h index fe8b5144e03f..adea1a59f620 100644 --- a/drivers/gpu/drm/amd/display/include/link_service_types.h +++ b/drivers/gpu/drm/amd/display/include/link_service_types.h @@ -56,6 +56,15 @@ enum { LINK_RATE_REF_FREQ_IN_KHZ = 27000 /*27MHz*/ }; +enum link_training_result { + LINK_TRAINING_SUCCESS, + LINK_TRAINING_CR_FAIL, + /* CR DONE bit is cleared during EQ step */ + LINK_TRAINING_EQ_FAIL_CR, + /* other failure during EQ step */ + LINK_TRAINING_EQ_FAIL_EQ, +}; + struct link_training_settings { struct dc_link_settings link_settings; struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]; -- cgit From 83572340097012c91de3f96e52797491c79cfe43 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Mon, 17 Jul 2017 17:46:49 -0400 Subject: drm/amd/display: fix DVI connected to HDMI connector max tmds clock Signed-off-by: Charlene Liu Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 812c29982a2e..5663d3dbd7d5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -830,6 +830,12 @@ bool dce110_link_encoder_validate_dvi_output( if (crtc_timing->pixel_encoding != PIXEL_ENCODING_RGB) return false; + /*connect DVI via adpater's HDMI connector*/ + if ((connector_signal == SIGNAL_TYPE_DVI_SINGLE_LINK || + connector_signal == SIGNAL_TYPE_HDMI_TYPE_A) && + signal != SIGNAL_TYPE_HDMI_TYPE_A && + crtc_timing->pix_clk_khz > TMDS_MAX_PIXEL_CLOCK) + return false; if (crtc_timing->pix_clk_khz < TMDS_MIN_PIXEL_CLOCK) return false; -- cgit From 1674d35bf57b0546577b87af266e45de3ccf45c0 Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Mon, 17 Jul 2017 10:22:05 -0400 Subject: drm/amd/display: properly turn off unused mpc before front end programming MPCC_OPP_ID must be programmed to 0xf to properly turn off the mpcc. However the software state of the mpcc must keep track of the opp that the mpcc is attached to for reset to properly happen. This is kinda hacky right now, but a good solution may involve a lot of work. Signed-off-by: Eric Yang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index d714422ef979..cadc940e7c0e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1572,17 +1572,24 @@ static void dcn10_apply_ctx_for_surface( if ((!pipe_ctx->surface && old_pipe_ctx->surface) || (!pipe_ctx->stream && old_pipe_ctx->stream)) { struct mpcc_cfg mpcc_cfg; + int opp_id_cached = old_pipe_ctx->mpcc->opp_id; if (!old_pipe_ctx->top_pipe) { ASSERT(0); continue; } - mpcc_cfg.opp_id = old_pipe_ctx->mpcc->opp_id; + mpcc_cfg.opp_id = 0xf; mpcc_cfg.top_dpp_id = 0xf; mpcc_cfg.bot_mpcc_id = 0xf; mpcc_cfg.top_of_tree = !old_pipe_ctx->top_pipe; old_pipe_ctx->mpcc->funcs->set(old_pipe_ctx->mpcc, &mpcc_cfg); + /* + * the mpcc is the only thing that keeps track of the mpcc + * mapping for reset front end right now. Might need some + * rework. + */ + old_pipe_ctx->mpcc->opp_id = opp_id_cached; old_pipe_ctx->top_pipe = NULL; old_pipe_ctx->bottom_pipe = NULL; -- cgit From 15e173352eeae76286e0d018f9eec6b55726caa4 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Mon, 17 Jul 2017 16:04:02 -0400 Subject: drm/amd/display: fix aviInfoFrame bar Info and add set_avMute Signed-off-by: Charlene Liu Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 10 ++++++ drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 37 ++++++++++++++++++---- .../drm/amd/display/dc/dce/dce_stream_encoder.c | 13 +++++++- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 13 ++++++-- .../amd/display/dc/dce110/dce110_hw_sequencer.h | 1 + .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 3 +- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 1 + .../gpu/drm/amd/display/dc/inc/hw/stream_encoder.h | 3 ++ drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 2 ++ .../display/dc/virtual/virtual_stream_encoder.c | 4 +++ 10 files changed, 77 insertions(+), 10 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index fed38fbab452..036d22f878b8 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1911,3 +1911,13 @@ void core_link_disable_stream(struct pipe_ctx *pipe_ctx) disable_link(pipe_ctx->stream->sink->link, pipe_ctx->stream->signal); } +void core_link_set_avmute(struct pipe_ctx *pipe_ctx, bool enable) +{ + struct core_dc *core_dc = DC_TO_CORE(pipe_ctx->stream->ctx->dc); + + if (pipe_ctx->stream->signal != SIGNAL_TYPE_HDMI_TYPE_A) + return; + + core_dc->hwss.set_avmute(pipe_ctx, enable); +} + diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 9d0128e95767..63056e8c6d78 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1607,6 +1607,8 @@ static void set_avi_info_frame( uint8_t *check_sum = NULL; uint8_t byte_index = 0; union hdmi_info_packet *hdmi_info = &info_frame.avi_info_packet.info_packet_hdmi; + unsigned int vic = pipe_ctx->stream->public.timing.vic; + enum dc_timing_3d_format format; color_space = pipe_ctx->stream->public.output_color_space; if (color_space == COLOR_SPACE_UNKNOWN) @@ -1661,8 +1663,7 @@ static void set_avi_info_frame( /* C0, C1 : Colorimetry */ if (color_space == COLOR_SPACE_YCBCR709 || - color_space == COLOR_SPACE_YCBCR709_LIMITED || - color_space == COLOR_SPACE_2020_YCBCR) + color_space == COLOR_SPACE_YCBCR709_LIMITED) hdmi_info->bits.C0_C1 = COLORIMETRY_ITU709; else if (color_space == COLOR_SPACE_YCBCR601 || color_space == COLOR_SPACE_YCBCR601_LIMITED) @@ -1722,9 +1723,29 @@ static void set_avi_info_frame( hdmi_info->bits.Q0_Q1 = RGB_QUANTIZATION_DEFAULT_RANGE; hdmi_info->bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; } - - hdmi_info->bits.VIC0_VIC7 = - stream->public.timing.vic; + ///VIC + format = stream->public.timing.timing_3d_format; + /*todo, add 3DStereo support*/ + if (format != TIMING_3D_FORMAT_NONE) { + // Based on HDMI specs hdmi vic needs to be converted to cea vic when 3D is enabled + switch (pipe_ctx->stream->public.timing.hdmi_vic) { + case 1: + vic = 95; + break; + case 2: + vic = 94; + break; + case 3: + vic = 93; + break; + case 4: + vic = 98; + break; + default: + break; + } + } + hdmi_info->bits.VIC0_VIC7 = vic; /* pixel repetition * PR0 - PR3 start from 0 whereas pHwPathMode->mode.timing.flags.pixel @@ -1737,7 +1758,7 @@ static void set_avi_info_frame( * barLeft: Pixel Number of End of Left Bar. * barRight: Pixel Number of Start of Right Bar. */ hdmi_info->bits.bar_top = stream->public.timing.v_border_top; - hdmi_info->bits.bar_bottom = (stream->public.timing.v_border_top + hdmi_info->bits.bar_bottom = (stream->public.timing.v_total - stream->public.timing.v_border_bottom + 1); hdmi_info->bits.bar_left = stream->public.timing.h_border_left; hdmi_info->bits.bar_right = (stream->public.timing.h_total @@ -1776,6 +1797,10 @@ static void set_vendor_info_packet( uint8_t checksum = 0; uint32_t i = 0; enum dc_timing_3d_format format; + // Can be different depending on packet content /*todo*/ + // unsigned int length = pPathMode->dolbyVision ? 24 : 5; + + info_packet->valid = false; format = stream->public.timing.timing_3d_format; if (stream->public.view_format == VIEW_3D_FORMAT_NONE) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c index daab81bd1773..532c6e638943 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c @@ -1003,6 +1003,16 @@ static void dce110_stream_encoder_dp_unblank( REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, true); } +static void dce110_stream_encoder_set_avmute( + struct stream_encoder *enc, + bool enable) +{ + struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); + unsigned int value = enable ? 1 : 0; + + REG_UPDATE(HDMI_GC, HDMI_GC_AVMUTE, value); +} + #define DP_SEC_AUD_N__DP_SEC_AUD_N__DEFAULT 0x8000 #define DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUTO_CALC 1 @@ -1582,7 +1592,6 @@ static const struct stream_encoder_funcs dce110_str_enc_funcs = { dce110_stream_encoder_dp_blank, .dp_unblank = dce110_stream_encoder_dp_unblank, - .audio_mute_control = dce110_se_audio_mute_control, .dp_audio_setup = dce110_se_dp_audio_setup, @@ -1592,6 +1601,8 @@ static const struct stream_encoder_funcs dce110_str_enc_funcs = { .hdmi_audio_setup = dce110_se_hdmi_audio_setup, .hdmi_audio_disable = dce110_se_hdmi_audio_disable, .setup_stereo_sync = setup_stereo_sync, + .set_avmute = dce110_stream_encoder_set_avmute, + }; bool dce110_stream_encoder_construct( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 5d64611eb6a6..b691ef956d45 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -801,6 +801,13 @@ void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, pipe_ctx->stream_enc->funcs->dp_unblank(pipe_ctx->stream_enc, ¶ms); } + +void dce110_set_avmute(struct pipe_ctx *pipe_ctx, bool enable) +{ + if (pipe_ctx != NULL && pipe_ctx->stream_enc != NULL) + pipe_ctx->stream_enc->funcs->set_avmute(pipe_ctx->stream_enc, enable); +} + static enum audio_dto_source translate_to_dto_source(enum controller_id crtc_id) { switch (crtc_id) { @@ -1095,10 +1102,11 @@ static enum dc_status apply_single_controller_ctx_to_hw( (pipe_ctx->stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK) ? true : false); + resource_build_info_frame(pipe_ctx); + if (!pipe_ctx_old->stream) { core_link_enable_stream(pipe_ctx); - resource_build_info_frame(pipe_ctx); dce110_update_info_frame(pipe_ctx); if (dc_is_dp_signal(pipe_ctx->stream->signal)) dce110_unblank_stream(pipe_ctx, @@ -2600,7 +2608,8 @@ static const struct hw_sequencer_funcs dce110_funcs = { .set_static_screen_control = set_static_screen_control, .reset_hw_ctx_wrap = reset_hw_ctx_wrap, .prog_pixclk_crtc_otg = dce110_prog_pixclk_crtc_otg, - .setup_stereo = NULL + .setup_stereo = NULL, + .set_avmute = dce110_set_avmute, }; bool dce110_hw_sequencer_construct(struct core_dc *dc) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h index 52462c17b2e9..89782ca1917f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h @@ -54,6 +54,7 @@ void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, void dce110_update_info_frame(struct pipe_ctx *pipe_ctx); +void dce110_set_avmute(struct pipe_ctx *pipe_ctx, bool enable); void dce110_enable_accelerated_mode(struct core_dc *dc); void dce110_power_down(struct core_dc *dc); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index cadc940e7c0e..8284837898d2 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1867,7 +1867,8 @@ static const struct hw_sequencer_funcs dcn10_funcs = { .set_drr = set_drr, .get_position = get_position, .set_static_screen_control = set_static_screen_control, - .setup_stereo = dcn10_setup_stereo + .setup_stereo = dcn10_setup_stereo, + .set_avmute = dce110_set_avmute, }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index d216522a9989..d75368030917 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -179,6 +179,7 @@ void core_link_enable_stream(struct pipe_ctx *pipe_ctx); void core_link_disable_stream(struct pipe_ctx *pipe_ctx); +void core_link_set_avmute(struct pipe_ctx *pipe_ctx, bool enable); /********** DAL Core*********************/ #include "display_clock.h" #include "transform.h" diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h index 9fb27bd360ac..6ff90a0fef24 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h @@ -123,6 +123,9 @@ struct stream_encoder_funcs { struct stream_encoder *enc, int tg_inst, bool enable); + + void (*set_avmute)( + struct stream_encoder *enc, bool enable); }; #endif /* STREAM_ENCODER_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 97dbd259f66c..d94e8e446ce5 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -152,6 +152,8 @@ struct hw_sequencer_funcs { void (*setup_stereo)( struct pipe_ctx *pipe_ctx, struct core_dc *dc); + + void (*set_avmute)(struct pipe_ctx *pipe_ctx, bool enable); }; void color_space_to_black_color( diff --git a/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c index 8de21d9a8079..7fe6085e6e37 100644 --- a/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c @@ -53,6 +53,9 @@ static void virtual_stream_encoder_update_hdmi_info_packets( static void virtual_stream_encoder_stop_hdmi_info_packets( struct stream_encoder *enc) {} +static void virtual_stream_encoder_set_avmute( + struct stream_encoder *enc, + bool enable) {} static void virtual_stream_encoder_update_dp_info_packets( struct stream_encoder *enc, const struct encoder_info_frame *info_frame) {} @@ -94,6 +97,7 @@ static const struct stream_encoder_funcs virtual_str_enc_funcs = { virtual_stream_encoder_dp_unblank, .audio_mute_control = virtual_audio_mute_control, + .set_avmute = virtual_stream_encoder_set_avmute, }; bool virtual_stream_encoder_construct( -- cgit From d65359d571aa33dee9ddae659e92d1cb09ffbb2a Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Fri, 14 Jul 2017 13:42:23 -0400 Subject: drm/amd/display: revert order change of HUBP and MPC disable - root cause was we disable opp clk in MPC disconnect - hubp_blank is not double buffered, so we can't blank until MPC disconnect or we have risk of underflow Signed-off-by: Tony Cheng Reviewed-by: Eric Yang Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h | 2 -- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 41 +++++++++++++--------- .../gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c | 5 +++ .../gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h | 2 ++ 4 files changed, 32 insertions(+), 18 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index 7e1d46fdcc76..94d12b5fb7c6 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -288,7 +288,6 @@ struct dce_hwseq_registers { HWS_SF1(OTG0_, PHYPLL_PIXEL_RATE_CNTL, PHYPLL_PIXEL_RATE_SOURCE, mask_sh), \ HWS_SF(OTG0_, OTG_GLOBAL_SYNC_STATUS, VUPDATE_NO_LOCK_EVENT_CLEAR, mask_sh), \ HWS_SF(OTG0_, OTG_GLOBAL_SYNC_STATUS, VUPDATE_NO_LOCK_EVENT_OCCURRED, mask_sh), \ - HWS_SF(HUBP0_, DCHUBP_CNTL, HUBP_NO_OUTSTANDING_REQ, mask_sh), \ HWS_SF(HUBP0_, DCHUBP_CNTL, HUBP_VTG_SEL, mask_sh), \ HWS_SF(HUBP0_, HUBP_CLK_CNTL, HUBP_CLOCK_ENABLE, mask_sh), \ HWS_SF(DPP_TOP0_, DPP_CONTROL, DPP_CLOCK_ENABLE, mask_sh), \ @@ -351,7 +350,6 @@ struct dce_hwseq_registers { #define HWSEQ_DCN_REG_FIELD_LIST(type) \ type VUPDATE_NO_LOCK_EVENT_CLEAR; \ type VUPDATE_NO_LOCK_EVENT_OCCURRED; \ - type HUBP_NO_OUTSTANDING_REQ; \ type HUBP_VTG_SEL; \ type HUBP_CLOCK_ENABLE; \ type DPP_CLOCK_ENABLE; \ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 8284837898d2..adf3d2990687 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -436,29 +436,17 @@ static void reset_back_end_for_pipe( pipe_ctx->pipe_idx, pipe_ctx->tg->inst); } -static void reset_front_end( +static void plane_atomic_stop( struct core_dc *dc, int fe_idx) { - struct dce_hwseq *hws = dc->hwseq; struct mpcc_cfg mpcc_cfg; struct mem_input *mi = dc->res_pool->mis[fe_idx]; struct transform *xfm = dc->res_pool->transforms[fe_idx]; struct mpcc *mpcc = dc->res_pool->mpcc[fe_idx]; struct timing_generator *tg = dc->res_pool->timing_generators[mpcc->opp_id]; - unsigned int opp_id = mpcc->opp_id; - - /*Already reset*/ - if (opp_id == 0xf) - return; - - tg->funcs->lock(tg); mi->funcs->dcc_control(mi, false, false); - mi->funcs->set_blank(mi, true); - REG_WAIT(DCHUBP_CNTL[fe_idx], - HUBP_NO_OUTSTANDING_REQ, 1, - 1, 200); mpcc_cfg.opp_id = 0xf; mpcc_cfg.top_dpp_id = 0xf; @@ -466,23 +454,44 @@ static void reset_front_end( mpcc_cfg.top_of_tree = tg->inst == mpcc->inst; mpcc->funcs->set(mpcc, &mpcc_cfg); + xfm->funcs->transform_reset(xfm); +} + +static void reset_front_end( + struct core_dc *dc, + int fe_idx) +{ + struct dce_hwseq *hws = dc->hwseq; + struct mem_input *mi = dc->res_pool->mis[fe_idx]; + struct mpcc *mpcc = dc->res_pool->mpcc[fe_idx]; + struct timing_generator *tg = dc->res_pool->timing_generators[mpcc->opp_id]; + unsigned int opp_id = mpcc->opp_id; + + /*Already reset*/ + if (opp_id == 0xf) + return; + + tg->funcs->lock(tg); + + plane_atomic_stop(dc, fe_idx); + REG_UPDATE(OTG_GLOBAL_SYNC_STATUS[tg->inst], VUPDATE_NO_LOCK_EVENT_CLEAR, 1); tg->funcs->unlock(tg); REG_WAIT(OTG_GLOBAL_SYNC_STATUS[tg->inst], VUPDATE_NO_LOCK_EVENT_OCCURRED, 1, 20000, 200000); mpcc->funcs->wait_for_idle(mpcc); + mi->funcs->set_blank(mi, true); + REG_UPDATE(HUBP_CLK_CNTL[fe_idx], HUBP_CLOCK_ENABLE, 0); REG_UPDATE(DPP_CONTROL[fe_idx], DPP_CLOCK_ENABLE, 0); - if (mpcc_cfg.top_of_tree) + if (tg->inst == mpcc->inst) REG_UPDATE(OPP_PIPE_CONTROL[opp_id], OPP_PIPE_CLOCK_EN, 0); - xfm->funcs->transform_reset(xfm); - dm_logger_write(dc->ctx->logger, LOG_DC, "Reset front end %d\n", fe_idx); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index efa02d160d1a..8054794dd96d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -46,6 +46,11 @@ static void min10_set_blank(struct mem_input *mem_input, bool blank) REG_UPDATE_2(DCHUBP_CNTL, HUBP_BLANK_EN, blank_en, HUBP_TTU_DISABLE, blank_en); + + if (blank) + REG_WAIT(DCHUBP_CNTL, + HUBP_NO_OUTSTANDING_REQ, 1, + 1, 200); } static void min10_vready_workaround(struct mem_input *mem_input, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h index 7efa857b8710..a0a1cef38d18 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h @@ -304,6 +304,7 @@ struct dcn_mi_registers { #define MI_MASK_SH_LIST_DCN(mask_sh)\ MI_SF(HUBP0_DCHUBP_CNTL, HUBP_BLANK_EN, mask_sh),\ MI_SF(HUBP0_DCHUBP_CNTL, HUBP_TTU_DISABLE, mask_sh),\ + MI_SF(HUBP0_DCHUBP_CNTL, HUBP_NO_OUTSTANDING_REQ, mask_sh),\ MI_SF(HUBP0_DCSURF_ADDR_CONFIG, NUM_PIPES, mask_sh),\ MI_SF(HUBP0_DCSURF_ADDR_CONFIG, NUM_BANKS, mask_sh),\ MI_SF(HUBP0_DCSURF_ADDR_CONFIG, PIPE_INTERLEAVE, mask_sh),\ @@ -463,6 +464,7 @@ struct dcn_mi_registers { #define DCN_MI_REG_FIELD_LIST(type) \ type HUBP_BLANK_EN;\ type HUBP_TTU_DISABLE;\ + type HUBP_NO_OUTSTANDING_REQ;\ type NUM_PIPES;\ type NUM_BANKS;\ type PIPE_INTERLEAVE;\ -- cgit From 2233ec72b350fb8480f67b83f6a71ea422af60a3 Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Tue, 18 Jul 2017 10:21:43 -0400 Subject: drm/amd/display: Add regkey for DRR control for internal panel Also need to change default to off Signed-off-by: Anthony Koo Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 1 - .../drm/amd/display/modules/freesync/freesync.c | 74 ++++++++++++---------- .../gpu/drm/amd/display/modules/inc/mod_freesync.h | 1 - 3 files changed, 40 insertions(+), 36 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 6a22c91cbcef..07f064f53d85 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -188,7 +188,6 @@ struct dc_debug { bool disable_dmcu; bool disable_psr; bool force_abm_enable; - bool no_static_for_external_dp; }; struct dc { diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index 4df79f7147f8..a989d5de9f3c 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -43,6 +43,10 @@ #define FREESYNC_REGISTRY_NAME "freesync_v1" +#define FREESYNC_NO_STATIC_FOR_EXTERNAL_DP_REGKEY "DalFreeSyncNoStaticForExternalDp" + +#define FREESYNC_NO_STATIC_FOR_INTERNAL_REGKEY "DalFreeSyncNoStaticForInternal" + struct gradual_static_ramp { bool ramp_is_active; bool ramp_direction_is_up; @@ -114,7 +118,8 @@ struct freesync_entity { }; struct freesync_registry_options { - unsigned int min_refresh_from_edid; + bool drr_external_supported; + bool drr_internal_supported; }; struct core_freesync { @@ -176,9 +181,19 @@ struct mod_freesync *mod_freesync_create(struct dc *dc) NULL, NULL, 0, &flag); flag.save_per_edid = false; flag.save_per_link = false; + if (dm_read_persistent_data(core_dc->ctx, NULL, NULL, - "DalDrrSupport", &data, sizeof(data), &flag)) { - core_freesync->opts.min_refresh_from_edid = data; + FREESYNC_NO_STATIC_FOR_INTERNAL_REGKEY, + &data, sizeof(data), &flag)) { + core_freesync->opts.drr_internal_supported = + (data & 1) ? false : true; + } + + if (dm_read_persistent_data(core_dc->ctx, NULL, NULL, + FREESYNC_NO_STATIC_FOR_EXTERNAL_DP_REGKEY, + &data, sizeof(data), &flag)) { + core_freesync->opts.drr_external_supported = + (data & 1) ? false : true; } return &core_freesync->public; @@ -236,7 +251,7 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, struct core_freesync *core_freesync = NULL; int persistent_freesync_enable = 0; struct persistent_data_flag flag; - unsigned int nom_refresh_rate_micro_hz; + unsigned int nom_refresh_rate_uhz; unsigned long long temp; if (mod_freesync == NULL) @@ -258,20 +273,7 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, temp = div_u64(temp, stream->timing.h_total); temp = div_u64(temp, stream->timing.v_total); - nom_refresh_rate_micro_hz = (unsigned int) temp; - - if (core_freesync->opts.min_refresh_from_edid != 0 && - dc_is_embedded_signal(stream->sink->sink_signal) - && (nom_refresh_rate_micro_hz - - core_freesync->opts.min_refresh_from_edid * - 1000000) >= 10000000) { - caps->supported = true; - caps->min_refresh_in_micro_hz = - core_freesync->opts.min_refresh_from_edid * - 1000000; - caps->max_refresh_in_micro_hz = - nom_refresh_rate_micro_hz; - } + nom_refresh_rate_uhz = (unsigned int) temp; core_freesync->map[core_freesync->num_entities].stream = stream; core_freesync->map[core_freesync->num_entities].caps = caps; @@ -311,8 +313,8 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, } if (caps->supported && - nom_refresh_rate_micro_hz >= caps->min_refresh_in_micro_hz && - nom_refresh_rate_micro_hz <= caps->max_refresh_in_micro_hz) + nom_refresh_rate_uhz >= caps->min_refresh_in_micro_hz && + nom_refresh_rate_uhz <= caps->max_refresh_in_micro_hz) core_stream->public.ignore_msa_timing_param = 1; core_freesync->num_entities++; @@ -865,6 +867,11 @@ void mod_freesync_update_state(struct mod_freesync *mod_freesync, unsigned int map_index = map_index_from_stream(core_freesync, streams[stream_index]); + bool is_embedded = dc_is_embedded_signal( + streams[stream_index]->sink->sink_signal); + + struct freesync_registry_options *opts = &core_freesync->opts; + state = &core_freesync->map[map_index].state; switch (freesync_params->state){ @@ -875,25 +882,24 @@ void mod_freesync_update_state(struct mod_freesync *mod_freesync, freesync_params->windowed_fullscreen; break; case FREESYNC_STATE_STATIC_SCREEN: - /* Static screen ramp is only enabled for embedded - * panels. Also change core variables only if there - * is a change. + /* Static screen ramp is disabled by default, but can + * be enabled through regkey. */ - if ((dc_is_embedded_signal( - streams[stream_index]->sink->sink_signal) || - core_freesync->map[map_index].caps-> - no_static_for_external_dp == false) && - state->static_screen != - freesync_params->enable) { + if ((is_embedded && opts->drr_internal_supported) || + (!is_embedded && opts->drr_external_supported)) - /* Change the state flag */ - state->static_screen = freesync_params->enable; + if (state->static_screen != + freesync_params->enable) { - /* Change static screen ramp variables */ - set_static_ramp_variables(core_freesync, + /* Change the state flag */ + state->static_screen = + freesync_params->enable; + + /* Update static screen ramp */ + set_static_ramp_variables(core_freesync, map_index, freesync_params->enable); - } + } /* We program the ramp starting next VUpdate */ break; case FREESYNC_STATE_VIDEO: diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h b/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h index eae1b348b0dd..53c428b97902 100644 --- a/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h +++ b/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h @@ -88,7 +88,6 @@ struct mod_freesync_caps { unsigned int max_refresh_in_micro_hz; bool btr_supported; - bool no_static_for_external_dp; }; struct mod_freesync_params { -- cgit From 4bdbab3efda297b2432ae4e722385deaa0089315 Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Tue, 18 Jul 2017 15:50:47 -0400 Subject: drm/amd/display: powergate fe of reused pipes to reset ttu When we exit MPO, disconnected pipes cannot be immediately powergated because registers are double buffered, and actual disconnection does not happen until VUPDATE. So it is differred for many flips. However in the case of exiting full screen, the transition from MPO to grph only back to MPO is very fast and also involves increasing of watermarks. Since the underlay pipe is never powergated in this scenario, it keeps its old TTU counter, which causes allowPstateSwitch signal to be de-asserted when compared to the new increased watermark. Since the new pipe is not enabled yet, the signal will be continously de-asserted and hangs SMU, who's waiting for the signal to do pstate switching. Signed-off-by: Eric Yang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index adf3d2990687..6543027469af 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1577,6 +1577,14 @@ static void dcn10_apply_ctx_for_surface( struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; struct pipe_ctx *old_pipe_ctx = &dc->current_context->res_ctx.pipe_ctx[i]; + /* + * Powergate reused pipes that are not powergated + * fairly hacky right now, using opp_id as indicator + */ + if (pipe_ctx->surface && !old_pipe_ctx->surface) { + if (pipe_ctx->mpcc->opp_id != 0xf) + dcn10_power_down_fe(dc, pipe_ctx->pipe_idx); + } if ((!pipe_ctx->surface && old_pipe_ctx->surface) || (!pipe_ctx->stream && old_pipe_ctx->stream)) { @@ -1588,6 +1596,7 @@ static void dcn10_apply_ctx_for_surface( continue; } + /* reset mpc */ mpcc_cfg.opp_id = 0xf; mpcc_cfg.top_dpp_id = 0xf; mpcc_cfg.bot_mpcc_id = 0xf; -- cgit From eb78d83e06371873b87a19721e7fe1503ba1d308 Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Tue, 18 Jul 2017 18:33:23 -0400 Subject: drm/amd/display: Do not release state objects on atomic check fail In any drm ioctl call, drm_atomic_state_clear() is called at the end to destroy the states; even if atomic check fails. Therefore, releasing states on atomic check failure is incorrect. Signed-off-by: Leo (Sunpeng) Li Reviewed-by: Andrey Grodzovsky Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index af4de578dadb..44d85b77e252 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2989,7 +2989,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, conn_state = drm_atomic_get_connector_state(state, &aconnector->base); if (IS_ERR(conn_state)) { ret = PTR_ERR_OR_ZERO(conn_state); - goto fail_crtcs; + goto fail; } dm_conn_state = to_dm_connector_state(conn_state); @@ -3048,7 +3048,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, ret = drm_atomic_add_affected_planes(state, crtc); if (ret) - goto fail_crtcs; + goto fail; } } @@ -3110,7 +3110,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, crtc_state, false); if (ret) - goto fail_planes; + goto fail; if (dm_plane_state->surface) @@ -3142,13 +3142,12 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, ret = do_aquire_global_lock(dev, state); if (ret) - goto fail_planes; - + goto fail; WARN_ON(dm_state->context); dm_state->context = dc_get_validate_context(dc, set, set_count); if (!dm_state->context) { ret = -EINVAL; - goto fail_planes; + goto fail; } } @@ -3156,15 +3155,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, WARN_ON(ret); return ret; -fail_planes: - for (i = 0; i < set_count; i++) - for (j = 0; j < set[i].surface_count; j++) - dc_surface_release(set[i].surfaces[j]); - -fail_crtcs: - for (i = 0; i < set_count; i++) - dc_stream_release(set[i].stream); - +fail: if (ret == -EDEADLK) DRM_DEBUG_KMS("Atomic check stopped due to to deadlock.\n"); else if (ret == -EINTR || ret == -EAGAIN || ret == -ERESTARTSYS) -- cgit From d8bad05a62a72975cab549f875e0fe2d159169c4 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 24 Jul 2017 17:23:45 -0400 Subject: drm/amd/include: Add DC_PINSTRAPS.AUDIO defines Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/include/asic_reg/raven1/DCN/dcn_1_0_offset.h | 2 ++ drivers/gpu/drm/amd/include/asic_reg/raven1/DCN/dcn_1_0_sh_mask.h | 3 +++ 2 files changed, 5 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/include/asic_reg/raven1/DCN/dcn_1_0_offset.h b/drivers/gpu/drm/amd/include/asic_reg/raven1/DCN/dcn_1_0_offset.h index b39fb6821faa..3580218702ce 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/raven1/DCN/dcn_1_0_offset.h +++ b/drivers/gpu/drm/amd/include/asic_reg/raven1/DCN/dcn_1_0_offset.h @@ -10361,6 +10361,8 @@ #define mmUNIPHYG_CHANNEL_XBAR_CNTL_BASE_IDX 2 #define mmDCIO_WRCMD_DELAY 0x287e #define mmDCIO_WRCMD_DELAY_BASE_IDX 2 +#define mmDC_PINSTRAPS 0x2880 +#define mmDC_PINSTRAPS_BASE_IDX 2 #define mmDC_DVODATA_CONFIG 0x2882 #define mmDC_DVODATA_CONFIG_BASE_IDX 2 #define mmLVTMA_PWRSEQ_CNTL 0x2883 diff --git a/drivers/gpu/drm/amd/include/asic_reg/raven1/DCN/dcn_1_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/raven1/DCN/dcn_1_0_sh_mask.h index 1e98ce86ed19..ecbe5bfa989b 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/raven1/DCN/dcn_1_0_sh_mask.h +++ b/drivers/gpu/drm/amd/include/asic_reg/raven1/DCN/dcn_1_0_sh_mask.h @@ -39956,6 +39956,9 @@ #define DCIO_WRCMD_DELAY__DPHY_DELAY_MASK 0x00000F00L #define DCIO_WRCMD_DELAY__DCRXPHY_DELAY_MASK 0x0000F000L #define DCIO_WRCMD_DELAY__ZCAL_DELAY_MASK 0x000F0000L +//DC_PINSTRAPS +#define DC_PINSTRAPS__DC_PINSTRAPS_AUDIO__SHIFT 0xe +#define DC_PINSTRAPS__DC_PINSTRAPS_AUDIO_MASK 0x0000C000L //DC_DVODATA_CONFIG #define DC_DVODATA_CONFIG__VIP_MUX_EN__SHIFT 0x13 #define DC_DVODATA_CONFIG__VIP_ALTER_MAPPING_EN__SHIFT 0x14 -- cgit From ee87a45e95a859a9df5a623d532dd472535cd6ea Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 25 Jul 2017 10:56:49 -0400 Subject: drm/amd/include: Add DCHUBBUB_TEST_DEBUG register defines Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/include/asic_reg/raven1/DCN/dcn_1_0_offset.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/include/asic_reg/raven1/DCN/dcn_1_0_offset.h b/drivers/gpu/drm/amd/include/asic_reg/raven1/DCN/dcn_1_0_offset.h index 3580218702ce..4ccf9681c45d 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/raven1/DCN/dcn_1_0_offset.h +++ b/drivers/gpu/drm/amd/include/asic_reg/raven1/DCN/dcn_1_0_offset.h @@ -2283,6 +2283,10 @@ #define mmDCHUBBUB_VLINE_SNAPSHOT_BASE_IDX 2 #define mmDCHUBBUB_SPARE 0x0534 #define mmDCHUBBUB_SPARE_BASE_IDX 2 +#define mmDCHUBBUB_TEST_DEBUG_INDEX 0x053a +#define mmDCHUBBUB_TEST_DEBUG_INDEX_BASE_IDX 2 +#define mmDCHUBBUB_TEST_DEBUG_DATA 0x053b +#define mmDCHUBBUB_TEST_DEBUG_DATA_BASE_IDX 2 // addressBlock: dce_dc_dchubbub_dchubbub_dcperfmon_dc_perfmon_dispdec -- cgit From 20e9b0718babaaea9912ad5481a5089292c451a6 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Fri, 4 Aug 2017 16:20:10 -0400 Subject: drm/amd: Add missing SURFACE_TMZ register shift/mask Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/include/asic_reg/raven1/DCN/dcn_1_0_sh_mask.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/include/asic_reg/raven1/DCN/dcn_1_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/raven1/DCN/dcn_1_0_sh_mask.h index ecbe5bfa989b..b28d4b64c05d 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/raven1/DCN/dcn_1_0_sh_mask.h +++ b/drivers/gpu/drm/amd/include/asic_reg/raven1/DCN/dcn_1_0_sh_mask.h @@ -9361,12 +9361,14 @@ #define HUBPREQ0_DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH_C__SECONDARY_META_SURFACE_ADDRESS_HIGH_C__SHIFT 0x0 #define HUBPREQ0_DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH_C__SECONDARY_META_SURFACE_ADDRESS_HIGH_C_MASK 0x0000FFFFL //HUBPREQ0_DCSURF_SURFACE_CONTROL +#define HUBPREQ0_DCSURF_SURFACE_CONTROL__PRIMARY_SURFACE_TMZ__SHIFT 0x0 #define HUBPREQ0_DCSURF_SURFACE_CONTROL__PRIMARY_SURFACE_DCC_EN__SHIFT 0x1 #define HUBPREQ0_DCSURF_SURFACE_CONTROL__PRIMARY_SURFACE_DCC_IND_64B_BLK__SHIFT 0x2 #define HUBPREQ0_DCSURF_SURFACE_CONTROL__PRIMARY_SURFACE_DCC_IND_64B_BLK_C__SHIFT 0x5 #define HUBPREQ0_DCSURF_SURFACE_CONTROL__SECONDARY_SURFACE_DCC_EN__SHIFT 0x9 #define HUBPREQ0_DCSURF_SURFACE_CONTROL__SECONDARY_SURFACE_DCC_IND_64B_BLK__SHIFT 0xa #define HUBPREQ0_DCSURF_SURFACE_CONTROL__SECONDARY_SURFACE_DCC_IND_64B_BLK_C__SHIFT 0xd +#define HUBPREQ0_DCSURF_SURFACE_CONTROL__PRIMARY_SURFACE_TMZ_MASK 0x00000001L #define HUBPREQ0_DCSURF_SURFACE_CONTROL__PRIMARY_SURFACE_DCC_EN_MASK 0x00000002L #define HUBPREQ0_DCSURF_SURFACE_CONTROL__PRIMARY_SURFACE_DCC_IND_64B_BLK_MASK 0x00000004L #define HUBPREQ0_DCSURF_SURFACE_CONTROL__PRIMARY_SURFACE_DCC_IND_64B_BLK_C_MASK 0x00000020L -- cgit From 6631e5a91139f317caa6c75b38553afda0fa8626 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 19 Jul 2017 14:32:21 -0400 Subject: drm/amd/display: fix dcn10_resource read_dce_straps Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 4a996f9ae468..b5f0f547ee83 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -610,12 +610,8 @@ static void read_dce_straps( struct dc_context *ctx, struct resource_straps *straps) { - /* TODO: Registers are missing */ - /*REG_GET_2(CC_DC_HDMI_STRAPS, - HDMI_DISABLE, &straps->hdmi_disable, - AUDIO_STREAM_NUMBER, &straps->audio_stream_number); - - REG_GET(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO, &straps->dc_pinstraps_audio);*/ + generic_reg_get(ctx, mmDC_PINSTRAPS + BASE(mmDC_PINSTRAPS_BASE_IDX), + FN(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO), &straps->dc_pinstraps_audio); } static struct audio *create_audio( -- cgit From 3d696cbfd48f20d482f2aab2c65ce3a540debd89 Mon Sep 17 00:00:00 2001 From: Zeyu Fan Date: Wed, 19 Jul 2017 16:46:42 -0400 Subject: drm/amd/display: Set i2c speed to 100khz for DCE11.2 and later. Signed-off-by: Zeyu Fan Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c index 983645b1be78..45e766ea79e3 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c @@ -337,6 +337,9 @@ enum { DEFAULT_I2C_SW_SPEED = 50, DEFAULT_I2C_HW_SPEED = 50, + DEFAULT_I2C_SW_SPEED_100KHZ = 100, + DEFAULT_I2C_HW_SPEED_100KHZ = 100, + /* This is the timeout as defined in DP 1.2a, * 2.3.4 "Detailed uPacket TX AUX CH State Description". */ AUX_TIMEOUT_PERIOD = 400, @@ -436,8 +439,13 @@ bool dal_i2caux_construct( i2caux->aux_timeout_period = SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD; - i2caux->default_i2c_sw_speed = DEFAULT_I2C_SW_SPEED; - i2caux->default_i2c_hw_speed = DEFAULT_I2C_HW_SPEED; + if (ctx->dce_version >= DCE_VERSION_11_2) { + i2caux->default_i2c_hw_speed = DEFAULT_I2C_HW_SPEED_100KHZ; + i2caux->default_i2c_sw_speed = DEFAULT_I2C_SW_SPEED_100KHZ; + } else { + i2caux->default_i2c_hw_speed = DEFAULT_I2C_HW_SPEED; + i2caux->default_i2c_sw_speed = DEFAULT_I2C_SW_SPEED; + } return true; } -- cgit From 8ee65d7c93cb082d6c1ca584b7565c1cc08e7861 Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Wed, 19 Jul 2017 13:18:26 -0400 Subject: drm/amd/display: Return hpd_irq_dpcd from hpd_rx handler Signed-off-by: Wenjing Liu Reviewed-by: Wenjing Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 5 ++++- drivers/gpu/drm/amd/display/dc/dc.h | 3 ++- 3 files changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') 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 a41d271f21a3..26fbadba97dd 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -914,7 +914,7 @@ static void handle_hpd_rx_irq(void *param) if (aconnector->dc_link->type != dc_connection_mst_branch) mutex_lock(&aconnector->hpd_lock); - if (dc_link_handle_hpd_rx_irq(aconnector->dc_link) && + if (dc_link_handle_hpd_rx_irq(aconnector->dc_link, NULL) && !is_mst_root_connector) { /* Downstream Port status changed. */ if (dc_link_detect(aconnector->dc_link, false)) { 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 dd3f57fce834..445cd226d36d 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 @@ -1924,7 +1924,7 @@ static void handle_automated_test(struct core_link *link) sizeof(test_response)); } -bool dc_link_handle_hpd_rx_irq(const struct dc_link *dc_link) +bool dc_link_handle_hpd_rx_irq(const struct dc_link *dc_link, union hpd_irq_data *out_hpd_irq_dpcd_data) { struct core_link *link = DC_LINK_TO_LINK(dc_link); union hpd_irq_data hpd_irq_dpcd_data = {{{{0}}}}; @@ -1939,12 +1939,15 @@ bool dc_link_handle_hpd_rx_irq(const struct dc_link *dc_link) "%s: Got short pulse HPD on link %d\n", __func__, link->public.link_index); + /* All the "handle_hpd_irq_xxx()" methods * should be called only after * dal_dpsst_ls_read_hpd_irq_data * Order of calls is important too */ result = read_hpd_rx_irq_data(link, &hpd_irq_dpcd_data); + if (out_hpd_irq_dpcd_data) + *out_hpd_irq_dpcd_data = hpd_irq_dpcd_data; if (result != DC_OK) { dm_logger_write(link->ctx->logger, LOG_HW_HPD_IRQ, diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 07f064f53d85..7ecbff792e66 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -755,7 +755,8 @@ bool dc_link_detect(const struct dc_link *dc_link, bool boot); * detection. * false - no change in Downstream port status. No further action required * from DM. */ -bool dc_link_handle_hpd_rx_irq(const struct dc_link *dc_link); +bool dc_link_handle_hpd_rx_irq(const struct dc_link *dc_link, + union hpd_irq_data *hpd_irq_dpcd_data); struct dc_sink_init_data; -- cgit From 72f0281d34b464121f9f6b75a2d7a2502055ec79 Mon Sep 17 00:00:00 2001 From: Roman Li Date: Wed, 19 Jul 2017 16:59:14 -0400 Subject: drm/amd/display: fix index and union overwrite in compressor Fixing 2 bugs in compressor: - array out of bounds due to incorrect index - compressor options always 0 due to union overwrite Signed-off-by: Roman Li Reviewed-by: Bhawanpreet Lakha Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c | 4 ++-- drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c | 4 ++-- drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c index 1e59f4e31a6a..9759d8e790a3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c @@ -198,7 +198,7 @@ void dce110_compressor_enable_fbc( /* Keep track of enum controller_id FBC is attached to */ compressor->is_enabled = true; compressor->attached_inst = params->inst; - cp110->offsets = reg_offsets[params->inst - 1]; + cp110->offsets = reg_offsets[params->inst]; /*Toggle it as there is bug in HW */ set_reg_field_value(value, 0, FBC_CNTL, FBC_GRPH_COMP_EN); @@ -469,6 +469,7 @@ bool dce110_compressor_construct(struct dce110_compressor *compressor, struct dc_context *ctx) { + compressor->base.options.raw = 0; compressor->base.options.bits.FBC_SUPPORT = true; /* for dce 11 always use one dram channel for lpt */ @@ -490,7 +491,6 @@ bool dce110_compressor_construct(struct dce110_compressor *compressor, compressor->base.allocated_size = 0; compressor->base.preferred_requested_size = 0; compressor->base.min_compress_ratio = FBC_COMPRESS_RATIO_INVALID; - compressor->base.options.raw = 0; compressor->base.banks_num = 0; compressor->base.raw_size = 0; compressor->base.channel_interleave_size = 0; diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c index 22a5aba073ca..75af2125344b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c @@ -404,7 +404,7 @@ void dce112_compressor_enable_fbc( /* Keep track of enum controller_id FBC is attached to */ compressor->is_enabled = true; compressor->attached_inst = params->inst; - cp110->offsets = reg_offsets[params->inst - 1]; + cp110->offsets = reg_offsets[params->inst]; /*Toggle it as there is bug in HW */ set_reg_field_value(value, 0, FBC_CNTL, FBC_GRPH_COMP_EN); @@ -797,6 +797,7 @@ bool dce112_compressor_construct(struct dce112_compressor *compressor, struct dc_bios *bp = ctx->dc_bios; struct embedded_panel_info panel_info; + compressor->base.options.raw = 0; compressor->base.options.bits.FBC_SUPPORT = true; compressor->base.options.bits.LPT_SUPPORT = true; /* For DCE 11 always use one DRAM channel for LPT */ @@ -817,7 +818,6 @@ bool dce112_compressor_construct(struct dce112_compressor *compressor, compressor->base.allocated_size = 0; compressor->base.preferred_requested_size = 0; compressor->base.min_compress_ratio = FBC_COMPRESS_RATIO_INVALID; - compressor->base.options.raw = 0; compressor->base.banks_num = 0; compressor->base.raw_size = 0; compressor->base.channel_interleave_size = 0; diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.c index eeedb7c4fe53..77626d7624c6 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.c @@ -407,7 +407,7 @@ void dce80_compressor_enable_fbc( /* Keep track of enum controller_id FBC is attached to */ compressor->is_enabled = true; compressor->attached_inst = params->inst; - cp80->offsets = reg_offsets[params->inst - 1]; + cp80->offsets = reg_offsets[params->inst]; /*Toggle it as there is bug in HW */ set_reg_field_value(value, 0, FBC_CNTL, FBC_GRPH_COMP_EN); @@ -777,6 +777,7 @@ bool dce80_compressor_construct(struct dce80_compressor *compressor, struct dc_bios *bp = ctx->dc_bios; struct embedded_panel_info panel_info; + compressor->base.options.raw = 0; compressor->base.options.bits.FBC_SUPPORT = true; compressor->base.options.bits.LPT_SUPPORT = true; /* For DCE 11 always use one DRAM channel for LPT */ @@ -797,7 +798,6 @@ bool dce80_compressor_construct(struct dce80_compressor *compressor, compressor->base.allocated_size = 0; compressor->base.preferred_requested_size = 0; compressor->base.min_compress_ratio = FBC_COMPRESS_RATIO_INVALID; - compressor->base.options.raw = 0; compressor->base.banks_num = 0; compressor->base.raw_size = 0; compressor->base.channel_interleave_size = 0; -- cgit From fc0956909f24d2cd6f69777881bcccd771a06f35 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Wed, 12 Jul 2017 22:00:34 -0400 Subject: drm/amd/display: register programming consolidation remove redundant DPP_CLOCK_ENABLE in ipp. clock programmed by HWSS Signed-off-by: Tony Cheng Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c | 1 - drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h | 2 -- 2 files changed, 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c index 4910d4c59b31..53dd9a9593f0 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c @@ -418,7 +418,6 @@ static void ippn10_enable_cm_block( { struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); - REG_UPDATE(DPP_CONTROL, DPP_CLOCK_ENABLE, 1); REG_UPDATE(CM_CONTROL, CM_BYPASS_EN, 0); } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h index 1703589623b0..f14e208dbf1c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h @@ -235,7 +235,6 @@ IPP_SF(CM0_CM_DGAM_LUT_WRITE_EN_MASK, CM_DGAM_LUT_WRITE_SEL, mask_sh), \ IPP_SF(CM0_CM_DGAM_LUT_INDEX, CM_DGAM_LUT_INDEX, mask_sh), \ IPP_SF(CM0_CM_DGAM_LUT_DATA, CM_DGAM_LUT_DATA, mask_sh), \ - IPP_SF(DPP_TOP0_DPP_CONTROL, DPP_CLOCK_ENABLE, mask_sh), \ IPP_SF(CNVC_CFG0_CNVC_SURFACE_PIXEL_FORMAT, CNVC_SURFACE_PIXEL_FORMAT, mask_sh), \ IPP_SF(CNVC_CFG0_FORMAT_CONTROL, CNVC_BYPASS, mask_sh), \ IPP_SF(CNVC_CFG0_FORMAT_CONTROL, ALPHA_EN, mask_sh), \ @@ -433,7 +432,6 @@ type CM_DGAM_LUT_WRITE_SEL; \ type CM_DGAM_LUT_INDEX; \ type CM_DGAM_LUT_DATA; \ - type DPP_CLOCK_ENABLE; \ type CM_BYPASS_EN; \ type CM_BYPASS; \ type CNVC_SURFACE_PIXEL_FORMAT; \ -- cgit From 6d244be884d20b1e9c912291a242dccedd6d9040 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Thu, 20 Jul 2017 00:12:20 -0400 Subject: drm/amd/display: plumbing to allow easy print of HW state for DTN Signed-off-by: Tony Cheng Reviewed-by: Wesley Chalmers Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 7 +++++++ drivers/gpu/drm/amd/display/dc/dc.h | 2 ++ drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 12 ++++++++++++ drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 2 ++ drivers/gpu/drm/amd/display/include/logger_interface.h | 4 ++++ 5 files changed, 27 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index eda36c7a5c57..ad1b90563eb6 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -2035,3 +2035,10 @@ bool dc_init_dchub(struct dc *dc, struct dchub_init_data *dh_data) } +void dc_log_hw_state(struct dc *dc) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + + if (core_dc->hwss.log_hw_state) + core_dc->hwss.log_hw_state(core_dc); +} diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 7ecbff792e66..7b8e11c28c62 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -236,6 +236,8 @@ void dc_destroy(struct dc **dc); bool dc_init_dchub(struct dc *dc, struct dchub_init_data *dh_data); +void dc_log_hw_state(struct dc *dc); + /******************************************************************************* * Surface Interfaces ******************************************************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 6543027469af..c0aa32b71ad1 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1851,6 +1851,17 @@ static void dcn10_setup_stereo(struct pipe_ctx *pipe_ctx, struct core_dc *dc) return; } +static void dcn10_log_hw_state(struct core_dc *dc) +{ + struct dc_context *dc_ctx = dc->ctx; + + DTN_INFO("%s: Hello World", __func__); + + /* todo: add meaningful register reads and print out HW state + * + */ +} + static bool dcn10_dummy_display_power_gating( struct core_dc *dc, uint8_t controller_id, @@ -1887,6 +1898,7 @@ static const struct hw_sequencer_funcs dcn10_funcs = { .set_static_screen_control = set_static_screen_control, .setup_stereo = dcn10_setup_stereo, .set_avmute = dce110_set_avmute, + .log_hw_state = dcn10_log_hw_state, }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index d94e8e446ce5..4c027a98cfd3 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -154,6 +154,8 @@ struct hw_sequencer_funcs { struct core_dc *dc); void (*set_avmute)(struct pipe_ctx *pipe_ctx, bool enable); + + void (*log_hw_state)(struct core_dc *dc); }; void color_space_to_black_color( diff --git a/drivers/gpu/drm/amd/display/include/logger_interface.h b/drivers/gpu/drm/amd/display/include/logger_interface.h index ce5fef243b09..c861e726cd8f 100644 --- a/drivers/gpu/drm/amd/display/include/logger_interface.h +++ b/drivers/gpu/drm/amd/display/include/logger_interface.h @@ -123,6 +123,10 @@ void context_clock_trace( dm_logger_write(dc_ctx->logger, LOG_ERROR, \ __VA_ARGS__); +#define DTN_INFO(...) \ + dm_logger_write(dc_ctx->logger, LOG_DTN, \ + __VA_ARGS__) + #define DC_SYNC_INFO(...) \ dm_logger_write(dc_ctx->logger, LOG_SYNC, \ __VA_ARGS__); -- cgit From 2b13d7d380d50811fd4fc022d135c3c5bb70a418 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Fri, 14 Jul 2017 14:07:16 -0400 Subject: drm/amd/display: mpo debug sanity checks Signed-off-by: Tony Cheng Reviewed-by: Eric Yang Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 1 + drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h | 6 + .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 152 ++++++++++++++++++++- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c | 21 +++ .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 1 + 5 files changed, 179 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 7b8e11c28c62..617270829936 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -160,6 +160,7 @@ struct dc_config { struct dc_debug { bool surface_visual_confirm; + bool sanity_checks; bool max_disp_clk; bool surface_trace; bool timing_trace; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index 94d12b5fb7c6..0479554bc231 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -147,6 +147,9 @@ SRII(OPP_PIPE_CONTROL, OPP_PIPE, 3), \ SR(REFCLK_CNTL), \ SR(DCHUBBUB_GLOBAL_TIMER_CNTL), \ + SR(DCHUBBUB_ARB_DRAM_STATE_CNTL), \ + SR(DCHUBBUB_TEST_DEBUG_INDEX), \ + SR(DCHUBBUB_TEST_DEBUG_DATA), \ SR(DC_IP_REQUEST_CNTL), \ SR(DOMAIN0_PG_CONFIG), \ SR(DOMAIN1_PG_CONFIG), \ @@ -195,6 +198,9 @@ struct dce_hwseq_registers { uint32_t OPP_PIPE_CONTROL[4]; uint32_t REFCLK_CNTL; uint32_t DCHUBBUB_GLOBAL_TIMER_CNTL; + uint32_t DCHUBBUB_ARB_DRAM_STATE_CNTL; + uint32_t DCHUBBUB_TEST_DEBUG_INDEX; + uint32_t DCHUBBUB_TEST_DEBUG_DATA; uint32_t DC_IP_REQUEST_CNTL; uint32_t DOMAIN0_PG_CONFIG; uint32_t DOMAIN1_PG_CONFIG; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index c0aa32b71ad1..b5a925362c8c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -52,6 +52,75 @@ #define FN(reg_name, field_name) \ hws->shifts->field_name, hws->masks->field_name + +static void verify_allow_pstate_change_high( + struct dce_hwseq *hws) +{ + /* pstate latency is ~20us so if we wait over 40us and pstate allow + * still not asserted, we are probably stuck and going to hang + */ + static unsigned int pstate_wait_timeout_us = 40; + static unsigned int max_sampled_pstate_wait_us; /* data collection */ + static bool forced_pstate_allow; /* help with revert wa */ + + unsigned int debug_index = 0x7; + unsigned int debug_data; + unsigned int force_allow_pstate = 0x30; + unsigned int i; + + if (forced_pstate_allow) { + /* we hacked to force pstate allow to prevent hang last time + * we verify_allow_pstate_change_high. so disable force + * here so we can check status + */ + REG_WRITE(DCHUBBUB_ARB_DRAM_STATE_CNTL, 0); + forced_pstate_allow = false; + } + + /* description "3-0: Pipe0 cursor0 QOS + * 7-4: Pipe1 cursor0 QOS + * 11-8: Pipe2 cursor0 QOS + * 15-12: Pipe3 cursor0 QOS + * 16: Pipe0 Plane0 Allow Pstate Change + * 17: Pipe1 Plane0 Allow Pstate Change + * 18: Pipe2 Plane0 Allow Pstate Change + * 19: Pipe3 Plane0 Allow Pstate Change + * 20: Pipe0 Plane1 Allow Pstate Change + * 21: Pipe1 Plane1 Allow Pstate Change + * 22: Pipe2 Plane1 Allow Pstate Change + * 23: Pipe3 Plane1 Allow Pstate Change + * 24: Pipe0 cursor0 Allow Pstate Change + * 25: Pipe1 cursor0 Allow Pstate Change + * 26: Pipe2 cursor0 Allow Pstate Change + * 27: Pipe3 cursor0 Allow Pstate Change + * 28: WB0 Allow Pstate Change + * 29: WB1 Allow Pstate Change + * 30: Arbiter's allow_pstate_change + * 31: SOC pstate change request + */ + + REG_WRITE(DCHUBBUB_TEST_DEBUG_INDEX, debug_index); + + for (i = 0; i < pstate_wait_timeout_us; i++) { + debug_data = REG_READ(DCHUBBUB_TEST_DEBUG_DATA); + + if (debug_data & (1 << 30)) + return; + + if (max_sampled_pstate_wait_us < i) + max_sampled_pstate_wait_us = i; + + udelay(1); + } + + /* force pstate allow to prevent system hang + * and break to debugger to investigate + */ + REG_WRITE(DCHUBBUB_ARB_DRAM_STATE_CNTL, force_allow_pstate); + forced_pstate_allow = true; + BREAK_TO_DEBUGGER(); +} + static void enable_dppclk( struct dce_hwseq *hws, uint8_t plane_id, @@ -477,12 +546,19 @@ static void reset_front_end( REG_UPDATE(OTG_GLOBAL_SYNC_STATUS[tg->inst], VUPDATE_NO_LOCK_EVENT_CLEAR, 1); tg->funcs->unlock(tg); + + if (dc->public.debug.sanity_checks) + verify_allow_pstate_change_high(dc->hwseq); + REG_WAIT(OTG_GLOBAL_SYNC_STATUS[tg->inst], VUPDATE_NO_LOCK_EVENT_OCCURRED, 1, 20000, 200000); mpcc->funcs->wait_for_idle(mpcc); mi->funcs->set_blank(mi, true); + if (dc->public.debug.sanity_checks) + verify_allow_pstate_change_high(dc->hwseq); + REG_UPDATE(HUBP_CLK_CNTL[fe_idx], HUBP_CLOCK_ENABLE, 0); REG_UPDATE(DPP_CONTROL[fe_idx], @@ -495,6 +571,9 @@ static void reset_front_end( dm_logger_write(dc->ctx->logger, LOG_DC, "Reset front end %d\n", fe_idx); + + if (dc->public.debug.sanity_checks) + verify_allow_pstate_change_high(dc->hwseq); } static void dcn10_power_down_fe(struct core_dc *dc, int fe_idx) @@ -511,6 +590,9 @@ static void dcn10_power_down_fe(struct core_dc *dc, int fe_idx) IP_REQUEST_EN, 0); dm_logger_write(dc->ctx->logger, LOG_DC, "Power gated front end %d\n", fe_idx); + + if (dc->public.debug.sanity_checks) + verify_allow_pstate_change_high(dc->hwseq); } static void reset_hw_ctx_wrap( @@ -995,10 +1077,16 @@ static void dcn10_pipe_control_lock( if (pipe->top_pipe) return; + if (dc->public.debug.sanity_checks) + verify_allow_pstate_change_high(dc->hwseq); + if (lock) pipe->tg->funcs->lock(pipe->tg); else pipe->tg->funcs->unlock(pipe->tg); + + if (dc->public.debug.sanity_checks) + verify_allow_pstate_change_high(dc->hwseq); } static bool wait_for_reset_trigger_to_occur( @@ -1516,6 +1604,12 @@ static void program_all_pipe_in_tree( /* watermark is for all pipes */ pipe_ctx->mi->funcs->program_watermarks( pipe_ctx->mi, &context->bw.dcn.watermarks, ref_clk_mhz); + + if (dc->public.debug.sanity_checks) { + /* pstate stuck check after watermark update */ + verify_allow_pstate_change_high(dc->hwseq); + } + pipe_ctx->tg->funcs->lock(pipe_ctx->tg); pipe_ctx->tg->dlg_otg_param.vready_offset = pipe_ctx->pipe_dlg_param.vready_offset; @@ -1534,6 +1628,11 @@ static void program_all_pipe_in_tree( update_dchubp_dpp(dc, pipe_ctx, context); } + if (dc->public.debug.sanity_checks) { + /* pstate stuck check after each pipe is programmed */ + verify_allow_pstate_change_high(dc->hwseq); + } + if (pipe_ctx->bottom_pipe != NULL) program_all_pipe_in_tree(dc, pipe_ctx->bottom_pipe, context); } @@ -1572,6 +1671,9 @@ static void dcn10_apply_ctx_for_surface( { int i; + if (dc->public.debug.sanity_checks) + verify_allow_pstate_change_high(dc->hwseq); + /* reset unused mpcc */ for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; @@ -1602,6 +1704,10 @@ static void dcn10_apply_ctx_for_surface( mpcc_cfg.bot_mpcc_id = 0xf; mpcc_cfg.top_of_tree = !old_pipe_ctx->top_pipe; old_pipe_ctx->mpcc->funcs->set(old_pipe_ctx->mpcc, &mpcc_cfg); + + if (dc->public.debug.sanity_checks) + verify_allow_pstate_change_high(dc->hwseq); + /* * the mpcc is the only thing that keeps track of the mpcc * mapping for reset front end right now. Might need some @@ -1679,6 +1785,9 @@ static void dcn10_apply_ctx_for_surface( context->bw.dcn.watermarks.d.cstate_pstate.pstate_change_ns, context->bw.dcn.watermarks.d.pte_meta_urgent_ns ); + + if (dc->public.debug.sanity_checks) + verify_allow_pstate_change_high(dc->hwseq); } static void dcn10_set_bandwidth( @@ -1738,6 +1847,8 @@ static void dcn10_set_bandwidth( context->bw.dcn.calc_clk.min_active_dram_ccm_us; } dcn10_pplib_apply_display_requirements(dc, context); + + /* need to fix this function. not doing the right thing here */ } static void set_drr(struct pipe_ctx **pipe_ctx, @@ -1866,7 +1977,44 @@ static bool dcn10_dummy_display_power_gating( struct core_dc *dc, uint8_t controller_id, struct dc_bios *dcb, - enum pipe_gating_control power_gating) {return true; } + enum pipe_gating_control power_gating) +{ + return true; +} + +void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx) +{ + struct core_surface *surface = pipe_ctx->surface; + struct timing_generator *tg = pipe_ctx->tg; + + if (surface->ctx->dc->debug.sanity_checks) { + struct core_dc *dc = DC_TO_CORE(surface->ctx->dc); + + verify_allow_pstate_change_high(dc->hwseq); + } + + if (surface == NULL) + return; + + surface->status.is_flip_pending = + pipe_ctx->mi->funcs->mem_input_is_flip_pending( + pipe_ctx->mi); + + /* DCN we read INUSE address in MI, do we still need this wa? */ + if (surface->status.is_flip_pending && + !surface->public.visible) { + pipe_ctx->mi->current_address = + pipe_ctx->mi->request_address; + BREAK_TO_DEBUGGER(); + } + + surface->status.current_address = pipe_ctx->mi->current_address; + if (pipe_ctx->mi->current_address.type == PLN_ADDR_TYPE_GRPH_STEREO && + tg->funcs->is_stereo_left_eye) { + surface->status.is_right_eye = + !tg->funcs->is_stereo_left_eye(pipe_ctx->tg); + } +} static const struct hw_sequencer_funcs dcn10_funcs = { .program_gamut_remap = program_gamut_remap, @@ -1876,7 +2024,7 @@ static const struct hw_sequencer_funcs dcn10_funcs = { .apply_ctx_for_surface = dcn10_apply_ctx_for_surface, .set_plane_config = set_plane_config, .update_plane_addr = update_plane_addr, - .update_pending_status = dce110_update_pending_status, + .update_pending_status = dcn10_update_pending_status, .set_input_transfer_func = dcn10_set_input_transfer_func, .set_output_transfer_func = dcn10_set_output_transfer_func, .power_down = dce110_power_down, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c index de3341d572be..9af288167e2e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c @@ -77,6 +77,24 @@ static void reset_output_mux(struct dcn10_mpcc *mpcc10) mpcc10->base.opp_id = 0xf; } +static void assert_mpcc_idle_before_connect(struct dcn10_mpcc *mpcc10) +{ + unsigned int top_sel; + unsigned int mpcc_busy, mpcc_idle, mpcc_status; + + REG_GET(MPCC_TOP_SEL, + MPCC_TOP_SEL, &top_sel); + + if (top_sel == 0xf) { + mpcc_status = REG_GET_2(MPCC_STATUS, + MPCC_BUSY, &mpcc_busy, + MPCC_IDLE, &mpcc_idle); + + ASSERT(mpcc_busy == 0); + ASSERT(mpcc_idle == 1); + } +} + static void dcn10_mpcc_set(struct mpcc *mpcc, struct mpcc_cfg *cfg) { struct dcn10_mpcc *mpcc10 = TO_DCN10_MPCC(mpcc); @@ -87,6 +105,9 @@ static void dcn10_mpcc_set(struct mpcc *mpcc, struct mpcc_cfg *cfg) bool blend_active_only = cfg->top_of_tree && !mpcc->ctx->dc->debug.surface_visual_confirm; + if (mpcc->ctx->dc->debug.sanity_checks) + assert_mpcc_idle_before_connect(mpcc10); + REG_SET(MPCC_OPP_ID, 0, MPCC_OPP_ID, cfg->opp_id); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index b5f0f547ee83..eec0d5b22a9f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -424,6 +424,7 @@ static const struct resource_caps res_cap = { static const struct dc_debug debug_defaults_drv = { .disable_dcc = false, + .sanity_checks = true, .disable_dmcu = true, .force_abm_enable = false, .timing_trace = false, -- cgit From 9b1c9b4c2eec7cb2a4d3762da7aa78aea8e34630 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Thu, 20 Jul 2017 14:51:16 -0400 Subject: drm/amd/display: update dcn register headers Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h | 7 ++++--- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h | 12 +++++++----- 2 files changed, 11 insertions(+), 8 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h index f14e208dbf1c..69db441e78c4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h @@ -87,7 +87,6 @@ SRI(CM_DGAM_CONTROL, CM, id), \ SRI(FORMAT_CONTROL, CNVC_CFG, id), \ SRI(DPP_CONTROL, DPP_TOP, id), \ - SRI(CURSOR_SETTINS, HUBPREQ, id), \ SRI(CNVC_SURFACE_PIXEL_FORMAT, CNVC_CFG, id), \ SRI(CURSOR0_CONTROL, CNVC_CUR, id), \ SRI(CURSOR0_COLOR0, CNVC_CUR, id), \ @@ -95,6 +94,7 @@ #define IPP_REG_LIST_DCN10(id) \ IPP_REG_LIST_DCN(id), \ + SRI(CURSOR_SETTINS, HUBPREQ, id), \ SRI(CM_IGAM_CONTROL, CM, id), \ SRI(CM_COMA_C11_C12, CM, id), \ SRI(CM_COMA_C13_C14, CM, id), \ @@ -240,8 +240,6 @@ IPP_SF(CNVC_CFG0_FORMAT_CONTROL, ALPHA_EN, mask_sh), \ IPP_SF(CNVC_CFG0_FORMAT_CONTROL, FORMAT_EXPANSION_MODE, mask_sh), \ IPP_SF(CM0_CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, mask_sh), \ - IPP_SF(HUBPREQ0_CURSOR_SETTINS, CURSOR0_DST_Y_OFFSET, mask_sh), \ - IPP_SF(HUBPREQ0_CURSOR_SETTINS, CURSOR0_CHUNK_HDL_ADJUST, mask_sh), \ IPP_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_MODE, mask_sh), \ IPP_SF(CNVC_CUR0_CURSOR0_COLOR0, CUR0_COLOR0, mask_sh), \ IPP_SF(CNVC_CUR0_CURSOR0_COLOR1, CUR0_COLOR1, mask_sh), \ @@ -250,6 +248,8 @@ #define IPP_MASK_SH_LIST_DCN10(mask_sh) \ IPP_MASK_SH_LIST_DCN(mask_sh),\ + IPP_SF(HUBPREQ0_CURSOR_SETTINS, CURSOR0_DST_Y_OFFSET, mask_sh), \ + IPP_SF(HUBPREQ0_CURSOR_SETTINS, CURSOR0_CHUNK_HDL_ADJUST, mask_sh), \ IPP_SF(CM0_CM_COMA_C11_C12, CM_COMA_C11, mask_sh), \ IPP_SF(CM0_CM_COMA_C11_C12, CM_COMA_C12, mask_sh), \ IPP_SF(CM0_CM_COMA_C13_C14, CM_COMA_C13, mask_sh), \ @@ -537,6 +537,7 @@ struct dcn10_ipp_registers { uint32_t CM_IGAM_CONTROL; uint32_t DPP_CONTROL; uint32_t CURSOR_SETTINS; + uint32_t CURSOR_SETTINGS; uint32_t CNVC_SURFACE_PIXEL_FORMAT; uint32_t CURSOR0_CONTROL; uint32_t CURSOR0_COLOR0; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h index a0a1cef38d18..0f4d247c4237 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h @@ -75,7 +75,6 @@ SRI(BLANK_OFFSET_1, HUBPREQ, id),\ SRI(DST_DIMENSIONS, HUBPREQ, id),\ SRI(DST_AFTER_SCALER, HUBPREQ, id),\ - SRI(PREFETCH_SETTINS, HUBPREQ, id),\ SRI(VBLANK_PARAMETERS_0, HUBPREQ, id),\ SRI(REF_FREQ_TO_PIX_FREQ, HUBPREQ, id),\ SRI(VBLANK_PARAMETERS_1, HUBPREQ, id),\ @@ -86,7 +85,6 @@ SRI(NOM_PARAMETERS_5, HUBPREQ, id),\ SRI(PER_LINE_DELIVERY_PRE, HUBPREQ, id),\ SRI(PER_LINE_DELIVERY, HUBPREQ, id),\ - SRI(PREFETCH_SETTINS_C, HUBPREQ, id),\ SRI(VBLANK_PARAMETERS_2, HUBPREQ, id),\ SRI(VBLANK_PARAMETERS_4, HUBPREQ, id),\ SRI(NOM_PARAMETERS_2, HUBPREQ, id),\ @@ -140,6 +138,8 @@ #define MI_REG_LIST_DCN10(id)\ MI_REG_LIST_DCN(id),\ + SRI(PREFETCH_SETTINS, HUBPREQ, id),\ + SRI(PREFETCH_SETTINS_C, HUBPREQ, id),\ SRI(DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, HUBPREQ, id),\ SRI(DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB, HUBPREQ, id),\ SRI(DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB, HUBPREQ, id),\ @@ -206,6 +206,7 @@ struct dcn_mi_registers { uint32_t DST_DIMENSIONS; uint32_t DST_AFTER_SCALER; uint32_t PREFETCH_SETTINS; + uint32_t PREFETCH_SETTINGS; uint32_t VBLANK_PARAMETERS_0; uint32_t REF_FREQ_TO_PIX_FREQ; uint32_t VBLANK_PARAMETERS_1; @@ -217,6 +218,7 @@ struct dcn_mi_registers { uint32_t PER_LINE_DELIVERY_PRE; uint32_t PER_LINE_DELIVERY; uint32_t PREFETCH_SETTINS_C; + uint32_t PREFETCH_SETTINGS_C; uint32_t VBLANK_PARAMETERS_2; uint32_t VBLANK_PARAMETERS_4; uint32_t NOM_PARAMETERS_2; @@ -388,8 +390,6 @@ struct dcn_mi_registers { MI_SF(HUBPREQ0_DST_DIMENSIONS, REFCYC_PER_HTOTAL, mask_sh),\ MI_SF(HUBPREQ0_DST_AFTER_SCALER, REFCYC_X_AFTER_SCALER, mask_sh),\ MI_SF(HUBPREQ0_DST_AFTER_SCALER, DST_Y_AFTER_SCALER, mask_sh),\ - MI_SF(HUBPREQ0_PREFETCH_SETTINS, DST_Y_PREFETCH, mask_sh),\ - MI_SF(HUBPREQ0_PREFETCH_SETTINS, VRATIO_PREFETCH, mask_sh),\ MI_SF(HUBPREQ0_VBLANK_PARAMETERS_0, DST_Y_PER_VM_VBLANK, mask_sh),\ MI_SF(HUBPREQ0_VBLANK_PARAMETERS_0, DST_Y_PER_ROW_VBLANK, mask_sh),\ MI_SF(HUBPREQ0_REF_FREQ_TO_PIX_FREQ, REF_FREQ_TO_PIX_FREQ, mask_sh),\ @@ -403,7 +403,6 @@ struct dcn_mi_registers { MI_SF(HUBPREQ0_PER_LINE_DELIVERY_PRE, REFCYC_PER_LINE_DELIVERY_PRE_C, mask_sh),\ MI_SF(HUBPREQ0_PER_LINE_DELIVERY, REFCYC_PER_LINE_DELIVERY_L, mask_sh),\ MI_SF(HUBPREQ0_PER_LINE_DELIVERY, REFCYC_PER_LINE_DELIVERY_C, mask_sh),\ - MI_SF(HUBPREQ0_PREFETCH_SETTINS_C, VRATIO_PREFETCH_C, mask_sh),\ MI_SF(HUBPREQ0_VBLANK_PARAMETERS_2, REFCYC_PER_PTE_GROUP_VBLANK_C, mask_sh),\ MI_SF(HUBPREQ0_VBLANK_PARAMETERS_4, REFCYC_PER_META_CHUNK_VBLANK_C, mask_sh),\ MI_SF(HUBPREQ0_NOM_PARAMETERS_2, DST_Y_PER_PTE_ROW_NOM_C, mask_sh),\ @@ -429,6 +428,9 @@ struct dcn_mi_registers { #define MI_MASK_SH_LIST_DCN10(mask_sh)\ MI_MASK_SH_LIST_DCN(mask_sh),\ + MI_SF(HUBPREQ0_PREFETCH_SETTINS, DST_Y_PREFETCH, mask_sh),\ + MI_SF(HUBPREQ0_PREFETCH_SETTINS, VRATIO_PREFETCH, mask_sh),\ + MI_SF(HUBPREQ0_PREFETCH_SETTINS_C, VRATIO_PREFETCH_C, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB, VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB, VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB, mask_sh),\ -- cgit From 7f10f3c2a761ddf3dc18be45d4ccf60db5fe10cf Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Wed, 19 Jul 2017 20:22:22 -0400 Subject: drm/amd/display: mpcc disconnect and pipe pg in multi-display still quite hacky. but this address not properly shutdown pipe video underlay + enable another display case, as well as mode changes with video overlay. Signed-off-by: Eric Yang Reviewed-by: Tony Cheng Reviewed-by: Eric Yang Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 23 +++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index b5a925362c8c..d607ca94bd13 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1669,30 +1669,46 @@ static void dcn10_apply_ctx_for_surface( struct core_surface *surface, struct validate_context *context) { - int i; + int i, be_idx; if (dc->public.debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); + if (!surface) + return; + + for (be_idx = 0; be_idx < dc->res_pool->pipe_count; be_idx++) + if (surface == context->res_ctx.pipe_ctx[be_idx].surface) + break; + /* reset unused mpcc */ for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; struct pipe_ctx *old_pipe_ctx = &dc->current_context->res_ctx.pipe_ctx[i]; + + if (!pipe_ctx->surface && !old_pipe_ctx->surface) + continue; + /* * Powergate reused pipes that are not powergated * fairly hacky right now, using opp_id as indicator */ + if (pipe_ctx->surface && !old_pipe_ctx->surface) { - if (pipe_ctx->mpcc->opp_id != 0xf) + if (pipe_ctx->mpcc->opp_id != 0xf && pipe_ctx->tg->inst == be_idx) dcn10_power_down_fe(dc, pipe_ctx->pipe_idx); } + if ((!pipe_ctx->surface && old_pipe_ctx->surface) || (!pipe_ctx->stream && old_pipe_ctx->stream)) { struct mpcc_cfg mpcc_cfg; int opp_id_cached = old_pipe_ctx->mpcc->opp_id; + if (old_pipe_ctx->tg->inst != be_idx) + continue; + if (!old_pipe_ctx->top_pipe) { ASSERT(0); continue; @@ -1725,9 +1741,6 @@ static void dcn10_apply_ctx_for_surface( } } - if (!surface) - return; - for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; -- cgit From aa9850705fc05b7e7f44558e30705ac54579e724 Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Thu, 20 Jul 2017 16:17:17 -0400 Subject: drm/amd/display: fix locking in apply_ctx_for_surface Signed-off-by: Eric Yang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index d607ca94bd13..6db78d9f8e3b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1696,8 +1696,14 @@ static void dcn10_apply_ctx_for_surface( */ if (pipe_ctx->surface && !old_pipe_ctx->surface) { - if (pipe_ctx->mpcc->opp_id != 0xf && pipe_ctx->tg->inst == be_idx) + if (pipe_ctx->mpcc->opp_id != 0xf && pipe_ctx->tg->inst == be_idx) { dcn10_power_down_fe(dc, pipe_ctx->pipe_idx); + /* + * power down fe will unlock when calling reset, need + * to lock it back here. Messy, need rework. + */ + pipe_ctx->tg->funcs->lock(pipe_ctx->tg); + } } -- cgit From 98e4a22f02da4a66f7652a3301dcb689b739e521 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Tue, 18 Jul 2017 20:13:05 -0400 Subject: drm/amd/display: revert dcn10 soc defaults to 17 19 Signed-off-by: Dmytro Laktyushkin Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 0ea0dab49e0f..a1eabc47558e 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -37,8 +37,8 @@ /* Defaults from spreadsheet rev#247 */ const struct dcn_soc_bounding_box dcn10_soc_defaults = { /* latencies */ - .sr_exit_time = 13, /*us*/ - .sr_enter_plus_exit_time = 15, /*us*/ + .sr_exit_time = 17, /*us*/ + .sr_enter_plus_exit_time = 19, /*us*/ .urgent_latency = 4, /*us*/ .dram_clock_change_latency = 17, /*us*/ .write_back_latency = 12, /*us*/ -- cgit From 50e27654d778114382093eecc1d6e5b7e9343d23 Mon Sep 17 00:00:00 2001 From: Zeyu Fan Date: Thu, 20 Jul 2017 19:04:56 -0400 Subject: drm/amd/display: Implement logic for hdmi info packet bits. Signed-off-by: Zeyu Fan Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 68 +++++++++++++++++++---- drivers/gpu/drm/amd/display/dc/dc_types.h | 25 +++++++++ 2 files changed, 83 insertions(+), 10 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 63056e8c6d78..5acc5cdcda16 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1603,10 +1603,13 @@ static void set_avi_info_frame( enum scanning_type scan_type = SCANNING_TYPE_NODATA; enum dc_aspect_ratio aspect = ASPECT_RATIO_NO_DATA; bool itc = false; + uint8_t itc_value = 0; uint8_t cn0_cn1 = 0; + unsigned int cn0_cn1_value = 0; uint8_t *check_sum = NULL; uint8_t byte_index = 0; union hdmi_info_packet *hdmi_info = &info_frame.avi_info_packet.info_packet_hdmi; + union display_content_support support = {0}; unsigned int vic = pipe_ctx->stream->public.timing.vic; enum dc_timing_3d_format format; @@ -1703,26 +1706,71 @@ static void set_avi_info_frame( hdmi_info->bits.R0_R3 = ACTIVE_FORMAT_ASPECT_RATIO_SAME_AS_PICTURE; /* TODO: un-hardcode cn0_cn1 and itc */ + cn0_cn1 = 0; - itc = false; + cn0_cn1_value = 0; + + itc = true; + itc_value = 1; + + support = stream->public.sink->edid_caps.content_support; if (itc) { - hdmi_info->bits.ITC = 1; - hdmi_info->bits.CN0_CN1 = cn0_cn1; + if (!support.bits.valid_content_type) { + cn0_cn1_value = 0; + } else { + if (cn0_cn1 == DISPLAY_CONTENT_TYPE_GRAPHICS) { + if (support.bits.graphics_content == 1) { + cn0_cn1_value = 0; + } + } else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_PHOTO) { + if (support.bits.photo_content == 1) { + cn0_cn1_value = 1; + } else { + cn0_cn1_value = 0; + itc_value = 0; + } + } else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_CINEMA) { + if (support.bits.cinema_content == 1) { + cn0_cn1_value = 2; + } else { + cn0_cn1_value = 0; + itc_value = 0; + } + } else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_GAME) { + if (support.bits.game_content == 1) { + cn0_cn1_value = 3; + } else { + cn0_cn1_value = 0; + itc_value = 0; + } + } + } + hdmi_info->bits.CN0_CN1 = cn0_cn1_value; + hdmi_info->bits.ITC = itc_value; } /* TODO : We should handle YCC quantization */ /* but we do not have matrix calculation */ - if (color_space == COLOR_SPACE_SRGB) { - hdmi_info->bits.Q0_Q1 = RGB_QUANTIZATION_FULL_RANGE; - hdmi_info->bits.YQ0_YQ1 = YYC_QUANTIZATION_FULL_RANGE; - } else if (color_space == COLOR_SPACE_SRGB_LIMITED) { - hdmi_info->bits.Q0_Q1 = RGB_QUANTIZATION_LIMITED_RANGE; - hdmi_info->bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; + if (stream->public.sink->edid_caps.qs_bit == 1 && + stream->public.sink->edid_caps.qy_bit == 1) { + if (color_space == COLOR_SPACE_SRGB || + color_space == COLOR_SPACE_2020_RGB_FULLRANGE) { + hdmi_info->bits.Q0_Q1 = RGB_QUANTIZATION_FULL_RANGE; + hdmi_info->bits.YQ0_YQ1 = YYC_QUANTIZATION_FULL_RANGE; + } else if (color_space == COLOR_SPACE_SRGB_LIMITED || + color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE) { + hdmi_info->bits.Q0_Q1 = RGB_QUANTIZATION_LIMITED_RANGE; + hdmi_info->bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; + } else { + hdmi_info->bits.Q0_Q1 = RGB_QUANTIZATION_DEFAULT_RANGE; + hdmi_info->bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; + } } else { hdmi_info->bits.Q0_Q1 = RGB_QUANTIZATION_DEFAULT_RANGE; - hdmi_info->bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; + hdmi_info->bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; } + ///VIC format = stream->public.timing.timing_3d_format; /*todo, add 3DStereo support*/ diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 9662f2c68f83..c7539fe36b66 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -177,6 +177,18 @@ struct dc_edid { #define AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS 20 +union display_content_support { + unsigned int raw; + struct { + unsigned int valid_content_type :1; + unsigned int game_content :1; + unsigned int cinema_content :1; + unsigned int photo_content :1; + unsigned int graphics_content :1; + unsigned int reserved :27; + } bits; +}; + struct dc_edid_caps { /* sink identification */ uint16_t manufacturer_id; @@ -193,6 +205,11 @@ struct dc_edid_caps { uint32_t audio_latency; uint32_t video_latency; + union display_content_support content_support; + + uint8_t qs_bit; + uint8_t qy_bit; + /*HDMI 2.0 caps*/ bool lte_340mcsc_scramble; @@ -384,6 +401,14 @@ enum scaling_transformation { SCALING_TRANSFORMATION_PRESERVE_ASPECT_RATIO_SCALE }; +enum display_content_type { + DISPLAY_CONTENT_TYPE_NO_DATA = 0, + DISPLAY_CONTENT_TYPE_GRAPHICS = 1, + DISPLAY_CONTENT_TYPE_PHOTO = 2, + DISPLAY_CONTENT_TYPE_CINEMA = 4, + DISPLAY_CONTENT_TYPE_GAME = 8 +}; + /* audio*/ union audio_sample_rates { -- cgit From f811fd5a66a3e69cdc184accfe189de5a1f6dba4 Mon Sep 17 00:00:00 2001 From: Wesley Chalmers Date: Thu, 20 Jul 2017 17:13:12 -0400 Subject: drm/amd/display: Change DTN_INFO macro Signed-off-by: Wesley Chalmers Reviewed-by: Wesley Chalmers Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/include/logger_interface.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/include/logger_interface.h b/drivers/gpu/drm/amd/display/include/logger_interface.h index c861e726cd8f..6e6fd4e8fc00 100644 --- a/drivers/gpu/drm/amd/display/include/logger_interface.h +++ b/drivers/gpu/drm/amd/display/include/logger_interface.h @@ -124,7 +124,7 @@ void context_clock_trace( __VA_ARGS__); #define DTN_INFO(...) \ - dm_logger_write(dc_ctx->logger, LOG_DTN, \ + dc_raw_log(dc_ctx, LOG_DTN, \ __VA_ARGS__) #define DC_SYNC_INFO(...) \ -- cgit From 516666318fe1f427ab81e2ebe45d116a9667c3b5 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 21 Jul 2017 17:35:16 -0400 Subject: drm/amd/display: support for updated register headers on DCN Signed-off-by: Dmytro Laktyushkin Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h | 12 +++++++- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 2 +- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 14 +++++++-- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c | 17 +++++++--- .../gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c | 19 +++++++++--- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h | 15 ++++++++- .../amd/display/dc/dcn10/dcn10_timing_generator.c | 36 ++++++++++++---------- drivers/gpu/drm/amd/display/dc/inc/hw/opp.h | 4 +++ 8 files changed, 88 insertions(+), 31 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index 0479554bc231..80ee1ac32fee 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -227,6 +227,15 @@ struct dce_hwseq_registers { uint32_t DISPCLK_FREQ_CHANGE_CNTL; uint32_t RBBMIF_TIMEOUT_DIS; uint32_t RBBMIF_TIMEOUT_DIS_2; + uint32_t DENTIST_DISPCLK_CNTL; + uint32_t DCHUBBUB_CRC_CTRL; + uint32_t DPP_TOP0_DPP_CRC_CTRL; + uint32_t DPP_TOP0_DPP_CRC_VAL_R_G; + uint32_t DPP_TOP0_DPP_CRC_VAL_B_A; + uint32_t MPC_CRC_CTRL; + uint32_t MPC_CRC_RESULT_GB; + uint32_t MPC_CRC_RESULT_C; + uint32_t MPC_CRC_RESULT_AR; #endif }; /* set field name */ @@ -388,7 +397,8 @@ struct dce_hwseq_registers { type DOMAIN6_PGFSM_PWR_STATUS; \ type DOMAIN7_PGFSM_PWR_STATUS; \ type DCFCLK_GATE_DIS; \ - type DCHUBBUB_GLOBAL_TIMER_REFDIV; + type DCHUBBUB_GLOBAL_TIMER_REFDIV; \ + type DENTIST_DPPCLK_WDIVIDER; #endif struct dce_hwseq_shift { diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index b691ef956d45..baafe6609d24 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -256,7 +256,7 @@ static bool dce110_set_input_transfer_func( ipp->funcs->ipp_program_prescale(ipp, &prescale_params); if (surface->public.gamma_correction && dce_use_lut(surface)) - ipp->funcs->ipp_program_input_lut(ipp, surface->public.gamma_correction); + ipp->funcs->ipp_program_input_lut(ipp, surface->public.gamma_correction); if (tf == NULL) { /* Default case if no input transfer function specified */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 6db78d9f8e3b..ce7da8864507 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -550,7 +550,9 @@ static void reset_front_end( if (dc->public.debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); - REG_WAIT(OTG_GLOBAL_SYNC_STATUS[tg->inst], VUPDATE_NO_LOCK_EVENT_OCCURRED, 1, 20000, 200000); + if (tg->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS) + REG_WAIT(OTG_GLOBAL_SYNC_STATUS[tg->inst], + VUPDATE_NO_LOCK_EVENT_OCCURRED, 1, 20000, 200000); mpcc->funcs->wait_for_idle(mpcc); @@ -1295,6 +1297,7 @@ static void dcn10_power_on_fe( /* make sure OPP_PIPE_CLOCK_EN = 1 */ REG_UPDATE(OPP_PIPE_CONTROL[pipe_ctx->tg->inst], OPP_PIPE_CLOCK_EN, 1); + /*TODO: REG_UPDATE(DENTIST_DISPCLK_CNTL, DENTIST_DPPCLK_WDIVIDER, 0x1f);*/ if (dc_surface) { dm_logger_write(dc->ctx->logger, LOG_DC, @@ -1984,9 +1987,16 @@ static void dcn10_setup_stereo(struct pipe_ctx *pipe_ctx, struct core_dc *dc) static void dcn10_log_hw_state(struct core_dc *dc) { struct dc_context *dc_ctx = dc->ctx; + struct dce_hwseq *hws = dc->hwseq; DTN_INFO("%s: Hello World", __func__); + if (REG(MPC_CRC_RESULT_GB)) + DTN_INFO("MPC_CRC_RESULT_GB:%d MPC_CRC_RESULT_C:%d MPC_CRC_RESULT_AR:%d\n", + REG_READ(MPC_CRC_RESULT_GB), REG_READ(MPC_CRC_RESULT_C), REG_READ(MPC_CRC_RESULT_AR)); + if (REG(DPP_TOP0_DPP_CRC_VAL_B_A)) + DTN_INFO("DPP_TOP0_DPP_CRC_VAL_B_A:%d DPP_TOP0_DPP_CRC_VAL_R_G:%d\n", + REG_READ(DPP_TOP0_DPP_CRC_VAL_B_A), REG_READ(DPP_TOP0_DPP_CRC_VAL_R_G)); /* todo: add meaningful register reads and print out HW state * */ @@ -2065,7 +2075,7 @@ static const struct hw_sequencer_funcs dcn10_funcs = { .set_static_screen_control = set_static_screen_control, .setup_stereo = dcn10_setup_stereo, .set_avmute = dce110_set_avmute, - .log_hw_state = dcn10_log_hw_state, + .log_hw_state = dcn10_log_hw_state }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c index 53dd9a9593f0..ee12f671d8ea 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c @@ -472,11 +472,18 @@ static bool ippn10_cursor_program_control( bool pixel_data_invert, enum dc_cursor_color_format color_format) { - REG_SET_2(CURSOR_SETTINS, 0, - /* no shift of the cursor HDL schedule */ - CURSOR0_DST_Y_OFFSET, 0, - /* used to shift the cursor chunk request deadline */ - CURSOR0_CHUNK_HDL_ADJUST, 3); + if (REG(CURSOR_SETTINS)) + REG_SET_2(CURSOR_SETTINS, 0, + /* no shift of the cursor HDL schedule */ + CURSOR0_DST_Y_OFFSET, 0, + /* used to shift the cursor chunk request deadline */ + CURSOR0_CHUNK_HDL_ADJUST, 3); + else + REG_SET_2(CURSOR_SETTINGS, 0, + /* no shift of the cursor HDL schedule */ + CURSOR0_DST_Y_OFFSET, 0, + /* used to shift the cursor chunk request deadline */ + CURSOR0_CHUNK_HDL_ADJUST, 3); REG_UPDATE_2(CURSOR0_CONTROL, CUR0_MODE, color_format, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index 8054794dd96d..1f86295d6db6 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -460,9 +460,14 @@ static void min10_program_deadline( REFCYC_X_AFTER_SCALER, dlg_attr->refcyc_x_after_scaler, DST_Y_AFTER_SCALER, dlg_attr->dst_y_after_scaler); - REG_SET_2(PREFETCH_SETTINS, 0, - DST_Y_PREFETCH, dlg_attr->dst_y_prefetch, - VRATIO_PREFETCH, dlg_attr->vratio_prefetch); + if (REG(PREFETCH_SETTINS)) + REG_SET_2(PREFETCH_SETTINS, 0, + DST_Y_PREFETCH, dlg_attr->dst_y_prefetch, + VRATIO_PREFETCH, dlg_attr->vratio_prefetch); + else + REG_SET_2(PREFETCH_SETTINGS, 0, + DST_Y_PREFETCH, dlg_attr->dst_y_prefetch, + VRATIO_PREFETCH, dlg_attr->vratio_prefetch); REG_SET_2(VBLANK_PARAMETERS_0, 0, DST_Y_PER_VM_VBLANK, dlg_attr->dst_y_per_vm_vblank, @@ -498,8 +503,12 @@ static void min10_program_deadline( REFCYC_PER_LINE_DELIVERY_L, dlg_attr->refcyc_per_line_delivery_l, REFCYC_PER_LINE_DELIVERY_C, dlg_attr->refcyc_per_line_delivery_c); - REG_SET(PREFETCH_SETTINS_C, 0, - VRATIO_PREFETCH_C, dlg_attr->vratio_prefetch_c); + if (REG(PREFETCH_SETTINS_C)) + REG_SET(PREFETCH_SETTINS_C, 0, + VRATIO_PREFETCH_C, dlg_attr->vratio_prefetch_c); + else + REG_SET(PREFETCH_SETTINGS_C, 0, + VRATIO_PREFETCH_C, dlg_attr->vratio_prefetch_c); REG_SET(VBLANK_PARAMETERS_2, 0, REFCYC_PER_PTE_GROUP_VBLANK_C, dlg_attr->refcyc_per_pte_group_vblank_c); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h index de0b631736bb..d9d66a4afb19 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h @@ -123,7 +123,6 @@ SRI(CM_MEM_PWR_CTRL, CM, id), \ SRI(CM_RGAM_LUT_DATA, CM, id) - #define OPP_MASK_SH_LIST_DCN(mask_sh) \ OPP_SF(DSCL0_OBUF_CONTROL, OBUF_BYPASS, mask_sh), \ OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN, mask_sh), \ @@ -357,6 +356,16 @@ OPP_SF(CM0_CM_RGAM_LUT_DATA, CM_RGAM_LUT_DATA, mask_sh) #define OPP_DCN10_REG_FIELD_LIST(type) \ + type DPG_EN; \ + type DPG_MODE; \ + type DPG_VRES; \ + type DPG_HRES; \ + type DPG_COLOUR0_R_CR; \ + type DPG_COLOUR1_R_CR; \ + type DPG_COLOUR0_B_CB; \ + type DPG_COLOUR1_B_CB; \ + type DPG_COLOUR0_G_Y; \ + type DPG_COLOUR1_G_Y; \ type CM_OCSC_C11; \ type CM_OCSC_C12; \ type CM_OCSC_C13; \ @@ -594,6 +603,10 @@ struct dcn10_opp_mask { }; struct dcn10_opp_registers { + uint32_t DPG_CONTROL; + uint32_t DPG_COLOUR_B_CB; + uint32_t DPG_COLOUR_G_Y; + uint32_t DPG_COLOUR_R_CR; uint32_t CM_OCSC_C11_C12; uint32_t CM_OCSC_C13_C14; uint32_t CM_OCSC_C21_C22; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c index 12d7f3570cfa..b2e796d87dac 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c @@ -345,17 +345,18 @@ static void tgn10_enable_optc_clock(struct timing_generator *tg, bool enable) struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); if (enable) { - REG_UPDATE(OPTC_INPUT_CLOCK_CONTROL, - OPTC_INPUT_CLK_EN, 1); + REG_UPDATE_2(OPTC_INPUT_CLOCK_CONTROL, + OPTC_INPUT_CLK_EN, 1, + OPTC_INPUT_CLK_GATE_DIS, 1); REG_WAIT(OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_ON, 1, 2000, 500); /* Enable clock */ - REG_UPDATE(OTG_CLOCK_CONTROL, - OTG_CLOCK_EN, 1); - + REG_UPDATE_2(OTG_CLOCK_CONTROL, + OTG_CLOCK_EN, 1, + OTG_CLOCK_GATE_DIS, 1); REG_WAIT(OTG_CLOCK_CONTROL, OTG_CLOCK_ON, 1, 2000, 500); @@ -364,17 +365,19 @@ static void tgn10_enable_optc_clock(struct timing_generator *tg, bool enable) OTG_CLOCK_GATE_DIS, 0, OTG_CLOCK_EN, 0); - REG_WAIT(OTG_CLOCK_CONTROL, - OTG_CLOCK_ON, 0, - 2000, 500); + if (tg->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS) + REG_WAIT(OTG_CLOCK_CONTROL, + OTG_CLOCK_ON, 0, + 2000, 500); REG_UPDATE_2(OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_GATE_DIS, 0, OPTC_INPUT_CLK_EN, 0); - REG_WAIT(OPTC_INPUT_CLOCK_CONTROL, - OPTC_INPUT_CLK_ON, 0, - 2000, 500); + if (tg->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS) + REG_WAIT(OPTC_INPUT_CLOCK_CONTROL, + OPTC_INPUT_CLK_ON, 0, + 2000, 500); } } @@ -574,9 +577,10 @@ static void tgn10_lock(struct timing_generator *tg) REG_SET(OTG_MASTER_UPDATE_LOCK, 0, OTG_MASTER_UPDATE_LOCK, 1); - REG_WAIT(OTG_MASTER_UPDATE_LOCK, - UPDATE_LOCK_STATUS, 1, - 1, 100); + if (tg->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS) + REG_WAIT(OTG_MASTER_UPDATE_LOCK, + UPDATE_LOCK_STATUS, 1, + 1, 100); } static void tgn10_unlock(struct timing_generator *tg) @@ -587,9 +591,9 @@ static void tgn10_unlock(struct timing_generator *tg) OTG_MASTER_UPDATE_LOCK, 0); /* why are we waiting here? */ - /*REG_WAIT(OTG_DOUBLE_BUFFER_CONTROL, + REG_WAIT(OTG_DOUBLE_BUFFER_CONTROL, OTG_UPDATE_PENDING, 0, - 20000, 200000);*/ + 20000, 200000); } static void tgn10_get_position(struct timing_generator *tg, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h index a101f4b5e0c7..4b0c28eef352 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h @@ -324,6 +324,10 @@ struct opp_funcs { struct output_pixel_processor *opp, bool enable, bool rightEyePolarity); + + void (*opp_set_test_pattern)( + struct output_pixel_processor *opp, + bool enable); }; #endif -- cgit From 03618e910797c9bb7ec8eb1e45df64ad8080a37a Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 20 Jul 2017 10:26:23 -0400 Subject: drm/amd/display: Roll surface struct into core_surface Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_surface.c | 37 +++++++++--------------- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 4 +++ 2 files changed, 18 insertions(+), 23 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index d44ddfb85748..3784358d35ef 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -34,20 +34,11 @@ /******************************************************************************* * Private structures ******************************************************************************/ -struct surface { - struct core_surface protected; - enum dc_irq_source irq_source; - int ref_count; -}; - struct gamma { struct core_gamma protected; int ref_count; }; -#define DC_SURFACE_TO_SURFACE(dc_surface) container_of(dc_surface, struct surface, protected.public) -#define CORE_SURFACE_TO_SURFACE(core_surface) container_of(core_surface, struct surface, protected) - #define DC_GAMMA_TO_GAMMA(dc_gamma) \ container_of(dc_gamma, struct gamma, protected.public) #define CORE_GAMMA_TO_GAMMA(core_gamma) \ @@ -56,23 +47,23 @@ struct gamma { /******************************************************************************* * Private functions ******************************************************************************/ -static bool construct(struct dc_context *ctx, struct surface *surface) +static bool construct(struct dc_context *ctx, struct core_surface *surface) { - surface->protected.ctx = ctx; - memset(&surface->protected.public.hdr_static_ctx, + surface->ctx = ctx; + memset(&surface->public.hdr_static_ctx, 0, sizeof(struct dc_hdr_static_metadata)); return true; } -static void destruct(struct surface *surface) +static void destruct(struct core_surface *surface) { - if (surface->protected.public.gamma_correction != NULL) { - dc_gamma_release(&surface->protected.public.gamma_correction); + if (surface->public.gamma_correction != NULL) { + dc_gamma_release(&surface->public.gamma_correction); } - if (surface->protected.public.in_transfer_func != NULL) { + if (surface->public.in_transfer_func != NULL) { dc_transfer_func_release( - surface->protected.public.in_transfer_func); - surface->protected.public.in_transfer_func = NULL; + surface->public.in_transfer_func); + surface->public.in_transfer_func = NULL; } } @@ -82,7 +73,7 @@ static void destruct(struct surface *surface) void enable_surface_flip_reporting(struct dc_surface *dc_surface, uint32_t controller_id) { - struct surface *surface = DC_SURFACE_TO_SURFACE(dc_surface); + struct core_surface *surface = DC_SURFACE_TO_CORE(dc_surface); surface->irq_source = controller_id + DC_IRQ_SOURCE_PFLIP1 - 1; /*register_flip_interrupt(surface);*/ } @@ -91,7 +82,7 @@ struct dc_surface *dc_create_surface(const struct dc *dc) { struct core_dc *core_dc = DC_TO_CORE(dc); - struct surface *surface = dm_alloc(sizeof(*surface)); + struct core_surface *surface = dm_alloc(sizeof(*surface)); if (NULL == surface) goto alloc_fail; @@ -101,7 +92,7 @@ struct dc_surface *dc_create_surface(const struct dc *dc) ++surface->ref_count; - return &surface->protected.public; + return &surface->public; construct_fail: dm_free(surface); @@ -146,7 +137,7 @@ const struct dc_surface_status *dc_surface_get_status( void dc_surface_retain(const struct dc_surface *dc_surface) { - struct surface *surface = DC_SURFACE_TO_SURFACE(dc_surface); + struct core_surface *surface = DC_SURFACE_TO_CORE(dc_surface); ASSERT(surface->ref_count > 0); ++surface->ref_count; @@ -154,7 +145,7 @@ void dc_surface_retain(const struct dc_surface *dc_surface) void dc_surface_release(const struct dc_surface *dc_surface) { - struct surface *surface = DC_SURFACE_TO_SURFACE(dc_surface); + struct core_surface *surface = DC_SURFACE_TO_CORE(dc_surface); ASSERT(surface->ref_count > 0); --surface->ref_count; diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index d75368030917..30177f839b8a 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -53,6 +53,10 @@ struct core_surface { struct dc_surface public; struct dc_surface_status status; struct dc_context *ctx; + + /* private to dc_surface.c */ + enum dc_irq_source irq_source; + int ref_count; }; struct core_gamma { -- cgit From 8c4abe0b07a12c402f009abed8217e6c2e33a300 Mon Sep 17 00:00:00 2001 From: Ding Wang Date: Tue, 18 Jul 2017 17:18:11 -0400 Subject: drm/amd/display: fix decide_link_settings Signed-off-by: Ding Wang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 6 +- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 140 ++++++++++------------- drivers/gpu/drm/amd/display/dc/dc.h | 1 + 3 files changed, 63 insertions(+), 84 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index ad1b90563eb6..de05ad09599f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -308,10 +308,8 @@ static void set_preferred_link_settings(struct dc *dc, { struct core_link *core_link = DC_LINK_TO_CORE(link); - core_link->public.verified_link_cap.lane_count = - link_setting->lane_count; - core_link->public.verified_link_cap.link_rate = - link_setting->link_rate; + core_link->public.preferred_link_setting = + *link_setting; dp_retrain_link_dp_test(core_link, link_setting, false); } 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 445cd226d36d..e90b3ebc8347 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 @@ -33,32 +33,6 @@ enum { LINK_TRAINING_MAX_CR_RETRY = 100 }; -static const struct dc_link_settings link_training_fallback_table[] = { -/* 4320 Mbytes/sec*/ -{ LANE_COUNT_FOUR, LINK_RATE_HIGH3, LINK_SPREAD_DISABLED }, -/* 2160 Mbytes/sec*/ -{ LANE_COUNT_FOUR, LINK_RATE_HIGH2, LINK_SPREAD_DISABLED }, -/* 1080 Mbytes/sec*/ -{ LANE_COUNT_FOUR, LINK_RATE_HIGH, LINK_SPREAD_DISABLED }, -/* 648 Mbytes/sec*/ -{ LANE_COUNT_FOUR, LINK_RATE_LOW, LINK_SPREAD_DISABLED }, -/* 2160 Mbytes/sec*/ -{ LANE_COUNT_TWO, LINK_RATE_HIGH3, LINK_SPREAD_DISABLED }, -/* 1080 Mbytes/sec*/ -{ LANE_COUNT_TWO, LINK_RATE_HIGH2, LINK_SPREAD_DISABLED }, -/* 540 Mbytes/sec*/ -{ LANE_COUNT_TWO, LINK_RATE_HIGH, LINK_SPREAD_DISABLED }, -/* 324 Mbytes/sec*/ -{ LANE_COUNT_TWO, LINK_RATE_LOW, LINK_SPREAD_DISABLED }, -/* 1080 Mbytes/sec*/ -{ LANE_COUNT_ONE, LINK_RATE_HIGH3, LINK_SPREAD_DISABLED }, -/* 540 Mbytes/sec*/ -{ LANE_COUNT_ONE, LINK_RATE_HIGH2, LINK_SPREAD_DISABLED }, -/* 270 Mbytes/sec*/ -{ LANE_COUNT_ONE, LINK_RATE_HIGH, LINK_SPREAD_DISABLED }, -/* 162 Mbytes/sec*/ -{ LANE_COUNT_ONE, LINK_RATE_LOW, LINK_SPREAD_DISABLED } }; - static void wait_for_training_aux_rd_interval( struct core_link* link, uint32_t default_wait_in_micro_secs) @@ -1053,29 +1027,6 @@ bool perform_link_training_with_retries( return false; } -/*TODO add more check to see if link support request link configuration */ -static bool is_link_setting_supported( - const struct dc_link_settings *link_setting, - const struct dc_link_settings *max_link_setting) -{ - if (link_setting->lane_count > max_link_setting->lane_count || - link_setting->link_rate > max_link_setting->link_rate) - return false; - return true; -} - -static const uint32_t get_link_training_fallback_table_len( - struct core_link *link) -{ - return ARRAY_SIZE(link_training_fallback_table); -} - -static const struct dc_link_settings *get_link_training_fallback_table( - struct core_link *link, uint32_t i) -{ - return &link_training_fallback_table[i]; -} - static struct dc_link_settings get_max_link_cap(struct core_link *link) { /* Set Default link settings */ @@ -1284,6 +1235,32 @@ enum dc_link_rate reduce_link_rate(enum dc_link_rate link_rate) } } +enum dc_lane_count increase_lane_count(enum dc_lane_count lane_count) +{ + switch (lane_count) { + case LANE_COUNT_ONE: + return LANE_COUNT_TWO; + case LANE_COUNT_TWO: + return LANE_COUNT_FOUR; + default: + return LANE_COUNT_UNKNOWN; + } +} + +enum dc_link_rate increase_link_rate(enum dc_link_rate link_rate) +{ + switch (link_rate) { + case LINK_RATE_LOW: + return LINK_RATE_HIGH; + case LINK_RATE_HIGH: + return LINK_RATE_HIGH2; + case LINK_RATE_HIGH2: + return LINK_RATE_HIGH3; + default: + return LINK_RATE_UNKNOWN; + } +} + /* * function: set link rate and lane count fallback based * on current link setting and last link training result @@ -1463,57 +1440,60 @@ void decide_link_settings(struct core_stream *stream, struct dc_link_settings *link_setting) { - const struct dc_link_settings *cur_ls; + struct dc_link_settings initial_link_setting = { + LANE_COUNT_ONE, LINK_RATE_LOW, LINK_SPREAD_DISABLED}; + struct dc_link_settings current_link_setting = + initial_link_setting; struct core_link* link; uint32_t req_bw; uint32_t link_bw; - uint32_t i; req_bw = bandwidth_in_kbps_from_timing( &stream->public.timing); + link = stream->sink->link; + /* if preferred is specified through AMDDP, use it, if it's enough * to drive the mode */ - link = stream->sink->link; - - if ((link->public.reported_link_cap.lane_count != LANE_COUNT_UNKNOWN) && - (link->public.reported_link_cap.link_rate <= - link->public.verified_link_cap.link_rate)) { + if (link->public.preferred_link_setting.lane_count != + LANE_COUNT_UNKNOWN && + link->public.preferred_link_setting.link_rate != + LINK_RATE_UNKNOWN) { + *link_setting = link->public.preferred_link_setting; + return; + } + /* search for the minimum link setting that: + * 1. is supported according to the link training result + * 2. could support the b/w requested by the timing + */ + while (current_link_setting.link_rate <= + link->public.max_link_setting.link_rate) { link_bw = bandwidth_in_kbps_from_link_settings( - &link->public.reported_link_cap); - - if (req_bw < link_bw) { - *link_setting = link->public.reported_link_cap; + ¤t_link_setting); + if (req_bw <= link_bw) { + *link_setting = current_link_setting; return; } - } - /* search for first suitable setting for the requested - * bandwidth - */ - for (i = 0; i < get_link_training_fallback_table_len(link); i++) { - - cur_ls = get_link_training_fallback_table(link, i); - - link_bw = - bandwidth_in_kbps_from_link_settings( - cur_ls); - - if (req_bw < link_bw) { - if (is_link_setting_supported( - cur_ls, - &link->public.max_link_setting)) { - *link_setting = *cur_ls; - return; - } + if (current_link_setting.lane_count < + link->public.max_link_setting.lane_count) { + current_link_setting.lane_count = + increase_lane_count( + current_link_setting.lane_count); + } else { + current_link_setting.link_rate = + increase_link_rate( + current_link_setting.link_rate); + current_link_setting.lane_count = + initial_link_setting.lane_count; } } BREAK_TO_DEBUGGER(); ASSERT(link->public.verified_link_cap.lane_count != - LANE_COUNT_UNKNOWN); + LANE_COUNT_UNKNOWN); *link_setting = link->public.verified_link_cap; } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 617270829936..ee04c3562081 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -674,6 +674,7 @@ struct dc_link { struct dc_link_settings max_link_setting; struct dc_link_settings cur_link_settings; struct dc_lane_settings cur_lane_setting; + struct dc_link_settings preferred_link_setting; uint8_t ddc_hw_inst; -- cgit From 0a87425a37b4c1f06d75949ea39e60455a2b0a4f Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Wed, 12 Jul 2017 22:35:52 -0400 Subject: drm/amd/display: move VGA to HWSS from TG Signed-off-by: Tony Cheng Reviewed-by: Zeyu Fan Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h | 11 ++++++- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 3 +- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 12 ++++++- .../amd/display/dc/dcn10/dcn10_timing_generator.c | 38 ---------------------- 4 files changed, 23 insertions(+), 41 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index 80ee1ac32fee..7feb1ca9b8c0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -170,7 +170,12 @@ SR(DIO_MEM_PWR_CTRL), \ SR(DCCG_GATE_DISABLE_CNTL), \ SR(DCCG_GATE_DISABLE_CNTL2), \ - SR(DCFCLK_CNTL) + SR(DCFCLK_CNTL),\ + SR(DCFCLK_CNTL), \ + SR(D1VGA_CONTROL), \ + SR(D2VGA_CONTROL), \ + SR(D3VGA_CONTROL), \ + SR(D4VGA_CONTROL) #endif #if defined(CONFIG_DRM_AMD_DC_DCN1_0) @@ -236,6 +241,10 @@ struct dce_hwseq_registers { uint32_t MPC_CRC_RESULT_GB; uint32_t MPC_CRC_RESULT_C; uint32_t MPC_CRC_RESULT_AR; + uint32_t D1VGA_CONTROL; + uint32_t D2VGA_CONTROL; + uint32_t D3VGA_CONTROL; + uint32_t D4VGA_CONTROL; #endif }; /* set field name */ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index baafe6609d24..72e099953a05 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1198,7 +1198,8 @@ static void disable_vga_and_power_gate_all_controllers( for (i = 0; i < dc->res_pool->pipe_count; i++) { tg = dc->res_pool->timing_generators[i]; - tg->funcs->disable_vga(tg); + if (tg->funcs->disable_vga) + tg->funcs->disable_vga(tg); /* Enable CLOCK gating for each pipe BEFORE controller * powergating. */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index ce7da8864507..64f2fd0d539e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -163,6 +163,15 @@ static void enable_power_gating_plane( REG_UPDATE(DOMAIN7_PG_CONFIG, DOMAIN7_POWER_FORCEON, force_on); } +static void disable_vga( + struct dce_hwseq *hws) +{ + REG_WRITE(D1VGA_CONTROL, 0); + REG_WRITE(D2VGA_CONTROL, 0); + REG_WRITE(D3VGA_CONTROL, 0); + REG_WRITE(D4VGA_CONTROL, 0); +} + static void dpp_pg_control( struct dce_hwseq *hws, unsigned int dpp_inst, @@ -312,6 +321,8 @@ static void dcn10_init_hw(struct core_dc *dc) bios_golden_init(dc); + disable_vga(dc->hwseq); + for (i = 0; i < dc->link_count; i++) { /* Power up AND update implementation according to the * required signal (which may be different from the @@ -335,7 +346,6 @@ static void dcn10_init_hw(struct core_dc *dc) mpcc_cfg.top_of_tree = true; mpcc->funcs->set(mpcc, &mpcc_cfg); - tg->funcs->disable_vga(tg); /* Blank controller using driver code instead of * command table. */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c index b2e796d87dac..0ef5d8f0625c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c @@ -447,43 +447,6 @@ static void tgn10_program_blank_color( OTG_BLACK_COLOR_R_CR, black_color->color_r_cr); } -/** - * dcn10_dcn10_timing_generator_disable_vga - * Turn OFF VGA Mode and Timing - DxVGA_CONTROL - * VGA Mode and VGA Timing is used by VBIOS on CRT Monitors; - */ -/* TODO FPGA FPGA setup is done by Diag which does not enable VGA mode. - * VGA is disable by ASIC default. This function is not needed for - * FPGA story. - * usage: - * init_hw within dc.c - * disable_vga_and_power_gate_all_controllers within dce110_hw_sequencer.c - * We may move init_hw into DC specific so that we can remove - * .disable_vga from upper layer stack - */ -static void tgn10_disable_vga( - struct timing_generator *tg) -{ - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); - - switch (tgn10->base.inst) { - case 0: - REG_WRITE(D1VGA_CONTROL, 0); - break; - case 1: - REG_WRITE(D2VGA_CONTROL, 0); - break; - case 2: - REG_WRITE(D2VGA_CONTROL, 0); - break; - case 3: - REG_WRITE(D4VGA_CONTROL, 0); - break; - default: - break; - } -} - static bool tgn10_validate_timing( struct timing_generator *tg, const struct dc_crtc_timing *timing) @@ -1144,7 +1107,6 @@ static struct timing_generator_funcs dcn10_tg_funcs = { .set_blank = tgn10_set_blank, .is_blanked = tgn10_is_blanked, .set_blank_color = tgn10_program_blank_color, - .disable_vga = tgn10_disable_vga, .did_triggered_reset_occur = tgn10_did_triggered_reset_occur, .enable_reset_trigger = tgn10_enable_reset_trigger, .disable_reset_trigger = tgn10_disable_reset_trigger, -- cgit From 755d3bcfd44c16d344c7c6305ac6e7da19c27f5e Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Sun, 23 Jul 2017 14:17:09 -0400 Subject: drm/amd/display: Fix generic_reg_wait 1000ms case Signed-off-by: Eric Yang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc_helper.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc_helper.c b/drivers/gpu/drm/amd/display/dc/dc_helper.c index 87b7f6f8870e..f219bd2068e5 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_helper.c +++ b/drivers/gpu/drm/amd/display/dc/dc_helper.c @@ -143,11 +143,10 @@ uint32_t generic_reg_wait(const struct dc_context *ctx, for (i = 0; i <= time_out_num_tries; i++) { if (i) { - if (0 < delay_between_poll_us && delay_between_poll_us < 1000) - udelay(delay_between_poll_us); - - if (delay_between_poll_us > 1000) + if (delay_between_poll_us >= 1000) msleep(delay_between_poll_us/1000); + else if (delay_between_poll_us > 0) + udelay(delay_between_poll_us); } reg_val = dm_read_reg(ctx, addr); -- cgit From 8748068764e7a50ac787c1c17f402f3fbbe97ccc Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Sun, 23 Jul 2017 15:18:57 -0400 Subject: drm/amd/display: add idle wait for passive surface update and modeset Signed-off-by: Eric Yang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 19 +++++++++++++++++++ .../gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 18 +++++++++++++++++- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c | 4 ++++ drivers/gpu/drm/amd/display/dc/inc/core_types.h | 2 -- drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h | 3 +++ drivers/gpu/drm/amd/display/dc/inc/hw/opp.h | 1 + drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 2 ++ 7 files changed, 46 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index de05ad09599f..9ef671735125 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -934,6 +934,10 @@ static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *c if (!dcb->funcs->is_accelerated_mode(dcb)) core_dc->hwss.enable_accelerated_mode(core_dc); + for (i = 0; i < core_dc->res_pool->pipe_count; i++) { + pipe = &context->res_ctx.pipe_ctx[i]; + core_dc->hwss.wait_for_mpcc_disconnect(core_dc->res_pool, pipe); + } result = core_dc->hwss.apply_ctx_to_hw(core_dc, context); program_timing_sync(core_dc, context); @@ -1537,6 +1541,21 @@ void dc_update_surfaces_and_stream(struct dc *dc, } } + if (update_type > UPDATE_TYPE_FAST) { + for (i = 0; i < surface_count; i++) { + struct core_surface *surface = DC_SURFACE_TO_CORE(srf_updates[i].surface); + + for (j = 0; j < core_dc->res_pool->pipe_count; j++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; + + if (pipe_ctx->surface != surface) + continue; + + core_dc->hwss.wait_for_mpcc_disconnect(core_dc->res_pool, pipe_ctx); + } + } + } + if (surface_count == 0) core_dc->hwss.apply_ctx_for_surface(core_dc, NULL, context); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 64f2fd0d539e..633d858caf6f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1739,6 +1739,7 @@ static void dcn10_apply_ctx_for_surface( mpcc_cfg.bot_mpcc_id = 0xf; mpcc_cfg.top_of_tree = !old_pipe_ctx->top_pipe; old_pipe_ctx->mpcc->funcs->set(old_pipe_ctx->mpcc, &mpcc_cfg); + old_pipe_ctx->top_pipe->opp->mpcc_disconnect_pending[old_pipe_ctx->mpcc->inst] = true; if (dc->public.debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); @@ -2012,6 +2013,20 @@ static void dcn10_log_hw_state(struct core_dc *dc) */ } +static void dcn10_wait_for_mpcc_disconnect(struct resource_pool *res_pool, struct pipe_ctx *pipe_ctx) +{ + int i; + for (i = 0; i < MAX_PIPES; i++) { + if (!pipe_ctx->opp || !pipe_ctx->mpcc) + continue; + + if (pipe_ctx->opp->mpcc_disconnect_pending[i]) { + pipe_ctx->mpcc->funcs->wait_for_idle(res_pool->mpcc[i]); + pipe_ctx->opp->mpcc_disconnect_pending[i] = false; + } + } +} + static bool dcn10_dummy_display_power_gating( struct core_dc *dc, uint8_t controller_id, @@ -2085,7 +2100,8 @@ static const struct hw_sequencer_funcs dcn10_funcs = { .set_static_screen_control = set_static_screen_control, .setup_stereo = dcn10_setup_stereo, .set_avmute = dce110_set_avmute, - .log_hw_state = dcn10_log_hw_state + .log_hw_state = dcn10_log_hw_state, + .wait_for_mpcc_disconnect = dcn10_wait_for_mpcc_disconnect }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c index 669ac4b67ea9..c2aa69deecc2 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c @@ -907,10 +907,14 @@ void dcn10_opp_construct(struct dcn10_opp *oppn10, const struct dcn10_opp_shift *opp_shift, const struct dcn10_opp_mask *opp_mask) { + int i; oppn10->base.ctx = ctx; oppn10->base.inst = inst; oppn10->base.funcs = &dcn10_opp_funcs; + for (i = 0; i < MAX_PIPES; i++) + oppn10->base.mpcc_disconnect_pending[i] = false; + oppn10->regs = regs; oppn10->opp_shift = opp_shift; oppn10->opp_mask = opp_mask; diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 30177f839b8a..cc65cfdea66f 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -38,10 +38,8 @@ struct core_stream; -#define MAX_PIPES 6 #define MAX_CLOCK_SOURCES 7 - /********* core_surface **********/ #define DC_SURFACE_TO_CORE(dc_surface) \ container_of(dc_surface, struct core_surface, public) diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h index 907e0a9a8474..0212618a36be 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h @@ -32,6 +32,9 @@ /****************************************************************************** * Data types shared between different Virtual HW blocks ******************************************************************************/ + +#define MAX_PIPES 6 + struct gamma_curve { uint32_t offset; uint32_t segments_num; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h index 4b0c28eef352..57bdd6c8f955 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h @@ -207,6 +207,7 @@ struct output_pixel_processor { struct dc_context *ctx; uint32_t inst; struct pwl_params regamma_params; + bool mpcc_disconnect_pending[MAX_PIPES]; const struct opp_funcs *funcs; }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 4c027a98cfd3..22aca5a375ae 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -156,6 +156,8 @@ struct hw_sequencer_funcs { void (*set_avmute)(struct pipe_ctx *pipe_ctx, bool enable); void (*log_hw_state)(struct core_dc *dc); + + void (*wait_for_mpcc_disconnect)(struct resource_pool *res_pool, struct pipe_ctx *pipe_ctx); }; void color_space_to_black_color( -- cgit From 7db90a6b58761577596499ddd90f3c5ace2b716d Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Sat, 22 Jul 2017 21:58:08 -0400 Subject: drm/amd/display: move ocsc programming from opp to dpp Signed-off-by: Tony Cheng Reviewed-by: Yuehin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c | 148 +++++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h | 46 ++++++- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 2 +- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c | 147 -------------------- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h | 40 ------ drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h | 37 ++++++ drivers/gpu/drm/amd/display/dc/inc/hw/opp.h | 21 --- drivers/gpu/drm/amd/display/dc/inc/hw/transform.h | 26 ++-- 8 files changed, 242 insertions(+), 225 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c index fff81a14b21c..0f3f1a31f10b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c @@ -988,11 +988,159 @@ static void dcn_dpp_set_gamut_remap( } } +static void oppn10_set_output_csc_default( + struct transform *xfm_base, + const struct default_adjustment *default_adjust) +{ + + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + uint32_t ocsc_mode = 0; + + if (default_adjust != NULL) { + switch (default_adjust->out_color_space) { + case COLOR_SPACE_SRGB: + case COLOR_SPACE_2020_RGB_FULLRANGE: + ocsc_mode = 0; + break; + case COLOR_SPACE_SRGB_LIMITED: + case COLOR_SPACE_2020_RGB_LIMITEDRANGE: + ocsc_mode = 1; + break; + case COLOR_SPACE_YCBCR601: + case COLOR_SPACE_YCBCR601_LIMITED: + ocsc_mode = 2; + break; + case COLOR_SPACE_YCBCR709: + case COLOR_SPACE_YCBCR709_LIMITED: + case COLOR_SPACE_2020_YCBCR: + ocsc_mode = 3; + break; + case COLOR_SPACE_UNKNOWN: + default: + break; + } + } + + REG_SET(CM_OCSC_CONTROL, 0, CM_OCSC_MODE, ocsc_mode); + +} + +static void oppn10_program_color_matrix( + struct dcn10_dpp *xfm, + const struct out_csc_color_matrix *tbl_entry) +{ + uint32_t mode; + + REG_GET(CM_OCSC_CONTROL, CM_OCSC_MODE, &mode); + + if (tbl_entry == NULL) { + BREAK_TO_DEBUGGER(); + return; + } + + if (mode == 4) { + /*R*/ + REG_SET_2(CM_OCSC_C11_C12, 0, + CM_OCSC_C11, tbl_entry->regval[0], + CM_OCSC_C12, tbl_entry->regval[1]); + + REG_SET_2(CM_OCSC_C13_C14, 0, + CM_OCSC_C13, tbl_entry->regval[2], + CM_OCSC_C14, tbl_entry->regval[3]); + + /*G*/ + REG_SET_2(CM_OCSC_C21_C22, 0, + CM_OCSC_C21, tbl_entry->regval[4], + CM_OCSC_C22, tbl_entry->regval[5]); + + REG_SET_2(CM_OCSC_C23_C24, 0, + CM_OCSC_C23, tbl_entry->regval[6], + CM_OCSC_C24, tbl_entry->regval[7]); + + /*B*/ + REG_SET_2(CM_OCSC_C31_C32, 0, + CM_OCSC_C31, tbl_entry->regval[8], + CM_OCSC_C32, tbl_entry->regval[9]); + + REG_SET_2(CM_OCSC_C33_C34, 0, + CM_OCSC_C33, tbl_entry->regval[10], + CM_OCSC_C34, tbl_entry->regval[11]); + } else { + /*R*/ + REG_SET_2(CM_COMB_C11_C12, 0, + CM_COMB_C11, tbl_entry->regval[0], + CM_COMB_C12, tbl_entry->regval[1]); + + REG_SET_2(CM_COMB_C13_C14, 0, + CM_COMB_C13, tbl_entry->regval[2], + CM_COMB_C14, tbl_entry->regval[3]); + + /*G*/ + REG_SET_2(CM_COMB_C21_C22, 0, + CM_COMB_C21, tbl_entry->regval[4], + CM_COMB_C22, tbl_entry->regval[5]); + + REG_SET_2(CM_COMB_C23_C24, 0, + CM_COMB_C23, tbl_entry->regval[6], + CM_COMB_C24, tbl_entry->regval[7]); + + /*B*/ + REG_SET_2(CM_COMB_C31_C32, 0, + CM_COMB_C31, tbl_entry->regval[8], + CM_COMB_C32, tbl_entry->regval[9]); + + REG_SET_2(CM_COMB_C33_C34, 0, + CM_COMB_C33, tbl_entry->regval[10], + CM_COMB_C34, tbl_entry->regval[11]); + } +} + +static void oppn10_set_output_csc_adjustment( + struct transform *xfm_base, + const struct out_csc_color_matrix *tbl_entry) +{ + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + //enum csc_color_mode config = CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; + uint32_t ocsc_mode = 4; + + /** + *if (tbl_entry != NULL) { + * switch (tbl_entry->color_space) { + * case COLOR_SPACE_SRGB: + * case COLOR_SPACE_2020_RGB_FULLRANGE: + * ocsc_mode = 0; + * break; + * case COLOR_SPACE_SRGB_LIMITED: + * case COLOR_SPACE_2020_RGB_LIMITEDRANGE: + * ocsc_mode = 1; + * break; + * case COLOR_SPACE_YCBCR601: + * case COLOR_SPACE_YCBCR601_LIMITED: + * ocsc_mode = 2; + * break; + * case COLOR_SPACE_YCBCR709: + * case COLOR_SPACE_YCBCR709_LIMITED: + * case COLOR_SPACE_2020_YCBCR: + * ocsc_mode = 3; + * break; + * case COLOR_SPACE_UNKNOWN: + * default: + * break; + * } + *} + */ + + REG_SET(CM_OCSC_CONTROL, 0, CM_OCSC_MODE, ocsc_mode); + oppn10_program_color_matrix(xfm, tbl_entry); +} + static struct transform_funcs dcn10_dpp_funcs = { .transform_reset = dpp_reset, .transform_set_scaler = dpp_set_scaler_manual_scale, .transform_get_optimal_number_of_taps = dpp_get_optimal_number_of_taps, .transform_set_gamut_remap = dcn_dpp_set_gamut_remap, + .opp_set_csc_adjustment = oppn10_set_output_csc_adjustment, + .opp_set_csc_default = oppn10_set_output_csc_default, }; /*****************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h index c1124e962d0e..693060e79d21 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h @@ -86,7 +86,14 @@ SRI(CM_COMB_C21_C22, CM, id),\ SRI(CM_COMB_C23_C24, CM, id),\ SRI(CM_COMB_C31_C32, CM, id),\ - SRI(CM_COMB_C33_C34, CM, id) + SRI(CM_COMB_C33_C34, CM, id),\ + SRI(CM_OCSC_CONTROL, CM, id), \ + SRI(CM_OCSC_C11_C12, CM, id), \ + SRI(CM_OCSC_C13_C14, CM, id), \ + SRI(CM_OCSC_C21_C22, CM, id), \ + SRI(CM_OCSC_C23_C24, CM, id), \ + SRI(CM_OCSC_C31_C32, CM, id), \ + SRI(CM_OCSC_C33_C34, CM, id) #define TF_REG_LIST_SH_MASK_DCN(mask_sh)\ TF_SF(CM0_CM_GAMUT_REMAP_CONTROL, CM_GAMUT_REMAP_MODE, mask_sh),\ @@ -194,7 +201,20 @@ TF_SF(CM0_CM_COMB_C31_C32, CM_COMB_C31, mask_sh),\ TF_SF(CM0_CM_COMB_C33_C34, CM_COMB_C33, mask_sh),\ TF_SF(CM0_CM_COMB_C31_C32, CM_COMB_C32, mask_sh),\ - TF_SF(CM0_CM_COMB_C33_C34, CM_COMB_C34, mask_sh) + TF_SF(CM0_CM_COMB_C33_C34, CM_COMB_C34, mask_sh),\ + TF_SF(CM0_CM_OCSC_CONTROL, CM_OCSC_MODE, mask_sh), \ + TF_SF(CM0_CM_OCSC_C11_C12, CM_OCSC_C11, mask_sh), \ + TF_SF(CM0_CM_OCSC_C11_C12, CM_OCSC_C12, mask_sh), \ + TF_SF(CM0_CM_OCSC_C13_C14, CM_OCSC_C13, mask_sh), \ + TF_SF(CM0_CM_OCSC_C13_C14, CM_OCSC_C14, mask_sh), \ + TF_SF(CM0_CM_OCSC_C21_C22, CM_OCSC_C21, mask_sh), \ + TF_SF(CM0_CM_OCSC_C21_C22, CM_OCSC_C22, mask_sh), \ + TF_SF(CM0_CM_OCSC_C23_C24, CM_OCSC_C23, mask_sh), \ + TF_SF(CM0_CM_OCSC_C23_C24, CM_OCSC_C24, mask_sh), \ + TF_SF(CM0_CM_OCSC_C31_C32, CM_OCSC_C31, mask_sh), \ + TF_SF(CM0_CM_OCSC_C31_C32, CM_OCSC_C32, mask_sh), \ + TF_SF(CM0_CM_OCSC_C33_C34, CM_OCSC_C33, mask_sh), \ + TF_SF(CM0_CM_OCSC_C33_C34, CM_OCSC_C34, mask_sh) #define TF_REG_FIELD_LIST(type) \ @@ -300,7 +320,20 @@ type CM_COMB_C31; \ type CM_COMB_C32; \ type CM_COMB_C33; \ - type CM_COMB_C34 + type CM_COMB_C34; \ + type CM_OCSC_MODE; \ + type CM_OCSC_C11; \ + type CM_OCSC_C12; \ + type CM_OCSC_C13; \ + type CM_OCSC_C14; \ + type CM_OCSC_C21; \ + type CM_OCSC_C22; \ + type CM_OCSC_C23; \ + type CM_OCSC_C24; \ + type CM_OCSC_C31; \ + type CM_OCSC_C32; \ + type CM_OCSC_C33; \ + type CM_OCSC_C34 struct dcn_dpp_shift { TF_REG_FIELD_LIST(uint8_t); @@ -357,6 +390,13 @@ struct dcn_dpp_registers { uint32_t CM_COMB_C23_C24; uint32_t CM_COMB_C31_C32; uint32_t CM_COMB_C33_C34; + uint32_t CM_OCSC_CONTROL; + uint32_t CM_OCSC_C11_C12; + uint32_t CM_OCSC_C13_C14; + uint32_t CM_OCSC_C21_C22; + uint32_t CM_OCSC_C23_C24; + uint32_t CM_OCSC_C31_C32; + uint32_t CM_OCSC_C33_C34; }; struct dcn10_dpp { diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 633d858caf6f..4cbca15e1cc5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1588,7 +1588,7 @@ static void update_dchubp_dpp( /*TODO add adjustments parameters*/ ocsc.out_color_space = pipe_ctx->stream->public.output_color_space; - pipe_ctx->opp->funcs->opp_set_csc_default(pipe_ctx->opp, &ocsc); + pipe_ctx->xfm->funcs->opp_set_csc_default(pipe_ctx->xfm, &ocsc); mi->funcs->mem_input_program_surface_config( mi, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c index c2aa69deecc2..5cf985e4ffa9 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c @@ -327,42 +327,7 @@ static void oppn10_program_fmt( return; } -static void oppn10_set_output_csc_default( - struct output_pixel_processor *opp, - const struct default_adjustment *default_adjust) -{ - struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); - uint32_t ocsc_mode = 0; - - if (default_adjust != NULL) { - switch (default_adjust->out_color_space) { - case COLOR_SPACE_SRGB: - case COLOR_SPACE_2020_RGB_FULLRANGE: - ocsc_mode = 0; - break; - case COLOR_SPACE_SRGB_LIMITED: - case COLOR_SPACE_2020_RGB_LIMITEDRANGE: - ocsc_mode = 1; - break; - case COLOR_SPACE_YCBCR601: - case COLOR_SPACE_YCBCR601_LIMITED: - ocsc_mode = 2; - break; - case COLOR_SPACE_YCBCR709: - case COLOR_SPACE_YCBCR709_LIMITED: - case COLOR_SPACE_2020_YCBCR: - ocsc_mode = 3; - break; - case COLOR_SPACE_UNKNOWN: - default: - break; - } - } - - REG_SET(CM_OCSC_CONTROL, 0, CM_OCSC_MODE, ocsc_mode); - -} /*program re gamma RAM B*/ static void opp_program_regamma_lutb_settings( struct output_pixel_processor *opp, @@ -714,117 +679,7 @@ static void oppn10_power_on_regamma_lut( } -static void oppn10_program_color_matrix(struct dcn10_opp *oppn10, - const struct out_csc_color_matrix *tbl_entry) -{ - uint32_t mode; - - REG_GET(CM_OCSC_CONTROL, CM_OCSC_MODE, &mode); - - if (tbl_entry == NULL) { - BREAK_TO_DEBUGGER(); - return; - } - - - if (mode == 4) { - /*R*/ - REG_SET_2(CM_OCSC_C11_C12, 0, - CM_OCSC_C11, tbl_entry->regval[0], - CM_OCSC_C12, tbl_entry->regval[1]); - - REG_SET_2(CM_OCSC_C13_C14, 0, - CM_OCSC_C13, tbl_entry->regval[2], - CM_OCSC_C14, tbl_entry->regval[3]); - /*G*/ - REG_SET_2(CM_OCSC_C21_C22, 0, - CM_OCSC_C21, tbl_entry->regval[4], - CM_OCSC_C22, tbl_entry->regval[5]); - - REG_SET_2(CM_OCSC_C23_C24, 0, - CM_OCSC_C23, tbl_entry->regval[6], - CM_OCSC_C24, tbl_entry->regval[7]); - - /*B*/ - REG_SET_2(CM_OCSC_C31_C32, 0, - CM_OCSC_C31, tbl_entry->regval[8], - CM_OCSC_C32, tbl_entry->regval[9]); - - REG_SET_2(CM_OCSC_C33_C34, 0, - CM_OCSC_C33, tbl_entry->regval[10], - CM_OCSC_C34, tbl_entry->regval[11]); - } else { - /*R*/ - REG_SET_2(CM_COMB_C11_C12, 0, - CM_COMB_C11, tbl_entry->regval[0], - CM_COMB_C12, tbl_entry->regval[1]); - - REG_SET_2(CM_COMB_C13_C14, 0, - CM_COMB_C13, tbl_entry->regval[2], - CM_COMB_C14, tbl_entry->regval[3]); - - /*G*/ - REG_SET_2(CM_COMB_C21_C22, 0, - CM_COMB_C21, tbl_entry->regval[4], - CM_COMB_C22, tbl_entry->regval[5]); - - REG_SET_2(CM_COMB_C23_C24, 0, - CM_COMB_C23, tbl_entry->regval[6], - CM_COMB_C24, tbl_entry->regval[7]); - - /*B*/ - REG_SET_2(CM_COMB_C31_C32, 0, - CM_COMB_C31, tbl_entry->regval[8], - CM_COMB_C32, tbl_entry->regval[9]); - - REG_SET_2(CM_COMB_C33_C34, 0, - CM_COMB_C33, tbl_entry->regval[10], - CM_COMB_C34, tbl_entry->regval[11]); - } -} - -static void oppn10_set_output_csc_adjustment( - struct output_pixel_processor *opp, - const struct out_csc_color_matrix *tbl_entry) -{ - - struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); - //enum csc_color_mode config = CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; - - - uint32_t ocsc_mode = 4; - - /** - *if (tbl_entry != NULL) { - * switch (tbl_entry->color_space) { - * case COLOR_SPACE_SRGB: - * case COLOR_SPACE_2020_RGB_FULLRANGE: - * ocsc_mode = 0; - * break; - * case COLOR_SPACE_SRGB_LIMITED: - * case COLOR_SPACE_2020_RGB_LIMITEDRANGE: - * ocsc_mode = 1; - * break; - * case COLOR_SPACE_YCBCR601: - * case COLOR_SPACE_YCBCR601_LIMITED: - * ocsc_mode = 2; - * break; - * case COLOR_SPACE_YCBCR709: - * case COLOR_SPACE_YCBCR709_LIMITED: - * case COLOR_SPACE_2020_YCBCR: - * ocsc_mode = 3; - * break; - * case COLOR_SPACE_UNKNOWN: - * default: - * break; - * } - *} - */ - - REG_SET(CM_OCSC_CONTROL, 0, CM_OCSC_MODE, ocsc_mode); - oppn10_program_color_matrix(oppn10, tbl_entry); -} static void opp_program_regamma_lut( struct output_pixel_processor *opp, @@ -889,8 +744,6 @@ static void dcn10_opp_destroy(struct output_pixel_processor **opp) static struct opp_funcs dcn10_opp_funcs = { .opp_power_on_regamma_lut = oppn10_power_on_regamma_lut, - .opp_set_csc_adjustment = oppn10_set_output_csc_adjustment, - .opp_set_csc_default = oppn10_set_output_csc_default, .opp_set_dyn_expansion = oppn10_set_dyn_expansion, .opp_program_regamma_pwl = oppn10_set_regamma_pwl, .opp_set_regamma_mode = oppn10_set_regamma_mode, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h index d9d66a4afb19..900298d6e5b5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h @@ -46,21 +46,8 @@ #define OPP_REG_LIST_DCN10(id) \ OPP_REG_LIST_DCN(id), \ - SRI(CM_OCSC_C11_C12, CM, id), \ - SRI(CM_OCSC_C13_C14, CM, id), \ - SRI(CM_OCSC_C21_C22, CM, id), \ - SRI(CM_OCSC_C23_C24, CM, id), \ - SRI(CM_OCSC_C31_C32, CM, id), \ - SRI(CM_OCSC_C33_C34, CM, id), \ - SRI(CM_COMB_C11_C12, CM, id), \ - SRI(CM_COMB_C13_C14, CM, id), \ - SRI(CM_COMB_C21_C22, CM, id), \ - SRI(CM_COMB_C23_C24, CM, id), \ - SRI(CM_COMB_C31_C32, CM, id), \ - SRI(CM_COMB_C33_C34, CM, id), \ SRI(CM_RGAM_LUT_WRITE_EN_MASK, CM, id), \ SRI(CM_RGAM_CONTROL, CM, id), \ - SRI(CM_OCSC_CONTROL, CM, id), \ SRI(CM_RGAM_RAMB_START_CNTL_B, CM, id), \ SRI(CM_RGAM_RAMB_START_CNTL_G, CM, id), \ SRI(CM_RGAM_RAMB_START_CNTL_R, CM, id), \ @@ -151,32 +138,7 @@ #define OPP_MASK_SH_LIST_DCN10(mask_sh) \ OPP_MASK_SH_LIST_DCN(mask_sh), \ OPP_SF(DSCL0_OBUF_CONTROL, OBUF_H_2X_UPSCALE_EN, mask_sh), \ - OPP_SF(CM0_CM_OCSC_C11_C12, CM_OCSC_C11, mask_sh), \ - OPP_SF(CM0_CM_OCSC_C11_C12, CM_OCSC_C12, mask_sh), \ - OPP_SF(CM0_CM_OCSC_C13_C14, CM_OCSC_C13, mask_sh), \ - OPP_SF(CM0_CM_OCSC_C13_C14, CM_OCSC_C14, mask_sh), \ - OPP_SF(CM0_CM_OCSC_C21_C22, CM_OCSC_C21, mask_sh), \ - OPP_SF(CM0_CM_OCSC_C21_C22, CM_OCSC_C22, mask_sh), \ - OPP_SF(CM0_CM_OCSC_C23_C24, CM_OCSC_C23, mask_sh), \ - OPP_SF(CM0_CM_OCSC_C23_C24, CM_OCSC_C24, mask_sh), \ - OPP_SF(CM0_CM_OCSC_C31_C32, CM_OCSC_C31, mask_sh), \ - OPP_SF(CM0_CM_OCSC_C31_C32, CM_OCSC_C32, mask_sh), \ - OPP_SF(CM0_CM_OCSC_C33_C34, CM_OCSC_C33, mask_sh), \ - OPP_SF(CM0_CM_OCSC_C33_C34, CM_OCSC_C34, mask_sh), \ - OPP_SF(CM0_CM_COMB_C11_C12, CM_COMB_C11, mask_sh), \ - OPP_SF(CM0_CM_COMB_C11_C12, CM_COMB_C12, mask_sh), \ - OPP_SF(CM0_CM_COMB_C13_C14, CM_COMB_C13, mask_sh), \ - OPP_SF(CM0_CM_COMB_C13_C14, CM_COMB_C14, mask_sh), \ - OPP_SF(CM0_CM_COMB_C21_C22, CM_COMB_C21, mask_sh), \ - OPP_SF(CM0_CM_COMB_C21_C22, CM_COMB_C22, mask_sh), \ - OPP_SF(CM0_CM_COMB_C23_C24, CM_COMB_C23, mask_sh), \ - OPP_SF(CM0_CM_COMB_C23_C24, CM_COMB_C24, mask_sh), \ - OPP_SF(CM0_CM_COMB_C31_C32, CM_COMB_C31, mask_sh), \ - OPP_SF(CM0_CM_COMB_C31_C32, CM_COMB_C32, mask_sh), \ - OPP_SF(CM0_CM_COMB_C33_C34, CM_COMB_C33, mask_sh), \ - OPP_SF(CM0_CM_COMB_C33_C34, CM_COMB_C34, mask_sh), \ OPP_SF(CM0_CM_RGAM_CONTROL, CM_RGAM_LUT_MODE, mask_sh), \ - OPP_SF(CM0_CM_OCSC_CONTROL, CM_OCSC_MODE, mask_sh), \ OPP_SF(CM0_CM_RGAM_RAMB_START_CNTL_B, CM_RGAM_RAMB_EXP_REGION_START_B, mask_sh), \ OPP_SF(CM0_CM_RGAM_RAMB_START_CNTL_B, CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B, mask_sh), \ OPP_SF(CM0_CM_RGAM_RAMB_START_CNTL_G, CM_RGAM_RAMB_EXP_REGION_START_G, mask_sh), \ @@ -414,7 +376,6 @@ type FMT_DYNAMIC_EXP_EN; \ type FMT_DYNAMIC_EXP_MODE; \ type FMT_MAP420MEM_PWR_FORCE; \ - type CM_OCSC_MODE; \ type CM_RGAM_RAMB_EXP_REGION_START_B; \ type CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B; \ type CM_RGAM_RAMB_EXP_REGION_START_G; \ @@ -630,7 +591,6 @@ struct dcn10_opp_registers { uint32_t FMT_CLAMP_CNTL; uint32_t FMT_DYNAMIC_EXP_CNTL; uint32_t FMT_MAP420_MEMORY_CONTROL; - uint32_t CM_OCSC_CONTROL; uint32_t CM_RGAM_RAMB_START_CNTL_B; uint32_t CM_RGAM_RAMB_START_CNTL_G; uint32_t CM_RGAM_RAMB_START_CNTL_R; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h index 0212618a36be..137b4c8dc9d5 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h @@ -28,6 +28,7 @@ #include "os_types.h" #include "fixed31_32.h" +#include "dc_hw_types.h" /****************************************************************************** * Data types shared between different Virtual HW blocks @@ -76,4 +77,40 @@ struct pwl_params { struct pwl_result_data rgb_resulted[256 + 3]; uint32_t hw_points_num; }; + +/* move to dpp + * while we are moving functionality out of opp to dpp to align + * HW programming to HW IP, we define these struct in hw_shared + * so we can still compile while refactoring + */ + +enum lb_pixel_depth { + /* do not change the values because it is used as bit vector */ + LB_PIXEL_DEPTH_18BPP = 1, + LB_PIXEL_DEPTH_24BPP = 2, + LB_PIXEL_DEPTH_30BPP = 4, + LB_PIXEL_DEPTH_36BPP = 8 +}; + +enum graphics_csc_adjust_type { + GRAPHICS_CSC_ADJUST_TYPE_BYPASS = 0, + GRAPHICS_CSC_ADJUST_TYPE_HW, /* without adjustments */ + GRAPHICS_CSC_ADJUST_TYPE_SW /*use adjustments */ +}; + +struct default_adjustment { + enum lb_pixel_depth lb_color_depth; + enum dc_color_space out_color_space; + enum dc_color_space in_color_space; + enum dc_color_depth color_depth; + enum pixel_format surface_pixel_format; + enum graphics_csc_adjust_type csc_adjust_type; + bool force_hw_default; +}; + +struct out_csc_color_matrix { + enum dc_color_space color_space; + uint16_t regval[12]; +}; + #endif /* __DAL_HW_SHARED_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h index 57bdd6c8f955..ef36ffdf2a68 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h @@ -217,22 +217,6 @@ enum fmt_stereo_action { FMT_STEREO_ACTION_UPDATE_POLARITY }; -enum graphics_csc_adjust_type { - GRAPHICS_CSC_ADJUST_TYPE_BYPASS = 0, - GRAPHICS_CSC_ADJUST_TYPE_HW, /* without adjustments */ - GRAPHICS_CSC_ADJUST_TYPE_SW /*use adjustments */ -}; - -struct default_adjustment { - enum lb_pixel_depth lb_color_depth; - enum dc_color_space out_color_space; - enum dc_color_space in_color_space; - enum dc_color_depth color_depth; - enum pixel_format surface_pixel_format; - enum graphics_csc_adjust_type csc_adjust_type; - bool force_hw_default; -}; - enum grph_color_adjust_option { GRPH_COLOR_MATRIX_HW_DEFAULT = 1, GRPH_COLOR_MATRIX_SW @@ -250,11 +234,6 @@ struct opp_grph_csc_adjustment { int32_t grph_hue; }; -struct out_csc_color_matrix { - enum dc_color_space color_space; - uint16_t regval[12]; -}; - /* Underlay related types */ struct hw_adjustment_range { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h index b4862c376b41..132c5db07456 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h @@ -26,6 +26,7 @@ #ifndef __DAL_TRANSFORM_H__ #define __DAL_TRANSFORM_H__ +#include "hw_shared.h" #include "dc_hw_types.h" #include "fixed31_32.h" @@ -112,14 +113,6 @@ struct xfm_grph_csc_adjustment { enum graphics_gamut_adjust_type gamut_adjust_type; }; -enum lb_pixel_depth { - /* do not change the values because it is used as bit vector */ - LB_PIXEL_DEPTH_18BPP = 1, - LB_PIXEL_DEPTH_24BPP = 2, - LB_PIXEL_DEPTH_30BPP = 4, - LB_PIXEL_DEPTH_36BPP = 8 -}; - struct overscan_info { int left; int right; @@ -176,11 +169,6 @@ struct transform_funcs { void (*transform_set_scaler)(struct transform *xfm, const struct scaler_data *scl_data); - void (*transform_set_gamut_remap)( - struct transform *xfm, - const struct xfm_grph_csc_adjustment *adjust); - - void (*transform_set_pixel_storage_depth)( struct transform *xfm, enum lb_pixel_depth depth, @@ -190,6 +178,18 @@ struct transform_funcs { struct transform *xfm, struct scaler_data *scl_data, const struct scaling_taps *in_taps); + + void (*transform_set_gamut_remap)( + struct transform *xfm, + const struct xfm_grph_csc_adjustment *adjust); + + void (*opp_set_csc_default)( + struct transform *xfm, + const struct default_adjustment *default_adjust); + + void (*opp_set_csc_adjustment)( + struct transform *xfm, + const struct out_csc_color_matrix *tbl_entry); }; extern const uint16_t filter_2tap_16p[18]; -- cgit From b6762f0c16a43c3d2867fb652f8efa429f70c83d Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Mon, 24 Jul 2017 11:18:29 -0400 Subject: drm/amd/display: add missing func for dce11o to avoid crash Signed-off-by: Eric Yang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 72e099953a05..6ab9712ed808 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -2582,6 +2582,11 @@ static void dce110_power_down_fe(struct core_dc *dc, int fe_idx) dc->res_pool->transforms[fe_idx]); } +static void dce110_wait_for_mpcc_disconnect(struct resource_pool *res_pool, struct pipe_ctx *pipe_ctx) +{ + /* do nothing*/ +} + static const struct hw_sequencer_funcs dce110_funcs = { .program_gamut_remap = program_gamut_remap, .init_hw = init_hw, @@ -2611,6 +2616,7 @@ static const struct hw_sequencer_funcs dce110_funcs = { .prog_pixclk_crtc_otg = dce110_prog_pixclk_crtc_otg, .setup_stereo = NULL, .set_avmute = dce110_set_avmute, + .wait_for_mpcc_disconnect = dce110_wait_for_mpcc_disconnect }; bool dce110_hw_sequencer_construct(struct core_dc *dc) -- cgit From e63825be738ea0bb975aee43b603ac5f0190d7a8 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Sun, 23 Jul 2017 16:45:45 -0400 Subject: drm/amd/display: fix YCbCr420 deep color mode not supported Signed-off-by: Charlene Liu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index a1eabc47558e..17b28280236f 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -858,6 +858,8 @@ bool dcn_validate_bandwidth( - pipe->stream->public.timing.v_front_porch; v->vactive[input_idx] = pipe->stream->public.timing.v_addressable; v->pixel_clock[input_idx] = pipe->stream->public.timing.pix_clk_khz / 1000.0f; + if (pipe->stream->public.timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) + v->pixel_clock[input_idx] /= 2; if (!pipe->surface){ -- cgit From c8d7bd8bd0c08aa9115589d264e274ed7fdf4c2e Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Sun, 23 Jul 2017 12:13:37 -0400 Subject: drm/amd/display: move RGAM programming from opp to dpp Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c | 432 ++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h | 499 ++++++++++++++++++++- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 16 +- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c | 428 ------------------ drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h | 492 +------------------- drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h | 7 + drivers/gpu/drm/amd/display/dc/inc/hw/opp.h | 7 - drivers/gpu/drm/amd/display/dc/inc/hw/transform.h | 29 ++ 8 files changed, 972 insertions(+), 938 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c index 0f3f1a31f10b..b6aaa95d442b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c @@ -1134,6 +1134,431 @@ static void oppn10_set_output_csc_adjustment( oppn10_program_color_matrix(xfm, tbl_entry); } +static void oppn10_power_on_regamma_lut( + struct transform *xfm_base, + bool power_on) +{ + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + REG_SET(CM_MEM_PWR_CTRL, 0, + RGAM_MEM_PWR_FORCE, power_on == true ? 0:1); + +} + +static void opp_program_regamma_lut( + struct transform *xfm_base, + const struct pwl_result_data *rgb, + uint32_t num) +{ + uint32_t i; + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + for (i = 0 ; i < num; i++) { + REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].red_reg); + REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].green_reg); + REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].blue_reg); + + REG_SET(CM_RGAM_LUT_DATA, 0, + CM_RGAM_LUT_DATA, rgb[i].delta_red_reg); + REG_SET(CM_RGAM_LUT_DATA, 0, + CM_RGAM_LUT_DATA, rgb[i].delta_green_reg); + REG_SET(CM_RGAM_LUT_DATA, 0, + CM_RGAM_LUT_DATA, rgb[i].delta_blue_reg); + + } + +} + +static void opp_configure_regamma_lut( + struct transform *xfm_base, + bool is_ram_a) +{ + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + + REG_UPDATE(CM_RGAM_LUT_WRITE_EN_MASK, + CM_RGAM_LUT_WRITE_EN_MASK, 7); + REG_UPDATE(CM_RGAM_LUT_WRITE_EN_MASK, + CM_RGAM_LUT_WRITE_SEL, is_ram_a == true ? 0:1); + REG_SET(CM_RGAM_LUT_INDEX, 0, CM_RGAM_LUT_INDEX, 0); +} + +/*program re gamma RAM A*/ +static void opp_program_regamma_luta_settings( + struct transform *xfm_base, + const struct pwl_params *params) +{ + const struct gamma_curve *curve; + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + + REG_SET_2(CM_RGAM_RAMA_START_CNTL_B, 0, + CM_RGAM_RAMA_EXP_REGION_START_B, params->arr_points[0].custom_float_x, + CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_B, 0); + REG_SET_2(CM_RGAM_RAMA_START_CNTL_G, 0, + CM_RGAM_RAMA_EXP_REGION_START_G, params->arr_points[0].custom_float_x, + CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_G, 0); + REG_SET_2(CM_RGAM_RAMA_START_CNTL_R, 0, + CM_RGAM_RAMA_EXP_REGION_START_R, params->arr_points[0].custom_float_x, + CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_R, 0); + + REG_SET(CM_RGAM_RAMA_SLOPE_CNTL_B, 0, + CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B, params->arr_points[0].custom_float_slope); + REG_SET(CM_RGAM_RAMA_SLOPE_CNTL_G, 0, + CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G, params->arr_points[0].custom_float_slope); + REG_SET(CM_RGAM_RAMA_SLOPE_CNTL_R, 0, + CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R, params->arr_points[0].custom_float_slope); + + REG_SET(CM_RGAM_RAMA_END_CNTL1_B, 0, + CM_RGAM_RAMA_EXP_REGION_END_B, params->arr_points[1].custom_float_x); + REG_SET_2(CM_RGAM_RAMA_END_CNTL2_B, 0, + CM_RGAM_RAMA_EXP_REGION_END_SLOPE_B, params->arr_points[1].custom_float_slope, + CM_RGAM_RAMA_EXP_REGION_END_BASE_B, params->arr_points[1].custom_float_y); + + REG_SET(CM_RGAM_RAMA_END_CNTL1_G, 0, + CM_RGAM_RAMA_EXP_REGION_END_G, params->arr_points[1].custom_float_x); + REG_SET_2(CM_RGAM_RAMA_END_CNTL2_G, 0, + CM_RGAM_RAMA_EXP_REGION_END_SLOPE_G, params->arr_points[1].custom_float_slope, + CM_RGAM_RAMA_EXP_REGION_END_BASE_G, params->arr_points[1].custom_float_y); + + REG_SET(CM_RGAM_RAMA_END_CNTL1_R, 0, + CM_RGAM_RAMA_EXP_REGION_END_R, params->arr_points[1].custom_float_x); + REG_SET_2(CM_RGAM_RAMA_END_CNTL2_R, 0, + CM_RGAM_RAMA_EXP_REGION_END_SLOPE_R, params->arr_points[1].custom_float_slope, + CM_RGAM_RAMA_EXP_REGION_END_BASE_R, params->arr_points[1].custom_float_y); + + curve = params->arr_curve_points; + REG_SET_4(CM_RGAM_RAMA_REGION_0_1, 0, + CM_RGAM_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_2_3, 0, + CM_RGAM_RAMA_EXP_REGION2_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION3_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_4_5, 0, + CM_RGAM_RAMA_EXP_REGION4_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION5_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_6_7, 0, + CM_RGAM_RAMA_EXP_REGION6_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION7_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_8_9, 0, + CM_RGAM_RAMA_EXP_REGION8_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION9_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_10_11, 0, + CM_RGAM_RAMA_EXP_REGION10_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION11_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_12_13, 0, + CM_RGAM_RAMA_EXP_REGION12_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION13_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_14_15, 0, + CM_RGAM_RAMA_EXP_REGION14_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION15_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_16_17, 0, + CM_RGAM_RAMA_EXP_REGION16_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION16_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION17_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION17_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_18_19, 0, + CM_RGAM_RAMA_EXP_REGION18_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION18_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION19_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION19_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_20_21, 0, + CM_RGAM_RAMA_EXP_REGION20_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION20_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION21_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION21_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_22_23, 0, + CM_RGAM_RAMA_EXP_REGION22_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION22_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION23_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION23_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_24_25, 0, + CM_RGAM_RAMA_EXP_REGION24_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION24_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION25_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION25_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_26_27, 0, + CM_RGAM_RAMA_EXP_REGION26_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION26_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION27_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION27_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_28_29, 0, + CM_RGAM_RAMA_EXP_REGION28_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION28_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION29_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION29_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_30_31, 0, + CM_RGAM_RAMA_EXP_REGION30_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION30_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION31_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION31_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_32_33, 0, + CM_RGAM_RAMA_EXP_REGION32_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION32_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION33_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION33_NUM_SEGMENTS, curve[1].segments_num); +} + +/*program re gamma RAM B*/ +static void opp_program_regamma_lutb_settings( + struct transform *xfm_base, + const struct pwl_params *params) +{ + const struct gamma_curve *curve; + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + + REG_SET_2(CM_RGAM_RAMB_START_CNTL_B, 0, + CM_RGAM_RAMB_EXP_REGION_START_B, params->arr_points[0].custom_float_x, + CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B, 0); + REG_SET_2(CM_RGAM_RAMB_START_CNTL_G, 0, + CM_RGAM_RAMB_EXP_REGION_START_G, params->arr_points[0].custom_float_x, + CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_G, 0); + REG_SET_2(CM_RGAM_RAMB_START_CNTL_R, 0, + CM_RGAM_RAMB_EXP_REGION_START_R, params->arr_points[0].custom_float_x, + CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_R, 0); + + REG_SET(CM_RGAM_RAMB_SLOPE_CNTL_B, 0, + CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B, params->arr_points[0].custom_float_slope); + REG_SET(CM_RGAM_RAMB_SLOPE_CNTL_G, 0, + CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_G, params->arr_points[0].custom_float_slope); + REG_SET(CM_RGAM_RAMB_SLOPE_CNTL_R, 0, + CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_R, params->arr_points[0].custom_float_slope); + + REG_SET(CM_RGAM_RAMB_END_CNTL1_B, 0, + CM_RGAM_RAMB_EXP_REGION_END_B, params->arr_points[1].custom_float_x); + REG_SET_2(CM_RGAM_RAMB_END_CNTL2_B, 0, + CM_RGAM_RAMB_EXP_REGION_END_SLOPE_B, params->arr_points[1].custom_float_slope, + CM_RGAM_RAMB_EXP_REGION_END_BASE_B, params->arr_points[1].custom_float_y); + + REG_SET(CM_RGAM_RAMB_END_CNTL1_G, 0, + CM_RGAM_RAMB_EXP_REGION_END_G, params->arr_points[1].custom_float_x); + REG_SET_2(CM_RGAM_RAMB_END_CNTL2_G, 0, + CM_RGAM_RAMB_EXP_REGION_END_SLOPE_G, params->arr_points[1].custom_float_slope, + CM_RGAM_RAMB_EXP_REGION_END_BASE_G, params->arr_points[1].custom_float_y); + + REG_SET(CM_RGAM_RAMB_END_CNTL1_R, 0, + CM_RGAM_RAMB_EXP_REGION_END_R, params->arr_points[1].custom_float_x); + REG_SET_2(CM_RGAM_RAMB_END_CNTL2_R, 0, + CM_RGAM_RAMB_EXP_REGION_END_SLOPE_R, params->arr_points[1].custom_float_slope, + CM_RGAM_RAMB_EXP_REGION_END_BASE_R, params->arr_points[1].custom_float_y); + + curve = params->arr_curve_points; + REG_SET_4(CM_RGAM_RAMB_REGION_0_1, 0, + CM_RGAM_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_2_3, 0, + CM_RGAM_RAMB_EXP_REGION2_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION3_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_4_5, 0, + CM_RGAM_RAMB_EXP_REGION4_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION5_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_6_7, 0, + CM_RGAM_RAMB_EXP_REGION6_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION7_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_8_9, 0, + CM_RGAM_RAMB_EXP_REGION8_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION9_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_10_11, 0, + CM_RGAM_RAMB_EXP_REGION10_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION11_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_12_13, 0, + CM_RGAM_RAMB_EXP_REGION12_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION13_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_14_15, 0, + CM_RGAM_RAMB_EXP_REGION14_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION15_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_16_17, 0, + CM_RGAM_RAMB_EXP_REGION16_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION16_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION17_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION17_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_18_19, 0, + CM_RGAM_RAMB_EXP_REGION18_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION18_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION19_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION19_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_20_21, 0, + CM_RGAM_RAMB_EXP_REGION20_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION20_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION21_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION21_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_22_23, 0, + CM_RGAM_RAMB_EXP_REGION22_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION22_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION23_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION23_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_24_25, 0, + CM_RGAM_RAMB_EXP_REGION24_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION24_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION25_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION25_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_26_27, 0, + CM_RGAM_RAMB_EXP_REGION26_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION26_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION27_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION27_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_28_29, 0, + CM_RGAM_RAMB_EXP_REGION28_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION28_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION29_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION29_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_30_31, 0, + CM_RGAM_RAMB_EXP_REGION30_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION30_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION31_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION31_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_32_33, 0, + CM_RGAM_RAMB_EXP_REGION32_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION32_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION33_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION33_NUM_SEGMENTS, curve[1].segments_num); + +} + +static bool oppn10_set_regamma_pwl( + struct transform *xfm_base, const struct pwl_params *params) +{ + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + + oppn10_power_on_regamma_lut(xfm_base, true); + opp_configure_regamma_lut(xfm_base, xfm->is_write_to_ram_a_safe); + + if (xfm->is_write_to_ram_a_safe) + opp_program_regamma_luta_settings(xfm_base, params); + else + opp_program_regamma_lutb_settings(xfm_base, params); + + opp_program_regamma_lut( + xfm_base, params->rgb_resulted, params->hw_points_num); + + return true; +} + +static void oppn10_set_regamma_mode( + struct transform *xfm_base, + enum opp_regamma mode) +{ + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + uint32_t re_mode = 0; + uint32_t obuf_bypass = 0; /* need for pipe split */ + uint32_t obuf_hupscale = 0; + + switch (mode) { + case OPP_REGAMMA_BYPASS: + re_mode = 0; + break; + case OPP_REGAMMA_SRGB: + re_mode = 1; + break; + case OPP_REGAMMA_3_6: + re_mode = 2; + break; + case OPP_REGAMMA_USER: + re_mode = xfm->is_write_to_ram_a_safe ? 3 : 4; + xfm->is_write_to_ram_a_safe = !xfm->is_write_to_ram_a_safe; + break; + default: + break; + } + + REG_SET(CM_RGAM_CONTROL, 0, CM_RGAM_LUT_MODE, re_mode); + REG_UPDATE_2(OBUF_CONTROL, + OBUF_BYPASS, obuf_bypass, + OBUF_H_2X_UPSCALE_EN, obuf_hupscale); +} + static struct transform_funcs dcn10_dpp_funcs = { .transform_reset = dpp_reset, .transform_set_scaler = dpp_set_scaler_manual_scale, @@ -1141,6 +1566,13 @@ static struct transform_funcs dcn10_dpp_funcs = { .transform_set_gamut_remap = dcn_dpp_set_gamut_remap, .opp_set_csc_adjustment = oppn10_set_output_csc_adjustment, .opp_set_csc_default = oppn10_set_output_csc_default, + .opp_power_on_regamma_lut = oppn10_power_on_regamma_lut, + .opp_program_regamma_lut = opp_program_regamma_lut, + .opp_configure_regamma_lut = opp_configure_regamma_lut, + .opp_program_regamma_lutb_settings = opp_program_regamma_lutb_settings, + .opp_program_regamma_luta_settings = opp_program_regamma_luta_settings, + .opp_program_regamma_pwl = oppn10_set_regamma_pwl, + .opp_set_regamma_mode = oppn10_set_regamma_mode }; /*****************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h index 693060e79d21..34085c0818e5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h @@ -71,7 +71,8 @@ SRI(SCL_VERT_FILTER_INIT_C, DSCL, id), \ SRI(SCL_VERT_FILTER_INIT_BOT_C, DSCL, id), \ SRI(RECOUT_START, DSCL, id), \ - SRI(RECOUT_SIZE, DSCL, id) + SRI(RECOUT_SIZE, DSCL, id), \ + SRI(OBUF_CONTROL, DSCL, id) #define TF_REG_LIST_DCN10(id) \ TF_REG_LIST_DCN(id), \ @@ -93,7 +94,70 @@ SRI(CM_OCSC_C21_C22, CM, id), \ SRI(CM_OCSC_C23_C24, CM, id), \ SRI(CM_OCSC_C31_C32, CM, id), \ - SRI(CM_OCSC_C33_C34, CM, id) + SRI(CM_OCSC_C33_C34, CM, id), \ + SRI(CM_MEM_PWR_CTRL, CM, id), \ + SRI(CM_RGAM_LUT_DATA, CM, id), \ + SRI(CM_RGAM_LUT_WRITE_EN_MASK, CM, id),\ + SRI(CM_RGAM_LUT_INDEX, CM, id), \ + SRI(CM_RGAM_RAMB_START_CNTL_B, CM, id), \ + SRI(CM_RGAM_RAMB_START_CNTL_G, CM, id), \ + SRI(CM_RGAM_RAMB_START_CNTL_R, CM, id), \ + SRI(CM_RGAM_RAMB_SLOPE_CNTL_B, CM, id), \ + SRI(CM_RGAM_RAMB_SLOPE_CNTL_G, CM, id), \ + SRI(CM_RGAM_RAMB_SLOPE_CNTL_R, CM, id), \ + SRI(CM_RGAM_RAMB_END_CNTL1_B, CM, id), \ + SRI(CM_RGAM_RAMB_END_CNTL2_B, CM, id), \ + SRI(CM_RGAM_RAMB_END_CNTL1_G, CM, id), \ + SRI(CM_RGAM_RAMB_END_CNTL2_G, CM, id), \ + SRI(CM_RGAM_RAMB_END_CNTL1_R, CM, id), \ + SRI(CM_RGAM_RAMB_END_CNTL2_R, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_0_1, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_2_3, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_4_5, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_6_7, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_8_9, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_10_11, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_12_13, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_14_15, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_16_17, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_18_19, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_20_21, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_22_23, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_24_25, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_26_27, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_28_29, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_30_31, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_32_33, CM, id), \ + SRI(CM_RGAM_RAMA_START_CNTL_B, CM, id), \ + SRI(CM_RGAM_RAMA_START_CNTL_G, CM, id), \ + SRI(CM_RGAM_RAMA_START_CNTL_R, CM, id), \ + SRI(CM_RGAM_RAMA_SLOPE_CNTL_B, CM, id), \ + SRI(CM_RGAM_RAMA_SLOPE_CNTL_G, CM, id), \ + SRI(CM_RGAM_RAMA_SLOPE_CNTL_R, CM, id), \ + SRI(CM_RGAM_RAMA_END_CNTL1_B, CM, id), \ + SRI(CM_RGAM_RAMA_END_CNTL2_B, CM, id), \ + SRI(CM_RGAM_RAMA_END_CNTL1_G, CM, id), \ + SRI(CM_RGAM_RAMA_END_CNTL2_G, CM, id), \ + SRI(CM_RGAM_RAMA_END_CNTL1_R, CM, id), \ + SRI(CM_RGAM_RAMA_END_CNTL2_R, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_0_1, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_2_3, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_4_5, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_6_7, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_8_9, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_10_11, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_12_13, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_14_15, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_16_17, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_18_19, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_20_21, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_22_23, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_24_25, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_26_27, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_28_29, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_30_31, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_32_33, CM, id), \ + SRI(CM_RGAM_CONTROL, CM, id) #define TF_REG_LIST_SH_MASK_DCN(mask_sh)\ TF_SF(CM0_CM_GAMUT_REMAP_CONTROL, CM_GAMUT_REMAP_MODE, mask_sh),\ @@ -169,7 +233,8 @@ TF_SF(DSCL0_SCL_VERT_FILTER_INIT_BOT_C, SCL_V_INIT_FRAC_BOT_C, mask_sh),\ TF_SF(DSCL0_SCL_VERT_FILTER_INIT_BOT_C, SCL_V_INIT_INT_BOT_C, mask_sh),\ TF_SF(DSCL0_SCL_MODE, SCL_CHROMA_COEF_MODE, mask_sh),\ - TF_SF(DSCL0_SCL_MODE, SCL_COEF_RAM_SELECT_CURRENT, mask_sh) + TF_SF(DSCL0_SCL_MODE, SCL_COEF_RAM_SELECT_CURRENT, mask_sh), \ + TF_SF(DSCL0_OBUF_CONTROL, OBUF_BYPASS, mask_sh) #define TF_REG_LIST_SH_MASK_DCN10(mask_sh)\ TF_REG_LIST_SH_MASK_DCN(mask_sh),\ @@ -214,7 +279,186 @@ TF_SF(CM0_CM_OCSC_C31_C32, CM_OCSC_C31, mask_sh), \ TF_SF(CM0_CM_OCSC_C31_C32, CM_OCSC_C32, mask_sh), \ TF_SF(CM0_CM_OCSC_C33_C34, CM_OCSC_C33, mask_sh), \ - TF_SF(CM0_CM_OCSC_C33_C34, CM_OCSC_C34, mask_sh) + TF_SF(CM0_CM_OCSC_C33_C34, CM_OCSC_C34, mask_sh), \ + TF_SF(CM0_CM_MEM_PWR_CTRL, RGAM_MEM_PWR_FORCE, mask_sh), \ + TF_SF(CM0_CM_RGAM_LUT_DATA, CM_RGAM_LUT_DATA, mask_sh), \ + TF_SF(CM0_CM_RGAM_LUT_WRITE_EN_MASK, CM_RGAM_LUT_WRITE_EN_MASK, mask_sh), \ + TF_SF(CM0_CM_RGAM_LUT_WRITE_EN_MASK, CM_RGAM_LUT_WRITE_SEL, mask_sh), \ + TF_SF(CM0_CM_RGAM_LUT_INDEX, CM_RGAM_LUT_INDEX, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_START_CNTL_B, CM_RGAM_RAMB_EXP_REGION_START_B, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_START_CNTL_B, CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_START_CNTL_G, CM_RGAM_RAMB_EXP_REGION_START_G, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_START_CNTL_G, CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_G, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_START_CNTL_R, CM_RGAM_RAMB_EXP_REGION_START_R, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_START_CNTL_R, CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_R, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_SLOPE_CNTL_B, CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_SLOPE_CNTL_G, CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_G, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_SLOPE_CNTL_R, CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_R, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_END_CNTL1_B, CM_RGAM_RAMB_EXP_REGION_END_B, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_END_CNTL2_B, CM_RGAM_RAMB_EXP_REGION_END_SLOPE_B, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_END_CNTL2_B, CM_RGAM_RAMB_EXP_REGION_END_BASE_B, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_END_CNTL1_G, CM_RGAM_RAMB_EXP_REGION_END_G, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_END_CNTL2_G, CM_RGAM_RAMB_EXP_REGION_END_SLOPE_G, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_END_CNTL2_G, CM_RGAM_RAMB_EXP_REGION_END_BASE_G, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_END_CNTL1_R, CM_RGAM_RAMB_EXP_REGION_END_R, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_END_CNTL2_R, CM_RGAM_RAMB_EXP_REGION_END_SLOPE_R, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_END_CNTL2_R, CM_RGAM_RAMB_EXP_REGION_END_BASE_R, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_0_1, CM_RGAM_RAMB_EXP_REGION0_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_0_1, CM_RGAM_RAMB_EXP_REGION0_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_0_1, CM_RGAM_RAMB_EXP_REGION1_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_0_1, CM_RGAM_RAMB_EXP_REGION1_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_2_3, CM_RGAM_RAMB_EXP_REGION2_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_2_3, CM_RGAM_RAMB_EXP_REGION2_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_2_3, CM_RGAM_RAMB_EXP_REGION3_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_2_3, CM_RGAM_RAMB_EXP_REGION3_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_4_5, CM_RGAM_RAMB_EXP_REGION4_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_4_5, CM_RGAM_RAMB_EXP_REGION4_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_4_5, CM_RGAM_RAMB_EXP_REGION5_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_4_5, CM_RGAM_RAMB_EXP_REGION5_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_6_7, CM_RGAM_RAMB_EXP_REGION6_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_6_7, CM_RGAM_RAMB_EXP_REGION6_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_6_7, CM_RGAM_RAMB_EXP_REGION7_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_6_7, CM_RGAM_RAMB_EXP_REGION7_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_8_9, CM_RGAM_RAMB_EXP_REGION8_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_8_9, CM_RGAM_RAMB_EXP_REGION8_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_8_9, CM_RGAM_RAMB_EXP_REGION9_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_8_9, CM_RGAM_RAMB_EXP_REGION9_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_10_11, CM_RGAM_RAMB_EXP_REGION10_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_10_11, CM_RGAM_RAMB_EXP_REGION10_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_10_11, CM_RGAM_RAMB_EXP_REGION11_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_10_11, CM_RGAM_RAMB_EXP_REGION11_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_12_13, CM_RGAM_RAMB_EXP_REGION12_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_12_13, CM_RGAM_RAMB_EXP_REGION12_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_12_13, CM_RGAM_RAMB_EXP_REGION13_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_12_13, CM_RGAM_RAMB_EXP_REGION13_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_14_15, CM_RGAM_RAMB_EXP_REGION14_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_14_15, CM_RGAM_RAMB_EXP_REGION14_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_14_15, CM_RGAM_RAMB_EXP_REGION15_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_14_15, CM_RGAM_RAMB_EXP_REGION15_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_16_17, CM_RGAM_RAMB_EXP_REGION16_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_16_17, CM_RGAM_RAMB_EXP_REGION16_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_16_17, CM_RGAM_RAMB_EXP_REGION17_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_16_17, CM_RGAM_RAMB_EXP_REGION17_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_18_19, CM_RGAM_RAMB_EXP_REGION18_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_18_19, CM_RGAM_RAMB_EXP_REGION18_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_18_19, CM_RGAM_RAMB_EXP_REGION19_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_18_19, CM_RGAM_RAMB_EXP_REGION19_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_20_21, CM_RGAM_RAMB_EXP_REGION20_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_20_21, CM_RGAM_RAMB_EXP_REGION20_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_20_21, CM_RGAM_RAMB_EXP_REGION21_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_20_21, CM_RGAM_RAMB_EXP_REGION21_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_22_23, CM_RGAM_RAMB_EXP_REGION22_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_22_23, CM_RGAM_RAMB_EXP_REGION22_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_22_23, CM_RGAM_RAMB_EXP_REGION23_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_22_23, CM_RGAM_RAMB_EXP_REGION23_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_24_25, CM_RGAM_RAMB_EXP_REGION24_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_24_25, CM_RGAM_RAMB_EXP_REGION24_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_24_25, CM_RGAM_RAMB_EXP_REGION25_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_24_25, CM_RGAM_RAMB_EXP_REGION25_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_26_27, CM_RGAM_RAMB_EXP_REGION26_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_26_27, CM_RGAM_RAMB_EXP_REGION26_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_26_27, CM_RGAM_RAMB_EXP_REGION27_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_26_27, CM_RGAM_RAMB_EXP_REGION27_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_28_29, CM_RGAM_RAMB_EXP_REGION28_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_28_29, CM_RGAM_RAMB_EXP_REGION28_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_28_29, CM_RGAM_RAMB_EXP_REGION29_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_28_29, CM_RGAM_RAMB_EXP_REGION29_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_30_31, CM_RGAM_RAMB_EXP_REGION30_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_30_31, CM_RGAM_RAMB_EXP_REGION30_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_30_31, CM_RGAM_RAMB_EXP_REGION31_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_30_31, CM_RGAM_RAMB_EXP_REGION31_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_32_33, CM_RGAM_RAMB_EXP_REGION32_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_32_33, CM_RGAM_RAMB_EXP_REGION32_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_32_33, CM_RGAM_RAMB_EXP_REGION33_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_32_33, CM_RGAM_RAMB_EXP_REGION33_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_START_CNTL_B, CM_RGAM_RAMA_EXP_REGION_START_B, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_START_CNTL_B, CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_B, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_START_CNTL_G, CM_RGAM_RAMA_EXP_REGION_START_G, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_START_CNTL_G, CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_G, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_START_CNTL_R, CM_RGAM_RAMA_EXP_REGION_START_R, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_START_CNTL_R, CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_R, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_SLOPE_CNTL_B, CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_SLOPE_CNTL_G, CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_SLOPE_CNTL_R, CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_END_CNTL1_B, CM_RGAM_RAMA_EXP_REGION_END_B, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_END_CNTL2_B, CM_RGAM_RAMA_EXP_REGION_END_SLOPE_B, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_END_CNTL2_B, CM_RGAM_RAMA_EXP_REGION_END_BASE_B, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_END_CNTL1_G, CM_RGAM_RAMA_EXP_REGION_END_G, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_END_CNTL2_G, CM_RGAM_RAMA_EXP_REGION_END_SLOPE_G, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_END_CNTL2_G, CM_RGAM_RAMA_EXP_REGION_END_BASE_G, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_END_CNTL1_R, CM_RGAM_RAMA_EXP_REGION_END_R, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_END_CNTL2_R, CM_RGAM_RAMA_EXP_REGION_END_SLOPE_R, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_END_CNTL2_R, CM_RGAM_RAMA_EXP_REGION_END_BASE_R, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_0_1, CM_RGAM_RAMA_EXP_REGION0_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_0_1, CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_0_1, CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_0_1, CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_2_3, CM_RGAM_RAMA_EXP_REGION2_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_2_3, CM_RGAM_RAMA_EXP_REGION2_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_2_3, CM_RGAM_RAMA_EXP_REGION3_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_2_3, CM_RGAM_RAMA_EXP_REGION3_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_4_5, CM_RGAM_RAMA_EXP_REGION4_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_4_5, CM_RGAM_RAMA_EXP_REGION4_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_4_5, CM_RGAM_RAMA_EXP_REGION5_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_4_5, CM_RGAM_RAMA_EXP_REGION5_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_6_7, CM_RGAM_RAMA_EXP_REGION6_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_6_7, CM_RGAM_RAMA_EXP_REGION6_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_6_7, CM_RGAM_RAMA_EXP_REGION7_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_6_7, CM_RGAM_RAMA_EXP_REGION7_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_8_9, CM_RGAM_RAMA_EXP_REGION8_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_8_9, CM_RGAM_RAMA_EXP_REGION8_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_8_9, CM_RGAM_RAMA_EXP_REGION9_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_8_9, CM_RGAM_RAMA_EXP_REGION9_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_10_11, CM_RGAM_RAMA_EXP_REGION10_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_10_11, CM_RGAM_RAMA_EXP_REGION10_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_10_11, CM_RGAM_RAMA_EXP_REGION11_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_10_11, CM_RGAM_RAMA_EXP_REGION11_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_12_13, CM_RGAM_RAMA_EXP_REGION12_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_12_13, CM_RGAM_RAMA_EXP_REGION12_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_12_13, CM_RGAM_RAMA_EXP_REGION13_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_12_13, CM_RGAM_RAMA_EXP_REGION13_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_14_15, CM_RGAM_RAMA_EXP_REGION14_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_14_15, CM_RGAM_RAMA_EXP_REGION14_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_14_15, CM_RGAM_RAMA_EXP_REGION15_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_14_15, CM_RGAM_RAMA_EXP_REGION15_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_16_17, CM_RGAM_RAMA_EXP_REGION16_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_16_17, CM_RGAM_RAMA_EXP_REGION16_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_16_17, CM_RGAM_RAMA_EXP_REGION17_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_16_17, CM_RGAM_RAMA_EXP_REGION17_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_18_19, CM_RGAM_RAMA_EXP_REGION18_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_18_19, CM_RGAM_RAMA_EXP_REGION18_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_18_19, CM_RGAM_RAMA_EXP_REGION19_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_18_19, CM_RGAM_RAMA_EXP_REGION19_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_20_21, CM_RGAM_RAMA_EXP_REGION20_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_20_21, CM_RGAM_RAMA_EXP_REGION20_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_20_21, CM_RGAM_RAMA_EXP_REGION21_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_20_21, CM_RGAM_RAMA_EXP_REGION21_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_22_23, CM_RGAM_RAMA_EXP_REGION22_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_22_23, CM_RGAM_RAMA_EXP_REGION22_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_22_23, CM_RGAM_RAMA_EXP_REGION23_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_22_23, CM_RGAM_RAMA_EXP_REGION23_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_24_25, CM_RGAM_RAMA_EXP_REGION24_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_24_25, CM_RGAM_RAMA_EXP_REGION24_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_24_25, CM_RGAM_RAMA_EXP_REGION25_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_24_25, CM_RGAM_RAMA_EXP_REGION25_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_26_27, CM_RGAM_RAMA_EXP_REGION26_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_26_27, CM_RGAM_RAMA_EXP_REGION26_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_26_27, CM_RGAM_RAMA_EXP_REGION27_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_26_27, CM_RGAM_RAMA_EXP_REGION27_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_28_29, CM_RGAM_RAMA_EXP_REGION28_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_28_29, CM_RGAM_RAMA_EXP_REGION28_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_28_29, CM_RGAM_RAMA_EXP_REGION29_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_28_29, CM_RGAM_RAMA_EXP_REGION29_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_30_31, CM_RGAM_RAMA_EXP_REGION30_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_30_31, CM_RGAM_RAMA_EXP_REGION30_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_30_31, CM_RGAM_RAMA_EXP_REGION31_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_30_31, CM_RGAM_RAMA_EXP_REGION31_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_32_33, CM_RGAM_RAMA_EXP_REGION32_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_32_33, CM_RGAM_RAMA_EXP_REGION32_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_32_33, CM_RGAM_RAMA_EXP_REGION33_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_32_33, CM_RGAM_RAMA_EXP_REGION33_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_CONTROL, CM_RGAM_LUT_MODE, mask_sh), \ + TF_SF(DSCL0_OBUF_CONTROL, OBUF_H_2X_UPSCALE_EN, mask_sh) #define TF_REG_FIELD_LIST(type) \ @@ -333,7 +577,187 @@ type CM_OCSC_C31; \ type CM_OCSC_C32; \ type CM_OCSC_C33; \ - type CM_OCSC_C34 + type CM_OCSC_C34; \ + type RGAM_MEM_PWR_FORCE; \ + type CM_RGAM_LUT_DATA; \ + type CM_RGAM_LUT_WRITE_EN_MASK; \ + type CM_RGAM_LUT_WRITE_SEL; \ + type CM_RGAM_LUT_INDEX; \ + type CM_RGAM_RAMB_EXP_REGION_START_B; \ + type CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B; \ + type CM_RGAM_RAMB_EXP_REGION_START_G; \ + type CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_G; \ + type CM_RGAM_RAMB_EXP_REGION_START_R; \ + type CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_R; \ + type CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B; \ + type CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_G; \ + type CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_R; \ + type CM_RGAM_RAMB_EXP_REGION_END_B; \ + type CM_RGAM_RAMB_EXP_REGION_END_SLOPE_B; \ + type CM_RGAM_RAMB_EXP_REGION_END_BASE_B; \ + type CM_RGAM_RAMB_EXP_REGION_END_G; \ + type CM_RGAM_RAMB_EXP_REGION_END_SLOPE_G; \ + type CM_RGAM_RAMB_EXP_REGION_END_BASE_G; \ + type CM_RGAM_RAMB_EXP_REGION_END_R; \ + type CM_RGAM_RAMB_EXP_REGION_END_SLOPE_R; \ + type CM_RGAM_RAMB_EXP_REGION_END_BASE_R; \ + type CM_RGAM_RAMB_EXP_REGION0_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION0_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION1_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION1_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION2_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION2_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION3_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION3_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION4_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION4_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION5_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION5_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION6_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION6_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION7_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION7_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION8_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION8_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION9_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION9_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION10_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION10_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION11_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION11_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION12_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION12_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION13_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION13_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION14_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION14_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION15_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION15_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION16_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION16_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION17_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION17_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION18_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION18_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION19_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION19_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION20_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION20_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION21_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION21_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION22_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION22_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION23_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION23_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION24_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION24_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION25_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION25_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION26_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION26_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION27_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION27_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION28_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION28_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION29_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION29_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION30_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION30_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION31_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION31_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION32_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION32_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION33_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION33_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION_START_B; \ + type CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_B; \ + type CM_RGAM_RAMA_EXP_REGION_START_G; \ + type CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_G; \ + type CM_RGAM_RAMA_EXP_REGION_START_R; \ + type CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_R; \ + type CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B; \ + type CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G; \ + type CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R; \ + type CM_RGAM_RAMA_EXP_REGION_END_B; \ + type CM_RGAM_RAMA_EXP_REGION_END_SLOPE_B; \ + type CM_RGAM_RAMA_EXP_REGION_END_BASE_B; \ + type CM_RGAM_RAMA_EXP_REGION_END_G; \ + type CM_RGAM_RAMA_EXP_REGION_END_SLOPE_G; \ + type CM_RGAM_RAMA_EXP_REGION_END_BASE_G; \ + type CM_RGAM_RAMA_EXP_REGION_END_R; \ + type CM_RGAM_RAMA_EXP_REGION_END_SLOPE_R; \ + type CM_RGAM_RAMA_EXP_REGION_END_BASE_R; \ + type CM_RGAM_RAMA_EXP_REGION0_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION2_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION2_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION3_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION3_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION4_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION4_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION5_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION5_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION6_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION6_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION7_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION7_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION8_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION8_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION9_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION9_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION10_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION10_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION11_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION11_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION12_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION12_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION13_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION13_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION14_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION14_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION15_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION15_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION16_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION16_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION17_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION17_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION18_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION18_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION19_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION19_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION20_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION20_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION21_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION21_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION22_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION22_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION23_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION23_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION24_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION24_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION25_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION25_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION26_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION26_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION27_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION27_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION28_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION28_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION29_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION29_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION30_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION30_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION31_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION31_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION32_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION32_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION33_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION33_NUM_SEGMENTS; \ + type CM_RGAM_LUT_MODE; \ + type OBUF_BYPASS; \ + type OBUF_H_2X_UPSCALE_EN struct dcn_dpp_shift { TF_REG_FIELD_LIST(uint8_t); @@ -397,6 +821,70 @@ struct dcn_dpp_registers { uint32_t CM_OCSC_C23_C24; uint32_t CM_OCSC_C31_C32; uint32_t CM_OCSC_C33_C34; + uint32_t CM_MEM_PWR_CTRL; + uint32_t CM_RGAM_LUT_DATA; + uint32_t CM_RGAM_LUT_WRITE_EN_MASK; + uint32_t CM_RGAM_LUT_INDEX; + uint32_t CM_RGAM_RAMB_START_CNTL_B; + uint32_t CM_RGAM_RAMB_START_CNTL_G; + uint32_t CM_RGAM_RAMB_START_CNTL_R; + uint32_t CM_RGAM_RAMB_SLOPE_CNTL_B; + uint32_t CM_RGAM_RAMB_SLOPE_CNTL_G; + uint32_t CM_RGAM_RAMB_SLOPE_CNTL_R; + uint32_t CM_RGAM_RAMB_END_CNTL1_B; + uint32_t CM_RGAM_RAMB_END_CNTL2_B; + uint32_t CM_RGAM_RAMB_END_CNTL1_G; + uint32_t CM_RGAM_RAMB_END_CNTL2_G; + uint32_t CM_RGAM_RAMB_END_CNTL1_R; + uint32_t CM_RGAM_RAMB_END_CNTL2_R; + uint32_t CM_RGAM_RAMB_REGION_0_1; + uint32_t CM_RGAM_RAMB_REGION_2_3; + uint32_t CM_RGAM_RAMB_REGION_4_5; + uint32_t CM_RGAM_RAMB_REGION_6_7; + uint32_t CM_RGAM_RAMB_REGION_8_9; + uint32_t CM_RGAM_RAMB_REGION_10_11; + uint32_t CM_RGAM_RAMB_REGION_12_13; + uint32_t CM_RGAM_RAMB_REGION_14_15; + uint32_t CM_RGAM_RAMB_REGION_16_17; + uint32_t CM_RGAM_RAMB_REGION_18_19; + uint32_t CM_RGAM_RAMB_REGION_20_21; + uint32_t CM_RGAM_RAMB_REGION_22_23; + uint32_t CM_RGAM_RAMB_REGION_24_25; + uint32_t CM_RGAM_RAMB_REGION_26_27; + uint32_t CM_RGAM_RAMB_REGION_28_29; + uint32_t CM_RGAM_RAMB_REGION_30_31; + uint32_t CM_RGAM_RAMB_REGION_32_33; + uint32_t CM_RGAM_RAMA_START_CNTL_B; + uint32_t CM_RGAM_RAMA_START_CNTL_G; + uint32_t CM_RGAM_RAMA_START_CNTL_R; + uint32_t CM_RGAM_RAMA_SLOPE_CNTL_B; + uint32_t CM_RGAM_RAMA_SLOPE_CNTL_G; + uint32_t CM_RGAM_RAMA_SLOPE_CNTL_R; + uint32_t CM_RGAM_RAMA_END_CNTL1_B; + uint32_t CM_RGAM_RAMA_END_CNTL2_B; + uint32_t CM_RGAM_RAMA_END_CNTL1_G; + uint32_t CM_RGAM_RAMA_END_CNTL2_G; + uint32_t CM_RGAM_RAMA_END_CNTL1_R; + uint32_t CM_RGAM_RAMA_END_CNTL2_R; + uint32_t CM_RGAM_RAMA_REGION_0_1; + uint32_t CM_RGAM_RAMA_REGION_2_3; + uint32_t CM_RGAM_RAMA_REGION_4_5; + uint32_t CM_RGAM_RAMA_REGION_6_7; + uint32_t CM_RGAM_RAMA_REGION_8_9; + uint32_t CM_RGAM_RAMA_REGION_10_11; + uint32_t CM_RGAM_RAMA_REGION_12_13; + uint32_t CM_RGAM_RAMA_REGION_14_15; + uint32_t CM_RGAM_RAMA_REGION_16_17; + uint32_t CM_RGAM_RAMA_REGION_18_19; + uint32_t CM_RGAM_RAMA_REGION_20_21; + uint32_t CM_RGAM_RAMA_REGION_22_23; + uint32_t CM_RGAM_RAMA_REGION_24_25; + uint32_t CM_RGAM_RAMA_REGION_26_27; + uint32_t CM_RGAM_RAMA_REGION_28_29; + uint32_t CM_RGAM_RAMA_REGION_30_31; + uint32_t CM_RGAM_RAMA_REGION_32_33; + uint32_t CM_RGAM_CONTROL; + uint32_t OBUF_CONTROL; }; struct dcn10_dpp { @@ -413,6 +901,7 @@ struct dcn10_dpp { int lb_pixel_depth_supported; int lb_memory_size; int lb_bits_per_entry; + bool is_write_to_ram_a_safe; }; bool dcn10_dpp_construct(struct dcn10_dpp *xfm110, struct dc_context *ctx, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 4cbca15e1cc5..d61b63df16b8 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1054,25 +1054,25 @@ static bool dcn10_set_output_transfer_func( struct pipe_ctx *pipe_ctx, const struct core_stream *stream) { - struct output_pixel_processor *opp = pipe_ctx->opp; + struct transform *xfm = pipe_ctx->xfm; - if (opp == NULL) + if (xfm == NULL) return false; - opp->regamma_params.hw_points_num = GAMMA_HW_POINTS_NUM; + xfm->regamma_params.hw_points_num = GAMMA_HW_POINTS_NUM; if (stream->public.out_transfer_func && stream->public.out_transfer_func->type == TF_TYPE_PREDEFINED && stream->public.out_transfer_func->tf == TRANSFER_FUNCTION_SRGB) { - opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_SRGB); + xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_SRGB); } else if (dcn10_translate_regamma_to_hw_format( - stream->public.out_transfer_func, &opp->regamma_params)) { - opp->funcs->opp_program_regamma_pwl(opp, &opp->regamma_params); - opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_USER); + stream->public.out_transfer_func, &xfm->regamma_params)) { + xfm->funcs->opp_program_regamma_pwl(xfm, &xfm->regamma_params); + xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_USER); } else { - opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_BYPASS); + xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_BYPASS); } return true; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c index 5cf985e4ffa9..f8e4724a629d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c @@ -37,38 +37,7 @@ #define CTX \ oppn10->base.ctx -static void oppn10_set_regamma_mode( - struct output_pixel_processor *opp, - enum opp_regamma mode) -{ - struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); - uint32_t re_mode = 0; - uint32_t obuf_bypass = 0; /* need for pipe split */ - uint32_t obuf_hupscale = 0; - - switch (mode) { - case OPP_REGAMMA_BYPASS: - re_mode = 0; - break; - case OPP_REGAMMA_SRGB: - re_mode = 1; - break; - case OPP_REGAMMA_3_6: - re_mode = 2; - break; - case OPP_REGAMMA_USER: - re_mode = oppn10->is_write_to_ram_a_safe ? 3 : 4; - oppn10->is_write_to_ram_a_safe = !oppn10->is_write_to_ram_a_safe; - break; - default: - break; - } - REG_SET(CM_RGAM_CONTROL, 0, CM_RGAM_LUT_MODE, re_mode); - REG_UPDATE_2(OBUF_CONTROL, - OBUF_BYPASS, obuf_bypass, - OBUF_H_2X_UPSCALE_EN, obuf_hupscale); -} /************* FORMATTER ************/ @@ -328,400 +297,6 @@ static void oppn10_program_fmt( } -/*program re gamma RAM B*/ -static void opp_program_regamma_lutb_settings( - struct output_pixel_processor *opp, - const struct pwl_params *params) -{ - const struct gamma_curve *curve; - struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); - - REG_SET_2(CM_RGAM_RAMB_START_CNTL_B, 0, - CM_RGAM_RAMB_EXP_REGION_START_B, params->arr_points[0].custom_float_x, - CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B, 0); - REG_SET_2(CM_RGAM_RAMB_START_CNTL_G, 0, - CM_RGAM_RAMB_EXP_REGION_START_G, params->arr_points[0].custom_float_x, - CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_G, 0); - REG_SET_2(CM_RGAM_RAMB_START_CNTL_R, 0, - CM_RGAM_RAMB_EXP_REGION_START_R, params->arr_points[0].custom_float_x, - CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_R, 0); - - REG_SET(CM_RGAM_RAMB_SLOPE_CNTL_B, 0, - CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B, params->arr_points[0].custom_float_slope); - REG_SET(CM_RGAM_RAMB_SLOPE_CNTL_G, 0, - CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_G, params->arr_points[0].custom_float_slope); - REG_SET(CM_RGAM_RAMB_SLOPE_CNTL_R, 0, - CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_R, params->arr_points[0].custom_float_slope); - - REG_SET(CM_RGAM_RAMB_END_CNTL1_B, 0, - CM_RGAM_RAMB_EXP_REGION_END_B, params->arr_points[1].custom_float_x); - REG_SET_2(CM_RGAM_RAMB_END_CNTL2_B, 0, - CM_RGAM_RAMB_EXP_REGION_END_SLOPE_B, params->arr_points[1].custom_float_slope, - CM_RGAM_RAMB_EXP_REGION_END_BASE_B, params->arr_points[1].custom_float_y); - - REG_SET(CM_RGAM_RAMB_END_CNTL1_G, 0, - CM_RGAM_RAMB_EXP_REGION_END_G, params->arr_points[1].custom_float_x); - REG_SET_2(CM_RGAM_RAMB_END_CNTL2_G, 0, - CM_RGAM_RAMB_EXP_REGION_END_SLOPE_G, params->arr_points[1].custom_float_slope, - CM_RGAM_RAMB_EXP_REGION_END_BASE_G, params->arr_points[1].custom_float_y); - - REG_SET(CM_RGAM_RAMB_END_CNTL1_R, 0, - CM_RGAM_RAMB_EXP_REGION_END_R, params->arr_points[1].custom_float_x); - REG_SET_2(CM_RGAM_RAMB_END_CNTL2_R, 0, - CM_RGAM_RAMB_EXP_REGION_END_SLOPE_R, params->arr_points[1].custom_float_slope, - CM_RGAM_RAMB_EXP_REGION_END_BASE_R, params->arr_points[1].custom_float_y); - - curve = params->arr_curve_points; - REG_SET_4(CM_RGAM_RAMB_REGION_0_1, 0, - CM_RGAM_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_2_3, 0, - CM_RGAM_RAMB_EXP_REGION2_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION3_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_4_5, 0, - CM_RGAM_RAMB_EXP_REGION4_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION5_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_6_7, 0, - CM_RGAM_RAMB_EXP_REGION6_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION7_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_8_9, 0, - CM_RGAM_RAMB_EXP_REGION8_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION9_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_10_11, 0, - CM_RGAM_RAMB_EXP_REGION10_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION11_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_12_13, 0, - CM_RGAM_RAMB_EXP_REGION12_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION13_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_14_15, 0, - CM_RGAM_RAMB_EXP_REGION14_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION15_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_16_17, 0, - CM_RGAM_RAMB_EXP_REGION16_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION16_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION17_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION17_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_18_19, 0, - CM_RGAM_RAMB_EXP_REGION18_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION18_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION19_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION19_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_20_21, 0, - CM_RGAM_RAMB_EXP_REGION20_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION20_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION21_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION21_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_22_23, 0, - CM_RGAM_RAMB_EXP_REGION22_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION22_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION23_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION23_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_24_25, 0, - CM_RGAM_RAMB_EXP_REGION24_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION24_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION25_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION25_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_26_27, 0, - CM_RGAM_RAMB_EXP_REGION26_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION26_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION27_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION27_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_28_29, 0, - CM_RGAM_RAMB_EXP_REGION28_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION28_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION29_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION29_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_30_31, 0, - CM_RGAM_RAMB_EXP_REGION30_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION30_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION31_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION31_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_32_33, 0, - CM_RGAM_RAMB_EXP_REGION32_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION32_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION33_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION33_NUM_SEGMENTS, curve[1].segments_num); - -} - -/*program re gamma RAM A*/ -static void opp_program_regamma_luta_settings( - struct output_pixel_processor *opp, - const struct pwl_params *params) -{ - const struct gamma_curve *curve; - struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); - - REG_SET_2(CM_RGAM_RAMA_START_CNTL_B, 0, - CM_RGAM_RAMA_EXP_REGION_START_B, params->arr_points[0].custom_float_x, - CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_B, 0); - REG_SET_2(CM_RGAM_RAMA_START_CNTL_G, 0, - CM_RGAM_RAMA_EXP_REGION_START_G, params->arr_points[0].custom_float_x, - CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_G, 0); - REG_SET_2(CM_RGAM_RAMA_START_CNTL_R, 0, - CM_RGAM_RAMA_EXP_REGION_START_R, params->arr_points[0].custom_float_x, - CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_R, 0); - - REG_SET(CM_RGAM_RAMA_SLOPE_CNTL_B, 0, - CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B, params->arr_points[0].custom_float_slope); - REG_SET(CM_RGAM_RAMA_SLOPE_CNTL_G, 0, - CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G, params->arr_points[0].custom_float_slope); - REG_SET(CM_RGAM_RAMA_SLOPE_CNTL_R, 0, - CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R, params->arr_points[0].custom_float_slope); - - REG_SET(CM_RGAM_RAMA_END_CNTL1_B, 0, - CM_RGAM_RAMA_EXP_REGION_END_B, params->arr_points[1].custom_float_x); - REG_SET_2(CM_RGAM_RAMA_END_CNTL2_B, 0, - CM_RGAM_RAMA_EXP_REGION_END_SLOPE_B, params->arr_points[1].custom_float_slope, - CM_RGAM_RAMA_EXP_REGION_END_BASE_B, params->arr_points[1].custom_float_y); - - REG_SET(CM_RGAM_RAMA_END_CNTL1_G, 0, - CM_RGAM_RAMA_EXP_REGION_END_G, params->arr_points[1].custom_float_x); - REG_SET_2(CM_RGAM_RAMA_END_CNTL2_G, 0, - CM_RGAM_RAMA_EXP_REGION_END_SLOPE_G, params->arr_points[1].custom_float_slope, - CM_RGAM_RAMA_EXP_REGION_END_BASE_G, params->arr_points[1].custom_float_y); - - REG_SET(CM_RGAM_RAMA_END_CNTL1_R, 0, - CM_RGAM_RAMA_EXP_REGION_END_R, params->arr_points[1].custom_float_x); - REG_SET_2(CM_RGAM_RAMA_END_CNTL2_R, 0, - CM_RGAM_RAMA_EXP_REGION_END_SLOPE_R, params->arr_points[1].custom_float_slope, - CM_RGAM_RAMA_EXP_REGION_END_BASE_R, params->arr_points[1].custom_float_y); - - curve = params->arr_curve_points; - REG_SET_4(CM_RGAM_RAMA_REGION_0_1, 0, - CM_RGAM_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_2_3, 0, - CM_RGAM_RAMA_EXP_REGION2_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION3_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_4_5, 0, - CM_RGAM_RAMA_EXP_REGION4_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION5_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_6_7, 0, - CM_RGAM_RAMA_EXP_REGION6_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION7_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_8_9, 0, - CM_RGAM_RAMA_EXP_REGION8_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION9_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_10_11, 0, - CM_RGAM_RAMA_EXP_REGION10_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION11_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_12_13, 0, - CM_RGAM_RAMA_EXP_REGION12_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION13_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_14_15, 0, - CM_RGAM_RAMA_EXP_REGION14_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION15_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_16_17, 0, - CM_RGAM_RAMA_EXP_REGION16_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION16_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION17_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION17_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_18_19, 0, - CM_RGAM_RAMA_EXP_REGION18_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION18_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION19_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION19_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_20_21, 0, - CM_RGAM_RAMA_EXP_REGION20_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION20_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION21_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION21_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_22_23, 0, - CM_RGAM_RAMA_EXP_REGION22_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION22_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION23_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION23_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_24_25, 0, - CM_RGAM_RAMA_EXP_REGION24_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION24_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION25_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION25_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_26_27, 0, - CM_RGAM_RAMA_EXP_REGION26_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION26_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION27_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION27_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_28_29, 0, - CM_RGAM_RAMA_EXP_REGION28_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION28_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION29_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION29_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_30_31, 0, - CM_RGAM_RAMA_EXP_REGION30_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION30_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION31_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION31_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_32_33, 0, - CM_RGAM_RAMA_EXP_REGION32_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION32_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION33_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION33_NUM_SEGMENTS, curve[1].segments_num); -} - -static void opp_configure_regamma_lut( - struct output_pixel_processor *opp, - bool is_ram_a) -{ - struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); - - REG_UPDATE(CM_RGAM_LUT_WRITE_EN_MASK, - CM_RGAM_LUT_WRITE_EN_MASK, 7); - REG_UPDATE(CM_RGAM_LUT_WRITE_EN_MASK, - CM_RGAM_LUT_WRITE_SEL, is_ram_a == true ? 0:1); - REG_SET(CM_RGAM_LUT_INDEX, 0, CM_RGAM_LUT_INDEX, 0); -} - -static void oppn10_power_on_regamma_lut( - struct output_pixel_processor *opp, - bool power_on) -{ - struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); - REG_SET(CM_MEM_PWR_CTRL, 0, - RGAM_MEM_PWR_FORCE, power_on == true ? 0:1); - -} - - - - -static void opp_program_regamma_lut( - struct output_pixel_processor *opp, - const struct pwl_result_data *rgb, - uint32_t num) -{ - uint32_t i; - struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); - for (i = 0 ; i < num; i++) { - REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].red_reg); - REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].green_reg); - REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].blue_reg); - - REG_SET(CM_RGAM_LUT_DATA, 0, - CM_RGAM_LUT_DATA, rgb[i].delta_red_reg); - REG_SET(CM_RGAM_LUT_DATA, 0, - CM_RGAM_LUT_DATA, rgb[i].delta_green_reg); - REG_SET(CM_RGAM_LUT_DATA, 0, - CM_RGAM_LUT_DATA, rgb[i].delta_blue_reg); - - } - -} - -static bool oppn10_set_regamma_pwl( - struct output_pixel_processor *opp, const struct pwl_params *params) -{ - struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); - - oppn10_power_on_regamma_lut(opp, true); - opp_configure_regamma_lut(opp, oppn10->is_write_to_ram_a_safe); - - if (oppn10->is_write_to_ram_a_safe) - opp_program_regamma_luta_settings(opp, params); - else - opp_program_regamma_lutb_settings(opp, params); - - opp_program_regamma_lut( - opp, params->rgb_resulted, params->hw_points_num); - - return true; -} static void oppn10_set_stereo_polarity( struct output_pixel_processor *opp, @@ -743,10 +318,7 @@ static void dcn10_opp_destroy(struct output_pixel_processor **opp) } static struct opp_funcs dcn10_opp_funcs = { - .opp_power_on_regamma_lut = oppn10_power_on_regamma_lut, .opp_set_dyn_expansion = oppn10_set_dyn_expansion, - .opp_program_regamma_pwl = oppn10_set_regamma_pwl, - .opp_set_regamma_mode = oppn10_set_regamma_mode, .opp_program_fmt = oppn10_program_fmt, .opp_program_bit_depth_reduction = oppn10_program_bit_depth_reduction, .opp_set_stereo_polarity = oppn10_set_stereo_polarity, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h index 900298d6e5b5..790ce6014832 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h @@ -34,7 +34,6 @@ .field_name = reg_name ## __ ## field_name ## post_fix #define OPP_REG_LIST_DCN(id) \ - SRI(OBUF_CONTROL, DSCL, id), \ SRI(FMT_BIT_DEPTH_CONTROL, FMT, id), \ SRI(FMT_CONTROL, FMT, id), \ SRI(FMT_DITHER_RAND_R_SEED, FMT, id), \ @@ -45,73 +44,9 @@ SRI(FMT_MAP420_MEMORY_CONTROL, FMT, id) #define OPP_REG_LIST_DCN10(id) \ - OPP_REG_LIST_DCN(id), \ - SRI(CM_RGAM_LUT_WRITE_EN_MASK, CM, id), \ - SRI(CM_RGAM_CONTROL, CM, id), \ - SRI(CM_RGAM_RAMB_START_CNTL_B, CM, id), \ - SRI(CM_RGAM_RAMB_START_CNTL_G, CM, id), \ - SRI(CM_RGAM_RAMB_START_CNTL_R, CM, id), \ - SRI(CM_RGAM_RAMB_SLOPE_CNTL_B, CM, id), \ - SRI(CM_RGAM_RAMB_SLOPE_CNTL_G, CM, id), \ - SRI(CM_RGAM_RAMB_SLOPE_CNTL_R, CM, id), \ - SRI(CM_RGAM_RAMB_END_CNTL1_B, CM, id), \ - SRI(CM_RGAM_RAMB_END_CNTL2_B, CM, id), \ - SRI(CM_RGAM_RAMB_END_CNTL1_G, CM, id), \ - SRI(CM_RGAM_RAMB_END_CNTL2_G, CM, id), \ - SRI(CM_RGAM_RAMB_END_CNTL1_R, CM, id), \ - SRI(CM_RGAM_RAMB_END_CNTL2_R, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_0_1, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_2_3, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_4_5, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_6_7, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_8_9, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_10_11, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_12_13, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_14_15, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_16_17, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_18_19, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_20_21, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_22_23, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_24_25, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_26_27, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_28_29, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_30_31, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_32_33, CM, id), \ - SRI(CM_RGAM_RAMA_START_CNTL_B, CM, id), \ - SRI(CM_RGAM_RAMA_START_CNTL_G, CM, id), \ - SRI(CM_RGAM_RAMA_START_CNTL_R, CM, id), \ - SRI(CM_RGAM_RAMA_SLOPE_CNTL_B, CM, id), \ - SRI(CM_RGAM_RAMA_SLOPE_CNTL_G, CM, id), \ - SRI(CM_RGAM_RAMA_SLOPE_CNTL_R, CM, id), \ - SRI(CM_RGAM_RAMA_END_CNTL1_B, CM, id), \ - SRI(CM_RGAM_RAMA_END_CNTL2_B, CM, id), \ - SRI(CM_RGAM_RAMA_END_CNTL1_G, CM, id), \ - SRI(CM_RGAM_RAMA_END_CNTL2_G, CM, id), \ - SRI(CM_RGAM_RAMA_END_CNTL1_R, CM, id), \ - SRI(CM_RGAM_RAMA_END_CNTL2_R, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_0_1, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_2_3, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_4_5, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_6_7, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_8_9, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_10_11, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_12_13, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_14_15, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_16_17, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_18_19, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_20_21, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_22_23, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_24_25, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_26_27, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_28_29, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_30_31, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_32_33, CM, id), \ - SRI(CM_RGAM_LUT_INDEX, CM, id), \ - SRI(CM_MEM_PWR_CTRL, CM, id), \ - SRI(CM_RGAM_LUT_DATA, CM, id) + OPP_REG_LIST_DCN(id) #define OPP_MASK_SH_LIST_DCN(mask_sh) \ - OPP_SF(DSCL0_OBUF_CONTROL, OBUF_BYPASS, mask_sh), \ OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN, mask_sh), \ OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_DEPTH, mask_sh), \ OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_MODE, mask_sh), \ @@ -136,186 +71,7 @@ OPP_SF(FMT0_FMT_MAP420_MEMORY_CONTROL, FMT_MAP420MEM_PWR_FORCE, mask_sh) #define OPP_MASK_SH_LIST_DCN10(mask_sh) \ - OPP_MASK_SH_LIST_DCN(mask_sh), \ - OPP_SF(DSCL0_OBUF_CONTROL, OBUF_H_2X_UPSCALE_EN, mask_sh), \ - OPP_SF(CM0_CM_RGAM_CONTROL, CM_RGAM_LUT_MODE, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_START_CNTL_B, CM_RGAM_RAMB_EXP_REGION_START_B, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_START_CNTL_B, CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_START_CNTL_G, CM_RGAM_RAMB_EXP_REGION_START_G, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_START_CNTL_G, CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_G, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_START_CNTL_R, CM_RGAM_RAMB_EXP_REGION_START_R, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_START_CNTL_R, CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_R, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_SLOPE_CNTL_B, CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_SLOPE_CNTL_G, CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_G, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_SLOPE_CNTL_R, CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_R, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_END_CNTL1_B, CM_RGAM_RAMB_EXP_REGION_END_B, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_END_CNTL2_B, CM_RGAM_RAMB_EXP_REGION_END_SLOPE_B, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_END_CNTL2_B, CM_RGAM_RAMB_EXP_REGION_END_BASE_B, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_END_CNTL1_G, CM_RGAM_RAMB_EXP_REGION_END_G, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_END_CNTL2_G, CM_RGAM_RAMB_EXP_REGION_END_SLOPE_G, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_END_CNTL2_G, CM_RGAM_RAMB_EXP_REGION_END_BASE_G, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_END_CNTL1_R, CM_RGAM_RAMB_EXP_REGION_END_R, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_END_CNTL2_R, CM_RGAM_RAMB_EXP_REGION_END_SLOPE_R, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_END_CNTL2_R, CM_RGAM_RAMB_EXP_REGION_END_BASE_R, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_0_1, CM_RGAM_RAMB_EXP_REGION0_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_0_1, CM_RGAM_RAMB_EXP_REGION0_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_0_1, CM_RGAM_RAMB_EXP_REGION1_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_0_1, CM_RGAM_RAMB_EXP_REGION1_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_2_3, CM_RGAM_RAMB_EXP_REGION2_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_2_3, CM_RGAM_RAMB_EXP_REGION2_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_2_3, CM_RGAM_RAMB_EXP_REGION3_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_2_3, CM_RGAM_RAMB_EXP_REGION3_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_4_5, CM_RGAM_RAMB_EXP_REGION4_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_4_5, CM_RGAM_RAMB_EXP_REGION4_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_4_5, CM_RGAM_RAMB_EXP_REGION5_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_4_5, CM_RGAM_RAMB_EXP_REGION5_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_6_7, CM_RGAM_RAMB_EXP_REGION6_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_6_7, CM_RGAM_RAMB_EXP_REGION6_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_6_7, CM_RGAM_RAMB_EXP_REGION7_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_6_7, CM_RGAM_RAMB_EXP_REGION7_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_8_9, CM_RGAM_RAMB_EXP_REGION8_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_8_9, CM_RGAM_RAMB_EXP_REGION8_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_8_9, CM_RGAM_RAMB_EXP_REGION9_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_8_9, CM_RGAM_RAMB_EXP_REGION9_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_10_11, CM_RGAM_RAMB_EXP_REGION10_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_10_11, CM_RGAM_RAMB_EXP_REGION10_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_10_11, CM_RGAM_RAMB_EXP_REGION11_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_10_11, CM_RGAM_RAMB_EXP_REGION11_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_12_13, CM_RGAM_RAMB_EXP_REGION12_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_12_13, CM_RGAM_RAMB_EXP_REGION12_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_12_13, CM_RGAM_RAMB_EXP_REGION13_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_12_13, CM_RGAM_RAMB_EXP_REGION13_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_14_15, CM_RGAM_RAMB_EXP_REGION14_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_14_15, CM_RGAM_RAMB_EXP_REGION14_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_14_15, CM_RGAM_RAMB_EXP_REGION15_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_14_15, CM_RGAM_RAMB_EXP_REGION15_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_16_17, CM_RGAM_RAMB_EXP_REGION16_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_16_17, CM_RGAM_RAMB_EXP_REGION16_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_16_17, CM_RGAM_RAMB_EXP_REGION17_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_16_17, CM_RGAM_RAMB_EXP_REGION17_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_18_19, CM_RGAM_RAMB_EXP_REGION18_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_18_19, CM_RGAM_RAMB_EXP_REGION18_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_18_19, CM_RGAM_RAMB_EXP_REGION19_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_18_19, CM_RGAM_RAMB_EXP_REGION19_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_20_21, CM_RGAM_RAMB_EXP_REGION20_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_20_21, CM_RGAM_RAMB_EXP_REGION20_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_20_21, CM_RGAM_RAMB_EXP_REGION21_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_20_21, CM_RGAM_RAMB_EXP_REGION21_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_22_23, CM_RGAM_RAMB_EXP_REGION22_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_22_23, CM_RGAM_RAMB_EXP_REGION22_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_22_23, CM_RGAM_RAMB_EXP_REGION23_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_22_23, CM_RGAM_RAMB_EXP_REGION23_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_24_25, CM_RGAM_RAMB_EXP_REGION24_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_24_25, CM_RGAM_RAMB_EXP_REGION24_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_24_25, CM_RGAM_RAMB_EXP_REGION25_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_24_25, CM_RGAM_RAMB_EXP_REGION25_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_26_27, CM_RGAM_RAMB_EXP_REGION26_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_26_27, CM_RGAM_RAMB_EXP_REGION26_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_26_27, CM_RGAM_RAMB_EXP_REGION27_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_26_27, CM_RGAM_RAMB_EXP_REGION27_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_28_29, CM_RGAM_RAMB_EXP_REGION28_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_28_29, CM_RGAM_RAMB_EXP_REGION28_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_28_29, CM_RGAM_RAMB_EXP_REGION29_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_28_29, CM_RGAM_RAMB_EXP_REGION29_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_30_31, CM_RGAM_RAMB_EXP_REGION30_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_30_31, CM_RGAM_RAMB_EXP_REGION30_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_30_31, CM_RGAM_RAMB_EXP_REGION31_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_30_31, CM_RGAM_RAMB_EXP_REGION31_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_32_33, CM_RGAM_RAMB_EXP_REGION32_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_32_33, CM_RGAM_RAMB_EXP_REGION32_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_32_33, CM_RGAM_RAMB_EXP_REGION33_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_32_33, CM_RGAM_RAMB_EXP_REGION33_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_START_CNTL_B, CM_RGAM_RAMA_EXP_REGION_START_B, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_START_CNTL_B, CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_B, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_START_CNTL_G, CM_RGAM_RAMA_EXP_REGION_START_G, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_START_CNTL_G, CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_G, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_START_CNTL_R, CM_RGAM_RAMA_EXP_REGION_START_R, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_START_CNTL_R, CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_R, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_SLOPE_CNTL_B, CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_SLOPE_CNTL_G, CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_SLOPE_CNTL_R, CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_END_CNTL1_B, CM_RGAM_RAMA_EXP_REGION_END_B, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_END_CNTL2_B, CM_RGAM_RAMA_EXP_REGION_END_SLOPE_B, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_END_CNTL2_B, CM_RGAM_RAMA_EXP_REGION_END_BASE_B, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_END_CNTL1_G, CM_RGAM_RAMA_EXP_REGION_END_G, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_END_CNTL2_G, CM_RGAM_RAMA_EXP_REGION_END_SLOPE_G, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_END_CNTL2_G, CM_RGAM_RAMA_EXP_REGION_END_BASE_G, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_END_CNTL1_R, CM_RGAM_RAMA_EXP_REGION_END_R, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_END_CNTL2_R, CM_RGAM_RAMA_EXP_REGION_END_SLOPE_R, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_END_CNTL2_R, CM_RGAM_RAMA_EXP_REGION_END_BASE_R, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_0_1, CM_RGAM_RAMA_EXP_REGION0_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_0_1, CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_0_1, CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_0_1, CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_2_3, CM_RGAM_RAMA_EXP_REGION2_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_2_3, CM_RGAM_RAMA_EXP_REGION2_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_2_3, CM_RGAM_RAMA_EXP_REGION3_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_2_3, CM_RGAM_RAMA_EXP_REGION3_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_4_5, CM_RGAM_RAMA_EXP_REGION4_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_4_5, CM_RGAM_RAMA_EXP_REGION4_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_4_5, CM_RGAM_RAMA_EXP_REGION5_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_4_5, CM_RGAM_RAMA_EXP_REGION5_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_6_7, CM_RGAM_RAMA_EXP_REGION6_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_6_7, CM_RGAM_RAMA_EXP_REGION6_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_6_7, CM_RGAM_RAMA_EXP_REGION7_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_6_7, CM_RGAM_RAMA_EXP_REGION7_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_8_9, CM_RGAM_RAMA_EXP_REGION8_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_8_9, CM_RGAM_RAMA_EXP_REGION8_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_8_9, CM_RGAM_RAMA_EXP_REGION9_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_8_9, CM_RGAM_RAMA_EXP_REGION9_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_10_11, CM_RGAM_RAMA_EXP_REGION10_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_10_11, CM_RGAM_RAMA_EXP_REGION10_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_10_11, CM_RGAM_RAMA_EXP_REGION11_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_10_11, CM_RGAM_RAMA_EXP_REGION11_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_12_13, CM_RGAM_RAMA_EXP_REGION12_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_12_13, CM_RGAM_RAMA_EXP_REGION12_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_12_13, CM_RGAM_RAMA_EXP_REGION13_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_12_13, CM_RGAM_RAMA_EXP_REGION13_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_14_15, CM_RGAM_RAMA_EXP_REGION14_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_14_15, CM_RGAM_RAMA_EXP_REGION14_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_14_15, CM_RGAM_RAMA_EXP_REGION15_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_14_15, CM_RGAM_RAMA_EXP_REGION15_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_16_17, CM_RGAM_RAMA_EXP_REGION16_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_16_17, CM_RGAM_RAMA_EXP_REGION16_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_16_17, CM_RGAM_RAMA_EXP_REGION17_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_16_17, CM_RGAM_RAMA_EXP_REGION17_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_18_19, CM_RGAM_RAMA_EXP_REGION18_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_18_19, CM_RGAM_RAMA_EXP_REGION18_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_18_19, CM_RGAM_RAMA_EXP_REGION19_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_18_19, CM_RGAM_RAMA_EXP_REGION19_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_20_21, CM_RGAM_RAMA_EXP_REGION20_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_20_21, CM_RGAM_RAMA_EXP_REGION20_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_20_21, CM_RGAM_RAMA_EXP_REGION21_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_20_21, CM_RGAM_RAMA_EXP_REGION21_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_22_23, CM_RGAM_RAMA_EXP_REGION22_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_22_23, CM_RGAM_RAMA_EXP_REGION22_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_22_23, CM_RGAM_RAMA_EXP_REGION23_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_22_23, CM_RGAM_RAMA_EXP_REGION23_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_24_25, CM_RGAM_RAMA_EXP_REGION24_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_24_25, CM_RGAM_RAMA_EXP_REGION24_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_24_25, CM_RGAM_RAMA_EXP_REGION25_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_24_25, CM_RGAM_RAMA_EXP_REGION25_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_26_27, CM_RGAM_RAMA_EXP_REGION26_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_26_27, CM_RGAM_RAMA_EXP_REGION26_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_26_27, CM_RGAM_RAMA_EXP_REGION27_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_26_27, CM_RGAM_RAMA_EXP_REGION27_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_28_29, CM_RGAM_RAMA_EXP_REGION28_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_28_29, CM_RGAM_RAMA_EXP_REGION28_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_28_29, CM_RGAM_RAMA_EXP_REGION29_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_28_29, CM_RGAM_RAMA_EXP_REGION29_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_30_31, CM_RGAM_RAMA_EXP_REGION30_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_30_31, CM_RGAM_RAMA_EXP_REGION30_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_30_31, CM_RGAM_RAMA_EXP_REGION31_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_30_31, CM_RGAM_RAMA_EXP_REGION31_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_32_33, CM_RGAM_RAMA_EXP_REGION32_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_32_33, CM_RGAM_RAMA_EXP_REGION32_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_32_33, CM_RGAM_RAMA_EXP_REGION33_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_32_33, CM_RGAM_RAMA_EXP_REGION33_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_LUT_WRITE_EN_MASK, CM_RGAM_LUT_WRITE_EN_MASK, mask_sh), \ - OPP_SF(CM0_CM_RGAM_LUT_WRITE_EN_MASK, CM_RGAM_LUT_WRITE_SEL, mask_sh), \ - OPP_SF(CM0_CM_RGAM_LUT_INDEX, CM_RGAM_LUT_INDEX, mask_sh), \ - OPP_SF(CM0_CM_MEM_PWR_CTRL, RGAM_MEM_PWR_FORCE, mask_sh), \ - OPP_SF(CM0_CM_RGAM_LUT_DATA, CM_RGAM_LUT_DATA, mask_sh) + OPP_MASK_SH_LIST_DCN(mask_sh) #define OPP_DCN10_REG_FIELD_LIST(type) \ type DPG_EN; \ @@ -352,9 +108,6 @@ type CM_COMB_C32; \ type CM_COMB_C33; \ type CM_COMB_C34; \ - type CM_RGAM_LUT_MODE; \ - type OBUF_BYPASS; \ - type OBUF_H_2X_UPSCALE_EN; \ type FMT_TRUNCATE_EN; \ type FMT_TRUNCATE_DEPTH; \ type FMT_TRUNCATE_MODE; \ @@ -376,183 +129,6 @@ type FMT_DYNAMIC_EXP_EN; \ type FMT_DYNAMIC_EXP_MODE; \ type FMT_MAP420MEM_PWR_FORCE; \ - type CM_RGAM_RAMB_EXP_REGION_START_B; \ - type CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B; \ - type CM_RGAM_RAMB_EXP_REGION_START_G; \ - type CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_G; \ - type CM_RGAM_RAMB_EXP_REGION_START_R; \ - type CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_R; \ - type CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B; \ - type CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_G; \ - type CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_R; \ - type CM_RGAM_RAMB_EXP_REGION_END_B; \ - type CM_RGAM_RAMB_EXP_REGION_END_SLOPE_B; \ - type CM_RGAM_RAMB_EXP_REGION_END_BASE_B; \ - type CM_RGAM_RAMB_EXP_REGION_END_G; \ - type CM_RGAM_RAMB_EXP_REGION_END_SLOPE_G; \ - type CM_RGAM_RAMB_EXP_REGION_END_BASE_G; \ - type CM_RGAM_RAMB_EXP_REGION_END_R; \ - type CM_RGAM_RAMB_EXP_REGION_END_SLOPE_R; \ - type CM_RGAM_RAMB_EXP_REGION_END_BASE_R; \ - type CM_RGAM_RAMB_EXP_REGION0_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION0_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION1_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION1_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION2_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION2_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION3_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION3_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION4_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION4_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION5_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION5_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION6_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION6_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION7_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION7_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION8_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION8_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION9_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION9_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION10_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION10_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION11_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION11_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION12_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION12_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION13_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION13_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION14_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION14_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION15_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION15_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION16_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION16_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION17_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION17_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION18_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION18_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION19_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION19_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION20_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION20_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION21_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION21_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION22_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION22_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION23_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION23_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION24_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION24_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION25_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION25_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION26_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION26_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION27_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION27_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION28_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION28_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION29_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION29_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION30_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION30_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION31_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION31_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION32_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION32_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION33_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION33_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION_START_B; \ - type CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_B; \ - type CM_RGAM_RAMA_EXP_REGION_START_G; \ - type CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_G; \ - type CM_RGAM_RAMA_EXP_REGION_START_R; \ - type CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_R; \ - type CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B; \ - type CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G; \ - type CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R; \ - type CM_RGAM_RAMA_EXP_REGION_END_B; \ - type CM_RGAM_RAMA_EXP_REGION_END_SLOPE_B; \ - type CM_RGAM_RAMA_EXP_REGION_END_BASE_B; \ - type CM_RGAM_RAMA_EXP_REGION_END_G; \ - type CM_RGAM_RAMA_EXP_REGION_END_SLOPE_G; \ - type CM_RGAM_RAMA_EXP_REGION_END_BASE_G; \ - type CM_RGAM_RAMA_EXP_REGION_END_R; \ - type CM_RGAM_RAMA_EXP_REGION_END_SLOPE_R; \ - type CM_RGAM_RAMA_EXP_REGION_END_BASE_R; \ - type CM_RGAM_RAMA_EXP_REGION0_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION2_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION2_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION3_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION3_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION4_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION4_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION5_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION5_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION6_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION6_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION7_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION7_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION8_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION8_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION9_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION9_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION10_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION10_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION11_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION11_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION12_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION12_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION13_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION13_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION14_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION14_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION15_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION15_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION16_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION16_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION17_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION17_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION18_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION18_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION19_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION19_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION20_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION20_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION21_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION21_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION22_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION22_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION23_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION23_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION24_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION24_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION25_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION25_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION26_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION26_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION27_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION27_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION28_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION28_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION29_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION29_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION30_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION30_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION31_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION31_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION32_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION32_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION33_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION33_NUM_SEGMENTS; \ - type CM_RGAM_LUT_WRITE_EN_MASK; \ - type CM_RGAM_LUT_WRITE_SEL; \ - type CM_RGAM_LUT_INDEX; \ - type RGAM_MEM_PWR_FORCE; \ - type CM_RGAM_LUT_DATA; \ type FMT_STEREOSYNC_OVERRIDE struct dcn10_opp_shift { @@ -580,9 +156,6 @@ struct dcn10_opp_registers { uint32_t CM_COMB_C23_C24; uint32_t CM_COMB_C31_C32; uint32_t CM_COMB_C33_C34; - uint32_t CM_RGAM_LUT_WRITE_EN_MASK; - uint32_t CM_RGAM_CONTROL; - uint32_t OBUF_CONTROL; uint32_t FMT_BIT_DEPTH_CONTROL; uint32_t FMT_CONTROL; uint32_t FMT_DITHER_RAND_R_SEED; @@ -591,67 +164,6 @@ struct dcn10_opp_registers { uint32_t FMT_CLAMP_CNTL; uint32_t FMT_DYNAMIC_EXP_CNTL; uint32_t FMT_MAP420_MEMORY_CONTROL; - uint32_t CM_RGAM_RAMB_START_CNTL_B; - uint32_t CM_RGAM_RAMB_START_CNTL_G; - uint32_t CM_RGAM_RAMB_START_CNTL_R; - uint32_t CM_RGAM_RAMB_SLOPE_CNTL_B; - uint32_t CM_RGAM_RAMB_SLOPE_CNTL_G; - uint32_t CM_RGAM_RAMB_SLOPE_CNTL_R; - uint32_t CM_RGAM_RAMB_END_CNTL1_B; - uint32_t CM_RGAM_RAMB_END_CNTL2_B; - uint32_t CM_RGAM_RAMB_END_CNTL1_G; - uint32_t CM_RGAM_RAMB_END_CNTL2_G; - uint32_t CM_RGAM_RAMB_END_CNTL1_R; - uint32_t CM_RGAM_RAMB_END_CNTL2_R; - uint32_t CM_RGAM_RAMB_REGION_0_1; - uint32_t CM_RGAM_RAMB_REGION_2_3; - uint32_t CM_RGAM_RAMB_REGION_4_5; - uint32_t CM_RGAM_RAMB_REGION_6_7; - uint32_t CM_RGAM_RAMB_REGION_8_9; - uint32_t CM_RGAM_RAMB_REGION_10_11; - uint32_t CM_RGAM_RAMB_REGION_12_13; - uint32_t CM_RGAM_RAMB_REGION_14_15; - uint32_t CM_RGAM_RAMB_REGION_16_17; - uint32_t CM_RGAM_RAMB_REGION_18_19; - uint32_t CM_RGAM_RAMB_REGION_20_21; - uint32_t CM_RGAM_RAMB_REGION_22_23; - uint32_t CM_RGAM_RAMB_REGION_24_25; - uint32_t CM_RGAM_RAMB_REGION_26_27; - uint32_t CM_RGAM_RAMB_REGION_28_29; - uint32_t CM_RGAM_RAMB_REGION_30_31; - uint32_t CM_RGAM_RAMB_REGION_32_33; - uint32_t CM_RGAM_RAMA_START_CNTL_B; - uint32_t CM_RGAM_RAMA_START_CNTL_G; - uint32_t CM_RGAM_RAMA_START_CNTL_R; - uint32_t CM_RGAM_RAMA_SLOPE_CNTL_B; - uint32_t CM_RGAM_RAMA_SLOPE_CNTL_G; - uint32_t CM_RGAM_RAMA_SLOPE_CNTL_R; - uint32_t CM_RGAM_RAMA_END_CNTL1_B; - uint32_t CM_RGAM_RAMA_END_CNTL2_B; - uint32_t CM_RGAM_RAMA_END_CNTL1_G; - uint32_t CM_RGAM_RAMA_END_CNTL2_G; - uint32_t CM_RGAM_RAMA_END_CNTL1_R; - uint32_t CM_RGAM_RAMA_END_CNTL2_R; - uint32_t CM_RGAM_RAMA_REGION_0_1; - uint32_t CM_RGAM_RAMA_REGION_2_3; - uint32_t CM_RGAM_RAMA_REGION_4_5; - uint32_t CM_RGAM_RAMA_REGION_6_7; - uint32_t CM_RGAM_RAMA_REGION_8_9; - uint32_t CM_RGAM_RAMA_REGION_10_11; - uint32_t CM_RGAM_RAMA_REGION_12_13; - uint32_t CM_RGAM_RAMA_REGION_14_15; - uint32_t CM_RGAM_RAMA_REGION_16_17; - uint32_t CM_RGAM_RAMA_REGION_18_19; - uint32_t CM_RGAM_RAMA_REGION_20_21; - uint32_t CM_RGAM_RAMA_REGION_22_23; - uint32_t CM_RGAM_RAMA_REGION_24_25; - uint32_t CM_RGAM_RAMA_REGION_26_27; - uint32_t CM_RGAM_RAMA_REGION_28_29; - uint32_t CM_RGAM_RAMA_REGION_30_31; - uint32_t CM_RGAM_RAMA_REGION_32_33; - uint32_t CM_RGAM_LUT_INDEX; - uint32_t CM_MEM_PWR_CTRL; - uint32_t CM_RGAM_LUT_DATA; }; struct dcn10_opp { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h index 137b4c8dc9d5..589bddad7e66 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h @@ -113,4 +113,11 @@ struct out_csc_color_matrix { uint16_t regval[12]; }; +enum opp_regamma { + OPP_REGAMMA_BYPASS = 0, + OPP_REGAMMA_SRGB, + OPP_REGAMMA_3_6, + OPP_REGAMMA_USER +}; + #endif /* __DAL_HW_SHARED_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h index ef36ffdf2a68..a43a09b3f414 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h @@ -196,13 +196,6 @@ struct pwl_float_data { struct fixed31_32 b; }; -enum opp_regamma { - OPP_REGAMMA_BYPASS = 0, - OPP_REGAMMA_SRGB, - OPP_REGAMMA_3_6, - OPP_REGAMMA_USER, -}; - struct output_pixel_processor { struct dc_context *ctx; uint32_t inst; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h index 132c5db07456..f3d66752ed90 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h @@ -38,6 +38,7 @@ struct transform { const struct transform_funcs *funcs; struct dc_context *ctx; int inst; + struct pwl_params regamma_params; }; /* Colorimetry */ @@ -190,6 +191,34 @@ struct transform_funcs { void (*opp_set_csc_adjustment)( struct transform *xfm, const struct out_csc_color_matrix *tbl_entry); + + void (*opp_power_on_regamma_lut)( + struct transform *xfm, + bool power_on); + + void (*opp_program_regamma_lut)( + struct transform *xfm, + const struct pwl_result_data *rgb, + uint32_t num); + + void (*opp_configure_regamma_lut)( + struct transform *xfm, + bool is_ram_a); + + void (*opp_program_regamma_lutb_settings)( + struct transform *xfm, + const struct pwl_params *params); + + void (*opp_program_regamma_luta_settings)( + struct transform *xfm, + const struct pwl_params *params); + + bool (*opp_program_regamma_pwl)( + struct transform *xfm, const struct pwl_params *params); + + void (*opp_set_regamma_mode)( + struct transform *xfm_base, + enum opp_regamma mode); }; extern const uint16_t filter_2tap_16p[18]; -- cgit From 08b1688620426ad3e09fc7a98aabc28dda30cde6 Mon Sep 17 00:00:00 2001 From: Zeyu Fan Date: Sun, 23 Jul 2017 18:30:15 -0400 Subject: drm/amd/display: Move DCHUBBUB block from MemInput to HW sequencer. Signed-off-by: Zeyu Fan Reviewed-by: Zeyu Fan Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 6 +- drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h | 122 ++++++++- drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c | 54 +--- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 1 + .../amd/display/dc/dce120/dce120_hw_sequencer.c | 64 +++++ .../drm/amd/display/dc/dce120/dce120_resource.c | 2 +- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 304 ++++++++++++++++++++- .../gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c | 303 -------------------- .../gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h | 76 +----- drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h | 7 +- drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 4 + 11 files changed, 492 insertions(+), 451 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 9ef671735125..e89a2e5c8902 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -2042,10 +2042,10 @@ bool dc_init_dchub(struct dc *dc, struct dchub_init_data *dh_data) return false; } - if (mi->funcs->mem_input_update_dchub) - mi->funcs->mem_input_update_dchub(mi, dh_data); + if (core_dc->hwss.update_dchub) + core_dc->hwss.update_dchub(core_dc->hwseq, dh_data); else - ASSERT(mi->funcs->mem_input_update_dchub); + ASSERT(core_dc->hwss.update_dchub); return true; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index 7feb1ca9b8c0..d62fc526783f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -116,6 +116,15 @@ .BLND_V_UPDATE_LOCK[3] = mmBLNDV_V_UPDATE_LOCK, \ .BLND_CONTROL[3] = mmBLNDV_CONTROL +#define HWSEQ_DCE120_REG_LIST() \ + HWSEQ_DCE10_REG_LIST(), \ + HWSEQ_PIXEL_RATE_REG_LIST(CRTC), \ + HWSEQ_PHYPLL_REG_LIST(CRTC), \ + SR(DCHUB_FB_LOCATION),\ + SR(DCHUB_AGP_BASE),\ + SR(DCHUB_AGP_BOT),\ + SR(DCHUB_AGP_TOP) + #define HWSEQ_DCE112_REG_LIST() \ HWSEQ_DCE10_REG_LIST(), \ HWSEQ_PIXEL_RATE_REG_LIST(CRTC), \ @@ -146,8 +155,31 @@ SRII(OPP_PIPE_CONTROL, OPP_PIPE, 2), \ SRII(OPP_PIPE_CONTROL, OPP_PIPE, 3), \ SR(REFCLK_CNTL), \ + SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A),\ + SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A),\ + SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A),\ + SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A),\ + SR(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A),\ + SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B),\ + SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B),\ + SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B),\ + SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B),\ + SR(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B),\ + SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C),\ + SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C),\ + SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C),\ + SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C),\ + SR(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C),\ + SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D),\ + SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D),\ + SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D),\ + SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D),\ + SR(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D),\ + SR(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL),\ + SR(DCHUBBUB_ARB_DRAM_STATE_CNTL),\ + SR(DCHUBBUB_ARB_SAT_LEVEL),\ + SR(DCHUBBUB_ARB_DF_REQ_OUTSTAND),\ SR(DCHUBBUB_GLOBAL_TIMER_CNTL), \ - SR(DCHUBBUB_ARB_DRAM_STATE_CNTL), \ SR(DCHUBBUB_TEST_DEBUG_INDEX), \ SR(DCHUBBUB_TEST_DEBUG_DATA), \ SR(DC_IP_REQUEST_CNTL), \ @@ -180,7 +212,13 @@ #if defined(CONFIG_DRM_AMD_DC_DCN1_0) #define HWSEQ_DCN1_REG_LIST()\ - HWSEQ_DCN_REG_LIST() + HWSEQ_DCN_REG_LIST(), \ + SR(DCHUBBUB_SDPIF_FB_TOP),\ + SR(DCHUBBUB_SDPIF_FB_BASE),\ + SR(DCHUBBUB_SDPIF_FB_OFFSET),\ + SR(DCHUBBUB_SDPIF_AGP_BASE),\ + SR(DCHUBBUB_SDPIF_AGP_BOT),\ + SR(DCHUBBUB_SDPIF_AGP_TOP) #endif @@ -194,6 +232,11 @@ struct dce_hwseq_registers { uint32_t CRTC_H_BLANK_START_END[6]; uint32_t PIXEL_RATE_CNTL[6]; uint32_t PHYPLL_PIXEL_RATE_CNTL[6]; + /*DCHUB*/ + uint32_t DCHUB_FB_LOCATION; + uint32_t DCHUB_AGP_BASE; + uint32_t DCHUB_AGP_BOT; + uint32_t DCHUB_AGP_TOP; #if defined(CONFIG_DRM_AMD_DC_DCN1_0) uint32_t OTG_GLOBAL_SYNC_STATUS[4]; @@ -202,10 +245,39 @@ struct dce_hwseq_registers { uint32_t DPP_CONTROL[4]; uint32_t OPP_PIPE_CONTROL[4]; uint32_t REFCLK_CNTL; + uint32_t DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A; + uint32_t DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A; + uint32_t DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A; + uint32_t DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A; + uint32_t DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A; + uint32_t DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B; + uint32_t DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B; + uint32_t DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B; + uint32_t DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B; + uint32_t DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B; + uint32_t DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C; + uint32_t DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C; + uint32_t DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C; + uint32_t DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C; + uint32_t DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C; + uint32_t DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D; + uint32_t DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D; + uint32_t DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D; + uint32_t DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D; + uint32_t DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D; + uint32_t DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL; + uint32_t DCHUBBUB_ARB_SAT_LEVEL; + uint32_t DCHUBBUB_ARB_DF_REQ_OUTSTAND; uint32_t DCHUBBUB_GLOBAL_TIMER_CNTL; uint32_t DCHUBBUB_ARB_DRAM_STATE_CNTL; uint32_t DCHUBBUB_TEST_DEBUG_INDEX; uint32_t DCHUBBUB_TEST_DEBUG_DATA; + uint32_t DCHUBBUB_SDPIF_FB_TOP; + uint32_t DCHUBBUB_SDPIF_FB_BASE; + uint32_t DCHUBBUB_SDPIF_FB_OFFSET; + uint32_t DCHUBBUB_SDPIF_AGP_BASE; + uint32_t DCHUBBUB_SDPIF_AGP_BOT; + uint32_t DCHUBBUB_SDPIF_AGP_TOP; uint32_t DC_IP_REQUEST_CNTL; uint32_t DOMAIN0_PG_CONFIG; uint32_t DOMAIN1_PG_CONFIG; @@ -300,11 +372,19 @@ struct dce_hwseq_registers { HWSEQ_DCE10_MASK_SH_LIST(mask_sh),\ HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, CRTC0_) +#define HWSEQ_GFX9_DCHUB_MASK_SH_LIST(mask_sh)\ + SF(DCHUB_FB_LOCATION, FB_TOP, mask_sh),\ + SF(DCHUB_FB_LOCATION, FB_BASE, mask_sh),\ + SF(DCHUB_AGP_BASE, AGP_BASE, mask_sh),\ + SF(DCHUB_AGP_BOT, AGP_BOT, mask_sh),\ + SF(DCHUB_AGP_TOP, AGP_TOP, mask_sh) + #define HWSEQ_DCE12_MASK_SH_LIST(mask_sh)\ HWSEQ_DCEF_MASK_SH_LIST(mask_sh, DCFE0_DCFE_),\ HWSEQ_BLND_MASK_SH_LIST(mask_sh, BLND0_BLND_),\ HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_),\ - HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, CRTC0_) + HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, CRTC0_),\ + HWSEQ_GFX9_DCHUB_MASK_SH_LIST(mask_sh) #if defined(CONFIG_DRM_AMD_DC_DCN1_0) #define HWSEQ_DCN_MASK_SH_LIST(mask_sh)\ @@ -342,6 +422,12 @@ struct dce_hwseq_registers { HWS_SF(, DOMAIN5_PG_STATUS, DOMAIN5_PGFSM_PWR_STATUS, mask_sh), \ HWS_SF(, DOMAIN6_PG_STATUS, DOMAIN6_PGFSM_PWR_STATUS, mask_sh), \ HWS_SF(, DOMAIN7_PG_STATUS, DOMAIN7_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, mask_sh), \ + HWS_SF(, DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE, mask_sh), \ + HWS_SF(, DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE, mask_sh), \ + HWS_SF(, DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, mask_sh), \ + HWS_SF(, DCHUBBUB_ARB_SAT_LEVEL, DCHUBBUB_ARB_SAT_LEVEL, mask_sh), \ + HWS_SF(, DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MIN_REQ_OUTSTAND, mask_sh), \ HWS_SF(, DCFCLK_CNTL, DCFCLK_GATE_DIS, mask_sh) #endif @@ -349,6 +435,12 @@ struct dce_hwseq_registers { #define HWSEQ_DCN1_MASK_SH_LIST(mask_sh)\ HWSEQ_DCN_MASK_SH_LIST(mask_sh), \ HWS_SF1(OTG0_, PHYPLL_PIXEL_RATE_CNTL, PIXEL_RATE_PLL_SOURCE, mask_sh), \ + HWS_SF(, DCHUBBUB_SDPIF_FB_TOP, SDPIF_FB_TOP, mask_sh), \ + HWS_SF(, DCHUBBUB_SDPIF_FB_BASE, SDPIF_FB_BASE, mask_sh), \ + HWS_SF(, DCHUBBUB_SDPIF_FB_OFFSET, SDPIF_FB_OFFSET, mask_sh), \ + HWS_SF(, DCHUBBUB_SDPIF_AGP_BASE, SDPIF_AGP_BASE, mask_sh), \ + HWS_SF(, DCHUBBUB_SDPIF_AGP_BOT, SDPIF_AGP_BOT, mask_sh), \ + HWS_SF(, DCHUBBUB_SDPIF_AGP_TOP, SDPIF_AGP_TOP, mask_sh), \ HWS_SF(DPP_TOP0_, DPP_CONTROL, DPPCLK_RATE_CONTROL, mask_sh) #endif @@ -370,7 +462,6 @@ struct dce_hwseq_registers { type PHYPLL_PIXEL_RATE_SOURCE; \ type PIXEL_RATE_PLL_SOURCE; \ -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) #define HWSEQ_DCN_REG_FIELD_LIST(type) \ type VUPDATE_NO_LOCK_EVENT_CLEAR; \ type VUPDATE_NO_LOCK_EVENT_OCCURRED; \ @@ -378,7 +469,25 @@ struct dce_hwseq_registers { type HUBP_CLOCK_ENABLE; \ type DPP_CLOCK_ENABLE; \ type DPPCLK_RATE_CONTROL; \ + type SDPIF_FB_TOP;\ + type SDPIF_FB_BASE;\ + type SDPIF_FB_OFFSET;\ + type SDPIF_AGP_BASE;\ + type SDPIF_AGP_BOT;\ + type SDPIF_AGP_TOP;\ + type FB_TOP;\ + type FB_BASE;\ + type FB_OFFSET;\ + type AGP_BASE;\ + type AGP_BOT;\ + type AGP_TOP;\ type DCHUBBUB_GLOBAL_TIMER_ENABLE; \ + type DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST;\ + type DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE;\ + type DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE;\ + type DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE;\ + type DCHUBBUB_ARB_SAT_LEVEL;\ + type DCHUBBUB_ARB_MIN_REQ_OUTSTAND;\ type OPP_PIPE_CLOCK_EN;\ type IP_REQUEST_EN; \ type DOMAIN0_POWER_FORCEON; \ @@ -408,20 +517,15 @@ struct dce_hwseq_registers { type DCFCLK_GATE_DIS; \ type DCHUBBUB_GLOBAL_TIMER_REFDIV; \ type DENTIST_DPPCLK_WDIVIDER; -#endif struct dce_hwseq_shift { HWSEQ_REG_FIELD_LIST(uint8_t) -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) HWSEQ_DCN_REG_FIELD_LIST(uint8_t) -#endif }; struct dce_hwseq_mask { HWSEQ_REG_FIELD_LIST(uint32_t) -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) HWSEQ_DCN_REG_FIELD_LIST(uint32_t) -#endif }; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c index 157f4e1680e3..627669749740 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c @@ -656,57 +656,6 @@ static bool dce_mi_program_surface_flip_and_addr( return true; } -static void dce_mi_update_dchub(struct mem_input *mi, - struct dchub_init_data *dh_data) -{ - struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi); - /* TODO: port code from dal2 */ - switch (dh_data->fb_mode) { - case FRAME_BUFFER_MODE_ZFB_ONLY: - /*For ZFB case need to put DCHUB FB BASE and TOP upside down to indicate ZFB mode*/ - REG_UPDATE_2(DCHUB_FB_LOCATION, - FB_TOP, 0, - FB_BASE, 0x0FFFF); - - REG_UPDATE(DCHUB_AGP_BASE, - AGP_BASE, dh_data->zfb_phys_addr_base >> 22); - - REG_UPDATE(DCHUB_AGP_BOT, - AGP_BOT, dh_data->zfb_mc_base_addr >> 22); - - REG_UPDATE(DCHUB_AGP_TOP, - AGP_TOP, (dh_data->zfb_mc_base_addr + dh_data->zfb_size_in_byte - 1) >> 22); - break; - case FRAME_BUFFER_MODE_MIXED_ZFB_AND_LOCAL: - /*Should not touch FB LOCATION (done by VBIOS on AsicInit table)*/ - REG_UPDATE(DCHUB_AGP_BASE, - AGP_BASE, dh_data->zfb_phys_addr_base >> 22); - - REG_UPDATE(DCHUB_AGP_BOT, - AGP_BOT, dh_data->zfb_mc_base_addr >> 22); - - REG_UPDATE(DCHUB_AGP_TOP, - AGP_TOP, (dh_data->zfb_mc_base_addr + dh_data->zfb_size_in_byte - 1) >> 22); - break; - case FRAME_BUFFER_MODE_LOCAL_ONLY: - /*Should not touch FB LOCATION (done by VBIOS on AsicInit table)*/ - REG_UPDATE(DCHUB_AGP_BASE, - AGP_BASE, 0); - - REG_UPDATE(DCHUB_AGP_BOT, - AGP_BOT, 0x03FFFF); - - REG_UPDATE(DCHUB_AGP_TOP, - AGP_TOP, 0); - break; - default: - break; - } - - dh_data->dchub_initialzied = true; - dh_data->dchub_info_valid = false; -} - static struct mem_input_funcs dce_mi_funcs = { .mem_input_program_display_marks = dce_mi_program_display_marks, .allocate_mem_input = dce_mi_allocate_dmif, @@ -716,8 +665,7 @@ static struct mem_input_funcs dce_mi_funcs = { .mem_input_program_pte_vm = dce_mi_program_pte_vm, .mem_input_program_surface_config = dce_mi_program_surface_config, - .mem_input_is_flip_pending = dce_mi_is_flip_pending, - .mem_input_update_dchub = dce_mi_update_dchub + .mem_input_is_flip_pending = dce_mi_is_flip_pending }; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 6ab9712ed808..efba8d7964eb 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -49,6 +49,7 @@ #include "abm.h" #include "audio.h" #include "dce/dce_hwseq.h" +#include "reg_helper.h" /* include DCE11 register header files */ #include "dce/dce_11_0_d.h" diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c index f5ffd8f6ed3b..91301b412aa0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c @@ -28,6 +28,7 @@ #include "core_dc.h" #include "core_types.h" #include "dce120_hw_sequencer.h" +#include "dce/dce_hwseq.h" #include "dce110/dce110_hw_sequencer.h" @@ -37,6 +38,15 @@ #include "vega10/soc15ip.h" #include "reg_helper.h" +#define CTX \ + hws->ctx +#define REG(reg)\ + hws->regs->reg + +#undef FN +#define FN(reg_name, field_name) \ + hws->shifts->field_name, hws->masks->field_name + struct dce120_hw_seq_reg_offsets { uint32_t crtc; }; @@ -184,6 +194,59 @@ static bool dce120_enable_display_power_gating( return false; } +static void dce120_update_dchub( + struct dce_hwseq *hws, + struct dchub_init_data *dh_data) +{ + /* TODO: port code from dal2 */ + switch (dh_data->fb_mode) { + case FRAME_BUFFER_MODE_ZFB_ONLY: + /*For ZFB case need to put DCHUB FB BASE and TOP upside down to indicate ZFB mode*/ + REG_UPDATE_2(DCHUB_FB_LOCATION, + FB_TOP, 0, + FB_BASE, 0x0FFFF); + + REG_UPDATE(DCHUB_AGP_BASE, + AGP_BASE, dh_data->zfb_phys_addr_base >> 22); + + REG_UPDATE(DCHUB_AGP_BOT, + AGP_BOT, dh_data->zfb_mc_base_addr >> 22); + + REG_UPDATE(DCHUB_AGP_TOP, + AGP_TOP, (dh_data->zfb_mc_base_addr + dh_data->zfb_size_in_byte - 1) >> 22); + break; + case FRAME_BUFFER_MODE_MIXED_ZFB_AND_LOCAL: + /*Should not touch FB LOCATION (done by VBIOS on AsicInit table)*/ + REG_UPDATE(DCHUB_AGP_BASE, + AGP_BASE, dh_data->zfb_phys_addr_base >> 22); + + REG_UPDATE(DCHUB_AGP_BOT, + AGP_BOT, dh_data->zfb_mc_base_addr >> 22); + + REG_UPDATE(DCHUB_AGP_TOP, + AGP_TOP, (dh_data->zfb_mc_base_addr + dh_data->zfb_size_in_byte - 1) >> 22); + break; + case FRAME_BUFFER_MODE_LOCAL_ONLY: + /*Should not touch FB LOCATION (done by VBIOS on AsicInit table)*/ + REG_UPDATE(DCHUB_AGP_BASE, + AGP_BASE, 0); + + REG_UPDATE(DCHUB_AGP_BOT, + AGP_BOT, 0x03FFFF); + + REG_UPDATE(DCHUB_AGP_TOP, + AGP_TOP, 0); + break; + default: + break; + } + + dh_data->dchub_initialzied = true; + dh_data->dchub_info_valid = false; +} + + + bool dce120_hw_sequencer_construct(struct core_dc *dc) { /* All registers used by dce11.2 match those in dce11 in offset and @@ -191,6 +254,7 @@ bool dce120_hw_sequencer_construct(struct core_dc *dc) */ dce110_hw_sequencer_construct(dc); dc->hwss.enable_display_power_gating = dce120_enable_display_power_gating; + dc->hwss.update_dchub = dce120_update_dchub; return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index 82481247a812..f829b6e58bcb 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -598,7 +598,7 @@ static struct stream_encoder *dce120_stream_encoder_create( mm ## block ## id ## _ ## reg_name static const struct dce_hwseq_registers hwseq_reg = { - HWSEQ_DCE112_REG_LIST() + HWSEQ_DCE120_REG_LIST() }; static const struct dce_hwseq_shift hwseq_shift = { diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index d61b63df16b8..b7940876c761 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -218,6 +218,306 @@ static void dpp_pg_control( } } +static uint32_t convert_and_clamp( + uint32_t wm_ns, + uint32_t refclk_mhz, + uint32_t clamp_value) +{ + uint32_t ret_val = 0; + ret_val = wm_ns * refclk_mhz; + ret_val /= 1000; + + if (ret_val > clamp_value) + ret_val = clamp_value; + + return ret_val; +} + +static void program_watermarks( + struct dce_hwseq *hws, + struct dcn_watermark_set *watermarks, + unsigned int refclk_mhz) +{ + uint32_t force_en = hws->ctx->dc->debug.disable_stutter ? 1 : 0; + /* + * Need to clamp to max of the register values (i.e. no wrap) + * for dcn1, all wm registers are 21-bit wide + */ + uint32_t prog_wm_value; + + /* Repeat for water mark set A, B, C and D. */ + /* clock state A */ + prog_wm_value = convert_and_clamp(watermarks->a.urgent_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, prog_wm_value); + + dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + "URGENCY_WATERMARK_A calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->a.urgent_ns, prog_wm_value); + + prog_wm_value = convert_and_clamp(watermarks->a.pte_meta_urgent_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + "PTE_META_URGENCY_WATERMARK_A calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->a.pte_meta_urgent_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, + refclk_mhz, 0x1fffff); + + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + "SR_ENTER_EXIT_WATERMARK_A calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->a.cstate_pstate.cstate_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + "SR_EXIT_WATERMARK_A calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->a.cstate_pstate.cstate_exit_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->a.cstate_pstate.pstate_change_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + "DRAM_CLK_CHANGE_WATERMARK_A calculated =%d\n" + "HW register value = 0x%x\n\n", + watermarks->a.cstate_pstate.pstate_change_ns, prog_wm_value); + + + /* clock state B */ + prog_wm_value = convert_and_clamp( + watermarks->b.urgent_ns, refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + "URGENCY_WATERMARK_B calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->b.urgent_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->b.pte_meta_urgent_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + "PTE_META_URGENCY_WATERMARK_B calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->b.pte_meta_urgent_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + "SR_ENTER_WATERMARK_B calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->b.cstate_pstate.cstate_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + "SR_EXIT_WATERMARK_B calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->b.cstate_pstate.cstate_exit_ns, prog_wm_value); + + prog_wm_value = convert_and_clamp( + watermarks->b.cstate_pstate.pstate_change_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + "DRAM_CLK_CHANGE_WATERMARK_B calculated =%d\n\n" + "HW register value = 0x%x\n", + watermarks->b.cstate_pstate.pstate_change_ns, prog_wm_value); + + /* clock state C */ + prog_wm_value = convert_and_clamp( + watermarks->c.urgent_ns, refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + "URGENCY_WATERMARK_C calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->c.urgent_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->c.pte_meta_urgent_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + "PTE_META_URGENCY_WATERMARK_C calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->c.pte_meta_urgent_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + "SR_ENTER_WATERMARK_C calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->c.cstate_pstate.cstate_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + "SR_EXIT_WATERMARK_C calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->c.cstate_pstate.cstate_exit_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->c.cstate_pstate.pstate_change_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + "DRAM_CLK_CHANGE_WATERMARK_C calculated =%d\n\n" + "HW register value = 0x%x\n", + watermarks->c.cstate_pstate.pstate_change_ns, prog_wm_value); + + /* clock state D */ + prog_wm_value = convert_and_clamp( + watermarks->d.urgent_ns, refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + "URGENCY_WATERMARK_D calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->d.urgent_ns, prog_wm_value); + + prog_wm_value = convert_and_clamp( + watermarks->d.pte_meta_urgent_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + "PTE_META_URGENCY_WATERMARK_D calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->d.pte_meta_urgent_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + "SR_ENTER_WATERMARK_D calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->d.cstate_pstate.cstate_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + "SR_EXIT_WATERMARK_D calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->d.cstate_pstate.cstate_exit_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->d.cstate_pstate.pstate_change_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + "DRAM_CLK_CHANGE_WATERMARK_D calculated =%d\n" + "HW register value = 0x%x\n\n", + watermarks->d.cstate_pstate.pstate_change_ns, prog_wm_value); + + REG_UPDATE(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, + DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, 1); + REG_UPDATE(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, + DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, 0); + REG_UPDATE(DCHUBBUB_ARB_SAT_LEVEL, + DCHUBBUB_ARB_SAT_LEVEL, 60 * refclk_mhz); + REG_UPDATE(DCHUBBUB_ARB_DF_REQ_OUTSTAND, + DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 68); + + REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL, + DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE, 0, + DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, force_en); + +#if 0 + REG_UPDATE_2(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, + DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE, 1, + DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, 1); +#endif +} + + +static void dcn10_update_dchub( + struct dce_hwseq *hws, + struct dchub_init_data *dh_data) +{ + /* TODO: port code from dal2 */ + switch (dh_data->fb_mode) { + case FRAME_BUFFER_MODE_ZFB_ONLY: + /*For ZFB case need to put DCHUB FB BASE and TOP upside down to indicate ZFB mode*/ + REG_UPDATE(DCHUBBUB_SDPIF_FB_TOP, + SDPIF_FB_TOP, 0); + + REG_UPDATE(DCHUBBUB_SDPIF_FB_BASE, + SDPIF_FB_BASE, 0x0FFFF); + + REG_UPDATE(DCHUBBUB_SDPIF_AGP_BASE, + SDPIF_AGP_BASE, dh_data->zfb_phys_addr_base >> 22); + + REG_UPDATE(DCHUBBUB_SDPIF_AGP_BOT, + SDPIF_AGP_BOT, dh_data->zfb_mc_base_addr >> 22); + + REG_UPDATE(DCHUBBUB_SDPIF_AGP_TOP, + SDPIF_AGP_TOP, (dh_data->zfb_mc_base_addr + + dh_data->zfb_size_in_byte - 1) >> 22); + break; + case FRAME_BUFFER_MODE_MIXED_ZFB_AND_LOCAL: + /*Should not touch FB LOCATION (done by VBIOS on AsicInit table)*/ + + REG_UPDATE(DCHUBBUB_SDPIF_AGP_BASE, + SDPIF_AGP_BASE, dh_data->zfb_phys_addr_base >> 22); + + REG_UPDATE(DCHUBBUB_SDPIF_AGP_BOT, + SDPIF_AGP_BOT, dh_data->zfb_mc_base_addr >> 22); + + REG_UPDATE(DCHUBBUB_SDPIF_AGP_TOP, + SDPIF_AGP_TOP, (dh_data->zfb_mc_base_addr + + dh_data->zfb_size_in_byte - 1) >> 22); + break; + case FRAME_BUFFER_MODE_LOCAL_ONLY: + /*Should not touch FB LOCATION (done by VBIOS on AsicInit table)*/ + REG_UPDATE(DCHUBBUB_SDPIF_AGP_BASE, + SDPIF_AGP_BASE, 0); + + REG_UPDATE(DCHUBBUB_SDPIF_AGP_BOT, + SDPIF_AGP_BOT, 0X03FFFF); + + REG_UPDATE(DCHUBBUB_SDPIF_AGP_TOP, + SDPIF_AGP_TOP, 0); + break; + default: + break; + } + + dh_data->dchub_initialzied = true; + dh_data->dchub_info_valid = false; +} + static void hubp_pg_control( struct dce_hwseq *hws, unsigned int hubp_inst, @@ -1615,8 +1915,7 @@ static void program_all_pipe_in_tree( * this OTG. this is done only one time. */ /* watermark is for all pipes */ - pipe_ctx->mi->funcs->program_watermarks( - pipe_ctx->mi, &context->bw.dcn.watermarks, ref_clk_mhz); + program_watermarks(dc->hwseq, &context->bw.dcn.watermarks, ref_clk_mhz); if (dc->public.debug.sanity_checks) { /* pstate stuck check after watermark update */ @@ -2078,6 +2377,7 @@ static const struct hw_sequencer_funcs dcn10_funcs = { .apply_ctx_for_surface = dcn10_apply_ctx_for_surface, .set_plane_config = set_plane_config, .update_plane_addr = update_plane_addr, + .update_dchub = dcn10_update_dchub, .update_pending_status = dcn10_update_pending_status, .set_input_transfer_func = dcn10_set_input_transfer_func, .set_output_transfer_func = dcn10_set_output_transfer_func, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index 1f86295d6db6..c56a69b5a4d7 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -574,250 +574,6 @@ static void min10_setup( min10_vready_workaround(mem_input, pipe_dest); } -static uint32_t convert_and_clamp( - uint32_t wm_ns, - uint32_t refclk_mhz, - uint32_t clamp_value) -{ - uint32_t ret_val = 0; - ret_val = wm_ns * refclk_mhz; - ret_val /= 1000; - - if (ret_val > clamp_value) - ret_val = clamp_value; - - return ret_val; -} - -static void min10_program_watermarks( - struct mem_input *mem_input, - struct dcn_watermark_set *watermarks, - unsigned int refclk_mhz) -{ - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); - uint32_t force_en = mem_input->ctx->dc->debug.disable_stutter ? 1 : 0; - /* - * Need to clamp to max of the register values (i.e. no wrap) - * for dcn1, all wm registers are 21-bit wide - */ - uint32_t prog_wm_value; - - /* Repeat for water mark set A, B, C and D. */ - /* clock state A */ - prog_wm_value = convert_and_clamp(watermarks->a.urgent_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, prog_wm_value); - - dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, - "URGENCY_WATERMARK_A calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->a.urgent_ns, prog_wm_value); - - prog_wm_value = convert_and_clamp(watermarks->a.pte_meta_urgent_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A, prog_wm_value); - dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, - "PTE_META_URGENCY_WATERMARK_A calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->a.pte_meta_urgent_ns, prog_wm_value); - - - prog_wm_value = convert_and_clamp( - watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, - refclk_mhz, 0x1fffff); - - REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, prog_wm_value); - dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, - "SR_ENTER_EXIT_WATERMARK_A calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); - - - prog_wm_value = convert_and_clamp( - watermarks->a.cstate_pstate.cstate_exit_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value); - dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, - "SR_EXIT_WATERMARK_A calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->a.cstate_pstate.cstate_exit_ns, prog_wm_value); - - - prog_wm_value = convert_and_clamp( - watermarks->a.cstate_pstate.pstate_change_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, prog_wm_value); - dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, - "DRAM_CLK_CHANGE_WATERMARK_A calculated =%d\n" - "HW register value = 0x%x\n\n", - watermarks->a.cstate_pstate.pstate_change_ns, prog_wm_value); - - - /* clock state B */ - prog_wm_value = convert_and_clamp( - watermarks->b.urgent_ns, refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, prog_wm_value); - dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, - "URGENCY_WATERMARK_B calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->b.urgent_ns, prog_wm_value); - - - prog_wm_value = convert_and_clamp( - watermarks->b.pte_meta_urgent_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B, prog_wm_value); - dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, - "PTE_META_URGENCY_WATERMARK_B calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->b.pte_meta_urgent_ns, prog_wm_value); - - - prog_wm_value = convert_and_clamp( - watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, prog_wm_value); - dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, - "SR_ENTER_WATERMARK_B calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); - - - prog_wm_value = convert_and_clamp( - watermarks->b.cstate_pstate.cstate_exit_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, prog_wm_value); - dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, - "SR_EXIT_WATERMARK_B calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->b.cstate_pstate.cstate_exit_ns, prog_wm_value); - - prog_wm_value = convert_and_clamp( - watermarks->b.cstate_pstate.pstate_change_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, prog_wm_value); - dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, - "DRAM_CLK_CHANGE_WATERMARK_B calculated =%d\n\n" - "HW register value = 0x%x\n", - watermarks->b.cstate_pstate.pstate_change_ns, prog_wm_value); - - /* clock state C */ - prog_wm_value = convert_and_clamp( - watermarks->c.urgent_ns, refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, prog_wm_value); - dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, - "URGENCY_WATERMARK_C calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->c.urgent_ns, prog_wm_value); - - - prog_wm_value = convert_and_clamp( - watermarks->c.pte_meta_urgent_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C, prog_wm_value); - dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, - "PTE_META_URGENCY_WATERMARK_C calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->c.pte_meta_urgent_ns, prog_wm_value); - - - prog_wm_value = convert_and_clamp( - watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, prog_wm_value); - dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, - "SR_ENTER_WATERMARK_C calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); - - - prog_wm_value = convert_and_clamp( - watermarks->c.cstate_pstate.cstate_exit_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, prog_wm_value); - dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, - "SR_EXIT_WATERMARK_C calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->c.cstate_pstate.cstate_exit_ns, prog_wm_value); - - - prog_wm_value = convert_and_clamp( - watermarks->c.cstate_pstate.pstate_change_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, prog_wm_value); - dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, - "DRAM_CLK_CHANGE_WATERMARK_C calculated =%d\n\n" - "HW register value = 0x%x\n", - watermarks->c.cstate_pstate.pstate_change_ns, prog_wm_value); - - /* clock state D */ - prog_wm_value = convert_and_clamp( - watermarks->d.urgent_ns, refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, prog_wm_value); - dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, - "URGENCY_WATERMARK_D calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->d.urgent_ns, prog_wm_value); - - prog_wm_value = convert_and_clamp( - watermarks->d.pte_meta_urgent_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D, prog_wm_value); - dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, - "PTE_META_URGENCY_WATERMARK_D calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->d.pte_meta_urgent_ns, prog_wm_value); - - - prog_wm_value = convert_and_clamp( - watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, prog_wm_value); - dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, - "SR_ENTER_WATERMARK_D calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); - - - prog_wm_value = convert_and_clamp( - watermarks->d.cstate_pstate.cstate_exit_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, prog_wm_value); - dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, - "SR_EXIT_WATERMARK_D calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->d.cstate_pstate.cstate_exit_ns, prog_wm_value); - - - prog_wm_value = convert_and_clamp( - watermarks->d.cstate_pstate.pstate_change_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, prog_wm_value); - dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, - "DRAM_CLK_CHANGE_WATERMARK_D calculated =%d\n" - "HW register value = 0x%x\n\n", - watermarks->d.cstate_pstate.pstate_change_ns, prog_wm_value); - - REG_UPDATE(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, - DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, 1); - REG_UPDATE(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, - DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, 0); - REG_UPDATE(DCHUBBUB_ARB_SAT_LEVEL, - DCHUBBUB_ARB_SAT_LEVEL, 60 * refclk_mhz); - REG_UPDATE(DCHUBBUB_ARB_DF_REQ_OUTSTAND, - DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 68); - - REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL, - DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE, 0, - DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, force_en); - -#if 0 - REG_UPDATE_2(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, - DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE, 1, - DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, 1); -#endif -} - static void min10_program_display_marks( struct mem_input *mem_input, struct dce_watermarks nbp, @@ -855,63 +611,6 @@ static bool min10_is_flip_pending(struct mem_input *mem_input) return false; } -static void min10_update_dchub( - struct mem_input *mem_input, - struct dchub_init_data *dh_data) -{ - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); - /* TODO: port code from dal2 */ - switch (dh_data->fb_mode) { - case FRAME_BUFFER_MODE_ZFB_ONLY: - /*For ZFB case need to put DCHUB FB BASE and TOP upside down to indicate ZFB mode*/ - REG_UPDATE(DCHUBBUB_SDPIF_FB_TOP, - SDPIF_FB_TOP, 0); - - REG_UPDATE(DCHUBBUB_SDPIF_FB_BASE, - SDPIF_FB_BASE, 0x0FFFF); - - REG_UPDATE(DCHUBBUB_SDPIF_AGP_BASE, - SDPIF_AGP_BASE, dh_data->zfb_phys_addr_base >> 22); - - REG_UPDATE(DCHUBBUB_SDPIF_AGP_BOT, - SDPIF_AGP_BOT, dh_data->zfb_mc_base_addr >> 22); - - REG_UPDATE(DCHUBBUB_SDPIF_AGP_TOP, - SDPIF_AGP_TOP, (dh_data->zfb_mc_base_addr + - dh_data->zfb_size_in_byte - 1) >> 22); - break; - case FRAME_BUFFER_MODE_MIXED_ZFB_AND_LOCAL: - /*Should not touch FB LOCATION (done by VBIOS on AsicInit table)*/ - - REG_UPDATE(DCHUBBUB_SDPIF_AGP_BASE, - SDPIF_AGP_BASE, dh_data->zfb_phys_addr_base >> 22); - - REG_UPDATE(DCHUBBUB_SDPIF_AGP_BOT, - SDPIF_AGP_BOT, dh_data->zfb_mc_base_addr >> 22); - - REG_UPDATE(DCHUBBUB_SDPIF_AGP_TOP, - SDPIF_AGP_TOP, (dh_data->zfb_mc_base_addr + - dh_data->zfb_size_in_byte - 1) >> 22); - break; - case FRAME_BUFFER_MODE_LOCAL_ONLY: - /*Should not touch FB LOCATION (done by VBIOS on AsicInit table)*/ - REG_UPDATE(DCHUBBUB_SDPIF_AGP_BASE, - SDPIF_AGP_BASE, 0); - - REG_UPDATE(DCHUBBUB_SDPIF_AGP_BOT, - SDPIF_AGP_BOT, 0X03FFFF); - - REG_UPDATE(DCHUBBUB_SDPIF_AGP_TOP, - SDPIF_AGP_TOP, 0); - break; - default: - break; - } - - dh_data->dchub_initialzied = true; - dh_data->dchub_info_valid = false; -} - struct vm_system_aperture_param { PHYSICAL_ADDRESS_LOC sys_default; PHYSICAL_ADDRESS_LOC sys_low; @@ -1114,8 +813,6 @@ static struct mem_input_funcs dcn10_mem_input_funcs = { min10_program_surface_config, .mem_input_is_flip_pending = min10_is_flip_pending, .mem_input_setup = min10_setup, - .program_watermarks = min10_program_watermarks, - .mem_input_update_dchub = min10_update_dchub, .mem_input_program_pte_vm = min10_program_pte_vm, .set_blank = min10_set_blank, .dcc_control = min10_dcc_control, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h index 0f4d247c4237..9130f5e0ab03 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h @@ -98,30 +98,6 @@ SRI(DCN_SURF1_TTU_CNTL0, HUBPREQ, id),\ SRI(DCN_SURF1_TTU_CNTL1, HUBPREQ, id),\ SRI(DCN_VM_MX_L1_TLB_CNTL, HUBPREQ, id),\ - SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A),\ - SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A),\ - SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A),\ - SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A),\ - SR(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A),\ - SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B),\ - SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B),\ - SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B),\ - SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B),\ - SR(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B),\ - SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C),\ - SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C),\ - SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C),\ - SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C),\ - SR(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C),\ - SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D),\ - SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D),\ - SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D),\ - SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D),\ - SR(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D),\ - SR(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL),\ - SR(DCHUBBUB_ARB_DRAM_STATE_CNTL),\ - SR(DCHUBBUB_ARB_SAT_LEVEL),\ - SR(DCHUBBUB_ARB_DF_REQ_OUTSTAND),\ /* todo: get these from GVM instead of reading registers ourselves */\ MMHUB_SR(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32),\ MMHUB_SR(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32),\ @@ -154,12 +130,8 @@ SRI(DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, HUBPREQ, id),\ SRI(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, HUBPREQ, id),\ SRI(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, HUBPREQ, id),\ - SR(DCHUBBUB_SDPIF_FB_TOP),\ SR(DCHUBBUB_SDPIF_FB_BASE),\ - SR(DCHUBBUB_SDPIF_FB_OFFSET),\ - SR(DCHUBBUB_SDPIF_AGP_BASE),\ - SR(DCHUBBUB_SDPIF_AGP_BOT),\ - SR(DCHUBBUB_SDPIF_AGP_TOP) + SR(DCHUBBUB_SDPIF_FB_OFFSET) struct dcn_mi_registers { uint32_t DCHUBP_CNTL; @@ -248,42 +220,14 @@ struct dcn_mi_registers { uint32_t DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB; uint32_t DCN_VM_SYSTEM_APERTURE_LOW_ADDR; uint32_t DCN_VM_SYSTEM_APERTURE_HIGH_ADDR; - uint32_t DCHUBBUB_SDPIF_FB_TOP; uint32_t DCHUBBUB_SDPIF_FB_BASE; uint32_t DCHUBBUB_SDPIF_FB_OFFSET; - uint32_t DCHUBBUB_SDPIF_AGP_BASE; - uint32_t DCHUBBUB_SDPIF_AGP_BOT; - uint32_t DCHUBBUB_SDPIF_AGP_TOP; uint32_t DCN_VM_FB_LOCATION_TOP; uint32_t DCN_VM_FB_LOCATION_BASE; uint32_t DCN_VM_FB_OFFSET; uint32_t DCN_VM_AGP_BASE; uint32_t DCN_VM_AGP_BOT; uint32_t DCN_VM_AGP_TOP; - uint32_t DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A; - uint32_t DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A; - uint32_t DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A; - uint32_t DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A; - uint32_t DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A; - uint32_t DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B; - uint32_t DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B; - uint32_t DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B; - uint32_t DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B; - uint32_t DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B; - uint32_t DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C; - uint32_t DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C; - uint32_t DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C; - uint32_t DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C; - uint32_t DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C; - uint32_t DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D; - uint32_t DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D; - uint32_t DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D; - uint32_t DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D; - uint32_t DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D; - uint32_t DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL; - uint32_t DCHUBBUB_ARB_DRAM_STATE_CNTL; - uint32_t DCHUBBUB_ARB_SAT_LEVEL; - uint32_t DCHUBBUB_ARB_DF_REQ_OUTSTAND; /* GC registers. read only. temporary hack */ uint32_t VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32; @@ -418,13 +362,7 @@ struct dcn_mi_registers { MI_SF(HUBPREQ0_DCN_SURF0_TTU_CNTL0, QoS_RAMP_DISABLE, mask_sh),\ MI_SF(HUBPREQ0_DCN_SURF0_TTU_CNTL1, REFCYC_PER_REQ_DELIVERY_PRE, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_MX_L1_TLB_CNTL, ENABLE_L1_TLB, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_MX_L1_TLB_CNTL, SYSTEM_ACCESS_MODE, mask_sh),\ - MI_SF(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, mask_sh),\ - MI_SF(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE, mask_sh),\ - MI_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE, mask_sh),\ - MI_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, mask_sh),\ - MI_SF(DCHUBBUB_ARB_SAT_LEVEL, DCHUBBUB_ARB_SAT_LEVEL, mask_sh),\ - MI_SF(DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MIN_REQ_OUTSTAND, mask_sh) + MI_SF(HUBPREQ0_DCN_VM_MX_L1_TLB_CNTL, SYSTEM_ACCESS_MODE, mask_sh) #define MI_MASK_SH_LIST_DCN10(mask_sh)\ MI_MASK_SH_LIST_DCN(mask_sh),\ @@ -443,12 +381,8 @@ struct dcn_mi_registers { MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, MC_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, MC_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, MC_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, mask_sh),\ - MI_SF(DCHUBBUB_SDPIF_FB_TOP, SDPIF_FB_TOP, mask_sh),\ MI_SF(DCHUBBUB_SDPIF_FB_BASE, SDPIF_FB_BASE, mask_sh),\ MI_SF(DCHUBBUB_SDPIF_FB_OFFSET, SDPIF_FB_OFFSET, mask_sh),\ - MI_SF(DCHUBBUB_SDPIF_AGP_BASE, SDPIF_AGP_BASE, mask_sh),\ - MI_SF(DCHUBBUB_SDPIF_AGP_BOT, SDPIF_AGP_BOT, mask_sh),\ - MI_SF(DCHUBBUB_SDPIF_AGP_TOP, SDPIF_AGP_TOP, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, MC_VM_SYSTEM_APERTURE_DEFAULT_SYSTEM, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, mask_sh),\ @@ -611,12 +545,6 @@ struct dcn_mi_registers { type AGP_BASE;\ type AGP_BOT;\ type AGP_TOP;\ - type DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST;\ - type DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE;\ - type DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE;\ - type DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE;\ - type DCHUBBUB_ARB_SAT_LEVEL;\ - type DCHUBBUB_ARB_MIN_REQ_OUTSTAND;\ /* todo: get these from GVM instead of reading registers ourselves */\ type PAGE_DIRECTORY_ENTRY_HI32;\ type PAGE_DIRECTORY_ENTRY_LO32;\ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h index 1b7d151a66f8..fd3ce742af2c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h @@ -75,11 +75,6 @@ struct mem_input { struct mem_input_funcs { #if defined(CONFIG_DRM_AMD_DC_DCN1_0) - void (*program_watermarks)( - struct mem_input *mem_input, - struct dcn_watermark_set *watermarks, - unsigned int refclk_period_ns); - void (*mem_input_setup)( struct mem_input *mem_input, struct _vcs_dpi_display_dlg_regs_st *dlg_regs, @@ -143,7 +138,7 @@ struct mem_input_funcs { bool (*mem_input_is_flip_pending)(struct mem_input *mem_input); void (*mem_input_update_dchub)(struct mem_input *mem_input, - struct dchub_init_data *dh_data); + struct dchub_init_data *dh_data); void (*set_blank)(struct mem_input *mi, bool blank); }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 22aca5a375ae..d865df802c88 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -79,6 +79,10 @@ struct hw_sequencer_funcs { const struct core_dc *dc, struct pipe_ctx *pipe_ctx); + void (*update_dchub)( + struct dce_hwseq *hws, + struct dchub_init_data *dh_data); + void (*update_pending_status)( struct pipe_ctx *pipe_ctx); -- cgit From e12cfcb1d447cc937d1abc6f4aab8bbe5f88542e Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 20 Jul 2017 11:43:32 -0400 Subject: drm/amd/display: Roll core_surface into dc_surface Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 8 +- drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c | 16 ++-- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 26 +++--- drivers/gpu/drm/amd/display/dc/core/dc.c | 73 +++++++-------- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 42 ++++----- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 4 +- drivers/gpu/drm/amd/display/dc/core/dc_surface.c | 44 ++++----- drivers/gpu/drm/amd/display/dc/dc.h | 45 +++++---- drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c | 4 +- drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h | 2 +- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 102 ++++++++++----------- .../drm/amd/display/dc/dce110/dce110_resource.c | 2 +- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 76 +++++++-------- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 16 +--- drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 4 +- drivers/gpu/drm/amd/display/dc/inc/resource.h | 2 +- 16 files changed, 226 insertions(+), 240 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 44d85b77e252..b247904206ba 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2345,7 +2345,7 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, struct drm_plane *plane; struct drm_plane_state *old_plane_state; const struct dc_stream *dc_stream_attach; - const struct dc_surface *dc_surfaces_constructed[MAX_SURFACES]; + struct dc_surface *dc_surfaces_constructed[MAX_SURFACES]; struct amdgpu_crtc *acrtc_attach = to_amdgpu_crtc(pcrtc); struct dm_crtc_state *acrtc_state = to_dm_crtc_state(pcrtc->state); int planes_count = 0; @@ -2624,7 +2624,7 @@ void amdgpu_dm_atomic_commit_tail( struct dm_connector_state *con_old_state = to_dm_connector_state(old_conn_state); struct amdgpu_crtc *acrtc = to_amdgpu_crtc(con_new_state->base.crtc); - const struct dc_stream_status *status = NULL; + struct dc_stream_status *status = NULL; /* Skip any modesets/resets */ if (!acrtc || drm_atomic_crtc_needs_modeset(acrtc->base.state)) @@ -2649,7 +2649,7 @@ void amdgpu_dm_atomic_commit_tail( /*TODO How it works with MPO ?*/ if (!dc_commit_surfaces_to_stream( dm->dc, - (const struct dc_surface **)status->surfaces, + status->surfaces, status->surface_count, new_acrtc_state->stream)) dm_error("%s: Failed to update stream scaling!\n", __func__); @@ -2793,7 +2793,7 @@ static uint32_t add_val_sets_surface( struct dc_validation_set *val_sets, uint32_t set_count, const struct dc_stream *stream, - const struct dc_surface *surface) + struct dc_surface *surface) { uint32_t i = 0, j = 0; diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c index 87666987429e..5ef44ff4bcf8 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c @@ -2597,12 +2597,12 @@ static void populate_initial_data( ASSERT(pipe[i].surface); if (num_displays == 0) { - if (!pipe[i].surface->public.visible) + if (!pipe[i].surface->visible) data->d0_underlay_mode = bw_def_underlay_only; else data->d0_underlay_mode = bw_def_blend; } else { - if (!pipe[i].surface->public.visible) + if (!pipe[i].surface->visible) data->d1_underlay_mode = bw_def_underlay_only; else data->d1_underlay_mode = bw_def_blend; @@ -2620,7 +2620,7 @@ static void populate_initial_data( data->v_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.taps.v_taps); data->h_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].scl_data.ratios.horz.value); data->v_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].scl_data.ratios.vert.value); - switch (pipe[i].surface->public.rotation) { + switch (pipe[i].surface->rotation) { case ROTATION_ANGLE_0: data->rotation_angle[num_displays + 4] = bw_int_to_fixed(0); break; @@ -2636,7 +2636,7 @@ static void populate_initial_data( default: break; } - switch (pipe[i].surface->public.format) { + switch (pipe[i].surface->format) { case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: case SURFACE_PIXEL_FORMAT_GRPH_RGB565: @@ -2670,14 +2670,14 @@ static void populate_initial_data( data->src_height[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->scl_data.viewport.height); data->src_width[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->scl_data.viewport.width); data->pitch_in_pixels[num_displays * 2 + j] = bw_int_to_fixed( - pipe[i].bottom_pipe->surface->public.plane_size.grph.surface_pitch); + pipe[i].bottom_pipe->surface->plane_size.grph.surface_pitch); data->h_taps[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->scl_data.taps.h_taps); data->v_taps[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->scl_data.taps.v_taps); data->h_scale_ratio[num_displays * 2 + j] = fixed31_32_to_bw_fixed( pipe[i].bottom_pipe->scl_data.ratios.horz.value); data->v_scale_ratio[num_displays * 2 + j] = fixed31_32_to_bw_fixed( pipe[i].bottom_pipe->scl_data.ratios.vert.value); - switch (pipe[i].bottom_pipe->surface->public.rotation) { + switch (pipe[i].bottom_pipe->surface->rotation) { case ROTATION_ANGLE_0: data->rotation_angle[num_displays * 2 + j] = bw_int_to_fixed(0); break; @@ -2718,7 +2718,7 @@ static void populate_initial_data( data->v_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.taps.v_taps); data->h_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].scl_data.ratios.horz.value); data->v_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].scl_data.ratios.vert.value); - switch (pipe[i].surface->public.rotation) { + switch (pipe[i].surface->rotation) { case ROTATION_ANGLE_0: data->rotation_angle[num_displays + 4] = bw_int_to_fixed(0); break; @@ -2734,7 +2734,7 @@ static void populate_initial_data( default: break; } - switch (pipe[i].surface->public.format) { + switch (pipe[i].surface->format) { case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 17b28280236f..1651b7548d40 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -238,11 +238,11 @@ static void pipe_ctx_to_e2e_pipe_params ( else if (pipe->bottom_pipe != NULL && pipe->bottom_pipe->surface == pipe->surface) input->src.is_hsplit = true; - input->src.dcc = pipe->surface->public.dcc.enable; + input->src.dcc = pipe->surface->dcc.enable; input->src.dcc_rate = 1; - input->src.meta_pitch = pipe->surface->public.dcc.grph.meta_pitch; + input->src.meta_pitch = pipe->surface->dcc.grph.meta_pitch; input->src.source_scan = dm_horz; - input->src.sw_mode = pipe->surface->public.tiling_info.gfx9.swizzle; + input->src.sw_mode = pipe->surface->tiling_info.gfx9.swizzle; input->src.viewport_width = pipe->scl_data.viewport.width; input->src.viewport_height = pipe->scl_data.viewport.height; @@ -251,7 +251,7 @@ static void pipe_ctx_to_e2e_pipe_params ( input->src.cur0_src_width = 128; /* TODO: Cursor calcs, not curently stored */ input->src.cur0_bpp = 32; - switch (pipe->surface->public.tiling_info.gfx9.swizzle) { + switch (pipe->surface->tiling_info.gfx9.swizzle) { /* for 4/8/16 high tiles */ case DC_SW_LINEAR: input->src.is_display_sw = 1; @@ -299,7 +299,7 @@ static void pipe_ctx_to_e2e_pipe_params ( break; } - switch (pipe->surface->public.rotation) { + switch (pipe->surface->rotation) { case ROTATION_ANGLE_0: case ROTATION_ANGLE_180: input->src.source_scan = dm_horz; @@ -314,7 +314,7 @@ static void pipe_ctx_to_e2e_pipe_params ( } /* TODO: Fix pixel format mappings */ - switch (pipe->surface->public.format) { + switch (pipe->surface->format) { case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: input->src.source_format = dm_420_8; @@ -455,7 +455,7 @@ static void dcn_bw_calc_rq_dlg_ttu( true, true, v->pte_enable == dcn_bw_yes, - pipe->surface->public.flip_immediate); + pipe->surface->flip_immediate); } static void dcn_dml_wm_override( @@ -527,7 +527,7 @@ static void dcn_dml_wm_override( true, true, v->pte_enable == dcn_bw_yes, - pipe->surface->public.flip_immediate); + pipe->surface->flip_immediate); in_idx++; } dm_free(input); @@ -883,7 +883,7 @@ bool dcn_validate_bandwidth( v->scaler_rec_out_width[input_idx] = pipe->scl_data.recout.width; v->scaler_recout_height[input_idx] = pipe->scl_data.recout.height; if (pipe->bottom_pipe && pipe->bottom_pipe->surface == pipe->surface) { - if (pipe->surface->public.rotation % 2 == 0) { + if (pipe->surface->rotation % 2 == 0) { int viewport_end = pipe->scl_data.viewport.width + pipe->scl_data.viewport.x; int viewport_b_end = pipe->bottom_pipe->scl_data.viewport.width @@ -912,17 +912,17 @@ bool dcn_validate_bandwidth( + pipe->bottom_pipe->scl_data.recout.width; } - v->dcc_enable[input_idx] = pipe->surface->public.dcc.enable ? dcn_bw_yes : dcn_bw_no; + v->dcc_enable[input_idx] = pipe->surface->dcc.enable ? dcn_bw_yes : dcn_bw_no; v->source_pixel_format[input_idx] = tl_pixel_format_to_bw_defs( - pipe->surface->public.format); + pipe->surface->format); v->source_surface_mode[input_idx] = tl_sw_mode_to_bw_defs( - pipe->surface->public.tiling_info.gfx9.swizzle); + pipe->surface->tiling_info.gfx9.swizzle); v->lb_bit_per_pixel[input_idx] = tl_lb_bpp_to_int(pipe->scl_data.lb_params.depth); v->override_hta_ps[input_idx] = pipe->scl_data.taps.h_taps; v->override_vta_ps[input_idx] = pipe->scl_data.taps.v_taps; v->override_hta_pschroma[input_idx] = pipe->scl_data.taps.h_taps_c; v->override_vta_pschroma[input_idx] = pipe->scl_data.taps.v_taps_c; - v->source_scan[input_idx] = (pipe->surface->public.rotation % 2) ? dcn_bw_vert : dcn_bw_hor; + v->source_scan[input_idx] = (pipe->surface->rotation % 2) ? dcn_bw_vert : dcn_bw_hor; } if (v->is_line_buffer_bpp_fixed == dcn_bw_yes) v->lb_bit_per_pixel[input_idx] = v->line_buffer_fixed_bpp; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index e89a2e5c8902..569310ab116d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -946,8 +946,8 @@ static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *c const struct core_sink *sink = context->streams[i]->sink; for (j = 0; j < context->stream_status[i].surface_count; j++) { - struct core_surface *surface = - DC_SURFACE_TO_CORE(context->stream_status[i].surfaces[j]); + const struct dc_surface *surface = + context->stream_status[i].surfaces[j]; core_dc->hwss.apply_ctx_for_surface(core_dc, surface, context); @@ -1098,7 +1098,7 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) bool dc_commit_surfaces_to_stream( struct dc *dc, - const struct dc_surface **new_surfaces, + struct dc_surface **new_surfaces, uint8_t new_surface_count, const struct dc_stream *dc_stream) { @@ -1189,7 +1189,7 @@ static bool is_surface_in_context( for (j = 0; j < MAX_PIPES; j++) { const struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - if (surface == &pipe_ctx->surface->public) { + if (surface == pipe_ctx->surface) { return true; } } @@ -1422,7 +1422,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, update_surface_trace(dc, srf_updates, surface_count); if (update_type >= UPDATE_TYPE_FULL) { - const struct dc_surface *new_surfaces[MAX_SURFACES] = {0}; + struct dc_surface *new_surfaces[MAX_SURFACES] = {0}; for (i = 0; i < surface_count; i++) new_surfaces[i] = srf_updates[i].surface; @@ -1448,46 +1448,45 @@ void dc_update_surfaces_and_stream(struct dc *dc, /* save update parameters into surface */ for (i = 0; i < surface_count; i++) { - struct core_surface *surface = - DC_SURFACE_TO_CORE(srf_updates[i].surface); + struct dc_surface *surface = srf_updates[i].surface; if (srf_updates[i].flip_addr) { - surface->public.address = srf_updates[i].flip_addr->address; - surface->public.flip_immediate = + surface->address = srf_updates[i].flip_addr->address; + surface->flip_immediate = srf_updates[i].flip_addr->flip_immediate; } if (srf_updates[i].scaling_info) { - surface->public.scaling_quality = + surface->scaling_quality = srf_updates[i].scaling_info->scaling_quality; - surface->public.dst_rect = + surface->dst_rect = srf_updates[i].scaling_info->dst_rect; - surface->public.src_rect = + surface->src_rect = srf_updates[i].scaling_info->src_rect; - surface->public.clip_rect = + surface->clip_rect = srf_updates[i].scaling_info->clip_rect; } if (srf_updates[i].plane_info) { - surface->public.color_space = + surface->color_space = srf_updates[i].plane_info->color_space; - surface->public.format = + surface->format = srf_updates[i].plane_info->format; - surface->public.plane_size = + surface->plane_size = srf_updates[i].plane_info->plane_size; - surface->public.rotation = + surface->rotation = srf_updates[i].plane_info->rotation; - surface->public.horizontal_mirror = + surface->horizontal_mirror = srf_updates[i].plane_info->horizontal_mirror; - surface->public.stereo_format = + surface->stereo_format = srf_updates[i].plane_info->stereo_format; - surface->public.tiling_info = + surface->tiling_info = srf_updates[i].plane_info->tiling_info; - surface->public.visible = + surface->visible = srf_updates[i].plane_info->visible; - surface->public.per_pixel_alpha = + surface->per_pixel_alpha = srf_updates[i].plane_info->per_pixel_alpha; - surface->public.dcc = + surface->dcc = srf_updates[i].plane_info->dcc; } @@ -1503,31 +1502,31 @@ void dc_update_surfaces_and_stream(struct dc *dc, } if (srf_updates[i].gamma && - srf_updates[i].gamma != surface->public.gamma_correction) { - if (surface->public.gamma_correction != NULL) - dc_gamma_release(&surface->public. + srf_updates[i].gamma != surface->gamma_correction) { + if (surface->gamma_correction != NULL) + dc_gamma_release(&surface-> gamma_correction); dc_gamma_retain(srf_updates[i].gamma); - surface->public.gamma_correction = + surface->gamma_correction = srf_updates[i].gamma; } if (srf_updates[i].in_transfer_func && - srf_updates[i].in_transfer_func != surface->public.in_transfer_func) { - if (surface->public.in_transfer_func != NULL) + srf_updates[i].in_transfer_func != surface->in_transfer_func) { + if (surface->in_transfer_func != NULL) dc_transfer_func_release( - surface->public. + surface-> in_transfer_func); dc_transfer_func_retain( srf_updates[i].in_transfer_func); - surface->public.in_transfer_func = + surface->in_transfer_func = srf_updates[i].in_transfer_func; } if (srf_updates[i].hdr_static_metadata) - surface->public.hdr_static_ctx = + surface->hdr_static_ctx = *(srf_updates[i].hdr_static_metadata); } @@ -1543,12 +1542,10 @@ void dc_update_surfaces_and_stream(struct dc *dc, if (update_type > UPDATE_TYPE_FAST) { for (i = 0; i < surface_count; i++) { - struct core_surface *surface = DC_SURFACE_TO_CORE(srf_updates[i].surface); - for (j = 0; j < core_dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - if (pipe_ctx->surface != surface) + if (pipe_ctx->surface != srf_updates[i].surface) continue; core_dc->hwss.wait_for_mpcc_disconnect(core_dc->res_pool, pipe_ctx); @@ -1561,7 +1558,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, /* Lock pipes for provided surfaces, or all active if full update*/ for (i = 0; i < surface_count; i++) { - struct core_surface *surface = DC_SURFACE_TO_CORE(srf_updates[i].surface); + struct dc_surface *surface = srf_updates[i].surface; for (j = 0; j < core_dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; @@ -1613,7 +1610,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, /* Perform requested Updates */ for (i = 0; i < surface_count; i++) { - struct core_surface *surface = DC_SURFACE_TO_CORE(srf_updates[i].surface); + struct dc_surface *surface = srf_updates[i].surface; if (update_type == UPDATE_TYPE_MED) core_dc->hwss.apply_ctx_for_surface( @@ -1654,7 +1651,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, for (j = 0; j < surface_count; j++) { if (update_type != UPDATE_TYPE_FULL && - srf_updates[j].surface != &pipe_ctx->surface->public) + srf_updates[j].surface != pipe_ctx->surface) continue; if (!pipe_ctx->surface || pipe_ctx->top_pipe) continue; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 5acc5cdcda16..303c95432d5b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -428,7 +428,7 @@ static void rect_swap_helper(struct rect *rect) static void calculate_viewport(struct pipe_ctx *pipe_ctx) { - const struct dc_surface *surface = &pipe_ctx->surface->public; + const struct dc_surface *surface = pipe_ctx->surface; const struct dc_stream *stream = &pipe_ctx->stream->public; struct scaler_data *data = &pipe_ctx->scl_data; struct rect surf_src = surface->src_rect; @@ -446,8 +446,8 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) sec_split = false; } - if (pipe_ctx->surface->public.rotation == ROTATION_ANGLE_90 || - pipe_ctx->surface->public.rotation == ROTATION_ANGLE_270) + if (pipe_ctx->surface->rotation == ROTATION_ANGLE_90 || + pipe_ctx->surface->rotation == ROTATION_ANGLE_270) rect_swap_helper(&surf_src); /* The actual clip is an intersection between stream @@ -527,14 +527,14 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip) { - const struct dc_surface *surface = &pipe_ctx->surface->public; + const struct dc_surface *surface = pipe_ctx->surface; struct core_stream *stream = pipe_ctx->stream; struct rect surf_src = surface->src_rect; struct rect surf_clip = surface->clip_rect; int recout_full_x, recout_full_y; - if (pipe_ctx->surface->public.rotation == ROTATION_ANGLE_90 || - pipe_ctx->surface->public.rotation == ROTATION_ANGLE_270) + if (pipe_ctx->surface->rotation == ROTATION_ANGLE_90 || + pipe_ctx->surface->rotation == ROTATION_ANGLE_270) rect_swap_helper(&surf_src); pipe_ctx->scl_data.recout.x = stream->public.dst.x; @@ -605,7 +605,7 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) { - const struct dc_surface *surface = &pipe_ctx->surface->public; + const struct dc_surface *surface = pipe_ctx->surface; struct core_stream *stream = pipe_ctx->stream; struct rect surf_src = surface->src_rect; const int in_w = stream->public.src.width; @@ -613,8 +613,8 @@ static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) const int out_w = stream->public.dst.width; const int out_h = stream->public.dst.height; - if (pipe_ctx->surface->public.rotation == ROTATION_ANGLE_90 || - pipe_ctx->surface->public.rotation == ROTATION_ANGLE_270) + if (pipe_ctx->surface->rotation == ROTATION_ANGLE_90 || + pipe_ctx->surface->rotation == ROTATION_ANGLE_270) rect_swap_helper(&surf_src); pipe_ctx->scl_data.ratios.horz = dal_fixed31_32_from_fraction( @@ -647,13 +647,13 @@ static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *recout_skip) { struct scaler_data *data = &pipe_ctx->scl_data; - struct rect src = pipe_ctx->surface->public.src_rect; + struct rect src = pipe_ctx->surface->src_rect; int vpc_div = (data->format == PIXEL_FORMAT_420BPP8 || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1; - if (pipe_ctx->surface->public.rotation == ROTATION_ANGLE_90 || - pipe_ctx->surface->public.rotation == ROTATION_ANGLE_270) { + if (pipe_ctx->surface->rotation == ROTATION_ANGLE_90 || + pipe_ctx->surface->rotation == ROTATION_ANGLE_270) { rect_swap_helper(&src); rect_swap_helper(&data->viewport_c); rect_swap_helper(&data->viewport); @@ -803,8 +803,8 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *r data->inits.v_bot = dal_fixed31_32_add(data->inits.v, data->ratios.vert); data->inits.v_c_bot = dal_fixed31_32_add(data->inits.v_c, data->ratios.vert_c); - if (pipe_ctx->surface->public.rotation == ROTATION_ANGLE_90 || - pipe_ctx->surface->public.rotation == ROTATION_ANGLE_270) { + if (pipe_ctx->surface->rotation == ROTATION_ANGLE_90 || + pipe_ctx->surface->rotation == ROTATION_ANGLE_270) { rect_swap_helper(&data->viewport_c); rect_swap_helper(&data->viewport); } @@ -812,7 +812,7 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *r bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) { - const struct dc_surface *surface = &pipe_ctx->surface->public; + const struct dc_surface *surface = pipe_ctx->surface; struct dc_crtc_timing *timing = &pipe_ctx->stream->public.timing; struct view recout_skip = { 0 }; bool res = false; @@ -822,7 +822,7 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) * Inits require viewport, taps, ratios and recout of split pipe */ pipe_ctx->scl_data.format = convert_pixel_format_to_dalsurface( - pipe_ctx->surface->public.format); + pipe_ctx->surface->format); calculate_scaling_ratios(pipe_ctx); @@ -1029,7 +1029,7 @@ static int acquire_first_split_pipe( #endif bool resource_attach_surfaces_to_context( - const struct dc_surface * const *surfaces, + struct dc_surface * const *surfaces, int surface_count, const struct dc_stream *dc_stream, struct validate_context *context, @@ -1077,7 +1077,7 @@ bool resource_attach_surfaces_to_context( tail_pipe = NULL; for (i = 0; i < surface_count; i++) { - struct core_surface *surface = DC_SURFACE_TO_CORE(surfaces[i]); + struct dc_surface *surface = surfaces[i]; struct pipe_ctx *free_pipe = acquire_free_pipe_for_stream( context, pool, dc_stream); @@ -1358,7 +1358,7 @@ bool resource_is_stream_unchanged( static void copy_pipe_ctx( const struct pipe_ctx *from_pipe_ctx, struct pipe_ctx *to_pipe_ctx) { - struct core_surface *surface = to_pipe_ctx->surface; + struct dc_surface *surface = to_pipe_ctx->surface; struct core_stream *stream = to_pipe_ctx->stream; *to_pipe_ctx = *from_pipe_ctx; @@ -2072,7 +2072,7 @@ static void set_spd_info_packet( static void set_hdr_static_info_packet( struct encoder_info_packet *info_packet, - struct core_surface *surface, + struct dc_surface *surface, struct core_stream *stream) { uint16_t i = 0; @@ -2083,7 +2083,7 @@ static void set_hdr_static_info_packet( if (!surface) return; - hdr_metadata = surface->public.hdr_static_ctx; + hdr_metadata = surface->hdr_static_ctx; if (!hdr_metadata.hdr_supported) return; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index ead7b63caab7..73712fd6f64a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -157,7 +157,7 @@ alloc_fail: return NULL; } -const struct dc_stream_status *dc_stream_get_status( +struct dc_stream_status *dc_stream_get_status( const struct dc_stream *dc_stream) { uint8_t i; @@ -252,7 +252,7 @@ bool dc_stream_set_cursor_position( !pipe_ctx->ipp || !pipe_ctx->surface) continue; - if (pipe_ctx->surface->public.address.type + if (pipe_ctx->surface->address.type == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE) pos_cpy.enable = false; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index 3784358d35ef..9a21ea71f4b3 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -47,33 +47,32 @@ struct gamma { /******************************************************************************* * Private functions ******************************************************************************/ -static bool construct(struct dc_context *ctx, struct core_surface *surface) +static bool construct(struct dc_context *ctx, struct dc_surface *surface) { surface->ctx = ctx; - memset(&surface->public.hdr_static_ctx, + memset(&surface->hdr_static_ctx, 0, sizeof(struct dc_hdr_static_metadata)); return true; } -static void destruct(struct core_surface *surface) +static void destruct(struct dc_surface *surface) { - if (surface->public.gamma_correction != NULL) { - dc_gamma_release(&surface->public.gamma_correction); + if (surface->gamma_correction != NULL) { + dc_gamma_release(&surface->gamma_correction); } - if (surface->public.in_transfer_func != NULL) { + if (surface->in_transfer_func != NULL) { dc_transfer_func_release( - surface->public.in_transfer_func); - surface->public.in_transfer_func = NULL; + surface->in_transfer_func); + surface->in_transfer_func = NULL; } } /******************************************************************************* * Public functions ******************************************************************************/ -void enable_surface_flip_reporting(struct dc_surface *dc_surface, +void enable_surface_flip_reporting(struct dc_surface *surface, uint32_t controller_id) { - struct core_surface *surface = DC_SURFACE_TO_CORE(dc_surface); surface->irq_source = controller_id + DC_IRQ_SOURCE_PFLIP1 - 1; /*register_flip_interrupt(surface);*/ } @@ -82,7 +81,7 @@ struct dc_surface *dc_create_surface(const struct dc *dc) { struct core_dc *core_dc = DC_TO_CORE(dc); - struct core_surface *surface = dm_alloc(sizeof(*surface)); + struct dc_surface *surface = dm_alloc(sizeof(*surface)); if (NULL == surface) goto alloc_fail; @@ -92,7 +91,7 @@ struct dc_surface *dc_create_surface(const struct dc *dc) ++surface->ref_count; - return &surface->public; + return surface; construct_fail: dm_free(surface); @@ -104,20 +103,19 @@ alloc_fail: const struct dc_surface_status *dc_surface_get_status( const struct dc_surface *dc_surface) { - struct dc_surface_status *surface_status; - struct core_surface *core_surface = DC_SURFACE_TO_CORE(dc_surface); + const struct dc_surface_status *surface_status; struct core_dc *core_dc; int i; if (!dc_surface || - !core_surface->ctx || - !core_surface->ctx->dc) { + !dc_surface->ctx || + !dc_surface->ctx->dc) { ASSERT(0); return NULL; /* remove this if above assert never hit */ } - surface_status = &core_surface->status; - core_dc = DC_TO_CORE(core_surface->ctx->dc); + surface_status = &dc_surface->status; + core_dc = DC_TO_CORE(dc_surface->ctx->dc); if (core_dc->current_context == NULL) return NULL; @@ -126,7 +124,7 @@ const struct dc_surface_status *dc_surface_get_status( struct pipe_ctx *pipe_ctx = &core_dc->current_context->res_ctx.pipe_ctx[i]; - if (pipe_ctx->surface != core_surface) + if (pipe_ctx->surface != dc_surface) continue; core_dc->hwss.update_pending_status(pipe_ctx); @@ -135,18 +133,14 @@ const struct dc_surface_status *dc_surface_get_status( return surface_status; } -void dc_surface_retain(const struct dc_surface *dc_surface) +void dc_surface_retain(struct dc_surface *surface) { - struct core_surface *surface = DC_SURFACE_TO_CORE(dc_surface); - ASSERT(surface->ref_count > 0); ++surface->ref_count; } -void dc_surface_release(const struct dc_surface *dc_surface) +void dc_surface_release(struct dc_surface *surface) { - struct core_surface *surface = DC_SURFACE_TO_CORE(dc_surface); - ASSERT(surface->ref_count > 0); --surface->ref_count; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index ee04c3562081..b14bad10db97 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -299,6 +299,18 @@ struct dc_transfer_func { int ref_count; }; +/* + * This structure is filled in by dc_surface_get_status and contains + * the last requested address and the currently active address so the called + * can determine if there are any outstanding flips + */ +struct dc_surface_status { + struct dc_plane_address requested_address; + struct dc_plane_address current_address; + bool is_flip_pending; + bool is_right_eye; +}; + struct dc_surface { struct dc_plane_address address; @@ -325,6 +337,14 @@ struct dc_surface { bool visible; bool flip_immediate; bool horizontal_mirror; + + /* private to DC core */ + struct dc_surface_status status; + struct dc_context *ctx; + + /* private to dc_surface.c */ + enum dc_irq_source irq_source; + int ref_count; }; struct dc_plane_info { @@ -348,7 +368,7 @@ struct dc_scaling_info { }; struct dc_surface_update { - const struct dc_surface *surface; + struct dc_surface *surface; /* isr safe update parameters. null means no updates */ struct dc_flip_addrs *flip_addr; @@ -362,17 +382,6 @@ struct dc_surface_update { struct dc_transfer_func *in_transfer_func; struct dc_hdr_static_metadata *hdr_static_metadata; }; -/* - * This structure is filled in by dc_surface_get_status and contains - * the last requested address and the currently active address so the called - * can determine if there are any outstanding flips - */ -struct dc_surface_status { - struct dc_plane_address requested_address; - struct dc_plane_address current_address; - bool is_flip_pending; - bool is_right_eye; -}; /* * Create a new surface with default parameters; @@ -381,8 +390,8 @@ struct dc_surface *dc_create_surface(const struct dc *dc); const struct dc_surface_status *dc_surface_get_status( const struct dc_surface *dc_surface); -void dc_surface_retain(const struct dc_surface *dc_surface); -void dc_surface_release(const struct dc_surface *dc_surface); +void dc_surface_retain(struct dc_surface *dc_surface); +void dc_surface_release(struct dc_surface *dc_surface); void dc_gamma_retain(const struct dc_gamma *dc_gamma); void dc_gamma_release(const struct dc_gamma **dc_gamma); @@ -416,7 +425,7 @@ struct dc_flip_addrs { bool dc_commit_surfaces_to_stream( struct dc *dc, - const struct dc_surface **dc_surfaces, + struct dc_surface **dc_surfaces, uint8_t surface_count, const struct dc_stream *stream); @@ -545,7 +554,7 @@ bool dc_stream_get_scanoutpos(const struct dc_stream *stream, */ struct dc_validation_set { const struct dc_stream *stream; - const struct dc_surface *surfaces[MAX_SURFACES]; + struct dc_surface *surfaces[MAX_SURFACES]; uint8_t surface_count; }; @@ -627,7 +636,7 @@ void dc_stream_release(const struct dc_stream *dc_stream); struct dc_stream_status { int primary_otg_inst; int surface_count; - const struct dc_surface *surfaces[MAX_SURFACE_NUM]; + struct dc_surface *surfaces[MAX_SURFACE_NUM]; /* * link this stream passes through @@ -635,7 +644,7 @@ struct dc_stream_status { const struct dc_link *link; }; -const struct dc_stream_status *dc_stream_get_status( +struct dc_stream_status *dc_stream_get_status( const struct dc_stream *dc_stream); enum surface_update_type dc_check_update_surfaces_for_stream( diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c index cc3178acfc54..a8c254f66c98 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c @@ -193,9 +193,9 @@ void dce_crtc_switch_to_clk_src(struct dce_hwseq *hws, } /* Only use LUT for 8 bit formats */ -bool dce_use_lut(const struct core_surface *surface) +bool dce_use_lut(const struct dc_surface *surface) { - switch (surface->public.format) { + switch (surface->format) { case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: return true; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index d62fc526783f..ade7507e99c7 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -552,5 +552,5 @@ void dce_crtc_switch_to_clk_src(struct dce_hwseq *hws, struct clock_source *clk_src, unsigned int tg_inst); -bool dce_use_lut(const struct core_surface *surface); +bool dce_use_lut(const struct dc_surface *surface); #endif /*__DCE_HWSEQ_H__*/ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index efba8d7964eb..cf6bf2098b7c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -215,11 +215,11 @@ static bool dce110_enable_display_power_gating( } static void build_prescale_params(struct ipp_prescale_params *prescale_params, - const struct core_surface *surface) + const struct dc_surface *surface) { prescale_params->mode = IPP_PRESCALE_MODE_FIXED_UNSIGNED; - switch (surface->public.format) { + switch (surface->format) { case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: prescale_params->scale = 0x2020; @@ -240,7 +240,7 @@ static void build_prescale_params(struct ipp_prescale_params *prescale_params, static bool dce110_set_input_transfer_func( struct pipe_ctx *pipe_ctx, - const struct core_surface *surface) + const struct dc_surface *surface) { struct input_pixel_processor *ipp = pipe_ctx->ipp; const struct dc_transfer_func *tf = NULL; @@ -250,14 +250,14 @@ static bool dce110_set_input_transfer_func( if (ipp == NULL) return false; - if (surface->public.in_transfer_func) - tf = surface->public.in_transfer_func; + if (surface->in_transfer_func) + tf = surface->in_transfer_func; build_prescale_params(&prescale_params, surface); ipp->funcs->ipp_program_prescale(ipp, &prescale_params); - if (surface->public.gamma_correction && dce_use_lut(surface)) - ipp->funcs->ipp_program_input_lut(ipp, surface->public.gamma_correction); + if (surface->gamma_correction && dce_use_lut(surface)) + ipp->funcs->ipp_program_input_lut(ipp, surface->gamma_correction); if (tf == NULL) { /* Default case if no input transfer function specified */ @@ -1857,7 +1857,7 @@ static void set_default_colors(struct pipe_ctx *pipe_ctx) default_adjust.in_color_space = COLOR_SPACE_SRGB; else default_adjust.in_color_space = - pipe_ctx->surface->public.color_space; + pipe_ctx->surface->color_space; if (pipe_ctx->stream == NULL) default_adjust.out_color_space = COLOR_SPACE_SRGB; else @@ -1908,16 +1908,16 @@ static void program_surface_visibility(const struct core_dc *dc, /* For now we are supporting only two pipes */ ASSERT(pipe_ctx->bottom_pipe->bottom_pipe == NULL); - if (pipe_ctx->bottom_pipe->surface->public.visible) { - if (pipe_ctx->surface->public.visible) + if (pipe_ctx->bottom_pipe->surface->visible) { + if (pipe_ctx->surface->visible) blender_mode = BLND_MODE_BLENDING; else blender_mode = BLND_MODE_OTHER_PIPE; - } else if (!pipe_ctx->surface->public.visible) + } else if (!pipe_ctx->surface->visible) blank_target = true; - } else if (!pipe_ctx->surface->public.visible) + } else if (!pipe_ctx->surface->visible) blank_target = true; dce_set_blender_mode(dc->hwseq, pipe_ctx->pipe_idx, blender_mode); @@ -1975,7 +1975,7 @@ static void set_plane_config( struct resource_context *res_ctx) { struct mem_input *mi = pipe_ctx->mi; - struct core_surface *surface = pipe_ctx->surface; + struct dc_surface *surface = pipe_ctx->surface; struct xfm_grph_csc_adjustment adjust; struct out_csc_color_matrix tbl_entry; unsigned int i; @@ -2040,42 +2040,42 @@ static void set_plane_config( mi->funcs->mem_input_program_surface_config( mi, - surface->public.format, - &surface->public.tiling_info, - &surface->public.plane_size, - surface->public.rotation, + surface->format, + &surface->tiling_info, + &surface->plane_size, + surface->rotation, NULL, false); if (mi->funcs->set_blank) - mi->funcs->set_blank(mi, pipe_ctx->surface->public.visible); + mi->funcs->set_blank(mi, pipe_ctx->surface->visible); if (dc->public.config.gpu_vm_support) mi->funcs->mem_input_program_pte_vm( pipe_ctx->mi, - surface->public.format, - &surface->public.tiling_info, - surface->public.rotation); + surface->format, + &surface->tiling_info, + surface->rotation); } static void update_plane_addr(const struct core_dc *dc, struct pipe_ctx *pipe_ctx) { - struct core_surface *surface = pipe_ctx->surface; + struct dc_surface *surface = pipe_ctx->surface; if (surface == NULL) return; pipe_ctx->mi->funcs->mem_input_program_surface_flip_and_addr( pipe_ctx->mi, - &surface->public.address, - surface->public.flip_immediate); + &surface->address, + surface->flip_immediate); - surface->status.requested_address = surface->public.address; + surface->status.requested_address = surface->address; } void dce110_update_pending_status(struct pipe_ctx *pipe_ctx) { - struct core_surface *surface = pipe_ctx->surface; + struct dc_surface *surface = pipe_ctx->surface; if (surface == NULL) return; @@ -2084,7 +2084,7 @@ void dce110_update_pending_status(struct pipe_ctx *pipe_ctx) pipe_ctx->mi->funcs->mem_input_is_flip_pending( pipe_ctx->mi); - if (surface->status.is_flip_pending && !surface->public.visible) + if (surface->status.is_flip_pending && !surface->visible) pipe_ctx->mi->current_address = pipe_ctx->mi->request_address; surface->status.current_address = pipe_ctx->mi->current_address; @@ -2425,7 +2425,7 @@ static void dce110_program_front_end_for_pipe( { struct mem_input *mi = pipe_ctx->mi; struct pipe_ctx *old_pipe = NULL; - struct core_surface *surface = pipe_ctx->surface; + struct dc_surface *surface = pipe_ctx->surface; struct xfm_grph_csc_adjustment adjust; struct out_csc_color_matrix tbl_entry; unsigned int i; @@ -2493,21 +2493,21 @@ static void dce110_program_front_end_for_pipe( mi->funcs->mem_input_program_surface_config( mi, - surface->public.format, - &surface->public.tiling_info, - &surface->public.plane_size, - surface->public.rotation, + surface->format, + &surface->tiling_info, + &surface->plane_size, + surface->rotation, NULL, false); if (mi->funcs->set_blank) - mi->funcs->set_blank(mi, pipe_ctx->surface->public.visible); + mi->funcs->set_blank(mi, pipe_ctx->surface->visible); if (dc->public.config.gpu_vm_support) mi->funcs->mem_input_program_pte_vm( pipe_ctx->mi, - surface->public.format, - &surface->public.tiling_info, - surface->public.rotation); + surface->format, + &surface->tiling_info, + surface->rotation); dm_logger_write(dc->ctx->logger, LOG_SURFACE, "Pipe:%d 0x%x: addr hi:0x%x, " @@ -2517,20 +2517,20 @@ static void dce110_program_front_end_for_pipe( "clip: %d, %d, %d, %d\n", pipe_ctx->pipe_idx, pipe_ctx->surface, - pipe_ctx->surface->public.address.grph.addr.high_part, - pipe_ctx->surface->public.address.grph.addr.low_part, - pipe_ctx->surface->public.src_rect.x, - pipe_ctx->surface->public.src_rect.y, - pipe_ctx->surface->public.src_rect.width, - pipe_ctx->surface->public.src_rect.height, - pipe_ctx->surface->public.dst_rect.x, - pipe_ctx->surface->public.dst_rect.y, - pipe_ctx->surface->public.dst_rect.width, - pipe_ctx->surface->public.dst_rect.height, - pipe_ctx->surface->public.clip_rect.x, - pipe_ctx->surface->public.clip_rect.y, - pipe_ctx->surface->public.clip_rect.width, - pipe_ctx->surface->public.clip_rect.height); + pipe_ctx->surface->address.grph.addr.high_part, + pipe_ctx->surface->address.grph.addr.low_part, + pipe_ctx->surface->src_rect.x, + pipe_ctx->surface->src_rect.y, + pipe_ctx->surface->src_rect.width, + pipe_ctx->surface->src_rect.height, + pipe_ctx->surface->dst_rect.x, + pipe_ctx->surface->dst_rect.y, + pipe_ctx->surface->dst_rect.width, + pipe_ctx->surface->dst_rect.height, + pipe_ctx->surface->clip_rect.x, + pipe_ctx->surface->clip_rect.y, + pipe_ctx->surface->clip_rect.width, + pipe_ctx->surface->clip_rect.height); dm_logger_write(dc->ctx->logger, LOG_SURFACE, "Pipe %d: width, height, x, y\n" @@ -2549,7 +2549,7 @@ static void dce110_program_front_end_for_pipe( static void dce110_apply_ctx_for_surface( struct core_dc *dc, - struct core_surface *surface, + const struct dc_surface *surface, struct validate_context *context) { int i; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 8b7bc1cc2b7b..0fcb1cf4b4ce 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -766,7 +766,7 @@ static bool is_surface_pixel_format_supported(struct pipe_ctx *pipe_ctx, unsigne return true; if (!pipe_ctx->surface) return false; - if (pipe_ctx->surface->public.format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) + if (pipe_ctx->surface->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) return false; return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index b7940876c761..4390023ca6dc 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -945,24 +945,24 @@ static void reset_hw_ctx_wrap( static bool patch_address_for_sbs_tb_stereo( struct pipe_ctx *pipe_ctx, PHYSICAL_ADDRESS_LOC *addr) { - struct core_surface *surface = pipe_ctx->surface; + struct dc_surface *surface = pipe_ctx->surface; bool sec_split = pipe_ctx->top_pipe && pipe_ctx->top_pipe->surface == pipe_ctx->surface; - if (sec_split && surface->public.address.type == PLN_ADDR_TYPE_GRPH_STEREO && + if (sec_split && surface->address.type == PLN_ADDR_TYPE_GRPH_STEREO && (pipe_ctx->stream->public.timing.timing_3d_format == TIMING_3D_FORMAT_SIDE_BY_SIDE || pipe_ctx->stream->public.timing.timing_3d_format == TIMING_3D_FORMAT_TOP_AND_BOTTOM)) { - *addr = surface->public.address.grph_stereo.left_addr; - surface->public.address.grph_stereo.left_addr = - surface->public.address.grph_stereo.right_addr; + *addr = surface->address.grph_stereo.left_addr; + surface->address.grph_stereo.left_addr = + surface->address.grph_stereo.right_addr; return true; } else { if (pipe_ctx->stream->public.view_format != VIEW_3D_FORMAT_NONE && - surface->public.address.type != PLN_ADDR_TYPE_GRPH_STEREO) { - surface->public.address.type = PLN_ADDR_TYPE_GRPH_STEREO; - surface->public.address.grph_stereo.right_addr = - surface->public.address.grph_stereo.left_addr; + surface->address.type != PLN_ADDR_TYPE_GRPH_STEREO) { + surface->address.type = PLN_ADDR_TYPE_GRPH_STEREO; + surface->address.grph_stereo.right_addr = + surface->address.grph_stereo.left_addr; } } return false; @@ -972,22 +972,22 @@ static void update_plane_addr(const struct core_dc *dc, struct pipe_ctx *pipe_ct { bool addr_patched = false; PHYSICAL_ADDRESS_LOC addr; - struct core_surface *surface = pipe_ctx->surface; + struct dc_surface *surface = pipe_ctx->surface; if (surface == NULL) return; addr_patched = patch_address_for_sbs_tb_stereo(pipe_ctx, &addr); pipe_ctx->mi->funcs->mem_input_program_surface_flip_and_addr( pipe_ctx->mi, - &surface->public.address, - surface->public.flip_immediate); - surface->status.requested_address = surface->public.address; + &surface->address, + surface->flip_immediate); + surface->status.requested_address = surface->address; if (addr_patched) - pipe_ctx->surface->public.address.grph_stereo.left_addr = addr; + pipe_ctx->surface->address.grph_stereo.left_addr = addr; } static bool dcn10_set_input_transfer_func( - struct pipe_ctx *pipe_ctx, const struct core_surface *surface) + struct pipe_ctx *pipe_ctx, const struct dc_surface *surface) { struct input_pixel_processor *ipp = pipe_ctx->ipp; const struct dc_transfer_func *tf = NULL; @@ -996,12 +996,12 @@ static bool dcn10_set_input_transfer_func( if (ipp == NULL) return false; - if (surface->public.in_transfer_func) - tf = surface->public.in_transfer_func; + if (surface->in_transfer_func) + tf = surface->in_transfer_func; - if (surface->public.gamma_correction && dce_use_lut(surface)) + if (surface->gamma_correction && dce_use_lut(surface)) ipp->funcs->ipp_program_input_lut(ipp, - surface->public.gamma_correction); + surface->gamma_correction); if (tf == NULL) ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS); @@ -1594,7 +1594,7 @@ static void dcn10_power_on_fe( struct pipe_ctx *pipe_ctx, struct validate_context *context) { - struct dc_surface *dc_surface = &pipe_ctx->surface->public; + struct dc_surface *dc_surface = pipe_ctx->surface; struct dce_hwseq *hws = dc->hwseq; power_on_plane(dc->hwseq, @@ -1710,7 +1710,7 @@ static void program_csc_matrix(struct pipe_ctx *pipe_ctx, } static bool is_lower_pipe_tree_visible(struct pipe_ctx *pipe_ctx) { - if (pipe_ctx->surface->public.visible) + if (pipe_ctx->surface->visible) return true; if (pipe_ctx->bottom_pipe && is_lower_pipe_tree_visible(pipe_ctx->bottom_pipe)) return true; @@ -1719,7 +1719,7 @@ static bool is_lower_pipe_tree_visible(struct pipe_ctx *pipe_ctx) static bool is_upper_pipe_tree_visible(struct pipe_ctx *pipe_ctx) { - if (pipe_ctx->surface->public.visible) + if (pipe_ctx->surface->visible) return true; if (pipe_ctx->top_pipe && is_upper_pipe_tree_visible(pipe_ctx->top_pipe)) return true; @@ -1728,7 +1728,7 @@ static bool is_upper_pipe_tree_visible(struct pipe_ctx *pipe_ctx) static bool is_pipe_tree_visible(struct pipe_ctx *pipe_ctx) { - if (pipe_ctx->surface->public.visible) + if (pipe_ctx->surface->visible) return true; if (pipe_ctx->top_pipe && is_upper_pipe_tree_visible(pipe_ctx->top_pipe)) return true; @@ -1803,12 +1803,12 @@ static void update_dchubp_dpp( struct dce_hwseq *hws = dc->hwseq; struct mem_input *mi = pipe_ctx->mi; struct input_pixel_processor *ipp = pipe_ctx->ipp; - struct core_surface *surface = pipe_ctx->surface; - union plane_size size = surface->public.plane_size; + struct dc_surface *surface = pipe_ctx->surface; + union plane_size size = surface->plane_size; struct default_adjustment ocsc = {0}; struct tg_color black_color = {0}; struct mpcc_cfg mpcc_cfg; - bool per_pixel_alpha = surface->public.per_pixel_alpha && pipe_ctx->bottom_pipe; + bool per_pixel_alpha = surface->per_pixel_alpha && pipe_ctx->bottom_pipe; /* TODO: proper fix once fpga works */ /* depends on DML calculation, DPP clock value may change dynamically */ @@ -1841,12 +1841,12 @@ static void update_dchubp_dpp( if (dc->public.config.gpu_vm_support) mi->funcs->mem_input_program_pte_vm( pipe_ctx->mi, - surface->public.format, - &surface->public.tiling_info, - surface->public.rotation); + surface->format, + &surface->tiling_info, + surface->rotation); ipp->funcs->ipp_setup(ipp, - surface->public.format, + surface->format, 1, IPP_OUTPUT_FORMAT_12_BIT_FIX); @@ -1892,12 +1892,12 @@ static void update_dchubp_dpp( mi->funcs->mem_input_program_surface_config( mi, - surface->public.format, - &surface->public.tiling_info, + surface->format, + &surface->tiling_info, &size, - surface->public.rotation, - &surface->public.dcc, - surface->public.horizontal_mirror); + surface->rotation, + &surface->dcc, + surface->horizontal_mirror); mi->funcs->set_blank(mi, !is_pipe_tree_visible(pipe_ctx)); } @@ -1978,7 +1978,7 @@ static void dcn10_pplib_apply_display_requirements( static void dcn10_apply_ctx_for_surface( struct core_dc *dc, - struct core_surface *surface, + const struct dc_surface *surface, struct validate_context *context) { int i, be_idx; @@ -2337,7 +2337,7 @@ static bool dcn10_dummy_display_power_gating( void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx) { - struct core_surface *surface = pipe_ctx->surface; + struct dc_surface *surface = pipe_ctx->surface; struct timing_generator *tg = pipe_ctx->tg; if (surface->ctx->dc->debug.sanity_checks) { @@ -2355,7 +2355,7 @@ void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx) /* DCN we read INUSE address in MI, do we still need this wa? */ if (surface->status.is_flip_pending && - !surface->public.visible) { + !surface->visible) { pipe_ctx->mi->current_address = pipe_ctx->mi->request_address; BREAK_TO_DEBUGGER(); diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index cc65cfdea66f..07a1aec5a28b 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -40,23 +40,9 @@ struct core_stream; #define MAX_CLOCK_SOURCES 7 -/********* core_surface **********/ -#define DC_SURFACE_TO_CORE(dc_surface) \ - container_of(dc_surface, struct core_surface, public) - #define DC_GAMMA_TO_CORE(dc_gamma) \ container_of(dc_gamma, struct core_gamma, public) -struct core_surface { - struct dc_surface public; - struct dc_surface_status status; - struct dc_context *ctx; - - /* private to dc_surface.c */ - enum dc_irq_source irq_source; - int ref_count; -}; - struct core_gamma { struct dc_gamma public; struct dc_context *ctx; @@ -263,7 +249,7 @@ struct resource_pool { }; struct pipe_ctx { - struct core_surface *surface; + struct dc_surface *surface; struct core_stream *stream; struct mem_input *mi; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index d865df802c88..2343beb4ef87 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -59,7 +59,7 @@ struct hw_sequencer_funcs { void (*apply_ctx_for_surface)( struct core_dc *dc, - struct core_surface *surface, + const struct dc_surface *surface, struct validate_context *context); void (*set_plane_config)( @@ -88,7 +88,7 @@ struct hw_sequencer_funcs { bool (*set_input_transfer_func)( struct pipe_ctx *pipe_ctx, - const struct core_surface *surface); + const struct dc_surface *surface); bool (*set_output_transfer_func)( struct pipe_ctx *pipe_ctx, diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index 04e5fd1d8c89..ed94df16a2d3 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -119,7 +119,7 @@ struct pipe_ctx *resource_get_head_pipe_for_stream( const struct core_stream *stream); bool resource_attach_surfaces_to_context( - const struct dc_surface *const *surfaces, + struct dc_surface *const *surfaces, int surface_count, const struct dc_stream *dc_stream, struct validate_context *context, -- cgit From d0778ebfd58f5650de17531296ee5ecdde39ba68 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Sat, 22 Jul 2017 20:05:20 -0400 Subject: drm/amd/display: Roll core_link into dc_link Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 2 +- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 4 +- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.h | 2 +- drivers/gpu/drm/amd/display/dc/core/dc.c | 100 ++++---- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 229 +++++++++--------- drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c | 6 +- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 264 ++++++++++----------- drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 40 ++-- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 8 +- drivers/gpu/drm/amd/display/dc/core/dc_sink.c | 9 +- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 4 +- drivers/gpu/drm/amd/display/dc/dc.h | 112 ++++++--- drivers/gpu/drm/amd/display/dc/dc_ddc_types.h | 2 +- drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c | 4 +- .../gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 2 +- .../drm/amd/display/dc/dce100/dce100_resource.c | 2 +- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 16 +- .../drm/amd/display/dc/dce110/dce110_resource.c | 2 +- .../drm/amd/display/dc/dce112/dce112_resource.c | 2 +- .../gpu/drm/amd/display/dc/dce80/dce80_resource.c | 2 +- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 4 +- .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/inc/core_dc.h | 2 +- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 58 +---- drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h | 2 +- drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h | 16 +- drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h | 2 +- drivers/gpu/drm/amd/display/dc/inc/link_hwss.h | 22 +- .../gpu/drm/amd/display/include/logger_interface.h | 8 +- 29 files changed, 444 insertions(+), 484 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index 2bb2fc2a6566..c558f700df35 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -563,7 +563,7 @@ struct amdgpu_connector { /* The 'old' sink - before an HPD. * The 'current' sink is in dc_link->sink. */ const struct dc_sink *dc_sink; - const struct dc_link *dc_link; + struct dc_link *dc_link; const struct dc_sink *dc_em_sink; const struct dc_stream *stream; void *con_priv; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index b247904206ba..4885403f5cec 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -1874,7 +1874,7 @@ void amdgpu_dm_connector_init_helper( struct amdgpu_display_manager *dm, struct amdgpu_connector *aconnector, int connector_type, - const struct dc_link *link, + struct dc_link *link, int link_index) { struct amdgpu_device *adev = dm->ddev->dev_private; @@ -1997,7 +1997,7 @@ int amdgpu_dm_connector_init( int res = 0; int connector_type; struct dc *dc = dm->dc; - const struct dc_link *link = dc_get_link_at_index(dc, link_index); + struct dc_link *link = dc_get_link_at_index(dc, link_index); struct amdgpu_i2c_adapter *i2c; ((struct dc_link *)link)->priv = aconnector; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h index 115d9081d964..c565787cd782 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h @@ -114,7 +114,7 @@ void amdgpu_dm_connector_init_helper( struct amdgpu_display_manager *dm, struct amdgpu_connector *aconnector, int connector_type, - const struct dc_link *link, + struct dc_link *link, int link_index); int amdgpu_dm_connector_mode_valid( diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 569310ab116d..73740e2a5819 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -94,7 +94,7 @@ static bool create_links( for (i = 0; i < connectors_num; i++) { struct link_init_data link_init_params = {0}; - struct core_link *link; + struct dc_link *link; link_init_params.ctx = dc->ctx; /* next BIOS object table connector */ @@ -111,7 +111,7 @@ static bool create_links( } for (i = 0; i < num_virtual_links; i++) { - struct core_link *link = dm_alloc(sizeof(*link)); + struct dc_link *link = dm_alloc(sizeof(*link)); struct encoder_init_data enc_init = {0}; if (link == NULL) { @@ -121,7 +121,7 @@ static bool create_links( link->ctx = dc->ctx; link->dc = dc; - link->public.connector_signal = SIGNAL_TYPE_VIRTUAL; + link->connector_signal = SIGNAL_TYPE_VIRTUAL; link->link_id.type = OBJECT_TYPE_CONNECTOR; link->link_id.id = CONNECTOR_ID_VIRTUAL; link->link_id.enum_id = ENUM_ID_1; @@ -137,7 +137,7 @@ static bool create_links( enc_init.encoder.enum_id = ENUM_ID_1; virtual_link_encoder_construct(link->link_enc, &enc_init); - link->public.link_index = dc->link_count; + link->link_index = dc->link_count; dc->links[dc->link_count] = link; dc->link_count++; } @@ -278,14 +278,14 @@ static void set_drive_settings(struct dc *dc, int i; for (i = 0; i < core_dc->link_count; i++) { - if (&core_dc->links[i]->public == link) + if (core_dc->links[i] == link) break; } if (i >= core_dc->link_count) ASSERT_CRITICAL(false); - dc_link_dp_set_drive_settings(&core_dc->links[i]->public, lt_settings); + dc_link_dp_set_drive_settings(core_dc->links[i], lt_settings); } static void perform_link_training(struct dc *dc, @@ -297,20 +297,17 @@ static void perform_link_training(struct dc *dc, for (i = 0; i < core_dc->link_count; i++) dc_link_dp_perform_link_training( - &core_dc->links[i]->public, + core_dc->links[i], link_setting, skip_video_pattern); } static void set_preferred_link_settings(struct dc *dc, struct dc_link_settings *link_setting, - const struct dc_link *link) + struct dc_link *link) { - struct core_link *core_link = DC_LINK_TO_CORE(link); - - core_link->public.preferred_link_setting = - *link_setting; - dp_retrain_link_dp_test(core_link, link_setting, false); + link->preferred_link_setting = *link_setting; + dp_retrain_link_dp_test(link, link_setting, false); } static void enable_hpd(const struct dc_link *link) @@ -325,7 +322,7 @@ static void disable_hpd(const struct dc_link *link) static void set_test_pattern( - const struct dc_link *link, + struct dc_link *link, enum dp_test_pattern test_pattern, const struct link_training_settings *p_link_settings, const unsigned char *p_custom_pattern, @@ -345,9 +342,8 @@ void set_dither_option(const struct dc_stream *dc_stream, { struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); struct bit_depth_reduction_params params; - struct core_link *core_link = DC_LINK_TO_CORE(stream->status.link); - struct pipe_ctx *pipes = - core_link->dc->current_context->res_ctx.pipe_ctx; + struct dc_link *link = stream->status.link; + struct pipe_ctx *pipes = link->dc->current_context->res_ctx.pipe_ctx; memset(¶ms, 0, sizeof(params)); if (!stream) @@ -1693,10 +1689,10 @@ struct dc_stream *dc_get_stream_at_index(const struct dc *dc, uint8_t i) return NULL; } -const struct dc_link *dc_get_link_at_index(const struct dc *dc, uint32_t link_index) +struct dc_link *dc_get_link_at_index(const struct dc *dc, uint32_t link_index) { struct core_dc *core_dc = DC_TO_CORE(dc); - return &core_dc->links[link_index]->public; + return core_dc->links[link_index]; } const struct graphics_object_id dc_get_link_id_at_index( @@ -1710,7 +1706,7 @@ enum dc_irq_source dc_get_hpd_irq_source_at_index( struct dc *dc, uint32_t link_index) { struct core_dc *core_dc = DC_TO_CORE(dc); - return core_dc->links[link_index]->public.irq_source_hpd; + return core_dc->links[link_index]->irq_source_hpd; } const struct audio **dc_get_audios(struct dc *dc) @@ -1796,9 +1792,9 @@ bool dc_read_aux_dpcd( { struct core_dc *core_dc = DC_TO_CORE(dc); - struct core_link *link = core_dc->links[link_index]; + struct dc_link *link = core_dc->links[link_index]; enum ddc_result r = dal_ddc_service_read_dpcd_data( - link->public.ddc, + link->ddc, false, I2C_MOT_UNDEF, address, @@ -1815,10 +1811,10 @@ bool dc_write_aux_dpcd( uint32_t size) { struct core_dc *core_dc = DC_TO_CORE(dc); - struct core_link *link = core_dc->links[link_index]; + struct dc_link *link = core_dc->links[link_index]; enum ddc_result r = dal_ddc_service_write_dpcd_data( - link->public.ddc, + link->ddc, false, I2C_MOT_UNDEF, address, @@ -1837,9 +1833,9 @@ bool dc_read_aux_i2c( { struct core_dc *core_dc = DC_TO_CORE(dc); - struct core_link *link = core_dc->links[link_index]; + struct dc_link *link = core_dc->links[link_index]; enum ddc_result r = dal_ddc_service_read_dpcd_data( - link->public.ddc, + link->ddc, true, mot, address, @@ -1857,10 +1853,10 @@ bool dc_write_aux_i2c( uint32_t size) { struct core_dc *core_dc = DC_TO_CORE(dc); - struct core_link *link = core_dc->links[link_index]; + struct dc_link *link = core_dc->links[link_index]; enum ddc_result r = dal_ddc_service_write_dpcd_data( - link->public.ddc, + link->ddc, true, mot, address, @@ -1880,10 +1876,10 @@ bool dc_query_ddc_data( struct core_dc *core_dc = DC_TO_CORE(dc); - struct core_link *link = core_dc->links[link_index]; + struct dc_link *link = core_dc->links[link_index]; bool result = dal_ddc_service_query_ddc_data( - link->public.ddc, + link->ddc, address, write_buf, write_size, @@ -1900,8 +1896,8 @@ bool dc_submit_i2c( { struct core_dc *core_dc = DC_TO_CORE(dc); - struct core_link *link = core_dc->links[link_index]; - struct ddc_service *ddc = link->public.ddc; + struct dc_link *link = core_dc->links[link_index]; + struct ddc_service *ddc = link->ddc; return dal_i2caux_submit_i2c_command( ddc->ctx->i2caux, @@ -1909,10 +1905,8 @@ bool dc_submit_i2c( cmd); } -static bool link_add_remote_sink_helper(struct core_link *core_link, struct dc_sink *sink) +static bool link_add_remote_sink_helper(struct dc_link *dc_link, struct dc_sink *sink) { - struct dc_link *dc_link = &core_link->public; - if (dc_link->sink_count >= MAX_SINKS_PER_LINK) { BREAK_TO_DEBUGGER(); return false; @@ -1927,14 +1921,13 @@ static bool link_add_remote_sink_helper(struct core_link *core_link, struct dc_s } struct dc_sink *dc_link_add_remote_sink( - const struct dc_link *link, + struct dc_link *link, const uint8_t *edid, int len, struct dc_sink_init_data *init_data) { struct dc_sink *dc_sink; enum dc_edid_status edid_status; - struct core_link *core_link = DC_LINK_TO_LINK(link); if (len > MAX_EDID_BUFFER_SIZE) { dm_error("Max EDID buffer size breached!\n"); @@ -1960,12 +1953,12 @@ struct dc_sink *dc_link_add_remote_sink( dc_sink->dc_edid.length = len; if (!link_add_remote_sink_helper( - core_link, + link, dc_sink)) goto fail_add_sink; edid_status = dm_helpers_parse_edid_caps( - core_link->ctx, + link->ctx, &dc_sink->dc_edid, &dc_sink->edid_caps); @@ -1980,43 +1973,38 @@ fail_add_sink: return NULL; } -void dc_link_set_sink(const struct dc_link *link, struct dc_sink *sink) +void dc_link_set_sink(struct dc_link *link, struct dc_sink *sink) { - struct core_link *core_link = DC_LINK_TO_LINK(link); - struct dc_link *dc_link = &core_link->public; - - dc_link->local_sink = sink; + link->local_sink = sink; if (sink == NULL) { - dc_link->type = dc_connection_none; + link->type = dc_connection_none; } else { - dc_link->type = dc_connection_single; + link->type = dc_connection_single; } } -void dc_link_remove_remote_sink(const struct dc_link *link, const struct dc_sink *sink) +void dc_link_remove_remote_sink(struct dc_link *link, const struct dc_sink *sink) { int i; - struct core_link *core_link = DC_LINK_TO_LINK(link); - struct dc_link *dc_link = &core_link->public; if (!link->sink_count) { BREAK_TO_DEBUGGER(); return; } - for (i = 0; i < dc_link->sink_count; i++) { - if (dc_link->remote_sinks[i] == sink) { + for (i = 0; i < link->sink_count; i++) { + if (link->remote_sinks[i] == sink) { dc_sink_release(sink); - dc_link->remote_sinks[i] = NULL; + link->remote_sinks[i] = NULL; /* shrink array to remove empty place */ - while (i < dc_link->sink_count - 1) { - dc_link->remote_sinks[i] = dc_link->remote_sinks[i+1]; + while (i < link->sink_count - 1) { + link->remote_sinks[i] = link->remote_sinks[i+1]; i++; } - dc_link->remote_sinks[i] = NULL; - dc_link->sink_count--; + link->remote_sinks[i] = NULL; + link->sink_count--; return; } } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 036d22f878b8..428dbff8505b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -62,24 +62,24 @@ enum { /******************************************************************************* * Private functions ******************************************************************************/ -static void destruct(struct core_link *link) +static void destruct(struct dc_link *link) { int i; - if (link->public.ddc) - dal_ddc_service_destroy(&link->public.ddc); + if (link->ddc) + dal_ddc_service_destroy(&link->ddc); if(link->link_enc) link->link_enc->funcs->destroy(&link->link_enc); - if (link->public.local_sink) - dc_sink_release(link->public.local_sink); + if (link->local_sink) + dc_sink_release(link->local_sink); - for (i = 0; i < link->public.sink_count; ++i) - dc_sink_release(link->public.remote_sinks[i]); + for (i = 0; i < link->sink_count; ++i) + dc_sink_release(link->remote_sinks[i]); } -static struct gpio *get_hpd_gpio(const struct core_link *link) +static struct gpio *get_hpd_gpio(const struct dc_link *link) { enum bp_result bp_result; struct dc_bios *dcb = link->ctx->dc_bios; @@ -116,7 +116,7 @@ static struct gpio *get_hpd_gpio(const struct core_link *link) * true on success, false otherwise */ static bool program_hpd_filter( - const struct core_link *link) + const struct dc_link *link) { bool result = false; @@ -126,7 +126,7 @@ static bool program_hpd_filter( int delay_on_disconnect_in_ms = 0; /* Verify feature is supported */ - switch (link->public.connector_signal) { + switch (link->connector_signal) { case SIGNAL_TYPE_DVI_SINGLE_LINK: case SIGNAL_TYPE_DVI_DUAL_LINK: case SIGNAL_TYPE_HDMI_TYPE_A: @@ -181,7 +181,7 @@ static bool program_hpd_filter( return result; } -static bool detect_sink(struct core_link *link, enum dc_connection_type *type) +static bool detect_sink(struct dc_link *link, enum dc_connection_type *type) { uint32_t is_hpd_high = 0; struct gpio *hpd_pin; @@ -306,7 +306,7 @@ static enum signal_type get_basic_signal_type( * @brief * Check whether there is a dongle on DP connector */ -static bool is_dp_sink_present(struct core_link *link) +static bool is_dp_sink_present(struct dc_link *link) { enum gpio_result gpio_result; uint32_t clock_pin = 0; @@ -320,7 +320,7 @@ static bool is_dp_sink_present(struct core_link *link) ((connector_id == CONNECTOR_ID_DISPLAY_PORT) || (connector_id == CONNECTOR_ID_EDP)); - ddc = dal_ddc_service_get_ddc_pin(link->public.ddc); + ddc = dal_ddc_service_get_ddc_pin(link->ddc); if (!ddc) { BREAK_TO_DEBUGGER(); @@ -356,7 +356,7 @@ static bool is_dp_sink_present(struct core_link *link) * @brief * Detect output sink type */ -static enum signal_type link_detect_sink(struct core_link *link) +static enum signal_type link_detect_sink(struct dc_link *link) { enum signal_type result = get_basic_signal_type( link->link_enc->id, link->link_id); @@ -446,18 +446,18 @@ static enum signal_type dp_passive_dongle_detection( audio_support); } -static void link_disconnect_sink(struct core_link *link) +static void link_disconnect_sink(struct dc_link *link) { - if (link->public.local_sink) { - dc_sink_release(link->public.local_sink); - link->public.local_sink = NULL; + if (link->local_sink) { + dc_sink_release(link->local_sink); + link->local_sink = NULL; } link->dpcd_sink_count = 0; } static void detect_dp( - struct core_link *link, + struct dc_link *link, struct display_sink_capability *sink_caps, bool *converter_disable_audio, struct audio_support *audio_support, @@ -473,7 +473,7 @@ static void detect_dp( /* DP active dongles */ if (is_dp_active_dongle(link)) { - link->public.type = dc_connection_active_dongle; + link->type = dc_connection_active_dongle; if (!link->dpcd_caps.sink_count.bits.SINK_COUNT) { /* * active dongle unplug processing for short irq @@ -517,8 +517,8 @@ static void detect_dp( if (dm_helpers_dp_mst_start_top_mgr( link->ctx, - &link->public, boot)) { - link->public.type = dc_connection_mst_branch; + link, boot)) { + link->type = dc_connection_mst_branch; } else { /* MST not supported */ sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT; @@ -526,15 +526,14 @@ static void detect_dp( } } else { /* DP passive dongles */ - sink_caps->signal = dp_passive_dongle_detection(link->public.ddc, + sink_caps->signal = dp_passive_dongle_detection(link->ddc, sink_caps, audio_support); } } -bool dc_link_detect(const struct dc_link *dc_link, bool boot) +bool dc_link_detect(struct dc_link *link, bool boot) { - struct core_link *link = DC_LINK_TO_LINK(dc_link); struct dc_sink_init_data sink_init_data = { 0 }; struct display_sink_capability sink_caps = { 0 }; uint8_t i; @@ -546,7 +545,7 @@ bool dc_link_detect(const struct dc_link *dc_link, bool boot) struct core_sink *sink = NULL; enum dc_connection_type new_connection_type = dc_connection_none; - if (link->public.connector_signal == SIGNAL_TYPE_VIRTUAL) + if (link->connector_signal == SIGNAL_TYPE_VIRTUAL) return false; if (false == detect_sink(link, &new_connection_type)) { @@ -554,17 +553,17 @@ bool dc_link_detect(const struct dc_link *dc_link, bool boot) return false; } - if (link->public.connector_signal == SIGNAL_TYPE_EDP && - link->public.local_sink) + if (link->connector_signal == SIGNAL_TYPE_EDP && + link->local_sink) return true; link_disconnect_sink(link); if (new_connection_type != dc_connection_none) { - link->public.type = new_connection_type; + link->type = new_connection_type; /* From Disconnected-to-Connected. */ - switch (link->public.connector_signal) { + switch (link->connector_signal) { case SIGNAL_TYPE_HDMI_TYPE_A: { sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C; if (aud_support->hdmi_audio_native) @@ -602,14 +601,14 @@ bool dc_link_detect(const struct dc_link *dc_link, bool boot) aud_support, boot); /* Active dongle downstream unplug */ - if (link->public.type == dc_connection_active_dongle + if (link->type == dc_connection_active_dongle && link->dpcd_caps.sink_count. bits.SINK_COUNT == 0) return true; - if (link->public.type == dc_connection_mst_branch) { + if (link->type == dc_connection_mst_branch) { LINK_INFO("link=%d, mst branch is now Connected\n", - link->public.link_index); + link->link_index); return false; } @@ -618,7 +617,7 @@ bool dc_link_detect(const struct dc_link *dc_link, bool boot) default: DC_ERROR("Invalid connector type! signal:%d\n", - link->public.connector_signal); + link->connector_signal); return false; } /* switch() */ @@ -629,13 +628,13 @@ bool dc_link_detect(const struct dc_link *dc_link, bool boot) link->dpcd_sink_count = 1; dal_ddc_service_set_transaction_type( - link->public.ddc, + link->ddc, sink_caps.transaction_type); - link->public.aux_mode = dal_ddc_service_is_in_aux_transaction_mode( - link->public.ddc); + link->aux_mode = dal_ddc_service_is_in_aux_transaction_mode( + link->ddc); - sink_init_data.link = &link->public; + sink_init_data.link = link; sink_init_data.sink_signal = sink_caps.signal; dc_sink = dc_sink_create(&sink_init_data); @@ -648,11 +647,11 @@ bool dc_link_detect(const struct dc_link *dc_link, bool boot) dc_sink->converter_disable_audio = converter_disable_audio; sink = DC_SINK_TO_CORE(dc_sink); - link->public.local_sink = &sink->public; + link->local_sink = &sink->public; edid_status = dm_helpers_read_local_edid( link->ctx, - &link->public, + link, &sink->public); switch (edid_status) { @@ -719,21 +718,21 @@ bool dc_link_detect(const struct dc_link *dc_link, bool boot) } else { /* From Connected-to-Disconnected. */ - if (link->public.type == dc_connection_mst_branch) { + if (link->type == dc_connection_mst_branch) { LINK_INFO("link=%d, mst branch is now Disconnected\n", - link->public.link_index); - dm_helpers_dp_mst_stop_top_mgr(link->ctx, &link->public); + link->link_index); + dm_helpers_dp_mst_stop_top_mgr(link->ctx, link); link->mst_stream_alloc_table.stream_count = 0; memset(link->mst_stream_alloc_table.stream_allocations, 0, sizeof(link->mst_stream_alloc_table.stream_allocations)); } - link->public.type = dc_connection_none; + link->type = dc_connection_none; sink_caps.signal = SIGNAL_TYPE_NONE; } LINK_INFO("link=%d, dc_sink_in=%p is now %s\n", - link->public.link_index, &sink->public, + link->link_index, &sink->public, (sink_caps.signal == SIGNAL_TYPE_NONE ? "Disconnected":"Connected")); @@ -741,7 +740,7 @@ bool dc_link_detect(const struct dc_link *dc_link, bool boot) } static enum hpd_source_id get_hpd_line( - struct core_link *link) + struct dc_link *link) { struct gpio *hpd; enum hpd_source_id hpd_id = HPD_SOURCEID_UNKNOWN; @@ -779,12 +778,12 @@ static enum hpd_source_id get_hpd_line( return hpd_id; } -static enum channel_id get_ddc_line(struct core_link *link) +static enum channel_id get_ddc_line(struct dc_link *link) { struct ddc *ddc; enum channel_id channel = CHANNEL_ID_UNKNOWN; - ddc = dal_ddc_service_get_ddc_pin(link->public.ddc); + ddc = dal_ddc_service_get_ddc_pin(link->ddc); if (ddc) { switch (dal_ddc_get_line(ddc)) { @@ -887,7 +886,7 @@ static enum transmitter translate_encoder_to_transmitter( } static bool construct( - struct core_link *link, + struct dc_link *link, const struct link_init_data *init_params) { uint8_t i; @@ -899,14 +898,14 @@ static bool construct( struct dc_bios *bios = init_params->dc->ctx->dc_bios; const struct dc_vbios_funcs *bp_funcs = bios->funcs; - link->public.irq_source_hpd = DC_IRQ_SOURCE_INVALID; - link->public.irq_source_hpd_rx = DC_IRQ_SOURCE_INVALID; + link->irq_source_hpd = DC_IRQ_SOURCE_INVALID; + link->irq_source_hpd_rx = DC_IRQ_SOURCE_INVALID; link->link_status.dpcd_caps = &link->dpcd_caps; link->dc = init_params->dc; link->ctx = dc_ctx; - link->public.link_index = init_params->link_index; + link->link_index = init_params->link_index; link->link_id = bios->funcs->get_connector_id(bios, init_params->connector_index); @@ -919,35 +918,35 @@ static bool construct( hpd_gpio = get_hpd_gpio(link); if (hpd_gpio != NULL) - link->public.irq_source_hpd = dal_irq_get_source(hpd_gpio); + link->irq_source_hpd = dal_irq_get_source(hpd_gpio); switch (link->link_id.id) { case CONNECTOR_ID_HDMI_TYPE_A: - link->public.connector_signal = SIGNAL_TYPE_HDMI_TYPE_A; + link->connector_signal = SIGNAL_TYPE_HDMI_TYPE_A; break; case CONNECTOR_ID_SINGLE_LINK_DVID: case CONNECTOR_ID_SINGLE_LINK_DVII: - link->public.connector_signal = SIGNAL_TYPE_DVI_SINGLE_LINK; + link->connector_signal = SIGNAL_TYPE_DVI_SINGLE_LINK; break; case CONNECTOR_ID_DUAL_LINK_DVID: case CONNECTOR_ID_DUAL_LINK_DVII: - link->public.connector_signal = SIGNAL_TYPE_DVI_DUAL_LINK; + link->connector_signal = SIGNAL_TYPE_DVI_DUAL_LINK; break; case CONNECTOR_ID_DISPLAY_PORT: - link->public.connector_signal = SIGNAL_TYPE_DISPLAY_PORT; + link->connector_signal = SIGNAL_TYPE_DISPLAY_PORT; if (hpd_gpio != NULL) - link->public.irq_source_hpd_rx = + link->irq_source_hpd_rx = dal_irq_get_rx_source(hpd_gpio); break; case CONNECTOR_ID_EDP: - link->public.connector_signal = SIGNAL_TYPE_EDP; + link->connector_signal = SIGNAL_TYPE_EDP; if (hpd_gpio != NULL) { - link->public.irq_source_hpd = DC_IRQ_SOURCE_INVALID; - link->public.irq_source_hpd_rx = + link->irq_source_hpd = DC_IRQ_SOURCE_INVALID; + link->irq_source_hpd_rx = dal_irq_get_rx_source(hpd_gpio); } break; @@ -966,21 +965,21 @@ static bool construct( LINK_INFO("Connector[%d] description:" "signal %d\n", init_params->connector_index, - link->public.connector_signal); + link->connector_signal); ddc_service_init_data.ctx = link->ctx; ddc_service_init_data.id = link->link_id; ddc_service_init_data.link = link; - link->public.ddc = dal_ddc_service_create(&ddc_service_init_data); + link->ddc = dal_ddc_service_create(&ddc_service_init_data); - if (link->public.ddc == NULL) { + if (link->ddc == NULL) { DC_ERROR("Failed to create ddc_service!\n"); goto ddc_create_fail; } - link->public.ddc_hw_inst = + link->ddc_hw_inst = dal_ddc_get_line( - dal_ddc_service_get_ddc_pin(link->public.ddc)); + dal_ddc_service_get_ddc_pin(link->ddc)); enc_init_data.ctx = dc_ctx; bp_funcs->get_src_obj(dc_ctx->dc_bios, link->link_id, 0, &enc_init_data.encoder); @@ -988,7 +987,7 @@ static bool construct( enc_init_data.channel = get_ddc_line(link); enc_init_data.hpd_source = get_hpd_line(link); - link->public.hpd_src = enc_init_data.hpd_source; + link->hpd_src = enc_init_data.hpd_source; enc_init_data.transmitter = translate_encoder_to_transmitter(enc_init_data.encoder); @@ -1000,7 +999,7 @@ static bool construct( goto link_enc_create_fail; } - link->public.link_enc_hw_inst = link->link_enc->transmitter; + link->link_enc_hw_inst = link->link_enc->transmitter; for (i = 0; i < 4; i++) { if (BP_RESULT_OK != @@ -1015,10 +1014,10 @@ static bool construct( if (!bp_funcs->is_device_id_supported(dc_ctx->dc_bios, link->device_tag.dev_id)) continue; if (link->device_tag.dev_id.device_type == DEVICE_TYPE_CRT - && link->public.connector_signal != SIGNAL_TYPE_RGB) + && link->connector_signal != SIGNAL_TYPE_RGB) continue; if (link->device_tag.dev_id.device_type == DEVICE_TYPE_LCD - && link->public.connector_signal == SIGNAL_TYPE_RGB) + && link->connector_signal == SIGNAL_TYPE_RGB) continue; break; } @@ -1052,7 +1051,7 @@ static bool construct( device_tag_fail: link->link_enc->funcs->destroy(&link->link_enc); link_enc_create_fail: - dal_ddc_service_destroy(&link->public.ddc); + dal_ddc_service_destroy(&link->ddc); ddc_create_fail: create_fail: @@ -1066,9 +1065,9 @@ create_fail: /******************************************************************************* * Public functions ******************************************************************************/ -struct core_link *link_create(const struct link_init_data *init_params) +struct dc_link *link_create(const struct link_init_data *init_params) { - struct core_link *link = + struct dc_link *link = dm_alloc(sizeof(*link)); if (NULL == link) @@ -1086,7 +1085,7 @@ alloc_fail: return NULL; } -void link_destroy(struct core_link **link) +void link_destroy(struct dc_link **link) { destruct(*link); dm_free(*link); @@ -1094,7 +1093,7 @@ void link_destroy(struct core_link **link) } static void dpcd_configure_panel_mode( - struct core_link *link, + struct dc_link *link, enum dp_panel_mode panel_mode) { union dpcd_edp_config edp_config_set; @@ -1139,7 +1138,7 @@ static void dpcd_configure_panel_mode( dm_logger_write(link->ctx->logger, LOG_DETECTION_DP_CAPS, "Link: %d eDP panel mode supported: %d " "eDP panel mode enabled: %d \n", - link->public.link_index, + link->link_index, link->dpcd_caps.panel_mode_edp, panel_mode_edp); } @@ -1147,7 +1146,7 @@ static void dpcd_configure_panel_mode( static void enable_stream_features(struct pipe_ctx *pipe_ctx) { struct core_stream *stream = pipe_ctx->stream; - struct core_link *link = stream->sink->link; + struct dc_link *link = stream->sink->link; union down_spread_ctrl downspread; core_link_read_dpcd(link, DP_DOWNSPREAD_CTRL, @@ -1165,7 +1164,7 @@ static enum dc_status enable_link_dp(struct pipe_ctx *pipe_ctx) struct core_stream *stream = pipe_ctx->stream; enum dc_status status; bool skip_video_pattern; - struct core_link *link = stream->sink->link; + struct dc_link *link = stream->sink->link; struct dc_link_settings link_settings = {0}; enum dp_panel_mode panel_mode; enum dc_link_rate max_link_rate = LINK_RATE_HIGH2; @@ -1224,7 +1223,7 @@ static enum dc_status enable_link_dp(struct pipe_ctx *pipe_ctx) &link_settings, skip_video_pattern, LINK_TRAINING_ATTEMPTS)) { - link->public.cur_link_settings = link_settings; + link->cur_link_settings = link_settings; status = DC_OK; } else @@ -1237,12 +1236,12 @@ static enum dc_status enable_link_dp(struct pipe_ctx *pipe_ctx) static enum dc_status enable_link_dp_mst(struct pipe_ctx *pipe_ctx) { - struct core_link *link = pipe_ctx->stream->sink->link; + struct dc_link *link = pipe_ctx->stream->sink->link; /* sink signal type after MST branch is MST. Multiple MST sinks * share one link. Link DP PHY is enable or training only once. */ - if (link->public.cur_link_settings.lane_count != LANE_COUNT_UNKNOWN) + if (link->cur_link_settings.lane_count != LANE_COUNT_UNKNOWN) return DC_OK; /* set the sink to MST mode before enabling the link */ @@ -1254,16 +1253,16 @@ static enum dc_status enable_link_dp_mst(struct pipe_ctx *pipe_ctx) static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) { struct core_stream *stream = pipe_ctx->stream; - struct core_link *link = stream->sink->link; + struct dc_link *link = stream->sink->link; enum dc_color_depth display_color_depth; if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) dal_ddc_service_write_scdc_data( - stream->sink->link->public.ddc, + stream->sink->link->ddc, stream->phy_pix_clk, stream->public.timing.flags.LTE_340MCSC_SCRAMBLE); - memset(&stream->sink->link->public.cur_link_settings, 0, + memset(&stream->sink->link->cur_link_settings, 0, sizeof(struct dc_link_settings)); display_color_depth = stream->public.timing.display_color_depth; @@ -1279,7 +1278,7 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) stream->phy_pix_clk); if (pipe_ctx->stream->signal == SIGNAL_TYPE_HDMI_TYPE_A) - dal_ddc_service_read_scdc_data(link->public.ddc); + dal_ddc_service_read_scdc_data(link->ddc); } /****************************enable_link***********************************/ @@ -1321,7 +1320,7 @@ static enum dc_status enable_link(struct pipe_ctx *pipe_ctx) return status; } -static void disable_link(struct core_link *link, enum signal_type signal) +static void disable_link(struct dc_link *link, enum signal_type signal) { /* * TODO: implement call for dp_set_hw_test_pattern @@ -1345,7 +1344,7 @@ static void disable_link(struct core_link *link, enum signal_type signal) enum dc_status dc_link_validate_mode_timing( const struct core_stream *stream, - struct core_link *link, + struct dc_link *link, const struct dc_crtc_timing *timing) { uint32_t max_pix_clk = stream->sink->public.dongle_max_pix_clk; @@ -1353,7 +1352,7 @@ enum dc_status dc_link_validate_mode_timing( /* A hack to avoid failing any modes for EDID override feature on * topology change such as lower quality cable for DP or different dongle */ - if (link->public.remote_sinks[0]) + if (link->remote_sinks[0]) return DC_OK; if (0 != max_pix_clk && timing->pix_clk_khz > max_pix_clk) @@ -1376,10 +1375,9 @@ enum dc_status dc_link_validate_mode_timing( } -bool dc_link_set_backlight_level(const struct dc_link *dc_link, uint32_t level, +bool dc_link_set_backlight_level(const struct dc_link *link, uint32_t level, uint32_t frame_ramp, const struct dc_stream *stream) { - struct core_link *link = DC_LINK_TO_CORE(dc_link); struct core_dc *core_dc = DC_TO_CORE(link->ctx->dc); struct core_stream *core_stream = NULL; struct abm *abm = core_dc->res_pool->abm; @@ -1392,7 +1390,7 @@ bool dc_link_set_backlight_level(const struct dc_link *dc_link, uint32_t level, dm_logger_write(link->ctx->logger, LOG_BACKLIGHT, "New Backlight level: %d (0x%X)\n", level, level); - if (dc_is_embedded_signal(dc_link->connector_signal)) { + if (dc_is_embedded_signal(link->connector_signal)) { if (stream != NULL) { core_stream = DC_STREAM_TO_CORE(stream); for (i = 0; i < MAX_PIPES; i++) { @@ -1419,9 +1417,8 @@ bool dc_link_set_backlight_level(const struct dc_link *dc_link, uint32_t level, } -bool dc_link_set_abm_disable(const struct dc_link *dc_link) +bool dc_link_set_abm_disable(const struct dc_link *link) { - struct core_link *link = DC_LINK_TO_CORE(dc_link); struct core_dc *core_dc = DC_TO_CORE(link->ctx->dc); struct abm *abm = core_dc->res_pool->abm; @@ -1434,11 +1431,9 @@ bool dc_link_set_abm_disable(const struct dc_link *dc_link) } -bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable) +bool dc_link_set_psr_enable(const struct dc_link *link, bool enable) { - struct core_link *link = DC_LINK_TO_CORE(dc_link); - struct dc_context *ctx = link->ctx; - struct core_dc *core_dc = DC_TO_CORE(ctx->dc); + struct core_dc *core_dc = DC_TO_CORE(link->ctx->dc); struct dmcu *dmcu = core_dc->res_pool->dmcu; if (dmcu != NULL && link->psr_enabled) @@ -1447,11 +1442,9 @@ bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable) return true; } -bool dc_link_get_psr_state(const struct dc_link *dc_link, uint32_t *psr_state) +bool dc_link_get_psr_state(const struct dc_link *link, uint32_t *psr_state) { - struct core_link *link = DC_LINK_TO_CORE(dc_link); - struct dc_context *ctx = link->ctx; - struct core_dc *core_dc = DC_TO_CORE(ctx->dc); + struct core_dc *core_dc = DC_TO_CORE(link->ctx->dc); struct dmcu *dmcu = core_dc->res_pool->dmcu; if (dmcu != NULL && link->psr_enabled) @@ -1460,20 +1453,18 @@ bool dc_link_get_psr_state(const struct dc_link *dc_link, uint32_t *psr_state) return true; } -bool dc_link_setup_psr(const struct dc_link *dc_link, +bool dc_link_setup_psr(struct dc_link *link, const struct dc_stream *stream, struct psr_config *psr_config, struct psr_context *psr_context) { - struct core_link *link = DC_LINK_TO_CORE(dc_link); - struct dc_context *ctx = link->ctx; - struct core_dc *core_dc = DC_TO_CORE(ctx->dc); + struct core_dc *core_dc = DC_TO_CORE(link->ctx->dc); struct dmcu *dmcu = core_dc->res_pool->dmcu; struct core_stream *core_stream = DC_STREAM_TO_CORE(stream); int i; psr_context->controllerId = CONTROLLER_ID_UNDEFINED; - if (dc_link != NULL && + if (link != NULL && dmcu != NULL) { /* updateSinkPsrDpcdConfig*/ union dpcd_psr_configuration psr_configuration; @@ -1501,12 +1492,12 @@ bool dc_link_setup_psr(const struct dc_link *dc_link, dm_helpers_dp_write_dpcd( link->ctx, - dc_link, + link, 368, &psr_configuration.raw, sizeof(psr_configuration.raw)); - psr_context->channel = link->public.ddc->ddc_pin->hw_info.ddc_channel; + psr_context->channel = link->ddc->ddc_pin->hw_info.ddc_channel; psr_context->transmitterId = link->link_enc->transmitter; psr_context->engineId = link->link_enc->preferred_engine; @@ -1584,23 +1575,21 @@ bool dc_link_setup_psr(const struct dc_link *dc_link, } -const struct dc_link_status *dc_link_get_status(const struct dc_link *dc_link) +const struct dc_link_status *dc_link_get_status(const struct dc_link *link) { - struct core_link *link = DC_LINK_TO_CORE(dc_link); - return &link->link_status; } -void core_link_resume(struct core_link *link) +void core_link_resume(struct dc_link *link) { - if (link->public.connector_signal != SIGNAL_TYPE_VIRTUAL) + if (link->connector_signal != SIGNAL_TYPE_VIRTUAL) program_hpd_filter(link); } static struct fixed31_32 get_pbn_per_slot(struct core_stream *stream) { struct dc_link_settings *link_settings = - &stream->sink->link->public.cur_link_settings; + &stream->sink->link->cur_link_settings; uint32_t link_rate_in_mbps = link_settings->link_rate * LINK_RATE_REF_FREQ_IN_MHZ; struct fixed31_32 mbps = dal_fixed31_32_from_int( @@ -1653,7 +1642,7 @@ static struct fixed31_32 get_pbn_from_timing(struct pipe_ctx *pipe_ctx) } static void update_mst_stream_alloc_table( - struct core_link *link, + struct dc_link *link, struct stream_encoder *stream_enc, const struct dp_mst_stream_allocation_table *proposed_table) { @@ -1668,7 +1657,7 @@ static void update_mst_stream_alloc_table( ASSERT(proposed_table->stream_count - link->mst_stream_alloc_table.stream_count < 2); - /* copy proposed_table to core_link, add stream encoder */ + /* copy proposed_table to link, add stream encoder */ for (i = 0; i < proposed_table->stream_count; i++) { for (j = 0; j < link->mst_stream_alloc_table.stream_count; j++) { @@ -1707,7 +1696,7 @@ static void update_mst_stream_alloc_table( static enum dc_status allocate_mst_payload(struct pipe_ctx *pipe_ctx) { struct core_stream *stream = pipe_ctx->stream; - struct core_link *link = stream->sink->link; + struct dc_link *link = stream->sink->link; struct link_encoder *link_encoder = link->link_enc; struct stream_encoder *stream_encoder = pipe_ctx->stream_enc; struct dp_mst_stream_allocation_table proposed_table = {0}; @@ -1789,13 +1778,13 @@ static enum dc_status allocate_mst_payload(struct pipe_ctx *pipe_ctx) static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx) { struct core_stream *stream = pipe_ctx->stream; - struct core_link *link = stream->sink->link; + struct dc_link *link = stream->sink->link; struct link_encoder *link_encoder = link->link_enc; struct stream_encoder *stream_encoder = pipe_ctx->stream_enc; struct dp_mst_stream_allocation_table proposed_table = {0}; struct fixed31_32 avg_time_slots_per_mtp = dal_fixed31_32_from_int(0); uint8_t i; - bool mst_mode = (link->public.type == dc_connection_mst_branch); + bool mst_mode = (link->type == dc_connection_mst_branch); /* deallocate_mst_payload is called before disable link. When mode or * disable/enable monitor, new stream is created which is not in link @@ -1875,7 +1864,7 @@ void core_link_enable_stream(struct pipe_ctx *pipe_ctx) if (status != DC_OK) { dm_logger_write(pipe_ctx->stream->ctx->logger, LOG_WARNING, "enabling link %u failed: %d\n", - pipe_ctx->stream->sink->link->public.link_index, + pipe_ctx->stream->sink->link->link_index, status); /* Abort stream enable *unless* the failure was due to diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c index 2f5a89c5b063..d09e539397ea 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c @@ -354,7 +354,7 @@ static uint32_t defer_delay_converter_wa( struct ddc_service *ddc, uint32_t defer_delay) { - struct core_link *link = ddc->link; + struct dc_link *link = ddc->link; if (link->dpcd_caps.branch_dev_id == DP_BRANCH_DEVICE_ID_4 && !memcmp(link->dpcd_caps.branch_dev_name, @@ -423,7 +423,7 @@ static bool i2c_read( return dm_helpers_submit_i2c( ddc->ctx, - &ddc->link->public, + ddc->link, &command); } @@ -624,7 +624,7 @@ bool dal_ddc_service_query_ddc_data( ret = dm_helpers_submit_i2c( ddc->ctx, - &ddc->link->public, + ddc->link, &command); dal_ddc_i2c_payloads_destroy(&payloads); 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 e90b3ebc8347..c7b400786121 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 @@ -34,7 +34,7 @@ enum { }; static void wait_for_training_aux_rd_interval( - struct core_link* link, + struct dc_link *link, uint32_t default_wait_in_micro_secs) { union training_aux_rd_interval training_rd_interval; @@ -63,7 +63,7 @@ static void wait_for_training_aux_rd_interval( } static void dpcd_set_training_pattern( - struct core_link* link, + struct dc_link *link, union dpcd_training_pattern dpcd_pattern) { core_link_write_dpcd( @@ -80,7 +80,7 @@ static void dpcd_set_training_pattern( } static void dpcd_set_link_settings( - struct core_link* link, + struct dc_link *link, const struct link_training_settings *lt_settings) { uint8_t rate = (uint8_t) @@ -123,7 +123,7 @@ static void dpcd_set_link_settings( static enum dpcd_training_patterns hw_training_pattern_to_dpcd_training_pattern( - struct core_link* link, + struct dc_link *link, enum hw_dp_training_pattern pattern) { enum dpcd_training_patterns dpcd_tr_pattern = @@ -155,7 +155,7 @@ static enum dpcd_training_patterns } static void dpcd_set_lt_pattern_and_lane_settings( - struct core_link* link, + struct dc_link *link, const struct link_training_settings *lt_settings, enum hw_dp_training_pattern pattern) { @@ -246,7 +246,7 @@ static void dpcd_set_lt_pattern_and_lane_settings( dpcd_lt_buffer, size_in_bytes + sizeof(dpcd_pattern.raw) ); - link->public.cur_lane_setting = lt_settings->lane_settings[0]; + link->cur_lane_setting = lt_settings->lane_settings[0]; } static bool is_cr_done(enum dc_lane_count ln_count, @@ -419,7 +419,7 @@ static void find_max_drive_settings( } static void get_lane_status_and_drive_settings( - struct core_link* link, + struct dc_link *link, const struct link_training_settings *link_training_setting, union lane_status *ln_status, union lane_align_status_updated *ln_status_updated, @@ -500,7 +500,7 @@ static void get_lane_status_and_drive_settings( } static void dpcd_set_lane_settings( - struct core_link* link, + struct dc_link *link, const struct link_training_settings *link_training_setting) { union dpcd_training_lane dpcd_lane[LANE_COUNT_DP_MAX] = {{{0}}}; @@ -560,7 +560,7 @@ static void dpcd_set_lane_settings( dpcd_lane[0].bits.MAX_SWING_REACHED, dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED); - link->public.cur_lane_setting = link_training_setting->lane_settings[0]; + link->cur_lane_setting = link_training_setting->lane_settings[0]; } @@ -580,19 +580,18 @@ static bool is_max_vs_reached( } void dc_link_dp_set_drive_settings( - const struct dc_link *link, + struct dc_link *link, struct link_training_settings *lt_settings) { - struct core_link *core_link = DC_LINK_TO_CORE(link); /* program ASIC PHY settings*/ - dp_set_hw_lane_settings(core_link, lt_settings); + dp_set_hw_lane_settings(link, lt_settings); /* Notify DP sink the PHY settings from source */ - dpcd_set_lane_settings(core_link, lt_settings); + dpcd_set_lane_settings(link, lt_settings); } static bool perform_post_lt_adj_req_sequence( - struct core_link *link, + struct dc_link *link, struct link_training_settings *lt_settings) { enum dc_lane_count lane_count = @@ -656,7 +655,7 @@ static bool perform_post_lt_adj_req_sequence( update_drive_settings( lt_settings,req_settings); - dc_link_dp_set_drive_settings(&link->public, + dc_link_dp_set_drive_settings(link, lt_settings); break; } @@ -682,7 +681,7 @@ static bool perform_post_lt_adj_req_sequence( } -static enum hw_dp_training_pattern get_supported_tp(struct core_link *link) +static enum hw_dp_training_pattern get_supported_tp(struct dc_link *link) { enum hw_dp_training_pattern highest_tp = HW_DP_TRAINING_PATTERN_2; struct encoder_feature_support *features = &link->link_enc->features; @@ -706,7 +705,7 @@ static enum hw_dp_training_pattern get_supported_tp(struct core_link *link) } static enum link_training_result perform_channel_equalization_sequence( - struct core_link *link, + struct dc_link *link, struct link_training_settings *lt_settings) { struct link_training_settings req_settings; @@ -768,7 +767,7 @@ static enum link_training_result perform_channel_equalization_sequence( } static bool perform_clock_recovery_sequence( - struct core_link *link, + struct dc_link *link, struct link_training_settings *lt_settings) { uint32_t retries_cr; @@ -877,7 +876,7 @@ static bool perform_clock_recovery_sequence( } static inline bool perform_link_training_int( - struct core_link *link, + struct dc_link *link, struct link_training_settings *lt_settings, bool status) { @@ -923,7 +922,6 @@ enum link_training_result dc_link_dp_perform_link_training( bool skip_video_pattern) { enum link_training_result status = LINK_TRAINING_SUCCESS; - struct core_link *core_link = DC_LINK_TO_CORE(link); char *link_rate = "Unknown"; struct link_training_settings lt_settings; @@ -945,19 +943,19 @@ enum link_training_result dc_link_dp_perform_link_training( lt_settings.link_settings.link_spread = LINK_SPREAD_05_DOWNSPREAD_30KHZ; /* 1. set link rate, lane count and spread*/ - dpcd_set_link_settings(core_link, <_settings); + dpcd_set_link_settings(link, <_settings); /* 2. perform link training (set link training done * to false is done as well)*/ - if (!perform_clock_recovery_sequence(core_link, <_settings)) { + if (!perform_clock_recovery_sequence(link, <_settings)) { status = LINK_TRAINING_CR_FAIL; } else { - status = perform_channel_equalization_sequence(core_link, + status = perform_channel_equalization_sequence(link, <_settings); } if ((status == LINK_TRAINING_SUCCESS) || !skip_video_pattern) { - if (!perform_link_training_int(core_link, + if (!perform_link_training_int(link, <_settings, status == LINK_TRAINING_SUCCESS)) { /* the next link training setting in this case @@ -990,7 +988,7 @@ enum link_training_result dc_link_dp_perform_link_training( } /* Connectivity log: link training */ - CONN_MSG_LT(core_link, "%sx%d %s VS=%d, PE=%d", + CONN_MSG_LT(link, "%sx%d %s VS=%d, PE=%d", link_rate, lt_settings.link_settings.lane_count, (status == LINK_TRAINING_SUCCESS) ? "pass" : @@ -1004,7 +1002,7 @@ enum link_training_result dc_link_dp_perform_link_training( bool perform_link_training_with_retries( - struct core_link *link, + struct dc_link *link, const struct dc_link_settings *link_setting, bool skip_video_pattern, int attempts) @@ -1015,7 +1013,7 @@ bool perform_link_training_with_retries( for (j = 0; j < attempts; ++j) { if (dc_link_dp_perform_link_training( - &link->public, + link, link_setting, skip_video_pattern) == LINK_TRAINING_SUCCESS) return true; @@ -1027,7 +1025,7 @@ bool perform_link_training_with_retries( return false; } -static struct dc_link_settings get_max_link_cap(struct core_link *link) +static struct dc_link_settings get_max_link_cap(struct dc_link *link) { /* Set Default link settings */ struct dc_link_settings max_link_cap = {LANE_COUNT_FOUR, LINK_RATE_HIGH, @@ -1041,21 +1039,21 @@ static struct dc_link_settings get_max_link_cap(struct core_link *link) max_link_cap.link_rate = LINK_RATE_HIGH3; /* Lower link settings based on sink's link cap */ - if (link->public.reported_link_cap.lane_count < max_link_cap.lane_count) + if (link->reported_link_cap.lane_count < max_link_cap.lane_count) max_link_cap.lane_count = - link->public.reported_link_cap.lane_count; - if (link->public.reported_link_cap.link_rate < max_link_cap.link_rate) + link->reported_link_cap.lane_count; + if (link->reported_link_cap.link_rate < max_link_cap.link_rate) max_link_cap.link_rate = - link->public.reported_link_cap.link_rate; - if (link->public.reported_link_cap.link_spread < + link->reported_link_cap.link_rate; + if (link->reported_link_cap.link_spread < max_link_cap.link_spread) max_link_cap.link_spread = - link->public.reported_link_cap.link_spread; + link->reported_link_cap.link_spread; return max_link_cap; } bool dp_hbr_verify_link_cap( - struct core_link *link, + struct dc_link *link, struct dc_link_settings *known_limit_link_setting) { struct dc_link_settings max_link_cap = {0}; @@ -1080,7 +1078,7 @@ bool dp_hbr_verify_link_cap( * find the physical link capability */ /* disable PHY done possible by BIOS, will be done by driver itself */ - dp_disable_link_phy(link, link->public.connector_signal); + dp_disable_link_phy(link, link->connector_signal); dp_cs = link->dc->res_pool->dp_clock_source; @@ -1109,7 +1107,7 @@ bool dp_hbr_verify_link_cap( dp_enable_link_phy( link, - link->public.connector_signal, + link->connector_signal, dp_cs_id, cur); @@ -1117,7 +1115,7 @@ bool dp_hbr_verify_link_cap( success = true; else { status = dc_link_dp_perform_link_training( - &link->public, + link, cur, skip_video_pattern); if (status == LINK_TRAINING_SUCCESS) @@ -1125,13 +1123,13 @@ bool dp_hbr_verify_link_cap( } if (success) - link->public.verified_link_cap = *cur; + link->verified_link_cap = *cur; /* always disable the link before trying another * setting or before returning we'll enable it later * based on the actual mode we're driving */ - dp_disable_link_phy(link, link->public.connector_signal); + dp_disable_link_phy(link, link->connector_signal); } while (!success && decide_fallback_link_setting( initial_link_settings, cur, status)); @@ -1142,14 +1140,14 @@ bool dp_hbr_verify_link_cap( /* If all LT fails for all settings, * set verified = failed safe (1 lane low) */ - link->public.verified_link_cap.lane_count = LANE_COUNT_ONE; - link->public.verified_link_cap.link_rate = LINK_RATE_LOW; + link->verified_link_cap.lane_count = LANE_COUNT_ONE; + link->verified_link_cap.link_rate = LINK_RATE_LOW; - link->public.verified_link_cap.link_spread = + link->verified_link_cap.link_spread = LINK_SPREAD_DISABLED; } - link->public.max_link_setting = link->public.verified_link_cap; + link->max_link_setting = link->verified_link_cap; return success; } @@ -1391,7 +1389,7 @@ static uint32_t bandwidth_in_kbps_from_link_settings( } bool dp_validate_mode_timing( - struct core_link *link, + struct dc_link *link, const struct dc_crtc_timing *timing) { uint32_t req_bw; @@ -1406,12 +1404,12 @@ bool dp_validate_mode_timing( return true; /* We always use verified link settings */ - link_setting = &link->public.verified_link_cap; + link_setting = &link->verified_link_cap; /* TODO: DYNAMIC_VALIDATION needs to be implemented */ /*if (flags.DYNAMIC_VALIDATION == 1 && - link->public.verified_link_cap.lane_count != LANE_COUNT_UNKNOWN) - link_setting = &link->public.verified_link_cap; + link->verified_link_cap.lane_count != LANE_COUNT_UNKNOWN) + link_setting = &link->verified_link_cap; */ req_bw = bandwidth_in_kbps_from_timing(timing); @@ -1444,7 +1442,7 @@ void decide_link_settings(struct core_stream *stream, LANE_COUNT_ONE, LINK_RATE_LOW, LINK_SPREAD_DISABLED}; struct dc_link_settings current_link_setting = initial_link_setting; - struct core_link* link; + struct dc_link *link; uint32_t req_bw; uint32_t link_bw; @@ -1456,11 +1454,11 @@ void decide_link_settings(struct core_stream *stream, /* if preferred is specified through AMDDP, use it, if it's enough * to drive the mode */ - if (link->public.preferred_link_setting.lane_count != + if (link->preferred_link_setting.lane_count != LANE_COUNT_UNKNOWN && - link->public.preferred_link_setting.link_rate != + link->preferred_link_setting.link_rate != LINK_RATE_UNKNOWN) { - *link_setting = link->public.preferred_link_setting; + *link_setting = link->preferred_link_setting; return; } @@ -1469,7 +1467,7 @@ void decide_link_settings(struct core_stream *stream, * 2. could support the b/w requested by the timing */ while (current_link_setting.link_rate <= - link->public.max_link_setting.link_rate) { + link->max_link_setting.link_rate) { link_bw = bandwidth_in_kbps_from_link_settings( ¤t_link_setting); if (req_bw <= link_bw) { @@ -1478,7 +1476,7 @@ void decide_link_settings(struct core_stream *stream, } if (current_link_setting.lane_count < - link->public.max_link_setting.lane_count) { + link->max_link_setting.lane_count) { current_link_setting.lane_count = increase_lane_count( current_link_setting.lane_count); @@ -1492,16 +1490,15 @@ void decide_link_settings(struct core_stream *stream, } BREAK_TO_DEBUGGER(); - ASSERT(link->public.verified_link_cap.lane_count != - LANE_COUNT_UNKNOWN); + ASSERT(link->verified_link_cap.lane_count != LANE_COUNT_UNKNOWN); - *link_setting = link->public.verified_link_cap; + *link_setting = link->verified_link_cap; } /*************************Short Pulse IRQ***************************/ static bool hpd_rx_irq_check_link_loss_status( - struct core_link *link, + struct dc_link *link, union hpd_irq_data *hpd_irq_dpcd_data) { uint8_t irq_reg_rx_power_state; @@ -1514,7 +1511,7 @@ static bool hpd_rx_irq_check_link_loss_status( sink_status_changed = false; return_code = false; - if (link->public.cur_link_settings.lane_count == 0) + if (link->cur_link_settings.lane_count == 0) return return_code; /*1. Check that we can handle interrupt: Not in FS DOS, * Not in "Display Timeout" state, Link is trained. @@ -1538,7 +1535,7 @@ static bool hpd_rx_irq_check_link_loss_status( /*parse lane status*/ for (lane = 0; - lane < link->public.cur_link_settings.lane_count; + lane < link->cur_link_settings.lane_count; lane++) { /* check status of lanes 0,1 @@ -1577,7 +1574,7 @@ static bool hpd_rx_irq_check_link_loss_status( } static enum dc_status read_hpd_rx_irq_data( - struct core_link *link, + struct dc_link *link, union hpd_irq_data *irq_data) { /* The HW reads 16 bytes from 200h on HPD, @@ -1593,7 +1590,7 @@ static enum dc_status read_hpd_rx_irq_data( sizeof(union hpd_irq_data)); } -static bool allow_hpd_rx_irq(const struct core_link *link) +static bool allow_hpd_rx_irq(const struct dc_link *link) { /* * Don't handle RX IRQ unless one of following is met: @@ -1602,15 +1599,15 @@ static bool allow_hpd_rx_irq(const struct core_link *link) * 3) We know we're dealing with an active dongle */ - if ((link->public.cur_link_settings.lane_count != LANE_COUNT_UNKNOWN) || - (link->public.type == dc_connection_mst_branch) || + if ((link->cur_link_settings.lane_count != LANE_COUNT_UNKNOWN) || + (link->type == dc_connection_mst_branch) || is_dp_active_dongle(link)) return true; return false; } -static bool handle_hpd_irq_psr_sink(const struct core_link *link) +static bool handle_hpd_irq_psr_sink(const struct dc_link *link) { union dpcd_psr_configuration psr_configuration; @@ -1619,7 +1616,7 @@ static bool handle_hpd_irq_psr_sink(const struct core_link *link) dm_helpers_dp_read_dpcd( link->ctx, - &link->public, + link, 368,/*DpcdAddress_PSR_Enable_Cfg*/ &psr_configuration.raw, sizeof(psr_configuration.raw)); @@ -1632,7 +1629,7 @@ static bool handle_hpd_irq_psr_sink(const struct core_link *link) dm_helpers_dp_read_dpcd( link->ctx, - &link->public, + link, 0x2006, /*DpcdAddress_PSR_Error_Status*/ (unsigned char *) dpcdbuf, sizeof(dpcdbuf)); @@ -1647,14 +1644,14 @@ static bool handle_hpd_irq_psr_sink(const struct core_link *link) /* Acknowledge and clear error bits */ dm_helpers_dp_write_dpcd( link->ctx, - &link->public, + link, 8198,/*DpcdAddress_PSR_Error_Status*/ &psr_error_status.raw, sizeof(psr_error_status.raw)); /* PSR error, disable and re-enable PSR */ - dc_link_set_psr_enable(&link->public, false); - dc_link_set_psr_enable(&link->public, true); + dc_link_set_psr_enable(link, false); + dc_link_set_psr_enable(link, true); return true; } else if (psr_sink_psr_status.bits.SINK_SELF_REFRESH_STATUS == @@ -1670,7 +1667,7 @@ static bool handle_hpd_irq_psr_sink(const struct core_link *link) return false; } -static void dp_test_send_link_training(struct core_link *link) +static void dp_test_send_link_training(struct dc_link *link) { struct dc_link_settings link_settings = {0}; @@ -1686,13 +1683,13 @@ static void dp_test_send_link_training(struct core_link *link) 1); /* Set preferred link settings */ - link->public.verified_link_cap.lane_count = link_settings.lane_count; - link->public.verified_link_cap.link_rate = link_settings.link_rate; + link->verified_link_cap.lane_count = link_settings.lane_count; + link->verified_link_cap.link_rate = link_settings.link_rate; dp_retrain_link_dp_test(link, &link_settings, false); } -static void dp_test_send_phy_test_pattern(struct core_link *link) +static void dp_test_send_phy_test_pattern(struct dc_link *link) { union phy_test_pattern dpcd_test_pattern; union lane_adjust dpcd_lane_adjustment[2]; @@ -1771,10 +1768,10 @@ static void dp_test_send_phy_test_pattern(struct core_link *link) sizeof(test_80_bit_pattern)); /* prepare link training settings */ - link_settings.link = link->public.cur_link_settings; + link_settings.link = link->cur_link_settings; for (lane = 0; lane < - (unsigned int)(link->public.cur_link_settings.lane_count); + (unsigned int)(link->cur_link_settings.lane_count); lane++) { dpcd_lane_adjust.raw = get_nibble_at_index(&dpcd_lane_adjustment[0].raw, lane); @@ -1802,7 +1799,7 @@ static void dp_test_send_phy_test_pattern(struct core_link *link) * forward request to DS */ dc_link_dp_set_test_pattern( - &link->public, + link, test_pattern, &link_training_settings, test_80_bit_pattern, @@ -1810,7 +1807,7 @@ static void dp_test_send_phy_test_pattern(struct core_link *link) DP_TEST_80BIT_CUSTOM_PATTERN_7_0)+1); } -static void dp_test_send_link_test_pattern(struct core_link *link) +static void dp_test_send_link_test_pattern(struct dc_link *link) { union link_test_pattern dpcd_test_pattern; union test_misc dpcd_test_params; @@ -1850,14 +1847,14 @@ static void dp_test_send_link_test_pattern(struct core_link *link) } dc_link_dp_set_test_pattern( - &link->public, + link, test_pattern, NULL, NULL, 0); } -static void handle_automated_test(struct core_link *link) +static void handle_automated_test(struct dc_link *link) { union test_request test_request; union test_response test_response; @@ -1904,9 +1901,8 @@ static void handle_automated_test(struct core_link *link) sizeof(test_response)); } -bool dc_link_handle_hpd_rx_irq(const struct dc_link *dc_link, union hpd_irq_data *out_hpd_irq_dpcd_data) +bool dc_link_handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd_irq_dpcd_data) { - struct core_link *link = DC_LINK_TO_LINK(dc_link); union hpd_irq_data hpd_irq_dpcd_data = {{{{0}}}}; union device_service_irq device_service_clear = { { 0 } }; enum dc_status result = DDC_RESULT_UNKNOWN; @@ -1917,7 +1913,7 @@ bool dc_link_handle_hpd_rx_irq(const struct dc_link *dc_link, union hpd_irq_data dm_logger_write(link->ctx->logger, LOG_HW_HPD_IRQ, "%s: Got short pulse HPD on link %d\n", - __func__, link->public.link_index); + __func__, link->link_index); /* All the "handle_hpd_irq_xxx()" methods @@ -1951,7 +1947,7 @@ bool dc_link_handle_hpd_rx_irq(const struct dc_link *dc_link, union hpd_irq_data if (!allow_hpd_rx_irq(link)) { dm_logger_write(link->ctx->logger, LOG_HW_HPD_IRQ, "%s: skipping HPD handling on %d\n", - __func__, link->public.link_index); + __func__, link->link_index); return false; } @@ -1984,13 +1980,13 @@ bool dc_link_handle_hpd_rx_irq(const struct dc_link *dc_link, union hpd_irq_data "Status: "); perform_link_training_with_retries(link, - &link->public.cur_link_settings, + &link->cur_link_settings, true, LINK_TRAINING_ATTEMPTS); status = false; } - if (link->public.type == dc_connection_active_dongle && + if (link->type == dc_connection_active_dongle && hpd_irq_dpcd_data.bytes.sink_cnt.bits.SINK_COUNT != link->dpcd_sink_count) status = true; @@ -2010,7 +2006,7 @@ bool dc_link_handle_hpd_rx_irq(const struct dc_link *dc_link, union hpd_irq_data } /*query dpcd for version and mst cap addresses*/ -bool is_mst_supported(struct core_link *link) +bool is_mst_supported(struct dc_link *link) { bool mst = false; enum dc_status st = DC_OK; @@ -2034,7 +2030,7 @@ bool is_mst_supported(struct core_link *link) } -bool is_dp_active_dongle(const struct core_link *link) +bool is_dp_active_dongle(const struct dc_link *link) { enum display_dongle_type dongle_type = link->dpcd_caps.dongle_type; @@ -2044,14 +2040,14 @@ bool is_dp_active_dongle(const struct core_link *link) } static void get_active_converter_info( - uint8_t data, struct core_link *link) + uint8_t data, struct dc_link *link) { union dp_downstream_port_present ds_port = { .byte = data }; /* decode converter info*/ if (!ds_port.fields.PORT_PRESENT) { link->dpcd_caps.dongle_type = DISPLAY_DONGLE_NONE; - ddc_service_set_dongle_type(link->public.ddc, + ddc_service_set_dongle_type(link->ddc, link->dpcd_caps.dongle_type); return; } @@ -2121,7 +2117,7 @@ static void get_active_converter_info( } } - ddc_service_set_dongle_type(link->public.ddc, link->dpcd_caps.dongle_type); + ddc_service_set_dongle_type(link->ddc, link->dpcd_caps.dongle_type); { struct dp_device_vendor_id dp_id; @@ -2158,7 +2154,7 @@ static void get_active_converter_info( } } -static void dp_wa_power_up_0010FA(struct core_link *link, uint8_t *dpcd_data, +static void dp_wa_power_up_0010FA(struct dc_link *link, uint8_t *dpcd_data, int length) { int retry = 0; @@ -2199,7 +2195,7 @@ static void dp_wa_power_up_0010FA(struct core_link *link, uint8_t *dpcd_data, link->wa_flags.dp_keep_receiver_powered = false; } -static void retrieve_link_cap(struct core_link *link) +static void retrieve_link_cap(struct dc_link *link) { uint8_t dpcd_data[DP_TRAINING_AUX_RD_INTERVAL - DP_DPCD_REV + 1]; @@ -2253,11 +2249,11 @@ static void retrieve_link_cap(struct core_link *link) link->dpcd_caps.max_down_spread.raw = dpcd_data[ DP_MAX_DOWNSPREAD - DP_DPCD_REV]; - link->public.reported_link_cap.lane_count = + link->reported_link_cap.lane_count = link->dpcd_caps.max_ln_count.bits.MAX_LANE_COUNT; - link->public.reported_link_cap.link_rate = dpcd_data[ + link->reported_link_cap.link_rate = dpcd_data[ DP_MAX_LINK_RATE - DP_DPCD_REV]; - link->public.reported_link_cap.link_spread = + link->reported_link_cap.link_spread = link->dpcd_caps.max_down_spread.bits.MAX_DOWN_SPREAD ? LINK_SPREAD_05_DOWNSPREAD_30KHZ : LINK_SPREAD_DISABLED; @@ -2266,8 +2262,8 @@ static void retrieve_link_cap(struct core_link *link) link->dpcd_caps.panel_mode_edp = edp_config_cap.bits.ALT_SCRAMBLER_RESET; - link->public.test_pattern_enabled = false; - link->public.compliance_test_state.raw = 0; + link->test_pattern_enabled = false; + link->compliance_test_state.raw = 0; /* read sink count */ core_link_read_dpcd(link, @@ -2279,7 +2275,7 @@ static void retrieve_link_cap(struct core_link *link) CONN_DATA_DETECT(link, dpcd_data, sizeof(dpcd_data), "Rx Caps: "); } -void detect_dp_sink_caps(struct core_link *link) +void detect_dp_sink_caps(struct dc_link *link) { retrieve_link_cap(link); @@ -2291,18 +2287,17 @@ void detect_dp_sink_caps(struct core_link *link) */ if (is_mst_supported(link)) { - link->public.verified_link_cap = link->public.reported_link_cap; + link->verified_link_cap = link->reported_link_cap; } else { dp_hbr_verify_link_cap(link, - &link->public.reported_link_cap); + &link->reported_link_cap); } /* TODO save sink caps in link->sink */ } void dc_link_dp_enable_hpd(const struct dc_link *link) { - struct core_link *core_link = DC_LINK_TO_CORE(link); - struct link_encoder *encoder = core_link->link_enc; + struct link_encoder *encoder = link->link_enc; if (encoder != NULL && encoder->funcs->enable_hpd != NULL) encoder->funcs->enable_hpd(encoder); @@ -2310,8 +2305,7 @@ void dc_link_dp_enable_hpd(const struct dc_link *link) void dc_link_dp_disable_hpd(const struct dc_link *link) { - struct core_link *core_link = DC_LINK_TO_CORE(link); - struct link_encoder *encoder = core_link->link_enc; + struct link_encoder *encoder = link->link_enc; if (encoder != NULL && encoder->funcs->enable_hpd != NULL) encoder->funcs->disable_hpd(encoder); @@ -2327,7 +2321,7 @@ static bool is_dp_phy_pattern(enum dp_test_pattern test_pattern) return false; } -static void set_crtc_test_pattern(struct core_link *link, +static void set_crtc_test_pattern(struct dc_link *link, struct pipe_ctx *pipe_ctx, enum dp_test_pattern test_pattern) { @@ -2402,15 +2396,13 @@ static void set_crtc_test_pattern(struct core_link *link, } bool dc_link_dp_set_test_pattern( - const struct dc_link *link, + struct dc_link *link, enum dp_test_pattern test_pattern, const struct link_training_settings *p_link_settings, const unsigned char *p_custom_pattern, unsigned int cust_pattern_size) { - struct core_link *core_link = DC_LINK_TO_CORE(link); - struct pipe_ctx *pipes = - core_link->dc->current_context->res_ctx.pipe_ctx; + struct pipe_ctx *pipes = link->dc->current_context->res_ctx.pipe_ctx; struct pipe_ctx pipe_ctx = pipes[0]; unsigned int lane; unsigned int i; @@ -2421,7 +2413,7 @@ bool dc_link_dp_set_test_pattern( memset(&training_pattern, 0, sizeof(training_pattern)); for (i = 0; i < MAX_PIPES; i++) { - if (pipes[i].stream->sink->link == core_link) { + if (pipes[i].stream->sink->link == link) { pipe_ctx = pipes[i]; break; } @@ -2431,24 +2423,24 @@ bool dc_link_dp_set_test_pattern( * is VideoMode Reset DP Phy Test Pattern if it is currently running * and request is VideoMode */ - if (core_link->public.test_pattern_enabled && test_pattern == + if (link->test_pattern_enabled && test_pattern == DP_TEST_PATTERN_VIDEO_MODE) { /* Set CRTC Test Pattern */ - set_crtc_test_pattern(core_link, &pipe_ctx, test_pattern); - dp_set_hw_test_pattern(core_link, test_pattern, + set_crtc_test_pattern(link, &pipe_ctx, test_pattern); + dp_set_hw_test_pattern(link, test_pattern, (uint8_t *)p_custom_pattern, (uint32_t)cust_pattern_size); /* Unblank Stream */ - core_link->dc->hwss.unblank_stream( + link->dc->hwss.unblank_stream( &pipe_ctx, - &core_link->public.verified_link_cap); + &link->verified_link_cap); /* TODO:m_pHwss->MuteAudioEndpoint * (pPathMode->pDisplayPath, false); */ /* Reset Test Pattern state */ - core_link->public.test_pattern_enabled = false; + link->test_pattern_enabled = false; return true; } @@ -2457,8 +2449,8 @@ bool dc_link_dp_set_test_pattern( if (is_dp_phy_pattern(test_pattern)) { /* Set DPCD Lane Settings before running test pattern */ if (p_link_settings != NULL) { - dp_set_hw_lane_settings(core_link, p_link_settings); - dpcd_set_lane_settings(core_link, p_link_settings); + dp_set_hw_lane_settings(link, p_link_settings); + dpcd_set_lane_settings(link, p_link_settings); } /* Blank stream if running test pattern */ @@ -2471,15 +2463,15 @@ bool dc_link_dp_set_test_pattern( pipes->stream_enc->funcs->dp_blank(pipe_ctx.stream_enc); } - dp_set_hw_test_pattern(core_link, test_pattern, + dp_set_hw_test_pattern(link, test_pattern, (uint8_t *)p_custom_pattern, (uint32_t)cust_pattern_size); if (test_pattern != DP_TEST_PATTERN_VIDEO_MODE) { /* Set Test Pattern state */ - core_link->public.test_pattern_enabled = true; + link->test_pattern_enabled = true; if (p_link_settings != NULL) - dpcd_set_link_settings(core_link, + dpcd_set_link_settings(link, p_link_settings); } @@ -2516,7 +2508,7 @@ bool dc_link_dp_set_test_pattern( /*TODO:&& !pPathMode->pDisplayPath->IsTargetPoweredOn()*/) return false; - if (core_link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) { + if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) { /* tell receiver that we are sending qualification * pattern DP 1.2 or later - DP receiver's link quality * pattern is set using DPCD LINK_QUAL_LANEx_SET @@ -2526,12 +2518,12 @@ bool dc_link_dp_set_test_pattern( link_qual_pattern[lane] = (unsigned char)(pattern); - core_link_write_dpcd(core_link, + core_link_write_dpcd(link, DP_LINK_QUAL_LANE0_SET, link_qual_pattern, sizeof(link_qual_pattern)); - } else if (core_link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_10 || - core_link->dpcd_caps.dpcd_rev.raw == 0) { + } else if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_10 || + link->dpcd_caps.dpcd_rev.raw == 0) { /* tell receiver that we are sending qualification * pattern DP 1.1a or earlier - DP receiver's link * quality pattern is set using @@ -2539,27 +2531,25 @@ bool dc_link_dp_set_test_pattern( * register (0x102). We will use v_1.3 when we are * setting test pattern for DP 1.1. */ - core_link_read_dpcd(core_link, - DP_TRAINING_PATTERN_SET, - &training_pattern.raw, - sizeof(training_pattern)); + core_link_read_dpcd(link, DP_TRAINING_PATTERN_SET, + &training_pattern.raw, + sizeof(training_pattern)); training_pattern.v1_3.LINK_QUAL_PATTERN_SET = pattern; - core_link_write_dpcd(core_link, - DP_TRAINING_PATTERN_SET, - &training_pattern.raw, - sizeof(training_pattern)); + core_link_write_dpcd(link, DP_TRAINING_PATTERN_SET, + &training_pattern.raw, + sizeof(training_pattern)); } } else { /* CRTC Patterns */ - set_crtc_test_pattern(core_link, &pipe_ctx, test_pattern); + set_crtc_test_pattern(link, &pipe_ctx, test_pattern); /* Set Test Pattern state */ - core_link->public.test_pattern_enabled = true; + link->test_pattern_enabled = true; } return true; } -void dp_enable_mst_on_sink(struct core_link *link, bool enable) +void dp_enable_mst_on_sink(struct dc_link *link, bool enable) { unsigned char mstmCntl; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 0092e70b9efd..aac2420caefa 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -16,13 +16,13 @@ #include "dpcd_defs.h" enum dc_status core_link_read_dpcd( - struct core_link* link, + struct dc_link *link, uint32_t address, uint8_t *data, uint32_t size) { if (!dm_helpers_dp_read_dpcd(link->ctx, - &link->public, + link, address, data, size)) return DC_ERROR_UNEXPECTED; @@ -30,20 +30,20 @@ enum dc_status core_link_read_dpcd( } enum dc_status core_link_write_dpcd( - struct core_link* link, + struct dc_link *link, uint32_t address, const uint8_t *data, uint32_t size) { if (!dm_helpers_dp_write_dpcd(link->ctx, - &link->public, + link, address, data, size)) return DC_ERROR_UNEXPECTED; return DC_OK; } -void dp_receiver_power_ctrl(struct core_link *link, bool on) +void dp_receiver_power_ctrl(struct dc_link *link, bool on) { uint8_t state; @@ -54,7 +54,7 @@ void dp_receiver_power_ctrl(struct core_link *link, bool on) } void dp_enable_link_phy( - struct core_link *link, + struct dc_link *link, enum signal_type signal, enum clock_source_id clock_source, const struct dc_link_settings *link_settings) @@ -107,7 +107,7 @@ void dp_enable_link_phy( dp_receiver_power_ctrl(link, true); } -void dp_disable_link_phy(struct core_link *link, enum signal_type signal) +void dp_disable_link_phy(struct dc_link *link, enum signal_type signal) { if (!link->wa_flags.dp_keep_receiver_powered) dp_receiver_power_ctrl(link, false); @@ -120,11 +120,11 @@ void dp_disable_link_phy(struct core_link *link, enum signal_type signal) link->link_enc->funcs->disable_output(link->link_enc, signal); /* Clear current link setting.*/ - memset(&link->public.cur_link_settings, 0, - sizeof(link->public.cur_link_settings)); + memset(&link->cur_link_settings, 0, + sizeof(link->cur_link_settings)); } -void dp_disable_link_phy_mst(struct core_link *link, enum signal_type signal) +void dp_disable_link_phy_mst(struct dc_link *link, enum signal_type signal) { /* MST disable link only when no stream use the link */ if (link->mst_stream_alloc_table.stream_count > 0) @@ -137,7 +137,7 @@ void dp_disable_link_phy_mst(struct core_link *link, enum signal_type signal) } bool dp_set_hw_training_pattern( - struct core_link *link, + struct dc_link *link, enum hw_dp_training_pattern pattern) { enum dp_test_pattern test_pattern = DP_TEST_PATTERN_UNSUPPORTED; @@ -165,7 +165,7 @@ bool dp_set_hw_training_pattern( } void dp_set_hw_lane_settings( - struct core_link *link, + struct dc_link *link, const struct link_training_settings *link_settings) { struct link_encoder *encoder = link->link_enc; @@ -174,13 +174,13 @@ void dp_set_hw_lane_settings( encoder->funcs->dp_set_lane_settings(encoder, link_settings); } -enum dp_panel_mode dp_get_panel_mode(struct core_link *link) +enum dp_panel_mode dp_get_panel_mode(struct dc_link *link) { /* We need to explicitly check that connector * is not DP. Some Travis_VGA get reported * by video bios as DP. */ - if (link->public.connector_signal != SIGNAL_TYPE_DISPLAY_PORT) { + if (link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT) { switch (link->dpcd_caps.branch_dev_id) { case DP_BRANCH_DEVICE_ID_2: @@ -215,7 +215,7 @@ enum dp_panel_mode dp_get_panel_mode(struct core_link *link) } void dp_set_hw_test_pattern( - struct core_link *link, + struct dc_link *link, enum dp_test_pattern test_pattern, uint8_t *custom_pattern, uint32_t custom_pattern_size) @@ -231,7 +231,7 @@ void dp_set_hw_test_pattern( encoder->funcs->dp_set_phy_pattern(encoder, &pattern_param); } -void dp_retrain_link_dp_test(struct core_link *link, +void dp_retrain_link_dp_test(struct dc_link *link, struct dc_link_settings *link_setting, bool skip_video_pattern) { @@ -263,8 +263,8 @@ void dp_retrain_link_dp_test(struct core_link *link, SIGNAL_TYPE_DISPLAY_PORT); /* Clear current link setting. */ - memset(&link->public.cur_link_settings, 0, - sizeof(link->public.cur_link_settings)); + memset(&link->cur_link_settings, 0, + sizeof(link->cur_link_settings)); link->link_enc->funcs->enable_dp_output( link->link_enc, @@ -274,11 +274,11 @@ void dp_retrain_link_dp_test(struct core_link *link, dp_receiver_power_ctrl(link, true); dc_link_dp_perform_link_training( - &link->public, + link, link_setting, skip_video_pattern); - link->public.cur_link_settings = *link_setting; + link->cur_link_settings = *link_setting; link->dc->hwss.enable_stream(&pipes[i]); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 303c95432d5b..7a3d090f8465 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1269,7 +1269,7 @@ static struct stream_encoder *find_first_free_match_stream_enc_for_link( { int i; int j = -1; - struct core_link *link = stream->sink->link; + struct dc_link *link = stream->sink->link; for (i = 0; i < pool->stream_enc_count; i++) { if (!res_ctx->is_stream_enc_acquired[i] && @@ -1322,9 +1322,7 @@ static void update_stream_signal(struct core_stream *stream) const struct dc_sink *dc_sink = stream->public.sink; if (dc_sink->sink_signal == SIGNAL_TYPE_NONE) - stream->signal = - stream->sink->link-> - public.connector_signal; + stream->signal = stream->sink->link->connector_signal; else stream->signal = dc_sink->sink_signal; } else { @@ -1380,7 +1378,7 @@ static struct core_stream *find_pll_sharable_stream( if (resource_are_streams_timing_synchronizable( stream_needs_pll, stream_has_pll) && !dc_is_dp_signal(stream_has_pll->signal) - && stream_has_pll->sink->link->public.connector_signal + && stream_has_pll->sink->link->connector_signal != SIGNAL_TYPE_VIRTUAL) return stream_has_pll; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_sink.c b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c index da9955675fbf..7f0ba7267682 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_sink.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c @@ -54,15 +54,14 @@ static void destruct(struct sink *sink) static bool construct(struct sink *sink, const struct dc_sink_init_data *init_params) { - struct core_link *core_link = DC_LINK_TO_LINK(init_params->link); + struct dc_link *link = init_params->link; - if (!core_link) { + if (!link) return false; - } sink->protected.public.sink_signal = init_params->sink_signal; - sink->protected.link = core_link; - sink->protected.ctx = core_link->ctx; + sink->protected.link = link; + sink->protected.ctx = link->ctx; sink->protected.public.dongle_max_pix_clk = init_params->dongle_max_pix_clk; sink->protected.public.converter_disable_audio = init_params->converter_disable_audio; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 73712fd6f64a..a329709de360 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -91,7 +91,7 @@ static bool construct(struct core_stream *stream, /* EDID CAP translation for HDMI 2.0 */ stream->public.timing.flags.LTE_340MCSC_SCRAMBLE = dc_sink_data->edid_caps.lte_340mcsc_scramble; - stream->status.link = &stream->sink->link->public; + stream->status.link = stream->sink->link; return true; } @@ -355,5 +355,5 @@ void dc_stream_log( dm_logger_write(dm_logger, log_type, "\tlink: %d\n", - core_stream->sink->link->public.link_index); + core_stream->sink->link->link_index); } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index b14bad10db97..e15e8fb1eefe 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -31,6 +31,7 @@ #include "logger_types.h" #include "gpio_types.h" #include "link_service_types.h" +#include "grph_object_ctrl_defs.h" #define MAX_SURFACES 3 #define MAX_STREAMS 6 @@ -141,11 +142,11 @@ struct dc_link_funcs { bool skip_video_pattern); void (*set_preferred_link_settings)(struct dc *dc, struct dc_link_settings *link_setting, - const struct dc_link *link); + struct dc_link *link); void (*enable_hpd)(const struct dc_link *link); void (*disable_hpd)(const struct dc_link *link); void (*set_test_pattern)( - const struct dc_link *link, + struct dc_link *link, enum dp_test_pattern test_pattern, const struct link_training_settings *p_link_settings, const unsigned char *p_custom_pattern, @@ -641,7 +642,7 @@ struct dc_stream_status { /* * link this stream passes through */ - const struct dc_link *link; + struct dc_link *link; }; struct dc_stream_status *dc_stream_get_status( @@ -662,6 +663,50 @@ void dc_release_validate_context(struct validate_context *context); * Link Interfaces ******************************************************************************/ +struct dpcd_caps { + union dpcd_rev dpcd_rev; + union max_lane_count max_ln_count; + union max_down_spread max_down_spread; + + /* dongle type (DP converter, CV smart dongle) */ + enum display_dongle_type dongle_type; + /* Dongle's downstream count. */ + union sink_count sink_count; + /* If dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER, + indicates 'Frame Sequential-to-lllFrame Pack' conversion capability.*/ + struct dc_dongle_caps dongle_caps; + + uint32_t sink_dev_id; + uint32_t branch_dev_id; + int8_t branch_dev_name[6]; + int8_t branch_hw_revision; + + bool allow_invalid_MSA_timing_param; + bool panel_mode_edp; +}; + +struct dc_link_status { + struct dpcd_caps *dpcd_caps; +}; + +/* DP MST stream allocation (payload bandwidth number) */ +struct link_mst_stream_allocation { + /* DIG front */ + const struct stream_encoder *stream_enc; + /* associate DRM payload table with DC stream encoder */ + uint8_t vcp_id; + /* number of slots required for the DP stream in transport packet */ + uint8_t slot_count; +}; + +/* DP MST stream allocation table */ +struct link_mst_stream_allocation_table { + /* number of DP video streams */ + int stream_count; + /* array of stream allocations */ + struct link_mst_stream_allocation stream_allocations[MAX_CONTROLLER_NUM]; +}; + /* * A link contains one or more sinks and their connected status. * The currently active signal type (HDMI, DP-SST, DP-MST) is also reported. @@ -699,32 +744,31 @@ struct dc_link { struct ddc_service *ddc; bool aux_mode; -}; -struct dpcd_caps { - union dpcd_rev dpcd_rev; - union max_lane_count max_ln_count; - union max_down_spread max_down_spread; + /* Private to DC core */ - /* dongle type (DP converter, CV smart dongle) */ - enum display_dongle_type dongle_type; - /* Dongle's downstream count. */ - union sink_count sink_count; - /* If dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER, - indicates 'Frame Sequential-to-lllFrame Pack' conversion capability.*/ - struct dc_dongle_caps dongle_caps; + const struct core_dc *dc; - uint32_t sink_dev_id; - uint32_t branch_dev_id; - int8_t branch_dev_name[6]; - int8_t branch_hw_revision; + struct dc_context *ctx; - bool allow_invalid_MSA_timing_param; - bool panel_mode_edp; -}; + struct link_encoder *link_enc; + struct graphics_object_id link_id; + union ddi_channel_mapping ddi_channel_mapping; + struct connector_device_tag_info device_tag; + struct dpcd_caps dpcd_caps; + unsigned int dpcd_sink_count; + + enum edp_revision edp_revision; + bool psr_enabled; + + /* MST record stream using this link */ + struct link_flags { + bool dp_keep_receiver_powered; + } wa_flags; + struct link_mst_stream_allocation_table mst_stream_alloc_table; + + struct dc_link_status link_status; -struct dc_link_status { - struct dpcd_caps *dpcd_caps; }; const struct dc_link_status *dc_link_get_status(const struct dc_link *dc_link); @@ -734,7 +778,7 @@ const struct dc_link_status *dc_link_get_status(const struct dc_link *dc_link); * boot time. They cannot be created or destroyed. * Use dc_get_caps() to get number of links. */ -const struct dc_link *dc_get_link_at_index(const struct dc *dc, uint32_t link_index); +struct dc_link *dc_get_link_at_index(const struct dc *dc, uint32_t link_index); /* Return id of physical connector represented by a dc_link at link_index.*/ const struct graphics_object_id dc_get_link_id_at_index( @@ -750,7 +794,7 @@ bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable); bool dc_link_get_psr_state(const struct dc_link *dc_link, uint32_t *psr_state); -bool dc_link_setup_psr(const struct dc_link *dc_link, +bool dc_link_setup_psr(struct dc_link *dc_link, const struct dc_stream *stream, struct psr_config *psr_config, struct psr_context *psr_context); @@ -760,7 +804,7 @@ bool dc_link_setup_psr(const struct dc_link *dc_link, * true otherwise. True meaning further action is required (status update * and OS notification). */ -bool dc_link_detect(const struct dc_link *dc_link, bool boot); +bool dc_link_detect(struct dc_link *dc_link, bool boot); /* Notify DC about DP RX Interrupt (aka Short Pulse Interrupt). * Return: @@ -768,26 +812,26 @@ bool dc_link_detect(const struct dc_link *dc_link, bool boot); * detection. * false - no change in Downstream port status. No further action required * from DM. */ -bool dc_link_handle_hpd_rx_irq(const struct dc_link *dc_link, +bool dc_link_handle_hpd_rx_irq(struct dc_link *dc_link, union hpd_irq_data *hpd_irq_dpcd_data); struct dc_sink_init_data; struct dc_sink *dc_link_add_remote_sink( - const struct dc_link *dc_link, + struct dc_link *dc_link, const uint8_t *edid, int len, struct dc_sink_init_data *init_data); void dc_link_remove_remote_sink( - const struct dc_link *link, + struct dc_link *link, const struct dc_sink *sink); /* Used by diagnostics for virtual link at the moment */ -void dc_link_set_sink(const struct dc_link *link, struct dc_sink *sink); +void dc_link_set_sink(struct dc_link *link, struct dc_sink *sink); void dc_link_dp_set_drive_settings( - const struct dc_link *link, + struct dc_link *link, struct link_training_settings *lt_settings); enum link_training_result dc_link_dp_perform_link_training( @@ -800,7 +844,7 @@ void dc_link_dp_enable_hpd(const struct dc_link *link); void dc_link_dp_disable_hpd(const struct dc_link *link); bool dc_link_dp_set_test_pattern( - const struct dc_link *link, + struct dc_link *link, enum dp_test_pattern test_pattern, const struct link_training_settings *p_link_settings, const unsigned char *p_custom_pattern, @@ -844,7 +888,7 @@ const struct audio **dc_get_audios(struct dc *dc); struct dc_sink_init_data { enum signal_type sink_signal; - const struct dc_link *link; + struct dc_link *link; uint32_t dongle_max_pix_clk; bool converter_disable_audio; }; diff --git a/drivers/gpu/drm/amd/display/dc/dc_ddc_types.h b/drivers/gpu/drm/amd/display/dc/dc_ddc_types.h index b143fe88f49f..e1affeb5cc51 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_ddc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_ddc_types.h @@ -105,7 +105,7 @@ struct ddc_service { enum ddc_transaction_type transaction_type; enum display_dongle_type dongle_type; struct dc_context *ctx; - struct core_link *link; + struct dc_link *link; uint32_t address; uint32_t edid_buf_len; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c index 0fe3ee8e29d3..aaff946a6d0a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c @@ -142,7 +142,7 @@ static void dce_dmcu_set_psr_enable(struct dmcu *dmcu, bool enable) } static void dce_dmcu_setup_psr(struct dmcu *dmcu, - struct core_link *link, + struct dc_link *link, struct psr_context *psr_context) { struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); @@ -382,7 +382,7 @@ static void dcn10_dmcu_set_psr_enable(struct dmcu *dmcu, bool enable) } static void dcn10_dmcu_setup_psr(struct dmcu *dmcu, - struct core_link *link, + struct dc_link *link, struct psr_context *psr_context) { struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 5663d3dbd7d5..318673da189b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -1020,7 +1020,7 @@ bool dce110_link_encoder_validate_output_with_stream( case SIGNAL_TYPE_DVI_DUAL_LINK: is_valid = dce110_link_encoder_validate_dvi_output( enc110, - stream->sink->link->public.connector_signal, + stream->sink->link->connector_signal, pipe_ctx->stream->signal, &stream->public.timing); break; diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 716f664f40ce..6938158bed7f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -661,7 +661,7 @@ static enum dc_status validate_mapped_resource( for (i = 0; i < context->stream_count; i++) { struct core_stream *stream = context->streams[i]; - struct core_link *link = stream->sink->link; + struct dc_link *link = stream->sink->link; if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index cf6bf2098b7c..fe8084e290a3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -700,10 +700,10 @@ void dce110_update_info_frame(struct pipe_ctx *pipe_ctx) void dce110_enable_stream(struct pipe_ctx *pipe_ctx) { enum dc_lane_count lane_count = - pipe_ctx->stream->sink->link->public.cur_link_settings.lane_count; + pipe_ctx->stream->sink->link->cur_link_settings.lane_count; struct dc_crtc_timing *timing = &pipe_ctx->stream->public.timing; - struct core_link *link = pipe_ctx->stream->sink->link; + struct dc_link *link = pipe_ctx->stream->sink->link; /* 1. update AVI info frame (HDMI, DP) * we always need to update info frame @@ -746,7 +746,7 @@ void dce110_enable_stream(struct pipe_ctx *pipe_ctx) void dce110_disable_stream(struct pipe_ctx *pipe_ctx) { struct core_stream *stream = pipe_ctx->stream; - struct core_link *link = stream->sink->link; + struct dc_link *link = stream->sink->link; if (pipe_ctx->audio) { pipe_ctx->audio->funcs->az_disable(pipe_ctx->audio); @@ -1111,7 +1111,7 @@ static enum dc_status apply_single_controller_ctx_to_hw( dce110_update_info_frame(pipe_ctx); if (dc_is_dp_signal(pipe_ctx->stream->signal)) dce110_unblank_stream(pipe_ctx, - &stream->sink->link->public.cur_link_settings); + &stream->sink->link->cur_link_settings); } pipe_ctx->scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; @@ -2220,7 +2220,7 @@ static void init_hw(struct core_dc *dc) /* Power up AND update implementation according to the * required signal (which may be different from the * default signal on connector). */ - struct core_link *link = dc->links[i]; + struct dc_link *link = dc->links[i]; link->link_enc->funcs->hw_init(link->link_enc); } @@ -2283,11 +2283,11 @@ void dce110_fill_display_configs( cfg->transmitter = stream->sink->link->link_enc->transmitter; cfg->link_settings.lane_count = - stream->sink->link->public.cur_link_settings.lane_count; + stream->sink->link->cur_link_settings.lane_count; cfg->link_settings.link_rate = - stream->sink->link->public.cur_link_settings.link_rate; + stream->sink->link->cur_link_settings.link_rate; cfg->link_settings.link_spread = - stream->sink->link->public.cur_link_settings.link_spread; + stream->sink->link->cur_link_settings.link_spread; cfg->sym_clock = stream->phy_pix_clk; /* Round v_refresh*/ cfg->v_refresh = stream->public.timing.pix_clk_khz * 1000; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 0fcb1cf4b4ce..015306a6ef88 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -781,7 +781,7 @@ static enum dc_status validate_mapped_resource( for (i = 0; i < context->stream_count; i++) { struct core_stream *stream = context->streams[i]; - struct core_link *link = stream->sink->link; + struct dc_link *link = stream->sink->link; if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 80f067343a91..ca1e13e2a3db 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -730,7 +730,7 @@ static enum dc_status validate_mapped_resource( for (i = 0; i < context->stream_count; i++) { struct core_stream *stream = context->streams[i]; - struct core_link *link = stream->sink->link; + struct dc_link *link = stream->sink->link; if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 5861b3fdf7d2..b2319dbf3be3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -677,7 +677,7 @@ static enum dc_status validate_mapped_resource( for (i = 0; i < context->stream_count; i++) { struct core_stream *stream = context->streams[i]; - struct core_link *link = stream->sink->link; + struct dc_link *link = stream->sink->link; if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 4390023ca6dc..c25a39214111 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -628,7 +628,7 @@ static void dcn10_init_hw(struct core_dc *dc) * required signal (which may be different from the * default signal on connector). */ - struct core_link *link = dc->links[i]; + struct dc_link *link = dc->links[i]; link->link_enc->funcs->hw_init(link->link_enc); } @@ -2259,7 +2259,7 @@ static void dcn10_config_stereo_parameters( timing_3d_format == TIMING_3D_FORMAT_DP_HDMI_INBAND_FA || timing_3d_format == TIMING_3D_FORMAT_SIDEBAND_FA) { enum display_dongle_type dongle = \ - stream->sink->link->public.ddc->dongle_type; + stream->sink->link->ddc->dongle_type; if (dongle == DISPLAY_DONGLE_DP_VGA_CONVERTER || dongle == DISPLAY_DONGLE_DP_DVI_CONVERTER || dongle == DISPLAY_DONGLE_DP_HDMI_CONVERTER) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index eec0d5b22a9f..0110a431e289 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -845,7 +845,7 @@ static enum dc_status validate_mapped_resource( for (i = 0; i < context->stream_count; i++) { struct core_stream *stream = context->streams[i]; - struct core_link *link = stream->sink->link; + struct dc_link *link = stream->sink->link; if (old_context && resource_is_stream_unchanged(old_context, stream)) { if (stream != NULL && old_context->streams[i] != NULL) { diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_dc.h b/drivers/gpu/drm/amd/display/dc/inc/core_dc.h index 785236a44aee..1ecb54603e17 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_dc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_dc.h @@ -20,7 +20,7 @@ struct core_dc { struct dc_context *ctx; uint8_t link_count; - struct core_link *links[MAX_PIPES * 2]; + struct dc_link *links[MAX_PIPES * 2]; struct validate_context *current_context; struct resource_pool *res_pool; diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 07a1aec5a28b..6cdfeeba0faf 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -92,13 +92,11 @@ struct core_sink { /** The 'protected' area - read/write access, for use only inside DC **/ /* not used for now */ - struct core_link *link; + struct dc_link *link; struct dc_context *ctx; }; /************ link *****************/ -#define DC_LINK_TO_CORE(dc_link) container_of(dc_link, struct core_link, public) - struct link_init_data { const struct core_dc *dc; struct dc_context *ctx; /* TODO: remove 'dal' when DC is complete. */ @@ -107,61 +105,15 @@ struct link_init_data { TODO: remove it when DC is complete. */ }; -/* DP MST stream allocation (payload bandwidth number) */ -struct link_mst_stream_allocation { - /* DIG front */ - const struct stream_encoder *stream_enc; - /* associate DRM payload table with DC stream encoder */ - uint8_t vcp_id; - /* number of slots required for the DP stream in transport packet */ - uint8_t slot_count; -}; - -/* DP MST stream allocation table */ -struct link_mst_stream_allocation_table { - /* number of DP video streams */ - int stream_count; - /* array of stream allocations */ - struct link_mst_stream_allocation - stream_allocations[MAX_CONTROLLER_NUM]; -}; - -struct core_link { - struct dc_link public; - const struct core_dc *dc; - - struct dc_context *ctx; /* TODO: AUTO remove 'dal' when DC is complete*/ - - struct link_encoder *link_enc; - struct graphics_object_id link_id; - union ddi_channel_mapping ddi_channel_mapping; - struct connector_device_tag_info device_tag; - struct dpcd_caps dpcd_caps; - unsigned int dpcd_sink_count; - - enum edp_revision edp_revision; - bool psr_enabled; - - /* MST record stream using this link */ - struct link_flags { - bool dp_keep_receiver_powered; - } wa_flags; - struct link_mst_stream_allocation_table mst_stream_alloc_table; - - struct dc_link_status link_status; -}; - -#define DC_LINK_TO_LINK(dc_link) container_of(dc_link, struct core_link, public) - -struct core_link *link_create(const struct link_init_data *init_params); -void link_destroy(struct core_link **link); +struct dc_link *link_create(const struct link_init_data *init_params); +void link_destroy(struct dc_link **link); enum dc_status dc_link_validate_mode_timing( const struct core_stream *stream, - struct core_link *link, + struct dc_link *link, const struct dc_crtc_timing *timing); -void core_link_resume(struct core_link *link); +void core_link_resume(struct dc_link *link); void core_link_enable_stream(struct pipe_ctx *pipe_ctx); diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h index 9c2f670c3dc3..af7ea5eaf185 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h @@ -84,7 +84,7 @@ void dal_ddc_aux_payloads_add( struct ddc_service_init_data { struct graphics_object_id id; struct dc_context *ctx; - struct core_link *link; + struct dc_link *link; }; struct ddc_service *dal_ddc_service_create( diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h index b6ef1bfd267c..d9af028a39df 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h @@ -29,12 +29,12 @@ #define LINK_TRAINING_ATTEMPTS 4 #define LINK_TRAINING_RETRY_DELAY 50 /* ms */ -struct core_link; +struct dc_link; struct core_stream; struct dc_link_settings; bool dp_hbr_verify_link_cap( - struct core_link *link, + struct dc_link *link, struct dc_link_settings *known_limit_link_setting); bool decide_fallback_link_setting(struct dc_link_settings link_setting_init, @@ -46,7 +46,7 @@ struct dc_link_settings get_common_supported_link_settings ( struct dc_link_settings link_setting_b); bool dp_validate_mode_timing( - struct core_link *link, + struct dc_link *link, const struct dc_crtc_timing *timing); void decide_link_settings( @@ -54,17 +54,17 @@ void decide_link_settings( struct dc_link_settings *link_setting); bool perform_link_training_with_retries( - struct core_link *link, + struct dc_link *link, const struct dc_link_settings *link_setting, bool skip_video_pattern, int attempts); -bool is_mst_supported(struct core_link *link); +bool is_mst_supported(struct dc_link *link); -void detect_dp_sink_caps(struct core_link *link); +void detect_dp_sink_caps(struct dc_link *link); -bool is_dp_active_dongle(const struct core_link *link); +bool is_dp_active_dongle(const struct dc_link *link); -void dp_enable_mst_on_sink(struct core_link *link, bool enable); +void dp_enable_mst_on_sink(struct dc_link *link, bool enable); #endif /* __DC_LINK_DP_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h index 6067f464d805..e34b25939a98 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h @@ -39,7 +39,7 @@ struct dmcu_funcs { unsigned int bytes); void (*set_psr_enable)(struct dmcu *dmcu, bool enable); void (*setup_psr)(struct dmcu *dmcu, - struct core_link *link, + struct dc_link *link, struct psr_context *psr_context); void (*get_psr_state)(struct dmcu *dmcu, uint32_t *psr_state); void (*set_psr_wait_loop)(struct dmcu *dmcu, diff --git a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h index 75d10e93b002..f7994cfc850d 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h +++ b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h @@ -29,46 +29,46 @@ #include "inc/core_status.h" enum dc_status core_link_read_dpcd( - struct core_link* link, + struct dc_link *link, uint32_t address, uint8_t *data, uint32_t size); enum dc_status core_link_write_dpcd( - struct core_link* link, + struct dc_link *link, uint32_t address, const uint8_t *data, uint32_t size); void dp_enable_link_phy( - struct core_link *link, + struct dc_link *link, enum signal_type signal, enum clock_source_id clock_source, const struct dc_link_settings *link_settings); -void dp_receiver_power_ctrl(struct core_link *link, bool on); +void dp_receiver_power_ctrl(struct dc_link *link, bool on); -void dp_disable_link_phy(struct core_link *link, enum signal_type signal); +void dp_disable_link_phy(struct dc_link *link, enum signal_type signal); -void dp_disable_link_phy_mst(struct core_link *link, enum signal_type signal); +void dp_disable_link_phy_mst(struct dc_link *link, enum signal_type signal); bool dp_set_hw_training_pattern( - struct core_link *link, + struct dc_link *link, enum hw_dp_training_pattern pattern); void dp_set_hw_lane_settings( - struct core_link *link, + struct dc_link *link, const struct link_training_settings *link_settings); void dp_set_hw_test_pattern( - struct core_link *link, + struct dc_link *link, enum dp_test_pattern test_pattern, uint8_t *custom_pattern, uint32_t custom_pattern_size); -enum dp_panel_mode dp_get_panel_mode(struct core_link *link); +enum dp_panel_mode dp_get_panel_mode(struct dc_link *link); -void dp_retrain_link_dp_test(struct core_link *link, +void dp_retrain_link_dp_test(struct dc_link *link, struct dc_link_settings *link_setting, bool skip_video_pattern); diff --git a/drivers/gpu/drm/amd/display/include/logger_interface.h b/drivers/gpu/drm/amd/display/include/logger_interface.h index 6e6fd4e8fc00..3adf3cfc7aba 100644 --- a/drivers/gpu/drm/amd/display/include/logger_interface.h +++ b/drivers/gpu/drm/amd/display/include/logger_interface.h @@ -140,19 +140,19 @@ void context_clock_trace( */ #define CONN_DATA_DETECT(link, hex_data, hex_len, ...) \ - dc_conn_log(link->ctx, &link->public, hex_data, hex_len, \ + dc_conn_log(link->ctx, link, hex_data, hex_len, \ LOG_EVENT_DETECTION, ##__VA_ARGS__) #define CONN_DATA_LINK_LOSS(link, hex_data, hex_len, ...) \ - dc_conn_log(link->ctx, &link->public, hex_data, hex_len, \ + dc_conn_log(link->ctx, link, hex_data, hex_len, \ LOG_EVENT_LINK_LOSS, ##__VA_ARGS__) #define CONN_MSG_LT(link, ...) \ - dc_conn_log(link->ctx, &link->public, NULL, 0, \ + dc_conn_log(link->ctx, link, NULL, 0, \ LOG_EVENT_LINK_TRAINING, ##__VA_ARGS__) #define CONN_MSG_MODE(link, ...) \ - dc_conn_log(link->ctx, &link->public, NULL, 0, \ + dc_conn_log(link->ctx, link, NULL, 0, \ LOG_EVENT_MODE_SET, ##__VA_ARGS__) #endif /* __DAL_LOGGER_INTERFACE_H__ */ -- cgit From 89899039356a645c1cebe5a454d3577aa1f42bf2 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 24 Jul 2017 13:55:26 -0400 Subject: drm/amd/display: Roll sink struct into core_sink Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_sink.c | 43 +++++++++---------------- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 3 ++ 2 files changed, 18 insertions(+), 28 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_sink.c b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c index 7f0ba7267682..1f7985ad5dba 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_sink.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c @@ -27,31 +27,19 @@ #include "dm_helpers.h" #include "core_types.h" -/******************************************************************************* - * Private definitions - ******************************************************************************/ - -struct sink { - struct core_sink protected; - int ref_count; -}; - -#define DC_SINK_TO_SINK(dc_sink) \ - container_of(dc_sink, struct sink, protected.public) - /******************************************************************************* * Private functions ******************************************************************************/ -static void destruct(struct sink *sink) +static void destruct(struct core_sink *sink) { - if (sink->protected.public.dc_container_id) { - dm_free(sink->protected.public.dc_container_id); - sink->protected.public.dc_container_id = NULL; + if (sink->public.dc_container_id) { + dm_free(sink->public.dc_container_id); + sink->public.dc_container_id = NULL; } } -static bool construct(struct sink *sink, const struct dc_sink_init_data *init_params) +static bool construct(struct core_sink *sink, const struct dc_sink_init_data *init_params) { struct dc_link *link = init_params->link; @@ -59,13 +47,12 @@ static bool construct(struct sink *sink, const struct dc_sink_init_data *init_pa if (!link) return false; - sink->protected.public.sink_signal = init_params->sink_signal; - sink->protected.link = link; - sink->protected.ctx = link->ctx; - sink->protected.public.dongle_max_pix_clk = init_params->dongle_max_pix_clk; - sink->protected.public.converter_disable_audio = - init_params->converter_disable_audio; - sink->protected.public.dc_container_id = NULL; + sink->public.sink_signal = init_params->sink_signal; + sink->link = link; + sink->ctx = link->ctx; + sink->public.dongle_max_pix_clk = init_params->dongle_max_pix_clk; + sink->public.converter_disable_audio = init_params->converter_disable_audio; + sink->public.dc_container_id = NULL; return true; } @@ -76,7 +63,7 @@ static bool construct(struct sink *sink, const struct dc_sink_init_data *init_pa void dc_sink_retain(const struct dc_sink *dc_sink) { - struct sink *sink = DC_SINK_TO_SINK(dc_sink); + struct core_sink *sink = DC_SINK_TO_CORE(dc_sink); ASSERT(sink->ref_count > 0); ++sink->ref_count; @@ -84,7 +71,7 @@ void dc_sink_retain(const struct dc_sink *dc_sink) void dc_sink_release(const struct dc_sink *dc_sink) { - struct sink *sink = DC_SINK_TO_SINK(dc_sink); + struct core_sink *sink = DC_SINK_TO_CORE(dc_sink); ASSERT(sink->ref_count > 0); --sink->ref_count; @@ -97,7 +84,7 @@ void dc_sink_release(const struct dc_sink *dc_sink) struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params) { - struct sink *sink = dm_alloc(sizeof(*sink)); + struct core_sink *sink = dm_alloc(sizeof(*sink)); if (NULL == sink) goto alloc_fail; @@ -107,7 +94,7 @@ struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params) ++sink->ref_count; - return &sink->protected.public; + return &sink->public; construct_fail: dm_free(sink); diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 6cdfeeba0faf..eed31a827a90 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -94,6 +94,9 @@ struct core_sink { /* not used for now */ struct dc_link *link; struct dc_context *ctx; + + /* private to dc_sink.c */ + int ref_count; }; /************ link *****************/ -- cgit From b73a22d3257f9ec237c46be12d74b58d5a925d8c Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 24 Jul 2017 14:04:27 -0400 Subject: drm/amd/display: Roll core_sink into dc_sink Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 4 +- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 4 +- drivers/gpu/drm/amd/display/dc/core/dc.c | 4 +- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 60 +++++++++++----------- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_sink.c | 30 +++++------ drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 15 +++--- drivers/gpu/drm/amd/display/dc/dc.h | 19 ++++--- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 2 +- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 21 +------- 11 files changed, 72 insertions(+), 91 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index c558f700df35..8d939e3b3f15 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -562,9 +562,9 @@ struct amdgpu_connector { int num_modes; /* The 'old' sink - before an HPD. * The 'current' sink is in dc_link->sink. */ - const struct dc_sink *dc_sink; + struct dc_sink *dc_sink; struct dc_link *dc_link; - const struct dc_sink *dc_em_sink; + struct dc_sink *dc_em_sink; const struct dc_stream *stream; void *con_priv; bool dac_load_detect; 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 26fbadba97dd..696a4112c8d9 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -697,7 +697,7 @@ void amdgpu_dm_update_connector_after_detect( { struct drm_connector *connector = &aconnector->base; struct drm_device *dev = connector->dev; - const struct dc_sink *sink; + struct dc_sink *sink; /* MST handled by drm_mst framework */ if (aconnector->mst_mgr.mst_state == true) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 4885403f5cec..13708bcb83cd 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -1266,7 +1266,7 @@ int amdgpu_dm_connector_mode_valid( struct drm_display_mode *mode) { int result = MODE_ERROR; - const struct dc_sink *dc_sink; + struct dc_sink *dc_sink; struct amdgpu_device *adev = connector->dev->dev_private; struct dc_validation_set val_set = { 0 }; /* TODO: Unhardcode stream count */ @@ -1535,7 +1535,7 @@ int dm_create_validation_set_for_connector(struct drm_connector *connector, struct drm_display_mode *mode, struct dc_validation_set *val_set) { int result = MODE_ERROR; - const struct dc_sink *dc_sink = + struct dc_sink *dc_sink = to_amdgpu_connector(connector)->dc_sink; /* TODO: Unhardcode stream count */ struct dc_stream *stream; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 73740e2a5819..30374ffaae0b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -939,7 +939,7 @@ static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *c program_timing_sync(core_dc, context); for (i = 0; i < context->stream_count; i++) { - const struct core_sink *sink = context->streams[i]->sink; + const struct dc_sink *sink = context->streams[i]->sink; for (j = 0; j < context->stream_status[i].surface_count; j++) { const struct dc_surface *surface = @@ -1984,7 +1984,7 @@ void dc_link_set_sink(struct dc_link *link, struct dc_sink *sink) } } -void dc_link_remove_remote_sink(struct dc_link *link, const struct dc_sink *sink) +void dc_link_remove_remote_sink(struct dc_link *link, struct dc_sink *sink) { int i; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 428dbff8505b..e7062069d9a1 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -541,8 +541,7 @@ bool dc_link_detect(struct dc_link *link, bool boot) struct audio_support *aud_support = &link->dc->res_pool->audio_support; enum dc_edid_status edid_status; struct dc_context *dc_ctx = link->ctx; - struct dc_sink *dc_sink; - struct core_sink *sink = NULL; + struct dc_sink *sink; enum dc_connection_type new_connection_type = dc_connection_none; if (link->connector_signal == SIGNAL_TYPE_VIRTUAL) @@ -637,22 +636,21 @@ bool dc_link_detect(struct dc_link *link, bool boot) sink_init_data.link = link; sink_init_data.sink_signal = sink_caps.signal; - dc_sink = dc_sink_create(&sink_init_data); - if (!dc_sink) { + sink = dc_sink_create(&sink_init_data); + if (!sink) { DC_ERROR("Failed to create sink!\n"); return false; } - dc_sink->dongle_max_pix_clk = sink_caps.max_hdmi_pixel_clock; - dc_sink->converter_disable_audio = converter_disable_audio; + sink->dongle_max_pix_clk = sink_caps.max_hdmi_pixel_clock; + sink->converter_disable_audio = converter_disable_audio; - sink = DC_SINK_TO_CORE(dc_sink); - link->local_sink = &sink->public; + link->local_sink = sink; edid_status = dm_helpers_read_local_edid( link->ctx, link, - &sink->public); + sink); switch (edid_status) { case EDID_BAD_CHECKSUM: @@ -669,16 +667,16 @@ bool dc_link_detect(struct dc_link *link, bool boot) } /* HDMI-DVI Dongle */ - if (dc_sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A && - !dc_sink->edid_caps.edid_hdmi) - dc_sink->sink_signal = SIGNAL_TYPE_DVI_SINGLE_LINK; + if (sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A && + !sink->edid_caps.edid_hdmi) + sink->sink_signal = SIGNAL_TYPE_DVI_SINGLE_LINK; /* Connectivity log: detection */ - for (i = 0; i < sink->public.dc_edid.length / EDID_BLOCK_SIZE; i++) { + for (i = 0; i < sink->dc_edid.length / EDID_BLOCK_SIZE; i++) { CONN_DATA_DETECT(link, - &sink->public.dc_edid.raw_edid[i * EDID_BLOCK_SIZE], + &sink->dc_edid.raw_edid[i * EDID_BLOCK_SIZE], EDID_BLOCK_SIZE, - "%s: [Block %d] ", sink->public.edid_caps.display_name, i); + "%s: [Block %d] ", sink->edid_caps.display_name, i); } dm_logger_write(link->ctx->logger, LOG_DETECTION_EDID_PARSER, @@ -692,16 +690,16 @@ bool dc_link_detect(struct dc_link *link, bool boot) "speaker_flag = %d, " "audio_mode_count = %d\n", __func__, - sink->public.edid_caps.manufacturer_id, - sink->public.edid_caps.product_id, - sink->public.edid_caps.serial_number, - sink->public.edid_caps.manufacture_week, - sink->public.edid_caps.manufacture_year, - sink->public.edid_caps.display_name, - sink->public.edid_caps.speaker_flags, - sink->public.edid_caps.audio_mode_count); - - for (i = 0; i < sink->public.edid_caps.audio_mode_count; i++) { + sink->edid_caps.manufacturer_id, + sink->edid_caps.product_id, + sink->edid_caps.serial_number, + sink->edid_caps.manufacture_week, + sink->edid_caps.manufacture_year, + sink->edid_caps.display_name, + sink->edid_caps.speaker_flags, + sink->edid_caps.audio_mode_count); + + for (i = 0; i < sink->edid_caps.audio_mode_count; i++) { dm_logger_write(link->ctx->logger, LOG_DETECTION_EDID_PARSER, "%s: mode number = %d, " "format_code = %d, " @@ -710,10 +708,10 @@ bool dc_link_detect(struct dc_link *link, bool boot) "sample_size = %d\n", __func__, i, - sink->public.edid_caps.audio_modes[i].format_code, - sink->public.edid_caps.audio_modes[i].channel_count, - sink->public.edid_caps.audio_modes[i].sample_rate, - sink->public.edid_caps.audio_modes[i].sample_size); + sink->edid_caps.audio_modes[i].format_code, + sink->edid_caps.audio_modes[i].channel_count, + sink->edid_caps.audio_modes[i].sample_rate, + sink->edid_caps.audio_modes[i].sample_size); } } else { @@ -732,7 +730,7 @@ bool dc_link_detect(struct dc_link *link, bool boot) } LINK_INFO("link=%d, dc_sink_in=%p is now %s\n", - link->link_index, &sink->public, + link->link_index, sink, (sink_caps.signal == SIGNAL_TYPE_NONE ? "Disconnected":"Connected")); @@ -1347,7 +1345,7 @@ enum dc_status dc_link_validate_mode_timing( struct dc_link *link, const struct dc_crtc_timing *timing) { - uint32_t max_pix_clk = stream->sink->public.dongle_max_pix_clk; + uint32_t max_pix_clk = stream->sink->dongle_max_pix_clk; /* A hack to avoid failing any modes for EDID override feature on * topology change such as lower quality cable for DP or different dongle diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 7a3d090f8465..7cb572ff3cba 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1528,7 +1528,7 @@ enum dc_status resource_map_pool_resources( pipe_ctx->stream_enc); /* TODO: Add check if ASIC support and EDID audio */ - if (!stream->sink->public.converter_disable_audio && + if (!stream->sink->converter_disable_audio && dc_is_audio_capable_signal(pipe_ctx->stream->signal) && stream->public.audio_info.mode_count) { pipe_ctx->audio = find_first_free_audio( diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_sink.c b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c index 1f7985ad5dba..a83f1243a9d1 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_sink.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c @@ -31,15 +31,15 @@ * Private functions ******************************************************************************/ -static void destruct(struct core_sink *sink) +static void destruct(struct dc_sink *sink) { - if (sink->public.dc_container_id) { - dm_free(sink->public.dc_container_id); - sink->public.dc_container_id = NULL; + if (sink->dc_container_id) { + dm_free(sink->dc_container_id); + sink->dc_container_id = NULL; } } -static bool construct(struct core_sink *sink, const struct dc_sink_init_data *init_params) +static bool construct(struct dc_sink *sink, const struct dc_sink_init_data *init_params) { struct dc_link *link = init_params->link; @@ -47,12 +47,12 @@ static bool construct(struct core_sink *sink, const struct dc_sink_init_data *in if (!link) return false; - sink->public.sink_signal = init_params->sink_signal; + sink->sink_signal = init_params->sink_signal; sink->link = link; sink->ctx = link->ctx; - sink->public.dongle_max_pix_clk = init_params->dongle_max_pix_clk; - sink->public.converter_disable_audio = init_params->converter_disable_audio; - sink->public.dc_container_id = NULL; + sink->dongle_max_pix_clk = init_params->dongle_max_pix_clk; + sink->converter_disable_audio = init_params->converter_disable_audio; + sink->dc_container_id = NULL; return true; } @@ -61,18 +61,14 @@ static bool construct(struct core_sink *sink, const struct dc_sink_init_data *in * Public functions ******************************************************************************/ -void dc_sink_retain(const struct dc_sink *dc_sink) +void dc_sink_retain(struct dc_sink *sink) { - struct core_sink *sink = DC_SINK_TO_CORE(dc_sink); - ASSERT(sink->ref_count > 0); ++sink->ref_count; } -void dc_sink_release(const struct dc_sink *dc_sink) +void dc_sink_release(struct dc_sink *sink) { - struct core_sink *sink = DC_SINK_TO_CORE(dc_sink); - ASSERT(sink->ref_count > 0); --sink->ref_count; @@ -84,7 +80,7 @@ void dc_sink_release(const struct dc_sink *dc_sink) struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params) { - struct core_sink *sink = dm_alloc(sizeof(*sink)); + struct dc_sink *sink = dm_alloc(sizeof(*sink)); if (NULL == sink) goto alloc_fail; @@ -94,7 +90,7 @@ struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params) ++sink->ref_count; - return &sink->public; + return sink; construct_fail: dm_free(sink); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index a329709de360..5b356ddf5614 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -46,11 +46,11 @@ struct stream { ******************************************************************************/ static bool construct(struct core_stream *stream, - const struct dc_sink *dc_sink_data) + struct dc_sink *dc_sink_data) { uint32_t i = 0; - stream->sink = DC_SINK_TO_CORE(dc_sink_data); + stream->sink = dc_sink_data; stream->ctx = stream->sink->ctx; stream->public.sink = dc_sink_data; @@ -97,7 +97,7 @@ static bool construct(struct core_stream *stream, static void destruct(struct core_stream *stream) { - dc_sink_release(&stream->sink->public); + dc_sink_release(stream->sink); if (stream->public.out_transfer_func != NULL) { dc_transfer_func_release( stream->public.out_transfer_func); @@ -130,9 +130,8 @@ void dc_stream_release(const struct dc_stream *public) } struct dc_stream *dc_create_stream_for_sink( - const struct dc_sink *dc_sink) + struct dc_sink *sink) { - struct core_sink *sink = DC_SINK_TO_CORE(dc_sink); struct stream *stream; if (sink == NULL) @@ -143,7 +142,7 @@ struct dc_stream *dc_create_stream_for_sink( if (NULL == stream) goto alloc_fail; - if (false == construct(&stream->protected, dc_sink)) + if (false == construct(&stream->protected, sink)) goto construct_fail; stream->ref_count++; @@ -350,8 +349,8 @@ void dc_stream_log( dm_logger_write(dm_logger, log_type, "\tsink name: %s, serial: %d\n", - core_stream->sink->public.edid_caps.display_name, - core_stream->sink->public.edid_caps.serial_number); + core_stream->sink->edid_caps.display_name, + core_stream->sink->edid_caps.serial_number); dm_logger_write(dm_logger, log_type, "\tlink: %d\n", diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index e15e8fb1eefe..77bd54659a8b 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -629,7 +629,7 @@ bool dc_enable_stereo( /** * Create a new default stream for the requested sink */ -struct dc_stream *dc_create_stream_for_sink(const struct dc_sink *dc_sink); +struct dc_stream *dc_create_stream_for_sink(struct dc_sink *dc_sink); void dc_stream_retain(const struct dc_stream *dc_stream); void dc_stream_release(const struct dc_stream *dc_stream); @@ -712,9 +712,9 @@ struct link_mst_stream_allocation_table { * The currently active signal type (HDMI, DP-SST, DP-MST) is also reported. */ struct dc_link { - const struct dc_sink *remote_sinks[MAX_SINKS_PER_LINK]; + struct dc_sink *remote_sinks[MAX_SINKS_PER_LINK]; unsigned int sink_count; - const struct dc_sink *local_sink; + struct dc_sink *local_sink; unsigned int link_index; enum dc_connection_type type; enum signal_type connector_signal; @@ -825,7 +825,7 @@ struct dc_sink *dc_link_add_remote_sink( void dc_link_remove_remote_sink( struct dc_link *link, - const struct dc_sink *sink); + struct dc_sink *sink); /* Used by diagnostics for virtual link at the moment */ void dc_link_set_sink(struct dc_link *link, struct dc_sink *sink); @@ -879,10 +879,17 @@ struct dc_sink { void *priv; struct stereo_3d_features features_3d[TIMING_3D_FORMAT_MAX]; bool converter_disable_audio; + + /* private to DC core */ + struct dc_link *link; + struct dc_context *ctx; + + /* private to dc_sink.c */ + int ref_count; }; -void dc_sink_retain(const struct dc_sink *sink); -void dc_sink_release(const struct dc_sink *sink); +void dc_sink_retain(struct dc_sink *sink); +void dc_sink_release(struct dc_sink *sink); const struct audio **dc_get_audios(struct dc *dc); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index fe8084e290a3..58701fdb7c94 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -657,7 +657,7 @@ static enum dc_status bios_parser_crtc_source_select( * encoder block * note: video bios clears all FMT setting here. */ struct bp_crtc_source_select crtc_source_select = {0}; - const struct core_sink *sink = pipe_ctx->stream->sink; + const struct dc_sink *sink = pipe_ctx->stream->sink; crtc_source_select.engine_id = pipe_ctx->stream_enc->id; crtc_source_select.controller_id = pipe_ctx->pipe_idx + 1; diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index eed31a827a90..1d733c837854 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -68,7 +68,7 @@ struct core_stream { /* field internal to DC */ struct dc_context *ctx; - const struct core_sink *sink; + struct dc_sink *sink; /* used by DCP and FMT */ struct bit_depth_reduction_params bit_depth_params; @@ -80,25 +80,6 @@ struct core_stream { struct dc_stream_status status; }; -/************ core_sink *****************/ - -#define DC_SINK_TO_CORE(dc_sink) \ - container_of(dc_sink, struct core_sink, public) - -struct core_sink { - /** The public, read-only (for DM) area of sink. **/ - struct dc_sink public; - /** End-of-public area. **/ - - /** The 'protected' area - read/write access, for use only inside DC **/ - /* not used for now */ - struct dc_link *link; - struct dc_context *ctx; - - /* private to dc_sink.c */ - int ref_count; -}; - /************ link *****************/ struct link_init_data { const struct core_dc *dc; -- cgit From 0b0aab86d51ee63d521f0d96ff4dfe1d6252f9b2 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 24 Jul 2017 15:20:50 -0400 Subject: drm/amd/display: Roll gamma struct into core_gamma Signed-off-by: Harry Wentland Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_surface.c | 21 ++++----------------- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 3 +++ 2 files changed, 7 insertions(+), 17 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index 9a21ea71f4b3..a8b9515fd367 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -31,19 +31,6 @@ #include "core_dc.h" #include "transform.h" -/******************************************************************************* - * Private structures - ******************************************************************************/ -struct gamma { - struct core_gamma protected; - int ref_count; -}; - -#define DC_GAMMA_TO_GAMMA(dc_gamma) \ - container_of(dc_gamma, struct gamma, protected.public) -#define CORE_GAMMA_TO_GAMMA(core_gamma) \ - container_of(core_gamma, struct gamma, protected) - /******************************************************************************* * Private functions ******************************************************************************/ @@ -152,7 +139,7 @@ void dc_surface_release(struct dc_surface *surface) void dc_gamma_retain(const struct dc_gamma *dc_gamma) { - struct gamma *gamma = DC_GAMMA_TO_GAMMA(dc_gamma); + struct core_gamma *gamma = DC_GAMMA_TO_CORE(dc_gamma); ASSERT(gamma->ref_count > 0); ++gamma->ref_count; @@ -160,7 +147,7 @@ void dc_gamma_retain(const struct dc_gamma *dc_gamma) void dc_gamma_release(const struct dc_gamma **dc_gamma) { - struct gamma *gamma = DC_GAMMA_TO_GAMMA(*dc_gamma); + struct core_gamma *gamma = DC_GAMMA_TO_CORE(*dc_gamma); ASSERT(gamma->ref_count > 0); --gamma->ref_count; @@ -173,14 +160,14 @@ void dc_gamma_release(const struct dc_gamma **dc_gamma) struct dc_gamma *dc_create_gamma() { - struct gamma *gamma = dm_alloc(sizeof(*gamma)); + struct core_gamma *gamma = dm_alloc(sizeof(*gamma)); if (gamma == NULL) goto alloc_fail; ++gamma->ref_count; - return &gamma->protected.public; + return &gamma->public; alloc_fail: return NULL; diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 1d733c837854..43e9ada278d3 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -46,6 +46,9 @@ struct core_stream; struct core_gamma { struct dc_gamma public; struct dc_context *ctx; + + /* private to dc_surface.c */ + int ref_count; }; void enable_surface_flip_reporting(struct dc_surface *dc_surface, -- cgit From 7a6c4af6bf41516cc9e12d83cc8fcebfdd8be01c Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 24 Jul 2017 15:30:17 -0400 Subject: drm/amd/display: Roll core_gamma into dc_gamma Signed-off-by: Harry Wentland Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 6 ++---- drivers/gpu/drm/amd/display/dc/core/dc_surface.c | 22 +++++++++------------- drivers/gpu/drm/amd/display/dc/dc.h | 6 +++--- drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 7 +++++++ drivers/gpu/drm/amd/display/dc/inc/core_types.h | 11 ----------- 5 files changed, 21 insertions(+), 31 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 30374ffaae0b..d3873ac45cf3 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1500,12 +1500,10 @@ void dc_update_surfaces_and_stream(struct dc *dc, if (srf_updates[i].gamma && srf_updates[i].gamma != surface->gamma_correction) { if (surface->gamma_correction != NULL) - dc_gamma_release(&surface-> - gamma_correction); + dc_gamma_release(&surface->gamma_correction); dc_gamma_retain(srf_updates[i].gamma); - surface->gamma_correction = - srf_updates[i].gamma; + surface->gamma_correction = srf_updates[i].gamma; } if (srf_updates[i].in_transfer_func && diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index a8b9515fd367..eded6b7da97d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -137,37 +137,33 @@ void dc_surface_release(struct dc_surface *surface) } } -void dc_gamma_retain(const struct dc_gamma *dc_gamma) +void dc_gamma_retain(struct dc_gamma *gamma) { - struct core_gamma *gamma = DC_GAMMA_TO_CORE(dc_gamma); - ASSERT(gamma->ref_count > 0); ++gamma->ref_count; } -void dc_gamma_release(const struct dc_gamma **dc_gamma) +void dc_gamma_release(struct dc_gamma **gamma) { - struct core_gamma *gamma = DC_GAMMA_TO_CORE(*dc_gamma); - - ASSERT(gamma->ref_count > 0); - --gamma->ref_count; + ASSERT((*gamma)->ref_count > 0); + --(*gamma)->ref_count; - if (gamma->ref_count == 0) - dm_free(gamma); + if ((*gamma)->ref_count == 0) + dm_free((*gamma)); - *dc_gamma = NULL; + *gamma = NULL; } struct dc_gamma *dc_create_gamma() { - struct core_gamma *gamma = dm_alloc(sizeof(*gamma)); + struct dc_gamma *gamma = dm_alloc(sizeof(*gamma)); if (gamma == NULL) goto alloc_fail; ++gamma->ref_count; - return &gamma->public; + return gamma; alloc_fail: return NULL; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 77bd54659a8b..5523bb68f4e8 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -326,7 +326,7 @@ struct dc_surface { struct dc_plane_dcc_param dcc; struct dc_hdr_static_metadata hdr_static_ctx; - const struct dc_gamma *gamma_correction; + struct dc_gamma *gamma_correction; struct dc_transfer_func *in_transfer_func; enum dc_color_space color_space; @@ -394,8 +394,8 @@ const struct dc_surface_status *dc_surface_get_status( void dc_surface_retain(struct dc_surface *dc_surface); void dc_surface_release(struct dc_surface *dc_surface); -void dc_gamma_retain(const struct dc_gamma *dc_gamma); -void dc_gamma_release(const struct dc_gamma **dc_gamma); +void dc_gamma_retain(struct dc_gamma *dc_gamma); +void dc_gamma_release(struct dc_gamma **dc_gamma); struct dc_gamma *dc_create_gamma(void); void dc_transfer_func_retain(struct dc_transfer_func *dc_tf); diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index 05f030ee8cf0..4c5e797da5b1 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -415,6 +415,13 @@ struct dc_gamma { uint16_t red[INPUT_LUT_ENTRIES]; uint16_t green[INPUT_LUT_ENTRIES]; uint16_t blue[INPUT_LUT_ENTRIES]; + + /* private to DC core */ + struct dc_context *ctx; + + /* private to dc_surface.c */ + int ref_count; + }; /* Used by both ipp amd opp functions*/ diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 43e9ada278d3..5a47d4c94df6 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -40,17 +40,6 @@ struct core_stream; #define MAX_CLOCK_SOURCES 7 -#define DC_GAMMA_TO_CORE(dc_gamma) \ - container_of(dc_gamma, struct core_gamma, public) - -struct core_gamma { - struct dc_gamma public; - struct dc_context *ctx; - - /* private to dc_surface.c */ - int ref_count; -}; - void enable_surface_flip_reporting(struct dc_surface *dc_surface, uint32_t controller_id); -- cgit From ee356d8f4fff35510b83aa71299ddc0ccb798d58 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Mon, 24 Jul 2017 21:41:28 -0400 Subject: drm/amd/display: single PSR display not allow CSTATE sw w/a Description: HW issue when all the pipes are off, DCE_allow_cstate is 0. New sequence : blank OTG only instead of previous OTG_master_en=0) Signed-off-by: Charlene Liu Reviewed-by: Anthony Koo Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 6 ++++++ drivers/gpu/drm/amd/display/dc/dc_types.h | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index e7062069d9a1..fd2ae181cff2 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1548,6 +1548,12 @@ bool dc_link_setup_psr(struct dc_link *link, psr_context->psr_level.u32all = 0; +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + /*skip power down the single pipe since it blocks the cstate*/ + if (ASIC_REV_IS_RAVEN(link->ctx->asic_id.hw_internal_rev)) + psr_context->psr_level.bits.SKIP_SINGLE_OTG_DISABLE = true; +#endif + /* SMU will perform additional powerdown sequence. * For unsupported ASICs, set psr_level flag to skip PSR * static screen notification to SMU. diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index c7539fe36b66..99b893fbcb42 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -539,7 +539,8 @@ union dmcu_psr_level { unsigned int SKIP_SMU_NOTIFICATION:1; unsigned int SKIP_AUTO_STATE_ADVANCE:1; unsigned int DISABLE_PSR_ENTRY_ABORT:1; - unsigned int RESERVED:23; + unsigned int SKIP_SINGLE_OTG_DISABLE:1; + unsigned int RESERVED:22; } bits; unsigned int u32all; }; -- cgit From a74b27341e46aad3eb48a8c5eadc38b71f79cbce Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Sun, 23 Jul 2017 15:22:47 -0400 Subject: drm/amd/display: separate plane disable sequence - disconnect: trigger hw to disconnect plane on next vsync - disable: disables HW block and disable clocks - power_down: kill power Signed-off-by: Tony Cheng Reviewed-by: Eric Yang Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 83 ++++++++++++++++------ 1 file changed, 61 insertions(+), 22 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index c25a39214111..3a0fcaad84c2 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -815,8 +815,8 @@ static void reset_back_end_for_pipe( pipe_ctx->pipe_idx, pipe_ctx->tg->inst); } -static void plane_atomic_stop( - struct core_dc *dc, +/* trigger HW to start disconnect plane from stream on the next vsync */ +static void plane_atomic_disconnect(struct core_dc *dc, int fe_idx) { struct mpcc_cfg mpcc_cfg; @@ -824,6 +824,12 @@ static void plane_atomic_stop( struct transform *xfm = dc->res_pool->transforms[fe_idx]; struct mpcc *mpcc = dc->res_pool->mpcc[fe_idx]; struct timing_generator *tg = dc->res_pool->timing_generators[mpcc->opp_id]; + unsigned int opp_id = mpcc->opp_id; + int opp_id_cached = mpcc->opp_id; + + /*Already reset*/ + if (opp_id == 0xf) + return; mi->funcs->dcc_control(mi, false, false); @@ -833,11 +839,19 @@ static void plane_atomic_stop( mpcc_cfg.top_of_tree = tg->inst == mpcc->inst; mpcc->funcs->set(mpcc, &mpcc_cfg); + /* Hack to preserve old opp_id for plane_atomic_disable + * to find the correct otg */ + mpcc->opp_id = opp_id_cached; + + /* todo:call remove pipe from tree */ + /* flag mpcc idle pending */ + xfm->funcs->transform_reset(xfm); } -static void reset_front_end( - struct core_dc *dc, +/* disable HW used by plane. + * note: cannot disable until disconnect is complete */ +static void plane_atomic_disable(struct core_dc *dc, int fe_idx) { struct dce_hwseq *hws = dc->hwseq; @@ -846,24 +860,9 @@ static void reset_front_end( struct timing_generator *tg = dc->res_pool->timing_generators[mpcc->opp_id]; unsigned int opp_id = mpcc->opp_id; - /*Already reset*/ if (opp_id == 0xf) return; - tg->funcs->lock(tg); - - plane_atomic_stop(dc, fe_idx); - - REG_UPDATE(OTG_GLOBAL_SYNC_STATUS[tg->inst], VUPDATE_NO_LOCK_EVENT_CLEAR, 1); - tg->funcs->unlock(tg); - - if (dc->public.debug.sanity_checks) - verify_allow_pstate_change_high(dc->hwseq); - - if (tg->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS) - REG_WAIT(OTG_GLOBAL_SYNC_STATUS[tg->inst], - VUPDATE_NO_LOCK_EVENT_OCCURRED, 1, 20000, 200000); - mpcc->funcs->wait_for_idle(mpcc); mi->funcs->set_blank(mi, true); @@ -880,14 +879,54 @@ static void reset_front_end( REG_UPDATE(OPP_PIPE_CONTROL[opp_id], OPP_PIPE_CLOCK_EN, 0); - dm_logger_write(dc->ctx->logger, LOG_DC, - "Reset front end %d\n", - fe_idx); + mpcc->opp_id = 0xf; if (dc->public.debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); } +/* kill power to plane hw + * note: cannot power down until plane is disable +static void plane_atomic_power_down() +{ + +} +*/ + +static void reset_front_end( + struct core_dc *dc, + int fe_idx) +{ + struct dce_hwseq *hws = dc->hwseq; + struct mpcc *mpcc = dc->res_pool->mpcc[fe_idx]; + struct timing_generator *tg = dc->res_pool->timing_generators[mpcc->opp_id]; + unsigned int opp_id = mpcc->opp_id; + + /*Already reset*/ + if (opp_id == 0xf) + return; + + tg->funcs->lock(tg); + + plane_atomic_disconnect(dc, fe_idx); + + REG_UPDATE(OTG_GLOBAL_SYNC_STATUS[tg->inst], VUPDATE_NO_LOCK_EVENT_CLEAR, 1); + tg->funcs->unlock(tg); + + if (dc->public.debug.sanity_checks) + verify_allow_pstate_change_high(dc->hwseq); + + if (tg->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS) + REG_WAIT(OTG_GLOBAL_SYNC_STATUS[tg->inst], + VUPDATE_NO_LOCK_EVENT_OCCURRED, 1, 20000, 200000); + + plane_atomic_disable(dc, fe_idx); + + dm_logger_write(dc->ctx->logger, LOG_DC, + "Reset front end %d\n", + fe_idx); +} + static void dcn10_power_down_fe(struct core_dc *dc, int fe_idx) { struct dce_hwseq *hws = dc->hwseq; -- cgit From 6be425f3dc16bac797f300136b976bce46229784 Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Mon, 24 Jul 2017 10:47:02 -0400 Subject: drm/amd/display: break up plane disable and disconnect in set mode Signed-off-by: Eric Yang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 23 +++-- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 5 +- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 102 ++++++++++++++++++--- drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 4 +- 4 files changed, 111 insertions(+), 23 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index d3873ac45cf3..79218805754e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -932,7 +932,7 @@ static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *c for (i = 0; i < core_dc->res_pool->pipe_count; i++) { pipe = &context->res_ctx.pipe_ctx[i]; - core_dc->hwss.wait_for_mpcc_disconnect(core_dc->res_pool, pipe); + core_dc->hwss.wait_for_mpcc_disconnect(core_dc, core_dc->res_pool, pipe); } result = core_dc->hwss.apply_ctx_to_hw(core_dc, context); @@ -1364,6 +1364,16 @@ void dc_update_surfaces_and_stream(struct dc *dc, struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); struct dc_context *dc_ctx = core_dc->ctx; + /* Currently this function do not result in any HW programming + * when called with 0 surface. But proceeding will cause + * SW state to be updated in validate_context. So we might as + * well make it not do anything at all until the hw programming + * is implemented properly to handle 0 surface case. + * TODO: fix hw programming then remove this early return + */ + if (surface_count == 0) + return; + stream_status = dc_stream_get_status(dc_stream); ASSERT(stream_status); if (!stream_status) @@ -1535,15 +1545,10 @@ void dc_update_surfaces_and_stream(struct dc *dc, } if (update_type > UPDATE_TYPE_FAST) { - for (i = 0; i < surface_count; i++) { - for (j = 0; j < core_dc->res_pool->pipe_count; j++) { - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - - if (pipe_ctx->surface != srf_updates[i].surface) - continue; + for (j = 0; j < core_dc->res_pool->pipe_count; j++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - core_dc->hwss.wait_for_mpcc_disconnect(core_dc->res_pool, pipe_ctx); - } + core_dc->hwss.wait_for_mpcc_disconnect(core_dc, core_dc->res_pool, pipe_ctx); } } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 58701fdb7c94..aa4777a8ec36 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -2583,7 +2583,10 @@ static void dce110_power_down_fe(struct core_dc *dc, int fe_idx) dc->res_pool->transforms[fe_idx]); } -static void dce110_wait_for_mpcc_disconnect(struct resource_pool *res_pool, struct pipe_ctx *pipe_ctx) +static void dce110_wait_for_mpcc_disconnect( + struct core_dc *dc, + struct resource_pool *res_pool, + struct pipe_ctx *pipe_ctx) { /* do nothing*/ } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 3a0fcaad84c2..bbe3e8705405 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -831,21 +831,32 @@ static void plane_atomic_disconnect(struct core_dc *dc, if (opp_id == 0xf) return; + if (dc->public.debug.sanity_checks) + verify_allow_pstate_change_high(dc->hwseq); + mi->funcs->dcc_control(mi, false, false); + if (dc->public.debug.sanity_checks) + verify_allow_pstate_change_high(dc->hwseq); + mpcc_cfg.opp_id = 0xf; mpcc_cfg.top_dpp_id = 0xf; mpcc_cfg.bot_mpcc_id = 0xf; mpcc_cfg.top_of_tree = tg->inst == mpcc->inst; mpcc->funcs->set(mpcc, &mpcc_cfg); - /* Hack to preserve old opp_id for plane_atomic_disable - * to find the correct otg */ + /* + * Hack to preserve old opp_id for plane_atomic_disable + * to find the correct otg + */ mpcc->opp_id = opp_id_cached; /* todo:call remove pipe from tree */ /* flag mpcc idle pending */ + /*dm_logger_write(dc->ctx->logger, LOG_ERROR, + "[debug_mpo: plane_atomic_disconnect pending on mpcc %d]\n", + fe_idx);*/ xfm->funcs->transform_reset(xfm); } @@ -864,6 +875,10 @@ static void plane_atomic_disable(struct core_dc *dc, return; mpcc->funcs->wait_for_idle(mpcc); + dc->res_pool->opps[opp_id]->mpcc_disconnect_pending[mpcc->inst] = false; + /*dm_logger_write(dc->ctx->logger, LOG_ERROR, + "[debug_mpo: atomic disable finished on mpcc %d]\n", + fe_idx);*/ mi->funcs->set_blank(mi, true); @@ -885,13 +900,27 @@ static void plane_atomic_disable(struct core_dc *dc, verify_allow_pstate_change_high(dc->hwseq); } -/* kill power to plane hw +/* + * kill power to plane hw * note: cannot power down until plane is disable -static void plane_atomic_power_down() + */ +static void plane_atomic_power_down(struct core_dc *dc, int fe_idx) { + struct dce_hwseq *hws = dc->hwseq; + + REG_SET(DC_IP_REQUEST_CNTL, 0, + IP_REQUEST_EN, 1); + dpp_pg_control(hws, fe_idx, false); + hubp_pg_control(hws, fe_idx, false); + REG_SET(DC_IP_REQUEST_CNTL, 0, + IP_REQUEST_EN, 0); + dm_logger_write(dc->ctx->logger, LOG_DC, + "Power gated front end %d\n", fe_idx); + if (dc->public.debug.sanity_checks) + verify_allow_pstate_change_high(dc->hwseq); } -*/ + static void reset_front_end( struct core_dc *dc, @@ -953,6 +982,37 @@ static void reset_hw_ctx_wrap( int i; /* Reset Front End*/ + /* Lock*/ + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *cur_pipe_ctx = &dc->current_context->res_ctx.pipe_ctx[i]; + struct timing_generator *tg = cur_pipe_ctx->tg; + + if (cur_pipe_ctx->stream) + tg->funcs->lock(tg); + } + /* Disconnect*/ + for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) { + struct pipe_ctx *pipe_ctx_old = + &dc->current_context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + + if (!pipe_ctx->stream || + !pipe_ctx->surface || + pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) { + + plane_atomic_disconnect(dc, i); + } + } + /* Unlock*/ + for (i = dc->res_pool->pipe_count - 1; i >= 0; i--) { + struct pipe_ctx *cur_pipe_ctx = &dc->current_context->res_ctx.pipe_ctx[i]; + struct timing_generator *tg = cur_pipe_ctx->tg; + + if (cur_pipe_ctx->stream) + tg->funcs->unlock(tg); + } + + /* Disable and Powerdown*/ for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) { struct pipe_ctx *pipe_ctx_old = &dc->current_context->res_ctx.pipe_ctx[i]; @@ -961,11 +1021,16 @@ static void reset_hw_ctx_wrap( /*if (!pipe_ctx_old->stream) continue;*/ + if (pipe_ctx->stream && pipe_ctx->surface + && !pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) + continue; + + plane_atomic_disable(dc, i); + if (!pipe_ctx->stream || !pipe_ctx->surface) - dcn10_power_down_fe(dc, i); - else if (pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) - reset_front_end(dc, i); + plane_atomic_power_down(dc, i); } + /* Reset Back End*/ for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) { struct pipe_ctx *pipe_ctx_old = @@ -2079,6 +2144,10 @@ static void dcn10_apply_ctx_for_surface( old_pipe_ctx->mpcc->funcs->set(old_pipe_ctx->mpcc, &mpcc_cfg); old_pipe_ctx->top_pipe->opp->mpcc_disconnect_pending[old_pipe_ctx->mpcc->inst] = true; + /*dm_logger_write(dc->ctx->logger, LOG_ERROR, + "[debug_mpo: apply_ctx disconnect pending on mpcc %d]\n", + old_pipe_ctx->mpcc->inst);*/ + if (dc->public.debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); @@ -2351,18 +2420,27 @@ static void dcn10_log_hw_state(struct core_dc *dc) */ } -static void dcn10_wait_for_mpcc_disconnect(struct resource_pool *res_pool, struct pipe_ctx *pipe_ctx) +static void dcn10_wait_for_mpcc_disconnect( + struct core_dc *dc, + struct resource_pool *res_pool, + struct pipe_ctx *pipe_ctx) { int i; - for (i = 0; i < MAX_PIPES; i++) { - if (!pipe_ctx->opp || !pipe_ctx->mpcc) - continue; + if (!pipe_ctx->opp || !pipe_ctx->mpcc) + return; + + for (i = 0; i < MAX_PIPES; i++) { if (pipe_ctx->opp->mpcc_disconnect_pending[i]) { pipe_ctx->mpcc->funcs->wait_for_idle(res_pool->mpcc[i]); pipe_ctx->opp->mpcc_disconnect_pending[i] = false; + res_pool->mis[i]->funcs->set_blank(res_pool->mis[i], true); + /*dm_logger_write(dc->ctx->logger, LOG_ERROR, + "[debug_mpo: wait_for_mpcc finished waiting on mpcc %d]\n", + i);*/ } } + } static bool dcn10_dummy_display_power_gating( diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 2343beb4ef87..a3eec078dead 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -161,7 +161,9 @@ struct hw_sequencer_funcs { void (*log_hw_state)(struct core_dc *dc); - void (*wait_for_mpcc_disconnect)(struct resource_pool *res_pool, struct pipe_ctx *pipe_ctx); + void (*wait_for_mpcc_disconnect)(struct core_dc *dc, + struct resource_pool *res_pool, + struct pipe_ctx *pipe_ctx); }; void color_space_to_black_color( -- cgit From 9345d9874c324b2f8cce79d4de11f27ae1ef80e9 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Fri, 21 Jul 2017 16:34:36 -0400 Subject: drm/amd/display: Move stream validations into seperate function. Stateless streams validations (not require resource population) moved into hook to be called directly from DM. Call dc_validate_stream be before validate_with_context for non Linux APIs Signed-off-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 24 +++++++++ drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 61 +++++++++++++++------- drivers/gpu/drm/amd/display/dc/dc.h | 2 + .../gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 7 ++- .../gpu/drm/amd/display/dc/dce/dce_link_encoder.h | 2 +- .../drm/amd/display/dc/dce100/dce100_resource.c | 24 ++------- .../drm/amd/display/dc/dce110/dce110_resource.c | 23 ++------ .../drm/amd/display/dc/dce112/dce112_resource.c | 25 ++------- .../gpu/drm/amd/display/dc/dce80/dce80_resource.c | 25 ++------- .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 25 ++------- .../gpu/drm/amd/display/dc/inc/hw/link_encoder.h | 2 +- .../amd/display/dc/virtual/virtual_link_encoder.c | 2 +- 12 files changed, 90 insertions(+), 132 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 79218805754e..9c2faf8e4b14 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -664,6 +664,20 @@ static bool is_validation_required( return false; } +static bool validate_streams ( + const struct dc *dc, + const struct dc_validation_set set[], + int set_count) +{ + int i; + + for (i = 0; i < set_count; i++) + if (!dc_validate_stream(dc, set[i].stream)) + return false; + + return true; +} + struct validate_context *dc_get_validate_context( const struct dc *dc, const struct dc_validation_set set[], @@ -673,6 +687,7 @@ struct validate_context *dc_get_validate_context( enum dc_status result = DC_ERROR_UNEXPECTED; struct validate_context *context; + context = dm_alloc(sizeof(struct validate_context)); if (context == NULL) goto context_alloc_fail; @@ -711,6 +726,9 @@ bool dc_validate_resources( enum dc_status result = DC_ERROR_UNEXPECTED; struct validate_context *context; + if (!validate_streams(dc, set, set_count)) + return false; + context = dm_alloc(sizeof(struct validate_context)); if (context == NULL) goto context_alloc_fail; @@ -742,6 +760,9 @@ bool dc_validate_guaranteed( enum dc_status result = DC_ERROR_UNEXPECTED; struct validate_context *context; + if (!dc_validate_stream(dc, stream)) + return false; + context = dm_alloc(sizeof(struct validate_context)); if (context == NULL) goto context_alloc_fail; @@ -1044,6 +1065,9 @@ bool dc_commit_streams( } + if (!validate_streams(dc, set, stream_count)) + return false; + context = dm_alloc(sizeof(struct validate_context)); if (context == NULL) goto context_alloc_fail; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 7cb572ff3cba..4403d8244407 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1416,23 +1416,17 @@ static int get_norm_pix_clk(const struct dc_crtc_timing *timing) return normalized_pix_clk; } -static void calculate_phy_pix_clks(struct validate_context *context) +static void calculate_phy_pix_clks(struct core_stream *stream) { - int i; - - for (i = 0; i < context->stream_count; i++) { - struct core_stream *stream = context->streams[i]; - - update_stream_signal(stream); - - /* update actual pixel clock on all streams */ - if (dc_is_hdmi_signal(stream->signal)) - stream->phy_pix_clk = get_norm_pix_clk( - &stream->public.timing); - else - stream->phy_pix_clk = - stream->public.timing.pix_clk_khz; - } + update_stream_signal(stream); + + /* update actual pixel clock on all streams */ + if (dc_is_hdmi_signal(stream->signal)) + stream->phy_pix_clk = get_norm_pix_clk( + &stream->public.timing); + else + stream->phy_pix_clk = + stream->public.timing.pix_clk_khz; } enum dc_status resource_map_pool_resources( @@ -1443,8 +1437,6 @@ enum dc_status resource_map_pool_resources( const struct resource_pool *pool = dc->res_pool; int i, j; - calculate_phy_pix_clks(context); - for (i = 0; old_context && i < context->stream_count; i++) { struct core_stream *stream = context->streams[i]; @@ -2516,3 +2508,36 @@ void resource_build_bit_depth_reduction_params(const struct core_stream *stream, fmt_bit_depth->pixel_encoding = pixel_encoding; } + +bool dc_validate_stream(const struct dc *dc, const struct dc_stream *stream) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc_context *dc_ctx = core_dc->ctx; + struct core_stream *core_stream = DC_STREAM_TO_CORE(stream); + struct dc_link *link = core_stream->sink->link; + struct timing_generator *tg = core_dc->res_pool->timing_generators[0]; + enum dc_status res = DC_OK; + + calculate_phy_pix_clks(core_stream); + + if (!tg->funcs->validate_timing(tg, &core_stream->public.timing)) + res = DC_FAIL_CONTROLLER_VALIDATE; + + if (res == DC_OK) + if (!link->link_enc->funcs->validate_output_with_stream( + link->link_enc, core_stream)) + res = DC_FAIL_ENC_VALIDATE; + + /* TODO: validate audio ASIC caps, encoder */ + + if (res == DC_OK) + res = dc_link_validate_mode_timing(core_stream, + link, + &core_stream->public.timing); + + if (res != DC_OK) + DC_ERROR("Failed validation for stream %p, err:%d, !\n", + stream, res); + + return res == DC_OK; +} diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 5523bb68f4e8..f250e87d39dd 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -559,6 +559,8 @@ struct dc_validation_set { uint8_t surface_count; }; +bool dc_validate_stream(const struct dc *dc, const struct dc_stream *stream); + /* * This function takes a set of resources and checks that they are cofunctional. * diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 318673da189b..aff0a440d4d3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -1009,19 +1009,18 @@ bool dce110_link_encoder_construct( bool dce110_link_encoder_validate_output_with_stream( struct link_encoder *enc, - struct pipe_ctx *pipe_ctx) + const struct core_stream *stream) { - struct core_stream *stream = pipe_ctx->stream; struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); bool is_valid; - switch (pipe_ctx->stream->signal) { + switch (stream->signal) { case SIGNAL_TYPE_DVI_SINGLE_LINK: case SIGNAL_TYPE_DVI_DUAL_LINK: is_valid = dce110_link_encoder_validate_dvi_output( enc110, stream->sink->link->connector_signal, - pipe_ctx->stream->signal, + stream->signal, &stream->public.timing); break; case SIGNAL_TYPE_HDMI_TYPE_A: diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h index fd6ba7efc0f9..ded6c61304e6 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h @@ -199,7 +199,7 @@ bool dce110_link_encoder_validate_wireless_output( bool dce110_link_encoder_validate_output_with_stream( struct link_encoder *enc, - struct pipe_ctx *pipe_ctx); + const struct core_stream *stream); /****************** HW programming ************************/ diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 6938158bed7f..3d25a90e49b4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -651,7 +651,7 @@ static void destruct(struct dce110_resource_pool *pool) dal_irq_service_destroy(&pool->base.irqs); } -static enum dc_status validate_mapped_resource( +static enum dc_status build_mapped_resource( const struct core_dc *dc, struct validate_context *context, struct validate_context *old_context) @@ -661,7 +661,6 @@ static enum dc_status validate_mapped_resource( for (i = 0; i < context->stream_count; i++) { struct core_stream *stream = context->streams[i]; - struct dc_link *link = stream->sink->link; if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; @@ -673,25 +672,8 @@ static enum dc_status validate_mapped_resource( if (context->res_ctx.pipe_ctx[j].stream != stream) continue; - if (!pipe_ctx->tg->funcs->validate_timing( - pipe_ctx->tg, &stream->public.timing)) - return DC_FAIL_CONTROLLER_VALIDATE; - status = dce110_resource_build_pipe_hw_param(pipe_ctx); - if (status != DC_OK) - return status; - - if (!link->link_enc->funcs->validate_output_with_stream( - link->link_enc, - pipe_ctx)) - return DC_FAIL_ENC_VALIDATE; - - /* TODO: validate audio ASIC caps, encoder */ - status = dc_link_validate_mode_timing(stream, - link, - &stream->public.timing); - if (status != DC_OK) return status; @@ -769,7 +751,7 @@ enum dc_status dce100_validate_with_context( } if (result == DC_OK) - result = validate_mapped_resource(dc, context, old_context); + result = build_mapped_resource(dc, context, old_context); if (result == DC_OK) result = resource_build_scaling_params_for_context(dc, context); @@ -798,7 +780,7 @@ enum dc_status dce100_validate_guaranteed( result = resource_map_clock_resources(dc, context, NULL); if (result == DC_OK) - result = validate_mapped_resource(dc, context, NULL); + result = build_mapped_resource(dc, context, NULL); if (result == DC_OK) { validate_guaranteed_copy_streams( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 015306a6ef88..c773351e93af 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -771,7 +771,7 @@ static bool is_surface_pixel_format_supported(struct pipe_ctx *pipe_ctx, unsigne return true; } -static enum dc_status validate_mapped_resource( +static enum dc_status build_mapped_resource( const struct core_dc *dc, struct validate_context *context, struct validate_context *old_context) @@ -781,7 +781,6 @@ static enum dc_status validate_mapped_resource( for (i = 0; i < context->stream_count; i++) { struct core_stream *stream = context->streams[i]; - struct dc_link *link = stream->sink->link; if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; @@ -797,29 +796,13 @@ static enum dc_status validate_mapped_resource( dc->res_pool->underlay_pipe_index)) return DC_SURFACE_PIXEL_FORMAT_UNSUPPORTED; - if (!pipe_ctx->tg->funcs->validate_timing( - pipe_ctx->tg, &stream->public.timing)) - return DC_FAIL_CONTROLLER_VALIDATE; - status = dce110_resource_build_pipe_hw_param(pipe_ctx); if (status != DC_OK) return status; - if (!link->link_enc->funcs->validate_output_with_stream( - link->link_enc, - pipe_ctx)) - return DC_FAIL_ENC_VALIDATE; - /* TODO: validate audio ASIC caps, encoder */ - status = dc_link_validate_mode_timing(stream, - link, - &stream->public.timing); - - if (status != DC_OK) - return status; - resource_build_info_frame(pipe_ctx); /* do not need to validate non root pipes */ @@ -976,7 +959,7 @@ enum dc_status dce110_validate_with_context( } if (result == DC_OK) - result = validate_mapped_resource(dc, context, old_context); + result = build_mapped_resource(dc, context, old_context); if (result == DC_OK) result = resource_build_scaling_params_for_context(dc, context); @@ -1005,7 +988,7 @@ enum dc_status dce110_validate_guaranteed( result = resource_map_clock_resources(dc, context, NULL); if (result == DC_OK) - result = validate_mapped_resource(dc, context, NULL); + result = build_mapped_resource(dc, context, NULL); if (result == DC_OK) { validate_guaranteed_copy_streams( diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index ca1e13e2a3db..19cd99923b24 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -720,7 +720,7 @@ static struct clock_source *find_matching_pll( return 0; } -static enum dc_status validate_mapped_resource( +static enum dc_status build_mapped_resource( const struct core_dc *dc, struct validate_context *context, struct validate_context *old_context) @@ -730,7 +730,6 @@ static enum dc_status validate_mapped_resource( for (i = 0; i < context->stream_count; i++) { struct core_stream *stream = context->streams[i]; - struct dc_link *link = stream->sink->link; if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; @@ -742,26 +741,8 @@ static enum dc_status validate_mapped_resource( if (context->res_ctx.pipe_ctx[j].stream != stream) continue; - if (!pipe_ctx->tg->funcs->validate_timing( - pipe_ctx->tg, &stream->public.timing)) - return DC_FAIL_CONTROLLER_VALIDATE; - status = dce110_resource_build_pipe_hw_param(pipe_ctx); - if (status != DC_OK) - return status; - - if (!link->link_enc->funcs->validate_output_with_stream( - link->link_enc, - pipe_ctx)) - return DC_FAIL_ENC_VALIDATE; - - /* TODO: validate audio ASIC caps, encoder */ - - status = dc_link_validate_mode_timing(stream, - link, - &stream->public.timing); - if (status != DC_OK) return status; @@ -952,7 +933,7 @@ enum dc_status dce112_validate_with_context( } if (result == DC_OK) - result = validate_mapped_resource(dc, context, old_context); + result = build_mapped_resource(dc, context, old_context); if (result == DC_OK) result = resource_build_scaling_params_for_context(dc, context); @@ -981,7 +962,7 @@ enum dc_status dce112_validate_guaranteed( result = resource_map_phy_clock_resources(dc, context, NULL); if (result == DC_OK) - result = validate_mapped_resource(dc, context, NULL); + result = build_mapped_resource(dc, context, NULL); if (result == DC_OK) { validate_guaranteed_copy_streams( diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index b2319dbf3be3..0123006e5360 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -667,7 +667,7 @@ static void destruct(struct dce110_resource_pool *pool) } } -static enum dc_status validate_mapped_resource( +static enum dc_status build_mapped_resource( const struct core_dc *dc, struct validate_context *context, struct validate_context *old_context) @@ -677,7 +677,6 @@ static enum dc_status validate_mapped_resource( for (i = 0; i < context->stream_count; i++) { struct core_stream *stream = context->streams[i]; - struct dc_link *link = stream->sink->link; if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; @@ -689,26 +688,8 @@ static enum dc_status validate_mapped_resource( if (context->res_ctx.pipe_ctx[j].stream != stream) continue; - if (!pipe_ctx->tg->funcs->validate_timing( - pipe_ctx->tg, &stream->public.timing)) - return DC_FAIL_CONTROLLER_VALIDATE; - status = dce110_resource_build_pipe_hw_param(pipe_ctx); - if (status != DC_OK) - return status; - - if (!link->link_enc->funcs->validate_output_with_stream( - link->link_enc, - pipe_ctx)) - return DC_FAIL_ENC_VALIDATE; - - /* TODO: validate audio ASIC caps, encoder */ - - status = dc_link_validate_mode_timing(stream, - link, - &stream->public.timing); - if (status != DC_OK) return status; @@ -786,7 +767,7 @@ enum dc_status dce80_validate_with_context( } if (result == DC_OK) - result = validate_mapped_resource(dc, context, old_context); + result = build_mapped_resource(dc, context, old_context); if (result == DC_OK) result = resource_build_scaling_params_for_context(dc, context); @@ -814,7 +795,7 @@ enum dc_status dce80_validate_guaranteed( result = resource_map_clock_resources(dc, context, NULL); if (result == DC_OK) - result = validate_mapped_resource(dc, context, NULL); + result = build_mapped_resource(dc, context, NULL); if (result == DC_OK) { validate_guaranteed_copy_streams( diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 0110a431e289..b901ef9689a6 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -835,7 +835,7 @@ static enum dc_status build_pipe_hw_param(struct pipe_ctx *pipe_ctx) return DC_OK; } -static enum dc_status validate_mapped_resource( +static enum dc_status build_mapped_resource( const struct core_dc *dc, struct validate_context *context, struct validate_context *old_context) @@ -845,7 +845,6 @@ static enum dc_status validate_mapped_resource( for (i = 0; i < context->stream_count; i++) { struct core_stream *stream = context->streams[i]; - struct dc_link *link = stream->sink->link; if (old_context && resource_is_stream_unchanged(old_context, stream)) { if (stream != NULL && old_context->streams[i] != NULL) { @@ -870,29 +869,11 @@ static enum dc_status validate_mapped_resource( if (context->res_ctx.pipe_ctx[j].stream != stream) continue; - - if (!pipe_ctx->tg->funcs->validate_timing( - pipe_ctx->tg, &stream->public.timing)) - return DC_FAIL_CONTROLLER_VALIDATE; - status = build_pipe_hw_param(pipe_ctx); if (status != DC_OK) return status; - if (!link->link_enc->funcs->validate_output_with_stream( - link->link_enc, pipe_ctx)) - return DC_FAIL_ENC_VALIDATE; - - /* TODO: validate audio ASIC caps, encoder */ - - status = dc_link_validate_mode_timing( - stream, link, &stream->public.timing); - - if (status != DC_OK) - return status; - - /* do not need to validate non root pipes */ break; } @@ -928,7 +909,7 @@ enum dc_status dcn10_validate_with_context( if (result != DC_OK) return result; - result = validate_mapped_resource(dc, context, old_context); + result = build_mapped_resource(dc, context, old_context); if (result != DC_OK) return result; @@ -963,7 +944,7 @@ enum dc_status dcn10_validate_guaranteed( result = resource_map_phy_clock_resources(dc, context, NULL); if (result == DC_OK) - result = validate_mapped_resource(dc, context, NULL); + result = build_mapped_resource(dc, context, NULL); if (result == DC_OK) { validate_guaranteed_copy_streams( diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h index d330d38aff16..0ee738774f9f 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h @@ -94,7 +94,7 @@ struct link_encoder { struct link_encoder_funcs { bool (*validate_output_with_stream)( - struct link_encoder *enc, struct pipe_ctx *pipe_ctx); + struct link_encoder *enc, const struct core_stream *stream); void (*hw_init)(struct link_encoder *enc); void (*setup)(struct link_encoder *enc, enum signal_type signal); diff --git a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c index 12df49927f09..d312874d95b5 100644 --- a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c @@ -30,7 +30,7 @@ static bool virtual_link_encoder_validate_output_with_stream( struct link_encoder *enc, - struct pipe_ctx *pipe_ctx) { return true; } + const struct core_stream *stream) { return true; } static void virtual_link_encoder_hw_init(struct link_encoder *enc) {} -- cgit From 4017fcdf5824ea30736e2ecebd02dfa37a249eb5 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Mon, 24 Jul 2017 15:35:24 -0400 Subject: drm/amd/display: Use stream validation hook. Use dc_validate_stream from crtc atomic_check for single stream validation. Signed-off-by: Andrey Grodzovsky Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 86 ++++++++++++---------- 1 file changed, 48 insertions(+), 38 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 13708bcb83cd..0fcd9b373172 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -64,6 +64,24 @@ struct dm_connector_state { #define to_dm_connector_state(x)\ container_of((x), struct dm_connector_state, base) +static bool modeset_required(struct drm_crtc_state *crtc_state) +{ + if (!drm_atomic_crtc_needs_modeset(crtc_state)) + return false; + + if (!crtc_state->enable) + return false; + + return crtc_state->active; +} + +static bool modereset_required(struct drm_crtc_state *crtc_state) +{ + if (!drm_atomic_crtc_needs_modeset(crtc_state)) + return false; + + return !crtc_state->enable || !crtc_state->active; +} void amdgpu_dm_encoder_destroy(struct drm_encoder *encoder) { @@ -1268,11 +1286,9 @@ int amdgpu_dm_connector_mode_valid( int result = MODE_ERROR; struct dc_sink *dc_sink; struct amdgpu_device *adev = connector->dev->dev_private; - struct dc_validation_set val_set = { 0 }; /* TODO: Unhardcode stream count */ struct dc_stream *stream; struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); - struct validate_context *context; if ((mode->flags & DRM_MODE_FLAG_INTERLACE) || (mode->flags & DRM_MODE_FLAG_DBLSCAN)) @@ -1289,35 +1305,28 @@ int amdgpu_dm_connector_mode_valid( if (NULL == dc_sink) { DRM_ERROR("dc_sink is NULL!\n"); - goto null_sink; + goto fail; } stream = dc_create_stream_for_sink(dc_sink); if (NULL == stream) { DRM_ERROR("Failed to create stream for sink!\n"); - goto stream_create_fail; + goto fail; } drm_mode_set_crtcinfo(mode, 0); fill_stream_properties_from_drm_display_mode(stream, mode, connector); - val_set.stream = stream; - val_set.surface_count = 0; stream->src.width = mode->hdisplay; stream->src.height = mode->vdisplay; stream->dst = stream->src; - context = dc_get_validate_context(adev->dm.dc, &val_set, 1); - - if (context) { + if (dc_validate_stream(adev->dm.dc, stream)) result = MODE_OK; - dc_release_validate_context(context); - } dc_stream_release(stream); -stream_create_fail: -null_sink: +fail: /* TODO: error handling*/ return result; } @@ -1343,7 +1352,24 @@ static int dm_crtc_helper_atomic_check( struct drm_crtc *crtc, struct drm_crtc_state *state) { - return 0; + struct amdgpu_device *adev = crtc->dev->dev_private; + struct dc *dc = adev->dm.dc; + struct dm_crtc_state *dm_crtc_state = to_dm_crtc_state(state); + int ret = -EINVAL; + + if (unlikely(!dm_crtc_state->stream && modeset_required(state))) { + WARN_ON(1); + return ret; + } + + /* In some use cases, like reset, no stream is attached */ + if (!dm_crtc_state->stream) + return 0; + + if (dc_validate_stream(dc, dm_crtc_state->stream)) + return 0; + + return ret; } static bool dm_crtc_helper_mode_fixup( @@ -2119,25 +2145,6 @@ int amdgpu_dm_encoder_init( return res; } -static bool modeset_required(struct drm_crtc_state *crtc_state) -{ - if (!drm_atomic_crtc_needs_modeset(crtc_state)) - return false; - - if (!crtc_state->enable) - return false; - - return crtc_state->active; -} - -static bool modereset_required(struct drm_crtc_state *crtc_state) -{ - if (!drm_atomic_crtc_needs_modeset(crtc_state)) - return false; - - return !crtc_state->enable || !crtc_state->active; -} - static void manage_dm_interrupts( struct amdgpu_device *adev, struct amdgpu_crtc *acrtc, @@ -2935,7 +2942,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, */ bool lock_and_validation_needed = false; - ret = drm_atomic_helper_check(dev, state); + ret = drm_atomic_helper_check_modeset(dev, state); if (ret) { DRM_ERROR("Atomic state validation failed with error :%d !\n", ret); @@ -2957,6 +2964,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, } } + /*TODO Move this code into dm_crtc_atomic_check once we get rid of dc_validation_set */ /* update changed items */ for_each_crtc_in_state(state, crtc, crtc_state, i) { struct amdgpu_crtc *acrtc = NULL; @@ -3089,10 +3097,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, if (plane->type == DRM_PLANE_TYPE_CURSOR) continue; - if (!fb || !plane_crtc || crtc != plane_crtc || - (!crtc_state->planes_changed && - !crtc_state->color_mgmt_changed) || - !crtc_state->active) + if (!fb || !plane_crtc || crtc != plane_crtc || !crtc_state->active) continue; WARN_ON(!new_acrtc_state->stream); @@ -3128,6 +3133,11 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, } } + /* Run this here since we want to validate the streams we created */ + ret = drm_atomic_helper_check_planes(dev, state); + if (ret) + goto fail; + /* * For full updates case when * removing/adding/updating streams on once CRTC while flipping -- cgit From 48841a20fc794cee0dcbcabee64e068bd6db2df7 Mon Sep 17 00:00:00 2001 From: Roman Li Date: Tue, 25 Jul 2017 14:50:44 -0400 Subject: drm/amd/display: Fix eDP panel light-up Power-down panel on disale only if sink exists otherwise it fails edid read during init sequence Signed-off-by: Roman Li Reviewed-by: Andrey Grodzovsky Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index aac2420caefa..5bdcd5067116 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -114,7 +114,9 @@ void dp_disable_link_phy(struct dc_link *link, enum signal_type signal) if (signal == SIGNAL_TYPE_EDP) { link->link_enc->funcs->backlight_control(link->link_enc, false); - link->link_enc->funcs->power_control(link->link_enc, false); + if (link->dpcd_sink_count) + link->link_enc->funcs->power_control(link->link_enc, + false); } link->link_enc->funcs->disable_output(link->link_enc, signal); -- cgit From f4d5abf56b03e55f83d300324e5bf5f32431171c Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Tue, 25 Jul 2017 16:02:33 -0400 Subject: drm/amd/display: move ocsc programming from opp to dpp Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index bbe3e8705405..7c24e8f43bb1 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1809,7 +1809,7 @@ static void program_csc_matrix(struct pipe_ctx *pipe_ctx, tbl_entry.color_space = color_space; //tbl_entry.regval = matrix; - pipe_ctx->opp->funcs->opp_set_csc_adjustment(pipe_ctx->opp, &tbl_entry); + pipe_ctx->xfm->funcs->opp_set_csc_adjustment(pipe_ctx->xfm, &tbl_entry); } } static bool is_lower_pipe_tree_visible(struct pipe_ctx *pipe_ctx) -- cgit From 3639fa68122154b453eeaac840daadf3c7c56db4 Mon Sep 17 00:00:00 2001 From: Zeyu Fan Date: Tue, 25 Jul 2017 15:14:24 -0400 Subject: drm/amd/display: Clean up some DCN1 guards Signed-off-by: Zeyu Fan Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c | 1 + drivers/gpu/drm/amd/display/dc/core/dc.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 2 ++ drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c | 2 ++ drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c | 2 +- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 6 +++--- drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c | 1 + drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c | 1 + drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c | 5 +++-- 9 files changed, 15 insertions(+), 7 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c index 84b1f515aa47..9084a32aab79 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c @@ -58,6 +58,7 @@ bool dal_bios_parser_init_cmd_tbl_helper2( *h = dal_cmd_tbl_helper_dce112_get_table2(); return true; #endif + case DCE_VERSION_12_0: *h = dal_cmd_tbl_helper_dce112_get_table2(); return true; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 9c2faf8e4b14..bab07f8d4880 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1109,7 +1109,7 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) /* 3rd param should be true, temp w/a for RV*/ #if defined(CONFIG_DRM_AMD_DC_DCN1_0) - core_dc->hwss.set_bandwidth(core_dc, context, core_dc->ctx->dce_version != DCN_VERSION_1_0); + core_dc->hwss.set_bandwidth(core_dc, context, core_dc->ctx->dce_version < DCN_VERSION_1_0); #else core_dc->hwss.set_bandwidth(core_dc, context, true); #endif diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 4403d8244407..dea2943392e4 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -120,6 +120,8 @@ struct resource_pool *dc_create_resource_pool( num_virtual_links, dc); break; #endif + + default: break; } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index 142b3a01c204..2205491c83e9 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -589,6 +589,7 @@ static uint32_t dce110_get_pix_clk_dividers( #if defined(CONFIG_DRM_AMD_DC_DCN1_0) case DCN_VERSION_1_0: #endif + dce112_get_pix_clk_dividers_helper(clk_src, pll_settings, pix_clk_params); break; @@ -901,6 +902,7 @@ static bool dce110_program_pix_clk( #if defined(CONFIG_DRM_AMD_DC_DCN1_0) case DCN_VERSION_1_0: #endif + if (clock_source->id != CLOCK_SOURCE_ID_DP_DTO) { bp_pc_params.flags.SET_GENLOCK_REF_DIV_SRC = pll_settings->use_external_clk; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c index f30cd4dff554..37d074f595fb 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c @@ -614,7 +614,7 @@ static bool dce_apply_clock_voltage_request( } if (send_request) { #if defined(CONFIG_DRM_AMD_DC_DCN1_0) - if (clk->ctx->dce_version == DCN_VERSION_1_0) { + if (clk->ctx->dce_version >= DCN_VERSION_1_0) { struct core_dc *core_dc = DC_TO_CORE(clk->ctx->dc); /*use dcfclk request voltage*/ clock_voltage_req.clk_type = DM_PP_CLOCK_TYPE_DCFCLK; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index aa4777a8ec36..119365960cd0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1104,11 +1104,11 @@ static enum dc_status apply_single_controller_ctx_to_hw( true : false); resource_build_info_frame(pipe_ctx); - + dce110_update_info_frame(pipe_ctx); if (!pipe_ctx_old->stream) { core_link_enable_stream(pipe_ctx); - dce110_update_info_frame(pipe_ctx); + if (dc_is_dp_signal(pipe_ctx->stream->signal)) dce110_unblank_stream(pipe_ctx, &stream->sink->link->cur_link_settings); @@ -1664,7 +1664,7 @@ enum dc_status dce110_apply_ctx_to_hw( apply_min_clocks(dc, context, &clocks_state, true); #if defined(CONFIG_DRM_AMD_DC_DCN1_0) - if (dc->ctx->dce_version == DCN_VERSION_1_0) { + if (dc->ctx->dce_version >= DCN_VERSION_1_0) { if (context->bw.dcn.calc_clk.fclk_khz > dc->current_context->bw.dcn.cur_clk.fclk_khz) { struct dm_pp_clock_for_voltage_req clock; diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c index 8a8b619a60a8..425f1c4fa891 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c @@ -84,6 +84,7 @@ bool dal_hw_factory_init( dal_hw_factory_dcn10_init(factory); return true; #endif + default: ASSERT_CRITICAL(false); return false; diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c index 36c082bda4ae..3b55d45b6775 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c @@ -80,6 +80,7 @@ bool dal_hw_translate_init( dal_hw_translate_dcn10_init(translate); return true; #endif + default: BREAK_TO_DEBUGGER(); return false; diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c index 45e766ea79e3..10061cc4ba31 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c @@ -88,10 +88,11 @@ struct i2caux *dal_i2caux_create( return dal_i2caux_dce100_create(ctx); case DCE_VERSION_12_0: return dal_i2caux_dce120_create(ctx); - #if defined(CONFIG_DRM_AMD_DC_DCN1_0) +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) case DCN_VERSION_1_0: return dal_i2caux_dcn10_create(ctx); - #endif +#endif + default: BREAK_TO_DEBUGGER(); return NULL; -- cgit From b3d6c3f0f676a06820aa23c9f8590e080d6f6765 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 24 Jul 2017 14:04:27 -0400 Subject: drm/amd/display: Minor fix for dc_sink refactor Signed-off-by: Harry Wentland Reviewed-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index dea2943392e4..eeefc9c33633 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1321,7 +1321,7 @@ static struct audio *find_first_free_audio( static void update_stream_signal(struct core_stream *stream) { if (stream->public.output_signal == SIGNAL_TYPE_NONE) { - const struct dc_sink *dc_sink = stream->public.sink; + struct dc_sink *dc_sink = stream->public.sink; if (dc_sink->sink_signal == SIGNAL_TYPE_NONE) stream->signal = stream->sink->link->connector_signal; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index f250e87d39dd..f87f6c12494c 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -469,7 +469,7 @@ enum surface_update_type { * Stream Interfaces ******************************************************************************/ struct dc_stream { - const struct dc_sink *sink; + struct dc_sink *sink; struct dc_crtc_timing timing; struct rect src; /* composition area */ -- cgit From 8d6a615a16d6fd75c455561914e71b903df73aa4 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Tue, 25 Jul 2017 17:11:26 -0400 Subject: drm/amd/display: Disable timestamp and entry heading Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/basics/logger.c | 3 ++- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/basics/logger.c b/drivers/gpu/drm/amd/display/dc/basics/logger.c index 0b17374b1535..dfd23783cc47 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/logger.c +++ b/drivers/gpu/drm/amd/display/dc/basics/logger.c @@ -428,7 +428,8 @@ void dm_logger_open( logger->open_count++; - log_heading(entry); + if (log_type != LOG_DTN) + log_heading(entry); } void dm_logger_close(struct log_entry *entry) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 7c24e8f43bb1..03f404808a1c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2407,7 +2407,7 @@ static void dcn10_log_hw_state(struct core_dc *dc) struct dc_context *dc_ctx = dc->ctx; struct dce_hwseq *hws = dc->hwseq; - DTN_INFO("%s: Hello World", __func__); + DTN_INFO("Hello World"); if (REG(MPC_CRC_RESULT_GB)) DTN_INFO("MPC_CRC_RESULT_GB:%d MPC_CRC_RESULT_C:%d MPC_CRC_RESULT_AR:%d\n", -- cgit From d1f69890658909fad1b3881e618a841fc3bd3d96 Mon Sep 17 00:00:00 2001 From: Vitaly Prosyak Date: Tue, 25 Jul 2017 09:01:13 -0500 Subject: drm/amd/display: Add interfaces for new CM blocks Signed-off-by: Vitaly Prosyak Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c | 2 +- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h | 485 ++++++++++++++++++++++- 2 files changed, 485 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c index b6aaa95d442b..e52e1f43f67b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c @@ -1572,7 +1572,7 @@ static struct transform_funcs dcn10_dpp_funcs = { .opp_program_regamma_lutb_settings = opp_program_regamma_lutb_settings, .opp_program_regamma_luta_settings = opp_program_regamma_luta_settings, .opp_program_regamma_pwl = oppn10_set_regamma_pwl, - .opp_set_regamma_mode = oppn10_set_regamma_mode + .opp_set_regamma_mode = oppn10_set_regamma_mode, }; /*****************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h index 34085c0818e5..1c9d3320064a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h @@ -159,6 +159,7 @@ SRI(CM_RGAM_RAMA_REGION_32_33, CM, id), \ SRI(CM_RGAM_CONTROL, CM, id) + #define TF_REG_LIST_SH_MASK_DCN(mask_sh)\ TF_SF(CM0_CM_GAMUT_REMAP_CONTROL, CM_GAMUT_REMAP_MODE, mask_sh),\ TF_SF(CM0_CM_GAMUT_REMAP_C11_C12, CM_GAMUT_REMAP_C11, mask_sh),\ @@ -757,7 +758,373 @@ type CM_RGAM_RAMA_EXP_REGION33_NUM_SEGMENTS; \ type CM_RGAM_LUT_MODE; \ type OBUF_BYPASS; \ - type OBUF_H_2X_UPSCALE_EN + type OBUF_H_2X_UPSCALE_EN; \ + type CM_BLNDGAM_LUT_MODE; \ + type CM_BLNDGAM_RAMB_EXP_REGION_START_B; \ + type CM_BLNDGAM_RAMB_EXP_REGION_START_SEGMENT_B; \ + type CM_BLNDGAM_RAMB_EXP_REGION_START_G; \ + type CM_BLNDGAM_RAMB_EXP_REGION_START_SEGMENT_G; \ + type CM_BLNDGAM_RAMB_EXP_REGION_START_R; \ + type CM_BLNDGAM_RAMB_EXP_REGION_START_SEGMENT_R; \ + type CM_BLNDGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B; \ + type CM_BLNDGAM_RAMB_EXP_REGION_LINEAR_SLOPE_G; \ + type CM_BLNDGAM_RAMB_EXP_REGION_LINEAR_SLOPE_R; \ + type CM_BLNDGAM_RAMB_EXP_REGION_END_B; \ + type CM_BLNDGAM_RAMB_EXP_REGION_END_SLOPE_B; \ + type CM_BLNDGAM_RAMB_EXP_REGION_END_BASE_B; \ + type CM_BLNDGAM_RAMB_EXP_REGION_END_G; \ + type CM_BLNDGAM_RAMB_EXP_REGION_END_SLOPE_G; \ + type CM_BLNDGAM_RAMB_EXP_REGION_END_BASE_G; \ + type CM_BLNDGAM_RAMB_EXP_REGION_END_R; \ + type CM_BLNDGAM_RAMB_EXP_REGION_END_SLOPE_R; \ + type CM_BLNDGAM_RAMB_EXP_REGION_END_BASE_R; \ + type CM_BLNDGAM_RAMB_EXP_REGION0_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION0_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION1_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION1_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION2_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION2_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION3_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION3_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION4_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION4_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION5_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION5_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION6_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION6_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION7_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION7_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION8_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION8_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION9_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION9_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION10_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION10_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION11_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION11_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION12_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION12_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION13_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION13_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION14_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION14_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION15_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION15_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION16_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION16_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION17_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION17_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION18_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION18_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION19_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION19_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION20_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION20_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION21_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION21_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION22_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION22_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION23_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION23_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION24_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION24_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION25_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION25_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION26_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION26_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION27_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION27_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION28_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION28_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION29_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION29_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION30_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION30_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION31_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION31_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION32_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION32_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION33_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION33_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION_START_B; \ + type CM_BLNDGAM_RAMA_EXP_REGION_START_SEGMENT_B; \ + type CM_BLNDGAM_RAMA_EXP_REGION_START_G; \ + type CM_BLNDGAM_RAMA_EXP_REGION_START_SEGMENT_G; \ + type CM_BLNDGAM_RAMA_EXP_REGION_START_R; \ + type CM_BLNDGAM_RAMA_EXP_REGION_START_SEGMENT_R; \ + type CM_BLNDGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B; \ + type CM_BLNDGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G; \ + type CM_BLNDGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R; \ + type CM_BLNDGAM_RAMA_EXP_REGION_END_B; \ + type CM_BLNDGAM_RAMA_EXP_REGION_END_SLOPE_B; \ + type CM_BLNDGAM_RAMA_EXP_REGION_END_BASE_B; \ + type CM_BLNDGAM_RAMA_EXP_REGION_END_G; \ + type CM_BLNDGAM_RAMA_EXP_REGION_END_SLOPE_G; \ + type CM_BLNDGAM_RAMA_EXP_REGION_END_BASE_G; \ + type CM_BLNDGAM_RAMA_EXP_REGION_END_R; \ + type CM_BLNDGAM_RAMA_EXP_REGION_END_SLOPE_R; \ + type CM_BLNDGAM_RAMA_EXP_REGION_END_BASE_R; \ + type CM_BLNDGAM_RAMA_EXP_REGION0_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION0_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION1_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION1_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION2_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION2_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION3_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION3_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION4_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION4_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION5_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION5_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION6_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION6_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION7_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION7_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION8_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION8_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION9_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION9_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION10_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION10_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION11_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION11_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION12_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION12_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION13_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION13_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION14_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION14_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION15_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION15_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION16_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION16_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION17_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION17_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION18_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION18_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION19_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION19_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION20_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION20_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION21_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION21_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION22_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION22_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION23_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION23_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION24_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION24_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION25_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION25_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION26_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION26_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION27_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION27_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION28_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION28_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION29_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION29_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION30_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION30_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION31_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION31_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION32_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION32_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION33_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION33_NUM_SEGMENTS; \ + type CM_BLNDGAM_LUT_WRITE_EN_MASK; \ + type CM_BLNDGAM_LUT_WRITE_SEL; \ + type CM_BLNDGAM_LUT_INDEX; \ + type CM_BLNDGAM_LUT_DATA; \ + type CM_3DLUT_MODE; \ + type CM_3DLUT_SIZE; \ + type CM_3DLUT_INDEX; \ + type CM_3DLUT_DATA0; \ + type CM_3DLUT_DATA1; \ + type CM_3DLUT_DATA_30BIT; \ + type CM_3DLUT_WRITE_EN_MASK; \ + type CM_3DLUT_RAM_SEL; \ + type CM_3DLUT_30BIT_EN; \ + type CM_3DLUT_CONFIG_STATUS; \ + type CM_3DLUT_READ_SEL; \ + type CM_SHAPER_LUT_MODE; \ + type CM_SHAPER_RAMB_EXP_REGION_START_B; \ + type CM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_B; \ + type CM_SHAPER_RAMB_EXP_REGION_START_G; \ + type CM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_G; \ + type CM_SHAPER_RAMB_EXP_REGION_START_R; \ + type CM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_R; \ + type CM_SHAPER_RAMB_EXP_REGION_LINEAR_SLOPE_B; \ + type CM_SHAPER_RAMB_EXP_REGION_LINEAR_SLOPE_G; \ + type CM_SHAPER_RAMB_EXP_REGION_LINEAR_SLOPE_R; \ + type CM_SHAPER_RAMB_EXP_REGION_END_B; \ + type CM_SHAPER_RAMB_EXP_REGION_END_SLOPE_B; \ + type CM_SHAPER_RAMB_EXP_REGION_END_BASE_B; \ + type CM_SHAPER_RAMB_EXP_REGION_END_G; \ + type CM_SHAPER_RAMB_EXP_REGION_END_SLOPE_G; \ + type CM_SHAPER_RAMB_EXP_REGION_END_BASE_G; \ + type CM_SHAPER_RAMB_EXP_REGION_END_R; \ + type CM_SHAPER_RAMB_EXP_REGION_END_SLOPE_R; \ + type CM_SHAPER_RAMB_EXP_REGION_END_BASE_R; \ + type CM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION2_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION2_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION3_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION3_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION4_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION4_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION5_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION5_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION6_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION6_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION7_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION7_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION8_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION8_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION9_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION9_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION10_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION10_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION11_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION11_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION12_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION12_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION13_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION13_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION14_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION14_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION15_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION15_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION16_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION16_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION17_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION17_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION18_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION18_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION19_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION19_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION20_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION20_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION21_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION21_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION22_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION22_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION23_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION23_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION24_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION24_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION25_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION25_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION26_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION26_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION27_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION27_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION28_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION28_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION29_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION29_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION30_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION30_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION31_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION31_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION32_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION32_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION33_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION33_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION_START_B; \ + type CM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B; \ + type CM_SHAPER_RAMA_EXP_REGION_START_G; \ + type CM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_G; \ + type CM_SHAPER_RAMA_EXP_REGION_START_R; \ + type CM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_R; \ + type CM_SHAPER_RAMA_EXP_REGION_LINEAR_SLOPE_B; \ + type CM_SHAPER_RAMA_EXP_REGION_LINEAR_SLOPE_G; \ + type CM_SHAPER_RAMA_EXP_REGION_LINEAR_SLOPE_R; \ + type CM_SHAPER_RAMA_EXP_REGION_END_B; \ + type CM_SHAPER_RAMA_EXP_REGION_END_SLOPE_B; \ + type CM_SHAPER_RAMA_EXP_REGION_END_BASE_B; \ + type CM_SHAPER_RAMA_EXP_REGION_END_G; \ + type CM_SHAPER_RAMA_EXP_REGION_END_SLOPE_G; \ + type CM_SHAPER_RAMA_EXP_REGION_END_BASE_G; \ + type CM_SHAPER_RAMA_EXP_REGION_END_R; \ + type CM_SHAPER_RAMA_EXP_REGION_END_SLOPE_R; \ + type CM_SHAPER_RAMA_EXP_REGION_END_BASE_R; \ + type CM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION2_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION2_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION3_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION3_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION4_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION4_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION5_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION5_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION6_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION6_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION7_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION7_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION8_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION8_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION9_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION9_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION10_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION10_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION11_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION11_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION12_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION12_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION13_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION13_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION14_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION14_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION15_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION15_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION16_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION16_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION17_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION17_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION18_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION18_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION19_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION19_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION20_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION20_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION21_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION21_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION22_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION22_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION23_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION23_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION24_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION24_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION25_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION25_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION26_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION26_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION27_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION27_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION28_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION28_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION29_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION29_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION30_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION30_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION31_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION31_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION32_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION32_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION33_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION33_NUM_SEGMENTS; \ + type CM_SHAPER_LUT_WRITE_EN_MASK; \ + type CM_SHAPER_LUT_WRITE_SEL; \ + type CM_SHAPER_LUT_INDEX; \ + type CM_SHAPER_LUT_DATA + struct dcn_dpp_shift { TF_REG_FIELD_LIST(uint8_t); @@ -767,6 +1134,9 @@ struct dcn_dpp_mask { TF_REG_FIELD_LIST(uint32_t); }; + + + struct dcn_dpp_registers { uint32_t DSCL_EXT_OVERSCAN_LEFT_RIGHT; uint32_t DSCL_EXT_OVERSCAN_TOP_BOTTOM; @@ -885,6 +1255,119 @@ struct dcn_dpp_registers { uint32_t CM_RGAM_RAMA_REGION_32_33; uint32_t CM_RGAM_CONTROL; uint32_t OBUF_CONTROL; + uint32_t CM_BLNDGAM_LUT_WRITE_EN_MASK; + uint32_t CM_BLNDGAM_CONTROL; + uint32_t CM_BLNDGAM_RAMB_START_CNTL_B; + uint32_t CM_BLNDGAM_RAMB_START_CNTL_G; + uint32_t CM_BLNDGAM_RAMB_START_CNTL_R; + uint32_t CM_BLNDGAM_RAMB_SLOPE_CNTL_B; + uint32_t CM_BLNDGAM_RAMB_SLOPE_CNTL_G; + uint32_t CM_BLNDGAM_RAMB_SLOPE_CNTL_R; + uint32_t CM_BLNDGAM_RAMB_END_CNTL1_B; + uint32_t CM_BLNDGAM_RAMB_END_CNTL2_B; + uint32_t CM_BLNDGAM_RAMB_END_CNTL1_G; + uint32_t CM_BLNDGAM_RAMB_END_CNTL2_G; + uint32_t CM_BLNDGAM_RAMB_END_CNTL1_R; + uint32_t CM_BLNDGAM_RAMB_END_CNTL2_R; + uint32_t CM_BLNDGAM_RAMB_REGION_0_1; + uint32_t CM_BLNDGAM_RAMB_REGION_2_3; + uint32_t CM_BLNDGAM_RAMB_REGION_4_5; + uint32_t CM_BLNDGAM_RAMB_REGION_6_7; + uint32_t CM_BLNDGAM_RAMB_REGION_8_9; + uint32_t CM_BLNDGAM_RAMB_REGION_10_11; + uint32_t CM_BLNDGAM_RAMB_REGION_12_13; + uint32_t CM_BLNDGAM_RAMB_REGION_14_15; + uint32_t CM_BLNDGAM_RAMB_REGION_16_17; + uint32_t CM_BLNDGAM_RAMB_REGION_18_19; + uint32_t CM_BLNDGAM_RAMB_REGION_20_21; + uint32_t CM_BLNDGAM_RAMB_REGION_22_23; + uint32_t CM_BLNDGAM_RAMB_REGION_24_25; + uint32_t CM_BLNDGAM_RAMB_REGION_26_27; + uint32_t CM_BLNDGAM_RAMB_REGION_28_29; + uint32_t CM_BLNDGAM_RAMB_REGION_30_31; + uint32_t CM_BLNDGAM_RAMB_REGION_32_33; + uint32_t CM_BLNDGAM_RAMA_START_CNTL_B; + uint32_t CM_BLNDGAM_RAMA_START_CNTL_G; + uint32_t CM_BLNDGAM_RAMA_START_CNTL_R; + uint32_t CM_BLNDGAM_RAMA_SLOPE_CNTL_B; + uint32_t CM_BLNDGAM_RAMA_SLOPE_CNTL_G; + uint32_t CM_BLNDGAM_RAMA_SLOPE_CNTL_R; + uint32_t CM_BLNDGAM_RAMA_END_CNTL1_B; + uint32_t CM_BLNDGAM_RAMA_END_CNTL2_B; + uint32_t CM_BLNDGAM_RAMA_END_CNTL1_G; + uint32_t CM_BLNDGAM_RAMA_END_CNTL2_G; + uint32_t CM_BLNDGAM_RAMA_END_CNTL1_R; + uint32_t CM_BLNDGAM_RAMA_END_CNTL2_R; + uint32_t CM_BLNDGAM_RAMA_REGION_0_1; + uint32_t CM_BLNDGAM_RAMA_REGION_2_3; + uint32_t CM_BLNDGAM_RAMA_REGION_4_5; + uint32_t CM_BLNDGAM_RAMA_REGION_6_7; + uint32_t CM_BLNDGAM_RAMA_REGION_8_9; + uint32_t CM_BLNDGAM_RAMA_REGION_10_11; + uint32_t CM_BLNDGAM_RAMA_REGION_12_13; + uint32_t CM_BLNDGAM_RAMA_REGION_14_15; + uint32_t CM_BLNDGAM_RAMA_REGION_16_17; + uint32_t CM_BLNDGAM_RAMA_REGION_18_19; + uint32_t CM_BLNDGAM_RAMA_REGION_20_21; + uint32_t CM_BLNDGAM_RAMA_REGION_22_23; + uint32_t CM_BLNDGAM_RAMA_REGION_24_25; + uint32_t CM_BLNDGAM_RAMA_REGION_26_27; + uint32_t CM_BLNDGAM_RAMA_REGION_28_29; + uint32_t CM_BLNDGAM_RAMA_REGION_30_31; + uint32_t CM_BLNDGAM_RAMA_REGION_32_33; + uint32_t CM_BLNDGAM_LUT_INDEX; + uint32_t CM_BLNDGAM_LUT_DATA; + uint32_t CM_3DLUT_MODE; + uint32_t CM_3DLUT_INDEX; + uint32_t CM_3DLUT_DATA; + uint32_t CM_3DLUT_DATA_30BIT; + uint32_t CM_3DLUT_READ_WRITE_CONTROL; + uint32_t CM_SHAPER_LUT_WRITE_EN_MASK; + uint32_t CM_SHAPER_CONTROL; + uint32_t CM_SHAPER_RAMB_START_CNTL_B; + uint32_t CM_SHAPER_RAMB_START_CNTL_G; + uint32_t CM_SHAPER_RAMB_START_CNTL_R; + uint32_t CM_SHAPER_RAMB_REGION_0_1; + uint32_t CM_SHAPER_RAMB_REGION_2_3; + uint32_t CM_SHAPER_RAMB_REGION_4_5; + uint32_t CM_SHAPER_RAMB_REGION_6_7; + uint32_t CM_SHAPER_RAMB_REGION_8_9; + uint32_t CM_SHAPER_RAMB_REGION_10_11; + uint32_t CM_SHAPER_RAMB_REGION_12_13; + uint32_t CM_SHAPER_RAMB_REGION_14_15; + uint32_t CM_SHAPER_RAMB_REGION_16_17; + uint32_t CM_SHAPER_RAMB_REGION_18_19; + uint32_t CM_SHAPER_RAMB_REGION_20_21; + uint32_t CM_SHAPER_RAMB_REGION_22_23; + uint32_t CM_SHAPER_RAMB_REGION_24_25; + uint32_t CM_SHAPER_RAMB_REGION_26_27; + uint32_t CM_SHAPER_RAMB_REGION_28_29; + uint32_t CM_SHAPER_RAMB_REGION_30_31; + uint32_t CM_SHAPER_RAMB_REGION_32_33; + uint32_t CM_SHAPER_RAMA_START_CNTL_B; + uint32_t CM_SHAPER_RAMA_START_CNTL_G; + uint32_t CM_SHAPER_RAMA_START_CNTL_R; + uint32_t CM_SHAPER_RAMA_REGION_0_1; + uint32_t CM_SHAPER_RAMA_REGION_2_3; + uint32_t CM_SHAPER_RAMA_REGION_4_5; + uint32_t CM_SHAPER_RAMA_REGION_6_7; + uint32_t CM_SHAPER_RAMA_REGION_8_9; + uint32_t CM_SHAPER_RAMA_REGION_10_11; + uint32_t CM_SHAPER_RAMA_REGION_12_13; + uint32_t CM_SHAPER_RAMA_REGION_14_15; + uint32_t CM_SHAPER_RAMA_REGION_16_17; + uint32_t CM_SHAPER_RAMA_REGION_18_19; + uint32_t CM_SHAPER_RAMA_REGION_20_21; + uint32_t CM_SHAPER_RAMA_REGION_22_23; + uint32_t CM_SHAPER_RAMA_REGION_24_25; + uint32_t CM_SHAPER_RAMA_REGION_26_27; + uint32_t CM_SHAPER_RAMA_REGION_28_29; + uint32_t CM_SHAPER_RAMA_REGION_30_31; + uint32_t CM_SHAPER_RAMA_REGION_32_33; + uint32_t CM_SHAPER_LUT_INDEX; + uint32_t CM_SHAPER_LUT_DATA; + + }; struct dcn10_dpp { -- cgit From 2248eb6b4f1fdd7aded987d178a95b021d3a1d91 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Tue, 25 Jul 2017 22:52:45 -0400 Subject: drm/amd/display: log HUBP using DTN logging also simplify DTN INFO. all we need is a way to have DC log register states some where we can compare with golden. going through connectivity is overkill. Signed-off-by: Tony Cheng Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 9 ++++ .../gpu/drm/amd/display/dc/basics/log_helpers.c | 28 ------------ drivers/gpu/drm/amd/display/dc/basics/logger.c | 3 +- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 53 +++++++++++++++++++--- .../gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c | 34 ++++++++++++++ .../gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h | 18 ++++++++ drivers/gpu/drm/amd/display/dc/dm_helpers.h | 6 --- drivers/gpu/drm/amd/display/dc/dm_services.h | 12 +++++ .../gpu/drm/amd/display/include/logger_interface.h | 24 +++++----- 9 files changed, 133 insertions(+), 54 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index df4d221e46c1..6c19a07709df 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -327,6 +327,15 @@ bool dm_helpers_dc_conn_log(struct dc_context *ctx, struct log_entry *entry, enu return true; } +void dm_dtn_log_begin(struct dc_context *ctx) +{} + +void dm_dtn_log_append_v(struct dc_context *ctx, + const char *pMsg, ...) +{} + +void dm_dtn_log_end(struct dc_context *ctx) +{} bool dm_helpers_dp_mst_start_top_mgr( struct dc_context *ctx, diff --git a/drivers/gpu/drm/amd/display/dc/basics/log_helpers.c b/drivers/gpu/drm/amd/display/dc/basics/log_helpers.c index 070ae6f680e1..785b943b60ed 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/log_helpers.c +++ b/drivers/gpu/drm/amd/display/dc/basics/log_helpers.c @@ -100,31 +100,3 @@ void dc_conn_log(struct dc_context *ctx, va_end(args); } - -void dc_raw_log(struct dc_context *ctx, - enum dc_log_type event, - const char *msg, - ...) -{ - va_list args; - struct log_entry entry = { 0 }; - - dm_logger_open(ctx->logger, &entry, event); - - va_start(args, msg); - entry.buf_offset += dm_log_to_buffer( - &entry.buf[entry.buf_offset], - LOG_MAX_LINE_SIZE - entry.buf_offset, - msg, args); - - if (entry.buf[strlen(entry.buf) - 1] == '\n') { - entry.buf[strlen(entry.buf) - 1] = '\0'; - entry.buf_offset--; - } - - dm_logger_append(&entry, "^\n"); - dm_helpers_dc_conn_log(ctx, &entry, event); - dm_logger_close(&entry); - - va_end(args); -} diff --git a/drivers/gpu/drm/amd/display/dc/basics/logger.c b/drivers/gpu/drm/amd/display/dc/basics/logger.c index dfd23783cc47..0b17374b1535 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/logger.c +++ b/drivers/gpu/drm/amd/display/dc/basics/logger.c @@ -428,8 +428,7 @@ void dm_logger_open( logger->open_count++; - if (log_type != LOG_DTN) - log_heading(entry); + log_heading(entry); } void dm_logger_close(struct log_entry *entry) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 03f404808a1c..e738387d8ba3 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -31,9 +31,9 @@ #include "dce110/dce110_hw_sequencer.h" #include "dce/dce_hwseq.h" #include "abm.h" +#include "dcn10/dcn10_mem_input.h" #include "dcn10/dcn10_dpp.h" #include "dcn10/dcn10_mpc.h" -#include "mem_input.h" #include "timing_generator.h" #include "opp.h" #include "ipp.h" @@ -2402,22 +2402,61 @@ static void dcn10_setup_stereo(struct pipe_ctx *pipe_ctx, struct core_dc *dc) return; } -static void dcn10_log_hw_state(struct core_dc *dc) + +static void log_mpc_crc(struct core_dc *dc) { struct dc_context *dc_ctx = dc->ctx; struct dce_hwseq *hws = dc->hwseq; - DTN_INFO("Hello World"); - if (REG(MPC_CRC_RESULT_GB)) DTN_INFO("MPC_CRC_RESULT_GB:%d MPC_CRC_RESULT_C:%d MPC_CRC_RESULT_AR:%d\n", REG_READ(MPC_CRC_RESULT_GB), REG_READ(MPC_CRC_RESULT_C), REG_READ(MPC_CRC_RESULT_AR)); if (REG(DPP_TOP0_DPP_CRC_VAL_B_A)) DTN_INFO("DPP_TOP0_DPP_CRC_VAL_B_A:%d DPP_TOP0_DPP_CRC_VAL_R_G:%d\n", REG_READ(DPP_TOP0_DPP_CRC_VAL_B_A), REG_READ(DPP_TOP0_DPP_CRC_VAL_R_G)); - /* todo: add meaningful register reads and print out HW state - * - */ +} + +static void dcn10_log_hw_state(struct core_dc *dc) +{ + struct dc_context *dc_ctx = dc->ctx; + struct resource_pool *pool = dc->res_pool; + int i; + + DTN_INFO_BEGIN(); + + DTN_INFO("HUBP:\t format \t addr_hi \t width \t height \t rotation \t" + "mirror \t sw_mode \t dcc_en \t blank_en \t ttu_dis \t" + "min_ttu_vblank \t qos_low_wm \t qos_high_wm \n"); + + for (i = 0; i < pool->pipe_count; i++) { + struct mem_input *mi = pool->mis[i]; + struct dcn_hubp_state s; + + dcn10_mem_input_read_state(TO_DCN10_MEM_INPUT(mi), &s); + + DTN_INFO("[%d]:\t %xh \t %xh \t %d \t %d \t %xh \t %xh \t " + "%d \t %d \t %d \t %d \t" + "%d \t %d \t %d \n", + i, + s.pixel_format, + s.inuse_addr_hi, + s.viewport_width, + s.viewport_height, + s.rotation_angle, + s.h_mirror_en, + s.sw_mode, + s.dcc_en, + s.blank_en, + s.ttu_disable, + s.min_ttu_vblank, + s.qos_level_low_wm, + s.qos_level_high_wm); + } + DTN_INFO("\n"); + + log_mpc_crc(dc); + + DTN_INFO_END(); } static void dcn10_wait_for_mpcc_disconnect( diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index c56a69b5a4d7..6f01db6a51dd 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -804,6 +804,40 @@ static void min_set_viewport( PRI_VIEWPORT_Y_START_C, viewport_c->y); } +void dcn10_mem_input_read_state(struct dcn10_mem_input *mi, + struct dcn_hubp_state *s) +{ + REG_GET(DCSURF_SURFACE_CONFIG, + SURFACE_PIXEL_FORMAT, &s->pixel_format); + + REG_GET(DCSURF_SURFACE_EARLIEST_INUSE_HIGH, + SURFACE_EARLIEST_INUSE_ADDRESS_HIGH, &s->inuse_addr_hi); + + REG_GET_2(DCSURF_PRI_VIEWPORT_DIMENSION, + PRI_VIEWPORT_WIDTH, &s->viewport_width, + PRI_VIEWPORT_HEIGHT, &s->viewport_height); + + REG_GET_2(DCSURF_SURFACE_CONFIG, + ROTATION_ANGLE, &s->rotation_angle, + H_MIRROR_EN, &s->h_mirror_en); + + REG_GET(DCSURF_TILING_CONFIG, + SW_MODE, &s->sw_mode); + + REG_GET(DCSURF_SURFACE_CONTROL, + PRIMARY_SURFACE_DCC_EN, &s->dcc_en); + + REG_GET_2(DCHUBP_CNTL, + HUBP_BLANK_EN, &s->blank_en, + HUBP_TTU_DISABLE, &s->ttu_disable); + + REG_GET(DCN_GLOBAL_TTU_CNTL, + MIN_TTU_VBLANK, &s->min_ttu_vblank); + + REG_GET_2(DCN_TTU_QOS_WM, + QoS_LEVEL_LOW_WM, &s->qos_level_low_wm, + QoS_LEVEL_HIGH_WM, &s->qos_level_high_wm); +} static struct mem_input_funcs dcn10_mem_input_funcs = { .mem_input_program_display_marks = min10_program_display_marks, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h index 9130f5e0ab03..4f4e2c0708d5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h @@ -579,4 +579,22 @@ bool dcn10_mem_input_construct( const struct dcn_mi_shift *mi_shift, const struct dcn_mi_mask *mi_mask); +struct dcn_hubp_state { + uint32_t pixel_format; + uint32_t inuse_addr_hi; + uint32_t viewport_width; + uint32_t viewport_height; + uint32_t rotation_angle; + uint32_t h_mirror_en; + uint32_t sw_mode; + uint32_t dcc_en; + uint32_t blank_en; + uint32_t ttu_disable; + uint32_t min_ttu_vblank; + uint32_t qos_level_low_wm; + uint32_t qos_level_high_wm; +}; +void dcn10_mem_input_read_state(struct dcn10_mem_input *mi, + struct dcn_hubp_state *s); + #endif diff --git a/drivers/gpu/drm/amd/display/dc/dm_helpers.h b/drivers/gpu/drm/amd/display/dc/dm_helpers.h index a831421c7ea0..e8bd501feb48 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_helpers.h +++ b/drivers/gpu/drm/amd/display/dc/dm_helpers.h @@ -68,15 +68,9 @@ bool dm_helpers_dp_mst_start_top_mgr( const struct dc_link *link, bool boot); -bool dm_helpers_dc_conn_log( - struct dc_context*ctx, - struct log_entry *entry, - enum dc_log_type event); - void dm_helpers_dp_mst_stop_top_mgr( struct dc_context *ctx, const struct dc_link *link); - /** * OS specific aux read callback. */ diff --git a/drivers/gpu/drm/amd/display/dc/dm_services.h b/drivers/gpu/drm/amd/display/dc/dm_services.h index ea494a71a80b..e9bf4c417cc7 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services.h @@ -463,4 +463,16 @@ bool dm_dmcu_set_pipe(struct dc_context *ctx, unsigned int controller_id); #define dm_log_to_buffer(buffer, size, fmt, args)\ vsnprintf(buffer, size, fmt, args) +/* + * Debug and verification hooks + */ +bool dm_helpers_dc_conn_log( + struct dc_context *ctx, + struct log_entry *entry, + enum dc_log_type event); + +void dm_dtn_log_begin(struct dc_context *ctx); +void dm_dtn_log_append_v(struct dc_context *ctx, const char *msg, ...); +void dm_dtn_log_end(struct dc_context *ctx); + #endif /* __DM_SERVICES_H__ */ diff --git a/drivers/gpu/drm/amd/display/include/logger_interface.h b/drivers/gpu/drm/amd/display/include/logger_interface.h index 3adf3cfc7aba..0a872472ecba 100644 --- a/drivers/gpu/drm/amd/display/include/logger_interface.h +++ b/drivers/gpu/drm/amd/display/include/logger_interface.h @@ -70,11 +70,6 @@ void dc_conn_log(struct dc_context *ctx, const char *msg, ...); -void dc_raw_log(struct dc_context *ctx, - enum dc_log_type event, - const char *msg, - ...); - void logger_write(struct dal_logger *logger, enum dc_log_type log_type, const char *msg, @@ -121,16 +116,11 @@ void context_clock_trace( #define DC_ERROR(...) \ dm_logger_write(dc_ctx->logger, LOG_ERROR, \ - __VA_ARGS__); - -#define DTN_INFO(...) \ - dc_raw_log(dc_ctx, LOG_DTN, \ __VA_ARGS__) #define DC_SYNC_INFO(...) \ dm_logger_write(dc_ctx->logger, LOG_SYNC, \ - __VA_ARGS__); - + __VA_ARGS__) /* Connectivity log format: * [time stamp] [drm] [Major_minor] [connector name] message..... @@ -155,4 +145,16 @@ void context_clock_trace( dc_conn_log(link->ctx, link, NULL, 0, \ LOG_EVENT_MODE_SET, ##__VA_ARGS__) +/* + * Display Test Next logging + */ +#define DTN_INFO_BEGIN() \ + dm_dtn_log_begin(dc_ctx) + +#define DTN_INFO(msg, ...) \ + dm_dtn_log_append_v(dc_ctx, msg, ##__VA_ARGS__) + +#define DTN_INFO_END() \ + dm_dtn_log_end(dc_ctx) + #endif /* __DAL_LOGGER_INTERFACE_H__ */ -- cgit From 4fa086b9b6640818c053c79d4d7104790ba76cb7 Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Tue, 25 Jul 2017 20:51:26 -0400 Subject: drm/amd/display: Roll core_stream into dc_stream Signed-off-by: Leo (Sunpeng) Li Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 10 +- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.h | 2 +- drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c | 16 +- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 92 ++++---- drivers/gpu/drm/amd/display/dc/core/dc.c | 107 ++++----- drivers/gpu/drm/amd/display/dc/core/dc_debug.c | 4 +- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 41 ++-- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 7 +- drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 259 ++++++++++----------- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 118 +++++----- drivers/gpu/drm/amd/display/dc/dc.h | 71 +++--- .../gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 10 +- .../gpu/drm/amd/display/dc/dce/dce_link_encoder.h | 2 +- .../drm/amd/display/dc/dce100/dce100_resource.c | 12 +- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 176 +++++++------- .../drm/amd/display/dc/dce110/dce110_resource.c | 46 ++-- .../drm/amd/display/dc/dce112/dce112_resource.c | 16 +- .../drm/amd/display/dc/dce112/dce112_resource.h | 2 +- .../gpu/drm/amd/display/dc/dce80/dce80_resource.c | 12 +- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 72 +++--- .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 36 +-- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 33 +-- drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h | 4 +- .../gpu/drm/amd/display/dc/inc/hw/link_encoder.h | 3 +- drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 2 +- drivers/gpu/drm/amd/display/dc/inc/resource.h | 14 +- .../amd/display/dc/virtual/virtual_link_encoder.c | 2 +- .../drm/amd/display/modules/freesync/freesync.c | 60 +++-- .../gpu/drm/amd/display/modules/inc/mod_freesync.h | 28 +-- 31 files changed, 612 insertions(+), 649 deletions(-) (limited to 'drivers/gpu') 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 696a4112c8d9..c802437f4858 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1401,7 +1401,7 @@ static int amdgpu_notify_freesync(struct drm_device *dev, void *data, num_streams = dc_get_current_stream_count(adev->dm.dc); for (i = 0; i < num_streams; i++) { - const struct dc_stream *stream; + struct dc_stream *stream; stream = dc_get_stream_at_index(adev->dm.dc, i); mod_freesync_update_state(adev->dm.freesync_module, diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 0fcd9b373172..80d4e2670cc2 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2196,7 +2196,7 @@ static bool is_scaling_state_different( static void remove_stream( struct amdgpu_device *adev, struct amdgpu_crtc *acrtc, - const struct dc_stream *stream) + struct dc_stream *stream) { /* this is the update mode case */ if (adev->dm.freesync_module) @@ -2351,7 +2351,7 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, uint32_t i; struct drm_plane *plane; struct drm_plane_state *old_plane_state; - const struct dc_stream *dc_stream_attach; + struct dc_stream *dc_stream_attach; struct dc_surface *dc_surfaces_constructed[MAX_SURFACES]; struct amdgpu_crtc *acrtc_attach = to_amdgpu_crtc(pcrtc); struct dm_crtc_state *acrtc_state = to_dm_crtc_state(pcrtc->state); @@ -2487,7 +2487,7 @@ void amdgpu_dm_atomic_commit_tail( struct drm_crtc *crtc, *pcrtc; struct drm_crtc_state *old_crtc_state; struct amdgpu_crtc *new_crtcs[MAX_STREAMS]; - const struct dc_stream *new_stream; + struct dc_stream *new_stream = NULL; unsigned long flags; bool wait_for_vblank = true; struct drm_connector *connector; @@ -2822,8 +2822,8 @@ static uint32_t add_val_sets_surface( static uint32_t update_in_val_sets_stream( struct dc_validation_set *val_sets, uint32_t set_count, - const struct dc_stream *old_stream, - const struct dc_stream *new_stream, + struct dc_stream *old_stream, + struct dc_stream *new_stream, struct drm_crtc *crtc) { uint32_t i = 0; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h index c565787cd782..94de6a3736fc 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h @@ -45,7 +45,7 @@ struct dm_plane_state { struct dm_crtc_state { struct drm_crtc_state base; - const struct dc_stream *stream; + struct dc_stream *stream; }; #define to_dm_crtc_state(x) container_of(x, struct dm_crtc_state, base) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c index 5ef44ff4bcf8..9a850227eeeb 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c @@ -2610,9 +2610,9 @@ static void populate_initial_data( data->fbc_en[num_displays + 4] = false; data->lpt_en[num_displays + 4] = false; - data->h_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->public.timing.h_total); - data->v_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->public.timing.v_total); - data->pixel_rate[num_displays + 4] = bw_frc_to_fixed(pipe[i].stream->public.timing.pix_clk_khz, 1000); + data->h_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->timing.h_total); + data->v_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->timing.v_total); + data->pixel_rate[num_displays + 4] = bw_frc_to_fixed(pipe[i].stream->timing.pix_clk_khz, 1000); data->src_width[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.viewport.width); data->pitch_in_pixels[num_displays + 4] = data->src_width[num_displays + 4]; data->src_height[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.viewport.height); @@ -2707,9 +2707,9 @@ static void populate_initial_data( data->fbc_en[num_displays + 4] = false; data->lpt_en[num_displays + 4] = false; - data->h_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->public.timing.h_total); - data->v_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->public.timing.v_total); - data->pixel_rate[num_displays + 4] = bw_frc_to_fixed(pipe[i].stream->public.timing.pix_clk_khz, 1000); + data->h_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->timing.h_total); + data->v_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->timing.v_total); + data->pixel_rate[num_displays + 4] = bw_frc_to_fixed(pipe[i].stream->timing.pix_clk_khz, 1000); if (pipe[i].surface) { data->src_width[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.viewport.width); data->pitch_in_pixels[num_displays + 4] = data->src_width[num_displays + 4]; @@ -2759,9 +2759,9 @@ static void populate_initial_data( break; } } else { - data->src_width[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->public.timing.h_addressable); + data->src_width[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->timing.h_addressable); data->pitch_in_pixels[num_displays + 4] = data->src_width[num_displays + 4]; - data->src_height[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->public.timing.v_addressable); + data->src_height[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->timing.v_addressable); data->h_taps[num_displays + 4] = bw_int_to_fixed(1); data->v_taps[num_displays + 4] = bw_int_to_fixed(1); data->h_scale_ratio[num_displays + 4] = bw_int_to_fixed(1); diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 1651b7548d40..ef10a8b49379 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -365,7 +365,7 @@ static void pipe_ctx_to_e2e_pipe_params ( } - input->dest.vactive = pipe->stream->public.timing.v_addressable; + input->dest.vactive = pipe->stream->timing.v_addressable; input->dest.recout_width = pipe->scl_data.recout.width; input->dest.recout_height = pipe->scl_data.recout.height; @@ -373,24 +373,24 @@ static void pipe_ctx_to_e2e_pipe_params ( input->dest.full_recout_width = pipe->scl_data.recout.width; input->dest.full_recout_height = pipe->scl_data.recout.height; - input->dest.htotal = pipe->stream->public.timing.h_total; - input->dest.hblank_start = input->dest.htotal - pipe->stream->public.timing.h_front_porch; + input->dest.htotal = pipe->stream->timing.h_total; + input->dest.hblank_start = input->dest.htotal - pipe->stream->timing.h_front_porch; input->dest.hblank_end = input->dest.hblank_start - - pipe->stream->public.timing.h_addressable - - pipe->stream->public.timing.h_border_left - - pipe->stream->public.timing.h_border_right; + - pipe->stream->timing.h_addressable + - pipe->stream->timing.h_border_left + - pipe->stream->timing.h_border_right; - input->dest.vtotal = pipe->stream->public.timing.v_total; - input->dest.vblank_start = input->dest.vtotal - pipe->stream->public.timing.v_front_porch; + input->dest.vtotal = pipe->stream->timing.v_total; + input->dest.vblank_start = input->dest.vtotal - pipe->stream->timing.v_front_porch; input->dest.vblank_end = input->dest.vblank_start - - pipe->stream->public.timing.v_addressable - - pipe->stream->public.timing.v_border_bottom - - pipe->stream->public.timing.v_border_top; - - input->dest.vsync_plus_back_porch = pipe->stream->public.timing.v_total - - pipe->stream->public.timing.v_addressable - - pipe->stream->public.timing.v_front_porch; - input->dest.pixel_rate_mhz = pipe->stream->public.timing.pix_clk_khz/1000.0; + - pipe->stream->timing.v_addressable + - pipe->stream->timing.v_border_bottom + - pipe->stream->timing.v_border_top; + + input->dest.vsync_plus_back_porch = pipe->stream->timing.v_total + - pipe->stream->timing.v_addressable + - pipe->stream->timing.v_front_porch; + input->dest.pixel_rate_mhz = pipe->stream->timing.pix_clk_khz/1000.0; input->dest.vstartup_start = pipe->pipe_dlg_param.vstartup_start; input->dest.vupdate_offset = pipe->pipe_dlg_param.vupdate_offset; input->dest.vupdate_offset = pipe->pipe_dlg_param.vupdate_offset; @@ -851,14 +851,14 @@ bool dcn_validate_bandwidth( v->underscan_output[input_idx] = false; /* taken care of in recout already*/ v->interlace_output[input_idx] = false; - v->htotal[input_idx] = pipe->stream->public.timing.h_total; - v->vtotal[input_idx] = pipe->stream->public.timing.v_total; - v->v_sync_plus_back_porch[input_idx] = pipe->stream->public.timing.v_total - - pipe->stream->public.timing.v_addressable - - pipe->stream->public.timing.v_front_porch; - v->vactive[input_idx] = pipe->stream->public.timing.v_addressable; - v->pixel_clock[input_idx] = pipe->stream->public.timing.pix_clk_khz / 1000.0f; - if (pipe->stream->public.timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) + v->htotal[input_idx] = pipe->stream->timing.h_total; + v->vtotal[input_idx] = pipe->stream->timing.v_total; + v->v_sync_plus_back_porch[input_idx] = pipe->stream->timing.v_total + - pipe->stream->timing.v_addressable + - pipe->stream->timing.v_front_porch; + v->vactive[input_idx] = pipe->stream->timing.v_addressable; + v->pixel_clock[input_idx] = pipe->stream->timing.pix_clk_khz / 1000.0f; + if (pipe->stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) v->pixel_clock[input_idx] /= 2; @@ -867,10 +867,10 @@ bool dcn_validate_bandwidth( v->source_pixel_format[input_idx] = dcn_bw_rgb_sub_32; v->source_surface_mode[input_idx] = dcn_bw_sw_4_kb_s; v->lb_bit_per_pixel[input_idx] = 30; - v->viewport_width[input_idx] = pipe->stream->public.timing.h_addressable; - v->viewport_height[input_idx] = pipe->stream->public.timing.v_addressable; - v->scaler_rec_out_width[input_idx] = pipe->stream->public.timing.h_addressable; - v->scaler_recout_height[input_idx] = pipe->stream->public.timing.v_addressable; + v->viewport_width[input_idx] = pipe->stream->timing.h_addressable; + v->viewport_height[input_idx] = pipe->stream->timing.v_addressable; + v->scaler_rec_out_width[input_idx] = pipe->stream->timing.h_addressable; + v->scaler_recout_height[input_idx] = pipe->stream->timing.v_addressable; v->override_hta_ps[input_idx] = 1; v->override_vta_ps[input_idx] = 1; v->override_hta_pschroma[input_idx] = 1; @@ -995,22 +995,22 @@ bool dcn_validate_bandwidth( pipe->pipe_dlg_param.vready_offset = v->v_ready_offset[input_idx]; pipe->pipe_dlg_param.vstartup_start = v->v_startup[input_idx]; - pipe->pipe_dlg_param.htotal = pipe->stream->public.timing.h_total; - pipe->pipe_dlg_param.vtotal = pipe->stream->public.timing.v_total; - vesa_sync_start = pipe->stream->public.timing.v_addressable + - pipe->stream->public.timing.v_border_bottom + - pipe->stream->public.timing.v_front_porch; + pipe->pipe_dlg_param.htotal = pipe->stream->timing.h_total; + pipe->pipe_dlg_param.vtotal = pipe->stream->timing.v_total; + vesa_sync_start = pipe->stream->timing.v_addressable + + pipe->stream->timing.v_border_bottom + + pipe->stream->timing.v_front_porch; - asic_blank_end = (pipe->stream->public.timing.v_total - + asic_blank_end = (pipe->stream->timing.v_total - vesa_sync_start - - pipe->stream->public.timing.v_border_top) - * (pipe->stream->public.timing.flags.INTERLACE ? 1 : 0); + pipe->stream->timing.v_border_top) + * (pipe->stream->timing.flags.INTERLACE ? 1 : 0); asic_blank_start = asic_blank_end + - (pipe->stream->public.timing.v_border_top + - pipe->stream->public.timing.v_addressable + - pipe->stream->public.timing.v_border_bottom) - * (pipe->stream->public.timing.flags.INTERLACE ? 1 : 0); + (pipe->stream->timing.v_border_top + + pipe->stream->timing.v_addressable + + pipe->stream->timing.v_border_bottom) + * (pipe->stream->timing.flags.INTERLACE ? 1 : 0); pipe->pipe_dlg_param.vblank_start = asic_blank_start; pipe->pipe_dlg_param.vblank_end = asic_blank_end; @@ -1019,13 +1019,13 @@ bool dcn_validate_bandwidth( struct pipe_ctx *hsplit_pipe = pipe->bottom_pipe; if (v->dpp_per_plane[input_idx] == 2 || - ((pipe->stream->public.view_format == + ((pipe->stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE || - pipe->stream->public.view_format == + pipe->stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) && - (pipe->stream->public.timing.timing_3d_format == + (pipe->stream->timing.timing_3d_format == TIMING_3D_FORMAT_TOP_AND_BOTTOM || - pipe->stream->public.timing.timing_3d_format == + pipe->stream->timing.timing_3d_format == TIMING_3D_FORMAT_SIDE_BY_SIDE))) { if (hsplit_pipe && hsplit_pipe->surface == pipe->surface) { /* update previously split pipe */ @@ -1034,8 +1034,8 @@ bool dcn_validate_bandwidth( hsplit_pipe->pipe_dlg_param.vready_offset = v->v_ready_offset[input_idx]; hsplit_pipe->pipe_dlg_param.vstartup_start = v->v_startup[input_idx]; - hsplit_pipe->pipe_dlg_param.htotal = pipe->stream->public.timing.h_total; - hsplit_pipe->pipe_dlg_param.vtotal = pipe->stream->public.timing.v_total; + hsplit_pipe->pipe_dlg_param.htotal = pipe->stream->timing.h_total; + hsplit_pipe->pipe_dlg_param.vtotal = pipe->stream->timing.v_total; hsplit_pipe->pipe_dlg_param.vblank_start = pipe->pipe_dlg_param.vblank_start; hsplit_pipe->pipe_dlg_param.vblank_end = pipe->pipe_dlg_param.vblank_end; } else { diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index bab07f8d4880..df8c5ca6b22a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -149,19 +149,19 @@ failed_alloc: } static bool stream_adjust_vmin_vmax(struct dc *dc, - const struct dc_stream **stream, int num_streams, + struct dc_stream **streams, int num_streams, int vmin, int vmax) { /* TODO: Support multiple streams */ struct core_dc *core_dc = DC_TO_CORE(dc); - struct core_stream *core_stream = DC_STREAM_TO_CORE(stream[0]); + struct dc_stream *stream = streams[0]; int i = 0; bool ret = false; for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe = &core_dc->current_context->res_ctx.pipe_ctx[i]; - if (pipe->stream == core_stream && pipe->stream_enc) { + if (pipe->stream == stream && pipe->stream_enc) { core_dc->hwss.set_drr(&pipe, 1, vmin, vmax); /* build and update the info frame */ @@ -175,12 +175,12 @@ static bool stream_adjust_vmin_vmax(struct dc *dc, } static bool stream_get_crtc_position(struct dc *dc, - const struct dc_stream **stream, int num_streams, + struct dc_stream **streams, int num_streams, unsigned int *v_pos, unsigned int *nom_v_pos) { /* TODO: Support multiple streams */ struct core_dc *core_dc = DC_TO_CORE(dc); - struct core_stream *core_stream = DC_STREAM_TO_CORE(stream[0]); + struct dc_stream *stream = streams[0]; int i = 0; bool ret = false; struct crtc_position position; @@ -189,7 +189,7 @@ static bool stream_get_crtc_position(struct dc *dc, struct pipe_ctx *pipe = &core_dc->current_context->res_ctx.pipe_ctx[i]; - if (pipe->stream == core_stream && pipe->stream_enc) { + if (pipe->stream == stream && pipe->stream_enc) { core_dc->hwss.get_position(&pipe, 1, &position); *v_pos = position.vertical_count; @@ -203,15 +203,12 @@ static bool stream_get_crtc_position(struct dc *dc, static bool set_gamut_remap(struct dc *dc, const struct dc_stream *stream) { struct core_dc *core_dc = DC_TO_CORE(dc); - struct core_stream *core_stream = DC_STREAM_TO_CORE(stream); int i = 0; bool ret = false; struct pipe_ctx *pipes; for (i = 0; i < MAX_PIPES; i++) { - if (core_dc->current_context->res_ctx.pipe_ctx[i].stream - == core_stream) { - + if (core_dc->current_context->res_ctx.pipe_ctx[i].stream == stream) { pipes = &core_dc->current_context->res_ctx.pipe_ctx[i]; core_dc->hwss.program_gamut_remap(pipes); ret = true; @@ -221,22 +218,21 @@ static bool set_gamut_remap(struct dc *dc, const struct dc_stream *stream) return ret; } -static bool program_csc_matrix(struct dc *dc, const struct dc_stream *stream) +static bool program_csc_matrix(struct dc *dc, struct dc_stream *stream) { struct core_dc *core_dc = DC_TO_CORE(dc); - struct core_stream *core_stream = DC_STREAM_TO_CORE(stream); int i = 0; bool ret = false; struct pipe_ctx *pipes; for (i = 0; i < MAX_PIPES; i++) { if (core_dc->current_context->res_ctx.pipe_ctx[i].stream - == core_stream) { + == stream) { pipes = &core_dc->current_context->res_ctx.pipe_ctx[i]; core_dc->hwss.program_csc_matrix(pipes, - core_stream->public.output_color_space, - core_stream->public.csc_color_matrix.matrix); + stream->output_color_space, + stream->csc_color_matrix.matrix); ret = true; } } @@ -245,7 +241,7 @@ static bool program_csc_matrix(struct dc *dc, const struct dc_stream *stream) } static void set_static_screen_events(struct dc *dc, - const struct dc_stream **stream, + struct dc_stream **streams, int num_streams, const struct dc_static_screen_events *events) { @@ -256,11 +252,11 @@ static void set_static_screen_events(struct dc *dc, int num_pipes_affected = 0; for (i = 0; i < num_streams; i++) { - struct core_stream *core_stream = DC_STREAM_TO_CORE(stream[i]); + struct dc_stream *stream = streams[i]; for (j = 0; j < MAX_PIPES; j++) { if (core_dc->current_context->res_ctx.pipe_ctx[j].stream - == core_stream) { + == stream) { pipes_affected[num_pipes_affected++] = &core_dc->current_context->res_ctx.pipe_ctx[j]; } @@ -337,10 +333,9 @@ static void set_test_pattern( cust_pattern_size); } -void set_dither_option(const struct dc_stream *dc_stream, +void set_dither_option(struct dc_stream *stream, enum dc_dither_option option) { - struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); struct bit_depth_reduction_params params; struct dc_link *link = stream->status.link; struct pipe_ctx *pipes = link->dc->current_context->res_ctx.pipe_ctx; @@ -351,21 +346,21 @@ void set_dither_option(const struct dc_stream *dc_stream, if (option > DITHER_OPTION_MAX) return; if (option == DITHER_OPTION_DEFAULT) { - switch (stream->public.timing.display_color_depth) { + switch (stream->timing.display_color_depth) { case COLOR_DEPTH_666: - stream->public.dither_option = DITHER_OPTION_SPATIAL6; + stream->dither_option = DITHER_OPTION_SPATIAL6; break; case COLOR_DEPTH_888: - stream->public.dither_option = DITHER_OPTION_SPATIAL8; + stream->dither_option = DITHER_OPTION_SPATIAL8; break; case COLOR_DEPTH_101010: - stream->public.dither_option = DITHER_OPTION_SPATIAL10; + stream->dither_option = DITHER_OPTION_SPATIAL10; break; default: option = DITHER_OPTION_DISABLE; } } else { - stream->public.dither_option = option; + stream->dither_option = option; } resource_build_bit_depth_reduction_params(stream, ¶ms); @@ -644,7 +639,7 @@ static bool is_validation_required( if (set[i].surface_count != context->stream_status[i].surface_count) return true; - if (!is_stream_unchanged(DC_STREAM_TO_CORE(set[i].stream), context->streams[i])) + if (!is_stream_unchanged(set[i].stream, context->streams[i])) return true; for (j = 0; j < set[i].surface_count; j++) { @@ -754,7 +749,7 @@ context_alloc_fail: bool dc_validate_guaranteed( const struct dc *dc, - const struct dc_stream *stream) + struct dc_stream *stream) { struct core_dc *core_dc = DC_TO_CORE(dc); enum dc_status result = DC_ERROR_UNEXPECTED; @@ -869,7 +864,7 @@ static bool context_changed( return true; for (i = 0; i < dc->current_context->stream_count; i++) { - if (&dc->current_context->streams[i]->public != &context->streams[i]->public) + if (dc->current_context->streams[i] != context->streams[i]) return true; } @@ -878,7 +873,7 @@ static bool context_changed( static bool streams_changed( struct core_dc *dc, - const struct dc_stream *streams[], + struct dc_stream *streams[], uint8_t stream_count) { uint8_t i; @@ -887,7 +882,7 @@ static bool streams_changed( return true; for (i = 0; i < dc->current_context->stream_count; i++) { - if (&dc->current_context->streams[i]->public != streams[i]) + if (dc->current_context->streams[i] != streams[i]) return true; } @@ -897,7 +892,7 @@ static bool streams_changed( bool dc_enable_stereo( struct dc *dc, struct validate_context *context, - const struct dc_stream *streams[], + struct dc_stream *streams[], uint8_t stream_count) { bool ret = true; @@ -915,7 +910,7 @@ bool dc_enable_stereo( else pipe = &core_dc->current_context->res_ctx.pipe_ctx[i]; for (j = 0 ; pipe && j < stream_count; j++) { - if (streams[j] && streams[j] == &pipe->stream->public && + if (streams[j] && streams[j] == pipe->stream && core_dc->hwss.setup_stereo) core_dc->hwss.setup_stereo(pipe, core_dc); } @@ -943,10 +938,10 @@ static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *c enum dc_status result = DC_ERROR_UNEXPECTED; struct pipe_ctx *pipe; int i, j, k, l; - const struct dc_stream *dc_streams[MAX_STREAMS] = {0}; + struct dc_stream *dc_streams[MAX_STREAMS] = {0}; for (i = 0; i < context->stream_count; i++) - dc_streams[i] = &context->streams[i]->public; + dc_streams[i] = context->streams[i]; if (!dcb->funcs->is_accelerated_mode(dcb)) core_dc->hwss.enable_accelerated_mode(core_dc); @@ -985,11 +980,11 @@ static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *c } CONN_MSG_MODE(sink->link, "{%dx%d, %dx%d@%dKhz}", - context->streams[i]->public.timing.h_addressable, - context->streams[i]->public.timing.v_addressable, - context->streams[i]->public.timing.h_total, - context->streams[i]->public.timing.v_total, - context->streams[i]->public.timing.pix_clk_khz); + context->streams[i]->timing.h_addressable, + context->streams[i]->timing.v_addressable, + context->streams[i]->timing.h_total, + context->streams[i]->timing.v_total, + context->streams[i]->timing.pix_clk_khz); } dc_enable_stereo(dc, context, dc_streams, context->stream_count); @@ -1016,7 +1011,7 @@ bool dc_commit_context(struct dc *dc, struct validate_context *context) __func__, context->stream_count); for (i = 0; i < context->stream_count; i++) { - const struct dc_stream *stream = &context->streams[i]->public; + struct dc_stream *stream = context->streams[i]; dc_stream_log(stream, core_dc->ctx->logger, @@ -1031,7 +1026,7 @@ bool dc_commit_context(struct dc *dc, struct validate_context *context) bool dc_commit_streams( struct dc *dc, - const struct dc_stream *streams[], + struct dc_stream *streams[], uint8_t stream_count) { struct core_dc *core_dc = DC_TO_CORE(dc); @@ -1047,8 +1042,8 @@ bool dc_commit_streams( __func__, stream_count); for (i = 0; i < stream_count; i++) { - const struct dc_stream *stream = streams[i]; - const struct dc_stream_status *status = dc_stream_get_status(stream); + struct dc_stream *stream = streams[i]; + struct dc_stream_status *status = dc_stream_get_status(stream); int j; dc_stream_log(stream, @@ -1120,7 +1115,7 @@ bool dc_commit_surfaces_to_stream( struct dc *dc, struct dc_surface **new_surfaces, uint8_t new_surface_count, - const struct dc_stream *dc_stream) + struct dc_stream *dc_stream) { struct dc_surface_update updates[MAX_SURFACES]; struct dc_flip_addrs flip_addr[MAX_SURFACES]; @@ -1377,7 +1372,7 @@ enum surface_update_type update_surface_trace_level = UPDATE_TYPE_FULL; void dc_update_surfaces_and_stream(struct dc *dc, struct dc_surface_update *srf_updates, int surface_count, - const struct dc_stream *dc_stream, + struct dc_stream *stream, struct dc_stream_update *stream_update) { struct core_dc *core_dc = DC_TO_CORE(dc); @@ -1385,7 +1380,6 @@ void dc_update_surfaces_and_stream(struct dc *dc, int i, j; enum surface_update_type update_type; const struct dc_stream_status *stream_status; - struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); struct dc_context *dc_ctx = core_dc->ctx; /* Currently this function do not result in any HW programming @@ -1398,7 +1392,8 @@ void dc_update_surfaces_and_stream(struct dc *dc, if (surface_count == 0) return; - stream_status = dc_stream_get_status(dc_stream); + stream_status = dc_stream_get_status(stream); + ASSERT(stream_status); if (!stream_status) return; /* Cannot commit surface to stream that is not committed */ @@ -1415,19 +1410,19 @@ void dc_update_surfaces_and_stream(struct dc *dc, if (stream_update) { if ((stream_update->src.height != 0) && (stream_update->src.width != 0)) - stream->public.src = stream_update->src; + stream->src = stream_update->src; if ((stream_update->dst.height != 0) && (stream_update->dst.width != 0)) - stream->public.dst = stream_update->dst; + stream->dst = stream_update->dst; if (stream_update->out_transfer_func && stream_update->out_transfer_func != - dc_stream->out_transfer_func) { - if (dc_stream->out_transfer_func != NULL) - dc_transfer_func_release(dc_stream->out_transfer_func); + stream->out_transfer_func) { + if (stream->out_transfer_func != NULL) + dc_transfer_func_release(stream->out_transfer_func); dc_transfer_func_retain(stream_update->out_transfer_func); - stream->public.out_transfer_func = + stream->out_transfer_func = stream_update->out_transfer_func; } } @@ -1469,7 +1464,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, /* add surface to context */ if (!resource_attach_surfaces_to_context( - new_surfaces, surface_count, dc_stream, + new_surfaces, surface_count, stream, context, core_dc->res_pool)) { BREAK_TO_DEBUGGER(); goto fail; @@ -1617,7 +1612,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, core_dc, pipe_ctx->surface, context); /* TODO: this is a hack w/a for switching from mpo to pipe split */ - dc_stream_set_cursor_position(&pipe_ctx->stream->public, &position); + dc_stream_set_cursor_position(pipe_ctx->stream, &position); if (is_new_pipe_surface) { core_dc->hwss.update_plane_addr(core_dc, pipe_ctx); @@ -1712,7 +1707,7 @@ struct dc_stream *dc_get_stream_at_index(const struct dc *dc, uint8_t i) { struct core_dc *core_dc = DC_TO_CORE(dc); if (i < core_dc->current_context->stream_count) - return &(core_dc->current_context->streams[i]->public); + return core_dc->current_context->streams[i]; return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c index 9a5df3a848b5..bf127a88e533 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c @@ -321,8 +321,8 @@ void context_timing_trace( TIMING_TRACE("OTG_%d H_tot:%d V_tot:%d H_pos:%d V_pos:%d\n", pipe_ctx->tg->inst, - pipe_ctx->stream->public.timing.h_total, - pipe_ctx->stream->public.timing.v_total, + pipe_ctx->stream->timing.h_total, + pipe_ctx->stream->timing.v_total, h_pos[i], v_pos[i]); } } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index fd2ae181cff2..2487046457c8 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1143,7 +1143,7 @@ static void dpcd_configure_panel_mode( static void enable_stream_features(struct pipe_ctx *pipe_ctx) { - struct core_stream *stream = pipe_ctx->stream; + struct dc_stream *stream = pipe_ctx->stream; struct dc_link *link = stream->sink->link; union down_spread_ctrl downspread; @@ -1151,7 +1151,7 @@ static void enable_stream_features(struct pipe_ctx *pipe_ctx) &downspread.raw, sizeof(downspread)); downspread.bits.IGNORE_MSA_TIMING_PARAM = - (stream->public.ignore_msa_timing_param) ? 1 : 0; + (stream->ignore_msa_timing_param) ? 1 : 0; core_link_write_dpcd(link, DP_DOWNSPREAD_CTRL, &downspread.raw, sizeof(downspread)); @@ -1159,7 +1159,7 @@ static void enable_stream_features(struct pipe_ctx *pipe_ctx) static enum dc_status enable_link_dp(struct pipe_ctx *pipe_ctx) { - struct core_stream *stream = pipe_ctx->stream; + struct dc_stream *stream = pipe_ctx->stream; enum dc_status status; bool skip_video_pattern; struct dc_link *link = stream->sink->link; @@ -1250,7 +1250,7 @@ static enum dc_status enable_link_dp_mst(struct pipe_ctx *pipe_ctx) static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) { - struct core_stream *stream = pipe_ctx->stream; + struct dc_stream *stream = pipe_ctx->stream; struct dc_link *link = stream->sink->link; enum dc_color_depth display_color_depth; @@ -1258,13 +1258,13 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) dal_ddc_service_write_scdc_data( stream->sink->link->ddc, stream->phy_pix_clk, - stream->public.timing.flags.LTE_340MCSC_SCRAMBLE); + stream->timing.flags.LTE_340MCSC_SCRAMBLE); memset(&stream->sink->link->cur_link_settings, 0, sizeof(struct dc_link_settings)); - display_color_depth = stream->public.timing.display_color_depth; - if (stream->public.timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) + display_color_depth = stream->timing.display_color_depth; + if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) display_color_depth = COLOR_DEPTH_888; link->link_enc->funcs->enable_tmds_output( @@ -1341,7 +1341,7 @@ static void disable_link(struct dc_link *link, enum signal_type signal) } enum dc_status dc_link_validate_mode_timing( - const struct core_stream *stream, + const struct dc_stream *stream, struct dc_link *link, const struct dc_crtc_timing *timing) { @@ -1377,7 +1377,6 @@ bool dc_link_set_backlight_level(const struct dc_link *link, uint32_t level, uint32_t frame_ramp, const struct dc_stream *stream) { struct core_dc *core_dc = DC_TO_CORE(link->ctx->dc); - struct core_stream *core_stream = NULL; struct abm *abm = core_dc->res_pool->abm; unsigned int controller_id = 0; int i; @@ -1390,11 +1389,10 @@ bool dc_link_set_backlight_level(const struct dc_link *link, uint32_t level, if (dc_is_embedded_signal(link->connector_signal)) { if (stream != NULL) { - core_stream = DC_STREAM_TO_CORE(stream); for (i = 0; i < MAX_PIPES; i++) { if (core_dc->current_context->res_ctx. pipe_ctx[i].stream - == core_stream) + == stream) /* DMCU -1 for all controller id values, * therefore +1 here */ @@ -1457,7 +1455,6 @@ bool dc_link_setup_psr(struct dc_link *link, { struct core_dc *core_dc = DC_TO_CORE(link->ctx->dc); struct dmcu *dmcu = core_dc->res_pool->dmcu; - struct core_stream *core_stream = DC_STREAM_TO_CORE(stream); int i; psr_context->controllerId = CONTROLLER_ID_UNDEFINED; @@ -1501,7 +1498,7 @@ bool dc_link_setup_psr(struct dc_link *link, for (i = 0; i < MAX_PIPES; i++) { if (core_dc->current_context->res_ctx.pipe_ctx[i].stream - == core_stream) { + == stream) { /* dmcu -1 for all controller id values, * therefore +1 here */ @@ -1590,7 +1587,7 @@ void core_link_resume(struct dc_link *link) program_hpd_filter(link); } -static struct fixed31_32 get_pbn_per_slot(struct core_stream *stream) +static struct fixed31_32 get_pbn_per_slot(struct dc_stream *stream) { struct dc_link_settings *link_settings = &stream->sink->link->cur_link_settings; @@ -1699,7 +1696,7 @@ static void update_mst_stream_alloc_table( */ static enum dc_status allocate_mst_payload(struct pipe_ctx *pipe_ctx) { - struct core_stream *stream = pipe_ctx->stream; + struct dc_stream *stream = pipe_ctx->stream; struct dc_link *link = stream->sink->link; struct link_encoder *link_encoder = link->link_enc; struct stream_encoder *stream_encoder = pipe_ctx->stream_enc; @@ -1717,7 +1714,7 @@ static enum dc_status allocate_mst_payload(struct pipe_ctx *pipe_ctx) /* get calculate VC payload for stream: stream_alloc */ if (dm_helpers_dp_mst_write_payload_allocation_table( stream->ctx, - &stream->public, + stream, &proposed_table, true)) { update_mst_stream_alloc_table( @@ -1759,11 +1756,11 @@ static enum dc_status allocate_mst_payload(struct pipe_ctx *pipe_ctx) /* send down message */ dm_helpers_dp_mst_poll_for_allocation_change_trigger( stream->ctx, - &stream->public); + stream); dm_helpers_dp_mst_send_payload_allocation( stream->ctx, - &stream->public, + stream, true); /* slot X.Y for only current stream */ @@ -1781,7 +1778,7 @@ static enum dc_status allocate_mst_payload(struct pipe_ctx *pipe_ctx) static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx) { - struct core_stream *stream = pipe_ctx->stream; + struct dc_stream *stream = pipe_ctx->stream; struct dc_link *link = stream->sink->link; struct link_encoder *link_encoder = link->link_enc; struct stream_encoder *stream_encoder = pipe_ctx->stream_enc; @@ -1806,7 +1803,7 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx) if (mst_mode) { if (dm_helpers_dp_mst_write_payload_allocation_table( stream->ctx, - &stream->public, + stream, &proposed_table, false)) { @@ -1848,11 +1845,11 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx) if (mst_mode) { dm_helpers_dp_mst_poll_for_allocation_change_trigger( stream->ctx, - &stream->public); + stream); dm_helpers_dp_mst_send_payload_allocation( stream->ctx, - &stream->public, + stream, false); } 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 c7b400786121..d9754b5f2543 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 @@ -1434,7 +1434,7 @@ bool dp_validate_mode_timing( return false; } -void decide_link_settings(struct core_stream *stream, +void decide_link_settings(struct dc_stream *stream, struct dc_link_settings *link_setting) { @@ -1446,8 +1446,7 @@ void decide_link_settings(struct core_stream *stream, uint32_t req_bw; uint32_t link_bw; - req_bw = bandwidth_in_kbps_from_timing( - &stream->public.timing); + req_bw = bandwidth_in_kbps_from_timing(&stream->timing); link = stream->sink->link; @@ -2327,7 +2326,7 @@ static void set_crtc_test_pattern(struct dc_link *link, { enum controller_dp_test_pattern controller_test_pattern; enum dc_color_depth color_depth = pipe_ctx-> - stream->public.timing.display_color_depth; + stream->timing.display_color_depth; struct bit_depth_reduction_params params; memset(¶ms, 0, sizeof(params)); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 5bdcd5067116..76dc16916821 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -78,7 +78,7 @@ void dp_enable_link_phy( pipes[i].clock_source->id != CLOCK_SOURCE_ID_DP_DTO) { pipes[i].clock_source = dp_cs; pipes[i].pix_clk_params.requested_pix_clk = - pipes[i].stream->public.timing.pix_clk_khz; + pipes[i].stream->timing.pix_clk_khz; pipes[i].clock_source->funcs->program_pix_clk( pipes[i].clock_source, &pipes[i].pix_clk_params, diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index eeefc9c33633..ddbd3de63a8d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -294,25 +294,25 @@ void resource_reference_clock_source( } bool resource_are_streams_timing_synchronizable( - const struct core_stream *stream1, - const struct core_stream *stream2) + struct dc_stream *stream1, + struct dc_stream *stream2) { - if (stream1->public.timing.h_total != stream2->public.timing.h_total) + if (stream1->timing.h_total != stream2->timing.h_total) return false; - if (stream1->public.timing.v_total != stream2->public.timing.v_total) + if (stream1->timing.v_total != stream2->timing.v_total) return false; - if (stream1->public.timing.h_addressable - != stream2->public.timing.h_addressable) + if (stream1->timing.h_addressable + != stream2->timing.h_addressable) return false; - if (stream1->public.timing.v_addressable - != stream2->public.timing.v_addressable) + if (stream1->timing.v_addressable + != stream2->timing.v_addressable) return false; - if (stream1->public.timing.pix_clk_khz - != stream2->public.timing.pix_clk_khz) + if (stream1->timing.pix_clk_khz + != stream2->timing.pix_clk_khz) return false; if (stream1->phy_pix_clk != stream2->phy_pix_clk @@ -431,7 +431,7 @@ static void rect_swap_helper(struct rect *rect) static void calculate_viewport(struct pipe_ctx *pipe_ctx) { const struct dc_surface *surface = pipe_ctx->surface; - const struct dc_stream *stream = &pipe_ctx->stream->public; + const struct dc_stream *stream = pipe_ctx->stream; struct scaler_data *data = &pipe_ctx->scl_data; struct rect surf_src = surface->src_rect; struct rect clip = { 0 }; @@ -530,7 +530,7 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip) { const struct dc_surface *surface = pipe_ctx->surface; - struct core_stream *stream = pipe_ctx->stream; + const struct dc_stream *stream = pipe_ctx->stream; struct rect surf_src = surface->src_rect; struct rect surf_clip = surface->clip_rect; int recout_full_x, recout_full_y; @@ -539,38 +539,38 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip pipe_ctx->surface->rotation == ROTATION_ANGLE_270) rect_swap_helper(&surf_src); - pipe_ctx->scl_data.recout.x = stream->public.dst.x; - if (stream->public.src.x < surf_clip.x) + pipe_ctx->scl_data.recout.x = stream->dst.x; + if (stream->src.x < surf_clip.x) pipe_ctx->scl_data.recout.x += (surf_clip.x - - stream->public.src.x) * stream->public.dst.width - / stream->public.src.width; + - stream->src.x) * stream->dst.width + / stream->src.width; pipe_ctx->scl_data.recout.width = surf_clip.width * - stream->public.dst.width / stream->public.src.width; + stream->dst.width / stream->src.width; if (pipe_ctx->scl_data.recout.width + pipe_ctx->scl_data.recout.x > - stream->public.dst.x + stream->public.dst.width) + stream->dst.x + stream->dst.width) pipe_ctx->scl_data.recout.width = - stream->public.dst.x + stream->public.dst.width + stream->dst.x + stream->dst.width - pipe_ctx->scl_data.recout.x; - pipe_ctx->scl_data.recout.y = stream->public.dst.y; - if (stream->public.src.y < surf_clip.y) + pipe_ctx->scl_data.recout.y = stream->dst.y; + if (stream->src.y < surf_clip.y) pipe_ctx->scl_data.recout.y += (surf_clip.y - - stream->public.src.y) * stream->public.dst.height - / stream->public.src.height; + - stream->src.y) * stream->dst.height + / stream->src.height; pipe_ctx->scl_data.recout.height = surf_clip.height * - stream->public.dst.height / stream->public.src.height; + stream->dst.height / stream->src.height; if (pipe_ctx->scl_data.recout.height + pipe_ctx->scl_data.recout.y > - stream->public.dst.y + stream->public.dst.height) + stream->dst.y + stream->dst.height) pipe_ctx->scl_data.recout.height = - stream->public.dst.y + stream->public.dst.height + stream->dst.y + stream->dst.height - pipe_ctx->scl_data.recout.y; /* Handle h & vsplit */ if (pipe_ctx->top_pipe && pipe_ctx->top_pipe->surface == pipe_ctx->surface) { - if (stream->public.view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) { + if (stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) { pipe_ctx->scl_data.recout.height /= 2; pipe_ctx->scl_data.recout.y += pipe_ctx->scl_data.recout.height; /* Floor primary pipe, ceil 2ndary pipe */ @@ -582,7 +582,7 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip } } else if (pipe_ctx->bottom_pipe && pipe_ctx->bottom_pipe->surface == pipe_ctx->surface) { - if (stream->public.view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) + if (stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) pipe_ctx->scl_data.recout.height /= 2; else pipe_ctx->scl_data.recout.width /= 2; @@ -592,14 +592,14 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip * * 1/ stream scaling ratio) - (surf surf_src offset * 1/ full scl * ratio) */ - recout_full_x = stream->public.dst.x + (surface->dst_rect.x - stream->public.src.x) - * stream->public.dst.width / stream->public.src.width - + recout_full_x = stream->dst.x + (surface->dst_rect.x - stream->src.x) + * stream->dst.width / stream->src.width - surf_src.x * surface->dst_rect.width / surf_src.width - * stream->public.dst.width / stream->public.src.width; - recout_full_y = stream->public.dst.y + (surface->dst_rect.y - stream->public.src.y) - * stream->public.dst.height / stream->public.src.height - + * stream->dst.width / stream->src.width; + recout_full_y = stream->dst.y + (surface->dst_rect.y - stream->src.y) + * stream->dst.height / stream->src.height - surf_src.y * surface->dst_rect.height / surf_src.height - * stream->public.dst.height / stream->public.src.height; + * stream->dst.height / stream->src.height; recout_skip->width = pipe_ctx->scl_data.recout.x - recout_full_x; recout_skip->height = pipe_ctx->scl_data.recout.y - recout_full_y; @@ -608,12 +608,12 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) { const struct dc_surface *surface = pipe_ctx->surface; - struct core_stream *stream = pipe_ctx->stream; + const struct dc_stream *stream = pipe_ctx->stream; struct rect surf_src = surface->src_rect; - const int in_w = stream->public.src.width; - const int in_h = stream->public.src.height; - const int out_w = stream->public.dst.width; - const int out_h = stream->public.dst.height; + const int in_w = stream->src.width; + const int in_h = stream->src.height; + const int out_w = stream->dst.width; + const int out_h = stream->dst.height; if (pipe_ctx->surface->rotation == ROTATION_ANGLE_90 || pipe_ctx->surface->rotation == ROTATION_ANGLE_270) @@ -626,9 +626,9 @@ static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) surf_src.height, surface->dst_rect.height); - if (stream->public.view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE) + if (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE) pipe_ctx->scl_data.ratios.horz.value *= 2; - else if (stream->public.view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) + else if (stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) pipe_ctx->scl_data.ratios.vert.value *= 2; pipe_ctx->scl_data.ratios.vert.value = div64_s64( @@ -815,7 +815,7 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *r bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) { const struct dc_surface *surface = pipe_ctx->surface; - struct dc_crtc_timing *timing = &pipe_ctx->stream->public.timing; + struct dc_crtc_timing *timing = &pipe_ctx->stream->timing; struct view recout_skip = { 0 }; bool res = false; @@ -920,7 +920,7 @@ struct pipe_ctx *find_idle_secondary_pipe( struct pipe_ctx *resource_get_head_pipe_for_stream( struct resource_context *res_ctx, - const struct core_stream *stream) + struct dc_stream *stream) { int i; for (i = 0; i < MAX_PIPES; i++) { @@ -940,11 +940,10 @@ struct pipe_ctx *resource_get_head_pipe_for_stream( static struct pipe_ctx *acquire_free_pipe_for_stream( struct validate_context *context, const struct resource_pool *pool, - const struct dc_stream *dc_stream) + struct dc_stream *stream) { int i; struct resource_context *res_ctx = &context->res_ctx; - struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); struct pipe_ctx *head_pipe = NULL; @@ -980,10 +979,9 @@ static struct pipe_ctx *acquire_free_pipe_for_stream( static void release_free_pipes_for_stream( struct resource_context *res_ctx, - const struct dc_stream *dc_stream) + struct dc_stream *stream) { int i; - struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); for (i = MAX_PIPES - 1; i >= 0; i--) { /* never release the topmost pipe*/ @@ -999,7 +997,7 @@ static void release_free_pipes_for_stream( static int acquire_first_split_pipe( struct resource_context *res_ctx, const struct resource_pool *pool, - struct core_stream *stream) + struct dc_stream *stream) { int i; @@ -1033,14 +1031,13 @@ static int acquire_first_split_pipe( bool resource_attach_surfaces_to_context( struct dc_surface * const *surfaces, int surface_count, - const struct dc_stream *dc_stream, + struct dc_stream *stream, struct validate_context *context, const struct resource_pool *pool) { int i; struct pipe_ctx *tail_pipe; struct dc_stream_status *stream_status = NULL; - struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); if (surface_count > MAX_SURFACE_NUM) { @@ -1050,7 +1047,7 @@ bool resource_attach_surfaces_to_context( } for (i = 0; i < context->stream_count; i++) - if (&context->streams[i]->public == dc_stream) { + if (context->streams[i] == stream) { stream_status = &context->stream_status[i]; break; } @@ -1081,7 +1078,7 @@ bool resource_attach_surfaces_to_context( for (i = 0; i < surface_count; i++) { struct dc_surface *surface = surfaces[i]; struct pipe_ctx *free_pipe = acquire_free_pipe_for_stream( - context, pool, dc_stream); + context, pool, stream); #if defined(CONFIG_DRM_AMD_DC_DCN1_0) if (!free_pipe) { @@ -1109,7 +1106,7 @@ bool resource_attach_surfaces_to_context( tail_pipe = free_pipe; } - release_free_pipes_for_stream(&context->res_ctx, dc_stream); + release_free_pipes_for_stream(&context->res_ctx, stream); /* assign new surfaces*/ for (i = 0; i < surface_count; i++) @@ -1121,8 +1118,8 @@ bool resource_attach_surfaces_to_context( } -static bool is_timing_changed(const struct core_stream *cur_stream, - const struct core_stream *new_stream) +static bool is_timing_changed(struct dc_stream *cur_stream, + struct dc_stream *new_stream) { if (cur_stream == NULL) return true; @@ -1134,18 +1131,17 @@ static bool is_timing_changed(const struct core_stream *cur_stream, return true; /* If output color space is changed, need to reprogram info frames */ - if (cur_stream->public.output_color_space != - new_stream->public.output_color_space) + if (cur_stream->output_color_space != new_stream->output_color_space) return true; return memcmp( - &cur_stream->public.timing, - &new_stream->public.timing, + &cur_stream->timing, + &new_stream->timing, sizeof(struct dc_crtc_timing)) != 0; } static bool are_stream_backends_same( - const struct core_stream *stream_a, const struct core_stream *stream_b) + struct dc_stream *stream_a, struct dc_stream *stream_b) { if (stream_a == stream_b) return true; @@ -1160,7 +1156,7 @@ static bool are_stream_backends_same( } bool is_stream_unchanged( - const struct core_stream *old_stream, const struct core_stream *stream) + struct dc_stream *old_stream, struct dc_stream *stream) { if (!are_stream_backends_same(old_stream, stream)) @@ -1186,7 +1182,7 @@ bool resource_validate_attach_surfaces( if (!resource_attach_surfaces_to_context( old_context->stream_status[j].surfaces, old_context->stream_status[j].surface_count, - &context->streams[i]->public, + context->streams[i], context, pool)) return false; context->stream_status[i] = old_context->stream_status[j]; @@ -1195,7 +1191,7 @@ bool resource_validate_attach_surfaces( if (!resource_attach_surfaces_to_context( set[i].surfaces, set[i].surface_count, - &context->streams[i]->public, + context->streams[i], context, pool)) return false; @@ -1237,7 +1233,7 @@ static void set_audio_in_use( static int acquire_first_free_pipe( struct resource_context *res_ctx, const struct resource_pool *pool, - struct core_stream *stream) + struct dc_stream *stream) { int i; @@ -1267,7 +1263,7 @@ static int acquire_first_free_pipe( static struct stream_encoder *find_first_free_match_stream_enc_for_link( struct resource_context *res_ctx, const struct resource_pool *pool, - struct core_stream *stream) + struct dc_stream *stream) { int i; int j = -1; @@ -1318,22 +1314,22 @@ static struct audio *find_first_free_audio( return 0; } -static void update_stream_signal(struct core_stream *stream) +static void update_stream_signal(struct dc_stream *stream) { - if (stream->public.output_signal == SIGNAL_TYPE_NONE) { - struct dc_sink *dc_sink = stream->public.sink; + if (stream->output_signal == SIGNAL_TYPE_NONE) { + struct dc_sink *dc_sink = stream->sink; if (dc_sink->sink_signal == SIGNAL_TYPE_NONE) stream->signal = stream->sink->link->connector_signal; else stream->signal = dc_sink->sink_signal; } else { - stream->signal = stream->public.output_signal; + stream->signal = stream->output_signal; } if (dc_is_dvi_signal(stream->signal)) { - if (stream->public.timing.pix_clk_khz > TMDS_MAX_PIXEL_CLOCK_IN_KHZ_UPMOST && - stream->public.sink->sink_signal != SIGNAL_TYPE_DVI_SINGLE_LINK) + if (stream->timing.pix_clk_khz > TMDS_MAX_PIXEL_CLOCK_IN_KHZ_UPMOST && + stream->sink->sink_signal != SIGNAL_TYPE_DVI_SINGLE_LINK) stream->signal = SIGNAL_TYPE_DVI_DUAL_LINK; else stream->signal = SIGNAL_TYPE_DVI_SINGLE_LINK; @@ -1341,12 +1337,12 @@ static void update_stream_signal(struct core_stream *stream) } bool resource_is_stream_unchanged( - const struct validate_context *old_context, const struct core_stream *stream) + struct validate_context *old_context, struct dc_stream *stream) { int i; for (i = 0; i < old_context->stream_count; i++) { - const struct core_stream *old_stream = old_context->streams[i]; + struct dc_stream *old_stream = old_context->streams[i]; if (are_stream_backends_same(old_stream, stream)) return true; @@ -1359,7 +1355,7 @@ static void copy_pipe_ctx( const struct pipe_ctx *from_pipe_ctx, struct pipe_ctx *to_pipe_ctx) { struct dc_surface *surface = to_pipe_ctx->surface; - struct core_stream *stream = to_pipe_ctx->stream; + struct dc_stream *stream = to_pipe_ctx->stream; *to_pipe_ctx = *from_pipe_ctx; to_pipe_ctx->stream = stream; @@ -1367,14 +1363,14 @@ static void copy_pipe_ctx( to_pipe_ctx->surface = surface; } -static struct core_stream *find_pll_sharable_stream( - const struct core_stream *stream_needs_pll, +static struct dc_stream *find_pll_sharable_stream( + struct dc_stream *stream_needs_pll, struct validate_context *context) { int i; for (i = 0; i < context->stream_count; i++) { - struct core_stream *stream_has_pll = context->streams[i]; + struct dc_stream *stream_has_pll = context->streams[i]; /* We are looking for non dp, non virtual stream */ if (resource_are_streams_timing_synchronizable( @@ -1418,17 +1414,17 @@ static int get_norm_pix_clk(const struct dc_crtc_timing *timing) return normalized_pix_clk; } -static void calculate_phy_pix_clks(struct core_stream *stream) +static void calculate_phy_pix_clks(struct dc_stream *stream) { update_stream_signal(stream); /* update actual pixel clock on all streams */ if (dc_is_hdmi_signal(stream->signal)) stream->phy_pix_clk = get_norm_pix_clk( - &stream->public.timing); + &stream->timing); else stream->phy_pix_clk = - stream->public.timing.pix_clk_khz; + stream->timing.pix_clk_khz; } enum dc_status resource_map_pool_resources( @@ -1440,7 +1436,7 @@ enum dc_status resource_map_pool_resources( int i, j; for (i = 0; old_context && i < context->stream_count; i++) { - struct core_stream *stream = context->streams[i]; + struct dc_stream *stream = context->streams[i]; if (!resource_is_stream_unchanged(old_context, stream)) { if (stream != NULL && old_context->streams[i] != NULL) { @@ -1493,7 +1489,7 @@ enum dc_status resource_map_pool_resources( } for (i = 0; i < context->stream_count; i++) { - struct core_stream *stream = context->streams[i]; + struct dc_stream *stream = context->streams[i]; struct pipe_ctx *pipe_ctx = NULL; int pipe_idx = -1; @@ -1524,7 +1520,7 @@ enum dc_status resource_map_pool_resources( /* TODO: Add check if ASIC support and EDID audio */ if (!stream->sink->converter_disable_audio && dc_is_audio_capable_signal(pipe_ctx->stream->signal) && - stream->public.audio_info.mode_count) { + stream->audio_info.mode_count) { pipe_ctx->audio = find_first_free_audio( &context->res_ctx, pool); @@ -1560,7 +1556,7 @@ void validate_guaranteed_copy_streams( context->res_ctx.pipe_ctx[i].stream = context->res_ctx.pipe_ctx[0].stream; - dc_stream_retain(&context->streams[i]->public); + dc_stream_retain(context->streams[i]); context->stream_count++; } } @@ -1588,7 +1584,7 @@ static void set_avi_info_frame( struct encoder_info_packet *info_packet, struct pipe_ctx *pipe_ctx) { - struct core_stream *stream = pipe_ctx->stream; + struct dc_stream *stream = pipe_ctx->stream; enum dc_color_space color_space = COLOR_SPACE_UNKNOWN; struct info_frame info_frame = { {0} }; uint32_t pixel_encoding = 0; @@ -1602,12 +1598,12 @@ static void set_avi_info_frame( uint8_t byte_index = 0; union hdmi_info_packet *hdmi_info = &info_frame.avi_info_packet.info_packet_hdmi; union display_content_support support = {0}; - unsigned int vic = pipe_ctx->stream->public.timing.vic; + unsigned int vic = pipe_ctx->stream->timing.vic; enum dc_timing_3d_format format; - color_space = pipe_ctx->stream->public.output_color_space; + color_space = pipe_ctx->stream->output_color_space; if (color_space == COLOR_SPACE_UNKNOWN) - color_space = (stream->public.timing.pixel_encoding == PIXEL_ENCODING_RGB)? + color_space = (stream->timing.pixel_encoding == PIXEL_ENCODING_RGB) ? COLOR_SPACE_SRGB:COLOR_SPACE_YCBCR709; /* Initialize header */ @@ -1622,7 +1618,7 @@ static void set_avi_info_frame( * according to HDMI 2.0 spec (Section 10.1) */ - switch (stream->public.timing.pixel_encoding) { + switch (stream->timing.pixel_encoding) { case PIXEL_ENCODING_YCBCR422: pixel_encoding = 1; break; @@ -1664,7 +1660,7 @@ static void set_avi_info_frame( color_space == COLOR_SPACE_YCBCR601_LIMITED) hdmi_info->bits.C0_C1 = COLORIMETRY_ITU601; else { - if (stream->public.timing.pixel_encoding != PIXEL_ENCODING_RGB) + if (stream->timing.pixel_encoding != PIXEL_ENCODING_RGB) BREAK_TO_DEBUGGER(); hdmi_info->bits.C0_C1 = COLORIMETRY_NO_DATA; } @@ -1679,7 +1675,7 @@ static void set_avi_info_frame( } /* TODO: un-hardcode aspect ratio */ - aspect = stream->public.timing.aspect_ratio; + aspect = stream->timing.aspect_ratio; switch (aspect) { case ASPECT_RATIO_4_3: @@ -1705,7 +1701,7 @@ static void set_avi_info_frame( itc = true; itc_value = 1; - support = stream->public.sink->edid_caps.content_support; + support = stream->sink->edid_caps.content_support; if (itc) { if (!support.bits.valid_content_type) { @@ -1744,8 +1740,8 @@ static void set_avi_info_frame( /* TODO : We should handle YCC quantization */ /* but we do not have matrix calculation */ - if (stream->public.sink->edid_caps.qs_bit == 1 && - stream->public.sink->edid_caps.qy_bit == 1) { + if (stream->sink->edid_caps.qs_bit == 1 && + stream->sink->edid_caps.qy_bit == 1) { if (color_space == COLOR_SPACE_SRGB || color_space == COLOR_SPACE_2020_RGB_FULLRANGE) { hdmi_info->bits.Q0_Q1 = RGB_QUANTIZATION_FULL_RANGE; @@ -1764,11 +1760,11 @@ static void set_avi_info_frame( } ///VIC - format = stream->public.timing.timing_3d_format; + format = stream->timing.timing_3d_format; /*todo, add 3DStereo support*/ if (format != TIMING_3D_FORMAT_NONE) { // Based on HDMI specs hdmi vic needs to be converted to cea vic when 3D is enabled - switch (pipe_ctx->stream->public.timing.hdmi_vic) { + switch (pipe_ctx->stream->timing.hdmi_vic) { case 1: vic = 95; break; @@ -1797,12 +1793,12 @@ static void set_avi_info_frame( * barBottom: Line Number of Start of Bottom Bar. * barLeft: Pixel Number of End of Left Bar. * barRight: Pixel Number of Start of Right Bar. */ - hdmi_info->bits.bar_top = stream->public.timing.v_border_top; - hdmi_info->bits.bar_bottom = (stream->public.timing.v_total - - stream->public.timing.v_border_bottom + 1); - hdmi_info->bits.bar_left = stream->public.timing.h_border_left; - hdmi_info->bits.bar_right = (stream->public.timing.h_total - - stream->public.timing.h_border_right + 1); + hdmi_info->bits.bar_top = stream->timing.v_border_top; + hdmi_info->bits.bar_bottom = (stream->timing.v_total + - stream->timing.v_border_bottom + 1); + hdmi_info->bits.bar_left = stream->timing.h_border_left; + hdmi_info->bits.bar_right = (stream->timing.h_total + - stream->timing.h_border_right + 1); /* check_sum - Calculate AFMT_AVI_INFO0 ~ AFMT_AVI_INFO3 */ check_sum = &info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.sb[0]; @@ -1830,7 +1826,7 @@ static void set_avi_info_frame( static void set_vendor_info_packet( struct encoder_info_packet *info_packet, - struct core_stream *stream) + struct dc_stream *stream) { uint32_t length = 0; bool hdmi_vic_mode = false; @@ -1842,16 +1838,16 @@ static void set_vendor_info_packet( info_packet->valid = false; - format = stream->public.timing.timing_3d_format; - if (stream->public.view_format == VIEW_3D_FORMAT_NONE) + format = stream->timing.timing_3d_format; + if (stream->view_format == VIEW_3D_FORMAT_NONE) format = TIMING_3D_FORMAT_NONE; /* Can be different depending on packet content */ length = 5; - if (stream->public.timing.hdmi_vic != 0 - && stream->public.timing.h_total >= 3840 - && stream->public.timing.v_total >= 2160) + if (stream->timing.hdmi_vic != 0 + && stream->timing.h_total >= 3840 + && stream->timing.v_total >= 2160) hdmi_vic_mode = true; /* According to HDMI 1.4a CTS, VSIF should be sent @@ -1918,7 +1914,7 @@ static void set_vendor_info_packet( /*PB5: If PB4 is set to 0x1 (extended resolution format) * fill PB5 with the correct HDMI VIC code */ if (hdmi_vic_mode) - info_packet->sb[5] = stream->public.timing.hdmi_vic; + info_packet->sb[5] = stream->timing.hdmi_vic; /* Header */ info_packet->hb0 = HDMI_INFOFRAME_TYPE_VENDOR; /* VSIF packet type. */ @@ -1943,7 +1939,7 @@ static void set_vendor_info_packet( static void set_spd_info_packet( struct encoder_info_packet *info_packet, - struct core_stream *stream) + struct dc_stream *stream) { /* SPD info packet for FreeSync */ @@ -1953,7 +1949,7 @@ static void set_spd_info_packet( /* Check if Freesync is supported. Return if false. If true, * set the corresponding bit in the info packet */ - if (stream->public.freesync_ctx.supported == false) + if (stream->freesync_ctx.supported == false) return; if (dc_is_hdmi_signal(stream->signal)) { @@ -2018,20 +2014,20 @@ static void set_spd_info_packet( /* PB6 = [Bits 7:3 = Reserved] */ info_packet->sb[6] = 0x00; - if (stream->public.freesync_ctx.supported == true) + if (stream->freesync_ctx.supported == true) /* PB6 = [Bit 0 = FreeSync Supported] */ info_packet->sb[6] |= 0x01; - if (stream->public.freesync_ctx.enabled == true) + if (stream->freesync_ctx.enabled == true) /* PB6 = [Bit 1 = FreeSync Enabled] */ info_packet->sb[6] |= 0x02; - if (stream->public.freesync_ctx.active == true) + if (stream->freesync_ctx.active == true) /* PB6 = [Bit 2 = FreeSync Active] */ info_packet->sb[6] |= 0x04; /* PB7 = FreeSync Minimum refresh rate (Hz) */ - info_packet->sb[7] = (unsigned char) (stream->public.freesync_ctx. + info_packet->sb[7] = (unsigned char) (stream->freesync_ctx. min_refresh_in_micro_hz / 1000000); /* PB8 = FreeSync Maximum refresh rate (Hz) @@ -2040,7 +2036,7 @@ static void set_spd_info_packet( * of the panel, because we should never go above the field * rate of the mode timing set. */ - info_packet->sb[8] = (unsigned char) (stream->public.freesync_ctx. + info_packet->sb[8] = (unsigned char) (stream->freesync_ctx. nominal_refresh_in_micro_hz / 1000000); /* PB9 - PB27 = Reserved */ @@ -2065,7 +2061,7 @@ static void set_spd_info_packet( static void set_hdr_static_info_packet( struct encoder_info_packet *info_packet, struct dc_surface *surface, - struct core_stream *stream) + struct dc_stream *stream) { uint16_t i = 0; enum signal_type signal = stream->signal; @@ -2168,7 +2164,7 @@ static void set_hdr_static_info_packet( static void set_vsc_info_packet( struct encoder_info_packet *info_packet, - struct core_stream *stream) + struct dc_stream *stream) { unsigned int vscPacketRevision = 0; unsigned int i; @@ -2218,7 +2214,7 @@ void dc_resource_validate_ctx_destruct(struct validate_context *context) context->stream_status[i].surfaces[j]); context->stream_status[i].surface_count = 0; - dc_stream_release(&context->streams[i]->public); + dc_stream_release(context->streams[i]); context->streams[i] = NULL; } } @@ -2248,7 +2244,7 @@ void dc_resource_validate_ctx_copy_construct( } for (i = 0; i < dst_ctx->stream_count; i++) { - dc_stream_retain(&dst_ctx->streams[i]->public); + dc_stream_retain(dst_ctx->streams[i]); for (j = 0; j < dst_ctx->stream_status[i].surface_count; j++) dc_surface_retain( dst_ctx->stream_status[i].surfaces[j]); @@ -2321,7 +2317,7 @@ enum dc_status resource_map_clock_resources( /* acquire new resources */ for (i = 0; i < context->stream_count; i++) { - const struct core_stream *stream = context->streams[i]; + struct dc_stream *stream = context->streams[i]; if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; @@ -2401,12 +2397,12 @@ bool pipe_need_reprogram( return false; } -void resource_build_bit_depth_reduction_params(const struct core_stream *stream, +void resource_build_bit_depth_reduction_params(struct dc_stream *stream, struct bit_depth_reduction_params *fmt_bit_depth) { - enum dc_dither_option option = stream->public.dither_option; + enum dc_dither_option option = stream->dither_option; enum dc_pixel_encoding pixel_encoding = - stream->public.timing.pixel_encoding; + stream->timing.pixel_encoding; memset(fmt_bit_depth, 0, sizeof(*fmt_bit_depth)); @@ -2511,31 +2507,30 @@ void resource_build_bit_depth_reduction_params(const struct core_stream *stream, fmt_bit_depth->pixel_encoding = pixel_encoding; } -bool dc_validate_stream(const struct dc *dc, const struct dc_stream *stream) +bool dc_validate_stream(const struct dc *dc, struct dc_stream *stream) { struct core_dc *core_dc = DC_TO_CORE(dc); struct dc_context *dc_ctx = core_dc->ctx; - struct core_stream *core_stream = DC_STREAM_TO_CORE(stream); - struct dc_link *link = core_stream->sink->link; + struct dc_link *link = stream->sink->link; struct timing_generator *tg = core_dc->res_pool->timing_generators[0]; enum dc_status res = DC_OK; - calculate_phy_pix_clks(core_stream); + calculate_phy_pix_clks(stream); - if (!tg->funcs->validate_timing(tg, &core_stream->public.timing)) + if (!tg->funcs->validate_timing(tg, &stream->timing)) res = DC_FAIL_CONTROLLER_VALIDATE; if (res == DC_OK) if (!link->link_enc->funcs->validate_output_with_stream( - link->link_enc, core_stream)) + link->link_enc, stream)) res = DC_FAIL_ENC_VALIDATE; /* TODO: validate audio ASIC caps, encoder */ if (res == DC_OK) - res = dc_link_validate_mode_timing(core_stream, + res = dc_link_validate_mode_timing(stream, link, - &core_stream->public.timing); + &stream->timing); if (res != DC_OK) DC_ERROR("Failed validation for stream %p, err:%d, !\n", diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 5b356ddf5614..46ad1bc12f63 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -35,24 +35,24 @@ ******************************************************************************/ struct stream { - struct core_stream protected; + struct dc_stream protected; int ref_count; }; -#define DC_STREAM_TO_STREAM(dc_stream) container_of(dc_stream, struct stream, protected.public) +#define DC_STREAM_TO_STREAM(dc_stream) container_of(dc_stream, struct stream, protected) /******************************************************************************* * Private functions ******************************************************************************/ -static bool construct(struct core_stream *stream, +static bool construct(struct dc_stream *stream, struct dc_sink *dc_sink_data) { uint32_t i = 0; stream->sink = dc_sink_data; stream->ctx = stream->sink->ctx; - stream->public.sink = dc_sink_data; + stream->sink = dc_sink_data; dc_sink_retain(dc_sink_data); @@ -60,52 +60,52 @@ static bool construct(struct core_stream *stream, /* TODO - Remove this translation */ for (i = 0; i < (dc_sink_data->edid_caps.audio_mode_count); i++) { - stream->public.audio_info.modes[i].channel_count = dc_sink_data->edid_caps.audio_modes[i].channel_count; - stream->public.audio_info.modes[i].format_code = dc_sink_data->edid_caps.audio_modes[i].format_code; - stream->public.audio_info.modes[i].sample_rates.all = dc_sink_data->edid_caps.audio_modes[i].sample_rate; - stream->public.audio_info.modes[i].sample_size = dc_sink_data->edid_caps.audio_modes[i].sample_size; + stream->audio_info.modes[i].channel_count = dc_sink_data->edid_caps.audio_modes[i].channel_count; + stream->audio_info.modes[i].format_code = dc_sink_data->edid_caps.audio_modes[i].format_code; + stream->audio_info.modes[i].sample_rates.all = dc_sink_data->edid_caps.audio_modes[i].sample_rate; + stream->audio_info.modes[i].sample_size = dc_sink_data->edid_caps.audio_modes[i].sample_size; } - stream->public.audio_info.mode_count = dc_sink_data->edid_caps.audio_mode_count; - stream->public.audio_info.audio_latency = dc_sink_data->edid_caps.audio_latency; - stream->public.audio_info.video_latency = dc_sink_data->edid_caps.video_latency; + stream->audio_info.mode_count = dc_sink_data->edid_caps.audio_mode_count; + stream->audio_info.audio_latency = dc_sink_data->edid_caps.audio_latency; + stream->audio_info.video_latency = dc_sink_data->edid_caps.video_latency; memmove( - stream->public.audio_info.display_name, + stream->audio_info.display_name, dc_sink_data->edid_caps.display_name, AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS); - stream->public.audio_info.manufacture_id = dc_sink_data->edid_caps.manufacturer_id; - stream->public.audio_info.product_id = dc_sink_data->edid_caps.product_id; - stream->public.audio_info.flags.all = dc_sink_data->edid_caps.speaker_flags; + stream->audio_info.manufacture_id = dc_sink_data->edid_caps.manufacturer_id; + stream->audio_info.product_id = dc_sink_data->edid_caps.product_id; + stream->audio_info.flags.all = dc_sink_data->edid_caps.speaker_flags; if (dc_sink_data->dc_container_id != NULL) { struct dc_container_id *dc_container_id = dc_sink_data->dc_container_id; - stream->public.audio_info.port_id[0] = dc_container_id->portId[0]; - stream->public.audio_info.port_id[1] = dc_container_id->portId[1]; + stream->audio_info.port_id[0] = dc_container_id->portId[0]; + stream->audio_info.port_id[1] = dc_container_id->portId[1]; } else { /* TODO - WindowDM has implemented, other DMs need Unhardcode port_id */ - stream->public.audio_info.port_id[0] = 0x5558859e; - stream->public.audio_info.port_id[1] = 0xd989449; + stream->audio_info.port_id[0] = 0x5558859e; + stream->audio_info.port_id[1] = 0xd989449; } /* EDID CAP translation for HDMI 2.0 */ - stream->public.timing.flags.LTE_340MCSC_SCRAMBLE = dc_sink_data->edid_caps.lte_340mcsc_scramble; + stream->timing.flags.LTE_340MCSC_SCRAMBLE = dc_sink_data->edid_caps.lte_340mcsc_scramble; stream->status.link = stream->sink->link; return true; } -static void destruct(struct core_stream *stream) +static void destruct(struct dc_stream *stream) { dc_sink_release(stream->sink); - if (stream->public.out_transfer_func != NULL) { + if (stream->out_transfer_func != NULL) { dc_transfer_func_release( - stream->public.out_transfer_func); - stream->public.out_transfer_func = NULL; + stream->out_transfer_func); + stream->out_transfer_func = NULL; } } -void dc_stream_retain(const struct dc_stream *dc_stream) +void dc_stream_retain(struct dc_stream *dc_stream) { struct stream *stream = DC_STREAM_TO_STREAM(dc_stream); @@ -113,17 +113,16 @@ void dc_stream_retain(const struct dc_stream *dc_stream) stream->ref_count++; } -void dc_stream_release(const struct dc_stream *public) +void dc_stream_release(struct dc_stream *public) { struct stream *stream = DC_STREAM_TO_STREAM(public); - struct core_stream *protected = DC_STREAM_TO_CORE(public); if (public != NULL) { ASSERT(stream->ref_count > 0); stream->ref_count--; if (stream->ref_count == 0) { - destruct(protected); + destruct(public); dm_free(stream); } } @@ -147,7 +146,7 @@ struct dc_stream *dc_create_stream_for_sink( stream->ref_count++; - return &stream->protected.public; + return &stream->protected; construct_fail: dm_free(stream); @@ -157,10 +156,9 @@ alloc_fail: } struct dc_stream_status *dc_stream_get_status( - const struct dc_stream *dc_stream) + struct dc_stream *stream) { uint8_t i; - struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); struct core_dc *dc = DC_TO_CORE(stream->ctx->dc); for (i = 0; i < dc->current_context->stream_count; i++) { @@ -176,15 +174,14 @@ struct dc_stream_status *dc_stream_get_status( * Update the cursor attributes and set cursor surface address */ bool dc_stream_set_cursor_attributes( - const struct dc_stream *dc_stream, + const struct dc_stream *stream, const struct dc_cursor_attributes *attributes) { int i; - struct core_stream *stream; struct core_dc *core_dc; struct resource_context *res_ctx; - if (NULL == dc_stream) { + if (NULL == stream) { dm_error("DC: dc_stream is NULL!\n"); return false; } @@ -193,7 +190,6 @@ bool dc_stream_set_cursor_attributes( return false; } - stream = DC_STREAM_TO_CORE(dc_stream); core_dc = DC_TO_CORE(stream->ctx->dc); res_ctx = &core_dc->current_context->res_ctx; @@ -213,15 +209,14 @@ bool dc_stream_set_cursor_attributes( } bool dc_stream_set_cursor_position( - const struct dc_stream *dc_stream, + struct dc_stream *stream, const struct dc_cursor_position *position) { int i; - struct core_stream *stream; struct core_dc *core_dc; struct resource_context *res_ctx; - if (NULL == dc_stream) { + if (NULL == stream) { dm_error("DC: dc_stream is NULL!\n"); return false; } @@ -231,7 +226,6 @@ bool dc_stream_set_cursor_position( return false; } - stream = DC_STREAM_TO_CORE(dc_stream); core_dc = DC_TO_CORE(stream->ctx->dc); res_ctx = &core_dc->current_context->res_ctx; @@ -240,7 +234,7 @@ bool dc_stream_set_cursor_position( struct input_pixel_processor *ipp = pipe_ctx->ipp; struct dc_cursor_position pos_cpy = *position; struct dc_cursor_mi_param param = { - .pixel_clk_khz = dc_stream->timing.pix_clk_khz, + .pixel_clk_khz = stream->timing.pix_clk_khz, .ref_clk_khz = core_dc->res_pool->ref_clock_inKhz, .viewport_x_start = pipe_ctx->scl_data.viewport.x, .viewport_width = pipe_ctx->scl_data.viewport.width, @@ -264,10 +258,9 @@ bool dc_stream_set_cursor_position( return true; } -uint32_t dc_stream_get_vblank_counter(const struct dc_stream *dc_stream) +uint32_t dc_stream_get_vblank_counter(const struct dc_stream *stream) { uint8_t i; - struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); struct core_dc *core_dc = DC_TO_CORE(stream->ctx->dc); struct resource_context *res_ctx = &core_dc->current_context->res_ctx; @@ -284,7 +277,7 @@ uint32_t dc_stream_get_vblank_counter(const struct dc_stream *dc_stream) return 0; } -bool dc_stream_get_scanoutpos(const struct dc_stream *dc_stream, +bool dc_stream_get_scanoutpos(const struct dc_stream *stream, uint32_t *v_blank_start, uint32_t *v_blank_end, uint32_t *h_position, @@ -292,7 +285,6 @@ bool dc_stream_get_scanoutpos(const struct dc_stream *dc_stream, { uint8_t i; bool ret = false; - struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); struct core_dc *core_dc = DC_TO_CORE(stream->ctx->dc); struct resource_context *res_ctx = &core_dc->current_context->res_ctx; @@ -322,37 +314,35 @@ void dc_stream_log( struct dal_logger *dm_logger, enum dc_log_type log_type) { - const struct core_stream *core_stream = - DC_STREAM_TO_CORE(stream); dm_logger_write(dm_logger, log_type, "core_stream 0x%x: src: %d, %d, %d, %d; dst: %d, %d, %d, %d, colorSpace:%d\n", - core_stream, - core_stream->public.src.x, - core_stream->public.src.y, - core_stream->public.src.width, - core_stream->public.src.height, - core_stream->public.dst.x, - core_stream->public.dst.y, - core_stream->public.dst.width, - core_stream->public.dst.height, - core_stream->public.output_color_space); + stream, + stream->src.x, + stream->src.y, + stream->src.width, + stream->src.height, + stream->dst.x, + stream->dst.y, + stream->dst.width, + stream->dst.height, + stream->output_color_space); dm_logger_write(dm_logger, log_type, "\tpix_clk_khz: %d, h_total: %d, v_total: %d, pixelencoder:%d, displaycolorDepth:%d\n", - core_stream->public.timing.pix_clk_khz, - core_stream->public.timing.h_total, - core_stream->public.timing.v_total, - core_stream->public.timing.pixel_encoding, - core_stream->public.timing.display_color_depth); + stream->timing.pix_clk_khz, + stream->timing.h_total, + stream->timing.v_total, + stream->timing.pixel_encoding, + stream->timing.display_color_depth); dm_logger_write(dm_logger, log_type, "\tsink name: %s, serial: %d\n", - core_stream->sink->edid_caps.display_name, - core_stream->sink->edid_caps.serial_number); + stream->sink->edid_caps.display_name, + stream->sink->edid_caps.serial_number); dm_logger_write(dm_logger, log_type, "\tlink: %d\n", - core_stream->sink->link->link_index); + stream->sink->link->link_index); } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index f87f6c12494c..b20f7bfcdc1f 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -32,6 +32,7 @@ #include "gpio_types.h" #include "link_service_types.h" #include "grph_object_ctrl_defs.h" +#include #define MAX_SURFACES 3 #define MAX_STREAMS 6 @@ -106,12 +107,12 @@ struct dc_cap_funcs { struct dc_stream_funcs { bool (*adjust_vmin_vmax)(struct dc *dc, - const struct dc_stream **stream, + struct dc_stream **stream, int num_streams, int vmin, int vmax); bool (*get_crtc_position)(struct dc *dc, - const struct dc_stream **stream, + struct dc_stream **stream, int num_streams, unsigned int *v_pos, unsigned int *nom_v_pos); @@ -120,14 +121,14 @@ struct dc_stream_funcs { const struct dc_stream *stream); bool (*program_csc_matrix)(struct dc *dc, - const struct dc_stream *stream); + struct dc_stream *stream); void (*set_static_screen_events)(struct dc *dc, - const struct dc_stream **stream, + struct dc_stream **stream, int num_streams, const struct dc_static_screen_events *events); - void (*set_dither_option)(const struct dc_stream *stream, + void (*set_dither_option)(struct dc_stream *stream, enum dc_dither_option option); }; @@ -428,7 +429,7 @@ bool dc_commit_surfaces_to_stream( struct dc *dc, struct dc_surface **dc_surfaces, uint8_t surface_count, - const struct dc_stream *stream); + struct dc_stream *stream); bool dc_post_update_surfaces_to_stream( struct dc *dc); @@ -468,6 +469,18 @@ enum surface_update_type { /******************************************************************************* * Stream Interfaces ******************************************************************************/ + +struct dc_stream_status { + int primary_otg_inst; + int surface_count; + struct dc_surface *surfaces[MAX_SURFACE_NUM]; + + /* + * link this stream passes through + */ + struct dc_link *link; +}; + struct dc_stream { struct dc_sink *sink; struct dc_crtc_timing timing; @@ -495,6 +508,21 @@ struct dc_stream { /* TODO: ABM info (DMCU) */ /* TODO: PSR info */ /* TODO: CEA VIC */ + + /* from core_stream struct */ + struct dc_context *ctx; + + /* used by DCP and FMT */ + struct bit_depth_reduction_params bit_depth_params; + struct clamping_and_pixel_encoding_params clamping; + + int phy_pix_clk; + enum signal_type signal; + + struct dc_stream_status status; + + /* from stream struct */ + int ref_count; }; struct dc_stream_update { @@ -521,7 +549,7 @@ struct dc_stream_update { void dc_update_surfaces_and_stream(struct dc *dc, struct dc_surface_update *surface_updates, int surface_count, - const struct dc_stream *dc_stream, + struct dc_stream *dc_stream, struct dc_stream_update *stream_update); /* @@ -554,12 +582,12 @@ bool dc_stream_get_scanoutpos(const struct dc_stream *stream, * Structure to store surface/stream associations for validation */ struct dc_validation_set { - const struct dc_stream *stream; + struct dc_stream *stream; struct dc_surface *surfaces[MAX_SURFACES]; uint8_t surface_count; }; -bool dc_validate_stream(const struct dc *dc, const struct dc_stream *stream); +bool dc_validate_stream(const struct dc *dc, struct dc_stream *stream); /* * This function takes a set of resources and checks that they are cofunctional. @@ -587,7 +615,7 @@ bool dc_validate_resources( bool dc_validate_guaranteed( const struct dc *dc, - const struct dc_stream *stream); + struct dc_stream *stream); void dc_resource_validate_ctx_copy_construct( const struct validate_context *src_ctx, @@ -616,7 +644,7 @@ bool dc_commit_context(struct dc *dc, struct validate_context *context); */ bool dc_commit_streams( struct dc *dc, - const struct dc_stream *streams[], + struct dc_stream *streams[], uint8_t stream_count); /* * Enable stereo when commit_streams is not required, @@ -625,7 +653,7 @@ bool dc_commit_streams( bool dc_enable_stereo( struct dc *dc, struct validate_context *context, - const struct dc_stream *streams[], + struct dc_stream *streams[], uint8_t stream_count); /** @@ -633,22 +661,11 @@ bool dc_enable_stereo( */ struct dc_stream *dc_create_stream_for_sink(struct dc_sink *dc_sink); -void dc_stream_retain(const struct dc_stream *dc_stream); -void dc_stream_release(const struct dc_stream *dc_stream); - -struct dc_stream_status { - int primary_otg_inst; - int surface_count; - struct dc_surface *surfaces[MAX_SURFACE_NUM]; - - /* - * link this stream passes through - */ - struct dc_link *link; -}; +void dc_stream_retain(struct dc_stream *dc_stream); +void dc_stream_release(struct dc_stream *dc_stream); struct dc_stream_status *dc_stream_get_status( - const struct dc_stream *dc_stream); + struct dc_stream *dc_stream); enum surface_update_type dc_check_update_surfaces_for_stream( struct dc *dc, @@ -915,7 +932,7 @@ bool dc_stream_set_cursor_attributes( const struct dc_cursor_attributes *attributes); bool dc_stream_set_cursor_position( - const struct dc_stream *stream, + struct dc_stream *stream, const struct dc_cursor_position *position); /* Newer interfaces */ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index aff0a440d4d3..24d0c48258ee 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -1009,7 +1009,7 @@ bool dce110_link_encoder_construct( bool dce110_link_encoder_validate_output_with_stream( struct link_encoder *enc, - const struct core_stream *stream) + const struct dc_stream *stream) { struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); bool is_valid; @@ -1021,22 +1021,22 @@ bool dce110_link_encoder_validate_output_with_stream( enc110, stream->sink->link->connector_signal, stream->signal, - &stream->public.timing); + &stream->timing); break; case SIGNAL_TYPE_HDMI_TYPE_A: is_valid = dce110_link_encoder_validate_hdmi_output( enc110, - &stream->public.timing, + &stream->timing, stream->phy_pix_clk); break; case SIGNAL_TYPE_DISPLAY_PORT: case SIGNAL_TYPE_DISPLAY_PORT_MST: is_valid = dce110_link_encoder_validate_dp_output( - enc110, &stream->public.timing); + enc110, &stream->timing); break; case SIGNAL_TYPE_EDP: is_valid = - (stream->public.timing. + (stream->timing. pixel_encoding == PIXEL_ENCODING_RGB) ? true : false; break; case SIGNAL_TYPE_VIRTUAL: diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h index ded6c61304e6..a47b075f4869 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h @@ -199,7 +199,7 @@ bool dce110_link_encoder_validate_wireless_output( bool dce110_link_encoder_validate_output_with_stream( struct link_encoder *enc, - const struct core_stream *stream); + const struct dc_stream *stream); /****************** HW programming ************************/ diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 3d25a90e49b4..cf98f2471023 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -660,7 +660,7 @@ static enum dc_status build_mapped_resource( uint8_t i, j; for (i = 0; i < context->stream_count; i++) { - struct core_stream *stream = context->streams[i]; + struct dc_stream *stream = context->streams[i]; if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; @@ -734,8 +734,8 @@ enum dc_status dce100_validate_with_context( return DC_FAIL_SURFACE_VALIDATE; for (i = 0; i < set_count; i++) { - context->streams[i] = DC_STREAM_TO_CORE(set[i].stream); - dc_stream_retain(&context->streams[i]->public); + context->streams[i] = set[i].stream; + dc_stream_retain(context->streams[i]); context->stream_count++; } @@ -765,13 +765,13 @@ enum dc_status dce100_validate_with_context( enum dc_status dce100_validate_guaranteed( const struct core_dc *dc, - const struct dc_stream *dc_stream, + struct dc_stream *dc_stream, struct validate_context *context) { enum dc_status result = DC_ERROR_UNEXPECTED; - context->streams[0] = DC_STREAM_TO_CORE(dc_stream); - dc_stream_retain(&context->streams[0]->public); + context->streams[0] = dc_stream; + dc_stream_retain(context->streams[0]); context->stream_count++; result = resource_map_pool_resources(dc, context, NULL); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 119365960cd0..15f6eeef343d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -623,21 +623,21 @@ static bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func static bool dce110_set_output_transfer_func( struct pipe_ctx *pipe_ctx, - const struct core_stream *stream) + const struct dc_stream *stream) { struct output_pixel_processor *opp = pipe_ctx->opp; opp->funcs->opp_power_on_regamma_lut(opp, true); opp->regamma_params.hw_points_num = GAMMA_HW_POINTS_NUM; - if (stream->public.out_transfer_func && - stream->public.out_transfer_func->type == + if (stream->out_transfer_func && + stream->out_transfer_func->type == TF_TYPE_PREDEFINED && - stream->public.out_transfer_func->tf == + stream->out_transfer_func->tf == TRANSFER_FUNCTION_SRGB) { opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_SRGB); } else if (dce110_translate_regamma_to_hw_format( - stream->public.out_transfer_func, &opp->regamma_params)) { + stream->out_transfer_func, &opp->regamma_params)) { opp->funcs->opp_program_regamma_pwl(opp, &opp->regamma_params); opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_USER); } else { @@ -702,7 +702,7 @@ void dce110_enable_stream(struct pipe_ctx *pipe_ctx) enum dc_lane_count lane_count = pipe_ctx->stream->sink->link->cur_link_settings.lane_count; - struct dc_crtc_timing *timing = &pipe_ctx->stream->public.timing; + struct dc_crtc_timing *timing = &pipe_ctx->stream->timing; struct dc_link *link = pipe_ctx->stream->sink->link; /* 1. update AVI info frame (HDMI, DP) @@ -745,7 +745,7 @@ void dce110_enable_stream(struct pipe_ctx *pipe_ctx) void dce110_disable_stream(struct pipe_ctx *pipe_ctx) { - struct core_stream *stream = pipe_ctx->stream; + struct dc_stream *stream = pipe_ctx->stream; struct dc_link *link = stream->sink->link; if (pipe_ctx->audio) { @@ -797,7 +797,7 @@ void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, /* only 3 items below are used by unblank */ params.pixel_clk_khz = - pipe_ctx->stream->public.timing.pix_clk_khz; + pipe_ctx->stream->timing.pix_clk_khz; params.link_settings.link_rate = link_settings->link_rate; pipe_ctx->stream_enc->funcs->dp_unblank(pipe_ctx->stream_enc, ¶ms); } @@ -833,7 +833,7 @@ static void build_audio_output( const struct pipe_ctx *pipe_ctx, struct audio_output *audio_output) { - const struct core_stream *stream = pipe_ctx->stream; + const struct dc_stream *stream = pipe_ctx->stream; audio_output->engine_id = pipe_ctx->stream_enc->id; audio_output->signal = pipe_ctx->stream->signal; @@ -841,33 +841,33 @@ static void build_audio_output( /* audio_crtc_info */ audio_output->crtc_info.h_total = - stream->public.timing.h_total; + stream->timing.h_total; /* * Audio packets are sent during actual CRTC blank physical signal, we * need to specify actual active signal portion */ audio_output->crtc_info.h_active = - stream->public.timing.h_addressable - + stream->public.timing.h_border_left - + stream->public.timing.h_border_right; + stream->timing.h_addressable + + stream->timing.h_border_left + + stream->timing.h_border_right; audio_output->crtc_info.v_active = - stream->public.timing.v_addressable - + stream->public.timing.v_border_top - + stream->public.timing.v_border_bottom; + stream->timing.v_addressable + + stream->timing.v_border_top + + stream->timing.v_border_bottom; audio_output->crtc_info.pixel_repetition = 1; audio_output->crtc_info.interlaced = - stream->public.timing.flags.INTERLACE; + stream->timing.flags.INTERLACE; audio_output->crtc_info.refresh_rate = - (stream->public.timing.pix_clk_khz*1000)/ - (stream->public.timing.h_total*stream->public.timing.v_total); + (stream->timing.pix_clk_khz*1000)/ + (stream->timing.h_total*stream->timing.v_total); audio_output->crtc_info.color_depth = - stream->public.timing.display_color_depth; + stream->timing.display_color_depth; audio_output->crtc_info.requested_pixel_clock = pipe_ctx->pix_clk_params.requested_pix_clk; @@ -878,7 +878,7 @@ static void build_audio_output( /*for HDMI, audio ACR is with deep color ratio factor*/ if (dc_is_hdmi_signal(pipe_ctx->stream->signal) && audio_output->crtc_info.requested_pixel_clock == - stream->public.timing.pix_clk_khz) { + stream->timing.pix_clk_khz) { if (pipe_ctx->pix_clk_params.pixel_encoding == PIXEL_ENCODING_YCBCR420) { audio_output->crtc_info.requested_pixel_clock = audio_output->crtc_info.requested_pixel_clock/2; @@ -959,7 +959,7 @@ static void program_scaler(const struct core_dc *dc, get_surface_visual_confirm_color(pipe_ctx, &color); else color_space_to_black_color(dc, - pipe_ctx->stream->public.output_color_space, + pipe_ctx->stream->output_color_space, &color); pipe_ctx->xfm->funcs->transform_set_pixel_storage_depth( @@ -981,7 +981,7 @@ static enum dc_status dce110_prog_pixclk_crtc_otg( struct validate_context *context, struct core_dc *dc) { - struct core_stream *stream = pipe_ctx->stream; + struct dc_stream *stream = pipe_ctx->stream; struct pipe_ctx *pipe_ctx_old = &dc->current_context->res_ctx. pipe_ctx[pipe_ctx->pipe_idx]; struct tg_color black_color = {0}; @@ -990,7 +990,7 @@ static enum dc_status dce110_prog_pixclk_crtc_otg( /* program blank color */ color_space_to_black_color(dc, - stream->public.output_color_space, &black_color); + stream->output_color_space, &black_color); pipe_ctx->tg->funcs->set_blank_color( pipe_ctx->tg, &black_color); @@ -1011,7 +1011,7 @@ static enum dc_status dce110_prog_pixclk_crtc_otg( pipe_ctx->tg->funcs->program_timing( pipe_ctx->tg, - &stream->public.timing, + &stream->timing, true); pipe_ctx->tg->funcs->set_static_screen_control( @@ -1037,7 +1037,7 @@ static enum dc_status apply_single_controller_ctx_to_hw( struct validate_context *context, struct core_dc *dc) { - struct core_stream *stream = pipe_ctx->stream; + struct dc_stream *stream = pipe_ctx->stream; struct pipe_ctx *pipe_ctx_old = &dc->current_context->res_ctx. pipe_ctx[pipe_ctx->pipe_idx]; @@ -1047,7 +1047,7 @@ static enum dc_status apply_single_controller_ctx_to_hw( pipe_ctx->opp->funcs->opp_set_dyn_expansion( pipe_ctx->opp, COLOR_SPACE_YCBCR601, - stream->public.timing.display_color_depth, + stream->timing.display_color_depth, pipe_ctx->stream->signal); /* FPGA does not program backend */ @@ -1074,7 +1074,7 @@ static enum dc_status apply_single_controller_ctx_to_hw( pipe_ctx->stream_enc->funcs->setup_stereo_sync( pipe_ctx->stream_enc, pipe_ctx->tg->inst, - stream->public.timing.timing_3d_format != TIMING_3D_FORMAT_NONE); + stream->timing.timing_3d_format != TIMING_3D_FORMAT_NONE); /*vbios crtc_source_selection and encoder_setup will override fmt_C*/ @@ -1086,20 +1086,20 @@ static enum dc_status apply_single_controller_ctx_to_hw( if (dc_is_dp_signal(pipe_ctx->stream->signal)) pipe_ctx->stream_enc->funcs->dp_set_stream_attribute( pipe_ctx->stream_enc, - &stream->public.timing, - stream->public.output_color_space); + &stream->timing, + stream->output_color_space); if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) pipe_ctx->stream_enc->funcs->hdmi_set_stream_attribute( pipe_ctx->stream_enc, - &stream->public.timing, + &stream->timing, stream->phy_pix_clk, pipe_ctx->audio != NULL); if (dc_is_dvi_signal(pipe_ctx->stream->signal)) pipe_ctx->stream_enc->funcs->dvi_set_stream_attribute( pipe_ctx->stream_enc, - &stream->public.timing, + &stream->timing, (pipe_ctx->stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK) ? true : false); @@ -1129,9 +1129,9 @@ static enum dc_status apply_single_controller_ctx_to_hw( #endif pipe_ctx->mi->funcs->allocate_mem_input( pipe_ctx->mi, - stream->public.timing.h_total, - stream->public.timing.v_total, - stream->public.timing.pix_clk_khz, + stream->timing.h_total, + stream->timing.v_total, + stream->timing.pix_clk_khz, context->stream_count); pipe_ctx->stream->sink->link->psr_enabled = false; @@ -1228,7 +1228,7 @@ void dce110_enable_accelerated_mode(struct core_dc *dc) static uint32_t compute_pstate_blackout_duration( struct bw_fixed blackout_duration, - const struct core_stream *stream) + const struct dc_stream *stream) { uint32_t total_dest_line_time_ns; uint32_t pstate_blackout_duration_ns; @@ -1236,8 +1236,8 @@ static uint32_t compute_pstate_blackout_duration( pstate_blackout_duration_ns = 1000 * blackout_duration.value >> 24; total_dest_line_time_ns = 1000000UL * - stream->public.timing.h_total / - stream->public.timing.pix_clk_khz + + stream->timing.h_total / + stream->timing.pix_clk_khz + pstate_blackout_duration_ns; return total_dest_line_time_ns; @@ -1805,19 +1805,19 @@ enum dc_status dce110_apply_ctx_to_hw( pipe_ctx->stream_enc->funcs->dp_audio_setup( pipe_ctx->stream_enc, pipe_ctx->audio->inst, - &pipe_ctx->stream->public.audio_info); + &pipe_ctx->stream->audio_info); else pipe_ctx->stream_enc->funcs->hdmi_audio_setup( pipe_ctx->stream_enc, pipe_ctx->audio->inst, - &pipe_ctx->stream->public.audio_info, + &pipe_ctx->stream->audio_info, &audio_output.crtc_info); pipe_ctx->audio->funcs->az_configure( pipe_ctx->audio, pipe_ctx->stream->signal, &audio_output.crtc_info, - &pipe_ctx->stream->public.audio_info); + &pipe_ctx->stream->audio_info); } status = apply_single_controller_ctx_to_hw( @@ -1862,13 +1862,13 @@ static void set_default_colors(struct pipe_ctx *pipe_ctx) default_adjust.out_color_space = COLOR_SPACE_SRGB; else default_adjust.out_color_space = - pipe_ctx->stream->public.output_color_space; + pipe_ctx->stream->output_color_space; default_adjust.csc_adjust_type = GRAPHICS_CSC_ADJUST_TYPE_SW; default_adjust.surface_pixel_format = pipe_ctx->scl_data.format; /* display color depth */ default_adjust.color_depth = - pipe_ctx->stream->public.timing.display_color_depth; + pipe_ctx->stream->timing.display_color_depth; /* Lb color depth */ default_adjust.lb_color_depth = pipe_ctx->scl_data.lb_params.depth; @@ -1932,35 +1932,35 @@ static void program_gamut_remap(struct pipe_ctx *pipe_ctx) adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS; - if (pipe_ctx->stream->public.gamut_remap_matrix.enable_remap == true) { + if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) { adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW; adjust.temperature_matrix[0] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[0]; + gamut_remap_matrix.matrix[0]; adjust.temperature_matrix[1] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[1]; + gamut_remap_matrix.matrix[1]; adjust.temperature_matrix[2] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[2]; + gamut_remap_matrix.matrix[2]; adjust.temperature_matrix[3] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[4]; + gamut_remap_matrix.matrix[4]; adjust.temperature_matrix[4] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[5]; + gamut_remap_matrix.matrix[5]; adjust.temperature_matrix[5] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[6]; + gamut_remap_matrix.matrix[6]; adjust.temperature_matrix[6] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[8]; + gamut_remap_matrix.matrix[8]; adjust.temperature_matrix[7] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[9]; + gamut_remap_matrix.matrix[9]; adjust.temperature_matrix[8] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[10]; + gamut_remap_matrix.matrix[10]; } pipe_ctx->xfm->funcs->transform_set_gamut_remap(pipe_ctx->xfm, &adjust); @@ -1987,48 +1987,48 @@ static void set_plane_config( dce_enable_fe_clock(dc->hwseq, pipe_ctx->pipe_idx, true); set_default_colors(pipe_ctx); - if (pipe_ctx->stream->public.csc_color_matrix.enable_adjustment + if (pipe_ctx->stream->csc_color_matrix.enable_adjustment == true) { tbl_entry.color_space = - pipe_ctx->stream->public.output_color_space; + pipe_ctx->stream->output_color_space; for (i = 0; i < 12; i++) tbl_entry.regval[i] = - pipe_ctx->stream->public.csc_color_matrix.matrix[i]; + pipe_ctx->stream->csc_color_matrix.matrix[i]; pipe_ctx->opp->funcs->opp_set_csc_adjustment (pipe_ctx->opp, &tbl_entry); } - if (pipe_ctx->stream->public.gamut_remap_matrix.enable_remap == true) { + if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) { adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW; adjust.temperature_matrix[0] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[0]; + gamut_remap_matrix.matrix[0]; adjust.temperature_matrix[1] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[1]; + gamut_remap_matrix.matrix[1]; adjust.temperature_matrix[2] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[2]; + gamut_remap_matrix.matrix[2]; adjust.temperature_matrix[3] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[4]; + gamut_remap_matrix.matrix[4]; adjust.temperature_matrix[4] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[5]; + gamut_remap_matrix.matrix[5]; adjust.temperature_matrix[5] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[6]; + gamut_remap_matrix.matrix[6]; adjust.temperature_matrix[6] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[8]; + gamut_remap_matrix.matrix[8]; adjust.temperature_matrix[7] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[9]; + gamut_remap_matrix.matrix[9]; adjust.temperature_matrix[8] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[10]; + gamut_remap_matrix.matrix[10]; } pipe_ctx->xfm->funcs->transform_set_gamut_remap(pipe_ctx->xfm, &adjust); @@ -2260,7 +2260,7 @@ void dce110_fill_display_configs( for (j = 0; j < context->stream_count; j++) { int k; - const struct core_stream *stream = context->streams[j]; + const struct dc_stream *stream = context->streams[j]; struct dm_pp_single_disp_config *cfg = &pp_display_cfg->disp_configs[num_cfgs]; const struct pipe_ctx *pipe_ctx = NULL; @@ -2276,8 +2276,8 @@ void dce110_fill_display_configs( num_cfgs++; cfg->signal = pipe_ctx->stream->signal; cfg->pipe_idx = pipe_ctx->pipe_idx; - cfg->src_height = stream->public.src.height; - cfg->src_width = stream->public.src.width; + cfg->src_height = stream->src.height; + cfg->src_width = stream->src.width; cfg->ddi_channel_mapping = stream->sink->link->ddi_channel_mapping.raw; cfg->transmitter = @@ -2290,10 +2290,10 @@ void dce110_fill_display_configs( stream->sink->link->cur_link_settings.link_spread; cfg->sym_clock = stream->phy_pix_clk; /* Round v_refresh*/ - cfg->v_refresh = stream->public.timing.pix_clk_khz * 1000; - cfg->v_refresh /= stream->public.timing.h_total; - cfg->v_refresh = (cfg->v_refresh + stream->public.timing.v_total / 2) - / stream->public.timing.v_total; + cfg->v_refresh = stream->timing.pix_clk_khz * 1000; + cfg->v_refresh /= stream->timing.h_total; + cfg->v_refresh = (cfg->v_refresh + stream->timing.v_total / 2) + / stream->timing.v_total; } pp_display_cfg->display_count = num_cfgs; @@ -2305,7 +2305,7 @@ uint32_t dce110_get_min_vblank_time_us(const struct validate_context *context) uint32_t min_vertical_blank_time = -1; for (j = 0; j < context->stream_count; j++) { - const struct dc_stream *stream = &context->streams[j]->public; + struct dc_stream *stream = context->streams[j]; uint32_t vertical_blank_in_pixels = 0; uint32_t vertical_blank_time = 0; @@ -2388,7 +2388,7 @@ static void pplib_apply_display_requirements( /* TODO: is this still applicable?*/ if (pp_display_cfg->display_count == 1) { const struct dc_crtc_timing *timing = - &context->streams[0]->public.timing; + &context->streams[0]->timing; pp_display_cfg->crtc_index = pp_display_cfg->disp_configs[0].pipe_idx; @@ -2441,48 +2441,48 @@ static void dce110_program_front_end_for_pipe( dce_enable_fe_clock(dc->hwseq, pipe_ctx->pipe_idx, true); set_default_colors(pipe_ctx); - if (pipe_ctx->stream->public.csc_color_matrix.enable_adjustment + if (pipe_ctx->stream->csc_color_matrix.enable_adjustment == true) { tbl_entry.color_space = - pipe_ctx->stream->public.output_color_space; + pipe_ctx->stream->output_color_space; for (i = 0; i < 12; i++) tbl_entry.regval[i] = - pipe_ctx->stream->public.csc_color_matrix.matrix[i]; + pipe_ctx->stream->csc_color_matrix.matrix[i]; pipe_ctx->opp->funcs->opp_set_csc_adjustment (pipe_ctx->opp, &tbl_entry); } - if (pipe_ctx->stream->public.gamut_remap_matrix.enable_remap == true) { + if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) { adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW; adjust.temperature_matrix[0] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[0]; + gamut_remap_matrix.matrix[0]; adjust.temperature_matrix[1] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[1]; + gamut_remap_matrix.matrix[1]; adjust.temperature_matrix[2] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[2]; + gamut_remap_matrix.matrix[2]; adjust.temperature_matrix[3] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[4]; + gamut_remap_matrix.matrix[4]; adjust.temperature_matrix[4] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[5]; + gamut_remap_matrix.matrix[5]; adjust.temperature_matrix[5] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[6]; + gamut_remap_matrix.matrix[6]; adjust.temperature_matrix[6] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[8]; + gamut_remap_matrix.matrix[8]; adjust.temperature_matrix[7] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[9]; + gamut_remap_matrix.matrix[9]; adjust.temperature_matrix[8] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[10]; + gamut_remap_matrix.matrix[10]; } pipe_ctx->xfm->funcs->transform_set_gamut_remap(pipe_ctx->xfm, &adjust); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index c773351e93af..cc25c4b6c06f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -718,13 +718,13 @@ static void get_pixel_clock_parameters( const struct pipe_ctx *pipe_ctx, struct pixel_clk_params *pixel_clk_params) { - const struct core_stream *stream = pipe_ctx->stream; + const struct dc_stream *stream = pipe_ctx->stream; /*TODO: is this halved for YCbCr 420? in that case we might want to move * the pixel clock normalization for hdmi up to here instead of doing it * in pll_adjust_pix_clk */ - pixel_clk_params->requested_pix_clk = stream->public.timing.pix_clk_khz; + pixel_clk_params->requested_pix_clk = stream->timing.pix_clk_khz; pixel_clk_params->encoder_object_id = stream->sink->link->link_enc->id; pixel_clk_params->signal_type = pipe_ctx->stream->signal; pixel_clk_params->controller_id = pipe_ctx->pipe_idx + 1; @@ -733,15 +733,15 @@ static void get_pixel_clock_parameters( LINK_RATE_REF_FREQ_IN_KHZ; pixel_clk_params->flags.ENABLE_SS = 0; pixel_clk_params->color_depth = - stream->public.timing.display_color_depth; + stream->timing.display_color_depth; pixel_clk_params->flags.DISPLAY_BLANKED = 1; - pixel_clk_params->flags.SUPPORT_YCBCR420 = (stream->public.timing.pixel_encoding == + pixel_clk_params->flags.SUPPORT_YCBCR420 = (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420); - pixel_clk_params->pixel_encoding = stream->public.timing.pixel_encoding; - if (stream->public.timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) { + pixel_clk_params->pixel_encoding = stream->timing.pixel_encoding; + if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) { pixel_clk_params->color_depth = COLOR_DEPTH_888; } - if (stream->public.timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) { + if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) { pixel_clk_params->requested_pix_clk = pixel_clk_params->requested_pix_clk / 2; } } @@ -755,7 +755,7 @@ enum dc_status dce110_resource_build_pipe_hw_param(struct pipe_ctx *pipe_ctx) &pipe_ctx->pll_settings); resource_build_bit_depth_reduction_params(pipe_ctx->stream, &pipe_ctx->stream->bit_depth_params); - pipe_ctx->stream->clamping.pixel_encoding = pipe_ctx->stream->public.timing.pixel_encoding; + pipe_ctx->stream->clamping.pixel_encoding = pipe_ctx->stream->timing.pixel_encoding; return DC_OK; } @@ -780,7 +780,7 @@ static enum dc_status build_mapped_resource( uint8_t i, j; for (i = 0; i < context->stream_count; i++) { - struct core_stream *stream = context->streams[i]; + struct dc_stream *stream = context->streams[i]; if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; @@ -837,9 +837,9 @@ bool dce110_validate_bandwidth( dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_VALIDATION, "%s: %dx%d@%d Bandwidth validation failed!\n", __func__, - context->streams[0]->public.timing.h_addressable, - context->streams[0]->public.timing.v_addressable, - context->streams[0]->public.timing.pix_clk_khz); + context->streams[0]->timing.h_addressable, + context->streams[0]->timing.v_addressable, + context->streams[0]->timing.pix_clk_khz); if (memcmp(&dc->current_context->bw.dce, &context->bw.dce, sizeof(context->bw.dce))) { @@ -942,8 +942,8 @@ enum dc_status dce110_validate_with_context( return DC_FAIL_SURFACE_VALIDATE; for (i = 0; i < set_count; i++) { - context->streams[i] = DC_STREAM_TO_CORE(set[i].stream); - dc_stream_retain(&context->streams[i]->public); + context->streams[i] = set[i].stream; + dc_stream_retain(context->streams[i]); context->stream_count++; } @@ -973,13 +973,13 @@ enum dc_status dce110_validate_with_context( enum dc_status dce110_validate_guaranteed( const struct core_dc *dc, - const struct dc_stream *dc_stream, + struct dc_stream *dc_stream, struct validate_context *context) { enum dc_status result = DC_ERROR_UNEXPECTED; - context->streams[0] = DC_STREAM_TO_CORE(dc_stream); - dc_stream_retain(&context->streams[0]->public); + context->streams[0] = dc_stream; + dc_stream_retain(context->streams[0]); context->stream_count++; result = resource_map_pool_resources(dc, context, NULL); @@ -1006,7 +1006,7 @@ enum dc_status dce110_validate_guaranteed( static struct pipe_ctx *dce110_acquire_underlay( struct validate_context *context, const struct resource_pool *pool, - struct core_stream *stream) + struct dc_stream *stream) { struct core_dc *dc = DC_TO_CORE(stream->ctx->dc); struct resource_context *res_ctx = &context->res_ctx; @@ -1041,18 +1041,18 @@ static struct pipe_ctx *dce110_acquire_underlay( */ pipe_ctx->tg->funcs->program_timing(pipe_ctx->tg, - &stream->public.timing, + &stream->timing, false); pipe_ctx->tg->funcs->enable_advanced_request( pipe_ctx->tg, true, - &stream->public.timing); + &stream->timing); pipe_ctx->mi->funcs->allocate_mem_input(pipe_ctx->mi, - stream->public.timing.h_total, - stream->public.timing.v_total, - stream->public.timing.pix_clk_khz, + stream->timing.h_total, + stream->timing.v_total, + stream->timing.pix_clk_khz, context->stream_count); color_space_to_black_color(dc, diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 19cd99923b24..9589208ea0c8 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -698,7 +698,7 @@ static void destruct(struct dce110_resource_pool *pool) static struct clock_source *find_matching_pll( struct resource_context *res_ctx, const struct resource_pool *pool, - const struct core_stream *const stream) + const struct dc_stream *const stream) { switch (stream->sink->link->link_enc->transmitter) { case TRANSMITTER_UNIPHY_A: @@ -729,7 +729,7 @@ static enum dc_status build_mapped_resource( uint8_t i, j; for (i = 0; i < context->stream_count; i++) { - struct core_stream *stream = context->streams[i]; + struct dc_stream *stream = context->streams[i]; if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; @@ -843,7 +843,7 @@ enum dc_status resource_map_phy_clock_resources( /* acquire new resources */ for (i = 0; i < context->stream_count; i++) { - struct core_stream *stream = context->streams[i]; + struct dc_stream *stream = context->streams[i]; if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; @@ -916,8 +916,8 @@ enum dc_status dce112_validate_with_context( return DC_FAIL_SURFACE_VALIDATE; for (i = 0; i < set_count; i++) { - context->streams[i] = DC_STREAM_TO_CORE(set[i].stream); - dc_stream_retain(&context->streams[i]->public); + context->streams[i] = set[i].stream; + dc_stream_retain(context->streams[i]); context->stream_count++; } @@ -947,13 +947,13 @@ enum dc_status dce112_validate_with_context( enum dc_status dce112_validate_guaranteed( const struct core_dc *dc, - const struct dc_stream *dc_stream, + struct dc_stream *stream, struct validate_context *context) { enum dc_status result = DC_ERROR_UNEXPECTED; - context->streams[0] = DC_STREAM_TO_CORE(dc_stream); - dc_stream_retain(&context->streams[0]->public); + context->streams[0] = stream; + dc_stream_retain(context->streams[0]); context->stream_count++; result = resource_map_pool_resources(dc, context, NULL); diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h index c6c0bbac5335..cb2c69fb05a6 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h @@ -44,7 +44,7 @@ enum dc_status dce112_validate_with_context( enum dc_status dce112_validate_guaranteed( const struct core_dc *dc, - const struct dc_stream *dc_stream, + struct dc_stream *dc_stream, struct validate_context *context); bool dce112_validate_bandwidth( diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 0123006e5360..2fde43c91ad0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -676,7 +676,7 @@ static enum dc_status build_mapped_resource( uint8_t i, j; for (i = 0; i < context->stream_count; i++) { - struct core_stream *stream = context->streams[i]; + struct dc_stream *stream = context->streams[i]; if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; @@ -750,8 +750,8 @@ enum dc_status dce80_validate_with_context( return DC_FAIL_SURFACE_VALIDATE; for (i = 0; i < set_count; i++) { - context->streams[i] = DC_STREAM_TO_CORE(set[i].stream); - dc_stream_retain(&context->streams[i]->public); + context->streams[i] = set[i].stream; + dc_stream_retain(context->streams[i]); context->stream_count++; } @@ -780,13 +780,13 @@ enum dc_status dce80_validate_with_context( enum dc_status dce80_validate_guaranteed( const struct core_dc *dc, - const struct dc_stream *dc_stream, + struct dc_stream *dc_stream, struct validate_context *context) { enum dc_status result = DC_ERROR_UNEXPECTED; - context->streams[0] = DC_STREAM_TO_CORE(dc_stream); - dc_stream_retain(&context->streams[0]->public); + context->streams[0] = dc_stream; + dc_stream_retain(context->streams[0]); context->stream_count++; result = resource_map_pool_resources(dc, context, NULL); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index e738387d8ba3..1531b52e61c2 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -684,12 +684,12 @@ static enum dc_status dcn10_prog_pixclk_crtc_otg( struct validate_context *context, struct core_dc *dc) { - struct core_stream *stream = pipe_ctx->stream; + struct dc_stream *stream = pipe_ctx->stream; enum dc_color_space color_space; struct tg_color black_color = {0}; - bool enableStereo = stream->public.timing.timing_3d_format == TIMING_3D_FORMAT_NONE ? + bool enableStereo = stream->timing.timing_3d_format == TIMING_3D_FORMAT_NONE ? false:true; - bool rightEyePolarity = stream->public.timing.flags.RIGHT_EYE_3D_POLARITY; + bool rightEyePolarity = stream->timing.flags.RIGHT_EYE_3D_POLARITY; /* by upper caller loop, pipe0 is parent pipe and be called first. @@ -722,7 +722,7 @@ static enum dc_status dcn10_prog_pixclk_crtc_otg( pipe_ctx->tg->funcs->program_timing( pipe_ctx->tg, - &stream->public.timing, + &stream->timing, true); pipe_ctx->opp->funcs->opp_set_stereo_polarity( @@ -742,7 +742,7 @@ static enum dc_status dcn10_prog_pixclk_crtc_otg( &stream->clamping); #endif /* program otg blank color */ - color_space = stream->public.output_color_space; + color_space = stream->output_color_space; color_space_to_black_color(dc, color_space, &black_color); pipe_ctx->tg->funcs->set_blank_color( pipe_ctx->tg, @@ -1053,16 +1053,16 @@ static bool patch_address_for_sbs_tb_stereo( bool sec_split = pipe_ctx->top_pipe && pipe_ctx->top_pipe->surface == pipe_ctx->surface; if (sec_split && surface->address.type == PLN_ADDR_TYPE_GRPH_STEREO && - (pipe_ctx->stream->public.timing.timing_3d_format == + (pipe_ctx->stream->timing.timing_3d_format == TIMING_3D_FORMAT_SIDE_BY_SIDE || - pipe_ctx->stream->public.timing.timing_3d_format == + pipe_ctx->stream->timing.timing_3d_format == TIMING_3D_FORMAT_TOP_AND_BOTTOM)) { *addr = surface->address.grph_stereo.left_addr; surface->address.grph_stereo.left_addr = surface->address.grph_stereo.right_addr; return true; } else { - if (pipe_ctx->stream->public.view_format != VIEW_3D_FORMAT_NONE && + if (pipe_ctx->stream->view_format != VIEW_3D_FORMAT_NONE && surface->address.type != PLN_ADDR_TYPE_GRPH_STEREO) { surface->address.type = PLN_ADDR_TYPE_GRPH_STEREO; surface->address.grph_stereo.right_addr = @@ -1456,7 +1456,7 @@ static bool dcn10_translate_regamma_to_hw_format(const struct dc_transfer_func static bool dcn10_set_output_transfer_func( struct pipe_ctx *pipe_ctx, - const struct core_stream *stream) + const struct dc_stream *stream) { struct transform *xfm = pipe_ctx->xfm; @@ -1465,14 +1465,14 @@ static bool dcn10_set_output_transfer_func( xfm->regamma_params.hw_points_num = GAMMA_HW_POINTS_NUM; - if (stream->public.out_transfer_func && - stream->public.out_transfer_func->type == + if (stream->out_transfer_func && + stream->out_transfer_func->type == TF_TYPE_PREDEFINED && - stream->public.out_transfer_func->tf == + stream->out_transfer_func->tf == TRANSFER_FUNCTION_SRGB) { xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_SRGB); } else if (dcn10_translate_regamma_to_hw_format( - stream->public.out_transfer_func, &xfm->regamma_params)) { + stream->out_transfer_func, &xfm->regamma_params)) { xfm->funcs->opp_program_regamma_pwl(xfm, &xfm->regamma_params); xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_USER); } else { @@ -1756,35 +1756,35 @@ static void program_gamut_remap(struct pipe_ctx *pipe_ctx) adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS; - if (pipe_ctx->stream->public.gamut_remap_matrix.enable_remap == true) { + if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) { adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW; adjust.temperature_matrix[0] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[0]; + gamut_remap_matrix.matrix[0]; adjust.temperature_matrix[1] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[1]; + gamut_remap_matrix.matrix[1]; adjust.temperature_matrix[2] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[2]; + gamut_remap_matrix.matrix[2]; adjust.temperature_matrix[3] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[4]; + gamut_remap_matrix.matrix[4]; adjust.temperature_matrix[4] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[5]; + gamut_remap_matrix.matrix[5]; adjust.temperature_matrix[5] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[6]; + gamut_remap_matrix.matrix[6]; adjust.temperature_matrix[6] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[8]; + gamut_remap_matrix.matrix[8]; adjust.temperature_matrix[7] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[9]; + gamut_remap_matrix.matrix[9]; adjust.temperature_matrix[8] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[10]; + gamut_remap_matrix.matrix[10]; } pipe_ctx->xfm->funcs->transform_set_gamut_remap(pipe_ctx->xfm, &adjust); @@ -1798,14 +1798,14 @@ static void program_csc_matrix(struct pipe_ctx *pipe_ctx, int i; struct out_csc_color_matrix tbl_entry; - if (pipe_ctx->stream->public.csc_color_matrix.enable_adjustment + if (pipe_ctx->stream->csc_color_matrix.enable_adjustment == true) { enum dc_color_space color_space = - pipe_ctx->stream->public.output_color_space; + pipe_ctx->stream->output_color_space; //uint16_t matrix[12]; for (i = 0; i < 12; i++) - tbl_entry.regval[i] = pipe_ctx->stream->public.csc_color_matrix.matrix[i]; + tbl_entry.regval[i] = pipe_ctx->stream->csc_color_matrix.matrix[i]; tbl_entry.color_space = color_space; //tbl_entry.regval = matrix; @@ -1967,7 +1967,7 @@ static void update_dchubp_dpp( * pre-multiplied alpha. */ mpcc_cfg.pre_multiplied_alpha = is_rgb_cspace( - pipe_ctx->stream->public.output_color_space) + pipe_ctx->stream->output_color_space) && per_pixel_alpha; pipe_ctx->mpcc->funcs->set(pipe_ctx->mpcc, &mpcc_cfg); @@ -1975,7 +1975,7 @@ static void update_dchubp_dpp( dcn10_get_surface_visual_confirm_color(pipe_ctx, &black_color); } else { color_space_to_black_color( - dc, pipe_ctx->stream->public.output_color_space, + dc, pipe_ctx->stream->output_color_space, &black_color); } pipe_ctx->mpcc->funcs->set_bg_color(pipe_ctx->mpcc, &black_color); @@ -1991,7 +1991,7 @@ static void update_dchubp_dpp( program_gamut_remap(pipe_ctx); /*TODO add adjustments parameters*/ - ocsc.out_color_space = pipe_ctx->stream->public.output_color_space; + ocsc.out_color_space = pipe_ctx->stream->output_color_space; pipe_ctx->xfm->funcs->opp_set_csc_default(pipe_ctx->xfm, &ocsc); mi->funcs->mem_input_program_surface_config( @@ -2346,11 +2346,11 @@ static void set_plane_config( } static void dcn10_config_stereo_parameters( - struct core_stream *stream, struct crtc_stereo_flags *flags) + struct dc_stream *stream, struct crtc_stereo_flags *flags) { - enum view_3d_format view_format = stream->public.view_format; + enum view_3d_format view_format = stream->view_format; enum dc_timing_3d_format timing_3d_format =\ - stream->public.timing.timing_3d_format; + stream->timing.timing_3d_format; bool non_stereo_timing = false; if (timing_3d_format == TIMING_3D_FORMAT_NONE || @@ -2374,7 +2374,7 @@ static void dcn10_config_stereo_parameters( flags->DISABLE_STEREO_DP_SYNC = 1; } flags->RIGHT_EYE_POLARITY =\ - stream->public.timing.flags.RIGHT_EYE_3D_POLARITY; + stream->timing.flags.RIGHT_EYE_3D_POLARITY; if (timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING) flags->FRAME_PACKED = 1; } @@ -2385,18 +2385,18 @@ static void dcn10_config_stereo_parameters( static void dcn10_setup_stereo(struct pipe_ctx *pipe_ctx, struct core_dc *dc) { struct crtc_stereo_flags flags = { 0 }; - struct core_stream *stream = pipe_ctx->stream; + struct dc_stream *stream = pipe_ctx->stream; dcn10_config_stereo_parameters(stream, &flags); pipe_ctx->opp->funcs->opp_set_stereo_polarity( pipe_ctx->opp, flags.PROGRAM_STEREO == 1 ? true:false, - stream->public.timing.flags.RIGHT_EYE_3D_POLARITY == 1 ? true:false); + stream->timing.flags.RIGHT_EYE_3D_POLARITY == 1 ? true:false); pipe_ctx->tg->funcs->program_stereo( pipe_ctx->tg, - &stream->public.timing, + &stream->timing, &flags); return; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index b901ef9689a6..33beb0bc3ddf 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -787,8 +787,8 @@ static void get_pixel_clock_parameters( const struct pipe_ctx *pipe_ctx, struct pixel_clk_params *pixel_clk_params) { - const struct core_stream *stream = pipe_ctx->stream; - pixel_clk_params->requested_pix_clk = stream->public.timing.pix_clk_khz; + const struct dc_stream *stream = pipe_ctx->stream; + pixel_clk_params->requested_pix_clk = stream->timing.pix_clk_khz; pixel_clk_params->encoder_object_id = stream->sink->link->link_enc->id; pixel_clk_params->signal_type = pipe_ctx->stream->signal; pixel_clk_params->controller_id = pipe_ctx->pipe_idx + 1; @@ -797,23 +797,23 @@ static void get_pixel_clock_parameters( LINK_RATE_REF_FREQ_IN_KHZ; pixel_clk_params->flags.ENABLE_SS = 0; pixel_clk_params->color_depth = - stream->public.timing.display_color_depth; + stream->timing.display_color_depth; pixel_clk_params->flags.DISPLAY_BLANKED = 1; - pixel_clk_params->pixel_encoding = stream->public.timing.pixel_encoding; + pixel_clk_params->pixel_encoding = stream->timing.pixel_encoding; - if (stream->public.timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) + if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) pixel_clk_params->color_depth = COLOR_DEPTH_888; - if (stream->public.timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) + if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) pixel_clk_params->requested_pix_clk /= 2; } -static void build_clamping_params(struct core_stream *stream) +static void build_clamping_params(struct dc_stream *stream) { stream->clamping.clamping_level = CLAMPING_FULL_RANGE; - stream->clamping.c_depth = stream->public.timing.display_color_depth; - stream->clamping.pixel_encoding = stream->public.timing.pixel_encoding; + stream->clamping.c_depth = stream->timing.display_color_depth; + stream->clamping.pixel_encoding = stream->timing.pixel_encoding; } static enum dc_status build_pipe_hw_param(struct pipe_ctx *pipe_ctx) @@ -826,7 +826,7 @@ static enum dc_status build_pipe_hw_param(struct pipe_ctx *pipe_ctx) &pipe_ctx->pix_clk_params, &pipe_ctx->pll_settings); - pipe_ctx->stream->clamping.pixel_encoding = pipe_ctx->stream->public.timing.pixel_encoding; + pipe_ctx->stream->clamping.pixel_encoding = pipe_ctx->stream->timing.pixel_encoding; resource_build_bit_depth_reduction_params(pipe_ctx->stream, &pipe_ctx->stream->bit_depth_params); @@ -844,7 +844,7 @@ static enum dc_status build_mapped_resource( uint8_t i, j; for (i = 0; i < context->stream_count; i++) { - struct core_stream *stream = context->streams[i]; + struct dc_stream *stream = context->streams[i]; if (old_context && resource_is_stream_unchanged(old_context, stream)) { if (stream != NULL && old_context->streams[i] != NULL) { @@ -852,7 +852,7 @@ static enum dc_status build_mapped_resource( resource_build_bit_depth_reduction_params(stream, &stream->bit_depth_params); stream->clamping.pixel_encoding = - stream->public.timing.pixel_encoding; + stream->timing.pixel_encoding; resource_build_bit_depth_reduction_params(stream, &stream->bit_depth_params); @@ -896,8 +896,8 @@ enum dc_status dcn10_validate_with_context( return result; for (i = 0; i < set_count; i++) { - context->streams[i] = DC_STREAM_TO_CORE(set[i].stream); - dc_stream_retain(&context->streams[i]->public); + context->streams[i] = set[i].stream; + dc_stream_retain(context->streams[i]); context->stream_count++; } @@ -929,13 +929,13 @@ enum dc_status dcn10_validate_with_context( enum dc_status dcn10_validate_guaranteed( const struct core_dc *dc, - const struct dc_stream *dc_stream, + struct dc_stream *dc_stream, struct validate_context *context) { enum dc_status result = DC_ERROR_UNEXPECTED; - context->streams[0] = DC_STREAM_TO_CORE(dc_stream); - dc_stream_retain(&context->streams[0]->public); + context->streams[0] = dc_stream; + dc_stream_retain(context->streams[0]); context->stream_count++; result = resource_map_pool_resources(dc, context, NULL); @@ -960,7 +960,7 @@ enum dc_status dcn10_validate_guaranteed( static struct pipe_ctx *dcn10_acquire_idle_pipe_for_layer( struct validate_context *context, const struct resource_pool *pool, - struct core_stream *stream) + struct dc_stream *stream) { struct resource_context *res_ctx = &context->res_ctx; struct pipe_ctx *head_pipe = resource_get_head_pipe_for_stream(res_ctx, stream); diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 5a47d4c94df6..2ae5a607fb5a 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -36,41 +36,18 @@ #include "mpc.h" #endif -struct core_stream; - #define MAX_CLOCK_SOURCES 7 void enable_surface_flip_reporting(struct dc_surface *dc_surface, uint32_t controller_id); -/********* core_stream ************/ #include "grph_object_id.h" #include "link_encoder.h" #include "stream_encoder.h" #include "clock_source.h" #include "audio.h" #include "hw_sequencer_types.h" -#include "opp.h" - -#define DC_STREAM_TO_CORE(dc_stream) container_of( \ - dc_stream, struct core_stream, public) - -struct core_stream { - struct dc_stream public; - - /* field internal to DC */ - struct dc_context *ctx; - struct dc_sink *sink; - /* used by DCP and FMT */ - struct bit_depth_reduction_params bit_depth_params; - struct clamping_and_pixel_encoding_params clamping; - - int phy_pix_clk; - enum signal_type signal; - - struct dc_stream_status status; -}; /************ link *****************/ struct link_init_data { @@ -85,7 +62,7 @@ struct dc_link *link_create(const struct link_init_data *init_params); void link_destroy(struct dc_link **link); enum dc_status dc_link_validate_mode_timing( - const struct core_stream *stream, + const struct dc_stream *stream, struct dc_link *link, const struct dc_crtc_timing *timing); @@ -117,7 +94,7 @@ struct resource_funcs { enum dc_status (*validate_guaranteed)( const struct core_dc *dc, - const struct dc_stream *stream, + struct dc_stream *stream, struct validate_context *context); bool (*validate_bandwidth)( @@ -127,7 +104,7 @@ struct resource_funcs { struct pipe_ctx *(*acquire_idle_pipe_for_layer)( struct validate_context *context, const struct resource_pool *pool, - struct core_stream *stream); + struct dc_stream *stream); }; struct audio_support{ @@ -178,7 +155,7 @@ struct resource_pool { struct pipe_ctx { struct dc_surface *surface; - struct core_stream *stream; + struct dc_stream *stream; struct mem_input *mi; struct input_pixel_processor *ipp; @@ -264,7 +241,7 @@ union bw_context { }; struct validate_context { - struct core_stream *streams[MAX_PIPES]; + struct dc_stream *streams[MAX_PIPES]; struct dc_stream_status stream_status[MAX_PIPES]; uint8_t stream_count; diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h index d9af028a39df..5b4185053e9c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h @@ -30,7 +30,7 @@ #define LINK_TRAINING_RETRY_DELAY 50 /* ms */ struct dc_link; -struct core_stream; +struct dc_stream; struct dc_link_settings; bool dp_hbr_verify_link_cap( @@ -50,7 +50,7 @@ bool dp_validate_mode_timing( const struct dc_crtc_timing *timing); void decide_link_settings( - struct core_stream *stream, + struct dc_stream *stream, struct dc_link_settings *link_setting); bool perform_link_training_with_retries( diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h index 0ee738774f9f..28fb02fb677e 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h @@ -17,7 +17,6 @@ struct encoder_set_dp_phy_pattern_param; struct link_mst_stream_allocation_table; struct dc_link_settings; struct link_training_settings; -struct core_stream; struct pipe_ctx; struct encoder_init_data { @@ -94,7 +93,7 @@ struct link_encoder { struct link_encoder_funcs { bool (*validate_output_with_stream)( - struct link_encoder *enc, const struct core_stream *stream); + struct link_encoder *enc, const struct dc_stream *stream); void (*hw_init)(struct link_encoder *enc); void (*setup)(struct link_encoder *enc, enum signal_type signal); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index a3eec078dead..b2f7ba2115c9 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -92,7 +92,7 @@ struct hw_sequencer_funcs { bool (*set_output_transfer_func)( struct pipe_ctx *pipe_ctx, - const struct core_stream *stream); + const struct dc_stream *stream); void (*power_down)(struct core_dc *dc); diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index ed94df16a2d3..571bfae62a3c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -103,8 +103,8 @@ void resource_reference_clock_source( struct clock_source *clock_source); bool resource_are_streams_timing_synchronizable( - const struct core_stream *stream1, - const struct core_stream *stream2); + struct dc_stream *stream1, + struct dc_stream *stream2); struct clock_source *resource_find_used_clk_src_for_sharing( struct resource_context *res_ctx, @@ -116,12 +116,12 @@ struct clock_source *dc_resource_find_first_free_pll( struct pipe_ctx *resource_get_head_pipe_for_stream( struct resource_context *res_ctx, - const struct core_stream *stream); + struct dc_stream *stream); bool resource_attach_surfaces_to_context( struct dc_surface *const *surfaces, int surface_count, - const struct dc_stream *dc_stream, + struct dc_stream *dc_stream, struct validate_context *context, const struct resource_pool *pool); @@ -130,10 +130,10 @@ struct pipe_ctx *find_idle_secondary_pipe( const struct resource_pool *pool); bool resource_is_stream_unchanged( - const struct validate_context *old_context, const struct core_stream *stream); + struct validate_context *old_context, struct dc_stream *stream); bool is_stream_unchanged( - const struct core_stream *old_stream, const struct core_stream *stream); + struct dc_stream *old_stream, struct dc_stream *stream); bool resource_validate_attach_surfaces( const struct dc_validation_set set[], @@ -164,7 +164,7 @@ bool pipe_need_reprogram( struct pipe_ctx *pipe_ctx_old, struct pipe_ctx *pipe_ctx); -void resource_build_bit_depth_reduction_params(const struct core_stream *stream, +void resource_build_bit_depth_reduction_params(struct dc_stream *stream, struct bit_depth_reduction_params *fmt_bit_depth); #endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c index d312874d95b5..dd024c99fb7e 100644 --- a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c @@ -30,7 +30,7 @@ static bool virtual_link_encoder_validate_output_with_stream( struct link_encoder *enc, - const struct core_stream *stream) { return true; } + const struct dc_stream *stream) { return true; } static void virtual_link_encoder_hw_init(struct link_encoder *enc) {} diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index a989d5de9f3c..358f8a855a59 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -111,7 +111,7 @@ struct freesync_state { }; struct freesync_entity { - const struct dc_stream *stream; + struct dc_stream *stream; struct mod_freesync_caps *caps; struct freesync_state state; struct mod_freesync_user_enable user_enable; @@ -229,7 +229,7 @@ void mod_freesync_destroy(struct mod_freesync *mod_freesync) * on the core_freesync->map and returns the corresponding index */ static unsigned int map_index_from_stream(struct core_freesync *core_freesync, - const struct dc_stream *stream) + struct dc_stream *stream) { unsigned int index = 0; @@ -244,9 +244,8 @@ static unsigned int map_index_from_stream(struct core_freesync *core_freesync, } bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, - const struct dc_stream *stream, struct mod_freesync_caps *caps) + struct dc_stream *stream, struct mod_freesync_caps *caps) { - struct core_stream *core_stream = NULL; struct core_dc *core_dc = NULL; struct core_freesync *core_freesync = NULL; int persistent_freesync_enable = 0; @@ -258,7 +257,6 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, return false; core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync); - core_stream = DC_STREAM_TO_CORE(stream); core_dc = DC_TO_CORE(core_freesync->dc); flag.save_per_edid = true; @@ -315,7 +313,7 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, if (caps->supported && nom_refresh_rate_uhz >= caps->min_refresh_in_micro_hz && nom_refresh_rate_uhz <= caps->max_refresh_in_micro_hz) - core_stream->public.ignore_msa_timing_param = 1; + stream->ignore_msa_timing_param = 1; core_freesync->num_entities++; return true; @@ -324,7 +322,7 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, } bool mod_freesync_remove_stream(struct mod_freesync *mod_freesync, - const struct dc_stream *stream) + struct dc_stream *stream) { int i = 0; struct core_freesync *core_freesync = NULL; @@ -346,14 +344,12 @@ bool mod_freesync_remove_stream(struct mod_freesync *mod_freesync, } static void update_stream_freesync_context(struct core_freesync *core_freesync, - const struct dc_stream *stream) + struct dc_stream *stream) { unsigned int index; struct freesync_context *ctx; - struct core_stream *core_stream; - core_stream = DC_STREAM_TO_CORE(stream); - ctx = &core_stream->public.freesync_ctx; + ctx = &stream->freesync_ctx; index = map_index_from_stream(core_freesync, stream); @@ -372,19 +368,17 @@ static void update_stream_freesync_context(struct core_freesync *core_freesync, } static void update_stream(struct core_freesync *core_freesync, - const struct dc_stream *stream) + struct dc_stream *stream) { - struct core_stream *core_stream = DC_STREAM_TO_CORE(stream); - unsigned int index = map_index_from_stream(core_freesync, stream); if (core_freesync->map[index].caps->supported) { - core_stream->public.ignore_msa_timing_param = 1; + stream->ignore_msa_timing_param = 1; update_stream_freesync_context(core_freesync, stream); } } static void calc_freesync_range(struct core_freesync *core_freesync, - const struct dc_stream *stream, + struct dc_stream *stream, struct freesync_state *state, unsigned int min_refresh_in_uhz, unsigned int max_refresh_in_uhz) @@ -458,7 +452,7 @@ static void calc_freesync_range(struct core_freesync *core_freesync, min_frame_duration_in_ns) / 2000; } -static void calc_v_total_from_duration(const struct dc_stream *stream, +static void calc_v_total_from_duration(struct dc_stream *stream, unsigned int duration_in_ns, int *v_total_nominal) { *v_total_nominal = div64_u64(div64_u64(((unsigned long long)( @@ -467,7 +461,7 @@ static void calc_v_total_from_duration(const struct dc_stream *stream, } static void calc_v_total_for_static_ramp(struct core_freesync *core_freesync, - const struct dc_stream *stream, + struct dc_stream *stream, unsigned int index, int *v_total) { unsigned int frame_duration = 0; @@ -563,7 +557,7 @@ static void reset_freesync_state_variables(struct freesync_state* state) * Sets freesync mode on a stream depending on current freesync state. */ static bool set_freesync_on_streams(struct core_freesync *core_freesync, - const struct dc_stream **streams, int num_streams) + struct dc_stream **streams, int num_streams) { int v_total_nominal = 0, v_total_min = 0, v_total_max = 0; unsigned int stream_idx, map_index = 0; @@ -735,7 +729,7 @@ static void set_static_ramp_variables(struct core_freesync *core_freesync, } void mod_freesync_handle_v_update(struct mod_freesync *mod_freesync, - const struct dc_stream **streams, int num_streams) + struct dc_stream **streams, int num_streams) { unsigned int index, v_total, inserted_frame_v_total = 0; unsigned int min_frame_duration_in_ns, vmax, vmin = 0; @@ -845,7 +839,7 @@ void mod_freesync_handle_v_update(struct mod_freesync *mod_freesync, } void mod_freesync_update_state(struct mod_freesync *mod_freesync, - const struct dc_stream **streams, int num_streams, + struct dc_stream **streams, int num_streams, struct mod_freesync_params *freesync_params) { bool freesync_program_required = false; @@ -935,7 +929,7 @@ void mod_freesync_update_state(struct mod_freesync *mod_freesync, bool mod_freesync_get_state(struct mod_freesync *mod_freesync, - const struct dc_stream *stream, + struct dc_stream *stream, struct mod_freesync_params *freesync_params) { unsigned int index = 0; @@ -971,7 +965,7 @@ bool mod_freesync_get_state(struct mod_freesync *mod_freesync, } bool mod_freesync_set_user_enable(struct mod_freesync *mod_freesync, - const struct dc_stream **streams, int num_streams, + struct dc_stream **streams, int num_streams, struct mod_freesync_user_enable *user_enable) { unsigned int stream_index, map_index; @@ -1023,7 +1017,7 @@ bool mod_freesync_set_user_enable(struct mod_freesync *mod_freesync, } bool mod_freesync_get_user_enable(struct mod_freesync *mod_freesync, - const struct dc_stream *stream, + struct dc_stream *stream, struct mod_freesync_user_enable *user_enable) { unsigned int index = 0; @@ -1041,7 +1035,7 @@ bool mod_freesync_get_user_enable(struct mod_freesync *mod_freesync, } bool mod_freesync_get_static_ramp_active(struct mod_freesync *mod_freesync, - const struct dc_stream *stream, + struct dc_stream *stream, bool *is_ramp_active) { unsigned int index = 0; @@ -1060,7 +1054,7 @@ bool mod_freesync_get_static_ramp_active(struct mod_freesync *mod_freesync, } bool mod_freesync_override_min_max(struct mod_freesync *mod_freesync, - const struct dc_stream *streams, + struct dc_stream *streams, unsigned int min_refresh, unsigned int max_refresh, struct mod_freesync_caps *caps) @@ -1113,7 +1107,7 @@ bool mod_freesync_override_min_max(struct mod_freesync *mod_freesync, } bool mod_freesync_get_min_max(struct mod_freesync *mod_freesync, - const struct dc_stream *stream, + struct dc_stream *stream, unsigned int *min_refresh, unsigned int *max_refresh) { @@ -1135,7 +1129,7 @@ bool mod_freesync_get_min_max(struct mod_freesync *mod_freesync, } bool mod_freesync_get_vmin_vmax(struct mod_freesync *mod_freesync, - const struct dc_stream *stream, + struct dc_stream *stream, unsigned int *vmin, unsigned int *vmax) { @@ -1157,7 +1151,7 @@ bool mod_freesync_get_vmin_vmax(struct mod_freesync *mod_freesync, } bool mod_freesync_get_v_position(struct mod_freesync *mod_freesync, - const struct dc_stream *stream, + struct dc_stream *stream, unsigned int *nom_v_pos, unsigned int *v_pos) { @@ -1185,7 +1179,7 @@ bool mod_freesync_get_v_position(struct mod_freesync *mod_freesync, } void mod_freesync_notify_mode_change(struct mod_freesync *mod_freesync, - const struct dc_stream **streams, int num_streams) + struct dc_stream **streams, int num_streams) { unsigned int stream_index, map_index; struct freesync_state *state; @@ -1310,7 +1304,7 @@ static void update_timestamps(struct core_freesync *core_freesync, } static void apply_below_the_range(struct core_freesync *core_freesync, - const struct dc_stream *stream, unsigned int map_index, + struct dc_stream *stream, unsigned int map_index, unsigned int last_render_time_in_us) { unsigned int inserted_frame_duration_in_us = 0; @@ -1409,7 +1403,7 @@ static void apply_below_the_range(struct core_freesync *core_freesync, } static void apply_fixed_refresh(struct core_freesync *core_freesync, - const struct dc_stream *stream, unsigned int map_index) + struct dc_stream *stream, unsigned int map_index) { unsigned int vmin = 0, vmax = 0; struct freesync_state *state = &core_freesync->map[map_index].state; @@ -1440,7 +1434,7 @@ static void apply_fixed_refresh(struct core_freesync *core_freesync, } void mod_freesync_pre_update_plane_addresses(struct mod_freesync *mod_freesync, - const struct dc_stream **streams, int num_streams, + struct dc_stream **streams, int num_streams, unsigned int curr_time_stamp_in_us) { unsigned int stream_index, map_index, last_render_time_in_us = 0; diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h b/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h index 53c428b97902..2b9d45100bdd 100644 --- a/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h +++ b/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h @@ -101,67 +101,67 @@ struct mod_freesync_params { * Add stream to be tracked by module */ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, - const struct dc_stream *stream, struct mod_freesync_caps *caps); + struct dc_stream *stream, struct mod_freesync_caps *caps); /* * Remove stream to be tracked by module */ bool mod_freesync_remove_stream(struct mod_freesync *mod_freesync, - const struct dc_stream *stream); + struct dc_stream *stream); /* * Update the freesync state flags for each display and program * freesync accordingly */ void mod_freesync_update_state(struct mod_freesync *mod_freesync, - const struct dc_stream **streams, int num_streams, + struct dc_stream **streams, int num_streams, struct mod_freesync_params *freesync_params); bool mod_freesync_get_state(struct mod_freesync *mod_freesync, - const struct dc_stream *stream, + struct dc_stream *stream, struct mod_freesync_params *freesync_params); bool mod_freesync_set_user_enable(struct mod_freesync *mod_freesync, - const struct dc_stream **streams, int num_streams, + struct dc_stream **streams, int num_streams, struct mod_freesync_user_enable *user_enable); bool mod_freesync_get_user_enable(struct mod_freesync *mod_freesync, - const struct dc_stream *stream, + struct dc_stream *stream, struct mod_freesync_user_enable *user_enable); bool mod_freesync_get_static_ramp_active(struct mod_freesync *mod_freesync, - const struct dc_stream *stream, + struct dc_stream *stream, bool *is_ramp_active); bool mod_freesync_override_min_max(struct mod_freesync *mod_freesync, - const struct dc_stream *streams, + struct dc_stream *streams, unsigned int min_refresh, unsigned int max_refresh, struct mod_freesync_caps *caps); bool mod_freesync_get_min_max(struct mod_freesync *mod_freesync, - const struct dc_stream *stream, + struct dc_stream *stream, unsigned int *min_refresh, unsigned int *max_refresh); bool mod_freesync_get_vmin_vmax(struct mod_freesync *mod_freesync, - const struct dc_stream *stream, + struct dc_stream *stream, unsigned int *vmin, unsigned int *vmax); bool mod_freesync_get_v_position(struct mod_freesync *mod_freesync, - const struct dc_stream *stream, + struct dc_stream *stream, unsigned int *nom_v_pos, unsigned int *v_pos); void mod_freesync_handle_v_update(struct mod_freesync *mod_freesync, - const struct dc_stream **streams, int num_streams); + struct dc_stream **streams, int num_streams); void mod_freesync_notify_mode_change(struct mod_freesync *mod_freesync, - const struct dc_stream **streams, int num_streams); + struct dc_stream **streams, int num_streams); void mod_freesync_pre_update_plane_addresses(struct mod_freesync *mod_freesync, - const struct dc_stream **streams, int num_streams, + struct dc_stream **streams, int num_streams, unsigned int curr_time_stamp); #endif -- cgit From a989ab08a7e3ee4675ea56b5dcfd0f2966aa91db Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Wed, 26 Jul 2017 16:13:48 -0400 Subject: drm/amd/display: Roll stream into dc_stream Signed-off-by: Leo (Sunpeng) Li Reviewed-by: Andrey Grodzovsky Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 29 +++++++------------------ 1 file changed, 8 insertions(+), 21 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 46ad1bc12f63..a77e1e80d7c2 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -30,17 +30,6 @@ #include "ipp.h" #include "timing_generator.h" -/******************************************************************************* - * Private definitions - ******************************************************************************/ - -struct stream { - struct dc_stream protected; - int ref_count; -}; - -#define DC_STREAM_TO_STREAM(dc_stream) container_of(dc_stream, struct stream, protected) - /******************************************************************************* * Private functions ******************************************************************************/ @@ -105,24 +94,22 @@ static void destruct(struct dc_stream *stream) } } -void dc_stream_retain(struct dc_stream *dc_stream) +void dc_stream_retain(struct dc_stream *stream) { - struct stream *stream = DC_STREAM_TO_STREAM(dc_stream); ASSERT(stream->ref_count > 0); stream->ref_count++; } -void dc_stream_release(struct dc_stream *public) +void dc_stream_release(struct dc_stream *stream) { - struct stream *stream = DC_STREAM_TO_STREAM(public); - if (public != NULL) { + if (stream != NULL) { ASSERT(stream->ref_count > 0); stream->ref_count--; if (stream->ref_count == 0) { - destruct(public); + destruct(stream); dm_free(stream); } } @@ -131,22 +118,22 @@ void dc_stream_release(struct dc_stream *public) struct dc_stream *dc_create_stream_for_sink( struct dc_sink *sink) { - struct stream *stream; + struct dc_stream *stream; if (sink == NULL) goto alloc_fail; - stream = dm_alloc(sizeof(struct stream)); + stream = dm_alloc(sizeof(struct dc_stream)); if (NULL == stream) goto alloc_fail; - if (false == construct(&stream->protected, sink)) + if (false == construct(stream, sink)) goto construct_fail; stream->ref_count++; - return &stream->protected; + return stream; construct_fail: dm_free(stream); -- cgit From 4d6356b0cc264686597aac2d04886cbfd8607f09 Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Wed, 26 Jul 2017 16:15:26 -0400 Subject: drm/amd/display: reduce 40s time out to 1s in disable crtc Signed-off-by: Eric Yang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c index 0ef5d8f0625c..f4dce2806ae1 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c @@ -429,7 +429,7 @@ static bool tgn10_disable_crtc(struct timing_generator *tg) /* CRTC disabled, so disable clock. */ REG_WAIT(OTG_CLOCK_CONTROL, OTG_BUSY, 0, - 2000, 20000); + 2000, 500); return true; } -- cgit From 2f3bfb2794e1aed018e344469f9c371f36f12867 Mon Sep 17 00:00:00 2001 From: Roman Li Date: Wed, 26 Jul 2017 14:42:38 -0400 Subject: drm/amd/display: safeguard compressor api Only call compressor api if it's available. Signed-off-by: Roman Li Reviewed-by: Bhawanpreet Lakha Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 15f6eeef343d..d45773087644 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1185,7 +1185,8 @@ static void power_down_all_hw_blocks(struct core_dc *dc) power_down_clock_sources(dc); #ifdef ENABLE_FBC - dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); + if (dc->fbc_compressor) + dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); #endif } @@ -1658,7 +1659,8 @@ enum dc_status dce110_apply_ctx_to_hw( set_safe_displaymarks(&context->res_ctx, dc->res_pool); #ifdef ENABLE_FBC - dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); + if (dc->fbc_compressor) + dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); #endif /*TODO: when pplib works*/ apply_min_clocks(dc, context, &clocks_state, true); @@ -2246,7 +2248,8 @@ static void init_hw(struct core_dc *dc) abm->funcs->abm_init(abm); } #ifdef ENABLE_FBC - dc->fbc_compressor->funcs->power_up_fbc(dc->fbc_compressor); + if (dc->fbc_compressor) + dc->fbc_compressor->funcs->power_up_fbc(dc->fbc_compressor); #endif } -- cgit From 54e8695ef14acc04e9aa99957249f520cf52e826 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 26 Jul 2017 16:54:39 -0400 Subject: drm/amd/display: collapse dce11 reset_hw_ctx_wrap into 1 function Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 47 +++++++++------------- 1 file changed, 20 insertions(+), 27 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index d45773087644..6afe572cfb06 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1345,28 +1345,6 @@ static void switch_dp_clock_sources( * Public functions ******************************************************************************/ -static void reset_single_pipe_hw_ctx( - const struct core_dc *dc, - struct pipe_ctx *pipe_ctx, - struct validate_context *context) -{ - core_link_disable_stream(pipe_ctx); - pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, true); - if (!hwss_wait_for_blank_complete(pipe_ctx->tg)) { - dm_error("DC: failed to blank crtc!\n"); - BREAK_TO_DEBUGGER(); - } - pipe_ctx->tg->funcs->disable_crtc(pipe_ctx->tg); - pipe_ctx->mi->funcs->free_mem_input( - pipe_ctx->mi, context->stream_count); - resource_unreference_clock_source(&context->res_ctx, dc->res_pool, - &pipe_ctx->clock_source); - - dc->hwss.power_down_front_end((struct core_dc *)dc, pipe_ctx->pipe_idx); - - pipe_ctx->stream = NULL; -} - static void set_drr(struct pipe_ctx **pipe_ctx, int num_pipes, int vmin, int vmax) { @@ -1580,7 +1558,7 @@ static enum dc_status apply_ctx_to_hw_fpga( return DC_OK; } -static void reset_hw_ctx_wrap( +static void dce110_reset_hw_ctx_wrap( struct core_dc *dc, struct validate_context *context) { @@ -1603,9 +1581,24 @@ static void reset_hw_ctx_wrap( continue; if (!pipe_ctx->stream || - pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) - reset_single_pipe_hw_ctx( - dc, pipe_ctx_old, dc->current_context); + pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) { + core_link_disable_stream(pipe_ctx_old); + pipe_ctx_old->tg->funcs->set_blank(pipe_ctx_old->tg, true); + if (!hwss_wait_for_blank_complete(pipe_ctx_old->tg)) { + dm_error("DC: failed to blank crtc!\n"); + BREAK_TO_DEBUGGER(); + } + pipe_ctx_old->tg->funcs->disable_crtc(pipe_ctx_old->tg); + pipe_ctx_old->mi->funcs->free_mem_input( + pipe_ctx_old->mi, dc->current_context->stream_count); + resource_unreference_clock_source( + &dc->current_context->res_ctx, dc->res_pool, + &pipe_ctx_old->clock_source); + + dc->hwss.power_down_front_end(dc, pipe_ctx_old->pipe_idx); + + pipe_ctx_old->stream = NULL; + } } } @@ -2619,7 +2612,7 @@ static const struct hw_sequencer_funcs dce110_funcs = { .set_drr = set_drr, .get_position = get_position, .set_static_screen_control = set_static_screen_control, - .reset_hw_ctx_wrap = reset_hw_ctx_wrap, + .reset_hw_ctx_wrap = dce110_reset_hw_ctx_wrap, .prog_pixclk_crtc_otg = dce110_prog_pixclk_crtc_otg, .setup_stereo = NULL, .set_avmute = dce110_set_avmute, -- cgit From cc408d726c20f32e4fdd688f870dd2b17960d4a2 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 21 Jul 2017 17:46:50 -0400 Subject: drm/amd/display: mpc block redesign Signed-off-by: Dmytro Laktyushkin Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 2 - drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 5 +- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 146 +++++------- .../gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c | 8 +- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c | 246 ++++++++++++++------- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h | 82 +++---- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c | 3 + .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 74 +++---- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 3 +- drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h | 4 +- drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h | 26 ++- drivers/gpu/drm/amd/display/dc/inc/hw/opp.h | 7 + 12 files changed, 339 insertions(+), 267 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index ef10a8b49379..49b75765d900 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -547,11 +547,9 @@ static void split_stream_across_pipes( *secondary_pipe = *primary_pipe; secondary_pipe->pipe_idx = pipe_idx; - secondary_pipe->mpcc = pool->mpcc[secondary_pipe->pipe_idx]; secondary_pipe->mi = pool->mis[secondary_pipe->pipe_idx]; secondary_pipe->ipp = pool->ipps[secondary_pipe->pipe_idx]; secondary_pipe->xfm = pool->transforms[secondary_pipe->pipe_idx]; - secondary_pipe->opp = pool->opps[secondary_pipe->pipe_idx]; if (primary_pipe->bottom_pipe) { secondary_pipe->bottom_pipe = primary_pipe->bottom_pipe; secondary_pipe->bottom_pipe->top_pipe = secondary_pipe; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index ddbd3de63a8d..4068d53137f5 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1017,7 +1017,6 @@ static int acquire_first_split_pipe( pipe_ctx->xfm = pool->transforms[i]; pipe_ctx->opp = pool->opps[i]; pipe_ctx->dis_clk = pool->display_clock; - pipe_ctx->mpcc = pool->mpcc[i]; pipe_ctx->pipe_idx = i; pipe_ctx->stream = stream; @@ -1096,6 +1095,7 @@ bool resource_attach_surfaces_to_context( if (tail_pipe) { free_pipe->tg = tail_pipe->tg; + free_pipe->opp = tail_pipe->opp; free_pipe->stream_enc = tail_pipe->stream_enc; free_pipe->audio = tail_pipe->audio; free_pipe->clock_source = tail_pipe->clock_source; @@ -1241,9 +1241,6 @@ static int acquire_first_free_pipe( if (!res_ctx->pipe_ctx[i].stream) { struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) - pipe_ctx->mpcc = pool->mpcc[i]; -#endif pipe_ctx->tg = pool->timing_generators[i]; pipe_ctx->mi = pool->mis[i]; pipe_ctx->ipp = pool->ipps[i]; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 1531b52e61c2..2299bdaca376 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -636,15 +636,10 @@ static void dcn10_init_hw(struct core_dc *dc) for (i = 0; i < dc->res_pool->pipe_count; i++) { struct transform *xfm = dc->res_pool->transforms[i]; struct timing_generator *tg = dc->res_pool->timing_generators[i]; - struct mpcc *mpcc = dc->res_pool->mpcc[i]; - struct mpcc_cfg mpcc_cfg; xfm->funcs->transform_reset(xfm); - mpcc_cfg.opp_id = 0xf; - mpcc_cfg.top_dpp_id = 0xf; - mpcc_cfg.bot_mpcc_id = 0xf; - mpcc_cfg.top_of_tree = true; - mpcc->funcs->set(mpcc, &mpcc_cfg); + dc->res_pool->mpc->funcs->remove( + dc->res_pool->mpc, dc->res_pool->opps[i], i); /* Blank controller using driver code instead of * command table. @@ -819,45 +814,35 @@ static void reset_back_end_for_pipe( static void plane_atomic_disconnect(struct core_dc *dc, int fe_idx) { - struct mpcc_cfg mpcc_cfg; struct mem_input *mi = dc->res_pool->mis[fe_idx]; - struct transform *xfm = dc->res_pool->transforms[fe_idx]; - struct mpcc *mpcc = dc->res_pool->mpcc[fe_idx]; - struct timing_generator *tg = dc->res_pool->timing_generators[mpcc->opp_id]; - unsigned int opp_id = mpcc->opp_id; - int opp_id_cached = mpcc->opp_id; + struct mpc *mpc = dc->res_pool->mpc; + int opp_id, z_idx; + int mpcc_id = -1; + + /* look at tree rather than mi here to know if we already reset */ + for (opp_id = 0; opp_id < dc->res_pool->pipe_count; opp_id++) { + struct output_pixel_processor *opp = dc->res_pool->opps[opp_id]; + for (z_idx = 0; z_idx < opp->mpc_tree.num_pipes; z_idx++) { + if (opp->mpc_tree.dpp[z_idx] == fe_idx) { + mpcc_id = opp->mpc_tree.mpcc[z_idx]; + break; + } + } + if (mpcc_id != -1) + break; + } /*Already reset*/ - if (opp_id == 0xf) + if (opp_id == dc->res_pool->pipe_count) return; if (dc->public.debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); - mi->funcs->dcc_control(mi, false, false); - if (dc->public.debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); - mpcc_cfg.opp_id = 0xf; - mpcc_cfg.top_dpp_id = 0xf; - mpcc_cfg.bot_mpcc_id = 0xf; - mpcc_cfg.top_of_tree = tg->inst == mpcc->inst; - mpcc->funcs->set(mpcc, &mpcc_cfg); - - /* - * Hack to preserve old opp_id for plane_atomic_disable - * to find the correct otg - */ - mpcc->opp_id = opp_id_cached; - - /* todo:call remove pipe from tree */ - /* flag mpcc idle pending */ - - /*dm_logger_write(dc->ctx->logger, LOG_ERROR, - "[debug_mpo: plane_atomic_disconnect pending on mpcc %d]\n", - fe_idx);*/ - xfm->funcs->transform_reset(xfm); + mpc->funcs->remove(mpc, dc->res_pool->opps[opp_id], fe_idx); } /* disable HW used by plane. @@ -867,20 +852,21 @@ static void plane_atomic_disable(struct core_dc *dc, { struct dce_hwseq *hws = dc->hwseq; struct mem_input *mi = dc->res_pool->mis[fe_idx]; - struct mpcc *mpcc = dc->res_pool->mpcc[fe_idx]; - struct timing_generator *tg = dc->res_pool->timing_generators[mpcc->opp_id]; - unsigned int opp_id = mpcc->opp_id; + struct mpc *mpc = dc->res_pool->mpc; - if (opp_id == 0xf) + if (mi->opp_id == 0xf) return; - mpcc->funcs->wait_for_idle(mpcc); - dc->res_pool->opps[opp_id]->mpcc_disconnect_pending[mpcc->inst] = false; + mpc->funcs->wait_for_idle(mpc, mi->mpcc_id); + dc->res_pool->opps[mi->opp_id]->mpcc_disconnect_pending[mi->mpcc_id] = false; /*dm_logger_write(dc->ctx->logger, LOG_ERROR, "[debug_mpo: atomic disable finished on mpcc %d]\n", fe_idx);*/ mi->funcs->set_blank(mi, true); + /*todo: unhack this*/ + mi->opp_id = 0xf; + mi->mpcc_id = 0xf; if (dc->public.debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); @@ -890,12 +876,10 @@ static void plane_atomic_disable(struct core_dc *dc, REG_UPDATE(DPP_CONTROL[fe_idx], DPP_CLOCK_ENABLE, 0); - if (tg->inst == mpcc->inst) - REG_UPDATE(OPP_PIPE_CONTROL[opp_id], + if (dc->res_pool->opps[mi->opp_id]->mpc_tree.num_pipes == 0) + REG_UPDATE(OPP_PIPE_CONTROL[mi->opp_id], OPP_PIPE_CLOCK_EN, 0); - mpcc->opp_id = 0xf; - if (dc->public.debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); } @@ -907,11 +891,13 @@ static void plane_atomic_disable(struct core_dc *dc, static void plane_atomic_power_down(struct core_dc *dc, int fe_idx) { struct dce_hwseq *hws = dc->hwseq; + struct transform *xfm = dc->res_pool->transforms[fe_idx]; REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1); dpp_pg_control(hws, fe_idx, false); hubp_pg_control(hws, fe_idx, false); + xfm->funcs->transform_reset(xfm); REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0); dm_logger_write(dc->ctx->logger, LOG_DC, @@ -927,14 +913,14 @@ static void reset_front_end( int fe_idx) { struct dce_hwseq *hws = dc->hwseq; - struct mpcc *mpcc = dc->res_pool->mpcc[fe_idx]; - struct timing_generator *tg = dc->res_pool->timing_generators[mpcc->opp_id]; - unsigned int opp_id = mpcc->opp_id; + struct timing_generator *tg; + int opp_id = dc->res_pool->mis[fe_idx]->opp_id; /*Already reset*/ if (opp_id == 0xf) return; + tg = dc->res_pool->timing_generators[opp_id]; tg->funcs->lock(tg); plane_atomic_disconnect(dc, fe_idx); @@ -943,7 +929,7 @@ static void reset_front_end( tg->funcs->unlock(tg); if (dc->public.debug.sanity_checks) - verify_allow_pstate_change_high(dc->hwseq); + verify_allow_pstate_change_high(hws); if (tg->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS) REG_WAIT(OTG_GLOBAL_SYNC_STATUS[tg->inst], @@ -959,6 +945,7 @@ static void reset_front_end( static void dcn10_power_down_fe(struct core_dc *dc, int fe_idx) { struct dce_hwseq *hws = dc->hwseq; + struct transform *xfm = dc->res_pool->transforms[fe_idx]; reset_front_end(dc, fe_idx); @@ -966,6 +953,7 @@ static void dcn10_power_down_fe(struct core_dc *dc, int fe_idx) IP_REQUEST_EN, 1); dpp_pg_control(hws, fe_idx, false); hubp_pg_control(hws, fe_idx, false); + xfm->funcs->transform_reset(xfm); REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0); dm_logger_write(dc->ctx->logger, LOG_DC, @@ -1910,8 +1898,8 @@ static void update_dchubp_dpp( struct dc_surface *surface = pipe_ctx->surface; union plane_size size = surface->plane_size; struct default_adjustment ocsc = {0}; - struct tg_color black_color = {0}; - struct mpcc_cfg mpcc_cfg; + struct mpcc_cfg mpcc_cfg = {0}; + struct pipe_ctx *top_pipe; bool per_pixel_alpha = surface->per_pixel_alpha && pipe_ctx->bottom_pipe; /* TODO: proper fix once fpga works */ @@ -1954,14 +1942,17 @@ static void update_dchubp_dpp( 1, IPP_OUTPUT_FORMAT_12_BIT_FIX); - pipe_ctx->scl_data.lb_params.alpha_en = per_pixel_alpha; - mpcc_cfg.top_dpp_id = pipe_ctx->pipe_idx; - if (pipe_ctx->bottom_pipe) - mpcc_cfg.bot_mpcc_id = pipe_ctx->bottom_pipe->mpcc->inst; + mpcc_cfg.mi = mi; + mpcc_cfg.opp = pipe_ctx->opp; + for (top_pipe = pipe_ctx->top_pipe; top_pipe; top_pipe = top_pipe->top_pipe) + mpcc_cfg.z_index++; + if (dc->public.debug.surface_visual_confirm) + dcn10_get_surface_visual_confirm_color( + pipe_ctx, &mpcc_cfg.black_color); else - mpcc_cfg.bot_mpcc_id = 0xf; - mpcc_cfg.opp_id = pipe_ctx->tg->inst; - mpcc_cfg.top_of_tree = pipe_ctx->pipe_idx == pipe_ctx->tg->inst; + color_space_to_black_color( + dc, pipe_ctx->stream->output_color_space, + &mpcc_cfg.black_color); mpcc_cfg.per_pixel_alpha = per_pixel_alpha; /* DCN1.0 has output CM before MPC which seems to screw with * pre-multiplied alpha. @@ -1969,17 +1960,9 @@ static void update_dchubp_dpp( mpcc_cfg.pre_multiplied_alpha = is_rgb_cspace( pipe_ctx->stream->output_color_space) && per_pixel_alpha; - pipe_ctx->mpcc->funcs->set(pipe_ctx->mpcc, &mpcc_cfg); - - if (dc->public.debug.surface_visual_confirm) { - dcn10_get_surface_visual_confirm_color(pipe_ctx, &black_color); - } else { - color_space_to_black_color( - dc, pipe_ctx->stream->output_color_space, - &black_color); - } - pipe_ctx->mpcc->funcs->set_bg_color(pipe_ctx->mpcc, &black_color); + dc->res_pool->mpc->funcs->add(dc->res_pool->mpc, &mpcc_cfg); + pipe_ctx->scl_data.lb_params.alpha_en = per_pixel_alpha; pipe_ctx->scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; /* scaler configuration */ pipe_ctx->xfm->funcs->transform_set_scaler( @@ -2112,7 +2095,7 @@ static void dcn10_apply_ctx_for_surface( */ if (pipe_ctx->surface && !old_pipe_ctx->surface) { - if (pipe_ctx->mpcc->opp_id != 0xf && pipe_ctx->tg->inst == be_idx) { + if (pipe_ctx->mi->opp_id != 0xf && pipe_ctx->tg->inst == be_idx) { dcn10_power_down_fe(dc, pipe_ctx->pipe_idx); /* * power down fe will unlock when calling reset, need @@ -2125,9 +2108,6 @@ static void dcn10_apply_ctx_for_surface( if ((!pipe_ctx->surface && old_pipe_ctx->surface) || (!pipe_ctx->stream && old_pipe_ctx->stream)) { - struct mpcc_cfg mpcc_cfg; - int opp_id_cached = old_pipe_ctx->mpcc->opp_id; - if (old_pipe_ctx->tg->inst != be_idx) continue; @@ -2137,12 +2117,11 @@ static void dcn10_apply_ctx_for_surface( } /* reset mpc */ - mpcc_cfg.opp_id = 0xf; - mpcc_cfg.top_dpp_id = 0xf; - mpcc_cfg.bot_mpcc_id = 0xf; - mpcc_cfg.top_of_tree = !old_pipe_ctx->top_pipe; - old_pipe_ctx->mpcc->funcs->set(old_pipe_ctx->mpcc, &mpcc_cfg); - old_pipe_ctx->top_pipe->opp->mpcc_disconnect_pending[old_pipe_ctx->mpcc->inst] = true; + dc->res_pool->mpc->funcs->remove( + dc->res_pool->mpc, + old_pipe_ctx->opp, + old_pipe_ctx->pipe_idx); + old_pipe_ctx->opp->mpcc_disconnect_pending[old_pipe_ctx->mi->mpcc_id] = true; /*dm_logger_write(dc->ctx->logger, LOG_ERROR, "[debug_mpo: apply_ctx disconnect pending on mpcc %d]\n", @@ -2151,13 +2130,6 @@ static void dcn10_apply_ctx_for_surface( if (dc->public.debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); - /* - * the mpcc is the only thing that keeps track of the mpcc - * mapping for reset front end right now. Might need some - * rework. - */ - old_pipe_ctx->mpcc->opp_id = opp_id_cached; - old_pipe_ctx->top_pipe = NULL; old_pipe_ctx->bottom_pipe = NULL; old_pipe_ctx->surface = NULL; @@ -2466,12 +2438,12 @@ static void dcn10_wait_for_mpcc_disconnect( { int i; - if (!pipe_ctx->opp || !pipe_ctx->mpcc) + if (!pipe_ctx->opp) return; for (i = 0; i < MAX_PIPES; i++) { if (pipe_ctx->opp->mpcc_disconnect_pending[i]) { - pipe_ctx->mpcc->funcs->wait_for_idle(res_pool->mpcc[i]); + res_pool->mpc->funcs->wait_for_idle(res_pool->mpc, i); pipe_ctx->opp->mpcc_disconnect_pending[i] = false; res_pool->mis[i]->funcs->set_blank(res_pool->mis[i], true); /*dm_logger_write(dc->ctx->logger, LOG_ERROR, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index 6f01db6a51dd..76879f5d7907 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -47,10 +47,14 @@ static void min10_set_blank(struct mem_input *mem_input, bool blank) HUBP_BLANK_EN, blank_en, HUBP_TTU_DISABLE, blank_en); - if (blank) + if (blank) { REG_WAIT(DCHUBP_CNTL, HUBP_NO_OUTSTANDING_REQ, 1, 1, 200); + /*todo: unhack this + mem_input->mpcc_id = 0xf; + mem_input->opp_id = 0xf;*/ + } } static void min10_vready_workaround(struct mem_input *mem_input, @@ -871,6 +875,8 @@ bool dcn10_mem_input_construct( mi->mi_shift = mi_shift; mi->mi_mask = mi_mask; mi->base.inst = inst; + mi->base.opp_id = 0xf; + mi->base.mpcc_id = 0xf; return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c index 9af288167e2e..246b60a16521 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c @@ -26,16 +26,17 @@ #include "reg_helper.h" #include "dcn10_mpc.h" #include "dc.h" +#include "mem_input.h" #define REG(reg)\ - mpcc10->mpcc_regs->reg + mpc10->mpc_regs->reg #define CTX \ - mpcc10->base.ctx + mpc10->base.ctx #undef FN #define FN(reg_name, field_name) \ - mpcc10->mpcc_shift->field_name, mpcc10->mpcc_mask->field_name + mpc10->mpc_shift->field_name, mpc10->mpc_mask->field_name #define MODE_TOP_ONLY 1 #define MODE_BLEND 3 @@ -43,11 +44,11 @@ #define BLND_GLOBAL_ALPHA 2 -void dcn10_mpcc_set_bg_color( - struct mpcc *mpcc, - struct tg_color *bg_color) +static void mpc10_set_bg_color( + struct dcn10_mpc *mpc10, + struct tg_color *bg_color, + int id) { - struct dcn10_mpcc *mpcc10 = TO_DCN10_MPCC(mpcc); /* mpc color is 12 bit. tg_color is 10 bit */ /* todo: might want to use 16 bit to represent color and have each * hw block translate to correct color depth. @@ -56,113 +57,210 @@ void dcn10_mpcc_set_bg_color( uint32_t bg_g_y = bg_color->color_g_y << 2; uint32_t bg_b_cb = bg_color->color_b_cb << 2; - REG_SET(MPCC_BG_R_CR, 0, + REG_SET(MPCC_BG_R_CR[id], 0, MPCC_BG_R_CR, bg_r_cr); - REG_SET(MPCC_BG_G_Y, 0, + REG_SET(MPCC_BG_G_Y[id], 0, MPCC_BG_G_Y, bg_g_y); - REG_SET(MPCC_BG_B_CB, 0, + REG_SET(MPCC_BG_B_CB[id], 0, MPCC_BG_B_CB, bg_b_cb); } -static void set_output_mux(struct dcn10_mpcc *mpcc10, int opp_id, int mpcc_id) +static void mpc10_assert_idle_mpcc(struct mpc *mpc, int id) { - ASSERT(mpcc10->base.opp_id == 0xf || opp_id == mpcc10->base.opp_id); - mpcc10->base.opp_id = opp_id; - REG_SET(MUX[opp_id], 0, MPC_OUT_MUX, mpcc_id); + struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); + + ASSERT(!(mpc10->mpcc_in_use_mask & 1 << id)); + REG_WAIT(MPCC_STATUS[id], + MPCC_BUSY, 0, + 1000, 1000); } -static void reset_output_mux(struct dcn10_mpcc *mpcc10) +static int mpc10_get_idle_mpcc_id(struct dcn10_mpc *mpc10) { - REG_SET(MUX[mpcc10->base.opp_id], 0, MPC_OUT_MUX, 0xf); - mpcc10->base.opp_id = 0xf; + int i; + int last_free_mpcc_id = -1; + + for (i = 0; i < mpc10->num_mpcc; i++) { + uint32_t is_idle = 0; + + if (mpc10->mpcc_in_use_mask & 1 << i) + continue; + + last_free_mpcc_id = i; + REG_GET(MPCC_STATUS[i], MPCC_IDLE, &is_idle); + if (is_idle) + return i; + } + + /* This assert should never trigger, we have mpcc leak if it does */ + ASSERT(last_free_mpcc_id != -1); + + mpc10_assert_idle_mpcc(&mpc10->base, last_free_mpcc_id); + return last_free_mpcc_id; } -static void assert_mpcc_idle_before_connect(struct dcn10_mpcc *mpcc10) +static void mpc10_assert_mpcc_idle_before_connect(struct dcn10_mpc *mpc10, int id) { - unsigned int top_sel; - unsigned int mpcc_busy, mpcc_idle, mpcc_status; + unsigned int top_sel, mpc_busy, mpc_idle; - REG_GET(MPCC_TOP_SEL, + REG_GET(MPCC_TOP_SEL[id], MPCC_TOP_SEL, &top_sel); if (top_sel == 0xf) { - mpcc_status = REG_GET_2(MPCC_STATUS, - MPCC_BUSY, &mpcc_busy, - MPCC_IDLE, &mpcc_idle); + REG_GET_2(MPCC_STATUS[id], + MPCC_BUSY, &mpc_busy, + MPCC_IDLE, &mpc_idle); + + ASSERT(mpc_busy == 0); + ASSERT(mpc_idle == 1); + } +} + +static void mpc10_mpcc_remove( + struct mpc *mpc, + struct output_pixel_processor *opp, + int dpp_id) +{ + struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); + int mpcc_id, z_idx; + + for (z_idx = 0; z_idx < opp->mpc_tree.num_pipes; z_idx++) + if (opp->mpc_tree.dpp[z_idx] == dpp_id) + break; + if (z_idx == opp->mpc_tree.num_pipes) { + ASSERT(0); + return; + } + mpcc_id = opp->mpc_tree.mpcc[z_idx]; + + REG_SET(MPCC_OPP_ID[mpcc_id], 0, + MPCC_OPP_ID, 0xf); + REG_SET(MPCC_TOP_SEL[mpcc_id], 0, + MPCC_TOP_SEL, 0xf); + REG_SET(MPCC_BOT_SEL[mpcc_id], 0, + MPCC_BOT_SEL, 0xf); - ASSERT(mpcc_busy == 0); - ASSERT(mpcc_idle == 1); + if (z_idx > 0) { + int top_mpcc_id = opp->mpc_tree.mpcc[z_idx - 1]; + + if (z_idx + 1 < opp->mpc_tree.num_pipes) + REG_SET(MPCC_BOT_SEL[top_mpcc_id], 0, + MPCC_BOT_SEL, opp->mpc_tree.mpcc[z_idx + 1]); + else { + REG_SET(MPCC_BOT_SEL[top_mpcc_id], 0, + MPCC_BOT_SEL, 0xf); + REG_UPDATE(MPCC_CONTROL[top_mpcc_id], + MPCC_MODE, MODE_TOP_ONLY); + } + } else if (opp->mpc_tree.num_pipes > 1) + REG_SET(MUX[opp->inst], 0, + MPC_OUT_MUX, opp->mpc_tree.mpcc[z_idx + 1]); + else + REG_SET(MUX[opp->inst], 0, MPC_OUT_MUX, 0xf); + + mpc10->mpcc_in_use_mask &= ~(1 << mpcc_id); + opp->mpc_tree.num_pipes--; + for (; z_idx < opp->mpc_tree.num_pipes; z_idx++) { + opp->mpc_tree.dpp[z_idx] = opp->mpc_tree.dpp[z_idx + 1]; + opp->mpc_tree.mpcc[z_idx] = opp->mpc_tree.mpcc[z_idx + 1]; } + opp->mpc_tree.dpp[opp->mpc_tree.num_pipes] = 0xdeadbeef; + opp->mpc_tree.mpcc[opp->mpc_tree.num_pipes] = 0xdeadbeef; } -static void dcn10_mpcc_set(struct mpcc *mpcc, struct mpcc_cfg *cfg) +static void mpc10_mpcc_add(struct mpc *mpc, struct mpcc_cfg *cfg) { - struct dcn10_mpcc *mpcc10 = TO_DCN10_MPCC(mpcc); + struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); int alpha_blnd_mode = cfg->per_pixel_alpha ? BLND_PP_ALPHA : BLND_GLOBAL_ALPHA; - int mpcc_mode = cfg->bot_mpcc_id != 0xf ? - MODE_BLEND : MODE_TOP_ONLY; - bool blend_active_only = cfg->top_of_tree && - !mpcc->ctx->dc->debug.surface_visual_confirm; + int mpcc_mode = MODE_TOP_ONLY; + int mpcc_id, z_idx; + + ASSERT(cfg->z_index < mpc10->num_mpcc); - if (mpcc->ctx->dc->debug.sanity_checks) - assert_mpcc_idle_before_connect(mpcc10); + for (z_idx = 0; z_idx < cfg->opp->mpc_tree.num_pipes; z_idx++) + if (cfg->opp->mpc_tree.dpp[z_idx] == cfg->mi->inst) + break; + if (z_idx == cfg->opp->mpc_tree.num_pipes) { + ASSERT(cfg->z_index <= cfg->opp->mpc_tree.num_pipes); + mpcc_id = mpc10_get_idle_mpcc_id(mpc10); + /*todo: remove hack*/ + mpcc_id = cfg->mi->inst; + ASSERT(!(mpc10->mpcc_in_use_mask & 1 << mpcc_id)); + + if (mpc->ctx->dc->debug.sanity_checks) + mpc10_assert_mpcc_idle_before_connect(mpc10, mpcc_id); + } else { + ASSERT(cfg->z_index < cfg->opp->mpc_tree.num_pipes); + mpcc_id = cfg->opp->mpc_tree.mpcc[z_idx]; + mpc10_mpcc_remove(mpc, cfg->opp, cfg->mi->inst); + } - REG_SET(MPCC_OPP_ID, 0, - MPCC_OPP_ID, cfg->opp_id); + REG_SET(MPCC_OPP_ID[mpcc_id], 0, + MPCC_OPP_ID, cfg->opp->inst); - REG_SET(MPCC_TOP_SEL, 0, - MPCC_TOP_SEL, cfg->top_dpp_id); + REG_SET(MPCC_TOP_SEL[mpcc_id], 0, + MPCC_TOP_SEL, cfg->mi->inst); - REG_SET(MPCC_BOT_SEL, 0, - MPCC_BOT_SEL, cfg->bot_mpcc_id); + if (cfg->z_index > 0) { + int top_mpcc_id = cfg->opp->mpc_tree.mpcc[cfg->z_index - 1]; + + REG_SET(MPCC_BOT_SEL[top_mpcc_id], 0, + MPCC_BOT_SEL, mpcc_id); + REG_UPDATE(MPCC_CONTROL[top_mpcc_id], + MPCC_MODE, MODE_BLEND); + } else + REG_SET(MUX[cfg->opp->inst], 0, MPC_OUT_MUX, mpcc_id); + + if (cfg->z_index < cfg->opp->mpc_tree.num_pipes) { + int bot_mpcc_id = cfg->opp->mpc_tree.mpcc[cfg->z_index]; + + REG_SET(MPCC_BOT_SEL[mpcc_id], 0, + MPCC_BOT_SEL, bot_mpcc_id); + mpcc_mode = MODE_BLEND; + } - REG_SET_4(MPCC_CONTROL, 0xffffffff, + REG_SET_4(MPCC_CONTROL[mpcc_id], 0xffffffff, MPCC_MODE, mpcc_mode, MPCC_ALPHA_BLND_MODE, alpha_blnd_mode, MPCC_ALPHA_MULTIPLIED_MODE, cfg->pre_multiplied_alpha, - MPCC_BLND_ACTIVE_OVERLAP_ONLY, blend_active_only); + MPCC_BLND_ACTIVE_OVERLAP_ONLY, false); - if (cfg->top_of_tree) { - if (cfg->opp_id != 0xf) - set_output_mux(mpcc10, cfg->opp_id, mpcc->inst); - else if (mpcc->opp_id != 0xf) - reset_output_mux(mpcc10); - } - mpcc10->base.opp_id = cfg->opp_id; -} - -static void dcn10_mpcc_wait_idle(struct mpcc *mpcc) -{ - struct dcn10_mpcc *mpcc10 = TO_DCN10_MPCC(mpcc); + mpc10_set_bg_color(mpc10, &cfg->black_color, mpcc_id); - REG_WAIT(MPCC_STATUS, - MPCC_BUSY, 0, - 1000, 1000); + mpc10->mpcc_in_use_mask |= 1 << mpcc_id; + for (z_idx = cfg->z_index; z_idx < cfg->opp->mpc_tree.num_pipes; z_idx++) { + cfg->opp->mpc_tree.dpp[z_idx + 1] = cfg->opp->mpc_tree.dpp[z_idx]; + cfg->opp->mpc_tree.mpcc[z_idx + 1] = cfg->opp->mpc_tree.mpcc[z_idx]; + } + cfg->opp->mpc_tree.dpp[cfg->z_index] = cfg->mi->inst; + cfg->opp->mpc_tree.mpcc[cfg->z_index] = mpcc_id; + cfg->opp->mpc_tree.num_pipes++; + cfg->mi->opp_id = cfg->opp->inst; + cfg->mi->mpcc_id = mpcc_id; } - -const struct mpcc_funcs dcn10_mpcc_funcs = { - .set = dcn10_mpcc_set, - .wait_for_idle = dcn10_mpcc_wait_idle, - .set_bg_color = dcn10_mpcc_set_bg_color, +const struct mpc_funcs dcn10_mpc_funcs = { + .add = mpc10_mpcc_add, + .remove = mpc10_mpcc_remove, + .wait_for_idle = mpc10_assert_idle_mpcc }; -void dcn10_mpcc_construct(struct dcn10_mpcc *mpcc10, +void dcn10_mpc_construct(struct dcn10_mpc *mpc10, struct dc_context *ctx, - const struct dcn_mpcc_registers *mpcc_regs, - const struct dcn_mpcc_shift *mpcc_shift, - const struct dcn_mpcc_mask *mpcc_mask, - int inst) + const struct dcn_mpc_registers *mpc_regs, + const struct dcn_mpc_shift *mpc_shift, + const struct dcn_mpc_mask *mpc_mask, + int num_mpcc) { - mpcc10->base.ctx = ctx; + mpc10->base.ctx = ctx; - mpcc10->base.inst = inst; - mpcc10->base.funcs = &dcn10_mpcc_funcs; + mpc10->base.funcs = &dcn10_mpc_funcs; - mpcc10->mpcc_regs = mpcc_regs; - mpcc10->mpcc_shift = mpcc_shift; - mpcc10->mpcc_mask = mpcc_mask; + mpc10->mpc_regs = mpc_regs; + mpc10->mpc_shift = mpc_shift; + mpc10->mpc_mask = mpc_mask; - mpcc10->base.opp_id = inst; + mpc10->mpcc_in_use_mask = 0; + mpc10->num_mpcc = num_mpcc; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h index 2985c5d5a0e3..94f890a0ad40 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h @@ -27,38 +27,37 @@ #include "mpc.h" -#define TO_DCN10_MPCC(mpcc_base) \ - container_of(mpcc_base, struct dcn10_mpcc, base) +#define TO_DCN10_MPC(mpc_base) \ + container_of(mpc_base, struct dcn10_mpc, base) +#define MAX_MPCC 6 #define MAX_OPP 6 #define MPC_COMMON_REG_LIST_DCN1_0(inst) \ - SRII(MUX, MPC_OUT, inst) + SRII(MUX, MPC_OUT, inst),\ + SRII(MPCC_TOP_SEL, MPCC, inst),\ + SRII(MPCC_BOT_SEL, MPCC, inst),\ + SRII(MPCC_CONTROL, MPCC, inst),\ + SRII(MPCC_STATUS, MPCC, inst),\ + SRII(MPCC_OPP_ID, MPCC, inst),\ + SRII(MPCC_BG_G_Y, MPCC, inst),\ + SRII(MPCC_BG_R_CR, MPCC, inst),\ + SRII(MPCC_BG_B_CB, MPCC, inst),\ + SRII(MPCC_BG_B_CB, MPCC, inst) -#define MPCC_COMMON_REG_LIST_DCN1_0(inst) \ - SRI(MPCC_TOP_SEL, MPCC, inst),\ - SRI(MPCC_BOT_SEL, MPCC, inst),\ - SRI(MPCC_CONTROL, MPCC, inst),\ - SRI(MPCC_STATUS, MPCC, inst),\ - SRI(MPCC_OPP_ID, MPCC, inst),\ - SRI(MPCC_BG_G_Y, MPCC, inst),\ - SRI(MPCC_BG_R_CR, MPCC, inst),\ - SRI(MPCC_BG_B_CB, MPCC, inst),\ - SRI(MPCC_BG_B_CB, MPCC, inst) - -struct dcn_mpcc_registers { - uint32_t MPCC_TOP_SEL; - uint32_t MPCC_BOT_SEL; - uint32_t MPCC_CONTROL; - uint32_t MPCC_STATUS; - uint32_t MPCC_OPP_ID; - uint32_t MPCC_BG_G_Y; - uint32_t MPCC_BG_R_CR; - uint32_t MPCC_BG_B_CB; +struct dcn_mpc_registers { + uint32_t MPCC_TOP_SEL[MAX_MPCC]; + uint32_t MPCC_BOT_SEL[MAX_MPCC]; + uint32_t MPCC_CONTROL[MAX_MPCC]; + uint32_t MPCC_STATUS[MAX_MPCC]; + uint32_t MPCC_OPP_ID[MAX_MPCC]; + uint32_t MPCC_BG_G_Y[MAX_MPCC]; + uint32_t MPCC_BG_R_CR[MAX_MPCC]; + uint32_t MPCC_BG_B_CB[MAX_MPCC]; uint32_t MUX[MAX_OPP]; }; -#define MPCC_COMMON_MASK_SH_LIST_DCN1_0(mask_sh)\ +#define MPC_COMMON_MASK_SH_LIST_DCN1_0(mask_sh)\ SF(MPCC0_MPCC_TOP_SEL, MPCC_TOP_SEL, mask_sh),\ SF(MPCC0_MPCC_BOT_SEL, MPCC_BOT_SEL, mask_sh),\ SF(MPCC0_MPCC_CONTROL, MPCC_MODE, mask_sh),\ @@ -73,7 +72,7 @@ struct dcn_mpcc_registers { SF(MPCC0_MPCC_BG_B_CB, MPCC_BG_B_CB, mask_sh),\ SF(MPC_OUT0_MUX, MPC_OUT_MUX, mask_sh) -#define MPCC_REG_FIELD_LIST(type) \ +#define MPC_REG_FIELD_LIST(type) \ type MPCC_TOP_SEL;\ type MPCC_BOT_SEL;\ type MPCC_MODE;\ @@ -86,28 +85,31 @@ struct dcn_mpcc_registers { type MPCC_BG_G_Y;\ type MPCC_BG_R_CR;\ type MPCC_BG_B_CB;\ - type MPC_OUT_MUX;\ + type MPC_OUT_MUX; -struct dcn_mpcc_shift { - MPCC_REG_FIELD_LIST(uint8_t) +struct dcn_mpc_shift { + MPC_REG_FIELD_LIST(uint8_t) }; -struct dcn_mpcc_mask { - MPCC_REG_FIELD_LIST(uint32_t) +struct dcn_mpc_mask { + MPC_REG_FIELD_LIST(uint32_t) }; -struct dcn10_mpcc { - struct mpcc base; - const struct dcn_mpcc_registers *mpcc_regs; - const struct dcn_mpcc_shift *mpcc_shift; - const struct dcn_mpcc_mask *mpcc_mask; +struct dcn10_mpc { + struct mpc base; + + int mpcc_in_use_mask; + int num_mpcc; + const struct dcn_mpc_registers *mpc_regs; + const struct dcn_mpc_shift *mpc_shift; + const struct dcn_mpc_mask *mpc_mask; }; -void dcn10_mpcc_construct(struct dcn10_mpcc *mpcc10, +void dcn10_mpc_construct(struct dcn10_mpc *mpcc10, struct dc_context *ctx, - const struct dcn_mpcc_registers *mpcc_regs, - const struct dcn_mpcc_shift *mpcc_shift, - const struct dcn_mpcc_mask *mpcc_mask, - int inst); + const struct dcn_mpc_registers *mpc_regs, + const struct dcn_mpc_shift *mpc_shift, + const struct dcn_mpc_mask *mpc_mask, + int num_mpcc); #endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c index f8e4724a629d..38d15f7c2a88 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c @@ -337,6 +337,9 @@ void dcn10_opp_construct(struct dcn10_opp *oppn10, oppn10->base.inst = inst; oppn10->base.funcs = &dcn10_opp_funcs; + oppn10->base.mpc_tree.dpp[0] = inst; + oppn10->base.mpc_tree.mpcc[0] = inst; + oppn10->base.mpc_tree.num_pipes = 1; for (i = 0; i < MAX_PIPES; i++) oppn10->base.mpcc_disconnect_pending[i] = false; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 33beb0bc3ddf..9d44f42cbf96 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -324,29 +324,19 @@ static const struct dcn_dpp_mask tf_mask = { TF_REG_LIST_SH_MASK_DCN10(_MASK), }; - -#define mpcc_regs(id)\ -[id] = {\ - MPCC_COMMON_REG_LIST_DCN1_0(id),\ - MPC_COMMON_REG_LIST_DCN1_0(0),\ - MPC_COMMON_REG_LIST_DCN1_0(1),\ - MPC_COMMON_REG_LIST_DCN1_0(2),\ - MPC_COMMON_REG_LIST_DCN1_0(3),\ -} - -static const struct dcn_mpcc_registers mpcc_regs[] = { - mpcc_regs(0), - mpcc_regs(1), - mpcc_regs(2), - mpcc_regs(3), +static const struct dcn_mpc_registers mpc_regs = { + MPC_COMMON_REG_LIST_DCN1_0(0), + MPC_COMMON_REG_LIST_DCN1_0(1), + MPC_COMMON_REG_LIST_DCN1_0(2), + MPC_COMMON_REG_LIST_DCN1_0(3) }; -static const struct dcn_mpcc_shift mpcc_shift = { - MPCC_COMMON_MASK_SH_LIST_DCN1_0(__SHIFT) +static const struct dcn_mpc_shift mpc_shift = { + MPC_COMMON_MASK_SH_LIST_DCN1_0(__SHIFT) }; -static const struct dcn_mpcc_mask mpcc_mask = { - MPCC_COMMON_MASK_SH_LIST_DCN1_0(_MASK), +static const struct dcn_mpc_mask mpc_mask = { + MPC_COMMON_MASK_SH_LIST_DCN1_0(_MASK), }; #define tg_regs(id)\ @@ -508,22 +498,20 @@ static struct output_pixel_processor *dcn10_opp_create( return &opp->base; } -static struct mpcc *dcn10_mpcc_create( - struct dc_context *ctx, - int inst) +static struct mpc *dcn10_mpc_create(struct dc_context *ctx) { - struct dcn10_mpcc *mpcc10 = dm_alloc(sizeof(struct dcn10_mpcc)); + struct dcn10_mpc *mpc10 = dm_alloc(sizeof(struct dcn10_mpc)); - if (!mpcc10) + if (!mpc10) return NULL; - dcn10_mpcc_construct(mpcc10, ctx, - &mpcc_regs[inst], - &mpcc_shift, - &mpcc_mask, - inst); + dcn10_mpc_construct(mpc10, ctx, + &mpc_regs, + &mpc_shift, + &mpc_mask, + 4); - return &mpcc10->base; + return &mpc10->base; } static struct timing_generator *dcn10_timing_generator_create( @@ -702,6 +690,10 @@ static void destruct(struct dcn10_resource_pool *pool) } } + if (pool->base.mpc != NULL) { + dm_free(TO_DCN10_MPC(pool->base.mpc)); + pool->base.mpc = NULL; + } for (i = 0; i < pool->base.pipe_count; i++) { if (pool->base.opps[i] != NULL) pool->base.opps[i]->funcs->opp_destroy(&pool->base.opps[i]); @@ -725,11 +717,6 @@ static void destruct(struct dcn10_resource_pool *pool) dm_free(DCN10TG_FROM_TG(pool->base.timing_generators[i])); pool->base.timing_generators[i] = NULL; } - - if (pool->base.mpcc[i] != NULL) { - dm_free(TO_DCN10_MPCC(pool->base.mpcc[i])); - pool->base.mpcc[i] = NULL; - } } for (i = 0; i < pool->base.stream_enc_count; i++) { @@ -974,12 +961,11 @@ static struct pipe_ctx *dcn10_acquire_idle_pipe_for_layer( idle_pipe->stream = head_pipe->stream; idle_pipe->tg = head_pipe->tg; + idle_pipe->opp = head_pipe->opp; - idle_pipe->mpcc = pool->mpcc[idle_pipe->pipe_idx]; idle_pipe->mi = pool->mis[idle_pipe->pipe_idx]; idle_pipe->ipp = pool->ipps[idle_pipe->pipe_idx]; idle_pipe->xfm = pool->transforms[idle_pipe->pipe_idx]; - idle_pipe->opp = pool->opps[idle_pipe->pipe_idx]; return idle_pipe; } @@ -1406,12 +1392,12 @@ static bool construct( dm_error("DC: failed to create tg!\n"); goto otg_create_fail; } - pool->base.mpcc[i] = dcn10_mpcc_create(ctx, i); - if (pool->base.mpcc[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create mpcc!\n"); - goto mpcc_create_fail; - } + } + pool->base.mpc = dcn10_mpc_create(ctx); + if (pool->base.mpc == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create mpc!\n"); + goto mpc_create_fail; } if (!resource_construct(num_virtual_links, dc, &pool->base, @@ -1427,7 +1413,7 @@ static bool construct( return true; disp_clk_create_fail: -mpcc_create_fail: +mpc_create_fail: otg_create_fail: opp_create_fail: dpp_create_fail: diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 2ae5a607fb5a..b312bb3b3350 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -123,7 +123,7 @@ struct resource_pool { struct timing_generator *timing_generators[MAX_PIPES]; struct stream_encoder *stream_enc[MAX_PIPES * 2]; #ifdef CONFIG_DRM_AMD_DC_DCN1_0 - struct mpcc *mpcc[MAX_PIPES]; + struct mpc *mpc; #endif unsigned int pipe_count; @@ -183,7 +183,6 @@ struct pipe_ctx { struct pipe_ctx *bottom_pipe; #ifdef CONFIG_DRM_AMD_DC_DCN1_0 - struct mpcc *mpcc; struct _vcs_dpi_display_dlg_regs_st dlg_regs; struct _vcs_dpi_display_ttu_regs_st ttu_regs; struct _vcs_dpi_display_rq_regs_st rq_regs; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h index fd3ce742af2c..a7c89c36f90f 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h @@ -69,7 +69,9 @@ struct mem_input { struct dc_context *ctx; struct dc_plane_address request_address; struct dc_plane_address current_address; - uint32_t inst; + int inst; + int opp_id; + int mpcc_id; struct stutter_modes stutter_mode; }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h index 55c9c305a259..4bbcff48acc8 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h @@ -26,27 +26,29 @@ #define __DC_MPCC_H__ #include "dc_hw_types.h" +#include "opp.h" struct mpcc_cfg { - int top_dpp_id; - int bot_mpcc_id; - int opp_id; + struct mem_input *mi; + struct output_pixel_processor *opp; + unsigned int z_index; + + struct tg_color black_color; bool per_pixel_alpha; bool pre_multiplied_alpha; - bool top_of_tree; }; -struct mpcc { - const struct mpcc_funcs *funcs; +struct mpc { + const struct mpc_funcs *funcs; struct dc_context *ctx; - int inst; - int opp_id; }; -struct mpcc_funcs { - void (*set)(struct mpcc *mpcc, struct mpcc_cfg *cfg); - void (*wait_for_idle)(struct mpcc *mpcc); - void (*set_bg_color)( struct mpcc *mpcc, struct tg_color *bg_color); +struct mpc_funcs { + void (*add)(struct mpc *mpc, struct mpcc_cfg *cfg); + void (*remove)(struct mpc *mpc, + struct output_pixel_processor *opp, + int mpcc_inst); + void (*wait_for_idle)(struct mpc *mpc, int id); }; #endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h index a43a09b3f414..01d6957c07fb 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h @@ -196,10 +196,17 @@ struct pwl_float_data { struct fixed31_32 b; }; +struct mpc_tree_cfg { + int num_pipes; + int dpp[MAX_PIPES]; + int mpcc[MAX_PIPES]; +}; + struct output_pixel_processor { struct dc_context *ctx; uint32_t inst; struct pwl_params regamma_params; + struct mpc_tree_cfg mpc_tree; bool mpcc_disconnect_pending[MAX_PIPES]; const struct opp_funcs *funcs; }; -- cgit From cd273548e4f96508c97e5325ce0f5301aa2e3ad5 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 26 Jul 2017 17:01:06 -0400 Subject: drm/amd/display: fix mpcc idle wait Signed-off-by: Dmytro Laktyushkin Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c index 246b60a16521..036f161ab1c1 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c @@ -71,7 +71,7 @@ static void mpc10_assert_idle_mpcc(struct mpc *mpc, int id) ASSERT(!(mpc10->mpcc_in_use_mask & 1 << id)); REG_WAIT(MPCC_STATUS[id], - MPCC_BUSY, 0, + MPCC_IDLE, 1, 1000, 1000); } -- cgit From 4654a2f7fce0c2fd3dafe2c366ddf8e9e080fa44 Mon Sep 17 00:00:00 2001 From: Roman Li Date: Wed, 26 Jul 2017 16:27:37 -0400 Subject: drm/amd/display: add detect caps for edp 1. The caps detect sequence for edp is different from dp. Added separate function for edp. 2. Removed max_link_setting and replaced it with verified to avoid confusion. 3. Reverted sink count guard for edp powerdown as unnecessary with the changes above. Signed-off-by: Roman Li Signed-off-by: Tony Cheng Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 11 ++++++++--- drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 4 +--- drivers/gpu/drm/amd/display/dc/dc.h | 1 - drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h | 2 ++ 5 files changed, 12 insertions(+), 8 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 2487046457c8..a983a5ee3172 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -585,7 +585,7 @@ bool dc_link_detect(struct dc_link *link, bool boot) } case SIGNAL_TYPE_EDP: { - detect_dp_sink_caps(link); + detect_edp_sink_caps(link); sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C_OVER_AUX; sink_caps.signal = SIGNAL_TYPE_EDP; 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 d9754b5f2543..17506345f97a 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 @@ -1147,7 +1147,6 @@ bool dp_hbr_verify_link_cap( LINK_SPREAD_DISABLED; } - link->max_link_setting = link->verified_link_cap; return success; } @@ -1466,7 +1465,7 @@ void decide_link_settings(struct dc_stream *stream, * 2. could support the b/w requested by the timing */ while (current_link_setting.link_rate <= - link->max_link_setting.link_rate) { + link->verified_link_cap.link_rate) { link_bw = bandwidth_in_kbps_from_link_settings( ¤t_link_setting); if (req_bw <= link_bw) { @@ -1475,7 +1474,7 @@ void decide_link_settings(struct dc_stream *stream, } if (current_link_setting.lane_count < - link->max_link_setting.lane_count) { + link->verified_link_cap.lane_count) { current_link_setting.lane_count = increase_lane_count( current_link_setting.lane_count); @@ -2294,6 +2293,12 @@ void detect_dp_sink_caps(struct dc_link *link) /* TODO save sink caps in link->sink */ } +void detect_edp_sink_caps(struct dc_link *link) +{ + retrieve_link_cap(link); + link->verified_link_cap = link->reported_link_cap; +} + void dc_link_dp_enable_hpd(const struct dc_link *link) { struct link_encoder *encoder = link->link_enc; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 76dc16916821..f2f57a75f864 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -114,9 +114,7 @@ void dp_disable_link_phy(struct dc_link *link, enum signal_type signal) if (signal == SIGNAL_TYPE_EDP) { link->link_enc->funcs->backlight_control(link->link_enc, false); - if (link->dpcd_sink_count) - link->link_enc->funcs->power_control(link->link_enc, - false); + link->link_enc->funcs->power_control(link->link_enc, false); } link->link_enc->funcs->disable_output(link->link_enc, signal); diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index b20f7bfcdc1f..58bfb867b71c 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -744,7 +744,6 @@ struct dc_link { */ struct dc_link_settings reported_link_cap; struct dc_link_settings verified_link_cap; - struct dc_link_settings max_link_setting; struct dc_link_settings cur_link_settings; struct dc_lane_settings cur_lane_setting; struct dc_link_settings preferred_link_setting; diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h index 5b4185053e9c..1a4a605cb449 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h @@ -63,6 +63,8 @@ bool is_mst_supported(struct dc_link *link); void detect_dp_sink_caps(struct dc_link *link); +void detect_edp_sink_caps(struct dc_link *link); + bool is_dp_active_dongle(const struct dc_link *link); void dp_enable_mst_on_sink(struct dc_link *link, bool enable); -- cgit From 1c3fb02d2567ae348a3495c93bea991e9d028780 Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Wed, 26 Jul 2017 18:31:25 -0400 Subject: drm/amd/display: update clocks we report to PPlib Signed-off-by: Eric Yang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 39 ++++++++++++------------ 1 file changed, 20 insertions(+), 19 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 49b75765d900..875b98dae6e1 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -1267,13 +1267,14 @@ void dcn_bw_notify_pplib_of_wm_ranges(struct core_dc *dc) { struct dm_pp_wm_sets_with_clock_ranges_soc15 clk_ranges = {0}; int max_fclk_khz, nom_fclk_khz, min_fclk_khz, max_dcfclk_khz, - nom_dcfclk_khz, min_dcfclk_khz, socclk_khz; + nom_dcfclk_khz, mid_fclk_khz, min_dcfclk_khz, socclk_khz; const int overdrive = 5000000; /* 5 GHz to cover Overdrive */ unsigned factor = (ddr4_dram_factor_single_Channel * dc->dcn_soc.number_of_channels); kernel_fpu_begin(); max_fclk_khz = dc->dcn_soc.fabric_and_dram_bandwidth_vmax0p9 * 1000000 / factor; nom_fclk_khz = dc->dcn_soc.fabric_and_dram_bandwidth_vnom0p8 * 1000000 / factor; + mid_fclk_khz = dc->dcn_soc.fabric_and_dram_bandwidth_vmid0p72 * 1000000 / factor; min_fclk_khz = dc->dcn_soc.fabric_and_dram_bandwidth_vmin0p65 * 1000000 / 32; max_dcfclk_khz = dc->dcn_soc.dcfclkv_max0p9 * 1000; nom_dcfclk_khz = dc->dcn_soc.dcfclkv_nom0p8 * 1000; @@ -1293,48 +1294,48 @@ void dcn_bw_notify_pplib_of_wm_ranges(struct core_dc *dc) clk_ranges.num_wm_mcif_sets = 4; clk_ranges.wm_dmif_clocks_ranges[0].wm_set_id = WM_SET_A; clk_ranges.wm_dmif_clocks_ranges[0].wm_min_dcfclk_clk_in_khz = min_dcfclk_khz; - clk_ranges.wm_dmif_clocks_ranges[0].wm_max_dcfclk_clk_in_khz = nom_dcfclk_khz - 1; + clk_ranges.wm_dmif_clocks_ranges[0].wm_max_dcfclk_clk_in_khz = max_dcfclk_khz; clk_ranges.wm_dmif_clocks_ranges[0].wm_min_memg_clk_in_khz = min_fclk_khz; - clk_ranges.wm_dmif_clocks_ranges[0].wm_max_mem_clk_in_khz = nom_fclk_khz - 1; + clk_ranges.wm_dmif_clocks_ranges[0].wm_max_mem_clk_in_khz = min_fclk_khz; clk_ranges.wm_mcif_clocks_ranges[0].wm_set_id = WM_SET_A; clk_ranges.wm_mcif_clocks_ranges[0].wm_min_socclk_clk_in_khz = socclk_khz; clk_ranges.wm_mcif_clocks_ranges[0].wm_max_socclk_clk_in_khz = overdrive; clk_ranges.wm_mcif_clocks_ranges[0].wm_min_memg_clk_in_khz = min_fclk_khz; - clk_ranges.wm_mcif_clocks_ranges[0].wm_max_mem_clk_in_khz = nom_fclk_khz - 1; + clk_ranges.wm_mcif_clocks_ranges[0].wm_max_mem_clk_in_khz = min_fclk_khz; clk_ranges.wm_dmif_clocks_ranges[1].wm_set_id = WM_SET_B; - clk_ranges.wm_dmif_clocks_ranges[1].wm_min_dcfclk_clk_in_khz = min_dcfclk_khz; - clk_ranges.wm_dmif_clocks_ranges[1].wm_max_dcfclk_clk_in_khz = nom_dcfclk_khz - 1; - clk_ranges.wm_dmif_clocks_ranges[1].wm_min_memg_clk_in_khz = nom_fclk_khz; - clk_ranges.wm_dmif_clocks_ranges[1].wm_max_mem_clk_in_khz = max_fclk_khz; + clk_ranges.wm_dmif_clocks_ranges[1].wm_min_dcfclk_clk_in_khz = min_fclk_khz; + clk_ranges.wm_dmif_clocks_ranges[1].wm_max_dcfclk_clk_in_khz = max_dcfclk_khz; + clk_ranges.wm_dmif_clocks_ranges[1].wm_min_memg_clk_in_khz = mid_fclk_khz; + clk_ranges.wm_dmif_clocks_ranges[1].wm_max_mem_clk_in_khz = mid_fclk_khz; clk_ranges.wm_mcif_clocks_ranges[1].wm_set_id = WM_SET_B; clk_ranges.wm_mcif_clocks_ranges[1].wm_min_socclk_clk_in_khz = socclk_khz; clk_ranges.wm_mcif_clocks_ranges[1].wm_max_socclk_clk_in_khz = overdrive; - clk_ranges.wm_mcif_clocks_ranges[1].wm_min_memg_clk_in_khz = nom_fclk_khz; - clk_ranges.wm_mcif_clocks_ranges[1].wm_max_mem_clk_in_khz = max_fclk_khz; + clk_ranges.wm_mcif_clocks_ranges[1].wm_min_memg_clk_in_khz = mid_fclk_khz; + clk_ranges.wm_mcif_clocks_ranges[1].wm_max_mem_clk_in_khz = mid_fclk_khz; clk_ranges.wm_dmif_clocks_ranges[2].wm_set_id = WM_SET_C; - clk_ranges.wm_dmif_clocks_ranges[2].wm_min_dcfclk_clk_in_khz = nom_dcfclk_khz; + clk_ranges.wm_dmif_clocks_ranges[2].wm_min_dcfclk_clk_in_khz = min_fclk_khz; clk_ranges.wm_dmif_clocks_ranges[2].wm_max_dcfclk_clk_in_khz = max_dcfclk_khz; clk_ranges.wm_dmif_clocks_ranges[2].wm_min_memg_clk_in_khz = nom_fclk_khz; - clk_ranges.wm_dmif_clocks_ranges[2].wm_max_mem_clk_in_khz = max_fclk_khz; + clk_ranges.wm_dmif_clocks_ranges[2].wm_max_mem_clk_in_khz = nom_fclk_khz; clk_ranges.wm_mcif_clocks_ranges[2].wm_set_id = WM_SET_C; clk_ranges.wm_mcif_clocks_ranges[2].wm_min_socclk_clk_in_khz = socclk_khz; clk_ranges.wm_mcif_clocks_ranges[2].wm_max_socclk_clk_in_khz = overdrive; clk_ranges.wm_mcif_clocks_ranges[2].wm_min_memg_clk_in_khz = nom_fclk_khz; - clk_ranges.wm_mcif_clocks_ranges[2].wm_max_mem_clk_in_khz = max_fclk_khz; + clk_ranges.wm_mcif_clocks_ranges[2].wm_max_mem_clk_in_khz = nom_fclk_khz; clk_ranges.wm_dmif_clocks_ranges[3].wm_set_id = WM_SET_D; - clk_ranges.wm_dmif_clocks_ranges[3].wm_min_dcfclk_clk_in_khz = max_dcfclk_khz + 1; - clk_ranges.wm_dmif_clocks_ranges[3].wm_max_dcfclk_clk_in_khz = overdrive; - clk_ranges.wm_dmif_clocks_ranges[3].wm_min_memg_clk_in_khz = max_fclk_khz + 1; - clk_ranges.wm_dmif_clocks_ranges[3].wm_max_mem_clk_in_khz = overdrive; + clk_ranges.wm_dmif_clocks_ranges[3].wm_min_dcfclk_clk_in_khz = min_fclk_khz; + clk_ranges.wm_dmif_clocks_ranges[3].wm_max_dcfclk_clk_in_khz = max_dcfclk_khz; + clk_ranges.wm_dmif_clocks_ranges[3].wm_min_memg_clk_in_khz = max_fclk_khz; + clk_ranges.wm_dmif_clocks_ranges[3].wm_max_mem_clk_in_khz = max_fclk_khz; clk_ranges.wm_mcif_clocks_ranges[3].wm_set_id = WM_SET_D; clk_ranges.wm_mcif_clocks_ranges[3].wm_min_socclk_clk_in_khz = socclk_khz; clk_ranges.wm_mcif_clocks_ranges[3].wm_max_socclk_clk_in_khz = overdrive; - clk_ranges.wm_mcif_clocks_ranges[3].wm_min_memg_clk_in_khz = max_fclk_khz + 1; - clk_ranges.wm_mcif_clocks_ranges[3].wm_max_mem_clk_in_khz = overdrive; + clk_ranges.wm_mcif_clocks_ranges[3].wm_min_memg_clk_in_khz = max_fclk_khz; + clk_ranges.wm_mcif_clocks_ranges[3].wm_max_mem_clk_in_khz = max_fclk_khz; /* Notify PP Lib/SMU which Watermarks to use for which clock ranges */ dm_pp_notify_wm_clock_changes_soc15(dc->ctx, &clk_ranges); -- cgit From 1515a47b44c8667987d070fdc494691f91b44b46 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Wed, 26 Jul 2017 19:31:53 -0400 Subject: drm/amd/display: Rename firmware_info to dc_firmware_info This is to avoid conflicts with amdgpu's firmware_info once we merge amdgpu_dm_types with amdgpu_dm. Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/bios/bios_parser.c | 14 +++++++------- drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c | 8 ++++---- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/dc_bios_types.h | 2 +- drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c | 4 ++-- drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c | 2 +- drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c | 2 +- .../gpu/drm/amd/display/include/grph_object_ctrl_defs.h | 2 +- 11 files changed, 21 insertions(+), 21 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c index 47a467688073..2c683d468bb8 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c @@ -622,17 +622,17 @@ static enum bp_result bios_parser_get_device_tag( static enum bp_result get_firmware_info_v1_4( struct bios_parser *bp, - struct firmware_info *info); + struct dc_firmware_info *info); static enum bp_result get_firmware_info_v2_1( struct bios_parser *bp, - struct firmware_info *info); + struct dc_firmware_info *info); static enum bp_result get_firmware_info_v2_2( struct bios_parser *bp, - struct firmware_info *info); + struct dc_firmware_info *info); static enum bp_result bios_parser_get_firmware_info( struct dc_bios *dcb, - struct firmware_info *info) + struct dc_firmware_info *info) { struct bios_parser *bp = BP_FROM_DCB(dcb); enum bp_result result = BP_RESULT_BADBIOSTABLE; @@ -676,7 +676,7 @@ static enum bp_result bios_parser_get_firmware_info( static enum bp_result get_firmware_info_v1_4( struct bios_parser *bp, - struct firmware_info *info) + struct dc_firmware_info *info) { ATOM_FIRMWARE_INFO_V1_4 *firmware_info = GET_IMAGE(ATOM_FIRMWARE_INFO_V1_4, @@ -726,7 +726,7 @@ static enum bp_result get_ss_info_v3_1( static enum bp_result get_firmware_info_v2_1( struct bios_parser *bp, - struct firmware_info *info) + struct dc_firmware_info *info) { ATOM_FIRMWARE_INFO_V2_1 *firmwareInfo = GET_IMAGE(ATOM_FIRMWARE_INFO_V2_1, DATA_TABLES(FirmwareInfo)); @@ -810,7 +810,7 @@ static enum bp_result get_firmware_info_v2_1( static enum bp_result get_firmware_info_v2_2( struct bios_parser *bp, - struct firmware_info *info) + struct dc_firmware_info *info) { ATOM_FIRMWARE_INFO_V2_2 *firmware_info; struct spread_spectrum_info internal_ss; diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c index 3a69f9c5d20a..86fce5ae5856 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -81,7 +81,7 @@ static enum bp_result get_gpio_i2c_info(struct bios_parser *bp, static enum bp_result bios_parser_get_firmware_info( struct dc_bios *dcb, - struct firmware_info *info); + struct dc_firmware_info *info); static enum bp_result bios_parser_get_encoder_cap_info( struct dc_bios *dcb, @@ -90,7 +90,7 @@ static enum bp_result bios_parser_get_encoder_cap_info( static enum bp_result get_firmware_info_v3_1( struct bios_parser *bp, - struct firmware_info *info); + struct dc_firmware_info *info); static struct atom_hpd_int_record *get_hpd_record(struct bios_parser *bp, struct atom_display_object_path_v2 *object); @@ -1583,7 +1583,7 @@ static void bios_parser_set_scratch_critical_state( static enum bp_result bios_parser_get_firmware_info( struct dc_bios *dcb, - struct firmware_info *info) + struct dc_firmware_info *info) { struct bios_parser *bp = BP_FROM_DCB(dcb); enum bp_result result = BP_RESULT_BADBIOSTABLE; @@ -1615,7 +1615,7 @@ static enum bp_result bios_parser_get_firmware_info( static enum bp_result get_firmware_info_v3_1( struct bios_parser *bp, - struct firmware_info *info) + struct dc_firmware_info *info) { struct atom_firmware_info_v3_1 *firmware_info; struct atom_display_controller_info_v4_1 *dce_info = NULL; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 4068d53137f5..d381e380e974 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -126,7 +126,7 @@ struct resource_pool *dc_create_resource_pool( break; } if (res_pool != NULL) { - struct firmware_info fw_info = { { 0 } }; + struct dc_firmware_info fw_info = { { 0 } }; if (dc->ctx->dc_bios->funcs->get_firmware_info( dc->ctx->dc_bios, &fw_info) == BP_RESULT_OK) { diff --git a/drivers/gpu/drm/amd/display/dc/dc_bios_types.h b/drivers/gpu/drm/amd/display/dc/dc_bios_types.h index 6e1291d5f51d..273d80a4ebce 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_bios_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_bios_types.h @@ -84,7 +84,7 @@ struct dc_vbios_funcs { struct connector_device_tag_info *info); enum bp_result (*get_firmware_info)( struct dc_bios *bios, - struct firmware_info *info); + struct dc_firmware_info *info); enum bp_result (*get_spread_spectrum_info)( struct dc_bios *bios, enum as_signal_type signal, diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index 2205491c83e9..dd7e1dd62636 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -1103,7 +1103,7 @@ static bool calc_pll_max_vco_construct( struct calc_pll_clock_source_init_data *init_data) { uint32_t i; - struct firmware_info fw_info = { { 0 } }; + struct dc_firmware_info fw_info = { { 0 } }; if (calc_pll_cs == NULL || init_data == NULL || init_data->bp == NULL) @@ -1185,7 +1185,7 @@ bool dce110_clk_src_construct( const struct dce110_clk_src_shift *cs_shift, const struct dce110_clk_src_mask *cs_mask) { - struct firmware_info fw_info = { { 0 } }; + struct dc_firmware_info fw_info = { { 0 } }; struct calc_pll_clock_source_init_data calc_pll_cs_init_data_hdmi; struct calc_pll_clock_source_init_data calc_pll_cs_init_data; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c index 37d074f595fb..a73228b97da5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c @@ -424,7 +424,7 @@ static void dce_clock_read_integrated_info(struct dce_disp_clk *clk_dce) struct dc_debug *debug = &clk_dce->base.ctx->dc->debug; struct dc_bios *bp = clk_dce->base.ctx->dc_bios; struct integrated_info info = { { { 0 } } }; - struct firmware_info fw_info = { { 0 } }; + struct dc_firmware_info fw_info = { { 0 } }; int i; if (bp->integrated_info) diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index cf98f2471023..9ac246f05110 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -819,7 +819,7 @@ static bool construct( { unsigned int i; struct dc_context *ctx = dc->ctx; - struct firmware_info info; + struct dc_firmware_info info; struct dc_bios *bp; struct dm_pp_static_clock_info static_clk_info = {0}; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index cc25c4b6c06f..5c1790b61290 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -1190,7 +1190,7 @@ static bool construct( { unsigned int i; struct dc_context *ctx = dc->ctx; - struct firmware_info info; + struct dc_firmware_info info; struct dc_bios *bp; struct dm_pp_static_clock_info static_clk_info = {0}; diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 2fde43c91ad0..92f01ed97621 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -833,7 +833,7 @@ static bool construct( { unsigned int i; struct dc_context *ctx = dc->ctx; - struct firmware_info info; + struct dc_firmware_info info; struct dc_bios *bp; struct dm_pp_static_clock_info static_clk_info = {0}; diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c index 10061cc4ba31..da08cc1c6dc3 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c @@ -320,7 +320,7 @@ void dal_i2caux_destroy( uint32_t dal_i2caux_get_reference_clock( struct dc_bios *bios) { - struct firmware_info info = { { 0 } }; + struct dc_firmware_info info = { { 0 } }; if (bios->funcs->get_firmware_info(bios, &info) != BP_RESULT_OK) return 0; diff --git a/drivers/gpu/drm/amd/display/include/grph_object_ctrl_defs.h b/drivers/gpu/drm/amd/display/include/grph_object_ctrl_defs.h index 9c0bf6521dd9..6cdbf84f34e6 100644 --- a/drivers/gpu/drm/amd/display/include/grph_object_ctrl_defs.h +++ b/drivers/gpu/drm/amd/display/include/grph_object_ctrl_defs.h @@ -154,7 +154,7 @@ struct embedded_panel_info { bool realtek_eDPToLVDS; }; -struct firmware_info { +struct dc_firmware_info { struct pll_info { uint32_t crystal_frequency; /* in KHz */ uint32_t min_input_pxl_clk_pll_frequency; /* in KHz */ -- cgit From e7b07ceef2a650e5ed8ca37997689e086c680daf Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 10 Aug 2017 13:29:07 -0400 Subject: drm/amd/display: Merge amdgpu_dm_types and amdgpu_dm This separation stopped making sense a long time ago. Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/Makefile | 2 +- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3245 ++++++++++++++++++- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 108 +- .../drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 1 - .../amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 2 +- .../drm/amd/display/amdgpu_dm/amdgpu_dm_services.c | 1 - .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 3286 -------------------- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.h | 135 - 8 files changed, 3350 insertions(+), 3430 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c delete mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile b/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile index 698b1d4f83f5..4699e47aa76b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile @@ -4,7 +4,7 @@ -AMDGPUDM = amdgpu_dm_types.o amdgpu_dm.o amdgpu_dm_irq.o amdgpu_dm_mst_types.o +AMDGPUDM = amdgpu_dm.o amdgpu_dm_irq.o amdgpu_dm_mst_types.o ifneq ($(CONFIG_DRM_AMD_DC),) AMDGPUDM += amdgpu_dm_services.o amdgpu_dm_helpers.o 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 c802437f4858..646a946a2571 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -31,21 +31,27 @@ #include "amdgpu_display.h" #include "atom.h" #include "amdgpu_dm.h" -#include "amdgpu_dm_types.h" +#include "amdgpu_pm.h" #include "amd_shared.h" #include "amdgpu_dm_irq.h" #include "dm_helpers.h" +#include "dm_services_types.h" +#include "amdgpu_dm_mst_types.h" #include "ivsrcid/ivsrcid_vislands30.h" #include #include #include +#include +#include #include #include #include +#include +#include #include "modules/inc/mod_freesync.h" @@ -59,6 +65,11 @@ #include "soc15_common.h" #endif +#include "modules/inc/mod_freesync.h" + +#include "i2caux_interface.h" + + static enum drm_plane_type dm_surfaces_type_default[AMDGPU_MAX_PLANES] = { DRM_PLANE_TYPE_PRIMARY, DRM_PLANE_TYPE_PRIMARY, @@ -1552,8 +1563,3238 @@ bool amdgpu_dm_acquire_dal_lock(struct amdgpu_display_manager *dm) bool amdgpu_dm_release_dal_lock(struct amdgpu_display_manager *dm) { - /* TODO */ + /* TODO */ return true; +} + + +struct dm_connector_state { + struct drm_connector_state base; + + enum amdgpu_rmx_type scaling; + uint8_t underscan_vborder; + uint8_t underscan_hborder; + bool underscan_enable; +}; + +#define to_dm_connector_state(x)\ + container_of((x), struct dm_connector_state, base) + +static bool modeset_required(struct drm_crtc_state *crtc_state) +{ + if (!drm_atomic_crtc_needs_modeset(crtc_state)) + return false; + + if (!crtc_state->enable) + return false; + + return crtc_state->active; +} + +static bool modereset_required(struct drm_crtc_state *crtc_state) +{ + if (!drm_atomic_crtc_needs_modeset(crtc_state)) + return false; + + return !crtc_state->enable || !crtc_state->active; +} + +void amdgpu_dm_encoder_destroy(struct drm_encoder *encoder) +{ + drm_encoder_cleanup(encoder); + kfree(encoder); +} + +static const struct drm_encoder_funcs amdgpu_dm_encoder_funcs = { + .destroy = amdgpu_dm_encoder_destroy, +}; + +static void dm_set_cursor( + struct amdgpu_crtc *amdgpu_crtc, + uint64_t gpu_addr, + uint32_t width, + uint32_t height) +{ + struct dc_cursor_attributes attributes; + struct dc_cursor_position position; + struct drm_crtc *crtc = &amdgpu_crtc->base; + int x, y; + int xorigin = 0, yorigin = 0; + struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state); + + amdgpu_crtc->cursor_width = width; + amdgpu_crtc->cursor_height = height; + + attributes.address.high_part = upper_32_bits(gpu_addr); + attributes.address.low_part = lower_32_bits(gpu_addr); + attributes.width = width; + attributes.height = height; + attributes.color_format = CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA; + attributes.rotation_angle = 0; + attributes.attribute_flags.value = 0; + + attributes.pitch = attributes.width; + + x = amdgpu_crtc->cursor_x; + y = amdgpu_crtc->cursor_y; + + /* avivo cursor are offset into the total surface */ + x += crtc->primary->state->src_x >> 16; + y += crtc->primary->state->src_y >> 16; + + if (x < 0) { + xorigin = min(-x, amdgpu_crtc->max_cursor_width - 1); + x = 0; + } + if (y < 0) { + yorigin = min(-y, amdgpu_crtc->max_cursor_height - 1); + y = 0; + } + + position.enable = true; + position.x = x; + position.y = y; + + position.x_hotspot = xorigin; + position.y_hotspot = yorigin; + + if (!dc_stream_set_cursor_attributes( + acrtc_state->stream, + &attributes)) { + DRM_ERROR("DC failed to set cursor attributes\n"); + } + + if (!dc_stream_set_cursor_position( + acrtc_state->stream, + &position)) { + DRM_ERROR("DC failed to set cursor position\n"); + } +} + +static int dm_crtc_cursor_set( + struct drm_crtc *crtc, + uint64_t address, + uint32_t width, + uint32_t height) +{ + struct dc_cursor_position position; + struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state); + + int ret; + + struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); + ret = EINVAL; + + DRM_DEBUG_KMS( + "%s: crtc_id=%d with size %d to %d \n", + __func__, + amdgpu_crtc->crtc_id, + width, + height); + + if (!address) { + /* turn off cursor */ + position.enable = false; + position.x = 0; + position.y = 0; + + if (acrtc_state->stream) { + /*set cursor visible false*/ + dc_stream_set_cursor_position( + acrtc_state->stream, + &position); + } + goto release; + + } + + if ((width > amdgpu_crtc->max_cursor_width) || + (height > amdgpu_crtc->max_cursor_height)) { + DRM_ERROR( + "%s: bad cursor width or height %d x %d\n", + __func__, + width, + height); + goto release; + } + + /*program new cursor bo to hardware*/ + dm_set_cursor(amdgpu_crtc, address, width, height); + +release: + return ret; + +} + +static int dm_crtc_cursor_move(struct drm_crtc *crtc, + int x, int y) +{ + struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); + int xorigin = 0, yorigin = 0; + struct dc_cursor_position position; + struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state); + + amdgpu_crtc->cursor_x = x; + amdgpu_crtc->cursor_y = y; + + /* avivo cursor are offset into the total surface */ + x += crtc->primary->state->src_x >> 16; + y += crtc->primary->state->src_y >> 16; + + /* + * TODO: for cursor debugging unguard the following + */ +#if 0 + DRM_DEBUG_KMS( + "%s: x %d y %d c->x %d c->y %d\n", + __func__, + x, + y, + crtc->x, + crtc->y); +#endif + + if (x < 0) { + xorigin = min(-x, amdgpu_crtc->max_cursor_width - 1); + x = 0; + } + if (y < 0) { + yorigin = min(-y, amdgpu_crtc->max_cursor_height - 1); + y = 0; + } + + position.enable = true; + position.x = x; + position.y = y; + + position.x_hotspot = xorigin; + position.y_hotspot = yorigin; + + if (acrtc_state->stream) { + if (!dc_stream_set_cursor_position( + acrtc_state->stream, + &position)) { + DRM_ERROR("DC failed to set cursor position\n"); + return -EINVAL; + } + } + + return 0; +} + +static bool fill_rects_from_plane_state( + const struct drm_plane_state *state, + struct dc_surface *surface) +{ + surface->src_rect.x = state->src_x >> 16; + surface->src_rect.y = state->src_y >> 16; + /*we ignore for now mantissa and do not to deal with floating pixels :(*/ + surface->src_rect.width = state->src_w >> 16; + + if (surface->src_rect.width == 0) + return false; + + surface->src_rect.height = state->src_h >> 16; + if (surface->src_rect.height == 0) + return false; + + surface->dst_rect.x = state->crtc_x; + surface->dst_rect.y = state->crtc_y; + + if (state->crtc_w == 0) + return false; + + surface->dst_rect.width = state->crtc_w; + + if (state->crtc_h == 0) + return false; + + surface->dst_rect.height = state->crtc_h; + + surface->clip_rect = surface->dst_rect; + + switch (state->rotation & DRM_MODE_ROTATE_MASK) { + case DRM_MODE_ROTATE_0: + surface->rotation = ROTATION_ANGLE_0; + break; + case DRM_MODE_ROTATE_90: + surface->rotation = ROTATION_ANGLE_90; + break; + case DRM_MODE_ROTATE_180: + surface->rotation = ROTATION_ANGLE_180; + break; + case DRM_MODE_ROTATE_270: + surface->rotation = ROTATION_ANGLE_270; + break; + default: + surface->rotation = ROTATION_ANGLE_0; + break; + } + return true; } +static int get_fb_info( + const struct amdgpu_framebuffer *amdgpu_fb, + uint64_t *tiling_flags, + uint64_t *fb_location) +{ + struct amdgpu_bo *rbo = gem_to_amdgpu_bo(amdgpu_fb->obj); + int r = amdgpu_bo_reserve(rbo, false); + if (unlikely(r)) { + DRM_ERROR("Unable to reserve buffer\n"); + return r; + } + + if (fb_location) + *fb_location = amdgpu_bo_gpu_offset(rbo); + + if (tiling_flags) + amdgpu_bo_get_tiling_flags(rbo, tiling_flags); + + amdgpu_bo_unreserve(rbo); + + return r; +} + +static int fill_plane_attributes_from_fb( + struct amdgpu_device *adev, + struct dc_surface *surface, + const struct amdgpu_framebuffer *amdgpu_fb, bool addReq) +{ + uint64_t tiling_flags; + uint64_t fb_location = 0; + unsigned int awidth; + const struct drm_framebuffer *fb = &amdgpu_fb->base; + int ret = 0; + struct drm_format_name_buf format_name; + + ret = get_fb_info( + amdgpu_fb, + &tiling_flags, + addReq == true ? &fb_location:NULL); + + if (ret) + return ret; + + switch (fb->format->format) { + case DRM_FORMAT_C8: + surface->format = SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS; + break; + case DRM_FORMAT_RGB565: + surface->format = SURFACE_PIXEL_FORMAT_GRPH_RGB565; + break; + case DRM_FORMAT_XRGB8888: + case DRM_FORMAT_ARGB8888: + surface->format = SURFACE_PIXEL_FORMAT_GRPH_ARGB8888; + break; + case DRM_FORMAT_XRGB2101010: + case DRM_FORMAT_ARGB2101010: + surface->format = SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010; + break; + case DRM_FORMAT_XBGR2101010: + case DRM_FORMAT_ABGR2101010: + surface->format = SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010; + break; + case DRM_FORMAT_NV21: + surface->format = SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr; + break; + case DRM_FORMAT_NV12: + surface->format = SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb; + break; + default: + DRM_ERROR("Unsupported screen format %s\n", + drm_get_format_name(fb->format->format, &format_name)); + return -EINVAL; + } + + if (surface->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) { + surface->address.type = PLN_ADDR_TYPE_GRAPHICS; + surface->address.grph.addr.low_part = lower_32_bits(fb_location); + surface->address.grph.addr.high_part = upper_32_bits(fb_location); + surface->plane_size.grph.surface_size.x = 0; + surface->plane_size.grph.surface_size.y = 0; + surface->plane_size.grph.surface_size.width = fb->width; + surface->plane_size.grph.surface_size.height = fb->height; + surface->plane_size.grph.surface_pitch = + fb->pitches[0] / fb->format->cpp[0]; + /* TODO: unhardcode */ + surface->color_space = COLOR_SPACE_SRGB; + + } else { + awidth = ALIGN(fb->width, 64); + surface->address.type = PLN_ADDR_TYPE_VIDEO_PROGRESSIVE; + surface->address.video_progressive.luma_addr.low_part + = lower_32_bits(fb_location); + surface->address.video_progressive.chroma_addr.low_part + = lower_32_bits(fb_location) + + (awidth * fb->height); + surface->plane_size.video.luma_size.x = 0; + surface->plane_size.video.luma_size.y = 0; + surface->plane_size.video.luma_size.width = awidth; + surface->plane_size.video.luma_size.height = fb->height; + /* TODO: unhardcode */ + surface->plane_size.video.luma_pitch = awidth; + + surface->plane_size.video.chroma_size.x = 0; + surface->plane_size.video.chroma_size.y = 0; + surface->plane_size.video.chroma_size.width = awidth; + surface->plane_size.video.chroma_size.height = fb->height; + surface->plane_size.video.chroma_pitch = awidth / 2; + + /* TODO: unhardcode */ + surface->color_space = COLOR_SPACE_YCBCR709; + } + + memset(&surface->tiling_info, 0, sizeof(surface->tiling_info)); + + /* Fill GFX params */ + if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE) == DC_ARRAY_2D_TILED_THIN1) + { + unsigned bankw, bankh, mtaspect, tile_split, num_banks; + + bankw = AMDGPU_TILING_GET(tiling_flags, BANK_WIDTH); + bankh = AMDGPU_TILING_GET(tiling_flags, BANK_HEIGHT); + mtaspect = AMDGPU_TILING_GET(tiling_flags, MACRO_TILE_ASPECT); + tile_split = AMDGPU_TILING_GET(tiling_flags, TILE_SPLIT); + num_banks = AMDGPU_TILING_GET(tiling_flags, NUM_BANKS); + + /* XXX fix me for VI */ + surface->tiling_info.gfx8.num_banks = num_banks; + surface->tiling_info.gfx8.array_mode = + DC_ARRAY_2D_TILED_THIN1; + surface->tiling_info.gfx8.tile_split = tile_split; + surface->tiling_info.gfx8.bank_width = bankw; + surface->tiling_info.gfx8.bank_height = bankh; + surface->tiling_info.gfx8.tile_aspect = mtaspect; + surface->tiling_info.gfx8.tile_mode = + DC_ADDR_SURF_MICRO_TILING_DISPLAY; + } else if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE) + == DC_ARRAY_1D_TILED_THIN1) { + surface->tiling_info.gfx8.array_mode = DC_ARRAY_1D_TILED_THIN1; + } + + surface->tiling_info.gfx8.pipe_config = + AMDGPU_TILING_GET(tiling_flags, PIPE_CONFIG); + + if (adev->asic_type == CHIP_VEGA10 || + adev->asic_type == CHIP_RAVEN) { + /* Fill GFX9 params */ + surface->tiling_info.gfx9.num_pipes = + adev->gfx.config.gb_addr_config_fields.num_pipes; + surface->tiling_info.gfx9.num_banks = + adev->gfx.config.gb_addr_config_fields.num_banks; + surface->tiling_info.gfx9.pipe_interleave = + adev->gfx.config.gb_addr_config_fields.pipe_interleave_size; + surface->tiling_info.gfx9.num_shader_engines = + adev->gfx.config.gb_addr_config_fields.num_se; + surface->tiling_info.gfx9.max_compressed_frags = + adev->gfx.config.gb_addr_config_fields.max_compress_frags; + surface->tiling_info.gfx9.num_rb_per_se = + adev->gfx.config.gb_addr_config_fields.num_rb_per_se; + surface->tiling_info.gfx9.swizzle = + AMDGPU_TILING_GET(tiling_flags, SWIZZLE_MODE); + surface->tiling_info.gfx9.shaderEnable = 1; + } + + surface->visible = true; + surface->scaling_quality.h_taps_c = 0; + surface->scaling_quality.v_taps_c = 0; + + /* is this needed? is surface zeroed at allocation? */ + surface->scaling_quality.h_taps = 0; + surface->scaling_quality.v_taps = 0; + surface->stereo_format = PLANE_STEREO_FORMAT_NONE; + + return ret; + +} + +#define NUM_OF_RAW_GAMMA_RAMP_RGB_256 256 + +static void fill_gamma_from_crtc_state( + const struct drm_crtc_state *crtc_state, + struct dc_surface *dc_surface) +{ + int i; + struct dc_gamma *gamma; + struct drm_color_lut *lut = (struct drm_color_lut *) crtc_state->gamma_lut->data; + + gamma = dc_create_gamma(); + + if (gamma == NULL) { + WARN_ON(1); + return; + } + + for (i = 0; i < NUM_OF_RAW_GAMMA_RAMP_RGB_256; i++) { + gamma->red[i] = lut[i].red; + gamma->green[i] = lut[i].green; + gamma->blue[i] = lut[i].blue; + } + + dc_surface->gamma_correction = gamma; +} + +static int fill_plane_attributes( + struct amdgpu_device *adev, + struct dc_surface *surface, + struct drm_plane_state *plane_state, + struct drm_crtc_state *crtc_state, + bool addrReq) +{ + const struct amdgpu_framebuffer *amdgpu_fb = + to_amdgpu_framebuffer(plane_state->fb); + const struct drm_crtc *crtc = plane_state->crtc; + struct dc_transfer_func *input_tf; + int ret = 0; + + if (!fill_rects_from_plane_state(plane_state, surface)) + return -EINVAL; + + ret = fill_plane_attributes_from_fb( + crtc->dev->dev_private, + surface, + amdgpu_fb, + addrReq); + + if (ret) + return ret; + + input_tf = dc_create_transfer_func(); + + if (input_tf == NULL) + return -ENOMEM; + + input_tf->type = TF_TYPE_PREDEFINED; + input_tf->tf = TRANSFER_FUNCTION_SRGB; + + surface->in_transfer_func = input_tf; + + /* In case of gamma set, update gamma value */ + if (crtc_state->gamma_lut) + fill_gamma_from_crtc_state(crtc_state, surface); + + return ret; +} + +/*****************************************************************************/ + +struct amdgpu_connector *aconnector_from_drm_crtc_id( + const struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct drm_connector *connector; + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + struct amdgpu_connector *aconnector; + + list_for_each_entry(connector, + &dev->mode_config.connector_list, head) { + + aconnector = to_amdgpu_connector(connector); + + if (aconnector->base.state->crtc != &acrtc->base) + continue; + + /* Found the connector */ + return aconnector; + } + + /* If we get here, not found. */ + return NULL; +} + +static void update_stream_scaling_settings( + const struct drm_display_mode *mode, + const struct dm_connector_state *dm_state, + struct dc_stream *stream) +{ + enum amdgpu_rmx_type rmx_type; + + struct rect src = { 0 }; /* viewport in composition space*/ + struct rect dst = { 0 }; /* stream addressable area */ + + /* no mode. nothing to be done */ + if (!mode) + return; + + /* Full screen scaling by default */ + src.width = mode->hdisplay; + src.height = mode->vdisplay; + dst.width = stream->timing.h_addressable; + dst.height = stream->timing.v_addressable; + + rmx_type = dm_state->scaling; + if (rmx_type == RMX_ASPECT || rmx_type == RMX_OFF) { + if (src.width * dst.height < + src.height * dst.width) { + /* height needs less upscaling/more downscaling */ + dst.width = src.width * + dst.height / src.height; + } else { + /* width needs less upscaling/more downscaling */ + dst.height = src.height * + dst.width / src.width; + } + } else if (rmx_type == RMX_CENTER) { + dst = src; + } + + dst.x = (stream->timing.h_addressable - dst.width) / 2; + dst.y = (stream->timing.v_addressable - dst.height) / 2; + + if (dm_state->underscan_enable) { + dst.x += dm_state->underscan_hborder / 2; + dst.y += dm_state->underscan_vborder / 2; + dst.width -= dm_state->underscan_hborder; + dst.height -= dm_state->underscan_vborder; + } + + stream->src = src; + stream->dst = dst; + + DRM_DEBUG_KMS("Destination Rectangle x:%d y:%d width:%d height:%d\n", + dst.x, dst.y, dst.width, dst.height); + +} + +static enum dc_color_depth convert_color_depth_from_display_info( + const struct drm_connector *connector) +{ + uint32_t bpc = connector->display_info.bpc; + + /* Limited color depth to 8bit + * TODO: Still need to handle deep color*/ + if (bpc > 8) + bpc = 8; + + switch (bpc) { + case 0: + /* Temporary Work around, DRM don't parse color depth for + * EDID revision before 1.4 + * TODO: Fix edid parsing + */ + return COLOR_DEPTH_888; + case 6: + return COLOR_DEPTH_666; + case 8: + return COLOR_DEPTH_888; + case 10: + return COLOR_DEPTH_101010; + case 12: + return COLOR_DEPTH_121212; + case 14: + return COLOR_DEPTH_141414; + case 16: + return COLOR_DEPTH_161616; + default: + return COLOR_DEPTH_UNDEFINED; + } +} + +static enum dc_aspect_ratio get_aspect_ratio( + const struct drm_display_mode *mode_in) +{ + int32_t width = mode_in->crtc_hdisplay * 9; + int32_t height = mode_in->crtc_vdisplay * 16; + if ((width - height) < 10 && (width - height) > -10) + return ASPECT_RATIO_16_9; + else + return ASPECT_RATIO_4_3; +} + +static enum dc_color_space get_output_color_space( + const struct dc_crtc_timing *dc_crtc_timing) +{ + enum dc_color_space color_space = COLOR_SPACE_SRGB; + + switch (dc_crtc_timing->pixel_encoding) { + case PIXEL_ENCODING_YCBCR422: + case PIXEL_ENCODING_YCBCR444: + case PIXEL_ENCODING_YCBCR420: + { + /* + * 27030khz is the separation point between HDTV and SDTV + * according to HDMI spec, we use YCbCr709 and YCbCr601 + * respectively + */ + if (dc_crtc_timing->pix_clk_khz > 27030) { + if (dc_crtc_timing->flags.Y_ONLY) + color_space = + COLOR_SPACE_YCBCR709_LIMITED; + else + color_space = COLOR_SPACE_YCBCR709; + } else { + if (dc_crtc_timing->flags.Y_ONLY) + color_space = + COLOR_SPACE_YCBCR601_LIMITED; + else + color_space = COLOR_SPACE_YCBCR601; + } + + } + break; + case PIXEL_ENCODING_RGB: + color_space = COLOR_SPACE_SRGB; + break; + + default: + WARN_ON(1); + break; + } + + return color_space; +} + +/*****************************************************************************/ + +static void fill_stream_properties_from_drm_display_mode( + struct dc_stream *stream, + const struct drm_display_mode *mode_in, + const struct drm_connector *connector) +{ + struct dc_crtc_timing *timing_out = &stream->timing; + memset(timing_out, 0, sizeof(struct dc_crtc_timing)); + + timing_out->h_border_left = 0; + timing_out->h_border_right = 0; + timing_out->v_border_top = 0; + timing_out->v_border_bottom = 0; + /* TODO: un-hardcode */ + + if ((connector->display_info.color_formats & DRM_COLOR_FORMAT_YCRCB444) + && stream->sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A) + timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR444; + else + timing_out->pixel_encoding = PIXEL_ENCODING_RGB; + + timing_out->timing_3d_format = TIMING_3D_FORMAT_NONE; + timing_out->display_color_depth = convert_color_depth_from_display_info( + connector); + timing_out->scan_type = SCANNING_TYPE_NODATA; + timing_out->hdmi_vic = 0; + timing_out->vic = drm_match_cea_mode(mode_in); + + timing_out->h_addressable = mode_in->crtc_hdisplay; + timing_out->h_total = mode_in->crtc_htotal; + timing_out->h_sync_width = + mode_in->crtc_hsync_end - mode_in->crtc_hsync_start; + timing_out->h_front_porch = + mode_in->crtc_hsync_start - mode_in->crtc_hdisplay; + timing_out->v_total = mode_in->crtc_vtotal; + timing_out->v_addressable = mode_in->crtc_vdisplay; + timing_out->v_front_porch = + mode_in->crtc_vsync_start - mode_in->crtc_vdisplay; + timing_out->v_sync_width = + mode_in->crtc_vsync_end - mode_in->crtc_vsync_start; + timing_out->pix_clk_khz = mode_in->crtc_clock; + timing_out->aspect_ratio = get_aspect_ratio(mode_in); + if (mode_in->flags & DRM_MODE_FLAG_PHSYNC) + timing_out->flags.HSYNC_POSITIVE_POLARITY = 1; + if (mode_in->flags & DRM_MODE_FLAG_PVSYNC) + timing_out->flags.VSYNC_POSITIVE_POLARITY = 1; + + stream->output_color_space = get_output_color_space(timing_out); + + { + struct dc_transfer_func *tf = dc_create_transfer_func(); + tf->type = TF_TYPE_PREDEFINED; + tf->tf = TRANSFER_FUNCTION_SRGB; + stream->out_transfer_func = tf; + } +} + +static void fill_audio_info( + struct audio_info *audio_info, + const struct drm_connector *drm_connector, + const struct dc_sink *dc_sink) +{ + int i = 0; + int cea_revision = 0; + const struct dc_edid_caps *edid_caps = &dc_sink->edid_caps; + + audio_info->manufacture_id = edid_caps->manufacturer_id; + audio_info->product_id = edid_caps->product_id; + + cea_revision = drm_connector->display_info.cea_rev; + + while (i < AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS && + edid_caps->display_name[i]) { + audio_info->display_name[i] = edid_caps->display_name[i]; + i++; + } + + if(cea_revision >= 3) { + audio_info->mode_count = edid_caps->audio_mode_count; + + for (i = 0; i < audio_info->mode_count; ++i) { + audio_info->modes[i].format_code = + (enum audio_format_code) + (edid_caps->audio_modes[i].format_code); + audio_info->modes[i].channel_count = + edid_caps->audio_modes[i].channel_count; + audio_info->modes[i].sample_rates.all = + edid_caps->audio_modes[i].sample_rate; + audio_info->modes[i].sample_size = + edid_caps->audio_modes[i].sample_size; + } + } + + audio_info->flags.all = edid_caps->speaker_flags; + + /* TODO: We only check for the progressive mode, check for interlace mode too */ + if(drm_connector->latency_present[0]) { + audio_info->video_latency = drm_connector->video_latency[0]; + audio_info->audio_latency = drm_connector->audio_latency[0]; + } + + /* TODO: For DP, video and audio latency should be calculated from DPCD caps */ + +} + +static void copy_crtc_timing_for_drm_display_mode( + const struct drm_display_mode *src_mode, + struct drm_display_mode *dst_mode) +{ + dst_mode->crtc_hdisplay = src_mode->crtc_hdisplay; + dst_mode->crtc_vdisplay = src_mode->crtc_vdisplay; + dst_mode->crtc_clock = src_mode->crtc_clock; + dst_mode->crtc_hblank_start = src_mode->crtc_hblank_start; + dst_mode->crtc_hblank_end = src_mode->crtc_hblank_end; + dst_mode->crtc_hsync_start= src_mode->crtc_hsync_start; + dst_mode->crtc_hsync_end = src_mode->crtc_hsync_end; + dst_mode->crtc_htotal = src_mode->crtc_htotal; + dst_mode->crtc_hskew = src_mode->crtc_hskew; + dst_mode->crtc_vblank_start = src_mode->crtc_vblank_start; + dst_mode->crtc_vblank_end = src_mode->crtc_vblank_end; + dst_mode->crtc_vsync_start = src_mode->crtc_vsync_start; + dst_mode->crtc_vsync_end = src_mode->crtc_vsync_end; + dst_mode->crtc_vtotal = src_mode->crtc_vtotal; +} + +static void decide_crtc_timing_for_drm_display_mode( + struct drm_display_mode *drm_mode, + const struct drm_display_mode *native_mode, + bool scale_enabled) +{ + if (scale_enabled) { + copy_crtc_timing_for_drm_display_mode(native_mode, drm_mode); + } else if (native_mode->clock == drm_mode->clock && + native_mode->htotal == drm_mode->htotal && + native_mode->vtotal == drm_mode->vtotal) { + copy_crtc_timing_for_drm_display_mode(native_mode, drm_mode); + } else { + /* no scaling nor amdgpu inserted, no need to patch */ + } +} + +static struct dc_stream *create_stream_for_sink( + struct amdgpu_connector *aconnector, + const struct drm_display_mode *drm_mode, + const struct dm_connector_state *dm_state) +{ + struct drm_display_mode *preferred_mode = NULL; + const struct drm_connector *drm_connector; + struct dc_stream *stream = NULL; + struct drm_display_mode mode = *drm_mode; + bool native_mode_found = false; + + if (NULL == aconnector) { + DRM_ERROR("aconnector is NULL!\n"); + goto drm_connector_null; + } + + if (NULL == dm_state) { + DRM_ERROR("dm_state is NULL!\n"); + goto dm_state_null; + } + drm_connector = &aconnector->base; + stream = dc_create_stream_for_sink(aconnector->dc_sink); + if (NULL == stream) { + DRM_ERROR("Failed to create stream for sink!\n"); + goto stream_create_fail; + } + + list_for_each_entry(preferred_mode, &aconnector->base.modes, head) { + /* Search for preferred mode */ + if (preferred_mode->type & DRM_MODE_TYPE_PREFERRED) { + native_mode_found = true; + break; + } + } + if (!native_mode_found) + preferred_mode = list_first_entry_or_null( + &aconnector->base.modes, + struct drm_display_mode, + head); + + if (NULL == preferred_mode) { + /* This may not be an error, the use case is when we we have no + * usermode calls to reset and set mode upon hotplug. In this + * case, we call set mode ourselves to restore the previous mode + * and the modelist may not be filled in in time. + */ + DRM_INFO("No preferred mode found\n"); + } else { + decide_crtc_timing_for_drm_display_mode( + &mode, preferred_mode, + dm_state->scaling != RMX_OFF); + } + + fill_stream_properties_from_drm_display_mode(stream, + &mode, &aconnector->base); + update_stream_scaling_settings(&mode, dm_state, stream); + + fill_audio_info( + &stream->audio_info, + drm_connector, + aconnector->dc_sink); + +stream_create_fail: +dm_state_null: +drm_connector_null: + return stream; +} + +void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc) +{ + drm_crtc_cleanup(crtc); + kfree(crtc); +} + +static void dm_crtc_destroy_state(struct drm_crtc *crtc, + struct drm_crtc_state *state) +{ + struct dm_crtc_state *cur = to_dm_crtc_state(state); + + /* TODO Destroy dc_stream objects are stream object is flattened */ + if (cur->stream) + dc_stream_release(cur->stream); + + + __drm_atomic_helper_crtc_destroy_state(state); + + + kfree(state); +} + +static void dm_crtc_reset_state(struct drm_crtc *crtc) +{ + struct dm_crtc_state *state; + + if (crtc->state) + dm_crtc_destroy_state(crtc, crtc->state); + + state = kzalloc(sizeof(*state), GFP_KERNEL); + if (WARN_ON(!state)) + return; + + crtc->state = &state->base; + crtc->state->crtc = crtc; + +} + +static struct drm_crtc_state * +dm_crtc_duplicate_state(struct drm_crtc *crtc) +{ + struct dm_crtc_state *state, *cur; + + cur = to_dm_crtc_state(crtc->state); + + if (WARN_ON(!crtc->state)) + return NULL; + + state = dm_alloc(sizeof(*state)); + + __drm_atomic_helper_crtc_duplicate_state(crtc, &state->base); + + if (cur->stream) { + state->stream = cur->stream; + dc_stream_retain(state->stream); + } + + /* TODO Duplicate dc_stream after objects are stream object is flattened */ + + return &state->base; +} + +/* Implemented only the options currently availible for the driver */ +static const struct drm_crtc_funcs amdgpu_dm_crtc_funcs = { + .reset = dm_crtc_reset_state, + .destroy = amdgpu_dm_crtc_destroy, + .gamma_set = drm_atomic_helper_legacy_gamma_set, + .set_config = drm_atomic_helper_set_config, + .page_flip = drm_atomic_helper_page_flip, + .atomic_duplicate_state = dm_crtc_duplicate_state, + .atomic_destroy_state = dm_crtc_destroy_state, +}; + +static enum drm_connector_status +amdgpu_dm_connector_detect(struct drm_connector *connector, bool force) +{ + bool connected; + struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + + /* Notes: + * 1. This interface is NOT called in context of HPD irq. + * 2. This interface *is called* in context of user-mode ioctl. Which + * makes it a bad place for *any* MST-related activit. */ + + if (aconnector->base.force == DRM_FORCE_UNSPECIFIED) + connected = (aconnector->dc_sink != NULL); + else + connected = (aconnector->base.force == DRM_FORCE_ON); + + return (connected ? connector_status_connected : + connector_status_disconnected); +} + +int amdgpu_dm_connector_atomic_set_property( + struct drm_connector *connector, + struct drm_connector_state *connector_state, + struct drm_property *property, + uint64_t val) +{ + struct drm_device *dev = connector->dev; + struct amdgpu_device *adev = dev->dev_private; + struct dm_connector_state *dm_old_state = + to_dm_connector_state(connector->state); + struct dm_connector_state *dm_new_state = + to_dm_connector_state(connector_state); + + int ret = -EINVAL; + + if (property == dev->mode_config.scaling_mode_property) { + enum amdgpu_rmx_type rmx_type; + + switch (val) { + case DRM_MODE_SCALE_CENTER: + rmx_type = RMX_CENTER; + break; + case DRM_MODE_SCALE_ASPECT: + rmx_type = RMX_ASPECT; + break; + case DRM_MODE_SCALE_FULLSCREEN: + rmx_type = RMX_FULL; + break; + case DRM_MODE_SCALE_NONE: + default: + rmx_type = RMX_OFF; + break; + } + + if (dm_old_state->scaling == rmx_type) + return 0; + + dm_new_state->scaling = rmx_type; + ret = 0; + } else if (property == adev->mode_info.underscan_hborder_property) { + dm_new_state->underscan_hborder = val; + ret = 0; + } else if (property == adev->mode_info.underscan_vborder_property) { + dm_new_state->underscan_vborder = val; + ret = 0; + } else if (property == adev->mode_info.underscan_property) { + dm_new_state->underscan_enable = val; + ret = 0; + } + + return ret; +} + +int amdgpu_dm_connector_atomic_get_property( + struct drm_connector *connector, + const struct drm_connector_state *state, + struct drm_property *property, + uint64_t *val) +{ + struct drm_device *dev = connector->dev; + struct amdgpu_device *adev = dev->dev_private; + struct dm_connector_state *dm_state = + to_dm_connector_state(state); + int ret = -EINVAL; + + if (property == dev->mode_config.scaling_mode_property) { + switch (dm_state->scaling) { + case RMX_CENTER: + *val = DRM_MODE_SCALE_CENTER; + break; + case RMX_ASPECT: + *val = DRM_MODE_SCALE_ASPECT; + break; + case RMX_FULL: + *val = DRM_MODE_SCALE_FULLSCREEN; + break; + case RMX_OFF: + default: + *val = DRM_MODE_SCALE_NONE; + break; + } + ret = 0; + } else if (property == adev->mode_info.underscan_hborder_property) { + *val = dm_state->underscan_hborder; + ret = 0; + } else if (property == adev->mode_info.underscan_vborder_property) { + *val = dm_state->underscan_vborder; + ret = 0; + } else if (property == adev->mode_info.underscan_property) { + *val = dm_state->underscan_enable; + ret = 0; + } + return ret; +} + +void amdgpu_dm_connector_destroy(struct drm_connector *connector) +{ + struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + const struct dc_link *link = aconnector->dc_link; + struct amdgpu_device *adev = connector->dev->dev_private; + struct amdgpu_display_manager *dm = &adev->dm; +#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\ + defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) + + if (link->connector_signal & (SIGNAL_TYPE_EDP | SIGNAL_TYPE_LVDS)) { + amdgpu_dm_register_backlight_device(dm); + + if (dm->backlight_dev) { + backlight_device_unregister(dm->backlight_dev); + dm->backlight_dev = NULL; + } + + } +#endif + drm_connector_unregister(connector); + drm_connector_cleanup(connector); + kfree(connector); +} + +void amdgpu_dm_connector_funcs_reset(struct drm_connector *connector) +{ + struct dm_connector_state *state = + to_dm_connector_state(connector->state); + + kfree(state); + + state = kzalloc(sizeof(*state), GFP_KERNEL); + + if (state) { + state->scaling = RMX_OFF; + state->underscan_enable = false; + state->underscan_hborder = 0; + state->underscan_vborder = 0; + + connector->state = &state->base; + connector->state->connector = connector; + } +} + +struct drm_connector_state *amdgpu_dm_connector_atomic_duplicate_state( + struct drm_connector *connector) +{ + struct dm_connector_state *state = + to_dm_connector_state(connector->state); + + struct dm_connector_state *new_state = + kmemdup(state, sizeof(*state), GFP_KERNEL); + + if (new_state) { + __drm_atomic_helper_connector_duplicate_state(connector, + &new_state->base); + return &new_state->base; + } + + return NULL; +} + +static const struct drm_connector_funcs amdgpu_dm_connector_funcs = { + .reset = amdgpu_dm_connector_funcs_reset, + .detect = amdgpu_dm_connector_detect, + .fill_modes = drm_helper_probe_single_connector_modes, + .destroy = amdgpu_dm_connector_destroy, + .atomic_duplicate_state = amdgpu_dm_connector_atomic_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, + .atomic_set_property = amdgpu_dm_connector_atomic_set_property, + .atomic_get_property = amdgpu_dm_connector_atomic_get_property +}; + +static struct drm_encoder *best_encoder(struct drm_connector *connector) +{ + int enc_id = connector->encoder_ids[0]; + struct drm_mode_object *obj; + struct drm_encoder *encoder; + + DRM_DEBUG_KMS("Finding the best encoder\n"); + + /* pick the encoder ids */ + if (enc_id) { + obj = drm_mode_object_find(connector->dev, enc_id, DRM_MODE_OBJECT_ENCODER); + if (!obj) { + DRM_ERROR("Couldn't find a matching encoder for our connector\n"); + return NULL; + } + encoder = obj_to_encoder(obj); + return encoder; + } + DRM_ERROR("No encoder id\n"); + return NULL; +} + +static int get_modes(struct drm_connector *connector) +{ + return amdgpu_dm_connector_get_modes(connector); +} + +static void create_eml_sink(struct amdgpu_connector *aconnector) +{ + struct dc_sink_init_data init_params = { + .link = aconnector->dc_link, + .sink_signal = SIGNAL_TYPE_VIRTUAL + }; + struct edid *edid = (struct edid *) aconnector->base.edid_blob_ptr->data; + + if (!aconnector->base.edid_blob_ptr || + !aconnector->base.edid_blob_ptr->data) { + DRM_ERROR("No EDID firmware found on connector: %s ,forcing to OFF!\n", + aconnector->base.name); + + aconnector->base.force = DRM_FORCE_OFF; + aconnector->base.override_edid = false; + return; + } + + aconnector->edid = edid; + + aconnector->dc_em_sink = dc_link_add_remote_sink( + aconnector->dc_link, + (uint8_t *)edid, + (edid->extensions + 1) * EDID_LENGTH, + &init_params); + + if (aconnector->base.force + == DRM_FORCE_ON) + aconnector->dc_sink = aconnector->dc_link->local_sink ? + aconnector->dc_link->local_sink : + aconnector->dc_em_sink; +} + +static void handle_edid_mgmt(struct amdgpu_connector *aconnector) +{ + struct dc_link *link = (struct dc_link *)aconnector->dc_link; + + /* In case of headless boot with force on for DP managed connector + * Those settings have to be != 0 to get initial modeset + */ + if (link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT) { + link->verified_link_cap.lane_count = LANE_COUNT_FOUR; + link->verified_link_cap.link_rate = LINK_RATE_HIGH2; + } + + + aconnector->base.override_edid = true; + create_eml_sink(aconnector); +} + +int amdgpu_dm_connector_mode_valid( + struct drm_connector *connector, + struct drm_display_mode *mode) +{ + int result = MODE_ERROR; + struct dc_sink *dc_sink; + struct amdgpu_device *adev = connector->dev->dev_private; + /* TODO: Unhardcode stream count */ + struct dc_stream *stream; + struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + + if ((mode->flags & DRM_MODE_FLAG_INTERLACE) || + (mode->flags & DRM_MODE_FLAG_DBLSCAN)) + return result; + + /* Only run this the first time mode_valid is called to initilialize + * EDID mgmt + */ + if (aconnector->base.force != DRM_FORCE_UNSPECIFIED && + !aconnector->dc_em_sink) + handle_edid_mgmt(aconnector); + + dc_sink = to_amdgpu_connector(connector)->dc_sink; + + if (NULL == dc_sink) { + DRM_ERROR("dc_sink is NULL!\n"); + goto fail; + } + + stream = dc_create_stream_for_sink(dc_sink); + if (NULL == stream) { + DRM_ERROR("Failed to create stream for sink!\n"); + goto fail; + } + + drm_mode_set_crtcinfo(mode, 0); + fill_stream_properties_from_drm_display_mode(stream, mode, connector); + + stream->src.width = mode->hdisplay; + stream->src.height = mode->vdisplay; + stream->dst = stream->src; + + if (dc_validate_stream(adev->dm.dc, stream)) + result = MODE_OK; + + dc_stream_release(stream); + +fail: + /* TODO: error handling*/ + return result; +} + +static const struct drm_connector_helper_funcs +amdgpu_dm_connector_helper_funcs = { + /* + * If hotplug a second bigger display in FB Con mode, bigger resolution + * modes will be filtered by drm_mode_validate_size(), and those modes + * is missing after user start lightdm. So we need to renew modes list. + * in get_modes call back, not just return the modes count + */ + .get_modes = get_modes, + .mode_valid = amdgpu_dm_connector_mode_valid, + .best_encoder = best_encoder +}; + +static void dm_crtc_helper_disable(struct drm_crtc *crtc) +{ +} + +static int dm_crtc_helper_atomic_check( + struct drm_crtc *crtc, + struct drm_crtc_state *state) +{ + struct amdgpu_device *adev = crtc->dev->dev_private; + struct dc *dc = adev->dm.dc; + struct dm_crtc_state *dm_crtc_state = to_dm_crtc_state(state); + int ret = -EINVAL; + + if (unlikely(!dm_crtc_state->stream && modeset_required(state))) { + WARN_ON(1); + return ret; + } + + /* In some use cases, like reset, no stream is attached */ + if (!dm_crtc_state->stream) + return 0; + + if (dc_validate_stream(dc, dm_crtc_state->stream)) + return 0; + + return ret; +} + +static bool dm_crtc_helper_mode_fixup( + struct drm_crtc *crtc, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + return true; +} + +static const struct drm_crtc_helper_funcs amdgpu_dm_crtc_helper_funcs = { + .disable = dm_crtc_helper_disable, + .atomic_check = dm_crtc_helper_atomic_check, + .mode_fixup = dm_crtc_helper_mode_fixup +}; + +static void dm_encoder_helper_disable(struct drm_encoder *encoder) +{ + +} + +static int dm_encoder_helper_atomic_check( + struct drm_encoder *encoder, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) +{ + return 0; +} + +const struct drm_encoder_helper_funcs amdgpu_dm_encoder_helper_funcs = { + .disable = dm_encoder_helper_disable, + .atomic_check = dm_encoder_helper_atomic_check +}; + +static void dm_drm_plane_reset(struct drm_plane *plane) +{ + struct dm_plane_state *amdgpu_state = NULL; + + if (plane->state) + plane->funcs->atomic_destroy_state(plane, plane->state); + + amdgpu_state = kzalloc(sizeof(*amdgpu_state), GFP_KERNEL); + + if (amdgpu_state) { + plane->state = &amdgpu_state->base; + plane->state->plane = plane; + plane->state->rotation = DRM_MODE_ROTATE_0; + } else + WARN_ON(1); +} + +static struct drm_plane_state * +dm_drm_plane_duplicate_state(struct drm_plane *plane) +{ + struct dm_plane_state *dm_plane_state, *old_dm_plane_state; + + old_dm_plane_state = to_dm_plane_state(plane->state); + dm_plane_state = kzalloc(sizeof(*dm_plane_state), GFP_KERNEL); + if (!dm_plane_state) + return NULL; + + __drm_atomic_helper_plane_duplicate_state(plane, &dm_plane_state->base); + + if (old_dm_plane_state->surface) { + dm_plane_state->surface = old_dm_plane_state->surface; + dc_surface_retain(dm_plane_state->surface); + } + + return &dm_plane_state->base; +} + +void dm_drm_plane_destroy_state(struct drm_plane *plane, + struct drm_plane_state *state) +{ + struct dm_plane_state *dm_plane_state = to_dm_plane_state(state); + + if (dm_plane_state->surface) + dc_surface_release(dm_plane_state->surface); + + __drm_atomic_helper_plane_destroy_state(state); + kfree(dm_plane_state); +} + +static const struct drm_plane_funcs dm_plane_funcs = { + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, + .destroy = drm_plane_cleanup, + .reset = dm_drm_plane_reset, + .atomic_duplicate_state = dm_drm_plane_duplicate_state, + .atomic_destroy_state = dm_drm_plane_destroy_state, +}; + +static int dm_plane_helper_prepare_fb( + struct drm_plane *plane, + struct drm_plane_state *new_state) +{ + struct amdgpu_framebuffer *afb; + struct drm_gem_object *obj; + struct amdgpu_bo *rbo; + int r; + struct dm_plane_state *dm_plane_state_new, *dm_plane_state_old; + unsigned int awidth; + + dm_plane_state_old = to_dm_plane_state(plane->state); + dm_plane_state_new = to_dm_plane_state(new_state); + + if (!new_state->fb) { + DRM_DEBUG_KMS("No FB bound\n"); + return 0; + } + + afb = to_amdgpu_framebuffer(new_state->fb); + + obj = afb->obj; + rbo = gem_to_amdgpu_bo(obj); + r = amdgpu_bo_reserve(rbo, false); + if (unlikely(r != 0)) + return r; + + r = amdgpu_bo_pin(rbo, AMDGPU_GEM_DOMAIN_VRAM, &afb->address); + + + amdgpu_bo_unreserve(rbo); + + if (unlikely(r != 0)) { + DRM_ERROR("Failed to pin framebuffer\n"); + return r; + } + + amdgpu_bo_ref(rbo); + + if (dm_plane_state_new->surface && + dm_plane_state_old->surface != dm_plane_state_new->surface) { + struct dc_surface *surface = dm_plane_state_new->surface; + + if (surface->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) { + surface->address.grph.addr.low_part = lower_32_bits(afb->address); + surface->address.grph.addr.high_part = upper_32_bits(afb->address); + } else { + awidth = ALIGN(new_state->fb->width, 64); + surface->address.video_progressive.luma_addr.low_part + = lower_32_bits(afb->address); + surface->address.video_progressive.chroma_addr.low_part + = lower_32_bits(afb->address) + + (awidth * new_state->fb->height); + } + } + + /* It's a hack for s3 since in 4.9 kernel filter out cursor buffer + * prepare and cleanup in drm_atomic_helper_prepare_planes + * and drm_atomic_helper_cleanup_planes because fb doens't in s3. + * IN 4.10 kernel this code should be removed and amdgpu_device_suspend + * code touching fram buffers should be avoided for DC. + */ + if (plane->type == DRM_PLANE_TYPE_CURSOR) { + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(new_state->crtc); + + acrtc->cursor_bo = obj; + } + return 0; +} + +static void dm_plane_helper_cleanup_fb( + struct drm_plane *plane, + struct drm_plane_state *old_state) +{ + struct amdgpu_bo *rbo; + struct amdgpu_framebuffer *afb; + int r; + + if (!old_state->fb) + return; + + afb = to_amdgpu_framebuffer(old_state->fb); + rbo = gem_to_amdgpu_bo(afb->obj); + r = amdgpu_bo_reserve(rbo, false); + if (unlikely(r)) { + DRM_ERROR("failed to reserve rbo before unpin\n"); + return; + } else { + amdgpu_bo_unpin(rbo); + amdgpu_bo_unreserve(rbo); + amdgpu_bo_unref(&rbo); + }; +} + +int dm_create_validation_set_for_connector(struct drm_connector *connector, + struct drm_display_mode *mode, struct dc_validation_set *val_set) +{ + int result = MODE_ERROR; + struct dc_sink *dc_sink = + to_amdgpu_connector(connector)->dc_sink; + /* TODO: Unhardcode stream count */ + struct dc_stream *stream; + + if ((mode->flags & DRM_MODE_FLAG_INTERLACE) || + (mode->flags & DRM_MODE_FLAG_DBLSCAN)) + return result; + + if (NULL == dc_sink) { + DRM_ERROR("dc_sink is NULL!\n"); + return result; + } + + stream = dc_create_stream_for_sink(dc_sink); + + if (NULL == stream) { + DRM_ERROR("Failed to create stream for sink!\n"); + return result; + } + + drm_mode_set_crtcinfo(mode, 0); + + fill_stream_properties_from_drm_display_mode(stream, mode, connector); + + val_set->stream = stream; + + stream->src.width = mode->hdisplay; + stream->src.height = mode->vdisplay; + stream->dst = stream->src; + + return MODE_OK; +} + +static const struct drm_plane_helper_funcs dm_plane_helper_funcs = { + .prepare_fb = dm_plane_helper_prepare_fb, + .cleanup_fb = dm_plane_helper_cleanup_fb, +}; + +/* + * TODO: these are currently initialized to rgb formats only. + * For future use cases we should either initialize them dynamically based on + * plane capabilities, or initialize this array to all formats, so internal drm + * check will succeed, and let DC to implement proper check + */ +static uint32_t rgb_formats[] = { + DRM_FORMAT_RGB888, + DRM_FORMAT_XRGB8888, + DRM_FORMAT_ARGB8888, + DRM_FORMAT_RGBA8888, + DRM_FORMAT_XRGB2101010, + DRM_FORMAT_XBGR2101010, + DRM_FORMAT_ARGB2101010, + DRM_FORMAT_ABGR2101010, +}; + +static uint32_t yuv_formats[] = { + DRM_FORMAT_NV12, + DRM_FORMAT_NV21, +}; + +static const u32 cursor_formats[] = { + DRM_FORMAT_ARGB8888 +}; + +int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, + struct amdgpu_plane *aplane, + unsigned long possible_crtcs) +{ + int res = -EPERM; + + switch (aplane->base.type) { + case DRM_PLANE_TYPE_PRIMARY: + aplane->base.format_default = true; + + res = drm_universal_plane_init( + dm->adev->ddev, + &aplane->base, + possible_crtcs, + &dm_plane_funcs, + rgb_formats, + ARRAY_SIZE(rgb_formats), + NULL, aplane->base.type, NULL); + break; + case DRM_PLANE_TYPE_OVERLAY: + res = drm_universal_plane_init( + dm->adev->ddev, + &aplane->base, + possible_crtcs, + &dm_plane_funcs, + yuv_formats, + ARRAY_SIZE(yuv_formats), + NULL, aplane->base.type, NULL); + break; + case DRM_PLANE_TYPE_CURSOR: + res = drm_universal_plane_init( + dm->adev->ddev, + &aplane->base, + possible_crtcs, + &dm_plane_funcs, + cursor_formats, + ARRAY_SIZE(cursor_formats), + NULL, aplane->base.type, NULL); + break; + } + + drm_plane_helper_add(&aplane->base, &dm_plane_helper_funcs); + + return res; +} + +int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, + struct drm_plane *plane, + uint32_t crtc_index) +{ + struct amdgpu_crtc *acrtc = NULL; + struct amdgpu_plane *cursor_plane; + + int res = -ENOMEM; + + cursor_plane = kzalloc(sizeof(*cursor_plane), GFP_KERNEL); + if (!cursor_plane) + goto fail; + + cursor_plane->base.type = DRM_PLANE_TYPE_CURSOR; + res = amdgpu_dm_plane_init(dm, cursor_plane, 0); + + acrtc = kzalloc(sizeof(struct amdgpu_crtc), GFP_KERNEL); + if (!acrtc) + goto fail; + + res = drm_crtc_init_with_planes( + dm->ddev, + &acrtc->base, + plane, + &cursor_plane->base, + &amdgpu_dm_crtc_funcs, NULL); + + if (res) + goto fail; + + drm_crtc_helper_add(&acrtc->base, &amdgpu_dm_crtc_helper_funcs); + + acrtc->max_cursor_width = dm->adev->dm.dc->caps.max_cursor_size; + acrtc->max_cursor_height = dm->adev->dm.dc->caps.max_cursor_size; + + acrtc->crtc_id = crtc_index; + acrtc->base.enabled = false; + + dm->adev->mode_info.crtcs[crtc_index] = acrtc; + drm_mode_crtc_set_gamma_size(&acrtc->base, 256); + + return 0; + +fail: + if (acrtc) + kfree(acrtc); + if (cursor_plane) + kfree(cursor_plane); + acrtc->crtc_id = -1; + return res; +} + + +static int to_drm_connector_type(enum signal_type st) +{ + switch (st) { + case SIGNAL_TYPE_HDMI_TYPE_A: + return DRM_MODE_CONNECTOR_HDMIA; + case SIGNAL_TYPE_EDP: + return DRM_MODE_CONNECTOR_eDP; + case SIGNAL_TYPE_RGB: + return DRM_MODE_CONNECTOR_VGA; + case SIGNAL_TYPE_DISPLAY_PORT: + case SIGNAL_TYPE_DISPLAY_PORT_MST: + return DRM_MODE_CONNECTOR_DisplayPort; + case SIGNAL_TYPE_DVI_DUAL_LINK: + case SIGNAL_TYPE_DVI_SINGLE_LINK: + return DRM_MODE_CONNECTOR_DVID; + case SIGNAL_TYPE_VIRTUAL: + return DRM_MODE_CONNECTOR_VIRTUAL; + + default: + return DRM_MODE_CONNECTOR_Unknown; + } +} + +static void amdgpu_dm_get_native_mode(struct drm_connector *connector) +{ + const struct drm_connector_helper_funcs *helper = + connector->helper_private; + struct drm_encoder *encoder; + struct amdgpu_encoder *amdgpu_encoder; + + encoder = helper->best_encoder(connector); + + if (encoder == NULL) + return; + + amdgpu_encoder = to_amdgpu_encoder(encoder); + + amdgpu_encoder->native_mode.clock = 0; + + if (!list_empty(&connector->probed_modes)) { + struct drm_display_mode *preferred_mode = NULL; + list_for_each_entry(preferred_mode, + &connector->probed_modes, + head) { + if (preferred_mode->type & DRM_MODE_TYPE_PREFERRED) { + amdgpu_encoder->native_mode = *preferred_mode; + } + break; + } + + } +} + +static struct drm_display_mode *amdgpu_dm_create_common_mode( + struct drm_encoder *encoder, char *name, + int hdisplay, int vdisplay) +{ + struct drm_device *dev = encoder->dev; + struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); + struct drm_display_mode *mode = NULL; + struct drm_display_mode *native_mode = &amdgpu_encoder->native_mode; + + mode = drm_mode_duplicate(dev, native_mode); + + if(mode == NULL) + return NULL; + + mode->hdisplay = hdisplay; + mode->vdisplay = vdisplay; + mode->type &= ~DRM_MODE_TYPE_PREFERRED; + strncpy(mode->name, name, DRM_DISPLAY_MODE_LEN); + + return mode; + +} + +static void amdgpu_dm_connector_add_common_modes(struct drm_encoder *encoder, + struct drm_connector *connector) +{ + struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); + struct drm_display_mode *mode = NULL; + struct drm_display_mode *native_mode = &amdgpu_encoder->native_mode; + struct amdgpu_connector *amdgpu_connector = + to_amdgpu_connector(connector); + int i; + int n; + struct mode_size { + char name[DRM_DISPLAY_MODE_LEN]; + int w; + int h; + }common_modes[] = { + { "640x480", 640, 480}, + { "800x600", 800, 600}, + { "1024x768", 1024, 768}, + { "1280x720", 1280, 720}, + { "1280x800", 1280, 800}, + {"1280x1024", 1280, 1024}, + { "1440x900", 1440, 900}, + {"1680x1050", 1680, 1050}, + {"1600x1200", 1600, 1200}, + {"1920x1080", 1920, 1080}, + {"1920x1200", 1920, 1200} + }; + + n = sizeof(common_modes) / sizeof(common_modes[0]); + + for (i = 0; i < n; i++) { + struct drm_display_mode *curmode = NULL; + bool mode_existed = false; + + if (common_modes[i].w > native_mode->hdisplay || + common_modes[i].h > native_mode->vdisplay || + (common_modes[i].w == native_mode->hdisplay && + common_modes[i].h == native_mode->vdisplay)) + continue; + + list_for_each_entry(curmode, &connector->probed_modes, head) { + if (common_modes[i].w == curmode->hdisplay && + common_modes[i].h == curmode->vdisplay) { + mode_existed = true; + break; + } + } + + if (mode_existed) + continue; + + mode = amdgpu_dm_create_common_mode(encoder, + common_modes[i].name, common_modes[i].w, + common_modes[i].h); + drm_mode_probed_add(connector, mode); + amdgpu_connector->num_modes++; + } +} + +static void amdgpu_dm_connector_ddc_get_modes( + struct drm_connector *connector, + struct edid *edid) +{ + struct amdgpu_connector *amdgpu_connector = + to_amdgpu_connector(connector); + + if (edid) { + /* empty probed_modes */ + INIT_LIST_HEAD(&connector->probed_modes); + amdgpu_connector->num_modes = + drm_add_edid_modes(connector, edid); + + drm_edid_to_eld(connector, edid); + + amdgpu_dm_get_native_mode(connector); + } else + amdgpu_connector->num_modes = 0; +} + +int amdgpu_dm_connector_get_modes(struct drm_connector *connector) +{ + const struct drm_connector_helper_funcs *helper = + connector->helper_private; + struct amdgpu_connector *amdgpu_connector = + to_amdgpu_connector(connector); + struct drm_encoder *encoder; + struct edid *edid = amdgpu_connector->edid; + + encoder = helper->best_encoder(connector); + + amdgpu_dm_connector_ddc_get_modes(connector, edid); + amdgpu_dm_connector_add_common_modes(encoder, connector); + return amdgpu_connector->num_modes; +} + +void amdgpu_dm_connector_init_helper( + struct amdgpu_display_manager *dm, + struct amdgpu_connector *aconnector, + int connector_type, + struct dc_link *link, + int link_index) +{ + struct amdgpu_device *adev = dm->ddev->dev_private; + + aconnector->connector_id = link_index; + aconnector->dc_link = link; + aconnector->base.interlace_allowed = false; + aconnector->base.doublescan_allowed = false; + aconnector->base.stereo_allowed = false; + aconnector->base.dpms = DRM_MODE_DPMS_OFF; + aconnector->hpd.hpd = AMDGPU_HPD_NONE; /* not used */ + + mutex_init(&aconnector->hpd_lock); + + /*configure suport HPD hot plug connector_>polled default value is 0 + * which means HPD hot plug not supported*/ + switch (connector_type) { + case DRM_MODE_CONNECTOR_HDMIA: + aconnector->base.polled = DRM_CONNECTOR_POLL_HPD; + break; + case DRM_MODE_CONNECTOR_DisplayPort: + aconnector->base.polled = DRM_CONNECTOR_POLL_HPD; + break; + case DRM_MODE_CONNECTOR_DVID: + aconnector->base.polled = DRM_CONNECTOR_POLL_HPD; + break; + default: + break; + } + + drm_object_attach_property(&aconnector->base.base, + dm->ddev->mode_config.scaling_mode_property, + DRM_MODE_SCALE_NONE); + + drm_object_attach_property(&aconnector->base.base, + adev->mode_info.underscan_property, + UNDERSCAN_OFF); + drm_object_attach_property(&aconnector->base.base, + adev->mode_info.underscan_hborder_property, + 0); + drm_object_attach_property(&aconnector->base.base, + adev->mode_info.underscan_vborder_property, + 0); + +} + +int amdgpu_dm_i2c_xfer(struct i2c_adapter *i2c_adap, + struct i2c_msg *msgs, int num) +{ + struct amdgpu_i2c_adapter *i2c = i2c_get_adapdata(i2c_adap); + struct ddc_service *ddc_service = i2c->ddc_service; + struct i2c_command cmd; + int i; + int result = -EIO; + + cmd.payloads = kzalloc(num * sizeof(struct i2c_payload), GFP_KERNEL); + + if (!cmd.payloads) + return result; + + cmd.number_of_payloads = num; + cmd.engine = I2C_COMMAND_ENGINE_DEFAULT; + cmd.speed = 100; + + for (i = 0; i < num; i++) { + cmd.payloads[i].write = !(msgs[i].flags & I2C_M_RD); + cmd.payloads[i].address = msgs[i].addr; + cmd.payloads[i].length = msgs[i].len; + cmd.payloads[i].data = msgs[i].buf; + } + + if (dal_i2caux_submit_i2c_command( + ddc_service->ctx->i2caux, + ddc_service->ddc_pin, + &cmd)) + result = num; + + kfree(cmd.payloads); + return result; +} + +u32 amdgpu_dm_i2c_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + +static const struct i2c_algorithm amdgpu_dm_i2c_algo = { + .master_xfer = amdgpu_dm_i2c_xfer, + .functionality = amdgpu_dm_i2c_func, +}; + +static struct amdgpu_i2c_adapter *create_i2c( + struct ddc_service *ddc_service, + int link_index, + int *res) +{ + struct amdgpu_device *adev = ddc_service->ctx->driver_context; + struct amdgpu_i2c_adapter *i2c; + + i2c = kzalloc(sizeof (struct amdgpu_i2c_adapter), GFP_KERNEL); + i2c->base.owner = THIS_MODULE; + i2c->base.class = I2C_CLASS_DDC; + i2c->base.dev.parent = &adev->pdev->dev; + i2c->base.algo = &amdgpu_dm_i2c_algo; + snprintf(i2c->base.name, sizeof (i2c->base.name), "AMDGPU DM i2c hw bus %d", link_index); + i2c_set_adapdata(&i2c->base, i2c); + i2c->ddc_service = ddc_service; + + return i2c; +} + +/* Note: this function assumes that dc_link_detect() was called for the + * dc_link which will be represented by this aconnector. */ +int amdgpu_dm_connector_init( + struct amdgpu_display_manager *dm, + struct amdgpu_connector *aconnector, + uint32_t link_index, + struct amdgpu_encoder *aencoder) +{ + int res = 0; + int connector_type; + struct dc *dc = dm->dc; + struct dc_link *link = dc_get_link_at_index(dc, link_index); + struct amdgpu_i2c_adapter *i2c; + ((struct dc_link *)link)->priv = aconnector; + + DRM_DEBUG_KMS("%s()\n", __func__); + + i2c = create_i2c(link->ddc, link->link_index, &res); + aconnector->i2c = i2c; + res = i2c_add_adapter(&i2c->base); + + if (res) { + DRM_ERROR("Failed to register hw i2c %d\n", link->link_index); + goto out_free; + } + + connector_type = to_drm_connector_type(link->connector_signal); + + res = drm_connector_init( + dm->ddev, + &aconnector->base, + &amdgpu_dm_connector_funcs, + connector_type); + + if (res) { + DRM_ERROR("connector_init failed\n"); + aconnector->connector_id = -1; + goto out_free; + } + + drm_connector_helper_add( + &aconnector->base, + &amdgpu_dm_connector_helper_funcs); + + amdgpu_dm_connector_init_helper( + dm, + aconnector, + connector_type, + link, + link_index); + + drm_mode_connector_attach_encoder( + &aconnector->base, &aencoder->base); + + drm_connector_register(&aconnector->base); + + if (connector_type == DRM_MODE_CONNECTOR_DisplayPort + || connector_type == DRM_MODE_CONNECTOR_eDP) + amdgpu_dm_initialize_dp_connector(dm, aconnector); + +#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\ + defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) + + /* NOTE: this currently will create backlight device even if a panel + * is not connected to the eDP/LVDS connector. + * + * This is less than ideal but we don't have sink information at this + * stage since detection happens after. We can't do detection earlier + * since MST detection needs connectors to be created first. + */ + if (link->connector_signal & (SIGNAL_TYPE_EDP | SIGNAL_TYPE_LVDS)) { + /* Event if registration failed, we should continue with + * DM initialization because not having a backlight control + * is better then a black screen. */ + amdgpu_dm_register_backlight_device(dm); + + if (dm->backlight_dev) + dm->backlight_link = link; + } +#endif + +out_free: + if (res) { + kfree(i2c); + aconnector->i2c = NULL; + } + return res; +} + +int amdgpu_dm_get_encoder_crtc_mask(struct amdgpu_device *adev) +{ + switch (adev->mode_info.num_crtc) { + case 1: + return 0x1; + case 2: + return 0x3; + case 3: + return 0x7; + case 4: + return 0xf; + case 5: + return 0x1f; + case 6: + default: + return 0x3f; + } +} + +int amdgpu_dm_encoder_init( + struct drm_device *dev, + struct amdgpu_encoder *aencoder, + uint32_t link_index) +{ + struct amdgpu_device *adev = dev->dev_private; + + int res = drm_encoder_init(dev, + &aencoder->base, + &amdgpu_dm_encoder_funcs, + DRM_MODE_ENCODER_TMDS, + NULL); + + aencoder->base.possible_crtcs = amdgpu_dm_get_encoder_crtc_mask(adev); + + if (!res) + aencoder->encoder_id = link_index; + else + aencoder->encoder_id = -1; + + drm_encoder_helper_add(&aencoder->base, &amdgpu_dm_encoder_helper_funcs); + + return res; +} + +static void manage_dm_interrupts( + struct amdgpu_device *adev, + struct amdgpu_crtc *acrtc, + bool enable) +{ + /* + * this is not correct translation but will work as soon as VBLANK + * constant is the same as PFLIP + */ + int irq_type = + amdgpu_crtc_idx_to_irq_type( + adev, + acrtc->crtc_id); + + if (enable) { + drm_crtc_vblank_on(&acrtc->base); + amdgpu_irq_get( + adev, + &adev->pageflip_irq, + irq_type); + } else { + + amdgpu_irq_put( + adev, + &adev->pageflip_irq, + irq_type); + drm_crtc_vblank_off(&acrtc->base); + } +} + +static bool is_scaling_state_different( + const struct dm_connector_state *dm_state, + const struct dm_connector_state *old_dm_state) +{ + if (dm_state->scaling != old_dm_state->scaling) + return true; + if (!dm_state->underscan_enable && old_dm_state->underscan_enable) { + if (old_dm_state->underscan_hborder != 0 && old_dm_state->underscan_vborder != 0) + return true; + } else if (dm_state->underscan_enable && !old_dm_state->underscan_enable) { + if (dm_state->underscan_hborder != 0 && dm_state->underscan_vborder != 0) + return true; + } else if (dm_state->underscan_hborder != old_dm_state->underscan_hborder + || dm_state->underscan_vborder != old_dm_state->underscan_vborder) + return true; + return false; +} + +static void remove_stream( + struct amdgpu_device *adev, + struct amdgpu_crtc *acrtc, + struct dc_stream *stream) +{ + /* this is the update mode case */ + if (adev->dm.freesync_module) + mod_freesync_remove_stream(adev->dm.freesync_module, stream); + + acrtc->otg_inst = -1; + acrtc->enabled = false; +} + +static void handle_cursor_update( + struct drm_plane *plane, + struct drm_plane_state *old_plane_state) +{ + if (!plane->state->fb && !old_plane_state->fb) + return; + + /* Check if it's a cursor on/off update or just cursor move*/ + if (plane->state->fb == old_plane_state->fb) + dm_crtc_cursor_move( + plane->state->crtc, + plane->state->crtc_x, + plane->state->crtc_y); + else { + struct amdgpu_framebuffer *afb = + to_amdgpu_framebuffer(plane->state->fb); + dm_crtc_cursor_set( + (!!plane->state->fb) ? + plane->state->crtc : + old_plane_state->crtc, + (!!plane->state->fb) ? + afb->address : + 0, + plane->state->crtc_w, + plane->state->crtc_h); + } +} + + +static void prepare_flip_isr(struct amdgpu_crtc *acrtc) +{ + + assert_spin_locked(&acrtc->base.dev->event_lock); + WARN_ON(acrtc->event); + + acrtc->event = acrtc->base.state->event; + + /* Set the flip status */ + acrtc->pflip_status = AMDGPU_FLIP_SUBMITTED; + + /* Mark this event as consumed */ + acrtc->base.state->event = NULL; + + DRM_DEBUG_DRIVER("crtc:%d, pflip_stat:AMDGPU_FLIP_SUBMITTED\n", + acrtc->crtc_id); +} + +/* + * Executes flip + * + * Waits on all BO's fences and for proper vblank count + */ +static void amdgpu_dm_do_flip( + struct drm_crtc *crtc, + struct drm_framebuffer *fb, + uint32_t target) +{ + unsigned long flags; + uint32_t target_vblank; + int r, vpos, hpos; + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + struct amdgpu_framebuffer *afb = to_amdgpu_framebuffer(fb); + struct amdgpu_bo *abo = gem_to_amdgpu_bo(afb->obj); + struct amdgpu_device *adev = crtc->dev->dev_private; + bool async_flip = (acrtc->flip_flags & DRM_MODE_PAGE_FLIP_ASYNC) != 0; + struct dc_flip_addrs addr = { {0} }; + struct dc_surface_update surface_updates[1] = { {0} }; + struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state); + + + /* Prepare wait for target vblank early - before the fence-waits */ + target_vblank = target - drm_crtc_vblank_count(crtc) + + amdgpu_get_vblank_counter_kms(crtc->dev, acrtc->crtc_id); + + /*TODO This might fail and hence better not used, wait + * explicitly on fences instead + * and in general should be called for + * blocking commit to as per framework helpers + * */ + r = amdgpu_bo_reserve(abo, true); + if (unlikely(r != 0)) { + DRM_ERROR("failed to reserve buffer before flip\n"); + WARN_ON(1); + } + + /* Wait for all fences on this FB */ + WARN_ON(reservation_object_wait_timeout_rcu(abo->tbo.resv, true, false, + MAX_SCHEDULE_TIMEOUT) < 0); + + amdgpu_bo_unreserve(abo); + + /* Wait until we're out of the vertical blank period before the one + * targeted by the flip + */ + while ((acrtc->enabled && + (amdgpu_get_crtc_scanoutpos(adev->ddev, acrtc->crtc_id, 0, + &vpos, &hpos, NULL, NULL, + &crtc->hwmode) + & (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_IN_VBLANK)) == + (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_IN_VBLANK) && + (int)(target_vblank - + amdgpu_get_vblank_counter_kms(adev->ddev, acrtc->crtc_id)) > 0)) { + usleep_range(1000, 1100); + } + + /* Flip */ + spin_lock_irqsave(&crtc->dev->event_lock, flags); + /* update crtc fb */ + crtc->primary->fb = fb; + + WARN_ON(acrtc->pflip_status != AMDGPU_FLIP_NONE); + WARN_ON(!acrtc_state->stream); + + addr.address.grph.addr.low_part = lower_32_bits(afb->address); + addr.address.grph.addr.high_part = upper_32_bits(afb->address); + addr.flip_immediate = async_flip; + + + if (acrtc->base.state->event) + prepare_flip_isr(acrtc); + + surface_updates->surface = dc_stream_get_status(acrtc_state->stream)->surfaces[0]; + surface_updates->flip_addr = &addr; + + + dc_update_surfaces_and_stream(adev->dm.dc, surface_updates, 1, acrtc_state->stream, NULL); + + DRM_DEBUG_DRIVER("%s Flipping to hi: 0x%x, low: 0x%x \n", + __func__, + addr.address.grph.addr.high_part, + addr.address.grph.addr.low_part); + + + spin_unlock_irqrestore(&crtc->dev->event_lock, flags); +} + +static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, + struct drm_device *dev, + struct amdgpu_display_manager *dm, + struct drm_crtc *pcrtc, + bool *wait_for_vblank) +{ + uint32_t i; + struct drm_plane *plane; + struct drm_plane_state *old_plane_state; + struct dc_stream *dc_stream_attach; + struct dc_surface *dc_surfaces_constructed[MAX_SURFACES]; + struct amdgpu_crtc *acrtc_attach = to_amdgpu_crtc(pcrtc); + struct dm_crtc_state *acrtc_state = to_dm_crtc_state(pcrtc->state); + int planes_count = 0; + unsigned long flags; + + /* update planes when needed */ + for_each_plane_in_state(state, plane, old_plane_state, i) { + struct drm_plane_state *plane_state = plane->state; + struct drm_crtc *crtc = plane_state->crtc; + struct drm_framebuffer *fb = plane_state->fb; + bool pflip_needed; + struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state); + + if (plane->type == DRM_PLANE_TYPE_CURSOR) { + handle_cursor_update(plane, old_plane_state); + continue; + } + + if (!fb || !crtc || pcrtc != crtc || !crtc->state->active || + (!crtc->state->planes_changed && + !pcrtc->state->color_mgmt_changed)) + continue; + + pflip_needed = !state->allow_modeset; + + spin_lock_irqsave(&crtc->dev->event_lock, flags); + if (acrtc_attach->pflip_status != AMDGPU_FLIP_NONE) { + DRM_ERROR("add_surface: acrtc %d, already busy\n", + acrtc_attach->crtc_id); + spin_unlock_irqrestore(&crtc->dev->event_lock, flags); + /* In comit tail framework this cannot happen */ + WARN_ON(1); + } + spin_unlock_irqrestore(&crtc->dev->event_lock, flags); + + if (!pflip_needed) { + WARN_ON(!dm_plane_state->surface); + + dc_surfaces_constructed[planes_count] = dm_plane_state->surface; + + dc_stream_attach = acrtc_state->stream; + planes_count++; + + } else if (crtc->state->planes_changed) { + /* Assume even ONE crtc with immediate flip means + * entire can't wait for VBLANK + * TODO Check if it's correct + */ + *wait_for_vblank = + acrtc_attach->flip_flags & DRM_MODE_PAGE_FLIP_ASYNC ? + false : true; + + /* TODO: Needs rework for multiplane flip */ + if (plane->type == DRM_PLANE_TYPE_PRIMARY) + drm_crtc_vblank_get(crtc); + + amdgpu_dm_do_flip( + crtc, + fb, + drm_crtc_vblank_count(crtc) + *wait_for_vblank); + + /*TODO BUG remove ASAP in 4.12 to avoid race between worker and flip IOCTL */ + + /*clean up the flags for next usage*/ + acrtc_attach->flip_flags = 0; + } + + } + + if (planes_count) { + unsigned long flags; + + if (pcrtc->state->event) { + + drm_crtc_vblank_get(pcrtc); + + spin_lock_irqsave(&pcrtc->dev->event_lock, flags); + prepare_flip_isr(acrtc_attach); + spin_unlock_irqrestore(&pcrtc->dev->event_lock, flags); + } + + if (false == dc_commit_surfaces_to_stream(dm->dc, + dc_surfaces_constructed, + planes_count, + dc_stream_attach)) + dm_error("%s: Failed to attach surface!\n", __func__); + } else { + /*TODO BUG Here should go disable planes on CRTC. */ + } +} + + +int amdgpu_dm_atomic_commit( + struct drm_device *dev, + struct drm_atomic_state *state, + bool nonblock) +{ + struct drm_crtc *crtc; + struct drm_crtc_state *new_state; + struct amdgpu_device *adev = dev->dev_private; + int i; + + /* + * We evade vblanks and pflips on crtc that + * should be changed. We do it here to flush & disable + * interrupts before drm_swap_state is called in drm_atomic_helper_commit + * it will update crtc->dm_crtc_state->stream pointer which is used in + * the ISRs. + */ + for_each_crtc_in_state(state, crtc, new_state, i) { + struct dm_crtc_state *old_acrtc_state = to_dm_crtc_state(crtc->state); + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + + if (drm_atomic_crtc_needs_modeset(new_state) && old_acrtc_state->stream) + manage_dm_interrupts(adev, acrtc, false); + } + + return drm_atomic_helper_commit(dev, state, nonblock); + + /*TODO Handle EINTR, reenable IRQ*/ +} + +void amdgpu_dm_atomic_commit_tail( + struct drm_atomic_state *state) +{ + struct drm_device *dev = state->dev; + struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_display_manager *dm = &adev->dm; + struct dm_atomic_state *dm_state; + uint32_t i, j; + uint32_t new_crtcs_count = 0; + struct drm_crtc *crtc, *pcrtc; + struct drm_crtc_state *old_crtc_state; + struct amdgpu_crtc *new_crtcs[MAX_STREAMS]; + struct dc_stream *new_stream = NULL; + unsigned long flags; + bool wait_for_vblank = true; + struct drm_connector *connector; + struct drm_connector_state *old_conn_state; + struct dm_crtc_state *old_acrtc_state, *new_acrtc_state; + + drm_atomic_helper_update_legacy_modeset_state(dev, state); + + dm_state = to_dm_atomic_state(state); + + /* update changed items */ + for_each_crtc_in_state(state, crtc, old_crtc_state, i) { + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + struct drm_crtc_state *new_state = crtc->state; + new_acrtc_state = to_dm_crtc_state(new_state); + old_acrtc_state = to_dm_crtc_state(old_crtc_state); + + DRM_DEBUG_KMS( + "amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, " + "planes_changed:%d, mode_changed:%d,active_changed:%d," + "connectors_changed:%d\n", + acrtc->crtc_id, + new_state->enable, + new_state->active, + new_state->planes_changed, + new_state->mode_changed, + new_state->active_changed, + new_state->connectors_changed); + + /* handles headless hotplug case, updating new_state and + * aconnector as needed + */ + + if (modeset_required(new_state)) { + + DRM_INFO("Atomic commit: SET crtc id %d: [%p]\n", acrtc->crtc_id, acrtc); + + if (!new_acrtc_state->stream) { + /* + * this could happen because of issues with + * userspace notifications delivery. + * In this case userspace tries to set mode on + * display which is disconnect in fact. + * dc_sink in NULL in this case on aconnector. + * We expect reset mode will come soon. + * + * This can also happen when unplug is done + * during resume sequence ended + * + * In this case, we want to pretend we still + * have a sink to keep the pipe running so that + * hw state is consistent with the sw state + */ + DRM_DEBUG_KMS("%s: Failed to create new stream for crtc %d\n", + __func__, acrtc->base.base.id); + continue; + } + + + if (old_acrtc_state->stream) + remove_stream(adev, acrtc, old_acrtc_state->stream); + + + /* + * this loop saves set mode crtcs + * we needed to enable vblanks once all + * resources acquired in dc after dc_commit_streams + */ + + /*TODO move all this into dm_crtc_state, get rid of + * new_crtcs array and use old and new atomic states + * instead + */ + new_crtcs[new_crtcs_count] = acrtc; + new_crtcs_count++; + + acrtc->enabled = true; + acrtc->hw_mode = crtc->state->mode; + crtc->hwmode = crtc->state->mode; + } else if (modereset_required(new_state)) { + DRM_INFO("Atomic commit: RESET. crtc id %d:[%p]\n", acrtc->crtc_id, acrtc); + + /* i.e. reset mode */ + if (old_acrtc_state->stream) + remove_stream(adev, acrtc, old_acrtc_state->stream); + } + } /* for_each_crtc_in_state() */ + + /* + * Add streams after required streams from new and replaced streams + * are removed from freesync module + */ + if (adev->dm.freesync_module) { + for (i = 0; i < new_crtcs_count; i++) { + struct amdgpu_connector *aconnector = NULL; + new_acrtc_state = to_dm_crtc_state(new_crtcs[i]->base.state); + + new_stream = new_acrtc_state->stream; + aconnector = + amdgpu_dm_find_first_crct_matching_connector( + state, + &new_crtcs[i]->base, + false); + if (!aconnector) { + DRM_INFO( + "Atomic commit: Failed to find connector for acrtc id:%d " + "skipping freesync init\n", + new_crtcs[i]->crtc_id); + continue; + } + + mod_freesync_add_stream(adev->dm.freesync_module, + new_stream, &aconnector->caps); + } + } + + if (dm_state->context) + WARN_ON(!dc_commit_context(dm->dc, dm_state->context)); + + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + new_acrtc_state = to_dm_crtc_state(crtc->state); + + if (new_acrtc_state->stream != NULL) { + const struct dc_stream_status *status = + dc_stream_get_status(new_acrtc_state->stream); + + if (!status) + DC_ERR("got no status for stream %p on acrtc%p\n", new_acrtc_state->stream, acrtc); + else + acrtc->otg_inst = status->primary_otg_inst; + } + } + + /* Handle scaling and undersacn changes*/ + for_each_connector_in_state(state, connector, old_conn_state, i) { + struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + struct dm_connector_state *con_new_state = + to_dm_connector_state(aconnector->base.state); + struct dm_connector_state *con_old_state = + to_dm_connector_state(old_conn_state); + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(con_new_state->base.crtc); + struct dc_stream_status *status = NULL; + + /* Skip any modesets/resets */ + if (!acrtc || drm_atomic_crtc_needs_modeset(acrtc->base.state)) + continue; + + /* Skip any thing not scale or underscan changes */ + if (!is_scaling_state_different(con_new_state, con_old_state)) + continue; + + new_acrtc_state = to_dm_crtc_state(acrtc->base.state); + + update_stream_scaling_settings(&con_new_state->base.crtc->mode, + con_new_state, (struct dc_stream *)new_acrtc_state->stream); + + status = dc_stream_get_status(new_acrtc_state->stream); + WARN_ON(!status); + WARN_ON(!status->surface_count); + + if (!new_acrtc_state->stream) + continue; + + /*TODO How it works with MPO ?*/ + if (!dc_commit_surfaces_to_stream( + dm->dc, + status->surfaces, + status->surface_count, + new_acrtc_state->stream)) + dm_error("%s: Failed to update stream scaling!\n", __func__); + } + + for (i = 0; i < new_crtcs_count; i++) { + /* + * loop to enable interrupts on newly arrived crtc + */ + struct amdgpu_crtc *acrtc = new_crtcs[i]; + new_acrtc_state = to_dm_crtc_state(acrtc->base.state); + + if (adev->dm.freesync_module) + mod_freesync_notify_mode_change( + adev->dm.freesync_module, &new_acrtc_state->stream, 1); + + manage_dm_interrupts(adev, acrtc, true); + } + + /* update planes when needed per crtc*/ + for_each_crtc_in_state(state, pcrtc, old_crtc_state, j) { + new_acrtc_state = to_dm_crtc_state(pcrtc->state); + + if (new_acrtc_state->stream) + amdgpu_dm_commit_surfaces(state, dev, dm, pcrtc, &wait_for_vblank); + } + + + /* + * send vblank event on all events not handled in flip and + * mark consumed event for drm_atomic_helper_commit_hw_done + */ + spin_lock_irqsave(&adev->ddev->event_lock, flags); + for_each_crtc_in_state(state, crtc, old_crtc_state, i) { + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + + if (acrtc->base.state->event) + drm_send_event_locked(dev, &crtc->state->event->base); + + acrtc->base.state->event = NULL; + } + spin_unlock_irqrestore(&adev->ddev->event_lock, flags); + + /* Signal HW programming completion */ + drm_atomic_helper_commit_hw_done(state); + + if (wait_for_vblank) + drm_atomic_helper_wait_for_vblanks(dev, state); + + drm_atomic_helper_cleanup_planes(dev, state); +} + + +static int dm_force_atomic_commit(struct drm_connector *connector) +{ + int ret = 0; + struct drm_device *ddev = connector->dev; + struct drm_atomic_state *state = drm_atomic_state_alloc(ddev); + struct amdgpu_crtc *disconnected_acrtc = to_amdgpu_crtc(connector->encoder->crtc); + struct drm_plane *plane = disconnected_acrtc->base.primary; + struct drm_connector_state *conn_state; + struct drm_crtc_state *crtc_state; + struct drm_plane_state *plane_state; + + if (!state) + return -ENOMEM; + + state->acquire_ctx = ddev->mode_config.acquire_ctx; + + /* Construct an atomic state to restore previous display setting */ + + /* + * Attach connectors to drm_atomic_state + */ + conn_state = drm_atomic_get_connector_state(state, connector); + + ret = PTR_ERR_OR_ZERO(conn_state); + if (ret) + goto err; + + /* Attach crtc to drm_atomic_state*/ + crtc_state = drm_atomic_get_crtc_state(state, &disconnected_acrtc->base); + + ret = PTR_ERR_OR_ZERO(crtc_state); + if (ret) + goto err; + + /* force a restore */ + crtc_state->mode_changed = true; + + /* Attach plane to drm_atomic_state */ + plane_state = drm_atomic_get_plane_state(state, plane); + + ret = PTR_ERR_OR_ZERO(plane_state); + if (ret) + goto err; + + + /* Call commit internally with the state we just constructed */ + ret = drm_atomic_commit(state); + if (!ret) + return 0; + +err: + DRM_ERROR("Restoring old state failed with %i\n", ret); + drm_atomic_state_put(state); + + return ret; +} + +/* + * This functions handle all cases when set mode does not come upon hotplug. + * This include when the same display is unplugged then plugged back into the + * same port and when we are running without usermode desktop manager supprot + */ +void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector *connector) +{ + struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + struct amdgpu_crtc *disconnected_acrtc; + struct dm_crtc_state *acrtc_state; + + if (!aconnector->dc_sink || !connector->state || !connector->encoder) + return; + + disconnected_acrtc = to_amdgpu_crtc(connector->encoder->crtc); + acrtc_state = to_dm_crtc_state(disconnected_acrtc->base.state); + + if (!disconnected_acrtc || !acrtc_state->stream) + return; + + /* + * If the previous sink is not released and different from the current, + * we deduce we are in a state where we can not rely on usermode call + * to turn on the display, so we do it here + */ + if (acrtc_state->stream->sink != aconnector->dc_sink) + dm_force_atomic_commit(&aconnector->base); +} + +static uint32_t add_val_sets_surface( + struct dc_validation_set *val_sets, + uint32_t set_count, + const struct dc_stream *stream, + struct dc_surface *surface) +{ + uint32_t i = 0, j = 0; + + while (i < set_count) { + if (val_sets[i].stream == stream) { + while (val_sets[i].surfaces[j]) + j++; + break; + } + ++i; + } + + val_sets[i].surfaces[j] = surface; + val_sets[i].surface_count++; + + return val_sets[i].surface_count; +} + +static uint32_t update_in_val_sets_stream( + struct dc_validation_set *val_sets, + uint32_t set_count, + struct dc_stream *old_stream, + struct dc_stream *new_stream, + struct drm_crtc *crtc) +{ + uint32_t i = 0; + + while (i < set_count) { + if (val_sets[i].stream == old_stream) + break; + ++i; + } + + val_sets[i].stream = new_stream; + + if (i == set_count) + /* nothing found. add new one to the end */ + return set_count + 1; + + return set_count; +} + +static uint32_t remove_from_val_sets( + struct dc_validation_set *val_sets, + uint32_t set_count, + const struct dc_stream *stream) +{ + int i; + + for (i = 0; i < set_count; i++) + if (val_sets[i].stream == stream) + break; + + if (i == set_count) { + /* nothing found */ + return set_count; + } + + set_count--; + + for (; i < set_count; i++) { + val_sets[i] = val_sets[i + 1]; + } + + return set_count; +} + +/*` + * Grabs all modesetting locks to serialize against any blocking commits, + * Waits for completion of all non blocking commits. + */ +static int do_aquire_global_lock( + struct drm_device *dev, + struct drm_atomic_state *state) +{ + struct drm_crtc *crtc; + struct drm_crtc_commit *commit; + long ret; + + /* Adding all modeset locks to aquire_ctx will + * ensure that when the framework release it the + * extra locks we are locking here will get released to + */ + ret = drm_modeset_lock_all_ctx(dev, state->acquire_ctx); + if (ret) + return ret; + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + spin_lock(&crtc->commit_lock); + commit = list_first_entry_or_null(&crtc->commit_list, + struct drm_crtc_commit, commit_entry); + if (commit) + drm_crtc_commit_get(commit); + spin_unlock(&crtc->commit_lock); + + if (!commit) + continue; + + /* Make sure all pending HW programming completed and + * page flips done + */ + ret = wait_for_completion_interruptible_timeout(&commit->hw_done, 10*HZ); + + if (ret > 0) + ret = wait_for_completion_interruptible_timeout( + &commit->flip_done, 10*HZ); + + if (ret == 0) + DRM_ERROR("[CRTC:%d:%s] hw_done or flip_done " + "timed out\n", crtc->base.id, crtc->name); + + drm_crtc_commit_put(commit); + } + + return ret < 0 ? ret : 0; +} + +int amdgpu_dm_atomic_check(struct drm_device *dev, + struct drm_atomic_state *state) +{ + struct dm_atomic_state *dm_state; + struct drm_crtc *crtc; + struct drm_crtc_state *crtc_state; + struct drm_plane *plane; + struct drm_plane_state *plane_state; + int i, j; + int ret; + struct amdgpu_device *adev = dev->dev_private; + struct dc *dc = adev->dm.dc; + struct drm_connector *connector; + struct drm_connector_state *conn_state; + int set_count; + struct dc_validation_set set[MAX_STREAMS] = { { 0 } }; + struct dm_crtc_state *old_acrtc_state, *new_acrtc_state; + + /* + * This bool will be set for true for any modeset/reset + * or surface update which implies non fast surface update. + */ + bool lock_and_validation_needed = false; + + ret = drm_atomic_helper_check_modeset(dev, state); + + if (ret) { + DRM_ERROR("Atomic state validation failed with error :%d !\n", ret); + return ret; + } + + dm_state = to_dm_atomic_state(state); + + /* copy existing configuration */ + set_count = 0; + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + + old_acrtc_state = to_dm_crtc_state(crtc->state); + + if (old_acrtc_state->stream) { + dc_stream_retain(old_acrtc_state->stream); + set[set_count].stream = old_acrtc_state->stream; + ++set_count; + } + } + + /*TODO Move this code into dm_crtc_atomic_check once we get rid of dc_validation_set */ + /* update changed items */ + for_each_crtc_in_state(state, crtc, crtc_state, i) { + struct amdgpu_crtc *acrtc = NULL; + struct amdgpu_connector *aconnector = NULL; + old_acrtc_state = to_dm_crtc_state(crtc->state); + new_acrtc_state = to_dm_crtc_state(crtc_state); + acrtc = to_amdgpu_crtc(crtc); + + aconnector = amdgpu_dm_find_first_crct_matching_connector(state, crtc, true); + + DRM_DEBUG_KMS( + "amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, " + "planes_changed:%d, mode_changed:%d,active_changed:%d," + "connectors_changed:%d\n", + acrtc->crtc_id, + crtc_state->enable, + crtc_state->active, + crtc_state->planes_changed, + crtc_state->mode_changed, + crtc_state->active_changed, + crtc_state->connectors_changed); + + if (modeset_required(crtc_state)) { + + struct dc_stream *new_stream = NULL; + struct drm_connector_state *conn_state = NULL; + struct dm_connector_state *dm_conn_state = NULL; + + if (aconnector) { + conn_state = drm_atomic_get_connector_state(state, &aconnector->base); + if (IS_ERR(conn_state)) { + ret = PTR_ERR_OR_ZERO(conn_state); + goto fail; + } + + dm_conn_state = to_dm_connector_state(conn_state); + } + + new_stream = create_stream_for_sink(aconnector, &crtc_state->mode, dm_conn_state); + + /* + * we can have no stream on ACTION_SET if a display + * was disconnected during S3, in this case it not and + * error, the OS will be updated after detection, and + * do the right thing on next atomic commit + */ + if (!new_stream) { + DRM_DEBUG_KMS("%s: Failed to create new stream for crtc %d\n", + __func__, acrtc->base.base.id); + break; + } + + if (new_acrtc_state->stream) + dc_stream_release(new_acrtc_state->stream); + + new_acrtc_state->stream = new_stream; + + set_count = update_in_val_sets_stream( + set, + set_count, + old_acrtc_state->stream, + new_acrtc_state->stream, + crtc); + + lock_and_validation_needed = true; + + } else if (modereset_required(crtc_state)) { + + /* i.e. reset mode */ + if (new_acrtc_state->stream) { + set_count = remove_from_val_sets( + set, + set_count, + new_acrtc_state->stream); + + dc_stream_release(new_acrtc_state->stream); + new_acrtc_state->stream = NULL; + + lock_and_validation_needed = true; + } + } + + + /* + * Hack: Commit needs planes right now, specifically for gamma + * TODO rework commit to check CRTC for gamma change + */ + if (crtc_state->color_mgmt_changed) { + + ret = drm_atomic_add_affected_planes(state, crtc); + if (ret) + goto fail; + } + } + + /* Check scaling and undersacn changes*/ + /*TODO Removed scaling changes validation due to inability to commit + * new stream into context w\o causing full reset. Need to + * decide how to handle. + */ + for_each_connector_in_state(state, connector, conn_state, i) { + struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + struct dm_connector_state *con_old_state = + to_dm_connector_state(aconnector->base.state); + struct dm_connector_state *con_new_state = + to_dm_connector_state(conn_state); + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(con_new_state->base.crtc); + + /* Skip any modesets/resets */ + if (!acrtc || drm_atomic_crtc_needs_modeset(acrtc->base.state)) + continue; + + /* Skip any thing not scale or underscan chnages */ + if (!is_scaling_state_different(con_new_state, con_old_state)) + continue; + + lock_and_validation_needed = true; + } + + for_each_crtc_in_state(state, crtc, crtc_state, i) { + new_acrtc_state = to_dm_crtc_state(crtc_state); + + for_each_plane_in_state(state, plane, plane_state, j) { + struct drm_crtc *plane_crtc = plane_state->crtc; + struct drm_framebuffer *fb = plane_state->fb; + bool pflip_needed; + struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state); + + /*TODO Implement atomic check for cursor plane */ + if (plane->type == DRM_PLANE_TYPE_CURSOR) + continue; + + if (!fb || !plane_crtc || crtc != plane_crtc || !crtc_state->active) + continue; + + WARN_ON(!new_acrtc_state->stream); + + pflip_needed = !state->allow_modeset; + if (!pflip_needed) { + struct dc_surface *surface; + + surface = dc_create_surface(dc); + + ret = fill_plane_attributes( + plane_crtc->dev->dev_private, + surface, + plane_state, + crtc_state, + false); + if (ret) + goto fail; + + + if (dm_plane_state->surface) + dc_surface_release(dm_plane_state->surface); + + dm_plane_state->surface = surface; + + add_val_sets_surface(set, + set_count, + new_acrtc_state->stream, + surface); + + lock_and_validation_needed = true; + } + } + } + + /* Run this here since we want to validate the streams we created */ + ret = drm_atomic_helper_check_planes(dev, state); + if (ret) + goto fail; + + /* + * For full updates case when + * removing/adding/updating streams on once CRTC while flipping + * on another CRTC, + * acquiring global lock will guarantee that any such full + * update commit + * will wait for completion of any outstanding flip using DRMs + * synchronization events. + */ + + if (lock_and_validation_needed) { + + ret = do_aquire_global_lock(dev, state); + if (ret) + goto fail; + WARN_ON(dm_state->context); + dm_state->context = dc_get_validate_context(dc, set, set_count); + if (!dm_state->context) { + ret = -EINVAL; + goto fail; + } + } + + /* Must be success */ + WARN_ON(ret); + return ret; + +fail: + if (ret == -EDEADLK) + DRM_DEBUG_KMS("Atomic check stopped due to to deadlock.\n"); + else if (ret == -EINTR || ret == -EAGAIN || ret == -ERESTARTSYS) + DRM_DEBUG_KMS("Atomic check stopped due to to signal.\n"); + else + DRM_ERROR("Atomic check failed with err: %d .\n", ret); + + return ret; +} + +static bool is_dp_capable_without_timing_msa( + struct dc *dc, + struct amdgpu_connector *amdgpu_connector) +{ + uint8_t dpcd_data; + bool capable = false; + + if (amdgpu_connector->dc_link && + dm_helpers_dp_read_dpcd( + NULL, + amdgpu_connector->dc_link, + DP_DOWN_STREAM_PORT_COUNT, + &dpcd_data, + sizeof(dpcd_data))) { + capable = (dpcd_data & DP_MSA_TIMING_PAR_IGNORED) ? true:false; + } + + return capable; +} +void amdgpu_dm_add_sink_to_freesync_module( + struct drm_connector *connector, + struct edid *edid) +{ + int i; + uint64_t val_capable; + bool edid_check_required; + struct detailed_timing *timing; + struct detailed_non_pixel *data; + struct detailed_data_monitor_range *range; + struct amdgpu_connector *amdgpu_connector = + to_amdgpu_connector(connector); + + struct drm_device *dev = connector->dev; + struct amdgpu_device *adev = dev->dev_private; + edid_check_required = false; + if (!amdgpu_connector->dc_sink) { + DRM_ERROR("dc_sink NULL, could not add free_sync module.\n"); + return; + } + if (!adev->dm.freesync_module) + return; + /* + * if edid non zero restrict freesync only for dp and edp + */ + if (edid) { + if (amdgpu_connector->dc_sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT + || amdgpu_connector->dc_sink->sink_signal == SIGNAL_TYPE_EDP) { + edid_check_required = is_dp_capable_without_timing_msa( + adev->dm.dc, + amdgpu_connector); + } + } + val_capable = 0; + if (edid_check_required == true && (edid->version > 1 || + (edid->version == 1 && edid->revision > 1))) { + for (i = 0; i < 4; i++) { + + timing = &edid->detailed_timings[i]; + data = &timing->data.other_data; + range = &data->data.range; + /* + * Check if monitor has continuous frequency mode + */ + if (data->type != EDID_DETAIL_MONITOR_RANGE) + continue; + /* + * Check for flag range limits only. If flag == 1 then + * no additional timing information provided. + * Default GTF, GTF Secondary curve and CVT are not + * supported + */ + if (range->flags != 1) + continue; + + amdgpu_connector->min_vfreq = range->min_vfreq; + amdgpu_connector->max_vfreq = range->max_vfreq; + amdgpu_connector->pixel_clock_mhz = + range->pixel_clock_mhz * 10; + break; + } + + if (amdgpu_connector->max_vfreq - + amdgpu_connector->min_vfreq > 10) { + amdgpu_connector->caps.supported = true; + amdgpu_connector->caps.min_refresh_in_micro_hz = + amdgpu_connector->min_vfreq * 1000000; + amdgpu_connector->caps.max_refresh_in_micro_hz = + amdgpu_connector->max_vfreq * 1000000; + val_capable = 1; + } + } + + /* + * TODO figure out how to notify user-mode or DRM of freesync caps + * once we figure out how to deal with freesync in an upstreamable + * fashion + */ + +} + +void amdgpu_dm_remove_sink_from_freesync_module( + struct drm_connector *connector) +{ + /* + * TODO fill in once we figure out how to deal with freesync in + * an upstreamable fashion + */ +} 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 ee69179636a1..16b2e0849a65 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -26,9 +26,9 @@ #ifndef __AMDGPU_DM_H__ #define __AMDGPU_DM_H__ -/* -#include "linux/switch.h" -*/ +#include +#include +#include "dc.h" /* * This file contains the definition for amdgpu_display_manager @@ -173,4 +173,106 @@ struct amdgpu_connector *amdgpu_dm_find_first_crct_matching_connector( struct drm_crtc *crtc, bool from_state_var); + +struct amdgpu_framebuffer; +struct amdgpu_display_manager; +struct dc_validation_set; +struct dc_surface; +/* TODO rename to dc_stream_state */ +struct dc_stream; + + +struct dm_plane_state { + struct drm_plane_state base; + struct dc_surface *surface; +}; + +struct dm_crtc_state { + struct drm_crtc_state base; + struct dc_stream *stream; +}; + +#define to_dm_crtc_state(x) container_of(x, struct dm_crtc_state, base) + +struct dm_atomic_state { + struct drm_atomic_state base; + + struct validate_context *context; +}; + +#define to_dm_atomic_state(x) container_of(x, struct dm_atomic_state, base) + + +/*TODO Jodan Hersen use the one in amdgpu_dm*/ +int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, + struct amdgpu_plane *aplane, + unsigned long possible_crtcs); +int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, + struct drm_plane *plane, + uint32_t link_index); +int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm, + struct amdgpu_connector *amdgpu_connector, + uint32_t link_index, + struct amdgpu_encoder *amdgpu_encoder); +int amdgpu_dm_encoder_init( + struct drm_device *dev, + struct amdgpu_encoder *aencoder, + uint32_t link_index); + +void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc); +void amdgpu_dm_connector_destroy(struct drm_connector *connector); +void amdgpu_dm_encoder_destroy(struct drm_encoder *encoder); + +int amdgpu_dm_connector_get_modes(struct drm_connector *connector); + +int amdgpu_dm_atomic_commit( + struct drm_device *dev, + struct drm_atomic_state *state, + bool nonblock); + +void amdgpu_dm_atomic_commit_tail( + struct drm_atomic_state *state); + +int amdgpu_dm_atomic_check(struct drm_device *dev, + struct drm_atomic_state *state); + +void amdgpu_dm_connector_funcs_reset(struct drm_connector *connector); +struct drm_connector_state *amdgpu_dm_connector_atomic_duplicate_state( + struct drm_connector *connector); +int amdgpu_dm_connector_atomic_set_property( + struct drm_connector *connector, + struct drm_connector_state *state, + struct drm_property *property, + uint64_t val); + +int amdgpu_dm_connector_atomic_get_property( + struct drm_connector *connector, + const struct drm_connector_state *state, + struct drm_property *property, + uint64_t *val); + +int amdgpu_dm_get_encoder_crtc_mask(struct amdgpu_device *adev); + +void amdgpu_dm_connector_init_helper( + struct amdgpu_display_manager *dm, + struct amdgpu_connector *aconnector, + int connector_type, + struct dc_link *link, + int link_index); + +int amdgpu_dm_connector_mode_valid( + struct drm_connector *connector, + struct drm_display_mode *mode); + +void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector *connector); + +void amdgpu_dm_add_sink_to_freesync_module( + struct drm_connector *connector, + struct edid *edid); + +void amdgpu_dm_remove_sink_from_freesync_module( + struct drm_connector *connector); + +extern const struct drm_encoder_helper_funcs amdgpu_dm_encoder_helper_funcs; + #endif /* __AMDGPU_DM_H__ */ diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index 6c19a07709df..0a615583de63 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -38,7 +38,6 @@ #include "dc.h" #include "amdgpu_dm.h" #include "amdgpu_dm_irq.h" -#include "amdgpu_dm_types.h" #include "dm_helpers.h" diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index ec91a52c002f..82e4d49fb184 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -27,7 +27,7 @@ #include #include "dm_services.h" #include "amdgpu.h" -#include "amdgpu_dm_types.h" +#include "amdgpu_dm.h" #include "amdgpu_dm_mst_types.h" #include "dc.h" diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c index a8a53b85905a..3348e90a0a37 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c @@ -33,7 +33,6 @@ #include "amdgpu.h" #include "amdgpu_dm.h" #include "amdgpu_dm_irq.h" -#include "amdgpu_dm_types.h" #include "amdgpu_pm.h" /****************************************************************************** diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c deleted file mode 100644 index 80d4e2670cc2..000000000000 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ /dev/null @@ -1,3286 +0,0 @@ -/* - * Copyright 2012-13 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include -#include - -#include -#include -#include -#include -#include - - -#include "amdgpu.h" -#include "amdgpu_pm.h" -#include "dm_helpers.h" -#include "dm_services_types.h" - -// We need to #undef FRAME_SIZE and DEPRECATED because they conflict -// with ptrace-abi.h's #define's of them. -#undef FRAME_SIZE -#undef DEPRECATED - -#include "dc.h" - -#include "amdgpu_dm_types.h" -#include "amdgpu_dm_mst_types.h" - -#include "modules/inc/mod_freesync.h" - -#include "i2caux_interface.h" - -struct dm_connector_state { - struct drm_connector_state base; - - enum amdgpu_rmx_type scaling; - uint8_t underscan_vborder; - uint8_t underscan_hborder; - bool underscan_enable; -}; - -#define to_dm_connector_state(x)\ - container_of((x), struct dm_connector_state, base) - -static bool modeset_required(struct drm_crtc_state *crtc_state) -{ - if (!drm_atomic_crtc_needs_modeset(crtc_state)) - return false; - - if (!crtc_state->enable) - return false; - - return crtc_state->active; -} - -static bool modereset_required(struct drm_crtc_state *crtc_state) -{ - if (!drm_atomic_crtc_needs_modeset(crtc_state)) - return false; - - return !crtc_state->enable || !crtc_state->active; -} - -void amdgpu_dm_encoder_destroy(struct drm_encoder *encoder) -{ - drm_encoder_cleanup(encoder); - kfree(encoder); -} - -static const struct drm_encoder_funcs amdgpu_dm_encoder_funcs = { - .destroy = amdgpu_dm_encoder_destroy, -}; - -static void dm_set_cursor( - struct amdgpu_crtc *amdgpu_crtc, - uint64_t gpu_addr, - uint32_t width, - uint32_t height) -{ - struct dc_cursor_attributes attributes; - struct dc_cursor_position position; - struct drm_crtc *crtc = &amdgpu_crtc->base; - int x, y; - int xorigin = 0, yorigin = 0; - struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state); - - amdgpu_crtc->cursor_width = width; - amdgpu_crtc->cursor_height = height; - - attributes.address.high_part = upper_32_bits(gpu_addr); - attributes.address.low_part = lower_32_bits(gpu_addr); - attributes.width = width; - attributes.height = height; - attributes.color_format = CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA; - attributes.rotation_angle = 0; - attributes.attribute_flags.value = 0; - - attributes.pitch = attributes.width; - - x = amdgpu_crtc->cursor_x; - y = amdgpu_crtc->cursor_y; - - /* avivo cursor are offset into the total surface */ - x += crtc->primary->state->src_x >> 16; - y += crtc->primary->state->src_y >> 16; - - if (x < 0) { - xorigin = min(-x, amdgpu_crtc->max_cursor_width - 1); - x = 0; - } - if (y < 0) { - yorigin = min(-y, amdgpu_crtc->max_cursor_height - 1); - y = 0; - } - - position.enable = true; - position.x = x; - position.y = y; - - position.x_hotspot = xorigin; - position.y_hotspot = yorigin; - - if (!dc_stream_set_cursor_attributes( - acrtc_state->stream, - &attributes)) { - DRM_ERROR("DC failed to set cursor attributes\n"); - } - - if (!dc_stream_set_cursor_position( - acrtc_state->stream, - &position)) { - DRM_ERROR("DC failed to set cursor position\n"); - } -} - -static int dm_crtc_cursor_set( - struct drm_crtc *crtc, - uint64_t address, - uint32_t width, - uint32_t height) -{ - struct dc_cursor_position position; - struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state); - - int ret; - - struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); - ret = EINVAL; - - DRM_DEBUG_KMS( - "%s: crtc_id=%d with size %d to %d \n", - __func__, - amdgpu_crtc->crtc_id, - width, - height); - - if (!address) { - /* turn off cursor */ - position.enable = false; - position.x = 0; - position.y = 0; - - if (acrtc_state->stream) { - /*set cursor visible false*/ - dc_stream_set_cursor_position( - acrtc_state->stream, - &position); - } - goto release; - - } - - if ((width > amdgpu_crtc->max_cursor_width) || - (height > amdgpu_crtc->max_cursor_height)) { - DRM_ERROR( - "%s: bad cursor width or height %d x %d\n", - __func__, - width, - height); - goto release; - } - - /*program new cursor bo to hardware*/ - dm_set_cursor(amdgpu_crtc, address, width, height); - -release: - return ret; - -} - -static int dm_crtc_cursor_move(struct drm_crtc *crtc, - int x, int y) -{ - struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); - int xorigin = 0, yorigin = 0; - struct dc_cursor_position position; - struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state); - - amdgpu_crtc->cursor_x = x; - amdgpu_crtc->cursor_y = y; - - /* avivo cursor are offset into the total surface */ - x += crtc->primary->state->src_x >> 16; - y += crtc->primary->state->src_y >> 16; - - /* - * TODO: for cursor debugging unguard the following - */ -#if 0 - DRM_DEBUG_KMS( - "%s: x %d y %d c->x %d c->y %d\n", - __func__, - x, - y, - crtc->x, - crtc->y); -#endif - - if (x < 0) { - xorigin = min(-x, amdgpu_crtc->max_cursor_width - 1); - x = 0; - } - if (y < 0) { - yorigin = min(-y, amdgpu_crtc->max_cursor_height - 1); - y = 0; - } - - position.enable = true; - position.x = x; - position.y = y; - - position.x_hotspot = xorigin; - position.y_hotspot = yorigin; - - if (acrtc_state->stream) { - if (!dc_stream_set_cursor_position( - acrtc_state->stream, - &position)) { - DRM_ERROR("DC failed to set cursor position\n"); - return -EINVAL; - } - } - - return 0; -} - -static bool fill_rects_from_plane_state( - const struct drm_plane_state *state, - struct dc_surface *surface) -{ - surface->src_rect.x = state->src_x >> 16; - surface->src_rect.y = state->src_y >> 16; - /*we ignore for now mantissa and do not to deal with floating pixels :(*/ - surface->src_rect.width = state->src_w >> 16; - - if (surface->src_rect.width == 0) - return false; - - surface->src_rect.height = state->src_h >> 16; - if (surface->src_rect.height == 0) - return false; - - surface->dst_rect.x = state->crtc_x; - surface->dst_rect.y = state->crtc_y; - - if (state->crtc_w == 0) - return false; - - surface->dst_rect.width = state->crtc_w; - - if (state->crtc_h == 0) - return false; - - surface->dst_rect.height = state->crtc_h; - - surface->clip_rect = surface->dst_rect; - - switch (state->rotation & DRM_MODE_ROTATE_MASK) { - case DRM_MODE_ROTATE_0: - surface->rotation = ROTATION_ANGLE_0; - break; - case DRM_MODE_ROTATE_90: - surface->rotation = ROTATION_ANGLE_90; - break; - case DRM_MODE_ROTATE_180: - surface->rotation = ROTATION_ANGLE_180; - break; - case DRM_MODE_ROTATE_270: - surface->rotation = ROTATION_ANGLE_270; - break; - default: - surface->rotation = ROTATION_ANGLE_0; - break; - } - - return true; -} -static int get_fb_info( - const struct amdgpu_framebuffer *amdgpu_fb, - uint64_t *tiling_flags, - uint64_t *fb_location) -{ - struct amdgpu_bo *rbo = gem_to_amdgpu_bo(amdgpu_fb->obj); - int r = amdgpu_bo_reserve(rbo, false); - if (unlikely(r)) { - DRM_ERROR("Unable to reserve buffer\n"); - return r; - } - - if (fb_location) - *fb_location = amdgpu_bo_gpu_offset(rbo); - - if (tiling_flags) - amdgpu_bo_get_tiling_flags(rbo, tiling_flags); - - amdgpu_bo_unreserve(rbo); - - return r; -} - -static int fill_plane_attributes_from_fb( - struct amdgpu_device *adev, - struct dc_surface *surface, - const struct amdgpu_framebuffer *amdgpu_fb, bool addReq) -{ - uint64_t tiling_flags; - uint64_t fb_location = 0; - unsigned int awidth; - const struct drm_framebuffer *fb = &amdgpu_fb->base; - int ret = 0; - struct drm_format_name_buf format_name; - - ret = get_fb_info( - amdgpu_fb, - &tiling_flags, - addReq == true ? &fb_location:NULL); - - if (ret) - return ret; - - switch (fb->format->format) { - case DRM_FORMAT_C8: - surface->format = SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS; - break; - case DRM_FORMAT_RGB565: - surface->format = SURFACE_PIXEL_FORMAT_GRPH_RGB565; - break; - case DRM_FORMAT_XRGB8888: - case DRM_FORMAT_ARGB8888: - surface->format = SURFACE_PIXEL_FORMAT_GRPH_ARGB8888; - break; - case DRM_FORMAT_XRGB2101010: - case DRM_FORMAT_ARGB2101010: - surface->format = SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010; - break; - case DRM_FORMAT_XBGR2101010: - case DRM_FORMAT_ABGR2101010: - surface->format = SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010; - break; - case DRM_FORMAT_NV21: - surface->format = SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr; - break; - case DRM_FORMAT_NV12: - surface->format = SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb; - break; - default: - DRM_ERROR("Unsupported screen format %s\n", - drm_get_format_name(fb->format->format, &format_name)); - return -EINVAL; - } - - if (surface->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) { - surface->address.type = PLN_ADDR_TYPE_GRAPHICS; - surface->address.grph.addr.low_part = lower_32_bits(fb_location); - surface->address.grph.addr.high_part = upper_32_bits(fb_location); - surface->plane_size.grph.surface_size.x = 0; - surface->plane_size.grph.surface_size.y = 0; - surface->plane_size.grph.surface_size.width = fb->width; - surface->plane_size.grph.surface_size.height = fb->height; - surface->plane_size.grph.surface_pitch = - fb->pitches[0] / fb->format->cpp[0]; - /* TODO: unhardcode */ - surface->color_space = COLOR_SPACE_SRGB; - - } else { - awidth = ALIGN(fb->width, 64); - surface->address.type = PLN_ADDR_TYPE_VIDEO_PROGRESSIVE; - surface->address.video_progressive.luma_addr.low_part - = lower_32_bits(fb_location); - surface->address.video_progressive.chroma_addr.low_part - = lower_32_bits(fb_location) + - (awidth * fb->height); - surface->plane_size.video.luma_size.x = 0; - surface->plane_size.video.luma_size.y = 0; - surface->plane_size.video.luma_size.width = awidth; - surface->plane_size.video.luma_size.height = fb->height; - /* TODO: unhardcode */ - surface->plane_size.video.luma_pitch = awidth; - - surface->plane_size.video.chroma_size.x = 0; - surface->plane_size.video.chroma_size.y = 0; - surface->plane_size.video.chroma_size.width = awidth; - surface->plane_size.video.chroma_size.height = fb->height; - surface->plane_size.video.chroma_pitch = awidth / 2; - - /* TODO: unhardcode */ - surface->color_space = COLOR_SPACE_YCBCR709; - } - - memset(&surface->tiling_info, 0, sizeof(surface->tiling_info)); - - /* Fill GFX params */ - if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE) == DC_ARRAY_2D_TILED_THIN1) - { - unsigned bankw, bankh, mtaspect, tile_split, num_banks; - - bankw = AMDGPU_TILING_GET(tiling_flags, BANK_WIDTH); - bankh = AMDGPU_TILING_GET(tiling_flags, BANK_HEIGHT); - mtaspect = AMDGPU_TILING_GET(tiling_flags, MACRO_TILE_ASPECT); - tile_split = AMDGPU_TILING_GET(tiling_flags, TILE_SPLIT); - num_banks = AMDGPU_TILING_GET(tiling_flags, NUM_BANKS); - - /* XXX fix me for VI */ - surface->tiling_info.gfx8.num_banks = num_banks; - surface->tiling_info.gfx8.array_mode = - DC_ARRAY_2D_TILED_THIN1; - surface->tiling_info.gfx8.tile_split = tile_split; - surface->tiling_info.gfx8.bank_width = bankw; - surface->tiling_info.gfx8.bank_height = bankh; - surface->tiling_info.gfx8.tile_aspect = mtaspect; - surface->tiling_info.gfx8.tile_mode = - DC_ADDR_SURF_MICRO_TILING_DISPLAY; - } else if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE) - == DC_ARRAY_1D_TILED_THIN1) { - surface->tiling_info.gfx8.array_mode = DC_ARRAY_1D_TILED_THIN1; - } - - surface->tiling_info.gfx8.pipe_config = - AMDGPU_TILING_GET(tiling_flags, PIPE_CONFIG); - - if (adev->asic_type == CHIP_VEGA10 || - adev->asic_type == CHIP_RAVEN) { - /* Fill GFX9 params */ - surface->tiling_info.gfx9.num_pipes = - adev->gfx.config.gb_addr_config_fields.num_pipes; - surface->tiling_info.gfx9.num_banks = - adev->gfx.config.gb_addr_config_fields.num_banks; - surface->tiling_info.gfx9.pipe_interleave = - adev->gfx.config.gb_addr_config_fields.pipe_interleave_size; - surface->tiling_info.gfx9.num_shader_engines = - adev->gfx.config.gb_addr_config_fields.num_se; - surface->tiling_info.gfx9.max_compressed_frags = - adev->gfx.config.gb_addr_config_fields.max_compress_frags; - surface->tiling_info.gfx9.num_rb_per_se = - adev->gfx.config.gb_addr_config_fields.num_rb_per_se; - surface->tiling_info.gfx9.swizzle = - AMDGPU_TILING_GET(tiling_flags, SWIZZLE_MODE); - surface->tiling_info.gfx9.shaderEnable = 1; - } - - surface->visible = true; - surface->scaling_quality.h_taps_c = 0; - surface->scaling_quality.v_taps_c = 0; - - /* is this needed? is surface zeroed at allocation? */ - surface->scaling_quality.h_taps = 0; - surface->scaling_quality.v_taps = 0; - surface->stereo_format = PLANE_STEREO_FORMAT_NONE; - - return ret; - -} - -#define NUM_OF_RAW_GAMMA_RAMP_RGB_256 256 - -static void fill_gamma_from_crtc_state( - const struct drm_crtc_state *crtc_state, - struct dc_surface *dc_surface) -{ - int i; - struct dc_gamma *gamma; - struct drm_color_lut *lut = (struct drm_color_lut *) crtc_state->gamma_lut->data; - - gamma = dc_create_gamma(); - - if (gamma == NULL) { - WARN_ON(1); - return; - } - - for (i = 0; i < NUM_OF_RAW_GAMMA_RAMP_RGB_256; i++) { - gamma->red[i] = lut[i].red; - gamma->green[i] = lut[i].green; - gamma->blue[i] = lut[i].blue; - } - - dc_surface->gamma_correction = gamma; -} - -static int fill_plane_attributes( - struct amdgpu_device *adev, - struct dc_surface *surface, - struct drm_plane_state *plane_state, - struct drm_crtc_state *crtc_state, - bool addrReq) -{ - const struct amdgpu_framebuffer *amdgpu_fb = - to_amdgpu_framebuffer(plane_state->fb); - const struct drm_crtc *crtc = plane_state->crtc; - struct dc_transfer_func *input_tf; - int ret = 0; - - if (!fill_rects_from_plane_state(plane_state, surface)) - return -EINVAL; - - ret = fill_plane_attributes_from_fb( - crtc->dev->dev_private, - surface, - amdgpu_fb, - addrReq); - - if (ret) - return ret; - - input_tf = dc_create_transfer_func(); - - if (input_tf == NULL) - return -ENOMEM; - - input_tf->type = TF_TYPE_PREDEFINED; - input_tf->tf = TRANSFER_FUNCTION_SRGB; - - surface->in_transfer_func = input_tf; - - /* In case of gamma set, update gamma value */ - if (crtc_state->gamma_lut) - fill_gamma_from_crtc_state(crtc_state, surface); - - return ret; -} - -/*****************************************************************************/ - -struct amdgpu_connector *aconnector_from_drm_crtc_id( - const struct drm_crtc *crtc) -{ - struct drm_device *dev = crtc->dev; - struct drm_connector *connector; - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - struct amdgpu_connector *aconnector; - - list_for_each_entry(connector, - &dev->mode_config.connector_list, head) { - - aconnector = to_amdgpu_connector(connector); - - if (aconnector->base.state->crtc != &acrtc->base) - continue; - - /* Found the connector */ - return aconnector; - } - - /* If we get here, not found. */ - return NULL; -} - -static void update_stream_scaling_settings( - const struct drm_display_mode *mode, - const struct dm_connector_state *dm_state, - struct dc_stream *stream) -{ - enum amdgpu_rmx_type rmx_type; - - struct rect src = { 0 }; /* viewport in composition space*/ - struct rect dst = { 0 }; /* stream addressable area */ - - /* no mode. nothing to be done */ - if (!mode) - return; - - /* Full screen scaling by default */ - src.width = mode->hdisplay; - src.height = mode->vdisplay; - dst.width = stream->timing.h_addressable; - dst.height = stream->timing.v_addressable; - - rmx_type = dm_state->scaling; - if (rmx_type == RMX_ASPECT || rmx_type == RMX_OFF) { - if (src.width * dst.height < - src.height * dst.width) { - /* height needs less upscaling/more downscaling */ - dst.width = src.width * - dst.height / src.height; - } else { - /* width needs less upscaling/more downscaling */ - dst.height = src.height * - dst.width / src.width; - } - } else if (rmx_type == RMX_CENTER) { - dst = src; - } - - dst.x = (stream->timing.h_addressable - dst.width) / 2; - dst.y = (stream->timing.v_addressable - dst.height) / 2; - - if (dm_state->underscan_enable) { - dst.x += dm_state->underscan_hborder / 2; - dst.y += dm_state->underscan_vborder / 2; - dst.width -= dm_state->underscan_hborder; - dst.height -= dm_state->underscan_vborder; - } - - stream->src = src; - stream->dst = dst; - - DRM_DEBUG_KMS("Destination Rectangle x:%d y:%d width:%d height:%d\n", - dst.x, dst.y, dst.width, dst.height); - -} - -static enum dc_color_depth convert_color_depth_from_display_info( - const struct drm_connector *connector) -{ - uint32_t bpc = connector->display_info.bpc; - - /* Limited color depth to 8bit - * TODO: Still need to handle deep color*/ - if (bpc > 8) - bpc = 8; - - switch (bpc) { - case 0: - /* Temporary Work around, DRM don't parse color depth for - * EDID revision before 1.4 - * TODO: Fix edid parsing - */ - return COLOR_DEPTH_888; - case 6: - return COLOR_DEPTH_666; - case 8: - return COLOR_DEPTH_888; - case 10: - return COLOR_DEPTH_101010; - case 12: - return COLOR_DEPTH_121212; - case 14: - return COLOR_DEPTH_141414; - case 16: - return COLOR_DEPTH_161616; - default: - return COLOR_DEPTH_UNDEFINED; - } -} - -static enum dc_aspect_ratio get_aspect_ratio( - const struct drm_display_mode *mode_in) -{ - int32_t width = mode_in->crtc_hdisplay * 9; - int32_t height = mode_in->crtc_vdisplay * 16; - if ((width - height) < 10 && (width - height) > -10) - return ASPECT_RATIO_16_9; - else - return ASPECT_RATIO_4_3; -} - -static enum dc_color_space get_output_color_space( - const struct dc_crtc_timing *dc_crtc_timing) -{ - enum dc_color_space color_space = COLOR_SPACE_SRGB; - - switch (dc_crtc_timing->pixel_encoding) { - case PIXEL_ENCODING_YCBCR422: - case PIXEL_ENCODING_YCBCR444: - case PIXEL_ENCODING_YCBCR420: - { - /* - * 27030khz is the separation point between HDTV and SDTV - * according to HDMI spec, we use YCbCr709 and YCbCr601 - * respectively - */ - if (dc_crtc_timing->pix_clk_khz > 27030) { - if (dc_crtc_timing->flags.Y_ONLY) - color_space = - COLOR_SPACE_YCBCR709_LIMITED; - else - color_space = COLOR_SPACE_YCBCR709; - } else { - if (dc_crtc_timing->flags.Y_ONLY) - color_space = - COLOR_SPACE_YCBCR601_LIMITED; - else - color_space = COLOR_SPACE_YCBCR601; - } - - } - break; - case PIXEL_ENCODING_RGB: - color_space = COLOR_SPACE_SRGB; - break; - - default: - WARN_ON(1); - break; - } - - return color_space; -} - -/*****************************************************************************/ - -static void fill_stream_properties_from_drm_display_mode( - struct dc_stream *stream, - const struct drm_display_mode *mode_in, - const struct drm_connector *connector) -{ - struct dc_crtc_timing *timing_out = &stream->timing; - memset(timing_out, 0, sizeof(struct dc_crtc_timing)); - - timing_out->h_border_left = 0; - timing_out->h_border_right = 0; - timing_out->v_border_top = 0; - timing_out->v_border_bottom = 0; - /* TODO: un-hardcode */ - - if ((connector->display_info.color_formats & DRM_COLOR_FORMAT_YCRCB444) - && stream->sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A) - timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR444; - else - timing_out->pixel_encoding = PIXEL_ENCODING_RGB; - - timing_out->timing_3d_format = TIMING_3D_FORMAT_NONE; - timing_out->display_color_depth = convert_color_depth_from_display_info( - connector); - timing_out->scan_type = SCANNING_TYPE_NODATA; - timing_out->hdmi_vic = 0; - timing_out->vic = drm_match_cea_mode(mode_in); - - timing_out->h_addressable = mode_in->crtc_hdisplay; - timing_out->h_total = mode_in->crtc_htotal; - timing_out->h_sync_width = - mode_in->crtc_hsync_end - mode_in->crtc_hsync_start; - timing_out->h_front_porch = - mode_in->crtc_hsync_start - mode_in->crtc_hdisplay; - timing_out->v_total = mode_in->crtc_vtotal; - timing_out->v_addressable = mode_in->crtc_vdisplay; - timing_out->v_front_porch = - mode_in->crtc_vsync_start - mode_in->crtc_vdisplay; - timing_out->v_sync_width = - mode_in->crtc_vsync_end - mode_in->crtc_vsync_start; - timing_out->pix_clk_khz = mode_in->crtc_clock; - timing_out->aspect_ratio = get_aspect_ratio(mode_in); - if (mode_in->flags & DRM_MODE_FLAG_PHSYNC) - timing_out->flags.HSYNC_POSITIVE_POLARITY = 1; - if (mode_in->flags & DRM_MODE_FLAG_PVSYNC) - timing_out->flags.VSYNC_POSITIVE_POLARITY = 1; - - stream->output_color_space = get_output_color_space(timing_out); - - { - struct dc_transfer_func *tf = dc_create_transfer_func(); - tf->type = TF_TYPE_PREDEFINED; - tf->tf = TRANSFER_FUNCTION_SRGB; - stream->out_transfer_func = tf; - } -} - -static void fill_audio_info( - struct audio_info *audio_info, - const struct drm_connector *drm_connector, - const struct dc_sink *dc_sink) -{ - int i = 0; - int cea_revision = 0; - const struct dc_edid_caps *edid_caps = &dc_sink->edid_caps; - - audio_info->manufacture_id = edid_caps->manufacturer_id; - audio_info->product_id = edid_caps->product_id; - - cea_revision = drm_connector->display_info.cea_rev; - - while (i < AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS && - edid_caps->display_name[i]) { - audio_info->display_name[i] = edid_caps->display_name[i]; - i++; - } - - if(cea_revision >= 3) { - audio_info->mode_count = edid_caps->audio_mode_count; - - for (i = 0; i < audio_info->mode_count; ++i) { - audio_info->modes[i].format_code = - (enum audio_format_code) - (edid_caps->audio_modes[i].format_code); - audio_info->modes[i].channel_count = - edid_caps->audio_modes[i].channel_count; - audio_info->modes[i].sample_rates.all = - edid_caps->audio_modes[i].sample_rate; - audio_info->modes[i].sample_size = - edid_caps->audio_modes[i].sample_size; - } - } - - audio_info->flags.all = edid_caps->speaker_flags; - - /* TODO: We only check for the progressive mode, check for interlace mode too */ - if(drm_connector->latency_present[0]) { - audio_info->video_latency = drm_connector->video_latency[0]; - audio_info->audio_latency = drm_connector->audio_latency[0]; - } - - /* TODO: For DP, video and audio latency should be calculated from DPCD caps */ - -} - -static void copy_crtc_timing_for_drm_display_mode( - const struct drm_display_mode *src_mode, - struct drm_display_mode *dst_mode) -{ - dst_mode->crtc_hdisplay = src_mode->crtc_hdisplay; - dst_mode->crtc_vdisplay = src_mode->crtc_vdisplay; - dst_mode->crtc_clock = src_mode->crtc_clock; - dst_mode->crtc_hblank_start = src_mode->crtc_hblank_start; - dst_mode->crtc_hblank_end = src_mode->crtc_hblank_end; - dst_mode->crtc_hsync_start= src_mode->crtc_hsync_start; - dst_mode->crtc_hsync_end = src_mode->crtc_hsync_end; - dst_mode->crtc_htotal = src_mode->crtc_htotal; - dst_mode->crtc_hskew = src_mode->crtc_hskew; - dst_mode->crtc_vblank_start = src_mode->crtc_vblank_start; - dst_mode->crtc_vblank_end = src_mode->crtc_vblank_end; - dst_mode->crtc_vsync_start = src_mode->crtc_vsync_start; - dst_mode->crtc_vsync_end = src_mode->crtc_vsync_end; - dst_mode->crtc_vtotal = src_mode->crtc_vtotal; -} - -static void decide_crtc_timing_for_drm_display_mode( - struct drm_display_mode *drm_mode, - const struct drm_display_mode *native_mode, - bool scale_enabled) -{ - if (scale_enabled) { - copy_crtc_timing_for_drm_display_mode(native_mode, drm_mode); - } else if (native_mode->clock == drm_mode->clock && - native_mode->htotal == drm_mode->htotal && - native_mode->vtotal == drm_mode->vtotal) { - copy_crtc_timing_for_drm_display_mode(native_mode, drm_mode); - } else { - /* no scaling nor amdgpu inserted, no need to patch */ - } -} - -static struct dc_stream *create_stream_for_sink( - struct amdgpu_connector *aconnector, - const struct drm_display_mode *drm_mode, - const struct dm_connector_state *dm_state) -{ - struct drm_display_mode *preferred_mode = NULL; - const struct drm_connector *drm_connector; - struct dc_stream *stream = NULL; - struct drm_display_mode mode = *drm_mode; - bool native_mode_found = false; - - if (NULL == aconnector) { - DRM_ERROR("aconnector is NULL!\n"); - goto drm_connector_null; - } - - if (NULL == dm_state) { - DRM_ERROR("dm_state is NULL!\n"); - goto dm_state_null; - } - - drm_connector = &aconnector->base; - stream = dc_create_stream_for_sink(aconnector->dc_sink); - - if (NULL == stream) { - DRM_ERROR("Failed to create stream for sink!\n"); - goto stream_create_fail; - } - - list_for_each_entry(preferred_mode, &aconnector->base.modes, head) { - /* Search for preferred mode */ - if (preferred_mode->type & DRM_MODE_TYPE_PREFERRED) { - native_mode_found = true; - break; - } - } - if (!native_mode_found) - preferred_mode = list_first_entry_or_null( - &aconnector->base.modes, - struct drm_display_mode, - head); - - if (NULL == preferred_mode) { - /* This may not be an error, the use case is when we we have no - * usermode calls to reset and set mode upon hotplug. In this - * case, we call set mode ourselves to restore the previous mode - * and the modelist may not be filled in in time. - */ - DRM_INFO("No preferred mode found\n"); - } else { - decide_crtc_timing_for_drm_display_mode( - &mode, preferred_mode, - dm_state->scaling != RMX_OFF); - } - - fill_stream_properties_from_drm_display_mode(stream, - &mode, &aconnector->base); - update_stream_scaling_settings(&mode, dm_state, stream); - - fill_audio_info( - &stream->audio_info, - drm_connector, - aconnector->dc_sink); - -stream_create_fail: -dm_state_null: -drm_connector_null: - return stream; -} - -void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc) -{ - drm_crtc_cleanup(crtc); - kfree(crtc); -} - -static void dm_crtc_destroy_state(struct drm_crtc *crtc, - struct drm_crtc_state *state) -{ - struct dm_crtc_state *cur = to_dm_crtc_state(state); - - /* TODO Destroy dc_stream objects are stream object is flattened */ - if (cur->stream) - dc_stream_release(cur->stream); - - - __drm_atomic_helper_crtc_destroy_state(state); - - - kfree(state); -} - -static void dm_crtc_reset_state(struct drm_crtc *crtc) -{ - struct dm_crtc_state *state; - - if (crtc->state) - dm_crtc_destroy_state(crtc, crtc->state); - - state = kzalloc(sizeof(*state), GFP_KERNEL); - if (WARN_ON(!state)) - return; - - crtc->state = &state->base; - crtc->state->crtc = crtc; - -} - -static struct drm_crtc_state * -dm_crtc_duplicate_state(struct drm_crtc *crtc) -{ - struct dm_crtc_state *state, *cur; - - cur = to_dm_crtc_state(crtc->state); - - if (WARN_ON(!crtc->state)) - return NULL; - - state = dm_alloc(sizeof(*state)); - - __drm_atomic_helper_crtc_duplicate_state(crtc, &state->base); - - if (cur->stream) { - state->stream = cur->stream; - dc_stream_retain(state->stream); - } - - /* TODO Duplicate dc_stream after objects are stream object is flattened */ - - return &state->base; -} - -/* Implemented only the options currently availible for the driver */ -static const struct drm_crtc_funcs amdgpu_dm_crtc_funcs = { - .reset = dm_crtc_reset_state, - .destroy = amdgpu_dm_crtc_destroy, - .gamma_set = drm_atomic_helper_legacy_gamma_set, - .set_config = drm_atomic_helper_set_config, - .page_flip = drm_atomic_helper_page_flip, - .atomic_duplicate_state = dm_crtc_duplicate_state, - .atomic_destroy_state = dm_crtc_destroy_state, -}; - -static enum drm_connector_status -amdgpu_dm_connector_detect(struct drm_connector *connector, bool force) -{ - bool connected; - struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); - - /* Notes: - * 1. This interface is NOT called in context of HPD irq. - * 2. This interface *is called* in context of user-mode ioctl. Which - * makes it a bad place for *any* MST-related activit. */ - - if (aconnector->base.force == DRM_FORCE_UNSPECIFIED) - connected = (aconnector->dc_sink != NULL); - else - connected = (aconnector->base.force == DRM_FORCE_ON); - - return (connected ? connector_status_connected : - connector_status_disconnected); -} - -int amdgpu_dm_connector_atomic_set_property( - struct drm_connector *connector, - struct drm_connector_state *connector_state, - struct drm_property *property, - uint64_t val) -{ - struct drm_device *dev = connector->dev; - struct amdgpu_device *adev = dev->dev_private; - struct dm_connector_state *dm_old_state = - to_dm_connector_state(connector->state); - struct dm_connector_state *dm_new_state = - to_dm_connector_state(connector_state); - - int ret = -EINVAL; - - if (property == dev->mode_config.scaling_mode_property) { - enum amdgpu_rmx_type rmx_type; - - switch (val) { - case DRM_MODE_SCALE_CENTER: - rmx_type = RMX_CENTER; - break; - case DRM_MODE_SCALE_ASPECT: - rmx_type = RMX_ASPECT; - break; - case DRM_MODE_SCALE_FULLSCREEN: - rmx_type = RMX_FULL; - break; - case DRM_MODE_SCALE_NONE: - default: - rmx_type = RMX_OFF; - break; - } - - if (dm_old_state->scaling == rmx_type) - return 0; - - dm_new_state->scaling = rmx_type; - ret = 0; - } else if (property == adev->mode_info.underscan_hborder_property) { - dm_new_state->underscan_hborder = val; - ret = 0; - } else if (property == adev->mode_info.underscan_vborder_property) { - dm_new_state->underscan_vborder = val; - ret = 0; - } else if (property == adev->mode_info.underscan_property) { - dm_new_state->underscan_enable = val; - ret = 0; - } - - return ret; -} - -int amdgpu_dm_connector_atomic_get_property( - struct drm_connector *connector, - const struct drm_connector_state *state, - struct drm_property *property, - uint64_t *val) -{ - struct drm_device *dev = connector->dev; - struct amdgpu_device *adev = dev->dev_private; - struct dm_connector_state *dm_state = - to_dm_connector_state(state); - int ret = -EINVAL; - - if (property == dev->mode_config.scaling_mode_property) { - switch (dm_state->scaling) { - case RMX_CENTER: - *val = DRM_MODE_SCALE_CENTER; - break; - case RMX_ASPECT: - *val = DRM_MODE_SCALE_ASPECT; - break; - case RMX_FULL: - *val = DRM_MODE_SCALE_FULLSCREEN; - break; - case RMX_OFF: - default: - *val = DRM_MODE_SCALE_NONE; - break; - } - ret = 0; - } else if (property == adev->mode_info.underscan_hborder_property) { - *val = dm_state->underscan_hborder; - ret = 0; - } else if (property == adev->mode_info.underscan_vborder_property) { - *val = dm_state->underscan_vborder; - ret = 0; - } else if (property == adev->mode_info.underscan_property) { - *val = dm_state->underscan_enable; - ret = 0; - } - return ret; -} - -void amdgpu_dm_connector_destroy(struct drm_connector *connector) -{ - struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); - const struct dc_link *link = aconnector->dc_link; - struct amdgpu_device *adev = connector->dev->dev_private; - struct amdgpu_display_manager *dm = &adev->dm; -#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\ - defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) - - if (link->connector_signal & (SIGNAL_TYPE_EDP | SIGNAL_TYPE_LVDS)) { - amdgpu_dm_register_backlight_device(dm); - - if (dm->backlight_dev) { - backlight_device_unregister(dm->backlight_dev); - dm->backlight_dev = NULL; - } - - } -#endif - drm_connector_unregister(connector); - drm_connector_cleanup(connector); - kfree(connector); -} - -void amdgpu_dm_connector_funcs_reset(struct drm_connector *connector) -{ - struct dm_connector_state *state = - to_dm_connector_state(connector->state); - - kfree(state); - - state = kzalloc(sizeof(*state), GFP_KERNEL); - - if (state) { - state->scaling = RMX_OFF; - state->underscan_enable = false; - state->underscan_hborder = 0; - state->underscan_vborder = 0; - - connector->state = &state->base; - connector->state->connector = connector; - } -} - -struct drm_connector_state *amdgpu_dm_connector_atomic_duplicate_state( - struct drm_connector *connector) -{ - struct dm_connector_state *state = - to_dm_connector_state(connector->state); - - struct dm_connector_state *new_state = - kmemdup(state, sizeof(*state), GFP_KERNEL); - - if (new_state) { - __drm_atomic_helper_connector_duplicate_state(connector, - &new_state->base); - return &new_state->base; - } - - return NULL; -} - -static const struct drm_connector_funcs amdgpu_dm_connector_funcs = { - .reset = amdgpu_dm_connector_funcs_reset, - .detect = amdgpu_dm_connector_detect, - .fill_modes = drm_helper_probe_single_connector_modes, - .destroy = amdgpu_dm_connector_destroy, - .atomic_duplicate_state = amdgpu_dm_connector_atomic_duplicate_state, - .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, - .atomic_set_property = amdgpu_dm_connector_atomic_set_property, - .atomic_get_property = amdgpu_dm_connector_atomic_get_property -}; - -static struct drm_encoder *best_encoder(struct drm_connector *connector) -{ - int enc_id = connector->encoder_ids[0]; - struct drm_mode_object *obj; - struct drm_encoder *encoder; - - DRM_DEBUG_KMS("Finding the best encoder\n"); - - /* pick the encoder ids */ - if (enc_id) { - obj = drm_mode_object_find(connector->dev, enc_id, DRM_MODE_OBJECT_ENCODER); - if (!obj) { - DRM_ERROR("Couldn't find a matching encoder for our connector\n"); - return NULL; - } - encoder = obj_to_encoder(obj); - return encoder; - } - DRM_ERROR("No encoder id\n"); - return NULL; -} - -static int get_modes(struct drm_connector *connector) -{ - return amdgpu_dm_connector_get_modes(connector); -} - -static void create_eml_sink(struct amdgpu_connector *aconnector) -{ - struct dc_sink_init_data init_params = { - .link = aconnector->dc_link, - .sink_signal = SIGNAL_TYPE_VIRTUAL - }; - struct edid *edid = (struct edid *) aconnector->base.edid_blob_ptr->data; - - if (!aconnector->base.edid_blob_ptr || - !aconnector->base.edid_blob_ptr->data) { - DRM_ERROR("No EDID firmware found on connector: %s ,forcing to OFF!\n", - aconnector->base.name); - - aconnector->base.force = DRM_FORCE_OFF; - aconnector->base.override_edid = false; - return; - } - - aconnector->edid = edid; - - aconnector->dc_em_sink = dc_link_add_remote_sink( - aconnector->dc_link, - (uint8_t *)edid, - (edid->extensions + 1) * EDID_LENGTH, - &init_params); - - if (aconnector->base.force - == DRM_FORCE_ON) - aconnector->dc_sink = aconnector->dc_link->local_sink ? - aconnector->dc_link->local_sink : - aconnector->dc_em_sink; -} - -static void handle_edid_mgmt(struct amdgpu_connector *aconnector) -{ - struct dc_link *link = (struct dc_link *)aconnector->dc_link; - - /* In case of headless boot with force on for DP managed connector - * Those settings have to be != 0 to get initial modeset - */ - if (link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT) { - link->verified_link_cap.lane_count = LANE_COUNT_FOUR; - link->verified_link_cap.link_rate = LINK_RATE_HIGH2; - } - - - aconnector->base.override_edid = true; - create_eml_sink(aconnector); -} - -int amdgpu_dm_connector_mode_valid( - struct drm_connector *connector, - struct drm_display_mode *mode) -{ - int result = MODE_ERROR; - struct dc_sink *dc_sink; - struct amdgpu_device *adev = connector->dev->dev_private; - /* TODO: Unhardcode stream count */ - struct dc_stream *stream; - struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); - - if ((mode->flags & DRM_MODE_FLAG_INTERLACE) || - (mode->flags & DRM_MODE_FLAG_DBLSCAN)) - return result; - - /* Only run this the first time mode_valid is called to initilialize - * EDID mgmt - */ - if (aconnector->base.force != DRM_FORCE_UNSPECIFIED && - !aconnector->dc_em_sink) - handle_edid_mgmt(aconnector); - - dc_sink = to_amdgpu_connector(connector)->dc_sink; - - if (NULL == dc_sink) { - DRM_ERROR("dc_sink is NULL!\n"); - goto fail; - } - - stream = dc_create_stream_for_sink(dc_sink); - if (NULL == stream) { - DRM_ERROR("Failed to create stream for sink!\n"); - goto fail; - } - - drm_mode_set_crtcinfo(mode, 0); - fill_stream_properties_from_drm_display_mode(stream, mode, connector); - - stream->src.width = mode->hdisplay; - stream->src.height = mode->vdisplay; - stream->dst = stream->src; - - if (dc_validate_stream(adev->dm.dc, stream)) - result = MODE_OK; - - dc_stream_release(stream); - -fail: - /* TODO: error handling*/ - return result; -} - -static const struct drm_connector_helper_funcs -amdgpu_dm_connector_helper_funcs = { - /* - * If hotplug a second bigger display in FB Con mode, bigger resolution - * modes will be filtered by drm_mode_validate_size(), and those modes - * is missing after user start lightdm. So we need to renew modes list. - * in get_modes call back, not just return the modes count - */ - .get_modes = get_modes, - .mode_valid = amdgpu_dm_connector_mode_valid, - .best_encoder = best_encoder -}; - -static void dm_crtc_helper_disable(struct drm_crtc *crtc) -{ -} - -static int dm_crtc_helper_atomic_check( - struct drm_crtc *crtc, - struct drm_crtc_state *state) -{ - struct amdgpu_device *adev = crtc->dev->dev_private; - struct dc *dc = adev->dm.dc; - struct dm_crtc_state *dm_crtc_state = to_dm_crtc_state(state); - int ret = -EINVAL; - - if (unlikely(!dm_crtc_state->stream && modeset_required(state))) { - WARN_ON(1); - return ret; - } - - /* In some use cases, like reset, no stream is attached */ - if (!dm_crtc_state->stream) - return 0; - - if (dc_validate_stream(dc, dm_crtc_state->stream)) - return 0; - - return ret; -} - -static bool dm_crtc_helper_mode_fixup( - struct drm_crtc *crtc, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - return true; -} - -static const struct drm_crtc_helper_funcs amdgpu_dm_crtc_helper_funcs = { - .disable = dm_crtc_helper_disable, - .atomic_check = dm_crtc_helper_atomic_check, - .mode_fixup = dm_crtc_helper_mode_fixup -}; - -static void dm_encoder_helper_disable(struct drm_encoder *encoder) -{ - -} - -static int dm_encoder_helper_atomic_check( - struct drm_encoder *encoder, - struct drm_crtc_state *crtc_state, - struct drm_connector_state *conn_state) -{ - return 0; -} - -const struct drm_encoder_helper_funcs amdgpu_dm_encoder_helper_funcs = { - .disable = dm_encoder_helper_disable, - .atomic_check = dm_encoder_helper_atomic_check -}; - -static void dm_drm_plane_reset(struct drm_plane *plane) -{ - struct dm_plane_state *amdgpu_state = NULL; - - if (plane->state) - plane->funcs->atomic_destroy_state(plane, plane->state); - - amdgpu_state = kzalloc(sizeof(*amdgpu_state), GFP_KERNEL); - - if (amdgpu_state) { - plane->state = &amdgpu_state->base; - plane->state->plane = plane; - plane->state->rotation = DRM_MODE_ROTATE_0; - } - else - WARN_ON(1); -} - -static struct drm_plane_state * -dm_drm_plane_duplicate_state(struct drm_plane *plane) -{ - struct dm_plane_state *dm_plane_state, *old_dm_plane_state; - - old_dm_plane_state = to_dm_plane_state(plane->state); - dm_plane_state = kzalloc(sizeof(*dm_plane_state), GFP_KERNEL); - if (!dm_plane_state) - return NULL; - - __drm_atomic_helper_plane_duplicate_state(plane, &dm_plane_state->base); - - if (old_dm_plane_state->surface) { - dm_plane_state->surface = old_dm_plane_state->surface; - dc_surface_retain(dm_plane_state->surface); - } - - return &dm_plane_state->base; -} - -void dm_drm_plane_destroy_state(struct drm_plane *plane, - struct drm_plane_state *state) -{ - struct dm_plane_state *dm_plane_state = to_dm_plane_state(state); - - if (dm_plane_state->surface) - dc_surface_release(dm_plane_state->surface); - - __drm_atomic_helper_plane_destroy_state(state); - kfree(dm_plane_state); -} - -static const struct drm_plane_funcs dm_plane_funcs = { - .update_plane = drm_atomic_helper_update_plane, - .disable_plane = drm_atomic_helper_disable_plane, - .destroy = drm_plane_cleanup, - .reset = dm_drm_plane_reset, - .atomic_duplicate_state = dm_drm_plane_duplicate_state, - .atomic_destroy_state = dm_drm_plane_destroy_state, -}; - -static int dm_plane_helper_prepare_fb( - struct drm_plane *plane, - struct drm_plane_state *new_state) -{ - struct amdgpu_framebuffer *afb; - struct drm_gem_object *obj; - struct amdgpu_bo *rbo; - int r; - struct dm_plane_state *dm_plane_state_new, *dm_plane_state_old; - unsigned int awidth; - - dm_plane_state_old = to_dm_plane_state(plane->state); - dm_plane_state_new = to_dm_plane_state(new_state); - - if (!new_state->fb) { - DRM_DEBUG_KMS("No FB bound\n"); - return 0; - } - - afb = to_amdgpu_framebuffer(new_state->fb); - - obj = afb->obj; - rbo = gem_to_amdgpu_bo(obj); - r = amdgpu_bo_reserve(rbo, false); - if (unlikely(r != 0)) - return r; - - r = amdgpu_bo_pin(rbo, AMDGPU_GEM_DOMAIN_VRAM, &afb->address); - - - amdgpu_bo_unreserve(rbo); - - if (unlikely(r != 0)) { - DRM_ERROR("Failed to pin framebuffer\n"); - return r; - } - - amdgpu_bo_ref(rbo); - - if (dm_plane_state_new->surface && - dm_plane_state_old->surface != dm_plane_state_new->surface) { - struct dc_surface *surface = dm_plane_state_new->surface; - - if (surface->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) { - surface->address.grph.addr.low_part = lower_32_bits(afb->address); - surface->address.grph.addr.high_part = upper_32_bits(afb->address); - } else { - awidth = ALIGN(new_state->fb->width, 64); - surface->address.video_progressive.luma_addr.low_part - = lower_32_bits(afb->address); - surface->address.video_progressive.chroma_addr.low_part - = lower_32_bits(afb->address) + - (awidth * new_state->fb->height); - } - } - - /* It's a hack for s3 since in 4.9 kernel filter out cursor buffer - * prepare and cleanup in drm_atomic_helper_prepare_planes - * and drm_atomic_helper_cleanup_planes because fb doens't in s3. - * IN 4.10 kernel this code should be removed and amdgpu_device_suspend - * code touching fram buffers should be avoided for DC. - */ - if (plane->type == DRM_PLANE_TYPE_CURSOR) { - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(new_state->crtc); - - acrtc->cursor_bo = obj; - } - return 0; -} - -static void dm_plane_helper_cleanup_fb( - struct drm_plane *plane, - struct drm_plane_state *old_state) -{ - struct amdgpu_bo *rbo; - struct amdgpu_framebuffer *afb; - int r; - - if (!old_state->fb) - return; - - afb = to_amdgpu_framebuffer(old_state->fb); - rbo = gem_to_amdgpu_bo(afb->obj); - r = amdgpu_bo_reserve(rbo, false); - if (unlikely(r)) { - DRM_ERROR("failed to reserve rbo before unpin\n"); - return; - } else { - amdgpu_bo_unpin(rbo); - amdgpu_bo_unreserve(rbo); - amdgpu_bo_unref(&rbo); - }; -} - -int dm_create_validation_set_for_connector(struct drm_connector *connector, - struct drm_display_mode *mode, struct dc_validation_set *val_set) -{ - int result = MODE_ERROR; - struct dc_sink *dc_sink = - to_amdgpu_connector(connector)->dc_sink; - /* TODO: Unhardcode stream count */ - struct dc_stream *stream; - - if ((mode->flags & DRM_MODE_FLAG_INTERLACE) || - (mode->flags & DRM_MODE_FLAG_DBLSCAN)) - return result; - - if (NULL == dc_sink) { - DRM_ERROR("dc_sink is NULL!\n"); - return result; - } - - stream = dc_create_stream_for_sink(dc_sink); - - if (NULL == stream) { - DRM_ERROR("Failed to create stream for sink!\n"); - return result; - } - - drm_mode_set_crtcinfo(mode, 0); - - fill_stream_properties_from_drm_display_mode(stream, mode, connector); - - val_set->stream = stream; - - stream->src.width = mode->hdisplay; - stream->src.height = mode->vdisplay; - stream->dst = stream->src; - - return MODE_OK; -} - -static const struct drm_plane_helper_funcs dm_plane_helper_funcs = { - .prepare_fb = dm_plane_helper_prepare_fb, - .cleanup_fb = dm_plane_helper_cleanup_fb, -}; - -/* - * TODO: these are currently initialized to rgb formats only. - * For future use cases we should either initialize them dynamically based on - * plane capabilities, or initialize this array to all formats, so internal drm - * check will succeed, and let DC to implement proper check - */ -static uint32_t rgb_formats[] = { - DRM_FORMAT_RGB888, - DRM_FORMAT_XRGB8888, - DRM_FORMAT_ARGB8888, - DRM_FORMAT_RGBA8888, - DRM_FORMAT_XRGB2101010, - DRM_FORMAT_XBGR2101010, - DRM_FORMAT_ARGB2101010, - DRM_FORMAT_ABGR2101010, -}; - -static uint32_t yuv_formats[] = { - DRM_FORMAT_NV12, - DRM_FORMAT_NV21, -}; - -static const u32 cursor_formats[] = { - DRM_FORMAT_ARGB8888 -}; - -int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, - struct amdgpu_plane *aplane, - unsigned long possible_crtcs) -{ - int res = -EPERM; - - switch (aplane->base.type) { - case DRM_PLANE_TYPE_PRIMARY: - aplane->base.format_default = true; - - res = drm_universal_plane_init( - dm->adev->ddev, - &aplane->base, - possible_crtcs, - &dm_plane_funcs, - rgb_formats, - ARRAY_SIZE(rgb_formats), - NULL, aplane->base.type, NULL); - break; - case DRM_PLANE_TYPE_OVERLAY: - res = drm_universal_plane_init( - dm->adev->ddev, - &aplane->base, - possible_crtcs, - &dm_plane_funcs, - yuv_formats, - ARRAY_SIZE(yuv_formats), - NULL, aplane->base.type, NULL); - break; - case DRM_PLANE_TYPE_CURSOR: - res = drm_universal_plane_init( - dm->adev->ddev, - &aplane->base, - possible_crtcs, - &dm_plane_funcs, - cursor_formats, - ARRAY_SIZE(cursor_formats), - NULL, aplane->base.type, NULL); - break; - } - - drm_plane_helper_add(&aplane->base, &dm_plane_helper_funcs); - - return res; -} - -int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, - struct drm_plane *plane, - uint32_t crtc_index) -{ - struct amdgpu_crtc *acrtc = NULL; - struct amdgpu_plane *cursor_plane; - - int res = -ENOMEM; - - cursor_plane = kzalloc(sizeof(*cursor_plane), GFP_KERNEL); - if (!cursor_plane) - goto fail; - - cursor_plane->base.type = DRM_PLANE_TYPE_CURSOR; - res = amdgpu_dm_plane_init(dm, cursor_plane, 0); - - acrtc = kzalloc(sizeof(struct amdgpu_crtc), GFP_KERNEL); - if (!acrtc) - goto fail; - - res = drm_crtc_init_with_planes( - dm->ddev, - &acrtc->base, - plane, - &cursor_plane->base, - &amdgpu_dm_crtc_funcs, NULL); - - if (res) - goto fail; - - drm_crtc_helper_add(&acrtc->base, &amdgpu_dm_crtc_helper_funcs); - - acrtc->max_cursor_width = dm->adev->dm.dc->caps.max_cursor_size; - acrtc->max_cursor_height = dm->adev->dm.dc->caps.max_cursor_size; - - acrtc->crtc_id = crtc_index; - acrtc->base.enabled = false; - - dm->adev->mode_info.crtcs[crtc_index] = acrtc; - drm_mode_crtc_set_gamma_size(&acrtc->base, 256); - - return 0; - -fail: - if (acrtc) - kfree(acrtc); - if (cursor_plane) - kfree(cursor_plane); - acrtc->crtc_id = -1; - return res; -} - - -static int to_drm_connector_type(enum signal_type st) -{ - switch (st) { - case SIGNAL_TYPE_HDMI_TYPE_A: - return DRM_MODE_CONNECTOR_HDMIA; - case SIGNAL_TYPE_EDP: - return DRM_MODE_CONNECTOR_eDP; - case SIGNAL_TYPE_RGB: - return DRM_MODE_CONNECTOR_VGA; - case SIGNAL_TYPE_DISPLAY_PORT: - case SIGNAL_TYPE_DISPLAY_PORT_MST: - return DRM_MODE_CONNECTOR_DisplayPort; - case SIGNAL_TYPE_DVI_DUAL_LINK: - case SIGNAL_TYPE_DVI_SINGLE_LINK: - return DRM_MODE_CONNECTOR_DVID; - case SIGNAL_TYPE_VIRTUAL: - return DRM_MODE_CONNECTOR_VIRTUAL; - - default: - return DRM_MODE_CONNECTOR_Unknown; - } -} - -static void amdgpu_dm_get_native_mode(struct drm_connector *connector) -{ - const struct drm_connector_helper_funcs *helper = - connector->helper_private; - struct drm_encoder *encoder; - struct amdgpu_encoder *amdgpu_encoder; - - encoder = helper->best_encoder(connector); - - if (encoder == NULL) - return; - - amdgpu_encoder = to_amdgpu_encoder(encoder); - - amdgpu_encoder->native_mode.clock = 0; - - if (!list_empty(&connector->probed_modes)) { - struct drm_display_mode *preferred_mode = NULL; - list_for_each_entry(preferred_mode, - &connector->probed_modes, - head) { - if (preferred_mode->type & DRM_MODE_TYPE_PREFERRED) { - amdgpu_encoder->native_mode = *preferred_mode; - } - break; - } - - } -} - -static struct drm_display_mode *amdgpu_dm_create_common_mode( - struct drm_encoder *encoder, char *name, - int hdisplay, int vdisplay) -{ - struct drm_device *dev = encoder->dev; - struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); - struct drm_display_mode *mode = NULL; - struct drm_display_mode *native_mode = &amdgpu_encoder->native_mode; - - mode = drm_mode_duplicate(dev, native_mode); - - if(mode == NULL) - return NULL; - - mode->hdisplay = hdisplay; - mode->vdisplay = vdisplay; - mode->type &= ~DRM_MODE_TYPE_PREFERRED; - strncpy(mode->name, name, DRM_DISPLAY_MODE_LEN); - - return mode; - -} - -static void amdgpu_dm_connector_add_common_modes(struct drm_encoder *encoder, - struct drm_connector *connector) -{ - struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); - struct drm_display_mode *mode = NULL; - struct drm_display_mode *native_mode = &amdgpu_encoder->native_mode; - struct amdgpu_connector *amdgpu_connector = - to_amdgpu_connector(connector); - int i; - int n; - struct mode_size { - char name[DRM_DISPLAY_MODE_LEN]; - int w; - int h; - }common_modes[] = { - { "640x480", 640, 480}, - { "800x600", 800, 600}, - { "1024x768", 1024, 768}, - { "1280x720", 1280, 720}, - { "1280x800", 1280, 800}, - {"1280x1024", 1280, 1024}, - { "1440x900", 1440, 900}, - {"1680x1050", 1680, 1050}, - {"1600x1200", 1600, 1200}, - {"1920x1080", 1920, 1080}, - {"1920x1200", 1920, 1200} - }; - - n = sizeof(common_modes) / sizeof(common_modes[0]); - - for (i = 0; i < n; i++) { - struct drm_display_mode *curmode = NULL; - bool mode_existed = false; - - if (common_modes[i].w > native_mode->hdisplay || - common_modes[i].h > native_mode->vdisplay || - (common_modes[i].w == native_mode->hdisplay && - common_modes[i].h == native_mode->vdisplay)) - continue; - - list_for_each_entry(curmode, &connector->probed_modes, head) { - if (common_modes[i].w == curmode->hdisplay && - common_modes[i].h == curmode->vdisplay) { - mode_existed = true; - break; - } - } - - if (mode_existed) - continue; - - mode = amdgpu_dm_create_common_mode(encoder, - common_modes[i].name, common_modes[i].w, - common_modes[i].h); - drm_mode_probed_add(connector, mode); - amdgpu_connector->num_modes++; - } -} - -static void amdgpu_dm_connector_ddc_get_modes( - struct drm_connector *connector, - struct edid *edid) -{ - struct amdgpu_connector *amdgpu_connector = - to_amdgpu_connector(connector); - - if (edid) { - /* empty probed_modes */ - INIT_LIST_HEAD(&connector->probed_modes); - amdgpu_connector->num_modes = - drm_add_edid_modes(connector, edid); - - drm_edid_to_eld(connector, edid); - - amdgpu_dm_get_native_mode(connector); - } else - amdgpu_connector->num_modes = 0; -} - -int amdgpu_dm_connector_get_modes(struct drm_connector *connector) -{ - const struct drm_connector_helper_funcs *helper = - connector->helper_private; - struct amdgpu_connector *amdgpu_connector = - to_amdgpu_connector(connector); - struct drm_encoder *encoder; - struct edid *edid = amdgpu_connector->edid; - - encoder = helper->best_encoder(connector); - - amdgpu_dm_connector_ddc_get_modes(connector, edid); - amdgpu_dm_connector_add_common_modes(encoder, connector); - return amdgpu_connector->num_modes; -} - -void amdgpu_dm_connector_init_helper( - struct amdgpu_display_manager *dm, - struct amdgpu_connector *aconnector, - int connector_type, - struct dc_link *link, - int link_index) -{ - struct amdgpu_device *adev = dm->ddev->dev_private; - - aconnector->connector_id = link_index; - aconnector->dc_link = link; - aconnector->base.interlace_allowed = false; - aconnector->base.doublescan_allowed = false; - aconnector->base.stereo_allowed = false; - aconnector->base.dpms = DRM_MODE_DPMS_OFF; - aconnector->hpd.hpd = AMDGPU_HPD_NONE; /* not used */ - - mutex_init(&aconnector->hpd_lock); - - /*configure suport HPD hot plug connector_>polled default value is 0 - * which means HPD hot plug not supported*/ - switch (connector_type) { - case DRM_MODE_CONNECTOR_HDMIA: - aconnector->base.polled = DRM_CONNECTOR_POLL_HPD; - break; - case DRM_MODE_CONNECTOR_DisplayPort: - aconnector->base.polled = DRM_CONNECTOR_POLL_HPD; - break; - case DRM_MODE_CONNECTOR_DVID: - aconnector->base.polled = DRM_CONNECTOR_POLL_HPD; - break; - default: - break; - } - - drm_object_attach_property(&aconnector->base.base, - dm->ddev->mode_config.scaling_mode_property, - DRM_MODE_SCALE_NONE); - - drm_object_attach_property(&aconnector->base.base, - adev->mode_info.underscan_property, - UNDERSCAN_OFF); - drm_object_attach_property(&aconnector->base.base, - adev->mode_info.underscan_hborder_property, - 0); - drm_object_attach_property(&aconnector->base.base, - adev->mode_info.underscan_vborder_property, - 0); - -} - -int amdgpu_dm_i2c_xfer(struct i2c_adapter *i2c_adap, - struct i2c_msg *msgs, int num) -{ - struct amdgpu_i2c_adapter *i2c = i2c_get_adapdata(i2c_adap); - struct ddc_service *ddc_service = i2c->ddc_service; - struct i2c_command cmd; - int i; - int result = -EIO; - - cmd.payloads = kzalloc(num * sizeof(struct i2c_payload), GFP_KERNEL); - - if (!cmd.payloads) - return result; - - cmd.number_of_payloads = num; - cmd.engine = I2C_COMMAND_ENGINE_DEFAULT; - cmd.speed = 100; - - for (i = 0; i < num; i++) { - cmd.payloads[i].write = !(msgs[i].flags & I2C_M_RD); - cmd.payloads[i].address = msgs[i].addr; - cmd.payloads[i].length = msgs[i].len; - cmd.payloads[i].data = msgs[i].buf; - } - - if (dal_i2caux_submit_i2c_command( - ddc_service->ctx->i2caux, - ddc_service->ddc_pin, - &cmd)) - result = num; - - kfree(cmd.payloads); - return result; -} - -u32 amdgpu_dm_i2c_func(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; -} - -static const struct i2c_algorithm amdgpu_dm_i2c_algo = { - .master_xfer = amdgpu_dm_i2c_xfer, - .functionality = amdgpu_dm_i2c_func, -}; - -static struct amdgpu_i2c_adapter *create_i2c( - struct ddc_service *ddc_service, - int link_index, - int *res) -{ - struct amdgpu_device *adev = ddc_service->ctx->driver_context; - struct amdgpu_i2c_adapter *i2c; - - i2c = kzalloc(sizeof (struct amdgpu_i2c_adapter), GFP_KERNEL); - i2c->base.owner = THIS_MODULE; - i2c->base.class = I2C_CLASS_DDC; - i2c->base.dev.parent = &adev->pdev->dev; - i2c->base.algo = &amdgpu_dm_i2c_algo; - snprintf(i2c->base.name, sizeof (i2c->base.name), "AMDGPU DM i2c hw bus %d", link_index); - i2c_set_adapdata(&i2c->base, i2c); - i2c->ddc_service = ddc_service; - - return i2c; -} - -/* Note: this function assumes that dc_link_detect() was called for the - * dc_link which will be represented by this aconnector. */ -int amdgpu_dm_connector_init( - struct amdgpu_display_manager *dm, - struct amdgpu_connector *aconnector, - uint32_t link_index, - struct amdgpu_encoder *aencoder) -{ - int res = 0; - int connector_type; - struct dc *dc = dm->dc; - struct dc_link *link = dc_get_link_at_index(dc, link_index); - struct amdgpu_i2c_adapter *i2c; - ((struct dc_link *)link)->priv = aconnector; - - DRM_DEBUG_KMS("%s()\n", __func__); - - i2c = create_i2c(link->ddc, link->link_index, &res); - aconnector->i2c = i2c; - res = i2c_add_adapter(&i2c->base); - - if (res) { - DRM_ERROR("Failed to register hw i2c %d\n", link->link_index); - goto out_free; - } - - connector_type = to_drm_connector_type(link->connector_signal); - - res = drm_connector_init( - dm->ddev, - &aconnector->base, - &amdgpu_dm_connector_funcs, - connector_type); - - if (res) { - DRM_ERROR("connector_init failed\n"); - aconnector->connector_id = -1; - goto out_free; - } - - drm_connector_helper_add( - &aconnector->base, - &amdgpu_dm_connector_helper_funcs); - - amdgpu_dm_connector_init_helper( - dm, - aconnector, - connector_type, - link, - link_index); - - drm_mode_connector_attach_encoder( - &aconnector->base, &aencoder->base); - - drm_connector_register(&aconnector->base); - - if (connector_type == DRM_MODE_CONNECTOR_DisplayPort - || connector_type == DRM_MODE_CONNECTOR_eDP) - amdgpu_dm_initialize_dp_connector(dm, aconnector); - -#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\ - defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) - - /* NOTE: this currently will create backlight device even if a panel - * is not connected to the eDP/LVDS connector. - * - * This is less than ideal but we don't have sink information at this - * stage since detection happens after. We can't do detection earlier - * since MST detection needs connectors to be created first. - */ - if (link->connector_signal & (SIGNAL_TYPE_EDP | SIGNAL_TYPE_LVDS)) { - /* Event if registration failed, we should continue with - * DM initialization because not having a backlight control - * is better then a black screen. */ - amdgpu_dm_register_backlight_device(dm); - - if (dm->backlight_dev) - dm->backlight_link = link; - } -#endif - -out_free: - if (res) { - kfree(i2c); - aconnector->i2c = NULL; - } - return res; -} - -int amdgpu_dm_get_encoder_crtc_mask(struct amdgpu_device *adev) -{ - switch (adev->mode_info.num_crtc) { - case 1: - return 0x1; - case 2: - return 0x3; - case 3: - return 0x7; - case 4: - return 0xf; - case 5: - return 0x1f; - case 6: - default: - return 0x3f; - } -} - -int amdgpu_dm_encoder_init( - struct drm_device *dev, - struct amdgpu_encoder *aencoder, - uint32_t link_index) -{ - struct amdgpu_device *adev = dev->dev_private; - - int res = drm_encoder_init(dev, - &aencoder->base, - &amdgpu_dm_encoder_funcs, - DRM_MODE_ENCODER_TMDS, - NULL); - - aencoder->base.possible_crtcs = amdgpu_dm_get_encoder_crtc_mask(adev); - - if (!res) - aencoder->encoder_id = link_index; - else - aencoder->encoder_id = -1; - - drm_encoder_helper_add(&aencoder->base, &amdgpu_dm_encoder_helper_funcs); - - return res; -} - -static void manage_dm_interrupts( - struct amdgpu_device *adev, - struct amdgpu_crtc *acrtc, - bool enable) -{ - /* - * this is not correct translation but will work as soon as VBLANK - * constant is the same as PFLIP - */ - int irq_type = - amdgpu_crtc_idx_to_irq_type( - adev, - acrtc->crtc_id); - - if (enable) { - drm_crtc_vblank_on(&acrtc->base); - amdgpu_irq_get( - adev, - &adev->pageflip_irq, - irq_type); - } else { - - amdgpu_irq_put( - adev, - &adev->pageflip_irq, - irq_type); - drm_crtc_vblank_off(&acrtc->base); - } -} - -static bool is_scaling_state_different( - const struct dm_connector_state *dm_state, - const struct dm_connector_state *old_dm_state) -{ - if (dm_state->scaling != old_dm_state->scaling) - return true; - if (!dm_state->underscan_enable && old_dm_state->underscan_enable) { - if (old_dm_state->underscan_hborder != 0 && old_dm_state->underscan_vborder != 0) - return true; - } else if (dm_state->underscan_enable && !old_dm_state->underscan_enable) { - if (dm_state->underscan_hborder != 0 && dm_state->underscan_vborder != 0) - return true; - } else if (dm_state->underscan_hborder != old_dm_state->underscan_hborder - || dm_state->underscan_vborder != old_dm_state->underscan_vborder) - return true; - return false; -} - -static void remove_stream( - struct amdgpu_device *adev, - struct amdgpu_crtc *acrtc, - struct dc_stream *stream) -{ - /* this is the update mode case */ - if (adev->dm.freesync_module) - mod_freesync_remove_stream(adev->dm.freesync_module, stream); - - acrtc->otg_inst = -1; - acrtc->enabled = false; -} - -static void handle_cursor_update( - struct drm_plane *plane, - struct drm_plane_state *old_plane_state) -{ - if (!plane->state->fb && !old_plane_state->fb) - return; - - /* Check if it's a cursor on/off update or just cursor move*/ - if (plane->state->fb == old_plane_state->fb) - dm_crtc_cursor_move( - plane->state->crtc, - plane->state->crtc_x, - plane->state->crtc_y); - else { - struct amdgpu_framebuffer *afb = - to_amdgpu_framebuffer(plane->state->fb); - dm_crtc_cursor_set( - (!!plane->state->fb) ? - plane->state->crtc : - old_plane_state->crtc, - (!!plane->state->fb) ? - afb->address : - 0, - plane->state->crtc_w, - plane->state->crtc_h); - } -} - - -static void prepare_flip_isr(struct amdgpu_crtc *acrtc) -{ - - assert_spin_locked(&acrtc->base.dev->event_lock); - WARN_ON(acrtc->event); - - acrtc->event = acrtc->base.state->event; - - /* Set the flip status */ - acrtc->pflip_status = AMDGPU_FLIP_SUBMITTED; - - /* Mark this event as consumed */ - acrtc->base.state->event = NULL; - - DRM_DEBUG_DRIVER("crtc:%d, pflip_stat:AMDGPU_FLIP_SUBMITTED\n", - acrtc->crtc_id); -} - -/* - * Executes flip - * - * Waits on all BO's fences and for proper vblank count - */ -static void amdgpu_dm_do_flip( - struct drm_crtc *crtc, - struct drm_framebuffer *fb, - uint32_t target) -{ - unsigned long flags; - uint32_t target_vblank; - int r, vpos, hpos; - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - struct amdgpu_framebuffer *afb = to_amdgpu_framebuffer(fb); - struct amdgpu_bo *abo = gem_to_amdgpu_bo(afb->obj); - struct amdgpu_device *adev = crtc->dev->dev_private; - bool async_flip = (acrtc->flip_flags & DRM_MODE_PAGE_FLIP_ASYNC) != 0; - struct dc_flip_addrs addr = { {0} }; - struct dc_surface_update surface_updates[1] = { {0} }; - struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state); - - - /* Prepare wait for target vblank early - before the fence-waits */ - target_vblank = target - drm_crtc_vblank_count(crtc) + - amdgpu_get_vblank_counter_kms(crtc->dev, acrtc->crtc_id); - - /*TODO This might fail and hence better not used, wait - * explicitly on fences instead - * and in general should be called for - * blocking commit to as per framework helpers - * */ - r = amdgpu_bo_reserve(abo, true); - if (unlikely(r != 0)) { - DRM_ERROR("failed to reserve buffer before flip\n"); - WARN_ON(1); - } - - /* Wait for all fences on this FB */ - WARN_ON(reservation_object_wait_timeout_rcu(abo->tbo.resv, true, false, - MAX_SCHEDULE_TIMEOUT) < 0); - - amdgpu_bo_unreserve(abo); - - /* Wait until we're out of the vertical blank period before the one - * targeted by the flip - */ - while ((acrtc->enabled && - (amdgpu_get_crtc_scanoutpos(adev->ddev, acrtc->crtc_id, 0, - &vpos, &hpos, NULL, NULL, - &crtc->hwmode) - & (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_IN_VBLANK)) == - (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_IN_VBLANK) && - (int)(target_vblank - - amdgpu_get_vblank_counter_kms(adev->ddev, acrtc->crtc_id)) > 0)) { - usleep_range(1000, 1100); - } - - /* Flip */ - spin_lock_irqsave(&crtc->dev->event_lock, flags); - /* update crtc fb */ - crtc->primary->fb = fb; - - WARN_ON(acrtc->pflip_status != AMDGPU_FLIP_NONE); - WARN_ON(!acrtc_state->stream); - - addr.address.grph.addr.low_part = lower_32_bits(afb->address); - addr.address.grph.addr.high_part = upper_32_bits(afb->address); - addr.flip_immediate = async_flip; - - - if (acrtc->base.state->event) - prepare_flip_isr(acrtc); - - surface_updates->surface = dc_stream_get_status(acrtc_state->stream)->surfaces[0]; - surface_updates->flip_addr = &addr; - - - dc_update_surfaces_and_stream(adev->dm.dc, surface_updates, 1, acrtc_state->stream, NULL); - - DRM_DEBUG_DRIVER("%s Flipping to hi: 0x%x, low: 0x%x \n", - __func__, - addr.address.grph.addr.high_part, - addr.address.grph.addr.low_part); - - - spin_unlock_irqrestore(&crtc->dev->event_lock, flags); -} - -static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, - struct drm_device *dev, - struct amdgpu_display_manager *dm, - struct drm_crtc *pcrtc, - bool *wait_for_vblank) -{ - uint32_t i; - struct drm_plane *plane; - struct drm_plane_state *old_plane_state; - struct dc_stream *dc_stream_attach; - struct dc_surface *dc_surfaces_constructed[MAX_SURFACES]; - struct amdgpu_crtc *acrtc_attach = to_amdgpu_crtc(pcrtc); - struct dm_crtc_state *acrtc_state = to_dm_crtc_state(pcrtc->state); - int planes_count = 0; - unsigned long flags; - - /* update planes when needed */ - for_each_plane_in_state(state, plane, old_plane_state, i) { - struct drm_plane_state *plane_state = plane->state; - struct drm_crtc *crtc = plane_state->crtc; - struct drm_framebuffer *fb = plane_state->fb; - bool pflip_needed; - struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state); - - if (plane->type == DRM_PLANE_TYPE_CURSOR) { - handle_cursor_update(plane, old_plane_state); - continue; - } - - if (!fb || !crtc || pcrtc != crtc || !crtc->state->active || - (!crtc->state->planes_changed && - !pcrtc->state->color_mgmt_changed)) - continue; - - pflip_needed = !state->allow_modeset; - - spin_lock_irqsave(&crtc->dev->event_lock, flags); - if (acrtc_attach->pflip_status != AMDGPU_FLIP_NONE) { - DRM_ERROR("add_surface: acrtc %d, already busy\n", - acrtc_attach->crtc_id); - spin_unlock_irqrestore(&crtc->dev->event_lock, flags); - /* In comit tail framework this cannot happen */ - WARN_ON(1); - } - spin_unlock_irqrestore(&crtc->dev->event_lock, flags); - - if (!pflip_needed) { - WARN_ON(!dm_plane_state->surface); - - dc_surfaces_constructed[planes_count] = dm_plane_state->surface; - - dc_stream_attach = acrtc_state->stream; - planes_count++; - - } else if (crtc->state->planes_changed) { - /* Assume even ONE crtc with immediate flip means - * entire can't wait for VBLANK - * TODO Check if it's correct - */ - *wait_for_vblank = - acrtc_attach->flip_flags & DRM_MODE_PAGE_FLIP_ASYNC ? - false : true; - - /* TODO: Needs rework for multiplane flip */ - if (plane->type == DRM_PLANE_TYPE_PRIMARY) - drm_crtc_vblank_get(crtc); - - amdgpu_dm_do_flip( - crtc, - fb, - drm_crtc_vblank_count(crtc) + *wait_for_vblank); - - /*TODO BUG remove ASAP in 4.12 to avoid race between worker and flip IOCTL */ - - /*clean up the flags for next usage*/ - acrtc_attach->flip_flags = 0; - } - - } - - if (planes_count) { - unsigned long flags; - - if (pcrtc->state->event) { - - drm_crtc_vblank_get(pcrtc); - - spin_lock_irqsave(&pcrtc->dev->event_lock, flags); - prepare_flip_isr(acrtc_attach); - spin_unlock_irqrestore(&pcrtc->dev->event_lock, flags); - } - - if (false == dc_commit_surfaces_to_stream(dm->dc, - dc_surfaces_constructed, - planes_count, - dc_stream_attach)) - dm_error("%s: Failed to attach surface!\n", __func__); - } else { - /*TODO BUG Here should go disable planes on CRTC. */ - } -} - - -int amdgpu_dm_atomic_commit( - struct drm_device *dev, - struct drm_atomic_state *state, - bool nonblock) -{ - struct drm_crtc *crtc; - struct drm_crtc_state *new_state; - struct amdgpu_device *adev = dev->dev_private; - int i; - - /* - * We evade vblanks and pflips on crtc that - * should be changed. We do it here to flush & disable - * interrupts before drm_swap_state is called in drm_atomic_helper_commit - * it will update crtc->dm_crtc_state->stream pointer which is used in - * the ISRs. - */ - for_each_crtc_in_state(state, crtc, new_state, i) { - struct dm_crtc_state *old_acrtc_state = to_dm_crtc_state(crtc->state); - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - - if (drm_atomic_crtc_needs_modeset(new_state) && old_acrtc_state->stream) - manage_dm_interrupts(adev, acrtc, false); - } - - return drm_atomic_helper_commit(dev, state, nonblock); - - /*TODO Handle EINTR, reenable IRQ*/ -} - -void amdgpu_dm_atomic_commit_tail( - struct drm_atomic_state *state) -{ - struct drm_device *dev = state->dev; - struct amdgpu_device *adev = dev->dev_private; - struct amdgpu_display_manager *dm = &adev->dm; - struct dm_atomic_state *dm_state; - uint32_t i, j; - uint32_t new_crtcs_count = 0; - struct drm_crtc *crtc, *pcrtc; - struct drm_crtc_state *old_crtc_state; - struct amdgpu_crtc *new_crtcs[MAX_STREAMS]; - struct dc_stream *new_stream = NULL; - unsigned long flags; - bool wait_for_vblank = true; - struct drm_connector *connector; - struct drm_connector_state *old_conn_state; - struct dm_crtc_state *old_acrtc_state, *new_acrtc_state; - - drm_atomic_helper_update_legacy_modeset_state(dev, state); - - dm_state = to_dm_atomic_state(state); - - /* update changed items */ - for_each_crtc_in_state(state, crtc, old_crtc_state, i) { - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - struct drm_crtc_state *new_state = crtc->state; - new_acrtc_state = to_dm_crtc_state(new_state); - old_acrtc_state = to_dm_crtc_state(old_crtc_state); - - DRM_DEBUG_KMS( - "amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, " - "planes_changed:%d, mode_changed:%d,active_changed:%d," - "connectors_changed:%d\n", - acrtc->crtc_id, - new_state->enable, - new_state->active, - new_state->planes_changed, - new_state->mode_changed, - new_state->active_changed, - new_state->connectors_changed); - - /* handles headless hotplug case, updating new_state and - * aconnector as needed - */ - - if (modeset_required(new_state)) { - - DRM_INFO("Atomic commit: SET crtc id %d: [%p]\n", acrtc->crtc_id, acrtc); - - if (!new_acrtc_state->stream) { - /* - * this could happen because of issues with - * userspace notifications delivery. - * In this case userspace tries to set mode on - * display which is disconnect in fact. - * dc_sink in NULL in this case on aconnector. - * We expect reset mode will come soon. - * - * This can also happen when unplug is done - * during resume sequence ended - * - * In this case, we want to pretend we still - * have a sink to keep the pipe running so that - * hw state is consistent with the sw state - */ - DRM_DEBUG_KMS("%s: Failed to create new stream for crtc %d\n", - __func__, acrtc->base.base.id); - continue; - } - - - if (old_acrtc_state->stream) - remove_stream(adev, acrtc, old_acrtc_state->stream); - - - /* - * this loop saves set mode crtcs - * we needed to enable vblanks once all - * resources acquired in dc after dc_commit_streams - */ - - /*TODO move all this into dm_crtc_state, get rid of - * new_crtcs array and use old and new atomic states - * instead - */ - new_crtcs[new_crtcs_count] = acrtc; - new_crtcs_count++; - - acrtc->enabled = true; - acrtc->hw_mode = crtc->state->mode; - crtc->hwmode = crtc->state->mode; - } else if (modereset_required(new_state)) { - DRM_INFO("Atomic commit: RESET. crtc id %d:[%p]\n", acrtc->crtc_id, acrtc); - - /* i.e. reset mode */ - if (old_acrtc_state->stream) - remove_stream(adev, acrtc, old_acrtc_state->stream); - } - } /* for_each_crtc_in_state() */ - - /* - * Add streams after required streams from new and replaced streams - * are removed from freesync module - */ - if (adev->dm.freesync_module) { - for (i = 0; i < new_crtcs_count; i++) { - struct amdgpu_connector *aconnector = NULL; - new_acrtc_state = to_dm_crtc_state(new_crtcs[i]->base.state); - - new_stream = new_acrtc_state->stream; - aconnector = - amdgpu_dm_find_first_crct_matching_connector( - state, - &new_crtcs[i]->base, - false); - if (!aconnector) { - DRM_INFO( - "Atomic commit: Failed to find connector for acrtc id:%d " - "skipping freesync init\n", - new_crtcs[i]->crtc_id); - continue; - } - - mod_freesync_add_stream(adev->dm.freesync_module, - new_stream, &aconnector->caps); - } - } - - if (dm_state->context) - WARN_ON(!dc_commit_context(dm->dc, dm_state->context)); - - - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - new_acrtc_state = to_dm_crtc_state(crtc->state); - - if (new_acrtc_state->stream != NULL) { - const struct dc_stream_status *status = - dc_stream_get_status(new_acrtc_state->stream); - - if (!status) - DC_ERR("got no status for stream %p on acrtc%p\n", new_acrtc_state->stream, acrtc); - else - acrtc->otg_inst = status->primary_otg_inst; - } - } - - /* Handle scaling and undersacn changes*/ - for_each_connector_in_state(state, connector, old_conn_state, i) { - struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); - struct dm_connector_state *con_new_state = - to_dm_connector_state(aconnector->base.state); - struct dm_connector_state *con_old_state = - to_dm_connector_state(old_conn_state); - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(con_new_state->base.crtc); - struct dc_stream_status *status = NULL; - - /* Skip any modesets/resets */ - if (!acrtc || drm_atomic_crtc_needs_modeset(acrtc->base.state)) - continue; - - /* Skip any thing not scale or underscan changes */ - if (!is_scaling_state_different(con_new_state, con_old_state)) - continue; - - new_acrtc_state = to_dm_crtc_state(acrtc->base.state); - - update_stream_scaling_settings(&con_new_state->base.crtc->mode, - con_new_state, (struct dc_stream *)new_acrtc_state->stream); - - status = dc_stream_get_status(new_acrtc_state->stream); - WARN_ON(!status); - WARN_ON(!status->surface_count); - - if (!new_acrtc_state->stream) - continue; - - /*TODO How it works with MPO ?*/ - if (!dc_commit_surfaces_to_stream( - dm->dc, - status->surfaces, - status->surface_count, - new_acrtc_state->stream)) - dm_error("%s: Failed to update stream scaling!\n", __func__); - } - - for (i = 0; i < new_crtcs_count; i++) { - /* - * loop to enable interrupts on newly arrived crtc - */ - struct amdgpu_crtc *acrtc = new_crtcs[i]; - new_acrtc_state = to_dm_crtc_state(acrtc->base.state); - - if (adev->dm.freesync_module) - mod_freesync_notify_mode_change( - adev->dm.freesync_module, &new_acrtc_state->stream, 1); - - manage_dm_interrupts(adev, acrtc, true); - } - - /* update planes when needed per crtc*/ - for_each_crtc_in_state(state, pcrtc, old_crtc_state, j) { - new_acrtc_state = to_dm_crtc_state(pcrtc->state); - - if (new_acrtc_state->stream) - amdgpu_dm_commit_surfaces(state, dev, dm, pcrtc, &wait_for_vblank); - } - - - /* - * send vblank event on all events not handled in flip and - * mark consumed event for drm_atomic_helper_commit_hw_done - */ - spin_lock_irqsave(&adev->ddev->event_lock, flags); - for_each_crtc_in_state(state, crtc, old_crtc_state, i) { - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - - if (acrtc->base.state->event) - drm_send_event_locked(dev, &crtc->state->event->base); - - acrtc->base.state->event = NULL; - } - spin_unlock_irqrestore(&adev->ddev->event_lock, flags); - - /* Signal HW programming completion */ - drm_atomic_helper_commit_hw_done(state); - - if (wait_for_vblank) - drm_atomic_helper_wait_for_vblanks(dev, state); - - drm_atomic_helper_cleanup_planes(dev, state); -} - - -static int dm_force_atomic_commit(struct drm_connector *connector) -{ - int ret = 0; - struct drm_device *ddev = connector->dev; - struct drm_atomic_state *state = drm_atomic_state_alloc(ddev); - struct amdgpu_crtc *disconnected_acrtc = to_amdgpu_crtc(connector->encoder->crtc); - struct drm_plane *plane = disconnected_acrtc->base.primary; - struct drm_connector_state *conn_state; - struct drm_crtc_state *crtc_state; - struct drm_plane_state *plane_state; - - if (!state) - return -ENOMEM; - - state->acquire_ctx = ddev->mode_config.acquire_ctx; - - /* Construct an atomic state to restore previous display setting */ - - /* - * Attach connectors to drm_atomic_state - */ - conn_state = drm_atomic_get_connector_state(state, connector); - - ret = PTR_ERR_OR_ZERO(conn_state); - if (ret) - goto err; - - /* Attach crtc to drm_atomic_state*/ - crtc_state = drm_atomic_get_crtc_state(state, &disconnected_acrtc->base); - - ret = PTR_ERR_OR_ZERO(crtc_state); - if (ret) - goto err; - - /* force a restore */ - crtc_state->mode_changed = true; - - /* Attach plane to drm_atomic_state */ - plane_state = drm_atomic_get_plane_state(state, plane); - - ret = PTR_ERR_OR_ZERO(plane_state); - if (ret) - goto err; - - - /* Call commit internally with the state we just constructed */ - ret = drm_atomic_commit(state); - if (!ret) - return 0; - -err: - DRM_ERROR("Restoring old state failed with %i\n", ret); - drm_atomic_state_put(state); - - return ret; -} - -/* - * This functions handle all cases when set mode does not come upon hotplug. - * This include when the same display is unplugged then plugged back into the - * same port and when we are running without usermode desktop manager supprot - */ -void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector *connector) -{ - struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); - struct amdgpu_crtc *disconnected_acrtc; - struct dm_crtc_state *acrtc_state; - - if (!aconnector->dc_sink || !connector->state || !connector->encoder) - return; - - disconnected_acrtc = to_amdgpu_crtc(connector->encoder->crtc); - acrtc_state = to_dm_crtc_state(disconnected_acrtc->base.state); - - if (!disconnected_acrtc || !acrtc_state->stream) - return; - - /* - * If the previous sink is not released and different from the current, - * we deduce we are in a state where we can not rely on usermode call - * to turn on the display, so we do it here - */ - if (acrtc_state->stream->sink != aconnector->dc_sink) - dm_force_atomic_commit(&aconnector->base); -} - -static uint32_t add_val_sets_surface( - struct dc_validation_set *val_sets, - uint32_t set_count, - const struct dc_stream *stream, - struct dc_surface *surface) -{ - uint32_t i = 0, j = 0; - - while (i < set_count) { - if (val_sets[i].stream == stream) { - while (val_sets[i].surfaces[j]) - j++; - break; - } - ++i; - } - - val_sets[i].surfaces[j] = surface; - val_sets[i].surface_count++; - - return val_sets[i].surface_count; -} - -static uint32_t update_in_val_sets_stream( - struct dc_validation_set *val_sets, - uint32_t set_count, - struct dc_stream *old_stream, - struct dc_stream *new_stream, - struct drm_crtc *crtc) -{ - uint32_t i = 0; - - while (i < set_count) { - if (val_sets[i].stream == old_stream) - break; - ++i; - } - - val_sets[i].stream = new_stream; - - if (i == set_count) - /* nothing found. add new one to the end */ - return set_count + 1; - - return set_count; -} - -static uint32_t remove_from_val_sets( - struct dc_validation_set *val_sets, - uint32_t set_count, - const struct dc_stream *stream) -{ - int i; - - for (i = 0; i < set_count; i++) - if (val_sets[i].stream == stream) - break; - - if (i == set_count) { - /* nothing found */ - return set_count; - } - - set_count--; - - for (; i < set_count; i++) { - val_sets[i] = val_sets[i + 1]; - } - - return set_count; -} - -/*` - * Grabs all modesetting locks to serialize against any blocking commits, - * Waits for completion of all non blocking commits. - */ -static int do_aquire_global_lock( - struct drm_device *dev, - struct drm_atomic_state *state) -{ - struct drm_crtc *crtc; - struct drm_crtc_commit *commit; - long ret; - - /* Adding all modeset locks to aquire_ctx will - * ensure that when the framework release it the - * extra locks we are locking here will get released to - */ - ret = drm_modeset_lock_all_ctx(dev, state->acquire_ctx); - if (ret) - return ret; - - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - spin_lock(&crtc->commit_lock); - commit = list_first_entry_or_null(&crtc->commit_list, - struct drm_crtc_commit, commit_entry); - if (commit) - drm_crtc_commit_get(commit); - spin_unlock(&crtc->commit_lock); - - if (!commit) - continue; - - /* Make sure all pending HW programming completed and - * page flips done - */ - ret = wait_for_completion_interruptible_timeout(&commit->hw_done, 10*HZ); - - if (ret > 0) - ret = wait_for_completion_interruptible_timeout( - &commit->flip_done, 10*HZ); - - if (ret == 0) - DRM_ERROR("[CRTC:%d:%s] hw_done or flip_done " - "timed out\n", crtc->base.id, crtc->name); - - drm_crtc_commit_put(commit); - } - - return ret < 0 ? ret : 0; -} - -int amdgpu_dm_atomic_check(struct drm_device *dev, - struct drm_atomic_state *state) -{ - struct dm_atomic_state *dm_state; - struct drm_crtc *crtc; - struct drm_crtc_state *crtc_state; - struct drm_plane *plane; - struct drm_plane_state *plane_state; - int i, j; - int ret; - struct amdgpu_device *adev = dev->dev_private; - struct dc *dc = adev->dm.dc; - struct drm_connector *connector; - struct drm_connector_state *conn_state; - int set_count; - struct dc_validation_set set[MAX_STREAMS] = { { 0 } }; - struct dm_crtc_state *old_acrtc_state, *new_acrtc_state; - - /* - * This bool will be set for true for any modeset/reset - * or surface update which implies non fast surface update. - */ - bool lock_and_validation_needed = false; - - ret = drm_atomic_helper_check_modeset(dev, state); - - if (ret) { - DRM_ERROR("Atomic state validation failed with error :%d !\n", ret); - return ret; - } - - dm_state = to_dm_atomic_state(state); - - /* copy existing configuration */ - set_count = 0; - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - - old_acrtc_state = to_dm_crtc_state(crtc->state); - - if (old_acrtc_state->stream) { - dc_stream_retain(old_acrtc_state->stream); - set[set_count].stream = old_acrtc_state->stream; - ++set_count; - } - } - - /*TODO Move this code into dm_crtc_atomic_check once we get rid of dc_validation_set */ - /* update changed items */ - for_each_crtc_in_state(state, crtc, crtc_state, i) { - struct amdgpu_crtc *acrtc = NULL; - struct amdgpu_connector *aconnector = NULL; - old_acrtc_state = to_dm_crtc_state(crtc->state); - new_acrtc_state = to_dm_crtc_state(crtc_state); - acrtc = to_amdgpu_crtc(crtc); - - aconnector = amdgpu_dm_find_first_crct_matching_connector(state, crtc, true); - - DRM_DEBUG_KMS( - "amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, " - "planes_changed:%d, mode_changed:%d,active_changed:%d," - "connectors_changed:%d\n", - acrtc->crtc_id, - crtc_state->enable, - crtc_state->active, - crtc_state->planes_changed, - crtc_state->mode_changed, - crtc_state->active_changed, - crtc_state->connectors_changed); - - if (modeset_required(crtc_state)) { - - struct dc_stream *new_stream = NULL; - struct drm_connector_state *conn_state = NULL; - struct dm_connector_state *dm_conn_state = NULL; - - if (aconnector) { - conn_state = drm_atomic_get_connector_state(state, &aconnector->base); - if (IS_ERR(conn_state)) { - ret = PTR_ERR_OR_ZERO(conn_state); - goto fail; - } - - dm_conn_state = to_dm_connector_state(conn_state); - } - - new_stream = create_stream_for_sink(aconnector, &crtc_state->mode, dm_conn_state); - - /* - * we can have no stream on ACTION_SET if a display - * was disconnected during S3, in this case it not and - * error, the OS will be updated after detection, and - * do the right thing on next atomic commit - */ - if (!new_stream) { - DRM_DEBUG_KMS("%s: Failed to create new stream for crtc %d\n", - __func__, acrtc->base.base.id); - break; - } - - if (new_acrtc_state->stream) - dc_stream_release(new_acrtc_state->stream); - - new_acrtc_state->stream = new_stream; - - set_count = update_in_val_sets_stream( - set, - set_count, - old_acrtc_state->stream, - new_acrtc_state->stream, - crtc); - - lock_and_validation_needed = true; - - } else if (modereset_required(crtc_state)) { - - /* i.e. reset mode */ - if (new_acrtc_state->stream) { - set_count = remove_from_val_sets( - set, - set_count, - new_acrtc_state->stream); - - dc_stream_release(new_acrtc_state->stream); - new_acrtc_state->stream = NULL; - - lock_and_validation_needed = true; - } - } - - - /* - * Hack: Commit needs planes right now, specifically for gamma - * TODO rework commit to check CRTC for gamma change - */ - if (crtc_state->color_mgmt_changed) { - - ret = drm_atomic_add_affected_planes(state, crtc); - if (ret) - goto fail; - } - } - - /* Check scaling and undersacn changes*/ - /*TODO Removed scaling changes validation due to inability to commit - * new stream into context w\o causing full reset. Need to - * decide how to handle. - */ - for_each_connector_in_state(state, connector, conn_state, i) { - struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); - struct dm_connector_state *con_old_state = - to_dm_connector_state(aconnector->base.state); - struct dm_connector_state *con_new_state = - to_dm_connector_state(conn_state); - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(con_new_state->base.crtc); - - /* Skip any modesets/resets */ - if (!acrtc || drm_atomic_crtc_needs_modeset(acrtc->base.state)) - continue; - - /* Skip any thing not scale or underscan chnages */ - if (!is_scaling_state_different(con_new_state, con_old_state)) - continue; - - lock_and_validation_needed = true; - } - - for_each_crtc_in_state(state, crtc, crtc_state, i) { - new_acrtc_state = to_dm_crtc_state(crtc_state); - - for_each_plane_in_state(state, plane, plane_state, j) { - struct drm_crtc *plane_crtc = plane_state->crtc; - struct drm_framebuffer *fb = plane_state->fb; - bool pflip_needed; - struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state); - - /*TODO Implement atomic check for cursor plane */ - if (plane->type == DRM_PLANE_TYPE_CURSOR) - continue; - - if (!fb || !plane_crtc || crtc != plane_crtc || !crtc_state->active) - continue; - - WARN_ON(!new_acrtc_state->stream); - - pflip_needed = !state->allow_modeset; - if (!pflip_needed) { - struct dc_surface *surface; - - surface = dc_create_surface(dc); - - ret = fill_plane_attributes( - plane_crtc->dev->dev_private, - surface, - plane_state, - crtc_state, - false); - if (ret) - goto fail; - - - if (dm_plane_state->surface) - dc_surface_release(dm_plane_state->surface); - - dm_plane_state->surface = surface; - - add_val_sets_surface(set, - set_count, - new_acrtc_state->stream, - surface); - - lock_and_validation_needed = true; - } - } - } - - /* Run this here since we want to validate the streams we created */ - ret = drm_atomic_helper_check_planes(dev, state); - if (ret) - goto fail; - - /* - * For full updates case when - * removing/adding/updating streams on once CRTC while flipping - * on another CRTC, - * acquiring global lock will guarantee that any such full - * update commit - * will wait for completion of any outstanding flip using DRMs - * synchronization events. - */ - - if (lock_and_validation_needed) { - - ret = do_aquire_global_lock(dev, state); - if (ret) - goto fail; - WARN_ON(dm_state->context); - dm_state->context = dc_get_validate_context(dc, set, set_count); - if (!dm_state->context) { - ret = -EINVAL; - goto fail; - } - } - - /* Must be success */ - WARN_ON(ret); - return ret; - -fail: - if (ret == -EDEADLK) - DRM_DEBUG_KMS("Atomic check stopped due to to deadlock.\n"); - else if (ret == -EINTR || ret == -EAGAIN || ret == -ERESTARTSYS) - DRM_DEBUG_KMS("Atomic check stopped due to to signal.\n"); - else - DRM_ERROR("Atomic check failed with err: %d .\n", ret); - - return ret; -} - -static bool is_dp_capable_without_timing_msa( - struct dc *dc, - struct amdgpu_connector *amdgpu_connector) -{ - uint8_t dpcd_data; - bool capable = false; - - if (amdgpu_connector->dc_link && - dm_helpers_dp_read_dpcd( - NULL, - amdgpu_connector->dc_link, - DP_DOWN_STREAM_PORT_COUNT, - &dpcd_data, - sizeof(dpcd_data))) { - capable = (dpcd_data & DP_MSA_TIMING_PAR_IGNORED) ? true:false; - } - - return capable; -} -void amdgpu_dm_add_sink_to_freesync_module( - struct drm_connector *connector, - struct edid *edid) -{ - int i; - uint64_t val_capable; - bool edid_check_required; - struct detailed_timing *timing; - struct detailed_non_pixel *data; - struct detailed_data_monitor_range *range; - struct amdgpu_connector *amdgpu_connector = - to_amdgpu_connector(connector); - - struct drm_device *dev = connector->dev; - struct amdgpu_device *adev = dev->dev_private; - edid_check_required = false; - if (!amdgpu_connector->dc_sink) { - DRM_ERROR("dc_sink NULL, could not add free_sync module.\n"); - return; - } - if (!adev->dm.freesync_module) - return; - /* - * if edid non zero restrict freesync only for dp and edp - */ - if (edid) { - if (amdgpu_connector->dc_sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT - || amdgpu_connector->dc_sink->sink_signal == SIGNAL_TYPE_EDP) { - edid_check_required = is_dp_capable_without_timing_msa( - adev->dm.dc, - amdgpu_connector); - } - } - val_capable = 0; - if (edid_check_required == true && (edid->version > 1 || - (edid->version == 1 && edid->revision > 1))) { - for (i = 0; i < 4; i++) { - - timing = &edid->detailed_timings[i]; - data = &timing->data.other_data; - range = &data->data.range; - /* - * Check if monitor has continuous frequency mode - */ - if (data->type != EDID_DETAIL_MONITOR_RANGE) - continue; - /* - * Check for flag range limits only. If flag == 1 then - * no additional timing information provided. - * Default GTF, GTF Secondary curve and CVT are not - * supported - */ - if (range->flags != 1) - continue; - - amdgpu_connector->min_vfreq = range->min_vfreq; - amdgpu_connector->max_vfreq = range->max_vfreq; - amdgpu_connector->pixel_clock_mhz = - range->pixel_clock_mhz * 10; - break; - } - - if (amdgpu_connector->max_vfreq - - amdgpu_connector->min_vfreq > 10) { - amdgpu_connector->caps.supported = true; - amdgpu_connector->caps.min_refresh_in_micro_hz = - amdgpu_connector->min_vfreq * 1000000; - amdgpu_connector->caps.max_refresh_in_micro_hz = - amdgpu_connector->max_vfreq * 1000000; - val_capable = 1; - } - } - - /* - * TODO figure out how to notify user-mode or DRM of freesync caps - * once we figure out how to deal with freesync in an upstreamable - * fashion - */ - -} - -void amdgpu_dm_remove_sink_from_freesync_module( - struct drm_connector *connector) -{ - /* - * TODO fill in once we figure out how to deal with freesync in - * an upstreamable fashion - */ -} diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h deleted file mode 100644 index 94de6a3736fc..000000000000 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright 2012-13 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __AMDGPU_DM_TYPES_H__ -#define __AMDGPU_DM_TYPES_H__ - -#include -#include -#include "dc.h" - -struct amdgpu_framebuffer; -struct amdgpu_display_manager; -struct dc_validation_set; -struct dc_surface; -/* TODO rename to dc_stream_state */ -struct dc_stream; - - -struct dm_plane_state { - struct drm_plane_state base; - struct dc_surface *surface; -}; - -struct dm_crtc_state { - struct drm_crtc_state base; - struct dc_stream *stream; -}; - -#define to_dm_crtc_state(x) container_of(x, struct dm_crtc_state, base) - -struct dm_atomic_state { - struct drm_atomic_state base; - - struct validate_context *context; -}; - -#define to_dm_atomic_state(x) container_of(x, struct dm_atomic_state, base) - - -/*TODO Jodan Hersen use the one in amdgpu_dm*/ -int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, - struct amdgpu_plane *aplane, - unsigned long possible_crtcs); -int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, - struct drm_plane *plane, - uint32_t link_index); -int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm, - struct amdgpu_connector *amdgpu_connector, - uint32_t link_index, - struct amdgpu_encoder *amdgpu_encoder); -int amdgpu_dm_encoder_init( - struct drm_device *dev, - struct amdgpu_encoder *aencoder, - uint32_t link_index); - -void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc); -void amdgpu_dm_connector_destroy(struct drm_connector *connector); -void amdgpu_dm_encoder_destroy(struct drm_encoder *encoder); - -int amdgpu_dm_connector_get_modes(struct drm_connector *connector); - -int amdgpu_dm_atomic_commit( - struct drm_device *dev, - struct drm_atomic_state *state, - bool nonblock); - -void amdgpu_dm_atomic_commit_tail( - struct drm_atomic_state *state); - -int amdgpu_dm_atomic_check(struct drm_device *dev, - struct drm_atomic_state *state); - -void amdgpu_dm_connector_funcs_reset(struct drm_connector *connector); -struct drm_connector_state *amdgpu_dm_connector_atomic_duplicate_state( - struct drm_connector *connector); - -int amdgpu_dm_connector_atomic_set_property( - struct drm_connector *connector, - struct drm_connector_state *state, - struct drm_property *property, - uint64_t val); - -int amdgpu_dm_connector_atomic_get_property( - struct drm_connector *connector, - const struct drm_connector_state *state, - struct drm_property *property, - uint64_t *val); - -int amdgpu_dm_get_encoder_crtc_mask(struct amdgpu_device *adev); - -void amdgpu_dm_connector_init_helper( - struct amdgpu_display_manager *dm, - struct amdgpu_connector *aconnector, - int connector_type, - struct dc_link *link, - int link_index); - -int amdgpu_dm_connector_mode_valid( - struct drm_connector *connector, - struct drm_display_mode *mode); - -void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector *connector); - -void amdgpu_dm_add_sink_to_freesync_module( - struct drm_connector *connector, - struct edid *edid); - -void amdgpu_dm_remove_sink_from_freesync_module( - struct drm_connector *connector); - -extern const struct drm_encoder_helper_funcs amdgpu_dm_encoder_helper_funcs; - -#endif /* __AMDGPU_DM_TYPES_H__ */ -- cgit From b830ebc910f641286ea0b816614db43d1135fc1a Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Wed, 26 Jul 2017 21:03:22 -0400 Subject: drm/amd/display: Fix ckeckpatch problems in amdgpu_dm Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 179 ++++++++++++---------- 1 file changed, 94 insertions(+), 85 deletions(-) (limited to 'drivers/gpu') 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 646a946a2571..02ca9d6225eb 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1682,14 +1682,13 @@ static int dm_crtc_cursor_set( int ret; struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); - ret = EINVAL; + ret = EINVAL; - DRM_DEBUG_KMS( - "%s: crtc_id=%d with size %d to %d \n", - __func__, - amdgpu_crtc->crtc_id, - width, - height); + DRM_DEBUG_KMS("%s: crtc_id=%d with size %d to %d \n", + __func__, + amdgpu_crtc->crtc_id, + width, + height); if (!address) { /* turn off cursor */ @@ -1839,6 +1838,7 @@ static int get_fb_info( { struct amdgpu_bo *rbo = gem_to_amdgpu_bo(amdgpu_fb->obj); int r = amdgpu_bo_reserve(rbo, false); + if (unlikely(r)) { DRM_ERROR("Unable to reserve buffer\n"); return r; @@ -1946,10 +1946,9 @@ static int fill_plane_attributes_from_fb( memset(&surface->tiling_info, 0, sizeof(surface->tiling_info)); - /* Fill GFX params */ - if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE) == DC_ARRAY_2D_TILED_THIN1) - { - unsigned bankw, bankh, mtaspect, tile_split, num_banks; + /* Fill GFX8 params */ + if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE) == DC_ARRAY_2D_TILED_THIN1) { + unsigned int bankw, bankh, mtaspect, tile_split, num_banks; bankw = AMDGPU_TILING_GET(tiling_flags, BANK_WIDTH); bankh = AMDGPU_TILING_GET(tiling_flags, BANK_HEIGHT); @@ -2162,7 +2161,8 @@ static enum dc_color_depth convert_color_depth_from_display_info( uint32_t bpc = connector->display_info.bpc; /* Limited color depth to 8bit - * TODO: Still need to handle deep color*/ + * TODO: Still need to handle deep color + */ if (bpc > 8) bpc = 8; @@ -2195,6 +2195,7 @@ static enum dc_aspect_ratio get_aspect_ratio( { int32_t width = mode_in->crtc_hdisplay * 9; int32_t height = mode_in->crtc_vdisplay * 16; + if ((width - height) < 10 && (width - height) > -10) return ASPECT_RATIO_16_9; else @@ -2252,6 +2253,7 @@ static void fill_stream_properties_from_drm_display_mode( const struct drm_connector *connector) { struct dc_crtc_timing *timing_out = &stream->timing; + memset(timing_out, 0, sizeof(struct dc_crtc_timing)); timing_out->h_border_left = 0; @@ -2296,6 +2298,7 @@ static void fill_stream_properties_from_drm_display_mode( { struct dc_transfer_func *tf = dc_create_transfer_func(); + tf->type = TF_TYPE_PREDEFINED; tf->tf = TRANSFER_FUNCTION_SRGB; stream->out_transfer_func = tf; @@ -2322,7 +2325,7 @@ static void fill_audio_info( i++; } - if(cea_revision >= 3) { + if (cea_revision >= 3) { audio_info->mode_count = edid_caps->audio_mode_count; for (i = 0; i < audio_info->mode_count; ++i) { @@ -2341,7 +2344,7 @@ static void fill_audio_info( audio_info->flags.all = edid_caps->speaker_flags; /* TODO: We only check for the progressive mode, check for interlace mode too */ - if(drm_connector->latency_present[0]) { + if (drm_connector->latency_present[0]) { audio_info->video_latency = drm_connector->video_latency[0]; audio_info->audio_latency = drm_connector->audio_latency[0]; } @@ -2359,7 +2362,7 @@ static void copy_crtc_timing_for_drm_display_mode( dst_mode->crtc_clock = src_mode->crtc_clock; dst_mode->crtc_hblank_start = src_mode->crtc_hblank_start; dst_mode->crtc_hblank_end = src_mode->crtc_hblank_end; - dst_mode->crtc_hsync_start= src_mode->crtc_hsync_start; + dst_mode->crtc_hsync_start = src_mode->crtc_hsync_start; dst_mode->crtc_hsync_end = src_mode->crtc_hsync_end; dst_mode->crtc_htotal = src_mode->crtc_htotal; dst_mode->crtc_hskew = src_mode->crtc_hskew; @@ -2397,12 +2400,12 @@ static struct dc_stream *create_stream_for_sink( struct drm_display_mode mode = *drm_mode; bool native_mode_found = false; - if (NULL == aconnector) { + if (aconnector == NULL) { DRM_ERROR("aconnector is NULL!\n"); goto drm_connector_null; } - if (NULL == dm_state) { + if (dm_state == NULL) { DRM_ERROR("dm_state is NULL!\n"); goto dm_state_null; } @@ -2410,7 +2413,7 @@ static struct dc_stream *create_stream_for_sink( drm_connector = &aconnector->base; stream = dc_create_stream_for_sink(aconnector->dc_sink); - if (NULL == stream) { + if (stream == NULL) { DRM_ERROR("Failed to create stream for sink!\n"); goto stream_create_fail; } @@ -2428,7 +2431,7 @@ static struct dc_stream *create_stream_for_sink( struct drm_display_mode, head); - if (NULL == preferred_mode) { + if (preferred_mode == NULL) { /* This may not be an error, the use case is when we we have no * usermode calls to reset and set mode upon hotplug. In this * case, we call set mode ourselves to restore the previous mode @@ -2818,13 +2821,13 @@ int amdgpu_dm_connector_mode_valid( dc_sink = to_amdgpu_connector(connector)->dc_sink; - if (NULL == dc_sink) { + if (dc_sink == NULL) { DRM_ERROR("dc_sink is NULL!\n"); goto fail; } stream = dc_create_stream_for_sink(dc_sink); - if (NULL == stream) { + if (stream == NULL) { DRM_ERROR("Failed to create stream for sink!\n"); goto fail; } @@ -2849,11 +2852,11 @@ fail: static const struct drm_connector_helper_funcs amdgpu_dm_connector_helper_funcs = { /* - * If hotplug a second bigger display in FB Con mode, bigger resolution - * modes will be filtered by drm_mode_validate_size(), and those modes - * is missing after user start lightdm. So we need to renew modes list. - * in get_modes call back, not just return the modes count - */ + * If hotplug a second bigger display in FB Con mode, bigger resolution + * modes will be filtered by drm_mode_validate_size(), and those modes + * is missing after user start lightdm. So we need to renew modes list. + * in get_modes call back, not just return the modes count + */ .get_modes = get_modes, .mode_valid = amdgpu_dm_connector_mode_valid, .best_encoder = best_encoder @@ -3064,11 +3067,11 @@ static void dm_plane_helper_cleanup_fb( if (unlikely(r)) { DRM_ERROR("failed to reserve rbo before unpin\n"); return; - } else { - amdgpu_bo_unpin(rbo); - amdgpu_bo_unreserve(rbo); - amdgpu_bo_unref(&rbo); - }; + } + + amdgpu_bo_unpin(rbo); + amdgpu_bo_unreserve(rbo); + amdgpu_bo_unref(&rbo); } int dm_create_validation_set_for_connector(struct drm_connector *connector, @@ -3084,14 +3087,14 @@ int dm_create_validation_set_for_connector(struct drm_connector *connector, (mode->flags & DRM_MODE_FLAG_DBLSCAN)) return result; - if (NULL == dc_sink) { + if (dc_sink == NULL) { DRM_ERROR("dc_sink is NULL!\n"); return result; } stream = dc_create_stream_for_sink(dc_sink); - if (NULL == stream) { + if (stream == NULL) { DRM_ERROR("Failed to create stream for sink!\n"); return result; } @@ -3230,10 +3233,8 @@ int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, return 0; fail: - if (acrtc) - kfree(acrtc); - if (cursor_plane) - kfree(cursor_plane); + kfree(acrtc); + kfree(cursor_plane); acrtc->crtc_id = -1; return res; } @@ -3280,12 +3281,13 @@ static void amdgpu_dm_get_native_mode(struct drm_connector *connector) if (!list_empty(&connector->probed_modes)) { struct drm_display_mode *preferred_mode = NULL; + list_for_each_entry(preferred_mode, - &connector->probed_modes, - head) { - if (preferred_mode->type & DRM_MODE_TYPE_PREFERRED) { - amdgpu_encoder->native_mode = *preferred_mode; - } + &connector->probed_modes, + head) { + if (preferred_mode->type & DRM_MODE_TYPE_PREFERRED) + amdgpu_encoder->native_mode = *preferred_mode; + break; } @@ -3303,7 +3305,7 @@ static struct drm_display_mode *amdgpu_dm_create_common_mode( mode = drm_mode_duplicate(dev, native_mode); - if(mode == NULL) + if (mode == NULL) return NULL; mode->hdisplay = hdisplay; @@ -3329,7 +3331,7 @@ static void amdgpu_dm_connector_add_common_modes(struct drm_encoder *encoder, char name[DRM_DISPLAY_MODE_LEN]; int w; int h; - }common_modes[] = { + } common_modes[] = { { "640x480", 640, 480}, { "800x600", 800, 600}, { "1024x768", 1024, 768}, @@ -3343,21 +3345,21 @@ static void amdgpu_dm_connector_add_common_modes(struct drm_encoder *encoder, {"1920x1200", 1920, 1200} }; - n = sizeof(common_modes) / sizeof(common_modes[0]); + n = ARRAY_SIZE(common_modes); for (i = 0; i < n; i++) { struct drm_display_mode *curmode = NULL; bool mode_existed = false; if (common_modes[i].w > native_mode->hdisplay || - common_modes[i].h > native_mode->vdisplay || - (common_modes[i].w == native_mode->hdisplay && - common_modes[i].h == native_mode->vdisplay)) - continue; + common_modes[i].h > native_mode->vdisplay || + (common_modes[i].w == native_mode->hdisplay && + common_modes[i].h == native_mode->vdisplay)) + continue; list_for_each_entry(curmode, &connector->probed_modes, head) { if (common_modes[i].w == curmode->hdisplay && - common_modes[i].h == curmode->vdisplay) { + common_modes[i].h == curmode->vdisplay) { mode_existed = true; break; } @@ -3429,8 +3431,9 @@ void amdgpu_dm_connector_init_helper( mutex_init(&aconnector->hpd_lock); - /*configure suport HPD hot plug connector_>polled default value is 0 - * which means HPD hot plug not supported*/ + /* configure support HPD hot plug connector_>polled default value is 0 + * which means HPD hot plug not supported + */ switch (connector_type) { case DRM_MODE_CONNECTOR_HDMIA: aconnector->base.polled = DRM_CONNECTOR_POLL_HPD; @@ -3470,7 +3473,7 @@ int amdgpu_dm_i2c_xfer(struct i2c_adapter *i2c_adap, int i; int result = -EIO; - cmd.payloads = kzalloc(num * sizeof(struct i2c_payload), GFP_KERNEL); + cmd.payloads = kcalloc(num, sizeof(struct i2c_payload), GFP_KERNEL); if (!cmd.payloads) return result; @@ -3514,12 +3517,12 @@ static struct amdgpu_i2c_adapter *create_i2c( struct amdgpu_device *adev = ddc_service->ctx->driver_context; struct amdgpu_i2c_adapter *i2c; - i2c = kzalloc(sizeof (struct amdgpu_i2c_adapter), GFP_KERNEL); + i2c = kzalloc(sizeof(struct amdgpu_i2c_adapter), GFP_KERNEL); i2c->base.owner = THIS_MODULE; i2c->base.class = I2C_CLASS_DDC; i2c->base.dev.parent = &adev->pdev->dev; i2c->base.algo = &amdgpu_dm_i2c_algo; - snprintf(i2c->base.name, sizeof (i2c->base.name), "AMDGPU DM i2c hw bus %d", link_index); + snprintf(i2c->base.name, sizeof(i2c->base.name), "AMDGPU DM i2c hw bus %d", link_index); i2c_set_adapdata(&i2c->base, i2c); i2c->ddc_service = ddc_service; @@ -3527,7 +3530,8 @@ static struct amdgpu_i2c_adapter *create_i2c( } /* Note: this function assumes that dc_link_detect() was called for the - * dc_link which will be represented by this aconnector. */ + * dc_link which will be represented by this aconnector. + */ int amdgpu_dm_connector_init( struct amdgpu_display_manager *dm, struct amdgpu_connector *aconnector, @@ -3599,7 +3603,8 @@ int amdgpu_dm_connector_init( if (link->connector_signal & (SIGNAL_TYPE_EDP | SIGNAL_TYPE_LVDS)) { /* Event if registration failed, we should continue with * DM initialization because not having a backlight control - * is better then a black screen. */ + * is better then a black screen. + */ amdgpu_dm_register_backlight_device(dm); if (dm->backlight_dev) @@ -3701,9 +3706,9 @@ static bool is_scaling_state_different( } else if (dm_state->underscan_enable && !old_dm_state->underscan_enable) { if (dm_state->underscan_hborder != 0 && dm_state->underscan_vborder != 0) return true; - } else if (dm_state->underscan_hborder != old_dm_state->underscan_hborder - || dm_state->underscan_vborder != old_dm_state->underscan_vborder) - return true; + } else if (dm_state->underscan_hborder != old_dm_state->underscan_hborder || + dm_state->underscan_vborder != old_dm_state->underscan_vborder) + return true; return false; } @@ -3794,11 +3799,11 @@ static void amdgpu_dm_do_flip( target_vblank = target - drm_crtc_vblank_count(crtc) + amdgpu_get_vblank_counter_kms(crtc->dev, acrtc->crtc_id); - /*TODO This might fail and hence better not used, wait + /* TODO This might fail and hence better not used, wait * explicitly on fences instead * and in general should be called for * blocking commit to as per framework helpers - * */ + */ r = amdgpu_bo_reserve(abo, true); if (unlikely(r != 0)) { DRM_ERROR("failed to reserve buffer before flip\n"); @@ -3897,7 +3902,7 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, DRM_ERROR("add_surface: acrtc %d, already busy\n", acrtc_attach->crtc_id); spin_unlock_irqrestore(&crtc->dev->event_lock, flags); - /* In comit tail framework this cannot happen */ + /* In commit tail framework this cannot happen */ WARN_ON(1); } spin_unlock_irqrestore(&crtc->dev->event_lock, flags); @@ -4016,6 +4021,7 @@ void amdgpu_dm_atomic_commit_tail( for_each_crtc_in_state(state, crtc, old_crtc_state, i) { struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); struct drm_crtc_state *new_state = crtc->state; + new_acrtc_state = to_dm_crtc_state(new_state); old_acrtc_state = to_dm_crtc_state(old_crtc_state); @@ -4041,20 +4047,20 @@ void amdgpu_dm_atomic_commit_tail( if (!new_acrtc_state->stream) { /* - * this could happen because of issues with - * userspace notifications delivery. - * In this case userspace tries to set mode on - * display which is disconnect in fact. - * dc_sink in NULL in this case on aconnector. - * We expect reset mode will come soon. - * - * This can also happen when unplug is done - * during resume sequence ended - * - * In this case, we want to pretend we still - * have a sink to keep the pipe running so that - * hw state is consistent with the sw state - */ + * this could happen because of issues with + * userspace notifications delivery. + * In this case userspace tries to set mode on + * display which is disconnect in fact. + * dc_sink in NULL in this case on aconnector. + * We expect reset mode will come soon. + * + * This can also happen when unplug is done + * during resume sequence ended + * + * In this case, we want to pretend we still + * have a sink to keep the pipe running so that + * hw state is consistent with the sw state + */ DRM_DEBUG_KMS("%s: Failed to create new stream for crtc %d\n", __func__, acrtc->base.base.id); continue; @@ -4097,6 +4103,7 @@ void amdgpu_dm_atomic_commit_tail( if (adev->dm.freesync_module) { for (i = 0; i < new_crtcs_count; i++) { struct amdgpu_connector *aconnector = NULL; + new_acrtc_state = to_dm_crtc_state(new_crtcs[i]->base.state); new_stream = new_acrtc_state->stream; @@ -4106,10 +4113,9 @@ void amdgpu_dm_atomic_commit_tail( &new_crtcs[i]->base, false); if (!aconnector) { - DRM_INFO( - "Atomic commit: Failed to find connector for acrtc id:%d " - "skipping freesync init\n", - new_crtcs[i]->crtc_id); + DRM_INFO("Atomic commit: Failed to find connector for acrtc id:%d " + "skipping freesync init\n", + new_crtcs[i]->crtc_id); continue; } @@ -4124,6 +4130,7 @@ void amdgpu_dm_atomic_commit_tail( list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + new_acrtc_state = to_dm_crtc_state(crtc->state); if (new_acrtc_state->stream != NULL) { @@ -4181,6 +4188,7 @@ void amdgpu_dm_atomic_commit_tail( * loop to enable interrupts on newly arrived crtc */ struct amdgpu_crtc *acrtc = new_crtcs[i]; + new_acrtc_state = to_dm_crtc_state(acrtc->base.state); if (adev->dm.freesync_module) @@ -4375,9 +4383,8 @@ static uint32_t remove_from_val_sets( set_count--; - for (; i < set_count; i++) { + for (; i < set_count; i++) val_sets[i] = val_sets[i + 1]; - } return set_count; } @@ -4424,7 +4431,7 @@ static int do_aquire_global_lock( if (ret == 0) DRM_ERROR("[CRTC:%d:%s] hw_done or flip_done " - "timed out\n", crtc->base.id, crtc->name); + "timed out\n", crtc->base.id, crtc->name); drm_crtc_commit_put(commit); } @@ -4483,6 +4490,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, for_each_crtc_in_state(state, crtc, crtc_state, i) { struct amdgpu_crtc *acrtc = NULL; struct amdgpu_connector *aconnector = NULL; + old_acrtc_state = to_dm_crtc_state(crtc->state); new_acrtc_state = to_dm_crtc_state(crtc_state); acrtc = to_amdgpu_crtc(crtc); @@ -4591,7 +4599,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, if (!acrtc || drm_atomic_crtc_needs_modeset(acrtc->base.state)) continue; - /* Skip any thing not scale or underscan chnages */ + /* Skip any thing not scale or underscan changes */ if (!is_scaling_state_different(con_new_state, con_old_state)) continue; @@ -4724,6 +4732,7 @@ void amdgpu_dm_add_sink_to_freesync_module( struct drm_device *dev = connector->dev; struct amdgpu_device *adev = dev->dev_private; + edid_check_required = false; if (!amdgpu_connector->dc_sink) { DRM_ERROR("dc_sink NULL, could not add free_sync module.\n"); -- cgit From bdf9a1a0e16c9e60be796341d79da87503a1cf70 Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Tue, 25 Jul 2017 16:45:18 -0400 Subject: drm/amd/display: move ocsc programming from opp to dpp for dce Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_opp.c | 201 +------------------- drivers/gpu/drm/amd/display/dc/dce/dce_opp.h | 31 --- drivers/gpu/drm/amd/display/dc/dce/dce_transform.c | 210 +++++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dce/dce_transform.h | 30 +++ .../amd/display/dc/dce110/dce110_hw_sequencer.c | 35 +++- .../drm/amd/display/dc/dce110/dce110_opp_csc_v.c | 45 +++-- .../gpu/drm/amd/display/dc/dce110/dce110_opp_v.c | 2 - .../gpu/drm/amd/display/dc/dce110/dce110_opp_v.h | 6 - .../drm/amd/display/dc/dce110/dce110_transform_v.c | 2 + .../drm/amd/display/dc/dce110/dce110_transform_v.h | 7 + drivers/gpu/drm/amd/display/dc/inc/hw/opp.h | 7 +- 11 files changed, 306 insertions(+), 270 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c index f716a9e8784e..7abf252369fb 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c @@ -55,31 +55,9 @@ enum { OUTPUT_CSC_MATRIX_SIZE = 12 }; -static const struct out_csc_color_matrix global_color_matrix[] = { -{ COLOR_SPACE_SRGB, - { 0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} }, -{ COLOR_SPACE_SRGB_LIMITED, - { 0x1B60, 0, 0, 0x200, 0, 0x1B60, 0, 0x200, 0, 0, 0x1B60, 0x200} }, -{ COLOR_SPACE_YCBCR601, - { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x82F, 0x1012, 0x31F, 0x200, 0xFB47, - 0xF6B9, 0xE00, 0x1000} }, -{ COLOR_SPACE_YCBCR709, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x5D2, 0x1394, 0x1FA, - 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} }, -/* TODO: correct values below */ -{ COLOR_SPACE_YCBCR601_LIMITED, { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x991, - 0x12C9, 0x3A6, 0x200, 0xFB47, 0xF6B9, 0xE00, 0x1000} }, -{ COLOR_SPACE_YCBCR709_LIMITED, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x6CE, 0x16E3, - 0x24F, 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} } -}; -enum csc_color_mode { - /* 00 - BITS2:0 Bypass */ - CSC_COLOR_MODE_GRAPHICS_BYPASS, - /* 01 - hard coded coefficient TV RGB */ - CSC_COLOR_MODE_GRAPHICS_PREDEFINED, - /* 04 - programmable OUTPUT CSC coefficient */ - CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC, -}; + + @@ -781,181 +759,8 @@ void dce110_opp_program_fmt( return; } -static void program_color_matrix( - struct dce110_opp *opp110, - const struct out_csc_color_matrix *tbl_entry, - enum grph_color_adjust_option options) -{ - { - REG_SET_2(OUTPUT_CSC_C11_C12, 0, - OUTPUT_CSC_C11, tbl_entry->regval[0], - OUTPUT_CSC_C12, tbl_entry->regval[1]); - } - { - REG_SET_2(OUTPUT_CSC_C13_C14, 0, - OUTPUT_CSC_C11, tbl_entry->regval[2], - OUTPUT_CSC_C12, tbl_entry->regval[3]); - } - { - REG_SET_2(OUTPUT_CSC_C21_C22, 0, - OUTPUT_CSC_C11, tbl_entry->regval[4], - OUTPUT_CSC_C12, tbl_entry->regval[5]); - } - { - REG_SET_2(OUTPUT_CSC_C23_C24, 0, - OUTPUT_CSC_C11, tbl_entry->regval[6], - OUTPUT_CSC_C12, tbl_entry->regval[7]); - } - { - REG_SET_2(OUTPUT_CSC_C31_C32, 0, - OUTPUT_CSC_C11, tbl_entry->regval[8], - OUTPUT_CSC_C12, tbl_entry->regval[9]); - } - { - REG_SET_2(OUTPUT_CSC_C33_C34, 0, - OUTPUT_CSC_C11, tbl_entry->regval[10], - OUTPUT_CSC_C12, tbl_entry->regval[11]); - } -} -static bool configure_graphics_mode( - struct dce110_opp *opp110, - enum csc_color_mode config, - enum graphics_csc_adjust_type csc_adjust_type, - enum dc_color_space color_space) -{ - REG_SET(OUTPUT_CSC_CONTROL, 0, - OUTPUT_CSC_GRPH_MODE, 0); - if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_SW) { - if (config == CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC) { - REG_SET(OUTPUT_CSC_CONTROL, 0, - OUTPUT_CSC_GRPH_MODE, 4); - } else { - - switch (color_space) { - case COLOR_SPACE_SRGB: - /* by pass */ - REG_SET(OUTPUT_CSC_CONTROL, 0, - OUTPUT_CSC_GRPH_MODE, 0); - break; - case COLOR_SPACE_SRGB_LIMITED: - /* TV RGB */ - REG_SET(OUTPUT_CSC_CONTROL, 0, - OUTPUT_CSC_GRPH_MODE, 1); - break; - case COLOR_SPACE_YCBCR601: - case COLOR_SPACE_YCBCR601_LIMITED: - /* YCbCr601 */ - REG_SET(OUTPUT_CSC_CONTROL, 0, - OUTPUT_CSC_GRPH_MODE, 2); - break; - case COLOR_SPACE_YCBCR709: - case COLOR_SPACE_YCBCR709_LIMITED: - /* YCbCr709 */ - REG_SET(OUTPUT_CSC_CONTROL, 0, - OUTPUT_CSC_GRPH_MODE, 3); - break; - default: - return false; - } - } - } else if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_HW) { - switch (color_space) { - case COLOR_SPACE_SRGB: - /* by pass */ - REG_SET(OUTPUT_CSC_CONTROL, 0, - OUTPUT_CSC_GRPH_MODE, 0); - break; - break; - case COLOR_SPACE_SRGB_LIMITED: - /* TV RGB */ - REG_SET(OUTPUT_CSC_CONTROL, 0, - OUTPUT_CSC_GRPH_MODE, 1); - break; - case COLOR_SPACE_YCBCR601: - case COLOR_SPACE_YCBCR601_LIMITED: - /* YCbCr601 */ - REG_SET(OUTPUT_CSC_CONTROL, 0, - OUTPUT_CSC_GRPH_MODE, 2); - break; - case COLOR_SPACE_YCBCR709: - case COLOR_SPACE_YCBCR709_LIMITED: - /* YCbCr709 */ - REG_SET(OUTPUT_CSC_CONTROL, 0, - OUTPUT_CSC_GRPH_MODE, 3); - break; - default: - return false; - } - - } else - /* by pass */ - REG_SET(OUTPUT_CSC_CONTROL, 0, - OUTPUT_CSC_GRPH_MODE, 0); - - return true; -} - -void dce110_opp_set_csc_adjustment( - struct output_pixel_processor *opp, - const struct out_csc_color_matrix *tbl_entry) -{ - struct dce110_opp *opp110 = TO_DCE110_OPP(opp); - enum csc_color_mode config = - CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; - - program_color_matrix( - opp110, tbl_entry, GRAPHICS_CSC_ADJUST_TYPE_SW); - - /* We did everything ,now program DxOUTPUT_CSC_CONTROL */ - configure_graphics_mode(opp110, config, GRAPHICS_CSC_ADJUST_TYPE_SW, - tbl_entry->color_space); -} - -void dce110_opp_set_csc_default( - struct output_pixel_processor *opp, - const struct default_adjustment *default_adjust) -{ - struct dce110_opp *opp110 = TO_DCE110_OPP(opp); - enum csc_color_mode config = - CSC_COLOR_MODE_GRAPHICS_PREDEFINED; - - if (default_adjust->force_hw_default == false) { - const struct out_csc_color_matrix *elm; - /* currently parameter not in use */ - enum grph_color_adjust_option option = - GRPH_COLOR_MATRIX_HW_DEFAULT; - uint32_t i; - /* - * HW default false we program locally defined matrix - * HW default true we use predefined hw matrix and we - * do not need to program matrix - * OEM wants the HW default via runtime parameter. - */ - option = GRPH_COLOR_MATRIX_SW; - - for (i = 0; i < ARRAY_SIZE(global_color_matrix); ++i) { - elm = &global_color_matrix[i]; - if (elm->color_space != default_adjust->out_color_space) - continue; - /* program the matrix with default values from this - * file */ - program_color_matrix(opp110, elm, option); - config = CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; - break; - } - } - - /* configure the what we programmed : - * 1. Default values from this file - * 2. Use hardware default from ROM_A and we do not need to program - * matrix */ - - configure_graphics_mode(opp110, config, - default_adjust->csc_adjust_type, - default_adjust->out_color_space); -} /*****************************************/ @@ -964,8 +769,6 @@ void dce110_opp_set_csc_default( static const struct opp_funcs funcs = { .opp_power_on_regamma_lut = dce110_opp_power_on_regamma_lut, - .opp_set_csc_adjustment = dce110_opp_set_csc_adjustment, - .opp_set_csc_default = dce110_opp_set_csc_default, .opp_set_dyn_expansion = dce110_opp_set_dyn_expansion, .opp_program_regamma_pwl = dce110_opp_program_regamma_pwl, .opp_set_regamma_mode = dce110_opp_set_regamma_mode, diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h index e5045d21a05c..ca09f52f49e5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h @@ -57,13 +57,6 @@ enum dce110_opp_reg_type { SRI(REGAMMA_LUT_INDEX, DCP, id), \ SRI(REGAMMA_LUT_DATA, DCP, id), \ SRI(REGAMMA_CONTROL, DCP, id), \ - SRI(OUTPUT_CSC_C11_C12, DCP, id), \ - SRI(OUTPUT_CSC_C13_C14, DCP, id), \ - SRI(OUTPUT_CSC_C21_C22, DCP, id), \ - SRI(OUTPUT_CSC_C23_C24, DCP, id), \ - SRI(OUTPUT_CSC_C31_C32, DCP, id), \ - SRI(OUTPUT_CSC_C33_C34, DCP, id), \ - SRI(OUTPUT_CSC_CONTROL, DCP, id), \ SRI(FMT_DYNAMIC_EXP_CNTL, FMT, id), \ SRI(FMT_BIT_DEPTH_CONTROL, FMT, id), \ SRI(FMT_CONTROL, FMT, id), \ @@ -129,9 +122,6 @@ enum dce110_opp_reg_type { OPP_SF(REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, mask_sh),\ OPP_SF(REGAMMA_LUT_WRITE_EN_MASK, REGAMMA_LUT_WRITE_EN_MASK, mask_sh),\ OPP_SF(REGAMMA_CONTROL, GRPH_REGAMMA_MODE, mask_sh),\ - OPP_SF(OUTPUT_CSC_C11_C12, OUTPUT_CSC_C11, mask_sh),\ - OPP_SF(OUTPUT_CSC_C11_C12, OUTPUT_CSC_C12, mask_sh),\ - OPP_SF(OUTPUT_CSC_CONTROL, OUTPUT_CSC_GRPH_MODE, mask_sh),\ OPP_SF(FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN, mask_sh),\ OPP_SF(FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE, mask_sh),\ OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN, mask_sh),\ @@ -222,9 +212,6 @@ enum dce110_opp_reg_type { OPP_SF(DCFE0_DCFE_MEM_PWR_STATUS, DCP_REGAMMA_MEM_PWR_STATE, mask_sh),\ OPP_SF(DCP0_REGAMMA_LUT_WRITE_EN_MASK, REGAMMA_LUT_WRITE_EN_MASK, mask_sh),\ OPP_SF(DCP0_REGAMMA_CONTROL, GRPH_REGAMMA_MODE, mask_sh),\ - OPP_SF(DCP0_OUTPUT_CSC_C11_C12, OUTPUT_CSC_C11, mask_sh),\ - OPP_SF(DCP0_OUTPUT_CSC_C11_C12, OUTPUT_CSC_C12, mask_sh),\ - OPP_SF(DCP0_OUTPUT_CSC_CONTROL, OUTPUT_CSC_GRPH_MODE, mask_sh),\ OPP_SF(FMT0_FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN, mask_sh),\ OPP_SF(FMT0_FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE, mask_sh),\ OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN, mask_sh),\ @@ -288,9 +275,6 @@ enum dce110_opp_reg_type { type REGAMMA_LUT_MEM_PWR_STATE; \ type REGAMMA_LUT_WRITE_EN_MASK; \ type GRPH_REGAMMA_MODE; \ - type OUTPUT_CSC_C11; \ - type OUTPUT_CSC_C12; \ - type OUTPUT_CSC_GRPH_MODE; \ type FMT_DYNAMIC_EXP_EN; \ type FMT_DYNAMIC_EXP_MODE; \ type FMT_TRUNCATE_EN; \ @@ -362,13 +346,6 @@ struct dce_opp_registers { uint32_t DCFE_MEM_PWR_STATUS; uint32_t REGAMMA_LUT_DATA; uint32_t REGAMMA_CONTROL; - uint32_t OUTPUT_CSC_C11_C12; - uint32_t OUTPUT_CSC_C13_C14; - uint32_t OUTPUT_CSC_C21_C22; - uint32_t OUTPUT_CSC_C23_C24; - uint32_t OUTPUT_CSC_C31_C32; - uint32_t OUTPUT_CSC_C33_C34; - uint32_t OUTPUT_CSC_CONTROL; uint32_t FMT_DYNAMIC_EXP_CNTL; uint32_t FMT_BIT_DEPTH_CONTROL; uint32_t FMT_CONTROL; @@ -417,14 +394,6 @@ bool dce110_opp_program_regamma_pwl( void dce110_opp_set_regamma_mode(struct output_pixel_processor *opp, enum opp_regamma mode); -void dce110_opp_set_csc_adjustment( - struct output_pixel_processor *opp, - const struct out_csc_color_matrix *tbl_entry); - -void dce110_opp_set_csc_default( - struct output_pixel_processor *opp, - const struct default_adjustment *default_adjust); - /* FORMATTER RELATED */ void dce110_opp_program_bit_depth_reduction( struct output_pixel_processor *opp, diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c index c861fd7b5767..fb64dca427c1 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c @@ -80,6 +80,37 @@ enum dcp_spatial_dither_depth { DCP_SPATIAL_DITHER_DEPTH_24BPP }; +enum csc_color_mode { + /* 00 - BITS2:0 Bypass */ + CSC_COLOR_MODE_GRAPHICS_BYPASS, + /* 01 - hard coded coefficient TV RGB */ + CSC_COLOR_MODE_GRAPHICS_PREDEFINED, + /* 04 - programmable OUTPUT CSC coefficient */ + CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC, +}; + +enum grph_color_adjust_option { + GRPH_COLOR_MATRIX_HW_DEFAULT = 1, + GRPH_COLOR_MATRIX_SW +}; + +static const struct out_csc_color_matrix global_color_matrix[] = { +{ COLOR_SPACE_SRGB, + { 0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} }, +{ COLOR_SPACE_SRGB_LIMITED, + { 0x1B60, 0, 0, 0x200, 0, 0x1B60, 0, 0x200, 0, 0, 0x1B60, 0x200} }, +{ COLOR_SPACE_YCBCR601, + { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x82F, 0x1012, 0x31F, 0x200, 0xFB47, + 0xF6B9, 0xE00, 0x1000} }, +{ COLOR_SPACE_YCBCR709, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x5D2, 0x1394, 0x1FA, + 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} }, +/* TODO: correct values below */ +{ COLOR_SPACE_YCBCR601_LIMITED, { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x991, + 0x12C9, 0x3A6, 0x200, 0xFB47, 0xF6B9, 0xE00, 0x1000} }, +{ COLOR_SPACE_YCBCR709_LIMITED, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x6CE, 0x16E3, + 0x24F, 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} } +}; + static bool setup_scaling_configuration( struct dce_transform *xfm_dce, const struct scaler_data *data) @@ -970,6 +1001,183 @@ static void dce_transform_reset(struct transform *xfm) xfm_dce->filter_v = NULL; } +static void program_color_matrix( + struct dce_transform *xfm_dce, + const struct out_csc_color_matrix *tbl_entry, + enum grph_color_adjust_option options) +{ + { + REG_SET_2(OUTPUT_CSC_C11_C12, 0, + OUTPUT_CSC_C11, tbl_entry->regval[0], + OUTPUT_CSC_C12, tbl_entry->regval[1]); + } + { + REG_SET_2(OUTPUT_CSC_C13_C14, 0, + OUTPUT_CSC_C11, tbl_entry->regval[2], + OUTPUT_CSC_C12, tbl_entry->regval[3]); + } + { + REG_SET_2(OUTPUT_CSC_C21_C22, 0, + OUTPUT_CSC_C11, tbl_entry->regval[4], + OUTPUT_CSC_C12, tbl_entry->regval[5]); + } + { + REG_SET_2(OUTPUT_CSC_C23_C24, 0, + OUTPUT_CSC_C11, tbl_entry->regval[6], + OUTPUT_CSC_C12, tbl_entry->regval[7]); + } + { + REG_SET_2(OUTPUT_CSC_C31_C32, 0, + OUTPUT_CSC_C11, tbl_entry->regval[8], + OUTPUT_CSC_C12, tbl_entry->regval[9]); + } + { + REG_SET_2(OUTPUT_CSC_C33_C34, 0, + OUTPUT_CSC_C11, tbl_entry->regval[10], + OUTPUT_CSC_C12, tbl_entry->regval[11]); + } +} + +static bool configure_graphics_mode( + struct dce_transform *xfm_dce, + enum csc_color_mode config, + enum graphics_csc_adjust_type csc_adjust_type, + enum dc_color_space color_space) +{ + REG_SET(OUTPUT_CSC_CONTROL, 0, + OUTPUT_CSC_GRPH_MODE, 0); + + if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_SW) { + if (config == CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC) { + REG_SET(OUTPUT_CSC_CONTROL, 0, + OUTPUT_CSC_GRPH_MODE, 4); + } else { + + switch (color_space) { + case COLOR_SPACE_SRGB: + /* by pass */ + REG_SET(OUTPUT_CSC_CONTROL, 0, + OUTPUT_CSC_GRPH_MODE, 0); + break; + case COLOR_SPACE_SRGB_LIMITED: + /* TV RGB */ + REG_SET(OUTPUT_CSC_CONTROL, 0, + OUTPUT_CSC_GRPH_MODE, 1); + break; + case COLOR_SPACE_YCBCR601: + case COLOR_SPACE_YCBCR601_LIMITED: + /* YCbCr601 */ + REG_SET(OUTPUT_CSC_CONTROL, 0, + OUTPUT_CSC_GRPH_MODE, 2); + break; + case COLOR_SPACE_YCBCR709: + case COLOR_SPACE_YCBCR709_LIMITED: + /* YCbCr709 */ + REG_SET(OUTPUT_CSC_CONTROL, 0, + OUTPUT_CSC_GRPH_MODE, 3); + break; + default: + return false; + } + } + } else if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_HW) { + switch (color_space) { + case COLOR_SPACE_SRGB: + /* by pass */ + REG_SET(OUTPUT_CSC_CONTROL, 0, + OUTPUT_CSC_GRPH_MODE, 0); + break; + break; + case COLOR_SPACE_SRGB_LIMITED: + /* TV RGB */ + REG_SET(OUTPUT_CSC_CONTROL, 0, + OUTPUT_CSC_GRPH_MODE, 1); + break; + case COLOR_SPACE_YCBCR601: + case COLOR_SPACE_YCBCR601_LIMITED: + /* YCbCr601 */ + REG_SET(OUTPUT_CSC_CONTROL, 0, + OUTPUT_CSC_GRPH_MODE, 2); + break; + case COLOR_SPACE_YCBCR709: + case COLOR_SPACE_YCBCR709_LIMITED: + /* YCbCr709 */ + REG_SET(OUTPUT_CSC_CONTROL, 0, + OUTPUT_CSC_GRPH_MODE, 3); + break; + default: + return false; + } + + } else + /* by pass */ + REG_SET(OUTPUT_CSC_CONTROL, 0, + OUTPUT_CSC_GRPH_MODE, 0); + + return true; +} + +void dce110_opp_set_csc_adjustment( + struct transform *xfm, + const struct out_csc_color_matrix *tbl_entry) +{ + struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); + enum csc_color_mode config = + CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; + + program_color_matrix( + xfm_dce, tbl_entry, GRAPHICS_CSC_ADJUST_TYPE_SW); + + /* We did everything ,now program DxOUTPUT_CSC_CONTROL */ + configure_graphics_mode(xfm_dce, config, GRAPHICS_CSC_ADJUST_TYPE_SW, + tbl_entry->color_space); +} + +void dce110_opp_set_csc_default( + struct transform *xfm, + const struct default_adjustment *default_adjust) +{ + struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); + enum csc_color_mode config = + CSC_COLOR_MODE_GRAPHICS_PREDEFINED; + + if (default_adjust->force_hw_default == false) { + const struct out_csc_color_matrix *elm; + /* currently parameter not in use */ + enum grph_color_adjust_option option = + GRPH_COLOR_MATRIX_HW_DEFAULT; + uint32_t i; + /* + * HW default false we program locally defined matrix + * HW default true we use predefined hw matrix and we + * do not need to program matrix + * OEM wants the HW default via runtime parameter. + */ + option = GRPH_COLOR_MATRIX_SW; + + for (i = 0; i < ARRAY_SIZE(global_color_matrix); ++i) { + elm = &global_color_matrix[i]; + if (elm->color_space != default_adjust->out_color_space) + continue; + /* program the matrix with default values from this + * file */ + program_color_matrix(xfm_dce, elm, option); + config = CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; + break; + } + } + + /* configure the what we programmed : + * 1. Default values from this file + * 2. Use hardware default from ROM_A and we do not need to program + * matrix */ + + configure_graphics_mode(xfm_dce, config, + default_adjust->csc_adjust_type, + default_adjust->out_color_space); +} + + static const struct transform_funcs dce_transform_funcs = { .transform_reset = dce_transform_reset, @@ -977,6 +1185,8 @@ static const struct transform_funcs dce_transform_funcs = { dce_transform_set_scaler, .transform_set_gamut_remap = dce_transform_set_gamut_remap, + .opp_set_csc_adjustment = dce110_opp_set_csc_adjustment, + .opp_set_csc_default = dce110_opp_set_csc_default, .transform_set_pixel_storage_depth = dce_transform_set_pixel_storage_depth, .transform_get_optimal_number_of_taps = diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h index ca6c621151b2..8632d8f4dac0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h @@ -44,6 +44,13 @@ SRI(GAMUT_REMAP_C23_C24, DCP, id), \ SRI(GAMUT_REMAP_C31_C32, DCP, id), \ SRI(GAMUT_REMAP_C33_C34, DCP, id), \ + SRI(OUTPUT_CSC_C11_C12, DCP, id), \ + SRI(OUTPUT_CSC_C13_C14, DCP, id), \ + SRI(OUTPUT_CSC_C21_C22, DCP, id), \ + SRI(OUTPUT_CSC_C23_C24, DCP, id), \ + SRI(OUTPUT_CSC_C31_C32, DCP, id), \ + SRI(OUTPUT_CSC_C33_C34, DCP, id), \ + SRI(OUTPUT_CSC_CONTROL, DCP, id), \ SRI(DENORM_CONTROL, DCP, id), \ SRI(DCP_SPATIAL_DITHER_CNTL, DCP, id), \ SRI(OUT_ROUND_CONTROL, DCP, id), \ @@ -114,6 +121,9 @@ XFM_SF(GAMUT_REMAP_C33_C34, GAMUT_REMAP_C33, mask_sh), \ XFM_SF(GAMUT_REMAP_C33_C34, GAMUT_REMAP_C34, mask_sh), \ XFM_SF(GAMUT_REMAP_CONTROL, GRPH_GAMUT_REMAP_MODE, mask_sh), \ + XFM_SF(OUTPUT_CSC_C11_C12, OUTPUT_CSC_C11, mask_sh),\ + XFM_SF(OUTPUT_CSC_C11_C12, OUTPUT_CSC_C12, mask_sh),\ + XFM_SF(OUTPUT_CSC_CONTROL, OUTPUT_CSC_GRPH_MODE, mask_sh),\ XFM_SF(SCL_MODE, SCL_MODE, mask_sh), \ XFM_SF(SCL_TAP_CONTROL, SCL_H_NUM_OF_TAPS, mask_sh), \ XFM_SF(SCL_TAP_CONTROL, SCL_V_NUM_OF_TAPS, mask_sh), \ @@ -183,6 +193,9 @@ XFM_SF(DCP0_GAMUT_REMAP_C33_C34, GAMUT_REMAP_C33, mask_sh), \ XFM_SF(DCP0_GAMUT_REMAP_C33_C34, GAMUT_REMAP_C34, mask_sh), \ XFM_SF(DCP0_GAMUT_REMAP_CONTROL, GRPH_GAMUT_REMAP_MODE, mask_sh), \ + XFM_SF(DCP0_OUTPUT_CSC_C11_C12, OUTPUT_CSC_C11, mask_sh),\ + XFM_SF(DCP0_OUTPUT_CSC_C11_C12, OUTPUT_CSC_C12, mask_sh),\ + XFM_SF(DCP0_OUTPUT_CSC_CONTROL, OUTPUT_CSC_GRPH_MODE, mask_sh),\ XFM_SF(SCL0_SCL_MODE, SCL_MODE, mask_sh), \ XFM_SF(SCL0_SCL_TAP_CONTROL, SCL_H_NUM_OF_TAPS, mask_sh), \ XFM_SF(SCL0_SCL_TAP_CONTROL, SCL_V_NUM_OF_TAPS, mask_sh), \ @@ -249,6 +262,9 @@ type GAMUT_REMAP_C33; \ type GAMUT_REMAP_C34; \ type GRPH_GAMUT_REMAP_MODE; \ + type OUTPUT_CSC_C11; \ + type OUTPUT_CSC_C12; \ + type OUTPUT_CSC_GRPH_MODE; \ type SCL_MODE; \ type SCL_BYPASS_MODE; \ type SCL_PSCL_EN; \ @@ -302,6 +318,13 @@ struct dce_transform_registers { uint32_t GAMUT_REMAP_C23_C24; uint32_t GAMUT_REMAP_C31_C32; uint32_t GAMUT_REMAP_C33_C34; + uint32_t OUTPUT_CSC_C11_C12; + uint32_t OUTPUT_CSC_C13_C14; + uint32_t OUTPUT_CSC_C21_C22; + uint32_t OUTPUT_CSC_C23_C24; + uint32_t OUTPUT_CSC_C31_C32; + uint32_t OUTPUT_CSC_C33_C34; + uint32_t OUTPUT_CSC_CONTROL; uint32_t DENORM_CONTROL; uint32_t DCP_SPATIAL_DITHER_CNTL; uint32_t OUT_ROUND_CONTROL; @@ -381,5 +404,12 @@ bool dce_transform_get_optimal_number_of_taps( struct scaler_data *scl_data, const struct scaling_taps *in_taps); +void dce110_opp_set_csc_adjustment( + struct transform *xfm, + const struct out_csc_color_matrix *tbl_entry); + +void dce110_opp_set_csc_default( + struct transform *xfm, + const struct default_adjustment *default_adjust); #endif /* _DCE_DCE_TRANSFORM_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 6afe572cfb06..ad831e586021 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1868,8 +1868,8 @@ static void set_default_colors(struct pipe_ctx *pipe_ctx) /* Lb color depth */ default_adjust.lb_color_depth = pipe_ctx->scl_data.lb_params.depth; - pipe_ctx->opp->funcs->opp_set_csc_default( - pipe_ctx->opp, &default_adjust); + pipe_ctx->xfm->funcs->opp_set_csc_default( + pipe_ctx->xfm, &default_adjust); } @@ -1991,8 +1991,8 @@ static void set_plane_config( tbl_entry.regval[i] = pipe_ctx->stream->csc_color_matrix.matrix[i]; - pipe_ctx->opp->funcs->opp_set_csc_adjustment - (pipe_ctx->opp, &tbl_entry); + pipe_ctx->xfm->funcs->opp_set_csc_adjustment + (pipe_ctx->xfm, &tbl_entry); } if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) { @@ -2446,8 +2446,8 @@ static void dce110_program_front_end_for_pipe( tbl_entry.regval[i] = pipe_ctx->stream->csc_color_matrix.matrix[i]; - pipe_ctx->opp->funcs->opp_set_csc_adjustment - (pipe_ctx->opp, &tbl_entry); + pipe_ctx->xfm->funcs->opp_set_csc_adjustment + (pipe_ctx->xfm, &tbl_entry); } if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) { @@ -2587,8 +2587,31 @@ static void dce110_wait_for_mpcc_disconnect( /* do nothing*/ } +static void program_csc_matrix(struct pipe_ctx *pipe_ctx, + enum dc_color_space colorspace, + uint16_t *matrix) +{ + int i; + struct out_csc_color_matrix tbl_entry; + + if (pipe_ctx->stream->csc_color_matrix.enable_adjustment + == true) { + enum dc_color_space color_space = + pipe_ctx->stream->output_color_space; + + //uint16_t matrix[12]; + for (i = 0; i < 12; i++) + tbl_entry.regval[i] = pipe_ctx->stream->csc_color_matrix.matrix[i]; + + tbl_entry.color_space = color_space; + //tbl_entry.regval = matrix; + pipe_ctx->xfm->funcs->opp_set_csc_adjustment(pipe_ctx->xfm, &tbl_entry); + } +} + static const struct hw_sequencer_funcs dce110_funcs = { .program_gamut_remap = program_gamut_remap, + .program_csc_matrix = program_csc_matrix, .init_hw = init_hw, .apply_ctx_to_hw = dce110_apply_ctx_to_hw, .apply_ctx_for_surface = dce110_apply_ctx_for_surface, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c index 019effe4c99c..feb397b5c1a3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c @@ -24,7 +24,7 @@ */ #include "dm_services.h" -#include "dce/dce_opp.h" +#include "dce110_transform_v.h" #include "basics/conversion.h" /* include DCE11 register header files */ @@ -100,12 +100,17 @@ enum csc_color_mode { CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC, }; +enum grph_color_adjust_option { + GRPH_COLOR_MATRIX_HW_DEFAULT = 1, + GRPH_COLOR_MATRIX_SW +}; + static void program_color_matrix_v( - struct dce110_opp *opp110, + struct dce_transform *xfm_dce, const struct out_csc_color_matrix *tbl_entry, enum grph_color_adjust_option options) { - struct dc_context *ctx = opp110->base.ctx; + struct dc_context *ctx = xfm_dce->base.ctx; uint32_t cntl_value = dm_read_reg(ctx, mmCOL_MAN_OUTPUT_CSC_CONTROL); bool use_set_a = (get_reg_field_value(cntl_value, COL_MAN_OUTPUT_CSC_CONTROL, @@ -351,12 +356,12 @@ static void program_color_matrix_v( } static bool configure_graphics_mode_v( - struct dce110_opp *opp110, + struct dce_transform *xfm_dce, enum csc_color_mode config, enum graphics_csc_adjust_type csc_adjust_type, enum dc_color_space color_space) { - struct dc_context *ctx = opp110->base.ctx; + struct dc_context *ctx = xfm_dce->base.ctx; uint32_t addr = mmCOL_MAN_OUTPUT_CSC_CONTROL; uint32_t value = dm_read_reg(ctx, addr); @@ -454,10 +459,10 @@ static bool configure_graphics_mode_v( } /*TODO: color depth is not correct when this is called*/ -static void set_Denormalization(struct output_pixel_processor *opp, +static void set_Denormalization(struct transform *xfm, enum dc_color_depth color_depth) { - uint32_t value = dm_read_reg(opp->ctx, mmDENORM_CLAMP_CONTROL); + uint32_t value = dm_read_reg(xfm->ctx, mmDENORM_CLAMP_CONTROL); switch (color_depth) { case COLOR_DEPTH_888: @@ -495,7 +500,7 @@ static void set_Denormalization(struct output_pixel_processor *opp, DENORM_CLAMP_CONTROL, DENORM_10BIT_OUT); - dm_write_reg(opp->ctx, mmDENORM_CLAMP_CONTROL, value); + dm_write_reg(xfm->ctx, mmDENORM_CLAMP_CONTROL, value); } struct input_csc_matrix { @@ -524,10 +529,10 @@ static const struct input_csc_matrix input_csc_matrix[] = { }; static void program_input_csc( - struct output_pixel_processor *opp, enum dc_color_space color_space) + struct transform *xfm, enum dc_color_space color_space) { int arr_size = sizeof(input_csc_matrix)/sizeof(struct input_csc_matrix); - struct dc_context *ctx = opp->ctx; + struct dc_context *ctx = xfm->ctx; const uint32_t *regval = NULL; bool use_set_a; uint32_t value; @@ -664,10 +669,10 @@ static void program_input_csc( } void dce110_opp_v_set_csc_default( - struct output_pixel_processor *opp, + struct transform *xfm, const struct default_adjustment *default_adjust) { - struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); enum csc_color_mode config = CSC_COLOR_MODE_GRAPHICS_PREDEFINED; @@ -692,13 +697,13 @@ void dce110_opp_v_set_csc_default( /* program the matrix with default values from this * file */ - program_color_matrix_v(opp110, elm, option); + program_color_matrix_v(xfm_dce, elm, option); config = CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; break; } } - program_input_csc(opp, default_adjust->in_color_space); + program_input_csc(xfm, default_adjust->in_color_space); /* configure the what we programmed : * 1. Default values from this file @@ -706,26 +711,26 @@ void dce110_opp_v_set_csc_default( * matrix */ - configure_graphics_mode_v(opp110, config, + configure_graphics_mode_v(xfm_dce, config, default_adjust->csc_adjust_type, default_adjust->out_color_space); - set_Denormalization(opp, default_adjust->color_depth); + set_Denormalization(xfm, default_adjust->color_depth); } void dce110_opp_v_set_csc_adjustment( - struct output_pixel_processor *opp, + struct transform *xfm, const struct out_csc_color_matrix *tbl_entry) { - struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); enum csc_color_mode config = CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; program_color_matrix_v( - opp110, tbl_entry, GRAPHICS_CSC_ADJUST_TYPE_SW); + xfm_dce, tbl_entry, GRAPHICS_CSC_ADJUST_TYPE_SW); /* We did everything ,now program DxOUTPUT_CSC_CONTROL */ - configure_graphics_mode_v(opp110, config, GRAPHICS_CSC_ADJUST_TYPE_SW, + configure_graphics_mode_v(xfm_dce, config, GRAPHICS_CSC_ADJUST_TYPE_SW, tbl_entry->color_space); /*TODO: Check if denormalization is needed*/ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c index 6f8b414cabbc..24d9032faade 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c @@ -39,8 +39,6 @@ static const struct opp_funcs funcs = { .opp_power_on_regamma_lut = dce110_opp_power_on_regamma_lut_v, .opp_program_regamma_pwl = dce110_opp_program_regamma_pwl_v, - .opp_set_csc_default = dce110_opp_v_set_csc_default, - .opp_set_csc_adjustment = dce110_opp_v_set_csc_adjustment, .opp_set_dyn_expansion = dce110_opp_set_dyn_expansion, .opp_set_regamma_mode = dce110_opp_set_regamma_mode_v, .opp_destroy = dce110_opp_destroy, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h index cb26c515d30f..7deaa4f5c659 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h @@ -33,13 +33,7 @@ bool dce110_opp_v_construct(struct dce110_opp *opp110, struct dc_context *ctx); /* underlay callbacks */ -void dce110_opp_v_set_csc_default( - struct output_pixel_processor *opp, - const struct default_adjustment *default_adjust); -void dce110_opp_v_set_csc_adjustment( - struct output_pixel_processor *opp, - const struct out_csc_color_matrix *tbl_entry); bool dce110_opp_program_regamma_pwl_v( struct output_pixel_processor *opp, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c index 8548248d4b19..f655145b3c47 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c @@ -681,6 +681,8 @@ static const struct transform_funcs dce110_xfmv_funcs = { .transform_set_scaler = dce110_xfmv_set_scaler, .transform_set_gamut_remap = dce110_xfmv_set_gamut_remap, + .opp_set_csc_default = dce110_opp_v_set_csc_default, + .opp_set_csc_adjustment = dce110_opp_v_set_csc_adjustment, .transform_set_pixel_storage_depth = dce110_xfmv_set_pixel_storage_depth, .transform_get_optimal_number_of_taps = diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.h index 267af34db3e5..b7f8fdb392a5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.h @@ -34,4 +34,11 @@ bool dce110_transform_v_construct( struct dce_transform *xfm110, struct dc_context *ctx); +void dce110_opp_v_set_csc_default( + struct transform *xfm, + const struct default_adjustment *default_adjust); + +void dce110_opp_v_set_csc_adjustment( + struct transform *xfm, + const struct out_csc_color_matrix *tbl_entry); #endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h index 01d6957c07fb..a4f8556d6797 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h @@ -217,13 +217,8 @@ enum fmt_stereo_action { FMT_STEREO_ACTION_UPDATE_POLARITY }; -enum grph_color_adjust_option { - GRPH_COLOR_MATRIX_HW_DEFAULT = 1, - GRPH_COLOR_MATRIX_SW -}; - struct opp_grph_csc_adjustment { - enum grph_color_adjust_option color_adjust_option; + //enum grph_color_adjust_option color_adjust_option; enum dc_color_space c_space; enum dc_color_depth color_depth; /* clean up to uint32_t */ enum graphics_csc_adjust_type csc_adjust_type; -- cgit From 49baf95740b4f233ea286ebbe7c1066c03f5dd3b Mon Sep 17 00:00:00 2001 From: Vikrant Mhaske Date: Thu, 27 Jul 2017 17:30:52 +0800 Subject: drm/amd/display: Fix DCN compile errors Fix for DCN compiler errors caused due to various submits Signed-off-by: Charlene Liu Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 2299bdaca376..e1298d7029e6 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1475,6 +1475,8 @@ static void dcn10_pipe_control_lock( struct pipe_ctx *pipe, bool lock) { + struct mem_input *mi = NULL; + mi = dc->res_pool->mis[pipe->pipe_idx]; /* use TG master update lock to lock everything on the TG * therefore only top pipe need to lock */ -- cgit From 792671d7e1e28995c6a63104fac1208e19a0ab08 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Wed, 26 Jul 2017 15:51:31 -0400 Subject: drm/amd/display: Add per surface validation hook. For now just validate pixel format in the hook. Signed-off-by: Andrey Grodzovsky Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 11 +++++++++++ drivers/gpu/drm/amd/display/dc/dc.h | 1 + drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c | 12 +++++++++++- drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h | 2 ++ drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c | 3 +++ drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c | 5 ++++- drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c | 4 +++- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 2 ++ 8 files changed, 37 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index d381e380e974..1f4237fc3e53 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -2535,3 +2535,14 @@ bool dc_validate_stream(const struct dc *dc, struct dc_stream *stream) return res == DC_OK; } + +bool dc_validate_surface(const struct dc *dc, const struct dc_surface *surface) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + + /* TODO For now validates pixel format only */ + if (core_dc->res_pool->funcs->validate_surface) + return core_dc->res_pool->funcs->validate_surface(surface) == DC_OK; + + return true; +} diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 58bfb867b71c..e9c9b91d1286 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -589,6 +589,7 @@ struct dc_validation_set { bool dc_validate_stream(const struct dc *dc, struct dc_stream *stream); +bool dc_validate_surface(const struct dc *dc, const struct dc_surface *surface); /* * This function takes a set of resources and checks that they are cofunctional. * diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 9ac246f05110..59f4caf057f7 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -804,12 +804,22 @@ static void dce100_destroy_resource_pool(struct resource_pool **pool) *pool = NULL; } +enum dc_status dce100_validate_surface(const struct dc_surface *surface) +{ + + if (surface->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) + return DC_OK; + + return DC_FAIL_SURFACE_VALIDATE; +} + static const struct resource_funcs dce100_res_pool_funcs = { .destroy = dce100_destroy_resource_pool, .link_enc_create = dce100_link_encoder_create, .validate_with_context = dce100_validate_with_context, .validate_guaranteed = dce100_validate_guaranteed, - .validate_bandwidth = dce100_validate_bandwidth + .validate_bandwidth = dce100_validate_bandwidth, + .validate_surface = dce100_validate_surface, }; static bool construct( diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h index bfd7518c94c9..13fc637eb731 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h @@ -16,4 +16,6 @@ struct resource_pool *dce100_create_resource_pool( uint8_t num_virtual_links, struct core_dc *dc); +enum dc_status dce100_validate_surface(const struct dc_surface *surface); + #endif /* DCE100_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 9589208ea0c8..495f38750ae4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -55,6 +55,8 @@ #include "dce/dce_11_2_d.h" #include "dce/dce_11_2_sh_mask.h" +#include "dce100/dce100_resource.h" + #ifndef mmDP_DPHY_INTERNAL_CTRL #define mmDP_DPHY_INTERNAL_CTRL 0x4aa7 #define mmDP0_DP_DPHY_INTERNAL_CTRL 0x4aa7 @@ -992,6 +994,7 @@ static const struct resource_funcs dce112_res_pool_funcs = { .validate_with_context = dce112_validate_with_context, .validate_guaranteed = dce112_validate_guaranteed, .validate_bandwidth = dce112_validate_bandwidth, + .validate_surface = dce100_validate_surface }; static void bw_calcs_data_update_from_pplib(struct core_dc *dc) diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index f829b6e58bcb..b31307b9d3e3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -60,6 +60,8 @@ #include "vega10/NBIO/nbio_6_1_offset.h" #include "reg_helper.h" +#include "dce100/dce100_resource.h" + #ifndef mmDP0_DP_DPHY_INTERNAL_CTRL #define mmDP0_DP_DPHY_INTERNAL_CTRL 0x210f #define mmDP0_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 @@ -698,7 +700,8 @@ static const struct resource_funcs dce120_res_pool_funcs = { .link_enc_create = dce120_link_encoder_create, .validate_with_context = dce112_validate_with_context, .validate_guaranteed = dce112_validate_guaranteed, - .validate_bandwidth = dce112_validate_bandwidth + .validate_bandwidth = dce112_validate_bandwidth, + .validate_surface = dce100_validate_surface }; static void bw_calcs_data_update_from_pplib(struct core_dc *dc) diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 92f01ed97621..6eeb5e9f656f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -49,6 +49,7 @@ #include "dce/dce_audio.h" #include "dce/dce_hwseq.h" #include "dce80/dce80_hw_sequencer.h" +#include "dce100/dce100_resource.h" #include "reg_helper.h" @@ -823,7 +824,8 @@ static const struct resource_funcs dce80_res_pool_funcs = { .link_enc_create = dce80_link_encoder_create, .validate_with_context = dce80_validate_with_context, .validate_guaranteed = dce80_validate_guaranteed, - .validate_bandwidth = dce80_validate_bandwidth + .validate_bandwidth = dce80_validate_bandwidth, + .validate_surface = dce100_validate_surface }; static bool construct( diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index b312bb3b3350..ab389abf4e79 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -105,6 +105,8 @@ struct resource_funcs { struct validate_context *context, const struct resource_pool *pool, struct dc_stream *stream); + + enum dc_status (*validate_surface)(const struct dc_surface *surface); }; struct audio_support{ -- cgit From cdc95cbb4cc29679e6116548d6e39d02a2b91649 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Wed, 26 Jul 2017 15:51:31 -0400 Subject: drm/amd/display: add preferred mode from Video Format Preference Data Block Signed-off-by: Charlene Liu Reviewed-by: Vitaly Prosyak Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 875b98dae6e1..be6e3ca9fb0d 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -856,8 +856,6 @@ bool dcn_validate_bandwidth( - pipe->stream->timing.v_front_porch; v->vactive[input_idx] = pipe->stream->timing.v_addressable; v->pixel_clock[input_idx] = pipe->stream->timing.pix_clk_khz / 1000.0f; - if (pipe->stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) - v->pixel_clock[input_idx] /= 2; if (!pipe->surface){ -- cgit From a32e24b486e80417e62d34f60d625783affff431 Mon Sep 17 00:00:00 2001 From: Roman Li Date: Thu, 27 Jul 2017 19:53:55 -0400 Subject: drm/amd/display: Initial prototype of FBC implementation - Protected by ENABLE_FBC compile flag - DC part will follow Signed-off-by: Roman Li Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 29 +++++++++++++++++++++++ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 12 ++++++++++ 2 files changed, 41 insertions(+) (limited to 'drivers/gpu') 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 02ca9d6225eb..dfb04c5776ad 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -297,6 +297,30 @@ static void hotplug_notify_work_func(struct work_struct *work) drm_kms_helper_hotplug_event(dev); } +#ifdef ENABLE_FBC +#include "dal_asic_id.h" +/* Allocate memory for FBC compressed data */ +/* TODO: Dynamic allocation */ +#define AMDGPU_FBC_SIZE (3840 * 2160 * 4) + +void amdgpu_dm_initialize_fbc(struct amdgpu_device *adev) +{ + int r; + struct dm_comressor_info *compressor = &adev->dm.compressor; + + if (!compressor->bo_ptr) { + r = amdgpu_bo_create_kernel(adev, AMDGPU_FBC_SIZE, PAGE_SIZE, + AMDGPU_GEM_DOMAIN_VRAM, &compressor->bo_ptr, + &compressor->gpu_addr, &compressor->cpu_addr); + + if (r) + DRM_ERROR("DM: Failed to initialize fbc\n"); + } + +} +#endif + + /* Init display KMS * * Returns 0 on success @@ -347,6 +371,11 @@ int amdgpu_dm_init(struct amdgpu_device *adev) init_data.dce_environment = DCE_ENV_PRODUCTION_DRV; +#ifdef ENABLE_FBC + if (adev->family == FAMILY_CZ) + amdgpu_dm_initialize_fbc(adev); + init_data.fbc_gpu_addr = adev->dm.compressor.gpu_addr; +#endif /* Display Core create. */ adev->dm.dc = dc_create(&init_data); 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 16b2e0849a65..ce0223af7d5f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -72,6 +72,15 @@ struct irq_list_head { struct work_struct work; }; +#ifdef ENABLE_FBC +struct dm_comressor_info { + void *cpu_addr; + struct amdgpu_bo *bo_ptr; + uint64_t gpu_addr; +}; +#endif + + struct amdgpu_display_manager { struct dal *dal; struct dc *dc; @@ -133,6 +142,9 @@ struct amdgpu_display_manager { * Caches device atomic state for suspend/resume */ struct drm_atomic_state *cached_state; +#ifdef ENABLE_FBC + struct dm_comressor_info compressor; +#endif }; /* basic init/fini API */ -- cgit From 690b5e3960810c733f812f8849c3a05415c2f53d Mon Sep 17 00:00:00 2001 From: Roman Li Date: Thu, 27 Jul 2017 20:00:06 -0400 Subject: drm/amd/display: Initial prototype of FBC implementation - Protected by ENABLE_FBC compile flag Signed-off-by: Roman Li Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 7 ++- drivers/gpu/drm/amd/display/dc/dc.h | 3 + drivers/gpu/drm/amd/display/dc/dc_types.h | 3 + .../amd/display/dc/dce110/dce110_hw_sequencer.c | 69 ++++++++++++++++++++++ drivers/gpu/drm/amd/display/dc/inc/compressor.h | 1 + 5 files changed, 81 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index df8c5ca6b22a..1c0d21840cba 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -475,7 +475,9 @@ static bool construct(struct core_dc *dc, dc_version = resource_parse_asic_id(init_params->asic_id); dc->ctx->dce_version = dc_version; - +#ifdef ENABLE_FBC + dc->ctx->fbc_gpu_addr = init_params->fbc_gpu_addr; +#endif /* Resource should construct all asic specific resources. * This should be the only place where we need to parse the asic id */ @@ -919,7 +921,7 @@ bool dc_enable_stereo( #ifdef ENABLE_FBC if (fbc_compressor != NULL && fbc_compressor->funcs->is_fbc_enabled_in_hw(core_dc->fbc_compressor, - &pipe->tg->inst)) + NULL)) fbc_compressor->funcs->disable_fbc(fbc_compressor); #endif @@ -2066,3 +2068,4 @@ void dc_log_hw_state(struct dc *dc) if (core_dc->hwss.log_hw_state) core_dc->hwss.log_hw_state(core_dc); } + diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index e9c9b91d1286..63fd5b3de738 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -231,6 +231,9 @@ struct dc_init_data { enum dce_environment dce_environment; struct dc_config flags; +#ifdef ENABLE_FBC + uint64_t fbc_gpu_addr; +#endif }; struct dc *dc_create(const struct dc_init_data *init_params); diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 99b893fbcb42..ee9e6bc88c32 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -92,6 +92,9 @@ struct dc_context { bool created_bios; struct gpio_service *gpio_service; struct i2caux *i2caux; +#ifdef ENABLE_FBC + uint64_t fbc_gpu_addr; +#endif }; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index ad831e586021..b62a7614fd28 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1528,6 +1528,69 @@ static void apply_min_clocks( } } +#ifdef ENABLE_FBC + +/* + * Check if FBC can be enabled + */ +static enum dc_status validate_fbc(struct core_dc *dc, + struct validate_context *context) +{ + struct pipe_ctx *pipe_ctx = + &context->res_ctx.pipe_ctx[0]; + + ASSERT(dc->fbc_compressor); + + /* FBC memory should be allocated */ + if (!dc->ctx->fbc_gpu_addr) + return DC_ERROR_UNEXPECTED; + + /* Only supports single display */ + if (context->stream_count != 1) + return DC_ERROR_UNEXPECTED; + + /* Only supports eDP */ + if (pipe_ctx->stream->sink->link->connector_signal != SIGNAL_TYPE_EDP) + return DC_ERROR_UNEXPECTED; + + /* PSR should not be enabled */ + if (pipe_ctx->stream->sink->link->psr_enabled) + return DC_ERROR_UNEXPECTED; + + return DC_OK; +} + +/* + * Enable FBC + */ +static enum dc_status enable_fbc(struct core_dc *dc, + struct validate_context *context) +{ + enum dc_status status = validate_fbc(dc, context); + + if (status == DC_OK) { + /* Program GRPH COMPRESSED ADDRESS and PITCH */ + struct compr_addr_and_pitch_params params = {0, 0, 0}; + struct compressor *compr = dc->fbc_compressor; + struct pipe_ctx *pipe_ctx = + &context->res_ctx.pipe_ctx[0]; + + params.source_view_width = + pipe_ctx->stream->timing.h_addressable; + params.source_view_height = + pipe_ctx->stream->timing.v_addressable; + + compr->compr_surface_address.quad_part = dc->ctx->fbc_gpu_addr; + + compr->funcs->surface_address_and_pitch(compr, ¶ms); + compr->funcs->set_fbc_invalidation_triggers(compr, 1); + + compr->funcs->enable_fbc(compr, ¶ms); + } + return status; +} +#endif + static enum dc_status apply_ctx_to_hw_fpga( struct core_dc *dc, struct validate_context *context) @@ -1836,6 +1899,11 @@ enum dc_status dce110_apply_ctx_to_hw( switch_dp_clock_sources(dc, &context->res_ctx); +#ifdef ENABLE_FBC + if (dc->fbc_compressor) + enable_fbc(dc, context); + +#endif return DC_OK; } @@ -2244,6 +2312,7 @@ static void init_hw(struct core_dc *dc) if (dc->fbc_compressor) dc->fbc_compressor->funcs->power_up_fbc(dc->fbc_compressor); #endif + } void dce110_fill_display_configs( diff --git a/drivers/gpu/drm/amd/display/dc/inc/compressor.h b/drivers/gpu/drm/amd/display/dc/inc/compressor.h index 24cca18f3c8f..bcb18f5e1e60 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/compressor.h +++ b/drivers/gpu/drm/amd/display/dc/inc/compressor.h @@ -42,6 +42,7 @@ union fbc_physical_address { uint32_t low_part; int32_t high_part; } addr; + uint64_t quad_part; }; struct compr_addr_and_pitch_params { -- cgit From cbd194881e05844cc54573480aac8df3fd97222d Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Wed, 26 Jul 2017 15:52:28 -0400 Subject: drm/amd/display: Implement plane atomic_check. Use per surface validation hook. Signed-off-by: Andrey Grodzovsky Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'drivers/gpu') 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 dfb04c5776ad..baa788ba6f55 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3141,9 +3141,26 @@ int dm_create_validation_set_for_connector(struct drm_connector *connector, return MODE_OK; } +int dm_plane_atomic_check(struct drm_plane *plane, + struct drm_plane_state *state) +{ + struct amdgpu_device *adev = plane->dev->dev_private; + struct dc *dc = adev->dm.dc; + struct dm_plane_state *dm_plane_state = to_dm_plane_state(state); + + if (!dm_plane_state->surface) + return true; + + if (dc_validate_surface(dc, dm_plane_state->surface)) + return 0; + + return -EINVAL; +} + static const struct drm_plane_helper_funcs dm_plane_helper_funcs = { .prepare_fb = dm_plane_helper_prepare_fb, .cleanup_fb = dm_plane_helper_cleanup_fb, + .atomic_check = dm_plane_atomic_check, }; /* -- cgit From f669089aa12ab9b509ed8ff3755e73794b7941ea Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Thu, 27 Jul 2017 16:47:14 -0400 Subject: drm/amd/display: Add stateless surface validation to validate_resources Signed-off-by: Andrey Grodzovsky Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 1c0d21840cba..83b8b196cc1e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -675,6 +675,21 @@ static bool validate_streams ( return true; } +static bool validate_surfaces( + const struct dc *dc, + const struct dc_validation_set set[], + int set_count) +{ + int i, j; + + for (i = 0; i < set_count; i++) + for (j = 0; j < set[i].surface_count; j++) + if (!dc_validate_surface(dc, set[i].surfaces[j])) + return false; + + return true; +} + struct validate_context *dc_get_validate_context( const struct dc *dc, const struct dc_validation_set set[], @@ -726,6 +741,9 @@ bool dc_validate_resources( if (!validate_streams(dc, set, set_count)) return false; + if (!validate_surfaces(dc, set, set_count)) + return false; + context = dm_alloc(sizeof(struct validate_context)); if (context == NULL) goto context_alloc_fail; @@ -1065,6 +1083,9 @@ bool dc_commit_streams( if (!validate_streams(dc, set, stream_count)) return false; + if (!validate_surfaces(dc, set, stream_count)) + return false; + context = dm_alloc(sizeof(struct validate_context)); if (context == NULL) goto context_alloc_fail; -- cgit From e75504b1292f3a9a173789a06a674fb3ba04450f Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 28 Jul 2017 14:16:13 -0400 Subject: drm/amd/display: fix dcn fe reset memory access error Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index e1298d7029e6..fa19c6b92f29 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -853,8 +853,9 @@ static void plane_atomic_disable(struct core_dc *dc, struct dce_hwseq *hws = dc->hwseq; struct mem_input *mi = dc->res_pool->mis[fe_idx]; struct mpc *mpc = dc->res_pool->mpc; + int opp_id = mi->opp_id; - if (mi->opp_id == 0xf) + if (opp_id == 0xf) return; mpc->funcs->wait_for_idle(mpc, mi->mpcc_id); @@ -876,8 +877,8 @@ static void plane_atomic_disable(struct core_dc *dc, REG_UPDATE(DPP_CONTROL[fe_idx], DPP_CLOCK_ENABLE, 0); - if (dc->res_pool->opps[mi->opp_id]->mpc_tree.num_pipes == 0) - REG_UPDATE(OPP_PIPE_CONTROL[mi->opp_id], + if (dc->res_pool->opps[opp_id]->mpc_tree.num_pipes == 0) + REG_UPDATE(OPP_PIPE_CONTROL[opp_id], OPP_PIPE_CLOCK_EN, 0); if (dc->public.debug.sanity_checks) -- cgit From d70ccd4a65373599fe9aa999dff07c05ea2893e6 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Fri, 28 Jul 2017 15:33:38 -0400 Subject: drm/amd/display: Keep blank until set visibility to true after mode switch Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 21 +++++++++------------ drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c | 4 ++++ 2 files changed, 13 insertions(+), 12 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 83b8b196cc1e..ba8093317aa9 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1609,12 +1609,10 @@ void dc_update_surfaces_and_stream(struct dc *dc, if (!pipe_ctx->surface || pipe_ctx->top_pipe) continue; - if (!pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) { - core_dc->hwss.pipe_control_lock( - core_dc, - pipe_ctx, - true); - } + core_dc->hwss.pipe_control_lock( + core_dc, + pipe_ctx, + true); } if (update_type == UPDATE_TYPE_FULL) break; @@ -1697,12 +1695,11 @@ void dc_update_surfaces_and_stream(struct dc *dc, if (!pipe_ctx->surface || pipe_ctx->top_pipe) continue; - if (!pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) { - core_dc->hwss.pipe_control_lock( - core_dc, - pipe_ctx, - false); - } + core_dc->hwss.pipe_control_lock( + core_dc, + pipe_ctx, + false); + break; } } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c index a8c254f66c98..c46b3e82cdcc 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c @@ -52,6 +52,10 @@ void dce_pipe_control_lock(struct core_dc *dc, uint32_t dcp_grph, scl, blnd, update_lock_mode, val; struct dce_hwseq *hws = dc->hwseq; + /* Not lock pipe when blank */ + if (lock && pipe->tg->funcs->is_blanked(pipe->tg)) + return; + val = REG_GET_4(BLND_V_UPDATE_LOCK[pipe->pipe_idx], BLND_DCP_GRPH_V_UPDATE_LOCK, &dcp_grph, BLND_SCL_V_UPDATE_LOCK, &scl, -- cgit From e51bf71e8c827e1d71235f6b1fe12a952c3a0514 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 28 Jul 2017 18:21:22 -0400 Subject: drm/amd/display: fix bw_calc for hdmi and 420 outputs Signed-off-by: Dmytro Laktyushkin Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index be6e3ca9fb0d..c809ad3738e9 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -923,8 +923,10 @@ bool dcn_validate_bandwidth( if (v->is_line_buffer_bpp_fixed == dcn_bw_yes) v->lb_bit_per_pixel[input_idx] = v->line_buffer_fixed_bpp; v->dcc_rate[input_idx] = 1; /*TODO: Worst case? does this change?*/ - v->output_format[input_idx] = dcn_bw_444; - v->output[input_idx] = dcn_bw_dp; + v->output_format[input_idx] = pipe->stream->timing.pixel_encoding == + PIXEL_ENCODING_YCBCR420 ? dcn_bw_420 : dcn_bw_444; + v->output[input_idx] = pipe->stream->sink->sink_signal == + SIGNAL_TYPE_HDMI_TYPE_A ? dcn_bw_hdmi : dcn_bw_dp; input_idx++; } -- cgit From b701542d29d61c3514f51496168831c8476a8e2a Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Fri, 28 Jul 2017 18:21:22 -0400 Subject: drm/amd/display: fix >340 Mhz with deep color pipe split no display the input to HW formula needs to take care the deep color. Signed-off-by: Charlene Liu Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 13 ++++++++++++- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 2 -- 2 files changed, 12 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index c809ad3738e9..7f7cb8ff124d 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -856,7 +856,18 @@ bool dcn_validate_bandwidth( - pipe->stream->timing.v_front_porch; v->vactive[input_idx] = pipe->stream->timing.v_addressable; v->pixel_clock[input_idx] = pipe->stream->timing.pix_clk_khz / 1000.0f; - + if (pipe->stream->sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A) { + switch (pipe->stream->timing.display_color_depth) { + case COLOR_DEPTH_101010: + v->pixel_clock[input_idx] = (v->pixel_clock[input_idx] * 30) / 24; + break; + case COLOR_DEPTH_121212: + v->pixel_clock[input_idx] = (v->pixel_clock[input_idx] * 36) / 24; + break; + default: + break; + } + } if (!pipe->surface){ v->dcc_enable[input_idx] = dcn_bw_yes; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 1f4237fc3e53..566a1bed9828 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1657,8 +1657,6 @@ static void set_avi_info_frame( color_space == COLOR_SPACE_YCBCR601_LIMITED) hdmi_info->bits.C0_C1 = COLORIMETRY_ITU601; else { - if (stream->timing.pixel_encoding != PIXEL_ENCODING_RGB) - BREAK_TO_DEBUGGER(); hdmi_info->bits.C0_C1 = COLORIMETRY_NO_DATA; } if (color_space == COLOR_SPACE_2020_RGB_FULLRANGE || -- cgit From d54d29db47cdbe1f26776f2d03320ca56c5271fa Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Fri, 28 Jul 2017 12:07:38 -0400 Subject: drm/amd/display: Move and Rename "is_stream_changed()" -Move "is_stream_changed()" to DC interface -Rename "is_stream_changed()" to "dc_is_stream_changed()" Signed-off-by: Bhawanpreet Lakha Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 4 ++-- drivers/gpu/drm/amd/display/dc/dc.h | 2 ++ drivers/gpu/drm/amd/display/dc/inc/resource.h | 2 -- 4 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index ba8093317aa9..5acf4c697ae8 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -641,7 +641,7 @@ static bool is_validation_required( if (set[i].surface_count != context->stream_status[i].surface_count) return true; - if (!is_stream_unchanged(set[i].stream, context->streams[i])) + if (!dc_is_stream_unchanged(set[i].stream, context->streams[i])) return true; for (j = 0; j < set[i].surface_count; j++) { diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 566a1bed9828..005eac5fae80 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1155,7 +1155,7 @@ static bool are_stream_backends_same( return true; } -bool is_stream_unchanged( +bool dc_is_stream_unchanged( struct dc_stream *old_stream, struct dc_stream *stream) { @@ -1176,7 +1176,7 @@ bool resource_validate_attach_surfaces( for (i = 0; i < set_count; i++) { for (j = 0; old_context && j < old_context->stream_count; j++) - if (is_stream_unchanged( + if (dc_is_stream_unchanged( old_context->streams[j], context->streams[i])) { if (!resource_attach_surfaces_to_context( diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 63fd5b3de738..0918569eefa8 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -534,6 +534,8 @@ struct dc_stream_update { struct dc_transfer_func *out_transfer_func; }; +bool dc_is_stream_unchanged( + struct dc_stream *old_stream, struct dc_stream *stream); /* * Setup stream attributes if no stream updates are provided diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index 571bfae62a3c..ca3f49379bea 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -132,8 +132,6 @@ struct pipe_ctx *find_idle_secondary_pipe( bool resource_is_stream_unchanged( struct validate_context *old_context, struct dc_stream *stream); -bool is_stream_unchanged( - struct dc_stream *old_stream, struct dc_stream *stream); bool resource_validate_attach_surfaces( const struct dc_validation_set set[], -- cgit From 9b690ef3c70422cdcd0cf912db33f2c92ef4a53f Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Fri, 28 Jul 2017 13:11:00 -0400 Subject: drm/amd/display: Avoid full modeset when not required Fix IGT test case (kms_atomic_transition) -DRM sets the mode_changed flag, while we don't need to do a full modeset. -We want to override the mode_changed flag in this case If we don't do this, we will still bypass the modeset in DC. This will fail to update the new stream_status, causing nullptr at a later stage when trying to access stream_status" We now avoid this by discarding the new_stream instead of partially filling it. Signed-off-by: Bhawanpreet Lakha Reviewed-by: Andrey Grodzovsky Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 97 +++++++++++++++-------- 1 file changed, 62 insertions(+), 35 deletions(-) (limited to 'drivers/gpu') 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 baa788ba6f55..7b597a0a2ab9 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1608,8 +1608,16 @@ struct dm_connector_state { #define to_dm_connector_state(x)\ container_of((x), struct dm_connector_state, base) -static bool modeset_required(struct drm_crtc_state *crtc_state) +static bool modeset_required(struct drm_crtc_state *crtc_state, + struct dc_stream *new_stream, + struct dc_stream *old_stream) { + if (dc_is_stream_unchanged(new_stream, old_stream)) { + crtc_state->mode_changed = false; + DRM_DEBUG_KMS("Mode change not required, setting mode_changed to %d", + crtc_state->mode_changed); + } + if (!drm_atomic_crtc_needs_modeset(crtc_state)) return false; @@ -2904,7 +2912,8 @@ static int dm_crtc_helper_atomic_check( struct dm_crtc_state *dm_crtc_state = to_dm_crtc_state(state); int ret = -EINVAL; - if (unlikely(!dm_crtc_state->stream && modeset_required(state))) { + if (unlikely(!dm_crtc_state->stream && + modeset_required(state, NULL, dm_crtc_state->stream))) { WARN_ON(1); return ret; } @@ -4087,7 +4096,7 @@ void amdgpu_dm_atomic_commit_tail( * aconnector as needed */ - if (modeset_required(new_state)) { + if (modeset_required(new_state, new_acrtc_state->stream, old_acrtc_state->stream)) { DRM_INFO("Atomic commit: SET crtc id %d: [%p]\n", acrtc->crtc_id, acrtc); @@ -4536,6 +4545,9 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, for_each_crtc_in_state(state, crtc, crtc_state, i) { struct amdgpu_crtc *acrtc = NULL; struct amdgpu_connector *aconnector = NULL; + struct dc_stream *new_stream = NULL; + struct drm_connector_state *conn_state = NULL; + struct dm_connector_state *dm_conn_state = NULL; old_acrtc_state = to_dm_crtc_state(crtc->state); new_acrtc_state = to_dm_crtc_state(crtc_state); @@ -4555,23 +4567,50 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, crtc_state->active_changed, crtc_state->connectors_changed); - if (modeset_required(crtc_state)) { + if (modereset_required(crtc_state)) { - struct dc_stream *new_stream = NULL; - struct drm_connector_state *conn_state = NULL; - struct dm_connector_state *dm_conn_state = NULL; + /* i.e. reset mode */ + if (new_acrtc_state->stream) { + set_count = remove_from_val_sets( + set, + set_count, + new_acrtc_state->stream); + + dc_stream_release(new_acrtc_state->stream); + new_acrtc_state->stream = NULL; + + lock_and_validation_needed = true; + } + + } else { if (aconnector) { - conn_state = drm_atomic_get_connector_state(state, &aconnector->base); + conn_state = drm_atomic_get_connector_state(state, + &aconnector->base); + if (IS_ERR(conn_state)) { ret = PTR_ERR_OR_ZERO(conn_state); goto fail; } dm_conn_state = to_dm_connector_state(conn_state); + + new_stream = create_stream_for_sink(aconnector, + &crtc_state->mode, + dm_conn_state); + + if (!new_stream) { + DRM_DEBUG_KMS("%s: Failed to create new stream for crtc %d\n", + __func__, acrtc->base.base.id); + break; + } + + } - new_stream = create_stream_for_sink(aconnector, &crtc_state->mode, dm_conn_state); + if (modeset_required(crtc_state, new_stream, + old_acrtc_state->stream)) { + /* * we can have no stream on ACTION_SET if a display @@ -4579,39 +4618,27 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, * error, the OS will be updated after detection, and * do the right thing on next atomic commit */ - if (!new_stream) { - DRM_DEBUG_KMS("%s: Failed to create new stream for crtc %d\n", - __func__, acrtc->base.base.id); - break; - } - - if (new_acrtc_state->stream) - dc_stream_release(new_acrtc_state->stream); - - new_acrtc_state->stream = new_stream; - - set_count = update_in_val_sets_stream( - set, - set_count, - old_acrtc_state->stream, - new_acrtc_state->stream, - crtc); - lock_and_validation_needed = true; + if (new_acrtc_state->stream) + dc_stream_release(new_acrtc_state->stream); - } else if (modereset_required(crtc_state)) { + new_acrtc_state->stream = new_stream; - /* i.e. reset mode */ - if (new_acrtc_state->stream) { - set_count = remove_from_val_sets( + set_count = update_in_val_sets_stream( set, set_count, - new_acrtc_state->stream); - - dc_stream_release(new_acrtc_state->stream); - new_acrtc_state->stream = NULL; + old_acrtc_state->stream, + new_acrtc_state->stream, + crtc); lock_and_validation_needed = true; + } else { + /* + * The new stream is unused, so we release it + */ + if (new_stream) + dc_stream_release(new_stream); + } } -- cgit From 7a09f5be98df25a7253e4647e801120b37b90feb Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Fri, 28 Jul 2017 13:08:03 -0400 Subject: drm/amd/display: move regamma from opp to dpp for dce Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_opp.c | 237 -------------------- drivers/gpu/drm/amd/display/dc/dce/dce_opp.h | 113 +--------- drivers/gpu/drm/amd/display/dc/dce/dce_transform.c | 240 +++++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dce/dce_transform.h | 88 ++++++++ .../amd/display/dc/dce110/dce110_hw_sequencer.c | 18 +- .../amd/display/dc/dce110/dce110_opp_regamma_v.c | 88 ++++---- .../gpu/drm/amd/display/dc/dce110/dce110_opp_v.c | 3 - .../gpu/drm/amd/display/dc/dce110/dce110_opp_v.h | 11 - .../drm/amd/display/dc/dce110/dce110_transform_v.c | 3 + .../drm/amd/display/dc/dce110/dce110_transform_v.h | 14 ++ drivers/gpu/drm/amd/display/dc/inc/hw/opp.h | 17 -- 11 files changed, 399 insertions(+), 433 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c index 7abf252369fb..348e4b7047f1 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c @@ -92,242 +92,8 @@ enum { * ***************************************************************************** */ -static void regamma_config_regions_and_segments( - struct dce110_opp *opp110, - const struct pwl_params *params) -{ - const struct gamma_curve *curve; - - { - REG_SET_2(REGAMMA_CNTLA_START_CNTL, 0, - REGAMMA_CNTLA_EXP_REGION_START, params->arr_points[0].custom_float_x, - REGAMMA_CNTLA_EXP_REGION_START_SEGMENT, 0); - } - { - REG_SET(REGAMMA_CNTLA_SLOPE_CNTL, 0, - REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE, params->arr_points[0].custom_float_slope); - - } - { - REG_SET(REGAMMA_CNTLA_END_CNTL1, 0, - REGAMMA_CNTLA_EXP_REGION_END, params->arr_points[1].custom_float_x); - } - { - REG_SET_2(REGAMMA_CNTLA_END_CNTL2, 0, - REGAMMA_CNTLA_EXP_REGION_END_BASE, params->arr_points[1].custom_float_y, - REGAMMA_CNTLA_EXP_REGION_END_SLOPE, params->arr_points[2].custom_float_slope); - } - - curve = params->arr_curve_points; - - { - REG_SET_4(REGAMMA_CNTLA_REGION_0_1, 0, - REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, - REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, - REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, - REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); - } - - curve += 2; - - { - REG_SET_4(REGAMMA_CNTLA_REGION_2_3, 0, - REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, - REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, - REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, - REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); - - } - - curve += 2; - - { - REG_SET_4(REGAMMA_CNTLA_REGION_4_5, 0, - REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, - REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, - REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, - REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); - - } - - curve += 2; - { - REG_SET_4(REGAMMA_CNTLA_REGION_6_7, 0, - REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, - REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, - REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, - REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); - } - - curve += 2; - - { - REG_SET_4(REGAMMA_CNTLA_REGION_8_9, 0, - REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, - REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, - REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, - REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); - - } - - curve += 2; - - { - REG_SET_4(REGAMMA_CNTLA_REGION_10_11, 0, - REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, - REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, - REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, - REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); - - } - - curve += 2; - - { - REG_SET_4(REGAMMA_CNTLA_REGION_12_13, 0, - REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, - REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, - REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, - REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); - - } - - curve += 2; - - { - REG_SET_4(REGAMMA_CNTLA_REGION_14_15, 0, - REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, - REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, - REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, - REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); - } -} - -static void program_pwl( - struct dce110_opp *opp110, - const struct pwl_params *params) -{ - uint32_t value; - int retval; - - { - uint8_t max_tries = 10; - uint8_t counter = 0; - - /* Power on LUT memory */ - if (REG(DCFE_MEM_PWR_CTRL)) - REG_UPDATE(DCFE_MEM_PWR_CTRL, - DCP_REGAMMA_MEM_PWR_DIS, 1); - else - REG_UPDATE(DCFE_MEM_LIGHT_SLEEP_CNTL, - REGAMMA_LUT_LIGHT_SLEEP_DIS, 1); - - while (counter < max_tries) { - if (REG(DCFE_MEM_PWR_STATUS)) { - value = REG_READ(DCFE_MEM_PWR_STATUS); - REG_GET(DCFE_MEM_PWR_STATUS, - DCP_REGAMMA_MEM_PWR_STATE, - &retval); - - if (retval == 0) - break; - ++counter; - } else { - value = REG_READ(DCFE_MEM_LIGHT_SLEEP_CNTL); - REG_GET(DCFE_MEM_LIGHT_SLEEP_CNTL, - REGAMMA_LUT_MEM_PWR_STATE, - &retval); - - if (retval == 0) - break; - ++counter; - } - } - - if (counter == max_tries) { - dm_logger_write(opp110->base.ctx->logger, LOG_WARNING, - "%s: regamma lut was not powered on " - "in a timely manner," - " programming still proceeds\n", - __func__); - } - } - - REG_UPDATE(REGAMMA_LUT_WRITE_EN_MASK, - REGAMMA_LUT_WRITE_EN_MASK, 7); - - REG_WRITE(REGAMMA_LUT_INDEX, 0); - - /* Program REGAMMA_LUT_DATA */ - { - uint32_t i = 0; - const struct pwl_result_data *rgb = params->rgb_resulted; - - while (i != params->hw_points_num) { - - REG_WRITE(REGAMMA_LUT_DATA, rgb->red_reg); - REG_WRITE(REGAMMA_LUT_DATA, rgb->green_reg); - REG_WRITE(REGAMMA_LUT_DATA, rgb->blue_reg); - REG_WRITE(REGAMMA_LUT_DATA, rgb->delta_red_reg); - REG_WRITE(REGAMMA_LUT_DATA, rgb->delta_green_reg); - REG_WRITE(REGAMMA_LUT_DATA, rgb->delta_blue_reg); - - ++rgb; - ++i; - } - } - - /* we are done with DCP LUT memory; re-enable low power mode */ - if (REG(DCFE_MEM_PWR_CTRL)) - REG_UPDATE(DCFE_MEM_PWR_CTRL, - DCP_REGAMMA_MEM_PWR_DIS, 0); - else - REG_UPDATE(DCFE_MEM_LIGHT_SLEEP_CNTL, - REGAMMA_LUT_LIGHT_SLEEP_DIS, 0); -} - -bool dce110_opp_program_regamma_pwl( - struct output_pixel_processor *opp, - const struct pwl_params *params) -{ - struct dce110_opp *opp110 = TO_DCE110_OPP(opp); - - /* Setup regions */ - regamma_config_regions_and_segments(opp110, params); - - /* Program PWL */ - program_pwl(opp110, params); - - return true; -} - -void dce110_opp_power_on_regamma_lut( - struct output_pixel_processor *opp, - bool power_on) -{ - struct dce110_opp *opp110 = TO_DCE110_OPP(opp); - - if (REG(DCFE_MEM_PWR_CTRL)) - REG_UPDATE_2(DCFE_MEM_PWR_CTRL, - DCP_REGAMMA_MEM_PWR_DIS, power_on, - DCP_LUT_MEM_PWR_DIS, power_on); - else - REG_UPDATE_2(DCFE_MEM_LIGHT_SLEEP_CNTL, - REGAMMA_LUT_LIGHT_SLEEP_DIS, power_on, - DCP_LUT_LIGHT_SLEEP_DIS, power_on); - -} - -void dce110_opp_set_regamma_mode(struct output_pixel_processor *opp, - enum opp_regamma mode) -{ - struct dce110_opp *opp110 = TO_DCE110_OPP(opp); - - REG_SET(REGAMMA_CONTROL, 0, - GRPH_REGAMMA_MODE, mode); -} /** * set_truncation @@ -768,10 +534,7 @@ void dce110_opp_program_fmt( /*****************************************/ static const struct opp_funcs funcs = { - .opp_power_on_regamma_lut = dce110_opp_power_on_regamma_lut, .opp_set_dyn_expansion = dce110_opp_set_dyn_expansion, - .opp_program_regamma_pwl = dce110_opp_program_regamma_pwl, - .opp_set_regamma_mode = dce110_opp_set_regamma_mode, .opp_destroy = dce110_opp_destroy, .opp_program_fmt = dce110_opp_program_fmt, .opp_program_bit_depth_reduction = dce110_opp_program_bit_depth_reduction diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h index ca09f52f49e5..0874c22b8b02 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h @@ -41,22 +41,6 @@ enum dce110_opp_reg_type { }; #define OPP_COMMON_REG_LIST_BASE(id) \ - SRI(REGAMMA_CNTLA_START_CNTL, DCP, id), \ - SRI(REGAMMA_CNTLA_SLOPE_CNTL, DCP, id), \ - SRI(REGAMMA_CNTLA_END_CNTL1, DCP, id), \ - SRI(REGAMMA_CNTLA_END_CNTL2, DCP, id), \ - SRI(REGAMMA_CNTLA_REGION_0_1, DCP, id), \ - SRI(REGAMMA_CNTLA_REGION_2_3, DCP, id), \ - SRI(REGAMMA_CNTLA_REGION_4_5, DCP, id), \ - SRI(REGAMMA_CNTLA_REGION_6_7, DCP, id), \ - SRI(REGAMMA_CNTLA_REGION_8_9, DCP, id), \ - SRI(REGAMMA_CNTLA_REGION_10_11, DCP, id), \ - SRI(REGAMMA_CNTLA_REGION_12_13, DCP, id), \ - SRI(REGAMMA_CNTLA_REGION_14_15, DCP, id), \ - SRI(REGAMMA_LUT_WRITE_EN_MASK, DCP, id), \ - SRI(REGAMMA_LUT_INDEX, DCP, id), \ - SRI(REGAMMA_LUT_DATA, DCP, id), \ - SRI(REGAMMA_CONTROL, DCP, id), \ SRI(FMT_DYNAMIC_EXP_CNTL, FMT, id), \ SRI(FMT_BIT_DEPTH_CONTROL, FMT, id), \ SRI(FMT_CONTROL, FMT, id), \ @@ -70,31 +54,24 @@ enum dce110_opp_reg_type { #define OPP_DCE_80_REG_LIST(id) \ OPP_COMMON_REG_LIST_BASE(id), \ - SRI(DCFE_MEM_LIGHT_SLEEP_CNTL, CRTC, id), \ SRI(FMT_TEMPORAL_DITHER_PATTERN_CONTROL, FMT, id), \ SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX, FMT, id), \ SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX, FMT, id) #define OPP_DCE_100_REG_LIST(id) \ OPP_COMMON_REG_LIST_BASE(id), \ - SRI(DCFE_MEM_PWR_CTRL, CRTC, id), \ - SRI(DCFE_MEM_PWR_STATUS, CRTC, id), \ SRI(FMT_TEMPORAL_DITHER_PATTERN_CONTROL, FMT, id), \ SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX, FMT, id), \ SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX, FMT, id) #define OPP_DCE_110_REG_LIST(id) \ OPP_COMMON_REG_LIST_BASE(id), \ - SRI(DCFE_MEM_PWR_CTRL, DCFE, id), \ - SRI(DCFE_MEM_PWR_STATUS, DCFE, id), \ SRI(FMT_TEMPORAL_DITHER_PATTERN_CONTROL, FMT, id), \ SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX, FMT, id), \ SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX, FMT, id) #define OPP_DCE_112_REG_LIST(id) \ OPP_COMMON_REG_LIST_BASE(id), \ - SRI(DCFE_MEM_PWR_CTRL, DCFE, id), \ - SRI(DCFE_MEM_PWR_STATUS, DCFE, id), \ SRI(FMT_TEMPORAL_DITHER_PATTERN_CONTROL, FMT, id), \ SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX, FMT, id), \ SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX, FMT, id), \ @@ -102,26 +79,12 @@ enum dce110_opp_reg_type { #define OPP_DCE_120_REG_LIST(id) \ OPP_COMMON_REG_LIST_BASE(id), \ - SRI(DCFE_MEM_PWR_CTRL, DCFE, id), \ - SRI(DCFE_MEM_PWR_STATUS, DCFE, id), \ SRI(CONTROL, FMT_MEMORY, id) #define OPP_SF(reg_name, field_name, post_fix)\ .field_name = reg_name ## __ ## field_name ## post_fix #define OPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh)\ - OPP_SF(REGAMMA_CNTLA_START_CNTL, REGAMMA_CNTLA_EXP_REGION_START, mask_sh),\ - OPP_SF(REGAMMA_CNTLA_START_CNTL, REGAMMA_CNTLA_EXP_REGION_START_SEGMENT, mask_sh),\ - OPP_SF(REGAMMA_CNTLA_SLOPE_CNTL, REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE, mask_sh),\ - OPP_SF(REGAMMA_CNTLA_END_CNTL1, REGAMMA_CNTLA_EXP_REGION_END, mask_sh),\ - OPP_SF(REGAMMA_CNTLA_END_CNTL2, REGAMMA_CNTLA_EXP_REGION_END_BASE, mask_sh),\ - OPP_SF(REGAMMA_CNTLA_END_CNTL2, REGAMMA_CNTLA_EXP_REGION_END_SLOPE, mask_sh),\ - OPP_SF(REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, mask_sh),\ - OPP_SF(REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, mask_sh),\ - OPP_SF(REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, mask_sh),\ - OPP_SF(REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, mask_sh),\ - OPP_SF(REGAMMA_LUT_WRITE_EN_MASK, REGAMMA_LUT_WRITE_EN_MASK, mask_sh),\ - OPP_SF(REGAMMA_CONTROL, GRPH_REGAMMA_MODE, mask_sh),\ OPP_SF(FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN, mask_sh),\ OPP_SF(FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE, mask_sh),\ OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN, mask_sh),\ @@ -160,27 +123,18 @@ enum dce110_opp_reg_type { #define OPP_COMMON_MASK_SH_LIST_DCE_110(mask_sh)\ OPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh),\ - OPP_SF(DCFE_MEM_PWR_CTRL, DCP_REGAMMA_MEM_PWR_DIS, mask_sh),\ - OPP_SF(DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, mask_sh),\ - OPP_SF(DCFE_MEM_PWR_STATUS, DCP_REGAMMA_MEM_PWR_STATE, mask_sh),\ OPP_SF(FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, mask_sh),\ OPP_SF(FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, mask_sh),\ OPP_SF(FMT_CONTROL, FMT_STEREOSYNC_OVERRIDE, mask_sh) #define OPP_COMMON_MASK_SH_LIST_DCE_100(mask_sh)\ OPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh),\ - OPP_SF(DCFE_MEM_PWR_CTRL, DCP_REGAMMA_MEM_PWR_DIS, mask_sh),\ - OPP_SF(DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, mask_sh),\ - OPP_SF(DCFE_MEM_PWR_STATUS, DCP_REGAMMA_MEM_PWR_STATE, mask_sh),\ OPP_SF(FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, mask_sh),\ OPP_SF(FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, mask_sh),\ OPP_SF(FMT_CONTROL, FMT_STEREOSYNC_OVERRIDE, mask_sh) #define OPP_COMMON_MASK_SH_LIST_DCE_112(mask_sh)\ OPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh),\ - OPP_SF(DCFE_MEM_PWR_CTRL, DCP_REGAMMA_MEM_PWR_DIS, mask_sh),\ - OPP_SF(DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, mask_sh),\ - OPP_SF(DCFE_MEM_PWR_STATUS, DCP_REGAMMA_MEM_PWR_STATE, mask_sh),\ OPP_SF(FMT_MEMORY0_CONTROL, FMT420_MEM0_SOURCE_SEL, mask_sh),\ OPP_SF(FMT_MEMORY0_CONTROL, FMT420_MEM0_PWR_FORCE, mask_sh),\ OPP_SF(FMT_CONTROL, FMT_420_PIXEL_PHASE_LOCKED_CLEAR, mask_sh),\ @@ -191,27 +145,9 @@ enum dce110_opp_reg_type { OPP_SF(FMT_CONTROL, FMT_STEREOSYNC_OVERRIDE, mask_sh) #define OPP_COMMON_MASK_SH_LIST_DCE_80(mask_sh)\ - OPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh),\ - OPP_SF(DCFE_MEM_LIGHT_SLEEP_CNTL, REGAMMA_LUT_LIGHT_SLEEP_DIS, mask_sh),\ - OPP_SF(DCFE_MEM_LIGHT_SLEEP_CNTL, DCP_LUT_LIGHT_SLEEP_DIS, mask_sh),\ - OPP_SF(DCFE_MEM_LIGHT_SLEEP_CNTL, REGAMMA_LUT_MEM_PWR_STATE, mask_sh) + OPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh) #define OPP_COMMON_MASK_SH_LIST_DCE_120(mask_sh)\ - OPP_SF(DCFE0_DCFE_MEM_PWR_CTRL, DCP_REGAMMA_MEM_PWR_DIS, mask_sh),\ - OPP_SF(DCFE0_DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, mask_sh),\ - OPP_SF(DCP0_REGAMMA_CNTLA_START_CNTL, REGAMMA_CNTLA_EXP_REGION_START, mask_sh),\ - OPP_SF(DCP0_REGAMMA_CNTLA_START_CNTL, REGAMMA_CNTLA_EXP_REGION_START_SEGMENT, mask_sh),\ - OPP_SF(DCP0_REGAMMA_CNTLA_SLOPE_CNTL, REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE, mask_sh),\ - OPP_SF(DCP0_REGAMMA_CNTLA_END_CNTL1, REGAMMA_CNTLA_EXP_REGION_END, mask_sh),\ - OPP_SF(DCP0_REGAMMA_CNTLA_END_CNTL2, REGAMMA_CNTLA_EXP_REGION_END_BASE, mask_sh),\ - OPP_SF(DCP0_REGAMMA_CNTLA_END_CNTL2, REGAMMA_CNTLA_EXP_REGION_END_SLOPE, mask_sh),\ - OPP_SF(DCP0_REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, mask_sh),\ - OPP_SF(DCP0_REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, mask_sh),\ - OPP_SF(DCP0_REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, mask_sh),\ - OPP_SF(DCP0_REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, mask_sh),\ - OPP_SF(DCFE0_DCFE_MEM_PWR_STATUS, DCP_REGAMMA_MEM_PWR_STATE, mask_sh),\ - OPP_SF(DCP0_REGAMMA_LUT_WRITE_EN_MASK, REGAMMA_LUT_WRITE_EN_MASK, mask_sh),\ - OPP_SF(DCP0_REGAMMA_CONTROL, GRPH_REGAMMA_MODE, mask_sh),\ OPP_SF(FMT0_FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN, mask_sh),\ OPP_SF(FMT0_FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE, mask_sh),\ OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN, mask_sh),\ @@ -257,24 +193,6 @@ enum dce110_opp_reg_type { OPP_SF(FMT0_FMT_CONTROL, FMT_CBCR_BIT_REDUCTION_BYPASS, mask_sh) #define OPP_REG_FIELD_LIST(type) \ - type DCP_REGAMMA_MEM_PWR_DIS; \ - type DCP_LUT_MEM_PWR_DIS; \ - type REGAMMA_LUT_LIGHT_SLEEP_DIS; \ - type DCP_LUT_LIGHT_SLEEP_DIS; \ - type REGAMMA_CNTLA_EXP_REGION_START; \ - type REGAMMA_CNTLA_EXP_REGION_START_SEGMENT; \ - type REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE; \ - type REGAMMA_CNTLA_EXP_REGION_END; \ - type REGAMMA_CNTLA_EXP_REGION_END_BASE; \ - type REGAMMA_CNTLA_EXP_REGION_END_SLOPE; \ - type REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET; \ - type REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS; \ - type REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET; \ - type REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS; \ - type DCP_REGAMMA_MEM_PWR_STATE; \ - type REGAMMA_LUT_MEM_PWR_STATE; \ - type REGAMMA_LUT_WRITE_EN_MASK; \ - type GRPH_REGAMMA_MODE; \ type FMT_DYNAMIC_EXP_EN; \ type FMT_DYNAMIC_EXP_MODE; \ type FMT_TRUNCATE_EN; \ @@ -327,25 +245,6 @@ struct dce_opp_mask { }; struct dce_opp_registers { - uint32_t DCFE_MEM_PWR_CTRL; - uint32_t DCFE_MEM_LIGHT_SLEEP_CNTL; - uint32_t REGAMMA_CNTLA_START_CNTL; - uint32_t REGAMMA_CNTLA_SLOPE_CNTL; - uint32_t REGAMMA_CNTLA_END_CNTL1; - uint32_t REGAMMA_CNTLA_END_CNTL2; - uint32_t REGAMMA_CNTLA_REGION_0_1; - uint32_t REGAMMA_CNTLA_REGION_2_3; - uint32_t REGAMMA_CNTLA_REGION_4_5; - uint32_t REGAMMA_CNTLA_REGION_6_7; - uint32_t REGAMMA_CNTLA_REGION_8_9; - uint32_t REGAMMA_CNTLA_REGION_10_11; - uint32_t REGAMMA_CNTLA_REGION_12_13; - uint32_t REGAMMA_CNTLA_REGION_14_15; - uint32_t REGAMMA_LUT_WRITE_EN_MASK; - uint32_t REGAMMA_LUT_INDEX; - uint32_t DCFE_MEM_PWR_STATUS; - uint32_t REGAMMA_LUT_DATA; - uint32_t REGAMMA_CONTROL; uint32_t FMT_DYNAMIC_EXP_CNTL; uint32_t FMT_BIT_DEPTH_CONTROL; uint32_t FMT_CONTROL; @@ -382,17 +281,7 @@ bool dce110_opp_construct(struct dce110_opp *opp110, void dce110_opp_destroy(struct output_pixel_processor **opp); -/* REGAMMA RELATED */ -void dce110_opp_power_on_regamma_lut( - struct output_pixel_processor *opp, - bool power_on); - -bool dce110_opp_program_regamma_pwl( - struct output_pixel_processor *opp, - const struct pwl_params *params); -void dce110_opp_set_regamma_mode(struct output_pixel_processor *opp, - enum opp_regamma mode); /* FORMATTER RELATED */ void dce110_opp_program_bit_depth_reduction( diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c index fb64dca427c1..0e366021cf16 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c @@ -1177,7 +1177,244 @@ void dce110_opp_set_csc_default( default_adjust->out_color_space); } +static void program_pwl( + struct dce_transform *xfm_dce, + const struct pwl_params *params) +{ + uint32_t value; + int retval; + + { + uint8_t max_tries = 10; + uint8_t counter = 0; + + /* Power on LUT memory */ + if (REG(DCFE_MEM_PWR_CTRL)) + REG_UPDATE(DCFE_MEM_PWR_CTRL, + DCP_REGAMMA_MEM_PWR_DIS, 1); + else + REG_UPDATE(DCFE_MEM_LIGHT_SLEEP_CNTL, + REGAMMA_LUT_LIGHT_SLEEP_DIS, 1); + + while (counter < max_tries) { + if (REG(DCFE_MEM_PWR_STATUS)) { + value = REG_READ(DCFE_MEM_PWR_STATUS); + REG_GET(DCFE_MEM_PWR_STATUS, + DCP_REGAMMA_MEM_PWR_STATE, + &retval); + + if (retval == 0) + break; + ++counter; + } else { + value = REG_READ(DCFE_MEM_LIGHT_SLEEP_CNTL); + REG_GET(DCFE_MEM_LIGHT_SLEEP_CNTL, + REGAMMA_LUT_MEM_PWR_STATE, + &retval); + + if (retval == 0) + break; + ++counter; + } + } + + if (counter == max_tries) { + dm_logger_write(xfm_dce->base.ctx->logger, LOG_WARNING, + "%s: regamma lut was not powered on " + "in a timely manner," + " programming still proceeds\n", + __func__); + } + } + + REG_UPDATE(REGAMMA_LUT_WRITE_EN_MASK, + REGAMMA_LUT_WRITE_EN_MASK, 7); + + REG_WRITE(REGAMMA_LUT_INDEX, 0); + + /* Program REGAMMA_LUT_DATA */ + { + uint32_t i = 0; + const struct pwl_result_data *rgb = params->rgb_resulted; + + while (i != params->hw_points_num) { + + REG_WRITE(REGAMMA_LUT_DATA, rgb->red_reg); + REG_WRITE(REGAMMA_LUT_DATA, rgb->green_reg); + REG_WRITE(REGAMMA_LUT_DATA, rgb->blue_reg); + REG_WRITE(REGAMMA_LUT_DATA, rgb->delta_red_reg); + REG_WRITE(REGAMMA_LUT_DATA, rgb->delta_green_reg); + REG_WRITE(REGAMMA_LUT_DATA, rgb->delta_blue_reg); + + ++rgb; + ++i; + } + } + + /* we are done with DCP LUT memory; re-enable low power mode */ + if (REG(DCFE_MEM_PWR_CTRL)) + REG_UPDATE(DCFE_MEM_PWR_CTRL, + DCP_REGAMMA_MEM_PWR_DIS, 0); + else + REG_UPDATE(DCFE_MEM_LIGHT_SLEEP_CNTL, + REGAMMA_LUT_LIGHT_SLEEP_DIS, 0); +} + +static void regamma_config_regions_and_segments( + struct dce_transform *xfm_dce, + const struct pwl_params *params) +{ + const struct gamma_curve *curve; + + { + REG_SET_2(REGAMMA_CNTLA_START_CNTL, 0, + REGAMMA_CNTLA_EXP_REGION_START, params->arr_points[0].custom_float_x, + REGAMMA_CNTLA_EXP_REGION_START_SEGMENT, 0); + } + { + REG_SET(REGAMMA_CNTLA_SLOPE_CNTL, 0, + REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE, params->arr_points[0].custom_float_slope); + + } + { + REG_SET(REGAMMA_CNTLA_END_CNTL1, 0, + REGAMMA_CNTLA_EXP_REGION_END, params->arr_points[1].custom_float_x); + } + { + REG_SET_2(REGAMMA_CNTLA_END_CNTL2, 0, + REGAMMA_CNTLA_EXP_REGION_END_BASE, params->arr_points[1].custom_float_y, + REGAMMA_CNTLA_EXP_REGION_END_SLOPE, params->arr_points[2].custom_float_slope); + } + + curve = params->arr_curve_points; + + { + REG_SET_4(REGAMMA_CNTLA_REGION_0_1, 0, + REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + } + + curve += 2; + + { + REG_SET_4(REGAMMA_CNTLA_REGION_2_3, 0, + REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + } + + curve += 2; + + { + REG_SET_4(REGAMMA_CNTLA_REGION_4_5, 0, + REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + } + + curve += 2; + + { + REG_SET_4(REGAMMA_CNTLA_REGION_6_7, 0, + REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + } + + curve += 2; + + { + REG_SET_4(REGAMMA_CNTLA_REGION_8_9, 0, + REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + } + + curve += 2; + + { + REG_SET_4(REGAMMA_CNTLA_REGION_10_11, 0, + REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + } + + curve += 2; + + { + REG_SET_4(REGAMMA_CNTLA_REGION_12_13, 0, + REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + } + + curve += 2; + + { + REG_SET_4(REGAMMA_CNTLA_REGION_14_15, 0, + REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + } +} + + + +bool dce110_opp_program_regamma_pwl( + struct transform *xfm, + const struct pwl_params *params) +{ + struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); + /* Setup regions */ + regamma_config_regions_and_segments(xfm_dce, params); + + /* Program PWL */ + program_pwl(xfm_dce, params); + + return true; +} + +void dce110_opp_power_on_regamma_lut( + struct transform *xfm, + bool power_on) +{ + struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); + + if (REG(DCFE_MEM_PWR_CTRL)) + REG_UPDATE_2(DCFE_MEM_PWR_CTRL, + DCP_REGAMMA_MEM_PWR_DIS, power_on, + DCP_LUT_MEM_PWR_DIS, power_on); + else + REG_UPDATE_2(DCFE_MEM_LIGHT_SLEEP_CNTL, + REGAMMA_LUT_LIGHT_SLEEP_DIS, power_on, + DCP_LUT_LIGHT_SLEEP_DIS, power_on); + +} + +void dce110_opp_set_regamma_mode(struct transform *xfm, + enum opp_regamma mode) +{ + struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); + + REG_SET(REGAMMA_CONTROL, 0, + GRPH_REGAMMA_MODE, mode); +} static const struct transform_funcs dce_transform_funcs = { .transform_reset = dce_transform_reset, @@ -1187,6 +1424,9 @@ static const struct transform_funcs dce_transform_funcs = { dce_transform_set_gamut_remap, .opp_set_csc_adjustment = dce110_opp_set_csc_adjustment, .opp_set_csc_default = dce110_opp_set_csc_default, + .opp_power_on_regamma_lut = dce110_opp_power_on_regamma_lut, + .opp_program_regamma_pwl = dce110_opp_program_regamma_pwl, + .opp_set_regamma_mode = dce110_opp_set_regamma_mode, .transform_set_pixel_storage_depth = dce_transform_set_pixel_storage_depth, .transform_get_optimal_number_of_taps = diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h index 8632d8f4dac0..f9622ff54560 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h @@ -51,6 +51,22 @@ SRI(OUTPUT_CSC_C31_C32, DCP, id), \ SRI(OUTPUT_CSC_C33_C34, DCP, id), \ SRI(OUTPUT_CSC_CONTROL, DCP, id), \ + SRI(REGAMMA_CNTLA_START_CNTL, DCP, id), \ + SRI(REGAMMA_CNTLA_SLOPE_CNTL, DCP, id), \ + SRI(REGAMMA_CNTLA_END_CNTL1, DCP, id), \ + SRI(REGAMMA_CNTLA_END_CNTL2, DCP, id), \ + SRI(REGAMMA_CNTLA_REGION_0_1, DCP, id), \ + SRI(REGAMMA_CNTLA_REGION_2_3, DCP, id), \ + SRI(REGAMMA_CNTLA_REGION_4_5, DCP, id), \ + SRI(REGAMMA_CNTLA_REGION_6_7, DCP, id), \ + SRI(REGAMMA_CNTLA_REGION_8_9, DCP, id), \ + SRI(REGAMMA_CNTLA_REGION_10_11, DCP, id), \ + SRI(REGAMMA_CNTLA_REGION_12_13, DCP, id), \ + SRI(REGAMMA_CNTLA_REGION_14_15, DCP, id), \ + SRI(REGAMMA_LUT_WRITE_EN_MASK, DCP, id), \ + SRI(REGAMMA_LUT_INDEX, DCP, id), \ + SRI(REGAMMA_LUT_DATA, DCP, id), \ + SRI(REGAMMA_CONTROL, DCP, id), \ SRI(DENORM_CONTROL, DCP, id), \ SRI(DCP_SPATIAL_DITHER_CNTL, DCP, id), \ SRI(OUT_ROUND_CONTROL, DCP, id), \ @@ -124,6 +140,18 @@ XFM_SF(OUTPUT_CSC_C11_C12, OUTPUT_CSC_C11, mask_sh),\ XFM_SF(OUTPUT_CSC_C11_C12, OUTPUT_CSC_C12, mask_sh),\ XFM_SF(OUTPUT_CSC_CONTROL, OUTPUT_CSC_GRPH_MODE, mask_sh),\ + XFM_SF(REGAMMA_CNTLA_START_CNTL, REGAMMA_CNTLA_EXP_REGION_START, mask_sh),\ + XFM_SF(REGAMMA_CNTLA_START_CNTL, REGAMMA_CNTLA_EXP_REGION_START_SEGMENT, mask_sh),\ + XFM_SF(REGAMMA_CNTLA_SLOPE_CNTL, REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE, mask_sh),\ + XFM_SF(REGAMMA_CNTLA_END_CNTL1, REGAMMA_CNTLA_EXP_REGION_END, mask_sh),\ + XFM_SF(REGAMMA_CNTLA_END_CNTL2, REGAMMA_CNTLA_EXP_REGION_END_BASE, mask_sh),\ + XFM_SF(REGAMMA_CNTLA_END_CNTL2, REGAMMA_CNTLA_EXP_REGION_END_SLOPE, mask_sh),\ + XFM_SF(REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, mask_sh),\ + XFM_SF(REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, mask_sh),\ + XFM_SF(REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, mask_sh),\ + XFM_SF(REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, mask_sh),\ + XFM_SF(REGAMMA_LUT_WRITE_EN_MASK, REGAMMA_LUT_WRITE_EN_MASK, mask_sh),\ + XFM_SF(REGAMMA_CONTROL, GRPH_REGAMMA_MODE, mask_sh),\ XFM_SF(SCL_MODE, SCL_MODE, mask_sh), \ XFM_SF(SCL_TAP_CONTROL, SCL_H_NUM_OF_TAPS, mask_sh), \ XFM_SF(SCL_TAP_CONTROL, SCL_V_NUM_OF_TAPS, mask_sh), \ @@ -161,6 +189,9 @@ XFM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh), \ XFM_SF(DCFE_MEM_PWR_CTRL, SCL_COEFF_MEM_PWR_DIS, mask_sh), \ XFM_SF(DCFE_MEM_PWR_STATUS, SCL_COEFF_MEM_PWR_STATE, mask_sh), \ + XFM_SF(DCFE_MEM_PWR_CTRL, DCP_REGAMMA_MEM_PWR_DIS, mask_sh),\ + XFM_SF(DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, mask_sh),\ + XFM_SF(DCFE_MEM_PWR_STATUS, DCP_REGAMMA_MEM_PWR_STATE, mask_sh),\ XFM_SF(SCL_MODE, SCL_PSCL_EN, mask_sh) #define XFM_COMMON_MASK_SH_LIST_SOC_BASE(mask_sh) \ @@ -196,6 +227,16 @@ XFM_SF(DCP0_OUTPUT_CSC_C11_C12, OUTPUT_CSC_C11, mask_sh),\ XFM_SF(DCP0_OUTPUT_CSC_C11_C12, OUTPUT_CSC_C12, mask_sh),\ XFM_SF(DCP0_OUTPUT_CSC_CONTROL, OUTPUT_CSC_GRPH_MODE, mask_sh),\ + XFM_SF(DCP0_REGAMMA_CNTLA_START_CNTL, REGAMMA_CNTLA_EXP_REGION_START, mask_sh),\ + XFM_SF(DCP0_REGAMMA_CNTLA_START_CNTL, REGAMMA_CNTLA_EXP_REGION_START_SEGMENT, mask_sh),\ + XFM_SF(DCP0_REGAMMA_CNTLA_SLOPE_CNTL, REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE, mask_sh),\ + XFM_SF(DCP0_REGAMMA_CNTLA_END_CNTL1, REGAMMA_CNTLA_EXP_REGION_END, mask_sh),\ + XFM_SF(DCP0_REGAMMA_CNTLA_END_CNTL2, REGAMMA_CNTLA_EXP_REGION_END_BASE, mask_sh),\ + XFM_SF(DCP0_REGAMMA_CNTLA_END_CNTL2, REGAMMA_CNTLA_EXP_REGION_END_SLOPE, mask_sh),\ + XFM_SF(DCP0_REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, mask_sh),\ + XFM_SF(DCP0_REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, mask_sh),\ + XFM_SF(DCP0_REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, mask_sh),\ + XFM_SF(DCP0_REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, mask_sh),\ XFM_SF(SCL0_SCL_MODE, SCL_MODE, mask_sh), \ XFM_SF(SCL0_SCL_TAP_CONTROL, SCL_H_NUM_OF_TAPS, mask_sh), \ XFM_SF(SCL0_SCL_TAP_CONTROL, SCL_V_NUM_OF_TAPS, mask_sh), \ @@ -265,6 +306,24 @@ type OUTPUT_CSC_C11; \ type OUTPUT_CSC_C12; \ type OUTPUT_CSC_GRPH_MODE; \ + type DCP_REGAMMA_MEM_PWR_DIS; \ + type DCP_LUT_MEM_PWR_DIS; \ + type REGAMMA_LUT_LIGHT_SLEEP_DIS; \ + type DCP_LUT_LIGHT_SLEEP_DIS; \ + type REGAMMA_CNTLA_EXP_REGION_START; \ + type REGAMMA_CNTLA_EXP_REGION_START_SEGMENT; \ + type REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE; \ + type REGAMMA_CNTLA_EXP_REGION_END; \ + type REGAMMA_CNTLA_EXP_REGION_END_BASE; \ + type REGAMMA_CNTLA_EXP_REGION_END_SLOPE; \ + type REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET; \ + type REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS; \ + type REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET; \ + type REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS; \ + type DCP_REGAMMA_MEM_PWR_STATE; \ + type REGAMMA_LUT_MEM_PWR_STATE; \ + type REGAMMA_LUT_WRITE_EN_MASK; \ + type GRPH_REGAMMA_MODE; \ type SCL_MODE; \ type SCL_BYPASS_MODE; \ type SCL_PSCL_EN; \ @@ -325,6 +384,23 @@ struct dce_transform_registers { uint32_t OUTPUT_CSC_C31_C32; uint32_t OUTPUT_CSC_C33_C34; uint32_t OUTPUT_CSC_CONTROL; + uint32_t DCFE_MEM_LIGHT_SLEEP_CNTL; + uint32_t REGAMMA_CNTLA_START_CNTL; + uint32_t REGAMMA_CNTLA_SLOPE_CNTL; + uint32_t REGAMMA_CNTLA_END_CNTL1; + uint32_t REGAMMA_CNTLA_END_CNTL2; + uint32_t REGAMMA_CNTLA_REGION_0_1; + uint32_t REGAMMA_CNTLA_REGION_2_3; + uint32_t REGAMMA_CNTLA_REGION_4_5; + uint32_t REGAMMA_CNTLA_REGION_6_7; + uint32_t REGAMMA_CNTLA_REGION_8_9; + uint32_t REGAMMA_CNTLA_REGION_10_11; + uint32_t REGAMMA_CNTLA_REGION_12_13; + uint32_t REGAMMA_CNTLA_REGION_14_15; + uint32_t REGAMMA_LUT_WRITE_EN_MASK; + uint32_t REGAMMA_LUT_INDEX; + uint32_t REGAMMA_LUT_DATA; + uint32_t REGAMMA_CONTROL; uint32_t DENORM_CONTROL; uint32_t DCP_SPATIAL_DITHER_CNTL; uint32_t OUT_ROUND_CONTROL; @@ -412,4 +488,16 @@ void dce110_opp_set_csc_default( struct transform *xfm, const struct default_adjustment *default_adjust); +/* REGAMMA RELATED */ +void dce110_opp_power_on_regamma_lut( + struct transform *xfm, + bool power_on); + +bool dce110_opp_program_regamma_pwl( + struct transform *xfm, + const struct pwl_params *params); + +void dce110_opp_set_regamma_mode(struct transform *xfm, + enum opp_regamma mode); + #endif /* _DCE_DCE_TRANSFORM_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index b62a7614fd28..1f18fcf52661 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -625,26 +625,26 @@ static bool dce110_set_output_transfer_func( struct pipe_ctx *pipe_ctx, const struct dc_stream *stream) { - struct output_pixel_processor *opp = pipe_ctx->opp; + struct transform *xfm = pipe_ctx->xfm; - opp->funcs->opp_power_on_regamma_lut(opp, true); - opp->regamma_params.hw_points_num = GAMMA_HW_POINTS_NUM; + xfm->funcs->opp_power_on_regamma_lut(xfm, true); + xfm->regamma_params.hw_points_num = GAMMA_HW_POINTS_NUM; if (stream->out_transfer_func && stream->out_transfer_func->type == TF_TYPE_PREDEFINED && stream->out_transfer_func->tf == TRANSFER_FUNCTION_SRGB) { - opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_SRGB); + xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_SRGB); } else if (dce110_translate_regamma_to_hw_format( - stream->out_transfer_func, &opp->regamma_params)) { - opp->funcs->opp_program_regamma_pwl(opp, &opp->regamma_params); - opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_USER); + stream->out_transfer_func, &xfm->regamma_params)) { + xfm->funcs->opp_program_regamma_pwl(xfm, &xfm->regamma_params); + xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_USER); } else { - opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_BYPASS); + xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_BYPASS); } - opp->funcs->opp_power_on_regamma_lut(opp, false); + xfm->funcs->opp_power_on_regamma_lut(xfm, false); return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c index 876445f14c85..c86105b8cfaf 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c @@ -29,12 +29,12 @@ #include "dce/dce_11_0_d.h" #include "dce/dce_11_0_sh_mask.h" -#include "dce/dce_opp.h" +#include "dce110_transform_v.h" -static void power_on_lut(struct output_pixel_processor *opp, +static void power_on_lut(struct transform *xfm, bool power_on, bool inputgamma, bool regamma) { - uint32_t value = dm_read_reg(opp->ctx, mmDCFEV_MEM_PWR_CTRL); + uint32_t value = dm_read_reg(xfm->ctx, mmDCFEV_MEM_PWR_CTRL); int i; if (power_on) { @@ -65,10 +65,10 @@ static void power_on_lut(struct output_pixel_processor *opp, COL_MAN_GAMMA_CORR_MEM_PWR_DIS); } - dm_write_reg(opp->ctx, mmDCFEV_MEM_PWR_CTRL, value); + dm_write_reg(xfm->ctx, mmDCFEV_MEM_PWR_CTRL, value); for (i = 0; i < 3; i++) { - value = dm_read_reg(opp->ctx, mmDCFEV_MEM_PWR_CTRL); + value = dm_read_reg(xfm->ctx, mmDCFEV_MEM_PWR_CTRL); if (get_reg_field_value(value, DCFEV_MEM_PWR_CTRL, COL_MAN_INPUT_GAMMA_MEM_PWR_DIS) && @@ -81,11 +81,11 @@ static void power_on_lut(struct output_pixel_processor *opp, } } -static void set_bypass_input_gamma(struct dce110_opp *opp110) +static void set_bypass_input_gamma(struct dce_transform *xfm_dce) { uint32_t value; - value = dm_read_reg(opp110->base.ctx, + value = dm_read_reg(xfm_dce->base.ctx, mmCOL_MAN_INPUT_GAMMA_CONTROL1); set_reg_field_value( @@ -94,11 +94,11 @@ static void set_bypass_input_gamma(struct dce110_opp *opp110) COL_MAN_INPUT_GAMMA_CONTROL1, INPUT_GAMMA_MODE); - dm_write_reg(opp110->base.ctx, + dm_write_reg(xfm_dce->base.ctx, mmCOL_MAN_INPUT_GAMMA_CONTROL1, value); } -static void configure_regamma_mode(struct dce110_opp *opp110, uint32_t mode) +static void configure_regamma_mode(struct dce_transform *xfm_dce, uint32_t mode) { uint32_t value = 0; @@ -108,7 +108,7 @@ static void configure_regamma_mode(struct dce110_opp *opp110, uint32_t mode) GAMMA_CORR_CONTROL, GAMMA_CORR_MODE); - dm_write_reg(opp110->base.ctx, mmGAMMA_CORR_CONTROL, 0); + dm_write_reg(xfm_dce->base.ctx, mmGAMMA_CORR_CONTROL, 0); } /* @@ -128,7 +128,7 @@ static void configure_regamma_mode(struct dce110_opp *opp110, uint32_t mode) ***************************************************************************** */ static void regamma_config_regions_and_segments( - struct dce110_opp *opp110, const struct pwl_params *params) + struct dce_transform *xfm_dce, const struct pwl_params *params) { const struct gamma_curve *curve; uint32_t value = 0; @@ -146,7 +146,7 @@ static void regamma_config_regions_and_segments( GAMMA_CORR_CNTLA_START_CNTL, GAMMA_CORR_CNTLA_EXP_REGION_START_SEGMENT); - dm_write_reg(opp110->base.ctx, mmGAMMA_CORR_CNTLA_START_CNTL, + dm_write_reg(xfm_dce->base.ctx, mmGAMMA_CORR_CNTLA_START_CNTL, value); } { @@ -157,7 +157,7 @@ static void regamma_config_regions_and_segments( GAMMA_CORR_CNTLA_SLOPE_CNTL, GAMMA_CORR_CNTLA_EXP_REGION_LINEAR_SLOPE); - dm_write_reg(opp110->base.ctx, + dm_write_reg(xfm_dce->base.ctx, mmGAMMA_CORR_CNTLA_SLOPE_CNTL, value); } { @@ -168,7 +168,7 @@ static void regamma_config_regions_and_segments( GAMMA_CORR_CNTLA_END_CNTL1, GAMMA_CORR_CNTLA_EXP_REGION_END); - dm_write_reg(opp110->base.ctx, + dm_write_reg(xfm_dce->base.ctx, mmGAMMA_CORR_CNTLA_END_CNTL1, value); } { @@ -185,7 +185,7 @@ static void regamma_config_regions_and_segments( GAMMA_CORR_CNTLA_END_CNTL2, GAMMA_CORR_CNTLA_EXP_REGION_END_SLOPE); - dm_write_reg(opp110->base.ctx, + dm_write_reg(xfm_dce->base.ctx, mmGAMMA_CORR_CNTLA_END_CNTL2, value); } @@ -218,7 +218,7 @@ static void regamma_config_regions_and_segments( GAMMA_CORR_CNTLA_EXP_REGION1_NUM_SEGMENTS); dm_write_reg( - opp110->base.ctx, + xfm_dce->base.ctx, mmGAMMA_CORR_CNTLA_REGION_0_1, value); } @@ -250,7 +250,7 @@ static void regamma_config_regions_and_segments( GAMMA_CORR_CNTLA_REGION_2_3, GAMMA_CORR_CNTLA_EXP_REGION3_NUM_SEGMENTS); - dm_write_reg(opp110->base.ctx, + dm_write_reg(xfm_dce->base.ctx, mmGAMMA_CORR_CNTLA_REGION_2_3, value); } @@ -282,7 +282,7 @@ static void regamma_config_regions_and_segments( GAMMA_CORR_CNTLA_REGION_4_5, GAMMA_CORR_CNTLA_EXP_REGION5_NUM_SEGMENTS); - dm_write_reg(opp110->base.ctx, + dm_write_reg(xfm_dce->base.ctx, mmGAMMA_CORR_CNTLA_REGION_4_5, value); } @@ -314,7 +314,7 @@ static void regamma_config_regions_and_segments( GAMMA_CORR_CNTLA_REGION_6_7, GAMMA_CORR_CNTLA_EXP_REGION7_NUM_SEGMENTS); - dm_write_reg(opp110->base.ctx, + dm_write_reg(xfm_dce->base.ctx, mmGAMMA_CORR_CNTLA_REGION_6_7, value); } @@ -346,7 +346,7 @@ static void regamma_config_regions_and_segments( GAMMA_CORR_CNTLA_REGION_8_9, GAMMA_CORR_CNTLA_EXP_REGION9_NUM_SEGMENTS); - dm_write_reg(opp110->base.ctx, + dm_write_reg(xfm_dce->base.ctx, mmGAMMA_CORR_CNTLA_REGION_8_9, value); } @@ -378,7 +378,7 @@ static void regamma_config_regions_and_segments( GAMMA_CORR_CNTLA_REGION_10_11, GAMMA_CORR_CNTLA_EXP_REGION11_NUM_SEGMENTS); - dm_write_reg(opp110->base.ctx, + dm_write_reg(xfm_dce->base.ctx, mmGAMMA_CORR_CNTLA_REGION_10_11, value); } @@ -410,7 +410,7 @@ static void regamma_config_regions_and_segments( GAMMA_CORR_CNTLA_REGION_12_13, GAMMA_CORR_CNTLA_EXP_REGION13_NUM_SEGMENTS); - dm_write_reg(opp110->base.ctx, + dm_write_reg(xfm_dce->base.ctx, mmGAMMA_CORR_CNTLA_REGION_12_13, value); } @@ -442,13 +442,13 @@ static void regamma_config_regions_and_segments( GAMMA_CORR_CNTLA_REGION_14_15, GAMMA_CORR_CNTLA_EXP_REGION15_NUM_SEGMENTS); - dm_write_reg(opp110->base.ctx, + dm_write_reg(xfm_dce->base.ctx, mmGAMMA_CORR_CNTLA_REGION_14_15, value); } } -static void program_pwl(struct dce110_opp *opp110, +static void program_pwl(struct dce_transform *xfm_dce, const struct pwl_params *params) { uint32_t value = 0; @@ -459,10 +459,10 @@ static void program_pwl(struct dce110_opp *opp110, GAMMA_CORR_LUT_WRITE_EN_MASK, GAMMA_CORR_LUT_WRITE_EN_MASK); - dm_write_reg(opp110->base.ctx, + dm_write_reg(xfm_dce->base.ctx, mmGAMMA_CORR_LUT_WRITE_EN_MASK, value); - dm_write_reg(opp110->base.ctx, + dm_write_reg(xfm_dce->base.ctx, mmGAMMA_CORR_LUT_INDEX, 0); /* Program REGAMMA_LUT_DATA */ @@ -473,15 +473,15 @@ static void program_pwl(struct dce110_opp *opp110, params->rgb_resulted; while (i != params->hw_points_num) { - dm_write_reg(opp110->base.ctx, addr, rgb->red_reg); - dm_write_reg(opp110->base.ctx, addr, rgb->green_reg); - dm_write_reg(opp110->base.ctx, addr, rgb->blue_reg); + dm_write_reg(xfm_dce->base.ctx, addr, rgb->red_reg); + dm_write_reg(xfm_dce->base.ctx, addr, rgb->green_reg); + dm_write_reg(xfm_dce->base.ctx, addr, rgb->blue_reg); - dm_write_reg(opp110->base.ctx, addr, + dm_write_reg(xfm_dce->base.ctx, addr, rgb->delta_red_reg); - dm_write_reg(opp110->base.ctx, addr, + dm_write_reg(xfm_dce->base.ctx, addr, rgb->delta_green_reg); - dm_write_reg(opp110->base.ctx, addr, + dm_write_reg(xfm_dce->base.ctx, addr, rgb->delta_blue_reg); ++rgb; @@ -491,36 +491,36 @@ static void program_pwl(struct dce110_opp *opp110, } bool dce110_opp_program_regamma_pwl_v( - struct output_pixel_processor *opp, + struct transform *xfm, const struct pwl_params *params) { - struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); /* Setup regions */ - regamma_config_regions_and_segments(opp110, params); + regamma_config_regions_and_segments(xfm_dce, params); - set_bypass_input_gamma(opp110); + set_bypass_input_gamma(xfm_dce); /* Power on gamma LUT memory */ - power_on_lut(opp, true, false, true); + power_on_lut(xfm, true, false, true); /* Program PWL */ - program_pwl(opp110, params); + program_pwl(xfm_dce, params); /* program regamma config */ - configure_regamma_mode(opp110, 1); + configure_regamma_mode(xfm_dce, 1); /* Power return to auto back */ - power_on_lut(opp, false, false, true); + power_on_lut(xfm, false, false, true); return true; } void dce110_opp_power_on_regamma_lut_v( - struct output_pixel_processor *opp, + struct transform *xfm, bool power_on) { - uint32_t value = dm_read_reg(opp->ctx, mmDCFEV_MEM_PWR_CTRL); + uint32_t value = dm_read_reg(xfm->ctx, mmDCFEV_MEM_PWR_CTRL); set_reg_field_value( value, @@ -546,11 +546,11 @@ void dce110_opp_power_on_regamma_lut_v( DCFEV_MEM_PWR_CTRL, COL_MAN_INPUT_GAMMA_MEM_PWR_DIS); - dm_write_reg(opp->ctx, mmDCFEV_MEM_PWR_CTRL, value); + dm_write_reg(xfm->ctx, mmDCFEV_MEM_PWR_CTRL, value); } void dce110_opp_set_regamma_mode_v( - struct output_pixel_processor *opp, + struct transform *xfm, enum opp_regamma mode) { // TODO: need to implement the function diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c index 24d9032faade..69d6a110dbc3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c @@ -37,10 +37,7 @@ /*****************************************/ static const struct opp_funcs funcs = { - .opp_power_on_regamma_lut = dce110_opp_power_on_regamma_lut_v, - .opp_program_regamma_pwl = dce110_opp_program_regamma_pwl_v, .opp_set_dyn_expansion = dce110_opp_set_dyn_expansion, - .opp_set_regamma_mode = dce110_opp_set_regamma_mode_v, .opp_destroy = dce110_opp_destroy, .opp_program_fmt = dce110_opp_program_fmt, .opp_program_bit_depth_reduction = diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h index 7deaa4f5c659..269c1a88d5bb 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h @@ -35,16 +35,5 @@ bool dce110_opp_v_construct(struct dce110_opp *opp110, /* underlay callbacks */ -bool dce110_opp_program_regamma_pwl_v( - struct output_pixel_processor *opp, - const struct pwl_params *params); - -void dce110_opp_power_on_regamma_lut_v( - struct output_pixel_processor *opp, - bool power_on); - -void dce110_opp_set_regamma_mode_v( - struct output_pixel_processor *opp, - enum opp_regamma mode); #endif /* __DC_OPP_DCE110_V_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c index f655145b3c47..c84823a40f61 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c @@ -683,6 +683,9 @@ static const struct transform_funcs dce110_xfmv_funcs = { dce110_xfmv_set_gamut_remap, .opp_set_csc_default = dce110_opp_v_set_csc_default, .opp_set_csc_adjustment = dce110_opp_v_set_csc_adjustment, + .opp_power_on_regamma_lut = dce110_opp_power_on_regamma_lut_v, + .opp_program_regamma_pwl = dce110_opp_program_regamma_pwl_v, + .opp_set_regamma_mode = dce110_opp_set_regamma_mode_v, .transform_set_pixel_storage_depth = dce110_xfmv_set_pixel_storage_depth, .transform_get_optimal_number_of_taps = diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.h index b7f8fdb392a5..eeed3b9f90f7 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.h @@ -41,4 +41,18 @@ void dce110_opp_v_set_csc_default( void dce110_opp_v_set_csc_adjustment( struct transform *xfm, const struct out_csc_color_matrix *tbl_entry); + + +bool dce110_opp_program_regamma_pwl_v( + struct transform *xfm, + const struct pwl_params *params); + +void dce110_opp_power_on_regamma_lut_v( + struct transform *xfm, + bool power_on); + +void dce110_opp_set_regamma_mode_v( + struct transform *xfm, + enum opp_regamma mode); + #endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h index a4f8556d6797..dadd2ad2e5b8 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h @@ -251,24 +251,7 @@ enum ovl_csc_adjust_item { }; struct opp_funcs { - void (*opp_power_on_regamma_lut)( - struct output_pixel_processor *opp, - bool power_on); - - bool (*opp_program_regamma_pwl)( - struct output_pixel_processor *opp, - const struct pwl_params *params); - - void (*opp_set_regamma_mode)(struct output_pixel_processor *opp, - enum opp_regamma mode); - void (*opp_set_csc_adjustment)( - struct output_pixel_processor *opp, - const struct out_csc_color_matrix *tbl_entry); - - void (*opp_set_csc_default)( - struct output_pixel_processor *opp, - const struct default_adjustment *default_adjust); /* FORMATTER RELATED */ -- cgit From 43193c7991de7a2112fe2ddcfd930733bc357862 Mon Sep 17 00:00:00 2001 From: "AMD\\ktsao" Date: Sun, 30 Jul 2017 14:18:36 -0400 Subject: drm/amd/display: remove DCN1 guard as DCN1 is already open sourced. Signed-off-by: Kenny Tsao Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 6 -- drivers/gpu/drm/amd/display/dc/dce/dce_abm.h | 91 ++++++++++------------ .../gpu/drm/amd/display/dc/dce/dce_clock_source.h | 2 - drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h | 20 ++--- .../gpu/drm/amd/display/dc/dce/dce_link_encoder.h | 15 ++-- .../drm/amd/display/dc/dce/dce_stream_encoder.h | 6 -- drivers/gpu/drm/amd/display/dc/dm_services.h | 2 - drivers/gpu/drm/amd/display/dc/inc/core_types.h | 2 - .../gpu/drm/amd/display/dc/inc/hw/display_clock.h | 2 - drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h | 2 - drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h | 4 - drivers/gpu/drm/amd/display/dc/inc/hw/opp.h | 2 - .../drm/amd/display/dc/inc/hw/timing_generator.h | 7 +- drivers/gpu/drm/amd/display/include/dal_asic_id.h | 4 - drivers/gpu/drm/amd/display/include/dal_types.h | 3 +- 15 files changed, 58 insertions(+), 110 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 0918569eefa8..d03218d6210a 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -96,13 +96,9 @@ struct dc_surface; struct validate_context; struct dc_cap_funcs { -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) bool (*get_dcc_compression_cap)(const struct dc *dc, const struct dc_dcc_surface_param *input, struct dc_surface_dcc_cap *output); -#else - int i; -#endif }; struct dc_stream_funcs { @@ -171,7 +167,6 @@ struct dc_debug { bool disable_stutter; bool disable_dcc; bool disable_dfs_bypass; -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) bool disable_dpp_power_gate; bool disable_hubp_power_gate; bool disable_pplib_wm_range; @@ -185,7 +180,6 @@ struct dc_debug { int percent_of_ideal_drambw; int dram_clock_change_latency_ns; int always_scale; -#endif bool disable_pplib_clock_request; bool disable_clock_gate; bool disable_dmcu; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h index e0abd2d49370..59e909ec88f2 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h @@ -54,21 +54,19 @@ SR(DC_ABM1_HGLS_REG_READ_PROGRESS), \ SR(BIOS_SCRATCH_2) -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) - #define ABM_DCN10_REG_LIST(id)\ - ABM_COMMON_REG_LIST_DCE_BASE(), \ - SRI(DC_ABM1_HG_SAMPLE_RATE, ABM, id), \ - SRI(DC_ABM1_LS_SAMPLE_RATE, ABM, id), \ - SRI(BL1_PWM_BL_UPDATE_SAMPLE_RATE, ABM, id), \ - SRI(DC_ABM1_HG_MISC_CTRL, ABM, id), \ - SRI(DC_ABM1_IPCSC_COEFF_SEL, ABM, id), \ - SRI(BL1_PWM_CURRENT_ABM_LEVEL, ABM, id), \ - SRI(BL1_PWM_TARGET_ABM_LEVEL, ABM, id), \ - SRI(BL1_PWM_USER_LEVEL, ABM, id), \ - SRI(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, ABM, id), \ - SRI(DC_ABM1_HGLS_REG_READ_PROGRESS, ABM, id), \ - NBIO_SR(BIOS_SCRATCH_2) -#endif +#define ABM_DCN10_REG_LIST(id)\ + ABM_COMMON_REG_LIST_DCE_BASE(), \ + SRI(DC_ABM1_HG_SAMPLE_RATE, ABM, id), \ + SRI(DC_ABM1_LS_SAMPLE_RATE, ABM, id), \ + SRI(BL1_PWM_BL_UPDATE_SAMPLE_RATE, ABM, id), \ + SRI(DC_ABM1_HG_MISC_CTRL, ABM, id), \ + SRI(DC_ABM1_IPCSC_COEFF_SEL, ABM, id), \ + SRI(BL1_PWM_CURRENT_ABM_LEVEL, ABM, id), \ + SRI(BL1_PWM_TARGET_ABM_LEVEL, ABM, id), \ + SRI(BL1_PWM_USER_LEVEL, ABM, id), \ + SRI(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, ABM, id), \ + SRI(DC_ABM1_HGLS_REG_READ_PROGRESS, ABM, id), \ + NBIO_SR(BIOS_SCRATCH_2) #define ABM_SF(reg_name, field_name, post_fix)\ .field_name = reg_name ## __ ## field_name ## post_fix @@ -120,39 +118,36 @@ ABM_SF(DC_ABM1_HGLS_REG_READ_PROGRESS, \ ABM1_BL_REG_READ_MISSED_FRAME_CLEAR, mask_sh) - -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) - #define ABM_MASK_SH_LIST_DCN10(mask_sh) \ - ABM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh), \ - ABM_SF(ABM0_DC_ABM1_HG_MISC_CTRL, \ - ABM1_HG_NUM_OF_BINS_SEL, mask_sh), \ - ABM_SF(ABM0_DC_ABM1_HG_MISC_CTRL, \ - ABM1_HG_VMAX_SEL, mask_sh), \ - ABM_SF(ABM0_DC_ABM1_HG_MISC_CTRL, \ - ABM1_HG_BIN_BITWIDTH_SIZE_SEL, mask_sh), \ - ABM_SF(ABM0_DC_ABM1_IPCSC_COEFF_SEL, \ - ABM1_IPCSC_COEFF_SEL_R, mask_sh), \ - ABM_SF(ABM0_DC_ABM1_IPCSC_COEFF_SEL, \ - ABM1_IPCSC_COEFF_SEL_G, mask_sh), \ - ABM_SF(ABM0_DC_ABM1_IPCSC_COEFF_SEL, \ - ABM1_IPCSC_COEFF_SEL_B, mask_sh), \ - ABM_SF(ABM0_BL1_PWM_CURRENT_ABM_LEVEL, \ - BL1_PWM_CURRENT_ABM_LEVEL, mask_sh), \ - ABM_SF(ABM0_BL1_PWM_TARGET_ABM_LEVEL, \ - BL1_PWM_TARGET_ABM_LEVEL, mask_sh), \ - ABM_SF(ABM0_BL1_PWM_USER_LEVEL, \ - BL1_PWM_USER_LEVEL, mask_sh), \ - ABM_SF(ABM0_DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, \ - ABM1_LS_MIN_PIXEL_VALUE_THRES, mask_sh), \ - ABM_SF(ABM0_DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, \ - ABM1_LS_MAX_PIXEL_VALUE_THRES, mask_sh), \ - ABM_SF(ABM0_DC_ABM1_HGLS_REG_READ_PROGRESS, \ - ABM1_HG_REG_READ_MISSED_FRAME_CLEAR, mask_sh), \ - ABM_SF(ABM0_DC_ABM1_HGLS_REG_READ_PROGRESS, \ - ABM1_LS_REG_READ_MISSED_FRAME_CLEAR, mask_sh), \ - ABM_SF(ABM0_DC_ABM1_HGLS_REG_READ_PROGRESS, \ - ABM1_BL_REG_READ_MISSED_FRAME_CLEAR, mask_sh) -#endif +#define ABM_MASK_SH_LIST_DCN10(mask_sh) \ + ABM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh), \ + ABM_SF(ABM0_DC_ABM1_HG_MISC_CTRL, \ + ABM1_HG_NUM_OF_BINS_SEL, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_HG_MISC_CTRL, \ + ABM1_HG_VMAX_SEL, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_HG_MISC_CTRL, \ + ABM1_HG_BIN_BITWIDTH_SIZE_SEL, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_IPCSC_COEFF_SEL, \ + ABM1_IPCSC_COEFF_SEL_R, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_IPCSC_COEFF_SEL, \ + ABM1_IPCSC_COEFF_SEL_G, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_IPCSC_COEFF_SEL, \ + ABM1_IPCSC_COEFF_SEL_B, mask_sh), \ + ABM_SF(ABM0_BL1_PWM_CURRENT_ABM_LEVEL, \ + BL1_PWM_CURRENT_ABM_LEVEL, mask_sh), \ + ABM_SF(ABM0_BL1_PWM_TARGET_ABM_LEVEL, \ + BL1_PWM_TARGET_ABM_LEVEL, mask_sh), \ + ABM_SF(ABM0_BL1_PWM_USER_LEVEL, \ + BL1_PWM_USER_LEVEL, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, \ + ABM1_LS_MIN_PIXEL_VALUE_THRES, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, \ + ABM1_LS_MAX_PIXEL_VALUE_THRES, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_HGLS_REG_READ_PROGRESS, \ + ABM1_HG_REG_READ_MISSED_FRAME_CLEAR, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_HGLS_REG_READ_PROGRESS, \ + ABM1_LS_REG_READ_MISSED_FRAME_CLEAR, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_HGLS_REG_READ_PROGRESS, \ + ABM1_BL_REG_READ_MISSED_FRAME_CLEAR, mask_sh) #define ABM_REG_FIELD_LIST(type) \ type ABM1_HG_NUM_OF_BINS_SEL; \ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h index e8bc98b3b622..fc923886e3d4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h @@ -55,7 +55,6 @@ CS_SF(PHYPLLA_PIXCLK_RESYNC_CNTL, PHYPLLA_DCCG_DEEP_COLOR_CNTL, mask_sh),\ CS_SF(PHYPLLA_PIXCLK_RESYNC_CNTL, PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE, mask_sh) -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) #define CS_COMMON_REG_LIST_DCN1_0(index, pllid) \ SRI(PIXCLK_RESYNC_CNTL, PHYPLL, pllid),\ SRII(PHASE, DP_DTO, 0),\ @@ -74,7 +73,6 @@ #define CS_COMMON_MASK_SH_LIST_DCN1_0(mask_sh)\ CS_SF(PHYPLLA_PIXCLK_RESYNC_CNTL, PHYPLLA_DCCG_DEEP_COLOR_CNTL, mask_sh),\ CS_SF(OTG0_PIXEL_RATE_CNTL, DP_DTO0_ENABLE, mask_sh) -#endif #define CS_REG_FIELD_LIST(type) \ type PLL_REF_DIV_SRC; \ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h index c421a0250016..b85f53c2f6f8 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h @@ -48,11 +48,9 @@ DMCU_COMMON_REG_LIST_DCE_BASE(), \ SR(DCI_MEM_PWR_STATUS) -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) - #define DMCU_DCN10_REG_LIST()\ - DMCU_COMMON_REG_LIST_DCE_BASE(), \ - SR(DMU_MEM_PWR_CNTL) -#endif +#define DMCU_DCN10_REG_LIST()\ + DMCU_COMMON_REG_LIST_DCE_BASE(), \ + SR(DMU_MEM_PWR_CNTL) #define DMCU_SF(reg_name, field_name, post_fix)\ .field_name = reg_name ## __ ## field_name ## post_fix @@ -82,12 +80,10 @@ DMCU_SF(DCI_MEM_PWR_STATUS, \ DMCU_IRAM_MEM_PWR_STATE, mask_sh) -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) - #define DMCU_MASK_SH_LIST_DCN10(mask_sh) \ - DMCU_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh), \ - DMCU_SF(DMU_MEM_PWR_CNTL, \ - DMCU_IRAM_MEM_PWR_STATE, mask_sh) -#endif +#define DMCU_MASK_SH_LIST_DCN10(mask_sh) \ + DMCU_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh), \ + DMCU_SF(DMU_MEM_PWR_CNTL, \ + DMCU_IRAM_MEM_PWR_STATE, mask_sh) #define DMCU_REG_FIELD_LIST(type) \ type DMCU_IRAM_MEM_PWR_STATE; \ @@ -211,13 +207,11 @@ struct dmcu *dce_dmcu_create( const struct dce_dmcu_shift *dmcu_shift, const struct dce_dmcu_mask *dmcu_mask); -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) struct dmcu *dcn10_dmcu_create( struct dc_context *ctx, const struct dce_dmcu_registers *regs, const struct dce_dmcu_shift *dmcu_shift, const struct dce_dmcu_mask *dmcu_mask); -#endif void dce_dmcu_destroy(struct dmcu **dmcu); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h index a47b075f4869..5f05ca65281e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h @@ -100,15 +100,12 @@ SRI(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id), \ SR(DCI_MEM_PWR_STATUS) -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) - #define LE_DCN10_REG_LIST(id)\ - LE_COMMON_REG_LIST_BASE(id), \ - SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ - SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ - SRI(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id), \ - SR(DMU_MEM_PWR_CNTL) -#endif - +#define LE_DCN10_REG_LIST(id)\ + LE_COMMON_REG_LIST_BASE(id), \ + SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ + SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ + SRI(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id), \ + SR(DMU_MEM_PWR_CNTL) struct dce110_link_enc_aux_registers { uint32_t AUX_CONTROL; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h index 0b548cb3af14..ff8ca1246650 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h @@ -97,7 +97,6 @@ SE_COMMON_REG_LIST_DCE_BASE(id), \ SRI(AFMT_CNTL, DIG, id) -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) #define SE_DCN_REG_LIST(id)\ SE_COMMON_REG_LIST_BASE(id),\ SRI(AFMT_CNTL, DIG, id),\ @@ -112,7 +111,6 @@ SRI(DP_MSA_TIMING_PARAM3, DP, id), \ SRI(DP_MSA_TIMING_PARAM4, DP, id), \ SRI(HDMI_DB_CONTROL, DIG, id) -#endif #define SE_SF(reg_name, field_name, post_fix)\ .field_name = reg_name ## __ ## field_name ## post_fix @@ -328,7 +326,6 @@ SE_SF(DIG0_AFMT_AVI_INFO3, AFMT_AVI_INFO_VERSION, mask_sh),\ SE_SF(DP0_DP_VID_TIMING, DP_VID_M_DOUBLE_VALUE_EN, mask_sh) -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) #define SE_COMMON_MASK_SH_LIST_DCN10(mask_sh)\ SE_COMMON_MASK_SH_LIST_SOC(mask_sh),\ SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_LOCK_STATUS, mask_sh),\ @@ -368,7 +365,6 @@ SE_SF(DP0_DP_MSA_TIMING_PARAM4, DP_MSA_VHEIGHT, mask_sh),\ SE_SF(DIG0_HDMI_DB_CONTROL, HDMI_DB_DISABLE, mask_sh),\ SE_SF(DP0_DP_VID_TIMING, DP_VID_N_MUL, mask_sh) -#endif struct dce_stream_encoder_shift { uint8_t AFMT_GENERIC_INDEX; @@ -684,7 +680,6 @@ struct dce110_stream_enc_registers { uint32_t HDMI_ACR_48_0; uint32_t HDMI_ACR_48_1; uint32_t TMDS_CNTL; -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) uint32_t DP_DB_CNTL; uint32_t DP_MSA_MISC; uint32_t DP_MSA_COLORIMETRY; @@ -693,7 +688,6 @@ struct dce110_stream_enc_registers { uint32_t DP_MSA_TIMING_PARAM3; uint32_t DP_MSA_TIMING_PARAM4; uint32_t HDMI_DB_CONTROL; -#endif }; struct dce110_stream_encoder { diff --git a/drivers/gpu/drm/amd/display/dc/dm_services.h b/drivers/gpu/drm/amd/display/dc/dm_services.h index e9bf4c417cc7..a7d661d1ff1d 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services.h @@ -75,9 +75,7 @@ BREAK_TO_DEBUGGER(); \ } while (0) -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) #include -#endif #define dm_alloc(size) kzalloc(size, GFP_KERNEL) #define dm_realloc(ptr, size) krealloc(ptr, size, GFP_KERNEL) diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index ab389abf4e79..da52971d3f06 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -32,9 +32,7 @@ #include "ddc_service_types.h" #include "dc_bios_types.h" #include "mem_input.h" -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) #include "mpc.h" -#endif #define MAX_CLOCK_SOURCES 7 diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h b/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h index 240ab11d1d30..879c3db7cba6 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h @@ -37,13 +37,11 @@ struct clocks_value { bool dispclk_notify_pplib_done; bool pixelclk_notify_pplib_done; bool phyclk_notigy_pplib_done; -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) int dcfclock_in_khz; int dppclk_in_khz; int mclk_in_khz; int phyclk_in_khz; int common_vdd_level; -#endif }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h index 1298d306db69..0f952e5b3ae8 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h @@ -122,9 +122,7 @@ struct ipp_funcs { struct input_pixel_processor *ipp, const struct pwl_params *params); -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) void (*ipp_destroy)(struct input_pixel_processor **ipp); -#endif }; #endif /* __DAL_IPP_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h index a7c89c36f90f..a02f18ae527d 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h @@ -28,7 +28,6 @@ #include "dc.h" #include "include/grph_object_id.h" -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) #include "dml/display_mode_structs.h" struct cstate_pstate_watermarks_st { @@ -49,7 +48,6 @@ struct dcn_watermark_set { struct dcn_watermarks c; struct dcn_watermarks d; }; -#endif struct dce_watermarks { int a_mark; @@ -76,7 +74,6 @@ struct mem_input { }; struct mem_input_funcs { -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) void (*mem_input_setup)( struct mem_input *mem_input, struct _vcs_dpi_display_dlg_regs_st *dlg_regs, @@ -90,7 +87,6 @@ struct mem_input_funcs { struct mem_input *mem_input, const struct rect *viewport, const struct rect *viewport_c); -#endif void (*mem_input_program_display_marks)( struct mem_input *mem_input, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h index dadd2ad2e5b8..75adb8fec551 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h @@ -27,9 +27,7 @@ #define __DAL_OPP_H__ #include "hw_shared.h" -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) #include "dc_hw_types.h" -#endif #include "transform.h" struct fixed31_32; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h index 2b72d1d8012f..c6ab38c5b2be 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h @@ -91,7 +91,7 @@ enum crtc_state { CRTC_STATE_VBLANK = 0, CRTC_STATE_VACTIVE }; -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + struct _dlg_otg_param { int vstartup_start; int vupdate_offset; @@ -99,7 +99,6 @@ struct _dlg_otg_param { int vready_offset; enum signal_type signal; }; -#endif struct crtc_stereo_flags { uint8_t PROGRAM_STEREO : 1; @@ -113,9 +112,7 @@ struct timing_generator { const struct timing_generator_funcs *funcs; struct dc_bios *bp; struct dc_context *ctx; -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) struct _dlg_otg_param dlg_otg_param; -#endif int inst; }; @@ -176,10 +173,8 @@ struct timing_generator_funcs { bool (*arm_vert_intr)(struct timing_generator *tg, uint8_t width); -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) void (*program_global_sync)(struct timing_generator *tg); void (*enable_optc_clock)(struct timing_generator *tg, bool enable); -#endif void (*program_stereo)(struct timing_generator *tg, const struct dc_crtc_timing *timing, struct crtc_stereo_flags *flags); bool (*is_stereo_left_eye)(struct timing_generator *tg); diff --git a/drivers/gpu/drm/amd/display/include/dal_asic_id.h b/drivers/gpu/drm/amd/display/include/dal_asic_id.h index 3d2ed5c83734..af9fa66b32b8 100644 --- a/drivers/gpu/drm/amd/display/include/dal_asic_id.h +++ b/drivers/gpu/drm/amd/display/include/dal_asic_id.h @@ -109,18 +109,14 @@ #define ASIC_REV_IS_STONEY(rev) \ ((rev >= STONEY_A0) && (rev < CZ_UNKNOWN)) -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) /* DCN1_0 */ #define INTERNAL_REV_RAVEN_A0 0x00 /* First spin of Raven */ #define RAVEN_A0 0x01 #define RAVEN_UNKNOWN 0xFF #define ASIC_REV_IS_RAVEN(eChipRev) ((eChipRev >= RAVEN_A0) && eChipRev < RAVEN_UNKNOWN) -#endif -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) #define FAMILY_RV 142 /* DCN 1*/ -#endif /* * ASIC chip ID diff --git a/drivers/gpu/drm/amd/display/include/dal_types.h b/drivers/gpu/drm/amd/display/include/dal_types.h index 50a2a3ebf36d..1bfc191574aa 100644 --- a/drivers/gpu/drm/amd/display/include/dal_types.h +++ b/drivers/gpu/drm/amd/display/include/dal_types.h @@ -39,9 +39,8 @@ enum dce_version { DCE_VERSION_11_0, DCE_VERSION_11_2, DCE_VERSION_12_0, -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + DCE_VERSION_MAX, DCN_VERSION_1_0, -#endif DCN_VERSION_MAX }; -- cgit From c9614aeb12f80fa7a787e608d75b707175997edd Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 27 Jul 2017 09:24:04 -0400 Subject: drm/amd/display: Rename dc_surface to dc_plane_state find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/struct dc_surface/struct dc_plane_state/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/struct dc_plane_state_update/struct dc_surface_update/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/struct dc_plane_state_status/struct dc_surface_status/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/struct dc_plane_state_dcc_cap/struct dc_surface_dcc_cap/g' Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 18 +++++++++--------- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 4 ++-- drivers/gpu/drm/amd/display/dc/core/dc.c | 18 +++++++++--------- drivers/gpu/drm/amd/display/dc/core/dc_debug.c | 4 ++-- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 22 +++++++++++----------- drivers/gpu/drm/amd/display/dc/core/dc_surface.c | 16 ++++++++-------- drivers/gpu/drm/amd/display/dc/dc.h | 22 +++++++++++----------- drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 2 +- drivers/gpu/drm/amd/display/dc/dc_types.h | 2 +- drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c | 2 +- drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h | 2 +- .../drm/amd/display/dc/dce100/dce100_resource.c | 6 +++--- .../drm/amd/display/dc/dce100/dce100_resource.h | 2 +- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 14 +++++++------- .../drm/amd/display/dc/dce112/dce112_resource.c | 2 +- .../drm/amd/display/dc/dce120/dce120_resource.c | 2 +- .../gpu/drm/amd/display/dc/dce80/dce80_resource.c | 2 +- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 14 +++++++------- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 6 +++--- drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 4 ++-- drivers/gpu/drm/amd/display/dc/inc/resource.h | 2 +- .../gpu/drm/amd/display/include/logger_interface.h | 2 +- 22 files changed, 84 insertions(+), 84 deletions(-) (limited to 'drivers/gpu') 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 7b597a0a2ab9..af6bed907d10 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1819,7 +1819,7 @@ static int dm_crtc_cursor_move(struct drm_crtc *crtc, static bool fill_rects_from_plane_state( const struct drm_plane_state *state, - struct dc_surface *surface) + struct dc_plane_state *surface) { surface->src_rect.x = state->src_x >> 16; surface->src_rect.y = state->src_y >> 16; @@ -1894,7 +1894,7 @@ static int get_fb_info( static int fill_plane_attributes_from_fb( struct amdgpu_device *adev, - struct dc_surface *surface, + struct dc_plane_state *surface, const struct amdgpu_framebuffer *amdgpu_fb, bool addReq) { uint64_t tiling_flags; @@ -2048,7 +2048,7 @@ static int fill_plane_attributes_from_fb( static void fill_gamma_from_crtc_state( const struct drm_crtc_state *crtc_state, - struct dc_surface *dc_surface) + struct dc_plane_state *dc_surface) { int i; struct dc_gamma *gamma; @@ -2072,7 +2072,7 @@ static void fill_gamma_from_crtc_state( static int fill_plane_attributes( struct amdgpu_device *adev, - struct dc_surface *surface, + struct dc_plane_state *surface, struct drm_plane_state *plane_state, struct drm_crtc_state *crtc_state, bool addrReq) @@ -3059,7 +3059,7 @@ static int dm_plane_helper_prepare_fb( if (dm_plane_state_new->surface && dm_plane_state_old->surface != dm_plane_state_new->surface) { - struct dc_surface *surface = dm_plane_state_new->surface; + struct dc_plane_state *surface = dm_plane_state_new->surface; if (surface->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) { surface->address.grph.addr.low_part = lower_32_bits(afb->address); @@ -3160,7 +3160,7 @@ int dm_plane_atomic_check(struct drm_plane *plane, if (!dm_plane_state->surface) return true; - if (dc_validate_surface(dc, dm_plane_state->surface)) + if (dc_validate_plane(dc, dm_plane_state->surface)) return 0; return -EINVAL; @@ -3926,7 +3926,7 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, struct drm_plane *plane; struct drm_plane_state *old_plane_state; struct dc_stream *dc_stream_attach; - struct dc_surface *dc_surfaces_constructed[MAX_SURFACES]; + struct dc_plane_state *dc_surfaces_constructed[MAX_SURFACES]; struct amdgpu_crtc *acrtc_attach = to_amdgpu_crtc(pcrtc); struct dm_crtc_state *acrtc_state = to_dm_crtc_state(pcrtc->state); int planes_count = 0; @@ -4377,7 +4377,7 @@ static uint32_t add_val_sets_surface( struct dc_validation_set *val_sets, uint32_t set_count, const struct dc_stream *stream, - struct dc_surface *surface) + struct dc_plane_state *surface) { uint32_t i = 0, j = 0; @@ -4699,7 +4699,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, pflip_needed = !state->allow_modeset; if (!pflip_needed) { - struct dc_surface *surface; + struct dc_plane_state *surface; surface = dc_create_surface(dc); 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 ce0223af7d5f..dcf1f77390a8 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -189,14 +189,14 @@ struct amdgpu_connector *amdgpu_dm_find_first_crct_matching_connector( struct amdgpu_framebuffer; struct amdgpu_display_manager; struct dc_validation_set; -struct dc_surface; +struct dc_plane_state; /* TODO rename to dc_stream_state */ struct dc_stream; struct dm_plane_state { struct drm_plane_state base; - struct dc_surface *surface; + struct dc_plane_state *surface; }; struct dm_crtc_state { diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 5acf4c697ae8..500788c35d70 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -645,7 +645,7 @@ static bool is_validation_required( return true; for (j = 0; j < set[i].surface_count; j++) { - struct dc_surface temp_surf; + struct dc_plane_state temp_surf; memset(&temp_surf, 0, sizeof(temp_surf)); temp_surf = *context->stream_status[i].surfaces[j]; @@ -684,7 +684,7 @@ static bool validate_surfaces( for (i = 0; i < set_count; i++) for (j = 0; j < set[i].surface_count; j++) - if (!dc_validate_surface(dc, set[i].surfaces[j])) + if (!dc_validate_plane(dc, set[i].surfaces[j])) return false; return true; @@ -978,7 +978,7 @@ static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *c const struct dc_sink *sink = context->streams[i]->sink; for (j = 0; j < context->stream_status[i].surface_count; j++) { - const struct dc_surface *surface = + const struct dc_plane_state *surface = context->stream_status[i].surfaces[j]; core_dc->hwss.apply_ctx_for_surface(core_dc, surface, context); @@ -1136,7 +1136,7 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) bool dc_commit_surfaces_to_stream( struct dc *dc, - struct dc_surface **new_surfaces, + struct dc_plane_state **new_surfaces, uint8_t new_surface_count, struct dc_stream *dc_stream) { @@ -1220,7 +1220,7 @@ void dc_release_validate_context(struct validate_context *context) static bool is_surface_in_context( const struct validate_context *context, - const struct dc_surface *surface) + const struct dc_plane_state *surface) { int j; @@ -1470,7 +1470,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, update_surface_trace(dc, srf_updates, surface_count); if (update_type >= UPDATE_TYPE_FULL) { - struct dc_surface *new_surfaces[MAX_SURFACES] = {0}; + struct dc_plane_state *new_surfaces[MAX_SURFACES] = {0}; for (i = 0; i < surface_count; i++) new_surfaces[i] = srf_updates[i].surface; @@ -1496,7 +1496,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, /* save update parameters into surface */ for (i = 0; i < surface_count; i++) { - struct dc_surface *surface = srf_updates[i].surface; + struct dc_plane_state *surface = srf_updates[i].surface; if (srf_updates[i].flip_addr) { surface->address = srf_updates[i].flip_addr->address; @@ -1599,7 +1599,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, /* Lock pipes for provided surfaces, or all active if full update*/ for (i = 0; i < surface_count; i++) { - struct dc_surface *surface = srf_updates[i].surface; + struct dc_plane_state *surface = srf_updates[i].surface; for (j = 0; j < core_dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; @@ -1649,7 +1649,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, /* Perform requested Updates */ for (i = 0; i < surface_count; i++) { - struct dc_surface *surface = srf_updates[i].surface; + struct dc_plane_state *surface = srf_updates[i].surface; if (update_type == UPDATE_TYPE_MED) core_dc->hwss.apply_ctx_for_surface( diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c index bf127a88e533..e8d4b8c3ac2b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c @@ -38,7 +38,7 @@ void pre_surface_trace( const struct dc *dc, - const struct dc_surface *const *surfaces, + const struct dc_plane_state *const *surfaces, int surface_count) { int i; @@ -46,7 +46,7 @@ void pre_surface_trace( struct dal_logger *logger = core_dc->ctx->logger; for (i = 0; i < surface_count; i++) { - const struct dc_surface *surface = surfaces[i]; + const struct dc_plane_state *surface = surfaces[i]; SURFACE_TRACE("Surface %d:\n", i); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 005eac5fae80..fd1d6be79fee 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -430,7 +430,7 @@ static void rect_swap_helper(struct rect *rect) static void calculate_viewport(struct pipe_ctx *pipe_ctx) { - const struct dc_surface *surface = pipe_ctx->surface; + const struct dc_plane_state *surface = pipe_ctx->surface; const struct dc_stream *stream = pipe_ctx->stream; struct scaler_data *data = &pipe_ctx->scl_data; struct rect surf_src = surface->src_rect; @@ -529,7 +529,7 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip) { - const struct dc_surface *surface = pipe_ctx->surface; + const struct dc_plane_state *surface = pipe_ctx->surface; const struct dc_stream *stream = pipe_ctx->stream; struct rect surf_src = surface->src_rect; struct rect surf_clip = surface->clip_rect; @@ -607,7 +607,7 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) { - const struct dc_surface *surface = pipe_ctx->surface; + const struct dc_plane_state *surface = pipe_ctx->surface; const struct dc_stream *stream = pipe_ctx->stream; struct rect surf_src = surface->src_rect; const int in_w = stream->src.width; @@ -814,7 +814,7 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *r bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) { - const struct dc_surface *surface = pipe_ctx->surface; + const struct dc_plane_state *surface = pipe_ctx->surface; struct dc_crtc_timing *timing = &pipe_ctx->stream->timing; struct view recout_skip = { 0 }; bool res = false; @@ -1028,7 +1028,7 @@ static int acquire_first_split_pipe( #endif bool resource_attach_surfaces_to_context( - struct dc_surface * const *surfaces, + struct dc_plane_state * const *surfaces, int surface_count, struct dc_stream *stream, struct validate_context *context, @@ -1075,7 +1075,7 @@ bool resource_attach_surfaces_to_context( tail_pipe = NULL; for (i = 0; i < surface_count; i++) { - struct dc_surface *surface = surfaces[i]; + struct dc_plane_state *surface = surfaces[i]; struct pipe_ctx *free_pipe = acquire_free_pipe_for_stream( context, pool, stream); @@ -1351,7 +1351,7 @@ bool resource_is_stream_unchanged( static void copy_pipe_ctx( const struct pipe_ctx *from_pipe_ctx, struct pipe_ctx *to_pipe_ctx) { - struct dc_surface *surface = to_pipe_ctx->surface; + struct dc_plane_state *surface = to_pipe_ctx->surface; struct dc_stream *stream = to_pipe_ctx->stream; *to_pipe_ctx = *from_pipe_ctx; @@ -2055,7 +2055,7 @@ static void set_spd_info_packet( static void set_hdr_static_info_packet( struct encoder_info_packet *info_packet, - struct dc_surface *surface, + struct dc_plane_state *surface, struct dc_stream *stream) { uint16_t i = 0; @@ -2534,13 +2534,13 @@ bool dc_validate_stream(const struct dc *dc, struct dc_stream *stream) return res == DC_OK; } -bool dc_validate_surface(const struct dc *dc, const struct dc_surface *surface) +bool dc_validate_plane(const struct dc *dc, const struct dc_plane_state *plane_state) { struct core_dc *core_dc = DC_TO_CORE(dc); /* TODO For now validates pixel format only */ - if (core_dc->res_pool->funcs->validate_surface) - return core_dc->res_pool->funcs->validate_surface(surface) == DC_OK; + if (core_dc->res_pool->funcs->validate_plane) + return core_dc->res_pool->funcs->validate_plane(plane_state) == DC_OK; return true; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index eded6b7da97d..941b3671375d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -34,7 +34,7 @@ /******************************************************************************* * Private functions ******************************************************************************/ -static bool construct(struct dc_context *ctx, struct dc_surface *surface) +static bool construct(struct dc_context *ctx, struct dc_plane_state *surface) { surface->ctx = ctx; memset(&surface->hdr_static_ctx, @@ -42,7 +42,7 @@ static bool construct(struct dc_context *ctx, struct dc_surface *surface) return true; } -static void destruct(struct dc_surface *surface) +static void destruct(struct dc_plane_state *surface) { if (surface->gamma_correction != NULL) { dc_gamma_release(&surface->gamma_correction); @@ -57,18 +57,18 @@ static void destruct(struct dc_surface *surface) /******************************************************************************* * Public functions ******************************************************************************/ -void enable_surface_flip_reporting(struct dc_surface *surface, +void enable_surface_flip_reporting(struct dc_plane_state *surface, uint32_t controller_id) { surface->irq_source = controller_id + DC_IRQ_SOURCE_PFLIP1 - 1; /*register_flip_interrupt(surface);*/ } -struct dc_surface *dc_create_surface(const struct dc *dc) +struct dc_plane_state *dc_create_surface(const struct dc *dc) { struct core_dc *core_dc = DC_TO_CORE(dc); - struct dc_surface *surface = dm_alloc(sizeof(*surface)); + struct dc_plane_state *surface = dm_alloc(sizeof(*surface)); if (NULL == surface) goto alloc_fail; @@ -88,7 +88,7 @@ alloc_fail: } const struct dc_surface_status *dc_surface_get_status( - const struct dc_surface *dc_surface) + const struct dc_plane_state *dc_surface) { const struct dc_surface_status *surface_status; struct core_dc *core_dc; @@ -120,13 +120,13 @@ const struct dc_surface_status *dc_surface_get_status( return surface_status; } -void dc_surface_retain(struct dc_surface *surface) +void dc_surface_retain(struct dc_plane_state *surface) { ASSERT(surface->ref_count > 0); ++surface->ref_count; } -void dc_surface_release(struct dc_surface *surface) +void dc_surface_release(struct dc_plane_state *surface) { ASSERT(surface->ref_count > 0); --surface->ref_count; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index d03218d6210a..d1943b9644d4 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -92,7 +92,7 @@ struct dc_static_screen_events { /* Forward declaration*/ struct dc; -struct dc_surface; +struct dc_plane_state; struct validate_context; struct dc_cap_funcs { @@ -310,7 +310,7 @@ struct dc_surface_status { bool is_right_eye; }; -struct dc_surface { +struct dc_plane_state { struct dc_plane_address address; struct scaling_taps scaling_quality; @@ -367,7 +367,7 @@ struct dc_scaling_info { }; struct dc_surface_update { - struct dc_surface *surface; + struct dc_plane_state *surface; /* isr safe update parameters. null means no updates */ struct dc_flip_addrs *flip_addr; @@ -385,12 +385,12 @@ struct dc_surface_update { /* * Create a new surface with default parameters; */ -struct dc_surface *dc_create_surface(const struct dc *dc); +struct dc_plane_state *dc_create_surface(const struct dc *dc); const struct dc_surface_status *dc_surface_get_status( - const struct dc_surface *dc_surface); + const struct dc_plane_state *dc_surface); -void dc_surface_retain(struct dc_surface *dc_surface); -void dc_surface_release(struct dc_surface *dc_surface); +void dc_surface_retain(struct dc_plane_state *dc_surface); +void dc_surface_release(struct dc_plane_state *dc_surface); void dc_gamma_retain(struct dc_gamma *dc_gamma); void dc_gamma_release(struct dc_gamma **dc_gamma); @@ -424,7 +424,7 @@ struct dc_flip_addrs { bool dc_commit_surfaces_to_stream( struct dc *dc, - struct dc_surface **dc_surfaces, + struct dc_plane_state **dc_surfaces, uint8_t surface_count, struct dc_stream *stream); @@ -470,7 +470,7 @@ enum surface_update_type { struct dc_stream_status { int primary_otg_inst; int surface_count; - struct dc_surface *surfaces[MAX_SURFACE_NUM]; + struct dc_plane_state *surfaces[MAX_SURFACE_NUM]; /* * link this stream passes through @@ -582,13 +582,13 @@ bool dc_stream_get_scanoutpos(const struct dc_stream *stream, */ struct dc_validation_set { struct dc_stream *stream; - struct dc_surface *surfaces[MAX_SURFACES]; + struct dc_plane_state *surfaces[MAX_SURFACES]; uint8_t surface_count; }; bool dc_validate_stream(const struct dc *dc, struct dc_stream *stream); -bool dc_validate_surface(const struct dc *dc, const struct dc_surface *surface); +bool dc_validate_plane(const struct dc *dc, const struct dc_plane_state *plane_state); /* * This function takes a set of resources and checks that they are cofunctional. * diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index 4c5e797da5b1..3c0b47373dfb 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -528,7 +528,7 @@ enum dc_quantization_range { /* XFM */ -/* used in struct dc_surface */ +/* used in struct dc_plane_state */ struct scaling_taps { uint32_t v_taps; uint32_t h_taps; diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index ee9e6bc88c32..4fb9584452a4 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -34,7 +34,7 @@ #include "grph_object_defs.h" /* forward declarations */ -struct dc_surface; +struct dc_plane_state; struct dc_stream; struct dc_link; struct dc_sink; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c index c46b3e82cdcc..af59ab93796a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c @@ -197,7 +197,7 @@ void dce_crtc_switch_to_clk_src(struct dce_hwseq *hws, } /* Only use LUT for 8 bit formats */ -bool dce_use_lut(const struct dc_surface *surface) +bool dce_use_lut(const struct dc_plane_state *surface) { switch (surface->format) { case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index ade7507e99c7..d5cb98a92c53 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -552,5 +552,5 @@ void dce_crtc_switch_to_clk_src(struct dce_hwseq *hws, struct clock_source *clk_src, unsigned int tg_inst); -bool dce_use_lut(const struct dc_surface *surface); +bool dce_use_lut(const struct dc_plane_state *surface); #endif /*__DCE_HWSEQ_H__*/ diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 59f4caf057f7..2cf2fefc3d79 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -804,10 +804,10 @@ static void dce100_destroy_resource_pool(struct resource_pool **pool) *pool = NULL; } -enum dc_status dce100_validate_surface(const struct dc_surface *surface) +enum dc_status dce100_validate_plane(const struct dc_plane_state *plane_state) { - if (surface->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) + if (plane_state->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) return DC_OK; return DC_FAIL_SURFACE_VALIDATE; @@ -819,7 +819,7 @@ static const struct resource_funcs dce100_res_pool_funcs = { .validate_with_context = dce100_validate_with_context, .validate_guaranteed = dce100_validate_guaranteed, .validate_bandwidth = dce100_validate_bandwidth, - .validate_surface = dce100_validate_surface, + .validate_plane = dce100_validate_plane, }; static bool construct( diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h index 13fc637eb731..edc50caf04d1 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h @@ -16,6 +16,6 @@ struct resource_pool *dce100_create_resource_pool( uint8_t num_virtual_links, struct core_dc *dc); -enum dc_status dce100_validate_surface(const struct dc_surface *surface); +enum dc_status dce100_validate_plane(const struct dc_plane_state *plane_state); #endif /* DCE100_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 1f18fcf52661..84dc8916de96 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -215,7 +215,7 @@ static bool dce110_enable_display_power_gating( } static void build_prescale_params(struct ipp_prescale_params *prescale_params, - const struct dc_surface *surface) + const struct dc_plane_state *surface) { prescale_params->mode = IPP_PRESCALE_MODE_FIXED_UNSIGNED; @@ -240,7 +240,7 @@ static void build_prescale_params(struct ipp_prescale_params *prescale_params, static bool dce110_set_input_transfer_func( struct pipe_ctx *pipe_ctx, - const struct dc_surface *surface) + const struct dc_plane_state *surface) { struct input_pixel_processor *ipp = pipe_ctx->ipp; const struct dc_transfer_func *tf = NULL; @@ -2038,7 +2038,7 @@ static void set_plane_config( struct resource_context *res_ctx) { struct mem_input *mi = pipe_ctx->mi; - struct dc_surface *surface = pipe_ctx->surface; + struct dc_plane_state *surface = pipe_ctx->surface; struct xfm_grph_csc_adjustment adjust; struct out_csc_color_matrix tbl_entry; unsigned int i; @@ -2123,7 +2123,7 @@ static void set_plane_config( static void update_plane_addr(const struct core_dc *dc, struct pipe_ctx *pipe_ctx) { - struct dc_surface *surface = pipe_ctx->surface; + struct dc_plane_state *surface = pipe_ctx->surface; if (surface == NULL) return; @@ -2138,7 +2138,7 @@ static void update_plane_addr(const struct core_dc *dc, void dce110_update_pending_status(struct pipe_ctx *pipe_ctx) { - struct dc_surface *surface = pipe_ctx->surface; + struct dc_plane_state *surface = pipe_ctx->surface; if (surface == NULL) return; @@ -2490,7 +2490,7 @@ static void dce110_program_front_end_for_pipe( { struct mem_input *mi = pipe_ctx->mi; struct pipe_ctx *old_pipe = NULL; - struct dc_surface *surface = pipe_ctx->surface; + struct dc_plane_state *surface = pipe_ctx->surface; struct xfm_grph_csc_adjustment adjust; struct out_csc_color_matrix tbl_entry; unsigned int i; @@ -2614,7 +2614,7 @@ static void dce110_program_front_end_for_pipe( static void dce110_apply_ctx_for_surface( struct core_dc *dc, - const struct dc_surface *surface, + const struct dc_plane_state *surface, struct validate_context *context) { int i; diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 495f38750ae4..c68372fa1292 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -994,7 +994,7 @@ static const struct resource_funcs dce112_res_pool_funcs = { .validate_with_context = dce112_validate_with_context, .validate_guaranteed = dce112_validate_guaranteed, .validate_bandwidth = dce112_validate_bandwidth, - .validate_surface = dce100_validate_surface + .validate_plane = dce100_validate_plane }; static void bw_calcs_data_update_from_pplib(struct core_dc *dc) diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index b31307b9d3e3..45f5fd63ce14 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -701,7 +701,7 @@ static const struct resource_funcs dce120_res_pool_funcs = { .validate_with_context = dce112_validate_with_context, .validate_guaranteed = dce112_validate_guaranteed, .validate_bandwidth = dce112_validate_bandwidth, - .validate_surface = dce100_validate_surface + .validate_plane = dce100_validate_plane }; static void bw_calcs_data_update_from_pplib(struct core_dc *dc) diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 6eeb5e9f656f..bcb66447b558 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -825,7 +825,7 @@ static const struct resource_funcs dce80_res_pool_funcs = { .validate_with_context = dce80_validate_with_context, .validate_guaranteed = dce80_validate_guaranteed, .validate_bandwidth = dce80_validate_bandwidth, - .validate_surface = dce100_validate_surface + .validate_plane = dce100_validate_plane }; static bool construct( diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index fa19c6b92f29..3979cb03cf8d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1038,7 +1038,7 @@ static void reset_hw_ctx_wrap( static bool patch_address_for_sbs_tb_stereo( struct pipe_ctx *pipe_ctx, PHYSICAL_ADDRESS_LOC *addr) { - struct dc_surface *surface = pipe_ctx->surface; + struct dc_plane_state *surface = pipe_ctx->surface; bool sec_split = pipe_ctx->top_pipe && pipe_ctx->top_pipe->surface == pipe_ctx->surface; if (sec_split && surface->address.type == PLN_ADDR_TYPE_GRPH_STEREO && @@ -1065,7 +1065,7 @@ static void update_plane_addr(const struct core_dc *dc, struct pipe_ctx *pipe_ct { bool addr_patched = false; PHYSICAL_ADDRESS_LOC addr; - struct dc_surface *surface = pipe_ctx->surface; + struct dc_plane_state *surface = pipe_ctx->surface; if (surface == NULL) return; @@ -1080,7 +1080,7 @@ static void update_plane_addr(const struct core_dc *dc, struct pipe_ctx *pipe_ct } static bool dcn10_set_input_transfer_func( - struct pipe_ctx *pipe_ctx, const struct dc_surface *surface) + struct pipe_ctx *pipe_ctx, const struct dc_plane_state *surface) { struct input_pixel_processor *ipp = pipe_ctx->ipp; const struct dc_transfer_func *tf = NULL; @@ -1689,7 +1689,7 @@ static void dcn10_power_on_fe( struct pipe_ctx *pipe_ctx, struct validate_context *context) { - struct dc_surface *dc_surface = pipe_ctx->surface; + struct dc_plane_state *dc_surface = pipe_ctx->surface; struct dce_hwseq *hws = dc->hwseq; power_on_plane(dc->hwseq, @@ -1898,7 +1898,7 @@ static void update_dchubp_dpp( struct dce_hwseq *hws = dc->hwseq; struct mem_input *mi = pipe_ctx->mi; struct input_pixel_processor *ipp = pipe_ctx->ipp; - struct dc_surface *surface = pipe_ctx->surface; + struct dc_plane_state *surface = pipe_ctx->surface; union plane_size size = surface->plane_size; struct default_adjustment ocsc = {0}; struct mpcc_cfg mpcc_cfg = {0}; @@ -2068,7 +2068,7 @@ static void dcn10_pplib_apply_display_requirements( static void dcn10_apply_ctx_for_surface( struct core_dc *dc, - const struct dc_surface *surface, + const struct dc_plane_state *surface, struct validate_context *context) { int i, be_idx; @@ -2468,7 +2468,7 @@ static bool dcn10_dummy_display_power_gating( void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx) { - struct dc_surface *surface = pipe_ctx->surface; + struct dc_plane_state *surface = pipe_ctx->surface; struct timing_generator *tg = pipe_ctx->tg; if (surface->ctx->dc->debug.sanity_checks) { diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index da52971d3f06..44a87c9427f7 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -36,7 +36,7 @@ #define MAX_CLOCK_SOURCES 7 -void enable_surface_flip_reporting(struct dc_surface *dc_surface, +void enable_surface_flip_reporting(struct dc_plane_state *dc_surface, uint32_t controller_id); #include "grph_object_id.h" @@ -104,7 +104,7 @@ struct resource_funcs { const struct resource_pool *pool, struct dc_stream *stream); - enum dc_status (*validate_surface)(const struct dc_surface *surface); + enum dc_status (*validate_plane)(const struct dc_plane_state *plane_state); }; struct audio_support{ @@ -154,7 +154,7 @@ struct resource_pool { }; struct pipe_ctx { - struct dc_surface *surface; + struct dc_plane_state *surface; struct dc_stream *stream; struct mem_input *mi; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index b2f7ba2115c9..c529ddd2e0d5 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -59,7 +59,7 @@ struct hw_sequencer_funcs { void (*apply_ctx_for_surface)( struct core_dc *dc, - const struct dc_surface *surface, + const struct dc_plane_state *surface, struct validate_context *context); void (*set_plane_config)( @@ -88,7 +88,7 @@ struct hw_sequencer_funcs { bool (*set_input_transfer_func)( struct pipe_ctx *pipe_ctx, - const struct dc_surface *surface); + const struct dc_plane_state *surface); bool (*set_output_transfer_func)( struct pipe_ctx *pipe_ctx, diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index ca3f49379bea..bfd7cfc86df0 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -119,7 +119,7 @@ struct pipe_ctx *resource_get_head_pipe_for_stream( struct dc_stream *stream); bool resource_attach_surfaces_to_context( - struct dc_surface *const *surfaces, + struct dc_plane_state *const *surfaces, int surface_count, struct dc_stream *dc_stream, struct validate_context *context, diff --git a/drivers/gpu/drm/amd/display/include/logger_interface.h b/drivers/gpu/drm/amd/display/include/logger_interface.h index 0a872472ecba..0e978d921fdf 100644 --- a/drivers/gpu/drm/amd/display/include/logger_interface.h +++ b/drivers/gpu/drm/amd/display/include/logger_interface.h @@ -77,7 +77,7 @@ void logger_write(struct dal_logger *logger, void pre_surface_trace( const struct dc *dc, - const struct dc_surface *const *surfaces, + const struct dc_plane_state *const *surfaces, int surface_count); void update_surface_trace( -- cgit From 0971c40e180696c3512b9a63ca7ca5161cbfce32 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 27 Jul 2017 09:33:33 -0400 Subject: drm/amd/display: Rename dc_stream to dc_stream_state find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/struct dc_stream/struct dc_stream_state/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/struct dc_stream_state_update/struct dc_stream_update/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/struct dc_stream_state_status/struct dc_stream_status/g' Plus some manual changes Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 42 ++++++------- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 2 +- .../drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 6 +- drivers/gpu/drm/amd/display/dc/core/dc.c | 38 ++++++------ drivers/gpu/drm/amd/display/dc/core/dc_link.c | 18 +++--- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 68 +++++++++++----------- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 26 ++++----- drivers/gpu/drm/amd/display/dc/dc.h | 58 +++++++++--------- drivers/gpu/drm/amd/display/dc/dc_types.h | 2 +- .../gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 2 +- .../gpu/drm/amd/display/dc/dce/dce_link_encoder.h | 2 +- .../drm/amd/display/dc/dce100/dce100_resource.c | 4 +- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 16 ++--- .../drm/amd/display/dc/dce110/dce110_resource.c | 8 +-- .../drm/amd/display/dc/dce112/dce112_resource.c | 8 +-- .../drm/amd/display/dc/dce112/dce112_resource.h | 2 +- .../gpu/drm/amd/display/dc/dce80/dce80_resource.c | 4 +- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 8 +-- .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 10 ++-- drivers/gpu/drm/amd/display/dc/dm_helpers.h | 6 +- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 11 ++-- drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h | 4 +- .../gpu/drm/amd/display/dc/inc/hw/link_encoder.h | 2 +- drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 2 +- drivers/gpu/drm/amd/display/dc/inc/resource.h | 13 ++--- .../amd/display/dc/virtual/virtual_link_encoder.c | 2 +- .../drm/amd/display/modules/freesync/freesync.c | 50 ++++++++-------- .../gpu/drm/amd/display/modules/inc/mod_freesync.h | 28 ++++----- 29 files changed, 222 insertions(+), 222 deletions(-) (limited to 'drivers/gpu') 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 af6bed907d10..497104a29d89 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -116,7 +116,8 @@ static u32 dm_vblank_get_counter(struct amdgpu_device *adev, int crtc) if (acrtc_state->stream == NULL) { - DRM_ERROR("dc_stream is NULL for crtc '%d'!\n", crtc); + DRM_ERROR("dc_stream_state is NULL for crtc '%d'!\n", + crtc); return 0; } @@ -137,7 +138,8 @@ static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc, acrtc->base.state); if (acrtc_state->stream == NULL) { - DRM_ERROR("dc_stream is NULL for crtc '%d'!\n", crtc); + DRM_ERROR("dc_stream_state is NULL for crtc '%d'!\n", + crtc); return 0; } @@ -1441,7 +1443,7 @@ static int amdgpu_notify_freesync(struct drm_device *dev, void *data, num_streams = dc_get_current_stream_count(adev->dm.dc); for (i = 0; i < num_streams; i++) { - struct dc_stream *stream; + struct dc_stream_state *stream; stream = dc_get_stream_at_index(adev->dm.dc, i); mod_freesync_update_state(adev->dm.freesync_module, @@ -1609,8 +1611,8 @@ struct dm_connector_state { container_of((x), struct dm_connector_state, base) static bool modeset_required(struct drm_crtc_state *crtc_state, - struct dc_stream *new_stream, - struct dc_stream *old_stream) + struct dc_stream_state *new_stream, + struct dc_stream_state *old_stream) { if (dc_is_stream_unchanged(new_stream, old_stream)) { crtc_state->mode_changed = false; @@ -2141,7 +2143,7 @@ struct amdgpu_connector *aconnector_from_drm_crtc_id( static void update_stream_scaling_settings( const struct drm_display_mode *mode, const struct dm_connector_state *dm_state, - struct dc_stream *stream) + struct dc_stream_state *stream) { enum amdgpu_rmx_type rmx_type; @@ -2285,7 +2287,7 @@ static enum dc_color_space get_output_color_space( /*****************************************************************************/ static void fill_stream_properties_from_drm_display_mode( - struct dc_stream *stream, + struct dc_stream_state *stream, const struct drm_display_mode *mode_in, const struct drm_connector *connector) { @@ -2426,14 +2428,14 @@ static void decide_crtc_timing_for_drm_display_mode( } } -static struct dc_stream *create_stream_for_sink( +static struct dc_stream_state *create_stream_for_sink( struct amdgpu_connector *aconnector, const struct drm_display_mode *drm_mode, const struct dm_connector_state *dm_state) { struct drm_display_mode *preferred_mode = NULL; const struct drm_connector *drm_connector; - struct dc_stream *stream = NULL; + struct dc_stream_state *stream = NULL; struct drm_display_mode mode = *drm_mode; bool native_mode_found = false; @@ -2842,7 +2844,7 @@ int amdgpu_dm_connector_mode_valid( struct dc_sink *dc_sink; struct amdgpu_device *adev = connector->dev->dev_private; /* TODO: Unhardcode stream count */ - struct dc_stream *stream; + struct dc_stream_state *stream; struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); if ((mode->flags & DRM_MODE_FLAG_INTERLACE) || @@ -3119,7 +3121,7 @@ int dm_create_validation_set_for_connector(struct drm_connector *connector, struct dc_sink *dc_sink = to_amdgpu_connector(connector)->dc_sink; /* TODO: Unhardcode stream count */ - struct dc_stream *stream; + struct dc_stream_state *stream; if ((mode->flags & DRM_MODE_FLAG_INTERLACE) || (mode->flags & DRM_MODE_FLAG_DBLSCAN)) @@ -3770,7 +3772,7 @@ static bool is_scaling_state_different( static void remove_stream( struct amdgpu_device *adev, struct amdgpu_crtc *acrtc, - struct dc_stream *stream) + struct dc_stream_state *stream) { /* this is the update mode case */ if (adev->dm.freesync_module) @@ -3925,7 +3927,7 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, uint32_t i; struct drm_plane *plane; struct drm_plane_state *old_plane_state; - struct dc_stream *dc_stream_attach; + struct dc_stream_state *dc_stream_attach; struct dc_plane_state *dc_surfaces_constructed[MAX_SURFACES]; struct amdgpu_crtc *acrtc_attach = to_amdgpu_crtc(pcrtc); struct dm_crtc_state *acrtc_state = to_dm_crtc_state(pcrtc->state); @@ -4061,7 +4063,7 @@ void amdgpu_dm_atomic_commit_tail( struct drm_crtc *crtc, *pcrtc; struct drm_crtc_state *old_crtc_state; struct amdgpu_crtc *new_crtcs[MAX_STREAMS]; - struct dc_stream *new_stream = NULL; + struct dc_stream_state *new_stream = NULL; unsigned long flags; bool wait_for_vblank = true; struct drm_connector *connector; @@ -4220,7 +4222,7 @@ void amdgpu_dm_atomic_commit_tail( new_acrtc_state = to_dm_crtc_state(acrtc->base.state); update_stream_scaling_settings(&con_new_state->base.crtc->mode, - con_new_state, (struct dc_stream *)new_acrtc_state->stream); + con_new_state, (struct dc_stream_state *)new_acrtc_state->stream); status = dc_stream_get_status(new_acrtc_state->stream); WARN_ON(!status); @@ -4376,7 +4378,7 @@ void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector static uint32_t add_val_sets_surface( struct dc_validation_set *val_sets, uint32_t set_count, - const struct dc_stream *stream, + const struct dc_stream_state *stream, struct dc_plane_state *surface) { uint32_t i = 0, j = 0; @@ -4399,8 +4401,8 @@ static uint32_t add_val_sets_surface( static uint32_t update_in_val_sets_stream( struct dc_validation_set *val_sets, uint32_t set_count, - struct dc_stream *old_stream, - struct dc_stream *new_stream, + struct dc_stream_state *old_stream, + struct dc_stream_state *new_stream, struct drm_crtc *crtc) { uint32_t i = 0; @@ -4423,7 +4425,7 @@ static uint32_t update_in_val_sets_stream( static uint32_t remove_from_val_sets( struct dc_validation_set *val_sets, uint32_t set_count, - const struct dc_stream *stream) + const struct dc_stream_state *stream) { int i; @@ -4545,7 +4547,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, for_each_crtc_in_state(state, crtc, crtc_state, i) { struct amdgpu_crtc *acrtc = NULL; struct amdgpu_connector *aconnector = NULL; - struct dc_stream *new_stream = NULL; + struct dc_stream_state *new_stream = NULL; struct drm_connector_state *conn_state = NULL; struct dm_connector_state *dm_conn_state = NULL; 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 dcf1f77390a8..cca65a37b213 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -201,7 +201,7 @@ struct dm_plane_state { struct dm_crtc_state { struct drm_crtc_state base; - struct dc_stream *stream; + struct dc_stream_state *stream; }; #define to_dm_crtc_state(x) container_of(x, struct dm_crtc_state, base) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index 0a615583de63..4a124537dc9a 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -174,7 +174,7 @@ static void get_payload_table( */ bool dm_helpers_dp_mst_write_payload_allocation_table( struct dc_context *ctx, - const struct dc_stream *stream, + const struct dc_stream_state *stream, struct dp_mst_stream_allocation_table *proposed_table, bool enable) { @@ -264,7 +264,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table( */ bool dm_helpers_dp_mst_poll_for_allocation_change_trigger( struct dc_context *ctx, - const struct dc_stream *stream) + const struct dc_stream_state *stream) { struct amdgpu_connector *aconnector; struct drm_dp_mst_topology_mgr *mst_mgr; @@ -290,7 +290,7 @@ bool dm_helpers_dp_mst_poll_for_allocation_change_trigger( bool dm_helpers_dp_mst_send_payload_allocation( struct dc_context *ctx, - const struct dc_stream *stream, + const struct dc_stream_state *stream, bool enable) { struct amdgpu_connector *aconnector; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 500788c35d70..8b6b7631d776 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -149,12 +149,12 @@ failed_alloc: } static bool stream_adjust_vmin_vmax(struct dc *dc, - struct dc_stream **streams, int num_streams, + struct dc_stream_state **streams, int num_streams, int vmin, int vmax) { /* TODO: Support multiple streams */ struct core_dc *core_dc = DC_TO_CORE(dc); - struct dc_stream *stream = streams[0]; + struct dc_stream_state *stream = streams[0]; int i = 0; bool ret = false; @@ -175,12 +175,12 @@ static bool stream_adjust_vmin_vmax(struct dc *dc, } static bool stream_get_crtc_position(struct dc *dc, - struct dc_stream **streams, int num_streams, + struct dc_stream_state **streams, int num_streams, unsigned int *v_pos, unsigned int *nom_v_pos) { /* TODO: Support multiple streams */ struct core_dc *core_dc = DC_TO_CORE(dc); - struct dc_stream *stream = streams[0]; + struct dc_stream_state *stream = streams[0]; int i = 0; bool ret = false; struct crtc_position position; @@ -200,7 +200,7 @@ static bool stream_get_crtc_position(struct dc *dc, return ret; } -static bool set_gamut_remap(struct dc *dc, const struct dc_stream *stream) +static bool set_gamut_remap(struct dc *dc, const struct dc_stream_state *stream) { struct core_dc *core_dc = DC_TO_CORE(dc); int i = 0; @@ -218,7 +218,7 @@ static bool set_gamut_remap(struct dc *dc, const struct dc_stream *stream) return ret; } -static bool program_csc_matrix(struct dc *dc, struct dc_stream *stream) +static bool program_csc_matrix(struct dc *dc, struct dc_stream_state *stream) { struct core_dc *core_dc = DC_TO_CORE(dc); int i = 0; @@ -241,7 +241,7 @@ static bool program_csc_matrix(struct dc *dc, struct dc_stream *stream) } static void set_static_screen_events(struct dc *dc, - struct dc_stream **streams, + struct dc_stream_state **streams, int num_streams, const struct dc_static_screen_events *events) { @@ -252,7 +252,7 @@ static void set_static_screen_events(struct dc *dc, int num_pipes_affected = 0; for (i = 0; i < num_streams; i++) { - struct dc_stream *stream = streams[i]; + struct dc_stream_state *stream = streams[i]; for (j = 0; j < MAX_PIPES; j++) { if (core_dc->current_context->res_ctx.pipe_ctx[j].stream @@ -333,7 +333,7 @@ static void set_test_pattern( cust_pattern_size); } -void set_dither_option(struct dc_stream *stream, +void set_dither_option(struct dc_stream_state *stream, enum dc_dither_option option) { struct bit_depth_reduction_params params; @@ -769,7 +769,7 @@ context_alloc_fail: bool dc_validate_guaranteed( const struct dc *dc, - struct dc_stream *stream) + struct dc_stream_state *stream) { struct core_dc *core_dc = DC_TO_CORE(dc); enum dc_status result = DC_ERROR_UNEXPECTED; @@ -893,7 +893,7 @@ static bool context_changed( static bool streams_changed( struct core_dc *dc, - struct dc_stream *streams[], + struct dc_stream_state *streams[], uint8_t stream_count) { uint8_t i; @@ -912,7 +912,7 @@ static bool streams_changed( bool dc_enable_stereo( struct dc *dc, struct validate_context *context, - struct dc_stream *streams[], + struct dc_stream_state *streams[], uint8_t stream_count) { bool ret = true; @@ -958,7 +958,7 @@ static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *c enum dc_status result = DC_ERROR_UNEXPECTED; struct pipe_ctx *pipe; int i, j, k, l; - struct dc_stream *dc_streams[MAX_STREAMS] = {0}; + struct dc_stream_state *dc_streams[MAX_STREAMS] = {0}; for (i = 0; i < context->stream_count; i++) dc_streams[i] = context->streams[i]; @@ -1031,7 +1031,7 @@ bool dc_commit_context(struct dc *dc, struct validate_context *context) __func__, context->stream_count); for (i = 0; i < context->stream_count; i++) { - struct dc_stream *stream = context->streams[i]; + struct dc_stream_state *stream = context->streams[i]; dc_stream_log(stream, core_dc->ctx->logger, @@ -1046,7 +1046,7 @@ bool dc_commit_context(struct dc *dc, struct validate_context *context) bool dc_commit_streams( struct dc *dc, - struct dc_stream *streams[], + struct dc_stream_state *streams[], uint8_t stream_count) { struct core_dc *core_dc = DC_TO_CORE(dc); @@ -1062,7 +1062,7 @@ bool dc_commit_streams( __func__, stream_count); for (i = 0; i < stream_count; i++) { - struct dc_stream *stream = streams[i]; + struct dc_stream_state *stream = streams[i]; struct dc_stream_status *status = dc_stream_get_status(stream); int j; @@ -1138,7 +1138,7 @@ bool dc_commit_surfaces_to_stream( struct dc *dc, struct dc_plane_state **new_surfaces, uint8_t new_surface_count, - struct dc_stream *dc_stream) + struct dc_stream_state *dc_stream) { struct dc_surface_update updates[MAX_SURFACES]; struct dc_flip_addrs flip_addr[MAX_SURFACES]; @@ -1395,7 +1395,7 @@ enum surface_update_type update_surface_trace_level = UPDATE_TYPE_FULL; void dc_update_surfaces_and_stream(struct dc *dc, struct dc_surface_update *srf_updates, int surface_count, - struct dc_stream *stream, + struct dc_stream_state *stream, struct dc_stream_update *stream_update) { struct core_dc *core_dc = DC_TO_CORE(dc); @@ -1723,7 +1723,7 @@ uint8_t dc_get_current_stream_count(const struct dc *dc) return core_dc->current_context->stream_count; } -struct dc_stream *dc_get_stream_at_index(const struct dc *dc, uint8_t i) +struct dc_stream_state *dc_get_stream_at_index(const struct dc *dc, uint8_t i) { struct core_dc *core_dc = DC_TO_CORE(dc); if (i < core_dc->current_context->stream_count) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index a983a5ee3172..7a2fe2f3e65c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1143,7 +1143,7 @@ static void dpcd_configure_panel_mode( static void enable_stream_features(struct pipe_ctx *pipe_ctx) { - struct dc_stream *stream = pipe_ctx->stream; + struct dc_stream_state *stream = pipe_ctx->stream; struct dc_link *link = stream->sink->link; union down_spread_ctrl downspread; @@ -1159,7 +1159,7 @@ static void enable_stream_features(struct pipe_ctx *pipe_ctx) static enum dc_status enable_link_dp(struct pipe_ctx *pipe_ctx) { - struct dc_stream *stream = pipe_ctx->stream; + struct dc_stream_state *stream = pipe_ctx->stream; enum dc_status status; bool skip_video_pattern; struct dc_link *link = stream->sink->link; @@ -1250,7 +1250,7 @@ static enum dc_status enable_link_dp_mst(struct pipe_ctx *pipe_ctx) static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) { - struct dc_stream *stream = pipe_ctx->stream; + struct dc_stream_state *stream = pipe_ctx->stream; struct dc_link *link = stream->sink->link; enum dc_color_depth display_color_depth; @@ -1341,7 +1341,7 @@ static void disable_link(struct dc_link *link, enum signal_type signal) } enum dc_status dc_link_validate_mode_timing( - const struct dc_stream *stream, + const struct dc_stream_state *stream, struct dc_link *link, const struct dc_crtc_timing *timing) { @@ -1374,7 +1374,7 @@ enum dc_status dc_link_validate_mode_timing( bool dc_link_set_backlight_level(const struct dc_link *link, uint32_t level, - uint32_t frame_ramp, const struct dc_stream *stream) + uint32_t frame_ramp, const struct dc_stream_state *stream) { struct core_dc *core_dc = DC_TO_CORE(link->ctx->dc); struct abm *abm = core_dc->res_pool->abm; @@ -1450,7 +1450,7 @@ bool dc_link_get_psr_state(const struct dc_link *link, uint32_t *psr_state) } bool dc_link_setup_psr(struct dc_link *link, - const struct dc_stream *stream, struct psr_config *psr_config, + const struct dc_stream_state *stream, struct psr_config *psr_config, struct psr_context *psr_context) { struct core_dc *core_dc = DC_TO_CORE(link->ctx->dc); @@ -1587,7 +1587,7 @@ void core_link_resume(struct dc_link *link) program_hpd_filter(link); } -static struct fixed31_32 get_pbn_per_slot(struct dc_stream *stream) +static struct fixed31_32 get_pbn_per_slot(struct dc_stream_state *stream) { struct dc_link_settings *link_settings = &stream->sink->link->cur_link_settings; @@ -1696,7 +1696,7 @@ static void update_mst_stream_alloc_table( */ static enum dc_status allocate_mst_payload(struct pipe_ctx *pipe_ctx) { - struct dc_stream *stream = pipe_ctx->stream; + struct dc_stream_state *stream = pipe_ctx->stream; struct dc_link *link = stream->sink->link; struct link_encoder *link_encoder = link->link_enc; struct stream_encoder *stream_encoder = pipe_ctx->stream_enc; @@ -1778,7 +1778,7 @@ static enum dc_status allocate_mst_payload(struct pipe_ctx *pipe_ctx) static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx) { - struct dc_stream *stream = pipe_ctx->stream; + struct dc_stream_state *stream = pipe_ctx->stream; struct dc_link *link = stream->sink->link; struct link_encoder *link_encoder = link->link_enc; struct stream_encoder *stream_encoder = pipe_ctx->stream_enc; 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 17506345f97a..50724f9a8e2c 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 @@ -1433,7 +1433,7 @@ bool dp_validate_mode_timing( return false; } -void decide_link_settings(struct dc_stream *stream, +void decide_link_settings(struct dc_stream_state *stream, struct dc_link_settings *link_setting) { diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index fd1d6be79fee..ce0415f26600 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -294,8 +294,8 @@ void resource_reference_clock_source( } bool resource_are_streams_timing_synchronizable( - struct dc_stream *stream1, - struct dc_stream *stream2) + struct dc_stream_state *stream1, + struct dc_stream_state *stream2) { if (stream1->timing.h_total != stream2->timing.h_total) return false; @@ -431,7 +431,7 @@ static void rect_swap_helper(struct rect *rect) static void calculate_viewport(struct pipe_ctx *pipe_ctx) { const struct dc_plane_state *surface = pipe_ctx->surface; - const struct dc_stream *stream = pipe_ctx->stream; + const struct dc_stream_state *stream = pipe_ctx->stream; struct scaler_data *data = &pipe_ctx->scl_data; struct rect surf_src = surface->src_rect; struct rect clip = { 0 }; @@ -530,7 +530,7 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip) { const struct dc_plane_state *surface = pipe_ctx->surface; - const struct dc_stream *stream = pipe_ctx->stream; + const struct dc_stream_state *stream = pipe_ctx->stream; struct rect surf_src = surface->src_rect; struct rect surf_clip = surface->clip_rect; int recout_full_x, recout_full_y; @@ -608,7 +608,7 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) { const struct dc_plane_state *surface = pipe_ctx->surface; - const struct dc_stream *stream = pipe_ctx->stream; + const struct dc_stream_state *stream = pipe_ctx->stream; struct rect surf_src = surface->src_rect; const int in_w = stream->src.width; const int in_h = stream->src.height; @@ -920,7 +920,7 @@ struct pipe_ctx *find_idle_secondary_pipe( struct pipe_ctx *resource_get_head_pipe_for_stream( struct resource_context *res_ctx, - struct dc_stream *stream) + struct dc_stream_state *stream) { int i; for (i = 0; i < MAX_PIPES; i++) { @@ -940,7 +940,7 @@ struct pipe_ctx *resource_get_head_pipe_for_stream( static struct pipe_ctx *acquire_free_pipe_for_stream( struct validate_context *context, const struct resource_pool *pool, - struct dc_stream *stream) + struct dc_stream_state *stream) { int i; struct resource_context *res_ctx = &context->res_ctx; @@ -979,7 +979,7 @@ static struct pipe_ctx *acquire_free_pipe_for_stream( static void release_free_pipes_for_stream( struct resource_context *res_ctx, - struct dc_stream *stream) + struct dc_stream_state *stream) { int i; @@ -997,7 +997,7 @@ static void release_free_pipes_for_stream( static int acquire_first_split_pipe( struct resource_context *res_ctx, const struct resource_pool *pool, - struct dc_stream *stream) + struct dc_stream_state *stream) { int i; @@ -1030,7 +1030,7 @@ static int acquire_first_split_pipe( bool resource_attach_surfaces_to_context( struct dc_plane_state * const *surfaces, int surface_count, - struct dc_stream *stream, + struct dc_stream_state *stream, struct validate_context *context, const struct resource_pool *pool) { @@ -1118,8 +1118,8 @@ bool resource_attach_surfaces_to_context( } -static bool is_timing_changed(struct dc_stream *cur_stream, - struct dc_stream *new_stream) +static bool is_timing_changed(struct dc_stream_state *cur_stream, + struct dc_stream_state *new_stream) { if (cur_stream == NULL) return true; @@ -1141,7 +1141,7 @@ static bool is_timing_changed(struct dc_stream *cur_stream, } static bool are_stream_backends_same( - struct dc_stream *stream_a, struct dc_stream *stream_b) + struct dc_stream_state *stream_a, struct dc_stream_state *stream_b) { if (stream_a == stream_b) return true; @@ -1156,7 +1156,7 @@ static bool are_stream_backends_same( } bool dc_is_stream_unchanged( - struct dc_stream *old_stream, struct dc_stream *stream) + struct dc_stream_state *old_stream, struct dc_stream_state *stream) { if (!are_stream_backends_same(old_stream, stream)) @@ -1233,7 +1233,7 @@ static void set_audio_in_use( static int acquire_first_free_pipe( struct resource_context *res_ctx, const struct resource_pool *pool, - struct dc_stream *stream) + struct dc_stream_state *stream) { int i; @@ -1260,7 +1260,7 @@ static int acquire_first_free_pipe( static struct stream_encoder *find_first_free_match_stream_enc_for_link( struct resource_context *res_ctx, const struct resource_pool *pool, - struct dc_stream *stream) + struct dc_stream_state *stream) { int i; int j = -1; @@ -1311,7 +1311,7 @@ static struct audio *find_first_free_audio( return 0; } -static void update_stream_signal(struct dc_stream *stream) +static void update_stream_signal(struct dc_stream_state *stream) { if (stream->output_signal == SIGNAL_TYPE_NONE) { struct dc_sink *dc_sink = stream->sink; @@ -1334,12 +1334,12 @@ static void update_stream_signal(struct dc_stream *stream) } bool resource_is_stream_unchanged( - struct validate_context *old_context, struct dc_stream *stream) + struct validate_context *old_context, struct dc_stream_state *stream) { int i; for (i = 0; i < old_context->stream_count; i++) { - struct dc_stream *old_stream = old_context->streams[i]; + struct dc_stream_state *old_stream = old_context->streams[i]; if (are_stream_backends_same(old_stream, stream)) return true; @@ -1352,7 +1352,7 @@ static void copy_pipe_ctx( const struct pipe_ctx *from_pipe_ctx, struct pipe_ctx *to_pipe_ctx) { struct dc_plane_state *surface = to_pipe_ctx->surface; - struct dc_stream *stream = to_pipe_ctx->stream; + struct dc_stream_state *stream = to_pipe_ctx->stream; *to_pipe_ctx = *from_pipe_ctx; to_pipe_ctx->stream = stream; @@ -1360,14 +1360,14 @@ static void copy_pipe_ctx( to_pipe_ctx->surface = surface; } -static struct dc_stream *find_pll_sharable_stream( - struct dc_stream *stream_needs_pll, +static struct dc_stream_state *find_pll_sharable_stream( + struct dc_stream_state *stream_needs_pll, struct validate_context *context) { int i; for (i = 0; i < context->stream_count; i++) { - struct dc_stream *stream_has_pll = context->streams[i]; + struct dc_stream_state *stream_has_pll = context->streams[i]; /* We are looking for non dp, non virtual stream */ if (resource_are_streams_timing_synchronizable( @@ -1411,7 +1411,7 @@ static int get_norm_pix_clk(const struct dc_crtc_timing *timing) return normalized_pix_clk; } -static void calculate_phy_pix_clks(struct dc_stream *stream) +static void calculate_phy_pix_clks(struct dc_stream_state *stream) { update_stream_signal(stream); @@ -1433,7 +1433,7 @@ enum dc_status resource_map_pool_resources( int i, j; for (i = 0; old_context && i < context->stream_count; i++) { - struct dc_stream *stream = context->streams[i]; + struct dc_stream_state *stream = context->streams[i]; if (!resource_is_stream_unchanged(old_context, stream)) { if (stream != NULL && old_context->streams[i] != NULL) { @@ -1486,7 +1486,7 @@ enum dc_status resource_map_pool_resources( } for (i = 0; i < context->stream_count; i++) { - struct dc_stream *stream = context->streams[i]; + struct dc_stream_state *stream = context->streams[i]; struct pipe_ctx *pipe_ctx = NULL; int pipe_idx = -1; @@ -1581,7 +1581,7 @@ static void set_avi_info_frame( struct encoder_info_packet *info_packet, struct pipe_ctx *pipe_ctx) { - struct dc_stream *stream = pipe_ctx->stream; + struct dc_stream_state *stream = pipe_ctx->stream; enum dc_color_space color_space = COLOR_SPACE_UNKNOWN; struct info_frame info_frame = { {0} }; uint32_t pixel_encoding = 0; @@ -1821,7 +1821,7 @@ static void set_avi_info_frame( static void set_vendor_info_packet( struct encoder_info_packet *info_packet, - struct dc_stream *stream) + struct dc_stream_state *stream) { uint32_t length = 0; bool hdmi_vic_mode = false; @@ -1934,7 +1934,7 @@ static void set_vendor_info_packet( static void set_spd_info_packet( struct encoder_info_packet *info_packet, - struct dc_stream *stream) + struct dc_stream_state *stream) { /* SPD info packet for FreeSync */ @@ -2056,7 +2056,7 @@ static void set_spd_info_packet( static void set_hdr_static_info_packet( struct encoder_info_packet *info_packet, struct dc_plane_state *surface, - struct dc_stream *stream) + struct dc_stream_state *stream) { uint16_t i = 0; enum signal_type signal = stream->signal; @@ -2159,7 +2159,7 @@ static void set_hdr_static_info_packet( static void set_vsc_info_packet( struct encoder_info_packet *info_packet, - struct dc_stream *stream) + struct dc_stream_state *stream) { unsigned int vscPacketRevision = 0; unsigned int i; @@ -2312,7 +2312,7 @@ enum dc_status resource_map_clock_resources( /* acquire new resources */ for (i = 0; i < context->stream_count; i++) { - struct dc_stream *stream = context->streams[i]; + struct dc_stream_state *stream = context->streams[i]; if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; @@ -2392,7 +2392,7 @@ bool pipe_need_reprogram( return false; } -void resource_build_bit_depth_reduction_params(struct dc_stream *stream, +void resource_build_bit_depth_reduction_params(struct dc_stream_state *stream, struct bit_depth_reduction_params *fmt_bit_depth) { enum dc_dither_option option = stream->dither_option; @@ -2502,7 +2502,7 @@ void resource_build_bit_depth_reduction_params(struct dc_stream *stream, fmt_bit_depth->pixel_encoding = pixel_encoding; } -bool dc_validate_stream(const struct dc *dc, struct dc_stream *stream) +bool dc_validate_stream(const struct dc *dc, struct dc_stream_state *stream) { struct core_dc *core_dc = DC_TO_CORE(dc); struct dc_context *dc_ctx = core_dc->ctx; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index a77e1e80d7c2..7a87f38f2324 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -34,7 +34,7 @@ * Private functions ******************************************************************************/ -static bool construct(struct dc_stream *stream, +static bool construct(struct dc_stream_state *stream, struct dc_sink *dc_sink_data) { uint32_t i = 0; @@ -84,7 +84,7 @@ static bool construct(struct dc_stream *stream, return true; } -static void destruct(struct dc_stream *stream) +static void destruct(struct dc_stream_state *stream) { dc_sink_release(stream->sink); if (stream->out_transfer_func != NULL) { @@ -94,14 +94,14 @@ static void destruct(struct dc_stream *stream) } } -void dc_stream_retain(struct dc_stream *stream) +void dc_stream_retain(struct dc_stream_state *stream) { ASSERT(stream->ref_count > 0); stream->ref_count++; } -void dc_stream_release(struct dc_stream *stream) +void dc_stream_release(struct dc_stream_state *stream) { if (stream != NULL) { @@ -115,15 +115,15 @@ void dc_stream_release(struct dc_stream *stream) } } -struct dc_stream *dc_create_stream_for_sink( +struct dc_stream_state *dc_create_stream_for_sink( struct dc_sink *sink) { - struct dc_stream *stream; + struct dc_stream_state *stream; if (sink == NULL) goto alloc_fail; - stream = dm_alloc(sizeof(struct dc_stream)); + stream = dm_alloc(sizeof(struct dc_stream_state)); if (NULL == stream) goto alloc_fail; @@ -143,7 +143,7 @@ alloc_fail: } struct dc_stream_status *dc_stream_get_status( - struct dc_stream *stream) + struct dc_stream_state *stream) { uint8_t i; struct core_dc *dc = DC_TO_CORE(stream->ctx->dc); @@ -161,7 +161,7 @@ struct dc_stream_status *dc_stream_get_status( * Update the cursor attributes and set cursor surface address */ bool dc_stream_set_cursor_attributes( - const struct dc_stream *stream, + const struct dc_stream_state *stream, const struct dc_cursor_attributes *attributes) { int i; @@ -196,7 +196,7 @@ bool dc_stream_set_cursor_attributes( } bool dc_stream_set_cursor_position( - struct dc_stream *stream, + struct dc_stream_state *stream, const struct dc_cursor_position *position) { int i; @@ -245,7 +245,7 @@ bool dc_stream_set_cursor_position( return true; } -uint32_t dc_stream_get_vblank_counter(const struct dc_stream *stream) +uint32_t dc_stream_get_vblank_counter(const struct dc_stream_state *stream) { uint8_t i; struct core_dc *core_dc = DC_TO_CORE(stream->ctx->dc); @@ -264,7 +264,7 @@ uint32_t dc_stream_get_vblank_counter(const struct dc_stream *stream) return 0; } -bool dc_stream_get_scanoutpos(const struct dc_stream *stream, +bool dc_stream_get_scanoutpos(const struct dc_stream_state *stream, uint32_t *v_blank_start, uint32_t *v_blank_end, uint32_t *h_position, @@ -297,7 +297,7 @@ bool dc_stream_get_scanoutpos(const struct dc_stream *stream, void dc_stream_log( - const struct dc_stream *stream, + const struct dc_stream_state *stream, struct dal_logger *dm_logger, enum dc_log_type log_type) { diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index d1943b9644d4..ab805965e321 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -101,30 +101,30 @@ struct dc_cap_funcs { struct dc_surface_dcc_cap *output); }; -struct dc_stream_funcs { +struct dc_stream_state_funcs { bool (*adjust_vmin_vmax)(struct dc *dc, - struct dc_stream **stream, + struct dc_stream_state **stream, int num_streams, int vmin, int vmax); bool (*get_crtc_position)(struct dc *dc, - struct dc_stream **stream, + struct dc_stream_state **stream, int num_streams, unsigned int *v_pos, unsigned int *nom_v_pos); bool (*set_gamut_remap)(struct dc *dc, - const struct dc_stream *stream); + const struct dc_stream_state *stream); bool (*program_csc_matrix)(struct dc *dc, - struct dc_stream *stream); + struct dc_stream_state *stream); void (*set_static_screen_events)(struct dc *dc, - struct dc_stream **stream, + struct dc_stream_state **stream, int num_streams, const struct dc_static_screen_events *events); - void (*set_dither_option)(struct dc_stream *stream, + void (*set_dither_option)(struct dc_stream_state *stream, enum dc_dither_option option); }; @@ -190,7 +190,7 @@ struct dc_debug { struct dc { struct dc_caps caps; struct dc_cap_funcs cap_funcs; - struct dc_stream_funcs stream_funcs; + struct dc_stream_state_funcs stream_funcs; struct dc_link_funcs link_funcs; struct dc_config config; struct dc_debug debug; @@ -426,7 +426,7 @@ bool dc_commit_surfaces_to_stream( struct dc *dc, struct dc_plane_state **dc_surfaces, uint8_t surface_count, - struct dc_stream *stream); + struct dc_stream_state *stream); bool dc_post_update_surfaces_to_stream( struct dc *dc); @@ -478,7 +478,7 @@ struct dc_stream_status { struct dc_link *link; }; -struct dc_stream { +struct dc_stream_state { struct dc_sink *sink; struct dc_crtc_timing timing; @@ -529,7 +529,7 @@ struct dc_stream_update { }; bool dc_is_stream_unchanged( - struct dc_stream *old_stream, struct dc_stream *stream); + struct dc_stream_state *old_stream, struct dc_stream_state *stream); /* * Setup stream attributes if no stream updates are provided @@ -548,30 +548,30 @@ bool dc_is_stream_unchanged( void dc_update_surfaces_and_stream(struct dc *dc, struct dc_surface_update *surface_updates, int surface_count, - struct dc_stream *dc_stream, + struct dc_stream_state *dc_stream, struct dc_stream_update *stream_update); /* * Log the current stream state. */ void dc_stream_log( - const struct dc_stream *stream, + const struct dc_stream_state *stream, struct dal_logger *dc_logger, enum dc_log_type log_type); uint8_t dc_get_current_stream_count(const struct dc *dc); -struct dc_stream *dc_get_stream_at_index(const struct dc *dc, uint8_t i); +struct dc_stream_state *dc_get_stream_at_index(const struct dc *dc, uint8_t i); /* * Return the current frame counter. */ -uint32_t dc_stream_get_vblank_counter(const struct dc_stream *stream); +uint32_t dc_stream_get_vblank_counter(const struct dc_stream_state *stream); /* TODO: Return parsed values rather than direct register read * This has a dependency on the caller (amdgpu_get_crtc_scanoutpos) * being refactored properly to be dce-specific */ -bool dc_stream_get_scanoutpos(const struct dc_stream *stream, +bool dc_stream_get_scanoutpos(const struct dc_stream_state *stream, uint32_t *v_blank_start, uint32_t *v_blank_end, uint32_t *h_position, @@ -581,12 +581,12 @@ bool dc_stream_get_scanoutpos(const struct dc_stream *stream, * Structure to store surface/stream associations for validation */ struct dc_validation_set { - struct dc_stream *stream; + struct dc_stream_state *stream; struct dc_plane_state *surfaces[MAX_SURFACES]; uint8_t surface_count; }; -bool dc_validate_stream(const struct dc *dc, struct dc_stream *stream); +bool dc_validate_stream(const struct dc *dc, struct dc_stream_state *stream); bool dc_validate_plane(const struct dc *dc, const struct dc_plane_state *plane_state); /* @@ -615,7 +615,7 @@ bool dc_validate_resources( bool dc_validate_guaranteed( const struct dc *dc, - struct dc_stream *stream); + struct dc_stream_state *stream); void dc_resource_validate_ctx_copy_construct( const struct validate_context *src_ctx, @@ -644,7 +644,7 @@ bool dc_commit_context(struct dc *dc, struct validate_context *context); */ bool dc_commit_streams( struct dc *dc, - struct dc_stream *streams[], + struct dc_stream_state *streams[], uint8_t stream_count); /* * Enable stereo when commit_streams is not required, @@ -653,19 +653,19 @@ bool dc_commit_streams( bool dc_enable_stereo( struct dc *dc, struct validate_context *context, - struct dc_stream *streams[], + struct dc_stream_state *streams[], uint8_t stream_count); /** * Create a new default stream for the requested sink */ -struct dc_stream *dc_create_stream_for_sink(struct dc_sink *dc_sink); +struct dc_stream_state *dc_create_stream_for_sink(struct dc_sink *dc_sink); -void dc_stream_retain(struct dc_stream *dc_stream); -void dc_stream_release(struct dc_stream *dc_stream); +void dc_stream_retain(struct dc_stream_state *dc_stream); +void dc_stream_release(struct dc_stream_state *dc_stream); struct dc_stream_status *dc_stream_get_status( - struct dc_stream *dc_stream); + struct dc_stream_state *dc_stream); enum surface_update_type dc_check_update_surfaces_for_stream( struct dc *dc, @@ -804,7 +804,7 @@ const struct graphics_object_id dc_get_link_id_at_index( /* Set backlight level of an embedded panel (eDP, LVDS). */ bool dc_link_set_backlight_level(const struct dc_link *dc_link, uint32_t level, - uint32_t frame_ramp, const struct dc_stream *stream); + uint32_t frame_ramp, const struct dc_stream_state *stream); bool dc_link_set_abm_disable(const struct dc_link *dc_link); @@ -813,7 +813,7 @@ bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable); bool dc_link_get_psr_state(const struct dc_link *dc_link, uint32_t *psr_state); bool dc_link_setup_psr(struct dc_link *dc_link, - const struct dc_stream *stream, struct psr_config *psr_config, + const struct dc_stream_state *stream, struct psr_config *psr_config, struct psr_context *psr_context); /* Request DC to detect if there is a Panel connected. @@ -927,11 +927,11 @@ bool dc_sink_set_container_id(struct dc_sink *dc_sink, const struct dc_container ******************************************************************************/ /* TODO: Deprecated once we switch to dc_set_cursor_position */ bool dc_stream_set_cursor_attributes( - const struct dc_stream *stream, + const struct dc_stream_state *stream, const struct dc_cursor_attributes *attributes); bool dc_stream_set_cursor_position( - struct dc_stream *stream, + struct dc_stream_state *stream, const struct dc_cursor_position *position); /* Newer interfaces */ diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 4fb9584452a4..a47f7472ea92 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -35,7 +35,7 @@ /* forward declarations */ struct dc_plane_state; -struct dc_stream; +struct dc_stream_state; struct dc_link; struct dc_sink; struct dal; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 24d0c48258ee..5bb2ac71f297 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -1009,7 +1009,7 @@ bool dce110_link_encoder_construct( bool dce110_link_encoder_validate_output_with_stream( struct link_encoder *enc, - const struct dc_stream *stream) + const struct dc_stream_state *stream) { struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); bool is_valid; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h index 5f05ca65281e..5960fb933f1f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h @@ -196,7 +196,7 @@ bool dce110_link_encoder_validate_wireless_output( bool dce110_link_encoder_validate_output_with_stream( struct link_encoder *enc, - const struct dc_stream *stream); + const struct dc_stream_state *stream); /****************** HW programming ************************/ diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 2cf2fefc3d79..98fb7f02a6fe 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -660,7 +660,7 @@ static enum dc_status build_mapped_resource( uint8_t i, j; for (i = 0; i < context->stream_count; i++) { - struct dc_stream *stream = context->streams[i]; + struct dc_stream_state *stream = context->streams[i]; if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; @@ -765,7 +765,7 @@ enum dc_status dce100_validate_with_context( enum dc_status dce100_validate_guaranteed( const struct core_dc *dc, - struct dc_stream *dc_stream, + struct dc_stream_state *dc_stream, struct validate_context *context) { enum dc_status result = DC_ERROR_UNEXPECTED; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 84dc8916de96..e4310a376116 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -623,7 +623,7 @@ static bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func static bool dce110_set_output_transfer_func( struct pipe_ctx *pipe_ctx, - const struct dc_stream *stream) + const struct dc_stream_state *stream) { struct transform *xfm = pipe_ctx->xfm; @@ -745,7 +745,7 @@ void dce110_enable_stream(struct pipe_ctx *pipe_ctx) void dce110_disable_stream(struct pipe_ctx *pipe_ctx) { - struct dc_stream *stream = pipe_ctx->stream; + struct dc_stream_state *stream = pipe_ctx->stream; struct dc_link *link = stream->sink->link; if (pipe_ctx->audio) { @@ -833,7 +833,7 @@ static void build_audio_output( const struct pipe_ctx *pipe_ctx, struct audio_output *audio_output) { - const struct dc_stream *stream = pipe_ctx->stream; + const struct dc_stream_state *stream = pipe_ctx->stream; audio_output->engine_id = pipe_ctx->stream_enc->id; audio_output->signal = pipe_ctx->stream->signal; @@ -981,7 +981,7 @@ static enum dc_status dce110_prog_pixclk_crtc_otg( struct validate_context *context, struct core_dc *dc) { - struct dc_stream *stream = pipe_ctx->stream; + struct dc_stream_state *stream = pipe_ctx->stream; struct pipe_ctx *pipe_ctx_old = &dc->current_context->res_ctx. pipe_ctx[pipe_ctx->pipe_idx]; struct tg_color black_color = {0}; @@ -1037,7 +1037,7 @@ static enum dc_status apply_single_controller_ctx_to_hw( struct validate_context *context, struct core_dc *dc) { - struct dc_stream *stream = pipe_ctx->stream; + struct dc_stream_state *stream = pipe_ctx->stream; struct pipe_ctx *pipe_ctx_old = &dc->current_context->res_ctx. pipe_ctx[pipe_ctx->pipe_idx]; @@ -1229,7 +1229,7 @@ void dce110_enable_accelerated_mode(struct core_dc *dc) static uint32_t compute_pstate_blackout_duration( struct bw_fixed blackout_duration, - const struct dc_stream *stream) + const struct dc_stream_state *stream) { uint32_t total_dest_line_time_ns; uint32_t pstate_blackout_duration_ns; @@ -2325,7 +2325,7 @@ void dce110_fill_display_configs( for (j = 0; j < context->stream_count; j++) { int k; - const struct dc_stream *stream = context->streams[j]; + const struct dc_stream_state *stream = context->streams[j]; struct dm_pp_single_disp_config *cfg = &pp_display_cfg->disp_configs[num_cfgs]; const struct pipe_ctx *pipe_ctx = NULL; @@ -2370,7 +2370,7 @@ uint32_t dce110_get_min_vblank_time_us(const struct validate_context *context) uint32_t min_vertical_blank_time = -1; for (j = 0; j < context->stream_count; j++) { - struct dc_stream *stream = context->streams[j]; + struct dc_stream_state *stream = context->streams[j]; uint32_t vertical_blank_in_pixels = 0; uint32_t vertical_blank_time = 0; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 5c1790b61290..89b21bd57a35 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -718,7 +718,7 @@ static void get_pixel_clock_parameters( const struct pipe_ctx *pipe_ctx, struct pixel_clk_params *pixel_clk_params) { - const struct dc_stream *stream = pipe_ctx->stream; + const struct dc_stream_state *stream = pipe_ctx->stream; /*TODO: is this halved for YCbCr 420? in that case we might want to move * the pixel clock normalization for hdmi up to here instead of doing it @@ -780,7 +780,7 @@ static enum dc_status build_mapped_resource( uint8_t i, j; for (i = 0; i < context->stream_count; i++) { - struct dc_stream *stream = context->streams[i]; + struct dc_stream_state *stream = context->streams[i]; if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; @@ -973,7 +973,7 @@ enum dc_status dce110_validate_with_context( enum dc_status dce110_validate_guaranteed( const struct core_dc *dc, - struct dc_stream *dc_stream, + struct dc_stream_state *dc_stream, struct validate_context *context) { enum dc_status result = DC_ERROR_UNEXPECTED; @@ -1006,7 +1006,7 @@ enum dc_status dce110_validate_guaranteed( static struct pipe_ctx *dce110_acquire_underlay( struct validate_context *context, const struct resource_pool *pool, - struct dc_stream *stream) + struct dc_stream_state *stream) { struct core_dc *dc = DC_TO_CORE(stream->ctx->dc); struct resource_context *res_ctx = &context->res_ctx; diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index c68372fa1292..68554d6edd94 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -700,7 +700,7 @@ static void destruct(struct dce110_resource_pool *pool) static struct clock_source *find_matching_pll( struct resource_context *res_ctx, const struct resource_pool *pool, - const struct dc_stream *const stream) + const struct dc_stream_state *const stream) { switch (stream->sink->link->link_enc->transmitter) { case TRANSMITTER_UNIPHY_A: @@ -731,7 +731,7 @@ static enum dc_status build_mapped_resource( uint8_t i, j; for (i = 0; i < context->stream_count; i++) { - struct dc_stream *stream = context->streams[i]; + struct dc_stream_state *stream = context->streams[i]; if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; @@ -845,7 +845,7 @@ enum dc_status resource_map_phy_clock_resources( /* acquire new resources */ for (i = 0; i < context->stream_count; i++) { - struct dc_stream *stream = context->streams[i]; + struct dc_stream_state *stream = context->streams[i]; if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; @@ -949,7 +949,7 @@ enum dc_status dce112_validate_with_context( enum dc_status dce112_validate_guaranteed( const struct core_dc *dc, - struct dc_stream *stream, + struct dc_stream_state *stream, struct validate_context *context) { enum dc_status result = DC_ERROR_UNEXPECTED; diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h index cb2c69fb05a6..feef559f1ecd 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h @@ -44,7 +44,7 @@ enum dc_status dce112_validate_with_context( enum dc_status dce112_validate_guaranteed( const struct core_dc *dc, - struct dc_stream *dc_stream, + struct dc_stream_state *dc_stream, struct validate_context *context); bool dce112_validate_bandwidth( diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index bcb66447b558..734b35eddeed 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -677,7 +677,7 @@ static enum dc_status build_mapped_resource( uint8_t i, j; for (i = 0; i < context->stream_count; i++) { - struct dc_stream *stream = context->streams[i]; + struct dc_stream_state *stream = context->streams[i]; if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; @@ -781,7 +781,7 @@ enum dc_status dce80_validate_with_context( enum dc_status dce80_validate_guaranteed( const struct core_dc *dc, - struct dc_stream *dc_stream, + struct dc_stream_state *dc_stream, struct validate_context *context) { enum dc_status result = DC_ERROR_UNEXPECTED; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 3979cb03cf8d..866f63d1259d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -679,7 +679,7 @@ static enum dc_status dcn10_prog_pixclk_crtc_otg( struct validate_context *context, struct core_dc *dc) { - struct dc_stream *stream = pipe_ctx->stream; + struct dc_stream_state *stream = pipe_ctx->stream; enum dc_color_space color_space; struct tg_color black_color = {0}; bool enableStereo = stream->timing.timing_3d_format == TIMING_3D_FORMAT_NONE ? @@ -1445,7 +1445,7 @@ static bool dcn10_translate_regamma_to_hw_format(const struct dc_transfer_func static bool dcn10_set_output_transfer_func( struct pipe_ctx *pipe_ctx, - const struct dc_stream *stream) + const struct dc_stream_state *stream) { struct transform *xfm = pipe_ctx->xfm; @@ -2321,7 +2321,7 @@ static void set_plane_config( } static void dcn10_config_stereo_parameters( - struct dc_stream *stream, struct crtc_stereo_flags *flags) + struct dc_stream_state *stream, struct crtc_stereo_flags *flags) { enum view_3d_format view_format = stream->view_format; enum dc_timing_3d_format timing_3d_format =\ @@ -2360,7 +2360,7 @@ static void dcn10_config_stereo_parameters( static void dcn10_setup_stereo(struct pipe_ctx *pipe_ctx, struct core_dc *dc) { struct crtc_stereo_flags flags = { 0 }; - struct dc_stream *stream = pipe_ctx->stream; + struct dc_stream_state *stream = pipe_ctx->stream; dcn10_config_stereo_parameters(stream, &flags); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 9d44f42cbf96..5a9fcbc22d04 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -774,7 +774,7 @@ static void get_pixel_clock_parameters( const struct pipe_ctx *pipe_ctx, struct pixel_clk_params *pixel_clk_params) { - const struct dc_stream *stream = pipe_ctx->stream; + const struct dc_stream_state *stream = pipe_ctx->stream; pixel_clk_params->requested_pix_clk = stream->timing.pix_clk_khz; pixel_clk_params->encoder_object_id = stream->sink->link->link_enc->id; pixel_clk_params->signal_type = pipe_ctx->stream->signal; @@ -796,7 +796,7 @@ static void get_pixel_clock_parameters( } -static void build_clamping_params(struct dc_stream *stream) +static void build_clamping_params(struct dc_stream_state *stream) { stream->clamping.clamping_level = CLAMPING_FULL_RANGE; stream->clamping.c_depth = stream->timing.display_color_depth; @@ -831,7 +831,7 @@ static enum dc_status build_mapped_resource( uint8_t i, j; for (i = 0; i < context->stream_count; i++) { - struct dc_stream *stream = context->streams[i]; + struct dc_stream_state *stream = context->streams[i]; if (old_context && resource_is_stream_unchanged(old_context, stream)) { if (stream != NULL && old_context->streams[i] != NULL) { @@ -916,7 +916,7 @@ enum dc_status dcn10_validate_with_context( enum dc_status dcn10_validate_guaranteed( const struct core_dc *dc, - struct dc_stream *dc_stream, + struct dc_stream_state *dc_stream, struct validate_context *context) { enum dc_status result = DC_ERROR_UNEXPECTED; @@ -947,7 +947,7 @@ enum dc_status dcn10_validate_guaranteed( static struct pipe_ctx *dcn10_acquire_idle_pipe_for_layer( struct validate_context *context, const struct resource_pool *pool, - struct dc_stream *stream) + struct dc_stream_state *stream) { struct resource_context *res_ctx = &context->res_ctx; struct pipe_ctx *head_pipe = resource_get_head_pipe_for_stream(res_ctx, stream); diff --git a/drivers/gpu/drm/amd/display/dc/dm_helpers.h b/drivers/gpu/drm/amd/display/dc/dm_helpers.h index e8bd501feb48..39010325cef9 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_helpers.h +++ b/drivers/gpu/drm/amd/display/dc/dm_helpers.h @@ -45,7 +45,7 @@ enum dc_edid_status dm_helpers_parse_edid_caps( */ bool dm_helpers_dp_mst_write_payload_allocation_table( struct dc_context *ctx, - const struct dc_stream *stream, + const struct dc_stream_state *stream, struct dp_mst_stream_allocation_table *proposed_table, bool enable); @@ -54,13 +54,13 @@ bool dm_helpers_dp_mst_write_payload_allocation_table( */ bool dm_helpers_dp_mst_poll_for_allocation_change_trigger( struct dc_context *ctx, - const struct dc_stream *stream); + const struct dc_stream_state *stream); /* * Sends ALLOCATE_PAYLOAD message. */ bool dm_helpers_dp_mst_send_payload_allocation( struct dc_context *ctx, - const struct dc_stream *stream, + const struct dc_stream_state *stream, bool enable); bool dm_helpers_dp_mst_start_top_mgr( diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 44a87c9427f7..d5c0f9e34ce9 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -60,7 +60,7 @@ struct dc_link *link_create(const struct link_init_data *init_params); void link_destroy(struct dc_link **link); enum dc_status dc_link_validate_mode_timing( - const struct dc_stream *stream, + const struct dc_stream_state *stream, struct dc_link *link, const struct dc_crtc_timing *timing); @@ -92,7 +92,7 @@ struct resource_funcs { enum dc_status (*validate_guaranteed)( const struct core_dc *dc, - struct dc_stream *stream, + struct dc_stream_state *stream, struct validate_context *context); bool (*validate_bandwidth)( @@ -102,8 +102,7 @@ struct resource_funcs { struct pipe_ctx *(*acquire_idle_pipe_for_layer)( struct validate_context *context, const struct resource_pool *pool, - struct dc_stream *stream); - + struct dc_stream_state *stream); enum dc_status (*validate_plane)(const struct dc_plane_state *plane_state); }; @@ -155,7 +154,7 @@ struct resource_pool { struct pipe_ctx { struct dc_plane_state *surface; - struct dc_stream *stream; + struct dc_stream_state *stream; struct mem_input *mi; struct input_pixel_processor *ipp; @@ -240,7 +239,7 @@ union bw_context { }; struct validate_context { - struct dc_stream *streams[MAX_PIPES]; + struct dc_stream_state *streams[MAX_PIPES]; struct dc_stream_status stream_status[MAX_PIPES]; uint8_t stream_count; diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h index 1a4a605cb449..7168dcc70ae7 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h @@ -30,7 +30,7 @@ #define LINK_TRAINING_RETRY_DELAY 50 /* ms */ struct dc_link; -struct dc_stream; +struct dc_stream_state; struct dc_link_settings; bool dp_hbr_verify_link_cap( @@ -50,7 +50,7 @@ bool dp_validate_mode_timing( const struct dc_crtc_timing *timing); void decide_link_settings( - struct dc_stream *stream, + struct dc_stream_state *stream, struct dc_link_settings *link_setting); bool perform_link_training_with_retries( diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h index 28fb02fb677e..38e4070806cb 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h @@ -93,7 +93,7 @@ struct link_encoder { struct link_encoder_funcs { bool (*validate_output_with_stream)( - struct link_encoder *enc, const struct dc_stream *stream); + struct link_encoder *enc, const struct dc_stream_state *stream); void (*hw_init)(struct link_encoder *enc); void (*setup)(struct link_encoder *enc, enum signal_type signal); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index c529ddd2e0d5..7e03f8d45b2b 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -92,7 +92,7 @@ struct hw_sequencer_funcs { bool (*set_output_transfer_func)( struct pipe_ctx *pipe_ctx, - const struct dc_stream *stream); + const struct dc_stream_state *stream); void (*power_down)(struct core_dc *dc); diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index bfd7cfc86df0..aef1197cf749 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -103,8 +103,8 @@ void resource_reference_clock_source( struct clock_source *clock_source); bool resource_are_streams_timing_synchronizable( - struct dc_stream *stream1, - struct dc_stream *stream2); + struct dc_stream_state *stream1, + struct dc_stream_state *stream2); struct clock_source *resource_find_used_clk_src_for_sharing( struct resource_context *res_ctx, @@ -116,12 +116,12 @@ struct clock_source *dc_resource_find_first_free_pll( struct pipe_ctx *resource_get_head_pipe_for_stream( struct resource_context *res_ctx, - struct dc_stream *stream); + struct dc_stream_state *stream); bool resource_attach_surfaces_to_context( struct dc_plane_state *const *surfaces, int surface_count, - struct dc_stream *dc_stream, + struct dc_stream_state *dc_stream, struct validate_context *context, const struct resource_pool *pool); @@ -130,8 +130,7 @@ struct pipe_ctx *find_idle_secondary_pipe( const struct resource_pool *pool); bool resource_is_stream_unchanged( - struct validate_context *old_context, struct dc_stream *stream); - + struct validate_context *old_context, struct dc_stream_state *stream); bool resource_validate_attach_surfaces( const struct dc_validation_set set[], @@ -162,7 +161,7 @@ bool pipe_need_reprogram( struct pipe_ctx *pipe_ctx_old, struct pipe_ctx *pipe_ctx); -void resource_build_bit_depth_reduction_params(struct dc_stream *stream, +void resource_build_bit_depth_reduction_params(struct dc_stream_state *stream, struct bit_depth_reduction_params *fmt_bit_depth); #endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c index dd024c99fb7e..57b5a3babdf8 100644 --- a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c @@ -30,7 +30,7 @@ static bool virtual_link_encoder_validate_output_with_stream( struct link_encoder *enc, - const struct dc_stream *stream) { return true; } + const struct dc_stream_state *stream) { return true; } static void virtual_link_encoder_hw_init(struct link_encoder *enc) {} diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index 358f8a855a59..f0a3e4332a09 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -111,7 +111,7 @@ struct freesync_state { }; struct freesync_entity { - struct dc_stream *stream; + struct dc_stream_state *stream; struct mod_freesync_caps *caps; struct freesync_state state; struct mod_freesync_user_enable user_enable; @@ -229,7 +229,7 @@ void mod_freesync_destroy(struct mod_freesync *mod_freesync) * on the core_freesync->map and returns the corresponding index */ static unsigned int map_index_from_stream(struct core_freesync *core_freesync, - struct dc_stream *stream) + struct dc_stream_state *stream) { unsigned int index = 0; @@ -244,7 +244,7 @@ static unsigned int map_index_from_stream(struct core_freesync *core_freesync, } bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, - struct dc_stream *stream, struct mod_freesync_caps *caps) + struct dc_stream_state *stream, struct mod_freesync_caps *caps) { struct core_dc *core_dc = NULL; struct core_freesync *core_freesync = NULL; @@ -322,7 +322,7 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, } bool mod_freesync_remove_stream(struct mod_freesync *mod_freesync, - struct dc_stream *stream) + struct dc_stream_state *stream) { int i = 0; struct core_freesync *core_freesync = NULL; @@ -344,7 +344,7 @@ bool mod_freesync_remove_stream(struct mod_freesync *mod_freesync, } static void update_stream_freesync_context(struct core_freesync *core_freesync, - struct dc_stream *stream) + struct dc_stream_state *stream) { unsigned int index; struct freesync_context *ctx; @@ -368,7 +368,7 @@ static void update_stream_freesync_context(struct core_freesync *core_freesync, } static void update_stream(struct core_freesync *core_freesync, - struct dc_stream *stream) + struct dc_stream_state *stream) { unsigned int index = map_index_from_stream(core_freesync, stream); if (core_freesync->map[index].caps->supported) { @@ -378,7 +378,7 @@ static void update_stream(struct core_freesync *core_freesync, } static void calc_freesync_range(struct core_freesync *core_freesync, - struct dc_stream *stream, + struct dc_stream_state *stream, struct freesync_state *state, unsigned int min_refresh_in_uhz, unsigned int max_refresh_in_uhz) @@ -452,7 +452,7 @@ static void calc_freesync_range(struct core_freesync *core_freesync, min_frame_duration_in_ns) / 2000; } -static void calc_v_total_from_duration(struct dc_stream *stream, +static void calc_v_total_from_duration(struct dc_stream_state *stream, unsigned int duration_in_ns, int *v_total_nominal) { *v_total_nominal = div64_u64(div64_u64(((unsigned long long)( @@ -461,7 +461,7 @@ static void calc_v_total_from_duration(struct dc_stream *stream, } static void calc_v_total_for_static_ramp(struct core_freesync *core_freesync, - struct dc_stream *stream, + struct dc_stream_state *stream, unsigned int index, int *v_total) { unsigned int frame_duration = 0; @@ -557,7 +557,7 @@ static void reset_freesync_state_variables(struct freesync_state* state) * Sets freesync mode on a stream depending on current freesync state. */ static bool set_freesync_on_streams(struct core_freesync *core_freesync, - struct dc_stream **streams, int num_streams) + struct dc_stream_state **streams, int num_streams) { int v_total_nominal = 0, v_total_min = 0, v_total_max = 0; unsigned int stream_idx, map_index = 0; @@ -729,7 +729,7 @@ static void set_static_ramp_variables(struct core_freesync *core_freesync, } void mod_freesync_handle_v_update(struct mod_freesync *mod_freesync, - struct dc_stream **streams, int num_streams) + struct dc_stream_state **streams, int num_streams) { unsigned int index, v_total, inserted_frame_v_total = 0; unsigned int min_frame_duration_in_ns, vmax, vmin = 0; @@ -839,7 +839,7 @@ void mod_freesync_handle_v_update(struct mod_freesync *mod_freesync, } void mod_freesync_update_state(struct mod_freesync *mod_freesync, - struct dc_stream **streams, int num_streams, + struct dc_stream_state **streams, int num_streams, struct mod_freesync_params *freesync_params) { bool freesync_program_required = false; @@ -929,7 +929,7 @@ void mod_freesync_update_state(struct mod_freesync *mod_freesync, bool mod_freesync_get_state(struct mod_freesync *mod_freesync, - struct dc_stream *stream, + struct dc_stream_state *stream, struct mod_freesync_params *freesync_params) { unsigned int index = 0; @@ -965,7 +965,7 @@ bool mod_freesync_get_state(struct mod_freesync *mod_freesync, } bool mod_freesync_set_user_enable(struct mod_freesync *mod_freesync, - struct dc_stream **streams, int num_streams, + struct dc_stream_state **streams, int num_streams, struct mod_freesync_user_enable *user_enable) { unsigned int stream_index, map_index; @@ -1017,7 +1017,7 @@ bool mod_freesync_set_user_enable(struct mod_freesync *mod_freesync, } bool mod_freesync_get_user_enable(struct mod_freesync *mod_freesync, - struct dc_stream *stream, + struct dc_stream_state *stream, struct mod_freesync_user_enable *user_enable) { unsigned int index = 0; @@ -1035,7 +1035,7 @@ bool mod_freesync_get_user_enable(struct mod_freesync *mod_freesync, } bool mod_freesync_get_static_ramp_active(struct mod_freesync *mod_freesync, - struct dc_stream *stream, + struct dc_stream_state *stream, bool *is_ramp_active) { unsigned int index = 0; @@ -1054,7 +1054,7 @@ bool mod_freesync_get_static_ramp_active(struct mod_freesync *mod_freesync, } bool mod_freesync_override_min_max(struct mod_freesync *mod_freesync, - struct dc_stream *streams, + struct dc_stream_state *streams, unsigned int min_refresh, unsigned int max_refresh, struct mod_freesync_caps *caps) @@ -1107,7 +1107,7 @@ bool mod_freesync_override_min_max(struct mod_freesync *mod_freesync, } bool mod_freesync_get_min_max(struct mod_freesync *mod_freesync, - struct dc_stream *stream, + struct dc_stream_state *stream, unsigned int *min_refresh, unsigned int *max_refresh) { @@ -1129,7 +1129,7 @@ bool mod_freesync_get_min_max(struct mod_freesync *mod_freesync, } bool mod_freesync_get_vmin_vmax(struct mod_freesync *mod_freesync, - struct dc_stream *stream, + struct dc_stream_state *stream, unsigned int *vmin, unsigned int *vmax) { @@ -1151,7 +1151,7 @@ bool mod_freesync_get_vmin_vmax(struct mod_freesync *mod_freesync, } bool mod_freesync_get_v_position(struct mod_freesync *mod_freesync, - struct dc_stream *stream, + struct dc_stream_state *stream, unsigned int *nom_v_pos, unsigned int *v_pos) { @@ -1179,7 +1179,7 @@ bool mod_freesync_get_v_position(struct mod_freesync *mod_freesync, } void mod_freesync_notify_mode_change(struct mod_freesync *mod_freesync, - struct dc_stream **streams, int num_streams) + struct dc_stream_state **streams, int num_streams) { unsigned int stream_index, map_index; struct freesync_state *state; @@ -1239,7 +1239,7 @@ void mod_freesync_notify_mode_change(struct mod_freesync *mod_freesync, * is required, depending on the times calculated */ static void update_timestamps(struct core_freesync *core_freesync, - const struct dc_stream *stream, unsigned int map_index, + const struct dc_stream_state *stream, unsigned int map_index, unsigned int last_render_time_in_us) { struct freesync_state *state = &core_freesync->map[map_index].state; @@ -1304,7 +1304,7 @@ static void update_timestamps(struct core_freesync *core_freesync, } static void apply_below_the_range(struct core_freesync *core_freesync, - struct dc_stream *stream, unsigned int map_index, + struct dc_stream_state *stream, unsigned int map_index, unsigned int last_render_time_in_us) { unsigned int inserted_frame_duration_in_us = 0; @@ -1403,7 +1403,7 @@ static void apply_below_the_range(struct core_freesync *core_freesync, } static void apply_fixed_refresh(struct core_freesync *core_freesync, - struct dc_stream *stream, unsigned int map_index) + struct dc_stream_state *stream, unsigned int map_index) { unsigned int vmin = 0, vmax = 0; struct freesync_state *state = &core_freesync->map[map_index].state; @@ -1434,7 +1434,7 @@ static void apply_fixed_refresh(struct core_freesync *core_freesync, } void mod_freesync_pre_update_plane_addresses(struct mod_freesync *mod_freesync, - struct dc_stream **streams, int num_streams, + struct dc_stream_state **streams, int num_streams, unsigned int curr_time_stamp_in_us) { unsigned int stream_index, map_index, last_render_time_in_us = 0; diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h b/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h index 2b9d45100bdd..84b53425f2c8 100644 --- a/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h +++ b/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h @@ -101,67 +101,67 @@ struct mod_freesync_params { * Add stream to be tracked by module */ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, - struct dc_stream *stream, struct mod_freesync_caps *caps); + struct dc_stream_state *stream, struct mod_freesync_caps *caps); /* * Remove stream to be tracked by module */ bool mod_freesync_remove_stream(struct mod_freesync *mod_freesync, - struct dc_stream *stream); + struct dc_stream_state *stream); /* * Update the freesync state flags for each display and program * freesync accordingly */ void mod_freesync_update_state(struct mod_freesync *mod_freesync, - struct dc_stream **streams, int num_streams, + struct dc_stream_state **streams, int num_streams, struct mod_freesync_params *freesync_params); bool mod_freesync_get_state(struct mod_freesync *mod_freesync, - struct dc_stream *stream, + struct dc_stream_state *stream, struct mod_freesync_params *freesync_params); bool mod_freesync_set_user_enable(struct mod_freesync *mod_freesync, - struct dc_stream **streams, int num_streams, + struct dc_stream_state **streams, int num_streams, struct mod_freesync_user_enable *user_enable); bool mod_freesync_get_user_enable(struct mod_freesync *mod_freesync, - struct dc_stream *stream, + struct dc_stream_state *stream, struct mod_freesync_user_enable *user_enable); bool mod_freesync_get_static_ramp_active(struct mod_freesync *mod_freesync, - struct dc_stream *stream, + struct dc_stream_state *stream, bool *is_ramp_active); bool mod_freesync_override_min_max(struct mod_freesync *mod_freesync, - struct dc_stream *streams, + struct dc_stream_state *streams, unsigned int min_refresh, unsigned int max_refresh, struct mod_freesync_caps *caps); bool mod_freesync_get_min_max(struct mod_freesync *mod_freesync, - struct dc_stream *stream, + struct dc_stream_state *stream, unsigned int *min_refresh, unsigned int *max_refresh); bool mod_freesync_get_vmin_vmax(struct mod_freesync *mod_freesync, - struct dc_stream *stream, + struct dc_stream_state *stream, unsigned int *vmin, unsigned int *vmax); bool mod_freesync_get_v_position(struct mod_freesync *mod_freesync, - struct dc_stream *stream, + struct dc_stream_state *stream, unsigned int *nom_v_pos, unsigned int *v_pos); void mod_freesync_handle_v_update(struct mod_freesync *mod_freesync, - struct dc_stream **streams, int num_streams); + struct dc_stream_state **streams, int num_streams); void mod_freesync_notify_mode_change(struct mod_freesync *mod_freesync, - struct dc_stream **streams, int num_streams); + struct dc_stream_state **streams, int num_streams); void mod_freesync_pre_update_plane_addresses(struct mod_freesync *mod_freesync, - struct dc_stream **streams, int num_streams, + struct dc_stream_state **streams, int num_streams, unsigned int curr_time_stamp); #endif -- cgit From 3be5262e353b8ab97c528bfc7d0dd3c820e4ba27 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 27 Jul 2017 09:55:38 -0400 Subject: drm/amd/display: Rename more dc_surface stuff to plane_state Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 288 +++++++++++---------- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 2 +- drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c | 20 +- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 52 ++-- drivers/gpu/drm/amd/display/dc/core/dc.c | 130 +++++----- drivers/gpu/drm/amd/display/dc/core/dc_debug.c | 188 +++++++------- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 190 +++++++------- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 8 +- drivers/gpu/drm/amd/display/dc/core/dc_surface.c | 74 +++--- drivers/gpu/drm/amd/display/dc/dc.h | 32 +-- drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c | 4 +- drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h | 2 +- .../drm/amd/display/dc/dce100/dce100_resource.c | 8 +- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 125 +++++---- .../drm/amd/display/dc/dce110/dce110_resource.c | 20 +- .../drm/amd/display/dc/dce112/dce112_resource.c | 8 +- .../drm/amd/display/dc/dce120/dce120_resource.c | 2 +- .../gpu/drm/amd/display/dc/dce80/dce80_resource.c | 8 +- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 140 +++++----- .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 4 +- drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 4 +- drivers/gpu/drm/amd/display/dc/inc/resource.h | 2 +- .../gpu/drm/amd/display/include/logger_interface.h | 2 +- 24 files changed, 658 insertions(+), 657 deletions(-) (limited to 'drivers/gpu') 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 497104a29d89..08567b3631cf 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -70,7 +70,7 @@ #include "i2caux_interface.h" -static enum drm_plane_type dm_surfaces_type_default[AMDGPU_MAX_PLANES] = { +static enum drm_plane_type dm_plane_type_default[AMDGPU_MAX_PLANES] = { DRM_PLANE_TYPE_PRIMARY, DRM_PLANE_TYPE_PRIMARY, DRM_PLANE_TYPE_PRIMARY, @@ -79,14 +79,14 @@ static enum drm_plane_type dm_surfaces_type_default[AMDGPU_MAX_PLANES] = { DRM_PLANE_TYPE_PRIMARY, }; -static enum drm_plane_type dm_surfaces_type_carizzo[AMDGPU_MAX_PLANES] = { +static enum drm_plane_type dm_plane_type_carizzo[AMDGPU_MAX_PLANES] = { DRM_PLANE_TYPE_PRIMARY, DRM_PLANE_TYPE_PRIMARY, DRM_PLANE_TYPE_PRIMARY, DRM_PLANE_TYPE_OVERLAY,/* YUV Capable Underlay */ }; -static enum drm_plane_type dm_surfaces_type_stoney[AMDGPU_MAX_PLANES] = { +static enum drm_plane_type dm_plane_type_stoney[AMDGPU_MAX_PLANES] = { DRM_PLANE_TYPE_PRIMARY, DRM_PLANE_TYPE_PRIMARY, DRM_PLANE_TYPE_OVERLAY, /* YUV Capable Underlay */ @@ -1285,11 +1285,11 @@ int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) return -1; } - for (i = 0; i < dm->dc->caps.max_surfaces; i++) { + for (i = 0; i < dm->dc->caps.max_planes; i++) { mode_info->planes[i] = kzalloc(sizeof(struct amdgpu_plane), GFP_KERNEL); if (!mode_info->planes[i]) { - DRM_ERROR("KMS: Failed to allocate surface\n"); + DRM_ERROR("KMS: Failed to allocate plane\n"); goto fail_free_planes; } mode_info->planes[i]->base.type = mode_info->plane_type[i]; @@ -1389,7 +1389,7 @@ fail_free_encoder: fail_free_connector: kfree(aconnector); fail_free_planes: - for (i = 0; i < dm->dc->caps.max_surfaces; i++) + for (i = 0; i < dm->dc->caps.max_planes; i++) kfree(mode_info->planes[i]); return -1; } @@ -1518,52 +1518,52 @@ static int dm_early_init(void *handle) adev->mode_info.num_crtc = 6; adev->mode_info.num_hpd = 6; adev->mode_info.num_dig = 6; - adev->mode_info.plane_type = dm_surfaces_type_default; + adev->mode_info.plane_type = dm_plane_type_default; break; case CHIP_FIJI: case CHIP_TONGA: adev->mode_info.num_crtc = 6; adev->mode_info.num_hpd = 6; adev->mode_info.num_dig = 7; - adev->mode_info.plane_type = dm_surfaces_type_default; + adev->mode_info.plane_type = dm_plane_type_default; break; case CHIP_CARRIZO: adev->mode_info.num_crtc = 3; adev->mode_info.num_hpd = 6; adev->mode_info.num_dig = 9; - adev->mode_info.plane_type = dm_surfaces_type_carizzo; + adev->mode_info.plane_type = dm_plane_type_carizzo; break; case CHIP_STONEY: adev->mode_info.num_crtc = 2; adev->mode_info.num_hpd = 6; adev->mode_info.num_dig = 9; - adev->mode_info.plane_type = dm_surfaces_type_stoney; + adev->mode_info.plane_type = dm_plane_type_stoney; break; case CHIP_POLARIS11: case CHIP_POLARIS12: adev->mode_info.num_crtc = 5; adev->mode_info.num_hpd = 5; adev->mode_info.num_dig = 5; - adev->mode_info.plane_type = dm_surfaces_type_default; + adev->mode_info.plane_type = dm_plane_type_default; break; case CHIP_POLARIS10: adev->mode_info.num_crtc = 6; adev->mode_info.num_hpd = 6; adev->mode_info.num_dig = 6; - adev->mode_info.plane_type = dm_surfaces_type_default; + adev->mode_info.plane_type = dm_plane_type_default; break; case CHIP_VEGA10: adev->mode_info.num_crtc = 6; adev->mode_info.num_hpd = 6; adev->mode_info.num_dig = 6; - adev->mode_info.plane_type = dm_surfaces_type_default; + adev->mode_info.plane_type = dm_plane_type_default; break; #if defined(CONFIG_DRM_AMD_DC_DCN1_0) case CHIP_RAVEN: adev->mode_info.num_crtc = 4; adev->mode_info.num_hpd = 4; adev->mode_info.num_dig = 4; - adev->mode_info.plane_type = dm_surfaces_type_default; + adev->mode_info.plane_type = dm_plane_type_default; break; #endif default: @@ -1821,50 +1821,50 @@ static int dm_crtc_cursor_move(struct drm_crtc *crtc, static bool fill_rects_from_plane_state( const struct drm_plane_state *state, - struct dc_plane_state *surface) + struct dc_plane_state *plane_state) { - surface->src_rect.x = state->src_x >> 16; - surface->src_rect.y = state->src_y >> 16; + plane_state->src_rect.x = state->src_x >> 16; + plane_state->src_rect.y = state->src_y >> 16; /*we ignore for now mantissa and do not to deal with floating pixels :(*/ - surface->src_rect.width = state->src_w >> 16; + plane_state->src_rect.width = state->src_w >> 16; - if (surface->src_rect.width == 0) + if (plane_state->src_rect.width == 0) return false; - surface->src_rect.height = state->src_h >> 16; - if (surface->src_rect.height == 0) + plane_state->src_rect.height = state->src_h >> 16; + if (plane_state->src_rect.height == 0) return false; - surface->dst_rect.x = state->crtc_x; - surface->dst_rect.y = state->crtc_y; + plane_state->dst_rect.x = state->crtc_x; + plane_state->dst_rect.y = state->crtc_y; if (state->crtc_w == 0) return false; - surface->dst_rect.width = state->crtc_w; + plane_state->dst_rect.width = state->crtc_w; if (state->crtc_h == 0) return false; - surface->dst_rect.height = state->crtc_h; + plane_state->dst_rect.height = state->crtc_h; - surface->clip_rect = surface->dst_rect; + plane_state->clip_rect = plane_state->dst_rect; switch (state->rotation & DRM_MODE_ROTATE_MASK) { case DRM_MODE_ROTATE_0: - surface->rotation = ROTATION_ANGLE_0; + plane_state->rotation = ROTATION_ANGLE_0; break; case DRM_MODE_ROTATE_90: - surface->rotation = ROTATION_ANGLE_90; + plane_state->rotation = ROTATION_ANGLE_90; break; case DRM_MODE_ROTATE_180: - surface->rotation = ROTATION_ANGLE_180; + plane_state->rotation = ROTATION_ANGLE_180; break; case DRM_MODE_ROTATE_270: - surface->rotation = ROTATION_ANGLE_270; + plane_state->rotation = ROTATION_ANGLE_270; break; default: - surface->rotation = ROTATION_ANGLE_0; + plane_state->rotation = ROTATION_ANGLE_0; break; } @@ -1896,7 +1896,7 @@ static int get_fb_info( static int fill_plane_attributes_from_fb( struct amdgpu_device *adev, - struct dc_plane_state *surface, + struct dc_plane_state *plane_state, const struct amdgpu_framebuffer *amdgpu_fb, bool addReq) { uint64_t tiling_flags; @@ -1916,28 +1916,28 @@ static int fill_plane_attributes_from_fb( switch (fb->format->format) { case DRM_FORMAT_C8: - surface->format = SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS; + plane_state->format = SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS; break; case DRM_FORMAT_RGB565: - surface->format = SURFACE_PIXEL_FORMAT_GRPH_RGB565; + plane_state->format = SURFACE_PIXEL_FORMAT_GRPH_RGB565; break; case DRM_FORMAT_XRGB8888: case DRM_FORMAT_ARGB8888: - surface->format = SURFACE_PIXEL_FORMAT_GRPH_ARGB8888; + plane_state->format = SURFACE_PIXEL_FORMAT_GRPH_ARGB8888; break; case DRM_FORMAT_XRGB2101010: case DRM_FORMAT_ARGB2101010: - surface->format = SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010; + plane_state->format = SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010; break; case DRM_FORMAT_XBGR2101010: case DRM_FORMAT_ABGR2101010: - surface->format = SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010; + plane_state->format = SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010; break; case DRM_FORMAT_NV21: - surface->format = SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr; + plane_state->format = SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr; break; case DRM_FORMAT_NV12: - surface->format = SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb; + plane_state->format = SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb; break; default: DRM_ERROR("Unsupported screen format %s\n", @@ -1945,45 +1945,45 @@ static int fill_plane_attributes_from_fb( return -EINVAL; } - if (surface->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) { - surface->address.type = PLN_ADDR_TYPE_GRAPHICS; - surface->address.grph.addr.low_part = lower_32_bits(fb_location); - surface->address.grph.addr.high_part = upper_32_bits(fb_location); - surface->plane_size.grph.surface_size.x = 0; - surface->plane_size.grph.surface_size.y = 0; - surface->plane_size.grph.surface_size.width = fb->width; - surface->plane_size.grph.surface_size.height = fb->height; - surface->plane_size.grph.surface_pitch = + if (plane_state->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) { + plane_state->address.type = PLN_ADDR_TYPE_GRAPHICS; + plane_state->address.grph.addr.low_part = lower_32_bits(fb_location); + plane_state->address.grph.addr.high_part = upper_32_bits(fb_location); + plane_state->plane_size.grph.surface_size.x = 0; + plane_state->plane_size.grph.surface_size.y = 0; + plane_state->plane_size.grph.surface_size.width = fb->width; + plane_state->plane_size.grph.surface_size.height = fb->height; + plane_state->plane_size.grph.surface_pitch = fb->pitches[0] / fb->format->cpp[0]; /* TODO: unhardcode */ - surface->color_space = COLOR_SPACE_SRGB; + plane_state->color_space = COLOR_SPACE_SRGB; } else { awidth = ALIGN(fb->width, 64); - surface->address.type = PLN_ADDR_TYPE_VIDEO_PROGRESSIVE; - surface->address.video_progressive.luma_addr.low_part + plane_state->address.type = PLN_ADDR_TYPE_VIDEO_PROGRESSIVE; + plane_state->address.video_progressive.luma_addr.low_part = lower_32_bits(fb_location); - surface->address.video_progressive.chroma_addr.low_part + plane_state->address.video_progressive.chroma_addr.low_part = lower_32_bits(fb_location) + (awidth * fb->height); - surface->plane_size.video.luma_size.x = 0; - surface->plane_size.video.luma_size.y = 0; - surface->plane_size.video.luma_size.width = awidth; - surface->plane_size.video.luma_size.height = fb->height; + plane_state->plane_size.video.luma_size.x = 0; + plane_state->plane_size.video.luma_size.y = 0; + plane_state->plane_size.video.luma_size.width = awidth; + plane_state->plane_size.video.luma_size.height = fb->height; /* TODO: unhardcode */ - surface->plane_size.video.luma_pitch = awidth; + plane_state->plane_size.video.luma_pitch = awidth; - surface->plane_size.video.chroma_size.x = 0; - surface->plane_size.video.chroma_size.y = 0; - surface->plane_size.video.chroma_size.width = awidth; - surface->plane_size.video.chroma_size.height = fb->height; - surface->plane_size.video.chroma_pitch = awidth / 2; + plane_state->plane_size.video.chroma_size.x = 0; + plane_state->plane_size.video.chroma_size.y = 0; + plane_state->plane_size.video.chroma_size.width = awidth; + plane_state->plane_size.video.chroma_size.height = fb->height; + plane_state->plane_size.video.chroma_pitch = awidth / 2; /* TODO: unhardcode */ - surface->color_space = COLOR_SPACE_YCBCR709; + plane_state->color_space = COLOR_SPACE_YCBCR709; } - memset(&surface->tiling_info, 0, sizeof(surface->tiling_info)); + memset(&plane_state->tiling_info, 0, sizeof(plane_state->tiling_info)); /* Fill GFX8 params */ if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE) == DC_ARRAY_2D_TILED_THIN1) { @@ -1996,51 +1996,51 @@ static int fill_plane_attributes_from_fb( num_banks = AMDGPU_TILING_GET(tiling_flags, NUM_BANKS); /* XXX fix me for VI */ - surface->tiling_info.gfx8.num_banks = num_banks; - surface->tiling_info.gfx8.array_mode = + plane_state->tiling_info.gfx8.num_banks = num_banks; + plane_state->tiling_info.gfx8.array_mode = DC_ARRAY_2D_TILED_THIN1; - surface->tiling_info.gfx8.tile_split = tile_split; - surface->tiling_info.gfx8.bank_width = bankw; - surface->tiling_info.gfx8.bank_height = bankh; - surface->tiling_info.gfx8.tile_aspect = mtaspect; - surface->tiling_info.gfx8.tile_mode = + plane_state->tiling_info.gfx8.tile_split = tile_split; + plane_state->tiling_info.gfx8.bank_width = bankw; + plane_state->tiling_info.gfx8.bank_height = bankh; + plane_state->tiling_info.gfx8.tile_aspect = mtaspect; + plane_state->tiling_info.gfx8.tile_mode = DC_ADDR_SURF_MICRO_TILING_DISPLAY; } else if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE) == DC_ARRAY_1D_TILED_THIN1) { - surface->tiling_info.gfx8.array_mode = DC_ARRAY_1D_TILED_THIN1; + plane_state->tiling_info.gfx8.array_mode = DC_ARRAY_1D_TILED_THIN1; } - surface->tiling_info.gfx8.pipe_config = + plane_state->tiling_info.gfx8.pipe_config = AMDGPU_TILING_GET(tiling_flags, PIPE_CONFIG); if (adev->asic_type == CHIP_VEGA10 || adev->asic_type == CHIP_RAVEN) { /* Fill GFX9 params */ - surface->tiling_info.gfx9.num_pipes = + plane_state->tiling_info.gfx9.num_pipes = adev->gfx.config.gb_addr_config_fields.num_pipes; - surface->tiling_info.gfx9.num_banks = + plane_state->tiling_info.gfx9.num_banks = adev->gfx.config.gb_addr_config_fields.num_banks; - surface->tiling_info.gfx9.pipe_interleave = + plane_state->tiling_info.gfx9.pipe_interleave = adev->gfx.config.gb_addr_config_fields.pipe_interleave_size; - surface->tiling_info.gfx9.num_shader_engines = + plane_state->tiling_info.gfx9.num_shader_engines = adev->gfx.config.gb_addr_config_fields.num_se; - surface->tiling_info.gfx9.max_compressed_frags = + plane_state->tiling_info.gfx9.max_compressed_frags = adev->gfx.config.gb_addr_config_fields.max_compress_frags; - surface->tiling_info.gfx9.num_rb_per_se = + plane_state->tiling_info.gfx9.num_rb_per_se = adev->gfx.config.gb_addr_config_fields.num_rb_per_se; - surface->tiling_info.gfx9.swizzle = + plane_state->tiling_info.gfx9.swizzle = AMDGPU_TILING_GET(tiling_flags, SWIZZLE_MODE); - surface->tiling_info.gfx9.shaderEnable = 1; + plane_state->tiling_info.gfx9.shaderEnable = 1; } - surface->visible = true; - surface->scaling_quality.h_taps_c = 0; - surface->scaling_quality.v_taps_c = 0; + plane_state->visible = true; + plane_state->scaling_quality.h_taps_c = 0; + plane_state->scaling_quality.v_taps_c = 0; - /* is this needed? is surface zeroed at allocation? */ - surface->scaling_quality.h_taps = 0; - surface->scaling_quality.v_taps = 0; - surface->stereo_format = PLANE_STEREO_FORMAT_NONE; + /* is this needed? is plane_state zeroed at allocation? */ + plane_state->scaling_quality.h_taps = 0; + plane_state->scaling_quality.v_taps = 0; + plane_state->stereo_format = PLANE_STEREO_FORMAT_NONE; return ret; @@ -2050,7 +2050,7 @@ static int fill_plane_attributes_from_fb( static void fill_gamma_from_crtc_state( const struct drm_crtc_state *crtc_state, - struct dc_plane_state *dc_surface) + struct dc_plane_state *plane_state) { int i; struct dc_gamma *gamma; @@ -2069,12 +2069,12 @@ static void fill_gamma_from_crtc_state( gamma->blue[i] = lut[i].blue; } - dc_surface->gamma_correction = gamma; + plane_state->gamma_correction = gamma; } static int fill_plane_attributes( struct amdgpu_device *adev, - struct dc_plane_state *surface, + struct dc_plane_state *dc_plane_state, struct drm_plane_state *plane_state, struct drm_crtc_state *crtc_state, bool addrReq) @@ -2085,12 +2085,12 @@ static int fill_plane_attributes( struct dc_transfer_func *input_tf; int ret = 0; - if (!fill_rects_from_plane_state(plane_state, surface)) + if (!fill_rects_from_plane_state(plane_state, dc_plane_state)) return -EINVAL; ret = fill_plane_attributes_from_fb( crtc->dev->dev_private, - surface, + dc_plane_state, amdgpu_fb, addrReq); @@ -2105,11 +2105,11 @@ static int fill_plane_attributes( input_tf->type = TF_TYPE_PREDEFINED; input_tf->tf = TRANSFER_FUNCTION_SRGB; - surface->in_transfer_func = input_tf; + dc_plane_state->in_transfer_func = input_tf; /* In case of gamma set, update gamma value */ if (crtc_state->gamma_lut) - fill_gamma_from_crtc_state(crtc_state, surface); + fill_gamma_from_crtc_state(crtc_state, dc_plane_state); return ret; } @@ -2991,9 +2991,9 @@ dm_drm_plane_duplicate_state(struct drm_plane *plane) __drm_atomic_helper_plane_duplicate_state(plane, &dm_plane_state->base); - if (old_dm_plane_state->surface) { - dm_plane_state->surface = old_dm_plane_state->surface; - dc_surface_retain(dm_plane_state->surface); + if (old_dm_plane_state->dc_state) { + dm_plane_state->dc_state = old_dm_plane_state->dc_state; + dc_plane_state_retain(dm_plane_state->dc_state); } return &dm_plane_state->base; @@ -3004,8 +3004,8 @@ void dm_drm_plane_destroy_state(struct drm_plane *plane, { struct dm_plane_state *dm_plane_state = to_dm_plane_state(state); - if (dm_plane_state->surface) - dc_surface_release(dm_plane_state->surface); + if (dm_plane_state->dc_state) + dc_plane_state_release(dm_plane_state->dc_state); __drm_atomic_helper_plane_destroy_state(state); kfree(dm_plane_state); @@ -3059,18 +3059,18 @@ static int dm_plane_helper_prepare_fb( amdgpu_bo_ref(rbo); - if (dm_plane_state_new->surface && - dm_plane_state_old->surface != dm_plane_state_new->surface) { - struct dc_plane_state *surface = dm_plane_state_new->surface; + if (dm_plane_state_new->dc_state && + dm_plane_state_old->dc_state != dm_plane_state_new->dc_state) { + struct dc_plane_state *plane_state = dm_plane_state_new->dc_state; - if (surface->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) { - surface->address.grph.addr.low_part = lower_32_bits(afb->address); - surface->address.grph.addr.high_part = upper_32_bits(afb->address); + if (plane_state->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) { + plane_state->address.grph.addr.low_part = lower_32_bits(afb->address); + plane_state->address.grph.addr.high_part = upper_32_bits(afb->address); } else { awidth = ALIGN(new_state->fb->width, 64); - surface->address.video_progressive.luma_addr.low_part + plane_state->address.video_progressive.luma_addr.low_part = lower_32_bits(afb->address); - surface->address.video_progressive.chroma_addr.low_part + plane_state->address.video_progressive.chroma_addr.low_part = lower_32_bits(afb->address) + (awidth * new_state->fb->height); } @@ -3159,10 +3159,10 @@ int dm_plane_atomic_check(struct drm_plane *plane, struct dc *dc = adev->dm.dc; struct dm_plane_state *dm_plane_state = to_dm_plane_state(state); - if (!dm_plane_state->surface) + if (!dm_plane_state->dc_state) return true; - if (dc_validate_plane(dc, dm_plane_state->surface)) + if (dc_validate_plane(dc, dm_plane_state->dc_state)) return 0; return -EINVAL; @@ -3848,6 +3848,7 @@ static void amdgpu_dm_do_flip( struct amdgpu_device *adev = crtc->dev->dev_private; bool async_flip = (acrtc->flip_flags & DRM_MODE_PAGE_FLIP_ASYNC) != 0; struct dc_flip_addrs addr = { {0} }; + /* TODO eliminate or rename surface_update */ struct dc_surface_update surface_updates[1] = { {0} }; struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state); @@ -3903,11 +3904,11 @@ static void amdgpu_dm_do_flip( if (acrtc->base.state->event) prepare_flip_isr(acrtc); - surface_updates->surface = dc_stream_get_status(acrtc_state->stream)->surfaces[0]; + surface_updates->surface = dc_stream_get_status(acrtc_state->stream)->plane_states[0]; surface_updates->flip_addr = &addr; - dc_update_surfaces_and_stream(adev->dm.dc, surface_updates, 1, acrtc_state->stream, NULL); + dc_update_planes_and_stream(adev->dm.dc, surface_updates, 1, acrtc_state->stream, NULL); DRM_DEBUG_DRIVER("%s Flipping to hi: 0x%x, low: 0x%x \n", __func__, @@ -3918,7 +3919,7 @@ static void amdgpu_dm_do_flip( spin_unlock_irqrestore(&crtc->dev->event_lock, flags); } -static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, +static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, struct drm_device *dev, struct amdgpu_display_manager *dm, struct drm_crtc *pcrtc, @@ -3928,7 +3929,7 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, struct drm_plane *plane; struct drm_plane_state *old_plane_state; struct dc_stream_state *dc_stream_attach; - struct dc_plane_state *dc_surfaces_constructed[MAX_SURFACES]; + struct dc_plane_state *plane_states_constructed[MAX_SURFACES]; struct amdgpu_crtc *acrtc_attach = to_amdgpu_crtc(pcrtc); struct dm_crtc_state *acrtc_state = to_dm_crtc_state(pcrtc->state); int planes_count = 0; @@ -3956,8 +3957,9 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, spin_lock_irqsave(&crtc->dev->event_lock, flags); if (acrtc_attach->pflip_status != AMDGPU_FLIP_NONE) { - DRM_ERROR("add_surface: acrtc %d, already busy\n", - acrtc_attach->crtc_id); + DRM_ERROR("%s: acrtc %d, already busy\n", + __func__, + acrtc_attach->crtc_id); spin_unlock_irqrestore(&crtc->dev->event_lock, flags); /* In commit tail framework this cannot happen */ WARN_ON(1); @@ -3965,9 +3967,9 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, spin_unlock_irqrestore(&crtc->dev->event_lock, flags); if (!pflip_needed) { - WARN_ON(!dm_plane_state->surface); + WARN_ON(!dm_plane_state->dc_state); - dc_surfaces_constructed[planes_count] = dm_plane_state->surface; + plane_states_constructed[planes_count] = dm_plane_state->dc_state; dc_stream_attach = acrtc_state->stream; planes_count++; @@ -4010,11 +4012,11 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, spin_unlock_irqrestore(&pcrtc->dev->event_lock, flags); } - if (false == dc_commit_surfaces_to_stream(dm->dc, - dc_surfaces_constructed, - planes_count, - dc_stream_attach)) - dm_error("%s: Failed to attach surface!\n", __func__); + if (false == dc_commit_planes_to_stream(dm->dc, + plane_states_constructed, + planes_count, + dc_stream_attach)) + dm_error("%s: Failed to attach plane!\n", __func__); } else { /*TODO BUG Here should go disable planes on CRTC. */ } @@ -4226,16 +4228,16 @@ void amdgpu_dm_atomic_commit_tail( status = dc_stream_get_status(new_acrtc_state->stream); WARN_ON(!status); - WARN_ON(!status->surface_count); + WARN_ON(!status->plane_count); if (!new_acrtc_state->stream) continue; /*TODO How it works with MPO ?*/ - if (!dc_commit_surfaces_to_stream( + if (!dc_commit_planes_to_stream( dm->dc, - status->surfaces, - status->surface_count, + status->plane_states, + status->plane_count, new_acrtc_state->stream)) dm_error("%s: Failed to update stream scaling!\n", __func__); } @@ -4260,7 +4262,7 @@ void amdgpu_dm_atomic_commit_tail( new_acrtc_state = to_dm_crtc_state(pcrtc->state); if (new_acrtc_state->stream) - amdgpu_dm_commit_surfaces(state, dev, dm, pcrtc, &wait_for_vblank); + amdgpu_dm_commit_planes(state, dev, dm, pcrtc, &wait_for_vblank); } @@ -4375,27 +4377,27 @@ void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector dm_force_atomic_commit(&aconnector->base); } -static uint32_t add_val_sets_surface( +static uint32_t add_val_sets_plane( struct dc_validation_set *val_sets, uint32_t set_count, const struct dc_stream_state *stream, - struct dc_plane_state *surface) + struct dc_plane_state *plane_state) { uint32_t i = 0, j = 0; while (i < set_count) { if (val_sets[i].stream == stream) { - while (val_sets[i].surfaces[j]) + while (val_sets[i].plane_states[j]) j++; break; } ++i; } - val_sets[i].surfaces[j] = surface; - val_sets[i].surface_count++; + val_sets[i].plane_states[j] = plane_state; + val_sets[i].plane_count++; - return val_sets[i].surface_count; + return val_sets[i].plane_count; } static uint32_t update_in_val_sets_stream( @@ -4516,7 +4518,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, /* * This bool will be set for true for any modeset/reset - * or surface update which implies non fast surface update. + * or plane update which implies non fast surface update. */ bool lock_and_validation_needed = false; @@ -4701,13 +4703,13 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, pflip_needed = !state->allow_modeset; if (!pflip_needed) { - struct dc_plane_state *surface; + struct dc_plane_state *dc_plane_state; - surface = dc_create_surface(dc); + dc_plane_state = dc_create_plane_state(dc); ret = fill_plane_attributes( plane_crtc->dev->dev_private, - surface, + dc_plane_state, plane_state, crtc_state, false); @@ -4715,15 +4717,15 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, goto fail; - if (dm_plane_state->surface) - dc_surface_release(dm_plane_state->surface); + if (dm_plane_state->dc_state) + dc_plane_state_release(dm_plane_state->dc_state); - dm_plane_state->surface = surface; + dm_plane_state->dc_state = dc_plane_state; - add_val_sets_surface(set, + add_val_sets_plane(set, set_count, new_acrtc_state->stream, - surface); + dc_plane_state); lock_and_validation_needed = true; } 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 cca65a37b213..e0a5632f00a3 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -196,7 +196,7 @@ struct dc_stream; struct dm_plane_state { struct drm_plane_state base; - struct dc_plane_state *surface; + struct dc_plane_state *dc_state; }; struct dm_crtc_state { diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c index 9a850227eeeb..28dbd18b2d86 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c @@ -2594,15 +2594,15 @@ static void populate_initial_data( if (!pipe[i].stream || !pipe[i].bottom_pipe) continue; - ASSERT(pipe[i].surface); + ASSERT(pipe[i].plane_state); if (num_displays == 0) { - if (!pipe[i].surface->visible) + if (!pipe[i].plane_state->visible) data->d0_underlay_mode = bw_def_underlay_only; else data->d0_underlay_mode = bw_def_blend; } else { - if (!pipe[i].surface->visible) + if (!pipe[i].plane_state->visible) data->d1_underlay_mode = bw_def_underlay_only; else data->d1_underlay_mode = bw_def_blend; @@ -2620,7 +2620,7 @@ static void populate_initial_data( data->v_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.taps.v_taps); data->h_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].scl_data.ratios.horz.value); data->v_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].scl_data.ratios.vert.value); - switch (pipe[i].surface->rotation) { + switch (pipe[i].plane_state->rotation) { case ROTATION_ANGLE_0: data->rotation_angle[num_displays + 4] = bw_int_to_fixed(0); break; @@ -2636,7 +2636,7 @@ static void populate_initial_data( default: break; } - switch (pipe[i].surface->format) { + switch (pipe[i].plane_state->format) { case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: case SURFACE_PIXEL_FORMAT_GRPH_RGB565: @@ -2670,14 +2670,14 @@ static void populate_initial_data( data->src_height[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->scl_data.viewport.height); data->src_width[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->scl_data.viewport.width); data->pitch_in_pixels[num_displays * 2 + j] = bw_int_to_fixed( - pipe[i].bottom_pipe->surface->plane_size.grph.surface_pitch); + pipe[i].bottom_pipe->plane_state->plane_size.grph.surface_pitch); data->h_taps[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->scl_data.taps.h_taps); data->v_taps[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->scl_data.taps.v_taps); data->h_scale_ratio[num_displays * 2 + j] = fixed31_32_to_bw_fixed( pipe[i].bottom_pipe->scl_data.ratios.horz.value); data->v_scale_ratio[num_displays * 2 + j] = fixed31_32_to_bw_fixed( pipe[i].bottom_pipe->scl_data.ratios.vert.value); - switch (pipe[i].bottom_pipe->surface->rotation) { + switch (pipe[i].bottom_pipe->plane_state->rotation) { case ROTATION_ANGLE_0: data->rotation_angle[num_displays * 2 + j] = bw_int_to_fixed(0); break; @@ -2710,7 +2710,7 @@ static void populate_initial_data( data->h_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->timing.h_total); data->v_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->timing.v_total); data->pixel_rate[num_displays + 4] = bw_frc_to_fixed(pipe[i].stream->timing.pix_clk_khz, 1000); - if (pipe[i].surface) { + if (pipe[i].plane_state) { data->src_width[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.viewport.width); data->pitch_in_pixels[num_displays + 4] = data->src_width[num_displays + 4]; data->src_height[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.viewport.height); @@ -2718,7 +2718,7 @@ static void populate_initial_data( data->v_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.taps.v_taps); data->h_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].scl_data.ratios.horz.value); data->v_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].scl_data.ratios.vert.value); - switch (pipe[i].surface->rotation) { + switch (pipe[i].plane_state->rotation) { case ROTATION_ANGLE_0: data->rotation_angle[num_displays + 4] = bw_int_to_fixed(0); break; @@ -2734,7 +2734,7 @@ static void populate_initial_data( default: break; } - switch (pipe[i].surface->format) { + switch (pipe[i].plane_state->format) { case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 7f7cb8ff124d..404b39e7b44b 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -233,16 +233,16 @@ static void pipe_ctx_to_e2e_pipe_params ( struct _vcs_dpi_display_pipe_params_st *input) { input->src.is_hsplit = false; - if (pipe->top_pipe != NULL && pipe->top_pipe->surface == pipe->surface) + if (pipe->top_pipe != NULL && pipe->top_pipe->plane_state == pipe->plane_state) input->src.is_hsplit = true; - else if (pipe->bottom_pipe != NULL && pipe->bottom_pipe->surface == pipe->surface) + else if (pipe->bottom_pipe != NULL && pipe->bottom_pipe->plane_state == pipe->plane_state) input->src.is_hsplit = true; - input->src.dcc = pipe->surface->dcc.enable; + input->src.dcc = pipe->plane_state->dcc.enable; input->src.dcc_rate = 1; - input->src.meta_pitch = pipe->surface->dcc.grph.meta_pitch; + input->src.meta_pitch = pipe->plane_state->dcc.grph.meta_pitch; input->src.source_scan = dm_horz; - input->src.sw_mode = pipe->surface->tiling_info.gfx9.swizzle; + input->src.sw_mode = pipe->plane_state->tiling_info.gfx9.swizzle; input->src.viewport_width = pipe->scl_data.viewport.width; input->src.viewport_height = pipe->scl_data.viewport.height; @@ -251,7 +251,7 @@ static void pipe_ctx_to_e2e_pipe_params ( input->src.cur0_src_width = 128; /* TODO: Cursor calcs, not curently stored */ input->src.cur0_bpp = 32; - switch (pipe->surface->tiling_info.gfx9.swizzle) { + switch (pipe->plane_state->tiling_info.gfx9.swizzle) { /* for 4/8/16 high tiles */ case DC_SW_LINEAR: input->src.is_display_sw = 1; @@ -299,7 +299,7 @@ static void pipe_ctx_to_e2e_pipe_params ( break; } - switch (pipe->surface->rotation) { + switch (pipe->plane_state->rotation) { case ROTATION_ANGLE_0: case ROTATION_ANGLE_180: input->src.source_scan = dm_horz; @@ -314,7 +314,7 @@ static void pipe_ctx_to_e2e_pipe_params ( } /* TODO: Fix pixel format mappings */ - switch (pipe->surface->format) { + switch (pipe->plane_state->format) { case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: input->src.source_format = dm_420_8; @@ -455,7 +455,7 @@ static void dcn_bw_calc_rq_dlg_ttu( true, true, v->pte_enable == dcn_bw_yes, - pipe->surface->flip_immediate); + pipe->plane_state->flip_immediate); } static void dcn_dml_wm_override( @@ -478,7 +478,7 @@ static void dcn_dml_wm_override( for (i = 0, in_idx = 0; i < pool->pipe_count; i++) { struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; - if (!pipe->stream || !pipe->surface) + if (!pipe->stream || !pipe->plane_state) continue; input[in_idx].clks_cfg.dcfclk_mhz = v->dcfclk; @@ -516,7 +516,7 @@ static void dcn_dml_wm_override( for (i = 0, in_idx = 0; i < pool->pipe_count; i++) { struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; - if (!pipe->stream || !pipe->surface) + if (!pipe->stream || !pipe->plane_state) continue; dml_rq_dlg_get_dlg_reg(dml, @@ -527,7 +527,7 @@ static void dcn_dml_wm_override( true, true, v->pte_enable == dcn_bw_yes, - pipe->surface->flip_immediate); + pipe->plane_state->flip_immediate); in_idx++; } dm_free(input); @@ -541,7 +541,7 @@ static void split_stream_across_pipes( { int pipe_idx = secondary_pipe->pipe_idx; - if (!primary_pipe->surface) + if (!primary_pipe->plane_state) return; *secondary_pipe = *primary_pipe; @@ -843,7 +843,7 @@ bool dcn_validate_bandwidth( if (!pipe->stream) continue; /* skip all but first of split pipes */ - if (pipe->top_pipe && pipe->top_pipe->surface == pipe->surface) + if (pipe->top_pipe && pipe->top_pipe->plane_state == pipe->plane_state) continue; v->underscan_output[input_idx] = false; /* taken care of in recout already*/ @@ -869,7 +869,7 @@ bool dcn_validate_bandwidth( } } - if (!pipe->surface){ + if (!pipe->plane_state) { v->dcc_enable[input_idx] = dcn_bw_yes; v->source_pixel_format[input_idx] = dcn_bw_rgb_sub_32; v->source_surface_mode[input_idx] = dcn_bw_sw_4_kb_s; @@ -889,8 +889,8 @@ bool dcn_validate_bandwidth( v->viewport_width[input_idx] = pipe->scl_data.viewport.width; v->scaler_rec_out_width[input_idx] = pipe->scl_data.recout.width; v->scaler_recout_height[input_idx] = pipe->scl_data.recout.height; - if (pipe->bottom_pipe && pipe->bottom_pipe->surface == pipe->surface) { - if (pipe->surface->rotation % 2 == 0) { + if (pipe->bottom_pipe && pipe->bottom_pipe->plane_state == pipe->plane_state) { + if (pipe->plane_state->rotation % 2 == 0) { int viewport_end = pipe->scl_data.viewport.width + pipe->scl_data.viewport.x; int viewport_b_end = pipe->bottom_pipe->scl_data.viewport.width @@ -919,17 +919,17 @@ bool dcn_validate_bandwidth( + pipe->bottom_pipe->scl_data.recout.width; } - v->dcc_enable[input_idx] = pipe->surface->dcc.enable ? dcn_bw_yes : dcn_bw_no; + v->dcc_enable[input_idx] = pipe->plane_state->dcc.enable ? dcn_bw_yes : dcn_bw_no; v->source_pixel_format[input_idx] = tl_pixel_format_to_bw_defs( - pipe->surface->format); + pipe->plane_state->format); v->source_surface_mode[input_idx] = tl_sw_mode_to_bw_defs( - pipe->surface->tiling_info.gfx9.swizzle); + pipe->plane_state->tiling_info.gfx9.swizzle); v->lb_bit_per_pixel[input_idx] = tl_lb_bpp_to_int(pipe->scl_data.lb_params.depth); v->override_hta_ps[input_idx] = pipe->scl_data.taps.h_taps; v->override_vta_ps[input_idx] = pipe->scl_data.taps.v_taps; v->override_hta_pschroma[input_idx] = pipe->scl_data.taps.h_taps_c; v->override_vta_pschroma[input_idx] = pipe->scl_data.taps.v_taps_c; - v->source_scan[input_idx] = (pipe->surface->rotation % 2) ? dcn_bw_vert : dcn_bw_hor; + v->source_scan[input_idx] = (pipe->plane_state->rotation % 2) ? dcn_bw_vert : dcn_bw_hor; } if (v->is_line_buffer_bpp_fixed == dcn_bw_yes) v->lb_bit_per_pixel[input_idx] = v->line_buffer_fixed_bpp; @@ -996,7 +996,7 @@ bool dcn_validate_bandwidth( if (!pipe->stream) continue; /* skip all but first of split pipes */ - if (pipe->top_pipe && pipe->top_pipe->surface == pipe->surface) + if (pipe->top_pipe && pipe->top_pipe->plane_state == pipe->plane_state) continue; pipe->pipe_dlg_param.vupdate_width = v->v_update_width[input_idx]; @@ -1024,7 +1024,7 @@ bool dcn_validate_bandwidth( pipe->pipe_dlg_param.vblank_start = asic_blank_start; pipe->pipe_dlg_param.vblank_end = asic_blank_end; - if (pipe->surface) { + if (pipe->plane_state) { struct pipe_ctx *hsplit_pipe = pipe->bottom_pipe; if (v->dpp_per_plane[input_idx] == 2 || @@ -1036,7 +1036,7 @@ bool dcn_validate_bandwidth( TIMING_3D_FORMAT_TOP_AND_BOTTOM || pipe->stream->timing.timing_3d_format == TIMING_3D_FORMAT_SIDE_BY_SIDE))) { - if (hsplit_pipe && hsplit_pipe->surface == pipe->surface) { + if (hsplit_pipe && hsplit_pipe->plane_state == pipe->plane_state) { /* update previously split pipe */ hsplit_pipe->pipe_dlg_param.vupdate_width = v->v_update_width[input_idx]; hsplit_pipe->pipe_dlg_param.vupdate_offset = v->v_update_offset[input_idx]; @@ -1057,12 +1057,12 @@ bool dcn_validate_bandwidth( } dcn_bw_calc_rq_dlg_ttu(dc, v, hsplit_pipe); - } else if (hsplit_pipe && hsplit_pipe->surface == pipe->surface) { + } else if (hsplit_pipe && hsplit_pipe->plane_state == pipe->plane_state) { /* merge previously split pipe */ pipe->bottom_pipe = hsplit_pipe->bottom_pipe; if (hsplit_pipe->bottom_pipe) hsplit_pipe->bottom_pipe->top_pipe = pipe; - hsplit_pipe->surface = NULL; + hsplit_pipe->plane_state = NULL; hsplit_pipe->stream = NULL; hsplit_pipe->top_pipe = NULL; hsplit_pipe->bottom_pipe = NULL; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 8b6b7631d776..ffc9c05e2fb5 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -639,21 +639,21 @@ static bool is_validation_required( for (i = 0; i < set_count; i++) { - if (set[i].surface_count != context->stream_status[i].surface_count) + if (set[i].plane_count != context->stream_status[i].plane_count) return true; if (!dc_is_stream_unchanged(set[i].stream, context->streams[i])) return true; - for (j = 0; j < set[i].surface_count; j++) { - struct dc_plane_state temp_surf; - memset(&temp_surf, 0, sizeof(temp_surf)); + for (j = 0; j < set[i].plane_count; j++) { + struct dc_plane_state temp_plane; + memset(&temp_plane, 0, sizeof(temp_plane)); - temp_surf = *context->stream_status[i].surfaces[j]; - temp_surf.clip_rect = set[i].surfaces[j]->clip_rect; - temp_surf.dst_rect.x = set[i].surfaces[j]->dst_rect.x; - temp_surf.dst_rect.y = set[i].surfaces[j]->dst_rect.y; + temp_plane = *context->stream_status[i].plane_states[j]; + temp_plane.clip_rect = set[i].plane_states[j]->clip_rect; + temp_plane.dst_rect.x = set[i].plane_states[j]->dst_rect.x; + temp_plane.dst_rect.y = set[i].plane_states[j]->dst_rect.y; - if (memcmp(&temp_surf, set[i].surfaces[j], sizeof(temp_surf)) != 0) + if (memcmp(&temp_plane, set[i].plane_states[j], sizeof(temp_plane)) != 0) return true; } } @@ -683,8 +683,8 @@ static bool validate_surfaces( int i, j; for (i = 0; i < set_count; i++) - for (j = 0; j < set[i].surface_count; j++) - if (!dc_validate_plane(dc, set[i].surfaces[j])) + for (j = 0; j < set[i].plane_count; j++) + if (!dc_validate_plane(dc, set[i].plane_states[j])) return false; return true; @@ -977,11 +977,11 @@ static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *c for (i = 0; i < context->stream_count; i++) { const struct dc_sink *sink = context->streams[i]->sink; - for (j = 0; j < context->stream_status[i].surface_count; j++) { - const struct dc_plane_state *surface = - context->stream_status[i].surfaces[j]; + for (j = 0; j < context->stream_status[i].plane_count; j++) { + const struct dc_plane_state *plane_state = + context->stream_status[i].plane_states[j]; - core_dc->hwss.apply_ctx_for_surface(core_dc, surface, context); + core_dc->hwss.apply_ctx_for_surface(core_dc, plane_state, context); /* * enable stereo @@ -1073,9 +1073,9 @@ bool dc_commit_streams( set[i].stream = stream; if (status) { - set[i].surface_count = status->surface_count; - for (j = 0; j < status->surface_count; j++) - set[i].surfaces[j] = status->surfaces[j]; + set[i].plane_count = status->plane_count; + for (j = 0; j < status->plane_count; j++) + set[i].plane_states[j] = status->plane_states[j]; } } @@ -1122,7 +1122,7 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) for (i = 0; i < core_dc->res_pool->pipe_count; i++) if (context->res_ctx.pipe_ctx[i].stream == NULL - || context->res_ctx.pipe_ctx[i].surface == NULL) + || context->res_ctx.pipe_ctx[i].plane_state == NULL) core_dc->hwss.power_down_front_end(core_dc, i); /* 3rd param should be true, temp w/a for RV*/ @@ -1134,10 +1134,10 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) return true; } -bool dc_commit_surfaces_to_stream( +bool dc_commit_planes_to_stream( struct dc *dc, - struct dc_plane_state **new_surfaces, - uint8_t new_surface_count, + struct dc_plane_state **plane_states, + uint8_t new_plane_count, struct dc_stream_state *dc_stream) { struct dc_surface_update updates[MAX_SURFACES]; @@ -1162,37 +1162,37 @@ bool dc_commit_surfaces_to_stream( stream_update->dst = dc_stream->dst; stream_update->out_transfer_func = dc_stream->out_transfer_func; - for (i = 0; i < new_surface_count; i++) { - updates[i].surface = new_surfaces[i]; + for (i = 0; i < new_plane_count; i++) { + updates[i].surface = plane_states[i]; updates[i].gamma = - (struct dc_gamma *)new_surfaces[i]->gamma_correction; - updates[i].in_transfer_func = new_surfaces[i]->in_transfer_func; - flip_addr[i].address = new_surfaces[i]->address; - flip_addr[i].flip_immediate = new_surfaces[i]->flip_immediate; - plane_info[i].color_space = new_surfaces[i]->color_space; - plane_info[i].format = new_surfaces[i]->format; - plane_info[i].plane_size = new_surfaces[i]->plane_size; - plane_info[i].rotation = new_surfaces[i]->rotation; - plane_info[i].horizontal_mirror = new_surfaces[i]->horizontal_mirror; - plane_info[i].stereo_format = new_surfaces[i]->stereo_format; - plane_info[i].tiling_info = new_surfaces[i]->tiling_info; - plane_info[i].visible = new_surfaces[i]->visible; - plane_info[i].per_pixel_alpha = new_surfaces[i]->per_pixel_alpha; - plane_info[i].dcc = new_surfaces[i]->dcc; - scaling_info[i].scaling_quality = new_surfaces[i]->scaling_quality; - scaling_info[i].src_rect = new_surfaces[i]->src_rect; - scaling_info[i].dst_rect = new_surfaces[i]->dst_rect; - scaling_info[i].clip_rect = new_surfaces[i]->clip_rect; + (struct dc_gamma *)plane_states[i]->gamma_correction; + updates[i].in_transfer_func = plane_states[i]->in_transfer_func; + flip_addr[i].address = plane_states[i]->address; + flip_addr[i].flip_immediate = plane_states[i]->flip_immediate; + plane_info[i].color_space = plane_states[i]->color_space; + plane_info[i].format = plane_states[i]->format; + plane_info[i].plane_size = plane_states[i]->plane_size; + plane_info[i].rotation = plane_states[i]->rotation; + plane_info[i].horizontal_mirror = plane_states[i]->horizontal_mirror; + plane_info[i].stereo_format = plane_states[i]->stereo_format; + plane_info[i].tiling_info = plane_states[i]->tiling_info; + plane_info[i].visible = plane_states[i]->visible; + plane_info[i].per_pixel_alpha = plane_states[i]->per_pixel_alpha; + plane_info[i].dcc = plane_states[i]->dcc; + scaling_info[i].scaling_quality = plane_states[i]->scaling_quality; + scaling_info[i].src_rect = plane_states[i]->src_rect; + scaling_info[i].dst_rect = plane_states[i]->dst_rect; + scaling_info[i].clip_rect = plane_states[i]->clip_rect; updates[i].flip_addr = &flip_addr[i]; updates[i].plane_info = &plane_info[i]; updates[i].scaling_info = &scaling_info[i]; } - dc_update_surfaces_and_stream( + dc_update_planes_and_stream( dc, updates, - new_surface_count, + new_plane_count, dc_stream, stream_update); dc_post_update_surfaces_to_stream(dc); @@ -1220,14 +1220,14 @@ void dc_release_validate_context(struct validate_context *context) static bool is_surface_in_context( const struct validate_context *context, - const struct dc_plane_state *surface) + const struct dc_plane_state *plane_state) { int j; for (j = 0; j < MAX_PIPES; j++) { const struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - if (surface == pipe_ctx->surface) { + if (plane_state == pipe_ctx->plane_state) { return true; } } @@ -1371,7 +1371,7 @@ enum surface_update_type dc_check_update_surfaces_for_stream( int i; enum surface_update_type overall_type = UPDATE_TYPE_FAST; - if (stream_status == NULL || stream_status->surface_count != surface_count) + if (stream_status == NULL || stream_status->plane_count != surface_count) return UPDATE_TYPE_FULL; if (stream_update) @@ -1393,7 +1393,7 @@ enum surface_update_type dc_check_update_surfaces_for_stream( enum surface_update_type update_surface_trace_level = UPDATE_TYPE_FULL; -void dc_update_surfaces_and_stream(struct dc *dc, +void dc_update_planes_and_stream(struct dc *dc, struct dc_surface_update *srf_updates, int surface_count, struct dc_stream_state *stream, struct dc_stream_update *stream_update) @@ -1470,10 +1470,10 @@ void dc_update_surfaces_and_stream(struct dc *dc, update_surface_trace(dc, srf_updates, surface_count); if (update_type >= UPDATE_TYPE_FULL) { - struct dc_plane_state *new_surfaces[MAX_SURFACES] = {0}; + struct dc_plane_state *new_planes[MAX_SURFACES] = {0}; for (i = 0; i < surface_count; i++) - new_surfaces[i] = srf_updates[i].surface; + new_planes[i] = srf_updates[i].surface; /* initialize scratch memory for building context */ context = dm_alloc(sizeof(*context)); @@ -1487,7 +1487,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, /* add surface to context */ if (!resource_attach_surfaces_to_context( - new_surfaces, surface_count, stream, + new_planes, surface_count, stream, context, core_dc->res_pool)) { BREAK_TO_DEBUGGER(); goto fail; @@ -1542,7 +1542,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, for (j = 0; j < core_dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - if (pipe_ctx->surface != surface) + if (pipe_ctx->plane_state != surface) continue; resource_build_scaling_params(pipe_ctx); @@ -1599,14 +1599,14 @@ void dc_update_surfaces_and_stream(struct dc *dc, /* Lock pipes for provided surfaces, or all active if full update*/ for (i = 0; i < surface_count; i++) { - struct dc_plane_state *surface = srf_updates[i].surface; + struct dc_plane_state *plane_state = srf_updates[i].surface; for (j = 0; j < core_dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - if (update_type != UPDATE_TYPE_FULL && pipe_ctx->surface != surface) + if (update_type != UPDATE_TYPE_FULL && pipe_ctx->plane_state != plane_state) continue; - if (!pipe_ctx->surface || pipe_ctx->top_pipe) + if (!pipe_ctx->plane_state || pipe_ctx->top_pipe) continue; core_dc->hwss.pipe_control_lock( @@ -1622,15 +1622,15 @@ void dc_update_surfaces_and_stream(struct dc *dc, for (j = 0; j < core_dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; struct pipe_ctx *cur_pipe_ctx = &core_dc->current_context->res_ctx.pipe_ctx[j]; - bool is_new_pipe_surface = cur_pipe_ctx->surface != pipe_ctx->surface; + bool is_new_pipe_surface = cur_pipe_ctx->plane_state != pipe_ctx->plane_state; struct dc_cursor_position position = { 0 }; - if (update_type != UPDATE_TYPE_FULL || !pipe_ctx->surface) + if (update_type != UPDATE_TYPE_FULL || !pipe_ctx->plane_state) continue; if (!pipe_ctx->top_pipe) core_dc->hwss.apply_ctx_for_surface( - core_dc, pipe_ctx->surface, context); + core_dc, pipe_ctx->plane_state, context); /* TODO: this is a hack w/a for switching from mpo to pipe split */ dc_stream_set_cursor_position(pipe_ctx->stream, &position); @@ -1638,7 +1638,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, if (is_new_pipe_surface) { core_dc->hwss.update_plane_addr(core_dc, pipe_ctx); core_dc->hwss.set_input_transfer_func( - pipe_ctx, pipe_ctx->surface); + pipe_ctx, pipe_ctx->plane_state); core_dc->hwss.set_output_transfer_func( pipe_ctx, pipe_ctx->stream); } @@ -1649,16 +1649,16 @@ void dc_update_surfaces_and_stream(struct dc *dc, /* Perform requested Updates */ for (i = 0; i < surface_count; i++) { - struct dc_plane_state *surface = srf_updates[i].surface; + struct dc_plane_state *plane_state = srf_updates[i].surface; if (update_type == UPDATE_TYPE_MED) core_dc->hwss.apply_ctx_for_surface( - core_dc, surface, context); + core_dc, plane_state, context); for (j = 0; j < core_dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - if (pipe_ctx->surface != surface) + if (pipe_ctx->plane_state != plane_state) continue; if (srf_updates[i].flip_addr) @@ -1669,7 +1669,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, if (srf_updates[i].in_transfer_func) core_dc->hwss.set_input_transfer_func( - pipe_ctx, pipe_ctx->surface); + pipe_ctx, pipe_ctx->plane_state); if (stream_update != NULL && stream_update->out_transfer_func != NULL) { @@ -1690,9 +1690,9 @@ void dc_update_surfaces_and_stream(struct dc *dc, for (j = 0; j < surface_count; j++) { if (update_type != UPDATE_TYPE_FULL && - srf_updates[j].surface != pipe_ctx->surface) + srf_updates[j].surface != pipe_ctx->plane_state) continue; - if (!pipe_ctx->surface || pipe_ctx->top_pipe) + if (!pipe_ctx->plane_state || pipe_ctx->top_pipe) continue; core_dc->hwss.pipe_control_lock( diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c index e8d4b8c3ac2b..ca4f1db4a58a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c @@ -38,7 +38,7 @@ void pre_surface_trace( const struct dc *dc, - const struct dc_plane_state *const *surfaces, + const struct dc_plane_state *const *plane_states, int surface_count) { int i; @@ -46,111 +46,111 @@ void pre_surface_trace( struct dal_logger *logger = core_dc->ctx->logger; for (i = 0; i < surface_count; i++) { - const struct dc_plane_state *surface = surfaces[i]; + const struct dc_plane_state *plane_state = plane_states[i]; - SURFACE_TRACE("Surface %d:\n", i); + SURFACE_TRACE("Planes %d:\n", i); SURFACE_TRACE( - "surface->visible = %d;\n" - "surface->flip_immediate = %d;\n" - "surface->address.type = %d;\n" - "surface->address.grph.addr.quad_part = 0x%X;\n" - "surface->address.grph.meta_addr.quad_part = 0x%X;\n" - "surface->scaling_quality.h_taps = %d;\n" - "surface->scaling_quality.v_taps = %d;\n" - "surface->scaling_quality.h_taps_c = %d;\n" - "surface->scaling_quality.v_taps_c = %d;\n", - surface->visible, - surface->flip_immediate, - surface->address.type, - surface->address.grph.addr.quad_part, - surface->address.grph.meta_addr.quad_part, - surface->scaling_quality.h_taps, - surface->scaling_quality.v_taps, - surface->scaling_quality.h_taps_c, - surface->scaling_quality.v_taps_c); + "plane_state->visible = %d;\n" + "plane_state->flip_immediate = %d;\n" + "plane_state->address.type = %d;\n" + "plane_state->address.grph.addr.quad_part = 0x%X;\n" + "plane_state->address.grph.meta_addr.quad_part = 0x%X;\n" + "plane_state->scaling_quality.h_taps = %d;\n" + "plane_state->scaling_quality.v_taps = %d;\n" + "plane_state->scaling_quality.h_taps_c = %d;\n" + "plane_state->scaling_quality.v_taps_c = %d;\n", + plane_state->visible, + plane_state->flip_immediate, + plane_state->address.type, + plane_state->address.grph.addr.quad_part, + plane_state->address.grph.meta_addr.quad_part, + plane_state->scaling_quality.h_taps, + plane_state->scaling_quality.v_taps, + plane_state->scaling_quality.h_taps_c, + plane_state->scaling_quality.v_taps_c); SURFACE_TRACE( - "surface->src_rect.x = %d;\n" - "surface->src_rect.y = %d;\n" - "surface->src_rect.width = %d;\n" - "surface->src_rect.height = %d;\n" - "surface->dst_rect.x = %d;\n" - "surface->dst_rect.y = %d;\n" - "surface->dst_rect.width = %d;\n" - "surface->dst_rect.height = %d;\n" - "surface->clip_rect.x = %d;\n" - "surface->clip_rect.y = %d;\n" - "surface->clip_rect.width = %d;\n" - "surface->clip_rect.height = %d;\n", - surface->src_rect.x, - surface->src_rect.y, - surface->src_rect.width, - surface->src_rect.height, - surface->dst_rect.x, - surface->dst_rect.y, - surface->dst_rect.width, - surface->dst_rect.height, - surface->clip_rect.x, - surface->clip_rect.y, - surface->clip_rect.width, - surface->clip_rect.height); + "plane_state->src_rect.x = %d;\n" + "plane_state->src_rect.y = %d;\n" + "plane_state->src_rect.width = %d;\n" + "plane_state->src_rect.height = %d;\n" + "plane_state->dst_rect.x = %d;\n" + "plane_state->dst_rect.y = %d;\n" + "plane_state->dst_rect.width = %d;\n" + "plane_state->dst_rect.height = %d;\n" + "plane_state->clip_rect.x = %d;\n" + "plane_state->clip_rect.y = %d;\n" + "plane_state->clip_rect.width = %d;\n" + "plane_state->clip_rect.height = %d;\n", + plane_state->src_rect.x, + plane_state->src_rect.y, + plane_state->src_rect.width, + plane_state->src_rect.height, + plane_state->dst_rect.x, + plane_state->dst_rect.y, + plane_state->dst_rect.width, + plane_state->dst_rect.height, + plane_state->clip_rect.x, + plane_state->clip_rect.y, + plane_state->clip_rect.width, + plane_state->clip_rect.height); SURFACE_TRACE( - "surface->plane_size.grph.surface_size.x = %d;\n" - "surface->plane_size.grph.surface_size.y = %d;\n" - "surface->plane_size.grph.surface_size.width = %d;\n" - "surface->plane_size.grph.surface_size.height = %d;\n" - "surface->plane_size.grph.surface_pitch = %d;\n", - surface->plane_size.grph.surface_size.x, - surface->plane_size.grph.surface_size.y, - surface->plane_size.grph.surface_size.width, - surface->plane_size.grph.surface_size.height, - surface->plane_size.grph.surface_pitch); + "plane_state->plane_size.grph.surface_size.x = %d;\n" + "plane_state->plane_size.grph.surface_size.y = %d;\n" + "plane_state->plane_size.grph.surface_size.width = %d;\n" + "plane_state->plane_size.grph.surface_size.height = %d;\n" + "plane_state->plane_size.grph.surface_pitch = %d;\n", + plane_state->plane_size.grph.surface_size.x, + plane_state->plane_size.grph.surface_size.y, + plane_state->plane_size.grph.surface_size.width, + plane_state->plane_size.grph.surface_size.height, + plane_state->plane_size.grph.surface_pitch); SURFACE_TRACE( - "surface->tiling_info.gfx8.num_banks = %d;\n" - "surface->tiling_info.gfx8.bank_width = %d;\n" - "surface->tiling_info.gfx8.bank_width_c = %d;\n" - "surface->tiling_info.gfx8.bank_height = %d;\n" - "surface->tiling_info.gfx8.bank_height_c = %d;\n" - "surface->tiling_info.gfx8.tile_aspect = %d;\n" - "surface->tiling_info.gfx8.tile_aspect_c = %d;\n" - "surface->tiling_info.gfx8.tile_split = %d;\n" - "surface->tiling_info.gfx8.tile_split_c = %d;\n" - "surface->tiling_info.gfx8.tile_mode = %d;\n" - "surface->tiling_info.gfx8.tile_mode_c = %d;\n", - surface->tiling_info.gfx8.num_banks, - surface->tiling_info.gfx8.bank_width, - surface->tiling_info.gfx8.bank_width_c, - surface->tiling_info.gfx8.bank_height, - surface->tiling_info.gfx8.bank_height_c, - surface->tiling_info.gfx8.tile_aspect, - surface->tiling_info.gfx8.tile_aspect_c, - surface->tiling_info.gfx8.tile_split, - surface->tiling_info.gfx8.tile_split_c, - surface->tiling_info.gfx8.tile_mode, - surface->tiling_info.gfx8.tile_mode_c); + "plane_state->tiling_info.gfx8.num_banks = %d;\n" + "plane_state->tiling_info.gfx8.bank_width = %d;\n" + "plane_state->tiling_info.gfx8.bank_width_c = %d;\n" + "plane_state->tiling_info.gfx8.bank_height = %d;\n" + "plane_state->tiling_info.gfx8.bank_height_c = %d;\n" + "plane_state->tiling_info.gfx8.tile_aspect = %d;\n" + "plane_state->tiling_info.gfx8.tile_aspect_c = %d;\n" + "plane_state->tiling_info.gfx8.tile_split = %d;\n" + "plane_state->tiling_info.gfx8.tile_split_c = %d;\n" + "plane_state->tiling_info.gfx8.tile_mode = %d;\n" + "plane_state->tiling_info.gfx8.tile_mode_c = %d;\n", + plane_state->tiling_info.gfx8.num_banks, + plane_state->tiling_info.gfx8.bank_width, + plane_state->tiling_info.gfx8.bank_width_c, + plane_state->tiling_info.gfx8.bank_height, + plane_state->tiling_info.gfx8.bank_height_c, + plane_state->tiling_info.gfx8.tile_aspect, + plane_state->tiling_info.gfx8.tile_aspect_c, + plane_state->tiling_info.gfx8.tile_split, + plane_state->tiling_info.gfx8.tile_split_c, + plane_state->tiling_info.gfx8.tile_mode, + plane_state->tiling_info.gfx8.tile_mode_c); SURFACE_TRACE( - "surface->tiling_info.gfx8.pipe_config = %d;\n" - "surface->tiling_info.gfx8.array_mode = %d;\n" - "surface->color_space = %d;\n" - "surface->dcc.enable = %d;\n" - "surface->format = %d;\n" - "surface->rotation = %d;\n" - "surface->stereo_format = %d;\n", - surface->tiling_info.gfx8.pipe_config, - surface->tiling_info.gfx8.array_mode, - surface->color_space, - surface->dcc.enable, - surface->format, - surface->rotation, - surface->stereo_format); - - SURFACE_TRACE("surface->tiling_info.gfx9.swizzle = %d;\n", - surface->tiling_info.gfx9.swizzle); + "plane_state->tiling_info.gfx8.pipe_config = %d;\n" + "plane_state->tiling_info.gfx8.array_mode = %d;\n" + "plane_state->color_space = %d;\n" + "plane_state->dcc.enable = %d;\n" + "plane_state->format = %d;\n" + "plane_state->rotation = %d;\n" + "plane_state->stereo_format = %d;\n", + plane_state->tiling_info.gfx8.pipe_config, + plane_state->tiling_info.gfx8.array_mode, + plane_state->color_space, + plane_state->dcc.enable, + plane_state->format, + plane_state->rotation, + plane_state->stereo_format); + + SURFACE_TRACE("plane_state->tiling_info.gfx9.swizzle = %d;\n", + plane_state->tiling_info.gfx9.swizzle); SURFACE_TRACE("\n"); } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index ce0415f26600..4eef400cb551 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -430,17 +430,17 @@ static void rect_swap_helper(struct rect *rect) static void calculate_viewport(struct pipe_ctx *pipe_ctx) { - const struct dc_plane_state *surface = pipe_ctx->surface; + const struct dc_plane_state *plane_state = pipe_ctx->plane_state; const struct dc_stream_state *stream = pipe_ctx->stream; struct scaler_data *data = &pipe_ctx->scl_data; - struct rect surf_src = surface->src_rect; + struct rect surf_src = plane_state->src_rect; struct rect clip = { 0 }; int vpc_div = (data->format == PIXEL_FORMAT_420BPP8 || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1; bool pri_split = pipe_ctx->bottom_pipe && - pipe_ctx->bottom_pipe->surface == pipe_ctx->surface; + pipe_ctx->bottom_pipe->plane_state == pipe_ctx->plane_state; bool sec_split = pipe_ctx->top_pipe && - pipe_ctx->top_pipe->surface == pipe_ctx->surface; + pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state; if (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE || stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) { @@ -448,41 +448,41 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) sec_split = false; } - if (pipe_ctx->surface->rotation == ROTATION_ANGLE_90 || - pipe_ctx->surface->rotation == ROTATION_ANGLE_270) + if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 || + pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) rect_swap_helper(&surf_src); /* The actual clip is an intersection between stream * source and surface clip */ - clip.x = stream->src.x > surface->clip_rect.x ? - stream->src.x : surface->clip_rect.x; + clip.x = stream->src.x > plane_state->clip_rect.x ? + stream->src.x : plane_state->clip_rect.x; clip.width = stream->src.x + stream->src.width < - surface->clip_rect.x + surface->clip_rect.width ? + plane_state->clip_rect.x + plane_state->clip_rect.width ? stream->src.x + stream->src.width - clip.x : - surface->clip_rect.x + surface->clip_rect.width - clip.x ; + plane_state->clip_rect.x + plane_state->clip_rect.width - clip.x ; - clip.y = stream->src.y > surface->clip_rect.y ? - stream->src.y : surface->clip_rect.y; + clip.y = stream->src.y > plane_state->clip_rect.y ? + stream->src.y : plane_state->clip_rect.y; clip.height = stream->src.y + stream->src.height < - surface->clip_rect.y + surface->clip_rect.height ? + plane_state->clip_rect.y + plane_state->clip_rect.height ? stream->src.y + stream->src.height - clip.y : - surface->clip_rect.y + surface->clip_rect.height - clip.y ; + plane_state->clip_rect.y + plane_state->clip_rect.height - clip.y ; /* offset = surf_src.ofs + (clip.ofs - surface->dst_rect.ofs) * scl_ratio * num_pixels = clip.num_pix * scl_ratio */ - data->viewport.x = surf_src.x + (clip.x - surface->dst_rect.x) * - surf_src.width / surface->dst_rect.width; + data->viewport.x = surf_src.x + (clip.x - plane_state->dst_rect.x) * + surf_src.width / plane_state->dst_rect.width; data->viewport.width = clip.width * - surf_src.width / surface->dst_rect.width; + surf_src.width / plane_state->dst_rect.width; - data->viewport.y = surf_src.y + (clip.y - surface->dst_rect.y) * - surf_src.height / surface->dst_rect.height; + data->viewport.y = surf_src.y + (clip.y - plane_state->dst_rect.y) * + surf_src.height / plane_state->dst_rect.height; data->viewport.height = clip.height * - surf_src.height / surface->dst_rect.height; + surf_src.height / plane_state->dst_rect.height; /* Round down, compensate in init */ data->viewport_c.x = data->viewport.x / vpc_div; @@ -498,13 +498,13 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) /* Handle hsplit */ if (pri_split || sec_split) { /* HMirror XOR Secondary_pipe XOR Rotation_180 */ - bool right_view = (sec_split != surface->horizontal_mirror) != - (surface->rotation == ROTATION_ANGLE_180); + bool right_view = (sec_split != plane_state->horizontal_mirror) != + (plane_state->rotation == ROTATION_ANGLE_180); - if (surface->rotation == ROTATION_ANGLE_90 - || surface->rotation == ROTATION_ANGLE_270) + if (plane_state->rotation == ROTATION_ANGLE_90 + || plane_state->rotation == ROTATION_ANGLE_270) /* Secondary_pipe XOR Rotation_270 */ - right_view = (surface->rotation == ROTATION_ANGLE_270) != sec_split; + right_view = (plane_state->rotation == ROTATION_ANGLE_270) != sec_split; if (right_view) { data->viewport.width /= 2; @@ -520,8 +520,8 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) } } - if (surface->rotation == ROTATION_ANGLE_90 || - surface->rotation == ROTATION_ANGLE_270) { + if (plane_state->rotation == ROTATION_ANGLE_90 || + plane_state->rotation == ROTATION_ANGLE_270) { rect_swap_helper(&data->viewport_c); rect_swap_helper(&data->viewport); } @@ -529,14 +529,14 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip) { - const struct dc_plane_state *surface = pipe_ctx->surface; + const struct dc_plane_state *plane_state = pipe_ctx->plane_state; const struct dc_stream_state *stream = pipe_ctx->stream; - struct rect surf_src = surface->src_rect; - struct rect surf_clip = surface->clip_rect; + struct rect surf_src = plane_state->src_rect; + struct rect surf_clip = plane_state->clip_rect; int recout_full_x, recout_full_y; - if (pipe_ctx->surface->rotation == ROTATION_ANGLE_90 || - pipe_ctx->surface->rotation == ROTATION_ANGLE_270) + if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 || + pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) rect_swap_helper(&surf_src); pipe_ctx->scl_data.recout.x = stream->dst.x; @@ -568,8 +568,8 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip - pipe_ctx->scl_data.recout.y; /* Handle h & vsplit */ - if (pipe_ctx->top_pipe && pipe_ctx->top_pipe->surface == - pipe_ctx->surface) { + if (pipe_ctx->top_pipe && pipe_ctx->top_pipe->plane_state == + pipe_ctx->plane_state) { if (stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) { pipe_ctx->scl_data.recout.height /= 2; pipe_ctx->scl_data.recout.y += pipe_ctx->scl_data.recout.height; @@ -581,7 +581,7 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip pipe_ctx->scl_data.recout.width += pipe_ctx->scl_data.recout.width % 2; } } else if (pipe_ctx->bottom_pipe && - pipe_ctx->bottom_pipe->surface == pipe_ctx->surface) { + pipe_ctx->bottom_pipe->plane_state == pipe_ctx->plane_state) { if (stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) pipe_ctx->scl_data.recout.height /= 2; else @@ -592,13 +592,13 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip * * 1/ stream scaling ratio) - (surf surf_src offset * 1/ full scl * ratio) */ - recout_full_x = stream->dst.x + (surface->dst_rect.x - stream->src.x) + recout_full_x = stream->dst.x + (plane_state->dst_rect.x - stream->src.x) * stream->dst.width / stream->src.width - - surf_src.x * surface->dst_rect.width / surf_src.width + surf_src.x * plane_state->dst_rect.width / surf_src.width * stream->dst.width / stream->src.width; - recout_full_y = stream->dst.y + (surface->dst_rect.y - stream->src.y) + recout_full_y = stream->dst.y + (plane_state->dst_rect.y - stream->src.y) * stream->dst.height / stream->src.height - - surf_src.y * surface->dst_rect.height / surf_src.height + surf_src.y * plane_state->dst_rect.height / surf_src.height * stream->dst.height / stream->src.height; recout_skip->width = pipe_ctx->scl_data.recout.x - recout_full_x; @@ -607,24 +607,24 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) { - const struct dc_plane_state *surface = pipe_ctx->surface; + const struct dc_plane_state *plane_state = pipe_ctx->plane_state; const struct dc_stream_state *stream = pipe_ctx->stream; - struct rect surf_src = surface->src_rect; + struct rect surf_src = plane_state->src_rect; const int in_w = stream->src.width; const int in_h = stream->src.height; const int out_w = stream->dst.width; const int out_h = stream->dst.height; - if (pipe_ctx->surface->rotation == ROTATION_ANGLE_90 || - pipe_ctx->surface->rotation == ROTATION_ANGLE_270) + if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 || + pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) rect_swap_helper(&surf_src); pipe_ctx->scl_data.ratios.horz = dal_fixed31_32_from_fraction( surf_src.width, - surface->dst_rect.width); + plane_state->dst_rect.width); pipe_ctx->scl_data.ratios.vert = dal_fixed31_32_from_fraction( surf_src.height, - surface->dst_rect.height); + plane_state->dst_rect.height); if (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE) pipe_ctx->scl_data.ratios.horz.value *= 2; @@ -649,13 +649,13 @@ static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *recout_skip) { struct scaler_data *data = &pipe_ctx->scl_data; - struct rect src = pipe_ctx->surface->src_rect; + struct rect src = pipe_ctx->plane_state->src_rect; int vpc_div = (data->format == PIXEL_FORMAT_420BPP8 || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1; - if (pipe_ctx->surface->rotation == ROTATION_ANGLE_90 || - pipe_ctx->surface->rotation == ROTATION_ANGLE_270) { + if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 || + pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) { rect_swap_helper(&src); rect_swap_helper(&data->viewport_c); rect_swap_helper(&data->viewport); @@ -805,8 +805,8 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *r data->inits.v_bot = dal_fixed31_32_add(data->inits.v, data->ratios.vert); data->inits.v_c_bot = dal_fixed31_32_add(data->inits.v_c, data->ratios.vert_c); - if (pipe_ctx->surface->rotation == ROTATION_ANGLE_90 || - pipe_ctx->surface->rotation == ROTATION_ANGLE_270) { + if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 || + pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) { rect_swap_helper(&data->viewport_c); rect_swap_helper(&data->viewport); } @@ -814,7 +814,7 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *r bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) { - const struct dc_plane_state *surface = pipe_ctx->surface; + const struct dc_plane_state *plane_state = pipe_ctx->plane_state; struct dc_crtc_timing *timing = &pipe_ctx->stream->timing; struct view recout_skip = { 0 }; bool res = false; @@ -824,7 +824,7 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) * Inits require viewport, taps, ratios and recout of split pipe */ pipe_ctx->scl_data.format = convert_pixel_format_to_dalsurface( - pipe_ctx->surface->format); + pipe_ctx->plane_state->format); calculate_scaling_ratios(pipe_ctx); @@ -846,14 +846,14 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) /* Taps calculations */ res = pipe_ctx->xfm->funcs->transform_get_optimal_number_of_taps( - pipe_ctx->xfm, &pipe_ctx->scl_data, &surface->scaling_quality); + pipe_ctx->xfm, &pipe_ctx->scl_data, &plane_state->scaling_quality); if (!res) { /* Try 24 bpp linebuffer */ pipe_ctx->scl_data.lb_params.depth = LB_PIXEL_DEPTH_24BPP; res = pipe_ctx->xfm->funcs->transform_get_optimal_number_of_taps( - pipe_ctx->xfm, &pipe_ctx->scl_data, &surface->scaling_quality); + pipe_ctx->xfm, &pipe_ctx->scl_data, &plane_state->scaling_quality); } if (res) @@ -869,10 +869,10 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) pipe_ctx->scl_data.viewport.width, pipe_ctx->scl_data.viewport.x, pipe_ctx->scl_data.viewport.y, - surface->dst_rect.height, - surface->dst_rect.width, - surface->dst_rect.x, - surface->dst_rect.y); + plane_state->dst_rect.height, + plane_state->dst_rect.width, + plane_state->dst_rect.x, + plane_state->dst_rect.y); return res; } @@ -885,7 +885,7 @@ enum dc_status resource_build_scaling_params_for_context( int i; for (i = 0; i < MAX_PIPES; i++) { - if (context->res_ctx.pipe_ctx[i].surface != NULL && + if (context->res_ctx.pipe_ctx[i].plane_state != NULL && context->res_ctx.pipe_ctx[i].stream != NULL) if (!resource_build_scaling_params(&context->res_ctx.pipe_ctx[i])) return DC_FAIL_SCALING; @@ -954,13 +954,13 @@ static struct pipe_ctx *acquire_free_pipe_for_stream( if (!head_pipe) ASSERT(0); - if (!head_pipe->surface) + if (!head_pipe->plane_state) return head_pipe; /* Re-use pipe already acquired for this stream if available*/ for (i = pool->pipe_count - 1; i >= 0; i--) { if (res_ctx->pipe_ctx[i].stream == stream && - !res_ctx->pipe_ctx[i].surface) { + !res_ctx->pipe_ctx[i].plane_state) { return &res_ctx->pipe_ctx[i]; } } @@ -987,7 +987,7 @@ static void release_free_pipes_for_stream( /* never release the topmost pipe*/ if (res_ctx->pipe_ctx[i].stream == stream && res_ctx->pipe_ctx[i].top_pipe && - !res_ctx->pipe_ctx[i].surface) { + !res_ctx->pipe_ctx[i].plane_state) { memset(&res_ctx->pipe_ctx[i], 0, sizeof(struct pipe_ctx)); } } @@ -1005,7 +1005,7 @@ static int acquire_first_split_pipe( struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; if (pipe_ctx->top_pipe && - pipe_ctx->top_pipe->surface == pipe_ctx->surface) { + pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state) { pipe_ctx->top_pipe->bottom_pipe = pipe_ctx->bottom_pipe; if (pipe_ctx->bottom_pipe) pipe_ctx->bottom_pipe->top_pipe = pipe_ctx->top_pipe; @@ -1028,7 +1028,7 @@ static int acquire_first_split_pipe( #endif bool resource_attach_surfaces_to_context( - struct dc_plane_state * const *surfaces, + struct dc_plane_state * const *plane_states, int surface_count, struct dc_stream_state *stream, struct validate_context *context, @@ -1057,25 +1057,25 @@ bool resource_attach_surfaces_to_context( /* retain new surfaces */ for (i = 0; i < surface_count; i++) - dc_surface_retain(surfaces[i]); + dc_plane_state_retain(plane_states[i]); /* detach surfaces from pipes */ for (i = 0; i < pool->pipe_count; i++) if (context->res_ctx.pipe_ctx[i].stream == stream) { - context->res_ctx.pipe_ctx[i].surface = NULL; + context->res_ctx.pipe_ctx[i].plane_state = NULL; context->res_ctx.pipe_ctx[i].bottom_pipe = NULL; } /* release existing surfaces*/ - for (i = 0; i < stream_status->surface_count; i++) - dc_surface_release(stream_status->surfaces[i]); + for (i = 0; i < stream_status->plane_count; i++) + dc_plane_state_release(stream_status->plane_states[i]); - for (i = surface_count; i < stream_status->surface_count; i++) - stream_status->surfaces[i] = NULL; + for (i = surface_count; i < stream_status->plane_count; i++) + stream_status->plane_states[i] = NULL; tail_pipe = NULL; for (i = 0; i < surface_count; i++) { - struct dc_plane_state *surface = surfaces[i]; + struct dc_plane_state *plane_state = plane_states[i]; struct pipe_ctx *free_pipe = acquire_free_pipe_for_stream( context, pool, stream); @@ -1087,11 +1087,11 @@ bool resource_attach_surfaces_to_context( } #endif if (!free_pipe) { - stream_status->surfaces[i] = NULL; + stream_status->plane_states[i] = NULL; return false; } - free_pipe->surface = surface; + free_pipe->plane_state = plane_state; if (tail_pipe) { free_pipe->tg = tail_pipe->tg; @@ -1110,9 +1110,9 @@ bool resource_attach_surfaces_to_context( /* assign new surfaces*/ for (i = 0; i < surface_count; i++) - stream_status->surfaces[i] = surfaces[i]; + stream_status->plane_states[i] = plane_states[i]; - stream_status->surface_count = surface_count; + stream_status->plane_count = surface_count; return true; } @@ -1180,17 +1180,17 @@ bool resource_validate_attach_surfaces( old_context->streams[j], context->streams[i])) { if (!resource_attach_surfaces_to_context( - old_context->stream_status[j].surfaces, - old_context->stream_status[j].surface_count, + old_context->stream_status[j].plane_states, + old_context->stream_status[j].plane_count, context->streams[i], context, pool)) return false; context->stream_status[i] = old_context->stream_status[j]; } - if (set[i].surface_count != 0) + if (set[i].plane_count != 0) if (!resource_attach_surfaces_to_context( - set[i].surfaces, - set[i].surface_count, + set[i].plane_states, + set[i].plane_count, context->streams[i], context, pool)) return false; @@ -1351,13 +1351,13 @@ bool resource_is_stream_unchanged( static void copy_pipe_ctx( const struct pipe_ctx *from_pipe_ctx, struct pipe_ctx *to_pipe_ctx) { - struct dc_plane_state *surface = to_pipe_ctx->surface; + struct dc_plane_state *plane_state = to_pipe_ctx->plane_state; struct dc_stream_state *stream = to_pipe_ctx->stream; *to_pipe_ctx = *from_pipe_ctx; to_pipe_ctx->stream = stream; - if (surface != NULL) - to_pipe_ctx->surface = surface; + if (plane_state != NULL) + to_pipe_ctx->plane_state = plane_state; } static struct dc_stream_state *find_pll_sharable_stream( @@ -2055,7 +2055,7 @@ static void set_spd_info_packet( static void set_hdr_static_info_packet( struct encoder_info_packet *info_packet, - struct dc_plane_state *surface, + struct dc_plane_state *plane_state, struct dc_stream_state *stream) { uint16_t i = 0; @@ -2063,10 +2063,10 @@ static void set_hdr_static_info_packet( struct dc_hdr_static_metadata hdr_metadata; uint32_t data; - if (!surface) + if (!plane_state) return; - hdr_metadata = surface->hdr_static_ctx; + hdr_metadata = plane_state->hdr_static_ctx; if (!hdr_metadata.hdr_supported) return; @@ -2204,11 +2204,11 @@ void dc_resource_validate_ctx_destruct(struct validate_context *context) int i, j; for (i = 0; i < context->stream_count; i++) { - for (j = 0; j < context->stream_status[i].surface_count; j++) - dc_surface_release( - context->stream_status[i].surfaces[j]); + for (j = 0; j < context->stream_status[i].plane_count; j++) + dc_plane_state_release( + context->stream_status[i].plane_states[j]); - context->stream_status[i].surface_count = 0; + context->stream_status[i].plane_count = 0; dc_stream_release(context->streams[i]); context->streams[i] = NULL; } @@ -2240,9 +2240,9 @@ void dc_resource_validate_ctx_copy_construct( for (i = 0; i < dst_ctx->stream_count; i++) { dc_stream_retain(dst_ctx->streams[i]); - for (j = 0; j < dst_ctx->stream_status[i].surface_count; j++) - dc_surface_retain( - dst_ctx->stream_status[i].surfaces[j]); + for (j = 0; j < dst_ctx->stream_status[i].plane_count; j++) + dc_plane_state_retain( + dst_ctx->stream_status[i].plane_states[j]); } /* context refcount should not be overridden */ @@ -2288,7 +2288,7 @@ void resource_build_info_frame(struct pipe_ctx *pipe_ctx) set_spd_info_packet(&info->spd, pipe_ctx->stream); set_hdr_static_info_packet(&info->hdrsmd, - pipe_ctx->surface, pipe_ctx->stream); + pipe_ctx->plane_state, pipe_ctx->stream); } else if (dc_is_dp_signal(signal)) { set_vsc_info_packet(&info->vsc, pipe_ctx->stream); @@ -2296,7 +2296,7 @@ void resource_build_info_frame(struct pipe_ctx *pipe_ctx) set_spd_info_packet(&info->spd, pipe_ctx->stream); set_hdr_static_info_packet(&info->hdrsmd, - pipe_ctx->surface, pipe_ctx->stream); + pipe_ctx->plane_state, pipe_ctx->stream); } patch_gamut_packet_checksum(&info->gamut); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 7a87f38f2324..2b6506822cca 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -185,7 +185,7 @@ bool dc_stream_set_cursor_attributes( if (pipe_ctx->stream != stream || !pipe_ctx->ipp) continue; - if (pipe_ctx->top_pipe && pipe_ctx->surface != pipe_ctx->top_pipe->surface) + if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state) continue; pipe_ctx->ipp->funcs->ipp_cursor_set_attributes( @@ -229,14 +229,14 @@ bool dc_stream_set_cursor_position( }; if (pipe_ctx->stream != stream || - !pipe_ctx->ipp || !pipe_ctx->surface) + !pipe_ctx->ipp || !pipe_ctx->plane_state) continue; - if (pipe_ctx->surface->address.type + if (pipe_ctx->plane_state->address.type == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE) pos_cpy.enable = false; - if (pipe_ctx->top_pipe && pipe_ctx->surface != pipe_ctx->top_pipe->surface) + if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state) pos_cpy.enable = false; ipp->funcs->ipp_cursor_set_position(ipp, &pos_cpy, ¶m); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index 941b3671375d..3bcca2d1872b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -34,75 +34,75 @@ /******************************************************************************* * Private functions ******************************************************************************/ -static bool construct(struct dc_context *ctx, struct dc_plane_state *surface) +static bool construct(struct dc_context *ctx, struct dc_plane_state *plane_state) { - surface->ctx = ctx; - memset(&surface->hdr_static_ctx, + plane_state->ctx = ctx; + memset(&plane_state->hdr_static_ctx, 0, sizeof(struct dc_hdr_static_metadata)); return true; } -static void destruct(struct dc_plane_state *surface) +static void destruct(struct dc_plane_state *plane_state) { - if (surface->gamma_correction != NULL) { - dc_gamma_release(&surface->gamma_correction); + if (plane_state->gamma_correction != NULL) { + dc_gamma_release(&plane_state->gamma_correction); } - if (surface->in_transfer_func != NULL) { + if (plane_state->in_transfer_func != NULL) { dc_transfer_func_release( - surface->in_transfer_func); - surface->in_transfer_func = NULL; + plane_state->in_transfer_func); + plane_state->in_transfer_func = NULL; } } /******************************************************************************* * Public functions ******************************************************************************/ -void enable_surface_flip_reporting(struct dc_plane_state *surface, +void enable_surface_flip_reporting(struct dc_plane_state *plane_state, uint32_t controller_id) { - surface->irq_source = controller_id + DC_IRQ_SOURCE_PFLIP1 - 1; + plane_state->irq_source = controller_id + DC_IRQ_SOURCE_PFLIP1 - 1; /*register_flip_interrupt(surface);*/ } -struct dc_plane_state *dc_create_surface(const struct dc *dc) +struct dc_plane_state *dc_create_plane_state(const struct dc *dc) { struct core_dc *core_dc = DC_TO_CORE(dc); - struct dc_plane_state *surface = dm_alloc(sizeof(*surface)); + struct dc_plane_state *plane_state = dm_alloc(sizeof(*plane_state)); - if (NULL == surface) + if (NULL == plane_state) goto alloc_fail; - if (false == construct(core_dc->ctx, surface)) + if (false == construct(core_dc->ctx, plane_state)) goto construct_fail; - ++surface->ref_count; + ++plane_state->ref_count; - return surface; + return plane_state; construct_fail: - dm_free(surface); + dm_free(plane_state); alloc_fail: return NULL; } -const struct dc_surface_status *dc_surface_get_status( - const struct dc_plane_state *dc_surface) +const struct dc_plane_status *dc_plane_get_status( + const struct dc_plane_state *plane_state) { - const struct dc_surface_status *surface_status; + const struct dc_plane_status *plane_status; struct core_dc *core_dc; int i; - if (!dc_surface || - !dc_surface->ctx || - !dc_surface->ctx->dc) { + if (!plane_state || + !plane_state->ctx || + !plane_state->ctx->dc) { ASSERT(0); return NULL; /* remove this if above assert never hit */ } - surface_status = &dc_surface->status; - core_dc = DC_TO_CORE(dc_surface->ctx->dc); + plane_status = &plane_state->status; + core_dc = DC_TO_CORE(plane_state->ctx->dc); if (core_dc->current_context == NULL) return NULL; @@ -111,29 +111,29 @@ const struct dc_surface_status *dc_surface_get_status( struct pipe_ctx *pipe_ctx = &core_dc->current_context->res_ctx.pipe_ctx[i]; - if (pipe_ctx->surface != dc_surface) + if (pipe_ctx->plane_state != plane_state) continue; core_dc->hwss.update_pending_status(pipe_ctx); } - return surface_status; + return plane_status; } -void dc_surface_retain(struct dc_plane_state *surface) +void dc_plane_state_retain(struct dc_plane_state *plane_state) { - ASSERT(surface->ref_count > 0); - ++surface->ref_count; + ASSERT(plane_state->ref_count > 0); + ++plane_state->ref_count; } -void dc_surface_release(struct dc_plane_state *surface) +void dc_plane_state_release(struct dc_plane_state *plane_state) { - ASSERT(surface->ref_count > 0); - --surface->ref_count; + ASSERT(plane_state->ref_count > 0); + --plane_state->ref_count; - if (surface->ref_count == 0) { - destruct(surface); - dm_free(surface); + if (plane_state->ref_count == 0) { + destruct(plane_state); + dm_free(plane_state); } } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index ab805965e321..d1a6398043a3 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -47,7 +47,7 @@ struct dc_caps { uint32_t max_links; uint32_t max_audios; uint32_t max_slave_planes; - uint32_t max_surfaces; + uint32_t max_planes; uint32_t max_downscale_ratio; uint32_t i2c_speed_in_khz; @@ -303,7 +303,7 @@ struct dc_transfer_func { * the last requested address and the currently active address so the called * can determine if there are any outstanding flips */ -struct dc_surface_status { +struct dc_plane_status { struct dc_plane_address requested_address; struct dc_plane_address current_address; bool is_flip_pending; @@ -338,7 +338,7 @@ struct dc_plane_state { bool horizontal_mirror; /* private to DC core */ - struct dc_surface_status status; + struct dc_plane_status status; struct dc_context *ctx; /* private to dc_surface.c */ @@ -385,12 +385,12 @@ struct dc_surface_update { /* * Create a new surface with default parameters; */ -struct dc_plane_state *dc_create_surface(const struct dc *dc); -const struct dc_surface_status *dc_surface_get_status( - const struct dc_plane_state *dc_surface); +struct dc_plane_state *dc_create_plane_state(const struct dc *dc); +const struct dc_plane_status *dc_plane_get_status( + const struct dc_plane_state *plane_state); -void dc_surface_retain(struct dc_plane_state *dc_surface); -void dc_surface_release(struct dc_plane_state *dc_surface); +void dc_plane_state_retain(struct dc_plane_state *plane_state); +void dc_plane_state_release(struct dc_plane_state *plane_state); void dc_gamma_retain(struct dc_gamma *dc_gamma); void dc_gamma_release(struct dc_gamma **dc_gamma); @@ -422,10 +422,10 @@ struct dc_flip_addrs { * This does not trigger a flip. No surface address is programmed. */ -bool dc_commit_surfaces_to_stream( +bool dc_commit_planes_to_stream( struct dc *dc, - struct dc_plane_state **dc_surfaces, - uint8_t surface_count, + struct dc_plane_state **plane_states, + uint8_t new_plane_count, struct dc_stream_state *stream); bool dc_post_update_surfaces_to_stream( @@ -469,8 +469,8 @@ enum surface_update_type { struct dc_stream_status { int primary_otg_inst; - int surface_count; - struct dc_plane_state *surfaces[MAX_SURFACE_NUM]; + int plane_count; + struct dc_plane_state *plane_states[MAX_SURFACE_NUM]; /* * link this stream passes through @@ -546,7 +546,7 @@ bool dc_is_stream_unchanged( * */ -void dc_update_surfaces_and_stream(struct dc *dc, +void dc_update_planes_and_stream(struct dc *dc, struct dc_surface_update *surface_updates, int surface_count, struct dc_stream_state *dc_stream, struct dc_stream_update *stream_update); @@ -582,8 +582,8 @@ bool dc_stream_get_scanoutpos(const struct dc_stream_state *stream, */ struct dc_validation_set { struct dc_stream_state *stream; - struct dc_plane_state *surfaces[MAX_SURFACES]; - uint8_t surface_count; + struct dc_plane_state *plane_states[MAX_SURFACES]; + uint8_t plane_count; }; bool dc_validate_stream(const struct dc *dc, struct dc_stream_state *stream); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c index af59ab93796a..8140ff31c3bd 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c @@ -197,9 +197,9 @@ void dce_crtc_switch_to_clk_src(struct dce_hwseq *hws, } /* Only use LUT for 8 bit formats */ -bool dce_use_lut(const struct dc_plane_state *surface) +bool dce_use_lut(const struct dc_plane_state *plane_state) { - switch (surface->format) { + switch (plane_state->format) { case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: return true; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index d5cb98a92c53..a0531b3aa6a1 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -552,5 +552,5 @@ void dce_crtc_switch_to_clk_src(struct dce_hwseq *hws, struct clock_source *clk_src, unsigned int tg_inst); -bool dce_use_lut(const struct dc_plane_state *surface); +bool dce_use_lut(const struct dc_plane_state *plane_state); #endif /*__DCE_HWSEQ_H__*/ diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 98fb7f02a6fe..46f0c71fbac4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -705,13 +705,13 @@ static bool dce100_validate_surface_sets( int i; for (i = 0; i < set_count; i++) { - if (set[i].surface_count == 0) + if (set[i].plane_count == 0) continue; - if (set[i].surface_count > 1) + if (set[i].plane_count > 1) return false; - if (set[i].surfaces[0]->format + if (set[i].plane_states[0]->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) return false; } @@ -958,7 +958,7 @@ static bool construct( } } - dc->public.caps.max_surfaces = pool->base.pipe_count; + dc->public.caps.max_planes = pool->base.pipe_count; if (!resource_construct(num_virtual_links, dc, &pool->base, &res_create_funcs)) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index e4310a376116..ea9ce87d348a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -215,11 +215,11 @@ static bool dce110_enable_display_power_gating( } static void build_prescale_params(struct ipp_prescale_params *prescale_params, - const struct dc_plane_state *surface) + const struct dc_plane_state *plane_state) { prescale_params->mode = IPP_PRESCALE_MODE_FIXED_UNSIGNED; - switch (surface->format) { + switch (plane_state->format) { case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: prescale_params->scale = 0x2020; @@ -240,7 +240,7 @@ static void build_prescale_params(struct ipp_prescale_params *prescale_params, static bool dce110_set_input_transfer_func( struct pipe_ctx *pipe_ctx, - const struct dc_plane_state *surface) + const struct dc_plane_state *plane_state) { struct input_pixel_processor *ipp = pipe_ctx->ipp; const struct dc_transfer_func *tf = NULL; @@ -250,14 +250,14 @@ static bool dce110_set_input_transfer_func( if (ipp == NULL) return false; - if (surface->in_transfer_func) - tf = surface->in_transfer_func; + if (plane_state->in_transfer_func) + tf = plane_state->in_transfer_func; - build_prescale_params(&prescale_params, surface); + build_prescale_params(&prescale_params, plane_state); ipp->funcs->ipp_program_prescale(ipp, &prescale_params); - if (surface->gamma_correction && dce_use_lut(surface)) - ipp->funcs->ipp_program_input_lut(ipp, surface->gamma_correction); + if (plane_state->gamma_correction && dce_use_lut(plane_state)) + ipp->funcs->ipp_program_input_lut(ipp, plane_state->gamma_correction); if (tf == NULL) { /* Default case if no input transfer function specified */ @@ -1119,7 +1119,7 @@ static enum dc_status apply_single_controller_ctx_to_hw( if ((!pipe_ctx_old || memcmp(&pipe_ctx_old->scl_data, &pipe_ctx->scl_data, sizeof(struct scaler_data)) != 0) && - pipe_ctx->surface) { + pipe_ctx->plane_state) { program_scaler(dc, pipe_ctx); } @@ -1916,11 +1916,11 @@ static void set_default_colors(struct pipe_ctx *pipe_ctx) struct default_adjustment default_adjust = { 0 }; default_adjust.force_hw_default = false; - if (pipe_ctx->surface == NULL) + if (pipe_ctx->plane_state == NULL) default_adjust.in_color_space = COLOR_SPACE_SRGB; else default_adjust.in_color_space = - pipe_ctx->surface->color_space; + pipe_ctx->plane_state->color_space; if (pipe_ctx->stream == NULL) default_adjust.out_color_space = COLOR_SPACE_SRGB; else @@ -1971,16 +1971,16 @@ static void program_surface_visibility(const struct core_dc *dc, /* For now we are supporting only two pipes */ ASSERT(pipe_ctx->bottom_pipe->bottom_pipe == NULL); - if (pipe_ctx->bottom_pipe->surface->visible) { - if (pipe_ctx->surface->visible) + if (pipe_ctx->bottom_pipe->plane_state->visible) { + if (pipe_ctx->plane_state->visible) blender_mode = BLND_MODE_BLENDING; else blender_mode = BLND_MODE_OTHER_PIPE; - } else if (!pipe_ctx->surface->visible) + } else if (!pipe_ctx->plane_state->visible) blank_target = true; - } else if (!pipe_ctx->surface->visible) + } else if (!pipe_ctx->plane_state->visible) blank_target = true; dce_set_blender_mode(dc->hwseq, pipe_ctx->pipe_idx, blender_mode); @@ -2038,7 +2038,7 @@ static void set_plane_config( struct resource_context *res_ctx) { struct mem_input *mi = pipe_ctx->mi; - struct dc_plane_state *surface = pipe_ctx->surface; + struct dc_plane_state *plane_state = pipe_ctx->plane_state; struct xfm_grph_csc_adjustment adjust; struct out_csc_color_matrix tbl_entry; unsigned int i; @@ -2103,57 +2103,57 @@ static void set_plane_config( mi->funcs->mem_input_program_surface_config( mi, - surface->format, - &surface->tiling_info, - &surface->plane_size, - surface->rotation, + plane_state->format, + &plane_state->tiling_info, + &plane_state->plane_size, + plane_state->rotation, NULL, false); if (mi->funcs->set_blank) - mi->funcs->set_blank(mi, pipe_ctx->surface->visible); + mi->funcs->set_blank(mi, pipe_ctx->plane_state->visible); if (dc->public.config.gpu_vm_support) mi->funcs->mem_input_program_pte_vm( pipe_ctx->mi, - surface->format, - &surface->tiling_info, - surface->rotation); + plane_state->format, + &plane_state->tiling_info, + plane_state->rotation); } static void update_plane_addr(const struct core_dc *dc, struct pipe_ctx *pipe_ctx) { - struct dc_plane_state *surface = pipe_ctx->surface; + struct dc_plane_state *plane_state = pipe_ctx->plane_state; - if (surface == NULL) + if (plane_state == NULL) return; pipe_ctx->mi->funcs->mem_input_program_surface_flip_and_addr( pipe_ctx->mi, - &surface->address, - surface->flip_immediate); + &plane_state->address, + plane_state->flip_immediate); - surface->status.requested_address = surface->address; + plane_state->status.requested_address = plane_state->address; } void dce110_update_pending_status(struct pipe_ctx *pipe_ctx) { - struct dc_plane_state *surface = pipe_ctx->surface; + struct dc_plane_state *plane_state = pipe_ctx->plane_state; - if (surface == NULL) + if (plane_state == NULL) return; - surface->status.is_flip_pending = + plane_state->status.is_flip_pending = pipe_ctx->mi->funcs->mem_input_is_flip_pending( pipe_ctx->mi); - if (surface->status.is_flip_pending && !surface->visible) + if (plane_state->status.is_flip_pending && !plane_state->visible) pipe_ctx->mi->current_address = pipe_ctx->mi->request_address; - surface->status.current_address = pipe_ctx->mi->current_address; + plane_state->status.current_address = pipe_ctx->mi->current_address; if (pipe_ctx->mi->current_address.type == PLN_ADDR_TYPE_GRPH_STEREO && pipe_ctx->tg->funcs->is_stereo_left_eye) { - surface->status.is_right_eye =\ + plane_state->status.is_right_eye =\ !pipe_ctx->tg->funcs->is_stereo_left_eye(pipe_ctx->tg); } } @@ -2490,7 +2490,7 @@ static void dce110_program_front_end_for_pipe( { struct mem_input *mi = pipe_ctx->mi; struct pipe_ctx *old_pipe = NULL; - struct dc_plane_state *surface = pipe_ctx->surface; + struct dc_plane_state *plane_state = pipe_ctx->plane_state; struct xfm_grph_csc_adjustment adjust; struct out_csc_color_matrix tbl_entry; unsigned int i; @@ -2558,21 +2558,21 @@ static void dce110_program_front_end_for_pipe( mi->funcs->mem_input_program_surface_config( mi, - surface->format, - &surface->tiling_info, - &surface->plane_size, - surface->rotation, + plane_state->format, + &plane_state->tiling_info, + &plane_state->plane_size, + plane_state->rotation, NULL, false); if (mi->funcs->set_blank) - mi->funcs->set_blank(mi, pipe_ctx->surface->visible); + mi->funcs->set_blank(mi, pipe_ctx->plane_state->visible); if (dc->public.config.gpu_vm_support) mi->funcs->mem_input_program_pte_vm( pipe_ctx->mi, - surface->format, - &surface->tiling_info, - surface->rotation); + plane_state->format, + &plane_state->tiling_info, + plane_state->rotation); dm_logger_write(dc->ctx->logger, LOG_SURFACE, "Pipe:%d 0x%x: addr hi:0x%x, " @@ -2581,21 +2581,21 @@ static void dce110_program_front_end_for_pipe( " %d; dst: %d, %d, %d, %d;" "clip: %d, %d, %d, %d\n", pipe_ctx->pipe_idx, - pipe_ctx->surface, - pipe_ctx->surface->address.grph.addr.high_part, - pipe_ctx->surface->address.grph.addr.low_part, - pipe_ctx->surface->src_rect.x, - pipe_ctx->surface->src_rect.y, - pipe_ctx->surface->src_rect.width, - pipe_ctx->surface->src_rect.height, - pipe_ctx->surface->dst_rect.x, - pipe_ctx->surface->dst_rect.y, - pipe_ctx->surface->dst_rect.width, - pipe_ctx->surface->dst_rect.height, - pipe_ctx->surface->clip_rect.x, - pipe_ctx->surface->clip_rect.y, - pipe_ctx->surface->clip_rect.width, - pipe_ctx->surface->clip_rect.height); + pipe_ctx->plane_state, + pipe_ctx->plane_state->address.grph.addr.high_part, + pipe_ctx->plane_state->address.grph.addr.low_part, + pipe_ctx->plane_state->src_rect.x, + pipe_ctx->plane_state->src_rect.y, + pipe_ctx->plane_state->src_rect.width, + pipe_ctx->plane_state->src_rect.height, + pipe_ctx->plane_state->dst_rect.x, + pipe_ctx->plane_state->dst_rect.y, + pipe_ctx->plane_state->dst_rect.width, + pipe_ctx->plane_state->dst_rect.height, + pipe_ctx->plane_state->clip_rect.x, + pipe_ctx->plane_state->clip_rect.y, + pipe_ctx->plane_state->clip_rect.width, + pipe_ctx->plane_state->clip_rect.height); dm_logger_write(dc->ctx->logger, LOG_SURFACE, "Pipe %d: width, height, x, y\n" @@ -2614,19 +2614,18 @@ static void dce110_program_front_end_for_pipe( static void dce110_apply_ctx_for_surface( struct core_dc *dc, - const struct dc_plane_state *surface, + const struct dc_plane_state *plane_state, struct validate_context *context) { int i; - /* TODO remove when removing the surface reset workaroud*/ - if (!surface) + if (!plane_state) return; for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; - if (pipe_ctx->surface != surface) + if (pipe_ctx->plane_state != plane_state) continue; dce110_program_front_end_for_pipe(dc, pipe_ctx); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 89b21bd57a35..f580da1b3249 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -764,9 +764,9 @@ static bool is_surface_pixel_format_supported(struct pipe_ctx *pipe_ctx, unsigne { if (pipe_ctx->pipe_idx != underlay_idx) return true; - if (!pipe_ctx->surface) + if (!pipe_ctx->plane_state) return false; - if (pipe_ctx->surface->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) + if (pipe_ctx->plane_state->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) return false; return true; } @@ -901,22 +901,22 @@ static bool dce110_validate_surface_sets( int i; for (i = 0; i < set_count; i++) { - if (set[i].surface_count == 0) + if (set[i].plane_count == 0) continue; - if (set[i].surface_count > 2) + if (set[i].plane_count > 2) return false; - if (set[i].surfaces[0]->format + if (set[i].plane_states[0]->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) return false; - if (set[i].surface_count == 2) { - if (set[i].surfaces[1]->format + if (set[i].plane_count == 2) { + if (set[i].plane_states[1]->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) return false; - if (set[i].surfaces[1]->src_rect.width > 1920 - || set[i].surfaces[1]->src_rect.height > 1080) + if (set[i].plane_states[1]->src_rect.width > 1920 + || set[i].plane_states[1]->src_rect.height > 1080) return false; if (set[i].stream->timing.pixel_encoding != PIXEL_ENCODING_RGB) @@ -1351,7 +1351,7 @@ static bool construct( if (!dce110_hw_sequencer_construct(dc)) goto res_create_fail; - dc->public.caps.max_surfaces = pool->base.pipe_count; + dc->public.caps.max_planes = pool->base.pipe_count; bw_calcs_init(&dc->bw_dceip, &dc->bw_vbios, dc->ctx->asic_id); diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 68554d6edd94..420434d7283e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -889,13 +889,13 @@ static bool dce112_validate_surface_sets( int i; for (i = 0; i < set_count; i++) { - if (set[i].surface_count == 0) + if (set[i].plane_count == 0) continue; - if (set[i].surface_count > 1) + if (set[i].plane_count > 1) return false; - if (set[i].surfaces[0]->format + if (set[i].plane_states[0]->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) return false; } @@ -1319,7 +1319,7 @@ static bool construct( &res_create_funcs)) goto res_create_fail; - dc->public.caps.max_surfaces = pool->base.pipe_count; + dc->public.caps.max_planes = pool->base.pipe_count; /* Create hardware sequencer */ if (!dce112_hw_sequencer_construct(dc)) diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index 45f5fd63ce14..6448d15c02f5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -982,7 +982,7 @@ static bool construct( if (!dce120_hw_sequencer_create(dc)) goto controller_create_fail; - dc->public.caps.max_surfaces = pool->base.pipe_count; + dc->public.caps.max_planes = pool->base.pipe_count; bw_calcs_init(&dc->bw_dceip, &dc->bw_vbios, dc->ctx->asic_id); diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 734b35eddeed..7473f58584c3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -722,13 +722,13 @@ static bool dce80_validate_surface_sets( int i; for (i = 0; i < set_count; i++) { - if (set[i].surface_count == 0) + if (set[i].plane_count == 0) continue; - if (set[i].surface_count > 1) + if (set[i].plane_count > 1) return false; - if (set[i].surfaces[0]->format + if (set[i].plane_states[0]->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) return false; } @@ -959,7 +959,7 @@ static bool construct( } } - dc->public.caps.max_surfaces = pool->base.pipe_count; + dc->public.caps.max_planes = pool->base.pipe_count; if (!resource_construct(num_virtual_links, dc, &pool->base, &res_create_funcs)) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 866f63d1259d..5922cf8272f5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -986,7 +986,7 @@ static void reset_hw_ctx_wrap( struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; if (!pipe_ctx->stream || - !pipe_ctx->surface || + !pipe_ctx->plane_state || pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) { plane_atomic_disconnect(dc, i); @@ -1010,13 +1010,13 @@ static void reset_hw_ctx_wrap( /*if (!pipe_ctx_old->stream) continue;*/ - if (pipe_ctx->stream && pipe_ctx->surface + if (pipe_ctx->stream && pipe_ctx->plane_state && !pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) continue; plane_atomic_disable(dc, i); - if (!pipe_ctx->stream || !pipe_ctx->surface) + if (!pipe_ctx->stream || !pipe_ctx->plane_state) plane_atomic_power_down(dc, i); } @@ -1038,24 +1038,24 @@ static void reset_hw_ctx_wrap( static bool patch_address_for_sbs_tb_stereo( struct pipe_ctx *pipe_ctx, PHYSICAL_ADDRESS_LOC *addr) { - struct dc_plane_state *surface = pipe_ctx->surface; + struct dc_plane_state *plane_state = pipe_ctx->plane_state; bool sec_split = pipe_ctx->top_pipe && - pipe_ctx->top_pipe->surface == pipe_ctx->surface; - if (sec_split && surface->address.type == PLN_ADDR_TYPE_GRPH_STEREO && + pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state; + if (sec_split && plane_state->address.type == PLN_ADDR_TYPE_GRPH_STEREO && (pipe_ctx->stream->timing.timing_3d_format == TIMING_3D_FORMAT_SIDE_BY_SIDE || pipe_ctx->stream->timing.timing_3d_format == TIMING_3D_FORMAT_TOP_AND_BOTTOM)) { - *addr = surface->address.grph_stereo.left_addr; - surface->address.grph_stereo.left_addr = - surface->address.grph_stereo.right_addr; + *addr = plane_state->address.grph_stereo.left_addr; + plane_state->address.grph_stereo.left_addr = + plane_state->address.grph_stereo.right_addr; return true; } else { if (pipe_ctx->stream->view_format != VIEW_3D_FORMAT_NONE && - surface->address.type != PLN_ADDR_TYPE_GRPH_STEREO) { - surface->address.type = PLN_ADDR_TYPE_GRPH_STEREO; - surface->address.grph_stereo.right_addr = - surface->address.grph_stereo.left_addr; + plane_state->address.type != PLN_ADDR_TYPE_GRPH_STEREO) { + plane_state->address.type = PLN_ADDR_TYPE_GRPH_STEREO; + plane_state->address.grph_stereo.right_addr = + plane_state->address.grph_stereo.left_addr; } } return false; @@ -1065,22 +1065,22 @@ static void update_plane_addr(const struct core_dc *dc, struct pipe_ctx *pipe_ct { bool addr_patched = false; PHYSICAL_ADDRESS_LOC addr; - struct dc_plane_state *surface = pipe_ctx->surface; + struct dc_plane_state *plane_state = pipe_ctx->plane_state; - if (surface == NULL) + if (plane_state == NULL) return; addr_patched = patch_address_for_sbs_tb_stereo(pipe_ctx, &addr); pipe_ctx->mi->funcs->mem_input_program_surface_flip_and_addr( pipe_ctx->mi, - &surface->address, - surface->flip_immediate); - surface->status.requested_address = surface->address; + &plane_state->address, + plane_state->flip_immediate); + plane_state->status.requested_address = plane_state->address; if (addr_patched) - pipe_ctx->surface->address.grph_stereo.left_addr = addr; + pipe_ctx->plane_state->address.grph_stereo.left_addr = addr; } static bool dcn10_set_input_transfer_func( - struct pipe_ctx *pipe_ctx, const struct dc_plane_state *surface) + struct pipe_ctx *pipe_ctx, const struct dc_plane_state *plane_state) { struct input_pixel_processor *ipp = pipe_ctx->ipp; const struct dc_transfer_func *tf = NULL; @@ -1089,12 +1089,12 @@ static bool dcn10_set_input_transfer_func( if (ipp == NULL) return false; - if (surface->in_transfer_func) - tf = surface->in_transfer_func; + if (plane_state->in_transfer_func) + tf = plane_state->in_transfer_func; - if (surface->gamma_correction && dce_use_lut(surface)) + if (plane_state->gamma_correction && dce_use_lut(plane_state)) ipp->funcs->ipp_program_input_lut(ipp, - surface->gamma_correction); + plane_state->gamma_correction); if (tf == NULL) ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS); @@ -1689,7 +1689,7 @@ static void dcn10_power_on_fe( struct pipe_ctx *pipe_ctx, struct validate_context *context) { - struct dc_plane_state *dc_surface = pipe_ctx->surface; + struct dc_plane_state *plane_state = pipe_ctx->plane_state; struct dce_hwseq *hws = dc->hwseq; power_on_plane(dc->hwseq, @@ -1704,24 +1704,24 @@ static void dcn10_power_on_fe( OPP_PIPE_CLOCK_EN, 1); /*TODO: REG_UPDATE(DENTIST_DISPCLK_CNTL, DENTIST_DPPCLK_WDIVIDER, 0x1f);*/ - if (dc_surface) { + if (plane_state) { dm_logger_write(dc->ctx->logger, LOG_DC, "Pipe:%d 0x%x: addr hi:0x%x, " "addr low:0x%x, " "src: %d, %d, %d," " %d; dst: %d, %d, %d, %d;\n", pipe_ctx->pipe_idx, - dc_surface, - dc_surface->address.grph.addr.high_part, - dc_surface->address.grph.addr.low_part, - dc_surface->src_rect.x, - dc_surface->src_rect.y, - dc_surface->src_rect.width, - dc_surface->src_rect.height, - dc_surface->dst_rect.x, - dc_surface->dst_rect.y, - dc_surface->dst_rect.width, - dc_surface->dst_rect.height); + plane_state, + plane_state->address.grph.addr.high_part, + plane_state->address.grph.addr.low_part, + plane_state->src_rect.x, + plane_state->src_rect.y, + plane_state->src_rect.width, + plane_state->src_rect.height, + plane_state->dst_rect.x, + plane_state->dst_rect.y, + plane_state->dst_rect.width, + plane_state->dst_rect.height); dm_logger_write(dc->ctx->logger, LOG_HW_SET_MODE, "Pipe %d: width, height, x, y\n" @@ -1805,7 +1805,7 @@ static void program_csc_matrix(struct pipe_ctx *pipe_ctx, } static bool is_lower_pipe_tree_visible(struct pipe_ctx *pipe_ctx) { - if (pipe_ctx->surface->visible) + if (pipe_ctx->plane_state->visible) return true; if (pipe_ctx->bottom_pipe && is_lower_pipe_tree_visible(pipe_ctx->bottom_pipe)) return true; @@ -1814,7 +1814,7 @@ static bool is_lower_pipe_tree_visible(struct pipe_ctx *pipe_ctx) static bool is_upper_pipe_tree_visible(struct pipe_ctx *pipe_ctx) { - if (pipe_ctx->surface->visible) + if (pipe_ctx->plane_state->visible) return true; if (pipe_ctx->top_pipe && is_upper_pipe_tree_visible(pipe_ctx->top_pipe)) return true; @@ -1823,7 +1823,7 @@ static bool is_upper_pipe_tree_visible(struct pipe_ctx *pipe_ctx) static bool is_pipe_tree_visible(struct pipe_ctx *pipe_ctx) { - if (pipe_ctx->surface->visible) + if (pipe_ctx->plane_state->visible) return true; if (pipe_ctx->top_pipe && is_upper_pipe_tree_visible(pipe_ctx->top_pipe)) return true; @@ -1898,12 +1898,12 @@ static void update_dchubp_dpp( struct dce_hwseq *hws = dc->hwseq; struct mem_input *mi = pipe_ctx->mi; struct input_pixel_processor *ipp = pipe_ctx->ipp; - struct dc_plane_state *surface = pipe_ctx->surface; - union plane_size size = surface->plane_size; + struct dc_plane_state *plane_state = pipe_ctx->plane_state; + union plane_size size = plane_state->plane_size; struct default_adjustment ocsc = {0}; struct mpcc_cfg mpcc_cfg = {0}; struct pipe_ctx *top_pipe; - bool per_pixel_alpha = surface->per_pixel_alpha && pipe_ctx->bottom_pipe; + bool per_pixel_alpha = plane_state->per_pixel_alpha && pipe_ctx->bottom_pipe; /* TODO: proper fix once fpga works */ /* depends on DML calculation, DPP clock value may change dynamically */ @@ -1936,12 +1936,12 @@ static void update_dchubp_dpp( if (dc->public.config.gpu_vm_support) mi->funcs->mem_input_program_pte_vm( pipe_ctx->mi, - surface->format, - &surface->tiling_info, - surface->rotation); + plane_state->format, + &plane_state->tiling_info, + plane_state->rotation); ipp->funcs->ipp_setup(ipp, - surface->format, + plane_state->format, 1, IPP_OUTPUT_FORMAT_12_BIT_FIX); @@ -1982,12 +1982,12 @@ static void update_dchubp_dpp( mi->funcs->mem_input_program_surface_config( mi, - surface->format, - &surface->tiling_info, + plane_state->format, + &plane_state->tiling_info, &size, - surface->rotation, - &surface->dcc, - surface->horizontal_mirror); + plane_state->rotation, + &plane_state->dcc, + plane_state->horizontal_mirror); mi->funcs->set_blank(mi, !is_pipe_tree_visible(pipe_ctx)); } @@ -2025,7 +2025,7 @@ static void program_all_pipe_in_tree( pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, !is_pipe_tree_visible(pipe_ctx)); } - if (pipe_ctx->surface != NULL) { + if (pipe_ctx->plane_state != NULL) { dcn10_power_on_fe(dc, pipe_ctx, context); update_dchubp_dpp(dc, pipe_ctx, context); } @@ -2068,7 +2068,7 @@ static void dcn10_pplib_apply_display_requirements( static void dcn10_apply_ctx_for_surface( struct core_dc *dc, - const struct dc_plane_state *surface, + const struct dc_plane_state *plane_state, struct validate_context *context) { int i, be_idx; @@ -2076,11 +2076,11 @@ static void dcn10_apply_ctx_for_surface( if (dc->public.debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); - if (!surface) + if (!plane_state) return; for (be_idx = 0; be_idx < dc->res_pool->pipe_count; be_idx++) - if (surface == context->res_ctx.pipe_ctx[be_idx].surface) + if (plane_state == context->res_ctx.pipe_ctx[be_idx].plane_state) break; /* reset unused mpcc */ @@ -2089,7 +2089,7 @@ static void dcn10_apply_ctx_for_surface( struct pipe_ctx *old_pipe_ctx = &dc->current_context->res_ctx.pipe_ctx[i]; - if (!pipe_ctx->surface && !old_pipe_ctx->surface) + if (!pipe_ctx->plane_state && !old_pipe_ctx->plane_state) continue; /* @@ -2097,7 +2097,7 @@ static void dcn10_apply_ctx_for_surface( * fairly hacky right now, using opp_id as indicator */ - if (pipe_ctx->surface && !old_pipe_ctx->surface) { + if (pipe_ctx->plane_state && !old_pipe_ctx->plane_state) { if (pipe_ctx->mi->opp_id != 0xf && pipe_ctx->tg->inst == be_idx) { dcn10_power_down_fe(dc, pipe_ctx->pipe_idx); /* @@ -2109,7 +2109,7 @@ static void dcn10_apply_ctx_for_surface( } - if ((!pipe_ctx->surface && old_pipe_ctx->surface) + if ((!pipe_ctx->plane_state && old_pipe_ctx->plane_state) || (!pipe_ctx->stream && old_pipe_ctx->stream)) { if (old_pipe_ctx->tg->inst != be_idx) continue; @@ -2135,7 +2135,7 @@ static void dcn10_apply_ctx_for_surface( old_pipe_ctx->top_pipe = NULL; old_pipe_ctx->bottom_pipe = NULL; - old_pipe_ctx->surface = NULL; + old_pipe_ctx->plane_state = NULL; dm_logger_write(dc->ctx->logger, LOG_DC, "Reset mpcc for pipe %d\n", @@ -2146,7 +2146,7 @@ static void dcn10_apply_ctx_for_surface( for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; - if (pipe_ctx->surface != surface) + if (pipe_ctx->plane_state != plane_state) continue; /* looking for top pipe to program */ @@ -2468,34 +2468,34 @@ static bool dcn10_dummy_display_power_gating( void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx) { - struct dc_plane_state *surface = pipe_ctx->surface; + struct dc_plane_state *plane_state = pipe_ctx->plane_state; struct timing_generator *tg = pipe_ctx->tg; - if (surface->ctx->dc->debug.sanity_checks) { - struct core_dc *dc = DC_TO_CORE(surface->ctx->dc); + if (plane_state->ctx->dc->debug.sanity_checks) { + struct core_dc *dc = DC_TO_CORE(plane_state->ctx->dc); verify_allow_pstate_change_high(dc->hwseq); } - if (surface == NULL) + if (plane_state == NULL) return; - surface->status.is_flip_pending = + plane_state->status.is_flip_pending = pipe_ctx->mi->funcs->mem_input_is_flip_pending( pipe_ctx->mi); /* DCN we read INUSE address in MI, do we still need this wa? */ - if (surface->status.is_flip_pending && - !surface->visible) { + if (plane_state->status.is_flip_pending && + !plane_state->visible) { pipe_ctx->mi->current_address = pipe_ctx->mi->request_address; BREAK_TO_DEBUGGER(); } - surface->status.current_address = pipe_ctx->mi->current_address; + plane_state->status.current_address = pipe_ctx->mi->current_address; if (pipe_ctx->mi->current_address.type == PLN_ADDR_TYPE_GRPH_STEREO && tg->funcs->is_stereo_left_eye) { - surface->status.is_right_eye = + plane_state->status.is_right_eye = !tg->funcs->is_stereo_left_eye(pipe_ctx->tg); } } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 5a9fcbc22d04..3fe6df92f91f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -1406,7 +1406,7 @@ static bool construct( goto res_create_fail; dcn10_hw_sequencer_construct(dc); - dc->public.caps.max_surfaces = pool->base.pipe_count; + dc->public.caps.max_planes = pool->base.pipe_count; dc->public.cap_funcs = cap_funcs; diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index d5c0f9e34ce9..3b3330c563e0 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -36,7 +36,7 @@ #define MAX_CLOCK_SOURCES 7 -void enable_surface_flip_reporting(struct dc_plane_state *dc_surface, +void enable_surface_flip_reporting(struct dc_plane_state *plane_state, uint32_t controller_id); #include "grph_object_id.h" @@ -153,7 +153,7 @@ struct resource_pool { }; struct pipe_ctx { - struct dc_plane_state *surface; + struct dc_plane_state *plane_state; struct dc_stream_state *stream; struct mem_input *mi; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 7e03f8d45b2b..5d075f93b4b9 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -59,7 +59,7 @@ struct hw_sequencer_funcs { void (*apply_ctx_for_surface)( struct core_dc *dc, - const struct dc_plane_state *surface, + const struct dc_plane_state *plane_state, struct validate_context *context); void (*set_plane_config)( @@ -88,7 +88,7 @@ struct hw_sequencer_funcs { bool (*set_input_transfer_func)( struct pipe_ctx *pipe_ctx, - const struct dc_plane_state *surface); + const struct dc_plane_state *plane_state); bool (*set_output_transfer_func)( struct pipe_ctx *pipe_ctx, diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index aef1197cf749..7f30d9937d10 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -119,7 +119,7 @@ struct pipe_ctx *resource_get_head_pipe_for_stream( struct dc_stream_state *stream); bool resource_attach_surfaces_to_context( - struct dc_plane_state *const *surfaces, + struct dc_plane_state *const *plane_state, int surface_count, struct dc_stream_state *dc_stream, struct validate_context *context, diff --git a/drivers/gpu/drm/amd/display/include/logger_interface.h b/drivers/gpu/drm/amd/display/include/logger_interface.h index 0e978d921fdf..beb790937769 100644 --- a/drivers/gpu/drm/amd/display/include/logger_interface.h +++ b/drivers/gpu/drm/amd/display/include/logger_interface.h @@ -77,7 +77,7 @@ void logger_write(struct dal_logger *logger, void pre_surface_trace( const struct dc *dc, - const struct dc_plane_state *const *surfaces, + const struct dc_plane_state *const *plane_states, int surface_count); void update_surface_trace( -- cgit From 0a8f43ff64156525f98220efe0992925995153b6 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Sun, 30 Jul 2017 13:19:56 -0400 Subject: drm/amd/display: Remove struct from stack in dp_set_test_pattern Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') 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 50724f9a8e2c..231cade5e1fd 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 @@ -2407,7 +2407,7 @@ bool dc_link_dp_set_test_pattern( unsigned int cust_pattern_size) { struct pipe_ctx *pipes = link->dc->current_context->res_ctx.pipe_ctx; - struct pipe_ctx pipe_ctx = pipes[0]; + struct pipe_ctx *pipe_ctx = &pipes[0]; unsigned int lane; unsigned int i; unsigned char link_qual_pattern[LANE_COUNT_DP_MAX] = {0}; @@ -2418,7 +2418,7 @@ bool dc_link_dp_set_test_pattern( for (i = 0; i < MAX_PIPES; i++) { if (pipes[i].stream->sink->link == link) { - pipe_ctx = pipes[i]; + pipe_ctx = &pipes[i]; break; } } @@ -2430,14 +2430,14 @@ bool dc_link_dp_set_test_pattern( if (link->test_pattern_enabled && test_pattern == DP_TEST_PATTERN_VIDEO_MODE) { /* Set CRTC Test Pattern */ - set_crtc_test_pattern(link, &pipe_ctx, test_pattern); + set_crtc_test_pattern(link, pipe_ctx, test_pattern); dp_set_hw_test_pattern(link, test_pattern, (uint8_t *)p_custom_pattern, (uint32_t)cust_pattern_size); /* Unblank Stream */ link->dc->hwss.unblank_stream( - &pipe_ctx, + pipe_ctx, &link->verified_link_cap); /* TODO:m_pHwss->MuteAudioEndpoint * (pPathMode->pDisplayPath, false); @@ -2464,7 +2464,7 @@ bool dc_link_dp_set_test_pattern( * MuteAudioEndpoint(pPathMode->pDisplayPath, true); */ /* Blank stream */ - pipes->stream_enc->funcs->dp_blank(pipe_ctx.stream_enc); + pipes->stream_enc->funcs->dp_blank(pipe_ctx->stream_enc); } dp_set_hw_test_pattern(link, test_pattern, @@ -2545,7 +2545,7 @@ bool dc_link_dp_set_test_pattern( } } else { /* CRTC Patterns */ - set_crtc_test_pattern(link, &pipe_ctx, test_pattern); + set_crtc_test_pattern(link, pipe_ctx, test_pattern); /* Set Test Pattern state */ link->test_pattern_enabled = true; } -- cgit From 79b06f0ce58cc6eb7cd8ad83c308fa59ccb355e0 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Sun, 30 Jul 2017 11:43:06 -0400 Subject: drm/amd/display: Stub new resource objects We want to split pipe_ctx into plane and stream resource objects. Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 3b3330c563e0..6c937411af23 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -152,10 +152,21 @@ struct resource_pool { const struct resource_caps *res_cap; }; +struct stream_resource { + int stub; +}; + +struct plane_resource { + int stub; +}; + struct pipe_ctx { struct dc_plane_state *plane_state; struct dc_stream_state *stream; + struct plane_resource plane_res; + struct stream_resource stream_res; + struct mem_input *mi; struct input_pixel_processor *ipp; struct transform *xfm; -- cgit From 6702a9ac53f88a373a9969b4dee292f4c5f023f5 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Sun, 30 Jul 2017 11:51:21 -0400 Subject: drm/amd/display: Move scl_data to plane_res find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/\.scl_data/\.plane_res.scl_data/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/->scl_data/->plane_res.scl_data/g' Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c | 36 ++++---- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 84 ++++++++--------- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 100 ++++++++++----------- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 6 +- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 34 +++---- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 28 +++--- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 4 +- 7 files changed, 145 insertions(+), 147 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c index 28dbd18b2d86..dba25853f7f9 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c @@ -2613,13 +2613,13 @@ static void populate_initial_data( data->h_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->timing.h_total); data->v_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->timing.v_total); data->pixel_rate[num_displays + 4] = bw_frc_to_fixed(pipe[i].stream->timing.pix_clk_khz, 1000); - data->src_width[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.viewport.width); + data->src_width[num_displays + 4] = bw_int_to_fixed(pipe[i].plane_res.scl_data.viewport.width); data->pitch_in_pixels[num_displays + 4] = data->src_width[num_displays + 4]; - data->src_height[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.viewport.height); - data->h_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.taps.h_taps); - data->v_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.taps.v_taps); - data->h_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].scl_data.ratios.horz.value); - data->v_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].scl_data.ratios.vert.value); + data->src_height[num_displays + 4] = bw_int_to_fixed(pipe[i].plane_res.scl_data.viewport.height); + data->h_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].plane_res.scl_data.taps.h_taps); + data->v_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].plane_res.scl_data.taps.v_taps); + data->h_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].plane_res.scl_data.ratios.horz.value); + data->v_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].plane_res.scl_data.ratios.vert.value); switch (pipe[i].plane_state->rotation) { case ROTATION_ANGLE_0: data->rotation_angle[num_displays + 4] = bw_int_to_fixed(0); @@ -2667,16 +2667,16 @@ static void populate_initial_data( data->fbc_en[num_displays * 2 + j] = false; data->lpt_en[num_displays * 2 + j] = false; - data->src_height[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->scl_data.viewport.height); - data->src_width[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->scl_data.viewport.width); + data->src_height[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->plane_res.scl_data.viewport.height); + data->src_width[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->plane_res.scl_data.viewport.width); data->pitch_in_pixels[num_displays * 2 + j] = bw_int_to_fixed( pipe[i].bottom_pipe->plane_state->plane_size.grph.surface_pitch); - data->h_taps[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->scl_data.taps.h_taps); - data->v_taps[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->scl_data.taps.v_taps); + data->h_taps[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->plane_res.scl_data.taps.h_taps); + data->v_taps[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->plane_res.scl_data.taps.v_taps); data->h_scale_ratio[num_displays * 2 + j] = fixed31_32_to_bw_fixed( - pipe[i].bottom_pipe->scl_data.ratios.horz.value); + pipe[i].bottom_pipe->plane_res.scl_data.ratios.horz.value); data->v_scale_ratio[num_displays * 2 + j] = fixed31_32_to_bw_fixed( - pipe[i].bottom_pipe->scl_data.ratios.vert.value); + pipe[i].bottom_pipe->plane_res.scl_data.ratios.vert.value); switch (pipe[i].bottom_pipe->plane_state->rotation) { case ROTATION_ANGLE_0: data->rotation_angle[num_displays * 2 + j] = bw_int_to_fixed(0); @@ -2711,13 +2711,13 @@ static void populate_initial_data( data->v_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->timing.v_total); data->pixel_rate[num_displays + 4] = bw_frc_to_fixed(pipe[i].stream->timing.pix_clk_khz, 1000); if (pipe[i].plane_state) { - data->src_width[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.viewport.width); + data->src_width[num_displays + 4] = bw_int_to_fixed(pipe[i].plane_res.scl_data.viewport.width); data->pitch_in_pixels[num_displays + 4] = data->src_width[num_displays + 4]; - data->src_height[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.viewport.height); - data->h_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.taps.h_taps); - data->v_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.taps.v_taps); - data->h_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].scl_data.ratios.horz.value); - data->v_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].scl_data.ratios.vert.value); + data->src_height[num_displays + 4] = bw_int_to_fixed(pipe[i].plane_res.scl_data.viewport.height); + data->h_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].plane_res.scl_data.taps.h_taps); + data->v_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].plane_res.scl_data.taps.v_taps); + data->h_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].plane_res.scl_data.ratios.horz.value); + data->v_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].plane_res.scl_data.ratios.vert.value); switch (pipe[i].plane_state->rotation) { case ROTATION_ANGLE_0: data->rotation_angle[num_displays + 4] = bw_int_to_fixed(0); diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 404b39e7b44b..cb762006e1c3 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -244,10 +244,10 @@ static void pipe_ctx_to_e2e_pipe_params ( input->src.source_scan = dm_horz; input->src.sw_mode = pipe->plane_state->tiling_info.gfx9.swizzle; - input->src.viewport_width = pipe->scl_data.viewport.width; - input->src.viewport_height = pipe->scl_data.viewport.height; - input->src.data_pitch = pipe->scl_data.viewport.width; - input->src.data_pitch_c = pipe->scl_data.viewport.width; + input->src.viewport_width = pipe->plane_res.scl_data.viewport.width; + input->src.viewport_height = pipe->plane_res.scl_data.viewport.height; + input->src.data_pitch = pipe->plane_res.scl_data.viewport.width; + input->src.data_pitch_c = pipe->plane_res.scl_data.viewport.width; input->src.cur0_src_width = 128; /* TODO: Cursor calcs, not curently stored */ input->src.cur0_bpp = 32; @@ -341,21 +341,21 @@ static void pipe_ctx_to_e2e_pipe_params ( break; } - input->scale_taps.htaps = pipe->scl_data.taps.h_taps; - input->scale_ratio_depth.hscl_ratio = pipe->scl_data.ratios.horz.value/4294967296.0; - input->scale_ratio_depth.vscl_ratio = pipe->scl_data.ratios.vert.value/4294967296.0; - input->scale_ratio_depth.vinit = pipe->scl_data.inits.v.value/4294967296.0; + input->scale_taps.htaps = pipe->plane_res.scl_data.taps.h_taps; + input->scale_ratio_depth.hscl_ratio = pipe->plane_res.scl_data.ratios.horz.value/4294967296.0; + input->scale_ratio_depth.vscl_ratio = pipe->plane_res.scl_data.ratios.vert.value/4294967296.0; + input->scale_ratio_depth.vinit = pipe->plane_res.scl_data.inits.v.value/4294967296.0; if (input->scale_ratio_depth.vinit < 1.0) input->scale_ratio_depth.vinit = 1; - input->scale_taps.vtaps = pipe->scl_data.taps.v_taps; - input->scale_taps.vtaps_c = pipe->scl_data.taps.v_taps_c; - input->scale_taps.htaps_c = pipe->scl_data.taps.h_taps_c; - input->scale_ratio_depth.hscl_ratio_c = pipe->scl_data.ratios.horz_c.value/4294967296.0; - input->scale_ratio_depth.vscl_ratio_c = pipe->scl_data.ratios.vert_c.value/4294967296.0; - input->scale_ratio_depth.vinit_c = pipe->scl_data.inits.v_c.value/4294967296.0; + input->scale_taps.vtaps = pipe->plane_res.scl_data.taps.v_taps; + input->scale_taps.vtaps_c = pipe->plane_res.scl_data.taps.v_taps_c; + input->scale_taps.htaps_c = pipe->plane_res.scl_data.taps.h_taps_c; + input->scale_ratio_depth.hscl_ratio_c = pipe->plane_res.scl_data.ratios.horz_c.value/4294967296.0; + input->scale_ratio_depth.vscl_ratio_c = pipe->plane_res.scl_data.ratios.vert_c.value/4294967296.0; + input->scale_ratio_depth.vinit_c = pipe->plane_res.scl_data.inits.v_c.value/4294967296.0; if (input->scale_ratio_depth.vinit_c < 1.0) input->scale_ratio_depth.vinit_c = 1; - switch (pipe->scl_data.lb_params.depth) { + switch (pipe->plane_res.scl_data.lb_params.depth) { case LB_PIXEL_DEPTH_30BPP: input->scale_ratio_depth.lb_depth = 30; break; case LB_PIXEL_DEPTH_36BPP: @@ -367,11 +367,11 @@ static void pipe_ctx_to_e2e_pipe_params ( input->dest.vactive = pipe->stream->timing.v_addressable; - input->dest.recout_width = pipe->scl_data.recout.width; - input->dest.recout_height = pipe->scl_data.recout.height; + input->dest.recout_width = pipe->plane_res.scl_data.recout.width; + input->dest.recout_height = pipe->plane_res.scl_data.recout.height; - input->dest.full_recout_width = pipe->scl_data.recout.width; - input->dest.full_recout_height = pipe->scl_data.recout.height; + input->dest.full_recout_width = pipe->plane_res.scl_data.recout.width; + input->dest.full_recout_height = pipe->plane_res.scl_data.recout.height; input->dest.htotal = pipe->stream->timing.h_total; input->dest.hblank_start = input->dest.htotal - pipe->stream->timing.h_front_porch; @@ -885,38 +885,38 @@ bool dcn_validate_bandwidth( v->source_scan[input_idx] = dcn_bw_hor; } else { - v->viewport_height[input_idx] = pipe->scl_data.viewport.height; - v->viewport_width[input_idx] = pipe->scl_data.viewport.width; - v->scaler_rec_out_width[input_idx] = pipe->scl_data.recout.width; - v->scaler_recout_height[input_idx] = pipe->scl_data.recout.height; + v->viewport_height[input_idx] = pipe->plane_res.scl_data.viewport.height; + v->viewport_width[input_idx] = pipe->plane_res.scl_data.viewport.width; + v->scaler_rec_out_width[input_idx] = pipe->plane_res.scl_data.recout.width; + v->scaler_recout_height[input_idx] = pipe->plane_res.scl_data.recout.height; if (pipe->bottom_pipe && pipe->bottom_pipe->plane_state == pipe->plane_state) { if (pipe->plane_state->rotation % 2 == 0) { - int viewport_end = pipe->scl_data.viewport.width - + pipe->scl_data.viewport.x; - int viewport_b_end = pipe->bottom_pipe->scl_data.viewport.width - + pipe->bottom_pipe->scl_data.viewport.x; + int viewport_end = pipe->plane_res.scl_data.viewport.width + + pipe->plane_res.scl_data.viewport.x; + int viewport_b_end = pipe->bottom_pipe->plane_res.scl_data.viewport.width + + pipe->bottom_pipe->plane_res.scl_data.viewport.x; if (viewport_end > viewport_b_end) v->viewport_width[input_idx] = viewport_end - - pipe->bottom_pipe->scl_data.viewport.x; + - pipe->bottom_pipe->plane_res.scl_data.viewport.x; else v->viewport_width[input_idx] = viewport_b_end - - pipe->scl_data.viewport.x; + - pipe->plane_res.scl_data.viewport.x; } else { - int viewport_end = pipe->scl_data.viewport.height - + pipe->scl_data.viewport.y; - int viewport_b_end = pipe->bottom_pipe->scl_data.viewport.height - + pipe->bottom_pipe->scl_data.viewport.y; + int viewport_end = pipe->plane_res.scl_data.viewport.height + + pipe->plane_res.scl_data.viewport.y; + int viewport_b_end = pipe->bottom_pipe->plane_res.scl_data.viewport.height + + pipe->bottom_pipe->plane_res.scl_data.viewport.y; if (viewport_end > viewport_b_end) v->viewport_height[input_idx] = viewport_end - - pipe->bottom_pipe->scl_data.viewport.y; + - pipe->bottom_pipe->plane_res.scl_data.viewport.y; else v->viewport_height[input_idx] = viewport_b_end - - pipe->scl_data.viewport.y; + - pipe->plane_res.scl_data.viewport.y; } - v->scaler_rec_out_width[input_idx] = pipe->scl_data.recout.width - + pipe->bottom_pipe->scl_data.recout.width; + v->scaler_rec_out_width[input_idx] = pipe->plane_res.scl_data.recout.width + + pipe->bottom_pipe->plane_res.scl_data.recout.width; } v->dcc_enable[input_idx] = pipe->plane_state->dcc.enable ? dcn_bw_yes : dcn_bw_no; @@ -924,11 +924,11 @@ bool dcn_validate_bandwidth( pipe->plane_state->format); v->source_surface_mode[input_idx] = tl_sw_mode_to_bw_defs( pipe->plane_state->tiling_info.gfx9.swizzle); - v->lb_bit_per_pixel[input_idx] = tl_lb_bpp_to_int(pipe->scl_data.lb_params.depth); - v->override_hta_ps[input_idx] = pipe->scl_data.taps.h_taps; - v->override_vta_ps[input_idx] = pipe->scl_data.taps.v_taps; - v->override_hta_pschroma[input_idx] = pipe->scl_data.taps.h_taps_c; - v->override_vta_pschroma[input_idx] = pipe->scl_data.taps.v_taps_c; + v->lb_bit_per_pixel[input_idx] = tl_lb_bpp_to_int(pipe->plane_res.scl_data.lb_params.depth); + v->override_hta_ps[input_idx] = pipe->plane_res.scl_data.taps.h_taps; + v->override_vta_ps[input_idx] = pipe->plane_res.scl_data.taps.v_taps; + v->override_hta_pschroma[input_idx] = pipe->plane_res.scl_data.taps.h_taps_c; + v->override_vta_pschroma[input_idx] = pipe->plane_res.scl_data.taps.v_taps_c; v->source_scan[input_idx] = (pipe->plane_state->rotation % 2) ? dcn_bw_vert : dcn_bw_hor; } if (v->is_line_buffer_bpp_fixed == dcn_bw_yes) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 4eef400cb551..84a15a999117 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -432,7 +432,7 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) { const struct dc_plane_state *plane_state = pipe_ctx->plane_state; const struct dc_stream_state *stream = pipe_ctx->stream; - struct scaler_data *data = &pipe_ctx->scl_data; + struct scaler_data *data = &pipe_ctx->plane_res.scl_data; struct rect surf_src = plane_state->src_rect; struct rect clip = { 0 }; int vpc_div = (data->format == PIXEL_FORMAT_420BPP8 @@ -539,53 +539,53 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) rect_swap_helper(&surf_src); - pipe_ctx->scl_data.recout.x = stream->dst.x; + pipe_ctx->plane_res.scl_data.recout.x = stream->dst.x; if (stream->src.x < surf_clip.x) - pipe_ctx->scl_data.recout.x += (surf_clip.x + pipe_ctx->plane_res.scl_data.recout.x += (surf_clip.x - stream->src.x) * stream->dst.width / stream->src.width; - pipe_ctx->scl_data.recout.width = surf_clip.width * + pipe_ctx->plane_res.scl_data.recout.width = surf_clip.width * stream->dst.width / stream->src.width; - if (pipe_ctx->scl_data.recout.width + pipe_ctx->scl_data.recout.x > + if (pipe_ctx->plane_res.scl_data.recout.width + pipe_ctx->plane_res.scl_data.recout.x > stream->dst.x + stream->dst.width) - pipe_ctx->scl_data.recout.width = + pipe_ctx->plane_res.scl_data.recout.width = stream->dst.x + stream->dst.width - - pipe_ctx->scl_data.recout.x; + - pipe_ctx->plane_res.scl_data.recout.x; - pipe_ctx->scl_data.recout.y = stream->dst.y; + pipe_ctx->plane_res.scl_data.recout.y = stream->dst.y; if (stream->src.y < surf_clip.y) - pipe_ctx->scl_data.recout.y += (surf_clip.y + pipe_ctx->plane_res.scl_data.recout.y += (surf_clip.y - stream->src.y) * stream->dst.height / stream->src.height; - pipe_ctx->scl_data.recout.height = surf_clip.height * + pipe_ctx->plane_res.scl_data.recout.height = surf_clip.height * stream->dst.height / stream->src.height; - if (pipe_ctx->scl_data.recout.height + pipe_ctx->scl_data.recout.y > + if (pipe_ctx->plane_res.scl_data.recout.height + pipe_ctx->plane_res.scl_data.recout.y > stream->dst.y + stream->dst.height) - pipe_ctx->scl_data.recout.height = + pipe_ctx->plane_res.scl_data.recout.height = stream->dst.y + stream->dst.height - - pipe_ctx->scl_data.recout.y; + - pipe_ctx->plane_res.scl_data.recout.y; /* Handle h & vsplit */ if (pipe_ctx->top_pipe && pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state) { if (stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) { - pipe_ctx->scl_data.recout.height /= 2; - pipe_ctx->scl_data.recout.y += pipe_ctx->scl_data.recout.height; + pipe_ctx->plane_res.scl_data.recout.height /= 2; + pipe_ctx->plane_res.scl_data.recout.y += pipe_ctx->plane_res.scl_data.recout.height; /* Floor primary pipe, ceil 2ndary pipe */ - pipe_ctx->scl_data.recout.height += pipe_ctx->scl_data.recout.height % 2; + pipe_ctx->plane_res.scl_data.recout.height += pipe_ctx->plane_res.scl_data.recout.height % 2; } else { - pipe_ctx->scl_data.recout.width /= 2; - pipe_ctx->scl_data.recout.x += pipe_ctx->scl_data.recout.width; - pipe_ctx->scl_data.recout.width += pipe_ctx->scl_data.recout.width % 2; + pipe_ctx->plane_res.scl_data.recout.width /= 2; + pipe_ctx->plane_res.scl_data.recout.x += pipe_ctx->plane_res.scl_data.recout.width; + pipe_ctx->plane_res.scl_data.recout.width += pipe_ctx->plane_res.scl_data.recout.width % 2; } } else if (pipe_ctx->bottom_pipe && pipe_ctx->bottom_pipe->plane_state == pipe_ctx->plane_state) { if (stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) - pipe_ctx->scl_data.recout.height /= 2; + pipe_ctx->plane_res.scl_data.recout.height /= 2; else - pipe_ctx->scl_data.recout.width /= 2; + pipe_ctx->plane_res.scl_data.recout.width /= 2; } /* Unclipped recout offset = stream dst offset + ((surf dst offset - stream surf_src offset) @@ -601,8 +601,8 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip surf_src.y * plane_state->dst_rect.height / surf_src.height * stream->dst.height / stream->src.height; - recout_skip->width = pipe_ctx->scl_data.recout.x - recout_full_x; - recout_skip->height = pipe_ctx->scl_data.recout.y - recout_full_y; + recout_skip->width = pipe_ctx->plane_res.scl_data.recout.x - recout_full_x; + recout_skip->height = pipe_ctx->plane_res.scl_data.recout.y - recout_full_y; } static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) @@ -619,36 +619,36 @@ static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) rect_swap_helper(&surf_src); - pipe_ctx->scl_data.ratios.horz = dal_fixed31_32_from_fraction( + pipe_ctx->plane_res.scl_data.ratios.horz = dal_fixed31_32_from_fraction( surf_src.width, plane_state->dst_rect.width); - pipe_ctx->scl_data.ratios.vert = dal_fixed31_32_from_fraction( + pipe_ctx->plane_res.scl_data.ratios.vert = dal_fixed31_32_from_fraction( surf_src.height, plane_state->dst_rect.height); if (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE) - pipe_ctx->scl_data.ratios.horz.value *= 2; + pipe_ctx->plane_res.scl_data.ratios.horz.value *= 2; else if (stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) - pipe_ctx->scl_data.ratios.vert.value *= 2; + pipe_ctx->plane_res.scl_data.ratios.vert.value *= 2; - pipe_ctx->scl_data.ratios.vert.value = div64_s64( - pipe_ctx->scl_data.ratios.vert.value * in_h, out_h); - pipe_ctx->scl_data.ratios.horz.value = div64_s64( - pipe_ctx->scl_data.ratios.horz.value * in_w, out_w); + pipe_ctx->plane_res.scl_data.ratios.vert.value = div64_s64( + pipe_ctx->plane_res.scl_data.ratios.vert.value * in_h, out_h); + pipe_ctx->plane_res.scl_data.ratios.horz.value = div64_s64( + pipe_ctx->plane_res.scl_data.ratios.horz.value * in_w, out_w); - pipe_ctx->scl_data.ratios.horz_c = pipe_ctx->scl_data.ratios.horz; - pipe_ctx->scl_data.ratios.vert_c = pipe_ctx->scl_data.ratios.vert; + pipe_ctx->plane_res.scl_data.ratios.horz_c = pipe_ctx->plane_res.scl_data.ratios.horz; + pipe_ctx->plane_res.scl_data.ratios.vert_c = pipe_ctx->plane_res.scl_data.ratios.vert; - if (pipe_ctx->scl_data.format == PIXEL_FORMAT_420BPP8 - || pipe_ctx->scl_data.format == PIXEL_FORMAT_420BPP10) { - pipe_ctx->scl_data.ratios.horz_c.value /= 2; - pipe_ctx->scl_data.ratios.vert_c.value /= 2; + if (pipe_ctx->plane_res.scl_data.format == PIXEL_FORMAT_420BPP8 + || pipe_ctx->plane_res.scl_data.format == PIXEL_FORMAT_420BPP10) { + pipe_ctx->plane_res.scl_data.ratios.horz_c.value /= 2; + pipe_ctx->plane_res.scl_data.ratios.vert_c.value /= 2; } } static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *recout_skip) { - struct scaler_data *data = &pipe_ctx->scl_data; + struct scaler_data *data = &pipe_ctx->plane_res.scl_data; struct rect src = pipe_ctx->plane_state->src_rect; int vpc_div = (data->format == PIXEL_FORMAT_420BPP8 || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1; @@ -823,14 +823,14 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) * lb depth calculation requires recout and taps require scaling ratios. * Inits require viewport, taps, ratios and recout of split pipe */ - pipe_ctx->scl_data.format = convert_pixel_format_to_dalsurface( + pipe_ctx->plane_res.scl_data.format = convert_pixel_format_to_dalsurface( pipe_ctx->plane_state->format); calculate_scaling_ratios(pipe_ctx); calculate_viewport(pipe_ctx); - if (pipe_ctx->scl_data.viewport.height < 16 || pipe_ctx->scl_data.viewport.width < 16) + if (pipe_ctx->plane_res.scl_data.viewport.height < 16 || pipe_ctx->plane_res.scl_data.viewport.width < 16) return false; calculate_recout(pipe_ctx, &recout_skip); @@ -839,21 +839,21 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) * Setting line buffer pixel depth to 24bpp yields banding * on certain displays, such as the Sharp 4k */ - pipe_ctx->scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; + pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; - pipe_ctx->scl_data.h_active = timing->h_addressable; - pipe_ctx->scl_data.v_active = timing->v_addressable; + pipe_ctx->plane_res.scl_data.h_active = timing->h_addressable; + pipe_ctx->plane_res.scl_data.v_active = timing->v_addressable; /* Taps calculations */ res = pipe_ctx->xfm->funcs->transform_get_optimal_number_of_taps( - pipe_ctx->xfm, &pipe_ctx->scl_data, &plane_state->scaling_quality); + pipe_ctx->xfm, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); if (!res) { /* Try 24 bpp linebuffer */ - pipe_ctx->scl_data.lb_params.depth = LB_PIXEL_DEPTH_24BPP; + pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_24BPP; res = pipe_ctx->xfm->funcs->transform_get_optimal_number_of_taps( - pipe_ctx->xfm, &pipe_ctx->scl_data, &plane_state->scaling_quality); + pipe_ctx->xfm, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); } if (res) @@ -865,10 +865,10 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) "y:%d\n dst_rect:\nheight:%d width:%d x:%d " "y:%d\n", __func__, - pipe_ctx->scl_data.viewport.height, - pipe_ctx->scl_data.viewport.width, - pipe_ctx->scl_data.viewport.x, - pipe_ctx->scl_data.viewport.y, + pipe_ctx->plane_res.scl_data.viewport.height, + pipe_ctx->plane_res.scl_data.viewport.width, + pipe_ctx->plane_res.scl_data.viewport.x, + pipe_ctx->plane_res.scl_data.viewport.y, plane_state->dst_rect.height, plane_state->dst_rect.width, plane_state->dst_rect.x, diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 2b6506822cca..ef3a7b83cebe 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -223,9 +223,9 @@ bool dc_stream_set_cursor_position( struct dc_cursor_mi_param param = { .pixel_clk_khz = stream->timing.pix_clk_khz, .ref_clk_khz = core_dc->res_pool->ref_clock_inKhz, - .viewport_x_start = pipe_ctx->scl_data.viewport.x, - .viewport_width = pipe_ctx->scl_data.viewport.width, - .h_scale_ratio = pipe_ctx->scl_data.ratios.horz + .viewport_x_start = pipe_ctx->plane_res.scl_data.viewport.x, + .viewport_width = pipe_ctx->plane_res.scl_data.viewport.width, + .h_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.horz }; if (pipe_ctx->stream != stream || diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index ea9ce87d348a..dee18c92fd52 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -914,7 +914,7 @@ static void get_surface_visual_confirm_color(const struct pipe_ctx *pipe_ctx, { uint32_t color_value = MAX_TG_COLOR_VALUE * (4 - pipe_ctx->pipe_idx) / 4; - switch (pipe_ctx->scl_data.format) { + switch (pipe_ctx->plane_res.scl_data.format) { case PIXEL_FORMAT_ARGB8888: /* set boarder color to red */ color->color_r_cr = color_value; @@ -964,7 +964,7 @@ static void program_scaler(const struct core_dc *dc, pipe_ctx->xfm->funcs->transform_set_pixel_storage_depth( pipe_ctx->xfm, - pipe_ctx->scl_data.lb_params.depth, + pipe_ctx->plane_res.scl_data.lb_params.depth, &pipe_ctx->stream->bit_depth_params); if (pipe_ctx->tg->funcs->set_overscan_blank_color) @@ -973,7 +973,7 @@ static void program_scaler(const struct core_dc *dc, &color); pipe_ctx->xfm->funcs->transform_set_scaler(pipe_ctx->xfm, - &pipe_ctx->scl_data); + &pipe_ctx->plane_res.scl_data); } static enum dc_status dce110_prog_pixclk_crtc_otg( @@ -1114,10 +1114,10 @@ static enum dc_status apply_single_controller_ctx_to_hw( &stream->sink->link->cur_link_settings); } - pipe_ctx->scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; + pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; /* program_scaler and allocate_mem_input are not new asic */ if ((!pipe_ctx_old || - memcmp(&pipe_ctx_old->scl_data, &pipe_ctx->scl_data, + memcmp(&pipe_ctx_old->plane_res.scl_data, &pipe_ctx->plane_res.scl_data, sizeof(struct scaler_data)) != 0) && pipe_ctx->plane_state) { program_scaler(dc, pipe_ctx); @@ -1927,14 +1927,14 @@ static void set_default_colors(struct pipe_ctx *pipe_ctx) default_adjust.out_color_space = pipe_ctx->stream->output_color_space; default_adjust.csc_adjust_type = GRAPHICS_CSC_ADJUST_TYPE_SW; - default_adjust.surface_pixel_format = pipe_ctx->scl_data.format; + default_adjust.surface_pixel_format = pipe_ctx->plane_res.scl_data.format; /* display color depth */ default_adjust.color_depth = pipe_ctx->stream->timing.display_color_depth; /* Lb color depth */ - default_adjust.lb_color_depth = pipe_ctx->scl_data.lb_params.depth; + default_adjust.lb_color_depth = pipe_ctx->plane_res.scl_data.lb_params.depth; pipe_ctx->xfm->funcs->opp_set_csc_default( pipe_ctx->xfm, &default_adjust); @@ -2096,7 +2096,7 @@ static void set_plane_config( pipe_ctx->xfm->funcs->transform_set_gamut_remap(pipe_ctx->xfm, &adjust); - pipe_ctx->scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; + pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; program_scaler(dc, pipe_ctx); program_surface_visibility(dc, pipe_ctx); @@ -2552,7 +2552,7 @@ static void dce110_program_front_end_for_pipe( pipe_ctx->xfm->funcs->transform_set_gamut_remap(pipe_ctx->xfm, &adjust); - pipe_ctx->scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; + pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; program_scaler(dc, pipe_ctx); @@ -2602,14 +2602,14 @@ static void dce110_program_front_end_for_pipe( "viewport:%d, %d, %d, %d\n" "recout: %d, %d, %d, %d\n", pipe_ctx->pipe_idx, - pipe_ctx->scl_data.viewport.width, - pipe_ctx->scl_data.viewport.height, - pipe_ctx->scl_data.viewport.x, - pipe_ctx->scl_data.viewport.y, - pipe_ctx->scl_data.recout.width, - pipe_ctx->scl_data.recout.height, - pipe_ctx->scl_data.recout.x, - pipe_ctx->scl_data.recout.y); + pipe_ctx->plane_res.scl_data.viewport.width, + pipe_ctx->plane_res.scl_data.viewport.height, + pipe_ctx->plane_res.scl_data.viewport.x, + pipe_ctx->plane_res.scl_data.viewport.y, + pipe_ctx->plane_res.scl_data.recout.width, + pipe_ctx->plane_res.scl_data.recout.height, + pipe_ctx->plane_res.scl_data.recout.x, + pipe_ctx->plane_res.scl_data.recout.y); } static void dce110_apply_ctx_for_surface( diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 5922cf8272f5..314d7645a898 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1728,14 +1728,14 @@ static void dcn10_power_on_fe( "viewport:%d, %d, %d, %d\n" "recout: %d, %d, %d, %d\n", pipe_ctx->pipe_idx, - pipe_ctx->scl_data.viewport.width, - pipe_ctx->scl_data.viewport.height, - pipe_ctx->scl_data.viewport.x, - pipe_ctx->scl_data.viewport.y, - pipe_ctx->scl_data.recout.width, - pipe_ctx->scl_data.recout.height, - pipe_ctx->scl_data.recout.x, - pipe_ctx->scl_data.recout.y); + pipe_ctx->plane_res.scl_data.viewport.width, + pipe_ctx->plane_res.scl_data.viewport.height, + pipe_ctx->plane_res.scl_data.viewport.x, + pipe_ctx->plane_res.scl_data.viewport.y, + pipe_ctx->plane_res.scl_data.recout.width, + pipe_ctx->plane_res.scl_data.recout.height, + pipe_ctx->plane_res.scl_data.recout.x, + pipe_ctx->plane_res.scl_data.recout.y); print_rq_dlg_ttu(dc, pipe_ctx); } } @@ -1860,7 +1860,7 @@ static void dcn10_get_surface_visual_confirm_color( { uint32_t color_value = MAX_TG_COLOR_VALUE; - switch (pipe_ctx->scl_data.format) { + switch (pipe_ctx->plane_res.scl_data.format) { case PIXEL_FORMAT_ARGB8888: /* set boarder color to red */ color->color_r_cr = color_value; @@ -1931,7 +1931,7 @@ static void update_dchubp_dpp( &pipe_ctx->rq_regs, &pipe_ctx->pipe_dlg_param); - size.grph.surface_size = pipe_ctx->scl_data.viewport; + size.grph.surface_size = pipe_ctx->plane_res.scl_data.viewport; if (dc->public.config.gpu_vm_support) mi->funcs->mem_input_program_pte_vm( @@ -1965,13 +1965,13 @@ static void update_dchubp_dpp( && per_pixel_alpha; dc->res_pool->mpc->funcs->add(dc->res_pool->mpc, &mpcc_cfg); - pipe_ctx->scl_data.lb_params.alpha_en = per_pixel_alpha; - pipe_ctx->scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; + pipe_ctx->plane_res.scl_data.lb_params.alpha_en = per_pixel_alpha; + pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; /* scaler configuration */ pipe_ctx->xfm->funcs->transform_set_scaler( - pipe_ctx->xfm, &pipe_ctx->scl_data); + pipe_ctx->xfm, &pipe_ctx->plane_res.scl_data); mi->funcs->mem_program_viewport(mi, - &pipe_ctx->scl_data.viewport, &pipe_ctx->scl_data.viewport_c); + &pipe_ctx->plane_res.scl_data.viewport, &pipe_ctx->plane_res.scl_data.viewport_c); /*gamut remap*/ program_gamut_remap(pipe_ctx); diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 6c937411af23..dbca1de89494 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -157,7 +157,7 @@ struct stream_resource { }; struct plane_resource { - int stub; + struct scaler_data scl_data; }; struct pipe_ctx { @@ -173,8 +173,6 @@ struct pipe_ctx { struct output_pixel_processor *opp; struct timing_generator *tg; - struct scaler_data scl_data; - struct stream_encoder *stream_enc; struct display_clock *dis_clk; struct clock_source *clock_source; -- cgit From 86a66c4eb7365c96230bca218634439f7b057306 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Sun, 30 Jul 2017 11:55:55 -0400 Subject: drm/amd/display: Move mi, ipp, xfm to plane_res find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/\.mi/\.plane_res.mi/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/->mi/->plane_res.mi/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/\.ipp/\.plane_res.ipp/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/->ipp/->plane_res.ipp/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/\.xfm/\.plane_res.xfm/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/->xfm/->plane_res.xfm/g' To clean up bad renames: find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/\.plane_res\.min/\.min/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/->plane_res\.min/->min/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/->plane_res\.mic/->mic/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/\.plane_res\.mis/\.mis/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/->plane_res\.mid/->mid/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/\.plane_res\.mid/\.mid/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/->plane_res\.mis/->mis/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/\.plane_res\.min/\.min/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/->plane_res\.min/->min/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/->plane_res\.mic/->mic/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/\.plane_res\.mis/\.mis/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/->plane_res\.mid/->mid/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/\.plane_res\.mid/\.mid/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/->plane_res\.mis/->mis/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/\.plane_res\.ipps/\.ipps/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/mpcc_cfg\.plane_res\.mi/mpcc_cfg\.mi/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/mi->plane_res\./mi->/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/cfg->plane_res\./cfg->/g' Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 6 +- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 20 +++--- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 10 +-- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 80 +++++++++++----------- .../drm/amd/display/dc/dce110/dce110_resource.c | 8 +-- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 40 +++++------ .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 6 +- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 7 +- 8 files changed, 89 insertions(+), 88 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index cb762006e1c3..1922c13d6f22 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -547,9 +547,9 @@ static void split_stream_across_pipes( *secondary_pipe = *primary_pipe; secondary_pipe->pipe_idx = pipe_idx; - secondary_pipe->mi = pool->mis[secondary_pipe->pipe_idx]; - secondary_pipe->ipp = pool->ipps[secondary_pipe->pipe_idx]; - secondary_pipe->xfm = pool->transforms[secondary_pipe->pipe_idx]; + secondary_pipe->plane_res.mi = pool->mis[secondary_pipe->pipe_idx]; + secondary_pipe->plane_res.ipp = pool->ipps[secondary_pipe->pipe_idx]; + secondary_pipe->plane_res.xfm = pool->transforms[secondary_pipe->pipe_idx]; if (primary_pipe->bottom_pipe) { secondary_pipe->bottom_pipe = primary_pipe->bottom_pipe; secondary_pipe->bottom_pipe->top_pipe = secondary_pipe; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 84a15a999117..7270f0de9598 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -845,15 +845,15 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) pipe_ctx->plane_res.scl_data.v_active = timing->v_addressable; /* Taps calculations */ - res = pipe_ctx->xfm->funcs->transform_get_optimal_number_of_taps( - pipe_ctx->xfm, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); + res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps( + pipe_ctx->plane_res.xfm, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); if (!res) { /* Try 24 bpp linebuffer */ pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_24BPP; - res = pipe_ctx->xfm->funcs->transform_get_optimal_number_of_taps( - pipe_ctx->xfm, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); + res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps( + pipe_ctx->plane_res.xfm, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); } if (res) @@ -1012,9 +1012,9 @@ static int acquire_first_split_pipe( memset(pipe_ctx, 0, sizeof(*pipe_ctx)); pipe_ctx->tg = pool->timing_generators[i]; - pipe_ctx->mi = pool->mis[i]; - pipe_ctx->ipp = pool->ipps[i]; - pipe_ctx->xfm = pool->transforms[i]; + pipe_ctx->plane_res.mi = pool->mis[i]; + pipe_ctx->plane_res.ipp = pool->ipps[i]; + pipe_ctx->plane_res.xfm = pool->transforms[i]; pipe_ctx->opp = pool->opps[i]; pipe_ctx->dis_clk = pool->display_clock; pipe_ctx->pipe_idx = i; @@ -1242,9 +1242,9 @@ static int acquire_first_free_pipe( struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; pipe_ctx->tg = pool->timing_generators[i]; - pipe_ctx->mi = pool->mis[i]; - pipe_ctx->ipp = pool->ipps[i]; - pipe_ctx->xfm = pool->transforms[i]; + pipe_ctx->plane_res.mi = pool->mis[i]; + pipe_ctx->plane_res.ipp = pool->ipps[i]; + pipe_ctx->plane_res.xfm = pool->transforms[i]; pipe_ctx->opp = pool->opps[i]; pipe_ctx->dis_clk = pool->display_clock; pipe_ctx->pipe_idx = i; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index ef3a7b83cebe..10587896cc86 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -183,13 +183,13 @@ bool dc_stream_set_cursor_attributes( for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; - if (pipe_ctx->stream != stream || !pipe_ctx->ipp) + if (pipe_ctx->stream != stream || !pipe_ctx->plane_res.ipp) continue; if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state) continue; - pipe_ctx->ipp->funcs->ipp_cursor_set_attributes( - pipe_ctx->ipp, attributes); + pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes( + pipe_ctx->plane_res.ipp, attributes); } return true; @@ -218,7 +218,7 @@ bool dc_stream_set_cursor_position( for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; - struct input_pixel_processor *ipp = pipe_ctx->ipp; + struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp; struct dc_cursor_position pos_cpy = *position; struct dc_cursor_mi_param param = { .pixel_clk_khz = stream->timing.pix_clk_khz, @@ -229,7 +229,7 @@ bool dc_stream_set_cursor_position( }; if (pipe_ctx->stream != stream || - !pipe_ctx->ipp || !pipe_ctx->plane_state) + !pipe_ctx->plane_res.ipp || !pipe_ctx->plane_state) continue; if (pipe_ctx->plane_state->address.type diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index dee18c92fd52..1586dc95f5e4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -242,7 +242,7 @@ static bool dce110_set_input_transfer_func( struct pipe_ctx *pipe_ctx, const struct dc_plane_state *plane_state) { - struct input_pixel_processor *ipp = pipe_ctx->ipp; + struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp; const struct dc_transfer_func *tf = NULL; struct ipp_prescale_params prescale_params = { 0 }; bool result = true; @@ -625,7 +625,7 @@ static bool dce110_set_output_transfer_func( struct pipe_ctx *pipe_ctx, const struct dc_stream_state *stream) { - struct transform *xfm = pipe_ctx->xfm; + struct transform *xfm = pipe_ctx->plane_res.xfm; xfm->funcs->opp_power_on_regamma_lut(xfm, true); xfm->regamma_params.hw_points_num = GAMMA_HW_POINTS_NUM; @@ -951,7 +951,7 @@ static void program_scaler(const struct core_dc *dc, #if defined(CONFIG_DRM_AMD_DC_DCN1_0) /* TOFPGA */ - if (pipe_ctx->xfm->funcs->transform_set_pixel_storage_depth == NULL) + if (pipe_ctx->plane_res.xfm->funcs->transform_set_pixel_storage_depth == NULL) return; #endif @@ -962,8 +962,8 @@ static void program_scaler(const struct core_dc *dc, pipe_ctx->stream->output_color_space, &color); - pipe_ctx->xfm->funcs->transform_set_pixel_storage_depth( - pipe_ctx->xfm, + pipe_ctx->plane_res.xfm->funcs->transform_set_pixel_storage_depth( + pipe_ctx->plane_res.xfm, pipe_ctx->plane_res.scl_data.lb_params.depth, &pipe_ctx->stream->bit_depth_params); @@ -972,7 +972,7 @@ static void program_scaler(const struct core_dc *dc, pipe_ctx->tg, &color); - pipe_ctx->xfm->funcs->transform_set_scaler(pipe_ctx->xfm, + pipe_ctx->plane_res.xfm->funcs->transform_set_scaler(pipe_ctx->plane_res.xfm, &pipe_ctx->plane_res.scl_data); } @@ -1125,10 +1125,10 @@ static enum dc_status apply_single_controller_ctx_to_hw( /* mst support - use total stream count */ #if defined(CONFIG_DRM_AMD_DC_DCN1_0) - if (pipe_ctx->mi->funcs->allocate_mem_input != NULL) + if (pipe_ctx->plane_res.mi->funcs->allocate_mem_input != NULL) #endif - pipe_ctx->mi->funcs->allocate_mem_input( - pipe_ctx->mi, + pipe_ctx->plane_res.mi->funcs->allocate_mem_input( + pipe_ctx->plane_res.mi, stream->timing.h_total, stream->timing.v_total, stream->timing.pix_clk_khz, @@ -1260,16 +1260,16 @@ void dce110_set_displaymarks( total_dest_line_time_ns = compute_pstate_blackout_duration( dc->bw_vbios.blackout_duration, pipe_ctx->stream); - pipe_ctx->mi->funcs->mem_input_program_display_marks( - pipe_ctx->mi, + pipe_ctx->plane_res.mi->funcs->mem_input_program_display_marks( + pipe_ctx->plane_res.mi, context->bw.dce.nbp_state_change_wm_ns[num_pipes], context->bw.dce.stutter_exit_wm_ns[num_pipes], context->bw.dce.urgent_wm_ns[num_pipes], total_dest_line_time_ns); if (i == underlay_idx) { num_pipes++; - pipe_ctx->mi->funcs->mem_input_program_chroma_display_marks( - pipe_ctx->mi, + pipe_ctx->plane_res.mi->funcs->mem_input_program_chroma_display_marks( + pipe_ctx->plane_res.mi, context->bw.dce.nbp_state_change_wm_ns[num_pipes], context->bw.dce.stutter_exit_wm_ns[num_pipes], context->bw.dce.urgent_wm_ns[num_pipes], @@ -1294,15 +1294,15 @@ static void set_safe_displaymarks( if (res_ctx->pipe_ctx[i].stream == NULL) continue; - res_ctx->pipe_ctx[i].mi->funcs->mem_input_program_display_marks( - res_ctx->pipe_ctx[i].mi, + res_ctx->pipe_ctx[i].plane_res.mi->funcs->mem_input_program_display_marks( + res_ctx->pipe_ctx[i].plane_res.mi, nbp_marks, max_marks, max_marks, MAX_WATERMARK); if (i == underlay_idx) - res_ctx->pipe_ctx[i].mi->funcs->mem_input_program_chroma_display_marks( - res_ctx->pipe_ctx[i].mi, + res_ctx->pipe_ctx[i].plane_res.mi->funcs->mem_input_program_chroma_display_marks( + res_ctx->pipe_ctx[i].plane_res.mi, nbp_marks, max_marks, max_marks, @@ -1652,8 +1652,8 @@ static void dce110_reset_hw_ctx_wrap( BREAK_TO_DEBUGGER(); } pipe_ctx_old->tg->funcs->disable_crtc(pipe_ctx_old->tg); - pipe_ctx_old->mi->funcs->free_mem_input( - pipe_ctx_old->mi, dc->current_context->stream_count); + pipe_ctx_old->plane_res.mi->funcs->free_mem_input( + pipe_ctx_old->plane_res.mi, dc->current_context->stream_count); resource_unreference_clock_source( &dc->current_context->res_ctx, dc->res_pool, &pipe_ctx_old->clock_source); @@ -1936,8 +1936,8 @@ static void set_default_colors(struct pipe_ctx *pipe_ctx) /* Lb color depth */ default_adjust.lb_color_depth = pipe_ctx->plane_res.scl_data.lb_params.depth; - pipe_ctx->xfm->funcs->opp_set_csc_default( - pipe_ctx->xfm, &default_adjust); + pipe_ctx->plane_res.xfm->funcs->opp_set_csc_default( + pipe_ctx->plane_res.xfm, &default_adjust); } @@ -2026,7 +2026,7 @@ static void program_gamut_remap(struct pipe_ctx *pipe_ctx) gamut_remap_matrix.matrix[10]; } - pipe_ctx->xfm->funcs->transform_set_gamut_remap(pipe_ctx->xfm, &adjust); + pipe_ctx->plane_res.xfm->funcs->transform_set_gamut_remap(pipe_ctx->plane_res.xfm, &adjust); } /** @@ -2037,7 +2037,7 @@ static void set_plane_config( struct pipe_ctx *pipe_ctx, struct resource_context *res_ctx) { - struct mem_input *mi = pipe_ctx->mi; + struct mem_input *mi = pipe_ctx->plane_res.mi; struct dc_plane_state *plane_state = pipe_ctx->plane_state; struct xfm_grph_csc_adjustment adjust; struct out_csc_color_matrix tbl_entry; @@ -2059,8 +2059,8 @@ static void set_plane_config( tbl_entry.regval[i] = pipe_ctx->stream->csc_color_matrix.matrix[i]; - pipe_ctx->xfm->funcs->opp_set_csc_adjustment - (pipe_ctx->xfm, &tbl_entry); + pipe_ctx->plane_res.xfm->funcs->opp_set_csc_adjustment + (pipe_ctx->plane_res.xfm, &tbl_entry); } if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) { @@ -2094,7 +2094,7 @@ static void set_plane_config( gamut_remap_matrix.matrix[10]; } - pipe_ctx->xfm->funcs->transform_set_gamut_remap(pipe_ctx->xfm, &adjust); + pipe_ctx->plane_res.xfm->funcs->transform_set_gamut_remap(pipe_ctx->plane_res.xfm, &adjust); pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; program_scaler(dc, pipe_ctx); @@ -2114,7 +2114,7 @@ static void set_plane_config( if (dc->public.config.gpu_vm_support) mi->funcs->mem_input_program_pte_vm( - pipe_ctx->mi, + pipe_ctx->plane_res.mi, plane_state->format, &plane_state->tiling_info, plane_state->rotation); @@ -2128,8 +2128,8 @@ static void update_plane_addr(const struct core_dc *dc, if (plane_state == NULL) return; - pipe_ctx->mi->funcs->mem_input_program_surface_flip_and_addr( - pipe_ctx->mi, + pipe_ctx->plane_res.mi->funcs->mem_input_program_surface_flip_and_addr( + pipe_ctx->plane_res.mi, &plane_state->address, plane_state->flip_immediate); @@ -2144,14 +2144,14 @@ void dce110_update_pending_status(struct pipe_ctx *pipe_ctx) return; plane_state->status.is_flip_pending = - pipe_ctx->mi->funcs->mem_input_is_flip_pending( - pipe_ctx->mi); + pipe_ctx->plane_res.mi->funcs->mem_input_is_flip_pending( + pipe_ctx->plane_res.mi); if (plane_state->status.is_flip_pending && !plane_state->visible) - pipe_ctx->mi->current_address = pipe_ctx->mi->request_address; + pipe_ctx->plane_res.mi->current_address = pipe_ctx->plane_res.mi->request_address; - plane_state->status.current_address = pipe_ctx->mi->current_address; - if (pipe_ctx->mi->current_address.type == PLN_ADDR_TYPE_GRPH_STEREO && + plane_state->status.current_address = pipe_ctx->plane_res.mi->current_address; + if (pipe_ctx->plane_res.mi->current_address.type == PLN_ADDR_TYPE_GRPH_STEREO && pipe_ctx->tg->funcs->is_stereo_left_eye) { plane_state->status.is_right_eye =\ !pipe_ctx->tg->funcs->is_stereo_left_eye(pipe_ctx->tg); @@ -2488,7 +2488,7 @@ static void dce110_set_bandwidth( static void dce110_program_front_end_for_pipe( struct core_dc *dc, struct pipe_ctx *pipe_ctx) { - struct mem_input *mi = pipe_ctx->mi; + struct mem_input *mi = pipe_ctx->plane_res.mi; struct pipe_ctx *old_pipe = NULL; struct dc_plane_state *plane_state = pipe_ctx->plane_state; struct xfm_grph_csc_adjustment adjust; @@ -2515,8 +2515,8 @@ static void dce110_program_front_end_for_pipe( tbl_entry.regval[i] = pipe_ctx->stream->csc_color_matrix.matrix[i]; - pipe_ctx->xfm->funcs->opp_set_csc_adjustment - (pipe_ctx->xfm, &tbl_entry); + pipe_ctx->plane_res.xfm->funcs->opp_set_csc_adjustment + (pipe_ctx->plane_res.xfm, &tbl_entry); } if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) { @@ -2550,7 +2550,7 @@ static void dce110_program_front_end_for_pipe( gamut_remap_matrix.matrix[10]; } - pipe_ctx->xfm->funcs->transform_set_gamut_remap(pipe_ctx->xfm, &adjust); + pipe_ctx->plane_res.xfm->funcs->transform_set_gamut_remap(pipe_ctx->plane_res.xfm, &adjust); pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; @@ -2569,7 +2569,7 @@ static void dce110_program_front_end_for_pipe( if (dc->public.config.gpu_vm_support) mi->funcs->mem_input_program_pte_vm( - pipe_ctx->mi, + pipe_ctx->plane_res.mi, plane_state->format, &plane_state->tiling_info, plane_state->rotation); @@ -2673,7 +2673,7 @@ static void program_csc_matrix(struct pipe_ctx *pipe_ctx, tbl_entry.color_space = color_space; //tbl_entry.regval = matrix; - pipe_ctx->xfm->funcs->opp_set_csc_adjustment(pipe_ctx->xfm, &tbl_entry); + pipe_ctx->plane_res.xfm->funcs->opp_set_csc_adjustment(pipe_ctx->plane_res.xfm, &tbl_entry); } } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index f580da1b3249..04a508234251 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -1017,9 +1017,9 @@ static struct pipe_ctx *dce110_acquire_underlay( return NULL; pipe_ctx->tg = pool->timing_generators[underlay_idx]; - pipe_ctx->mi = pool->mis[underlay_idx]; - /*pipe_ctx->ipp = res_ctx->pool->ipps[underlay_idx];*/ - pipe_ctx->xfm = pool->transforms[underlay_idx]; + pipe_ctx->plane_res.mi = pool->mis[underlay_idx]; + /*pipe_ctx->plane_res.ipp = res_ctx->pool->ipps[underlay_idx];*/ + pipe_ctx->plane_res.xfm = pool->transforms[underlay_idx]; pipe_ctx->opp = pool->opps[underlay_idx]; pipe_ctx->dis_clk = pool->display_clock; pipe_ctx->pipe_idx = underlay_idx; @@ -1049,7 +1049,7 @@ static struct pipe_ctx *dce110_acquire_underlay( true, &stream->timing); - pipe_ctx->mi->funcs->allocate_mem_input(pipe_ctx->mi, + pipe_ctx->plane_res.mi->funcs->allocate_mem_input(pipe_ctx->plane_res.mi, stream->timing.h_total, stream->timing.v_total, stream->timing.pix_clk_khz, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 314d7645a898..1cf672d4a1ee 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1070,8 +1070,8 @@ static void update_plane_addr(const struct core_dc *dc, struct pipe_ctx *pipe_ct if (plane_state == NULL) return; addr_patched = patch_address_for_sbs_tb_stereo(pipe_ctx, &addr); - pipe_ctx->mi->funcs->mem_input_program_surface_flip_and_addr( - pipe_ctx->mi, + pipe_ctx->plane_res.mi->funcs->mem_input_program_surface_flip_and_addr( + pipe_ctx->plane_res.mi, &plane_state->address, plane_state->flip_immediate); plane_state->status.requested_address = plane_state->address; @@ -1082,7 +1082,7 @@ static void update_plane_addr(const struct core_dc *dc, struct pipe_ctx *pipe_ct static bool dcn10_set_input_transfer_func( struct pipe_ctx *pipe_ctx, const struct dc_plane_state *plane_state) { - struct input_pixel_processor *ipp = pipe_ctx->ipp; + struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp; const struct dc_transfer_func *tf = NULL; bool result = true; @@ -1447,7 +1447,7 @@ static bool dcn10_set_output_transfer_func( struct pipe_ctx *pipe_ctx, const struct dc_stream_state *stream) { - struct transform *xfm = pipe_ctx->xfm; + struct transform *xfm = pipe_ctx->plane_res.xfm; if (xfm == NULL) return false; @@ -1778,7 +1778,7 @@ static void program_gamut_remap(struct pipe_ctx *pipe_ctx) gamut_remap_matrix.matrix[10]; } - pipe_ctx->xfm->funcs->transform_set_gamut_remap(pipe_ctx->xfm, &adjust); + pipe_ctx->plane_res.xfm->funcs->transform_set_gamut_remap(pipe_ctx->plane_res.xfm, &adjust); } @@ -1800,7 +1800,7 @@ static void program_csc_matrix(struct pipe_ctx *pipe_ctx, tbl_entry.color_space = color_space; //tbl_entry.regval = matrix; - pipe_ctx->xfm->funcs->opp_set_csc_adjustment(pipe_ctx->xfm, &tbl_entry); + pipe_ctx->plane_res.xfm->funcs->opp_set_csc_adjustment(pipe_ctx->plane_res.xfm, &tbl_entry); } } static bool is_lower_pipe_tree_visible(struct pipe_ctx *pipe_ctx) @@ -1896,8 +1896,8 @@ static void update_dchubp_dpp( struct validate_context *context) { struct dce_hwseq *hws = dc->hwseq; - struct mem_input *mi = pipe_ctx->mi; - struct input_pixel_processor *ipp = pipe_ctx->ipp; + struct mem_input *mi = pipe_ctx->plane_res.mi; + struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp; struct dc_plane_state *plane_state = pipe_ctx->plane_state; union plane_size size = plane_state->plane_size; struct default_adjustment ocsc = {0}; @@ -1935,7 +1935,7 @@ static void update_dchubp_dpp( if (dc->public.config.gpu_vm_support) mi->funcs->mem_input_program_pte_vm( - pipe_ctx->mi, + pipe_ctx->plane_res.mi, plane_state->format, &plane_state->tiling_info, plane_state->rotation); @@ -1968,8 +1968,8 @@ static void update_dchubp_dpp( pipe_ctx->plane_res.scl_data.lb_params.alpha_en = per_pixel_alpha; pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; /* scaler configuration */ - pipe_ctx->xfm->funcs->transform_set_scaler( - pipe_ctx->xfm, &pipe_ctx->plane_res.scl_data); + pipe_ctx->plane_res.xfm->funcs->transform_set_scaler( + pipe_ctx->plane_res.xfm, &pipe_ctx->plane_res.scl_data); mi->funcs->mem_program_viewport(mi, &pipe_ctx->plane_res.scl_data.viewport, &pipe_ctx->plane_res.scl_data.viewport_c); @@ -1978,7 +1978,7 @@ static void update_dchubp_dpp( /*TODO add adjustments parameters*/ ocsc.out_color_space = pipe_ctx->stream->output_color_space; - pipe_ctx->xfm->funcs->opp_set_csc_default(pipe_ctx->xfm, &ocsc); + pipe_ctx->plane_res.xfm->funcs->opp_set_csc_default(pipe_ctx->plane_res.xfm, &ocsc); mi->funcs->mem_input_program_surface_config( mi, @@ -2098,7 +2098,7 @@ static void dcn10_apply_ctx_for_surface( */ if (pipe_ctx->plane_state && !old_pipe_ctx->plane_state) { - if (pipe_ctx->mi->opp_id != 0xf && pipe_ctx->tg->inst == be_idx) { + if (pipe_ctx->plane_res.mi->opp_id != 0xf && pipe_ctx->tg->inst == be_idx) { dcn10_power_down_fe(dc, pipe_ctx->pipe_idx); /* * power down fe will unlock when calling reset, need @@ -2124,7 +2124,7 @@ static void dcn10_apply_ctx_for_surface( dc->res_pool->mpc, old_pipe_ctx->opp, old_pipe_ctx->pipe_idx); - old_pipe_ctx->opp->mpcc_disconnect_pending[old_pipe_ctx->mi->mpcc_id] = true; + old_pipe_ctx->opp->mpcc_disconnect_pending[old_pipe_ctx->plane_res.mi->mpcc_id] = true; /*dm_logger_write(dc->ctx->logger, LOG_ERROR, "[debug_mpo: apply_ctx disconnect pending on mpcc %d]\n", @@ -2481,19 +2481,19 @@ void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx) return; plane_state->status.is_flip_pending = - pipe_ctx->mi->funcs->mem_input_is_flip_pending( - pipe_ctx->mi); + pipe_ctx->plane_res.mi->funcs->mem_input_is_flip_pending( + pipe_ctx->plane_res.mi); /* DCN we read INUSE address in MI, do we still need this wa? */ if (plane_state->status.is_flip_pending && !plane_state->visible) { - pipe_ctx->mi->current_address = - pipe_ctx->mi->request_address; + pipe_ctx->plane_res.mi->current_address = + pipe_ctx->plane_res.mi->request_address; BREAK_TO_DEBUGGER(); } - plane_state->status.current_address = pipe_ctx->mi->current_address; - if (pipe_ctx->mi->current_address.type == PLN_ADDR_TYPE_GRPH_STEREO && + plane_state->status.current_address = pipe_ctx->plane_res.mi->current_address; + if (pipe_ctx->plane_res.mi->current_address.type == PLN_ADDR_TYPE_GRPH_STEREO && tg->funcs->is_stereo_left_eye) { plane_state->status.is_right_eye = !tg->funcs->is_stereo_left_eye(pipe_ctx->tg); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 3fe6df92f91f..710e514ee950 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -963,9 +963,9 @@ static struct pipe_ctx *dcn10_acquire_idle_pipe_for_layer( idle_pipe->tg = head_pipe->tg; idle_pipe->opp = head_pipe->opp; - idle_pipe->mi = pool->mis[idle_pipe->pipe_idx]; - idle_pipe->ipp = pool->ipps[idle_pipe->pipe_idx]; - idle_pipe->xfm = pool->transforms[idle_pipe->pipe_idx]; + idle_pipe->plane_res.mi = pool->mis[idle_pipe->pipe_idx]; + idle_pipe->plane_res.ipp = pool->ipps[idle_pipe->pipe_idx]; + idle_pipe->plane_res.xfm = pool->transforms[idle_pipe->pipe_idx]; return idle_pipe; } diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index dbca1de89494..4640c43d17a4 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -158,6 +158,10 @@ struct stream_resource { struct plane_resource { struct scaler_data scl_data; + + struct mem_input *mi; + struct input_pixel_processor *ipp; + struct transform *xfm; }; struct pipe_ctx { @@ -167,9 +171,6 @@ struct pipe_ctx { struct plane_resource plane_res; struct stream_resource stream_res; - struct mem_input *mi; - struct input_pixel_processor *ipp; - struct transform *xfm; struct output_pixel_processor *opp; struct timing_generator *tg; -- cgit From a6a6cb349e39ef23a341a17752eebf69a5c0d7ff Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Sun, 30 Jul 2017 13:55:28 -0400 Subject: drm/amd/display: Move OPP to stream_res find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/pipes->opp/pipes->stream_res\.opp/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/ctx->opp->/ctx->stream_res\.opp->/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/pipe->opp/pipe->stream_res\.opp/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/pipe_ctx->opp/pipe_ctx->stream_res\.opp/g' Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 4 ++-- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 8 ++++---- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 6 +++--- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 12 +++++------ .../drm/amd/display/dc/dce110/dce110_resource.c | 2 +- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 24 +++++++++++----------- .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 3 +-- 8 files changed, 30 insertions(+), 31 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index ffc9c05e2fb5..507732e4b67b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -365,8 +365,8 @@ void set_dither_option(struct dc_stream_state *stream, resource_build_bit_depth_reduction_params(stream, ¶ms); stream->bit_depth_params = params; - pipes->opp->funcs-> - opp_program_bit_depth_reduction(pipes->opp, ¶ms); + pipes->stream_res.opp->funcs-> + opp_program_bit_depth_reduction(pipes->stream_res.opp, ¶ms); } static void allocate_dc_stream_funcs(struct core_dc *core_dc) 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 231cade5e1fd..0c90060c0f62 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 @@ -2372,8 +2372,8 @@ static void set_crtc_test_pattern(struct dc_link *link, { /* disable bit depth reduction */ pipe_ctx->stream->bit_depth_params = params; - pipe_ctx->opp->funcs-> - opp_program_bit_depth_reduction(pipe_ctx->opp, ¶ms); + pipe_ctx->stream_res.opp->funcs-> + opp_program_bit_depth_reduction(pipe_ctx->stream_res.opp, ¶ms); pipe_ctx->tg->funcs->set_test_pattern(pipe_ctx->tg, controller_test_pattern, color_depth); @@ -2385,8 +2385,8 @@ static void set_crtc_test_pattern(struct dc_link *link, resource_build_bit_depth_reduction_params(pipe_ctx->stream, ¶ms); pipe_ctx->stream->bit_depth_params = params; - pipe_ctx->opp->funcs-> - opp_program_bit_depth_reduction(pipe_ctx->opp, ¶ms); + pipe_ctx->stream_res.opp->funcs-> + opp_program_bit_depth_reduction(pipe_ctx->stream_res.opp, ¶ms); pipe_ctx->tg->funcs->set_test_pattern(pipe_ctx->tg, CONTROLLER_DP_TEST_PATTERN_VIDEOMODE, diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 7270f0de9598..ba529f8b24e8 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1015,7 +1015,7 @@ static int acquire_first_split_pipe( pipe_ctx->plane_res.mi = pool->mis[i]; pipe_ctx->plane_res.ipp = pool->ipps[i]; pipe_ctx->plane_res.xfm = pool->transforms[i]; - pipe_ctx->opp = pool->opps[i]; + pipe_ctx->stream_res.opp = pool->opps[i]; pipe_ctx->dis_clk = pool->display_clock; pipe_ctx->pipe_idx = i; @@ -1095,7 +1095,7 @@ bool resource_attach_surfaces_to_context( if (tail_pipe) { free_pipe->tg = tail_pipe->tg; - free_pipe->opp = tail_pipe->opp; + free_pipe->stream_res.opp = tail_pipe->stream_res.opp; free_pipe->stream_enc = tail_pipe->stream_enc; free_pipe->audio = tail_pipe->audio; free_pipe->clock_source = tail_pipe->clock_source; @@ -1245,7 +1245,7 @@ static int acquire_first_free_pipe( pipe_ctx->plane_res.mi = pool->mis[i]; pipe_ctx->plane_res.ipp = pool->ipps[i]; pipe_ctx->plane_res.xfm = pool->transforms[i]; - pipe_ctx->opp = pool->opps[i]; + pipe_ctx->stream_res.opp = pool->opps[i]; pipe_ctx->dis_clk = pool->display_clock; pipe_ctx->pipe_idx = i; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 1586dc95f5e4..0601105a5e3f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1044,16 +1044,16 @@ static enum dc_status apply_single_controller_ctx_to_hw( /* */ dc->hwss.prog_pixclk_crtc_otg(pipe_ctx, context, dc); - pipe_ctx->opp->funcs->opp_set_dyn_expansion( - pipe_ctx->opp, + pipe_ctx->stream_res.opp->funcs->opp_set_dyn_expansion( + pipe_ctx->stream_res.opp, COLOR_SPACE_YCBCR601, stream->timing.display_color_depth, pipe_ctx->stream->signal); /* FPGA does not program backend */ if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { - pipe_ctx->opp->funcs->opp_program_fmt( - pipe_ctx->opp, + pipe_ctx->stream_res.opp->funcs->opp_program_fmt( + pipe_ctx->stream_res.opp, &stream->bit_depth_params, &stream->clamping); return DC_OK; @@ -1078,8 +1078,8 @@ static enum dc_status apply_single_controller_ctx_to_hw( /*vbios crtc_source_selection and encoder_setup will override fmt_C*/ - pipe_ctx->opp->funcs->opp_program_fmt( - pipe_ctx->opp, + pipe_ctx->stream_res.opp->funcs->opp_program_fmt( + pipe_ctx->stream_res.opp, &stream->bit_depth_params, &stream->clamping); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 04a508234251..4b7bce2427a8 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -1020,7 +1020,7 @@ static struct pipe_ctx *dce110_acquire_underlay( pipe_ctx->plane_res.mi = pool->mis[underlay_idx]; /*pipe_ctx->plane_res.ipp = res_ctx->pool->ipps[underlay_idx];*/ pipe_ctx->plane_res.xfm = pool->transforms[underlay_idx]; - pipe_ctx->opp = pool->opps[underlay_idx]; + pipe_ctx->stream_res.opp = pool->opps[underlay_idx]; pipe_ctx->dis_clk = pool->display_clock; pipe_ctx->pipe_idx = underlay_idx; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 1cf672d4a1ee..2db6b46baa6c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -720,8 +720,8 @@ static enum dc_status dcn10_prog_pixclk_crtc_otg( &stream->timing, true); - pipe_ctx->opp->funcs->opp_set_stereo_polarity( - pipe_ctx->opp, + pipe_ctx->stream_res.opp->funcs->opp_set_stereo_polarity( + pipe_ctx->stream_res.opp, enableStereo, rightEyePolarity); @@ -731,8 +731,8 @@ static enum dc_status dcn10_prog_pixclk_crtc_otg( inst_offset = reg_offsets[pipe_ctx->tg->inst].fmt; - pipe_ctx->opp->funcs->opp_program_fmt( - pipe_ctx->opp, + pipe_ctx->stream_res.opp->funcs->opp_program_fmt( + pipe_ctx->stream_res.opp, &stream->bit_depth_params, &stream->clamping); #endif @@ -1946,7 +1946,7 @@ static void update_dchubp_dpp( IPP_OUTPUT_FORMAT_12_BIT_FIX); mpcc_cfg.mi = mi; - mpcc_cfg.opp = pipe_ctx->opp; + mpcc_cfg.opp = pipe_ctx->stream_res.opp; for (top_pipe = pipe_ctx->top_pipe; top_pipe; top_pipe = top_pipe->top_pipe) mpcc_cfg.z_index++; if (dc->public.debug.surface_visual_confirm) @@ -2122,9 +2122,9 @@ static void dcn10_apply_ctx_for_surface( /* reset mpc */ dc->res_pool->mpc->funcs->remove( dc->res_pool->mpc, - old_pipe_ctx->opp, + old_pipe_ctx->stream_res.opp, old_pipe_ctx->pipe_idx); - old_pipe_ctx->opp->mpcc_disconnect_pending[old_pipe_ctx->plane_res.mi->mpcc_id] = true; + old_pipe_ctx->stream_res.opp->mpcc_disconnect_pending[old_pipe_ctx->plane_res.mi->mpcc_id] = true; /*dm_logger_write(dc->ctx->logger, LOG_ERROR, "[debug_mpo: apply_ctx disconnect pending on mpcc %d]\n", @@ -2364,8 +2364,8 @@ static void dcn10_setup_stereo(struct pipe_ctx *pipe_ctx, struct core_dc *dc) dcn10_config_stereo_parameters(stream, &flags); - pipe_ctx->opp->funcs->opp_set_stereo_polarity( - pipe_ctx->opp, + pipe_ctx->stream_res.opp->funcs->opp_set_stereo_polarity( + pipe_ctx->stream_res.opp, flags.PROGRAM_STEREO == 1 ? true:false, stream->timing.flags.RIGHT_EYE_3D_POLARITY == 1 ? true:false); @@ -2441,13 +2441,13 @@ static void dcn10_wait_for_mpcc_disconnect( { int i; - if (!pipe_ctx->opp) + if (!pipe_ctx->stream_res.opp) return; for (i = 0; i < MAX_PIPES; i++) { - if (pipe_ctx->opp->mpcc_disconnect_pending[i]) { + if (pipe_ctx->stream_res.opp->mpcc_disconnect_pending[i]) { res_pool->mpc->funcs->wait_for_idle(res_pool->mpc, i); - pipe_ctx->opp->mpcc_disconnect_pending[i] = false; + pipe_ctx->stream_res.opp->mpcc_disconnect_pending[i] = false; res_pool->mis[i]->funcs->set_blank(res_pool->mis[i], true); /*dm_logger_write(dc->ctx->logger, LOG_ERROR, "[debug_mpo: wait_for_mpcc finished waiting on mpcc %d]\n", diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 710e514ee950..e15eec315228 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -961,7 +961,7 @@ static struct pipe_ctx *dcn10_acquire_idle_pipe_for_layer( idle_pipe->stream = head_pipe->stream; idle_pipe->tg = head_pipe->tg; - idle_pipe->opp = head_pipe->opp; + idle_pipe->stream_res.opp = head_pipe->stream_res.opp; idle_pipe->plane_res.mi = pool->mis[idle_pipe->pipe_idx]; idle_pipe->plane_res.ipp = pool->ipps[idle_pipe->pipe_idx]; diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 4640c43d17a4..24a525495bfc 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -153,7 +153,7 @@ struct resource_pool { }; struct stream_resource { - int stub; + struct output_pixel_processor *opp; }; struct plane_resource { @@ -171,7 +171,6 @@ struct pipe_ctx { struct plane_resource plane_res; struct stream_resource stream_res; - struct output_pixel_processor *opp; struct timing_generator *tg; struct stream_encoder *stream_enc; -- cgit From 6b670fa965b620bf0131a0a339a388a0581bc466 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Sun, 30 Jul 2017 13:59:26 -0400 Subject: drm/amd/display: Move TG to stream_res find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/pipes->tg/pipes->stream_res\.tg/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/ctx->tg->/ctx->stream_res\.tg->/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/pipe->tg/pipe->stream_res\.tg/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/pipe_ctx->tg/pipe_ctx->stream_res\.tg/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/pipe_ctx\[pipe_offset\]\.tg/pipe_ctx\[pipe_offset\]\.stream_res\.tg/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/grouped_pipes\[i\]->tg/grouped_pipes\[i\]->stream_^Cs\.tg/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/grouped_pipes\[0\]->tg/grouped_pipes\[0\]->stream_res\.tg/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/grouped_pipes\[1\]->tg/grouped_pipes\[1\]->stream_res\.tg/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/pipe_ctx\[i\]->tg/pipe_ctx\[i\]->stream_res\.tg/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/pipe_ctx_old->tg/pipe_ctx_old->stream_res\.tg/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/pipe_set\[j\]->tg/pipe_set\[j\]->stream_res\.tg/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/pipe_ctx\[i\]\.tg/pipe_ctx\[i\]\.stream_res\.tg/g' Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 4 +- drivers/gpu/drm/amd/display/dc/core/dc_debug.c | 4 +- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 6 +- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 4 +- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 8 +- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 4 +- drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c | 2 +- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 64 +++++++-------- .../drm/amd/display/dc/dce110/dce110_resource.c | 12 +-- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 96 +++++++++++----------- .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 3 +- .../amd/display/dc/irq/dce110/irq_service_dce110.c | 2 +- 13 files changed, 105 insertions(+), 106 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 507732e4b67b..61c2a210c123 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -846,7 +846,7 @@ static void program_timing_sync( for (j = 0; j < group_size; j++) { struct pipe_ctx *temp; - if (!pipe_set[j]->tg->funcs->is_blanked(pipe_set[j]->tg)) { + if (!pipe_set[j]->stream_res.tg->funcs->is_blanked(pipe_set[j]->stream_res.tg)) { if (j == 0) break; @@ -859,7 +859,7 @@ static void program_timing_sync( /* remove any other unblanked pipes as they have already been synced */ for (j = j + 1; j < group_size; j++) { - if (!pipe_set[j]->tg->funcs->is_blanked(pipe_set[j]->tg)) { + if (!pipe_set[j]->stream_res.tg->funcs->is_blanked(pipe_set[j]->stream_res.tg)) { group_size--; pipe_set[j] = pipe_set[group_size]; j--; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c index ca4f1db4a58a..21af3bc057c7 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c @@ -309,7 +309,7 @@ void context_timing_trace( || pipe_ctx->pipe_idx == underlay_idx) continue; - pipe_ctx->tg->funcs->get_position(pipe_ctx->tg, &position); + pipe_ctx->stream_res.tg->funcs->get_position(pipe_ctx->stream_res.tg, &position); h_pos[i] = position.horizontal_count; v_pos[i] = position.vertical_count; } @@ -320,7 +320,7 @@ void context_timing_trace( continue; TIMING_TRACE("OTG_%d H_tot:%d V_tot:%d H_pos:%d V_pos:%d\n", - pipe_ctx->tg->inst, + pipe_ctx->stream_res.tg->inst, pipe_ctx->stream->timing.h_total, pipe_ctx->stream->timing.v_total, h_pos[i], v_pos[i]); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 7a2fe2f3e65c..2c43edf2c7c4 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1398,7 +1398,7 @@ bool dc_link_set_backlight_level(const struct dc_link *link, uint32_t level, */ controller_id = core_dc->current_context-> - res_ctx.pipe_ctx[i].tg->inst + + res_ctx.pipe_ctx[i].stream_res.tg->inst + 1; } } @@ -1504,7 +1504,7 @@ bool dc_link_setup_psr(struct dc_link *link, */ psr_context->controllerId = core_dc->current_context->res_ctx. - pipe_ctx[i].tg->inst + 1; + pipe_ctx[i].stream_res.tg->inst + 1; break; } } @@ -1879,7 +1879,7 @@ void core_link_enable_stream(struct pipe_ctx *pipe_ctx) } /* turn off otg test pattern if enable */ - pipe_ctx->tg->funcs->set_test_pattern(pipe_ctx->tg, + pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg, CONTROLLER_DP_TEST_PATTERN_VIDEOMODE, COLOR_DEPTH_UNDEFINED); 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 0c90060c0f62..eda25942aea0 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 @@ -2375,7 +2375,7 @@ static void set_crtc_test_pattern(struct dc_link *link, pipe_ctx->stream_res.opp->funcs-> opp_program_bit_depth_reduction(pipe_ctx->stream_res.opp, ¶ms); - pipe_ctx->tg->funcs->set_test_pattern(pipe_ctx->tg, + pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg, controller_test_pattern, color_depth); } break; @@ -2388,7 +2388,7 @@ static void set_crtc_test_pattern(struct dc_link *link, pipe_ctx->stream_res.opp->funcs-> opp_program_bit_depth_reduction(pipe_ctx->stream_res.opp, ¶ms); - pipe_ctx->tg->funcs->set_test_pattern(pipe_ctx->tg, + pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg, CONTROLLER_DP_TEST_PATTERN_VIDEOMODE, color_depth); } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index ba529f8b24e8..5326713bf3fb 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1011,7 +1011,7 @@ static int acquire_first_split_pipe( pipe_ctx->bottom_pipe->top_pipe = pipe_ctx->top_pipe; memset(pipe_ctx, 0, sizeof(*pipe_ctx)); - pipe_ctx->tg = pool->timing_generators[i]; + pipe_ctx->stream_res.tg = pool->timing_generators[i]; pipe_ctx->plane_res.mi = pool->mis[i]; pipe_ctx->plane_res.ipp = pool->ipps[i]; pipe_ctx->plane_res.xfm = pool->transforms[i]; @@ -1094,7 +1094,7 @@ bool resource_attach_surfaces_to_context( free_pipe->plane_state = plane_state; if (tail_pipe) { - free_pipe->tg = tail_pipe->tg; + free_pipe->stream_res.tg = tail_pipe->stream_res.tg; free_pipe->stream_res.opp = tail_pipe->stream_res.opp; free_pipe->stream_enc = tail_pipe->stream_enc; free_pipe->audio = tail_pipe->audio; @@ -1241,7 +1241,7 @@ static int acquire_first_free_pipe( if (!res_ctx->pipe_ctx[i].stream) { struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; - pipe_ctx->tg = pool->timing_generators[i]; + pipe_ctx->stream_res.tg = pool->timing_generators[i]; pipe_ctx->plane_res.mi = pool->mis[i]; pipe_ctx->plane_res.ipp = pool->ipps[i]; pipe_ctx->plane_res.xfm = pool->transforms[i]; @@ -1532,7 +1532,7 @@ enum dc_status resource_map_pool_resources( pipe_ctx->audio); } - context->stream_status[i].primary_otg_inst = pipe_ctx->tg->inst; + context->stream_status[i].primary_otg_inst = pipe_ctx->stream_res.tg->inst; } return DC_OK; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 10587896cc86..2de37fed12a5 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -253,7 +253,7 @@ uint32_t dc_stream_get_vblank_counter(const struct dc_stream_state *stream) &core_dc->current_context->res_ctx; for (i = 0; i < MAX_PIPES; i++) { - struct timing_generator *tg = res_ctx->pipe_ctx[i].tg; + struct timing_generator *tg = res_ctx->pipe_ctx[i].stream_res.tg; if (res_ctx->pipe_ctx[i].stream != stream) continue; @@ -277,7 +277,7 @@ bool dc_stream_get_scanoutpos(const struct dc_stream_state *stream, &core_dc->current_context->res_ctx; for (i = 0; i < MAX_PIPES; i++) { - struct timing_generator *tg = res_ctx->pipe_ctx[i].tg; + struct timing_generator *tg = res_ctx->pipe_ctx[i].stream_res.tg; if (res_ctx->pipe_ctx[i].stream != stream) continue; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c index 8140ff31c3bd..4894e1755d84 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c @@ -53,7 +53,7 @@ void dce_pipe_control_lock(struct core_dc *dc, struct dce_hwseq *hws = dc->hwseq; /* Not lock pipe when blank */ - if (lock && pipe->tg->funcs->is_blanked(pipe->tg)) + if (lock && pipe->stream_res.tg->funcs->is_blanked(pipe->stream_res.tg)) return; val = REG_GET_4(BLND_V_UPDATE_LOCK[pipe->pipe_idx], diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 0601105a5e3f..1d7c7fb668be 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -710,7 +710,7 @@ void dce110_enable_stream(struct pipe_ctx *pipe_ctx) */ uint32_t active_total_with_borders; uint32_t early_control = 0; - struct timing_generator *tg = pipe_ctx->tg; + struct timing_generator *tg = pipe_ctx->stream_res.tg; /* TODOFPGA may change to hwss.update_info_frame */ dce110_update_info_frame(pipe_ctx); @@ -967,9 +967,9 @@ static void program_scaler(const struct core_dc *dc, pipe_ctx->plane_res.scl_data.lb_params.depth, &pipe_ctx->stream->bit_depth_params); - if (pipe_ctx->tg->funcs->set_overscan_blank_color) - pipe_ctx->tg->funcs->set_overscan_blank_color( - pipe_ctx->tg, + if (pipe_ctx->stream_res.tg->funcs->set_overscan_blank_color) + pipe_ctx->stream_res.tg->funcs->set_overscan_blank_color( + pipe_ctx->stream_res.tg, &color); pipe_ctx->plane_res.xfm->funcs->transform_set_scaler(pipe_ctx->plane_res.xfm, @@ -991,15 +991,15 @@ static enum dc_status dce110_prog_pixclk_crtc_otg( /* program blank color */ color_space_to_black_color(dc, stream->output_color_space, &black_color); - pipe_ctx->tg->funcs->set_blank_color( - pipe_ctx->tg, + pipe_ctx->stream_res.tg->funcs->set_blank_color( + pipe_ctx->stream_res.tg, &black_color); /* * Must blank CRTC after disabling power gating and before any * programming, otherwise CRTC will be hung in bad state */ - pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, true); + pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, true); if (false == pipe_ctx->clock_source->funcs->program_pix_clk( pipe_ctx->clock_source, @@ -1009,19 +1009,19 @@ static enum dc_status dce110_prog_pixclk_crtc_otg( return DC_ERROR_UNEXPECTED; } - pipe_ctx->tg->funcs->program_timing( - pipe_ctx->tg, + pipe_ctx->stream_res.tg->funcs->program_timing( + pipe_ctx->stream_res.tg, &stream->timing, true); - pipe_ctx->tg->funcs->set_static_screen_control( - pipe_ctx->tg, + pipe_ctx->stream_res.tg->funcs->set_static_screen_control( + pipe_ctx->stream_res.tg, 0x182); } if (!pipe_ctx_old->stream) { - if (false == pipe_ctx->tg->funcs->enable_crtc( - pipe_ctx->tg)) { + if (false == pipe_ctx->stream_res.tg->funcs->enable_crtc( + pipe_ctx->stream_res.tg)) { BREAK_TO_DEBUGGER(); return DC_ERROR_UNEXPECTED; } @@ -1073,7 +1073,7 @@ static enum dc_status apply_single_controller_ctx_to_hw( if (pipe_ctx->stream->signal != SIGNAL_TYPE_VIRTUAL) pipe_ctx->stream_enc->funcs->setup_stereo_sync( pipe_ctx->stream_enc, - pipe_ctx->tg->inst, + pipe_ctx->stream_res.tg->inst, stream->timing.timing_3d_format != TIMING_3D_FORMAT_NONE); @@ -1359,7 +1359,7 @@ static void set_drr(struct pipe_ctx **pipe_ctx, */ for (i = 0; i < num_pipes; i++) { - pipe_ctx[i]->tg->funcs->set_drr(pipe_ctx[i]->tg, ¶ms); + pipe_ctx[i]->stream_res.tg->funcs->set_drr(pipe_ctx[i]->stream_res.tg, ¶ms); } } @@ -1372,7 +1372,7 @@ static void get_position(struct pipe_ctx **pipe_ctx, /* TODO: handle pipes > 1 */ for (i = 0; i < num_pipes; i++) - pipe_ctx[i]->tg->funcs->get_position(pipe_ctx[i]->tg, position); + pipe_ctx[i]->stream_res.tg->funcs->get_position(pipe_ctx[i]->stream_res.tg, position); } static void set_static_screen_control(struct pipe_ctx **pipe_ctx, @@ -1393,8 +1393,8 @@ static void set_static_screen_control(struct pipe_ctx **pipe_ctx, #endif for (i = 0; i < num_pipes; i++) - pipe_ctx[i]->tg->funcs-> - set_static_screen_control(pipe_ctx[i]->tg, value); + pipe_ctx[i]->stream_res.tg->funcs-> + set_static_screen_control(pipe_ctx[i]->stream_res.tg, value); } /* unit: in_khz before mode set, get pixel clock from context. ASIC register @@ -1646,12 +1646,12 @@ static void dce110_reset_hw_ctx_wrap( if (!pipe_ctx->stream || pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) { core_link_disable_stream(pipe_ctx_old); - pipe_ctx_old->tg->funcs->set_blank(pipe_ctx_old->tg, true); - if (!hwss_wait_for_blank_complete(pipe_ctx_old->tg)) { + pipe_ctx_old->stream_res.tg->funcs->set_blank(pipe_ctx_old->stream_res.tg, true); + if (!hwss_wait_for_blank_complete(pipe_ctx_old->stream_res.tg)) { dm_error("DC: failed to blank crtc!\n"); BREAK_TO_DEBUGGER(); } - pipe_ctx_old->tg->funcs->disable_crtc(pipe_ctx_old->tg); + pipe_ctx_old->stream_res.tg->funcs->disable_crtc(pipe_ctx_old->stream_res.tg); pipe_ctx_old->plane_res.mi->funcs->free_mem_input( pipe_ctx_old->plane_res.mi, dc->current_context->stream_count); resource_unreference_clock_source( @@ -1984,7 +1984,7 @@ static void program_surface_visibility(const struct core_dc *dc, blank_target = true; dce_set_blender_mode(dc->hwseq, pipe_ctx->pipe_idx, blender_mode); - pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, blank_target); + pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, blank_target); } @@ -2152,9 +2152,9 @@ void dce110_update_pending_status(struct pipe_ctx *pipe_ctx) plane_state->status.current_address = pipe_ctx->plane_res.mi->current_address; if (pipe_ctx->plane_res.mi->current_address.type == PLN_ADDR_TYPE_GRPH_STEREO && - pipe_ctx->tg->funcs->is_stereo_left_eye) { + pipe_ctx->stream_res.tg->funcs->is_stereo_left_eye) { plane_state->status.is_right_eye =\ - !pipe_ctx->tg->funcs->is_stereo_left_eye(pipe_ctx->tg); + !pipe_ctx->stream_res.tg->funcs->is_stereo_left_eye(pipe_ctx->stream_res.tg); } } @@ -2218,28 +2218,28 @@ static void dce110_enable_timing_synchronization( * Since HW doesn't care which one, we always assign * the 1st one in the group. */ gsl_params.gsl_group = 0; - gsl_params.gsl_master = grouped_pipes[0]->tg->inst; + gsl_params.gsl_master = grouped_pipes[0]->stream_res.tg->inst; for (i = 0; i < group_size; i++) - grouped_pipes[i]->tg->funcs->setup_global_swap_lock( - grouped_pipes[i]->tg, &gsl_params); + grouped_pipes[i]->stream_res.tg->funcs->setup_global_swap_lock( + grouped_pipes[i]->stream_res.tg, &gsl_params); /* Reset slave controllers on master VSync */ DC_SYNC_INFO("GSL: enabling trigger-reset\n"); for (i = 1 /* skip the master */; i < group_size; i++) - grouped_pipes[i]->tg->funcs->enable_reset_trigger( - grouped_pipes[i]->tg, gsl_params.gsl_group); + grouped_pipes[i]->stream_res.tg->funcs->enable_reset_trigger( + grouped_pipes[i]->stream_res.tg, gsl_params.gsl_group); for (i = 1 /* skip the master */; i < group_size; i++) { DC_SYNC_INFO("GSL: waiting for reset to occur.\n"); - wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[i]->tg); + wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[i]->stream_res.tg); /* Regardless of success of the wait above, remove the reset or * the driver will start timing out on Display requests. */ DC_SYNC_INFO("GSL: disabling trigger-reset.\n"); - grouped_pipes[i]->tg->funcs->disable_reset_trigger(grouped_pipes[i]->tg); + grouped_pipes[i]->stream_res.tg->funcs->disable_reset_trigger(grouped_pipes[i]->stream_res.tg); } @@ -2247,7 +2247,7 @@ static void dce110_enable_timing_synchronization( * is that the sync'ed displays will not drift out of sync over time*/ DC_SYNC_INFO("GSL: Restoring register states.\n"); for (i = 0; i < group_size; i++) - grouped_pipes[i]->tg->funcs->tear_down_global_swap_lock(grouped_pipes[i]->tg); + grouped_pipes[i]->stream_res.tg->funcs->tear_down_global_swap_lock(grouped_pipes[i]->stream_res.tg); DC_SYNC_INFO("GSL: Set-up complete.\n"); } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 4b7bce2427a8..94058ee16029 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -1016,7 +1016,7 @@ static struct pipe_ctx *dce110_acquire_underlay( if (res_ctx->pipe_ctx[underlay_idx].stream) return NULL; - pipe_ctx->tg = pool->timing_generators[underlay_idx]; + pipe_ctx->stream_res.tg = pool->timing_generators[underlay_idx]; pipe_ctx->plane_res.mi = pool->mis[underlay_idx]; /*pipe_ctx->plane_res.ipp = res_ctx->pool->ipps[underlay_idx];*/ pipe_ctx->plane_res.xfm = pool->transforms[underlay_idx]; @@ -1040,12 +1040,12 @@ static struct pipe_ctx *dce110_acquire_underlay( * need to be enabled */ - pipe_ctx->tg->funcs->program_timing(pipe_ctx->tg, + pipe_ctx->stream_res.tg->funcs->program_timing(pipe_ctx->stream_res.tg, &stream->timing, false); - pipe_ctx->tg->funcs->enable_advanced_request( - pipe_ctx->tg, + pipe_ctx->stream_res.tg->funcs->enable_advanced_request( + pipe_ctx->stream_res.tg, true, &stream->timing); @@ -1057,8 +1057,8 @@ static struct pipe_ctx *dce110_acquire_underlay( color_space_to_black_color(dc, COLOR_SPACE_YCBCR601, &black_color); - pipe_ctx->tg->funcs->set_blank_color( - pipe_ctx->tg, + pipe_ctx->stream_res.tg->funcs->set_blank_color( + pipe_ctx->stream_res.tg, &black_color); } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 2db6b46baa6c..99ef0f25492c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -699,7 +699,7 @@ static enum dc_status dcn10_prog_pixclk_crtc_otg( /* HW program guide assume display already disable * by unplug sequence. OTG assume stop. */ - pipe_ctx->tg->funcs->enable_optc_clock(pipe_ctx->tg, true); + pipe_ctx->stream_res.tg->funcs->enable_optc_clock(pipe_ctx->stream_res.tg, true); if (false == pipe_ctx->clock_source->funcs->program_pix_clk( pipe_ctx->clock_source, @@ -708,15 +708,15 @@ static enum dc_status dcn10_prog_pixclk_crtc_otg( BREAK_TO_DEBUGGER(); return DC_ERROR_UNEXPECTED; } - pipe_ctx->tg->dlg_otg_param.vready_offset = pipe_ctx->pipe_dlg_param.vready_offset; - pipe_ctx->tg->dlg_otg_param.vstartup_start = pipe_ctx->pipe_dlg_param.vstartup_start; - pipe_ctx->tg->dlg_otg_param.vupdate_offset = pipe_ctx->pipe_dlg_param.vupdate_offset; - pipe_ctx->tg->dlg_otg_param.vupdate_width = pipe_ctx->pipe_dlg_param.vupdate_width; + pipe_ctx->stream_res.tg->dlg_otg_param.vready_offset = pipe_ctx->pipe_dlg_param.vready_offset; + pipe_ctx->stream_res.tg->dlg_otg_param.vstartup_start = pipe_ctx->pipe_dlg_param.vstartup_start; + pipe_ctx->stream_res.tg->dlg_otg_param.vupdate_offset = pipe_ctx->pipe_dlg_param.vupdate_offset; + pipe_ctx->stream_res.tg->dlg_otg_param.vupdate_width = pipe_ctx->pipe_dlg_param.vupdate_width; - pipe_ctx->tg->dlg_otg_param.signal = pipe_ctx->stream->signal; + pipe_ctx->stream_res.tg->dlg_otg_param.signal = pipe_ctx->stream->signal; - pipe_ctx->tg->funcs->program_timing( - pipe_ctx->tg, + pipe_ctx->stream_res.tg->funcs->program_timing( + pipe_ctx->stream_res.tg, &stream->timing, true); @@ -729,7 +729,7 @@ static enum dc_status dcn10_prog_pixclk_crtc_otg( /* TODO: OPP FMT, ABM. etc. should be done here. */ /* or FPGA now. instance 0 only. TODO: move to opp.c */ - inst_offset = reg_offsets[pipe_ctx->tg->inst].fmt; + inst_offset = reg_offsets[pipe_ctx->stream_res.tg->inst].fmt; pipe_ctx->stream_res.opp->funcs->opp_program_fmt( pipe_ctx->stream_res.opp, @@ -739,15 +739,15 @@ static enum dc_status dcn10_prog_pixclk_crtc_otg( /* program otg blank color */ color_space = stream->output_color_space; color_space_to_black_color(dc, color_space, &black_color); - pipe_ctx->tg->funcs->set_blank_color( - pipe_ctx->tg, + pipe_ctx->stream_res.tg->funcs->set_blank_color( + pipe_ctx->stream_res.tg, &black_color); - pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, true); - hwss_wait_for_blank_complete(pipe_ctx->tg); + pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, true); + hwss_wait_for_blank_complete(pipe_ctx->stream_res.tg); /* VTG is within DCHUB command block. DCFCLK is always on */ - if (false == pipe_ctx->tg->funcs->enable_crtc(pipe_ctx->tg)) { + if (false == pipe_ctx->stream_res.tg->funcs->enable_crtc(pipe_ctx->stream_res.tg)) { BREAK_TO_DEBUGGER(); return DC_ERROR_UNEXPECTED; } @@ -787,9 +787,9 @@ static void reset_back_end_for_pipe( * parent pipe. */ if (pipe_ctx->top_pipe == NULL) { - pipe_ctx->tg->funcs->disable_crtc(pipe_ctx->tg); + pipe_ctx->stream_res.tg->funcs->disable_crtc(pipe_ctx->stream_res.tg); - pipe_ctx->tg->funcs->enable_optc_clock(pipe_ctx->tg, false); + pipe_ctx->stream_res.tg->funcs->enable_optc_clock(pipe_ctx->stream_res.tg, false); } if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) @@ -807,7 +807,7 @@ static void reset_back_end_for_pipe( pipe_ctx->stream = NULL; dm_logger_write(dc->ctx->logger, LOG_DC, "Reset back end for pipe %d, tg:%d\n", - pipe_ctx->pipe_idx, pipe_ctx->tg->inst); + pipe_ctx->pipe_idx, pipe_ctx->stream_res.tg->inst); } /* trigger HW to start disconnect plane from stream on the next vsync */ @@ -974,7 +974,7 @@ static void reset_hw_ctx_wrap( /* Lock*/ for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *cur_pipe_ctx = &dc->current_context->res_ctx.pipe_ctx[i]; - struct timing_generator *tg = cur_pipe_ctx->tg; + struct timing_generator *tg = cur_pipe_ctx->stream_res.tg; if (cur_pipe_ctx->stream) tg->funcs->lock(tg); @@ -995,7 +995,7 @@ static void reset_hw_ctx_wrap( /* Unlock*/ for (i = dc->res_pool->pipe_count - 1; i >= 0; i--) { struct pipe_ctx *cur_pipe_ctx = &dc->current_context->res_ctx.pipe_ctx[i]; - struct timing_generator *tg = cur_pipe_ctx->tg; + struct timing_generator *tg = cur_pipe_ctx->stream_res.tg; if (cur_pipe_ctx->stream) tg->funcs->unlock(tg); @@ -1488,9 +1488,9 @@ static void dcn10_pipe_control_lock( verify_allow_pstate_change_high(dc->hwseq); if (lock) - pipe->tg->funcs->lock(pipe->tg); + pipe->stream_res.tg->funcs->lock(pipe->stream_res.tg); else - pipe->tg->funcs->unlock(pipe->tg); + pipe->stream_res.tg->funcs->unlock(pipe->stream_res.tg); if (dc->public.debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); @@ -1545,8 +1545,8 @@ static void dcn10_enable_timing_synchronization( DC_SYNC_INFO("Setting up OTG reset trigger\n"); for (i = 1; i < group_size; i++) - grouped_pipes[i]->tg->funcs->enable_reset_trigger( - grouped_pipes[i]->tg, grouped_pipes[0]->tg->inst); + grouped_pipes[i]->stream_res.tg->funcs->enable_reset_trigger( + grouped_pipes[i]->stream_res.tg, grouped_pipes[0]->stream_res.tg->inst); DC_SYNC_INFO("Waiting for trigger\n"); @@ -1554,10 +1554,10 @@ static void dcn10_enable_timing_synchronization( /* Need to get only check 1 pipe for having reset as all the others are * synchronized. Look at last pipe programmed to reset. */ - wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[1]->tg); + wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[1]->stream_res.tg); for (i = 1; i < group_size; i++) - grouped_pipes[i]->tg->funcs->disable_reset_trigger( - grouped_pipes[i]->tg); + grouped_pipes[i]->stream_res.tg->funcs->disable_reset_trigger( + grouped_pipes[i]->stream_res.tg); DC_SYNC_INFO("Sync complete\n"); } @@ -1700,7 +1700,7 @@ static void dcn10_power_on_fe( HUBP_CLOCK_ENABLE, 1); /* make sure OPP_PIPE_CLOCK_EN = 1 */ - REG_UPDATE(OPP_PIPE_CONTROL[pipe_ctx->tg->inst], + REG_UPDATE(OPP_PIPE_CONTROL[pipe_ctx->stream_res.tg->inst], OPP_PIPE_CLOCK_EN, 1); /*TODO: REG_UPDATE(DENTIST_DISPCLK_CNTL, DENTIST_DPPCLK_WDIVIDER, 0x1f);*/ @@ -1920,7 +1920,7 @@ static void update_dchubp_dpp( * VTG is within DCHUBBUB which is commond block share by each pipe HUBP. * VTG is 1:1 mapping with OTG. Each pipe HUBP will select which VTG */ - REG_UPDATE(DCHUBP_CNTL[pipe_ctx->pipe_idx], HUBP_VTG_SEL, pipe_ctx->tg->inst); + REG_UPDATE(DCHUBP_CNTL[pipe_ctx->pipe_idx], HUBP_VTG_SEL, pipe_ctx->stream_res.tg->inst); update_plane_addr(dc, pipe_ctx); @@ -2012,17 +2012,17 @@ static void program_all_pipe_in_tree( verify_allow_pstate_change_high(dc->hwseq); } - pipe_ctx->tg->funcs->lock(pipe_ctx->tg); + pipe_ctx->stream_res.tg->funcs->lock(pipe_ctx->stream_res.tg); - pipe_ctx->tg->dlg_otg_param.vready_offset = pipe_ctx->pipe_dlg_param.vready_offset; - pipe_ctx->tg->dlg_otg_param.vstartup_start = pipe_ctx->pipe_dlg_param.vstartup_start; - pipe_ctx->tg->dlg_otg_param.vupdate_offset = pipe_ctx->pipe_dlg_param.vupdate_offset; - pipe_ctx->tg->dlg_otg_param.vupdate_width = pipe_ctx->pipe_dlg_param.vupdate_width; - pipe_ctx->tg->dlg_otg_param.signal = pipe_ctx->stream->signal; + pipe_ctx->stream_res.tg->dlg_otg_param.vready_offset = pipe_ctx->pipe_dlg_param.vready_offset; + pipe_ctx->stream_res.tg->dlg_otg_param.vstartup_start = pipe_ctx->pipe_dlg_param.vstartup_start; + pipe_ctx->stream_res.tg->dlg_otg_param.vupdate_offset = pipe_ctx->pipe_dlg_param.vupdate_offset; + pipe_ctx->stream_res.tg->dlg_otg_param.vupdate_width = pipe_ctx->pipe_dlg_param.vupdate_width; + pipe_ctx->stream_res.tg->dlg_otg_param.signal = pipe_ctx->stream->signal; - pipe_ctx->tg->funcs->program_global_sync( - pipe_ctx->tg); - pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, !is_pipe_tree_visible(pipe_ctx)); + pipe_ctx->stream_res.tg->funcs->program_global_sync( + pipe_ctx->stream_res.tg); + pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, !is_pipe_tree_visible(pipe_ctx)); } if (pipe_ctx->plane_state != NULL) { @@ -2098,20 +2098,20 @@ static void dcn10_apply_ctx_for_surface( */ if (pipe_ctx->plane_state && !old_pipe_ctx->plane_state) { - if (pipe_ctx->plane_res.mi->opp_id != 0xf && pipe_ctx->tg->inst == be_idx) { + if (pipe_ctx->plane_res.mi->opp_id != 0xf && pipe_ctx->stream_res.tg->inst == be_idx) { dcn10_power_down_fe(dc, pipe_ctx->pipe_idx); /* * power down fe will unlock when calling reset, need * to lock it back here. Messy, need rework. */ - pipe_ctx->tg->funcs->lock(pipe_ctx->tg); + pipe_ctx->stream_res.tg->funcs->lock(pipe_ctx->stream_res.tg); } } if ((!pipe_ctx->plane_state && old_pipe_ctx->plane_state) || (!pipe_ctx->stream && old_pipe_ctx->stream)) { - if (old_pipe_ctx->tg->inst != be_idx) + if (old_pipe_ctx->stream_res.tg->inst != be_idx) continue; if (!old_pipe_ctx->top_pipe) { @@ -2279,7 +2279,7 @@ static void set_drr(struct pipe_ctx **pipe_ctx, * some GSL stuff */ for (i = 0; i < num_pipes; i++) { - pipe_ctx[i]->tg->funcs->set_drr(pipe_ctx[i]->tg, ¶ms); + pipe_ctx[i]->stream_res.tg->funcs->set_drr(pipe_ctx[i]->stream_res.tg, ¶ms); } } @@ -2292,7 +2292,7 @@ static void get_position(struct pipe_ctx **pipe_ctx, /* TODO: handle pipes > 1 */ for (i = 0; i < num_pipes; i++) - pipe_ctx[i]->tg->funcs->get_position(pipe_ctx[i]->tg, position); + pipe_ctx[i]->stream_res.tg->funcs->get_position(pipe_ctx[i]->stream_res.tg, position); } static void set_static_screen_control(struct pipe_ctx **pipe_ctx, @@ -2307,8 +2307,8 @@ static void set_static_screen_control(struct pipe_ctx **pipe_ctx, value |= 0x2; for (i = 0; i < num_pipes; i++) - pipe_ctx[i]->tg->funcs-> - set_static_screen_control(pipe_ctx[i]->tg, value); + pipe_ctx[i]->stream_res.tg->funcs-> + set_static_screen_control(pipe_ctx[i]->stream_res.tg, value); } static void set_plane_config( @@ -2369,8 +2369,8 @@ static void dcn10_setup_stereo(struct pipe_ctx *pipe_ctx, struct core_dc *dc) flags.PROGRAM_STEREO == 1 ? true:false, stream->timing.flags.RIGHT_EYE_3D_POLARITY == 1 ? true:false); - pipe_ctx->tg->funcs->program_stereo( - pipe_ctx->tg, + pipe_ctx->stream_res.tg->funcs->program_stereo( + pipe_ctx->stream_res.tg, &stream->timing, &flags); @@ -2469,7 +2469,7 @@ static bool dcn10_dummy_display_power_gating( void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx) { struct dc_plane_state *plane_state = pipe_ctx->plane_state; - struct timing_generator *tg = pipe_ctx->tg; + struct timing_generator *tg = pipe_ctx->stream_res.tg; if (plane_state->ctx->dc->debug.sanity_checks) { struct core_dc *dc = DC_TO_CORE(plane_state->ctx->dc); @@ -2496,7 +2496,7 @@ void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx) if (pipe_ctx->plane_res.mi->current_address.type == PLN_ADDR_TYPE_GRPH_STEREO && tg->funcs->is_stereo_left_eye) { plane_state->status.is_right_eye = - !tg->funcs->is_stereo_left_eye(pipe_ctx->tg); + !tg->funcs->is_stereo_left_eye(pipe_ctx->stream_res.tg); } } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index e15eec315228..bb9a42d0a147 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -960,7 +960,7 @@ static struct pipe_ctx *dcn10_acquire_idle_pipe_for_layer( return false; idle_pipe->stream = head_pipe->stream; - idle_pipe->tg = head_pipe->tg; + idle_pipe->stream_res.tg = head_pipe->stream_res.tg; idle_pipe->stream_res.opp = head_pipe->stream_res.opp; idle_pipe->plane_res.mi = pool->mis[idle_pipe->pipe_idx]; diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 24a525495bfc..488ade37e353 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -154,6 +154,7 @@ struct resource_pool { struct stream_resource { struct output_pixel_processor *opp; + struct timing_generator *tg; }; struct plane_resource { @@ -171,8 +172,6 @@ struct pipe_ctx { struct plane_resource plane_res; struct stream_resource stream_res; - struct timing_generator *tg; - struct stream_encoder *stream_enc; struct display_clock *dis_clk; struct clock_source *clock_source; diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c index 52361d1472fa..24e47eb8cf3f 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c @@ -214,7 +214,7 @@ bool dce110_vblank_set( uint8_t pipe_offset = dal_irq_src - IRQ_TYPE_VBLANK; struct timing_generator *tg = - core_dc->current_context->res_ctx.pipe_ctx[pipe_offset].tg; + core_dc->current_context->res_ctx.pipe_ctx[pipe_offset].stream_res.tg; if (enable) { if (!tg->funcs->arm_vert_intr(tg, 2)) { -- cgit From 8e9c4c8cf35ff23aafc69f9ef4c9cc471dac4094 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Sun, 30 Jul 2017 14:36:12 -0400 Subject: drm/amd/display: Move stream_enc to stream_res find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/pipes->stream_enc/pipes->stream_res\.stream_enc/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/ctx->stream_enc->/ctx->stream_res\.stream_enc->/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/pipe->stream_enc/pipe->stream_res\.stream_enc/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/pipe_ctx->stream_enc/pipe_ctx->stream_res\.stream_enc/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/pipe_ctx\[pipe_offset\]\.stream_enc/pipe_ctx\[pipe_offset\]\.stream_res\.stream_enc/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/grouped_pipes\[i\]->stream_enc/grouped_pipes\[i\]->stream_^Cs\.stream_enc/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/grouped_pipes\[0\]->stream_enc/grouped_pipes\[0\]->stream_res\.stream_enc/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/grouped_pipes\[1\]->stream_enc/grouped_pipes\[1\]->stream_res\.stream_enc/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/pipe_ctx\[i\]->stream_enc/pipe_ctx\[i\]->stream_res\.stream_enc/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/pipe_ctx_old->stream_enc/pipe_ctx_old->stream_res\.stream_enc/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/pipe_set\[j\]->stream_enc/pipe_set\[j\]->stream_res\.stream_enc/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/pipe_ctx\[i\]\.stream_enc/pipe_ctx\[i\]\.stream_res\.stream_enc/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/pipes\[i\]\.stream_enc/pipes\[i\]\.stream_res\.stream_enc/g' Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 4 +- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 12 ++-- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 6 +- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 16 ++--- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 72 +++++++++++----------- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 2 +- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 2 +- 8 files changed, 58 insertions(+), 58 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 61c2a210c123..748e709c611f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -161,7 +161,7 @@ static bool stream_adjust_vmin_vmax(struct dc *dc, for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe = &core_dc->current_context->res_ctx.pipe_ctx[i]; - if (pipe->stream == stream && pipe->stream_enc) { + if (pipe->stream == stream && pipe->stream_res.stream_enc) { core_dc->hwss.set_drr(&pipe, 1, vmin, vmax); /* build and update the info frame */ @@ -189,7 +189,7 @@ static bool stream_get_crtc_position(struct dc *dc, struct pipe_ctx *pipe = &core_dc->current_context->res_ctx.pipe_ctx[i]; - if (pipe->stream == stream && pipe->stream_enc) { + if (pipe->stream == stream && pipe->stream_res.stream_enc) { core_dc->hwss.get_position(&pipe, 1, &position); *v_pos = position.vertical_count; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 2c43edf2c7c4..6a3d2ad97d5d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1311,8 +1311,8 @@ static enum dc_status enable_link(struct pipe_ctx *pipe_ctx) /* un-mute audio */ /* TODO: audio should be per stream rather than per link */ - pipe_ctx->stream_enc->funcs->audio_mute_control( - pipe_ctx->stream_enc, false); + pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control( + pipe_ctx->stream_res.stream_enc, false); } return status; @@ -1699,7 +1699,7 @@ static enum dc_status allocate_mst_payload(struct pipe_ctx *pipe_ctx) struct dc_stream_state *stream = pipe_ctx->stream; struct dc_link *link = stream->sink->link; struct link_encoder *link_encoder = link->link_enc; - struct stream_encoder *stream_encoder = pipe_ctx->stream_enc; + struct stream_encoder *stream_encoder = pipe_ctx->stream_res.stream_enc; struct dp_mst_stream_allocation_table proposed_table = {0}; struct fixed31_32 avg_time_slots_per_mtp; struct fixed31_32 pbn; @@ -1718,7 +1718,7 @@ static enum dc_status allocate_mst_payload(struct pipe_ctx *pipe_ctx) &proposed_table, true)) { update_mst_stream_alloc_table( - link, pipe_ctx->stream_enc, &proposed_table); + link, pipe_ctx->stream_res.stream_enc, &proposed_table); } else dm_logger_write(link->ctx->logger, LOG_WARNING, @@ -1781,7 +1781,7 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx) struct dc_stream_state *stream = pipe_ctx->stream; struct dc_link *link = stream->sink->link; struct link_encoder *link_encoder = link->link_enc; - struct stream_encoder *stream_encoder = pipe_ctx->stream_enc; + struct stream_encoder *stream_encoder = pipe_ctx->stream_res.stream_enc; struct dp_mst_stream_allocation_table proposed_table = {0}; struct fixed31_32 avg_time_slots_per_mtp = dal_fixed31_32_from_int(0); uint8_t i; @@ -1808,7 +1808,7 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx) false)) { update_mst_stream_alloc_table( - link, pipe_ctx->stream_enc, &proposed_table); + link, pipe_ctx->stream_res.stream_enc, &proposed_table); } else { dm_logger_write(link->ctx->logger, LOG_WARNING, 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 eda25942aea0..3d296b1d118f 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 @@ -2464,7 +2464,7 @@ bool dc_link_dp_set_test_pattern( * MuteAudioEndpoint(pPathMode->pDisplayPath, true); */ /* Blank stream */ - pipes->stream_enc->funcs->dp_blank(pipe_ctx->stream_enc); + pipes->stream_res.stream_enc->funcs->dp_blank(pipe_ctx->stream_res.stream_enc); } dp_set_hw_test_pattern(link, test_pattern, diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index f2f57a75f864..7d52c6c7cf89 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -243,12 +243,12 @@ void dp_retrain_link_dp_test(struct dc_link *link, if (pipes[i].stream != NULL && pipes[i].stream->sink != NULL && pipes[i].stream->sink->link != NULL && - pipes[i].stream_enc != NULL && + pipes[i].stream_res.stream_enc != NULL && pipes[i].stream->sink->link == link) { dm_delay_in_microseconds(link->ctx, 100); - pipes[i].stream_enc->funcs->dp_blank( - pipes[i].stream_enc); + pipes[i].stream_res.stream_enc->funcs->dp_blank( + pipes[i].stream_res.stream_enc); /* disable any test pattern that might be active */ dp_set_hw_test_pattern(link, diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 5326713bf3fb..13feff1003d8 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -925,7 +925,7 @@ struct pipe_ctx *resource_get_head_pipe_for_stream( int i; for (i = 0; i < MAX_PIPES; i++) { if (res_ctx->pipe_ctx[i].stream == stream && - res_ctx->pipe_ctx[i].stream_enc) { + res_ctx->pipe_ctx[i].stream_res.stream_enc) { return &res_ctx->pipe_ctx[i]; break; } @@ -1096,7 +1096,7 @@ bool resource_attach_surfaces_to_context( if (tail_pipe) { free_pipe->stream_res.tg = tail_pipe->stream_res.tg; free_pipe->stream_res.opp = tail_pipe->stream_res.opp; - free_pipe->stream_enc = tail_pipe->stream_enc; + free_pipe->stream_res.stream_enc = tail_pipe->stream_res.stream_enc; free_pipe->audio = tail_pipe->audio; free_pipe->clock_source = tail_pipe->clock_source; free_pipe->top_pipe = tail_pipe; @@ -1461,12 +1461,12 @@ enum dc_status resource_map_pool_resources( copy_pipe_ctx(old_pipe_ctx, pipe_ctx); /* Split pipe resource, do not acquire back end */ - if (!pipe_ctx->stream_enc) + if (!pipe_ctx->stream_res.stream_enc) continue; set_stream_engine_in_use( &context->res_ctx, pool, - pipe_ctx->stream_enc); + pipe_ctx->stream_res.stream_enc); /* Switch to dp clock source only if there is * no non dp stream that shares the same timing @@ -1503,16 +1503,16 @@ enum dc_status resource_map_pool_resources( pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx]; - pipe_ctx->stream_enc = + pipe_ctx->stream_res.stream_enc = find_first_free_match_stream_enc_for_link( &context->res_ctx, pool, stream); - if (!pipe_ctx->stream_enc) + if (!pipe_ctx->stream_res.stream_enc) return DC_NO_STREAM_ENG_RESOURCE; set_stream_engine_in_use( &context->res_ctx, pool, - pipe_ctx->stream_enc); + pipe_ctx->stream_res.stream_enc); /* TODO: Add check if ASIC support and EDID audio */ if (!stream->sink->converter_disable_audio && @@ -2382,7 +2382,7 @@ bool pipe_need_reprogram( && pipe_ctx_old->stream != pipe_ctx->stream) return true; - if (pipe_ctx_old->stream_enc != pipe_ctx->stream_enc) + if (pipe_ctx_old->stream_res.stream_enc != pipe_ctx->stream_res.stream_enc) return true; if (is_timing_changed(pipe_ctx_old->stream, pipe_ctx->stream)) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 1d7c7fb668be..48d151039fe8 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -659,7 +659,7 @@ static enum dc_status bios_parser_crtc_source_select( struct bp_crtc_source_select crtc_source_select = {0}; const struct dc_sink *sink = pipe_ctx->stream->sink; - crtc_source_select.engine_id = pipe_ctx->stream_enc->id; + crtc_source_select.engine_id = pipe_ctx->stream_res.stream_enc->id; crtc_source_select.controller_id = pipe_ctx->pipe_idx + 1; /*TODO: Need to un-hardcode color depth, dp_audio and account for * the case where signal and sink signal is different (translator @@ -684,16 +684,16 @@ void dce110_update_info_frame(struct pipe_ctx *pipe_ctx) { ASSERT(pipe_ctx->stream); - if (pipe_ctx->stream_enc == NULL) + if (pipe_ctx->stream_res.stream_enc == NULL) return; /* this is not root pipe */ if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) - pipe_ctx->stream_enc->funcs->update_hdmi_info_packets( - pipe_ctx->stream_enc, + pipe_ctx->stream_res.stream_enc->funcs->update_hdmi_info_packets( + pipe_ctx->stream_res.stream_enc, &pipe_ctx->encoder_info_frame); else if (dc_is_dp_signal(pipe_ctx->stream->signal)) - pipe_ctx->stream_enc->funcs->update_dp_info_packets( - pipe_ctx->stream_enc, + pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets( + pipe_ctx->stream_res.stream_enc, &pipe_ctx->encoder_info_frame); } @@ -731,7 +731,7 @@ void dce110_enable_stream(struct pipe_ctx *pipe_ctx) /* enable audio only within mode set */ if (pipe_ctx->audio != NULL) { if (dc_is_dp_signal(pipe_ctx->stream->signal)) - pipe_ctx->stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_enc); + pipe_ctx->stream_res.stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_res.stream_enc); } /* For MST, there are multiply stream go to only one link. @@ -739,7 +739,7 @@ void dce110_enable_stream(struct pipe_ctx *pipe_ctx) * disconnect them during disable_stream * BY this, it is logic clean to separate stream and link */ link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc, - pipe_ctx->stream_enc->id, true); + pipe_ctx->stream_res.stream_enc->id, true); } @@ -752,11 +752,11 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) pipe_ctx->audio->funcs->az_disable(pipe_ctx->audio); if (dc_is_dp_signal(pipe_ctx->stream->signal)) - pipe_ctx->stream_enc->funcs->dp_audio_disable( - pipe_ctx->stream_enc); + pipe_ctx->stream_res.stream_enc->funcs->dp_audio_disable( + pipe_ctx->stream_res.stream_enc); else - pipe_ctx->stream_enc->funcs->hdmi_audio_disable( - pipe_ctx->stream_enc); + pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_disable( + pipe_ctx->stream_res.stream_enc); pipe_ctx->audio = NULL; @@ -768,24 +768,24 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) } if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) - pipe_ctx->stream_enc->funcs->stop_hdmi_info_packets( - pipe_ctx->stream_enc); + pipe_ctx->stream_res.stream_enc->funcs->stop_hdmi_info_packets( + pipe_ctx->stream_res.stream_enc); if (dc_is_dp_signal(pipe_ctx->stream->signal)) - pipe_ctx->stream_enc->funcs->stop_dp_info_packets( - pipe_ctx->stream_enc); + pipe_ctx->stream_res.stream_enc->funcs->stop_dp_info_packets( + pipe_ctx->stream_res.stream_enc); - pipe_ctx->stream_enc->funcs->audio_mute_control( - pipe_ctx->stream_enc, true); + pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control( + pipe_ctx->stream_res.stream_enc, true); /* blank at encoder level */ if (dc_is_dp_signal(pipe_ctx->stream->signal)) - pipe_ctx->stream_enc->funcs->dp_blank(pipe_ctx->stream_enc); + pipe_ctx->stream_res.stream_enc->funcs->dp_blank(pipe_ctx->stream_res.stream_enc); link->link_enc->funcs->connect_dig_be_to_fe( link->link_enc, - pipe_ctx->stream_enc->id, + pipe_ctx->stream_res.stream_enc->id, false); } @@ -799,14 +799,14 @@ void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, params.pixel_clk_khz = pipe_ctx->stream->timing.pix_clk_khz; params.link_settings.link_rate = link_settings->link_rate; - pipe_ctx->stream_enc->funcs->dp_unblank(pipe_ctx->stream_enc, ¶ms); + pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(pipe_ctx->stream_res.stream_enc, ¶ms); } void dce110_set_avmute(struct pipe_ctx *pipe_ctx, bool enable) { - if (pipe_ctx != NULL && pipe_ctx->stream_enc != NULL) - pipe_ctx->stream_enc->funcs->set_avmute(pipe_ctx->stream_enc, enable); + if (pipe_ctx != NULL && pipe_ctx->stream_res.stream_enc != NULL) + pipe_ctx->stream_res.stream_enc->funcs->set_avmute(pipe_ctx->stream_res.stream_enc, enable); } static enum audio_dto_source translate_to_dto_source(enum controller_id crtc_id) @@ -834,7 +834,7 @@ static void build_audio_output( struct audio_output *audio_output) { const struct dc_stream_state *stream = pipe_ctx->stream; - audio_output->engine_id = pipe_ctx->stream_enc->id; + audio_output->engine_id = pipe_ctx->stream_res.stream_enc->id; audio_output->signal = pipe_ctx->stream->signal; @@ -1071,8 +1071,8 @@ static enum dc_status apply_single_controller_ctx_to_hw( pipe_ctx->stream->signal); if (pipe_ctx->stream->signal != SIGNAL_TYPE_VIRTUAL) - pipe_ctx->stream_enc->funcs->setup_stereo_sync( - pipe_ctx->stream_enc, + pipe_ctx->stream_res.stream_enc->funcs->setup_stereo_sync( + pipe_ctx->stream_res.stream_enc, pipe_ctx->stream_res.tg->inst, stream->timing.timing_3d_format != TIMING_3D_FORMAT_NONE); @@ -1084,21 +1084,21 @@ static enum dc_status apply_single_controller_ctx_to_hw( &stream->clamping); if (dc_is_dp_signal(pipe_ctx->stream->signal)) - pipe_ctx->stream_enc->funcs->dp_set_stream_attribute( - pipe_ctx->stream_enc, + pipe_ctx->stream_res.stream_enc->funcs->dp_set_stream_attribute( + pipe_ctx->stream_res.stream_enc, &stream->timing, stream->output_color_space); if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) - pipe_ctx->stream_enc->funcs->hdmi_set_stream_attribute( - pipe_ctx->stream_enc, + pipe_ctx->stream_res.stream_enc->funcs->hdmi_set_stream_attribute( + pipe_ctx->stream_res.stream_enc, &stream->timing, stream->phy_pix_clk, pipe_ctx->audio != NULL); if (dc_is_dvi_signal(pipe_ctx->stream->signal)) - pipe_ctx->stream_enc->funcs->dvi_set_stream_attribute( - pipe_ctx->stream_enc, + pipe_ctx->stream_res.stream_enc->funcs->dvi_set_stream_attribute( + pipe_ctx->stream_res.stream_enc, &stream->timing, (pipe_ctx->stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK) ? true : false); @@ -1860,13 +1860,13 @@ enum dc_status dce110_apply_ctx_to_hw( build_audio_output(pipe_ctx, &audio_output); if (dc_is_dp_signal(pipe_ctx->stream->signal)) - pipe_ctx->stream_enc->funcs->dp_audio_setup( - pipe_ctx->stream_enc, + pipe_ctx->stream_res.stream_enc->funcs->dp_audio_setup( + pipe_ctx->stream_res.stream_enc, pipe_ctx->audio->inst, &pipe_ctx->stream->audio_info); else - pipe_ctx->stream_enc->funcs->hdmi_audio_setup( - pipe_ctx->stream_enc, + pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_setup( + pipe_ctx->stream_res.stream_enc, pipe_ctx->audio->inst, &pipe_ctx->stream->audio_info, &audio_output.crtc_info); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 99ef0f25492c..16ac96358620 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -770,7 +770,7 @@ static void reset_back_end_for_pipe( { int i; - if (pipe_ctx->stream_enc == NULL) { + if (pipe_ctx->stream_res.stream_enc == NULL) { pipe_ctx->stream = NULL; return; } diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 488ade37e353..4d35c6d120a7 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -155,6 +155,7 @@ struct resource_pool { struct stream_resource { struct output_pixel_processor *opp; struct timing_generator *tg; + struct stream_encoder *stream_enc; }; struct plane_resource { @@ -172,7 +173,6 @@ struct pipe_ctx { struct plane_resource plane_res; struct stream_resource stream_res; - struct stream_encoder *stream_enc; struct display_clock *dis_clk; struct clock_source *clock_source; -- cgit From 0b73b84cf59334e48d56e5ef5e121f4ecd02be44 Mon Sep 17 00:00:00 2001 From: Kenny Tsao Date: Sun, 30 Jul 2017 16:17:49 -0400 Subject: drm/amd/display: remove remaining DCN1 guard Signed-off-by: Kenny Tsao Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index a0531b3aa6a1..9a97d8ee7971 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -130,7 +130,6 @@ HWSEQ_PIXEL_RATE_REG_LIST(CRTC), \ HWSEQ_PHYPLL_REG_LIST(CRTC) -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) #define HWSEQ_DCN_REG_LIST()\ HWSEQ_PIXEL_RATE_REG_LIST(OTG), \ HWSEQ_PHYPLL_REG_LIST(OTG), \ @@ -208,9 +207,7 @@ SR(D2VGA_CONTROL), \ SR(D3VGA_CONTROL), \ SR(D4VGA_CONTROL) -#endif -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) #define HWSEQ_DCN1_REG_LIST()\ HWSEQ_DCN_REG_LIST(), \ SR(DCHUBBUB_SDPIF_FB_TOP),\ @@ -219,7 +216,6 @@ SR(DCHUBBUB_SDPIF_AGP_BASE),\ SR(DCHUBBUB_SDPIF_AGP_BOT),\ SR(DCHUBBUB_SDPIF_AGP_TOP) -#endif struct dce_hwseq_registers { @@ -238,7 +234,6 @@ struct dce_hwseq_registers { uint32_t DCHUB_AGP_BOT; uint32_t DCHUB_AGP_TOP; -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) uint32_t OTG_GLOBAL_SYNC_STATUS[4]; uint32_t DCHUBP_CNTL[4]; uint32_t HUBP_CLK_CNTL[4]; @@ -317,7 +312,6 @@ struct dce_hwseq_registers { uint32_t D2VGA_CONTROL; uint32_t D3VGA_CONTROL; uint32_t D4VGA_CONTROL; -#endif }; /* set field name */ #define HWS_SF(blk_name, reg_name, field_name, post_fix)\ @@ -386,7 +380,6 @@ struct dce_hwseq_registers { HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, CRTC0_),\ HWSEQ_GFX9_DCHUB_MASK_SH_LIST(mask_sh) -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) #define HWSEQ_DCN_MASK_SH_LIST(mask_sh)\ HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, OTG0_),\ HWS_SF1(OTG0_, PHYPLL_PIXEL_RATE_CNTL, PHYPLL_PIXEL_RATE_SOURCE, mask_sh), \ @@ -429,9 +422,7 @@ struct dce_hwseq_registers { HWS_SF(, DCHUBBUB_ARB_SAT_LEVEL, DCHUBBUB_ARB_SAT_LEVEL, mask_sh), \ HWS_SF(, DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MIN_REQ_OUTSTAND, mask_sh), \ HWS_SF(, DCFCLK_CNTL, DCFCLK_GATE_DIS, mask_sh) -#endif -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) #define HWSEQ_DCN1_MASK_SH_LIST(mask_sh)\ HWSEQ_DCN_MASK_SH_LIST(mask_sh), \ HWS_SF1(OTG0_, PHYPLL_PIXEL_RATE_CNTL, PIXEL_RATE_PLL_SOURCE, mask_sh), \ @@ -442,7 +433,6 @@ struct dce_hwseq_registers { HWS_SF(, DCHUBBUB_SDPIF_AGP_BOT, SDPIF_AGP_BOT, mask_sh), \ HWS_SF(, DCHUBBUB_SDPIF_AGP_TOP, SDPIF_AGP_TOP, mask_sh), \ HWS_SF(DPP_TOP0_, DPP_CONTROL, DPPCLK_RATE_CONTROL, mask_sh) -#endif #define HWSEQ_REG_FIELD_LIST(type) \ type DCFE_CLOCK_ENABLE; \ -- cgit From afaacef482759215681ad0a8c6a8b60cc7d29592 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Sun, 30 Jul 2017 14:59:17 -0400 Subject: drm/amd/display: Move audio to stream_res find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/pipes->audio/pipes->stream_res\.audio/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/pipe_with_clk_src->audio/pipe_with_clk_src->stream_res\.audio/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/ctx->audio->/ctx->stream_res\.audio->/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/pipe->audio/pipe->stream_res\.audio/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/pipe_ctx->audio/pipe_ctx->stream_res\.audio/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/pipe_ctx\[pipe_offset\]\.audio/pipe_ctx\[pipe_offset\]\.stream_res\.audio/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/grouped_pipes\[i\]->audio/grouped_pipes\[i\]->stream_^Cs\.audio/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/grouped_pipes\[0\]->audio/grouped_pipes\[0\]->stream_res\.audio/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/grouped_pipes\[1\]->audio/grouped_pipes\[1\]->stream_res\.audio/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/pipe_ctx\[i\]->audio/pipe_ctx\[i\]->stream_res\.audio/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/pipe_ctx_old->audio/pipe_ctx_old->stream_res\.audio/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/pipe_set\[j\]->audio/pipe_set\[j\]->stream_res\.audio/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/pipe_ctx\[i\]\.audio/pipe_ctx\[i\]\.stream_res\.audio/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/pipes\[i\]\.audio/pipes\[i\]\.stream_res\.audio/g' Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 4 +-- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 12 ++++---- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 32 +++++++++++----------- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 3 +- 4 files changed, 25 insertions(+), 26 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 6a3d2ad97d5d..9665fc127fe2 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1305,9 +1305,9 @@ static enum dc_status enable_link(struct pipe_ctx *pipe_ctx) break; } - if (pipe_ctx->audio && status == DC_OK) { + if (pipe_ctx->stream_res.audio && status == DC_OK) { /* notify audio driver for audio modes of monitor */ - pipe_ctx->audio->funcs->az_enable(pipe_ctx->audio); + pipe_ctx->stream_res.audio->funcs->az_enable(pipe_ctx->stream_res.audio); /* un-mute audio */ /* TODO: audio should be per stream rather than per link */ diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 13feff1003d8..5c1d3c568090 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1097,7 +1097,7 @@ bool resource_attach_surfaces_to_context( free_pipe->stream_res.tg = tail_pipe->stream_res.tg; free_pipe->stream_res.opp = tail_pipe->stream_res.opp; free_pipe->stream_res.stream_enc = tail_pipe->stream_res.stream_enc; - free_pipe->audio = tail_pipe->audio; + free_pipe->stream_res.audio = tail_pipe->stream_res.audio; free_pipe->clock_source = tail_pipe->clock_source; free_pipe->top_pipe = tail_pipe; tail_pipe->bottom_pipe = free_pipe; @@ -1481,7 +1481,7 @@ enum dc_status resource_map_pool_resources( pipe_ctx->clock_source); set_audio_in_use(&context->res_ctx, pool, - pipe_ctx->audio); + pipe_ctx->stream_res.audio); } } @@ -1518,7 +1518,7 @@ enum dc_status resource_map_pool_resources( if (!stream->sink->converter_disable_audio && dc_is_audio_capable_signal(pipe_ctx->stream->signal) && stream->audio_info.mode_count) { - pipe_ctx->audio = find_first_free_audio( + pipe_ctx->stream_res.audio = find_first_free_audio( &context->res_ctx, pool); /* @@ -1526,10 +1526,10 @@ enum dc_status resource_map_pool_resources( * There are asics which has number of audio * resources less then number of pipes */ - if (pipe_ctx->audio) + if (pipe_ctx->stream_res.audio) set_audio_in_use( &context->res_ctx, pool, - pipe_ctx->audio); + pipe_ctx->stream_res.audio); } context->stream_status[i].primary_otg_inst = pipe_ctx->stream_res.tg->inst; @@ -2375,7 +2375,7 @@ bool pipe_need_reprogram( if (pipe_ctx_old->stream->signal != pipe_ctx->stream->signal) return true; - if (pipe_ctx_old->audio != pipe_ctx->audio) + if (pipe_ctx_old->stream_res.audio != pipe_ctx->stream_res.audio) return true; if (pipe_ctx_old->clock_source != pipe_ctx->clock_source diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 48d151039fe8..ef5d496656e5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -729,7 +729,7 @@ void dce110_enable_stream(struct pipe_ctx *pipe_ctx) tg->funcs->set_early_control(tg, early_control); /* enable audio only within mode set */ - if (pipe_ctx->audio != NULL) { + if (pipe_ctx->stream_res.audio != NULL) { if (dc_is_dp_signal(pipe_ctx->stream->signal)) pipe_ctx->stream_res.stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_res.stream_enc); } @@ -748,8 +748,8 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) struct dc_stream_state *stream = pipe_ctx->stream; struct dc_link *link = stream->sink->link; - if (pipe_ctx->audio) { - pipe_ctx->audio->funcs->az_disable(pipe_ctx->audio); + if (pipe_ctx->stream_res.audio) { + pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio); if (dc_is_dp_signal(pipe_ctx->stream->signal)) pipe_ctx->stream_res.stream_enc->funcs->dp_audio_disable( @@ -758,7 +758,7 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_disable( pipe_ctx->stream_res.stream_enc); - pipe_ctx->audio = NULL; + pipe_ctx->stream_res.audio = NULL; /* TODO: notify audio driver for if audio modes list changed * add audio mode list change flag */ @@ -1094,7 +1094,7 @@ static enum dc_status apply_single_controller_ctx_to_hw( pipe_ctx->stream_res.stream_enc, &stream->timing, stream->phy_pix_clk, - pipe_ctx->audio != NULL); + pipe_ctx->stream_res.audio != NULL); if (dc_is_dvi_signal(pipe_ctx->stream->signal)) pipe_ctx->stream_res.stream_enc->funcs->dvi_set_stream_attribute( @@ -1792,13 +1792,13 @@ enum dc_status dce110_apply_ctx_to_hw( if (pipe_ctx->stream->signal != SIGNAL_TYPE_HDMI_TYPE_A) continue; - if (pipe_ctx->audio != NULL) { + if (pipe_ctx->stream_res.audio != NULL) { struct audio_output audio_output; build_audio_output(pipe_ctx, &audio_output); - pipe_ctx->audio->funcs->wall_dto_setup( - pipe_ctx->audio, + pipe_ctx->stream_res.audio->funcs->wall_dto_setup( + pipe_ctx->stream_res.audio, pipe_ctx->stream->signal, &audio_output.crtc_info, &audio_output.pll_info); @@ -1820,13 +1820,13 @@ enum dc_status dce110_apply_ctx_to_hw( if (!dc_is_dp_signal(pipe_ctx->stream->signal)) continue; - if (pipe_ctx->audio != NULL) { + if (pipe_ctx->stream_res.audio != NULL) { struct audio_output audio_output; build_audio_output(pipe_ctx, &audio_output); - pipe_ctx->audio->funcs->wall_dto_setup( - pipe_ctx->audio, + pipe_ctx->stream_res.audio->funcs->wall_dto_setup( + pipe_ctx->stream_res.audio, pipe_ctx->stream->signal, &audio_output.crtc_info, &audio_output.pll_info); @@ -1853,7 +1853,7 @@ enum dc_status dce110_apply_ctx_to_hw( if (pipe_ctx->top_pipe) continue; - if (context->res_ctx.pipe_ctx[i].audio != NULL) { + if (context->res_ctx.pipe_ctx[i].stream_res.audio != NULL) { struct audio_output audio_output; @@ -1862,17 +1862,17 @@ enum dc_status dce110_apply_ctx_to_hw( if (dc_is_dp_signal(pipe_ctx->stream->signal)) pipe_ctx->stream_res.stream_enc->funcs->dp_audio_setup( pipe_ctx->stream_res.stream_enc, - pipe_ctx->audio->inst, + pipe_ctx->stream_res.audio->inst, &pipe_ctx->stream->audio_info); else pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_setup( pipe_ctx->stream_res.stream_enc, - pipe_ctx->audio->inst, + pipe_ctx->stream_res.audio->inst, &pipe_ctx->stream->audio_info, &audio_output.crtc_info); - pipe_ctx->audio->funcs->az_configure( - pipe_ctx->audio, + pipe_ctx->stream_res.audio->funcs->az_configure( + pipe_ctx->stream_res.audio, pipe_ctx->stream->signal, &audio_output.crtc_info, &pipe_ctx->stream->audio_info); diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 4d35c6d120a7..6f09653ac2cb 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -156,6 +156,7 @@ struct stream_resource { struct output_pixel_processor *opp; struct timing_generator *tg; struct stream_encoder *stream_enc; + struct audio *audio; }; struct plane_resource { @@ -176,8 +177,6 @@ struct pipe_ctx { struct display_clock *dis_clk; struct clock_source *clock_source; - struct audio *audio; - struct pixel_clk_params pix_clk_params; struct pll_settings pll_settings; -- cgit From 10688217e3af3ec73892139bed3d23a6e1170a14 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Sun, 30 Jul 2017 15:17:43 -0400 Subject: drm/amd/display: Move pix_clk_params into stream_res find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/pipes->pix_clk_params/pipes->stream_res\.pix_clk_params/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/pipe_with_clk_src->pix_clk_params/pipe_with_clk_src->stream_res\.pix_clk_params/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/ctx->pix_clk_params->/ctx->stream_res\.pix_clk_params->/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/pipe->pix_clk_params/pipe->stream_res\.pix_clk_params/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/pipe_ctx->pix_clk_params/pipe_ctx->stream_res\.pix_clk_params/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/pipe_ctx\[pipe_offset\]\.pix_clk_params/pipe_ctx\[pipe_offset\]\.stream_res\.pix_clk_params/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/grouped_pipes\[i\]->pix_clk_params/grouped_pipes\[i\]->stream_^Cs\.pix_clk_params/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/grouped_pipes\[0\]->pix_clk_params/grouped_pipes\[0\]->stream_res\.pix_clk_params/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/grouped_pipes\[1\]->pix_clk_params/grouped_pipes\[1\]->stream_res\.pix_clk_params/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/pipe_ctx\[i\]->pix_clk_params/pipe_ctx\[i\]->stream_res\.pix_clk_params/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/pipe_ctx_old->pix_clk_params/pipe_ctx_old->stream_res\.pix_clk_params/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/pipe_set\[j\]->pix_clk_params/pipe_set\[j\]->stream_res\.pix_clk_params/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/pipe_ctx\[i\]\.pix_clk_params/pipe_ctx\[i\]\.stream_res\.pix_clk_params/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/pipes\[i\]\.pix_clk_params/pipes\[i\]\.stream_res\.pix_clk_params/g' Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 4 ++-- drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 4 ++-- .../gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 14 +++++++------- drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c | 4 ++-- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 4 ++-- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 4 ++-- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 3 ++- 7 files changed, 19 insertions(+), 18 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 9665fc127fe2..1279eb1dfc2e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1620,8 +1620,8 @@ static struct fixed31_32 get_pbn_from_timing(struct pipe_ctx *pipe_ctx) uint32_t numerator; uint32_t denominator; - bpc = get_color_depth(pipe_ctx->pix_clk_params.color_depth); - kbps = pipe_ctx->pix_clk_params.requested_pix_clk * bpc * 3; + bpc = get_color_depth(pipe_ctx->stream_res.pix_clk_params.color_depth); + kbps = pipe_ctx->stream_res.pix_clk_params.requested_pix_clk * bpc * 3; /* * margin 5300ppm + 300ppm ~ 0.6% as per spec, factor is 1.006 diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 7d52c6c7cf89..822568767f2d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -77,11 +77,11 @@ void dp_enable_link_phy( if (pipes[i].clock_source != NULL && pipes[i].clock_source->id != CLOCK_SOURCE_ID_DP_DTO) { pipes[i].clock_source = dp_cs; - pipes[i].pix_clk_params.requested_pix_clk = + pipes[i].stream_res.pix_clk_params.requested_pix_clk = pipes[i].stream->timing.pix_clk_khz; pipes[i].clock_source->funcs->program_pix_clk( pipes[i].clock_source, - &pipes[i].pix_clk_params, + &pipes[i].stream_res.pix_clk_params, &pipes[i].pll_settings); } } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index ef5d496656e5..93161a92a427 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -870,20 +870,20 @@ static void build_audio_output( stream->timing.display_color_depth; audio_output->crtc_info.requested_pixel_clock = - pipe_ctx->pix_clk_params.requested_pix_clk; + pipe_ctx->stream_res.pix_clk_params.requested_pix_clk; audio_output->crtc_info.calculated_pixel_clock = - pipe_ctx->pix_clk_params.requested_pix_clk; + pipe_ctx->stream_res.pix_clk_params.requested_pix_clk; /*for HDMI, audio ACR is with deep color ratio factor*/ if (dc_is_hdmi_signal(pipe_ctx->stream->signal) && audio_output->crtc_info.requested_pixel_clock == stream->timing.pix_clk_khz) { - if (pipe_ctx->pix_clk_params.pixel_encoding == PIXEL_ENCODING_YCBCR420) { + if (pipe_ctx->stream_res.pix_clk_params.pixel_encoding == PIXEL_ENCODING_YCBCR420) { audio_output->crtc_info.requested_pixel_clock = audio_output->crtc_info.requested_pixel_clock/2; audio_output->crtc_info.calculated_pixel_clock = - pipe_ctx->pix_clk_params.requested_pix_clk/2; + pipe_ctx->stream_res.pix_clk_params.requested_pix_clk/2; } } @@ -1003,7 +1003,7 @@ static enum dc_status dce110_prog_pixclk_crtc_otg( if (false == pipe_ctx->clock_source->funcs->program_pix_clk( pipe_ctx->clock_source, - &pipe_ctx->pix_clk_params, + &pipe_ctx->stream_res.pix_clk_params, &pipe_ctx->pll_settings)) { BREAK_TO_DEBUGGER(); return DC_ERROR_UNEXPECTED; @@ -1425,9 +1425,9 @@ static uint32_t get_max_pixel_clock_for_all_paths( if (pipe_ctx->top_pipe) continue; - if (pipe_ctx->pix_clk_params.requested_pix_clk > max_pix_clk) + if (pipe_ctx->stream_res.pix_clk_params.requested_pix_clk > max_pix_clk) max_pix_clk = - pipe_ctx->pix_clk_params.requested_pix_clk; + pipe_ctx->stream_res.pix_clk_params.requested_pix_clk; } if (max_pix_clk == 0) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 94058ee16029..c677f98c3516 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -748,10 +748,10 @@ static void get_pixel_clock_parameters( enum dc_status dce110_resource_build_pipe_hw_param(struct pipe_ctx *pipe_ctx) { - get_pixel_clock_parameters(pipe_ctx, &pipe_ctx->pix_clk_params); + get_pixel_clock_parameters(pipe_ctx, &pipe_ctx->stream_res.pix_clk_params); pipe_ctx->clock_source->funcs->get_pix_clk_dividers( pipe_ctx->clock_source, - &pipe_ctx->pix_clk_params, + &pipe_ctx->stream_res.pix_clk_params, &pipe_ctx->pll_settings); resource_build_bit_depth_reduction_params(pipe_ctx->stream, &pipe_ctx->stream->bit_depth_params); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 16ac96358620..e69839802889 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -703,7 +703,7 @@ static enum dc_status dcn10_prog_pixclk_crtc_otg( if (false == pipe_ctx->clock_source->funcs->program_pix_clk( pipe_ctx->clock_source, - &pipe_ctx->pix_clk_params, + &pipe_ctx->stream_res.pix_clk_params, &pipe_ctx->pll_settings)) { BREAK_TO_DEBUGGER(); return DC_ERROR_UNEXPECTED; @@ -1910,7 +1910,7 @@ static void update_dchubp_dpp( enable_dppclk( dc->hwseq, pipe_ctx->pipe_idx, - pipe_ctx->pix_clk_params.requested_pix_clk, + pipe_ctx->stream_res.pix_clk_params.requested_pix_clk, context->bw.dcn.calc_clk.dppclk_div); dc->current_context->bw.dcn.cur_clk.dppclk_div = context->bw.dcn.calc_clk.dppclk_div; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index bb9a42d0a147..ff2dcb7a491d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -806,11 +806,11 @@ static void build_clamping_params(struct dc_stream_state *stream) static enum dc_status build_pipe_hw_param(struct pipe_ctx *pipe_ctx) { - get_pixel_clock_parameters(pipe_ctx, &pipe_ctx->pix_clk_params); + get_pixel_clock_parameters(pipe_ctx, &pipe_ctx->stream_res.pix_clk_params); pipe_ctx->clock_source->funcs->get_pix_clk_dividers( pipe_ctx->clock_source, - &pipe_ctx->pix_clk_params, + &pipe_ctx->stream_res.pix_clk_params, &pipe_ctx->pll_settings); pipe_ctx->stream->clamping.pixel_encoding = pipe_ctx->stream->timing.pixel_encoding; diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 6f09653ac2cb..968835191da8 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -157,6 +157,8 @@ struct stream_resource { struct timing_generator *tg; struct stream_encoder *stream_enc; struct audio *audio; + + struct pixel_clk_params pix_clk_params; }; struct plane_resource { @@ -177,7 +179,6 @@ struct pipe_ctx { struct display_clock *dis_clk; struct clock_source *clock_source; - struct pixel_clk_params pix_clk_params; struct pll_settings pll_settings; /*fmt*/ -- cgit From 96c50c0d0cead772001fd4ab1861594c059e7e0f Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Sun, 30 Jul 2017 15:58:26 -0400 Subject: drm/amd/display: Move encoder_info_frame to stream_res find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/pipes->encoder_info_frame/pipes->stream_res\.encoder_info_frame/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/pipe_with_clk_src->encoder_info_frame/pipe_with_clk_src->stream_res\.encoder_info_frame/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/ctx->encoder_info_frame->/ctx->stream_res\.encoder_info_frame->/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/pipe->encoder_info_frame/pipe->stream_res\.encoder_info_frame/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/pipe_ctx->encoder_info_frame/pipe_ctx->stream_res\.encoder_info_frame/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/pipe_ctx\[pipe_offset\]\.encoder_info_frame/pipe_ctx\[pipe_offset\]\.stream_res\.encoder_info_frame/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/grouped_pipes\[i\]->encoder_info_frame/grouped_pipes\[i\]->stream_^Cs\.encoder_info_frame/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/grouped_pipes\[0\]->encoder_info_frame/grouped_pipes\[0\]->stream_res\.encoder_info_frame/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/grouped_pipes\[1\]->encoder_info_frame/grouped_pipes\[1\]->stream_res\.encoder_info_frame/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/pipe_ctx\[i\]->encoder_info_frame/pipe_ctx\[i\]->stream_res\.encoder_info_frame/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/pipe_ctx_old->encoder_info_frame/pipe_ctx_old->stream_res\.encoder_info_frame/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/pipe_set\[j\]->encoder_info_frame/pipe_set\[j\]->stream_res\.encoder_info_frame/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/pipe_ctx\[i\]\.encoder_info_frame/pipe_ctx\[i\]\.stream_res\.encoder_info_frame/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/pipes\[i\]\.encoder_info_frame/pipes\[i\]\.stream_res\.encoder_info_frame/g' Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 4 ++-- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 4 +--- 3 files changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 5c1d3c568090..30237f049c99 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -2267,7 +2267,7 @@ struct clock_source *dc_resource_find_first_free_pll( void resource_build_info_frame(struct pipe_ctx *pipe_ctx) { enum signal_type signal = SIGNAL_TYPE_NONE; - struct encoder_info_frame *info = &pipe_ctx->encoder_info_frame; + struct encoder_info_frame *info = &pipe_ctx->stream_res.encoder_info_frame; /* default all packets to invalid */ info->avi.valid = false; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 93161a92a427..d3368a8bd1d5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -690,11 +690,11 @@ void dce110_update_info_frame(struct pipe_ctx *pipe_ctx) if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) pipe_ctx->stream_res.stream_enc->funcs->update_hdmi_info_packets( pipe_ctx->stream_res.stream_enc, - &pipe_ctx->encoder_info_frame); + &pipe_ctx->stream_res.encoder_info_frame); else if (dc_is_dp_signal(pipe_ctx->stream->signal)) pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets( pipe_ctx->stream_res.stream_enc, - &pipe_ctx->encoder_info_frame); + &pipe_ctx->stream_res.encoder_info_frame); } void dce110_enable_stream(struct pipe_ctx *pipe_ctx) diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 968835191da8..b3005629ab21 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -159,6 +159,7 @@ struct stream_resource { struct audio *audio; struct pixel_clk_params pix_clk_params; + struct encoder_info_frame encoder_info_frame; }; struct plane_resource { @@ -181,9 +182,6 @@ struct pipe_ctx { struct pll_settings pll_settings; - /*fmt*/ - struct encoder_info_frame encoder_info_frame; - uint8_t pipe_idx; struct pipe_ctx *top_pipe; -- cgit From 6dd28867b1f964226c1c0b1600ecbfa4f8f98bba Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Mon, 31 Jul 2017 15:35:01 -0400 Subject: drm/amd/display: fix PHYCLK in formula. Signed-off-by: Charlene Liu Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c | 11 +++++++++ drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 28 ++++++++++++---------- drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h | 5 ++++ 3 files changed, 32 insertions(+), 12 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c index fb5d8db33a82..e8086c09eb6f 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c @@ -266,6 +266,17 @@ void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v) v->required_output_bw = v->pixel_clock[k] * 3.0; } if (v->output[k] == dcn_bw_hdmi) { + v->required_phyclk[k] = v->required_output_bw; + switch (v->output_deep_color[k]) { + case dcn_bw_encoder_10bpc: + v->required_phyclk[k] = v->required_phyclk[k] * 5.0 / 4; + break; + case dcn_bw_encoder_12bpc: + v->required_phyclk[k] = v->required_phyclk[k] * 3.0 / 2; + break; + default: + break; + } v->required_phyclk[k] = v->required_output_bw / 3.0; } else if (v->output[k] == dcn_bw_dp) { diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 1922c13d6f22..13b7d8872f97 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -856,18 +856,6 @@ bool dcn_validate_bandwidth( - pipe->stream->timing.v_front_porch; v->vactive[input_idx] = pipe->stream->timing.v_addressable; v->pixel_clock[input_idx] = pipe->stream->timing.pix_clk_khz / 1000.0f; - if (pipe->stream->sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A) { - switch (pipe->stream->timing.display_color_depth) { - case COLOR_DEPTH_101010: - v->pixel_clock[input_idx] = (v->pixel_clock[input_idx] * 30) / 24; - break; - case COLOR_DEPTH_121212: - v->pixel_clock[input_idx] = (v->pixel_clock[input_idx] * 36) / 24; - break; - default: - break; - } - } if (!pipe->plane_state) { v->dcc_enable[input_idx] = dcn_bw_yes; @@ -938,6 +926,22 @@ bool dcn_validate_bandwidth( PIXEL_ENCODING_YCBCR420 ? dcn_bw_420 : dcn_bw_444; v->output[input_idx] = pipe->stream->sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A ? dcn_bw_hdmi : dcn_bw_dp; + v->output_deep_color[input_idx] = dcn_bw_encoder_8bpc; + if (v->output[input_idx] == dcn_bw_hdmi) { + switch (pipe->stream->timing.display_color_depth) { + case COLOR_DEPTH_101010: + v->output_deep_color[input_idx] = dcn_bw_encoder_10bpc; + break; + case COLOR_DEPTH_121212: + v->output_deep_color[input_idx] = dcn_bw_encoder_12bpc; + break; + case COLOR_DEPTH_161616: + v->output_deep_color[input_idx] = dcn_bw_encoder_16bpc; + break; + default: + break; + } + } input_idx++; } diff --git a/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h b/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h index b6cc07450f1f..7e8abcd60d12 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h @@ -89,6 +89,10 @@ enum dcn_bw_defs { dcn_bw_supported_in_v_blank, dcn_bw_not_supported, dcn_bw_na, + dcn_bw_encoder_8bpc, + dcn_bw_encoder_10bpc, + dcn_bw_encoder_12bpc, + dcn_bw_encoder_16bpc, }; /*bounding box parameters*/ @@ -182,6 +186,7 @@ struct dcn_bw_internal_vars { enum dcn_bw_defs source_pixel_format[number_of_planes_minus_one + 1]; enum dcn_bw_defs source_surface_mode[number_of_planes_minus_one + 1]; enum dcn_bw_defs output_format[number_of_planes_minus_one + 1]; + enum dcn_bw_defs output_deep_color[number_of_planes_minus_one + 1]; enum dcn_bw_defs output[number_of_planes_minus_one + 1]; float scaler_rec_out_width[number_of_planes_minus_one + 1]; float scaler_recout_height[number_of_planes_minus_one + 1]; -- cgit From 4d128c2f8a0d90f6e693c62423a678af4fc34bf5 Mon Sep 17 00:00:00 2001 From: Jerry Zuo Date: Thu, 27 Jul 2017 15:50:26 -0400 Subject: drm/amd/display: Add surface to dm_plane_state if fb reserve fails Signed-off-by: Jerry Zuo Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') 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 08567b3631cf..41731943b4e7 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4707,6 +4707,11 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, dc_plane_state = dc_create_plane_state(dc); + if (dm_plane_state->dc_state) + dc_plane_state_release(dm_plane_state->dc_state); + + dm_plane_state->dc_state = dc_plane_state; + ret = fill_plane_attributes( plane_crtc->dev->dev_private, dc_plane_state, @@ -4716,12 +4721,6 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, if (ret) goto fail; - - if (dm_plane_state->dc_state) - dc_plane_state_release(dm_plane_state->dc_state); - - dm_plane_state->dc_state = dc_plane_state; - add_val_sets_plane(set, set_count, new_acrtc_state->stream, -- cgit From 9a3329b172d26806477d07da7142925c8643ec9b Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 31 Jul 2017 13:15:04 -0400 Subject: drm/amd/display: Fix plane_atomic_check when no dc_state Signed-off-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') 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 41731943b4e7..0436261243ab 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3160,7 +3160,7 @@ int dm_plane_atomic_check(struct drm_plane *plane, struct dm_plane_state *dm_plane_state = to_dm_plane_state(state); if (!dm_plane_state->dc_state) - return true; + return 0; if (dc_validate_plane(dc, dm_plane_state->dc_state)) return 0; -- cgit From f0f8b2db570bf3cdb6948cadb83e6dad0faf4c37 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Mon, 31 Jul 2017 17:27:52 -0400 Subject: drm/amd/display: fix PHYCLK in formula. Signed-off-by: Charlene Liu Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c index e8086c09eb6f..626f9cf8aad2 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c @@ -277,7 +277,7 @@ void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v) default: break; } - v->required_phyclk[k] = v->required_output_bw / 3.0; + v->required_phyclk[k] = v->required_phyclk[k] / 3.0; } else if (v->output[k] == dcn_bw_dp) { v->required_phyclk[k] = v->required_output_bw / 4.0; -- cgit From 497de04ffe666c2f006ab318aa99cde25cc1176a Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 30 Jun 2017 11:52:14 -0400 Subject: drm/amd/display: do not report min_memory_clock_khz to pplib for dce8 & 10 Signed-off-by: Dmytro Laktyushkin Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c index 843f50a08e21..c638f47acefc 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c @@ -114,8 +114,8 @@ static void dce100_pplib_apply_display_requirements( pp_display_cfg->avail_mclk_switch_time_us = dce110_get_min_vblank_time_us(context); - pp_display_cfg->min_memory_clock_khz = context->bw.dce.yclk_khz - / MEMORY_TYPE_MULTIPLIER; + /*pp_display_cfg->min_memory_clock_khz = context->bw.dce.yclk_khz + / MEMORY_TYPE_MULTIPLIER;*/ dce110_fill_display_configs(context, pp_display_cfg); -- cgit From a7b06724eeb4ecca0c64e8f734e8ef27001670ca Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Mon, 31 Jul 2017 12:09:02 -0400 Subject: drm/amd/display: Fix comment placement for when new_stream is null Signed-off-by: Bhawanpreet Lakha Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'drivers/gpu') 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 0436261243ab..c89d6089f3c3 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4603,6 +4603,13 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, &crtc_state->mode, dm_conn_state); + /* + * we can have no stream on ACTION_SET if a display + * was disconnected during S3, in this case it not and + * error, the OS will be updated after detection, and + * do the right thing on next atomic commit + */ + if (!new_stream) { DRM_DEBUG_KMS("%s: Failed to create new stream for crtc %d\n", __func__, acrtc->base.base.id); @@ -4615,14 +4622,6 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, if (modeset_required(crtc_state, new_stream, old_acrtc_state->stream)) { - - /* - * we can have no stream on ACTION_SET if a display - * was disconnected during S3, in this case it not and - * error, the OS will be updated after detection, and - * do the right thing on next atomic commit - */ - if (new_acrtc_state->stream) dc_stream_release(new_acrtc_state->stream); -- cgit From 746e082fdd1c7650322ba4c08652245fcdf83adb Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Tue, 1 Aug 2017 13:23:56 -0400 Subject: drm/amd/display: update predefined latency for Rv1_F0 Signed-off-by: Charlene Liu Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 10 ++++++++++ drivers/gpu/drm/amd/display/include/dal_asic_id.h | 3 +++ 2 files changed, 13 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index ff2dcb7a491d..6006fb4799c3 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -1323,6 +1323,13 @@ static bool construct( dc->dcn_ip = dcn10_ip_defaults; dc->dcn_soc = dcn10_soc_defaults; + if (ASICREV_IS_RV1_F0(dc->ctx->asic_id.hw_internal_rev)) { + dc->dcn_soc.urgent_latency = 3; + dc->public.debug.disable_dmcu = true; + dc->dcn_soc.fabric_and_dram_bandwidth_vmax0p9 = 41.60f; + } + + dc->dcn_soc.number_of_channels = dc->ctx->asic_id.vram_width / ddr4_dram_width; ASSERT(dc->dcn_soc.number_of_channels < 3); if (dc->dcn_soc.number_of_channels == 0)/*old sbios bug*/ @@ -1333,6 +1340,9 @@ static bool construct( dc->dcn_soc.fabric_and_dram_bandwidth_vnom0p8 = 17.066f; dc->dcn_soc.fabric_and_dram_bandwidth_vmid0p72 = 14.933f; dc->dcn_soc.fabric_and_dram_bandwidth_vmin0p65 = 12.8f; + if (ASICREV_IS_RV1_F0(dc->ctx->asic_id.hw_internal_rev)) { + dc->dcn_soc.fabric_and_dram_bandwidth_vmax0p9 = 20.80f; + } } if (!dc->public.debug.disable_pplib_clock_request) diff --git a/drivers/gpu/drm/amd/display/include/dal_asic_id.h b/drivers/gpu/drm/amd/display/include/dal_asic_id.h index af9fa66b32b8..14e3146a0cb2 100644 --- a/drivers/gpu/drm/amd/display/include/dal_asic_id.h +++ b/drivers/gpu/drm/amd/display/include/dal_asic_id.h @@ -115,6 +115,9 @@ #define RAVEN_UNKNOWN 0xFF #define ASIC_REV_IS_RAVEN(eChipRev) ((eChipRev >= RAVEN_A0) && eChipRev < RAVEN_UNKNOWN) +#define RAVEN1_F0 0xF0 +#define ASICREV_IS_RV1_F0(eChipRev) ((eChipRev >= RAVEN1_F0) && (eChipRev < RAVEN_UNKNOWN)) + #define FAMILY_RV 142 /* DCN 1*/ -- cgit From 0d18d7bb80132467a3b88a2fe7277dc1fee65353 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Tue, 1 Aug 2017 21:13:24 -0400 Subject: drm/amd/display: fix dlg ttu calculation input Signed-off-by: Charlene Liu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 37 ++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 13b7d8872f97..67da973c898b 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -401,7 +401,8 @@ static void pipe_ctx_to_e2e_pipe_params ( static void dcn_bw_calc_rq_dlg_ttu( const struct core_dc *dc, const struct dcn_bw_internal_vars *v, - struct pipe_ctx *pipe) + struct pipe_ctx *pipe, + int in_idx) { struct display_mode_lib *dml = (struct display_mode_lib *)(&dc->dml); struct _vcs_dpi_display_dlg_regs_st *dlg_regs = &pipe->dlg_regs; @@ -439,6 +440,21 @@ static void dcn_bw_calc_rq_dlg_ttu( input.clks_cfg.socclk_mhz = v->socclk; input.clks_cfg.voltage = v->voltage_level; // dc->dml.logger = pool->base.logger; + input.dout.output_format = (v->output_format[in_idx] == dcn_bw_420) ? dm_420 : dm_444; + input.dout.output_type = (v->output[in_idx] == dcn_bw_hdmi) ? dm_hdmi : dm_dp; + //input[in_idx].dout.output_standard; + switch (v->output_deep_color[in_idx]) { + case dcn_bw_encoder_12bpc: + input.dout.output_bpc = dm_out_12; + break; + case dcn_bw_encoder_10bpc: + input.dout.output_bpc = dm_out_10; + break; + case dcn_bw_encoder_8bpc: + default: + input.dout.output_bpc = dm_out_8; + break; + } /*todo: soc->sr_enter_plus_exit_time??*/ dlg_sys_param.t_srx_delay_us = dc->dcn_ip.dcfclk_cstate_latency / v->dcf_clk_deep_sleep; @@ -487,6 +503,21 @@ static void dcn_dml_wm_override( input[in_idx].clks_cfg.refclk_mhz = pool->ref_clock_inKhz / 1000; input[in_idx].clks_cfg.socclk_mhz = v->socclk; input[in_idx].clks_cfg.voltage = v->voltage_level; + input[in_idx].dout.output_format = (v->output_format[in_idx] == dcn_bw_420) ? dm_420 : dm_444; + input[in_idx].dout.output_type = (v->output[in_idx] == dcn_bw_hdmi) ? dm_hdmi : dm_dp; + //input[in_idx].dout.output_standard; + switch (v->output_deep_color[in_idx]) { + case dcn_bw_encoder_12bpc: + input[in_idx].dout.output_bpc = dm_out_12; + break; + case dcn_bw_encoder_10bpc: + input[in_idx].dout.output_bpc = dm_out_10; + break; + case dcn_bw_encoder_8bpc: + default: + input[in_idx].dout.output_bpc = dm_out_8; + break; + } pipe_ctx_to_e2e_pipe_params(pipe, &input[in_idx].pipe); dml_rq_dlg_get_rq_reg( dml, @@ -1060,7 +1091,7 @@ bool dcn_validate_bandwidth( pipe, hsplit_pipe); } - dcn_bw_calc_rq_dlg_ttu(dc, v, hsplit_pipe); + dcn_bw_calc_rq_dlg_ttu(dc, v, hsplit_pipe, input_idx); } else if (hsplit_pipe && hsplit_pipe->plane_state == pipe->plane_state) { /* merge previously split pipe */ pipe->bottom_pipe = hsplit_pipe->bottom_pipe; @@ -1073,7 +1104,7 @@ bool dcn_validate_bandwidth( resource_build_scaling_params(pipe); } /* for now important to do this after pipe split for building e2e params */ - dcn_bw_calc_rq_dlg_ttu(dc, v, pipe); + dcn_bw_calc_rq_dlg_ttu(dc, v, pipe, input_idx); } input_idx++; -- cgit From 9ee20ee6117b84fb6240f0ba5c4deafc23d9a458 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Tue, 1 Aug 2017 16:54:48 -0400 Subject: drm/amd/display: Implement tmz surface. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 1 + drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c | 10 ++++++++++ drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h | 2 ++ 3 files changed, 13 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index 3c0b47373dfb..778bd5555c7a 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -66,6 +66,7 @@ enum dc_plane_addr_type { struct dc_plane_address { enum dc_plane_addr_type type; + bool tmz_surface; union { struct{ PHYSICAL_ADDRESS_LOC addr; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index 76879f5d7907..0d40fa753036 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -266,6 +266,9 @@ static bool min10_program_surface_flip_and_addr( if (address->grph.addr.quad_part == 0) break; + REG_UPDATE(DCSURF_SURFACE_CONTROL, + PRIMARY_SURFACE_TMZ, address->tmz_surface); + if (address->grph.meta_addr.quad_part != 0) { REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, 0, PRIMARY_META_SURFACE_ADDRESS_HIGH, @@ -289,6 +292,9 @@ static bool min10_program_surface_flip_and_addr( || address->video_progressive.chroma_addr.quad_part == 0) break; + REG_UPDATE(DCSURF_SURFACE_CONTROL, + PRIMARY_SURFACE_TMZ, address->tmz_surface); + if (address->video_progressive.luma_meta_addr.quad_part != 0) { REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C, 0, PRIMARY_META_SURFACE_ADDRESS_HIGH_C, @@ -328,6 +334,10 @@ static bool min10_program_surface_flip_and_addr( break; if (address->grph_stereo.right_addr.quad_part == 0) break; + + REG_UPDATE(DCSURF_SURFACE_CONTROL, + PRIMARY_SURFACE_TMZ, address->tmz_surface); + if (address->grph_stereo.right_meta_addr.quad_part != 0) { REG_SET(DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH, 0, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h index 4f4e2c0708d5..e2eba25f44ec 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h @@ -303,6 +303,7 @@ struct dcn_mi_registers { MI_SF(HUBPREQ0_DCSURF_SURFACE_EARLIEST_INUSE_HIGH, SURFACE_EARLIEST_INUSE_ADDRESS_HIGH, mask_sh),\ MI_SF(HUBPREQ0_DCSURF_SURFACE_EARLIEST_INUSE_C, SURFACE_EARLIEST_INUSE_ADDRESS_C, mask_sh),\ MI_SF(HUBPREQ0_DCSURF_SURFACE_EARLIEST_INUSE_HIGH_C, SURFACE_EARLIEST_INUSE_ADDRESS_HIGH_C, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, PRIMARY_SURFACE_TMZ, mask_sh),\ MI_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, PRIMARY_SURFACE_DCC_EN, mask_sh),\ MI_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, PRIMARY_SURFACE_DCC_IND_64B_BLK, mask_sh),\ MI_SF(HUBPRET0_HUBPRET_CONTROL, DET_BUF_PLANE1_BASE_ADDRESS, mask_sh),\ @@ -453,6 +454,7 @@ struct dcn_mi_registers { type SURFACE_EARLIEST_INUSE_ADDRESS_HIGH;\ type SURFACE_EARLIEST_INUSE_ADDRESS_C;\ type SURFACE_EARLIEST_INUSE_ADDRESS_HIGH_C;\ + type PRIMARY_SURFACE_TMZ;\ type PRIMARY_SURFACE_DCC_EN;\ type PRIMARY_SURFACE_DCC_IND_64B_BLK;\ type DET_BUF_PLANE1_BASE_ADDRESS;\ -- cgit From 2a8f6ccb665c6ac53afdcf76b2aaa7fc5e513bfc Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 31 Jul 2017 16:32:18 -0400 Subject: drm/amd/display: Clean up cursor code This will also fix disappearing cursor after resume. With this change we'll set cursor attributes, as well as cursor position on every update. The impact is minor. These are sample logs that show timestamps at beginning and end of atomic_check, commit_tail, handle_cursor_update, and before and after cursor_attribute and cursor_position calls: [ 66.800353] hwhw: begin of check [ 66.800377] hwhw: end of check [ 66.800428] hwhw: begin of commit_tail [ 66.800441] hwhw: begin of cursor [ 66.800449] hwhw: begin of cursor_attr [ 66.800468] hwhw: end of cursor_attr [ 66.800484] hwhw: end of cursor_positionr [ 66.800501] hwhw: end of commit_tail [ 66.807139] hwhw: begin of check [ 66.807160] hwhw: end of check [ 66.807206] hwhw: begin of commit_tail [ 66.807217] hwhw: begin of cursor [ 66.807225] hwhw: begin of cursor_attr [ 66.807357] hwhw: end of cursor_attr [ 66.807374] hwhw: end of cursor_positionr [ 66.807392] hwhw: end of commit_tail Signed-off-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 283 +++++++--------------- 1 file changed, 92 insertions(+), 191 deletions(-) (limited to 'drivers/gpu') 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 c89d6089f3c3..4535942e8a63 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1647,178 +1647,6 @@ static const struct drm_encoder_funcs amdgpu_dm_encoder_funcs = { .destroy = amdgpu_dm_encoder_destroy, }; -static void dm_set_cursor( - struct amdgpu_crtc *amdgpu_crtc, - uint64_t gpu_addr, - uint32_t width, - uint32_t height) -{ - struct dc_cursor_attributes attributes; - struct dc_cursor_position position; - struct drm_crtc *crtc = &amdgpu_crtc->base; - int x, y; - int xorigin = 0, yorigin = 0; - struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state); - - amdgpu_crtc->cursor_width = width; - amdgpu_crtc->cursor_height = height; - - attributes.address.high_part = upper_32_bits(gpu_addr); - attributes.address.low_part = lower_32_bits(gpu_addr); - attributes.width = width; - attributes.height = height; - attributes.color_format = CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA; - attributes.rotation_angle = 0; - attributes.attribute_flags.value = 0; - - attributes.pitch = attributes.width; - - x = amdgpu_crtc->cursor_x; - y = amdgpu_crtc->cursor_y; - - /* avivo cursor are offset into the total surface */ - x += crtc->primary->state->src_x >> 16; - y += crtc->primary->state->src_y >> 16; - - if (x < 0) { - xorigin = min(-x, amdgpu_crtc->max_cursor_width - 1); - x = 0; - } - if (y < 0) { - yorigin = min(-y, amdgpu_crtc->max_cursor_height - 1); - y = 0; - } - - position.enable = true; - position.x = x; - position.y = y; - - position.x_hotspot = xorigin; - position.y_hotspot = yorigin; - - if (!dc_stream_set_cursor_attributes( - acrtc_state->stream, - &attributes)) { - DRM_ERROR("DC failed to set cursor attributes\n"); - } - - if (!dc_stream_set_cursor_position( - acrtc_state->stream, - &position)) { - DRM_ERROR("DC failed to set cursor position\n"); - } -} - -static int dm_crtc_cursor_set( - struct drm_crtc *crtc, - uint64_t address, - uint32_t width, - uint32_t height) -{ - struct dc_cursor_position position; - struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state); - - int ret; - - struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); - ret = EINVAL; - - DRM_DEBUG_KMS("%s: crtc_id=%d with size %d to %d \n", - __func__, - amdgpu_crtc->crtc_id, - width, - height); - - if (!address) { - /* turn off cursor */ - position.enable = false; - position.x = 0; - position.y = 0; - - if (acrtc_state->stream) { - /*set cursor visible false*/ - dc_stream_set_cursor_position( - acrtc_state->stream, - &position); - } - goto release; - - } - - if ((width > amdgpu_crtc->max_cursor_width) || - (height > amdgpu_crtc->max_cursor_height)) { - DRM_ERROR( - "%s: bad cursor width or height %d x %d\n", - __func__, - width, - height); - goto release; - } - - /*program new cursor bo to hardware*/ - dm_set_cursor(amdgpu_crtc, address, width, height); - -release: - return ret; - -} - -static int dm_crtc_cursor_move(struct drm_crtc *crtc, - int x, int y) -{ - struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); - int xorigin = 0, yorigin = 0; - struct dc_cursor_position position; - struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state); - - amdgpu_crtc->cursor_x = x; - amdgpu_crtc->cursor_y = y; - - /* avivo cursor are offset into the total surface */ - x += crtc->primary->state->src_x >> 16; - y += crtc->primary->state->src_y >> 16; - - /* - * TODO: for cursor debugging unguard the following - */ -#if 0 - DRM_DEBUG_KMS( - "%s: x %d y %d c->x %d c->y %d\n", - __func__, - x, - y, - crtc->x, - crtc->y); -#endif - - if (x < 0) { - xorigin = min(-x, amdgpu_crtc->max_cursor_width - 1); - x = 0; - } - if (y < 0) { - yorigin = min(-y, amdgpu_crtc->max_cursor_height - 1); - y = 0; - } - - position.enable = true; - position.x = x; - position.y = y; - - position.x_hotspot = xorigin; - position.y_hotspot = yorigin; - - if (acrtc_state->stream) { - if (!dc_stream_set_cursor_position( - acrtc_state->stream, - &position)) { - DRM_ERROR("DC failed to set cursor position\n"); - return -EINVAL; - } - } - - return 0; -} - static bool fill_rects_from_plane_state( const struct drm_plane_state *state, struct dc_plane_state *plane_state) @@ -3782,34 +3610,107 @@ static void remove_stream( acrtc->enabled = false; } +int get_cursor_position(struct drm_plane *plane, struct drm_crtc *crtc, + struct dc_cursor_position *position) +{ + struct amdgpu_crtc *amdgpu_crtc = amdgpu_crtc = to_amdgpu_crtc(crtc); + int x, y; + int xorigin = 0, yorigin = 0; + + if (!crtc || !plane->state->fb) { + position->enable = false; + position->x = 0; + position->y = 0; + return 0; + } + + if ((plane->state->crtc_w > amdgpu_crtc->max_cursor_width) || + (plane->state->crtc_h > amdgpu_crtc->max_cursor_height)) { + DRM_ERROR("%s: bad cursor width or height %d x %d\n", + __func__, + plane->state->crtc_w, + plane->state->crtc_h); + return -EINVAL; + } + + x = plane->state->crtc_x; + y = plane->state->crtc_y; + /* avivo cursor are offset into the total surface */ + x += crtc->primary->state->src_x >> 16; + y += crtc->primary->state->src_y >> 16; + if (x < 0) { + xorigin = min(-x, amdgpu_crtc->max_cursor_width - 1); + x = 0; + } + if (y < 0) { + yorigin = min(-y, amdgpu_crtc->max_cursor_height - 1); + y = 0; + } + position->enable = true; + position->x = x; + position->y = y; + position->x_hotspot = xorigin; + position->y_hotspot = yorigin; + + return 0; +} + static void handle_cursor_update( struct drm_plane *plane, struct drm_plane_state *old_plane_state) { + struct amdgpu_framebuffer *afb = to_amdgpu_framebuffer(plane->state->fb); + struct drm_crtc *crtc = afb ? plane->state->crtc : old_plane_state->crtc; + struct dm_crtc_state *crtc_state = crtc ? to_dm_crtc_state(crtc->state) : NULL; + struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); + uint64_t address = afb ? afb->address : 0; + struct dc_cursor_position position; + struct dc_cursor_attributes attributes; + int ret; + if (!plane->state->fb && !old_plane_state->fb) return; - /* Check if it's a cursor on/off update or just cursor move*/ - if (plane->state->fb == old_plane_state->fb) - dm_crtc_cursor_move( - plane->state->crtc, - plane->state->crtc_x, - plane->state->crtc_y); - else { - struct amdgpu_framebuffer *afb = - to_amdgpu_framebuffer(plane->state->fb); - dm_crtc_cursor_set( - (!!plane->state->fb) ? - plane->state->crtc : - old_plane_state->crtc, - (!!plane->state->fb) ? - afb->address : - 0, - plane->state->crtc_w, - plane->state->crtc_h); + DRM_DEBUG_KMS("%s: crtc_id=%d with size %d to %d\n", + __func__, + amdgpu_crtc->crtc_id, + plane->state->crtc_w, + plane->state->crtc_h); + + ret = get_cursor_position(plane, crtc, &position); + if (ret) + return; + + if (!position.enable) { + /* turn off cursor */ + if (crtc_state && crtc_state->stream) + dc_stream_set_cursor_position(crtc_state->stream, + &position); + return; } -} + amdgpu_crtc->cursor_width = plane->state->crtc_w; + amdgpu_crtc->cursor_height = plane->state->crtc_h; + + attributes.address.high_part = upper_32_bits(address); + attributes.address.low_part = lower_32_bits(address); + attributes.width = plane->state->crtc_w; + attributes.height = plane->state->crtc_h; + attributes.color_format = CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA; + attributes.rotation_angle = 0; + attributes.attribute_flags.value = 0; + + attributes.pitch = attributes.width; + + if (!dc_stream_set_cursor_attributes(crtc_state->stream, + &attributes)) + DRM_ERROR("DC failed to set cursor attributes\n"); + + if (crtc_state->stream) + if (!dc_stream_set_cursor_position(crtc_state->stream, + &position)) + DRM_ERROR("DC failed to set cursor position\n"); +} static void prepare_flip_isr(struct amdgpu_crtc *acrtc) { -- cgit From c10efbd3714bfb6fff8c3b8e2d817028bc25355b Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Thu, 3 Aug 2017 13:04:44 -0400 Subject: drm/amd/display: fix eDP power down sequence Signed-off-by: Charlene Liu Reviewed-by: Anthony Koo Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 822568767f2d..d19c663c257f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -90,10 +90,13 @@ void dp_enable_link_phy( if (dc_is_dp_sst_signal(signal)) { if (signal == SIGNAL_TYPE_EDP) { link_enc->funcs->power_control(link_enc, true); + link_enc->funcs->enable_dp_output( + link_enc, + link_settings, + clock_source); link_enc->funcs->backlight_control(link_enc, true); - } - - link_enc->funcs->enable_dp_output( + } else + link_enc->funcs->enable_dp_output( link_enc, link_settings, clock_source); @@ -114,10 +117,10 @@ void dp_disable_link_phy(struct dc_link *link, enum signal_type signal) if (signal == SIGNAL_TYPE_EDP) { link->link_enc->funcs->backlight_control(link->link_enc, false); + link->link_enc->funcs->disable_output(link->link_enc, signal); link->link_enc->funcs->power_control(link->link_enc, false); - } - - link->link_enc->funcs->disable_output(link->link_enc, signal); + } else + link->link_enc->funcs->disable_output(link->link_enc, signal); /* Clear current link setting.*/ memset(&link->cur_link_settings, 0, -- cgit From 713950115bc5f964e65f79a7684468c41ed41654 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Thu, 3 Aug 2017 08:59:12 -0400 Subject: drm/amd/display: log HW state when we about to encounter DF DPM hang Signed-off-by: Tony Cheng Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 115 +++++++++++---------- 1 file changed, 58 insertions(+), 57 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index e69839802889..30ddf920b270 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -52,6 +52,61 @@ #define FN(reg_name, field_name) \ hws->shifts->field_name, hws->masks->field_name +static void log_mpc_crc(struct core_dc *dc) +{ + struct dc_context *dc_ctx = dc->ctx; + struct dce_hwseq *hws = dc->hwseq; + + if (REG(MPC_CRC_RESULT_GB)) + DTN_INFO("MPC_CRC_RESULT_GB:%d MPC_CRC_RESULT_C:%d MPC_CRC_RESULT_AR:%d\n", + REG_READ(MPC_CRC_RESULT_GB), REG_READ(MPC_CRC_RESULT_C), REG_READ(MPC_CRC_RESULT_AR)); + if (REG(DPP_TOP0_DPP_CRC_VAL_B_A)) + DTN_INFO("DPP_TOP0_DPP_CRC_VAL_B_A:%d DPP_TOP0_DPP_CRC_VAL_R_G:%d\n", + REG_READ(DPP_TOP0_DPP_CRC_VAL_B_A), REG_READ(DPP_TOP0_DPP_CRC_VAL_R_G)); +} + +static void dcn10_log_hw_state(struct core_dc *dc) +{ + struct dc_context *dc_ctx = dc->ctx; + struct resource_pool *pool = dc->res_pool; + int i; + + DTN_INFO_BEGIN(); + + DTN_INFO("HUBP:\t format \t addr_hi \t width \t height \t rotation \t" + "mirror \t sw_mode \t dcc_en \t blank_en \t ttu_dis \t" + "min_ttu_vblank \t qos_low_wm \t qos_high_wm \n"); + + for (i = 0; i < pool->pipe_count; i++) { + struct mem_input *mi = pool->mis[i]; + struct dcn_hubp_state s; + + dcn10_mem_input_read_state(TO_DCN10_MEM_INPUT(mi), &s); + + DTN_INFO("[%d]:\t %xh \t %xh \t %d \t %d \t %xh \t %xh \t " + "%d \t %d \t %d \t %d \t" + "%d \t %d \t %d \n", + i, + s.pixel_format, + s.inuse_addr_hi, + s.viewport_width, + s.viewport_height, + s.rotation_angle, + s.h_mirror_en, + s.sw_mode, + s.dcc_en, + s.blank_en, + s.ttu_disable, + s.min_ttu_vblank, + s.qos_level_low_wm, + s.qos_level_high_wm); + } + DTN_INFO("\n"); + + log_mpc_crc(dc); + + DTN_INFO_END(); +} static void verify_allow_pstate_change_high( struct dce_hwseq *hws) @@ -118,6 +173,9 @@ static void verify_allow_pstate_change_high( */ REG_WRITE(DCHUBBUB_ARB_DRAM_STATE_CNTL, force_allow_pstate); forced_pstate_allow = true; + + dcn10_log_hw_state(DC_TO_CORE(hws->ctx->dc)); + BREAK_TO_DEBUGGER(); } @@ -2377,63 +2435,6 @@ static void dcn10_setup_stereo(struct pipe_ctx *pipe_ctx, struct core_dc *dc) return; } - -static void log_mpc_crc(struct core_dc *dc) -{ - struct dc_context *dc_ctx = dc->ctx; - struct dce_hwseq *hws = dc->hwseq; - - if (REG(MPC_CRC_RESULT_GB)) - DTN_INFO("MPC_CRC_RESULT_GB:%d MPC_CRC_RESULT_C:%d MPC_CRC_RESULT_AR:%d\n", - REG_READ(MPC_CRC_RESULT_GB), REG_READ(MPC_CRC_RESULT_C), REG_READ(MPC_CRC_RESULT_AR)); - if (REG(DPP_TOP0_DPP_CRC_VAL_B_A)) - DTN_INFO("DPP_TOP0_DPP_CRC_VAL_B_A:%d DPP_TOP0_DPP_CRC_VAL_R_G:%d\n", - REG_READ(DPP_TOP0_DPP_CRC_VAL_B_A), REG_READ(DPP_TOP0_DPP_CRC_VAL_R_G)); -} - -static void dcn10_log_hw_state(struct core_dc *dc) -{ - struct dc_context *dc_ctx = dc->ctx; - struct resource_pool *pool = dc->res_pool; - int i; - - DTN_INFO_BEGIN(); - - DTN_INFO("HUBP:\t format \t addr_hi \t width \t height \t rotation \t" - "mirror \t sw_mode \t dcc_en \t blank_en \t ttu_dis \t" - "min_ttu_vblank \t qos_low_wm \t qos_high_wm \n"); - - for (i = 0; i < pool->pipe_count; i++) { - struct mem_input *mi = pool->mis[i]; - struct dcn_hubp_state s; - - dcn10_mem_input_read_state(TO_DCN10_MEM_INPUT(mi), &s); - - DTN_INFO("[%d]:\t %xh \t %xh \t %d \t %d \t %xh \t %xh \t " - "%d \t %d \t %d \t %d \t" - "%d \t %d \t %d \n", - i, - s.pixel_format, - s.inuse_addr_hi, - s.viewport_width, - s.viewport_height, - s.rotation_angle, - s.h_mirror_en, - s.sw_mode, - s.dcc_en, - s.blank_en, - s.ttu_disable, - s.min_ttu_vblank, - s.qos_level_low_wm, - s.qos_level_high_wm); - } - DTN_INFO("\n"); - - log_mpc_crc(dc); - - DTN_INFO_END(); -} - static void dcn10_wait_for_mpcc_disconnect( struct core_dc *dc, struct resource_pool *res_pool, -- cgit From eb4e33b7c98a4d69d84d783fd0a7918e5ad011da Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Thu, 3 Aug 2017 09:22:14 -0400 Subject: drm/amd/display: log underflow as well as convert output in ref_cycle to nano sec Signed-off-by: Tony Cheng Reviewed-by: Logatharshan Thothiralingam Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 33 ++++++++++++++++------ .../gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c | 5 ++-- .../gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h | 3 ++ 3 files changed, 31 insertions(+), 10 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 30ddf920b270..a4c0c338285d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -65,6 +65,20 @@ static void log_mpc_crc(struct core_dc *dc) REG_READ(DPP_TOP0_DPP_CRC_VAL_B_A), REG_READ(DPP_TOP0_DPP_CRC_VAL_R_G)); } +void print_microsec(struct dc_context *dc_ctx, uint32_t ref_cycle) +{ + static const uint32_t ref_clk_mhz = 48; + static const unsigned int frac = 10; + uint32_t us_x10 = (ref_cycle * frac) / ref_clk_mhz; + + DTN_INFO("%d.%d \t ", + us_x10 / frac, + us_x10 % frac); +} + +#define DTN_INFO_MICRO_SEC(ref_cycle) \ + print_microsec(dc_ctx, ref_cycle) + static void dcn10_log_hw_state(struct core_dc *dc) { struct dc_context *dc_ctx = dc->ctx; @@ -73,8 +87,9 @@ static void dcn10_log_hw_state(struct core_dc *dc) DTN_INFO_BEGIN(); - DTN_INFO("HUBP:\t format \t addr_hi \t width \t height \t rotation \t" - "mirror \t sw_mode \t dcc_en \t blank_en \t ttu_dis \t" + DTN_INFO("HUBP:\t format \t addr_hi \t width \t height \t " + "rotation \t mirror \t sw_mode \t " + "dcc_en \t blank_en \t ttu_dis \t underflow \t " "min_ttu_vblank \t qos_low_wm \t qos_high_wm \n"); for (i = 0; i < pool->pipe_count; i++) { @@ -83,9 +98,9 @@ static void dcn10_log_hw_state(struct core_dc *dc) dcn10_mem_input_read_state(TO_DCN10_MEM_INPUT(mi), &s); - DTN_INFO("[%d]:\t %xh \t %xh \t %d \t %d \t %xh \t %xh \t " - "%d \t %d \t %d \t %d \t" - "%d \t %d \t %d \n", + DTN_INFO("[%d]:\t %xh \t %xh \t %d \t %d \t " + "%xh \t %xh \t %xh \t " + "%d \t %d \t %d \t %xh \t", i, s.pixel_format, s.inuse_addr_hi, @@ -97,9 +112,11 @@ static void dcn10_log_hw_state(struct core_dc *dc) s.dcc_en, s.blank_en, s.ttu_disable, - s.min_ttu_vblank, - s.qos_level_low_wm, - s.qos_level_high_wm); + s.underflow_status); + DTN_INFO_MICRO_SEC(s.min_ttu_vblank); + DTN_INFO_MICRO_SEC(s.qos_level_low_wm); + DTN_INFO_MICRO_SEC(s.qos_level_high_wm); + DTN_INFO("\n"); } DTN_INFO("\n"); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index 0d40fa753036..f36585de15df 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -841,9 +841,10 @@ void dcn10_mem_input_read_state(struct dcn10_mem_input *mi, REG_GET(DCSURF_SURFACE_CONTROL, PRIMARY_SURFACE_DCC_EN, &s->dcc_en); - REG_GET_2(DCHUBP_CNTL, + REG_GET_3(DCHUBP_CNTL, HUBP_BLANK_EN, &s->blank_en, - HUBP_TTU_DISABLE, &s->ttu_disable); + HUBP_TTU_DISABLE, &s->ttu_disable, + HUBP_UNDERFLOW_STATUS, &s->underflow_status); REG_GET(DCN_GLOBAL_TTU_CNTL, MIN_TTU_VBLANK, &s->min_ttu_vblank); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h index e2eba25f44ec..b3ec16c17826 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h @@ -250,6 +250,7 @@ struct dcn_mi_registers { #define MI_MASK_SH_LIST_DCN(mask_sh)\ MI_SF(HUBP0_DCHUBP_CNTL, HUBP_BLANK_EN, mask_sh),\ MI_SF(HUBP0_DCHUBP_CNTL, HUBP_TTU_DISABLE, mask_sh),\ + MI_SF(HUBP0_DCHUBP_CNTL, HUBP_UNDERFLOW_STATUS, mask_sh),\ MI_SF(HUBP0_DCHUBP_CNTL, HUBP_NO_OUTSTANDING_REQ, mask_sh),\ MI_SF(HUBP0_DCSURF_ADDR_CONFIG, NUM_PIPES, mask_sh),\ MI_SF(HUBP0_DCSURF_ADDR_CONFIG, NUM_BANKS, mask_sh),\ @@ -402,6 +403,7 @@ struct dcn_mi_registers { type HUBP_BLANK_EN;\ type HUBP_TTU_DISABLE;\ type HUBP_NO_OUTSTANDING_REQ;\ + type HUBP_UNDERFLOW_STATUS;\ type NUM_PIPES;\ type NUM_BANKS;\ type PIPE_INTERLEAVE;\ @@ -591,6 +593,7 @@ struct dcn_hubp_state { uint32_t sw_mode; uint32_t dcc_en; uint32_t blank_en; + uint32_t underflow_status; uint32_t ttu_disable; uint32_t min_ttu_vblank; uint32_t qos_level_low_wm; -- cgit From 665da60f23d8c6bda5431529a73be49b3b9d97cb Mon Sep 17 00:00:00 2001 From: Corbin McElhanney Date: Thu, 3 Aug 2017 14:20:14 -0400 Subject: drm/amd/display: Add more pstate sanity checks Signed-off-by: Corbin McElhanney Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 24 ++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index a4c0c338285d..114dd279fe47 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1767,6 +1767,10 @@ static void dcn10_power_on_fe( struct dc_plane_state *plane_state = pipe_ctx->plane_state; struct dce_hwseq *hws = dc->hwseq; + if (dc->public.debug.sanity_checks) { + verify_allow_pstate_change_high(dc->hwseq); + } + power_on_plane(dc->hwseq, pipe_ctx->pipe_idx); @@ -1813,6 +1817,10 @@ static void dcn10_power_on_fe( pipe_ctx->plane_res.scl_data.recout.y); print_rq_dlg_ttu(dc, pipe_ctx); } + + if (dc->public.debug.sanity_checks) { + verify_allow_pstate_change_high(dc->hwseq); + } } static void program_gamut_remap(struct pipe_ctx *pipe_ctx) @@ -2287,6 +2295,10 @@ static void dcn10_set_bandwidth( { struct dm_pp_clock_for_voltage_req clock; + if (dc->public.debug.sanity_checks) { + verify_allow_pstate_change_high(dc->hwseq); + } + if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) return; @@ -2338,6 +2350,10 @@ static void dcn10_set_bandwidth( } dcn10_pplib_apply_display_requirements(dc, context); + if (dc->public.debug.sanity_checks) { + verify_allow_pstate_change_high(dc->hwseq); + } + /* need to fix this function. not doing the right thing here */ } @@ -2459,6 +2475,10 @@ static void dcn10_wait_for_mpcc_disconnect( { int i; + if (dc->public.debug.sanity_checks) { + verify_allow_pstate_change_high(dc->hwseq); + } + if (!pipe_ctx->stream_res.opp) return; @@ -2473,6 +2493,10 @@ static void dcn10_wait_for_mpcc_disconnect( } } + if (dc->public.debug.sanity_checks) { + verify_allow_pstate_change_high(dc->hwseq); + } + } static bool dcn10_dummy_display_power_gating( -- cgit From d66cf5f5013a4268057bcb92d301d010268ea27f Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Thu, 3 Aug 2017 09:59:23 -0400 Subject: drm/amd/display: implement DXGI Gamma Ramps Support for gamma correction ramp in Floating Point format Signed-off-by: Anthony Koo Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 14 +++++++------- drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 21 ++++++++++++++++----- drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c | 14 ++++++++++---- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c | 11 +++++++---- 4 files changed, 40 insertions(+), 20 deletions(-) (limited to 'drivers/gpu') 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 4535942e8a63..b0fcfebc04b8 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1874,15 +1874,14 @@ static int fill_plane_attributes_from_fb( } -#define NUM_OF_RAW_GAMMA_RAMP_RGB_256 256 - static void fill_gamma_from_crtc_state( const struct drm_crtc_state *crtc_state, struct dc_plane_state *plane_state) { int i; struct dc_gamma *gamma; - struct drm_color_lut *lut = (struct drm_color_lut *) crtc_state->gamma_lut->data; + struct drm_color_lut *lut = + (struct drm_color_lut *) crtc_state->gamma_lut->data; gamma = dc_create_gamma(); @@ -1891,10 +1890,11 @@ static void fill_gamma_from_crtc_state( return; } - for (i = 0; i < NUM_OF_RAW_GAMMA_RAMP_RGB_256; i++) { - gamma->red[i] = lut[i].red; - gamma->green[i] = lut[i].green; - gamma->blue[i] = lut[i].blue; + gamma->type = GAMMA_RGB_256_ENTRIES; + for (i = 0; i < GAMMA_RGB_256_ENTRIES; i++) { + gamma->entries.red[i] = dal_fixed31_32_from_int(lut[i].red); + gamma->entries.green[i] = dal_fixed31_32_from_int(lut[i].green); + gamma->entries.blue[i] = dal_fixed31_32_from_int(lut[i].blue); } plane_state->gamma_correction = gamma; diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index 778bd5555c7a..8d1504668ec7 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -409,20 +409,31 @@ struct dc_cursor_mi_param { /* IPP related types */ enum { - INPUT_LUT_ENTRIES = 256 + GAMMA_RGB_256_ENTRIES = 256, + GAMMA_RGB_FLOAT_1024_ENTRIES = 1024, + GAMMA_MAX_ENTRIES = 1024 +}; + +enum dc_gamma_type { + GAMMA_RGB_256 = 1, + GAMMA_RGB_FLOAT_1024 = 2 }; struct dc_gamma { - uint16_t red[INPUT_LUT_ENTRIES]; - uint16_t green[INPUT_LUT_ENTRIES]; - uint16_t blue[INPUT_LUT_ENTRIES]; + enum dc_gamma_type type; + unsigned int num_entries; + + struct dc_gamma_entries { + struct fixed31_32 red[GAMMA_MAX_ENTRIES]; + struct fixed31_32 green[GAMMA_MAX_ENTRIES]; + struct fixed31_32 blue[GAMMA_MAX_ENTRIES]; + } entries; /* private to DC core */ struct dc_context *ctx; /* private to dc_surface.c */ int ref_count; - }; /* Used by both ipp amd opp functions*/ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c index 9e8f0a3593a2..e010cf10d605 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c @@ -193,10 +193,16 @@ static void dce_ipp_program_input_lut( REG_SET(DC_LUT_RW_INDEX, 0, DC_LUT_RW_INDEX, 0); - for (i = 0; i < INPUT_LUT_ENTRIES; i++) { - REG_SET(DC_LUT_SEQ_COLOR, 0, DC_LUT_SEQ_COLOR, gamma->red[i]); - REG_SET(DC_LUT_SEQ_COLOR, 0, DC_LUT_SEQ_COLOR, gamma->green[i]); - REG_SET(DC_LUT_SEQ_COLOR, 0, DC_LUT_SEQ_COLOR, gamma->blue[i]); + for (i = 0; i < gamma->num_entries; i++) { + REG_SET(DC_LUT_SEQ_COLOR, 0, DC_LUT_SEQ_COLOR, + dal_fixed31_32_round( + gamma->entries.red[i])); + REG_SET(DC_LUT_SEQ_COLOR, 0, DC_LUT_SEQ_COLOR, + dal_fixed31_32_round( + gamma->entries.green[i])); + REG_SET(DC_LUT_SEQ_COLOR, 0, DC_LUT_SEQ_COLOR, + dal_fixed31_32_round( + gamma->entries.blue[i])); } /* power off LUT memory */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c index ee12f671d8ea..8ee830522148 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c @@ -910,13 +910,16 @@ static void ippn10_program_input_lut( CM_IGAM_LUT_FORMAT_B, 3); // Start at index 0 of IGAM LUT REG_UPDATE(CM_IGAM_LUT_RW_INDEX, CM_IGAM_LUT_RW_INDEX, 0); - for (i = 0; i < INPUT_LUT_ENTRIES; i++) { + for (i = 0; i < gamma->num_entries; i++) { REG_SET(CM_IGAM_LUT_SEQ_COLOR, 0, CM_IGAM_LUT_SEQ_COLOR, - gamma->red[i]); + dal_fixed31_32_round( + gamma->entries.red[i])); REG_SET(CM_IGAM_LUT_SEQ_COLOR, 0, CM_IGAM_LUT_SEQ_COLOR, - gamma->green[i]); + dal_fixed31_32_round( + gamma->entries.green[i])); REG_SET(CM_IGAM_LUT_SEQ_COLOR, 0, CM_IGAM_LUT_SEQ_COLOR, - gamma->blue[i]); + dal_fixed31_32_round( + gamma->entries.blue[i])); } // Power off LUT memory REG_SET(CM_MEM_PWR_CTRL, 0, SHARED_MEM_PWR_DIS, 0); -- cgit From f334073ae31eaee742811e6ca282622aad5844ad Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Thu, 3 Aug 2017 13:57:05 -0400 Subject: drm/amd/display: Move verify link cap after read edid DP link layer test 400.1.1 fails intermittently. The test device will pull hpd low immediately after verify link cap. Driver reads edid when hpd low that causes the test to fail. Move read edid before verify link cap, so driver will read edid before starting link training Signed-off-by: Wenjing Liu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 16 ++++++++++++++++ drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 7 ------- 2 files changed, 16 insertions(+), 7 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 1279eb1dfc2e..72eb6af62f45 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -666,6 +666,22 @@ bool dc_link_detect(struct dc_link *link, bool boot) break; } + if (link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT && + sink_caps.transaction_type == + DDC_TRANSACTION_TYPE_I2C_OVER_AUX) { + /* + * TODO debug why Dell 2413 doesn't like + * two link trainings + */ + if (is_mst_supported(link)) { + link->verified_link_cap = + link->reported_link_cap; + } else { + dp_hbr_verify_link_cap(link, + &link->reported_link_cap); + } + } + /* HDMI-DVI Dongle */ if (sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A && !sink->edid_caps.edid_hdmi) 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 3d296b1d118f..9d5fe658d14c 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 @@ -2283,13 +2283,6 @@ void detect_dp_sink_caps(struct dc_link *link) * DP, hw_init may need check signal or power up * encoder here. */ - - if (is_mst_supported(link)) { - link->verified_link_cap = link->reported_link_cap; - } else { - dp_hbr_verify_link_cap(link, - &link->reported_link_cap); - } /* TODO save sink caps in link->sink */ } -- cgit From 3e9ad6164b98f82ff4b191980c502f09fee4deef Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Thu, 3 Aug 2017 00:22:25 -0400 Subject: drm/amd/display: add programming for 0 plane case Signed-off-by: Eric Yang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 45 +++++++++++++--------- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 17 ++++++-- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 29 ++++++++++---- drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 3 +- 4 files changed, 64 insertions(+), 30 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 748e709c611f..f305780c36ce 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -978,10 +978,10 @@ static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *c const struct dc_sink *sink = context->streams[i]->sink; for (j = 0; j < context->stream_status[i].plane_count; j++) { - const struct dc_plane_state *plane_state = - context->stream_status[i].plane_states[j]; - - core_dc->hwss.apply_ctx_for_surface(core_dc, plane_state, context); + core_dc->hwss.apply_ctx_for_surface( + core_dc, context->streams[i], + context->stream_status[i].plane_count, + context); /* * enable stereo @@ -1391,6 +1391,21 @@ enum surface_update_type dc_check_update_surfaces_for_stream( return overall_type; } +static struct dc_stream_status *stream_get_status( + struct validate_context *ctx, + struct dc_stream_state *stream) +{ + uint8_t i; + + for (i = 0; i < ctx->stream_count; i++) { + if (stream == ctx->streams[i]) { + return &ctx->stream_status[i]; + } + } + + return NULL; +} + enum surface_update_type update_surface_trace_level = UPDATE_TYPE_FULL; void dc_update_planes_and_stream(struct dc *dc, @@ -1405,16 +1420,6 @@ void dc_update_planes_and_stream(struct dc *dc, const struct dc_stream_status *stream_status; struct dc_context *dc_ctx = core_dc->ctx; - /* Currently this function do not result in any HW programming - * when called with 0 surface. But proceeding will cause - * SW state to be updated in validate_context. So we might as - * well make it not do anything at all until the hw programming - * is implemented properly to handle 0 surface case. - * TODO: fix hw programming then remove this early return - */ - if (surface_count == 0) - return; - stream_status = dc_stream_get_status(stream); ASSERT(stream_status); @@ -1595,7 +1600,7 @@ void dc_update_planes_and_stream(struct dc *dc, } if (surface_count == 0) - core_dc->hwss.apply_ctx_for_surface(core_dc, NULL, context); + core_dc->hwss.apply_ctx_for_surface(core_dc, stream, surface_count, context); /* Lock pipes for provided surfaces, or all active if full update*/ for (i = 0; i < surface_count; i++) { @@ -1625,12 +1630,16 @@ void dc_update_planes_and_stream(struct dc *dc, bool is_new_pipe_surface = cur_pipe_ctx->plane_state != pipe_ctx->plane_state; struct dc_cursor_position position = { 0 }; + if (update_type != UPDATE_TYPE_FULL || !pipe_ctx->plane_state) continue; - if (!pipe_ctx->top_pipe) + if (!pipe_ctx->top_pipe && pipe_ctx->stream) { + struct dc_stream_status *stream_status = stream_get_status(context, pipe_ctx->stream); + core_dc->hwss.apply_ctx_for_surface( - core_dc, pipe_ctx->plane_state, context); + core_dc, pipe_ctx->stream, stream_status->plane_count, context); + } /* TODO: this is a hack w/a for switching from mpo to pipe split */ dc_stream_set_cursor_position(pipe_ctx->stream, &position); @@ -1653,7 +1662,7 @@ void dc_update_planes_and_stream(struct dc *dc, if (update_type == UPDATE_TYPE_MED) core_dc->hwss.apply_ctx_for_surface( - core_dc, plane_state, context); + core_dc, stream, surface_count, context); for (j = 0; j < core_dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index d3368a8bd1d5..59925723271e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -2614,18 +2614,27 @@ static void dce110_program_front_end_for_pipe( static void dce110_apply_ctx_for_surface( struct core_dc *dc, - const struct dc_plane_state *plane_state, + const struct dc_stream_state *stream, + int num_planes, struct validate_context *context) { - int i; + int i, be_idx; - if (!plane_state) + if (num_planes == 0) return; + be_idx = -1; + for (i = 0; i < dc->res_pool->pipe_count; i++) { + if (stream == context->res_ctx.pipe_ctx[i].stream) { + be_idx = context->res_ctx.pipe_ctx[i].stream_res.tg->inst; + break; + } + } + for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; - if (pipe_ctx->plane_state != plane_state) + if (pipe_ctx->stream == stream) continue; dce110_program_front_end_for_pipe(dc, pipe_ctx); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 114dd279fe47..948aaeb73122 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2151,7 +2151,8 @@ static void dcn10_pplib_apply_display_requirements( static void dcn10_apply_ctx_for_surface( struct core_dc *dc, - const struct dc_plane_state *plane_state, + const struct dc_stream_state *stream, + int num_planes, struct validate_context *context) { int i, be_idx; @@ -2159,12 +2160,26 @@ static void dcn10_apply_ctx_for_surface( if (dc->public.debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); - if (!plane_state) - return; - - for (be_idx = 0; be_idx < dc->res_pool->pipe_count; be_idx++) - if (plane_state == context->res_ctx.pipe_ctx[be_idx].plane_state) + be_idx = -1; + for (i = 0; i < dc->res_pool->pipe_count; i++) { + if (stream == context->res_ctx.pipe_ctx[i].stream) { + be_idx = context->res_ctx.pipe_ctx[i].stream_res.tg->inst; break; + } + } + + ASSERT(be_idx != -1); + + if (num_planes == 0) { + for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) { + struct pipe_ctx *old_pipe_ctx = + &dc->current_context->res_ctx.pipe_ctx[i]; + + if (old_pipe_ctx->stream_res.tg && old_pipe_ctx->stream_res.tg->inst == be_idx) + dcn10_power_down_fe(dc, old_pipe_ctx->pipe_idx); + } + return; + } /* reset unused mpcc */ for (i = 0; i < dc->res_pool->pipe_count; i++) { @@ -2229,7 +2244,7 @@ static void dcn10_apply_ctx_for_surface( for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; - if (pipe_ctx->plane_state != plane_state) + if (pipe_ctx->stream != stream) continue; /* looking for top pipe to program */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 5d075f93b4b9..7689e372b9da 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -59,7 +59,8 @@ struct hw_sequencer_funcs { void (*apply_ctx_for_surface)( struct core_dc *dc, - const struct dc_plane_state *plane_state, + const struct dc_stream_state *stream, + int num_planes, struct validate_context *context); void (*set_plane_config)( -- cgit From cbb4d72e290df8fedc764c7abb823cae938a45aa Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Thu, 3 Aug 2017 15:46:10 -0400 Subject: drm/amd/display: Clear water mark change request bit before programing. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 948aaeb73122..9165dc80cd22 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -320,6 +320,9 @@ static void program_watermarks( */ uint32_t prog_wm_value; + REG_UPDATE(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, + DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, 0); + /* Repeat for water mark set A, B, C and D. */ /* clock state A */ prog_wm_value = convert_and_clamp(watermarks->a.urgent_ns, @@ -518,8 +521,7 @@ static void program_watermarks( REG_UPDATE(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, 1); - REG_UPDATE(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, - DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, 0); + REG_UPDATE(DCHUBBUB_ARB_SAT_LEVEL, DCHUBBUB_ARB_SAT_LEVEL, 60 * refclk_mhz); REG_UPDATE(DCHUBBUB_ARB_DF_REQ_OUTSTAND, -- cgit From 5aa72db72ccc08c2d3d3e4b0a285bab932db5132 Mon Sep 17 00:00:00 2001 From: Corbin McElhanney Date: Thu, 3 Aug 2017 18:29:42 -0400 Subject: drm/amd/display: Fix accessing freed memory Signed-off-by: Corbin McElhanney Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index f305780c36ce..b69a726717d9 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1714,8 +1714,11 @@ void dc_update_planes_and_stream(struct dc *dc, } if (core_dc->current_context != context) { - dc_release_validate_context(core_dc->current_context); + struct validate_context *old = core_dc->current_context; + core_dc->current_context = context; + dc_release_validate_context(old); + } return; -- cgit From 8a5d82451e297fc3864bb9ab0247b53c7ab8a022 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Thu, 3 Aug 2017 21:23:04 -0400 Subject: drm/amd/display: use some sensible time out 40s time out is not sensible. also make all udelay poll happen more frequently since CPU is busy anyways Signed-off-by: Tony Cheng Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc_helper.c | 6 ++++- drivers/gpu/drm/amd/display/dc/dce/dce_abm.c | 11 +++++---- drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c | 4 ++-- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 27 ++++++++++++++-------- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c | 2 +- .../amd/display/dc/dcn10/dcn10_timing_generator.c | 18 +++++++-------- 6 files changed, 41 insertions(+), 27 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc_helper.c b/drivers/gpu/drm/amd/display/dc/dc_helper.c index f219bd2068e5..0d84b2a1ccfd 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_helper.c +++ b/drivers/gpu/drm/amd/display/dc/dc_helper.c @@ -135,6 +135,9 @@ uint32_t generic_reg_wait(const struct dc_context *ctx, uint32_t reg_val; int i; + /* something is terribly wrong if time out is > 200ms. (5Hz) */ + ASSERT(delay_between_poll_us * time_out_num_tries <= 200000); + if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment)) { /* 35 seconds */ delay_between_poll_us = 35000; @@ -158,7 +161,8 @@ uint32_t generic_reg_wait(const struct dc_context *ctx, } dm_error("REG_WAIT timeout %dus * %d tries - %s line:%d\n", - delay_between_poll_us, time_out_num_tries, func_name, line); + delay_between_poll_us, time_out_num_tries, + func_name, line); if (!IS_FPGA_MAXIMUS_DC(ctx->dce_environment)) BREAK_TO_DEBUGGER(); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c index b4fa78292ad2..0e9d914e1a8f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c @@ -195,8 +195,9 @@ static void driver_set_backlight_level(struct dce_abm *abm_dce, uint32_t level) BL_PWM_GRP1_REG_LOCK, 0); /* 5.4.4 Wait for pending bit to be cleared */ - REG_WAIT(BL_PWM_GRP1_REG_LOCK, BL_PWM_GRP1_REG_UPDATE_PENDING, - 0, 10, 1000); + REG_WAIT(BL_PWM_GRP1_REG_LOCK, + BL_PWM_GRP1_REG_UPDATE_PENDING, 0, + 1, 10000); } static void dmcu_set_backlight_level( @@ -224,7 +225,7 @@ static void dmcu_set_backlight_level( /* waitDMCUReadyForCmd */ REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, - 0, 100, 800); + 0, 1, 80000); /* setDMCUParam_BL */ REG_UPDATE(BL1_PWM_USER_LEVEL, BL1_PWM_USER_LEVEL, backlight_17_bit); @@ -304,7 +305,7 @@ static bool dce_abm_set_level(struct abm *abm, uint32_t level) struct dce_abm *abm_dce = TO_DCE_ABM(abm); REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, - 100, 800); + 1, 80000); /* setDMCUParam_ABMLevel */ REG_UPDATE_2(MASTER_COMM_CMD_REG, @@ -322,7 +323,7 @@ static bool dce_abm_immediate_disable(struct abm *abm) struct dce_abm *abm_dce = TO_DCE_ABM(abm); REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, - 100, 800); + 1, 80000); /* setDMCUParam_ABMLevel */ REG_UPDATE_2(MASTER_COMM_CMD_REG, diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c index aaff946a6d0a..92902f011418 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c @@ -262,7 +262,7 @@ static void dce_psr_wait_loop( union dce_dmcu_psr_config_data_wait_loop_reg1 masterCmdData1; /* waitDMCUReadyForCmd */ - REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 100, 100); + REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 1, 10000); masterCmdData1.u32 = 0; masterCmdData1.bits.wait_loop = wait_loop_number; @@ -502,7 +502,7 @@ static void dcn10_psr_wait_loop( union dce_dmcu_psr_config_data_wait_loop_reg1 masterCmdData1; /* waitDMCUReadyForCmd */ - REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 100, 100); + REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 1, 10000); masterCmdData1.u32 = 0; masterCmdData1.bits.wait_loop = wait_loop_number; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 9165dc80cd22..292dfef91c9d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -264,28 +264,32 @@ static void dpp_pg_control( DOMAIN1_POWER_GATE, power_gate); REG_WAIT(DOMAIN1_PG_STATUS, - DOMAIN1_PGFSM_PWR_STATUS, pwr_status, 20000, 200000); + DOMAIN1_PGFSM_PWR_STATUS, pwr_status, + 1, 1000); break; case 1: /* DPP1 */ REG_UPDATE(DOMAIN3_PG_CONFIG, DOMAIN3_POWER_GATE, power_gate); REG_WAIT(DOMAIN3_PG_STATUS, - DOMAIN3_PGFSM_PWR_STATUS, pwr_status, 20000, 200000); + DOMAIN3_PGFSM_PWR_STATUS, pwr_status, + 1, 1000); break; case 2: /* DPP2 */ REG_UPDATE(DOMAIN5_PG_CONFIG, DOMAIN5_POWER_GATE, power_gate); REG_WAIT(DOMAIN5_PG_STATUS, - DOMAIN5_PGFSM_PWR_STATUS, pwr_status, 20000, 200000); + DOMAIN5_PGFSM_PWR_STATUS, pwr_status, + 1, 1000); break; case 3: /* DPP3 */ REG_UPDATE(DOMAIN7_PG_CONFIG, DOMAIN7_POWER_GATE, power_gate); REG_WAIT(DOMAIN7_PG_STATUS, - DOMAIN7_PGFSM_PWR_STATUS, pwr_status, 20000, 200000); + DOMAIN7_PGFSM_PWR_STATUS, pwr_status, + 1, 1000); break; default: BREAK_TO_DEBUGGER(); @@ -612,28 +616,32 @@ static void hubp_pg_control( DOMAIN0_POWER_GATE, power_gate); REG_WAIT(DOMAIN0_PG_STATUS, - DOMAIN0_PGFSM_PWR_STATUS, pwr_status, 20000, 200000); + DOMAIN0_PGFSM_PWR_STATUS, pwr_status, + 1, 1000); break; case 1: /* DCHUBP1 */ REG_UPDATE(DOMAIN2_PG_CONFIG, DOMAIN2_POWER_GATE, power_gate); REG_WAIT(DOMAIN2_PG_STATUS, - DOMAIN2_PGFSM_PWR_STATUS, pwr_status, 20000, 200000); + DOMAIN2_PGFSM_PWR_STATUS, pwr_status, + 1, 1000); break; case 2: /* DCHUBP2 */ REG_UPDATE(DOMAIN4_PG_CONFIG, DOMAIN4_POWER_GATE, power_gate); REG_WAIT(DOMAIN4_PG_STATUS, - DOMAIN4_PGFSM_PWR_STATUS, pwr_status, 20000, 200000); + DOMAIN4_PGFSM_PWR_STATUS, pwr_status, + 1, 1000); break; case 3: /* DCHUBP3 */ REG_UPDATE(DOMAIN6_PG_CONFIG, DOMAIN6_POWER_GATE, power_gate); REG_WAIT(DOMAIN6_PG_STATUS, - DOMAIN6_PGFSM_PWR_STATUS, pwr_status, 20000, 200000); + DOMAIN6_PGFSM_PWR_STATUS, pwr_status, + 1, 1000); break; default: BREAK_TO_DEBUGGER(); @@ -1011,7 +1019,8 @@ static void reset_front_end( if (tg->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS) REG_WAIT(OTG_GLOBAL_SYNC_STATUS[tg->inst], - VUPDATE_NO_LOCK_EVENT_OCCURRED, 1, 20000, 200000); + VUPDATE_NO_LOCK_EVENT_OCCURRED, 1, + 1, 100000); plane_atomic_disable(dc, fe_idx); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c index 036f161ab1c1..52f2f2dd9a43 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c @@ -72,7 +72,7 @@ static void mpc10_assert_idle_mpcc(struct mpc *mpc, int id) ASSERT(!(mpc10->mpcc_in_use_mask & 1 << id)); REG_WAIT(MPCC_STATUS[id], MPCC_IDLE, 1, - 1000, 1000); + 1, 100000); } static int mpc10_get_idle_mpcc_id(struct dcn10_mpc *mpc10) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c index f4dce2806ae1..941e0125ff06 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c @@ -312,7 +312,7 @@ static void tgn10_blank_crtc(struct timing_generator *tg) */ REG_WAIT(OTG_BLANK_CONTROL, OTG_BLANK_DATA_EN, 1, - 20000, 200000); + 1, 100000); REG_UPDATE(OTG_DOUBLE_BUFFER_CONTROL, OTG_BLANK_DATA_DOUBLE_BUFFER_EN, 0); @@ -351,7 +351,7 @@ static void tgn10_enable_optc_clock(struct timing_generator *tg, bool enable) REG_WAIT(OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_ON, 1, - 2000, 500); + 1, 1000); /* Enable clock */ REG_UPDATE_2(OTG_CLOCK_CONTROL, @@ -359,7 +359,7 @@ static void tgn10_enable_optc_clock(struct timing_generator *tg, bool enable) OTG_CLOCK_GATE_DIS, 1); REG_WAIT(OTG_CLOCK_CONTROL, OTG_CLOCK_ON, 1, - 2000, 500); + 1, 1000); } else { REG_UPDATE_2(OTG_CLOCK_CONTROL, OTG_CLOCK_GATE_DIS, 0, @@ -368,7 +368,7 @@ static void tgn10_enable_optc_clock(struct timing_generator *tg, bool enable) if (tg->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS) REG_WAIT(OTG_CLOCK_CONTROL, OTG_CLOCK_ON, 0, - 2000, 500); + 1, 1000); REG_UPDATE_2(OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_GATE_DIS, 0, @@ -377,7 +377,7 @@ static void tgn10_enable_optc_clock(struct timing_generator *tg, bool enable) if (tg->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS) REG_WAIT(OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_ON, 0, - 2000, 500); + 1, 1000); } } @@ -429,7 +429,7 @@ static bool tgn10_disable_crtc(struct timing_generator *tg) /* CRTC disabled, so disable clock. */ REG_WAIT(OTG_CLOCK_CONTROL, OTG_BUSY, 0, - 2000, 500); + 1, 100000); return true; } @@ -556,7 +556,7 @@ static void tgn10_unlock(struct timing_generator *tg) /* why are we waiting here? */ REG_WAIT(OTG_DOUBLE_BUFFER_CONTROL, OTG_UPDATE_PENDING, 0, - 20000, 200000); + 1, 100000); } static void tgn10_get_position(struct timing_generator *tg, @@ -651,13 +651,13 @@ static void tgn10_wait_for_state(struct timing_generator *tg, case CRTC_STATE_VBLANK: REG_WAIT(OTG_STATUS, OTG_V_BLANK, 1, - 100, 100000); /* 1 vupdate at 10hz */ + 1, 100000); /* 1 vupdate at 10hz */ break; case CRTC_STATE_VACTIVE: REG_WAIT(OTG_STATUS, OTG_V_ACTIVE_DISP, 1, - 100, 100000); /* 1 vupdate at 10hz */ + 1, 100000); /* 1 vupdate at 10hz */ break; default: -- cgit From 0627bbd30f87e06987cb38aee557b06414ae3735 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Sat, 5 Aug 2017 10:30:11 -0400 Subject: drm/amd/display: Use public plane destroy helper Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/gpu') 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 b0fcfebc04b8..3aab3d233a52 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2835,8 +2835,7 @@ void dm_drm_plane_destroy_state(struct drm_plane *plane, if (dm_plane_state->dc_state) dc_plane_state_release(dm_plane_state->dc_state); - __drm_atomic_helper_plane_destroy_state(state); - kfree(dm_plane_state); + drm_atomic_helper_plane_destroy_state(plane, state); } static const struct drm_plane_funcs dm_plane_funcs = { -- cgit From e1403629d86402ccc25a5c18feb80fc97f671c12 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Sat, 5 Aug 2017 12:43:45 -0400 Subject: drm/amd/display: Couple newline fixes Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 ++-- drivers/gpu/drm/amd/display/dc/dc.h | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') 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 3aab3d233a52..0caf8135084b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1472,7 +1472,6 @@ static const struct amdgpu_display_funcs dm_display_funcs = { }; - #if defined(CONFIG_DEBUG_KERNEL_DC) static ssize_t s3_debug_store( @@ -1594,7 +1593,8 @@ bool amdgpu_dm_acquire_dal_lock(struct amdgpu_display_manager *dm) bool amdgpu_dm_release_dal_lock(struct amdgpu_display_manager *dm) { - /* TODO */ return true; + /* TODO */ + return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index d1a6398043a3..cac92bf91e4a 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -312,7 +312,6 @@ struct dc_plane_status { struct dc_plane_state { struct dc_plane_address address; - struct scaling_taps scaling_quality; struct rect src_rect; struct rect dst_rect; -- cgit From 08b8ccfbcb511aa64efd8fa211f785597890af9e Mon Sep 17 00:00:00 2001 From: Corbin McElhanney Date: Fri, 4 Aug 2017 15:30:45 -0400 Subject: drm/amd/display: Fix hw state logging regression Signed-off-by: Corbin McElhanney Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 292dfef91c9d..2fd9c33dbf1c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -134,6 +134,7 @@ static void verify_allow_pstate_change_high( static unsigned int pstate_wait_timeout_us = 40; static unsigned int max_sampled_pstate_wait_us; /* data collection */ static bool forced_pstate_allow; /* help with revert wa */ + static bool should_log_hw_state; /* prevent hw state log by default */ unsigned int debug_index = 0x7; unsigned int debug_data; @@ -191,7 +192,9 @@ static void verify_allow_pstate_change_high( REG_WRITE(DCHUBBUB_ARB_DRAM_STATE_CNTL, force_allow_pstate); forced_pstate_allow = true; - dcn10_log_hw_state(DC_TO_CORE(hws->ctx->dc)); + if (should_log_hw_state) { + dcn10_log_hw_state(DC_TO_CORE(hws->ctx->dc)); + } BREAK_TO_DEBUGGER(); } -- cgit From 9d6f264b5653e1fe5e9646c7075cfc81445b25cd Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Fri, 4 Aug 2017 15:42:36 -0400 Subject: drm/amd/display: Workaround for underflow. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 29 ++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 2fd9c33dbf1c..b07ca5693cb6 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1150,6 +1150,22 @@ static bool patch_address_for_sbs_tb_stereo( return false; } +static void toggle_watermark_change_req(struct dce_hwseq *hws) +{ + uint32_t watermark_change_req; + + REG_GET(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, + DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, &watermark_change_req); + + if (watermark_change_req) + watermark_change_req = 0; + else + watermark_change_req = 1; + + REG_UPDATE(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, + DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, watermark_change_req); +} + static void update_plane_addr(const struct core_dc *dc, struct pipe_ctx *pipe_ctx) { bool addr_patched = false; @@ -2089,6 +2105,7 @@ static void update_dchubp_dpp( mi->funcs->set_blank(mi, !is_pipe_tree_visible(pipe_ctx)); } + static void program_all_pipe_in_tree( struct core_dc *dc, struct pipe_ctx *pipe_ctx, @@ -2124,6 +2141,18 @@ static void program_all_pipe_in_tree( if (pipe_ctx->plane_state != NULL) { dcn10_power_on_fe(dc, pipe_ctx, context); + + /* temporary dcn1 wa: + * watermark update requires toggle after a/b/c/d sets are programmed + * if hubp is pg then wm value doesn't get properaged to hubp + * need to toggle after ungate to ensure wm gets to hubp. + * + * final solution: we need to get SMU to do the toggle as + * DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST is owned by SMU we should have + * both driver and fw accessing same register + */ + toggle_watermark_change_req(dc->hwseq); + update_dchubp_dpp(dc, pipe_ctx, context); } -- cgit From 233dcd2092f9f9786ff019174b1d38f288231f2c Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Thu, 3 Aug 2017 23:21:46 -0400 Subject: drm/amd/display: log watermarks Signed-off-by: Tony Cheng Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 80 ++++++++++++++++++++++ 1 file changed, 80 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index b07ca5693cb6..7b943e1837ce 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -79,6 +79,84 @@ void print_microsec(struct dc_context *dc_ctx, uint32_t ref_cycle) #define DTN_INFO_MICRO_SEC(ref_cycle) \ print_microsec(dc_ctx, ref_cycle) +struct dcn_hubbub_wm_set { + uint32_t wm_set; + uint32_t data_urgent; + uint32_t pte_meta_urgent; + uint32_t sr_enter; + uint32_t sr_exit; + uint32_t dram_clk_chanage; +}; + +struct dcn_hubbub_wm { + struct dcn_hubbub_wm_set sets[4]; +}; + +static void dcn10_hubbub_wm_read_state(struct dce_hwseq *hws, + struct dcn_hubbub_wm *wm) +{ + struct dcn_hubbub_wm_set *s; + + s = &wm->sets[0]; + s->wm_set = 0; + s->data_urgent = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A); + s->pte_meta_urgent = REG_READ(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A); + s->sr_enter = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A); + s->sr_exit = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A); + s->dram_clk_chanage = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A); + + s = &wm->sets[1]; + s->wm_set = 1; + s->data_urgent = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B); + s->pte_meta_urgent = REG_READ(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B); + s->sr_enter = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B); + s->sr_exit = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B); + s->dram_clk_chanage = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B); + + s = &wm->sets[2]; + s->wm_set = 2; + s->data_urgent = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C); + s->pte_meta_urgent = REG_READ(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C); + s->sr_enter = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C); + s->sr_exit = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C); + s->dram_clk_chanage = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C); + + s = &wm->sets[3]; + s->wm_set = 3; + s->data_urgent = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D); + s->pte_meta_urgent = REG_READ(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D); + s->sr_enter = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D); + s->sr_exit = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D); + s->dram_clk_chanage = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D); +} + +static void dcn10_log_hubbub_state(struct core_dc *dc) +{ + struct dc_context *dc_ctx = dc->ctx; + struct dcn_hubbub_wm wm; + int i; + + dcn10_hubbub_wm_read_state(dc->hwseq, &wm); + + DTN_INFO("HUBBUB WM: \t data_urgent \t pte_meta_urgent \t " + "sr_enter \t sr_exit \t dram_clk_change \n"); + + for (i = 0; i < 4; i++) { + struct dcn_hubbub_wm_set *s; + + s = &wm.sets[i]; + DTN_INFO("WM_Set[%d]:\t ", s->wm_set); + DTN_INFO_MICRO_SEC(s->data_urgent); + DTN_INFO_MICRO_SEC(s->pte_meta_urgent); + DTN_INFO_MICRO_SEC(s->sr_enter); + DTN_INFO_MICRO_SEC(s->sr_exit); + DTN_INFO_MICRO_SEC(s->dram_clk_chanage); + DTN_INFO("\n"); + } + + DTN_INFO("\n"); +} + static void dcn10_log_hw_state(struct core_dc *dc) { struct dc_context *dc_ctx = dc->ctx; @@ -87,6 +165,8 @@ static void dcn10_log_hw_state(struct core_dc *dc) DTN_INFO_BEGIN(); + dcn10_log_hubbub_state(dc); + DTN_INFO("HUBP:\t format \t addr_hi \t width \t height \t " "rotation \t mirror \t sw_mode \t " "dcc_en \t blank_en \t ttu_dis \t underflow \t " -- cgit From f0c4d9977ae215859ff13304ef0fc02a8b779478 Mon Sep 17 00:00:00 2001 From: Corbin McElhanney Date: Thu, 3 Aug 2017 14:20:14 -0400 Subject: drm/amd/display: fix HDMI 12bits last two bits are zero issue (FF-158) -[FF N-1] HDMI Deep Color Mode incorrect bit depth: FMT_DYNAMIC_EXP_EN is being reset to 0 Signed-off-by: Charlene Liu Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 17 +++++++++++------ drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c | 3 ++- 2 files changed, 13 insertions(+), 7 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 59925723271e..c29e51409286 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1044,14 +1044,14 @@ static enum dc_status apply_single_controller_ctx_to_hw( /* */ dc->hwss.prog_pixclk_crtc_otg(pipe_ctx, context, dc); - pipe_ctx->stream_res.opp->funcs->opp_set_dyn_expansion( - pipe_ctx->stream_res.opp, - COLOR_SPACE_YCBCR601, - stream->timing.display_color_depth, - pipe_ctx->stream->signal); - /* FPGA does not program backend */ if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { + pipe_ctx->stream_res.opp->funcs->opp_set_dyn_expansion( + pipe_ctx->stream_res.opp, + COLOR_SPACE_YCBCR601, + stream->timing.display_color_depth, + pipe_ctx->stream->signal); + pipe_ctx->stream_res.opp->funcs->opp_program_fmt( pipe_ctx->stream_res.opp, &stream->bit_depth_params, @@ -1064,6 +1064,11 @@ static enum dc_status apply_single_controller_ctx_to_hw( BREAK_TO_DEBUGGER(); return DC_ERROR_UNEXPECTED; } + pipe_ctx->stream_res.opp->funcs->opp_set_dyn_expansion( + pipe_ctx->stream_res.opp, + COLOR_SPACE_YCBCR601, + stream->timing.display_color_depth, + pipe_ctx->stream->signal); if (pipe_ctx->stream->signal != SIGNAL_TYPE_VIRTUAL) stream->sink->link->link_enc->funcs->setup( diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c index 38d15f7c2a88..8048782ac599 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c @@ -240,7 +240,8 @@ static void oppn10_set_dyn_expansion( /*01 - 8-bit -> 12-bit dynamic expansion*/ if (signal == SIGNAL_TYPE_HDMI_TYPE_A || signal == SIGNAL_TYPE_DISPLAY_PORT || - signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { + signal == SIGNAL_TYPE_DISPLAY_PORT_MST || + signal == SIGNAL_TYPE_VIRTUAL) { switch (color_dpth) { case COLOR_DEPTH_888: REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL, -- cgit From a2607aef3d0210859d4e9cae6bba7e134ec720d8 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 8 Aug 2017 11:35:10 -0400 Subject: drm/amd/display: Fix regression in dce110_apply_ctx_for_surfaces Caused by "add programming for 0 plane case" which was tested on DCN but not on DCE. Signed-off-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index c29e51409286..5b46e776b9b7 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -2639,7 +2639,7 @@ static void dce110_apply_ctx_for_surface( for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; - if (pipe_ctx->stream == stream) + if (pipe_ctx->stream != stream) continue; dce110_program_front_end_for_pipe(dc, pipe_ctx); -- cgit From 7483bed45de728dacc7cfffe641e67abb3513f61 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 8 Aug 2017 12:23:15 -0400 Subject: drm/amd/display: Pass correct number for gamma entries This was broken by "implement DXGI Gamma Ramps" Signed-off-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') 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 0caf8135084b..7a50aeae8ad7 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1890,7 +1890,8 @@ static void fill_gamma_from_crtc_state( return; } - gamma->type = GAMMA_RGB_256_ENTRIES; + gamma->type = GAMMA_RGB_256; + gamma->num_entries = GAMMA_RGB_256_ENTRIES; for (i = 0; i < GAMMA_RGB_256_ENTRIES; i++) { gamma->entries.red[i] = dal_fixed31_32_from_int(lut[i].red); gamma->entries.green[i] = dal_fixed31_32_from_int(lut[i].green); -- cgit From 533ed6c708334b697254ff831972b657f5c98a40 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 8 Aug 2017 21:01:20 -0400 Subject: drm/amd/display: Fix warnings about uninitialized use Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 2 +- drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 72eb6af62f45..b858fec72bd7 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -541,7 +541,7 @@ bool dc_link_detect(struct dc_link *link, bool boot) struct audio_support *aud_support = &link->dc->res_pool->audio_support; enum dc_edid_status edid_status; struct dc_context *dc_ctx = link->ctx; - struct dc_sink *sink; + struct dc_sink *sink = NULL; enum dc_connection_type new_connection_type = dc_connection_none; if (link->connector_signal == SIGNAL_TYPE_VIRTUAL) diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c index da08cc1c6dc3..4035caf47d31 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c @@ -265,6 +265,8 @@ static bool get_hw_supported_ddc_line( { enum gpio_ddc_line line_found; + *line = GPIO_DDC_LINE_UNKNOWN; + if (!ddc) { BREAK_TO_DEBUGGER(); return false; -- cgit From 5394eb82133b6e9897b9d6e5aed13c08dd71d8c2 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 10 Aug 2017 14:22:21 -0400 Subject: drm/amd/display/dc: Make dce110_validate_bandwidth static (v2) Not used outside of the dce110_resource.c. v2: make a bunch of other functions static as well. Signed-off-by: Alex Deucher Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index c677f98c3516..a7f30dcc906c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -565,7 +565,7 @@ static const struct encoder_feature_support link_enc_feature = { .flags.bits.IS_YCBCR_CAPABLE = true }; -struct link_encoder *dce110_link_encoder_create( +static struct link_encoder *dce110_link_encoder_create( const struct encoder_init_data *enc_init_data) { struct dce110_link_encoder *enc110 = @@ -813,7 +813,7 @@ static enum dc_status build_mapped_resource( return DC_OK; } -bool dce110_validate_bandwidth( +static bool dce110_validate_bandwidth( const struct core_dc *dc, struct validate_context *context) { @@ -927,7 +927,7 @@ static bool dce110_validate_surface_sets( return true; } -enum dc_status dce110_validate_with_context( +static enum dc_status dce110_validate_with_context( const struct core_dc *dc, const struct dc_validation_set set[], int set_count, @@ -971,7 +971,7 @@ enum dc_status dce110_validate_with_context( return result; } -enum dc_status dce110_validate_guaranteed( +static enum dc_status dce110_validate_guaranteed( const struct core_dc *dc, struct dc_stream_state *dc_stream, struct validate_context *context) -- cgit From 2cf5a5e6adba1021a608f58fcedce7201d671086 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 10 Aug 2017 14:22:22 -0400 Subject: drm/amd/display/dc: make dce120_link_encoder_create static Only used in dce120_resource.c. Signed-off-by: Alex Deucher Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index 6448d15c02f5..d4e962756fbb 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -535,7 +535,7 @@ static const struct encoder_feature_support link_enc_feature = { .flags.bits.IS_YCBCR_CAPABLE = true }; -struct link_encoder *dce120_link_encoder_create( +static struct link_encoder *dce120_link_encoder_create( const struct encoder_init_data *enc_init_data) { struct dce110_link_encoder *enc110 = -- cgit From cd4b356f3a8abcd8a96e19b515cf7dc00f41dcbe Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 10 Aug 2017 14:39:47 -0400 Subject: drm/amd/display/dm: add KV, KB, ML (v2) Add DCE8 APUs to display manager. v2: rebase changes Signed-off-by: Alex Deucher Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers/gpu') 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 7a50aeae8ad7..d28de04efa42 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1355,6 +1355,9 @@ int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) switch (adev->asic_type) { case CHIP_BONAIRE: case CHIP_HAWAII: + case CHIP_KAVERI: + case CHIP_KABINI: + case CHIP_MULLINS: case CHIP_TONGA: case CHIP_FIJI: case CHIP_CARRIZO: @@ -1519,6 +1522,19 @@ static int dm_early_init(void *handle) adev->mode_info.num_dig = 6; adev->mode_info.plane_type = dm_plane_type_default; break; + case CHIP_KAVERI: + adev->mode_info.num_crtc = 4; + adev->mode_info.num_hpd = 6; + adev->mode_info.num_dig = 7; + adev->mode_info.plane_type = dm_plane_type_default; + break; + case CHIP_KABINI: + case CHIP_MULLINS: + adev->mode_info.num_crtc = 2; + adev->mode_info.num_hpd = 6; + adev->mode_info.num_dig = 6; + adev->mode_info.plane_type = dm_plane_type_default; + break; case CHIP_FIJI: case CHIP_TONGA: adev->mode_info.num_crtc = 6; -- cgit From 0d6fbccb22f8af70b729367431a489093aad2ddd Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 10 Aug 2017 14:39:48 -0400 Subject: drm/amdgpu: add DCE8 APUs to dc_supported check Signed-off-by: Alex Deucher Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 2368792b7d67..99f91e52db10 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1980,6 +1980,9 @@ bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type) #if defined(CONFIG_DRM_AMD_DC) case CHIP_BONAIRE: case CHIP_HAWAII: + case CHIP_KAVERI: + case CHIP_KABINI: + case CHIP_MULLINS: case CHIP_CARRIZO: case CHIP_STONEY: case CHIP_POLARIS11: -- cgit From ea062558fd796ecff167ca64282bd2c3e3e2663f Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 10 Aug 2017 14:39:49 -0400 Subject: drm/amd/display/dc: add DIGG for KV KV has 7 possible DIG blocks. Signed-off-by: Alex Deucher Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 6 ++++++ drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 5bb2ac71f297..7e9afab8fca0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -80,6 +80,7 @@ #define DCE110_DIG_FE_SOURCE_SELECT_DIGD 0x08 #define DCE110_DIG_FE_SOURCE_SELECT_DIGE 0x10 #define DCE110_DIG_FE_SOURCE_SELECT_DIGF 0x20 +#define DCE110_DIG_FE_SOURCE_SELECT_DIGG 0x40 /* all values are in milliseconds */ /* For eDP, after power-up/power/down, @@ -471,6 +472,8 @@ static uint8_t get_frontend_source( return DCE110_DIG_FE_SOURCE_SELECT_DIGE; case ENGINE_ID_DIGF: return DCE110_DIG_FE_SOURCE_SELECT_DIGF; + case ENGINE_ID_DIGG: + return DCE110_DIG_FE_SOURCE_SELECT_DIGG; default: ASSERT_CRITICAL(false); return DCE110_DIG_FE_SOURCE_SELECT_INVALID; @@ -984,6 +987,9 @@ bool dce110_link_encoder_construct( case TRANSMITTER_UNIPHY_F: enc110->base.preferred_engine = ENGINE_ID_DIGF; break; + case TRANSMITTER_UNIPHY_G: + enc110->base.preferred_engine = ENGINE_ID_DIGG; + break; default: ASSERT_CRITICAL(false); enc110->base.preferred_engine = ENGINE_ID_UNKNOWN; diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 7473f58584c3..40a9591833aa 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -262,7 +262,8 @@ static const struct dce110_stream_enc_registers stream_enc_regs[] = { stream_enc_regs(2), stream_enc_regs(3), stream_enc_regs(4), - stream_enc_regs(5) + stream_enc_regs(5), + stream_enc_regs(6) }; static const struct dce_stream_encoder_shift se_shift = { -- cgit From ebfdf0d0770bd20e9baff3750b5103d6b7fa21c3 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 10 Aug 2017 14:39:50 -0400 Subject: drm/amd/display/dc: add DCE_VERSION for DCE8 APUs DCE 8.1 = Kaveri DCE 8.3 = Kabini/Mullins Signed-off-by: Alex Deucher Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/bios/command_table_helper.c | 2 ++ drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c | 2 ++ drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 11 ++++++++++- drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c | 6 ++++++ drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c | 2 ++ drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c | 2 ++ drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c | 2 ++ drivers/gpu/drm/amd/display/include/dal_types.h | 2 ++ 8 files changed, 28 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper.c b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper.c index 40d9a9921c45..2979358c6a55 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper.c @@ -37,6 +37,8 @@ bool dal_bios_parser_init_cmd_tbl_helper( { switch (dce) { case DCE_VERSION_8_0: + case DCE_VERSION_8_1: + case DCE_VERSION_8_3: *h = dal_cmd_tbl_helper_dce80_get_table(); return true; diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c index 9084a32aab79..35c3f3a8e493 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c @@ -39,6 +39,8 @@ bool dal_bios_parser_init_cmd_tbl_helper2( { switch (dce) { case DCE_VERSION_8_0: + case DCE_VERSION_8_1: + case DCE_VERSION_8_3: *h = dal_cmd_tbl_helper_dce80_get_table(); return true; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 30237f049c99..ee7a393b2b00 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -50,9 +50,16 @@ enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id) switch (asic_id.chip_family) { case FAMILY_CI: - case FAMILY_KV: dc_version = DCE_VERSION_8_0; break; + case FAMILY_KV: + if (ASIC_REV_IS_KALINDI(asic_id.hw_internal_rev) || + ASIC_REV_IS_BHAVANI(asic_id.hw_internal_rev) || + ASIC_REV_IS_GODAVARI(asic_id.hw_internal_rev)) + dc_version = DCE_VERSION_8_3; + else + dc_version = DCE_VERSION_8_1; + break; case FAMILY_CZ: dc_version = DCE_VERSION_11_0; break; @@ -94,6 +101,8 @@ struct resource_pool *dc_create_resource_pool( switch (dc_version) { case DCE_VERSION_8_0: + case DCE_VERSION_8_1: + case DCE_VERSION_8_3: res_pool = dce80_create_resource_pool( num_virtual_links, dc); break; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index dd7e1dd62636..88e266ac6dd3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -578,6 +578,8 @@ static uint32_t dce110_get_pix_clk_dividers( switch (cs->ctx->dce_version) { case DCE_VERSION_8_0: + case DCE_VERSION_8_1: + case DCE_VERSION_8_3: case DCE_VERSION_10_0: case DCE_VERSION_11_0: pll_calc_error = @@ -862,6 +864,8 @@ static bool dce110_program_pix_clk( switch (clock_source->ctx->dce_version) { case DCE_VERSION_8_0: + case DCE_VERSION_8_1: + case DCE_VERSION_8_3: case DCE_VERSION_10_0: case DCE_VERSION_11_0: bp_pc_params.reference_divider = pll_settings->reference_divider; @@ -1209,6 +1213,8 @@ bool dce110_clk_src_construct( switch (clk_src->base.ctx->dce_version) { case DCE_VERSION_8_0: + case DCE_VERSION_8_1: + case DCE_VERSION_8_3: case DCE_VERSION_10_0: case DCE_VERSION_11_0: diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c index 425f1c4fa891..25f6f9103c44 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c @@ -66,6 +66,8 @@ bool dal_hw_factory_init( switch (dce_version) { case DCE_VERSION_8_0: + case DCE_VERSION_8_1: + case DCE_VERSION_8_3: dal_hw_factory_dce80_init(factory); return true; diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c index 3b55d45b6775..0ae8ace25739 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c @@ -65,6 +65,8 @@ bool dal_hw_translate_init( switch (dce_version) { case DCE_VERSION_8_0: + case DCE_VERSION_8_1: + case DCE_VERSION_8_3: dal_hw_translate_dce80_init(translate); return true; case DCE_VERSION_10_0: diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c index 4035caf47d31..9b115e1e2f1a 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c @@ -79,6 +79,8 @@ struct i2caux *dal_i2caux_create( switch (ctx->dce_version) { case DCE_VERSION_8_0: + case DCE_VERSION_8_1: + case DCE_VERSION_8_3: return dal_i2caux_dce80_create(ctx); case DCE_VERSION_11_2: return dal_i2caux_dce112_create(ctx); diff --git a/drivers/gpu/drm/amd/display/include/dal_types.h b/drivers/gpu/drm/amd/display/include/dal_types.h index 1bfc191574aa..fa543965feb5 100644 --- a/drivers/gpu/drm/amd/display/include/dal_types.h +++ b/drivers/gpu/drm/amd/display/include/dal_types.h @@ -35,6 +35,8 @@ struct dc_bios; enum dce_version { DCE_VERSION_UNKNOWN = (-1), DCE_VERSION_8_0, + DCE_VERSION_8_1, + DCE_VERSION_8_3, DCE_VERSION_10_0, DCE_VERSION_11_0, DCE_VERSION_11_2, -- cgit From 7992a6290a79afc1568c873d434f39234f7d3e26 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 10 Aug 2017 14:39:51 -0400 Subject: drm/amd/disply/dc: add resource support for DCE8 APUs (v2) Add the appropriate resources for APUs: KV: 4 pipes, 7 dig, 3 PPLLs KB/ML: 2 pipes, 6 dig, 2 PPLLs v2: rebase changes Signed-off-by: Alex Deucher Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 8 +- .../gpu/drm/amd/display/dc/dce80/dce80_resource.c | 343 ++++++++++++++++++++- .../gpu/drm/amd/display/dc/dce80/dce80_resource.h | 8 + 3 files changed, 356 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index ee7a393b2b00..56a85c80131d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -101,9 +101,15 @@ struct resource_pool *dc_create_resource_pool( switch (dc_version) { case DCE_VERSION_8_0: + res_pool = dce80_create_resource_pool( + num_virtual_links, dc); + break; case DCE_VERSION_8_1: + res_pool = dce81_create_resource_pool( + num_virtual_links, dc); + break; case DCE_VERSION_8_3: - res_pool = dce80_create_resource_pool( + res_pool = dce83_create_resource_pool( num_virtual_links, dc); break; case DCE_VERSION_10_0: diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 40a9591833aa..132117e8bb77 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -350,6 +350,20 @@ static const struct resource_caps res_cap = { .num_pll = 3, }; +static const struct resource_caps res_cap_81 = { + .num_timing_generator = 4, + .num_audio = 7, + .num_stream_encoder = 7, + .num_pll = 3, +}; + +static const struct resource_caps res_cap_83 = { + .num_timing_generator = 2, + .num_audio = 6, + .num_stream_encoder = 6, + .num_pll = 2, +}; + #define CTX ctx #define REG(reg) mm ## reg @@ -829,7 +843,7 @@ static const struct resource_funcs dce80_res_pool_funcs = { .validate_plane = dce100_validate_plane }; -static bool construct( +static bool dce80_construct( uint8_t num_virtual_links, struct core_dc *dc, struct dce110_resource_pool *pool) @@ -987,10 +1001,335 @@ struct resource_pool *dce80_create_resource_pool( if (!pool) return NULL; - if (construct(num_virtual_links, dc, pool)) + if (dce80_construct(num_virtual_links, dc, pool)) return &pool->base; BREAK_TO_DEBUGGER(); return NULL; } +static bool dce81_construct( + uint8_t num_virtual_links, + struct core_dc *dc, + struct dce110_resource_pool *pool) +{ + unsigned int i; + struct dc_context *ctx = dc->ctx; + struct dc_firmware_info info; + struct dc_bios *bp; + struct dm_pp_static_clock_info static_clk_info = {0}; + + ctx->dc_bios->regs = &bios_regs; + + pool->base.res_cap = &res_cap_81; + pool->base.funcs = &dce80_res_pool_funcs; + + + /************************************************* + * Resource + asic cap harcoding * + *************************************************/ + pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + pool->base.pipe_count = res_cap_81.num_timing_generator; + dc->public.caps.max_downscale_ratio = 200; + dc->public.caps.i2c_speed_in_khz = 40; + dc->public.caps.max_cursor_size = 128; + + /************************************************* + * Create resources * + *************************************************/ + + bp = ctx->dc_bios; + + if ((bp->funcs->get_firmware_info(bp, &info) == BP_RESULT_OK) && + info.external_clock_source_frequency_for_dp != 0) { + pool->base.dp_clock_source = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true); + + pool->base.clock_sources[0] = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], false); + pool->base.clock_sources[1] = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false); + pool->base.clock_sources[2] = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false); + pool->base.clk_src_count = 3; + + } else { + pool->base.dp_clock_source = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], true); + + pool->base.clock_sources[0] = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false); + pool->base.clock_sources[1] = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false); + pool->base.clk_src_count = 2; + } + + if (pool->base.dp_clock_source == NULL) { + dm_error("DC: failed to create dp clock source!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] == NULL) { + dm_error("DC: failed to create clock sources!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + } + + pool->base.display_clock = dce_disp_clk_create(ctx, + &disp_clk_regs, + &disp_clk_shift, + &disp_clk_mask); + if (pool->base.display_clock == NULL) { + dm_error("DC: failed to create display clock!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + + if (dm_pp_get_static_clocks(ctx, &static_clk_info)) + pool->base.display_clock->max_clks_state = + static_clk_info.max_clocks_state; + + { + struct irq_service_init_data init_data; + init_data.ctx = dc->ctx; + pool->base.irqs = dal_irq_service_dce80_create(&init_data); + if (!pool->base.irqs) + goto res_create_fail; + } + + for (i = 0; i < pool->base.pipe_count; i++) { + pool->base.timing_generators[i] = dce80_timing_generator_create( + ctx, i, &dce80_tg_offsets[i]); + if (pool->base.timing_generators[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create tg!\n"); + goto res_create_fail; + } + + pool->base.mis[i] = dce80_mem_input_create(ctx, i); + if (pool->base.mis[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create memory input!\n"); + goto res_create_fail; + } + + pool->base.ipps[i] = dce80_ipp_create(ctx, i); + if (pool->base.ipps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create input pixel processor!\n"); + goto res_create_fail; + } + + pool->base.transforms[i] = dce80_transform_create(ctx, i); + if (pool->base.transforms[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create transform!\n"); + goto res_create_fail; + } + + pool->base.opps[i] = dce80_opp_create(ctx, i); + if (pool->base.opps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create output pixel processor!\n"); + goto res_create_fail; + } + } + + dc->public.caps.max_planes = pool->base.pipe_count; + + if (!resource_construct(num_virtual_links, dc, &pool->base, + &res_create_funcs)) + goto res_create_fail; + + /* Create hardware sequencer */ + if (!dce80_hw_sequencer_construct(dc)) + goto res_create_fail; + + return true; + +res_create_fail: + destruct(pool); + return false; +} + +struct resource_pool *dce81_create_resource_pool( + uint8_t num_virtual_links, + struct core_dc *dc) +{ + struct dce110_resource_pool *pool = + dm_alloc(sizeof(struct dce110_resource_pool)); + + if (!pool) + return NULL; + + if (dce81_construct(num_virtual_links, dc, pool)) + return &pool->base; + + BREAK_TO_DEBUGGER(); + return NULL; +} + +static bool dce83_construct( + uint8_t num_virtual_links, + struct core_dc *dc, + struct dce110_resource_pool *pool) +{ + unsigned int i; + struct dc_context *ctx = dc->ctx; + struct dc_firmware_info info; + struct dc_bios *bp; + struct dm_pp_static_clock_info static_clk_info = {0}; + + ctx->dc_bios->regs = &bios_regs; + + pool->base.res_cap = &res_cap_83; + pool->base.funcs = &dce80_res_pool_funcs; + + + /************************************************* + * Resource + asic cap harcoding * + *************************************************/ + pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + pool->base.pipe_count = res_cap_83.num_timing_generator; + dc->public.caps.max_downscale_ratio = 200; + dc->public.caps.i2c_speed_in_khz = 40; + dc->public.caps.max_cursor_size = 128; + + /************************************************* + * Create resources * + *************************************************/ + + bp = ctx->dc_bios; + + if ((bp->funcs->get_firmware_info(bp, &info) == BP_RESULT_OK) && + info.external_clock_source_frequency_for_dp != 0) { + pool->base.dp_clock_source = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true); + + pool->base.clock_sources[0] = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[0], false); + pool->base.clock_sources[1] = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[1], false); + pool->base.clk_src_count = 2; + + } else { + pool->base.dp_clock_source = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[0], true); + + pool->base.clock_sources[0] = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[1], false); + pool->base.clk_src_count = 1; + } + + if (pool->base.dp_clock_source == NULL) { + dm_error("DC: failed to create dp clock source!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] == NULL) { + dm_error("DC: failed to create clock sources!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + } + + pool->base.display_clock = dce_disp_clk_create(ctx, + &disp_clk_regs, + &disp_clk_shift, + &disp_clk_mask); + if (pool->base.display_clock == NULL) { + dm_error("DC: failed to create display clock!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + + if (dm_pp_get_static_clocks(ctx, &static_clk_info)) + pool->base.display_clock->max_clks_state = + static_clk_info.max_clocks_state; + + { + struct irq_service_init_data init_data; + init_data.ctx = dc->ctx; + pool->base.irqs = dal_irq_service_dce80_create(&init_data); + if (!pool->base.irqs) + goto res_create_fail; + } + + for (i = 0; i < pool->base.pipe_count; i++) { + pool->base.timing_generators[i] = dce80_timing_generator_create( + ctx, i, &dce80_tg_offsets[i]); + if (pool->base.timing_generators[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create tg!\n"); + goto res_create_fail; + } + + pool->base.mis[i] = dce80_mem_input_create(ctx, i); + if (pool->base.mis[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create memory input!\n"); + goto res_create_fail; + } + + pool->base.ipps[i] = dce80_ipp_create(ctx, i); + if (pool->base.ipps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create input pixel processor!\n"); + goto res_create_fail; + } + + pool->base.transforms[i] = dce80_transform_create(ctx, i); + if (pool->base.transforms[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create transform!\n"); + goto res_create_fail; + } + + pool->base.opps[i] = dce80_opp_create(ctx, i); + if (pool->base.opps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create output pixel processor!\n"); + goto res_create_fail; + } + } + + dc->public.caps.max_planes = pool->base.pipe_count; + + if (!resource_construct(num_virtual_links, dc, &pool->base, + &res_create_funcs)) + goto res_create_fail; + + /* Create hardware sequencer */ + if (!dce80_hw_sequencer_construct(dc)) + goto res_create_fail; + + return true; + +res_create_fail: + destruct(pool); + return false; +} + +struct resource_pool *dce83_create_resource_pool( + uint8_t num_virtual_links, + struct core_dc *dc) +{ + struct dce110_resource_pool *pool = + dm_alloc(sizeof(struct dce110_resource_pool)); + + if (!pool) + return NULL; + + if (dce83_construct(num_virtual_links, dc, pool)) + return &pool->base; + + BREAK_TO_DEBUGGER(); + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.h b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.h index 2a0cdccddeaf..04f0cfe24ef2 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.h @@ -35,5 +35,13 @@ struct resource_pool *dce80_create_resource_pool( uint8_t num_virtual_links, struct core_dc *dc); +struct resource_pool *dce81_create_resource_pool( + uint8_t num_virtual_links, + struct core_dc *dc); + +struct resource_pool *dce83_create_resource_pool( + uint8_t num_virtual_links, + struct core_dc *dc); + #endif /* __DC_RESOURCE_DCE80_H__ */ -- cgit From 9355c0e8519f3b0d61278b5ab9dee68321494351 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 10 Aug 2017 14:39:52 -0400 Subject: drm/amdgpu/cik: add IP modules for DC for APUs Enable DC for DCE8 APUs. Signed-off-by: Alex Deucher Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/cik.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/cik.c b/drivers/gpu/drm/amd/amdgpu/cik.c index af3b66f6f47c..793b1470284d 100644 --- a/drivers/gpu/drm/amd/amdgpu/cik.c +++ b/drivers/gpu/drm/amd/amdgpu/cik.c @@ -1937,6 +1937,10 @@ int cik_set_ip_blocks(struct amdgpu_device *adev) amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block); if (adev->enable_virtual_display) amdgpu_ip_block_add(adev, &dce_virtual_ip_block); +#if defined(CONFIG_DRM_AMD_DC) + else if (amdgpu_device_has_dc_support(adev)) + amdgpu_ip_block_add(adev, &dm_ip_block); +#endif else amdgpu_ip_block_add(adev, &dce_v8_1_ip_block); amdgpu_ip_block_add(adev, &gfx_v7_1_ip_block); @@ -1952,6 +1956,10 @@ int cik_set_ip_blocks(struct amdgpu_device *adev) amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block); if (adev->enable_virtual_display) amdgpu_ip_block_add(adev, &dce_virtual_ip_block); +#if defined(CONFIG_DRM_AMD_DC) + else if (amdgpu_device_has_dc_support(adev)) + amdgpu_ip_block_add(adev, &dm_ip_block); +#endif else amdgpu_ip_block_add(adev, &dce_v8_3_ip_block); amdgpu_ip_block_add(adev, &gfx_v7_2_ip_block); -- cgit From 153ae53232d7d885b532d1aa7fa7ad156834a366 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 10 Aug 2017 15:20:00 -0400 Subject: drm/amd/display: Add a TODO list Signed-off-by: Harry Wentland Reviewed-by: Jordan Lazare Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/TODO | 81 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 drivers/gpu/drm/amd/display/TODO (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/TODO b/drivers/gpu/drm/amd/display/TODO new file mode 100644 index 000000000000..2737873db12d --- /dev/null +++ b/drivers/gpu/drm/amd/display/TODO @@ -0,0 +1,81 @@ +=============================================================================== +TODOs +=============================================================================== + +1. Base this on drm-next - WIP + + +2. Cleanup commit history + + +3. WIP - Drop page flip helper and use DRM's version + + +4. DONE - Flatten all DC objects + * dc_stream/core_stream/stream should just be dc_stream + * Same for other DC objects + + "Is there any major reason to keep all those abstractions? + + Could you collapse everything into struct dc_stream? + + I haven't looked recently but I didn't get the impression there was a + lot of design around what was public/protected, more whatever needed + to be used by someone else was in public." + ~ Dave Airlie + + +5. DONE - Rename DC objects to align more with DRM + * dc_surface -> dc_plane_state + * dc_stream -> dc_stream_state + + +6. DONE - Per-plane and per-stream validation + + +7. WIP - Per-plane and per-stream commit + + +8. WIP - Split pipe_ctx into plane and stream resource structs + + +9. Attach plane and stream reources to state object instead of validate_context + + +10. Remove dc_edid_caps and drm_helpers_parse_edid_caps + * Use drm_display_info instead + * Remove DC's edid quirks and rely on DRM's quirks (add quirks if needed) + + "Making sure you use the sink-specific helper libraries and kernel + subsystems, since there's really no good reason to have 2nd + implementation of those in the kernel. Looks likes that's done for mst + and edid parsing. There's still a bit a midlayer feeling to the edid + parsing side (e.g. dc_edid_caps and dm_helpers_parse_edid_caps, I + think it'd be much better if you convert that over to reading stuff + from drm_display_info and if needed, push stuff into the core). Also, + I can't come up with a good reason why DC needs all this (except to + reimplement half of our edid quirk table, which really isn't a good + idea). Might be good if you put this onto the list of things to fix + long-term, but imo not a blocker. Definitely make sure new stuff + doesn't slip in (i.e. if you start adding edid quirks to DC instead of + the drm core, refactoring to use the core edid stuff was pointless)." + ~ Daniel Vetter + + +11. Remove existing i2c implementation from DC + + "Similar story for i2c, it uses the kernel's i2c code now, but there's + still a full i2c implementation hidden beneath that in + display/dc/i2caux. Kinda not cool, but imo ok if you fix that + post-merging (perhaps by not including any of this in the linux DC + code in the upstream kernel, but as an aux module in your internal + codebase since there you probably need that, same applies to the edid + parsing DC still does. For both cases I assume that the minimal shim + you need on linux (bit banging and edid parsing isn't rocket since) is + a lot less than the glue code to interface with the dc-provided + abstraction." + ~ Daniel Vetter + + +12. drm_modeset_lock in MST should no longer be needed in recent kernels + * Adopt appropriate locking scheme -- cgit From 17b7cf8c556601eea56b38582fd74945a712cd93 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 23 Aug 2017 09:42:22 -0400 Subject: drm/amdgpu: disable DC on KB/ML for now Until I've had time to test it better. bug: https://bugs.freedesktop.org/show_bug.cgi?id=102372 Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 99f91e52db10..add0032977f3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1981,8 +1981,6 @@ bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type) case CHIP_BONAIRE: case CHIP_HAWAII: case CHIP_KAVERI: - case CHIP_KABINI: - case CHIP_MULLINS: case CHIP_CARRIZO: case CHIP_STONEY: case CHIP_POLARIS11: @@ -1993,9 +1991,10 @@ bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type) case CHIP_VEGA10: #if defined(CONFIG_DRM_AMD_DC_PRE_VEGA) return amdgpu_dc != 0; -#else - return amdgpu_dc > 0; #endif + case CHIP_KABINI: + case CHIP_MULLINS: + return amdgpu_dc > 0; #endif #if defined(CONFIG_DRM_AMD_DC) && defined(CONFIG_DRM_AMD_DC_DCN1_0) case CHIP_RAVEN: -- cgit From f81483c4ccca0d2ceca14ee15564a14f2c34eb2c Mon Sep 17 00:00:00 2001 From: Roman Li Date: Thu, 10 Aug 2017 16:11:10 -0400 Subject: drm/amd/display: fix gamma distortion on Vega Added missing reg shift/masks to soc base Signed-off-by: Roman Li Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_transform.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h index f9622ff54560..d87225d15cd9 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h @@ -237,6 +237,7 @@ XFM_SF(DCP0_REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, mask_sh),\ XFM_SF(DCP0_REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, mask_sh),\ XFM_SF(DCP0_REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, mask_sh),\ + XFM_SF(DCP0_REGAMMA_CONTROL, GRPH_REGAMMA_MODE, mask_sh),\ XFM_SF(SCL0_SCL_MODE, SCL_MODE, mask_sh), \ XFM_SF(SCL0_SCL_TAP_CONTROL, SCL_H_NUM_OF_TAPS, mask_sh), \ XFM_SF(SCL0_SCL_TAP_CONTROL, SCL_V_NUM_OF_TAPS, mask_sh), \ @@ -270,6 +271,8 @@ XFM_SF(SCL0_SCL_UPDATE, SCL_COEF_UPDATE_COMPLETE, mask_sh), \ XFM_SF(LB0_LB_DATA_FORMAT, ALPHA_EN, mask_sh), \ XFM_SF(DCFE0_DCFE_MEM_PWR_CTRL, SCL_COEFF_MEM_PWR_DIS, mask_sh), \ + XFM_SF(DCFE0_DCFE_MEM_PWR_CTRL, DCP_REGAMMA_MEM_PWR_DIS, mask_sh),\ + XFM_SF(DCFE0_DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, mask_sh),\ XFM_SF(DCFE0_DCFE_MEM_PWR_STATUS, SCL_COEFF_MEM_PWR_STATE, mask_sh), \ XFM_SF(SCL0_SCL_MODE, SCL_PSCL_EN, mask_sh) -- cgit From e8cd26434df0cd8d97f31aeb4399afcdc37fcfda Mon Sep 17 00:00:00 2001 From: Jerry Zuo Date: Mon, 31 Jul 2017 17:10:44 -0400 Subject: drm/amd/display: Use atomic types for ref_count Current ref_count inc/dec is not guarded by locks which leads to a raced condition where two threads try to access the variable at the same time. In this case, both might act on the same cached value and inc/dec from the same value, rather than inc/dec by 2. Signed-off-by: Jerry Zuo Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 24 +++++++-------- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_sink.c | 12 ++++---- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 14 ++++----- drivers/gpu/drm/amd/display/dc/core/dc_surface.c | 36 +++++++++++------------ drivers/gpu/drm/amd/display/dc/dc.h | 8 ++--- drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 2 +- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 2 +- 8 files changed, 49 insertions(+), 51 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index b69a726717d9..8efdd05841e1 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -454,7 +454,7 @@ static bool construct(struct core_dc *dc, goto val_ctx_fail; } - dc->current_context->ref_count++; + atomic_inc(&dc->current_context->ref_count); dc_ctx->cgs_device = init_params->cgs_device; dc_ctx->driver_context = init_params->driver; @@ -704,7 +704,7 @@ struct validate_context *dc_get_validate_context( if (context == NULL) goto context_alloc_fail; - ++context->ref_count; + atomic_inc(&context->ref_count); if (!is_validation_required(core_dc, set, set_count)) { dc_resource_validate_ctx_copy_construct(core_dc->current_context, context); @@ -748,7 +748,7 @@ bool dc_validate_resources( if (context == NULL) goto context_alloc_fail; - ++context->ref_count; + atomic_inc(&context->ref_count); result = core_dc->res_pool->funcs->validate_with_context( core_dc, set, set_count, context, NULL); @@ -782,7 +782,7 @@ bool dc_validate_guaranteed( if (context == NULL) goto context_alloc_fail; - ++context->ref_count; + atomic_inc(&context->ref_count); result = core_dc->res_pool->funcs->validate_guaranteed( core_dc, stream, context); @@ -1090,7 +1090,7 @@ bool dc_commit_streams( if (context == NULL) goto context_alloc_fail; - ++context->ref_count; + atomic_inc(&context->ref_count); result = core_dc->res_pool->funcs->validate_with_context( core_dc, set, stream_count, context, core_dc->current_context); @@ -1203,16 +1203,16 @@ bool dc_commit_planes_to_stream( void dc_retain_validate_context(struct validate_context *context) { - ASSERT(context->ref_count > 0); - ++context->ref_count; + ASSERT(atomic_read(&context->ref_count) > 0); + atomic_inc(&context->ref_count); } void dc_release_validate_context(struct validate_context *context) { - ASSERT(context->ref_count > 0); - --context->ref_count; + ASSERT(atomic_read(&context->ref_count) > 0); + atomic_dec(&context->ref_count); - if (context->ref_count == 0) { + if (atomic_read(&context->ref_count) == 0) { dc_resource_validate_ctx_destruct(context); dm_free(context); } @@ -1485,7 +1485,7 @@ void dc_update_planes_and_stream(struct dc *dc, if (context == NULL) goto context_alloc_fail; - ++context->ref_count; + atomic_inc(&context->ref_count); dc_resource_validate_ctx_copy_construct( core_dc->current_context, context); @@ -1800,7 +1800,7 @@ void dc_set_power_state( enum dc_acpi_cm_power_state power_state) { struct core_dc *core_dc = DC_TO_CORE(dc); - int ref_count; + atomic_t ref_count; switch (power_state) { case DC_ACPI_CM_POWER_STATE_D0: diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 56a85c80131d..1d69bd25e07b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -2238,7 +2238,7 @@ void dc_resource_validate_ctx_copy_construct( struct validate_context *dst_ctx) { int i, j; - int ref_count = dst_ctx->ref_count; + atomic_t ref_count = dst_ctx->ref_count; *dst_ctx = *src_ctx; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_sink.c b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c index a83f1243a9d1..7717350297a5 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_sink.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c @@ -63,16 +63,16 @@ static bool construct(struct dc_sink *sink, const struct dc_sink_init_data *init void dc_sink_retain(struct dc_sink *sink) { - ASSERT(sink->ref_count > 0); - ++sink->ref_count; + ASSERT(atomic_read(&sink->ref_count) > 0); + atomic_inc(&sink->ref_count); } void dc_sink_release(struct dc_sink *sink) { - ASSERT(sink->ref_count > 0); - --sink->ref_count; + ASSERT(atomic_read(&sink->ref_count) > 0); + atomic_dec(&sink->ref_count); - if (sink->ref_count == 0) { + if (atomic_read(&sink->ref_count) == 0) { destruct(sink); dm_free(sink); } @@ -88,7 +88,7 @@ struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params) if (false == construct(sink, init_params)) goto construct_fail; - ++sink->ref_count; + atomic_inc(&sink->ref_count); return sink; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 2de37fed12a5..47e407dab4a3 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -96,19 +96,17 @@ static void destruct(struct dc_stream_state *stream) void dc_stream_retain(struct dc_stream_state *stream) { - - ASSERT(stream->ref_count > 0); - stream->ref_count++; + ASSERT(atomic_read(&stream->ref_count) > 0); + atomic_inc(&stream->ref_count); } void dc_stream_release(struct dc_stream_state *stream) { - if (stream != NULL) { - ASSERT(stream->ref_count > 0); - stream->ref_count--; + ASSERT(atomic_read(&stream->ref_count) > 0); + atomic_dec(&stream->ref_count); - if (stream->ref_count == 0) { + if (atomic_read(&stream->ref_count) == 0) { destruct(stream); dm_free(stream); } @@ -131,7 +129,7 @@ struct dc_stream_state *dc_create_stream_for_sink( if (false == construct(stream, sink)) goto construct_fail; - stream->ref_count++; + atomic_inc(&stream->ref_count); return stream; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index 3bcca2d1872b..da19c7fa5151 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -76,7 +76,7 @@ struct dc_plane_state *dc_create_plane_state(const struct dc *dc) if (false == construct(core_dc->ctx, plane_state)) goto construct_fail; - ++plane_state->ref_count; + atomic_inc(&plane_state->ref_count); return plane_state; @@ -122,16 +122,16 @@ const struct dc_plane_status *dc_plane_get_status( void dc_plane_state_retain(struct dc_plane_state *plane_state) { - ASSERT(plane_state->ref_count > 0); - ++plane_state->ref_count; + ASSERT(atomic_read(&plane_state->ref_count) > 0); + atomic_inc(&plane_state->ref_count); } void dc_plane_state_release(struct dc_plane_state *plane_state) { - ASSERT(plane_state->ref_count > 0); - --plane_state->ref_count; + ASSERT(atomic_read(&plane_state->ref_count) > 0); + atomic_dec(&plane_state->ref_count); - if (plane_state->ref_count == 0) { + if (atomic_read(&plane_state->ref_count) == 0) { destruct(plane_state); dm_free(plane_state); } @@ -139,16 +139,16 @@ void dc_plane_state_release(struct dc_plane_state *plane_state) void dc_gamma_retain(struct dc_gamma *gamma) { - ASSERT(gamma->ref_count > 0); - ++gamma->ref_count; + ASSERT(atomic_read(&gamma->ref_count) > 0); + atomic_inc(&gamma->ref_count); } void dc_gamma_release(struct dc_gamma **gamma) { - ASSERT((*gamma)->ref_count > 0); - --(*gamma)->ref_count; + ASSERT(atomic_read(&(*gamma)->ref_count) > 0); + atomic_dec(&(*gamma)->ref_count); - if ((*gamma)->ref_count == 0) + if (atomic_read(&(*gamma)->ref_count) == 0) dm_free((*gamma)); *gamma = NULL; @@ -161,7 +161,7 @@ struct dc_gamma *dc_create_gamma() if (gamma == NULL) goto alloc_fail; - ++gamma->ref_count; + atomic_inc(&gamma->ref_count); return gamma; @@ -171,16 +171,16 @@ alloc_fail: void dc_transfer_func_retain(struct dc_transfer_func *tf) { - ASSERT(tf->ref_count > 0); - ++tf->ref_count; + ASSERT(atomic_read(&tf->ref_count) > 0); + atomic_inc(&tf->ref_count); } void dc_transfer_func_release(struct dc_transfer_func *tf) { - ASSERT(tf->ref_count > 0); - --tf->ref_count; + ASSERT(atomic_read(&tf->ref_count) > 0); + atomic_dec(&tf->ref_count); - if (tf->ref_count == 0) + if (atomic_read(&tf->ref_count) == 0) dm_free(tf); } @@ -191,7 +191,7 @@ struct dc_transfer_func *dc_create_transfer_func() if (tf == NULL) goto alloc_fail; - ++tf->ref_count; + atomic_inc(&tf->ref_count); return tf; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index cac92bf91e4a..4e60adb981e1 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -295,7 +295,7 @@ struct dc_transfer_func { enum dc_transfer_func_type type; enum dc_transfer_func_predefined tf; struct dc_context *ctx; - int ref_count; + atomic_t ref_count; }; /* @@ -342,7 +342,7 @@ struct dc_plane_state { /* private to dc_surface.c */ enum dc_irq_source irq_source; - int ref_count; + atomic_t ref_count; }; struct dc_plane_info { @@ -518,7 +518,7 @@ struct dc_stream_state { struct dc_stream_status status; /* from stream struct */ - int ref_count; + atomic_t ref_count; }; struct dc_stream_update { @@ -902,7 +902,7 @@ struct dc_sink { struct dc_context *ctx; /* private to dc_sink.c */ - int ref_count; + atomic_t ref_count; }; void dc_sink_retain(struct dc_sink *sink); diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index 8d1504668ec7..94f83cd9ab32 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -433,7 +433,7 @@ struct dc_gamma { struct dc_context *ctx; /* private to dc_surface.c */ - int ref_count; + atomic_t ref_count; }; /* Used by both ipp amd opp functions*/ diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index b3005629ab21..5190901ea379 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -260,7 +260,7 @@ struct validate_context { struct dcn_bw_internal_vars dcn_bw_vars; #endif - int ref_count; + atomic_t ref_count; }; #endif /* _CORE_TYPES_H_ */ -- cgit From 391e20d84104a6b7b9d4a66fec6a7eb0a93f6ef4 Mon Sep 17 00:00:00 2001 From: Duke Du Date: Thu, 3 Aug 2017 10:20:52 -0400 Subject: drm/amd/display: add display write back(DWB) Signed-off-by: Duke Du Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 10 + drivers/gpu/drm/amd/display/dc/dc.h | 2 + .../gpu/drm/amd/display/dc/dce/dce_clock_source.c | 87 ++- .../gpu/drm/amd/display/dc/dce/dce_clock_source.h | 8 + drivers/gpu/drm/amd/display/dc/dcn10/Makefile | 2 +- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c | 652 +++++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.h | 32 + .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 9 + drivers/gpu/drm/amd/display/dc/inc/clock_source.h | 4 + drivers/gpu/drm/amd/display/dc/inc/core_types.h | 6 + drivers/gpu/drm/amd/display/dc/inc/hw/dwb.h | 193 ++++++ 11 files changed, 1003 insertions(+), 2 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw/dwb.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 8efdd05841e1..aeed95a5d097 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1749,6 +1749,16 @@ struct dc_link *dc_get_link_at_index(const struct dc *dc, uint32_t link_index) return core_dc->links[link_index]; } +struct dwbc *dc_get_dwb_at_pipe(const struct dc *dc, uint32_t pipe) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + if ((pipe >= dwb_pipe0) && (pipe < dwb_pipe_max_num)) { + return core_dc->res_pool->dwbc[(int)pipe]; + } else { + return NULL; + } +} + const struct graphics_object_id dc_get_link_id_at_index( struct dc *dc, uint32_t link_index) { diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 4e60adb981e1..e62d15d90fdb 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -797,6 +797,8 @@ const struct dc_link_status *dc_link_get_status(const struct dc_link *dc_link); */ struct dc_link *dc_get_link_at_index(const struct dc *dc, uint32_t link_index); +struct dwbc *dc_get_dwb_at_pipe(const struct dc *dc, uint32_t pipe); + /* Return id of physical connector represented by a dc_link at link_index.*/ const struct graphics_object_id dc_get_link_id_at_index( struct dc *dc, uint32_t link_index); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index 88e266ac6dd3..cc707bd615dc 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -34,6 +34,7 @@ #include "dce_clock_source.h" +#include "core_dc.h" #include "reg_helper.h" #define REG(reg)\ @@ -602,6 +603,89 @@ static uint32_t dce110_get_pix_clk_dividers( return pll_calc_error; } +static uint32_t dce110_get_pll_pixel_rate_in_hz( + struct clock_source *cs, + struct pixel_clk_params *pix_clk_params, + struct pll_settings *pll_settings) +{ + uint32_t inst = pix_clk_params->controller_id - CONTROLLER_ID_D0; + struct core_dc *dc_core = DC_TO_CORE(cs->ctx->dc); + struct validate_context *context = dc_core->current_context; + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[inst]; + + /* This function need separate to different DCE version, before separate, just use pixel clock */ + return pipe_ctx->stream->phy_pix_clk; +} + +static uint32_t dce110_get_dp_pixel_rate_from_combo_phy_pll( + struct clock_source *cs, + struct pixel_clk_params *pix_clk_params, + struct pll_settings *pll_settings) +{ + uint32_t inst = pix_clk_params->controller_id - CONTROLLER_ID_D0; + struct core_dc *dc_core = DC_TO_CORE(cs->ctx->dc); + struct validate_context *context = dc_core->current_context; + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[inst]; + + /* This function need separate to different DCE version, before separate, just use pixel clock */ + return pipe_ctx->stream->phy_pix_clk; +} + +static uint32_t dce110_get_d_to_pixel_rate_in_hz( + struct clock_source *cs, + struct pixel_clk_params *pix_clk_params, + struct pll_settings *pll_settings) +{ + uint32_t inst = pix_clk_params->controller_id - CONTROLLER_ID_D0; + struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(cs); + int dto_enabled = 0; + struct fixed31_32 pix_rate; + + REG_GET(PIXEL_RATE_CNTL[inst], DP_DTO0_ENABLE, &dto_enabled); + + if (dto_enabled) { + uint32_t phase = 0; + uint32_t modulo = 0; + REG_GET(PHASE[inst], DP_DTO0_PHASE, &phase); + REG_GET(MODULO[inst], DP_DTO0_MODULO, &modulo); + + if (modulo == 0) { + return 0; + } + + pix_rate = dal_fixed31_32_from_int(clk_src->ref_freq_khz); + pix_rate = dal_fixed31_32_mul_int(pix_rate, 1000); + pix_rate = dal_fixed31_32_mul_int(pix_rate, phase); + pix_rate = dal_fixed31_32_div_int(pix_rate, modulo); + + return dal_fixed31_32_round(pix_rate); + } else { + return dce110_get_dp_pixel_rate_from_combo_phy_pll(cs, pix_clk_params, pll_settings); + } +} + +static uint32_t dce110_get_pix_rate_in_hz( + struct clock_source *cs, + struct pixel_clk_params *pix_clk_params, + struct pll_settings *pll_settings) +{ + uint32_t pix_rate = 0; + switch (pix_clk_params->signal_type) { + case SIGNAL_TYPE_DISPLAY_PORT: + case SIGNAL_TYPE_DISPLAY_PORT_MST: + case SIGNAL_TYPE_EDP: + case SIGNAL_TYPE_VIRTUAL: + pix_rate = dce110_get_d_to_pixel_rate_in_hz(cs, pix_clk_params, pll_settings); + break; + case SIGNAL_TYPE_HDMI_TYPE_A: + default: + pix_rate = dce110_get_pll_pixel_rate_in_hz(cs, pix_clk_params, pll_settings); + break; + } + + return pix_rate; +} + static bool disable_spread_spectrum(struct dce110_clk_src *clk_src) { enum bp_result result; @@ -962,7 +1046,8 @@ static bool dce110_clock_source_power_down( static const struct clock_source_funcs dce110_clk_src_funcs = { .cs_power_down = dce110_clock_source_power_down, .program_pix_clk = dce110_program_pix_clk, - .get_pix_clk_dividers = dce110_get_pix_clk_dividers + .get_pix_clk_dividers = dce110_get_pix_clk_dividers, + .get_pix_rate_in_hz = dce110_get_pix_rate_in_hz }; static void get_ss_info_from_atombios( diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h index fc923886e3d4..238c03f14959 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h @@ -55,6 +55,8 @@ CS_SF(PHYPLLA_PIXCLK_RESYNC_CNTL, PHYPLLA_DCCG_DEEP_COLOR_CNTL, mask_sh),\ CS_SF(PHYPLLA_PIXCLK_RESYNC_CNTL, PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE, mask_sh) +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + #define CS_COMMON_REG_LIST_DCN1_0(index, pllid) \ SRI(PIXCLK_RESYNC_CNTL, PHYPLL, pllid),\ SRII(PHASE, DP_DTO, 0),\ @@ -71,9 +73,13 @@ SRII(PIXEL_RATE_CNTL, OTG, 3) #define CS_COMMON_MASK_SH_LIST_DCN1_0(mask_sh)\ + CS_SF(DP_DTO0_PHASE, DP_DTO0_PHASE, mask_sh),\ + CS_SF(DP_DTO0_MODULO, DP_DTO0_MODULO, mask_sh),\ CS_SF(PHYPLLA_PIXCLK_RESYNC_CNTL, PHYPLLA_DCCG_DEEP_COLOR_CNTL, mask_sh),\ CS_SF(OTG0_PIXEL_RATE_CNTL, DP_DTO0_ENABLE, mask_sh) +#endif + #define CS_REG_FIELD_LIST(type) \ type PLL_REF_DIV_SRC; \ type DCCG_DEEP_COLOR_CNTL1; \ @@ -81,6 +87,8 @@ type PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE; \ type PLL_POST_DIV_PIXCLK; \ type PLL_REF_DIV; \ + type DP_DTO0_PHASE; \ + type DP_DTO0_MODULO; \ type DP_DTO0_ENABLE; struct dce110_clk_src_shift { diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile index 9ba1bfc30146..8af201a51a2a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile @@ -3,7 +3,7 @@ DCN10 = dcn10_resource.o dcn10_ipp.o dcn10_hw_sequencer.o \ dcn10_dpp.o dcn10_opp.o dcn10_timing_generator.o \ - dcn10_mem_input.o dcn10_mpc.o + dcn10_mem_input.o dcn10_mpc.o dcn10_dwb.o AMD_DAL_DCN10 = $(addprefix $(AMDDALPATH)/dc/dcn10/,$(DCN10)) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c new file mode 100644 index 000000000000..11386121f8ed --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c @@ -0,0 +1,652 @@ +/* + * Copyright 2012-17 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + +#include "reg_helper.h" +#include "core_dc.h" +#include "resource.h" +#include "dwb.h" +#include "dcn10_dwb.h" +#include "vega10/soc15ip.h" +#include "raven1/DCN/dcn_1_0_offset.h" +#include "raven1/DCN/dcn_1_0_sh_mask.h" + +/* DCN */ +#define BASE_INNER(seg) \ + DCE_BASE__INST0_SEG ## seg + +#define BASE(seg) \ + BASE_INNER(seg) + +#define SR(reg_name)\ + .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + \ + mm ## reg_name + +#define SRI(reg_name, block, id)\ + .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + + +#define SRII(reg_name, block, id)\ + .reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +#define SF(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define REG(reg)\ + dwbc10->dwbc_regs->reg + +#define CTX \ + dwbc10->base.ctx + +#undef FN +#define FN(reg_name, field_name) \ + dwbc10->dwbc_shift->field_name, dwbc10->dwbc_mask->field_name + +#define TO_DCN10_DWBC(dwbc_base) \ + container_of(dwbc_base, struct dcn10_dwbc, base) + +#define DWBC_COMMON_REG_LIST_DCN1_0(inst) \ + SRI(WB_ENABLE, CNV, inst),\ + SRI(WB_EC_CONFIG, CNV, inst),\ + SRI(CNV_MODE, CNV, inst),\ + SRI(WB_SOFT_RESET, CNV, inst),\ + SRI(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_PITCH, MCIF_WB, inst),\ + SRI(MCIF_WB_ARBITRATION_CONTROL, MCIF_WB, inst),\ + SRI(MCIF_WB_SCLK_CHANGE, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_1_ADDR_Y, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_1_ADDR_Y_OFFSET, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_1_ADDR_C, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_1_ADDR_C_OFFSET, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_2_ADDR_Y, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_2_ADDR_Y_OFFSET, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_2_ADDR_C, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_2_ADDR_C_OFFSET, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_3_ADDR_Y, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_3_ADDR_Y_OFFSET, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_3_ADDR_C, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_3_ADDR_C_OFFSET, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_4_ADDR_Y, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_4_ADDR_Y_OFFSET, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_4_ADDR_C, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_4_ADDR_C_OFFSET, MCIF_WB, inst),\ + SRI(MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB, inst),\ + SRI(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, MCIF_WB, inst),\ + SRI(MCIF_WB_NB_PSTATE_CONTROL, MCIF_WB, inst),\ + SRI(MCIF_WB_WATERMARK, MCIF_WB, inst),\ + SRI(MCIF_WB_WARM_UP_CNTL, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_LUMA_SIZE, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_CHROMA_SIZE, MCIF_WB, inst),\ + .DWB_SOURCE_SELECT = mmDWB_SOURCE_SELECT\ + +#define DWBC_COMMON_MASK_SH_LIST_DCN1_0(mask_sh) \ + SF(CNV0_WB_ENABLE, WB_ENABLE, mask_sh),\ + SF(CNV0_WB_EC_CONFIG, DISPCLK_R_WB_GATE_DIS, mask_sh),\ + SF(CNV0_WB_EC_CONFIG, DISPCLK_G_WB_GATE_DIS, mask_sh),\ + SF(CNV0_WB_EC_CONFIG, DISPCLK_G_WBSCL_GATE_DIS, mask_sh),\ + SF(CNV0_WB_EC_CONFIG, WB_LB_LS_DIS, mask_sh),\ + SF(CNV0_WB_EC_CONFIG, WB_LUT_LS_DIS, mask_sh),\ + SF(CNV0_CNV_MODE, CNV_WINDOW_CROP_EN, mask_sh),\ + SF(CNV0_CNV_MODE, CNV_STEREO_TYPE, mask_sh),\ + SF(CNV0_CNV_MODE, CNV_INTERLACED_MODE, mask_sh),\ + SF(CNV0_CNV_MODE, CNV_EYE_SELECTION, mask_sh),\ + SF(CNV0_CNV_MODE, CNV_STEREO_POLARITY, mask_sh),\ + SF(CNV0_CNV_MODE, CNV_INTERLACED_FIELD_ORDER, mask_sh),\ + SF(CNV0_CNV_MODE, CNV_STEREO_SPLIT, mask_sh),\ + SF(CNV0_CNV_MODE, CNV_NEW_CONTENT, mask_sh),\ + SF(CNV0_CNV_MODE, CNV_FRAME_CAPTURE_EN, mask_sh),\ + SF(CNV0_WB_SOFT_RESET, WB_SOFT_RESET, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_ENABLE, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUF_DUALSIZE_REQ, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_INT_EN, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_INT_ACK, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_SLICE_INT_EN, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_OVERRUN_INT_EN, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_LOCK, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_P_VMID, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUF_ADDR_FENCE_EN, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_PITCH, MCIF_WB_BUF_LUMA_PITCH, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_PITCH, MCIF_WB_BUF_CHROMA_PITCH, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_ARBITRATION_CONTROL, MCIF_WB_CLIENT_ARBITRATION_SLICE, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_ARBITRATION_CONTROL, MCIF_WB_TIME_PER_PIXEL, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_SCLK_CHANGE, WM_CHANGE_ACK_FORCE_ON, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_SCLK_CHANGE, MCIF_WB_CLI_WATERMARK_MASK, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_1_ADDR_Y, MCIF_WB_BUF_1_ADDR_Y, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_1_ADDR_Y_OFFSET, MCIF_WB_BUF_1_ADDR_Y_OFFSET, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_1_ADDR_C, MCIF_WB_BUF_1_ADDR_C, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_1_ADDR_C_OFFSET, MCIF_WB_BUF_1_ADDR_C_OFFSET, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_2_ADDR_Y, MCIF_WB_BUF_2_ADDR_Y, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_2_ADDR_Y_OFFSET, MCIF_WB_BUF_2_ADDR_Y_OFFSET, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_2_ADDR_C, MCIF_WB_BUF_2_ADDR_C, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_2_ADDR_C_OFFSET, MCIF_WB_BUF_2_ADDR_C_OFFSET, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_3_ADDR_Y, MCIF_WB_BUF_3_ADDR_Y, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_3_ADDR_Y_OFFSET, MCIF_WB_BUF_3_ADDR_Y_OFFSET, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_3_ADDR_C, MCIF_WB_BUF_3_ADDR_C, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_3_ADDR_C_OFFSET, MCIF_WB_BUF_3_ADDR_C_OFFSET, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_4_ADDR_Y, MCIF_WB_BUF_4_ADDR_Y, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_4_ADDR_Y_OFFSET, MCIF_WB_BUF_4_ADDR_Y_OFFSET, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_4_ADDR_C, MCIF_WB_BUF_4_ADDR_C, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_4_ADDR_C_OFFSET, MCIF_WB_BUF_4_ADDR_C_OFFSET, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_LOCK_IGNORE, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_INT_EN, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_INT_ACK, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_SLICE_INT_EN, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_LOCK, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_SLICE_SIZE, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, NB_PSTATE_CHANGE_REFRESH_WATERMARK, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_CHANGE_URGENT_DURING_REQUEST, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_CHANGE_FORCE_ON, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_ALLOW_FOR_URGENT, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_CHANGE_WATERMARK_MASK, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_WATERMARK, MCIF_WB_CLI_WATERMARK, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_WARM_UP_CNTL, MCIF_WB_PITCH_SIZE_WARMUP, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_LUMA_SIZE, MCIF_WB_BUF_LUMA_SIZE, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_CHROMA_SIZE, MCIF_WB_BUF_CHROMA_SIZE, mask_sh),\ + SF(DWB_SOURCE_SELECT, OPTC_DWB0_SOURCE_SELECT, mask_sh),\ + SF(DWB_SOURCE_SELECT, OPTC_DWB1_SOURCE_SELECT, mask_sh) + +#define DWBC_REG_FIELD_LIST(type) \ + type WB_ENABLE;\ + type DISPCLK_R_WB_GATE_DIS;\ + type DISPCLK_G_WB_GATE_DIS;\ + type DISPCLK_G_WBSCL_GATE_DIS;\ + type WB_LB_LS_DIS;\ + type WB_LB_SD_DIS;\ + type WB_LUT_LS_DIS;\ + type CNV_WINDOW_CROP_EN;\ + type CNV_STEREO_TYPE;\ + type CNV_INTERLACED_MODE;\ + type CNV_EYE_SELECTION;\ + type CNV_STEREO_POLARITY;\ + type CNV_INTERLACED_FIELD_ORDER;\ + type CNV_STEREO_SPLIT;\ + type CNV_NEW_CONTENT;\ + type CNV_FRAME_CAPTURE_EN;\ + type WB_SOFT_RESET;\ + type MCIF_WB_BUFMGR_ENABLE;\ + type MCIF_WB_BUF_DUALSIZE_REQ;\ + type MCIF_WB_BUFMGR_SW_INT_EN;\ + type MCIF_WB_BUFMGR_SW_INT_ACK;\ + type MCIF_WB_BUFMGR_SW_SLICE_INT_EN;\ + type MCIF_WB_BUFMGR_SW_OVERRUN_INT_EN;\ + type MCIF_WB_BUFMGR_SW_LOCK;\ + type MCIF_WB_P_VMID;\ + type MCIF_WB_BUF_ADDR_FENCE_EN;\ + type MCIF_WB_BUF_LUMA_PITCH;\ + type MCIF_WB_BUF_CHROMA_PITCH;\ + type MCIF_WB_CLIENT_ARBITRATION_SLICE;\ + type MCIF_WB_TIME_PER_PIXEL;\ + type WM_CHANGE_ACK_FORCE_ON;\ + type MCIF_WB_CLI_WATERMARK_MASK;\ + type MCIF_WB_BUF_1_ADDR_Y;\ + type MCIF_WB_BUF_1_ADDR_Y_OFFSET;\ + type MCIF_WB_BUF_1_ADDR_C;\ + type MCIF_WB_BUF_1_ADDR_C_OFFSET;\ + type MCIF_WB_BUF_2_ADDR_Y;\ + type MCIF_WB_BUF_2_ADDR_Y_OFFSET;\ + type MCIF_WB_BUF_2_ADDR_C;\ + type MCIF_WB_BUF_2_ADDR_C_OFFSET;\ + type MCIF_WB_BUF_3_ADDR_Y;\ + type MCIF_WB_BUF_3_ADDR_Y_OFFSET;\ + type MCIF_WB_BUF_3_ADDR_C;\ + type MCIF_WB_BUF_3_ADDR_C_OFFSET;\ + type MCIF_WB_BUF_4_ADDR_Y;\ + type MCIF_WB_BUF_4_ADDR_Y_OFFSET;\ + type MCIF_WB_BUF_4_ADDR_C;\ + type MCIF_WB_BUF_4_ADDR_C_OFFSET;\ + type MCIF_WB_BUFMGR_VCE_LOCK_IGNORE;\ + type MCIF_WB_BUFMGR_VCE_INT_EN;\ + type MCIF_WB_BUFMGR_VCE_INT_ACK;\ + type MCIF_WB_BUFMGR_VCE_SLICE_INT_EN;\ + type MCIF_WB_BUFMGR_VCE_LOCK;\ + type MCIF_WB_BUFMGR_SLICE_SIZE;\ + type NB_PSTATE_CHANGE_REFRESH_WATERMARK;\ + type NB_PSTATE_CHANGE_URGENT_DURING_REQUEST;\ + type NB_PSTATE_CHANGE_FORCE_ON;\ + type NB_PSTATE_ALLOW_FOR_URGENT;\ + type NB_PSTATE_CHANGE_WATERMARK_MASK;\ + type MCIF_WB_CLI_WATERMARK;\ + type MCIF_WB_CLI_CLOCK_GATER_OVERRIDE;\ + type MCIF_WB_PITCH_SIZE_WARMUP;\ + type MCIF_WB_BUF_LUMA_SIZE;\ + type MCIF_WB_BUF_CHROMA_SIZE;\ + type OPTC_DWB0_SOURCE_SELECT;\ + type OPTC_DWB1_SOURCE_SELECT;\ + +struct dcn10_dwbc_registers { + uint32_t WB_ENABLE; + uint32_t WB_EC_CONFIG; + uint32_t CNV_MODE; + uint32_t WB_SOFT_RESET; + uint32_t MCIF_WB_BUFMGR_SW_CONTROL; + uint32_t MCIF_WB_BUF_PITCH; + uint32_t MCIF_WB_ARBITRATION_CONTROL; + uint32_t MCIF_WB_SCLK_CHANGE; + uint32_t MCIF_WB_BUF_1_ADDR_Y; + uint32_t MCIF_WB_BUF_1_ADDR_Y_OFFSET; + uint32_t MCIF_WB_BUF_1_ADDR_C; + uint32_t MCIF_WB_BUF_1_ADDR_C_OFFSET; + uint32_t MCIF_WB_BUF_2_ADDR_Y; + uint32_t MCIF_WB_BUF_2_ADDR_Y_OFFSET; + uint32_t MCIF_WB_BUF_2_ADDR_C; + uint32_t MCIF_WB_BUF_2_ADDR_C_OFFSET; + uint32_t MCIF_WB_BUF_3_ADDR_Y; + uint32_t MCIF_WB_BUF_3_ADDR_Y_OFFSET; + uint32_t MCIF_WB_BUF_3_ADDR_C; + uint32_t MCIF_WB_BUF_3_ADDR_C_OFFSET; + uint32_t MCIF_WB_BUF_4_ADDR_Y; + uint32_t MCIF_WB_BUF_4_ADDR_Y_OFFSET; + uint32_t MCIF_WB_BUF_4_ADDR_C; + uint32_t MCIF_WB_BUF_4_ADDR_C_OFFSET; + uint32_t MCIF_WB_BUFMGR_VCE_CONTROL; + uint32_t MCIF_WB_NB_PSTATE_LATENCY_WATERMARK; + uint32_t MCIF_WB_NB_PSTATE_CONTROL; + uint32_t MCIF_WB_WATERMARK; + uint32_t MCIF_WB_WARM_UP_CNTL; + uint32_t MCIF_WB_BUF_LUMA_SIZE; + uint32_t MCIF_WB_BUF_CHROMA_SIZE; + uint32_t DWB_SOURCE_SELECT; +}; +struct dcn10_dwbc_mask { + DWBC_REG_FIELD_LIST(uint32_t) +}; +struct dcn10_dwbc_shift { + DWBC_REG_FIELD_LIST(uint8_t) +}; +struct dcn10_dwbc { + struct dwbc base; + const struct dcn10_dwbc_registers *dwbc_regs; + const struct dcn10_dwbc_shift *dwbc_shift; + const struct dcn10_dwbc_mask *dwbc_mask; +}; + +#define dwbc_regs(id)\ +[id] = {\ + DWBC_COMMON_REG_LIST_DCN1_0(id),\ +} + +static const struct dcn10_dwbc_registers dwbc10_regs[] = { + dwbc_regs(0), + dwbc_regs(1), +}; + +static const struct dcn10_dwbc_shift dwbc10_shift = { + DWBC_COMMON_MASK_SH_LIST_DCN1_0(__SHIFT) +}; + +static const struct dcn10_dwbc_mask dwbc10_mask = { + DWBC_COMMON_MASK_SH_LIST_DCN1_0(_MASK) +}; + + +static bool get_caps(struct dwbc *dwbc, struct dwb_caps *caps) +{ + if (caps) { + caps->adapter_id = 0; /* we only support 1 adapter currently */ + caps->hw_version = DCN_VERSION_1_0; + caps->num_pipes = 2; + memset(&caps->reserved, 0, sizeof(caps->reserved)); + memset(&caps->reserved2, 0, sizeof(caps->reserved2)); + caps->sw_version = dwb_ver_1_0; + caps->caps.support_dwb = true; + caps->caps.support_ogam = false; + caps->caps.support_wbscl = true; + caps->caps.support_ocsc = false; + return true; + } else { + return false; + } +} + +static bool enable(struct dwbc *dwbc) +{ + struct dcn10_dwbc *dwbc10 = TO_DCN10_DWBC(dwbc); + + /* disable first. */ + dwbc->funcs->disable(dwbc); + + /* disable power gating */ + REG_UPDATE_5(WB_EC_CONFIG, DISPCLK_R_WB_GATE_DIS, 1, + DISPCLK_G_WB_GATE_DIS, 1, DISPCLK_G_WBSCL_GATE_DIS, 1, + WB_LB_LS_DIS, 1, WB_LUT_LS_DIS, 1); + + REG_UPDATE(WB_ENABLE, WB_ENABLE, 1); + + /* lock buffer0~buffer3 */ + REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_LOCK, 0xf); + + /* buffer address for packing mode or Luma in planar mode */ + REG_UPDATE(MCIF_WB_BUF_1_ADDR_Y, MCIF_WB_BUF_1_ADDR_Y, (dwbc->config.basic_settings.luma_address[0] & 0xffffffff)); +/* REG_UPDATE(MCIF_WB_BUF_1_ADDR_Y_HIGH, MCIF_WB_BUF_1_ADDR_Y_HIGH, (dwbc->config.basic_settings.luma_address[0] >> 32)); */ + /* right eye sub-buffer address offset for packing mode or Luma in planar mode */ + REG_UPDATE(MCIF_WB_BUF_1_ADDR_Y_OFFSET, MCIF_WB_BUF_1_ADDR_Y_OFFSET, 0); + + /* buffer address for Chroma in planar mode (unused in packing mode) */ + REG_UPDATE(MCIF_WB_BUF_1_ADDR_C, MCIF_WB_BUF_1_ADDR_C, (dwbc->config.basic_settings.chroma_address[0] & 0xffffffff)); +/* REG_UPDATE(MCIF_WB_BUF_1_ADDR_C_HIGH, MCIF_WB_BUF_1_ADDR_C_HIGH, (dwbc->config.basic_settings.chroma_address[0] >> 32)); */ + /* right eye offset for packing mode or Luma in planar mode */ + REG_UPDATE(MCIF_WB_BUF_1_ADDR_C_OFFSET, MCIF_WB_BUF_1_ADDR_C_OFFSET, 0); + + /* buffer address for packing mode or Luma in planar mode */ + REG_UPDATE(MCIF_WB_BUF_2_ADDR_Y, MCIF_WB_BUF_2_ADDR_Y, (dwbc->config.basic_settings.luma_address[1] & 0xffffffff)); +/* REG_UPDATE(MCIF_WB_BUF_2_ADDR_Y_HIGH, MCIF_WB_BUF_2_ADDR_Y_HIGH, (dwbc->config.basic_settings.luma_address[1] >> 32)); */ + /* right eye sub-buffer address offset for packing mode or Luma in planar mode */ + REG_UPDATE(MCIF_WB_BUF_2_ADDR_Y_OFFSET, MCIF_WB_BUF_2_ADDR_Y_OFFSET, 0); + + /* buffer address for Chroma in planar mode (unused in packing mode) */ + REG_UPDATE(MCIF_WB_BUF_2_ADDR_C, MCIF_WB_BUF_2_ADDR_C, (dwbc->config.basic_settings.chroma_address[1] & 0xffffffff)); +/* REG_UPDATE(MCIF_WB_BUF_2_ADDR_C_HIGH, MCIF_WB_BUF_2_ADDR_C_HIGH, (dwbc->config.basic_settings.chroma_address[1] >> 32)); */ + /* right eye offset for packing mode or Luma in planar mode */ + REG_UPDATE(MCIF_WB_BUF_2_ADDR_C_OFFSET, MCIF_WB_BUF_2_ADDR_C_OFFSET, 0); + + /* buffer address for packing mode or Luma in planar mode */ + REG_UPDATE(MCIF_WB_BUF_3_ADDR_Y, MCIF_WB_BUF_3_ADDR_Y, (dwbc->config.basic_settings.luma_address[2] & 0xffffffff)); +/* REG_UPDATE(MCIF_WB_BUF_3_ADDR_Y_HIGH, MCIF_WB_BUF_3_ADDR_Y_HIGH, (dwbc->config.basic_settings.luma_address[2] >> 32)); */ + /* right eye sub-buffer address offset for packing mode or Luma in planar mode */ + REG_UPDATE(MCIF_WB_BUF_3_ADDR_Y_OFFSET, MCIF_WB_BUF_3_ADDR_Y_OFFSET, 0); + + /* buffer address for Chroma in planar mode (unused in packing mode) */ + REG_UPDATE(MCIF_WB_BUF_3_ADDR_C, MCIF_WB_BUF_3_ADDR_C, (dwbc->config.basic_settings.chroma_address[2] & 0xffffffff)); +/* REG_UPDATE(MCIF_WB_BUF_3_ADDR_C_HIGH, MCIF_WB_BUF_3_ADDR_C_HIGH, (dwbc->config.basic_settings.chroma_address[2] >> 32)); */ + /* right eye offset for packing mode or Luma in planar mode */ + REG_UPDATE(MCIF_WB_BUF_3_ADDR_C_OFFSET, MCIF_WB_BUF_3_ADDR_C_OFFSET, 0); + + /* buffer address for packing mode or Luma in planar mode */ + REG_UPDATE(MCIF_WB_BUF_4_ADDR_Y, MCIF_WB_BUF_4_ADDR_Y, (dwbc->config.basic_settings.luma_address[3] & 0xffffffff)); +/* REG_UPDATE(MCIF_WB_BUF_4_ADDR_Y_HIGH, MCIF_WB_BUF_4_ADDR_Y_HIGH, (dwbc->config.basic_settings.luma_address[3] >> 32)); */ + /* right eye sub-buffer address offset for packing mode or Luma in planar mode */ + REG_UPDATE(MCIF_WB_BUF_4_ADDR_Y_OFFSET, MCIF_WB_BUF_4_ADDR_Y_OFFSET, 0); + + /* buffer address for Chroma in planar mode (unused in packing mode) */ + REG_UPDATE(MCIF_WB_BUF_4_ADDR_C, MCIF_WB_BUF_4_ADDR_C, (dwbc->config.basic_settings.chroma_address[3] & 0xffffffff)); +/* REG_UPDATE(MCIF_WB_BUF_4_ADDR_C_HIGH, MCIF_WB_BUF_4_ADDR_C_HIGH, (dwbc->config.basic_settings.chroma_address[3] >> 32)); */ + /* right eye offset for packing mode or Luma in planar mode */ + REG_UPDATE(MCIF_WB_BUF_4_ADDR_C_OFFSET, MCIF_WB_BUF_4_ADDR_C_OFFSET, 0); + + /* setup luma & chroma size */ + REG_UPDATE(MCIF_WB_BUF_LUMA_SIZE, MCIF_WB_BUF_LUMA_SIZE, dwbc->config.basic_settings.luma_pitch * dwbc->config.basic_settings.dest_height); /* should be enough to contain a whole frame Luma data, same for stereo mode */ + REG_UPDATE(MCIF_WB_BUF_CHROMA_SIZE, MCIF_WB_BUF_CHROMA_SIZE, dwbc->config.basic_settings.chroma_pitch * dwbc->config.basic_settings.dest_height); /* should be enough to contain a whole frame Luma data, same for stereo mode */ + + /* enable address fence */ + REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUF_ADDR_FENCE_EN, 1); + + /* setup pitch */ + REG_UPDATE_2(MCIF_WB_BUF_PITCH, MCIF_WB_BUF_LUMA_PITCH, dwbc->config.basic_settings.luma_pitch, + MCIF_WB_BUF_CHROMA_PITCH, dwbc->config.basic_settings.chroma_pitch); + + /* Set pitch for MC cache warm up mode */ + /* Pitch is 256 bytes aligned. The default pitch is 4K */ + REG_UPDATE(MCIF_WB_WARM_UP_CNTL, MCIF_WB_PITCH_SIZE_WARMUP, 0x10); /* default is 0x10 */ + + /* Programmed by the video driver based on the CRTC timing (for DWB) */ + REG_UPDATE(MCIF_WB_ARBITRATION_CONTROL, MCIF_WB_TIME_PER_PIXEL, 0); + + /* Programming dwb watermark */ + /* Watermark to generate urgent in MCIF_WB_CLI, value is determined by MCIF_WB_CLI_WATERMARK_MASK. */ + /* Program in ns. A formula will be provided in the pseudo code to calculate the value. */ + REG_UPDATE(MCIF_WB_SCLK_CHANGE, MCIF_WB_CLI_WATERMARK_MASK, 0x0); + REG_UPDATE(MCIF_WB_WATERMARK, MCIF_WB_CLI_WATERMARK, 0xffff); /* urgent_watermarkA */ + REG_UPDATE(MCIF_WB_SCLK_CHANGE, MCIF_WB_CLI_WATERMARK_MASK, 0x1); + REG_UPDATE(MCIF_WB_WATERMARK, MCIF_WB_CLI_WATERMARK, 0xffff); /* urgent_watermarkB */ + REG_UPDATE(MCIF_WB_SCLK_CHANGE, MCIF_WB_CLI_WATERMARK_MASK, 0x2); + REG_UPDATE(MCIF_WB_WATERMARK, MCIF_WB_CLI_WATERMARK, 0xffff); /* urgent_watermarkC */ + REG_UPDATE(MCIF_WB_SCLK_CHANGE, MCIF_WB_CLI_WATERMARK_MASK, 0x3); + REG_UPDATE(MCIF_WB_WATERMARK, MCIF_WB_CLI_WATERMARK, 0xffff); /* urgent_watermarkD */ + + /* Programming nb pstate watermark */ + REG_UPDATE(MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_CHANGE_WATERMARK_MASK, 0x0); + REG_UPDATE(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, NB_PSTATE_CHANGE_REFRESH_WATERMARK, 0xffff); /* nbp_state_change_watermarkA */ + REG_UPDATE(MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_CHANGE_WATERMARK_MASK, 0x1); + REG_UPDATE(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, NB_PSTATE_CHANGE_REFRESH_WATERMARK, 0xffff); /* nbp_state_change_watermarkB */ + REG_UPDATE(MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_CHANGE_WATERMARK_MASK, 0x2); + REG_UPDATE(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, NB_PSTATE_CHANGE_REFRESH_WATERMARK, 0xffff); /* nbp_state_change_watermarkC */ + REG_UPDATE(MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_CHANGE_WATERMARK_MASK, 0x3); + REG_UPDATE(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, NB_PSTATE_CHANGE_REFRESH_WATERMARK, 0xffff); /* nbp_state_change_watermarkD */ + + /* buf_lh_capability = (buffer_size / byte_per_pixel)*time_per_pixel; //client buffer latency hiding capability */ + /* if (MCIF_WB_CLI_WATERMARK * 2 < buf_lh_capability) //factor '2' can be adjusted if better value is identified during bringup/debug */ + /* MULTI_LEVEL_QOS_CTRL.MAX_SCALED_TIME_TO_URGENT = MCIF_WB_CLI_WATERMARK * 2; */ + /* else */ + /* MULTI_LEVEL_QOS_CTRL.MAX_SCALED_TIME_TO_URGENT = buf_lh_capability; //ensure QoS can be fully mapped to [0:15] region in any scenario */ + + REG_UPDATE(MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_SLICE_SIZE, 31); + + /* Set arbitration unit for Luma/Chroma */ + /* arb_unit=2 should be chosen for more efficiency */ + REG_UPDATE(MCIF_WB_ARBITRATION_CONTROL, MCIF_WB_CLIENT_ARBITRATION_SLICE, 2); /* Arbitration size, 0: 512 bytes 1: 1024 bytes 2: 2048 Bytes */ + + /* Program VMID, don't support virtual mode, won't set VMID */ + /* REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_P_VMID, pVmid); */ + + if (dwbc->config.basic_settings.input_pipe_select == dwb_pipe0) { + REG_UPDATE(DWB_SOURCE_SELECT, OPTC_DWB0_SOURCE_SELECT, dwbc->config.basic_settings.input_src_select - dwb_src_otg0); + } else if (dwbc->config.basic_settings.input_pipe_select == dwb_pipe1) { + REG_UPDATE(DWB_SOURCE_SELECT, OPTC_DWB1_SOURCE_SELECT, dwbc->config.basic_settings.input_src_select - dwb_src_otg0); + } + + /* Set interrupt mask */ + REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_INT_EN, 0); /* Disable interrupt to SW. (the default value is 0.) */ + REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_SLICE_INT_EN, 0); /* Disable slice complete interrupt to SW.(the default value is 0.) */ + REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_OVERRUN_INT_EN, 0); /* Disable frame buffer overrun interrupt to SW. (the default value is 0.) */ + + REG_UPDATE(MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_INT_EN, 1); /* Enable interrupt to VCE */ + REG_UPDATE(MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_SLICE_INT_EN, 0); /* Disable slice complete interrupt to VCE. */ + + /* ////////////////// */ + /* Enable Mcifwb */ + REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_ENABLE, 1); /* Start working */ + + /* unlock sw lock. */ + REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_LOCK, 0); + + dwbc->status.enabled = true; + + return true; +} + +static bool disable(struct dwbc *dwbc) +{ + struct dcn10_dwbc *dwbc10 = TO_DCN10_DWBC(dwbc); + + /* disable CNV */ + REG_UPDATE(CNV_MODE, CNV_FRAME_CAPTURE_EN, 0); + + /* disable WB */ + REG_UPDATE(WB_ENABLE, WB_ENABLE, 0); + + /* soft reset */ + REG_UPDATE(WB_SOFT_RESET, WB_SOFT_RESET, 1); + REG_UPDATE(WB_SOFT_RESET, WB_SOFT_RESET, 0); + + /* enable power gating */ + REG_UPDATE_5(WB_EC_CONFIG, DISPCLK_R_WB_GATE_DIS, 0, + DISPCLK_G_WB_GATE_DIS, 0, DISPCLK_G_WBSCL_GATE_DIS, 0, + WB_LB_LS_DIS, 0, WB_LUT_LS_DIS, 0); + + /* disable buffer manager */ + REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_ENABLE, 0); + + dwbc->status.enabled = false; + + return true; +} + +static bool get_status(struct dwbc *dwbc, struct dwb_status *status) +{ + if (status) { + memcpy(status, &dwbc->status, sizeof(struct dwb_status)); + return true; + } else { + return false; + } +} + +static bool dump_frame(struct dwbc *dwbc, struct dwb_frame_info *frame_info, + unsigned char *luma_buffer, unsigned char *chroma_buffer, + unsigned char *dest_luma_buffer, unsigned char *dest_chroma_buffer) +{ + struct dcn10_dwbc *dwbc10 = TO_DCN10_DWBC(dwbc); + + REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_LOCK, 0xf); + + memcpy(dest_luma_buffer, luma_buffer, dwbc->config.basic_settings.luma_pitch * dwbc->config.basic_settings.dest_height); + memcpy(dest_chroma_buffer, chroma_buffer, dwbc->config.basic_settings.chroma_pitch * dwbc->config.basic_settings.dest_height / 2); + + REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_LOCK, 0x0); + + frame_info->format = dwbc->config.advanced_settings.out_format; + frame_info->width = dwbc->config.basic_settings.dest_width; + frame_info->height = dwbc->config.basic_settings.dest_height; + frame_info->luma_pitch = dwbc->config.basic_settings.luma_pitch; + frame_info->chroma_pitch = dwbc->config.basic_settings.chroma_pitch; + frame_info->size = dwbc->config.basic_settings.dest_height * (dwbc->config.basic_settings.luma_pitch + dwbc->config.basic_settings.chroma_pitch); + + return true; +} + +static bool set_basic_settings(struct dwbc *dwbc, + const struct dwb_basic_settings *basic_settings) +{ + if (basic_settings) { + memcpy(&dwbc->config.basic_settings, basic_settings, sizeof(struct dwb_basic_settings)); + return true; + } else { + return false; + } +} + +static bool get_basic_settings(struct dwbc *dwbc, + struct dwb_basic_settings *basic_settings) +{ + if (basic_settings) { + memcpy(basic_settings, &dwbc->config.basic_settings, sizeof(struct dwb_basic_settings)); + return true; + } else { + return false; + } +} + +static bool set_advanced_settings(struct dwbc *dwbc, + const struct dwb_advanced_settings *advanced_settings) +{ + if (advanced_settings) { + if (advanced_settings->uFlag & sf_output_format) { + dwbc->config.advanced_settings.uFlag |= sf_output_format; + dwbc->config.advanced_settings.out_format = advanced_settings->out_format; + } + + if (advanced_settings->uFlag & sf_capture_rate) { + dwbc->config.advanced_settings.uFlag |= sf_capture_rate; + dwbc->config.advanced_settings.capture_rate = advanced_settings->capture_rate; + } + + return true; + } else { + return false; + } +} + +static bool get_advanced_settings(struct dwbc *dwbc, + struct dwb_advanced_settings *advanced_settings) +{ + if (advanced_settings) { + memcpy(advanced_settings, &dwbc->config.advanced_settings, sizeof(struct dwb_advanced_settings)); + return true; + } else { + return false; + } +} + +static bool reset_advanced_settings(struct dwbc *dwbc) +{ + dwbc->config.advanced_settings.uFlag = 0; + dwbc->config.advanced_settings.out_format = dwb_scaler_mode_bypass444; + dwbc->config.advanced_settings.capture_rate = dwb_capture_rate_0; + + return true; +} + +const struct dwbc_funcs dcn10_dwbc_funcs = { + .get_caps = get_caps, + .enable = enable, + .disable = disable, + .get_status = get_status, + .dump_frame = dump_frame, + .set_basic_settings = set_basic_settings, + .get_basic_settings = get_basic_settings, + .set_advanced_settings = set_advanced_settings, + .get_advanced_settings = get_advanced_settings, + .reset_advanced_settings = reset_advanced_settings, +}; + +static void dcn10_dwbc_construct(struct dcn10_dwbc *dwbc10, + struct dc_context *ctx, + const struct dcn10_dwbc_registers *dwbc_regs, + const struct dcn10_dwbc_shift *dwbc_shift, + const struct dcn10_dwbc_mask *dwbc_mask, + int inst) +{ + dwbc10->base.ctx = ctx; + + dwbc10->base.inst = inst; + dwbc10->base.funcs = &dcn10_dwbc_funcs; + + dwbc10->dwbc_regs = dwbc_regs; + dwbc10->dwbc_shift = dwbc_shift; + dwbc10->dwbc_mask = dwbc_mask; +} + +bool dcn10_dwbc_create(struct dc_context *ctx, struct resource_pool *pool) +{ + int i; + uint32_t pipe_count = pool->res_cap->num_dwb; + + ASSERT(pipe_count > 0); + + for (i = 0; i < pipe_count; i++) { + struct dcn10_dwbc *dwbc10 = dm_alloc(sizeof(struct dcn10_dwbc)); + + if (!dwbc10) + return false; + + dcn10_dwbc_construct(dwbc10, ctx, + &dwbc10_regs[i], + &dwbc10_shift, + &dwbc10_mask, + i); + + pool->dwbc[i] = &dwbc10->base; + if (pool->dwbc[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create dwbc10!\n"); + return false; + } + } + return true; +} +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.h new file mode 100644 index 000000000000..cf530aed4e1c --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.h @@ -0,0 +1,32 @@ +/* Copyright 2012-17 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef __DC_DWBC_DCN10_H__ +#define __DC_DWBC_DCN10_H__ + +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + +bool dcn10_dwbc_create(struct dc_context *ctx, struct resource_pool *pool); +#endif + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 6006fb4799c3..fa990a51ac83 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -32,6 +32,7 @@ #include "dcn10/dcn10_ipp.h" #include "dcn10/dcn10_mpc.h" +#include "dcn10/dcn10_dwb.h" #include "irq/dcn10/irq_service_dcn10.h" #include "dcn10/dcn10_dpp.h" #include "dcn10/dcn10_timing_generator.h" @@ -410,6 +411,7 @@ static const struct resource_caps res_cap = { .num_audio = 4, .num_stream_encoder = 4, .num_pll = 4, + .num_dwb = 2, }; static const struct dc_debug debug_defaults_drv = { @@ -1410,6 +1412,12 @@ static bool construct( goto mpc_create_fail; } +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + if (!dcn10_dwbc_create(ctx, &pool->base)) { + goto dwbc_create_fail; + } +#endif + if (!resource_construct(num_virtual_links, dc, &pool->base, (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) ? &res_create_funcs : &res_create_maximus_funcs))) @@ -1432,6 +1440,7 @@ mi_create_fail: irqs_create_fail: res_create_fail: clock_source_create_fail: +dwbc_create_fail: destruct(pool); diff --git a/drivers/gpu/drm/amd/display/dc/inc/clock_source.h b/drivers/gpu/drm/amd/display/dc/inc/clock_source.h index 47ef90495376..ebcf67b5fc57 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/clock_source.h +++ b/drivers/gpu/drm/amd/display/dc/inc/clock_source.h @@ -166,6 +166,10 @@ struct clock_source_funcs { struct clock_source *, struct pixel_clk_params *, struct pll_settings *); + uint32_t (*get_pix_rate_in_hz)( + struct clock_source *, + struct pixel_clk_params *, + struct pll_settings *); }; struct clock_source { diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 5190901ea379..28454028434c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -32,7 +32,10 @@ #include "ddc_service_types.h" #include "dc_bios_types.h" #include "mem_input.h" +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) #include "mpc.h" +#endif +#include "dwb.h" #define MAX_CLOCK_SOURCES 7 @@ -125,6 +128,8 @@ struct resource_pool { struct mpc *mpc; #endif + struct dwbc *dwbc[MAX_DWB_PIPES]; + unsigned int pipe_count; unsigned int underlay_pipe_index; unsigned int stream_enc_count; @@ -193,6 +198,7 @@ struct pipe_ctx { struct _vcs_dpi_display_rq_regs_st rq_regs; struct _vcs_dpi_display_pipe_dest_params_st pipe_dlg_param; #endif + struct dwbc *dwbc; }; struct resource_context { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dwb.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dwb.h new file mode 100644 index 000000000000..82347ba480fe --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dwb.h @@ -0,0 +1,193 @@ +/* Copyright 2012-17 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_DWBC_H__ +#define __DC_DWBC_H__ + +#include "dc_hw_types.h" + +#define MAX_DWB_PIPES 3 + +enum dce_version; + +enum dwb_sw_version { + dwb_ver_1_0 = 1, +}; + +enum dwb_source { + dwb_src_scl = 0, /* for DCE7x/9x, DCN won't support. */ + dwb_src_blnd, /* for DCE7x/9x */ + dwb_src_fmt, /* for DCE7x/9x */ +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + dwb_src_otg0 = 0x100, /* for DCN1.x, register: mmDWB_SOURCE_SELECT */ + dwb_src_otg1, /* for DCN1.x */ + dwb_src_otg2, /* for DCN1.x */ + dwb_src_otg3, /* for DCN1.x */ +#endif +}; + +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +/* DCN1.x supports 2 pipes */ +#endif +enum dwb_pipe { + dwb_pipe0 = 0, +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + dwb_pipe1, +#endif + dwb_pipe_max_num, +}; + +enum setting_flags { + sf_pipe = 0x00000001, + sf_output_format = 0x00000002, + sf_capture_rate = 0x00000004, + sf_all = 0xffffffff, +}; + +enum dwb_capture_rate { + + dwb_capture_rate_0 = 0, /* Every frame is captured. */ + dwb_capture_rate_1 = 1, /* Every other frame is captured. */ + dwb_capture_rate_2 = 2, /* Every 3rd frame is captured. */ + dwb_capture_rate_3 = 3, /* Every 4th frame is captured. */ +}; + +enum dwb_scaler_mode { + dwb_scaler_mode_bypass444 = 0, + dwb_scaler_mode_rgb444 = 1, + dwb_scaler_mode_yuv444 = 2, + dwb_scaler_mode_yuv420 = 3 +}; + +struct dwb_caps { + enum dce_version hw_version; /* DCN engine version. */ + enum dwb_sw_version sw_version; /* DWB sw implementation version. */ + unsigned int reserved[6]; /* Reserved for future use, MUST BE 0. */ + unsigned int adapter_id; + unsigned int num_pipes; /* number of DWB pipes */ + struct { + unsigned int support_dwb :1; + unsigned int support_ogam :1; + unsigned int support_wbscl :1; + unsigned int support_ocsc :1; + } caps; + unsigned int reserved2[10]; /* Reserved for future use, MUST BE 0. */ +}; + +struct dwb_status { + bool enabled; + /* Reserved ========================================================================= */ + unsigned int reserved[8]; /* Reserved fields */ +}; + +struct dwb_basic_settings { + /* General DWB related input parameters ============================================= */ + enum dwb_source input_src_select; /* Select input source: (DCE) 0: SCL; 1: BLND; 2: FMT; (DCN) OTG* or MPC* */ + enum dwb_pipe input_pipe_select; /* Select input pipe: 0: PIPE0; 1: PIPE1; 2: PIPE2 */ + + /* CNV: WND Related parameters ====================================================== */ + unsigned int capture_rate; /* Captures once every (capture_rate+1) frames */ + + /* CNV: CSC Related parameters ====================================================== */ + unsigned int start_x; /* Horizontal window start position */ + unsigned int start_y; /* Vertical window start position */ + unsigned int src_width; /* Width of window captured within source window */ + unsigned int src_height; /* Height of window captured within source window */ + + /* SISCL Related parameters ========================================================= */ + unsigned int dest_width; /* Destination width */ + unsigned int dest_height; /* Destination height */ + + /* MCIF bufer parameters ========================================================= */ + unsigned long long luma_address[4]; + unsigned long long chroma_address[4]; + unsigned int luma_pitch; + unsigned int chroma_pitch; + unsigned int slice_lines; + + /* Reserved ========================================================================= */ + unsigned int reserved[8]; /* Reserved fields */ + +}; + +struct dwb_advanced_settings { + enum setting_flags uFlag; + enum dwb_pipe pipe; /* default = DWB_PIPE_ALL */ + enum dwb_scaler_mode out_format; /* default = DWBScalerMode_YUV420 */ + enum dwb_capture_rate capture_rate; /* default = Every frame is captured */ + unsigned int reserved[64]; /* reserved for future use, must be 0 */ +}; + +/* / - dwb_frame_info is the info of the dumping data */ +struct dwb_frame_info { + unsigned int size; + unsigned int width; + unsigned int height; + unsigned int luma_pitch; + unsigned int chroma_pitch; + enum dwb_scaler_mode format; +}; + +struct dwbc_cfg { + struct dwb_basic_settings basic_settings; + struct dwb_advanced_settings advanced_settings; +}; + +struct dwbc { + const struct dwbc_funcs *funcs; + struct dc_context *ctx; + struct dwbc_cfg config; + struct dwb_status status; + int inst; +}; + +struct dwbc_funcs { + bool (*get_caps)(struct dwbc *dwbc, struct dwb_caps *caps); + + bool (*enable)(struct dwbc *dwbc); + + bool (*disable)(struct dwbc *dwbc); + + bool (*get_status)(struct dwbc *dwbc, struct dwb_status *status); + + bool (*dump_frame)(struct dwbc *dwbc, struct dwb_frame_info *frame_info, + unsigned char *luma_buffer, unsigned char *chroma_buffer, + unsigned char *dest_luma_buffer, unsigned char *dest_chroma_buffer); + + bool (*set_basic_settings)(struct dwbc *dwbc, + const struct dwb_basic_settings *basic_settings); + + bool (*get_basic_settings)(struct dwbc *dwbc, + struct dwb_basic_settings *basic_settings); + + bool (*set_advanced_settings)(struct dwbc *dwbc, + const struct dwb_advanced_settings *advanced_settings); + + bool (*get_advanced_settings)(struct dwbc *dwbc, + struct dwb_advanced_settings *advanced_settings); + + bool (*reset_advanced_settings)(struct dwbc *dwbc); +}; + +#endif -- cgit From 77a4ea53fd89ccf823e77cc31cea808a3589f732 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Wed, 2 Aug 2017 16:56:03 -0400 Subject: drm/amd/display: change bw_dceip and bw_vbios into pointers -Change bw_calcs_dceip into pointer -Change bw_calcs_vbios into pointer This is needed for flattening of core_dc into dc, as without this the diags build fails Signed-off-by: Bhawanpreet Lakha Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 26 +++++++++++ .../amd/display/dc/dce110/dce110_hw_sequencer.c | 2 +- .../drm/amd/display/dc/dce110/dce110_resource.c | 34 +++++++-------- .../drm/amd/display/dc/dce112/dce112_resource.c | 50 +++++++++++----------- .../drm/amd/display/dc/dce120/dce120_resource.c | 24 +++++------ drivers/gpu/drm/amd/display/dc/inc/core_dc.h | 4 +- 6 files changed, 83 insertions(+), 57 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index aeed95a5d097..477024c467e6 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -433,6 +433,13 @@ static void destruct(struct core_dc *dc) dm_free(dc->ctx); dc->ctx = NULL; + + dm_free(dc->bw_vbios); + dc->bw_vbios = NULL; + + dm_free(dc->bw_dceip); + dc->bw_dceip = NULL; + } static bool construct(struct core_dc *dc, @@ -440,8 +447,25 @@ static bool construct(struct core_dc *dc, { struct dal_logger *logger; struct dc_context *dc_ctx = dm_alloc(sizeof(*dc_ctx)); + struct bw_calcs_dceip *dc_dceip = dm_alloc(sizeof(*dc_dceip)); + struct bw_calcs_vbios *dc_vbios = dm_alloc(sizeof(*dc_vbios)); + enum dce_version dc_version = DCE_VERSION_UNKNOWN; + if (!dc_dceip) { + dm_error("%s: failed to create dceip\n", __func__); + goto dceip_fail; + } + + dc->bw_dceip = dc_dceip; + + if (!dc_vbios) { + dm_error("%s: failed to create vbios\n", __func__); + goto vbios_fail; + } + + dc->bw_vbios = dc_vbios; + if (!dc_ctx) { dm_error("%s: failed to create ctx\n", __func__); goto ctx_fail; @@ -544,6 +568,8 @@ bios_fail: logger_fail: val_ctx_fail: ctx_fail: +dceip_fail: +vbios_fail: destruct(dc); return false; } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 5b46e776b9b7..ccde7c80d658 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1264,7 +1264,7 @@ void dce110_set_displaymarks( continue; total_dest_line_time_ns = compute_pstate_blackout_duration( - dc->bw_vbios.blackout_duration, pipe_ctx->stream); + dc->bw_vbios->blackout_duration, pipe_ctx->stream); pipe_ctx->plane_res.mi->funcs->mem_input_program_display_marks( pipe_ctx->plane_res.mi, context->bw.dce.nbp_state_change_wm_ns[num_pipes], diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index a7f30dcc906c..56be84ce5a0d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -826,8 +826,8 @@ static bool dce110_validate_bandwidth( if (bw_calcs( dc->ctx, - &dc->bw_dceip, - &dc->bw_vbios, + dc->bw_dceip, + dc->bw_vbios, context->res_ctx.pipe_ctx, dc->res_pool->pipe_count, &context->bw.dce)) @@ -1127,21 +1127,21 @@ static void bw_calcs_data_update_from_pplib(struct core_dc *dc) DM_PP_CLOCK_TYPE_ENGINE_CLK, &clks); /* convert all the clock fro kHz to fix point mHz */ - dc->bw_vbios.high_sclk = bw_frc_to_fixed( + dc->bw_vbios->high_sclk = bw_frc_to_fixed( clks.clocks_in_khz[clks.num_levels-1], 1000); - dc->bw_vbios.mid1_sclk = bw_frc_to_fixed( + dc->bw_vbios->mid1_sclk = bw_frc_to_fixed( clks.clocks_in_khz[clks.num_levels/8], 1000); - dc->bw_vbios.mid2_sclk = bw_frc_to_fixed( + dc->bw_vbios->mid2_sclk = bw_frc_to_fixed( clks.clocks_in_khz[clks.num_levels*2/8], 1000); - dc->bw_vbios.mid3_sclk = bw_frc_to_fixed( + dc->bw_vbios->mid3_sclk = bw_frc_to_fixed( clks.clocks_in_khz[clks.num_levels*3/8], 1000); - dc->bw_vbios.mid4_sclk = bw_frc_to_fixed( + dc->bw_vbios->mid4_sclk = bw_frc_to_fixed( clks.clocks_in_khz[clks.num_levels*4/8], 1000); - dc->bw_vbios.mid5_sclk = bw_frc_to_fixed( + dc->bw_vbios->mid5_sclk = bw_frc_to_fixed( clks.clocks_in_khz[clks.num_levels*5/8], 1000); - dc->bw_vbios.mid6_sclk = bw_frc_to_fixed( + dc->bw_vbios->mid6_sclk = bw_frc_to_fixed( clks.clocks_in_khz[clks.num_levels*6/8], 1000); - dc->bw_vbios.low_sclk = bw_frc_to_fixed( + dc->bw_vbios->low_sclk = bw_frc_to_fixed( clks.clocks_in_khz[0], 1000); dc->sclk_lvls = clks; @@ -1150,11 +1150,11 @@ static void bw_calcs_data_update_from_pplib(struct core_dc *dc) dc->ctx, DM_PP_CLOCK_TYPE_DISPLAY_CLK, &clks); - dc->bw_vbios.high_voltage_max_dispclk = bw_frc_to_fixed( + dc->bw_vbios->high_voltage_max_dispclk = bw_frc_to_fixed( clks.clocks_in_khz[clks.num_levels-1], 1000); - dc->bw_vbios.mid_voltage_max_dispclk = bw_frc_to_fixed( + dc->bw_vbios->mid_voltage_max_dispclk = bw_frc_to_fixed( clks.clocks_in_khz[clks.num_levels>>1], 1000); - dc->bw_vbios.low_voltage_max_dispclk = bw_frc_to_fixed( + dc->bw_vbios->low_voltage_max_dispclk = bw_frc_to_fixed( clks.clocks_in_khz[0], 1000); /*do memory clock*/ @@ -1163,12 +1163,12 @@ static void bw_calcs_data_update_from_pplib(struct core_dc *dc) DM_PP_CLOCK_TYPE_MEMORY_CLK, &clks); - dc->bw_vbios.low_yclk = bw_frc_to_fixed( + dc->bw_vbios->low_yclk = bw_frc_to_fixed( clks.clocks_in_khz[0] * MEMORY_TYPE_MULTIPLIER, 1000); - dc->bw_vbios.mid_yclk = bw_frc_to_fixed( + dc->bw_vbios->mid_yclk = bw_frc_to_fixed( clks.clocks_in_khz[clks.num_levels>>1] * MEMORY_TYPE_MULTIPLIER, 1000); - dc->bw_vbios.high_yclk = bw_frc_to_fixed( + dc->bw_vbios->high_yclk = bw_frc_to_fixed( clks.clocks_in_khz[clks.num_levels-1] * MEMORY_TYPE_MULTIPLIER, 1000); } @@ -1353,7 +1353,7 @@ static bool construct( dc->public.caps.max_planes = pool->base.pipe_count; - bw_calcs_init(&dc->bw_dceip, &dc->bw_vbios, dc->ctx->asic_id); + bw_calcs_init(dc->bw_dceip, dc->bw_vbios, dc->ctx->asic_id); bw_calcs_data_update_from_pplib(dc); diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 420434d7283e..d6e58a25f3d0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -771,8 +771,8 @@ bool dce112_validate_bandwidth( if (bw_calcs( dc->ctx, - &dc->bw_dceip, - &dc->bw_vbios, + dc->bw_dceip, + dc->bw_vbios, context->res_ctx.pipe_ctx, dc->res_pool->pipe_count, &context->bw.dce)) @@ -1018,21 +1018,21 @@ static void bw_calcs_data_update_from_pplib(struct core_dc *dc) DM_PP_CLOCK_TYPE_ENGINE_CLK, &clks); /* convert all the clock fro kHz to fix point mHz */ - dc->bw_vbios.high_sclk = bw_frc_to_fixed( + dc->bw_vbios->high_sclk = bw_frc_to_fixed( clks.clocks_in_khz[clks.num_levels-1], 1000); - dc->bw_vbios.mid1_sclk = bw_frc_to_fixed( + dc->bw_vbios->mid1_sclk = bw_frc_to_fixed( clks.clocks_in_khz[clks.num_levels/8], 1000); - dc->bw_vbios.mid2_sclk = bw_frc_to_fixed( + dc->bw_vbios->mid2_sclk = bw_frc_to_fixed( clks.clocks_in_khz[clks.num_levels*2/8], 1000); - dc->bw_vbios.mid3_sclk = bw_frc_to_fixed( + dc->bw_vbios->mid3_sclk = bw_frc_to_fixed( clks.clocks_in_khz[clks.num_levels*3/8], 1000); - dc->bw_vbios.mid4_sclk = bw_frc_to_fixed( + dc->bw_vbios->mid4_sclk = bw_frc_to_fixed( clks.clocks_in_khz[clks.num_levels*4/8], 1000); - dc->bw_vbios.mid5_sclk = bw_frc_to_fixed( + dc->bw_vbios->mid5_sclk = bw_frc_to_fixed( clks.clocks_in_khz[clks.num_levels*5/8], 1000); - dc->bw_vbios.mid6_sclk = bw_frc_to_fixed( + dc->bw_vbios->mid6_sclk = bw_frc_to_fixed( clks.clocks_in_khz[clks.num_levels*6/8], 1000); - dc->bw_vbios.low_sclk = bw_frc_to_fixed( + dc->bw_vbios->low_sclk = bw_frc_to_fixed( clks.clocks_in_khz[0], 1000); /*do memory clock*/ @@ -1041,12 +1041,12 @@ static void bw_calcs_data_update_from_pplib(struct core_dc *dc) DM_PP_CLOCK_TYPE_MEMORY_CLK, &clks); - dc->bw_vbios.low_yclk = bw_frc_to_fixed( + dc->bw_vbios->low_yclk = bw_frc_to_fixed( clks.clocks_in_khz[0] * MEMORY_TYPE_MULTIPLIER, 1000); - dc->bw_vbios.mid_yclk = bw_frc_to_fixed( + dc->bw_vbios->mid_yclk = bw_frc_to_fixed( clks.clocks_in_khz[clks.num_levels>>1] * MEMORY_TYPE_MULTIPLIER, 1000); - dc->bw_vbios.high_yclk = bw_frc_to_fixed( + dc->bw_vbios->high_yclk = bw_frc_to_fixed( clks.clocks_in_khz[clks.num_levels-1] * MEMORY_TYPE_MULTIPLIER, 1000); @@ -1054,21 +1054,21 @@ static void bw_calcs_data_update_from_pplib(struct core_dc *dc) } /* convert all the clock fro kHz to fix point mHz TODO: wloop data */ - dc->bw_vbios.high_sclk = bw_frc_to_fixed( + dc->bw_vbios->high_sclk = bw_frc_to_fixed( eng_clks.data[eng_clks.num_levels-1].clocks_in_khz, 1000); - dc->bw_vbios.mid1_sclk = bw_frc_to_fixed( + dc->bw_vbios->mid1_sclk = bw_frc_to_fixed( eng_clks.data[eng_clks.num_levels/8].clocks_in_khz, 1000); - dc->bw_vbios.mid2_sclk = bw_frc_to_fixed( + dc->bw_vbios->mid2_sclk = bw_frc_to_fixed( eng_clks.data[eng_clks.num_levels*2/8].clocks_in_khz, 1000); - dc->bw_vbios.mid3_sclk = bw_frc_to_fixed( + dc->bw_vbios->mid3_sclk = bw_frc_to_fixed( eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz, 1000); - dc->bw_vbios.mid4_sclk = bw_frc_to_fixed( + dc->bw_vbios->mid4_sclk = bw_frc_to_fixed( eng_clks.data[eng_clks.num_levels*4/8].clocks_in_khz, 1000); - dc->bw_vbios.mid5_sclk = bw_frc_to_fixed( + dc->bw_vbios->mid5_sclk = bw_frc_to_fixed( eng_clks.data[eng_clks.num_levels*5/8].clocks_in_khz, 1000); - dc->bw_vbios.mid6_sclk = bw_frc_to_fixed( + dc->bw_vbios->mid6_sclk = bw_frc_to_fixed( eng_clks.data[eng_clks.num_levels*6/8].clocks_in_khz, 1000); - dc->bw_vbios.low_sclk = bw_frc_to_fixed( + dc->bw_vbios->low_sclk = bw_frc_to_fixed( eng_clks.data[0].clocks_in_khz, 1000); /*do memory clock*/ @@ -1082,12 +1082,12 @@ static void bw_calcs_data_update_from_pplib(struct core_dc *dc) * ALSO always convert UMA clock (from PPLIB) to YCLK (HW formula): * YCLK = UMACLK*m_memoryTypeMultiplier */ - dc->bw_vbios.low_yclk = bw_frc_to_fixed( + dc->bw_vbios->low_yclk = bw_frc_to_fixed( mem_clks.data[0].clocks_in_khz * MEMORY_TYPE_MULTIPLIER, 1000); - dc->bw_vbios.mid_yclk = bw_frc_to_fixed( + dc->bw_vbios->mid_yclk = bw_frc_to_fixed( mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz * MEMORY_TYPE_MULTIPLIER, 1000); - dc->bw_vbios.high_yclk = bw_frc_to_fixed( + dc->bw_vbios->high_yclk = bw_frc_to_fixed( mem_clks.data[mem_clks.num_levels-1].clocks_in_khz * MEMORY_TYPE_MULTIPLIER, 1000); @@ -1325,7 +1325,7 @@ static bool construct( if (!dce112_hw_sequencer_construct(dc)) goto res_create_fail; - bw_calcs_init(&dc->bw_dceip, &dc->bw_vbios, dc->ctx->asic_id); + bw_calcs_init(dc->bw_dceip, dc->bw_vbios, dc->ctx->asic_id); bw_calcs_data_update_from_pplib(dc); diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index d4e962756fbb..562ae2205a90 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -729,21 +729,21 @@ static void bw_calcs_data_update_from_pplib(struct core_dc *dc) } /* convert all the clock fro kHz to fix point mHz TODO: wloop data */ - dc->bw_vbios.high_sclk = bw_frc_to_fixed( + dc->bw_vbios->high_sclk = bw_frc_to_fixed( eng_clks.data[eng_clks.num_levels-1].clocks_in_khz, 1000); - dc->bw_vbios.mid1_sclk = bw_frc_to_fixed( + dc->bw_vbios->mid1_sclk = bw_frc_to_fixed( eng_clks.data[eng_clks.num_levels/8].clocks_in_khz, 1000); - dc->bw_vbios.mid2_sclk = bw_frc_to_fixed( + dc->bw_vbios->mid2_sclk = bw_frc_to_fixed( eng_clks.data[eng_clks.num_levels*2/8].clocks_in_khz, 1000); - dc->bw_vbios.mid3_sclk = bw_frc_to_fixed( + dc->bw_vbios->mid3_sclk = bw_frc_to_fixed( eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz, 1000); - dc->bw_vbios.mid4_sclk = bw_frc_to_fixed( + dc->bw_vbios->mid4_sclk = bw_frc_to_fixed( eng_clks.data[eng_clks.num_levels*4/8].clocks_in_khz, 1000); - dc->bw_vbios.mid5_sclk = bw_frc_to_fixed( + dc->bw_vbios->mid5_sclk = bw_frc_to_fixed( eng_clks.data[eng_clks.num_levels*5/8].clocks_in_khz, 1000); - dc->bw_vbios.mid6_sclk = bw_frc_to_fixed( + dc->bw_vbios->mid6_sclk = bw_frc_to_fixed( eng_clks.data[eng_clks.num_levels*6/8].clocks_in_khz, 1000); - dc->bw_vbios.low_sclk = bw_frc_to_fixed( + dc->bw_vbios->low_sclk = bw_frc_to_fixed( eng_clks.data[0].clocks_in_khz, 1000); /*do memory clock*/ @@ -770,12 +770,12 @@ static void bw_calcs_data_update_from_pplib(struct core_dc *dc) * ALSO always convert UMA clock (from PPLIB) to YCLK (HW formula): * YCLK = UMACLK*m_memoryTypeMultiplier */ - dc->bw_vbios.low_yclk = bw_frc_to_fixed( + dc->bw_vbios->low_yclk = bw_frc_to_fixed( mem_clks.data[0].clocks_in_khz * MEMORY_TYPE_MULTIPLIER, 1000); - dc->bw_vbios.mid_yclk = bw_frc_to_fixed( + dc->bw_vbios->mid_yclk = bw_frc_to_fixed( mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz * MEMORY_TYPE_MULTIPLIER, 1000); - dc->bw_vbios.high_yclk = bw_frc_to_fixed( + dc->bw_vbios->high_yclk = bw_frc_to_fixed( mem_clks.data[mem_clks.num_levels-1].clocks_in_khz * MEMORY_TYPE_MULTIPLIER, 1000); @@ -984,7 +984,7 @@ static bool construct( dc->public.caps.max_planes = pool->base.pipe_count; - bw_calcs_init(&dc->bw_dceip, &dc->bw_vbios, dc->ctx->asic_id); + bw_calcs_init(dc->bw_dceip, dc->bw_vbios, dc->ctx->asic_id); bw_calcs_data_update_from_pplib(dc); diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_dc.h b/drivers/gpu/drm/amd/display/dc/inc/core_dc.h index 1ecb54603e17..982f7170f5d2 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_dc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_dc.h @@ -29,8 +29,8 @@ struct core_dc { struct dm_pp_clock_levels sclk_lvls; /* Inputs into BW and WM calculations. */ - struct bw_calcs_dceip bw_dceip; - struct bw_calcs_vbios bw_vbios; + struct bw_calcs_dceip *bw_dceip; + struct bw_calcs_vbios *bw_vbios; #ifdef CONFIG_DRM_AMD_DC_DCN1_0 struct dcn_soc_bounding_box dcn_soc; struct dcn_ip_params dcn_ip; -- cgit From e771aae02baa59386972faec491cd221c169ed53 Mon Sep 17 00:00:00 2001 From: Corbin McElhanney Date: Wed, 9 Aug 2017 10:30:28 -0400 Subject: drm/amd/display: Add comment explaining context free This comment explains a previous change that adds some complexity to the context free in dc: commit 9ad58779a895 ("drm/amd/display: Fix accessing freed memory") Signed-off-by: Corbin McElhanney Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 477024c467e6..33c3d88b1c86 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1740,6 +1740,15 @@ void dc_update_planes_and_stream(struct dc *dc, } if (core_dc->current_context != context) { + + /* Since memory free requires elevated IRQL, an interrupt + * request is generated by mem free. If this happens + * between freeing and reassigning the context, our vsync + * interrupt will call into dc and cause a memory + * corruption BSOD. Hence, we first reassign the context, + * then free the old context. + */ + struct validate_context *old = core_dc->current_context; core_dc->current_context = context; -- cgit From 65111f25f1fea751f3b4321a59c993c2898b7dbf Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Thu, 3 Aug 2017 13:02:29 -0400 Subject: drm/amd/display: change dcn_ip and dcn_soc into pointers -Change dcn_ip into pointer -Change dcn_soc into pointer This is needed for flattening of core_dc into dc, as without this the diags build fails Signed-off-by: Bhawanpreet Lakha Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 553 +++++++++++---------- drivers/gpu/drm/amd/display/dc/core/dc.c | 59 ++- .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 28 +- drivers/gpu/drm/amd/display/dc/inc/core_dc.h | 4 +- 4 files changed, 331 insertions(+), 313 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 67da973c898b..6fb1b9a91993 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -457,7 +457,7 @@ static void dcn_bw_calc_rq_dlg_ttu( } /*todo: soc->sr_enter_plus_exit_time??*/ - dlg_sys_param.t_srx_delay_us = dc->dcn_ip.dcfclk_cstate_latency / v->dcf_clk_deep_sleep; + dlg_sys_param.t_srx_delay_us = dc->dcn_ip->dcfclk_cstate_latency / v->dcf_clk_deep_sleep; dml_rq_dlg_get_rq_params(dml, &rq_param, input.pipe.src); extract_rq_regs(dml, rq_regs, rq_param); @@ -679,39 +679,39 @@ static bool dcn_bw_apply_registry_override(struct core_dc *dc) bool updated = false; kernel_fpu_begin(); - if ((int)(dc->dcn_soc.sr_exit_time * 1000) != dc->public.debug.sr_exit_time_ns + if ((int)(dc->dcn_soc->sr_exit_time * 1000) != dc->public.debug.sr_exit_time_ns && dc->public.debug.sr_exit_time_ns) { updated = true; - dc->dcn_soc.sr_exit_time = dc->public.debug.sr_exit_time_ns / 1000.0; + dc->dcn_soc->sr_exit_time = dc->public.debug.sr_exit_time_ns / 1000.0; } - if ((int)(dc->dcn_soc.sr_enter_plus_exit_time * 1000) + if ((int)(dc->dcn_soc->sr_enter_plus_exit_time * 1000) != dc->public.debug.sr_enter_plus_exit_time_ns && dc->public.debug.sr_enter_plus_exit_time_ns) { updated = true; - dc->dcn_soc.sr_enter_plus_exit_time = + dc->dcn_soc->sr_enter_plus_exit_time = dc->public.debug.sr_enter_plus_exit_time_ns / 1000.0; } - if ((int)(dc->dcn_soc.urgent_latency * 1000) != dc->public.debug.urgent_latency_ns + if ((int)(dc->dcn_soc->urgent_latency * 1000) != dc->public.debug.urgent_latency_ns && dc->public.debug.urgent_latency_ns) { updated = true; - dc->dcn_soc.urgent_latency = dc->public.debug.urgent_latency_ns / 1000.0; + dc->dcn_soc->urgent_latency = dc->public.debug.urgent_latency_ns / 1000.0; } - if ((int)(dc->dcn_soc.percent_of_ideal_drambw_received_after_urg_latency * 1000) + if ((int)(dc->dcn_soc->percent_of_ideal_drambw_received_after_urg_latency * 1000) != dc->public.debug.percent_of_ideal_drambw && dc->public.debug.percent_of_ideal_drambw) { updated = true; - dc->dcn_soc.percent_of_ideal_drambw_received_after_urg_latency = + dc->dcn_soc->percent_of_ideal_drambw_received_after_urg_latency = dc->public.debug.percent_of_ideal_drambw; } - if ((int)(dc->dcn_soc.dram_clock_change_latency * 1000) + if ((int)(dc->dcn_soc->dram_clock_change_latency * 1000) != dc->public.debug.dram_clock_change_latency_ns && dc->public.debug.dram_clock_change_latency_ns) { updated = true; - dc->dcn_soc.dram_clock_change_latency = + dc->dcn_soc->dram_clock_change_latency = dc->public.debug.dram_clock_change_latency_ns / 1000.0; } kernel_fpu_end(); @@ -735,83 +735,83 @@ bool dcn_validate_bandwidth( memset(v, 0, sizeof(*v)); kernel_fpu_begin(); - v->sr_exit_time = dc->dcn_soc.sr_exit_time; - v->sr_enter_plus_exit_time = dc->dcn_soc.sr_enter_plus_exit_time; - v->urgent_latency = dc->dcn_soc.urgent_latency; - v->write_back_latency = dc->dcn_soc.write_back_latency; + v->sr_exit_time = dc->dcn_soc->sr_exit_time; + v->sr_enter_plus_exit_time = dc->dcn_soc->sr_enter_plus_exit_time; + v->urgent_latency = dc->dcn_soc->urgent_latency; + v->write_back_latency = dc->dcn_soc->write_back_latency; v->percent_of_ideal_drambw_received_after_urg_latency = - dc->dcn_soc.percent_of_ideal_drambw_received_after_urg_latency; - - v->dcfclkv_min0p65 = dc->dcn_soc.dcfclkv_min0p65; - v->dcfclkv_mid0p72 = dc->dcn_soc.dcfclkv_mid0p72; - v->dcfclkv_nom0p8 = dc->dcn_soc.dcfclkv_nom0p8; - v->dcfclkv_max0p9 = dc->dcn_soc.dcfclkv_max0p9; - - v->max_dispclk_vmin0p65 = dc->dcn_soc.max_dispclk_vmin0p65; - v->max_dispclk_vmid0p72 = dc->dcn_soc.max_dispclk_vmid0p72; - v->max_dispclk_vnom0p8 = dc->dcn_soc.max_dispclk_vnom0p8; - v->max_dispclk_vmax0p9 = dc->dcn_soc.max_dispclk_vmax0p9; - - v->max_dppclk_vmin0p65 = dc->dcn_soc.max_dppclk_vmin0p65; - v->max_dppclk_vmid0p72 = dc->dcn_soc.max_dppclk_vmid0p72; - v->max_dppclk_vnom0p8 = dc->dcn_soc.max_dppclk_vnom0p8; - v->max_dppclk_vmax0p9 = dc->dcn_soc.max_dppclk_vmax0p9; - - v->socclk = dc->dcn_soc.socclk; - - v->fabric_and_dram_bandwidth_vmin0p65 = dc->dcn_soc.fabric_and_dram_bandwidth_vmin0p65; - v->fabric_and_dram_bandwidth_vmid0p72 = dc->dcn_soc.fabric_and_dram_bandwidth_vmid0p72; - v->fabric_and_dram_bandwidth_vnom0p8 = dc->dcn_soc.fabric_and_dram_bandwidth_vnom0p8; - v->fabric_and_dram_bandwidth_vmax0p9 = dc->dcn_soc.fabric_and_dram_bandwidth_vmax0p9; - - v->phyclkv_min0p65 = dc->dcn_soc.phyclkv_min0p65; - v->phyclkv_mid0p72 = dc->dcn_soc.phyclkv_mid0p72; - v->phyclkv_nom0p8 = dc->dcn_soc.phyclkv_nom0p8; - v->phyclkv_max0p9 = dc->dcn_soc.phyclkv_max0p9; - - v->downspreading = dc->dcn_soc.downspreading; - v->round_trip_ping_latency_cycles = dc->dcn_soc.round_trip_ping_latency_cycles; - v->urgent_out_of_order_return_per_channel = dc->dcn_soc.urgent_out_of_order_return_per_channel; - v->number_of_channels = dc->dcn_soc.number_of_channels; - v->vmm_page_size = dc->dcn_soc.vmm_page_size; - v->dram_clock_change_latency = dc->dcn_soc.dram_clock_change_latency; - v->return_bus_width = dc->dcn_soc.return_bus_width; - - v->rob_buffer_size_in_kbyte = dc->dcn_ip.rob_buffer_size_in_kbyte; - v->det_buffer_size_in_kbyte = dc->dcn_ip.det_buffer_size_in_kbyte; - v->dpp_output_buffer_pixels = dc->dcn_ip.dpp_output_buffer_pixels; - v->opp_output_buffer_lines = dc->dcn_ip.opp_output_buffer_lines; - v->pixel_chunk_size_in_kbyte = dc->dcn_ip.pixel_chunk_size_in_kbyte; - v->pte_enable = dc->dcn_ip.pte_enable; - v->pte_chunk_size = dc->dcn_ip.pte_chunk_size; - v->meta_chunk_size = dc->dcn_ip.meta_chunk_size; - v->writeback_chunk_size = dc->dcn_ip.writeback_chunk_size; - v->odm_capability = dc->dcn_ip.odm_capability; - v->dsc_capability = dc->dcn_ip.dsc_capability; - v->line_buffer_size = dc->dcn_ip.line_buffer_size; - v->is_line_buffer_bpp_fixed = dc->dcn_ip.is_line_buffer_bpp_fixed; - v->line_buffer_fixed_bpp = dc->dcn_ip.line_buffer_fixed_bpp; - v->max_line_buffer_lines = dc->dcn_ip.max_line_buffer_lines; - v->writeback_luma_buffer_size = dc->dcn_ip.writeback_luma_buffer_size; - v->writeback_chroma_buffer_size = dc->dcn_ip.writeback_chroma_buffer_size; - v->max_num_dpp = dc->dcn_ip.max_num_dpp; - v->max_num_writeback = dc->dcn_ip.max_num_writeback; - v->max_dchub_topscl_throughput = dc->dcn_ip.max_dchub_topscl_throughput; - v->max_pscl_tolb_throughput = dc->dcn_ip.max_pscl_tolb_throughput; - v->max_lb_tovscl_throughput = dc->dcn_ip.max_lb_tovscl_throughput; - v->max_vscl_tohscl_throughput = dc->dcn_ip.max_vscl_tohscl_throughput; - v->max_hscl_ratio = dc->dcn_ip.max_hscl_ratio; - v->max_vscl_ratio = dc->dcn_ip.max_vscl_ratio; - v->max_hscl_taps = dc->dcn_ip.max_hscl_taps; - v->max_vscl_taps = dc->dcn_ip.max_vscl_taps; - v->under_scan_factor = dc->dcn_ip.under_scan_factor; - v->pte_buffer_size_in_requests = dc->dcn_ip.pte_buffer_size_in_requests; - v->dispclk_ramping_margin = dc->dcn_ip.dispclk_ramping_margin; - v->max_inter_dcn_tile_repeaters = dc->dcn_ip.max_inter_dcn_tile_repeaters; + dc->dcn_soc->percent_of_ideal_drambw_received_after_urg_latency; + + v->dcfclkv_min0p65 = dc->dcn_soc->dcfclkv_min0p65; + v->dcfclkv_mid0p72 = dc->dcn_soc->dcfclkv_mid0p72; + v->dcfclkv_nom0p8 = dc->dcn_soc->dcfclkv_nom0p8; + v->dcfclkv_max0p9 = dc->dcn_soc->dcfclkv_max0p9; + + v->max_dispclk_vmin0p65 = dc->dcn_soc->max_dispclk_vmin0p65; + v->max_dispclk_vmid0p72 = dc->dcn_soc->max_dispclk_vmid0p72; + v->max_dispclk_vnom0p8 = dc->dcn_soc->max_dispclk_vnom0p8; + v->max_dispclk_vmax0p9 = dc->dcn_soc->max_dispclk_vmax0p9; + + v->max_dppclk_vmin0p65 = dc->dcn_soc->max_dppclk_vmin0p65; + v->max_dppclk_vmid0p72 = dc->dcn_soc->max_dppclk_vmid0p72; + v->max_dppclk_vnom0p8 = dc->dcn_soc->max_dppclk_vnom0p8; + v->max_dppclk_vmax0p9 = dc->dcn_soc->max_dppclk_vmax0p9; + + v->socclk = dc->dcn_soc->socclk; + + v->fabric_and_dram_bandwidth_vmin0p65 = dc->dcn_soc->fabric_and_dram_bandwidth_vmin0p65; + v->fabric_and_dram_bandwidth_vmid0p72 = dc->dcn_soc->fabric_and_dram_bandwidth_vmid0p72; + v->fabric_and_dram_bandwidth_vnom0p8 = dc->dcn_soc->fabric_and_dram_bandwidth_vnom0p8; + v->fabric_and_dram_bandwidth_vmax0p9 = dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9; + + v->phyclkv_min0p65 = dc->dcn_soc->phyclkv_min0p65; + v->phyclkv_mid0p72 = dc->dcn_soc->phyclkv_mid0p72; + v->phyclkv_nom0p8 = dc->dcn_soc->phyclkv_nom0p8; + v->phyclkv_max0p9 = dc->dcn_soc->phyclkv_max0p9; + + v->downspreading = dc->dcn_soc->downspreading; + v->round_trip_ping_latency_cycles = dc->dcn_soc->round_trip_ping_latency_cycles; + v->urgent_out_of_order_return_per_channel = dc->dcn_soc->urgent_out_of_order_return_per_channel; + v->number_of_channels = dc->dcn_soc->number_of_channels; + v->vmm_page_size = dc->dcn_soc->vmm_page_size; + v->dram_clock_change_latency = dc->dcn_soc->dram_clock_change_latency; + v->return_bus_width = dc->dcn_soc->return_bus_width; + + v->rob_buffer_size_in_kbyte = dc->dcn_ip->rob_buffer_size_in_kbyte; + v->det_buffer_size_in_kbyte = dc->dcn_ip->det_buffer_size_in_kbyte; + v->dpp_output_buffer_pixels = dc->dcn_ip->dpp_output_buffer_pixels; + v->opp_output_buffer_lines = dc->dcn_ip->opp_output_buffer_lines; + v->pixel_chunk_size_in_kbyte = dc->dcn_ip->pixel_chunk_size_in_kbyte; + v->pte_enable = dc->dcn_ip->pte_enable; + v->pte_chunk_size = dc->dcn_ip->pte_chunk_size; + v->meta_chunk_size = dc->dcn_ip->meta_chunk_size; + v->writeback_chunk_size = dc->dcn_ip->writeback_chunk_size; + v->odm_capability = dc->dcn_ip->odm_capability; + v->dsc_capability = dc->dcn_ip->dsc_capability; + v->line_buffer_size = dc->dcn_ip->line_buffer_size; + v->is_line_buffer_bpp_fixed = dc->dcn_ip->is_line_buffer_bpp_fixed; + v->line_buffer_fixed_bpp = dc->dcn_ip->line_buffer_fixed_bpp; + v->max_line_buffer_lines = dc->dcn_ip->max_line_buffer_lines; + v->writeback_luma_buffer_size = dc->dcn_ip->writeback_luma_buffer_size; + v->writeback_chroma_buffer_size = dc->dcn_ip->writeback_chroma_buffer_size; + v->max_num_dpp = dc->dcn_ip->max_num_dpp; + v->max_num_writeback = dc->dcn_ip->max_num_writeback; + v->max_dchub_topscl_throughput = dc->dcn_ip->max_dchub_topscl_throughput; + v->max_pscl_tolb_throughput = dc->dcn_ip->max_pscl_tolb_throughput; + v->max_lb_tovscl_throughput = dc->dcn_ip->max_lb_tovscl_throughput; + v->max_vscl_tohscl_throughput = dc->dcn_ip->max_vscl_tohscl_throughput; + v->max_hscl_ratio = dc->dcn_ip->max_hscl_ratio; + v->max_vscl_ratio = dc->dcn_ip->max_vscl_ratio; + v->max_hscl_taps = dc->dcn_ip->max_hscl_taps; + v->max_vscl_taps = dc->dcn_ip->max_vscl_taps; + v->under_scan_factor = dc->dcn_ip->under_scan_factor; + v->pte_buffer_size_in_requests = dc->dcn_ip->pte_buffer_size_in_requests; + v->dispclk_ramping_margin = dc->dcn_ip->dispclk_ramping_margin; + v->max_inter_dcn_tile_repeaters = dc->dcn_ip->max_inter_dcn_tile_repeaters; v->can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one = - dc->dcn_ip.can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one; + dc->dcn_ip->can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one; v->bug_forcing_luma_and_chroma_request_to_same_size_fixed = - dc->dcn_ip.bug_forcing_luma_and_chroma_request_to_same_size_fixed; + dc->dcn_ip->bug_forcing_luma_and_chroma_request_to_same_size_fixed; v->voltage[5] = dcn_bw_no_support; v->voltage[4] = dcn_bw_v_max0p9; @@ -1021,7 +1021,7 @@ bool dcn_validate_bandwidth( context->bw.dcn.calc_clk.dcfclk_khz = (int)(v->dcfclk * 1000); context->bw.dcn.calc_clk.dispclk_khz = (int)(v->dispclk * 1000); if (dc->public.debug.max_disp_clk == true) - context->bw.dcn.calc_clk.dispclk_khz = (int)(dc->dcn_soc.max_dispclk_vmax0p9 * 1000); + context->bw.dcn.calc_clk.dispclk_khz = (int)(dc->dcn_soc->max_dispclk_vmax0p9 * 1000); context->bw.dcn.calc_clk.dppclk_div = (int)(v->dispclk_dppclk_ratio) == 2; for (i = 0, input_idx = 0; i < pool->pipe_count; i++) { @@ -1118,15 +1118,15 @@ bool dcn_validate_bandwidth( struct core_dc *dc_core = DC_TO_CORE(&dc->public); dc_core->dml.soc.sr_enter_plus_exit_time_us = - dc_core->dcn_soc.sr_enter_plus_exit_time; - dc_core->dml.soc.sr_exit_time_us = dc_core->dcn_soc.sr_exit_time; + dc_core->dcn_soc->sr_enter_plus_exit_time; + dc_core->dml.soc.sr_exit_time_us = dc_core->dcn_soc->sr_exit_time; } /* * BW limit is set to prevent display from impacting other system functions */ - bw_limit = dc->dcn_soc.percent_disp_bw_limit * v->fabric_and_dram_bandwidth_vmax0p9; + bw_limit = dc->dcn_soc->percent_disp_bw_limit * v->fabric_and_dram_bandwidth_vmax0p9; bw_limit_pass = (v->total_data_read_bandwidth / 1000.0) < bw_limit; kernel_fpu_end(); @@ -1149,41 +1149,41 @@ unsigned int dcn_find_normalized_clock_vdd_Level( switch (clocks_type) { case DM_PP_CLOCK_TYPE_DISPLAY_CLK: - if (clocks_in_khz > dc->dcn_soc.max_dispclk_vmax0p9*1000) { + if (clocks_in_khz > dc->dcn_soc->max_dispclk_vmax0p9*1000) { vdd_level = dcn_bw_v_max0p91; BREAK_TO_DEBUGGER(); - } else if (clocks_in_khz > dc->dcn_soc.max_dispclk_vnom0p8*1000) { + } else if (clocks_in_khz > dc->dcn_soc->max_dispclk_vnom0p8*1000) { vdd_level = dcn_bw_v_max0p9; - } else if (clocks_in_khz > dc->dcn_soc.max_dispclk_vmid0p72*1000) { + } else if (clocks_in_khz > dc->dcn_soc->max_dispclk_vmid0p72*1000) { vdd_level = dcn_bw_v_nom0p8; - } else if (clocks_in_khz > dc->dcn_soc.max_dispclk_vmin0p65*1000) { + } else if (clocks_in_khz > dc->dcn_soc->max_dispclk_vmin0p65*1000) { vdd_level = dcn_bw_v_mid0p72; } else vdd_level = dcn_bw_v_min0p65; break; case DM_PP_CLOCK_TYPE_DISPLAYPHYCLK: - if (clocks_in_khz > dc->dcn_soc.phyclkv_max0p9*1000) { + if (clocks_in_khz > dc->dcn_soc->phyclkv_max0p9*1000) { vdd_level = dcn_bw_v_max0p91; BREAK_TO_DEBUGGER(); - } else if (clocks_in_khz > dc->dcn_soc.phyclkv_nom0p8*1000) { + } else if (clocks_in_khz > dc->dcn_soc->phyclkv_nom0p8*1000) { vdd_level = dcn_bw_v_max0p9; - } else if (clocks_in_khz > dc->dcn_soc.phyclkv_mid0p72*1000) { + } else if (clocks_in_khz > dc->dcn_soc->phyclkv_mid0p72*1000) { vdd_level = dcn_bw_v_nom0p8; - } else if (clocks_in_khz > dc->dcn_soc.phyclkv_min0p65*1000) { + } else if (clocks_in_khz > dc->dcn_soc->phyclkv_min0p65*1000) { vdd_level = dcn_bw_v_mid0p72; } else vdd_level = dcn_bw_v_min0p65; break; case DM_PP_CLOCK_TYPE_DPPCLK: - if (clocks_in_khz > dc->dcn_soc.max_dppclk_vmax0p9*1000) { + if (clocks_in_khz > dc->dcn_soc->max_dppclk_vmax0p9*1000) { vdd_level = dcn_bw_v_max0p91; BREAK_TO_DEBUGGER(); - } else if (clocks_in_khz > dc->dcn_soc.max_dppclk_vnom0p8*1000) { + } else if (clocks_in_khz > dc->dcn_soc->max_dppclk_vnom0p8*1000) { vdd_level = dcn_bw_v_max0p9; - } else if (clocks_in_khz > dc->dcn_soc.max_dppclk_vmid0p72*1000) { + } else if (clocks_in_khz > dc->dcn_soc->max_dppclk_vmid0p72*1000) { vdd_level = dcn_bw_v_nom0p8; - } else if (clocks_in_khz > dc->dcn_soc.max_dppclk_vmin0p65*1000) { + } else if (clocks_in_khz > dc->dcn_soc->max_dppclk_vmin0p65*1000) { vdd_level = dcn_bw_v_mid0p72; } else vdd_level = dcn_bw_v_min0p65; @@ -1191,15 +1191,16 @@ unsigned int dcn_find_normalized_clock_vdd_Level( case DM_PP_CLOCK_TYPE_MEMORY_CLK: { - unsigned factor = (ddr4_dram_factor_single_Channel * dc->dcn_soc.number_of_channels); - if (clocks_in_khz > dc->dcn_soc.fabric_and_dram_bandwidth_vmax0p9*1000000/factor) { + unsigned factor = (ddr4_dram_factor_single_Channel * dc->dcn_soc->number_of_channels); + + if (clocks_in_khz > dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9*1000000/factor) { vdd_level = dcn_bw_v_max0p91; BREAK_TO_DEBUGGER(); - } else if (clocks_in_khz > dc->dcn_soc.fabric_and_dram_bandwidth_vnom0p8*1000000/factor) { + } else if (clocks_in_khz > dc->dcn_soc->fabric_and_dram_bandwidth_vnom0p8*1000000/factor) { vdd_level = dcn_bw_v_max0p9; - } else if (clocks_in_khz > dc->dcn_soc.fabric_and_dram_bandwidth_vmid0p72*1000000/factor) { + } else if (clocks_in_khz > dc->dcn_soc->fabric_and_dram_bandwidth_vmid0p72*1000000/factor) { vdd_level = dcn_bw_v_nom0p8; - } else if (clocks_in_khz > dc->dcn_soc.fabric_and_dram_bandwidth_vmin0p65*1000000/factor) { + } else if (clocks_in_khz > dc->dcn_soc->fabric_and_dram_bandwidth_vmin0p65*1000000/factor) { vdd_level = dcn_bw_v_mid0p72; } else vdd_level = dcn_bw_v_min0p65; @@ -1207,14 +1208,14 @@ unsigned int dcn_find_normalized_clock_vdd_Level( break; case DM_PP_CLOCK_TYPE_DCFCLK: - if (clocks_in_khz > dc->dcn_soc.dcfclkv_max0p9*1000) { + if (clocks_in_khz > dc->dcn_soc->dcfclkv_max0p9*1000) { vdd_level = dcn_bw_v_max0p91; BREAK_TO_DEBUGGER(); - } else if (clocks_in_khz > dc->dcn_soc.dcfclkv_nom0p8*1000) { + } else if (clocks_in_khz > dc->dcn_soc->dcfclkv_nom0p8*1000) { vdd_level = dcn_bw_v_max0p9; - } else if (clocks_in_khz > dc->dcn_soc.dcfclkv_mid0p72*1000) { + } else if (clocks_in_khz > dc->dcn_soc->dcfclkv_mid0p72*1000) { vdd_level = dcn_bw_v_nom0p8; - } else if (clocks_in_khz > dc->dcn_soc.dcfclkv_min0p65*1000) { + } else if (clocks_in_khz > dc->dcn_soc->dcfclkv_min0p65*1000) { vdd_level = dcn_bw_v_mid0p72; } else vdd_level = dcn_bw_v_min0p65; @@ -1254,15 +1255,15 @@ unsigned int dcn_find_dcfclk_suits_all( vdd_level = dcn_bw_max(vdd_level, vdd_level_temp); if (vdd_level == dcn_bw_v_max0p91) { BREAK_TO_DEBUGGER(); - dcf_clk = dc->dcn_soc.dcfclkv_max0p9*1000; + dcf_clk = dc->dcn_soc->dcfclkv_max0p9*1000; } else if (vdd_level == dcn_bw_v_max0p9) - dcf_clk = dc->dcn_soc.dcfclkv_max0p9*1000; + dcf_clk = dc->dcn_soc->dcfclkv_max0p9*1000; else if (vdd_level == dcn_bw_v_nom0p8) - dcf_clk = dc->dcn_soc.dcfclkv_nom0p8*1000; + dcf_clk = dc->dcn_soc->dcfclkv_nom0p8*1000; else if (vdd_level == dcn_bw_v_mid0p72) - dcf_clk = dc->dcn_soc.dcfclkv_mid0p72*1000; + dcf_clk = dc->dcn_soc->dcfclkv_mid0p72*1000; else - dcf_clk = dc->dcn_soc.dcfclkv_min0p65*1000; + dcf_clk = dc->dcn_soc->dcfclkv_min0p65*1000; dm_logger_write(dc->ctx->logger, LOG_HW_MARKS, "\tdcf_clk for voltage = %d\n", dcf_clk); @@ -1282,27 +1283,27 @@ void dcn_bw_update_from_pplib(struct core_dc *dc) ctx, DM_PP_CLOCK_TYPE_FCLK, &clks) && clks.num_levels != 0) { ASSERT(clks.num_levels >= 3); - dc->dcn_soc.fabric_and_dram_bandwidth_vmin0p65 = 32 * (clks.data[0].clocks_in_khz / 1000.0) / 1000.0; + dc->dcn_soc->fabric_and_dram_bandwidth_vmin0p65 = 32 * (clks.data[0].clocks_in_khz / 1000.0) / 1000.0; if (clks.num_levels > 2) { - dc->dcn_soc.fabric_and_dram_bandwidth_vmid0p72 = dc->dcn_soc.number_of_channels * + dc->dcn_soc->fabric_and_dram_bandwidth_vmid0p72 = dc->dcn_soc->number_of_channels * (clks.data[clks.num_levels - 3].clocks_in_khz / 1000.0) * ddr4_dram_factor_single_Channel / 1000.0; } else { - dc->dcn_soc.fabric_and_dram_bandwidth_vmid0p72 = dc->dcn_soc.number_of_channels * + dc->dcn_soc->fabric_and_dram_bandwidth_vmid0p72 = dc->dcn_soc->number_of_channels * (clks.data[clks.num_levels - 2].clocks_in_khz / 1000.0) * ddr4_dram_factor_single_Channel / 1000.0; } - dc->dcn_soc.fabric_and_dram_bandwidth_vnom0p8 = dc->dcn_soc.number_of_channels * + dc->dcn_soc->fabric_and_dram_bandwidth_vnom0p8 = dc->dcn_soc->number_of_channels * (clks.data[clks.num_levels - 2].clocks_in_khz / 1000.0) * ddr4_dram_factor_single_Channel / 1000.0; - dc->dcn_soc.fabric_and_dram_bandwidth_vmax0p9 = dc->dcn_soc.number_of_channels * + dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9 = dc->dcn_soc->number_of_channels * (clks.data[clks.num_levels - 1].clocks_in_khz / 1000.0) * ddr4_dram_factor_single_Channel / 1000.0; } else BREAK_TO_DEBUGGER(); if (dm_pp_get_clock_levels_by_type_with_voltage( ctx, DM_PP_CLOCK_TYPE_DCFCLK, &clks) && clks.num_levels >= 3) { - dc->dcn_soc.dcfclkv_min0p65 = clks.data[0].clocks_in_khz / 1000.0; - dc->dcn_soc.dcfclkv_mid0p72 = clks.data[clks.num_levels - 3].clocks_in_khz / 1000.0; - dc->dcn_soc.dcfclkv_nom0p8 = clks.data[clks.num_levels - 2].clocks_in_khz / 1000.0; - dc->dcn_soc.dcfclkv_max0p9 = clks.data[clks.num_levels - 1].clocks_in_khz / 1000.0; + dc->dcn_soc->dcfclkv_min0p65 = clks.data[0].clocks_in_khz / 1000.0; + dc->dcn_soc->dcfclkv_mid0p72 = clks.data[clks.num_levels - 3].clocks_in_khz / 1000.0; + dc->dcn_soc->dcfclkv_nom0p8 = clks.data[clks.num_levels - 2].clocks_in_khz / 1000.0; + dc->dcn_soc->dcfclkv_max0p9 = clks.data[clks.num_levels - 1].clocks_in_khz / 1000.0; } else BREAK_TO_DEBUGGER(); @@ -1315,17 +1316,17 @@ void dcn_bw_notify_pplib_of_wm_ranges(struct core_dc *dc) int max_fclk_khz, nom_fclk_khz, min_fclk_khz, max_dcfclk_khz, nom_dcfclk_khz, mid_fclk_khz, min_dcfclk_khz, socclk_khz; const int overdrive = 5000000; /* 5 GHz to cover Overdrive */ - unsigned factor = (ddr4_dram_factor_single_Channel * dc->dcn_soc.number_of_channels); + unsigned factor = (ddr4_dram_factor_single_Channel * dc->dcn_soc->number_of_channels); kernel_fpu_begin(); - max_fclk_khz = dc->dcn_soc.fabric_and_dram_bandwidth_vmax0p9 * 1000000 / factor; - nom_fclk_khz = dc->dcn_soc.fabric_and_dram_bandwidth_vnom0p8 * 1000000 / factor; - mid_fclk_khz = dc->dcn_soc.fabric_and_dram_bandwidth_vmid0p72 * 1000000 / factor; - min_fclk_khz = dc->dcn_soc.fabric_and_dram_bandwidth_vmin0p65 * 1000000 / 32; - max_dcfclk_khz = dc->dcn_soc.dcfclkv_max0p9 * 1000; - nom_dcfclk_khz = dc->dcn_soc.dcfclkv_nom0p8 * 1000; - min_dcfclk_khz = dc->dcn_soc.dcfclkv_min0p65 * 1000; - socclk_khz = dc->dcn_soc.socclk * 1000; + max_fclk_khz = dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9 * 1000000 / factor; + nom_fclk_khz = dc->dcn_soc->fabric_and_dram_bandwidth_vnom0p8 * 1000000 / factor; + mid_fclk_khz = dc->dcn_soc->fabric_and_dram_bandwidth_vmid0p72 * 1000000 / factor; + min_fclk_khz = dc->dcn_soc->fabric_and_dram_bandwidth_vmin0p65 * 1000000 / 32; + max_dcfclk_khz = dc->dcn_soc->dcfclkv_max0p9 * 1000; + nom_dcfclk_khz = dc->dcn_soc->dcfclkv_nom0p8 * 1000; + min_dcfclk_khz = dc->dcn_soc->dcfclkv_min0p65 * 1000; + socclk_khz = dc->dcn_soc->socclk * 1000; kernel_fpu_end(); /* Now notify PPLib/SMU about which Watermarks sets they should select @@ -1425,40 +1426,40 @@ void dcn_bw_sync_calcs_and_dml(struct core_dc *dc) "vmm_page_size: %d Bytes\n" "dram_clock_change_latency: %d ns\n" "return_bus_width: %d Bytes\n", - dc->dcn_soc.sr_exit_time * 1000, - dc->dcn_soc.sr_enter_plus_exit_time * 1000, - dc->dcn_soc.urgent_latency * 1000, - dc->dcn_soc.write_back_latency * 1000, - dc->dcn_soc.percent_of_ideal_drambw_received_after_urg_latency, - dc->dcn_soc.max_request_size, - dc->dcn_soc.dcfclkv_max0p9 * 1000, - dc->dcn_soc.dcfclkv_nom0p8 * 1000, - dc->dcn_soc.dcfclkv_mid0p72 * 1000, - dc->dcn_soc.dcfclkv_min0p65 * 1000, - dc->dcn_soc.max_dispclk_vmax0p9 * 1000, - dc->dcn_soc.max_dispclk_vnom0p8 * 1000, - dc->dcn_soc.max_dispclk_vmid0p72 * 1000, - dc->dcn_soc.max_dispclk_vmin0p65 * 1000, - dc->dcn_soc.max_dppclk_vmax0p9 * 1000, - dc->dcn_soc.max_dppclk_vnom0p8 * 1000, - dc->dcn_soc.max_dppclk_vmid0p72 * 1000, - dc->dcn_soc.max_dppclk_vmin0p65 * 1000, - dc->dcn_soc.socclk * 1000, - dc->dcn_soc.fabric_and_dram_bandwidth_vmax0p9 * 1000, - dc->dcn_soc.fabric_and_dram_bandwidth_vnom0p8 * 1000, - dc->dcn_soc.fabric_and_dram_bandwidth_vmid0p72 * 1000, - dc->dcn_soc.fabric_and_dram_bandwidth_vmin0p65 * 1000, - dc->dcn_soc.phyclkv_max0p9 * 1000, - dc->dcn_soc.phyclkv_nom0p8 * 1000, - dc->dcn_soc.phyclkv_mid0p72 * 1000, - dc->dcn_soc.phyclkv_min0p65 * 1000, - dc->dcn_soc.downspreading * 100, - dc->dcn_soc.round_trip_ping_latency_cycles, - dc->dcn_soc.urgent_out_of_order_return_per_channel, - dc->dcn_soc.number_of_channels, - dc->dcn_soc.vmm_page_size, - dc->dcn_soc.dram_clock_change_latency * 1000, - dc->dcn_soc.return_bus_width); + dc->dcn_soc->sr_exit_time * 1000, + dc->dcn_soc->sr_enter_plus_exit_time * 1000, + dc->dcn_soc->urgent_latency * 1000, + dc->dcn_soc->write_back_latency * 1000, + dc->dcn_soc->percent_of_ideal_drambw_received_after_urg_latency, + dc->dcn_soc->max_request_size, + dc->dcn_soc->dcfclkv_max0p9 * 1000, + dc->dcn_soc->dcfclkv_nom0p8 * 1000, + dc->dcn_soc->dcfclkv_mid0p72 * 1000, + dc->dcn_soc->dcfclkv_min0p65 * 1000, + dc->dcn_soc->max_dispclk_vmax0p9 * 1000, + dc->dcn_soc->max_dispclk_vnom0p8 * 1000, + dc->dcn_soc->max_dispclk_vmid0p72 * 1000, + dc->dcn_soc->max_dispclk_vmin0p65 * 1000, + dc->dcn_soc->max_dppclk_vmax0p9 * 1000, + dc->dcn_soc->max_dppclk_vnom0p8 * 1000, + dc->dcn_soc->max_dppclk_vmid0p72 * 1000, + dc->dcn_soc->max_dppclk_vmin0p65 * 1000, + dc->dcn_soc->socclk * 1000, + dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9 * 1000, + dc->dcn_soc->fabric_and_dram_bandwidth_vnom0p8 * 1000, + dc->dcn_soc->fabric_and_dram_bandwidth_vmid0p72 * 1000, + dc->dcn_soc->fabric_and_dram_bandwidth_vmin0p65 * 1000, + dc->dcn_soc->phyclkv_max0p9 * 1000, + dc->dcn_soc->phyclkv_nom0p8 * 1000, + dc->dcn_soc->phyclkv_mid0p72 * 1000, + dc->dcn_soc->phyclkv_min0p65 * 1000, + dc->dcn_soc->downspreading * 100, + dc->dcn_soc->round_trip_ping_latency_cycles, + dc->dcn_soc->urgent_out_of_order_return_per_channel, + dc->dcn_soc->number_of_channels, + dc->dcn_soc->vmm_page_size, + dc->dcn_soc->dram_clock_change_latency * 1000, + dc->dcn_soc->return_bus_width); dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_CALCS, "rob_buffer_size_in_kbyte: %d\n" "det_buffer_size_in_kbyte: %d\n" @@ -1494,120 +1495,120 @@ void dcn_bw_sync_calcs_and_dml(struct core_dc *dc) "can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one: %d\n" "bug_forcing_luma_and_chroma_request_to_same_size_fixed: %d\n" "dcfclk_cstate_latency: %d\n", - dc->dcn_ip.rob_buffer_size_in_kbyte, - dc->dcn_ip.det_buffer_size_in_kbyte, - dc->dcn_ip.dpp_output_buffer_pixels, - dc->dcn_ip.opp_output_buffer_lines, - dc->dcn_ip.pixel_chunk_size_in_kbyte, - dc->dcn_ip.pte_enable, - dc->dcn_ip.pte_chunk_size, - dc->dcn_ip.meta_chunk_size, - dc->dcn_ip.writeback_chunk_size, - dc->dcn_ip.odm_capability, - dc->dcn_ip.dsc_capability, - dc->dcn_ip.line_buffer_size, - dc->dcn_ip.max_line_buffer_lines, - dc->dcn_ip.is_line_buffer_bpp_fixed, - dc->dcn_ip.line_buffer_fixed_bpp, - dc->dcn_ip.writeback_luma_buffer_size, - dc->dcn_ip.writeback_chroma_buffer_size, - dc->dcn_ip.max_num_dpp, - dc->dcn_ip.max_num_writeback, - dc->dcn_ip.max_dchub_topscl_throughput, - dc->dcn_ip.max_pscl_tolb_throughput, - dc->dcn_ip.max_lb_tovscl_throughput, - dc->dcn_ip.max_vscl_tohscl_throughput, - dc->dcn_ip.max_hscl_ratio, - dc->dcn_ip.max_vscl_ratio, - dc->dcn_ip.max_hscl_taps, - dc->dcn_ip.max_vscl_taps, - dc->dcn_ip.pte_buffer_size_in_requests, - dc->dcn_ip.dispclk_ramping_margin, - dc->dcn_ip.under_scan_factor * 100, - dc->dcn_ip.max_inter_dcn_tile_repeaters, - dc->dcn_ip.can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one, - dc->dcn_ip.bug_forcing_luma_and_chroma_request_to_same_size_fixed, - dc->dcn_ip.dcfclk_cstate_latency); - dc->dml.soc.vmin.socclk_mhz = dc->dcn_soc.socclk; - dc->dml.soc.vmid.socclk_mhz = dc->dcn_soc.socclk; - dc->dml.soc.vnom.socclk_mhz = dc->dcn_soc.socclk; - dc->dml.soc.vmax.socclk_mhz = dc->dcn_soc.socclk; - - dc->dml.soc.vmin.dcfclk_mhz = dc->dcn_soc.dcfclkv_min0p65; - dc->dml.soc.vmid.dcfclk_mhz = dc->dcn_soc.dcfclkv_mid0p72; - dc->dml.soc.vnom.dcfclk_mhz = dc->dcn_soc.dcfclkv_nom0p8; - dc->dml.soc.vmax.dcfclk_mhz = dc->dcn_soc.dcfclkv_max0p9; - - dc->dml.soc.vmin.dispclk_mhz = dc->dcn_soc.max_dispclk_vmin0p65; - dc->dml.soc.vmid.dispclk_mhz = dc->dcn_soc.max_dispclk_vmid0p72; - dc->dml.soc.vnom.dispclk_mhz = dc->dcn_soc.max_dispclk_vnom0p8; - dc->dml.soc.vmax.dispclk_mhz = dc->dcn_soc.max_dispclk_vmax0p9; - - dc->dml.soc.vmin.dppclk_mhz = dc->dcn_soc.max_dppclk_vmin0p65; - dc->dml.soc.vmid.dppclk_mhz = dc->dcn_soc.max_dppclk_vmid0p72; - dc->dml.soc.vnom.dppclk_mhz = dc->dcn_soc.max_dppclk_vnom0p8; - dc->dml.soc.vmax.dppclk_mhz = dc->dcn_soc.max_dppclk_vmax0p9; - - dc->dml.soc.vmin.phyclk_mhz = dc->dcn_soc.phyclkv_min0p65; - dc->dml.soc.vmid.phyclk_mhz = dc->dcn_soc.phyclkv_mid0p72; - dc->dml.soc.vnom.phyclk_mhz = dc->dcn_soc.phyclkv_nom0p8; - dc->dml.soc.vmax.phyclk_mhz = dc->dcn_soc.phyclkv_max0p9; - - dc->dml.soc.vmin.dram_bw_per_chan_gbps = dc->dcn_soc.fabric_and_dram_bandwidth_vmin0p65; - dc->dml.soc.vmid.dram_bw_per_chan_gbps = dc->dcn_soc.fabric_and_dram_bandwidth_vmid0p72; - dc->dml.soc.vnom.dram_bw_per_chan_gbps = dc->dcn_soc.fabric_and_dram_bandwidth_vnom0p8; - dc->dml.soc.vmax.dram_bw_per_chan_gbps = dc->dcn_soc.fabric_and_dram_bandwidth_vmax0p9; - - dc->dml.soc.sr_exit_time_us = dc->dcn_soc.sr_exit_time; - dc->dml.soc.sr_enter_plus_exit_time_us = dc->dcn_soc.sr_enter_plus_exit_time; - dc->dml.soc.urgent_latency_us = dc->dcn_soc.urgent_latency; - dc->dml.soc.writeback_latency_us = dc->dcn_soc.write_back_latency; + dc->dcn_ip->rob_buffer_size_in_kbyte, + dc->dcn_ip->det_buffer_size_in_kbyte, + dc->dcn_ip->dpp_output_buffer_pixels, + dc->dcn_ip->opp_output_buffer_lines, + dc->dcn_ip->pixel_chunk_size_in_kbyte, + dc->dcn_ip->pte_enable, + dc->dcn_ip->pte_chunk_size, + dc->dcn_ip->meta_chunk_size, + dc->dcn_ip->writeback_chunk_size, + dc->dcn_ip->odm_capability, + dc->dcn_ip->dsc_capability, + dc->dcn_ip->line_buffer_size, + dc->dcn_ip->max_line_buffer_lines, + dc->dcn_ip->is_line_buffer_bpp_fixed, + dc->dcn_ip->line_buffer_fixed_bpp, + dc->dcn_ip->writeback_luma_buffer_size, + dc->dcn_ip->writeback_chroma_buffer_size, + dc->dcn_ip->max_num_dpp, + dc->dcn_ip->max_num_writeback, + dc->dcn_ip->max_dchub_topscl_throughput, + dc->dcn_ip->max_pscl_tolb_throughput, + dc->dcn_ip->max_lb_tovscl_throughput, + dc->dcn_ip->max_vscl_tohscl_throughput, + dc->dcn_ip->max_hscl_ratio, + dc->dcn_ip->max_vscl_ratio, + dc->dcn_ip->max_hscl_taps, + dc->dcn_ip->max_vscl_taps, + dc->dcn_ip->pte_buffer_size_in_requests, + dc->dcn_ip->dispclk_ramping_margin, + dc->dcn_ip->under_scan_factor * 100, + dc->dcn_ip->max_inter_dcn_tile_repeaters, + dc->dcn_ip->can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one, + dc->dcn_ip->bug_forcing_luma_and_chroma_request_to_same_size_fixed, + dc->dcn_ip->dcfclk_cstate_latency); + dc->dml.soc.vmin.socclk_mhz = dc->dcn_soc->socclk; + dc->dml.soc.vmid.socclk_mhz = dc->dcn_soc->socclk; + dc->dml.soc.vnom.socclk_mhz = dc->dcn_soc->socclk; + dc->dml.soc.vmax.socclk_mhz = dc->dcn_soc->socclk; + + dc->dml.soc.vmin.dcfclk_mhz = dc->dcn_soc->dcfclkv_min0p65; + dc->dml.soc.vmid.dcfclk_mhz = dc->dcn_soc->dcfclkv_mid0p72; + dc->dml.soc.vnom.dcfclk_mhz = dc->dcn_soc->dcfclkv_nom0p8; + dc->dml.soc.vmax.dcfclk_mhz = dc->dcn_soc->dcfclkv_max0p9; + + dc->dml.soc.vmin.dispclk_mhz = dc->dcn_soc->max_dispclk_vmin0p65; + dc->dml.soc.vmid.dispclk_mhz = dc->dcn_soc->max_dispclk_vmid0p72; + dc->dml.soc.vnom.dispclk_mhz = dc->dcn_soc->max_dispclk_vnom0p8; + dc->dml.soc.vmax.dispclk_mhz = dc->dcn_soc->max_dispclk_vmax0p9; + + dc->dml.soc.vmin.dppclk_mhz = dc->dcn_soc->max_dppclk_vmin0p65; + dc->dml.soc.vmid.dppclk_mhz = dc->dcn_soc->max_dppclk_vmid0p72; + dc->dml.soc.vnom.dppclk_mhz = dc->dcn_soc->max_dppclk_vnom0p8; + dc->dml.soc.vmax.dppclk_mhz = dc->dcn_soc->max_dppclk_vmax0p9; + + dc->dml.soc.vmin.phyclk_mhz = dc->dcn_soc->phyclkv_min0p65; + dc->dml.soc.vmid.phyclk_mhz = dc->dcn_soc->phyclkv_mid0p72; + dc->dml.soc.vnom.phyclk_mhz = dc->dcn_soc->phyclkv_nom0p8; + dc->dml.soc.vmax.phyclk_mhz = dc->dcn_soc->phyclkv_max0p9; + + dc->dml.soc.vmin.dram_bw_per_chan_gbps = dc->dcn_soc->fabric_and_dram_bandwidth_vmin0p65; + dc->dml.soc.vmid.dram_bw_per_chan_gbps = dc->dcn_soc->fabric_and_dram_bandwidth_vmid0p72; + dc->dml.soc.vnom.dram_bw_per_chan_gbps = dc->dcn_soc->fabric_and_dram_bandwidth_vnom0p8; + dc->dml.soc.vmax.dram_bw_per_chan_gbps = dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9; + + dc->dml.soc.sr_exit_time_us = dc->dcn_soc->sr_exit_time; + dc->dml.soc.sr_enter_plus_exit_time_us = dc->dcn_soc->sr_enter_plus_exit_time; + dc->dml.soc.urgent_latency_us = dc->dcn_soc->urgent_latency; + dc->dml.soc.writeback_latency_us = dc->dcn_soc->write_back_latency; dc->dml.soc.ideal_dram_bw_after_urgent_percent = - dc->dcn_soc.percent_of_ideal_drambw_received_after_urg_latency; - dc->dml.soc.max_request_size_bytes = dc->dcn_soc.max_request_size; - dc->dml.soc.downspread_percent = dc->dcn_soc.downspreading; + dc->dcn_soc->percent_of_ideal_drambw_received_after_urg_latency; + dc->dml.soc.max_request_size_bytes = dc->dcn_soc->max_request_size; + dc->dml.soc.downspread_percent = dc->dcn_soc->downspreading; dc->dml.soc.round_trip_ping_latency_dcfclk_cycles = - dc->dcn_soc.round_trip_ping_latency_cycles; + dc->dcn_soc->round_trip_ping_latency_cycles; dc->dml.soc.urgent_out_of_order_return_per_channel_bytes = - dc->dcn_soc.urgent_out_of_order_return_per_channel; - dc->dml.soc.num_chans = dc->dcn_soc.number_of_channels; - dc->dml.soc.vmm_page_size_bytes = dc->dcn_soc.vmm_page_size; - dc->dml.soc.dram_clock_change_latency_us = dc->dcn_soc.dram_clock_change_latency; - dc->dml.soc.return_bus_width_bytes = dc->dcn_soc.return_bus_width; - - dc->dml.ip.rob_buffer_size_kbytes = dc->dcn_ip.rob_buffer_size_in_kbyte; - dc->dml.ip.det_buffer_size_kbytes = dc->dcn_ip.det_buffer_size_in_kbyte; - dc->dml.ip.dpp_output_buffer_pixels = dc->dcn_ip.dpp_output_buffer_pixels; - dc->dml.ip.opp_output_buffer_lines = dc->dcn_ip.opp_output_buffer_lines; - dc->dml.ip.pixel_chunk_size_kbytes = dc->dcn_ip.pixel_chunk_size_in_kbyte; - dc->dml.ip.pte_enable = dc->dcn_ip.pte_enable == dcn_bw_yes; - dc->dml.ip.pte_chunk_size_kbytes = dc->dcn_ip.pte_chunk_size; - dc->dml.ip.meta_chunk_size_kbytes = dc->dcn_ip.meta_chunk_size; - dc->dml.ip.writeback_chunk_size_kbytes = dc->dcn_ip.writeback_chunk_size; - dc->dml.ip.line_buffer_size_bits = dc->dcn_ip.line_buffer_size; - dc->dml.ip.max_line_buffer_lines = dc->dcn_ip.max_line_buffer_lines; - dc->dml.ip.IsLineBufferBppFixed = dc->dcn_ip.is_line_buffer_bpp_fixed == dcn_bw_yes; - dc->dml.ip.LineBufferFixedBpp = dc->dcn_ip.line_buffer_fixed_bpp; - dc->dml.ip.writeback_luma_buffer_size_kbytes = dc->dcn_ip.writeback_luma_buffer_size; - dc->dml.ip.writeback_chroma_buffer_size_kbytes = dc->dcn_ip.writeback_chroma_buffer_size; - dc->dml.ip.max_num_dpp = dc->dcn_ip.max_num_dpp; - dc->dml.ip.max_num_wb = dc->dcn_ip.max_num_writeback; - dc->dml.ip.max_dchub_pscl_bw_pix_per_clk = dc->dcn_ip.max_dchub_topscl_throughput; - dc->dml.ip.max_pscl_lb_bw_pix_per_clk = dc->dcn_ip.max_pscl_tolb_throughput; - dc->dml.ip.max_lb_vscl_bw_pix_per_clk = dc->dcn_ip.max_lb_tovscl_throughput; - dc->dml.ip.max_vscl_hscl_bw_pix_per_clk = dc->dcn_ip.max_vscl_tohscl_throughput; - dc->dml.ip.max_hscl_ratio = dc->dcn_ip.max_hscl_ratio; - dc->dml.ip.max_vscl_ratio = dc->dcn_ip.max_vscl_ratio; - dc->dml.ip.max_hscl_taps = dc->dcn_ip.max_hscl_taps; - dc->dml.ip.max_vscl_taps = dc->dcn_ip.max_vscl_taps; + dc->dcn_soc->urgent_out_of_order_return_per_channel; + dc->dml.soc.num_chans = dc->dcn_soc->number_of_channels; + dc->dml.soc.vmm_page_size_bytes = dc->dcn_soc->vmm_page_size; + dc->dml.soc.dram_clock_change_latency_us = dc->dcn_soc->dram_clock_change_latency; + dc->dml.soc.return_bus_width_bytes = dc->dcn_soc->return_bus_width; + + dc->dml.ip.rob_buffer_size_kbytes = dc->dcn_ip->rob_buffer_size_in_kbyte; + dc->dml.ip.det_buffer_size_kbytes = dc->dcn_ip->det_buffer_size_in_kbyte; + dc->dml.ip.dpp_output_buffer_pixels = dc->dcn_ip->dpp_output_buffer_pixels; + dc->dml.ip.opp_output_buffer_lines = dc->dcn_ip->opp_output_buffer_lines; + dc->dml.ip.pixel_chunk_size_kbytes = dc->dcn_ip->pixel_chunk_size_in_kbyte; + dc->dml.ip.pte_enable = dc->dcn_ip->pte_enable == dcn_bw_yes; + dc->dml.ip.pte_chunk_size_kbytes = dc->dcn_ip->pte_chunk_size; + dc->dml.ip.meta_chunk_size_kbytes = dc->dcn_ip->meta_chunk_size; + dc->dml.ip.writeback_chunk_size_kbytes = dc->dcn_ip->writeback_chunk_size; + dc->dml.ip.line_buffer_size_bits = dc->dcn_ip->line_buffer_size; + dc->dml.ip.max_line_buffer_lines = dc->dcn_ip->max_line_buffer_lines; + dc->dml.ip.IsLineBufferBppFixed = dc->dcn_ip->is_line_buffer_bpp_fixed == dcn_bw_yes; + dc->dml.ip.LineBufferFixedBpp = dc->dcn_ip->line_buffer_fixed_bpp; + dc->dml.ip.writeback_luma_buffer_size_kbytes = dc->dcn_ip->writeback_luma_buffer_size; + dc->dml.ip.writeback_chroma_buffer_size_kbytes = dc->dcn_ip->writeback_chroma_buffer_size; + dc->dml.ip.max_num_dpp = dc->dcn_ip->max_num_dpp; + dc->dml.ip.max_num_wb = dc->dcn_ip->max_num_writeback; + dc->dml.ip.max_dchub_pscl_bw_pix_per_clk = dc->dcn_ip->max_dchub_topscl_throughput; + dc->dml.ip.max_pscl_lb_bw_pix_per_clk = dc->dcn_ip->max_pscl_tolb_throughput; + dc->dml.ip.max_lb_vscl_bw_pix_per_clk = dc->dcn_ip->max_lb_tovscl_throughput; + dc->dml.ip.max_vscl_hscl_bw_pix_per_clk = dc->dcn_ip->max_vscl_tohscl_throughput; + dc->dml.ip.max_hscl_ratio = dc->dcn_ip->max_hscl_ratio; + dc->dml.ip.max_vscl_ratio = dc->dcn_ip->max_vscl_ratio; + dc->dml.ip.max_hscl_taps = dc->dcn_ip->max_hscl_taps; + dc->dml.ip.max_vscl_taps = dc->dcn_ip->max_vscl_taps; /*pte_buffer_size_in_requests missing in dml*/ - dc->dml.ip.dispclk_ramp_margin_percent = dc->dcn_ip.dispclk_ramping_margin; - dc->dml.ip.underscan_factor = dc->dcn_ip.under_scan_factor; - dc->dml.ip.max_inter_dcn_tile_repeaters = dc->dcn_ip.max_inter_dcn_tile_repeaters; + dc->dml.ip.dispclk_ramp_margin_percent = dc->dcn_ip->dispclk_ramping_margin; + dc->dml.ip.underscan_factor = dc->dcn_ip->under_scan_factor; + dc->dml.ip.max_inter_dcn_tile_repeaters = dc->dcn_ip->max_inter_dcn_tile_repeaters; dc->dml.ip.can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one = - dc->dcn_ip.can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one == dcn_bw_yes; + dc->dcn_ip->can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one == dcn_bw_yes; dc->dml.ip.bug_forcing_LC_req_same_size_fixed = - dc->dcn_ip.bug_forcing_luma_and_chroma_request_to_same_size_fixed == dcn_bw_yes; - dc->dml.ip.dcfclk_cstate_latency = dc->dcn_ip.dcfclk_cstate_latency; + dc->dcn_ip->bug_forcing_luma_and_chroma_request_to_same_size_fixed == dcn_bw_yes; + dc->dml.ip.dcfclk_cstate_latency = dc->dcn_ip->dcfclk_cstate_latency; kernel_fpu_end(); } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 33c3d88b1c86..40d65b758994 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -440,6 +440,13 @@ static void destruct(struct core_dc *dc) dm_free(dc->bw_dceip); dc->bw_dceip = NULL; +#ifdef CONFIG_DRM_AMD_DC_DCN1_0 + dm_free(dc->dcn_soc); + dc->dcn_soc = NULL; + + dm_free(dc->dcn_ip); + dc->dcn_ip = NULL; +#endif } static bool construct(struct core_dc *dc, @@ -449,33 +456,52 @@ static bool construct(struct core_dc *dc, struct dc_context *dc_ctx = dm_alloc(sizeof(*dc_ctx)); struct bw_calcs_dceip *dc_dceip = dm_alloc(sizeof(*dc_dceip)); struct bw_calcs_vbios *dc_vbios = dm_alloc(sizeof(*dc_vbios)); +#ifdef CONFIG_DRM_AMD_DC_DCN1_0 + struct dcn_soc_bounding_box *dcn_soc = dm_alloc(sizeof(*dcn_soc)); + struct dcn_ip_params *dcn_ip = dm_alloc(sizeof(*dcn_ip)); +#endif enum dce_version dc_version = DCE_VERSION_UNKNOWN; if (!dc_dceip) { dm_error("%s: failed to create dceip\n", __func__); - goto dceip_fail; + goto fail; } dc->bw_dceip = dc_dceip; if (!dc_vbios) { dm_error("%s: failed to create vbios\n", __func__); - goto vbios_fail; + goto fail; } dc->bw_vbios = dc_vbios; +#ifdef CONFIG_DRM_AMD_DC_DCN1_0 + if (!dcn_soc) { + dm_error("%s: failed to create dcn_soc\n", __func__); + goto fail; + } + + dc->dcn_soc = dcn_soc; + + if (!dcn_ip) { + dm_error("%s: failed to create dcn_ip\n", __func__); + goto fail; + } + + dc->dcn_ip = dcn_ip; +#endif if (!dc_ctx) { dm_error("%s: failed to create ctx\n", __func__); - goto ctx_fail; + goto fail; } dc->current_context = dm_alloc(sizeof(*dc->current_context)); if (!dc->current_context) { dm_error("%s: failed to create validate ctx\n", __func__); - goto val_ctx_fail; + goto fail; } atomic_inc(&dc->current_context->ref_count); @@ -491,7 +517,7 @@ static bool construct(struct core_dc *dc, if (!logger) { /* can *not* call logger. call base driver 'print error' */ dm_error("%s: failed to create Logger!\n", __func__); - goto logger_fail; + goto fail; } dc_ctx->logger = logger; dc->ctx = dc_ctx; @@ -519,7 +545,7 @@ static bool construct(struct core_dc *dc, if (!dc_ctx->dc_bios) { ASSERT_CRITICAL(false); - goto bios_fail; + goto fail; } dc_ctx->created_bios = true; @@ -530,7 +556,7 @@ static bool construct(struct core_dc *dc, if (!dc_ctx->i2caux) { ASSERT_CRITICAL(false); - goto failed_to_create_i2caux; + goto fail; } /* Create GPIO service */ @@ -541,7 +567,7 @@ static bool construct(struct core_dc *dc, if (!dc_ctx->gpio_service) { ASSERT_CRITICAL(false); - goto gpio_fail; + goto fail; } dc->res_pool = dc_create_resource_pool( @@ -550,26 +576,17 @@ static bool construct(struct core_dc *dc, dc_version, init_params->asic_id); if (!dc->res_pool) - goto create_resource_fail; + goto fail; if (!create_links(dc, init_params->num_virtual_links)) - goto create_links_fail; + goto fail; allocate_dc_stream_funcs(dc); return true; - /**** error handling here ****/ -create_links_fail: -create_resource_fail: -gpio_fail: -failed_to_create_i2caux: -bios_fail: -logger_fail: -val_ctx_fail: -ctx_fail: -dceip_fail: -vbios_fail: +fail: + destruct(dc); return false; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index fa990a51ac83..c36843d497ac 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -1322,28 +1322,28 @@ static bool construct( } dml_init_instance(&dc->dml, DML_PROJECT_RAVEN1); - dc->dcn_ip = dcn10_ip_defaults; - dc->dcn_soc = dcn10_soc_defaults; + memcpy(dc->dcn_ip, &dcn10_ip_defaults, sizeof(dcn10_ip_defaults)); + memcpy(dc->dcn_soc, &dcn10_soc_defaults, sizeof(dcn10_soc_defaults)); if (ASICREV_IS_RV1_F0(dc->ctx->asic_id.hw_internal_rev)) { - dc->dcn_soc.urgent_latency = 3; + dc->dcn_soc->urgent_latency = 3; dc->public.debug.disable_dmcu = true; - dc->dcn_soc.fabric_and_dram_bandwidth_vmax0p9 = 41.60f; + dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9 = 41.60f; } - dc->dcn_soc.number_of_channels = dc->ctx->asic_id.vram_width / ddr4_dram_width; - ASSERT(dc->dcn_soc.number_of_channels < 3); - if (dc->dcn_soc.number_of_channels == 0)/*old sbios bug*/ - dc->dcn_soc.number_of_channels = 2; + dc->dcn_soc->number_of_channels = dc->ctx->asic_id.vram_width / ddr4_dram_width; + ASSERT(dc->dcn_soc->number_of_channels < 3); + if (dc->dcn_soc->number_of_channels == 0)/*old sbios bug*/ + dc->dcn_soc->number_of_channels = 2; - if (dc->dcn_soc.number_of_channels == 1) { - dc->dcn_soc.fabric_and_dram_bandwidth_vmax0p9 = 19.2f; - dc->dcn_soc.fabric_and_dram_bandwidth_vnom0p8 = 17.066f; - dc->dcn_soc.fabric_and_dram_bandwidth_vmid0p72 = 14.933f; - dc->dcn_soc.fabric_and_dram_bandwidth_vmin0p65 = 12.8f; + if (dc->dcn_soc->number_of_channels == 1) { + dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9 = 19.2f; + dc->dcn_soc->fabric_and_dram_bandwidth_vnom0p8 = 17.066f; + dc->dcn_soc->fabric_and_dram_bandwidth_vmid0p72 = 14.933f; + dc->dcn_soc->fabric_and_dram_bandwidth_vmin0p65 = 12.8f; if (ASICREV_IS_RV1_F0(dc->ctx->asic_id.hw_internal_rev)) { - dc->dcn_soc.fabric_and_dram_bandwidth_vmax0p9 = 20.80f; + dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9 = 20.80f; } } diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_dc.h b/drivers/gpu/drm/amd/display/dc/inc/core_dc.h index 982f7170f5d2..ebe1fd78a92a 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_dc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_dc.h @@ -32,8 +32,8 @@ struct core_dc { struct bw_calcs_dceip *bw_dceip; struct bw_calcs_vbios *bw_vbios; #ifdef CONFIG_DRM_AMD_DC_DCN1_0 - struct dcn_soc_bounding_box dcn_soc; - struct dcn_ip_params dcn_ip; + struct dcn_soc_bounding_box *dcn_soc; + struct dcn_ip_params *dcn_ip; struct display_mode_lib dml; #endif -- cgit From b8e9eb7259f744fdc2e34f008e4af211ce0df19a Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Wed, 9 Aug 2017 14:03:34 -0400 Subject: drm/amd/display: fix eDP bootup/S4 backlight on also pass-in correct dispclk tor DMCU Signed-off-by: Charlene Liu Reviewed-by: Anthony Koo Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 12 +++++------- drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c | 22 ++++++++++++++-------- .../gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 2 ++ .../gpu/drm/amd/display/dc/inc/hw/display_clock.h | 2 +- 4 files changed, 22 insertions(+), 16 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 1d69bd25e07b..0d33e179d9f7 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -169,16 +169,14 @@ static void update_num_audio( unsigned int *num_audio, struct audio_support *aud_support) { + aud_support->dp_audio = true; + aud_support->hdmi_audio_native = false; + aud_support->hdmi_audio_on_dongle = false; + if (straps->hdmi_disable == 0) { - aud_support->hdmi_audio_native = true; - aud_support->hdmi_audio_on_dongle = true; - aud_support->dp_audio = true; - } else { if (straps->dc_pinstraps_audio & 0x2) { aud_support->hdmi_audio_on_dongle = true; - aud_support->dp_audio = true; - } else { - aud_support->dp_audio = true; + aud_support->hdmi_audio_native = true; } } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c index a73228b97da5..7bb2eaf07da5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c @@ -327,13 +327,14 @@ static bool dce_clock_set_min_clocks_state( return true; } -static void dce_set_clock( +static int dce_set_clock( struct display_clock *clk, int requested_clk_khz) { struct dce_disp_clk *clk_dce = TO_DCE_CLOCKS(clk); struct bp_pixel_clock_parameters pxl_clk_params = { 0 }; struct dc_bios *bp = clk->ctx->dc_bios; + int actual_clock = requested_clk_khz; /* Make sure requested clock isn't lower than minimum threshold*/ if (requested_clk_khz > 0) @@ -351,15 +352,17 @@ static void dce_set_clock( /* Cache the fixed display clock*/ clk_dce->dfs_bypass_disp_clk = pxl_clk_params.dfs_bypass_display_clock; + actual_clock = pxl_clk_params.dfs_bypass_display_clock; } /* from power down, we need mark the clock state as ClocksStateNominal * from HWReset, so when resume we will call pplib voltage regulator.*/ if (requested_clk_khz == 0) clk->cur_min_clks_state = DM_PP_CLOCKS_STATE_NOMINAL; + return actual_clock; } -static void dce_psr_set_clock( +static int dce_psr_set_clock( struct display_clock *clk, int requested_clk_khz) { @@ -367,13 +370,15 @@ static void dce_psr_set_clock( struct dc_context *ctx = clk_dce->base.ctx; struct core_dc *core_dc = DC_TO_CORE(ctx->dc); struct dmcu *dmcu = core_dc->res_pool->dmcu; + int actual_clk_khz = requested_clk_khz; - dce_set_clock(clk, requested_clk_khz); + actual_clk_khz = dce_set_clock(clk, requested_clk_khz); - dmcu->funcs->set_psr_wait_loop(dmcu, requested_clk_khz / 1000 / 7); + dmcu->funcs->set_psr_wait_loop(dmcu, actual_clk_khz / 1000 / 7); + return actual_clk_khz; } -static void dce112_set_clock( +static int dce112_set_clock( struct display_clock *clk, int requested_clk_khz) { @@ -383,7 +388,7 @@ static void dce112_set_clock( struct core_dc *core_dc = DC_TO_CORE(clk->ctx->dc); struct abm *abm = core_dc->res_pool->abm; struct dmcu *dmcu = core_dc->res_pool->dmcu; - + int actual_clock = requested_clk_khz; /* Prepare to program display clock*/ memset(&dce_clk_params, 0, sizeof(dce_clk_params)); @@ -397,6 +402,7 @@ static void dce112_set_clock( dce_clk_params.clock_type = DCECLOCK_TYPE_DISPLAY_CLOCK; bp->funcs->set_dce_clock(bp, &dce_clk_params); + actual_clock = dce_clk_params.target_clock_frequency; /* from power down, we need mark the clock state as ClocksStateNominal * from HWReset, so when resume we will call pplib voltage regulator.*/ @@ -415,8 +421,8 @@ static void dce112_set_clock( if (abm->funcs->is_dmcu_initialized(abm)) dmcu->funcs->set_psr_wait_loop(dmcu, - requested_clk_khz / 1000 / 7); - + actual_clock / 1000 / 7); + return actual_clock; } static void dce_clock_read_integrated_info(struct dce_disp_clk *clk_dce) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 7e9afab8fca0..0dab5bacde3c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -1288,6 +1288,8 @@ void dce110_link_encoder_disable_output( /* OF_SKIP_POWER_DOWN_INACTIVE_ENCODER */ return; } + if (enc110->base.connector.id == CONNECTOR_ID_EDP) + dce110_link_encoder_edp_backlight_control(enc, false); /* Power-down RX and disable GPU PHY should be paired. * Disabling PHY without powering down RX may cause * symbol lock loss, on which we will get DP Sink interrupt. */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h b/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h index 879c3db7cba6..f5f69cd81f6f 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h @@ -62,7 +62,7 @@ struct display_clock { }; struct display_clock_funcs { - void (*set_clock)(struct display_clock *disp_clk, + int (*set_clock)(struct display_clock *disp_clk, int requested_clock_khz); enum dm_pp_clocks_state (*get_required_clocks_state)( -- cgit From 503a7c6f2518be909fa61276ee002846524b588b Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Thu, 3 Aug 2017 10:19:58 -0400 Subject: drm/amd/display: Use function pointer for update_plane_addr Signed-off-by: Dmytro Laktyushkin Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c | 1 + drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 6 +++--- 3 files changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 0d33e179d9f7..d2b8f27416d6 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -132,7 +132,7 @@ struct resource_pool *dc_create_resource_pool( #if defined(CONFIG_DRM_AMD_DC_DCN1_0) case DCN_VERSION_1_0: res_pool = dcn10_create_resource_pool( - num_virtual_links, dc); + num_virtual_links, dc); break; #endif diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index cc707bd615dc..922af2d1b91a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -615,6 +615,7 @@ static uint32_t dce110_get_pll_pixel_rate_in_hz( /* This function need separate to different DCE version, before separate, just use pixel clock */ return pipe_ctx->stream->phy_pix_clk; + } static uint32_t dce110_get_dp_pixel_rate_from_combo_phy_pll( diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 7b943e1837ce..184627c8685e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1246,7 +1246,7 @@ static void toggle_watermark_change_req(struct dce_hwseq *hws) DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, watermark_change_req); } -static void update_plane_addr(const struct core_dc *dc, struct pipe_ctx *pipe_ctx) +static void dcn10_update_plane_addr(const struct core_dc *dc, struct pipe_ctx *pipe_ctx) { bool addr_patched = false; PHYSICAL_ADDRESS_LOC addr; @@ -2115,7 +2115,7 @@ static void update_dchubp_dpp( */ REG_UPDATE(DCHUBP_CNTL[pipe_ctx->pipe_idx], HUBP_VTG_SEL, pipe_ctx->stream_res.tg->inst); - update_plane_addr(dc, pipe_ctx); + dc->hwss.update_plane_addr(dc, pipe_ctx); mi->funcs->mem_input_setup( mi, @@ -2687,7 +2687,7 @@ static const struct hw_sequencer_funcs dcn10_funcs = { .apply_ctx_to_hw = dce110_apply_ctx_to_hw, .apply_ctx_for_surface = dcn10_apply_ctx_for_surface, .set_plane_config = set_plane_config, - .update_plane_addr = update_plane_addr, + .update_plane_addr = dcn10_update_plane_addr, .update_dchub = dcn10_update_dchub, .update_pending_status = dcn10_update_pending_status, .set_input_transfer_func = dcn10_set_input_transfer_func, -- cgit From fb3466a450cc4684654367ae2f47fc3fc7846574 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Tue, 1 Aug 2017 15:00:25 -0400 Subject: drm/amd/display: Flattening core_dc to dc -Flattening core_dc to dc Signed-off-by: Bhawanpreet Lakha Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 73 +++++----- drivers/gpu/drm/amd/display/dc/core/dc.c | 162 ++++++++++----------- drivers/gpu/drm/amd/display/dc/core/dc_debug.c | 20 +-- .../gpu/drm/amd/display/dc/core/dc_hw_sequencer.c | 3 +- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 19 ++- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 1 - drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 22 +-- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 14 +- drivers/gpu/drm/amd/display/dc/core/dc_surface.c | 10 +- drivers/gpu/drm/amd/display/dc/dc.h | 71 +++++++-- .../gpu/drm/amd/display/dc/dce/dce_clock_source.c | 5 +- drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c | 10 +- drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c | 4 +- drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h | 2 +- .../amd/display/dc/dce100/dce100_hw_sequencer.c | 9 +- .../amd/display/dc/dce100/dce100_hw_sequencer.h | 6 +- .../drm/amd/display/dc/dce100/dce100_resource.c | 22 +-- .../drm/amd/display/dc/dce100/dce100_resource.h | 4 +- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 72 ++++----- .../amd/display/dc/dce110/dce110_hw_sequencer.h | 12 +- .../drm/amd/display/dc/dce110/dce110_resource.c | 26 ++-- .../drm/amd/display/dc/dce110/dce110_resource.h | 4 +- .../amd/display/dc/dce112/dce112_hw_sequencer.c | 5 +- .../amd/display/dc/dce112/dce112_hw_sequencer.h | 4 +- .../drm/amd/display/dc/dce112/dce112_resource.c | 26 ++-- .../drm/amd/display/dc/dce112/dce112_resource.h | 10 +- .../amd/display/dc/dce120/dce120_hw_sequencer.c | 5 +- .../amd/display/dc/dce120/dce120_hw_sequencer.h | 4 +- .../drm/amd/display/dc/dce120/dce120_resource.c | 18 +-- .../drm/amd/display/dc/dce120/dce120_resource.h | 4 +- .../drm/amd/display/dc/dce80/dce80_hw_sequencer.c | 5 +- .../drm/amd/display/dc/dce80/dce80_hw_sequencer.h | 4 +- .../gpu/drm/amd/display/dc/dce80/dce80_resource.c | 46 +++--- .../gpu/drm/amd/display/dc/dce80/dce80_resource.h | 8 +- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c | 1 - .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 108 +++++++------- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h | 4 +- .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 34 ++--- .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.h | 4 +- drivers/gpu/drm/amd/display/dc/inc/core_dc.h | 55 ------- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 8 +- drivers/gpu/drm/amd/display/dc/inc/dce_calcs.h | 2 +- drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h | 12 +- drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h | 1 + drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 50 ++++--- drivers/gpu/drm/amd/display/dc/inc/resource.h | 15 +- .../amd/display/dc/irq/dce110/irq_service_dce110.c | 6 +- .../amd/display/dc/irq/dce80/irq_service_dce80.c | 1 - .../gpu/drm/amd/display/include/logger_interface.h | 10 +- .../drm/amd/display/modules/freesync/freesync.c | 11 +- 51 files changed, 507 insertions(+), 527 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/dc/inc/core_dc.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 6fb1b9a91993..f0dfd3c3c12c 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -27,7 +27,6 @@ #include "dcn_calcs.h" #include "dcn_calc_auto.h" #include "dc.h" -#include "core_dc.h" #include "dal_asic_id.h" #include "resource.h" @@ -399,7 +398,7 @@ static void pipe_ctx_to_e2e_pipe_params ( } static void dcn_bw_calc_rq_dlg_ttu( - const struct core_dc *dc, + const struct dc *dc, const struct dcn_bw_internal_vars *v, struct pipe_ctx *pipe, int in_idx) @@ -674,45 +673,45 @@ static void calc_wm_sets_and_perf_params( context->bw.dcn.watermarks.d = context->bw.dcn.watermarks.a; } -static bool dcn_bw_apply_registry_override(struct core_dc *dc) +static bool dcn_bw_apply_registry_override(struct dc *dc) { bool updated = false; kernel_fpu_begin(); - if ((int)(dc->dcn_soc->sr_exit_time * 1000) != dc->public.debug.sr_exit_time_ns - && dc->public.debug.sr_exit_time_ns) { + if ((int)(dc->dcn_soc->sr_exit_time * 1000) != dc->debug.sr_exit_time_ns + && dc->debug.sr_exit_time_ns) { updated = true; - dc->dcn_soc->sr_exit_time = dc->public.debug.sr_exit_time_ns / 1000.0; + dc->dcn_soc->sr_exit_time = dc->debug.sr_exit_time_ns / 1000.0; } if ((int)(dc->dcn_soc->sr_enter_plus_exit_time * 1000) - != dc->public.debug.sr_enter_plus_exit_time_ns - && dc->public.debug.sr_enter_plus_exit_time_ns) { + != dc->debug.sr_enter_plus_exit_time_ns + && dc->debug.sr_enter_plus_exit_time_ns) { updated = true; dc->dcn_soc->sr_enter_plus_exit_time = - dc->public.debug.sr_enter_plus_exit_time_ns / 1000.0; + dc->debug.sr_enter_plus_exit_time_ns / 1000.0; } - if ((int)(dc->dcn_soc->urgent_latency * 1000) != dc->public.debug.urgent_latency_ns - && dc->public.debug.urgent_latency_ns) { + if ((int)(dc->dcn_soc->urgent_latency * 1000) != dc->debug.urgent_latency_ns + && dc->debug.urgent_latency_ns) { updated = true; - dc->dcn_soc->urgent_latency = dc->public.debug.urgent_latency_ns / 1000.0; + dc->dcn_soc->urgent_latency = dc->debug.urgent_latency_ns / 1000.0; } if ((int)(dc->dcn_soc->percent_of_ideal_drambw_received_after_urg_latency * 1000) - != dc->public.debug.percent_of_ideal_drambw - && dc->public.debug.percent_of_ideal_drambw) { + != dc->debug.percent_of_ideal_drambw + && dc->debug.percent_of_ideal_drambw) { updated = true; dc->dcn_soc->percent_of_ideal_drambw_received_after_urg_latency = - dc->public.debug.percent_of_ideal_drambw; + dc->debug.percent_of_ideal_drambw; } if ((int)(dc->dcn_soc->dram_clock_change_latency * 1000) - != dc->public.debug.dram_clock_change_latency_ns - && dc->public.debug.dram_clock_change_latency_ns) { + != dc->debug.dram_clock_change_latency_ns + && dc->debug.dram_clock_change_latency_ns) { updated = true; dc->dcn_soc->dram_clock_change_latency = - dc->public.debug.dram_clock_change_latency_ns / 1000.0; + dc->debug.dram_clock_change_latency_ns / 1000.0; } kernel_fpu_end(); @@ -720,7 +719,7 @@ static bool dcn_bw_apply_registry_override(struct core_dc *dc) } bool dcn_validate_bandwidth( - const struct core_dc *dc, + struct dc *dc, struct validate_context *context) { const struct resource_pool *pool = dc->res_pool; @@ -730,8 +729,8 @@ bool dcn_validate_bandwidth( bool bw_limit_pass; float bw_limit; - if (dcn_bw_apply_registry_override(DC_TO_CORE(&dc->public))) - dcn_bw_sync_calcs_and_dml(DC_TO_CORE(&dc->public)); + if (dcn_bw_apply_registry_override(dc)) + dcn_bw_sync_calcs_and_dml(dc); memset(v, 0, sizeof(*v)); kernel_fpu_begin(); @@ -850,7 +849,7 @@ bool dcn_validate_bandwidth( v->phyclk_per_state[1] = v->phyclkv_mid0p72; v->phyclk_per_state[0] = v->phyclkv_min0p65; - if (dc->public.debug.disable_pipe_split) { + if (dc->debug.disable_pipe_split) { v->max_dispclk[0] = v->max_dppclk_vmin0p65; } @@ -982,15 +981,15 @@ bool dcn_validate_bandwidth( mode_support_and_system_configuration(v); if (v->voltage_level == 0 && - (dc->public.debug.sr_exit_time_dpm0_ns - || dc->public.debug.sr_enter_plus_exit_time_dpm0_ns)) { - struct core_dc *dc_core = DC_TO_CORE(&dc->public); + (dc->debug.sr_exit_time_dpm0_ns + || dc->debug.sr_enter_plus_exit_time_dpm0_ns)) { + struct dc *dc_core = dc; - if (dc->public.debug.sr_enter_plus_exit_time_dpm0_ns) + if (dc->debug.sr_enter_plus_exit_time_dpm0_ns) v->sr_enter_plus_exit_time = - dc->public.debug.sr_enter_plus_exit_time_dpm0_ns / 1000.0f; - if (dc->public.debug.sr_exit_time_dpm0_ns) - v->sr_exit_time = dc->public.debug.sr_exit_time_dpm0_ns / 1000.0f; + dc->debug.sr_enter_plus_exit_time_dpm0_ns / 1000.0f; + if (dc->debug.sr_exit_time_dpm0_ns) + v->sr_exit_time = dc->debug.sr_exit_time_dpm0_ns / 1000.0f; dc_core->dml.soc.sr_enter_plus_exit_time_us = v->sr_enter_plus_exit_time; dc_core->dml.soc.sr_exit_time_us = v->sr_exit_time; mode_support_and_system_configuration(v); @@ -1020,7 +1019,7 @@ bool dcn_validate_bandwidth( context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz = (int)(v->dcf_clk_deep_sleep * 1000); context->bw.dcn.calc_clk.dcfclk_khz = (int)(v->dcfclk * 1000); context->bw.dcn.calc_clk.dispclk_khz = (int)(v->dispclk * 1000); - if (dc->public.debug.max_disp_clk == true) + if (dc->debug.max_disp_clk == true) context->bw.dcn.calc_clk.dispclk_khz = (int)(dc->dcn_soc->max_dispclk_vmax0p9 * 1000); context->bw.dcn.calc_clk.dppclk_div = (int)(v->dispclk_dppclk_ratio) == 2; @@ -1109,13 +1108,13 @@ bool dcn_validate_bandwidth( input_idx++; } - if (dc->public.debug.use_dml_wm) + if (dc->debug.use_dml_wm) dcn_dml_wm_override(v, (struct display_mode_lib *) &dc->dml, context, pool); } if (v->voltage_level == 0) { - struct core_dc *dc_core = DC_TO_CORE(&dc->public); + struct dc *dc_core = dc; dc_core->dml.soc.sr_enter_plus_exit_time_us = dc_core->dcn_soc->sr_enter_plus_exit_time; @@ -1138,7 +1137,7 @@ bool dcn_validate_bandwidth( } unsigned int dcn_find_normalized_clock_vdd_Level( - const struct core_dc *dc, + const struct dc *dc, enum dm_pp_clock_type clocks_type, int clocks_in_khz) { @@ -1228,7 +1227,7 @@ unsigned int dcn_find_normalized_clock_vdd_Level( } unsigned int dcn_find_dcfclk_suits_all( - const struct core_dc *dc, + const struct dc *dc, struct clocks_value *clocks) { unsigned vdd_level, vdd_level_temp; @@ -1270,7 +1269,7 @@ unsigned int dcn_find_dcfclk_suits_all( return dcf_clk; } -void dcn_bw_update_from_pplib(struct core_dc *dc) +void dcn_bw_update_from_pplib(struct dc *dc) { struct dc_context *ctx = dc->ctx; struct dm_pp_clock_levels_with_voltage clks = {0}; @@ -1310,7 +1309,7 @@ void dcn_bw_update_from_pplib(struct core_dc *dc) kernel_fpu_end(); } -void dcn_bw_notify_pplib_of_wm_ranges(struct core_dc *dc) +void dcn_bw_notify_pplib_of_wm_ranges(struct dc *dc) { struct dm_pp_wm_sets_with_clock_ranges_soc15 clk_ranges = {0}; int max_fclk_khz, nom_fclk_khz, min_fclk_khz, max_dcfclk_khz, @@ -1388,7 +1387,7 @@ void dcn_bw_notify_pplib_of_wm_ranges(struct core_dc *dc) dm_pp_notify_wm_clock_changes_soc15(dc->ctx, &clk_ranges); } -void dcn_bw_sync_calcs_and_dml(struct core_dc *dc) +void dcn_bw_sync_calcs_and_dml(struct dc *dc) { kernel_fpu_begin(); dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_CALCS, diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 40d65b758994..44c7b52e4a00 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -35,7 +35,6 @@ #include "clock_source.h" #include "dc_bios_types.h" -#include "dce_calcs.h" #include "bios_parser_interface.h" #include "include/irq_service_interface.h" #include "transform.h" @@ -52,7 +51,7 @@ /******************************************************************************* * Private functions ******************************************************************************/ -static void destroy_links(struct core_dc *dc) +static void destroy_links(struct dc *dc) { uint32_t i; @@ -63,7 +62,7 @@ static void destroy_links(struct core_dc *dc) } static bool create_links( - struct core_dc *dc, + struct dc *dc, uint32_t num_virtual_links) { int i; @@ -153,7 +152,7 @@ static bool stream_adjust_vmin_vmax(struct dc *dc, int vmin, int vmax) { /* TODO: Support multiple streams */ - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; struct dc_stream_state *stream = streams[0]; int i = 0; bool ret = false; @@ -179,7 +178,7 @@ static bool stream_get_crtc_position(struct dc *dc, unsigned int *v_pos, unsigned int *nom_v_pos) { /* TODO: Support multiple streams */ - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; struct dc_stream_state *stream = streams[0]; int i = 0; bool ret = false; @@ -202,7 +201,7 @@ static bool stream_get_crtc_position(struct dc *dc, static bool set_gamut_remap(struct dc *dc, const struct dc_stream_state *stream) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; int i = 0; bool ret = false; struct pipe_ctx *pipes; @@ -220,7 +219,7 @@ static bool set_gamut_remap(struct dc *dc, const struct dc_stream_state *stream) static bool program_csc_matrix(struct dc *dc, struct dc_stream_state *stream) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; int i = 0; bool ret = false; struct pipe_ctx *pipes; @@ -245,7 +244,7 @@ static void set_static_screen_events(struct dc *dc, int num_streams, const struct dc_static_screen_events *events) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; int i = 0; int j = 0; struct pipe_ctx *pipes_affected[MAX_PIPES]; @@ -270,7 +269,7 @@ static void set_drive_settings(struct dc *dc, struct link_training_settings *lt_settings, const struct dc_link *link) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; int i; for (i = 0; i < core_dc->link_count; i++) { @@ -288,7 +287,7 @@ static void perform_link_training(struct dc *dc, struct dc_link_settings *link_setting, bool skip_video_pattern) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; int i; for (i = 0; i < core_dc->link_count; i++) @@ -369,48 +368,48 @@ void set_dither_option(struct dc_stream_state *stream, opp_program_bit_depth_reduction(pipes->stream_res.opp, ¶ms); } -static void allocate_dc_stream_funcs(struct core_dc *core_dc) +static void allocate_dc_stream_funcs(struct dc *core_dc) { if (core_dc->hwss.set_drr != NULL) { - core_dc->public.stream_funcs.adjust_vmin_vmax = + core_dc->stream_funcs.adjust_vmin_vmax = stream_adjust_vmin_vmax; } - core_dc->public.stream_funcs.set_static_screen_events = + core_dc->stream_funcs.set_static_screen_events = set_static_screen_events; - core_dc->public.stream_funcs.get_crtc_position = + core_dc->stream_funcs.get_crtc_position = stream_get_crtc_position; - core_dc->public.stream_funcs.set_gamut_remap = + core_dc->stream_funcs.set_gamut_remap = set_gamut_remap; - core_dc->public.stream_funcs.program_csc_matrix = + core_dc->stream_funcs.program_csc_matrix = program_csc_matrix; - core_dc->public.stream_funcs.set_dither_option = + core_dc->stream_funcs.set_dither_option = set_dither_option; - core_dc->public.link_funcs.set_drive_settings = + core_dc->link_funcs.set_drive_settings = set_drive_settings; - core_dc->public.link_funcs.perform_link_training = + core_dc->link_funcs.perform_link_training = perform_link_training; - core_dc->public.link_funcs.set_preferred_link_settings = + core_dc->link_funcs.set_preferred_link_settings = set_preferred_link_settings; - core_dc->public.link_funcs.enable_hpd = + core_dc->link_funcs.enable_hpd = enable_hpd; - core_dc->public.link_funcs.disable_hpd = + core_dc->link_funcs.disable_hpd = disable_hpd; - core_dc->public.link_funcs.set_test_pattern = + core_dc->link_funcs.set_test_pattern = set_test_pattern; } -static void destruct(struct core_dc *dc) +static void destruct(struct dc *dc) { dc_release_validate_context(dc->current_context); dc->current_context = NULL; @@ -446,10 +445,11 @@ static void destruct(struct core_dc *dc) dm_free(dc->dcn_ip); dc->dcn_ip = NULL; + #endif } -static bool construct(struct core_dc *dc, +static bool construct(struct dc *dc, const struct dc_init_data *init_params) { struct dal_logger *logger; @@ -508,7 +508,7 @@ static bool construct(struct core_dc *dc, dc_ctx->cgs_device = init_params->cgs_device; dc_ctx->driver_context = init_params->driver; - dc_ctx->dc = &dc->public; + dc_ctx->dc = dc; dc_ctx->asic_id = init_params->asic_id; /* Create logger */ @@ -621,7 +621,7 @@ void ProgramPixelDurationV(unsigned int pixelClockInKHz ) struct dc *dc_create(const struct dc_init_data *init_params) { - struct core_dc *core_dc = dm_alloc(sizeof(*core_dc)); + struct dc *core_dc = dm_alloc(sizeof(*core_dc)); unsigned int full_pipe_count; if (NULL == core_dc) @@ -636,23 +636,23 @@ struct dc *dc_create(const struct dc_init_data *init_params) full_pipe_count = core_dc->res_pool->pipe_count; if (core_dc->res_pool->underlay_pipe_index != NO_UNDERLAY_PIPE) full_pipe_count--; - core_dc->public.caps.max_streams = min( + core_dc->caps.max_streams = min( full_pipe_count, core_dc->res_pool->stream_enc_count); - core_dc->public.caps.max_links = core_dc->link_count; - core_dc->public.caps.max_audios = core_dc->res_pool->audio_count; + core_dc->caps.max_links = core_dc->link_count; + core_dc->caps.max_audios = core_dc->res_pool->audio_count; - core_dc->public.config = init_params->flags; + core_dc->config = init_params->flags; dm_logger_write(core_dc->ctx->logger, LOG_DC, "Display Core initialized\n"); /* TODO: missing feature to be enabled */ - core_dc->public.debug.disable_dfs_bypass = true; + core_dc->debug.disable_dfs_bypass = true; - return &core_dc->public; + return core_dc; construct_fail: dm_free(core_dc); @@ -663,14 +663,14 @@ alloc_fail: void dc_destroy(struct dc **dc) { - struct core_dc *core_dc = DC_TO_CORE(*dc); + struct dc *core_dc = *dc; destruct(core_dc); dm_free(core_dc); *dc = NULL; } static bool is_validation_required( - const struct core_dc *dc, + const struct dc *dc, const struct dc_validation_set set[], int set_count) { @@ -705,7 +705,7 @@ static bool is_validation_required( } static bool validate_streams ( - const struct dc *dc, + struct dc *dc, const struct dc_validation_set set[], int set_count) { @@ -719,7 +719,7 @@ static bool validate_streams ( } static bool validate_surfaces( - const struct dc *dc, + struct dc *dc, const struct dc_validation_set set[], int set_count) { @@ -734,11 +734,11 @@ static bool validate_surfaces( } struct validate_context *dc_get_validate_context( - const struct dc *dc, + struct dc *dc, const struct dc_validation_set set[], uint8_t set_count) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; enum dc_status result = DC_ERROR_UNEXPECTED; struct validate_context *context; @@ -773,11 +773,11 @@ context_alloc_fail: } bool dc_validate_resources( - const struct dc *dc, + struct dc *dc, const struct dc_validation_set set[], uint8_t set_count) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; enum dc_status result = DC_ERROR_UNEXPECTED; struct validate_context *context; @@ -811,10 +811,10 @@ context_alloc_fail: } bool dc_validate_guaranteed( - const struct dc *dc, + struct dc *dc, struct dc_stream_state *stream) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; enum dc_status result = DC_ERROR_UNEXPECTED; struct validate_context *context; @@ -844,7 +844,7 @@ context_alloc_fail: } static void program_timing_sync( - struct core_dc *core_dc, + struct dc *core_dc, struct validate_context *ctx) { int i, j; @@ -918,7 +918,7 @@ static void program_timing_sync( } static bool context_changed( - struct core_dc *dc, + struct dc *dc, struct validate_context *context) { uint8_t i; @@ -935,7 +935,7 @@ static bool context_changed( } static bool streams_changed( - struct core_dc *dc, + struct dc *dc, struct dc_stream_state *streams[], uint8_t stream_count) { @@ -961,7 +961,7 @@ bool dc_enable_stereo( bool ret = true; int i, j; struct pipe_ctx *pipe; - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; #ifdef ENABLE_FBC struct compressor *fbc_compressor = core_dc->fbc_compressor; @@ -996,7 +996,7 @@ bool dc_enable_stereo( */ static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *context) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; struct dc_bios *dcb = core_dc->ctx->dc_bios; enum dc_status result = DC_ERROR_UNEXPECTED; struct pipe_ctx *pipe; @@ -1064,7 +1064,7 @@ static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *c bool dc_commit_context(struct dc *dc, struct validate_context *context) { enum dc_status result = DC_ERROR_UNEXPECTED; - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; int i; if (false == context_changed(core_dc, context)) @@ -1092,7 +1092,7 @@ bool dc_commit_streams( struct dc_stream_state *streams[], uint8_t stream_count) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; enum dc_status result = DC_ERROR_UNEXPECTED; struct validate_context *context; struct dc_validation_set set[MAX_STREAMS] = { {0, {0} } }; @@ -1158,7 +1158,7 @@ context_alloc_fail: bool dc_post_update_surfaces_to_stream(struct dc *dc) { int i; - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; struct validate_context *context = core_dc->current_context; post_surface_trace(dc); @@ -1375,7 +1375,7 @@ static enum surface_update_type get_scaling_info_update_type( } static enum surface_update_type det_surface_update( - const struct core_dc *dc, + const struct dc *dc, const struct dc_surface_update *u, int surface_index) { @@ -1410,7 +1410,7 @@ enum surface_update_type dc_check_update_surfaces_for_stream( struct dc_stream_update *stream_update, const struct dc_stream_status *stream_status) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; int i; enum surface_update_type overall_type = UPDATE_TYPE_FAST; @@ -1456,7 +1456,7 @@ void dc_update_planes_and_stream(struct dc *dc, struct dc_stream_state *stream, struct dc_stream_update *stream_update) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; struct validate_context *context; int i, j; enum surface_update_type update_type; @@ -1781,29 +1781,29 @@ context_alloc_fail: DC_ERROR("Failed to allocate new validate context!\n"); } -uint8_t dc_get_current_stream_count(const struct dc *dc) +uint8_t dc_get_current_stream_count(struct dc *dc) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; return core_dc->current_context->stream_count; } -struct dc_stream_state *dc_get_stream_at_index(const struct dc *dc, uint8_t i) +struct dc_stream_state *dc_get_stream_at_index(struct dc *dc, uint8_t i) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; if (i < core_dc->current_context->stream_count) return core_dc->current_context->streams[i]; return NULL; } -struct dc_link *dc_get_link_at_index(const struct dc *dc, uint32_t link_index) +struct dc_link *dc_get_link_at_index(struct dc *dc, uint32_t link_index) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; return core_dc->links[link_index]; } -struct dwbc *dc_get_dwb_at_pipe(const struct dc *dc, uint32_t pipe) +struct dwbc *dc_get_dwb_at_pipe(struct dc *dc, uint32_t pipe) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; if ((pipe >= dwb_pipe0) && (pipe < dwb_pipe_max_num)) { return core_dc->res_pool->dwbc[(int)pipe]; } else { @@ -1814,20 +1814,20 @@ struct dwbc *dc_get_dwb_at_pipe(const struct dc *dc, uint32_t pipe) const struct graphics_object_id dc_get_link_id_at_index( struct dc *dc, uint32_t link_index) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; return core_dc->links[link_index]->link_id; } enum dc_irq_source dc_get_hpd_irq_source_at_index( struct dc *dc, uint32_t link_index) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; return core_dc->links[link_index]->irq_source_hpd; } const struct audio **dc_get_audios(struct dc *dc) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; return (const struct audio **)core_dc->res_pool->audios; } @@ -1836,24 +1836,24 @@ enum dc_irq_source dc_interrupt_to_irq_source( uint32_t src_id, uint32_t ext_id) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; return dal_irq_service_to_irq_source(core_dc->res_pool->irqs, src_id, ext_id); } -void dc_interrupt_set(const struct dc *dc, enum dc_irq_source src, bool enable) +void dc_interrupt_set(struct dc *dc, enum dc_irq_source src, bool enable) { - struct core_dc *core_dc; + struct dc *core_dc; if (dc == NULL) return; - core_dc = DC_TO_CORE(dc); + core_dc = dc; dal_irq_service_set(core_dc->res_pool->irqs, src, enable); } void dc_interrupt_ack(struct dc *dc, enum dc_irq_source src) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; dal_irq_service_ack(core_dc->res_pool->irqs, src); } @@ -1861,7 +1861,7 @@ void dc_set_power_state( struct dc *dc, enum dc_acpi_cm_power_state power_state) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; atomic_t ref_count; switch (power_state) { @@ -1889,9 +1889,9 @@ void dc_set_power_state( } -void dc_resume(const struct dc *dc) +void dc_resume(struct dc *dc) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; uint32_t i; @@ -1906,7 +1906,7 @@ bool dc_read_aux_dpcd( uint8_t *data, uint32_t size) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; struct dc_link *link = core_dc->links[link_index]; enum ddc_result r = dal_ddc_service_read_dpcd_data( @@ -1926,7 +1926,7 @@ bool dc_write_aux_dpcd( const uint8_t *data, uint32_t size) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; struct dc_link *link = core_dc->links[link_index]; enum ddc_result r = dal_ddc_service_write_dpcd_data( @@ -1947,7 +1947,7 @@ bool dc_read_aux_i2c( uint8_t *data, uint32_t size) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; struct dc_link *link = core_dc->links[link_index]; enum ddc_result r = dal_ddc_service_read_dpcd_data( @@ -1968,7 +1968,7 @@ bool dc_write_aux_i2c( const uint8_t *data, uint32_t size) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; struct dc_link *link = core_dc->links[link_index]; enum ddc_result r = dal_ddc_service_write_dpcd_data( @@ -1990,7 +1990,7 @@ bool dc_query_ddc_data( uint8_t *read_buf, uint32_t read_size) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; struct dc_link *link = core_dc->links[link_index]; @@ -2010,7 +2010,7 @@ bool dc_submit_i2c( uint32_t link_index, struct i2c_command *cmd) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; struct dc_link *link = core_dc->links[link_index]; struct ddc_service *ddc = link->ddc; @@ -2129,7 +2129,7 @@ void dc_link_remove_remote_sink(struct dc_link *link, struct dc_sink *sink) bool dc_init_dchub(struct dc *dc, struct dchub_init_data *dh_data) { int i; - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; struct mem_input *mi = NULL; for (i = 0; i < core_dc->res_pool->pipe_count; i++) { @@ -2155,7 +2155,7 @@ bool dc_init_dchub(struct dc *dc, struct dchub_init_data *dh_data) void dc_log_hw_state(struct dc *dc) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; if (core_dc->hwss.log_hw_state) core_dc->hwss.log_hw_state(core_dc); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c index 21af3bc057c7..d74eed8f9b96 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c @@ -37,12 +37,12 @@ } while (0) void pre_surface_trace( - const struct dc *dc, + struct dc *dc, const struct dc_plane_state *const *plane_states, int surface_count) { int i; - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; struct dal_logger *logger = core_dc->ctx->logger; for (i = 0; i < surface_count; i++) { @@ -158,12 +158,12 @@ void pre_surface_trace( } void update_surface_trace( - const struct dc *dc, + struct dc *dc, const struct dc_surface_update *updates, int surface_count) { int i; - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; struct dal_logger *logger = core_dc->ctx->logger; for (i = 0; i < surface_count; i++) { @@ -279,9 +279,9 @@ void update_surface_trace( SURFACE_TRACE("\n"); } -void post_surface_trace(const struct dc *dc) +void post_surface_trace(struct dc *dc) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; struct dal_logger *logger = core_dc->ctx->logger; SURFACE_TRACE("post surface process.\n"); @@ -289,11 +289,11 @@ void post_surface_trace(const struct dc *dc) } void context_timing_trace( - const struct dc *dc, + struct dc *dc, struct resource_context *res_ctx) { int i; - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; struct dal_logger *logger = core_dc->ctx->logger; int h_pos[MAX_PIPES], v_pos[MAX_PIPES]; struct crtc_position position; @@ -328,11 +328,11 @@ void context_timing_trace( } void context_clock_trace( - const struct dc *dc, + struct dc *dc, struct validate_context *context) { #if defined(CONFIG_DRM_AMD_DC_DCN1_0) - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; struct dal_logger *logger = core_dc->ctx->logger; CLOCK_TRACE("Current: dispclk_khz:%d dppclk_div:%d dcfclk_khz:%d\n" diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c index 7b1f2493cbc9..71993d5983bf 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c @@ -25,7 +25,6 @@ #include "dm_services.h" #include "core_types.h" -#include "core_dc.h" #include "timing_generator.h" #include "hw_sequencer.h" @@ -55,7 +54,7 @@ static const struct tg_color black_color_format[] = { }; void color_space_to_black_color( - const struct core_dc *dc, + const struct dc *dc, enum dc_color_space colorspace, struct tg_color *black_color) { diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index b858fec72bd7..1888bf4d2c3f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -26,14 +26,13 @@ #include "dm_services.h" #include "dm_helpers.h" #include "dc.h" -#include "core_dc.h" #include "grph_object_id.h" #include "gpio_service_interface.h" #include "core_status.h" #include "dc_link_dp.h" #include "dc_link_ddc.h" #include "link_hwss.h" -#include "stream_encoder.h" + #include "link_encoder.h" #include "hw_sequencer.h" #include "resource.h" @@ -1392,7 +1391,7 @@ enum dc_status dc_link_validate_mode_timing( bool dc_link_set_backlight_level(const struct dc_link *link, uint32_t level, uint32_t frame_ramp, const struct dc_stream_state *stream) { - struct core_dc *core_dc = DC_TO_CORE(link->ctx->dc); + struct dc *core_dc = link->ctx->dc; struct abm *abm = core_dc->res_pool->abm; unsigned int controller_id = 0; int i; @@ -1431,7 +1430,7 @@ bool dc_link_set_backlight_level(const struct dc_link *link, uint32_t level, bool dc_link_set_abm_disable(const struct dc_link *link) { - struct core_dc *core_dc = DC_TO_CORE(link->ctx->dc); + struct dc *core_dc = link->ctx->dc; struct abm *abm = core_dc->res_pool->abm; if ((abm == NULL) || (abm->funcs->set_backlight_level == NULL)) @@ -1445,7 +1444,7 @@ bool dc_link_set_abm_disable(const struct dc_link *link) bool dc_link_set_psr_enable(const struct dc_link *link, bool enable) { - struct core_dc *core_dc = DC_TO_CORE(link->ctx->dc); + struct dc *core_dc = link->ctx->dc; struct dmcu *dmcu = core_dc->res_pool->dmcu; if (dmcu != NULL && link->psr_enabled) @@ -1456,7 +1455,7 @@ bool dc_link_set_psr_enable(const struct dc_link *link, bool enable) bool dc_link_get_psr_state(const struct dc_link *link, uint32_t *psr_state) { - struct core_dc *core_dc = DC_TO_CORE(link->ctx->dc); + struct dc *core_dc = link->ctx->dc; struct dmcu *dmcu = core_dc->res_pool->dmcu; if (dmcu != NULL && link->psr_enabled) @@ -1469,7 +1468,7 @@ bool dc_link_setup_psr(struct dc_link *link, const struct dc_stream_state *stream, struct psr_config *psr_config, struct psr_context *psr_context) { - struct core_dc *core_dc = DC_TO_CORE(link->ctx->dc); + struct dc *core_dc = link->ctx->dc; struct dmcu *dmcu = core_dc->res_pool->dmcu; int i; @@ -1874,7 +1873,7 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx) void core_link_enable_stream(struct pipe_ctx *pipe_ctx) { - struct core_dc *core_dc = DC_TO_CORE(pipe_ctx->stream->ctx->dc); + struct dc *core_dc = pipe_ctx->stream->ctx->dc; enum dc_status status = enable_link(pipe_ctx); @@ -1907,7 +1906,7 @@ void core_link_enable_stream(struct pipe_ctx *pipe_ctx) void core_link_disable_stream(struct pipe_ctx *pipe_ctx) { - struct core_dc *core_dc = DC_TO_CORE(pipe_ctx->stream->ctx->dc); + struct dc *core_dc = pipe_ctx->stream->ctx->dc; if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) deallocate_mst_payload(pipe_ctx); @@ -1919,7 +1918,7 @@ void core_link_disable_stream(struct pipe_ctx *pipe_ctx) void core_link_set_avmute(struct pipe_ctx *pipe_ctx, bool enable) { - struct core_dc *core_dc = DC_TO_CORE(pipe_ctx->stream->ctx->dc); + struct dc *core_dc = pipe_ctx->stream->ctx->dc; if (pipe_ctx->stream->signal != SIGNAL_TYPE_HDMI_TYPE_A) return; 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 9d5fe658d14c..0144c98fd0d5 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 @@ -10,7 +10,6 @@ #include "core_status.h" #include "dpcd_defs.h" -#include "core_dc.h" #include "resource.h" /* maximum pre emphasis level allowed for each voltage swing level*/ diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index d19c663c257f..da880bd02ad7 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -3,7 +3,7 @@ #include "dm_services.h" #include "dc.h" -#include "inc/core_dc.h" +#include "inc/core_types.h" #include "include/ddc_service_types.h" #include "include/i2caux_interface.h" #include "link_hwss.h" diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index d2b8f27416d6..2b357318f945 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -92,7 +92,7 @@ enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id) } struct resource_pool *dc_create_resource_pool( - struct core_dc *dc, + struct dc *dc, int num_virtual_links, enum dce_version dc_version, struct hw_asic_id asic_id) @@ -153,7 +153,7 @@ struct resource_pool *dc_create_resource_pool( return res_pool; } -void dc_destroy_resource_pool(struct core_dc *dc) +void dc_destroy_resource_pool(struct dc *dc) { if (dc) { if (dc->res_pool) @@ -193,7 +193,7 @@ static void update_num_audio( bool resource_construct( unsigned int num_virtual_links, - struct core_dc *dc, + struct dc *dc, struct resource_pool *pool, const struct resource_create_funcs *create_funcs) { @@ -892,7 +892,7 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) enum dc_status resource_build_scaling_params_for_context( - const struct core_dc *dc, + const struct dc *dc, struct validate_context *context) { int i; @@ -1438,7 +1438,7 @@ static void calculate_phy_pix_clks(struct dc_stream_state *stream) } enum dc_status resource_map_pool_resources( - const struct core_dc *dc, + const struct dc *dc, struct validate_context *context, struct validate_context *old_context) { @@ -2316,7 +2316,7 @@ void resource_build_info_frame(struct pipe_ctx *pipe_ctx) } enum dc_status resource_map_clock_resources( - const struct core_dc *dc, + const struct dc *dc, struct validate_context *context, struct validate_context *old_context) { @@ -2343,7 +2343,7 @@ enum dc_status resource_map_clock_resources( else { pipe_ctx->clock_source = NULL; - if (!dc->public.config.disable_disp_pll_sharing) + if (!dc->config.disable_disp_pll_sharing) resource_find_used_clk_src_for_sharing( &context->res_ctx, pipe_ctx); @@ -2515,9 +2515,9 @@ void resource_build_bit_depth_reduction_params(struct dc_stream_state *stream, fmt_bit_depth->pixel_encoding = pixel_encoding; } -bool dc_validate_stream(const struct dc *dc, struct dc_stream_state *stream) +bool dc_validate_stream(struct dc *dc, struct dc_stream_state *stream) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; struct dc_context *dc_ctx = core_dc->ctx; struct dc_link *link = stream->sink->link; struct timing_generator *tg = core_dc->res_pool->timing_generators[0]; @@ -2547,9 +2547,9 @@ bool dc_validate_stream(const struct dc *dc, struct dc_stream_state *stream) return res == DC_OK; } -bool dc_validate_plane(const struct dc *dc, const struct dc_plane_state *plane_state) +bool dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; /* TODO For now validates pixel format only */ if (core_dc->res_pool->funcs->validate_plane) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 47e407dab4a3..5e4f7f08e3db 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -144,7 +144,7 @@ struct dc_stream_status *dc_stream_get_status( struct dc_stream_state *stream) { uint8_t i; - struct core_dc *dc = DC_TO_CORE(stream->ctx->dc); + struct dc *dc = stream->ctx->dc; for (i = 0; i < dc->current_context->stream_count; i++) { if (stream == dc->current_context->streams[i]) { @@ -163,7 +163,7 @@ bool dc_stream_set_cursor_attributes( const struct dc_cursor_attributes *attributes) { int i; - struct core_dc *core_dc; + struct dc *core_dc; struct resource_context *res_ctx; if (NULL == stream) { @@ -175,7 +175,7 @@ bool dc_stream_set_cursor_attributes( return false; } - core_dc = DC_TO_CORE(stream->ctx->dc); + core_dc = stream->ctx->dc; res_ctx = &core_dc->current_context->res_ctx; for (i = 0; i < MAX_PIPES; i++) { @@ -198,7 +198,7 @@ bool dc_stream_set_cursor_position( const struct dc_cursor_position *position) { int i; - struct core_dc *core_dc; + struct dc *core_dc; struct resource_context *res_ctx; if (NULL == stream) { @@ -211,7 +211,7 @@ bool dc_stream_set_cursor_position( return false; } - core_dc = DC_TO_CORE(stream->ctx->dc); + core_dc = stream->ctx->dc; res_ctx = &core_dc->current_context->res_ctx; for (i = 0; i < MAX_PIPES; i++) { @@ -246,7 +246,7 @@ bool dc_stream_set_cursor_position( uint32_t dc_stream_get_vblank_counter(const struct dc_stream_state *stream) { uint8_t i; - struct core_dc *core_dc = DC_TO_CORE(stream->ctx->dc); + struct dc *core_dc = stream->ctx->dc; struct resource_context *res_ctx = &core_dc->current_context->res_ctx; @@ -270,7 +270,7 @@ bool dc_stream_get_scanoutpos(const struct dc_stream_state *stream, { uint8_t i; bool ret = false; - struct core_dc *core_dc = DC_TO_CORE(stream->ctx->dc); + struct dc *core_dc = stream->ctx->dc; struct resource_context *res_ctx = &core_dc->current_context->res_ctx; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index da19c7fa5151..0b6410fb2f3e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -28,7 +28,7 @@ #include "dc.h" /* DC core (private) */ -#include "core_dc.h" +#include "core_types.h" #include "transform.h" /******************************************************************************* @@ -64,9 +64,9 @@ void enable_surface_flip_reporting(struct dc_plane_state *plane_state, /*register_flip_interrupt(surface);*/ } -struct dc_plane_state *dc_create_plane_state(const struct dc *dc) +struct dc_plane_state *dc_create_plane_state(struct dc *dc) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; struct dc_plane_state *plane_state = dm_alloc(sizeof(*plane_state)); @@ -91,7 +91,7 @@ const struct dc_plane_status *dc_plane_get_status( const struct dc_plane_state *plane_state) { const struct dc_plane_status *plane_status; - struct core_dc *core_dc; + struct dc *core_dc; int i; if (!plane_state || @@ -102,7 +102,7 @@ const struct dc_plane_status *dc_plane_get_status( } plane_status = &plane_state->status; - core_dc = DC_TO_CORE(plane_state->ctx->dc); + core_dc = plane_state->ctx->dc; if (core_dc->current_context == NULL) return NULL; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index e62d15d90fdb..68056d888def 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -34,14 +34,19 @@ #include "grph_object_ctrl_defs.h" #include +#include "inc/hw_sequencer.h" +#include "dml/display_mode_lib.h" + + + #define MAX_SURFACES 3 #define MAX_STREAMS 6 #define MAX_SINKS_PER_LINK 4 + /******************************************************************************* * Display Core Interfaces ******************************************************************************/ - struct dc_caps { uint32_t max_streams; uint32_t max_links; @@ -186,7 +191,9 @@ struct dc_debug { bool disable_psr; bool force_abm_enable; }; - +struct validate_context; +struct resource_pool; +struct dce_hwseq; struct dc { struct dc_caps caps; struct dc_cap_funcs cap_funcs; @@ -194,6 +201,40 @@ struct dc { struct dc_link_funcs link_funcs; struct dc_config config; struct dc_debug debug; + + struct dc_context *ctx; + + uint8_t link_count; + struct dc_link *links[MAX_PIPES * 2]; + + struct validate_context *current_context; + struct resource_pool *res_pool; + + /* Display Engine Clock levels */ + struct dm_pp_clock_levels sclk_lvls; + + /* Inputs into BW and WM calculations. */ + struct bw_calcs_dceip *bw_dceip; + struct bw_calcs_vbios *bw_vbios; +#ifdef CONFIG_DRM_AMD_DC_DCN1_0 + struct dcn_soc_bounding_box *dcn_soc; + struct dcn_ip_params *dcn_ip; + struct display_mode_lib dml; +#endif + + /* HW functions */ + struct hw_sequencer_funcs hwss; + struct dce_hwseq *hwseq; + + /* temp store of dm_pp_display_configuration + * to compare to see if display config changed + */ + struct dm_pp_display_configuration prev_display_config; + + /* FBC compressor */ +#ifdef ENABLE_FBC + struct compressor *fbc_compressor; +#endif }; enum frame_buffer_mode { @@ -384,7 +425,7 @@ struct dc_surface_update { /* * Create a new surface with default parameters; */ -struct dc_plane_state *dc_create_plane_state(const struct dc *dc); +struct dc_plane_state *dc_create_plane_state(struct dc *dc); const struct dc_plane_status *dc_plane_get_status( const struct dc_plane_state *plane_state); @@ -558,8 +599,8 @@ void dc_stream_log( struct dal_logger *dc_logger, enum dc_log_type log_type); -uint8_t dc_get_current_stream_count(const struct dc *dc); -struct dc_stream_state *dc_get_stream_at_index(const struct dc *dc, uint8_t i); +uint8_t dc_get_current_stream_count(struct dc *dc); +struct dc_stream_state *dc_get_stream_at_index(struct dc *dc, uint8_t i); /* * Return the current frame counter. @@ -585,9 +626,9 @@ struct dc_validation_set { uint8_t plane_count; }; -bool dc_validate_stream(const struct dc *dc, struct dc_stream_state *stream); +bool dc_validate_stream(struct dc *dc, struct dc_stream_state *stream); -bool dc_validate_plane(const struct dc *dc, const struct dc_plane_state *plane_state); +bool dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state); /* * This function takes a set of resources and checks that they are cofunctional. * @@ -595,12 +636,12 @@ bool dc_validate_plane(const struct dc *dc, const struct dc_plane_state *plane_s * No hardware is programmed for call. Only validation is done. */ struct validate_context *dc_get_validate_context( - const struct dc *dc, + struct dc *dc, const struct dc_validation_set set[], uint8_t set_count); bool dc_validate_resources( - const struct dc *dc, + struct dc *dc, const struct dc_validation_set set[], uint8_t set_count); @@ -613,7 +654,7 @@ bool dc_validate_resources( */ bool dc_validate_guaranteed( - const struct dc *dc, + struct dc *dc, struct dc_stream_state *stream); void dc_resource_validate_ctx_copy_construct( @@ -764,7 +805,7 @@ struct dc_link { /* Private to DC core */ - const struct core_dc *dc; + const struct dc *dc; struct dc_context *ctx; @@ -795,9 +836,9 @@ const struct dc_link_status *dc_link_get_status(const struct dc_link *dc_link); * boot time. They cannot be created or destroyed. * Use dc_get_caps() to get number of links. */ -struct dc_link *dc_get_link_at_index(const struct dc *dc, uint32_t link_index); +struct dc_link *dc_get_link_at_index(struct dc *dc, uint32_t link_index); -struct dwbc *dc_get_dwb_at_pipe(const struct dc *dc, uint32_t pipe); +struct dwbc *dc_get_dwb_at_pipe(struct dc *dc, uint32_t pipe); /* Return id of physical connector represented by a dc_link at link_index.*/ const struct graphics_object_id dc_get_link_id_at_index( @@ -948,7 +989,7 @@ enum dc_irq_source dc_interrupt_to_irq_source( struct dc *dc, uint32_t src_id, uint32_t ext_id); -void dc_interrupt_set(const struct dc *dc, enum dc_irq_source src, bool enable); +void dc_interrupt_set(struct dc *dc, enum dc_irq_source src, bool enable); void dc_interrupt_ack(struct dc *dc, enum dc_irq_source src); enum dc_irq_source dc_get_hpd_irq_source_at_index( struct dc *dc, uint32_t link_index); @@ -960,7 +1001,7 @@ enum dc_irq_source dc_get_hpd_irq_source_at_index( void dc_set_power_state( struct dc *dc, enum dc_acpi_cm_power_state power_state); -void dc_resume(const struct dc *dc); +void dc_resume(struct dc *dc); /* * DPCD access interfaces diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index 922af2d1b91a..0654fe34627c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -34,7 +34,6 @@ #include "dce_clock_source.h" -#include "core_dc.h" #include "reg_helper.h" #define REG(reg)\ @@ -609,7 +608,7 @@ static uint32_t dce110_get_pll_pixel_rate_in_hz( struct pll_settings *pll_settings) { uint32_t inst = pix_clk_params->controller_id - CONTROLLER_ID_D0; - struct core_dc *dc_core = DC_TO_CORE(cs->ctx->dc); + struct dc *dc_core = cs->ctx->dc; struct validate_context *context = dc_core->current_context; struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[inst]; @@ -624,7 +623,7 @@ static uint32_t dce110_get_dp_pixel_rate_from_combo_phy_pll( struct pll_settings *pll_settings) { uint32_t inst = pix_clk_params->controller_id - CONTROLLER_ID_D0; - struct core_dc *dc_core = DC_TO_CORE(cs->ctx->dc); + struct dc *dc_core = cs->ctx->dc; struct validate_context *context = dc_core->current_context; struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[inst]; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c index 7bb2eaf07da5..9d67340a6b8b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c @@ -29,14 +29,12 @@ #include "fixed32_32.h" #include "bios_parser_interface.h" #include "dc.h" -#include "core_dc.h" #include "dce_abm.h" #include "dmcu.h" #if defined(CONFIG_DRM_AMD_DC_DCN1_0) #include "dcn_calcs.h" -#include "core_dc.h" #endif - +#include "core_types.h" #define TO_DCE_CLOCKS(clocks)\ @@ -368,7 +366,7 @@ static int dce_psr_set_clock( { struct dce_disp_clk *clk_dce = TO_DCE_CLOCKS(clk); struct dc_context *ctx = clk_dce->base.ctx; - struct core_dc *core_dc = DC_TO_CORE(ctx->dc); + struct dc *core_dc = ctx->dc; struct dmcu *dmcu = core_dc->res_pool->dmcu; int actual_clk_khz = requested_clk_khz; @@ -385,7 +383,7 @@ static int dce112_set_clock( struct dce_disp_clk *clk_dce = TO_DCE_CLOCKS(clk); struct bp_set_dce_clock_parameters dce_clk_params; struct dc_bios *bp = clk->ctx->dc_bios; - struct core_dc *core_dc = DC_TO_CORE(clk->ctx->dc); + struct dc *core_dc = clk->ctx->dc; struct abm *abm = core_dc->res_pool->abm; struct dmcu *dmcu = core_dc->res_pool->dmcu; int actual_clock = requested_clk_khz; @@ -621,7 +619,7 @@ static bool dce_apply_clock_voltage_request( if (send_request) { #if defined(CONFIG_DRM_AMD_DC_DCN1_0) if (clk->ctx->dce_version >= DCN_VERSION_1_0) { - struct core_dc *core_dc = DC_TO_CORE(clk->ctx->dc); + struct dc *core_dc = clk->ctx->dc; /*use dcfclk request voltage*/ clock_voltage_req.clk_type = DM_PP_CLOCK_TYPE_DCFCLK; clock_voltage_req.clocks_in_khz = diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c index 4894e1755d84..d2e66b1bc0ef 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c @@ -26,7 +26,7 @@ #include "dce_hwseq.h" #include "reg_helper.h" #include "hw_sequencer.h" -#include "core_dc.h" +#include "core_types.h" #define CTX \ hws->ctx @@ -44,7 +44,7 @@ void dce_enable_fe_clock(struct dce_hwseq *hws, DCFE_CLOCK_ENABLE, enable); } -void dce_pipe_control_lock(struct core_dc *dc, +void dce_pipe_control_lock(struct dc *dc, struct pipe_ctx *pipe, bool lock) { diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index 9a97d8ee7971..3a1eb6a79d66 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -528,7 +528,7 @@ enum blnd_mode { void dce_enable_fe_clock(struct dce_hwseq *hwss, unsigned int inst, bool enable); -void dce_pipe_control_lock(struct core_dc *dc, +void dce_pipe_control_lock(struct dc *dc, struct pipe_ctx *pipe, bool lock); diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c index c638f47acefc..b7e51c5ed1b1 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c @@ -24,7 +24,6 @@ */ #include "dm_services.h" #include "dc.h" -#include "core_dc.h" #include "core_types.h" #include "hw_sequencer.h" #include "dce100_hw_sequencer.h" @@ -71,7 +70,7 @@ static const struct dce100_hw_seq_reg_offsets reg_offsets[] = { /***************************PIPE_CONTROL***********************************/ static bool dce100_enable_display_power_gating( - struct core_dc *dc, + struct dc *dc, uint8_t controller_id, struct dc_bios *dcb, enum pipe_gating_control power_gating) @@ -107,7 +106,7 @@ static bool dce100_enable_display_power_gating( } static void dce100_pplib_apply_display_requirements( - struct core_dc *dc, + struct dc *dc, struct validate_context *context) { struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg; @@ -127,7 +126,7 @@ static void dce100_pplib_apply_display_requirements( } void dce100_set_bandwidth( - struct core_dc *dc, + struct dc *dc, struct validate_context *context, bool decrease_allowed) { @@ -143,7 +142,7 @@ void dce100_set_bandwidth( /**************************************************************************/ -bool dce100_hw_sequencer_construct(struct core_dc *dc) +bool dce100_hw_sequencer_construct(struct dc *dc) { dce110_hw_sequencer_construct(dc); diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h index 24433f0e770b..c04aa15cd656 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h @@ -28,13 +28,13 @@ #include "core_types.h" -struct core_dc; +struct dc; struct validate_context; -bool dce100_hw_sequencer_construct(struct core_dc *dc); +bool dce100_hw_sequencer_construct(struct dc *dc); void dce100_set_bandwidth( - struct core_dc *dc, + struct dc *dc, struct validate_context *context, bool decrease_allowed); diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 46f0c71fbac4..b2b03633eb4f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -652,7 +652,7 @@ static void destruct(struct dce110_resource_pool *pool) } static enum dc_status build_mapped_resource( - const struct core_dc *dc, + const struct dc *dc, struct validate_context *context, struct validate_context *old_context) { @@ -688,7 +688,7 @@ static enum dc_status build_mapped_resource( } bool dce100_validate_bandwidth( - const struct core_dc *dc, + struct dc *dc, struct validate_context *context) { /* TODO implement when needed but for now hardcode max value*/ @@ -720,7 +720,7 @@ static bool dce100_validate_surface_sets( } enum dc_status dce100_validate_with_context( - const struct core_dc *dc, + struct dc *dc, const struct dc_validation_set set[], int set_count, struct validate_context *context, @@ -764,7 +764,7 @@ enum dc_status dce100_validate_with_context( } enum dc_status dce100_validate_guaranteed( - const struct core_dc *dc, + struct dc *dc, struct dc_stream_state *dc_stream, struct validate_context *context) { @@ -784,7 +784,7 @@ enum dc_status dce100_validate_guaranteed( if (result == DC_OK) { validate_guaranteed_copy_streams( - context, dc->public.caps.max_streams); + context, dc->caps.max_streams); result = resource_build_scaling_params_for_context(dc, context); } @@ -824,7 +824,7 @@ static const struct resource_funcs dce100_res_pool_funcs = { static bool construct( uint8_t num_virtual_links, - struct core_dc *dc, + struct dc *dc, struct dce110_resource_pool *pool) { unsigned int i; @@ -909,9 +909,9 @@ static bool construct( *************************************************/ pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; pool->base.pipe_count = res_cap.num_timing_generator; - dc->public.caps.max_downscale_ratio = 200; - dc->public.caps.i2c_speed_in_khz = 40; - dc->public.caps.max_cursor_size = 128; + dc->caps.max_downscale_ratio = 200; + dc->caps.i2c_speed_in_khz = 40; + dc->caps.max_cursor_size = 128; for (i = 0; i < pool->base.pipe_count; i++) { pool->base.timing_generators[i] = @@ -958,7 +958,7 @@ static bool construct( } } - dc->public.caps.max_planes = pool->base.pipe_count; + dc->caps.max_planes = pool->base.pipe_count; if (!resource_construct(num_virtual_links, dc, &pool->base, &res_create_funcs)) @@ -978,7 +978,7 @@ res_create_fail: struct resource_pool *dce100_create_resource_pool( uint8_t num_virtual_links, - struct core_dc *dc) + struct dc *dc) { struct dce110_resource_pool *pool = dm_alloc(sizeof(struct dce110_resource_pool)); diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h index edc50caf04d1..ca7b2b7c1a48 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h @@ -8,13 +8,13 @@ #ifndef DCE100_RESOURCE_H_ #define DCE100_RESOURCE_H_ -struct core_dc; +struct dc; struct resource_pool; struct dc_validation_set; struct resource_pool *dce100_create_resource_pool( uint8_t num_virtual_links, - struct core_dc *dc); + struct dc *dc); enum dc_status dce100_validate_plane(const struct dc_plane_state *plane_state); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index ccde7c80d658..e6c6f1108078 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -164,7 +164,7 @@ static void enable_display_pipe_clock_gating( } static bool dce110_enable_display_power_gating( - struct core_dc *dc, + struct dc *dc, uint8_t controller_id, struct dc_bios *dcb, enum pipe_gating_control power_gating) @@ -944,7 +944,7 @@ static void get_surface_visual_confirm_color(const struct pipe_ctx *pipe_ctx, } } -static void program_scaler(const struct core_dc *dc, +static void program_scaler(const struct dc *dc, const struct pipe_ctx *pipe_ctx) { struct tg_color color = {0}; @@ -955,7 +955,7 @@ static void program_scaler(const struct core_dc *dc, return; #endif - if (dc->public.debug.surface_visual_confirm) + if (dc->debug.surface_visual_confirm) get_surface_visual_confirm_color(pipe_ctx, &color); else color_space_to_black_color(dc, @@ -979,7 +979,7 @@ static void program_scaler(const struct core_dc *dc, static enum dc_status dce110_prog_pixclk_crtc_otg( struct pipe_ctx *pipe_ctx, struct validate_context *context, - struct core_dc *dc) + struct dc *dc) { struct dc_stream_state *stream = pipe_ctx->stream; struct pipe_ctx *pipe_ctx_old = &dc->current_context->res_ctx. @@ -1035,7 +1035,7 @@ static enum dc_status dce110_prog_pixclk_crtc_otg( static enum dc_status apply_single_controller_ctx_to_hw( struct pipe_ctx *pipe_ctx, struct validate_context *context, - struct core_dc *dc) + struct dc *dc) { struct dc_stream_state *stream = pipe_ctx->stream; struct pipe_ctx *pipe_ctx_old = &dc->current_context->res_ctx. @@ -1146,7 +1146,7 @@ static enum dc_status apply_single_controller_ctx_to_hw( /******************************************************************************/ -static void power_down_encoders(struct core_dc *dc) +static void power_down_encoders(struct dc *dc) { int i; @@ -1156,7 +1156,7 @@ static void power_down_encoders(struct core_dc *dc) } } -static void power_down_controllers(struct core_dc *dc) +static void power_down_controllers(struct dc *dc) { int i; @@ -1166,7 +1166,7 @@ static void power_down_controllers(struct core_dc *dc) } } -static void power_down_clock_sources(struct core_dc *dc) +static void power_down_clock_sources(struct dc *dc) { int i; @@ -1181,7 +1181,7 @@ static void power_down_clock_sources(struct core_dc *dc) } } -static void power_down_all_hw_blocks(struct core_dc *dc) +static void power_down_all_hw_blocks(struct dc *dc) { power_down_encoders(dc); @@ -1196,7 +1196,7 @@ static void power_down_all_hw_blocks(struct core_dc *dc) } static void disable_vga_and_power_gate_all_controllers( - struct core_dc *dc) + struct dc *dc) { int i; struct timing_generator *tg; @@ -1224,7 +1224,7 @@ static void disable_vga_and_power_gate_all_controllers( * 3. Enable power gating for controller * 4. Set acc_mode_change bit (VBIOS will clear this bit when going to FSDOS) */ -void dce110_enable_accelerated_mode(struct core_dc *dc) +void dce110_enable_accelerated_mode(struct dc *dc) { power_down_all_hw_blocks(dc); @@ -1250,7 +1250,7 @@ static uint32_t compute_pstate_blackout_duration( } void dce110_set_displaymarks( - const struct core_dc *dc, + const struct dc *dc, struct validate_context *context) { uint8_t i, num_pipes; @@ -1316,7 +1316,7 @@ static void set_safe_displaymarks( } static void switch_dp_clock_sources( - const struct core_dc *dc, + const struct dc *dc, struct resource_context *res_ctx) { uint8_t i; @@ -1408,7 +1408,7 @@ static void set_static_screen_control(struct pipe_ctx **pipe_ctx, * may read PLL register to get pixel clock */ static uint32_t get_max_pixel_clock_for_all_paths( - struct core_dc *dc, + struct dc *dc, struct validate_context *context, bool pre_mode_set) { @@ -1449,7 +1449,7 @@ static uint32_t get_max_pixel_clock_for_all_paths( * etc support for dcn1.0 */ static void apply_min_clocks( - struct core_dc *dc, + struct dc *dc, struct validate_context *context, enum dm_pp_clocks_state *clocks_state, bool pre_mode_set) @@ -1538,7 +1538,7 @@ static void apply_min_clocks( /* * Check if FBC can be enabled */ -static enum dc_status validate_fbc(struct core_dc *dc, +static enum dc_status validate_fbc(struct dc *dc, struct validate_context *context) { struct pipe_ctx *pipe_ctx = @@ -1568,7 +1568,7 @@ static enum dc_status validate_fbc(struct core_dc *dc, /* * Enable FBC */ -static enum dc_status enable_fbc(struct core_dc *dc, +static enum dc_status enable_fbc(struct dc *dc, struct validate_context *context) { enum dc_status status = validate_fbc(dc, context); @@ -1597,7 +1597,7 @@ static enum dc_status enable_fbc(struct core_dc *dc, #endif static enum dc_status apply_ctx_to_hw_fpga( - struct core_dc *dc, + struct dc *dc, struct validate_context *context) { enum dc_status status = DC_ERROR_UNEXPECTED; @@ -1627,7 +1627,7 @@ static enum dc_status apply_ctx_to_hw_fpga( } static void dce110_reset_hw_ctx_wrap( - struct core_dc *dc, + struct dc *dc, struct validate_context *context) { int i; @@ -1672,7 +1672,7 @@ static void dce110_reset_hw_ctx_wrap( enum dc_status dce110_apply_ctx_to_hw( - struct core_dc *dc, + struct dc *dc, struct validate_context *context) { struct dc_bios *dcb = dc->ctx->dc_bios; @@ -1965,7 +1965,7 @@ static void set_default_colors(struct pipe_ctx *pipe_ctx) * -------------------------------------------------| * ******************************************************************************/ -static void program_surface_visibility(const struct core_dc *dc, +static void program_surface_visibility(const struct dc *dc, struct pipe_ctx *pipe_ctx) { enum blnd_mode blender_mode = BLND_MODE_CURRENT_PIPE; @@ -2038,7 +2038,7 @@ static void program_gamut_remap(struct pipe_ctx *pipe_ctx) * TODO REMOVE, USE UPDATE INSTEAD */ static void set_plane_config( - const struct core_dc *dc, + const struct dc *dc, struct pipe_ctx *pipe_ctx, struct resource_context *res_ctx) { @@ -2117,7 +2117,7 @@ static void set_plane_config( if (mi->funcs->set_blank) mi->funcs->set_blank(mi, pipe_ctx->plane_state->visible); - if (dc->public.config.gpu_vm_support) + if (dc->config.gpu_vm_support) mi->funcs->mem_input_program_pte_vm( pipe_ctx->plane_res.mi, plane_state->format, @@ -2125,7 +2125,7 @@ static void set_plane_config( plane_state->rotation); } -static void update_plane_addr(const struct core_dc *dc, +static void update_plane_addr(const struct dc *dc, struct pipe_ctx *pipe_ctx) { struct dc_plane_state *plane_state = pipe_ctx->plane_state; @@ -2163,7 +2163,7 @@ void dce110_update_pending_status(struct pipe_ctx *pipe_ctx) } } -void dce110_power_down(struct core_dc *dc) +void dce110_power_down(struct dc *dc) { power_down_all_hw_blocks(dc); disable_vga_and_power_gate_all_controllers(dc); @@ -2208,7 +2208,7 @@ static bool wait_for_reset_trigger_to_occur( /* Enable timing synchronization for a group of Timing Generators. */ static void dce110_enable_timing_synchronization( - struct core_dc *dc, + struct dc *dc, int group_index, int group_size, struct pipe_ctx *grouped_pipes[]) @@ -2257,7 +2257,7 @@ static void dce110_enable_timing_synchronization( DC_SYNC_INFO("GSL: Set-up complete.\n"); } -static void init_hw(struct core_dc *dc) +static void init_hw(struct dc *dc) { int i; struct dc_bios *bp; @@ -2394,7 +2394,7 @@ uint32_t dce110_get_min_vblank_time_us(const struct validate_context *context) } static int determine_sclk_from_bounding_box( - const struct core_dc *dc, + const struct dc *dc, int required_sclk) { int i; @@ -2420,7 +2420,7 @@ static int determine_sclk_from_bounding_box( } static void pplib_apply_display_requirements( - struct core_dc *dc, + struct dc *dc, struct validate_context *context) { struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg; @@ -2474,7 +2474,7 @@ static void pplib_apply_display_requirements( } static void dce110_set_bandwidth( - struct core_dc *dc, + struct dc *dc, struct validate_context *context, bool decrease_allowed) { @@ -2491,7 +2491,7 @@ static void dce110_set_bandwidth( } static void dce110_program_front_end_for_pipe( - struct core_dc *dc, struct pipe_ctx *pipe_ctx) + struct dc *dc, struct pipe_ctx *pipe_ctx) { struct mem_input *mi = pipe_ctx->plane_res.mi; struct pipe_ctx *old_pipe = NULL; @@ -2572,7 +2572,7 @@ static void dce110_program_front_end_for_pipe( if (mi->funcs->set_blank) mi->funcs->set_blank(mi, pipe_ctx->plane_state->visible); - if (dc->public.config.gpu_vm_support) + if (dc->config.gpu_vm_support) mi->funcs->mem_input_program_pte_vm( pipe_ctx->plane_res.mi, plane_state->format, @@ -2618,7 +2618,7 @@ static void dce110_program_front_end_for_pipe( } static void dce110_apply_ctx_for_surface( - struct core_dc *dc, + struct dc *dc, const struct dc_stream_state *stream, int num_planes, struct validate_context *context) @@ -2648,7 +2648,7 @@ static void dce110_apply_ctx_for_surface( } } -static void dce110_power_down_fe(struct core_dc *dc, int fe_idx) +static void dce110_power_down_fe(struct dc *dc, int fe_idx) { /* Do not power down fe when stream is active on dce*/ if (dc->current_context->res_ctx.pipe_ctx[fe_idx].stream) @@ -2662,7 +2662,7 @@ static void dce110_power_down_fe(struct core_dc *dc, int fe_idx) } static void dce110_wait_for_mpcc_disconnect( - struct core_dc *dc, + struct dc *dc, struct resource_pool *res_pool, struct pipe_ctx *pipe_ctx) { @@ -2724,7 +2724,7 @@ static const struct hw_sequencer_funcs dce110_funcs = { .wait_for_mpcc_disconnect = dce110_wait_for_mpcc_disconnect }; -bool dce110_hw_sequencer_construct(struct core_dc *dc) +bool dce110_hw_sequencer_construct(struct dc *dc) { dc->hwss = dce110_funcs; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h index 89782ca1917f..d710f6e6dc07 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h @@ -29,20 +29,20 @@ #include "core_types.h" #define GAMMA_HW_POINTS_NUM 256 -struct core_dc; +struct dc; struct validate_context; struct dm_pp_display_configuration; -bool dce110_hw_sequencer_construct(struct core_dc *dc); +bool dce110_hw_sequencer_construct(struct dc *dc); enum dc_status dce110_apply_ctx_to_hw( - struct core_dc *dc, + struct dc *dc, struct validate_context *context); void dce110_set_display_clock(struct validate_context *context); void dce110_set_displaymarks( - const struct core_dc *dc, + const struct dc *dc, struct validate_context *context); void dce110_enable_stream(struct pipe_ctx *pipe_ctx); @@ -55,9 +55,9 @@ void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, void dce110_update_info_frame(struct pipe_ctx *pipe_ctx); void dce110_set_avmute(struct pipe_ctx *pipe_ctx, bool enable); -void dce110_enable_accelerated_mode(struct core_dc *dc); +void dce110_enable_accelerated_mode(struct dc *dc); -void dce110_power_down(struct core_dc *dc); +void dce110_power_down(struct dc *dc); void dce110_update_pending_status(struct pipe_ctx *pipe_ctx); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 56be84ce5a0d..2154c2e567f2 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -772,7 +772,7 @@ static bool is_surface_pixel_format_supported(struct pipe_ctx *pipe_ctx, unsigne } static enum dc_status build_mapped_resource( - const struct core_dc *dc, + const struct dc *dc, struct validate_context *context, struct validate_context *old_context) { @@ -814,7 +814,7 @@ static enum dc_status build_mapped_resource( } static bool dce110_validate_bandwidth( - const struct core_dc *dc, + struct dc *dc, struct validate_context *context) { bool result = false; @@ -928,7 +928,7 @@ static bool dce110_validate_surface_sets( } static enum dc_status dce110_validate_with_context( - const struct core_dc *dc, + struct dc *dc, const struct dc_validation_set set[], int set_count, struct validate_context *context, @@ -972,7 +972,7 @@ static enum dc_status dce110_validate_with_context( } static enum dc_status dce110_validate_guaranteed( - const struct core_dc *dc, + struct dc *dc, struct dc_stream_state *dc_stream, struct validate_context *context) { @@ -992,7 +992,7 @@ static enum dc_status dce110_validate_guaranteed( if (result == DC_OK) { validate_guaranteed_copy_streams( - context, dc->public.caps.max_streams); + context, dc->caps.max_streams); result = resource_build_scaling_params_for_context(dc, context); } @@ -1008,7 +1008,7 @@ static struct pipe_ctx *dce110_acquire_underlay( const struct resource_pool *pool, struct dc_stream_state *stream) { - struct core_dc *dc = DC_TO_CORE(stream->ctx->dc); + struct dc *dc = stream->ctx->dc; struct resource_context *res_ctx = &context->res_ctx; unsigned int underlay_idx = pool->underlay_pipe_index; struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[underlay_idx]; @@ -1117,7 +1117,7 @@ static bool underlay_create(struct dc_context *ctx, struct resource_pool *pool) return true; } -static void bw_calcs_data_update_from_pplib(struct core_dc *dc) +static void bw_calcs_data_update_from_pplib(struct dc *dc) { struct dm_pp_clock_levels clks = {0}; @@ -1184,7 +1184,7 @@ const struct resource_caps *dce110_resource_cap( static bool construct( uint8_t num_virtual_links, - struct core_dc *dc, + struct dc *dc, struct dce110_resource_pool *pool, struct hw_asic_id asic_id) { @@ -1206,9 +1206,9 @@ static bool construct( pool->base.pipe_count = pool->base.res_cap->num_timing_generator; pool->base.underlay_pipe_index = pool->base.pipe_count; - dc->public.caps.max_downscale_ratio = 150; - dc->public.caps.i2c_speed_in_khz = 100; - dc->public.caps.max_cursor_size = 128; + dc->caps.max_downscale_ratio = 150; + dc->caps.i2c_speed_in_khz = 100; + dc->caps.max_cursor_size = 128; /************************************************* * Create resources * @@ -1351,7 +1351,7 @@ static bool construct( if (!dce110_hw_sequencer_construct(dc)) goto res_create_fail; - dc->public.caps.max_planes = pool->base.pipe_count; + dc->caps.max_planes = pool->base.pipe_count; bw_calcs_init(dc->bw_dceip, dc->bw_vbios, dc->ctx->asic_id); @@ -1366,7 +1366,7 @@ res_create_fail: struct resource_pool *dce110_create_resource_pool( uint8_t num_virtual_links, - struct core_dc *dc, + struct dc *dc, struct hw_asic_id asic_id) { struct dce110_resource_pool *pool = diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.h index 8e2e85dd30b9..5bb692d037d9 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.h @@ -28,7 +28,7 @@ #include "core_types.h" -struct core_dc; +struct dc; struct resource_pool; #define TO_DCE110_RES_POOL(pool)\ @@ -42,7 +42,7 @@ enum dc_status dce110_resource_build_pipe_hw_param(struct pipe_ctx *pipe_ctx); struct resource_pool *dce110_create_resource_pool( uint8_t num_virtual_links, - struct core_dc *dc, + struct dc *dc, struct hw_asic_id asic_id); #endif /* __DC_RESOURCE_DCE110_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.c index 204f613467b7..8816e09110e1 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.c @@ -25,7 +25,6 @@ #include "dm_services.h" #include "dc.h" -#include "core_dc.h" #include "core_types.h" #include "dce112_hw_sequencer.h" @@ -112,7 +111,7 @@ static void dce112_init_pte(struct dc_context *ctx) } static bool dce112_enable_display_power_gating( - struct core_dc *dc, + struct dc *dc, uint8_t controller_id, struct dc_bios *dcb, enum pipe_gating_control power_gating) @@ -153,7 +152,7 @@ static bool dce112_enable_display_power_gating( return false; } -bool dce112_hw_sequencer_construct(struct core_dc *dc) +bool dce112_hw_sequencer_construct(struct dc *dc) { /* All registers used by dce11.2 match those in dce11 in offset and * structure diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.h index d96c582da45c..37bd60cc93f9 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.h @@ -28,9 +28,9 @@ #include "core_types.h" -struct core_dc; +struct dc; -bool dce112_hw_sequencer_construct(struct core_dc *dc); +bool dce112_hw_sequencer_construct(struct dc *dc); #endif /* __DC_HWSS_DCE112_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index d6e58a25f3d0..89a8dfa68c01 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -723,7 +723,7 @@ static struct clock_source *find_matching_pll( } static enum dc_status build_mapped_resource( - const struct core_dc *dc, + const struct dc *dc, struct validate_context *context, struct validate_context *old_context) { @@ -759,7 +759,7 @@ static enum dc_status build_mapped_resource( } bool dce112_validate_bandwidth( - const struct core_dc *dc, + struct dc *dc, struct validate_context *context) { bool result = false; @@ -837,7 +837,7 @@ bool dce112_validate_bandwidth( } enum dc_status resource_map_phy_clock_resources( - const struct core_dc *dc, + const struct dc *dc, struct validate_context *context, struct validate_context *old_context) { @@ -904,7 +904,7 @@ static bool dce112_validate_surface_sets( } enum dc_status dce112_validate_with_context( - const struct core_dc *dc, + struct dc *dc, const struct dc_validation_set set[], int set_count, struct validate_context *context, @@ -948,7 +948,7 @@ enum dc_status dce112_validate_with_context( } enum dc_status dce112_validate_guaranteed( - const struct core_dc *dc, + struct dc *dc, struct dc_stream_state *stream, struct validate_context *context) { @@ -968,7 +968,7 @@ enum dc_status dce112_validate_guaranteed( if (result == DC_OK) { validate_guaranteed_copy_streams( - context, dc->public.caps.max_streams); + context, dc->caps.max_streams); result = resource_build_scaling_params_for_context(dc, context); } @@ -997,7 +997,7 @@ static const struct resource_funcs dce112_res_pool_funcs = { .validate_plane = dce100_validate_plane }; -static void bw_calcs_data_update_from_pplib(struct core_dc *dc) +static void bw_calcs_data_update_from_pplib(struct dc *dc) { struct dm_pp_clock_levels_with_latency eng_clks = {0}; struct dm_pp_clock_levels_with_latency mem_clks = {0}; @@ -1153,7 +1153,7 @@ const struct resource_caps *dce112_resource_cap( static bool construct( uint8_t num_virtual_links, - struct core_dc *dc, + struct dc *dc, struct dce110_resource_pool *pool) { unsigned int i; @@ -1170,9 +1170,9 @@ static bool construct( *************************************************/ pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; pool->base.pipe_count = pool->base.res_cap->num_timing_generator; - dc->public.caps.max_downscale_ratio = 200; - dc->public.caps.i2c_speed_in_khz = 100; - dc->public.caps.max_cursor_size = 128; + dc->caps.max_downscale_ratio = 200; + dc->caps.i2c_speed_in_khz = 100; + dc->caps.max_cursor_size = 128; /************************************************* * Create resources * @@ -1319,7 +1319,7 @@ static bool construct( &res_create_funcs)) goto res_create_fail; - dc->public.caps.max_planes = pool->base.pipe_count; + dc->caps.max_planes = pool->base.pipe_count; /* Create hardware sequencer */ if (!dce112_hw_sequencer_construct(dc)) @@ -1338,7 +1338,7 @@ res_create_fail: struct resource_pool *dce112_create_resource_pool( uint8_t num_virtual_links, - struct core_dc *dc) + struct dc *dc) { struct dce110_resource_pool *pool = dm_alloc(sizeof(struct dce110_resource_pool)); diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h index feef559f1ecd..69f8f689196d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h @@ -28,27 +28,27 @@ #include "core_types.h" -struct core_dc; +struct dc; struct resource_pool; struct resource_pool *dce112_create_resource_pool( uint8_t num_virtual_links, - struct core_dc *dc); + struct dc *dc); enum dc_status dce112_validate_with_context( - const struct core_dc *dc, + struct dc *dc, const struct dc_validation_set set[], int set_count, struct validate_context *context, struct validate_context *old_context); enum dc_status dce112_validate_guaranteed( - const struct core_dc *dc, + struct dc *dc, struct dc_stream_state *dc_stream, struct validate_context *context); bool dce112_validate_bandwidth( - const struct core_dc *dc, + struct dc *dc, struct validate_context *context); diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c index 91301b412aa0..d6225f332431 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c @@ -25,7 +25,6 @@ #include "dm_services.h" #include "dc.h" -#include "core_dc.h" #include "core_types.h" #include "dce120_hw_sequencer.h" #include "dce/dce_hwseq.h" @@ -149,7 +148,7 @@ static void dce120_init_pte(struct dc_context *ctx, uint8_t controller_id) #endif static bool dce120_enable_display_power_gating( - struct core_dc *dc, + struct dc *dc, uint8_t controller_id, struct dc_bios *dcb, enum pipe_gating_control power_gating) @@ -247,7 +246,7 @@ static void dce120_update_dchub( -bool dce120_hw_sequencer_construct(struct core_dc *dc) +bool dce120_hw_sequencer_construct(struct dc *dc) { /* All registers used by dce11.2 match those in dce11 in offset and * structure diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.h index 3402413c7156..6448a17c2fde 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.h @@ -28,9 +28,9 @@ #include "core_types.h" -struct core_dc; +struct dc; -bool dce120_hw_sequencer_construct(struct core_dc *dc); +bool dce120_hw_sequencer_construct(struct dc *dc); #endif /* __DC_HWSS_DCE112_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index 562ae2205a90..b8fcdff40db3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -410,7 +410,7 @@ void dce120_clock_source_destroy(struct clock_source **clk_src) } -bool dce120_hw_sequencer_create(struct core_dc *dc) +bool dce120_hw_sequencer_create(struct dc *dc) { /* All registers used by dce11.2 match those in dce11 in offset and * structure @@ -704,7 +704,7 @@ static const struct resource_funcs dce120_res_pool_funcs = { .validate_plane = dce100_validate_plane }; -static void bw_calcs_data_update_from_pplib(struct core_dc *dc) +static void bw_calcs_data_update_from_pplib(struct dc *dc) { struct dm_pp_clock_levels_with_latency eng_clks = {0}; struct dm_pp_clock_levels_with_latency mem_clks = {0}; @@ -831,7 +831,7 @@ static void bw_calcs_data_update_from_pplib(struct core_dc *dc) static bool construct( uint8_t num_virtual_links, - struct core_dc *dc, + struct dc *dc, struct dce110_resource_pool *pool) { unsigned int i; @@ -847,10 +847,10 @@ static bool construct( pool->base.pipe_count = res_cap.num_timing_generator; pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; - dc->public.caps.max_downscale_ratio = 200; - dc->public.caps.i2c_speed_in_khz = 100; - dc->public.caps.max_cursor_size = 128; - dc->public.debug = debug_defaults; + dc->caps.max_downscale_ratio = 200; + dc->caps.i2c_speed_in_khz = 100; + dc->caps.max_cursor_size = 128; + dc->debug = debug_defaults; /************************************************* * Create resources * @@ -982,7 +982,7 @@ static bool construct( if (!dce120_hw_sequencer_create(dc)) goto controller_create_fail; - dc->public.caps.max_planes = pool->base.pipe_count; + dc->caps.max_planes = pool->base.pipe_count; bw_calcs_init(dc->bw_dceip, dc->bw_vbios, dc->ctx->asic_id); @@ -1003,7 +1003,7 @@ res_create_fail: struct resource_pool *dce120_create_resource_pool( uint8_t num_virtual_links, - struct core_dc *dc) + struct dc *dc) { struct dce110_resource_pool *pool = dm_alloc(sizeof(struct dce110_resource_pool)); diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.h b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.h index 038c78dcc247..3d1f3cf012f4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.h @@ -28,12 +28,12 @@ #include "core_types.h" -struct core_dc; +struct dc; struct resource_pool; struct resource_pool *dce120_create_resource_pool( uint8_t num_virtual_links, - struct core_dc *dc); + struct dc *dc); #endif /* __DC_RESOURCE_DCE120_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c index 4cba80ff6ca4..28fe3824441f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c @@ -25,7 +25,6 @@ #include "dm_services.h" #include "dc.h" -#include "core_dc.h" #include "core_types.h" #include "dce80_hw_sequencer.h" @@ -72,7 +71,7 @@ static const struct dce80_hw_seq_reg_offsets reg_offsets[] = { /***************************PIPE_CONTROL***********************************/ static bool dce80_enable_display_power_gating( - struct core_dc *dc, + struct dc *dc, uint8_t controller_id, struct dc_bios *dcb, enum pipe_gating_control power_gating) @@ -107,7 +106,7 @@ static bool dce80_enable_display_power_gating( return false; } -bool dce80_hw_sequencer_construct(struct core_dc *dc) +bool dce80_hw_sequencer_construct(struct dc *dc) { dce110_hw_sequencer_construct(dc); diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.h index 7cc203f433d3..9d6dd05bd596 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.h @@ -28,9 +28,9 @@ #include "core_types.h" -struct core_dc; +struct dc; -bool dce80_hw_sequencer_construct(struct core_dc *dc); +bool dce80_hw_sequencer_construct(struct dc *dc); #endif /* __DC_HWSS_DCE80_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 132117e8bb77..838bfdaee009 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -684,7 +684,7 @@ static void destruct(struct dce110_resource_pool *pool) } static enum dc_status build_mapped_resource( - const struct core_dc *dc, + const struct dc *dc, struct validate_context *context, struct validate_context *old_context) { @@ -720,7 +720,7 @@ static enum dc_status build_mapped_resource( } bool dce80_validate_bandwidth( - const struct core_dc *dc, + struct dc *dc, struct validate_context *context) { /* TODO implement when needed but for now hardcode max value*/ @@ -752,7 +752,7 @@ static bool dce80_validate_surface_sets( } enum dc_status dce80_validate_with_context( - const struct core_dc *dc, + struct dc *dc, const struct dc_validation_set set[], int set_count, struct validate_context *context, @@ -795,7 +795,7 @@ enum dc_status dce80_validate_with_context( } enum dc_status dce80_validate_guaranteed( - const struct core_dc *dc, + struct dc *dc, struct dc_stream_state *dc_stream, struct validate_context *context) { @@ -815,7 +815,7 @@ enum dc_status dce80_validate_guaranteed( if (result == DC_OK) { validate_guaranteed_copy_streams( - context, dc->public.caps.max_streams); + context, dc->caps.max_streams); result = resource_build_scaling_params_for_context(dc, context); } @@ -845,7 +845,7 @@ static const struct resource_funcs dce80_res_pool_funcs = { static bool dce80_construct( uint8_t num_virtual_links, - struct core_dc *dc, + struct dc *dc, struct dce110_resource_pool *pool) { unsigned int i; @@ -865,9 +865,9 @@ static bool dce80_construct( *************************************************/ pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; pool->base.pipe_count = res_cap.num_timing_generator; - dc->public.caps.max_downscale_ratio = 200; - dc->public.caps.i2c_speed_in_khz = 40; - dc->public.caps.max_cursor_size = 128; + dc->caps.max_downscale_ratio = 200; + dc->caps.i2c_speed_in_khz = 40; + dc->caps.max_cursor_size = 128; /************************************************* * Create resources * @@ -974,7 +974,7 @@ static bool dce80_construct( } } - dc->public.caps.max_planes = pool->base.pipe_count; + dc->caps.max_planes = pool->base.pipe_count; if (!resource_construct(num_virtual_links, dc, &pool->base, &res_create_funcs)) @@ -993,7 +993,7 @@ res_create_fail: struct resource_pool *dce80_create_resource_pool( uint8_t num_virtual_links, - struct core_dc *dc) + struct dc *dc) { struct dce110_resource_pool *pool = dm_alloc(sizeof(struct dce110_resource_pool)); @@ -1010,7 +1010,7 @@ struct resource_pool *dce80_create_resource_pool( static bool dce81_construct( uint8_t num_virtual_links, - struct core_dc *dc, + struct dc *dc, struct dce110_resource_pool *pool) { unsigned int i; @@ -1030,9 +1030,9 @@ static bool dce81_construct( *************************************************/ pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; pool->base.pipe_count = res_cap_81.num_timing_generator; - dc->public.caps.max_downscale_ratio = 200; - dc->public.caps.i2c_speed_in_khz = 40; - dc->public.caps.max_cursor_size = 128; + dc->caps.max_downscale_ratio = 200; + dc->caps.i2c_speed_in_khz = 40; + dc->caps.max_cursor_size = 128; /************************************************* * Create resources * @@ -1139,7 +1139,7 @@ static bool dce81_construct( } } - dc->public.caps.max_planes = pool->base.pipe_count; + dc->caps.max_planes = pool->base.pipe_count; if (!resource_construct(num_virtual_links, dc, &pool->base, &res_create_funcs)) @@ -1158,7 +1158,7 @@ res_create_fail: struct resource_pool *dce81_create_resource_pool( uint8_t num_virtual_links, - struct core_dc *dc) + struct dc *dc) { struct dce110_resource_pool *pool = dm_alloc(sizeof(struct dce110_resource_pool)); @@ -1175,7 +1175,7 @@ struct resource_pool *dce81_create_resource_pool( static bool dce83_construct( uint8_t num_virtual_links, - struct core_dc *dc, + struct dc *dc, struct dce110_resource_pool *pool) { unsigned int i; @@ -1195,9 +1195,9 @@ static bool dce83_construct( *************************************************/ pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; pool->base.pipe_count = res_cap_83.num_timing_generator; - dc->public.caps.max_downscale_ratio = 200; - dc->public.caps.i2c_speed_in_khz = 40; - dc->public.caps.max_cursor_size = 128; + dc->caps.max_downscale_ratio = 200; + dc->caps.i2c_speed_in_khz = 40; + dc->caps.max_cursor_size = 128; /************************************************* * Create resources * @@ -1300,7 +1300,7 @@ static bool dce83_construct( } } - dc->public.caps.max_planes = pool->base.pipe_count; + dc->caps.max_planes = pool->base.pipe_count; if (!resource_construct(num_virtual_links, dc, &pool->base, &res_create_funcs)) @@ -1319,7 +1319,7 @@ res_create_fail: struct resource_pool *dce83_create_resource_pool( uint8_t num_virtual_links, - struct core_dc *dc) + struct dc *dc) { struct dce110_resource_pool *pool = dm_alloc(sizeof(struct dce110_resource_pool)); diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.h b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.h index 04f0cfe24ef2..eff31ab83a39 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.h @@ -28,20 +28,20 @@ #include "core_types.h" -struct core_dc; +struct dc; struct resource_pool; struct resource_pool *dce80_create_resource_pool( uint8_t num_virtual_links, - struct core_dc *dc); + struct dc *dc); struct resource_pool *dce81_create_resource_pool( uint8_t num_virtual_links, - struct core_dc *dc); + struct dc *dc); struct resource_pool *dce83_create_resource_pool( uint8_t num_virtual_links, - struct core_dc *dc); + struct dc *dc); #endif /* __DC_RESOURCE_DCE80_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c index 11386121f8ed..684241cb40d7 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c @@ -26,7 +26,6 @@ #if defined(CONFIG_DRM_AMD_DC_DCN1_0) #include "reg_helper.h" -#include "core_dc.h" #include "resource.h" #include "dwb.h" #include "dcn10_dwb.h" diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 184627c8685e..d5d2398d92b8 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -52,7 +52,7 @@ #define FN(reg_name, field_name) \ hws->shifts->field_name, hws->masks->field_name -static void log_mpc_crc(struct core_dc *dc) +static void log_mpc_crc(struct dc *dc) { struct dc_context *dc_ctx = dc->ctx; struct dce_hwseq *hws = dc->hwseq; @@ -130,7 +130,7 @@ static void dcn10_hubbub_wm_read_state(struct dce_hwseq *hws, s->dram_clk_chanage = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D); } -static void dcn10_log_hubbub_state(struct core_dc *dc) +static void dcn10_log_hubbub_state(struct dc *dc) { struct dc_context *dc_ctx = dc->ctx; struct dcn_hubbub_wm wm; @@ -157,7 +157,7 @@ static void dcn10_log_hubbub_state(struct core_dc *dc) DTN_INFO("\n"); } -static void dcn10_log_hw_state(struct core_dc *dc) +static void dcn10_log_hw_state(struct dc *dc) { struct dc_context *dc_ctx = dc->ctx; struct resource_pool *pool = dc->res_pool; @@ -273,7 +273,7 @@ static void verify_allow_pstate_change_high( forced_pstate_allow = true; if (should_log_hw_state) { - dcn10_log_hw_state(DC_TO_CORE(hws->ctx->dc)); + dcn10_log_hw_state(hws->ctx->dc); } BREAK_TO_DEBUGGER(); @@ -746,7 +746,7 @@ static void power_on_plane( "Un-gated front end for pipe %d\n", plane_id); } -static void bios_golden_init(struct core_dc *dc) +static void bios_golden_init(struct dc *dc) { struct dc_bios *bp = dc->ctx->dc_bios; int i; @@ -762,7 +762,7 @@ static void bios_golden_init(struct core_dc *dc) } } -static void dcn10_init_hw(struct core_dc *dc) +static void dcn10_init_hw(struct dc *dc) { int i; struct abm *abm = dc->res_pool->abm; @@ -773,7 +773,7 @@ static void dcn10_init_hw(struct core_dc *dc) REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1); REG_WRITE(DIO_MEM_PWR_CTRL, 0); - if (!dc->public.debug.disable_clock_gate) { + if (!dc->debug.disable_clock_gate) { /* enable all DCN clock gating */ REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0); @@ -830,7 +830,7 @@ static void dcn10_init_hw(struct core_dc *dc) /* power AFMT HDMI memory TODO: may move to dis/en output save power*/ REG_WRITE(DIO_MEM_PWR_CTRL, 0); - if (!dc->public.debug.disable_clock_gate) { + if (!dc->debug.disable_clock_gate) { /* enable all DCN clock gating */ REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0); @@ -845,7 +845,7 @@ static void dcn10_init_hw(struct core_dc *dc) static enum dc_status dcn10_prog_pixclk_crtc_otg( struct pipe_ctx *pipe_ctx, struct validate_context *context, - struct core_dc *dc) + struct dc *dc) { struct dc_stream_state *stream = pipe_ctx->stream; enum dc_color_space color_space; @@ -932,7 +932,7 @@ static enum dc_status dcn10_prog_pixclk_crtc_otg( } static void reset_back_end_for_pipe( - struct core_dc *dc, + struct dc *dc, struct pipe_ctx *pipe_ctx, struct validate_context *context) { @@ -979,7 +979,7 @@ static void reset_back_end_for_pipe( } /* trigger HW to start disconnect plane from stream on the next vsync */ -static void plane_atomic_disconnect(struct core_dc *dc, +static void plane_atomic_disconnect(struct dc *dc, int fe_idx) { struct mem_input *mi = dc->res_pool->mis[fe_idx]; @@ -1004,10 +1004,10 @@ static void plane_atomic_disconnect(struct core_dc *dc, if (opp_id == dc->res_pool->pipe_count) return; - if (dc->public.debug.sanity_checks) + if (dc->debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); mi->funcs->dcc_control(mi, false, false); - if (dc->public.debug.sanity_checks) + if (dc->debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); mpc->funcs->remove(mpc, dc->res_pool->opps[opp_id], fe_idx); @@ -1015,7 +1015,7 @@ static void plane_atomic_disconnect(struct core_dc *dc, /* disable HW used by plane. * note: cannot disable until disconnect is complete */ -static void plane_atomic_disable(struct core_dc *dc, +static void plane_atomic_disable(struct dc *dc, int fe_idx) { struct dce_hwseq *hws = dc->hwseq; @@ -1037,7 +1037,7 @@ static void plane_atomic_disable(struct core_dc *dc, mi->opp_id = 0xf; mi->mpcc_id = 0xf; - if (dc->public.debug.sanity_checks) + if (dc->debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); REG_UPDATE(HUBP_CLK_CNTL[fe_idx], @@ -1049,7 +1049,7 @@ static void plane_atomic_disable(struct core_dc *dc, REG_UPDATE(OPP_PIPE_CONTROL[opp_id], OPP_PIPE_CLOCK_EN, 0); - if (dc->public.debug.sanity_checks) + if (dc->debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); } @@ -1057,7 +1057,7 @@ static void plane_atomic_disable(struct core_dc *dc, * kill power to plane hw * note: cannot power down until plane is disable */ -static void plane_atomic_power_down(struct core_dc *dc, int fe_idx) +static void plane_atomic_power_down(struct dc *dc, int fe_idx) { struct dce_hwseq *hws = dc->hwseq; struct transform *xfm = dc->res_pool->transforms[fe_idx]; @@ -1072,13 +1072,13 @@ static void plane_atomic_power_down(struct core_dc *dc, int fe_idx) dm_logger_write(dc->ctx->logger, LOG_DC, "Power gated front end %d\n", fe_idx); - if (dc->public.debug.sanity_checks) + if (dc->debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); } static void reset_front_end( - struct core_dc *dc, + struct dc *dc, int fe_idx) { struct dce_hwseq *hws = dc->hwseq; @@ -1097,7 +1097,7 @@ static void reset_front_end( REG_UPDATE(OTG_GLOBAL_SYNC_STATUS[tg->inst], VUPDATE_NO_LOCK_EVENT_CLEAR, 1); tg->funcs->unlock(tg); - if (dc->public.debug.sanity_checks) + if (dc->debug.sanity_checks) verify_allow_pstate_change_high(hws); if (tg->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS) @@ -1112,7 +1112,7 @@ static void reset_front_end( fe_idx); } -static void dcn10_power_down_fe(struct core_dc *dc, int fe_idx) +static void dcn10_power_down_fe(struct dc *dc, int fe_idx) { struct dce_hwseq *hws = dc->hwseq; struct transform *xfm = dc->res_pool->transforms[fe_idx]; @@ -1129,12 +1129,12 @@ static void dcn10_power_down_fe(struct core_dc *dc, int fe_idx) dm_logger_write(dc->ctx->logger, LOG_DC, "Power gated front end %d\n", fe_idx); - if (dc->public.debug.sanity_checks) + if (dc->debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); } static void reset_hw_ctx_wrap( - struct core_dc *dc, + struct dc *dc, struct validate_context *context) { int i; @@ -1246,7 +1246,7 @@ static void toggle_watermark_change_req(struct dce_hwseq *hws) DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, watermark_change_req); } -static void dcn10_update_plane_addr(const struct core_dc *dc, struct pipe_ctx *pipe_ctx) +static void dcn10_update_plane_addr(const struct dc *dc, struct pipe_ctx *pipe_ctx) { bool addr_patched = false; PHYSICAL_ADDRESS_LOC addr; @@ -1657,7 +1657,7 @@ static bool dcn10_set_output_transfer_func( } static void dcn10_pipe_control_lock( - struct core_dc *dc, + struct dc *dc, struct pipe_ctx *pipe, bool lock) { @@ -1669,7 +1669,7 @@ static void dcn10_pipe_control_lock( if (pipe->top_pipe) return; - if (dc->public.debug.sanity_checks) + if (dc->debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); if (lock) @@ -1677,7 +1677,7 @@ static void dcn10_pipe_control_lock( else pipe->stream_res.tg->funcs->unlock(pipe->stream_res.tg); - if (dc->public.debug.sanity_checks) + if (dc->debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); } @@ -1719,7 +1719,7 @@ static bool wait_for_reset_trigger_to_occur( } static void dcn10_enable_timing_synchronization( - struct core_dc *dc, + struct dc *dc, int group_index, int group_size, struct pipe_ctx *grouped_pipes[]) @@ -1748,7 +1748,7 @@ static void dcn10_enable_timing_synchronization( } static void print_rq_dlg_ttu( - struct core_dc *core_dc, + struct dc *core_dc, struct pipe_ctx *pipe_ctx) { dm_logger_write(core_dc->ctx->logger, LOG_BANDWIDTH_CALCS, @@ -1870,14 +1870,14 @@ static void print_rq_dlg_ttu( } static void dcn10_power_on_fe( - struct core_dc *dc, + struct dc *dc, struct pipe_ctx *pipe_ctx, struct validate_context *context) { struct dc_plane_state *plane_state = pipe_ctx->plane_state; struct dce_hwseq *hws = dc->hwseq; - if (dc->public.debug.sanity_checks) { + if (dc->debug.sanity_checks) { verify_allow_pstate_change_high(dc->hwseq); } @@ -1928,7 +1928,7 @@ static void dcn10_power_on_fe( print_rq_dlg_ttu(dc, pipe_ctx); } - if (dc->public.debug.sanity_checks) { + if (dc->debug.sanity_checks) { verify_allow_pstate_change_high(dc->hwseq); } } @@ -2084,7 +2084,7 @@ static void dcn10_get_surface_visual_confirm_color( } static void update_dchubp_dpp( - struct core_dc *dc, + struct dc *dc, struct pipe_ctx *pipe_ctx, struct validate_context *context) { @@ -2126,7 +2126,7 @@ static void update_dchubp_dpp( size.grph.surface_size = pipe_ctx->plane_res.scl_data.viewport; - if (dc->public.config.gpu_vm_support) + if (dc->config.gpu_vm_support) mi->funcs->mem_input_program_pte_vm( pipe_ctx->plane_res.mi, plane_state->format, @@ -2142,7 +2142,7 @@ static void update_dchubp_dpp( mpcc_cfg.opp = pipe_ctx->stream_res.opp; for (top_pipe = pipe_ctx->top_pipe; top_pipe; top_pipe = top_pipe->top_pipe) mpcc_cfg.z_index++; - if (dc->public.debug.surface_visual_confirm) + if (dc->debug.surface_visual_confirm) dcn10_get_surface_visual_confirm_color( pipe_ctx, &mpcc_cfg.black_color); else @@ -2187,7 +2187,7 @@ static void update_dchubp_dpp( static void program_all_pipe_in_tree( - struct core_dc *dc, + struct dc *dc, struct pipe_ctx *pipe_ctx, struct validate_context *context) { @@ -2201,7 +2201,7 @@ static void program_all_pipe_in_tree( /* watermark is for all pipes */ program_watermarks(dc->hwseq, &context->bw.dcn.watermarks, ref_clk_mhz); - if (dc->public.debug.sanity_checks) { + if (dc->debug.sanity_checks) { /* pstate stuck check after watermark update */ verify_allow_pstate_change_high(dc->hwseq); } @@ -2236,7 +2236,7 @@ static void program_all_pipe_in_tree( update_dchubp_dpp(dc, pipe_ctx, context); } - if (dc->public.debug.sanity_checks) { + if (dc->debug.sanity_checks) { /* pstate stuck check after each pipe is programmed */ verify_allow_pstate_change_high(dc->hwseq); } @@ -2246,7 +2246,7 @@ static void program_all_pipe_in_tree( } static void dcn10_pplib_apply_display_requirements( - struct core_dc *dc, + struct dc *dc, struct validate_context *context) { struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg; @@ -2273,14 +2273,14 @@ static void dcn10_pplib_apply_display_requirements( } static void dcn10_apply_ctx_for_surface( - struct core_dc *dc, + struct dc *dc, const struct dc_stream_state *stream, int num_planes, struct validate_context *context) { int i, be_idx; - if (dc->public.debug.sanity_checks) + if (dc->debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); be_idx = -1; @@ -2351,7 +2351,7 @@ static void dcn10_apply_ctx_for_surface( "[debug_mpo: apply_ctx disconnect pending on mpcc %d]\n", old_pipe_ctx->mpcc->inst);*/ - if (dc->public.debug.sanity_checks) + if (dc->debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); old_pipe_ctx->top_pipe = NULL; @@ -2422,18 +2422,18 @@ static void dcn10_apply_ctx_for_surface( context->bw.dcn.watermarks.d.pte_meta_urgent_ns ); - if (dc->public.debug.sanity_checks) + if (dc->debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); } static void dcn10_set_bandwidth( - struct core_dc *dc, + struct dc *dc, struct validate_context *context, bool decrease_allowed) { struct dm_pp_clock_for_voltage_req clock; - if (dc->public.debug.sanity_checks) { + if (dc->debug.sanity_checks) { verify_allow_pstate_change_high(dc->hwseq); } @@ -2488,7 +2488,7 @@ static void dcn10_set_bandwidth( } dcn10_pplib_apply_display_requirements(dc, context); - if (dc->public.debug.sanity_checks) { + if (dc->debug.sanity_checks) { verify_allow_pstate_change_high(dc->hwseq); } @@ -2541,7 +2541,7 @@ static void set_static_screen_control(struct pipe_ctx **pipe_ctx, } static void set_plane_config( - const struct core_dc *dc, + const struct dc *dc, struct pipe_ctx *pipe_ctx, struct resource_context *res_ctx) { @@ -2586,7 +2586,7 @@ static void dcn10_config_stereo_parameters( return; } -static void dcn10_setup_stereo(struct pipe_ctx *pipe_ctx, struct core_dc *dc) +static void dcn10_setup_stereo(struct pipe_ctx *pipe_ctx, struct dc *dc) { struct crtc_stereo_flags flags = { 0 }; struct dc_stream_state *stream = pipe_ctx->stream; @@ -2607,13 +2607,13 @@ static void dcn10_setup_stereo(struct pipe_ctx *pipe_ctx, struct core_dc *dc) } static void dcn10_wait_for_mpcc_disconnect( - struct core_dc *dc, + struct dc *dc, struct resource_pool *res_pool, struct pipe_ctx *pipe_ctx) { int i; - if (dc->public.debug.sanity_checks) { + if (dc->debug.sanity_checks) { verify_allow_pstate_change_high(dc->hwseq); } @@ -2631,14 +2631,14 @@ static void dcn10_wait_for_mpcc_disconnect( } } - if (dc->public.debug.sanity_checks) { + if (dc->debug.sanity_checks) { verify_allow_pstate_change_high(dc->hwseq); } } static bool dcn10_dummy_display_power_gating( - struct core_dc *dc, + struct dc *dc, uint8_t controller_id, struct dc_bios *dcb, enum pipe_gating_control power_gating) @@ -2652,7 +2652,7 @@ void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx) struct timing_generator *tg = pipe_ctx->stream_res.tg; if (plane_state->ctx->dc->debug.sanity_checks) { - struct core_dc *dc = DC_TO_CORE(plane_state->ctx->dc); + struct dc *dc = plane_state->ctx->dc; verify_allow_pstate_change_high(dc->hwseq); } @@ -2716,7 +2716,7 @@ static const struct hw_sequencer_funcs dcn10_funcs = { }; -void dcn10_hw_sequencer_construct(struct core_dc *dc) +void dcn10_hw_sequencer_construct(struct dc *dc) { dc->hwss = dcn10_funcs; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h index 28218dc43522..8bb09de8dcd7 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h @@ -28,9 +28,9 @@ #include "core_types.h" -struct core_dc; +struct dc; -void dcn10_hw_sequencer_construct(struct core_dc *dc); +void dcn10_hw_sequencer_construct(struct dc *dc); extern void fill_display_configs( const struct validate_context *context, struct dm_pp_display_configuration *pp_display_cfg); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index c36843d497ac..2d9e88f08abb 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -825,7 +825,7 @@ static enum dc_status build_pipe_hw_param(struct pipe_ctx *pipe_ctx) } static enum dc_status build_mapped_resource( - const struct core_dc *dc, + const struct dc *dc, struct validate_context *context, struct validate_context *old_context) { @@ -872,7 +872,7 @@ static enum dc_status build_mapped_resource( } enum dc_status dcn10_validate_with_context( - const struct core_dc *dc, + struct dc *dc, const struct dc_validation_set set[], int set_count, struct validate_context *context, @@ -917,7 +917,7 @@ enum dc_status dcn10_validate_with_context( } enum dc_status dcn10_validate_guaranteed( - const struct core_dc *dc, + struct dc *dc, struct dc_stream_state *dc_stream, struct validate_context *context) { @@ -937,7 +937,7 @@ enum dc_status dcn10_validate_guaranteed( if (result == DC_OK) { validate_guaranteed_copy_streams( - context, dc->public.caps.max_streams); + context, dc->caps.max_streams); result = resource_build_scaling_params_for_context(dc, context); } if (result == DC_OK && !dcn_validate_bandwidth(dc, context)) @@ -1221,7 +1221,7 @@ static struct resource_funcs dcn10_res_pool_funcs = { static bool construct( uint8_t num_virtual_links, - struct core_dc *dc, + struct dc *dc, struct dcn10_resource_pool *pool) { int i; @@ -1244,16 +1244,16 @@ static bool construct( /* TODO: Hardcode to correct number of functional controllers */ pool->base.pipe_count = 4; - dc->public.caps.max_downscale_ratio = 200; - dc->public.caps.i2c_speed_in_khz = 100; - dc->public.caps.max_cursor_size = 256; + dc->caps.max_downscale_ratio = 200; + dc->caps.i2c_speed_in_khz = 100; + dc->caps.max_cursor_size = 256; - dc->public.caps.max_slave_planes = 1; + dc->caps.max_slave_planes = 1; if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) - dc->public.debug = debug_defaults_drv; + dc->debug = debug_defaults_drv; else - dc->public.debug = debug_defaults_diags; + dc->debug = debug_defaults_diags; /************************************************* * Create resources * @@ -1327,7 +1327,7 @@ static bool construct( if (ASICREV_IS_RV1_F0(dc->ctx->asic_id.hw_internal_rev)) { dc->dcn_soc->urgent_latency = 3; - dc->public.debug.disable_dmcu = true; + dc->debug.disable_dmcu = true; dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9 = 41.60f; } @@ -1347,10 +1347,10 @@ static bool construct( } } - if (!dc->public.debug.disable_pplib_clock_request) + if (!dc->debug.disable_pplib_clock_request) dcn_bw_update_from_pplib(dc); dcn_bw_sync_calcs_and_dml(dc); - if (!dc->public.debug.disable_pplib_wm_range) + if (!dc->debug.disable_pplib_wm_range) dcn_bw_notify_pplib_of_wm_ranges(dc); { @@ -1424,9 +1424,9 @@ static bool construct( goto res_create_fail; dcn10_hw_sequencer_construct(dc); - dc->public.caps.max_planes = pool->base.pipe_count; + dc->caps.max_planes = pool->base.pipe_count; - dc->public.cap_funcs = cap_funcs; + dc->cap_funcs = cap_funcs; return true; @@ -1449,7 +1449,7 @@ dwbc_create_fail: struct resource_pool *dcn10_create_resource_pool( uint8_t num_virtual_links, - struct core_dc *dc) + struct dc *dc) { struct dcn10_resource_pool *pool = dm_alloc(sizeof(struct dcn10_resource_pool)); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.h index 5f84dbd0bdea..8f71225bc61b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.h @@ -31,7 +31,7 @@ #define TO_DCN10_RES_POOL(pool)\ container_of(pool, struct dcn10_resource_pool, base) -struct core_dc; +struct dc; struct resource_pool; struct _vcs_dpi_display_pipe_params_st; @@ -40,7 +40,7 @@ struct dcn10_resource_pool { }; struct resource_pool *dcn10_create_resource_pool( uint8_t num_virtual_links, - struct core_dc *dc); + struct dc *dc); #endif /* __DC_RESOURCE_DCN10_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_dc.h b/drivers/gpu/drm/amd/display/dc/inc/core_dc.h deleted file mode 100644 index ebe1fd78a92a..000000000000 --- a/drivers/gpu/drm/amd/display/dc/inc/core_dc.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * core_dc.h - * - * Created on: Nov 13, 2015 - * Author: yonsun - */ - -#ifndef __CORE_DC_H__ -#define __CORE_DC_H__ - -#include "core_types.h" -#include "hw_sequencer.h" -#include "compressor.h" - -#define DC_TO_CORE(dc)\ - container_of(dc, struct core_dc, public) - -struct core_dc { - struct dc public; - struct dc_context *ctx; - - uint8_t link_count; - struct dc_link *links[MAX_PIPES * 2]; - - struct validate_context *current_context; - struct resource_pool *res_pool; - - /* Display Engine Clock levels */ - struct dm_pp_clock_levels sclk_lvls; - - /* Inputs into BW and WM calculations. */ - struct bw_calcs_dceip *bw_dceip; - struct bw_calcs_vbios *bw_vbios; -#ifdef CONFIG_DRM_AMD_DC_DCN1_0 - struct dcn_soc_bounding_box *dcn_soc; - struct dcn_ip_params *dcn_ip; - struct display_mode_lib dml; -#endif - - /* HW functions */ - struct hw_sequencer_funcs hwss; - struct dce_hwseq *hwseq; - - /* temp store of dm_pp_display_configuration - * to compare to see if display config changed - */ - struct dm_pp_display_configuration prev_display_config; - - /* FBC compressor */ -#ifdef ENABLE_FBC - struct compressor *fbc_compressor; -#endif -}; - -#endif /* __CORE_DC_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 28454028434c..f8ade552c595 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -52,7 +52,7 @@ void enable_surface_flip_reporting(struct dc_plane_state *plane_state, /************ link *****************/ struct link_init_data { - const struct core_dc *dc; + const struct dc *dc; struct dc_context *ctx; /* TODO: remove 'dal' when DC is complete. */ uint32_t connector_index; /* this will be mapped to the HPD pins */ uint32_t link_index; /* this is mapped to DAL display_index @@ -87,19 +87,19 @@ struct resource_funcs { struct link_encoder *(*link_enc_create)( const struct encoder_init_data *init); enum dc_status (*validate_with_context)( - const struct core_dc *dc, + struct dc *dc, const struct dc_validation_set set[], int set_count, struct validate_context *context, struct validate_context *old_context); enum dc_status (*validate_guaranteed)( - const struct core_dc *dc, + struct dc *dc, struct dc_stream_state *stream, struct validate_context *context); bool (*validate_bandwidth)( - const struct core_dc *dc, + struct dc *dc, struct validate_context *context); struct pipe_ctx *(*acquire_idle_pipe_for_layer)( diff --git a/drivers/gpu/drm/amd/display/dc/inc/dce_calcs.h b/drivers/gpu/drm/amd/display/dc/inc/dce_calcs.h index 36c48f7d3f56..6a205b010084 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dce_calcs.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dce_calcs.h @@ -33,7 +33,7 @@ #include "bw_fixed.h" struct pipe_ctx; -struct core_dc; +struct dc; struct validate_context; struct dce_bw_output; diff --git a/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h b/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h index 7e8abcd60d12..58744fe87ed8 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h @@ -34,7 +34,7 @@ #include "display_clock.h" #include "../dml/display_mode_lib.h" -struct core_dc; +struct dc; struct validate_context; /******************************************************************************* @@ -620,16 +620,16 @@ struct dcn_ip_params { extern const struct dcn_ip_params dcn10_ip_defaults; bool dcn_validate_bandwidth( - const struct core_dc *dc, + struct dc *dc, struct validate_context *context); unsigned int dcn_find_dcfclk_suits_all( - const struct core_dc *dc, + const struct dc *dc, struct clocks_value *clocks); -void dcn_bw_update_from_pplib(struct core_dc *dc); -void dcn_bw_notify_pplib_of_wm_ranges(struct core_dc *dc); -void dcn_bw_sync_calcs_and_dml(struct core_dc *dc); +void dcn_bw_update_from_pplib(struct dc *dc); +void dcn_bw_notify_pplib_of_wm_ranges(struct dc *dc); +void dcn_bw_sync_calcs_and_dml(struct dc *dc); #endif /* __DCN_CALCS_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h index a02f18ae527d..f876a11c903f 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h @@ -30,6 +30,7 @@ #include "dml/display_mode_structs.h" +struct dchub_init_data; struct cstate_pstate_watermarks_st { uint32_t cstate_exit_ns; uint32_t cstate_enter_plus_exit_ns; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 7689e372b9da..c73dca9f6d46 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -25,8 +25,10 @@ #ifndef __DC_HW_SEQUENCER_H__ #define __DC_HW_SEQUENCER_H__ -#include "core_types.h" -#include "timing_generator.h" +#include "dc_types.h" +#include "clock_source.h" +#include "inc/hw/timing_generator.h" +#include "core_status.h" enum pipe_gating_control { PIPE_GATING_CONTROL_DISABLE = 0, @@ -46,25 +48,31 @@ struct dce_hwseq { struct dce_hwseq_wa wa; }; +struct pipe_ctx; +struct validate_context; +struct dchub_init_data; +struct dc_static_screen_events; +struct resource_pool; +struct resource_context; struct hw_sequencer_funcs { - void (*init_hw)(struct core_dc *dc); + void (*init_hw)(struct dc *dc); enum dc_status (*apply_ctx_to_hw)( - struct core_dc *dc, struct validate_context *context); + struct dc *dc, struct validate_context *context); void (*reset_hw_ctx_wrap)( - struct core_dc *dc, struct validate_context *context); + struct dc *dc, struct validate_context *context); void (*apply_ctx_for_surface)( - struct core_dc *dc, + struct dc *dc, const struct dc_stream_state *stream, int num_planes, struct validate_context *context); void (*set_plane_config)( - const struct core_dc *dc, + const struct dc *dc, struct pipe_ctx *pipe_ctx, struct resource_context *res_ctx); @@ -77,7 +85,7 @@ struct hw_sequencer_funcs { uint16_t *matrix); void (*update_plane_addr)( - const struct core_dc *dc, + const struct dc *dc, struct pipe_ctx *pipe_ctx); void (*update_dchub)( @@ -95,12 +103,12 @@ struct hw_sequencer_funcs { struct pipe_ctx *pipe_ctx, const struct dc_stream_state *stream); - void (*power_down)(struct core_dc *dc); + void (*power_down)(struct dc *dc); - void (*enable_accelerated_mode)(struct core_dc *dc); + void (*enable_accelerated_mode)(struct dc *dc); void (*enable_timing_synchronization)( - struct core_dc *dc, + struct dc *dc, int group_index, int group_size, struct pipe_ctx *grouped_pipes[]); @@ -110,14 +118,14 @@ struct hw_sequencer_funcs { bool clock_gating); bool (*enable_display_power_gating)( - struct core_dc *dc, + struct dc *dc, uint8_t controller_id, struct dc_bios *dcb, enum pipe_gating_control power_gating); - void (*power_down_front_end)(struct core_dc *dc, int fe_idx); + void (*power_down_front_end)(struct dc *dc, int fe_idx); - void (*power_on_front_end)(struct core_dc *dc, + void (*power_on_front_end)(struct dc *dc, struct pipe_ctx *pipe, struct validate_context *context); @@ -131,12 +139,12 @@ struct hw_sequencer_funcs { struct dc_link_settings *link_settings); void (*pipe_control_lock)( - struct core_dc *dc, + struct dc *dc, struct pipe_ctx *pipe, bool lock); void (*set_bandwidth)( - struct core_dc *dc, + struct dc *dc, struct validate_context *context, bool decrease_allowed); @@ -152,23 +160,23 @@ struct hw_sequencer_funcs { enum dc_status (*prog_pixclk_crtc_otg)( struct pipe_ctx *pipe_ctx, struct validate_context *context, - struct core_dc *dc); + struct dc *dc); void (*setup_stereo)( struct pipe_ctx *pipe_ctx, - struct core_dc *dc); + struct dc *dc); void (*set_avmute)(struct pipe_ctx *pipe_ctx, bool enable); - void (*log_hw_state)(struct core_dc *dc); + void (*log_hw_state)(struct dc *dc); - void (*wait_for_mpcc_disconnect)(struct core_dc *dc, + void (*wait_for_mpcc_disconnect)(struct dc *dc, struct resource_pool *res_pool, struct pipe_ctx *pipe_ctx); }; void color_space_to_black_color( - const struct core_dc *dc, + const struct dc *dc, enum dc_color_space colorspace, struct tg_color *black_color); diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index 7f30d9937d10..13218a52e2fa 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -27,7 +27,6 @@ #include "core_types.h" #include "core_status.h" -#include "core_dc.h" #include "dal_asic_id.h" /* TODO unhardcode, 4 for CZ*/ @@ -67,27 +66,27 @@ struct resource_create_funcs { bool resource_construct( unsigned int num_virtual_links, - struct core_dc *dc, + struct dc *dc, struct resource_pool *pool, const struct resource_create_funcs *create_funcs); struct resource_pool *dc_create_resource_pool( - struct core_dc *dc, + struct dc *dc, int num_virtual_links, enum dce_version dc_version, struct hw_asic_id asic_id); -void dc_destroy_resource_pool(struct core_dc *dc); +void dc_destroy_resource_pool(struct dc *dc); enum dc_status resource_map_pool_resources( - const struct core_dc *dc, + const struct dc *dc, struct validate_context *context, struct validate_context *old_context); bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx); enum dc_status resource_build_scaling_params_for_context( - const struct core_dc *dc, + const struct dc *dc, struct validate_context *context); void resource_build_info_frame(struct pipe_ctx *pipe_ctx); @@ -148,12 +147,12 @@ void resource_validate_ctx_update_pointer_after_copy( struct validate_context *dst_ctx); enum dc_status resource_map_clock_resources( - const struct core_dc *dc, + const struct dc *dc, struct validate_context *context, struct validate_context *old_context); enum dc_status resource_map_phy_clock_resources( - const struct core_dc *dc, + const struct dc *dc, struct validate_context *context, struct validate_context *old_context); diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c index 24e47eb8cf3f..e3a12f3e0642 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c @@ -34,8 +34,8 @@ #include "ivsrcid/ivsrcid_vislands30.h" -#include "core_dc.h" - +#include "dc.h" +#include "core_types.h" static bool hpd_ack( struct irq_service *irq_service, const struct irq_source_info *info) @@ -206,7 +206,7 @@ bool dce110_vblank_set( bool enable) { struct dc_context *dc_ctx = irq_service->ctx; - struct core_dc *core_dc = DC_TO_CORE(irq_service->ctx->dc); + struct dc *core_dc = irq_service->ctx->dc; enum dc_irq_source dal_irq_src = dc_interrupt_to_irq_source( irq_service->ctx->dc, info->src_id, diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c b/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c index 7e8cb22f280f..f458ef8e4c57 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c @@ -36,7 +36,6 @@ #include "ivsrcid/ivsrcid_vislands30.h" #include "dc_types.h" -#include "inc/core_dc.h" static bool hpd_ack( struct irq_service *irq_service, diff --git a/drivers/gpu/drm/amd/display/include/logger_interface.h b/drivers/gpu/drm/amd/display/include/logger_interface.h index beb790937769..93c8556358f0 100644 --- a/drivers/gpu/drm/amd/display/include/logger_interface.h +++ b/drivers/gpu/drm/amd/display/include/logger_interface.h @@ -76,23 +76,23 @@ void logger_write(struct dal_logger *logger, void *paralist); void pre_surface_trace( - const struct dc *dc, + struct dc *dc, const struct dc_plane_state *const *plane_states, int surface_count); void update_surface_trace( - const struct dc *dc, + struct dc *dc, const struct dc_surface_update *updates, int surface_count); -void post_surface_trace(const struct dc *dc); +void post_surface_trace(struct dc *dc); void context_timing_trace( - const struct dc *dc, + struct dc *dc, struct resource_context *res_ctx); void context_clock_trace( - const struct dc *dc, + struct dc *dc, struct validate_context *context); /* Any function which is empty or have incomplete implementation should be diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index f0a3e4332a09..f49203b3eb94 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -27,7 +27,6 @@ #include "dc.h" #include "mod_freesync.h" #include "core_types.h" -#include "core_dc.h" #define MOD_FREESYNC_MAX_CONCURRENT_STREAMS 32 @@ -146,7 +145,7 @@ struct mod_freesync *mod_freesync_create(struct dc *dc) struct core_freesync *core_freesync = dm_alloc(sizeof(struct core_freesync)); - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; struct persistent_data_flag flag; @@ -246,7 +245,7 @@ static unsigned int map_index_from_stream(struct core_freesync *core_freesync, bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, struct dc_stream_state *stream, struct mod_freesync_caps *caps) { - struct core_dc *core_dc = NULL; + struct dc *core_dc = NULL; struct core_freesync *core_freesync = NULL; int persistent_freesync_enable = 0; struct persistent_data_flag flag; @@ -257,7 +256,7 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, return false; core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync); - core_dc = DC_TO_CORE(core_freesync->dc); + core_dc = core_freesync->dc; flag.save_per_edid = true; flag.save_per_link = false; @@ -971,14 +970,14 @@ bool mod_freesync_set_user_enable(struct mod_freesync *mod_freesync, unsigned int stream_index, map_index; int persistent_data = 0; struct persistent_data_flag flag; - struct core_dc *core_dc = NULL; + struct dc *core_dc = NULL; struct core_freesync *core_freesync = NULL; if (mod_freesync == NULL) return false; core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync); - core_dc = DC_TO_CORE(core_freesync->dc); + core_dc = core_freesync->dc; flag.save_per_edid = true; flag.save_per_link = false; -- cgit From 641106d3fab8790af12c71e750d9b6287ffc75ce Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Thu, 3 Aug 2017 16:41:48 -0400 Subject: drm/amd/display: Use MAX_PIPES for DTO reg arrays Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h index 238c03f14959..c45e2f76189e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h @@ -107,9 +107,9 @@ struct dce110_clk_src_regs { /* below are for DTO. * todo: should probably use different struct to not waste space */ - uint32_t PHASE[4]; - uint32_t MODULO[4]; - uint32_t PIXEL_RATE_CNTL[4]; + uint32_t PHASE[MAX_PIPES]; + uint32_t MODULO[MAX_PIPES]; + uint32_t PIXEL_RATE_CNTL[MAX_PIPES]; }; struct dce110_clk_src { -- cgit From 4e772ae5f99a1595a2e064a70d2eab4946e5c08d Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Fri, 11 Aug 2017 11:23:30 -0400 Subject: drm/amd/display: blank otg before power gate front end. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index d5d2398d92b8..ce48d81c4442 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2298,8 +2298,10 @@ static void dcn10_apply_ctx_for_surface( struct pipe_ctx *old_pipe_ctx = &dc->current_context->res_ctx.pipe_ctx[i]; - if (old_pipe_ctx->stream_res.tg && old_pipe_ctx->stream_res.tg->inst == be_idx) + if (old_pipe_ctx->stream_res.tg && old_pipe_ctx->stream_res.tg->inst == be_idx) { + old_pipe_ctx->stream_res.tg->funcs->set_blank(old_pipe_ctx->stream_res.tg, true); dcn10_power_down_fe(dc, old_pipe_ctx->pipe_idx); + } } return; } -- cgit From 71afd9d14f49a0a16050ada488ac1be182f5602f Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Fri, 11 Aug 2017 13:22:02 -0400 Subject: drm/amd/display: eDP power sequence T9 fail Signed-off-by: Charlene Liu Reviewed-by: Anthony Koo Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 23 ++++++++++++++++++++++ .../gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index da880bd02ad7..e12f1f9fb590 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -110,6 +110,28 @@ void dp_enable_link_phy( dp_receiver_power_ctrl(link, true); } +bool edp_receiver_ready_T9(struct dc_link *link) +{ + unsigned int tries = 0; + unsigned char sinkstatus = 0; + unsigned char edpRev = 0; + enum dc_status result = DC_OK; + result = core_link_read_dpcd(link, DP_EDP_DPCD_REV, &edpRev, sizeof(edpRev)); + if (edpRev < DP_EDP_12) + return true; + /* start from eDP version 1.2, SINK_STAUS indicate the sink is ready.*/ + do { + sinkstatus = 1; + result = core_link_read_dpcd(link, DP_SINK_STATUS, &sinkstatus, sizeof(sinkstatus)); + if (sinkstatus == 0) + break; + if (result != DC_OK) + break; + dm_delay_in_microseconds(link->ctx, 100); //MAx T9 + } while (++tries < 50); + return result; +} + void dp_disable_link_phy(struct dc_link *link, enum signal_type signal) { if (!link->wa_flags.dp_keep_receiver_powered) @@ -117,6 +139,7 @@ void dp_disable_link_phy(struct dc_link *link, enum signal_type signal) if (signal == SIGNAL_TYPE_EDP) { link->link_enc->funcs->backlight_control(link->link_enc, false); + edp_receiver_ready_T9(link); link->link_enc->funcs->disable_output(link->link_enc, signal); link->link_enc->funcs->power_control(link->link_enc, false); } else diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 0dab5bacde3c..559a9f81c9c9 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -744,7 +744,7 @@ void dce110_link_encoder_edp_backlight_control( return; } - if (!enable && !is_panel_powered_on(enc110)) { + if (!enable && !is_panel_backlight_on(enc110)) { dm_logger_write(ctx->logger, LOG_HW_RESUME_S3, "%s: panel already powered down. Do nothing.\n", __func__); -- cgit From b4c8e6da39091b2931074e001febc598e2acdbb1 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 10 Aug 2017 16:16:20 -0400 Subject: drm/amd/display: Leave DCN config guard around fpu header See https://lists.freedesktop.org/archives/dri-devel/2017-August/149938.html Signed-off-by: Harry Wentland Reviewed-by: Jordan Lazare Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dm_services.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dm_services.h b/drivers/gpu/drm/amd/display/dc/dm_services.h index a7d661d1ff1d..e9bf4c417cc7 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services.h @@ -75,7 +75,9 @@ BREAK_TO_DEBUGGER(); \ } while (0) +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) #include +#endif #define dm_alloc(size) kzalloc(size, GFP_KERNEL) #define dm_realloc(ptr, size) krealloc(ptr, size, GFP_KERNEL) -- cgit From be7c97f6a7d10cd60f09001c61047055b49d5d8d Mon Sep 17 00:00:00 2001 From: Roman Li Date: Mon, 14 Aug 2017 17:35:08 -0400 Subject: drm/amd/display: Fix FBC compilation - Fixing compilation with ENABLE_FBC flag which was broken after flattening core_dc to dc Signed-off-by: Roman Li Reviewed-by: Jerry Zuo Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 68056d888def..1210fdd48c56 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -35,6 +35,7 @@ #include #include "inc/hw_sequencer.h" +#include "inc/compressor.h" #include "dml/display_mode_lib.h" -- cgit From 992fe94c1b6afdf6f09ada61d4a1ecc5df52fe5f Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Thu, 3 Aug 2017 08:49:41 -0400 Subject: drm/amd/display: remove fake address reporting when blank Signed-off-by: Tony Cheng Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index ce48d81c4442..23aa6e1242c5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2666,14 +2666,6 @@ void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx) pipe_ctx->plane_res.mi->funcs->mem_input_is_flip_pending( pipe_ctx->plane_res.mi); - /* DCN we read INUSE address in MI, do we still need this wa? */ - if (plane_state->status.is_flip_pending && - !plane_state->visible) { - pipe_ctx->plane_res.mi->current_address = - pipe_ctx->plane_res.mi->request_address; - BREAK_TO_DEBUGGER(); - } - plane_state->status.current_address = pipe_ctx->plane_res.mi->current_address; if (pipe_ctx->plane_res.mi->current_address.type == PLN_ADDR_TYPE_GRPH_STEREO && tg->funcs->is_stereo_left_eye) { -- cgit From 0cb8a88122ecfaa183ede19748269cb4fb5c739c Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Mon, 14 Aug 2017 18:17:01 -0400 Subject: drm/amd/display: move vm registers to hwsequencer Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h | 52 +++++++++- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 95 +++++++++++++++++- .../gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c | 106 ++------------------- .../gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h | 41 +------- drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h | 21 ++++ 5 files changed, 172 insertions(+), 143 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index 3a1eb6a79d66..2d3a41f744af 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -206,7 +206,20 @@ SR(D1VGA_CONTROL), \ SR(D2VGA_CONTROL), \ SR(D3VGA_CONTROL), \ - SR(D4VGA_CONTROL) + SR(D4VGA_CONTROL), \ + /* todo: get these from GVM instead of reading registers ourselves */\ + MMHUB_SR(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32),\ + MMHUB_SR(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32),\ + MMHUB_SR(VM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32),\ + MMHUB_SR(VM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32),\ + MMHUB_SR(VM_CONTEXT0_PAGE_TABLE_END_ADDR_HI32),\ + MMHUB_SR(VM_CONTEXT0_PAGE_TABLE_END_ADDR_LO32),\ + MMHUB_SR(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_HI32),\ + MMHUB_SR(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32),\ + MMHUB_SR(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB),\ + MMHUB_SR(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB),\ + MMHUB_SR(MC_VM_SYSTEM_APERTURE_LOW_ADDR),\ + MMHUB_SR(MC_VM_SYSTEM_APERTURE_HIGH_ADDR) #define HWSEQ_DCN1_REG_LIST()\ HWSEQ_DCN_REG_LIST(), \ @@ -312,6 +325,19 @@ struct dce_hwseq_registers { uint32_t D2VGA_CONTROL; uint32_t D3VGA_CONTROL; uint32_t D4VGA_CONTROL; + /* MMHUB registers. read only. temporary hack */ + uint32_t VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32; + uint32_t VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32; + uint32_t VM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32; + uint32_t VM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32; + uint32_t VM_CONTEXT0_PAGE_TABLE_END_ADDR_HI32; + uint32_t VM_CONTEXT0_PAGE_TABLE_END_ADDR_LO32; + uint32_t VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_HI32; + uint32_t VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32; + uint32_t MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB; + uint32_t MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB; + uint32_t MC_VM_SYSTEM_APERTURE_LOW_ADDR; + uint32_t MC_VM_SYSTEM_APERTURE_HIGH_ADDR; }; /* set field name */ #define HWS_SF(blk_name, reg_name, field_name, post_fix)\ @@ -432,7 +458,17 @@ struct dce_hwseq_registers { HWS_SF(, DCHUBBUB_SDPIF_AGP_BASE, SDPIF_AGP_BASE, mask_sh), \ HWS_SF(, DCHUBBUB_SDPIF_AGP_BOT, SDPIF_AGP_BOT, mask_sh), \ HWS_SF(, DCHUBBUB_SDPIF_AGP_TOP, SDPIF_AGP_TOP, mask_sh), \ - HWS_SF(DPP_TOP0_, DPP_CONTROL, DPPCLK_RATE_CONTROL, mask_sh) + HWS_SF(DPP_TOP0_, DPP_CONTROL, DPPCLK_RATE_CONTROL, mask_sh), \ + /* todo: get these from GVM instead of reading registers ourselves */\ + HWS_SF(, VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32, PAGE_DIRECTORY_ENTRY_HI32, mask_sh),\ + HWS_SF(, VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32, PAGE_DIRECTORY_ENTRY_LO32, mask_sh),\ + HWS_SF(, VM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32, LOGICAL_PAGE_NUMBER_HI4, mask_sh),\ + HWS_SF(, VM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32, LOGICAL_PAGE_NUMBER_LO32, mask_sh),\ + HWS_SF(, VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_HI32, PHYSICAL_PAGE_ADDR_HI4, mask_sh),\ + HWS_SF(, VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32, PHYSICAL_PAGE_ADDR_LO32, mask_sh),\ + HWS_SF(, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, PHYSICAL_PAGE_NUMBER_MSB, mask_sh),\ + HWS_SF(, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, PHYSICAL_PAGE_NUMBER_LSB, mask_sh),\ + HWS_SF(, MC_VM_SYSTEM_APERTURE_LOW_ADDR, LOGICAL_ADDR, mask_sh) #define HWSEQ_REG_FIELD_LIST(type) \ type DCFE_CLOCK_ENABLE; \ @@ -451,6 +487,18 @@ struct dce_hwseq_registers { type PIXEL_RATE_SOURCE; \ type PHYPLL_PIXEL_RATE_SOURCE; \ type PIXEL_RATE_PLL_SOURCE; \ + /* todo: get these from GVM instead of reading registers ourselves */\ + type PAGE_DIRECTORY_ENTRY_HI32;\ + type PAGE_DIRECTORY_ENTRY_LO32;\ + type LOGICAL_PAGE_NUMBER_HI4;\ + type LOGICAL_PAGE_NUMBER_LO32;\ + type PHYSICAL_PAGE_ADDR_HI4;\ + type PHYSICAL_PAGE_ADDR_LO32;\ + type PHYSICAL_PAGE_NUMBER_MSB;\ + type PHYSICAL_PAGE_NUMBER_LSB;\ + type LOGICAL_ADDR; \ + type ENABLE_L1_TLB;\ + type SYSTEM_ACCESS_MODE; #define HWSEQ_DCN_REG_FIELD_LIST(type) \ type VUPDATE_NO_LOCK_EVENT_CLEAR; \ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 23aa6e1242c5..f0e49d16019c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2083,6 +2083,93 @@ static void dcn10_get_surface_visual_confirm_color( } } +static void mmhub_read_vm_system_aperture_settings(struct dcn10_mem_input *mi, + struct vm_system_aperture_param *apt, + struct dce_hwseq *hws) +{ + PHYSICAL_ADDRESS_LOC physical_page_number; + uint32_t logical_addr_low; + uint32_t logical_addr_high; + + REG_GET(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, + PHYSICAL_PAGE_NUMBER_MSB, &physical_page_number.high_part); + REG_GET(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, + PHYSICAL_PAGE_NUMBER_LSB, &physical_page_number.low_part); + + REG_GET(MC_VM_SYSTEM_APERTURE_LOW_ADDR, + LOGICAL_ADDR, &logical_addr_low); + + REG_GET(MC_VM_SYSTEM_APERTURE_HIGH_ADDR, + LOGICAL_ADDR, &logical_addr_high); + + apt->sys_default.quad_part = physical_page_number.quad_part << 12; + apt->sys_low.quad_part = (int64_t)logical_addr_low << 18; + apt->sys_high.quad_part = (int64_t)logical_addr_high << 18; +} + +/* Temporary read settings, future will get values from kmd directly */ +static void mmhub_read_vm_context0_settings(struct dcn10_mem_input *mi, + struct vm_context0_param *vm0, + struct dce_hwseq *hws) +{ + PHYSICAL_ADDRESS_LOC fb_base; + PHYSICAL_ADDRESS_LOC fb_offset; + uint32_t fb_base_value; + uint32_t fb_offset_value; + + REG_GET(DCHUBBUB_SDPIF_FB_BASE, SDPIF_FB_BASE, &fb_base_value); + REG_GET(DCHUBBUB_SDPIF_FB_OFFSET, SDPIF_FB_OFFSET, &fb_offset_value); + + REG_GET(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32, + PAGE_DIRECTORY_ENTRY_HI32, &vm0->pte_base.high_part); + REG_GET(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32, + PAGE_DIRECTORY_ENTRY_LO32, &vm0->pte_base.low_part); + + REG_GET(VM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32, + LOGICAL_PAGE_NUMBER_HI4, &vm0->pte_start.high_part); + REG_GET(VM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32, + LOGICAL_PAGE_NUMBER_LO32, &vm0->pte_start.low_part); + + REG_GET(VM_CONTEXT0_PAGE_TABLE_END_ADDR_HI32, + LOGICAL_PAGE_NUMBER_HI4, &vm0->pte_end.high_part); + REG_GET(VM_CONTEXT0_PAGE_TABLE_END_ADDR_LO32, + LOGICAL_PAGE_NUMBER_LO32, &vm0->pte_end.low_part); + + REG_GET(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_HI32, + PHYSICAL_PAGE_ADDR_HI4, &vm0->fault_default.high_part); + REG_GET(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32, + PHYSICAL_PAGE_ADDR_LO32, &vm0->fault_default.low_part); + + /* + * The values in VM_CONTEXT0_PAGE_TABLE_BASE_ADDR is in UMA space. + * Therefore we need to do + * DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR = VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + * - DCHUBBUB_SDPIF_FB_OFFSET + DCHUBBUB_SDPIF_FB_BASE + */ + fb_base.quad_part = (uint64_t)fb_base_value << 24; + fb_offset.quad_part = (uint64_t)fb_offset_value << 24; + vm0->pte_base.quad_part += fb_base.quad_part; + vm0->pte_base.quad_part -= fb_offset.quad_part; +} + +static void dcn10_program_pte_vm(struct mem_input *mem_input, + enum surface_pixel_format format, + union dc_tiling_info *tiling_info, + enum dc_rotation_angle rotation, + struct dce_hwseq *hws) +{ + struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + struct vm_system_aperture_param apt = { {{ 0 } } }; + struct vm_context0_param vm0 = { { { 0 } } }; + + + mmhub_read_vm_system_aperture_settings(mi, &apt, hws); + mmhub_read_vm_context0_settings(mi, &vm0, hws); + + mem_input->funcs->mem_input_set_vm_system_aperture_settings(mem_input, &apt); + mem_input->funcs->mem_input_set_vm_context0_settings(mem_input, &vm0); +} + static void update_dchubp_dpp( struct dc *dc, struct pipe_ctx *pipe_ctx, @@ -2127,11 +2214,13 @@ static void update_dchubp_dpp( size.grph.surface_size = pipe_ctx->plane_res.scl_data.viewport; if (dc->config.gpu_vm_support) - mi->funcs->mem_input_program_pte_vm( + dcn10_program_pte_vm( pipe_ctx->plane_res.mi, plane_state->format, &plane_state->tiling_info, - plane_state->rotation); + plane_state->rotation, + hws + ); ipp->funcs->ipp_setup(ipp, plane_state->format, @@ -2674,6 +2763,8 @@ void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx) } } + + static const struct hw_sequencer_funcs dcn10_funcs = { .program_gamut_remap = program_gamut_remap, .program_csc_matrix = program_csc_matrix, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index f36585de15df..11daf6b5c7d8 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -625,38 +625,10 @@ static bool min10_is_flip_pending(struct mem_input *mem_input) return false; } -struct vm_system_aperture_param { - PHYSICAL_ADDRESS_LOC sys_default; - PHYSICAL_ADDRESS_LOC sys_low; - PHYSICAL_ADDRESS_LOC sys_high; -}; - -static void min10_read_vm_system_aperture_settings(struct dcn10_mem_input *mi, - struct vm_system_aperture_param *apt) -{ - PHYSICAL_ADDRESS_LOC physical_page_number; - uint32_t logical_addr_low; - uint32_t logical_addr_high; - - REG_GET(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, - PHYSICAL_PAGE_NUMBER_MSB, &physical_page_number.high_part); - REG_GET(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, - PHYSICAL_PAGE_NUMBER_LSB, &physical_page_number.low_part); - - REG_GET(MC_VM_SYSTEM_APERTURE_LOW_ADDR, - LOGICAL_ADDR, &logical_addr_low); - - REG_GET(MC_VM_SYSTEM_APERTURE_HIGH_ADDR, - LOGICAL_ADDR, &logical_addr_high); - - apt->sys_default.quad_part = physical_page_number.quad_part << 12; - apt->sys_low.quad_part = (int64_t)logical_addr_low << 18; - apt->sys_high.quad_part = (int64_t)logical_addr_high << 18; -} - -static void min10_set_vm_system_aperture_settings(struct dcn10_mem_input *mi, +static void min10_set_vm_system_aperture_settings(struct mem_input *mem_input, struct vm_system_aperture_param *apt) { + struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); PHYSICAL_ADDRESS_LOC mc_vm_apt_default; PHYSICAL_ADDRESS_LOC mc_vm_apt_low; PHYSICAL_ADDRESS_LOC mc_vm_apt_high; @@ -682,60 +654,10 @@ static void min10_set_vm_system_aperture_settings(struct dcn10_mem_input *mi, MC_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, mc_vm_apt_high.low_part); } -struct vm_context0_param { - PHYSICAL_ADDRESS_LOC pte_base; - PHYSICAL_ADDRESS_LOC pte_start; - PHYSICAL_ADDRESS_LOC pte_end; - PHYSICAL_ADDRESS_LOC fault_default; -}; - -/* Temporary read settings, future will get values from kmd directly */ -static void min10_read_vm_context0_settings(struct dcn10_mem_input *mi, - struct vm_context0_param *vm0) -{ - PHYSICAL_ADDRESS_LOC fb_base; - PHYSICAL_ADDRESS_LOC fb_offset; - uint32_t fb_base_value; - uint32_t fb_offset_value; - - REG_GET(DCHUBBUB_SDPIF_FB_BASE, SDPIF_FB_BASE, &fb_base_value); - REG_GET(DCHUBBUB_SDPIF_FB_OFFSET, SDPIF_FB_OFFSET, &fb_offset_value); - - REG_GET(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32, - PAGE_DIRECTORY_ENTRY_HI32, &vm0->pte_base.high_part); - REG_GET(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32, - PAGE_DIRECTORY_ENTRY_LO32, &vm0->pte_base.low_part); - - REG_GET(VM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32, - LOGICAL_PAGE_NUMBER_HI4, &vm0->pte_start.high_part); - REG_GET(VM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32, - LOGICAL_PAGE_NUMBER_LO32, &vm0->pte_start.low_part); - - REG_GET(VM_CONTEXT0_PAGE_TABLE_END_ADDR_HI32, - LOGICAL_PAGE_NUMBER_HI4, &vm0->pte_end.high_part); - REG_GET(VM_CONTEXT0_PAGE_TABLE_END_ADDR_LO32, - LOGICAL_PAGE_NUMBER_LO32, &vm0->pte_end.low_part); - - REG_GET(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_HI32, - PHYSICAL_PAGE_ADDR_HI4, &vm0->fault_default.high_part); - REG_GET(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32, - PHYSICAL_PAGE_ADDR_LO32, &vm0->fault_default.low_part); - - /* - * The values in VM_CONTEXT0_PAGE_TABLE_BASE_ADDR is in UMA space. - * Therefore we need to do - * DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR = VM_CONTEXT0_PAGE_TABLE_BASE_ADDR - * - DCHUBBUB_SDPIF_FB_OFFSET + DCHUBBUB_SDPIF_FB_BASE - */ - fb_base.quad_part = (uint64_t)fb_base_value << 24; - fb_offset.quad_part = (uint64_t)fb_offset_value << 24; - vm0->pte_base.quad_part += fb_base.quad_part; - vm0->pte_base.quad_part -= fb_offset.quad_part; -} - -static void min10_set_vm_context0_settings(struct dcn10_mem_input *mi, +static void min10_set_vm_context0_settings(struct mem_input *mem_input, const struct vm_context0_param *vm0) { + struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); /* pte base */ REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, 0, VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, vm0->pte_base.high_part); @@ -760,23 +682,6 @@ static void min10_set_vm_context0_settings(struct dcn10_mem_input *mi, /* VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_SYSTEM, 0 */ REG_SET(DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, 0, VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, vm0->fault_default.low_part); -} - -static void min10_program_pte_vm(struct mem_input *mem_input, - enum surface_pixel_format format, - union dc_tiling_info *tiling_info, - enum dc_rotation_angle rotation) -{ - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); - struct vm_system_aperture_param apt = { {{ 0 } } }; - struct vm_context0_param vm0 = { { { 0 } } }; - - - min10_read_vm_system_aperture_settings(mi, &apt); - min10_read_vm_context0_settings(mi, &vm0); - - min10_set_vm_system_aperture_settings(mi, &apt); - min10_set_vm_context0_settings(mi, &vm0); /* control: enable VM PTE*/ REG_SET_2(DCN_VM_MX_L1_TLB_CNTL, 0, @@ -862,7 +767,8 @@ static struct mem_input_funcs dcn10_mem_input_funcs = { min10_program_surface_config, .mem_input_is_flip_pending = min10_is_flip_pending, .mem_input_setup = min10_setup, - .mem_input_program_pte_vm = min10_program_pte_vm, + .mem_input_set_vm_system_aperture_settings = min10_set_vm_system_aperture_settings, + .mem_input_set_vm_context0_settings = min10_set_vm_context0_settings, .set_blank = min10_set_blank, .dcc_control = min10_dcc_control, .mem_program_viewport = min_set_viewport, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h index b3ec16c17826..acee05155b5b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h @@ -97,20 +97,7 @@ SRI(DCN_SURF0_TTU_CNTL1, HUBPREQ, id),\ SRI(DCN_SURF1_TTU_CNTL0, HUBPREQ, id),\ SRI(DCN_SURF1_TTU_CNTL1, HUBPREQ, id),\ - SRI(DCN_VM_MX_L1_TLB_CNTL, HUBPREQ, id),\ - /* todo: get these from GVM instead of reading registers ourselves */\ - MMHUB_SR(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32),\ - MMHUB_SR(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32),\ - MMHUB_SR(VM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32),\ - MMHUB_SR(VM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32),\ - MMHUB_SR(VM_CONTEXT0_PAGE_TABLE_END_ADDR_HI32),\ - MMHUB_SR(VM_CONTEXT0_PAGE_TABLE_END_ADDR_LO32),\ - MMHUB_SR(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_HI32),\ - MMHUB_SR(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32),\ - MMHUB_SR(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB),\ - MMHUB_SR(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB),\ - MMHUB_SR(MC_VM_SYSTEM_APERTURE_LOW_ADDR),\ - MMHUB_SR(MC_VM_SYSTEM_APERTURE_HIGH_ADDR) + SRI(DCN_VM_MX_L1_TLB_CNTL, HUBPREQ, id) #define MI_REG_LIST_DCN10(id)\ MI_REG_LIST_DCN(id),\ @@ -228,20 +215,6 @@ struct dcn_mi_registers { uint32_t DCN_VM_AGP_BASE; uint32_t DCN_VM_AGP_BOT; uint32_t DCN_VM_AGP_TOP; - - /* GC registers. read only. temporary hack */ - uint32_t VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32; - uint32_t VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32; - uint32_t VM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32; - uint32_t VM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32; - uint32_t VM_CONTEXT0_PAGE_TABLE_END_ADDR_HI32; - uint32_t VM_CONTEXT0_PAGE_TABLE_END_ADDR_LO32; - uint32_t VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_HI32; - uint32_t VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32; - uint32_t MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB; - uint32_t MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB; - uint32_t MC_VM_SYSTEM_APERTURE_LOW_ADDR; - uint32_t MC_VM_SYSTEM_APERTURE_HIGH_ADDR; }; #define MI_SF(reg_name, field_name, post_fix)\ @@ -387,17 +360,7 @@ struct dcn_mi_registers { MI_SF(DCHUBBUB_SDPIF_FB_OFFSET, SDPIF_FB_OFFSET, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, MC_VM_SYSTEM_APERTURE_DEFAULT_SYSTEM, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, mask_sh),\ - /* todo: get these from GVM instead of reading registers ourselves */\ - MI_SF(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32, PAGE_DIRECTORY_ENTRY_HI32, mask_sh),\ - MI_SF(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32, PAGE_DIRECTORY_ENTRY_LO32, mask_sh),\ - MI_SF(VM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32, LOGICAL_PAGE_NUMBER_HI4, mask_sh),\ - MI_SF(VM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32, LOGICAL_PAGE_NUMBER_LO32, mask_sh),\ - MI_SF(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_HI32, PHYSICAL_PAGE_ADDR_HI4, mask_sh),\ - MI_SF(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32, PHYSICAL_PAGE_ADDR_LO32, mask_sh),\ - MI_SF(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, PHYSICAL_PAGE_NUMBER_MSB, mask_sh),\ - MI_SF(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, PHYSICAL_PAGE_NUMBER_LSB, mask_sh),\ - MI_SF(MC_VM_SYSTEM_APERTURE_LOW_ADDR, LOGICAL_ADDR, mask_sh) + MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, mask_sh) #define DCN_MI_REG_FIELD_LIST(type) \ type HUBP_BLANK_EN;\ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h index f876a11c903f..6f4f04da9e28 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h @@ -74,6 +74,19 @@ struct mem_input { struct stutter_modes stutter_mode; }; +struct vm_system_aperture_param { + PHYSICAL_ADDRESS_LOC sys_default; + PHYSICAL_ADDRESS_LOC sys_low; + PHYSICAL_ADDRESS_LOC sys_high; +}; + +struct vm_context0_param { + PHYSICAL_ADDRESS_LOC pte_base; + PHYSICAL_ADDRESS_LOC pte_start; + PHYSICAL_ADDRESS_LOC pte_end; + PHYSICAL_ADDRESS_LOC fault_default; +}; + struct mem_input_funcs { void (*mem_input_setup)( struct mem_input *mem_input, @@ -125,6 +138,14 @@ struct mem_input_funcs { union dc_tiling_info *tiling_info, enum dc_rotation_angle rotation); + void (*mem_input_set_vm_system_aperture_settings)( + struct mem_input *mem_input, + struct vm_system_aperture_param *apt); + + void (*mem_input_set_vm_context0_settings)( + struct mem_input *mem_input, + const struct vm_context0_param *vm0); + void (*mem_input_program_surface_config)( struct mem_input *mem_input, enum surface_pixel_format format, -- cgit From 1e8635ea0ea370bf4f0f2b2f1b3eb61474dd962a Mon Sep 17 00:00:00 2001 From: Zeyu Fan Date: Mon, 14 Aug 2017 18:43:11 -0400 Subject: drm/amd/display: Implement HDMI retimer settings for RV AM4 support. Signed-off-by: Zeyu Fan Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c | 69 ++++ drivers/gpu/drm/amd/display/dc/core/dc_link.c | 420 ++++++++++++++++++++- drivers/gpu/drm/amd/display/dc/dc.h | 1 + drivers/gpu/drm/amd/display/dc/dm_helpers.h | 5 - .../amd/display/include/grph_object_ctrl_defs.h | 38 ++ 5 files changed, 524 insertions(+), 9 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c index 86fce5ae5856..f8d4f08bf985 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -993,6 +993,8 @@ static struct device_id device_type_from_device_id(uint16_t device_id) struct device_id result_device_id; + result_device_id.raw_device_tag = device_id; + switch (device_id) { case ATOM_DISPLAY_LCD1_SUPPORT: result_device_id.device_type = DEVICE_TYPE_LCD; @@ -1812,10 +1814,77 @@ static enum bp_result get_integrated_info_v11( info_v11->extdispconninfo.path[i].hpdlut_index; info->ext_disp_conn_info.path[i].channel_mapping.raw = info_v11->extdispconninfo.path[i].channelmapping; + info->ext_disp_conn_info.path[i].caps = + le16_to_cpu(info_v11->extdispconninfo.path[i].caps); } info->ext_disp_conn_info.checksum = info_v11->extdispconninfo.checksum; + info->dp0_ext_hdmi_slv_addr = info_v11->dp0_retimer_set.HdmiSlvAddr; + info->dp0_ext_hdmi_reg_num = info_v11->dp0_retimer_set.HdmiRegNum; + for (i = 0; i < info->dp0_ext_hdmi_reg_num; i++) { + info->dp0_ext_hdmi_reg_settings[i].i2c_reg_index = + info_v11->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegIndex; + info->dp0_ext_hdmi_reg_settings[i].i2c_reg_val = + info_v11->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegVal; + } + info->dp0_ext_hdmi_6g_reg_num = info_v11->dp0_retimer_set.Hdmi6GRegNum; + for (i = 0; i < info->dp0_ext_hdmi_6g_reg_num; i++) { + info->dp0_ext_hdmi_6g_reg_settings[i].i2c_reg_index = + info_v11->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex; + info->dp0_ext_hdmi_6g_reg_settings[i].i2c_reg_val = + info_v11->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal; + } + + info->dp1_ext_hdmi_slv_addr = info_v11->dp1_retimer_set.HdmiSlvAddr; + info->dp1_ext_hdmi_reg_num = info_v11->dp1_retimer_set.HdmiRegNum; + for (i = 0; i < info->dp1_ext_hdmi_reg_num; i++) { + info->dp1_ext_hdmi_reg_settings[i].i2c_reg_index = + info_v11->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegIndex; + info->dp1_ext_hdmi_reg_settings[i].i2c_reg_val = + info_v11->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegVal; + } + info->dp1_ext_hdmi_6g_reg_num = info_v11->dp1_retimer_set.Hdmi6GRegNum; + for (i = 0; i < info->dp1_ext_hdmi_6g_reg_num; i++) { + info->dp1_ext_hdmi_6g_reg_settings[i].i2c_reg_index = + info_v11->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex; + info->dp1_ext_hdmi_6g_reg_settings[i].i2c_reg_val = + info_v11->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal; + } + + info->dp2_ext_hdmi_slv_addr = info_v11->dp2_retimer_set.HdmiSlvAddr; + info->dp2_ext_hdmi_reg_num = info_v11->dp2_retimer_set.HdmiRegNum; + for (i = 0; i < info->dp2_ext_hdmi_reg_num; i++) { + info->dp2_ext_hdmi_reg_settings[i].i2c_reg_index = + info_v11->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegIndex; + info->dp2_ext_hdmi_reg_settings[i].i2c_reg_val = + info_v11->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegVal; + } + info->dp2_ext_hdmi_6g_reg_num = info_v11->dp2_retimer_set.Hdmi6GRegNum; + for (i = 0; i < info->dp2_ext_hdmi_6g_reg_num; i++) { + info->dp2_ext_hdmi_6g_reg_settings[i].i2c_reg_index = + info_v11->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex; + info->dp2_ext_hdmi_6g_reg_settings[i].i2c_reg_val = + info_v11->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal; + } + + info->dp3_ext_hdmi_slv_addr = info_v11->dp3_retimer_set.HdmiSlvAddr; + info->dp3_ext_hdmi_reg_num = info_v11->dp3_retimer_set.HdmiRegNum; + for (i = 0; i < info->dp3_ext_hdmi_reg_num; i++) { + info->dp3_ext_hdmi_reg_settings[i].i2c_reg_index = + info_v11->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegIndex; + info->dp3_ext_hdmi_reg_settings[i].i2c_reg_val = + info_v11->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegVal; + } + info->dp3_ext_hdmi_6g_reg_num = info_v11->dp3_retimer_set.Hdmi6GRegNum; + for (i = 0; i < info->dp3_ext_hdmi_6g_reg_num; i++) { + info->dp3_ext_hdmi_6g_reg_settings[i].i2c_reg_index = + info_v11->dp3_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex; + info->dp3_ext_hdmi_6g_reg_settings[i].i2c_reg_val = + info_v11->dp3_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal; + } + + /** TODO - review **/ #if 0 info->boot_up_engine_clock = le32_to_cpu(info_v11->ulBootUpEngineClock) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 1888bf4d2c3f..d77f0de0f2bf 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1044,10 +1044,17 @@ static bool construct( &info.ext_disp_conn_info.path[i]; if (path->device_connector_id.enum_id == link->link_id.enum_id && path->device_connector_id.id == link->link_id.id - && path->device_connector_id.type == link->link_id.type - && path->device_acpi_enum - == link->device_tag.acpi_device) { - link->ddi_channel_mapping = path->channel_mapping; + && path->device_connector_id.type == link->link_id.type) { + + if (link->device_tag.acpi_device != 0 + && path->device_acpi_enum == link->device_tag.acpi_device) { + link->ddi_channel_mapping = path->channel_mapping; + link->chip_caps = path->caps; + } else if (path->device_tag == + link->device_tag.dev_id.raw_device_tag) { + link->ddi_channel_mapping = path->channel_mapping; + link->chip_caps = path->caps; + } break; } } @@ -1263,11 +1270,416 @@ static enum dc_status enable_link_dp_mst(struct pipe_ctx *pipe_ctx) return enable_link_dp(pipe_ctx); } +static bool get_ext_hdmi_settings(struct pipe_ctx *pipe_ctx, + enum engine_id eng_id, + struct ext_hdmi_settings *settings) +{ + bool result = false; + int i = 0; + struct integrated_info *integrated_info = + pipe_ctx->stream->ctx->dc_bios->integrated_info; + + if (integrated_info == NULL) + return false; + + /* + * Get retimer settings from sbios for passing SI eye test for DCE11 + * The setting values are varied based on board revision and port id + * Therefore the setting values of each ports is passed by sbios. + */ + + // Check if current bios contains ext Hdmi settings + if (integrated_info->gpu_cap_info & 0x20) { + switch (eng_id) { + case ENGINE_ID_DIGA: + settings->slv_addr = integrated_info->dp0_ext_hdmi_slv_addr; + settings->reg_num = integrated_info->dp0_ext_hdmi_6g_reg_num; + settings->reg_num_6g = integrated_info->dp0_ext_hdmi_6g_reg_num; + memmove(settings->reg_settings, + integrated_info->dp0_ext_hdmi_reg_settings, + sizeof(integrated_info->dp0_ext_hdmi_reg_settings)); + memmove(settings->reg_settings_6g, + integrated_info->dp0_ext_hdmi_6g_reg_settings, + sizeof(integrated_info->dp0_ext_hdmi_6g_reg_settings)); + result = true; + break; + case ENGINE_ID_DIGB: + settings->slv_addr = integrated_info->dp1_ext_hdmi_slv_addr; + settings->reg_num = integrated_info->dp1_ext_hdmi_6g_reg_num; + settings->reg_num_6g = integrated_info->dp1_ext_hdmi_6g_reg_num; + memmove(settings->reg_settings, + integrated_info->dp1_ext_hdmi_reg_settings, + sizeof(integrated_info->dp1_ext_hdmi_reg_settings)); + memmove(settings->reg_settings_6g, + integrated_info->dp1_ext_hdmi_6g_reg_settings, + sizeof(integrated_info->dp1_ext_hdmi_6g_reg_settings)); + result = true; + break; + case ENGINE_ID_DIGC: + settings->slv_addr = integrated_info->dp2_ext_hdmi_slv_addr; + settings->reg_num = integrated_info->dp2_ext_hdmi_6g_reg_num; + settings->reg_num_6g = integrated_info->dp2_ext_hdmi_6g_reg_num; + memmove(settings->reg_settings, + integrated_info->dp2_ext_hdmi_reg_settings, + sizeof(integrated_info->dp2_ext_hdmi_reg_settings)); + memmove(settings->reg_settings_6g, + integrated_info->dp2_ext_hdmi_6g_reg_settings, + sizeof(integrated_info->dp2_ext_hdmi_6g_reg_settings)); + result = true; + break; + + default: + break; + } + + if (result == true) { + // Validate settings from bios integrated info table + if (settings->slv_addr == 0) + return false; + if (settings->reg_num > 9) + return false; + if (settings->reg_num_6g > 3) + return false; + + for (i = 0; i < settings->reg_num; i++) { + if (settings->reg_settings[i].i2c_reg_index > 0x20) + return false; + } + + for (i = 0; i < settings->reg_num_6g; i++) { + if (settings->reg_settings_6g[i].i2c_reg_index > 0x20) + return false; + } + } + } + + return result; +} + +static bool i2c_write(struct pipe_ctx *pipe_ctx, + uint8_t address, uint8_t *buffer, uint32_t length) +{ + struct i2c_command cmd = {0}; + struct i2c_payload payload = {0}; + + memset(&payload, 0, sizeof(payload)); + memset(&cmd, 0, sizeof(cmd)); + + cmd.number_of_payloads = 1; + cmd.engine = I2C_COMMAND_ENGINE_DEFAULT; + cmd.speed = pipe_ctx->stream->ctx->dc->caps.i2c_speed_in_khz; + + payload.address = address; + payload.data = buffer; + payload.length = length; + payload.write = true; + cmd.payloads = &payload; + + if (dc_submit_i2c(pipe_ctx->stream->ctx->dc, + pipe_ctx->stream->sink->link->link_index, &cmd)) + return true; + + return false; +} + +static void write_i2c_retimer_setting( + struct pipe_ctx *pipe_ctx, + bool is_vga_mode, + bool is_over_340mhz, + struct ext_hdmi_settings *settings) +{ + uint8_t slave_address = (settings->slv_addr >> 1); + uint8_t buffer[2]; + const uint8_t apply_rx_tx_change = 0x4; + uint8_t offset = 0xA; + uint8_t value = 0; + int i = 0; + bool i2c_success = false; + + memset(&buffer, 0, sizeof(buffer)); + + /* Start Ext-Hdmi programming*/ + + for (i = 0; i < settings->reg_num; i++) { + /* Apply 3G settings */ + if (settings->reg_settings[i].i2c_reg_index <= 0x20) { + + buffer[0] = settings->reg_settings[i].i2c_reg_index; + buffer[1] = settings->reg_settings[i].i2c_reg_val; + i2c_success = i2c_write(pipe_ctx, slave_address, + buffer, sizeof(buffer)); + + if (!i2c_success) + /* Write failure */ + ASSERT(i2c_success); + + /* Based on DP159 specs, APPLY_RX_TX_CHANGE bit in 0x0A + * needs to be set to 1 on every 0xA-0xC write. + */ + if (settings->reg_settings[i].i2c_reg_index == 0xA || + settings->reg_settings[i].i2c_reg_index == 0xB || + settings->reg_settings[i].i2c_reg_index == 0xC) { + + /* Query current value from offset 0xA */ + if (settings->reg_settings[i].i2c_reg_index == 0xA) + value = settings->reg_settings[i].i2c_reg_val; + else { + i2c_success = + dal_ddc_service_query_ddc_data( + pipe_ctx->stream->sink->link->ddc, + slave_address, &offset, 1, &value, 1); + if (!i2c_success) + /* Write failure */ + ASSERT(i2c_success); + } + + buffer[0] = offset; + /* Set APPLY_RX_TX_CHANGE bit to 1 */ + buffer[1] = value | apply_rx_tx_change; + i2c_success = i2c_write(pipe_ctx, slave_address, + buffer, sizeof(buffer)); + if (!i2c_success) + /* Write failure */ + ASSERT(i2c_success); + } + } + } + + /* Apply 3G settings */ + if (is_over_340mhz) { + for (i = 0; i < settings->reg_num_6g; i++) { + /* Apply 3G settings */ + if (settings->reg_settings[i].i2c_reg_index <= 0x20) { + + buffer[0] = settings->reg_settings_6g[i].i2c_reg_index; + buffer[1] = settings->reg_settings_6g[i].i2c_reg_val; + i2c_success = i2c_write(pipe_ctx, slave_address, + buffer, sizeof(buffer)); + + if (!i2c_success) + /* Write failure */ + ASSERT(i2c_success); + + /* Based on DP159 specs, APPLY_RX_TX_CHANGE bit in 0x0A + * needs to be set to 1 on every 0xA-0xC write. + */ + if (settings->reg_settings_6g[i].i2c_reg_index == 0xA || + settings->reg_settings_6g[i].i2c_reg_index == 0xB || + settings->reg_settings_6g[i].i2c_reg_index == 0xC) { + + /* Query current value from offset 0xA */ + if (settings->reg_settings_6g[i].i2c_reg_index == 0xA) + value = settings->reg_settings_6g[i].i2c_reg_val; + else { + i2c_success = + dal_ddc_service_query_ddc_data( + pipe_ctx->stream->sink->link->ddc, + slave_address, &offset, 1, &value, 1); + if (!i2c_success) + /* Write failure */ + ASSERT(i2c_success); + } + + buffer[0] = offset; + /* Set APPLY_RX_TX_CHANGE bit to 1 */ + buffer[1] = value | apply_rx_tx_change; + i2c_success = i2c_write(pipe_ctx, slave_address, + buffer, sizeof(buffer)); + if (!i2c_success) + /* Write failure */ + ASSERT(i2c_success); + } + } + } + } + + if (is_vga_mode) { + /* Program additional settings if using 640x480 resolution */ + + /* Write offset 0xFF to 0x01 */ + buffer[0] = 0xff; + buffer[1] = 0x01; + i2c_success = i2c_write(pipe_ctx, slave_address, + buffer, sizeof(buffer)); + if (!i2c_success) + /* Write failure */ + ASSERT(i2c_success); + + /* Write offset 0x00 to 0x23 */ + buffer[0] = 0x00; + buffer[1] = 0x23; + i2c_success = i2c_write(pipe_ctx, slave_address, + buffer, sizeof(buffer)); + if (!i2c_success) + /* Write failure */ + ASSERT(i2c_success); + + /* Write offset 0xff to 0x00 */ + buffer[0] = 0xff; + buffer[1] = 0x00; + i2c_success = i2c_write(pipe_ctx, slave_address, + buffer, sizeof(buffer)); + if (!i2c_success) + /* Write failure */ + ASSERT(i2c_success); + + } +} + +static void write_i2c_default_retimer_setting( + struct pipe_ctx *pipe_ctx, + bool is_vga_mode, + bool is_over_340mhz) +{ + uint8_t slave_address = (0xBA >> 1); + uint8_t buffer[2]; + bool i2c_success = false; + + memset(&buffer, 0, sizeof(buffer)); + + /* Program Slave Address for tuning single integrity */ + /* Write offset 0x0A to 0x13 */ + buffer[0] = 0x0A; + buffer[1] = 0x13; + i2c_success = i2c_write(pipe_ctx, slave_address, + buffer, sizeof(buffer)); + if (!i2c_success) + /* Write failure */ + ASSERT(i2c_success); + + /* Write offset 0x0A to 0x17 */ + buffer[0] = 0x0A; + buffer[1] = 0x17; + i2c_success = i2c_write(pipe_ctx, slave_address, + buffer, sizeof(buffer)); + if (!i2c_success) + /* Write failure */ + ASSERT(i2c_success); + + /* Write offset 0x0B to 0xDA or 0xD8 */ + buffer[0] = 0x0B; + buffer[1] = is_over_340mhz ? 0xDA : 0xD8; + i2c_success = i2c_write(pipe_ctx, slave_address, + buffer, sizeof(buffer)); + if (!i2c_success) + /* Write failure */ + ASSERT(i2c_success); + + /* Write offset 0x0A to 0x17 */ + buffer[0] = 0x0A; + buffer[1] = 0x17; + i2c_success = i2c_write(pipe_ctx, slave_address, + buffer, sizeof(buffer)); + if (!i2c_success) + /* Write failure */ + ASSERT(i2c_success); + + /* Write offset 0x0C to 0x1D or 0x91 */ + buffer[0] = 0x0C; + buffer[1] = is_over_340mhz ? 0x1D : 0x91; + i2c_success = i2c_write(pipe_ctx, slave_address, + buffer, sizeof(buffer)); + if (!i2c_success) + /* Write failure */ + ASSERT(i2c_success); + + /* Write offset 0x0A to 0x17 */ + buffer[0] = 0x0A; + buffer[1] = 0x17; + i2c_success = i2c_write(pipe_ctx, slave_address, + buffer, sizeof(buffer)); + if (!i2c_success) + /* Write failure */ + ASSERT(i2c_success); + + + if (is_vga_mode) { + /* Program additional settings if using 640x480 resolution */ + + /* Write offset 0xFF to 0x01 */ + buffer[0] = 0xff; + buffer[1] = 0x01; + i2c_success = i2c_write(pipe_ctx, slave_address, + buffer, sizeof(buffer)); + if (!i2c_success) + /* Write failure */ + ASSERT(i2c_success); + + /* Write offset 0x00 to 0x23 */ + buffer[0] = 0x00; + buffer[1] = 0x23; + i2c_success = i2c_write(pipe_ctx, slave_address, + buffer, sizeof(buffer)); + if (!i2c_success) + /* Write failure */ + ASSERT(i2c_success); + + /* Write offset 0xff to 0x00 */ + buffer[0] = 0xff; + buffer[1] = 0x00; + i2c_success = i2c_write(pipe_ctx, slave_address, + buffer, sizeof(buffer)); + if (!i2c_success) + /* Write failure */ + ASSERT(i2c_success); + } +} + +static void write_i2c_redriver_setting( + struct pipe_ctx *pipe_ctx, + bool is_over_340mhz) +{ + uint8_t slave_address = (0xF0 >> 1); + uint8_t buffer[16]; + bool i2c_success = false; + + memset(&buffer, 0, sizeof(buffer)); + + // Program Slave Address for tuning single integrity + buffer[3] = 0x4E; + buffer[4] = 0x4E; + buffer[5] = 0x4E; + buffer[6] = is_over_340mhz ? 0x4E : 0x4A; + + i2c_success = i2c_write(pipe_ctx, slave_address, + buffer, sizeof(buffer)); + + if (!i2c_success) + /* Write failure */ + ASSERT(i2c_success); +} + static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) { struct dc_stream_state *stream = pipe_ctx->stream; struct dc_link *link = stream->sink->link; enum dc_color_depth display_color_depth; + enum engine_id eng_id; + struct ext_hdmi_settings settings = {0}; + bool is_over_340mhz = false; + bool is_vga_mode = (stream->timing.h_addressable == 640) + && (stream->timing.v_addressable == 480); + + if (stream->phy_pix_clk > 340000) + is_over_340mhz = true; + + if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) { + if ((pipe_ctx->stream->sink->link->chip_caps >> 2) == 0x2) { + /* DP159, Retimer settings */ + eng_id = pipe_ctx->stream_res.stream_enc->id; + + if (get_ext_hdmi_settings(pipe_ctx, eng_id, &settings)) { + write_i2c_retimer_setting(pipe_ctx, + is_vga_mode, is_over_340mhz, &settings); + } else { + write_i2c_default_retimer_setting(pipe_ctx, + is_vga_mode, is_over_340mhz); + } + } else if ((pipe_ctx->stream->sink->link->chip_caps >> 2) == 0x1) { + /* PI3EQX1204, Redriver settings */ + write_i2c_redriver_setting(pipe_ctx, is_over_340mhz); + } + } if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) dal_ddc_service_write_scdc_data( diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 1210fdd48c56..629aa3c323ca 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -815,6 +815,7 @@ struct dc_link { union ddi_channel_mapping ddi_channel_mapping; struct connector_device_tag_info device_tag; struct dpcd_caps dpcd_caps; + unsigned short chip_caps; unsigned int dpcd_sink_count; enum edp_revision edp_revision; diff --git a/drivers/gpu/drm/amd/display/dc/dm_helpers.h b/drivers/gpu/drm/amd/display/dc/dm_helpers.h index 39010325cef9..ab88f07772a3 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_helpers.h +++ b/drivers/gpu/drm/amd/display/dc/dm_helpers.h @@ -96,11 +96,6 @@ bool dm_helpers_submit_i2c( const struct dc_link *link, struct i2c_command *cmd); - - - - - enum dc_edid_status dm_helpers_read_local_edid( struct dc_context *ctx, struct dc_link *link, diff --git a/drivers/gpu/drm/amd/display/include/grph_object_ctrl_defs.h b/drivers/gpu/drm/amd/display/include/grph_object_ctrl_defs.h index 6cdbf84f34e6..92fe00fab87c 100644 --- a/drivers/gpu/drm/amd/display/include/grph_object_ctrl_defs.h +++ b/drivers/gpu/drm/amd/display/include/grph_object_ctrl_defs.h @@ -65,6 +65,7 @@ enum dal_device_type { struct device_id { enum dal_device_type device_type:16; uint32_t enum_id:16; /* 1 based enum */ + uint16_t raw_device_tag; }; struct graphics_object_i2c_info { @@ -264,6 +265,20 @@ struct transmitter_configuration { #define NUMBER_OF_DISP_CLK_VOLTAGE 4 #define NUMBER_OF_AVAILABLE_SCLK 5 +struct i2c_reg_info { + unsigned char i2c_reg_index; + unsigned char i2c_reg_val; +}; + +struct ext_hdmi_settings { + unsigned char slv_addr; + unsigned char reg_num; + struct i2c_reg_info reg_settings[9]; + unsigned char reg_num_6g; + struct i2c_reg_info reg_settings_6g[3]; +}; + + /* V6 */ struct integrated_info { struct clock_voltage_caps { @@ -291,6 +306,8 @@ struct integrated_info { struct graphics_object_id ext_encoder_obj_id; /* XBAR mapping of the PHY channels */ union ddi_channel_mapping channel_mapping; + + unsigned short caps; } path[MAX_NUMBER_OF_EXT_DISPLAY_PATH]; uint8_t gu_id[NUMBER_OF_UCHAR_FOR_GUID]; @@ -357,6 +374,27 @@ struct integrated_info { uint32_t lvds_pwr_off_seq_blon_to_vary_bl_in_4ms; uint32_t lvds_reserved1; uint32_t lvds_bit_depth_control_val; + //Start from V9 + unsigned char dp0_ext_hdmi_slv_addr; + unsigned char dp0_ext_hdmi_reg_num; + struct i2c_reg_info dp0_ext_hdmi_reg_settings[9]; + unsigned char dp0_ext_hdmi_6g_reg_num; + struct i2c_reg_info dp0_ext_hdmi_6g_reg_settings[3]; + unsigned char dp1_ext_hdmi_slv_addr; + unsigned char dp1_ext_hdmi_reg_num; + struct i2c_reg_info dp1_ext_hdmi_reg_settings[9]; + unsigned char dp1_ext_hdmi_6g_reg_num; + struct i2c_reg_info dp1_ext_hdmi_6g_reg_settings[3]; + unsigned char dp2_ext_hdmi_slv_addr; + unsigned char dp2_ext_hdmi_reg_num; + struct i2c_reg_info dp2_ext_hdmi_reg_settings[9]; + unsigned char dp2_ext_hdmi_6g_reg_num; + struct i2c_reg_info dp2_ext_hdmi_6g_reg_settings[3]; + unsigned char dp3_ext_hdmi_slv_addr; + unsigned char dp3_ext_hdmi_reg_num; + struct i2c_reg_info dp3_ext_hdmi_reg_settings[9]; + unsigned char dp3_ext_hdmi_6g_reg_num; + struct i2c_reg_info dp3_ext_hdmi_6g_reg_settings[3]; }; /** -- cgit From a185048ca88ce143f980f2b819f034cfc09a5377 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Sun, 13 Aug 2017 13:50:52 -0400 Subject: drm/amd/display: refactor pplib/smu communication new per SoC interface instead legacy interface with lots of un-used field that only cause confusion model pp_smu like one of our HW objects with func_ptr interface to call into it. struct pp_smu as handle to call pp/smu Signed-off-by: Tony Cheng Reviewed-by: Jun Lei Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_services.c | 13 +- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 100 ++++++++-------- .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 19 ++- drivers/gpu/drm/amd/display/dc/dm_pp_smu.h | 131 +++++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dm_services.h | 5 +- drivers/gpu/drm/amd/display/dc/dm_services_types.h | 2 + drivers/gpu/drm/amd/display/dc/inc/core_types.h | 2 + drivers/gpu/drm/amd/display/dc/inc/resource.h | 1 + 8 files changed, 213 insertions(+), 60 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/dc/dm_pp_smu.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c index 3348e90a0a37..aefd9ebc7bce 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c @@ -401,14 +401,6 @@ bool dm_pp_notify_wm_clock_changes( return false; } -bool dm_pp_notify_wm_clock_changes_soc15( - const struct dc_context *ctx, - struct dm_pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges) -{ - /* TODO: to be implemented */ - return false; -} - bool dm_pp_apply_power_level_change_request( const struct dc_context *ctx, struct dm_pp_power_level_change_request *level_change_req) @@ -433,4 +425,9 @@ bool dm_pp_get_static_clocks( return false; } +void dm_pp_get_funcs_rv( + struct dc_context *ctx, + struct pp_smu_funcs_rv *funcs) +{} + /**** end of power component interfaces ****/ diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index f0dfd3c3c12c..afd403ceb2a7 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -1311,12 +1311,16 @@ void dcn_bw_update_from_pplib(struct dc *dc) void dcn_bw_notify_pplib_of_wm_ranges(struct dc *dc) { - struct dm_pp_wm_sets_with_clock_ranges_soc15 clk_ranges = {0}; + struct pp_smu_funcs_rv *pp = dc->res_pool->pp_smu; + struct pp_smu_wm_range_sets ranges = {0}; int max_fclk_khz, nom_fclk_khz, min_fclk_khz, max_dcfclk_khz, nom_dcfclk_khz, mid_fclk_khz, min_dcfclk_khz, socclk_khz; const int overdrive = 5000000; /* 5 GHz to cover Overdrive */ unsigned factor = (ddr4_dram_factor_single_Channel * dc->dcn_soc->number_of_channels); + if (!pp->set_wm_ranges) + return; + kernel_fpu_begin(); max_fclk_khz = dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9 * 1000000 / factor; nom_fclk_khz = dc->dcn_soc->fabric_and_dram_bandwidth_vnom0p8 * 1000000 / factor; @@ -1336,55 +1340,55 @@ void dcn_bw_notify_pplib_of_wm_ranges(struct dc *dc) /* SOCCLK does not affect anytihng but writeback for DCN so for now we dont * care what the value is, hence min to overdrive level */ - clk_ranges.num_wm_dmif_sets = 4; - clk_ranges.num_wm_mcif_sets = 4; - clk_ranges.wm_dmif_clocks_ranges[0].wm_set_id = WM_SET_A; - clk_ranges.wm_dmif_clocks_ranges[0].wm_min_dcfclk_clk_in_khz = min_dcfclk_khz; - clk_ranges.wm_dmif_clocks_ranges[0].wm_max_dcfclk_clk_in_khz = max_dcfclk_khz; - clk_ranges.wm_dmif_clocks_ranges[0].wm_min_memg_clk_in_khz = min_fclk_khz; - clk_ranges.wm_dmif_clocks_ranges[0].wm_max_mem_clk_in_khz = min_fclk_khz; - clk_ranges.wm_mcif_clocks_ranges[0].wm_set_id = WM_SET_A; - clk_ranges.wm_mcif_clocks_ranges[0].wm_min_socclk_clk_in_khz = socclk_khz; - clk_ranges.wm_mcif_clocks_ranges[0].wm_max_socclk_clk_in_khz = overdrive; - clk_ranges.wm_mcif_clocks_ranges[0].wm_min_memg_clk_in_khz = min_fclk_khz; - clk_ranges.wm_mcif_clocks_ranges[0].wm_max_mem_clk_in_khz = min_fclk_khz; - - clk_ranges.wm_dmif_clocks_ranges[1].wm_set_id = WM_SET_B; - clk_ranges.wm_dmif_clocks_ranges[1].wm_min_dcfclk_clk_in_khz = min_fclk_khz; - clk_ranges.wm_dmif_clocks_ranges[1].wm_max_dcfclk_clk_in_khz = max_dcfclk_khz; - clk_ranges.wm_dmif_clocks_ranges[1].wm_min_memg_clk_in_khz = mid_fclk_khz; - clk_ranges.wm_dmif_clocks_ranges[1].wm_max_mem_clk_in_khz = mid_fclk_khz; - clk_ranges.wm_mcif_clocks_ranges[1].wm_set_id = WM_SET_B; - clk_ranges.wm_mcif_clocks_ranges[1].wm_min_socclk_clk_in_khz = socclk_khz; - clk_ranges.wm_mcif_clocks_ranges[1].wm_max_socclk_clk_in_khz = overdrive; - clk_ranges.wm_mcif_clocks_ranges[1].wm_min_memg_clk_in_khz = mid_fclk_khz; - clk_ranges.wm_mcif_clocks_ranges[1].wm_max_mem_clk_in_khz = mid_fclk_khz; - - - clk_ranges.wm_dmif_clocks_ranges[2].wm_set_id = WM_SET_C; - clk_ranges.wm_dmif_clocks_ranges[2].wm_min_dcfclk_clk_in_khz = min_fclk_khz; - clk_ranges.wm_dmif_clocks_ranges[2].wm_max_dcfclk_clk_in_khz = max_dcfclk_khz; - clk_ranges.wm_dmif_clocks_ranges[2].wm_min_memg_clk_in_khz = nom_fclk_khz; - clk_ranges.wm_dmif_clocks_ranges[2].wm_max_mem_clk_in_khz = nom_fclk_khz; - clk_ranges.wm_mcif_clocks_ranges[2].wm_set_id = WM_SET_C; - clk_ranges.wm_mcif_clocks_ranges[2].wm_min_socclk_clk_in_khz = socclk_khz; - clk_ranges.wm_mcif_clocks_ranges[2].wm_max_socclk_clk_in_khz = overdrive; - clk_ranges.wm_mcif_clocks_ranges[2].wm_min_memg_clk_in_khz = nom_fclk_khz; - clk_ranges.wm_mcif_clocks_ranges[2].wm_max_mem_clk_in_khz = nom_fclk_khz; - - clk_ranges.wm_dmif_clocks_ranges[3].wm_set_id = WM_SET_D; - clk_ranges.wm_dmif_clocks_ranges[3].wm_min_dcfclk_clk_in_khz = min_fclk_khz; - clk_ranges.wm_dmif_clocks_ranges[3].wm_max_dcfclk_clk_in_khz = max_dcfclk_khz; - clk_ranges.wm_dmif_clocks_ranges[3].wm_min_memg_clk_in_khz = max_fclk_khz; - clk_ranges.wm_dmif_clocks_ranges[3].wm_max_mem_clk_in_khz = max_fclk_khz; - clk_ranges.wm_mcif_clocks_ranges[3].wm_set_id = WM_SET_D; - clk_ranges.wm_mcif_clocks_ranges[3].wm_min_socclk_clk_in_khz = socclk_khz; - clk_ranges.wm_mcif_clocks_ranges[3].wm_max_socclk_clk_in_khz = overdrive; - clk_ranges.wm_mcif_clocks_ranges[3].wm_min_memg_clk_in_khz = max_fclk_khz; - clk_ranges.wm_mcif_clocks_ranges[3].wm_max_mem_clk_in_khz = max_fclk_khz; + ranges.num_reader_wm_sets = WM_COUNT; + ranges.num_writer_wm_sets = WM_COUNT; + ranges.reader_wm_sets[0].wm_inst = WM_A; + ranges.reader_wm_sets[0].min_drain_clk_khz = min_dcfclk_khz; + ranges.reader_wm_sets[0].max_drain_clk_khz = max_dcfclk_khz; + ranges.reader_wm_sets[0].min_fill_clk_khz = min_fclk_khz; + ranges.reader_wm_sets[0].max_fill_clk_khz = min_fclk_khz; + ranges.writer_wm_sets[0].wm_inst = WM_A; + ranges.writer_wm_sets[0].min_fill_clk_khz = socclk_khz; + ranges.writer_wm_sets[0].max_fill_clk_khz = overdrive; + ranges.writer_wm_sets[0].min_drain_clk_khz = min_fclk_khz; + ranges.writer_wm_sets[0].max_drain_clk_khz = min_fclk_khz; + + ranges.reader_wm_sets[1].wm_inst = WM_B; + ranges.reader_wm_sets[1].min_drain_clk_khz = min_fclk_khz; + ranges.reader_wm_sets[1].max_drain_clk_khz = max_dcfclk_khz; + ranges.reader_wm_sets[1].min_fill_clk_khz = mid_fclk_khz; + ranges.reader_wm_sets[1].max_fill_clk_khz = mid_fclk_khz; + ranges.writer_wm_sets[1].wm_inst = WM_B; + ranges.writer_wm_sets[1].min_fill_clk_khz = socclk_khz; + ranges.writer_wm_sets[1].max_fill_clk_khz = overdrive; + ranges.writer_wm_sets[1].min_drain_clk_khz = mid_fclk_khz; + ranges.writer_wm_sets[1].max_drain_clk_khz = mid_fclk_khz; + + + ranges.reader_wm_sets[2].wm_inst = WM_C; + ranges.reader_wm_sets[2].min_drain_clk_khz = min_fclk_khz; + ranges.reader_wm_sets[2].max_drain_clk_khz = max_dcfclk_khz; + ranges.reader_wm_sets[2].min_fill_clk_khz = nom_fclk_khz; + ranges.reader_wm_sets[2].max_fill_clk_khz = nom_fclk_khz; + ranges.writer_wm_sets[2].wm_inst = WM_C; + ranges.writer_wm_sets[2].min_fill_clk_khz = socclk_khz; + ranges.writer_wm_sets[2].max_fill_clk_khz = overdrive; + ranges.writer_wm_sets[2].min_drain_clk_khz = nom_fclk_khz; + ranges.writer_wm_sets[2].max_drain_clk_khz = nom_fclk_khz; + + ranges.reader_wm_sets[3].wm_inst = WM_D; + ranges.reader_wm_sets[3].min_drain_clk_khz = min_fclk_khz; + ranges.reader_wm_sets[3].max_drain_clk_khz = max_dcfclk_khz; + ranges.reader_wm_sets[3].min_fill_clk_khz = max_fclk_khz; + ranges.reader_wm_sets[3].max_fill_clk_khz = max_fclk_khz; + ranges.writer_wm_sets[3].wm_inst = WM_D; + ranges.writer_wm_sets[3].min_fill_clk_khz = socclk_khz; + ranges.writer_wm_sets[3].max_fill_clk_khz = overdrive; + ranges.writer_wm_sets[3].min_drain_clk_khz = max_fclk_khz; + ranges.writer_wm_sets[3].max_drain_clk_khz = max_fclk_khz; /* Notify PP Lib/SMU which Watermarks to use for which clock ranges */ - dm_pp_notify_wm_clock_changes_soc15(dc->ctx, &clk_ranges); + pp->set_wm_ranges(&pp->pp_smu, &ranges); } void dcn_bw_sync_calcs_and_dml(struct dc *dc) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 2d9e88f08abb..954c234090db 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -678,6 +678,17 @@ void dcn10_clock_source_destroy(struct clock_source **clk_src) *clk_src = NULL; } +static struct pp_smu_funcs_rv *dcn10_pp_smu_create(struct dc_context *ctx) +{ + struct pp_smu_funcs_rv *pp_smu = dm_alloc(sizeof(*pp_smu)); + + if (!pp_smu) + return pp_smu; + + dm_pp_get_funcs_rv(ctx, pp_smu); + return pp_smu; +} + static void destruct(struct dcn10_resource_pool *pool) { unsigned int i; @@ -751,6 +762,8 @@ static void destruct(struct dcn10_resource_pool *pool) if (pool->base.display_clock != NULL) dce_disp_clk_destroy(&pool->base.display_clock); + + dm_free(pool->base.pp_smu); } static struct mem_input *dcn10_mem_input_create( @@ -1347,11 +1360,15 @@ static bool construct( } } + pool->base.pp_smu = dcn10_pp_smu_create(ctx); + if (!dc->debug.disable_pplib_clock_request) dcn_bw_update_from_pplib(dc); dcn_bw_sync_calcs_and_dml(dc); - if (!dc->debug.disable_pplib_wm_range) + if (!dc->debug.disable_pplib_wm_range) { + dc->res_pool = &pool->base; dcn_bw_notify_pplib_of_wm_ranges(dc); + } { #if defined(CONFIG_DRM_AMD_DC_DCN1_0) diff --git a/drivers/gpu/drm/amd/display/dc/dm_pp_smu.h b/drivers/gpu/drm/amd/display/dc/dm_pp_smu.h new file mode 100644 index 000000000000..bbfa83252fc1 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dm_pp_smu.h @@ -0,0 +1,131 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef DM_PP_SMU_IF__H +#define DM_PP_SMU_IF__H + +/* + * interface to PPLIB/SMU to setup clocks and pstate requirements on SoC + */ + + +struct pp_smu { + struct dc_context *ctx; +}; + +enum wm_set_id { + WM_A, + WM_B, + WM_C, + WM_D, + WM_COUNT, +}; + +struct pp_smu_wm_set_range { + enum wm_set_id wm_inst; + uint32_t min_fill_clk_khz; + uint32_t max_fill_clk_khz; + uint32_t min_drain_clk_khz; + uint32_t max_drain_clk_khz; +}; + +struct pp_smu_wm_range_sets { + uint32_t num_reader_wm_sets; + struct pp_smu_wm_set_range reader_wm_sets[WM_COUNT]; + + uint32_t num_writer_wm_sets; + struct pp_smu_wm_set_range writer_wm_sets[WM_COUNT]; +}; + +struct pp_smu_display_requirement_rv { + /* PPSMC_MSG_SetDisplayCount: count + * 0 triggers S0i2 optimization + */ + unsigned int display_count; + + /* PPSMC_MSG_SetHardMinFclkByFreq: khz + * FCLK will vary with DPM, but never below requested hard min + */ + unsigned int hard_min_fclk_khz; + + /* PPSMC_MSG_SetHardMinDcefclkByFreq: khz + * fixed clock at requested freq, either from FCH bypass or DFS + */ + unsigned int hard_min_dcefclk_khz; + + /* PPSMC_MSG_SetMinDeepSleepDcefclk: mhz + * when DF is in cstate, dcf clock is further divided down + * to just above given frequency + */ + unsigned int min_deep_sleep_dcefclk_mhz; +}; + +struct pp_smu_funcs_rv { + struct pp_smu pp_smu; + + void (*set_display_requirement)(struct pp_smu *pp, + struct pp_smu_display_requirement_rv *req); + + /* which SMU message? are reader and writer WM separate SMU msg? */ + void (*set_wm_ranges)(struct pp_smu *pp, + struct pp_smu_wm_range_sets *ranges); + +}; + +#if 0 +struct pp_smu_funcs_rv { + + /* PPSMC_MSG_SetDisplayCount + * 0 triggers S0i2 optimization + */ + void (*set_display_count)(struct pp_smu *pp, int count); + + /* PPSMC_MSG_SetHardMinFclkByFreq + * FCLK will vary with DPM, but never below requested hard min + */ + void (*set_hard_min_fclk_by_freq)(struct pp_smu *pp, int khz); + + /* PPSMC_MSG_SetHardMinDcefclkByFreq + * fixed clock at requested freq, either from FCH bypass or DFS + */ + void (*set_hard_min_dcefclk_by_freq)(struct pp_smu *pp, int khz); + + /* PPSMC_MSG_SetMinDeepSleepDcefclk + * when DF is in cstate, dcf clock is further divided down + * to just above given frequency + */ + void (*set_min_deep_sleep_dcefclk)(struct pp_smu *pp, int mhz); + + /* todo: aesthetic + * watermark range table + */ + + /* todo: functional/feature + * PPSMC_MSG_SetHardMinSocclkByFreq: required to support DWB + */ +}; +#endif + +#endif /* DM_PP_SMU_IF__H */ diff --git a/drivers/gpu/drm/amd/display/dc/dm_services.h b/drivers/gpu/drm/amd/display/dc/dm_services.h index e9bf4c417cc7..8ab0af6f4c6b 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services.h @@ -339,9 +339,8 @@ bool dm_pp_notify_wm_clock_changes( const struct dc_context *ctx, struct dm_pp_wm_sets_with_clock_ranges *wm_with_clock_ranges); -bool dm_pp_notify_wm_clock_changes_soc15( - const struct dc_context *ctx, - struct dm_pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges); +void dm_pp_get_funcs_rv(struct dc_context *ctx, + struct pp_smu_funcs_rv *funcs); /* DAL calls this function to notify PP about completion of Mode Set. * For PP it means that current DCE clocks are those which were returned diff --git a/drivers/gpu/drm/amd/display/dc/dm_services_types.h b/drivers/gpu/drm/amd/display/dc/dm_services_types.h index 4c04ec587308..fa26cf488b3c 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services_types.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services_types.h @@ -29,6 +29,8 @@ #include "os_types.h" #include "dc_types.h" +#include "dm_pp_smu.h" + struct dm_pp_clock_range { int min_khz; int max_khz; diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index f8ade552c595..a3f0039088ab 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -48,6 +48,7 @@ void enable_surface_flip_reporting(struct dc_plane_state *plane_state, #include "clock_source.h" #include "audio.h" #include "hw_sequencer_types.h" +#include "dm_pp_smu.h" /************ link *****************/ @@ -126,6 +127,7 @@ struct resource_pool { struct stream_encoder *stream_enc[MAX_PIPES * 2]; #ifdef CONFIG_DRM_AMD_DC_DCN1_0 struct mpc *mpc; + struct pp_smu_funcs_rv *pp_smu; #endif struct dwbc *dwbc[MAX_DWB_PIPES]; diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index 13218a52e2fa..9085ec7ceac7 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -28,6 +28,7 @@ #include "core_types.h" #include "core_status.h" #include "dal_asic_id.h" +#include "dm_pp_smu.h" /* TODO unhardcode, 4 for CZ*/ #define MEMORY_TYPE_MULTIPLIER 4 -- cgit From 1dc904974eb7deef924650adc5af542878ce2040 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Mon, 31 Jul 2017 11:29:25 -0400 Subject: drm/amd/display: Per stream validate_context build v2. Until now new context would start as empty, then populated with exsisting pipes + new. Now we start with duplication of existing context and then add/delete from the context pipes as needed. This allows to do a per stream resource population, start discarding dc_validation_set and by this brings DC closer to to DRM. v2: Add some fixes and rebase. Signed-off-by: Andrey Grodzovsky Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 68 ++- drivers/gpu/drm/amd/display/dc/core/dc.c | 108 +---- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 468 +++++++++++++++------ drivers/gpu/drm/amd/display/dc/dc.h | 32 +- .../drm/amd/display/dc/dce100/dce100_resource.c | 78 +--- .../drm/amd/display/dc/dce110/dce110_resource.c | 86 +--- .../drm/amd/display/dc/dce112/dce112_resource.c | 143 +++---- .../drm/amd/display/dc/dce112/dce112_resource.h | 5 + .../drm/amd/display/dc/dce120/dce120_resource.c | 4 +- .../gpu/drm/amd/display/dc/dce80/dce80_resource.c | 79 +--- .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 85 ++-- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 19 +- drivers/gpu/drm/amd/display/dc/inc/resource.h | 6 +- 13 files changed, 577 insertions(+), 604 deletions(-) (limited to 'drivers/gpu') 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 d28de04efa42..17e9bf7a2ebb 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -25,6 +25,7 @@ #include "dm_services_types.h" #include "dc.h" +#include "dc/inc/core_types.h" #include "vid.h" #include "amdgpu.h" @@ -690,13 +691,33 @@ struct drm_atomic_state * dm_atomic_state_alloc(struct drm_device *dev) { struct dm_atomic_state *state = kzalloc(sizeof(*state), GFP_KERNEL); + struct validate_context *new_ctx; + struct amdgpu_device *adev = dev->dev_private; + struct dc *dc = adev->dm.dc; - if (!state || drm_atomic_state_init(dev, &state->base) < 0) { - kfree(state); + if (!state) return NULL; - } + + if (drm_atomic_state_init(dev, &state->base) < 0) + goto fail; + + /* copy existing configuration */ + new_ctx = dm_alloc(sizeof(*new_ctx)); + + if (!new_ctx) + goto fail; + + atomic_inc(&new_ctx->ref_count); + + dc_resource_validate_ctx_copy_construct_current(dc, new_ctx); + + state->context = new_ctx; return &state->base; + +fail: + kfree(state); + return NULL; } static void @@ -4418,7 +4439,6 @@ static int do_aquire_global_lock( int amdgpu_dm_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) { - struct dm_atomic_state *dm_state; struct drm_crtc *crtc; struct drm_crtc_state *crtc_state; struct drm_plane *plane; @@ -4432,6 +4452,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, int set_count; struct dc_validation_set set[MAX_STREAMS] = { { 0 } }; struct dm_crtc_state *old_acrtc_state, *new_acrtc_state; + struct dm_atomic_state *dm_state = to_dm_atomic_state(state); /* * This bool will be set for true for any modeset/reset @@ -4446,8 +4467,6 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, return ret; } - dm_state = to_dm_atomic_state(state); - /* copy existing configuration */ set_count = 0; list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { @@ -4490,8 +4509,17 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, if (modereset_required(crtc_state)) { - /* i.e. reset mode */ + /* i.e. reset mode */ if (new_acrtc_state->stream) { + + if (!dc_remove_stream_from_ctx( + dc, + dm_state->context, + new_acrtc_state->stream)) { + ret = -EINVAL; + goto fail; + } + set_count = remove_from_val_sets( set, set_count, @@ -4539,8 +4567,19 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, if (modeset_required(crtc_state, new_stream, old_acrtc_state->stream)) { - if (new_acrtc_state->stream) + if (new_acrtc_state->stream) { + + if (!dc_remove_stream_from_ctx( + dc, + dm_state->context, + new_acrtc_state->stream)) { + ret = -EINVAL; + goto fail; + } + + dc_stream_release(new_acrtc_state->stream); + } new_acrtc_state->stream = new_stream; @@ -4551,6 +4590,14 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, new_acrtc_state->stream, crtc); + if (!dc_add_stream_to_ctx( + dc, + dm_state->context, + new_acrtc_state->stream)) { + ret = -EINVAL; + goto fail; + } + lock_and_validation_needed = true; } else { /* @@ -4667,9 +4714,8 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, ret = do_aquire_global_lock(dev, state); if (ret) goto fail; - WARN_ON(dm_state->context); - dm_state->context = dc_get_validate_context(dc, set, set_count); - if (!dm_state->context) { + + if (!dc_validate_global_state(dc, set, set_count, dm_state->context)) { ret = -EINVAL; goto fail; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 44c7b52e4a00..10126d9a7233 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -669,41 +669,6 @@ void dc_destroy(struct dc **dc) *dc = NULL; } -static bool is_validation_required( - const struct dc *dc, - const struct dc_validation_set set[], - int set_count) -{ - const struct validate_context *context = dc->current_context; - int i, j; - - if (context->stream_count != set_count) - return true; - - for (i = 0; i < set_count; i++) { - - if (set[i].plane_count != context->stream_status[i].plane_count) - return true; - if (!dc_is_stream_unchanged(set[i].stream, context->streams[i])) - return true; - - for (j = 0; j < set[i].plane_count; j++) { - struct dc_plane_state temp_plane; - memset(&temp_plane, 0, sizeof(temp_plane)); - - temp_plane = *context->stream_status[i].plane_states[j]; - temp_plane.clip_rect = set[i].plane_states[j]->clip_rect; - temp_plane.dst_rect.x = set[i].plane_states[j]->dst_rect.x; - temp_plane.dst_rect.y = set[i].plane_states[j]->dst_rect.y; - - if (memcmp(&temp_plane, set[i].plane_states[j], sizeof(temp_plane)) != 0) - return true; - } - } - - return false; -} - static bool validate_streams ( struct dc *dc, const struct dc_validation_set set[], @@ -733,52 +698,12 @@ static bool validate_surfaces( return true; } -struct validate_context *dc_get_validate_context( - struct dc *dc, - const struct dc_validation_set set[], - uint8_t set_count) -{ - struct dc *core_dc = dc; - enum dc_status result = DC_ERROR_UNEXPECTED; - struct validate_context *context; - - - context = dm_alloc(sizeof(struct validate_context)); - if (context == NULL) - goto context_alloc_fail; - - atomic_inc(&context->ref_count); - - if (!is_validation_required(core_dc, set, set_count)) { - dc_resource_validate_ctx_copy_construct(core_dc->current_context, context); - return context; - } - - result = core_dc->res_pool->funcs->validate_with_context( - core_dc, set, set_count, context, core_dc->current_context); - -context_alloc_fail: - if (result != DC_OK) { - dm_logger_write(core_dc->ctx->logger, LOG_WARNING, - "%s:resource validation failed, dc_status:%d\n", - __func__, - result); - - dc_release_validate_context(context); - context = NULL; - } - - return context; - -} - bool dc_validate_resources( struct dc *dc, const struct dc_validation_set set[], uint8_t set_count) { - struct dc *core_dc = dc; - enum dc_status result = DC_ERROR_UNEXPECTED; + bool result = false; struct validate_context *context; if (!validate_streams(dc, set, set_count)) @@ -793,21 +718,16 @@ bool dc_validate_resources( atomic_inc(&context->ref_count); - result = core_dc->res_pool->funcs->validate_with_context( - core_dc, set, set_count, context, NULL); + dc_resource_validate_ctx_copy_construct_current(dc, context); -context_alloc_fail: - if (result != DC_OK) { - dm_logger_write(core_dc->ctx->logger, LOG_WARNING, - "%s:resource validation failed, dc_status:%d\n", - __func__, - result); - } + result = dc_validate_with_context( + dc, set, set_count, context); +context_alloc_fail: dc_release_validate_context(context); context = NULL; - return result == DC_OK; + return result; } bool dc_validate_guaranteed( @@ -1093,7 +1013,7 @@ bool dc_commit_streams( uint8_t stream_count) { struct dc *core_dc = dc; - enum dc_status result = DC_ERROR_UNEXPECTED; + bool result = false; struct validate_context *context; struct dc_validation_set set[MAX_STREAMS] = { {0, {0} } }; int i; @@ -1135,13 +1055,11 @@ bool dc_commit_streams( atomic_inc(&context->ref_count); - result = core_dc->res_pool->funcs->validate_with_context( - core_dc, set, stream_count, context, core_dc->current_context); - if (result != DC_OK){ - dm_logger_write(core_dc->ctx->logger, LOG_ERROR, - "%s: Context validation failed! dc_status:%d\n", - __func__, - result); + dc_resource_validate_ctx_copy_construct_current(dc, context); + + result = dc_validate_with_context( + dc, set, stream_count, context); + if (!result) { BREAK_TO_DEBUGGER(); goto fail; } @@ -1152,7 +1070,7 @@ fail: dc_release_validate_context(context); context_alloc_fail: - return (result == DC_OK); + return result; } bool dc_post_update_surfaces_to_stream(struct dc *dc) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 2b357318f945..f640986c6fd2 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -938,7 +938,7 @@ struct pipe_ctx *resource_get_head_pipe_for_stream( int i; for (i = 0; i < MAX_PIPES; i++) { if (res_ctx->pipe_ctx[i].stream == stream && - res_ctx->pipe_ctx[i].stream_res.stream_enc) { + !res_ctx->pipe_ctx[i].top_pipe) { return &res_ctx->pipe_ctx[i]; break; } @@ -1217,29 +1217,31 @@ bool resource_validate_attach_surfaces( #define TMDS_MAX_PIXEL_CLOCK_IN_KHZ 165000 #define TMDS_MAX_PIXEL_CLOCK_IN_KHZ_UPMOST 297000 -static void set_stream_engine_in_use( +static void update_stream_engine_usage( struct resource_context *res_ctx, const struct resource_pool *pool, - struct stream_encoder *stream_enc) + struct stream_encoder *stream_enc, + bool acquired) { int i; for (i = 0; i < pool->stream_enc_count; i++) { if (pool->stream_enc[i] == stream_enc) - res_ctx->is_stream_enc_acquired[i] = true; + res_ctx->is_stream_enc_acquired[i] = acquired; } } /* TODO: release audio object */ -static void set_audio_in_use( +static void update_audio_usage( struct resource_context *res_ctx, const struct resource_pool *pool, - struct audio *audio) + struct audio *audio, + bool acquired) { int i; for (i = 0; i < pool->audio_count; i++) { if (pool->audios[i] == audio) - res_ctx->is_audio_acquired[i] = true; + res_ctx->is_audio_acquired[i] = acquired; } } @@ -1361,6 +1363,100 @@ bool resource_is_stream_unchanged( return false; } +bool dc_add_stream_to_ctx( + struct dc *dc, + struct validate_context *new_ctx, + struct dc_stream_state *stream) +{ + struct dc_context *dc_ctx = dc->ctx; + enum dc_status res; + + if (new_ctx->stream_count >= dc->res_pool->pipe_count) { + DC_ERROR("Max streams reached, can add stream %p !\n", stream); + return DC_ERROR_UNEXPECTED; + } + + new_ctx->streams[new_ctx->stream_count] = stream; + dc_stream_retain(stream); + new_ctx->stream_count++; + + res = dc->res_pool->funcs->add_stream_to_ctx(dc, new_ctx, stream); + if (res != DC_OK) + DC_ERROR("Adding stream %p to context failed with err %d!\n", stream, res); + + return res == DC_OK; +} + +bool dc_remove_stream_from_ctx( + struct dc *dc, + struct validate_context *new_ctx, + struct dc_stream_state *stream) +{ + int i, j; + struct dc_context *dc_ctx = dc->ctx; + struct pipe_ctx *del_pipe = NULL; + + /*TODO MPO to remove extra pipe or in surface remove ?*/ + + /* Release primary and secondary pipe (if exsist) */ + for (i = 0; i < MAX_PIPES; i++) { + if (new_ctx->res_ctx.pipe_ctx[i].stream == stream) { + del_pipe = &new_ctx->res_ctx.pipe_ctx[i]; + + if (del_pipe->stream_res.stream_enc) + update_stream_engine_usage( + &new_ctx->res_ctx, + dc->res_pool, + del_pipe->stream_res.stream_enc, + false); + + if (del_pipe->stream_res.audio) + update_audio_usage( + &new_ctx->res_ctx, + dc->res_pool, + del_pipe->stream_res.audio, + false); + + memset(del_pipe, 0, sizeof(*del_pipe)); + } + } + + if (!del_pipe) { + DC_ERROR("Pipe not found for stream %p !\n", stream); + return DC_ERROR_UNEXPECTED; + } + + for (i = 0; i < new_ctx->stream_count; i++) + if (new_ctx->streams[i] == stream) + break; + + if (new_ctx->streams[i] != stream) { + DC_ERROR("Context doesn't have stream %p !\n", stream); + return DC_ERROR_UNEXPECTED; + } + + dc_stream_release(new_ctx->streams[i]); + new_ctx->stream_count--; + + /*TODO move into dc_remove_surface_from_ctx ?*/ + for (j = 0; j < new_ctx->stream_status[i].plane_count; j++) + dc_plane_state_release(new_ctx->stream_status[i].plane_states[j]); + + /* Trim back arrays */ + for (; i < new_ctx->stream_count; i++) { + new_ctx->streams[i] = new_ctx->streams[i + 1]; + new_ctx->stream_status[i] = new_ctx->stream_status[i + 1]; + } + + new_ctx->streams[new_ctx->stream_count] = NULL; + memset( + &new_ctx->stream_status[new_ctx->stream_count], + 0, + sizeof(new_ctx->stream_status[0])); + + return DC_OK; +} + static void copy_pipe_ctx( const struct pipe_ctx *from_pipe_ctx, struct pipe_ctx *to_pipe_ctx) { @@ -1440,15 +1536,16 @@ static void calculate_phy_pix_clks(struct dc_stream_state *stream) enum dc_status resource_map_pool_resources( const struct dc *dc, struct validate_context *context, - struct validate_context *old_context) + struct dc_stream_state *stream) { const struct resource_pool *pool = dc->res_pool; - int i, j; - - for (i = 0; old_context && i < context->stream_count; i++) { - struct dc_stream_state *stream = context->streams[i]; + int i; + struct dc_context *dc_ctx = dc->ctx; + struct pipe_ctx *pipe_ctx = NULL; + int pipe_idx = -1; - if (!resource_is_stream_unchanged(old_context, stream)) { + /* TODO Check if this is needed */ + /*if (!resource_is_stream_unchanged(old_context, stream)) { if (stream != NULL && old_context->streams[i] != NULL) { stream->bit_depth_params = old_context->streams[i]->bit_depth_params; @@ -1456,119 +1553,228 @@ enum dc_status resource_map_pool_resources( continue; } } + */ - /* mark resources used for stream that is already active */ - for (j = 0; j < pool->pipe_count; j++) { - struct pipe_ctx *pipe_ctx = - &context->res_ctx.pipe_ctx[j]; - const struct pipe_ctx *old_pipe_ctx = - &old_context->res_ctx.pipe_ctx[j]; - - if (!are_stream_backends_same(old_pipe_ctx->stream, stream)) - continue; + /* acquire new resources */ + pipe_idx = acquire_first_free_pipe(&context->res_ctx, pool, stream); - if (old_pipe_ctx->top_pipe) - continue; +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + if (pipe_idx < 0) + acquire_first_split_pipe(&context->res_ctx, pool, stream); +#endif + if (pipe_idx < 0) + return DC_NO_CONTROLLER_RESOURCE; + + pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx]; + + pipe_ctx->stream_res.stream_enc = + find_first_free_match_stream_enc_for_link( + &context->res_ctx, pool, stream); + + if (!pipe_ctx->stream_res.stream_enc) + return DC_NO_STREAM_ENG_RESOURCE; + + update_stream_engine_usage( + &context->res_ctx, pool, + pipe_ctx->stream_res.stream_enc, + true); + + /* TODO: Add check if ASIC support and EDID audio */ + if (!stream->sink->converter_disable_audio && + dc_is_audio_capable_signal(pipe_ctx->stream->signal) && + stream->audio_info.mode_count) { + pipe_ctx->stream_res.audio = find_first_free_audio( + &context->res_ctx, pool); + + /* + * Audio assigned in order first come first get. + * There are asics which has number of audio + * resources less then number of pipes + */ + if (pipe_ctx->stream_res.audio) + update_audio_usage(&context->res_ctx, pool, + pipe_ctx->stream_res.audio, true); + } - pipe_ctx->stream = stream; - copy_pipe_ctx(old_pipe_ctx, pipe_ctx); + for (i = 0; i < context->stream_count; i++) + if (context->streams[i] == stream) { + context->stream_status[i].primary_otg_inst = pipe_ctx->stream_res.tg->inst; + return DC_OK; + } - /* Split pipe resource, do not acquire back end */ - if (!pipe_ctx->stream_res.stream_enc) - continue; + DC_ERROR("Stream %p not found in new ctx!\n", stream); + return DC_ERROR_UNEXPECTED; +} - set_stream_engine_in_use( - &context->res_ctx, pool, - pipe_ctx->stream_res.stream_enc); +/* first stream in the context is used to populate the rest */ +void validate_guaranteed_copy_streams( + struct validate_context *context, + int max_streams) +{ + int i; - /* Switch to dp clock source only if there is - * no non dp stream that shares the same timing - * with the dp stream. - */ - if (dc_is_dp_signal(pipe_ctx->stream->signal) && - !find_pll_sharable_stream(stream, context)) - pipe_ctx->clock_source = pool->dp_clock_source; + for (i = 1; i < max_streams; i++) { + context->streams[i] = context->streams[0]; - resource_reference_clock_source( - &context->res_ctx, pool, - pipe_ctx->clock_source); + copy_pipe_ctx(&context->res_ctx.pipe_ctx[0], + &context->res_ctx.pipe_ctx[i]); + context->res_ctx.pipe_ctx[i].stream = + context->res_ctx.pipe_ctx[0].stream; - set_audio_in_use(&context->res_ctx, pool, - pipe_ctx->stream_res.audio); - } + dc_stream_retain(context->streams[i]); + context->stream_count++; } +} - for (i = 0; i < context->stream_count; i++) { - struct dc_stream_state *stream = context->streams[i]; - struct pipe_ctx *pipe_ctx = NULL; - int pipe_idx = -1; +void dc_resource_validate_ctx_copy_construct_current( + const struct dc *dc, + struct validate_context *dst_ctx) +{ + dc_resource_validate_ctx_copy_construct(dc->current_context, dst_ctx); +} - if (old_context && resource_is_stream_unchanged(old_context, stream)) - continue; - /* acquire new resources */ - pipe_idx = acquire_first_free_pipe(&context->res_ctx, pool, stream); -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) - if (pipe_idx < 0) - acquire_first_split_pipe(&context->res_ctx, pool, stream); -#endif - if (pipe_idx < 0) - return DC_NO_CONTROLLER_RESOURCE; +bool dc_validate_with_context( + struct dc *dc, + const struct dc_validation_set set[], + int set_count, + struct validate_context *context) +{ + int i, j; + enum dc_status res = DC_ERROR_UNEXPECTED; + bool found = false; + int old_stream_count = context->stream_count; + struct dc_stream_state *del_streams[MAX_PIPES] = { 0 }; + struct dc_stream_state *add_streams[MAX_PIPES] = { 0 }; + int del_streams_count = 0; + int add_streams_count = 0; - pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx]; - pipe_ctx->stream_res.stream_enc = - find_first_free_match_stream_enc_for_link( - &context->res_ctx, pool, stream); + /* First remove from context all deleted streams */ + for (i = 0; i < old_stream_count; i++) { + struct dc_stream_state *stream = context->streams[i]; + + for (j = 0; j < set_count; j++) { + if (stream == set[j].stream) { + found = true; + break; + } + } - if (!pipe_ctx->stream_res.stream_enc) - return DC_NO_STREAM_ENG_RESOURCE; + if (!found) + del_streams[del_streams_count++] = stream; - set_stream_engine_in_use( - &context->res_ctx, pool, - pipe_ctx->stream_res.stream_enc); + found = false; + } - /* TODO: Add check if ASIC support and EDID audio */ - if (!stream->sink->converter_disable_audio && - dc_is_audio_capable_signal(pipe_ctx->stream->signal) && - stream->audio_info.mode_count) { - pipe_ctx->stream_res.audio = find_first_free_audio( - &context->res_ctx, pool); + /* Now add new ones */ + for (i = 0; i < set_count; i++) { + struct dc_stream_state *stream = set[i].stream; - /* - * Audio assigned in order first come first get. - * There are asics which has number of audio - * resources less then number of pipes - */ - if (pipe_ctx->stream_res.audio) - set_audio_in_use( - &context->res_ctx, pool, - pipe_ctx->stream_res.audio); + for (j = 0; j < old_stream_count; j++) { + if (stream == context->streams[j]) { + found = true; + break; + } } - context->stream_status[i].primary_otg_inst = pipe_ctx->stream_res.tg->inst; + if (!found) + add_streams[add_streams_count++] = stream; + + found = false; } - return DC_OK; + for (i = 0; i < del_streams_count; i++) + if (!dc_remove_stream_from_ctx(dc, context, del_streams[i])) + goto fail; + + for (i = 0; i < add_streams_count; i++) + if (!dc_add_stream_to_ctx(dc, context, add_streams[i])) + goto fail; + + if (!dc_validate_global_state(dc, set, set_count, context)) + goto fail; + + res = DC_OK; + +fail: + if (res != DC_OK) { + dm_logger_write(dc->ctx->logger, LOG_WARNING, + "%s:resource validation failed, dc_status:%d\n", + __func__, + res); +} + return res == DC_OK; } -/* first stream in the context is used to populate the rest */ -void validate_guaranteed_copy_streams( - struct validate_context *context, - int max_streams) +bool dc_validate_global_state( + struct dc *dc, + const struct dc_validation_set set[], + int set_count, + struct validate_context *new_ctx) { - int i; + enum dc_status result = DC_ERROR_UNEXPECTED; + struct dc_context *dc_ctx = dc->ctx; + struct validate_context *old_context = dc->current_context; + int i, j; - for (i = 1; i < max_streams; i++) { - context->streams[i] = context->streams[0]; + if (dc->res_pool->funcs->validate_global && + dc->res_pool->funcs->validate_global(dc, set, set_count, + old_context, new_ctx) != DC_OK) + return false; - copy_pipe_ctx(&context->res_ctx.pipe_ctx[0], - &context->res_ctx.pipe_ctx[i]); - context->res_ctx.pipe_ctx[i].stream = - context->res_ctx.pipe_ctx[0].stream; + /* TODO without this SWDEV-114774 brakes */ + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &new_ctx->res_ctx.pipe_ctx[i]; - dc_stream_retain(context->streams[i]); - context->stream_count++; + if (pipe_ctx->top_pipe) + memset(pipe_ctx, 0, sizeof(*pipe_ctx)); + } + + for (i = 0; new_ctx && i < new_ctx->stream_count; i++) { + struct dc_stream_state *stream = new_ctx->streams[i]; + + for (j = 0; j < dc->res_pool->pipe_count; j++) { + struct pipe_ctx *pipe_ctx = &new_ctx->res_ctx.pipe_ctx[j]; + + if (pipe_ctx->stream != stream) + continue; + + /* Switch to dp clock source only if there is + * no non dp stream that shares the same timing + * with the dp stream. + */ + if (dc_is_dp_signal(pipe_ctx->stream->signal) && + !find_pll_sharable_stream(stream, new_ctx)) { + + resource_unreference_clock_source( + &new_ctx->res_ctx, + dc->res_pool, + &pipe_ctx->clock_source); + pipe_ctx->clock_source = dc->res_pool->dp_clock_source; + resource_reference_clock_source( + &new_ctx->res_ctx, + dc->res_pool, + pipe_ctx->clock_source); + } + } + } + + /*TODO This should be ok */ + /* Split pipe resource, do not acquire back end */ + + if (!resource_validate_attach_surfaces( + set, set_count, old_context, new_ctx, dc->res_pool)) { + DC_ERROR("Failed to attach surface to stream!\n"); + return DC_FAIL_ATTACH_SURFACES; } + + result = resource_build_scaling_params_for_context(dc, new_ctx); + + if (result == DC_OK) + if (!dc->res_pool->funcs->validate_bandwidth(dc, new_ctx)) + result = DC_FAIL_BANDWIDTH_VALIDATE; + + return result; } static void patch_gamut_packet_checksum( @@ -2318,54 +2524,40 @@ void resource_build_info_frame(struct pipe_ctx *pipe_ctx) enum dc_status resource_map_clock_resources( const struct dc *dc, struct validate_context *context, - struct validate_context *old_context) + struct dc_stream_state *stream) { - int i, j; - const struct resource_pool *pool = dc->res_pool; - /* acquire new resources */ - for (i = 0; i < context->stream_count; i++) { - struct dc_stream_state *stream = context->streams[i]; - - if (old_context && resource_is_stream_unchanged(old_context, stream)) - continue; + const struct resource_pool *pool = dc->res_pool; + struct pipe_ctx *pipe_ctx = resource_get_head_pipe_for_stream( + &context->res_ctx, stream); - for (j = 0; j < MAX_PIPES; j++) { - struct pipe_ctx *pipe_ctx = - &context->res_ctx.pipe_ctx[j]; + if (!pipe_ctx) + return DC_ERROR_UNEXPECTED; - if (context->res_ctx.pipe_ctx[j].stream != stream) - continue; + if (dc_is_dp_signal(pipe_ctx->stream->signal) + || pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL) + pipe_ctx->clock_source = pool->dp_clock_source; + else { + pipe_ctx->clock_source = NULL; - if (dc_is_dp_signal(pipe_ctx->stream->signal) - || pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL) - pipe_ctx->clock_source = pool->dp_clock_source; - else { - pipe_ctx->clock_source = NULL; - - if (!dc->config.disable_disp_pll_sharing) - resource_find_used_clk_src_for_sharing( - &context->res_ctx, - pipe_ctx); - - if (pipe_ctx->clock_source == NULL) - pipe_ctx->clock_source = - dc_resource_find_first_free_pll( - &context->res_ctx, - pool); - } + if (!dc->config.disable_disp_pll_sharing) + resource_find_used_clk_src_for_sharing( + &context->res_ctx, + pipe_ctx); - if (pipe_ctx->clock_source == NULL) - return DC_NO_CLOCK_SOURCE_RESOURCE; + if (pipe_ctx->clock_source == NULL) + pipe_ctx->clock_source = + dc_resource_find_first_free_pll( + &context->res_ctx, + pool); + } - resource_reference_clock_source( - &context->res_ctx, pool, - pipe_ctx->clock_source); + if (pipe_ctx->clock_source == NULL) + return DC_NO_CLOCK_SOURCE_RESOURCE; - /* only one cs per stream regardless of mpo */ - break; - } - } + resource_reference_clock_source( + &context->res_ctx, pool, + pipe_ctx->clock_source); return DC_OK; } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 629aa3c323ca..2b4fc6616243 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -618,6 +618,16 @@ bool dc_stream_get_scanoutpos(const struct dc_stream_state *stream, uint32_t *h_position, uint32_t *v_position); +bool dc_remove_stream_from_ctx( + struct dc *dc, + struct validate_context *new_ctx, + struct dc_stream_state *stream); + +bool dc_add_stream_to_ctx( + struct dc *dc, + struct validate_context *new_ctx, + struct dc_stream_state *stream); + /* * Structure to store surface/stream associations for validation */ @@ -630,16 +640,18 @@ struct dc_validation_set { bool dc_validate_stream(struct dc *dc, struct dc_stream_state *stream); bool dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state); -/* - * This function takes a set of resources and checks that they are cofunctional. - * - * After this call: - * No hardware is programmed for call. Only validation is done. - */ -struct validate_context *dc_get_validate_context( + +bool dc_validate_with_context( struct dc *dc, const struct dc_validation_set set[], - uint8_t set_count); + int set_count, + struct validate_context *context); + +bool dc_validate_global_state( + struct dc *dc, + const struct dc_validation_set set[], + int set_count, + struct validate_context *new_ctx); bool dc_validate_resources( struct dc *dc, @@ -662,6 +674,10 @@ void dc_resource_validate_ctx_copy_construct( const struct validate_context *src_ctx, struct validate_context *dst_ctx); +void dc_resource_validate_ctx_copy_construct_current( + const struct dc *dc, + struct validate_context *dst_ctx); + void dc_resource_validate_ctx_destruct(struct validate_context *context); /* diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index b2b03633eb4f..c9dad4e2a7c8 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -654,35 +654,20 @@ static void destruct(struct dce110_resource_pool *pool) static enum dc_status build_mapped_resource( const struct dc *dc, struct validate_context *context, - struct validate_context *old_context) + struct dc_stream_state *stream) { enum dc_status status = DC_OK; - uint8_t i, j; + struct pipe_ctx *pipe_ctx = resource_get_head_pipe_for_stream(&context->res_ctx, stream); - for (i = 0; i < context->stream_count; i++) { - struct dc_stream_state *stream = context->streams[i]; + if (!pipe_ctx) + return DC_ERROR_UNEXPECTED; - if (old_context && resource_is_stream_unchanged(old_context, stream)) - continue; - - for (j = 0; j < MAX_PIPES; j++) { - struct pipe_ctx *pipe_ctx = - &context->res_ctx.pipe_ctx[j]; - - if (context->res_ctx.pipe_ctx[j].stream != stream) - continue; - - status = dce110_resource_build_pipe_hw_param(pipe_ctx); + status = dce110_resource_build_pipe_hw_param(pipe_ctx); - if (status != DC_OK) - return status; + if (status != DC_OK) + return status; - resource_build_info_frame(pipe_ctx); - - /* do not need to validate non root pipes */ - break; - } - } + resource_build_info_frame(pipe_ctx); return DC_OK; } @@ -719,48 +704,17 @@ static bool dce100_validate_surface_sets( return true; } -enum dc_status dce100_validate_with_context( +enum dc_status dce100_validate_global( struct dc *dc, const struct dc_validation_set set[], int set_count, - struct validate_context *context, - struct validate_context *old_context) + struct validate_context *old_context, + struct validate_context *context) { - struct dc_context *dc_ctx = dc->ctx; - enum dc_status result = DC_ERROR_UNEXPECTED; - int i; - if (!dce100_validate_surface_sets(set, set_count)) return DC_FAIL_SURFACE_VALIDATE; - for (i = 0; i < set_count; i++) { - context->streams[i] = set[i].stream; - dc_stream_retain(context->streams[i]); - context->stream_count++; - } - - result = resource_map_pool_resources(dc, context, old_context); - - if (result == DC_OK) - result = resource_map_clock_resources(dc, context, old_context); - - if (!resource_validate_attach_surfaces(set, set_count, - old_context, context, dc->res_pool)) { - DC_ERROR("Failed to attach surface to stream!\n"); - return DC_FAIL_ATTACH_SURFACES; - } - - if (result == DC_OK) - result = build_mapped_resource(dc, context, old_context); - - if (result == DC_OK) - result = resource_build_scaling_params_for_context(dc, context); - - if (result == DC_OK) - if (!dce100_validate_bandwidth(dc, context)) - result = DC_FAIL_BANDWIDTH_VALIDATE; - - return result; + return DC_OK; } enum dc_status dce100_validate_guaranteed( @@ -774,13 +728,13 @@ enum dc_status dce100_validate_guaranteed( dc_stream_retain(context->streams[0]); context->stream_count++; - result = resource_map_pool_resources(dc, context, NULL); + result = resource_map_pool_resources(dc, context, dc_stream); if (result == DC_OK) - result = resource_map_clock_resources(dc, context, NULL); + result = resource_map_clock_resources(dc, context, dc_stream); if (result == DC_OK) - result = build_mapped_resource(dc, context, NULL); + result = build_mapped_resource(dc, context, dc_stream); if (result == DC_OK) { validate_guaranteed_copy_streams( @@ -816,10 +770,10 @@ enum dc_status dce100_validate_plane(const struct dc_plane_state *plane_state) static const struct resource_funcs dce100_res_pool_funcs = { .destroy = dce100_destroy_resource_pool, .link_enc_create = dce100_link_encoder_create, - .validate_with_context = dce100_validate_with_context, .validate_guaranteed = dce100_validate_guaranteed, .validate_bandwidth = dce100_validate_bandwidth, .validate_plane = dce100_validate_plane, + .validate_global = dce100_validate_global }; static bool construct( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 2154c2e567f2..d682180f2eaf 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -774,41 +774,26 @@ static bool is_surface_pixel_format_supported(struct pipe_ctx *pipe_ctx, unsigne static enum dc_status build_mapped_resource( const struct dc *dc, struct validate_context *context, - struct validate_context *old_context) + struct dc_stream_state *stream) { enum dc_status status = DC_OK; - uint8_t i, j; - - for (i = 0; i < context->stream_count; i++) { - struct dc_stream_state *stream = context->streams[i]; - - if (old_context && resource_is_stream_unchanged(old_context, stream)) - continue; + struct pipe_ctx *pipe_ctx = resource_get_head_pipe_for_stream(&context->res_ctx, stream); - for (j = 0; j < MAX_PIPES; j++) { - struct pipe_ctx *pipe_ctx = - &context->res_ctx.pipe_ctx[j]; + if (!pipe_ctx) + return DC_ERROR_UNEXPECTED; - if (context->res_ctx.pipe_ctx[j].stream != stream) - continue; + if (!is_surface_pixel_format_supported(pipe_ctx, + dc->res_pool->underlay_pipe_index)) + return DC_SURFACE_PIXEL_FORMAT_UNSUPPORTED; - if (!is_surface_pixel_format_supported(pipe_ctx, - dc->res_pool->underlay_pipe_index)) - return DC_SURFACE_PIXEL_FORMAT_UNSUPPORTED; + status = dce110_resource_build_pipe_hw_param(pipe_ctx); - status = dce110_resource_build_pipe_hw_param(pipe_ctx); + if (status != DC_OK) + return status; - if (status != DC_OK) - return status; + /* TODO: validate audio ASIC caps, encoder */ - /* TODO: validate audio ASIC caps, encoder */ - - resource_build_info_frame(pipe_ctx); - - /* do not need to validate non root pipes */ - break; - } - } + resource_build_info_frame(pipe_ctx); return DC_OK; } @@ -927,48 +912,17 @@ static bool dce110_validate_surface_sets( return true; } -static enum dc_status dce110_validate_with_context( +enum dc_status dce110_validate_global( struct dc *dc, const struct dc_validation_set set[], int set_count, - struct validate_context *context, - struct validate_context *old_context) + struct validate_context *old_context, + struct validate_context *context) { - struct dc_context *dc_ctx = dc->ctx; - enum dc_status result = DC_ERROR_UNEXPECTED; - int i; - if (!dce110_validate_surface_sets(set, set_count)) return DC_FAIL_SURFACE_VALIDATE; - for (i = 0; i < set_count; i++) { - context->streams[i] = set[i].stream; - dc_stream_retain(context->streams[i]); - context->stream_count++; - } - - result = resource_map_pool_resources(dc, context, old_context); - - if (result == DC_OK) - result = resource_map_clock_resources(dc, context, old_context); - - if (!resource_validate_attach_surfaces(set, set_count, - old_context, context, dc->res_pool)) { - DC_ERROR("Failed to attach surface to stream!\n"); - return DC_FAIL_ATTACH_SURFACES; - } - - if (result == DC_OK) - result = build_mapped_resource(dc, context, old_context); - - if (result == DC_OK) - result = resource_build_scaling_params_for_context(dc, context); - - if (result == DC_OK) - if (!dce110_validate_bandwidth(dc, context)) - result = DC_FAIL_BANDWIDTH_VALIDATE; - - return result; + return DC_OK; } static enum dc_status dce110_validate_guaranteed( @@ -982,13 +936,13 @@ static enum dc_status dce110_validate_guaranteed( dc_stream_retain(context->streams[0]); context->stream_count++; - result = resource_map_pool_resources(dc, context, NULL); + result = resource_map_pool_resources(dc, context, dc_stream); if (result == DC_OK) - result = resource_map_clock_resources(dc, context, NULL); + result = resource_map_clock_resources(dc, context, dc_stream); if (result == DC_OK) - result = build_mapped_resource(dc, context, NULL); + result = build_mapped_resource(dc, context, dc_stream); if (result == DC_OK) { validate_guaranteed_copy_streams( @@ -1078,10 +1032,10 @@ static void dce110_destroy_resource_pool(struct resource_pool **pool) static const struct resource_funcs dce110_res_pool_funcs = { .destroy = dce110_destroy_resource_pool, .link_enc_create = dce110_link_encoder_create, - .validate_with_context = dce110_validate_with_context, .validate_guaranteed = dce110_validate_guaranteed, .validate_bandwidth = dce110_validate_bandwidth, .acquire_idle_pipe_for_layer = dce110_acquire_underlay, + .validate_global = dce110_validate_global }; static bool underlay_create(struct dc_context *ctx, struct resource_pool *pool) diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 89a8dfa68c01..85a396ef5aa5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -725,35 +725,20 @@ static struct clock_source *find_matching_pll( static enum dc_status build_mapped_resource( const struct dc *dc, struct validate_context *context, - struct validate_context *old_context) + struct dc_stream_state *stream) { enum dc_status status = DC_OK; - uint8_t i, j; + struct pipe_ctx *pipe_ctx = resource_get_head_pipe_for_stream(&context->res_ctx, stream); - for (i = 0; i < context->stream_count; i++) { - struct dc_stream_state *stream = context->streams[i]; + if (!pipe_ctx) + return DC_ERROR_UNEXPECTED; - if (old_context && resource_is_stream_unchanged(old_context, stream)) - continue; - - for (j = 0; j < MAX_PIPES; j++) { - struct pipe_ctx *pipe_ctx = - &context->res_ctx.pipe_ctx[j]; - - if (context->res_ctx.pipe_ctx[j].stream != stream) - continue; + status = dce110_resource_build_pipe_hw_param(pipe_ctx); - status = dce110_resource_build_pipe_hw_param(pipe_ctx); + if (status != DC_OK) + return status; - if (status != DC_OK) - return status; - - resource_build_info_frame(pipe_ctx); - - /* do not need to validate non root pipes */ - break; - } - } + resource_build_info_frame(pipe_ctx); return DC_OK; } @@ -839,45 +824,32 @@ bool dce112_validate_bandwidth( enum dc_status resource_map_phy_clock_resources( const struct dc *dc, struct validate_context *context, - struct validate_context *old_context) + struct dc_stream_state *stream) { - uint8_t i, j; /* acquire new resources */ - for (i = 0; i < context->stream_count; i++) { - struct dc_stream_state *stream = context->streams[i]; - - if (old_context && resource_is_stream_unchanged(old_context, stream)) - continue; - - for (j = 0; j < MAX_PIPES; j++) { - struct pipe_ctx *pipe_ctx = - &context->res_ctx.pipe_ctx[j]; - - if (context->res_ctx.pipe_ctx[j].stream != stream) - continue; + struct pipe_ctx *pipe_ctx = resource_get_head_pipe_for_stream( + &context->res_ctx, stream); - if (dc_is_dp_signal(pipe_ctx->stream->signal) - || pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL) - pipe_ctx->clock_source = - dc->res_pool->dp_clock_source; - else - pipe_ctx->clock_source = find_matching_pll( - &context->res_ctx, dc->res_pool, - stream); + if (!pipe_ctx) + return DC_ERROR_UNEXPECTED; - if (pipe_ctx->clock_source == NULL) - return DC_NO_CLOCK_SOURCE_RESOURCE; + if (dc_is_dp_signal(pipe_ctx->stream->signal) + || pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL) + pipe_ctx->clock_source = + dc->res_pool->dp_clock_source; + else + pipe_ctx->clock_source = find_matching_pll( + &context->res_ctx, dc->res_pool, + stream); - resource_reference_clock_source( - &context->res_ctx, - dc->res_pool, - pipe_ctx->clock_source); + if (pipe_ctx->clock_source == NULL) + return DC_NO_CLOCK_SOURCE_RESOURCE; - /* only one cs per stream regardless of mpo */ - break; - } - } + resource_reference_clock_source( + &context->res_ctx, + dc->res_pool, + pipe_ctx->clock_source); return DC_OK; } @@ -903,46 +875,21 @@ static bool dce112_validate_surface_sets( return true; } -enum dc_status dce112_validate_with_context( +enum dc_status dce112_add_stream_to_ctx( struct dc *dc, - const struct dc_validation_set set[], - int set_count, - struct validate_context *context, - struct validate_context *old_context) + struct validate_context *new_ctx, + struct dc_stream_state *dc_stream) { - struct dc_context *dc_ctx = dc->ctx; enum dc_status result = DC_ERROR_UNEXPECTED; - int i; - if (!dce112_validate_surface_sets(set, set_count)) - return DC_FAIL_SURFACE_VALIDATE; - - for (i = 0; i < set_count; i++) { - context->streams[i] = set[i].stream; - dc_stream_retain(context->streams[i]); - context->stream_count++; - } - - result = resource_map_pool_resources(dc, context, old_context); + result = resource_map_pool_resources(dc, new_ctx, dc_stream); if (result == DC_OK) - result = resource_map_phy_clock_resources(dc, context, old_context); - - if (!resource_validate_attach_surfaces(set, set_count, - old_context, context, dc->res_pool)) { - DC_ERROR("Failed to attach surface to stream!\n"); - return DC_FAIL_ATTACH_SURFACES; - } + result = resource_map_phy_clock_resources(dc, new_ctx, dc_stream); - if (result == DC_OK) - result = build_mapped_resource(dc, context, old_context); if (result == DC_OK) - result = resource_build_scaling_params_for_context(dc, context); - - if (result == DC_OK) - if (!dce112_validate_bandwidth(dc, context)) - result = DC_FAIL_BANDWIDTH_VALIDATE; + result = build_mapped_resource(dc, new_ctx, dc_stream); return result; } @@ -958,13 +905,13 @@ enum dc_status dce112_validate_guaranteed( dc_stream_retain(context->streams[0]); context->stream_count++; - result = resource_map_pool_resources(dc, context, NULL); + result = resource_map_pool_resources(dc, context, stream); if (result == DC_OK) - result = resource_map_phy_clock_resources(dc, context, NULL); + result = resource_map_phy_clock_resources(dc, context, stream); if (result == DC_OK) - result = build_mapped_resource(dc, context, NULL); + result = build_mapped_resource(dc, context, stream); if (result == DC_OK) { validate_guaranteed_copy_streams( @@ -979,6 +926,19 @@ enum dc_status dce112_validate_guaranteed( return result; } +enum dc_status dce112_validate_global( + struct dc *dc, + const struct dc_validation_set set[], + int set_count, + struct validate_context *old_context, + struct validate_context *context) +{ + if (!dce112_validate_surface_sets(set, set_count)) + return DC_FAIL_SURFACE_VALIDATE; + + return DC_OK; +} + static void dce112_destroy_resource_pool(struct resource_pool **pool) { struct dce110_resource_pool *dce110_pool = TO_DCE110_RES_POOL(*pool); @@ -991,10 +951,11 @@ static void dce112_destroy_resource_pool(struct resource_pool **pool) static const struct resource_funcs dce112_res_pool_funcs = { .destroy = dce112_destroy_resource_pool, .link_enc_create = dce112_link_encoder_create, - .validate_with_context = dce112_validate_with_context, .validate_guaranteed = dce112_validate_guaranteed, .validate_bandwidth = dce112_validate_bandwidth, - .validate_plane = dce100_validate_plane + .validate_plane = dce100_validate_plane, + .add_stream_to_ctx = dce112_add_stream_to_ctx, + .validate_global = dce112_validate_global }; static void bw_calcs_data_update_from_pplib(struct dc *dc) diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h index 69f8f689196d..f1834bfe3d1e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h @@ -51,6 +51,11 @@ bool dce112_validate_bandwidth( struct dc *dc, struct validate_context *context); +enum dc_status dce112_add_stream_to_ctx( + struct dc *dc, + struct validate_context *new_ctx, + struct dc_stream_state *dc_stream); + #endif /* __DC_RESOURCE_DCE112_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index b8fcdff40db3..e5d2d98982f7 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -698,10 +698,10 @@ static void dce120_destroy_resource_pool(struct resource_pool **pool) static const struct resource_funcs dce120_res_pool_funcs = { .destroy = dce120_destroy_resource_pool, .link_enc_create = dce120_link_encoder_create, - .validate_with_context = dce112_validate_with_context, .validate_guaranteed = dce112_validate_guaranteed, .validate_bandwidth = dce112_validate_bandwidth, - .validate_plane = dce100_validate_plane + .validate_plane = dce100_validate_plane, + .add_stream_to_ctx = dce112_add_stream_to_ctx }; static void bw_calcs_data_update_from_pplib(struct dc *dc) diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 838bfdaee009..ac3f42a44030 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -686,35 +686,20 @@ static void destruct(struct dce110_resource_pool *pool) static enum dc_status build_mapped_resource( const struct dc *dc, struct validate_context *context, - struct validate_context *old_context) + struct dc_stream_state *stream) { enum dc_status status = DC_OK; - uint8_t i, j; + struct pipe_ctx *pipe_ctx = resource_get_head_pipe_for_stream(&context->res_ctx, stream); - for (i = 0; i < context->stream_count; i++) { - struct dc_stream_state *stream = context->streams[i]; + if (!pipe_ctx) + return DC_ERROR_UNEXPECTED; - if (old_context && resource_is_stream_unchanged(old_context, stream)) - continue; - - for (j = 0; j < MAX_PIPES; j++) { - struct pipe_ctx *pipe_ctx = - &context->res_ctx.pipe_ctx[j]; - - if (context->res_ctx.pipe_ctx[j].stream != stream) - continue; - - status = dce110_resource_build_pipe_hw_param(pipe_ctx); + status = dce110_resource_build_pipe_hw_param(pipe_ctx); - if (status != DC_OK) - return status; + if (status != DC_OK) + return status; - resource_build_info_frame(pipe_ctx); - - /* do not need to validate non root pipes */ - break; - } - } + resource_build_info_frame(pipe_ctx); return DC_OK; } @@ -751,47 +736,17 @@ static bool dce80_validate_surface_sets( return true; } -enum dc_status dce80_validate_with_context( +enum dc_status dce80_validate_global( struct dc *dc, const struct dc_validation_set set[], int set_count, - struct validate_context *context, - struct validate_context *old_context) + struct validate_context *old_context, + struct validate_context *context) { - struct dc_context *dc_ctx = dc->ctx; - enum dc_status result = DC_ERROR_UNEXPECTED; - int i; - if (!dce80_validate_surface_sets(set, set_count)) return DC_FAIL_SURFACE_VALIDATE; - for (i = 0; i < set_count; i++) { - context->streams[i] = set[i].stream; - dc_stream_retain(context->streams[i]); - context->stream_count++; - } - - result = resource_map_pool_resources(dc, context, old_context); - - if (result == DC_OK) - result = resource_map_clock_resources(dc, context, old_context); - - if (!resource_validate_attach_surfaces(set, set_count, - old_context, context, dc->res_pool)) { - DC_ERROR("Failed to attach surface to stream!\n"); - return DC_FAIL_ATTACH_SURFACES; - } - - if (result == DC_OK) - result = build_mapped_resource(dc, context, old_context); - - if (result == DC_OK) - result = resource_build_scaling_params_for_context(dc, context); - - if (result == DC_OK) - result = dce80_validate_bandwidth(dc, context); - - return result; + return DC_OK; } enum dc_status dce80_validate_guaranteed( @@ -805,13 +760,13 @@ enum dc_status dce80_validate_guaranteed( dc_stream_retain(context->streams[0]); context->stream_count++; - result = resource_map_pool_resources(dc, context, NULL); + result = resource_map_pool_resources(dc, context, dc_stream); if (result == DC_OK) - result = resource_map_clock_resources(dc, context, NULL); + result = resource_map_clock_resources(dc, context, dc_stream); if (result == DC_OK) - result = build_mapped_resource(dc, context, NULL); + result = build_mapped_resource(dc, context, dc_stream); if (result == DC_OK) { validate_guaranteed_copy_streams( @@ -837,10 +792,10 @@ static void dce80_destroy_resource_pool(struct resource_pool **pool) static const struct resource_funcs dce80_res_pool_funcs = { .destroy = dce80_destroy_resource_pool, .link_enc_create = dce80_link_encoder_create, - .validate_with_context = dce80_validate_with_context, .validate_guaranteed = dce80_validate_guaranteed, .validate_bandwidth = dce80_validate_bandwidth, - .validate_plane = dce100_validate_plane + .validate_plane = dce100_validate_plane, + .validate_global = dce80_validate_global }; static bool dce80_construct( diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 954c234090db..ee43cbc70c8a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -48,6 +48,7 @@ #include "dce/dce_hwseq.h" #include "../virtual/virtual_stream_encoder.h" #include "dce110/dce110_resource.h" +#include "dce112/dce112_resource.h" #include "vega10/soc15ip.h" @@ -840,17 +841,15 @@ static enum dc_status build_pipe_hw_param(struct pipe_ctx *pipe_ctx) static enum dc_status build_mapped_resource( const struct dc *dc, struct validate_context *context, - struct validate_context *old_context) + struct dc_stream_state *stream) { enum dc_status status = DC_OK; - uint8_t i, j; - - for (i = 0; i < context->stream_count; i++) { - struct dc_stream_state *stream = context->streams[i]; + struct pipe_ctx *pipe_ctx = resource_get_head_pipe_for_stream(&context->res_ctx, stream); - if (old_context && resource_is_stream_unchanged(old_context, stream)) { + /*TODO Seems unneeded anymore */ + /* if (old_context && resource_is_stream_unchanged(old_context, stream)) { if (stream != NULL && old_context->streams[i] != NULL) { - /* todo: shouldn't have to copy missing parameter here */ + todo: shouldn't have to copy missing parameter here resource_build_bit_depth_reduction_params(stream, &stream->bit_depth_params); stream->clamping.pixel_encoding = @@ -863,68 +862,34 @@ static enum dc_status build_mapped_resource( continue; } } + */ - for (j = 0; j < dc->res_pool->pipe_count ; j++) { - struct pipe_ctx *pipe_ctx = - &context->res_ctx.pipe_ctx[j]; + if (!pipe_ctx) + return DC_ERROR_UNEXPECTED; - if (context->res_ctx.pipe_ctx[j].stream != stream) - continue; + status = build_pipe_hw_param(pipe_ctx); - status = build_pipe_hw_param(pipe_ctx); - - if (status != DC_OK) - return status; - - /* do not need to validate non root pipes */ - break; - } - } + if (status != DC_OK) + return status; return DC_OK; } -enum dc_status dcn10_validate_with_context( +enum dc_status dcn10_add_stream_to_ctx( struct dc *dc, - const struct dc_validation_set set[], - int set_count, - struct validate_context *context, - struct validate_context *old_context) + struct validate_context *new_ctx, + struct dc_stream_state *dc_stream) { - enum dc_status result = DC_OK; - int i; - - if (set_count == 0) - return result; - - for (i = 0; i < set_count; i++) { - context->streams[i] = set[i].stream; - dc_stream_retain(context->streams[i]); - context->stream_count++; - } - - result = resource_map_pool_resources(dc, context, old_context); - if (result != DC_OK) - return result; - - result = resource_map_phy_clock_resources(dc, context, old_context); - if (result != DC_OK) - return result; + enum dc_status result = DC_ERROR_UNEXPECTED; - result = build_mapped_resource(dc, context, old_context); - if (result != DC_OK) - return result; + result = resource_map_pool_resources(dc, new_ctx, dc_stream); - if (!resource_validate_attach_surfaces(set, set_count, - old_context, context, dc->res_pool)) - return DC_FAIL_ATTACH_SURFACES; + if (result == DC_OK) + result = resource_map_phy_clock_resources(dc, new_ctx, dc_stream); - result = resource_build_scaling_params_for_context(dc, context); - if (result != DC_OK) - return result; - if (!dcn_validate_bandwidth(dc, context)) - return DC_FAIL_BANDWIDTH_VALIDATE; + if (result == DC_OK) + result = build_mapped_resource(dc, new_ctx, dc_stream); return result; } @@ -940,13 +905,13 @@ enum dc_status dcn10_validate_guaranteed( dc_stream_retain(context->streams[0]); context->stream_count++; - result = resource_map_pool_resources(dc, context, NULL); + result = resource_map_pool_resources(dc, context, dc_stream); if (result == DC_OK) - result = resource_map_phy_clock_resources(dc, context, NULL); + result = resource_map_phy_clock_resources(dc, context, dc_stream); if (result == DC_OK) - result = build_mapped_resource(dc, context, NULL); + result = build_mapped_resource(dc, context, dc_stream); if (result == DC_OK) { validate_guaranteed_copy_streams( @@ -1226,10 +1191,10 @@ static struct dc_cap_funcs cap_funcs = { static struct resource_funcs dcn10_res_pool_funcs = { .destroy = dcn10_destroy_resource_pool, .link_enc_create = dcn10_link_encoder_create, - .validate_with_context = dcn10_validate_with_context, .validate_guaranteed = dcn10_validate_guaranteed, .validate_bandwidth = dcn_validate_bandwidth, .acquire_idle_pipe_for_layer = dcn10_acquire_idle_pipe_for_layer, + .add_stream_to_ctx = dcn10_add_stream_to_ctx }; static bool construct( diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index a3f0039088ab..9a3239028377 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -87,12 +87,6 @@ struct resource_funcs { void (*destroy)(struct resource_pool **pool); struct link_encoder *(*link_enc_create)( const struct encoder_init_data *init); - enum dc_status (*validate_with_context)( - struct dc *dc, - const struct dc_validation_set set[], - int set_count, - struct validate_context *context, - struct validate_context *old_context); enum dc_status (*validate_guaranteed)( struct dc *dc, @@ -103,11 +97,24 @@ struct resource_funcs { struct dc *dc, struct validate_context *context); + enum dc_status (*validate_global)( + struct dc *dc, + const struct dc_validation_set set[], + int set_count, + struct validate_context *old_context, + struct validate_context *context); + struct pipe_ctx *(*acquire_idle_pipe_for_layer)( struct validate_context *context, const struct resource_pool *pool, struct dc_stream_state *stream); + enum dc_status (*validate_plane)(const struct dc_plane_state *plane_state); + + enum dc_status (*add_stream_to_ctx)( + struct dc *dc, + struct validate_context *new_ctx, + struct dc_stream_state *dc_stream); }; struct audio_support{ diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index 9085ec7ceac7..ebc0f5b02365 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -82,7 +82,7 @@ void dc_destroy_resource_pool(struct dc *dc); enum dc_status resource_map_pool_resources( const struct dc *dc, struct validate_context *context, - struct validate_context *old_context); + struct dc_stream_state *stream); bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx); @@ -150,12 +150,12 @@ void resource_validate_ctx_update_pointer_after_copy( enum dc_status resource_map_clock_resources( const struct dc *dc, struct validate_context *context, - struct validate_context *old_context); + struct dc_stream_state *stream); enum dc_status resource_map_phy_clock_resources( const struct dc *dc, struct validate_context *context, - struct validate_context *old_context); + struct dc_stream_state *stream); bool pipe_need_reprogram( struct pipe_ctx *pipe_ctx_old, -- cgit From 81c90ec0348002b6f6b0c108e3e60e666cb4b673 Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Thu, 7 Sep 2017 16:46:34 -0400 Subject: drm/amd/display: Refactor dc_state creation into a function. For less repetition and easy debugging. Signed-off-by: Leo (Sunpeng) Li Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 +--- drivers/gpu/drm/amd/display/dc/core/dc.c | 19 +++++++++++++------ drivers/gpu/drm/amd/display/dc/dc.h | 1 + 3 files changed, 15 insertions(+), 9 deletions(-) (limited to 'drivers/gpu') 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 17e9bf7a2ebb..776bd4a1fecc 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -702,13 +702,11 @@ dm_atomic_state_alloc(struct drm_device *dev) goto fail; /* copy existing configuration */ - new_ctx = dm_alloc(sizeof(*new_ctx)); + new_ctx = dc_create_state(); if (!new_ctx) goto fail; - atomic_inc(&new_ctx->ref_count); - dc_resource_validate_ctx_copy_construct_current(dc, new_ctx); state->context = new_ctx; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 10126d9a7233..8a6bd2917799 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -497,15 +497,13 @@ static bool construct(struct dc *dc, goto fail; } - dc->current_context = dm_alloc(sizeof(*dc->current_context)); + dc->current_context = dc_create_state(); if (!dc->current_context) { dm_error("%s: failed to create validate ctx\n", __func__); goto fail; } - atomic_inc(&dc->current_context->ref_count); - dc_ctx->cgs_device = init_params->cgs_device; dc_ctx->driver_context = init_params->driver; dc_ctx->dc = dc; @@ -1162,6 +1160,17 @@ bool dc_commit_planes_to_stream( return true; } +struct validate_context *dc_create_state(void) +{ + struct validate_context *context = dm_alloc(sizeof(struct validate_context)); + + if (!context) + return NULL; + + atomic_inc(&context->ref_count); + return context; +} + void dc_retain_validate_context(struct validate_context *context) { ASSERT(atomic_read(&context->ref_count) > 0); @@ -1442,12 +1451,10 @@ void dc_update_planes_and_stream(struct dc *dc, new_planes[i] = srf_updates[i].surface; /* initialize scratch memory for building context */ - context = dm_alloc(sizeof(*context)); + context = dc_create_state(); if (context == NULL) goto context_alloc_fail; - atomic_inc(&context->ref_count); - dc_resource_validate_ctx_copy_construct( core_dc->current_context, context); diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 2b4fc6616243..928d2a0501eb 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -732,6 +732,7 @@ enum surface_update_type dc_check_update_surfaces_for_stream( const struct dc_stream_status *stream_status); +struct validate_context *dc_create_state(void); void dc_retain_validate_context(struct validate_context *context); void dc_release_validate_context(struct validate_context *context); -- cgit From d4d4a64574ab546811d29a21366afe6bb6cdb264 Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Thu, 21 Sep 2017 16:13:00 -0400 Subject: drm/amd/display: Move copy_construct from state_alloc to atomic_check. Previously atomic_check assumed that dc_state is allocated and filled in. This is not the case when we hit EDEADLK and have to backup and retry. We could change atomic_state_clear but that revealed some other problems. For now let's create and construct dc_state in atomic_check. Signed-off-by: Leo (Sunpeng) Li Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) (limited to 'drivers/gpu') 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 776bd4a1fecc..4bb78f76acce 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -691,9 +691,6 @@ struct drm_atomic_state * dm_atomic_state_alloc(struct drm_device *dev) { struct dm_atomic_state *state = kzalloc(sizeof(*state), GFP_KERNEL); - struct validate_context *new_ctx; - struct amdgpu_device *adev = dev->dev_private; - struct dc *dc = adev->dm.dc; if (!state) return NULL; @@ -701,16 +698,6 @@ dm_atomic_state_alloc(struct drm_device *dev) if (drm_atomic_state_init(dev, &state->base) < 0) goto fail; - /* copy existing configuration */ - new_ctx = dc_create_state(); - - if (!new_ctx) - goto fail; - - dc_resource_validate_ctx_copy_construct_current(dc, new_ctx); - - state->context = new_ctx; - return &state->base; fail: @@ -4465,6 +4452,10 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, return ret; } + dm_state->context = dc_create_state(); + ASSERT(dm_state->context); + dc_resource_validate_ctx_copy_construct_current(dc, dm_state->context); + /* copy existing configuration */ set_count = 0; list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { -- cgit From 42f8ffa1081a7bf430107587757a1e1b02dfcdf8 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Fri, 15 Sep 2017 14:07:30 -0400 Subject: drm/amd/display: Enable Vega by default. Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index add0032977f3..3c0885ed5db7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1988,16 +1988,16 @@ bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type) case CHIP_POLARIS12: case CHIP_TONGA: case CHIP_FIJI: - case CHIP_VEGA10: #if defined(CONFIG_DRM_AMD_DC_PRE_VEGA) return amdgpu_dc != 0; #endif case CHIP_KABINI: case CHIP_MULLINS: return amdgpu_dc > 0; -#endif -#if defined(CONFIG_DRM_AMD_DC) && defined(CONFIG_DRM_AMD_DC_DCN1_0) + case CHIP_VEGA10: +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) case CHIP_RAVEN: +#endif return amdgpu_dc != 0; #endif default: -- cgit From 1bd4653a29a49f6fd732cd294e0f87b15feec5a8 Mon Sep 17 00:00:00 2001 From: Roman Li Date: Wed, 16 Aug 2017 19:06:49 -0400 Subject: drm/amd/display: increase polling interval for fbc status update 1.Fixing error message: "wait counter exceeded, changes to HW not applied" 2. Added "FBC status changed to 0/1" logs Signed-off-by: Roman Li Reviewed-by: Bhawanpreet Lakha Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c index 9759d8e790a3..2e97e5757fb9 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c @@ -115,7 +115,7 @@ static void wait_for_fbc_state_changed( FBC_STATUS, FBC_ENABLE_STATUS) == enabled) break; - udelay(10); + msleep(10); counter++; } @@ -124,7 +124,13 @@ static void wait_for_fbc_state_changed( cp110->base.ctx->logger, LOG_WARNING, "%s: wait counter exceeded, changes to HW not applied", __func__); + } else { + dm_logger_write( + cp110->base.ctx->logger, LOG_SYNC, + "FBC status changed to %d", enabled); } + + } void dce110_compressor_power_up_fbc(struct compressor *compressor) -- cgit From b05dee52efdcb6286a28be4dddeb450b58591c6d Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Wed, 16 Aug 2017 20:25:42 -0400 Subject: drm/amd/display: fix not enter/exit PSR with latest driver/SBIOS Signed-off-by: Charlene Liu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 2 +- drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c | 3 ++- drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c | 5 ++++- 3 files changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index d77f0de0f2bf..cab54afa1131 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1975,7 +1975,7 @@ bool dc_link_setup_psr(struct dc_link *link, #if defined(CONFIG_DRM_AMD_DC_DCN1_0) /*skip power down the single pipe since it blocks the cstate*/ if (ASIC_REV_IS_RAVEN(link->ctx->asic_id.hw_internal_rev)) - psr_context->psr_level.bits.SKIP_SINGLE_OTG_DISABLE = true; + psr_context->psr_level.bits.SKIP_SINGLE_OTG_DISABLE = false; #endif /* SMU will perform additional powerdown sequence. diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c index 9d67340a6b8b..06d9a3e7c8a2 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c @@ -417,9 +417,10 @@ static int dce112_set_clock( bp->funcs->set_dce_clock(bp, &dce_clk_params); - if (abm->funcs->is_dmcu_initialized(abm)) + if (abm->funcs->is_dmcu_initialized(abm) && clk_dce->dfs_bypass_disp_clk != actual_clock) dmcu->funcs->set_psr_wait_loop(dmcu, actual_clock / 1000 / 7); + clk_dce->dfs_bypass_disp_clk = actual_clock; return actual_clock; } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c index 92902f011418..efcdb2bf4d0d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c @@ -260,6 +260,8 @@ static void dce_psr_wait_loop( { struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); union dce_dmcu_psr_config_data_wait_loop_reg1 masterCmdData1; + if (cached_wait_loop_number == wait_loop_number) + return; /* waitDMCUReadyForCmd */ REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 1, 10000); @@ -500,7 +502,7 @@ static void dcn10_psr_wait_loop( { struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); union dce_dmcu_psr_config_data_wait_loop_reg1 masterCmdData1; - + if (wait_loop_number != 0) { /* waitDMCUReadyForCmd */ REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 1, 10000); @@ -514,6 +516,7 @@ static void dcn10_psr_wait_loop( /* notifyDMCUMsg */ REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); + } } static void dcn10_get_psr_wait_loop(unsigned int *psr_wait_loop_number) -- cgit From 214435ff1369a9d48c194c7a75d918130c53bab2 Mon Sep 17 00:00:00 2001 From: Corbin McElhanney Date: Wed, 16 Aug 2017 11:49:07 -0400 Subject: drm/amd/display: Log OTG registers with dcn10 hw state Signed-off-by: Corbin McElhanney Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 33 +++++++++++++++++ .../amd/display/dc/dcn10/dcn10_timing_generator.c | 42 ++++++++++++++++++++++ .../amd/display/dc/dcn10/dcn10_timing_generator.h | 25 +++++++++++++ 3 files changed, 100 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index f0e49d16019c..ddfa6a8d087b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -32,6 +32,7 @@ #include "dce/dce_hwseq.h" #include "abm.h" #include "dcn10/dcn10_mem_input.h" +#include "dcn10/dcn10_timing_generator.h" #include "dcn10/dcn10_dpp.h" #include "dcn10/dcn10_mpc.h" #include "timing_generator.h" @@ -200,6 +201,38 @@ static void dcn10_log_hw_state(struct dc *dc) } DTN_INFO("\n"); + DTN_INFO("OTG:\t v_bs \t v_be \t v_ss \t v_se \t vpol \t vmax \t vmin \t " + "h_bs \t h_be \t h_ss \t h_se \t hpol \t htot \t vtot \t underflow\n"); + + for (i = 0; i < pool->pipe_count; i++) { + struct timing_generator *tg = pool->timing_generators[i]; + struct dcn_otg_state s; + + tgn10_read_otg_state(DCN10TG_FROM_TG(tg), &s); + + DTN_INFO("[%d]:\t %d \t %d \t %d \t %d \t " + "%d \t %d \t %d \t %d \t %d \t %d \t " + "%d \t %d \t %d \t %d \t %d \t ", + i, + s.v_blank_start, + s.v_blank_end, + s.v_sync_a_start, + s.v_sync_a_end, + s.v_sync_a_pol, + s.v_total_max, + s.v_total_min, + s.h_blank_start, + s.h_blank_end, + s.h_sync_a_start, + s.h_sync_a_end, + s.h_sync_a_pol, + s.h_total, + s.v_total, + s.underflow_occurred_status); + DTN_INFO("\n"); + } + DTN_INFO("\n"); + log_mpc_crc(dc); DTN_INFO_END(); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c index 941e0125ff06..6a5f2683c2e5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c @@ -1090,6 +1090,48 @@ static bool tgn10_is_stereo_left_eye(struct timing_generator *tg) return ret; } +void tgn10_read_otg_state(struct dcn10_timing_generator *tgn10, + struct dcn_otg_state *s) +{ + REG_GET_2(OTG_V_BLANK_START_END, + OTG_V_BLANK_START, &s->v_blank_start, + OTG_V_BLANK_END, &s->v_blank_end); + + REG_GET(OTG_V_SYNC_A_CNTL, + OTG_V_SYNC_A_POL, &s->v_sync_a_pol); + + REG_GET(OTG_V_TOTAL, + OTG_V_TOTAL, &s->v_total); + + REG_GET(OTG_V_TOTAL_MAX, + OTG_V_TOTAL_MAX, &s->v_total_max); + + REG_GET(OTG_V_TOTAL_MIN, + OTG_V_TOTAL_MIN, &s->v_total_min); + + REG_GET_2(OTG_V_SYNC_A, + OTG_V_SYNC_A_START, &s->v_sync_a_start, + OTG_V_SYNC_A_END, &s->v_sync_a_end); + + REG_GET_2(OTG_H_BLANK_START_END, + OTG_H_BLANK_START, &s->h_blank_start, + OTG_H_BLANK_END, &s->h_blank_end); + + REG_GET_2(OTG_H_SYNC_A, + OTG_H_SYNC_A_START, &s->h_sync_a_start, + OTG_H_SYNC_A_END, &s->h_sync_a_end); + + REG_GET(OTG_H_SYNC_A_CNTL, + OTG_H_SYNC_A_POL, &s->h_sync_a_pol); + + REG_GET(OTG_H_TOTAL, + OTG_H_TOTAL, &s->h_total); + + REG_GET(OPTC_INPUT_GLOBAL_CONTROL, + OPTC_UNDERFLOW_OCCURRED_STATUS, &s->underflow_occurred_status); +} + + static struct timing_generator_funcs dcn10_tg_funcs = { .validate_timing = tgn10_validate_timing, .program_timing = tgn10_program_timing, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h index 747e8211e507..654889318fc1 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h @@ -67,6 +67,7 @@ SRI(OTG_CLOCK_CONTROL, OTG, inst),\ SRI(OPTC_INPUT_CLOCK_CONTROL, ODM, inst),\ SRI(OPTC_DATA_SOURCE_SELECT, ODM, inst),\ + SRI(OPTC_INPUT_GLOBAL_CONTROL, ODM, inst),\ SRI(OPPBUF_CONTROL, OPPBUF, inst),\ SRI(OPPBUF_3D_PARAMETERS_0, OPPBUF, inst),\ SRI(CONTROL, VTG, inst),\ @@ -121,6 +122,7 @@ struct dcn_tg_registers { uint32_t OTG_CLOCK_CONTROL; uint32_t OPTC_INPUT_CLOCK_CONTROL; uint32_t OPTC_DATA_SOURCE_SELECT; + uint32_t OPTC_INPUT_GLOBAL_CONTROL; uint32_t OPPBUF_CONTROL; uint32_t OPPBUF_3D_PARAMETERS_0; uint32_t CONTROL; @@ -204,6 +206,7 @@ struct dcn_tg_registers { SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_EN, mask_sh),\ SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_ON, mask_sh),\ SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_GATE_DIS, mask_sh),\ + SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_OCCURRED_STATUS, mask_sh),\ SF(OPPBUF0_OPPBUF_CONTROL, OPPBUF_ACTIVE_WIDTH, mask_sh),\ SF(OPPBUF0_OPPBUF_3D_PARAMETERS_0, OPPBUF_3D_VACT_SPACE1_SIZE, mask_sh),\ SF(VTG0_CONTROL, VTG0_ENABLE, mask_sh),\ @@ -310,6 +313,7 @@ struct dcn_tg_registers { type OPTC_INPUT_CLK_GATE_DIS;\ type OPTC_SRC_SEL;\ type OPTC_SEG0_SRC_SEL;\ + type OPTC_UNDERFLOW_OCCURRED_STATUS;\ type OPPBUF_ACTIVE_WIDTH;\ type OPPBUF_3D_VACT_SPACE1_SIZE;\ type VTG0_ENABLE;\ @@ -346,4 +350,25 @@ struct dcn10_timing_generator { void dcn10_timing_generator_init(struct dcn10_timing_generator *tg); +struct dcn_otg_state { + uint32_t v_blank_start; + uint32_t v_blank_end; + uint32_t v_sync_a_pol; + uint32_t v_total; + uint32_t v_total_max; + uint32_t v_total_min; + uint32_t v_sync_a_start; + uint32_t v_sync_a_end; + uint32_t h_blank_start; + uint32_t h_blank_end; + uint32_t h_sync_a_start; + uint32_t h_sync_a_end; + uint32_t h_sync_a_pol; + uint32_t h_total; + uint32_t underflow_occurred_status; +}; + +void tgn10_read_otg_state(struct dcn10_timing_generator *tgn10, + struct dcn_otg_state *s); + #endif /* __DC_TIMING_GENERATOR_DCN10_H__ */ -- cgit From 57d972d4927581d027007c92b57b843c186128d4 Mon Sep 17 00:00:00 2001 From: Roman Li Date: Thu, 17 Aug 2017 16:14:45 -0400 Subject: drm/amd/display: Fix FBC disable for stereo Removed FBC disable from dc_enable_stereo(). It should be implemented in stereo_setup callback, which is not implemented yet. Otherwise it always disable FBC regardless if stereo supported or not. Signed-off-by: Roman Li Reviewed-by: Bhawanpreet Lakha Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 8a6bd2917799..035c44e0e7d2 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -881,10 +881,6 @@ bool dc_enable_stereo( struct pipe_ctx *pipe; struct dc *core_dc = dc; -#ifdef ENABLE_FBC - struct compressor *fbc_compressor = core_dc->fbc_compressor; -#endif - for (i = 0; i < MAX_PIPES; i++) { if (context != NULL) pipe = &context->res_ctx.pipe_ctx[i]; @@ -897,13 +893,6 @@ bool dc_enable_stereo( } } -#ifdef ENABLE_FBC - if (fbc_compressor != NULL && - fbc_compressor->funcs->is_fbc_enabled_in_hw(core_dc->fbc_compressor, - NULL)) - fbc_compressor->funcs->disable_fbc(fbc_compressor); - -#endif return ret; } -- cgit From 5e9a81b2c465557adbaeef7231834e3ab40e4102 Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Tue, 15 Aug 2017 17:44:19 -0400 Subject: drm/amd/display: separate scl functions out from dcn10_dpp Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/Makefile | 3 +- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c | 650 +----------------- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h | 5 + .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c | 762 +++++++++++++++++++++ 4 files changed, 770 insertions(+), 650 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile index 8af201a51a2a..83619e6b8a05 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile @@ -3,7 +3,8 @@ DCN10 = dcn10_resource.o dcn10_ipp.o dcn10_hw_sequencer.o \ dcn10_dpp.o dcn10_opp.o dcn10_timing_generator.o \ - dcn10_mem_input.o dcn10_mpc.o dcn10_dwb.o + dcn10_mem_input.o dcn10_mpc.o dcn10_dwb.o \ + dcn10_dpp_dscl.o AMD_DAL_DCN10 = $(addprefix $(AMDDALPATH)/dc/dcn10/,$(DCN10)) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c index e52e1f43f67b..a841ed36c217 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c @@ -112,514 +112,6 @@ enum gamut_remap_select { GAMUT_REMAP_COMB_COEFF }; -static void dpp_set_overscan( - struct dcn10_dpp *xfm, - const struct scaler_data *data) -{ - uint32_t left = data->recout.x; - uint32_t top = data->recout.y; - - int right = data->h_active - data->recout.x - data->recout.width; - int bottom = data->v_active - data->recout.y - data->recout.height; - - if (right < 0) { - BREAK_TO_DEBUGGER(); - right = 0; - } - if (bottom < 0) { - BREAK_TO_DEBUGGER(); - bottom = 0; - } - - REG_SET_2(DSCL_EXT_OVERSCAN_LEFT_RIGHT, 0, - EXT_OVERSCAN_LEFT, left, - EXT_OVERSCAN_RIGHT, right); - - REG_SET_2(DSCL_EXT_OVERSCAN_TOP_BOTTOM, 0, - EXT_OVERSCAN_BOTTOM, bottom, - EXT_OVERSCAN_TOP, top); -} - -static void dpp_set_otg_blank( - struct dcn10_dpp *xfm, const struct scaler_data *data) -{ - uint32_t h_blank_start = data->h_active; - uint32_t h_blank_end = 0; - uint32_t v_blank_start = data->v_active; - uint32_t v_blank_end = 0; - - REG_SET_2(OTG_H_BLANK, 0, - OTG_H_BLANK_START, h_blank_start, - OTG_H_BLANK_END, h_blank_end); - - REG_SET_2(OTG_V_BLANK, 0, - OTG_V_BLANK_START, v_blank_start, - OTG_V_BLANK_END, v_blank_end); -} - -static enum dscl_mode_sel get_dscl_mode( - const struct scaler_data *data, bool dbg_always_scale) -{ - const long long one = dal_fixed31_32_one.value; - bool ycbcr = false; - bool format420 = false; - - if (data->format == PIXEL_FORMAT_FP16) - return DSCL_MODE_DSCL_BYPASS; - - if (data->format >= PIXEL_FORMAT_VIDEO_BEGIN - && data->format <= PIXEL_FORMAT_VIDEO_END) - ycbcr = true; - - if (data->format == PIXEL_FORMAT_420BPP8 || - data->format == PIXEL_FORMAT_420BPP10) - format420 = true; - - if (data->ratios.horz.value == one - && data->ratios.vert.value == one - && data->ratios.horz_c.value == one - && data->ratios.vert_c.value == one - && !dbg_always_scale) - return DSCL_MODE_SCALING_444_BYPASS; - - if (!format420) { - if (ycbcr) - return DSCL_MODE_SCALING_444_YCBCR_ENABLE; - else - return DSCL_MODE_SCALING_444_RGB_ENABLE; - } - if (data->ratios.horz.value == one && data->ratios.vert.value == one) - return DSCL_MODE_SCALING_420_LUMA_BYPASS; - if (data->ratios.horz_c.value == one && data->ratios.vert_c.value == one) - return DSCL_MODE_SCALING_420_CHROMA_BYPASS; - - return DSCL_MODE_SCALING_420_YCBCR_ENABLE; -} - -static int get_pixel_depth_val(enum lb_pixel_depth depth) -{ - if (depth == LB_PIXEL_DEPTH_30BPP) - return 0; /* 10 bpc */ - else if (depth == LB_PIXEL_DEPTH_24BPP) - return 1; /* 8 bpc */ - else if (depth == LB_PIXEL_DEPTH_18BPP) - return 2; /* 6 bpc */ - else if (depth == LB_PIXEL_DEPTH_36BPP) - return 3; /* 12 bpc */ - else { - ASSERT(0); - return -1; /* Unsupported */ - } -} - -static void dpp_set_lb( - struct dcn10_dpp *xfm, - const struct line_buffer_params *lb_params, - enum lb_memory_config mem_size_config) -{ - uint32_t pixel_depth = get_pixel_depth_val(lb_params->depth); - uint32_t dyn_pix_depth = lb_params->dynamic_pixel_depth; - REG_SET_7(LB_DATA_FORMAT, 0, - PIXEL_DEPTH, pixel_depth, /* Pixel depth stored in LB */ - PIXEL_EXPAN_MODE, lb_params->pixel_expan_mode, /* Pixel expansion mode */ - PIXEL_REDUCE_MODE, 1, /* Pixel reduction mode: Rounding */ - DYNAMIC_PIXEL_DEPTH, dyn_pix_depth, /* Dynamic expansion pixel depth */ - DITHER_EN, 0, /* Dithering enable: Disabled */ - INTERLEAVE_EN, lb_params->interleave_en, /* Interleave source enable */ - ALPHA_EN, lb_params->alpha_en); /* Alpha enable */ - - REG_SET_2(LB_MEMORY_CTRL, 0, - MEMORY_CONFIG, mem_size_config, - LB_MAX_PARTITIONS, 63); -} - -static void dpp_set_scaler_filter( - struct dcn10_dpp *xfm, - uint32_t taps, - enum dcn10_coef_filter_type_sel filter_type, - const uint16_t *filter) -{ - const int tap_pairs = (taps + 1) / 2; - int phase; - int pair; - uint16_t odd_coef, even_coef; - - REG_SET_3(SCL_COEF_RAM_TAP_SELECT, 0, - SCL_COEF_RAM_TAP_PAIR_IDX, 0, - SCL_COEF_RAM_PHASE, 0, - SCL_COEF_RAM_FILTER_TYPE, filter_type); - - for (phase = 0; phase < (NUM_PHASES / 2 + 1); phase++) { - for (pair = 0; pair < tap_pairs; pair++) { - even_coef = filter[phase * taps + 2 * pair]; - if ((pair * 2 + 1) < taps) - odd_coef = filter[phase * taps + 2 * pair + 1]; - else - odd_coef = 0; - - REG_SET_4(SCL_COEF_RAM_TAP_DATA, 0, - /* Even tap coefficient (bits 1:0 fixed to 0) */ - SCL_COEF_RAM_EVEN_TAP_COEF, even_coef, - /* Write/read control for even coefficient */ - SCL_COEF_RAM_EVEN_TAP_COEF_EN, 1, - /* Odd tap coefficient (bits 1:0 fixed to 0) */ - SCL_COEF_RAM_ODD_TAP_COEF, odd_coef, - /* Write/read control for odd coefficient */ - SCL_COEF_RAM_ODD_TAP_COEF_EN, 1); - } - } - -} - -#if 0 -bool dpp_set_pixel_storage_depth( - struct dpp *xfm, - enum lb_pixel_depth depth, - const struct bit_depth_reduction_params *bit_depth_params) -{ - struct dcn10_dpp *xfm110 = TO_DCN10_DPP(xfm); - bool ret = true; - uint32_t value; - enum dc_color_depth color_depth; - - value = dm_read_reg(xfm->ctx, LB_REG(mmLB_DATA_FORMAT)); - switch (depth) { - case LB_PIXEL_DEPTH_18BPP: - color_depth = COLOR_DEPTH_666; - set_reg_field_value(value, 2, LB_DATA_FORMAT, PIXEL_DEPTH); - set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_EXPAN_MODE); - break; - case LB_PIXEL_DEPTH_24BPP: - color_depth = COLOR_DEPTH_888; - set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_DEPTH); - set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_EXPAN_MODE); - break; - case LB_PIXEL_DEPTH_30BPP: - color_depth = COLOR_DEPTH_101010; - set_reg_field_value(value, 0, LB_DATA_FORMAT, PIXEL_DEPTH); - set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_EXPAN_MODE); - break; - case LB_PIXEL_DEPTH_36BPP: - color_depth = COLOR_DEPTH_121212; - set_reg_field_value(value, 3, LB_DATA_FORMAT, PIXEL_DEPTH); - set_reg_field_value(value, 0, LB_DATA_FORMAT, PIXEL_EXPAN_MODE); - break; - default: - ret = false; - break; - } - - if (ret == true) { - set_denormalization(xfm110, color_depth); - ret = program_bit_depth_reduction(xfm110, color_depth, - bit_depth_params); - - set_reg_field_value(value, 0, LB_DATA_FORMAT, ALPHA_EN); - dm_write_reg(xfm->ctx, LB_REG(mmLB_DATA_FORMAT), value); - if (!(xfm110->lb_pixel_depth_supported & depth)) { - /* We should use unsupported capabilities - * unless it is required by w/a - */ - dm_logger_write(xfm->ctx->logger, LOG_WARNING, - "%s: Capability not supported", - __func__); - } - } - - return ret; -} -#endif - -static const uint16_t *get_filter_coeffs_64p(int taps, struct fixed31_32 ratio) -{ - if (taps == 8) - return get_filter_8tap_64p(ratio); - else if (taps == 7) - return get_filter_7tap_64p(ratio); - else if (taps == 6) - return get_filter_6tap_64p(ratio); - else if (taps == 5) - return get_filter_5tap_64p(ratio); - else if (taps == 4) - return get_filter_4tap_64p(ratio); - else if (taps == 3) - return get_filter_3tap_64p(ratio); - else if (taps == 2) - return filter_2tap_64p; - else if (taps == 1) - return NULL; - else { - /* should never happen, bug */ - BREAK_TO_DEBUGGER(); - return NULL; - } -} - -static void dpp_set_scl_filter( - struct dcn10_dpp *xfm, - const struct scaler_data *scl_data, - bool chroma_coef_mode) -{ - bool h_2tap_hardcode_coef_en = false; - bool v_2tap_hardcode_coef_en = false; - bool h_2tap_sharp_en = false; - bool v_2tap_sharp_en = false; - uint32_t h_2tap_sharp_factor = scl_data->sharpness.horz; - uint32_t v_2tap_sharp_factor = scl_data->sharpness.vert; - bool coef_ram_current; - const uint16_t *filter_h = NULL; - const uint16_t *filter_v = NULL; - const uint16_t *filter_h_c = NULL; - const uint16_t *filter_v_c = NULL; - - h_2tap_hardcode_coef_en = scl_data->taps.h_taps < 3 - && scl_data->taps.h_taps_c < 3 - && (scl_data->taps.h_taps > 1 || scl_data->taps.h_taps_c > 1); - v_2tap_hardcode_coef_en = scl_data->taps.v_taps < 3 - && scl_data->taps.v_taps_c < 3 - && (scl_data->taps.v_taps > 1 || scl_data->taps.v_taps_c > 1); - - h_2tap_sharp_en = h_2tap_hardcode_coef_en && h_2tap_sharp_factor != 0; - v_2tap_sharp_en = v_2tap_hardcode_coef_en && v_2tap_sharp_factor != 0; - - REG_UPDATE_6(DSCL_2TAP_CONTROL, - SCL_H_2TAP_HARDCODE_COEF_EN, h_2tap_hardcode_coef_en, - SCL_H_2TAP_SHARP_EN, h_2tap_sharp_en, - SCL_H_2TAP_SHARP_FACTOR, h_2tap_sharp_factor, - SCL_V_2TAP_HARDCODE_COEF_EN, v_2tap_hardcode_coef_en, - SCL_V_2TAP_SHARP_EN, v_2tap_sharp_en, - SCL_V_2TAP_SHARP_FACTOR, v_2tap_sharp_factor); - - if (!v_2tap_hardcode_coef_en || !h_2tap_hardcode_coef_en) { - bool filter_updated = false; - - filter_h = get_filter_coeffs_64p( - scl_data->taps.h_taps, scl_data->ratios.horz); - filter_v = get_filter_coeffs_64p( - scl_data->taps.v_taps, scl_data->ratios.vert); - - filter_updated = (filter_h && (filter_h != xfm->filter_h)) - || (filter_v && (filter_v != xfm->filter_v)); - - if (chroma_coef_mode) { - filter_h_c = get_filter_coeffs_64p( - scl_data->taps.h_taps_c, scl_data->ratios.horz_c); - filter_v_c = get_filter_coeffs_64p( - scl_data->taps.v_taps_c, scl_data->ratios.vert_c); - filter_updated = filter_updated || (filter_h_c && (filter_h_c != xfm->filter_h_c)) - || (filter_v_c && (filter_v_c != xfm->filter_v_c)); - } - - if (filter_updated) { - uint32_t scl_mode = REG_READ(SCL_MODE); - - if (!h_2tap_hardcode_coef_en && filter_h) { - dpp_set_scaler_filter( - xfm, scl_data->taps.h_taps, - SCL_COEF_LUMA_HORZ_FILTER, filter_h); - } - xfm->filter_h = filter_h; - if (!v_2tap_hardcode_coef_en && filter_v) { - dpp_set_scaler_filter( - xfm, scl_data->taps.v_taps, - SCL_COEF_LUMA_VERT_FILTER, filter_v); - } - xfm->filter_v = filter_v; - if (chroma_coef_mode) { - if (!h_2tap_hardcode_coef_en && filter_h_c) { - dpp_set_scaler_filter( - xfm, scl_data->taps.h_taps_c, - SCL_COEF_CHROMA_HORZ_FILTER, filter_h_c); - } - if (!v_2tap_hardcode_coef_en && filter_v_c) { - dpp_set_scaler_filter( - xfm, scl_data->taps.v_taps_c, - SCL_COEF_CHROMA_VERT_FILTER, filter_v_c); - } - } - xfm->filter_h_c = filter_h_c; - xfm->filter_v_c = filter_v_c; - - coef_ram_current = get_reg_field_value_ex( - scl_mode, xfm->tf_mask->SCL_COEF_RAM_SELECT_CURRENT, - xfm->tf_shift->SCL_COEF_RAM_SELECT_CURRENT); - - /* Swap coefficient RAM and set chroma coefficient mode */ - REG_SET_2(SCL_MODE, scl_mode, - SCL_COEF_RAM_SELECT, !coef_ram_current, - SCL_CHROMA_COEF_MODE, chroma_coef_mode); - } - } -} - - -static int get_lb_depth_bpc(enum lb_pixel_depth depth) -{ - if (depth == LB_PIXEL_DEPTH_30BPP) - return 10; - else if (depth == LB_PIXEL_DEPTH_24BPP) - return 8; - else if (depth == LB_PIXEL_DEPTH_18BPP) - return 6; - else if (depth == LB_PIXEL_DEPTH_36BPP) - return 12; - else { - BREAK_TO_DEBUGGER(); - return -1; /* Unsupported */ - } -} - -static void calc_lb_num_partitions( - const struct scaler_data *scl_data, - enum lb_memory_config lb_config, - int *num_part_y, - int *num_part_c) -{ - int line_size = scl_data->viewport.width < scl_data->recout.width ? - scl_data->viewport.width : scl_data->recout.width; - int line_size_c = scl_data->viewport_c.width < scl_data->recout.width ? - scl_data->viewport_c.width : scl_data->recout.width; - int lb_bpc = get_lb_depth_bpc(scl_data->lb_params.depth); - int memory_line_size_y = (line_size * lb_bpc + 71) / 72; /* +71 to ceil */ - int memory_line_size_c = (line_size_c * lb_bpc + 71) / 72; /* +71 to ceil */ - int memory_line_size_a = (line_size + 5) / 6; /* +5 to ceil */ - int lb_memory_size, lb_memory_size_c, lb_memory_size_a, num_partitions_a; - - if (lb_config == LB_MEMORY_CONFIG_1) { - lb_memory_size = 816; - lb_memory_size_c = 816; - lb_memory_size_a = 984; - } else if (lb_config == LB_MEMORY_CONFIG_2) { - lb_memory_size = 1088; - lb_memory_size_c = 1088; - lb_memory_size_a = 1312; - } else if (lb_config == LB_MEMORY_CONFIG_3) { - lb_memory_size = 816 + 1088 + 848 + 848 + 848; - lb_memory_size_c = 816 + 1088; - lb_memory_size_a = 984 + 1312 + 456; - } else { - lb_memory_size = 816 + 1088 + 848; - lb_memory_size_c = 816 + 1088 + 848; - lb_memory_size_a = 984 + 1312 + 456; - } - *num_part_y = lb_memory_size / memory_line_size_y; - *num_part_c = lb_memory_size_c / memory_line_size_c; - num_partitions_a = lb_memory_size_a / memory_line_size_a; - - if (scl_data->lb_params.alpha_en - && (num_partitions_a < *num_part_y)) - *num_part_y = num_partitions_a; - - if (*num_part_y > 64) - *num_part_y = 64; - if (*num_part_c > 64) - *num_part_c = 64; - -} - -static bool is_lb_conf_valid(int ceil_vratio, int num_partitions, int vtaps) -{ - if (ceil_vratio > 2) - return vtaps <= (num_partitions - ceil_vratio + 2); - else - return vtaps <= num_partitions; -} - -/*find first match configuration which meets the min required lb size*/ -static enum lb_memory_config find_lb_memory_config(const struct scaler_data *scl_data) -{ - int num_part_y, num_part_c; - int vtaps = scl_data->taps.v_taps; - int vtaps_c = scl_data->taps.v_taps_c; - int ceil_vratio = dal_fixed31_32_ceil(scl_data->ratios.vert); - int ceil_vratio_c = dal_fixed31_32_ceil(scl_data->ratios.vert_c); - - calc_lb_num_partitions( - scl_data, LB_MEMORY_CONFIG_1, &num_part_y, &num_part_c); - - if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) - && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)) - return LB_MEMORY_CONFIG_1; - - calc_lb_num_partitions( - scl_data, LB_MEMORY_CONFIG_2, &num_part_y, &num_part_c); - - if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) - && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)) - return LB_MEMORY_CONFIG_2; - - if (scl_data->format == PIXEL_FORMAT_420BPP8 - || scl_data->format == PIXEL_FORMAT_420BPP10) { - calc_lb_num_partitions( - scl_data, LB_MEMORY_CONFIG_3, &num_part_y, &num_part_c); - - if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) - && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)) - return LB_MEMORY_CONFIG_3; - } - - calc_lb_num_partitions( - scl_data, LB_MEMORY_CONFIG_0, &num_part_y, &num_part_c); - - /*Ensure we can support the requested number of vtaps*/ - ASSERT(is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) - && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)); - - return LB_MEMORY_CONFIG_0; -} - -void dpp_set_scaler_auto_scale( - struct transform *xfm_base, - const struct scaler_data *scl_data) -{ - enum lb_memory_config lb_config; - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); - enum dscl_mode_sel dscl_mode = get_dscl_mode( - scl_data, xfm_base->ctx->dc->debug.always_scale); - bool ycbcr = scl_data->format >= PIXEL_FORMAT_VIDEO_BEGIN - && scl_data->format <= PIXEL_FORMAT_VIDEO_END; - - dpp_set_overscan(xfm, scl_data); - - dpp_set_otg_blank(xfm, scl_data); - - REG_UPDATE(SCL_MODE, DSCL_MODE, dscl_mode); - - if (dscl_mode == DSCL_MODE_DSCL_BYPASS) - return; - - lb_config = find_lb_memory_config(scl_data); - dpp_set_lb(xfm, &scl_data->lb_params, lb_config); - - if (dscl_mode == DSCL_MODE_SCALING_444_BYPASS) - return; - - /* TODO: v_min */ - REG_SET_3(DSCL_AUTOCAL, 0, - AUTOCAL_MODE, AUTOCAL_MODE_AUTOSCALE, - AUTOCAL_NUM_PIPE, 0, - AUTOCAL_PIPE_ID, 0); - - /* Black offsets */ - if (ycbcr) - REG_SET_2(SCL_BLACK_OFFSET, 0, - SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y, - SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_CBCR); - else - - REG_SET_2(SCL_BLACK_OFFSET, 0, - SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y, - SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_RGB_Y); - - REG_SET_4(SCL_TAP_CONTROL, 0, - SCL_V_NUM_TAPS, scl_data->taps.v_taps - 1, - SCL_H_NUM_TAPS, scl_data->taps.h_taps - 1, - SCL_V_NUM_TAPS_C, scl_data->taps.v_taps_c - 1, - SCL_H_NUM_TAPS_C, scl_data->taps.h_taps_c - 1); - - dpp_set_scl_filter(xfm, scl_data, ycbcr); -} - /* Program gamut remap in bypass mode */ void dpp_set_gamut_remap_bypass(struct dcn10_dpp *xfm) { @@ -628,146 +120,6 @@ void dpp_set_gamut_remap_bypass(struct dcn10_dpp *xfm) /* Gamut remap in bypass */ } -static void dpp_set_recout( - struct dcn10_dpp *xfm, const struct rect *recout) -{ - REG_SET_2(RECOUT_START, 0, - /* First pixel of RECOUT */ - RECOUT_START_X, recout->x, - /* First line of RECOUT */ - RECOUT_START_Y, recout->y); - - REG_SET_2(RECOUT_SIZE, 0, - /* Number of RECOUT horizontal pixels */ - RECOUT_WIDTH, recout->width, - /* Number of RECOUT vertical lines */ - RECOUT_HEIGHT, recout->height - - xfm->base.ctx->dc->debug.surface_visual_confirm * 4 * - (xfm->base.inst + 1)); -} - -static void dpp_set_manual_ratio_init( - struct dcn10_dpp *xfm, const struct scaler_data *data) -{ - uint32_t init_frac = 0; - uint32_t init_int = 0; - - REG_SET(SCL_HORZ_FILTER_SCALE_RATIO, 0, - SCL_H_SCALE_RATIO, dal_fixed31_32_u2d19(data->ratios.horz) << 5); - - REG_SET(SCL_VERT_FILTER_SCALE_RATIO, 0, - SCL_V_SCALE_RATIO, dal_fixed31_32_u2d19(data->ratios.vert) << 5); - - REG_SET(SCL_HORZ_FILTER_SCALE_RATIO_C, 0, - SCL_H_SCALE_RATIO_C, dal_fixed31_32_u2d19(data->ratios.horz_c) << 5); - - REG_SET(SCL_VERT_FILTER_SCALE_RATIO_C, 0, - SCL_V_SCALE_RATIO_C, dal_fixed31_32_u2d19(data->ratios.vert_c) << 5); - - /* - * 0.24 format for fraction, first five bits zeroed - */ - init_frac = dal_fixed31_32_u0d19(data->inits.h) << 5; - init_int = dal_fixed31_32_floor(data->inits.h); - REG_SET_2(SCL_HORZ_FILTER_INIT, 0, - SCL_H_INIT_FRAC, init_frac, - SCL_H_INIT_INT, init_int); - - init_frac = dal_fixed31_32_u0d19(data->inits.h_c) << 5; - init_int = dal_fixed31_32_floor(data->inits.h_c); - REG_SET_2(SCL_HORZ_FILTER_INIT_C, 0, - SCL_H_INIT_FRAC_C, init_frac, - SCL_H_INIT_INT_C, init_int); - - init_frac = dal_fixed31_32_u0d19(data->inits.v) << 5; - init_int = dal_fixed31_32_floor(data->inits.v); - REG_SET_2(SCL_VERT_FILTER_INIT, 0, - SCL_V_INIT_FRAC, init_frac, - SCL_V_INIT_INT, init_int); - - init_frac = dal_fixed31_32_u0d19(data->inits.v_bot) << 5; - init_int = dal_fixed31_32_floor(data->inits.v_bot); - REG_SET_2(SCL_VERT_FILTER_INIT_BOT, 0, - SCL_V_INIT_FRAC_BOT, init_frac, - SCL_V_INIT_INT_BOT, init_int); - - init_frac = dal_fixed31_32_u0d19(data->inits.v_c) << 5; - init_int = dal_fixed31_32_floor(data->inits.v_c); - REG_SET_2(SCL_VERT_FILTER_INIT_C, 0, - SCL_V_INIT_FRAC_C, init_frac, - SCL_V_INIT_INT_C, init_int); - - init_frac = dal_fixed31_32_u0d19(data->inits.v_c_bot) << 5; - init_int = dal_fixed31_32_floor(data->inits.v_c_bot); - REG_SET_2(SCL_VERT_FILTER_INIT_BOT_C, 0, - SCL_V_INIT_FRAC_BOT_C, init_frac, - SCL_V_INIT_INT_BOT_C, init_int); -} - -/* Main function to program scaler and line buffer in manual scaling mode */ -static void dpp_set_scaler_manual_scale( - struct transform *xfm_base, - const struct scaler_data *scl_data) -{ - enum lb_memory_config lb_config; - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); - enum dscl_mode_sel dscl_mode = get_dscl_mode( - scl_data, xfm_base->ctx->dc->debug.always_scale); - bool ycbcr = scl_data->format >= PIXEL_FORMAT_VIDEO_BEGIN - && scl_data->format <= PIXEL_FORMAT_VIDEO_END; - - /* Recout */ - dpp_set_recout(xfm, &scl_data->recout); - - /* MPC Size */ - REG_SET_2(MPC_SIZE, 0, - /* Number of horizontal pixels of MPC */ - MPC_WIDTH, scl_data->h_active, - /* Number of vertical lines of MPC */ - MPC_HEIGHT, scl_data->v_active); - - /* SCL mode */ - REG_UPDATE(SCL_MODE, DSCL_MODE, dscl_mode); - - if (dscl_mode == DSCL_MODE_DSCL_BYPASS) - return; - /* LB */ - lb_config = find_lb_memory_config(scl_data); - dpp_set_lb(xfm, &scl_data->lb_params, lb_config); - - if (dscl_mode == DSCL_MODE_SCALING_444_BYPASS) - return; - - /* Autocal off */ - REG_SET_3(DSCL_AUTOCAL, 0, - AUTOCAL_MODE, AUTOCAL_MODE_OFF, - AUTOCAL_NUM_PIPE, 0, - AUTOCAL_PIPE_ID, 0); - - /* Black offsets */ - if (ycbcr) - REG_SET_2(SCL_BLACK_OFFSET, 0, - SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y, - SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_CBCR); - else - - REG_SET_2(SCL_BLACK_OFFSET, 0, - SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y, - SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_RGB_Y); - - /* Manually calculate scale ratio and init values */ - dpp_set_manual_ratio_init(xfm, scl_data); - - /* HTaps/VTaps */ - REG_SET_4(SCL_TAP_CONTROL, 0, - SCL_V_NUM_TAPS, scl_data->taps.v_taps - 1, - SCL_H_NUM_TAPS, scl_data->taps.h_taps - 1, - SCL_V_NUM_TAPS_C, scl_data->taps.v_taps_c - 1, - SCL_H_NUM_TAPS_C, scl_data->taps.h_taps_c - 1); - - dpp_set_scl_filter(xfm, scl_data, ycbcr); -} - #define IDENTITY_RATIO(ratio) (dal_fixed31_32_u2d19(ratio) == (1 << 19)) @@ -1561,7 +913,7 @@ static void oppn10_set_regamma_mode( static struct transform_funcs dcn10_dpp_funcs = { .transform_reset = dpp_reset, - .transform_set_scaler = dpp_set_scaler_manual_scale, + .transform_set_scaler = dcn10_dpp_set_scaler_manual_scale, .transform_get_optimal_number_of_taps = dpp_get_optimal_number_of_taps, .transform_set_gamut_remap = dcn_dpp_set_gamut_remap, .opp_set_csc_adjustment = oppn10_set_output_csc_adjustment, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h index 1c9d3320064a..496df1fad8c4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h @@ -1386,6 +1386,11 @@ struct dcn10_dpp { int lb_bits_per_entry; bool is_write_to_ram_a_safe; }; + +void dcn10_dpp_set_scaler_manual_scale( + struct transform *xfm_base, + const struct scaler_data *scl_data); + bool dcn10_dpp_construct(struct dcn10_dpp *xfm110, struct dc_context *ctx, uint32_t inst, 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 new file mode 100644 index 000000000000..95f014b5e7ed --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c @@ -0,0 +1,762 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "core_types.h" + +#include "reg_helper.h" +#include "dcn10_dpp.h" +#include "basics/conversion.h" + +#define NUM_PHASES 64 +#define HORZ_MAX_TAPS 8 +#define VERT_MAX_TAPS 8 + +#define BLACK_OFFSET_RGB_Y 0x0 +#define BLACK_OFFSET_CBCR 0x8000 + +#define REG(reg)\ + xfm->tf_regs->reg + +#define CTX \ + xfm->base.ctx + +#undef FN +#define FN(reg_name, field_name) \ + xfm->tf_shift->field_name, xfm->tf_mask->field_name + +enum dcn10_coef_filter_type_sel { + SCL_COEF_LUMA_VERT_FILTER = 0, + SCL_COEF_LUMA_HORZ_FILTER = 1, + SCL_COEF_CHROMA_VERT_FILTER = 2, + SCL_COEF_CHROMA_HORZ_FILTER = 3, + SCL_COEF_ALPHA_VERT_FILTER = 4, + SCL_COEF_ALPHA_HORZ_FILTER = 5 +}; + +enum lb_memory_config { + /* Enable all 3 pieces of memory */ + LB_MEMORY_CONFIG_0 = 0, + + /* Enable only the first piece of memory */ + LB_MEMORY_CONFIG_1 = 1, + + /* Enable only the second piece of memory */ + LB_MEMORY_CONFIG_2 = 2, + + /* Only applicable in 4:2:0 mode, enable all 3 pieces of memory and the + * last piece of chroma memory used for the luma storage + */ + LB_MEMORY_CONFIG_3 = 3 +}; + +enum dscl_autocal_mode { + AUTOCAL_MODE_OFF = 0, + + /* Autocal calculate the scaling ratio and initial phase and the + * DSCL_MODE_SEL must be set to 1 + */ + AUTOCAL_MODE_AUTOSCALE = 1, + /* Autocal perform auto centering without replication and the + * DSCL_MODE_SEL must be set to 0 + */ + AUTOCAL_MODE_AUTOCENTER = 2, + /* Autocal perform auto centering and auto replication and the + * DSCL_MODE_SEL must be set to 0 + */ + AUTOCAL_MODE_AUTOREPLICATE = 3 +}; + +enum dscl_mode_sel { + DSCL_MODE_SCALING_444_BYPASS = 0, + DSCL_MODE_SCALING_444_RGB_ENABLE = 1, + DSCL_MODE_SCALING_444_YCBCR_ENABLE = 2, + DSCL_MODE_SCALING_420_YCBCR_ENABLE = 3, + DSCL_MODE_SCALING_420_LUMA_BYPASS = 4, + DSCL_MODE_SCALING_420_CHROMA_BYPASS = 5, + DSCL_MODE_DSCL_BYPASS = 6 +}; + +enum gamut_remap_select { + GAMUT_REMAP_BYPASS = 0, + GAMUT_REMAP_COEFF, + GAMUT_REMAP_COMA_COEFF, + GAMUT_REMAP_COMB_COEFF +}; + + +static void dpp_set_overscan( + struct dcn10_dpp *xfm, + const struct scaler_data *data) +{ + uint32_t left = data->recout.x; + uint32_t top = data->recout.y; + + int right = data->h_active - data->recout.x - data->recout.width; + int bottom = data->v_active - data->recout.y - data->recout.height; + + if (right < 0) { + BREAK_TO_DEBUGGER(); + right = 0; + } + if (bottom < 0) { + BREAK_TO_DEBUGGER(); + bottom = 0; + } + + REG_SET_2(DSCL_EXT_OVERSCAN_LEFT_RIGHT, 0, + EXT_OVERSCAN_LEFT, left, + EXT_OVERSCAN_RIGHT, right); + + REG_SET_2(DSCL_EXT_OVERSCAN_TOP_BOTTOM, 0, + EXT_OVERSCAN_BOTTOM, bottom, + EXT_OVERSCAN_TOP, top); +} + +static void dpp_set_otg_blank( + struct dcn10_dpp *xfm, const struct scaler_data *data) +{ + uint32_t h_blank_start = data->h_active; + uint32_t h_blank_end = 0; + uint32_t v_blank_start = data->v_active; + uint32_t v_blank_end = 0; + + REG_SET_2(OTG_H_BLANK, 0, + OTG_H_BLANK_START, h_blank_start, + OTG_H_BLANK_END, h_blank_end); + + REG_SET_2(OTG_V_BLANK, 0, + OTG_V_BLANK_START, v_blank_start, + OTG_V_BLANK_END, v_blank_end); +} + +static int get_pixel_depth_val(enum lb_pixel_depth depth) +{ + if (depth == LB_PIXEL_DEPTH_30BPP) + return 0; /* 10 bpc */ + else if (depth == LB_PIXEL_DEPTH_24BPP) + return 1; /* 8 bpc */ + else if (depth == LB_PIXEL_DEPTH_18BPP) + return 2; /* 6 bpc */ + else if (depth == LB_PIXEL_DEPTH_36BPP) + return 3; /* 12 bpc */ + else { + ASSERT(0); + return -1; /* Unsupported */ + } +} + +static enum dscl_mode_sel get_dscl_mode( + const struct scaler_data *data, bool dbg_always_scale) +{ + const long long one = dal_fixed31_32_one.value; + bool ycbcr = false; + bool format420 = false; + + if (data->format == PIXEL_FORMAT_FP16) + return DSCL_MODE_DSCL_BYPASS; + + if (data->format >= PIXEL_FORMAT_VIDEO_BEGIN + && data->format <= PIXEL_FORMAT_VIDEO_END) + ycbcr = true; + + if (data->format == PIXEL_FORMAT_420BPP8 || + data->format == PIXEL_FORMAT_420BPP10) + format420 = true; + + if (data->ratios.horz.value == one + && data->ratios.vert.value == one + && data->ratios.horz_c.value == one + && data->ratios.vert_c.value == one + && !dbg_always_scale) + return DSCL_MODE_SCALING_444_BYPASS; + + if (!format420) { + if (ycbcr) + return DSCL_MODE_SCALING_444_YCBCR_ENABLE; + else + return DSCL_MODE_SCALING_444_RGB_ENABLE; + } + if (data->ratios.horz.value == one && data->ratios.vert.value == one) + return DSCL_MODE_SCALING_420_LUMA_BYPASS; + if (data->ratios.horz_c.value == one && data->ratios.vert_c.value == one) + return DSCL_MODE_SCALING_420_CHROMA_BYPASS; + + return DSCL_MODE_SCALING_420_YCBCR_ENABLE; +} + +static void dpp_set_lb( + struct dcn10_dpp *xfm, + const struct line_buffer_params *lb_params, + enum lb_memory_config mem_size_config) +{ + uint32_t pixel_depth = get_pixel_depth_val(lb_params->depth); + uint32_t dyn_pix_depth = lb_params->dynamic_pixel_depth; + REG_SET_7(LB_DATA_FORMAT, 0, + PIXEL_DEPTH, pixel_depth, /* Pixel depth stored in LB */ + PIXEL_EXPAN_MODE, lb_params->pixel_expan_mode, /* Pixel expansion mode */ + PIXEL_REDUCE_MODE, 1, /* Pixel reduction mode: Rounding */ + DYNAMIC_PIXEL_DEPTH, dyn_pix_depth, /* Dynamic expansion pixel depth */ + DITHER_EN, 0, /* Dithering enable: Disabled */ + INTERLEAVE_EN, lb_params->interleave_en, /* Interleave source enable */ + ALPHA_EN, lb_params->alpha_en); /* Alpha enable */ + + REG_SET_2(LB_MEMORY_CTRL, 0, + MEMORY_CONFIG, mem_size_config, + LB_MAX_PARTITIONS, 63); +} + +static const uint16_t *get_filter_coeffs_64p(int taps, struct fixed31_32 ratio) +{ + if (taps == 8) + return get_filter_8tap_64p(ratio); + else if (taps == 7) + return get_filter_7tap_64p(ratio); + else if (taps == 6) + return get_filter_6tap_64p(ratio); + else if (taps == 5) + return get_filter_5tap_64p(ratio); + else if (taps == 4) + return get_filter_4tap_64p(ratio); + else if (taps == 3) + return get_filter_3tap_64p(ratio); + else if (taps == 2) + return filter_2tap_64p; + else if (taps == 1) + return NULL; + else { + /* should never happen, bug */ + BREAK_TO_DEBUGGER(); + return NULL; + } +} + +static void dpp_set_scaler_filter( + struct dcn10_dpp *xfm, + uint32_t taps, + enum dcn10_coef_filter_type_sel filter_type, + const uint16_t *filter) +{ + const int tap_pairs = (taps + 1) / 2; + int phase; + int pair; + uint16_t odd_coef, even_coef; + + REG_SET_3(SCL_COEF_RAM_TAP_SELECT, 0, + SCL_COEF_RAM_TAP_PAIR_IDX, 0, + SCL_COEF_RAM_PHASE, 0, + SCL_COEF_RAM_FILTER_TYPE, filter_type); + + for (phase = 0; phase < (NUM_PHASES / 2 + 1); phase++) { + for (pair = 0; pair < tap_pairs; pair++) { + even_coef = filter[phase * taps + 2 * pair]; + if ((pair * 2 + 1) < taps) + odd_coef = filter[phase * taps + 2 * pair + 1]; + else + odd_coef = 0; + + REG_SET_4(SCL_COEF_RAM_TAP_DATA, 0, + /* Even tap coefficient (bits 1:0 fixed to 0) */ + SCL_COEF_RAM_EVEN_TAP_COEF, even_coef, + /* Write/read control for even coefficient */ + SCL_COEF_RAM_EVEN_TAP_COEF_EN, 1, + /* Odd tap coefficient (bits 1:0 fixed to 0) */ + SCL_COEF_RAM_ODD_TAP_COEF, odd_coef, + /* Write/read control for odd coefficient */ + SCL_COEF_RAM_ODD_TAP_COEF_EN, 1); + } + } + +} + +static void dpp_set_scl_filter( + struct dcn10_dpp *xfm, + const struct scaler_data *scl_data, + bool chroma_coef_mode) +{ + bool h_2tap_hardcode_coef_en = false; + bool v_2tap_hardcode_coef_en = false; + bool h_2tap_sharp_en = false; + bool v_2tap_sharp_en = false; + uint32_t h_2tap_sharp_factor = scl_data->sharpness.horz; + uint32_t v_2tap_sharp_factor = scl_data->sharpness.vert; + bool coef_ram_current; + const uint16_t *filter_h = NULL; + const uint16_t *filter_v = NULL; + const uint16_t *filter_h_c = NULL; + const uint16_t *filter_v_c = NULL; + + h_2tap_hardcode_coef_en = scl_data->taps.h_taps < 3 + && scl_data->taps.h_taps_c < 3 + && (scl_data->taps.h_taps > 1 || scl_data->taps.h_taps_c > 1); + v_2tap_hardcode_coef_en = scl_data->taps.v_taps < 3 + && scl_data->taps.v_taps_c < 3 + && (scl_data->taps.v_taps > 1 || scl_data->taps.v_taps_c > 1); + + h_2tap_sharp_en = h_2tap_hardcode_coef_en && h_2tap_sharp_factor != 0; + v_2tap_sharp_en = v_2tap_hardcode_coef_en && v_2tap_sharp_factor != 0; + + REG_UPDATE_6(DSCL_2TAP_CONTROL, + SCL_H_2TAP_HARDCODE_COEF_EN, h_2tap_hardcode_coef_en, + SCL_H_2TAP_SHARP_EN, h_2tap_sharp_en, + SCL_H_2TAP_SHARP_FACTOR, h_2tap_sharp_factor, + SCL_V_2TAP_HARDCODE_COEF_EN, v_2tap_hardcode_coef_en, + SCL_V_2TAP_SHARP_EN, v_2tap_sharp_en, + SCL_V_2TAP_SHARP_FACTOR, v_2tap_sharp_factor); + + if (!v_2tap_hardcode_coef_en || !h_2tap_hardcode_coef_en) { + bool filter_updated = false; + + filter_h = get_filter_coeffs_64p( + scl_data->taps.h_taps, scl_data->ratios.horz); + filter_v = get_filter_coeffs_64p( + scl_data->taps.v_taps, scl_data->ratios.vert); + + filter_updated = (filter_h && (filter_h != xfm->filter_h)) + || (filter_v && (filter_v != xfm->filter_v)); + + if (chroma_coef_mode) { + filter_h_c = get_filter_coeffs_64p( + scl_data->taps.h_taps_c, scl_data->ratios.horz_c); + filter_v_c = get_filter_coeffs_64p( + scl_data->taps.v_taps_c, scl_data->ratios.vert_c); + filter_updated = filter_updated || (filter_h_c && (filter_h_c != xfm->filter_h_c)) + || (filter_v_c && (filter_v_c != xfm->filter_v_c)); + } + + if (filter_updated) { + uint32_t scl_mode = REG_READ(SCL_MODE); + + if (!h_2tap_hardcode_coef_en && filter_h) { + dpp_set_scaler_filter( + xfm, scl_data->taps.h_taps, + SCL_COEF_LUMA_HORZ_FILTER, filter_h); + } + xfm->filter_h = filter_h; + if (!v_2tap_hardcode_coef_en && filter_v) { + dpp_set_scaler_filter( + xfm, scl_data->taps.v_taps, + SCL_COEF_LUMA_VERT_FILTER, filter_v); + } + xfm->filter_v = filter_v; + if (chroma_coef_mode) { + if (!h_2tap_hardcode_coef_en && filter_h_c) { + dpp_set_scaler_filter( + xfm, scl_data->taps.h_taps_c, + SCL_COEF_CHROMA_HORZ_FILTER, filter_h_c); + } + if (!v_2tap_hardcode_coef_en && filter_v_c) { + dpp_set_scaler_filter( + xfm, scl_data->taps.v_taps_c, + SCL_COEF_CHROMA_VERT_FILTER, filter_v_c); + } + } + xfm->filter_h_c = filter_h_c; + xfm->filter_v_c = filter_v_c; + + coef_ram_current = get_reg_field_value_ex( + scl_mode, xfm->tf_mask->SCL_COEF_RAM_SELECT_CURRENT, + xfm->tf_shift->SCL_COEF_RAM_SELECT_CURRENT); + + /* Swap coefficient RAM and set chroma coefficient mode */ + REG_SET_2(SCL_MODE, scl_mode, + SCL_COEF_RAM_SELECT, !coef_ram_current, + SCL_CHROMA_COEF_MODE, chroma_coef_mode); + } + } +} + +static int get_lb_depth_bpc(enum lb_pixel_depth depth) +{ + if (depth == LB_PIXEL_DEPTH_30BPP) + return 10; + else if (depth == LB_PIXEL_DEPTH_24BPP) + return 8; + else if (depth == LB_PIXEL_DEPTH_18BPP) + return 6; + else if (depth == LB_PIXEL_DEPTH_36BPP) + return 12; + else { + BREAK_TO_DEBUGGER(); + return -1; /* Unsupported */ + } +} + +static void calc_lb_num_partitions( + const struct scaler_data *scl_data, + enum lb_memory_config lb_config, + int *num_part_y, + int *num_part_c) +{ + int line_size = scl_data->viewport.width < scl_data->recout.width ? + scl_data->viewport.width : scl_data->recout.width; + int line_size_c = scl_data->viewport_c.width < scl_data->recout.width ? + scl_data->viewport_c.width : scl_data->recout.width; + int lb_bpc = get_lb_depth_bpc(scl_data->lb_params.depth); + int memory_line_size_y = (line_size * lb_bpc + 71) / 72; /* +71 to ceil */ + int memory_line_size_c = (line_size_c * lb_bpc + 71) / 72; /* +71 to ceil */ + int memory_line_size_a = (line_size + 5) / 6; /* +5 to ceil */ + int lb_memory_size, lb_memory_size_c, lb_memory_size_a, num_partitions_a; + + if (lb_config == LB_MEMORY_CONFIG_1) { + lb_memory_size = 816; + lb_memory_size_c = 816; + lb_memory_size_a = 984; + } else if (lb_config == LB_MEMORY_CONFIG_2) { + lb_memory_size = 1088; + lb_memory_size_c = 1088; + lb_memory_size_a = 1312; + } else if (lb_config == LB_MEMORY_CONFIG_3) { + lb_memory_size = 816 + 1088 + 848 + 848 + 848; + lb_memory_size_c = 816 + 1088; + lb_memory_size_a = 984 + 1312 + 456; + } else { + lb_memory_size = 816 + 1088 + 848; + lb_memory_size_c = 816 + 1088 + 848; + lb_memory_size_a = 984 + 1312 + 456; + } + *num_part_y = lb_memory_size / memory_line_size_y; + *num_part_c = lb_memory_size_c / memory_line_size_c; + num_partitions_a = lb_memory_size_a / memory_line_size_a; + + if (scl_data->lb_params.alpha_en + && (num_partitions_a < *num_part_y)) + *num_part_y = num_partitions_a; + + if (*num_part_y > 64) + *num_part_y = 64; + if (*num_part_c > 64) + *num_part_c = 64; + +} + +static bool is_lb_conf_valid(int ceil_vratio, int num_partitions, int vtaps) +{ + if (ceil_vratio > 2) + return vtaps <= (num_partitions - ceil_vratio + 2); + else + return vtaps <= num_partitions; +} + +/*find first match configuration which meets the min required lb size*/ +static enum lb_memory_config find_lb_memory_config(const struct scaler_data *scl_data) +{ + int num_part_y, num_part_c; + int vtaps = scl_data->taps.v_taps; + int vtaps_c = scl_data->taps.v_taps_c; + int ceil_vratio = dal_fixed31_32_ceil(scl_data->ratios.vert); + int ceil_vratio_c = dal_fixed31_32_ceil(scl_data->ratios.vert_c); + + calc_lb_num_partitions( + scl_data, LB_MEMORY_CONFIG_1, &num_part_y, &num_part_c); + + if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) + && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)) + return LB_MEMORY_CONFIG_1; + + calc_lb_num_partitions( + scl_data, LB_MEMORY_CONFIG_2, &num_part_y, &num_part_c); + + if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) + && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)) + return LB_MEMORY_CONFIG_2; + + if (scl_data->format == PIXEL_FORMAT_420BPP8 + || scl_data->format == PIXEL_FORMAT_420BPP10) { + calc_lb_num_partitions( + scl_data, LB_MEMORY_CONFIG_3, &num_part_y, &num_part_c); + + if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) + && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)) + return LB_MEMORY_CONFIG_3; + } + + calc_lb_num_partitions( + scl_data, LB_MEMORY_CONFIG_0, &num_part_y, &num_part_c); + + /*Ensure we can support the requested number of vtaps*/ + ASSERT(is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) + && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)); + + return LB_MEMORY_CONFIG_0; +} + +void dpp_set_scaler_auto_scale( + struct transform *xfm_base, + const struct scaler_data *scl_data) +{ + enum lb_memory_config lb_config; + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + enum dscl_mode_sel dscl_mode = get_dscl_mode( + scl_data, xfm_base->ctx->dc->debug.always_scale); + bool ycbcr = scl_data->format >= PIXEL_FORMAT_VIDEO_BEGIN + && scl_data->format <= PIXEL_FORMAT_VIDEO_END; + + dpp_set_overscan(xfm, scl_data); + + dpp_set_otg_blank(xfm, scl_data); + + REG_UPDATE(SCL_MODE, DSCL_MODE, dscl_mode); + + if (dscl_mode == DSCL_MODE_DSCL_BYPASS) + return; + + lb_config = find_lb_memory_config(scl_data); + dpp_set_lb(xfm, &scl_data->lb_params, lb_config); + + if (dscl_mode == DSCL_MODE_SCALING_444_BYPASS) + return; + + /* TODO: v_min */ + REG_SET_3(DSCL_AUTOCAL, 0, + AUTOCAL_MODE, AUTOCAL_MODE_AUTOSCALE, + AUTOCAL_NUM_PIPE, 0, + AUTOCAL_PIPE_ID, 0); + + /* Black offsets */ + if (ycbcr) + REG_SET_2(SCL_BLACK_OFFSET, 0, + SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y, + SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_CBCR); + else + + REG_SET_2(SCL_BLACK_OFFSET, 0, + SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y, + SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_RGB_Y); + + REG_SET_4(SCL_TAP_CONTROL, 0, + SCL_V_NUM_TAPS, scl_data->taps.v_taps - 1, + SCL_H_NUM_TAPS, scl_data->taps.h_taps - 1, + SCL_V_NUM_TAPS_C, scl_data->taps.v_taps_c - 1, + SCL_H_NUM_TAPS_C, scl_data->taps.h_taps_c - 1); + + dpp_set_scl_filter(xfm, scl_data, ycbcr); +} + + +static void dpp_set_manual_ratio_init( + struct dcn10_dpp *xfm, const struct scaler_data *data) +{ + uint32_t init_frac = 0; + uint32_t init_int = 0; + + REG_SET(SCL_HORZ_FILTER_SCALE_RATIO, 0, + SCL_H_SCALE_RATIO, dal_fixed31_32_u2d19(data->ratios.horz) << 5); + + REG_SET(SCL_VERT_FILTER_SCALE_RATIO, 0, + SCL_V_SCALE_RATIO, dal_fixed31_32_u2d19(data->ratios.vert) << 5); + + REG_SET(SCL_HORZ_FILTER_SCALE_RATIO_C, 0, + SCL_H_SCALE_RATIO_C, dal_fixed31_32_u2d19(data->ratios.horz_c) << 5); + + REG_SET(SCL_VERT_FILTER_SCALE_RATIO_C, 0, + SCL_V_SCALE_RATIO_C, dal_fixed31_32_u2d19(data->ratios.vert_c) << 5); + + /* + * 0.24 format for fraction, first five bits zeroed + */ + init_frac = dal_fixed31_32_u0d19(data->inits.h) << 5; + init_int = dal_fixed31_32_floor(data->inits.h); + REG_SET_2(SCL_HORZ_FILTER_INIT, 0, + SCL_H_INIT_FRAC, init_frac, + SCL_H_INIT_INT, init_int); + + init_frac = dal_fixed31_32_u0d19(data->inits.h_c) << 5; + init_int = dal_fixed31_32_floor(data->inits.h_c); + REG_SET_2(SCL_HORZ_FILTER_INIT_C, 0, + SCL_H_INIT_FRAC_C, init_frac, + SCL_H_INIT_INT_C, init_int); + + init_frac = dal_fixed31_32_u0d19(data->inits.v) << 5; + init_int = dal_fixed31_32_floor(data->inits.v); + REG_SET_2(SCL_VERT_FILTER_INIT, 0, + SCL_V_INIT_FRAC, init_frac, + SCL_V_INIT_INT, init_int); + + init_frac = dal_fixed31_32_u0d19(data->inits.v_bot) << 5; + init_int = dal_fixed31_32_floor(data->inits.v_bot); + REG_SET_2(SCL_VERT_FILTER_INIT_BOT, 0, + SCL_V_INIT_FRAC_BOT, init_frac, + SCL_V_INIT_INT_BOT, init_int); + + init_frac = dal_fixed31_32_u0d19(data->inits.v_c) << 5; + init_int = dal_fixed31_32_floor(data->inits.v_c); + REG_SET_2(SCL_VERT_FILTER_INIT_C, 0, + SCL_V_INIT_FRAC_C, init_frac, + SCL_V_INIT_INT_C, init_int); + + init_frac = dal_fixed31_32_u0d19(data->inits.v_c_bot) << 5; + init_int = dal_fixed31_32_floor(data->inits.v_c_bot); + REG_SET_2(SCL_VERT_FILTER_INIT_BOT_C, 0, + SCL_V_INIT_FRAC_BOT_C, init_frac, + SCL_V_INIT_INT_BOT_C, init_int); +} + + + +static void dpp_set_recout( + struct dcn10_dpp *xfm, const struct rect *recout) +{ + REG_SET_2(RECOUT_START, 0, + /* First pixel of RECOUT */ + RECOUT_START_X, recout->x, + /* First line of RECOUT */ + RECOUT_START_Y, recout->y); + + REG_SET_2(RECOUT_SIZE, 0, + /* Number of RECOUT horizontal pixels */ + RECOUT_WIDTH, recout->width, + /* Number of RECOUT vertical lines */ + RECOUT_HEIGHT, recout->height + - xfm->base.ctx->dc->debug.surface_visual_confirm * 4 * + (xfm->base.inst + 1)); +} + +/* Main function to program scaler and line buffer in manual scaling mode */ +void dcn10_dpp_set_scaler_manual_scale( + struct transform *xfm_base, + const struct scaler_data *scl_data) +{ + enum lb_memory_config lb_config; + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + enum dscl_mode_sel dscl_mode = get_dscl_mode( + scl_data, xfm_base->ctx->dc->debug.always_scale); + bool ycbcr = scl_data->format >= PIXEL_FORMAT_VIDEO_BEGIN + && scl_data->format <= PIXEL_FORMAT_VIDEO_END; + + /* Recout */ + dpp_set_recout(xfm, &scl_data->recout); + + /* MPC Size */ + REG_SET_2(MPC_SIZE, 0, + /* Number of horizontal pixels of MPC */ + MPC_WIDTH, scl_data->h_active, + /* Number of vertical lines of MPC */ + MPC_HEIGHT, scl_data->v_active); + + /* SCL mode */ + REG_UPDATE(SCL_MODE, DSCL_MODE, dscl_mode); + + if (dscl_mode == DSCL_MODE_DSCL_BYPASS) + return; + /* LB */ + lb_config = find_lb_memory_config(scl_data); + dpp_set_lb(xfm, &scl_data->lb_params, lb_config); + + if (dscl_mode == DSCL_MODE_SCALING_444_BYPASS) + return; + + /* Autocal off */ + REG_SET_3(DSCL_AUTOCAL, 0, + AUTOCAL_MODE, AUTOCAL_MODE_OFF, + AUTOCAL_NUM_PIPE, 0, + AUTOCAL_PIPE_ID, 0); + + /* Black offsets */ + if (ycbcr) + REG_SET_2(SCL_BLACK_OFFSET, 0, + SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y, + SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_CBCR); + else + + REG_SET_2(SCL_BLACK_OFFSET, 0, + SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y, + SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_RGB_Y); + + /* Manually calculate scale ratio and init values */ + dpp_set_manual_ratio_init(xfm, scl_data); + + /* HTaps/VTaps */ + REG_SET_4(SCL_TAP_CONTROL, 0, + SCL_V_NUM_TAPS, scl_data->taps.v_taps - 1, + SCL_H_NUM_TAPS, scl_data->taps.h_taps - 1, + SCL_V_NUM_TAPS_C, scl_data->taps.v_taps_c - 1, + SCL_H_NUM_TAPS_C, scl_data->taps.h_taps_c - 1); + + dpp_set_scl_filter(xfm, scl_data, ycbcr); +} + + +#if 0 +bool dpp_set_pixel_storage_depth( + struct dpp *xfm, + enum lb_pixel_depth depth, + const struct bit_depth_reduction_params *bit_depth_params) +{ + struct dcn10_dpp *xfm110 = TO_DCN10_DPP(xfm); + bool ret = true; + uint32_t value; + enum dc_color_depth color_depth; + + value = dm_read_reg(xfm->ctx, LB_REG(mmLB_DATA_FORMAT)); + switch (depth) { + case LB_PIXEL_DEPTH_18BPP: + color_depth = COLOR_DEPTH_666; + set_reg_field_value(value, 2, LB_DATA_FORMAT, PIXEL_DEPTH); + set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_EXPAN_MODE); + break; + case LB_PIXEL_DEPTH_24BPP: + color_depth = COLOR_DEPTH_888; + set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_DEPTH); + set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_EXPAN_MODE); + break; + case LB_PIXEL_DEPTH_30BPP: + color_depth = COLOR_DEPTH_101010; + set_reg_field_value(value, 0, LB_DATA_FORMAT, PIXEL_DEPTH); + set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_EXPAN_MODE); + break; + case LB_PIXEL_DEPTH_36BPP: + color_depth = COLOR_DEPTH_121212; + set_reg_field_value(value, 3, LB_DATA_FORMAT, PIXEL_DEPTH); + set_reg_field_value(value, 0, LB_DATA_FORMAT, PIXEL_EXPAN_MODE); + break; + default: + ret = false; + break; + } + + if (ret == true) { + set_denormalization(xfm110, color_depth); + ret = program_bit_depth_reduction(xfm110, color_depth, + bit_depth_params); + + set_reg_field_value(value, 0, LB_DATA_FORMAT, ALPHA_EN); + dm_write_reg(xfm->ctx, LB_REG(mmLB_DATA_FORMAT), value); + if (!(xfm110->lb_pixel_depth_supported & depth)) { + /* We should use unsupported capabilities + * unless it is required by w/a + */ + dm_logger_write(xfm->ctx->logger, LOG_WARNING, + "%s: Capability not supported", + __func__); + } + } + + return ret; +} +#endif + + -- cgit From 9799624ac236eb238b5a5c885c759b1cbcac6349 Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Tue, 15 Aug 2017 19:10:14 -0400 Subject: drm/amd/display: Cache edp config in dc link Signed-off-by: Wenjing Liu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 2 ++ drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') 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 0144c98fd0d5..d621237e923e 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 @@ -2258,6 +2258,8 @@ static void retrieve_link_cap(struct dc_link *link) DP_EDP_CONFIGURATION_CAP - DP_DPCD_REV]; link->dpcd_caps.panel_mode_edp = edp_config_cap.bits.ALT_SCRAMBLER_RESET; + link->dpcd_caps.dpcd_display_control_capable = + edp_config_cap.bits.DPCD_DISPLAY_CONTROL_CAPABLE; link->test_pattern_enabled = false; link->compliance_test_state.raw = 0; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 928d2a0501eb..bd8b1ba22df8 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -760,6 +760,7 @@ struct dpcd_caps { bool allow_invalid_MSA_timing_param; bool panel_mode_edp; + bool dpcd_display_control_capable; }; struct dc_link_status { @@ -834,7 +835,6 @@ struct dc_link { struct dpcd_caps dpcd_caps; unsigned short chip_caps; unsigned int dpcd_sink_count; - enum edp_revision edp_revision; bool psr_enabled; -- cgit From 3005e437e70fd4d1da64d91b4ef027f62d3b9a41 Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Thu, 17 Aug 2017 16:24:11 -0400 Subject: drm/amd/display: re-enable audio after LT test [Description] Audio should be attached to the same pipe once it is attached. We will not remove audio endpoint in disable stream. We will reeanble the audio after automated link training test Signed-off-by: Wenjing Liu Reviewed-by: Tony Cheng Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 14 ++++++++++++++ .../gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 2 -- 2 files changed, 14 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index e12f1f9fb590..3a5abd92036a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -310,6 +310,20 @@ void dp_retrain_link_dp_test(struct dc_link *link, link->dc->hwss.unblank_stream(&pipes[i], link_setting); + + if (pipes[i].stream_res.audio) { + /* notify audio driver for + * audio modes of monitor */ + pipes[i].stream_res.audio->funcs->az_enable( + pipes[i].stream_res.audio); + + /* un-mute audio */ + /* TODO: audio should be per stream rather than + * per link */ + pipes[i].stream_res.stream_enc->funcs-> + audio_mute_control( + pipes[i].stream_res.stream_enc, false); + } } } } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index e6c6f1108078..7516c198d13a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -758,8 +758,6 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_disable( pipe_ctx->stream_res.stream_enc); - pipe_ctx->stream_res.audio = NULL; - /* TODO: notify audio driver for if audio modes list changed * add audio mode list change flag */ /* dal_audio_disable_azalia_audio_jack_presence(stream->audio, -- cgit From dff2721bd1d777eba3917f04d4b8adede89badff Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Thu, 17 Aug 2017 17:17:37 -0400 Subject: drm/amd/display: separate cm functions out from dcn10_dpp Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/Makefile | 2 +- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c | 662 ------------------ drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h | 34 + .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c | 776 +++++++++++++++++++++ 4 files changed, 811 insertions(+), 663 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile index 83619e6b8a05..52b56d19ca40 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile @@ -4,7 +4,7 @@ DCN10 = dcn10_resource.o dcn10_ipp.o dcn10_hw_sequencer.o \ dcn10_dpp.o dcn10_opp.o dcn10_timing_generator.o \ dcn10_mem_input.o dcn10_mpc.o dcn10_dwb.o \ - dcn10_dpp_dscl.o + dcn10_dpp_dscl.o dcn10_dpp_cm.o AMD_DAL_DCN10 = $(addprefix $(AMDDALPATH)/dc/dcn10/,$(DCN10)) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c index a841ed36c217..f0e74afc4518 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c @@ -195,669 +195,7 @@ static void dpp_reset(struct transform *xfm_base) REG_SET(DSCL_CONTROL, 0, SCL_BOUNDARY_MODE, 0); } -static void program_gamut_remap( - struct dcn10_dpp *xfm, - const uint16_t *regval, - enum gamut_remap_select select) -{ - uint16_t selection = 0; - - if (regval == NULL || select == GAMUT_REMAP_BYPASS) { - REG_SET(CM_GAMUT_REMAP_CONTROL, 0, - CM_GAMUT_REMAP_MODE, 0); - return; - } - switch (select) { - case GAMUT_REMAP_COEFF: - selection = 1; - break; - case GAMUT_REMAP_COMA_COEFF: - selection = 2; - break; - case GAMUT_REMAP_COMB_COEFF: - selection = 3; - break; - default: - break; - } - - - if (select == GAMUT_REMAP_COEFF) { - - REG_SET_2(CM_GAMUT_REMAP_C11_C12, 0, - CM_GAMUT_REMAP_C11, regval[0], - CM_GAMUT_REMAP_C12, regval[1]); - regval += 2; - REG_SET_2(CM_GAMUT_REMAP_C13_C14, 0, - CM_GAMUT_REMAP_C13, regval[0], - CM_GAMUT_REMAP_C14, regval[1]); - regval += 2; - REG_SET_2(CM_GAMUT_REMAP_C21_C22, 0, - CM_GAMUT_REMAP_C21, regval[0], - CM_GAMUT_REMAP_C22, regval[1]); - regval += 2; - REG_SET_2(CM_GAMUT_REMAP_C23_C24, 0, - CM_GAMUT_REMAP_C23, regval[0], - CM_GAMUT_REMAP_C24, regval[1]); - regval += 2; - REG_SET_2(CM_GAMUT_REMAP_C31_C32, 0, - CM_GAMUT_REMAP_C31, regval[0], - CM_GAMUT_REMAP_C32, regval[1]); - regval += 2; - REG_SET_2(CM_GAMUT_REMAP_C33_C34, 0, - CM_GAMUT_REMAP_C33, regval[0], - CM_GAMUT_REMAP_C34, regval[1]); - - } else if (select == GAMUT_REMAP_COMA_COEFF) { - REG_SET_2(CM_COMA_C11_C12, 0, - CM_COMA_C11, regval[0], - CM_COMA_C12, regval[1]); - regval += 2; - REG_SET_2(CM_COMA_C13_C14, 0, - CM_COMA_C13, regval[0], - CM_COMA_C14, regval[1]); - regval += 2; - REG_SET_2(CM_COMA_C21_C22, 0, - CM_COMA_C21, regval[0], - CM_COMA_C22, regval[1]); - regval += 2; - REG_SET_2(CM_COMA_C23_C24, 0, - CM_COMA_C23, regval[0], - CM_COMA_C24, regval[1]); - regval += 2; - REG_SET_2(CM_COMA_C31_C32, 0, - CM_COMA_C31, regval[0], - CM_COMA_C32, regval[1]); - regval += 2; - REG_SET_2(CM_COMA_C33_C34, 0, - CM_COMA_C33, regval[0], - CM_COMA_C34, regval[1]); - - } else { - REG_SET_2(CM_COMB_C11_C12, 0, - CM_COMB_C11, regval[0], - CM_COMB_C12, regval[1]); - regval += 2; - REG_SET_2(CM_COMB_C13_C14, 0, - CM_COMB_C13, regval[0], - CM_COMB_C14, regval[1]); - regval += 2; - REG_SET_2(CM_COMB_C21_C22, 0, - CM_COMB_C21, regval[0], - CM_COMB_C22, regval[1]); - regval += 2; - REG_SET_2(CM_COMB_C23_C24, 0, - CM_COMB_C23, regval[0], - CM_COMB_C24, regval[1]); - regval += 2; - REG_SET_2(CM_COMB_C31_C32, 0, - CM_COMB_C31, regval[0], - CM_COMB_C32, regval[1]); - regval += 2; - REG_SET_2(CM_COMB_C33_C34, 0, - CM_COMB_C33, regval[0], - CM_COMB_C34, regval[1]); - } - - REG_SET( - CM_GAMUT_REMAP_CONTROL, 0, - CM_GAMUT_REMAP_MODE, selection); - -} - -static void dcn_dpp_set_gamut_remap( - struct transform *xfm, - const struct xfm_grph_csc_adjustment *adjust) -{ - struct dcn10_dpp *dcn_xfm = TO_DCN10_DPP(xfm); - - if (adjust->gamut_adjust_type != GRAPHICS_GAMUT_ADJUST_TYPE_SW) - /* Bypass if type is bypass or hw */ - program_gamut_remap(dcn_xfm, NULL, GAMUT_REMAP_BYPASS); - else { - struct fixed31_32 arr_matrix[12]; - uint16_t arr_reg_val[12]; - - arr_matrix[0] = adjust->temperature_matrix[0]; - arr_matrix[1] = adjust->temperature_matrix[1]; - arr_matrix[2] = adjust->temperature_matrix[2]; - arr_matrix[3] = dal_fixed31_32_zero; - - arr_matrix[4] = adjust->temperature_matrix[3]; - arr_matrix[5] = adjust->temperature_matrix[4]; - arr_matrix[6] = adjust->temperature_matrix[5]; - arr_matrix[7] = dal_fixed31_32_zero; - - arr_matrix[8] = adjust->temperature_matrix[6]; - arr_matrix[9] = adjust->temperature_matrix[7]; - arr_matrix[10] = adjust->temperature_matrix[8]; - arr_matrix[11] = dal_fixed31_32_zero; - - convert_float_matrix( - arr_reg_val, arr_matrix, 12); - - program_gamut_remap(dcn_xfm, arr_reg_val, GAMUT_REMAP_COEFF); - } -} -static void oppn10_set_output_csc_default( - struct transform *xfm_base, - const struct default_adjustment *default_adjust) -{ - - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); - uint32_t ocsc_mode = 0; - - if (default_adjust != NULL) { - switch (default_adjust->out_color_space) { - case COLOR_SPACE_SRGB: - case COLOR_SPACE_2020_RGB_FULLRANGE: - ocsc_mode = 0; - break; - case COLOR_SPACE_SRGB_LIMITED: - case COLOR_SPACE_2020_RGB_LIMITEDRANGE: - ocsc_mode = 1; - break; - case COLOR_SPACE_YCBCR601: - case COLOR_SPACE_YCBCR601_LIMITED: - ocsc_mode = 2; - break; - case COLOR_SPACE_YCBCR709: - case COLOR_SPACE_YCBCR709_LIMITED: - case COLOR_SPACE_2020_YCBCR: - ocsc_mode = 3; - break; - case COLOR_SPACE_UNKNOWN: - default: - break; - } - } - - REG_SET(CM_OCSC_CONTROL, 0, CM_OCSC_MODE, ocsc_mode); - -} - -static void oppn10_program_color_matrix( - struct dcn10_dpp *xfm, - const struct out_csc_color_matrix *tbl_entry) -{ - uint32_t mode; - - REG_GET(CM_OCSC_CONTROL, CM_OCSC_MODE, &mode); - - if (tbl_entry == NULL) { - BREAK_TO_DEBUGGER(); - return; - } - - if (mode == 4) { - /*R*/ - REG_SET_2(CM_OCSC_C11_C12, 0, - CM_OCSC_C11, tbl_entry->regval[0], - CM_OCSC_C12, tbl_entry->regval[1]); - - REG_SET_2(CM_OCSC_C13_C14, 0, - CM_OCSC_C13, tbl_entry->regval[2], - CM_OCSC_C14, tbl_entry->regval[3]); - - /*G*/ - REG_SET_2(CM_OCSC_C21_C22, 0, - CM_OCSC_C21, tbl_entry->regval[4], - CM_OCSC_C22, tbl_entry->regval[5]); - - REG_SET_2(CM_OCSC_C23_C24, 0, - CM_OCSC_C23, tbl_entry->regval[6], - CM_OCSC_C24, tbl_entry->regval[7]); - - /*B*/ - REG_SET_2(CM_OCSC_C31_C32, 0, - CM_OCSC_C31, tbl_entry->regval[8], - CM_OCSC_C32, tbl_entry->regval[9]); - - REG_SET_2(CM_OCSC_C33_C34, 0, - CM_OCSC_C33, tbl_entry->regval[10], - CM_OCSC_C34, tbl_entry->regval[11]); - } else { - /*R*/ - REG_SET_2(CM_COMB_C11_C12, 0, - CM_COMB_C11, tbl_entry->regval[0], - CM_COMB_C12, tbl_entry->regval[1]); - - REG_SET_2(CM_COMB_C13_C14, 0, - CM_COMB_C13, tbl_entry->regval[2], - CM_COMB_C14, tbl_entry->regval[3]); - - /*G*/ - REG_SET_2(CM_COMB_C21_C22, 0, - CM_COMB_C21, tbl_entry->regval[4], - CM_COMB_C22, tbl_entry->regval[5]); - - REG_SET_2(CM_COMB_C23_C24, 0, - CM_COMB_C23, tbl_entry->regval[6], - CM_COMB_C24, tbl_entry->regval[7]); - - /*B*/ - REG_SET_2(CM_COMB_C31_C32, 0, - CM_COMB_C31, tbl_entry->regval[8], - CM_COMB_C32, tbl_entry->regval[9]); - - REG_SET_2(CM_COMB_C33_C34, 0, - CM_COMB_C33, tbl_entry->regval[10], - CM_COMB_C34, tbl_entry->regval[11]); - } -} - -static void oppn10_set_output_csc_adjustment( - struct transform *xfm_base, - const struct out_csc_color_matrix *tbl_entry) -{ - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); - //enum csc_color_mode config = CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; - uint32_t ocsc_mode = 4; - - /** - *if (tbl_entry != NULL) { - * switch (tbl_entry->color_space) { - * case COLOR_SPACE_SRGB: - * case COLOR_SPACE_2020_RGB_FULLRANGE: - * ocsc_mode = 0; - * break; - * case COLOR_SPACE_SRGB_LIMITED: - * case COLOR_SPACE_2020_RGB_LIMITEDRANGE: - * ocsc_mode = 1; - * break; - * case COLOR_SPACE_YCBCR601: - * case COLOR_SPACE_YCBCR601_LIMITED: - * ocsc_mode = 2; - * break; - * case COLOR_SPACE_YCBCR709: - * case COLOR_SPACE_YCBCR709_LIMITED: - * case COLOR_SPACE_2020_YCBCR: - * ocsc_mode = 3; - * break; - * case COLOR_SPACE_UNKNOWN: - * default: - * break; - * } - *} - */ - - REG_SET(CM_OCSC_CONTROL, 0, CM_OCSC_MODE, ocsc_mode); - oppn10_program_color_matrix(xfm, tbl_entry); -} - -static void oppn10_power_on_regamma_lut( - struct transform *xfm_base, - bool power_on) -{ - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); - REG_SET(CM_MEM_PWR_CTRL, 0, - RGAM_MEM_PWR_FORCE, power_on == true ? 0:1); - -} - -static void opp_program_regamma_lut( - struct transform *xfm_base, - const struct pwl_result_data *rgb, - uint32_t num) -{ - uint32_t i; - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); - for (i = 0 ; i < num; i++) { - REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].red_reg); - REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].green_reg); - REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].blue_reg); - - REG_SET(CM_RGAM_LUT_DATA, 0, - CM_RGAM_LUT_DATA, rgb[i].delta_red_reg); - REG_SET(CM_RGAM_LUT_DATA, 0, - CM_RGAM_LUT_DATA, rgb[i].delta_green_reg); - REG_SET(CM_RGAM_LUT_DATA, 0, - CM_RGAM_LUT_DATA, rgb[i].delta_blue_reg); - - } - -} - -static void opp_configure_regamma_lut( - struct transform *xfm_base, - bool is_ram_a) -{ - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); - - REG_UPDATE(CM_RGAM_LUT_WRITE_EN_MASK, - CM_RGAM_LUT_WRITE_EN_MASK, 7); - REG_UPDATE(CM_RGAM_LUT_WRITE_EN_MASK, - CM_RGAM_LUT_WRITE_SEL, is_ram_a == true ? 0:1); - REG_SET(CM_RGAM_LUT_INDEX, 0, CM_RGAM_LUT_INDEX, 0); -} - -/*program re gamma RAM A*/ -static void opp_program_regamma_luta_settings( - struct transform *xfm_base, - const struct pwl_params *params) -{ - const struct gamma_curve *curve; - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); - - REG_SET_2(CM_RGAM_RAMA_START_CNTL_B, 0, - CM_RGAM_RAMA_EXP_REGION_START_B, params->arr_points[0].custom_float_x, - CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_B, 0); - REG_SET_2(CM_RGAM_RAMA_START_CNTL_G, 0, - CM_RGAM_RAMA_EXP_REGION_START_G, params->arr_points[0].custom_float_x, - CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_G, 0); - REG_SET_2(CM_RGAM_RAMA_START_CNTL_R, 0, - CM_RGAM_RAMA_EXP_REGION_START_R, params->arr_points[0].custom_float_x, - CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_R, 0); - - REG_SET(CM_RGAM_RAMA_SLOPE_CNTL_B, 0, - CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B, params->arr_points[0].custom_float_slope); - REG_SET(CM_RGAM_RAMA_SLOPE_CNTL_G, 0, - CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G, params->arr_points[0].custom_float_slope); - REG_SET(CM_RGAM_RAMA_SLOPE_CNTL_R, 0, - CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R, params->arr_points[0].custom_float_slope); - - REG_SET(CM_RGAM_RAMA_END_CNTL1_B, 0, - CM_RGAM_RAMA_EXP_REGION_END_B, params->arr_points[1].custom_float_x); - REG_SET_2(CM_RGAM_RAMA_END_CNTL2_B, 0, - CM_RGAM_RAMA_EXP_REGION_END_SLOPE_B, params->arr_points[1].custom_float_slope, - CM_RGAM_RAMA_EXP_REGION_END_BASE_B, params->arr_points[1].custom_float_y); - - REG_SET(CM_RGAM_RAMA_END_CNTL1_G, 0, - CM_RGAM_RAMA_EXP_REGION_END_G, params->arr_points[1].custom_float_x); - REG_SET_2(CM_RGAM_RAMA_END_CNTL2_G, 0, - CM_RGAM_RAMA_EXP_REGION_END_SLOPE_G, params->arr_points[1].custom_float_slope, - CM_RGAM_RAMA_EXP_REGION_END_BASE_G, params->arr_points[1].custom_float_y); - - REG_SET(CM_RGAM_RAMA_END_CNTL1_R, 0, - CM_RGAM_RAMA_EXP_REGION_END_R, params->arr_points[1].custom_float_x); - REG_SET_2(CM_RGAM_RAMA_END_CNTL2_R, 0, - CM_RGAM_RAMA_EXP_REGION_END_SLOPE_R, params->arr_points[1].custom_float_slope, - CM_RGAM_RAMA_EXP_REGION_END_BASE_R, params->arr_points[1].custom_float_y); - - curve = params->arr_curve_points; - REG_SET_4(CM_RGAM_RAMA_REGION_0_1, 0, - CM_RGAM_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_2_3, 0, - CM_RGAM_RAMA_EXP_REGION2_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION3_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_4_5, 0, - CM_RGAM_RAMA_EXP_REGION4_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION5_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_6_7, 0, - CM_RGAM_RAMA_EXP_REGION6_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION7_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_8_9, 0, - CM_RGAM_RAMA_EXP_REGION8_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION9_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_10_11, 0, - CM_RGAM_RAMA_EXP_REGION10_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION11_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_12_13, 0, - CM_RGAM_RAMA_EXP_REGION12_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION13_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_14_15, 0, - CM_RGAM_RAMA_EXP_REGION14_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION15_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_16_17, 0, - CM_RGAM_RAMA_EXP_REGION16_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION16_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION17_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION17_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_18_19, 0, - CM_RGAM_RAMA_EXP_REGION18_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION18_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION19_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION19_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_20_21, 0, - CM_RGAM_RAMA_EXP_REGION20_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION20_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION21_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION21_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_22_23, 0, - CM_RGAM_RAMA_EXP_REGION22_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION22_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION23_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION23_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_24_25, 0, - CM_RGAM_RAMA_EXP_REGION24_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION24_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION25_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION25_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_26_27, 0, - CM_RGAM_RAMA_EXP_REGION26_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION26_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION27_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION27_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_28_29, 0, - CM_RGAM_RAMA_EXP_REGION28_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION28_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION29_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION29_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_30_31, 0, - CM_RGAM_RAMA_EXP_REGION30_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION30_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION31_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION31_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_32_33, 0, - CM_RGAM_RAMA_EXP_REGION32_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION32_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION33_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION33_NUM_SEGMENTS, curve[1].segments_num); -} - -/*program re gamma RAM B*/ -static void opp_program_regamma_lutb_settings( - struct transform *xfm_base, - const struct pwl_params *params) -{ - const struct gamma_curve *curve; - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); - - REG_SET_2(CM_RGAM_RAMB_START_CNTL_B, 0, - CM_RGAM_RAMB_EXP_REGION_START_B, params->arr_points[0].custom_float_x, - CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B, 0); - REG_SET_2(CM_RGAM_RAMB_START_CNTL_G, 0, - CM_RGAM_RAMB_EXP_REGION_START_G, params->arr_points[0].custom_float_x, - CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_G, 0); - REG_SET_2(CM_RGAM_RAMB_START_CNTL_R, 0, - CM_RGAM_RAMB_EXP_REGION_START_R, params->arr_points[0].custom_float_x, - CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_R, 0); - - REG_SET(CM_RGAM_RAMB_SLOPE_CNTL_B, 0, - CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B, params->arr_points[0].custom_float_slope); - REG_SET(CM_RGAM_RAMB_SLOPE_CNTL_G, 0, - CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_G, params->arr_points[0].custom_float_slope); - REG_SET(CM_RGAM_RAMB_SLOPE_CNTL_R, 0, - CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_R, params->arr_points[0].custom_float_slope); - - REG_SET(CM_RGAM_RAMB_END_CNTL1_B, 0, - CM_RGAM_RAMB_EXP_REGION_END_B, params->arr_points[1].custom_float_x); - REG_SET_2(CM_RGAM_RAMB_END_CNTL2_B, 0, - CM_RGAM_RAMB_EXP_REGION_END_SLOPE_B, params->arr_points[1].custom_float_slope, - CM_RGAM_RAMB_EXP_REGION_END_BASE_B, params->arr_points[1].custom_float_y); - - REG_SET(CM_RGAM_RAMB_END_CNTL1_G, 0, - CM_RGAM_RAMB_EXP_REGION_END_G, params->arr_points[1].custom_float_x); - REG_SET_2(CM_RGAM_RAMB_END_CNTL2_G, 0, - CM_RGAM_RAMB_EXP_REGION_END_SLOPE_G, params->arr_points[1].custom_float_slope, - CM_RGAM_RAMB_EXP_REGION_END_BASE_G, params->arr_points[1].custom_float_y); - - REG_SET(CM_RGAM_RAMB_END_CNTL1_R, 0, - CM_RGAM_RAMB_EXP_REGION_END_R, params->arr_points[1].custom_float_x); - REG_SET_2(CM_RGAM_RAMB_END_CNTL2_R, 0, - CM_RGAM_RAMB_EXP_REGION_END_SLOPE_R, params->arr_points[1].custom_float_slope, - CM_RGAM_RAMB_EXP_REGION_END_BASE_R, params->arr_points[1].custom_float_y); - - curve = params->arr_curve_points; - REG_SET_4(CM_RGAM_RAMB_REGION_0_1, 0, - CM_RGAM_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_2_3, 0, - CM_RGAM_RAMB_EXP_REGION2_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION3_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_4_5, 0, - CM_RGAM_RAMB_EXP_REGION4_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION5_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_6_7, 0, - CM_RGAM_RAMB_EXP_REGION6_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION7_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_8_9, 0, - CM_RGAM_RAMB_EXP_REGION8_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION9_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_10_11, 0, - CM_RGAM_RAMB_EXP_REGION10_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION11_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_12_13, 0, - CM_RGAM_RAMB_EXP_REGION12_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION13_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_14_15, 0, - CM_RGAM_RAMB_EXP_REGION14_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION15_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_16_17, 0, - CM_RGAM_RAMB_EXP_REGION16_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION16_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION17_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION17_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_18_19, 0, - CM_RGAM_RAMB_EXP_REGION18_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION18_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION19_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION19_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_20_21, 0, - CM_RGAM_RAMB_EXP_REGION20_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION20_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION21_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION21_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_22_23, 0, - CM_RGAM_RAMB_EXP_REGION22_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION22_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION23_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION23_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_24_25, 0, - CM_RGAM_RAMB_EXP_REGION24_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION24_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION25_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION25_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_26_27, 0, - CM_RGAM_RAMB_EXP_REGION26_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION26_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION27_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION27_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_28_29, 0, - CM_RGAM_RAMB_EXP_REGION28_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION28_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION29_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION29_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_30_31, 0, - CM_RGAM_RAMB_EXP_REGION30_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION30_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION31_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION31_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_32_33, 0, - CM_RGAM_RAMB_EXP_REGION32_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION32_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION33_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION33_NUM_SEGMENTS, curve[1].segments_num); - -} static bool oppn10_set_regamma_pwl( struct transform *xfm_base, const struct pwl_params *params) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h index 496df1fad8c4..a4dfdb9b4d69 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h @@ -1387,6 +1387,40 @@ struct dcn10_dpp { bool is_write_to_ram_a_safe; }; +void opp_program_regamma_lut( + struct transform *xfm_base, + const struct pwl_result_data *rgb, + uint32_t num); + +void oppn10_power_on_regamma_lut( + struct transform *xfm_base, + bool power_on); + +void opp_configure_regamma_lut( + struct transform *xfm_base, + bool is_ram_a); + +/*program re gamma RAM A*/ +void opp_program_regamma_luta_settings( + struct transform *xfm_base, + const struct pwl_params *params); + +/*program re gamma RAM B*/ +void opp_program_regamma_lutb_settings( + struct transform *xfm_base, + const struct pwl_params *params); +void oppn10_set_output_csc_adjustment( + struct transform *xfm_base, + const struct out_csc_color_matrix *tbl_entry); + +void oppn10_set_output_csc_default( + struct transform *xfm_base, + const struct default_adjustment *default_adjust); + +void dcn_dpp_set_gamut_remap( + struct transform *xfm, + const struct xfm_grph_csc_adjustment *adjust); + void dcn10_dpp_set_scaler_manual_scale( struct transform *xfm_base, const struct scaler_data *scl_data); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c new file mode 100644 index 000000000000..7eb4334c30fc --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c @@ -0,0 +1,776 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "core_types.h" + +#include "include/grph_object_id.h" +#include "include/fixed31_32.h" +#include "include/logger_interface.h" + +#include "reg_helper.h" +#include "dcn10_dpp.h" +#include "basics/conversion.h" + +#define NUM_PHASES 64 +#define HORZ_MAX_TAPS 8 +#define VERT_MAX_TAPS 8 + +#define BLACK_OFFSET_RGB_Y 0x0 +#define BLACK_OFFSET_CBCR 0x8000 + +#define REG(reg)\ + xfm->tf_regs->reg + +#define CTX \ + xfm->base.ctx + +#undef FN +#define FN(reg_name, field_name) \ + xfm->tf_shift->field_name, xfm->tf_mask->field_name + +enum dcn10_coef_filter_type_sel { + SCL_COEF_LUMA_VERT_FILTER = 0, + SCL_COEF_LUMA_HORZ_FILTER = 1, + SCL_COEF_CHROMA_VERT_FILTER = 2, + SCL_COEF_CHROMA_HORZ_FILTER = 3, + SCL_COEF_ALPHA_VERT_FILTER = 4, + SCL_COEF_ALPHA_HORZ_FILTER = 5 +}; + +enum lb_memory_config { + /* Enable all 3 pieces of memory */ + LB_MEMORY_CONFIG_0 = 0, + + /* Enable only the first piece of memory */ + LB_MEMORY_CONFIG_1 = 1, + + /* Enable only the second piece of memory */ + LB_MEMORY_CONFIG_2 = 2, + + /* Only applicable in 4:2:0 mode, enable all 3 pieces of memory and the + * last piece of chroma memory used for the luma storage + */ + LB_MEMORY_CONFIG_3 = 3 +}; + +enum dscl_autocal_mode { + AUTOCAL_MODE_OFF = 0, + + /* Autocal calculate the scaling ratio and initial phase and the + * DSCL_MODE_SEL must be set to 1 + */ + AUTOCAL_MODE_AUTOSCALE = 1, + /* Autocal perform auto centering without replication and the + * DSCL_MODE_SEL must be set to 0 + */ + AUTOCAL_MODE_AUTOCENTER = 2, + /* Autocal perform auto centering and auto replication and the + * DSCL_MODE_SEL must be set to 0 + */ + AUTOCAL_MODE_AUTOREPLICATE = 3 +}; + +enum dscl_mode_sel { + DSCL_MODE_SCALING_444_BYPASS = 0, + DSCL_MODE_SCALING_444_RGB_ENABLE = 1, + DSCL_MODE_SCALING_444_YCBCR_ENABLE = 2, + DSCL_MODE_SCALING_420_YCBCR_ENABLE = 3, + DSCL_MODE_SCALING_420_LUMA_BYPASS = 4, + DSCL_MODE_SCALING_420_CHROMA_BYPASS = 5, + DSCL_MODE_DSCL_BYPASS = 6 +}; + +enum gamut_remap_select { + GAMUT_REMAP_BYPASS = 0, + GAMUT_REMAP_COEFF, + GAMUT_REMAP_COMA_COEFF, + GAMUT_REMAP_COMB_COEFF +}; + +static void program_gamut_remap( + struct dcn10_dpp *xfm, + const uint16_t *regval, + enum gamut_remap_select select) +{ + uint16_t selection = 0; + + if (regval == NULL || select == GAMUT_REMAP_BYPASS) { + REG_SET(CM_GAMUT_REMAP_CONTROL, 0, + CM_GAMUT_REMAP_MODE, 0); + return; + } + switch (select) { + case GAMUT_REMAP_COEFF: + selection = 1; + break; + case GAMUT_REMAP_COMA_COEFF: + selection = 2; + break; + case GAMUT_REMAP_COMB_COEFF: + selection = 3; + break; + default: + break; + } + + + if (select == GAMUT_REMAP_COEFF) { + + REG_SET_2(CM_GAMUT_REMAP_C11_C12, 0, + CM_GAMUT_REMAP_C11, regval[0], + CM_GAMUT_REMAP_C12, regval[1]); + regval += 2; + REG_SET_2(CM_GAMUT_REMAP_C13_C14, 0, + CM_GAMUT_REMAP_C13, regval[0], + CM_GAMUT_REMAP_C14, regval[1]); + regval += 2; + REG_SET_2(CM_GAMUT_REMAP_C21_C22, 0, + CM_GAMUT_REMAP_C21, regval[0], + CM_GAMUT_REMAP_C22, regval[1]); + regval += 2; + REG_SET_2(CM_GAMUT_REMAP_C23_C24, 0, + CM_GAMUT_REMAP_C23, regval[0], + CM_GAMUT_REMAP_C24, regval[1]); + regval += 2; + REG_SET_2(CM_GAMUT_REMAP_C31_C32, 0, + CM_GAMUT_REMAP_C31, regval[0], + CM_GAMUT_REMAP_C32, regval[1]); + regval += 2; + REG_SET_2(CM_GAMUT_REMAP_C33_C34, 0, + CM_GAMUT_REMAP_C33, regval[0], + CM_GAMUT_REMAP_C34, regval[1]); + + } else if (select == GAMUT_REMAP_COMA_COEFF) { + REG_SET_2(CM_COMA_C11_C12, 0, + CM_COMA_C11, regval[0], + CM_COMA_C12, regval[1]); + regval += 2; + REG_SET_2(CM_COMA_C13_C14, 0, + CM_COMA_C13, regval[0], + CM_COMA_C14, regval[1]); + regval += 2; + REG_SET_2(CM_COMA_C21_C22, 0, + CM_COMA_C21, regval[0], + CM_COMA_C22, regval[1]); + regval += 2; + REG_SET_2(CM_COMA_C23_C24, 0, + CM_COMA_C23, regval[0], + CM_COMA_C24, regval[1]); + regval += 2; + REG_SET_2(CM_COMA_C31_C32, 0, + CM_COMA_C31, regval[0], + CM_COMA_C32, regval[1]); + regval += 2; + REG_SET_2(CM_COMA_C33_C34, 0, + CM_COMA_C33, regval[0], + CM_COMA_C34, regval[1]); + + } else { + REG_SET_2(CM_COMB_C11_C12, 0, + CM_COMB_C11, regval[0], + CM_COMB_C12, regval[1]); + regval += 2; + REG_SET_2(CM_COMB_C13_C14, 0, + CM_COMB_C13, regval[0], + CM_COMB_C14, regval[1]); + regval += 2; + REG_SET_2(CM_COMB_C21_C22, 0, + CM_COMB_C21, regval[0], + CM_COMB_C22, regval[1]); + regval += 2; + REG_SET_2(CM_COMB_C23_C24, 0, + CM_COMB_C23, regval[0], + CM_COMB_C24, regval[1]); + regval += 2; + REG_SET_2(CM_COMB_C31_C32, 0, + CM_COMB_C31, regval[0], + CM_COMB_C32, regval[1]); + regval += 2; + REG_SET_2(CM_COMB_C33_C34, 0, + CM_COMB_C33, regval[0], + CM_COMB_C34, regval[1]); + } + + REG_SET( + CM_GAMUT_REMAP_CONTROL, 0, + CM_GAMUT_REMAP_MODE, selection); + +} + +void dcn_dpp_set_gamut_remap( + struct transform *xfm, + const struct xfm_grph_csc_adjustment *adjust) +{ + struct dcn10_dpp *dcn_xfm = TO_DCN10_DPP(xfm); + + if (adjust->gamut_adjust_type != GRAPHICS_GAMUT_ADJUST_TYPE_SW) + /* Bypass if type is bypass or hw */ + program_gamut_remap(dcn_xfm, NULL, GAMUT_REMAP_BYPASS); + else { + struct fixed31_32 arr_matrix[12]; + uint16_t arr_reg_val[12]; + + arr_matrix[0] = adjust->temperature_matrix[0]; + arr_matrix[1] = adjust->temperature_matrix[1]; + arr_matrix[2] = adjust->temperature_matrix[2]; + arr_matrix[3] = dal_fixed31_32_zero; + + arr_matrix[4] = adjust->temperature_matrix[3]; + arr_matrix[5] = adjust->temperature_matrix[4]; + arr_matrix[6] = adjust->temperature_matrix[5]; + arr_matrix[7] = dal_fixed31_32_zero; + + arr_matrix[8] = adjust->temperature_matrix[6]; + arr_matrix[9] = adjust->temperature_matrix[7]; + arr_matrix[10] = adjust->temperature_matrix[8]; + arr_matrix[11] = dal_fixed31_32_zero; + + convert_float_matrix( + arr_reg_val, arr_matrix, 12); + + program_gamut_remap(dcn_xfm, arr_reg_val, GAMUT_REMAP_COEFF); + } +} + +void oppn10_set_output_csc_default( + struct transform *xfm_base, + const struct default_adjustment *default_adjust) +{ + + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + uint32_t ocsc_mode = 0; + + if (default_adjust != NULL) { + switch (default_adjust->out_color_space) { + case COLOR_SPACE_SRGB: + case COLOR_SPACE_2020_RGB_FULLRANGE: + ocsc_mode = 0; + break; + case COLOR_SPACE_SRGB_LIMITED: + case COLOR_SPACE_2020_RGB_LIMITEDRANGE: + ocsc_mode = 1; + break; + case COLOR_SPACE_YCBCR601: + case COLOR_SPACE_YCBCR601_LIMITED: + ocsc_mode = 2; + break; + case COLOR_SPACE_YCBCR709: + case COLOR_SPACE_YCBCR709_LIMITED: + case COLOR_SPACE_2020_YCBCR: + ocsc_mode = 3; + break; + case COLOR_SPACE_UNKNOWN: + default: + break; + } + } + + REG_SET(CM_OCSC_CONTROL, 0, CM_OCSC_MODE, ocsc_mode); + +} + +static void oppn10_program_color_matrix( + struct dcn10_dpp *xfm, + const struct out_csc_color_matrix *tbl_entry) +{ + uint32_t mode; + + REG_GET(CM_OCSC_CONTROL, CM_OCSC_MODE, &mode); + + if (tbl_entry == NULL) { + BREAK_TO_DEBUGGER(); + return; + } + + if (mode == 4) { + /*R*/ + REG_SET_2(CM_OCSC_C11_C12, 0, + CM_OCSC_C11, tbl_entry->regval[0], + CM_OCSC_C12, tbl_entry->regval[1]); + + REG_SET_2(CM_OCSC_C13_C14, 0, + CM_OCSC_C13, tbl_entry->regval[2], + CM_OCSC_C14, tbl_entry->regval[3]); + + /*G*/ + REG_SET_2(CM_OCSC_C21_C22, 0, + CM_OCSC_C21, tbl_entry->regval[4], + CM_OCSC_C22, tbl_entry->regval[5]); + + REG_SET_2(CM_OCSC_C23_C24, 0, + CM_OCSC_C23, tbl_entry->regval[6], + CM_OCSC_C24, tbl_entry->regval[7]); + + /*B*/ + REG_SET_2(CM_OCSC_C31_C32, 0, + CM_OCSC_C31, tbl_entry->regval[8], + CM_OCSC_C32, tbl_entry->regval[9]); + + REG_SET_2(CM_OCSC_C33_C34, 0, + CM_OCSC_C33, tbl_entry->regval[10], + CM_OCSC_C34, tbl_entry->regval[11]); + } else { + /*R*/ + REG_SET_2(CM_COMB_C11_C12, 0, + CM_COMB_C11, tbl_entry->regval[0], + CM_COMB_C12, tbl_entry->regval[1]); + + REG_SET_2(CM_COMB_C13_C14, 0, + CM_COMB_C13, tbl_entry->regval[2], + CM_COMB_C14, tbl_entry->regval[3]); + + /*G*/ + REG_SET_2(CM_COMB_C21_C22, 0, + CM_COMB_C21, tbl_entry->regval[4], + CM_COMB_C22, tbl_entry->regval[5]); + + REG_SET_2(CM_COMB_C23_C24, 0, + CM_COMB_C23, tbl_entry->regval[6], + CM_COMB_C24, tbl_entry->regval[7]); + + /*B*/ + REG_SET_2(CM_COMB_C31_C32, 0, + CM_COMB_C31, tbl_entry->regval[8], + CM_COMB_C32, tbl_entry->regval[9]); + + REG_SET_2(CM_COMB_C33_C34, 0, + CM_COMB_C33, tbl_entry->regval[10], + CM_COMB_C34, tbl_entry->regval[11]); + } +} + +void oppn10_set_output_csc_adjustment( + struct transform *xfm_base, + const struct out_csc_color_matrix *tbl_entry) +{ + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + //enum csc_color_mode config = CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; + uint32_t ocsc_mode = 4; + + /** + *if (tbl_entry != NULL) { + * switch (tbl_entry->color_space) { + * case COLOR_SPACE_SRGB: + * case COLOR_SPACE_2020_RGB_FULLRANGE: + * ocsc_mode = 0; + * break; + * case COLOR_SPACE_SRGB_LIMITED: + * case COLOR_SPACE_2020_RGB_LIMITEDRANGE: + * ocsc_mode = 1; + * break; + * case COLOR_SPACE_YCBCR601: + * case COLOR_SPACE_YCBCR601_LIMITED: + * ocsc_mode = 2; + * break; + * case COLOR_SPACE_YCBCR709: + * case COLOR_SPACE_YCBCR709_LIMITED: + * case COLOR_SPACE_2020_YCBCR: + * ocsc_mode = 3; + * break; + * case COLOR_SPACE_UNKNOWN: + * default: + * break; + * } + *} + */ + + REG_SET(CM_OCSC_CONTROL, 0, CM_OCSC_MODE, ocsc_mode); + oppn10_program_color_matrix(xfm, tbl_entry); +} + +void oppn10_power_on_regamma_lut( + struct transform *xfm_base, + bool power_on) +{ + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + REG_SET(CM_MEM_PWR_CTRL, 0, + RGAM_MEM_PWR_FORCE, power_on == true ? 0:1); + +} + +void opp_program_regamma_lut( + struct transform *xfm_base, + const struct pwl_result_data *rgb, + uint32_t num) +{ + uint32_t i; + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + for (i = 0 ; i < num; i++) { + REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].red_reg); + REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].green_reg); + REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].blue_reg); + + REG_SET(CM_RGAM_LUT_DATA, 0, + CM_RGAM_LUT_DATA, rgb[i].delta_red_reg); + REG_SET(CM_RGAM_LUT_DATA, 0, + CM_RGAM_LUT_DATA, rgb[i].delta_green_reg); + REG_SET(CM_RGAM_LUT_DATA, 0, + CM_RGAM_LUT_DATA, rgb[i].delta_blue_reg); + + } + +} + +void opp_configure_regamma_lut( + struct transform *xfm_base, + bool is_ram_a) +{ + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + + REG_UPDATE(CM_RGAM_LUT_WRITE_EN_MASK, + CM_RGAM_LUT_WRITE_EN_MASK, 7); + REG_UPDATE(CM_RGAM_LUT_WRITE_EN_MASK, + CM_RGAM_LUT_WRITE_SEL, is_ram_a == true ? 0:1); + REG_SET(CM_RGAM_LUT_INDEX, 0, CM_RGAM_LUT_INDEX, 0); +} + +/*program re gamma RAM A*/ +void opp_program_regamma_luta_settings( + struct transform *xfm_base, + const struct pwl_params *params) +{ + const struct gamma_curve *curve; + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + + REG_SET_2(CM_RGAM_RAMA_START_CNTL_B, 0, + CM_RGAM_RAMA_EXP_REGION_START_B, params->arr_points[0].custom_float_x, + CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_B, 0); + REG_SET_2(CM_RGAM_RAMA_START_CNTL_G, 0, + CM_RGAM_RAMA_EXP_REGION_START_G, params->arr_points[0].custom_float_x, + CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_G, 0); + REG_SET_2(CM_RGAM_RAMA_START_CNTL_R, 0, + CM_RGAM_RAMA_EXP_REGION_START_R, params->arr_points[0].custom_float_x, + CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_R, 0); + + REG_SET(CM_RGAM_RAMA_SLOPE_CNTL_B, 0, + CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B, params->arr_points[0].custom_float_slope); + REG_SET(CM_RGAM_RAMA_SLOPE_CNTL_G, 0, + CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G, params->arr_points[0].custom_float_slope); + REG_SET(CM_RGAM_RAMA_SLOPE_CNTL_R, 0, + CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R, params->arr_points[0].custom_float_slope); + + REG_SET(CM_RGAM_RAMA_END_CNTL1_B, 0, + CM_RGAM_RAMA_EXP_REGION_END_B, params->arr_points[1].custom_float_x); + REG_SET_2(CM_RGAM_RAMA_END_CNTL2_B, 0, + CM_RGAM_RAMA_EXP_REGION_END_SLOPE_B, params->arr_points[1].custom_float_slope, + CM_RGAM_RAMA_EXP_REGION_END_BASE_B, params->arr_points[1].custom_float_y); + + REG_SET(CM_RGAM_RAMA_END_CNTL1_G, 0, + CM_RGAM_RAMA_EXP_REGION_END_G, params->arr_points[1].custom_float_x); + REG_SET_2(CM_RGAM_RAMA_END_CNTL2_G, 0, + CM_RGAM_RAMA_EXP_REGION_END_SLOPE_G, params->arr_points[1].custom_float_slope, + CM_RGAM_RAMA_EXP_REGION_END_BASE_G, params->arr_points[1].custom_float_y); + + REG_SET(CM_RGAM_RAMA_END_CNTL1_R, 0, + CM_RGAM_RAMA_EXP_REGION_END_R, params->arr_points[1].custom_float_x); + REG_SET_2(CM_RGAM_RAMA_END_CNTL2_R, 0, + CM_RGAM_RAMA_EXP_REGION_END_SLOPE_R, params->arr_points[1].custom_float_slope, + CM_RGAM_RAMA_EXP_REGION_END_BASE_R, params->arr_points[1].custom_float_y); + + curve = params->arr_curve_points; + REG_SET_4(CM_RGAM_RAMA_REGION_0_1, 0, + CM_RGAM_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_2_3, 0, + CM_RGAM_RAMA_EXP_REGION2_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION3_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_4_5, 0, + CM_RGAM_RAMA_EXP_REGION4_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION5_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_6_7, 0, + CM_RGAM_RAMA_EXP_REGION6_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION7_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_8_9, 0, + CM_RGAM_RAMA_EXP_REGION8_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION9_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_10_11, 0, + CM_RGAM_RAMA_EXP_REGION10_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION11_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_12_13, 0, + CM_RGAM_RAMA_EXP_REGION12_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION13_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_14_15, 0, + CM_RGAM_RAMA_EXP_REGION14_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION15_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_16_17, 0, + CM_RGAM_RAMA_EXP_REGION16_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION16_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION17_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION17_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_18_19, 0, + CM_RGAM_RAMA_EXP_REGION18_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION18_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION19_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION19_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_20_21, 0, + CM_RGAM_RAMA_EXP_REGION20_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION20_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION21_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION21_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_22_23, 0, + CM_RGAM_RAMA_EXP_REGION22_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION22_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION23_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION23_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_24_25, 0, + CM_RGAM_RAMA_EXP_REGION24_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION24_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION25_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION25_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_26_27, 0, + CM_RGAM_RAMA_EXP_REGION26_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION26_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION27_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION27_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_28_29, 0, + CM_RGAM_RAMA_EXP_REGION28_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION28_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION29_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION29_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_30_31, 0, + CM_RGAM_RAMA_EXP_REGION30_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION30_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION31_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION31_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_32_33, 0, + CM_RGAM_RAMA_EXP_REGION32_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION32_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION33_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION33_NUM_SEGMENTS, curve[1].segments_num); +} + +/*program re gamma RAM B*/ +void opp_program_regamma_lutb_settings( + struct transform *xfm_base, + const struct pwl_params *params) +{ + const struct gamma_curve *curve; + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + + REG_SET_2(CM_RGAM_RAMB_START_CNTL_B, 0, + CM_RGAM_RAMB_EXP_REGION_START_B, params->arr_points[0].custom_float_x, + CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B, 0); + REG_SET_2(CM_RGAM_RAMB_START_CNTL_G, 0, + CM_RGAM_RAMB_EXP_REGION_START_G, params->arr_points[0].custom_float_x, + CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_G, 0); + REG_SET_2(CM_RGAM_RAMB_START_CNTL_R, 0, + CM_RGAM_RAMB_EXP_REGION_START_R, params->arr_points[0].custom_float_x, + CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_R, 0); + + REG_SET(CM_RGAM_RAMB_SLOPE_CNTL_B, 0, + CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B, params->arr_points[0].custom_float_slope); + REG_SET(CM_RGAM_RAMB_SLOPE_CNTL_G, 0, + CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_G, params->arr_points[0].custom_float_slope); + REG_SET(CM_RGAM_RAMB_SLOPE_CNTL_R, 0, + CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_R, params->arr_points[0].custom_float_slope); + + REG_SET(CM_RGAM_RAMB_END_CNTL1_B, 0, + CM_RGAM_RAMB_EXP_REGION_END_B, params->arr_points[1].custom_float_x); + REG_SET_2(CM_RGAM_RAMB_END_CNTL2_B, 0, + CM_RGAM_RAMB_EXP_REGION_END_SLOPE_B, params->arr_points[1].custom_float_slope, + CM_RGAM_RAMB_EXP_REGION_END_BASE_B, params->arr_points[1].custom_float_y); + + REG_SET(CM_RGAM_RAMB_END_CNTL1_G, 0, + CM_RGAM_RAMB_EXP_REGION_END_G, params->arr_points[1].custom_float_x); + REG_SET_2(CM_RGAM_RAMB_END_CNTL2_G, 0, + CM_RGAM_RAMB_EXP_REGION_END_SLOPE_G, params->arr_points[1].custom_float_slope, + CM_RGAM_RAMB_EXP_REGION_END_BASE_G, params->arr_points[1].custom_float_y); + + REG_SET(CM_RGAM_RAMB_END_CNTL1_R, 0, + CM_RGAM_RAMB_EXP_REGION_END_R, params->arr_points[1].custom_float_x); + REG_SET_2(CM_RGAM_RAMB_END_CNTL2_R, 0, + CM_RGAM_RAMB_EXP_REGION_END_SLOPE_R, params->arr_points[1].custom_float_slope, + CM_RGAM_RAMB_EXP_REGION_END_BASE_R, params->arr_points[1].custom_float_y); + + curve = params->arr_curve_points; + REG_SET_4(CM_RGAM_RAMB_REGION_0_1, 0, + CM_RGAM_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_2_3, 0, + CM_RGAM_RAMB_EXP_REGION2_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION3_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_4_5, 0, + CM_RGAM_RAMB_EXP_REGION4_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION5_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_6_7, 0, + CM_RGAM_RAMB_EXP_REGION6_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION7_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_8_9, 0, + CM_RGAM_RAMB_EXP_REGION8_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION9_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_10_11, 0, + CM_RGAM_RAMB_EXP_REGION10_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION11_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_12_13, 0, + CM_RGAM_RAMB_EXP_REGION12_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION13_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_14_15, 0, + CM_RGAM_RAMB_EXP_REGION14_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION15_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_16_17, 0, + CM_RGAM_RAMB_EXP_REGION16_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION16_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION17_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION17_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_18_19, 0, + CM_RGAM_RAMB_EXP_REGION18_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION18_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION19_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION19_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_20_21, 0, + CM_RGAM_RAMB_EXP_REGION20_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION20_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION21_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION21_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_22_23, 0, + CM_RGAM_RAMB_EXP_REGION22_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION22_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION23_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION23_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_24_25, 0, + CM_RGAM_RAMB_EXP_REGION24_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION24_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION25_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION25_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_26_27, 0, + CM_RGAM_RAMB_EXP_REGION26_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION26_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION27_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION27_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_28_29, 0, + CM_RGAM_RAMB_EXP_REGION28_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION28_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION29_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION29_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_30_31, 0, + CM_RGAM_RAMB_EXP_REGION30_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION30_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION31_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION31_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_32_33, 0, + CM_RGAM_RAMB_EXP_REGION32_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION32_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION33_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION33_NUM_SEGMENTS, curve[1].segments_num); + +} -- cgit From 3f1f74f436798a54b6ebcacfc026ddc4347eab46 Mon Sep 17 00:00:00 2001 From: Jerry Zuo Date: Thu, 17 Aug 2017 16:05:37 -0400 Subject: drm/amd/display: Fix two MST not light up regressions 1. Change 100104: Move verify link cap after read edid causes MST link_cap struct not being set. It leads to zero denominator pbn_per_slot value, leading to the crash at dal_fixed31_32_div(). Skip MST link training for now and will need to add MST specific link traning routine later. 2. Change 98822: Adding edp supports changes link setting condition from max_link to verified_link. It leads to MST is getting wrong link settings. e.g. LINK_SPREAD_05_DOWNSPREAD_30KHZ not set in MST case Signed-off-by: Jerry Zuo Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 16 +++++++++------- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 8 ++++++++ 2 files changed, 17 insertions(+), 7 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index cab54afa1131..ee9b98472029 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -607,6 +607,12 @@ bool dc_link_detect(struct dc_link *link, bool boot) if (link->type == dc_connection_mst_branch) { LINK_INFO("link=%d, mst branch is now Connected\n", link->link_index); + /* Need to setup mst link_cap struct here + * otherwise dc_link_detect() will leave mst link_cap + * empty which leads to allocate_mst_payload() has "0" + * pbn_per_slot value leading to exception on dal_fixed31_32_div() + */ + link->verified_link_cap = link->reported_link_cap; return false; } @@ -672,13 +678,9 @@ bool dc_link_detect(struct dc_link *link, bool boot) * TODO debug why Dell 2413 doesn't like * two link trainings */ - if (is_mst_supported(link)) { - link->verified_link_cap = - link->reported_link_cap; - } else { - dp_hbr_verify_link_cap(link, - &link->reported_link_cap); - } + + /* deal with non-mst cases */ + dp_hbr_verify_link_cap(link, &link->reported_link_cap); } /* HDMI-DVI Dongle */ 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 d621237e923e..e35bdce6a0f3 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 @@ -1459,6 +1459,14 @@ void decide_link_settings(struct dc_stream_state *stream, return; } + /* MST doesn't perform link training for now + * TODO: add MST specific link training routine + */ + if (is_mst_supported(link)) { + *link_setting = link->verified_link_cap; + return; + } + /* search for the minimum link setting that: * 1. is supported according to the link training result * 2. could support the b/w requested by the timing -- cgit From 79c24086570953e10f2c5c08946619a9a0f71ee9 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Thu, 17 Aug 2017 17:00:47 -0400 Subject: drm/amd/display: Disable stutter for Raven Signed-off-by: Bhawanpreet Lakha Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/gpu') 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 4bb78f76acce..e037ed85a5cc 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1383,6 +1383,10 @@ int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) DRM_ERROR("DM: Failed to initialize IRQ\n"); goto fail_free_encoder; } + /* + * Temporary disable until pplib/smu interaction is implemented + */ + dm->dc->debug.disable_stutter = true; break; #endif default: -- cgit From f670af8a954ae09b1f4949421e5d300be66d1156 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 17 Aug 2017 14:57:27 -0400 Subject: drm/amd/display: Remove unnecessary assignemnt Signed-off-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 5e4f7f08e3db..aaa6d2326190 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -41,7 +41,6 @@ static bool construct(struct dc_stream_state *stream, stream->sink = dc_sink_data; stream->ctx = stream->sink->ctx; - stream->sink = dc_sink_data; dc_sink_retain(dc_sink_data); -- cgit From 8eb5def95762dc1cd9e516510925a95060452c5a Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 28 Jul 2017 08:16:27 -0400 Subject: drm/amd/display: fix hubp mpcc and opp tracking This should be handled by mi and mpc only Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c | 2 ++ drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 6 ++---- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c | 3 +-- 3 files changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c index 627669749740..83d9caa4f438 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c @@ -686,6 +686,8 @@ void dce_mem_input_construct( dce_mi->shifts = mi_shift; dce_mi->masks = mi_mask; + dce_mi->base.mpcc_id = 0xf; + dce_mi->base.opp_id = 0xf; } void dce112_mem_input_construct( diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index ddfa6a8d087b..69f67f6e27b1 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1066,9 +1066,6 @@ static void plane_atomic_disable(struct dc *dc, fe_idx);*/ mi->funcs->set_blank(mi, true); - /*todo: unhack this*/ - mi->opp_id = 0xf; - mi->mpcc_id = 0xf; if (dc->debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); @@ -2304,7 +2301,8 @@ static void update_dchubp_dpp( &plane_state->dcc, plane_state->horizontal_mirror); - mi->funcs->set_blank(mi, !is_pipe_tree_visible(pipe_ctx)); + if (is_pipe_tree_visible(pipe_ctx)) + mi->funcs->set_blank(mi, false); } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index 11daf6b5c7d8..0a47e6ad4286 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -51,9 +51,8 @@ static void min10_set_blank(struct mem_input *mem_input, bool blank) REG_WAIT(DCHUBP_CNTL, HUBP_NO_OUTSTANDING_REQ, 1, 1, 200); - /*todo: unhack this mem_input->mpcc_id = 0xf; - mem_input->opp_id = 0xf;*/ + mem_input->opp_id = 0xf; } } -- cgit From b823defeb73aa8737006abe73844fd697ecf6983 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 28 Jul 2017 08:16:27 -0400 Subject: drm/amd/display: Fixed mpc add, enable always scaler for video surface. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c | 6 +++--- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 4 ++++ 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c index 52f2f2dd9a43..ce408ccb428e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c @@ -229,9 +229,9 @@ static void mpc10_mpcc_add(struct mpc *mpc, struct mpcc_cfg *cfg) mpc10_set_bg_color(mpc10, &cfg->black_color, mpcc_id); mpc10->mpcc_in_use_mask |= 1 << mpcc_id; - for (z_idx = cfg->z_index; z_idx < cfg->opp->mpc_tree.num_pipes; z_idx++) { - cfg->opp->mpc_tree.dpp[z_idx + 1] = cfg->opp->mpc_tree.dpp[z_idx]; - cfg->opp->mpc_tree.mpcc[z_idx + 1] = cfg->opp->mpc_tree.mpcc[z_idx]; + for (z_idx = cfg->opp->mpc_tree.num_pipes; z_idx > cfg->z_index; z_idx--) { + cfg->opp->mpc_tree.dpp[z_idx] = cfg->opp->mpc_tree.dpp[z_idx - 1]; + cfg->opp->mpc_tree.mpcc[z_idx] = cfg->opp->mpc_tree.mpcc[z_idx - 1]; } cfg->opp->mpc_tree.dpp[cfg->z_index] = cfg->mi->inst; cfg->opp->mpc_tree.mpcc[cfg->z_index] = mpcc_id; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index ee43cbc70c8a..9c7ec047f083 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -422,6 +422,10 @@ static const struct dc_debug debug_defaults_drv = { .force_abm_enable = false, .timing_trace = false, .clock_trace = true, + /* spread sheet doesn't handle taps_c is one properly, + * need to enable scaler for video surface to pass + * bandwidth validation.*/ + .always_scale = true, .disable_pplib_clock_request = true, .disable_pplib_wm_range = false, #if defined(CONFIG_DRM_AMD_DC_DCN1_0) -- cgit From 58314e5812d5027edb01e0d20cf72068c95a7c10 Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Sat, 19 Aug 2017 12:10:28 -0400 Subject: drm/amd/display: cleanup naming of DCN DPP functions Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c | 41 +++++++++++----------- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h | 25 ++++++++----- .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c | 20 +++++------ .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c | 2 +- 4 files changed, 48 insertions(+), 40 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c index f0e74afc4518..30722495de0a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c @@ -123,7 +123,7 @@ void dpp_set_gamut_remap_bypass(struct dcn10_dpp *xfm) #define IDENTITY_RATIO(ratio) (dal_fixed31_32_u2d19(ratio) == (1 << 19)) -static bool dpp_get_optimal_number_of_taps( +bool dpp_get_optimal_number_of_taps( struct transform *xfm, struct scaler_data *scl_data, const struct scaling_taps *in_taps) @@ -182,7 +182,7 @@ static bool dpp_get_optimal_number_of_taps( return true; } -static void dpp_reset(struct transform *xfm_base) +void dpp_reset(struct transform *xfm_base) { struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); @@ -197,26 +197,26 @@ static void dpp_reset(struct transform *xfm_base) -static bool oppn10_set_regamma_pwl( +static bool dcn10_dpp_cm_set_regamma_pwl( struct transform *xfm_base, const struct pwl_params *params) { struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); - oppn10_power_on_regamma_lut(xfm_base, true); - opp_configure_regamma_lut(xfm_base, xfm->is_write_to_ram_a_safe); + dcn10_dpp_cm_power_on_regamma_lut(xfm_base, true); + dcn10_dpp_cm_configure_regamma_lut(xfm_base, xfm->is_write_to_ram_a_safe); if (xfm->is_write_to_ram_a_safe) - opp_program_regamma_luta_settings(xfm_base, params); + dcn10_dpp_cm_program_regamma_luta_settings(xfm_base, params); else - opp_program_regamma_lutb_settings(xfm_base, params); + dcn10_dpp_cm_program_regamma_lutb_settings(xfm_base, params); - opp_program_regamma_lut( + dcn10_dpp_cm_program_regamma_lut( xfm_base, params->rgb_resulted, params->hw_points_num); return true; } -static void oppn10_set_regamma_mode( +static void dcn10_dpp_cm_set_regamma_mode( struct transform *xfm_base, enum opp_regamma mode) { @@ -251,20 +251,21 @@ static void oppn10_set_regamma_mode( static struct transform_funcs dcn10_dpp_funcs = { .transform_reset = dpp_reset, - .transform_set_scaler = dcn10_dpp_set_scaler_manual_scale, + .transform_set_scaler = dcn10_dpp_dscl_set_scaler_manual_scale, .transform_get_optimal_number_of_taps = dpp_get_optimal_number_of_taps, - .transform_set_gamut_remap = dcn_dpp_set_gamut_remap, - .opp_set_csc_adjustment = oppn10_set_output_csc_adjustment, - .opp_set_csc_default = oppn10_set_output_csc_default, - .opp_power_on_regamma_lut = oppn10_power_on_regamma_lut, - .opp_program_regamma_lut = opp_program_regamma_lut, - .opp_configure_regamma_lut = opp_configure_regamma_lut, - .opp_program_regamma_lutb_settings = opp_program_regamma_lutb_settings, - .opp_program_regamma_luta_settings = opp_program_regamma_luta_settings, - .opp_program_regamma_pwl = oppn10_set_regamma_pwl, - .opp_set_regamma_mode = oppn10_set_regamma_mode, + .transform_set_gamut_remap = dcn10_dpp_cm_set_gamut_remap, + .opp_set_csc_adjustment = dcn10_dpp_cm_set_output_csc_adjustment, + .opp_set_csc_default = dcn10_dpp_cm_set_output_csc_default, + .opp_power_on_regamma_lut = dcn10_dpp_cm_power_on_regamma_lut, + .opp_program_regamma_lut = dcn10_dpp_cm_program_regamma_lut, + .opp_configure_regamma_lut = dcn10_dpp_cm_configure_regamma_lut, + .opp_program_regamma_lutb_settings = dcn10_dpp_cm_program_regamma_lutb_settings, + .opp_program_regamma_luta_settings = dcn10_dpp_cm_program_regamma_luta_settings, + .opp_program_regamma_pwl = dcn10_dpp_cm_set_regamma_pwl, + .opp_set_regamma_mode = dcn10_dpp_cm_set_regamma_mode, }; + /*****************************************/ /* Constructor, Destructor */ /*****************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h index a4dfdb9b4d69..18ee338f6b28 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h @@ -1387,41 +1387,48 @@ struct dcn10_dpp { bool is_write_to_ram_a_safe; }; -void opp_program_regamma_lut( +bool dpp_get_optimal_number_of_taps( + struct transform *xfm, + struct scaler_data *scl_data, + const struct scaling_taps *in_taps); + +void dpp_reset(struct transform *xfm_base); + +void dcn10_dpp_cm_program_regamma_lut( struct transform *xfm_base, const struct pwl_result_data *rgb, uint32_t num); -void oppn10_power_on_regamma_lut( +void dcn10_dpp_cm_power_on_regamma_lut( struct transform *xfm_base, bool power_on); -void opp_configure_regamma_lut( +void dcn10_dpp_cm_configure_regamma_lut( struct transform *xfm_base, bool is_ram_a); /*program re gamma RAM A*/ -void opp_program_regamma_luta_settings( +void dcn10_dpp_cm_program_regamma_luta_settings( struct transform *xfm_base, const struct pwl_params *params); /*program re gamma RAM B*/ -void opp_program_regamma_lutb_settings( +void dcn10_dpp_cm_program_regamma_lutb_settings( struct transform *xfm_base, const struct pwl_params *params); -void oppn10_set_output_csc_adjustment( +void dcn10_dpp_cm_set_output_csc_adjustment( struct transform *xfm_base, const struct out_csc_color_matrix *tbl_entry); -void oppn10_set_output_csc_default( +void dcn10_dpp_cm_set_output_csc_default( struct transform *xfm_base, const struct default_adjustment *default_adjust); -void dcn_dpp_set_gamut_remap( +void dcn10_dpp_cm_set_gamut_remap( struct transform *xfm, const struct xfm_grph_csc_adjustment *adjust); -void dcn10_dpp_set_scaler_manual_scale( +void dcn10_dpp_dscl_set_scaler_manual_scale( struct transform *xfm_base, const struct scaler_data *scl_data); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c index 7eb4334c30fc..9ff283bff007 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c @@ -221,7 +221,7 @@ static void program_gamut_remap( } -void dcn_dpp_set_gamut_remap( +void dcn10_dpp_cm_set_gamut_remap( struct transform *xfm, const struct xfm_grph_csc_adjustment *adjust) { @@ -256,7 +256,7 @@ void dcn_dpp_set_gamut_remap( } } -void oppn10_set_output_csc_default( +void dcn10_dpp_cm_set_output_csc_default( struct transform *xfm_base, const struct default_adjustment *default_adjust) { @@ -293,7 +293,7 @@ void oppn10_set_output_csc_default( } -static void oppn10_program_color_matrix( +static void dcn10_dpp_cm_program_color_matrix( struct dcn10_dpp *xfm, const struct out_csc_color_matrix *tbl_entry) { @@ -363,7 +363,7 @@ static void oppn10_program_color_matrix( } } -void oppn10_set_output_csc_adjustment( +void dcn10_dpp_cm_set_output_csc_adjustment( struct transform *xfm_base, const struct out_csc_color_matrix *tbl_entry) { @@ -399,10 +399,10 @@ void oppn10_set_output_csc_adjustment( */ REG_SET(CM_OCSC_CONTROL, 0, CM_OCSC_MODE, ocsc_mode); - oppn10_program_color_matrix(xfm, tbl_entry); + dcn10_dpp_cm_program_color_matrix(xfm, tbl_entry); } -void oppn10_power_on_regamma_lut( +void dcn10_dpp_cm_power_on_regamma_lut( struct transform *xfm_base, bool power_on) { @@ -412,7 +412,7 @@ void oppn10_power_on_regamma_lut( } -void opp_program_regamma_lut( +void dcn10_dpp_cm_program_regamma_lut( struct transform *xfm_base, const struct pwl_result_data *rgb, uint32_t num) @@ -435,7 +435,7 @@ void opp_program_regamma_lut( } -void opp_configure_regamma_lut( +void dcn10_dpp_cm_configure_regamma_lut( struct transform *xfm_base, bool is_ram_a) { @@ -449,7 +449,7 @@ void opp_configure_regamma_lut( } /*program re gamma RAM A*/ -void opp_program_regamma_luta_settings( +void dcn10_dpp_cm_program_regamma_luta_settings( struct transform *xfm_base, const struct pwl_params *params) { @@ -612,7 +612,7 @@ void opp_program_regamma_luta_settings( } /*program re gamma RAM B*/ -void opp_program_regamma_lutb_settings( +void dcn10_dpp_cm_program_regamma_lutb_settings( struct transform *xfm_base, const struct pwl_params *params) { 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 95f014b5e7ed..76d5f5d4d82f 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 @@ -636,7 +636,7 @@ static void dpp_set_recout( } /* Main function to program scaler and line buffer in manual scaling mode */ -void dcn10_dpp_set_scaler_manual_scale( +void dcn10_dpp_dscl_set_scaler_manual_scale( struct transform *xfm_base, const struct scaler_data *scl_data) { -- cgit From 9ea29a1f8b9da52d8eca8b0996f1d84eac548d3b Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Sat, 19 Aug 2017 16:36:13 -0400 Subject: drm/amd/display: memory leak dwb Signed-off-by: Tony Cheng Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 9c7ec047f083..4af40f5138fc 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -747,6 +747,11 @@ static void destruct(struct dcn10_resource_pool *pool) dce_aud_destroy(&pool->base.audios[i]); } + for (i = 0; i < pool->base.res_cap->num_dwb; i++) { + dm_free(pool->base.dwbc[i]); + pool->base.dwbc[i] = NULL; + } + for (i = 0; i < pool->base.clk_src_count; i++) { if (pool->base.clock_sources[i] != NULL) { dcn10_clock_source_destroy(&pool->base.clock_sources[i]); -- cgit From 0045b749bdedc60ca46a7801cb9b5ae967bea669 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 22 Aug 2017 10:29:23 -0400 Subject: drm/amd/display: dc: Remove unneeded includes in DCN Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 69f67f6e27b1..54e37b10ffbf 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -39,9 +39,6 @@ #include "opp.h" #include "ipp.h" #include "mpc.h" -#include "raven1/DCN/dcn_1_0_offset.h" -#include "raven1/DCN/dcn_1_0_sh_mask.h" -#include "vega10/soc15ip.h" #include "reg_helper.h" #define CTX \ -- cgit From 4d1501eb65d606c05f28da12539cf0defd111f75 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Mon, 21 Aug 2017 11:00:25 -0400 Subject: drm/amd/display: Enable double buffer when unblank crtc. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c index 6a5f2683c2e5..cc58f43400d7 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c @@ -289,6 +289,9 @@ static void tgn10_unblank_crtc(struct timing_generator *tg) { struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + REG_UPDATE(OTG_DOUBLE_BUFFER_CONTROL, + OTG_BLANK_DATA_DOUBLE_BUFFER_EN, 1); + REG_UPDATE_2(OTG_BLANK_CONTROL, OTG_BLANK_DATA_EN, 0, OTG_BLANK_DE_MODE, 0); -- cgit From 7fb77c51f3b8e91499b6fd1973804c9230d2d8d3 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Sat, 19 Aug 2017 08:55:58 -0400 Subject: drm/amd/display: version 3.1.01 Signed-off-by: Tony Cheng Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 3 +++ drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 035c44e0e7d2..e6cea839d283 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -48,6 +48,9 @@ #include "dm_helpers.h" #include "mem_input.h" + +char dc_ver[] = DC_VER; + /******************************************************************************* * Private functions ******************************************************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index bd8b1ba22df8..caf585dbabb3 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -38,7 +38,7 @@ #include "inc/compressor.h" #include "dml/display_mode_lib.h" - +#define DC_VER "3.1.01" #define MAX_SURFACES 3 #define MAX_STREAMS 6 -- cgit From a0c38ebaa1fe99ea8d112d808d84a2e75194fcf6 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Mon, 21 Aug 2017 12:59:41 -0400 Subject: drm/amd/display: write dpcd 0x600 to 2 for DP/eDP when powerdown Signed-off-by: Charlene Liu Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 2 +- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 10 +++++++++- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h | 1 + 3 files changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index ee9b98472029..0bdd41ca8799 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1977,7 +1977,7 @@ bool dc_link_setup_psr(struct dc_link *link, #if defined(CONFIG_DRM_AMD_DC_DCN1_0) /*skip power down the single pipe since it blocks the cstate*/ if (ASIC_REV_IS_RAVEN(link->ctx->asic_id.hw_internal_rev)) - psr_context->psr_level.bits.SKIP_SINGLE_OTG_DISABLE = false; + psr_context->psr_level.bits.SKIP_CRTC_DISABLE = true; #endif /* SMU will perform additional powerdown sequence. diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 7516c198d13a..8ba61b9b8792 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1147,8 +1147,16 @@ static enum dc_status apply_single_controller_ctx_to_hw( static void power_down_encoders(struct dc *dc) { int i; - + enum connector_id connector_id; for (i = 0; i < dc->link_count; i++) { + connector_id = dal_graphics_object_id_get_connector_id(dc->links[i]->link_id); + if ((connector_id == CONNECTOR_ID_DISPLAY_PORT) || + (connector_id == CONNECTOR_ID_EDP)) { + + if (!dc->links[i]->wa_flags.dp_keep_receiver_powered) + dp_receiver_power_ctrl(dc->links[i], false); + } + dc->links[i]->link_enc->funcs->disable_output( dc->links[i]->link_enc, SIGNAL_TYPE_NONE); } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h index d710f6e6dc07..ac418fd83894 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h @@ -67,5 +67,6 @@ void dce110_fill_display_configs( uint32_t dce110_get_min_vblank_time_us(const struct validate_context *context); +void dp_receiver_power_ctrl(struct dc_link *link, bool on); #endif /* __DC_HWSS_DCE110_H__ */ -- cgit From 5f06b3cf90d252160352442a789cad410eb6696e Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Sun, 20 Aug 2017 14:25:19 -0400 Subject: drm/amd/display: retire dm_pp_apply_clock_for_voltage_request set dcfclk and fclk req with pp_smu_display_requirement_rv Signed-off-by: Tony Cheng Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 26 +++++++++++++--------- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 8 ++----- 2 files changed, 17 insertions(+), 17 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 54e37b10ffbf..20c4164a59d0 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2550,7 +2550,10 @@ static void dcn10_set_bandwidth( struct validate_context *context, bool decrease_allowed) { - struct dm_pp_clock_for_voltage_req clock; + struct pp_smu_display_requirement_rv *smu_req_cur = + &dc->res_pool->pp_smu_req; + struct pp_smu_display_requirement_rv smu_req = *smu_req_cur; + struct pp_smu_funcs_rv *pp_smu = dc->res_pool->pp_smu; if (dc->debug.sanity_checks) { verify_allow_pstate_change_high(dc->hwseq); @@ -2569,19 +2572,12 @@ static void dcn10_set_bandwidth( } if (decrease_allowed || context->bw.dcn.calc_clk.dcfclk_khz > dc->current_context->bw.dcn.cur_clk.dcfclk_khz) { - clock.clk_type = DM_PP_CLOCK_TYPE_DCFCLK; - clock.clocks_in_khz = context->bw.dcn.calc_clk.dcfclk_khz; - dm_pp_apply_clock_for_voltage_request(dc->ctx, &clock); - dc->current_context->bw.dcn.cur_clk.dcfclk_khz = clock.clocks_in_khz; - context->bw.dcn.cur_clk.dcfclk_khz = clock.clocks_in_khz; + smu_req.hard_min_dcefclk_khz = + context->bw.dcn.calc_clk.dcfclk_khz; } if (decrease_allowed || context->bw.dcn.calc_clk.fclk_khz > dc->current_context->bw.dcn.cur_clk.fclk_khz) { - clock.clk_type = DM_PP_CLOCK_TYPE_FCLK; - clock.clocks_in_khz = context->bw.dcn.calc_clk.fclk_khz; - dm_pp_apply_clock_for_voltage_request(dc->ctx, &clock); - dc->current_context->bw.dcn.calc_clk.fclk_khz = clock.clocks_in_khz; - context->bw.dcn.cur_clk.fclk_khz = clock.clocks_in_khz; + smu_req.hard_min_fclk_khz = context->bw.dcn.calc_clk.fclk_khz; } if (decrease_allowed || context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz > dc->current_context->bw.dcn.cur_clk.dcfclk_deep_sleep_khz) { @@ -2590,6 +2586,14 @@ static void dcn10_set_bandwidth( context->bw.dcn.cur_clk.dcfclk_deep_sleep_khz = context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz; } + + smu_req.display_count = context->stream_count; + + if (pp_smu->set_display_requirement) + pp_smu->set_display_requirement(&pp_smu->pp_smu, &smu_req); + + *smu_req_cur = smu_req; + /* Decrease in freq is increase in period so opposite comparison for dram_ccm */ if (decrease_allowed || context->bw.dcn.calc_clk.dram_ccm_us < dc->current_context->bw.dcn.cur_clk.dram_ccm_us) { diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 9a3239028377..62bd11d250c5 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -132,10 +132,10 @@ struct resource_pool { struct output_pixel_processor *opps[MAX_PIPES]; struct timing_generator *timing_generators[MAX_PIPES]; struct stream_encoder *stream_enc[MAX_PIPES * 2]; -#ifdef CONFIG_DRM_AMD_DC_DCN1_0 + struct mpc *mpc; struct pp_smu_funcs_rv *pp_smu; -#endif + struct pp_smu_display_requirement_rv pp_smu_req; struct dwbc *dwbc[MAX_DWB_PIPES]; @@ -234,7 +234,6 @@ struct dce_bw_output { int blackout_recovery_time_us; }; -#ifdef CONFIG_DRM_AMD_DC_DCN1_0 struct dcn_bw_clocks { int dispclk_khz; bool dppclk_div; @@ -250,12 +249,9 @@ struct dcn_bw_output { struct dcn_bw_clocks calc_clk; struct dcn_watermark_set watermarks; }; -#endif union bw_context { -#ifdef CONFIG_DRM_AMD_DC_DCN1_0 struct dcn_bw_output dcn; -#endif struct dce_bw_output dce; }; -- cgit From 39902db0343e0e4f335324d22d6707303be24448 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Mon, 21 Aug 2017 11:46:17 -0400 Subject: drm/amd/display: Change log level for DCN powergatting Change log level from LOG_DC to LOG_DEBUG LOG_DC spams dmesg on linux when hotpluging Signed-off-by: Bhawanpreet Lakha Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 20c4164a59d0..bd023299e2af 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -772,7 +772,7 @@ static void power_on_plane( hubp_pg_control(hws, plane_id, true); REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0); - dm_logger_write(hws->ctx->logger, LOG_DC, + dm_logger_write(hws->ctx->logger, LOG_DEBUG, "Un-gated front end for pipe %d\n", plane_id); } @@ -1003,7 +1003,7 @@ static void reset_back_end_for_pipe( return; pipe_ctx->stream = NULL; - dm_logger_write(dc->ctx->logger, LOG_DC, + dm_logger_write(dc->ctx->logger, LOG_DEBUG, "Reset back end for pipe %d, tg:%d\n", pipe_ctx->pipe_idx, pipe_ctx->stream_res.tg->inst); } @@ -1096,7 +1096,7 @@ static void plane_atomic_power_down(struct dc *dc, int fe_idx) xfm->funcs->transform_reset(xfm); REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0); - dm_logger_write(dc->ctx->logger, LOG_DC, + dm_logger_write(dc->ctx->logger, LOG_DEBUG, "Power gated front end %d\n", fe_idx); if (dc->debug.sanity_checks) @@ -1153,7 +1153,7 @@ static void dcn10_power_down_fe(struct dc *dc, int fe_idx) xfm->funcs->transform_reset(xfm); REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0); - dm_logger_write(dc->ctx->logger, LOG_DC, + dm_logger_write(dc->ctx->logger, LOG_DEBUG, "Power gated front end %d\n", fe_idx); if (dc->debug.sanity_checks) @@ -1921,7 +1921,7 @@ static void dcn10_power_on_fe( /*TODO: REG_UPDATE(DENTIST_DISPCLK_CNTL, DENTIST_DPPCLK_WDIVIDER, 0x1f);*/ if (plane_state) { - dm_logger_write(dc->ctx->logger, LOG_DC, + dm_logger_write(dc->ctx->logger, LOG_DEBUG, "Pipe:%d 0x%x: addr hi:0x%x, " "addr low:0x%x, " "src: %d, %d, %d," @@ -1939,7 +1939,7 @@ static void dcn10_power_on_fe( plane_state->dst_rect.width, plane_state->dst_rect.height); - dm_logger_write(dc->ctx->logger, LOG_HW_SET_MODE, + dm_logger_write(dc->ctx->logger, LOG_DEBUG, "Pipe %d: width, height, x, y\n" "viewport:%d, %d, %d, %d\n" "recout: %d, %d, %d, %d\n", -- cgit From c25e2d1f8ff403fdb7a82a025ae492d167bbdb99 Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Mon, 21 Aug 2017 16:43:08 -0400 Subject: drm/amd/display: retry LT on failing LT in automated request [Description] Link training is not retried in automated link training request. In case link training is occasionally failing, there is not way to retry so the requested lane settings will not set. Signed-off-by: Wenjing Liu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 3a5abd92036a..23d8b614e0fd 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -299,10 +299,11 @@ void dp_retrain_link_dp_test(struct dc_link *link, dp_receiver_power_ctrl(link, true); - dc_link_dp_perform_link_training( + perform_link_training_with_retries( link, link_setting, - skip_video_pattern); + skip_video_pattern, + LINK_TRAINING_ATTEMPTS); link->cur_link_settings = *link_setting; -- cgit From 83a3d42d121301d26601ef7599052e1d78fde9fb Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Mon, 21 Aug 2017 16:28:39 -0400 Subject: drm/amd/display: Remove unneeded code Signed-off-by: Bhawanpreet Lakha Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 145 ---------------------- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 73 ----------- drivers/gpu/drm/amd/display/dc/dc.h | 71 ----------- 3 files changed, 289 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index e6cea839d283..ab2b8f23b20a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -670,67 +670,6 @@ void dc_destroy(struct dc **dc) *dc = NULL; } -static bool validate_streams ( - struct dc *dc, - const struct dc_validation_set set[], - int set_count) -{ - int i; - - for (i = 0; i < set_count; i++) - if (!dc_validate_stream(dc, set[i].stream)) - return false; - - return true; -} - -static bool validate_surfaces( - struct dc *dc, - const struct dc_validation_set set[], - int set_count) -{ - int i, j; - - for (i = 0; i < set_count; i++) - for (j = 0; j < set[i].plane_count; j++) - if (!dc_validate_plane(dc, set[i].plane_states[j])) - return false; - - return true; -} - -bool dc_validate_resources( - struct dc *dc, - const struct dc_validation_set set[], - uint8_t set_count) -{ - bool result = false; - struct validate_context *context; - - if (!validate_streams(dc, set, set_count)) - return false; - - if (!validate_surfaces(dc, set, set_count)) - return false; - - context = dm_alloc(sizeof(struct validate_context)); - if (context == NULL) - goto context_alloc_fail; - - atomic_inc(&context->ref_count); - - dc_resource_validate_ctx_copy_construct_current(dc, context); - - result = dc_validate_with_context( - dc, set, set_count, context); - -context_alloc_fail: - dc_release_validate_context(context); - context = NULL; - - return result; -} - bool dc_validate_guaranteed( struct dc *dc, struct dc_stream_state *stream) @@ -855,24 +794,6 @@ static bool context_changed( return false; } -static bool streams_changed( - struct dc *dc, - struct dc_stream_state *streams[], - uint8_t stream_count) -{ - uint8_t i; - - if (stream_count != dc->current_context->stream_count) - return true; - - for (i = 0; i < dc->current_context->stream_count; i++) { - if (dc->current_context->streams[i] != streams[i]) - return true; - } - - return false; -} - bool dc_enable_stereo( struct dc *dc, struct validate_context *context, @@ -997,72 +918,6 @@ bool dc_commit_context(struct dc *dc, struct validate_context *context) } -bool dc_commit_streams( - struct dc *dc, - struct dc_stream_state *streams[], - uint8_t stream_count) -{ - struct dc *core_dc = dc; - bool result = false; - struct validate_context *context; - struct dc_validation_set set[MAX_STREAMS] = { {0, {0} } }; - int i; - - if (false == streams_changed(core_dc, streams, stream_count)) - return DC_OK; - - dm_logger_write(core_dc->ctx->logger, LOG_DC, "%s: %d streams\n", - __func__, stream_count); - - for (i = 0; i < stream_count; i++) { - struct dc_stream_state *stream = streams[i]; - struct dc_stream_status *status = dc_stream_get_status(stream); - int j; - - dc_stream_log(stream, - core_dc->ctx->logger, - LOG_DC); - - set[i].stream = stream; - - if (status) { - set[i].plane_count = status->plane_count; - for (j = 0; j < status->plane_count; j++) - set[i].plane_states[j] = status->plane_states[j]; - } - - } - - if (!validate_streams(dc, set, stream_count)) - return false; - - if (!validate_surfaces(dc, set, stream_count)) - return false; - - context = dm_alloc(sizeof(struct validate_context)); - if (context == NULL) - goto context_alloc_fail; - - atomic_inc(&context->ref_count); - - dc_resource_validate_ctx_copy_construct_current(dc, context); - - result = dc_validate_with_context( - dc, set, stream_count, context); - if (!result) { - BREAK_TO_DEBUGGER(); - goto fail; - } - - result = dc_commit_context_no_check(dc, context); - -fail: - dc_release_validate_context(context); - -context_alloc_fail: - return result; -} - bool dc_post_update_surfaces_to_stream(struct dc *dc) { int i; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index f640986c6fd2..428863bccab6 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1633,79 +1633,6 @@ void dc_resource_validate_ctx_copy_construct_current( dc_resource_validate_ctx_copy_construct(dc->current_context, dst_ctx); } -bool dc_validate_with_context( - struct dc *dc, - const struct dc_validation_set set[], - int set_count, - struct validate_context *context) -{ - int i, j; - enum dc_status res = DC_ERROR_UNEXPECTED; - bool found = false; - int old_stream_count = context->stream_count; - struct dc_stream_state *del_streams[MAX_PIPES] = { 0 }; - struct dc_stream_state *add_streams[MAX_PIPES] = { 0 }; - int del_streams_count = 0; - int add_streams_count = 0; - - - /* First remove from context all deleted streams */ - for (i = 0; i < old_stream_count; i++) { - struct dc_stream_state *stream = context->streams[i]; - - for (j = 0; j < set_count; j++) { - if (stream == set[j].stream) { - found = true; - break; - } - } - - if (!found) - del_streams[del_streams_count++] = stream; - - found = false; - } - - /* Now add new ones */ - for (i = 0; i < set_count; i++) { - struct dc_stream_state *stream = set[i].stream; - - for (j = 0; j < old_stream_count; j++) { - if (stream == context->streams[j]) { - found = true; - break; - } - } - - if (!found) - add_streams[add_streams_count++] = stream; - - found = false; - } - - for (i = 0; i < del_streams_count; i++) - if (!dc_remove_stream_from_ctx(dc, context, del_streams[i])) - goto fail; - - for (i = 0; i < add_streams_count; i++) - if (!dc_add_stream_to_ctx(dc, context, add_streams[i])) - goto fail; - - if (!dc_validate_global_state(dc, set, set_count, context)) - goto fail; - - res = DC_OK; - -fail: - if (res != DC_OK) { - dm_logger_write(dc->ctx->logger, LOG_WARNING, - "%s:resource validation failed, dc_status:%d\n", - __func__, - res); -} - return res == DC_OK; -} - bool dc_validate_global_state( struct dc *dc, const struct dc_validation_set set[], diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index caf585dbabb3..0f2a16a0cf82 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -641,23 +641,12 @@ bool dc_validate_stream(struct dc *dc, struct dc_stream_state *stream); bool dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state); -bool dc_validate_with_context( - struct dc *dc, - const struct dc_validation_set set[], - int set_count, - struct validate_context *context); - bool dc_validate_global_state( struct dc *dc, const struct dc_validation_set set[], int set_count, struct validate_context *new_ctx); -bool dc_validate_resources( - struct dc *dc, - const struct dc_validation_set set[], - uint8_t set_count); - /* * This function takes a stream and checks if it is guaranteed to be supported. * Guaranteed means that MAX_COFUNC similar streams are supported. @@ -666,10 +655,6 @@ bool dc_validate_resources( * No hardware is programmed for call. Only validation is done. */ -bool dc_validate_guaranteed( - struct dc *dc, - struct dc_stream_state *stream); - void dc_resource_validate_ctx_copy_construct( const struct validate_context *src_ctx, struct validate_context *dst_ctx); @@ -699,10 +684,6 @@ bool dc_commit_context(struct dc *dc, struct validate_context *context); * Phy, Encoder, Timing Generator are programmed and enabled. * New streams are enabled with blank stream; no memory read. */ -bool dc_commit_streams( - struct dc *dc, - struct dc_stream_state *streams[], - uint8_t stream_count); /* * Enable stereo when commit_streams is not required, * for example, frame alternate. @@ -857,18 +838,10 @@ const struct dc_link_status *dc_link_get_status(const struct dc_link *dc_link); */ struct dc_link *dc_get_link_at_index(struct dc *dc, uint32_t link_index); -struct dwbc *dc_get_dwb_at_pipe(struct dc *dc, uint32_t pipe); - -/* Return id of physical connector represented by a dc_link at link_index.*/ -const struct graphics_object_id dc_get_link_id_at_index( - struct dc *dc, uint32_t link_index); - /* Set backlight level of an embedded panel (eDP, LVDS). */ bool dc_link_set_backlight_level(const struct dc_link *dc_link, uint32_t level, uint32_t frame_ramp, const struct dc_stream_state *stream); -bool dc_link_set_abm_disable(const struct dc_link *dc_link); - bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable); bool dc_link_get_psr_state(const struct dc_link *dc_link, uint32_t *psr_state); @@ -907,7 +880,6 @@ void dc_link_remove_remote_sink( struct dc_sink *sink); /* Used by diagnostics for virtual link at the moment */ -void dc_link_set_sink(struct dc_link *link, struct dc_sink *sink); void dc_link_dp_set_drive_settings( struct dc_link *link, @@ -970,8 +942,6 @@ struct dc_sink { void dc_sink_retain(struct dc_sink *sink); void dc_sink_release(struct dc_sink *sink); -const struct audio **dc_get_audios(struct dc *dc); - struct dc_sink_init_data { enum signal_type sink_signal; struct dc_link *link; @@ -980,8 +950,6 @@ struct dc_sink_init_data { }; struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params); -bool dc_sink_get_container_id(struct dc_sink *dc_sink, struct dc_container_id *container_id); -bool dc_sink_set_container_id(struct dc_sink *dc_sink, const struct dc_container_id *container_id); /******************************************************************************* * Cursor interfaces - To manages the cursor within a stream @@ -1026,45 +994,6 @@ void dc_resume(struct dc *dc); * DPCD access interfaces */ -bool dc_read_aux_dpcd( - struct dc *dc, - uint32_t link_index, - uint32_t address, - uint8_t *data, - uint32_t size); - -bool dc_write_aux_dpcd( - struct dc *dc, - uint32_t link_index, - uint32_t address, - const uint8_t *data, - uint32_t size); - -bool dc_read_aux_i2c( - struct dc *dc, - uint32_t link_index, - enum i2c_mot_mode mot, - uint32_t address, - uint8_t *data, - uint32_t size); - -bool dc_write_aux_i2c( - struct dc *dc, - uint32_t link_index, - enum i2c_mot_mode mot, - uint32_t address, - const uint8_t *data, - uint32_t size); - -bool dc_query_ddc_data( - struct dc *dc, - uint32_t link_index, - uint32_t address, - uint8_t *write_buf, - uint32_t write_size, - uint8_t *read_buf, - uint32_t read_size); - bool dc_submit_i2c( struct dc *dc, uint32_t link_index, -- cgit From ae5baf7a1047eece4ff87469ae85a45b5ddf6aa3 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 22 Aug 2017 10:29:40 -0400 Subject: drm/amd/display: Remove old, misleading comment Signed-off-by: Harry Wentland Reviewed-by: Roman Li Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c index d6225f332431..56e3b124f19c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c @@ -31,7 +31,6 @@ #include "dce110/dce110_hw_sequencer.h" -/* include DCE12.0 register header files */ #include "vega10/DC/dce_12_0_offset.h" #include "vega10/DC/dce_12_0_sh_mask.h" #include "vega10/soc15ip.h" -- cgit From 67a72b6944446f68b9a930c13c8cdadba72beed8 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 22 Aug 2017 09:35:41 -0400 Subject: drm/amd/display: Stop including atomfimrwareid.h directly It's already included in atomfirmware.h Signed-off-by: Harry Wentland Reviewed-by: Roman Li Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c | 1 - drivers/gpu/drm/amd/display/dc/bios/command_table2.c | 1 - drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c | 1 - 3 files changed, 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c index f8d4f08bf985..95fe50f62c57 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -29,7 +29,6 @@ #include "ObjectID.h" #include "atomfirmware.h" -#include "atomfirmwareid.h" #include "dc_bios_types.h" #include "include/grph_object_ctrl_defs.h" diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c index e33e6bfccb6d..64eab356d336 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c @@ -27,7 +27,6 @@ #include "ObjectID.h" #include "atomfirmware.h" -#include "atomfirmwareid.h" #include "include/bios_parser_interface.h" diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c index 35c3f3a8e493..9a4d30dd4969 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c @@ -27,7 +27,6 @@ #include "ObjectID.h" #include "atomfirmware.h" -#include "atomfirmwareid.h" #include "include/bios_parser_types.h" -- cgit From aaa15026f273c184454ea8672274a682bc161da1 Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Tue, 22 Aug 2017 15:49:57 -0400 Subject: drm/amd/display: Fix return value from rx irq handler on up request Signed-off-by: Wenjing Liu Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') 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 e35bdce6a0f3..e19447d526ea 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 @@ -1964,11 +1964,11 @@ bool dc_link_handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd * so do not handle as a normal sink status change interrupt. */ + if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.UP_REQ_MSG_RDY) + return true; + /* check if we have MST msg and return since we poll for it */ - if (hpd_irq_dpcd_data.bytes.device_service_irq. - bits.DOWN_REP_MSG_RDY || - hpd_irq_dpcd_data.bytes.device_service_irq. - bits.UP_REQ_MSG_RDY) + if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.DOWN_REP_MSG_RDY) return false; /* For now we only handle 'Downstream port status' case. -- cgit From 0f0bdca5cae04ec2f842955bcef16a3daed6149f Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Tue, 22 Aug 2017 18:42:51 -0400 Subject: drm/amd/display: Safe stream encoder id in stream_status Signed-off-by: Wenjing Liu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 1 + drivers/gpu/drm/amd/display/dc/dc.h | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 428863bccab6..fbfe15f783c0 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1599,6 +1599,7 @@ enum dc_status resource_map_pool_resources( for (i = 0; i < context->stream_count; i++) if (context->streams[i] == stream) { context->stream_status[i].primary_otg_inst = pipe_ctx->stream_res.tg->inst; + context->stream_status[i].stream_enc_inst = pipe_ctx->stream_res.stream_enc->id; return DC_OK; } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 0f2a16a0cf82..9cc1c28caa4e 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -510,6 +510,7 @@ enum surface_update_type { struct dc_stream_status { int primary_otg_inst; + int stream_enc_inst; int plane_count; struct dc_plane_state *plane_states[MAX_SURFACE_NUM]; -- cgit From 577b5c2b51014b3c276ab1d456aaad965dbb4930 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Tue, 22 Aug 2017 20:15:28 -0400 Subject: drm/amd/display: Block 6Ghz timing if SBIOS set HDMI_6G_en to 0 Signed-off-by: Charlene Liu Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/bios/bios_parser.c | 1 + drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 4 ++++ drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h | 1 + 3 files changed, 6 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c index 2c683d468bb8..2c411441771b 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c @@ -1853,6 +1853,7 @@ static enum bp_result bios_parser_get_encoder_cap_info( info->DP_HBR2_EN = record->usHBR2En; info->DP_HBR3_EN = record->usHBR3En; + info->HDMI_6GB_EN = record->usHDMI6GEn; return BP_RESULT_OK; } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 559a9f81c9c9..0ce94ede80bf 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -887,6 +887,9 @@ static bool dce110_link_encoder_validate_hdmi_output( crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) return false; + if (!enc110->base.features.flags.bits.HDMI_6GB_EN && + adjusted_pix_clk_khz >= 300000) + return false; return true; } @@ -1008,6 +1011,7 @@ bool dce110_link_encoder_construct( bp_cap_info.DP_HBR2_EN; enc110->base.features.flags.bits.IS_HBR3_CAPABLE = bp_cap_info.DP_HBR3_EN; + enc110->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN; } return true; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h index 38e4070806cb..961bbcc9202c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h @@ -37,6 +37,7 @@ struct encoder_feature_support { uint32_t IS_TPS3_CAPABLE:1; uint32_t IS_TPS4_CAPABLE:1; uint32_t IS_YCBCR_CAPABLE:1; + uint32_t HDMI_6GB_EN:1; } bits; uint32_t raw; } flags; -- cgit From 19f89e2392e692208a0a00465d30b2b2bf43e9a9 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Fri, 11 Aug 2017 10:43:45 -0400 Subject: drm/amd/display: Per plane validation context build. Introduce add/remove plane to/from context. Make DC wrapper to use them in WIndows/Diags. Use them in dc_update_surface_to_stream. Call add/remove plane from Linux DM. Remove dc_validation_set from dc_validate_global_state interface and by this remove clean Linux DM from using it. Signed-off-by: Andrey Grodzovsky Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 165 ++++------ drivers/gpu/drm/amd/display/dc/core/dc.c | 12 +- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 362 +++++++++++++-------- drivers/gpu/drm/amd/display/dc/dc.h | 37 ++- .../drm/amd/display/dc/dce100/dce100_resource.c | 16 +- .../drm/amd/display/dc/dce110/dce110_resource.c | 26 +- .../drm/amd/display/dc/dce112/dce112_resource.c | 16 +- .../gpu/drm/amd/display/dc/dce80/dce80_resource.c | 16 +- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 3 - 9 files changed, 353 insertions(+), 300 deletions(-) (limited to 'drivers/gpu') 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 e037ed85a5cc..e8835e751702 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4304,77 +4304,6 @@ void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector dm_force_atomic_commit(&aconnector->base); } -static uint32_t add_val_sets_plane( - struct dc_validation_set *val_sets, - uint32_t set_count, - const struct dc_stream_state *stream, - struct dc_plane_state *plane_state) -{ - uint32_t i = 0, j = 0; - - while (i < set_count) { - if (val_sets[i].stream == stream) { - while (val_sets[i].plane_states[j]) - j++; - break; - } - ++i; - } - - val_sets[i].plane_states[j] = plane_state; - val_sets[i].plane_count++; - - return val_sets[i].plane_count; -} - -static uint32_t update_in_val_sets_stream( - struct dc_validation_set *val_sets, - uint32_t set_count, - struct dc_stream_state *old_stream, - struct dc_stream_state *new_stream, - struct drm_crtc *crtc) -{ - uint32_t i = 0; - - while (i < set_count) { - if (val_sets[i].stream == old_stream) - break; - ++i; - } - - val_sets[i].stream = new_stream; - - if (i == set_count) - /* nothing found. add new one to the end */ - return set_count + 1; - - return set_count; -} - -static uint32_t remove_from_val_sets( - struct dc_validation_set *val_sets, - uint32_t set_count, - const struct dc_stream_state *stream) -{ - int i; - - for (i = 0; i < set_count; i++) - if (val_sets[i].stream == stream) - break; - - if (i == set_count) { - /* nothing found */ - return set_count; - } - - set_count--; - - for (; i < set_count; i++) - val_sets[i] = val_sets[i + 1]; - - return set_count; -} - /*` * Grabs all modesetting locks to serialize against any blocking commits, * Waits for completion of all non blocking commits. @@ -4438,10 +4367,9 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, struct dc *dc = adev->dm.dc; struct drm_connector *connector; struct drm_connector_state *conn_state; - int set_count; - struct dc_validation_set set[MAX_STREAMS] = { { 0 } }; struct dm_crtc_state *old_acrtc_state, *new_acrtc_state; struct dm_atomic_state *dm_state = to_dm_atomic_state(state); + bool pflip_needed = !state->allow_modeset; /* * This bool will be set for true for any modeset/reset @@ -4460,16 +4388,44 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, ASSERT(dm_state->context); dc_resource_validate_ctx_copy_construct_current(dc, dm_state->context); - /* copy existing configuration */ - set_count = 0; - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + /* Remove exiting planes if they are disabled or their CRTC is updated */ + for_each_crtc_in_state(state, crtc, crtc_state, i) { + new_acrtc_state = to_dm_crtc_state(crtc_state); - old_acrtc_state = to_dm_crtc_state(crtc->state); + if (pflip_needed) + continue; - if (old_acrtc_state->stream) { - dc_stream_retain(old_acrtc_state->stream); - set[set_count].stream = old_acrtc_state->stream; - ++set_count; + for_each_plane_in_state(state, plane, plane_state, j) { + struct drm_crtc *plane_crtc = plane_state->crtc; + struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state); + + if (plane->type == DRM_PLANE_TYPE_CURSOR) + continue; + + if (crtc != plane_crtc || !dm_plane_state->dc_state) + continue; + + WARN_ON(!new_acrtc_state->stream); + + if (drm_atomic_plane_disabling(plane->state, plane_state) || + drm_atomic_crtc_needs_modeset(crtc_state)) { + if (!dc_remove_plane_from_context( + dc, + new_acrtc_state->stream, + dm_plane_state->dc_state, + dm_state->context)) { + + ret = EINVAL; + goto fail; + } + + } + + dc_plane_state_release(dm_plane_state->dc_state); + dm_plane_state->dc_state = NULL; + + DRM_DEBUG_KMS("Disabling DRM plane: %d on DRM crtc %d\n", + plane->base.id, crtc->base.id); } } @@ -4513,11 +4469,6 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, goto fail; } - set_count = remove_from_val_sets( - set, - set_count, - new_acrtc_state->stream); - dc_stream_release(new_acrtc_state->stream); new_acrtc_state->stream = NULL; @@ -4576,13 +4527,6 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, new_acrtc_state->stream = new_stream; - set_count = update_in_val_sets_stream( - set, - set_count, - old_acrtc_state->stream, - new_acrtc_state->stream, - crtc); - if (!dc_add_stream_to_ctx( dc, dm_state->context, @@ -4639,32 +4583,32 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, lock_and_validation_needed = true; } + /* Add new planes */ for_each_crtc_in_state(state, crtc, crtc_state, i) { new_acrtc_state = to_dm_crtc_state(crtc_state); + if (pflip_needed) + continue; + for_each_plane_in_state(state, plane, plane_state, j) { struct drm_crtc *plane_crtc = plane_state->crtc; - struct drm_framebuffer *fb = plane_state->fb; - bool pflip_needed; struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state); /*TODO Implement atomic check for cursor plane */ if (plane->type == DRM_PLANE_TYPE_CURSOR) continue; - if (!fb || !plane_crtc || crtc != plane_crtc || !crtc_state->active) + if (crtc != plane_crtc) continue; - WARN_ON(!new_acrtc_state->stream); - - pflip_needed = !state->allow_modeset; - if (!pflip_needed) { + if (!drm_atomic_plane_disabling(plane->state, plane_state)) { struct dc_plane_state *dc_plane_state; + WARN_ON(!new_acrtc_state->stream); + dc_plane_state = dc_create_plane_state(dc); - if (dm_plane_state->dc_state) - dc_plane_state_release(dm_plane_state->dc_state); + WARN_ON(dm_plane_state->dc_state); dm_plane_state->dc_state = dc_plane_state; @@ -4677,10 +4621,17 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, if (ret) goto fail; - add_val_sets_plane(set, - set_count, - new_acrtc_state->stream, - dc_plane_state); + + if (!dc_add_plane_to_context( + dc, + new_acrtc_state->stream, + dc_plane_state, + dm_state->context)) { + + ret = EINVAL; + goto fail; + } + lock_and_validation_needed = true; } @@ -4708,7 +4659,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, if (ret) goto fail; - if (!dc_validate_global_state(dc, set, set_count, dm_state->context)) { + if (!dc_validate_global_state(dc, dm_state->context)) { ret = -EINVAL; goto fail; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index ab2b8f23b20a..79980cb0900c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1305,10 +1305,16 @@ void dc_update_planes_and_stream(struct dc *dc, dc_resource_validate_ctx_copy_construct( core_dc->current_context, context); + /*remove old surfaces from context */ + if (!dc_rem_all_planes_for_stream(dc, stream, context)) { + + BREAK_TO_DEBUGGER(); + goto fail; + } + /* add surface to context */ - if (!resource_attach_surfaces_to_context( - new_planes, surface_count, stream, - context, core_dc->res_pool)) { + if (!dc_add_all_planes_for_stream(dc, stream, new_planes, surface_count, context)) { + BREAK_TO_DEBUGGER(); goto fail; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index fbfe15f783c0..6eee1b1a563e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -946,6 +946,26 @@ struct pipe_ctx *resource_get_head_pipe_for_stream( return NULL; } +static struct pipe_ctx *resource_get_tail_pipe_for_stream( + struct resource_context *res_ctx, + struct dc_stream_state *stream) +{ + struct pipe_ctx *head_pipe, *tail_pipe; + head_pipe = resource_get_head_pipe_for_stream(res_ctx, stream); + + if (!head_pipe) + return NULL; + + tail_pipe = head_pipe->bottom_pipe; + + while (tail_pipe) { + head_pipe = tail_pipe; + tail_pipe = tail_pipe->bottom_pipe; + } + + return head_pipe; +} + /* * A free_pipe for a stream is defined here as a pipe * that has no surface attached yet @@ -990,22 +1010,6 @@ static struct pipe_ctx *acquire_free_pipe_for_stream( } -static void release_free_pipes_for_stream( - struct resource_context *res_ctx, - struct dc_stream_state *stream) -{ - int i; - - for (i = MAX_PIPES - 1; i >= 0; i--) { - /* never release the topmost pipe*/ - if (res_ctx->pipe_ctx[i].stream == stream && - res_ctx->pipe_ctx[i].top_pipe && - !res_ctx->pipe_ctx[i].plane_state) { - memset(&res_ctx->pipe_ctx[i], 0, sizeof(struct pipe_ctx)); - } - } -} - #if defined(CONFIG_DRM_AMD_DC_DCN1_0) static int acquire_first_split_pipe( struct resource_context *res_ctx, @@ -1040,96 +1044,235 @@ static int acquire_first_split_pipe( } #endif -bool resource_attach_surfaces_to_context( - struct dc_plane_state * const *plane_states, - int surface_count, +bool dc_add_plane_to_context( + const struct dc *dc, struct dc_stream_state *stream, - struct validate_context *context, - const struct resource_pool *pool) + struct dc_plane_state *plane_state, + struct validate_context *context) { int i; - struct pipe_ctx *tail_pipe; + struct resource_pool *pool = dc->res_pool; + struct pipe_ctx *head_pipe, *tail_pipe, *free_pipe; struct dc_stream_status *stream_status = NULL; + for (i = 0; i < context->stream_count; i++) + if (context->streams[i] == stream) { + stream_status = &context->stream_status[i]; + break; + } + if (stream_status == NULL) { + dm_error("Existing stream not found; failed to attach surface!\n"); + return false; + } + + + if (stream_status->plane_count == MAX_SURFACE_NUM) { + dm_error("Surface: can not attach plane_state %p! Maximum is: %d\n", + plane_state, MAX_SURFACE_NUM); + return false; + } + + head_pipe = resource_get_head_pipe_for_stream(&context->res_ctx, stream); + + if (!head_pipe) { + dm_error("Head pipe not found for stream_state %p !\n", stream); + return false; + } + + /* retain new surfaces */ + dc_plane_state_retain(plane_state); + + free_pipe = acquire_free_pipe_for_stream(context, pool, stream); - if (surface_count > MAX_SURFACE_NUM) { - dm_error("Surface: can not attach %d surfaces! Maximum is: %d\n", - surface_count, MAX_SURFACE_NUM); +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + if (!free_pipe) { + int pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream); + if (pipe_idx >= 0) + free_pipe = &context->res_ctx.pipe_ctx[pipe_idx]; + } +#endif + if (!free_pipe) { + stream_status->plane_states[i] = NULL; return false; } + free_pipe->plane_state = plane_state; + + if (head_pipe != free_pipe) { + + tail_pipe = resource_get_tail_pipe_for_stream(&context->res_ctx, stream); + ASSERT(tail_pipe); + + free_pipe->stream_res.tg = tail_pipe->stream_res.tg; + free_pipe->stream_res.opp = tail_pipe->stream_res.opp; + free_pipe->stream_res.stream_enc = tail_pipe->stream_res.stream_enc; + free_pipe->stream_res.audio = tail_pipe->stream_res.audio; + free_pipe->clock_source = tail_pipe->clock_source; + free_pipe->top_pipe = tail_pipe; + tail_pipe->bottom_pipe = free_pipe; + } + + /* assign new surfaces*/ + stream_status->plane_states[stream_status->plane_count] = plane_state; + + stream_status->plane_count++; + + return true; +} + +bool dc_remove_plane_from_context( + const struct dc *dc, + struct dc_stream_state *stream, + struct dc_plane_state *plane_state, + struct validate_context *context) +{ + int i; + struct dc_stream_status *stream_status = NULL; + struct resource_pool *pool = dc->res_pool; + for (i = 0; i < context->stream_count; i++) if (context->streams[i] == stream) { stream_status = &context->stream_status[i]; break; } + if (stream_status == NULL) { - dm_error("Existing stream not found; failed to attach surfaces\n"); + dm_error("Existing stream not found; failed to remove plane.\n"); return false; } - /* retain new surfaces */ - for (i = 0; i < surface_count; i++) - dc_plane_state_retain(plane_states[i]); - - /* detach surfaces from pipes */ - for (i = 0; i < pool->pipe_count; i++) - if (context->res_ctx.pipe_ctx[i].stream == stream) { - context->res_ctx.pipe_ctx[i].plane_state = NULL; - context->res_ctx.pipe_ctx[i].bottom_pipe = NULL; - } + /* release pipe for plane*/ + for (i = pool->pipe_count - 1; i >= 0; i--) { + struct pipe_ctx *pipe_ctx; - /* release existing surfaces*/ - for (i = 0; i < stream_status->plane_count; i++) - dc_plane_state_release(stream_status->plane_states[i]); + if (context->res_ctx.pipe_ctx[i].plane_state == plane_state) { + pipe_ctx = &context->res_ctx.pipe_ctx[i]; - for (i = surface_count; i < stream_status->plane_count; i++) - stream_status->plane_states[i] = NULL; + if (pipe_ctx->top_pipe) + pipe_ctx->top_pipe->bottom_pipe = pipe_ctx->bottom_pipe; - tail_pipe = NULL; - for (i = 0; i < surface_count; i++) { - struct dc_plane_state *plane_state = plane_states[i]; - struct pipe_ctx *free_pipe = acquire_free_pipe_for_stream( - context, pool, stream); + /* Second condition is to avoid setting NULL to top pipe + * of tail pipe making it look like head pipe in subsequent + * deletes + */ + if (pipe_ctx->bottom_pipe && pipe_ctx->top_pipe) + pipe_ctx->bottom_pipe->top_pipe = pipe_ctx->top_pipe; -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) - if (!free_pipe) { - int pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream); - if (pipe_idx >= 0) - free_pipe = &context->res_ctx.pipe_ctx[pipe_idx]; - } -#endif - if (!free_pipe) { - stream_status->plane_states[i] = NULL; - return false; + /* + * For head pipe detach surfaces from pipe for tail + * pipe just zero it out + */ + if (!pipe_ctx->top_pipe) { + pipe_ctx->plane_state = NULL; + pipe_ctx->bottom_pipe = NULL; + } else { + memset(pipe_ctx, 0, sizeof(*pipe_ctx)); + } } + } + - free_pipe->plane_state = plane_state; + for (i = 0; i < stream_status->plane_count; i++) { + if (stream_status->plane_states[i] == plane_state) { - if (tail_pipe) { - free_pipe->stream_res.tg = tail_pipe->stream_res.tg; - free_pipe->stream_res.opp = tail_pipe->stream_res.opp; - free_pipe->stream_res.stream_enc = tail_pipe->stream_res.stream_enc; - free_pipe->stream_res.audio = tail_pipe->stream_res.audio; - free_pipe->clock_source = tail_pipe->clock_source; - free_pipe->top_pipe = tail_pipe; - tail_pipe->bottom_pipe = free_pipe; + dc_plane_state_release(stream_status->plane_states[i]); + break; } + } - tail_pipe = free_pipe; + if (i == stream_status->plane_count) { + dm_error("Existing plane_state not found; failed to detach it!\n"); + return false; } - release_free_pipes_for_stream(&context->res_ctx, stream); + stream_status->plane_count--; - /* assign new surfaces*/ - for (i = 0; i < surface_count; i++) - stream_status->plane_states[i] = plane_states[i]; + /* Trim back arrays */ + for (i = 0; i < stream_status->plane_count; i++) + stream_status->plane_states[i] = stream_status->plane_states[i + 1]; + + stream_status->plane_states[stream_status->plane_count] = NULL; + + return true; +} + +bool dc_rem_all_planes_for_stream( + const struct dc *dc, + struct dc_stream_state *stream, + struct validate_context *context) +{ + int i, old_plane_count; + struct dc_stream_status *stream_status = NULL; + struct dc_plane_state *del_planes[MAX_SURFACE_NUM] = { 0 }; + + for (i = 0; i < context->stream_count; i++) + if (context->streams[i] == stream) { + stream_status = &context->stream_status[i]; + break; + } + + if (stream_status == NULL) { + dm_error("Existing stream %p not found!\n", stream); + return false; + } + + old_plane_count = stream_status->plane_count; - stream_status->plane_count = surface_count; + for (i = 0; i < old_plane_count; i++) + del_planes[i] = stream_status->plane_states[i]; + + for (i = 0; i < old_plane_count; i++) + if (!dc_remove_plane_from_context(dc, stream, del_planes[i], context)) + return false; return true; } +static bool add_all_planes_for_stream( + const struct dc *dc, + struct dc_stream_state *stream, + const struct dc_validation_set set[], + int set_count, + struct validate_context *context) +{ + int i, j; + + for (i = 0; i < set_count; i++) + if (set[i].stream == stream) + break; + + if (i == set_count) { + dm_error("Stream %p not found in set!\n", stream); + return false; + } + + for (j = 0; j < set[i].plane_count; j++) + if (!dc_add_plane_to_context(dc, stream, set[i].plane_states[j], context)) + return false; + + return true; +} + +bool dc_add_all_planes_for_stream( + const struct dc *dc, + struct dc_stream_state *stream, + struct dc_plane_state * const *plane_states, + int plane_count, + struct validate_context *context) +{ + struct dc_validation_set set; + int i; + + set.stream = stream; + set.plane_count = plane_count; + + for (i = 0; i < plane_count; i++) + set.plane_states[i] = plane_states[i]; + + return add_all_planes_for_stream(dc, stream, &set, 1, context); +} + + static bool is_timing_changed(struct dc_stream_state *cur_stream, struct dc_stream_state *new_stream) @@ -1178,41 +1321,6 @@ bool dc_is_stream_unchanged( return true; } -bool resource_validate_attach_surfaces( - const struct dc_validation_set set[], - int set_count, - const struct validate_context *old_context, - struct validate_context *context, - const struct resource_pool *pool) -{ - int i, j; - - for (i = 0; i < set_count; i++) { - for (j = 0; old_context && j < old_context->stream_count; j++) - if (dc_is_stream_unchanged( - old_context->streams[j], - context->streams[i])) { - if (!resource_attach_surfaces_to_context( - old_context->stream_status[j].plane_states, - old_context->stream_status[j].plane_count, - context->streams[i], - context, pool)) - return false; - context->stream_status[i] = old_context->stream_status[j]; - } - if (set[i].plane_count != 0) - if (!resource_attach_surfaces_to_context( - set[i].plane_states, - set[i].plane_count, - context->streams[i], - context, pool)) - return false; - - } - - return true; -} - /* Maximum TMDS single link pixel clock 165MHz */ #define TMDS_MAX_PIXEL_CLOCK_IN_KHZ 165000 #define TMDS_MAX_PIXEL_CLOCK_IN_KHZ_UPMOST 297000 @@ -1392,23 +1500,22 @@ bool dc_remove_stream_from_ctx( struct validate_context *new_ctx, struct dc_stream_state *stream) { - int i, j; + int i; struct dc_context *dc_ctx = dc->ctx; struct pipe_ctx *del_pipe = NULL; - /*TODO MPO to remove extra pipe or in surface remove ?*/ - - /* Release primary and secondary pipe (if exsist) */ + /* Release primary pipe */ for (i = 0; i < MAX_PIPES; i++) { - if (new_ctx->res_ctx.pipe_ctx[i].stream == stream) { + if (new_ctx->res_ctx.pipe_ctx[i].stream == stream && + !new_ctx->res_ctx.pipe_ctx[i].top_pipe) { del_pipe = &new_ctx->res_ctx.pipe_ctx[i]; - if (del_pipe->stream_res.stream_enc) - update_stream_engine_usage( - &new_ctx->res_ctx, + ASSERT(del_pipe->stream_res.stream_enc); + update_stream_engine_usage( + &new_ctx->res_ctx, dc->res_pool, - del_pipe->stream_res.stream_enc, - false); + del_pipe->stream_res.stream_enc, + false); if (del_pipe->stream_res.audio) update_audio_usage( @@ -1418,6 +1525,8 @@ bool dc_remove_stream_from_ctx( false); memset(del_pipe, 0, sizeof(*del_pipe)); + + break; } } @@ -1438,10 +1547,6 @@ bool dc_remove_stream_from_ctx( dc_stream_release(new_ctx->streams[i]); new_ctx->stream_count--; - /*TODO move into dc_remove_surface_from_ctx ?*/ - for (j = 0; j < new_ctx->stream_status[i].plane_count; j++) - dc_plane_state_release(new_ctx->stream_status[i].plane_states[j]); - /* Trim back arrays */ for (; i < new_ctx->stream_count; i++) { new_ctx->streams[i] = new_ctx->streams[i + 1]; @@ -1636,18 +1741,14 @@ void dc_resource_validate_ctx_copy_construct_current( bool dc_validate_global_state( struct dc *dc, - const struct dc_validation_set set[], - int set_count, struct validate_context *new_ctx) { enum dc_status result = DC_ERROR_UNEXPECTED; - struct dc_context *dc_ctx = dc->ctx; - struct validate_context *old_context = dc->current_context; int i, j; if (dc->res_pool->funcs->validate_global && - dc->res_pool->funcs->validate_global(dc, set, set_count, - old_context, new_ctx) != DC_OK) + dc->res_pool->funcs->validate_global( + dc, new_ctx) != DC_OK) return false; /* TODO without this SWDEV-114774 brakes */ @@ -1687,15 +1788,6 @@ bool dc_validate_global_state( } } - /*TODO This should be ok */ - /* Split pipe resource, do not acquire back end */ - - if (!resource_validate_attach_surfaces( - set, set_count, old_context, new_ctx, dc->res_pool)) { - DC_ERROR("Failed to attach surface to stream!\n"); - return DC_FAIL_ATTACH_SURFACES; - } - result = resource_build_scaling_params_for_context(dc, new_ctx); if (result == DC_OK) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 9cc1c28caa4e..55fc58102515 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -619,15 +619,40 @@ bool dc_stream_get_scanoutpos(const struct dc_stream_state *stream, uint32_t *h_position, uint32_t *v_position); -bool dc_remove_stream_from_ctx( +bool dc_add_stream_to_ctx( struct dc *dc, + struct validate_context *new_ctx, + struct dc_stream_state *stream); + +bool dc_remove_stream_from_ctx( + struct dc *dc, struct validate_context *new_ctx, struct dc_stream_state *stream); -bool dc_add_stream_to_ctx( - struct dc *dc, - struct validate_context *new_ctx, - struct dc_stream_state *stream); + +bool dc_add_plane_to_context( + const struct dc *dc, + struct dc_stream_state *stream, + struct dc_plane_state *plane_state, + struct validate_context *context); + +bool dc_remove_plane_from_context( + const struct dc *dc, + struct dc_stream_state *stream, + struct dc_plane_state *plane_state, + struct validate_context *context); + +bool dc_rem_all_planes_for_stream( + const struct dc *dc, + struct dc_stream_state *stream, + struct validate_context *context); + +bool dc_add_all_planes_for_stream( + const struct dc *dc, + struct dc_stream_state *stream, + struct dc_plane_state * const *plane_states, + int plane_count, + struct validate_context *context); /* * Structure to store surface/stream associations for validation @@ -644,8 +669,6 @@ bool dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state); bool dc_validate_global_state( struct dc *dc, - const struct dc_validation_set set[], - int set_count, struct validate_context *new_ctx); /* diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index c9dad4e2a7c8..c991610315b2 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -684,19 +684,18 @@ bool dce100_validate_bandwidth( } static bool dce100_validate_surface_sets( - const struct dc_validation_set set[], - int set_count) + struct validate_context *context) { int i; - for (i = 0; i < set_count; i++) { - if (set[i].plane_count == 0) + for (i = 0; i < context->stream_count; i++) { + if (context->stream_status[i].plane_count == 0) continue; - if (set[i].plane_count > 1) + if (context->stream_status[i].plane_count > 1) return false; - if (set[i].plane_states[0]->format + if (context->stream_status[i].plane_states[0]->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) return false; } @@ -706,12 +705,9 @@ static bool dce100_validate_surface_sets( enum dc_status dce100_validate_global( struct dc *dc, - const struct dc_validation_set set[], - int set_count, - struct validate_context *old_context, struct validate_context *context) { - if (!dce100_validate_surface_sets(set, set_count)) + if (!dce100_validate_surface_sets(context)) return DC_FAIL_SURFACE_VALIDATE; return DC_OK; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index d682180f2eaf..18c67f89e9b5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -880,31 +880,30 @@ static bool dce110_validate_bandwidth( } static bool dce110_validate_surface_sets( - const struct dc_validation_set set[], - int set_count) + struct validate_context *context) { int i; - for (i = 0; i < set_count; i++) { - if (set[i].plane_count == 0) + for (i = 0; i < context->stream_count; i++) { + if (context->stream_status[i].plane_count == 0) continue; - if (set[i].plane_count > 2) + if (context->stream_status[i].plane_count > 2) return false; - if (set[i].plane_states[0]->format + if (context->stream_status[i].plane_states[0]->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) return false; - if (set[i].plane_count == 2) { - if (set[i].plane_states[1]->format + if (context->stream_status[i].plane_count == 2) { + if (context->stream_status[i].plane_states[1]->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) return false; - if (set[i].plane_states[1]->src_rect.width > 1920 - || set[i].plane_states[1]->src_rect.height > 1080) + if (context->stream_status[i].plane_states[1]->src_rect.width > 1920 + || context->stream_status[i].plane_states[1]->src_rect.height > 1080) return false; - if (set[i].stream->timing.pixel_encoding != PIXEL_ENCODING_RGB) + if (context->streams[i]->timing.pixel_encoding != PIXEL_ENCODING_RGB) return false; } } @@ -914,12 +913,9 @@ static bool dce110_validate_surface_sets( enum dc_status dce110_validate_global( struct dc *dc, - const struct dc_validation_set set[], - int set_count, - struct validate_context *old_context, struct validate_context *context) { - if (!dce110_validate_surface_sets(set, set_count)) + if (!dce110_validate_surface_sets(context)) return DC_FAIL_SURFACE_VALIDATE; return DC_OK; diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 85a396ef5aa5..d5a8ee69171d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -855,19 +855,18 @@ enum dc_status resource_map_phy_clock_resources( } static bool dce112_validate_surface_sets( - const struct dc_validation_set set[], - int set_count) + struct validate_context *context) { int i; - for (i = 0; i < set_count; i++) { - if (set[i].plane_count == 0) + for (i = 0; i < context->stream_count; i++) { + if (context->stream_status[i].plane_count == 0) continue; - if (set[i].plane_count > 1) + if (context->stream_status[i].plane_count > 1) return false; - if (set[i].plane_states[0]->format + if (context->stream_status[i].plane_states[0]->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) return false; } @@ -928,12 +927,9 @@ enum dc_status dce112_validate_guaranteed( enum dc_status dce112_validate_global( struct dc *dc, - const struct dc_validation_set set[], - int set_count, - struct validate_context *old_context, struct validate_context *context) { - if (!dce112_validate_surface_sets(set, set_count)) + if (!dce112_validate_surface_sets(context)) return DC_FAIL_SURFACE_VALIDATE; return DC_OK; diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index ac3f42a44030..945ff7ee6cd9 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -716,19 +716,18 @@ bool dce80_validate_bandwidth( } static bool dce80_validate_surface_sets( - const struct dc_validation_set set[], - int set_count) + struct validate_context *context) { int i; - for (i = 0; i < set_count; i++) { - if (set[i].plane_count == 0) + for (i = 0; i < context->stream_count; i++) { + if (context->stream_status[i].plane_count == 0) continue; - if (set[i].plane_count > 1) + if (context->stream_status[i].plane_count > 1) return false; - if (set[i].plane_states[0]->format + if (context->stream_status[i].plane_states[0]->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) return false; } @@ -738,12 +737,9 @@ static bool dce80_validate_surface_sets( enum dc_status dce80_validate_global( struct dc *dc, - const struct dc_validation_set set[], - int set_count, - struct validate_context *old_context, struct validate_context *context) { - if (!dce80_validate_surface_sets(set, set_count)) + if (!dce80_validate_surface_sets(context)) return DC_FAIL_SURFACE_VALIDATE; return DC_OK; diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 62bd11d250c5..bd1a6367872f 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -99,9 +99,6 @@ struct resource_funcs { enum dc_status (*validate_global)( struct dc *dc, - const struct dc_validation_set set[], - int set_count, - struct validate_context *old_context, struct validate_context *context); struct pipe_ctx *(*acquire_idle_pipe_for_layer)( -- cgit From 62f555377f972c206c69c6acc93d91f2baec9a26 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Fri, 18 Aug 2017 10:52:20 -0400 Subject: drm/amd/display: Refactor atomic check. Split into update crtcs and update plane functions. Signed-off-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 462 ++++++++++++---------- 1 file changed, 261 insertions(+), 201 deletions(-) (limited to 'drivers/gpu') 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 e8835e751702..193a634f46e6 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1640,12 +1640,6 @@ static bool modeset_required(struct drm_crtc_state *crtc_state, struct dc_stream_state *new_stream, struct dc_stream_state *old_stream) { - if (dc_is_stream_unchanged(new_stream, old_stream)) { - crtc_state->mode_changed = false; - DRM_DEBUG_KMS("Mode change not required, setting mode_changed to %d", - crtc_state->mode_changed); - } - if (!drm_atomic_crtc_needs_modeset(crtc_state)) return false; @@ -3875,9 +3869,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, continue; } - if (!fb || !crtc || pcrtc != crtc || !crtc->state->active || - (!crtc->state->planes_changed && - !pcrtc->state->color_mgmt_changed)) + if (!fb || !crtc || pcrtc != crtc || !crtc->state->active) continue; pflip_needed = !state->allow_modeset; @@ -4354,95 +4346,76 @@ static int do_aquire_global_lock( return ret < 0 ? ret : 0; } -int amdgpu_dm_atomic_check(struct drm_device *dev, - struct drm_atomic_state *state) +static int dm_update_crtcs_state( + struct dc *dc, + struct drm_atomic_state *state, + bool enable, + bool *lock_and_validation_needed) { struct drm_crtc *crtc; struct drm_crtc_state *crtc_state; - struct drm_plane *plane; - struct drm_plane_state *plane_state; - int i, j; - int ret; - struct amdgpu_device *adev = dev->dev_private; - struct dc *dc = adev->dm.dc; - struct drm_connector *connector; - struct drm_connector_state *conn_state; + int i; struct dm_crtc_state *old_acrtc_state, *new_acrtc_state; struct dm_atomic_state *dm_state = to_dm_atomic_state(state); - bool pflip_needed = !state->allow_modeset; - - /* - * This bool will be set for true for any modeset/reset - * or plane update which implies non fast surface update. - */ - bool lock_and_validation_needed = false; - - ret = drm_atomic_helper_check_modeset(dev, state); - - if (ret) { - DRM_ERROR("Atomic state validation failed with error :%d !\n", ret); - return ret; - } - - dm_state->context = dc_create_state(); - ASSERT(dm_state->context); - dc_resource_validate_ctx_copy_construct_current(dc, dm_state->context); + int ret = 0; - /* Remove exiting planes if they are disabled or their CRTC is updated */ + /*TODO Move this code into dm_crtc_atomic_check once we get rid of dc_validation_set */ + /* update changed items */ for_each_crtc_in_state(state, crtc, crtc_state, i) { - new_acrtc_state = to_dm_crtc_state(crtc_state); + struct amdgpu_crtc *acrtc = NULL; + struct amdgpu_connector *aconnector = NULL; + struct dc_stream_state *new_stream = NULL; + struct drm_connector_state *conn_state = NULL; + struct dm_connector_state *dm_conn_state = NULL; - if (pflip_needed) - continue; + old_acrtc_state = to_dm_crtc_state(crtc->state); + new_acrtc_state = to_dm_crtc_state(crtc_state); + acrtc = to_amdgpu_crtc(crtc); - for_each_plane_in_state(state, plane, plane_state, j) { - struct drm_crtc *plane_crtc = plane_state->crtc; - struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state); + aconnector = amdgpu_dm_find_first_crct_matching_connector(state, crtc, true); - if (plane->type == DRM_PLANE_TYPE_CURSOR) - continue; + /* TODO This hack should go away */ + if (aconnector && aconnector->dc_sink) { + conn_state = drm_atomic_get_connector_state(state, + &aconnector->base); - if (crtc != plane_crtc || !dm_plane_state->dc_state) - continue; + if (IS_ERR(conn_state)) { + ret = PTR_ERR_OR_ZERO(conn_state); + break; + } - WARN_ON(!new_acrtc_state->stream); + dm_conn_state = to_dm_connector_state(conn_state); - if (drm_atomic_plane_disabling(plane->state, plane_state) || - drm_atomic_crtc_needs_modeset(crtc_state)) { - if (!dc_remove_plane_from_context( - dc, - new_acrtc_state->stream, - dm_plane_state->dc_state, - dm_state->context)) { + new_stream = create_stream_for_sink(aconnector, + &crtc_state->mode, + dm_conn_state); - ret = EINVAL; - goto fail; - } + /* + * we can have no stream on ACTION_SET if a display + * was disconnected during S3, in this case it not and + * error, the OS will be updated after detection, and + * do the right thing on next atomic commit + */ + if (!new_stream) { + DRM_DEBUG_KMS("%s: Failed to create new stream for crtc %d\n", + __func__, acrtc->base.base.id); + break; } + } - dc_plane_state_release(dm_plane_state->dc_state); - dm_plane_state->dc_state = NULL; + if (dc_is_stream_unchanged(new_stream, + old_acrtc_state->stream)) { - DRM_DEBUG_KMS("Disabling DRM plane: %d on DRM crtc %d\n", - plane->base.id, crtc->base.id); - } - } + crtc_state->mode_changed = false; - /*TODO Move this code into dm_crtc_atomic_check once we get rid of dc_validation_set */ - /* update changed items */ - for_each_crtc_in_state(state, crtc, crtc_state, i) { - struct amdgpu_crtc *acrtc = NULL; - struct amdgpu_connector *aconnector = NULL; - struct dc_stream_state *new_stream = NULL; - struct drm_connector_state *conn_state = NULL; - struct dm_connector_state *dm_conn_state = NULL; + DRM_DEBUG_KMS("Mode change not required, setting mode_changed to %d", + crtc_state->mode_changed); + } - old_acrtc_state = to_dm_crtc_state(crtc->state); - new_acrtc_state = to_dm_crtc_state(crtc_state); - acrtc = to_amdgpu_crtc(crtc); - aconnector = amdgpu_dm_find_first_crct_matching_connector(state, crtc, true); + if (!drm_atomic_crtc_needs_modeset(crtc_state)) + continue; DRM_DEBUG_KMS( "amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, " @@ -4456,109 +4429,256 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, crtc_state->active_changed, crtc_state->connectors_changed); - if (modereset_required(crtc_state)) { + /* Remove stream for any changed/disabled CRTC */ + if (!enable) { + + if (!old_acrtc_state->stream) + continue; + + DRM_DEBUG_KMS("Disabling DRM crtc: %d\n", + crtc->base.id); /* i.e. reset mode */ - if (new_acrtc_state->stream) { + if (!dc_remove_stream_from_ctx( + dc, + dm_state->context, + old_acrtc_state->stream)) { + ret = -EINVAL; + break; + } + + dc_stream_release(old_acrtc_state->stream); + new_acrtc_state->stream = NULL; + + *lock_and_validation_needed = true; + + } else {/* Add stream for any updated/enabled CRTC */ + + if (modereset_required(crtc_state)) + continue; + + if (modeset_required(crtc_state, new_stream, + old_acrtc_state->stream)) { + + WARN_ON(new_acrtc_state->stream); + + new_acrtc_state->stream = new_stream; + dc_stream_retain(new_stream); + + DRM_DEBUG_KMS("Enabling DRM crtc: %d\n", + crtc->base.id); - if (!dc_remove_stream_from_ctx( + if (!dc_add_stream_to_ctx( dc, dm_state->context, new_acrtc_state->stream)) { ret = -EINVAL; - goto fail; + break; } - dc_stream_release(new_acrtc_state->stream); - new_acrtc_state->stream = NULL; - - lock_and_validation_needed = true; + *lock_and_validation_needed = true; } + } - } else { + /* Release extra reference */ + if (new_stream) + dc_stream_release(new_stream); + } - if (aconnector) { - conn_state = drm_atomic_get_connector_state(state, - &aconnector->base); + return ret; +} - if (IS_ERR(conn_state)) { - ret = PTR_ERR_OR_ZERO(conn_state); - goto fail; - } +static int dm_update_planes_state( + struct dc *dc, + struct drm_atomic_state *state, + bool enable, + bool *lock_and_validation_needed) +{ + struct drm_crtc *new_plane_crtc, *old_plane_crtc; + struct drm_crtc_state *new_crtc_state; + struct drm_plane *plane; + struct drm_plane_state *old_plane_state, *new_plane_state; + struct dm_crtc_state *new_acrtc_state, *old_acrtc_state; + struct dm_atomic_state *dm_state = to_dm_atomic_state(state); + struct dm_plane_state *new_dm_plane_state, *old_dm_plane_state; + int i ; + /* TODO return page_flip_needed() function */ + bool pflip_needed = !state->allow_modeset; + int ret = 0; - dm_conn_state = to_dm_connector_state(conn_state); + if (pflip_needed) + return ret; - new_stream = create_stream_for_sink(aconnector, - &crtc_state->mode, - dm_conn_state); + /* Add new planes */ + for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) { + new_plane_crtc = new_plane_state->crtc; + old_plane_crtc = old_plane_state->crtc; + new_dm_plane_state = to_dm_plane_state(new_plane_state); + old_dm_plane_state = to_dm_plane_state(old_plane_state); + + /*TODO Implement atomic check for cursor plane */ + if (plane->type == DRM_PLANE_TYPE_CURSOR) + continue; - /* - * we can have no stream on ACTION_SET if a display - * was disconnected during S3, in this case it not and - * error, the OS will be updated after detection, and - * do the right thing on next atomic commit - */ + /* Remove any changed/removed planes */ + if (!enable) { - if (!new_stream) { - DRM_DEBUG_KMS("%s: Failed to create new stream for crtc %d\n", - __func__, acrtc->base.base.id); - break; - } + if (!old_plane_crtc) + continue; + + old_acrtc_state = to_dm_crtc_state( + drm_atomic_get_old_crtc_state( + state, + old_plane_crtc)); + if (!old_acrtc_state->stream) + continue; + + DRM_DEBUG_KMS("Disabling DRM plane: %d on DRM crtc %d\n", + plane->base.id, old_plane_crtc->base.id); + if (!dc_remove_plane_from_context( + dc, + old_acrtc_state->stream, + old_dm_plane_state->dc_state, + dm_state->context)) { + + ret = EINVAL; + return ret; } - if (modeset_required(crtc_state, new_stream, - old_acrtc_state->stream)) { - if (new_acrtc_state->stream) { + dc_plane_state_release(old_dm_plane_state->dc_state); + new_dm_plane_state->dc_state = NULL; - if (!dc_remove_stream_from_ctx( - dc, - dm_state->context, - new_acrtc_state->stream)) { - ret = -EINVAL; - goto fail; - } + *lock_and_validation_needed = true; + } else { /* Add new planes */ - dc_stream_release(new_acrtc_state->stream); - } + if (drm_atomic_plane_disabling(plane->state, new_plane_state)) + continue; - new_acrtc_state->stream = new_stream; + if (!new_plane_crtc) + continue; - if (!dc_add_stream_to_ctx( - dc, - dm_state->context, - new_acrtc_state->stream)) { - ret = -EINVAL; - goto fail; - } + new_crtc_state = drm_atomic_get_new_crtc_state(state, new_plane_crtc); + new_acrtc_state = to_dm_crtc_state(new_crtc_state); - lock_and_validation_needed = true; - } else { - /* - * The new stream is unused, so we release it - */ - if (new_stream) - dc_stream_release(new_stream); + if (!new_acrtc_state->stream) + continue; + + + WARN_ON(new_dm_plane_state->dc_state); + new_dm_plane_state->dc_state = dc_create_plane_state(dc); + + DRM_DEBUG_KMS("Enabling DRM plane: %d on DRM crtc %d\n", + plane->base.id, new_plane_crtc->base.id); + + if (!new_dm_plane_state->dc_state) { + ret = -EINVAL; + return ret; + } + + ret = fill_plane_attributes( + new_plane_crtc->dev->dev_private, + new_dm_plane_state->dc_state, + new_plane_state, + new_crtc_state, + false); + if (ret) + return ret; + + + if (!dc_add_plane_to_context( + dc, + new_acrtc_state->stream, + new_dm_plane_state->dc_state, + dm_state->context)) { + + ret = -EINVAL; + return ret; } + + *lock_and_validation_needed = true; } + } - /* - * Hack: Commit needs planes right now, specifically for gamma - * TODO rework commit to check CRTC for gamma change - */ - if (crtc_state->color_mgmt_changed) { + return ret; +} + +int amdgpu_dm_atomic_check(struct drm_device *dev, + struct drm_atomic_state *state) +{ + int i; + int ret; + struct amdgpu_device *adev = dev->dev_private; + struct dc *dc = adev->dm.dc; + struct dm_atomic_state *dm_state = to_dm_atomic_state(state); + struct drm_connector *connector; + struct drm_connector_state *conn_state; + struct drm_crtc *crtc; + struct drm_crtc_state *crtc_state; + /* + * This bool will be set for true for any modeset/reset + * or plane update which implies non fast surface update. + */ + bool lock_and_validation_needed = false; + + ret = drm_atomic_helper_check_modeset(dev, state); + + if (ret) { + DRM_ERROR("Atomic state validation failed with error :%d !\n", ret); + return ret; + } + + /* + * Hack: Commit needs planes right now, specifically for gamma + * TODO rework commit to check CRTC for gamma change + */ + for_each_crtc_in_state(state, crtc, crtc_state, i) { + if (crtc_state->color_mgmt_changed) { ret = drm_atomic_add_affected_planes(state, crtc); if (ret) goto fail; } } + dm_state->context = dc_create_state(); + ASSERT(dm_state->context); + dc_resource_validate_ctx_copy_construct_current(dc, dm_state->context); + + /* Remove exiting planes if they are modified */ + ret = dm_update_planes_state(dc, state, false, &lock_and_validation_needed); + if (ret) { + goto fail; + } + + /* Disable all crtcs which require disable */ + ret = dm_update_crtcs_state(dc, state, false, &lock_and_validation_needed); + if (ret) { + goto fail; + } + + /* Enable all crtcs which require enable */ + ret = dm_update_crtcs_state(dc, state, true, &lock_and_validation_needed); + if (ret) { + goto fail; + } + + /* Add new/modified planes */ + ret = dm_update_planes_state(dc, state, true, &lock_and_validation_needed); + if (ret) { + goto fail; + } + + /* Run this here since we want to validate the streams we created */ + ret = drm_atomic_helper_check_planes(dev, state); + if (ret) + goto fail; + /* Check scaling and undersacn changes*/ /*TODO Removed scaling changes validation due to inability to commit * new stream into context w\o causing full reset. Need to @@ -4583,66 +4703,6 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, lock_and_validation_needed = true; } - /* Add new planes */ - for_each_crtc_in_state(state, crtc, crtc_state, i) { - new_acrtc_state = to_dm_crtc_state(crtc_state); - - if (pflip_needed) - continue; - - for_each_plane_in_state(state, plane, plane_state, j) { - struct drm_crtc *plane_crtc = plane_state->crtc; - struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state); - - /*TODO Implement atomic check for cursor plane */ - if (plane->type == DRM_PLANE_TYPE_CURSOR) - continue; - - if (crtc != plane_crtc) - continue; - - if (!drm_atomic_plane_disabling(plane->state, plane_state)) { - struct dc_plane_state *dc_plane_state; - - WARN_ON(!new_acrtc_state->stream); - - dc_plane_state = dc_create_plane_state(dc); - - WARN_ON(dm_plane_state->dc_state); - - dm_plane_state->dc_state = dc_plane_state; - - ret = fill_plane_attributes( - plane_crtc->dev->dev_private, - dc_plane_state, - plane_state, - crtc_state, - false); - if (ret) - goto fail; - - - if (!dc_add_plane_to_context( - dc, - new_acrtc_state->stream, - dc_plane_state, - dm_state->context)) { - - ret = EINVAL; - goto fail; - } - - - lock_and_validation_needed = true; - } - } - } - - /* Run this here since we want to validate the streams we created */ - ret = drm_atomic_helper_check_planes(dev, state); - if (ret) - goto fail; - /* * For full updates case when * removing/adding/updating streams on once CRTC while flipping @@ -4675,7 +4735,7 @@ fail: else if (ret == -EINTR || ret == -EAGAIN || ret == -ERESTARTSYS) DRM_DEBUG_KMS("Atomic check stopped due to to signal.\n"); else - DRM_ERROR("Atomic check failed with err: %d .\n", ret); + DRM_ERROR("Atomic check failed with err: %d \n", ret); return ret; } -- cgit From 9635b75436e5f536831c810c715f3ae24a5bbbae Mon Sep 17 00:00:00 2001 From: Darren Salt Date: Tue, 12 Sep 2017 17:10:25 +0100 Subject: drm/amd/display: Don't leak dc_stream_state. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Noticed while playing “Valley”, which was causing some 8MB of leakage per second. kmemleak listed many entries looking like this: unreferenced object 0xffff8802c2951800 (size 1024): comm "Xorg", pid 2982, jiffies 4297410155 (age 392.787s) hex dump (first 32 bytes): 00 50 f9 0c 04 88 ff ff 98 08 00 00 00 00 00 00 .P.............. 80 07 00 00 00 00 00 00 58 00 00 00 2c 00 00 00 ........X...,... backtrace: [] create_object+0x13c/0x261 [] kmemleak_alloc+0x20/0x3c [] slab_post_alloc_hook+0x42/0x52 [] kmem_cache_alloc+0x67/0x76 [] dc_create_stream_for_sink+0x24/0x1cf [] create_stream_for_sink+0x6f/0x295 [] dm_update_crtcs_state+0xa6/0x268 [] amdgpu_dm_atomic_check+0x9a/0x314 [] drm_atomic_check_only+0x17a/0x42d [] drm_atomic_commit+0x13/0x4b [] drm_atomic_connector_commit_dpms+0xcb/0xe8 [] drm_mode_obj_set_property_ioctl+0xe6/0x1e3 [] drm_mode_connector_property_set_ioctl+0x2b/0x2d [] drm_ioctl_kernel+0x64/0x9d [] drm_ioctl+0x230/0x316 [] amdgpu_drm_ioctl+0x4b/0x7d v2: also handle break statements. Signed-off-by: Darren Salt Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') 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 193a634f46e6..4f1e31cd4cbe 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4357,6 +4357,7 @@ static int dm_update_crtcs_state( int i; struct dm_crtc_state *old_acrtc_state, *new_acrtc_state; struct dm_atomic_state *dm_state = to_dm_atomic_state(state); + struct dc_stream_state *new_stream; int ret = 0; /*TODO Move this code into dm_crtc_atomic_check once we get rid of dc_validation_set */ @@ -4364,10 +4365,11 @@ static int dm_update_crtcs_state( for_each_crtc_in_state(state, crtc, crtc_state, i) { struct amdgpu_crtc *acrtc = NULL; struct amdgpu_connector *aconnector = NULL; - struct dc_stream_state *new_stream = NULL; struct drm_connector_state *conn_state = NULL; struct dm_connector_state *dm_conn_state = NULL; + new_stream = NULL; + old_acrtc_state = to_dm_crtc_state(crtc->state); new_acrtc_state = to_dm_crtc_state(crtc_state); acrtc = to_amdgpu_crtc(crtc); @@ -4415,7 +4417,7 @@ static int dm_update_crtcs_state( if (!drm_atomic_crtc_needs_modeset(crtc_state)) - continue; + goto next_crtc; DRM_DEBUG_KMS( "amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, " @@ -4433,7 +4435,7 @@ static int dm_update_crtcs_state( if (!enable) { if (!old_acrtc_state->stream) - continue; + goto next_crtc; DRM_DEBUG_KMS("Disabling DRM crtc: %d\n", crtc->base.id); @@ -4444,7 +4446,7 @@ static int dm_update_crtcs_state( dm_state->context, old_acrtc_state->stream)) { ret = -EINVAL; - break; + goto fail; } dc_stream_release(old_acrtc_state->stream); @@ -4455,7 +4457,7 @@ static int dm_update_crtcs_state( } else {/* Add stream for any updated/enabled CRTC */ if (modereset_required(crtc_state)) - continue; + goto next_crtc; if (modeset_required(crtc_state, new_stream, old_acrtc_state->stream)) { @@ -4473,19 +4475,25 @@ static int dm_update_crtcs_state( dm_state->context, new_acrtc_state->stream)) { ret = -EINVAL; - break; + goto fail; } *lock_and_validation_needed = true; } } +next_crtc: /* Release extra reference */ if (new_stream) dc_stream_release(new_stream); } return ret; + +fail: + if (new_stream) + dc_stream_release(new_stream); + return ret; } static int dm_update_planes_state( -- cgit From 156590454259a19d1709fab2ff7d59870574e822 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Wed, 23 Aug 2017 15:44:42 -0400 Subject: drm/amd/display: Clean up flattening core_dc to dc Clean up some code related to flattening core_dc commit (Remove redundent dc = dc, which was the result of removing DC_TO_CORE() macro) Signed-off-by: Bhawanpreet Lakha Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 12 +- drivers/gpu/drm/amd/display/dc/core/dc.c | 335 +++++++++------------ .../drm/amd/display/modules/freesync/freesync.c | 19 +- 3 files changed, 164 insertions(+), 202 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index afd403ceb2a7..5e5766a63a47 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -983,15 +983,14 @@ bool dcn_validate_bandwidth( if (v->voltage_level == 0 && (dc->debug.sr_exit_time_dpm0_ns || dc->debug.sr_enter_plus_exit_time_dpm0_ns)) { - struct dc *dc_core = dc; if (dc->debug.sr_enter_plus_exit_time_dpm0_ns) v->sr_enter_plus_exit_time = dc->debug.sr_enter_plus_exit_time_dpm0_ns / 1000.0f; if (dc->debug.sr_exit_time_dpm0_ns) v->sr_exit_time = dc->debug.sr_exit_time_dpm0_ns / 1000.0f; - dc_core->dml.soc.sr_enter_plus_exit_time_us = v->sr_enter_plus_exit_time; - dc_core->dml.soc.sr_exit_time_us = v->sr_exit_time; + dc->dml.soc.sr_enter_plus_exit_time_us = v->sr_enter_plus_exit_time; + dc->dml.soc.sr_exit_time_us = v->sr_exit_time; mode_support_and_system_configuration(v); } @@ -1114,11 +1113,10 @@ bool dcn_validate_bandwidth( } if (v->voltage_level == 0) { - struct dc *dc_core = dc; - dc_core->dml.soc.sr_enter_plus_exit_time_us = - dc_core->dcn_soc->sr_enter_plus_exit_time; - dc_core->dml.soc.sr_exit_time_us = dc_core->dcn_soc->sr_exit_time; + dc->dml.soc.sr_enter_plus_exit_time_us = + dc->dcn_soc->sr_enter_plus_exit_time; + dc->dml.soc.sr_exit_time_us = dc->dcn_soc->sr_exit_time; } /* diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 79980cb0900c..dc1b7d061be2 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -155,20 +155,19 @@ static bool stream_adjust_vmin_vmax(struct dc *dc, int vmin, int vmax) { /* TODO: Support multiple streams */ - struct dc *core_dc = dc; struct dc_stream_state *stream = streams[0]; int i = 0; bool ret = false; for (i = 0; i < MAX_PIPES; i++) { - struct pipe_ctx *pipe = &core_dc->current_context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *pipe = &dc->current_context->res_ctx.pipe_ctx[i]; if (pipe->stream == stream && pipe->stream_res.stream_enc) { - core_dc->hwss.set_drr(&pipe, 1, vmin, vmax); + dc->hwss.set_drr(&pipe, 1, vmin, vmax); /* build and update the info frame */ resource_build_info_frame(pipe); - core_dc->hwss.update_info_frame(pipe); + dc->hwss.update_info_frame(pipe); ret = true; } @@ -181,7 +180,6 @@ static bool stream_get_crtc_position(struct dc *dc, unsigned int *v_pos, unsigned int *nom_v_pos) { /* TODO: Support multiple streams */ - struct dc *core_dc = dc; struct dc_stream_state *stream = streams[0]; int i = 0; bool ret = false; @@ -189,10 +187,10 @@ static bool stream_get_crtc_position(struct dc *dc, for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe = - &core_dc->current_context->res_ctx.pipe_ctx[i]; + &dc->current_context->res_ctx.pipe_ctx[i]; if (pipe->stream == stream && pipe->stream_res.stream_enc) { - core_dc->hwss.get_position(&pipe, 1, &position); + dc->hwss.get_position(&pipe, 1, &position); *v_pos = position.vertical_count; *nom_v_pos = position.nominal_vcount; @@ -204,15 +202,14 @@ static bool stream_get_crtc_position(struct dc *dc, static bool set_gamut_remap(struct dc *dc, const struct dc_stream_state *stream) { - struct dc *core_dc = dc; int i = 0; bool ret = false; struct pipe_ctx *pipes; for (i = 0; i < MAX_PIPES; i++) { - if (core_dc->current_context->res_ctx.pipe_ctx[i].stream == stream) { - pipes = &core_dc->current_context->res_ctx.pipe_ctx[i]; - core_dc->hwss.program_gamut_remap(pipes); + if (dc->current_context->res_ctx.pipe_ctx[i].stream == stream) { + pipes = &dc->current_context->res_ctx.pipe_ctx[i]; + dc->hwss.program_gamut_remap(pipes); ret = true; } } @@ -222,17 +219,16 @@ static bool set_gamut_remap(struct dc *dc, const struct dc_stream_state *stream) static bool program_csc_matrix(struct dc *dc, struct dc_stream_state *stream) { - struct dc *core_dc = dc; int i = 0; bool ret = false; struct pipe_ctx *pipes; for (i = 0; i < MAX_PIPES; i++) { - if (core_dc->current_context->res_ctx.pipe_ctx[i].stream + if (dc->current_context->res_ctx.pipe_ctx[i].stream == stream) { - pipes = &core_dc->current_context->res_ctx.pipe_ctx[i]; - core_dc->hwss.program_csc_matrix(pipes, + pipes = &dc->current_context->res_ctx.pipe_ctx[i]; + dc->hwss.program_csc_matrix(pipes, stream->output_color_space, stream->csc_color_matrix.matrix); ret = true; @@ -247,7 +243,6 @@ static void set_static_screen_events(struct dc *dc, int num_streams, const struct dc_static_screen_events *events) { - struct dc *core_dc = dc; int i = 0; int j = 0; struct pipe_ctx *pipes_affected[MAX_PIPES]; @@ -257,45 +252,44 @@ static void set_static_screen_events(struct dc *dc, struct dc_stream_state *stream = streams[i]; for (j = 0; j < MAX_PIPES; j++) { - if (core_dc->current_context->res_ctx.pipe_ctx[j].stream + if (dc->current_context->res_ctx.pipe_ctx[j].stream == stream) { pipes_affected[num_pipes_affected++] = - &core_dc->current_context->res_ctx.pipe_ctx[j]; + &dc->current_context->res_ctx.pipe_ctx[j]; } } } - core_dc->hwss.set_static_screen_control(pipes_affected, num_pipes_affected, events); + dc->hwss.set_static_screen_control(pipes_affected, num_pipes_affected, events); } static void set_drive_settings(struct dc *dc, struct link_training_settings *lt_settings, const struct dc_link *link) { - struct dc *core_dc = dc; + int i; - for (i = 0; i < core_dc->link_count; i++) { - if (core_dc->links[i] == link) + for (i = 0; i < dc->link_count; i++) { + if (dc->links[i] == link) break; } - if (i >= core_dc->link_count) + if (i >= dc->link_count) ASSERT_CRITICAL(false); - dc_link_dp_set_drive_settings(core_dc->links[i], lt_settings); + dc_link_dp_set_drive_settings(dc->links[i], lt_settings); } static void perform_link_training(struct dc *dc, struct dc_link_settings *link_setting, bool skip_video_pattern) { - struct dc *core_dc = dc; int i; - for (i = 0; i < core_dc->link_count; i++) + for (i = 0; i < dc->link_count; i++) dc_link_dp_perform_link_training( - core_dc->links[i], + dc->links[i], link_setting, skip_video_pattern); } @@ -371,44 +365,44 @@ void set_dither_option(struct dc_stream_state *stream, opp_program_bit_depth_reduction(pipes->stream_res.opp, ¶ms); } -static void allocate_dc_stream_funcs(struct dc *core_dc) +static void allocate_dc_stream_funcs(struct dc *dc) { - if (core_dc->hwss.set_drr != NULL) { - core_dc->stream_funcs.adjust_vmin_vmax = + if (dc->hwss.set_drr != NULL) { + dc->stream_funcs.adjust_vmin_vmax = stream_adjust_vmin_vmax; } - core_dc->stream_funcs.set_static_screen_events = + dc->stream_funcs.set_static_screen_events = set_static_screen_events; - core_dc->stream_funcs.get_crtc_position = + dc->stream_funcs.get_crtc_position = stream_get_crtc_position; - core_dc->stream_funcs.set_gamut_remap = + dc->stream_funcs.set_gamut_remap = set_gamut_remap; - core_dc->stream_funcs.program_csc_matrix = + dc->stream_funcs.program_csc_matrix = program_csc_matrix; - core_dc->stream_funcs.set_dither_option = + dc->stream_funcs.set_dither_option = set_dither_option; - core_dc->link_funcs.set_drive_settings = + dc->link_funcs.set_drive_settings = set_drive_settings; - core_dc->link_funcs.perform_link_training = + dc->link_funcs.perform_link_training = perform_link_training; - core_dc->link_funcs.set_preferred_link_settings = + dc->link_funcs.set_preferred_link_settings = set_preferred_link_settings; - core_dc->link_funcs.enable_hpd = + dc->link_funcs.enable_hpd = enable_hpd; - core_dc->link_funcs.disable_hpd = + dc->link_funcs.disable_hpd = disable_hpd; - core_dc->link_funcs.set_test_pattern = + dc->link_funcs.set_test_pattern = set_test_pattern; } @@ -622,41 +616,41 @@ void ProgramPixelDurationV(unsigned int pixelClockInKHz ) struct dc *dc_create(const struct dc_init_data *init_params) { - struct dc *core_dc = dm_alloc(sizeof(*core_dc)); + struct dc *dc = dm_alloc(sizeof(*dc)); unsigned int full_pipe_count; - if (NULL == core_dc) + if (NULL == dc) goto alloc_fail; - if (false == construct(core_dc, init_params)) + if (false == construct(dc, init_params)) goto construct_fail; /*TODO: separate HW and SW initialization*/ - core_dc->hwss.init_hw(core_dc); + dc->hwss.init_hw(dc); - full_pipe_count = core_dc->res_pool->pipe_count; - if (core_dc->res_pool->underlay_pipe_index != NO_UNDERLAY_PIPE) + full_pipe_count = dc->res_pool->pipe_count; + if (dc->res_pool->underlay_pipe_index != NO_UNDERLAY_PIPE) full_pipe_count--; - core_dc->caps.max_streams = min( + dc->caps.max_streams = min( full_pipe_count, - core_dc->res_pool->stream_enc_count); + dc->res_pool->stream_enc_count); - core_dc->caps.max_links = core_dc->link_count; - core_dc->caps.max_audios = core_dc->res_pool->audio_count; + dc->caps.max_links = dc->link_count; + dc->caps.max_audios = dc->res_pool->audio_count; - core_dc->config = init_params->flags; + dc->config = init_params->flags; - dm_logger_write(core_dc->ctx->logger, LOG_DC, + dm_logger_write(dc->ctx->logger, LOG_DC, "Display Core initialized\n"); /* TODO: missing feature to be enabled */ - core_dc->debug.disable_dfs_bypass = true; + dc->debug.disable_dfs_bypass = true; - return core_dc; + return dc; construct_fail: - dm_free(core_dc); + dm_free(dc); alloc_fail: return NULL; @@ -664,9 +658,8 @@ alloc_fail: void dc_destroy(struct dc **dc) { - struct dc *core_dc = *dc; - destruct(core_dc); - dm_free(core_dc); + destruct(*dc); + dm_free(*dc); *dc = NULL; } @@ -674,7 +667,6 @@ bool dc_validate_guaranteed( struct dc *dc, struct dc_stream_state *stream) { - struct dc *core_dc = dc; enum dc_status result = DC_ERROR_UNEXPECTED; struct validate_context *context; @@ -687,14 +679,14 @@ bool dc_validate_guaranteed( atomic_inc(&context->ref_count); - result = core_dc->res_pool->funcs->validate_guaranteed( - core_dc, stream, context); + result = dc->res_pool->funcs->validate_guaranteed( + dc, stream, context); dc_release_validate_context(context); context_alloc_fail: if (result != DC_OK) { - dm_logger_write(core_dc->ctx->logger, LOG_WARNING, + dm_logger_write(dc->ctx->logger, LOG_WARNING, "%s:guaranteed validation failed, dc_status:%d\n", __func__, result); @@ -704,12 +696,12 @@ context_alloc_fail: } static void program_timing_sync( - struct dc *core_dc, + struct dc *dc, struct validate_context *ctx) { int i, j; int group_index = 0; - int pipe_count = core_dc->res_pool->pipe_count; + int pipe_count = dc->res_pool->pipe_count; struct pipe_ctx *unsynced_pipes[MAX_PIPES] = { NULL }; for (i = 0; i < pipe_count; i++) { @@ -770,8 +762,8 @@ static void program_timing_sync( } if (group_size > 1) { - core_dc->hwss.enable_timing_synchronization( - core_dc, group_index, group_size, pipe_set); + dc->hwss.enable_timing_synchronization( + dc, group_index, group_size, pipe_set); group_index++; } } @@ -803,17 +795,16 @@ bool dc_enable_stereo( bool ret = true; int i, j; struct pipe_ctx *pipe; - struct dc *core_dc = dc; for (i = 0; i < MAX_PIPES; i++) { if (context != NULL) pipe = &context->res_ctx.pipe_ctx[i]; else - pipe = &core_dc->current_context->res_ctx.pipe_ctx[i]; + pipe = &dc->current_context->res_ctx.pipe_ctx[i]; for (j = 0 ; pipe && j < stream_count; j++) { if (streams[j] && streams[j] == pipe->stream && - core_dc->hwss.setup_stereo) - core_dc->hwss.setup_stereo(pipe, core_dc); + dc->hwss.setup_stereo) + dc->hwss.setup_stereo(pipe, dc); } } @@ -827,8 +818,7 @@ bool dc_enable_stereo( */ static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *context) { - struct dc *core_dc = dc; - struct dc_bios *dcb = core_dc->ctx->dc_bios; + struct dc_bios *dcb = dc->ctx->dc_bios; enum dc_status result = DC_ERROR_UNEXPECTED; struct pipe_ctx *pipe; int i, j, k, l; @@ -838,22 +828,22 @@ static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *c dc_streams[i] = context->streams[i]; if (!dcb->funcs->is_accelerated_mode(dcb)) - core_dc->hwss.enable_accelerated_mode(core_dc); + dc->hwss.enable_accelerated_mode(dc); - for (i = 0; i < core_dc->res_pool->pipe_count; i++) { + for (i = 0; i < dc->res_pool->pipe_count; i++) { pipe = &context->res_ctx.pipe_ctx[i]; - core_dc->hwss.wait_for_mpcc_disconnect(core_dc, core_dc->res_pool, pipe); + dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, pipe); } - result = core_dc->hwss.apply_ctx_to_hw(core_dc, context); + result = dc->hwss.apply_ctx_to_hw(dc, context); - program_timing_sync(core_dc, context); + program_timing_sync(dc, context); for (i = 0; i < context->stream_count; i++) { const struct dc_sink *sink = context->streams[i]->sink; for (j = 0; j < context->stream_status[i].plane_count; j++) { - core_dc->hwss.apply_ctx_for_surface( - core_dc, context->streams[i], + dc->hwss.apply_ctx_for_surface( + dc, context->streams[i], context->stream_status[i].plane_count, context); @@ -867,8 +857,8 @@ static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *c for (l = 0 ; pipe && l < context->stream_count; l++) { if (context->streams[l] && context->streams[l] == pipe->stream && - core_dc->hwss.setup_stereo) - core_dc->hwss.setup_stereo(pipe, core_dc); + dc->hwss.setup_stereo) + dc->hwss.setup_stereo(pipe, dc); } } } @@ -883,11 +873,11 @@ static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *c dc_enable_stereo(dc, context, dc_streams, context->stream_count); - dc_release_validate_context(core_dc->current_context); + dc_release_validate_context(dc->current_context); - core_dc->current_context = context; + dc->current_context = context; - dc_retain_validate_context(core_dc->current_context); + dc_retain_validate_context(dc->current_context); return (result == DC_OK); } @@ -895,20 +885,19 @@ static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *c bool dc_commit_context(struct dc *dc, struct validate_context *context) { enum dc_status result = DC_ERROR_UNEXPECTED; - struct dc *core_dc = dc; int i; - if (false == context_changed(core_dc, context)) + if (false == context_changed(dc, context)) return DC_OK; - dm_logger_write(core_dc->ctx->logger, LOG_DC, "%s: %d streams\n", + dm_logger_write(dc->ctx->logger, LOG_DC, "%s: %d streams\n", __func__, context->stream_count); for (i = 0; i < context->stream_count; i++) { struct dc_stream_state *stream = context->streams[i]; dc_stream_log(stream, - core_dc->ctx->logger, + dc->ctx->logger, LOG_DC); } @@ -921,21 +910,20 @@ bool dc_commit_context(struct dc *dc, struct validate_context *context) bool dc_post_update_surfaces_to_stream(struct dc *dc) { int i; - struct dc *core_dc = dc; - struct validate_context *context = core_dc->current_context; + struct validate_context *context = dc->current_context; post_surface_trace(dc); - for (i = 0; i < core_dc->res_pool->pipe_count; i++) + for (i = 0; i < dc->res_pool->pipe_count; i++) if (context->res_ctx.pipe_ctx[i].stream == NULL || context->res_ctx.pipe_ctx[i].plane_state == NULL) - core_dc->hwss.power_down_front_end(core_dc, i); + dc->hwss.power_down_front_end(dc, i); /* 3rd param should be true, temp w/a for RV*/ #if defined(CONFIG_DRM_AMD_DC_DCN1_0) - core_dc->hwss.set_bandwidth(core_dc, context, core_dc->ctx->dce_version < DCN_VERSION_1_0); + dc->hwss.set_bandwidth(dc, context, dc->ctx->dce_version < DCN_VERSION_1_0); #else - core_dc->hwss.set_bandwidth(core_dc, context, true); + dc->hwss.set_bandwidth(dc, context, true); #endif return true; } @@ -1184,7 +1172,6 @@ enum surface_update_type dc_check_update_surfaces_for_stream( struct dc_stream_update *stream_update, const struct dc_stream_status *stream_status) { - struct dc *core_dc = dc; int i; enum surface_update_type overall_type = UPDATE_TYPE_FAST; @@ -1196,7 +1183,7 @@ enum surface_update_type dc_check_update_surfaces_for_stream( for (i = 0 ; i < surface_count; i++) { enum surface_update_type type = - det_surface_update(core_dc, &updates[i], i); + det_surface_update(dc, &updates[i], i); if (type == UPDATE_TYPE_FULL) return type; @@ -1230,12 +1217,11 @@ void dc_update_planes_and_stream(struct dc *dc, struct dc_stream_state *stream, struct dc_stream_update *stream_update) { - struct dc *core_dc = dc; struct validate_context *context; int i, j; enum surface_update_type update_type; const struct dc_stream_status *stream_status; - struct dc_context *dc_ctx = core_dc->ctx; + struct dc_context *dc_ctx = dc->ctx; stream_status = dc_stream_get_status(stream); @@ -1249,7 +1235,7 @@ void dc_update_planes_and_stream(struct dc *dc, ASSERT(0); } #endif - context = core_dc->current_context; + context = dc->current_context; /* update current stream with the new updates */ if (stream_update) { @@ -1303,7 +1289,7 @@ void dc_update_planes_and_stream(struct dc *dc, goto context_alloc_fail; dc_resource_validate_ctx_copy_construct( - core_dc->current_context, context); + dc->current_context, context); /*remove old surfaces from context */ if (!dc_rem_all_planes_for_stream(dc, stream, context)) { @@ -1365,7 +1351,7 @@ void dc_update_planes_and_stream(struct dc *dc, } if (update_type >= UPDATE_TYPE_MED) { - for (j = 0; j < core_dc->res_pool->pipe_count; j++) { + for (j = 0; j < dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; if (pipe_ctx->plane_state != surface) @@ -1403,31 +1389,31 @@ void dc_update_planes_and_stream(struct dc *dc, } if (update_type == UPDATE_TYPE_FULL) { - if (!core_dc->res_pool->funcs->validate_bandwidth(core_dc, context)) { + if (!dc->res_pool->funcs->validate_bandwidth(dc, context)) { BREAK_TO_DEBUGGER(); goto fail; } else { - core_dc->hwss.set_bandwidth(core_dc, context, false); + dc->hwss.set_bandwidth(dc, context, false); context_clock_trace(dc, context); } } if (update_type > UPDATE_TYPE_FAST) { - for (j = 0; j < core_dc->res_pool->pipe_count; j++) { + for (j = 0; j < dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - core_dc->hwss.wait_for_mpcc_disconnect(core_dc, core_dc->res_pool, pipe_ctx); + dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, pipe_ctx); } } if (surface_count == 0) - core_dc->hwss.apply_ctx_for_surface(core_dc, stream, surface_count, context); + dc->hwss.apply_ctx_for_surface(dc, stream, surface_count, context); /* Lock pipes for provided surfaces, or all active if full update*/ for (i = 0; i < surface_count; i++) { struct dc_plane_state *plane_state = srf_updates[i].surface; - for (j = 0; j < core_dc->res_pool->pipe_count; j++) { + for (j = 0; j < dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; if (update_type != UPDATE_TYPE_FULL && pipe_ctx->plane_state != plane_state) @@ -1435,8 +1421,8 @@ void dc_update_planes_and_stream(struct dc *dc, if (!pipe_ctx->plane_state || pipe_ctx->top_pipe) continue; - core_dc->hwss.pipe_control_lock( - core_dc, + dc->hwss.pipe_control_lock( + dc, pipe_ctx, true); } @@ -1445,9 +1431,9 @@ void dc_update_planes_and_stream(struct dc *dc, } /* Full fe update*/ - for (j = 0; j < core_dc->res_pool->pipe_count; j++) { + for (j = 0; j < dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - struct pipe_ctx *cur_pipe_ctx = &core_dc->current_context->res_ctx.pipe_ctx[j]; + struct pipe_ctx *cur_pipe_ctx = &dc->current_context->res_ctx.pipe_ctx[j]; bool is_new_pipe_surface = cur_pipe_ctx->plane_state != pipe_ctx->plane_state; struct dc_cursor_position position = { 0 }; @@ -1458,18 +1444,18 @@ void dc_update_planes_and_stream(struct dc *dc, if (!pipe_ctx->top_pipe && pipe_ctx->stream) { struct dc_stream_status *stream_status = stream_get_status(context, pipe_ctx->stream); - core_dc->hwss.apply_ctx_for_surface( - core_dc, pipe_ctx->stream, stream_status->plane_count, context); + dc->hwss.apply_ctx_for_surface( + dc, pipe_ctx->stream, stream_status->plane_count, context); } /* TODO: this is a hack w/a for switching from mpo to pipe split */ dc_stream_set_cursor_position(pipe_ctx->stream, &position); if (is_new_pipe_surface) { - core_dc->hwss.update_plane_addr(core_dc, pipe_ctx); - core_dc->hwss.set_input_transfer_func( + dc->hwss.update_plane_addr(dc, pipe_ctx); + dc->hwss.set_input_transfer_func( pipe_ctx, pipe_ctx->plane_state); - core_dc->hwss.set_output_transfer_func( + dc->hwss.set_output_transfer_func( pipe_ctx, pipe_ctx->stream); } } @@ -1482,40 +1468,40 @@ void dc_update_planes_and_stream(struct dc *dc, struct dc_plane_state *plane_state = srf_updates[i].surface; if (update_type == UPDATE_TYPE_MED) - core_dc->hwss.apply_ctx_for_surface( - core_dc, stream, surface_count, context); + dc->hwss.apply_ctx_for_surface( + dc, stream, surface_count, context); - for (j = 0; j < core_dc->res_pool->pipe_count; j++) { + for (j = 0; j < dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; if (pipe_ctx->plane_state != plane_state) continue; if (srf_updates[i].flip_addr) - core_dc->hwss.update_plane_addr(core_dc, pipe_ctx); + dc->hwss.update_plane_addr(dc, pipe_ctx); if (update_type == UPDATE_TYPE_FAST) continue; if (srf_updates[i].in_transfer_func) - core_dc->hwss.set_input_transfer_func( + dc->hwss.set_input_transfer_func( pipe_ctx, pipe_ctx->plane_state); if (stream_update != NULL && stream_update->out_transfer_func != NULL) { - core_dc->hwss.set_output_transfer_func( + dc->hwss.set_output_transfer_func( pipe_ctx, pipe_ctx->stream); } if (srf_updates[i].hdr_static_metadata) { resource_build_info_frame(pipe_ctx); - core_dc->hwss.update_info_frame(pipe_ctx); + dc->hwss.update_info_frame(pipe_ctx); } } } /* Unlock pipes */ - for (i = core_dc->res_pool->pipe_count - 1; i >= 0; i--) { + for (i = dc->res_pool->pipe_count - 1; i >= 0; i--) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; for (j = 0; j < surface_count; j++) { @@ -1525,8 +1511,8 @@ void dc_update_planes_and_stream(struct dc *dc, if (!pipe_ctx->plane_state || pipe_ctx->top_pipe) continue; - core_dc->hwss.pipe_control_lock( - core_dc, + dc->hwss.pipe_control_lock( + dc, pipe_ctx, false); @@ -1534,7 +1520,7 @@ void dc_update_planes_and_stream(struct dc *dc, } } - if (core_dc->current_context != context) { + if (dc->current_context != context) { /* Since memory free requires elevated IRQL, an interrupt * request is generated by mem free. If this happens @@ -1544,9 +1530,9 @@ void dc_update_planes_and_stream(struct dc *dc, * then free the old context. */ - struct validate_context *old = core_dc->current_context; + struct validate_context *old = dc->current_context; - core_dc->current_context = context; + dc->current_context = context; dc_release_validate_context(old); } @@ -1561,29 +1547,25 @@ context_alloc_fail: uint8_t dc_get_current_stream_count(struct dc *dc) { - struct dc *core_dc = dc; - return core_dc->current_context->stream_count; + return dc->current_context->stream_count; } struct dc_stream_state *dc_get_stream_at_index(struct dc *dc, uint8_t i) { - struct dc *core_dc = dc; - if (i < core_dc->current_context->stream_count) - return core_dc->current_context->streams[i]; + if (i < dc->current_context->stream_count) + return dc->current_context->streams[i]; return NULL; } struct dc_link *dc_get_link_at_index(struct dc *dc, uint32_t link_index) { - struct dc *core_dc = dc; - return core_dc->links[link_index]; + return dc->links[link_index]; } struct dwbc *dc_get_dwb_at_pipe(struct dc *dc, uint32_t pipe) { - struct dc *core_dc = dc; if ((pipe >= dwb_pipe0) && (pipe < dwb_pipe_max_num)) { - return core_dc->res_pool->dwbc[(int)pipe]; + return dc->res_pool->dwbc[(int)pipe]; } else { return NULL; } @@ -1592,21 +1574,18 @@ struct dwbc *dc_get_dwb_at_pipe(struct dc *dc, uint32_t pipe) const struct graphics_object_id dc_get_link_id_at_index( struct dc *dc, uint32_t link_index) { - struct dc *core_dc = dc; - return core_dc->links[link_index]->link_id; + return dc->links[link_index]->link_id; } enum dc_irq_source dc_get_hpd_irq_source_at_index( struct dc *dc, uint32_t link_index) { - struct dc *core_dc = dc; - return core_dc->links[link_index]->irq_source_hpd; + return dc->links[link_index]->irq_source_hpd; } const struct audio **dc_get_audios(struct dc *dc) { - struct dc *core_dc = dc; - return (const struct audio **)core_dc->res_pool->audios; + return (const struct audio **)dc->res_pool->audios; } enum dc_irq_source dc_interrupt_to_irq_source( @@ -1614,41 +1593,36 @@ enum dc_irq_source dc_interrupt_to_irq_source( uint32_t src_id, uint32_t ext_id) { - struct dc *core_dc = dc; - return dal_irq_service_to_irq_source(core_dc->res_pool->irqs, src_id, ext_id); + return dal_irq_service_to_irq_source(dc->res_pool->irqs, src_id, ext_id); } void dc_interrupt_set(struct dc *dc, enum dc_irq_source src, bool enable) { - struct dc *core_dc; if (dc == NULL) return; - core_dc = dc; - dal_irq_service_set(core_dc->res_pool->irqs, src, enable); + dal_irq_service_set(dc->res_pool->irqs, src, enable); } void dc_interrupt_ack(struct dc *dc, enum dc_irq_source src) { - struct dc *core_dc = dc; - dal_irq_service_ack(core_dc->res_pool->irqs, src); + dal_irq_service_ack(dc->res_pool->irqs, src); } void dc_set_power_state( struct dc *dc, enum dc_acpi_cm_power_state power_state) { - struct dc *core_dc = dc; atomic_t ref_count; switch (power_state) { case DC_ACPI_CM_POWER_STATE_D0: - core_dc->hwss.init_hw(core_dc); + dc->hwss.init_hw(dc); break; default: - core_dc->hwss.power_down(core_dc); + dc->hwss.power_down(dc); /* Zero out the current context so that on resume we start with * clean state, and dc hw programming optimizations will not @@ -1656,11 +1630,11 @@ void dc_set_power_state( */ /* Preserve refcount */ - ref_count = core_dc->current_context->ref_count; - dc_resource_validate_ctx_destruct(core_dc->current_context); - memset(core_dc->current_context, 0, - sizeof(*core_dc->current_context)); - core_dc->current_context->ref_count = ref_count; + ref_count = dc->current_context->ref_count; + dc_resource_validate_ctx_destruct(dc->current_context); + memset(dc->current_context, 0, + sizeof(*dc->current_context)); + dc->current_context->ref_count = ref_count; break; } @@ -1669,12 +1643,11 @@ void dc_set_power_state( void dc_resume(struct dc *dc) { - struct dc *core_dc = dc; uint32_t i; - for (i = 0; i < core_dc->link_count; i++) - core_link_resume(core_dc->links[i]); + for (i = 0; i < dc->link_count; i++) + core_link_resume(dc->links[i]); } bool dc_read_aux_dpcd( @@ -1684,9 +1657,8 @@ bool dc_read_aux_dpcd( uint8_t *data, uint32_t size) { - struct dc *core_dc = dc; - struct dc_link *link = core_dc->links[link_index]; + struct dc_link *link = dc->links[link_index]; enum ddc_result r = dal_ddc_service_read_dpcd_data( link->ddc, false, @@ -1704,8 +1676,7 @@ bool dc_write_aux_dpcd( const uint8_t *data, uint32_t size) { - struct dc *core_dc = dc; - struct dc_link *link = core_dc->links[link_index]; + struct dc_link *link = dc->links[link_index]; enum ddc_result r = dal_ddc_service_write_dpcd_data( link->ddc, @@ -1725,9 +1696,8 @@ bool dc_read_aux_i2c( uint8_t *data, uint32_t size) { - struct dc *core_dc = dc; - struct dc_link *link = core_dc->links[link_index]; + struct dc_link *link = dc->links[link_index]; enum ddc_result r = dal_ddc_service_read_dpcd_data( link->ddc, true, @@ -1746,8 +1716,7 @@ bool dc_write_aux_i2c( const uint8_t *data, uint32_t size) { - struct dc *core_dc = dc; - struct dc_link *link = core_dc->links[link_index]; + struct dc_link *link = dc->links[link_index]; enum ddc_result r = dal_ddc_service_write_dpcd_data( link->ddc, @@ -1768,9 +1737,8 @@ bool dc_query_ddc_data( uint8_t *read_buf, uint32_t read_size) { - struct dc *core_dc = dc; - struct dc_link *link = core_dc->links[link_index]; + struct dc_link *link = dc->links[link_index]; bool result = dal_ddc_service_query_ddc_data( link->ddc, @@ -1788,9 +1756,8 @@ bool dc_submit_i2c( uint32_t link_index, struct i2c_command *cmd) { - struct dc *core_dc = dc; - struct dc_link *link = core_dc->links[link_index]; + struct dc_link *link = dc->links[link_index]; struct ddc_service *ddc = link->ddc; return dal_i2caux_submit_i2c_command( @@ -1907,12 +1874,11 @@ void dc_link_remove_remote_sink(struct dc_link *link, struct dc_sink *sink) bool dc_init_dchub(struct dc *dc, struct dchub_init_data *dh_data) { int i; - struct dc *core_dc = dc; struct mem_input *mi = NULL; - for (i = 0; i < core_dc->res_pool->pipe_count; i++) { - if (core_dc->res_pool->mis[i] != NULL) { - mi = core_dc->res_pool->mis[i]; + for (i = 0; i < dc->res_pool->pipe_count; i++) { + if (dc->res_pool->mis[i] != NULL) { + mi = dc->res_pool->mis[i]; break; } } @@ -1921,10 +1887,10 @@ bool dc_init_dchub(struct dc *dc, struct dchub_init_data *dh_data) return false; } - if (core_dc->hwss.update_dchub) - core_dc->hwss.update_dchub(core_dc->hwseq, dh_data); + if (dc->hwss.update_dchub) + dc->hwss.update_dchub(dc->hwseq, dh_data); else - ASSERT(core_dc->hwss.update_dchub); + ASSERT(dc->hwss.update_dchub); return true; @@ -1933,9 +1899,8 @@ bool dc_init_dchub(struct dc *dc, struct dchub_init_data *dh_data) void dc_log_hw_state(struct dc *dc) { - struct dc *core_dc = dc; - if (core_dc->hwss.log_hw_state) - core_dc->hwss.log_hw_state(core_dc); + if (dc->hwss.log_hw_state) + dc->hwss.log_hw_state(dc); } diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index f49203b3eb94..52350d0e68d0 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -145,7 +145,6 @@ struct mod_freesync *mod_freesync_create(struct dc *dc) struct core_freesync *core_freesync = dm_alloc(sizeof(struct core_freesync)); - struct dc *core_dc = dc; struct persistent_data_flag flag; @@ -176,19 +175,19 @@ struct mod_freesync *mod_freesync_create(struct dc *dc) /* Create initial module folder in registry for freesync enable data */ flag.save_per_edid = true; flag.save_per_link = false; - dm_write_persistent_data(core_dc->ctx, NULL, FREESYNC_REGISTRY_NAME, + dm_write_persistent_data(dc->ctx, NULL, FREESYNC_REGISTRY_NAME, NULL, NULL, 0, &flag); flag.save_per_edid = false; flag.save_per_link = false; - if (dm_read_persistent_data(core_dc->ctx, NULL, NULL, + if (dm_read_persistent_data(dc->ctx, NULL, NULL, FREESYNC_NO_STATIC_FOR_INTERNAL_REGKEY, &data, sizeof(data), &flag)) { core_freesync->opts.drr_internal_supported = (data & 1) ? false : true; } - if (dm_read_persistent_data(core_dc->ctx, NULL, NULL, + if (dm_read_persistent_data(dc->ctx, NULL, NULL, FREESYNC_NO_STATIC_FOR_EXTERNAL_DP_REGKEY, &data, sizeof(data), &flag)) { core_freesync->opts.drr_external_supported = @@ -245,7 +244,7 @@ static unsigned int map_index_from_stream(struct core_freesync *core_freesync, bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, struct dc_stream_state *stream, struct mod_freesync_caps *caps) { - struct dc *core_dc = NULL; + struct dc *dc = NULL; struct core_freesync *core_freesync = NULL; int persistent_freesync_enable = 0; struct persistent_data_flag flag; @@ -256,7 +255,7 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, return false; core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync); - core_dc = core_freesync->dc; + dc = core_freesync->dc; flag.save_per_edid = true; flag.save_per_link = false; @@ -287,7 +286,7 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, static_ramp.ramp_is_active = false; /* get persistent data from registry */ - if (dm_read_persistent_data(core_dc->ctx, stream->sink, + if (dm_read_persistent_data(dc->ctx, stream->sink, FREESYNC_REGISTRY_NAME, "userenable", &persistent_freesync_enable, sizeof(int), &flag)) { @@ -970,14 +969,14 @@ bool mod_freesync_set_user_enable(struct mod_freesync *mod_freesync, unsigned int stream_index, map_index; int persistent_data = 0; struct persistent_data_flag flag; - struct dc *core_dc = NULL; + struct dc *dc = NULL; struct core_freesync *core_freesync = NULL; if (mod_freesync == NULL) return false; core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync); - core_dc = core_freesync->dc; + dc = core_freesync->dc; flag.save_per_edid = true; flag.save_per_link = false; @@ -1001,7 +1000,7 @@ bool mod_freesync_set_user_enable(struct mod_freesync *mod_freesync, enable_for_video) persistent_data = persistent_data | 4; - dm_write_persistent_data(core_dc->ctx, + dm_write_persistent_data(dc->ctx, streams[stream_index]->sink, FREESYNC_REGISTRY_NAME, "userenable", -- cgit From 1cf49dea28dfc76f0816a4bc73c2ab975c72f55d Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Wed, 23 Aug 2017 17:02:34 -0400 Subject: drm/amd/display: do not reset lane count in EQ fallback [Description] According to DP1.4 specs we should not reset lane count back when falling back in failing EQ training. This causes PHY test pattern compliance to fail as infinite LT when LT fails EQ to 4 RBR and fails CR in a loop. Signed-off-by: Wenjing Liu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/gpu') 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 e19447d526ea..446e2933474c 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 @@ -1302,8 +1302,6 @@ bool decide_fallback_link_setting( current_link_setting->lane_count); } else if (!reached_minimum_link_rate (current_link_setting->link_rate)) { - current_link_setting->lane_count = - initial_link_settings.lane_count; current_link_setting->link_rate = reduce_link_rate( current_link_setting->link_rate); -- cgit From e1b522bff39d4834f4cfedc557857bb4d50f3946 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Thu, 24 Aug 2017 17:29:24 -0400 Subject: drm/amd/display: work around for 8k sleep crash Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 1 + drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 5e5766a63a47..6c85a54e47d6 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -581,6 +581,7 @@ static void split_stream_across_pipes( secondary_pipe->plane_res.ipp = pool->ipps[secondary_pipe->pipe_idx]; secondary_pipe->plane_res.xfm = pool->transforms[secondary_pipe->pipe_idx]; if (primary_pipe->bottom_pipe) { + ASSERT(primary_pipe->bottom_pipe != secondary_pipe); secondary_pipe->bottom_pipe = primary_pipe->bottom_pipe; secondary_pipe->bottom_pipe->top_pipe = secondary_pipe; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index bd023299e2af..498680a9b996 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2358,7 +2358,7 @@ static void program_all_pipe_in_tree( verify_allow_pstate_change_high(dc->hwseq); } - if (pipe_ctx->bottom_pipe != NULL) + if (pipe_ctx->bottom_pipe != NULL && pipe_ctx->bottom_pipe != pipe_ctx) program_all_pipe_in_tree(dc, pipe_ctx->bottom_pipe, context); } -- cgit From aac6a07e40dea7996851c81f9a5f0e433b806086 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Wed, 23 Aug 2017 16:54:03 -0400 Subject: drm/amd/display: Use DRM provided page flip flag. Starting with 4.12 kernel DRM provides page flip flags so we don't need to have our own copy. Signed-off-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'drivers/gpu') 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 4f1e31cd4cbe..9c44b82036fa 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3767,7 +3767,7 @@ static void amdgpu_dm_do_flip( struct amdgpu_framebuffer *afb = to_amdgpu_framebuffer(fb); struct amdgpu_bo *abo = gem_to_amdgpu_bo(afb->obj); struct amdgpu_device *adev = crtc->dev->dev_private; - bool async_flip = (acrtc->flip_flags & DRM_MODE_PAGE_FLIP_ASYNC) != 0; + bool async_flip = (crtc->state->pageflip_flags & DRM_MODE_PAGE_FLIP_ASYNC) != 0; struct dc_flip_addrs addr = { {0} }; /* TODO eliminate or rename surface_update */ struct dc_surface_update surface_updates[1] = { {0} }; @@ -3899,7 +3899,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, * TODO Check if it's correct */ *wait_for_vblank = - acrtc_attach->flip_flags & DRM_MODE_PAGE_FLIP_ASYNC ? + pcrtc->state->pageflip_flags & DRM_MODE_PAGE_FLIP_ASYNC ? false : true; /* TODO: Needs rework for multiplane flip */ @@ -3910,11 +3910,6 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, crtc, fb, drm_crtc_vblank_count(crtc) + *wait_for_vblank); - - /*TODO BUG remove ASAP in 4.12 to avoid race between worker and flip IOCTL */ - - /*clean up the flags for next usage*/ - acrtc_attach->flip_flags = 0; } } -- cgit From 96313f1b7a4b14c8e120564698aa3be709445324 Mon Sep 17 00:00:00 2001 From: Jerry Zuo Date: Thu, 24 Aug 2017 16:03:02 -0400 Subject: drm/amd/display: Fix MST downstream display not light up regression The fix is for the scenario: MST+SST chain together, and hook up to the card. Regression: Per stream validate_context build v2 Before dc_add_stream_to_ctx(), need to update/reset stream signal type to SIGNAL_TYPE_DISPLAY_PORT_MST. Otherwise, downstream device cannot be added to ctx due to the lack of signal type info (SIGNAL_TYPE_NONE). update_stream_signal() needs to be done after stream is created. Signed-off-by: Jerry Zuo Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 25 ----------------------- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 24 ++++++++++++++++++++++ 2 files changed, 24 insertions(+), 25 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 6eee1b1a563e..9eb8d48bc889 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1323,7 +1323,6 @@ bool dc_is_stream_unchanged( /* Maximum TMDS single link pixel clock 165MHz */ #define TMDS_MAX_PIXEL_CLOCK_IN_KHZ 165000 -#define TMDS_MAX_PIXEL_CLOCK_IN_KHZ_UPMOST 297000 static void update_stream_engine_usage( struct resource_context *res_ctx, @@ -1434,28 +1433,6 @@ static struct audio *find_first_free_audio( return 0; } -static void update_stream_signal(struct dc_stream_state *stream) -{ - if (stream->output_signal == SIGNAL_TYPE_NONE) { - struct dc_sink *dc_sink = stream->sink; - - if (dc_sink->sink_signal == SIGNAL_TYPE_NONE) - stream->signal = stream->sink->link->connector_signal; - else - stream->signal = dc_sink->sink_signal; - } else { - stream->signal = stream->output_signal; - } - - if (dc_is_dvi_signal(stream->signal)) { - if (stream->timing.pix_clk_khz > TMDS_MAX_PIXEL_CLOCK_IN_KHZ_UPMOST && - stream->sink->sink_signal != SIGNAL_TYPE_DVI_SINGLE_LINK) - stream->signal = SIGNAL_TYPE_DVI_DUAL_LINK; - else - stream->signal = SIGNAL_TYPE_DVI_SINGLE_LINK; - } -} - bool resource_is_stream_unchanged( struct validate_context *old_context, struct dc_stream_state *stream) { @@ -1627,8 +1604,6 @@ static int get_norm_pix_clk(const struct dc_crtc_timing *timing) static void calculate_phy_pix_clks(struct dc_stream_state *stream) { - update_stream_signal(stream); - /* update actual pixel clock on all streams */ if (dc_is_hdmi_signal(stream->signal)) stream->phy_pix_clk = get_norm_pix_clk( diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index aaa6d2326190..0e7cc293184e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -33,6 +33,28 @@ /******************************************************************************* * Private functions ******************************************************************************/ +#define TMDS_MAX_PIXEL_CLOCK_IN_KHZ_UPMOST 297000 +static void update_stream_signal(struct dc_stream_state *stream) +{ + if (stream->output_signal == SIGNAL_TYPE_NONE) { + struct dc_sink *dc_sink = stream->sink; + + if (dc_sink->sink_signal == SIGNAL_TYPE_NONE) + stream->signal = stream->sink->link->connector_signal; + else + stream->signal = dc_sink->sink_signal; + } else { + stream->signal = stream->output_signal; + } + + if (dc_is_dvi_signal(stream->signal)) { + if (stream->timing.pix_clk_khz > TMDS_MAX_PIXEL_CLOCK_IN_KHZ_UPMOST && + stream->sink->sink_signal != SIGNAL_TYPE_DVI_SINGLE_LINK) + stream->signal = SIGNAL_TYPE_DVI_DUAL_LINK; + else + stream->signal = SIGNAL_TYPE_DVI_SINGLE_LINK; + } +} static bool construct(struct dc_stream_state *stream, struct dc_sink *dc_sink_data) @@ -80,6 +102,8 @@ static bool construct(struct dc_stream_state *stream, stream->timing.flags.LTE_340MCSC_SCRAMBLE = dc_sink_data->edid_caps.lte_340mcsc_scramble; stream->status.link = stream->sink->link; + + update_stream_signal(stream); return true; } -- cgit From b656c34e24b5af59a5e8e1f0fbc740c3fc2d5ad8 Mon Sep 17 00:00:00 2001 From: Eric Bernstein Date: Thu, 24 Aug 2017 16:16:50 -0400 Subject: drm/amd/display: Update DSCL Signed-off-by: Eric Bernstein Signed-off-by: Tony Cheng Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c | 101 ++++++--------------- 1 file changed, 29 insertions(+), 72 deletions(-) (limited to 'drivers/gpu') 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 76d5f5d4d82f..33830639e210 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 @@ -215,14 +215,18 @@ static void dpp_set_lb( { uint32_t pixel_depth = get_pixel_depth_val(lb_params->depth); uint32_t dyn_pix_depth = lb_params->dynamic_pixel_depth; - REG_SET_7(LB_DATA_FORMAT, 0, - PIXEL_DEPTH, pixel_depth, /* Pixel depth stored in LB */ - PIXEL_EXPAN_MODE, lb_params->pixel_expan_mode, /* Pixel expansion mode */ - PIXEL_REDUCE_MODE, 1, /* Pixel reduction mode: Rounding */ - DYNAMIC_PIXEL_DEPTH, dyn_pix_depth, /* Dynamic expansion pixel depth */ - DITHER_EN, 0, /* Dithering enable: Disabled */ - INTERLEAVE_EN, lb_params->interleave_en, /* Interleave source enable */ - ALPHA_EN, lb_params->alpha_en); /* Alpha enable */ + + /* LB */ + if (xfm->tf_mask->PIXEL_DEPTH) { + REG_SET_7(LB_DATA_FORMAT, 0, + PIXEL_DEPTH, pixel_depth, /* Pixel depth stored in LB */ + PIXEL_EXPAN_MODE, lb_params->pixel_expan_mode, /* Pixel expansion mode */ + PIXEL_REDUCE_MODE, 1, /* Pixel reduction mode: Rounding */ + DYNAMIC_PIXEL_DEPTH, dyn_pix_depth, /* Dynamic expansion pixel depth */ + DITHER_EN, 0, /* Dithering enable: Disabled */ + INTERLEAVE_EN, lb_params->interleave_en, /* Interleave source enable */ + ALPHA_EN, lb_params->alpha_en); /* Alpha enable */ + } REG_SET_2(LB_MEMORY_CTRL, 0, MEMORY_CONFIG, mem_size_config, @@ -462,7 +466,8 @@ static bool is_lb_conf_valid(int ceil_vratio, int num_partitions, int vtaps) } /*find first match configuration which meets the min required lb size*/ -static enum lb_memory_config find_lb_memory_config(const struct scaler_data *scl_data) +static enum lb_memory_config dpp10_find_lb_memory_config( + const struct scaler_data *scl_data) { int num_part_y, num_part_c; int vtaps = scl_data->taps.v_taps; @@ -504,6 +509,18 @@ static enum lb_memory_config find_lb_memory_config(const struct scaler_data *scl return LB_MEMORY_CONFIG_0; } +/*find first match configuration which meets the min required lb size*/ +static enum lb_memory_config find_lb_memory_config(struct dcn10_dpp *xfm, + const struct scaler_data *scl_data) +{ + enum lb_memory_config mem_cfg = LB_MEMORY_CONFIG_0; + + if (xfm->tf_mask->PIXEL_DEPTH) { + mem_cfg = dpp10_find_lb_memory_config(scl_data); + } + return mem_cfg; +} + void dpp_set_scaler_auto_scale( struct transform *xfm_base, const struct scaler_data *scl_data) @@ -524,7 +541,7 @@ void dpp_set_scaler_auto_scale( if (dscl_mode == DSCL_MODE_DSCL_BYPASS) return; - lb_config = find_lb_memory_config(scl_data); + lb_config = find_lb_memory_config(xfm, scl_data); dpp_set_lb(xfm, &scl_data->lb_params, lb_config); if (dscl_mode == DSCL_MODE_SCALING_444_BYPASS) @@ -662,8 +679,9 @@ void dcn10_dpp_dscl_set_scaler_manual_scale( if (dscl_mode == DSCL_MODE_DSCL_BYPASS) return; + /* LB */ - lb_config = find_lb_memory_config(scl_data); + lb_config = find_lb_memory_config(xfm, scl_data); dpp_set_lb(xfm, &scl_data->lb_params, lb_config); if (dscl_mode == DSCL_MODE_SCALING_444_BYPASS) @@ -699,64 +717,3 @@ void dcn10_dpp_dscl_set_scaler_manual_scale( dpp_set_scl_filter(xfm, scl_data, ycbcr); } - -#if 0 -bool dpp_set_pixel_storage_depth( - struct dpp *xfm, - enum lb_pixel_depth depth, - const struct bit_depth_reduction_params *bit_depth_params) -{ - struct dcn10_dpp *xfm110 = TO_DCN10_DPP(xfm); - bool ret = true; - uint32_t value; - enum dc_color_depth color_depth; - - value = dm_read_reg(xfm->ctx, LB_REG(mmLB_DATA_FORMAT)); - switch (depth) { - case LB_PIXEL_DEPTH_18BPP: - color_depth = COLOR_DEPTH_666; - set_reg_field_value(value, 2, LB_DATA_FORMAT, PIXEL_DEPTH); - set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_EXPAN_MODE); - break; - case LB_PIXEL_DEPTH_24BPP: - color_depth = COLOR_DEPTH_888; - set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_DEPTH); - set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_EXPAN_MODE); - break; - case LB_PIXEL_DEPTH_30BPP: - color_depth = COLOR_DEPTH_101010; - set_reg_field_value(value, 0, LB_DATA_FORMAT, PIXEL_DEPTH); - set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_EXPAN_MODE); - break; - case LB_PIXEL_DEPTH_36BPP: - color_depth = COLOR_DEPTH_121212; - set_reg_field_value(value, 3, LB_DATA_FORMAT, PIXEL_DEPTH); - set_reg_field_value(value, 0, LB_DATA_FORMAT, PIXEL_EXPAN_MODE); - break; - default: - ret = false; - break; - } - - if (ret == true) { - set_denormalization(xfm110, color_depth); - ret = program_bit_depth_reduction(xfm110, color_depth, - bit_depth_params); - - set_reg_field_value(value, 0, LB_DATA_FORMAT, ALPHA_EN); - dm_write_reg(xfm->ctx, LB_REG(mmLB_DATA_FORMAT), value); - if (!(xfm110->lb_pixel_depth_supported & depth)) { - /* We should use unsupported capabilities - * unless it is required by w/a - */ - dm_logger_write(xfm->ctx->logger, LOG_WARNING, - "%s: Capability not supported", - __func__); - } - } - - return ret; -} -#endif - - -- cgit From b3c340fad4643b7351a4777fae37e58925db04c9 Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Sat, 19 Aug 2017 16:34:36 -0400 Subject: drm/amd/display: move cm registers from ipp to dpp_cm Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c | 150 +++++ drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h | 489 ++++++++++++++- .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c | 555 +++++++++++++++++ .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c | 3 +- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 20 +- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c | 676 +-------------------- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h | 416 ------------- drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h | 18 + drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h | 17 +- drivers/gpu/drm/amd/display/dc/inc/hw/transform.h | 20 + 10 files changed, 1239 insertions(+), 1125 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c index 30722495de0a..20163668e2a8 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c @@ -52,6 +52,12 @@ #define FN(reg_name, field_name) \ xfm->tf_shift->field_name, xfm->tf_mask->field_name +enum pixel_format_description { + PIXEL_FORMAT_FIXED = 0, + PIXEL_FORMAT_FIXED16, + PIXEL_FORMAT_FLOAT + +}; enum dcn10_coef_filter_type_sel { SCL_COEF_LUMA_VERT_FILTER = 0, @@ -249,6 +255,145 @@ static void dcn10_dpp_cm_set_regamma_mode( OBUF_H_2X_UPSCALE_EN, obuf_hupscale); } +static void ippn10_setup_format_flags(enum surface_pixel_format input_format,\ + enum pixel_format_description *fmt) +{ + + if (input_format == SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F || + input_format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F) + *fmt = PIXEL_FORMAT_FLOAT; + else if (input_format == SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616) + *fmt = PIXEL_FORMAT_FIXED16; + else + *fmt = PIXEL_FORMAT_FIXED; +} + +static void ippn10_set_degamma_format_float( + struct transform *xfm_base, + bool is_float) +{ + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + + if (is_float) { + REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_INPUT_FORMAT, 3); + REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, 1); + } else { + REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_INPUT_FORMAT, 2); + REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, 0); + } +} + +void ippn10_cnv_setup ( + struct transform *xfm_base, + enum surface_pixel_format input_format, + enum expansion_mode mode, + enum ipp_output_format cnv_out_format) +{ + uint32_t pixel_format; + uint32_t alpha_en; + enum pixel_format_description fmt ; + enum dc_color_space color_space; + enum dcn10_input_csc_select select; + bool is_float; + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + bool force_disable_cursor = false; + + ippn10_setup_format_flags(input_format, &fmt); + alpha_en = 1; + pixel_format = 0; + color_space = COLOR_SPACE_SRGB; + select = INPUT_CSC_SELECT_BYPASS; + is_float = false; + + switch (fmt) { + case PIXEL_FORMAT_FIXED: + case PIXEL_FORMAT_FIXED16: + /*when output is float then FORMAT_CONTROL__OUTPUT_FP=1*/ + REG_SET_3(FORMAT_CONTROL, 0, + CNVC_BYPASS, 0, + FORMAT_EXPANSION_MODE, mode, + OUTPUT_FP, 0); + break; + case PIXEL_FORMAT_FLOAT: + REG_SET_3(FORMAT_CONTROL, 0, + CNVC_BYPASS, 0, + FORMAT_EXPANSION_MODE, mode, + OUTPUT_FP, 1); + is_float = true; + break; + default: + + break; + } + + ippn10_set_degamma_format_float(xfm_base, is_float); + + switch (input_format) { + case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: + pixel_format = 1; + break; + case SURFACE_PIXEL_FORMAT_GRPH_RGB565: + pixel_format = 3; + alpha_en = 0; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: + pixel_format = 8; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: + pixel_format = 10; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: + force_disable_cursor = false; + pixel_format = 65; + color_space = COLOR_SPACE_YCBCR709; + select = INPUT_CSC_SELECT_ICSC; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: + force_disable_cursor = true; + pixel_format = 64; + color_space = COLOR_SPACE_YCBCR709; + select = INPUT_CSC_SELECT_ICSC; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: + force_disable_cursor = true; + pixel_format = 67; + color_space = COLOR_SPACE_YCBCR709; + select = INPUT_CSC_SELECT_ICSC; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: + force_disable_cursor = true; + pixel_format = 66; + color_space = COLOR_SPACE_YCBCR709; + select = INPUT_CSC_SELECT_ICSC; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: + pixel_format = 22; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: + pixel_format = 24; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: + pixel_format = 25; + break; + default: + break; + } + REG_SET(CNVC_SURFACE_PIXEL_FORMAT, 0, + CNVC_SURFACE_PIXEL_FORMAT, pixel_format); + REG_UPDATE(FORMAT_CONTROL, FORMAT_CONTROL__ALPHA_EN, alpha_en); + + ippn10_program_input_csc(xfm_base, color_space, select); + + if (force_disable_cursor) { + REG_UPDATE(CURSOR_CONTROL, + CURSOR_ENABLE, 0); + REG_UPDATE(CURSOR0_CONTROL, + CUR0_ENABLE, 0); + } +} + static struct transform_funcs dcn10_dpp_funcs = { .transform_reset = dpp_reset, .transform_set_scaler = dcn10_dpp_dscl_set_scaler_manual_scale, @@ -263,6 +408,11 @@ static struct transform_funcs dcn10_dpp_funcs = { .opp_program_regamma_luta_settings = dcn10_dpp_cm_program_regamma_luta_settings, .opp_program_regamma_pwl = dcn10_dpp_cm_set_regamma_pwl, .opp_set_regamma_mode = dcn10_dpp_cm_set_regamma_mode, + .ipp_set_degamma = ippn10_set_degamma, + .ipp_program_input_lut = ippn10_program_input_lut, + .ipp_program_degamma_pwl = ippn10_set_degamma_pwl, + .ipp_setup = ippn10_cnv_setup, + .ipp_full_bypass = ippn10_full_bypass, }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h index 18ee338f6b28..9a678dcaa908 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h @@ -37,6 +37,10 @@ #define TF_SF(reg_name, field_name, post_fix)\ .field_name = reg_name ## __ ## field_name ## post_fix +//Used to resolve corner case +#define TF2_SF(reg_name, field_name, post_fix)\ + .field_name = reg_name ## _ ## field_name ## post_fix + #define TF_REG_LIST_DCN(id) \ SRI(CM_GAMUT_REMAP_CONTROL, CM, id),\ SRI(CM_GAMUT_REMAP_C11_C12, CM, id),\ @@ -72,7 +76,65 @@ SRI(SCL_VERT_FILTER_INIT_BOT_C, DSCL, id), \ SRI(RECOUT_START, DSCL, id), \ SRI(RECOUT_SIZE, DSCL, id), \ - SRI(OBUF_CONTROL, DSCL, id) + SRI(OBUF_CONTROL, DSCL, id), \ + SRI(CM_ICSC_CONTROL, CM, id), \ + SRI(CM_ICSC_C11_C12, CM, id), \ + SRI(CM_ICSC_C13_C14, CM, id), \ + SRI(CM_ICSC_C21_C22, CM, id), \ + SRI(CM_ICSC_C23_C24, CM, id), \ + SRI(CM_ICSC_C31_C32, CM, id), \ + SRI(CM_ICSC_C33_C34, CM, id), \ + SRI(CM_DGAM_RAMB_START_CNTL_B, CM, id), \ + SRI(CM_DGAM_RAMB_START_CNTL_G, CM, id), \ + SRI(CM_DGAM_RAMB_START_CNTL_R, CM, id), \ + SRI(CM_DGAM_RAMB_SLOPE_CNTL_B, CM, id), \ + SRI(CM_DGAM_RAMB_SLOPE_CNTL_G, CM, id), \ + SRI(CM_DGAM_RAMB_SLOPE_CNTL_R, CM, id), \ + SRI(CM_DGAM_RAMB_END_CNTL1_B, CM, id), \ + SRI(CM_DGAM_RAMB_END_CNTL2_B, CM, id), \ + SRI(CM_DGAM_RAMB_END_CNTL1_G, CM, id), \ + SRI(CM_DGAM_RAMB_END_CNTL2_G, CM, id), \ + SRI(CM_DGAM_RAMB_END_CNTL1_R, CM, id), \ + SRI(CM_DGAM_RAMB_END_CNTL2_R, CM, id), \ + SRI(CM_DGAM_RAMB_REGION_0_1, CM, id), \ + SRI(CM_DGAM_RAMB_REGION_2_3, CM, id), \ + SRI(CM_DGAM_RAMB_REGION_4_5, CM, id), \ + SRI(CM_DGAM_RAMB_REGION_6_7, CM, id), \ + SRI(CM_DGAM_RAMB_REGION_8_9, CM, id), \ + SRI(CM_DGAM_RAMB_REGION_10_11, CM, id), \ + SRI(CM_DGAM_RAMB_REGION_12_13, CM, id), \ + SRI(CM_DGAM_RAMB_REGION_14_15, CM, id), \ + SRI(CM_DGAM_RAMA_START_CNTL_B, CM, id), \ + SRI(CM_DGAM_RAMA_START_CNTL_G, CM, id), \ + SRI(CM_DGAM_RAMA_START_CNTL_R, CM, id), \ + SRI(CM_DGAM_RAMA_SLOPE_CNTL_B, CM, id), \ + SRI(CM_DGAM_RAMA_SLOPE_CNTL_G, CM, id), \ + SRI(CM_DGAM_RAMA_SLOPE_CNTL_R, CM, id), \ + SRI(CM_DGAM_RAMA_END_CNTL1_B, CM, id), \ + SRI(CM_DGAM_RAMA_END_CNTL2_B, CM, id), \ + SRI(CM_DGAM_RAMA_END_CNTL1_G, CM, id), \ + SRI(CM_DGAM_RAMA_END_CNTL2_G, CM, id), \ + SRI(CM_DGAM_RAMA_END_CNTL1_R, CM, id), \ + SRI(CM_DGAM_RAMA_END_CNTL2_R, CM, id), \ + SRI(CM_DGAM_RAMA_REGION_0_1, CM, id), \ + SRI(CM_DGAM_RAMA_REGION_2_3, CM, id), \ + SRI(CM_DGAM_RAMA_REGION_4_5, CM, id), \ + SRI(CM_DGAM_RAMA_REGION_6_7, CM, id), \ + SRI(CM_DGAM_RAMA_REGION_8_9, CM, id), \ + SRI(CM_DGAM_RAMA_REGION_10_11, CM, id), \ + SRI(CM_DGAM_RAMA_REGION_12_13, CM, id), \ + SRI(CM_DGAM_RAMA_REGION_14_15, CM, id), \ + SRI(CM_MEM_PWR_CTRL, CM, id), \ + SRI(CM_DGAM_LUT_WRITE_EN_MASK, CM, id), \ + SRI(CM_DGAM_LUT_INDEX, CM, id), \ + SRI(CM_DGAM_LUT_DATA, CM, id), \ + SRI(CM_CONTROL, CM, id), \ + SRI(CM_DGAM_CONTROL, CM, id), \ + SRI(FORMAT_CONTROL, CNVC_CFG, id), \ + SRI(CNVC_SURFACE_PIXEL_FORMAT, CNVC_CFG, id), \ + SRI(CURSOR0_CONTROL, CNVC_CUR, id) + + #define TF_REG_LIST_DCN10(id) \ TF_REG_LIST_DCN(id), \ @@ -157,7 +219,12 @@ SRI(CM_RGAM_RAMA_REGION_28_29, CM, id), \ SRI(CM_RGAM_RAMA_REGION_30_31, CM, id), \ SRI(CM_RGAM_RAMA_REGION_32_33, CM, id), \ - SRI(CM_RGAM_CONTROL, CM, id) + SRI(CM_RGAM_CONTROL, CM, id), \ + SRI(CM_IGAM_CONTROL, CM, id), \ + SRI(CM_IGAM_LUT_RW_CONTROL, CM, id), \ + SRI(CM_IGAM_LUT_RW_INDEX, CM, id), \ + SRI(CM_IGAM_LUT_SEQ_COLOR, CM, id), \ + SRI(CURSOR_CONTROL, CURSOR, id) #define TF_REG_LIST_SH_MASK_DCN(mask_sh)\ @@ -183,7 +250,7 @@ TF_SF(DSCL0_OTG_V_BLANK, OTG_V_BLANK_START, mask_sh),\ TF_SF(DSCL0_OTG_V_BLANK, OTG_V_BLANK_END, mask_sh),\ TF_SF(DSCL0_LB_DATA_FORMAT, INTERLEAVE_EN, mask_sh),\ - TF_SF(DSCL0_LB_DATA_FORMAT, ALPHA_EN, mask_sh),\ + TF2_SF(DSCL0, LB_DATA_FORMAT__ALPHA_EN, mask_sh),\ TF_SF(DSCL0_LB_MEMORY_CTRL, MEMORY_CONFIG, mask_sh),\ TF_SF(DSCL0_LB_MEMORY_CTRL, LB_MAX_PARTITIONS, mask_sh),\ TF_SF(DSCL0_DSCL_AUTOCAL, AUTOCAL_MODE, mask_sh),\ @@ -235,7 +302,133 @@ TF_SF(DSCL0_SCL_VERT_FILTER_INIT_BOT_C, SCL_V_INIT_INT_BOT_C, mask_sh),\ TF_SF(DSCL0_SCL_MODE, SCL_CHROMA_COEF_MODE, mask_sh),\ TF_SF(DSCL0_SCL_MODE, SCL_COEF_RAM_SELECT_CURRENT, mask_sh), \ - TF_SF(DSCL0_OBUF_CONTROL, OBUF_BYPASS, mask_sh) + TF_SF(DSCL0_OBUF_CONTROL, OBUF_BYPASS, mask_sh), \ + TF_SF(CM0_CM_ICSC_CONTROL, CM_ICSC_MODE, mask_sh), \ + TF_SF(CM0_CM_ICSC_C11_C12, CM_ICSC_C11, mask_sh), \ + TF_SF(CM0_CM_ICSC_C11_C12, CM_ICSC_C12, mask_sh), \ + TF_SF(CM0_CM_ICSC_C13_C14, CM_ICSC_C13, mask_sh), \ + TF_SF(CM0_CM_ICSC_C13_C14, CM_ICSC_C14, mask_sh), \ + TF_SF(CM0_CM_ICSC_C21_C22, CM_ICSC_C21, mask_sh), \ + TF_SF(CM0_CM_ICSC_C21_C22, CM_ICSC_C22, mask_sh), \ + TF_SF(CM0_CM_ICSC_C23_C24, CM_ICSC_C23, mask_sh), \ + TF_SF(CM0_CM_ICSC_C23_C24, CM_ICSC_C24, mask_sh), \ + TF_SF(CM0_CM_ICSC_C31_C32, CM_ICSC_C31, mask_sh), \ + TF_SF(CM0_CM_ICSC_C31_C32, CM_ICSC_C32, mask_sh), \ + TF_SF(CM0_CM_ICSC_C33_C34, CM_ICSC_C33, mask_sh), \ + TF_SF(CM0_CM_ICSC_C33_C34, CM_ICSC_C34, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_START_CNTL_B, CM_DGAM_RAMB_EXP_REGION_START_B, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_START_CNTL_B, CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_B, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_START_CNTL_G, CM_DGAM_RAMB_EXP_REGION_START_G, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_START_CNTL_G, CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_G, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_START_CNTL_R, CM_DGAM_RAMB_EXP_REGION_START_R, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_START_CNTL_R, CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_R, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_SLOPE_CNTL_B, CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_SLOPE_CNTL_G, CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_G, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_SLOPE_CNTL_R, CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_R, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_END_CNTL1_B, CM_DGAM_RAMB_EXP_REGION_END_B, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_END_CNTL2_B, CM_DGAM_RAMB_EXP_REGION_END_SLOPE_B, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_END_CNTL2_B, CM_DGAM_RAMB_EXP_REGION_END_BASE_B, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_END_CNTL1_G, CM_DGAM_RAMB_EXP_REGION_END_G, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_END_CNTL2_G, CM_DGAM_RAMB_EXP_REGION_END_SLOPE_G, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_END_CNTL2_G, CM_DGAM_RAMB_EXP_REGION_END_BASE_G, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_END_CNTL1_R, CM_DGAM_RAMB_EXP_REGION_END_R, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_END_CNTL2_R, CM_DGAM_RAMB_EXP_REGION_END_SLOPE_R, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_END_CNTL2_R, CM_DGAM_RAMB_EXP_REGION_END_BASE_R, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_0_1, CM_DGAM_RAMB_EXP_REGION0_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_0_1, CM_DGAM_RAMB_EXP_REGION0_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_0_1, CM_DGAM_RAMB_EXP_REGION1_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_0_1, CM_DGAM_RAMB_EXP_REGION1_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_2_3, CM_DGAM_RAMB_EXP_REGION2_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_2_3, CM_DGAM_RAMB_EXP_REGION2_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_2_3, CM_DGAM_RAMB_EXP_REGION3_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_2_3, CM_DGAM_RAMB_EXP_REGION3_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_4_5, CM_DGAM_RAMB_EXP_REGION4_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_4_5, CM_DGAM_RAMB_EXP_REGION4_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_4_5, CM_DGAM_RAMB_EXP_REGION5_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_4_5, CM_DGAM_RAMB_EXP_REGION5_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_6_7, CM_DGAM_RAMB_EXP_REGION6_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_6_7, CM_DGAM_RAMB_EXP_REGION6_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_6_7, CM_DGAM_RAMB_EXP_REGION7_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_6_7, CM_DGAM_RAMB_EXP_REGION7_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_8_9, CM_DGAM_RAMB_EXP_REGION8_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_8_9, CM_DGAM_RAMB_EXP_REGION8_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_8_9, CM_DGAM_RAMB_EXP_REGION9_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_8_9, CM_DGAM_RAMB_EXP_REGION9_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_10_11, CM_DGAM_RAMB_EXP_REGION10_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_10_11, CM_DGAM_RAMB_EXP_REGION10_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_10_11, CM_DGAM_RAMB_EXP_REGION11_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_10_11, CM_DGAM_RAMB_EXP_REGION11_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_12_13, CM_DGAM_RAMB_EXP_REGION12_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_12_13, CM_DGAM_RAMB_EXP_REGION12_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_12_13, CM_DGAM_RAMB_EXP_REGION13_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_12_13, CM_DGAM_RAMB_EXP_REGION13_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_14_15, CM_DGAM_RAMB_EXP_REGION14_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_14_15, CM_DGAM_RAMB_EXP_REGION14_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_14_15, CM_DGAM_RAMB_EXP_REGION15_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_14_15, CM_DGAM_RAMB_EXP_REGION15_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_START_CNTL_B, CM_DGAM_RAMA_EXP_REGION_START_B, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_START_CNTL_B, CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_B, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_START_CNTL_G, CM_DGAM_RAMA_EXP_REGION_START_G, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_START_CNTL_G, CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_G, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_START_CNTL_R, CM_DGAM_RAMA_EXP_REGION_START_R, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_START_CNTL_R, CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_R, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_SLOPE_CNTL_B, CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_SLOPE_CNTL_G, CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_SLOPE_CNTL_R, CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_END_CNTL1_B, CM_DGAM_RAMA_EXP_REGION_END_B, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_END_CNTL2_B, CM_DGAM_RAMA_EXP_REGION_END_SLOPE_B, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_END_CNTL2_B, CM_DGAM_RAMA_EXP_REGION_END_BASE_B, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_END_CNTL1_G, CM_DGAM_RAMA_EXP_REGION_END_G, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_END_CNTL2_G, CM_DGAM_RAMA_EXP_REGION_END_SLOPE_G, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_END_CNTL2_G, CM_DGAM_RAMA_EXP_REGION_END_BASE_G, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_END_CNTL1_R, CM_DGAM_RAMA_EXP_REGION_END_R, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_END_CNTL2_R, CM_DGAM_RAMA_EXP_REGION_END_SLOPE_R, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_END_CNTL2_R, CM_DGAM_RAMA_EXP_REGION_END_BASE_R, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_0_1, CM_DGAM_RAMA_EXP_REGION0_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_0_1, CM_DGAM_RAMA_EXP_REGION0_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_0_1, CM_DGAM_RAMA_EXP_REGION1_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_0_1, CM_DGAM_RAMA_EXP_REGION1_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_2_3, CM_DGAM_RAMA_EXP_REGION2_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_2_3, CM_DGAM_RAMA_EXP_REGION2_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_2_3, CM_DGAM_RAMA_EXP_REGION3_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_2_3, CM_DGAM_RAMA_EXP_REGION3_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_4_5, CM_DGAM_RAMA_EXP_REGION4_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_4_5, CM_DGAM_RAMA_EXP_REGION4_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_4_5, CM_DGAM_RAMA_EXP_REGION5_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_4_5, CM_DGAM_RAMA_EXP_REGION5_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_6_7, CM_DGAM_RAMA_EXP_REGION6_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_6_7, CM_DGAM_RAMA_EXP_REGION6_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_6_7, CM_DGAM_RAMA_EXP_REGION7_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_6_7, CM_DGAM_RAMA_EXP_REGION7_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_8_9, CM_DGAM_RAMA_EXP_REGION8_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_8_9, CM_DGAM_RAMA_EXP_REGION8_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_8_9, CM_DGAM_RAMA_EXP_REGION9_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_8_9, CM_DGAM_RAMA_EXP_REGION9_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_10_11, CM_DGAM_RAMA_EXP_REGION10_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_10_11, CM_DGAM_RAMA_EXP_REGION10_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_10_11, CM_DGAM_RAMA_EXP_REGION11_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_10_11, CM_DGAM_RAMA_EXP_REGION11_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_12_13, CM_DGAM_RAMA_EXP_REGION12_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_12_13, CM_DGAM_RAMA_EXP_REGION12_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_12_13, CM_DGAM_RAMA_EXP_REGION13_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_12_13, CM_DGAM_RAMA_EXP_REGION13_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_14_15, CM_DGAM_RAMA_EXP_REGION14_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_14_15, CM_DGAM_RAMA_EXP_REGION14_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_14_15, CM_DGAM_RAMA_EXP_REGION15_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_14_15, CM_DGAM_RAMA_EXP_REGION15_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_MEM_PWR_CTRL, SHARED_MEM_PWR_DIS, mask_sh), \ + TF_SF(CM0_CM_DGAM_LUT_WRITE_EN_MASK, CM_DGAM_LUT_WRITE_EN_MASK, mask_sh), \ + TF_SF(CM0_CM_DGAM_LUT_WRITE_EN_MASK, CM_DGAM_LUT_WRITE_SEL, mask_sh), \ + TF_SF(CM0_CM_DGAM_LUT_INDEX, CM_DGAM_LUT_INDEX, mask_sh), \ + TF_SF(CM0_CM_DGAM_LUT_DATA, CM_DGAM_LUT_DATA, mask_sh), \ + TF_SF(CM0_CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, mask_sh), \ + TF_SF(CNVC_CFG0_FORMAT_CONTROL, CNVC_BYPASS, mask_sh), \ + TF2_SF(CNVC_CFG0, FORMAT_CONTROL__ALPHA_EN, mask_sh), \ + TF_SF(CNVC_CFG0_FORMAT_CONTROL, FORMAT_EXPANSION_MODE, mask_sh), \ + TF_SF(CNVC_CFG0_CNVC_SURFACE_PIXEL_FORMAT, CNVC_SURFACE_PIXEL_FORMAT, mask_sh), \ + TF_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_MODE, mask_sh), \ + TF_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_EXPANSION_MODE, mask_sh), \ + TF_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_ENABLE, mask_sh) #define TF_REG_LIST_SH_MASK_DCN10(mask_sh)\ TF_REG_LIST_SH_MASK_DCN(mask_sh),\ @@ -459,8 +652,25 @@ TF_SF(CM0_CM_RGAM_RAMA_REGION_32_33, CM_RGAM_RAMA_EXP_REGION33_LUT_OFFSET, mask_sh), \ TF_SF(CM0_CM_RGAM_RAMA_REGION_32_33, CM_RGAM_RAMA_EXP_REGION33_NUM_SEGMENTS, mask_sh), \ TF_SF(CM0_CM_RGAM_CONTROL, CM_RGAM_LUT_MODE, mask_sh), \ - TF_SF(DSCL0_OBUF_CONTROL, OBUF_H_2X_UPSCALE_EN, mask_sh) - + TF_SF(DSCL0_OBUF_CONTROL, OBUF_H_2X_UPSCALE_EN, mask_sh), \ + TF_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, mask_sh), \ + TF_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_LUT_FORMAT_R, mask_sh), \ + TF_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_LUT_FORMAT_G, mask_sh), \ + TF_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_LUT_FORMAT_B, mask_sh), \ + TF_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_INPUT_FORMAT, mask_sh), \ + TF_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_DGAM_CONFIG_STATUS, mask_sh), \ + TF_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_HOST_EN, mask_sh), \ + TF_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_RW_MODE, mask_sh), \ + TF_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_SEL, mask_sh), \ + TF_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_WRITE_EN_MASK, mask_sh), \ + TF_SF(CM0_CM_IGAM_LUT_RW_INDEX, CM_IGAM_LUT_RW_INDEX, mask_sh), \ + TF_SF(CM0_CM_CONTROL, CM_BYPASS_EN, mask_sh), \ + TF_SF(CM0_CM_IGAM_LUT_SEQ_COLOR, CM_IGAM_LUT_SEQ_COLOR, mask_sh), \ + TF_SF(CNVC_CFG0_FORMAT_CONTROL, OUTPUT_FP, mask_sh), \ + TF_SF(CURSOR0_CURSOR_CONTROL, CURSOR_MODE, mask_sh), \ + TF_SF(CURSOR0_CURSOR_CONTROL, CURSOR_PITCH, mask_sh), \ + TF_SF(CURSOR0_CURSOR_CONTROL, CURSOR_LINES_PER_CHUNK, mask_sh), \ + TF_SF(CURSOR0_CURSOR_CONTROL, CURSOR_ENABLE, mask_sh) #define TF_REG_FIELD_LIST(type) \ type EXT_OVERSCAN_LEFT; \ @@ -477,7 +687,7 @@ type DYNAMIC_PIXEL_DEPTH; \ type DITHER_EN; \ type INTERLEAVE_EN; \ - type ALPHA_EN; \ + type LB_DATA_FORMAT__ALPHA_EN; \ type MEMORY_CONFIG; \ type LB_MAX_PARTITIONS; \ type AUTOCAL_MODE; \ @@ -1123,7 +1333,154 @@ type CM_SHAPER_LUT_WRITE_EN_MASK; \ type CM_SHAPER_LUT_WRITE_SEL; \ type CM_SHAPER_LUT_INDEX; \ - type CM_SHAPER_LUT_DATA + type CM_SHAPER_LUT_DATA; \ + type CM_DGAM_CONFIG_STATUS; \ + type CM_ICSC_MODE; \ + type CM_ICSC_C11; \ + type CM_ICSC_C12; \ + type CM_ICSC_C13; \ + type CM_ICSC_C14; \ + type CM_ICSC_C21; \ + type CM_ICSC_C22; \ + type CM_ICSC_C23; \ + type CM_ICSC_C24; \ + type CM_ICSC_C31; \ + type CM_ICSC_C32; \ + type CM_ICSC_C33; \ + type CM_ICSC_C34; \ + type CM_DGAM_RAMB_EXP_REGION_START_B; \ + type CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_B; \ + type CM_DGAM_RAMB_EXP_REGION_START_G; \ + type CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_G; \ + type CM_DGAM_RAMB_EXP_REGION_START_R; \ + type CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_R; \ + type CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B; \ + type CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_G; \ + type CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_R; \ + type CM_DGAM_RAMB_EXP_REGION_END_B; \ + type CM_DGAM_RAMB_EXP_REGION_END_SLOPE_B; \ + type CM_DGAM_RAMB_EXP_REGION_END_BASE_B; \ + type CM_DGAM_RAMB_EXP_REGION_END_G; \ + type CM_DGAM_RAMB_EXP_REGION_END_SLOPE_G; \ + type CM_DGAM_RAMB_EXP_REGION_END_BASE_G; \ + type CM_DGAM_RAMB_EXP_REGION_END_R; \ + type CM_DGAM_RAMB_EXP_REGION_END_SLOPE_R; \ + type CM_DGAM_RAMB_EXP_REGION_END_BASE_R; \ + type CM_DGAM_RAMB_EXP_REGION0_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION0_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION1_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION1_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION2_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION2_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION3_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION3_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION4_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION4_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION5_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION5_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION6_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION6_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION7_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION7_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION8_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION8_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION9_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION9_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION10_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION10_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION11_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION11_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION12_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION12_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION13_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION13_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION14_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION14_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION15_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION15_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION_START_B; \ + type CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_B; \ + type CM_DGAM_RAMA_EXP_REGION_START_G; \ + type CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_G; \ + type CM_DGAM_RAMA_EXP_REGION_START_R; \ + type CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_R; \ + type CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B; \ + type CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G; \ + type CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R; \ + type CM_DGAM_RAMA_EXP_REGION_END_B; \ + type CM_DGAM_RAMA_EXP_REGION_END_SLOPE_B; \ + type CM_DGAM_RAMA_EXP_REGION_END_BASE_B; \ + type CM_DGAM_RAMA_EXP_REGION_END_G; \ + type CM_DGAM_RAMA_EXP_REGION_END_SLOPE_G; \ + type CM_DGAM_RAMA_EXP_REGION_END_BASE_G; \ + type CM_DGAM_RAMA_EXP_REGION_END_R; \ + type CM_DGAM_RAMA_EXP_REGION_END_SLOPE_R; \ + type CM_DGAM_RAMA_EXP_REGION_END_BASE_R; \ + type CM_DGAM_RAMA_EXP_REGION0_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION0_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION1_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION1_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION2_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION2_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION3_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION3_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION4_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION4_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION5_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION5_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION6_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION6_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION7_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION7_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION8_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION8_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION9_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION9_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION10_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION10_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION11_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION11_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION12_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION12_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION13_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION13_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION14_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION14_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION15_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION15_NUM_SEGMENTS; \ + type SHARED_MEM_PWR_DIS; \ + type CM_IGAM_LUT_FORMAT_R; \ + type CM_IGAM_LUT_FORMAT_G; \ + type CM_IGAM_LUT_FORMAT_B; \ + type CM_IGAM_LUT_HOST_EN; \ + type CM_IGAM_LUT_RW_MODE; \ + type CM_IGAM_LUT_WRITE_EN_MASK; \ + type CM_IGAM_LUT_SEL; \ + type CM_IGAM_LUT_SEQ_COLOR; \ + type CM_IGAM_DGAM_CONFIG_STATUS; \ + type CM_DGAM_LUT_WRITE_EN_MASK; \ + type CM_DGAM_LUT_WRITE_SEL; \ + type CM_DGAM_LUT_INDEX; \ + type CM_DGAM_LUT_DATA; \ + type CM_DGAM_LUT_MODE; \ + type CM_IGAM_LUT_MODE; \ + type CM_IGAM_INPUT_FORMAT; \ + type CM_IGAM_LUT_RW_INDEX; \ + type CM_BYPASS_EN; \ + type FORMAT_EXPANSION_MODE; \ + type CNVC_BYPASS; \ + type OUTPUT_FP; \ + type CNVC_SURFACE_PIXEL_FORMAT; \ + type CURSOR_MODE; \ + type CURSOR_PITCH; \ + type CURSOR_LINES_PER_CHUNK; \ + type CURSOR_ENABLE; \ + type CUR0_MODE; \ + type CUR0_EXPANSION_MODE; \ + type CUR0_ENABLE; \ + type CM_BYPASS; \ + type FORMAT_CONTROL__ALPHA_EN + struct dcn_dpp_shift { @@ -1366,8 +1723,66 @@ struct dcn_dpp_registers { uint32_t CM_SHAPER_RAMA_REGION_32_33; uint32_t CM_SHAPER_LUT_INDEX; uint32_t CM_SHAPER_LUT_DATA; - - + uint32_t CM_ICSC_CONTROL; + uint32_t CM_ICSC_C11_C12; + uint32_t CM_ICSC_C13_C14; + uint32_t CM_ICSC_C21_C22; + uint32_t CM_ICSC_C23_C24; + uint32_t CM_ICSC_C31_C32; + uint32_t CM_ICSC_C33_C34; + uint32_t CM_DGAM_RAMB_START_CNTL_B; + uint32_t CM_DGAM_RAMB_START_CNTL_G; + uint32_t CM_DGAM_RAMB_START_CNTL_R; + uint32_t CM_DGAM_RAMB_SLOPE_CNTL_B; + uint32_t CM_DGAM_RAMB_SLOPE_CNTL_G; + uint32_t CM_DGAM_RAMB_SLOPE_CNTL_R; + uint32_t CM_DGAM_RAMB_END_CNTL1_B; + uint32_t CM_DGAM_RAMB_END_CNTL2_B; + uint32_t CM_DGAM_RAMB_END_CNTL1_G; + uint32_t CM_DGAM_RAMB_END_CNTL2_G; + uint32_t CM_DGAM_RAMB_END_CNTL1_R; + uint32_t CM_DGAM_RAMB_END_CNTL2_R; + uint32_t CM_DGAM_RAMB_REGION_0_1; + uint32_t CM_DGAM_RAMB_REGION_2_3; + uint32_t CM_DGAM_RAMB_REGION_4_5; + uint32_t CM_DGAM_RAMB_REGION_6_7; + uint32_t CM_DGAM_RAMB_REGION_8_9; + uint32_t CM_DGAM_RAMB_REGION_10_11; + uint32_t CM_DGAM_RAMB_REGION_12_13; + uint32_t CM_DGAM_RAMB_REGION_14_15; + uint32_t CM_DGAM_RAMA_START_CNTL_B; + uint32_t CM_DGAM_RAMA_START_CNTL_G; + uint32_t CM_DGAM_RAMA_START_CNTL_R; + uint32_t CM_DGAM_RAMA_SLOPE_CNTL_B; + uint32_t CM_DGAM_RAMA_SLOPE_CNTL_G; + uint32_t CM_DGAM_RAMA_SLOPE_CNTL_R; + uint32_t CM_DGAM_RAMA_END_CNTL1_B; + uint32_t CM_DGAM_RAMA_END_CNTL2_B; + uint32_t CM_DGAM_RAMA_END_CNTL1_G; + uint32_t CM_DGAM_RAMA_END_CNTL2_G; + uint32_t CM_DGAM_RAMA_END_CNTL1_R; + uint32_t CM_DGAM_RAMA_END_CNTL2_R; + uint32_t CM_DGAM_RAMA_REGION_0_1; + uint32_t CM_DGAM_RAMA_REGION_2_3; + uint32_t CM_DGAM_RAMA_REGION_4_5; + uint32_t CM_DGAM_RAMA_REGION_6_7; + uint32_t CM_DGAM_RAMA_REGION_8_9; + uint32_t CM_DGAM_RAMA_REGION_10_11; + uint32_t CM_DGAM_RAMA_REGION_12_13; + uint32_t CM_DGAM_RAMA_REGION_14_15; + uint32_t CM_DGAM_LUT_WRITE_EN_MASK; + uint32_t CM_DGAM_LUT_INDEX; + uint32_t CM_DGAM_LUT_DATA; + uint32_t CM_CONTROL; + uint32_t CM_DGAM_CONTROL; + uint32_t CM_IGAM_CONTROL; + uint32_t CM_IGAM_LUT_RW_CONTROL; + uint32_t CM_IGAM_LUT_RW_INDEX; + uint32_t CM_IGAM_LUT_SEQ_COLOR; + uint32_t FORMAT_CONTROL; + uint32_t CNVC_SURFACE_PIXEL_FORMAT; + uint32_t CURSOR_CONTROL; + uint32_t CURSOR0_CONTROL; }; struct dcn10_dpp { @@ -1387,6 +1802,52 @@ struct dcn10_dpp { bool is_write_to_ram_a_safe; }; +enum dcn10_input_csc_select { + INPUT_CSC_SELECT_BYPASS = 0, + INPUT_CSC_SELECT_ICSC, + INPUT_CSC_SELECT_COMA +}; + +void ippn10_degamma_ram_select( + struct transform *xfm_base, + bool use_ram_a); + +void ippn10_program_degamma_luta_settings( + struct transform *xfm_base, + const struct pwl_params *params); + +void ippn10_program_degamma_lutb_settings( + struct transform *xfm_base, + const struct pwl_params *params); + +void ippn10_program_degamma_lut( + struct transform *xfm_base, + const struct pwl_result_data *rgb, + uint32_t num, + bool is_ram_a); + +void ippn10_power_on_degamma_lut( + struct transform *xfm_base, + bool power_on); + +void ippn10_program_input_csc( + struct transform *xfm_base, + enum dc_color_space color_space, + enum dcn10_input_csc_select select); + +void ippn10_program_input_lut( + struct transform *xfm_base, + const struct dc_gamma *gamma); + +void ippn10_full_bypass(struct transform *xfm_base); + +void ippn10_set_degamma( + struct transform *xfm_base, + enum ipp_degamma_mode mode); + +void ippn10_set_degamma_pwl(struct transform *xfm_base, + const struct pwl_params *params); + bool dpp_get_optimal_number_of_taps( struct transform *xfm, struct scaler_data *scl_data, @@ -1432,6 +1893,14 @@ void dcn10_dpp_dscl_set_scaler_manual_scale( struct transform *xfm_base, const struct scaler_data *scl_data); +void ippn10_cnv_setup ( + struct transform *xfm_base, + enum surface_pixel_format input_format, + enum expansion_mode mode, + enum ipp_output_format cnv_out_format); + +void ippn10_full_bypass(struct transform *xfm_base); + bool dcn10_dpp_construct(struct dcn10_dpp *xfm110, struct dc_context *ctx, uint32_t inst, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c index 9ff283bff007..409462f29f54 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c @@ -52,6 +52,11 @@ #define FN(reg_name, field_name) \ xfm->tf_shift->field_name, xfm->tf_mask->field_name +struct dcn10_input_csc_matrix { + enum dc_color_space color_space; + uint32_t regval[12]; +}; + enum dcn10_coef_filter_type_sel { SCL_COEF_LUMA_VERT_FILTER = 0, SCL_COEF_LUMA_HORZ_FILTER = 1, @@ -111,6 +116,26 @@ enum gamut_remap_select { GAMUT_REMAP_COMB_COEFF }; +static const struct dcn10_input_csc_matrix dcn10_input_csc_matrix[] = { + {COLOR_SPACE_SRGB, + {0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} }, + {COLOR_SPACE_SRGB_LIMITED, + {0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} }, + {COLOR_SPACE_YCBCR601, + {0x2cdd, 0x2000, 0, 0xe991, 0xe926, 0x2000, 0xf4fd, 0x10ef, + 0, 0x2000, 0x38b4, 0xe3a6} }, + {COLOR_SPACE_YCBCR601_LIMITED, + {0x3353, 0x2568, 0, 0xe400, 0xe5dc, 0x2568, 0xf367, 0x1108, + 0, 0x2568, 0x40de, 0xdd3a} }, + {COLOR_SPACE_YCBCR709, + {0x3265, 0x2000, 0, 0xe6ce, 0xf105, 0x2000, 0xfa01, 0xa7d, 0, + 0x2000, 0x3b61, 0xe24f} }, + + {COLOR_SPACE_YCBCR709_LIMITED, + {0x39a6, 0x2568, 0, 0xe0d6, 0xeedd, 0x2568, 0xf925, 0x9a8, 0, + 0x2568, 0x43ee, 0xdbb2} } +}; + static void program_gamut_remap( struct dcn10_dpp *xfm, const uint16_t *regval, @@ -774,3 +799,533 @@ void dcn10_dpp_cm_program_regamma_lutb_settings( CM_RGAM_RAMB_EXP_REGION33_NUM_SEGMENTS, curve[1].segments_num); } + +void ippn10_program_input_csc( + struct transform *xfm_base, + enum dc_color_space color_space, + enum dcn10_input_csc_select select) +{ + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + int i; + int arr_size = sizeof(dcn10_input_csc_matrix)/sizeof(struct dcn10_input_csc_matrix); + const uint32_t *regval = NULL; + uint32_t selection = 1; + + if (select == INPUT_CSC_SELECT_BYPASS) { + REG_SET(CM_ICSC_CONTROL, 0, CM_ICSC_MODE, 0); + return; + } + + for (i = 0; i < arr_size; i++) + if (dcn10_input_csc_matrix[i].color_space == color_space) { + regval = dcn10_input_csc_matrix[i].regval; + break; + } + + if (regval == NULL) { + BREAK_TO_DEBUGGER(); + return; + } + + if (select == INPUT_CSC_SELECT_COMA) + selection = 2; + REG_SET(CM_ICSC_CONTROL, 0, + CM_ICSC_MODE, selection); + + if (select == INPUT_CSC_SELECT_ICSC) { + /*R*/ + REG_SET_2(CM_ICSC_C11_C12, 0, + CM_ICSC_C11, regval[0], + CM_ICSC_C12, regval[1]); + regval += 2; + REG_SET_2(CM_ICSC_C13_C14, 0, + CM_ICSC_C13, regval[0], + CM_ICSC_C14, regval[1]); + /*G*/ + regval += 2; + REG_SET_2(CM_ICSC_C21_C22, 0, + CM_ICSC_C21, regval[0], + CM_ICSC_C22, regval[1]); + regval += 2; + REG_SET_2(CM_ICSC_C23_C24, 0, + CM_ICSC_C23, regval[0], + CM_ICSC_C24, regval[1]); + /*B*/ + regval += 2; + REG_SET_2(CM_ICSC_C31_C32, 0, + CM_ICSC_C31, regval[0], + CM_ICSC_C32, regval[1]); + regval += 2; + REG_SET_2(CM_ICSC_C33_C34, 0, + CM_ICSC_C33, regval[0], + CM_ICSC_C34, regval[1]); + } else { + /*R*/ + REG_SET_2(CM_COMA_C11_C12, 0, + CM_COMA_C11, regval[0], + CM_COMA_C12, regval[1]); + regval += 2; + REG_SET_2(CM_COMA_C13_C14, 0, + CM_COMA_C13, regval[0], + CM_COMA_C14, regval[1]); + /*G*/ + regval += 2; + REG_SET_2(CM_COMA_C21_C22, 0, + CM_COMA_C21, regval[0], + CM_COMA_C22, regval[1]); + regval += 2; + REG_SET_2(CM_COMA_C23_C24, 0, + CM_COMA_C23, regval[0], + CM_COMA_C24, regval[1]); + /*B*/ + regval += 2; + REG_SET_2(CM_COMA_C31_C32, 0, + CM_COMA_C31, regval[0], + CM_COMA_C32, regval[1]); + regval += 2; + REG_SET_2(CM_COMA_C33_C34, 0, + CM_COMA_C33, regval[0], + CM_COMA_C34, regval[1]); + } +} + +/*program de gamma RAM B*/ +void ippn10_program_degamma_lutb_settings( + struct transform *xfm_base, + const struct pwl_params *params) +{ + const struct gamma_curve *curve; + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + + REG_SET_2(CM_DGAM_RAMB_START_CNTL_B, 0, + CM_DGAM_RAMB_EXP_REGION_START_B, params->arr_points[0].custom_float_x, + CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_B, 0); + + REG_SET_2(CM_DGAM_RAMB_START_CNTL_G, 0, + CM_DGAM_RAMB_EXP_REGION_START_G, params->arr_points[0].custom_float_x, + CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_G, 0); + + REG_SET_2(CM_DGAM_RAMB_START_CNTL_R, 0, + CM_DGAM_RAMB_EXP_REGION_START_R, params->arr_points[0].custom_float_x, + CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_R, 0); + + REG_SET(CM_DGAM_RAMB_SLOPE_CNTL_B, 0, + CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B, params->arr_points[0].custom_float_slope); + + REG_SET(CM_DGAM_RAMB_SLOPE_CNTL_G, 0, + CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_G, params->arr_points[0].custom_float_slope); + + REG_SET(CM_DGAM_RAMB_SLOPE_CNTL_R, 0, + CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_R, params->arr_points[0].custom_float_slope); + + REG_SET(CM_DGAM_RAMB_END_CNTL1_B, 0, + CM_DGAM_RAMB_EXP_REGION_END_B, params->arr_points[1].custom_float_x); + + REG_SET_2(CM_DGAM_RAMB_END_CNTL2_B, 0, + CM_DGAM_RAMB_EXP_REGION_END_SLOPE_B, params->arr_points[1].custom_float_y, + CM_DGAM_RAMB_EXP_REGION_END_BASE_B, params->arr_points[2].custom_float_slope); + + REG_SET(CM_DGAM_RAMB_END_CNTL1_G, 0, + CM_DGAM_RAMB_EXP_REGION_END_G, params->arr_points[1].custom_float_x); + + REG_SET_2(CM_DGAM_RAMB_END_CNTL2_G, 0, + CM_DGAM_RAMB_EXP_REGION_END_SLOPE_G, params->arr_points[1].custom_float_y, + CM_DGAM_RAMB_EXP_REGION_END_BASE_G, params->arr_points[2].custom_float_slope); + + REG_SET(CM_DGAM_RAMB_END_CNTL1_R, 0, + CM_DGAM_RAMB_EXP_REGION_END_R, params->arr_points[1].custom_float_x); + + REG_SET_2(CM_DGAM_RAMB_END_CNTL2_R, 0, + CM_DGAM_RAMB_EXP_REGION_END_SLOPE_R, params->arr_points[1].custom_float_y, + CM_DGAM_RAMB_EXP_REGION_END_BASE_R, params->arr_points[2].custom_float_slope); + + curve = params->arr_curve_points; + REG_SET_4(CM_DGAM_RAMB_REGION_0_1, 0, + CM_DGAM_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMB_REGION_2_3, 0, + CM_DGAM_RAMB_EXP_REGION2_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMB_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMB_EXP_REGION3_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMB_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMB_REGION_4_5, 0, + CM_DGAM_RAMB_EXP_REGION4_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMB_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMB_EXP_REGION5_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMB_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMB_REGION_6_7, 0, + CM_DGAM_RAMB_EXP_REGION6_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMB_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMB_EXP_REGION7_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMB_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMB_REGION_8_9, 0, + CM_DGAM_RAMB_EXP_REGION8_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMB_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMB_EXP_REGION9_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMB_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMB_REGION_10_11, 0, + CM_DGAM_RAMB_EXP_REGION10_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMB_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMB_EXP_REGION11_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMB_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMB_REGION_12_13, 0, + CM_DGAM_RAMB_EXP_REGION12_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMB_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMB_EXP_REGION13_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMB_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMB_REGION_14_15, 0, + CM_DGAM_RAMB_EXP_REGION14_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMB_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMB_EXP_REGION15_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMB_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num); +} + +/*program de gamma RAM A*/ +void ippn10_program_degamma_luta_settings( + struct transform *xfm_base, + const struct pwl_params *params) +{ + const struct gamma_curve *curve; + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + + REG_SET_2(CM_DGAM_RAMA_START_CNTL_B, 0, + CM_DGAM_RAMA_EXP_REGION_START_B, params->arr_points[0].custom_float_x, + CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_B, 0); + + REG_SET_2(CM_DGAM_RAMA_START_CNTL_G, 0, + CM_DGAM_RAMA_EXP_REGION_START_G, params->arr_points[0].custom_float_x, + CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_G, 0); + + REG_SET_2(CM_DGAM_RAMA_START_CNTL_R, 0, + CM_DGAM_RAMA_EXP_REGION_START_R, params->arr_points[0].custom_float_x, + CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_R, 0); + + REG_SET(CM_DGAM_RAMA_SLOPE_CNTL_B, 0, + CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B, params->arr_points[0].custom_float_slope); + + REG_SET(CM_DGAM_RAMA_SLOPE_CNTL_G, 0, + CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G, params->arr_points[0].custom_float_slope); + + REG_SET(CM_DGAM_RAMA_SLOPE_CNTL_R, 0, + CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R, params->arr_points[0].custom_float_slope); + + REG_SET(CM_DGAM_RAMA_END_CNTL1_B, 0, + CM_DGAM_RAMA_EXP_REGION_END_B, params->arr_points[1].custom_float_x); + + REG_SET_2(CM_DGAM_RAMA_END_CNTL2_B, 0, + CM_DGAM_RAMA_EXP_REGION_END_SLOPE_B, params->arr_points[1].custom_float_y, + CM_DGAM_RAMA_EXP_REGION_END_BASE_B, params->arr_points[2].custom_float_slope); + + REG_SET(CM_DGAM_RAMA_END_CNTL1_G, 0, + CM_DGAM_RAMA_EXP_REGION_END_G, params->arr_points[1].custom_float_x); + + REG_SET_2(CM_DGAM_RAMA_END_CNTL2_G, 0, + CM_DGAM_RAMA_EXP_REGION_END_SLOPE_G, params->arr_points[1].custom_float_y, + CM_DGAM_RAMA_EXP_REGION_END_BASE_G, params->arr_points[2].custom_float_slope); + + REG_SET(CM_DGAM_RAMA_END_CNTL1_R, 0, + CM_DGAM_RAMA_EXP_REGION_END_R, params->arr_points[1].custom_float_x); + + REG_SET_2(CM_DGAM_RAMA_END_CNTL2_R, 0, + CM_DGAM_RAMA_EXP_REGION_END_SLOPE_R, params->arr_points[1].custom_float_y, + CM_DGAM_RAMA_EXP_REGION_END_BASE_R, params->arr_points[2].custom_float_slope); + + curve = params->arr_curve_points; + REG_SET_4(CM_DGAM_RAMA_REGION_0_1, 0, + CM_DGAM_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMA_REGION_2_3, 0, + CM_DGAM_RAMA_EXP_REGION2_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMA_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMA_EXP_REGION3_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMA_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMA_REGION_4_5, 0, + CM_DGAM_RAMA_EXP_REGION4_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMA_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMA_EXP_REGION5_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMA_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMA_REGION_6_7, 0, + CM_DGAM_RAMA_EXP_REGION6_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMA_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMA_EXP_REGION7_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMA_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMA_REGION_8_9, 0, + CM_DGAM_RAMA_EXP_REGION8_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMA_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMA_EXP_REGION9_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMA_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMA_REGION_10_11, 0, + CM_DGAM_RAMA_EXP_REGION10_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMA_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMA_EXP_REGION11_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMA_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMA_REGION_12_13, 0, + CM_DGAM_RAMA_EXP_REGION12_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMA_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMA_EXP_REGION13_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMA_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMA_REGION_14_15, 0, + CM_DGAM_RAMA_EXP_REGION14_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMA_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMA_EXP_REGION15_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMA_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num); +} + +void ippn10_power_on_degamma_lut( + struct transform *xfm_base, + bool power_on) +{ + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + + REG_SET(CM_MEM_PWR_CTRL, 0, + SHARED_MEM_PWR_DIS, power_on == true ? 0:1); + +} + +static void ippn10_enable_cm_block( + struct transform *xfm_base) +{ + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + + REG_UPDATE(CM_CONTROL, CM_BYPASS_EN, 0); +} + +void ippn10_set_degamma( + struct transform *xfm_base, + enum ipp_degamma_mode mode) +{ + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + ippn10_enable_cm_block(xfm_base); + + switch (mode) { + case IPP_DEGAMMA_MODE_BYPASS: + /* Setting de gamma bypass for now */ + REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 0); + break; + case IPP_DEGAMMA_MODE_HW_sRGB: + REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 1); + break; + case IPP_DEGAMMA_MODE_HW_xvYCC: + REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 2); + break; + default: + BREAK_TO_DEBUGGER(); + break; + } +} + +void ippn10_degamma_ram_select( + struct transform *xfm_base, + bool use_ram_a) +{ + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + + if (use_ram_a) + REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 3); + else + REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 4); + +} + +static bool ippn10_degamma_ram_inuse( + struct transform *xfm_base, + bool *ram_a_inuse) +{ + bool ret = false; + uint32_t status_reg = 0; + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + + REG_GET(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_DGAM_CONFIG_STATUS, + &status_reg); + + if (status_reg == 9) { + *ram_a_inuse = true; + ret = true; + } else if (status_reg == 10) { + *ram_a_inuse = false; + ret = true; + } + return ret; +} + +void ippn10_program_degamma_lut( + struct transform *xfm_base, + const struct pwl_result_data *rgb, + uint32_t num, + bool is_ram_a) +{ + uint32_t i; + + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_HOST_EN, 0); + REG_UPDATE(CM_DGAM_LUT_WRITE_EN_MASK, + CM_DGAM_LUT_WRITE_EN_MASK, 7); + REG_UPDATE(CM_DGAM_LUT_WRITE_EN_MASK, CM_DGAM_LUT_WRITE_SEL, + is_ram_a == true ? 0:1); + + REG_SET(CM_DGAM_LUT_INDEX, 0, CM_DGAM_LUT_INDEX, 0); + for (i = 0 ; i < num; i++) { + REG_SET(CM_DGAM_LUT_DATA, 0, CM_DGAM_LUT_DATA, rgb[i].red_reg); + REG_SET(CM_DGAM_LUT_DATA, 0, CM_DGAM_LUT_DATA, rgb[i].green_reg); + REG_SET(CM_DGAM_LUT_DATA, 0, CM_DGAM_LUT_DATA, rgb[i].blue_reg); + + REG_SET(CM_DGAM_LUT_DATA, 0, + CM_DGAM_LUT_DATA, rgb[i].delta_red_reg); + REG_SET(CM_DGAM_LUT_DATA, 0, + CM_DGAM_LUT_DATA, rgb[i].delta_green_reg); + REG_SET(CM_DGAM_LUT_DATA, 0, + CM_DGAM_LUT_DATA, rgb[i].delta_blue_reg); + } +} + +void ippn10_set_degamma_pwl(struct transform *xfm_base, + const struct pwl_params *params) +{ + bool is_ram_a = true; + + ippn10_power_on_degamma_lut(xfm_base, true); + ippn10_enable_cm_block(xfm_base); + ippn10_degamma_ram_inuse(xfm_base, &is_ram_a); + if (is_ram_a == true) + ippn10_program_degamma_lutb_settings(xfm_base, params); + else + ippn10_program_degamma_luta_settings(xfm_base, params); + + ippn10_program_degamma_lut(xfm_base, params->rgb_resulted, + params->hw_points_num, !is_ram_a); + ippn10_degamma_ram_select(xfm_base, !is_ram_a); +} + +void ippn10_full_bypass(struct transform *xfm_base) +{ + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + + /* Input pixel format: ARGB8888 */ + REG_SET(CNVC_SURFACE_PIXEL_FORMAT, 0, + CNVC_SURFACE_PIXEL_FORMAT, 0x8); + + /* Zero expansion */ + REG_SET_3(FORMAT_CONTROL, 0, + CNVC_BYPASS, 0, + FORMAT_CONTROL__ALPHA_EN, 0, + FORMAT_EXPANSION_MODE, 0); + + /* COLOR_KEYER_CONTROL.COLOR_KEYER_EN = 0 this should be default */ + REG_SET(CM_CONTROL, 0, CM_BYPASS_EN, 1); + + /* Setting degamma bypass for now */ + REG_SET(CM_DGAM_CONTROL, 0, CM_DGAM_LUT_MODE, 0); + REG_SET(CM_IGAM_CONTROL, 0, CM_IGAM_LUT_MODE, 0); +} + +static bool ippn10_ingamma_ram_inuse(struct transform *xfm_base, + bool *ram_a_inuse) +{ + bool in_use = false; + uint32_t status_reg = 0; + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + + REG_GET(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_DGAM_CONFIG_STATUS, + &status_reg); + + // 1 => IGAM_RAMA, 3 => IGAM_RAMA & DGAM_ROMA, 4 => IGAM_RAMA & DGAM_ROMB + if (status_reg == 1 || status_reg == 3 || status_reg == 4) { + *ram_a_inuse = true; + in_use = true; + // 2 => IGAM_RAMB, 5 => IGAM_RAMB & DGAM_ROMA, 6 => IGAM_RAMB & DGAM_ROMB + } else if (status_reg == 2 || status_reg == 5 || status_reg == 6) { + *ram_a_inuse = false; + in_use = true; + } + return in_use; +} + +/* + * Input gamma LUT currently supports 256 values only. This means input color + * can have a maximum of 8 bits per channel (= 256 possible values) in order to + * have a one-to-one mapping with the LUT. Truncation will occur with color + * values greater than 8 bits. + * + * In the future, this function should support additional input gamma methods, + * such as piecewise linear mapping, and input gamma bypass. + */ +void ippn10_program_input_lut( + struct transform *xfm_base, + const struct dc_gamma *gamma) +{ + int i; + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + bool rama_occupied = false; + uint32_t ram_num; + // Power on LUT memory. + REG_SET(CM_MEM_PWR_CTRL, 0, SHARED_MEM_PWR_DIS, 1); + ippn10_enable_cm_block(xfm_base); + // Determine whether to use RAM A or RAM B + ippn10_ingamma_ram_inuse(xfm_base, &rama_occupied); + if (!rama_occupied) + REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_SEL, 0); + else + REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_SEL, 1); + // RW mode is 256-entry LUT + REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_RW_MODE, 0); + // IGAM Input format should be 8 bits per channel. + REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_INPUT_FORMAT, 0); + // Do not mask any R,G,B values + REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_WRITE_EN_MASK, 7); + // LUT-256, unsigned, integer, new u0.12 format + REG_UPDATE_3( + CM_IGAM_CONTROL, + CM_IGAM_LUT_FORMAT_R, 3, + CM_IGAM_LUT_FORMAT_G, 3, + CM_IGAM_LUT_FORMAT_B, 3); + // Start at index 0 of IGAM LUT + REG_UPDATE(CM_IGAM_LUT_RW_INDEX, CM_IGAM_LUT_RW_INDEX, 0); + for (i = 0; i < gamma->num_entries; i++) { + REG_SET(CM_IGAM_LUT_SEQ_COLOR, 0, CM_IGAM_LUT_SEQ_COLOR, + dal_fixed31_32_round( + gamma->entries.red[i])); + REG_SET(CM_IGAM_LUT_SEQ_COLOR, 0, CM_IGAM_LUT_SEQ_COLOR, + dal_fixed31_32_round( + gamma->entries.green[i])); + REG_SET(CM_IGAM_LUT_SEQ_COLOR, 0, CM_IGAM_LUT_SEQ_COLOR, + dal_fixed31_32_round( + gamma->entries.blue[i])); + } + // Power off LUT memory + REG_SET(CM_MEM_PWR_CTRL, 0, SHARED_MEM_PWR_DIS, 0); + // Enable IGAM LUT on ram we just wrote to. 2 => RAMA, 3 => RAMB + REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, rama_occupied ? 3 : 2); + REG_GET(CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, &ram_num); +} 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 33830639e210..14c3b330b27b 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 @@ -225,7 +225,7 @@ static void dpp_set_lb( DYNAMIC_PIXEL_DEPTH, dyn_pix_depth, /* Dynamic expansion pixel depth */ DITHER_EN, 0, /* Dithering enable: Disabled */ INTERLEAVE_EN, lb_params->interleave_en, /* Interleave source enable */ - ALPHA_EN, lb_params->alpha_en); /* Alpha enable */ + LB_DATA_FORMAT__ALPHA_EN, lb_params->alpha_en); /* Alpha enable */ } REG_SET_2(LB_MEMORY_CTRL, 0, @@ -716,4 +716,3 @@ void dcn10_dpp_dscl_set_scaler_manual_scale( dpp_set_scl_filter(xfm, scl_data, ycbcr); } - diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 498680a9b996..4a24893486e8 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1294,34 +1294,34 @@ static void dcn10_update_plane_addr(const struct dc *dc, struct pipe_ctx *pipe_c static bool dcn10_set_input_transfer_func( struct pipe_ctx *pipe_ctx, const struct dc_plane_state *plane_state) { - struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp; + struct transform *xfm_base = pipe_ctx->plane_res.xfm; const struct dc_transfer_func *tf = NULL; bool result = true; - if (ipp == NULL) + if (xfm_base == NULL) return false; if (plane_state->in_transfer_func) tf = plane_state->in_transfer_func; if (plane_state->gamma_correction && dce_use_lut(plane_state)) - ipp->funcs->ipp_program_input_lut(ipp, + xfm_base->funcs->ipp_program_input_lut(xfm_base, plane_state->gamma_correction); if (tf == NULL) - ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS); + xfm_base->funcs->ipp_set_degamma(xfm_base, IPP_DEGAMMA_MODE_BYPASS); else if (tf->type == TF_TYPE_PREDEFINED) { switch (tf->tf) { case TRANSFER_FUNCTION_SRGB: - ipp->funcs->ipp_set_degamma(ipp, + xfm_base->funcs->ipp_set_degamma(xfm_base, IPP_DEGAMMA_MODE_HW_sRGB); break; case TRANSFER_FUNCTION_BT709: - ipp->funcs->ipp_set_degamma(ipp, + xfm_base->funcs->ipp_set_degamma(xfm_base, IPP_DEGAMMA_MODE_HW_xvYCC); break; case TRANSFER_FUNCTION_LINEAR: - ipp->funcs->ipp_set_degamma(ipp, + xfm_base->funcs->ipp_set_degamma(xfm_base, IPP_DEGAMMA_MODE_BYPASS); break; case TRANSFER_FUNCTION_PQ: @@ -1332,7 +1332,7 @@ static bool dcn10_set_input_transfer_func( break; } } else if (tf->type == TF_TYPE_BYPASS) { - ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS); + xfm_base->funcs->ipp_set_degamma(xfm_base, IPP_DEGAMMA_MODE_BYPASS); } else { /*TF_TYPE_DISTRIBUTED_POINTS*/ result = false; @@ -2204,7 +2204,7 @@ static void update_dchubp_dpp( { struct dce_hwseq *hws = dc->hwseq; struct mem_input *mi = pipe_ctx->plane_res.mi; - struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp; + struct transform *xfm = pipe_ctx->plane_res.xfm; struct dc_plane_state *plane_state = pipe_ctx->plane_state; union plane_size size = plane_state->plane_size; struct default_adjustment ocsc = {0}; @@ -2249,7 +2249,7 @@ static void update_dchubp_dpp( hws ); - ipp->funcs->ipp_setup(ipp, + xfm->funcs->ipp_setup(xfm, plane_state->format, 1, IPP_OUTPUT_FORMAT_12_BIT_FIX); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c index 8ee830522148..bc9827967535 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c @@ -69,403 +69,7 @@ enum dcn10_input_csc_select { INPUT_CSC_SELECT_COMA }; -static void ippn10_program_input_csc( - struct input_pixel_processor *ipp, - enum dc_color_space color_space, - enum dcn10_input_csc_select select) -{ - struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); - int i; - int arr_size = sizeof(dcn10_input_csc_matrix)/sizeof(struct dcn10_input_csc_matrix); - const uint32_t *regval = NULL; - uint32_t selection = 1; - - if (select == INPUT_CSC_SELECT_BYPASS) { - REG_SET(CM_ICSC_CONTROL, 0, CM_ICSC_MODE, 0); - return; - } - - for (i = 0; i < arr_size; i++) - if (dcn10_input_csc_matrix[i].color_space == color_space) { - regval = dcn10_input_csc_matrix[i].regval; - break; - } - - if (regval == NULL) { - BREAK_TO_DEBUGGER(); - return; - } - - if (select == INPUT_CSC_SELECT_COMA) - selection = 2; - REG_SET(CM_ICSC_CONTROL, 0, - CM_ICSC_MODE, selection); - - if (select == INPUT_CSC_SELECT_ICSC) { - /*R*/ - REG_SET_2(CM_ICSC_C11_C12, 0, - CM_ICSC_C11, regval[0], - CM_ICSC_C12, regval[1]); - regval += 2; - REG_SET_2(CM_ICSC_C13_C14, 0, - CM_ICSC_C13, regval[0], - CM_ICSC_C14, regval[1]); - /*G*/ - regval += 2; - REG_SET_2(CM_ICSC_C21_C22, 0, - CM_ICSC_C21, regval[0], - CM_ICSC_C22, regval[1]); - regval += 2; - REG_SET_2(CM_ICSC_C23_C24, 0, - CM_ICSC_C23, regval[0], - CM_ICSC_C24, regval[1]); - /*B*/ - regval += 2; - REG_SET_2(CM_ICSC_C31_C32, 0, - CM_ICSC_C31, regval[0], - CM_ICSC_C32, regval[1]); - regval += 2; - REG_SET_2(CM_ICSC_C33_C34, 0, - CM_ICSC_C33, regval[0], - CM_ICSC_C34, regval[1]); - } else { - /*R*/ - REG_SET_2(CM_COMA_C11_C12, 0, - CM_COMA_C11, regval[0], - CM_COMA_C12, regval[1]); - regval += 2; - REG_SET_2(CM_COMA_C13_C14, 0, - CM_COMA_C13, regval[0], - CM_COMA_C14, regval[1]); - /*G*/ - regval += 2; - REG_SET_2(CM_COMA_C21_C22, 0, - CM_COMA_C21, regval[0], - CM_COMA_C22, regval[1]); - regval += 2; - REG_SET_2(CM_COMA_C23_C24, 0, - CM_COMA_C23, regval[0], - CM_COMA_C24, regval[1]); - /*B*/ - regval += 2; - REG_SET_2(CM_COMA_C31_C32, 0, - CM_COMA_C31, regval[0], - CM_COMA_C32, regval[1]); - regval += 2; - REG_SET_2(CM_COMA_C33_C34, 0, - CM_COMA_C33, regval[0], - CM_COMA_C34, regval[1]); - } -} - -/*program de gamma RAM B*/ -static void ippn10_program_degamma_lutb_settings( - struct input_pixel_processor *ipp, - const struct pwl_params *params) -{ - const struct gamma_curve *curve; - struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); - - REG_SET_2(CM_DGAM_RAMB_START_CNTL_B, 0, - CM_DGAM_RAMB_EXP_REGION_START_B, params->arr_points[0].custom_float_x, - CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_B, 0); - - REG_SET_2(CM_DGAM_RAMB_START_CNTL_G, 0, - CM_DGAM_RAMB_EXP_REGION_START_G, params->arr_points[0].custom_float_x, - CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_G, 0); - - REG_SET_2(CM_DGAM_RAMB_START_CNTL_R, 0, - CM_DGAM_RAMB_EXP_REGION_START_R, params->arr_points[0].custom_float_x, - CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_R, 0); - - REG_SET(CM_DGAM_RAMB_SLOPE_CNTL_B, 0, - CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B, params->arr_points[0].custom_float_slope); - - REG_SET(CM_DGAM_RAMB_SLOPE_CNTL_G, 0, - CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_G, params->arr_points[0].custom_float_slope); - - REG_SET(CM_DGAM_RAMB_SLOPE_CNTL_R, 0, - CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_R, params->arr_points[0].custom_float_slope); - - REG_SET(CM_DGAM_RAMB_END_CNTL1_B, 0, - CM_DGAM_RAMB_EXP_REGION_END_B, params->arr_points[1].custom_float_x); - - REG_SET_2(CM_DGAM_RAMB_END_CNTL2_B, 0, - CM_DGAM_RAMB_EXP_REGION_END_SLOPE_B, params->arr_points[1].custom_float_y, - CM_DGAM_RAMB_EXP_REGION_END_BASE_B, params->arr_points[2].custom_float_slope); - - REG_SET(CM_DGAM_RAMB_END_CNTL1_G, 0, - CM_DGAM_RAMB_EXP_REGION_END_G, params->arr_points[1].custom_float_x); - - REG_SET_2(CM_DGAM_RAMB_END_CNTL2_G, 0, - CM_DGAM_RAMB_EXP_REGION_END_SLOPE_G, params->arr_points[1].custom_float_y, - CM_DGAM_RAMB_EXP_REGION_END_BASE_G, params->arr_points[2].custom_float_slope); - - REG_SET(CM_DGAM_RAMB_END_CNTL1_R, 0, - CM_DGAM_RAMB_EXP_REGION_END_R, params->arr_points[1].custom_float_x); - - REG_SET_2(CM_DGAM_RAMB_END_CNTL2_R, 0, - CM_DGAM_RAMB_EXP_REGION_END_SLOPE_R, params->arr_points[1].custom_float_y, - CM_DGAM_RAMB_EXP_REGION_END_BASE_R, params->arr_points[2].custom_float_slope); - - curve = params->arr_curve_points; - REG_SET_4(CM_DGAM_RAMB_REGION_0_1, 0, - CM_DGAM_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMB_REGION_2_3, 0, - CM_DGAM_RAMB_EXP_REGION2_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMB_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMB_EXP_REGION3_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMB_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMB_REGION_4_5, 0, - CM_DGAM_RAMB_EXP_REGION4_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMB_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMB_EXP_REGION5_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMB_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMB_REGION_6_7, 0, - CM_DGAM_RAMB_EXP_REGION6_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMB_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMB_EXP_REGION7_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMB_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMB_REGION_8_9, 0, - CM_DGAM_RAMB_EXP_REGION8_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMB_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMB_EXP_REGION9_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMB_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMB_REGION_10_11, 0, - CM_DGAM_RAMB_EXP_REGION10_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMB_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMB_EXP_REGION11_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMB_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMB_REGION_12_13, 0, - CM_DGAM_RAMB_EXP_REGION12_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMB_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMB_EXP_REGION13_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMB_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMB_REGION_14_15, 0, - CM_DGAM_RAMB_EXP_REGION14_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMB_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMB_EXP_REGION15_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMB_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num); -} - -/*program de gamma RAM A*/ -static void ippn10_program_degamma_luta_settings( - struct input_pixel_processor *ipp, - const struct pwl_params *params) -{ - const struct gamma_curve *curve; - struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); - - REG_SET_2(CM_DGAM_RAMA_START_CNTL_B, 0, - CM_DGAM_RAMA_EXP_REGION_START_B, params->arr_points[0].custom_float_x, - CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_B, 0); - - REG_SET_2(CM_DGAM_RAMA_START_CNTL_G, 0, - CM_DGAM_RAMA_EXP_REGION_START_G, params->arr_points[0].custom_float_x, - CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_G, 0); - - REG_SET_2(CM_DGAM_RAMA_START_CNTL_R, 0, - CM_DGAM_RAMA_EXP_REGION_START_R, params->arr_points[0].custom_float_x, - CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_R, 0); - - REG_SET(CM_DGAM_RAMA_SLOPE_CNTL_B, 0, - CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B, params->arr_points[0].custom_float_slope); - - REG_SET(CM_DGAM_RAMA_SLOPE_CNTL_G, 0, - CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G, params->arr_points[0].custom_float_slope); - - REG_SET(CM_DGAM_RAMA_SLOPE_CNTL_R, 0, - CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R, params->arr_points[0].custom_float_slope); - - REG_SET(CM_DGAM_RAMA_END_CNTL1_B, 0, - CM_DGAM_RAMA_EXP_REGION_END_B, params->arr_points[1].custom_float_x); - - REG_SET_2(CM_DGAM_RAMA_END_CNTL2_B, 0, - CM_DGAM_RAMA_EXP_REGION_END_SLOPE_B, params->arr_points[1].custom_float_y, - CM_DGAM_RAMA_EXP_REGION_END_BASE_B, params->arr_points[2].custom_float_slope); - - REG_SET(CM_DGAM_RAMA_END_CNTL1_G, 0, - CM_DGAM_RAMA_EXP_REGION_END_G, params->arr_points[1].custom_float_x); - - REG_SET_2(CM_DGAM_RAMA_END_CNTL2_G, 0, - CM_DGAM_RAMA_EXP_REGION_END_SLOPE_G, params->arr_points[1].custom_float_y, - CM_DGAM_RAMA_EXP_REGION_END_BASE_G, params->arr_points[2].custom_float_slope); - - REG_SET(CM_DGAM_RAMA_END_CNTL1_R, 0, - CM_DGAM_RAMA_EXP_REGION_END_R, params->arr_points[1].custom_float_x); - - REG_SET_2(CM_DGAM_RAMA_END_CNTL2_R, 0, - CM_DGAM_RAMA_EXP_REGION_END_SLOPE_R, params->arr_points[1].custom_float_y, - CM_DGAM_RAMA_EXP_REGION_END_BASE_R, params->arr_points[2].custom_float_slope); - - curve = params->arr_curve_points; - REG_SET_4(CM_DGAM_RAMA_REGION_0_1, 0, - CM_DGAM_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMA_REGION_2_3, 0, - CM_DGAM_RAMA_EXP_REGION2_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMA_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMA_EXP_REGION3_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMA_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMA_REGION_4_5, 0, - CM_DGAM_RAMA_EXP_REGION4_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMA_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMA_EXP_REGION5_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMA_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMA_REGION_6_7, 0, - CM_DGAM_RAMA_EXP_REGION6_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMA_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMA_EXP_REGION7_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMA_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMA_REGION_8_9, 0, - CM_DGAM_RAMA_EXP_REGION8_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMA_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMA_EXP_REGION9_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMA_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMA_REGION_10_11, 0, - CM_DGAM_RAMA_EXP_REGION10_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMA_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMA_EXP_REGION11_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMA_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMA_REGION_12_13, 0, - CM_DGAM_RAMA_EXP_REGION12_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMA_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMA_EXP_REGION13_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMA_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMA_REGION_14_15, 0, - CM_DGAM_RAMA_EXP_REGION14_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMA_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMA_EXP_REGION15_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMA_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num); -} - -static void ippn10_power_on_degamma_lut( - struct input_pixel_processor *ipp, - bool power_on) -{ - struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); - - REG_SET(CM_MEM_PWR_CTRL, 0, - SHARED_MEM_PWR_DIS, power_on == true ? 0:1); -} - -static void ippn10_program_degamma_lut( - struct input_pixel_processor *ipp, - const struct pwl_result_data *rgb, - uint32_t num, - bool is_ram_a) -{ - uint32_t i; - - struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); - REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_HOST_EN, 0); - REG_UPDATE(CM_DGAM_LUT_WRITE_EN_MASK, - CM_DGAM_LUT_WRITE_EN_MASK, 7); - REG_UPDATE(CM_DGAM_LUT_WRITE_EN_MASK, CM_DGAM_LUT_WRITE_SEL, - is_ram_a == true ? 0:1); - - REG_SET(CM_DGAM_LUT_INDEX, 0, CM_DGAM_LUT_INDEX, 0); - for (i = 0 ; i < num; i++) { - REG_SET(CM_DGAM_LUT_DATA, 0, CM_DGAM_LUT_DATA, rgb[i].red_reg); - REG_SET(CM_DGAM_LUT_DATA, 0, CM_DGAM_LUT_DATA, rgb[i].green_reg); - REG_SET(CM_DGAM_LUT_DATA, 0, CM_DGAM_LUT_DATA, rgb[i].blue_reg); - - REG_SET(CM_DGAM_LUT_DATA, 0, - CM_DGAM_LUT_DATA, rgb[i].delta_red_reg); - REG_SET(CM_DGAM_LUT_DATA, 0, - CM_DGAM_LUT_DATA, rgb[i].delta_green_reg); - REG_SET(CM_DGAM_LUT_DATA, 0, - CM_DGAM_LUT_DATA, rgb[i].delta_blue_reg); - } -} - -static void ippn10_enable_cm_block( - struct input_pixel_processor *ipp) -{ - struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); - - REG_UPDATE(CM_CONTROL, CM_BYPASS_EN, 0); -} - -static void ippn10_full_bypass(struct input_pixel_processor *ipp) -{ - struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); - - /* Input pixel format: ARGB8888 */ - REG_SET(CNVC_SURFACE_PIXEL_FORMAT, 0, - CNVC_SURFACE_PIXEL_FORMAT, 0x8); - - /* Zero expansion */ - REG_SET_3(FORMAT_CONTROL, 0, - CNVC_BYPASS, 0, - ALPHA_EN, 0, - FORMAT_EXPANSION_MODE, 0); - - /* COLOR_KEYER_CONTROL.COLOR_KEYER_EN = 0 this should be default */ - REG_SET(CM_CONTROL, 0, CM_BYPASS_EN, 1); - - /* Setting degamma bypass for now */ - REG_SET(CM_DGAM_CONTROL, 0, CM_DGAM_LUT_MODE, 0); - REG_SET(CM_IGAM_CONTROL, 0, CM_IGAM_LUT_MODE, 0); -} - -static void ippn10_set_degamma( - struct input_pixel_processor *ipp, - enum ipp_degamma_mode mode) -{ - struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); - ippn10_enable_cm_block(ipp); - - switch (mode) { - case IPP_DEGAMMA_MODE_BYPASS: - /* Setting de gamma bypass for now */ - REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 0); - break; - case IPP_DEGAMMA_MODE_HW_sRGB: - REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 1); - break; - case IPP_DEGAMMA_MODE_HW_xvYCC: - REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 2); - break; - default: - BREAK_TO_DEBUGGER(); - break; - } -} static bool ippn10_cursor_program_control( struct dcn10_ipp *ippn10, @@ -658,276 +262,6 @@ enum pixel_format_description { }; -static void ippn10_setup_format_flags(enum surface_pixel_format input_format,\ - enum pixel_format_description *fmt) -{ - - if (input_format == SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F || - input_format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F) - *fmt = PIXEL_FORMAT_FLOAT; - else if (input_format == SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616) - *fmt = PIXEL_FORMAT_FIXED16; - else - *fmt = PIXEL_FORMAT_FIXED; -} - -static void ippn10_set_degamma_format_float(struct input_pixel_processor *ipp, - bool is_float) -{ - struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); - - if (is_float) { - REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_INPUT_FORMAT, 3); - REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, 1); - } else { - REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_INPUT_FORMAT, 2); - REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, 0); - } -} - - -static void ippn10_cnv_setup ( - struct input_pixel_processor *ipp, - enum surface_pixel_format input_format, - enum expansion_mode mode, - enum ipp_output_format cnv_out_format) -{ - uint32_t pixel_format; - uint32_t alpha_en; - enum pixel_format_description fmt ; - enum dc_color_space color_space; - enum dcn10_input_csc_select select; - bool is_float; - struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); - bool force_disable_cursor = false; - - ippn10_setup_format_flags(input_format, &fmt); - alpha_en = 1; - pixel_format = 0; - color_space = COLOR_SPACE_SRGB; - select = INPUT_CSC_SELECT_BYPASS; - is_float = false; - - switch (fmt) { - case PIXEL_FORMAT_FIXED: - case PIXEL_FORMAT_FIXED16: - /*when output is float then FORMAT_CONTROL__OUTPUT_FP=1*/ - REG_SET_3(FORMAT_CONTROL, 0, - CNVC_BYPASS, 0, - FORMAT_EXPANSION_MODE, mode, - OUTPUT_FP, 0); - break; - case PIXEL_FORMAT_FLOAT: - REG_SET_3(FORMAT_CONTROL, 0, - CNVC_BYPASS, 0, - FORMAT_EXPANSION_MODE, mode, - OUTPUT_FP, 1); - is_float = true; - break; - default: - - break; - } - - ippn10_set_degamma_format_float(ipp, is_float); - - switch (input_format) { - case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: - pixel_format = 1; - break; - case SURFACE_PIXEL_FORMAT_GRPH_RGB565: - pixel_format = 3; - alpha_en = 0; - break; - case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: - case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: - pixel_format = 8; - break; - case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: - case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: - pixel_format = 10; - break; - case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: - force_disable_cursor = false; - pixel_format = 65; - color_space = COLOR_SPACE_YCBCR709; - select = INPUT_CSC_SELECT_ICSC; - break; - case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: - force_disable_cursor = true; - pixel_format = 64; - color_space = COLOR_SPACE_YCBCR709; - select = INPUT_CSC_SELECT_ICSC; - break; - case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: - force_disable_cursor = true; - pixel_format = 67; - color_space = COLOR_SPACE_YCBCR709; - select = INPUT_CSC_SELECT_ICSC; - break; - case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: - force_disable_cursor = true; - pixel_format = 66; - color_space = COLOR_SPACE_YCBCR709; - select = INPUT_CSC_SELECT_ICSC; - break; - case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: - pixel_format = 22; - break; - case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: - pixel_format = 24; - break; - case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: - pixel_format = 25; - break; - default: - break; - } - REG_SET(CNVC_SURFACE_PIXEL_FORMAT, 0, - CNVC_SURFACE_PIXEL_FORMAT, pixel_format); - REG_UPDATE(FORMAT_CONTROL, ALPHA_EN, alpha_en); - - ippn10_program_input_csc(ipp, color_space, select); - - if (force_disable_cursor) { - REG_UPDATE(CURSOR_CONTROL, - CURSOR_ENABLE, 0); - REG_UPDATE(CURSOR0_CONTROL, - CUR0_ENABLE, 0); - } -} - - -static bool ippn10_degamma_ram_inuse(struct input_pixel_processor *ipp, - bool *ram_a_inuse) -{ - bool ret = false; - uint32_t status_reg = 0; - struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); - - REG_GET(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_DGAM_CONFIG_STATUS, - &status_reg); - - if (status_reg == 9) { - *ram_a_inuse = true; - ret = true; - } else if (status_reg == 10) { - *ram_a_inuse = false; - ret = true; - } - return ret; -} - -static bool ippn10_ingamma_ram_inuse(struct input_pixel_processor *ipp, - bool *ram_a_inuse) -{ - bool in_use = false; - uint32_t status_reg = 0; - struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); - - REG_GET(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_DGAM_CONFIG_STATUS, - &status_reg); - - // 1 => IGAM_RAMA, 3 => IGAM_RAMA & DGAM_ROMA, 4 => IGAM_RAMA & DGAM_ROMB - if (status_reg == 1 || status_reg == 3 || status_reg == 4) { - *ram_a_inuse = true; - in_use = true; - // 2 => IGAM_RAMB, 5 => IGAM_RAMB & DGAM_ROMA, 6 => IGAM_RAMB & DGAM_ROMB - } else if (status_reg == 2 || status_reg == 5 || status_reg == 6) { - *ram_a_inuse = false; - in_use = true; - } - return in_use; -} - -static void ippn10_degamma_ram_select(struct input_pixel_processor *ipp, - bool use_ram_a) -{ - struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); - - if (use_ram_a) - REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 3); - else - REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 4); - -} - -static void ippn10_set_degamma_pwl(struct input_pixel_processor *ipp, - const struct pwl_params *params) -{ - bool is_ram_a = true; - - ippn10_power_on_degamma_lut(ipp, true); - ippn10_enable_cm_block(ipp); - ippn10_degamma_ram_inuse(ipp, &is_ram_a); - if (is_ram_a == true) - ippn10_program_degamma_lutb_settings(ipp, params); - else - ippn10_program_degamma_luta_settings(ipp, params); - - ippn10_program_degamma_lut(ipp, params->rgb_resulted, - params->hw_points_num, !is_ram_a); - ippn10_degamma_ram_select(ipp, !is_ram_a); -} - -/* - * Input gamma LUT currently supports 256 values only. This means input color - * can have a maximum of 8 bits per channel (= 256 possible values) in order to - * have a one-to-one mapping with the LUT. Truncation will occur with color - * values greater than 8 bits. - * - * In the future, this function should support additional input gamma methods, - * such as piecewise linear mapping, and input gamma bypass. - */ -static void ippn10_program_input_lut( - struct input_pixel_processor *ipp, - const struct dc_gamma *gamma) -{ - int i; - struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); - bool rama_occupied = false; - uint32_t ram_num; - // Power on LUT memory. - REG_SET(CM_MEM_PWR_CTRL, 0, SHARED_MEM_PWR_DIS, 1); - ippn10_enable_cm_block(ipp); - // Determine whether to use RAM A or RAM B - ippn10_ingamma_ram_inuse(ipp, &rama_occupied); - if (!rama_occupied) - REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_SEL, 0); - else - REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_SEL, 1); - // RW mode is 256-entry LUT - REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_RW_MODE, 0); - // IGAM Input format should be 8 bits per channel. - REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_INPUT_FORMAT, 0); - // Do not mask any R,G,B values - REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_WRITE_EN_MASK, 7); - // LUT-256, unsigned, integer, new u0.12 format - REG_UPDATE_3( - CM_IGAM_CONTROL, - CM_IGAM_LUT_FORMAT_R, 3, - CM_IGAM_LUT_FORMAT_G, 3, - CM_IGAM_LUT_FORMAT_B, 3); - // Start at index 0 of IGAM LUT - REG_UPDATE(CM_IGAM_LUT_RW_INDEX, CM_IGAM_LUT_RW_INDEX, 0); - for (i = 0; i < gamma->num_entries; i++) { - REG_SET(CM_IGAM_LUT_SEQ_COLOR, 0, CM_IGAM_LUT_SEQ_COLOR, - dal_fixed31_32_round( - gamma->entries.red[i])); - REG_SET(CM_IGAM_LUT_SEQ_COLOR, 0, CM_IGAM_LUT_SEQ_COLOR, - dal_fixed31_32_round( - gamma->entries.green[i])); - REG_SET(CM_IGAM_LUT_SEQ_COLOR, 0, CM_IGAM_LUT_SEQ_COLOR, - dal_fixed31_32_round( - gamma->entries.blue[i])); - } - // Power off LUT memory - REG_SET(CM_MEM_PWR_CTRL, 0, SHARED_MEM_PWR_DIS, 0); - // Enable IGAM LUT on ram we just wrote to. 2 => RAMA, 3 => RAMB - REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, rama_occupied ? 3 : 2); - REG_GET(CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, &ram_num); -} - /*****************************************/ /* Constructor, Destructor */ /*****************************************/ @@ -941,11 +275,11 @@ static void dcn10_ipp_destroy(struct input_pixel_processor **ipp) static const struct ipp_funcs dcn10_ipp_funcs = { .ipp_cursor_set_attributes = ippn10_cursor_set_attributes, .ipp_cursor_set_position = ippn10_cursor_set_position, - .ipp_set_degamma = ippn10_set_degamma, - .ipp_program_input_lut = ippn10_program_input_lut, - .ipp_full_bypass = ippn10_full_bypass, - .ipp_setup = ippn10_cnv_setup, - .ipp_program_degamma_pwl = ippn10_set_degamma_pwl, + .ipp_set_degamma = NULL, + .ipp_program_input_lut = NULL, + .ipp_full_bypass = NULL, + .ipp_setup = NULL, + .ipp_program_degamma_pwl = NULL, .ipp_destroy = dcn10_ipp_destroy }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h index 69db441e78c4..e4f292822975 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h @@ -32,59 +32,6 @@ container_of(ipp, struct dcn10_ipp, base) #define IPP_REG_LIST_DCN(id) \ - SRI(CM_ICSC_CONTROL, CM, id), \ - SRI(CM_ICSC_C11_C12, CM, id), \ - SRI(CM_ICSC_C13_C14, CM, id), \ - SRI(CM_ICSC_C21_C22, CM, id), \ - SRI(CM_ICSC_C23_C24, CM, id), \ - SRI(CM_ICSC_C31_C32, CM, id), \ - SRI(CM_ICSC_C33_C34, CM, id), \ - SRI(CM_DGAM_RAMB_START_CNTL_B, CM, id), \ - SRI(CM_DGAM_RAMB_START_CNTL_G, CM, id), \ - SRI(CM_DGAM_RAMB_START_CNTL_R, CM, id), \ - SRI(CM_DGAM_RAMB_SLOPE_CNTL_B, CM, id), \ - SRI(CM_DGAM_RAMB_SLOPE_CNTL_G, CM, id), \ - SRI(CM_DGAM_RAMB_SLOPE_CNTL_R, CM, id), \ - SRI(CM_DGAM_RAMB_END_CNTL1_B, CM, id), \ - SRI(CM_DGAM_RAMB_END_CNTL2_B, CM, id), \ - SRI(CM_DGAM_RAMB_END_CNTL1_G, CM, id), \ - SRI(CM_DGAM_RAMB_END_CNTL2_G, CM, id), \ - SRI(CM_DGAM_RAMB_END_CNTL1_R, CM, id), \ - SRI(CM_DGAM_RAMB_END_CNTL2_R, CM, id), \ - SRI(CM_DGAM_RAMB_REGION_0_1, CM, id), \ - SRI(CM_DGAM_RAMB_REGION_2_3, CM, id), \ - SRI(CM_DGAM_RAMB_REGION_4_5, CM, id), \ - SRI(CM_DGAM_RAMB_REGION_6_7, CM, id), \ - SRI(CM_DGAM_RAMB_REGION_8_9, CM, id), \ - SRI(CM_DGAM_RAMB_REGION_10_11, CM, id), \ - SRI(CM_DGAM_RAMB_REGION_12_13, CM, id), \ - SRI(CM_DGAM_RAMB_REGION_14_15, CM, id), \ - SRI(CM_DGAM_RAMA_START_CNTL_B, CM, id), \ - SRI(CM_DGAM_RAMA_START_CNTL_G, CM, id), \ - SRI(CM_DGAM_RAMA_START_CNTL_R, CM, id), \ - SRI(CM_DGAM_RAMA_SLOPE_CNTL_B, CM, id), \ - SRI(CM_DGAM_RAMA_SLOPE_CNTL_G, CM, id), \ - SRI(CM_DGAM_RAMA_SLOPE_CNTL_R, CM, id), \ - SRI(CM_DGAM_RAMA_END_CNTL1_B, CM, id), \ - SRI(CM_DGAM_RAMA_END_CNTL2_B, CM, id), \ - SRI(CM_DGAM_RAMA_END_CNTL1_G, CM, id), \ - SRI(CM_DGAM_RAMA_END_CNTL2_G, CM, id), \ - SRI(CM_DGAM_RAMA_END_CNTL1_R, CM, id), \ - SRI(CM_DGAM_RAMA_END_CNTL2_R, CM, id), \ - SRI(CM_DGAM_RAMA_REGION_0_1, CM, id), \ - SRI(CM_DGAM_RAMA_REGION_2_3, CM, id), \ - SRI(CM_DGAM_RAMA_REGION_4_5, CM, id), \ - SRI(CM_DGAM_RAMA_REGION_6_7, CM, id), \ - SRI(CM_DGAM_RAMA_REGION_8_9, CM, id), \ - SRI(CM_DGAM_RAMA_REGION_10_11, CM, id), \ - SRI(CM_DGAM_RAMA_REGION_12_13, CM, id), \ - SRI(CM_DGAM_RAMA_REGION_14_15, CM, id), \ - SRI(CM_MEM_PWR_CTRL, CM, id), \ - SRI(CM_DGAM_LUT_WRITE_EN_MASK, CM, id), \ - SRI(CM_DGAM_LUT_INDEX, CM, id), \ - SRI(CM_DGAM_LUT_DATA, CM, id), \ - SRI(CM_CONTROL, CM, id), \ - SRI(CM_DGAM_CONTROL, CM, id), \ SRI(FORMAT_CONTROL, CNVC_CFG, id), \ SRI(DPP_CONTROL, DPP_TOP, id), \ SRI(CNVC_SURFACE_PIXEL_FORMAT, CNVC_CFG, id), \ @@ -95,16 +42,6 @@ #define IPP_REG_LIST_DCN10(id) \ IPP_REG_LIST_DCN(id), \ SRI(CURSOR_SETTINS, HUBPREQ, id), \ - SRI(CM_IGAM_CONTROL, CM, id), \ - SRI(CM_COMA_C11_C12, CM, id), \ - SRI(CM_COMA_C13_C14, CM, id), \ - SRI(CM_COMA_C21_C22, CM, id), \ - SRI(CM_COMA_C23_C24, CM, id), \ - SRI(CM_COMA_C31_C32, CM, id), \ - SRI(CM_COMA_C33_C34, CM, id), \ - SRI(CM_IGAM_LUT_RW_CONTROL, CM, id), \ - SRI(CM_IGAM_LUT_RW_INDEX, CM, id), \ - SRI(CM_IGAM_LUT_SEQ_COLOR, CM, id), \ SRI(CURSOR_SURFACE_ADDRESS_HIGH, CURSOR, id), \ SRI(CURSOR_SURFACE_ADDRESS, CURSOR, id), \ SRI(CURSOR_SIZE, CURSOR, id), \ @@ -117,129 +54,10 @@ .field_name = reg_name ## __ ## field_name ## post_fix #define IPP_MASK_SH_LIST_DCN(mask_sh) \ - IPP_SF(CM0_CM_ICSC_CONTROL, CM_ICSC_MODE, mask_sh), \ - IPP_SF(CM0_CM_ICSC_C11_C12, CM_ICSC_C11, mask_sh), \ - IPP_SF(CM0_CM_ICSC_C11_C12, CM_ICSC_C12, mask_sh), \ - IPP_SF(CM0_CM_ICSC_C13_C14, CM_ICSC_C13, mask_sh), \ - IPP_SF(CM0_CM_ICSC_C13_C14, CM_ICSC_C14, mask_sh), \ - IPP_SF(CM0_CM_ICSC_C21_C22, CM_ICSC_C21, mask_sh), \ - IPP_SF(CM0_CM_ICSC_C21_C22, CM_ICSC_C22, mask_sh), \ - IPP_SF(CM0_CM_ICSC_C23_C24, CM_ICSC_C23, mask_sh), \ - IPP_SF(CM0_CM_ICSC_C23_C24, CM_ICSC_C24, mask_sh), \ - IPP_SF(CM0_CM_ICSC_C31_C32, CM_ICSC_C31, mask_sh), \ - IPP_SF(CM0_CM_ICSC_C31_C32, CM_ICSC_C32, mask_sh), \ - IPP_SF(CM0_CM_ICSC_C33_C34, CM_ICSC_C33, mask_sh), \ - IPP_SF(CM0_CM_ICSC_C33_C34, CM_ICSC_C34, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_START_CNTL_B, CM_DGAM_RAMB_EXP_REGION_START_B, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_START_CNTL_B, CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_B, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_START_CNTL_G, CM_DGAM_RAMB_EXP_REGION_START_G, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_START_CNTL_G, CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_G, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_START_CNTL_R, CM_DGAM_RAMB_EXP_REGION_START_R, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_START_CNTL_R, CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_R, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_SLOPE_CNTL_B, CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_SLOPE_CNTL_G, CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_G, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_SLOPE_CNTL_R, CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_R, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_END_CNTL1_B, CM_DGAM_RAMB_EXP_REGION_END_B, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_END_CNTL2_B, CM_DGAM_RAMB_EXP_REGION_END_SLOPE_B, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_END_CNTL2_B, CM_DGAM_RAMB_EXP_REGION_END_BASE_B, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_END_CNTL1_G, CM_DGAM_RAMB_EXP_REGION_END_G, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_END_CNTL2_G, CM_DGAM_RAMB_EXP_REGION_END_SLOPE_G, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_END_CNTL2_G, CM_DGAM_RAMB_EXP_REGION_END_BASE_G, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_END_CNTL1_R, CM_DGAM_RAMB_EXP_REGION_END_R, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_END_CNTL2_R, CM_DGAM_RAMB_EXP_REGION_END_SLOPE_R, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_END_CNTL2_R, CM_DGAM_RAMB_EXP_REGION_END_BASE_R, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_0_1, CM_DGAM_RAMB_EXP_REGION0_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_0_1, CM_DGAM_RAMB_EXP_REGION0_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_0_1, CM_DGAM_RAMB_EXP_REGION1_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_0_1, CM_DGAM_RAMB_EXP_REGION1_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_2_3, CM_DGAM_RAMB_EXP_REGION2_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_2_3, CM_DGAM_RAMB_EXP_REGION2_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_2_3, CM_DGAM_RAMB_EXP_REGION3_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_2_3, CM_DGAM_RAMB_EXP_REGION3_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_4_5, CM_DGAM_RAMB_EXP_REGION4_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_4_5, CM_DGAM_RAMB_EXP_REGION4_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_4_5, CM_DGAM_RAMB_EXP_REGION5_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_4_5, CM_DGAM_RAMB_EXP_REGION5_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_6_7, CM_DGAM_RAMB_EXP_REGION6_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_6_7, CM_DGAM_RAMB_EXP_REGION6_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_6_7, CM_DGAM_RAMB_EXP_REGION7_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_6_7, CM_DGAM_RAMB_EXP_REGION7_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_8_9, CM_DGAM_RAMB_EXP_REGION8_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_8_9, CM_DGAM_RAMB_EXP_REGION8_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_8_9, CM_DGAM_RAMB_EXP_REGION9_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_8_9, CM_DGAM_RAMB_EXP_REGION9_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_10_11, CM_DGAM_RAMB_EXP_REGION10_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_10_11, CM_DGAM_RAMB_EXP_REGION10_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_10_11, CM_DGAM_RAMB_EXP_REGION11_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_10_11, CM_DGAM_RAMB_EXP_REGION11_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_12_13, CM_DGAM_RAMB_EXP_REGION12_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_12_13, CM_DGAM_RAMB_EXP_REGION12_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_12_13, CM_DGAM_RAMB_EXP_REGION13_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_12_13, CM_DGAM_RAMB_EXP_REGION13_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_14_15, CM_DGAM_RAMB_EXP_REGION14_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_14_15, CM_DGAM_RAMB_EXP_REGION14_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_14_15, CM_DGAM_RAMB_EXP_REGION15_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_14_15, CM_DGAM_RAMB_EXP_REGION15_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_START_CNTL_B, CM_DGAM_RAMA_EXP_REGION_START_B, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_START_CNTL_B, CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_B, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_START_CNTL_G, CM_DGAM_RAMA_EXP_REGION_START_G, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_START_CNTL_G, CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_G, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_START_CNTL_R, CM_DGAM_RAMA_EXP_REGION_START_R, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_START_CNTL_R, CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_R, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_SLOPE_CNTL_B, CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_SLOPE_CNTL_G, CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_SLOPE_CNTL_R, CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_END_CNTL1_B, CM_DGAM_RAMA_EXP_REGION_END_B, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_END_CNTL2_B, CM_DGAM_RAMA_EXP_REGION_END_SLOPE_B, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_END_CNTL2_B, CM_DGAM_RAMA_EXP_REGION_END_BASE_B, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_END_CNTL1_G, CM_DGAM_RAMA_EXP_REGION_END_G, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_END_CNTL2_G, CM_DGAM_RAMA_EXP_REGION_END_SLOPE_G, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_END_CNTL2_G, CM_DGAM_RAMA_EXP_REGION_END_BASE_G, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_END_CNTL1_R, CM_DGAM_RAMA_EXP_REGION_END_R, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_END_CNTL2_R, CM_DGAM_RAMA_EXP_REGION_END_SLOPE_R, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_END_CNTL2_R, CM_DGAM_RAMA_EXP_REGION_END_BASE_R, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_0_1, CM_DGAM_RAMA_EXP_REGION0_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_0_1, CM_DGAM_RAMA_EXP_REGION0_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_0_1, CM_DGAM_RAMA_EXP_REGION1_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_0_1, CM_DGAM_RAMA_EXP_REGION1_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_2_3, CM_DGAM_RAMA_EXP_REGION2_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_2_3, CM_DGAM_RAMA_EXP_REGION2_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_2_3, CM_DGAM_RAMA_EXP_REGION3_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_2_3, CM_DGAM_RAMA_EXP_REGION3_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_4_5, CM_DGAM_RAMA_EXP_REGION4_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_4_5, CM_DGAM_RAMA_EXP_REGION4_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_4_5, CM_DGAM_RAMA_EXP_REGION5_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_4_5, CM_DGAM_RAMA_EXP_REGION5_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_6_7, CM_DGAM_RAMA_EXP_REGION6_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_6_7, CM_DGAM_RAMA_EXP_REGION6_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_6_7, CM_DGAM_RAMA_EXP_REGION7_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_6_7, CM_DGAM_RAMA_EXP_REGION7_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_8_9, CM_DGAM_RAMA_EXP_REGION8_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_8_9, CM_DGAM_RAMA_EXP_REGION8_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_8_9, CM_DGAM_RAMA_EXP_REGION9_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_8_9, CM_DGAM_RAMA_EXP_REGION9_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_10_11, CM_DGAM_RAMA_EXP_REGION10_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_10_11, CM_DGAM_RAMA_EXP_REGION10_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_10_11, CM_DGAM_RAMA_EXP_REGION11_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_10_11, CM_DGAM_RAMA_EXP_REGION11_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_12_13, CM_DGAM_RAMA_EXP_REGION12_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_12_13, CM_DGAM_RAMA_EXP_REGION12_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_12_13, CM_DGAM_RAMA_EXP_REGION13_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_12_13, CM_DGAM_RAMA_EXP_REGION13_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_14_15, CM_DGAM_RAMA_EXP_REGION14_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_14_15, CM_DGAM_RAMA_EXP_REGION14_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_14_15, CM_DGAM_RAMA_EXP_REGION15_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_14_15, CM_DGAM_RAMA_EXP_REGION15_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_MEM_PWR_CTRL, SHARED_MEM_PWR_DIS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_LUT_WRITE_EN_MASK, CM_DGAM_LUT_WRITE_EN_MASK, mask_sh), \ - IPP_SF(CM0_CM_DGAM_LUT_WRITE_EN_MASK, CM_DGAM_LUT_WRITE_SEL, mask_sh), \ - IPP_SF(CM0_CM_DGAM_LUT_INDEX, CM_DGAM_LUT_INDEX, mask_sh), \ - IPP_SF(CM0_CM_DGAM_LUT_DATA, CM_DGAM_LUT_DATA, mask_sh), \ IPP_SF(CNVC_CFG0_CNVC_SURFACE_PIXEL_FORMAT, CNVC_SURFACE_PIXEL_FORMAT, mask_sh), \ IPP_SF(CNVC_CFG0_FORMAT_CONTROL, CNVC_BYPASS, mask_sh), \ IPP_SF(CNVC_CFG0_FORMAT_CONTROL, ALPHA_EN, mask_sh), \ IPP_SF(CNVC_CFG0_FORMAT_CONTROL, FORMAT_EXPANSION_MODE, mask_sh), \ - IPP_SF(CM0_CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, mask_sh), \ IPP_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_MODE, mask_sh), \ IPP_SF(CNVC_CUR0_CURSOR0_COLOR0, CUR0_COLOR0, mask_sh), \ IPP_SF(CNVC_CUR0_CURSOR0_COLOR1, CUR0_COLOR1, mask_sh), \ @@ -250,26 +68,6 @@ IPP_MASK_SH_LIST_DCN(mask_sh),\ IPP_SF(HUBPREQ0_CURSOR_SETTINS, CURSOR0_DST_Y_OFFSET, mask_sh), \ IPP_SF(HUBPREQ0_CURSOR_SETTINS, CURSOR0_CHUNK_HDL_ADJUST, mask_sh), \ - IPP_SF(CM0_CM_COMA_C11_C12, CM_COMA_C11, mask_sh), \ - IPP_SF(CM0_CM_COMA_C11_C12, CM_COMA_C12, mask_sh), \ - IPP_SF(CM0_CM_COMA_C13_C14, CM_COMA_C13, mask_sh), \ - IPP_SF(CM0_CM_COMA_C13_C14, CM_COMA_C14, mask_sh), \ - IPP_SF(CM0_CM_COMA_C21_C22, CM_COMA_C21, mask_sh), \ - IPP_SF(CM0_CM_COMA_C21_C22, CM_COMA_C22, mask_sh), \ - IPP_SF(CM0_CM_COMA_C23_C24, CM_COMA_C23, mask_sh), \ - IPP_SF(CM0_CM_COMA_C23_C24, CM_COMA_C24, mask_sh), \ - IPP_SF(CM0_CM_COMA_C31_C32, CM_COMA_C31, mask_sh), \ - IPP_SF(CM0_CM_COMA_C31_C32, CM_COMA_C32, mask_sh), \ - IPP_SF(CM0_CM_COMA_C33_C34, CM_COMA_C33, mask_sh), \ - IPP_SF(CM0_CM_COMA_C33_C34, CM_COMA_C34, mask_sh), \ - IPP_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_DGAM_CONFIG_STATUS, mask_sh), \ - IPP_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_HOST_EN, mask_sh), \ - IPP_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_RW_MODE, mask_sh), \ - IPP_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_SEL, mask_sh), \ - IPP_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_WRITE_EN_MASK, mask_sh), \ - IPP_SF(CM0_CM_IGAM_LUT_RW_INDEX, CM_IGAM_LUT_RW_INDEX, mask_sh), \ - IPP_SF(CM0_CM_IGAM_LUT_SEQ_COLOR, CM_IGAM_LUT_SEQ_COLOR, mask_sh), \ - IPP_SF(CM0_CM_CONTROL, CM_BYPASS_EN, mask_sh), \ IPP_SF(CURSOR0_CURSOR_SURFACE_ADDRESS_HIGH, CURSOR_SURFACE_ADDRESS_HIGH, mask_sh), \ IPP_SF(CURSOR0_CURSOR_SURFACE_ADDRESS, CURSOR_SURFACE_ADDRESS, mask_sh), \ IPP_SF(CURSOR0_CURSOR_SIZE, CURSOR_WIDTH, mask_sh), \ @@ -283,163 +81,13 @@ IPP_SF(CURSOR0_CURSOR_HOT_SPOT, CURSOR_HOT_SPOT_X, mask_sh), \ IPP_SF(CURSOR0_CURSOR_HOT_SPOT, CURSOR_HOT_SPOT_Y, mask_sh), \ IPP_SF(CURSOR0_CURSOR_DST_OFFSET, CURSOR_DST_X_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, mask_sh), \ - IPP_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_LUT_FORMAT_R, mask_sh), \ - IPP_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_LUT_FORMAT_G, mask_sh), \ - IPP_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_LUT_FORMAT_B, mask_sh), \ - IPP_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_INPUT_FORMAT, mask_sh), \ IPP_SF(CNVC_CFG0_FORMAT_CONTROL, OUTPUT_FP, mask_sh) #define IPP_DCN10_REG_FIELD_LIST(type) \ - type CM_DGAM_CONFIG_STATUS; \ - type CM_ICSC_MODE; \ - type CM_ICSC_C11; \ - type CM_ICSC_C12; \ - type CM_ICSC_C13; \ - type CM_ICSC_C14; \ - type CM_ICSC_C21; \ - type CM_ICSC_C22; \ - type CM_ICSC_C23; \ - type CM_ICSC_C24; \ - type CM_ICSC_C31; \ - type CM_ICSC_C32; \ - type CM_ICSC_C33; \ - type CM_ICSC_C34; \ - type CM_COMA_C11; \ - type CM_COMA_C12; \ - type CM_COMA_C13; \ - type CM_COMA_C14; \ - type CM_COMA_C21; \ - type CM_COMA_C22; \ - type CM_COMA_C23; \ - type CM_COMA_C24; \ - type CM_COMA_C31; \ - type CM_COMA_C32; \ - type CM_COMA_C33; \ - type CM_COMA_C34; \ - type CM_DGAM_RAMB_EXP_REGION_START_B; \ - type CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_B; \ - type CM_DGAM_RAMB_EXP_REGION_START_G; \ - type CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_G; \ - type CM_DGAM_RAMB_EXP_REGION_START_R; \ - type CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_R; \ - type CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B; \ - type CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_G; \ - type CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_R; \ - type CM_DGAM_RAMB_EXP_REGION_END_B; \ - type CM_DGAM_RAMB_EXP_REGION_END_SLOPE_B; \ - type CM_DGAM_RAMB_EXP_REGION_END_BASE_B; \ - type CM_DGAM_RAMB_EXP_REGION_END_G; \ - type CM_DGAM_RAMB_EXP_REGION_END_SLOPE_G; \ - type CM_DGAM_RAMB_EXP_REGION_END_BASE_G; \ - type CM_DGAM_RAMB_EXP_REGION_END_R; \ - type CM_DGAM_RAMB_EXP_REGION_END_SLOPE_R; \ - type CM_DGAM_RAMB_EXP_REGION_END_BASE_R; \ - type CM_DGAM_RAMB_EXP_REGION0_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION0_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION1_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION1_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION2_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION2_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION3_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION3_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION4_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION4_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION5_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION5_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION6_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION6_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION7_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION7_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION8_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION8_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION9_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION9_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION10_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION10_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION11_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION11_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION12_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION12_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION13_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION13_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION14_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION14_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION15_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION15_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION_START_B; \ - type CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_B; \ - type CM_DGAM_RAMA_EXP_REGION_START_G; \ - type CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_G; \ - type CM_DGAM_RAMA_EXP_REGION_START_R; \ - type CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_R; \ - type CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B; \ - type CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G; \ - type CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R; \ - type CM_DGAM_RAMA_EXP_REGION_END_B; \ - type CM_DGAM_RAMA_EXP_REGION_END_SLOPE_B; \ - type CM_DGAM_RAMA_EXP_REGION_END_BASE_B; \ - type CM_DGAM_RAMA_EXP_REGION_END_G; \ - type CM_DGAM_RAMA_EXP_REGION_END_SLOPE_G; \ - type CM_DGAM_RAMA_EXP_REGION_END_BASE_G; \ - type CM_DGAM_RAMA_EXP_REGION_END_R; \ - type CM_DGAM_RAMA_EXP_REGION_END_SLOPE_R; \ - type CM_DGAM_RAMA_EXP_REGION_END_BASE_R; \ - type CM_DGAM_RAMA_EXP_REGION0_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION0_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION1_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION1_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION2_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION2_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION3_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION3_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION4_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION4_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION5_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION5_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION6_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION6_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION7_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION7_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION8_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION8_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION9_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION9_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION10_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION10_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION11_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION11_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION12_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION12_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION13_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION13_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION14_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION14_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION15_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION15_NUM_SEGMENTS; \ - type SHARED_MEM_PWR_DIS; \ - type CM_IGAM_LUT_FORMAT_R; \ - type CM_IGAM_LUT_FORMAT_G; \ - type CM_IGAM_LUT_FORMAT_B; \ - type CM_IGAM_LUT_HOST_EN; \ - type CM_IGAM_LUT_RW_INDEX; \ - type CM_IGAM_LUT_RW_MODE; \ - type CM_IGAM_LUT_WRITE_EN_MASK; \ - type CM_IGAM_LUT_SEL; \ - type CM_IGAM_LUT_SEQ_COLOR; \ - type CM_IGAM_DGAM_CONFIG_STATUS; \ - type CM_DGAM_LUT_WRITE_EN_MASK; \ - type CM_DGAM_LUT_WRITE_SEL; \ - type CM_DGAM_LUT_INDEX; \ - type CM_DGAM_LUT_DATA; \ - type CM_BYPASS_EN; \ - type CM_BYPASS; \ type CNVC_SURFACE_PIXEL_FORMAT; \ type CNVC_BYPASS; \ type ALPHA_EN; \ type FORMAT_EXPANSION_MODE; \ - type CM_DGAM_LUT_MODE; \ - type CM_IGAM_LUT_MODE; \ type CURSOR0_DST_Y_OFFSET; \ type CURSOR0_CHUNK_HDL_ADJUST; \ type CUR0_MODE; \ @@ -460,7 +108,6 @@ type CURSOR_HOT_SPOT_X; \ type CURSOR_HOT_SPOT_Y; \ type CURSOR_DST_X_OFFSET; \ - type CM_IGAM_INPUT_FORMAT; \ type OUTPUT_FP struct dcn10_ipp_shift { @@ -472,69 +119,6 @@ struct dcn10_ipp_mask { }; struct dcn10_ipp_registers { - uint32_t CM_ICSC_CONTROL; - uint32_t CM_ICSC_C11_C12; - uint32_t CM_ICSC_C13_C14; - uint32_t CM_ICSC_C21_C22; - uint32_t CM_ICSC_C23_C24; - uint32_t CM_ICSC_C31_C32; - uint32_t CM_ICSC_C33_C34; - uint32_t CM_COMA_C11_C12; - uint32_t CM_COMA_C13_C14; - uint32_t CM_COMA_C21_C22; - uint32_t CM_COMA_C23_C24; - uint32_t CM_COMA_C31_C32; - uint32_t CM_COMA_C33_C34; - uint32_t CM_DGAM_RAMB_START_CNTL_B; - uint32_t CM_DGAM_RAMB_START_CNTL_G; - uint32_t CM_DGAM_RAMB_START_CNTL_R; - uint32_t CM_DGAM_RAMB_SLOPE_CNTL_B; - uint32_t CM_DGAM_RAMB_SLOPE_CNTL_G; - uint32_t CM_DGAM_RAMB_SLOPE_CNTL_R; - uint32_t CM_DGAM_RAMB_END_CNTL1_B; - uint32_t CM_DGAM_RAMB_END_CNTL2_B; - uint32_t CM_DGAM_RAMB_END_CNTL1_G; - uint32_t CM_DGAM_RAMB_END_CNTL2_G; - uint32_t CM_DGAM_RAMB_END_CNTL1_R; - uint32_t CM_DGAM_RAMB_END_CNTL2_R; - uint32_t CM_DGAM_RAMB_REGION_0_1; - uint32_t CM_DGAM_RAMB_REGION_2_3; - uint32_t CM_DGAM_RAMB_REGION_4_5; - uint32_t CM_DGAM_RAMB_REGION_6_7; - uint32_t CM_DGAM_RAMB_REGION_8_9; - uint32_t CM_DGAM_RAMB_REGION_10_11; - uint32_t CM_DGAM_RAMB_REGION_12_13; - uint32_t CM_DGAM_RAMB_REGION_14_15; - uint32_t CM_DGAM_RAMA_START_CNTL_B; - uint32_t CM_DGAM_RAMA_START_CNTL_G; - uint32_t CM_DGAM_RAMA_START_CNTL_R; - uint32_t CM_DGAM_RAMA_SLOPE_CNTL_B; - uint32_t CM_DGAM_RAMA_SLOPE_CNTL_G; - uint32_t CM_DGAM_RAMA_SLOPE_CNTL_R; - uint32_t CM_DGAM_RAMA_END_CNTL1_B; - uint32_t CM_DGAM_RAMA_END_CNTL2_B; - uint32_t CM_DGAM_RAMA_END_CNTL1_G; - uint32_t CM_DGAM_RAMA_END_CNTL2_G; - uint32_t CM_DGAM_RAMA_END_CNTL1_R; - uint32_t CM_DGAM_RAMA_END_CNTL2_R; - uint32_t CM_DGAM_RAMA_REGION_0_1; - uint32_t CM_DGAM_RAMA_REGION_2_3; - uint32_t CM_DGAM_RAMA_REGION_4_5; - uint32_t CM_DGAM_RAMA_REGION_6_7; - uint32_t CM_DGAM_RAMA_REGION_8_9; - uint32_t CM_DGAM_RAMA_REGION_10_11; - uint32_t CM_DGAM_RAMA_REGION_12_13; - uint32_t CM_DGAM_RAMA_REGION_14_15; - uint32_t CM_MEM_PWR_CTRL; - uint32_t CM_IGAM_LUT_RW_CONTROL; - uint32_t CM_IGAM_LUT_RW_INDEX; - uint32_t CM_IGAM_LUT_SEQ_COLOR; - uint32_t CM_DGAM_LUT_WRITE_EN_MASK; - uint32_t CM_DGAM_LUT_INDEX; - uint32_t CM_DGAM_LUT_DATA; - uint32_t CM_CONTROL; - uint32_t CM_DGAM_CONTROL; - uint32_t CM_IGAM_CONTROL; uint32_t DPP_CONTROL; uint32_t CURSOR_SETTINS; uint32_t CURSOR_SETTINGS; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h index 589bddad7e66..9602f261b614 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h @@ -98,6 +98,24 @@ enum graphics_csc_adjust_type { GRAPHICS_CSC_ADJUST_TYPE_SW /*use adjustments */ }; +enum ipp_degamma_mode { + IPP_DEGAMMA_MODE_BYPASS, + IPP_DEGAMMA_MODE_HW_sRGB, + IPP_DEGAMMA_MODE_HW_xvYCC, + IPP_DEGAMMA_MODE_USER_PWL +}; + +enum ipp_output_format { + IPP_OUTPUT_FORMAT_12_BIT_FIX, + IPP_OUTPUT_FORMAT_16_BIT_BYPASS, + IPP_OUTPUT_FORMAT_FLOAT +}; + +enum expansion_mode { + EXPANSION_MODE_DYNAMIC, + EXPANSION_MODE_ZERO +}; + struct default_adjustment { enum lb_pixel_depth lb_color_depth; enum dc_color_space out_color_space; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h index 0f952e5b3ae8..7ebfdc1c19c1 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h @@ -54,12 +54,7 @@ struct ipp_prescale_params { uint16_t scale; }; -enum ipp_degamma_mode { - IPP_DEGAMMA_MODE_BYPASS, - IPP_DEGAMMA_MODE_HW_sRGB, - IPP_DEGAMMA_MODE_HW_xvYCC, - IPP_DEGAMMA_MODE_USER_PWL -}; + enum ovl_color_space { OVL_COLOR_SPACE_UNKNOWN = 0, @@ -68,16 +63,6 @@ enum ovl_color_space { OVL_COLOR_SPACE_YUV709 }; -enum expansion_mode { - EXPANSION_MODE_DYNAMIC, - EXPANSION_MODE_ZERO -}; - -enum ipp_output_format { - IPP_OUTPUT_FORMAT_12_BIT_FIX, - IPP_OUTPUT_FORMAT_16_BIT_BYPASS, - IPP_OUTPUT_FORMAT_FLOAT -}; struct ipp_funcs { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h index f3d66752ed90..623042d2c272 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h @@ -219,6 +219,26 @@ struct transform_funcs { void (*opp_set_regamma_mode)( struct transform *xfm_base, enum opp_regamma mode); + + void (*ipp_set_degamma)( + struct transform *xfm_base, + enum ipp_degamma_mode mode); + + void (*ipp_program_input_lut)( + struct transform *xfm_base, + const struct dc_gamma *gamma); + + void (*ipp_program_degamma_pwl)(struct transform *xfm_base, + const struct pwl_params *params); + + void (*ipp_setup)( + struct transform *xfm_base, + enum surface_pixel_format input_format, + enum expansion_mode mode, + enum ipp_output_format cnv_out_format); + + void (*ipp_full_bypass)(struct transform *xfm_base); + }; extern const uint16_t filter_2tap_16p[18]; -- cgit From 41f97c0773aed681ad65fa27ee88b503fbdcd298 Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Thu, 24 Aug 2017 17:40:00 -0400 Subject: drm/amd/display: DF C-state entry blocked when DPMS Signed-off-by: Hersen Wu Reviewed-by: Hersen Wu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 4 ++ .../amd/display/dc/dce110/dce110_hw_sequencer.c | 9 +++- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 48 +++++++++++++++++++++- .../gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c | 9 ++++ .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 1 + drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h | 2 + drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 3 ++ 7 files changed, 74 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index dc1b7d061be2..a20dc24db0d5 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -830,6 +830,8 @@ static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *c if (!dcb->funcs->is_accelerated_mode(dcb)) dc->hwss.enable_accelerated_mode(dc); + dc->hwss.ready_shared_resources(dc); + for (i = 0; i < dc->res_pool->pipe_count; i++) { pipe = &context->res_ctx.pipe_ctx[i]; dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, pipe); @@ -879,6 +881,8 @@ static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *c dc_retain_validate_context(dc->current_context); + dc->hwss.optimize_shared_resources(dc); + return (result == DC_OK); } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 8ba61b9b8792..3502faa1458f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -2697,6 +2697,10 @@ static void program_csc_matrix(struct pipe_ctx *pipe_ctx, } } +static void ready_shared_resources(struct dc *dc) {} + +static void optimize_shared_resources(struct dc *dc) {} + static const struct hw_sequencer_funcs dce110_funcs = { .program_gamut_remap = program_gamut_remap, .program_csc_matrix = program_csc_matrix, @@ -2727,7 +2731,10 @@ static const struct hw_sequencer_funcs dce110_funcs = { .prog_pixclk_crtc_otg = dce110_prog_pixclk_crtc_otg, .setup_stereo = NULL, .set_avmute = dce110_set_avmute, - .wait_for_mpcc_disconnect = dce110_wait_for_mpcc_disconnect + .wait_for_mpcc_disconnect = dce110_wait_for_mpcc_disconnect, + .ready_shared_resources = ready_shared_resources, + .optimize_shared_resources = optimize_shared_resources, + }; bool dce110_hw_sequencer_construct(struct dc *dc) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 4a24893486e8..9c54cae28997 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -776,6 +776,50 @@ static void power_on_plane( "Un-gated front end for pipe %d\n", plane_id); } +static void undo_DEGVIDCN10_253_wa(struct dc *dc) +{ + struct dce_hwseq *hws = dc->hwseq; + struct mem_input *mi = dc->res_pool->mis[0]; + + mi->funcs->set_blank(mi, true); + + REG_SET(DC_IP_REQUEST_CNTL, 0, + IP_REQUEST_EN, 1); + + hubp_pg_control(hws, 0, false); + REG_SET(DC_IP_REQUEST_CNTL, 0, + IP_REQUEST_EN, 0); +} + +static void ready_shared_resources(struct dc *dc) +{ + if (dc->current_context->stream_count == 0 && + !dc->debug.disable_stutter) + undo_DEGVIDCN10_253_wa(dc); +} + +static void apply_DEGVIDCN10_253_wa(struct dc *dc) +{ + struct dce_hwseq *hws = dc->hwseq; + struct mem_input *mi = dc->res_pool->mis[0]; + + REG_SET(DC_IP_REQUEST_CNTL, 0, + IP_REQUEST_EN, 1); + + hubp_pg_control(hws, 0, true); + REG_SET(DC_IP_REQUEST_CNTL, 0, + IP_REQUEST_EN, 0); + + mi->funcs->set_hubp_blank_en(mi, false); +} + +static void optimize_shared_resources(struct dc *dc) +{ + if (dc->current_context->stream_count == 0 && + !dc->debug.disable_stutter) + apply_DEGVIDCN10_253_wa(dc); +} + static void bios_golden_init(struct dc *dc) { struct dc_bios *bp = dc->ctx->dc_bios; @@ -2829,7 +2873,9 @@ static const struct hw_sequencer_funcs dcn10_funcs = { .setup_stereo = dcn10_setup_stereo, .set_avmute = dce110_set_avmute, .log_hw_state = dcn10_log_hw_state, - .wait_for_mpcc_disconnect = dcn10_wait_for_mpcc_disconnect + .wait_for_mpcc_disconnect = dcn10_wait_for_mpcc_disconnect, + .ready_shared_resources = ready_shared_resources, + .optimize_shared_resources = optimize_shared_resources, }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index 0a47e6ad4286..9008cd03b139 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -56,6 +56,14 @@ static void min10_set_blank(struct mem_input *mem_input, bool blank) } } +static void min10_set_hubp_blank_en(struct mem_input *mem_input, bool blank) +{ + struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + uint32_t blank_en = blank ? 1 : 0; + + REG_UPDATE(DCHUBP_CNTL, HUBP_BLANK_EN, blank_en); +} + static void min10_vready_workaround(struct mem_input *mem_input, struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest) { @@ -771,6 +779,7 @@ static struct mem_input_funcs dcn10_mem_input_funcs = { .set_blank = min10_set_blank, .dcc_control = min10_dcc_control, .mem_program_viewport = min_set_viewport, + .set_hubp_blank_en = min10_set_hubp_blank_en, }; /*****************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 4af40f5138fc..d09ed13fb8ea 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -439,6 +439,7 @@ static const struct dc_debug debug_defaults_diags = { .force_abm_enable = false, .timing_trace = true, .clock_trace = true, + .disable_stutter = true, #if defined(CONFIG_DRM_AMD_DC_DCN1_0) .disable_pplib_clock_request = true, .disable_pplib_wm_range = true, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h index 6f4f04da9e28..6cef9ad0af91 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h @@ -161,6 +161,8 @@ struct mem_input_funcs { struct dchub_init_data *dh_data); void (*set_blank)(struct mem_input *mi, bool blank); + void (*set_hubp_blank_en)(struct mem_input *mi, bool blank); + }; #endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index c73dca9f6d46..01e426194163 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -173,6 +173,9 @@ struct hw_sequencer_funcs { void (*wait_for_mpcc_disconnect)(struct dc *dc, struct resource_pool *res_pool, struct pipe_ctx *pipe_ctx); + + void (*ready_shared_resources)(struct dc *dc); + void (*optimize_shared_resources)(struct dc *dc); }; void color_space_to_black_color( -- cgit From d1423e6faf161e69070dbb1d6764dd5da59563a8 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Tue, 22 Aug 2017 15:03:06 -0400 Subject: drm/amd/display: Remove mpc from bios left over, keep double buffer disabled. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c | 10 +++++++++- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c | 3 --- 2 files changed, 9 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c index ce408ccb428e..082b39a65e6a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c @@ -127,10 +127,18 @@ static void mpc10_mpcc_remove( for (z_idx = 0; z_idx < opp->mpc_tree.num_pipes; z_idx++) if (opp->mpc_tree.dpp[z_idx] == dpp_id) break; + if (z_idx == opp->mpc_tree.num_pipes) { - ASSERT(0); + /* In case of resume from S3/S4, remove mpcc from bios left over */ + REG_SET(MPCC_OPP_ID[dpp_id], 0, + MPCC_OPP_ID, 0xf); + REG_SET(MPCC_TOP_SEL[dpp_id], 0, + MPCC_TOP_SEL, 0xf); + REG_SET(MPCC_BOT_SEL[dpp_id], 0, + MPCC_BOT_SEL, 0xf); return; } + mpcc_id = opp->mpc_tree.mpcc[z_idx]; REG_SET(MPCC_OPP_ID[mpcc_id], 0, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c index cc58f43400d7..6a5f2683c2e5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c @@ -289,9 +289,6 @@ static void tgn10_unblank_crtc(struct timing_generator *tg) { struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); - REG_UPDATE(OTG_DOUBLE_BUFFER_CONTROL, - OTG_BLANK_DATA_DOUBLE_BUFFER_EN, 1); - REG_UPDATE_2(OTG_BLANK_CONTROL, OTG_BLANK_DATA_EN, 0, OTG_BLANK_DE_MODE, 0); -- cgit From 9cffc573196bb3eea2d3dfd24893b6b9970cdfce Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Fri, 25 Aug 2017 16:13:55 -0400 Subject: drm/amd/display: clean up header file includes Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c | 20 ----------- .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c | 20 ----------- .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c | 8 ----- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c | 41 ---------------------- 4 files changed, 89 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c index 20163668e2a8..99caafb27b37 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c @@ -27,10 +27,6 @@ #include "core_types.h" -#include "include/grph_object_id.h" -#include "include/fixed31_32.h" -#include "include/logger_interface.h" - #include "reg_helper.h" #include "dcn10_dpp.h" #include "basics/conversion.h" @@ -68,22 +64,6 @@ enum dcn10_coef_filter_type_sel { SCL_COEF_ALPHA_HORZ_FILTER = 5 }; -enum lb_memory_config { - /* Enable all 3 pieces of memory */ - LB_MEMORY_CONFIG_0 = 0, - - /* Enable only the first piece of memory */ - LB_MEMORY_CONFIG_1 = 1, - - /* Enable only the second piece of memory */ - LB_MEMORY_CONFIG_2 = 2, - - /* Only applicable in 4:2:0 mode, enable all 3 pieces of memory and the - * last piece of chroma memory used for the luma storage - */ - LB_MEMORY_CONFIG_3 = 3 -}; - enum dscl_autocal_mode { AUTOCAL_MODE_OFF = 0, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c index 409462f29f54..81620241a978 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c @@ -27,10 +27,6 @@ #include "core_types.h" -#include "include/grph_object_id.h" -#include "include/fixed31_32.h" -#include "include/logger_interface.h" - #include "reg_helper.h" #include "dcn10_dpp.h" #include "basics/conversion.h" @@ -66,22 +62,6 @@ enum dcn10_coef_filter_type_sel { SCL_COEF_ALPHA_HORZ_FILTER = 5 }; -enum lb_memory_config { - /* Enable all 3 pieces of memory */ - LB_MEMORY_CONFIG_0 = 0, - - /* Enable only the first piece of memory */ - LB_MEMORY_CONFIG_1 = 1, - - /* Enable only the second piece of memory */ - LB_MEMORY_CONFIG_2 = 2, - - /* Only applicable in 4:2:0 mode, enable all 3 pieces of memory and the - * last piece of chroma memory used for the luma storage - */ - LB_MEMORY_CONFIG_3 = 3 -}; - enum dscl_autocal_mode { AUTOCAL_MODE_OFF = 0, 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 14c3b330b27b..b62cb38f523c 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 @@ -100,14 +100,6 @@ enum dscl_mode_sel { DSCL_MODE_DSCL_BYPASS = 6 }; -enum gamut_remap_select { - GAMUT_REMAP_BYPASS = 0, - GAMUT_REMAP_COEFF, - GAMUT_REMAP_COMA_COEFF, - GAMUT_REMAP_COMB_COEFF -}; - - static void dpp_set_overscan( struct dcn10_dpp *xfm, const struct scaler_data *data) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c index bc9827967535..5edc4b7073e1 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c @@ -37,40 +37,6 @@ #define CTX \ ippn10->base.ctx - -struct dcn10_input_csc_matrix { - enum dc_color_space color_space; - uint32_t regval[12]; -}; - -static const struct dcn10_input_csc_matrix dcn10_input_csc_matrix[] = { - {COLOR_SPACE_SRGB, - {0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} }, - {COLOR_SPACE_SRGB_LIMITED, - {0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} }, - {COLOR_SPACE_YCBCR601, - {0x2cdd, 0x2000, 0, 0xe991, 0xe926, 0x2000, 0xf4fd, 0x10ef, - 0, 0x2000, 0x38b4, 0xe3a6} }, - {COLOR_SPACE_YCBCR601_LIMITED, - {0x3353, 0x2568, 0, 0xe400, 0xe5dc, 0x2568, 0xf367, 0x1108, - 0, 0x2568, 0x40de, 0xdd3a} }, - {COLOR_SPACE_YCBCR709, - {0x3265, 0x2000, 0, 0xe6ce, 0xf105, 0x2000, 0xfa01, 0xa7d, 0, - 0x2000, 0x3b61, 0xe24f} }, - - {COLOR_SPACE_YCBCR709_LIMITED, - {0x39a6, 0x2568, 0, 0xe0d6, 0xeedd, 0x2568, 0xf925, 0x9a8, 0, - 0x2568, 0x43ee, 0xdbb2} } -}; - -enum dcn10_input_csc_select { - INPUT_CSC_SELECT_BYPASS = 0, - INPUT_CSC_SELECT_ICSC, - INPUT_CSC_SELECT_COMA -}; - - - static bool ippn10_cursor_program_control( struct dcn10_ipp *ippn10, bool pixel_data_invert, @@ -255,13 +221,6 @@ static void ippn10_cursor_set_position( /* TODO Handle surface pixel formats other than 4:4:4 */ } -enum pixel_format_description { - PIXEL_FORMAT_FIXED = 0, - PIXEL_FORMAT_FIXED16, - PIXEL_FORMAT_FLOAT - -}; - /*****************************************/ /* Constructor, Destructor */ /*****************************************/ -- cgit From 608ac7bb3924178d7bfa8b88d79d3d9d72b8f485 Mon Sep 17 00:00:00 2001 From: Jerry Zuo Date: Fri, 25 Aug 2017 16:16:10 -0400 Subject: drm/amd/display: Rename dc validate_context and current_context MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename all the dc validate_context to dc_state and dc current_context to current_state. Signed-off-by: Jerry Zuo Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 +- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 2 +- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 6 +- drivers/gpu/drm/amd/display/dc/core/dc.c | 108 ++++++++++----------- drivers/gpu/drm/amd/display/dc/core/dc_debug.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 8 +- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 4 +- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 40 ++++---- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 15 ++- drivers/gpu/drm/amd/display/dc/core/dc_surface.c | 4 +- drivers/gpu/drm/amd/display/dc/dc.h | 38 ++++---- .../gpu/drm/amd/display/dc/dce/dce_clock_source.c | 4 +- .../amd/display/dc/dce100/dce100_hw_sequencer.c | 8 +- .../amd/display/dc/dce100/dce100_hw_sequencer.h | 4 +- .../drm/amd/display/dc/dce100/dce100_resource.c | 10 +- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 70 ++++++------- .../amd/display/dc/dce110/dce110_hw_sequencer.h | 12 +-- .../drm/amd/display/dc/dce110/dce110_resource.c | 16 +-- .../drm/amd/display/dc/dce112/dce112_resource.c | 16 +-- .../drm/amd/display/dc/dce112/dce112_resource.h | 10 +- .../gpu/drm/amd/display/dc/dce80/dce80_resource.c | 10 +- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 62 ++++++------ .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h | 2 +- .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 8 +- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 14 +-- drivers/gpu/drm/amd/display/dc/inc/dce_calcs.h | 2 +- drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h | 4 +- drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 14 +-- drivers/gpu/drm/amd/display/dc/inc/resource.h | 22 ++--- .../amd/display/dc/irq/dce110/irq_service_dce110.c | 2 +- .../gpu/drm/amd/display/include/logger_interface.h | 4 +- 32 files changed, 263 insertions(+), 264 deletions(-) (limited to 'drivers/gpu') 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 9c44b82036fa..9b018115d97e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -711,7 +711,7 @@ dm_atomic_state_clear(struct drm_atomic_state *state) struct dm_atomic_state *dm_state = to_dm_atomic_state(state); if (dm_state->context) { - dc_release_validate_context(dm_state->context); + dc_release_state(dm_state->context); dm_state->context = NULL; } @@ -4098,7 +4098,7 @@ void amdgpu_dm_atomic_commit_tail( } if (dm_state->context) - WARN_ON(!dc_commit_context(dm->dc, dm_state->context)); + WARN_ON(!dc_commit_state(dm->dc, dm_state->context)); list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 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 e0a5632f00a3..71cbee199016 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -209,7 +209,7 @@ struct dm_crtc_state { struct dm_atomic_state { struct drm_atomic_state base; - struct validate_context *context; + struct dc_state *context; }; #define to_dm_atomic_state(x) container_of(x, struct dm_atomic_state, base) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 6c85a54e47d6..ee1b76c074e6 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -476,7 +476,7 @@ static void dcn_bw_calc_rq_dlg_ttu( static void dcn_dml_wm_override( const struct dcn_bw_internal_vars *v, struct display_mode_lib *dml, - struct validate_context *context, + struct dc_state *context, const struct resource_pool *pool) { int i, in_idx, active_count; @@ -593,7 +593,7 @@ static void split_stream_across_pipes( } static void calc_wm_sets_and_perf_params( - struct validate_context *context, + struct dc_state *context, struct dcn_bw_internal_vars *v) { /* Calculate set A last to keep internal var state consistent for required config */ @@ -721,7 +721,7 @@ static bool dcn_bw_apply_registry_override(struct dc *dc) bool dcn_validate_bandwidth( struct dc *dc, - struct validate_context *context) + struct dc_state *context) { const struct resource_pool *pool = dc->res_pool; struct dcn_bw_internal_vars *v = &context->dcn_bw_vars; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index a20dc24db0d5..53f814dcc24d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -160,7 +160,7 @@ static bool stream_adjust_vmin_vmax(struct dc *dc, bool ret = false; for (i = 0; i < MAX_PIPES; i++) { - struct pipe_ctx *pipe = &dc->current_context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i]; if (pipe->stream == stream && pipe->stream_res.stream_enc) { dc->hwss.set_drr(&pipe, 1, vmin, vmax); @@ -187,7 +187,7 @@ static bool stream_get_crtc_position(struct dc *dc, for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe = - &dc->current_context->res_ctx.pipe_ctx[i]; + &dc->current_state->res_ctx.pipe_ctx[i]; if (pipe->stream == stream && pipe->stream_res.stream_enc) { dc->hwss.get_position(&pipe, 1, &position); @@ -207,8 +207,8 @@ static bool set_gamut_remap(struct dc *dc, const struct dc_stream_state *stream) struct pipe_ctx *pipes; for (i = 0; i < MAX_PIPES; i++) { - if (dc->current_context->res_ctx.pipe_ctx[i].stream == stream) { - pipes = &dc->current_context->res_ctx.pipe_ctx[i]; + if (dc->current_state->res_ctx.pipe_ctx[i].stream == stream) { + pipes = &dc->current_state->res_ctx.pipe_ctx[i]; dc->hwss.program_gamut_remap(pipes); ret = true; } @@ -224,10 +224,10 @@ static bool program_csc_matrix(struct dc *dc, struct dc_stream_state *stream) struct pipe_ctx *pipes; for (i = 0; i < MAX_PIPES; i++) { - if (dc->current_context->res_ctx.pipe_ctx[i].stream + if (dc->current_state->res_ctx.pipe_ctx[i].stream == stream) { - pipes = &dc->current_context->res_ctx.pipe_ctx[i]; + pipes = &dc->current_state->res_ctx.pipe_ctx[i]; dc->hwss.program_csc_matrix(pipes, stream->output_color_space, stream->csc_color_matrix.matrix); @@ -252,10 +252,10 @@ static void set_static_screen_events(struct dc *dc, struct dc_stream_state *stream = streams[i]; for (j = 0; j < MAX_PIPES; j++) { - if (dc->current_context->res_ctx.pipe_ctx[j].stream + if (dc->current_state->res_ctx.pipe_ctx[j].stream == stream) { pipes_affected[num_pipes_affected++] = - &dc->current_context->res_ctx.pipe_ctx[j]; + &dc->current_state->res_ctx.pipe_ctx[j]; } } } @@ -334,7 +334,7 @@ void set_dither_option(struct dc_stream_state *stream, { struct bit_depth_reduction_params params; struct dc_link *link = stream->status.link; - struct pipe_ctx *pipes = link->dc->current_context->res_ctx.pipe_ctx; + struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx; memset(¶ms, 0, sizeof(params)); if (!stream) @@ -408,8 +408,8 @@ static void allocate_dc_stream_funcs(struct dc *dc) static void destruct(struct dc *dc) { - dc_release_validate_context(dc->current_context); - dc->current_context = NULL; + dc_release_state(dc->current_state); + dc->current_state = NULL; destroy_links(dc); @@ -494,9 +494,9 @@ static bool construct(struct dc *dc, goto fail; } - dc->current_context = dc_create_state(); + dc->current_state = dc_create_state(); - if (!dc->current_context) { + if (!dc->current_state) { dm_error("%s: failed to create validate ctx\n", __func__); goto fail; } @@ -668,12 +668,12 @@ bool dc_validate_guaranteed( struct dc_stream_state *stream) { enum dc_status result = DC_ERROR_UNEXPECTED; - struct validate_context *context; + struct dc_state *context; if (!dc_validate_stream(dc, stream)) return false; - context = dm_alloc(sizeof(struct validate_context)); + context = dm_alloc(sizeof(struct dc_state)); if (context == NULL) goto context_alloc_fail; @@ -682,7 +682,7 @@ bool dc_validate_guaranteed( result = dc->res_pool->funcs->validate_guaranteed( dc, stream, context); - dc_release_validate_context(context); + dc_release_state(context); context_alloc_fail: if (result != DC_OK) { @@ -697,7 +697,7 @@ context_alloc_fail: static void program_timing_sync( struct dc *dc, - struct validate_context *ctx) + struct dc_state *ctx) { int i, j; int group_index = 0; @@ -771,15 +771,15 @@ static void program_timing_sync( static bool context_changed( struct dc *dc, - struct validate_context *context) + struct dc_state *context) { uint8_t i; - if (context->stream_count != dc->current_context->stream_count) + if (context->stream_count != dc->current_state->stream_count) return true; - for (i = 0; i < dc->current_context->stream_count; i++) { - if (dc->current_context->streams[i] != context->streams[i]) + for (i = 0; i < dc->current_state->stream_count; i++) { + if (dc->current_state->streams[i] != context->streams[i]) return true; } @@ -788,7 +788,7 @@ static bool context_changed( bool dc_enable_stereo( struct dc *dc, - struct validate_context *context, + struct dc_state *context, struct dc_stream_state *streams[], uint8_t stream_count) { @@ -800,7 +800,7 @@ bool dc_enable_stereo( if (context != NULL) pipe = &context->res_ctx.pipe_ctx[i]; else - pipe = &dc->current_context->res_ctx.pipe_ctx[i]; + pipe = &dc->current_state->res_ctx.pipe_ctx[i]; for (j = 0 ; pipe && j < stream_count; j++) { if (streams[j] && streams[j] == pipe->stream && dc->hwss.setup_stereo) @@ -816,7 +816,7 @@ bool dc_enable_stereo( * Applies given context to HW and copy it into current context. * It's up to the user to release the src context afterwards. */ -static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *context) +static bool dc_commit_state_no_check(struct dc *dc, struct dc_state *context) { struct dc_bios *dcb = dc->ctx->dc_bios; enum dc_status result = DC_ERROR_UNEXPECTED; @@ -875,18 +875,18 @@ static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *c dc_enable_stereo(dc, context, dc_streams, context->stream_count); - dc_release_validate_context(dc->current_context); + dc_release_state(dc->current_state); - dc->current_context = context; + dc->current_state = context; - dc_retain_validate_context(dc->current_context); + dc_retain_state(dc->current_state); dc->hwss.optimize_shared_resources(dc); return (result == DC_OK); } -bool dc_commit_context(struct dc *dc, struct validate_context *context) +bool dc_commit_state(struct dc *dc, struct dc_state *context) { enum dc_status result = DC_ERROR_UNEXPECTED; int i; @@ -905,7 +905,7 @@ bool dc_commit_context(struct dc *dc, struct validate_context *context) LOG_DC); } - result = dc_commit_context_no_check(dc, context); + result = dc_commit_state_no_check(dc, context); return (result == DC_OK); } @@ -914,7 +914,7 @@ bool dc_commit_context(struct dc *dc, struct validate_context *context) bool dc_post_update_surfaces_to_stream(struct dc *dc) { int i; - struct validate_context *context = dc->current_context; + struct dc_state *context = dc->current_state; post_surface_trace(dc); @@ -999,9 +999,9 @@ bool dc_commit_planes_to_stream( return true; } -struct validate_context *dc_create_state(void) +struct dc_state *dc_create_state(void) { - struct validate_context *context = dm_alloc(sizeof(struct validate_context)); + struct dc_state *context = dm_alloc(sizeof(struct dc_state)); if (!context) return NULL; @@ -1010,13 +1010,13 @@ struct validate_context *dc_create_state(void) return context; } -void dc_retain_validate_context(struct validate_context *context) +void dc_retain_state(struct dc_state *context) { ASSERT(atomic_read(&context->ref_count) > 0); atomic_inc(&context->ref_count); } -void dc_release_validate_context(struct validate_context *context) +void dc_release_state(struct dc_state *context) { ASSERT(atomic_read(&context->ref_count) > 0); atomic_dec(&context->ref_count); @@ -1028,7 +1028,7 @@ void dc_release_validate_context(struct validate_context *context) } static bool is_surface_in_context( - const struct validate_context *context, + const struct dc_state *context, const struct dc_plane_state *plane_state) { int j; @@ -1145,7 +1145,7 @@ static enum surface_update_type det_surface_update( const struct dc_surface_update *u, int surface_index) { - const struct validate_context *context = dc->current_context; + const struct dc_state *context = dc->current_state; enum surface_update_type type = UPDATE_TYPE_FAST; enum surface_update_type overall_type = UPDATE_TYPE_FAST; @@ -1200,7 +1200,7 @@ enum surface_update_type dc_check_update_surfaces_for_stream( } static struct dc_stream_status *stream_get_status( - struct validate_context *ctx, + struct dc_state *ctx, struct dc_stream_state *stream) { uint8_t i; @@ -1221,7 +1221,7 @@ void dc_update_planes_and_stream(struct dc *dc, struct dc_stream_state *stream, struct dc_stream_update *stream_update) { - struct validate_context *context; + struct dc_state *context; int i, j; enum surface_update_type update_type; const struct dc_stream_status *stream_status; @@ -1239,7 +1239,7 @@ void dc_update_planes_and_stream(struct dc *dc, ASSERT(0); } #endif - context = dc->current_context; + context = dc->current_state; /* update current stream with the new updates */ if (stream_update) { @@ -1293,7 +1293,7 @@ void dc_update_planes_and_stream(struct dc *dc, goto context_alloc_fail; dc_resource_validate_ctx_copy_construct( - dc->current_context, context); + dc->current_state, context); /*remove old surfaces from context */ if (!dc_rem_all_planes_for_stream(dc, stream, context)) { @@ -1437,7 +1437,7 @@ void dc_update_planes_and_stream(struct dc *dc, /* Full fe update*/ for (j = 0; j < dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - struct pipe_ctx *cur_pipe_ctx = &dc->current_context->res_ctx.pipe_ctx[j]; + struct pipe_ctx *cur_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[j]; bool is_new_pipe_surface = cur_pipe_ctx->plane_state != pipe_ctx->plane_state; struct dc_cursor_position position = { 0 }; @@ -1524,7 +1524,7 @@ void dc_update_planes_and_stream(struct dc *dc, } } - if (dc->current_context != context) { + if (dc->current_state != context) { /* Since memory free requires elevated IRQL, an interrupt * request is generated by mem free. If this happens @@ -1534,16 +1534,16 @@ void dc_update_planes_and_stream(struct dc *dc, * then free the old context. */ - struct validate_context *old = dc->current_context; + struct dc_state *old = dc->current_state; - dc->current_context = context; - dc_release_validate_context(old); + dc->current_state = context; + dc_release_state(old); } return; fail: - dc_release_validate_context(context); + dc_release_state(context); context_alloc_fail: DC_ERROR("Failed to allocate new validate context!\n"); @@ -1551,13 +1551,13 @@ context_alloc_fail: uint8_t dc_get_current_stream_count(struct dc *dc) { - return dc->current_context->stream_count; + return dc->current_state->stream_count; } struct dc_stream_state *dc_get_stream_at_index(struct dc *dc, uint8_t i) { - if (i < dc->current_context->stream_count) - return dc->current_context->streams[i]; + if (i < dc->current_state->stream_count) + return dc->current_state->streams[i]; return NULL; } @@ -1634,11 +1634,11 @@ void dc_set_power_state( */ /* Preserve refcount */ - ref_count = dc->current_context->ref_count; - dc_resource_validate_ctx_destruct(dc->current_context); - memset(dc->current_context, 0, - sizeof(*dc->current_context)); - dc->current_context->ref_count = ref_count; + ref_count = dc->current_state->ref_count; + dc_resource_validate_ctx_destruct(dc->current_state); + memset(dc->current_state, 0, + sizeof(*dc->current_state)); + dc->current_state->ref_count = ref_count; break; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c index d74eed8f9b96..6acee5426e4b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c @@ -329,7 +329,7 @@ void context_timing_trace( void context_clock_trace( struct dc *dc, - struct validate_context *context) + struct dc_state *context) { #if defined(CONFIG_DRM_AMD_DC_DCN1_0) struct dc *core_dc = dc; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 0bdd41ca8799..65e12614d96c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1819,14 +1819,14 @@ bool dc_link_set_backlight_level(const struct dc_link *link, uint32_t level, if (dc_is_embedded_signal(link->connector_signal)) { if (stream != NULL) { for (i = 0; i < MAX_PIPES; i++) { - if (core_dc->current_context->res_ctx. + if (core_dc->current_state->res_ctx. pipe_ctx[i].stream == stream) /* DMCU -1 for all controller id values, * therefore +1 here */ controller_id = - core_dc->current_context-> + core_dc->current_state-> res_ctx.pipe_ctx[i].stream_res.tg->inst + 1; } @@ -1926,13 +1926,13 @@ bool dc_link_setup_psr(struct dc_link *link, psr_context->engineId = link->link_enc->preferred_engine; for (i = 0; i < MAX_PIPES; i++) { - if (core_dc->current_context->res_ctx.pipe_ctx[i].stream + if (core_dc->current_state->res_ctx.pipe_ctx[i].stream == stream) { /* dmcu -1 for all controller id values, * therefore +1 here */ psr_context->controllerId = - core_dc->current_context->res_ctx. + core_dc->current_state->res_ctx. pipe_ctx[i].stream_res.tg->inst + 1; break; } 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 446e2933474c..5f2b52e41427 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 @@ -2406,7 +2406,7 @@ bool dc_link_dp_set_test_pattern( const unsigned char *p_custom_pattern, unsigned int cust_pattern_size) { - struct pipe_ctx *pipes = link->dc->current_context->res_ctx.pipe_ctx; + struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx; struct pipe_ctx *pipe_ctx = &pipes[0]; unsigned int lane; unsigned int i; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 23d8b614e0fd..3427fb5b7e30 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -62,7 +62,7 @@ void dp_enable_link_phy( struct link_encoder *link_enc = link->link_enc; struct pipe_ctx *pipes = - link->dc->current_context->res_ctx.pipe_ctx; + link->dc->current_state->res_ctx.pipe_ctx; struct clock_source *dp_cs = link->dc->res_pool->dp_clock_source; unsigned int i; @@ -262,7 +262,7 @@ void dp_retrain_link_dp_test(struct dc_link *link, bool skip_video_pattern) { struct pipe_ctx *pipes = - &link->dc->current_context->res_ctx.pipe_ctx[0]; + &link->dc->current_state->res_ctx.pipe_ctx[0]; unsigned int i; for (i = 0; i < MAX_PIPES; i++) { diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 9eb8d48bc889..727afeaa3830 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -893,7 +893,7 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) enum dc_status resource_build_scaling_params_for_context( const struct dc *dc, - struct validate_context *context) + struct dc_state *context) { int i; @@ -971,7 +971,7 @@ static struct pipe_ctx *resource_get_tail_pipe_for_stream( * that has no surface attached yet */ static struct pipe_ctx *acquire_free_pipe_for_stream( - struct validate_context *context, + struct dc_state *context, const struct resource_pool *pool, struct dc_stream_state *stream) { @@ -1048,7 +1048,7 @@ bool dc_add_plane_to_context( const struct dc *dc, struct dc_stream_state *stream, struct dc_plane_state *plane_state, - struct validate_context *context) + struct dc_state *context) { int i; struct resource_pool *pool = dc->res_pool; @@ -1124,7 +1124,7 @@ bool dc_remove_plane_from_context( const struct dc *dc, struct dc_stream_state *stream, struct dc_plane_state *plane_state, - struct validate_context *context) + struct dc_state *context) { int i; struct dc_stream_status *stream_status = NULL; @@ -1199,7 +1199,7 @@ bool dc_remove_plane_from_context( bool dc_rem_all_planes_for_stream( const struct dc *dc, struct dc_stream_state *stream, - struct validate_context *context) + struct dc_state *context) { int i, old_plane_count; struct dc_stream_status *stream_status = NULL; @@ -1233,7 +1233,7 @@ static bool add_all_planes_for_stream( struct dc_stream_state *stream, const struct dc_validation_set set[], int set_count, - struct validate_context *context) + struct dc_state *context) { int i, j; @@ -1258,7 +1258,7 @@ bool dc_add_all_planes_for_stream( struct dc_stream_state *stream, struct dc_plane_state * const *plane_states, int plane_count, - struct validate_context *context) + struct dc_state *context) { struct dc_validation_set set; int i; @@ -1434,7 +1434,7 @@ static struct audio *find_first_free_audio( } bool resource_is_stream_unchanged( - struct validate_context *old_context, struct dc_stream_state *stream) + struct dc_state *old_context, struct dc_stream_state *stream) { int i; @@ -1450,7 +1450,7 @@ bool resource_is_stream_unchanged( bool dc_add_stream_to_ctx( struct dc *dc, - struct validate_context *new_ctx, + struct dc_state *new_ctx, struct dc_stream_state *stream) { struct dc_context *dc_ctx = dc->ctx; @@ -1474,7 +1474,7 @@ bool dc_add_stream_to_ctx( bool dc_remove_stream_from_ctx( struct dc *dc, - struct validate_context *new_ctx, + struct dc_state *new_ctx, struct dc_stream_state *stream) { int i; @@ -1553,7 +1553,7 @@ static void copy_pipe_ctx( static struct dc_stream_state *find_pll_sharable_stream( struct dc_stream_state *stream_needs_pll, - struct validate_context *context) + struct dc_state *context) { int i; @@ -1615,7 +1615,7 @@ static void calculate_phy_pix_clks(struct dc_stream_state *stream) enum dc_status resource_map_pool_resources( const struct dc *dc, - struct validate_context *context, + struct dc_state *context, struct dc_stream_state *stream) { const struct resource_pool *pool = dc->res_pool; @@ -1689,7 +1689,7 @@ enum dc_status resource_map_pool_resources( /* first stream in the context is used to populate the rest */ void validate_guaranteed_copy_streams( - struct validate_context *context, + struct dc_state *context, int max_streams) { int i; @@ -1709,14 +1709,14 @@ void validate_guaranteed_copy_streams( void dc_resource_validate_ctx_copy_construct_current( const struct dc *dc, - struct validate_context *dst_ctx) + struct dc_state *dst_ctx) { - dc_resource_validate_ctx_copy_construct(dc->current_context, dst_ctx); + dc_resource_validate_ctx_copy_construct(dc->current_state, dst_ctx); } bool dc_validate_global_state( struct dc *dc, - struct validate_context *new_ctx) + struct dc_state *new_ctx) { enum dc_status result = DC_ERROR_UNEXPECTED; int i, j; @@ -2413,7 +2413,7 @@ static void set_vsc_info_packet( /*TODO: stereo 3D support and extend pixel encoding colorimetry*/ } -void dc_resource_validate_ctx_destruct(struct validate_context *context) +void dc_resource_validate_ctx_destruct(struct dc_state *context) { int i, j; @@ -2433,8 +2433,8 @@ void dc_resource_validate_ctx_destruct(struct validate_context *context) * by the src_ctx */ void dc_resource_validate_ctx_copy_construct( - const struct validate_context *src_ctx, - struct validate_context *dst_ctx) + const struct dc_state *src_ctx, + struct dc_state *dst_ctx) { int i, j; atomic_t ref_count = dst_ctx->ref_count; @@ -2518,7 +2518,7 @@ void resource_build_info_frame(struct pipe_ctx *pipe_ctx) enum dc_status resource_map_clock_resources( const struct dc *dc, - struct validate_context *context, + struct dc_state *context, struct dc_stream_state *stream) { /* acquire new resources */ diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 0e7cc293184e..a421779093d9 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -169,10 +169,9 @@ struct dc_stream_status *dc_stream_get_status( uint8_t i; struct dc *dc = stream->ctx->dc; - for (i = 0; i < dc->current_context->stream_count; i++) { - if (stream == dc->current_context->streams[i]) { - return &dc->current_context->stream_status[i]; - } + for (i = 0; i < dc->current_state->stream_count; i++) { + if (stream == dc->current_state->streams[i]) + return &dc->current_state->stream_status[i]; } return NULL; @@ -199,7 +198,7 @@ bool dc_stream_set_cursor_attributes( } core_dc = stream->ctx->dc; - res_ctx = &core_dc->current_context->res_ctx; + res_ctx = &core_dc->current_state->res_ctx; for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; @@ -235,7 +234,7 @@ bool dc_stream_set_cursor_position( } core_dc = stream->ctx->dc; - res_ctx = &core_dc->current_context->res_ctx; + res_ctx = &core_dc->current_state->res_ctx; for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; @@ -271,7 +270,7 @@ uint32_t dc_stream_get_vblank_counter(const struct dc_stream_state *stream) uint8_t i; struct dc *core_dc = stream->ctx->dc; struct resource_context *res_ctx = - &core_dc->current_context->res_ctx; + &core_dc->current_state->res_ctx; for (i = 0; i < MAX_PIPES; i++) { struct timing_generator *tg = res_ctx->pipe_ctx[i].stream_res.tg; @@ -295,7 +294,7 @@ bool dc_stream_get_scanoutpos(const struct dc_stream_state *stream, bool ret = false; struct dc *core_dc = stream->ctx->dc; struct resource_context *res_ctx = - &core_dc->current_context->res_ctx; + &core_dc->current_state->res_ctx; for (i = 0; i < MAX_PIPES; i++) { struct timing_generator *tg = res_ctx->pipe_ctx[i].stream_res.tg; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index 0b6410fb2f3e..e96f63eed070 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -104,12 +104,12 @@ const struct dc_plane_status *dc_plane_get_status( plane_status = &plane_state->status; core_dc = plane_state->ctx->dc; - if (core_dc->current_context == NULL) + if (core_dc->current_state == NULL) return NULL; for (i = 0; i < core_dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = - &core_dc->current_context->res_ctx.pipe_ctx[i]; + &core_dc->current_state->res_ctx.pipe_ctx[i]; if (pipe_ctx->plane_state != plane_state) continue; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 55fc58102515..d1d5737398df 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -99,7 +99,7 @@ struct dc_static_screen_events { /* Forward declaration*/ struct dc; struct dc_plane_state; -struct validate_context; +struct dc_state; struct dc_cap_funcs { bool (*get_dcc_compression_cap)(const struct dc *dc, @@ -192,7 +192,7 @@ struct dc_debug { bool disable_psr; bool force_abm_enable; }; -struct validate_context; +struct dc_state; struct resource_pool; struct dce_hwseq; struct dc { @@ -208,7 +208,7 @@ struct dc { uint8_t link_count; struct dc_link *links[MAX_PIPES * 2]; - struct validate_context *current_context; + struct dc_state *current_state; struct resource_pool *res_pool; /* Display Engine Clock levels */ @@ -621,12 +621,12 @@ bool dc_stream_get_scanoutpos(const struct dc_stream_state *stream, bool dc_add_stream_to_ctx( struct dc *dc, - struct validate_context *new_ctx, + struct dc_state *new_ctx, struct dc_stream_state *stream); bool dc_remove_stream_from_ctx( struct dc *dc, - struct validate_context *new_ctx, + struct dc_state *new_ctx, struct dc_stream_state *stream); @@ -634,25 +634,25 @@ bool dc_add_plane_to_context( const struct dc *dc, struct dc_stream_state *stream, struct dc_plane_state *plane_state, - struct validate_context *context); + struct dc_state *context); bool dc_remove_plane_from_context( const struct dc *dc, struct dc_stream_state *stream, struct dc_plane_state *plane_state, - struct validate_context *context); + struct dc_state *context); bool dc_rem_all_planes_for_stream( const struct dc *dc, struct dc_stream_state *stream, - struct validate_context *context); + struct dc_state *context); bool dc_add_all_planes_for_stream( const struct dc *dc, struct dc_stream_state *stream, struct dc_plane_state * const *plane_states, int plane_count, - struct validate_context *context); + struct dc_state *context); /* * Structure to store surface/stream associations for validation @@ -669,7 +669,7 @@ bool dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state); bool dc_validate_global_state( struct dc *dc, - struct validate_context *new_ctx); + struct dc_state *new_ctx); /* * This function takes a stream and checks if it is guaranteed to be supported. @@ -680,14 +680,14 @@ bool dc_validate_global_state( */ void dc_resource_validate_ctx_copy_construct( - const struct validate_context *src_ctx, - struct validate_context *dst_ctx); + const struct dc_state *src_ctx, + struct dc_state *dst_ctx); void dc_resource_validate_ctx_copy_construct_current( const struct dc *dc, - struct validate_context *dst_ctx); + struct dc_state *dst_ctx); -void dc_resource_validate_ctx_destruct(struct validate_context *context); +void dc_resource_validate_ctx_destruct(struct dc_state *context); /* * TODO update to make it about validation sets @@ -698,7 +698,7 @@ void dc_resource_validate_ctx_destruct(struct validate_context *context); * Phy, Encoder, Timing Generator are programmed and enabled. * New streams are enabled with blank stream; no memory read. */ -bool dc_commit_context(struct dc *dc, struct validate_context *context); +bool dc_commit_state(struct dc *dc, struct dc_state *context); /* * Set up streams and links associated to drive sinks @@ -714,7 +714,7 @@ bool dc_commit_context(struct dc *dc, struct validate_context *context); */ bool dc_enable_stereo( struct dc *dc, - struct validate_context *context, + struct dc_state *context, struct dc_stream_state *streams[], uint8_t stream_count); @@ -737,9 +737,9 @@ enum surface_update_type dc_check_update_surfaces_for_stream( const struct dc_stream_status *stream_status); -struct validate_context *dc_create_state(void); -void dc_retain_validate_context(struct validate_context *context); -void dc_release_validate_context(struct validate_context *context); +struct dc_state *dc_create_state(void); +void dc_retain_state(struct dc_state *context); +void dc_release_state(struct dc_state *context); /******************************************************************************* * Link Interfaces diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index 0654fe34627c..d3b61b92ebec 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -609,7 +609,7 @@ static uint32_t dce110_get_pll_pixel_rate_in_hz( { uint32_t inst = pix_clk_params->controller_id - CONTROLLER_ID_D0; struct dc *dc_core = cs->ctx->dc; - struct validate_context *context = dc_core->current_context; + struct dc_state *context = dc_core->current_state; struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[inst]; /* This function need separate to different DCE version, before separate, just use pixel clock */ @@ -624,7 +624,7 @@ static uint32_t dce110_get_dp_pixel_rate_from_combo_phy_pll( { uint32_t inst = pix_clk_params->controller_id - CONTROLLER_ID_D0; struct dc *dc_core = cs->ctx->dc; - struct validate_context *context = dc_core->current_context; + struct dc_state *context = dc_core->current_state; struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[inst]; /* This function need separate to different DCE version, before separate, just use pixel clock */ diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c index b7e51c5ed1b1..492ea6069eb4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c @@ -107,7 +107,7 @@ static bool dce100_enable_display_power_gating( static void dce100_pplib_apply_display_requirements( struct dc *dc, - struct validate_context *context) + struct dc_state *context) { struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg; @@ -127,14 +127,14 @@ static void dce100_pplib_apply_display_requirements( void dce100_set_bandwidth( struct dc *dc, - struct validate_context *context, + struct dc_state *context, bool decrease_allowed) { - if (decrease_allowed || context->bw.dce.dispclk_khz > dc->current_context->bw.dce.dispclk_khz) { + if (decrease_allowed || context->bw.dce.dispclk_khz > dc->current_state->bw.dce.dispclk_khz) { dc->res_pool->display_clock->funcs->set_clock( dc->res_pool->display_clock, context->bw.dce.dispclk_khz * 115 / 100); - dc->current_context->bw.dce.dispclk_khz = context->bw.dce.dispclk_khz; + dc->current_state->bw.dce.dispclk_khz = context->bw.dce.dispclk_khz; } dce100_pplib_apply_display_requirements(dc, context); } diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h index c04aa15cd656..770b5bb1ff40 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h @@ -29,13 +29,13 @@ #include "core_types.h" struct dc; -struct validate_context; +struct dc_state; bool dce100_hw_sequencer_construct(struct dc *dc); void dce100_set_bandwidth( struct dc *dc, - struct validate_context *context, + struct dc_state *context, bool decrease_allowed); #endif /* __DC_HWSS_DCE100_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index c991610315b2..36d79175354c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -653,7 +653,7 @@ static void destruct(struct dce110_resource_pool *pool) static enum dc_status build_mapped_resource( const struct dc *dc, - struct validate_context *context, + struct dc_state *context, struct dc_stream_state *stream) { enum dc_status status = DC_OK; @@ -674,7 +674,7 @@ static enum dc_status build_mapped_resource( bool dce100_validate_bandwidth( struct dc *dc, - struct validate_context *context) + struct dc_state *context) { /* TODO implement when needed but for now hardcode max value*/ context->bw.dce.dispclk_khz = 681000; @@ -684,7 +684,7 @@ bool dce100_validate_bandwidth( } static bool dce100_validate_surface_sets( - struct validate_context *context) + struct dc_state *context) { int i; @@ -705,7 +705,7 @@ static bool dce100_validate_surface_sets( enum dc_status dce100_validate_global( struct dc *dc, - struct validate_context *context) + struct dc_state *context) { if (!dce100_validate_surface_sets(context)) return DC_FAIL_SURFACE_VALIDATE; @@ -716,7 +716,7 @@ enum dc_status dce100_validate_global( enum dc_status dce100_validate_guaranteed( struct dc *dc, struct dc_stream_state *dc_stream, - struct validate_context *context) + struct dc_state *context) { enum dc_status result = DC_ERROR_UNEXPECTED; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 3502faa1458f..1c6e2006f2a1 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -976,11 +976,11 @@ static void program_scaler(const struct dc *dc, static enum dc_status dce110_prog_pixclk_crtc_otg( struct pipe_ctx *pipe_ctx, - struct validate_context *context, + struct dc_state *context, struct dc *dc) { struct dc_stream_state *stream = pipe_ctx->stream; - struct pipe_ctx *pipe_ctx_old = &dc->current_context->res_ctx. + struct pipe_ctx *pipe_ctx_old = &dc->current_state->res_ctx. pipe_ctx[pipe_ctx->pipe_idx]; struct tg_color black_color = {0}; @@ -1032,11 +1032,11 @@ static enum dc_status dce110_prog_pixclk_crtc_otg( static enum dc_status apply_single_controller_ctx_to_hw( struct pipe_ctx *pipe_ctx, - struct validate_context *context, + struct dc_state *context, struct dc *dc) { struct dc_stream_state *stream = pipe_ctx->stream; - struct pipe_ctx *pipe_ctx_old = &dc->current_context->res_ctx. + struct pipe_ctx *pipe_ctx_old = &dc->current_state->res_ctx. pipe_ctx[pipe_ctx->pipe_idx]; /* */ @@ -1257,7 +1257,7 @@ static uint32_t compute_pstate_blackout_duration( void dce110_set_displaymarks( const struct dc *dc, - struct validate_context *context) + struct dc_state *context) { uint8_t i, num_pipes; unsigned int underlay_idx = dc->res_pool->underlay_pipe_index; @@ -1415,7 +1415,7 @@ static void set_static_screen_control(struct pipe_ctx **pipe_ctx, */ static uint32_t get_max_pixel_clock_for_all_paths( struct dc *dc, - struct validate_context *context, + struct dc_state *context, bool pre_mode_set) { uint32_t max_pix_clk = 0; @@ -1456,7 +1456,7 @@ static uint32_t get_max_pixel_clock_for_all_paths( */ static void apply_min_clocks( struct dc *dc, - struct validate_context *context, + struct dc_state *context, enum dm_pp_clocks_state *clocks_state, bool pre_mode_set) { @@ -1545,7 +1545,7 @@ static void apply_min_clocks( * Check if FBC can be enabled */ static enum dc_status validate_fbc(struct dc *dc, - struct validate_context *context) + struct dc_state *context) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[0]; @@ -1575,7 +1575,7 @@ static enum dc_status validate_fbc(struct dc *dc, * Enable FBC */ static enum dc_status enable_fbc(struct dc *dc, - struct validate_context *context) + struct dc_state *context) { enum dc_status status = validate_fbc(dc, context); @@ -1604,14 +1604,14 @@ static enum dc_status enable_fbc(struct dc *dc, static enum dc_status apply_ctx_to_hw_fpga( struct dc *dc, - struct validate_context *context) + struct dc_state *context) { enum dc_status status = DC_ERROR_UNEXPECTED; int i; for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe_ctx_old = - &dc->current_context->res_ctx.pipe_ctx[i]; + &dc->current_state->res_ctx.pipe_ctx[i]; struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; if (pipe_ctx->stream == NULL) @@ -1634,7 +1634,7 @@ static enum dc_status apply_ctx_to_hw_fpga( static void dce110_reset_hw_ctx_wrap( struct dc *dc, - struct validate_context *context) + struct dc_state *context) { int i; @@ -1642,7 +1642,7 @@ static void dce110_reset_hw_ctx_wrap( /* look up the targets that have been removed since last commit */ for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe_ctx_old = - &dc->current_context->res_ctx.pipe_ctx[i]; + &dc->current_state->res_ctx.pipe_ctx[i]; struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; /* Note: We need to disable output if clock sources change, @@ -1664,9 +1664,9 @@ static void dce110_reset_hw_ctx_wrap( } pipe_ctx_old->stream_res.tg->funcs->disable_crtc(pipe_ctx_old->stream_res.tg); pipe_ctx_old->plane_res.mi->funcs->free_mem_input( - pipe_ctx_old->plane_res.mi, dc->current_context->stream_count); + pipe_ctx_old->plane_res.mi, dc->current_state->stream_count); resource_unreference_clock_source( - &dc->current_context->res_ctx, dc->res_pool, + &dc->current_state->res_ctx, dc->res_pool, &pipe_ctx_old->clock_source); dc->hwss.power_down_front_end(dc, pipe_ctx_old->pipe_idx); @@ -1679,7 +1679,7 @@ static void dce110_reset_hw_ctx_wrap( enum dc_status dce110_apply_ctx_to_hw( struct dc *dc, - struct validate_context *context) + struct dc_state *context) { struct dc_bios *dcb = dc->ctx->dc_bios; enum dc_status status; @@ -1705,7 +1705,7 @@ enum dc_status dce110_apply_ctx_to_hw( /* below is for real asic only */ for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx_old = - &dc->current_context->res_ctx.pipe_ctx[i]; + &dc->current_state->res_ctx.pipe_ctx[i]; struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; if (pipe_ctx->stream == NULL || pipe_ctx->top_pipe) @@ -1735,31 +1735,31 @@ enum dc_status dce110_apply_ctx_to_hw( #if defined(CONFIG_DRM_AMD_DC_DCN1_0) if (dc->ctx->dce_version >= DCN_VERSION_1_0) { if (context->bw.dcn.calc_clk.fclk_khz - > dc->current_context->bw.dcn.cur_clk.fclk_khz) { + > dc->current_state->bw.dcn.cur_clk.fclk_khz) { struct dm_pp_clock_for_voltage_req clock; clock.clk_type = DM_PP_CLOCK_TYPE_FCLK; clock.clocks_in_khz = context->bw.dcn.calc_clk.fclk_khz; dm_pp_apply_clock_for_voltage_request(dc->ctx, &clock); - dc->current_context->bw.dcn.cur_clk.fclk_khz = clock.clocks_in_khz; + dc->current_state->bw.dcn.cur_clk.fclk_khz = clock.clocks_in_khz; context->bw.dcn.cur_clk.fclk_khz = clock.clocks_in_khz; } if (context->bw.dcn.calc_clk.dcfclk_khz - > dc->current_context->bw.dcn.cur_clk.dcfclk_khz) { + > dc->current_state->bw.dcn.cur_clk.dcfclk_khz) { struct dm_pp_clock_for_voltage_req clock; clock.clk_type = DM_PP_CLOCK_TYPE_DCFCLK; clock.clocks_in_khz = context->bw.dcn.calc_clk.dcfclk_khz; dm_pp_apply_clock_for_voltage_request(dc->ctx, &clock); - dc->current_context->bw.dcn.cur_clk.dcfclk_khz = clock.clocks_in_khz; + dc->current_state->bw.dcn.cur_clk.dcfclk_khz = clock.clocks_in_khz; context->bw.dcn.cur_clk.dcfclk_khz = clock.clocks_in_khz; } if (context->bw.dcn.calc_clk.dispclk_khz - > dc->current_context->bw.dcn.cur_clk.dispclk_khz) { + > dc->current_state->bw.dcn.cur_clk.dispclk_khz) { dc->res_pool->display_clock->funcs->set_clock( dc->res_pool->display_clock, context->bw.dcn.calc_clk.dispclk_khz); - dc->current_context->bw.dcn.cur_clk.dispclk_khz = + dc->current_state->bw.dcn.cur_clk.dispclk_khz = context->bw.dcn.calc_clk.dispclk_khz; context->bw.dcn.cur_clk.dispclk_khz = context->bw.dcn.calc_clk.dispclk_khz; @@ -1767,7 +1767,7 @@ enum dc_status dce110_apply_ctx_to_hw( } else #endif if (context->bw.dce.dispclk_khz - > dc->current_context->bw.dce.dispclk_khz) { + > dc->current_state->bw.dce.dispclk_khz) { dc->res_pool->display_clock->funcs->set_clock( dc->res_pool->display_clock, context->bw.dce.dispclk_khz * 115 / 100); @@ -1848,7 +1848,7 @@ enum dc_status dce110_apply_ctx_to_hw( for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx_old = - &dc->current_context->res_ctx.pipe_ctx[i]; + &dc->current_state->res_ctx.pipe_ctx[i]; struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; if (pipe_ctx->stream == NULL) @@ -2327,7 +2327,7 @@ static void init_hw(struct dc *dc) } void dce110_fill_display_configs( - const struct validate_context *context, + const struct dc_state *context, struct dm_pp_display_configuration *pp_display_cfg) { int j; @@ -2375,7 +2375,7 @@ void dce110_fill_display_configs( pp_display_cfg->display_count = num_cfgs; } -uint32_t dce110_get_min_vblank_time_us(const struct validate_context *context) +uint32_t dce110_get_min_vblank_time_us(const struct dc_state *context) { uint8_t j; uint32_t min_vertical_blank_time = -1; @@ -2427,7 +2427,7 @@ static int determine_sclk_from_bounding_box( static void pplib_apply_display_requirements( struct dc *dc, - struct validate_context *context) + struct dc_state *context) { struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg; @@ -2481,16 +2481,16 @@ static void pplib_apply_display_requirements( static void dce110_set_bandwidth( struct dc *dc, - struct validate_context *context, + struct dc_state *context, bool decrease_allowed) { dce110_set_displaymarks(dc, context); - if (decrease_allowed || context->bw.dce.dispclk_khz > dc->current_context->bw.dce.dispclk_khz) { + if (decrease_allowed || context->bw.dce.dispclk_khz > dc->current_state->bw.dce.dispclk_khz) { dc->res_pool->display_clock->funcs->set_clock( dc->res_pool->display_clock, context->bw.dce.dispclk_khz * 115 / 100); - dc->current_context->bw.dce.dispclk_khz = context->bw.dce.dispclk_khz; + dc->current_state->bw.dce.dispclk_khz = context->bw.dce.dispclk_khz; } pplib_apply_display_requirements(dc, context); @@ -2508,8 +2508,8 @@ static void dce110_program_front_end_for_pipe( memset(&tbl_entry, 0, sizeof(tbl_entry)); - if (dc->current_context) - old_pipe = &dc->current_context->res_ctx.pipe_ctx[pipe_ctx->pipe_idx]; + if (dc->current_state) + old_pipe = &dc->current_state->res_ctx.pipe_ctx[pipe_ctx->pipe_idx]; memset(&adjust, 0, sizeof(adjust)); adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS; @@ -2627,7 +2627,7 @@ static void dce110_apply_ctx_for_surface( struct dc *dc, const struct dc_stream_state *stream, int num_planes, - struct validate_context *context) + struct dc_state *context) { int i, be_idx; @@ -2657,7 +2657,7 @@ static void dce110_apply_ctx_for_surface( static void dce110_power_down_fe(struct dc *dc, int fe_idx) { /* Do not power down fe when stream is active on dce*/ - if (dc->current_context->res_ctx.pipe_ctx[fe_idx].stream) + if (dc->current_state->res_ctx.pipe_ctx[fe_idx].stream) return; dc->hwss.enable_display_power_gating( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h index ac418fd83894..baa20c1f17ad 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h @@ -30,20 +30,20 @@ #define GAMMA_HW_POINTS_NUM 256 struct dc; -struct validate_context; +struct dc_state; struct dm_pp_display_configuration; bool dce110_hw_sequencer_construct(struct dc *dc); enum dc_status dce110_apply_ctx_to_hw( struct dc *dc, - struct validate_context *context); + struct dc_state *context); -void dce110_set_display_clock(struct validate_context *context); +void dce110_set_display_clock(struct dc_state *context); void dce110_set_displaymarks( const struct dc *dc, - struct validate_context *context); + struct dc_state *context); void dce110_enable_stream(struct pipe_ctx *pipe_ctx); @@ -62,10 +62,10 @@ void dce110_power_down(struct dc *dc); void dce110_update_pending_status(struct pipe_ctx *pipe_ctx); void dce110_fill_display_configs( - const struct validate_context *context, + const struct dc_state *context, struct dm_pp_display_configuration *pp_display_cfg); -uint32_t dce110_get_min_vblank_time_us(const struct validate_context *context); +uint32_t dce110_get_min_vblank_time_us(const struct dc_state *context); void dp_receiver_power_ctrl(struct dc_link *link, bool on); #endif /* __DC_HWSS_DCE110_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 18c67f89e9b5..94b6eb83e01e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -773,7 +773,7 @@ static bool is_surface_pixel_format_supported(struct pipe_ctx *pipe_ctx, unsigne static enum dc_status build_mapped_resource( const struct dc *dc, - struct validate_context *context, + struct dc_state *context, struct dc_stream_state *stream) { enum dc_status status = DC_OK; @@ -800,7 +800,7 @@ static enum dc_status build_mapped_resource( static bool dce110_validate_bandwidth( struct dc *dc, - struct validate_context *context) + struct dc_state *context) { bool result = false; @@ -826,7 +826,7 @@ static bool dce110_validate_bandwidth( context->streams[0]->timing.v_addressable, context->streams[0]->timing.pix_clk_khz); - if (memcmp(&dc->current_context->bw.dce, + if (memcmp(&dc->current_state->bw.dce, &context->bw.dce, sizeof(context->bw.dce))) { struct log_entry log_entry; dm_logger_open( @@ -880,7 +880,7 @@ static bool dce110_validate_bandwidth( } static bool dce110_validate_surface_sets( - struct validate_context *context) + struct dc_state *context) { int i; @@ -913,7 +913,7 @@ static bool dce110_validate_surface_sets( enum dc_status dce110_validate_global( struct dc *dc, - struct validate_context *context) + struct dc_state *context) { if (!dce110_validate_surface_sets(context)) return DC_FAIL_SURFACE_VALIDATE; @@ -924,7 +924,7 @@ enum dc_status dce110_validate_global( static enum dc_status dce110_validate_guaranteed( struct dc *dc, struct dc_stream_state *dc_stream, - struct validate_context *context) + struct dc_state *context) { enum dc_status result = DC_ERROR_UNEXPECTED; @@ -954,7 +954,7 @@ static enum dc_status dce110_validate_guaranteed( } static struct pipe_ctx *dce110_acquire_underlay( - struct validate_context *context, + struct dc_state *context, const struct resource_pool *pool, struct dc_stream_state *stream) { @@ -976,7 +976,7 @@ static struct pipe_ctx *dce110_acquire_underlay( pipe_ctx->stream = stream; - if (!dc->current_context->res_ctx.pipe_ctx[underlay_idx].stream) { + if (!dc->current_state->res_ctx.pipe_ctx[underlay_idx].stream) { struct tg_color black_color = {0}; struct dc_bios *dcb = dc->ctx->dc_bios; diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index d5a8ee69171d..de6f71d8a89b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -724,7 +724,7 @@ static struct clock_source *find_matching_pll( static enum dc_status build_mapped_resource( const struct dc *dc, - struct validate_context *context, + struct dc_state *context, struct dc_stream_state *stream) { enum dc_status status = DC_OK; @@ -745,7 +745,7 @@ static enum dc_status build_mapped_resource( bool dce112_validate_bandwidth( struct dc *dc, - struct validate_context *context) + struct dc_state *context) { bool result = false; @@ -768,7 +768,7 @@ bool dce112_validate_bandwidth( "%s: Bandwidth validation failed!", __func__); - if (memcmp(&dc->current_context->bw.dce, + if (memcmp(&dc->current_state->bw.dce, &context->bw.dce, sizeof(context->bw.dce))) { struct log_entry log_entry; dm_logger_open( @@ -823,7 +823,7 @@ bool dce112_validate_bandwidth( enum dc_status resource_map_phy_clock_resources( const struct dc *dc, - struct validate_context *context, + struct dc_state *context, struct dc_stream_state *stream) { @@ -855,7 +855,7 @@ enum dc_status resource_map_phy_clock_resources( } static bool dce112_validate_surface_sets( - struct validate_context *context) + struct dc_state *context) { int i; @@ -876,7 +876,7 @@ static bool dce112_validate_surface_sets( enum dc_status dce112_add_stream_to_ctx( struct dc *dc, - struct validate_context *new_ctx, + struct dc_state *new_ctx, struct dc_stream_state *dc_stream) { enum dc_status result = DC_ERROR_UNEXPECTED; @@ -896,7 +896,7 @@ enum dc_status dce112_add_stream_to_ctx( enum dc_status dce112_validate_guaranteed( struct dc *dc, struct dc_stream_state *stream, - struct validate_context *context) + struct dc_state *context) { enum dc_status result = DC_ERROR_UNEXPECTED; @@ -927,7 +927,7 @@ enum dc_status dce112_validate_guaranteed( enum dc_status dce112_validate_global( struct dc *dc, - struct validate_context *context) + struct dc_state *context) { if (!dce112_validate_surface_sets(context)) return DC_FAIL_SURFACE_VALIDATE; diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h index f1834bfe3d1e..d5c19d34eb0a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h @@ -39,21 +39,21 @@ enum dc_status dce112_validate_with_context( struct dc *dc, const struct dc_validation_set set[], int set_count, - struct validate_context *context, - struct validate_context *old_context); + struct dc_state *context, + struct dc_state *old_context); enum dc_status dce112_validate_guaranteed( struct dc *dc, struct dc_stream_state *dc_stream, - struct validate_context *context); + struct dc_state *context); bool dce112_validate_bandwidth( struct dc *dc, - struct validate_context *context); + struct dc_state *context); enum dc_status dce112_add_stream_to_ctx( struct dc *dc, - struct validate_context *new_ctx, + struct dc_state *new_ctx, struct dc_stream_state *dc_stream); diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 945ff7ee6cd9..316080767a21 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -685,7 +685,7 @@ static void destruct(struct dce110_resource_pool *pool) static enum dc_status build_mapped_resource( const struct dc *dc, - struct validate_context *context, + struct dc_state *context, struct dc_stream_state *stream) { enum dc_status status = DC_OK; @@ -706,7 +706,7 @@ static enum dc_status build_mapped_resource( bool dce80_validate_bandwidth( struct dc *dc, - struct validate_context *context) + struct dc_state *context) { /* TODO implement when needed but for now hardcode max value*/ context->bw.dce.dispclk_khz = 681000; @@ -716,7 +716,7 @@ bool dce80_validate_bandwidth( } static bool dce80_validate_surface_sets( - struct validate_context *context) + struct dc_state *context) { int i; @@ -737,7 +737,7 @@ static bool dce80_validate_surface_sets( enum dc_status dce80_validate_global( struct dc *dc, - struct validate_context *context) + struct dc_state *context) { if (!dce80_validate_surface_sets(context)) return DC_FAIL_SURFACE_VALIDATE; @@ -748,7 +748,7 @@ enum dc_status dce80_validate_global( enum dc_status dce80_validate_guaranteed( struct dc *dc, struct dc_stream_state *dc_stream, - struct validate_context *context) + struct dc_state *context) { enum dc_status result = DC_ERROR_UNEXPECTED; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 9c54cae28997..71ff1cedbdf4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -793,7 +793,7 @@ static void undo_DEGVIDCN10_253_wa(struct dc *dc) static void ready_shared_resources(struct dc *dc) { - if (dc->current_context->stream_count == 0 && + if (dc->current_state->stream_count == 0 && !dc->debug.disable_stutter) undo_DEGVIDCN10_253_wa(dc); } @@ -815,7 +815,7 @@ static void apply_DEGVIDCN10_253_wa(struct dc *dc) static void optimize_shared_resources(struct dc *dc) { - if (dc->current_context->stream_count == 0 && + if (dc->current_state->stream_count == 0 && !dc->debug.disable_stutter) apply_DEGVIDCN10_253_wa(dc); } @@ -918,7 +918,7 @@ static void dcn10_init_hw(struct dc *dc) static enum dc_status dcn10_prog_pixclk_crtc_otg( struct pipe_ctx *pipe_ctx, - struct validate_context *context, + struct dc_state *context, struct dc *dc) { struct dc_stream_state *stream = pipe_ctx->stream; @@ -1008,7 +1008,7 @@ static enum dc_status dcn10_prog_pixclk_crtc_otg( static void reset_back_end_for_pipe( struct dc *dc, struct pipe_ctx *pipe_ctx, - struct validate_context *context) + struct dc_state *context) { int i; @@ -1040,7 +1040,7 @@ static void reset_back_end_for_pipe( &pipe_ctx->clock_source); for (i = 0; i < dc->res_pool->pipe_count; i++) - if (&dc->current_context->res_ctx.pipe_ctx[i] == pipe_ctx) + if (&dc->current_state->res_ctx.pipe_ctx[i] == pipe_ctx) break; if (i == dc->res_pool->pipe_count) @@ -1206,14 +1206,14 @@ static void dcn10_power_down_fe(struct dc *dc, int fe_idx) static void reset_hw_ctx_wrap( struct dc *dc, - struct validate_context *context) + struct dc_state *context) { int i; /* Reset Front End*/ /* Lock*/ for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *cur_pipe_ctx = &dc->current_context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *cur_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; struct timing_generator *tg = cur_pipe_ctx->stream_res.tg; if (cur_pipe_ctx->stream) @@ -1222,7 +1222,7 @@ static void reset_hw_ctx_wrap( /* Disconnect*/ for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) { struct pipe_ctx *pipe_ctx_old = - &dc->current_context->res_ctx.pipe_ctx[i]; + &dc->current_state->res_ctx.pipe_ctx[i]; struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; if (!pipe_ctx->stream || @@ -1234,7 +1234,7 @@ static void reset_hw_ctx_wrap( } /* Unlock*/ for (i = dc->res_pool->pipe_count - 1; i >= 0; i--) { - struct pipe_ctx *cur_pipe_ctx = &dc->current_context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *cur_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; struct timing_generator *tg = cur_pipe_ctx->stream_res.tg; if (cur_pipe_ctx->stream) @@ -1244,7 +1244,7 @@ static void reset_hw_ctx_wrap( /* Disable and Powerdown*/ for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) { struct pipe_ctx *pipe_ctx_old = - &dc->current_context->res_ctx.pipe_ctx[i]; + &dc->current_state->res_ctx.pipe_ctx[i]; struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; /*if (!pipe_ctx_old->stream) @@ -1263,7 +1263,7 @@ static void reset_hw_ctx_wrap( /* Reset Back End*/ for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) { struct pipe_ctx *pipe_ctx_old = - &dc->current_context->res_ctx.pipe_ctx[i]; + &dc->current_state->res_ctx.pipe_ctx[i]; struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; if (!pipe_ctx_old->stream) @@ -1271,7 +1271,7 @@ static void reset_hw_ctx_wrap( if (!pipe_ctx->stream || pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) - reset_back_end_for_pipe(dc, pipe_ctx_old, dc->current_context); + reset_back_end_for_pipe(dc, pipe_ctx_old, dc->current_state); } } @@ -1943,7 +1943,7 @@ static void print_rq_dlg_ttu( static void dcn10_power_on_fe( struct dc *dc, struct pipe_ctx *pipe_ctx, - struct validate_context *context) + struct dc_state *context) { struct dc_plane_state *plane_state = pipe_ctx->plane_state; struct dce_hwseq *hws = dc->hwseq; @@ -2244,7 +2244,7 @@ static void dcn10_program_pte_vm(struct mem_input *mem_input, static void update_dchubp_dpp( struct dc *dc, struct pipe_ctx *pipe_ctx, - struct validate_context *context) + struct dc_state *context) { struct dce_hwseq *hws = dc->hwseq; struct mem_input *mi = pipe_ctx->plane_res.mi; @@ -2263,7 +2263,7 @@ static void update_dchubp_dpp( pipe_ctx->pipe_idx, pipe_ctx->stream_res.pix_clk_params.requested_pix_clk, context->bw.dcn.calc_clk.dppclk_div); - dc->current_context->bw.dcn.cur_clk.dppclk_div = + dc->current_state->bw.dcn.cur_clk.dppclk_div = context->bw.dcn.calc_clk.dppclk_div; context->bw.dcn.cur_clk.dppclk_div = context->bw.dcn.calc_clk.dppclk_div; @@ -2350,7 +2350,7 @@ static void update_dchubp_dpp( static void program_all_pipe_in_tree( struct dc *dc, struct pipe_ctx *pipe_ctx, - struct validate_context *context) + struct dc_state *context) { unsigned int ref_clk_mhz = dc->res_pool->ref_clock_inKhz/1000; @@ -2408,7 +2408,7 @@ static void program_all_pipe_in_tree( static void dcn10_pplib_apply_display_requirements( struct dc *dc, - struct validate_context *context) + struct dc_state *context) { struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg; @@ -2437,7 +2437,7 @@ static void dcn10_apply_ctx_for_surface( struct dc *dc, const struct dc_stream_state *stream, int num_planes, - struct validate_context *context) + struct dc_state *context) { int i, be_idx; @@ -2457,7 +2457,7 @@ static void dcn10_apply_ctx_for_surface( if (num_planes == 0) { for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) { struct pipe_ctx *old_pipe_ctx = - &dc->current_context->res_ctx.pipe_ctx[i]; + &dc->current_state->res_ctx.pipe_ctx[i]; if (old_pipe_ctx->stream_res.tg && old_pipe_ctx->stream_res.tg->inst == be_idx) { old_pipe_ctx->stream_res.tg->funcs->set_blank(old_pipe_ctx->stream_res.tg, true); @@ -2471,7 +2471,7 @@ static void dcn10_apply_ctx_for_surface( for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; struct pipe_ctx *old_pipe_ctx = - &dc->current_context->res_ctx.pipe_ctx[i]; + &dc->current_state->res_ctx.pipe_ctx[i]; if (!pipe_ctx->plane_state && !old_pipe_ctx->plane_state) continue; @@ -2591,7 +2591,7 @@ static void dcn10_apply_ctx_for_surface( static void dcn10_set_bandwidth( struct dc *dc, - struct validate_context *context, + struct dc_state *context, bool decrease_allowed) { struct pp_smu_display_requirement_rv *smu_req_cur = @@ -2607,25 +2607,25 @@ static void dcn10_set_bandwidth( return; if (decrease_allowed || context->bw.dcn.calc_clk.dispclk_khz - > dc->current_context->bw.dcn.cur_clk.dispclk_khz) { + > dc->current_state->bw.dcn.cur_clk.dispclk_khz) { dc->res_pool->display_clock->funcs->set_clock( dc->res_pool->display_clock, context->bw.dcn.calc_clk.dispclk_khz); - dc->current_context->bw.dcn.cur_clk.dispclk_khz = + dc->current_state->bw.dcn.cur_clk.dispclk_khz = context->bw.dcn.calc_clk.dispclk_khz; } if (decrease_allowed || context->bw.dcn.calc_clk.dcfclk_khz - > dc->current_context->bw.dcn.cur_clk.dcfclk_khz) { + > dc->current_state->bw.dcn.cur_clk.dcfclk_khz) { smu_req.hard_min_dcefclk_khz = context->bw.dcn.calc_clk.dcfclk_khz; } if (decrease_allowed || context->bw.dcn.calc_clk.fclk_khz - > dc->current_context->bw.dcn.cur_clk.fclk_khz) { + > dc->current_state->bw.dcn.cur_clk.fclk_khz) { smu_req.hard_min_fclk_khz = context->bw.dcn.calc_clk.fclk_khz; } if (decrease_allowed || context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz - > dc->current_context->bw.dcn.cur_clk.dcfclk_deep_sleep_khz) { - dc->current_context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz = + > dc->current_state->bw.dcn.cur_clk.dcfclk_deep_sleep_khz) { + dc->current_state->bw.dcn.calc_clk.dcfclk_deep_sleep_khz = context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz; context->bw.dcn.cur_clk.dcfclk_deep_sleep_khz = context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz; @@ -2640,15 +2640,15 @@ static void dcn10_set_bandwidth( /* Decrease in freq is increase in period so opposite comparison for dram_ccm */ if (decrease_allowed || context->bw.dcn.calc_clk.dram_ccm_us - < dc->current_context->bw.dcn.cur_clk.dram_ccm_us) { - dc->current_context->bw.dcn.calc_clk.dram_ccm_us = + < dc->current_state->bw.dcn.cur_clk.dram_ccm_us) { + dc->current_state->bw.dcn.calc_clk.dram_ccm_us = context->bw.dcn.calc_clk.dram_ccm_us; context->bw.dcn.cur_clk.dram_ccm_us = context->bw.dcn.calc_clk.dram_ccm_us; } if (decrease_allowed || context->bw.dcn.calc_clk.min_active_dram_ccm_us - < dc->current_context->bw.dcn.cur_clk.min_active_dram_ccm_us) { - dc->current_context->bw.dcn.calc_clk.min_active_dram_ccm_us = + < dc->current_state->bw.dcn.cur_clk.min_active_dram_ccm_us) { + dc->current_state->bw.dcn.calc_clk.min_active_dram_ccm_us = context->bw.dcn.calc_clk.min_active_dram_ccm_us; context->bw.dcn.cur_clk.min_active_dram_ccm_us = context->bw.dcn.calc_clk.min_active_dram_ccm_us; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h index 8bb09de8dcd7..ca53dc1cc19b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h @@ -32,7 +32,7 @@ struct dc; void dcn10_hw_sequencer_construct(struct dc *dc); extern void fill_display_configs( - const struct validate_context *context, + const struct dc_state *context, struct dm_pp_display_configuration *pp_display_cfg); #endif /* __DC_HWSS_DCN10_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index d09ed13fb8ea..fff86ad0c411 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -850,7 +850,7 @@ static enum dc_status build_pipe_hw_param(struct pipe_ctx *pipe_ctx) static enum dc_status build_mapped_resource( const struct dc *dc, - struct validate_context *context, + struct dc_state *context, struct dc_stream_state *stream) { enum dc_status status = DC_OK; @@ -887,7 +887,7 @@ static enum dc_status build_mapped_resource( enum dc_status dcn10_add_stream_to_ctx( struct dc *dc, - struct validate_context *new_ctx, + struct dc_state *new_ctx, struct dc_stream_state *dc_stream) { enum dc_status result = DC_ERROR_UNEXPECTED; @@ -907,7 +907,7 @@ enum dc_status dcn10_add_stream_to_ctx( enum dc_status dcn10_validate_guaranteed( struct dc *dc, struct dc_stream_state *dc_stream, - struct validate_context *context) + struct dc_state *context) { enum dc_status result = DC_ERROR_UNEXPECTED; @@ -935,7 +935,7 @@ enum dc_status dcn10_validate_guaranteed( } static struct pipe_ctx *dcn10_acquire_idle_pipe_for_layer( - struct validate_context *context, + struct dc_state *context, const struct resource_pool *pool, struct dc_stream_state *stream) { diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index bd1a6367872f..71eb9859faf2 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -80,7 +80,7 @@ void core_link_set_avmute(struct pipe_ctx *pipe_ctx, bool enable); #include "transform.h" struct resource_pool; -struct validate_context; +struct dc_state; struct resource_context; struct resource_funcs { @@ -91,18 +91,18 @@ struct resource_funcs { enum dc_status (*validate_guaranteed)( struct dc *dc, struct dc_stream_state *stream, - struct validate_context *context); + struct dc_state *context); bool (*validate_bandwidth)( struct dc *dc, - struct validate_context *context); + struct dc_state *context); enum dc_status (*validate_global)( struct dc *dc, - struct validate_context *context); + struct dc_state *context); struct pipe_ctx *(*acquire_idle_pipe_for_layer)( - struct validate_context *context, + struct dc_state *context, const struct resource_pool *pool, struct dc_stream_state *stream); @@ -110,7 +110,7 @@ struct resource_funcs { enum dc_status (*add_stream_to_ctx)( struct dc *dc, - struct validate_context *new_ctx, + struct dc_state *new_ctx, struct dc_stream_state *dc_stream); }; @@ -252,7 +252,7 @@ union bw_context { struct dce_bw_output dce; }; -struct validate_context { +struct dc_state { struct dc_stream_state *streams[MAX_PIPES]; struct dc_stream_status stream_status[MAX_PIPES]; uint8_t stream_count; diff --git a/drivers/gpu/drm/amd/display/dc/inc/dce_calcs.h b/drivers/gpu/drm/amd/display/dc/inc/dce_calcs.h index 6a205b010084..ae2399f16d1c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dce_calcs.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dce_calcs.h @@ -34,7 +34,7 @@ struct pipe_ctx; struct dc; -struct validate_context; +struct dc_state; struct dce_bw_output; enum bw_calcs_version { diff --git a/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h b/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h index 58744fe87ed8..1e231f6de732 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h @@ -35,7 +35,7 @@ #include "../dml/display_mode_lib.h" struct dc; -struct validate_context; +struct dc_state; /******************************************************************************* * DCN data structures. @@ -621,7 +621,7 @@ extern const struct dcn_ip_params dcn10_ip_defaults; bool dcn_validate_bandwidth( struct dc *dc, - struct validate_context *context); + struct dc_state *context); unsigned int dcn_find_dcfclk_suits_all( const struct dc *dc, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 01e426194163..aae7629b1c08 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -49,7 +49,7 @@ struct dce_hwseq { }; struct pipe_ctx; -struct validate_context; +struct dc_state; struct dchub_init_data; struct dc_static_screen_events; struct resource_pool; @@ -60,16 +60,16 @@ struct hw_sequencer_funcs { void (*init_hw)(struct dc *dc); enum dc_status (*apply_ctx_to_hw)( - struct dc *dc, struct validate_context *context); + struct dc *dc, struct dc_state *context); void (*reset_hw_ctx_wrap)( - struct dc *dc, struct validate_context *context); + struct dc *dc, struct dc_state *context); void (*apply_ctx_for_surface)( struct dc *dc, const struct dc_stream_state *stream, int num_planes, - struct validate_context *context); + struct dc_state *context); void (*set_plane_config)( const struct dc *dc, @@ -127,7 +127,7 @@ struct hw_sequencer_funcs { void (*power_on_front_end)(struct dc *dc, struct pipe_ctx *pipe, - struct validate_context *context); + struct dc_state *context); void (*update_info_frame)(struct pipe_ctx *pipe_ctx); @@ -145,7 +145,7 @@ struct hw_sequencer_funcs { void (*set_bandwidth)( struct dc *dc, - struct validate_context *context, + struct dc_state *context, bool decrease_allowed); void (*set_drr)(struct pipe_ctx **pipe_ctx, int num_pipes, @@ -159,7 +159,7 @@ struct hw_sequencer_funcs { enum dc_status (*prog_pixclk_crtc_otg)( struct pipe_ctx *pipe_ctx, - struct validate_context *context, + struct dc_state *context, struct dc *dc); void (*setup_stereo)( diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index ebc0f5b02365..41437da5fb9b 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -81,14 +81,14 @@ void dc_destroy_resource_pool(struct dc *dc); enum dc_status resource_map_pool_resources( const struct dc *dc, - struct validate_context *context, + struct dc_state *context, struct dc_stream_state *stream); bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx); enum dc_status resource_build_scaling_params_for_context( const struct dc *dc, - struct validate_context *context); + struct dc_state *context); void resource_build_info_frame(struct pipe_ctx *pipe_ctx); @@ -122,7 +122,7 @@ bool resource_attach_surfaces_to_context( struct dc_plane_state *const *plane_state, int surface_count, struct dc_stream_state *dc_stream, - struct validate_context *context, + struct dc_state *context, const struct resource_pool *pool); struct pipe_ctx *find_idle_secondary_pipe( @@ -130,31 +130,31 @@ struct pipe_ctx *find_idle_secondary_pipe( const struct resource_pool *pool); bool resource_is_stream_unchanged( - struct validate_context *old_context, struct dc_stream_state *stream); + struct dc_state *old_context, struct dc_stream_state *stream); bool resource_validate_attach_surfaces( const struct dc_validation_set set[], int set_count, - const struct validate_context *old_context, - struct validate_context *context, + const struct dc_state *old_context, + struct dc_state *context, const struct resource_pool *pool); void validate_guaranteed_copy_streams( - struct validate_context *context, + struct dc_state *context, int max_streams); void resource_validate_ctx_update_pointer_after_copy( - const struct validate_context *src_ctx, - struct validate_context *dst_ctx); + const struct dc_state *src_ctx, + struct dc_state *dst_ctx); enum dc_status resource_map_clock_resources( const struct dc *dc, - struct validate_context *context, + struct dc_state *context, struct dc_stream_state *stream); enum dc_status resource_map_phy_clock_resources( const struct dc *dc, - struct validate_context *context, + struct dc_state *context, struct dc_stream_state *stream); bool pipe_need_reprogram( diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c index e3a12f3e0642..7cce28489dba 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c @@ -214,7 +214,7 @@ bool dce110_vblank_set( uint8_t pipe_offset = dal_irq_src - IRQ_TYPE_VBLANK; struct timing_generator *tg = - core_dc->current_context->res_ctx.pipe_ctx[pipe_offset].stream_res.tg; + core_dc->current_state->res_ctx.pipe_ctx[pipe_offset].stream_res.tg; if (enable) { if (!tg->funcs->arm_vert_intr(tg, 2)) { diff --git a/drivers/gpu/drm/amd/display/include/logger_interface.h b/drivers/gpu/drm/amd/display/include/logger_interface.h index 93c8556358f0..6641e8001e97 100644 --- a/drivers/gpu/drm/amd/display/include/logger_interface.h +++ b/drivers/gpu/drm/amd/display/include/logger_interface.h @@ -32,7 +32,7 @@ struct dc_context; struct dc_link; struct dc_surface_update; struct resource_context; -struct validate_context; +struct dc_state; /* * @@ -93,7 +93,7 @@ void context_timing_trace( void context_clock_trace( struct dc *dc, - struct validate_context *context); + struct dc_state *context); /* Any function which is empty or have incomplete implementation should be * marked by this macro. -- cgit From f36cc577c3254738e370b553f9f8cedf2df84070 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Mon, 28 Aug 2017 12:04:23 -0400 Subject: drm/amd/display: Rename dc resource_validate_ctx methods Rename dc_resource methods from validate_ctx to state Signed-off-by: Bhawanpreet Lakha Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc.c | 6 +++--- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 8 ++++---- drivers/gpu/drm/amd/display/dc/dc.h | 6 +++--- 4 files changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers/gpu') 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 9b018115d97e..4c7515d9c811 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4651,7 +4651,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, dm_state->context = dc_create_state(); ASSERT(dm_state->context); - dc_resource_validate_ctx_copy_construct_current(dc, dm_state->context); + dc_resource_state_copy_construct_current(dc, dm_state->context); /* Remove exiting planes if they are modified */ ret = dm_update_planes_state(dc, state, false, &lock_and_validation_needed); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 53f814dcc24d..6bf8af7a592d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1022,7 +1022,7 @@ void dc_release_state(struct dc_state *context) atomic_dec(&context->ref_count); if (atomic_read(&context->ref_count) == 0) { - dc_resource_validate_ctx_destruct(context); + dc_resource_state_destruct(context); dm_free(context); } } @@ -1292,7 +1292,7 @@ void dc_update_planes_and_stream(struct dc *dc, if (context == NULL) goto context_alloc_fail; - dc_resource_validate_ctx_copy_construct( + dc_resource_state_copy_construct( dc->current_state, context); /*remove old surfaces from context */ @@ -1635,7 +1635,7 @@ void dc_set_power_state( /* Preserve refcount */ ref_count = dc->current_state->ref_count; - dc_resource_validate_ctx_destruct(dc->current_state); + dc_resource_state_destruct(dc->current_state); memset(dc->current_state, 0, sizeof(*dc->current_state)); dc->current_state->ref_count = ref_count; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 727afeaa3830..d284d9d40e2b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1707,11 +1707,11 @@ void validate_guaranteed_copy_streams( } } -void dc_resource_validate_ctx_copy_construct_current( +void dc_resource_state_copy_construct_current( const struct dc *dc, struct dc_state *dst_ctx) { - dc_resource_validate_ctx_copy_construct(dc->current_state, dst_ctx); + dc_resource_state_copy_construct(dc->current_state, dst_ctx); } bool dc_validate_global_state( @@ -2413,7 +2413,7 @@ static void set_vsc_info_packet( /*TODO: stereo 3D support and extend pixel encoding colorimetry*/ } -void dc_resource_validate_ctx_destruct(struct dc_state *context) +void dc_resource_state_destruct(struct dc_state *context) { int i, j; @@ -2432,7 +2432,7 @@ void dc_resource_validate_ctx_destruct(struct dc_state *context) * Copy src_ctx into dst_ctx and retain all surfaces and streams referenced * by the src_ctx */ -void dc_resource_validate_ctx_copy_construct( +void dc_resource_state_copy_construct( const struct dc_state *src_ctx, struct dc_state *dst_ctx) { diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index d1d5737398df..f3ccc2043405 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -679,15 +679,15 @@ bool dc_validate_global_state( * No hardware is programmed for call. Only validation is done. */ -void dc_resource_validate_ctx_copy_construct( +void dc_resource_state_copy_construct( const struct dc_state *src_ctx, struct dc_state *dst_ctx); -void dc_resource_validate_ctx_copy_construct_current( +void dc_resource_state_copy_construct_current( const struct dc *dc, struct dc_state *dst_ctx); -void dc_resource_validate_ctx_destruct(struct dc_state *context); +void dc_resource_state_destruct(struct dc_state *context); /* * TODO update to make it about validation sets -- cgit From 4ed4e51b19496c4d160f3ca368d9ff5dd3e4a5b9 Mon Sep 17 00:00:00 2001 From: Mikita Lipski Date: Wed, 23 Aug 2017 15:29:18 -0400 Subject: drm/amd/display: Add a clock source to a sharing pipe Fix to allow DVI displays to share the same clock source Signed-off-by: Mikita Lipski Reviewed-by: Roman Li Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index d284d9d40e2b..a4e92219a594 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -2536,7 +2536,7 @@ enum dc_status resource_map_clock_resources( pipe_ctx->clock_source = NULL; if (!dc->config.disable_disp_pll_sharing) - resource_find_used_clk_src_for_sharing( + pipe_ctx->clock_source = resource_find_used_clk_src_for_sharing( &context->res_ctx, pipe_ctx); -- cgit From ceda4e980058316531a1a6b72797d9068ddacd02 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Thu, 24 Aug 2017 17:12:48 -0400 Subject: drm/amd/display: add aux arbitration logic Signed-off-by: Charlene Liu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.c | 6 +++++ drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.h | 2 ++ .../display/dc/i2caux/dce110/aux_engine_dce110.c | 30 ++++++++++++++++++++-- 3 files changed, 36 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.c b/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.c index 667660f3fa26..3c9608ce94b8 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.c @@ -69,6 +69,12 @@ bool dal_aux_engine_acquire( struct aux_engine *aux_engine = FROM_ENGINE(engine); enum gpio_result result; + if (aux_engine->funcs->is_engine_available) { + /*check whether SW could use the engine*/ + if (!aux_engine->funcs->is_engine_available(aux_engine)) { + return false; + } + } result = dal_ddc_open(ddc, GPIO_MODE_HARDWARE, GPIO_DDC_CONFIG_TYPE_MODE_AUX); diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.h b/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.h index b5d6c79eb029..40b202893772 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.h +++ b/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.h @@ -86,6 +86,8 @@ struct aux_engine_funcs { enum aux_channel_operation_result (*get_channel_status)( struct aux_engine *engine, uint8_t *returned_bytes); + bool (*is_engine_available) ( + struct aux_engine *engine); }; struct aux_engine { diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c index f49fd1ad3807..98ce0fe5ac37 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c @@ -93,15 +93,36 @@ static void destroy( } #define SW_CAN_ACCESS_AUX 1 +#define DMCU_CAN_ACCESS_AUX 2 +static bool is_engine_available( + struct aux_engine *engine) +{ + struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); + + uint32_t value = REG_READ(AUX_ARB_CONTROL); + uint32_t field = get_reg_field_value( + value, + AUX_ARB_CONTROL, + AUX_REG_RW_CNTL_STATUS); + + return (field != DMCU_CAN_ACCESS_AUX); +} static bool acquire_engine( struct aux_engine *engine) { struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); + uint32_t value = REG_READ(AUX_ARB_CONTROL); + uint32_t field = get_reg_field_value( + value, + AUX_ARB_CONTROL, + AUX_REG_RW_CNTL_STATUS); + if (field == DMCU_CAN_ACCESS_AUX) + return false; /* enable AUX before request SW to access AUX */ - uint32_t value = REG_READ(AUX_CONTROL); - uint32_t field = get_reg_field_value(value, + value = REG_READ(AUX_CONTROL); + field = get_reg_field_value(value, AUX_CONTROL, AUX_EN); @@ -395,6 +416,7 @@ static const struct aux_engine_funcs aux_engine_funcs = { .submit_channel_request = submit_channel_request, .process_channel_reply = process_channel_reply, .get_channel_status = get_channel_status, + .is_engine_available = is_engine_available, }; static const struct engine_funcs engine_funcs = { @@ -425,6 +447,10 @@ static bool construct( static void destruct( struct aux_engine_dce110 *engine) { + struct aux_engine_dce110 *aux110 = engine; +/*temp w/a, to do*/ + REG_UPDATE(AUX_ARB_CONTROL, AUX_DMCU_DONE_USING_AUX_REG, 1); + REG_UPDATE(AUX_ARB_CONTROL, AUX_SW_DONE_USING_AUX_REG, 1); dal_aux_engine_destruct(&engine->base); } -- cgit From ab8db3e1653c50ae19d1c31d82f94beb5115aeef Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Mon, 28 Aug 2017 14:25:01 -0400 Subject: drm/amd/display: Move dis_clk into dc_state. dis_clk is single instance across pipes. Signed-off-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 7 +++ drivers/gpu/drm/amd/display/dc/core/dc_link.c | 38 +++++++----- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 10 +++- drivers/gpu/drm/amd/display/dc/dc.h | 5 ++ .../amd/display/dc/dce110/dce110_hw_sequencer.c | 67 ++++++++++------------ .../drm/amd/display/dc/dce110/dce110_resource.c | 1 - drivers/gpu/drm/amd/display/dc/inc/core_types.h | 7 ++- 7 files changed, 78 insertions(+), 57 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 6bf8af7a592d..ab6ad946231e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -573,6 +573,8 @@ static bool construct(struct dc *dc, if (!dc->res_pool) goto fail; + dc_resource_state_construct(dc, dc->current_state); + if (!create_links(dc, init_params->num_virtual_links)) goto fail; @@ -677,6 +679,8 @@ bool dc_validate_guaranteed( if (context == NULL) goto context_alloc_fail; + dc_resource_state_construct(dc, dc->current_state); + atomic_inc(&context->ref_count); result = dc->res_pool->funcs->validate_guaranteed( @@ -1622,6 +1626,8 @@ void dc_set_power_state( switch (power_state) { case DC_ACPI_CM_POWER_STATE_D0: + dc_resource_state_construct(dc, dc->current_state); + dc->hwss.init_hw(dc); break; default: @@ -1638,6 +1644,7 @@ void dc_set_power_state( dc_resource_state_destruct(dc->current_state); memset(dc->current_state, 0, sizeof(*dc->current_state)); + dc->current_state->ref_count = ref_count; break; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 65e12614d96c..b95b58d3648a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1181,7 +1181,9 @@ static void enable_stream_features(struct pipe_ctx *pipe_ctx) &downspread.raw, sizeof(downspread)); } -static enum dc_status enable_link_dp(struct pipe_ctx *pipe_ctx) +static enum dc_status enable_link_dp( + struct dc_state *state, + struct pipe_ctx *pipe_ctx) { struct dc_stream_state *stream = pipe_ctx->stream; enum dc_status status; @@ -1201,14 +1203,14 @@ static enum dc_status enable_link_dp(struct pipe_ctx *pipe_ctx) max_link_rate = LINK_RATE_HIGH3; if (link_settings.link_rate == max_link_rate) { - if (pipe_ctx->dis_clk->funcs->set_min_clocks_state) { - if (pipe_ctx->dis_clk->cur_min_clks_state < DM_PP_CLOCKS_STATE_NOMINAL) - pipe_ctx->dis_clk->funcs->set_min_clocks_state( - pipe_ctx->dis_clk, DM_PP_CLOCKS_STATE_NOMINAL); + if (state->dis_clk->funcs->set_min_clocks_state) { + if (state->dis_clk->cur_min_clks_state < DM_PP_CLOCKS_STATE_NOMINAL) + state->dis_clk->funcs->set_min_clocks_state( + state->dis_clk, DM_PP_CLOCKS_STATE_NOMINAL); } else { uint32_t dp_phyclk_in_khz; const struct clocks_value clocks_value = - pipe_ctx->dis_clk->cur_clocks_value; + state->dis_clk->cur_clocks_value; /* 27mhz = 27000000hz= 27000khz */ dp_phyclk_in_khz = link_settings.link_rate * 27000; @@ -1216,8 +1218,8 @@ static enum dc_status enable_link_dp(struct pipe_ctx *pipe_ctx) if (((clocks_value.max_non_dp_phyclk_in_khz != 0) && (dp_phyclk_in_khz > clocks_value.max_non_dp_phyclk_in_khz)) || (dp_phyclk_in_khz > clocks_value.max_dp_phyclk_in_khz)) { - pipe_ctx->dis_clk->funcs->apply_clock_voltage_request( - pipe_ctx->dis_clk, + state->dis_clk->funcs->apply_clock_voltage_request( + state->dis_clk, DM_PP_CLOCK_TYPE_DISPLAYPHYCLK, dp_phyclk_in_khz, false, @@ -1256,7 +1258,9 @@ static enum dc_status enable_link_dp(struct pipe_ctx *pipe_ctx) return status; } -static enum dc_status enable_link_dp_mst(struct pipe_ctx *pipe_ctx) +static enum dc_status enable_link_dp_mst( + struct dc_state *state, + struct pipe_ctx *pipe_ctx) { struct dc_link *link = pipe_ctx->stream->sink->link; @@ -1269,7 +1273,7 @@ static enum dc_status enable_link_dp_mst(struct pipe_ctx *pipe_ctx) /* set the sink to MST mode before enabling the link */ dp_enable_mst_on_sink(link, true); - return enable_link_dp(pipe_ctx); + return enable_link_dp(state, pipe_ctx); } static bool get_ext_hdmi_settings(struct pipe_ctx *pipe_ctx, @@ -1709,16 +1713,18 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) } /****************************enable_link***********************************/ -static enum dc_status enable_link(struct pipe_ctx *pipe_ctx) +static enum dc_status enable_link( + struct dc_state *state, + struct pipe_ctx *pipe_ctx) { enum dc_status status = DC_ERROR_UNEXPECTED; switch (pipe_ctx->stream->signal) { case SIGNAL_TYPE_DISPLAY_PORT: case SIGNAL_TYPE_EDP: - status = enable_link_dp(pipe_ctx); + status = enable_link_dp(state, pipe_ctx); break; case SIGNAL_TYPE_DISPLAY_PORT_MST: - status = enable_link_dp_mst(pipe_ctx); + status = enable_link_dp_mst(state, pipe_ctx); msleep(200); break; case SIGNAL_TYPE_DVI_SINGLE_LINK: @@ -2285,11 +2291,13 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx) return DC_OK; } -void core_link_enable_stream(struct pipe_ctx *pipe_ctx) +void core_link_enable_stream( + struct dc_state *state, + struct pipe_ctx *pipe_ctx) { struct dc *core_dc = pipe_ctx->stream->ctx->dc; - enum dc_status status = enable_link(pipe_ctx); + enum dc_status status = enable_link(state, pipe_ctx); if (status != DC_OK) { dm_logger_write(pipe_ctx->stream->ctx->logger, diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index a4e92219a594..c7bb966e8b29 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1033,7 +1033,6 @@ static int acquire_first_split_pipe( pipe_ctx->plane_res.ipp = pool->ipps[i]; pipe_ctx->plane_res.xfm = pool->transforms[i]; pipe_ctx->stream_res.opp = pool->opps[i]; - pipe_ctx->dis_clk = pool->display_clock; pipe_ctx->pipe_idx = i; pipe_ctx->stream = stream; @@ -1368,7 +1367,6 @@ static int acquire_first_free_pipe( pipe_ctx->plane_res.ipp = pool->ipps[i]; pipe_ctx->plane_res.xfm = pool->transforms[i]; pipe_ctx->stream_res.opp = pool->opps[i]; - pipe_ctx->dis_clk = pool->display_clock; pipe_ctx->pipe_idx = i; @@ -1714,6 +1712,14 @@ void dc_resource_state_copy_construct_current( dc_resource_state_copy_construct(dc->current_state, dst_ctx); } + +void dc_resource_state_construct( + const struct dc *dc, + struct dc_state *dst_ctx) +{ + dst_ctx->dis_clk = dc->res_pool->display_clock; +} + bool dc_validate_global_state( struct dc *dc, struct dc_state *new_ctx) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index f3ccc2043405..e2159306a9c2 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -679,6 +679,11 @@ bool dc_validate_global_state( * No hardware is programmed for call. Only validation is done. */ + +void dc_resource_state_construct( + const struct dc *dc, + struct dc_state *dst_ctx); + void dc_resource_state_copy_construct( const struct dc_state *src_ctx, struct dc_state *dst_ctx); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 1c6e2006f2a1..42caad423430 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -828,6 +828,7 @@ static enum audio_dto_source translate_to_dto_source(enum controller_id crtc_id) } static void build_audio_output( + struct dc_state *state, const struct pipe_ctx *pipe_ctx, struct audio_output *audio_output) { @@ -889,8 +890,8 @@ static void build_audio_output( if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT || pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { audio_output->pll_info.dp_dto_source_clock_in_khz = - pipe_ctx->dis_clk->funcs->get_dp_ref_clk_frequency( - pipe_ctx->dis_clk); + state->dis_clk->funcs->get_dp_ref_clk_frequency( + state->dis_clk); } audio_output->pll_info.feed_back_divider = @@ -1109,7 +1110,7 @@ static enum dc_status apply_single_controller_ctx_to_hw( resource_build_info_frame(pipe_ctx); dce110_update_info_frame(pipe_ctx); if (!pipe_ctx_old->stream) { - core_link_enable_stream(pipe_ctx); + core_link_enable_stream(context, pipe_ctx); if (dc_is_dp_signal(pipe_ctx->stream->signal)) @@ -1461,42 +1462,34 @@ static void apply_min_clocks( bool pre_mode_set) { struct state_dependent_clocks req_clocks = {0}; - struct pipe_ctx *pipe_ctx; - int i; - - for (i = 0; i < MAX_PIPES; i++) { - pipe_ctx = &context->res_ctx.pipe_ctx[i]; - if (pipe_ctx->dis_clk != NULL) - break; - } if (!pre_mode_set) { /* set clock_state without verification */ - if (pipe_ctx->dis_clk->funcs->set_min_clocks_state) { - pipe_ctx->dis_clk->funcs->set_min_clocks_state( - pipe_ctx->dis_clk, *clocks_state); + if (context->dis_clk->funcs->set_min_clocks_state) { + context->dis_clk->funcs->set_min_clocks_state( + context->dis_clk, *clocks_state); return; } /* TODO: This is incorrect. Figure out how to fix. */ - pipe_ctx->dis_clk->funcs->apply_clock_voltage_request( - pipe_ctx->dis_clk, + context->dis_clk->funcs->apply_clock_voltage_request( + context->dis_clk, DM_PP_CLOCK_TYPE_DISPLAY_CLK, - pipe_ctx->dis_clk->cur_clocks_value.dispclk_in_khz, + context->dis_clk->cur_clocks_value.dispclk_in_khz, pre_mode_set, false); - pipe_ctx->dis_clk->funcs->apply_clock_voltage_request( - pipe_ctx->dis_clk, + context->dis_clk->funcs->apply_clock_voltage_request( + context->dis_clk, DM_PP_CLOCK_TYPE_PIXELCLK, - pipe_ctx->dis_clk->cur_clocks_value.max_pixelclk_in_khz, + context->dis_clk->cur_clocks_value.max_pixelclk_in_khz, pre_mode_set, false); - pipe_ctx->dis_clk->funcs->apply_clock_voltage_request( - pipe_ctx->dis_clk, + context->dis_clk->funcs->apply_clock_voltage_request( + context->dis_clk, DM_PP_CLOCK_TYPE_DISPLAYPHYCLK, - pipe_ctx->dis_clk->cur_clocks_value.max_non_dp_phyclk_in_khz, + context->dis_clk->cur_clocks_value.max_non_dp_phyclk_in_khz, pre_mode_set, false); return; @@ -1510,28 +1503,28 @@ static void apply_min_clocks( req_clocks.pixel_clk_khz = get_max_pixel_clock_for_all_paths( dc, context, true); - if (pipe_ctx->dis_clk->funcs->get_required_clocks_state) { - *clocks_state = pipe_ctx->dis_clk->funcs->get_required_clocks_state( - pipe_ctx->dis_clk, &req_clocks); - pipe_ctx->dis_clk->funcs->set_min_clocks_state( - pipe_ctx->dis_clk, *clocks_state); + if (context->dis_clk->funcs->get_required_clocks_state) { + *clocks_state = context->dis_clk->funcs->get_required_clocks_state( + context->dis_clk, &req_clocks); + context->dis_clk->funcs->set_min_clocks_state( + context->dis_clk, *clocks_state); } else { - pipe_ctx->dis_clk->funcs->apply_clock_voltage_request( - pipe_ctx->dis_clk, + context->dis_clk->funcs->apply_clock_voltage_request( + context->dis_clk, DM_PP_CLOCK_TYPE_DISPLAY_CLK, req_clocks.display_clk_khz, pre_mode_set, false); - pipe_ctx->dis_clk->funcs->apply_clock_voltage_request( - pipe_ctx->dis_clk, + context->dis_clk->funcs->apply_clock_voltage_request( + context->dis_clk, DM_PP_CLOCK_TYPE_PIXELCLK, req_clocks.pixel_clk_khz, pre_mode_set, false); - pipe_ctx->dis_clk->funcs->apply_clock_voltage_request( - pipe_ctx->dis_clk, + context->dis_clk->funcs->apply_clock_voltage_request( + context->dis_clk, DM_PP_CLOCK_TYPE_DISPLAYPHYCLK, req_clocks.pixel_clk_khz, pre_mode_set, @@ -1806,7 +1799,7 @@ enum dc_status dce110_apply_ctx_to_hw( if (pipe_ctx->stream_res.audio != NULL) { struct audio_output audio_output; - build_audio_output(pipe_ctx, &audio_output); + build_audio_output(context, pipe_ctx, &audio_output); pipe_ctx->stream_res.audio->funcs->wall_dto_setup( pipe_ctx->stream_res.audio, @@ -1834,7 +1827,7 @@ enum dc_status dce110_apply_ctx_to_hw( if (pipe_ctx->stream_res.audio != NULL) { struct audio_output audio_output; - build_audio_output(pipe_ctx, &audio_output); + build_audio_output(context, pipe_ctx, &audio_output); pipe_ctx->stream_res.audio->funcs->wall_dto_setup( pipe_ctx->stream_res.audio, @@ -1868,7 +1861,7 @@ enum dc_status dce110_apply_ctx_to_hw( struct audio_output audio_output; - build_audio_output(pipe_ctx, &audio_output); + build_audio_output(context, pipe_ctx, &audio_output); if (dc_is_dp_signal(pipe_ctx->stream->signal)) pipe_ctx->stream_res.stream_enc->funcs->dp_audio_setup( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 94b6eb83e01e..4942460d42ca 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -971,7 +971,6 @@ static struct pipe_ctx *dce110_acquire_underlay( /*pipe_ctx->plane_res.ipp = res_ctx->pool->ipps[underlay_idx];*/ pipe_ctx->plane_res.xfm = pool->transforms[underlay_idx]; pipe_ctx->stream_res.opp = pool->opps[underlay_idx]; - pipe_ctx->dis_clk = pool->display_clock; pipe_ctx->pipe_idx = underlay_idx; pipe_ctx->stream = stream; diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 71eb9859faf2..915d5c10361b 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -70,7 +70,9 @@ enum dc_status dc_link_validate_mode_timing( void core_link_resume(struct dc_link *link); -void core_link_enable_stream(struct pipe_ctx *pipe_ctx); +void core_link_enable_stream( + struct dc_state *state, + struct pipe_ctx *pipe_ctx); void core_link_disable_stream(struct pipe_ctx *pipe_ctx); @@ -188,7 +190,6 @@ struct pipe_ctx { struct plane_resource plane_res; struct stream_resource stream_res; - struct display_clock *dis_clk; struct clock_source *clock_source; struct pll_settings pll_settings; @@ -268,6 +269,8 @@ struct dc_state { struct dcn_bw_internal_vars dcn_bw_vars; #endif + struct display_clock *dis_clk; + atomic_t ref_count; }; -- cgit From c9bb686b597d30935d6e05aaade51fc765d1ca5b Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Mon, 28 Aug 2017 16:50:17 -0400 Subject: drm/amd/display: Fix time out on boot On boot, hubp 0 is powergated during enable accel mode, so we time out when we try to blank in undo wa. Fix: Check power gate status before set blank Signed-off-by: Eric Yang Reviewed-by: Hersen Wu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 71ff1cedbdf4..7ea274475598 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -780,6 +780,12 @@ static void undo_DEGVIDCN10_253_wa(struct dc *dc) { struct dce_hwseq *hws = dc->hwseq; struct mem_input *mi = dc->res_pool->mis[0]; + int pwr_status = 0; + + REG_GET(DOMAIN0_PG_STATUS, DOMAIN0_PGFSM_PWR_STATUS, &pwr_status); + /* Don't need to blank if hubp is power gated*/ + if (pwr_status == 2) + return; mi->funcs->set_blank(mi, true); -- cgit From c7299705e6e76fe499ddc9af7beb0500e945fec9 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Mon, 28 Aug 2017 16:28:34 -0400 Subject: drm/amd/display: only polling VSync Phase within VSync peroroid Signed-off-by: Charlene Liu Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 4 ++-- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 4 ++-- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c | 27 +++++++++++++----------- drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h | 2 +- 5 files changed, 21 insertions(+), 18 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index b95b58d3648a..cea8dafd2edc 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1862,13 +1862,13 @@ bool dc_link_set_abm_disable(const struct dc_link *link) } -bool dc_link_set_psr_enable(const struct dc_link *link, bool enable) +bool dc_link_set_psr_enable(const struct dc_link *link, bool enable, bool wait) { struct dc *core_dc = link->ctx->dc; struct dmcu *dmcu = core_dc->res_pool->dmcu; if (dmcu != NULL && link->psr_enabled) - dmcu->funcs->set_psr_enable(dmcu, enable); + dmcu->funcs->set_psr_enable(dmcu, enable, wait); return true; } 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 5f2b52e41427..527cc0400fd3 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 @@ -1653,8 +1653,8 @@ static bool handle_hpd_irq_psr_sink(const struct dc_link *link) sizeof(psr_error_status.raw)); /* PSR error, disable and re-enable PSR */ - dc_link_set_psr_enable(link, false); - dc_link_set_psr_enable(link, true); + dc_link_set_psr_enable(link, false, true); + dc_link_set_psr_enable(link, true, true); return true; } else if (psr_sink_psr_status.bits.SINK_SELF_REFRESH_STATUS == diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index e2159306a9c2..2316a6060b2c 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -871,7 +871,7 @@ struct dc_link *dc_get_link_at_index(struct dc *dc, uint32_t link_index); bool dc_link_set_backlight_level(const struct dc_link *dc_link, uint32_t level, uint32_t frame_ramp, const struct dc_stream_state *stream); -bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable); +bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable, bool wait); bool dc_link_get_psr_state(const struct dc_link *dc_link, uint32_t *psr_state); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c index efcdb2bf4d0d..313f61bf06e1 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c @@ -103,7 +103,7 @@ static void dce_get_dmcu_psr_state(struct dmcu *dmcu, uint32_t *psr_state) REG_UPDATE(DMCU_RAM_ACCESS_CTRL, IRAM_HOST_ACCESS_EN, 0); } -static void dce_dmcu_set_psr_enable(struct dmcu *dmcu, bool enable) +static void dce_dmcu_set_psr_enable(struct dmcu *dmcu, bool enable, bool wait) { struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); unsigned int dmcu_max_retry_on_wait_reg_ready = 801; @@ -127,17 +127,18 @@ static void dce_dmcu_set_psr_enable(struct dmcu *dmcu, bool enable) /* notifyDMCUMsg */ REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); - - for (retryCount = 0; retryCount <= 100; retryCount++) { - dce_get_dmcu_psr_state(dmcu, &psr_state); - if (enable) { - if (psr_state != 0) - break; - } else { - if (psr_state == 0) - break; + if (wait == true) { + for (retryCount = 0; retryCount <= 100; retryCount++) { + dce_get_dmcu_psr_state(dmcu, &psr_state); + if (enable) { + if (psr_state != 0) + break; + } else { + if (psr_state == 0) + break; + } + dm_delay_in_microseconds(dmcu->ctx, 10); } - dm_delay_in_microseconds(dmcu->ctx, 10); } } @@ -338,7 +339,7 @@ static void dcn10_get_dmcu_psr_state(struct dmcu *dmcu, uint32_t *psr_state) REG_UPDATE(DMCU_RAM_ACCESS_CTRL, IRAM_HOST_ACCESS_EN, 0); } -static void dcn10_dmcu_set_psr_enable(struct dmcu *dmcu, bool enable) +static void dcn10_dmcu_set_psr_enable(struct dmcu *dmcu, bool enable, bool wait) { struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); unsigned int dmcu_max_retry_on_wait_reg_ready = 801; @@ -367,6 +368,7 @@ static void dcn10_dmcu_set_psr_enable(struct dmcu *dmcu, bool enable) * Exit PSR may need to wait 1-2 frames to power up. Timeout after at * least a few frames. Should never hit the max retry assert below. */ + if (wait == true) { for (retryCount = 0; retryCount <= 1000; retryCount++) { dcn10_get_dmcu_psr_state(dmcu, &psr_state); if (enable) { @@ -381,6 +383,7 @@ static void dcn10_dmcu_set_psr_enable(struct dmcu *dmcu, bool enable) /* assert if max retry hit */ ASSERT(retryCount <= 1000); + } } static void dcn10_dmcu_setup_psr(struct dmcu *dmcu, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h index e34b25939a98..0574c29cc4a8 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h @@ -37,7 +37,7 @@ struct dmcu_funcs { unsigned int start_offset, const char *src, unsigned int bytes); - void (*set_psr_enable)(struct dmcu *dmcu, bool enable); + void (*set_psr_enable)(struct dmcu *dmcu, bool enable, bool wait); void (*setup_psr)(struct dmcu *dmcu, struct dc_link *link, struct psr_context *psr_context); -- cgit From b97a88cd569c5f1dac82654bee2efee07633921c Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Mon, 28 Aug 2017 14:05:17 -0400 Subject: drm/amd/display: clean up functions in dcn10_dpp_cm Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h | 420 -------------- .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c | 628 +++++---------------- 2 files changed, 140 insertions(+), 908 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h index 9a678dcaa908..717930584111 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h @@ -97,12 +97,6 @@ SRI(CM_DGAM_RAMB_END_CNTL1_R, CM, id), \ SRI(CM_DGAM_RAMB_END_CNTL2_R, CM, id), \ SRI(CM_DGAM_RAMB_REGION_0_1, CM, id), \ - SRI(CM_DGAM_RAMB_REGION_2_3, CM, id), \ - SRI(CM_DGAM_RAMB_REGION_4_5, CM, id), \ - SRI(CM_DGAM_RAMB_REGION_6_7, CM, id), \ - SRI(CM_DGAM_RAMB_REGION_8_9, CM, id), \ - SRI(CM_DGAM_RAMB_REGION_10_11, CM, id), \ - SRI(CM_DGAM_RAMB_REGION_12_13, CM, id), \ SRI(CM_DGAM_RAMB_REGION_14_15, CM, id), \ SRI(CM_DGAM_RAMA_START_CNTL_B, CM, id), \ SRI(CM_DGAM_RAMA_START_CNTL_G, CM, id), \ @@ -117,12 +111,6 @@ SRI(CM_DGAM_RAMA_END_CNTL1_R, CM, id), \ SRI(CM_DGAM_RAMA_END_CNTL2_R, CM, id), \ SRI(CM_DGAM_RAMA_REGION_0_1, CM, id), \ - SRI(CM_DGAM_RAMA_REGION_2_3, CM, id), \ - SRI(CM_DGAM_RAMA_REGION_4_5, CM, id), \ - SRI(CM_DGAM_RAMA_REGION_6_7, CM, id), \ - SRI(CM_DGAM_RAMA_REGION_8_9, CM, id), \ - SRI(CM_DGAM_RAMA_REGION_10_11, CM, id), \ - SRI(CM_DGAM_RAMA_REGION_12_13, CM, id), \ SRI(CM_DGAM_RAMA_REGION_14_15, CM, id), \ SRI(CM_MEM_PWR_CTRL, CM, id), \ SRI(CM_DGAM_LUT_WRITE_EN_MASK, CM, id), \ @@ -174,21 +162,6 @@ SRI(CM_RGAM_RAMB_END_CNTL1_R, CM, id), \ SRI(CM_RGAM_RAMB_END_CNTL2_R, CM, id), \ SRI(CM_RGAM_RAMB_REGION_0_1, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_2_3, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_4_5, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_6_7, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_8_9, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_10_11, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_12_13, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_14_15, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_16_17, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_18_19, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_20_21, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_22_23, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_24_25, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_26_27, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_28_29, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_30_31, CM, id), \ SRI(CM_RGAM_RAMB_REGION_32_33, CM, id), \ SRI(CM_RGAM_RAMA_START_CNTL_B, CM, id), \ SRI(CM_RGAM_RAMA_START_CNTL_G, CM, id), \ @@ -203,21 +176,6 @@ SRI(CM_RGAM_RAMA_END_CNTL1_R, CM, id), \ SRI(CM_RGAM_RAMA_END_CNTL2_R, CM, id), \ SRI(CM_RGAM_RAMA_REGION_0_1, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_2_3, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_4_5, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_6_7, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_8_9, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_10_11, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_12_13, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_14_15, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_16_17, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_18_19, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_20_21, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_22_23, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_24_25, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_26_27, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_28_29, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_30_31, CM, id), \ SRI(CM_RGAM_RAMA_REGION_32_33, CM, id), \ SRI(CM_RGAM_CONTROL, CM, id), \ SRI(CM_IGAM_CONTROL, CM, id), \ @@ -338,30 +296,6 @@ TF_SF(CM0_CM_DGAM_RAMB_REGION_0_1, CM_DGAM_RAMB_EXP_REGION0_NUM_SEGMENTS, mask_sh), \ TF_SF(CM0_CM_DGAM_RAMB_REGION_0_1, CM_DGAM_RAMB_EXP_REGION1_LUT_OFFSET, mask_sh), \ TF_SF(CM0_CM_DGAM_RAMB_REGION_0_1, CM_DGAM_RAMB_EXP_REGION1_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMB_REGION_2_3, CM_DGAM_RAMB_EXP_REGION2_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMB_REGION_2_3, CM_DGAM_RAMB_EXP_REGION2_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMB_REGION_2_3, CM_DGAM_RAMB_EXP_REGION3_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMB_REGION_2_3, CM_DGAM_RAMB_EXP_REGION3_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMB_REGION_4_5, CM_DGAM_RAMB_EXP_REGION4_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMB_REGION_4_5, CM_DGAM_RAMB_EXP_REGION4_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMB_REGION_4_5, CM_DGAM_RAMB_EXP_REGION5_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMB_REGION_4_5, CM_DGAM_RAMB_EXP_REGION5_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMB_REGION_6_7, CM_DGAM_RAMB_EXP_REGION6_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMB_REGION_6_7, CM_DGAM_RAMB_EXP_REGION6_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMB_REGION_6_7, CM_DGAM_RAMB_EXP_REGION7_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMB_REGION_6_7, CM_DGAM_RAMB_EXP_REGION7_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMB_REGION_8_9, CM_DGAM_RAMB_EXP_REGION8_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMB_REGION_8_9, CM_DGAM_RAMB_EXP_REGION8_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMB_REGION_8_9, CM_DGAM_RAMB_EXP_REGION9_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMB_REGION_8_9, CM_DGAM_RAMB_EXP_REGION9_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMB_REGION_10_11, CM_DGAM_RAMB_EXP_REGION10_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMB_REGION_10_11, CM_DGAM_RAMB_EXP_REGION10_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMB_REGION_10_11, CM_DGAM_RAMB_EXP_REGION11_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMB_REGION_10_11, CM_DGAM_RAMB_EXP_REGION11_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMB_REGION_12_13, CM_DGAM_RAMB_EXP_REGION12_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMB_REGION_12_13, CM_DGAM_RAMB_EXP_REGION12_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMB_REGION_12_13, CM_DGAM_RAMB_EXP_REGION13_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMB_REGION_12_13, CM_DGAM_RAMB_EXP_REGION13_NUM_SEGMENTS, mask_sh), \ TF_SF(CM0_CM_DGAM_RAMB_REGION_14_15, CM_DGAM_RAMB_EXP_REGION14_LUT_OFFSET, mask_sh), \ TF_SF(CM0_CM_DGAM_RAMB_REGION_14_15, CM_DGAM_RAMB_EXP_REGION14_NUM_SEGMENTS, mask_sh), \ TF_SF(CM0_CM_DGAM_RAMB_REGION_14_15, CM_DGAM_RAMB_EXP_REGION15_LUT_OFFSET, mask_sh), \ @@ -388,30 +322,6 @@ TF_SF(CM0_CM_DGAM_RAMA_REGION_0_1, CM_DGAM_RAMA_EXP_REGION0_NUM_SEGMENTS, mask_sh), \ TF_SF(CM0_CM_DGAM_RAMA_REGION_0_1, CM_DGAM_RAMA_EXP_REGION1_LUT_OFFSET, mask_sh), \ TF_SF(CM0_CM_DGAM_RAMA_REGION_0_1, CM_DGAM_RAMA_EXP_REGION1_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMA_REGION_2_3, CM_DGAM_RAMA_EXP_REGION2_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMA_REGION_2_3, CM_DGAM_RAMA_EXP_REGION2_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMA_REGION_2_3, CM_DGAM_RAMA_EXP_REGION3_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMA_REGION_2_3, CM_DGAM_RAMA_EXP_REGION3_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMA_REGION_4_5, CM_DGAM_RAMA_EXP_REGION4_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMA_REGION_4_5, CM_DGAM_RAMA_EXP_REGION4_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMA_REGION_4_5, CM_DGAM_RAMA_EXP_REGION5_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMA_REGION_4_5, CM_DGAM_RAMA_EXP_REGION5_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMA_REGION_6_7, CM_DGAM_RAMA_EXP_REGION6_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMA_REGION_6_7, CM_DGAM_RAMA_EXP_REGION6_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMA_REGION_6_7, CM_DGAM_RAMA_EXP_REGION7_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMA_REGION_6_7, CM_DGAM_RAMA_EXP_REGION7_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMA_REGION_8_9, CM_DGAM_RAMA_EXP_REGION8_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMA_REGION_8_9, CM_DGAM_RAMA_EXP_REGION8_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMA_REGION_8_9, CM_DGAM_RAMA_EXP_REGION9_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMA_REGION_8_9, CM_DGAM_RAMA_EXP_REGION9_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMA_REGION_10_11, CM_DGAM_RAMA_EXP_REGION10_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMA_REGION_10_11, CM_DGAM_RAMA_EXP_REGION10_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMA_REGION_10_11, CM_DGAM_RAMA_EXP_REGION11_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMA_REGION_10_11, CM_DGAM_RAMA_EXP_REGION11_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMA_REGION_12_13, CM_DGAM_RAMA_EXP_REGION12_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMA_REGION_12_13, CM_DGAM_RAMA_EXP_REGION12_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMA_REGION_12_13, CM_DGAM_RAMA_EXP_REGION13_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMA_REGION_12_13, CM_DGAM_RAMA_EXP_REGION13_NUM_SEGMENTS, mask_sh), \ TF_SF(CM0_CM_DGAM_RAMA_REGION_14_15, CM_DGAM_RAMA_EXP_REGION14_LUT_OFFSET, mask_sh), \ TF_SF(CM0_CM_DGAM_RAMA_REGION_14_15, CM_DGAM_RAMA_EXP_REGION14_NUM_SEGMENTS, mask_sh), \ TF_SF(CM0_CM_DGAM_RAMA_REGION_14_15, CM_DGAM_RAMA_EXP_REGION15_LUT_OFFSET, mask_sh), \ @@ -501,66 +411,6 @@ TF_SF(CM0_CM_RGAM_RAMB_REGION_0_1, CM_RGAM_RAMB_EXP_REGION0_NUM_SEGMENTS, mask_sh), \ TF_SF(CM0_CM_RGAM_RAMB_REGION_0_1, CM_RGAM_RAMB_EXP_REGION1_LUT_OFFSET, mask_sh), \ TF_SF(CM0_CM_RGAM_RAMB_REGION_0_1, CM_RGAM_RAMB_EXP_REGION1_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_2_3, CM_RGAM_RAMB_EXP_REGION2_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_2_3, CM_RGAM_RAMB_EXP_REGION2_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_2_3, CM_RGAM_RAMB_EXP_REGION3_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_2_3, CM_RGAM_RAMB_EXP_REGION3_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_4_5, CM_RGAM_RAMB_EXP_REGION4_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_4_5, CM_RGAM_RAMB_EXP_REGION4_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_4_5, CM_RGAM_RAMB_EXP_REGION5_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_4_5, CM_RGAM_RAMB_EXP_REGION5_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_6_7, CM_RGAM_RAMB_EXP_REGION6_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_6_7, CM_RGAM_RAMB_EXP_REGION6_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_6_7, CM_RGAM_RAMB_EXP_REGION7_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_6_7, CM_RGAM_RAMB_EXP_REGION7_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_8_9, CM_RGAM_RAMB_EXP_REGION8_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_8_9, CM_RGAM_RAMB_EXP_REGION8_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_8_9, CM_RGAM_RAMB_EXP_REGION9_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_8_9, CM_RGAM_RAMB_EXP_REGION9_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_10_11, CM_RGAM_RAMB_EXP_REGION10_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_10_11, CM_RGAM_RAMB_EXP_REGION10_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_10_11, CM_RGAM_RAMB_EXP_REGION11_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_10_11, CM_RGAM_RAMB_EXP_REGION11_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_12_13, CM_RGAM_RAMB_EXP_REGION12_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_12_13, CM_RGAM_RAMB_EXP_REGION12_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_12_13, CM_RGAM_RAMB_EXP_REGION13_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_12_13, CM_RGAM_RAMB_EXP_REGION13_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_14_15, CM_RGAM_RAMB_EXP_REGION14_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_14_15, CM_RGAM_RAMB_EXP_REGION14_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_14_15, CM_RGAM_RAMB_EXP_REGION15_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_14_15, CM_RGAM_RAMB_EXP_REGION15_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_16_17, CM_RGAM_RAMB_EXP_REGION16_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_16_17, CM_RGAM_RAMB_EXP_REGION16_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_16_17, CM_RGAM_RAMB_EXP_REGION17_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_16_17, CM_RGAM_RAMB_EXP_REGION17_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_18_19, CM_RGAM_RAMB_EXP_REGION18_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_18_19, CM_RGAM_RAMB_EXP_REGION18_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_18_19, CM_RGAM_RAMB_EXP_REGION19_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_18_19, CM_RGAM_RAMB_EXP_REGION19_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_20_21, CM_RGAM_RAMB_EXP_REGION20_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_20_21, CM_RGAM_RAMB_EXP_REGION20_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_20_21, CM_RGAM_RAMB_EXP_REGION21_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_20_21, CM_RGAM_RAMB_EXP_REGION21_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_22_23, CM_RGAM_RAMB_EXP_REGION22_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_22_23, CM_RGAM_RAMB_EXP_REGION22_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_22_23, CM_RGAM_RAMB_EXP_REGION23_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_22_23, CM_RGAM_RAMB_EXP_REGION23_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_24_25, CM_RGAM_RAMB_EXP_REGION24_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_24_25, CM_RGAM_RAMB_EXP_REGION24_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_24_25, CM_RGAM_RAMB_EXP_REGION25_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_24_25, CM_RGAM_RAMB_EXP_REGION25_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_26_27, CM_RGAM_RAMB_EXP_REGION26_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_26_27, CM_RGAM_RAMB_EXP_REGION26_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_26_27, CM_RGAM_RAMB_EXP_REGION27_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_26_27, CM_RGAM_RAMB_EXP_REGION27_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_28_29, CM_RGAM_RAMB_EXP_REGION28_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_28_29, CM_RGAM_RAMB_EXP_REGION28_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_28_29, CM_RGAM_RAMB_EXP_REGION29_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_28_29, CM_RGAM_RAMB_EXP_REGION29_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_30_31, CM_RGAM_RAMB_EXP_REGION30_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_30_31, CM_RGAM_RAMB_EXP_REGION30_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_30_31, CM_RGAM_RAMB_EXP_REGION31_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_30_31, CM_RGAM_RAMB_EXP_REGION31_NUM_SEGMENTS, mask_sh), \ TF_SF(CM0_CM_RGAM_RAMB_REGION_32_33, CM_RGAM_RAMB_EXP_REGION32_LUT_OFFSET, mask_sh), \ TF_SF(CM0_CM_RGAM_RAMB_REGION_32_33, CM_RGAM_RAMB_EXP_REGION32_NUM_SEGMENTS, mask_sh), \ TF_SF(CM0_CM_RGAM_RAMB_REGION_32_33, CM_RGAM_RAMB_EXP_REGION33_LUT_OFFSET, mask_sh), \ @@ -587,66 +437,6 @@ TF_SF(CM0_CM_RGAM_RAMA_REGION_0_1, CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS, mask_sh), \ TF_SF(CM0_CM_RGAM_RAMA_REGION_0_1, CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET, mask_sh), \ TF_SF(CM0_CM_RGAM_RAMA_REGION_0_1, CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_2_3, CM_RGAM_RAMA_EXP_REGION2_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_2_3, CM_RGAM_RAMA_EXP_REGION2_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_2_3, CM_RGAM_RAMA_EXP_REGION3_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_2_3, CM_RGAM_RAMA_EXP_REGION3_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_4_5, CM_RGAM_RAMA_EXP_REGION4_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_4_5, CM_RGAM_RAMA_EXP_REGION4_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_4_5, CM_RGAM_RAMA_EXP_REGION5_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_4_5, CM_RGAM_RAMA_EXP_REGION5_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_6_7, CM_RGAM_RAMA_EXP_REGION6_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_6_7, CM_RGAM_RAMA_EXP_REGION6_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_6_7, CM_RGAM_RAMA_EXP_REGION7_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_6_7, CM_RGAM_RAMA_EXP_REGION7_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_8_9, CM_RGAM_RAMA_EXP_REGION8_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_8_9, CM_RGAM_RAMA_EXP_REGION8_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_8_9, CM_RGAM_RAMA_EXP_REGION9_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_8_9, CM_RGAM_RAMA_EXP_REGION9_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_10_11, CM_RGAM_RAMA_EXP_REGION10_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_10_11, CM_RGAM_RAMA_EXP_REGION10_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_10_11, CM_RGAM_RAMA_EXP_REGION11_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_10_11, CM_RGAM_RAMA_EXP_REGION11_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_12_13, CM_RGAM_RAMA_EXP_REGION12_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_12_13, CM_RGAM_RAMA_EXP_REGION12_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_12_13, CM_RGAM_RAMA_EXP_REGION13_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_12_13, CM_RGAM_RAMA_EXP_REGION13_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_14_15, CM_RGAM_RAMA_EXP_REGION14_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_14_15, CM_RGAM_RAMA_EXP_REGION14_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_14_15, CM_RGAM_RAMA_EXP_REGION15_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_14_15, CM_RGAM_RAMA_EXP_REGION15_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_16_17, CM_RGAM_RAMA_EXP_REGION16_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_16_17, CM_RGAM_RAMA_EXP_REGION16_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_16_17, CM_RGAM_RAMA_EXP_REGION17_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_16_17, CM_RGAM_RAMA_EXP_REGION17_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_18_19, CM_RGAM_RAMA_EXP_REGION18_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_18_19, CM_RGAM_RAMA_EXP_REGION18_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_18_19, CM_RGAM_RAMA_EXP_REGION19_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_18_19, CM_RGAM_RAMA_EXP_REGION19_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_20_21, CM_RGAM_RAMA_EXP_REGION20_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_20_21, CM_RGAM_RAMA_EXP_REGION20_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_20_21, CM_RGAM_RAMA_EXP_REGION21_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_20_21, CM_RGAM_RAMA_EXP_REGION21_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_22_23, CM_RGAM_RAMA_EXP_REGION22_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_22_23, CM_RGAM_RAMA_EXP_REGION22_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_22_23, CM_RGAM_RAMA_EXP_REGION23_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_22_23, CM_RGAM_RAMA_EXP_REGION23_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_24_25, CM_RGAM_RAMA_EXP_REGION24_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_24_25, CM_RGAM_RAMA_EXP_REGION24_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_24_25, CM_RGAM_RAMA_EXP_REGION25_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_24_25, CM_RGAM_RAMA_EXP_REGION25_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_26_27, CM_RGAM_RAMA_EXP_REGION26_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_26_27, CM_RGAM_RAMA_EXP_REGION26_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_26_27, CM_RGAM_RAMA_EXP_REGION27_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_26_27, CM_RGAM_RAMA_EXP_REGION27_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_28_29, CM_RGAM_RAMA_EXP_REGION28_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_28_29, CM_RGAM_RAMA_EXP_REGION28_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_28_29, CM_RGAM_RAMA_EXP_REGION29_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_28_29, CM_RGAM_RAMA_EXP_REGION29_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_30_31, CM_RGAM_RAMA_EXP_REGION30_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_30_31, CM_RGAM_RAMA_EXP_REGION30_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_30_31, CM_RGAM_RAMA_EXP_REGION31_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_30_31, CM_RGAM_RAMA_EXP_REGION31_NUM_SEGMENTS, mask_sh), \ TF_SF(CM0_CM_RGAM_RAMA_REGION_32_33, CM_RGAM_RAMA_EXP_REGION32_LUT_OFFSET, mask_sh), \ TF_SF(CM0_CM_RGAM_RAMA_REGION_32_33, CM_RGAM_RAMA_EXP_REGION32_NUM_SEGMENTS, mask_sh), \ TF_SF(CM0_CM_RGAM_RAMA_REGION_32_33, CM_RGAM_RAMA_EXP_REGION33_LUT_OFFSET, mask_sh), \ @@ -816,66 +606,6 @@ type CM_RGAM_RAMB_EXP_REGION0_NUM_SEGMENTS; \ type CM_RGAM_RAMB_EXP_REGION1_LUT_OFFSET; \ type CM_RGAM_RAMB_EXP_REGION1_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION2_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION2_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION3_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION3_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION4_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION4_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION5_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION5_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION6_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION6_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION7_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION7_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION8_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION8_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION9_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION9_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION10_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION10_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION11_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION11_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION12_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION12_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION13_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION13_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION14_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION14_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION15_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION15_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION16_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION16_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION17_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION17_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION18_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION18_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION19_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION19_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION20_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION20_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION21_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION21_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION22_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION22_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION23_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION23_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION24_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION24_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION25_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION25_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION26_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION26_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION27_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION27_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION28_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION28_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION29_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION29_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION30_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION30_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION31_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION31_NUM_SEGMENTS; \ type CM_RGAM_RAMB_EXP_REGION32_LUT_OFFSET; \ type CM_RGAM_RAMB_EXP_REGION32_NUM_SEGMENTS; \ type CM_RGAM_RAMB_EXP_REGION33_LUT_OFFSET; \ @@ -902,66 +632,6 @@ type CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS; \ type CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET; \ type CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION2_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION2_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION3_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION3_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION4_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION4_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION5_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION5_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION6_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION6_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION7_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION7_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION8_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION8_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION9_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION9_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION10_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION10_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION11_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION11_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION12_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION12_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION13_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION13_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION14_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION14_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION15_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION15_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION16_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION16_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION17_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION17_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION18_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION18_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION19_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION19_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION20_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION20_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION21_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION21_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION22_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION22_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION23_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION23_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION24_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION24_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION25_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION25_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION26_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION26_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION27_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION27_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION28_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION28_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION29_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION29_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION30_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION30_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION31_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION31_NUM_SEGMENTS; \ type CM_RGAM_RAMA_EXP_REGION32_LUT_OFFSET; \ type CM_RGAM_RAMA_EXP_REGION32_NUM_SEGMENTS; \ type CM_RGAM_RAMA_EXP_REGION33_LUT_OFFSET; \ @@ -1370,30 +1040,6 @@ type CM_DGAM_RAMB_EXP_REGION0_NUM_SEGMENTS; \ type CM_DGAM_RAMB_EXP_REGION1_LUT_OFFSET; \ type CM_DGAM_RAMB_EXP_REGION1_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION2_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION2_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION3_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION3_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION4_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION4_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION5_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION5_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION6_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION6_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION7_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION7_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION8_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION8_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION9_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION9_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION10_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION10_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION11_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION11_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION12_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION12_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION13_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION13_NUM_SEGMENTS; \ type CM_DGAM_RAMB_EXP_REGION14_LUT_OFFSET; \ type CM_DGAM_RAMB_EXP_REGION14_NUM_SEGMENTS; \ type CM_DGAM_RAMB_EXP_REGION15_LUT_OFFSET; \ @@ -1420,30 +1066,6 @@ type CM_DGAM_RAMA_EXP_REGION0_NUM_SEGMENTS; \ type CM_DGAM_RAMA_EXP_REGION1_LUT_OFFSET; \ type CM_DGAM_RAMA_EXP_REGION1_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION2_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION2_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION3_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION3_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION4_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION4_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION5_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION5_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION6_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION6_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION7_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION7_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION8_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION8_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION9_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION9_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION10_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION10_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION11_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION11_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION12_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION12_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION13_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION13_NUM_SEGMENTS; \ type CM_DGAM_RAMA_EXP_REGION14_LUT_OFFSET; \ type CM_DGAM_RAMA_EXP_REGION14_NUM_SEGMENTS; \ type CM_DGAM_RAMA_EXP_REGION15_LUT_OFFSET; \ @@ -1565,21 +1187,6 @@ struct dcn_dpp_registers { uint32_t CM_RGAM_RAMB_END_CNTL1_R; uint32_t CM_RGAM_RAMB_END_CNTL2_R; uint32_t CM_RGAM_RAMB_REGION_0_1; - uint32_t CM_RGAM_RAMB_REGION_2_3; - uint32_t CM_RGAM_RAMB_REGION_4_5; - uint32_t CM_RGAM_RAMB_REGION_6_7; - uint32_t CM_RGAM_RAMB_REGION_8_9; - uint32_t CM_RGAM_RAMB_REGION_10_11; - uint32_t CM_RGAM_RAMB_REGION_12_13; - uint32_t CM_RGAM_RAMB_REGION_14_15; - uint32_t CM_RGAM_RAMB_REGION_16_17; - uint32_t CM_RGAM_RAMB_REGION_18_19; - uint32_t CM_RGAM_RAMB_REGION_20_21; - uint32_t CM_RGAM_RAMB_REGION_22_23; - uint32_t CM_RGAM_RAMB_REGION_24_25; - uint32_t CM_RGAM_RAMB_REGION_26_27; - uint32_t CM_RGAM_RAMB_REGION_28_29; - uint32_t CM_RGAM_RAMB_REGION_30_31; uint32_t CM_RGAM_RAMB_REGION_32_33; uint32_t CM_RGAM_RAMA_START_CNTL_B; uint32_t CM_RGAM_RAMA_START_CNTL_G; @@ -1594,21 +1201,6 @@ struct dcn_dpp_registers { uint32_t CM_RGAM_RAMA_END_CNTL1_R; uint32_t CM_RGAM_RAMA_END_CNTL2_R; uint32_t CM_RGAM_RAMA_REGION_0_1; - uint32_t CM_RGAM_RAMA_REGION_2_3; - uint32_t CM_RGAM_RAMA_REGION_4_5; - uint32_t CM_RGAM_RAMA_REGION_6_7; - uint32_t CM_RGAM_RAMA_REGION_8_9; - uint32_t CM_RGAM_RAMA_REGION_10_11; - uint32_t CM_RGAM_RAMA_REGION_12_13; - uint32_t CM_RGAM_RAMA_REGION_14_15; - uint32_t CM_RGAM_RAMA_REGION_16_17; - uint32_t CM_RGAM_RAMA_REGION_18_19; - uint32_t CM_RGAM_RAMA_REGION_20_21; - uint32_t CM_RGAM_RAMA_REGION_22_23; - uint32_t CM_RGAM_RAMA_REGION_24_25; - uint32_t CM_RGAM_RAMA_REGION_26_27; - uint32_t CM_RGAM_RAMA_REGION_28_29; - uint32_t CM_RGAM_RAMA_REGION_30_31; uint32_t CM_RGAM_RAMA_REGION_32_33; uint32_t CM_RGAM_CONTROL; uint32_t OBUF_CONTROL; @@ -1743,12 +1335,6 @@ struct dcn_dpp_registers { uint32_t CM_DGAM_RAMB_END_CNTL1_R; uint32_t CM_DGAM_RAMB_END_CNTL2_R; uint32_t CM_DGAM_RAMB_REGION_0_1; - uint32_t CM_DGAM_RAMB_REGION_2_3; - uint32_t CM_DGAM_RAMB_REGION_4_5; - uint32_t CM_DGAM_RAMB_REGION_6_7; - uint32_t CM_DGAM_RAMB_REGION_8_9; - uint32_t CM_DGAM_RAMB_REGION_10_11; - uint32_t CM_DGAM_RAMB_REGION_12_13; uint32_t CM_DGAM_RAMB_REGION_14_15; uint32_t CM_DGAM_RAMA_START_CNTL_B; uint32_t CM_DGAM_RAMA_START_CNTL_G; @@ -1763,12 +1349,6 @@ struct dcn_dpp_registers { uint32_t CM_DGAM_RAMA_END_CNTL1_R; uint32_t CM_DGAM_RAMA_END_CNTL2_R; uint32_t CM_DGAM_RAMA_REGION_0_1; - uint32_t CM_DGAM_RAMA_REGION_2_3; - uint32_t CM_DGAM_RAMA_REGION_4_5; - uint32_t CM_DGAM_RAMA_REGION_6_7; - uint32_t CM_DGAM_RAMA_REGION_8_9; - uint32_t CM_DGAM_RAMA_REGION_10_11; - uint32_t CM_DGAM_RAMA_REGION_12_13; uint32_t CM_DGAM_RAMA_REGION_14_15; uint32_t CM_DGAM_LUT_WRITE_EN_MASK; uint32_t CM_DGAM_LUT_INDEX; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c index 81620241a978..01b1c0ee0110 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c @@ -453,331 +453,145 @@ void dcn10_dpp_cm_configure_regamma_lut( REG_SET(CM_RGAM_LUT_INDEX, 0, CM_RGAM_LUT_INDEX, 0); } -/*program re gamma RAM A*/ -void dcn10_dpp_cm_program_regamma_luta_settings( +struct cm_gam_ram_reg { + uint32_t start_cntl_b; + uint32_t start_cntl_g; + uint32_t start_cntl_r; + uint32_t start_slope_cntl_b; + uint32_t start_slope_cntl_g; + uint32_t start_slope_cntl_r; + uint32_t start_end_cntl1_b; + uint32_t start_end_cntl2_b; + uint32_t start_end_cntl1_g; + uint32_t start_end_cntl2_g; + uint32_t start_end_cntl1_r; + uint32_t start_end_cntl2_r; + uint32_t region_start; + uint32_t region_end; +}; + +static void dpp_cm_program_region_lut( struct transform *xfm_base, - const struct pwl_params *params) + const struct pwl_params *params, + const struct cm_gam_ram_reg *reg) { - const struct gamma_curve *curve; struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + uint32_t reg_region_cur; + unsigned int i = 0; + +#undef REG +#define REG(reg) reg - REG_SET_2(CM_RGAM_RAMA_START_CNTL_B, 0, + REG_SET_2(reg->start_cntl_b, 0, CM_RGAM_RAMA_EXP_REGION_START_B, params->arr_points[0].custom_float_x, CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_B, 0); - REG_SET_2(CM_RGAM_RAMA_START_CNTL_G, 0, + REG_SET_2(reg->start_cntl_g, 0, CM_RGAM_RAMA_EXP_REGION_START_G, params->arr_points[0].custom_float_x, CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_G, 0); - REG_SET_2(CM_RGAM_RAMA_START_CNTL_R, 0, + REG_SET_2(reg->start_cntl_r, 0, CM_RGAM_RAMA_EXP_REGION_START_R, params->arr_points[0].custom_float_x, CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_R, 0); - REG_SET(CM_RGAM_RAMA_SLOPE_CNTL_B, 0, + REG_SET(reg->start_slope_cntl_b, 0, CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B, params->arr_points[0].custom_float_slope); - REG_SET(CM_RGAM_RAMA_SLOPE_CNTL_G, 0, + REG_SET(reg->start_slope_cntl_g, 0, CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G, params->arr_points[0].custom_float_slope); - REG_SET(CM_RGAM_RAMA_SLOPE_CNTL_R, 0, + REG_SET(reg->start_slope_cntl_r, 0, CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R, params->arr_points[0].custom_float_slope); - REG_SET(CM_RGAM_RAMA_END_CNTL1_B, 0, + REG_SET(reg->start_end_cntl1_b, 0, CM_RGAM_RAMA_EXP_REGION_END_B, params->arr_points[1].custom_float_x); - REG_SET_2(CM_RGAM_RAMA_END_CNTL2_B, 0, + REG_SET_2(reg->start_end_cntl2_b, 0, CM_RGAM_RAMA_EXP_REGION_END_SLOPE_B, params->arr_points[1].custom_float_slope, CM_RGAM_RAMA_EXP_REGION_END_BASE_B, params->arr_points[1].custom_float_y); - REG_SET(CM_RGAM_RAMA_END_CNTL1_G, 0, + REG_SET(reg->start_end_cntl1_g, 0, CM_RGAM_RAMA_EXP_REGION_END_G, params->arr_points[1].custom_float_x); - REG_SET_2(CM_RGAM_RAMA_END_CNTL2_G, 0, + REG_SET_2(reg->start_end_cntl2_g, 0, CM_RGAM_RAMA_EXP_REGION_END_SLOPE_G, params->arr_points[1].custom_float_slope, CM_RGAM_RAMA_EXP_REGION_END_BASE_G, params->arr_points[1].custom_float_y); - REG_SET(CM_RGAM_RAMA_END_CNTL1_R, 0, + REG_SET(reg->start_end_cntl1_r, 0, CM_RGAM_RAMA_EXP_REGION_END_R, params->arr_points[1].custom_float_x); - REG_SET_2(CM_RGAM_RAMA_END_CNTL2_R, 0, + REG_SET_2(reg->start_end_cntl2_r, 0, CM_RGAM_RAMA_EXP_REGION_END_SLOPE_R, params->arr_points[1].custom_float_slope, CM_RGAM_RAMA_EXP_REGION_END_BASE_R, params->arr_points[1].custom_float_y); - curve = params->arr_curve_points; - REG_SET_4(CM_RGAM_RAMA_REGION_0_1, 0, - CM_RGAM_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_2_3, 0, - CM_RGAM_RAMA_EXP_REGION2_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION3_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_4_5, 0, - CM_RGAM_RAMA_EXP_REGION4_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION5_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_6_7, 0, - CM_RGAM_RAMA_EXP_REGION6_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION7_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_8_9, 0, - CM_RGAM_RAMA_EXP_REGION8_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION9_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_10_11, 0, - CM_RGAM_RAMA_EXP_REGION10_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION11_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_12_13, 0, - CM_RGAM_RAMA_EXP_REGION12_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION13_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_14_15, 0, - CM_RGAM_RAMA_EXP_REGION14_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION15_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_16_17, 0, - CM_RGAM_RAMA_EXP_REGION16_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION16_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION17_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION17_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_18_19, 0, - CM_RGAM_RAMA_EXP_REGION18_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION18_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION19_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION19_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_20_21, 0, - CM_RGAM_RAMA_EXP_REGION20_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION20_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION21_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION21_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_22_23, 0, - CM_RGAM_RAMA_EXP_REGION22_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION22_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION23_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION23_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_24_25, 0, - CM_RGAM_RAMA_EXP_REGION24_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION24_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION25_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION25_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_26_27, 0, - CM_RGAM_RAMA_EXP_REGION26_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION26_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION27_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION27_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_28_29, 0, - CM_RGAM_RAMA_EXP_REGION28_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION28_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION29_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION29_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_30_31, 0, - CM_RGAM_RAMA_EXP_REGION30_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION30_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION31_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION31_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_32_33, 0, - CM_RGAM_RAMA_EXP_REGION32_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION32_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION33_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION33_NUM_SEGMENTS, curve[1].segments_num); + for (reg_region_cur = reg->region_start; + reg_region_cur <= reg->region_end; + reg_region_cur++) { + + const struct gamma_curve *curve0 = &(params->arr_curve_points[2 * i]); + const struct gamma_curve *curve1 = &(params->arr_curve_points[(2 * i) + 1]); + + REG_SET_4(reg_region_cur, 0, + CM_RGAM_RAMA_EXP_REGION0_LUT_OFFSET, curve0->offset, + CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS, curve0->segments_num, + CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET, curve1->offset, + CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS, curve1->segments_num); + + i++; + } + +#undef REG +#define REG(reg)\ + xfm->tf_regs->reg + } -/*program re gamma RAM B*/ -void dcn10_dpp_cm_program_regamma_lutb_settings( + + +/*program re gamma RAM A*/ +void dcn10_dpp_cm_program_regamma_luta_settings( struct transform *xfm_base, const struct pwl_params *params) { - const struct gamma_curve *curve; struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct cm_gam_ram_reg gam_regs; + + gam_regs.start_cntl_b = REG(CM_RGAM_RAMA_START_CNTL_B); + gam_regs.start_cntl_g = REG(CM_RGAM_RAMA_START_CNTL_G); + gam_regs.start_cntl_r = REG(CM_RGAM_RAMA_START_CNTL_R); + gam_regs.start_slope_cntl_b = REG(CM_RGAM_RAMA_SLOPE_CNTL_B); + gam_regs.start_slope_cntl_g = REG(CM_RGAM_RAMA_SLOPE_CNTL_G); + gam_regs.start_slope_cntl_r = REG(CM_RGAM_RAMA_SLOPE_CNTL_R); + gam_regs.start_end_cntl1_b = REG(CM_RGAM_RAMA_END_CNTL1_B); + gam_regs.start_end_cntl2_b = REG(CM_RGAM_RAMA_END_CNTL2_B); + gam_regs.start_end_cntl1_g = REG(CM_RGAM_RAMA_END_CNTL1_G); + gam_regs.start_end_cntl2_g = REG(CM_RGAM_RAMA_END_CNTL2_G); + gam_regs.start_end_cntl1_r = REG(CM_RGAM_RAMA_END_CNTL1_R); + gam_regs.start_end_cntl2_r = REG(CM_RGAM_RAMA_END_CNTL2_R); + gam_regs.region_start = REG(CM_RGAM_RAMA_REGION_0_1); + gam_regs.region_end = REG(CM_RGAM_RAMA_REGION_32_33); + + dpp_cm_program_region_lut(xfm_base, params, &gam_regs); - REG_SET_2(CM_RGAM_RAMB_START_CNTL_B, 0, - CM_RGAM_RAMB_EXP_REGION_START_B, params->arr_points[0].custom_float_x, - CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B, 0); - REG_SET_2(CM_RGAM_RAMB_START_CNTL_G, 0, - CM_RGAM_RAMB_EXP_REGION_START_G, params->arr_points[0].custom_float_x, - CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_G, 0); - REG_SET_2(CM_RGAM_RAMB_START_CNTL_R, 0, - CM_RGAM_RAMB_EXP_REGION_START_R, params->arr_points[0].custom_float_x, - CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_R, 0); - - REG_SET(CM_RGAM_RAMB_SLOPE_CNTL_B, 0, - CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B, params->arr_points[0].custom_float_slope); - REG_SET(CM_RGAM_RAMB_SLOPE_CNTL_G, 0, - CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_G, params->arr_points[0].custom_float_slope); - REG_SET(CM_RGAM_RAMB_SLOPE_CNTL_R, 0, - CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_R, params->arr_points[0].custom_float_slope); - - REG_SET(CM_RGAM_RAMB_END_CNTL1_B, 0, - CM_RGAM_RAMB_EXP_REGION_END_B, params->arr_points[1].custom_float_x); - REG_SET_2(CM_RGAM_RAMB_END_CNTL2_B, 0, - CM_RGAM_RAMB_EXP_REGION_END_SLOPE_B, params->arr_points[1].custom_float_slope, - CM_RGAM_RAMB_EXP_REGION_END_BASE_B, params->arr_points[1].custom_float_y); - - REG_SET(CM_RGAM_RAMB_END_CNTL1_G, 0, - CM_RGAM_RAMB_EXP_REGION_END_G, params->arr_points[1].custom_float_x); - REG_SET_2(CM_RGAM_RAMB_END_CNTL2_G, 0, - CM_RGAM_RAMB_EXP_REGION_END_SLOPE_G, params->arr_points[1].custom_float_slope, - CM_RGAM_RAMB_EXP_REGION_END_BASE_G, params->arr_points[1].custom_float_y); - - REG_SET(CM_RGAM_RAMB_END_CNTL1_R, 0, - CM_RGAM_RAMB_EXP_REGION_END_R, params->arr_points[1].custom_float_x); - REG_SET_2(CM_RGAM_RAMB_END_CNTL2_R, 0, - CM_RGAM_RAMB_EXP_REGION_END_SLOPE_R, params->arr_points[1].custom_float_slope, - CM_RGAM_RAMB_EXP_REGION_END_BASE_R, params->arr_points[1].custom_float_y); - - curve = params->arr_curve_points; - REG_SET_4(CM_RGAM_RAMB_REGION_0_1, 0, - CM_RGAM_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_2_3, 0, - CM_RGAM_RAMB_EXP_REGION2_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION3_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_4_5, 0, - CM_RGAM_RAMB_EXP_REGION4_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION5_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_6_7, 0, - CM_RGAM_RAMB_EXP_REGION6_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION7_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_8_9, 0, - CM_RGAM_RAMB_EXP_REGION8_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION9_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_10_11, 0, - CM_RGAM_RAMB_EXP_REGION10_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION11_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_12_13, 0, - CM_RGAM_RAMB_EXP_REGION12_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION13_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_14_15, 0, - CM_RGAM_RAMB_EXP_REGION14_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION15_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_16_17, 0, - CM_RGAM_RAMB_EXP_REGION16_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION16_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION17_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION17_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_18_19, 0, - CM_RGAM_RAMB_EXP_REGION18_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION18_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION19_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION19_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_20_21, 0, - CM_RGAM_RAMB_EXP_REGION20_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION20_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION21_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION21_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_22_23, 0, - CM_RGAM_RAMB_EXP_REGION22_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION22_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION23_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION23_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_24_25, 0, - CM_RGAM_RAMB_EXP_REGION24_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION24_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION25_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION25_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_26_27, 0, - CM_RGAM_RAMB_EXP_REGION26_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION26_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION27_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION27_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_28_29, 0, - CM_RGAM_RAMB_EXP_REGION28_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION28_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION29_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION29_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_30_31, 0, - CM_RGAM_RAMB_EXP_REGION30_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION30_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION31_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION31_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_32_33, 0, - CM_RGAM_RAMB_EXP_REGION32_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION32_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION33_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION33_NUM_SEGMENTS, curve[1].segments_num); +} +/*program re gamma RAM B*/ +void dcn10_dpp_cm_program_regamma_lutb_settings( + struct transform *xfm_base, + const struct pwl_params *params) +{ + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct cm_gam_ram_reg gam_regs; + + gam_regs.start_cntl_b = REG(CM_RGAM_RAMB_START_CNTL_B); + gam_regs.start_cntl_g = REG(CM_RGAM_RAMB_START_CNTL_G); + gam_regs.start_cntl_r = REG(CM_RGAM_RAMB_START_CNTL_R); + gam_regs.start_slope_cntl_b = REG(CM_RGAM_RAMB_SLOPE_CNTL_B); + gam_regs.start_slope_cntl_g = REG(CM_RGAM_RAMB_SLOPE_CNTL_G); + gam_regs.start_slope_cntl_r = REG(CM_RGAM_RAMB_SLOPE_CNTL_R); + gam_regs.start_end_cntl1_b = REG(CM_RGAM_RAMB_END_CNTL1_B); + gam_regs.start_end_cntl2_b = REG(CM_RGAM_RAMB_END_CNTL2_B); + gam_regs.start_end_cntl1_g = REG(CM_RGAM_RAMB_END_CNTL1_G); + gam_regs.start_end_cntl2_g = REG(CM_RGAM_RAMB_END_CNTL2_G); + gam_regs.start_end_cntl1_r = REG(CM_RGAM_RAMB_END_CNTL1_R); + gam_regs.start_end_cntl2_r = REG(CM_RGAM_RAMB_END_CNTL2_R); + gam_regs.region_start = REG(CM_RGAM_RAMB_REGION_0_1); + gam_regs.region_end = REG(CM_RGAM_RAMB_REGION_32_33); + + dpp_cm_program_region_lut(xfm_base, params, &gam_regs); } void ippn10_program_input_csc( @@ -874,106 +688,25 @@ void ippn10_program_degamma_lutb_settings( struct transform *xfm_base, const struct pwl_params *params) { - const struct gamma_curve *curve; struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); - - REG_SET_2(CM_DGAM_RAMB_START_CNTL_B, 0, - CM_DGAM_RAMB_EXP_REGION_START_B, params->arr_points[0].custom_float_x, - CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_B, 0); - - REG_SET_2(CM_DGAM_RAMB_START_CNTL_G, 0, - CM_DGAM_RAMB_EXP_REGION_START_G, params->arr_points[0].custom_float_x, - CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_G, 0); - - REG_SET_2(CM_DGAM_RAMB_START_CNTL_R, 0, - CM_DGAM_RAMB_EXP_REGION_START_R, params->arr_points[0].custom_float_x, - CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_R, 0); - - REG_SET(CM_DGAM_RAMB_SLOPE_CNTL_B, 0, - CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B, params->arr_points[0].custom_float_slope); - - REG_SET(CM_DGAM_RAMB_SLOPE_CNTL_G, 0, - CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_G, params->arr_points[0].custom_float_slope); - - REG_SET(CM_DGAM_RAMB_SLOPE_CNTL_R, 0, - CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_R, params->arr_points[0].custom_float_slope); - - REG_SET(CM_DGAM_RAMB_END_CNTL1_B, 0, - CM_DGAM_RAMB_EXP_REGION_END_B, params->arr_points[1].custom_float_x); - - REG_SET_2(CM_DGAM_RAMB_END_CNTL2_B, 0, - CM_DGAM_RAMB_EXP_REGION_END_SLOPE_B, params->arr_points[1].custom_float_y, - CM_DGAM_RAMB_EXP_REGION_END_BASE_B, params->arr_points[2].custom_float_slope); - - REG_SET(CM_DGAM_RAMB_END_CNTL1_G, 0, - CM_DGAM_RAMB_EXP_REGION_END_G, params->arr_points[1].custom_float_x); - - REG_SET_2(CM_DGAM_RAMB_END_CNTL2_G, 0, - CM_DGAM_RAMB_EXP_REGION_END_SLOPE_G, params->arr_points[1].custom_float_y, - CM_DGAM_RAMB_EXP_REGION_END_BASE_G, params->arr_points[2].custom_float_slope); - - REG_SET(CM_DGAM_RAMB_END_CNTL1_R, 0, - CM_DGAM_RAMB_EXP_REGION_END_R, params->arr_points[1].custom_float_x); - - REG_SET_2(CM_DGAM_RAMB_END_CNTL2_R, 0, - CM_DGAM_RAMB_EXP_REGION_END_SLOPE_R, params->arr_points[1].custom_float_y, - CM_DGAM_RAMB_EXP_REGION_END_BASE_R, params->arr_points[2].custom_float_slope); - - curve = params->arr_curve_points; - REG_SET_4(CM_DGAM_RAMB_REGION_0_1, 0, - CM_DGAM_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMB_REGION_2_3, 0, - CM_DGAM_RAMB_EXP_REGION2_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMB_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMB_EXP_REGION3_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMB_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMB_REGION_4_5, 0, - CM_DGAM_RAMB_EXP_REGION4_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMB_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMB_EXP_REGION5_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMB_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMB_REGION_6_7, 0, - CM_DGAM_RAMB_EXP_REGION6_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMB_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMB_EXP_REGION7_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMB_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMB_REGION_8_9, 0, - CM_DGAM_RAMB_EXP_REGION8_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMB_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMB_EXP_REGION9_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMB_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMB_REGION_10_11, 0, - CM_DGAM_RAMB_EXP_REGION10_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMB_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMB_EXP_REGION11_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMB_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMB_REGION_12_13, 0, - CM_DGAM_RAMB_EXP_REGION12_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMB_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMB_EXP_REGION13_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMB_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMB_REGION_14_15, 0, - CM_DGAM_RAMB_EXP_REGION14_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMB_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMB_EXP_REGION15_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMB_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num); + struct cm_gam_ram_reg gam_regs; + + gam_regs.start_cntl_b = REG(CM_DGAM_RAMB_START_CNTL_B); + gam_regs.start_cntl_g = REG(CM_DGAM_RAMB_START_CNTL_G); + gam_regs.start_cntl_r = REG(CM_DGAM_RAMB_START_CNTL_R); + gam_regs.start_slope_cntl_b = REG(CM_DGAM_RAMB_SLOPE_CNTL_B); + gam_regs.start_slope_cntl_g = REG(CM_DGAM_RAMB_SLOPE_CNTL_G); + gam_regs.start_slope_cntl_r = REG(CM_DGAM_RAMB_SLOPE_CNTL_R); + gam_regs.start_end_cntl1_b = REG(CM_DGAM_RAMB_END_CNTL1_B); + gam_regs.start_end_cntl2_b = REG(CM_DGAM_RAMB_END_CNTL2_B); + gam_regs.start_end_cntl1_g = REG(CM_DGAM_RAMB_END_CNTL1_G); + gam_regs.start_end_cntl2_g = REG(CM_DGAM_RAMB_END_CNTL2_G); + gam_regs.start_end_cntl1_r = REG(CM_DGAM_RAMB_END_CNTL1_R); + gam_regs.start_end_cntl2_r = REG(CM_DGAM_RAMB_END_CNTL2_R); + gam_regs.region_start = REG(CM_DGAM_RAMB_REGION_0_1); + gam_regs.region_end = REG(CM_DGAM_RAMB_REGION_14_15); + + dpp_cm_program_region_lut(xfm_base, params, &gam_regs); } /*program de gamma RAM A*/ @@ -981,106 +714,25 @@ void ippn10_program_degamma_luta_settings( struct transform *xfm_base, const struct pwl_params *params) { - const struct gamma_curve *curve; struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); - - REG_SET_2(CM_DGAM_RAMA_START_CNTL_B, 0, - CM_DGAM_RAMA_EXP_REGION_START_B, params->arr_points[0].custom_float_x, - CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_B, 0); - - REG_SET_2(CM_DGAM_RAMA_START_CNTL_G, 0, - CM_DGAM_RAMA_EXP_REGION_START_G, params->arr_points[0].custom_float_x, - CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_G, 0); - - REG_SET_2(CM_DGAM_RAMA_START_CNTL_R, 0, - CM_DGAM_RAMA_EXP_REGION_START_R, params->arr_points[0].custom_float_x, - CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_R, 0); - - REG_SET(CM_DGAM_RAMA_SLOPE_CNTL_B, 0, - CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B, params->arr_points[0].custom_float_slope); - - REG_SET(CM_DGAM_RAMA_SLOPE_CNTL_G, 0, - CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G, params->arr_points[0].custom_float_slope); - - REG_SET(CM_DGAM_RAMA_SLOPE_CNTL_R, 0, - CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R, params->arr_points[0].custom_float_slope); - - REG_SET(CM_DGAM_RAMA_END_CNTL1_B, 0, - CM_DGAM_RAMA_EXP_REGION_END_B, params->arr_points[1].custom_float_x); - - REG_SET_2(CM_DGAM_RAMA_END_CNTL2_B, 0, - CM_DGAM_RAMA_EXP_REGION_END_SLOPE_B, params->arr_points[1].custom_float_y, - CM_DGAM_RAMA_EXP_REGION_END_BASE_B, params->arr_points[2].custom_float_slope); - - REG_SET(CM_DGAM_RAMA_END_CNTL1_G, 0, - CM_DGAM_RAMA_EXP_REGION_END_G, params->arr_points[1].custom_float_x); - - REG_SET_2(CM_DGAM_RAMA_END_CNTL2_G, 0, - CM_DGAM_RAMA_EXP_REGION_END_SLOPE_G, params->arr_points[1].custom_float_y, - CM_DGAM_RAMA_EXP_REGION_END_BASE_G, params->arr_points[2].custom_float_slope); - - REG_SET(CM_DGAM_RAMA_END_CNTL1_R, 0, - CM_DGAM_RAMA_EXP_REGION_END_R, params->arr_points[1].custom_float_x); - - REG_SET_2(CM_DGAM_RAMA_END_CNTL2_R, 0, - CM_DGAM_RAMA_EXP_REGION_END_SLOPE_R, params->arr_points[1].custom_float_y, - CM_DGAM_RAMA_EXP_REGION_END_BASE_R, params->arr_points[2].custom_float_slope); - - curve = params->arr_curve_points; - REG_SET_4(CM_DGAM_RAMA_REGION_0_1, 0, - CM_DGAM_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMA_REGION_2_3, 0, - CM_DGAM_RAMA_EXP_REGION2_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMA_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMA_EXP_REGION3_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMA_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMA_REGION_4_5, 0, - CM_DGAM_RAMA_EXP_REGION4_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMA_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMA_EXP_REGION5_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMA_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMA_REGION_6_7, 0, - CM_DGAM_RAMA_EXP_REGION6_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMA_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMA_EXP_REGION7_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMA_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMA_REGION_8_9, 0, - CM_DGAM_RAMA_EXP_REGION8_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMA_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMA_EXP_REGION9_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMA_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMA_REGION_10_11, 0, - CM_DGAM_RAMA_EXP_REGION10_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMA_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMA_EXP_REGION11_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMA_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMA_REGION_12_13, 0, - CM_DGAM_RAMA_EXP_REGION12_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMA_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMA_EXP_REGION13_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMA_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMA_REGION_14_15, 0, - CM_DGAM_RAMA_EXP_REGION14_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMA_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMA_EXP_REGION15_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMA_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num); + struct cm_gam_ram_reg gam_regs; + + gam_regs.start_cntl_b = REG(CM_DGAM_RAMA_START_CNTL_B); + gam_regs.start_cntl_g = REG(CM_DGAM_RAMA_START_CNTL_G); + gam_regs.start_cntl_r = REG(CM_DGAM_RAMA_START_CNTL_R); + gam_regs.start_slope_cntl_b = REG(CM_DGAM_RAMA_SLOPE_CNTL_B); + gam_regs.start_slope_cntl_g = REG(CM_DGAM_RAMA_SLOPE_CNTL_G); + gam_regs.start_slope_cntl_r = REG(CM_DGAM_RAMA_SLOPE_CNTL_R); + gam_regs.start_end_cntl1_b = REG(CM_DGAM_RAMA_END_CNTL1_B); + gam_regs.start_end_cntl2_b = REG(CM_DGAM_RAMA_END_CNTL2_B); + gam_regs.start_end_cntl1_g = REG(CM_DGAM_RAMA_END_CNTL1_G); + gam_regs.start_end_cntl2_g = REG(CM_DGAM_RAMA_END_CNTL2_G); + gam_regs.start_end_cntl1_r = REG(CM_DGAM_RAMA_END_CNTL1_R); + gam_regs.start_end_cntl2_r = REG(CM_DGAM_RAMA_END_CNTL2_R); + gam_regs.region_start = REG(CM_DGAM_RAMA_REGION_0_1); + gam_regs.region_end = REG(CM_DGAM_RAMA_REGION_14_15); + + dpp_cm_program_region_lut(xfm_base, params, &gam_regs); } void ippn10_power_on_degamma_lut( -- cgit From 1f0997f1555571a9c16205a851ffbce92097196d Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Mon, 28 Aug 2017 19:33:23 -0400 Subject: drm/amd/display: not override the FMT setting set by VBIOS for eDP Signed-off-by: Charlene Liu Reviewed-by: Krunoslav Kovac Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 42caad423430..3b4ca1a9217f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1082,11 +1082,14 @@ static enum dc_status apply_single_controller_ctx_to_hw( /*vbios crtc_source_selection and encoder_setup will override fmt_C*/ - pipe_ctx->stream_res.opp->funcs->opp_program_fmt( + if (pipe_ctx->stream->signal != SIGNAL_TYPE_EDP && + pipe_ctx->stream->signal != SIGNAL_TYPE_LVDS) { + /*for embedded panel, don't override VBIOS's setting*/ + pipe_ctx->stream_res.opp->funcs->opp_program_fmt( pipe_ctx->stream_res.opp, &stream->bit_depth_params, &stream->clamping); - + } if (dc_is_dp_signal(pipe_ctx->stream->signal)) pipe_ctx->stream_res.stream_enc->funcs->dp_set_stream_attribute( pipe_ctx->stream_res.stream_enc, -- cgit From 1e4cee77bbd50d6c868439bfaf8ad61b6c6fcfc3 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Mon, 28 Aug 2017 19:35:25 -0400 Subject: drm/amd/display: add backlight control in blankstream. Signed-off-by: Charlene Liu Reviewed-by: Krunoslav Kovac Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 3b4ca1a9217f..9fb0ba7e7b7d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -778,9 +778,11 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) /* blank at encoder level */ - if (dc_is_dp_signal(pipe_ctx->stream->signal)) + if (dc_is_dp_signal(pipe_ctx->stream->signal)) { + if (pipe_ctx->stream->sink->link->connector_signal == SIGNAL_TYPE_EDP) + link->link_enc->funcs->backlight_control(link->link_enc, false); pipe_ctx->stream_res.stream_enc->funcs->dp_blank(pipe_ctx->stream_res.stream_enc); - + } link->link_enc->funcs->connect_dig_be_to_fe( link->link_enc, pipe_ctx->stream_res.stream_enc->id, @@ -792,12 +794,15 @@ void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, struct dc_link_settings *link_settings) { struct encoder_unblank_param params = { { 0 } }; + struct dc_link *link = pipe_ctx->stream->sink->link; /* only 3 items below are used by unblank */ params.pixel_clk_khz = pipe_ctx->stream->timing.pix_clk_khz; params.link_settings.link_rate = link_settings->link_rate; pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(pipe_ctx->stream_res.stream_enc, ¶ms); + if (link->connector_signal == SIGNAL_TYPE_EDP) + link->link_enc->funcs->backlight_control(link->link_enc, true); } -- cgit From 07fde11f27fb4de3b63ef117593291b094a23e15 Mon Sep 17 00:00:00 2001 From: Roman Li Date: Fri, 25 Aug 2017 16:44:20 -0400 Subject: drm/amd/display: program fbc for scatter/gather Fixing screen flickering when FBC enabled on Stoney Signed-off-by: Roman Li Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dce110/dce110_compressor.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c index 2e97e5757fb9..f82c26995609 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c @@ -189,7 +189,7 @@ void dce110_compressor_enable_fbc( (!dce110_compressor_is_fbc_enabled_in_hw(compressor, NULL))) { uint32_t addr; - uint32_t value; + uint32_t value, misc_value; addr = mmFBC_CNTL; @@ -206,9 +206,23 @@ void dce110_compressor_enable_fbc( compressor->attached_inst = params->inst; cp110->offsets = reg_offsets[params->inst]; - /*Toggle it as there is bug in HW */ + /* Toggle it as there is bug in HW */ set_reg_field_value(value, 0, FBC_CNTL, FBC_GRPH_COMP_EN); dm_write_reg(compressor->ctx, addr, value); + + /* FBC usage with scatter & gather for dce110 */ + misc_value = dm_read_reg(compressor->ctx, mmFBC_MISC); + + set_reg_field_value(misc_value, 1, + FBC_MISC, FBC_INVALIDATE_ON_ERROR); + set_reg_field_value(misc_value, 1, + FBC_MISC, FBC_DECOMPRESS_ERROR_CLEAR); + set_reg_field_value(misc_value, 0x14, + FBC_MISC, FBC_SLOW_REQ_INTERVAL); + + dm_write_reg(compressor->ctx, mmFBC_MISC, misc_value); + + /* Enable FBC */ set_reg_field_value(value, 1, FBC_CNTL, FBC_GRPH_COMP_EN); dm_write_reg(compressor->ctx, addr, value); -- cgit From 4486201caf9c890f132d9a7631b4e5ebbaf524c3 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Tue, 29 Aug 2017 12:50:21 -0400 Subject: drm/amd/display: Program reg for vertical interrupt. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c | 10 ++++++++++ drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h | 4 ++++ 2 files changed, 14 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c index 6a5f2683c2e5..94ea3a9f6bb4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c @@ -118,6 +118,7 @@ static void tgn10_program_timing( uint32_t start_point = 0; uint32_t field_num = 0; uint32_t h_div_2; + uint32_t vertial_line_start; struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); @@ -212,6 +213,12 @@ static void tgn10_program_timing( OTG_V_BLANK_START, asic_blank_start, OTG_V_BLANK_END, asic_blank_end); + /* Use OTG_VERTICAL_INTERRUPT2 replace VUPDATE interrupt, + * program the reg for interrupt postition. + */ + vertial_line_start = asic_blank_end - tg->dlg_otg_param.vstartup_start + 1; + REG_SET(OTG_VERTICAL_INTERRUPT2_POSITION, 0, + OTG_VERTICAL_INTERRUPT2_LINE_START, vertial_line_start); /* v_sync polarity */ v_sync_polarity = patched_crtc_timing.flags.VSYNC_POSITIVE_POLARITY ? @@ -289,6 +296,9 @@ static void tgn10_unblank_crtc(struct timing_generator *tg) { struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + REG_UPDATE(OTG_DOUBLE_BUFFER_CONTROL, + OTG_BLANK_DATA_DOUBLE_BUFFER_EN, 1); + REG_UPDATE_2(OTG_BLANK_CONTROL, OTG_BLANK_DATA_EN, 0, OTG_BLANK_DE_MODE, 0); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h index 654889318fc1..38d3dcf89d60 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h @@ -65,6 +65,7 @@ SRI(OTG_NOM_VERT_POSITION, OTG, inst),\ SRI(OTG_BLACK_COLOR, OTG, inst),\ SRI(OTG_CLOCK_CONTROL, OTG, inst),\ + SRI(OTG_VERTICAL_INTERRUPT2_POSITION, OTG, inst),\ SRI(OPTC_INPUT_CLOCK_CONTROL, ODM, inst),\ SRI(OPTC_DATA_SOURCE_SELECT, ODM, inst),\ SRI(OPTC_INPUT_GLOBAL_CONTROL, ODM, inst),\ @@ -120,6 +121,7 @@ struct dcn_tg_registers { uint32_t OTG_TEST_PATTERN_CONTROL; uint32_t OTG_TEST_PATTERN_COLOR; uint32_t OTG_CLOCK_CONTROL; + uint32_t OTG_VERTICAL_INTERRUPT2_POSITION; uint32_t OPTC_INPUT_CLOCK_CONTROL; uint32_t OPTC_DATA_SOURCE_SELECT; uint32_t OPTC_INPUT_GLOBAL_CONTROL; @@ -203,6 +205,7 @@ struct dcn_tg_registers { SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_EN, mask_sh),\ SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_ON, mask_sh),\ SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_GATE_DIS, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT2_POSITION, OTG_VERTICAL_INTERRUPT2_LINE_START, mask_sh),\ SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_EN, mask_sh),\ SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_ON, mask_sh),\ SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_GATE_DIS, mask_sh),\ @@ -308,6 +311,7 @@ struct dcn_tg_registers { type OTG_CLOCK_EN;\ type OTG_CLOCK_ON;\ type OTG_CLOCK_GATE_DIS;\ + type OTG_VERTICAL_INTERRUPT2_LINE_START;\ type OPTC_INPUT_CLK_EN;\ type OPTC_INPUT_CLK_ON;\ type OPTC_INPUT_CLK_GATE_DIS;\ -- cgit From 0bfac360edcd843e90a0444475616a486f643eeb Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Tue, 29 Aug 2017 15:27:20 -0400 Subject: drm/amd/display: Disable OTG double buffer. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c index 94ea3a9f6bb4..15f1f44e102a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c @@ -296,9 +296,6 @@ static void tgn10_unblank_crtc(struct timing_generator *tg) { struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); - REG_UPDATE(OTG_DOUBLE_BUFFER_CONTROL, - OTG_BLANK_DATA_DOUBLE_BUFFER_EN, 1); - REG_UPDATE_2(OTG_BLANK_CONTROL, OTG_BLANK_DATA_EN, 0, OTG_BLANK_DE_MODE, 0); -- cgit From 1d9521a74029c3afcf996e207ecd61a74414dd68 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Fri, 25 Aug 2017 16:33:40 -0400 Subject: drm/amd/display: Set add_stream_ctx for CZ, Hawaii and others Signed-off-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dce100/dce100_resource.c | 19 +++++++++++++++++++ .../gpu/drm/amd/display/dc/dce100/dce100_resource.h | 5 +++++ .../gpu/drm/amd/display/dc/dce110/dce110_resource.c | 20 ++++++++++++++++++++ .../gpu/drm/amd/display/dc/dce80/dce80_resource.c | 1 + 4 files changed, 45 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 36d79175354c..ca6c7c2a1b4c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -713,6 +713,24 @@ enum dc_status dce100_validate_global( return DC_OK; } +enum dc_status dce100_add_stream_to_ctx( + struct dc *dc, + struct dc_state *new_ctx, + struct dc_stream_state *dc_stream) +{ + enum dc_status result = DC_ERROR_UNEXPECTED; + + result = resource_map_pool_resources(dc, new_ctx, dc_stream); + + if (result == DC_OK) + result = resource_map_clock_resources(dc, new_ctx, dc_stream); + + if (result == DC_OK) + result = build_mapped_resource(dc, new_ctx, dc_stream); + + return result; +} + enum dc_status dce100_validate_guaranteed( struct dc *dc, struct dc_stream_state *dc_stream, @@ -769,6 +787,7 @@ static const struct resource_funcs dce100_res_pool_funcs = { .validate_guaranteed = dce100_validate_guaranteed, .validate_bandwidth = dce100_validate_bandwidth, .validate_plane = dce100_validate_plane, + .add_stream_to_ctx = dce100_add_stream_to_ctx, .validate_global = dce100_validate_global }; diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h index ca7b2b7c1a48..f52cae24ee23 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h @@ -18,4 +18,9 @@ struct resource_pool *dce100_create_resource_pool( enum dc_status dce100_validate_plane(const struct dc_plane_state *plane_state); +enum dc_status dce100_add_stream_to_ctx( + struct dc *dc, + struct dc_state *new_ctx, + struct dc_stream_state *dc_stream); + #endif /* DCE100_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 4942460d42ca..41bfddf9574e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -921,6 +921,25 @@ enum dc_status dce110_validate_global( return DC_OK; } +static enum dc_status dce110_add_stream_to_ctx( + struct dc *dc, + struct dc_state *new_ctx, + struct dc_stream_state *dc_stream) +{ + enum dc_status result = DC_ERROR_UNEXPECTED; + + result = resource_map_pool_resources(dc, new_ctx, dc_stream); + + if (result == DC_OK) + result = resource_map_clock_resources(dc, new_ctx, dc_stream); + + + if (result == DC_OK) + result = build_mapped_resource(dc, new_ctx, dc_stream); + + return result; +} + static enum dc_status dce110_validate_guaranteed( struct dc *dc, struct dc_stream_state *dc_stream, @@ -1030,6 +1049,7 @@ static const struct resource_funcs dce110_res_pool_funcs = { .validate_guaranteed = dce110_validate_guaranteed, .validate_bandwidth = dce110_validate_bandwidth, .acquire_idle_pipe_for_layer = dce110_acquire_underlay, + .add_stream_to_ctx = dce110_add_stream_to_ctx, .validate_global = dce110_validate_global }; diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 316080767a21..9234086aac27 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -791,6 +791,7 @@ static const struct resource_funcs dce80_res_pool_funcs = { .validate_guaranteed = dce80_validate_guaranteed, .validate_bandwidth = dce80_validate_bandwidth, .validate_plane = dce100_validate_plane, + .add_stream_to_ctx = dce100_add_stream_to_ctx, .validate_global = dce80_validate_global }; -- cgit From 513b5693391af332feda8f273af8446ccd4a220b Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Fri, 25 Aug 2017 22:34:51 -0400 Subject: drm/amd/display: Restore missing DCE8 xfm regs Signed-off-by: Harry Wentland Reviewed-by: Roman Li Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_transform.h | 10 ++++++++++ drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c | 6 +++--- 2 files changed, 13 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h index d87225d15cd9..805bb9c4e188 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h @@ -94,6 +94,10 @@ SRI(SCL_UPDATE, SCL, id), \ SRI(SCL_F_SHARP_CONTROL, SCL, id) +#define XFM_COMMON_REG_LIST_DCE80(id) \ + XFM_COMMON_REG_LIST_DCE_BASE(id), \ + SRI(DCFE_MEM_LIGHT_SLEEP_CNTL, CRTC, id) + #define XFM_COMMON_REG_LIST_DCE100(id) \ XFM_COMMON_REG_LIST_DCE_BASE(id), \ SRI(DCFE_MEM_PWR_CTRL, CRTC, id), \ @@ -185,6 +189,12 @@ XFM_SF(SCL_UPDATE, SCL_COEF_UPDATE_COMPLETE, mask_sh), \ XFM_SF(LB_DATA_FORMAT, ALPHA_EN, mask_sh) +#define XFM_COMMON_MASK_SH_LIST_DCE80(mask_sh) \ + XFM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh), \ + OPP_SF(DCFE_MEM_LIGHT_SLEEP_CNTL, REGAMMA_LUT_LIGHT_SLEEP_DIS, mask_sh),\ + OPP_SF(DCFE_MEM_LIGHT_SLEEP_CNTL, DCP_LUT_LIGHT_SLEEP_DIS, mask_sh),\ + OPP_SF(DCFE_MEM_LIGHT_SLEEP_CNTL, REGAMMA_LUT_MEM_PWR_STATE, mask_sh) + #define XFM_COMMON_MASK_SH_LIST_DCE110(mask_sh) \ XFM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh), \ XFM_SF(DCFE_MEM_PWR_CTRL, SCL_COEFF_MEM_PWR_DIS, mask_sh), \ diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 9234086aac27..5453f02ea8ca 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -187,7 +187,7 @@ static const struct dce_ipp_mask ipp_mask = { #define transform_regs(id)\ [id] = {\ - XFM_COMMON_REG_LIST_DCE_BASE(id)\ + XFM_COMMON_REG_LIST_DCE80(id)\ } static const struct dce_transform_registers xfm_regs[] = { @@ -200,11 +200,11 @@ static const struct dce_transform_registers xfm_regs[] = { }; static const struct dce_transform_shift xfm_shift = { - XFM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) + XFM_COMMON_MASK_SH_LIST_DCE80(__SHIFT) }; static const struct dce_transform_mask xfm_mask = { - XFM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) + XFM_COMMON_MASK_SH_LIST_DCE80(_MASK) }; #define aux_regs(id)\ -- cgit From 7c228a1a910784801360db5aedd153db9f465b56 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 28 Aug 2017 10:59:39 -0400 Subject: drm/amd/display: Don't spam log with failed validation In a lot of case we fail validation of timings for legitimate reasons. No need to print an error. Signed-off-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index c7bb966e8b29..fbf7747424a9 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -2711,7 +2711,6 @@ void resource_build_bit_depth_reduction_params(struct dc_stream_state *stream, bool dc_validate_stream(struct dc *dc, struct dc_stream_state *stream) { struct dc *core_dc = dc; - struct dc_context *dc_ctx = core_dc->ctx; struct dc_link *link = stream->sink->link; struct timing_generator *tg = core_dc->res_pool->timing_generators[0]; enum dc_status res = DC_OK; @@ -2733,10 +2732,6 @@ bool dc_validate_stream(struct dc *dc, struct dc_stream_state *stream) link, &stream->timing); - if (res != DC_OK) - DC_ERROR("Failed validation for stream %p, err:%d, !\n", - stream, res); - return res == DC_OK; } -- cgit From fd96c1775a75c14bf15465af7040cc00855b1ec0 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Mon, 28 Aug 2017 09:51:03 -0400 Subject: drm/amd/display: delete dead code Signed-off-by: Tony Cheng Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index ee1b76c074e6..1b0f64756be6 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -1312,8 +1312,9 @@ void dcn_bw_notify_pplib_of_wm_ranges(struct dc *dc) { struct pp_smu_funcs_rv *pp = dc->res_pool->pp_smu; struct pp_smu_wm_range_sets ranges = {0}; - int max_fclk_khz, nom_fclk_khz, min_fclk_khz, max_dcfclk_khz, - nom_dcfclk_khz, mid_fclk_khz, min_dcfclk_khz, socclk_khz; + int max_fclk_khz, nom_fclk_khz, mid_fclk_khz, min_fclk_khz; + int max_dcfclk_khz, min_dcfclk_khz; + int socclk_khz; const int overdrive = 5000000; /* 5 GHz to cover Overdrive */ unsigned factor = (ddr4_dram_factor_single_Channel * dc->dcn_soc->number_of_channels); @@ -1326,7 +1327,6 @@ void dcn_bw_notify_pplib_of_wm_ranges(struct dc *dc) mid_fclk_khz = dc->dcn_soc->fabric_and_dram_bandwidth_vmid0p72 * 1000000 / factor; min_fclk_khz = dc->dcn_soc->fabric_and_dram_bandwidth_vmin0p65 * 1000000 / 32; max_dcfclk_khz = dc->dcn_soc->dcfclkv_max0p9 * 1000; - nom_dcfclk_khz = dc->dcn_soc->dcfclkv_nom0p8 * 1000; min_dcfclk_khz = dc->dcn_soc->dcfclkv_min0p65 * 1000; socclk_khz = dc->dcn_soc->socclk * 1000; kernel_fpu_end(); -- cgit From 7ad124cc23172a7a70d642adf8f5c99f6c974539 Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Tue, 29 Aug 2017 15:01:06 -0400 Subject: drm/amd/display: clean up cm register programming functions Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h | 120 ---------- .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c | 251 +++++++-------------- 2 files changed, 76 insertions(+), 295 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h index 717930584111..4bbd3b4f7ae6 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h @@ -44,10 +44,6 @@ #define TF_REG_LIST_DCN(id) \ SRI(CM_GAMUT_REMAP_CONTROL, CM, id),\ SRI(CM_GAMUT_REMAP_C11_C12, CM, id),\ - SRI(CM_GAMUT_REMAP_C13_C14, CM, id),\ - SRI(CM_GAMUT_REMAP_C21_C22, CM, id),\ - SRI(CM_GAMUT_REMAP_C23_C24, CM, id),\ - SRI(CM_GAMUT_REMAP_C31_C32, CM, id),\ SRI(CM_GAMUT_REMAP_C33_C34, CM, id),\ SRI(DSCL_EXT_OVERSCAN_LEFT_RIGHT, DSCL, id), \ SRI(DSCL_EXT_OVERSCAN_TOP_BOTTOM, DSCL, id), \ @@ -79,10 +75,6 @@ SRI(OBUF_CONTROL, DSCL, id), \ SRI(CM_ICSC_CONTROL, CM, id), \ SRI(CM_ICSC_C11_C12, CM, id), \ - SRI(CM_ICSC_C13_C14, CM, id), \ - SRI(CM_ICSC_C21_C22, CM, id), \ - SRI(CM_ICSC_C23_C24, CM, id), \ - SRI(CM_ICSC_C31_C32, CM, id), \ SRI(CM_ICSC_C33_C34, CM, id), \ SRI(CM_DGAM_RAMB_START_CNTL_B, CM, id), \ SRI(CM_DGAM_RAMB_START_CNTL_G, CM, id), \ @@ -127,23 +119,11 @@ #define TF_REG_LIST_DCN10(id) \ TF_REG_LIST_DCN(id), \ SRI(CM_COMA_C11_C12, CM, id),\ - SRI(CM_COMA_C13_C14, CM, id),\ - SRI(CM_COMA_C21_C22, CM, id),\ - SRI(CM_COMA_C23_C24, CM, id),\ - SRI(CM_COMA_C31_C32, CM, id),\ SRI(CM_COMA_C33_C34, CM, id),\ SRI(CM_COMB_C11_C12, CM, id),\ - SRI(CM_COMB_C13_C14, CM, id),\ - SRI(CM_COMB_C21_C22, CM, id),\ - SRI(CM_COMB_C23_C24, CM, id),\ - SRI(CM_COMB_C31_C32, CM, id),\ SRI(CM_COMB_C33_C34, CM, id),\ SRI(CM_OCSC_CONTROL, CM, id), \ SRI(CM_OCSC_C11_C12, CM, id), \ - SRI(CM_OCSC_C13_C14, CM, id), \ - SRI(CM_OCSC_C21_C22, CM, id), \ - SRI(CM_OCSC_C23_C24, CM, id), \ - SRI(CM_OCSC_C31_C32, CM, id), \ SRI(CM_OCSC_C33_C34, CM, id), \ SRI(CM_MEM_PWR_CTRL, CM, id), \ SRI(CM_RGAM_LUT_DATA, CM, id), \ @@ -189,14 +169,6 @@ TF_SF(CM0_CM_GAMUT_REMAP_CONTROL, CM_GAMUT_REMAP_MODE, mask_sh),\ TF_SF(CM0_CM_GAMUT_REMAP_C11_C12, CM_GAMUT_REMAP_C11, mask_sh),\ TF_SF(CM0_CM_GAMUT_REMAP_C11_C12, CM_GAMUT_REMAP_C12, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C13_C14, CM_GAMUT_REMAP_C13, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C13_C14, CM_GAMUT_REMAP_C14, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C21_C22, CM_GAMUT_REMAP_C21, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C21_C22, CM_GAMUT_REMAP_C22, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C23_C24, CM_GAMUT_REMAP_C23, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C23_C24, CM_GAMUT_REMAP_C24, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C31_C32, CM_GAMUT_REMAP_C31, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C31_C32, CM_GAMUT_REMAP_C32, mask_sh),\ TF_SF(CM0_CM_GAMUT_REMAP_C33_C34, CM_GAMUT_REMAP_C33, mask_sh),\ TF_SF(CM0_CM_GAMUT_REMAP_C33_C34, CM_GAMUT_REMAP_C34, mask_sh),\ TF_SF(DSCL0_DSCL_EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_LEFT, mask_sh),\ @@ -264,14 +236,6 @@ TF_SF(CM0_CM_ICSC_CONTROL, CM_ICSC_MODE, mask_sh), \ TF_SF(CM0_CM_ICSC_C11_C12, CM_ICSC_C11, mask_sh), \ TF_SF(CM0_CM_ICSC_C11_C12, CM_ICSC_C12, mask_sh), \ - TF_SF(CM0_CM_ICSC_C13_C14, CM_ICSC_C13, mask_sh), \ - TF_SF(CM0_CM_ICSC_C13_C14, CM_ICSC_C14, mask_sh), \ - TF_SF(CM0_CM_ICSC_C21_C22, CM_ICSC_C21, mask_sh), \ - TF_SF(CM0_CM_ICSC_C21_C22, CM_ICSC_C22, mask_sh), \ - TF_SF(CM0_CM_ICSC_C23_C24, CM_ICSC_C23, mask_sh), \ - TF_SF(CM0_CM_ICSC_C23_C24, CM_ICSC_C24, mask_sh), \ - TF_SF(CM0_CM_ICSC_C31_C32, CM_ICSC_C31, mask_sh), \ - TF_SF(CM0_CM_ICSC_C31_C32, CM_ICSC_C32, mask_sh), \ TF_SF(CM0_CM_ICSC_C33_C34, CM_ICSC_C33, mask_sh), \ TF_SF(CM0_CM_ICSC_C33_C34, CM_ICSC_C34, mask_sh), \ TF_SF(CM0_CM_DGAM_RAMB_START_CNTL_B, CM_DGAM_RAMB_EXP_REGION_START_B, mask_sh), \ @@ -349,39 +313,15 @@ TF_SF(DSCL0_LB_DATA_FORMAT, DITHER_EN, mask_sh),\ TF_SF(CM0_CM_COMA_C11_C12, CM_COMA_C11, mask_sh),\ TF_SF(CM0_CM_COMA_C11_C12, CM_COMA_C12, mask_sh),\ - TF_SF(CM0_CM_COMA_C13_C14, CM_COMA_C13, mask_sh),\ - TF_SF(CM0_CM_COMA_C13_C14, CM_COMA_C14, mask_sh),\ - TF_SF(CM0_CM_COMA_C21_C22, CM_COMA_C21, mask_sh),\ - TF_SF(CM0_CM_COMA_C21_C22, CM_COMA_C22, mask_sh),\ - TF_SF(CM0_CM_COMA_C23_C24, CM_COMA_C23, mask_sh),\ - TF_SF(CM0_CM_COMA_C23_C24, CM_COMA_C24, mask_sh),\ - TF_SF(CM0_CM_COMA_C31_C32, CM_COMA_C31, mask_sh),\ - TF_SF(CM0_CM_COMA_C31_C32, CM_COMA_C32, mask_sh),\ TF_SF(CM0_CM_COMA_C33_C34, CM_COMA_C33, mask_sh),\ TF_SF(CM0_CM_COMA_C33_C34, CM_COMA_C34, mask_sh),\ TF_SF(CM0_CM_COMB_C11_C12, CM_COMB_C11, mask_sh),\ TF_SF(CM0_CM_COMB_C11_C12, CM_COMB_C12, mask_sh),\ - TF_SF(CM0_CM_COMB_C13_C14, CM_COMB_C13, mask_sh),\ - TF_SF(CM0_CM_COMB_C13_C14, CM_COMB_C14, mask_sh),\ - TF_SF(CM0_CM_COMB_C21_C22, CM_COMB_C21, mask_sh),\ - TF_SF(CM0_CM_COMB_C21_C22, CM_COMB_C22, mask_sh),\ - TF_SF(CM0_CM_COMB_C23_C24, CM_COMB_C23, mask_sh),\ - TF_SF(CM0_CM_COMB_C23_C24, CM_COMB_C24, mask_sh),\ - TF_SF(CM0_CM_COMB_C31_C32, CM_COMB_C31, mask_sh),\ TF_SF(CM0_CM_COMB_C33_C34, CM_COMB_C33, mask_sh),\ - TF_SF(CM0_CM_COMB_C31_C32, CM_COMB_C32, mask_sh),\ TF_SF(CM0_CM_COMB_C33_C34, CM_COMB_C34, mask_sh),\ TF_SF(CM0_CM_OCSC_CONTROL, CM_OCSC_MODE, mask_sh), \ TF_SF(CM0_CM_OCSC_C11_C12, CM_OCSC_C11, mask_sh), \ TF_SF(CM0_CM_OCSC_C11_C12, CM_OCSC_C12, mask_sh), \ - TF_SF(CM0_CM_OCSC_C13_C14, CM_OCSC_C13, mask_sh), \ - TF_SF(CM0_CM_OCSC_C13_C14, CM_OCSC_C14, mask_sh), \ - TF_SF(CM0_CM_OCSC_C21_C22, CM_OCSC_C21, mask_sh), \ - TF_SF(CM0_CM_OCSC_C21_C22, CM_OCSC_C22, mask_sh), \ - TF_SF(CM0_CM_OCSC_C23_C24, CM_OCSC_C23, mask_sh), \ - TF_SF(CM0_CM_OCSC_C23_C24, CM_OCSC_C24, mask_sh), \ - TF_SF(CM0_CM_OCSC_C31_C32, CM_OCSC_C31, mask_sh), \ - TF_SF(CM0_CM_OCSC_C31_C32, CM_OCSC_C32, mask_sh), \ TF_SF(CM0_CM_OCSC_C33_C34, CM_OCSC_C33, mask_sh), \ TF_SF(CM0_CM_OCSC_C33_C34, CM_OCSC_C34, mask_sh), \ TF_SF(CM0_CM_MEM_PWR_CTRL, RGAM_MEM_PWR_FORCE, mask_sh), \ @@ -532,51 +472,19 @@ type CM_GAMUT_REMAP_MODE; \ type CM_GAMUT_REMAP_C11; \ type CM_GAMUT_REMAP_C12; \ - type CM_GAMUT_REMAP_C13; \ - type CM_GAMUT_REMAP_C14; \ - type CM_GAMUT_REMAP_C21; \ - type CM_GAMUT_REMAP_C22; \ - type CM_GAMUT_REMAP_C23; \ - type CM_GAMUT_REMAP_C24; \ - type CM_GAMUT_REMAP_C31; \ - type CM_GAMUT_REMAP_C32; \ type CM_GAMUT_REMAP_C33; \ type CM_GAMUT_REMAP_C34; \ type CM_COMA_C11; \ type CM_COMA_C12; \ - type CM_COMA_C13; \ - type CM_COMA_C14; \ - type CM_COMA_C21; \ - type CM_COMA_C22; \ - type CM_COMA_C23; \ - type CM_COMA_C24; \ - type CM_COMA_C31; \ - type CM_COMA_C32; \ type CM_COMA_C33; \ type CM_COMA_C34; \ type CM_COMB_C11; \ type CM_COMB_C12; \ - type CM_COMB_C13; \ - type CM_COMB_C14; \ - type CM_COMB_C21; \ - type CM_COMB_C22; \ - type CM_COMB_C23; \ - type CM_COMB_C24; \ - type CM_COMB_C31; \ - type CM_COMB_C32; \ type CM_COMB_C33; \ type CM_COMB_C34; \ type CM_OCSC_MODE; \ type CM_OCSC_C11; \ type CM_OCSC_C12; \ - type CM_OCSC_C13; \ - type CM_OCSC_C14; \ - type CM_OCSC_C21; \ - type CM_OCSC_C22; \ - type CM_OCSC_C23; \ - type CM_OCSC_C24; \ - type CM_OCSC_C31; \ - type CM_OCSC_C32; \ type CM_OCSC_C33; \ type CM_OCSC_C34; \ type RGAM_MEM_PWR_FORCE; \ @@ -1008,14 +916,6 @@ type CM_ICSC_MODE; \ type CM_ICSC_C11; \ type CM_ICSC_C12; \ - type CM_ICSC_C13; \ - type CM_ICSC_C14; \ - type CM_ICSC_C21; \ - type CM_ICSC_C22; \ - type CM_ICSC_C23; \ - type CM_ICSC_C24; \ - type CM_ICSC_C31; \ - type CM_ICSC_C32; \ type CM_ICSC_C33; \ type CM_ICSC_C34; \ type CM_DGAM_RAMB_EXP_REGION_START_B; \ @@ -1146,29 +1046,13 @@ struct dcn_dpp_registers { uint32_t RECOUT_SIZE; uint32_t CM_GAMUT_REMAP_CONTROL; uint32_t CM_GAMUT_REMAP_C11_C12; - uint32_t CM_GAMUT_REMAP_C13_C14; - uint32_t CM_GAMUT_REMAP_C21_C22; - uint32_t CM_GAMUT_REMAP_C23_C24; - uint32_t CM_GAMUT_REMAP_C31_C32; uint32_t CM_GAMUT_REMAP_C33_C34; uint32_t CM_COMA_C11_C12; - uint32_t CM_COMA_C13_C14; - uint32_t CM_COMA_C21_C22; - uint32_t CM_COMA_C23_C24; - uint32_t CM_COMA_C31_C32; uint32_t CM_COMA_C33_C34; uint32_t CM_COMB_C11_C12; - uint32_t CM_COMB_C13_C14; - uint32_t CM_COMB_C21_C22; - uint32_t CM_COMB_C23_C24; - uint32_t CM_COMB_C31_C32; uint32_t CM_COMB_C33_C34; uint32_t CM_OCSC_CONTROL; uint32_t CM_OCSC_C11_C12; - uint32_t CM_OCSC_C13_C14; - uint32_t CM_OCSC_C21_C22; - uint32_t CM_OCSC_C23_C24; - uint32_t CM_OCSC_C31_C32; uint32_t CM_OCSC_C33_C34; uint32_t CM_MEM_PWR_CTRL; uint32_t CM_RGAM_LUT_DATA; @@ -1317,10 +1201,6 @@ struct dcn_dpp_registers { uint32_t CM_SHAPER_LUT_DATA; uint32_t CM_ICSC_CONTROL; uint32_t CM_ICSC_C11_C12; - uint32_t CM_ICSC_C13_C14; - uint32_t CM_ICSC_C21_C22; - uint32_t CM_ICSC_C23_C24; - uint32_t CM_ICSC_C31_C32; uint32_t CM_ICSC_C33_C34; uint32_t CM_DGAM_RAMB_START_CNTL_B; uint32_t CM_DGAM_RAMB_START_CNTL_G; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c index 01b1c0ee0110..d698fccdef68 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c @@ -50,7 +50,7 @@ struct dcn10_input_csc_matrix { enum dc_color_space color_space; - uint32_t regval[12]; + uint16_t regval[12]; }; enum dcn10_coef_filter_type_sel { @@ -116,6 +116,38 @@ static const struct dcn10_input_csc_matrix dcn10_input_csc_matrix[] = { 0x2568, 0x43ee, 0xdbb2} } }; +static void dpp_cm_program_color_registers( + struct dcn10_dpp *xfm, + const uint16_t *regval, + uint32_t cm_reg_start, + uint32_t cm_reg_end) +{ + uint32_t reg_region_cur; + unsigned int i = 0; + +#undef REG +#define REG(reg) reg + + for (reg_region_cur = cm_reg_start; + reg_region_cur <= cm_reg_end; + reg_region_cur++) { + + const uint16_t *regval0 = &(regval[2 * i]); + const uint16_t *regval1 = &(regval[(2 * i) + 1]); + + REG_SET_2(reg_region_cur, 0, + CM_GAMUT_REMAP_C11, *regval0, + CM_GAMUT_REMAP_C12, *regval1); + + i++; + } + +#undef REG +#define REG(reg)\ + xfm->tf_regs->reg + +} + static void program_gamut_remap( struct dcn10_dpp *xfm, const uint16_t *regval, @@ -145,79 +177,27 @@ static void program_gamut_remap( if (select == GAMUT_REMAP_COEFF) { - REG_SET_2(CM_GAMUT_REMAP_C11_C12, 0, - CM_GAMUT_REMAP_C11, regval[0], - CM_GAMUT_REMAP_C12, regval[1]); - regval += 2; - REG_SET_2(CM_GAMUT_REMAP_C13_C14, 0, - CM_GAMUT_REMAP_C13, regval[0], - CM_GAMUT_REMAP_C14, regval[1]); - regval += 2; - REG_SET_2(CM_GAMUT_REMAP_C21_C22, 0, - CM_GAMUT_REMAP_C21, regval[0], - CM_GAMUT_REMAP_C22, regval[1]); - regval += 2; - REG_SET_2(CM_GAMUT_REMAP_C23_C24, 0, - CM_GAMUT_REMAP_C23, regval[0], - CM_GAMUT_REMAP_C24, regval[1]); - regval += 2; - REG_SET_2(CM_GAMUT_REMAP_C31_C32, 0, - CM_GAMUT_REMAP_C31, regval[0], - CM_GAMUT_REMAP_C32, regval[1]); - regval += 2; - REG_SET_2(CM_GAMUT_REMAP_C33_C34, 0, - CM_GAMUT_REMAP_C33, regval[0], - CM_GAMUT_REMAP_C34, regval[1]); + dpp_cm_program_color_registers( + xfm, + regval, + REG(CM_GAMUT_REMAP_C11_C12), + REG(CM_GAMUT_REMAP_C33_C34)); } else if (select == GAMUT_REMAP_COMA_COEFF) { - REG_SET_2(CM_COMA_C11_C12, 0, - CM_COMA_C11, regval[0], - CM_COMA_C12, regval[1]); - regval += 2; - REG_SET_2(CM_COMA_C13_C14, 0, - CM_COMA_C13, regval[0], - CM_COMA_C14, regval[1]); - regval += 2; - REG_SET_2(CM_COMA_C21_C22, 0, - CM_COMA_C21, regval[0], - CM_COMA_C22, regval[1]); - regval += 2; - REG_SET_2(CM_COMA_C23_C24, 0, - CM_COMA_C23, regval[0], - CM_COMA_C24, regval[1]); - regval += 2; - REG_SET_2(CM_COMA_C31_C32, 0, - CM_COMA_C31, regval[0], - CM_COMA_C32, regval[1]); - regval += 2; - REG_SET_2(CM_COMA_C33_C34, 0, - CM_COMA_C33, regval[0], - CM_COMA_C34, regval[1]); + + dpp_cm_program_color_registers( + xfm, + regval, + REG(CM_COMA_C11_C12), + REG(CM_COMA_C33_C34)); } else { - REG_SET_2(CM_COMB_C11_C12, 0, - CM_COMB_C11, regval[0], - CM_COMB_C12, regval[1]); - regval += 2; - REG_SET_2(CM_COMB_C13_C14, 0, - CM_COMB_C13, regval[0], - CM_COMB_C14, regval[1]); - regval += 2; - REG_SET_2(CM_COMB_C21_C22, 0, - CM_COMB_C21, regval[0], - CM_COMB_C22, regval[1]); - regval += 2; - REG_SET_2(CM_COMB_C23_C24, 0, - CM_COMB_C23, regval[0], - CM_COMB_C24, regval[1]); - regval += 2; - REG_SET_2(CM_COMB_C31_C32, 0, - CM_COMB_C31, regval[0], - CM_COMB_C32, regval[1]); - regval += 2; - REG_SET_2(CM_COMB_C33_C34, 0, - CM_COMB_C33, regval[0], - CM_COMB_C34, regval[1]); + + dpp_cm_program_color_registers( + xfm, + regval, + REG(CM_COMB_C11_C12), + REG(CM_COMB_C33_C34)); } REG_SET( @@ -312,59 +292,20 @@ static void dcn10_dpp_cm_program_color_matrix( } if (mode == 4) { - /*R*/ - REG_SET_2(CM_OCSC_C11_C12, 0, - CM_OCSC_C11, tbl_entry->regval[0], - CM_OCSC_C12, tbl_entry->regval[1]); - - REG_SET_2(CM_OCSC_C13_C14, 0, - CM_OCSC_C13, tbl_entry->regval[2], - CM_OCSC_C14, tbl_entry->regval[3]); - - /*G*/ - REG_SET_2(CM_OCSC_C21_C22, 0, - CM_OCSC_C21, tbl_entry->regval[4], - CM_OCSC_C22, tbl_entry->regval[5]); - - REG_SET_2(CM_OCSC_C23_C24, 0, - CM_OCSC_C23, tbl_entry->regval[6], - CM_OCSC_C24, tbl_entry->regval[7]); - - /*B*/ - REG_SET_2(CM_OCSC_C31_C32, 0, - CM_OCSC_C31, tbl_entry->regval[8], - CM_OCSC_C32, tbl_entry->regval[9]); - - REG_SET_2(CM_OCSC_C33_C34, 0, - CM_OCSC_C33, tbl_entry->regval[10], - CM_OCSC_C34, tbl_entry->regval[11]); + + dpp_cm_program_color_registers( + xfm, + tbl_entry->regval, + REG(CM_OCSC_C11_C12), + REG(CM_OCSC_C33_C34)); + } else { - /*R*/ - REG_SET_2(CM_COMB_C11_C12, 0, - CM_COMB_C11, tbl_entry->regval[0], - CM_COMB_C12, tbl_entry->regval[1]); - - REG_SET_2(CM_COMB_C13_C14, 0, - CM_COMB_C13, tbl_entry->regval[2], - CM_COMB_C14, tbl_entry->regval[3]); - - /*G*/ - REG_SET_2(CM_COMB_C21_C22, 0, - CM_COMB_C21, tbl_entry->regval[4], - CM_COMB_C22, tbl_entry->regval[5]); - - REG_SET_2(CM_COMB_C23_C24, 0, - CM_COMB_C23, tbl_entry->regval[6], - CM_COMB_C24, tbl_entry->regval[7]); - - /*B*/ - REG_SET_2(CM_COMB_C31_C32, 0, - CM_COMB_C31, tbl_entry->regval[8], - CM_COMB_C32, tbl_entry->regval[9]); - - REG_SET_2(CM_COMB_C33_C34, 0, - CM_COMB_C33, tbl_entry->regval[10], - CM_COMB_C34, tbl_entry->regval[11]); + + dpp_cm_program_color_registers( + xfm, + tbl_entry->regval, + REG(CM_COMB_C11_C12), + REG(CM_COMB_C33_C34)); } } @@ -602,7 +543,7 @@ void ippn10_program_input_csc( struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); int i; int arr_size = sizeof(dcn10_input_csc_matrix)/sizeof(struct dcn10_input_csc_matrix); - const uint32_t *regval = NULL; + const uint16_t *regval = NULL; uint32_t selection = 1; if (select == INPUT_CSC_SELECT_BYPASS) { @@ -627,59 +568,19 @@ void ippn10_program_input_csc( CM_ICSC_MODE, selection); if (select == INPUT_CSC_SELECT_ICSC) { - /*R*/ - REG_SET_2(CM_ICSC_C11_C12, 0, - CM_ICSC_C11, regval[0], - CM_ICSC_C12, regval[1]); - regval += 2; - REG_SET_2(CM_ICSC_C13_C14, 0, - CM_ICSC_C13, regval[0], - CM_ICSC_C14, regval[1]); - /*G*/ - regval += 2; - REG_SET_2(CM_ICSC_C21_C22, 0, - CM_ICSC_C21, regval[0], - CM_ICSC_C22, regval[1]); - regval += 2; - REG_SET_2(CM_ICSC_C23_C24, 0, - CM_ICSC_C23, regval[0], - CM_ICSC_C24, regval[1]); - /*B*/ - regval += 2; - REG_SET_2(CM_ICSC_C31_C32, 0, - CM_ICSC_C31, regval[0], - CM_ICSC_C32, regval[1]); - regval += 2; - REG_SET_2(CM_ICSC_C33_C34, 0, - CM_ICSC_C33, regval[0], - CM_ICSC_C34, regval[1]); + + dpp_cm_program_color_registers( + xfm, + regval, + REG(CM_ICSC_C11_C12), + REG(CM_ICSC_C33_C34)); } else { - /*R*/ - REG_SET_2(CM_COMA_C11_C12, 0, - CM_COMA_C11, regval[0], - CM_COMA_C12, regval[1]); - regval += 2; - REG_SET_2(CM_COMA_C13_C14, 0, - CM_COMA_C13, regval[0], - CM_COMA_C14, regval[1]); - /*G*/ - regval += 2; - REG_SET_2(CM_COMA_C21_C22, 0, - CM_COMA_C21, regval[0], - CM_COMA_C22, regval[1]); - regval += 2; - REG_SET_2(CM_COMA_C23_C24, 0, - CM_COMA_C23, regval[0], - CM_COMA_C24, regval[1]); - /*B*/ - regval += 2; - REG_SET_2(CM_COMA_C31_C32, 0, - CM_COMA_C31, regval[0], - CM_COMA_C32, regval[1]); - regval += 2; - REG_SET_2(CM_COMA_C33_C34, 0, - CM_COMA_C33, regval[0], - CM_COMA_C34, regval[1]); + + dpp_cm_program_color_registers( + xfm, + regval, + REG(CM_COMA_C11_C12), + REG(CM_COMA_C33_C34)); } } -- cgit From b46c085c238fdfea9b1cc49326dae92a47b34832 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 31 Aug 2017 21:17:05 -0400 Subject: drm/amdgpu: Remove unused flip_flags from amdgpu_crtc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No more need since Andrey's change to use drm_crtc's version Signed-off-by: Harry Wentland Reviewed-by: Michel Dänzer Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index 8d939e3b3f15..b541ade8a03f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -436,7 +436,6 @@ struct amdgpu_crtc { enum amdgpu_interrupt_state vsync_timer_enabled; int otg_inst; - uint32_t flip_flags; /* After Set Mode stream will be non-NULL */ const struct dc_stream *stream; struct drm_pending_vblank_event *event; -- cgit From 6f54d0b1d82194116fcb8a3683827c9d8eb8cb9b Mon Sep 17 00:00:00 2001 From: Logatharshan Thothiralingam Date: Fri, 18 Aug 2017 19:09:57 -0400 Subject: drm/amd/display: Get OTG info if OTG master enabled Signed-off-by: Logatharshan Thothiralingam Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 6 +++++- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c | 3 +++ drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h | 1 + 3 files changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 7ea274475598..4fa856e9a872 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -203,10 +203,14 @@ static void dcn10_log_hw_state(struct dc *dc) for (i = 0; i < pool->pipe_count; i++) { struct timing_generator *tg = pool->timing_generators[i]; - struct dcn_otg_state s; + struct dcn_otg_state s = {0}; tgn10_read_otg_state(DCN10TG_FROM_TG(tg), &s); + //only print if OTG master is enabled + if ((s.otg_enabled & 1) == 0) + continue; + DTN_INFO("[%d]:\t %d \t %d \t %d \t %d \t " "%d \t %d \t %d \t %d \t %d \t %d \t " "%d \t %d \t %d \t %d \t %d \t ", diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c index 15f1f44e102a..405f595f219a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c @@ -1100,6 +1100,9 @@ static bool tgn10_is_stereo_left_eye(struct timing_generator *tg) void tgn10_read_otg_state(struct dcn10_timing_generator *tgn10, struct dcn_otg_state *s) { + REG_GET(OTG_CONTROL, + OTG_MASTER_EN, &s->otg_enabled); + REG_GET_2(OTG_V_BLANK_START_END, OTG_V_BLANK_START, &s->v_blank_start, OTG_V_BLANK_END, &s->v_blank_end); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h index 38d3dcf89d60..69da293e9b4a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h @@ -370,6 +370,7 @@ struct dcn_otg_state { uint32_t h_sync_a_pol; uint32_t h_total; uint32_t underflow_occurred_status; + uint32_t otg_enabled; }; void tgn10_read_otg_state(struct dcn10_timing_generator *tgn10, -- cgit From 649e0c7679a5189dec1045329e36cfcf41919dc9 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Wed, 30 Aug 2017 11:55:40 -0400 Subject: drm/amd/display: Added negative check for vertical line start. In case of vstartup happens before vsync, set vertical line start to 0. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c index 405f595f219a..2d3dd9a3a196 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c @@ -118,7 +118,7 @@ static void tgn10_program_timing( uint32_t start_point = 0; uint32_t field_num = 0; uint32_t h_div_2; - uint32_t vertial_line_start; + int32_t vertical_line_start; struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); @@ -216,9 +216,13 @@ static void tgn10_program_timing( /* Use OTG_VERTICAL_INTERRUPT2 replace VUPDATE interrupt, * program the reg for interrupt postition. */ - vertial_line_start = asic_blank_end - tg->dlg_otg_param.vstartup_start + 1; + vertical_line_start = asic_blank_end - tg->dlg_otg_param.vstartup_start + 1; + if (vertical_line_start < 0) { + ASSERT(0); + vertical_line_start = 0; + } REG_SET(OTG_VERTICAL_INTERRUPT2_POSITION, 0, - OTG_VERTICAL_INTERRUPT2_LINE_START, vertial_line_start); + OTG_VERTICAL_INTERRUPT2_LINE_START, vertical_line_start); /* v_sync polarity */ v_sync_polarity = patched_crtc_timing.flags.VSYNC_POSITIVE_POLARITY ? -- cgit From 890db270a5763ccacda8df7cbfac674ade78744a Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Wed, 30 Aug 2017 14:29:40 -0400 Subject: drm/amd/display: Remove sanity check. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 4fa856e9a872..a6015c2c20c6 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2828,12 +2828,6 @@ void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx) struct dc_plane_state *plane_state = pipe_ctx->plane_state; struct timing_generator *tg = pipe_ctx->stream_res.tg; - if (plane_state->ctx->dc->debug.sanity_checks) { - struct dc *dc = plane_state->ctx->dc; - - verify_allow_pstate_change_high(dc->hwseq); - } - if (plane_state == NULL) return; -- cgit From 78e685f9a385eb984f69720e463878e5c3ae80b7 Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Wed, 30 Aug 2017 17:49:39 -0400 Subject: drm/amd/display: Use TPS4 instead of CP2520_3 for phy pattern 7 [Description] We originally use TPS4 phy test pattern for test pattern 7. On RV we switched to a new method to use CP2520. CP2520 should produce the same result. However in reality, it fails DP PHY automation test. We use the original method instead. Signed-off-by: Wenjing Liu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') 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 527cc0400fd3..1aec586b0367 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 @@ -1756,7 +1756,7 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link) test_pattern = DP_TEST_PATTERN_CP2520_2; break; case PHY_TEST_PATTERN_CP2520_3: - test_pattern = DP_TEST_PATTERN_CP2520_3; + test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN4; break; default: test_pattern = DP_TEST_PATTERN_VIDEO_MODE; -- cgit From 1bb47154408ffa0501bb544580304ce0fdbc4ab6 Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Mon, 28 Aug 2017 17:15:34 -0400 Subject: drm/amd/display: Request to have DCN RV pipe Harvesting TODO: Current change only work for sucessive last fused pipe, like p3, or p3,p2. It does not work for fused p1,p2. Signed-off-by: Hersen Wu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 55 +++++++++++++++++----- 1 file changed, 43 insertions(+), 12 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index fff86ad0c411..ac6d01ec0505 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -1207,13 +1207,23 @@ static struct resource_funcs dcn10_res_pool_funcs = { .add_stream_to_ctx = dcn10_add_stream_to_ctx }; +static uint32_t read_pipe_fuses(struct dc_context *ctx) +{ + uint32_t value = dm_read_reg_soc15(ctx, mmCC_DC_PIPE_DIS, 0); + /* RV1 support max 4 pipes */ + value = value & 0xf; + return value; +} + static bool construct( uint8_t num_virtual_links, struct dc *dc, struct dcn10_resource_pool *pool) { int i; + int j; struct dc_context *ctx = dc->ctx; + uint32_t pipe_fuses = read_pipe_fuses(ctx); ctx->dc_bios->regs = &bios_regs; @@ -1230,8 +1240,9 @@ static bool construct( *************************************************/ pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; - /* TODO: Hardcode to correct number of functional controllers */ - pool->base.pipe_count = 4; + /* max pipe num for ASIC before check pipe fuses */ + pool->base.pipe_count = pool->base.res_cap->num_timing_generator; + dc->caps.max_downscale_ratio = 200; dc->caps.i2c_speed_in_khz = 100; dc->caps.max_cursor_size = 256; @@ -1355,48 +1366,68 @@ static bool construct( #endif } + /* index to valid pipe resource */ + j = 0; /* mem input -> ipp -> dpp -> opp -> TG */ for (i = 0; i < pool->base.pipe_count; i++) { - pool->base.mis[i] = dcn10_mem_input_create(ctx, i); - if (pool->base.mis[i] == NULL) { + /* if pipe is disabled, skip instance of HW pipe, + * i.e, skip ASIC register instance + */ + if ((pipe_fuses & (1 << i)) != 0) + continue; + + pool->base.mis[j] = dcn10_mem_input_create(ctx, i); + if (pool->base.mis[j] == NULL) { BREAK_TO_DEBUGGER(); dm_error( "DC: failed to create memory input!\n"); goto mi_create_fail; } - pool->base.ipps[i] = dcn10_ipp_create(ctx, i); - if (pool->base.ipps[i] == NULL) { + pool->base.ipps[j] = dcn10_ipp_create(ctx, i); + if (pool->base.ipps[j] == NULL) { BREAK_TO_DEBUGGER(); dm_error( "DC: failed to create input pixel processor!\n"); goto ipp_create_fail; } - pool->base.transforms[i] = dcn10_dpp_create(ctx, i); - if (pool->base.transforms[i] == NULL) { + pool->base.transforms[j] = dcn10_dpp_create(ctx, i); + if (pool->base.transforms[j] == NULL) { BREAK_TO_DEBUGGER(); dm_error( "DC: failed to create dpp!\n"); goto dpp_create_fail; } - pool->base.opps[i] = dcn10_opp_create(ctx, i); - if (pool->base.opps[i] == NULL) { + pool->base.opps[j] = dcn10_opp_create(ctx, i); + if (pool->base.opps[j] == NULL) { BREAK_TO_DEBUGGER(); dm_error( "DC: failed to create output pixel processor!\n"); goto opp_create_fail; } - pool->base.timing_generators[i] = dcn10_timing_generator_create( + pool->base.timing_generators[j] = dcn10_timing_generator_create( ctx, i); - if (pool->base.timing_generators[i] == NULL) { + if (pool->base.timing_generators[j] == NULL) { BREAK_TO_DEBUGGER(); dm_error("DC: failed to create tg!\n"); goto otg_create_fail; } + /* check next valid pipe */ + j++; } + + /* valid pipe num */ + pool->base.pipe_count = j; + + /* within dml lib, it is hard code to 4. If ASIC pipe is fused, + * the value may be changed + */ + dc->dml.ip.max_num_dpp = pool->base.pipe_count; + dc->dcn_ip->max_num_dpp = pool->base.pipe_count; + pool->base.mpc = dcn10_mpc_create(ctx); if (pool->base.mpc == NULL) { BREAK_TO_DEBUGGER(); -- cgit From 4451a2551dcac9ea8c90829e0fcc798b834deb6b Mon Sep 17 00:00:00 2001 From: Shirish S Date: Mon, 21 Aug 2017 14:02:17 +0530 Subject: drm/amd/display: dce110: fix plane validation For MPO to work with per surface rendering and flipping, the previous logic of restricting plane[1] only as underlay needs to be removed. validate_surface_sets() now checks only the width and height bounds in case of underlay rather than checking format. Without this patch one cannot set underlay only. Signed-off-by: Shirish S Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dce110/dce110_resource.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 41bfddf9574e..25eda52c32ef 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -891,21 +891,14 @@ static bool dce110_validate_surface_sets( if (context->stream_status[i].plane_count > 2) return false; - if (context->stream_status[i].plane_states[0]->format - >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) + if ((context->stream_status[i].plane_states[i]->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) && + (context->stream_status[i].plane_states[i]->src_rect.width > 1920 || + context->stream_status[i].plane_states[i]->src_rect.height > 1080)) return false; - if (context->stream_status[i].plane_count == 2) { - if (context->stream_status[i].plane_states[1]->format - < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) - return false; - if (context->stream_status[i].plane_states[1]->src_rect.width > 1920 - || context->stream_status[i].plane_states[1]->src_rect.height > 1080) - return false; - - if (context->streams[i]->timing.pixel_encoding != PIXEL_ENCODING_RGB) - return false; - } + /* irrespective of plane format, stream should be RGB encoded */ + if (context->streams[i]->timing.pixel_encoding != PIXEL_ENCODING_RGB) + return false; } return true; -- cgit From 8f38b66c82618854d019f9df8ff4cd8dd796da10 Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Mon, 11 Sep 2017 16:42:14 -0400 Subject: drm/amd/display: USB-C to HDMI dongle not light RV1 support only USB-C active DP-2-HDMI dongle. HPD short pulse is generated only for DP signal. When processing HPD short pulse, it must be DP active dongle. No need for I2C-Over-AUX detection. v2: Add description Signed-off-by: Hersen Wu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 9 ++++--- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 32 +++++++++++++++-------- drivers/gpu/drm/amd/display/dc/dc.h | 8 +++++- 3 files changed, 33 insertions(+), 16 deletions(-) (limited to 'drivers/gpu') 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 4c7515d9c811..febfff2225d9 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -639,7 +639,7 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev ) continue; mutex_lock(&aconnector->hpd_lock); - dc_link_detect(aconnector->dc_link, false); + dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD); aconnector->dc_sink = NULL; amdgpu_dm_update_connector_after_detect(aconnector); mutex_unlock(&aconnector->hpd_lock); @@ -855,7 +855,7 @@ static void handle_hpd_irq(void *param) * since (for MST case) MST does this in it's own context. */ mutex_lock(&aconnector->hpd_lock); - if (dc_link_detect(aconnector->dc_link, false)) { + if (dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD)) { amdgpu_dm_update_connector_after_detect(aconnector); @@ -965,7 +965,7 @@ static void handle_hpd_rx_irq(void *param) if (dc_link_handle_hpd_rx_irq(aconnector->dc_link, NULL) && !is_mst_root_connector) { /* Downstream Port status changed. */ - if (dc_link_detect(aconnector->dc_link, false)) { + if (dc_link_detect(aconnector->dc_link, DETECT_REASON_HPDRX)) { amdgpu_dm_update_connector_after_detect(aconnector); @@ -1353,7 +1353,8 @@ int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) goto fail_free_encoder; } - if (dc_link_detect(dc_get_link_at_index(dm->dc, i), true)) + if (dc_link_detect(dc_get_link_at_index(dm->dc, i), + DETECT_REASON_BOOT)) amdgpu_dm_update_connector_after_detect(aconnector); } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index cea8dafd2edc..845ec421d861 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -355,7 +355,9 @@ static bool is_dp_sink_present(struct dc_link *link) * @brief * Detect output sink type */ -static enum signal_type link_detect_sink(struct dc_link *link) +static enum signal_type link_detect_sink( + struct dc_link *link, + enum dc_detect_reason reason) { enum signal_type result = get_basic_signal_type( link->link_enc->id, link->link_id); @@ -388,12 +390,17 @@ static enum signal_type link_detect_sink(struct dc_link *link) } break; case CONNECTOR_ID_DISPLAY_PORT: { - - /* Check whether DP signal detected: if not - - * we assume signal is DVI; it could be corrected - * to HDMI after dongle detection */ - if (!is_dp_sink_present(link)) - result = SIGNAL_TYPE_DVI_SINGLE_LINK; + /* DP HPD short pulse. Passive DP dongle will not + * have short pulse + */ + if (reason != DETECT_REASON_HPDRX) { + /* Check whether DP signal detected: if not - + * we assume signal is DVI; it could be corrected + * to HDMI after dongle detection + */ + if (!is_dp_sink_present(link)) + result = SIGNAL_TYPE_DVI_SINGLE_LINK; + } } break; default: @@ -460,9 +467,10 @@ static void detect_dp( struct display_sink_capability *sink_caps, bool *converter_disable_audio, struct audio_support *audio_support, - bool boot) + enum dc_detect_reason reason) { - sink_caps->signal = link_detect_sink(link); + bool boot = false; + sink_caps->signal = link_detect_sink(link, reason); sink_caps->transaction_type = get_ddc_transaction_type(sink_caps->signal); @@ -513,6 +521,8 @@ static void detect_dp( * Need check ->sink usages in case ->sink = NULL * TODO: s3 resume check */ + if (reason == DETECT_REASON_BOOT) + boot = true; if (dm_helpers_dp_mst_start_top_mgr( link->ctx, @@ -531,7 +541,7 @@ static void detect_dp( } } -bool dc_link_detect(struct dc_link *link, bool boot) +bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) { struct dc_sink_init_data sink_init_data = { 0 }; struct display_sink_capability sink_caps = { 0 }; @@ -596,7 +606,7 @@ bool dc_link_detect(struct dc_link *link, bool boot) link, &sink_caps, &converter_disable_audio, - aud_support, boot); + aud_support, reason); /* Active dongle downstream unplug */ if (link->type == dc_connection_active_dongle diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 2316a6060b2c..1f0521ff4614 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -885,7 +885,13 @@ bool dc_link_setup_psr(struct dc_link *dc_link, * true otherwise. True meaning further action is required (status update * and OS notification). */ -bool dc_link_detect(struct dc_link *dc_link, bool boot); +enum dc_detect_reason { + DETECT_REASON_BOOT, + DETECT_REASON_HPD, + DETECT_REASON_HPDRX, +}; + +bool dc_link_detect(struct dc_link *dc_link, enum dc_detect_reason reason); /* Notify DC about DP RX Interrupt (aka Short Pulse Interrupt). * Return: -- cgit From acea7183b5d72d0713d2129956e7357ebde28054 Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Thu, 31 Aug 2017 16:49:56 -0400 Subject: drm/amd/display: set CP2520 Test pattern to use DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE Signed-off-by: Wenjing Liu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') 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 1aec586b0367..38ccc011004d 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 @@ -1750,7 +1750,7 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link) test_pattern = DP_TEST_PATTERN_80BIT_CUSTOM; break; case PHY_TEST_PATTERN_CP2520_1: - test_pattern = DP_TEST_PATTERN_CP2520_1; + test_pattern = DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE; break; case PHY_TEST_PATTERN_CP2520_2: test_pattern = DP_TEST_PATTERN_CP2520_2; -- cgit From 1b7441b00a986cbed017a13ccf316efb54ab7a4b Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Fri, 1 Sep 2017 12:51:47 -0400 Subject: drm/amd/display: fix crc_source_select use hardcoded color depth Signed-off-by: Charlene Liu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 9fb0ba7e7b7d..47e8b582445e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -667,7 +667,25 @@ static enum dc_status bios_parser_crtc_source_select( crtc_source_select.signal = pipe_ctx->stream->signal; crtc_source_select.enable_dp_audio = false; crtc_source_select.sink_signal = pipe_ctx->stream->signal; - crtc_source_select.display_output_bit_depth = PANEL_8BIT_COLOR; + + switch (pipe_ctx->stream->timing.display_color_depth) { + case COLOR_DEPTH_666: + crtc_source_select.display_output_bit_depth = PANEL_6BIT_COLOR; + break; + case COLOR_DEPTH_888: + crtc_source_select.display_output_bit_depth = PANEL_8BIT_COLOR; + break; + case COLOR_DEPTH_101010: + crtc_source_select.display_output_bit_depth = PANEL_10BIT_COLOR; + break; + case COLOR_DEPTH_121212: + crtc_source_select.display_output_bit_depth = PANEL_12BIT_COLOR; + break; + default: + BREAK_TO_DEBUGGER(); + crtc_source_select.display_output_bit_depth = PANEL_8BIT_COLOR; + break; + } dcb = sink->ctx->dc_bios; -- cgit From 61a44fc6265dd3bb86c35bcdfb62a225891ada59 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 31 Aug 2017 16:08:51 -0400 Subject: drm/amd/display: Enable dcn10_power_on_fe log by default This should only happen on full update. If this ever happens on regular pageflips it needs to be debugged. Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index a6015c2c20c6..6b76fc417456 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1975,7 +1975,7 @@ static void dcn10_power_on_fe( /*TODO: REG_UPDATE(DENTIST_DISPCLK_CNTL, DENTIST_DPPCLK_WDIVIDER, 0x1f);*/ if (plane_state) { - dm_logger_write(dc->ctx->logger, LOG_DEBUG, + dm_logger_write(dc->ctx->logger, LOG_DC, "Pipe:%d 0x%x: addr hi:0x%x, " "addr low:0x%x, " "src: %d, %d, %d," @@ -1993,7 +1993,7 @@ static void dcn10_power_on_fe( plane_state->dst_rect.width, plane_state->dst_rect.height); - dm_logger_write(dc->ctx->logger, LOG_DEBUG, + dm_logger_write(dc->ctx->logger, LOG_DC, "Pipe %d: width, height, x, y\n" "viewport:%d, %d, %d, %d\n" "recout: %d, %d, %d, %d\n", -- cgit From 603767f903bf5bf301728b197dcde63cf880fe2e Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Fri, 1 Sep 2017 16:14:01 -0400 Subject: drm/amd/display: fix default dithering bug: default is mapped to no dithering. default to spatial dithering based on color depth Signed-off-by: Tony Cheng Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 20 +++----------------- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 16 ++++++++++++++++ .../drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 14 +++++--------- 3 files changed, 24 insertions(+), 26 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index ab6ad946231e..d5320f7162b4 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -341,23 +341,9 @@ void set_dither_option(struct dc_stream_state *stream, return; if (option > DITHER_OPTION_MAX) return; - if (option == DITHER_OPTION_DEFAULT) { - switch (stream->timing.display_color_depth) { - case COLOR_DEPTH_666: - stream->dither_option = DITHER_OPTION_SPATIAL6; - break; - case COLOR_DEPTH_888: - stream->dither_option = DITHER_OPTION_SPATIAL8; - break; - case COLOR_DEPTH_101010: - stream->dither_option = DITHER_OPTION_SPATIAL10; - break; - default: - option = DITHER_OPTION_DISABLE; - } - } else { - stream->dither_option = option; - } + + stream->dither_option = option; + resource_build_bit_depth_reduction_params(stream, ¶ms); stream->bit_depth_params = params; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index fbf7747424a9..ce721b77c1bc 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -2607,6 +2607,22 @@ void resource_build_bit_depth_reduction_params(struct dc_stream_state *stream, memset(fmt_bit_depth, 0, sizeof(*fmt_bit_depth)); + if (option == DITHER_OPTION_DEFAULT) { + switch (stream->timing.display_color_depth) { + case COLOR_DEPTH_666: + option = DITHER_OPTION_SPATIAL6; + break; + case COLOR_DEPTH_888: + option = DITHER_OPTION_SPATIAL8; + break; + case COLOR_DEPTH_101010: + option = DITHER_OPTION_SPATIAL10; + break; + default: + option = DITHER_OPTION_DISABLE; + } + } + if (option == DITHER_OPTION_DISABLE) return; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 47e8b582445e..b36220bc619d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1104,15 +1104,11 @@ static enum dc_status apply_single_controller_ctx_to_hw( stream->timing.timing_3d_format != TIMING_3D_FORMAT_NONE); -/*vbios crtc_source_selection and encoder_setup will override fmt_C*/ - if (pipe_ctx->stream->signal != SIGNAL_TYPE_EDP && - pipe_ctx->stream->signal != SIGNAL_TYPE_LVDS) { - /*for embedded panel, don't override VBIOS's setting*/ - pipe_ctx->stream_res.opp->funcs->opp_program_fmt( - pipe_ctx->stream_res.opp, - &stream->bit_depth_params, - &stream->clamping); - } + pipe_ctx->stream_res.opp->funcs->opp_program_fmt( + pipe_ctx->stream_res.opp, + &stream->bit_depth_params, + &stream->clamping); + if (dc_is_dp_signal(pipe_ctx->stream->signal)) pipe_ctx->stream_res.stream_enc->funcs->dp_set_stream_attribute( pipe_ctx->stream_res.stream_enc, -- cgit From aeff7ab11e2516bfa41c77b9ea57bc2c07bb3b62 Mon Sep 17 00:00:00 2001 From: Andrew Jiang Date: Fri, 1 Sep 2017 16:03:16 -0400 Subject: drm/amd/display: Fix context alloc failed logging Since there was no return statement in the fail block immediately preceding the context_alloc_fail block, any failure within the function caused a context alloc failed error message to be printed. Since the context_alloc_fail block is only used once, move it to where the goto is directly and accompany it with a return statement. Signed-off-by: Andrew Jiang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index d5320f7162b4..5579d2167a9a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1279,8 +1279,10 @@ void dc_update_planes_and_stream(struct dc *dc, /* initialize scratch memory for building context */ context = dc_create_state(); - if (context == NULL) - goto context_alloc_fail; + if (context == NULL) { + DC_ERROR("Failed to allocate new validate context!\n"); + return; + } dc_resource_state_copy_construct( dc->current_state, context); @@ -1534,9 +1536,6 @@ void dc_update_planes_and_stream(struct dc *dc, fail: dc_release_state(context); - -context_alloc_fail: - DC_ERROR("Failed to allocate new validate context!\n"); } uint8_t dc_get_current_stream_count(struct dc *dc) -- cgit From 83524646611381c4b0e31ffc5286cb05f8818aba Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Tue, 29 Aug 2017 16:54:39 -0400 Subject: drm/amd/display: seperate dpp_cm_helper functions into new file Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/Makefile | 2 +- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h | 2 + .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c | 259 +++++++++------------ .../drm/amd/display/dc/dcn10/dcn10_dpp_cm_helper.c | 123 ++++++++++ .../drm/amd/display/dc/dcn10/dcn10_dpp_cm_helper.h | 99 ++++++++ 5 files changed, 330 insertions(+), 155 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm_helper.c create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm_helper.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile index 52b56d19ca40..e92ac2997a1a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile @@ -4,7 +4,7 @@ DCN10 = dcn10_resource.o dcn10_ipp.o dcn10_hw_sequencer.o \ dcn10_dpp.o dcn10_opp.o dcn10_timing_generator.o \ dcn10_mem_input.o dcn10_mpc.o dcn10_dwb.o \ - dcn10_dpp_dscl.o dcn10_dpp_cm.o + dcn10_dpp_dscl.o dcn10_dpp_cm.o dcn10_dpp_cm_helper.o AMD_DAL_DCN10 = $(addprefix $(AMDDALPATH)/dc/dcn10/,$(DCN10)) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h index 4bbd3b4f7ae6..70d6ba09501b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h @@ -1262,6 +1262,8 @@ struct dcn10_dpp { bool is_write_to_ram_a_safe; }; + + enum dcn10_input_csc_select { INPUT_CSC_SELECT_BYPASS = 0, INPUT_CSC_SELECT_ICSC, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c index d698fccdef68..840dd0346782 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c @@ -29,6 +29,7 @@ #include "reg_helper.h" #include "dcn10_dpp.h" +#include "dcn10_dpp_cm_helper.h" #include "basics/conversion.h" #define NUM_PHASES 64 @@ -116,37 +117,7 @@ static const struct dcn10_input_csc_matrix dcn10_input_csc_matrix[] = { 0x2568, 0x43ee, 0xdbb2} } }; -static void dpp_cm_program_color_registers( - struct dcn10_dpp *xfm, - const uint16_t *regval, - uint32_t cm_reg_start, - uint32_t cm_reg_end) -{ - uint32_t reg_region_cur; - unsigned int i = 0; - -#undef REG -#define REG(reg) reg - - for (reg_region_cur = cm_reg_start; - reg_region_cur <= cm_reg_end; - reg_region_cur++) { - - const uint16_t *regval0 = &(regval[2 * i]); - const uint16_t *regval1 = &(regval[(2 * i) + 1]); - REG_SET_2(reg_region_cur, 0, - CM_GAMUT_REMAP_C11, *regval0, - CM_GAMUT_REMAP_C12, *regval1); - - i++; - } - -#undef REG -#define REG(reg)\ - xfm->tf_regs->reg - -} static void program_gamut_remap( struct dcn10_dpp *xfm, @@ -154,6 +125,7 @@ static void program_gamut_remap( enum gamut_remap_select select) { uint16_t selection = 0; + struct color_matrices_reg gam_regs; if (regval == NULL || select == GAMUT_REMAP_BYPASS) { REG_SET(CM_GAMUT_REMAP_CONTROL, 0, @@ -174,30 +146,40 @@ static void program_gamut_remap( break; } + gam_regs.shifts.csc_c11 = xfm->tf_shift->CM_GAMUT_REMAP_C11; + gam_regs.masks.csc_c11 = xfm->tf_mask->CM_GAMUT_REMAP_C11; + gam_regs.shifts.csc_c12 = xfm->tf_shift->CM_GAMUT_REMAP_C12; + gam_regs.masks.csc_c12 = xfm->tf_mask->CM_GAMUT_REMAP_C12; + if (select == GAMUT_REMAP_COEFF) { + gam_regs.csc_c11_c12 = REG(CM_GAMUT_REMAP_C11_C12); + gam_regs.csc_c33_c34 = REG(CM_GAMUT_REMAP_C33_C34); - dpp_cm_program_color_registers( - xfm, + cm_helper_program_color_matrices( + xfm->base.ctx, regval, - REG(CM_GAMUT_REMAP_C11_C12), - REG(CM_GAMUT_REMAP_C33_C34)); + &gam_regs); } else if (select == GAMUT_REMAP_COMA_COEFF) { - dpp_cm_program_color_registers( - xfm, + gam_regs.csc_c11_c12 = REG(CM_COMA_C11_C12); + gam_regs.csc_c33_c34 = REG(CM_COMA_C33_C34); + + cm_helper_program_color_matrices( + xfm->base.ctx, regval, - REG(CM_COMA_C11_C12), - REG(CM_COMA_C33_C34)); + &gam_regs); } else { - dpp_cm_program_color_registers( - xfm, + gam_regs.csc_c11_c12 = REG(CM_COMB_C11_C12); + gam_regs.csc_c33_c34 = REG(CM_COMB_C33_C34); + + cm_helper_program_color_matrices( + xfm->base.ctx, regval, - REG(CM_COMB_C11_C12), - REG(CM_COMB_C33_C34)); + &gam_regs); } REG_SET( @@ -278,11 +260,39 @@ void dcn10_dpp_cm_set_output_csc_default( } +static void dcn10_dpp_cm_get_reg_field( + struct dcn10_dpp *xfm, + struct xfer_func_reg *reg) +{ + reg->shifts.exp_region0_lut_offset = xfm->tf_shift->CM_RGAM_RAMA_EXP_REGION0_LUT_OFFSET; + reg->masks.exp_region0_lut_offset = xfm->tf_mask->CM_RGAM_RAMA_EXP_REGION0_LUT_OFFSET; + reg->shifts.exp_region0_num_segments = xfm->tf_shift->CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS; + reg->masks.exp_region0_num_segments = xfm->tf_mask->CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS; + reg->shifts.exp_region1_lut_offset = xfm->tf_shift->CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET; + reg->masks.exp_region1_lut_offset = xfm->tf_mask->CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET; + reg->shifts.exp_region1_num_segments = xfm->tf_shift->CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS; + reg->masks.exp_region1_num_segments = xfm->tf_mask->CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS; + + reg->shifts.field_region_end = xfm->tf_shift->CM_RGAM_RAMB_EXP_REGION_END_B; + reg->masks.field_region_end = xfm->tf_mask->CM_RGAM_RAMB_EXP_REGION_END_B; + reg->shifts.field_region_end_slope = xfm->tf_shift->CM_RGAM_RAMB_EXP_REGION_END_SLOPE_B; + reg->masks.field_region_end_slope = xfm->tf_mask->CM_RGAM_RAMB_EXP_REGION_END_SLOPE_B; + reg->shifts.field_region_end_base = xfm->tf_shift->CM_RGAM_RAMB_EXP_REGION_END_BASE_B; + reg->masks.field_region_end_base = xfm->tf_mask->CM_RGAM_RAMB_EXP_REGION_END_BASE_B; + reg->shifts.field_region_linear_slope = xfm->tf_shift->CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B; + reg->masks.field_region_linear_slope = xfm->tf_mask->CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B; + reg->shifts.exp_region_start = xfm->tf_shift->CM_RGAM_RAMB_EXP_REGION_START_B; + reg->masks.exp_region_start = xfm->tf_mask->CM_RGAM_RAMB_EXP_REGION_START_B; + reg->shifts.exp_resion_start_segment = xfm->tf_shift->CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B; + reg->masks.exp_resion_start_segment = xfm->tf_mask->CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B; +} + static void dcn10_dpp_cm_program_color_matrix( struct dcn10_dpp *xfm, const struct out_csc_color_matrix *tbl_entry) { uint32_t mode; + struct color_matrices_reg gam_regs; REG_GET(CM_OCSC_CONTROL, CM_OCSC_MODE, &mode); @@ -291,21 +301,30 @@ static void dcn10_dpp_cm_program_color_matrix( return; } + gam_regs.shifts.csc_c11 = xfm->tf_shift->CM_OCSC_C11; + gam_regs.masks.csc_c11 = xfm->tf_mask->CM_OCSC_C11; + gam_regs.shifts.csc_c12 = xfm->tf_shift->CM_OCSC_C12; + gam_regs.masks.csc_c12 = xfm->tf_mask->CM_OCSC_C12; + if (mode == 4) { - dpp_cm_program_color_registers( - xfm, + gam_regs.csc_c11_c12 = REG(CM_OCSC_C11_C12); + gam_regs.csc_c33_c34 = REG(CM_OCSC_C33_C34); + + cm_helper_program_color_matrices( + xfm->base.ctx, tbl_entry->regval, - REG(CM_OCSC_C11_C12), - REG(CM_OCSC_C33_C34)); + &gam_regs); } else { - dpp_cm_program_color_registers( - xfm, + gam_regs.csc_c11_c12 = REG(CM_COMB_C11_C12); + gam_regs.csc_c33_c34 = REG(CM_COMB_C33_C34); + + cm_helper_program_color_matrices( + xfm->base.ctx, tbl_entry->regval, - REG(CM_COMB_C11_C12), - REG(CM_COMB_C33_C34)); + &gam_regs); } } @@ -394,101 +413,15 @@ void dcn10_dpp_cm_configure_regamma_lut( REG_SET(CM_RGAM_LUT_INDEX, 0, CM_RGAM_LUT_INDEX, 0); } -struct cm_gam_ram_reg { - uint32_t start_cntl_b; - uint32_t start_cntl_g; - uint32_t start_cntl_r; - uint32_t start_slope_cntl_b; - uint32_t start_slope_cntl_g; - uint32_t start_slope_cntl_r; - uint32_t start_end_cntl1_b; - uint32_t start_end_cntl2_b; - uint32_t start_end_cntl1_g; - uint32_t start_end_cntl2_g; - uint32_t start_end_cntl1_r; - uint32_t start_end_cntl2_r; - uint32_t region_start; - uint32_t region_end; -}; - -static void dpp_cm_program_region_lut( - struct transform *xfm_base, - const struct pwl_params *params, - const struct cm_gam_ram_reg *reg) -{ - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); - uint32_t reg_region_cur; - unsigned int i = 0; - -#undef REG -#define REG(reg) reg - - REG_SET_2(reg->start_cntl_b, 0, - CM_RGAM_RAMA_EXP_REGION_START_B, params->arr_points[0].custom_float_x, - CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_B, 0); - REG_SET_2(reg->start_cntl_g, 0, - CM_RGAM_RAMA_EXP_REGION_START_G, params->arr_points[0].custom_float_x, - CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_G, 0); - REG_SET_2(reg->start_cntl_r, 0, - CM_RGAM_RAMA_EXP_REGION_START_R, params->arr_points[0].custom_float_x, - CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_R, 0); - - REG_SET(reg->start_slope_cntl_b, 0, - CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B, params->arr_points[0].custom_float_slope); - REG_SET(reg->start_slope_cntl_g, 0, - CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G, params->arr_points[0].custom_float_slope); - REG_SET(reg->start_slope_cntl_r, 0, - CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R, params->arr_points[0].custom_float_slope); - - REG_SET(reg->start_end_cntl1_b, 0, - CM_RGAM_RAMA_EXP_REGION_END_B, params->arr_points[1].custom_float_x); - REG_SET_2(reg->start_end_cntl2_b, 0, - CM_RGAM_RAMA_EXP_REGION_END_SLOPE_B, params->arr_points[1].custom_float_slope, - CM_RGAM_RAMA_EXP_REGION_END_BASE_B, params->arr_points[1].custom_float_y); - - REG_SET(reg->start_end_cntl1_g, 0, - CM_RGAM_RAMA_EXP_REGION_END_G, params->arr_points[1].custom_float_x); - REG_SET_2(reg->start_end_cntl2_g, 0, - CM_RGAM_RAMA_EXP_REGION_END_SLOPE_G, params->arr_points[1].custom_float_slope, - CM_RGAM_RAMA_EXP_REGION_END_BASE_G, params->arr_points[1].custom_float_y); - - REG_SET(reg->start_end_cntl1_r, 0, - CM_RGAM_RAMA_EXP_REGION_END_R, params->arr_points[1].custom_float_x); - REG_SET_2(reg->start_end_cntl2_r, 0, - CM_RGAM_RAMA_EXP_REGION_END_SLOPE_R, params->arr_points[1].custom_float_slope, - CM_RGAM_RAMA_EXP_REGION_END_BASE_R, params->arr_points[1].custom_float_y); - - for (reg_region_cur = reg->region_start; - reg_region_cur <= reg->region_end; - reg_region_cur++) { - - const struct gamma_curve *curve0 = &(params->arr_curve_points[2 * i]); - const struct gamma_curve *curve1 = &(params->arr_curve_points[(2 * i) + 1]); - - REG_SET_4(reg_region_cur, 0, - CM_RGAM_RAMA_EXP_REGION0_LUT_OFFSET, curve0->offset, - CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS, curve0->segments_num, - CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET, curve1->offset, - CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS, curve1->segments_num); - - i++; - } - -#undef REG -#define REG(reg)\ - xfm->tf_regs->reg - -} - - - /*program re gamma RAM A*/ void dcn10_dpp_cm_program_regamma_luta_settings( struct transform *xfm_base, const struct pwl_params *params) { struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); - struct cm_gam_ram_reg gam_regs; + struct xfer_func_reg gam_regs; + + dcn10_dpp_cm_get_reg_field(xfm, &gam_regs); gam_regs.start_cntl_b = REG(CM_RGAM_RAMA_START_CNTL_B); gam_regs.start_cntl_g = REG(CM_RGAM_RAMA_START_CNTL_G); @@ -505,7 +438,7 @@ void dcn10_dpp_cm_program_regamma_luta_settings( gam_regs.region_start = REG(CM_RGAM_RAMA_REGION_0_1); gam_regs.region_end = REG(CM_RGAM_RAMA_REGION_32_33); - dpp_cm_program_region_lut(xfm_base, params, &gam_regs); + cm_helper_program_xfer_func(xfm->base.ctx, params, &gam_regs); } @@ -515,7 +448,9 @@ void dcn10_dpp_cm_program_regamma_lutb_settings( const struct pwl_params *params) { struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); - struct cm_gam_ram_reg gam_regs; + struct xfer_func_reg gam_regs; + + dcn10_dpp_cm_get_reg_field(xfm, &gam_regs); gam_regs.start_cntl_b = REG(CM_RGAM_RAMB_START_CNTL_B); gam_regs.start_cntl_g = REG(CM_RGAM_RAMB_START_CNTL_G); @@ -532,7 +467,7 @@ void dcn10_dpp_cm_program_regamma_lutb_settings( gam_regs.region_start = REG(CM_RGAM_RAMB_REGION_0_1); gam_regs.region_end = REG(CM_RGAM_RAMB_REGION_32_33); - dpp_cm_program_region_lut(xfm_base, params, &gam_regs); + cm_helper_program_xfer_func(xfm->base.ctx, params, &gam_regs); } void ippn10_program_input_csc( @@ -545,6 +480,7 @@ void ippn10_program_input_csc( int arr_size = sizeof(dcn10_input_csc_matrix)/sizeof(struct dcn10_input_csc_matrix); const uint16_t *regval = NULL; uint32_t selection = 1; + struct color_matrices_reg gam_regs; if (select == INPUT_CSC_SELECT_BYPASS) { REG_SET(CM_ICSC_CONTROL, 0, CM_ICSC_MODE, 0); @@ -567,20 +503,30 @@ void ippn10_program_input_csc( REG_SET(CM_ICSC_CONTROL, 0, CM_ICSC_MODE, selection); + gam_regs.shifts.csc_c11 = xfm->tf_shift->CM_ICSC_C11; + gam_regs.masks.csc_c11 = xfm->tf_mask->CM_ICSC_C11; + gam_regs.shifts.csc_c12 = xfm->tf_shift->CM_ICSC_C12; + gam_regs.masks.csc_c12 = xfm->tf_mask->CM_ICSC_C12; + + if (select == INPUT_CSC_SELECT_ICSC) { - dpp_cm_program_color_registers( - xfm, + gam_regs.csc_c11_c12 = REG(CM_ICSC_C11_C12); + gam_regs.csc_c33_c34 = REG(CM_ICSC_C33_C34); + + cm_helper_program_color_matrices( + xfm->base.ctx, regval, - REG(CM_ICSC_C11_C12), - REG(CM_ICSC_C33_C34)); + &gam_regs); } else { - dpp_cm_program_color_registers( - xfm, + gam_regs.csc_c11_c12 = REG(CM_COMA_C11_C12); + gam_regs.csc_c33_c34 = REG(CM_COMA_C33_C34); + + cm_helper_program_color_matrices( + xfm->base.ctx, regval, - REG(CM_COMA_C11_C12), - REG(CM_COMA_C33_C34)); + &gam_regs); } } @@ -590,7 +536,9 @@ void ippn10_program_degamma_lutb_settings( const struct pwl_params *params) { struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); - struct cm_gam_ram_reg gam_regs; + struct xfer_func_reg gam_regs; + + dcn10_dpp_cm_get_reg_field(xfm, &gam_regs); gam_regs.start_cntl_b = REG(CM_DGAM_RAMB_START_CNTL_B); gam_regs.start_cntl_g = REG(CM_DGAM_RAMB_START_CNTL_G); @@ -607,7 +555,8 @@ void ippn10_program_degamma_lutb_settings( gam_regs.region_start = REG(CM_DGAM_RAMB_REGION_0_1); gam_regs.region_end = REG(CM_DGAM_RAMB_REGION_14_15); - dpp_cm_program_region_lut(xfm_base, params, &gam_regs); + + cm_helper_program_xfer_func(xfm->base.ctx, params, &gam_regs); } /*program de gamma RAM A*/ @@ -616,7 +565,9 @@ void ippn10_program_degamma_luta_settings( const struct pwl_params *params) { struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); - struct cm_gam_ram_reg gam_regs; + struct xfer_func_reg gam_regs; + + dcn10_dpp_cm_get_reg_field(xfm, &gam_regs); gam_regs.start_cntl_b = REG(CM_DGAM_RAMA_START_CNTL_B); gam_regs.start_cntl_g = REG(CM_DGAM_RAMA_START_CNTL_G); @@ -633,7 +584,7 @@ void ippn10_program_degamma_luta_settings( gam_regs.region_start = REG(CM_DGAM_RAMA_REGION_0_1); gam_regs.region_end = REG(CM_DGAM_RAMA_REGION_14_15); - dpp_cm_program_region_lut(xfm_base, params, &gam_regs); + cm_helper_program_xfer_func(xfm->base.ctx, params, &gam_regs); } void ippn10_power_on_degamma_lut( diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm_helper.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm_helper.c new file mode 100644 index 000000000000..f616e08759de --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm_helper.c @@ -0,0 +1,123 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "reg_helper.h" +#include "dcn10_dpp.h" + +#include "dcn10_dpp_cm_helper.h" + +#define REG(reg) reg + +#define CTX \ + ctx + +#undef FN +#define FN(reg_name, field_name) \ + reg->shifts.field_name, reg->masks.field_name + +void cm_helper_program_color_matrices( + struct dc_context *ctx, + const uint16_t *regval, + const struct color_matrices_reg *reg) +{ + uint32_t cur_csc_reg; + unsigned int i = 0; + + for (cur_csc_reg = reg->csc_c11_c12; + cur_csc_reg <= reg->csc_c33_c34; + cur_csc_reg++) { + + const uint16_t *regval0 = &(regval[2 * i]); + const uint16_t *regval1 = &(regval[(2 * i) + 1]); + + REG_SET_2(cur_csc_reg, 0, + csc_c11, *regval0, + csc_c12, *regval1); + + i++; + } + +} + +void cm_helper_program_xfer_func( + struct dc_context *ctx, + const struct pwl_params *params, + const struct xfer_func_reg *reg) +{ + uint32_t reg_region_cur; + unsigned int i = 0; + + REG_SET_2(reg->start_cntl_b, 0, + exp_region_start, params->arr_points[0].custom_float_x, + exp_resion_start_segment, 0); + REG_SET_2(reg->start_cntl_g, 0, + exp_region_start, params->arr_points[0].custom_float_x, + exp_resion_start_segment, 0); + REG_SET_2(reg->start_cntl_r, 0, + exp_region_start, params->arr_points[0].custom_float_x, + exp_resion_start_segment, 0); + + REG_SET(reg->start_slope_cntl_b, 0, + field_region_linear_slope, params->arr_points[0].custom_float_slope); + REG_SET(reg->start_slope_cntl_g, 0, + field_region_linear_slope, params->arr_points[0].custom_float_slope); + REG_SET(reg->start_slope_cntl_r, 0, + field_region_linear_slope, params->arr_points[0].custom_float_slope); + + REG_SET(reg->start_end_cntl1_b, 0, + field_region_end, params->arr_points[1].custom_float_x); + REG_SET_2(reg->start_end_cntl2_b, 0, + field_region_end_slope, params->arr_points[1].custom_float_slope, + field_region_end_base, params->arr_points[1].custom_float_y); + + REG_SET(reg->start_end_cntl1_g, 0, + field_region_end, params->arr_points[1].custom_float_x); + REG_SET_2(reg->start_end_cntl2_g, 0, + field_region_end_slope, params->arr_points[1].custom_float_slope, + field_region_end_base, params->arr_points[1].custom_float_y); + + REG_SET(reg->start_end_cntl1_r, 0, + field_region_end, params->arr_points[1].custom_float_x); + REG_SET_2(reg->start_end_cntl2_r, 0, + field_region_end_slope, params->arr_points[1].custom_float_slope, + field_region_end_base, params->arr_points[1].custom_float_y); + + for (reg_region_cur = reg->region_start; + reg_region_cur <= reg->region_end; + reg_region_cur++) { + + const struct gamma_curve *curve0 = &(params->arr_curve_points[2 * i]); + const struct gamma_curve *curve1 = &(params->arr_curve_points[(2 * i) + 1]); + + REG_SET_4(reg_region_cur, 0, + exp_region0_lut_offset, curve0->offset, + exp_region0_num_segments, curve0->segments_num, + exp_region1_lut_offset, curve1->offset, + exp_region1_num_segments, curve1->segments_num); + + i++; + } + +} diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm_helper.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm_helper.h new file mode 100644 index 000000000000..1155ee522898 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm_helper.h @@ -0,0 +1,99 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_DPP_DCN10_CM_HELPER_H__ +#define __DAL_DPP_DCN10_CM_HELPER_H__ + +#define TF_HELPER_REG_FIELD_LIST(type) \ + type exp_region0_lut_offset; \ + type exp_region0_num_segments; \ + type exp_region1_lut_offset; \ + type exp_region1_num_segments;\ + type field_region_end;\ + type field_region_end_slope;\ + type field_region_end_base;\ + type exp_region_start;\ + type exp_resion_start_segment;\ + type field_region_linear_slope + +#define TF_CM_REG_FIELD_LIST(type) \ + type csc_c11; \ + type csc_c12 + +struct xfer_func_shift { + TF_HELPER_REG_FIELD_LIST(uint8_t); +}; + +struct xfer_func_mask { + TF_HELPER_REG_FIELD_LIST(uint32_t); +}; + +struct xfer_func_reg { + struct xfer_func_shift shifts; + struct xfer_func_mask masks; + + uint32_t start_cntl_b; + uint32_t start_cntl_g; + uint32_t start_cntl_r; + uint32_t start_slope_cntl_b; + uint32_t start_slope_cntl_g; + uint32_t start_slope_cntl_r; + uint32_t start_end_cntl1_b; + uint32_t start_end_cntl2_b; + uint32_t start_end_cntl1_g; + uint32_t start_end_cntl2_g; + uint32_t start_end_cntl1_r; + uint32_t start_end_cntl2_r; + uint32_t region_start; + uint32_t region_end; +}; + +struct cm_color_matrix_shift { + TF_CM_REG_FIELD_LIST(uint8_t); +}; + +struct cm_color_matrix_mask { + TF_CM_REG_FIELD_LIST(uint32_t); +}; + +struct color_matrices_reg{ + struct cm_color_matrix_shift shifts; + struct cm_color_matrix_mask masks; + + uint32_t csc_c11_c12; + uint32_t csc_c33_c34; +}; + +void cm_helper_program_color_matrices( + struct dc_context *ctx, + const uint16_t *regval, + const struct color_matrices_reg *reg); + +void cm_helper_program_xfer_func( + struct dc_context *ctx, + const struct pwl_params *params, + const struct xfer_func_reg *reg); + +#endif -- cgit From 4a6295361c737a80e9f079952ac863a3b0c26acf Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 28 Aug 2017 18:43:45 -0400 Subject: drm/amd/display: Don't reset clock source at unref Powering down the clock source during unref is unsafe as we might want to unref during atomic_check Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 25 ++++++++++++++-------- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 16 +++++++++----- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 9 +++++--- drivers/gpu/drm/amd/display/dc/inc/resource.h | 4 ++-- 4 files changed, 35 insertions(+), 19 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index ce721b77c1bc..57c3dcd3fadd 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -261,31 +261,34 @@ bool resource_construct( } -void resource_unreference_clock_source( +bool resource_unreference_clock_source( struct resource_context *res_ctx, const struct resource_pool *pool, - struct clock_source **clock_source) + struct clock_source *clock_source) { int i; + bool need_reset = false; + for (i = 0; i < pool->clk_src_count; i++) { - if (pool->clock_sources[i] != *clock_source) + if (pool->clock_sources[i] != clock_source) continue; res_ctx->clock_source_ref_count[i]--; if (res_ctx->clock_source_ref_count[i] == 0) - (*clock_source)->funcs->cs_power_down(*clock_source); + need_reset = true; break; } - if (pool->dp_clock_source == *clock_source) { + if (pool->dp_clock_source == clock_source) { res_ctx->dp_clock_source_ref_count--; if (res_ctx->dp_clock_source_ref_count == 0) - (*clock_source)->funcs->cs_power_down(*clock_source); + need_reset = true; } - *clock_source = NULL; + + return need_reset; } void resource_reference_clock_source( @@ -1756,10 +1759,14 @@ bool dc_validate_global_state( if (dc_is_dp_signal(pipe_ctx->stream->signal) && !find_pll_sharable_stream(stream, new_ctx)) { - resource_unreference_clock_source( + if (resource_unreference_clock_source( &new_ctx->res_ctx, dc->res_pool, - &pipe_ctx->clock_source); + pipe_ctx->clock_source)) { + pipe_ctx->clock_source->funcs->cs_power_down(pipe_ctx->clock_source); + pipe_ctx->clock_source = NULL; + } + pipe_ctx->clock_source = dc->res_pool->dp_clock_source; resource_reference_clock_source( &new_ctx->res_ctx, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index b36220bc619d..75c636cba545 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1362,9 +1362,12 @@ static void switch_dp_clock_sources( if (clk_src && clk_src != pipe_ctx->clock_source) { - resource_unreference_clock_source( - res_ctx, dc->res_pool, - &pipe_ctx->clock_source); + if (resource_unreference_clock_source(res_ctx, + dc->res_pool, pipe_ctx->clock_source)) { + pipe_ctx->clock_source->funcs->cs_power_down(pipe_ctx->clock_source); + pipe_ctx->clock_source = NULL; + } + pipe_ctx->clock_source = clk_src; resource_reference_clock_source( res_ctx, dc->res_pool, clk_src); @@ -1680,9 +1683,12 @@ static void dce110_reset_hw_ctx_wrap( pipe_ctx_old->stream_res.tg->funcs->disable_crtc(pipe_ctx_old->stream_res.tg); pipe_ctx_old->plane_res.mi->funcs->free_mem_input( pipe_ctx_old->plane_res.mi, dc->current_state->stream_count); - resource_unreference_clock_source( + if (resource_unreference_clock_source( &dc->current_state->res_ctx, dc->res_pool, - &pipe_ctx_old->clock_source); + pipe_ctx_old->clock_source)) { + pipe_ctx_old->clock_source->funcs->cs_power_down(pipe_ctx_old->clock_source); + pipe_ctx_old->clock_source = NULL; + } dc->hwss.power_down_front_end(dc, pipe_ctx_old->pipe_idx); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 6b76fc417456..7460560fbefc 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1045,9 +1045,12 @@ static void reset_back_end_for_pipe( } if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) - resource_unreference_clock_source( - &context->res_ctx, dc->res_pool, - &pipe_ctx->clock_source); + if (resource_unreference_clock_source(&context->res_ctx, + dc->res_pool, pipe_ctx->clock_source)) { + pipe_ctx->clock_source->funcs->cs_power_down(pipe_ctx->clock_source); + pipe_ctx->clock_source = NULL; + } + for (i = 0; i < dc->res_pool->pipe_count; i++) if (&dc->current_state->res_ctx.pipe_ctx[i] == pipe_ctx) diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index 41437da5fb9b..cf1797c191e9 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -92,10 +92,10 @@ enum dc_status resource_build_scaling_params_for_context( void resource_build_info_frame(struct pipe_ctx *pipe_ctx); -void resource_unreference_clock_source( +bool resource_unreference_clock_source( struct resource_context *res_ctx, const struct resource_pool *pool, - struct clock_source **clock_source); + struct clock_source *clock_source); void resource_reference_clock_source( struct resource_context *res_ctx, -- cgit From 9d0dcecd93e4997c65b18404f1ab2fce2ab79010 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 28 Aug 2017 19:05:17 -0400 Subject: drm/amd/display: Power down clock source at commit Still one more in dc_validate_global Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 19 ++++++++++------- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 22 ++++++++++++++------ .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 24 ++++++++++++++-------- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 2 ++ 4 files changed, 46 insertions(+), 21 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 57c3dcd3fadd..9aa0da743174 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -275,8 +275,10 @@ bool resource_unreference_clock_source( res_ctx->clock_source_ref_count[i]--; - if (res_ctx->clock_source_ref_count[i] == 0) + if (res_ctx->clock_source_ref_count[i] == 0) { + res_ctx->clock_source_changed[i] = true; need_reset = true; + } break; } @@ -284,8 +286,10 @@ bool resource_unreference_clock_source( if (pool->dp_clock_source == clock_source) { res_ctx->dp_clock_source_ref_count--; - if (res_ctx->dp_clock_source_ref_count == 0) + if (res_ctx->dp_clock_source_ref_count == 0) { + res_ctx->dp_clock_source_changed = true; need_reset = true; + } } return need_reset; @@ -1502,6 +1506,10 @@ bool dc_remove_stream_from_ctx( del_pipe->stream_res.audio, false); + resource_unreference_clock_source(&new_ctx->res_ctx, + dc->res_pool, + del_pipe->clock_source); + memset(del_pipe, 0, sizeof(*del_pipe)); break; @@ -1759,13 +1767,10 @@ bool dc_validate_global_state( if (dc_is_dp_signal(pipe_ctx->stream->signal) && !find_pll_sharable_stream(stream, new_ctx)) { - if (resource_unreference_clock_source( + resource_unreference_clock_source( &new_ctx->res_ctx, dc->res_pool, - pipe_ctx->clock_source)) { - pipe_ctx->clock_source->funcs->cs_power_down(pipe_ctx->clock_source); - pipe_ctx->clock_source = NULL; - } + pipe_ctx->clock_source); pipe_ctx->clock_source = dc->res_pool->dp_clock_source; resource_reference_clock_source( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 75c636cba545..96db166b7fba 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1683,18 +1683,28 @@ static void dce110_reset_hw_ctx_wrap( pipe_ctx_old->stream_res.tg->funcs->disable_crtc(pipe_ctx_old->stream_res.tg); pipe_ctx_old->plane_res.mi->funcs->free_mem_input( pipe_ctx_old->plane_res.mi, dc->current_state->stream_count); - if (resource_unreference_clock_source( - &dc->current_state->res_ctx, dc->res_pool, - pipe_ctx_old->clock_source)) { - pipe_ctx_old->clock_source->funcs->cs_power_down(pipe_ctx_old->clock_source); - pipe_ctx_old->clock_source = NULL; - } dc->hwss.power_down_front_end(dc, pipe_ctx_old->pipe_idx); pipe_ctx_old->stream = NULL; } } + + /* power down changed clock sources */ + for (i = 0; i < dc->res_pool->clk_src_count; i++) + if (context->res_ctx.clock_source_changed[i]) { + struct clock_source *clk = dc->res_pool->clock_sources[i]; + + clk->funcs->cs_power_down(clk); + context->res_ctx.clock_source_changed[i] = false; + } + + if (context->res_ctx.dp_clock_source_changed) { + struct clock_source *clk = dc->res_pool->dp_clock_source; + + clk->funcs->cs_power_down(clk); + context->res_ctx.clock_source_changed[i] = false; + } } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 7460560fbefc..a1f4a00e5e04 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1044,14 +1044,6 @@ static void reset_back_end_for_pipe( pipe_ctx->stream_res.tg->funcs->enable_optc_clock(pipe_ctx->stream_res.tg, false); } - if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) - if (resource_unreference_clock_source(&context->res_ctx, - dc->res_pool, pipe_ctx->clock_source)) { - pipe_ctx->clock_source->funcs->cs_power_down(pipe_ctx->clock_source); - pipe_ctx->clock_source = NULL; - } - - for (i = 0; i < dc->res_pool->pipe_count; i++) if (&dc->current_state->res_ctx.pipe_ctx[i] == pipe_ctx) break; @@ -1273,6 +1265,22 @@ static void reset_hw_ctx_wrap( plane_atomic_power_down(dc, i); } + /* power down changed clock sources */ + for (i = 0; i < dc->res_pool->clk_src_count; i++) + if (context->res_ctx.clock_source_changed[i]) { + struct clock_source *clk = dc->res_pool->clock_sources[i]; + + clk->funcs->cs_power_down(clk); + context->res_ctx.clock_source_changed[i] = false; + } + + if (context->res_ctx.dp_clock_source_changed) { + struct clock_source *clk = dc->res_pool->dp_clock_source; + + clk->funcs->cs_power_down(clk); + context->res_ctx.dp_clock_source_changed = false; + } + /* Reset Back End*/ for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) { struct pipe_ctx *pipe_ctx_old = diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 915d5c10361b..b6a513d6feda 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -213,7 +213,9 @@ struct resource_context { bool is_stream_enc_acquired[MAX_PIPES * 2]; bool is_audio_acquired[MAX_PIPES]; uint8_t clock_source_ref_count[MAX_CLOCK_SOURCES]; + bool clock_source_changed[MAX_CLOCK_SOURCES]; uint8_t dp_clock_source_ref_count; + bool dp_clock_source_changed; }; struct dce_bw_output { -- cgit From b8ea60cea245e8cd68b6ac45b9680a590f76391a Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 28 Aug 2017 19:44:38 -0400 Subject: drm/amd/display: Remove switching of clk sources at end of commit This should be taken care of in validate now. All of timing sync is quite broken at the moment anyways. Will submit another patch set to address that. Signed-off-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 36 ---------------------- 1 file changed, 36 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 96db166b7fba..c57dc45d6677 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1344,40 +1344,6 @@ static void set_safe_displaymarks( } } -static void switch_dp_clock_sources( - const struct dc *dc, - struct resource_context *res_ctx) -{ - uint8_t i; - for (i = 0; i < MAX_PIPES; i++) { - struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; - - if (pipe_ctx->stream == NULL || pipe_ctx->top_pipe) - continue; - - if (dc_is_dp_signal(pipe_ctx->stream->signal)) { - struct clock_source *clk_src = - resource_find_used_clk_src_for_sharing( - res_ctx, pipe_ctx); - - if (clk_src && - clk_src != pipe_ctx->clock_source) { - if (resource_unreference_clock_source(res_ctx, - dc->res_pool, pipe_ctx->clock_source)) { - pipe_ctx->clock_source->funcs->cs_power_down(pipe_ctx->clock_source); - pipe_ctx->clock_source = NULL; - } - - pipe_ctx->clock_source = clk_src; - resource_reference_clock_source( - res_ctx, dc->res_pool, clk_src); - - dce_crtc_switch_to_clk_src(dc->hwseq, clk_src, i); - } - } - } -} - /******************************************************************************* * Public functions ******************************************************************************/ @@ -1939,8 +1905,6 @@ enum dc_status dce110_apply_ctx_to_hw( dcb->funcs->set_scratch_critical_state(dcb, false); - switch_dp_clock_sources(dc, &context->res_ctx); - #ifdef ENABLE_FBC if (dc->fbc_compressor) enable_fbc(dc, context); -- cgit From 264efa31835dd87af4e77e3a27090e60d4fe1511 Mon Sep 17 00:00:00 2001 From: Eric Bernstein Date: Thu, 31 Aug 2017 16:04:24 -0400 Subject: drm/amd/display: remove output_format from ipp_setup Signed-off-by: Eric Bernstein Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c | 3 +-- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h | 3 +-- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c | 4 ++-- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 3 +-- drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h | 3 +-- drivers/gpu/drm/amd/display/dc/inc/hw/transform.h | 3 +-- 6 files changed, 7 insertions(+), 12 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c index 99caafb27b37..487694125ea4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c @@ -266,8 +266,7 @@ static void ippn10_set_degamma_format_float( void ippn10_cnv_setup ( struct transform *xfm_base, enum surface_pixel_format input_format, - enum expansion_mode mode, - enum ipp_output_format cnv_out_format) + enum expansion_mode mode) { uint32_t pixel_format; uint32_t alpha_en; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h index 70d6ba09501b..34e501979b55 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h @@ -1358,8 +1358,7 @@ void dcn10_dpp_dscl_set_scaler_manual_scale( void ippn10_cnv_setup ( struct transform *xfm_base, enum surface_pixel_format input_format, - enum expansion_mode mode, - enum ipp_output_format cnv_out_format); + enum expansion_mode mode); void ippn10_full_bypass(struct transform *xfm_base); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c index 840dd0346782..d0e72acfc1d5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c @@ -727,11 +727,11 @@ void ippn10_full_bypass(struct transform *xfm_base) FORMAT_EXPANSION_MODE, 0); /* COLOR_KEYER_CONTROL.COLOR_KEYER_EN = 0 this should be default */ - REG_SET(CM_CONTROL, 0, CM_BYPASS_EN, 1); + if (xfm->tf_mask->CM_BYPASS_EN) + REG_SET(CM_CONTROL, 0, CM_BYPASS_EN, 1); /* Setting degamma bypass for now */ REG_SET(CM_DGAM_CONTROL, 0, CM_DGAM_LUT_MODE, 0); - REG_SET(CM_IGAM_CONTROL, 0, CM_IGAM_LUT_MODE, 0); } static bool ippn10_ingamma_ram_inuse(struct transform *xfm_base, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index a1f4a00e5e04..6fee6957c1a6 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2316,8 +2316,7 @@ static void update_dchubp_dpp( xfm->funcs->ipp_setup(xfm, plane_state->format, - 1, - IPP_OUTPUT_FORMAT_12_BIT_FIX); + EXPANSION_MODE_ZERO); mpcc_cfg.mi = mi; mpcc_cfg.opp = pipe_ctx->stream_res.opp; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h index 7ebfdc1c19c1..f11aa484f46e 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h @@ -86,8 +86,7 @@ struct ipp_funcs { void (*ipp_setup)( struct input_pixel_processor *ipp, enum surface_pixel_format input_format, - enum expansion_mode mode, - enum ipp_output_format output_format); + enum expansion_mode mode); /* DCE function to setup IPP. TODO: see if we can consolidate to setup */ void (*ipp_program_prescale)( diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h index 623042d2c272..32947450e702 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h @@ -234,8 +234,7 @@ struct transform_funcs { void (*ipp_setup)( struct transform *xfm_base, enum surface_pixel_format input_format, - enum expansion_mode mode, - enum ipp_output_format cnv_out_format); + enum expansion_mode mode); void (*ipp_full_bypass)(struct transform *xfm_base); -- cgit From e74c6972f85d48de4d2fe797ddd0fbc8bd899f0e Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Tue, 5 Sep 2017 11:50:34 -0400 Subject: drm/amd/display: move dwb registers to header file Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c | 288 +-------------------- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.h | 247 +++++++++++++++++- .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 42 +++ 3 files changed, 289 insertions(+), 288 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c index 684241cb40d7..4ec5554f0f5b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c @@ -29,32 +29,7 @@ #include "resource.h" #include "dwb.h" #include "dcn10_dwb.h" -#include "vega10/soc15ip.h" -#include "raven1/DCN/dcn_1_0_offset.h" -#include "raven1/DCN/dcn_1_0_sh_mask.h" -/* DCN */ -#define BASE_INNER(seg) \ - DCE_BASE__INST0_SEG ## seg - -#define BASE(seg) \ - BASE_INNER(seg) - -#define SR(reg_name)\ - .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + \ - mm ## reg_name - -#define SRI(reg_name, block, id)\ - .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - mm ## block ## id ## _ ## reg_name - - -#define SRII(reg_name, block, id)\ - .reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - mm ## block ## id ## _ ## reg_name - -#define SF(reg_name, field_name, post_fix)\ - .field_name = reg_name ## __ ## field_name ## post_fix #define REG(reg)\ dwbc10->dwbc_regs->reg @@ -69,240 +44,6 @@ #define TO_DCN10_DWBC(dwbc_base) \ container_of(dwbc_base, struct dcn10_dwbc, base) -#define DWBC_COMMON_REG_LIST_DCN1_0(inst) \ - SRI(WB_ENABLE, CNV, inst),\ - SRI(WB_EC_CONFIG, CNV, inst),\ - SRI(CNV_MODE, CNV, inst),\ - SRI(WB_SOFT_RESET, CNV, inst),\ - SRI(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_PITCH, MCIF_WB, inst),\ - SRI(MCIF_WB_ARBITRATION_CONTROL, MCIF_WB, inst),\ - SRI(MCIF_WB_SCLK_CHANGE, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_1_ADDR_Y, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_1_ADDR_Y_OFFSET, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_1_ADDR_C, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_1_ADDR_C_OFFSET, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_2_ADDR_Y, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_2_ADDR_Y_OFFSET, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_2_ADDR_C, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_2_ADDR_C_OFFSET, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_3_ADDR_Y, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_3_ADDR_Y_OFFSET, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_3_ADDR_C, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_3_ADDR_C_OFFSET, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_4_ADDR_Y, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_4_ADDR_Y_OFFSET, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_4_ADDR_C, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_4_ADDR_C_OFFSET, MCIF_WB, inst),\ - SRI(MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB, inst),\ - SRI(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, MCIF_WB, inst),\ - SRI(MCIF_WB_NB_PSTATE_CONTROL, MCIF_WB, inst),\ - SRI(MCIF_WB_WATERMARK, MCIF_WB, inst),\ - SRI(MCIF_WB_WARM_UP_CNTL, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_LUMA_SIZE, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_CHROMA_SIZE, MCIF_WB, inst),\ - .DWB_SOURCE_SELECT = mmDWB_SOURCE_SELECT\ - -#define DWBC_COMMON_MASK_SH_LIST_DCN1_0(mask_sh) \ - SF(CNV0_WB_ENABLE, WB_ENABLE, mask_sh),\ - SF(CNV0_WB_EC_CONFIG, DISPCLK_R_WB_GATE_DIS, mask_sh),\ - SF(CNV0_WB_EC_CONFIG, DISPCLK_G_WB_GATE_DIS, mask_sh),\ - SF(CNV0_WB_EC_CONFIG, DISPCLK_G_WBSCL_GATE_DIS, mask_sh),\ - SF(CNV0_WB_EC_CONFIG, WB_LB_LS_DIS, mask_sh),\ - SF(CNV0_WB_EC_CONFIG, WB_LUT_LS_DIS, mask_sh),\ - SF(CNV0_CNV_MODE, CNV_WINDOW_CROP_EN, mask_sh),\ - SF(CNV0_CNV_MODE, CNV_STEREO_TYPE, mask_sh),\ - SF(CNV0_CNV_MODE, CNV_INTERLACED_MODE, mask_sh),\ - SF(CNV0_CNV_MODE, CNV_EYE_SELECTION, mask_sh),\ - SF(CNV0_CNV_MODE, CNV_STEREO_POLARITY, mask_sh),\ - SF(CNV0_CNV_MODE, CNV_INTERLACED_FIELD_ORDER, mask_sh),\ - SF(CNV0_CNV_MODE, CNV_STEREO_SPLIT, mask_sh),\ - SF(CNV0_CNV_MODE, CNV_NEW_CONTENT, mask_sh),\ - SF(CNV0_CNV_MODE, CNV_FRAME_CAPTURE_EN, mask_sh),\ - SF(CNV0_WB_SOFT_RESET, WB_SOFT_RESET, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_ENABLE, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUF_DUALSIZE_REQ, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_INT_EN, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_INT_ACK, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_SLICE_INT_EN, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_OVERRUN_INT_EN, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_LOCK, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_P_VMID, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUF_ADDR_FENCE_EN, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_PITCH, MCIF_WB_BUF_LUMA_PITCH, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_PITCH, MCIF_WB_BUF_CHROMA_PITCH, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_ARBITRATION_CONTROL, MCIF_WB_CLIENT_ARBITRATION_SLICE, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_ARBITRATION_CONTROL, MCIF_WB_TIME_PER_PIXEL, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_SCLK_CHANGE, WM_CHANGE_ACK_FORCE_ON, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_SCLK_CHANGE, MCIF_WB_CLI_WATERMARK_MASK, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_1_ADDR_Y, MCIF_WB_BUF_1_ADDR_Y, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_1_ADDR_Y_OFFSET, MCIF_WB_BUF_1_ADDR_Y_OFFSET, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_1_ADDR_C, MCIF_WB_BUF_1_ADDR_C, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_1_ADDR_C_OFFSET, MCIF_WB_BUF_1_ADDR_C_OFFSET, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_2_ADDR_Y, MCIF_WB_BUF_2_ADDR_Y, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_2_ADDR_Y_OFFSET, MCIF_WB_BUF_2_ADDR_Y_OFFSET, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_2_ADDR_C, MCIF_WB_BUF_2_ADDR_C, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_2_ADDR_C_OFFSET, MCIF_WB_BUF_2_ADDR_C_OFFSET, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_3_ADDR_Y, MCIF_WB_BUF_3_ADDR_Y, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_3_ADDR_Y_OFFSET, MCIF_WB_BUF_3_ADDR_Y_OFFSET, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_3_ADDR_C, MCIF_WB_BUF_3_ADDR_C, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_3_ADDR_C_OFFSET, MCIF_WB_BUF_3_ADDR_C_OFFSET, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_4_ADDR_Y, MCIF_WB_BUF_4_ADDR_Y, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_4_ADDR_Y_OFFSET, MCIF_WB_BUF_4_ADDR_Y_OFFSET, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_4_ADDR_C, MCIF_WB_BUF_4_ADDR_C, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_4_ADDR_C_OFFSET, MCIF_WB_BUF_4_ADDR_C_OFFSET, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_LOCK_IGNORE, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_INT_EN, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_INT_ACK, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_SLICE_INT_EN, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_LOCK, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_SLICE_SIZE, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, NB_PSTATE_CHANGE_REFRESH_WATERMARK, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_CHANGE_URGENT_DURING_REQUEST, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_CHANGE_FORCE_ON, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_ALLOW_FOR_URGENT, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_CHANGE_WATERMARK_MASK, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_WATERMARK, MCIF_WB_CLI_WATERMARK, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_WARM_UP_CNTL, MCIF_WB_PITCH_SIZE_WARMUP, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_LUMA_SIZE, MCIF_WB_BUF_LUMA_SIZE, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_CHROMA_SIZE, MCIF_WB_BUF_CHROMA_SIZE, mask_sh),\ - SF(DWB_SOURCE_SELECT, OPTC_DWB0_SOURCE_SELECT, mask_sh),\ - SF(DWB_SOURCE_SELECT, OPTC_DWB1_SOURCE_SELECT, mask_sh) - -#define DWBC_REG_FIELD_LIST(type) \ - type WB_ENABLE;\ - type DISPCLK_R_WB_GATE_DIS;\ - type DISPCLK_G_WB_GATE_DIS;\ - type DISPCLK_G_WBSCL_GATE_DIS;\ - type WB_LB_LS_DIS;\ - type WB_LB_SD_DIS;\ - type WB_LUT_LS_DIS;\ - type CNV_WINDOW_CROP_EN;\ - type CNV_STEREO_TYPE;\ - type CNV_INTERLACED_MODE;\ - type CNV_EYE_SELECTION;\ - type CNV_STEREO_POLARITY;\ - type CNV_INTERLACED_FIELD_ORDER;\ - type CNV_STEREO_SPLIT;\ - type CNV_NEW_CONTENT;\ - type CNV_FRAME_CAPTURE_EN;\ - type WB_SOFT_RESET;\ - type MCIF_WB_BUFMGR_ENABLE;\ - type MCIF_WB_BUF_DUALSIZE_REQ;\ - type MCIF_WB_BUFMGR_SW_INT_EN;\ - type MCIF_WB_BUFMGR_SW_INT_ACK;\ - type MCIF_WB_BUFMGR_SW_SLICE_INT_EN;\ - type MCIF_WB_BUFMGR_SW_OVERRUN_INT_EN;\ - type MCIF_WB_BUFMGR_SW_LOCK;\ - type MCIF_WB_P_VMID;\ - type MCIF_WB_BUF_ADDR_FENCE_EN;\ - type MCIF_WB_BUF_LUMA_PITCH;\ - type MCIF_WB_BUF_CHROMA_PITCH;\ - type MCIF_WB_CLIENT_ARBITRATION_SLICE;\ - type MCIF_WB_TIME_PER_PIXEL;\ - type WM_CHANGE_ACK_FORCE_ON;\ - type MCIF_WB_CLI_WATERMARK_MASK;\ - type MCIF_WB_BUF_1_ADDR_Y;\ - type MCIF_WB_BUF_1_ADDR_Y_OFFSET;\ - type MCIF_WB_BUF_1_ADDR_C;\ - type MCIF_WB_BUF_1_ADDR_C_OFFSET;\ - type MCIF_WB_BUF_2_ADDR_Y;\ - type MCIF_WB_BUF_2_ADDR_Y_OFFSET;\ - type MCIF_WB_BUF_2_ADDR_C;\ - type MCIF_WB_BUF_2_ADDR_C_OFFSET;\ - type MCIF_WB_BUF_3_ADDR_Y;\ - type MCIF_WB_BUF_3_ADDR_Y_OFFSET;\ - type MCIF_WB_BUF_3_ADDR_C;\ - type MCIF_WB_BUF_3_ADDR_C_OFFSET;\ - type MCIF_WB_BUF_4_ADDR_Y;\ - type MCIF_WB_BUF_4_ADDR_Y_OFFSET;\ - type MCIF_WB_BUF_4_ADDR_C;\ - type MCIF_WB_BUF_4_ADDR_C_OFFSET;\ - type MCIF_WB_BUFMGR_VCE_LOCK_IGNORE;\ - type MCIF_WB_BUFMGR_VCE_INT_EN;\ - type MCIF_WB_BUFMGR_VCE_INT_ACK;\ - type MCIF_WB_BUFMGR_VCE_SLICE_INT_EN;\ - type MCIF_WB_BUFMGR_VCE_LOCK;\ - type MCIF_WB_BUFMGR_SLICE_SIZE;\ - type NB_PSTATE_CHANGE_REFRESH_WATERMARK;\ - type NB_PSTATE_CHANGE_URGENT_DURING_REQUEST;\ - type NB_PSTATE_CHANGE_FORCE_ON;\ - type NB_PSTATE_ALLOW_FOR_URGENT;\ - type NB_PSTATE_CHANGE_WATERMARK_MASK;\ - type MCIF_WB_CLI_WATERMARK;\ - type MCIF_WB_CLI_CLOCK_GATER_OVERRIDE;\ - type MCIF_WB_PITCH_SIZE_WARMUP;\ - type MCIF_WB_BUF_LUMA_SIZE;\ - type MCIF_WB_BUF_CHROMA_SIZE;\ - type OPTC_DWB0_SOURCE_SELECT;\ - type OPTC_DWB1_SOURCE_SELECT;\ - -struct dcn10_dwbc_registers { - uint32_t WB_ENABLE; - uint32_t WB_EC_CONFIG; - uint32_t CNV_MODE; - uint32_t WB_SOFT_RESET; - uint32_t MCIF_WB_BUFMGR_SW_CONTROL; - uint32_t MCIF_WB_BUF_PITCH; - uint32_t MCIF_WB_ARBITRATION_CONTROL; - uint32_t MCIF_WB_SCLK_CHANGE; - uint32_t MCIF_WB_BUF_1_ADDR_Y; - uint32_t MCIF_WB_BUF_1_ADDR_Y_OFFSET; - uint32_t MCIF_WB_BUF_1_ADDR_C; - uint32_t MCIF_WB_BUF_1_ADDR_C_OFFSET; - uint32_t MCIF_WB_BUF_2_ADDR_Y; - uint32_t MCIF_WB_BUF_2_ADDR_Y_OFFSET; - uint32_t MCIF_WB_BUF_2_ADDR_C; - uint32_t MCIF_WB_BUF_2_ADDR_C_OFFSET; - uint32_t MCIF_WB_BUF_3_ADDR_Y; - uint32_t MCIF_WB_BUF_3_ADDR_Y_OFFSET; - uint32_t MCIF_WB_BUF_3_ADDR_C; - uint32_t MCIF_WB_BUF_3_ADDR_C_OFFSET; - uint32_t MCIF_WB_BUF_4_ADDR_Y; - uint32_t MCIF_WB_BUF_4_ADDR_Y_OFFSET; - uint32_t MCIF_WB_BUF_4_ADDR_C; - uint32_t MCIF_WB_BUF_4_ADDR_C_OFFSET; - uint32_t MCIF_WB_BUFMGR_VCE_CONTROL; - uint32_t MCIF_WB_NB_PSTATE_LATENCY_WATERMARK; - uint32_t MCIF_WB_NB_PSTATE_CONTROL; - uint32_t MCIF_WB_WATERMARK; - uint32_t MCIF_WB_WARM_UP_CNTL; - uint32_t MCIF_WB_BUF_LUMA_SIZE; - uint32_t MCIF_WB_BUF_CHROMA_SIZE; - uint32_t DWB_SOURCE_SELECT; -}; -struct dcn10_dwbc_mask { - DWBC_REG_FIELD_LIST(uint32_t) -}; -struct dcn10_dwbc_shift { - DWBC_REG_FIELD_LIST(uint8_t) -}; -struct dcn10_dwbc { - struct dwbc base; - const struct dcn10_dwbc_registers *dwbc_regs; - const struct dcn10_dwbc_shift *dwbc_shift; - const struct dcn10_dwbc_mask *dwbc_mask; -}; - -#define dwbc_regs(id)\ -[id] = {\ - DWBC_COMMON_REG_LIST_DCN1_0(id),\ -} - -static const struct dcn10_dwbc_registers dwbc10_regs[] = { - dwbc_regs(0), - dwbc_regs(1), -}; - -static const struct dcn10_dwbc_shift dwbc10_shift = { - DWBC_COMMON_MASK_SH_LIST_DCN1_0(__SHIFT) -}; - -static const struct dcn10_dwbc_mask dwbc10_mask = { - DWBC_COMMON_MASK_SH_LIST_DCN1_0(_MASK) -}; - - static bool get_caps(struct dwbc *dwbc, struct dwb_caps *caps) { if (caps) { @@ -603,7 +344,7 @@ const struct dwbc_funcs dcn10_dwbc_funcs = { .reset_advanced_settings = reset_advanced_settings, }; -static void dcn10_dwbc_construct(struct dcn10_dwbc *dwbc10, +void dcn10_dwbc_construct(struct dcn10_dwbc *dwbc10, struct dc_context *ctx, const struct dcn10_dwbc_registers *dwbc_regs, const struct dcn10_dwbc_shift *dwbc_shift, @@ -620,32 +361,5 @@ static void dcn10_dwbc_construct(struct dcn10_dwbc *dwbc10, dwbc10->dwbc_mask = dwbc_mask; } -bool dcn10_dwbc_create(struct dc_context *ctx, struct resource_pool *pool) -{ - int i; - uint32_t pipe_count = pool->res_cap->num_dwb; - - ASSERT(pipe_count > 0); - for (i = 0; i < pipe_count; i++) { - struct dcn10_dwbc *dwbc10 = dm_alloc(sizeof(struct dcn10_dwbc)); - - if (!dwbc10) - return false; - - dcn10_dwbc_construct(dwbc10, ctx, - &dwbc10_regs[i], - &dwbc10_shift, - &dwbc10_mask, - i); - - pool->dwbc[i] = &dwbc10->base; - if (pool->dwbc[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create dwbc10!\n"); - return false; - } - } - return true; -} #endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.h index cf530aed4e1c..1fdc2be42fa9 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.h @@ -26,7 +26,252 @@ #if defined(CONFIG_DRM_AMD_DC_DCN1_0) -bool dcn10_dwbc_create(struct dc_context *ctx, struct resource_pool *pool); +/* DCN */ +#define BASE_INNER(seg) \ + DCE_BASE__INST0_SEG ## seg + +#define BASE(seg) \ + BASE_INNER(seg) + +#define SR(reg_name)\ + .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + \ + mm ## reg_name + +#define SRI(reg_name, block, id)\ + .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + + +#define SRII(reg_name, block, id)\ + .reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +#define SF(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + + +#define DWBC_COMMON_REG_LIST_DCN1_0(inst) \ + SRI(WB_ENABLE, CNV, inst),\ + SRI(WB_EC_CONFIG, CNV, inst),\ + SRI(CNV_MODE, CNV, inst),\ + SRI(WB_SOFT_RESET, CNV, inst),\ + SRI(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_PITCH, MCIF_WB, inst),\ + SRI(MCIF_WB_ARBITRATION_CONTROL, MCIF_WB, inst),\ + SRI(MCIF_WB_SCLK_CHANGE, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_1_ADDR_Y, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_1_ADDR_Y_OFFSET, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_1_ADDR_C, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_1_ADDR_C_OFFSET, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_2_ADDR_Y, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_2_ADDR_Y_OFFSET, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_2_ADDR_C, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_2_ADDR_C_OFFSET, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_3_ADDR_Y, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_3_ADDR_Y_OFFSET, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_3_ADDR_C, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_3_ADDR_C_OFFSET, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_4_ADDR_Y, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_4_ADDR_Y_OFFSET, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_4_ADDR_C, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_4_ADDR_C_OFFSET, MCIF_WB, inst),\ + SRI(MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB, inst),\ + SRI(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, MCIF_WB, inst),\ + SRI(MCIF_WB_NB_PSTATE_CONTROL, MCIF_WB, inst),\ + SRI(MCIF_WB_WATERMARK, MCIF_WB, inst),\ + SRI(MCIF_WB_WARM_UP_CNTL, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_LUMA_SIZE, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_CHROMA_SIZE, MCIF_WB, inst),\ + .DWB_SOURCE_SELECT = mmDWB_SOURCE_SELECT\ + +#define DWBC_COMMON_MASK_SH_LIST_DCN1_0(mask_sh) \ + SF(CNV0_WB_ENABLE, WB_ENABLE, mask_sh),\ + SF(CNV0_WB_EC_CONFIG, DISPCLK_R_WB_GATE_DIS, mask_sh),\ + SF(CNV0_WB_EC_CONFIG, DISPCLK_G_WB_GATE_DIS, mask_sh),\ + SF(CNV0_WB_EC_CONFIG, DISPCLK_G_WBSCL_GATE_DIS, mask_sh),\ + SF(CNV0_WB_EC_CONFIG, WB_LB_LS_DIS, mask_sh),\ + SF(CNV0_WB_EC_CONFIG, WB_LUT_LS_DIS, mask_sh),\ + SF(CNV0_CNV_MODE, CNV_WINDOW_CROP_EN, mask_sh),\ + SF(CNV0_CNV_MODE, CNV_STEREO_TYPE, mask_sh),\ + SF(CNV0_CNV_MODE, CNV_INTERLACED_MODE, mask_sh),\ + SF(CNV0_CNV_MODE, CNV_EYE_SELECTION, mask_sh),\ + SF(CNV0_CNV_MODE, CNV_STEREO_POLARITY, mask_sh),\ + SF(CNV0_CNV_MODE, CNV_INTERLACED_FIELD_ORDER, mask_sh),\ + SF(CNV0_CNV_MODE, CNV_STEREO_SPLIT, mask_sh),\ + SF(CNV0_CNV_MODE, CNV_NEW_CONTENT, mask_sh),\ + SF(CNV0_CNV_MODE, CNV_FRAME_CAPTURE_EN, mask_sh),\ + SF(CNV0_WB_SOFT_RESET, WB_SOFT_RESET, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_ENABLE, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUF_DUALSIZE_REQ, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_INT_EN, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_INT_ACK, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_SLICE_INT_EN, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_OVERRUN_INT_EN, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_LOCK, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_P_VMID, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUF_ADDR_FENCE_EN, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_PITCH, MCIF_WB_BUF_LUMA_PITCH, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_PITCH, MCIF_WB_BUF_CHROMA_PITCH, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_ARBITRATION_CONTROL, MCIF_WB_CLIENT_ARBITRATION_SLICE, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_ARBITRATION_CONTROL, MCIF_WB_TIME_PER_PIXEL, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_SCLK_CHANGE, WM_CHANGE_ACK_FORCE_ON, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_SCLK_CHANGE, MCIF_WB_CLI_WATERMARK_MASK, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_1_ADDR_Y, MCIF_WB_BUF_1_ADDR_Y, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_1_ADDR_Y_OFFSET, MCIF_WB_BUF_1_ADDR_Y_OFFSET, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_1_ADDR_C, MCIF_WB_BUF_1_ADDR_C, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_1_ADDR_C_OFFSET, MCIF_WB_BUF_1_ADDR_C_OFFSET, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_2_ADDR_Y, MCIF_WB_BUF_2_ADDR_Y, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_2_ADDR_Y_OFFSET, MCIF_WB_BUF_2_ADDR_Y_OFFSET, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_2_ADDR_C, MCIF_WB_BUF_2_ADDR_C, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_2_ADDR_C_OFFSET, MCIF_WB_BUF_2_ADDR_C_OFFSET, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_3_ADDR_Y, MCIF_WB_BUF_3_ADDR_Y, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_3_ADDR_Y_OFFSET, MCIF_WB_BUF_3_ADDR_Y_OFFSET, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_3_ADDR_C, MCIF_WB_BUF_3_ADDR_C, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_3_ADDR_C_OFFSET, MCIF_WB_BUF_3_ADDR_C_OFFSET, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_4_ADDR_Y, MCIF_WB_BUF_4_ADDR_Y, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_4_ADDR_Y_OFFSET, MCIF_WB_BUF_4_ADDR_Y_OFFSET, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_4_ADDR_C, MCIF_WB_BUF_4_ADDR_C, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_4_ADDR_C_OFFSET, MCIF_WB_BUF_4_ADDR_C_OFFSET, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_LOCK_IGNORE, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_INT_EN, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_INT_ACK, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_SLICE_INT_EN, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_LOCK, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_SLICE_SIZE, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, NB_PSTATE_CHANGE_REFRESH_WATERMARK, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_CHANGE_URGENT_DURING_REQUEST, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_CHANGE_FORCE_ON, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_ALLOW_FOR_URGENT, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_CHANGE_WATERMARK_MASK, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_WATERMARK, MCIF_WB_CLI_WATERMARK, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_WARM_UP_CNTL, MCIF_WB_PITCH_SIZE_WARMUP, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_LUMA_SIZE, MCIF_WB_BUF_LUMA_SIZE, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_CHROMA_SIZE, MCIF_WB_BUF_CHROMA_SIZE, mask_sh),\ + SF(DWB_SOURCE_SELECT, OPTC_DWB0_SOURCE_SELECT, mask_sh),\ + SF(DWB_SOURCE_SELECT, OPTC_DWB1_SOURCE_SELECT, mask_sh) + +#define DWBC_REG_FIELD_LIST(type) \ + type WB_ENABLE;\ + type DISPCLK_R_WB_GATE_DIS;\ + type DISPCLK_G_WB_GATE_DIS;\ + type DISPCLK_G_WBSCL_GATE_DIS;\ + type WB_LB_LS_DIS;\ + type WB_LB_SD_DIS;\ + type WB_LUT_LS_DIS;\ + type CNV_WINDOW_CROP_EN;\ + type CNV_STEREO_TYPE;\ + type CNV_INTERLACED_MODE;\ + type CNV_EYE_SELECTION;\ + type CNV_STEREO_POLARITY;\ + type CNV_INTERLACED_FIELD_ORDER;\ + type CNV_STEREO_SPLIT;\ + type CNV_NEW_CONTENT;\ + type CNV_FRAME_CAPTURE_EN;\ + type WB_SOFT_RESET;\ + type MCIF_WB_BUFMGR_ENABLE;\ + type MCIF_WB_BUF_DUALSIZE_REQ;\ + type MCIF_WB_BUFMGR_SW_INT_EN;\ + type MCIF_WB_BUFMGR_SW_INT_ACK;\ + type MCIF_WB_BUFMGR_SW_SLICE_INT_EN;\ + type MCIF_WB_BUFMGR_SW_OVERRUN_INT_EN;\ + type MCIF_WB_BUFMGR_SW_LOCK;\ + type MCIF_WB_P_VMID;\ + type MCIF_WB_BUF_ADDR_FENCE_EN;\ + type MCIF_WB_BUF_LUMA_PITCH;\ + type MCIF_WB_BUF_CHROMA_PITCH;\ + type MCIF_WB_CLIENT_ARBITRATION_SLICE;\ + type MCIF_WB_TIME_PER_PIXEL;\ + type WM_CHANGE_ACK_FORCE_ON;\ + type MCIF_WB_CLI_WATERMARK_MASK;\ + type MCIF_WB_BUF_1_ADDR_Y;\ + type MCIF_WB_BUF_1_ADDR_Y_OFFSET;\ + type MCIF_WB_BUF_1_ADDR_C;\ + type MCIF_WB_BUF_1_ADDR_C_OFFSET;\ + type MCIF_WB_BUF_2_ADDR_Y;\ + type MCIF_WB_BUF_2_ADDR_Y_OFFSET;\ + type MCIF_WB_BUF_2_ADDR_C;\ + type MCIF_WB_BUF_2_ADDR_C_OFFSET;\ + type MCIF_WB_BUF_3_ADDR_Y;\ + type MCIF_WB_BUF_3_ADDR_Y_OFFSET;\ + type MCIF_WB_BUF_3_ADDR_C;\ + type MCIF_WB_BUF_3_ADDR_C_OFFSET;\ + type MCIF_WB_BUF_4_ADDR_Y;\ + type MCIF_WB_BUF_4_ADDR_Y_OFFSET;\ + type MCIF_WB_BUF_4_ADDR_C;\ + type MCIF_WB_BUF_4_ADDR_C_OFFSET;\ + type MCIF_WB_BUFMGR_VCE_LOCK_IGNORE;\ + type MCIF_WB_BUFMGR_VCE_INT_EN;\ + type MCIF_WB_BUFMGR_VCE_INT_ACK;\ + type MCIF_WB_BUFMGR_VCE_SLICE_INT_EN;\ + type MCIF_WB_BUFMGR_VCE_LOCK;\ + type MCIF_WB_BUFMGR_SLICE_SIZE;\ + type NB_PSTATE_CHANGE_REFRESH_WATERMARK;\ + type NB_PSTATE_CHANGE_URGENT_DURING_REQUEST;\ + type NB_PSTATE_CHANGE_FORCE_ON;\ + type NB_PSTATE_ALLOW_FOR_URGENT;\ + type NB_PSTATE_CHANGE_WATERMARK_MASK;\ + type MCIF_WB_CLI_WATERMARK;\ + type MCIF_WB_CLI_CLOCK_GATER_OVERRIDE;\ + type MCIF_WB_PITCH_SIZE_WARMUP;\ + type MCIF_WB_BUF_LUMA_SIZE;\ + type MCIF_WB_BUF_CHROMA_SIZE;\ + type OPTC_DWB0_SOURCE_SELECT;\ + type OPTC_DWB1_SOURCE_SELECT;\ + +struct dcn10_dwbc_registers { + uint32_t WB_ENABLE; + uint32_t WB_EC_CONFIG; + uint32_t CNV_MODE; + uint32_t WB_SOFT_RESET; + uint32_t MCIF_WB_BUFMGR_SW_CONTROL; + uint32_t MCIF_WB_BUF_PITCH; + uint32_t MCIF_WB_ARBITRATION_CONTROL; + uint32_t MCIF_WB_SCLK_CHANGE; + uint32_t MCIF_WB_BUF_1_ADDR_Y; + uint32_t MCIF_WB_BUF_1_ADDR_Y_OFFSET; + uint32_t MCIF_WB_BUF_1_ADDR_C; + uint32_t MCIF_WB_BUF_1_ADDR_C_OFFSET; + uint32_t MCIF_WB_BUF_2_ADDR_Y; + uint32_t MCIF_WB_BUF_2_ADDR_Y_OFFSET; + uint32_t MCIF_WB_BUF_2_ADDR_C; + uint32_t MCIF_WB_BUF_2_ADDR_C_OFFSET; + uint32_t MCIF_WB_BUF_3_ADDR_Y; + uint32_t MCIF_WB_BUF_3_ADDR_Y_OFFSET; + uint32_t MCIF_WB_BUF_3_ADDR_C; + uint32_t MCIF_WB_BUF_3_ADDR_C_OFFSET; + uint32_t MCIF_WB_BUF_4_ADDR_Y; + uint32_t MCIF_WB_BUF_4_ADDR_Y_OFFSET; + uint32_t MCIF_WB_BUF_4_ADDR_C; + uint32_t MCIF_WB_BUF_4_ADDR_C_OFFSET; + uint32_t MCIF_WB_BUFMGR_VCE_CONTROL; + uint32_t MCIF_WB_NB_PSTATE_LATENCY_WATERMARK; + uint32_t MCIF_WB_NB_PSTATE_CONTROL; + uint32_t MCIF_WB_WATERMARK; + uint32_t MCIF_WB_WARM_UP_CNTL; + uint32_t MCIF_WB_BUF_LUMA_SIZE; + uint32_t MCIF_WB_BUF_CHROMA_SIZE; + uint32_t DWB_SOURCE_SELECT; +}; +struct dcn10_dwbc_mask { + DWBC_REG_FIELD_LIST(uint32_t) +}; +struct dcn10_dwbc_shift { + DWBC_REG_FIELD_LIST(uint8_t) +}; +struct dcn10_dwbc { + struct dwbc base; + const struct dcn10_dwbc_registers *dwbc_regs; + const struct dcn10_dwbc_shift *dwbc_shift; + const struct dcn10_dwbc_mask *dwbc_mask; +}; + +void dcn10_dwbc_construct(struct dcn10_dwbc *dwbc10, + struct dc_context *ctx, + const struct dcn10_dwbc_registers *dwbc_regs, + const struct dcn10_dwbc_shift *dwbc_shift, + const struct dcn10_dwbc_mask *dwbc_mask, + int inst); + #endif #endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index ac6d01ec0505..298eb44ad9bf 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -326,6 +326,24 @@ static const struct dcn_dpp_mask tf_mask = { TF_REG_LIST_SH_MASK_DCN10(_MASK), }; +#define dwbc_regs(id)\ +[id] = {\ + DWBC_COMMON_REG_LIST_DCN1_0(id),\ +} + +static const struct dcn10_dwbc_registers dwbc10_regs[] = { + dwbc_regs(0), + dwbc_regs(1), +}; + +static const struct dcn10_dwbc_shift dwbc10_shift = { + DWBC_COMMON_MASK_SH_LIST_DCN1_0(__SHIFT) +}; + +static const struct dcn10_dwbc_mask dwbc10_mask = { + DWBC_COMMON_MASK_SH_LIST_DCN1_0(_MASK) +}; + static const struct dcn_mpc_registers mpc_regs = { MPC_COMMON_REG_LIST_DCN1_0(0), MPC_COMMON_REG_LIST_DCN1_0(1), @@ -1215,6 +1233,30 @@ static uint32_t read_pipe_fuses(struct dc_context *ctx) return value; } +static bool dcn10_dwbc_create(struct dc_context *ctx, struct resource_pool *pool) +{ + int i; + uint32_t dwb_count = pool->res_cap->num_dwb; + + for (i = 0; i < dwb_count; i++) { + struct dcn10_dwbc *dwbc10 = dm_alloc(sizeof(struct dcn10_dwbc)); + + if (!dwbc10) { + dm_error("DC: failed to create dwbc10!\n"); + return false; + } + + dcn10_dwbc_construct(dwbc10, ctx, + &dwbc10_regs[i], + &dwbc10_shift, + &dwbc10_mask, + i); + + pool->dwbc[i] = &dwbc10->base; + } + return true; +} + static bool construct( uint8_t num_virtual_links, struct dc *dc, -- cgit From 21e67d4d52ca8688feb8c4f6e6d29b2d16d578ad Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 5 Sep 2017 15:50:48 -0400 Subject: drm/amd/display: No need to keep track of unreffed clk sources This simplifies clock source reprogramming a bit. Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 18 ++-------------- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 21 +++++------------- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 25 +++++++--------------- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 2 -- drivers/gpu/drm/amd/display/dc/inc/resource.h | 2 +- 5 files changed, 16 insertions(+), 52 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 9aa0da743174..15b627548cd2 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -261,13 +261,12 @@ bool resource_construct( } -bool resource_unreference_clock_source( +void resource_unreference_clock_source( struct resource_context *res_ctx, const struct resource_pool *pool, struct clock_source *clock_source) { int i; - bool need_reset = false; for (i = 0; i < pool->clk_src_count; i++) { if (pool->clock_sources[i] != clock_source) @@ -275,24 +274,11 @@ bool resource_unreference_clock_source( res_ctx->clock_source_ref_count[i]--; - if (res_ctx->clock_source_ref_count[i] == 0) { - res_ctx->clock_source_changed[i] = true; - need_reset = true; - } - break; } - if (pool->dp_clock_source == clock_source) { + if (pool->dp_clock_source == clock_source) res_ctx->dp_clock_source_ref_count--; - - if (res_ctx->dp_clock_source_ref_count == 0) { - res_ctx->dp_clock_source_changed = true; - need_reset = true; - } - } - - return need_reset; } void resource_reference_clock_source( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index c57dc45d6677..31592e53f504 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1640,6 +1640,8 @@ static void dce110_reset_hw_ctx_wrap( if (!pipe_ctx->stream || pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) { + struct clock_source *old_clk = pipe_ctx_old->clock_source; + core_link_disable_stream(pipe_ctx_old); pipe_ctx_old->stream_res.tg->funcs->set_blank(pipe_ctx_old->stream_res.tg, true); if (!hwss_wait_for_blank_complete(pipe_ctx_old->stream_res.tg)) { @@ -1650,27 +1652,14 @@ static void dce110_reset_hw_ctx_wrap( pipe_ctx_old->plane_res.mi->funcs->free_mem_input( pipe_ctx_old->plane_res.mi, dc->current_state->stream_count); + if (old_clk) + old_clk->funcs->cs_power_down(old_clk); + dc->hwss.power_down_front_end(dc, pipe_ctx_old->pipe_idx); pipe_ctx_old->stream = NULL; } } - - /* power down changed clock sources */ - for (i = 0; i < dc->res_pool->clk_src_count; i++) - if (context->res_ctx.clock_source_changed[i]) { - struct clock_source *clk = dc->res_pool->clock_sources[i]; - - clk->funcs->cs_power_down(clk); - context->res_ctx.clock_source_changed[i] = false; - } - - if (context->res_ctx.dp_clock_source_changed) { - struct clock_source *clk = dc->res_pool->dp_clock_source; - - clk->funcs->cs_power_down(clk); - context->res_ctx.clock_source_changed[i] = false; - } } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 6fee6957c1a6..c8c4b951ee1d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1265,22 +1265,6 @@ static void reset_hw_ctx_wrap( plane_atomic_power_down(dc, i); } - /* power down changed clock sources */ - for (i = 0; i < dc->res_pool->clk_src_count; i++) - if (context->res_ctx.clock_source_changed[i]) { - struct clock_source *clk = dc->res_pool->clock_sources[i]; - - clk->funcs->cs_power_down(clk); - context->res_ctx.clock_source_changed[i] = false; - } - - if (context->res_ctx.dp_clock_source_changed) { - struct clock_source *clk = dc->res_pool->dp_clock_source; - - clk->funcs->cs_power_down(clk); - context->res_ctx.dp_clock_source_changed = false; - } - /* Reset Back End*/ for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) { struct pipe_ctx *pipe_ctx_old = @@ -1291,9 +1275,16 @@ static void reset_hw_ctx_wrap( continue; if (!pipe_ctx->stream || - pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) + pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) { + struct clock_source *old_clk = pipe_ctx_old->clock_source; + reset_back_end_for_pipe(dc, pipe_ctx_old, dc->current_state); + + if (old_clk) + old_clk->funcs->cs_power_down(old_clk); + } } + } static bool patch_address_for_sbs_tb_stereo( diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index b6a513d6feda..915d5c10361b 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -213,9 +213,7 @@ struct resource_context { bool is_stream_enc_acquired[MAX_PIPES * 2]; bool is_audio_acquired[MAX_PIPES]; uint8_t clock_source_ref_count[MAX_CLOCK_SOURCES]; - bool clock_source_changed[MAX_CLOCK_SOURCES]; uint8_t dp_clock_source_ref_count; - bool dp_clock_source_changed; }; struct dce_bw_output { diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index cf1797c191e9..614bb691ab59 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -92,7 +92,7 @@ enum dc_status resource_build_scaling_params_for_context( void resource_build_info_frame(struct pipe_ctx *pipe_ctx); -bool resource_unreference_clock_source( +void resource_unreference_clock_source( struct resource_context *res_ctx, const struct resource_pool *pool, struct clock_source *clock_source); -- cgit From e9475143fb42b62689163c95aabdb6c173fcdbb0 Mon Sep 17 00:00:00 2001 From: pana Date: Fri, 1 Sep 2017 15:43:22 +0800 Subject: drm/amd/display: Add 2X Cursor Magnification Code Signed-off-by: Pandey, Arun Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c | 2 -- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h | 11 +++++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c index 5edc4b7073e1..5e0e2464eab3 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c @@ -154,12 +154,10 @@ static void ippn10_cursor_set_attributes( REG_UPDATE_2(CURSOR_SIZE, CURSOR_WIDTH, attr->width, CURSOR_HEIGHT, attr->height); - REG_UPDATE_3(CURSOR_CONTROL, CURSOR_MODE, attr->color_format, CURSOR_PITCH, hw_pitch, CURSOR_LINES_PER_CHUNK, lpc); - ippn10_cursor_program_control(ippn10, attr->attribute_flags.bits.INVERT_PIXEL_DATA, attr->color_format); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h index e4f292822975..d7b5bd20352a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h @@ -50,6 +50,15 @@ SRI(CURSOR_HOT_SPOT, CURSOR, id), \ SRI(CURSOR_DST_OFFSET, CURSOR, id) +#define CURSOR0_CURSOR_CONTROL__CURSOR_2X_MAGNIFY__SHIFT 0x4 +#define CURSOR0_CURSOR_CONTROL__CURSOR_2X_MAGNIFY_MASK 0x00000010L +#define CURSOR1_CURSOR_CONTROL__CURSOR_2X_MAGNIFY__SHIFT 0x4 +#define CURSOR1_CURSOR_CONTROL__CURSOR_2X_MAGNIFY_MASK 0x00000010L +#define CURSOR2_CURSOR_CONTROL__CURSOR_2X_MAGNIFY__SHIFT 0x4 +#define CURSOR2_CURSOR_CONTROL__CURSOR_2X_MAGNIFY_MASK 0x00000010L +#define CURSOR3_CURSOR_CONTROL__CURSOR_2X_MAGNIFY__SHIFT 0x4 +#define CURSOR3_CURSOR_CONTROL__CURSOR_2X_MAGNIFY_MASK 0x00000010L + #define IPP_SF(reg_name, field_name, post_fix)\ .field_name = reg_name ## __ ## field_name ## post_fix @@ -73,6 +82,7 @@ IPP_SF(CURSOR0_CURSOR_SIZE, CURSOR_WIDTH, mask_sh), \ IPP_SF(CURSOR0_CURSOR_SIZE, CURSOR_HEIGHT, mask_sh), \ IPP_SF(CURSOR0_CURSOR_CONTROL, CURSOR_MODE, mask_sh), \ + IPP_SF(CURSOR0_CURSOR_CONTROL, CURSOR_2X_MAGNIFY, mask_sh), \ IPP_SF(CURSOR0_CURSOR_CONTROL, CURSOR_PITCH, mask_sh), \ IPP_SF(CURSOR0_CURSOR_CONTROL, CURSOR_LINES_PER_CHUNK, mask_sh), \ IPP_SF(CURSOR0_CURSOR_CONTROL, CURSOR_ENABLE, mask_sh), \ @@ -99,6 +109,7 @@ type CURSOR_WIDTH; \ type CURSOR_HEIGHT; \ type CURSOR_MODE; \ + type CURSOR_2X_MAGNIFY; \ type CURSOR_PITCH; \ type CURSOR_LINES_PER_CHUNK; \ type CURSOR_ENABLE; \ -- cgit From c84dec2fe8837facf4ccaffd2afae9b157719327 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 5 Sep 2017 14:16:09 -0400 Subject: drm/amd/display: Break out amdgpu_dm_connector Stop using amdgpu_connector and roll our own. There is no overlap with amdgpu. Signed-off-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 126 ++++++++++----------- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 53 ++++++++- .../drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 20 ++-- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c | 12 +- .../amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 34 +++--- .../amd/display/amdgpu_dm/amdgpu_dm_mst_types.h | 4 +- 6 files changed, 146 insertions(+), 103 deletions(-) (limited to 'drivers/gpu') 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 febfff2225d9..c42660520871 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -465,14 +465,14 @@ static int dm_sw_fini(void *handle) static int detect_mst_link_for_all_connectors(struct drm_device *dev) { - struct amdgpu_connector *aconnector; + struct amdgpu_dm_connector *aconnector; struct drm_connector *connector; int ret = 0; drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - aconnector = to_amdgpu_connector(connector); + aconnector = to_amdgpu_dm_connector(connector); if (aconnector->dc_link->type == dc_connection_mst_branch) { DRM_INFO("DM_MST: starting TM on aconnector: %p [id: %d]\n", aconnector, aconnector->base.base.id); @@ -500,13 +500,13 @@ static int dm_late_init(void *handle) static void s3_handle_mst(struct drm_device *dev, bool suspend) { - struct amdgpu_connector *aconnector; + struct amdgpu_dm_connector *aconnector; struct drm_connector *connector; drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - aconnector = to_amdgpu_connector(connector); + aconnector = to_amdgpu_dm_connector(connector); if (aconnector->dc_link->type == dc_connection_mst_branch && !aconnector->mst_port) { @@ -562,7 +562,7 @@ static int dm_suspend(void *handle) return ret; } -struct amdgpu_connector *amdgpu_dm_find_first_crct_matching_connector( +struct amdgpu_dm_connector *amdgpu_dm_find_first_crct_matching_connector( struct drm_atomic_state *state, struct drm_crtc *crtc, bool from_state_var) @@ -583,7 +583,7 @@ struct amdgpu_connector *amdgpu_dm_find_first_crct_matching_connector( connector->state->crtc; if (crtc_from_state == crtc) - return to_amdgpu_connector(connector); + return to_amdgpu_dm_connector(connector); } return NULL; @@ -607,7 +607,7 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev ) { struct drm_device *ddev = adev->ddev; struct amdgpu_display_manager *dm = &adev->dm; - struct amdgpu_connector *aconnector; + struct amdgpu_dm_connector *aconnector; struct drm_connector *connector; struct drm_crtc *crtc; struct drm_crtc_state *crtc_state; @@ -629,7 +629,7 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev ) /* Do detection*/ list_for_each_entry(connector, &ddev->mode_config.connector_list, head) { - aconnector = to_amdgpu_connector(connector); + aconnector = to_amdgpu_dm_connector(connector); /* * this is the case when traversing through already created @@ -741,7 +741,7 @@ static struct drm_mode_config_helper_funcs amdgpu_dm_mode_config_helperfuncs = { }; void amdgpu_dm_update_connector_after_detect( - struct amdgpu_connector *aconnector) + struct amdgpu_dm_connector *aconnector) { struct drm_connector *connector = &aconnector->base; struct drm_device *dev = connector->dev; @@ -847,7 +847,7 @@ void amdgpu_dm_update_connector_after_detect( static void handle_hpd_irq(void *param) { - struct amdgpu_connector *aconnector = (struct amdgpu_connector *)param; + struct amdgpu_dm_connector *aconnector = (struct amdgpu_dm_connector *)param; struct drm_connector *connector = &aconnector->base; struct drm_device *dev = connector->dev; @@ -870,7 +870,7 @@ static void handle_hpd_irq(void *param) } -static void dm_handle_hpd_rx_irq(struct amdgpu_connector *aconnector) +static void dm_handle_hpd_rx_irq(struct amdgpu_dm_connector *aconnector) { uint8_t esi[DP_PSR_ERROR_STATUS - DP_SINK_COUNT_ESI] = { 0 }; uint8_t dret; @@ -949,7 +949,7 @@ static void dm_handle_hpd_rx_irq(struct amdgpu_connector *aconnector) static void handle_hpd_rx_irq(void *param) { - struct amdgpu_connector *aconnector = (struct amdgpu_connector *)param; + struct amdgpu_dm_connector *aconnector = (struct amdgpu_dm_connector *)param; struct drm_connector *connector = &aconnector->base; struct drm_device *dev = connector->dev; const struct dc_link *dc_link = aconnector->dc_link; @@ -988,7 +988,7 @@ static void register_hpd_handlers(struct amdgpu_device *adev) { struct drm_device *dev = adev->ddev; struct drm_connector *connector; - struct amdgpu_connector *aconnector; + struct amdgpu_dm_connector *aconnector; const struct dc_link *dc_link; struct dc_interrupt_params int_params = {0}; @@ -998,7 +998,7 @@ static void register_hpd_handlers(struct amdgpu_device *adev) list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - aconnector = to_amdgpu_connector(connector); + aconnector = to_amdgpu_dm_connector(connector); dc_link = aconnector->dc_link; if (DC_IRQ_SOURCE_INVALID != dc_link->irq_source_hpd) { @@ -1279,7 +1279,7 @@ int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) { struct amdgpu_display_manager *dm = &adev->dm; uint32_t i; - struct amdgpu_connector *aconnector = NULL; + struct amdgpu_dm_connector *aconnector = NULL; struct amdgpu_encoder *aencoder = NULL; struct amdgpu_mode_info *mode_info = &adev->mode_info; uint32_t link_cnt; @@ -1966,18 +1966,18 @@ static int fill_plane_attributes( /*****************************************************************************/ -struct amdgpu_connector *aconnector_from_drm_crtc_id( +struct amdgpu_dm_connector *aconnector_from_drm_crtc_id( const struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; struct drm_connector *connector; struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - struct amdgpu_connector *aconnector; + struct amdgpu_dm_connector *aconnector; list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - aconnector = to_amdgpu_connector(connector); + aconnector = to_amdgpu_dm_connector(connector); if (aconnector->base.state->crtc != &acrtc->base) continue; @@ -2279,7 +2279,7 @@ static void decide_crtc_timing_for_drm_display_mode( } static struct dc_stream_state *create_stream_for_sink( - struct amdgpu_connector *aconnector, + struct amdgpu_dm_connector *aconnector, const struct drm_display_mode *drm_mode, const struct dm_connector_state *dm_state) { @@ -2425,7 +2425,7 @@ static enum drm_connector_status amdgpu_dm_connector_detect(struct drm_connector *connector, bool force) { bool connected; - struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); /* Notes: * 1. This interface is NOT called in context of HPD irq. @@ -2538,7 +2538,7 @@ int amdgpu_dm_connector_atomic_get_property( void amdgpu_dm_connector_destroy(struct drm_connector *connector) { - struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); const struct dc_link *link = aconnector->dc_link; struct amdgpu_device *adev = connector->dev->dev_private; struct amdgpu_display_manager *dm = &adev->dm; @@ -2636,7 +2636,7 @@ static int get_modes(struct drm_connector *connector) return amdgpu_dm_connector_get_modes(connector); } -static void create_eml_sink(struct amdgpu_connector *aconnector) +static void create_eml_sink(struct amdgpu_dm_connector *aconnector) { struct dc_sink_init_data init_params = { .link = aconnector->dc_link, @@ -2669,7 +2669,7 @@ static void create_eml_sink(struct amdgpu_connector *aconnector) aconnector->dc_em_sink; } -static void handle_edid_mgmt(struct amdgpu_connector *aconnector) +static void handle_edid_mgmt(struct amdgpu_dm_connector *aconnector) { struct dc_link *link = (struct dc_link *)aconnector->dc_link; @@ -2695,7 +2695,7 @@ int amdgpu_dm_connector_mode_valid( struct amdgpu_device *adev = connector->dev->dev_private; /* TODO: Unhardcode stream count */ struct dc_stream_state *stream; - struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); if ((mode->flags & DRM_MODE_FLAG_INTERLACE) || (mode->flags & DRM_MODE_FLAG_DBLSCAN)) @@ -2708,7 +2708,7 @@ int amdgpu_dm_connector_mode_valid( !aconnector->dc_em_sink) handle_edid_mgmt(aconnector); - dc_sink = to_amdgpu_connector(connector)->dc_sink; + dc_sink = to_amdgpu_dm_connector(connector)->dc_sink; if (dc_sink == NULL) { DRM_ERROR("dc_sink is NULL!\n"); @@ -2968,7 +2968,7 @@ int dm_create_validation_set_for_connector(struct drm_connector *connector, { int result = MODE_ERROR; struct dc_sink *dc_sink = - to_amdgpu_connector(connector)->dc_sink; + to_amdgpu_dm_connector(connector)->dc_sink; /* TODO: Unhardcode stream count */ struct dc_stream_state *stream; @@ -3229,8 +3229,8 @@ static void amdgpu_dm_connector_add_common_modes(struct drm_encoder *encoder, struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct drm_display_mode *mode = NULL; struct drm_display_mode *native_mode = &amdgpu_encoder->native_mode; - struct amdgpu_connector *amdgpu_connector = - to_amdgpu_connector(connector); + struct amdgpu_dm_connector *amdgpu_dm_connector = + to_amdgpu_dm_connector(connector); int i; int n; struct mode_size { @@ -3278,7 +3278,7 @@ static void amdgpu_dm_connector_add_common_modes(struct drm_encoder *encoder, common_modes[i].name, common_modes[i].w, common_modes[i].h); drm_mode_probed_add(connector, mode); - amdgpu_connector->num_modes++; + amdgpu_dm_connector->num_modes++; } } @@ -3286,41 +3286,41 @@ static void amdgpu_dm_connector_ddc_get_modes( struct drm_connector *connector, struct edid *edid) { - struct amdgpu_connector *amdgpu_connector = - to_amdgpu_connector(connector); + struct amdgpu_dm_connector *amdgpu_dm_connector = + to_amdgpu_dm_connector(connector); if (edid) { /* empty probed_modes */ INIT_LIST_HEAD(&connector->probed_modes); - amdgpu_connector->num_modes = + amdgpu_dm_connector->num_modes = drm_add_edid_modes(connector, edid); drm_edid_to_eld(connector, edid); amdgpu_dm_get_native_mode(connector); } else - amdgpu_connector->num_modes = 0; + amdgpu_dm_connector->num_modes = 0; } int amdgpu_dm_connector_get_modes(struct drm_connector *connector) { const struct drm_connector_helper_funcs *helper = connector->helper_private; - struct amdgpu_connector *amdgpu_connector = - to_amdgpu_connector(connector); + struct amdgpu_dm_connector *amdgpu_dm_connector = + to_amdgpu_dm_connector(connector); struct drm_encoder *encoder; - struct edid *edid = amdgpu_connector->edid; + struct edid *edid = amdgpu_dm_connector->edid; encoder = helper->best_encoder(connector); amdgpu_dm_connector_ddc_get_modes(connector, edid); amdgpu_dm_connector_add_common_modes(encoder, connector); - return amdgpu_connector->num_modes; + return amdgpu_dm_connector->num_modes; } void amdgpu_dm_connector_init_helper( struct amdgpu_display_manager *dm, - struct amdgpu_connector *aconnector, + struct amdgpu_dm_connector *aconnector, int connector_type, struct dc_link *link, int link_index) @@ -3440,7 +3440,7 @@ static struct amdgpu_i2c_adapter *create_i2c( */ int amdgpu_dm_connector_init( struct amdgpu_display_manager *dm, - struct amdgpu_connector *aconnector, + struct amdgpu_dm_connector *aconnector, uint32_t link_index, struct amdgpu_encoder *aencoder) { @@ -4076,7 +4076,7 @@ void amdgpu_dm_atomic_commit_tail( */ if (adev->dm.freesync_module) { for (i = 0; i < new_crtcs_count; i++) { - struct amdgpu_connector *aconnector = NULL; + struct amdgpu_dm_connector *aconnector = NULL; new_acrtc_state = to_dm_crtc_state(new_crtcs[i]->base.state); @@ -4120,7 +4120,7 @@ void amdgpu_dm_atomic_commit_tail( /* Handle scaling and undersacn changes*/ for_each_connector_in_state(state, connector, old_conn_state, i) { - struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); struct dm_connector_state *con_new_state = to_dm_connector_state(aconnector->base.state); struct dm_connector_state *con_old_state = @@ -4270,7 +4270,7 @@ err: */ void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector *connector) { - struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); struct amdgpu_crtc *disconnected_acrtc; struct dm_crtc_state *acrtc_state; @@ -4360,7 +4360,7 @@ static int dm_update_crtcs_state( /* update changed items */ for_each_crtc_in_state(state, crtc, crtc_state, i) { struct amdgpu_crtc *acrtc = NULL; - struct amdgpu_connector *aconnector = NULL; + struct amdgpu_dm_connector *aconnector = NULL; struct drm_connector_state *conn_state = NULL; struct dm_connector_state *dm_conn_state = NULL; @@ -4689,7 +4689,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, * decide how to handle. */ for_each_connector_in_state(state, connector, conn_state, i) { - struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); struct dm_connector_state *con_old_state = to_dm_connector_state(aconnector->base.state); struct dm_connector_state *con_new_state = @@ -4746,15 +4746,15 @@ fail: static bool is_dp_capable_without_timing_msa( struct dc *dc, - struct amdgpu_connector *amdgpu_connector) + struct amdgpu_dm_connector *amdgpu_dm_connector) { uint8_t dpcd_data; bool capable = false; - if (amdgpu_connector->dc_link && + if (amdgpu_dm_connector->dc_link && dm_helpers_dp_read_dpcd( NULL, - amdgpu_connector->dc_link, + amdgpu_dm_connector->dc_link, DP_DOWN_STREAM_PORT_COUNT, &dpcd_data, sizeof(dpcd_data))) { @@ -4773,14 +4773,14 @@ void amdgpu_dm_add_sink_to_freesync_module( struct detailed_timing *timing; struct detailed_non_pixel *data; struct detailed_data_monitor_range *range; - struct amdgpu_connector *amdgpu_connector = - to_amdgpu_connector(connector); + struct amdgpu_dm_connector *amdgpu_dm_connector = + to_amdgpu_dm_connector(connector); struct drm_device *dev = connector->dev; struct amdgpu_device *adev = dev->dev_private; edid_check_required = false; - if (!amdgpu_connector->dc_sink) { + if (!amdgpu_dm_connector->dc_sink) { DRM_ERROR("dc_sink NULL, could not add free_sync module.\n"); return; } @@ -4790,11 +4790,11 @@ void amdgpu_dm_add_sink_to_freesync_module( * if edid non zero restrict freesync only for dp and edp */ if (edid) { - if (amdgpu_connector->dc_sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT - || amdgpu_connector->dc_sink->sink_signal == SIGNAL_TYPE_EDP) { + if (amdgpu_dm_connector->dc_sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT + || amdgpu_dm_connector->dc_sink->sink_signal == SIGNAL_TYPE_EDP) { edid_check_required = is_dp_capable_without_timing_msa( adev->dm.dc, - amdgpu_connector); + amdgpu_dm_connector); } } val_capable = 0; @@ -4819,20 +4819,20 @@ void amdgpu_dm_add_sink_to_freesync_module( if (range->flags != 1) continue; - amdgpu_connector->min_vfreq = range->min_vfreq; - amdgpu_connector->max_vfreq = range->max_vfreq; - amdgpu_connector->pixel_clock_mhz = + amdgpu_dm_connector->min_vfreq = range->min_vfreq; + amdgpu_dm_connector->max_vfreq = range->max_vfreq; + amdgpu_dm_connector->pixel_clock_mhz = range->pixel_clock_mhz * 10; break; } - if (amdgpu_connector->max_vfreq - - amdgpu_connector->min_vfreq > 10) { - amdgpu_connector->caps.supported = true; - amdgpu_connector->caps.min_refresh_in_micro_hz = - amdgpu_connector->min_vfreq * 1000000; - amdgpu_connector->caps.max_refresh_in_micro_hz = - amdgpu_connector->max_vfreq * 1000000; + if (amdgpu_dm_connector->max_vfreq - + amdgpu_dm_connector->min_vfreq > 10) { + amdgpu_dm_connector->caps.supported = true; + amdgpu_dm_connector->caps.min_refresh_in_micro_hz = + amdgpu_dm_connector->min_vfreq * 1000000; + amdgpu_dm_connector->caps.max_refresh_in_micro_hz = + amdgpu_dm_connector->max_vfreq * 1000000; val_capable = 1; } } 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 71cbee199016..8894613e956c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -147,6 +147,50 @@ struct amdgpu_display_manager { #endif }; +struct amdgpu_dm_connector { + + struct drm_connector base; + uint32_t connector_id; + + /* we need to mind the EDID between detect + and get modes due to analog/digital/tvencoder */ + struct edid *edid; + + /* shared with amdgpu */ + struct amdgpu_hpd hpd; + + /* number of modes generated from EDID at 'dc_sink' */ + int num_modes; + + /* The 'old' sink - before an HPD. + * The 'current' sink is in dc_link->sink. */ + struct dc_sink *dc_sink; + struct dc_link *dc_link; + struct dc_sink *dc_em_sink; + + /* DM only */ + struct drm_dp_mst_topology_mgr mst_mgr; + struct amdgpu_dm_dp_aux dm_dp_aux; + struct drm_dp_mst_port *port; + struct amdgpu_dm_connector *mst_port; + struct amdgpu_encoder *mst_encoder; + + /* TODO see if we can merge with ddc_bus or make a dm_connector */ + struct amdgpu_i2c_adapter *i2c; + + /* Monitor range limits */ + int min_vfreq ; + int max_vfreq ; + int pixel_clock_mhz; + + /*freesync caps*/ + struct mod_freesync_caps caps; + + struct mutex hpd_lock; +}; + +#define to_amdgpu_dm_connector(x) container_of(x, struct amdgpu_dm_connector, base) + /* basic init/fini API */ int amdgpu_dm_init(struct amdgpu_device *adev); @@ -178,9 +222,9 @@ void amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm); extern const struct amdgpu_ip_block_version dm_ip_block; void amdgpu_dm_update_connector_after_detect( - struct amdgpu_connector *aconnector); + struct amdgpu_dm_connector *aconnector); -struct amdgpu_connector *amdgpu_dm_find_first_crct_matching_connector( +struct amdgpu_dm_connector *amdgpu_dm_find_first_crct_matching_connector( struct drm_atomic_state *state, struct drm_crtc *crtc, bool from_state_var); @@ -193,7 +237,6 @@ struct dc_plane_state; /* TODO rename to dc_stream_state */ struct dc_stream; - struct dm_plane_state { struct drm_plane_state base; struct dc_plane_state *dc_state; @@ -223,7 +266,7 @@ int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, struct drm_plane *plane, uint32_t link_index); int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm, - struct amdgpu_connector *amdgpu_connector, + struct amdgpu_dm_connector *amdgpu_dm_connector, uint32_t link_index, struct amdgpu_encoder *amdgpu_encoder); int amdgpu_dm_encoder_init( @@ -267,7 +310,7 @@ int amdgpu_dm_get_encoder_crtc_mask(struct amdgpu_device *adev); void amdgpu_dm_connector_init_helper( struct amdgpu_display_manager *dm, - struct amdgpu_connector *aconnector, + struct amdgpu_dm_connector *aconnector, int connector_type, struct dc_link *link, int link_index); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index 4a124537dc9a..9bd142f65f9b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -133,7 +133,7 @@ enum dc_edid_status dm_helpers_parse_edid_caps( } static void get_payload_table( - struct amdgpu_connector *aconnector, + struct amdgpu_dm_connector *aconnector, struct dp_mst_stream_allocation_table *proposed_table) { int i; @@ -178,7 +178,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table( struct dp_mst_stream_allocation_table *proposed_table, bool enable) { - struct amdgpu_connector *aconnector; + struct amdgpu_dm_connector *aconnector; struct drm_dp_mst_topology_mgr *mst_mgr; struct drm_dp_mst_port *mst_port; int slots = 0; @@ -266,7 +266,7 @@ bool dm_helpers_dp_mst_poll_for_allocation_change_trigger( struct dc_context *ctx, const struct dc_stream_state *stream) { - struct amdgpu_connector *aconnector; + struct amdgpu_dm_connector *aconnector; struct drm_dp_mst_topology_mgr *mst_mgr; int ret; @@ -293,7 +293,7 @@ bool dm_helpers_dp_mst_send_payload_allocation( const struct dc_stream_state *stream, bool enable) { - struct amdgpu_connector *aconnector; + struct amdgpu_dm_connector *aconnector; struct drm_dp_mst_topology_mgr *mst_mgr; struct drm_dp_mst_port *mst_port; int ret; @@ -341,7 +341,7 @@ bool dm_helpers_dp_mst_start_top_mgr( const struct dc_link *link, bool boot) { - struct amdgpu_connector *aconnector = link->priv; + struct amdgpu_dm_connector *aconnector = link->priv; if (!aconnector) { DRM_ERROR("Failed to found connector for link!"); @@ -364,7 +364,7 @@ void dm_helpers_dp_mst_stop_top_mgr( struct dc_context *ctx, const struct dc_link *link) { - struct amdgpu_connector *aconnector = link->priv; + struct amdgpu_dm_connector *aconnector = link->priv; if (!aconnector) { DRM_ERROR("Failed to found connector for link!"); @@ -386,7 +386,7 @@ bool dm_helpers_dp_read_dpcd( uint32_t size) { - struct amdgpu_connector *aconnector = link->priv; + struct amdgpu_dm_connector *aconnector = link->priv; if (!aconnector) { DRM_ERROR("Failed to found connector for link!"); @@ -404,7 +404,7 @@ bool dm_helpers_dp_write_dpcd( const uint8_t *data, uint32_t size) { - struct amdgpu_connector *aconnector = link->priv; + struct amdgpu_dm_connector *aconnector = link->priv; if (!aconnector) { DRM_ERROR("Failed to found connector for link!"); @@ -420,7 +420,7 @@ bool dm_helpers_submit_i2c( const struct dc_link *link, struct i2c_command *cmd) { - struct amdgpu_connector *aconnector = link->priv; + struct amdgpu_dm_connector *aconnector = link->priv; struct i2c_msg *msgs; int i = 0; int num = cmd->number_of_payloads; @@ -455,7 +455,7 @@ enum dc_edid_status dm_helpers_read_local_edid( struct dc_link *link, struct dc_sink *sink) { - struct amdgpu_connector *aconnector = link->priv; + struct amdgpu_dm_connector *aconnector = link->priv; struct i2c_adapter *ddc; int retry = 3; enum dc_edid_status edid_status; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c index 4aee146a848f..276adf96d5f2 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c @@ -787,10 +787,10 @@ void amdgpu_dm_hpd_init(struct amdgpu_device *adev) struct drm_connector *connector; list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - struct amdgpu_connector *amdgpu_connector = - to_amdgpu_connector(connector); + struct amdgpu_dm_connector *amdgpu_dm_connector = + to_amdgpu_dm_connector(connector); - const struct dc_link *dc_link = amdgpu_connector->dc_link; + const struct dc_link *dc_link = amdgpu_dm_connector->dc_link; if (DC_IRQ_SOURCE_INVALID != dc_link->irq_source_hpd) { dc_interrupt_set(adev->dm.dc, @@ -820,9 +820,9 @@ void amdgpu_dm_hpd_fini(struct amdgpu_device *adev) struct drm_connector *connector; list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - struct amdgpu_connector *amdgpu_connector = - to_amdgpu_connector(connector); - const struct dc_link *dc_link = amdgpu_connector->dc_link; + struct amdgpu_dm_connector *amdgpu_dm_connector = + to_amdgpu_dm_connector(connector); + const struct dc_link *dc_link = amdgpu_dm_connector->dc_link; dc_interrupt_set(adev->dm.dc, dc_link->irq_source_hpd, false); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 82e4d49fb184..343645e4070b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -137,8 +137,8 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg static enum drm_connector_status dm_dp_mst_detect(struct drm_connector *connector, bool force) { - struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); - struct amdgpu_connector *master = aconnector->mst_port; + struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); + struct amdgpu_dm_connector *master = aconnector->mst_port; enum drm_connector_status status = drm_dp_mst_detect_port( @@ -152,13 +152,13 @@ dm_dp_mst_detect(struct drm_connector *connector, bool force) static void dm_dp_mst_connector_destroy(struct drm_connector *connector) { - struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); - struct amdgpu_encoder *amdgpu_encoder = amdgpu_connector->mst_encoder; + struct amdgpu_dm_connector *amdgpu_dm_connector = to_amdgpu_dm_connector(connector); + struct amdgpu_encoder *amdgpu_encoder = amdgpu_dm_connector->mst_encoder; drm_encoder_cleanup(&amdgpu_encoder->base); kfree(amdgpu_encoder); drm_connector_cleanup(connector); - kfree(amdgpu_connector); + kfree(amdgpu_dm_connector); } static const struct drm_connector_funcs dm_dp_mst_connector_funcs = { @@ -174,7 +174,7 @@ static const struct drm_connector_funcs dm_dp_mst_connector_funcs = { static int dm_dp_mst_get_modes(struct drm_connector *connector) { - struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); int ret = 0; ret = drm_add_edid_modes(&aconnector->base, aconnector->edid); @@ -186,9 +186,9 @@ static int dm_dp_mst_get_modes(struct drm_connector *connector) static struct drm_encoder *dm_mst_best_encoder(struct drm_connector *connector) { - struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); + struct amdgpu_dm_connector *amdgpu_dm_connector = to_amdgpu_dm_connector(connector); - return &amdgpu_connector->mst_encoder->base; + return &amdgpu_dm_connector->mst_encoder->base; } static const struct drm_connector_helper_funcs dm_dp_mst_connector_helper_funcs = { @@ -198,7 +198,7 @@ static const struct drm_connector_helper_funcs dm_dp_mst_connector_helper_funcs }; static struct amdgpu_encoder * -dm_dp_create_fake_mst_encoder(struct amdgpu_connector *connector) +dm_dp_create_fake_mst_encoder(struct amdgpu_dm_connector *connector) { struct drm_device *dev = connector->base.dev; struct amdgpu_device *adev = dev->dev_private; @@ -233,15 +233,15 @@ static struct drm_connector *dm_dp_add_mst_connector(struct drm_dp_mst_topology_ struct drm_dp_mst_port *port, const char *pathprop) { - struct amdgpu_connector *master = container_of(mgr, struct amdgpu_connector, mst_mgr); + struct amdgpu_dm_connector *master = container_of(mgr, struct amdgpu_dm_connector, mst_mgr); struct drm_device *dev = master->base.dev; struct amdgpu_device *adev = dev->dev_private; - struct amdgpu_connector *aconnector; + struct amdgpu_dm_connector *aconnector; struct drm_connector *connector; drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - aconnector = to_amdgpu_connector(connector); + aconnector = to_amdgpu_dm_connector(connector); if (aconnector->mst_port == master && !aconnector->port) { DRM_INFO("DM_MST: reusing connector: %p [id: %d] [master: %p]\n", @@ -315,7 +315,7 @@ static void dm_dp_destroy_mst_connector( struct drm_dp_mst_topology_mgr *mgr, struct drm_connector *connector) { - struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); DRM_INFO("DM_MST: Disabling connector: %p [id: %d] [master: %p]\n", aconnector, connector->base.id, aconnector->mst_port); @@ -339,17 +339,17 @@ static void dm_dp_destroy_mst_connector( static void dm_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr) { - struct amdgpu_connector *master = container_of(mgr, struct amdgpu_connector, mst_mgr); + struct amdgpu_dm_connector *master = container_of(mgr, struct amdgpu_dm_connector, mst_mgr); struct drm_device *dev = master->base.dev; struct amdgpu_device *adev = dev->dev_private; struct drm_connector *connector; - struct amdgpu_connector *aconnector; + struct amdgpu_dm_connector *aconnector; struct edid *edid; struct dc_sink *dc_sink; drm_modeset_lock_all(dev); list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - aconnector = to_amdgpu_connector(connector); + aconnector = to_amdgpu_dm_connector(connector); if (aconnector->port && aconnector->port->pdt != DP_PEER_DEVICE_NONE && aconnector->port->pdt != DP_PEER_DEVICE_MST_BRANCHING && @@ -440,7 +440,7 @@ static const struct drm_dp_mst_topology_cbs dm_mst_cbs = { void amdgpu_dm_initialize_dp_connector( struct amdgpu_display_manager *dm, - struct amdgpu_connector *aconnector) + struct amdgpu_dm_connector *aconnector) { aconnector->dm_dp_aux.aux.name = "dmdc"; aconnector->dm_dp_aux.aux.dev = dm->adev->dev; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h index 418061f3b46b..ba64a408d79c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h @@ -27,10 +27,10 @@ #define __DAL_AMDGPU_DM_MST_TYPES_H__ struct amdgpu_display_manager; -struct amdgpu_connector; +struct amdgpu_dm_connector; void amdgpu_dm_initialize_dp_connector( struct amdgpu_display_manager *dm, - struct amdgpu_connector *aconnector); + struct amdgpu_dm_connector *aconnector); #endif -- cgit From 2e0ac3d68838d20a5eace958bdf853a295a7175f Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 17 Aug 2017 14:58:07 -0400 Subject: drm/amd/display: Create fake sink if needed when commit stream The problem we're trying to fix is this (and similar): 1) X Desktop with single display 2) VT switch 3) Unplug display 4) VT switch back to X 5) re-plug same display Before this we'd fail at step 4 when trying to create a dc_stream_state because of a missing sink. This change will fake a sink in this case. The same scenario applies to S3 resume. Signed-off-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 29 ++++++++++++++++++++++- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 2 ++ 2 files changed, 30 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') 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 c42660520871..d2ece343b5fa 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -855,6 +855,10 @@ static void handle_hpd_irq(void *param) * since (for MST case) MST does this in it's own context. */ mutex_lock(&aconnector->hpd_lock); + + if (aconnector->fake_enable) + aconnector->fake_enable = false; + if (dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD)) { amdgpu_dm_update_connector_after_detect(aconnector); @@ -2278,6 +2282,25 @@ static void decide_crtc_timing_for_drm_display_mode( } } +static void create_fake_sink(struct amdgpu_dm_connector *aconnector) +{ + struct dc_sink *sink = NULL; + struct dc_sink_init_data sink_init_data = { 0 }; + + sink_init_data.link = aconnector->dc_link; + sink_init_data.sink_signal = aconnector->dc_link->connector_signal; + + sink = dc_sink_create(&sink_init_data); + if (!sink) + DRM_ERROR("Failed to create sink!\n"); + + sink->sink_signal = SIGNAL_TYPE_VIRTUAL; + aconnector->fake_enable = true; + + aconnector->dc_sink = sink; + aconnector->dc_link->local_sink = sink; +} + static struct dc_stream_state *create_stream_for_sink( struct amdgpu_dm_connector *aconnector, const struct drm_display_mode *drm_mode, @@ -2300,6 +2323,10 @@ static struct dc_stream_state *create_stream_for_sink( } drm_connector = &aconnector->base; + + if (!aconnector->dc_sink) + create_fake_sink(aconnector); + stream = dc_create_stream_for_sink(aconnector->dc_sink); if (stream == NULL) { @@ -4373,7 +4400,7 @@ static int dm_update_crtcs_state( aconnector = amdgpu_dm_find_first_crct_matching_connector(state, crtc, true); /* TODO This hack should go away */ - if (aconnector && aconnector->dc_sink) { + if (aconnector) { conn_state = drm_atomic_get_connector_state(state, &aconnector->base); 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 8894613e956c..630e6cdf84f6 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -187,6 +187,8 @@ struct amdgpu_dm_connector { struct mod_freesync_caps caps; struct mutex hpd_lock; + + bool fake_enable; }; #define to_amdgpu_dm_connector(x) container_of(x, struct amdgpu_dm_connector, base) -- cgit From e338aab03f0d8d0ae37b83bdf3ff5633c6eaf52f Mon Sep 17 00:00:00 2001 From: Vitaly Prosyak Date: Tue, 5 Sep 2017 15:58:37 -0500 Subject: drm/amd/display: Update DPP registers Signed-off-by: Vitaly Prosyak Reviewed-by: Charlene Liu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h index 34e501979b55..afe9d8f629d6 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h @@ -742,17 +742,11 @@ type CM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_G; \ type CM_SHAPER_RAMB_EXP_REGION_START_R; \ type CM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_R; \ - type CM_SHAPER_RAMB_EXP_REGION_LINEAR_SLOPE_B; \ - type CM_SHAPER_RAMB_EXP_REGION_LINEAR_SLOPE_G; \ - type CM_SHAPER_RAMB_EXP_REGION_LINEAR_SLOPE_R; \ type CM_SHAPER_RAMB_EXP_REGION_END_B; \ - type CM_SHAPER_RAMB_EXP_REGION_END_SLOPE_B; \ type CM_SHAPER_RAMB_EXP_REGION_END_BASE_B; \ type CM_SHAPER_RAMB_EXP_REGION_END_G; \ - type CM_SHAPER_RAMB_EXP_REGION_END_SLOPE_G; \ type CM_SHAPER_RAMB_EXP_REGION_END_BASE_G; \ type CM_SHAPER_RAMB_EXP_REGION_END_R; \ - type CM_SHAPER_RAMB_EXP_REGION_END_SLOPE_R; \ type CM_SHAPER_RAMB_EXP_REGION_END_BASE_R; \ type CM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET; \ type CM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS; \ @@ -828,17 +822,11 @@ type CM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_G; \ type CM_SHAPER_RAMA_EXP_REGION_START_R; \ type CM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_R; \ - type CM_SHAPER_RAMA_EXP_REGION_LINEAR_SLOPE_B; \ - type CM_SHAPER_RAMA_EXP_REGION_LINEAR_SLOPE_G; \ - type CM_SHAPER_RAMA_EXP_REGION_LINEAR_SLOPE_R; \ type CM_SHAPER_RAMA_EXP_REGION_END_B; \ - type CM_SHAPER_RAMA_EXP_REGION_END_SLOPE_B; \ type CM_SHAPER_RAMA_EXP_REGION_END_BASE_B; \ type CM_SHAPER_RAMA_EXP_REGION_END_G; \ - type CM_SHAPER_RAMA_EXP_REGION_END_SLOPE_G; \ type CM_SHAPER_RAMA_EXP_REGION_END_BASE_G; \ type CM_SHAPER_RAMA_EXP_REGION_END_R; \ - type CM_SHAPER_RAMA_EXP_REGION_END_SLOPE_R; \ type CM_SHAPER_RAMA_EXP_REGION_END_BASE_R; \ type CM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET; \ type CM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS; \ @@ -1160,6 +1148,9 @@ struct dcn_dpp_registers { uint32_t CM_SHAPER_RAMB_START_CNTL_B; uint32_t CM_SHAPER_RAMB_START_CNTL_G; uint32_t CM_SHAPER_RAMB_START_CNTL_R; + uint32_t CM_SHAPER_RAMB_END_CNTL_B; + uint32_t CM_SHAPER_RAMB_END_CNTL_G; + uint32_t CM_SHAPER_RAMB_END_CNTL_R; uint32_t CM_SHAPER_RAMB_REGION_0_1; uint32_t CM_SHAPER_RAMB_REGION_2_3; uint32_t CM_SHAPER_RAMB_REGION_4_5; @@ -1180,6 +1171,9 @@ struct dcn_dpp_registers { uint32_t CM_SHAPER_RAMA_START_CNTL_B; uint32_t CM_SHAPER_RAMA_START_CNTL_G; uint32_t CM_SHAPER_RAMA_START_CNTL_R; + uint32_t CM_SHAPER_RAMA_END_CNTL_B; + uint32_t CM_SHAPER_RAMA_END_CNTL_G; + uint32_t CM_SHAPER_RAMA_END_CNTL_R; uint32_t CM_SHAPER_RAMA_REGION_0_1; uint32_t CM_SHAPER_RAMA_REGION_2_3; uint32_t CM_SHAPER_RAMA_REGION_4_5; -- cgit From 05230fa90d96523755ddad30972a25b6651de739 Mon Sep 17 00:00:00 2001 From: Roman Li Date: Tue, 5 Sep 2017 18:23:46 -0400 Subject: drm/amd/display: Disable FBC for linear tiling - Fixing text console on FBC-enabled builds Signed-off-by: Roman Li Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 31592e53f504..37497e88a930 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1552,6 +1552,10 @@ static enum dc_status validate_fbc(struct dc *dc, if (pipe_ctx->stream->sink->link->psr_enabled) return DC_ERROR_UNEXPECTED; + /* Only for non-linear tiling */ + if (pipe_ctx->plane_state->tiling_info.gfx8.array_mode == DC_ARRAY_LINEAR_GENERAL) + return DC_ERROR_UNEXPECTED; + return DC_OK; } -- cgit From 1ecfc3da95428983725d643e80e9a320497d2059 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Fri, 8 Sep 2017 10:23:42 -0400 Subject: drm/amd/display: Format changes to bring in line with internal tree Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 6 +++--- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c | 4 ++-- drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c | 1 - 3 files changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') 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 d2ece343b5fa..bb4f415746d5 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -603,7 +603,7 @@ static int dm_resume(void *handle) return 0; } -int amdgpu_dm_display_resume(struct amdgpu_device *adev ) +int amdgpu_dm_display_resume(struct amdgpu_device *adev) { struct drm_device *ddev = adev->ddev; struct amdgpu_display_manager *dm = &adev->dm; @@ -1794,7 +1794,7 @@ static int fill_plane_attributes_from_fb( break; default: DRM_ERROR("Unsupported screen format %s\n", - drm_get_format_name(fb->format->format, &format_name)); + drm_get_format_name(fb->format->format, &format_name)); return -EINVAL; } @@ -2618,7 +2618,7 @@ struct drm_connector_state *amdgpu_dm_connector_atomic_duplicate_state( if (new_state) { __drm_atomic_helper_connector_duplicate_state(connector, - &new_state->base); + &new_state->base); return &new_state->base; } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c index 276adf96d5f2..22d41d35249e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c @@ -705,8 +705,8 @@ static inline int dm_irq_state( if (!acrtc) { DRM_ERROR( "%s: crtc is NULL at id :%d\n", - func, - crtc_id); + func, + crtc_id); return 0; } diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c index 25f6f9103c44..f7d049c0e62a 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c @@ -41,7 +41,6 @@ */ #include "dce80/hw_factory_dce80.h" - #include "dce110/hw_factory_dce110.h" #include "dce120/hw_factory_dce120.h" #if defined(CONFIG_DRM_AMD_DC_DCN1_0) -- cgit From f6baff4d1a0e3235b4a8ffd755e257b998705419 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Fri, 8 Sep 2017 10:24:21 -0400 Subject: drm/amd/display: Change comments to bring in line with internal tree Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 8 +++----- drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 37497e88a930..5bbfc34d6f01 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1439,13 +1439,11 @@ static uint32_t get_max_pixel_clock_for_all_paths( return max_pix_clk; } -/* Find clock state based on clock requested. if clock value is 0, simply +/* + * Find clock state based on clock requested. if clock value is 0, simply * set clock state as requested without finding clock state by clock value - *TODO: when dce120_hw_sequencer.c is created, override apply_min_clock. - * - * TODOFPGA remove TODO after implement dal_display_clock_get_cur_clocks_value - * etc support for dcn1.0 */ + static void apply_min_clocks( struct dc *dc, struct dc_state *context, diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c index 98ce0fe5ac37..d3eaf8977a60 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c @@ -372,7 +372,7 @@ static enum aux_channel_operation_result get_channel_status( 10, aux110->timeout_period/10); /* Note that the following bits are set in 'status.bits' - * during CTS 4.2.1.2: + * during CTS 4.2.1.2 (FW 3.3.1): * AUX_SW_RX_MIN_COUNT_VIOL, AUX_SW_RX_INVALID_STOP, * AUX_SW_RX_RECV_NO_DET, AUX_SW_RX_RECV_INVALID_H. * -- cgit From a6def44598eb6b82992ffd696cfd7f027940e2cd Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Fri, 8 Sep 2017 10:25:25 -0400 Subject: drm/amd/display: Update include to bring in line with internal tree Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 1 + drivers/gpu/drm/amd/display/include/dal_asic_id.h | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index c8c4b951ee1d..c4875c3a0d93 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -40,6 +40,7 @@ #include "ipp.h" #include "mpc.h" #include "reg_helper.h" +#include "custom_float.h" #define CTX \ hws->ctx diff --git a/drivers/gpu/drm/amd/display/include/dal_asic_id.h b/drivers/gpu/drm/amd/display/include/dal_asic_id.h index 14e3146a0cb2..7abe663ecc6e 100644 --- a/drivers/gpu/drm/amd/display/include/dal_asic_id.h +++ b/drivers/gpu/drm/amd/display/include/dal_asic_id.h @@ -112,6 +112,7 @@ /* DCN1_0 */ #define INTERNAL_REV_RAVEN_A0 0x00 /* First spin of Raven */ #define RAVEN_A0 0x01 +#define RAVEN_B0 0x21 #define RAVEN_UNKNOWN 0xFF #define ASIC_REV_IS_RAVEN(eChipRev) ((eChipRev >= RAVEN_A0) && eChipRev < RAVEN_UNKNOWN) -- cgit From dd3d18bf5e4994c5f8dd008db6123d0525eb62e5 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 11 Sep 2017 18:48:27 -0400 Subject: drm/amd/display: Clean Kconfig formatting Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/Kconfig | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/Kconfig b/drivers/gpu/drm/amd/display/Kconfig index 89fc8e738668..6d1086d0a277 100644 --- a/drivers/gpu/drm/amd/display/Kconfig +++ b/drivers/gpu/drm/amd/display/Kconfig @@ -18,11 +18,11 @@ config DRM_AMD_DC_PRE_VEGA and Hawaii. config DRM_AMD_DC_DCN1_0 - bool "DCN 1.0 Raven family" - depends on DRM_AMD_DC && X86 - help - Choose this option if you want to have - RV family for display engine + bool "DCN 1.0 Raven family" + depends on DRM_AMD_DC && X86 + help + Choose this option if you want to have + RV family for display engine config DEBUG_KERNEL_DC bool "Enable kgdb break in DC" -- cgit From 02e749dcbe5da2b1b2b1c3825be094287257046f Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 12 Sep 2017 20:02:11 -0400 Subject: drm/amdgpu: Add dc_log module parameter We want to make DC less chatty but still allow bug reporters to provide more detailed logs. Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 4 ++++ 2 files changed, 5 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 2c88dd07e1bc..cd1562fefd73 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -103,6 +103,7 @@ extern int amdgpu_vm_fault_stop; extern int amdgpu_vm_debug; extern int amdgpu_vm_update_mode; extern int amdgpu_dc; +extern int amdgpu_dc_log; extern int amdgpu_sched_jobs; extern int amdgpu_sched_hw_submission; extern int amdgpu_no_evict; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 13cd35b70c51..7e753969506b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -104,6 +104,7 @@ int amdgpu_vram_page_split = 512; int amdgpu_vm_update_mode = -1; int amdgpu_exp_hw_support = 0; int amdgpu_dc = -1; +int amdgpu_dc_log = 0; int amdgpu_sched_jobs = 32; int amdgpu_sched_hw_submission = 2; int amdgpu_no_evict = 0; @@ -211,6 +212,9 @@ module_param_named(exp_hw_support, amdgpu_exp_hw_support, int, 0444); MODULE_PARM_DESC(dc, "Display Core driver (1 = enable, 0 = disable, -1 = auto (default))"); module_param_named(dc, amdgpu_dc, int, 0444); +MODULE_PARM_DESC(dc, "Display Core Log Level (0 = minimal (default), 1 = chatty"); +module_param_named(dc_log, amdgpu_dc_log, int, 0444); + MODULE_PARM_DESC(sched_jobs, "the max number of jobs supported in the sw queue (default 32)"); module_param_named(sched_jobs, amdgpu_sched_jobs, int, 0444); -- cgit From 01a526f3dee9abe1e2db9e37e4ceb4149f8ae77b Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 12 Sep 2017 19:33:40 -0400 Subject: drm/amd/display: Pass log_mask from DM Linux and Windows often desire different log levels. Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 ++ drivers/gpu/drm/amd/display/dc/basics/logger.c | 41 +++------------------- drivers/gpu/drm/amd/display/dc/core/dc.c | 2 +- drivers/gpu/drm/amd/display/dc/dc.h | 1 + .../gpu/drm/amd/display/include/logger_interface.h | 2 +- drivers/gpu/drm/amd/display/include/logger_types.h | 32 +++++++++++++++++ 6 files changed, 42 insertions(+), 38 deletions(-) (limited to 'drivers/gpu') 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 bb4f415746d5..5f4e7dc92797 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -374,6 +374,8 @@ int amdgpu_dm_init(struct amdgpu_device *adev) init_data.dce_environment = DCE_ENV_PRODUCTION_DRV; + init_data.log_mask = DC_DEFAULT_LOG_MASK; + #ifdef ENABLE_FBC if (adev->family == FAMILY_CZ) amdgpu_dm_initialize_fbc(adev); diff --git a/drivers/gpu/drm/amd/display/dc/basics/logger.c b/drivers/gpu/drm/amd/display/dc/basics/logger.c index 0b17374b1535..5895dd3903a3 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/logger.c +++ b/drivers/gpu/drm/amd/display/dc/basics/logger.c @@ -64,40 +64,9 @@ static const struct dc_log_type_info log_type_info_tbl[] = { }; -#define DC_DEFAULT_LOG_MASK ((1 << LOG_ERROR) | \ - (1 << LOG_WARNING) | \ - (1 << LOG_EVENT_MODE_SET) | \ - (1 << LOG_EVENT_DETECTION) | \ - (1 << LOG_EVENT_LINK_TRAINING) | \ - (1 << LOG_EVENT_LINK_LOSS) | \ - (1 << LOG_EVENT_UNDERFLOW) | \ - (1 << LOG_RESOURCE) | \ - (1 << LOG_FEATURE_OVERRIDE) | \ - (1 << LOG_DETECTION_EDID_PARSER) | \ - (1 << LOG_DC) | \ - (1 << LOG_HW_HOTPLUG) | \ - (1 << LOG_HW_SET_MODE) | \ - (1 << LOG_HW_RESUME_S3) | \ - (1 << LOG_HW_HPD_IRQ) | \ - (1 << LOG_SYNC) | \ - (1 << LOG_BANDWIDTH_VALIDATION) | \ - (1 << LOG_MST) | \ - (1 << LOG_DETECTION_DP_CAPS) | \ - (1 << LOG_BACKLIGHT)) | \ - (1 << LOG_I2C_AUX) | \ - (1 << LOG_IF_TRACE) | \ - (1 << LOG_DTN) /* | \ - (1 << LOG_DEBUG) | \ - (1 << LOG_BIOS) | \ - (1 << LOG_SURFACE) | \ - (1 << LOG_SCALER) | \ - (1 << LOG_DML) | \ - (1 << LOG_HW_LINK_TRAINING) | \ - (1 << LOG_HW_AUDIO)| \ - (1 << LOG_BANDWIDTH_CALCS)*/ - /* ----------- Object init and destruction ----------- */ -static bool construct(struct dc_context *ctx, struct dal_logger *logger) +static bool construct(struct dc_context *ctx, struct dal_logger *logger, + uint32_t log_mask) { /* malloc buffer and init offsets */ logger->log_buffer_size = DAL_LOGGER_BUFFER_MAX_SIZE; @@ -120,7 +89,7 @@ static bool construct(struct dc_context *ctx, struct dal_logger *logger) logger->ctx = ctx; - logger->mask = DC_DEFAULT_LOG_MASK; + logger->mask = log_mask; return true; } @@ -133,14 +102,14 @@ static void destruct(struct dal_logger *logger) } } -struct dal_logger *dal_logger_create(struct dc_context *ctx) +struct dal_logger *dal_logger_create(struct dc_context *ctx, uint32_t log_mask) { /* malloc struct */ struct dal_logger *logger = dm_alloc(sizeof(struct dal_logger)); if (!logger) return NULL; - if (!construct(ctx, logger)) { + if (!construct(ctx, logger, log_mask)) { dm_free(logger); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 5579d2167a9a..75a5fa2296d7 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -493,7 +493,7 @@ static bool construct(struct dc *dc, dc_ctx->asic_id = init_params->asic_id; /* Create logger */ - logger = dal_logger_create(dc_ctx); + logger = dal_logger_create(dc_ctx, init_params->log_mask); if (!logger) { /* can *not* call logger. call base driver 'print error' */ diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 1f0521ff4614..9c0e00050753 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -267,6 +267,7 @@ struct dc_init_data { enum dce_environment dce_environment; struct dc_config flags; + uint32_t log_mask; #ifdef ENABLE_FBC uint64_t fbc_gpu_addr; #endif diff --git a/drivers/gpu/drm/amd/display/include/logger_interface.h b/drivers/gpu/drm/amd/display/include/logger_interface.h index 6641e8001e97..5aaf2dacfe38 100644 --- a/drivers/gpu/drm/amd/display/include/logger_interface.h +++ b/drivers/gpu/drm/amd/display/include/logger_interface.h @@ -40,7 +40,7 @@ struct dc_state; * */ -struct dal_logger *dal_logger_create(struct dc_context *ctx); +struct dal_logger *dal_logger_create(struct dc_context *ctx, uint32_t log_mask); uint32_t dal_logger_destroy(struct dal_logger **logger); diff --git a/drivers/gpu/drm/amd/display/include/logger_types.h b/drivers/gpu/drm/amd/display/include/logger_types.h index 42ffb93e3172..044805ccac25 100644 --- a/drivers/gpu/drm/amd/display/include/logger_types.h +++ b/drivers/gpu/drm/amd/display/include/logger_types.h @@ -70,6 +70,38 @@ enum dc_log_type { LOG_SECTION_TOTAL_COUNT }; +#define DC_DEFAULT_LOG_MASK ((1 << LOG_ERROR) | \ + (1 << LOG_WARNING) | \ + (1 << LOG_EVENT_MODE_SET) | \ + (1 << LOG_EVENT_DETECTION) | \ + (1 << LOG_EVENT_LINK_TRAINING) | \ + (1 << LOG_EVENT_LINK_LOSS) | \ + (1 << LOG_EVENT_UNDERFLOW) | \ + (1 << LOG_RESOURCE) | \ + (1 << LOG_FEATURE_OVERRIDE) | \ + (1 << LOG_DETECTION_EDID_PARSER) | \ + (1 << LOG_DC) | \ + (1 << LOG_HW_HOTPLUG) | \ + (1 << LOG_HW_SET_MODE) | \ + (1 << LOG_HW_RESUME_S3) | \ + (1 << LOG_HW_HPD_IRQ) | \ + (1 << LOG_SYNC) | \ + (1 << LOG_BANDWIDTH_VALIDATION) | \ + (1 << LOG_MST) | \ + (1 << LOG_DETECTION_DP_CAPS) | \ + (1 << LOG_BACKLIGHT)) | \ + (1 << LOG_I2C_AUX) | \ + (1 << LOG_IF_TRACE) | \ + (1 << LOG_DTN) /* | \ + (1 << LOG_DEBUG) | \ + (1 << LOG_BIOS) | \ + (1 << LOG_SURFACE) | \ + (1 << LOG_SCALER) | \ + (1 << LOG_DML) | \ + (1 << LOG_HW_LINK_TRAINING) | \ + (1 << LOG_HW_AUDIO)| \ + (1 << LOG_BANDWIDTH_CALCS)*/ + union logger_flags { struct { uint32_t ENABLE_CONSOLE:1; /* Print to console */ -- cgit From f1ad2f5efd29dc838222f37281675a2623714538 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 12 Sep 2017 20:04:48 -0400 Subject: drm/amd/display: Reduce DC chattiness Log DC init but default log level to 0 (default for amdgpu_dc_log) otherwise. Bug reporters can still make DC more chatty by using the dc_log module param. amdgpu.dc_log = 1 v2: Only provide runtime option, no compile time config Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 74 ++++++++++++---------- drivers/gpu/drm/amd/display/include/logger_types.h | 3 + 2 files changed, 42 insertions(+), 35 deletions(-) (limited to 'drivers/gpu') 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 5f4e7dc92797..36635486b937 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -334,7 +334,6 @@ int amdgpu_dm_init(struct amdgpu_device *adev) adev->dm.ddev = adev->ddev; adev->dm.adev = adev; - DRM_INFO("DAL is enabled\n"); /* Zero all the fields */ memset(&init_data, 0, sizeof(init_data)); @@ -374,7 +373,10 @@ int amdgpu_dm_init(struct amdgpu_device *adev) init_data.dce_environment = DCE_ENV_PRODUCTION_DRV; - init_data.log_mask = DC_DEFAULT_LOG_MASK; + if (amdgpu_dc_log) + init_data.log_mask = DC_DEFAULT_LOG_MASK; + else + init_data.log_mask = DC_MIN_LOG_MASK; #ifdef ENABLE_FBC if (adev->family == FAMILY_CZ) @@ -384,7 +386,9 @@ int amdgpu_dm_init(struct amdgpu_device *adev) /* Display Core create. */ adev->dm.dc = dc_create(&init_data); - if (!adev->dm.dc) + if (adev->dm.dc) + DRM_INFO("Display Core initialized!\n"); + else DRM_INFO("Display Core failed to initialize!\n"); INIT_WORK(&adev->dm.mst_hotplug_work, hotplug_notify_work_func); @@ -394,7 +398,7 @@ int amdgpu_dm_init(struct amdgpu_device *adev) DRM_ERROR( "amdgpu: failed to initialize freesync_module.\n"); } else - DRM_INFO("amdgpu: freesync_module init done %p.\n", + DRM_DEBUG_DRIVER("amdgpu: freesync_module init done %p.\n", adev->dm.freesync_module); if (amdgpu_dm_initialize_drm_device(adev)) { @@ -418,7 +422,7 @@ int amdgpu_dm_init(struct amdgpu_device *adev) goto error; } - DRM_INFO("KMS initialized.\n"); + DRM_DEBUG_DRIVER("KMS initialized.\n"); return 0; error: @@ -476,7 +480,7 @@ static int detect_mst_link_for_all_connectors(struct drm_device *dev) list_for_each_entry(connector, &dev->mode_config.connector_list, head) { aconnector = to_amdgpu_dm_connector(connector); if (aconnector->dc_link->type == dc_connection_mst_branch) { - DRM_INFO("DM_MST: starting TM on aconnector: %p [id: %d]\n", + DRM_DEBUG_DRIVER("DM_MST: starting TM on aconnector: %p [id: %d]\n", aconnector, aconnector->base.base.id); ret = drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_mgr, true); @@ -805,12 +809,12 @@ void amdgpu_dm_update_connector_after_detect( if (aconnector->dc_sink == sink) { /* We got a DP short pulse (Link Loss, DP CTS, etc...). * Do nothing!! */ - DRM_INFO("DCHPD: connector_id=%d: dc_sink didn't change.\n", + DRM_DEBUG_DRIVER("DCHPD: connector_id=%d: dc_sink didn't change.\n", aconnector->connector_id); return; } - DRM_INFO("DCHPD: connector_id=%d: Old sink=%p New sink=%p\n", + DRM_DEBUG_DRIVER("DCHPD: connector_id=%d: Old sink=%p New sink=%p\n", aconnector->connector_id, aconnector->dc_sink, sink); mutex_lock(&dev->mode_config.mutex); @@ -912,7 +916,7 @@ static void dm_handle_hpd_rx_irq(struct amdgpu_dm_connector *aconnector) process_count++; - DRM_DEBUG_KMS("ESI %02x %02x %02x\n", esi[0], esi[1], esi[2]); + DRM_DEBUG_DRIVER("ESI %02x %02x %02x\n", esi[0], esi[1], esi[2]); /* handle HPD short pulse irq */ if (aconnector->mst_mgr.mst_state) drm_dp_mst_hpd_irq( @@ -950,7 +954,7 @@ static void dm_handle_hpd_rx_irq(struct amdgpu_dm_connector *aconnector) } if (process_count == max_process_count) - DRM_DEBUG_KMS("Loop exceeded max iterations\n"); + DRM_DEBUG_DRIVER("Loop exceeded max iterations\n"); } static void handle_hpd_rx_irq(void *param) @@ -1269,7 +1273,7 @@ void amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm) if (NULL == dm->backlight_dev) DRM_ERROR("DM: Backlight registration failed!\n"); else - DRM_INFO("DM: Registered Backlight device: %s\n", bl_name); + DRM_DEBUG_DRIVER("DM: Registered Backlight device: %s\n", bl_name); } #endif @@ -2045,7 +2049,7 @@ static void update_stream_scaling_settings( stream->src = src; stream->dst = dst; - DRM_DEBUG_KMS("Destination Rectangle x:%d y:%d width:%d height:%d\n", + DRM_DEBUG_DRIVER("Destination Rectangle x:%d y:%d width:%d height:%d\n", dst.x, dst.y, dst.width, dst.height); } @@ -2355,7 +2359,7 @@ static struct dc_stream_state *create_stream_for_sink( * case, we call set mode ourselves to restore the previous mode * and the modelist may not be filled in in time. */ - DRM_INFO("No preferred mode found\n"); + DRM_DEBUG_DRIVER("No preferred mode found\n"); } else { decide_crtc_timing_for_drm_display_mode( &mode, preferred_mode, @@ -2644,7 +2648,7 @@ static struct drm_encoder *best_encoder(struct drm_connector *connector) struct drm_mode_object *obj; struct drm_encoder *encoder; - DRM_DEBUG_KMS("Finding the best encoder\n"); + DRM_DEBUG_DRIVER("Finding the best encoder\n"); /* pick the encoder ids */ if (enc_id) { @@ -2913,7 +2917,7 @@ static int dm_plane_helper_prepare_fb( dm_plane_state_new = to_dm_plane_state(new_state); if (!new_state->fb) { - DRM_DEBUG_KMS("No FB bound\n"); + DRM_DEBUG_DRIVER("No FB bound\n"); return 0; } @@ -3480,7 +3484,7 @@ int amdgpu_dm_connector_init( struct amdgpu_i2c_adapter *i2c; ((struct dc_link *)link)->priv = aconnector; - DRM_DEBUG_KMS("%s()\n", __func__); + DRM_DEBUG_DRIVER("%s()\n", __func__); i2c = create_i2c(link->ddc, link->link_index, &res); aconnector->i2c = i2c; @@ -3721,11 +3725,11 @@ static void handle_cursor_update( if (!plane->state->fb && !old_plane_state->fb) return; - DRM_DEBUG_KMS("%s: crtc_id=%d with size %d to %d\n", - __func__, - amdgpu_crtc->crtc_id, - plane->state->crtc_w, - plane->state->crtc_h); + DRM_DEBUG_DRIVER("%s: crtc_id=%d with size %d to %d\n", + __func__, + amdgpu_crtc->crtc_id, + plane->state->crtc_w, + plane->state->crtc_h); ret = get_cursor_position(plane, crtc, &position); if (ret) @@ -4028,7 +4032,7 @@ void amdgpu_dm_atomic_commit_tail( new_acrtc_state = to_dm_crtc_state(new_state); old_acrtc_state = to_dm_crtc_state(old_crtc_state); - DRM_DEBUG_KMS( + DRM_DEBUG_DRIVER( "amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, " "planes_changed:%d, mode_changed:%d,active_changed:%d," "connectors_changed:%d\n", @@ -4046,7 +4050,7 @@ void amdgpu_dm_atomic_commit_tail( if (modeset_required(new_state, new_acrtc_state->stream, old_acrtc_state->stream)) { - DRM_INFO("Atomic commit: SET crtc id %d: [%p]\n", acrtc->crtc_id, acrtc); + DRM_DEBUG_DRIVER("Atomic commit: SET crtc id %d: [%p]\n", acrtc->crtc_id, acrtc); if (!new_acrtc_state->stream) { /* @@ -4064,7 +4068,7 @@ void amdgpu_dm_atomic_commit_tail( * have a sink to keep the pipe running so that * hw state is consistent with the sw state */ - DRM_DEBUG_KMS("%s: Failed to create new stream for crtc %d\n", + DRM_DEBUG_DRIVER("%s: Failed to create new stream for crtc %d\n", __func__, acrtc->base.base.id); continue; } @@ -4091,7 +4095,7 @@ void amdgpu_dm_atomic_commit_tail( acrtc->hw_mode = crtc->state->mode; crtc->hwmode = crtc->state->mode; } else if (modereset_required(new_state)) { - DRM_INFO("Atomic commit: RESET. crtc id %d:[%p]\n", acrtc->crtc_id, acrtc); + DRM_DEBUG_DRIVER("Atomic commit: RESET. crtc id %d:[%p]\n", acrtc->crtc_id, acrtc); /* i.e. reset mode */ if (old_acrtc_state->stream) @@ -4116,7 +4120,7 @@ void amdgpu_dm_atomic_commit_tail( &new_crtcs[i]->base, false); if (!aconnector) { - DRM_INFO("Atomic commit: Failed to find connector for acrtc id:%d " + DRM_DEBUG_DRIVER("Atomic commit: Failed to find connector for acrtc id:%d " "skipping freesync init\n", new_crtcs[i]->crtc_id); continue; @@ -4425,7 +4429,7 @@ static int dm_update_crtcs_state( */ if (!new_stream) { - DRM_DEBUG_KMS("%s: Failed to create new stream for crtc %d\n", + DRM_DEBUG_DRIVER("%s: Failed to create new stream for crtc %d\n", __func__, acrtc->base.base.id); break; } @@ -4436,7 +4440,7 @@ static int dm_update_crtcs_state( crtc_state->mode_changed = false; - DRM_DEBUG_KMS("Mode change not required, setting mode_changed to %d", + DRM_DEBUG_DRIVER("Mode change not required, setting mode_changed to %d", crtc_state->mode_changed); } @@ -4444,7 +4448,7 @@ static int dm_update_crtcs_state( if (!drm_atomic_crtc_needs_modeset(crtc_state)) goto next_crtc; - DRM_DEBUG_KMS( + DRM_DEBUG_DRIVER( "amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, " "planes_changed:%d, mode_changed:%d,active_changed:%d," "connectors_changed:%d\n", @@ -4462,7 +4466,7 @@ static int dm_update_crtcs_state( if (!old_acrtc_state->stream) goto next_crtc; - DRM_DEBUG_KMS("Disabling DRM crtc: %d\n", + DRM_DEBUG_DRIVER("Disabling DRM crtc: %d\n", crtc->base.id); /* i.e. reset mode */ @@ -4492,7 +4496,7 @@ static int dm_update_crtcs_state( new_acrtc_state->stream = new_stream; dc_stream_retain(new_stream); - DRM_DEBUG_KMS("Enabling DRM crtc: %d\n", + DRM_DEBUG_DRIVER("Enabling DRM crtc: %d\n", crtc->base.id); if (!dc_add_stream_to_ctx( @@ -4567,7 +4571,7 @@ static int dm_update_planes_state( if (!old_acrtc_state->stream) continue; - DRM_DEBUG_KMS("Disabling DRM plane: %d on DRM crtc %d\n", + DRM_DEBUG_DRIVER("Disabling DRM plane: %d on DRM crtc %d\n", plane->base.id, old_plane_crtc->base.id); if (!dc_remove_plane_from_context( @@ -4605,7 +4609,7 @@ static int dm_update_planes_state( new_dm_plane_state->dc_state = dc_create_plane_state(dc); - DRM_DEBUG_KMS("Enabling DRM plane: %d on DRM crtc %d\n", + DRM_DEBUG_DRIVER("Enabling DRM plane: %d on DRM crtc %d\n", plane->base.id, new_plane_crtc->base.id); if (!new_dm_plane_state->dc_state) { @@ -4764,9 +4768,9 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, fail: if (ret == -EDEADLK) - DRM_DEBUG_KMS("Atomic check stopped due to to deadlock.\n"); + DRM_DEBUG_DRIVER("Atomic check stopped due to to deadlock.\n"); else if (ret == -EINTR || ret == -EAGAIN || ret == -ERESTARTSYS) - DRM_DEBUG_KMS("Atomic check stopped due to to signal.\n"); + DRM_DEBUG_DRIVER("Atomic check stopped due to to signal.\n"); else DRM_ERROR("Atomic check failed with err: %d \n", ret); diff --git a/drivers/gpu/drm/amd/display/include/logger_types.h b/drivers/gpu/drm/amd/display/include/logger_types.h index 044805ccac25..1f22e84cedb9 100644 --- a/drivers/gpu/drm/amd/display/include/logger_types.h +++ b/drivers/gpu/drm/amd/display/include/logger_types.h @@ -70,6 +70,9 @@ enum dc_log_type { LOG_SECTION_TOTAL_COUNT }; +#define DC_MIN_LOG_MASK ((1 << LOG_ERROR) | \ + (1 << LOG_DETECTION_EDID_PARSER)) + #define DC_DEFAULT_LOG_MASK ((1 << LOG_ERROR) | \ (1 << LOG_WARNING) | \ (1 << LOG_EVENT_MODE_SET) | \ -- cgit From 4a6cee2ca142615970fa3334191e992e7fb51159 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Sun, 24 Sep 2017 14:31:51 -0400 Subject: drm/amd/display: Remove unused dc_validate_guaranteed function It got refactored away and was never cleaned. Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 34 -------------------------------- 1 file changed, 34 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 75a5fa2296d7..58c5083bef2a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -651,40 +651,6 @@ void dc_destroy(struct dc **dc) *dc = NULL; } -bool dc_validate_guaranteed( - struct dc *dc, - struct dc_stream_state *stream) -{ - enum dc_status result = DC_ERROR_UNEXPECTED; - struct dc_state *context; - - if (!dc_validate_stream(dc, stream)) - return false; - - context = dm_alloc(sizeof(struct dc_state)); - if (context == NULL) - goto context_alloc_fail; - - dc_resource_state_construct(dc, dc->current_state); - - atomic_inc(&context->ref_count); - - result = dc->res_pool->funcs->validate_guaranteed( - dc, stream, context); - - dc_release_state(context); - -context_alloc_fail: - if (result != DC_OK) { - dm_logger_write(dc->ctx->logger, LOG_WARNING, - "%s:guaranteed validation failed, dc_status:%d\n", - __func__, - result); - } - - return (result == DC_OK); -} - static void program_timing_sync( struct dc *dc, struct dc_state *ctx) -- cgit From 2c8f195adf21430e4e8bbd13942826ccf8fa225c Mon Sep 17 00:00:00 2001 From: Shirish S Date: Tue, 26 Sep 2017 12:26:41 +0530 Subject: drm/amd/display: don't clean-up bottom pipe plane_state In the scenario of setting underlay, dc_validate_global_state() is called after constructing the context with all relevant bottom_pipe related configurations in dm_update_planes_state(). Currently, in dc_validate_global_state(), without checking for bottom_pipe's existence, the pipe_ctx structure is initialised to 0, hence nullyfying the plane_state of bottom_pipe which shall be accessed in populate_initial_data() called from bw_calcs(). Due to this null pointer access kernel panics and leads to reboot when underlay is tried to set. This patch fixes the issue by no longer clearing the top_pipe. This workaround is no longer required. Signed-off-by: Shirish S Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 15b627548cd2..dcfdfebd5c62 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1729,14 +1729,6 @@ bool dc_validate_global_state( dc, new_ctx) != DC_OK) return false; - /* TODO without this SWDEV-114774 brakes */ - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe_ctx = &new_ctx->res_ctx.pipe_ctx[i]; - - if (pipe_ctx->top_pipe) - memset(pipe_ctx, 0, sizeof(*pipe_ctx)); - } - for (i = 0; new_ctx && i < new_ctx->stream_count; i++) { struct dc_stream_state *stream = new_ctx->streams[i]; -- cgit From fff0925832368d55d2d50ccfedc3fb0887721627 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Mon, 18 Sep 2017 15:19:31 -0400 Subject: drm/amd/display: fix pflip irq registor for raven The pflip registor index was incorrect, this was overriding the macro and caused a dummy irq call. Signed-off-by: Bhawanpreet Lakha Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c b/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c index 7577e2903787..be59f0a654e2 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c @@ -272,8 +272,8 @@ irq_source_info_dcn10[DAL_IRQ_SOURCES_NUMBER] = { pflip_int_entry(1), pflip_int_entry(2), pflip_int_entry(3), - [DC_IRQ_SOURCE_PFLIP4] = dummy_irq_entry(), [DC_IRQ_SOURCE_PFLIP5] = dummy_irq_entry(), + [DC_IRQ_SOURCE_PFLIP6] = dummy_irq_entry(), [DC_IRQ_SOURCE_PFLIP_UNDERLAY0] = dummy_irq_entry(), gpio_pad_int_entry(0), gpio_pad_int_entry(1), -- cgit From dfbf0c14dd75d3b15f65478f10f373aa83042a50 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 2 Jun 2017 14:38:03 -0400 Subject: drm/amdgpu: drop experimental flag for vega10 Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 7e753969506b..96774ce00124 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -519,15 +519,15 @@ static const struct pci_device_id pciidlist[] = { {0x1002, 0x6997, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12}, {0x1002, 0x699F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12}, /* Vega 10 */ - {0x1002, 0x6860, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10|AMD_EXP_HW_SUPPORT}, - {0x1002, 0x6861, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10|AMD_EXP_HW_SUPPORT}, - {0x1002, 0x6862, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10|AMD_EXP_HW_SUPPORT}, - {0x1002, 0x6863, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10|AMD_EXP_HW_SUPPORT}, - {0x1002, 0x6864, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10|AMD_EXP_HW_SUPPORT}, - {0x1002, 0x6867, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10|AMD_EXP_HW_SUPPORT}, - {0x1002, 0x6868, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10|AMD_EXP_HW_SUPPORT}, - {0x1002, 0x686c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10|AMD_EXP_HW_SUPPORT}, - {0x1002, 0x687f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10|AMD_EXP_HW_SUPPORT}, + {0x1002, 0x6860, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10}, + {0x1002, 0x6861, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10}, + {0x1002, 0x6862, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10}, + {0x1002, 0x6863, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10}, + {0x1002, 0x6864, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10}, + {0x1002, 0x6867, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10}, + {0x1002, 0x6868, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10}, + {0x1002, 0x686c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10}, + {0x1002, 0x687f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10}, /* Raven */ {0x1002, 0x15dd, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RAVEN|AMD_IS_APU|AMD_EXP_HW_SUPPORT}, -- cgit From 82b400a62f2fd42b87f91a298c5641d0ead99251 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 27 Sep 2017 12:15:50 +0200 Subject: drm/amd: DC pull request review Ok, here's one more attempt at scrolling through 130k diff. Overall verdict from me is that DC is big project, and like any big project it's never done. So at least for me the goal isn't to make things perfect, becaue if that's the hoop to jump through we wouldn't have any gpu drivers at all. More important is whether merging a new driver base will benefit the overall subsystem, and here this primarily means whether the DC team understands how upstream works and is designed, and whether the code is largely aligned with upstream (especially the atomic modeset) architecture. Looking back over the last two years I think that's the case now, so Acked-by: Daniel Vetter for merging this pull. While scrolling through the pull I spotted a bunch more things that should be refactored, but most of these will be a real pain with DC is out of tree, and much easier in tree since in many of these areas the in-tree helpers aren't up to snuff yet for what DC needs. That kind of work is best done when there's one tree with everything integrated. That's also why I think we should merge DC into drm-next directly, so we can get started on the integration polish right away. That has a bit higher risk of Linus having a spazz, so here's my recommendation for merging: - There's a few additions to drm_dp_helper.h sprinkled all over the pull. I think those should be put into a patch of it's own, and merged first. No need to rebase DC, git merge will dtrt and not end up with duplicates. - dm_alloc/realloc/free is something Dave Airlie noticed, and I agree it's an easy red flag that might upset Linus. cocci can fix this easy, so no real problem I think to patch up in one big patch (I thought we've had a "remove malloc wrappers" todo item in the very first review, apparently there was more than one such wrapper). - The history is huge, but AMD folks want to keep it if possible, and I see the value in that. Would be good to get an ack from Linus for that (but shouldn't be an issue, not the first time we've merged the full history of out-of-tree work). Short&longer term TODO items are still tracked, might be a good idea to integrate those the overall drm todo in our gpu documentation, for more visibility. So in a way this is kinda like staging, except not with the horribly broken process of having an entirely separate tree for staging drivers which just makes refactoring needlessly painful (which defeats the point of staging really). So staging-within-the-subsystem. We've had that before, with early nouveau. And yes some of the files are utterly horrible to read and not anything close to kernel coding style standards. But that's the point, they're essentially gospel from hw engineers that happens to be parseable by gcc. Signed-off-by: Daniel Vetter Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/TODO | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/TODO b/drivers/gpu/drm/amd/display/TODO index 2737873db12d..eea645b102a1 100644 --- a/drivers/gpu/drm/amd/display/TODO +++ b/drivers/gpu/drm/amd/display/TODO @@ -79,3 +79,34 @@ TODOs 12. drm_modeset_lock in MST should no longer be needed in recent kernels * Adopt appropriate locking scheme + +13. get_modes and best_encoder callbacks look a bit funny. Can probably rip out +a few indirections, and consider removing entirely and using the +drm_atomic_helper_best_encoder default behaviour. + +14. core/dc_debug.c, consider switching to the atomic state debug helpers and +moving all your driver state printing into the various atomic_print_state +callbacks. There's also plans to expose this stuff in a standard way across all +drivers, to make debugging userspace compositors easier across different hw. + +15. Move DP/HDMI dual mode adaptors to drm_dp_dual_mode_helper.c. + +16. Move to core SCDC helpers (I think those are new since initial DC review). + +17. There's still a pretty massive layer cake around dp aux and DPCD handling, +with like 3 levels of abstraction and using your own structures instead of the +stuff in drm_dp_helper.h. drm_dp_helper.h isn't really great and already has 2 +incompatible styles, just means more reasons not to add a third (or well third +one gets to do the cleanup refactor). + +18. There's a pile of sink handling code, both for DP and HDMI where I didn't +immediately recognize the standard. I think long term it'd be best for the drm +subsystem if we try to move as much of that into helpers/core as possible, and +share it with drivers. But that's a very long term goal, and by far not just an +issue with DC - other drivers, especially around DP sink handling, are equally +guilty. + +19. The DC logger is still a rather sore thing, but I know that the DRM_DEBUG +stuff just isn't up to the challenges either. We need to figure out something +that integrates better with DRM and linux debug printing, while not being +useless with filtering output. dynamic debug printing might be an option. -- cgit From 2004f45ef83f07f43f5da6ede780b08068c7583d Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Wed, 27 Sep 2017 10:53:50 -0400 Subject: drm/amd/display: Use kernel alloc/free Abstractions are frowned upon. cocci script: virtual context virtual patch virtual org virtual report @@ expression ptr; @@ - dm_alloc(ptr) + kzalloc(ptr, GFP_KERNEL) @@ expression ptr, size; @@ - dm_realloc(ptr, size) + krealloc(ptr, size, GFP_KERNEL) @@ expression ptr; @@ - dm_free(ptr) + kfree(ptr) v2: use GFP_KERNEL, not GFP_ATOMIC. add cocci script Reviewed-by: Alex Deucher Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- drivers/gpu/drm/amd/display/dc/basics/logger.c | 18 ++++--- drivers/gpu/drm/amd/display/dc/basics/vector.c | 19 +++---- drivers/gpu/drm/amd/display/dc/bios/bios_parser.c | 17 +++--- drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c | 14 ++--- drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c | 5 +- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 6 +-- drivers/gpu/drm/amd/display/dc/core/dc.c | 42 ++++++++------- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 6 +-- drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c | 18 +++---- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_sink.c | 11 ++-- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 6 +-- drivers/gpu/drm/amd/display/dc/core/dc_surface.c | 15 +++--- drivers/gpu/drm/amd/display/dc/dce/dce_abm.c | 4 +- drivers/gpu/drm/amd/display/dc/dce/dce_audio.c | 4 +- .../gpu/drm/amd/display/dc/dce/dce_clock_source.c | 12 +++-- drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c | 10 ++-- drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c | 6 +-- drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c | 2 +- .../gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 2 +- drivers/gpu/drm/amd/display/dc/dce/dce_opp.c | 2 +- .../drm/amd/display/dc/dce100/dce100_resource.c | 43 +++++++-------- .../drm/amd/display/dc/dce110/dce110_compressor.c | 6 +-- .../drm/amd/display/dc/dce110/dce110_resource.c | 61 ++++++++++++---------- .../drm/amd/display/dc/dce112/dce112_compressor.c | 6 +-- .../drm/amd/display/dc/dce112/dce112_resource.c | 43 +++++++-------- .../drm/amd/display/dc/dce120/dce120_resource.c | 43 +++++++-------- .../drm/amd/display/dc/dce80/dce80_compressor.c | 6 +-- .../gpu/drm/amd/display/dc/dce80/dce80_resource.c | 47 +++++++++-------- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c | 2 +- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c | 2 +- .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 56 ++++++++++---------- drivers/gpu/drm/amd/display/dc/gpio/gpio_base.c | 4 +- drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c | 21 ++++---- drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c | 6 +-- drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c | 2 +- drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.c | 6 +-- .../amd/display/dc/i2caux/dce100/i2caux_dce100.c | 4 +- .../display/dc/i2caux/dce110/aux_engine_dce110.c | 6 +-- .../dc/i2caux/dce110/i2c_hw_engine_dce110.c | 7 +-- .../dc/i2caux/dce110/i2c_sw_engine_dce110.c | 7 +-- .../amd/display/dc/i2caux/dce110/i2caux_dce110.c | 6 +-- .../amd/display/dc/i2caux/dce112/i2caux_dce112.c | 4 +- .../amd/display/dc/i2caux/dce120/i2caux_dce120.c | 4 +- .../display/dc/i2caux/dce80/i2c_hw_engine_dce80.c | 6 +-- .../display/dc/i2caux/dce80/i2c_sw_engine_dce80.c | 6 +-- .../drm/amd/display/dc/i2caux/dce80/i2caux_dce80.c | 6 +-- .../drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.c | 4 +- .../display/dc/i2caux/diagnostics/i2caux_diag.c | 7 +-- .../gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.c | 6 +-- .../amd/display/dc/irq/dce110/irq_service_dce110.c | 5 +- .../amd/display/dc/irq/dce120/irq_service_dce120.c | 5 +- .../amd/display/dc/irq/dce80/irq_service_dce80.c | 5 +- .../amd/display/dc/irq/dcn10/irq_service_dcn10.c | 5 +- drivers/gpu/drm/amd/display/dc/irq/irq_service.c | 2 +- .../amd/display/dc/virtual/virtual_link_encoder.c | 2 +- .../display/dc/virtual/virtual_stream_encoder.c | 4 +- .../drm/amd/display/modules/freesync/freesync.c | 14 ++--- 59 files changed, 362 insertions(+), 330 deletions(-) (limited to 'drivers/gpu') 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 36635486b937..dba54c0a7b5f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2429,7 +2429,7 @@ dm_crtc_duplicate_state(struct drm_crtc *crtc) if (WARN_ON(!crtc->state)) return NULL; - state = dm_alloc(sizeof(*state)); + state = kzalloc(sizeof(*state), GFP_KERNEL); __drm_atomic_helper_crtc_duplicate_state(crtc, &state->base); diff --git a/drivers/gpu/drm/amd/display/dc/basics/logger.c b/drivers/gpu/drm/amd/display/dc/basics/logger.c index 5895dd3903a3..afb6d2d80e0c 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/logger.c +++ b/drivers/gpu/drm/amd/display/dc/basics/logger.c @@ -70,8 +70,8 @@ static bool construct(struct dc_context *ctx, struct dal_logger *logger, { /* malloc buffer and init offsets */ logger->log_buffer_size = DAL_LOGGER_BUFFER_MAX_SIZE; - logger->log_buffer = (char *)dm_alloc(logger->log_buffer_size * - sizeof(char)); + logger->log_buffer = (char *)kzalloc(logger->log_buffer_size * sizeof(char), + GFP_KERNEL); if (!logger->log_buffer) return false; @@ -97,7 +97,7 @@ static bool construct(struct dc_context *ctx, struct dal_logger *logger, static void destruct(struct dal_logger *logger) { if (logger->log_buffer) { - dm_free(logger->log_buffer); + kfree(logger->log_buffer); logger->log_buffer = NULL; } } @@ -105,12 +105,13 @@ static void destruct(struct dal_logger *logger) struct dal_logger *dal_logger_create(struct dc_context *ctx, uint32_t log_mask) { /* malloc struct */ - struct dal_logger *logger = dm_alloc(sizeof(struct dal_logger)); + struct dal_logger *logger = kzalloc(sizeof(struct dal_logger), + GFP_KERNEL); if (!logger) return NULL; if (!construct(ctx, logger, log_mask)) { - dm_free(logger); + kfree(logger); return NULL; } @@ -122,7 +123,7 @@ uint32_t dal_logger_destroy(struct dal_logger **logger) if (logger == NULL || *logger == NULL) return 1; destruct(*logger); - dm_free(*logger); + kfree(*logger); *logger = NULL; return 0; @@ -390,7 +391,8 @@ void dm_logger_open( entry->type = log_type; entry->logger = logger; - entry->buf = dm_alloc(DAL_LOGGER_BUFFER_MAX_SIZE * sizeof(char)); + entry->buf = kzalloc(DAL_LOGGER_BUFFER_MAX_SIZE * sizeof(char), + GFP_KERNEL); entry->buf_offset = 0; entry->max_buf_bytes = DAL_LOGGER_BUFFER_MAX_SIZE * sizeof(char); @@ -421,7 +423,7 @@ void dm_logger_close(struct log_entry *entry) cleanup: if (entry->buf) { - dm_free(entry->buf); + kfree(entry->buf); entry->buf = NULL; entry->buf_offset = 0; entry->max_buf_bytes = 0; diff --git a/drivers/gpu/drm/amd/display/dc/basics/vector.c b/drivers/gpu/drm/amd/display/dc/basics/vector.c index bb72a1857160..e00fc4db3ac4 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/vector.c +++ b/drivers/gpu/drm/amd/display/dc/basics/vector.c @@ -40,7 +40,7 @@ bool dal_vector_construct( return false; } - vector->container = dm_alloc(struct_size * capacity); + vector->container = kzalloc(struct_size * capacity, GFP_KERNEL); if (vector->container == NULL) return false; vector->capacity = capacity; @@ -67,7 +67,7 @@ bool dal_vector_presized_costruct( return false; } - vector->container = dm_alloc(struct_size * count); + vector->container = kzalloc(struct_size * count, GFP_KERNEL); if (vector->container == NULL) return false; @@ -95,7 +95,7 @@ struct vector *dal_vector_presized_create( void *initial_value, uint32_t struct_size) { - struct vector *vector = dm_alloc(sizeof(struct vector)); + struct vector *vector = kzalloc(sizeof(struct vector), GFP_KERNEL); if (vector == NULL) return NULL; @@ -105,7 +105,7 @@ struct vector *dal_vector_presized_create( return vector; BREAK_TO_DEBUGGER(); - dm_free(vector); + kfree(vector); return NULL; } @@ -114,7 +114,7 @@ struct vector *dal_vector_create( uint32_t capacity, uint32_t struct_size) { - struct vector *vector = dm_alloc(sizeof(struct vector)); + struct vector *vector = kzalloc(sizeof(struct vector), GFP_KERNEL); if (vector == NULL) return NULL; @@ -123,7 +123,7 @@ struct vector *dal_vector_create( return vector; BREAK_TO_DEBUGGER(); - dm_free(vector); + kfree(vector); return NULL; } @@ -131,7 +131,7 @@ void dal_vector_destruct( struct vector *vector) { if (vector->container != NULL) - dm_free(vector->container); + kfree(vector->container); vector->count = 0; vector->capacity = 0; } @@ -142,7 +142,7 @@ void dal_vector_destroy( if (vector == NULL || *vector == NULL) return; dal_vector_destruct(*vector); - dm_free(*vector); + kfree(*vector); *vector = NULL; } @@ -290,7 +290,8 @@ bool dal_vector_reserve(struct vector *vector, uint32_t capacity) if (capacity <= vector->capacity) return true; - new_container = dm_realloc(vector->container, capacity * vector->struct_size); + new_container = krealloc(vector->container, + capacity * vector->struct_size, GFP_KERNEL); if (new_container) { vector->container = new_container; diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c index 2c411441771b..47d673a1f688 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c @@ -116,14 +116,14 @@ struct dc_bios *bios_parser_create( { struct bios_parser *bp = NULL; - bp = dm_alloc(sizeof(struct bios_parser)); + bp = kzalloc(sizeof(struct bios_parser), GFP_KERNEL); if (!bp) return NULL; if (bios_parser_construct(bp, init, dce_version)) return &bp->base; - dm_free(bp); + kfree(bp); BREAK_TO_DEBUGGER(); return NULL; } @@ -131,10 +131,10 @@ struct dc_bios *bios_parser_create( static void destruct(struct bios_parser *bp) { if (bp->base.bios_local_image) - dm_free(bp->base.bios_local_image); + kfree(bp->base.bios_local_image); if (bp->base.integrated_info) - dm_free(bp->base.integrated_info); + kfree(bp->base.integrated_info); } static void bios_parser_destroy(struct dc_bios **dcb) @@ -148,7 +148,7 @@ static void bios_parser_destroy(struct dc_bios **dcb) destruct(bp); - dm_free(bp); + kfree(bp); *dcb = NULL; } @@ -3531,7 +3531,8 @@ static void process_ext_display_connection_info(struct bios_parser *bp) uint8_t *original_bios; /* Step 1: Replace bios image with the new copy which will be * patched */ - bp->base.bios_local_image = dm_alloc(bp->base.bios_size); + bp->base.bios_local_image = kzalloc(bp->base.bios_size, + GFP_KERNEL); if (bp->base.bios_local_image == NULL) { BREAK_TO_DEBUGGER(); /* Failed to alloc bp->base.bios_local_image */ @@ -3965,7 +3966,7 @@ static struct integrated_info *bios_parser_create_integrated_info( struct bios_parser *bp = BP_FROM_DCB(dcb); struct integrated_info *info = NULL; - info = dm_alloc(sizeof(struct integrated_info)); + info = kzalloc(sizeof(struct integrated_info), GFP_KERNEL); if (info == NULL) { ASSERT_CRITICAL(0); @@ -3975,7 +3976,7 @@ static struct integrated_info *bios_parser_create_integrated_info( if (construct_integrated_info(bp, info) == BP_RESULT_OK) return info; - dm_free(info); + kfree(info); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c index 95fe50f62c57..3f8e605efde9 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -107,10 +107,10 @@ static struct atom_encoder_caps_record *get_encoder_cap_record( static void destruct(struct bios_parser *bp) { if (bp->base.bios_local_image) - dm_free(bp->base.bios_local_image); + kfree(bp->base.bios_local_image); if (bp->base.integrated_info) - dm_free(bp->base.integrated_info); + kfree(bp->base.integrated_info); } static void firmware_parser_destroy(struct dc_bios **dcb) @@ -124,7 +124,7 @@ static void firmware_parser_destroy(struct dc_bios **dcb) destruct(bp); - dm_free(bp); + kfree(bp); *dcb = NULL; } @@ -2030,7 +2030,7 @@ static struct integrated_info *bios_parser_create_integrated_info( struct bios_parser *bp = BP_FROM_DCB(dcb); struct integrated_info *info = NULL; - info = dm_alloc(sizeof(struct integrated_info)); + info = kzalloc(sizeof(struct integrated_info), GFP_KERNEL); if (info == NULL) { ASSERT_CRITICAL(0); @@ -2040,7 +2040,7 @@ static struct integrated_info *bios_parser_create_integrated_info( if (construct_integrated_info(bp, info) == BP_RESULT_OK) return info; - dm_free(info); + kfree(info); return NULL; } @@ -2205,14 +2205,14 @@ struct dc_bios *firmware_parser_create( { struct bios_parser *bp = NULL; - bp = dm_alloc(sizeof(struct bios_parser)); + bp = kzalloc(sizeof(struct bios_parser), GFP_KERNEL); if (!bp) return NULL; if (bios_parser_construct(bp, init, dce_version)) return &bp->base; - dm_free(bp); + kfree(bp); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c index dba25853f7f9..15cbfc400633 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c @@ -2792,7 +2792,8 @@ bool bw_calcs(struct dc_context *ctx, int pipe_count, struct dce_bw_output *calcs_output) { - struct bw_calcs_data *data = dm_alloc(sizeof(struct bw_calcs_data)); + struct bw_calcs_data *data = kzalloc(sizeof(struct bw_calcs_data), + GFP_KERNEL); populate_initial_data(pipe, pipe_count, data); @@ -3248,7 +3249,7 @@ bool bw_calcs(struct dc_context *ctx, calcs_output->sclk_khz = 0; } - dm_free(data); + kfree(data); return is_display_configuration_supported(vbios, calcs_output); } diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 1b0f64756be6..91f43a1b88ee 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -481,8 +481,8 @@ static void dcn_dml_wm_override( { int i, in_idx, active_count; - struct _vcs_dpi_display_e2e_pipe_params_st *input = dm_alloc(pool->pipe_count * - sizeof(struct _vcs_dpi_display_e2e_pipe_params_st)); + struct _vcs_dpi_display_e2e_pipe_params_st *input = kzalloc(pool->pipe_count * sizeof(struct _vcs_dpi_display_e2e_pipe_params_st), + GFP_KERNEL); struct wm { double urgent; struct _vcs_dpi_cstate_pstate_watermarks_st cpstate; @@ -560,7 +560,7 @@ static void dcn_dml_wm_override( pipe->plane_state->flip_immediate); in_idx++; } - dm_free(input); + kfree(input); } static void split_stream_across_pipes( diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 58c5083bef2a..d86d9796e4cc 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -113,7 +113,7 @@ static bool create_links( } for (i = 0; i < num_virtual_links; i++) { - struct dc_link *link = dm_alloc(sizeof(*link)); + struct dc_link *link = kzalloc(sizeof(*link), GFP_KERNEL); struct encoder_init_data enc_init = {0}; if (link == NULL) { @@ -127,7 +127,7 @@ static bool create_links( link->link_id.type = OBJECT_TYPE_CONNECTOR; link->link_id.id = CONNECTOR_ID_VIRTUAL; link->link_id.enum_id = ENUM_ID_1; - link->link_enc = dm_alloc(sizeof(*link->link_enc)); + link->link_enc = kzalloc(sizeof(*link->link_enc), GFP_KERNEL); enc_init.ctx = dc->ctx; enc_init.channel = CHANNEL_ID_UNKNOWN; @@ -413,20 +413,20 @@ static void destruct(struct dc *dc) if (dc->ctx->logger) dal_logger_destroy(&dc->ctx->logger); - dm_free(dc->ctx); + kfree(dc->ctx); dc->ctx = NULL; - dm_free(dc->bw_vbios); + kfree(dc->bw_vbios); dc->bw_vbios = NULL; - dm_free(dc->bw_dceip); + kfree(dc->bw_dceip); dc->bw_dceip = NULL; #ifdef CONFIG_DRM_AMD_DC_DCN1_0 - dm_free(dc->dcn_soc); + kfree(dc->dcn_soc); dc->dcn_soc = NULL; - dm_free(dc->dcn_ip); + kfree(dc->dcn_ip); dc->dcn_ip = NULL; #endif @@ -436,12 +436,15 @@ static bool construct(struct dc *dc, const struct dc_init_data *init_params) { struct dal_logger *logger; - struct dc_context *dc_ctx = dm_alloc(sizeof(*dc_ctx)); - struct bw_calcs_dceip *dc_dceip = dm_alloc(sizeof(*dc_dceip)); - struct bw_calcs_vbios *dc_vbios = dm_alloc(sizeof(*dc_vbios)); + struct dc_context *dc_ctx = kzalloc(sizeof(*dc_ctx), GFP_KERNEL); + struct bw_calcs_dceip *dc_dceip = kzalloc(sizeof(*dc_dceip), + GFP_KERNEL); + struct bw_calcs_vbios *dc_vbios = kzalloc(sizeof(*dc_vbios), + GFP_KERNEL); #ifdef CONFIG_DRM_AMD_DC_DCN1_0 - struct dcn_soc_bounding_box *dcn_soc = dm_alloc(sizeof(*dcn_soc)); - struct dcn_ip_params *dcn_ip = dm_alloc(sizeof(*dcn_ip)); + struct dcn_soc_bounding_box *dcn_soc = kzalloc(sizeof(*dcn_soc), + GFP_KERNEL); + struct dcn_ip_params *dcn_ip = kzalloc(sizeof(*dcn_ip), GFP_KERNEL); #endif enum dce_version dc_version = DCE_VERSION_UNKNOWN; @@ -604,7 +607,7 @@ void ProgramPixelDurationV(unsigned int pixelClockInKHz ) struct dc *dc_create(const struct dc_init_data *init_params) { - struct dc *dc = dm_alloc(sizeof(*dc)); + struct dc *dc = kzalloc(sizeof(*dc), GFP_KERNEL); unsigned int full_pipe_count; if (NULL == dc) @@ -638,7 +641,7 @@ struct dc *dc_create(const struct dc_init_data *init_params) return dc; construct_fail: - dm_free(dc); + kfree(dc); alloc_fail: return NULL; @@ -647,7 +650,7 @@ alloc_fail: void dc_destroy(struct dc **dc) { destruct(*dc); - dm_free(*dc); + kfree(*dc); *dc = NULL; } @@ -900,7 +903,7 @@ bool dc_commit_planes_to_stream( struct dc_scaling_info scaling_info[MAX_SURFACES]; int i; struct dc_stream_update *stream_update = - dm_alloc(sizeof(struct dc_stream_update)); + kzalloc(sizeof(struct dc_stream_update), GFP_KERNEL); if (!stream_update) { BREAK_TO_DEBUGGER(); @@ -951,13 +954,14 @@ bool dc_commit_planes_to_stream( dc_post_update_surfaces_to_stream(dc); - dm_free(stream_update); + kfree(stream_update); return true; } struct dc_state *dc_create_state(void) { - struct dc_state *context = dm_alloc(sizeof(struct dc_state)); + struct dc_state *context = kzalloc(sizeof(struct dc_state), + GFP_KERNEL); if (!context) return NULL; @@ -979,7 +983,7 @@ void dc_release_state(struct dc_state *context) if (atomic_read(&context->ref_count) == 0) { dc_resource_state_destruct(context); - dm_free(context); + kfree(context); } } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 845ec421d861..43ebd8941b77 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1100,7 +1100,7 @@ create_fail: struct dc_link *link_create(const struct link_init_data *init_params) { struct dc_link *link = - dm_alloc(sizeof(*link)); + kzalloc(sizeof(*link), GFP_KERNEL); if (NULL == link) goto alloc_fail; @@ -1111,7 +1111,7 @@ struct dc_link *link_create(const struct link_init_data *init_params) return link; construct_fail: - dm_free(link); + kfree(link); alloc_fail: return NULL; @@ -1120,7 +1120,7 @@ alloc_fail: void link_destroy(struct dc_link **link) { destruct(*link); - dm_free(*link); + kfree(*link); *link = NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c index d09e539397ea..226512c11ab7 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c @@ -130,7 +130,7 @@ struct i2c_payloads *dal_ddc_i2c_payloads_create(struct dc_context *ctx, uint32_ { struct i2c_payloads *payloads; - payloads = dm_alloc(sizeof(struct i2c_payloads)); + payloads = kzalloc(sizeof(struct i2c_payloads), GFP_KERNEL); if (!payloads) return NULL; @@ -139,7 +139,7 @@ struct i2c_payloads *dal_ddc_i2c_payloads_create(struct dc_context *ctx, uint32_ &payloads->payloads, ctx, count, sizeof(struct i2c_payload))) return payloads; - dm_free(payloads); + kfree(payloads); return NULL; } @@ -159,7 +159,7 @@ void dal_ddc_i2c_payloads_destroy(struct i2c_payloads **p) if (!p || !*p) return; dal_vector_destruct(&(*p)->payloads); - dm_free(*p); + kfree(*p); *p = NULL; } @@ -168,7 +168,7 @@ struct aux_payloads *dal_ddc_aux_payloads_create(struct dc_context *ctx, uint32_ { struct aux_payloads *payloads; - payloads = dm_alloc(sizeof(struct aux_payloads)); + payloads = kzalloc(sizeof(struct aux_payloads), GFP_KERNEL); if (!payloads) return NULL; @@ -177,7 +177,7 @@ struct aux_payloads *dal_ddc_aux_payloads_create(struct dc_context *ctx, uint32_ &payloads->payloads, ctx, count, sizeof(struct aux_payload))) return payloads; - dm_free(payloads); + kfree(payloads); return NULL; } @@ -197,7 +197,7 @@ void dal_ddc_aux_payloads_destroy(struct aux_payloads **p) return; dal_vector_destruct(&(*p)->payloads); - dm_free(*p); + kfree(*p); *p = NULL; } @@ -290,7 +290,7 @@ struct ddc_service *dal_ddc_service_create( { struct ddc_service *ddc_service; - ddc_service = dm_alloc(sizeof(struct ddc_service)); + ddc_service = kzalloc(sizeof(struct ddc_service), GFP_KERNEL); if (!ddc_service) return NULL; @@ -298,7 +298,7 @@ struct ddc_service *dal_ddc_service_create( if (construct(ddc_service, init_data)) return ddc_service; - dm_free(ddc_service); + kfree(ddc_service); return NULL; } @@ -315,7 +315,7 @@ void dal_ddc_service_destroy(struct ddc_service **ddc) return; } destruct(*ddc); - dm_free(*ddc); + kfree(*ddc); *ddc = NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index dcfdfebd5c62..1832f252edab 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -160,7 +160,7 @@ void dc_destroy_resource_pool(struct dc *dc) dc->res_pool->funcs->destroy(&dc->res_pool); if (dc->hwseq) - dm_free(dc->hwseq); + kfree(dc->hwseq); } } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_sink.c b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c index 7717350297a5..b3bbafc8fd6a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_sink.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c @@ -34,7 +34,7 @@ static void destruct(struct dc_sink *sink) { if (sink->dc_container_id) { - dm_free(sink->dc_container_id); + kfree(sink->dc_container_id); sink->dc_container_id = NULL; } } @@ -74,13 +74,13 @@ void dc_sink_release(struct dc_sink *sink) if (atomic_read(&sink->ref_count) == 0) { destruct(sink); - dm_free(sink); + kfree(sink); } } struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params) { - struct dc_sink *sink = dm_alloc(sizeof(*sink)); + struct dc_sink *sink = kzalloc(sizeof(*sink), GFP_KERNEL); if (NULL == sink) goto alloc_fail; @@ -93,7 +93,7 @@ struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params) return sink; construct_fail: - dm_free(sink); + kfree(sink); alloc_fail: return NULL; @@ -117,7 +117,8 @@ bool dc_sink_set_container_id(struct dc_sink *dc_sink, const struct dc_container { if (dc_sink && container_id) { if (!dc_sink->dc_container_id) - dc_sink->dc_container_id = dm_alloc(sizeof(*dc_sink->dc_container_id)); + dc_sink->dc_container_id = kzalloc(sizeof(*dc_sink->dc_container_id), + GFP_KERNEL); if (dc_sink->dc_container_id) { memmove(&dc_sink->dc_container_id->guid, &container_id->guid, diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index a421779093d9..d5da847ffad6 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -131,7 +131,7 @@ void dc_stream_release(struct dc_stream_state *stream) if (atomic_read(&stream->ref_count) == 0) { destruct(stream); - dm_free(stream); + kfree(stream); } } } @@ -144,7 +144,7 @@ struct dc_stream_state *dc_create_stream_for_sink( if (sink == NULL) goto alloc_fail; - stream = dm_alloc(sizeof(struct dc_stream_state)); + stream = kzalloc(sizeof(struct dc_stream_state), GFP_KERNEL); if (NULL == stream) goto alloc_fail; @@ -157,7 +157,7 @@ struct dc_stream_state *dc_create_stream_for_sink( return stream; construct_fail: - dm_free(stream); + kfree(stream); alloc_fail: return NULL; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index e96f63eed070..511ada94530e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -68,7 +68,8 @@ struct dc_plane_state *dc_create_plane_state(struct dc *dc) { struct dc *core_dc = dc; - struct dc_plane_state *plane_state = dm_alloc(sizeof(*plane_state)); + struct dc_plane_state *plane_state = kzalloc(sizeof(*plane_state), + GFP_KERNEL); if (NULL == plane_state) goto alloc_fail; @@ -81,7 +82,7 @@ struct dc_plane_state *dc_create_plane_state(struct dc *dc) return plane_state; construct_fail: - dm_free(plane_state); + kfree(plane_state); alloc_fail: return NULL; @@ -133,7 +134,7 @@ void dc_plane_state_release(struct dc_plane_state *plane_state) if (atomic_read(&plane_state->ref_count) == 0) { destruct(plane_state); - dm_free(plane_state); + kfree(plane_state); } } @@ -149,14 +150,14 @@ void dc_gamma_release(struct dc_gamma **gamma) atomic_dec(&(*gamma)->ref_count); if (atomic_read(&(*gamma)->ref_count) == 0) - dm_free((*gamma)); + kfree((*gamma)); *gamma = NULL; } struct dc_gamma *dc_create_gamma() { - struct dc_gamma *gamma = dm_alloc(sizeof(*gamma)); + struct dc_gamma *gamma = kzalloc(sizeof(*gamma), GFP_KERNEL); if (gamma == NULL) goto alloc_fail; @@ -181,12 +182,12 @@ void dc_transfer_func_release(struct dc_transfer_func *tf) atomic_dec(&tf->ref_count); if (atomic_read(&tf->ref_count) == 0) - dm_free(tf); + kfree(tf); } struct dc_transfer_func *dc_create_transfer_func() { - struct dc_transfer_func *tf = dm_alloc(sizeof(*tf)); + struct dc_transfer_func *tf = kzalloc(sizeof(*tf), GFP_KERNEL); if (tf == NULL) goto alloc_fail; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c index 0e9d914e1a8f..0e0336c5af4e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c @@ -462,7 +462,7 @@ struct abm *dce_abm_create( const struct dce_abm_shift *abm_shift, const struct dce_abm_mask *abm_mask) { - struct dce_abm *abm_dce = dm_alloc(sizeof(*abm_dce)); + struct dce_abm *abm_dce = kzalloc(sizeof(*abm_dce), GFP_KERNEL); if (abm_dce == NULL) { BREAK_TO_DEBUGGER(); @@ -480,6 +480,6 @@ void dce_abm_destroy(struct abm **abm) { struct dce_abm *abm_dce = TO_DCE_ABM(*abm); - dm_free(abm_dce); + kfree(abm_dce); *abm = NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c index b94c1e5d85cb..198f4532e100 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c @@ -897,7 +897,7 @@ void dce_aud_destroy(struct audio **audio) { struct dce_audio *aud = DCE_AUD(*audio); - dm_free(aud); + kfree(aud); *audio = NULL; } @@ -909,7 +909,7 @@ struct audio *dce_audio_create( const struct dce_aduio_mask *masks ) { - struct dce_audio *audio = dm_alloc(sizeof(*audio)); + struct dce_audio *audio = kzalloc(sizeof(*audio), GFP_KERNEL); if (audio == NULL) { ASSERT_CRITICAL(audio); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index d3b61b92ebec..31280d252753 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -1084,12 +1084,14 @@ static void get_ss_info_from_atombios( if (*ss_entries_num == 0) return; - ss_info = dm_alloc(sizeof(struct spread_spectrum_info) * (*ss_entries_num)); + ss_info = kzalloc(sizeof(struct spread_spectrum_info) * (*ss_entries_num), + GFP_KERNEL); ss_info_cur = ss_info; if (ss_info == NULL) return; - ss_data = dm_alloc(sizeof(struct spread_spectrum_data) * (*ss_entries_num)); + ss_data = kzalloc(sizeof(struct spread_spectrum_data) * (*ss_entries_num), + GFP_KERNEL); if (ss_data == NULL) goto out_free_info; @@ -1157,14 +1159,14 @@ static void get_ss_info_from_atombios( } *spread_spectrum_data = ss_data; - dm_free(ss_info); + kfree(ss_info); return; out_free_data: - dm_free(ss_data); + kfree(ss_data); *ss_entries_num = 0; out_free_info: - dm_free(ss_info); + kfree(ss_info); } static void ss_info_from_atombios_create( diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c index 06d9a3e7c8a2..3e9ff2f5472d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c @@ -719,7 +719,7 @@ struct display_clock *dce_disp_clk_create( const struct dce_disp_clk_shift *clk_shift, const struct dce_disp_clk_mask *clk_mask) { - struct dce_disp_clk *clk_dce = dm_alloc(sizeof(*clk_dce)); + struct dce_disp_clk *clk_dce = kzalloc(sizeof(*clk_dce), GFP_KERNEL); if (clk_dce == NULL) { BREAK_TO_DEBUGGER(); @@ -742,7 +742,7 @@ struct display_clock *dce110_disp_clk_create( const struct dce_disp_clk_shift *clk_shift, const struct dce_disp_clk_mask *clk_mask) { - struct dce_disp_clk *clk_dce = dm_alloc(sizeof(*clk_dce)); + struct dce_disp_clk *clk_dce = kzalloc(sizeof(*clk_dce), GFP_KERNEL); if (clk_dce == NULL) { BREAK_TO_DEBUGGER(); @@ -767,7 +767,7 @@ struct display_clock *dce112_disp_clk_create( const struct dce_disp_clk_shift *clk_shift, const struct dce_disp_clk_mask *clk_mask) { - struct dce_disp_clk *clk_dce = dm_alloc(sizeof(*clk_dce)); + struct dce_disp_clk *clk_dce = kzalloc(sizeof(*clk_dce), GFP_KERNEL); if (clk_dce == NULL) { BREAK_TO_DEBUGGER(); @@ -788,7 +788,7 @@ struct display_clock *dce112_disp_clk_create( struct display_clock *dce120_disp_clk_create(struct dc_context *ctx) { - struct dce_disp_clk *clk_dce = dm_alloc(sizeof(*clk_dce)); + struct dce_disp_clk *clk_dce = kzalloc(sizeof(*clk_dce), GFP_KERNEL); struct dm_pp_clock_levels_with_voltage clk_level_info = {0}; if (clk_dce == NULL) { @@ -822,6 +822,6 @@ void dce_disp_clk_destroy(struct display_clock **disp_clk) { struct dce_disp_clk *clk_dce = TO_DCE_CLOCKS(*disp_clk); - dm_free(clk_dce); + kfree(clk_dce); *disp_clk = NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c index 313f61bf06e1..f9873cad40e0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c @@ -573,7 +573,7 @@ struct dmcu *dce_dmcu_create( const struct dce_dmcu_shift *dmcu_shift, const struct dce_dmcu_mask *dmcu_mask) { - struct dce_dmcu *dmcu_dce = dm_alloc(sizeof(*dmcu_dce)); + struct dce_dmcu *dmcu_dce = kzalloc(sizeof(*dmcu_dce), GFP_KERNEL); if (dmcu_dce == NULL) { BREAK_TO_DEBUGGER(); @@ -595,7 +595,7 @@ struct dmcu *dcn10_dmcu_create( const struct dce_dmcu_shift *dmcu_shift, const struct dce_dmcu_mask *dmcu_mask) { - struct dce_dmcu *dmcu_dce = dm_alloc(sizeof(*dmcu_dce)); + struct dce_dmcu *dmcu_dce = kzalloc(sizeof(*dmcu_dce), GFP_KERNEL); if (dmcu_dce == NULL) { BREAK_TO_DEBUGGER(); @@ -615,6 +615,6 @@ void dce_dmcu_destroy(struct dmcu **dmcu) { struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(*dmcu); - dm_free(dmcu_dce); + kfree(dmcu_dce); *dmcu = NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c index e010cf10d605..fa481d481132 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c @@ -261,6 +261,6 @@ void dce_ipp_construct( void dce_ipp_destroy(struct input_pixel_processor **ipp) { - dm_free(TO_DCE_IPP(*ipp)); + kfree(TO_DCE_IPP(*ipp)); *ipp = NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 0ce94ede80bf..2ce730de0dc3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -1108,7 +1108,7 @@ void dce110_link_encoder_hw_init( void dce110_link_encoder_destroy(struct link_encoder **enc) { - dm_free(TO_DCE110_LINK_ENC(*enc)); + kfree(TO_DCE110_LINK_ENC(*enc)); *enc = NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c index 348e4b7047f1..c0736aeabd85 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c @@ -563,7 +563,7 @@ bool dce110_opp_construct(struct dce110_opp *opp110, void dce110_opp_destroy(struct output_pixel_processor **opp) { if (*opp) - dm_free(FROM_DCE11_OPP(*opp)); + kfree(FROM_DCE11_OPP(*opp)); *opp = NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index ca6c7c2a1b4c..9a75bde32611 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -370,7 +370,7 @@ static struct timing_generator *dce100_timing_generator_create( const struct dce110_timing_generator_offsets *offsets) { struct dce110_timing_generator *tg110 = - dm_alloc(sizeof(struct dce110_timing_generator)); + kzalloc(sizeof(struct dce110_timing_generator), GFP_KERNEL); if (!tg110) return NULL; @@ -380,7 +380,7 @@ static struct timing_generator *dce100_timing_generator_create( return &tg110->base; BREAK_TO_DEBUGGER(); - dm_free(tg110); + kfree(tg110); return NULL; } @@ -389,7 +389,7 @@ static struct stream_encoder *dce100_stream_encoder_create( struct dc_context *ctx) { struct dce110_stream_encoder *enc110 = - dm_alloc(sizeof(struct dce110_stream_encoder)); + kzalloc(sizeof(struct dce110_stream_encoder), GFP_KERNEL); if (!enc110) return NULL; @@ -400,7 +400,7 @@ static struct stream_encoder *dce100_stream_encoder_create( return &enc110->base; BREAK_TO_DEBUGGER(); - dm_free(enc110); + kfree(enc110); return NULL; } @@ -422,7 +422,7 @@ static const struct dce_hwseq_mask hwseq_mask = { static struct dce_hwseq *dce100_hwseq_create( struct dc_context *ctx) { - struct dce_hwseq *hws = dm_alloc(sizeof(struct dce_hwseq)); + struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); if (hws) { hws->ctx = ctx; @@ -467,7 +467,8 @@ static struct mem_input *dce100_mem_input_create( struct dc_context *ctx, uint32_t inst) { - struct dce_mem_input *dce_mi = dm_alloc(sizeof(struct dce_mem_input)); + struct dce_mem_input *dce_mi = kzalloc(sizeof(struct dce_mem_input), + GFP_KERNEL); if (!dce_mi) { BREAK_TO_DEBUGGER(); @@ -481,7 +482,7 @@ static struct mem_input *dce100_mem_input_create( static void dce100_transform_destroy(struct transform **xfm) { - dm_free(TO_DCE_TRANSFORM(*xfm)); + kfree(TO_DCE_TRANSFORM(*xfm)); *xfm = NULL; } @@ -490,7 +491,7 @@ static struct transform *dce100_transform_create( uint32_t inst) { struct dce_transform *transform = - dm_alloc(sizeof(struct dce_transform)); + kzalloc(sizeof(struct dce_transform), GFP_KERNEL); if (!transform) return NULL; @@ -501,14 +502,14 @@ static struct transform *dce100_transform_create( } BREAK_TO_DEBUGGER(); - dm_free(transform); + kfree(transform); return NULL; } static struct input_pixel_processor *dce100_ipp_create( struct dc_context *ctx, uint32_t inst) { - struct dce_ipp *ipp = dm_alloc(sizeof(struct dce_ipp)); + struct dce_ipp *ipp = kzalloc(sizeof(struct dce_ipp), GFP_KERNEL); if (!ipp) { BREAK_TO_DEBUGGER(); @@ -532,7 +533,7 @@ struct link_encoder *dce100_link_encoder_create( const struct encoder_init_data *enc_init_data) { struct dce110_link_encoder *enc110 = - dm_alloc(sizeof(struct dce110_link_encoder)); + kzalloc(sizeof(struct dce110_link_encoder), GFP_KERNEL); if (!enc110) return NULL; @@ -549,7 +550,7 @@ struct link_encoder *dce100_link_encoder_create( } BREAK_TO_DEBUGGER(); - dm_free(enc110); + kfree(enc110); return NULL; } @@ -558,7 +559,7 @@ struct output_pixel_processor *dce100_opp_create( uint32_t inst) { struct dce110_opp *opp = - dm_alloc(sizeof(struct dce110_opp)); + kzalloc(sizeof(struct dce110_opp), GFP_KERNEL); if (!opp) return NULL; @@ -568,7 +569,7 @@ struct output_pixel_processor *dce100_opp_create( return &opp->base; BREAK_TO_DEBUGGER(); - dm_free(opp); + kfree(opp); return NULL; } @@ -580,7 +581,7 @@ struct clock_source *dce100_clock_source_create( bool dp_clk_src) { struct dce110_clk_src *clk_src = - dm_alloc(sizeof(struct dce110_clk_src)); + kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); if (!clk_src) return NULL; @@ -597,7 +598,7 @@ struct clock_source *dce100_clock_source_create( void dce100_clock_source_destroy(struct clock_source **clk_src) { - dm_free(TO_DCE110_CLK_SRC(*clk_src)); + kfree(TO_DCE110_CLK_SRC(*clk_src)); *clk_src = NULL; } @@ -616,19 +617,19 @@ static void destruct(struct dce110_resource_pool *pool) dce_ipp_destroy(&pool->base.ipps[i]); if (pool->base.mis[i] != NULL) { - dm_free(TO_DCE_MEM_INPUT(pool->base.mis[i])); + kfree(TO_DCE_MEM_INPUT(pool->base.mis[i])); pool->base.mis[i] = NULL; } if (pool->base.timing_generators[i] != NULL) { - dm_free(DCE110TG_FROM_TG(pool->base.timing_generators[i])); + kfree(DCE110TG_FROM_TG(pool->base.timing_generators[i])); pool->base.timing_generators[i] = NULL; } } for (i = 0; i < pool->base.stream_enc_count; i++) { if (pool->base.stream_enc[i] != NULL) - dm_free(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); + kfree(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); } for (i = 0; i < pool->base.clk_src_count; i++) { @@ -768,7 +769,7 @@ static void dce100_destroy_resource_pool(struct resource_pool **pool) struct dce110_resource_pool *dce110_pool = TO_DCE110_RES_POOL(*pool); destruct(dce110_pool); - dm_free(dce110_pool); + kfree(dce110_pool); *pool = NULL; } @@ -950,7 +951,7 @@ struct resource_pool *dce100_create_resource_pool( struct dc *dc) { struct dce110_resource_pool *pool = - dm_alloc(sizeof(struct dce110_resource_pool)); + kzalloc(sizeof(struct dce110_resource_pool), GFP_KERNEL); if (!pool) return NULL; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c index f82c26995609..90770cb2ffcd 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c @@ -388,7 +388,7 @@ void dce110_compressor_set_fbc_invalidation_triggers( struct compressor *dce110_compressor_create(struct dc_context *ctx) { struct dce110_compressor *cp110 = - dm_alloc(sizeof(struct dce110_compressor)); + kzalloc(sizeof(struct dce110_compressor), GFP_KERNEL); if (!cp110) return NULL; @@ -397,13 +397,13 @@ struct compressor *dce110_compressor_create(struct dc_context *ctx) return &cp110->base; BREAK_TO_DEBUGGER(); - dm_free(cp110); + kfree(cp110); return NULL; } void dce110_compressor_destroy(struct compressor **compressor) { - dm_free(TO_DCE110_COMPRESSOR(*compressor)); + kfree(TO_DCE110_COMPRESSOR(*compressor)); *compressor = NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 25eda52c32ef..787e20e15221 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -405,7 +405,7 @@ static struct timing_generator *dce110_timing_generator_create( const struct dce110_timing_generator_offsets *offsets) { struct dce110_timing_generator *tg110 = - dm_alloc(sizeof(struct dce110_timing_generator)); + kzalloc(sizeof(struct dce110_timing_generator), GFP_KERNEL); if (!tg110) return NULL; @@ -414,7 +414,7 @@ static struct timing_generator *dce110_timing_generator_create( return &tg110->base; BREAK_TO_DEBUGGER(); - dm_free(tg110); + kfree(tg110); return NULL; } @@ -423,7 +423,7 @@ static struct stream_encoder *dce110_stream_encoder_create( struct dc_context *ctx) { struct dce110_stream_encoder *enc110 = - dm_alloc(sizeof(struct dce110_stream_encoder)); + kzalloc(sizeof(struct dce110_stream_encoder), GFP_KERNEL); if (!enc110) return NULL; @@ -434,7 +434,7 @@ static struct stream_encoder *dce110_stream_encoder_create( return &enc110->base; BREAK_TO_DEBUGGER(); - dm_free(enc110); + kfree(enc110); return NULL; } @@ -460,7 +460,7 @@ static const struct dce_hwseq_mask hwseq_mask = { static struct dce_hwseq *dce110_hwseq_create( struct dc_context *ctx) { - struct dce_hwseq *hws = dm_alloc(sizeof(struct dce_hwseq)); + struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); if (hws) { hws->ctx = ctx; @@ -505,7 +505,8 @@ static struct mem_input *dce110_mem_input_create( struct dc_context *ctx, uint32_t inst) { - struct dce_mem_input *dce_mi = dm_alloc(sizeof(struct dce_mem_input)); + struct dce_mem_input *dce_mi = kzalloc(sizeof(struct dce_mem_input), + GFP_KERNEL); if (!dce_mi) { BREAK_TO_DEBUGGER(); @@ -519,7 +520,7 @@ static struct mem_input *dce110_mem_input_create( static void dce110_transform_destroy(struct transform **xfm) { - dm_free(TO_DCE_TRANSFORM(*xfm)); + kfree(TO_DCE_TRANSFORM(*xfm)); *xfm = NULL; } @@ -528,7 +529,7 @@ static struct transform *dce110_transform_create( uint32_t inst) { struct dce_transform *transform = - dm_alloc(sizeof(struct dce_transform)); + kzalloc(sizeof(struct dce_transform), GFP_KERNEL); if (!transform) return NULL; @@ -538,14 +539,14 @@ static struct transform *dce110_transform_create( return &transform->base; BREAK_TO_DEBUGGER(); - dm_free(transform); + kfree(transform); return NULL; } static struct input_pixel_processor *dce110_ipp_create( struct dc_context *ctx, uint32_t inst) { - struct dce_ipp *ipp = dm_alloc(sizeof(struct dce_ipp)); + struct dce_ipp *ipp = kzalloc(sizeof(struct dce_ipp), GFP_KERNEL); if (!ipp) { BREAK_TO_DEBUGGER(); @@ -569,7 +570,7 @@ static struct link_encoder *dce110_link_encoder_create( const struct encoder_init_data *enc_init_data) { struct dce110_link_encoder *enc110 = - dm_alloc(sizeof(struct dce110_link_encoder)); + kzalloc(sizeof(struct dce110_link_encoder), GFP_KERNEL); if (!enc110) return NULL; @@ -586,7 +587,7 @@ static struct link_encoder *dce110_link_encoder_create( } BREAK_TO_DEBUGGER(); - dm_free(enc110); + kfree(enc110); return NULL; } @@ -595,7 +596,7 @@ static struct output_pixel_processor *dce110_opp_create( uint32_t inst) { struct dce110_opp *opp = - dm_alloc(sizeof(struct dce110_opp)); + kzalloc(sizeof(struct dce110_opp), GFP_KERNEL); if (!opp) return NULL; @@ -605,7 +606,7 @@ static struct output_pixel_processor *dce110_opp_create( return &opp->base; BREAK_TO_DEBUGGER(); - dm_free(opp); + kfree(opp); return NULL; } @@ -617,7 +618,7 @@ struct clock_source *dce110_clock_source_create( bool dp_clk_src) { struct dce110_clk_src *clk_src = - dm_alloc(sizeof(struct dce110_clk_src)); + kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); if (!clk_src) return NULL; @@ -642,15 +643,15 @@ void dce110_clock_source_destroy(struct clock_source **clk_src) dce110_clk_src = TO_DCE110_CLK_SRC(*clk_src); if (dce110_clk_src->dp_ss_params) - dm_free(dce110_clk_src->dp_ss_params); + kfree(dce110_clk_src->dp_ss_params); if (dce110_clk_src->hdmi_ss_params) - dm_free(dce110_clk_src->hdmi_ss_params); + kfree(dce110_clk_src->hdmi_ss_params); if (dce110_clk_src->dvi_ss_params) - dm_free(dce110_clk_src->dvi_ss_params); + kfree(dce110_clk_src->dvi_ss_params); - dm_free(dce110_clk_src); + kfree(dce110_clk_src); *clk_src = NULL; } @@ -669,19 +670,19 @@ static void destruct(struct dce110_resource_pool *pool) dce_ipp_destroy(&pool->base.ipps[i]); if (pool->base.mis[i] != NULL) { - dm_free(TO_DCE_MEM_INPUT(pool->base.mis[i])); + kfree(TO_DCE_MEM_INPUT(pool->base.mis[i])); pool->base.mis[i] = NULL; } if (pool->base.timing_generators[i] != NULL) { - dm_free(DCE110TG_FROM_TG(pool->base.timing_generators[i])); + kfree(DCE110TG_FROM_TG(pool->base.timing_generators[i])); pool->base.timing_generators[i] = NULL; } } for (i = 0; i < pool->base.stream_enc_count; i++) { if (pool->base.stream_enc[i] != NULL) - dm_free(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); + kfree(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); } for (i = 0; i < pool->base.clk_src_count; i++) { @@ -1031,7 +1032,7 @@ static void dce110_destroy_resource_pool(struct resource_pool **pool) struct dce110_resource_pool *dce110_pool = TO_DCE110_RES_POOL(*pool); destruct(dce110_pool); - dm_free(dce110_pool); + kfree(dce110_pool); *pool = NULL; } @@ -1048,10 +1049,14 @@ static const struct resource_funcs dce110_res_pool_funcs = { static bool underlay_create(struct dc_context *ctx, struct resource_pool *pool) { - struct dce110_timing_generator *dce110_tgv = dm_alloc(sizeof (*dce110_tgv)); - struct dce_transform *dce110_xfmv = dm_alloc(sizeof (*dce110_xfmv)); - struct dce_mem_input *dce110_miv = dm_alloc(sizeof (*dce110_miv)); - struct dce110_opp *dce110_oppv = dm_alloc(sizeof (*dce110_oppv)); + struct dce110_timing_generator *dce110_tgv = kzalloc(sizeof(*dce110_tgv), + GFP_KERNEL); + struct dce_transform *dce110_xfmv = kzalloc(sizeof(*dce110_xfmv), + GFP_KERNEL); + struct dce_mem_input *dce110_miv = kzalloc(sizeof(*dce110_miv), + GFP_KERNEL); + struct dce110_opp *dce110_oppv = kzalloc(sizeof(*dce110_oppv), + GFP_KERNEL); if ((dce110_tgv == NULL) || (dce110_xfmv == NULL) || @@ -1332,7 +1337,7 @@ struct resource_pool *dce110_create_resource_pool( struct hw_asic_id asic_id) { struct dce110_resource_pool *pool = - dm_alloc(sizeof(struct dce110_resource_pool)); + kzalloc(sizeof(struct dce110_resource_pool), GFP_KERNEL); if (!pool) return NULL; diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c index 75af2125344b..e75895baa132 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c @@ -839,7 +839,7 @@ bool dce112_compressor_construct(struct dce112_compressor *compressor, struct compressor *dce112_compressor_create(struct dc_context *ctx) { struct dce112_compressor *cp110 = - dm_alloc(sizeof(struct dce112_compressor)); + kzalloc(sizeof(struct dce112_compressor), GFP_KERNEL); if (!cp110) return NULL; @@ -848,12 +848,12 @@ struct compressor *dce112_compressor_create(struct dc_context *ctx) return &cp110->base; BREAK_TO_DEBUGGER(); - dm_free(cp110); + kfree(cp110); return NULL; } void dce112_compressor_destroy(struct compressor **compressor) { - dm_free(TO_DCE112_COMPRESSOR(*compressor)); + kfree(TO_DCE112_COMPRESSOR(*compressor)); *compressor = NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index de6f71d8a89b..4e2ed3429a90 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -410,7 +410,7 @@ static struct timing_generator *dce112_timing_generator_create( const struct dce110_timing_generator_offsets *offsets) { struct dce110_timing_generator *tg110 = - dm_alloc(sizeof(struct dce110_timing_generator)); + kzalloc(sizeof(struct dce110_timing_generator), GFP_KERNEL); if (!tg110) return NULL; @@ -419,7 +419,7 @@ static struct timing_generator *dce112_timing_generator_create( return &tg110->base; BREAK_TO_DEBUGGER(); - dm_free(tg110); + kfree(tg110); return NULL; } @@ -428,7 +428,7 @@ static struct stream_encoder *dce112_stream_encoder_create( struct dc_context *ctx) { struct dce110_stream_encoder *enc110 = - dm_alloc(sizeof(struct dce110_stream_encoder)); + kzalloc(sizeof(struct dce110_stream_encoder), GFP_KERNEL); if (!enc110) return NULL; @@ -439,7 +439,7 @@ static struct stream_encoder *dce112_stream_encoder_create( return &enc110->base; BREAK_TO_DEBUGGER(); - dm_free(enc110); + kfree(enc110); return NULL; } @@ -461,7 +461,7 @@ static const struct dce_hwseq_mask hwseq_mask = { static struct dce_hwseq *dce112_hwseq_create( struct dc_context *ctx) { - struct dce_hwseq *hws = dm_alloc(sizeof(struct dce_hwseq)); + struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); if (hws) { hws->ctx = ctx; @@ -501,7 +501,8 @@ static struct mem_input *dce112_mem_input_create( struct dc_context *ctx, uint32_t inst) { - struct dce_mem_input *dce_mi = dm_alloc(sizeof(struct dce_mem_input)); + struct dce_mem_input *dce_mi = kzalloc(sizeof(struct dce_mem_input), + GFP_KERNEL); if (!dce_mi) { BREAK_TO_DEBUGGER(); @@ -514,7 +515,7 @@ static struct mem_input *dce112_mem_input_create( static void dce112_transform_destroy(struct transform **xfm) { - dm_free(TO_DCE_TRANSFORM(*xfm)); + kfree(TO_DCE_TRANSFORM(*xfm)); *xfm = NULL; } @@ -523,7 +524,7 @@ static struct transform *dce112_transform_create( uint32_t inst) { struct dce_transform *transform = - dm_alloc(sizeof(struct dce_transform)); + kzalloc(sizeof(struct dce_transform), GFP_KERNEL); if (!transform) return NULL; @@ -535,7 +536,7 @@ static struct transform *dce112_transform_create( } BREAK_TO_DEBUGGER(); - dm_free(transform); + kfree(transform); return NULL; } @@ -554,7 +555,7 @@ struct link_encoder *dce112_link_encoder_create( const struct encoder_init_data *enc_init_data) { struct dce110_link_encoder *enc110 = - dm_alloc(sizeof(struct dce110_link_encoder)); + kzalloc(sizeof(struct dce110_link_encoder), GFP_KERNEL); if (!enc110) return NULL; @@ -571,14 +572,14 @@ struct link_encoder *dce112_link_encoder_create( } BREAK_TO_DEBUGGER(); - dm_free(enc110); + kfree(enc110); return NULL; } static struct input_pixel_processor *dce112_ipp_create( struct dc_context *ctx, uint32_t inst) { - struct dce_ipp *ipp = dm_alloc(sizeof(struct dce_ipp)); + struct dce_ipp *ipp = kzalloc(sizeof(struct dce_ipp), GFP_KERNEL); if (!ipp) { BREAK_TO_DEBUGGER(); @@ -595,7 +596,7 @@ struct output_pixel_processor *dce112_opp_create( uint32_t inst) { struct dce110_opp *opp = - dm_alloc(sizeof(struct dce110_opp)); + kzalloc(sizeof(struct dce110_opp), GFP_KERNEL); if (!opp) return NULL; @@ -605,7 +606,7 @@ struct output_pixel_processor *dce112_opp_create( return &opp->base; BREAK_TO_DEBUGGER(); - dm_free(opp); + kfree(opp); return NULL; } @@ -617,7 +618,7 @@ struct clock_source *dce112_clock_source_create( bool dp_clk_src) { struct dce110_clk_src *clk_src = - dm_alloc(sizeof(struct dce110_clk_src)); + kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); if (!clk_src) return NULL; @@ -634,7 +635,7 @@ struct clock_source *dce112_clock_source_create( void dce112_clock_source_destroy(struct clock_source **clk_src) { - dm_free(TO_DCE110_CLK_SRC(*clk_src)); + kfree(TO_DCE110_CLK_SRC(*clk_src)); *clk_src = NULL; } @@ -653,19 +654,19 @@ static void destruct(struct dce110_resource_pool *pool) dce_ipp_destroy(&pool->base.ipps[i]); if (pool->base.mis[i] != NULL) { - dm_free(TO_DCE_MEM_INPUT(pool->base.mis[i])); + kfree(TO_DCE_MEM_INPUT(pool->base.mis[i])); pool->base.mis[i] = NULL; } if (pool->base.timing_generators[i] != NULL) { - dm_free(DCE110TG_FROM_TG(pool->base.timing_generators[i])); + kfree(DCE110TG_FROM_TG(pool->base.timing_generators[i])); pool->base.timing_generators[i] = NULL; } } for (i = 0; i < pool->base.stream_enc_count; i++) { if (pool->base.stream_enc[i] != NULL) - dm_free(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); + kfree(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); } for (i = 0; i < pool->base.clk_src_count; i++) { @@ -940,7 +941,7 @@ static void dce112_destroy_resource_pool(struct resource_pool **pool) struct dce110_resource_pool *dce110_pool = TO_DCE110_RES_POOL(*pool); destruct(dce110_pool); - dm_free(dce110_pool); + kfree(dce110_pool); *pool = NULL; } @@ -1298,7 +1299,7 @@ struct resource_pool *dce112_create_resource_pool( struct dc *dc) { struct dce110_resource_pool *pool = - dm_alloc(sizeof(struct dce110_resource_pool)); + kzalloc(sizeof(struct dce110_resource_pool), GFP_KERNEL); if (!pool) return NULL; diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index e5d2d98982f7..6b5d5948ddb7 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -351,7 +351,7 @@ struct output_pixel_processor *dce120_opp_create( uint32_t inst) { struct dce110_opp *opp = - dm_alloc(sizeof(struct dce110_opp)); + kzalloc(sizeof(struct dce110_opp), GFP_KERNEL); if (!opp) return NULL; @@ -361,7 +361,7 @@ struct output_pixel_processor *dce120_opp_create( return &opp->base; BREAK_TO_DEBUGGER(); - dm_free(opp); + kfree(opp); return NULL; } @@ -388,7 +388,7 @@ struct clock_source *dce120_clock_source_create( bool dp_clk_src) { struct dce110_clk_src *clk_src = - dm_alloc(sizeof(*clk_src)); + kzalloc(sizeof(*clk_src), GFP_KERNEL); if (!clk_src) return NULL; @@ -405,7 +405,7 @@ struct clock_source *dce120_clock_source_create( void dce120_clock_source_destroy(struct clock_source **clk_src) { - dm_free(TO_DCE110_CLK_SRC(*clk_src)); + kfree(TO_DCE110_CLK_SRC(*clk_src)); *clk_src = NULL; } @@ -428,7 +428,7 @@ static struct timing_generator *dce120_timing_generator_create( const struct dce110_timing_generator_offsets *offsets) { struct dce110_timing_generator *tg110 = - dm_alloc(sizeof(struct dce110_timing_generator)); + kzalloc(sizeof(struct dce110_timing_generator), GFP_KERNEL); if (!tg110) return NULL; @@ -437,13 +437,13 @@ static struct timing_generator *dce120_timing_generator_create( return &tg110->base; BREAK_TO_DEBUGGER(); - dm_free(tg110); + kfree(tg110); return NULL; } static void dce120_transform_destroy(struct transform **xfm) { - dm_free(TO_DCE_TRANSFORM(*xfm)); + kfree(TO_DCE_TRANSFORM(*xfm)); *xfm = NULL; } @@ -462,7 +462,7 @@ static void destruct(struct dce110_resource_pool *pool) dce_ipp_destroy(&pool->base.ipps[i]); if (pool->base.mis[i] != NULL) { - dm_free(TO_DCE_MEM_INPUT(pool->base.mis[i])); + kfree(TO_DCE_MEM_INPUT(pool->base.mis[i])); pool->base.mis[i] = NULL; } @@ -471,7 +471,7 @@ static void destruct(struct dce110_resource_pool *pool) } if (pool->base.timing_generators[i] != NULL) { - dm_free(DCE110TG_FROM_TG(pool->base.timing_generators[i])); + kfree(DCE110TG_FROM_TG(pool->base.timing_generators[i])); pool->base.timing_generators[i] = NULL; } } @@ -483,7 +483,7 @@ static void destruct(struct dce110_resource_pool *pool) for (i = 0; i < pool->base.stream_enc_count; i++) { if (pool->base.stream_enc[i] != NULL) - dm_free(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); + kfree(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); } for (i = 0; i < pool->base.clk_src_count; i++) { @@ -539,7 +539,7 @@ static struct link_encoder *dce120_link_encoder_create( const struct encoder_init_data *enc_init_data) { struct dce110_link_encoder *enc110 = - dm_alloc(sizeof(struct dce110_link_encoder)); + kzalloc(sizeof(struct dce110_link_encoder), GFP_KERNEL); if (!enc110) return NULL; @@ -556,14 +556,14 @@ static struct link_encoder *dce120_link_encoder_create( } BREAK_TO_DEBUGGER(); - dm_free(enc110); + kfree(enc110); return NULL; } static struct input_pixel_processor *dce120_ipp_create( struct dc_context *ctx, uint32_t inst) { - struct dce_ipp *ipp = dm_alloc(sizeof(struct dce_ipp)); + struct dce_ipp *ipp = kzalloc(sizeof(struct dce_ipp), GFP_KERNEL); if (!ipp) { BREAK_TO_DEBUGGER(); @@ -580,7 +580,7 @@ static struct stream_encoder *dce120_stream_encoder_create( struct dc_context *ctx) { struct dce110_stream_encoder *enc110 = - dm_alloc(sizeof(struct dce110_stream_encoder)); + kzalloc(sizeof(struct dce110_stream_encoder), GFP_KERNEL); if (!enc110) return NULL; @@ -591,7 +591,7 @@ static struct stream_encoder *dce120_stream_encoder_create( return &enc110->base; BREAK_TO_DEBUGGER(); - dm_free(enc110); + kfree(enc110); return NULL; } @@ -614,7 +614,7 @@ static const struct dce_hwseq_mask hwseq_mask = { static struct dce_hwseq *dce120_hwseq_create( struct dc_context *ctx) { - struct dce_hwseq *hws = dm_alloc(sizeof(struct dce_hwseq)); + struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); if (hws) { hws->ctx = ctx; @@ -654,7 +654,8 @@ static struct mem_input *dce120_mem_input_create( struct dc_context *ctx, uint32_t inst) { - struct dce_mem_input *dce_mi = dm_alloc(sizeof(struct dce_mem_input)); + struct dce_mem_input *dce_mi = kzalloc(sizeof(struct dce_mem_input), + GFP_KERNEL); if (!dce_mi) { BREAK_TO_DEBUGGER(); @@ -670,7 +671,7 @@ static struct transform *dce120_transform_create( uint32_t inst) { struct dce_transform *transform = - dm_alloc(sizeof(struct dce_transform)); + kzalloc(sizeof(struct dce_transform), GFP_KERNEL); if (!transform) return NULL; @@ -682,7 +683,7 @@ static struct transform *dce120_transform_create( } BREAK_TO_DEBUGGER(); - dm_free(transform); + kfree(transform); return NULL; } @@ -691,7 +692,7 @@ static void dce120_destroy_resource_pool(struct resource_pool **pool) struct dce110_resource_pool *dce110_pool = TO_DCE110_RES_POOL(*pool); destruct(dce110_pool); - dm_free(dce110_pool); + kfree(dce110_pool); *pool = NULL; } @@ -1006,7 +1007,7 @@ struct resource_pool *dce120_create_resource_pool( struct dc *dc) { struct dce110_resource_pool *pool = - dm_alloc(sizeof(struct dce110_resource_pool)); + kzalloc(sizeof(struct dce110_resource_pool), GFP_KERNEL); if (!pool) return NULL; diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.c index 77626d7624c6..cc1c0d390945 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.c @@ -819,7 +819,7 @@ bool dce80_compressor_construct(struct dce80_compressor *compressor, struct compressor *dce80_compressor_create(struct dc_context *ctx) { struct dce80_compressor *cp80 = - dm_alloc(sizeof(struct dce80_compressor)); + kzalloc(sizeof(struct dce80_compressor), GFP_KERNEL); if (!cp80) return NULL; @@ -828,12 +828,12 @@ struct compressor *dce80_compressor_create(struct dc_context *ctx) return &cp80->base; BREAK_TO_DEBUGGER(); - dm_free(cp80); + kfree(cp80); return NULL; } void dce80_compressor_destroy(struct compressor **compressor) { - dm_free(TO_DCE80_COMPRESSOR(*compressor)); + kfree(TO_DCE80_COMPRESSOR(*compressor)); *compressor = NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 5453f02ea8ca..170509a4a221 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -399,7 +399,7 @@ static struct timing_generator *dce80_timing_generator_create( const struct dce110_timing_generator_offsets *offsets) { struct dce110_timing_generator *tg110 = - dm_alloc(sizeof(struct dce110_timing_generator)); + kzalloc(sizeof(struct dce110_timing_generator), GFP_KERNEL); if (!tg110) return NULL; @@ -408,7 +408,7 @@ static struct timing_generator *dce80_timing_generator_create( return &tg110->base; BREAK_TO_DEBUGGER(); - dm_free(tg110); + kfree(tg110); return NULL; } @@ -417,7 +417,7 @@ static struct output_pixel_processor *dce80_opp_create( uint32_t inst) { struct dce110_opp *opp = - dm_alloc(sizeof(struct dce110_opp)); + kzalloc(sizeof(struct dce110_opp), GFP_KERNEL); if (!opp) return NULL; @@ -427,7 +427,7 @@ static struct output_pixel_processor *dce80_opp_create( return &opp->base; BREAK_TO_DEBUGGER(); - dm_free(opp); + kfree(opp); return NULL; } @@ -436,7 +436,7 @@ static struct stream_encoder *dce80_stream_encoder_create( struct dc_context *ctx) { struct dce110_stream_encoder *enc110 = - dm_alloc(sizeof(struct dce110_stream_encoder)); + kzalloc(sizeof(struct dce110_stream_encoder), GFP_KERNEL); if (!enc110) return NULL; @@ -447,7 +447,7 @@ static struct stream_encoder *dce80_stream_encoder_create( return &enc110->base; BREAK_TO_DEBUGGER(); - dm_free(enc110); + kfree(enc110); return NULL; } @@ -469,7 +469,7 @@ static const struct dce_hwseq_mask hwseq_mask = { static struct dce_hwseq *dce80_hwseq_create( struct dc_context *ctx) { - struct dce_hwseq *hws = dm_alloc(sizeof(struct dce_hwseq)); + struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); if (hws) { hws->ctx = ctx; @@ -514,7 +514,8 @@ static struct mem_input *dce80_mem_input_create( struct dc_context *ctx, uint32_t inst) { - struct dce_mem_input *dce_mi = dm_alloc(sizeof(struct dce_mem_input)); + struct dce_mem_input *dce_mi = kzalloc(sizeof(struct dce_mem_input), + GFP_KERNEL); if (!dce_mi) { BREAK_TO_DEBUGGER(); @@ -528,7 +529,7 @@ static struct mem_input *dce80_mem_input_create( static void dce80_transform_destroy(struct transform **xfm) { - dm_free(TO_DCE_TRANSFORM(*xfm)); + kfree(TO_DCE_TRANSFORM(*xfm)); *xfm = NULL; } @@ -537,7 +538,7 @@ static struct transform *dce80_transform_create( uint32_t inst) { struct dce_transform *transform = - dm_alloc(sizeof(struct dce_transform)); + kzalloc(sizeof(struct dce_transform), GFP_KERNEL); if (!transform) return NULL; @@ -549,7 +550,7 @@ static struct transform *dce80_transform_create( } BREAK_TO_DEBUGGER(); - dm_free(transform); + kfree(transform); return NULL; } @@ -565,7 +566,7 @@ struct link_encoder *dce80_link_encoder_create( const struct encoder_init_data *enc_init_data) { struct dce110_link_encoder *enc110 = - dm_alloc(sizeof(struct dce110_link_encoder)); + kzalloc(sizeof(struct dce110_link_encoder), GFP_KERNEL); if (!enc110) return NULL; @@ -582,7 +583,7 @@ struct link_encoder *dce80_link_encoder_create( } BREAK_TO_DEBUGGER(); - dm_free(enc110); + kfree(enc110); return NULL; } @@ -594,7 +595,7 @@ struct clock_source *dce80_clock_source_create( bool dp_clk_src) { struct dce110_clk_src *clk_src = - dm_alloc(sizeof(struct dce110_clk_src)); + kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); if (!clk_src) return NULL; @@ -611,14 +612,14 @@ struct clock_source *dce80_clock_source_create( void dce80_clock_source_destroy(struct clock_source **clk_src) { - dm_free(TO_DCE110_CLK_SRC(*clk_src)); + kfree(TO_DCE110_CLK_SRC(*clk_src)); *clk_src = NULL; } static struct input_pixel_processor *dce80_ipp_create( struct dc_context *ctx, uint32_t inst) { - struct dce_ipp *ipp = dm_alloc(sizeof(struct dce_ipp)); + struct dce_ipp *ipp = kzalloc(sizeof(struct dce_ipp), GFP_KERNEL); if (!ipp) { BREAK_TO_DEBUGGER(); @@ -645,19 +646,19 @@ static void destruct(struct dce110_resource_pool *pool) dce_ipp_destroy(&pool->base.ipps[i]); if (pool->base.mis[i] != NULL) { - dm_free(TO_DCE_MEM_INPUT(pool->base.mis[i])); + kfree(TO_DCE_MEM_INPUT(pool->base.mis[i])); pool->base.mis[i] = NULL; } if (pool->base.timing_generators[i] != NULL) { - dm_free(DCE110TG_FROM_TG(pool->base.timing_generators[i])); + kfree(DCE110TG_FROM_TG(pool->base.timing_generators[i])); pool->base.timing_generators[i] = NULL; } } for (i = 0; i < pool->base.stream_enc_count; i++) { if (pool->base.stream_enc[i] != NULL) - dm_free(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); + kfree(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); } for (i = 0; i < pool->base.clk_src_count; i++) { @@ -781,7 +782,7 @@ static void dce80_destroy_resource_pool(struct resource_pool **pool) struct dce110_resource_pool *dce110_pool = TO_DCE110_RES_POOL(*pool); destruct(dce110_pool); - dm_free(dce110_pool); + kfree(dce110_pool); *pool = NULL; } @@ -948,7 +949,7 @@ struct resource_pool *dce80_create_resource_pool( struct dc *dc) { struct dce110_resource_pool *pool = - dm_alloc(sizeof(struct dce110_resource_pool)); + kzalloc(sizeof(struct dce110_resource_pool), GFP_KERNEL); if (!pool) return NULL; @@ -1113,7 +1114,7 @@ struct resource_pool *dce81_create_resource_pool( struct dc *dc) { struct dce110_resource_pool *pool = - dm_alloc(sizeof(struct dce110_resource_pool)); + kzalloc(sizeof(struct dce110_resource_pool), GFP_KERNEL); if (!pool) return NULL; @@ -1274,7 +1275,7 @@ struct resource_pool *dce83_create_resource_pool( struct dc *dc) { struct dce110_resource_pool *pool = - dm_alloc(sizeof(struct dce110_resource_pool)); + kzalloc(sizeof(struct dce110_resource_pool), GFP_KERNEL); if (!pool) return NULL; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c index 5e0e2464eab3..67bd6a738fe9 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c @@ -225,7 +225,7 @@ static void ippn10_cursor_set_position( static void dcn10_ipp_destroy(struct input_pixel_processor **ipp) { - dm_free(TO_DCN10_IPP(*ipp)); + kfree(TO_DCN10_IPP(*ipp)); *ipp = NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c index 8048782ac599..a136f70b7a3c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c @@ -314,7 +314,7 @@ static void oppn10_set_stereo_polarity( static void dcn10_opp_destroy(struct output_pixel_processor **opp) { - dm_free(TO_DCN10_OPP(*opp)); + kfree(TO_DCN10_OPP(*opp)); *opp = NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 298eb44ad9bf..71adda0e5b59 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -468,7 +468,7 @@ static const struct dc_debug debug_defaults_diags = { static void dcn10_dpp_destroy(struct transform **xfm) { - dm_free(TO_DCN10_DPP(*xfm)); + kfree(TO_DCN10_DPP(*xfm)); *xfm = NULL; } @@ -477,7 +477,7 @@ static struct transform *dcn10_dpp_create( uint32_t inst) { struct dcn10_dpp *dpp = - dm_alloc(sizeof(struct dcn10_dpp)); + kzalloc(sizeof(struct dcn10_dpp), GFP_KERNEL); if (!dpp) return NULL; @@ -487,7 +487,7 @@ static struct transform *dcn10_dpp_create( return &dpp->base; BREAK_TO_DEBUGGER(); - dm_free(dpp); + kfree(dpp); return NULL; } @@ -495,7 +495,7 @@ static struct input_pixel_processor *dcn10_ipp_create( struct dc_context *ctx, uint32_t inst) { struct dcn10_ipp *ipp = - dm_alloc(sizeof(struct dcn10_ipp)); + kzalloc(sizeof(struct dcn10_ipp), GFP_KERNEL); if (!ipp) { BREAK_TO_DEBUGGER(); @@ -512,7 +512,7 @@ static struct output_pixel_processor *dcn10_opp_create( struct dc_context *ctx, uint32_t inst) { struct dcn10_opp *opp = - dm_alloc(sizeof(struct dcn10_opp)); + kzalloc(sizeof(struct dcn10_opp), GFP_KERNEL); if (!opp) { BREAK_TO_DEBUGGER(); @@ -526,7 +526,8 @@ static struct output_pixel_processor *dcn10_opp_create( static struct mpc *dcn10_mpc_create(struct dc_context *ctx) { - struct dcn10_mpc *mpc10 = dm_alloc(sizeof(struct dcn10_mpc)); + struct dcn10_mpc *mpc10 = kzalloc(sizeof(struct dcn10_mpc), + GFP_KERNEL); if (!mpc10) return NULL; @@ -545,7 +546,7 @@ static struct timing_generator *dcn10_timing_generator_create( uint32_t instance) { struct dcn10_timing_generator *tgn10 = - dm_alloc(sizeof(struct dcn10_timing_generator)); + kzalloc(sizeof(struct dcn10_timing_generator), GFP_KERNEL); if (!tgn10) return NULL; @@ -577,7 +578,7 @@ struct link_encoder *dcn10_link_encoder_create( const struct encoder_init_data *enc_init_data) { struct dce110_link_encoder *enc110 = - dm_alloc(sizeof(struct dce110_link_encoder)); + kzalloc(sizeof(struct dce110_link_encoder), GFP_KERNEL); if (!enc110) return NULL; @@ -594,7 +595,7 @@ struct link_encoder *dcn10_link_encoder_create( } BREAK_TO_DEBUGGER(); - dm_free(enc110); + kfree(enc110); return NULL; } @@ -606,7 +607,7 @@ struct clock_source *dcn10_clock_source_create( bool dp_clk_src) { struct dce110_clk_src *clk_src = - dm_alloc(sizeof(struct dce110_clk_src)); + kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); if (!clk_src) return NULL; @@ -641,7 +642,7 @@ static struct stream_encoder *dcn10_stream_encoder_create( struct dc_context *ctx) { struct dce110_stream_encoder *enc110 = - dm_alloc(sizeof(struct dce110_stream_encoder)); + kzalloc(sizeof(struct dce110_stream_encoder), GFP_KERNEL); if (!enc110) return NULL; @@ -652,7 +653,7 @@ static struct stream_encoder *dcn10_stream_encoder_create( return &enc110->base; BREAK_TO_DEBUGGER(); - dm_free(enc110); + kfree(enc110); return NULL; } @@ -671,7 +672,7 @@ static const struct dce_hwseq_mask hwseq_mask = { static struct dce_hwseq *dcn10_hwseq_create( struct dc_context *ctx) { - struct dce_hwseq *hws = dm_alloc(sizeof(struct dce_hwseq)); + struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); if (hws) { hws->ctx = ctx; @@ -698,13 +699,13 @@ static const struct resource_create_funcs res_create_maximus_funcs = { void dcn10_clock_source_destroy(struct clock_source **clk_src) { - dm_free(TO_DCE110_CLK_SRC(*clk_src)); + kfree(TO_DCE110_CLK_SRC(*clk_src)); *clk_src = NULL; } static struct pp_smu_funcs_rv *dcn10_pp_smu_create(struct dc_context *ctx) { - struct pp_smu_funcs_rv *pp_smu = dm_alloc(sizeof(*pp_smu)); + struct pp_smu_funcs_rv *pp_smu = kzalloc(sizeof(*pp_smu), GFP_KERNEL); if (!pp_smu) return pp_smu; @@ -722,13 +723,13 @@ static void destruct(struct dcn10_resource_pool *pool) /* TODO: free dcn version of stream encoder once implemented * rather than using virtual stream encoder */ - dm_free(pool->base.stream_enc[i]); + kfree(pool->base.stream_enc[i]); pool->base.stream_enc[i] = NULL; } } if (pool->base.mpc != NULL) { - dm_free(TO_DCN10_MPC(pool->base.mpc)); + kfree(TO_DCN10_MPC(pool->base.mpc)); pool->base.mpc = NULL; } for (i = 0; i < pool->base.pipe_count; i++) { @@ -742,7 +743,7 @@ static void destruct(struct dcn10_resource_pool *pool) pool->base.ipps[i]->funcs->ipp_destroy(&pool->base.ipps[i]); if (pool->base.mis[i] != NULL) { - dm_free(TO_DCN10_MEM_INPUT(pool->base.mis[i])); + kfree(TO_DCN10_MEM_INPUT(pool->base.mis[i])); pool->base.mis[i] = NULL; } @@ -751,14 +752,14 @@ static void destruct(struct dcn10_resource_pool *pool) } if (pool->base.timing_generators[i] != NULL) { - dm_free(DCN10TG_FROM_TG(pool->base.timing_generators[i])); + kfree(DCN10TG_FROM_TG(pool->base.timing_generators[i])); pool->base.timing_generators[i] = NULL; } } for (i = 0; i < pool->base.stream_enc_count; i++) { if (pool->base.stream_enc[i] != NULL) - dm_free(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); + kfree(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); } for (i = 0; i < pool->base.audio_count; i++) { @@ -767,7 +768,7 @@ static void destruct(struct dcn10_resource_pool *pool) } for (i = 0; i < pool->base.res_cap->num_dwb; i++) { - dm_free(pool->base.dwbc[i]); + kfree(pool->base.dwbc[i]); pool->base.dwbc[i] = NULL; } @@ -792,7 +793,7 @@ static void destruct(struct dcn10_resource_pool *pool) if (pool->base.display_clock != NULL) dce_disp_clk_destroy(&pool->base.display_clock); - dm_free(pool->base.pp_smu); + kfree(pool->base.pp_smu); } static struct mem_input *dcn10_mem_input_create( @@ -800,7 +801,7 @@ static struct mem_input *dcn10_mem_input_create( uint32_t inst) { struct dcn10_mem_input *mem_inputn10 = - dm_alloc(sizeof(struct dcn10_mem_input)); + kzalloc(sizeof(struct dcn10_mem_input), GFP_KERNEL); if (!mem_inputn10) return NULL; @@ -810,7 +811,7 @@ static struct mem_input *dcn10_mem_input_create( return &mem_inputn10->base; BREAK_TO_DEBUGGER(); - dm_free(mem_inputn10); + kfree(mem_inputn10); return NULL; } @@ -1207,7 +1208,7 @@ static void dcn10_destroy_resource_pool(struct resource_pool **pool) struct dcn10_resource_pool *dcn10_pool = TO_DCN10_RES_POOL(*pool); destruct(dcn10_pool); - dm_free(dcn10_pool); + kfree(dcn10_pool); *pool = NULL; } @@ -1239,7 +1240,8 @@ static bool dcn10_dwbc_create(struct dc_context *ctx, struct resource_pool *pool uint32_t dwb_count = pool->res_cap->num_dwb; for (i = 0; i < dwb_count; i++) { - struct dcn10_dwbc *dwbc10 = dm_alloc(sizeof(struct dcn10_dwbc)); + struct dcn10_dwbc *dwbc10 = kzalloc(sizeof(struct dcn10_dwbc), + GFP_KERNEL); if (!dwbc10) { dm_error("DC: failed to create dwbc10!\n"); @@ -1517,7 +1519,7 @@ struct resource_pool *dcn10_create_resource_pool( struct dc *dc) { struct dcn10_resource_pool *pool = - dm_alloc(sizeof(struct dcn10_resource_pool)); + kzalloc(sizeof(struct dcn10_resource_pool), GFP_KERNEL); if (!pool) return NULL; diff --git a/drivers/gpu/drm/amd/display/dc/gpio/gpio_base.c b/drivers/gpu/drm/amd/display/dc/gpio/gpio_base.c index d42eb3de2ea4..1d1efd72b291 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/gpio_base.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/gpio_base.c @@ -239,7 +239,7 @@ struct gpio *dal_gpio_create( uint32_t en, enum gpio_pin_output_state output_state) { - struct gpio *gpio = dm_alloc(sizeof(struct gpio)); + struct gpio *gpio = kzalloc(sizeof(struct gpio), GFP_KERNEL); if (!gpio) { ASSERT_CRITICAL(false); @@ -266,7 +266,7 @@ void dal_gpio_destroy( dal_gpio_close(*gpio); - dm_free(*gpio); + kfree(*gpio); *gpio = NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c b/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c index eeb1cd0f75a6..d4e5ef64e489 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c @@ -59,7 +59,7 @@ struct gpio_service *dal_gpio_service_create( uint32_t index_of_id; - service = dm_alloc(sizeof(struct gpio_service)); + service = kzalloc(sizeof(struct gpio_service), GFP_KERNEL); if (!service) { BREAK_TO_DEBUGGER(); @@ -98,7 +98,8 @@ struct gpio_service *dal_gpio_service_create( if (number_of_bits) { uint32_t index_of_uint = 0; - slot = dm_alloc(number_of_uints * sizeof(uint32_t)); + slot = kzalloc(number_of_uints * sizeof(uint32_t), + GFP_KERNEL); if (!slot) { BREAK_TO_DEBUGGER(); @@ -130,11 +131,11 @@ failure_2: slot = service->busyness[index_of_id]; if (slot) - dm_free(slot); + kfree(slot); }; failure_1: - dm_free(service); + kfree(service); return NULL; } @@ -171,13 +172,13 @@ void dal_gpio_service_destroy( uint32_t *slot = (*ptr)->busyness[index_of_id]; if (slot) - dm_free(slot); + kfree(slot); ++index_of_id; } while (index_of_id < GPIO_ID_COUNT); } - dm_free(*ptr); + kfree(*ptr); *ptr = NULL; } @@ -399,7 +400,7 @@ void dal_gpio_destroy_irq( dal_gpio_close(*irq); dal_gpio_destroy(irq); - dm_free(*irq); + kfree(*irq); *irq = NULL; } @@ -417,7 +418,7 @@ struct ddc *dal_gpio_create_ddc( if (!service->translate.funcs->offset_to_id(offset, mask, &id, &en)) return NULL; - ddc = dm_alloc(sizeof(struct ddc)); + ddc = kzalloc(sizeof(struct ddc), GFP_KERNEL); if (!ddc) { BREAK_TO_DEBUGGER(); @@ -450,7 +451,7 @@ failure_2: dal_gpio_destroy(&ddc->pin_data); failure_1: - dm_free(ddc); + kfree(ddc); return NULL; } @@ -466,7 +467,7 @@ void dal_gpio_destroy_ddc( dal_ddc_close(*ddc); dal_gpio_destroy(&(*ddc)->pin_data); dal_gpio_destroy(&(*ddc)->pin_clock); - dm_free(*ddc); + kfree(*ddc); *ddc = NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c index 47e0f8f24a86..7b6efa4f2efd 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c @@ -55,7 +55,7 @@ static void destroy( destruct(pin); - dm_free(pin); + kfree(pin); *ptr = NULL; } @@ -225,7 +225,7 @@ struct hw_gpio_pin *dal_hw_ddc_create( enum gpio_id id, uint32_t en) { - struct hw_ddc *pin = dm_alloc(sizeof(struct hw_ddc)); + struct hw_ddc *pin = kzalloc(sizeof(struct hw_ddc), GFP_KERNEL); if (!pin) { ASSERT_CRITICAL(false); @@ -237,7 +237,7 @@ struct hw_gpio_pin *dal_hw_ddc_create( ASSERT_CRITICAL(false); - dm_free(pin); + kfree(pin); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c index f7d049c0e62a..87b580fa4bc9 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c @@ -101,7 +101,7 @@ void dal_hw_factory_destroy( return; } - dm_free(*factory); + kfree(*factory); *factory = NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.c index 9634e8841d90..0c255c02045b 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.c @@ -72,7 +72,7 @@ static void destroy( destruct(hpd); - dm_free(hpd); + kfree(hpd); *ptr = NULL; } @@ -157,7 +157,7 @@ struct hw_gpio_pin *dal_hw_hpd_create( enum gpio_id id, uint32_t en) { - struct hw_hpd *hpd = dm_alloc(sizeof(struct hw_hpd)); + struct hw_hpd *hpd = kzalloc(sizeof(struct hw_hpd), GFP_KERNEL); if (!hpd) { ASSERT_CRITICAL(false); @@ -169,7 +169,7 @@ struct hw_gpio_pin *dal_hw_hpd_create( ASSERT_CRITICAL(false); - dm_free(hpd); + kfree(hpd); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce100/i2caux_dce100.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce100/i2caux_dce100.c index 0712cafb4c42..c45a2ee8c336 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce100/i2caux_dce100.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce100/i2caux_dce100.c @@ -88,7 +88,7 @@ struct i2caux *dal_i2caux_dce100_create( struct dc_context *ctx) { struct i2caux_dce110 *i2caux_dce110 = - dm_alloc(sizeof(struct i2caux_dce110)); + kzalloc(sizeof(struct i2caux_dce110), GFP_KERNEL); if (!i2caux_dce110) { ASSERT_CRITICAL(false); @@ -106,7 +106,7 @@ struct i2caux *dal_i2caux_dce100_create( ASSERT_CRITICAL(false); - dm_free(i2caux_dce110); + kfree(i2caux_dce110); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c index d3eaf8977a60..4b673b48bf42 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c @@ -87,7 +87,7 @@ static void destroy( destruct(engine); - dm_free(engine); + kfree(engine); *aux_engine = NULL; } @@ -464,7 +464,7 @@ struct aux_engine *dal_aux_engine_dce110_create( return NULL; } - engine = dm_alloc(sizeof(*engine)); + engine = kzalloc(sizeof(*engine), GFP_KERNEL); if (!engine) { ASSERT_CRITICAL(false); @@ -476,7 +476,7 @@ struct aux_engine *dal_aux_engine_dce110_create( ASSERT_CRITICAL(false); - dm_free(engine); + kfree(engine); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.c index 80d06ad78e07..aab77a81008a 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.c @@ -469,7 +469,7 @@ static void destroy( dal_i2c_hw_engine_destruct(&engine_dce110->base); - dm_free(engine_dce110); + kfree(engine_dce110); *i2c_engine = NULL; } @@ -559,7 +559,8 @@ struct i2c_engine *dal_i2c_hw_engine_dce110_create( return NULL; } - engine_dce10 = dm_alloc(sizeof(struct i2c_hw_engine_dce110)); + engine_dce10 = kzalloc(sizeof(struct i2c_hw_engine_dce110), + GFP_KERNEL); if (!engine_dce10) { ASSERT_CRITICAL(false); @@ -571,7 +572,7 @@ struct i2c_engine *dal_i2c_hw_engine_dce110_create( ASSERT_CRITICAL(false); - dm_free(engine_dce10); + kfree(engine_dce10); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_sw_engine_dce110.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_sw_engine_dce110.c index 996813d9165f..bf2c4b240b78 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_sw_engine_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_sw_engine_dce110.c @@ -88,7 +88,7 @@ static void destroy( destruct(sw_engine); - dm_free(sw_engine); + kfree(sw_engine); *engine = NULL; } @@ -153,7 +153,8 @@ struct i2c_engine *dal_i2c_sw_engine_dce110_create( return NULL; } - engine_dce110 = dm_alloc(sizeof(struct i2c_sw_engine_dce110)); + engine_dce110 = kzalloc(sizeof(struct i2c_sw_engine_dce110), + GFP_KERNEL); if (!engine_dce110) { ASSERT_CRITICAL(false); @@ -165,7 +166,7 @@ struct i2c_engine *dal_i2c_sw_engine_dce110_create( ASSERT_CRITICAL(false); - dm_free(engine_dce110); + kfree(engine_dce110); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.c index 1c00ed0010d9..ae9adb389319 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.c @@ -68,7 +68,7 @@ static void destroy( destruct(i2caux_dce110); - dm_free(i2caux_dce110); + kfree(i2caux_dce110); *i2c_engine = NULL; } @@ -299,7 +299,7 @@ struct i2caux *dal_i2caux_dce110_create( struct dc_context *ctx) { struct i2caux_dce110 *i2caux_dce110 = - dm_alloc(sizeof(struct i2caux_dce110)); + kzalloc(sizeof(struct i2caux_dce110), GFP_KERNEL); if (!i2caux_dce110) { ASSERT_CRITICAL(false); @@ -317,7 +317,7 @@ struct i2caux *dal_i2caux_dce110_create( ASSERT_CRITICAL(false); - dm_free(i2caux_dce110); + kfree(i2caux_dce110); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.c index d74f3f15d600..715ba4390957 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.c @@ -122,7 +122,7 @@ struct i2caux *dal_i2caux_dce112_create( struct dc_context *ctx) { struct i2caux_dce110 *i2caux_dce110 = - dm_alloc(sizeof(struct i2caux_dce110)); + kzalloc(sizeof(struct i2caux_dce110), GFP_KERNEL); if (!i2caux_dce110) { ASSERT_CRITICAL(false); @@ -134,7 +134,7 @@ struct i2caux *dal_i2caux_dce112_create( ASSERT_CRITICAL(false); - dm_free(i2caux_dce110); + kfree(i2caux_dce110); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce120/i2caux_dce120.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce120/i2caux_dce120.c index 91198295f1a4..d52827ae3f1a 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce120/i2caux_dce120.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce120/i2caux_dce120.c @@ -101,7 +101,7 @@ struct i2caux *dal_i2caux_dce120_create( struct dc_context *ctx) { struct i2caux_dce110 *i2caux_dce110 = - dm_alloc(sizeof(struct i2caux_dce110)); + kzalloc(sizeof(struct i2caux_dce110), GFP_KERNEL); if (!i2caux_dce110) { ASSERT_CRITICAL(false); @@ -119,7 +119,7 @@ struct i2caux *dal_i2caux_dce120_create( ASSERT_CRITICAL(false); - dm_free(i2caux_dce110); + kfree(i2caux_dce110); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.c index 423c38ac880c..d41e37c94214 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.c @@ -190,7 +190,7 @@ static void destroy( destruct(engine); - dm_free(engine); + kfree(engine); *i2c_engine = NULL; } @@ -867,7 +867,7 @@ struct i2c_engine *dal_i2c_hw_engine_dce80_create( return NULL; } - engine = dm_alloc(sizeof(struct i2c_hw_engine_dce80)); + engine = kzalloc(sizeof(struct i2c_hw_engine_dce80), GFP_KERNEL); if (!engine) { BREAK_TO_DEBUGGER(); @@ -879,7 +879,7 @@ struct i2c_engine *dal_i2c_hw_engine_dce80_create( BREAK_TO_DEBUGGER(); - dm_free(engine); + kfree(engine); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_sw_engine_dce80.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_sw_engine_dce80.c index 804a3266c578..6be77bc931c6 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_sw_engine_dce80.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_sw_engine_dce80.c @@ -103,7 +103,7 @@ static void destroy( destruct(sw_engine); - dm_free(sw_engine); + kfree(sw_engine); *engine = NULL; } @@ -165,7 +165,7 @@ struct i2c_engine *dal_i2c_sw_engine_dce80_create( return NULL; } - engine = dm_alloc(sizeof(struct i2c_sw_engine_dce80)); + engine = kzalloc(sizeof(struct i2c_sw_engine_dce80), GFP_KERNEL); if (!engine) { BREAK_TO_DEBUGGER(); @@ -177,7 +177,7 @@ struct i2c_engine *dal_i2c_sw_engine_dce80_create( BREAK_TO_DEBUGGER(); - dm_free(engine); + kfree(engine); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2caux_dce80.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2caux_dce80.c index 5e71450c44e0..d3c157e5eccd 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2caux_dce80.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2caux_dce80.c @@ -101,7 +101,7 @@ static void destroy( destruct(i2caux_dce80); - dm_free(i2caux_dce80); + kfree(i2caux_dce80); *i2c_engine = NULL; } @@ -277,7 +277,7 @@ struct i2caux *dal_i2caux_dce80_create( struct dc_context *ctx) { struct i2caux_dce80 *i2caux_dce80 = - dm_alloc(sizeof(struct i2caux_dce80)); + kzalloc(sizeof(struct i2caux_dce80), GFP_KERNEL); if (!i2caux_dce80) { BREAK_TO_DEBUGGER(); @@ -289,7 +289,7 @@ struct i2caux *dal_i2caux_dce80_create( BREAK_TO_DEBUGGER(); - dm_free(i2caux_dce80); + kfree(i2caux_dce80); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.c b/drivers/gpu/drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.c index 9f17d2e4376b..f8659f1c5f9d 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.c @@ -101,7 +101,7 @@ struct i2caux *dal_i2caux_dcn10_create( struct dc_context *ctx) { struct i2caux_dce110 *i2caux_dce110 = - dm_alloc(sizeof(struct i2caux_dce110)); + kzalloc(sizeof(struct i2caux_dce110), GFP_KERNEL); if (!i2caux_dce110) { ASSERT_CRITICAL(false); @@ -119,7 +119,7 @@ struct i2caux *dal_i2caux_dcn10_create( ASSERT_CRITICAL(false); - dm_free(i2caux_dce110); + kfree(i2caux_dce110); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.c b/drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.c index 029bf735036c..1fdb3252920b 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.c @@ -59,7 +59,7 @@ static void destroy( { destruct(*i2c_engine); - dm_free(*i2c_engine); + kfree(*i2c_engine); *i2c_engine = NULL; } @@ -90,7 +90,8 @@ static bool construct( struct i2caux *dal_i2caux_diag_fpga_create( struct dc_context *ctx) { - struct i2caux *i2caux = dm_alloc(sizeof(struct i2caux)); + struct i2caux *i2caux = kzalloc(sizeof(struct i2caux), + GFP_KERNEL); if (!i2caux) { ASSERT_CRITICAL(false); @@ -102,7 +103,7 @@ struct i2caux *dal_i2caux_diag_fpga_create( ASSERT_CRITICAL(false); - dm_free(i2caux); + kfree(i2caux); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.c index 95bc4457d44b..9d0077ade12c 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.c @@ -541,7 +541,7 @@ static void destroy( { dal_i2c_sw_engine_destruct(FROM_I2C_ENGINE(*ptr)); - dm_free(*ptr); + kfree(*ptr); *ptr = NULL; } @@ -592,7 +592,7 @@ struct i2c_engine *dal_i2c_sw_engine_create( return NULL; } - engine = dm_alloc(sizeof(struct i2c_sw_engine)); + engine = kzalloc(sizeof(struct i2c_sw_engine), GFP_KERNEL); if (!engine) { BREAK_TO_DEBUGGER(); @@ -604,7 +604,7 @@ struct i2c_engine *dal_i2c_sw_engine_create( BREAK_TO_DEBUGGER(); - dm_free(engine); + kfree(engine); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c index 7cce28489dba..a6c3a7229def 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c @@ -422,7 +422,8 @@ bool construct( struct irq_service *dal_irq_service_dce110_create( struct irq_service_init_data *init_data) { - struct irq_service *irq_service = dm_alloc(sizeof(*irq_service)); + struct irq_service *irq_service = kzalloc(sizeof(*irq_service), + GFP_KERNEL); if (!irq_service) return NULL; @@ -430,6 +431,6 @@ struct irq_service *dal_irq_service_dce110_create( if (construct(irq_service, init_data)) return irq_service; - dm_free(irq_service); + kfree(irq_service); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c b/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c index 3871633ac635..61d7c286802a 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c @@ -281,7 +281,8 @@ static bool construct( struct irq_service *dal_irq_service_dce120_create( struct irq_service_init_data *init_data) { - struct irq_service *irq_service = dm_alloc(sizeof(*irq_service)); + struct irq_service *irq_service = kzalloc(sizeof(*irq_service), + GFP_KERNEL); if (!irq_service) return NULL; @@ -289,6 +290,6 @@ struct irq_service *dal_irq_service_dce120_create( if (construct(irq_service, init_data)) return irq_service; - dm_free(irq_service); + kfree(irq_service); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c b/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c index f458ef8e4c57..d6e1fb665d90 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c @@ -293,7 +293,8 @@ static bool construct( struct irq_service *dal_irq_service_dce80_create( struct irq_service_init_data *init_data) { - struct irq_service *irq_service = dm_alloc(sizeof(*irq_service)); + struct irq_service *irq_service = kzalloc(sizeof(*irq_service), + GFP_KERNEL); if (!irq_service) return NULL; @@ -301,7 +302,7 @@ struct irq_service *dal_irq_service_dce80_create( if (construct(irq_service, init_data)) return irq_service; - dm_free(irq_service); + kfree(irq_service); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c b/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c index be59f0a654e2..f6e861162a6e 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c @@ -348,7 +348,8 @@ static bool construct( struct irq_service *dal_irq_service_dcn10_create( struct irq_service_init_data *init_data) { - struct irq_service *irq_service = dm_alloc(sizeof(*irq_service)); + struct irq_service *irq_service = kzalloc(sizeof(*irq_service), + GFP_KERNEL); if (!irq_service) return NULL; @@ -356,6 +357,6 @@ struct irq_service *dal_irq_service_dcn10_create( if (construct(irq_service, init_data)) return irq_service; - dm_free(irq_service); + kfree(irq_service); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/irq/irq_service.c b/drivers/gpu/drm/amd/display/dc/irq/irq_service.c index 0a1fae4ef83a..ce20622c7c89 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/irq_service.c +++ b/drivers/gpu/drm/amd/display/dc/irq/irq_service.c @@ -66,7 +66,7 @@ void dal_irq_service_destroy(struct irq_service **irq_service) return; } - dm_free(*irq_service); + kfree(*irq_service); *irq_service = NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c index 57b5a3babdf8..db513abd735a 100644 --- a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c @@ -87,7 +87,7 @@ static void virtual_link_encoder_connect_dig_be_to_fe( static void virtual_link_encoder_destroy(struct link_encoder **enc) { - dm_free(*enc); + kfree(*enc); *enc = NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c index 7fe6085e6e37..3dc1733eea20 100644 --- a/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c @@ -121,7 +121,7 @@ bool virtual_stream_encoder_construct( struct stream_encoder *virtual_stream_encoder_create( struct dc_context *ctx, struct dc_bios *bp) { - struct stream_encoder *enc = dm_alloc(sizeof(*enc)); + struct stream_encoder *enc = kzalloc(sizeof(*enc), GFP_KERNEL); if (!enc) return NULL; @@ -130,7 +130,7 @@ struct stream_encoder *virtual_stream_encoder_create( return enc; BREAK_TO_DEBUGGER(); - dm_free(enc); + kfree(enc); return NULL; } diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index 52350d0e68d0..4d7db4aa28e0 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -143,7 +143,7 @@ static bool check_dc_support(const struct dc *dc) struct mod_freesync *mod_freesync_create(struct dc *dc) { struct core_freesync *core_freesync = - dm_alloc(sizeof(struct core_freesync)); + kzalloc(sizeof(struct core_freesync), GFP_KERNEL); struct persistent_data_flag flag; @@ -153,8 +153,8 @@ struct mod_freesync *mod_freesync_create(struct dc *dc) if (core_freesync == NULL) goto fail_alloc_context; - core_freesync->map = dm_alloc(sizeof(struct freesync_entity) * - MOD_FREESYNC_MAX_CONCURRENT_STREAMS); + core_freesync->map = kzalloc(sizeof(struct freesync_entity) * MOD_FREESYNC_MAX_CONCURRENT_STREAMS, + GFP_KERNEL); if (core_freesync->map == NULL) goto fail_alloc_map; @@ -197,10 +197,10 @@ struct mod_freesync *mod_freesync_create(struct dc *dc) return &core_freesync->public; fail_construct: - dm_free(core_freesync->map); + kfree(core_freesync->map); fail_alloc_map: - dm_free(core_freesync); + kfree(core_freesync); fail_alloc_context: return NULL; @@ -217,9 +217,9 @@ void mod_freesync_destroy(struct mod_freesync *mod_freesync) if (core_freesync->map[i].stream) dc_stream_release(core_freesync->map[i].stream); - dm_free(core_freesync->map); + kfree(core_freesync->map); - dm_free(core_freesync); + kfree(core_freesync); } } -- cgit From 2e12d9b761212053d0260b6309155c5e8a65948c Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Wed, 27 Sep 2017 15:36:11 -0400 Subject: drm/amd/display: DC I2C review While reviewing I2C in DC identified a few places. Added a couple to the TODO list. 1) Connector info read See get_ext_display_connection_info On some boards the connector information has to be read through a special I2C channel. This line is only used for this purpose and only on driver init. 2) SCDC stuff This should all be reworked to go through DRM's SCDC code. When this is done some unnecessary I2C code can be retired as well. 3) Max TMDS clock read See dal_ddc_service_i2c_query_dp_dual_mode_adaptor This should happen in DRM as well. I haven't checked if there's currently functionality in DRM. If not we can propose something. 4) HDMI retimer programming Some boards have an HDMI retimer that we need to program to pass PHY compliance. 1 & 3 might be a good exercise if someone is looking for things to do. v2: Merge dp_dual_mode_adaptor TODO Acked-by: Alex Deucher Signed-off-by: Harry Wentland Acked-by: Daniel Vetter Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/TODO | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/TODO b/drivers/gpu/drm/amd/display/TODO index eea645b102a1..46464678f2b3 100644 --- a/drivers/gpu/drm/amd/display/TODO +++ b/drivers/gpu/drm/amd/display/TODO @@ -62,20 +62,10 @@ TODOs ~ Daniel Vetter -11. Remove existing i2c implementation from DC - - "Similar story for i2c, it uses the kernel's i2c code now, but there's - still a full i2c implementation hidden beneath that in - display/dc/i2caux. Kinda not cool, but imo ok if you fix that - post-merging (perhaps by not including any of this in the linux DC - code in the upstream kernel, but as an aux module in your internal - codebase since there you probably need that, same applies to the edid - parsing DC still does. For both cases I assume that the minimal shim - you need on linux (bit banging and edid parsing isn't rocket since) is - a lot less than the glue code to interface with the dc-provided - abstraction." - ~ Daniel Vetter - +11. Remove dc/i2caux. This folder can be somewhat misleading. It's basically an +overy complicated HW programming function for sendind and receiving i2c/aux +commands. We can greatly simplify that and move it into dc/dceXYZ like other +HW blocks. 12. drm_modeset_lock in MST should no longer be needed in recent kernels * Adopt appropriate locking scheme @@ -89,7 +79,8 @@ moving all your driver state printing into the various atomic_print_state callbacks. There's also plans to expose this stuff in a standard way across all drivers, to make debugging userspace compositors easier across different hw. -15. Move DP/HDMI dual mode adaptors to drm_dp_dual_mode_helper.c. +15. Move DP/HDMI dual mode adaptors to drm_dp_dual_mode_helper.c. See +dal_ddc_service_i2c_query_dp_dual_mode_adaptor. 16. Move to core SCDC helpers (I think those are new since initial DC review). @@ -110,3 +101,7 @@ guilty. stuff just isn't up to the challenges either. We need to figure out something that integrates better with DRM and linux debug printing, while not being useless with filtering output. dynamic debug printing might be an option. + +20. Use kernel i2c device to program HDMI retimer. Some boards have an HDMI +retimer that we need to program to pass PHY compliance. Currently that's +bypassing the i2c device and goes directly to HW. This should be changed. -- cgit From 24a0d8538ed36ae08d8009bd4a46c6eb36d92bd1 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 28 Sep 2017 09:21:33 +1000 Subject: amdgpu/dc: add static to construct function There was a global construct symbol in the module symbols, kill it. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c index a6c3a7229def..5c558969f39f 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c @@ -406,7 +406,7 @@ static const struct irq_service_funcs irq_service_funcs_dce110 = { .to_dal_irq_source = to_dal_irq_source_dce110 }; -bool construct( +static bool construct( struct irq_service *irq_service, struct irq_service_init_data *init_data) { -- cgit From 8c0dc2b9891155afc3b1fbf6b04839819ec9099b Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 28 Sep 2017 10:22:48 +1000 Subject: amdgpu/dc: move filter taps to being static const data (v2) This just adds two accessor methods, and moves all the data to static const. v2: fix dcn build. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dce/dce_scl_filters.c | 78 ++++++++++++---------- drivers/gpu/drm/amd/display/dc/dce/dce_transform.c | 2 +- .../drm/amd/display/dc/dce110/dce110_transform_v.c | 2 +- .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c | 2 +- drivers/gpu/drm/amd/display/dc/inc/hw/transform.h | 4 +- 5 files changed, 49 insertions(+), 39 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_scl_filters.c b/drivers/gpu/drm/amd/display/dc/dce/dce_scl_filters.c index 2cfdb835f1a8..6243450b41b7 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_scl_filters.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_scl_filters.c @@ -25,7 +25,7 @@ #include "transform.h" -const uint16_t filter_2tap_16p[18] = { +static const uint16_t filter_2tap_16p[18] = { 4096, 0, 3840, 256, 3584, 512, @@ -37,7 +37,7 @@ const uint16_t filter_2tap_16p[18] = { 2048, 2048 }; -const uint16_t filter_3tap_16p_upscale[27] = { +static const uint16_t filter_3tap_16p_upscale[27] = { 2048, 2048, 0, 1708, 2424, 16348, 1372, 2796, 16308, @@ -49,7 +49,7 @@ const uint16_t filter_3tap_16p_upscale[27] = { 0, 4096, 0 }; -const uint16_t filter_3tap_16p_117[27] = { +static const uint16_t filter_3tap_16p_117[27] = { 2048, 2048, 0, 1824, 2276, 16376, 1600, 2496, 16380, @@ -61,7 +61,7 @@ const uint16_t filter_3tap_16p_117[27] = { 428, 3236, 428 }; -const uint16_t filter_3tap_16p_150[27] = { +static const uint16_t filter_3tap_16p_150[27] = { 2048, 2048, 0, 1872, 2184, 36, 1692, 2308, 88, @@ -73,7 +73,7 @@ const uint16_t filter_3tap_16p_150[27] = { 696, 2696, 696 }; -const uint16_t filter_3tap_16p_183[27] = { +static const uint16_t filter_3tap_16p_183[27] = { 2048, 2048, 0, 1892, 2104, 92, 1744, 2152, 196, @@ -85,7 +85,7 @@ const uint16_t filter_3tap_16p_183[27] = { 900, 2292, 900 }; -const uint16_t filter_4tap_16p_upscale[36] = { +static const uint16_t filter_4tap_16p_upscale[36] = { 0, 4096, 0, 0, 16240, 4056, 180, 16380, 16136, 3952, 404, 16364, @@ -97,7 +97,7 @@ const uint16_t filter_4tap_16p_upscale[36] = { 16128, 2304, 2304, 16128 }; -const uint16_t filter_4tap_16p_117[36] = { +static const uint16_t filter_4tap_16p_117[36] = { 428, 3236, 428, 0, 276, 3232, 604, 16364, 148, 3184, 800, 16340, @@ -109,7 +109,7 @@ const uint16_t filter_4tap_16p_117[36] = { 16212, 2216, 2216, 16212 }; -const uint16_t filter_4tap_16p_150[36] = { +static const uint16_t filter_4tap_16p_150[36] = { 696, 2700, 696, 0, 560, 2700, 848, 16364, 436, 2676, 1008, 16348, @@ -121,7 +121,7 @@ const uint16_t filter_4tap_16p_150[36] = { 16376, 2052, 2052, 16376 }; -const uint16_t filter_4tap_16p_183[36] = { +static const uint16_t filter_4tap_16p_183[36] = { 940, 2208, 940, 0, 832, 2200, 1052, 4, 728, 2180, 1164, 16, @@ -133,7 +133,7 @@ const uint16_t filter_4tap_16p_183[36] = { 232, 1812, 1812, 232 }; -const uint16_t filter_2tap_64p[66] = { +static const uint16_t filter_2tap_64p[66] = { 4096, 0, 4032, 64, 3968, 128, @@ -168,7 +168,7 @@ const uint16_t filter_2tap_64p[66] = { 2112, 1984, 2048, 2048 }; -const uint16_t filter_3tap_64p_upscale[99] = { +static const uint16_t filter_3tap_64p_upscale[99] = { 2048, 2048, 0, 1960, 2140, 16376, 1876, 2236, 16364, @@ -204,7 +204,7 @@ const uint16_t filter_3tap_64p_upscale[99] = { 0, 4096, 0 }; -const uint16_t filter_3tap_64p_117[99] = { +static const uint16_t filter_3tap_64p_117[99] = { 2048, 2048, 0, 1992, 2104, 16380, 1936, 2160, 16380, @@ -240,7 +240,7 @@ const uint16_t filter_3tap_64p_117[99] = { 428, 3236, 428 }; -const uint16_t filter_3tap_64p_150[99] = { +static const uint16_t filter_3tap_64p_150[99] = { 2048, 2048, 0, 2004, 2080, 8, 1960, 2116, 16, @@ -276,7 +276,7 @@ const uint16_t filter_3tap_64p_150[99] = { 696, 2696, 696 }; -const uint16_t filter_3tap_64p_183[99] = { +static const uint16_t filter_3tap_64p_183[99] = { 2048, 2048, 0, 2008, 2060, 20, 1968, 2076, 44, @@ -312,7 +312,7 @@ const uint16_t filter_3tap_64p_183[99] = { 900, 2292, 900 }; -const uint16_t filter_4tap_64p_upscale[132] = { +static const uint16_t filter_4tap_64p_upscale[132] = { 0, 4096, 0, 0, 16344, 4092, 40, 0, 16308, 4084, 84, 16380, @@ -347,7 +347,7 @@ const uint16_t filter_4tap_64p_upscale[132] = { 16116, 2388, 2216, 16140, 16128, 2304, 2304, 16128 }; -const uint16_t filter_4tap_64p_117[132] = { +static const uint16_t filter_4tap_64p_117[132] = { 420, 3248, 420, 0, 380, 3248, 464, 16380, 344, 3248, 508, 16372, @@ -382,7 +382,7 @@ const uint16_t filter_4tap_64p_117[132] = { 16212, 2276, 2160, 16212, 16212, 2220, 2220, 16212 }; -const uint16_t filter_4tap_64p_150[132] = { +static const uint16_t filter_4tap_64p_150[132] = { 696, 2700, 696, 0, 660, 2704, 732, 16380, 628, 2704, 768, 16376, @@ -417,7 +417,7 @@ const uint16_t filter_4tap_64p_150[132] = { 4, 2112, 1996, 16364, 16380, 2072, 2036, 16372 }; -const uint16_t filter_4tap_64p_183[132] = { +static const uint16_t filter_4tap_64p_183[132] = { 944, 2204, 944, 0, 916, 2204, 972, 0, 888, 2200, 996, 0, @@ -452,7 +452,7 @@ const uint16_t filter_4tap_64p_183[132] = { 252, 1832, 1784, 220, 236, 1808, 1808, 236 }; -const uint16_t filter_5tap_64p_upscale[165] = { +static const uint16_t filter_5tap_64p_upscale[165] = { 15936, 2496, 2496, 15936, 0, 15948, 2404, 2580, 15924, 0, 15960, 2312, 2664, 15912, 4, @@ -487,7 +487,7 @@ const uint16_t filter_5tap_64p_upscale[165] = { 16376, 48, 4092, 16336, 4, 0, 0, 4096, 0, 0 }; -const uint16_t filter_5tap_64p_117[165] = { +static const uint16_t filter_5tap_64p_117[165] = { 16056, 2372, 2372, 16056, 0, 16052, 2312, 2432, 16060, 0, 16052, 2252, 2488, 16064, 0, @@ -522,7 +522,7 @@ const uint16_t filter_5tap_64p_117[165] = { 16248, 504, 3428, 408, 16268, 16256, 456, 3428, 456, 16256 }; -const uint16_t filter_5tap_64p_150[165] = { +static const uint16_t filter_5tap_64p_150[165] = { 16368, 2064, 2064, 16368, 0, 16352, 2028, 2100, 16380, 16380, 16340, 1996, 2132, 12, 16376, @@ -557,7 +557,7 @@ const uint16_t filter_5tap_64p_150[165] = { 16248, 860, 2708, 788, 16252, 16248, 824, 2708, 824, 16248 }; -const uint16_t filter_5tap_64p_183[165] = { +static const uint16_t filter_5tap_64p_183[165] = { 228, 1816, 1816, 228, 0, 216, 1792, 1836, 248, 16380, 200, 1772, 1860, 264, 16376, @@ -592,7 +592,7 @@ const uint16_t filter_5tap_64p_183[165] = { 16340, 1000, 2232, 944, 16336, 16340, 972, 2232, 972, 16340 }; -const uint16_t filter_6tap_64p_upscale[198] = { +static const uint16_t filter_6tap_64p_upscale[198] = { 0, 0, 4092, 0, 0, 0, 12, 16332, 4092, 52, 16368, 0, 24, 16280, 4088, 108, 16356, 0, @@ -627,7 +627,7 @@ const uint16_t filter_6tap_64p_upscale[198] = { 104, 15816, 2588, 2416, 15840, 92, 100, 15828, 2504, 2504, 15828, 100 }; -const uint16_t filter_6tap_64p_117[198] = { +static const uint16_t filter_6tap_64p_117[198] = { 16168, 476, 3568, 476, 16168, 0, 16180, 428, 3564, 528, 16156, 0, 16192, 376, 3556, 584, 16144, 4, @@ -662,7 +662,7 @@ const uint16_t filter_6tap_64p_117[198] = { 40, 15956, 2496, 2376, 15944, 44, 40, 15952, 2436, 2436, 15952, 40 }; -const uint16_t filter_6tap_64p_150[198] = { +static const uint16_t filter_6tap_64p_150[198] = { 16148, 920, 2724, 920, 16148, 0, 16152, 880, 2724, 956, 16148, 0, 16152, 844, 2720, 996, 16144, 0, @@ -697,7 +697,7 @@ const uint16_t filter_6tap_64p_150[198] = { 16292, 8, 2172, 2108, 16356, 16304, 16300, 16372, 2140, 2140, 16372, 16300 }; -const uint16_t filter_6tap_64p_183[198] = { +static const uint16_t filter_6tap_64p_183[198] = { 16296, 1032, 2196, 1032, 16296, 0, 16292, 1004, 2200, 1060, 16304, 16380, 16288, 976, 2200, 1088, 16308, 16380, @@ -732,7 +732,7 @@ const uint16_t filter_6tap_64p_183[198] = { 16288, 296, 1880, 1840, 256, 16296, 16292, 276, 1860, 1860, 276, 16292 }; -const uint16_t filter_7tap_64p_upscale[231] = { +static const uint16_t filter_7tap_64p_upscale[231] = { 176, 15760, 2488, 2488, 15760, 176, 0, 172, 15772, 2404, 2572, 15752, 180, 16380, 168, 15784, 2324, 2656, 15740, 184, 16380, @@ -767,7 +767,7 @@ const uint16_t filter_7tap_64p_upscale[231] = { 0, 16364, 56, 4092, 16328, 16, 16380, 0, 0, 0, 4096, 0, 0, 0 }; -const uint16_t filter_7tap_64p_117[231] = { +static const uint16_t filter_7tap_64p_117[231] = { 92, 15868, 2464, 2464, 15868, 92, 0, 96, 15864, 2404, 2528, 15876, 88, 0, 100, 15860, 2344, 2584, 15884, 84, 0, @@ -802,7 +802,7 @@ const uint16_t filter_7tap_64p_117[231] = { 68, 16108, 504, 3572, 396, 16140, 60, 64, 16124, 452, 3576, 452, 16124, 64 }; -const uint16_t filter_7tap_64p_150[231] = { +static const uint16_t filter_7tap_64p_150[231] = { 16224, 16380, 2208, 2208, 16380, 16224, 0, 16232, 16360, 2172, 2236, 16, 16216, 0, 16236, 16340, 2140, 2268, 40, 16212, 0, @@ -837,7 +837,7 @@ const uint16_t filter_7tap_64p_150[231] = { 16380, 16076, 1020, 2740, 944, 16076, 0, 0, 16076, 984, 2740, 984, 16076, 0 }; -const uint16_t filter_7tap_64p_183[231] = { +static const uint16_t filter_7tap_64p_183[231] = { 16216, 324, 1884, 1884, 324, 16216, 0, 16220, 304, 1864, 1904, 344, 16216, 0, 16224, 284, 1844, 1924, 364, 16216, 0, @@ -872,7 +872,7 @@ const uint16_t filter_7tap_64p_183[231] = { 16316, 16284, 1132, 2216, 1076, 16268, 16324, 16320, 16276, 1104, 2216, 1104, 16276, 16320 }; -const uint16_t filter_8tap_64p_upscale[264] = { +static const uint16_t filter_8tap_64p_upscale[264] = { 0, 0, 0, 4096, 0, 0, 0, 0, 16376, 20, 16328, 4092, 56, 16364, 4, 0, 16372, 36, 16272, 4088, 116, 16340, 12, 0, @@ -907,7 +907,7 @@ const uint16_t filter_8tap_64p_upscale[264] = { 16328, 248, 15692, 2616, 2448, 15716, 240, 16332, 16332, 244, 15704, 2532, 2532, 15704, 244, 16332 }; -const uint16_t filter_8tap_64p_117[264] = { +static const uint16_t filter_8tap_64p_117[264] = { 116, 16100, 428, 3564, 428, 16100, 116, 0, 112, 16116, 376, 3564, 484, 16084, 120, 16380, 104, 16136, 324, 3560, 540, 16064, 124, 16380, @@ -942,7 +942,7 @@ const uint16_t filter_8tap_64p_117[264] = { 16372, 136, 15816, 2548, 2428, 15804, 148, 16368, 16372, 140, 15812, 2488, 2488, 15812, 140, 16372 }; -const uint16_t filter_8tap_64p_150[264] = { +static const uint16_t filter_8tap_64p_150[264] = { 16380, 16020, 1032, 2756, 1032, 16020, 16380, 0, 0, 16020, 992, 2756, 1068, 16024, 16376, 0, 4, 16020, 952, 2752, 1108, 16024, 16372, 0, @@ -977,7 +977,7 @@ const uint16_t filter_8tap_64p_150[264] = { 44, 16160, 24, 2244, 2180, 16364, 16176, 40, 44, 16168, 4, 2212, 2212, 4, 16168, 44 }; -const uint16_t filter_8tap_64p_183[264] = { +static const uint16_t filter_8tap_64p_183[264] = { 16264, 16264, 1164, 2244, 1164, 16264, 16264, 0, 16268, 16256, 1136, 2240, 1188, 16272, 16260, 0, 16272, 16248, 1108, 2240, 1216, 16280, 16256, 0, @@ -1107,3 +1107,13 @@ const uint16_t *get_filter_8tap_64p(struct fixed31_32 ratio) else return filter_8tap_64p_183; } + +const uint16_t *get_filter_2tap_16p(void) +{ + return filter_2tap_16p; +} + +const uint16_t *get_filter_2tap_64p(void) +{ + return filter_2tap_64p; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c index 0e366021cf16..a8f60d7531be 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c @@ -306,7 +306,7 @@ static const uint16_t *get_filter_coeffs_16p(int taps, struct fixed31_32 ratio) else if (taps == 3) return get_filter_3tap_16p(ratio); else if (taps == 2) - return filter_2tap_16p; + return get_filter_2tap_16p(); else if (taps == 1) return NULL; else { diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c index c84823a40f61..47390dc58306 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c @@ -489,7 +489,7 @@ static const uint16_t *get_filter_coeffs_64p(int taps, struct fixed31_32 ratio) if (taps == 4) return get_filter_4tap_64p(ratio); else if (taps == 2) - return filter_2tap_64p; + return get_filter_2tap_64p(); else if (taps == 1) return NULL; else { 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 b62cb38f523c..82b8887d4973 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 @@ -240,7 +240,7 @@ static const uint16_t *get_filter_coeffs_64p(int taps, struct fixed31_32 ratio) else if (taps == 3) return get_filter_3tap_64p(ratio); else if (taps == 2) - return filter_2tap_64p; + return get_filter_2tap_64p(); else if (taps == 1) return NULL; else { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h index 32947450e702..9d4a3a0098a9 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h @@ -240,8 +240,8 @@ struct transform_funcs { }; -extern const uint16_t filter_2tap_16p[18]; -extern const uint16_t filter_2tap_64p[66]; +const uint16_t *get_filter_2tap_16p(void); +const uint16_t *get_filter_2tap_64p(void); const uint16_t *get_filter_3tap_16p(struct fixed31_32 ratio); const uint16_t *get_filter_3tap_64p(struct fixed31_32 ratio); const uint16_t *get_filter_4tap_16p(struct fixed31_32 ratio); -- cgit From b3fbdcec5e6c16c93867289ae0960a64c423eb34 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 28 Sep 2017 10:10:22 +1000 Subject: amdgpu/dc: drop display_pipe_clocks.c. This code isn't used at all in the kernel tree, perhaps it can wait to be imported when it is. It also does a lot of floating point calcs, so probably good to drop it until it's needed and we can ensure proper fpu accessors. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/Makefile | 2 +- .../gpu/drm/amd/display/dc/dml/display_mode_lib.h | 1 - .../drm/amd/display/dc/dml/display_pipe_clocks.c | 367 --------------------- .../drm/amd/display/dc/dml/display_pipe_clocks.h | 41 --- 4 files changed, 1 insertion(+), 410 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dml/Makefile b/drivers/gpu/drm/amd/display/dc/dml/Makefile index 9d7791d00e97..a6bf36466497 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dml/Makefile @@ -13,7 +13,7 @@ CFLAGS_dml_common_defs.o := -mhard-float -msse -mpreferred-stack-boundary=4 CFLAGS_display_mode_support.o := -mhard-float -msse -mpreferred-stack-boundary=4 -DML = display_mode_lib.o display_pipe_clocks.o display_rq_dlg_calc.o \ +DML = display_mode_lib.o display_rq_dlg_calc.o \ display_rq_dlg_helpers.o display_watermark.o \ soc_bounding_box.o dml_common_defs.o display_mode_support.o diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h index e2e311138358..eb1c8e6e7f23 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h @@ -28,7 +28,6 @@ #include "dml_common_defs.h" #include "soc_bounding_box.h" #include "display_watermark.h" -#include "display_pipe_clocks.h" #include "display_rq_dlg_calc.h" #include "display_mode_support.h" diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.c b/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.c deleted file mode 100644 index 2e4dc57cafa0..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.c +++ /dev/null @@ -1,367 +0,0 @@ -/* - * Copyright 2017 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "display_pipe_clocks.h" -#include "display_mode_lib.h" -#include "soc_bounding_box.h" - -static enum voltage_state power_state( - struct display_mode_lib *mode_lib, - double dispclk, - double dppclk) -{ - enum voltage_state state1; - enum voltage_state state2; - - if (dispclk <= mode_lib->soc.vmin.dispclk_mhz) - state1 = dm_vmin; - else if (dispclk <= mode_lib->soc.vnom.dispclk_mhz) - state1 = dm_vnom; - else if (dispclk <= mode_lib->soc.vmax.dispclk_mhz) - state1 = dm_vmax; - else - state1 = dm_vmax_exceeded; - - if (dppclk <= mode_lib->soc.vmin.dppclk_mhz) - state2 = dm_vmin; - else if (dppclk <= mode_lib->soc.vnom.dppclk_mhz) - state2 = dm_vnom; - else if (dppclk <= mode_lib->soc.vmax.dppclk_mhz) - state2 = dm_vmax; - else - state2 = dm_vmax_exceeded; - - if (state1 > state2) - return state1; - else - return state2; -} - -static unsigned int dpp_in_grp( - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - unsigned int num_pipes, - unsigned int hsplit_grp) -{ - unsigned int num_dpp = 0; - unsigned int i; - - for (i = 0; i < num_pipes; i++) { - if (e2e[i].pipe.src.is_hsplit) { - if (e2e[i].pipe.src.hsplit_grp == hsplit_grp) { - num_dpp++; - } - } - } - - if (0 == num_dpp) - num_dpp = 1; - - return num_dpp; -} - -static void calculate_pipe_clk_requirement( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - unsigned int num_dpp_in_grp, - double *dppclk, - double *dispclk, - bool *dppdiv) -{ - double pscl_throughput = 0.0; - double max_hratio = e2e->pipe.scale_ratio_depth.hscl_ratio; - double max_vratio = e2e->pipe.scale_ratio_depth.vscl_ratio; - double max_htaps = e2e->pipe.scale_taps.htaps; - double max_vtaps = e2e->pipe.scale_taps.vtaps; - double dpp_clock_divider = (double) num_dpp_in_grp; - double dispclk_dppclk_ratio; - double dispclk_ramp_margin_percent; - - if (max_hratio > 1.0) { - double pscl_to_lb = ((double) mode_lib->ip.max_pscl_lb_bw_pix_per_clk * max_hratio) - / dml_ceil(max_htaps / 6.0); - pscl_throughput = dml_min( - pscl_to_lb, - (double) mode_lib->ip.max_dchub_pscl_bw_pix_per_clk); - } else { - pscl_throughput = dml_min( - (double) mode_lib->ip.max_pscl_lb_bw_pix_per_clk, - (double) mode_lib->ip.max_dchub_pscl_bw_pix_per_clk); - } - - DTRACE("pscl_throughput: %f pix per clk", pscl_throughput); - DTRACE("vtaps: %f hratio: %f vratio: %f", max_vtaps, max_hratio, max_vratio); - *dppclk = dml_max( - max_vtaps / 6.0 * dml_min(1.0, max_hratio), - max_hratio * max_vratio / pscl_throughput); - DTRACE("pixel rate multiplier: %f", *dppclk); - *dppclk = dml_max(*dppclk, 1.0); - DTRACE("pixel rate multiplier clamped: %f", *dppclk); - *dppclk = *dppclk * e2e->pipe.dest.pixel_rate_mhz; - - *dppclk = *dppclk / dpp_clock_divider; - DTRACE("dppclk after split: %f", *dppclk); - - if (dpp_clock_divider > 1.0 && (*dppclk < e2e->pipe.dest.pixel_rate_mhz)) { - dispclk_dppclk_ratio = 2.0; - *dppdiv = true; - } else { - dispclk_dppclk_ratio = 1.0; - *dppdiv = false; - } - - dispclk_ramp_margin_percent = mode_lib->ip.dispclk_ramp_margin_percent; - - /* Comment this out because of Gabes possible bug in spreadsheet, - * just to make other cases evident during debug - * - *if(e2e->clks_cfg.voltage == dm_vmax) - * dispclk_ramp_margin_percent = 0.0; - */ - - /* account for ramping margin and downspread */ - *dispclk = dml_max(*dppclk * dispclk_dppclk_ratio, e2e->pipe.dest.pixel_rate_mhz) - * (1.0 + (double) mode_lib->soc.downspread_percent / 100.0) - * (1.0 + (double) dispclk_ramp_margin_percent / 100.0); - - return; -} - -bool dml_clks_pipe_clock_requirement_fit_power_constraint( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - unsigned int num_dpp_in_grp) -{ - double dppclk = 0; - double dispclk = 0; - bool dppdiv = 0; - - calculate_pipe_clk_requirement(mode_lib, e2e, num_dpp_in_grp, &dppclk, &dispclk, &dppdiv); - - if (power_state(mode_lib, dispclk, dppclk) > e2e->clks_cfg.voltage) { - return false; - } - - return true; -} - -static void get_plane_clks( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - unsigned int num_pipes, - double *dppclks, - double *dispclks, - bool *dppdiv) -{ - /* it is assumed that the scale ratios passed into the e2e pipe params have already been calculated - * for any split pipe configurations, where extra pixels inthe overlap region do not contribute to - * the scale ratio. This means that we can simply calculate the dppclk for each dpp independently - * and we would expect the same result on any split pipes, which would be handled - */ - unsigned int i; - - for (i = 0; i < num_pipes; i++) { - double num_dpp_in_grp; - double dispclk_ramp_margin_percent; - double dispclk_margined; - - if (e2e[i].pipe.src.is_hsplit) - num_dpp_in_grp = (double) dpp_in_grp( - e2e, - num_pipes, - e2e[i].pipe.src.hsplit_grp); - else - num_dpp_in_grp = 1; - - calculate_pipe_clk_requirement( - mode_lib, - &e2e[i], - num_dpp_in_grp, - &dppclks[i], - &dispclks[i], - &dppdiv[i]); - - dispclk_ramp_margin_percent = mode_lib->ip.dispclk_ramp_margin_percent; - - dispclk_margined = e2e[i].pipe.dest.pixel_rate_mhz - * (1.0 + (double) mode_lib->soc.downspread_percent / 100.0) - * (1.0 + (double) dispclk_ramp_margin_percent / 100.0); - - DTRACE("p%d: requested power state: %d", i, (int) e2e[0].clks_cfg.voltage); - - if (power_state(mode_lib, dispclks[i], dppclks[i]) - > power_state(mode_lib, dispclk_margined, dispclk_margined) - && dispclk_margined > dppclks[i]) { - if (power_state(mode_lib, dispclks[i], dppclks[i]) - > e2e[0].clks_cfg.voltage) { - dispclks[i] = dispclk_margined; - dppclks[i] = dispclk_margined; - dppdiv[i] = false; - } - } - - DTRACE("p%d: dispclk: %f", i, dispclks[i]); - } -} - -static void get_dcfclk( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - unsigned int num_pipes, - double *dcfclk_mhz) -{ - double bytes_per_pixel_det_y[DC__NUM_PIPES__MAX]; - double bytes_per_pixel_det_c[DC__NUM_PIPES__MAX]; - double swath_width_y[DC__NUM_PIPES__MAX]; - unsigned int i; - double total_read_bandwidth_gbps = 0.0; - - for (i = 0; i < num_pipes; i++) { - if (e2e[i].pipe.src.source_scan == dm_horz) { - swath_width_y[i] = e2e[i].pipe.src.viewport_width * 1.0; - } else { - swath_width_y[i] = e2e[i].pipe.src.viewport_height * 1.0; - } - - switch (e2e[i].pipe.src.source_format) { - case dm_444_64: - bytes_per_pixel_det_y[i] = 8.0; - bytes_per_pixel_det_c[i] = 0.0; - break; - case dm_444_32: - bytes_per_pixel_det_y[i] = 4.0; - bytes_per_pixel_det_c[i] = 0.0; - break; - case dm_444_16: - bytes_per_pixel_det_y[i] = 2.0; - bytes_per_pixel_det_c[i] = 0.0; - break; - case dm_422_8: - bytes_per_pixel_det_y[i] = 2.0; - bytes_per_pixel_det_c[i] = 0.0; - break; - case dm_422_10: - bytes_per_pixel_det_y[i] = 4.0; - bytes_per_pixel_det_c[i] = 0.0; - break; - case dm_420_8: - bytes_per_pixel_det_y[i] = 1.0; - bytes_per_pixel_det_c[i] = 2.0; - break; - case dm_420_10: - bytes_per_pixel_det_y[i] = 4.0 / 3.0; - bytes_per_pixel_det_c[i] = 8.0 / 3.0; - break; - default: - BREAK_TO_DEBUGGER(); /* invalid src_format in get_dcfclk */ - } - } - - for (i = 0; i < num_pipes; i++) { - double read_bandwidth_plane_mbps = 0.0; - read_bandwidth_plane_mbps = (double) swath_width_y[i] - * ((double) bytes_per_pixel_det_y[i] - + (double) bytes_per_pixel_det_c[i] / 2.0) - / ((double) e2e[i].pipe.dest.htotal - / (double) e2e[i].pipe.dest.pixel_rate_mhz) - * e2e[i].pipe.scale_ratio_depth.vscl_ratio; - - if (e2e[i].pipe.src.dcc) { - read_bandwidth_plane_mbps += (read_bandwidth_plane_mbps / 1000.0 / 256.0); - } - - if (e2e[i].pipe.src.vm) { - read_bandwidth_plane_mbps += (read_bandwidth_plane_mbps / 1000.0 / 512.0); - } - - total_read_bandwidth_gbps = total_read_bandwidth_gbps - + read_bandwidth_plane_mbps / 1000.0; - } - - DTRACE("total bandwidth = %f gbps", total_read_bandwidth_gbps); - - (*dcfclk_mhz) = (total_read_bandwidth_gbps * 1000.0) / mode_lib->soc.return_bus_width_bytes; - - DTRACE( - "minimum theoretical dcfclk without stutter and full utilization = %f MHz", - (*dcfclk_mhz)); - -} - -struct _vcs_dpi_display_pipe_clock_st dml_clks_get_pipe_clocks( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - unsigned int num_pipes) -{ - struct _vcs_dpi_display_pipe_clock_st clocks; - double max_dispclk = 0.0; - double dcfclk; - double dispclks[DC__NUM_PIPES__MAX]; - double dppclks[DC__NUM_PIPES__MAX]; - bool dppdiv[DC__NUM_PIPES__MAX]; - unsigned int i; - - DTRACE("Calculating pipe clocks..."); - - /* this is the theoretical minimum, have to adjust based on valid values for soc */ - get_dcfclk(mode_lib, e2e, num_pipes, &dcfclk); - - /* if(dcfclk > soc.vnom.dcfclk_mhz) - * dcfclk = soc.vmax.dcfclk_mhz; - * else if(dcfclk > soc.vmin.dcfclk_mhz) - * dcfclk = soc.vnom.dcfclk_mhz; - * else - * dcfclk = soc.vmin.dcfclk_mhz; - */ - - dcfclk = dml_socbb_voltage_scaling( - &mode_lib->soc, - (enum voltage_state) e2e[0].clks_cfg.voltage).dcfclk_mhz; - clocks.dcfclk_mhz = dcfclk; - - get_plane_clks(mode_lib, e2e, num_pipes, dppclks, dispclks, dppdiv); - - for (i = 0; i < num_pipes; i++) { - max_dispclk = dml_max(max_dispclk, dispclks[i]); - } - - clocks.dispclk_mhz = max_dispclk; - DTRACE("dispclk: %f Mhz", clocks.dispclk_mhz); - DTRACE("dcfclk: %f Mhz", clocks.dcfclk_mhz); - - for (i = 0; i < num_pipes; i++) { - if (dppclks[i] * 2 < max_dispclk) - dppdiv[i] = 1; - - if (dppdiv[i]) - clocks.dppclk_div[i] = 1; - else - clocks.dppclk_div[i] = 0; - - clocks.dppclk_mhz[i] = max_dispclk / ((dppdiv[i]) ? 2.0 : 1.0); - DTRACE("dppclk%d: %f Mhz", i, clocks.dppclk_mhz[i]); - } - - return clocks; -} diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.h b/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.h deleted file mode 100644 index aed5f33bb04f..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2017 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ -#ifndef __DISPLAY_PIPE_CLOCKS_H__ -#define __DISPLAY_PIPE_CLOCKS_H__ - -#include "dml_common_defs.h" - -struct display_mode_lib; - -struct _vcs_dpi_display_pipe_clock_st dml_clks_get_pipe_clocks( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - unsigned int num_pipes); - -bool dml_clks_pipe_clock_requirement_fit_power_constraint( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - unsigned int num_dpp_in_grp); -#endif -- cgit From d1209512e028a917e6e70b13297ff185234ba24d Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 28 Sep 2017 10:45:25 +1000 Subject: amdgpu/dc: inline a bunch of float operations. This reduces code size for the bw calcs code. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/calcs/dcn_calc_math.c | 29 ----------------- .../gpu/drm/amd/display/dc/calcs/dcn_calc_math.h | 36 ++++++++++++++++++---- 2 files changed, 30 insertions(+), 35 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.c index a18474437990..05cf5f77ec60 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.c @@ -25,25 +25,6 @@ #include "dcn_calc_math.h" -float dcn_bw_mod(const float arg1, const float arg2) -{ - return arg1 - arg1 * ((int) (arg1 / arg2)); -} - -float dcn_bw_min2(const float arg1, const float arg2) -{ - return arg1 < arg2 ? arg1 : arg2; -} - -unsigned int dcn_bw_max(const unsigned int arg1, const unsigned int arg2) -{ - return arg1 > arg2 ? arg1 : arg2; -} -float dcn_bw_max2(const float arg1, const float arg2) -{ - return arg1 > arg2 ? arg1 : arg2; -} - float dcn_bw_floor2(const float arg, const float significance) { if (significance == 0) @@ -59,16 +40,6 @@ float dcn_bw_ceil2(const float arg, const float significance) return flr + 0.00001 >= arg ? arg : flr + significance; } -float dcn_bw_max3(float v1, float v2, float v3) -{ - return v3 > dcn_bw_max2(v1, v2) ? v3 : dcn_bw_max2(v1, v2); -} - -float dcn_bw_max5(float v1, float v2, float v3, float v4, float v5) -{ - return dcn_bw_max3(v1, v2, v3) > dcn_bw_max2(v4, v5) ? dcn_bw_max3(v1, v2, v3) : dcn_bw_max2(v4, v5); -} - float dcn_bw_pow(float a, float exp) { float temp; diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.h b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.h index f46ab0e24ca1..6f66d9d164d1 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.h +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.h @@ -26,14 +26,38 @@ #ifndef _DCN_CALC_MATH_H_ #define _DCN_CALC_MATH_H_ -float dcn_bw_mod(const float arg1, const float arg2); -float dcn_bw_min2(const float arg1, const float arg2); -unsigned int dcn_bw_max(const unsigned int arg1, const unsigned int arg2); -float dcn_bw_max2(const float arg1, const float arg2); +static inline float dcn_bw_mod(const float arg1, const float arg2) +{ + return arg1 - arg1 * ((int) (arg1 / arg2)); +} + +static inline float dcn_bw_min2(const float arg1, const float arg2) +{ + return arg1 < arg2 ? arg1 : arg2; +} + +static inline unsigned int dcn_bw_max(const unsigned int arg1, const unsigned int arg2) +{ + return arg1 > arg2 ? arg1 : arg2; +} + +static inline float dcn_bw_max2(const float arg1, const float arg2) +{ + return arg1 > arg2 ? arg1 : arg2; +} + +static inline float dcn_bw_max3(float v1, float v2, float v3) +{ + return v3 > dcn_bw_max2(v1, v2) ? v3 : dcn_bw_max2(v1, v2); +} + +static inline float dcn_bw_max5(float v1, float v2, float v3, float v4, float v5) +{ + return dcn_bw_max3(v1, v2, v3) > dcn_bw_max2(v4, v5) ? dcn_bw_max3(v1, v2, v3) : dcn_bw_max2(v4, v5); +} + float dcn_bw_floor2(const float arg, const float significance); float dcn_bw_ceil2(const float arg, const float significance); -float dcn_bw_max3(float v1, float v2, float v3); -float dcn_bw_max5(float v1, float v2, float v3, float v4, float v5); float dcn_bw_pow(float a, float exp); float dcn_bw_log(float a, float b); -- cgit From 3e8c3108dab197858e74dbb740c5312ae636ea9b Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 28 Sep 2017 10:45:26 +1000 Subject: amdgpu/dc: inline a bunch of the dml wrappers. This reduces code size. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dml/display_mode_support.c | 1 + .../drm/amd/display/dc/dml/display_rq_dlg_calc.c | 2 + .../gpu/drm/amd/display/dc/dml/display_watermark.c | 1 + .../gpu/drm/amd/display/dc/dml/dml_common_defs.c | 56 +------------------- .../gpu/drm/amd/display/dc/dml/dml_common_defs.h | 11 ---- .../gpu/drm/amd/display/dc/dml/dml_inline_defs.h | 61 ++++++++++++++++++++++ .../gpu/drm/amd/display/dc/dml/soc_bounding_box.c | 1 + 7 files changed, 67 insertions(+), 66 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c index 3b4ee74527f5..ac573568c10a 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c @@ -26,6 +26,7 @@ #include "display_mode_support.h" #include "display_mode_lib.h" +#include "dml_inline_defs.h" int dml_ms_check( struct display_mode_lib *mode_lib, struct _vcs_dpi_display_e2e_pipe_params_st *e2e, diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c index 9fccbbffe129..7a5fb1cef303 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c @@ -25,6 +25,8 @@ #include "display_rq_dlg_calc.h" #include "display_mode_lib.h" +#include "dml_inline_defs.h" + static unsigned int get_bytes_per_element(enum source_format_class source_format, bool is_chroma) { unsigned int ret_val = 0; diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_watermark.c b/drivers/gpu/drm/amd/display/dc/dml/display_watermark.c index 390f09391433..142a3284ac44 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_watermark.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_watermark.c @@ -24,6 +24,7 @@ */ #include "display_watermark.h" #include "display_mode_lib.h" +#include "dml_inline_defs.h" static void get_bytes_per_pixel( enum source_format_class format, diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c index 21349a022de3..c242b8d41b8a 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c @@ -26,26 +26,7 @@ #include "dml_common_defs.h" #include "../calcs/dcn_calc_math.h" -double dml_min(double a, double b) -{ - return (double) dcn_bw_min2(a, b); -} - -double dml_max(double a, double b) -{ - return (double) dcn_bw_max2(a, b); -} - -double dml_ceil(double a) -{ - return (double) dcn_bw_ceil2(a, 1); -} - -double dml_floor(double a) -{ - return (double) dcn_bw_floor2(a, 1); -} - +#include "dml_inline_defs.h" double dml_round(double a) { double round_pt = 0.5; @@ -58,16 +39,6 @@ double dml_round(double a) return floor; } -int dml_log2(double x) -{ - return dml_round((double)dcn_bw_log(x, 2)); -} - -double dml_pow(double a, int exp) -{ - return (double) dcn_bw_pow(a, exp); -} - unsigned int dml_round_to_multiple( unsigned int num, unsigned int multiple, @@ -89,16 +60,6 @@ unsigned int dml_round_to_multiple( return (num - remainder); } -double dml_fmod(double f, int val) -{ - return (double) dcn_bw_mod(f, val); -} - -double dml_ceil_2(double f) -{ - return (double) dcn_bw_ceil2(f, 2); -} - bool dml_util_is_420(enum source_format_class sorce_format) { bool val = false; @@ -131,18 +92,3 @@ bool dml_util_is_420(enum source_format_class sorce_format) return val; } - -double dml_ceil_ex(double x, double granularity) -{ - return (double) dcn_bw_ceil2(x, granularity); -} - -double dml_floor_ex(double x, double granularity) -{ - return (double) dcn_bw_floor2(x, granularity); -} - -double dml_log(double x, double base) -{ - return (double) dcn_bw_log(x, base); -} diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h index c5340d41eedb..c621f8321b03 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h @@ -32,20 +32,9 @@ #define DTRACE(str, ...) dm_logger_write(mode_lib->logger, LOG_DML, str, ##__VA_ARGS__); -double dml_min(double a, double b); -double dml_max(double a, double b); bool dml_util_is_420(enum source_format_class sorce_format); -double dml_ceil_ex(double x, double granularity); -double dml_floor_ex(double x, double granularity); -double dml_log(double x, double base); -double dml_ceil(double a); -double dml_floor(double a); double dml_round(double a); -int dml_log2(double x); -double dml_pow(double a, int exp); unsigned int dml_round_to_multiple( unsigned int num, unsigned int multiple, bool up); -double dml_fmod(double f, int val); -double dml_ceil_2(double f); #endif /* __DC_COMMON_DEFS_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h b/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h new file mode 100644 index 000000000000..1c6c631daad4 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h @@ -0,0 +1,61 @@ +#ifndef __DML_INLINE_DEFS_H__ +#define __DML_INLINE_DEFS_H__ +#include "dml_common_defs.h" +#include "../calcs/dcn_calc_math.h" + +static inline double dml_min(double a, double b) +{ + return (double) dcn_bw_min2(a, b); +} + +static inline double dml_max(double a, double b) +{ + return (double) dcn_bw_max2(a, b); +} + +static inline double dml_ceil(double a) +{ + return (double) dcn_bw_ceil2(a, 1); +} + +static inline double dml_floor(double a) +{ + return (double) dcn_bw_floor2(a, 1); +} + +static inline int dml_log2(double x) +{ + return dml_round((double)dcn_bw_log(x, 2)); +} + +static inline double dml_pow(double a, int exp) +{ + return (double) dcn_bw_pow(a, exp); +} + +static inline double dml_fmod(double f, int val) +{ + return (double) dcn_bw_mod(f, val); +} + +static inline double dml_ceil_2(double f) +{ + return (double) dcn_bw_ceil2(f, 2); +} + +static inline double dml_ceil_ex(double x, double granularity) +{ + return (double) dcn_bw_ceil2(x, granularity); +} + +static inline double dml_floor_ex(double x, double granularity) +{ + return (double) dcn_bw_floor2(x, granularity); +} + +static inline double dml_log(double x, double base) +{ + return (double) dcn_bw_log(x, base); +} + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c b/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c index cb143d3d40f0..0745366d80bc 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c +++ b/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c @@ -25,6 +25,7 @@ #include "soc_bounding_box.h" #include "display_mode_lib.h" +#include "dml_inline_defs.h" void dml_socbb_set_latencies( struct display_mode_lib *mode_lib, struct _vcs_dpi_soc_bounding_box_st *from_box) -- cgit From e5bcf3d83e40cc7acc9d111519b7bacaf4a01070 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 28 Sep 2017 10:55:25 +1000 Subject: amdgpu/dc: drop dml_util_is_420 This is unused code. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dml/dml_common_defs.c | 33 ---------------------- .../gpu/drm/amd/display/dc/dml/dml_common_defs.h | 1 - 2 files changed, 34 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c index c242b8d41b8a..7c0eb52b91b8 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c @@ -59,36 +59,3 @@ unsigned int dml_round_to_multiple( else return (num - remainder); } - -bool dml_util_is_420(enum source_format_class sorce_format) -{ - bool val = false; - - switch (sorce_format) { - case dm_444_16: - val = false; - break; - case dm_444_32: - val = false; - break; - case dm_444_64: - val = false; - break; - case dm_420_8: - val = true; - break; - case dm_420_10: - val = true; - break; - case dm_422_8: - val = false; - break; - case dm_422_10: - val = false; - break; - default: - BREAK_TO_DEBUGGER(); - } - - return val; -} diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h index c621f8321b03..a2da3da5ef8f 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h @@ -32,7 +32,6 @@ #define DTRACE(str, ...) dm_logger_write(mode_lib->logger, LOG_DML, str, ##__VA_ARGS__); -bool dml_util_is_420(enum source_format_class sorce_format); double dml_round(double a); unsigned int dml_round_to_multiple( unsigned int num, unsigned int multiple, bool up); -- cgit From e25cb588e6c8a948df147599de5469c3a95d3682 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 28 Sep 2017 11:24:06 +1000 Subject: amdgpu/dc: separate out some common code from bios parsers. This extracts the bios parser object id handling into a common file. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/bios/Makefile | 2 +- drivers/gpu/drm/amd/display/dc/bios/bios_parser.c | 274 +------------------- drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c | 284 +------------------- .../drm/amd/display/dc/bios/bios_parser_common.c | 288 +++++++++++++++++++++ .../drm/amd/display/dc/bios/bios_parser_common.h | 33 +++ 5 files changed, 324 insertions(+), 557 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/dc/bios/bios_parser_common.c create mode 100644 drivers/gpu/drm/amd/display/dc/bios/bios_parser_common.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/bios/Makefile b/drivers/gpu/drm/amd/display/dc/bios/Makefile index a26cc605462d..6ec815dce9cc 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/Makefile +++ b/drivers/gpu/drm/amd/display/dc/bios/Makefile @@ -2,7 +2,7 @@ # Makefile for the 'bios' sub-component of DAL. # It provides the parsing and executing controls for atom bios image. -BIOS = bios_parser.o bios_parser_interface.o bios_parser_helper.o command_table.o command_table_helper.o +BIOS = bios_parser.o bios_parser_interface.o bios_parser_helper.o command_table.o command_table_helper.o bios_parser_common.o BIOS += command_table2.o command_table_helper2.o bios_parser2.o diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c index 47d673a1f688..f6828f43eac6 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c @@ -41,6 +41,7 @@ #include "bios_parser_types_internal.h" #include "bios_parser_interface.h" +#include "bios_parser_common.h" /* TODO remove - only needed for default i2c speed */ #include "dc.h" @@ -57,18 +58,6 @@ static const uint8_t ext_display_connection_guid[NUMBER_OF_UCHAR_FOR_GUID] = { #define DATA_TABLES(table) (bp->master_data_tbl->ListOfDataTables.table) -static enum object_type object_type_from_bios_object_id( - uint32_t bios_object_id); -static struct graphics_object_id object_id_from_bios_object_id( - uint32_t bios_object_id); -static enum object_enum_id enum_id_from_bios_object_id(uint32_t bios_object_id); -static enum encoder_id encoder_id_from_bios_object_id(uint32_t bios_object_id); -static enum connector_id connector_id_from_bios_object_id( - uint32_t bios_object_id); -static uint32_t id_from_bios_object_id(enum object_type type, - uint32_t bios_object_id); -static uint32_t gpu_id_from_bios_object_id(uint32_t bios_object_id); -static enum generic_id generic_id_from_bios_object_id(uint32_t bios_object_id); static void get_atom_data_table_revision( ATOM_COMMON_TABLE_HEADER *atom_data_tbl, struct atom_data_revision *tbl_revision); @@ -2403,267 +2392,6 @@ static uint32_t get_dst_number_from_object(struct bios_parser *bp, return *number; } - -static struct graphics_object_id object_id_from_bios_object_id( - uint32_t bios_object_id) -{ - enum object_type type; - enum object_enum_id enum_id; - struct graphics_object_id go_id = { 0 }; - - type = object_type_from_bios_object_id(bios_object_id); - - if (OBJECT_TYPE_UNKNOWN == type) - return go_id; - - enum_id = enum_id_from_bios_object_id(bios_object_id); - - if (ENUM_ID_UNKNOWN == enum_id) - return go_id; - - go_id = dal_graphics_object_id_init( - id_from_bios_object_id(type, bios_object_id), enum_id, type); - - return go_id; -} - -static enum object_type object_type_from_bios_object_id(uint32_t bios_object_id) -{ - uint32_t bios_object_type = (bios_object_id & OBJECT_TYPE_MASK) - >> OBJECT_TYPE_SHIFT; - enum object_type object_type; - - switch (bios_object_type) { - case GRAPH_OBJECT_TYPE_GPU: - object_type = OBJECT_TYPE_GPU; - break; - case GRAPH_OBJECT_TYPE_ENCODER: - object_type = OBJECT_TYPE_ENCODER; - break; - case GRAPH_OBJECT_TYPE_CONNECTOR: - object_type = OBJECT_TYPE_CONNECTOR; - break; - case GRAPH_OBJECT_TYPE_ROUTER: - object_type = OBJECT_TYPE_ROUTER; - break; - case GRAPH_OBJECT_TYPE_GENERIC: - object_type = OBJECT_TYPE_GENERIC; - break; - default: - object_type = OBJECT_TYPE_UNKNOWN; - break; - } - - return object_type; -} - -static enum object_enum_id enum_id_from_bios_object_id(uint32_t bios_object_id) -{ - uint32_t bios_enum_id = - (bios_object_id & ENUM_ID_MASK) >> ENUM_ID_SHIFT; - enum object_enum_id id; - - switch (bios_enum_id) { - case GRAPH_OBJECT_ENUM_ID1: - id = ENUM_ID_1; - break; - case GRAPH_OBJECT_ENUM_ID2: - id = ENUM_ID_2; - break; - case GRAPH_OBJECT_ENUM_ID3: - id = ENUM_ID_3; - break; - case GRAPH_OBJECT_ENUM_ID4: - id = ENUM_ID_4; - break; - case GRAPH_OBJECT_ENUM_ID5: - id = ENUM_ID_5; - break; - case GRAPH_OBJECT_ENUM_ID6: - id = ENUM_ID_6; - break; - case GRAPH_OBJECT_ENUM_ID7: - id = ENUM_ID_7; - break; - default: - id = ENUM_ID_UNKNOWN; - break; - } - - return id; -} - -static uint32_t id_from_bios_object_id(enum object_type type, - uint32_t bios_object_id) -{ - switch (type) { - case OBJECT_TYPE_GPU: - return gpu_id_from_bios_object_id(bios_object_id); - case OBJECT_TYPE_ENCODER: - return (uint32_t)encoder_id_from_bios_object_id(bios_object_id); - case OBJECT_TYPE_CONNECTOR: - return (uint32_t)connector_id_from_bios_object_id( - bios_object_id); - case OBJECT_TYPE_GENERIC: - return generic_id_from_bios_object_id(bios_object_id); - default: - return 0; - } -} - -static enum connector_id connector_id_from_bios_object_id( - uint32_t bios_object_id) -{ - uint32_t bios_connector_id = gpu_id_from_bios_object_id(bios_object_id); - - enum connector_id id; - - switch (bios_connector_id) { - case CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I: - id = CONNECTOR_ID_SINGLE_LINK_DVII; - break; - case CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I: - id = CONNECTOR_ID_DUAL_LINK_DVII; - break; - case CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D: - id = CONNECTOR_ID_SINGLE_LINK_DVID; - break; - case CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D: - id = CONNECTOR_ID_DUAL_LINK_DVID; - break; - case CONNECTOR_OBJECT_ID_VGA: - id = CONNECTOR_ID_VGA; - break; - case CONNECTOR_OBJECT_ID_HDMI_TYPE_A: - id = CONNECTOR_ID_HDMI_TYPE_A; - break; - case CONNECTOR_OBJECT_ID_LVDS: - id = CONNECTOR_ID_LVDS; - break; - case CONNECTOR_OBJECT_ID_PCIE_CONNECTOR: - id = CONNECTOR_ID_PCIE; - break; - case CONNECTOR_OBJECT_ID_HARDCODE_DVI: - id = CONNECTOR_ID_HARDCODE_DVI; - break; - case CONNECTOR_OBJECT_ID_DISPLAYPORT: - id = CONNECTOR_ID_DISPLAY_PORT; - break; - case CONNECTOR_OBJECT_ID_eDP: - id = CONNECTOR_ID_EDP; - break; - case CONNECTOR_OBJECT_ID_MXM: - id = CONNECTOR_ID_MXM; - break; - default: - id = CONNECTOR_ID_UNKNOWN; - break; - } - - return id; -} - -static enum encoder_id encoder_id_from_bios_object_id(uint32_t bios_object_id) -{ - uint32_t bios_encoder_id = gpu_id_from_bios_object_id(bios_object_id); - enum encoder_id id; - - switch (bios_encoder_id) { - case ENCODER_OBJECT_ID_INTERNAL_LVDS: - id = ENCODER_ID_INTERNAL_LVDS; - break; - case ENCODER_OBJECT_ID_INTERNAL_TMDS1: - id = ENCODER_ID_INTERNAL_TMDS1; - break; - case ENCODER_OBJECT_ID_INTERNAL_TMDS2: - id = ENCODER_ID_INTERNAL_TMDS2; - break; - case ENCODER_OBJECT_ID_INTERNAL_DAC1: - id = ENCODER_ID_INTERNAL_DAC1; - break; - case ENCODER_OBJECT_ID_INTERNAL_DAC2: - id = ENCODER_ID_INTERNAL_DAC2; - break; - case ENCODER_OBJECT_ID_INTERNAL_LVTM1: - id = ENCODER_ID_INTERNAL_LVTM1; - break; - case ENCODER_OBJECT_ID_HDMI_INTERNAL: - id = ENCODER_ID_INTERNAL_HDMI; - break; - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: - id = ENCODER_ID_INTERNAL_KLDSCP_TMDS1; - break; - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: - id = ENCODER_ID_INTERNAL_KLDSCP_DAC1; - break; - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: - id = ENCODER_ID_INTERNAL_KLDSCP_DAC2; - break; - case ENCODER_OBJECT_ID_MVPU_FPGA: - id = ENCODER_ID_EXTERNAL_MVPU_FPGA; - break; - case ENCODER_OBJECT_ID_INTERNAL_DDI: - id = ENCODER_ID_INTERNAL_DDI; - break; - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: - id = ENCODER_ID_INTERNAL_UNIPHY; - break; - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: - id = ENCODER_ID_INTERNAL_KLDSCP_LVTMA; - break; - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: - id = ENCODER_ID_INTERNAL_UNIPHY1; - break; - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: - id = ENCODER_ID_INTERNAL_UNIPHY2; - break; - case ENCODER_OBJECT_ID_ALMOND: /* ENCODER_OBJECT_ID_NUTMEG */ - id = ENCODER_ID_EXTERNAL_NUTMEG; - break; - case ENCODER_OBJECT_ID_TRAVIS: - id = ENCODER_ID_EXTERNAL_TRAVIS; - break; - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3: - id = ENCODER_ID_INTERNAL_UNIPHY3; - break; - default: - id = ENCODER_ID_UNKNOWN; - ASSERT(0); - break; - } - - return id; -} - -uint32_t gpu_id_from_bios_object_id(uint32_t bios_object_id) -{ - return (bios_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; -} - -enum generic_id generic_id_from_bios_object_id(uint32_t bios_object_id) -{ - uint32_t bios_generic_id = gpu_id_from_bios_object_id(bios_object_id); - - enum generic_id id; - - switch (bios_generic_id) { - case GENERIC_OBJECT_ID_MXM_OPM: - id = GENERIC_ID_MXM_OPM; - break; - case GENERIC_OBJECT_ID_GLSYNC: - id = GENERIC_ID_GLSYNC; - break; - case GENERIC_OBJECT_ID_STEREO_PIN: - id = GENERIC_ID_STEREO; - break; - default: - id = GENERIC_ID_UNKNOWN; - break; - } - - return id; -} - static struct device_id device_type_from_device_id(uint16_t device_id) { diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c index 3f8e605efde9..852bb0d2eb8d 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -25,8 +25,6 @@ #include "dm_services.h" -#define _BIOS_PARSER_2_ - #include "ObjectID.h" #include "atomfirmware.h" @@ -44,6 +42,7 @@ #include "bios_parser_types_internal2.h" #include "bios_parser_interface.h" +#include "bios_parser_common.h" #define LAST_RECORD_TYPE 0xff @@ -54,26 +53,6 @@ struct i2c_id_config_access { uint8_t ucAccess; }; -static enum object_type object_type_from_bios_object_id( - uint32_t bios_object_id); - -static enum object_enum_id enum_id_from_bios_object_id(uint32_t bios_object_id); - -static struct graphics_object_id object_id_from_bios_object_id( - uint32_t bios_object_id); - -static uint32_t id_from_bios_object_id(enum object_type type, - uint32_t bios_object_id); - -static uint32_t gpu_id_from_bios_object_id(uint32_t bios_object_id); - -static enum encoder_id encoder_id_from_bios_object_id(uint32_t bios_object_id); - -static enum connector_id connector_id_from_bios_object_id( - uint32_t bios_object_id); - -static enum generic_id generic_id_from_bios_object_id(uint32_t bios_object_id); - static enum bp_result get_gpio_i2c_info(struct bios_parser *bp, struct atom_i2c_record *record, struct graphics_object_i2c_info *info); @@ -148,267 +127,6 @@ static void get_atom_data_table_revision( (uint32_t) atom_data_tbl->content_revision & 0x3f; } -static struct graphics_object_id object_id_from_bios_object_id( - uint32_t bios_object_id) -{ - enum object_type type; - enum object_enum_id enum_id; - struct graphics_object_id go_id = { 0 }; - - type = object_type_from_bios_object_id(bios_object_id); - - if (type == OBJECT_TYPE_UNKNOWN) - return go_id; - - enum_id = enum_id_from_bios_object_id(bios_object_id); - - if (enum_id == ENUM_ID_UNKNOWN) - return go_id; - - go_id = dal_graphics_object_id_init( - id_from_bios_object_id(type, bios_object_id), - enum_id, type); - - return go_id; -} - -static enum object_type object_type_from_bios_object_id(uint32_t bios_object_id) -{ - uint32_t bios_object_type = (bios_object_id & OBJECT_TYPE_MASK) - >> OBJECT_TYPE_SHIFT; - enum object_type object_type; - - switch (bios_object_type) { - case GRAPH_OBJECT_TYPE_GPU: - object_type = OBJECT_TYPE_GPU; - break; - case GRAPH_OBJECT_TYPE_ENCODER: - object_type = OBJECT_TYPE_ENCODER; - break; - case GRAPH_OBJECT_TYPE_CONNECTOR: - object_type = OBJECT_TYPE_CONNECTOR; - break; - case GRAPH_OBJECT_TYPE_ROUTER: - object_type = OBJECT_TYPE_ROUTER; - break; - case GRAPH_OBJECT_TYPE_GENERIC: - object_type = OBJECT_TYPE_GENERIC; - break; - default: - object_type = OBJECT_TYPE_UNKNOWN; - break; - } - - return object_type; -} - -static enum object_enum_id enum_id_from_bios_object_id(uint32_t bios_object_id) -{ - uint32_t bios_enum_id = - (bios_object_id & ENUM_ID_MASK) >> ENUM_ID_SHIFT; - enum object_enum_id id; - - switch (bios_enum_id) { - case GRAPH_OBJECT_ENUM_ID1: - id = ENUM_ID_1; - break; - case GRAPH_OBJECT_ENUM_ID2: - id = ENUM_ID_2; - break; - case GRAPH_OBJECT_ENUM_ID3: - id = ENUM_ID_3; - break; - case GRAPH_OBJECT_ENUM_ID4: - id = ENUM_ID_4; - break; - case GRAPH_OBJECT_ENUM_ID5: - id = ENUM_ID_5; - break; - case GRAPH_OBJECT_ENUM_ID6: - id = ENUM_ID_6; - break; - case GRAPH_OBJECT_ENUM_ID7: - id = ENUM_ID_7; - break; - default: - id = ENUM_ID_UNKNOWN; - break; - } - - return id; -} - -static uint32_t id_from_bios_object_id(enum object_type type, - uint32_t bios_object_id) -{ - switch (type) { - case OBJECT_TYPE_GPU: - return gpu_id_from_bios_object_id(bios_object_id); - case OBJECT_TYPE_ENCODER: - return (uint32_t)encoder_id_from_bios_object_id(bios_object_id); - case OBJECT_TYPE_CONNECTOR: - return (uint32_t)connector_id_from_bios_object_id( - bios_object_id); - case OBJECT_TYPE_GENERIC: - return generic_id_from_bios_object_id(bios_object_id); - default: - return 0; - } -} - -uint32_t gpu_id_from_bios_object_id(uint32_t bios_object_id) -{ - return (bios_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; -} - -static enum encoder_id encoder_id_from_bios_object_id(uint32_t bios_object_id) -{ - uint32_t bios_encoder_id = gpu_id_from_bios_object_id(bios_object_id); - enum encoder_id id; - - switch (bios_encoder_id) { - case ENCODER_OBJECT_ID_INTERNAL_LVDS: - id = ENCODER_ID_INTERNAL_LVDS; - break; - case ENCODER_OBJECT_ID_INTERNAL_TMDS1: - id = ENCODER_ID_INTERNAL_TMDS1; - break; - case ENCODER_OBJECT_ID_INTERNAL_TMDS2: - id = ENCODER_ID_INTERNAL_TMDS2; - break; - case ENCODER_OBJECT_ID_INTERNAL_DAC1: - id = ENCODER_ID_INTERNAL_DAC1; - break; - case ENCODER_OBJECT_ID_INTERNAL_DAC2: - id = ENCODER_ID_INTERNAL_DAC2; - break; - case ENCODER_OBJECT_ID_INTERNAL_LVTM1: - id = ENCODER_ID_INTERNAL_LVTM1; - break; - case ENCODER_OBJECT_ID_HDMI_INTERNAL: - id = ENCODER_ID_INTERNAL_HDMI; - break; - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: - id = ENCODER_ID_INTERNAL_KLDSCP_TMDS1; - break; - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: - id = ENCODER_ID_INTERNAL_KLDSCP_DAC1; - break; - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: - id = ENCODER_ID_INTERNAL_KLDSCP_DAC2; - break; - case ENCODER_OBJECT_ID_MVPU_FPGA: - id = ENCODER_ID_EXTERNAL_MVPU_FPGA; - break; - case ENCODER_OBJECT_ID_INTERNAL_DDI: - id = ENCODER_ID_INTERNAL_DDI; - break; - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: - id = ENCODER_ID_INTERNAL_UNIPHY; - break; - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: - id = ENCODER_ID_INTERNAL_KLDSCP_LVTMA; - break; - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: - id = ENCODER_ID_INTERNAL_UNIPHY1; - break; - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: - id = ENCODER_ID_INTERNAL_UNIPHY2; - break; - case ENCODER_OBJECT_ID_ALMOND: /* ENCODER_OBJECT_ID_NUTMEG */ - id = ENCODER_ID_EXTERNAL_NUTMEG; - break; - case ENCODER_OBJECT_ID_TRAVIS: - id = ENCODER_ID_EXTERNAL_TRAVIS; - break; - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3: - id = ENCODER_ID_INTERNAL_UNIPHY3; - break; - default: - id = ENCODER_ID_UNKNOWN; - ASSERT(0); - break; - } - - return id; -} - -static enum connector_id connector_id_from_bios_object_id( - uint32_t bios_object_id) -{ - uint32_t bios_connector_id = gpu_id_from_bios_object_id(bios_object_id); - - enum connector_id id; - - switch (bios_connector_id) { - case CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I: - id = CONNECTOR_ID_SINGLE_LINK_DVII; - break; - case CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I: - id = CONNECTOR_ID_DUAL_LINK_DVII; - break; - case CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D: - id = CONNECTOR_ID_SINGLE_LINK_DVID; - break; - case CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D: - id = CONNECTOR_ID_DUAL_LINK_DVID; - break; - case CONNECTOR_OBJECT_ID_VGA: - id = CONNECTOR_ID_VGA; - break; - case CONNECTOR_OBJECT_ID_HDMI_TYPE_A: - id = CONNECTOR_ID_HDMI_TYPE_A; - break; - case CONNECTOR_OBJECT_ID_LVDS: - id = CONNECTOR_ID_LVDS; - break; - case CONNECTOR_OBJECT_ID_PCIE_CONNECTOR: - id = CONNECTOR_ID_PCIE; - break; - case CONNECTOR_OBJECT_ID_HARDCODE_DVI: - id = CONNECTOR_ID_HARDCODE_DVI; - break; - case CONNECTOR_OBJECT_ID_DISPLAYPORT: - id = CONNECTOR_ID_DISPLAY_PORT; - break; - case CONNECTOR_OBJECT_ID_eDP: - id = CONNECTOR_ID_EDP; - break; - case CONNECTOR_OBJECT_ID_MXM: - id = CONNECTOR_ID_MXM; - break; - default: - id = CONNECTOR_ID_UNKNOWN; - break; - } - - return id; -} - -enum generic_id generic_id_from_bios_object_id(uint32_t bios_object_id) -{ - uint32_t bios_generic_id = gpu_id_from_bios_object_id(bios_object_id); - - enum generic_id id; - - switch (bios_generic_id) { - case GENERIC_OBJECT_ID_MXM_OPM: - id = GENERIC_ID_MXM_OPM; - break; - case GENERIC_OBJECT_ID_GLSYNC: - id = GENERIC_ID_GLSYNC; - break; - case GENERIC_OBJECT_ID_STEREO_PIN: - id = GENERIC_ID_STEREO; - break; - default: - id = GENERIC_ID_UNKNOWN; - break; - } - - return id; -} - /* BIOS oject table displaypath is per connector. * There is extra path not for connector. BIOS fill its encoderid as 0 */ diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_common.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_common.c new file mode 100644 index 000000000000..a8cb039d2572 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_common.c @@ -0,0 +1,288 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "bios_parser_common.h" +#include "include/grph_object_ctrl_defs.h" + +static enum object_type object_type_from_bios_object_id(uint32_t bios_object_id) +{ + uint32_t bios_object_type = (bios_object_id & OBJECT_TYPE_MASK) + >> OBJECT_TYPE_SHIFT; + enum object_type object_type; + + switch (bios_object_type) { + case GRAPH_OBJECT_TYPE_GPU: + object_type = OBJECT_TYPE_GPU; + break; + case GRAPH_OBJECT_TYPE_ENCODER: + object_type = OBJECT_TYPE_ENCODER; + break; + case GRAPH_OBJECT_TYPE_CONNECTOR: + object_type = OBJECT_TYPE_CONNECTOR; + break; + case GRAPH_OBJECT_TYPE_ROUTER: + object_type = OBJECT_TYPE_ROUTER; + break; + case GRAPH_OBJECT_TYPE_GENERIC: + object_type = OBJECT_TYPE_GENERIC; + break; + default: + object_type = OBJECT_TYPE_UNKNOWN; + break; + } + + return object_type; +} + +static enum object_enum_id enum_id_from_bios_object_id(uint32_t bios_object_id) +{ + uint32_t bios_enum_id = + (bios_object_id & ENUM_ID_MASK) >> ENUM_ID_SHIFT; + enum object_enum_id id; + + switch (bios_enum_id) { + case GRAPH_OBJECT_ENUM_ID1: + id = ENUM_ID_1; + break; + case GRAPH_OBJECT_ENUM_ID2: + id = ENUM_ID_2; + break; + case GRAPH_OBJECT_ENUM_ID3: + id = ENUM_ID_3; + break; + case GRAPH_OBJECT_ENUM_ID4: + id = ENUM_ID_4; + break; + case GRAPH_OBJECT_ENUM_ID5: + id = ENUM_ID_5; + break; + case GRAPH_OBJECT_ENUM_ID6: + id = ENUM_ID_6; + break; + case GRAPH_OBJECT_ENUM_ID7: + id = ENUM_ID_7; + break; + default: + id = ENUM_ID_UNKNOWN; + break; + } + + return id; +} + +static uint32_t gpu_id_from_bios_object_id(uint32_t bios_object_id) +{ + return (bios_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; +} + +static enum encoder_id encoder_id_from_bios_object_id(uint32_t bios_object_id) +{ + uint32_t bios_encoder_id = gpu_id_from_bios_object_id(bios_object_id); + enum encoder_id id; + + switch (bios_encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_LVDS: + id = ENCODER_ID_INTERNAL_LVDS; + break; + case ENCODER_OBJECT_ID_INTERNAL_TMDS1: + id = ENCODER_ID_INTERNAL_TMDS1; + break; + case ENCODER_OBJECT_ID_INTERNAL_TMDS2: + id = ENCODER_ID_INTERNAL_TMDS2; + break; + case ENCODER_OBJECT_ID_INTERNAL_DAC1: + id = ENCODER_ID_INTERNAL_DAC1; + break; + case ENCODER_OBJECT_ID_INTERNAL_DAC2: + id = ENCODER_ID_INTERNAL_DAC2; + break; + case ENCODER_OBJECT_ID_INTERNAL_LVTM1: + id = ENCODER_ID_INTERNAL_LVTM1; + break; + case ENCODER_OBJECT_ID_HDMI_INTERNAL: + id = ENCODER_ID_INTERNAL_HDMI; + break; + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: + id = ENCODER_ID_INTERNAL_KLDSCP_TMDS1; + break; + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: + id = ENCODER_ID_INTERNAL_KLDSCP_DAC1; + break; + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: + id = ENCODER_ID_INTERNAL_KLDSCP_DAC2; + break; + case ENCODER_OBJECT_ID_MVPU_FPGA: + id = ENCODER_ID_EXTERNAL_MVPU_FPGA; + break; + case ENCODER_OBJECT_ID_INTERNAL_DDI: + id = ENCODER_ID_INTERNAL_DDI; + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: + id = ENCODER_ID_INTERNAL_UNIPHY; + break; + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: + id = ENCODER_ID_INTERNAL_KLDSCP_LVTMA; + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: + id = ENCODER_ID_INTERNAL_UNIPHY1; + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: + id = ENCODER_ID_INTERNAL_UNIPHY2; + break; + case ENCODER_OBJECT_ID_ALMOND: /* ENCODER_OBJECT_ID_NUTMEG */ + id = ENCODER_ID_EXTERNAL_NUTMEG; + break; + case ENCODER_OBJECT_ID_TRAVIS: + id = ENCODER_ID_EXTERNAL_TRAVIS; + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3: + id = ENCODER_ID_INTERNAL_UNIPHY3; + break; + default: + id = ENCODER_ID_UNKNOWN; + ASSERT(0); + break; + } + + return id; +} + +static enum connector_id connector_id_from_bios_object_id( + uint32_t bios_object_id) +{ + uint32_t bios_connector_id = gpu_id_from_bios_object_id(bios_object_id); + + enum connector_id id; + + switch (bios_connector_id) { + case CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I: + id = CONNECTOR_ID_SINGLE_LINK_DVII; + break; + case CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I: + id = CONNECTOR_ID_DUAL_LINK_DVII; + break; + case CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D: + id = CONNECTOR_ID_SINGLE_LINK_DVID; + break; + case CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D: + id = CONNECTOR_ID_DUAL_LINK_DVID; + break; + case CONNECTOR_OBJECT_ID_VGA: + id = CONNECTOR_ID_VGA; + break; + case CONNECTOR_OBJECT_ID_HDMI_TYPE_A: + id = CONNECTOR_ID_HDMI_TYPE_A; + break; + case CONNECTOR_OBJECT_ID_LVDS: + id = CONNECTOR_ID_LVDS; + break; + case CONNECTOR_OBJECT_ID_PCIE_CONNECTOR: + id = CONNECTOR_ID_PCIE; + break; + case CONNECTOR_OBJECT_ID_HARDCODE_DVI: + id = CONNECTOR_ID_HARDCODE_DVI; + break; + case CONNECTOR_OBJECT_ID_DISPLAYPORT: + id = CONNECTOR_ID_DISPLAY_PORT; + break; + case CONNECTOR_OBJECT_ID_eDP: + id = CONNECTOR_ID_EDP; + break; + case CONNECTOR_OBJECT_ID_MXM: + id = CONNECTOR_ID_MXM; + break; + default: + id = CONNECTOR_ID_UNKNOWN; + break; + } + + return id; +} + +static enum generic_id generic_id_from_bios_object_id(uint32_t bios_object_id) +{ + uint32_t bios_generic_id = gpu_id_from_bios_object_id(bios_object_id); + + enum generic_id id; + + switch (bios_generic_id) { + case GENERIC_OBJECT_ID_MXM_OPM: + id = GENERIC_ID_MXM_OPM; + break; + case GENERIC_OBJECT_ID_GLSYNC: + id = GENERIC_ID_GLSYNC; + break; + case GENERIC_OBJECT_ID_STEREO_PIN: + id = GENERIC_ID_STEREO; + break; + default: + id = GENERIC_ID_UNKNOWN; + break; + } + + return id; +} + +static uint32_t id_from_bios_object_id(enum object_type type, + uint32_t bios_object_id) +{ + switch (type) { + case OBJECT_TYPE_GPU: + return gpu_id_from_bios_object_id(bios_object_id); + case OBJECT_TYPE_ENCODER: + return (uint32_t)encoder_id_from_bios_object_id(bios_object_id); + case OBJECT_TYPE_CONNECTOR: + return (uint32_t)connector_id_from_bios_object_id( + bios_object_id); + case OBJECT_TYPE_GENERIC: + return generic_id_from_bios_object_id(bios_object_id); + default: + return 0; + } +} + +struct graphics_object_id object_id_from_bios_object_id(uint32_t bios_object_id) +{ + enum object_type type; + enum object_enum_id enum_id; + struct graphics_object_id go_id = { 0 }; + + type = object_type_from_bios_object_id(bios_object_id); + + if (OBJECT_TYPE_UNKNOWN == type) + return go_id; + + enum_id = enum_id_from_bios_object_id(bios_object_id); + + if (ENUM_ID_UNKNOWN == enum_id) + return go_id; + + go_id = dal_graphics_object_id_init( + id_from_bios_object_id(type, bios_object_id), enum_id, type); + + return go_id; +} + + diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_common.h b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_common.h new file mode 100644 index 000000000000..a076c61dfae4 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_common.h @@ -0,0 +1,33 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __BIOS_PARSER_COMMON_H__ +#define __BIOS_PARSER_COMMON_H__ + +#include "dm_services.h" +#include "ObjectID.h" + +struct graphics_object_id object_id_from_bios_object_id(uint32_t bios_object_id); +#endif -- cgit From 5e0adbff084f33202db36be798c583a115990392 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 28 Sep 2017 12:29:53 +1000 Subject: amdgpu/dc: drop dml display_mode_support.c (v2) This code isn't used, and this function is huge, reimport later if going to be used. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/Makefile | 4 +- .../drm/amd/display/dc/dml/display_mode_support.c | 2327 -------------------- .../drm/amd/display/dc/dml/display_mode_support.h | 5 - 3 files changed, 1 insertion(+), 2335 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dml/Makefile b/drivers/gpu/drm/amd/display/dc/dml/Makefile index a6bf36466497..ec712d727665 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dml/Makefile @@ -10,12 +10,10 @@ CFLAGS_display_rq_dlg_helpers.o := -mhard-float -msse -mpreferred-stack-boundary CFLAGS_display_watermark.o := -mhard-float -msse -mpreferred-stack-boundary=4 CFLAGS_soc_bounding_box.o := -mhard-float -msse -mpreferred-stack-boundary=4 CFLAGS_dml_common_defs.o := -mhard-float -msse -mpreferred-stack-boundary=4 -CFLAGS_display_mode_support.o := -mhard-float -msse -mpreferred-stack-boundary=4 - DML = display_mode_lib.o display_rq_dlg_calc.o \ display_rq_dlg_helpers.o display_watermark.o \ - soc_bounding_box.o dml_common_defs.o display_mode_support.o + soc_bounding_box.o dml_common_defs.o AMD_DAL_DML = $(addprefix $(AMDDALPATH)/dc/dml/,$(DML)) diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c deleted file mode 100644 index ac573568c10a..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c +++ /dev/null @@ -1,2327 +0,0 @@ -/* - * Copyright 2017 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "display_mode_support.h" -#include "display_mode_lib.h" - -#include "dml_inline_defs.h" -int dml_ms_check( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - int num_pipes) -{ - struct _vcs_dpi_ip_params_st *ip; - struct _vcs_dpi_soc_bounding_box_st *soc; - struct _vcs_dpi_mode_evaluation_st *me; - struct dml_ms_internal_vars *v; - int num_planes, i, j, ij, k, ijk; - - ip = &(mode_lib->ip); - soc = &(mode_lib->soc); - me = &(mode_lib->me); - v = &(mode_lib->vars); - num_planes = dml_wm_e2e_to_wm(mode_lib, e2e, num_pipes, v->planes); - - //instantiating variables to zero - v->MacroTileBlockWidthC = 0; - v->SwathWidthGranularityC = 0; - - v->DCFCLKPerState[5] = 0; - v->DCFCLKPerState[4] = 0; - v->DCFCLKPerState[3] = 0; - v->DCFCLKPerState[2] = 0; - v->DCFCLKPerState[1] = 0; - v->DCFCLKPerState[0] = 0; - - if (soc->vmin.dcfclk_mhz > 0) { - v->DCFCLKPerState[5] = soc->vmin.dcfclk_mhz; - v->DCFCLKPerState[4] = soc->vmin.dcfclk_mhz; - v->DCFCLKPerState[3] = soc->vmin.dcfclk_mhz; - v->DCFCLKPerState[2] = soc->vmin.dcfclk_mhz; - v->DCFCLKPerState[1] = soc->vmin.dcfclk_mhz; - v->DCFCLKPerState[0] = soc->vmin.dcfclk_mhz; - } - - if (soc->vmid.dcfclk_mhz > 0) { - v->DCFCLKPerState[5] = soc->vmid.dcfclk_mhz; - v->DCFCLKPerState[4] = soc->vmid.dcfclk_mhz; - v->DCFCLKPerState[3] = soc->vmid.dcfclk_mhz; - v->DCFCLKPerState[2] = soc->vmid.dcfclk_mhz; - v->DCFCLKPerState[1] = soc->vmid.dcfclk_mhz; - } - - if (soc->vnom.dcfclk_mhz > 0) { - v->DCFCLKPerState[5] = soc->vnom.dcfclk_mhz; - v->DCFCLKPerState[4] = soc->vnom.dcfclk_mhz; - v->DCFCLKPerState[3] = soc->vnom.dcfclk_mhz; - v->DCFCLKPerState[2] = soc->vnom.dcfclk_mhz; - } - - if (soc->vmax.dcfclk_mhz > 0) { - v->DCFCLKPerState[5] = soc->vmax.dcfclk_mhz; - v->DCFCLKPerState[4] = soc->vmax.dcfclk_mhz; - v->DCFCLKPerState[3] = soc->vmax.dcfclk_mhz; - } - - v->FabricAndDRAMBandwidthPerState[5] = 0; - v->FabricAndDRAMBandwidthPerState[4] = 0; - v->FabricAndDRAMBandwidthPerState[3] = 0; - v->FabricAndDRAMBandwidthPerState[2] = 0; - v->FabricAndDRAMBandwidthPerState[1] = 0; - v->FabricAndDRAMBandwidthPerState[0] = 0; - - if (soc->vmin.dram_bw_per_chan_gbps > 0) { - v->FabricAndDRAMBandwidthPerState[5] = soc->vmin.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[4] = soc->vmin.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[3] = soc->vmin.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[2] = soc->vmin.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[1] = soc->vmin.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[0] = soc->vmin.dram_bw_per_chan_gbps; - } - - if (soc->vmid.dram_bw_per_chan_gbps > 0) { - v->FabricAndDRAMBandwidthPerState[5] = soc->vmid.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[4] = soc->vmid.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[3] = soc->vmid.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[2] = soc->vmid.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[1] = soc->vmid.dram_bw_per_chan_gbps; - } - - if (soc->vnom.dram_bw_per_chan_gbps > 0) { - v->FabricAndDRAMBandwidthPerState[5] = soc->vnom.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[4] = soc->vnom.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[3] = soc->vnom.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[2] = soc->vnom.dram_bw_per_chan_gbps; - } - - if (soc->vmax.dram_bw_per_chan_gbps > 0) { - v->FabricAndDRAMBandwidthPerState[5] = soc->vmax.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[4] = soc->vmax.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[3] = soc->vmax.dram_bw_per_chan_gbps; - } - - v->PHYCLKPerState[5] = 0; - v->PHYCLKPerState[4] = 0; - v->PHYCLKPerState[3] = 0; - v->PHYCLKPerState[2] = 0; - v->PHYCLKPerState[1] = 0; - v->PHYCLKPerState[0] = 0; - - if (soc->vmin.phyclk_mhz > 0) { - v->PHYCLKPerState[5] = soc->vmin.phyclk_mhz; - v->PHYCLKPerState[4] = soc->vmin.phyclk_mhz; - v->PHYCLKPerState[3] = soc->vmin.phyclk_mhz; - v->PHYCLKPerState[2] = soc->vmin.phyclk_mhz; - v->PHYCLKPerState[1] = soc->vmin.phyclk_mhz; - v->PHYCLKPerState[0] = soc->vmin.phyclk_mhz; - } - - if (soc->vmid.phyclk_mhz > 0) { - v->PHYCLKPerState[5] = soc->vmid.phyclk_mhz; - v->PHYCLKPerState[4] = soc->vmid.phyclk_mhz; - v->PHYCLKPerState[3] = soc->vmid.phyclk_mhz; - v->PHYCLKPerState[2] = soc->vmid.phyclk_mhz; - v->PHYCLKPerState[1] = soc->vmid.phyclk_mhz; - } - - if (soc->vnom.phyclk_mhz > 0) { - v->PHYCLKPerState[5] = soc->vnom.phyclk_mhz; - v->PHYCLKPerState[4] = soc->vnom.phyclk_mhz; - v->PHYCLKPerState[3] = soc->vnom.phyclk_mhz; - v->PHYCLKPerState[2] = soc->vnom.phyclk_mhz; - } - - if (soc->vmax.phyclk_mhz > 0) { - v->PHYCLKPerState[5] = soc->vmax.phyclk_mhz; - v->PHYCLKPerState[4] = soc->vmax.phyclk_mhz; - v->PHYCLKPerState[3] = soc->vmax.phyclk_mhz; - } - - v->MaxDispclk[5] = 0; - v->MaxDispclk[4] = 0; - v->MaxDispclk[3] = 0; - v->MaxDispclk[2] = 0; - v->MaxDispclk[1] = 0; - v->MaxDispclk[0] = 0; - - if (soc->vmin.dispclk_mhz > 0) { - v->MaxDispclk[5] = soc->vmin.dispclk_mhz; - v->MaxDispclk[4] = soc->vmin.dispclk_mhz; - v->MaxDispclk[3] = soc->vmin.dispclk_mhz; - v->MaxDispclk[2] = soc->vmin.dispclk_mhz; - v->MaxDispclk[1] = soc->vmin.dispclk_mhz; - v->MaxDispclk[0] = soc->vmin.dispclk_mhz; - } - - if (soc->vmid.dispclk_mhz > 0) { - v->MaxDispclk[5] = soc->vmid.dispclk_mhz; - v->MaxDispclk[4] = soc->vmid.dispclk_mhz; - v->MaxDispclk[3] = soc->vmid.dispclk_mhz; - v->MaxDispclk[2] = soc->vmid.dispclk_mhz; - v->MaxDispclk[1] = soc->vmid.dispclk_mhz; - } - - if (soc->vnom.dispclk_mhz > 0) { - v->MaxDispclk[5] = soc->vnom.dispclk_mhz; - v->MaxDispclk[4] = soc->vnom.dispclk_mhz; - v->MaxDispclk[3] = soc->vnom.dispclk_mhz; - v->MaxDispclk[2] = soc->vnom.dispclk_mhz; - } - - if (soc->vmax.dispclk_mhz > 0) { - v->MaxDispclk[5] = soc->vmax.dispclk_mhz; - v->MaxDispclk[4] = soc->vmax.dispclk_mhz; - v->MaxDispclk[3] = soc->vmax.dispclk_mhz; - } - - v->MaxDppclk[5] = 0; - v->MaxDppclk[4] = 0; - v->MaxDppclk[3] = 0; - v->MaxDppclk[2] = 0; - v->MaxDppclk[1] = 0; - v->MaxDppclk[0] = 0; - - if (soc->vmin.dppclk_mhz > 0) { - v->MaxDppclk[5] = soc->vmin.dppclk_mhz; - v->MaxDppclk[4] = soc->vmin.dppclk_mhz; - v->MaxDppclk[3] = soc->vmin.dppclk_mhz; - v->MaxDppclk[2] = soc->vmin.dppclk_mhz; - v->MaxDppclk[1] = soc->vmin.dppclk_mhz; - v->MaxDppclk[0] = soc->vmin.dppclk_mhz; - } - - if (soc->vmid.dppclk_mhz > 0) { - v->MaxDppclk[5] = soc->vmid.dppclk_mhz; - v->MaxDppclk[4] = soc->vmid.dppclk_mhz; - v->MaxDppclk[3] = soc->vmid.dppclk_mhz; - v->MaxDppclk[2] = soc->vmid.dppclk_mhz; - v->MaxDppclk[1] = soc->vmid.dppclk_mhz; - } - - if (soc->vnom.dppclk_mhz > 0) { - v->MaxDppclk[5] = soc->vnom.dppclk_mhz; - v->MaxDppclk[4] = soc->vnom.dppclk_mhz; - v->MaxDppclk[3] = soc->vnom.dppclk_mhz; - v->MaxDppclk[2] = soc->vnom.dppclk_mhz; - } - - if (soc->vmax.dppclk_mhz > 0) { - v->MaxDppclk[5] = soc->vmax.dppclk_mhz; - v->MaxDppclk[4] = soc->vmax.dppclk_mhz; - v->MaxDppclk[3] = soc->vmax.dppclk_mhz; - } - - if (me->voltage_override == dm_vmax) { - v->VoltageOverrideLevel = NumberOfStates - 1; - } else if (me->voltage_override == dm_vnom) { - v->VoltageOverrideLevel = NumberOfStates - 2; - } else if (me->voltage_override == dm_vmid) { - v->VoltageOverrideLevel = NumberOfStates - 3; - } else { - v->VoltageOverrideLevel = 0; - } - - // Scale Ratio Support Check - - v->ScaleRatioSupport = 1; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = - e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; - struct _vcs_dpi_scaler_taps_st scale_taps = - e2e[v->planes[k].e2e_index].pipe.scale_taps; - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - - if (scale_ratio_depth.hscl_ratio > ip->max_hscl_ratio - || scale_ratio_depth.vscl_ratio > ip->max_vscl_ratio - || scale_ratio_depth.hscl_ratio > scale_taps.htaps - || scale_ratio_depth.vscl_ratio > scale_taps.vtaps - || (src.source_format != dm_444_64 && src.source_format != dm_444_32 - && src.source_format != dm_444_16 - && ((scale_ratio_depth.hscl_ratio / 2 - > scale_taps.htaps_c) - || (scale_ratio_depth.vscl_ratio / 2 - > scale_taps.vtaps_c)))) - - { - v->ScaleRatioSupport = 0; - } - } - - // Source Format, Pixel Format and Scan Support Check - - v->SourceFormatPixelAndScanSupport = 1; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - - if ((src.sw_mode == dm_sw_linear && src.source_scan != dm_horz) - || ((src.sw_mode == dm_sw_4kb_d || src.sw_mode == dm_sw_4kb_d_x - || src.sw_mode == dm_sw_64kb_d - || src.sw_mode == dm_sw_64kb_d_t - || src.sw_mode == dm_sw_64kb_d_x - || src.sw_mode == dm_sw_var_d - || src.sw_mode == dm_sw_var_d_x) - && (src.source_format != dm_444_64))) { - v->SourceFormatPixelAndScanSupport = 0; - } - } - - // Bandwidth Support Check - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - - if (src.source_scan == dm_horz) { - v->SwathWidthYSingleDPP[k] = src.viewport_width; - } else { - v->SwathWidthYSingleDPP[k] = src.viewport_height; - } - - if (src.source_format == dm_444_64) { - v->BytePerPixelInDETY[k] = 8; - v->BytePerPixelInDETC[k] = 0; - } else if (src.source_format == dm_444_32) { - v->BytePerPixelInDETY[k] = 4; - v->BytePerPixelInDETC[k] = 0; - } else if (src.source_format == dm_444_16) { - v->BytePerPixelInDETY[k] = 2; - v->BytePerPixelInDETC[k] = 0; - } else if (src.source_format == dm_420_8) { - v->BytePerPixelInDETY[k] = 1; - v->BytePerPixelInDETC[k] = 2; - } else { - v->BytePerPixelInDETY[k] = 4.00 / 3.00; - v->BytePerPixelInDETC[k] = 8.00 / 3.00; - } - } - - v->TotalReadBandwidthConsumedGBytePerSecond = 0; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - struct _vcs_dpi_display_pipe_dest_params_st dest = - e2e[v->planes[k].e2e_index].pipe.dest; - struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = - e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; - - v->ReadBandwidth[k] = - v->SwathWidthYSingleDPP[k] - * (dml_ceil_ex(v->BytePerPixelInDETY[k], 1) - * scale_ratio_depth.vscl_ratio - + (dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2) / 2) - * (scale_ratio_depth.vscl_ratio - / 2)) - / (dest.htotal / dest.pixel_rate_mhz); - - if (src.dcc == 1) { - v->ReadBandwidth[k] = v->ReadBandwidth[k] * (1 + 1 / 256); - } - - if (ip->pte_enable == 1 && src.source_scan != dm_horz - && (src.sw_mode == dm_sw_4kb_s || src.sw_mode == dm_sw_4kb_s_x - || src.sw_mode == dm_sw_4kb_d - || src.sw_mode == dm_sw_4kb_d_x)) { - v->ReadBandwidth[k] = v->ReadBandwidth[k] * (1 + 1 / 64); - } else if (ip->pte_enable == 1 && src.source_scan == dm_horz - && (src.source_format == dm_444_64 || src.source_format == dm_444_32) - && (src.sw_mode == dm_sw_64kb_s || src.sw_mode == dm_sw_64kb_s_t - || src.sw_mode == dm_sw_64kb_s_x - || src.sw_mode == dm_sw_64kb_d - || src.sw_mode == dm_sw_64kb_d_t - || src.sw_mode == dm_sw_64kb_d_x)) { - v->ReadBandwidth[k] = v->ReadBandwidth[k] * (1 + 1 / 256); - } else if (ip->pte_enable == 1) { - v->ReadBandwidth[k] = v->ReadBandwidth[k] * (1 + 1 / 512); - } - - v->TotalReadBandwidthConsumedGBytePerSecond = - v->TotalReadBandwidthConsumedGBytePerSecond - + v->ReadBandwidth[k] / 1000; - } - - v->TotalWriteBandwidthConsumedGBytePerSecond = 0; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_dest_params_st dest = - e2e[v->planes[k].e2e_index].pipe.dest; - struct _vcs_dpi_display_output_params_st dout = e2e[v->planes[k].e2e_index].dout; - - if (dout.output_type == dm_wb && dout.output_format == dm_444) { - v->WriteBandwidth[k] = dest.recout_width - / (dest.htotal / dest.pixel_rate_mhz) * 4; - } else if (dout.output_type == dm_wb) { - v->WriteBandwidth[k] = dest.recout_width - / (dest.htotal / dest.pixel_rate_mhz) * 1.5; - } else { - v->WriteBandwidth[k] = 0; - } - - v->TotalWriteBandwidthConsumedGBytePerSecond = - v->TotalWriteBandwidthConsumedGBytePerSecond - + v->WriteBandwidth[k] / 1000; - } - - v->TotalBandwidthConsumedGBytePerSecond = v->TotalReadBandwidthConsumedGBytePerSecond - + v->TotalWriteBandwidthConsumedGBytePerSecond; - - v->DCCEnabledInAnyPlane = 0; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - - if (src.dcc == 1) { - v->DCCEnabledInAnyPlane = 1; - } - } - - for (i = 0; i < NumberOfStatesPlusTwo; i++) { - v->ReturnBWToDCNPerState = dml_min( - soc->return_bus_width_bytes * v->DCFCLKPerState[i], - v->FabricAndDRAMBandwidthPerState[i] * 1000 - * soc->ideal_dram_bw_after_urgent_percent / 100); - - v->ReturnBWPerState[i] = v->ReturnBWToDCNPerState; - - if (v->DCCEnabledInAnyPlane == 1 - && v->ReturnBWToDCNPerState - > (v->DCFCLKPerState[i] - * soc->return_bus_width_bytes / 4)) { - v->ReturnBWPerState[i] = - dml_min( - v->ReturnBWPerState[i], - v->ReturnBWToDCNPerState * 4 - * (1 - - soc->urgent_latency_us - / ((ip->rob_buffer_size_kbytes - - ip->pixel_chunk_size_kbytes) - * 1024 - / (v->ReturnBWToDCNPerState - - v->DCFCLKPerState[i] - * soc->return_bus_width_bytes - / 4) - + soc->urgent_latency_us))); - } - - v->CriticalPoint = 2 * soc->return_bus_width_bytes * v->DCFCLKPerState[i] - * soc->urgent_latency_us - / (v->ReturnBWToDCNPerState * soc->urgent_latency_us - + (ip->rob_buffer_size_kbytes - - ip->pixel_chunk_size_kbytes) - * 1024); - - if (v->DCCEnabledInAnyPlane == 1 && v->CriticalPoint > 1 && v->CriticalPoint < 4) { - v->ReturnBWPerState[i] = - dml_min( - v->ReturnBWPerState[i], - 4 * v->ReturnBWToDCNPerState - * (ip->rob_buffer_size_kbytes - - ip->pixel_chunk_size_kbytes) - * 1024 - * soc->return_bus_width_bytes - * v->DCFCLKPerState[i] - * soc->urgent_latency_us - / dml_pow( - (v->ReturnBWToDCNPerState - * soc->urgent_latency_us - + (ip->rob_buffer_size_kbytes - - ip->pixel_chunk_size_kbytes) - * 1024), - 2)); - } - - v->ReturnBWToDCNPerState = dml_min( - soc->return_bus_width_bytes * v->DCFCLKPerState[i], - v->FabricAndDRAMBandwidthPerState[i] * 1000); - - if (v->DCCEnabledInAnyPlane == 1 - && v->ReturnBWToDCNPerState - > (v->DCFCLKPerState[i] - * soc->return_bus_width_bytes / 4)) { - v->ReturnBWPerState[i] = - dml_min( - v->ReturnBWPerState[i], - v->ReturnBWToDCNPerState * 4 - * (1 - - soc->urgent_latency_us - / ((ip->rob_buffer_size_kbytes - - ip->pixel_chunk_size_kbytes) - * 1024 - / (v->ReturnBWToDCNPerState - - v->DCFCLKPerState[i] - * soc->return_bus_width_bytes - / 4) - + soc->urgent_latency_us))); - } - - v->CriticalPoint = 2 * soc->return_bus_width_bytes * v->DCFCLKPerState[i] - * soc->urgent_latency_us - / (v->ReturnBWToDCNPerState * soc->urgent_latency_us - + (ip->rob_buffer_size_kbytes - - ip->pixel_chunk_size_kbytes) - * 1024); - - if (v->DCCEnabledInAnyPlane == 1 && v->CriticalPoint > 1 && v->CriticalPoint < 4) { - v->ReturnBWPerState[i] = - dml_min( - v->ReturnBWPerState[i], - 4 * v->ReturnBWToDCNPerState - * (ip->rob_buffer_size_kbytes - - ip->pixel_chunk_size_kbytes) - * 1024 - * soc->return_bus_width_bytes - * v->DCFCLKPerState[i] - * soc->urgent_latency_us - / dml_pow( - (v->ReturnBWToDCNPerState - * soc->urgent_latency_us - + (ip->rob_buffer_size_kbytes - - ip->pixel_chunk_size_kbytes) - * 1024), - 2)); - } - } - - for (i = 0; i < NumberOfStatesPlusTwo; i++) { - if ((v->TotalReadBandwidthConsumedGBytePerSecond * 1000 <= v->ReturnBWPerState[i]) - && (v->TotalBandwidthConsumedGBytePerSecond * 1000 - <= v->FabricAndDRAMBandwidthPerState[i] * 1000 - * soc->ideal_dram_bw_after_urgent_percent - / 100)) { - v->BandwidthSupport[i] = 1; - } else { - v->BandwidthSupport[i] = 0; - } - } - - // Writeback Latency support check - - v->WritebackLatencySupport = 1; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_dest_params_st dest = - e2e[v->planes[k].e2e_index].pipe.dest; - struct _vcs_dpi_display_output_params_st dout = e2e[v->planes[k].e2e_index].dout; - - if (dout.output_type == dm_wb && dout.output_format == dm_444 - && (dest.recout_width / (dest.htotal / dest.pixel_rate_mhz) * 4) - > ((ip->writeback_luma_buffer_size_kbytes - + ip->writeback_chroma_buffer_size_kbytes) - * 1024 / soc->writeback_latency_us)) { - v->WritebackLatencySupport = 0; - } else if (dout.output_type == dm_wb - && (dest.recout_width / (dest.htotal / dest.pixel_rate_mhz)) - > (dml_min( - ip->writeback_luma_buffer_size_kbytes, - 2 - * ip->writeback_chroma_buffer_size_kbytes) - * 1024 / soc->writeback_latency_us)) { - v->WritebackLatencySupport = 0; - } - } - - // Re-ordering Buffer Support Check - - for (i = 0; i < NumberOfStatesPlusTwo; i++) { - v->UrgentRoundTripAndOutOfOrderLatencyPerState[i] = - (soc->round_trip_ping_latency_dcfclk_cycles + 32) - / v->DCFCLKPerState[i] - + soc->urgent_out_of_order_return_per_channel_bytes - * soc->num_chans - / v->ReturnBWPerState[i]; - - if ((ip->rob_buffer_size_kbytes - ip->pixel_chunk_size_kbytes) * 1024 - / v->ReturnBWPerState[i] - > v->UrgentRoundTripAndOutOfOrderLatencyPerState[i]) { - v->ROBSupport[i] = 1; - } else { - v->ROBSupport[i] = 0; - } - } - - // Display IO Support Check - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_dest_params_st dest = - e2e[v->planes[k].e2e_index].pipe.dest; - struct _vcs_dpi_display_output_params_st dout = e2e[v->planes[k].e2e_index].dout; - - if (dout.output_format == dm_420) { - v->RequiredOutputBW = dest.pixel_rate_mhz * 3 / 2; - } else { - v->RequiredOutputBW = dest.pixel_rate_mhz * 3; - } - - if (dout.output_type == dm_hdmi) { - v->RequiredPHYCLK[k] = v->RequiredOutputBW / 3; - } else if (dout.output_type == dm_dp) { - v->RequiredPHYCLK[k] = v->RequiredOutputBW / 4; - } else { - v->RequiredPHYCLK[k] = 0; - } - } - - for (i = 0; i < NumberOfStatesPlusTwo; i++) { - v->DIOSupport[i] = 1; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_output_params_st dout = - e2e[v->planes[k].e2e_index].dout; - - if ((v->RequiredPHYCLK[k] > v->PHYCLKPerState[i]) - || (dout.output_type == dm_hdmi - && v->RequiredPHYCLK[k] > 600)) { - v->DIOSupport[i] = 0; - } - } - } - - // Total Available Writeback Support Check - - v->TotalNumberOfActiveWriteback = 0; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_output_params_st dout = e2e[v->planes[k].e2e_index].dout; - - if (dout.output_type == dm_wb) { - v->TotalNumberOfActiveWriteback = v->TotalNumberOfActiveWriteback + 1; - } - } - - if (v->TotalNumberOfActiveWriteback <= ip->max_num_wb) { - v->TotalAvailableWritebackSupport = 1; - } else { - v->TotalAvailableWritebackSupport = 0; - } - - // Maximum DISPCLK/DPPCLK Support check - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_dest_params_st dest = - e2e[v->planes[k].e2e_index].pipe.dest; - struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = - e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; - struct _vcs_dpi_scaler_taps_st scale_taps = - e2e[v->planes[k].e2e_index].pipe.scale_taps; - - if (scale_ratio_depth.hscl_ratio > 1) { - v->PSCL_FACTOR[k] = dml_min( - ip->max_dchub_pscl_bw_pix_per_clk, - ip->max_pscl_lb_bw_pix_per_clk - * scale_ratio_depth.hscl_ratio - / dml_ceil_ex(scale_taps.htaps / 6, 1)); - } else { - v->PSCL_FACTOR[k] = dml_min( - ip->max_dchub_pscl_bw_pix_per_clk, - ip->max_pscl_lb_bw_pix_per_clk); - } - - if (v->BytePerPixelInDETC[k] == 0) { - v->PSCL_FACTOR_CHROMA[k] = 0; - v->MinDPPCLKUsingSingleDPP[k] = - dest.pixel_rate_mhz - * dml_max( - scale_taps.vtaps / 6 - * dml_min( - 1, - scale_ratio_depth.hscl_ratio), - dml_max( - scale_ratio_depth.hscl_ratio - * scale_ratio_depth.vscl_ratio - / v->PSCL_FACTOR[k], - 1)); - - } else { - if (scale_ratio_depth.hscl_ratio / 2 > 1) { - v->PSCL_FACTOR_CHROMA[k] = dml_min( - ip->max_dchub_pscl_bw_pix_per_clk, - ip->max_pscl_lb_bw_pix_per_clk - * scale_ratio_depth.hscl_ratio / 2 - / dml_ceil_ex( - scale_taps.htaps_c - / 6, - 1)); - } else { - v->PSCL_FACTOR_CHROMA[k] = dml_min( - ip->max_dchub_pscl_bw_pix_per_clk, - ip->max_pscl_lb_bw_pix_per_clk); - } - v->MinDPPCLKUsingSingleDPP[k] = - dest.pixel_rate_mhz - * dml_max( - dml_max( - scale_taps.vtaps - / 6 - * dml_min( - 1, - scale_ratio_depth.hscl_ratio), - scale_ratio_depth.hscl_ratio - * scale_ratio_depth.vscl_ratio - / v->PSCL_FACTOR[k]), - dml_max( - dml_max( - scale_taps.vtaps_c - / 6 - * dml_min( - 1, - scale_ratio_depth.hscl_ratio - / 2), - scale_ratio_depth.hscl_ratio - * scale_ratio_depth.vscl_ratio - / 4 - / v->PSCL_FACTOR_CHROMA[k]), - 1)); - - } - } - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = - e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; - struct _vcs_dpi_scaler_taps_st scale_taps = - e2e[v->planes[k].e2e_index].pipe.scale_taps; - - if (src.source_format == dm_444_64 || src.source_format == dm_444_32 - || src.source_format == dm_444_16) { - if (src.sw_mode == dm_sw_linear) { - v->Read256BlockHeightY[k] = 1; - } else if (src.source_format == dm_444_64) { - v->Read256BlockHeightY[k] = 4; - } else { - v->Read256BlockHeightY[k] = 8; - } - - v->Read256BlockWidthY[k] = 256 / dml_ceil_ex(v->BytePerPixelInDETY[k], 1) - / v->Read256BlockHeightY[k]; - v->Read256BlockHeightC[k] = 0; - v->Read256BlockWidthC[k] = 0; - } else { - if (src.sw_mode == dm_sw_linear) { - v->Read256BlockHeightY[k] = 1; - v->Read256BlockHeightC[k] = 1; - } else if (src.source_format == dm_420_8) { - v->Read256BlockHeightY[k] = 16; - v->Read256BlockHeightC[k] = 8; - } else { - v->Read256BlockHeightY[k] = 8; - v->Read256BlockHeightC[k] = 8; - } - - v->Read256BlockWidthY[k] = 256 / dml_ceil_ex(v->BytePerPixelInDETY[k], 1) - / v->Read256BlockHeightY[k]; - v->Read256BlockWidthC[k] = 256 / dml_ceil_ex(v->BytePerPixelInDETC[k], 2) - / v->Read256BlockHeightC[k]; - } - - if (src.source_scan == dm_horz) { - v->MaxSwathHeightY[k] = v->Read256BlockHeightY[k]; - v->MaxSwathHeightC[k] = v->Read256BlockHeightC[k]; - } else { - v->MaxSwathHeightY[k] = v->Read256BlockWidthY[k]; - v->MaxSwathHeightC[k] = v->Read256BlockWidthC[k]; - } - - if (src.source_format == dm_444_64 || src.source_format == dm_444_32 - || src.source_format == dm_444_16) { - if (src.sw_mode == dm_sw_linear - || (src.source_format == dm_444_64 - && (src.sw_mode == dm_sw_4kb_s - || src.sw_mode - == dm_sw_4kb_s_x - || src.sw_mode - == dm_sw_64kb_s - || src.sw_mode - == dm_sw_64kb_s_t - || src.sw_mode - == dm_sw_64kb_s_x - || src.sw_mode - == dm_sw_var_s - || src.sw_mode - == dm_sw_var_s_x) - && src.source_scan == dm_horz)) { - v->MinSwathHeightY[k] = v->MaxSwathHeightY[k]; - } else { - v->MinSwathHeightY[k] = v->MaxSwathHeightY[k] / 2; - } - v->MinSwathHeightC[k] = v->MaxSwathHeightC[k]; - } else { - if (src.sw_mode == dm_sw_linear) { - v->MinSwathHeightY[k] = v->MaxSwathHeightY[k]; - v->MinSwathHeightC[k] = v->MaxSwathHeightC[k]; - } else if (src.source_format == dm_420_8 && src.source_scan == dm_horz) { - v->MinSwathHeightY[k] = v->MaxSwathHeightY[k] / 2; - if (ip->bug_forcing_LC_req_same_size_fixed == 1) { - v->MinSwathHeightC[k] = v->MaxSwathHeightC[k]; - } else { - v->MinSwathHeightC[k] = v->MaxSwathHeightC[k] / 2; - } - } else if (src.source_format == dm_420_10 && src.source_scan == dm_horz) { - v->MinSwathHeightC[k] = v->MaxSwathHeightC[k] / 2; - if (ip->bug_forcing_LC_req_same_size_fixed == 1) { - v->MinSwathHeightY[k] = v->MaxSwathHeightY[k]; - } else { - v->MinSwathHeightY[k] = v->MaxSwathHeightY[k] / 2; - } - } else { - v->MinSwathHeightY[k] = v->MaxSwathHeightY[k]; - v->MinSwathHeightC[k] = v->MaxSwathHeightC[k]; - } - } - - if (src.sw_mode == dm_sw_linear) { - v->MaximumSwathWidth = 8192; - } else { - v->MaximumSwathWidth = 5120; - } - - v->NumberOfDPPRequiredForDETSize = - dml_ceil_ex( - v->SwathWidthYSingleDPP[k] - / dml_min( - v->MaximumSwathWidth, - ip->det_buffer_size_kbytes - * 1024 - / 2 - / (v->BytePerPixelInDETY[k] - * v->MinSwathHeightY[k] - + v->BytePerPixelInDETC[k] - / 2 - * v->MinSwathHeightC[k])), - 1); - - if (v->BytePerPixelInDETC[k] == 0) { - v->NumberOfDPPRequiredForLBSize = - dml_ceil_ex( - (scale_taps.vtaps - + dml_max( - dml_ceil_ex( - scale_ratio_depth.vscl_ratio, - 1) - - 2, - 0)) - * v->SwathWidthYSingleDPP[k] - / dml_max( - scale_ratio_depth.hscl_ratio, - 1) - * scale_ratio_depth.lb_depth - / ip->line_buffer_size_bits, - 1); - } else { - v->NumberOfDPPRequiredForLBSize = - dml_max( - dml_ceil_ex( - (scale_taps.vtaps - + dml_max( - dml_ceil_ex( - scale_ratio_depth.vscl_ratio, - 1) - - 2, - 0)) - * v->SwathWidthYSingleDPP[k] - / dml_max( - scale_ratio_depth.hscl_ratio, - 1) - * scale_ratio_depth.lb_depth - / ip->line_buffer_size_bits, - 1), - dml_ceil_ex( - (scale_taps.vtaps_c - + dml_max( - dml_ceil_ex( - scale_ratio_depth.vscl_ratio - / 2, - 1) - - 2, - 0)) - * v->SwathWidthYSingleDPP[k] - / 2 - / dml_max( - scale_ratio_depth.hscl_ratio - / 2, - 1) - * scale_ratio_depth.lb_depth - / ip->line_buffer_size_bits, - 1)); - } - - v->NumberOfDPPRequiredForDETAndLBSize[k] = dml_max( - v->NumberOfDPPRequiredForDETSize, - v->NumberOfDPPRequiredForLBSize); - - } - - for (i = 0; i < NumberOfStatesPlusTwo; i++) { - for (j = 0; j < 2; j++) { - v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] = 0; - v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = 0; - v->DISPCLK_DPPCLK_Support[j * NumberOfStatesPlusTwo + i] = 1; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_dest_params_st dest = - e2e[v->planes[k].e2e_index].pipe.dest; - ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; - - v->MinDispclkUsingSingleDPP = dml_max( - dest.pixel_rate_mhz, - v->MinDPPCLKUsingSingleDPP[k] * (j + 1)) - * (1 + soc->downspread_percent / 100); - v->MinDispclkUsingDualDPP = dml_max( - dest.pixel_rate_mhz, - v->MinDPPCLKUsingSingleDPP[k] / 2 * (j + 1)) - * (1 + soc->downspread_percent / 100); - - if (i < NumberOfStates) { - v->MinDispclkUsingSingleDPP = - v->MinDispclkUsingSingleDPP - * (1 - + ip->dispclk_ramp_margin_percent - / 100); - v->MinDispclkUsingDualDPP = - v->MinDispclkUsingDualDPP - * (1 - + ip->dispclk_ramp_margin_percent - / 100); - } - - if (v->MinDispclkUsingSingleDPP - <= dml_min( - v->MaxDispclk[i], - (j + 1) * v->MaxDppclk[i]) - && v->NumberOfDPPRequiredForDETAndLBSize[k] <= 1) { - v->NoOfDPP[ijk] = 1; - v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = dml_max( - v->RequiredDISPCLK[j * NumberOfStatesPlusTwo - + i], - v->MinDispclkUsingSingleDPP); - } else if (v->MinDispclkUsingDualDPP - <= dml_min( - v->MaxDispclk[i], - (j + 1) * v->MaxDppclk[i])) { - v->NoOfDPP[ijk] = 2; - v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = dml_max( - v->RequiredDISPCLK[j * NumberOfStatesPlusTwo - + i], - v->MinDispclkUsingDualDPP); - } else { - v->NoOfDPP[ijk] = 2; - v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = dml_max( - v->RequiredDISPCLK[j * NumberOfStatesPlusTwo - + i], - v->MinDispclkUsingDualDPP); - v->DISPCLK_DPPCLK_Support[j * NumberOfStatesPlusTwo + i] = - 0; - } - - v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] = - v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo - + i] + v->NoOfDPP[ijk]; - } - - if (v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] - > ip->max_num_dpp) { - v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] = 0; - v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = 0; - v->DISPCLK_DPPCLK_Support[j * NumberOfStatesPlusTwo + i] = 1; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_dest_params_st dest = - e2e[v->planes[k].e2e_index].pipe.dest; - ijk = k * 2 * NumberOfStatesPlusTwo - + j * NumberOfStatesPlusTwo + i; - - v->MinDispclkUsingSingleDPP = dml_max( - dest.pixel_rate_mhz, - v->MinDPPCLKUsingSingleDPP[k] * (j + 1)) - * (1 + soc->downspread_percent / 100); - v->MinDispclkUsingDualDPP = dml_max( - dest.pixel_rate_mhz, - v->MinDPPCLKUsingSingleDPP[k] / 2 * (j + 1)) - * (1 + soc->downspread_percent / 100); - - if (i < NumberOfStates) { - v->MinDispclkUsingSingleDPP = - v->MinDispclkUsingSingleDPP - * (1 - + ip->dispclk_ramp_margin_percent - / 100); - v->MinDispclkUsingDualDPP = - v->MinDispclkUsingDualDPP - * (1 - + ip->dispclk_ramp_margin_percent - / 100); - } - - if (v->NumberOfDPPRequiredForDETAndLBSize[k] <= 1) { - v->NoOfDPP[ijk] = 1; - v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = - dml_max( - v->RequiredDISPCLK[j - * NumberOfStatesPlusTwo - + i], - v->MinDispclkUsingSingleDPP); - if (v->MinDispclkUsingSingleDPP - > dml_min( - v->MaxDispclk[i], - (j + 1) - * v->MaxDppclk[i])) { - v->DISPCLK_DPPCLK_Support[j - * NumberOfStatesPlusTwo + i] = - 0; - } - } else { - v->NoOfDPP[ijk] = 2; - v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = - dml_max( - v->RequiredDISPCLK[j - * NumberOfStatesPlusTwo - + i], - v->MinDispclkUsingDualDPP); - if (v->MinDispclkUsingDualDPP - > dml_min( - v->MaxDispclk[i], - (j + 1) - * v->MaxDppclk[i])) { - v->DISPCLK_DPPCLK_Support[j - * NumberOfStatesPlusTwo + i] = - 0; - } - } - v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] = - v->TotalNumberOfActiveDPP[j - * NumberOfStatesPlusTwo + i] - + v->NoOfDPP[ijk]; - } - } - } - } - - // Viewport Size Check - - v->ViewportSizeSupport = 1; - - for (k = 0; k < num_planes; k++) { - if (v->NumberOfDPPRequiredForDETAndLBSize[k] > 2) { - v->ViewportSizeSupport = 0; - } - } - - // Total Available Pipes Support Check - - for (i = 0; i < NumberOfStatesPlusTwo; i++) { - for (j = 0; j < 2; j++) { - if (v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] - <= ip->max_num_dpp) { - v->TotalAvailablePipesSupport[j * NumberOfStatesPlusTwo + i] = 1; - } else { - v->TotalAvailablePipesSupport[j * NumberOfStatesPlusTwo + i] = 0; - } - } - } - - // Urgent Latency Support Check - - for (j = 0; j < 2; j++) { - for (i = 0; i < NumberOfStatesPlusTwo; i++) { - ij = j * NumberOfStatesPlusTwo + i; - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - struct _vcs_dpi_display_pipe_dest_params_st dest = - e2e[v->planes[k].e2e_index].pipe.dest; - struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = - e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; - struct _vcs_dpi_scaler_taps_st scale_taps = - e2e[v->planes[k].e2e_index].pipe.scale_taps; - ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; - - v->SwathWidthYPerState[ijk] = v->SwathWidthYSingleDPP[k] - / v->NoOfDPP[ijk]; - - v->SwathWidthGranularityY = 256 - / dml_ceil_ex(v->BytePerPixelInDETY[k], 1) - / v->MaxSwathHeightY[k]; - v->RoundedUpMaxSwathSizeBytesY = (dml_ceil_ex( - v->SwathWidthYPerState[ijk] - 1, - v->SwathWidthGranularityY) - + v->SwathWidthGranularityY) - * v->BytePerPixelInDETY[k] * v->MaxSwathHeightY[k]; - if (src.source_format == dm_420_10) { - v->RoundedUpMaxSwathSizeBytesY = dml_ceil_ex( - v->RoundedUpMaxSwathSizeBytesY, - 256) + 256; - } - if (v->MaxSwathHeightC[k] > 0) { - v->SwathWidthGranularityC = 256 - / dml_ceil_ex(v->BytePerPixelInDETC[k], 2) - / v->MaxSwathHeightC[k]; - } - v->RoundedUpMaxSwathSizeBytesC = (dml_ceil_ex( - v->SwathWidthYPerState[ijk] / 2 - 1, - v->SwathWidthGranularityC) - + v->SwathWidthGranularityC) - * v->BytePerPixelInDETC[k] * v->MaxSwathHeightC[k]; - if (src.source_format == dm_420_10) { - v->RoundedUpMaxSwathSizeBytesC = dml_ceil_ex( - v->RoundedUpMaxSwathSizeBytesC, - 256) + 256; - } - - if (v->RoundedUpMaxSwathSizeBytesY + v->RoundedUpMaxSwathSizeBytesC - <= ip->det_buffer_size_kbytes * 1024 / 2) { - v->SwathHeightYPerState[ijk] = v->MaxSwathHeightY[k]; - v->SwathHeightCPerState[ijk] = v->MaxSwathHeightC[k]; - } else { - v->SwathHeightYPerState[ijk] = v->MinSwathHeightY[k]; - v->SwathHeightCPerState[ijk] = v->MinSwathHeightC[k]; - } - - if (v->BytePerPixelInDETC[k] == 0) { - v->LinesInDETLuma = ip->det_buffer_size_kbytes * 1024 - / v->BytePerPixelInDETY[k] - / v->SwathWidthYPerState[ijk]; - - v->LinesInDETChroma = 0; - } else if (v->SwathHeightYPerState[ijk] - <= v->SwathHeightCPerState[ijk]) { - v->LinesInDETLuma = ip->det_buffer_size_kbytes * 1024 / 2 - / v->BytePerPixelInDETY[k] - / v->SwathWidthYPerState[ijk]; - v->LinesInDETChroma = ip->det_buffer_size_kbytes * 1024 / 2 - / v->BytePerPixelInDETC[k] - / (v->SwathWidthYPerState[ijk] / 2); - } else { - v->LinesInDETLuma = ip->det_buffer_size_kbytes * 1024 * 2 - / 3 / v->BytePerPixelInDETY[k] - / v->SwathWidthYPerState[ijk]; - v->LinesInDETChroma = ip->det_buffer_size_kbytes * 1024 / 3 - / v->BytePerPixelInDETY[k] - / (v->SwathWidthYPerState[ijk] / 2); - } - - v->EffectiveLBLatencyHidingSourceLinesLuma = - dml_min( - ip->max_line_buffer_lines, - dml_floor_ex( - ip->line_buffer_size_bits - / scale_ratio_depth.lb_depth - / (v->SwathWidthYPerState[ijk] - / dml_max( - scale_ratio_depth.hscl_ratio, - 1)), - 1)) - - (scale_taps.vtaps - 1); - - v->EffectiveLBLatencyHidingSourceLinesChroma = - dml_min( - ip->max_line_buffer_lines, - dml_floor_ex( - ip->line_buffer_size_bits - / scale_ratio_depth.lb_depth - / (v->SwathWidthYPerState[ijk] - / 2 - / dml_max( - scale_ratio_depth.hscl_ratio - / 2, - 1)), - 1)) - - (scale_taps.vtaps_c - 1); - - v->EffectiveDETLBLinesLuma = - dml_floor_ex( - v->LinesInDETLuma - + dml_min( - v->LinesInDETLuma - * v->RequiredDISPCLK[ij] - * v->BytePerPixelInDETY[k] - * v->PSCL_FACTOR[k] - / v->ReturnBWPerState[i], - v->EffectiveLBLatencyHidingSourceLinesLuma), - v->SwathHeightYPerState[ijk]); - - v->EffectiveDETLBLinesChroma = - dml_floor_ex( - v->LinesInDETChroma - + dml_min( - v->LinesInDETChroma - * v->RequiredDISPCLK[ij] - * v->BytePerPixelInDETC[k] - * v->PSCL_FACTOR_CHROMA[k] - / v->ReturnBWPerState[i], - v->EffectiveLBLatencyHidingSourceLinesChroma), - v->SwathHeightCPerState[ijk]); - - if (v->BytePerPixelInDETC[k] == 0) { - v->UrgentLatencySupportUsPerState[ijk] = - v->EffectiveDETLBLinesLuma - * (dest.htotal - / dest.pixel_rate_mhz) - / scale_ratio_depth.vscl_ratio - - v->EffectiveDETLBLinesLuma - * v->SwathWidthYPerState[ijk] - * dml_ceil_ex( - v->BytePerPixelInDETY[k], - 1) - / (v->ReturnBWPerState[i] - / v->NoOfDPP[ijk]); - } else { - v->UrgentLatencySupportUsPerState[ijk] = - dml_min( - v->EffectiveDETLBLinesLuma - * (dest.htotal - / dest.pixel_rate_mhz) - / scale_ratio_depth.vscl_ratio - - v->EffectiveDETLBLinesLuma - * v->SwathWidthYPerState[ijk] - * dml_ceil_ex( - v->BytePerPixelInDETY[k], - 1) - / (v->ReturnBWPerState[i] - / v->NoOfDPP[ijk]), - v->EffectiveDETLBLinesChroma - * (dest.htotal - / dest.pixel_rate_mhz) - / (scale_ratio_depth.vscl_ratio - / 2) - - v->EffectiveDETLBLinesChroma - * v->SwathWidthYPerState[ijk] - / 2 - * dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2) - / (v->ReturnBWPerState[i] - / v->NoOfDPP[ijk])); - } - - } - } - } - - for (i = 0; i < NumberOfStatesPlusTwo; i++) { - for (j = 0; j < 2; j++) { - ij = j * NumberOfStatesPlusTwo + i; - - v->UrgentLatencySupport[ij] = 1; - for (k = 0; k < num_planes; k++) { - ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; - - if (v->UrgentLatencySupportUsPerState[ijk] - < soc->urgent_latency_us / 1) { - v->UrgentLatencySupport[ij] = 0; - } - } - } - } - - // Prefetch Check - - for (i = 0; i < NumberOfStatesPlusTwo; i++) { - for (j = 0; j < 2; j++) { - ij = j * NumberOfStatesPlusTwo + i; - - v->TotalNumberOfDCCActiveDPP[ij] = 0; - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; - - if (src.dcc == 1) { - v->TotalNumberOfDCCActiveDPP[ij] = - v->TotalNumberOfDCCActiveDPP[ij] - + v->NoOfDPP[ijk]; - } - } - } - } - - for (i = 0; i < NumberOfStatesPlusTwo; i++) { - for (j = 0; j < 2; j++) { - ij = j * NumberOfStatesPlusTwo + i; - - v->ProjectedDCFCLKDeepSleep = 8; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_dest_params_st dest = - e2e[v->planes[k].e2e_index].pipe.dest; - struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = - e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; - ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; - - v->ProjectedDCFCLKDeepSleep = dml_max( - v->ProjectedDCFCLKDeepSleep, - dest.pixel_rate_mhz / 16); - if (v->BytePerPixelInDETC[k] == 0) { - if (scale_ratio_depth.vscl_ratio <= 1) { - v->ProjectedDCFCLKDeepSleep = - dml_max( - v->ProjectedDCFCLKDeepSleep, - 1.1 - * dml_ceil_ex( - v->BytePerPixelInDETY[k], - 1) - / 64 - * scale_ratio_depth.hscl_ratio - * dest.pixel_rate_mhz - / v->NoOfDPP[ijk]); - } else { - v->ProjectedDCFCLKDeepSleep = - dml_max( - v->ProjectedDCFCLKDeepSleep, - 1.1 - * dml_ceil_ex( - v->BytePerPixelInDETY[k], - 1) - / 64 - * v->PSCL_FACTOR[k] - * v->RequiredDISPCLK[ij] - / (1 - + j)); - } - - } else { - if (scale_ratio_depth.vscl_ratio <= 1) { - v->ProjectedDCFCLKDeepSleep = - dml_max( - v->ProjectedDCFCLKDeepSleep, - 1.1 - * dml_ceil_ex( - v->BytePerPixelInDETY[k], - 1) - / 32 - * scale_ratio_depth.hscl_ratio - * dest.pixel_rate_mhz - / v->NoOfDPP[ijk]); - } else { - v->ProjectedDCFCLKDeepSleep = - dml_max( - v->ProjectedDCFCLKDeepSleep, - 1.1 - * dml_ceil_ex( - v->BytePerPixelInDETY[k], - 1) - / 32 - * v->PSCL_FACTOR[k] - * v->RequiredDISPCLK[ij] - / (1 - + j)); - } - if ((scale_ratio_depth.vscl_ratio / 2) <= 1) { - v->ProjectedDCFCLKDeepSleep = - dml_max( - v->ProjectedDCFCLKDeepSleep, - 1.1 - * dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2) - / 32 - * scale_ratio_depth.hscl_ratio - / 2 - * dest.pixel_rate_mhz - / v->NoOfDPP[ijk]); - } else { - v->ProjectedDCFCLKDeepSleep = - dml_max( - v->ProjectedDCFCLKDeepSleep, - 1.1 - * dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2) - / 32 - * v->PSCL_FACTOR_CHROMA[k] - * v->RequiredDISPCLK[ij] - / (1 - + j)); - } - - } - } - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - struct _vcs_dpi_display_pipe_dest_params_st dest = - e2e[v->planes[k].e2e_index].pipe.dest; - struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = - e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; - struct _vcs_dpi_scaler_taps_st scale_taps = - e2e[v->planes[k].e2e_index].pipe.scale_taps; - struct _vcs_dpi_display_output_params_st dout = - e2e[v->planes[k].e2e_index].dout; - ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; - - if (src.dcc == 1) { - v->MetaReqHeightY = 8 * v->Read256BlockHeightY[k]; - v->MetaReqWidthY = 64 * 256 - / dml_ceil_ex(v->BytePerPixelInDETY[k], 1) - / v->MetaReqHeightY; - v->MetaSurfaceWidthY = dml_ceil_ex( - src.viewport_width / v->NoOfDPP[ijk] - 1, - v->MetaReqWidthY) + v->MetaReqWidthY; - v->MetaSurfaceHeightY = dml_ceil_ex( - src.viewport_height - 1, - v->MetaReqHeightY) + v->MetaReqHeightY; - if (ip->pte_enable == 1) { - v->MetaPteBytesPerFrameY = - (dml_ceil_ex( - (v->MetaSurfaceWidthY - * v->MetaSurfaceHeightY - * dml_ceil_ex( - v->BytePerPixelInDETY[k], - 1) - / 256.0 - - 4096) - / 8 - / 4096, - 1) + 1) * 64; - } else { - v->MetaPteBytesPerFrameY = 0; - } - if (src.source_scan == dm_horz) { - v->MetaRowBytesY = - v->MetaSurfaceWidthY - * v->MetaReqHeightY - * dml_ceil_ex( - v->BytePerPixelInDETY[k], - 1) - / 256; - } else { - v->MetaRowBytesY = - v->MetaSurfaceHeightY - * v->MetaReqWidthY - * dml_ceil_ex( - v->BytePerPixelInDETY[k], - 1) - / 256; - } - } else { - v->MetaPteBytesPerFrameY = 0; - v->MetaRowBytesY = 0; - } - - if (ip->pte_enable == 1) { - if (src.sw_mode == dm_sw_linear) { - v->MacroTileBlockSizeBytesY = 256; - v->MacroTileBlockHeightY = 1; - } else if (src.sw_mode == dm_sw_4kb_s - || src.sw_mode == dm_sw_4kb_s_x - || src.sw_mode == dm_sw_4kb_d - || src.sw_mode == dm_sw_4kb_d_x) { - v->MacroTileBlockSizeBytesY = 4096; - v->MacroTileBlockHeightY = 4 - * v->Read256BlockHeightY[k]; - } else if (src.sw_mode == dm_sw_64kb_s - || src.sw_mode == dm_sw_64kb_s_t - || src.sw_mode == dm_sw_64kb_s_x - || src.sw_mode == dm_sw_64kb_d - || src.sw_mode == dm_sw_64kb_d_t - || src.sw_mode == dm_sw_64kb_d_x) { - v->MacroTileBlockSizeBytesY = 64 * 1024; - v->MacroTileBlockHeightY = 16 - * v->Read256BlockHeightY[k]; - } else { - v->MacroTileBlockSizeBytesY = 256 * 1024; - v->MacroTileBlockHeightY = 32 - * v->Read256BlockHeightY[k]; - } - if (v->MacroTileBlockSizeBytesY <= 65536) { - v->DataPTEReqHeightY = v->MacroTileBlockHeightY; - } else { - v->DataPTEReqHeightY = 16 - * v->Read256BlockHeightY[k]; - } - v->DataPTEReqWidthY = 4096 - / dml_ceil_ex(v->BytePerPixelInDETY[k], 1) - / v->DataPTEReqHeightY * 8; - if (src.sw_mode == dm_sw_linear) { - v->DPTEBytesPerRowY = - 64 - * (dml_ceil_ex( - (src.viewport_width - / v->NoOfDPP[ijk] - * dml_min( - 128, - dml_pow( - 2, - dml_floor_ex( - dml_log( - ip->dpte_buffer_size_in_pte_reqs - * v->DataPTEReqWidthY - / (src.viewport_width - / v->NoOfDPP[ijk]), - 2), - 1))) - - 1) - / v->DataPTEReqWidthY, - 1) - + 1); - } else if (src.source_scan == dm_horz) { - v->DPTEBytesPerRowY = - 64 - * (dml_ceil_ex( - (src.viewport_width - / v->NoOfDPP[ijk] - - 1) - / v->DataPTEReqWidthY, - 1) - + 1); - } else { - v->DPTEBytesPerRowY = - 64 - * (dml_ceil_ex( - (src.viewport_height - - 1) - / v->DataPTEReqHeightY, - 1) - + 1); - } - } else { - v->DPTEBytesPerRowY = 0; - } - - if (src.source_format != dm_444_64 && src.source_format != dm_444_32 - && src.source_format != dm_444_16) { - if (src.dcc == 1) { - v->MetaReqHeightC = 8 * v->Read256BlockHeightC[k]; - v->MetaReqWidthC = - 64 * 256 - / dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2) - / v->MetaReqHeightC; - v->MetaSurfaceWidthC = dml_ceil_ex( - src.viewport_width / v->NoOfDPP[ijk] - / 2 - 1, - v->MetaReqWidthC) - + v->MetaReqWidthC; - v->MetaSurfaceHeightC = dml_ceil_ex( - src.viewport_height / 2 - 1, - v->MetaReqHeightC) - + v->MetaReqHeightC; - if (ip->pte_enable == 1) { - v->MetaPteBytesPerFrameC = - (dml_ceil_ex( - (v->MetaSurfaceWidthC - * v->MetaSurfaceHeightC - * dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2) - / 256.0 - - 4096) - / 8 - / 4096, - 1) + 1) - * 64; - } else { - v->MetaPteBytesPerFrameC = 0; - } - if (src.source_scan == dm_horz) { - v->MetaRowBytesC = - v->MetaSurfaceWidthC - * v->MetaReqHeightC - * dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2) - / 256; - } else { - v->MetaRowBytesC = - v->MetaSurfaceHeightC - * v->MetaReqWidthC - * dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2) - / 256; - } - } else { - v->MetaPteBytesPerFrameC = 0; - v->MetaRowBytesC = 0; - } - - if (ip->pte_enable == 1) { - if (src.sw_mode == dm_sw_linear) { - v->MacroTileBlockSizeBytesC = 256; - v->MacroTileBlockHeightC = 1; - } else if (src.sw_mode == dm_sw_4kb_s - || src.sw_mode == dm_sw_4kb_s_x - || src.sw_mode == dm_sw_4kb_d - || src.sw_mode == dm_sw_4kb_d_x) { - v->MacroTileBlockSizeBytesC = 4096; - v->MacroTileBlockHeightC = 4 - * v->Read256BlockHeightC[k]; - } else if (src.sw_mode == dm_sw_64kb_s - || src.sw_mode == dm_sw_64kb_s_t - || src.sw_mode == dm_sw_64kb_s_x - || src.sw_mode == dm_sw_64kb_d - || src.sw_mode == dm_sw_64kb_d_t - || src.sw_mode == dm_sw_64kb_d_x) { - v->MacroTileBlockSizeBytesC = 64 * 1024; - v->MacroTileBlockHeightC = 16 - * v->Read256BlockHeightC[k]; - } else { - v->MacroTileBlockSizeBytesC = 256 * 1024; - v->MacroTileBlockHeightC = 32 - * v->Read256BlockHeightC[k]; - } - v->MacroTileBlockWidthC = - v->MacroTileBlockSizeBytesC - / dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2) - / v->MacroTileBlockHeightC; - if (v->MacroTileBlockSizeBytesC <= 65536) { - v->DataPTEReqHeightC = - v->MacroTileBlockHeightC; - } else { - v->DataPTEReqHeightC = 16 - * v->Read256BlockHeightC[k]; - } - v->DataPTEReqWidthC = - 4096 - / dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2) - / v->DataPTEReqHeightC - * 8; - if (src.sw_mode == dm_sw_linear) { - v->DPTEBytesPerRowC = - 64 - * (dml_ceil_ex( - (src.viewport_width - / v->NoOfDPP[ijk] - / 2 - * dml_min( - 128, - dml_pow( - 2, - dml_floor_ex( - dml_log( - ip->dpte_buffer_size_in_pte_reqs - * v->DataPTEReqWidthC - / (src.viewport_width - / v->NoOfDPP[ijk] - / 2), - 2), - 1))) - - 1) - / v->DataPTEReqWidthC, - 1) - + 1); - } else if (src.source_scan == dm_horz) { - v->DPTEBytesPerRowC = - 64 - * (dml_ceil_ex( - (src.viewport_width - / v->NoOfDPP[ijk] - / 2 - - 1) - / v->DataPTEReqWidthC, - 1) - + 1); - } else { - v->DPTEBytesPerRowC = - 64 - * (dml_ceil_ex( - (src.viewport_height - / 2 - - 1) - / v->DataPTEReqHeightC, - 1) - + 1); - } - } else { - v->DPTEBytesPerRowC = 0; - } - } else { - v->DPTEBytesPerRowC = 0; - v->MetaPteBytesPerFrameC = 0; - v->MetaRowBytesC = 0; - } - - v->DPTEBytesPerRow[k] = v->DPTEBytesPerRowY + v->DPTEBytesPerRowC; - v->MetaPTEBytesPerFrame[k] = v->MetaPteBytesPerFrameY - + v->MetaPteBytesPerFrameC; - v->MetaRowBytes[k] = v->MetaRowBytesY + v->MetaRowBytesC; - - v->VInitY = (scale_ratio_depth.vscl_ratio + scale_taps.vtaps + 1 - + dest.interlaced * 0.5 - * scale_ratio_depth.vscl_ratio) - / 2.0; - v->PrefillY[k] = dml_floor_ex(v->VInitY, 1); - v->MaxNumSwY[k] = dml_ceil_ex( - (v->PrefillY[k] - 1.0) - / v->SwathHeightYPerState[ijk], - 1) + 1.0; - - if (v->PrefillY[k] > 1) { - v->MaxPartialSwY = ((int) (v->PrefillY[k] - 2)) - % ((int) v->SwathHeightYPerState[ijk]); - } else { - v->MaxPartialSwY = ((int) (v->PrefillY[k] - + v->SwathHeightYPerState[ijk] - 2)) - % ((int) v->SwathHeightYPerState[ijk]); - } - v->MaxPartialSwY = dml_max(1, v->MaxPartialSwY); - - v->PrefetchLinesY[k] = v->MaxNumSwY[k] - * v->SwathHeightYPerState[ijk] + v->MaxPartialSwY; - - if (src.source_format != dm_444_64 && src.source_format != dm_444_32 - && src.source_format != dm_444_16) { - v->VInitC = - (scale_ratio_depth.vscl_ratio / 2 - + scale_taps.vtaps + 1 - + dest.interlaced * 0.5 - * scale_ratio_depth.vscl_ratio - / 2) / 2.0; - v->PrefillC[k] = dml_floor_ex(v->VInitC, 1); - v->MaxNumSwC[k] = - dml_ceil_ex( - (v->PrefillC[k] - 1.0) - / v->SwathHeightCPerState[ijk], - 1) + 1.0; - if (v->PrefillC[k] > 1) { - v->MaxPartialSwC = - ((int) (v->PrefillC[k] - 2)) - % ((int) v->SwathHeightCPerState[ijk]); - } else { - v->MaxPartialSwC = - ((int) (v->PrefillC[k] - + v->SwathHeightCPerState[ijk] - - 2)) - % ((int) v->SwathHeightCPerState[ijk]); - } - v->MaxPartialSwC = dml_max(1, v->MaxPartialSwC); - - v->PrefetchLinesC[k] = v->MaxNumSwC[k] - * v->SwathHeightCPerState[ijk] - + v->MaxPartialSwC; - } else { - v->PrefetchLinesC[k] = 0; - } - - v->dst_x_after_scaler = 90 * dest.pixel_rate_mhz - / (v->RequiredDISPCLK[ij] / (j + 1)) - + 42 * dest.pixel_rate_mhz / v->RequiredDISPCLK[ij]; - if (v->NoOfDPP[ijk] > 1) { - v->dst_x_after_scaler = v->dst_x_after_scaler - + dest.recout_width / 2.0; - } - - if (dout.output_format == dm_420) { - v->dst_y_after_scaler = 1; - } else { - v->dst_y_after_scaler = 0; - } - - v->TimeCalc = 24 / v->ProjectedDCFCLKDeepSleep; - - v->VUpdateOffset = dml_ceil_ex(dest.htotal / 4, 1); - v->TotalRepeaterDelay = ip->max_inter_dcn_tile_repeaters - * (2 / (v->RequiredDISPCLK[ij] / (j + 1)) - + 3 / v->RequiredDISPCLK[ij]); - v->VUpdateWidth = (14 / v->ProjectedDCFCLKDeepSleep - + 12 / (v->RequiredDISPCLK[ij] / (j + 1)) - + v->TotalRepeaterDelay) * dest.pixel_rate_mhz; - v->VReadyOffset = - dml_max( - 150 - / (v->RequiredDISPCLK[ij] - / (j - + 1)), - v->TotalRepeaterDelay - + 20 - / v->ProjectedDCFCLKDeepSleep - + 10 - / (v->RequiredDISPCLK[ij] - / (j - + 1))) - * dest.pixel_rate_mhz; - - v->TimeSetup = - (v->VUpdateOffset + v->VUpdateWidth - + v->VReadyOffset) - / dest.pixel_rate_mhz; - - v->ExtraLatency = - v->UrgentRoundTripAndOutOfOrderLatencyPerState[i] - + (v->TotalNumberOfActiveDPP[ij] - * ip->pixel_chunk_size_kbytes - + v->TotalNumberOfDCCActiveDPP[ij] - * ip->meta_chunk_size_kbytes) - * 1024 - / v->ReturnBWPerState[i]; - - if (ip->pte_enable == 1) { - v->ExtraLatency = v->ExtraLatency - + v->TotalNumberOfActiveDPP[ij] - * ip->pte_chunk_size_kbytes - * 1024 - / v->ReturnBWPerState[i]; - } - - if (ip->can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one - == 1) { - v->MaximumVStartup = dest.vtotal - dest.vactive - 1; - } else { - v->MaximumVStartup = dest.vsync_plus_back_porch - 1; - } - - v->LineTimesForPrefetch[k] = - v->MaximumVStartup - - soc->urgent_latency_us - / (dest.htotal - / dest.pixel_rate_mhz) - - (v->TimeCalc + v->TimeSetup) - / (dest.htotal - / dest.pixel_rate_mhz) - - (v->dst_y_after_scaler - + v->dst_x_after_scaler - / dest.htotal); - - v->LineTimesForPrefetch[k] = dml_floor_ex( - 4.0 * (v->LineTimesForPrefetch[k] + 0.125), - 1) / 4; - - v->PrefetchBW[k] = - (v->MetaPTEBytesPerFrame[k] + 2 * v->MetaRowBytes[k] - + 2 * v->DPTEBytesPerRow[k] - + v->PrefetchLinesY[k] - * v->SwathWidthYPerState[ijk] - * dml_ceil_ex( - v->BytePerPixelInDETY[k], - 1) - + v->PrefetchLinesC[k] - * v->SwathWidthYPerState[ijk] - / 2 - * dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2)) - / (v->LineTimesForPrefetch[k] - * dest.htotal - / dest.pixel_rate_mhz); - } - - v->BWAvailableForImmediateFlip = v->ReturnBWPerState[i]; - - for (k = 0; k < num_planes; k++) { - v->BWAvailableForImmediateFlip = v->BWAvailableForImmediateFlip - - dml_max(v->ReadBandwidth[k], v->PrefetchBW[k]); - } - - v->TotalImmediateFlipBytes = 0; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - - if (src.source_format != dm_420_8 - && src.source_format != dm_420_10) { - v->TotalImmediateFlipBytes = v->TotalImmediateFlipBytes - + v->MetaPTEBytesPerFrame[k] - + v->MetaRowBytes[k] - + v->DPTEBytesPerRow[k]; - } - } - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - struct _vcs_dpi_display_pipe_dest_params_st dest = - e2e[v->planes[k].e2e_index].pipe.dest; - ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; - - if (ip->pte_enable == 1 && src.dcc == 1) { - v->TimeForMetaPTEWithImmediateFlip = - dml_max( - v->MetaPTEBytesPerFrame[k] - / v->PrefetchBW[k], - dml_max( - v->MetaPTEBytesPerFrame[k] - * v->TotalImmediateFlipBytes - / (v->BWAvailableForImmediateFlip - * (v->MetaPTEBytesPerFrame[k] - + v->MetaRowBytes[k] - + v->DPTEBytesPerRow[k])), - dml_max( - v->ExtraLatency, - dml_max( - soc->urgent_latency_us, - dest.htotal - / dest.pixel_rate_mhz - / 4)))); - - v->TimeForMetaPTEWithoutImmediateFlip = - dml_max( - v->MetaPTEBytesPerFrame[k] - / v->PrefetchBW[k], - dml_max( - v->ExtraLatency, - dest.htotal - / dest.pixel_rate_mhz - / 4)); - } else { - v->TimeForMetaPTEWithImmediateFlip = dest.htotal - / dest.pixel_rate_mhz / 4; - v->TimeForMetaPTEWithoutImmediateFlip = dest.htotal - / dest.pixel_rate_mhz / 4; - } - - if (ip->pte_enable == 1 || src.dcc == 1) { - v->TimeForMetaAndDPTERowWithImmediateFlip = - dml_max( - (v->MetaRowBytes[k] - + v->DPTEBytesPerRow[k]) - / v->PrefetchBW[k], - dml_max( - (v->MetaRowBytes[k] - + v->DPTEBytesPerRow[k]) - * v->TotalImmediateFlipBytes - / (v->BWAvailableForImmediateFlip - * (v->MetaPTEBytesPerFrame[k] - + v->MetaRowBytes[k] - + v->DPTEBytesPerRow[k])), - dml_max( - dest.htotal - / dest.pixel_rate_mhz - - v->TimeForMetaPTEWithImmediateFlip, - dml_max( - v->ExtraLatency, - 2 - * soc->urgent_latency_us)))); - - v->TimeForMetaAndDPTERowWithoutImmediateFlip = - dml_max( - (v->MetaRowBytes[k] - + v->DPTEBytesPerRow[k]) - / v->PrefetchBW[k], - dml_max( - dest.htotal - / dest.pixel_rate_mhz - - v->TimeForMetaPTEWithoutImmediateFlip, - v->ExtraLatency)); - } else { - v->TimeForMetaAndDPTERowWithImmediateFlip = - dml_max( - dest.htotal - / dest.pixel_rate_mhz - - v->TimeForMetaPTEWithImmediateFlip, - v->ExtraLatency - - v->TimeForMetaPTEWithImmediateFlip); - v->TimeForMetaAndDPTERowWithoutImmediateFlip = - dml_max( - dest.htotal - / dest.pixel_rate_mhz - - v->TimeForMetaPTEWithoutImmediateFlip, - v->ExtraLatency - - v->TimeForMetaPTEWithoutImmediateFlip); - } - - v->LinesForMetaPTEWithImmediateFlip[k] = - dml_floor_ex( - 4.0 - * (v->TimeForMetaPTEWithImmediateFlip - / (dest.htotal - / dest.pixel_rate_mhz) - + 0.125), - 1) / 4.0; - - v->LinesForMetaPTEWithoutImmediateFlip[k] = - dml_floor_ex( - 4.0 - * (v->TimeForMetaPTEWithoutImmediateFlip - / (dest.htotal - / dest.pixel_rate_mhz) - + 0.125), - 1) / 4.0; - - v->LinesForMetaAndDPTERowWithImmediateFlip[k] = - dml_floor_ex( - 4.0 - * (v->TimeForMetaAndDPTERowWithImmediateFlip - / (dest.htotal - / dest.pixel_rate_mhz) - + 0.125), - 1) / 4.0; - - v->LinesForMetaAndDPTERowWithoutImmediateFlip[k] = - dml_floor_ex( - 4.0 - * (v->TimeForMetaAndDPTERowWithoutImmediateFlip - / (dest.htotal - / dest.pixel_rate_mhz) - + 0.125), - 1) / 4.0; - - v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip = - v->LineTimesForPrefetch[k] - - v->LinesForMetaPTEWithImmediateFlip[k] - - v->LinesForMetaAndDPTERowWithImmediateFlip[k]; - - v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip = - v->LineTimesForPrefetch[k] - - v->LinesForMetaPTEWithoutImmediateFlip[k] - - v->LinesForMetaAndDPTERowWithoutImmediateFlip[k]; - - if (v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip > 0) { - v->VRatioPreYWithImmediateFlip[ijk] = - v->PrefetchLinesY[k] - / v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip; - if (v->SwathHeightYPerState[ijk] > 4) { - if (v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip - - (v->PrefillY[k] - 3.0) / 2.0 - > 0) { - v->VRatioPreYWithImmediateFlip[ijk] = - dml_max( - v->VRatioPreYWithImmediateFlip[ijk], - (v->MaxNumSwY[k] - * v->SwathHeightYPerState[ijk]) - / (v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip - - (v->PrefillY[k] - - 3.0) - / 2.0)); - } else { - v->VRatioPreYWithImmediateFlip[ijk] = - 999999; - } - } - v->VRatioPreCWithImmediateFlip[ijk] = - v->PrefetchLinesC[k] - / v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip; - if (v->SwathHeightCPerState[ijk] > 4) { - if (v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip - - (v->PrefillC[k] - 3.0) / 2.0 - > 0) { - v->VRatioPreCWithImmediateFlip[ijk] = - dml_max( - v->VRatioPreCWithImmediateFlip[ijk], - (v->MaxNumSwC[k] - * v->SwathHeightCPerState[ijk]) - / (v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip - - (v->PrefillC[k] - - 3.0) - / 2.0)); - } else { - v->VRatioPreCWithImmediateFlip[ijk] = - 999999; - } - } - - v->RequiredPrefetchPixelDataBWWithImmediateFlip[ijk] = - v->NoOfDPP[ijk] - * (v->PrefetchLinesY[k] - / v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip - * dml_ceil_ex( - v->BytePerPixelInDETY[k], - 1) - + v->PrefetchLinesC[k] - / v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip - * dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2) - / 2) - * v->SwathWidthYPerState[ijk] - / (dest.htotal - / dest.pixel_rate_mhz); - } else { - v->VRatioPreYWithImmediateFlip[ijk] = 999999; - v->VRatioPreCWithImmediateFlip[ijk] = 999999; - v->RequiredPrefetchPixelDataBWWithImmediateFlip[ijk] = - 999999; - } - - if (v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip - > 0) { - v->VRatioPreYWithoutImmediateFlip[ijk] = - v->PrefetchLinesY[k] - / v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip; - if (v->SwathHeightYPerState[ijk] > 4) { - if (v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip - - (v->PrefillY[k] - 3.0) / 2.0 - > 0) { - v->VRatioPreYWithoutImmediateFlip[ijk] = - dml_max( - v->VRatioPreYWithoutImmediateFlip[ijk], - (v->MaxNumSwY[k] - * v->SwathHeightYPerState[ijk]) - / (v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip - - (v->PrefillY[k] - - 3.0) - / 2.0)); - } else { - v->VRatioPreYWithoutImmediateFlip[ijk] = - 999999; - } - } - v->VRatioPreCWithoutImmediateFlip[ijk] = - v->PrefetchLinesC[k] - / v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip; - if (v->SwathHeightCPerState[ijk] > 4) { - if (v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip - - (v->PrefillC[k] - 3.0) / 2.0 - > 0) { - v->VRatioPreCWithoutImmediateFlip[ijk] = - dml_max( - v->VRatioPreCWithoutImmediateFlip[ijk], - (v->MaxNumSwC[k] - * v->SwathHeightCPerState[ijk]) - / (v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip - - (v->PrefillC[k] - - 3.0) - / 2.0)); - } else { - v->VRatioPreCWithoutImmediateFlip[ijk] = - 999999; - } - } - - v->RequiredPrefetchPixelDataBWWithoutImmediateFlip[ijk] = - v->NoOfDPP[ijk] - * (v->PrefetchLinesY[k] - / v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip - * dml_ceil_ex( - v->BytePerPixelInDETY[k], - 1) - + v->PrefetchLinesC[k] - / v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip - * dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2) - / 2) - * v->SwathWidthYPerState[ijk] - / (dest.htotal - / dest.pixel_rate_mhz); - } else { - v->VRatioPreYWithoutImmediateFlip[ijk] = 999999; - v->VRatioPreCWithoutImmediateFlip[ijk] = 999999; - v->RequiredPrefetchPixelDataBWWithoutImmediateFlip[ijk] = - 999999; - } - } - - v->MaximumReadBandwidthWithPrefetchWithImmediateFlip = 0; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - struct _vcs_dpi_display_pipe_dest_params_st dest = - e2e[v->planes[k].e2e_index].pipe.dest; - ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; - - if (src.source_format != dm_420_8 - && src.source_format != dm_420_10) { - v->MaximumReadBandwidthWithPrefetchWithImmediateFlip = - v->MaximumReadBandwidthWithPrefetchWithImmediateFlip - + dml_max( - v->ReadBandwidth[k], - v->RequiredPrefetchPixelDataBWWithImmediateFlip[ijk]) - + dml_max( - v->MetaPTEBytesPerFrame[k] - / (v->LinesForMetaPTEWithImmediateFlip[k] - * dest.htotal - / dest.pixel_rate_mhz), - (v->MetaRowBytes[k] - + v->DPTEBytesPerRow[k]) - / (v->LinesForMetaAndDPTERowWithImmediateFlip[k] - * dest.htotal - / dest.pixel_rate_mhz)); - } else { - v->MaximumReadBandwidthWithPrefetchWithImmediateFlip = - v->MaximumReadBandwidthWithPrefetchWithImmediateFlip - + dml_max( - v->ReadBandwidth[k], - v->RequiredPrefetchPixelDataBWWithoutImmediateFlip[ijk]); - } - } - - v->MaximumReadBandwidthWithPrefetchWithoutImmediateFlip = 0; - - for (k = 0; k < num_planes; k++) { - ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; - - v->MaximumReadBandwidthWithPrefetchWithoutImmediateFlip = - v->MaximumReadBandwidthWithPrefetchWithoutImmediateFlip - + dml_max( - v->ReadBandwidth[k], - v->RequiredPrefetchPixelDataBWWithoutImmediateFlip[ijk]); - } - - v->PrefetchSupportedWithImmediateFlip[ij] = 1; - if (v->MaximumReadBandwidthWithPrefetchWithImmediateFlip - > v->ReturnBWPerState[i]) { - v->PrefetchSupportedWithImmediateFlip[ij] = 0; - } - for (k = 0; k < num_planes; k++) { - if (v->LineTimesForPrefetch[k] < 2 - || v->LinesForMetaPTEWithImmediateFlip[k] >= 8 - || v->LinesForMetaAndDPTERowWithImmediateFlip[k] - >= 16) { - v->PrefetchSupportedWithImmediateFlip[ij] = 0; - } - } - - v->PrefetchSupportedWithoutImmediateFlip[ij] = 1; - if (v->MaximumReadBandwidthWithPrefetchWithoutImmediateFlip - > v->ReturnBWPerState[i]) { - v->PrefetchSupportedWithoutImmediateFlip[ij] = 0; - } - for (k = 0; k < num_planes; k++) { - if (v->LineTimesForPrefetch[k] < 2 - || v->LinesForMetaPTEWithoutImmediateFlip[k] >= 8 - || v->LinesForMetaAndDPTERowWithoutImmediateFlip[k] - >= 16) { - v->PrefetchSupportedWithoutImmediateFlip[ij] = 0; - } - } - } - } - - for (i = 0; i < NumberOfStatesPlusTwo; i++) { - for (j = 0; j < 2; j++) { - ij = j * NumberOfStatesPlusTwo + i; - - v->VRatioInPrefetchSupportedWithImmediateFlip[ij] = 1; - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; - - if (((src.source_format != dm_420_8 - && src.source_format != dm_420_10) - && (v->VRatioPreYWithImmediateFlip[ijk] > 4 - || v->VRatioPreCWithImmediateFlip[ijk] - > 4)) - || ((src.source_format == dm_420_8 - || src.source_format == dm_420_10) - && (v->VRatioPreYWithoutImmediateFlip[ijk] - > 4 - || v->VRatioPreCWithoutImmediateFlip[ijk] - > 4))) { - v->VRatioInPrefetchSupportedWithImmediateFlip[ij] = 0; - } - } - v->VRatioInPrefetchSupportedWithoutImmediateFlip[ij] = 1; - for (k = 0; k < num_planes; k++) { - ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; - - if (v->VRatioPreYWithoutImmediateFlip[ijk] > 4 - || v->VRatioPreCWithoutImmediateFlip[ijk] > 4) { - v->VRatioInPrefetchSupportedWithoutImmediateFlip[ij] = 0; - } - } - } - } - - // Mode Support, Voltage State and SOC Configuration - - for (i = (NumberOfStatesPlusTwo - 1); i >= 0; i--) // use int type here - { - for (j = 0; j < 2; j++) { - ij = j * NumberOfStatesPlusTwo + i; - - if (v->ScaleRatioSupport == 1 && v->SourceFormatPixelAndScanSupport == 1 - && v->ViewportSizeSupport == 1 - && v->BandwidthSupport[i] == 1 && v->DIOSupport[i] == 1 - && v->UrgentLatencySupport[ij] == 1 && v->ROBSupport[i] == 1 - && v->DISPCLK_DPPCLK_Support[ij] == 1 - && v->TotalAvailablePipesSupport[ij] == 1 - && v->TotalAvailableWritebackSupport == 1 - && v->WritebackLatencySupport == 1) { - if (v->PrefetchSupportedWithImmediateFlip[ij] == 1 - && v->VRatioInPrefetchSupportedWithImmediateFlip[ij] - == 1) { - v->ModeSupportWithImmediateFlip[ij] = 1; - } else { - v->ModeSupportWithImmediateFlip[ij] = 0; - } - if (v->PrefetchSupportedWithoutImmediateFlip[ij] == 1 - && v->VRatioInPrefetchSupportedWithoutImmediateFlip[ij] - == 1) { - v->ModeSupportWithoutImmediateFlip[ij] = 1; - } else { - v->ModeSupportWithoutImmediateFlip[ij] = 0; - } - } else { - v->ModeSupportWithImmediateFlip[ij] = 0; - v->ModeSupportWithoutImmediateFlip[ij] = 0; - } - } - } - - for (i = (NumberOfStatesPlusTwo - 1); i >= 0; i--) // use int type here - { - if ((i == (NumberOfStatesPlusTwo - 1) - || v->ModeSupportWithImmediateFlip[1 * NumberOfStatesPlusTwo + i] - == 1 - || v->ModeSupportWithImmediateFlip[0 * NumberOfStatesPlusTwo + i] - == 1) && i >= v->VoltageOverrideLevel) { - v->VoltageLevelWithImmediateFlip = i; - } - } - - for (i = (NumberOfStatesPlusTwo - 1); i >= 0; i--) // use int type here - { - if ((i == (NumberOfStatesPlusTwo - 1) - || v->ModeSupportWithoutImmediateFlip[1 * NumberOfStatesPlusTwo + i] - == 1 - || v->ModeSupportWithoutImmediateFlip[0 * NumberOfStatesPlusTwo + i] - == 1) && i >= v->VoltageOverrideLevel) { - v->VoltageLevelWithoutImmediateFlip = i; - } - } - - if (v->VoltageLevelWithImmediateFlip == (NumberOfStatesPlusTwo - 1)) { - v->ImmediateFlipSupported = 0; - v->VoltageLevel = v->VoltageLevelWithoutImmediateFlip; - } else { - v->ImmediateFlipSupported = 1; - v->VoltageLevel = v->VoltageLevelWithImmediateFlip; - } - - v->DCFCLK = v->DCFCLKPerState[(int) v->VoltageLevel]; - v->FabricAndDRAMBandwidth = v->FabricAndDRAMBandwidthPerState[(int) v->VoltageLevel]; - - for (j = 0; j < 2; j++) { - v->RequiredDISPCLKPerRatio[j] = v->RequiredDISPCLK[j * NumberOfStatesPlusTwo - + (int) v->VoltageLevel]; - for (k = 0; k < num_planes; k++) { - v->DPPPerPlanePerRatio[k * 2 + j] = v->NoOfDPP[k * 2 * NumberOfStatesPlusTwo - + j * NumberOfStatesPlusTwo + (int) v->VoltageLevel]; - } - v->DISPCLK_DPPCLK_SupportPerRatio[j] = v->DISPCLK_DPPCLK_Support[j - * NumberOfStatesPlusTwo + (int) v->VoltageLevel]; - } - - ASSERT(v->ImmediateFlipSupported || v->MacroTileBlockWidthC || v->DCFCLK || v->FabricAndDRAMBandwidth); - - return (v->VoltageLevel); -} - diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.h index ead4942f998c..d4ea0371cde2 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.h @@ -191,9 +191,4 @@ struct dml_ms_internal_vars { struct _vcs_dpi_wm_calc_pipe_params_st planes[DC__NUM_PIPES__MAX]; }; -int dml_ms_check( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - int num_pipes); - #endif -- cgit From e9d7dc62bc09bd95461d5444b54d59195b207fd6 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 28 Sep 2017 12:42:01 +1000 Subject: amdgpu/dc: don't check for 0 on register read/writes always. This adds ~50k to the driver text segment, and 10k to data segment. text data bss dec hex filename 2385556 39681 1045 2426282 2505aa drivers/gpu/drm/amd/amdgpu/amdgpu.o text data bss dec hex filename 2336593 28857 1045 2366495 241c1f drivers/gpu/drm/amd/amdgpu/amdgpu.o Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dm_services.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dm_services.h b/drivers/gpu/drm/amd/display/dc/dm_services.h index 8ab0af6f4c6b..c976e2aa10e0 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services.h @@ -96,6 +96,9 @@ irq_handler_idx dm_register_interrupt( * */ +/* enable for debugging new code, this adds 50k to the driver size. */ +/* #define DM_CHECK_ADDR_0 */ + #define dm_read_reg(ctx, address) \ dm_read_reg_func(ctx, address, __func__) @@ -105,12 +108,12 @@ static inline uint32_t dm_read_reg_func( const char *func_name) { uint32_t value; - +#ifdef DM_CHECK_ADDR_0 if (address == 0) { DC_ERR("invalid register read; address = 0\n"); return 0; } - +#endif value = cgs_read_register(ctx->cgs_device, address); return value; @@ -125,10 +128,12 @@ static inline void dm_write_reg_func( uint32_t value, const char *func_name) { +#ifdef DM_CHECK_ADDR_0 if (address == 0) { DC_ERR("invalid register write. address = 0"); return; } +#endif cgs_write_register(ctx->cgs_device, address, value); } -- cgit From 29656a363c1f3060e9a5b3bafa0bd4b589e20e3c Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 28 Sep 2017 13:29:32 +1000 Subject: amdgpu/dc: remove wait_reg/wait_reg_func interfaces. These aren't used in the tree anywhere, and there is a TODO. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dm_services.h | 46 ---------------------------- 1 file changed, 46 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dm_services.h b/drivers/gpu/drm/amd/display/dc/dm_services.h index c976e2aa10e0..8166027d2d83 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services.h @@ -236,52 +236,6 @@ unsigned int generic_reg_wait(const struct dc_context *ctx, block ## reg_num ## _ ## reg_name ## __ ## reg_field ## _MASK,\ block ## reg_num ## _ ## reg_name ## __ ## reg_field ## __SHIFT) -/* TODO get rid of this pos*/ -static inline bool wait_reg_func( - const struct dc_context *ctx, - uint32_t addr, - uint32_t mask, - uint8_t shift, - uint32_t condition_value, - unsigned int interval_us, - unsigned int timeout_us) -{ - uint32_t field_value; - uint32_t reg_val; - unsigned int count = 0; - - if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment)) - timeout_us *= 655; /* 6553 give about 30 second before time out */ - - do { - /* try once without sleeping */ - if (count > 0) { - if (interval_us >= 1000) - msleep(interval_us/1000); - else - udelay(interval_us); - } - reg_val = dm_read_reg(ctx, addr); - field_value = get_reg_field_value_ex(reg_val, mask, shift); - count += interval_us; - - } while (field_value != condition_value && count <= timeout_us); - - ASSERT(count <= timeout_us); - - return count <= timeout_us; -} - -#define wait_reg(ctx, inst_offset, reg_name, reg_field, condition_value)\ - wait_reg_func(\ - ctx,\ - mm##reg_name + inst_offset + DCE_BASE.instance[0].segment[mm##reg_name##_BASE_IDX],\ - reg_name ## __ ## reg_field ## _MASK,\ - reg_name ## __ ## reg_field ## __SHIFT,\ - condition_value,\ - 20000,\ - 200000) - /************************************** * Power Play (PP) interfaces **************************************/ -- cgit From a2e74cb626d2e1587a5ec35c3ccfc26104bdfa30 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 28 Sep 2017 15:39:41 -0400 Subject: drm/amd/display: Remove DWB It's not in a good shape and currently completely unused. Signed-off-by: Harry Wentland Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 9 - drivers/gpu/drm/amd/display/dc/dcn10/Makefile | 2 +- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c | 365 --------------------- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.h | 277 ---------------- .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 57 ---- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 3 - drivers/gpu/drm/amd/display/dc/inc/hw/dwb.h | 193 ----------- 7 files changed, 1 insertion(+), 905 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.h delete mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw/dwb.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index d86d9796e4cc..7fd42fc8bdfa 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1525,15 +1525,6 @@ struct dc_link *dc_get_link_at_index(struct dc *dc, uint32_t link_index) return dc->links[link_index]; } -struct dwbc *dc_get_dwb_at_pipe(struct dc *dc, uint32_t pipe) -{ - if ((pipe >= dwb_pipe0) && (pipe < dwb_pipe_max_num)) { - return dc->res_pool->dwbc[(int)pipe]; - } else { - return NULL; - } -} - const struct graphics_object_id dc_get_link_id_at_index( struct dc *dc, uint32_t link_index) { diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile index e92ac2997a1a..2d6d3a371858 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile @@ -3,7 +3,7 @@ DCN10 = dcn10_resource.o dcn10_ipp.o dcn10_hw_sequencer.o \ dcn10_dpp.o dcn10_opp.o dcn10_timing_generator.o \ - dcn10_mem_input.o dcn10_mpc.o dcn10_dwb.o \ + dcn10_mem_input.o dcn10_mpc.o \ dcn10_dpp_dscl.o dcn10_dpp_cm.o dcn10_dpp_cm_helper.o AMD_DAL_DCN10 = $(addprefix $(AMDDALPATH)/dc/dcn10/,$(DCN10)) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c deleted file mode 100644 index 4ec5554f0f5b..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c +++ /dev/null @@ -1,365 +0,0 @@ -/* - * Copyright 2012-17 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) - -#include "reg_helper.h" -#include "resource.h" -#include "dwb.h" -#include "dcn10_dwb.h" - - -#define REG(reg)\ - dwbc10->dwbc_regs->reg - -#define CTX \ - dwbc10->base.ctx - -#undef FN -#define FN(reg_name, field_name) \ - dwbc10->dwbc_shift->field_name, dwbc10->dwbc_mask->field_name - -#define TO_DCN10_DWBC(dwbc_base) \ - container_of(dwbc_base, struct dcn10_dwbc, base) - -static bool get_caps(struct dwbc *dwbc, struct dwb_caps *caps) -{ - if (caps) { - caps->adapter_id = 0; /* we only support 1 adapter currently */ - caps->hw_version = DCN_VERSION_1_0; - caps->num_pipes = 2; - memset(&caps->reserved, 0, sizeof(caps->reserved)); - memset(&caps->reserved2, 0, sizeof(caps->reserved2)); - caps->sw_version = dwb_ver_1_0; - caps->caps.support_dwb = true; - caps->caps.support_ogam = false; - caps->caps.support_wbscl = true; - caps->caps.support_ocsc = false; - return true; - } else { - return false; - } -} - -static bool enable(struct dwbc *dwbc) -{ - struct dcn10_dwbc *dwbc10 = TO_DCN10_DWBC(dwbc); - - /* disable first. */ - dwbc->funcs->disable(dwbc); - - /* disable power gating */ - REG_UPDATE_5(WB_EC_CONFIG, DISPCLK_R_WB_GATE_DIS, 1, - DISPCLK_G_WB_GATE_DIS, 1, DISPCLK_G_WBSCL_GATE_DIS, 1, - WB_LB_LS_DIS, 1, WB_LUT_LS_DIS, 1); - - REG_UPDATE(WB_ENABLE, WB_ENABLE, 1); - - /* lock buffer0~buffer3 */ - REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_LOCK, 0xf); - - /* buffer address for packing mode or Luma in planar mode */ - REG_UPDATE(MCIF_WB_BUF_1_ADDR_Y, MCIF_WB_BUF_1_ADDR_Y, (dwbc->config.basic_settings.luma_address[0] & 0xffffffff)); -/* REG_UPDATE(MCIF_WB_BUF_1_ADDR_Y_HIGH, MCIF_WB_BUF_1_ADDR_Y_HIGH, (dwbc->config.basic_settings.luma_address[0] >> 32)); */ - /* right eye sub-buffer address offset for packing mode or Luma in planar mode */ - REG_UPDATE(MCIF_WB_BUF_1_ADDR_Y_OFFSET, MCIF_WB_BUF_1_ADDR_Y_OFFSET, 0); - - /* buffer address for Chroma in planar mode (unused in packing mode) */ - REG_UPDATE(MCIF_WB_BUF_1_ADDR_C, MCIF_WB_BUF_1_ADDR_C, (dwbc->config.basic_settings.chroma_address[0] & 0xffffffff)); -/* REG_UPDATE(MCIF_WB_BUF_1_ADDR_C_HIGH, MCIF_WB_BUF_1_ADDR_C_HIGH, (dwbc->config.basic_settings.chroma_address[0] >> 32)); */ - /* right eye offset for packing mode or Luma in planar mode */ - REG_UPDATE(MCIF_WB_BUF_1_ADDR_C_OFFSET, MCIF_WB_BUF_1_ADDR_C_OFFSET, 0); - - /* buffer address for packing mode or Luma in planar mode */ - REG_UPDATE(MCIF_WB_BUF_2_ADDR_Y, MCIF_WB_BUF_2_ADDR_Y, (dwbc->config.basic_settings.luma_address[1] & 0xffffffff)); -/* REG_UPDATE(MCIF_WB_BUF_2_ADDR_Y_HIGH, MCIF_WB_BUF_2_ADDR_Y_HIGH, (dwbc->config.basic_settings.luma_address[1] >> 32)); */ - /* right eye sub-buffer address offset for packing mode or Luma in planar mode */ - REG_UPDATE(MCIF_WB_BUF_2_ADDR_Y_OFFSET, MCIF_WB_BUF_2_ADDR_Y_OFFSET, 0); - - /* buffer address for Chroma in planar mode (unused in packing mode) */ - REG_UPDATE(MCIF_WB_BUF_2_ADDR_C, MCIF_WB_BUF_2_ADDR_C, (dwbc->config.basic_settings.chroma_address[1] & 0xffffffff)); -/* REG_UPDATE(MCIF_WB_BUF_2_ADDR_C_HIGH, MCIF_WB_BUF_2_ADDR_C_HIGH, (dwbc->config.basic_settings.chroma_address[1] >> 32)); */ - /* right eye offset for packing mode or Luma in planar mode */ - REG_UPDATE(MCIF_WB_BUF_2_ADDR_C_OFFSET, MCIF_WB_BUF_2_ADDR_C_OFFSET, 0); - - /* buffer address for packing mode or Luma in planar mode */ - REG_UPDATE(MCIF_WB_BUF_3_ADDR_Y, MCIF_WB_BUF_3_ADDR_Y, (dwbc->config.basic_settings.luma_address[2] & 0xffffffff)); -/* REG_UPDATE(MCIF_WB_BUF_3_ADDR_Y_HIGH, MCIF_WB_BUF_3_ADDR_Y_HIGH, (dwbc->config.basic_settings.luma_address[2] >> 32)); */ - /* right eye sub-buffer address offset for packing mode or Luma in planar mode */ - REG_UPDATE(MCIF_WB_BUF_3_ADDR_Y_OFFSET, MCIF_WB_BUF_3_ADDR_Y_OFFSET, 0); - - /* buffer address for Chroma in planar mode (unused in packing mode) */ - REG_UPDATE(MCIF_WB_BUF_3_ADDR_C, MCIF_WB_BUF_3_ADDR_C, (dwbc->config.basic_settings.chroma_address[2] & 0xffffffff)); -/* REG_UPDATE(MCIF_WB_BUF_3_ADDR_C_HIGH, MCIF_WB_BUF_3_ADDR_C_HIGH, (dwbc->config.basic_settings.chroma_address[2] >> 32)); */ - /* right eye offset for packing mode or Luma in planar mode */ - REG_UPDATE(MCIF_WB_BUF_3_ADDR_C_OFFSET, MCIF_WB_BUF_3_ADDR_C_OFFSET, 0); - - /* buffer address for packing mode or Luma in planar mode */ - REG_UPDATE(MCIF_WB_BUF_4_ADDR_Y, MCIF_WB_BUF_4_ADDR_Y, (dwbc->config.basic_settings.luma_address[3] & 0xffffffff)); -/* REG_UPDATE(MCIF_WB_BUF_4_ADDR_Y_HIGH, MCIF_WB_BUF_4_ADDR_Y_HIGH, (dwbc->config.basic_settings.luma_address[3] >> 32)); */ - /* right eye sub-buffer address offset for packing mode or Luma in planar mode */ - REG_UPDATE(MCIF_WB_BUF_4_ADDR_Y_OFFSET, MCIF_WB_BUF_4_ADDR_Y_OFFSET, 0); - - /* buffer address for Chroma in planar mode (unused in packing mode) */ - REG_UPDATE(MCIF_WB_BUF_4_ADDR_C, MCIF_WB_BUF_4_ADDR_C, (dwbc->config.basic_settings.chroma_address[3] & 0xffffffff)); -/* REG_UPDATE(MCIF_WB_BUF_4_ADDR_C_HIGH, MCIF_WB_BUF_4_ADDR_C_HIGH, (dwbc->config.basic_settings.chroma_address[3] >> 32)); */ - /* right eye offset for packing mode or Luma in planar mode */ - REG_UPDATE(MCIF_WB_BUF_4_ADDR_C_OFFSET, MCIF_WB_BUF_4_ADDR_C_OFFSET, 0); - - /* setup luma & chroma size */ - REG_UPDATE(MCIF_WB_BUF_LUMA_SIZE, MCIF_WB_BUF_LUMA_SIZE, dwbc->config.basic_settings.luma_pitch * dwbc->config.basic_settings.dest_height); /* should be enough to contain a whole frame Luma data, same for stereo mode */ - REG_UPDATE(MCIF_WB_BUF_CHROMA_SIZE, MCIF_WB_BUF_CHROMA_SIZE, dwbc->config.basic_settings.chroma_pitch * dwbc->config.basic_settings.dest_height); /* should be enough to contain a whole frame Luma data, same for stereo mode */ - - /* enable address fence */ - REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUF_ADDR_FENCE_EN, 1); - - /* setup pitch */ - REG_UPDATE_2(MCIF_WB_BUF_PITCH, MCIF_WB_BUF_LUMA_PITCH, dwbc->config.basic_settings.luma_pitch, - MCIF_WB_BUF_CHROMA_PITCH, dwbc->config.basic_settings.chroma_pitch); - - /* Set pitch for MC cache warm up mode */ - /* Pitch is 256 bytes aligned. The default pitch is 4K */ - REG_UPDATE(MCIF_WB_WARM_UP_CNTL, MCIF_WB_PITCH_SIZE_WARMUP, 0x10); /* default is 0x10 */ - - /* Programmed by the video driver based on the CRTC timing (for DWB) */ - REG_UPDATE(MCIF_WB_ARBITRATION_CONTROL, MCIF_WB_TIME_PER_PIXEL, 0); - - /* Programming dwb watermark */ - /* Watermark to generate urgent in MCIF_WB_CLI, value is determined by MCIF_WB_CLI_WATERMARK_MASK. */ - /* Program in ns. A formula will be provided in the pseudo code to calculate the value. */ - REG_UPDATE(MCIF_WB_SCLK_CHANGE, MCIF_WB_CLI_WATERMARK_MASK, 0x0); - REG_UPDATE(MCIF_WB_WATERMARK, MCIF_WB_CLI_WATERMARK, 0xffff); /* urgent_watermarkA */ - REG_UPDATE(MCIF_WB_SCLK_CHANGE, MCIF_WB_CLI_WATERMARK_MASK, 0x1); - REG_UPDATE(MCIF_WB_WATERMARK, MCIF_WB_CLI_WATERMARK, 0xffff); /* urgent_watermarkB */ - REG_UPDATE(MCIF_WB_SCLK_CHANGE, MCIF_WB_CLI_WATERMARK_MASK, 0x2); - REG_UPDATE(MCIF_WB_WATERMARK, MCIF_WB_CLI_WATERMARK, 0xffff); /* urgent_watermarkC */ - REG_UPDATE(MCIF_WB_SCLK_CHANGE, MCIF_WB_CLI_WATERMARK_MASK, 0x3); - REG_UPDATE(MCIF_WB_WATERMARK, MCIF_WB_CLI_WATERMARK, 0xffff); /* urgent_watermarkD */ - - /* Programming nb pstate watermark */ - REG_UPDATE(MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_CHANGE_WATERMARK_MASK, 0x0); - REG_UPDATE(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, NB_PSTATE_CHANGE_REFRESH_WATERMARK, 0xffff); /* nbp_state_change_watermarkA */ - REG_UPDATE(MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_CHANGE_WATERMARK_MASK, 0x1); - REG_UPDATE(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, NB_PSTATE_CHANGE_REFRESH_WATERMARK, 0xffff); /* nbp_state_change_watermarkB */ - REG_UPDATE(MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_CHANGE_WATERMARK_MASK, 0x2); - REG_UPDATE(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, NB_PSTATE_CHANGE_REFRESH_WATERMARK, 0xffff); /* nbp_state_change_watermarkC */ - REG_UPDATE(MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_CHANGE_WATERMARK_MASK, 0x3); - REG_UPDATE(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, NB_PSTATE_CHANGE_REFRESH_WATERMARK, 0xffff); /* nbp_state_change_watermarkD */ - - /* buf_lh_capability = (buffer_size / byte_per_pixel)*time_per_pixel; //client buffer latency hiding capability */ - /* if (MCIF_WB_CLI_WATERMARK * 2 < buf_lh_capability) //factor '2' can be adjusted if better value is identified during bringup/debug */ - /* MULTI_LEVEL_QOS_CTRL.MAX_SCALED_TIME_TO_URGENT = MCIF_WB_CLI_WATERMARK * 2; */ - /* else */ - /* MULTI_LEVEL_QOS_CTRL.MAX_SCALED_TIME_TO_URGENT = buf_lh_capability; //ensure QoS can be fully mapped to [0:15] region in any scenario */ - - REG_UPDATE(MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_SLICE_SIZE, 31); - - /* Set arbitration unit for Luma/Chroma */ - /* arb_unit=2 should be chosen for more efficiency */ - REG_UPDATE(MCIF_WB_ARBITRATION_CONTROL, MCIF_WB_CLIENT_ARBITRATION_SLICE, 2); /* Arbitration size, 0: 512 bytes 1: 1024 bytes 2: 2048 Bytes */ - - /* Program VMID, don't support virtual mode, won't set VMID */ - /* REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_P_VMID, pVmid); */ - - if (dwbc->config.basic_settings.input_pipe_select == dwb_pipe0) { - REG_UPDATE(DWB_SOURCE_SELECT, OPTC_DWB0_SOURCE_SELECT, dwbc->config.basic_settings.input_src_select - dwb_src_otg0); - } else if (dwbc->config.basic_settings.input_pipe_select == dwb_pipe1) { - REG_UPDATE(DWB_SOURCE_SELECT, OPTC_DWB1_SOURCE_SELECT, dwbc->config.basic_settings.input_src_select - dwb_src_otg0); - } - - /* Set interrupt mask */ - REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_INT_EN, 0); /* Disable interrupt to SW. (the default value is 0.) */ - REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_SLICE_INT_EN, 0); /* Disable slice complete interrupt to SW.(the default value is 0.) */ - REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_OVERRUN_INT_EN, 0); /* Disable frame buffer overrun interrupt to SW. (the default value is 0.) */ - - REG_UPDATE(MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_INT_EN, 1); /* Enable interrupt to VCE */ - REG_UPDATE(MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_SLICE_INT_EN, 0); /* Disable slice complete interrupt to VCE. */ - - /* ////////////////// */ - /* Enable Mcifwb */ - REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_ENABLE, 1); /* Start working */ - - /* unlock sw lock. */ - REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_LOCK, 0); - - dwbc->status.enabled = true; - - return true; -} - -static bool disable(struct dwbc *dwbc) -{ - struct dcn10_dwbc *dwbc10 = TO_DCN10_DWBC(dwbc); - - /* disable CNV */ - REG_UPDATE(CNV_MODE, CNV_FRAME_CAPTURE_EN, 0); - - /* disable WB */ - REG_UPDATE(WB_ENABLE, WB_ENABLE, 0); - - /* soft reset */ - REG_UPDATE(WB_SOFT_RESET, WB_SOFT_RESET, 1); - REG_UPDATE(WB_SOFT_RESET, WB_SOFT_RESET, 0); - - /* enable power gating */ - REG_UPDATE_5(WB_EC_CONFIG, DISPCLK_R_WB_GATE_DIS, 0, - DISPCLK_G_WB_GATE_DIS, 0, DISPCLK_G_WBSCL_GATE_DIS, 0, - WB_LB_LS_DIS, 0, WB_LUT_LS_DIS, 0); - - /* disable buffer manager */ - REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_ENABLE, 0); - - dwbc->status.enabled = false; - - return true; -} - -static bool get_status(struct dwbc *dwbc, struct dwb_status *status) -{ - if (status) { - memcpy(status, &dwbc->status, sizeof(struct dwb_status)); - return true; - } else { - return false; - } -} - -static bool dump_frame(struct dwbc *dwbc, struct dwb_frame_info *frame_info, - unsigned char *luma_buffer, unsigned char *chroma_buffer, - unsigned char *dest_luma_buffer, unsigned char *dest_chroma_buffer) -{ - struct dcn10_dwbc *dwbc10 = TO_DCN10_DWBC(dwbc); - - REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_LOCK, 0xf); - - memcpy(dest_luma_buffer, luma_buffer, dwbc->config.basic_settings.luma_pitch * dwbc->config.basic_settings.dest_height); - memcpy(dest_chroma_buffer, chroma_buffer, dwbc->config.basic_settings.chroma_pitch * dwbc->config.basic_settings.dest_height / 2); - - REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_LOCK, 0x0); - - frame_info->format = dwbc->config.advanced_settings.out_format; - frame_info->width = dwbc->config.basic_settings.dest_width; - frame_info->height = dwbc->config.basic_settings.dest_height; - frame_info->luma_pitch = dwbc->config.basic_settings.luma_pitch; - frame_info->chroma_pitch = dwbc->config.basic_settings.chroma_pitch; - frame_info->size = dwbc->config.basic_settings.dest_height * (dwbc->config.basic_settings.luma_pitch + dwbc->config.basic_settings.chroma_pitch); - - return true; -} - -static bool set_basic_settings(struct dwbc *dwbc, - const struct dwb_basic_settings *basic_settings) -{ - if (basic_settings) { - memcpy(&dwbc->config.basic_settings, basic_settings, sizeof(struct dwb_basic_settings)); - return true; - } else { - return false; - } -} - -static bool get_basic_settings(struct dwbc *dwbc, - struct dwb_basic_settings *basic_settings) -{ - if (basic_settings) { - memcpy(basic_settings, &dwbc->config.basic_settings, sizeof(struct dwb_basic_settings)); - return true; - } else { - return false; - } -} - -static bool set_advanced_settings(struct dwbc *dwbc, - const struct dwb_advanced_settings *advanced_settings) -{ - if (advanced_settings) { - if (advanced_settings->uFlag & sf_output_format) { - dwbc->config.advanced_settings.uFlag |= sf_output_format; - dwbc->config.advanced_settings.out_format = advanced_settings->out_format; - } - - if (advanced_settings->uFlag & sf_capture_rate) { - dwbc->config.advanced_settings.uFlag |= sf_capture_rate; - dwbc->config.advanced_settings.capture_rate = advanced_settings->capture_rate; - } - - return true; - } else { - return false; - } -} - -static bool get_advanced_settings(struct dwbc *dwbc, - struct dwb_advanced_settings *advanced_settings) -{ - if (advanced_settings) { - memcpy(advanced_settings, &dwbc->config.advanced_settings, sizeof(struct dwb_advanced_settings)); - return true; - } else { - return false; - } -} - -static bool reset_advanced_settings(struct dwbc *dwbc) -{ - dwbc->config.advanced_settings.uFlag = 0; - dwbc->config.advanced_settings.out_format = dwb_scaler_mode_bypass444; - dwbc->config.advanced_settings.capture_rate = dwb_capture_rate_0; - - return true; -} - -const struct dwbc_funcs dcn10_dwbc_funcs = { - .get_caps = get_caps, - .enable = enable, - .disable = disable, - .get_status = get_status, - .dump_frame = dump_frame, - .set_basic_settings = set_basic_settings, - .get_basic_settings = get_basic_settings, - .set_advanced_settings = set_advanced_settings, - .get_advanced_settings = get_advanced_settings, - .reset_advanced_settings = reset_advanced_settings, -}; - -void dcn10_dwbc_construct(struct dcn10_dwbc *dwbc10, - struct dc_context *ctx, - const struct dcn10_dwbc_registers *dwbc_regs, - const struct dcn10_dwbc_shift *dwbc_shift, - const struct dcn10_dwbc_mask *dwbc_mask, - int inst) -{ - dwbc10->base.ctx = ctx; - - dwbc10->base.inst = inst; - dwbc10->base.funcs = &dcn10_dwbc_funcs; - - dwbc10->dwbc_regs = dwbc_regs; - dwbc10->dwbc_shift = dwbc_shift; - dwbc10->dwbc_mask = dwbc_mask; -} - - -#endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.h deleted file mode 100644 index 1fdc2be42fa9..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.h +++ /dev/null @@ -1,277 +0,0 @@ -/* Copyright 2012-17 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ -#ifndef __DC_DWBC_DCN10_H__ -#define __DC_DWBC_DCN10_H__ - -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) - -/* DCN */ -#define BASE_INNER(seg) \ - DCE_BASE__INST0_SEG ## seg - -#define BASE(seg) \ - BASE_INNER(seg) - -#define SR(reg_name)\ - .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + \ - mm ## reg_name - -#define SRI(reg_name, block, id)\ - .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - mm ## block ## id ## _ ## reg_name - - -#define SRII(reg_name, block, id)\ - .reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - mm ## block ## id ## _ ## reg_name - -#define SF(reg_name, field_name, post_fix)\ - .field_name = reg_name ## __ ## field_name ## post_fix - - -#define DWBC_COMMON_REG_LIST_DCN1_0(inst) \ - SRI(WB_ENABLE, CNV, inst),\ - SRI(WB_EC_CONFIG, CNV, inst),\ - SRI(CNV_MODE, CNV, inst),\ - SRI(WB_SOFT_RESET, CNV, inst),\ - SRI(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_PITCH, MCIF_WB, inst),\ - SRI(MCIF_WB_ARBITRATION_CONTROL, MCIF_WB, inst),\ - SRI(MCIF_WB_SCLK_CHANGE, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_1_ADDR_Y, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_1_ADDR_Y_OFFSET, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_1_ADDR_C, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_1_ADDR_C_OFFSET, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_2_ADDR_Y, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_2_ADDR_Y_OFFSET, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_2_ADDR_C, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_2_ADDR_C_OFFSET, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_3_ADDR_Y, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_3_ADDR_Y_OFFSET, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_3_ADDR_C, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_3_ADDR_C_OFFSET, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_4_ADDR_Y, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_4_ADDR_Y_OFFSET, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_4_ADDR_C, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_4_ADDR_C_OFFSET, MCIF_WB, inst),\ - SRI(MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB, inst),\ - SRI(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, MCIF_WB, inst),\ - SRI(MCIF_WB_NB_PSTATE_CONTROL, MCIF_WB, inst),\ - SRI(MCIF_WB_WATERMARK, MCIF_WB, inst),\ - SRI(MCIF_WB_WARM_UP_CNTL, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_LUMA_SIZE, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_CHROMA_SIZE, MCIF_WB, inst),\ - .DWB_SOURCE_SELECT = mmDWB_SOURCE_SELECT\ - -#define DWBC_COMMON_MASK_SH_LIST_DCN1_0(mask_sh) \ - SF(CNV0_WB_ENABLE, WB_ENABLE, mask_sh),\ - SF(CNV0_WB_EC_CONFIG, DISPCLK_R_WB_GATE_DIS, mask_sh),\ - SF(CNV0_WB_EC_CONFIG, DISPCLK_G_WB_GATE_DIS, mask_sh),\ - SF(CNV0_WB_EC_CONFIG, DISPCLK_G_WBSCL_GATE_DIS, mask_sh),\ - SF(CNV0_WB_EC_CONFIG, WB_LB_LS_DIS, mask_sh),\ - SF(CNV0_WB_EC_CONFIG, WB_LUT_LS_DIS, mask_sh),\ - SF(CNV0_CNV_MODE, CNV_WINDOW_CROP_EN, mask_sh),\ - SF(CNV0_CNV_MODE, CNV_STEREO_TYPE, mask_sh),\ - SF(CNV0_CNV_MODE, CNV_INTERLACED_MODE, mask_sh),\ - SF(CNV0_CNV_MODE, CNV_EYE_SELECTION, mask_sh),\ - SF(CNV0_CNV_MODE, CNV_STEREO_POLARITY, mask_sh),\ - SF(CNV0_CNV_MODE, CNV_INTERLACED_FIELD_ORDER, mask_sh),\ - SF(CNV0_CNV_MODE, CNV_STEREO_SPLIT, mask_sh),\ - SF(CNV0_CNV_MODE, CNV_NEW_CONTENT, mask_sh),\ - SF(CNV0_CNV_MODE, CNV_FRAME_CAPTURE_EN, mask_sh),\ - SF(CNV0_WB_SOFT_RESET, WB_SOFT_RESET, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_ENABLE, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUF_DUALSIZE_REQ, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_INT_EN, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_INT_ACK, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_SLICE_INT_EN, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_OVERRUN_INT_EN, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_LOCK, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_P_VMID, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUF_ADDR_FENCE_EN, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_PITCH, MCIF_WB_BUF_LUMA_PITCH, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_PITCH, MCIF_WB_BUF_CHROMA_PITCH, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_ARBITRATION_CONTROL, MCIF_WB_CLIENT_ARBITRATION_SLICE, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_ARBITRATION_CONTROL, MCIF_WB_TIME_PER_PIXEL, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_SCLK_CHANGE, WM_CHANGE_ACK_FORCE_ON, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_SCLK_CHANGE, MCIF_WB_CLI_WATERMARK_MASK, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_1_ADDR_Y, MCIF_WB_BUF_1_ADDR_Y, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_1_ADDR_Y_OFFSET, MCIF_WB_BUF_1_ADDR_Y_OFFSET, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_1_ADDR_C, MCIF_WB_BUF_1_ADDR_C, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_1_ADDR_C_OFFSET, MCIF_WB_BUF_1_ADDR_C_OFFSET, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_2_ADDR_Y, MCIF_WB_BUF_2_ADDR_Y, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_2_ADDR_Y_OFFSET, MCIF_WB_BUF_2_ADDR_Y_OFFSET, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_2_ADDR_C, MCIF_WB_BUF_2_ADDR_C, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_2_ADDR_C_OFFSET, MCIF_WB_BUF_2_ADDR_C_OFFSET, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_3_ADDR_Y, MCIF_WB_BUF_3_ADDR_Y, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_3_ADDR_Y_OFFSET, MCIF_WB_BUF_3_ADDR_Y_OFFSET, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_3_ADDR_C, MCIF_WB_BUF_3_ADDR_C, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_3_ADDR_C_OFFSET, MCIF_WB_BUF_3_ADDR_C_OFFSET, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_4_ADDR_Y, MCIF_WB_BUF_4_ADDR_Y, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_4_ADDR_Y_OFFSET, MCIF_WB_BUF_4_ADDR_Y_OFFSET, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_4_ADDR_C, MCIF_WB_BUF_4_ADDR_C, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_4_ADDR_C_OFFSET, MCIF_WB_BUF_4_ADDR_C_OFFSET, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_LOCK_IGNORE, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_INT_EN, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_INT_ACK, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_SLICE_INT_EN, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_LOCK, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_SLICE_SIZE, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, NB_PSTATE_CHANGE_REFRESH_WATERMARK, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_CHANGE_URGENT_DURING_REQUEST, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_CHANGE_FORCE_ON, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_ALLOW_FOR_URGENT, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_CHANGE_WATERMARK_MASK, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_WATERMARK, MCIF_WB_CLI_WATERMARK, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_WARM_UP_CNTL, MCIF_WB_PITCH_SIZE_WARMUP, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_LUMA_SIZE, MCIF_WB_BUF_LUMA_SIZE, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_CHROMA_SIZE, MCIF_WB_BUF_CHROMA_SIZE, mask_sh),\ - SF(DWB_SOURCE_SELECT, OPTC_DWB0_SOURCE_SELECT, mask_sh),\ - SF(DWB_SOURCE_SELECT, OPTC_DWB1_SOURCE_SELECT, mask_sh) - -#define DWBC_REG_FIELD_LIST(type) \ - type WB_ENABLE;\ - type DISPCLK_R_WB_GATE_DIS;\ - type DISPCLK_G_WB_GATE_DIS;\ - type DISPCLK_G_WBSCL_GATE_DIS;\ - type WB_LB_LS_DIS;\ - type WB_LB_SD_DIS;\ - type WB_LUT_LS_DIS;\ - type CNV_WINDOW_CROP_EN;\ - type CNV_STEREO_TYPE;\ - type CNV_INTERLACED_MODE;\ - type CNV_EYE_SELECTION;\ - type CNV_STEREO_POLARITY;\ - type CNV_INTERLACED_FIELD_ORDER;\ - type CNV_STEREO_SPLIT;\ - type CNV_NEW_CONTENT;\ - type CNV_FRAME_CAPTURE_EN;\ - type WB_SOFT_RESET;\ - type MCIF_WB_BUFMGR_ENABLE;\ - type MCIF_WB_BUF_DUALSIZE_REQ;\ - type MCIF_WB_BUFMGR_SW_INT_EN;\ - type MCIF_WB_BUFMGR_SW_INT_ACK;\ - type MCIF_WB_BUFMGR_SW_SLICE_INT_EN;\ - type MCIF_WB_BUFMGR_SW_OVERRUN_INT_EN;\ - type MCIF_WB_BUFMGR_SW_LOCK;\ - type MCIF_WB_P_VMID;\ - type MCIF_WB_BUF_ADDR_FENCE_EN;\ - type MCIF_WB_BUF_LUMA_PITCH;\ - type MCIF_WB_BUF_CHROMA_PITCH;\ - type MCIF_WB_CLIENT_ARBITRATION_SLICE;\ - type MCIF_WB_TIME_PER_PIXEL;\ - type WM_CHANGE_ACK_FORCE_ON;\ - type MCIF_WB_CLI_WATERMARK_MASK;\ - type MCIF_WB_BUF_1_ADDR_Y;\ - type MCIF_WB_BUF_1_ADDR_Y_OFFSET;\ - type MCIF_WB_BUF_1_ADDR_C;\ - type MCIF_WB_BUF_1_ADDR_C_OFFSET;\ - type MCIF_WB_BUF_2_ADDR_Y;\ - type MCIF_WB_BUF_2_ADDR_Y_OFFSET;\ - type MCIF_WB_BUF_2_ADDR_C;\ - type MCIF_WB_BUF_2_ADDR_C_OFFSET;\ - type MCIF_WB_BUF_3_ADDR_Y;\ - type MCIF_WB_BUF_3_ADDR_Y_OFFSET;\ - type MCIF_WB_BUF_3_ADDR_C;\ - type MCIF_WB_BUF_3_ADDR_C_OFFSET;\ - type MCIF_WB_BUF_4_ADDR_Y;\ - type MCIF_WB_BUF_4_ADDR_Y_OFFSET;\ - type MCIF_WB_BUF_4_ADDR_C;\ - type MCIF_WB_BUF_4_ADDR_C_OFFSET;\ - type MCIF_WB_BUFMGR_VCE_LOCK_IGNORE;\ - type MCIF_WB_BUFMGR_VCE_INT_EN;\ - type MCIF_WB_BUFMGR_VCE_INT_ACK;\ - type MCIF_WB_BUFMGR_VCE_SLICE_INT_EN;\ - type MCIF_WB_BUFMGR_VCE_LOCK;\ - type MCIF_WB_BUFMGR_SLICE_SIZE;\ - type NB_PSTATE_CHANGE_REFRESH_WATERMARK;\ - type NB_PSTATE_CHANGE_URGENT_DURING_REQUEST;\ - type NB_PSTATE_CHANGE_FORCE_ON;\ - type NB_PSTATE_ALLOW_FOR_URGENT;\ - type NB_PSTATE_CHANGE_WATERMARK_MASK;\ - type MCIF_WB_CLI_WATERMARK;\ - type MCIF_WB_CLI_CLOCK_GATER_OVERRIDE;\ - type MCIF_WB_PITCH_SIZE_WARMUP;\ - type MCIF_WB_BUF_LUMA_SIZE;\ - type MCIF_WB_BUF_CHROMA_SIZE;\ - type OPTC_DWB0_SOURCE_SELECT;\ - type OPTC_DWB1_SOURCE_SELECT;\ - -struct dcn10_dwbc_registers { - uint32_t WB_ENABLE; - uint32_t WB_EC_CONFIG; - uint32_t CNV_MODE; - uint32_t WB_SOFT_RESET; - uint32_t MCIF_WB_BUFMGR_SW_CONTROL; - uint32_t MCIF_WB_BUF_PITCH; - uint32_t MCIF_WB_ARBITRATION_CONTROL; - uint32_t MCIF_WB_SCLK_CHANGE; - uint32_t MCIF_WB_BUF_1_ADDR_Y; - uint32_t MCIF_WB_BUF_1_ADDR_Y_OFFSET; - uint32_t MCIF_WB_BUF_1_ADDR_C; - uint32_t MCIF_WB_BUF_1_ADDR_C_OFFSET; - uint32_t MCIF_WB_BUF_2_ADDR_Y; - uint32_t MCIF_WB_BUF_2_ADDR_Y_OFFSET; - uint32_t MCIF_WB_BUF_2_ADDR_C; - uint32_t MCIF_WB_BUF_2_ADDR_C_OFFSET; - uint32_t MCIF_WB_BUF_3_ADDR_Y; - uint32_t MCIF_WB_BUF_3_ADDR_Y_OFFSET; - uint32_t MCIF_WB_BUF_3_ADDR_C; - uint32_t MCIF_WB_BUF_3_ADDR_C_OFFSET; - uint32_t MCIF_WB_BUF_4_ADDR_Y; - uint32_t MCIF_WB_BUF_4_ADDR_Y_OFFSET; - uint32_t MCIF_WB_BUF_4_ADDR_C; - uint32_t MCIF_WB_BUF_4_ADDR_C_OFFSET; - uint32_t MCIF_WB_BUFMGR_VCE_CONTROL; - uint32_t MCIF_WB_NB_PSTATE_LATENCY_WATERMARK; - uint32_t MCIF_WB_NB_PSTATE_CONTROL; - uint32_t MCIF_WB_WATERMARK; - uint32_t MCIF_WB_WARM_UP_CNTL; - uint32_t MCIF_WB_BUF_LUMA_SIZE; - uint32_t MCIF_WB_BUF_CHROMA_SIZE; - uint32_t DWB_SOURCE_SELECT; -}; -struct dcn10_dwbc_mask { - DWBC_REG_FIELD_LIST(uint32_t) -}; -struct dcn10_dwbc_shift { - DWBC_REG_FIELD_LIST(uint8_t) -}; -struct dcn10_dwbc { - struct dwbc base; - const struct dcn10_dwbc_registers *dwbc_regs; - const struct dcn10_dwbc_shift *dwbc_shift; - const struct dcn10_dwbc_mask *dwbc_mask; -}; - -void dcn10_dwbc_construct(struct dcn10_dwbc *dwbc10, - struct dc_context *ctx, - const struct dcn10_dwbc_registers *dwbc_regs, - const struct dcn10_dwbc_shift *dwbc_shift, - const struct dcn10_dwbc_mask *dwbc_mask, - int inst); - -#endif - -#endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 71adda0e5b59..e21ba8c2f8d4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -32,7 +32,6 @@ #include "dcn10/dcn10_ipp.h" #include "dcn10/dcn10_mpc.h" -#include "dcn10/dcn10_dwb.h" #include "irq/dcn10/irq_service_dcn10.h" #include "dcn10/dcn10_dpp.h" #include "dcn10/dcn10_timing_generator.h" @@ -326,24 +325,6 @@ static const struct dcn_dpp_mask tf_mask = { TF_REG_LIST_SH_MASK_DCN10(_MASK), }; -#define dwbc_regs(id)\ -[id] = {\ - DWBC_COMMON_REG_LIST_DCN1_0(id),\ -} - -static const struct dcn10_dwbc_registers dwbc10_regs[] = { - dwbc_regs(0), - dwbc_regs(1), -}; - -static const struct dcn10_dwbc_shift dwbc10_shift = { - DWBC_COMMON_MASK_SH_LIST_DCN1_0(__SHIFT) -}; - -static const struct dcn10_dwbc_mask dwbc10_mask = { - DWBC_COMMON_MASK_SH_LIST_DCN1_0(_MASK) -}; - static const struct dcn_mpc_registers mpc_regs = { MPC_COMMON_REG_LIST_DCN1_0(0), MPC_COMMON_REG_LIST_DCN1_0(1), @@ -430,7 +411,6 @@ static const struct resource_caps res_cap = { .num_audio = 4, .num_stream_encoder = 4, .num_pll = 4, - .num_dwb = 2, }; static const struct dc_debug debug_defaults_drv = { @@ -767,11 +747,6 @@ static void destruct(struct dcn10_resource_pool *pool) dce_aud_destroy(&pool->base.audios[i]); } - for (i = 0; i < pool->base.res_cap->num_dwb; i++) { - kfree(pool->base.dwbc[i]); - pool->base.dwbc[i] = NULL; - } - for (i = 0; i < pool->base.clk_src_count; i++) { if (pool->base.clock_sources[i] != NULL) { dcn10_clock_source_destroy(&pool->base.clock_sources[i]); @@ -1234,31 +1209,6 @@ static uint32_t read_pipe_fuses(struct dc_context *ctx) return value; } -static bool dcn10_dwbc_create(struct dc_context *ctx, struct resource_pool *pool) -{ - int i; - uint32_t dwb_count = pool->res_cap->num_dwb; - - for (i = 0; i < dwb_count; i++) { - struct dcn10_dwbc *dwbc10 = kzalloc(sizeof(struct dcn10_dwbc), - GFP_KERNEL); - - if (!dwbc10) { - dm_error("DC: failed to create dwbc10!\n"); - return false; - } - - dcn10_dwbc_construct(dwbc10, ctx, - &dwbc10_regs[i], - &dwbc10_shift, - &dwbc10_mask, - i); - - pool->dwbc[i] = &dwbc10->base; - } - return true; -} - static bool construct( uint8_t num_virtual_links, struct dc *dc, @@ -1479,12 +1429,6 @@ static bool construct( goto mpc_create_fail; } -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) - if (!dcn10_dwbc_create(ctx, &pool->base)) { - goto dwbc_create_fail; - } -#endif - if (!resource_construct(num_virtual_links, dc, &pool->base, (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) ? &res_create_funcs : &res_create_maximus_funcs))) @@ -1507,7 +1451,6 @@ mi_create_fail: irqs_create_fail: res_create_fail: clock_source_create_fail: -dwbc_create_fail: destruct(pool); diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 915d5c10361b..1a1d322da8cc 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -35,7 +35,6 @@ #if defined(CONFIG_DRM_AMD_DC_DCN1_0) #include "mpc.h" #endif -#include "dwb.h" #define MAX_CLOCK_SOURCES 7 @@ -136,8 +135,6 @@ struct resource_pool { struct pp_smu_funcs_rv *pp_smu; struct pp_smu_display_requirement_rv pp_smu_req; - struct dwbc *dwbc[MAX_DWB_PIPES]; - unsigned int pipe_count; unsigned int underlay_pipe_index; unsigned int stream_enc_count; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dwb.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dwb.h deleted file mode 100644 index 82347ba480fe..000000000000 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dwb.h +++ /dev/null @@ -1,193 +0,0 @@ -/* Copyright 2012-17 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DC_DWBC_H__ -#define __DC_DWBC_H__ - -#include "dc_hw_types.h" - -#define MAX_DWB_PIPES 3 - -enum dce_version; - -enum dwb_sw_version { - dwb_ver_1_0 = 1, -}; - -enum dwb_source { - dwb_src_scl = 0, /* for DCE7x/9x, DCN won't support. */ - dwb_src_blnd, /* for DCE7x/9x */ - dwb_src_fmt, /* for DCE7x/9x */ -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) - dwb_src_otg0 = 0x100, /* for DCN1.x, register: mmDWB_SOURCE_SELECT */ - dwb_src_otg1, /* for DCN1.x */ - dwb_src_otg2, /* for DCN1.x */ - dwb_src_otg3, /* for DCN1.x */ -#endif -}; - -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) -/* DCN1.x supports 2 pipes */ -#endif -enum dwb_pipe { - dwb_pipe0 = 0, -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) - dwb_pipe1, -#endif - dwb_pipe_max_num, -}; - -enum setting_flags { - sf_pipe = 0x00000001, - sf_output_format = 0x00000002, - sf_capture_rate = 0x00000004, - sf_all = 0xffffffff, -}; - -enum dwb_capture_rate { - - dwb_capture_rate_0 = 0, /* Every frame is captured. */ - dwb_capture_rate_1 = 1, /* Every other frame is captured. */ - dwb_capture_rate_2 = 2, /* Every 3rd frame is captured. */ - dwb_capture_rate_3 = 3, /* Every 4th frame is captured. */ -}; - -enum dwb_scaler_mode { - dwb_scaler_mode_bypass444 = 0, - dwb_scaler_mode_rgb444 = 1, - dwb_scaler_mode_yuv444 = 2, - dwb_scaler_mode_yuv420 = 3 -}; - -struct dwb_caps { - enum dce_version hw_version; /* DCN engine version. */ - enum dwb_sw_version sw_version; /* DWB sw implementation version. */ - unsigned int reserved[6]; /* Reserved for future use, MUST BE 0. */ - unsigned int adapter_id; - unsigned int num_pipes; /* number of DWB pipes */ - struct { - unsigned int support_dwb :1; - unsigned int support_ogam :1; - unsigned int support_wbscl :1; - unsigned int support_ocsc :1; - } caps; - unsigned int reserved2[10]; /* Reserved for future use, MUST BE 0. */ -}; - -struct dwb_status { - bool enabled; - /* Reserved ========================================================================= */ - unsigned int reserved[8]; /* Reserved fields */ -}; - -struct dwb_basic_settings { - /* General DWB related input parameters ============================================= */ - enum dwb_source input_src_select; /* Select input source: (DCE) 0: SCL; 1: BLND; 2: FMT; (DCN) OTG* or MPC* */ - enum dwb_pipe input_pipe_select; /* Select input pipe: 0: PIPE0; 1: PIPE1; 2: PIPE2 */ - - /* CNV: WND Related parameters ====================================================== */ - unsigned int capture_rate; /* Captures once every (capture_rate+1) frames */ - - /* CNV: CSC Related parameters ====================================================== */ - unsigned int start_x; /* Horizontal window start position */ - unsigned int start_y; /* Vertical window start position */ - unsigned int src_width; /* Width of window captured within source window */ - unsigned int src_height; /* Height of window captured within source window */ - - /* SISCL Related parameters ========================================================= */ - unsigned int dest_width; /* Destination width */ - unsigned int dest_height; /* Destination height */ - - /* MCIF bufer parameters ========================================================= */ - unsigned long long luma_address[4]; - unsigned long long chroma_address[4]; - unsigned int luma_pitch; - unsigned int chroma_pitch; - unsigned int slice_lines; - - /* Reserved ========================================================================= */ - unsigned int reserved[8]; /* Reserved fields */ - -}; - -struct dwb_advanced_settings { - enum setting_flags uFlag; - enum dwb_pipe pipe; /* default = DWB_PIPE_ALL */ - enum dwb_scaler_mode out_format; /* default = DWBScalerMode_YUV420 */ - enum dwb_capture_rate capture_rate; /* default = Every frame is captured */ - unsigned int reserved[64]; /* reserved for future use, must be 0 */ -}; - -/* / - dwb_frame_info is the info of the dumping data */ -struct dwb_frame_info { - unsigned int size; - unsigned int width; - unsigned int height; - unsigned int luma_pitch; - unsigned int chroma_pitch; - enum dwb_scaler_mode format; -}; - -struct dwbc_cfg { - struct dwb_basic_settings basic_settings; - struct dwb_advanced_settings advanced_settings; -}; - -struct dwbc { - const struct dwbc_funcs *funcs; - struct dc_context *ctx; - struct dwbc_cfg config; - struct dwb_status status; - int inst; -}; - -struct dwbc_funcs { - bool (*get_caps)(struct dwbc *dwbc, struct dwb_caps *caps); - - bool (*enable)(struct dwbc *dwbc); - - bool (*disable)(struct dwbc *dwbc); - - bool (*get_status)(struct dwbc *dwbc, struct dwb_status *status); - - bool (*dump_frame)(struct dwbc *dwbc, struct dwb_frame_info *frame_info, - unsigned char *luma_buffer, unsigned char *chroma_buffer, - unsigned char *dest_luma_buffer, unsigned char *dest_chroma_buffer); - - bool (*set_basic_settings)(struct dwbc *dwbc, - const struct dwb_basic_settings *basic_settings); - - bool (*get_basic_settings)(struct dwbc *dwbc, - struct dwb_basic_settings *basic_settings); - - bool (*set_advanced_settings)(struct dwbc *dwbc, - const struct dwb_advanced_settings *advanced_settings); - - bool (*get_advanced_settings)(struct dwbc *dwbc, - struct dwb_advanced_settings *advanced_settings); - - bool (*reset_advanced_settings)(struct dwbc *dwbc); -}; - -#endif -- cgit From 2dc3e4a86c8cce49bc73f41d8e0134557c506488 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 10:20:39 +1000 Subject: amdgpu/dc: drop dc_ver char This isn't referenced anywhere, and if it was it should be const. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 7fd42fc8bdfa..008f137dff80 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -49,8 +49,6 @@ #include "mem_input.h" -char dc_ver[] = DC_VER; - /******************************************************************************* * Private functions ******************************************************************************/ -- cgit From b8a1d69ccb5e0ffc2771b3a7a6ec9d948d10ee9d Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 10:23:15 +1000 Subject: amdgpu/dc: static constify update_surface_trace_level Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 008f137dff80..c8235b041b5b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1172,7 +1172,7 @@ static struct dc_stream_status *stream_get_status( return NULL; } -enum surface_update_type update_surface_trace_level = UPDATE_TYPE_FULL; +static const enum surface_update_type update_surface_trace_level = UPDATE_TYPE_FULL; void dc_update_planes_and_stream(struct dc *dc, struct dc_surface_update *srf_updates, int surface_count, -- cgit From 99d1abf8f41ed2c256e8cca7e9da71d751894c7f Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 10:27:41 +1000 Subject: amdgpu/dm: constify yuv_formats. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') 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 dba54c0a7b5f..89442cce7373 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3073,7 +3073,7 @@ static uint32_t rgb_formats[] = { DRM_FORMAT_ABGR2101010, }; -static uint32_t yuv_formats[] = { +static const uint32_t yuv_formats[] = { DRM_FORMAT_NV12, DRM_FORMAT_NV21, }; -- cgit From e04a6123a45abf6836f547e679a8f9aca37ceeb6 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 10:32:23 +1000 Subject: amdgpu/dm: constify plane type. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 2 +- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index b541ade8a03f..59e2e5d59562 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -361,7 +361,7 @@ struct amdgpu_mode_info { int num_dig; /* number of dig blocks */ int disp_priority; const struct amdgpu_display_funcs *funcs; - enum drm_plane_type *plane_type; + const enum drm_plane_type *plane_type; }; #define AMDGPU_MAX_BL_LEVEL 0xFF 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 89442cce7373..ef938521fec8 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -71,7 +71,7 @@ #include "i2caux_interface.h" -static enum drm_plane_type dm_plane_type_default[AMDGPU_MAX_PLANES] = { +static const enum drm_plane_type dm_plane_type_default[AMDGPU_MAX_PLANES] = { DRM_PLANE_TYPE_PRIMARY, DRM_PLANE_TYPE_PRIMARY, DRM_PLANE_TYPE_PRIMARY, @@ -80,14 +80,14 @@ static enum drm_plane_type dm_plane_type_default[AMDGPU_MAX_PLANES] = { DRM_PLANE_TYPE_PRIMARY, }; -static enum drm_plane_type dm_plane_type_carizzo[AMDGPU_MAX_PLANES] = { +static const enum drm_plane_type dm_plane_type_carizzo[AMDGPU_MAX_PLANES] = { DRM_PLANE_TYPE_PRIMARY, DRM_PLANE_TYPE_PRIMARY, DRM_PLANE_TYPE_PRIMARY, DRM_PLANE_TYPE_OVERLAY,/* YUV Capable Underlay */ }; -static enum drm_plane_type dm_plane_type_stoney[AMDGPU_MAX_PLANES] = { +static const enum drm_plane_type dm_plane_type_stoney[AMDGPU_MAX_PLANES] = { DRM_PLANE_TYPE_PRIMARY, DRM_PLANE_TYPE_PRIMARY, DRM_PLANE_TYPE_OVERLAY, /* YUV Capable Underlay */ -- cgit From d90371b0f5f3258a808d12a17a942e4d16f8252c Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 10:32:24 +1000 Subject: amdgpu/dm: constify rgb formats. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') 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 ef938521fec8..61ccddd19718 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3062,7 +3062,7 @@ static const struct drm_plane_helper_funcs dm_plane_helper_funcs = { * plane capabilities, or initialize this array to all formats, so internal drm * check will succeed, and let DC to implement proper check */ -static uint32_t rgb_formats[] = { +static const uint32_t rgb_formats[] = { DRM_FORMAT_RGB888, DRM_FORMAT_XRGB8888, DRM_FORMAT_ARGB8888, -- cgit From 395f669eb69b8b37ed2ffe0c5f67e942e9d00dc8 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 10:39:29 +1000 Subject: amdgpu/dc: constify a bunch of dc structs. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c | 8 ++++---- drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c | 2 +- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c | 2 +- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c index 3e9ff2f5472d..9031d22285ea 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c @@ -51,7 +51,7 @@ clk_dce->base.ctx /* Max clock values for each state indexed by "enum clocks_state": */ -static struct state_dependent_clocks dce80_max_clks_by_state[] = { +static const struct state_dependent_clocks dce80_max_clks_by_state[] = { /* ClocksStateInvalid - should not be used */ { .display_clk_khz = 0, .pixel_clk_khz = 0 }, /* ClocksStateUltraLow - not expected to be used for DCE 8.0 */ @@ -63,7 +63,7 @@ static struct state_dependent_clocks dce80_max_clks_by_state[] = { /* ClocksStatePerformance */ { .display_clk_khz = 600000, .pixel_clk_khz = 400000 } }; -static struct state_dependent_clocks dce110_max_clks_by_state[] = { +static const struct state_dependent_clocks dce110_max_clks_by_state[] = { /*ClocksStateInvalid - should not be used*/ { .display_clk_khz = 0, .pixel_clk_khz = 0 }, /*ClocksStateUltraLow - currently by HW design team not supposed to be used*/ @@ -75,7 +75,7 @@ static struct state_dependent_clocks dce110_max_clks_by_state[] = { /*ClocksStatePerformance*/ { .display_clk_khz = 643000, .pixel_clk_khz = 400000 } }; -static struct state_dependent_clocks dce112_max_clks_by_state[] = { +static const struct state_dependent_clocks dce112_max_clks_by_state[] = { /*ClocksStateInvalid - should not be used*/ { .display_clk_khz = 0, .pixel_clk_khz = 0 }, /*ClocksStateUltraLow - currently by HW design team not supposed to be used*/ @@ -87,7 +87,7 @@ static struct state_dependent_clocks dce112_max_clks_by_state[] = { /*ClocksStatePerformance*/ { .display_clk_khz = 1132000, .pixel_clk_khz = 600000 } }; -static struct state_dependent_clocks dce120_max_clks_by_state[] = { +static const struct state_dependent_clocks dce120_max_clks_by_state[] = { /*ClocksStateInvalid - should not be used*/ { .display_clk_khz = 0, .pixel_clk_khz = 0 }, /*ClocksStateUltraLow - currently by HW design team not supposed to be used*/ diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index 6b5d5948ddb7..a6f93a42c2ec 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -302,7 +302,7 @@ static const struct dce_opp_mask opp_mask = { AUD_COMMON_REG_LIST(id)\ } -static struct dce_audio_registers audio_regs[] = { +static const struct dce_audio_registers audio_regs[] = { audio_regs(0), audio_regs(1), audio_regs(2), diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c index 58a070debd58..791c9b084941 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c @@ -1109,7 +1109,7 @@ static bool dce120_arm_vert_intr( return true; } -static struct timing_generator_funcs dce120_tg_funcs = { +static const struct timing_generator_funcs dce120_tg_funcs = { .validate_timing = dce120_tg_validate_timing, .program_timing = dce120_tg_program_timing, .enable_crtc = dce120_timing_generator_enable_crtc, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c index 487694125ea4..ac03b04f1ea5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c @@ -373,7 +373,7 @@ void ippn10_cnv_setup ( } } -static struct transform_funcs dcn10_dpp_funcs = { +static const struct transform_funcs dcn10_dpp_funcs = { .transform_reset = dpp_reset, .transform_set_scaler = dcn10_dpp_dscl_set_scaler_manual_scale, .transform_get_optimal_number_of_taps = dpp_get_optimal_number_of_taps, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c index 2d3dd9a3a196..7cd10cbc5497 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c @@ -1146,7 +1146,7 @@ void tgn10_read_otg_state(struct dcn10_timing_generator *tgn10, } -static struct timing_generator_funcs dcn10_tg_funcs = { +static const struct timing_generator_funcs dcn10_tg_funcs = { .validate_timing = tgn10_validate_timing, .program_timing = tgn10_program_timing, .program_global_sync = tgn10_program_global_sync, -- cgit From ca19d1a68b7e0f1d0717bd3f2d9d75cb3c568ddb Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 13:15:55 +1000 Subject: amdgpu/dc: make timing generator constructor return void. This can't fail as is. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c | 9 ++------- drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c | 8 ++------ drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c | 7 +------ drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h | 2 +- drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c | 8 ++------ 5 files changed, 8 insertions(+), 26 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 9a75bde32611..6765162a0d78 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -375,13 +375,8 @@ static struct timing_generator *dce100_timing_generator_create( if (!tg110) return NULL; - if (dce110_timing_generator_construct(tg110, ctx, instance, - offsets)) - return &tg110->base; - - BREAK_TO_DEBUGGER(); - kfree(tg110); - return NULL; + dce110_timing_generator_construct(tg110, ctx, instance, offsets); + return &tg110->base; } static struct stream_encoder *dce100_stream_encoder_create( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 787e20e15221..3d91f2a49d1d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -410,12 +410,8 @@ static struct timing_generator *dce110_timing_generator_create( if (!tg110) return NULL; - if (dce110_timing_generator_construct(tg110, ctx, instance, offsets)) - return &tg110->base; - - BREAK_TO_DEBUGGER(); - kfree(tg110); - return NULL; + dce110_timing_generator_construct(tg110, ctx, instance, offsets); + return &tg110->base; } static struct stream_encoder *dce110_stream_encoder_create( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c index 7f93d6d83cfd..bcd544d85621 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c @@ -1941,15 +1941,12 @@ static const struct timing_generator_funcs dce110_tg_funcs = { .arm_vert_intr = dce110_arm_vert_intr, }; -bool dce110_timing_generator_construct( +void dce110_timing_generator_construct( struct dce110_timing_generator *tg110, struct dc_context *ctx, uint32_t instance, const struct dce110_timing_generator_offsets *offsets) { - if (!tg110) - return false; - tg110->controller_id = CONTROLLER_ID_D0 + instance; tg110->base.inst = instance; @@ -1966,6 +1963,4 @@ bool dce110_timing_generator_construct( tg110->min_h_blank = 56; tg110->min_h_front_porch = 4; tg110->min_h_back_porch = 4; - - return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h index a5d63c626ada..bd8d0ab668b7 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h @@ -118,7 +118,7 @@ struct dce110_timing_generator { #define DCE110TG_FROM_TG(tg)\ container_of(tg, struct dce110_timing_generator, base) -bool dce110_timing_generator_construct( +void dce110_timing_generator_construct( struct dce110_timing_generator *tg, struct dc_context *ctx, uint32_t instance, diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 4e2ed3429a90..a06a68521c59 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -415,12 +415,8 @@ static struct timing_generator *dce112_timing_generator_create( if (!tg110) return NULL; - if (dce110_timing_generator_construct(tg110, ctx, instance, offsets)) - return &tg110->base; - - BREAK_TO_DEBUGGER(); - kfree(tg110); - return NULL; + dce110_timing_generator_construct(tg110, ctx, instance, offsets); + return &tg110->base; } static struct stream_encoder *dce112_stream_encoder_create( -- cgit From f29f918f2868ece27c8aff0edc84c7d7fbdc5598 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 13:15:56 +1000 Subject: amdgpu/dc: make stream encoder constructor return void. The checks weren't useful here really. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c | 9 +-------- drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h | 2 +- drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c | 11 +++-------- drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c | 12 ++++-------- drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c | 14 +++++--------- drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c | 12 ++++-------- drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c | 12 ++++-------- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 12 ++++-------- 8 files changed, 26 insertions(+), 58 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c index 532c6e638943..b2add58ef889 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c @@ -1605,7 +1605,7 @@ static const struct stream_encoder_funcs dce110_str_enc_funcs = { }; -bool dce110_stream_encoder_construct( +void dce110_stream_encoder_construct( struct dce110_stream_encoder *enc110, struct dc_context *ctx, struct dc_bios *bp, @@ -1614,11 +1614,6 @@ bool dce110_stream_encoder_construct( const struct dce_stream_encoder_shift *se_shift, const struct dce_stream_encoder_mask *se_mask) { - if (!enc110) - return false; - if (!bp) - return false; - enc110->base.funcs = &dce110_str_enc_funcs; enc110->base.ctx = ctx; enc110->base.id = eng_id; @@ -1626,6 +1621,4 @@ bool dce110_stream_encoder_construct( enc110->regs = regs; enc110->se_shift = se_shift; enc110->se_mask = se_mask; - - return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h index ff8ca1246650..6c28229c76eb 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h @@ -697,7 +697,7 @@ struct dce110_stream_encoder { const struct dce_stream_encoder_mask *se_mask; }; -bool dce110_stream_encoder_construct( +void dce110_stream_encoder_construct( struct dce110_stream_encoder *enc110, struct dc_context *ctx, struct dc_bios *bp, diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 6765162a0d78..75961338a8e4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -389,14 +389,9 @@ static struct stream_encoder *dce100_stream_encoder_create( if (!enc110) return NULL; - if (dce110_stream_encoder_construct( - enc110, ctx, ctx->dc_bios, eng_id, - &stream_enc_regs[eng_id], &se_shift, &se_mask)) - return &enc110->base; - - BREAK_TO_DEBUGGER(); - kfree(enc110); - return NULL; + dce110_stream_encoder_construct(enc110, ctx, ctx->dc_bios, eng_id, + &stream_enc_regs[eng_id], &se_shift, &se_mask); + return &enc110->base; } #define SRII(reg_name, block, id)\ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 3d91f2a49d1d..9faf2feabdf1 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -424,14 +424,10 @@ static struct stream_encoder *dce110_stream_encoder_create( if (!enc110) return NULL; - if (dce110_stream_encoder_construct( - enc110, ctx, ctx->dc_bios, eng_id, - &stream_enc_regs[eng_id], &se_shift, &se_mask)) - return &enc110->base; - - BREAK_TO_DEBUGGER(); - kfree(enc110); - return NULL; + dce110_stream_encoder_construct(enc110, ctx, ctx->dc_bios, eng_id, + &stream_enc_regs[eng_id], + &se_shift, &se_mask); + return &enc110->base; } #define SRII(reg_name, block, id)\ diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index a06a68521c59..0011dd704af0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -428,15 +428,11 @@ static struct stream_encoder *dce112_stream_encoder_create( if (!enc110) return NULL; - - if (dce110_stream_encoder_construct( - enc110, ctx, ctx->dc_bios, eng_id, - &stream_enc_regs[eng_id], &se_shift, &se_mask)) - return &enc110->base; - - BREAK_TO_DEBUGGER(); - kfree(enc110); - return NULL; + + dce110_stream_encoder_construct(enc110, ctx, ctx->dc_bios, eng_id, + &stream_enc_regs[eng_id], + &se_shift, &se_mask); + return &enc110->base; } #define SRII(reg_name, block, id)\ diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index a6f93a42c2ec..a63193913496 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -585,14 +585,10 @@ static struct stream_encoder *dce120_stream_encoder_create( if (!enc110) return NULL; - if (dce110_stream_encoder_construct( - enc110, ctx, ctx->dc_bios, eng_id, - &stream_enc_regs[eng_id], &se_shift, &se_mask)) - return &enc110->base; - - BREAK_TO_DEBUGGER(); - kfree(enc110); - return NULL; + dce110_stream_encoder_construct(enc110, ctx, ctx->dc_bios, eng_id, + &stream_enc_regs[eng_id], + &se_shift, &se_mask); + return &enc110->base; } #define SRII(reg_name, block, id)\ diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 170509a4a221..0b309acab6b1 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -441,14 +441,10 @@ static struct stream_encoder *dce80_stream_encoder_create( if (!enc110) return NULL; - if (dce110_stream_encoder_construct( - enc110, ctx, ctx->dc_bios, eng_id, - &stream_enc_regs[eng_id], &se_shift, &se_mask)) - return &enc110->base; - - BREAK_TO_DEBUGGER(); - kfree(enc110); - return NULL; + dce110_stream_encoder_construct(enc110, ctx, ctx->dc_bios, eng_id, + &stream_enc_regs[eng_id], + &se_shift, &se_mask); + return &enc110->base; } #define SRII(reg_name, block, id)\ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index e21ba8c2f8d4..5d6dd7f30253 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -627,14 +627,10 @@ static struct stream_encoder *dcn10_stream_encoder_create( if (!enc110) return NULL; - if (dce110_stream_encoder_construct( - enc110, ctx, ctx->dc_bios, eng_id, - &stream_enc_regs[eng_id], &se_shift, &se_mask)) - return &enc110->base; - - BREAK_TO_DEBUGGER(); - kfree(enc110); - return NULL; + dce110_stream_encoder_construct(enc110, ctx, ctx->dc_bios, eng_id, + &stream_enc_regs[eng_id], + &se_shift, &se_mask); + return &enc110->base; } static const struct dce_hwseq_registers hwseq_reg = { -- cgit From c60ae11201caff8b0c5c23e4349bf42388e3828b Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 13:15:57 +1000 Subject: amdgpu/dc: make link encoder construct void. This only ever returned true. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 4 +--- .../gpu/drm/amd/display/dc/dce/dce_link_encoder.h | 2 +- .../gpu/drm/amd/display/dc/dce100/dce100_resource.c | 21 +++++++-------------- .../gpu/drm/amd/display/dc/dce110/dce110_resource.c | 21 +++++++-------------- .../gpu/drm/amd/display/dc/dce112/dce112_resource.c | 21 +++++++-------------- .../gpu/drm/amd/display/dc/dce120/dce120_resource.c | 20 +++++++------------- .../gpu/drm/amd/display/dc/dce80/dce80_resource.c | 21 +++++++-------------- .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 20 +++++++------------- 8 files changed, 44 insertions(+), 86 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 2ce730de0dc3..37aeddfb7431 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -914,7 +914,7 @@ bool dce110_link_encoder_validate_dp_output( return false; } -bool dce110_link_encoder_construct( +void dce110_link_encoder_construct( struct dce110_link_encoder *enc110, const struct encoder_init_data *init_data, const struct encoder_feature_support *enc_features, @@ -1013,8 +1013,6 @@ bool dce110_link_encoder_construct( bp_cap_info.DP_HBR3_EN; enc110->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN; } - - return true; } bool dce110_link_encoder_validate_output_with_stream( diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h index 5960fb933f1f..be0a45bdc5e2 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h @@ -168,7 +168,7 @@ struct dce110_link_encoder { }; -bool dce110_link_encoder_construct( +void dce110_link_encoder_construct( struct dce110_link_encoder *enc110, const struct encoder_init_data *init_data, const struct encoder_feature_support *enc_features, diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 75961338a8e4..0084645837ec 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -528,20 +528,13 @@ struct link_encoder *dce100_link_encoder_create( if (!enc110) return NULL; - if (dce110_link_encoder_construct( - enc110, - enc_init_data, - &link_enc_feature, - &link_enc_regs[enc_init_data->transmitter], - &link_enc_aux_regs[enc_init_data->channel - 1], - &link_enc_hpd_regs[enc_init_data->hpd_source])) { - - return &enc110->base; - } - - BREAK_TO_DEBUGGER(); - kfree(enc110); - return NULL; + dce110_link_encoder_construct(enc110, + enc_init_data, + &link_enc_feature, + &link_enc_regs[enc_init_data->transmitter], + &link_enc_aux_regs[enc_init_data->channel - 1], + &link_enc_hpd_regs[enc_init_data->hpd_source]); + return &enc110->base; } struct output_pixel_processor *dce100_opp_create( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 9faf2feabdf1..2c24f2b882fe 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -567,20 +567,13 @@ static struct link_encoder *dce110_link_encoder_create( if (!enc110) return NULL; - if (dce110_link_encoder_construct( - enc110, - enc_init_data, - &link_enc_feature, - &link_enc_regs[enc_init_data->transmitter], - &link_enc_aux_regs[enc_init_data->channel - 1], - &link_enc_hpd_regs[enc_init_data->hpd_source])) { - - return &enc110->base; - } - - BREAK_TO_DEBUGGER(); - kfree(enc110); - return NULL; + dce110_link_encoder_construct(enc110, + enc_init_data, + &link_enc_feature, + &link_enc_regs[enc_init_data->transmitter], + &link_enc_aux_regs[enc_init_data->channel - 1], + &link_enc_hpd_regs[enc_init_data->hpd_source]); + return &enc110->base; } static struct output_pixel_processor *dce110_opp_create( diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 0011dd704af0..7aac8fdb3030 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -552,20 +552,13 @@ struct link_encoder *dce112_link_encoder_create( if (!enc110) return NULL; - if (dce110_link_encoder_construct( - enc110, - enc_init_data, - &link_enc_feature, - &link_enc_regs[enc_init_data->transmitter], - &link_enc_aux_regs[enc_init_data->channel - 1], - &link_enc_hpd_regs[enc_init_data->hpd_source])) { - - return &enc110->base; - } - - BREAK_TO_DEBUGGER(); - kfree(enc110); - return NULL; + dce110_link_encoder_construct(enc110, + enc_init_data, + &link_enc_feature, + &link_enc_regs[enc_init_data->transmitter], + &link_enc_aux_regs[enc_init_data->channel - 1], + &link_enc_hpd_regs[enc_init_data->hpd_source]); + return &enc110->base; } static struct input_pixel_processor *dce112_ipp_create( diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index a63193913496..7de99c454f4b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -544,20 +544,14 @@ static struct link_encoder *dce120_link_encoder_create( if (!enc110) return NULL; - if (dce110_link_encoder_construct( - enc110, - enc_init_data, - &link_enc_feature, - &link_enc_regs[enc_init_data->transmitter], - &link_enc_aux_regs[enc_init_data->channel - 1], - &link_enc_hpd_regs[enc_init_data->hpd_source])) { - - return &enc110->base; - } + dce110_link_encoder_construct(enc110, + enc_init_data, + &link_enc_feature, + &link_enc_regs[enc_init_data->transmitter], + &link_enc_aux_regs[enc_init_data->channel - 1], + &link_enc_hpd_regs[enc_init_data->hpd_source]); - BREAK_TO_DEBUGGER(); - kfree(enc110); - return NULL; + return &enc110->base; } static struct input_pixel_processor *dce120_ipp_create( diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 0b309acab6b1..3603ae93cd72 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -567,20 +567,13 @@ struct link_encoder *dce80_link_encoder_create( if (!enc110) return NULL; - if (dce110_link_encoder_construct( - enc110, - enc_init_data, - &link_enc_feature, - &link_enc_regs[enc_init_data->transmitter], - &link_enc_aux_regs[enc_init_data->channel - 1], - &link_enc_hpd_regs[enc_init_data->hpd_source])) { - - return &enc110->base; - } - - BREAK_TO_DEBUGGER(); - kfree(enc110); - return NULL; + dce110_link_encoder_construct(enc110, + enc_init_data, + &link_enc_feature, + &link_enc_regs[enc_init_data->transmitter], + &link_enc_aux_regs[enc_init_data->channel - 1], + &link_enc_hpd_regs[enc_init_data->hpd_source]); + return &enc110->base; } struct clock_source *dce80_clock_source_create( diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 5d6dd7f30253..c2df57b5e921 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -563,20 +563,14 @@ struct link_encoder *dcn10_link_encoder_create( if (!enc110) return NULL; - if (dce110_link_encoder_construct( - enc110, - enc_init_data, - &link_enc_feature, - &link_enc_regs[enc_init_data->transmitter], - &link_enc_aux_regs[enc_init_data->channel - 1], - &link_enc_hpd_regs[enc_init_data->hpd_source])) { - - return &enc110->base; - } + dce110_link_encoder_construct(enc110, + enc_init_data, + &link_enc_feature, + &link_enc_regs[enc_init_data->transmitter], + &link_enc_aux_regs[enc_init_data->channel - 1], + &link_enc_hpd_regs[enc_init_data->hpd_source]); - BREAK_TO_DEBUGGER(); - kfree(enc110); - return NULL; + return &enc110->base; } struct clock_source *dcn10_clock_source_create( -- cgit From 9cf29399f615fc13732f3c8ba3f5ff47e2ca256d Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 13:15:58 +1000 Subject: amdgpu/dc: make opp construct void. This doesn't return anything except true. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_opp.c | 4 +--- drivers/gpu/drm/amd/display/dc/dce/dce_opp.h | 2 +- drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c | 10 +++------- drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c | 10 +++------- drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c | 10 +++------- drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c | 10 +++------- drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c | 10 +++------- 7 files changed, 17 insertions(+), 39 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c index c0736aeabd85..3931412ab6d3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c @@ -540,7 +540,7 @@ static const struct opp_funcs funcs = { .opp_program_bit_depth_reduction = dce110_opp_program_bit_depth_reduction }; -bool dce110_opp_construct(struct dce110_opp *opp110, +void dce110_opp_construct(struct dce110_opp *opp110, struct dc_context *ctx, uint32_t inst, const struct dce_opp_registers *regs, @@ -556,8 +556,6 @@ bool dce110_opp_construct(struct dce110_opp *opp110, opp110->regs = regs; opp110->opp_shift = opp_shift; opp110->opp_mask = opp_mask; - - return true; } void dce110_opp_destroy(struct output_pixel_processor **opp) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h index 0874c22b8b02..2ab0147cbd9d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h @@ -272,7 +272,7 @@ struct dce110_opp { const struct dce_opp_mask *opp_mask; }; -bool dce110_opp_construct(struct dce110_opp *opp110, +void dce110_opp_construct(struct dce110_opp *opp110, struct dc_context *ctx, uint32_t inst, const struct dce_opp_registers *regs, diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 0084645837ec..729d82eb6500 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -547,13 +547,9 @@ struct output_pixel_processor *dce100_opp_create( if (!opp) return NULL; - if (dce110_opp_construct(opp, - ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask)) - return &opp->base; - - BREAK_TO_DEBUGGER(); - kfree(opp); - return NULL; + dce110_opp_construct(opp, + ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask); + return &opp->base; } struct clock_source *dce100_clock_source_create( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 2c24f2b882fe..8e3f365177b8 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -586,13 +586,9 @@ static struct output_pixel_processor *dce110_opp_create( if (!opp) return NULL; - if (dce110_opp_construct(opp, - ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask)) - return &opp->base; - - BREAK_TO_DEBUGGER(); - kfree(opp); - return NULL; + dce110_opp_construct(opp, + ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask); + return &opp->base; } struct clock_source *dce110_clock_source_create( diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 7aac8fdb3030..3cb18cecb800 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -586,13 +586,9 @@ struct output_pixel_processor *dce112_opp_create( if (!opp) return NULL; - if (dce110_opp_construct(opp, - ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask)) - return &opp->base; - - BREAK_TO_DEBUGGER(); - kfree(opp); - return NULL; + dce110_opp_construct(opp, + ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask); + return &opp->base; } struct clock_source *dce112_clock_source_create( diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index 7de99c454f4b..ea234376c0e2 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -356,13 +356,9 @@ struct output_pixel_processor *dce120_opp_create( if (!opp) return NULL; - if (dce110_opp_construct(opp, - ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask)) - return &opp->base; - - BREAK_TO_DEBUGGER(); - kfree(opp); - return NULL; + dce110_opp_construct(opp, + ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask); + return &opp->base; } static const struct bios_registers bios_regs = { diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 3603ae93cd72..71f265b6b670 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -422,13 +422,9 @@ static struct output_pixel_processor *dce80_opp_create( if (!opp) return NULL; - if (dce110_opp_construct(opp, - ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask)) - return &opp->base; - - BREAK_TO_DEBUGGER(); - kfree(opp); - return NULL; + dce110_opp_construct(opp, + ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask); + return &opp->base; } static struct stream_encoder *dce80_stream_encoder_create( -- cgit From 5fb005c4583749f54d5bab6622dbed1d2d56c268 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 13:15:59 +1000 Subject: amdgpu/dc: make dce transform constructor void This never returns anything but true. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_transform.c | 4 +--- drivers/gpu/drm/amd/display/dc/dce/dce_transform.h | 2 +- drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c | 11 +++-------- drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c | 10 +++------- drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c | 13 ++++--------- drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c | 13 ++++--------- drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c | 13 ++++--------- 7 files changed, 20 insertions(+), 46 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c index a8f60d7531be..c40d2e9e5f7c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c @@ -1437,7 +1437,7 @@ static const struct transform_funcs dce_transform_funcs = { /* Constructor, Destructor */ /*****************************************/ -bool dce_transform_construct( +void dce_transform_construct( struct dce_transform *xfm_dce, struct dc_context *ctx, uint32_t inst, @@ -1462,6 +1462,4 @@ bool dce_transform_construct( xfm_dce->lb_bits_per_entry = LB_BITS_PER_ENTRY; xfm_dce->lb_memory_size = LB_TOTAL_NUMBER_OF_ENTRIES; /*0x6B0*/ - - return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h index 805bb9c4e188..e1f1e5129f86 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h @@ -481,7 +481,7 @@ struct dce_transform { bool prescaler_on; }; -bool dce_transform_construct(struct dce_transform *xfm_dce, +void dce_transform_construct(struct dce_transform *xfm_dce, struct dc_context *ctx, uint32_t inst, const struct dce_transform_registers *regs, diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 729d82eb6500..1caf2983dda5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -486,14 +486,9 @@ static struct transform *dce100_transform_create( if (!transform) return NULL; - if (dce_transform_construct(transform, ctx, inst, - &xfm_regs[inst], &xfm_shift, &xfm_mask)) { - return &transform->base; - } - - BREAK_TO_DEBUGGER(); - kfree(transform); - return NULL; + dce_transform_construct(transform, ctx, inst, + &xfm_regs[inst], &xfm_shift, &xfm_mask); + return &transform->base; } static struct input_pixel_processor *dce100_ipp_create( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 8e3f365177b8..45c5facf79b1 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -526,13 +526,9 @@ static struct transform *dce110_transform_create( if (!transform) return NULL; - if (dce_transform_construct(transform, ctx, inst, - &xfm_regs[inst], &xfm_shift, &xfm_mask)) - return &transform->base; - - BREAK_TO_DEBUGGER(); - kfree(transform); - return NULL; + dce_transform_construct(transform, ctx, inst, + &xfm_regs[inst], &xfm_shift, &xfm_mask); + return &transform->base; } static struct input_pixel_processor *dce110_ipp_create( diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 3cb18cecb800..251e4a29d56f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -521,15 +521,10 @@ static struct transform *dce112_transform_create( if (!transform) return NULL; - if (dce_transform_construct(transform, ctx, inst, - &xfm_regs[inst], &xfm_shift, &xfm_mask)) { - transform->lb_memory_size = 0x1404; /*5124*/ - return &transform->base; - } - - BREAK_TO_DEBUGGER(); - kfree(transform); - return NULL; + dce_transform_construct(transform, ctx, inst, + &xfm_regs[inst], &xfm_shift, &xfm_mask); + transform->lb_memory_size = 0x1404; /*5124*/ + return &transform->base; } static const struct encoder_feature_support link_enc_feature = { diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index ea234376c0e2..13d75df71396 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -662,15 +662,10 @@ static struct transform *dce120_transform_create( if (!transform) return NULL; - if (dce_transform_construct(transform, ctx, inst, - &xfm_regs[inst], &xfm_shift, &xfm_mask)) { - transform->lb_memory_size = 0x1404; /*5124*/ - return &transform->base; - } - - BREAK_TO_DEBUGGER(); - kfree(transform); - return NULL; + dce_transform_construct(transform, ctx, inst, + &xfm_regs[inst], &xfm_shift, &xfm_mask); + transform->lb_memory_size = 0x1404; /*5124*/ + return &transform->base; } static void dce120_destroy_resource_pool(struct resource_pool **pool) diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 71f265b6b670..db8afb6491cd 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -535,15 +535,10 @@ static struct transform *dce80_transform_create( if (!transform) return NULL; - if (dce_transform_construct(transform, ctx, inst, - &xfm_regs[inst], &xfm_shift, &xfm_mask)) { - transform->prescaler_on = false; - return &transform->base; - } - - BREAK_TO_DEBUGGER(); - kfree(transform); - return NULL; + dce_transform_construct(transform, ctx, inst, + &xfm_regs[inst], &xfm_shift, &xfm_mask); + transform->prescaler_on = false; + return &transform->base; } static const struct encoder_feature_support link_enc_feature = { -- cgit From 99913a171d00b2d4c94127a9e38e5457bc45635d Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 13:16:00 +1000 Subject: amdgpu/dc: make dce80 timing generator construct return void. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c | 8 ++------ drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c | 7 +------ drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.h | 2 +- 3 files changed, 4 insertions(+), 13 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index db8afb6491cd..5e00ca6a1292 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -404,12 +404,8 @@ static struct timing_generator *dce80_timing_generator_create( if (!tg110) return NULL; - if (dce80_timing_generator_construct(tg110, ctx, instance, offsets)) - return &tg110->base; - - BREAK_TO_DEBUGGER(); - kfree(tg110); - return NULL; + dce80_timing_generator_construct(tg110, ctx, instance, offsets); + return &tg110->base; } static struct output_pixel_processor *dce80_opp_create( diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c index 179a6d604838..265894851493 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c @@ -152,15 +152,12 @@ static const struct timing_generator_funcs dce80_tg_funcs = { dce80_timing_generator_enable_advanced_request, }; -bool dce80_timing_generator_construct( +void dce80_timing_generator_construct( struct dce110_timing_generator *tg110, struct dc_context *ctx, uint32_t instance, const struct dce110_timing_generator_offsets *offsets) { - if (!tg110) - return false; - tg110->controller_id = CONTROLLER_ID_D0 + instance; tg110->base.inst = instance; tg110->offsets = *offsets; @@ -177,8 +174,6 @@ bool dce80_timing_generator_construct( tg110->min_h_blank = 56; tg110->min_h_front_porch = 4; tg110->min_h_back_porch = 4; - - return true; } void dce80_timing_generator_enable_advanced_request( diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.h index 6e4722a970d7..9cebb24c94c8 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.h @@ -30,7 +30,7 @@ #include "../include/grph_object_id.h" /* DCE8.0 implementation inherits from DCE11.0 */ -bool dce80_timing_generator_construct( +void dce80_timing_generator_construct( struct dce110_timing_generator *tg, struct dc_context *ctx, uint32_t instance, -- cgit From 2c9a7908b44eca05d1d08270a9f982b96ee30bda Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 14:34:34 +1000 Subject: amdgpu/dc: make get_audio_clock_info return void. This function never returned false under any sane circumstances. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dce/dce_stream_encoder.c | 75 ++++++++++------------ 1 file changed, 34 insertions(+), 41 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c index b2add58ef889..a09727fb405f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c @@ -1238,7 +1238,7 @@ uint32_t calc_max_audio_packets_per_line( return max_packets_per_line; } -bool get_audio_clock_info( +void get_audio_clock_info( enum dc_color_depth color_depth, uint32_t crtc_pixel_clock_in_khz, uint32_t actual_pixel_clock_in_khz, @@ -1249,9 +1249,6 @@ bool get_audio_clock_info( uint32_t crtc_pixel_clock_in_10khz = crtc_pixel_clock_in_khz / 10; uint32_t audio_array_size; - if (audio_clock_info == NULL) - return false; /* should not happen */ - switch (color_depth) { case COLOR_DEPTH_161616: clock_info = audio_clock_info_table_48bpc; @@ -1280,7 +1277,7 @@ bool get_audio_clock_info( crtc_pixel_clock_in_10khz) { /* match found */ *audio_clock_info = clock_info[index]; - return true; + return; } } } @@ -1300,8 +1297,6 @@ bool get_audio_clock_info( audio_clock_info->n_32khz = 4096; audio_clock_info->n_44khz = 6272; audio_clock_info->n_48khz = 6144; - - return true; } static void dce110_se_audio_setup( @@ -1362,40 +1357,38 @@ static void dce110_se_setup_hdmi_audio( HDMI_ACR_AUDIO_PRIORITY, 0); /* Program audio clock sample/regeneration parameters */ - if (get_audio_clock_info( - crtc_info->color_depth, - crtc_info->requested_pixel_clock, - crtc_info->calculated_pixel_clock, - &audio_clock_info)) { - dm_logger_write(enc->ctx->logger, LOG_HW_AUDIO, - "\n%s:Input::requested_pixel_clock = %d"\ - "calculated_pixel_clock = %d \n", __func__,\ - crtc_info->requested_pixel_clock,\ - crtc_info->calculated_pixel_clock); - - /* HDMI_ACR_32_0__HDMI_ACR_CTS_32_MASK */ - REG_UPDATE(HDMI_ACR_32_0, HDMI_ACR_CTS_32, audio_clock_info.cts_32khz); - - /* HDMI_ACR_32_1__HDMI_ACR_N_32_MASK */ - REG_UPDATE(HDMI_ACR_32_1, HDMI_ACR_N_32, audio_clock_info.n_32khz); - - /* HDMI_ACR_44_0__HDMI_ACR_CTS_44_MASK */ - REG_UPDATE(HDMI_ACR_44_0, HDMI_ACR_CTS_44, audio_clock_info.cts_44khz); - - /* HDMI_ACR_44_1__HDMI_ACR_N_44_MASK */ - REG_UPDATE(HDMI_ACR_44_1, HDMI_ACR_N_44, audio_clock_info.n_44khz); - - /* HDMI_ACR_48_0__HDMI_ACR_CTS_48_MASK */ - REG_UPDATE(HDMI_ACR_48_0, HDMI_ACR_CTS_48, audio_clock_info.cts_48khz); - - /* HDMI_ACR_48_1__HDMI_ACR_N_48_MASK */ - REG_UPDATE(HDMI_ACR_48_1, HDMI_ACR_N_48, audio_clock_info.n_48khz); - - /* Video driver cannot know in advance which sample rate will - be used by HD Audio driver - HDMI_ACR_PACKET_CONTROL__HDMI_ACR_N_MULTIPLE field is - programmed below in interruppt callback */ - } /* if */ + get_audio_clock_info(crtc_info->color_depth, + crtc_info->requested_pixel_clock, + crtc_info->calculated_pixel_clock, + &audio_clock_info); + dm_logger_write(enc->ctx->logger, LOG_HW_AUDIO, + "\n%s:Input::requested_pixel_clock = %d" \ + "calculated_pixel_clock = %d \n", __func__, \ + crtc_info->requested_pixel_clock, \ + crtc_info->calculated_pixel_clock); + + /* HDMI_ACR_32_0__HDMI_ACR_CTS_32_MASK */ + REG_UPDATE(HDMI_ACR_32_0, HDMI_ACR_CTS_32, audio_clock_info.cts_32khz); + + /* HDMI_ACR_32_1__HDMI_ACR_N_32_MASK */ + REG_UPDATE(HDMI_ACR_32_1, HDMI_ACR_N_32, audio_clock_info.n_32khz); + + /* HDMI_ACR_44_0__HDMI_ACR_CTS_44_MASK */ + REG_UPDATE(HDMI_ACR_44_0, HDMI_ACR_CTS_44, audio_clock_info.cts_44khz); + + /* HDMI_ACR_44_1__HDMI_ACR_N_44_MASK */ + REG_UPDATE(HDMI_ACR_44_1, HDMI_ACR_N_44, audio_clock_info.n_44khz); + + /* HDMI_ACR_48_0__HDMI_ACR_CTS_48_MASK */ + REG_UPDATE(HDMI_ACR_48_0, HDMI_ACR_CTS_48, audio_clock_info.cts_48khz); + + /* HDMI_ACR_48_1__HDMI_ACR_N_48_MASK */ + REG_UPDATE(HDMI_ACR_48_1, HDMI_ACR_N_48, audio_clock_info.n_48khz); + + /* Video driver cannot know in advance which sample rate will + be used by HD Audio driver + HDMI_ACR_PACKET_CONTROL__HDMI_ACR_N_MULTIPLE field is + programmed below in interruppt callback */ /* AFMT_60958_0__AFMT_60958_CS_CHANNEL_NUMBER_L_MASK & AFMT_60958_0__AFMT_60958_CS_CLOCK_ACCURACY_MASK */ -- cgit From 4dec2aa9eb1386e592d76f380360360178c4af02 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 14:34:35 +1000 Subject: amdgpu/dc: make program_regamma_pwl return void The return value was unused. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_transform.c | 4 +--- drivers/gpu/drm/amd/display/dc/dce/dce_transform.h | 2 +- drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c | 4 +--- drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.h | 2 +- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c | 4 +--- drivers/gpu/drm/amd/display/dc/inc/hw/transform.h | 2 +- 6 files changed, 6 insertions(+), 12 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c index c40d2e9e5f7c..ae32af31eff1 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c @@ -1375,7 +1375,7 @@ static void regamma_config_regions_and_segments( -bool dce110_opp_program_regamma_pwl( +void dce110_opp_program_regamma_pwl( struct transform *xfm, const struct pwl_params *params) { @@ -1386,8 +1386,6 @@ bool dce110_opp_program_regamma_pwl( /* Program PWL */ program_pwl(xfm_dce, params); - - return true; } void dce110_opp_power_on_regamma_lut( diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h index e1f1e5129f86..bfc94b4927b9 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h @@ -506,7 +506,7 @@ void dce110_opp_power_on_regamma_lut( struct transform *xfm, bool power_on); -bool dce110_opp_program_regamma_pwl( +void dce110_opp_program_regamma_pwl( struct transform *xfm, const struct pwl_params *params); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c index c86105b8cfaf..e98ed3058ea2 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c @@ -490,7 +490,7 @@ static void program_pwl(struct dce_transform *xfm_dce, } } -bool dce110_opp_program_regamma_pwl_v( +void dce110_opp_program_regamma_pwl_v( struct transform *xfm, const struct pwl_params *params) { @@ -512,8 +512,6 @@ bool dce110_opp_program_regamma_pwl_v( /* Power return to auto back */ power_on_lut(xfm, false, false, true); - - return true; } void dce110_opp_power_on_regamma_lut_v( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.h index eeed3b9f90f7..b70780210aad 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.h @@ -43,7 +43,7 @@ void dce110_opp_v_set_csc_adjustment( const struct out_csc_color_matrix *tbl_entry); -bool dce110_opp_program_regamma_pwl_v( +void dce110_opp_program_regamma_pwl_v( struct transform *xfm, const struct pwl_params *params); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c index ac03b04f1ea5..8607ab2da610 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c @@ -183,7 +183,7 @@ void dpp_reset(struct transform *xfm_base) -static bool dcn10_dpp_cm_set_regamma_pwl( +static void dcn10_dpp_cm_set_regamma_pwl( struct transform *xfm_base, const struct pwl_params *params) { struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); @@ -198,8 +198,6 @@ static bool dcn10_dpp_cm_set_regamma_pwl( dcn10_dpp_cm_program_regamma_lut( xfm_base, params->rgb_resulted, params->hw_points_num); - - return true; } static void dcn10_dpp_cm_set_regamma_mode( diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h index 9d4a3a0098a9..785d39706832 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h @@ -213,7 +213,7 @@ struct transform_funcs { struct transform *xfm, const struct pwl_params *params); - bool (*opp_program_regamma_pwl)( + void (*opp_program_regamma_pwl)( struct transform *xfm, const struct pwl_params *params); void (*opp_set_regamma_mode)( -- cgit From 4179cd81376112d627216580b09b803eb25e1635 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 14:34:36 +1000 Subject: amdgpu/dc: make some audio functions return void There is no need to check for these pointers being valid at this level. Check earlier if required. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_audio.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c index 198f4532e100..6e940286c98d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c @@ -703,14 +703,11 @@ void dce_aud_az_configure( */ /* search pixel clock value for Azalia HDMI Audio */ -static bool get_azalia_clock_info_hdmi( +static void get_azalia_clock_info_hdmi( uint32_t crtc_pixel_clock_in_khz, uint32_t actual_pixel_clock_in_khz, struct azalia_clock_info *azalia_clock_info) { - if (azalia_clock_info == NULL) - return false; - /* audio_dto_phase= 24 * 10,000; * 24MHz in [100Hz] units */ azalia_clock_info->audio_dto_phase = @@ -720,18 +717,13 @@ static bool get_azalia_clock_info_hdmi( * [khz] -> [100Hz] */ azalia_clock_info->audio_dto_module = actual_pixel_clock_in_khz * 10; - - return true; } -static bool get_azalia_clock_info_dp( +static void get_azalia_clock_info_dp( uint32_t requested_pixel_clock_in_khz, const struct audio_pll_info *pll_info, struct azalia_clock_info *azalia_clock_info) { - if (pll_info == NULL || azalia_clock_info == NULL) - return false; - /* Reported dpDtoSourceClockInkhz value for * DCE8 already adjusted for SS, do not need any * adjustment here anymore @@ -745,8 +737,6 @@ static bool get_azalia_clock_info_dp( * [khz] ->[100Hz] */ azalia_clock_info->audio_dto_module = pll_info->dp_dto_source_clock_in_khz * 10; - - return true; } void dce_aud_wall_dto_setup( -- cgit From b08c3ca4e90d03b3a120f4e60dba4b2b5e087433 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 15:44:54 +1000 Subject: amdgpu/dc: remove pointless returns in the i2caux constructor paths. (v2) There was lots of return true, and error checking that was never used in these paths. Just remove it all. v2: I missed one return true. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.c | 6 ++-- drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.h | 2 +- .../amd/display/dc/i2caux/dce100/i2caux_dce100.c | 21 +++++--------- .../display/dc/i2caux/dce110/aux_engine_dce110.c | 20 +++----------- .../dc/i2caux/dce110/i2c_hw_engine_dce110.c | 24 ++++++---------- .../dc/i2caux/dce110/i2c_hw_engine_dce110.h | 4 --- .../dc/i2caux/dce110/i2c_sw_engine_dce110.c | 20 +++----------- .../amd/display/dc/i2caux/dce110/i2caux_dce110.c | 30 ++++++-------------- .../amd/display/dc/i2caux/dce110/i2caux_dce110.h | 2 +- .../amd/display/dc/i2caux/dce112/i2caux_dce112.c | 30 ++++++-------------- .../amd/display/dc/i2caux/dce120/i2caux_dce120.c | 21 +++++--------- .../display/dc/i2caux/dce80/i2c_hw_engine_dce80.c | 32 ++++++++-------------- .../display/dc/i2caux/dce80/i2c_sw_engine_dce80.c | 19 +++---------- .../drm/amd/display/dc/i2caux/dce80/i2caux_dce80.c | 19 +++---------- .../drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.c | 21 +++++--------- .../display/dc/i2caux/diagnostics/i2caux_diag.c | 20 +++----------- drivers/gpu/drm/amd/display/dc/i2caux/engine.h | 2 +- .../gpu/drm/amd/display/dc/i2caux/engine_base.c | 3 +- drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.c | 7 ++--- drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.h | 2 +- .../amd/display/dc/i2caux/i2c_generic_hw_engine.c | 6 ++-- .../amd/display/dc/i2caux/i2c_generic_hw_engine.h | 2 +- .../gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.c | 6 ++-- .../gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.h | 2 +- .../gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.c | 17 +++--------- .../gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.h | 2 +- drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c | 4 +-- drivers/gpu/drm/amd/display/dc/i2caux/i2caux.h | 2 +- 28 files changed, 100 insertions(+), 246 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.c b/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.c index 3c9608ce94b8..fc7a7d4ebca5 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.c @@ -555,15 +555,13 @@ bool dal_aux_engine_submit_request( return result; } -bool dal_aux_engine_construct( +void dal_aux_engine_construct( struct aux_engine *engine, struct dc_context *ctx) { - if (!dal_i2caux_construct_engine(&engine->base, ctx)) - return false; + dal_i2caux_construct_engine(&engine->base, ctx); engine->delay = 0; engine->max_defer_write_retry = 0; - return true; } void dal_aux_engine_destruct( diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.h b/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.h index 40b202893772..8e71324ccb10 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.h +++ b/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.h @@ -100,7 +100,7 @@ struct aux_engine { bool acquire_reset; }; -bool dal_aux_engine_construct( +void dal_aux_engine_construct( struct aux_engine *engine, struct dc_context *ctx); diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce100/i2caux_dce100.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce100/i2caux_dce100.c index c45a2ee8c336..e8d3781deaed 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce100/i2caux_dce100.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce100/i2caux_dce100.c @@ -95,18 +95,11 @@ struct i2caux *dal_i2caux_dce100_create( return NULL; } - if (dal_i2caux_dce110_construct( - i2caux_dce110, - ctx, - dce100_aux_regs, - dce100_hw_engine_regs, - &i2c_shift, - &i2c_mask)) - return &i2caux_dce110->base; - - ASSERT_CRITICAL(false); - - kfree(i2caux_dce110); - - return NULL; + dal_i2caux_dce110_construct(i2caux_dce110, + ctx, + dce100_aux_regs, + dce100_hw_engine_regs, + &i2c_shift, + &i2c_mask); + return &i2caux_dce110->base; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c index 4b673b48bf42..0c4bbc10510d 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c @@ -426,22 +426,16 @@ static const struct engine_funcs engine_funcs = { .acquire = dal_aux_engine_acquire, }; -static bool construct( +static void construct( struct aux_engine_dce110 *engine, const struct aux_engine_dce110_init_data *aux_init_data) { - if (!dal_aux_engine_construct( - &engine->base, aux_init_data->ctx)) { - ASSERT_CRITICAL(false); - return false; - } + dal_aux_engine_construct(&engine->base, aux_init_data->ctx); engine->base.base.funcs = &engine_funcs; engine->base.funcs = &aux_engine_funcs; engine->timeout_period = aux_init_data->timeout_period; engine->regs = aux_init_data->regs; - - return true; } static void destruct( @@ -471,12 +465,6 @@ struct aux_engine *dal_aux_engine_dce110_create( return NULL; } - if (construct(engine, aux_init_data)) - return &engine->base; - - ASSERT_CRITICAL(false); - - kfree(engine); - - return NULL; + construct(engine, aux_init_data); + return &engine->base; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.c index aab77a81008a..1a5b3f70ddc9 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.c @@ -498,17 +498,13 @@ static const struct i2c_hw_engine_funcs i2c_hw_engine_funcs = { .wait_on_operation_result = dal_i2c_hw_engine_wait_on_operation_result, }; -bool i2c_hw_engine_dce110_construct( +static void construct( struct i2c_hw_engine_dce110 *hw_engine, const struct i2c_hw_engine_dce110_create_arg *arg) { uint32_t xtal_ref_div = 0; - if (!arg->reference_frequency) - return false; - - if (!dal_i2c_hw_engine_construct(&hw_engine->base, arg->ctx)) - return false; + dal_i2c_hw_engine_construct(&hw_engine->base, arg->ctx); hw_engine->base.base.base.funcs = &engine_funcs; hw_engine->base.base.funcs = &i2c_engine_funcs; @@ -545,8 +541,6 @@ bool i2c_hw_engine_dce110_construct( */ hw_engine->reference_frequency = (arg->reference_frequency * 2) / xtal_ref_div; - - return true; } struct i2c_engine *dal_i2c_hw_engine_dce110_create( @@ -558,6 +552,10 @@ struct i2c_engine *dal_i2c_hw_engine_dce110_create( ASSERT_CRITICAL(false); return NULL; } + if (!arg->reference_frequency) { + ASSERT_CRITICAL(false); + return NULL; + } engine_dce10 = kzalloc(sizeof(struct i2c_hw_engine_dce110), GFP_KERNEL); @@ -567,12 +565,6 @@ struct i2c_engine *dal_i2c_hw_engine_dce110_create( return NULL; } - if (i2c_hw_engine_dce110_construct(engine_dce10, arg)) - return &engine_dce10->base.base; - - ASSERT_CRITICAL(false); - - kfree(engine_dce10); - - return NULL; + construct(engine_dce10, arg); + return &engine_dce10->base.base; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.h b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.h index c573c6459ec6..5bb04085f670 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.h +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.h @@ -207,8 +207,4 @@ struct i2c_hw_engine_dce110_create_arg { struct i2c_engine *dal_i2c_hw_engine_dce110_create( const struct i2c_hw_engine_dce110_create_arg *arg); -bool i2c_hw_engine_dce110_construct( - struct i2c_hw_engine_dce110 *engine_dce110, - const struct i2c_hw_engine_dce110_create_arg *arg); - #endif diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_sw_engine_dce110.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_sw_engine_dce110.c index bf2c4b240b78..3aa7f791e523 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_sw_engine_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_sw_engine_dce110.c @@ -118,7 +118,7 @@ static const struct engine_funcs engine_funcs = { .submit_request = dal_i2c_sw_engine_submit_request, }; -static bool construct( +static void construct( struct i2c_sw_engine_dce110 *engine_dce110, const struct i2c_sw_engine_dce110_create_arg *arg_dce110) { @@ -127,11 +127,7 @@ static bool construct( arg_base.ctx = arg_dce110->ctx; arg_base.default_speed = arg_dce110->default_speed; - if (!dal_i2c_sw_engine_construct( - &engine_dce110->base, &arg_base)) { - ASSERT_CRITICAL(false); - return false; - } + dal_i2c_sw_engine_construct(&engine_dce110->base, &arg_base); /*struct engine struct engine_funcs*/ engine_dce110->base.base.base.funcs = &engine_funcs; @@ -139,8 +135,6 @@ static bool construct( engine_dce110->base.base.funcs = &i2c_engine_funcs; engine_dce110->base.default_speed = arg_dce110->default_speed; engine_dce110->engine_id = arg_dce110->engine_id; - - return true; } struct i2c_engine *dal_i2c_sw_engine_dce110_create( @@ -161,12 +155,6 @@ struct i2c_engine *dal_i2c_sw_engine_dce110_create( return NULL; } - if (construct(engine_dce110, arg)) - return &engine_dce110->base.base; - - ASSERT_CRITICAL(false); - - kfree(engine_dce110); - - return NULL; + construct(engine_dce110, arg); + return &engine_dce110->base.base; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.c index ae9adb389319..2a047f8ca0e9 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.c @@ -196,7 +196,7 @@ static const struct dce110_i2c_hw_engine_mask i2c_mask = { I2C_COMMON_MASK_SH_LIST_DCE110(_MASK) }; -bool dal_i2caux_dce110_construct( +void dal_i2caux_dce110_construct( struct i2caux_dce110 *i2caux_dce110, struct dc_context *ctx, const struct dce110_aux_registers aux_regs[], @@ -217,10 +217,7 @@ bool dal_i2caux_dce110_construct( base = &i2caux_dce110->base; - if (!dal_i2caux_construct(base, ctx)) { - ASSERT_CRITICAL(false); - return false; - } + dal_i2caux_construct(base, ctx); i2caux_dce110->base.funcs = &i2caux_funcs; i2caux_dce110->i2c_hw_buffer_in_use = false; @@ -278,8 +275,6 @@ bool dal_i2caux_dce110_construct( } while (i < ARRAY_SIZE(hw_aux_lines)); /*TODO Generic I2C SW and HW*/ - - return true; } /* @@ -306,18 +301,11 @@ struct i2caux *dal_i2caux_dce110_create( return NULL; } - if (dal_i2caux_dce110_construct( - i2caux_dce110, - ctx, - dce110_aux_regs, - i2c_hw_engine_regs, - &i2c_shift, - &i2c_mask)) - return &i2caux_dce110->base; - - ASSERT_CRITICAL(false); - - kfree(i2caux_dce110); - - return NULL; + dal_i2caux_dce110_construct(i2caux_dce110, + ctx, + dce110_aux_regs, + i2c_hw_engine_regs, + &i2c_shift, + &i2c_mask); + return &i2caux_dce110->base; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.h b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.h index fd1cc23c3d70..1b1f71c60ac9 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.h +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.h @@ -42,7 +42,7 @@ struct dce110_i2c_hw_engine_mask; struct i2caux *dal_i2caux_dce110_create( struct dc_context *ctx); -bool dal_i2caux_dce110_construct( +void dal_i2caux_dce110_construct( struct i2caux_dce110 *i2caux_dce110, struct dc_context *ctx, const struct dce110_aux_registers *aux_regs, diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.c index 715ba4390957..dafc1a727f7f 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.c @@ -87,22 +87,16 @@ static const struct dce110_i2c_hw_engine_mask i2c_mask = { I2C_COMMON_MASK_SH_LIST_DCE110(_MASK) }; -static bool construct( +static void construct( struct i2caux_dce110 *i2caux_dce110, struct dc_context *ctx) { - if (!dal_i2caux_dce110_construct( - i2caux_dce110, - ctx, - dce112_aux_regs, - dce112_hw_engine_regs, - &i2c_shift, - &i2c_mask)) { - ASSERT_CRITICAL(false); - return false; - } - - return true; + dal_i2caux_dce110_construct(i2caux_dce110, + ctx, + dce112_aux_regs, + dce112_hw_engine_regs, + &i2c_shift, + &i2c_mask); } /* @@ -129,12 +123,6 @@ struct i2caux *dal_i2caux_dce112_create( return NULL; } - if (construct(i2caux_dce110, ctx)) - return &i2caux_dce110->base; - - ASSERT_CRITICAL(false); - - kfree(i2caux_dce110); - - return NULL; + construct(i2caux_dce110, ctx); + return &i2caux_dce110->base; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce120/i2caux_dce120.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce120/i2caux_dce120.c index d52827ae3f1a..668981a4c285 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce120/i2caux_dce120.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce120/i2caux_dce120.c @@ -108,18 +108,11 @@ struct i2caux *dal_i2caux_dce120_create( return NULL; } - if (dal_i2caux_dce110_construct( - i2caux_dce110, - ctx, - dce120_aux_regs, - dce120_hw_engine_regs, - &i2c_shift, - &i2c_mask)) - return &i2caux_dce110->base; - - ASSERT_CRITICAL(false); - - kfree(i2caux_dce110); - - return NULL; + dal_i2caux_dce110_construct(i2caux_dce110, + ctx, + dce120_aux_regs, + dce120_hw_engine_regs, + &i2c_shift, + &i2c_mask); + return &i2caux_dce110->base; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.c index d41e37c94214..fd0832dd2c75 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.c @@ -824,20 +824,11 @@ static const struct i2c_hw_engine_funcs i2c_hw_engine_funcs = { dal_i2c_hw_engine_wait_on_operation_result, }; -static bool construct( +static void construct( struct i2c_hw_engine_dce80 *engine, const struct i2c_hw_engine_dce80_create_arg *arg) { - if (arg->engine_id >= sizeof(ddc_setup_offset) / sizeof(int32_t)) - return false; - if (arg->engine_id >= sizeof(ddc_speed_offset) / sizeof(int32_t)) - return false; - - if (!arg->reference_frequency) - return false; - - if (!dal_i2c_hw_engine_construct(&engine->base, arg->ctx)) - return false; + dal_i2c_hw_engine_construct(&engine->base, arg->ctx); engine->base.base.base.funcs = &engine_funcs; engine->base.base.funcs = &i2c_engine_funcs; @@ -853,8 +844,6 @@ static bool construct( engine->buffer_used_bytes = 0; engine->transaction_count = 0; engine->engine_keep_power_up_count = 1; - - return true; } struct i2c_engine *dal_i2c_hw_engine_dce80_create( @@ -867,6 +856,13 @@ struct i2c_engine *dal_i2c_hw_engine_dce80_create( return NULL; } + if ((arg->engine_id >= sizeof(ddc_setup_offset) / sizeof(int32_t)) || + (arg->engine_id >= sizeof(ddc_speed_offset) / sizeof(int32_t)) || + !arg->reference_frequency) { + BREAK_TO_DEBUGGER(); + return NULL; + } + engine = kzalloc(sizeof(struct i2c_hw_engine_dce80), GFP_KERNEL); if (!engine) { @@ -874,12 +870,6 @@ struct i2c_engine *dal_i2c_hw_engine_dce80_create( return NULL; } - if (construct(engine, arg)) - return &engine->base.base; - - BREAK_TO_DEBUGGER(); - - kfree(engine); - - return NULL; + construct(engine, arg); + return &engine->base.base; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_sw_engine_dce80.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_sw_engine_dce80.c index 6be77bc931c6..4853ee26096a 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_sw_engine_dce80.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_sw_engine_dce80.c @@ -133,7 +133,7 @@ static const struct engine_funcs engine_funcs = { .submit_request = dal_i2c_sw_engine_submit_request, }; -static bool construct( +static void construct( struct i2c_sw_engine_dce80 *engine, const struct i2c_sw_engine_dce80_create_arg *arg) { @@ -142,17 +142,12 @@ static bool construct( arg_base.ctx = arg->ctx; arg_base.default_speed = arg->default_speed; - if (!dal_i2c_sw_engine_construct(&engine->base, &arg_base)) { - BREAK_TO_DEBUGGER(); - return false; - } + dal_i2c_sw_engine_construct(&engine->base, &arg_base); engine->base.base.base.funcs = &engine_funcs; engine->base.base.funcs = &i2c_engine_funcs; engine->base.default_speed = arg->default_speed; engine->engine_id = arg->engine_id; - - return true; } struct i2c_engine *dal_i2c_sw_engine_dce80_create( @@ -172,13 +167,7 @@ struct i2c_engine *dal_i2c_sw_engine_dce80_create( return NULL; } - if (construct(engine, arg)) - return &engine->base.base; - - BREAK_TO_DEBUGGER(); - - kfree(engine); - - return NULL; + construct(engine, arg); + return &engine->base.base; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2caux_dce80.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2caux_dce80.c index d3c157e5eccd..ed48596dd2a5 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2caux_dce80.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2caux_dce80.c @@ -187,7 +187,7 @@ static const struct i2caux_funcs i2caux_funcs = { .acquire_aux_engine = dal_i2caux_acquire_aux_engine, }; -static bool construct( +static void construct( struct i2caux_dce80 *i2caux_dce80, struct dc_context *ctx) { @@ -207,10 +207,7 @@ static bool construct( uint32_t i; - if (!dal_i2caux_construct(base, ctx)) { - BREAK_TO_DEBUGGER(); - return false; - } + dal_i2caux_construct(base, ctx); i2caux_dce80->base.funcs = &i2caux_funcs; i2caux_dce80->i2c_hw_buffer_in_use = false; @@ -269,8 +266,6 @@ static bool construct( } while (i < ARRAY_SIZE(hw_aux_lines)); /* TODO Generic I2C SW and HW */ - - return true; } struct i2caux *dal_i2caux_dce80_create( @@ -284,12 +279,6 @@ struct i2caux *dal_i2caux_dce80_create( return NULL; } - if (construct(i2caux_dce80, ctx)) - return &i2caux_dce80->base; - - BREAK_TO_DEBUGGER(); - - kfree(i2caux_dce80); - - return NULL; + construct(i2caux_dce80, ctx); + return &i2caux_dce80->base; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.c b/drivers/gpu/drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.c index f8659f1c5f9d..13b807d8aff8 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.c @@ -108,18 +108,11 @@ struct i2caux *dal_i2caux_dcn10_create( return NULL; } - if (dal_i2caux_dce110_construct( - i2caux_dce110, - ctx, - dcn10_aux_regs, - dcn10_hw_engine_regs, - &i2c_shift, - &i2c_mask)) - return &i2caux_dce110->base; - - ASSERT_CRITICAL(false); - - kfree(i2caux_dce110); - - return NULL; + dal_i2caux_dce110_construct(i2caux_dce110, + ctx, + dcn10_aux_regs, + dcn10_hw_engine_regs, + &i2c_shift, + &i2c_mask); + return &i2caux_dce110->base; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.c b/drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.c index 1fdb3252920b..e6408f644086 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.c @@ -73,18 +73,12 @@ static const struct i2caux_funcs i2caux_funcs = { .acquire_aux_engine = NULL, }; -static bool construct( +static void construct( struct i2caux *i2caux, struct dc_context *ctx) { - if (!dal_i2caux_construct(i2caux, ctx)) { - ASSERT_CRITICAL(false); - return false; - } - + dal_i2caux_construct(i2caux, ctx); i2caux->funcs = &i2caux_funcs; - - return true; } struct i2caux *dal_i2caux_diag_fpga_create( @@ -98,12 +92,6 @@ struct i2caux *dal_i2caux_diag_fpga_create( return NULL; } - if (construct(i2caux, ctx)) - return i2caux; - - ASSERT_CRITICAL(false); - - kfree(i2caux); - - return NULL; + construct(i2caux, ctx); + return i2caux; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/engine.h b/drivers/gpu/drm/amd/display/dc/i2caux/engine.h index 76fe2df3c2f8..33de8a8834dc 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/engine.h +++ b/drivers/gpu/drm/amd/display/dc/i2caux/engine.h @@ -110,7 +110,7 @@ struct engine { struct dc_context *ctx; }; -bool dal_i2caux_construct_engine( +void dal_i2caux_construct_engine( struct engine *engine, struct dc_context *ctx); diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/engine_base.c b/drivers/gpu/drm/amd/display/dc/i2caux/engine_base.c index 09da81379491..5d155d36d353 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/engine_base.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/engine_base.c @@ -36,13 +36,12 @@ #include "engine.h" -bool dal_i2caux_construct_engine( +void dal_i2caux_construct_engine( struct engine *engine, struct dc_context *ctx) { engine->ddc = NULL; engine->ctx = ctx; - return true; } void dal_i2caux_destruct_engine( diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.c index 144f51dc4523..70e20bd47ce4 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.c @@ -103,15 +103,12 @@ void dal_i2c_engine_process_channel_reply( } -bool dal_i2c_engine_construct( +void dal_i2c_engine_construct( struct i2c_engine *engine, struct dc_context *ctx) { - if (!dal_i2caux_construct_engine(&engine->base, ctx)) - return false; - + dal_i2caux_construct_engine(&engine->base, ctx); engine->timeout_delay = 0; - return true; } void dal_i2c_engine_destruct( diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.h b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.h index ce2c51ddea02..58fc0f25eceb 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.h +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.h @@ -88,7 +88,7 @@ struct i2c_engine { uint32_t timeout_delay; }; -bool dal_i2c_engine_construct( +void dal_i2c_engine_construct( struct i2c_engine *engine, struct dc_context *ctx); diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_generic_hw_engine.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_generic_hw_engine.c index 521c4ec98632..5a4295e0fae5 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_generic_hw_engine.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_generic_hw_engine.c @@ -270,13 +270,11 @@ uint32_t dal_i2c_generic_hw_engine_get_transaction_timeout( (1 + (length << 3) + 1); } -bool dal_i2c_generic_hw_engine_construct( +void dal_i2c_generic_hw_engine_construct( struct i2c_generic_hw_engine *engine, struct dc_context *ctx) { - if (!dal_i2c_hw_engine_construct(&engine->base, ctx)) - return false; - return true; + dal_i2c_hw_engine_construct(&engine->base, ctx); } void dal_i2c_generic_hw_engine_destruct( diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_generic_hw_engine.h b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_generic_hw_engine.h index 083bb0dee9a1..1da0397b04a2 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_generic_hw_engine.h +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_generic_hw_engine.h @@ -59,7 +59,7 @@ struct i2c_generic_hw_engine { const struct i2c_generic_hw_engine_funcs *funcs; }; -bool dal_i2c_generic_hw_engine_construct( +void dal_i2c_generic_hw_engine_construct( struct i2c_generic_hw_engine *engine, struct dc_context *ctx); diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.c index 00a8f07a74e9..4b54fcfb28ec 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.c @@ -228,15 +228,13 @@ enum i2c_channel_operation_result dal_i2c_hw_engine_wait_on_operation_result( return result; } -bool dal_i2c_hw_engine_construct( +void dal_i2c_hw_engine_construct( struct i2c_hw_engine *engine, struct dc_context *ctx) { - if (!dal_i2c_engine_construct(&engine->base, ctx)) - return false; + dal_i2c_engine_construct(&engine->base, ctx); engine->original_speed = I2CAUX_DEFAULT_I2C_HW_SPEED; engine->default_speed = I2CAUX_DEFAULT_I2C_HW_SPEED; - return true; } void dal_i2c_hw_engine_destruct( diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.h b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.h index f2df1749820e..8936a994804a 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.h +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.h @@ -53,7 +53,7 @@ struct i2c_hw_engine { uint32_t default_speed; }; -bool dal_i2c_hw_engine_construct( +void dal_i2c_hw_engine_construct( struct i2c_hw_engine *engine, struct dc_context *ctx); diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.c index 9d0077ade12c..8e19bb629394 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.c @@ -569,17 +569,14 @@ static const struct engine_funcs engine_funcs = { .submit_request = dal_i2c_sw_engine_submit_request, }; -bool dal_i2c_sw_engine_construct( +void dal_i2c_sw_engine_construct( struct i2c_sw_engine *engine, const struct i2c_sw_engine_create_arg *arg) { - if (!dal_i2c_engine_construct(&engine->base, arg->ctx)) - return false; - + dal_i2c_engine_construct(&engine->base, arg->ctx); dal_i2c_sw_engine_set_speed(&engine->base, arg->default_speed); engine->base.funcs = &i2c_engine_funcs; engine->base.base.funcs = &engine_funcs; - return true; } struct i2c_engine *dal_i2c_sw_engine_create( @@ -599,12 +596,6 @@ struct i2c_engine *dal_i2c_sw_engine_create( return NULL; } - if (dal_i2c_sw_engine_construct(engine, arg)) - return &engine->base; - - BREAK_TO_DEBUGGER(); - - kfree(engine); - - return NULL; + dal_i2c_sw_engine_construct(engine, arg); + return &engine->base; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.h b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.h index e0cb4c3d483d..546f15b0d3f1 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.h +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.h @@ -48,7 +48,7 @@ struct i2c_sw_engine_create_arg { struct dc_context *ctx; }; -bool dal_i2c_sw_engine_construct( +void dal_i2c_sw_engine_construct( struct i2c_sw_engine *engine, const struct i2c_sw_engine_create_arg *arg); diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c index 9b115e1e2f1a..e1593ffe5a2b 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c @@ -423,7 +423,7 @@ void dal_i2caux_release_engine( engine->ddc = NULL; } -bool dal_i2caux_construct( +void dal_i2caux_construct( struct i2caux *i2caux, struct dc_context *ctx) { @@ -451,8 +451,6 @@ bool dal_i2caux_construct( i2caux->default_i2c_hw_speed = DEFAULT_I2C_HW_SPEED; i2caux->default_i2c_sw_speed = DEFAULT_I2C_SW_SPEED; } - - return true; } void dal_i2caux_destruct( diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.h b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.h index bc20de3da1c4..64f51bb06915 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.h +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.h @@ -97,7 +97,7 @@ struct i2caux { uint32_t default_i2c_hw_speed; }; -bool dal_i2caux_construct( +void dal_i2caux_construct( struct i2caux *i2caux, struct dc_context *ctx); -- cgit From 0e1c42fd181e7359be5c97655198551b6660f028 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 14:34:38 +1000 Subject: amdgpu/dc: cleanup construct returns in gpio. This is similiar to previous patches, don't return when we don't need to, also do error checking before allocating memory, makes it simpler to cleanup after. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c | 33 +++++++------------ drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.c | 4 +-- drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.h | 2 +- drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.c | 47 ++++++++++----------------- 4 files changed, 30 insertions(+), 56 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c index 7b6efa4f2efd..310f48965b27 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c @@ -199,25 +199,14 @@ static const struct hw_gpio_pin_funcs funcs = { .close = dal_hw_gpio_close, }; -static bool construct( +static void construct( struct hw_ddc *ddc, enum gpio_id id, uint32_t en, struct dc_context *ctx) { - if ((en < GPIO_DDC_LINE_MIN) || (en > GPIO_DDC_LINE_MAX)) { - ASSERT_CRITICAL(false); - return false; - } - - if (!dal_hw_gpio_construct(&ddc->base, id, en, ctx)) { - ASSERT_CRITICAL(false); - return false; - } - + dal_hw_gpio_construct(&ddc->base, id, en, ctx); ddc->base.base.funcs = &funcs; - - return true; } struct hw_gpio_pin *dal_hw_ddc_create( @@ -225,19 +214,19 @@ struct hw_gpio_pin *dal_hw_ddc_create( enum gpio_id id, uint32_t en) { - struct hw_ddc *pin = kzalloc(sizeof(struct hw_ddc), GFP_KERNEL); + struct hw_ddc *pin; - if (!pin) { + if ((en < GPIO_DDC_LINE_MIN) || (en > GPIO_DDC_LINE_MAX)) { ASSERT_CRITICAL(false); return NULL; } - if (construct(pin, id, en, ctx)) - return &pin->base.base; - - ASSERT_CRITICAL(false); - - kfree(pin); + pin = kzalloc(sizeof(struct hw_ddc), GFP_KERNEL); + if (!pin) { + ASSERT_CRITICAL(false); + return NULL; + } - return NULL; + construct(pin, id, en, ctx); + return &pin->base.base; } diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.c index 4cdcdfb73e5c..660510842ecf 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.c @@ -176,7 +176,7 @@ enum gpio_result dal_hw_gpio_config_mode( } } -bool dal_hw_gpio_construct( +void dal_hw_gpio_construct( struct hw_gpio *pin, enum gpio_id id, uint32_t en, @@ -194,8 +194,6 @@ bool dal_hw_gpio_construct( pin->store.mux = 0; pin->mux_supported = false; - - return true; } void dal_hw_gpio_destruct( diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.h b/drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.h index fb41ee2be958..bca0cef18ff9 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.h +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.h @@ -109,7 +109,7 @@ struct hw_gpio { #define HW_GPIO_FROM_BASE(hw_gpio_pin) \ container_of((hw_gpio_pin), struct hw_gpio, base) -bool dal_hw_gpio_construct( +void dal_hw_gpio_construct( struct hw_gpio *pin, enum gpio_id id, uint32_t en, diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.c index 0c255c02045b..784feccc5853 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.c @@ -41,15 +41,13 @@ #define REG(reg)\ (hpd->regs->reg) -static bool dal_hw_hpd_construct( +static void dal_hw_hpd_construct( struct hw_hpd *pin, enum gpio_id id, uint32_t en, struct dc_context *ctx) { - if (!dal_hw_gpio_construct(&pin->base, id, en, ctx)) - return false; - return true; + dal_hw_gpio_construct(&pin->base, id, en, ctx); } static void dal_hw_hpd_destruct( @@ -126,30 +124,14 @@ static const struct hw_gpio_pin_funcs funcs = { .close = dal_hw_gpio_close, }; -static bool construct( +static void construct( struct hw_hpd *hpd, enum gpio_id id, uint32_t en, struct dc_context *ctx) { - if (id != GPIO_ID_HPD) { - ASSERT_CRITICAL(false); - return false; - } - - if ((en < GPIO_HPD_MIN) || (en > GPIO_HPD_MAX)) { - ASSERT_CRITICAL(false); - return false; - } - - if (!dal_hw_hpd_construct(hpd, id, en, ctx)) { - ASSERT_CRITICAL(false); - return false; - } - + dal_hw_hpd_construct(hpd, id, en, ctx); hpd->base.base.funcs = &funcs; - - return true; } struct hw_gpio_pin *dal_hw_hpd_create( @@ -157,19 +139,24 @@ struct hw_gpio_pin *dal_hw_hpd_create( enum gpio_id id, uint32_t en) { - struct hw_hpd *hpd = kzalloc(sizeof(struct hw_hpd), GFP_KERNEL); + struct hw_hpd *hpd; - if (!hpd) { + if (id != GPIO_ID_HPD) { ASSERT_CRITICAL(false); return NULL; } - if (construct(hpd, id, en, ctx)) - return &hpd->base.base; - - ASSERT_CRITICAL(false); + if ((en < GPIO_HPD_MIN) || (en > GPIO_HPD_MAX)) { + ASSERT_CRITICAL(false); + return NULL; + } - kfree(hpd); + hpd = kzalloc(sizeof(struct hw_hpd), GFP_KERNEL); + if (!hpd) { + ASSERT_CRITICAL(false); + return NULL; + } - return NULL; + construct(hpd, id, en, ctx); + return &hpd->base.base; } -- cgit From c13b408b81f8a101501d78ca499afee98e0f0ab9 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 14:34:39 +1000 Subject: amdgpu/dc: another round of dce/dcn construct cleanups. This removes any remaining pointless return codepaths from the DCE code. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dce100/dce100_hw_sequencer.c | 4 +--- .../drm/amd/display/dc/dce100/dce100_hw_sequencer.h | 2 +- .../gpu/drm/amd/display/dc/dce100/dce100_resource.c | 4 +--- .../drm/amd/display/dc/dce110/dce110_compressor.c | 11 +++-------- .../drm/amd/display/dc/dce110/dce110_compressor.h | 2 +- .../drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 4 +--- .../drm/amd/display/dc/dce110/dce110_hw_sequencer.h | 2 +- drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c | 4 +--- drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h | 2 +- .../gpu/drm/amd/display/dc/dce110/dce110_resource.c | 6 ++---- .../display/dc/dce110/dce110_timing_generator_v.c | 7 +------ .../display/dc/dce110/dce110_timing_generator_v.h | 2 +- .../drm/amd/display/dc/dce112/dce112_compressor.c | 11 +++-------- .../drm/amd/display/dc/dce112/dce112_compressor.h | 2 +- .../drm/amd/display/dc/dce112/dce112_hw_sequencer.c | 4 +--- .../drm/amd/display/dc/dce112/dce112_hw_sequencer.h | 2 +- .../gpu/drm/amd/display/dc/dce112/dce112_resource.c | 3 +-- .../drm/amd/display/dc/dce120/dce120_hw_sequencer.c | 4 +--- .../drm/amd/display/dc/dce120/dce120_hw_sequencer.h | 2 +- .../gpu/drm/amd/display/dc/dce120/dce120_resource.c | 8 ++------ .../amd/display/dc/dce120/dce120_timing_generator.c | 7 +------ .../amd/display/dc/dce120/dce120_timing_generator.h | 2 +- .../gpu/drm/amd/display/dc/dce80/dce80_compressor.c | 11 +++-------- .../gpu/drm/amd/display/dc/dce80/dce80_compressor.h | 2 +- .../drm/amd/display/dc/dce80/dce80_hw_sequencer.c | 4 +--- .../drm/amd/display/dc/dce80/dce80_hw_sequencer.h | 2 +- .../gpu/drm/amd/display/dc/dce80/dce80_resource.c | 9 +++------ drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c | 4 +--- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h | 2 +- .../gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c | 4 +--- .../gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h | 2 +- .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 20 ++++++-------------- 32 files changed, 47 insertions(+), 108 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c index 492ea6069eb4..e7a694835e3e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c @@ -142,13 +142,11 @@ void dce100_set_bandwidth( /**************************************************************************/ -bool dce100_hw_sequencer_construct(struct dc *dc) +void dce100_hw_sequencer_construct(struct dc *dc) { dce110_hw_sequencer_construct(dc); dc->hwss.enable_display_power_gating = dce100_enable_display_power_gating; dc->hwss.set_bandwidth = dce100_set_bandwidth; - - return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h index 770b5bb1ff40..cb5384ef46c3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h @@ -31,7 +31,7 @@ struct dc; struct dc_state; -bool dce100_hw_sequencer_construct(struct dc *dc); +void dce100_hw_sequencer_construct(struct dc *dc); void dce100_set_bandwidth( struct dc *dc, diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 1caf2983dda5..0db987d504c0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -909,9 +909,7 @@ static bool construct( goto res_create_fail; /* Create hardware sequencer */ - if (!dce100_hw_sequencer_construct(dc)) - goto res_create_fail; - + dce100_hw_sequencer_construct(dc); return true; res_create_fail: diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c index 90770cb2ffcd..3872febb4f6b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c @@ -393,12 +393,8 @@ struct compressor *dce110_compressor_create(struct dc_context *ctx) if (!cp110) return NULL; - if (dce110_compressor_construct(cp110, ctx)) - return &cp110->base; - - BREAK_TO_DEBUGGER(); - kfree(cp110); - return NULL; + dce110_compressor_construct(cp110, ctx); + return &cp110->base; } void dce110_compressor_destroy(struct compressor **compressor) @@ -485,7 +481,7 @@ static const struct compressor_funcs dce110_compressor_funcs = { }; -bool dce110_compressor_construct(struct dce110_compressor *compressor, +void dce110_compressor_construct(struct dce110_compressor *compressor, struct dc_context *ctx) { @@ -522,6 +518,5 @@ bool dce110_compressor_construct(struct dce110_compressor *compressor, compressor->base.funcs = &dce110_compressor_funcs; #endif - return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.h index 460cb77b8d75..26c7335a1cbf 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.h @@ -42,7 +42,7 @@ struct dce110_compressor { struct compressor *dce110_compressor_create(struct dc_context *ctx); -bool dce110_compressor_construct(struct dce110_compressor *cp110, +void dce110_compressor_construct(struct dce110_compressor *cp110, struct dc_context *ctx); void dce110_compressor_destroy(struct compressor **cp); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 5bbfc34d6f01..de154329b049 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -2723,10 +2723,8 @@ static const struct hw_sequencer_funcs dce110_funcs = { }; -bool dce110_hw_sequencer_construct(struct dc *dc) +void dce110_hw_sequencer_construct(struct dc *dc) { dc->hwss = dce110_funcs; - - return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h index baa20c1f17ad..db6c19cd15eb 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h @@ -33,7 +33,7 @@ struct dc; struct dc_state; struct dm_pp_display_configuration; -bool dce110_hw_sequencer_construct(struct dc *dc); +void dce110_hw_sequencer_construct(struct dc *dc); enum dc_status dce110_apply_ctx_to_hw( struct dc *dc, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c index 69d6a110dbc3..3545e43a4b77 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c @@ -44,13 +44,11 @@ static const struct opp_funcs funcs = { dce110_opp_program_bit_depth_reduction }; -bool dce110_opp_v_construct(struct dce110_opp *opp110, +void dce110_opp_v_construct(struct dce110_opp *opp110, struct dc_context *ctx) { opp110->base.funcs = &funcs; opp110->base.ctx = ctx; - - return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h index 269c1a88d5bb..152af4c418cb 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h @@ -29,7 +29,7 @@ #include "opp.h" #include "core_types.h" -bool dce110_opp_v_construct(struct dce110_opp *opp110, +void dce110_opp_v_construct(struct dce110_opp *opp110, struct dc_context *ctx); /* underlay callbacks */ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 45c5facf79b1..017a1fd1f659 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -1041,8 +1041,7 @@ static bool underlay_create(struct dc_context *ctx, struct resource_pool *pool) (dce110_oppv == NULL)) return false; - if (!dce110_opp_v_construct(dce110_oppv, ctx)) - return false; + dce110_opp_v_construct(dce110_oppv, ctx); dce110_timing_generator_v_construct(dce110_tgv, ctx); dce110_mem_input_v_construct(dce110_miv, ctx); @@ -1292,8 +1291,7 @@ static bool construct( goto res_create_fail; /* Create hardware sequencer */ - if (!dce110_hw_sequencer_construct(dc)) - goto res_create_fail; + dce110_hw_sequencer_construct(dc); dc->caps.max_planes = pool->base.pipe_count; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c index 93ca6ae48cb9..07d9303d5477 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c @@ -668,13 +668,10 @@ static const struct timing_generator_funcs dce110_tg_v_funcs = { dce110_timing_generator_v_enable_advanced_request }; -bool dce110_timing_generator_v_construct( +void dce110_timing_generator_v_construct( struct dce110_timing_generator *tg110, struct dc_context *ctx) { - if (!tg110) - return false; - tg110->controller_id = CONTROLLER_ID_UNDERLAY0; tg110->base.funcs = &dce110_tg_v_funcs; @@ -688,6 +685,4 @@ bool dce110_timing_generator_v_construct( tg110->min_h_blank = 56; tg110->min_h_front_porch = 4; tg110->min_h_back_porch = 4; - - return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.h index 7e49ca8e26ad..d2623a5994e8 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.h @@ -26,7 +26,7 @@ #ifndef __DC_TIMING_GENERATOR_V_DCE110_H__ #define __DC_TIMING_GENERATOR_V_DCE110_H__ -bool dce110_timing_generator_v_construct( +void dce110_timing_generator_v_construct( struct dce110_timing_generator *tg110, struct dc_context *ctx); diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c index e75895baa132..69649928768c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c @@ -791,7 +791,7 @@ void dce112_compressor_set_fbc_invalidation_triggers( dm_write_reg(compressor->ctx, addr, value); } -bool dce112_compressor_construct(struct dce112_compressor *compressor, +void dce112_compressor_construct(struct dce112_compressor *compressor, struct dc_context *ctx) { struct dc_bios *bp = ctx->dc_bios; @@ -833,7 +833,6 @@ bool dce112_compressor_construct(struct dce112_compressor *compressor, compressor->base.embedded_panel_v_size = panel_info.lcd_timing.vertical_addressable; } - return true; } struct compressor *dce112_compressor_create(struct dc_context *ctx) @@ -844,12 +843,8 @@ struct compressor *dce112_compressor_create(struct dc_context *ctx) if (!cp110) return NULL; - if (dce112_compressor_construct(cp110, ctx)) - return &cp110->base; - - BREAK_TO_DEBUGGER(); - kfree(cp110); - return NULL; + dce112_compressor_construct(cp110, ctx); + return &cp110->base; } void dce112_compressor_destroy(struct compressor **compressor) diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.h b/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.h index 106506387270..f1227133f6df 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.h +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.h @@ -42,7 +42,7 @@ struct dce112_compressor { struct compressor *dce112_compressor_create(struct dc_context *ctx); -bool dce112_compressor_construct(struct dce112_compressor *cp110, +void dce112_compressor_construct(struct dce112_compressor *cp110, struct dc_context *ctx); void dce112_compressor_destroy(struct compressor **cp); diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.c index 8816e09110e1..1e4a7c13f0ed 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.c @@ -152,14 +152,12 @@ static bool dce112_enable_display_power_gating( return false; } -bool dce112_hw_sequencer_construct(struct dc *dc) +void dce112_hw_sequencer_construct(struct dc *dc) { /* All registers used by dce11.2 match those in dce11 in offset and * structure */ dce110_hw_sequencer_construct(dc); dc->hwss.enable_display_power_gating = dce112_enable_display_power_gating; - - return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.h index 37bd60cc93f9..e646f4a37fa2 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.h @@ -30,7 +30,7 @@ struct dc; -bool dce112_hw_sequencer_construct(struct dc *dc); +void dce112_hw_sequencer_construct(struct dc *dc); #endif /* __DC_HWSS_DCE112_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 251e4a29d56f..11902a2fdaa4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -1256,8 +1256,7 @@ static bool construct( dc->caps.max_planes = pool->base.pipe_count; /* Create hardware sequencer */ - if (!dce112_hw_sequencer_construct(dc)) - goto res_create_fail; + dce112_hw_sequencer_construct(dc); bw_calcs_init(dc->bw_dceip, dc->bw_vbios, dc->ctx->asic_id); diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c index 56e3b124f19c..1a0b54d6034e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c @@ -245,7 +245,7 @@ static void dce120_update_dchub( -bool dce120_hw_sequencer_construct(struct dc *dc) +void dce120_hw_sequencer_construct(struct dc *dc) { /* All registers used by dce11.2 match those in dce11 in offset and * structure @@ -253,7 +253,5 @@ bool dce120_hw_sequencer_construct(struct dc *dc) dce110_hw_sequencer_construct(dc); dc->hwss.enable_display_power_gating = dce120_enable_display_power_gating; dc->hwss.update_dchub = dce120_update_dchub; - - return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.h index 6448a17c2fde..77a6b86d7606 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.h @@ -30,7 +30,7 @@ struct dc; -bool dce120_hw_sequencer_construct(struct dc *dc); +void dce120_hw_sequencer_construct(struct dc *dc); #endif /* __DC_HWSS_DCE112_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index 13d75df71396..3ed28a870e20 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -429,12 +429,8 @@ static struct timing_generator *dce120_timing_generator_create( if (!tg110) return NULL; - if (dce120_timing_generator_construct(tg110, ctx, instance, offsets)) - return &tg110->base; - - BREAK_TO_DEBUGGER(); - kfree(tg110); - return NULL; + dce120_timing_generator_construct(tg110, ctx, instance, offsets); + return &tg110->base; } static void dce120_transform_destroy(struct transform **xfm) diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c index 791c9b084941..95d871be3a0b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c @@ -1143,15 +1143,12 @@ static const struct timing_generator_funcs dce120_tg_funcs = { }; -bool dce120_timing_generator_construct( +void dce120_timing_generator_construct( struct dce110_timing_generator *tg110, struct dc_context *ctx, uint32_t instance, const struct dce110_timing_generator_offsets *offsets) { - if (!tg110) - return false; - tg110->controller_id = CONTROLLER_ID_D0 + instance; tg110->base.inst = instance; @@ -1175,6 +1172,4 @@ bool dce120_timing_generator_construct( tg110->min_h_sync_width = 8; tg110->min_v_sync_width = 1; tg110->min_v_blank = 3; - - return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.h index 243c0a3493da..d69871ec0dde 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.h @@ -32,7 +32,7 @@ #include "dce110/dce110_timing_generator.h" -bool dce120_timing_generator_construct( +void dce120_timing_generator_construct( struct dce110_timing_generator *tg110, struct dc_context *ctx, uint32_t instance, diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.c index cc1c0d390945..951f2caba9b3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.c @@ -771,7 +771,7 @@ void dce80_compressor_set_fbc_invalidation_triggers( dm_write_reg(compressor->ctx, addr, value); } -bool dce80_compressor_construct(struct dce80_compressor *compressor, +void dce80_compressor_construct(struct dce80_compressor *compressor, struct dc_context *ctx) { struct dc_bios *bp = ctx->dc_bios; @@ -813,7 +813,6 @@ bool dce80_compressor_construct(struct dce80_compressor *compressor, compressor->base.embedded_panel_v_size = panel_info.lcd_timing.vertical_addressable; } - return true; } struct compressor *dce80_compressor_create(struct dc_context *ctx) @@ -824,12 +823,8 @@ struct compressor *dce80_compressor_create(struct dc_context *ctx) if (!cp80) return NULL; - if (dce80_compressor_construct(cp80, ctx)) - return &cp80->base; - - BREAK_TO_DEBUGGER(); - kfree(cp80); - return NULL; + dce80_compressor_construct(cp80, ctx); + return &cp80->base; } void dce80_compressor_destroy(struct compressor **compressor) diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.h b/drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.h index 01290969ff92..cca58b044402 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.h +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.h @@ -42,7 +42,7 @@ struct dce80_compressor { struct compressor *dce80_compressor_create(struct dc_context *ctx); -bool dce80_compressor_construct(struct dce80_compressor *cp80, +void dce80_compressor_construct(struct dce80_compressor *cp80, struct dc_context *ctx); void dce80_compressor_destroy(struct compressor **cp); diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c index 28fe3824441f..ccfcf1c0eeb3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c @@ -106,14 +106,12 @@ static bool dce80_enable_display_power_gating( return false; } -bool dce80_hw_sequencer_construct(struct dc *dc) +void dce80_hw_sequencer_construct(struct dc *dc) { dce110_hw_sequencer_construct(dc); dc->hwss.enable_display_power_gating = dce80_enable_display_power_gating; dc->hwss.pipe_control_lock = dce_pipe_control_lock; dc->hwss.set_bandwidth = dce100_set_bandwidth; - - return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.h index 9d6dd05bd596..7a1b31def66f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.h @@ -30,7 +30,7 @@ struct dc; -bool dce80_hw_sequencer_construct(struct dc *dc); +void dce80_hw_sequencer_construct(struct dc *dc); #endif /* __DC_HWSS_DCE80_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 5e00ca6a1292..c6571a908786 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -910,8 +910,7 @@ static bool dce80_construct( goto res_create_fail; /* Create hardware sequencer */ - if (!dce80_hw_sequencer_construct(dc)) - goto res_create_fail; + dce80_hw_sequencer_construct(dc); return true; @@ -1075,8 +1074,7 @@ static bool dce81_construct( goto res_create_fail; /* Create hardware sequencer */ - if (!dce80_hw_sequencer_construct(dc)) - goto res_create_fail; + dce80_hw_sequencer_construct(dc); return true; @@ -1236,8 +1234,7 @@ static bool dce83_construct( goto res_create_fail; /* Create hardware sequencer */ - if (!dce80_hw_sequencer_construct(dc)) - goto res_create_fail; + dce80_hw_sequencer_construct(dc); return true; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c index 8607ab2da610..9d9604f05095 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c @@ -397,7 +397,7 @@ static const struct transform_funcs dcn10_dpp_funcs = { /* Constructor, Destructor */ /*****************************************/ -bool dcn10_dpp_construct( +void dcn10_dpp_construct( struct dcn10_dpp *xfm, struct dc_context *ctx, uint32_t inst, @@ -421,6 +421,4 @@ bool dcn10_dpp_construct( xfm->lb_bits_per_entry = LB_BITS_PER_ENTRY; xfm->lb_memory_size = LB_TOTAL_NUMBER_OF_ENTRIES; /*0x1404*/ - - return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h index afe9d8f629d6..a1f6b01a2eb4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h @@ -1356,7 +1356,7 @@ void ippn10_cnv_setup ( void ippn10_full_bypass(struct transform *xfm_base); -bool dcn10_dpp_construct(struct dcn10_dpp *xfm110, +void dcn10_dpp_construct(struct dcn10_dpp *xfm110, struct dc_context *ctx, uint32_t inst, const struct dcn_dpp_registers *tf_regs, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index 9008cd03b139..c8088489c6a2 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -786,7 +786,7 @@ static struct mem_input_funcs dcn10_mem_input_funcs = { /* Constructor, Destructor */ /*****************************************/ -bool dcn10_mem_input_construct( +void dcn10_mem_input_construct( struct dcn10_mem_input *mi, struct dc_context *ctx, uint32_t inst, @@ -802,7 +802,5 @@ bool dcn10_mem_input_construct( mi->base.inst = inst; mi->base.opp_id = 0xf; mi->base.mpcc_id = 0xf; - - return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h index acee05155b5b..aefd3e7bd7eb 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h @@ -538,7 +538,7 @@ struct dcn10_mem_input { const struct dcn_mi_mask *mi_mask; }; -bool dcn10_mem_input_construct( +void dcn10_mem_input_construct( struct dcn10_mem_input *mi, struct dc_context *ctx, uint32_t inst, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index c2df57b5e921..fb3ef134ea12 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -462,13 +462,9 @@ static struct transform *dcn10_dpp_create( if (!dpp) return NULL; - if (dcn10_dpp_construct(dpp, ctx, inst, - &tf_regs[inst], &tf_shift, &tf_mask)) - return &dpp->base; - - BREAK_TO_DEBUGGER(); - kfree(dpp); - return NULL; + dcn10_dpp_construct(dpp, ctx, inst, + &tf_regs[inst], &tf_shift, &tf_mask); + return &dpp->base; } static struct input_pixel_processor *dcn10_ipp_create( @@ -771,13 +767,9 @@ static struct mem_input *dcn10_mem_input_create( if (!mem_inputn10) return NULL; - if (dcn10_mem_input_construct(mem_inputn10, ctx, inst, - &mi_regs[inst], &mi_shift, &mi_mask)) - return &mem_inputn10->base; - - BREAK_TO_DEBUGGER(); - kfree(mem_inputn10); - return NULL; + dcn10_mem_input_construct(mem_inputn10, ctx, inst, + &mi_regs[inst], &mi_shift, &mi_mask); + return &mem_inputn10->base; } static void get_pixel_clock_parameters( -- cgit From 94de2bbdfa613165ff20a3e958775c8d01581946 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 14:34:40 +1000 Subject: amdgpu/dc: remove pointless return from build_pipe_hw_param This never returned anything else. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c | 6 +----- drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c | 10 ++-------- drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.h | 2 +- drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c | 6 +----- drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c | 6 +----- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 11 ++--------- 6 files changed, 8 insertions(+), 33 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 0db987d504c0..b1cf591b3408 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -631,16 +631,12 @@ static enum dc_status build_mapped_resource( struct dc_state *context, struct dc_stream_state *stream) { - enum dc_status status = DC_OK; struct pipe_ctx *pipe_ctx = resource_get_head_pipe_for_stream(&context->res_ctx, stream); if (!pipe_ctx) return DC_ERROR_UNEXPECTED; - status = dce110_resource_build_pipe_hw_param(pipe_ctx); - - if (status != DC_OK) - return status; + dce110_resource_build_pipe_hw_param(pipe_ctx); resource_build_info_frame(pipe_ctx); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 017a1fd1f659..89036aff9021 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -724,7 +724,7 @@ static void get_pixel_clock_parameters( } } -enum dc_status dce110_resource_build_pipe_hw_param(struct pipe_ctx *pipe_ctx) +void dce110_resource_build_pipe_hw_param(struct pipe_ctx *pipe_ctx) { get_pixel_clock_parameters(pipe_ctx, &pipe_ctx->stream_res.pix_clk_params); pipe_ctx->clock_source->funcs->get_pix_clk_dividers( @@ -734,8 +734,6 @@ enum dc_status dce110_resource_build_pipe_hw_param(struct pipe_ctx *pipe_ctx) resource_build_bit_depth_reduction_params(pipe_ctx->stream, &pipe_ctx->stream->bit_depth_params); pipe_ctx->stream->clamping.pixel_encoding = pipe_ctx->stream->timing.pixel_encoding; - - return DC_OK; } static bool is_surface_pixel_format_supported(struct pipe_ctx *pipe_ctx, unsigned int underlay_idx) @@ -754,7 +752,6 @@ static enum dc_status build_mapped_resource( struct dc_state *context, struct dc_stream_state *stream) { - enum dc_status status = DC_OK; struct pipe_ctx *pipe_ctx = resource_get_head_pipe_for_stream(&context->res_ctx, stream); if (!pipe_ctx) @@ -764,10 +761,7 @@ static enum dc_status build_mapped_resource( dc->res_pool->underlay_pipe_index)) return DC_SURFACE_PIXEL_FORMAT_UNSUPPORTED; - status = dce110_resource_build_pipe_hw_param(pipe_ctx); - - if (status != DC_OK) - return status; + dce110_resource_build_pipe_hw_param(pipe_ctx); /* TODO: validate audio ASIC caps, encoder */ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.h index 5bb692d037d9..e5f168c1f8c8 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.h @@ -38,7 +38,7 @@ struct dce110_resource_pool { struct resource_pool base; }; -enum dc_status dce110_resource_build_pipe_hw_param(struct pipe_ctx *pipe_ctx); +void dce110_resource_build_pipe_hw_param(struct pipe_ctx *pipe_ctx); struct resource_pool *dce110_create_resource_pool( uint8_t num_virtual_links, diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 11902a2fdaa4..663e0a047a4b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -704,16 +704,12 @@ static enum dc_status build_mapped_resource( struct dc_state *context, struct dc_stream_state *stream) { - enum dc_status status = DC_OK; struct pipe_ctx *pipe_ctx = resource_get_head_pipe_for_stream(&context->res_ctx, stream); if (!pipe_ctx) return DC_ERROR_UNEXPECTED; - status = dce110_resource_build_pipe_hw_param(pipe_ctx); - - if (status != DC_OK) - return status; + dce110_resource_build_pipe_hw_param(pipe_ctx); resource_build_info_frame(pipe_ctx); diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index c6571a908786..9c18efd3446f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -665,16 +665,12 @@ static enum dc_status build_mapped_resource( struct dc_state *context, struct dc_stream_state *stream) { - enum dc_status status = DC_OK; struct pipe_ctx *pipe_ctx = resource_get_head_pipe_for_stream(&context->res_ctx, stream); if (!pipe_ctx) return DC_ERROR_UNEXPECTED; - status = dce110_resource_build_pipe_hw_param(pipe_ctx); - - if (status != DC_OK) - return status; + dce110_resource_build_pipe_hw_param(pipe_ctx); resource_build_info_frame(pipe_ctx); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index fb3ef134ea12..dc878f77837b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -805,7 +805,7 @@ static void build_clamping_params(struct dc_stream_state *stream) stream->clamping.pixel_encoding = stream->timing.pixel_encoding; } -static enum dc_status build_pipe_hw_param(struct pipe_ctx *pipe_ctx) +static void build_pipe_hw_param(struct pipe_ctx *pipe_ctx) { get_pixel_clock_parameters(pipe_ctx, &pipe_ctx->stream_res.pix_clk_params); @@ -820,8 +820,6 @@ static enum dc_status build_pipe_hw_param(struct pipe_ctx *pipe_ctx) resource_build_bit_depth_reduction_params(pipe_ctx->stream, &pipe_ctx->stream->bit_depth_params); build_clamping_params(pipe_ctx->stream); - - return DC_OK; } static enum dc_status build_mapped_resource( @@ -829,7 +827,6 @@ static enum dc_status build_mapped_resource( struct dc_state *context, struct dc_stream_state *stream) { - enum dc_status status = DC_OK; struct pipe_ctx *pipe_ctx = resource_get_head_pipe_for_stream(&context->res_ctx, stream); /*TODO Seems unneeded anymore */ @@ -853,11 +850,7 @@ static enum dc_status build_mapped_resource( if (!pipe_ctx) return DC_ERROR_UNEXPECTED; - status = build_pipe_hw_param(pipe_ctx); - - if (status != DC_OK) - return status; - + build_pipe_hw_param(pipe_ctx); return DC_OK; } -- cgit From db6c3bdcfe2d810338f90a13d415d43dd98d342b Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 14:34:41 +1000 Subject: amdgpu: fixup construct to void paths on some more dc objects. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c | 10 +++------- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 18 +++++------------- drivers/gpu/drm/amd/display/dc/core/dc_surface.c | 15 +++------------ 3 files changed, 11 insertions(+), 32 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c index 226512c11ab7..315160d5f0f7 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c @@ -245,7 +245,7 @@ void dal_ddc_aux_payloads_add( } } -static bool construct( +static void construct( struct ddc_service *ddc_service, struct ddc_service_init_data *init_data) { @@ -282,7 +282,6 @@ static bool construct( connector_id == CONNECTOR_ID_LVDS; ddc_service->wa.raw = 0; - return true; } struct ddc_service *dal_ddc_service_create( @@ -295,11 +294,8 @@ struct ddc_service *dal_ddc_service_create( if (!ddc_service) return NULL; - if (construct(ddc_service, init_data)) - return ddc_service; - - kfree(ddc_service); - return NULL; + construct(ddc_service, init_data); + return ddc_service; } static void destruct(struct ddc_service *ddc) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index d5da847ffad6..a99196414255 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -56,7 +56,7 @@ static void update_stream_signal(struct dc_stream_state *stream) } } -static bool construct(struct dc_stream_state *stream, +static void construct(struct dc_stream_state *stream, struct dc_sink *dc_sink_data) { uint32_t i = 0; @@ -104,7 +104,6 @@ static bool construct(struct dc_stream_state *stream, stream->status.link = stream->sink->link; update_stream_signal(stream); - return true; } static void destruct(struct dc_stream_state *stream) @@ -142,25 +141,18 @@ struct dc_stream_state *dc_create_stream_for_sink( struct dc_stream_state *stream; if (sink == NULL) - goto alloc_fail; + return NULL; stream = kzalloc(sizeof(struct dc_stream_state), GFP_KERNEL); + if (stream == NULL) + return NULL; - if (NULL == stream) - goto alloc_fail; - - if (false == construct(stream, sink)) - goto construct_fail; + construct(stream, sink); atomic_inc(&stream->ref_count); return stream; -construct_fail: - kfree(stream); - -alloc_fail: - return NULL; } struct dc_stream_status *dc_stream_get_status( diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index 511ada94530e..f170ae95529c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -34,12 +34,11 @@ /******************************************************************************* * Private functions ******************************************************************************/ -static bool construct(struct dc_context *ctx, struct dc_plane_state *plane_state) +static void construct(struct dc_context *ctx, struct dc_plane_state *plane_state) { plane_state->ctx = ctx; memset(&plane_state->hdr_static_ctx, 0, sizeof(struct dc_hdr_static_metadata)); - return true; } static void destruct(struct dc_plane_state *plane_state) @@ -72,20 +71,12 @@ struct dc_plane_state *dc_create_plane_state(struct dc *dc) GFP_KERNEL); if (NULL == plane_state) - goto alloc_fail; - - if (false == construct(core_dc->ctx, plane_state)) - goto construct_fail; + return NULL; + construct(core_dc->ctx, plane_state); atomic_inc(&plane_state->ref_count); return plane_state; - -construct_fail: - kfree(plane_state); - -alloc_fail: - return NULL; } const struct dc_plane_status *dc_plane_get_status( -- cgit From 6be663b5bdb7cc299b2aafca56be39f6618090ab Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 14:34:42 +1000 Subject: amdgpu/dc: fix construct return values on irq service. This just removes more unused return/errors paths. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c | 14 ++++---------- .../gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c | 14 ++++---------- .../gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c | 14 ++++---------- .../gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c | 14 ++++---------- drivers/gpu/drm/amd/display/dc/irq/irq_service.c | 9 +++++---- drivers/gpu/drm/amd/display/dc/irq/irq_service.h | 2 +- 6 files changed, 22 insertions(+), 45 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c index 5c558969f39f..f7e40b292dfb 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c @@ -406,17 +406,14 @@ static const struct irq_service_funcs irq_service_funcs_dce110 = { .to_dal_irq_source = to_dal_irq_source_dce110 }; -static bool construct( +static void construct( struct irq_service *irq_service, struct irq_service_init_data *init_data) { - if (!dal_irq_service_construct(irq_service, init_data)) - return false; + dal_irq_service_construct(irq_service, init_data); irq_service->info = irq_source_info_dce110; irq_service->funcs = &irq_service_funcs_dce110; - - return true; } struct irq_service *dal_irq_service_dce110_create( @@ -428,9 +425,6 @@ struct irq_service *dal_irq_service_dce110_create( if (!irq_service) return NULL; - if (construct(irq_service, init_data)) - return irq_service; - - kfree(irq_service); - return NULL; + construct(irq_service, init_data); + return irq_service; } diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c b/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c index 61d7c286802a..2ad56b1a4099 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c @@ -265,17 +265,14 @@ static const struct irq_service_funcs irq_service_funcs_dce120 = { .to_dal_irq_source = to_dal_irq_source_dce110 }; -static bool construct( +static void construct( struct irq_service *irq_service, struct irq_service_init_data *init_data) { - if (!dal_irq_service_construct(irq_service, init_data)) - return false; + dal_irq_service_construct(irq_service, init_data); irq_service->info = irq_source_info_dce120; irq_service->funcs = &irq_service_funcs_dce120; - - return true; } struct irq_service *dal_irq_service_dce120_create( @@ -287,9 +284,6 @@ struct irq_service *dal_irq_service_dce120_create( if (!irq_service) return NULL; - if (construct(irq_service, init_data)) - return irq_service; - - kfree(irq_service); - return NULL; + construct(irq_service, init_data); + return irq_service; } diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c b/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c index d6e1fb665d90..8a2066c313fe 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c @@ -277,17 +277,14 @@ static const struct irq_service_funcs irq_service_funcs_dce80 = { .to_dal_irq_source = to_dal_irq_source_dce110 }; -static bool construct( +static void construct( struct irq_service *irq_service, struct irq_service_init_data *init_data) { - if (!dal_irq_service_construct(irq_service, init_data)) - return false; + dal_irq_service_construct(irq_service, init_data); irq_service->info = irq_source_info_dce80; irq_service->funcs = &irq_service_funcs_dce80; - - return true; } struct irq_service *dal_irq_service_dce80_create( @@ -299,11 +296,8 @@ struct irq_service *dal_irq_service_dce80_create( if (!irq_service) return NULL; - if (construct(irq_service, init_data)) - return irq_service; - - kfree(irq_service); - return NULL; + construct(irq_service, init_data); + return irq_service; } diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c b/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c index f6e861162a6e..74ad24714f6b 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c @@ -332,17 +332,14 @@ static const struct irq_service_funcs irq_service_funcs_dcn10 = { .to_dal_irq_source = to_dal_irq_source_dcn10 }; -static bool construct( +static void construct( struct irq_service *irq_service, struct irq_service_init_data *init_data) { - if (!dal_irq_service_construct(irq_service, init_data)) - return false; + dal_irq_service_construct(irq_service, init_data); irq_service->info = irq_source_info_dcn10; irq_service->funcs = &irq_service_funcs_dcn10; - - return true; } struct irq_service *dal_irq_service_dcn10_create( @@ -354,9 +351,6 @@ struct irq_service *dal_irq_service_dcn10_create( if (!irq_service) return NULL; - if (construct(irq_service, init_data)) - return irq_service; - - kfree(irq_service); - return NULL; + construct(irq_service, init_data); + return irq_service; } diff --git a/drivers/gpu/drm/amd/display/dc/irq/irq_service.c b/drivers/gpu/drm/amd/display/dc/irq/irq_service.c index ce20622c7c89..b106513fc2dc 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/irq_service.c +++ b/drivers/gpu/drm/amd/display/dc/irq/irq_service.c @@ -48,15 +48,16 @@ #define CTX \ irq_service->ctx -bool dal_irq_service_construct( +void dal_irq_service_construct( struct irq_service *irq_service, struct irq_service_init_data *init_data) { - if (!init_data || !init_data->ctx) - return false; + if (!init_data || !init_data->ctx) { + BREAK_TO_DEBUGGER(); + return; + } irq_service->ctx = init_data->ctx; - return true; } void dal_irq_service_destroy(struct irq_service **irq_service) diff --git a/drivers/gpu/drm/amd/display/dc/irq/irq_service.h b/drivers/gpu/drm/amd/display/dc/irq/irq_service.h index a2a2d6965c2f..dbfcb096eedd 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/irq_service.h +++ b/drivers/gpu/drm/amd/display/dc/irq/irq_service.h @@ -69,7 +69,7 @@ struct irq_service { const struct irq_service_funcs *funcs; }; -bool dal_irq_service_construct( +void dal_irq_service_construct( struct irq_service *irq_service, struct irq_service_init_data *init_data); -- cgit From c4fee8796119ee6403317461b73d6afba85f8113 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 15:45:07 +1000 Subject: amdgpu/dc: inline some of the fixed 32_32 fns This drops ~400 bytes here. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/basics/fixpt32_32.c | 60 ----------------- drivers/gpu/drm/amd/display/include/fixed32_32.h | 76 +++++++++++++++++----- 2 files changed, 61 insertions(+), 75 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/basics/fixpt32_32.c b/drivers/gpu/drm/amd/display/dc/basics/fixpt32_32.c index 911e90bb1b5c..4d3aaa82a07b 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/fixpt32_32.c +++ b/drivers/gpu/drm/amd/display/dc/basics/fixpt32_32.c @@ -57,14 +57,6 @@ struct fixed32_32 dal_fixed32_32_from_fraction(uint32_t n, uint32_t d) return fx; } -struct fixed32_32 dal_fixed32_32_from_int(uint32_t value) -{ - struct fixed32_32 fx; - - fx.value = (uint64_t)value<<32; - return fx; -} - struct fixed32_32 dal_fixed32_32_add( struct fixed32_32 lhs, struct fixed32_32 rhs) @@ -155,67 +147,15 @@ struct fixed32_32 dal_fixed32_32_div_int(struct fixed32_32 lhs, uint32_t rhs) return fx; } -struct fixed32_32 dal_fixed32_32_min( - struct fixed32_32 lhs, - struct fixed32_32 rhs) -{ - return (lhs.value < rhs.value) ? lhs : rhs; -} - -struct fixed32_32 dal_fixed32_32_max( - struct fixed32_32 lhs, - struct fixed32_32 rhs) -{ - return (lhs.value > rhs.value) ? lhs : rhs; -} - -bool dal_fixed32_32_gt(struct fixed32_32 lhs, struct fixed32_32 rhs) -{ - return lhs.value > rhs.value; -} -bool dal_fixed32_32_gt_int(struct fixed32_32 lhs, uint32_t rhs) -{ - return lhs.value > ((uint64_t)rhs<<32); -} - -bool dal_fixed32_32_lt(struct fixed32_32 lhs, struct fixed32_32 rhs) -{ - return lhs.value < rhs.value; -} - -bool dal_fixed32_32_le(struct fixed32_32 lhs, struct fixed32_32 rhs) -{ - return lhs.value <= rhs.value; -} - -bool dal_fixed32_32_lt_int(struct fixed32_32 lhs, uint32_t rhs) -{ - return lhs.value < ((uint64_t)rhs<<32); -} - -bool dal_fixed32_32_le_int(struct fixed32_32 lhs, uint32_t rhs) -{ - return lhs.value <= ((uint64_t)rhs<<32); -} - uint32_t dal_fixed32_32_ceil(struct fixed32_32 v) { ASSERT((uint32_t)v.value ? (v.value >> 32) + 1 >= 1 : true); return (v.value>>32) + ((uint32_t)v.value ? 1 : 0); } -uint32_t dal_fixed32_32_floor(struct fixed32_32 v) -{ - return v.value>>32; -} - uint32_t dal_fixed32_32_round(struct fixed32_32 v) { ASSERT(v.value + (1ULL<<31) >= (1ULL<<31)); return (v.value + (1ULL<<31))>>32; } -bool dal_fixed32_32_eq(struct fixed32_32 lhs, struct fixed32_32 rhs) -{ - return lhs.value == rhs.value; -} diff --git a/drivers/gpu/drm/amd/display/include/fixed32_32.h b/drivers/gpu/drm/amd/display/include/fixed32_32.h index c7ddd0e435eb..9c70341fe026 100644 --- a/drivers/gpu/drm/amd/display/include/fixed32_32.h +++ b/drivers/gpu/drm/amd/display/include/fixed32_32.h @@ -38,7 +38,14 @@ static const struct fixed32_32 dal_fixed32_32_one = { 0x100000000LL }; static const struct fixed32_32 dal_fixed32_32_half = { 0x80000000LL }; struct fixed32_32 dal_fixed32_32_from_fraction(uint32_t n, uint32_t d); -struct fixed32_32 dal_fixed32_32_from_int(uint32_t value); +static inline struct fixed32_32 dal_fixed32_32_from_int(uint32_t value) +{ + struct fixed32_32 fx; + + fx.value = (uint64_t)value<<32; + return fx; +} + struct fixed32_32 dal_fixed32_32_add( struct fixed32_32 lhs, struct fixed32_32 rhs); @@ -63,21 +70,60 @@ struct fixed32_32 dal_fixed32_32_div( struct fixed32_32 dal_fixed32_32_div_int( struct fixed32_32 lhs, uint32_t rhs); -struct fixed32_32 dal_fixed32_32_min( - struct fixed32_32 lhs, - struct fixed32_32 rhs); -struct fixed32_32 dal_fixed32_32_max( - struct fixed32_32 lhs, - struct fixed32_32 rhs); -bool dal_fixed32_32_gt(struct fixed32_32 lhs, struct fixed32_32 rhs); -bool dal_fixed32_32_gt_int(struct fixed32_32 lhs, uint32_t rhs); -bool dal_fixed32_32_lt(struct fixed32_32 lhs, struct fixed32_32 rhs); -bool dal_fixed32_32_lt_int(struct fixed32_32 lhs, uint32_t rhs); -bool dal_fixed32_32_le(struct fixed32_32 lhs, struct fixed32_32 rhs); -bool dal_fixed32_32_le_int(struct fixed32_32 lhs, uint32_t rhs); -bool dal_fixed32_32_eq(struct fixed32_32 lhs, struct fixed32_32 rhs); + +static inline struct fixed32_32 dal_fixed32_32_min(struct fixed32_32 lhs, + struct fixed32_32 rhs) +{ + return (lhs.value < rhs.value) ? lhs : rhs; +} + +static inline struct fixed32_32 dal_fixed32_32_max(struct fixed32_32 lhs, + struct fixed32_32 rhs) +{ + return (lhs.value > rhs.value) ? lhs : rhs; +} + +static inline bool dal_fixed32_32_gt(struct fixed32_32 lhs, struct fixed32_32 rhs) +{ + return lhs.value > rhs.value; +} + +static inline bool dal_fixed32_32_gt_int(struct fixed32_32 lhs, uint32_t rhs) +{ + return lhs.value > ((uint64_t)rhs<<32); +} + +static inline bool dal_fixed32_32_lt(struct fixed32_32 lhs, struct fixed32_32 rhs) +{ + return lhs.value < rhs.value; +} + +static inline bool dal_fixed32_32_lt_int(struct fixed32_32 lhs, uint32_t rhs) +{ + return lhs.value < ((uint64_t)rhs<<32); +} + +static inline bool dal_fixed32_32_le(struct fixed32_32 lhs, struct fixed32_32 rhs) +{ + return lhs.value <= rhs.value; +} + +static inline bool dal_fixed32_32_le_int(struct fixed32_32 lhs, uint32_t rhs) +{ + return lhs.value <= ((uint64_t)rhs<<32); +} + +static inline bool dal_fixed32_32_eq(struct fixed32_32 lhs, struct fixed32_32 rhs) +{ + return lhs.value == rhs.value; +} + uint32_t dal_fixed32_32_ceil(struct fixed32_32 value); -uint32_t dal_fixed32_32_floor(struct fixed32_32 value); +static inline uint32_t dal_fixed32_32_floor(struct fixed32_32 value) +{ + return value.value>>32; +} + uint32_t dal_fixed32_32_round(struct fixed32_32 value); #endif -- cgit From 204de25fd0685237a6382626e5862328a16ce15b Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 15:45:08 +1000 Subject: amdgpu/dc: inline a bunch of the fixed 31_32 helpers. This decreases code size by a few hundred bytes. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c | 122 ------------------- drivers/gpu/drm/amd/display/include/fixed31_32.h | 132 +++++++++++++++------ 2 files changed, 93 insertions(+), 161 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c b/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c index 546ed67c6f83..578691cf8725 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c +++ b/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c @@ -132,79 +132,6 @@ struct fixed31_32 dal_fixed31_32_from_int( return res; } -struct fixed31_32 dal_fixed31_32_neg( - struct fixed31_32 arg) -{ - struct fixed31_32 res; - - res.value = -arg.value; - - return res; -} - -struct fixed31_32 dal_fixed31_32_abs( - struct fixed31_32 arg) -{ - if (arg.value < 0) - return dal_fixed31_32_neg(arg); - else - return arg; -} - -bool dal_fixed31_32_lt( - struct fixed31_32 arg1, - struct fixed31_32 arg2) -{ - return arg1.value < arg2.value; -} - -bool dal_fixed31_32_le( - struct fixed31_32 arg1, - struct fixed31_32 arg2) -{ - return arg1.value <= arg2.value; -} - -bool dal_fixed31_32_eq( - struct fixed31_32 arg1, - struct fixed31_32 arg2) -{ - return arg1.value == arg2.value; -} - -struct fixed31_32 dal_fixed31_32_min( - struct fixed31_32 arg1, - struct fixed31_32 arg2) -{ - if (arg1.value <= arg2.value) - return arg1; - else - return arg2; -} - -struct fixed31_32 dal_fixed31_32_max( - struct fixed31_32 arg1, - struct fixed31_32 arg2) -{ - if (arg1.value <= arg2.value) - return arg2; - else - return arg1; -} - -struct fixed31_32 dal_fixed31_32_clamp( - struct fixed31_32 arg, - struct fixed31_32 min_value, - struct fixed31_32 max_value) -{ - if (dal_fixed31_32_le(arg, min_value)) - return min_value; - else if (dal_fixed31_32_le(max_value, arg)) - return max_value; - else - return arg; -} - struct fixed31_32 dal_fixed31_32_shl( struct fixed31_32 arg, uint8_t shift) @@ -219,19 +146,6 @@ struct fixed31_32 dal_fixed31_32_shl( return res; } -struct fixed31_32 dal_fixed31_32_shr( - struct fixed31_32 arg, - uint8_t shift) -{ - struct fixed31_32 res; - - ASSERT(shift < 64); - - res.value = arg.value >> shift; - - return res; -} - struct fixed31_32 dal_fixed31_32_add( struct fixed31_32 arg1, struct fixed31_32 arg2) @@ -246,24 +160,6 @@ struct fixed31_32 dal_fixed31_32_add( return res; } -struct fixed31_32 dal_fixed31_32_add_int( - struct fixed31_32 arg1, - int32_t arg2) -{ - return dal_fixed31_32_add( - arg1, - dal_fixed31_32_from_int(arg2)); -} - -struct fixed31_32 dal_fixed31_32_sub_int( - struct fixed31_32 arg1, - int32_t arg2) -{ - return dal_fixed31_32_sub( - arg1, - dal_fixed31_32_from_int(arg2)); -} - struct fixed31_32 dal_fixed31_32_sub( struct fixed31_32 arg1, struct fixed31_32 arg2) @@ -278,15 +174,6 @@ struct fixed31_32 dal_fixed31_32_sub( return res; } -struct fixed31_32 dal_fixed31_32_mul_int( - struct fixed31_32 arg1, - int32_t arg2) -{ - return dal_fixed31_32_mul( - arg1, - dal_fixed31_32_from_int(arg2)); -} - struct fixed31_32 dal_fixed31_32_mul( struct fixed31_32 arg1, struct fixed31_32 arg2) @@ -390,15 +277,6 @@ struct fixed31_32 dal_fixed31_32_div_int( dal_fixed31_32_from_int(arg2).value); } -struct fixed31_32 dal_fixed31_32_div( - struct fixed31_32 arg1, - struct fixed31_32 arg2) -{ - return dal_fixed31_32_from_fraction( - arg1.value, - arg2.value); -} - struct fixed31_32 dal_fixed31_32_recip( struct fixed31_32 arg) { diff --git a/drivers/gpu/drm/amd/display/include/fixed31_32.h b/drivers/gpu/drm/amd/display/include/fixed31_32.h index 5a4364dfd2f7..f0bc3c4afe02 100644 --- a/drivers/gpu/drm/amd/display/include/fixed31_32.h +++ b/drivers/gpu/drm/amd/display/include/fixed31_32.h @@ -90,15 +90,26 @@ struct fixed31_32 dal_fixed31_32_from_int( * @brief * result = -arg */ -struct fixed31_32 dal_fixed31_32_neg( - struct fixed31_32 arg); +static inline struct fixed31_32 dal_fixed31_32_neg(struct fixed31_32 arg) +{ + struct fixed31_32 res; + + res.value = -arg.value; + + return res; +} /* * @brief * result = abs(arg) := (arg >= 0) ? arg : -arg */ -struct fixed31_32 dal_fixed31_32_abs( - struct fixed31_32 arg); +static inline struct fixed31_32 dal_fixed31_32_abs(struct fixed31_32 arg) +{ + if (arg.value < 0) + return dal_fixed31_32_neg(arg); + else + return arg; +} /* * @brief @@ -109,41 +120,57 @@ struct fixed31_32 dal_fixed31_32_abs( * @brief * result = arg1 < arg2 */ -bool dal_fixed31_32_lt( - struct fixed31_32 arg1, - struct fixed31_32 arg2); +static inline bool dal_fixed31_32_lt(struct fixed31_32 arg1, + struct fixed31_32 arg2) +{ + return arg1.value < arg2.value; +} /* * @brief * result = arg1 <= arg2 */ -bool dal_fixed31_32_le( - struct fixed31_32 arg1, - struct fixed31_32 arg2); +static inline bool dal_fixed31_32_le(struct fixed31_32 arg1, + struct fixed31_32 arg2) +{ + return arg1.value <= arg2.value; +} /* * @brief * result = arg1 == arg2 */ -bool dal_fixed31_32_eq( - struct fixed31_32 arg1, - struct fixed31_32 arg2); +static inline bool dal_fixed31_32_eq(struct fixed31_32 arg1, + struct fixed31_32 arg2) +{ + return arg1.value == arg2.value; +} /* * @brief * result = min(arg1, arg2) := (arg1 <= arg2) ? arg1 : arg2 */ -struct fixed31_32 dal_fixed31_32_min( - struct fixed31_32 arg1, - struct fixed31_32 arg2); +static inline struct fixed31_32 dal_fixed31_32_min(struct fixed31_32 arg1, + struct fixed31_32 arg2) +{ + if (arg1.value <= arg2.value) + return arg1; + else + return arg2; +} /* * @brief * result = max(arg1, arg2) := (arg1 <= arg2) ? arg2 : arg1 */ -struct fixed31_32 dal_fixed31_32_max( - struct fixed31_32 arg1, - struct fixed31_32 arg2); +static inline struct fixed31_32 dal_fixed31_32_max(struct fixed31_32 arg1, + struct fixed31_32 arg2) +{ + if (arg1.value <= arg2.value) + return arg2; + else + return arg1; +} /* * @brief @@ -151,10 +178,18 @@ struct fixed31_32 dal_fixed31_32_max( * result = | arg, when min_value < arg < max_value * | max_value, when arg >= max_value */ -struct fixed31_32 dal_fixed31_32_clamp( +static inline struct fixed31_32 dal_fixed31_32_clamp( struct fixed31_32 arg, struct fixed31_32 min_value, - struct fixed31_32 max_value); + struct fixed31_32 max_value) +{ + if (dal_fixed31_32_le(arg, min_value)) + return min_value; + else if (dal_fixed31_32_le(max_value, arg)) + return max_value; + else + return arg; +} /* * @brief @@ -173,9 +208,14 @@ struct fixed31_32 dal_fixed31_32_shl( * @brief * result = arg >> shift */ -struct fixed31_32 dal_fixed31_32_shr( +static inline struct fixed31_32 dal_fixed31_32_shr( struct fixed31_32 arg, - uint8_t shift); + uint8_t shift) +{ + struct fixed31_32 res; + res.value = arg.value >> shift; + return res; +} /* * @brief @@ -194,25 +234,32 @@ struct fixed31_32 dal_fixed31_32_add( * @brief * result = arg1 + arg2 */ -struct fixed31_32 dal_fixed31_32_add_int( - struct fixed31_32 arg1, - int32_t arg2); +static inline struct fixed31_32 dal_fixed31_32_add_int(struct fixed31_32 arg1, + int32_t arg2) +{ + return dal_fixed31_32_add(arg1, + dal_fixed31_32_from_int(arg2)); +} /* * @brief * result = arg1 - arg2 */ -struct fixed31_32 dal_fixed31_32_sub_int( +struct fixed31_32 dal_fixed31_32_sub( struct fixed31_32 arg1, - int32_t arg2); + struct fixed31_32 arg2); /* * @brief * result = arg1 - arg2 */ -struct fixed31_32 dal_fixed31_32_sub( - struct fixed31_32 arg1, - struct fixed31_32 arg2); +static inline struct fixed31_32 dal_fixed31_32_sub_int(struct fixed31_32 arg1, + int32_t arg2) +{ + return dal_fixed31_32_sub(arg1, + dal_fixed31_32_from_int(arg2)); +} + /* * @brief @@ -223,17 +270,21 @@ struct fixed31_32 dal_fixed31_32_sub( * @brief * result = arg1 * arg2 */ -struct fixed31_32 dal_fixed31_32_mul_int( +struct fixed31_32 dal_fixed31_32_mul( struct fixed31_32 arg1, - int32_t arg2); + struct fixed31_32 arg2); + /* * @brief * result = arg1 * arg2 */ -struct fixed31_32 dal_fixed31_32_mul( - struct fixed31_32 arg1, - struct fixed31_32 arg2); +static inline struct fixed31_32 dal_fixed31_32_mul_int(struct fixed31_32 arg1, + int32_t arg2) +{ + return dal_fixed31_32_mul(arg1, + dal_fixed31_32_from_int(arg2)); +} /* * @brief @@ -254,9 +305,12 @@ struct fixed31_32 dal_fixed31_32_div_int( * @brief * result = arg1 / arg2 */ -struct fixed31_32 dal_fixed31_32_div( - struct fixed31_32 arg1, - struct fixed31_32 arg2); +static inline struct fixed31_32 dal_fixed31_32_div(struct fixed31_32 arg1, + struct fixed31_32 arg2) +{ + return dal_fixed31_32_from_fraction(arg1.value, + arg2.value); +} /* * @brief -- cgit From 736b4f153b62247d0f2e2bd1e9b04b7489edb596 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 17:13:22 +1000 Subject: amdgpu/dc: hide some unused aux/i2c payload apis. I've no idea if these are used on other platforms, but they aren't used outside this file here, so make them static. Drops 300 bytes. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c | 16 ++++++++-------- drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h | 10 ---------- 2 files changed, 8 insertions(+), 18 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c index 315160d5f0f7..d5294798b0a5 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c @@ -126,7 +126,7 @@ struct aux_payloads { struct vector payloads; }; -struct i2c_payloads *dal_ddc_i2c_payloads_create(struct dc_context *ctx, uint32_t count) +static struct i2c_payloads *dal_ddc_i2c_payloads_create(struct dc_context *ctx, uint32_t count) { struct i2c_payloads *payloads; @@ -144,17 +144,17 @@ struct i2c_payloads *dal_ddc_i2c_payloads_create(struct dc_context *ctx, uint32_ } -struct i2c_payload *dal_ddc_i2c_payloads_get(struct i2c_payloads *p) +static struct i2c_payload *dal_ddc_i2c_payloads_get(struct i2c_payloads *p) { return (struct i2c_payload *)p->payloads.container; } -uint32_t dal_ddc_i2c_payloads_get_count(struct i2c_payloads *p) +static uint32_t dal_ddc_i2c_payloads_get_count(struct i2c_payloads *p) { return p->payloads.count; } -void dal_ddc_i2c_payloads_destroy(struct i2c_payloads **p) +static void dal_ddc_i2c_payloads_destroy(struct i2c_payloads **p) { if (!p || !*p) return; @@ -164,7 +164,7 @@ void dal_ddc_i2c_payloads_destroy(struct i2c_payloads **p) } -struct aux_payloads *dal_ddc_aux_payloads_create(struct dc_context *ctx, uint32_t count) +static struct aux_payloads *dal_ddc_aux_payloads_create(struct dc_context *ctx, uint32_t count) { struct aux_payloads *payloads; @@ -181,17 +181,17 @@ struct aux_payloads *dal_ddc_aux_payloads_create(struct dc_context *ctx, uint32_ return NULL; } -struct aux_payload *dal_ddc_aux_payloads_get(struct aux_payloads *p) +static struct aux_payload *dal_ddc_aux_payloads_get(struct aux_payloads *p) { return (struct aux_payload *)p->payloads.container; } -uint32_t dal_ddc_aux_payloads_get_count(struct aux_payloads *p) +static uint32_t dal_ddc_aux_payloads_get_count(struct aux_payloads *p) { return p->payloads.count; } -void dal_ddc_aux_payloads_destroy(struct aux_payloads **p) +static void dal_ddc_aux_payloads_destroy(struct aux_payloads **p) { if (!p || !*p) return; diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h index af7ea5eaf185..0bf73b742f1f 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h @@ -57,16 +57,6 @@ struct dp_receiver_id_info; struct i2c_payloads; struct aux_payloads; -struct i2c_payloads *dal_ddc_i2c_payloads_create(struct dc_context *ctx, uint32_t count); -struct i2c_payload *dal_ddc_i2c_payloads_get(struct i2c_payloads *p); -uint32_t dal_ddc_i2c_payloads_get_count(struct i2c_payloads *p); -void dal_ddc_i2c_payloads_destroy(struct i2c_payloads **p); - -struct aux_payloads *dal_ddc_aux_payloads_create(struct dc_context *ctx, uint32_t count); -struct aux_payload *dal_ddc_aux_payloads_get(struct aux_payloads *p); -uint32_t dal_ddc_aux_payloads_get_count(struct aux_payloads *p); -void dal_ddc_aux_payloads_destroy(struct aux_payloads **p); - void dal_ddc_i2c_payloads_add( struct i2c_payloads *payloads, uint32_t address, -- cgit From 450619d328d0824fab649187019cbea3532f879c Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 17:13:23 +1000 Subject: amdgpu/dc: move some one line dp functions to inlines. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') 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 38ccc011004d..305ca0decfaa 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 @@ -1191,12 +1191,12 @@ struct dc_link_settings get_common_supported_link_settings ( return link_settings; } -bool reached_minimum_lane_count(enum dc_lane_count lane_count) +static inline bool reached_minimum_lane_count(enum dc_lane_count lane_count) { return lane_count <= LANE_COUNT_ONE; } -bool reached_minimum_link_rate(enum dc_link_rate link_rate) +static inline bool reached_minimum_link_rate(enum dc_link_rate link_rate) { return link_rate <= LINK_RATE_LOW; } -- cgit From 1fcd8c53b0c45c405433b5d78a5e2b2d858bd3af Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 17:13:24 +1000 Subject: amdgpu/dc: inline some of the bw_fixed code. This results in a ~4.5k code size reduction. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/bw_fixed.c | 93 -------------------- drivers/gpu/drm/amd/display/dc/inc/bw_fixed.h | 111 ++++++++++++++++++++---- 2 files changed, 96 insertions(+), 108 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/bw_fixed.c b/drivers/gpu/drm/amd/display/dc/calcs/bw_fixed.c index fbf2adcc5ff8..0de6fa1bb07d 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/bw_fixed.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/bw_fixed.c @@ -56,16 +56,6 @@ static uint64_t abs_i64(int64_t arg) return (uint64_t)(-arg); } -struct bw_fixed bw_min3(struct bw_fixed v1, struct bw_fixed v2, struct bw_fixed v3) -{ - return bw_min2(bw_min2(v1, v2), v3); -} - -struct bw_fixed bw_max3(struct bw_fixed v1, struct bw_fixed v2, struct bw_fixed v3) -{ - return bw_max2(bw_max2(v1, v2), v3); -} - struct bw_fixed bw_int_to_fixed(int64_t value) { struct bw_fixed res; @@ -133,16 +123,6 @@ struct bw_fixed bw_frc_to_fixed(int64_t numerator, int64_t denominator) return res; } -struct bw_fixed bw_min2(const struct bw_fixed arg1, const struct bw_fixed arg2) -{ - return (arg1.value <= arg2.value) ? arg1 : arg2; -} - -struct bw_fixed bw_max2(const struct bw_fixed arg1, const struct bw_fixed arg2) -{ - return (arg2.value <= arg1.value) ? arg1 : arg2; -} - struct bw_fixed bw_floor2( const struct bw_fixed arg, const struct bw_fixed significance) @@ -174,24 +154,6 @@ struct bw_fixed bw_ceil2( return result; } -struct bw_fixed bw_add(const struct bw_fixed arg1, const struct bw_fixed arg2) -{ - struct bw_fixed res; - - res.value = arg1.value + arg2.value; - - return res; -} - -struct bw_fixed bw_sub(const struct bw_fixed arg1, const struct bw_fixed arg2) -{ - struct bw_fixed res; - - res.value = arg1.value - arg2.value; - - return res; -} - struct bw_fixed bw_mul(const struct bw_fixed arg1, const struct bw_fixed arg2) { struct bw_fixed res; @@ -242,58 +204,3 @@ struct bw_fixed bw_mul(const struct bw_fixed arg1, const struct bw_fixed arg2) return res; } -struct bw_fixed bw_div(const struct bw_fixed arg1, const struct bw_fixed arg2) -{ - struct bw_fixed res = bw_frc_to_fixed(arg1.value, arg2.value); - return res; -} - -struct bw_fixed bw_mod(const struct bw_fixed arg1, const struct bw_fixed arg2) -{ - struct bw_fixed res; - div64_u64_rem(arg1.value, arg2.value, &res.value); - return res; -} -struct bw_fixed fixed31_32_to_bw_fixed(int64_t raw) -{ - struct bw_fixed result = { 0 }; - - if (raw < 0) { - raw = -raw; - result.value = -(raw >> (32 - BITS_PER_FRACTIONAL_PART)); - } else { - result.value = raw >> (32 - BITS_PER_FRACTIONAL_PART); - } - - return result; -} - -bool bw_equ(const struct bw_fixed arg1, const struct bw_fixed arg2) -{ - return arg1.value == arg2.value; -} - -bool bw_neq(const struct bw_fixed arg1, const struct bw_fixed arg2) -{ - return arg1.value != arg2.value; -} - -bool bw_leq(const struct bw_fixed arg1, const struct bw_fixed arg2) -{ - return arg1.value <= arg2.value; -} - -bool bw_meq(const struct bw_fixed arg1, const struct bw_fixed arg2) -{ - return arg1.value >= arg2.value; -} - -bool bw_ltn(const struct bw_fixed arg1, const struct bw_fixed arg2) -{ - return arg1.value < arg2.value; -} - -bool bw_mtn(const struct bw_fixed arg1, const struct bw_fixed arg2) -{ - return arg1.value > arg2.value; -} diff --git a/drivers/gpu/drm/amd/display/dc/inc/bw_fixed.h b/drivers/gpu/drm/amd/display/dc/inc/bw_fixed.h index b31d07a57c31..4477e6208998 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/bw_fixed.h +++ b/drivers/gpu/drm/amd/display/dc/inc/bw_fixed.h @@ -30,9 +30,31 @@ struct bw_fixed { int64_t value; }; -struct bw_fixed bw_min3(struct bw_fixed v1, struct bw_fixed v2, struct bw_fixed v3); +static inline struct bw_fixed bw_min2(const struct bw_fixed arg1, + const struct bw_fixed arg2) +{ + return (arg1.value <= arg2.value) ? arg1 : arg2; +} -struct bw_fixed bw_max3(struct bw_fixed v1, struct bw_fixed v2, struct bw_fixed v3); +static inline struct bw_fixed bw_max2(const struct bw_fixed arg1, + const struct bw_fixed arg2) +{ + return (arg2.value <= arg1.value) ? arg1 : arg2; +} + +static inline struct bw_fixed bw_min3(struct bw_fixed v1, + struct bw_fixed v2, + struct bw_fixed v3) +{ + return bw_min2(bw_min2(v1, v2), v3); +} + +static inline struct bw_fixed bw_max3(struct bw_fixed v1, + struct bw_fixed v2, + struct bw_fixed v3) +{ + return bw_max2(bw_max2(v1, v2), v3); +} struct bw_fixed bw_int_to_fixed(int64_t value); @@ -40,24 +62,83 @@ int32_t bw_fixed_to_int(struct bw_fixed value); struct bw_fixed bw_frc_to_fixed(int64_t num, int64_t denum); -struct bw_fixed fixed31_32_to_bw_fixed(int64_t raw); +static inline struct bw_fixed fixed31_32_to_bw_fixed(int64_t raw) +{ + struct bw_fixed result = { 0 }; + + if (raw < 0) { + raw = -raw; + result.value = -(raw >> (32 - BW_FIXED_BITS_PER_FRACTIONAL_PART)); + } else { + result.value = raw >> (32 - BW_FIXED_BITS_PER_FRACTIONAL_PART); + } + + return result; +} + +static inline struct bw_fixed bw_add(const struct bw_fixed arg1, + const struct bw_fixed arg2) +{ + struct bw_fixed res; + + res.value = arg1.value + arg2.value; + + return res; +} + +static inline struct bw_fixed bw_sub(const struct bw_fixed arg1, const struct bw_fixed arg2) +{ + struct bw_fixed res; + + res.value = arg1.value - arg2.value; + + return res; +} -struct bw_fixed bw_add(const struct bw_fixed arg1, const struct bw_fixed arg2); -struct bw_fixed bw_sub(const struct bw_fixed arg1, const struct bw_fixed arg2); struct bw_fixed bw_mul(const struct bw_fixed arg1, const struct bw_fixed arg2); -struct bw_fixed bw_div(const struct bw_fixed arg1, const struct bw_fixed arg2); -struct bw_fixed bw_mod(const struct bw_fixed arg1, const struct bw_fixed arg2); +static inline struct bw_fixed bw_div(const struct bw_fixed arg1, const struct bw_fixed arg2) +{ + return bw_frc_to_fixed(arg1.value, arg2.value); +} + +static inline struct bw_fixed bw_mod(const struct bw_fixed arg1, const struct bw_fixed arg2) +{ + struct bw_fixed res; + div64_u64_rem(arg1.value, arg2.value, &res.value); + return res; +} -struct bw_fixed bw_min2(const struct bw_fixed arg1, const struct bw_fixed arg2); -struct bw_fixed bw_max2(const struct bw_fixed arg1, const struct bw_fixed arg2); struct bw_fixed bw_floor2(const struct bw_fixed arg, const struct bw_fixed significance); struct bw_fixed bw_ceil2(const struct bw_fixed arg, const struct bw_fixed significance); -bool bw_equ(const struct bw_fixed arg1, const struct bw_fixed arg2); -bool bw_neq(const struct bw_fixed arg1, const struct bw_fixed arg2); -bool bw_leq(const struct bw_fixed arg1, const struct bw_fixed arg2); -bool bw_meq(const struct bw_fixed arg1, const struct bw_fixed arg2); -bool bw_ltn(const struct bw_fixed arg1, const struct bw_fixed arg2); -bool bw_mtn(const struct bw_fixed arg1, const struct bw_fixed arg2); +static inline bool bw_equ(const struct bw_fixed arg1, const struct bw_fixed arg2) +{ + return arg1.value == arg2.value; +} + +static inline bool bw_neq(const struct bw_fixed arg1, const struct bw_fixed arg2) +{ + return arg1.value != arg2.value; +} + +static inline bool bw_leq(const struct bw_fixed arg1, const struct bw_fixed arg2) +{ + return arg1.value <= arg2.value; +} + +static inline bool bw_meq(const struct bw_fixed arg1, const struct bw_fixed arg2) +{ + return arg1.value >= arg2.value; +} + +static inline bool bw_ltn(const struct bw_fixed arg1, const struct bw_fixed arg2) +{ + return arg1.value < arg2.value; +} + +static inline bool bw_mtn(const struct bw_fixed arg1, const struct bw_fixed arg2) +{ + return arg1.value > arg2.value; +} #endif //BW_FIXED_H_ -- cgit From dfd1e5ce673b8b2557d622dc99735e2d7ad5ba5b Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 17:13:25 +1000 Subject: amdgpu/dc: allow inlining constant int to fixed a lot better. This uses two things that might be Linux specific, __builtin_constant_p (might be gcc) and BUILD_BUG_ON. (maybe other dm's can have something similiar). This saves 4k in the bw calcs code. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/bw_fixed.c | 37 ++++++++----------------- drivers/gpu/drm/amd/display/dc/inc/bw_fixed.h | 26 +++++++++++++++-- 2 files changed, 35 insertions(+), 28 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/bw_fixed.c b/drivers/gpu/drm/amd/display/dc/calcs/bw_fixed.c index 0de6fa1bb07d..6ca288fb5fb9 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/bw_fixed.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/bw_fixed.c @@ -25,13 +25,6 @@ #include "dm_services.h" #include "bw_fixed.h" -#define BITS_PER_FRACTIONAL_PART 24 - -#define MIN_I32 \ - (int64_t)(-(1LL << (63 - BITS_PER_FRACTIONAL_PART))) - -#define MAX_I32 \ - (int64_t)((1ULL << (63 - BITS_PER_FRACTIONAL_PART)) - 1) #define MIN_I64 \ (int64_t)(-(1LL << 63)) @@ -40,10 +33,7 @@ (int64_t)((1ULL << 63) - 1) #define FRACTIONAL_PART_MASK \ - ((1ULL << BITS_PER_FRACTIONAL_PART) - 1) - -#define GET_INTEGER_PART(x) \ - ((x) >> BITS_PER_FRACTIONAL_PART) + ((1ULL << BW_FIXED_BITS_PER_FRACTIONAL_PART) - 1) #define GET_FRACTIONAL_PART(x) \ (FRACTIONAL_PART_MASK & (x)) @@ -56,19 +46,14 @@ static uint64_t abs_i64(int64_t arg) return (uint64_t)(-arg); } -struct bw_fixed bw_int_to_fixed(int64_t value) +struct bw_fixed bw_int_to_fixed_nonconst(int64_t value) { struct bw_fixed res; - ASSERT(value < MAX_I32 && value > MIN_I32); - res.value = value << BITS_PER_FRACTIONAL_PART; + ASSERT(value < BW_FIXED_MAX_I32 && value > BW_FIXED_MIN_I32); + res.value = value << BW_FIXED_BITS_PER_FRACTIONAL_PART; return res; } -int32_t bw_fixed_to_int(struct bw_fixed value) -{ - return GET_INTEGER_PART(value.value); -} - struct bw_fixed bw_frc_to_fixed(int64_t numerator, int64_t denominator) { struct bw_fixed res; @@ -87,11 +72,11 @@ struct bw_fixed bw_frc_to_fixed(int64_t numerator, int64_t denominator) arg2_value = abs_i64(denominator); res_value = div64_u64_rem(arg1_value, arg2_value, &remainder); - ASSERT(res_value <= MAX_I32); + ASSERT(res_value <= BW_FIXED_MAX_I32); /* determine fractional part */ { - uint32_t i = BITS_PER_FRACTIONAL_PART; + uint32_t i = BW_FIXED_BITS_PER_FRACTIONAL_PART; do { @@ -164,8 +149,8 @@ struct bw_fixed bw_mul(const struct bw_fixed arg1, const struct bw_fixed arg2) uint64_t arg1_value = abs_i64(arg1.value); uint64_t arg2_value = abs_i64(arg2.value); - uint64_t arg1_int = GET_INTEGER_PART(arg1_value); - uint64_t arg2_int = GET_INTEGER_PART(arg2_value); + uint64_t arg1_int = BW_FIXED_GET_INTEGER_PART(arg1_value); + uint64_t arg2_int = BW_FIXED_GET_INTEGER_PART(arg2_value); uint64_t arg1_fra = GET_FRACTIONAL_PART(arg1_value); uint64_t arg2_fra = GET_FRACTIONAL_PART(arg2_value); @@ -174,9 +159,9 @@ struct bw_fixed bw_mul(const struct bw_fixed arg1, const struct bw_fixed arg2) res.value = arg1_int * arg2_int; - ASSERT(res.value <= MAX_I32); + ASSERT(res.value <= BW_FIXED_MAX_I32); - res.value <<= BITS_PER_FRACTIONAL_PART; + res.value <<= BW_FIXED_BITS_PER_FRACTIONAL_PART; tmp = arg1_int * arg2_fra; @@ -192,7 +177,7 @@ struct bw_fixed bw_mul(const struct bw_fixed arg1, const struct bw_fixed arg2) tmp = arg1_fra * arg2_fra; - tmp = (tmp >> BITS_PER_FRACTIONAL_PART) + + tmp = (tmp >> BW_FIXED_BITS_PER_FRACTIONAL_PART) + (tmp >= (uint64_t)(bw_frc_to_fixed(1, 2).value)); ASSERT(tmp <= (uint64_t)(MAX_I64 - res.value)); diff --git a/drivers/gpu/drm/amd/display/dc/inc/bw_fixed.h b/drivers/gpu/drm/amd/display/dc/inc/bw_fixed.h index 4477e6208998..39ee8eba3c31 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/bw_fixed.h +++ b/drivers/gpu/drm/amd/display/dc/inc/bw_fixed.h @@ -26,10 +26,19 @@ #ifndef BW_FIXED_H_ #define BW_FIXED_H_ +#define BW_FIXED_BITS_PER_FRACTIONAL_PART 24 + +#define BW_FIXED_GET_INTEGER_PART(x) ((x) >> BW_FIXED_BITS_PER_FRACTIONAL_PART) struct bw_fixed { int64_t value; }; +#define BW_FIXED_MIN_I32 \ + (int64_t)(-(1LL << (63 - BW_FIXED_BITS_PER_FRACTIONAL_PART))) + +#define BW_FIXED_MAX_I32 \ + (int64_t)((1ULL << (63 - BW_FIXED_BITS_PER_FRACTIONAL_PART)) - 1) + static inline struct bw_fixed bw_min2(const struct bw_fixed arg1, const struct bw_fixed arg2) { @@ -56,9 +65,22 @@ static inline struct bw_fixed bw_max3(struct bw_fixed v1, return bw_max2(bw_max2(v1, v2), v3); } -struct bw_fixed bw_int_to_fixed(int64_t value); +struct bw_fixed bw_int_to_fixed_nonconst(int64_t value); +static inline struct bw_fixed bw_int_to_fixed(int64_t value) +{ + if (__builtin_constant_p(value)) { + struct bw_fixed res; + BUILD_BUG_ON(value > BW_FIXED_MAX_I32 || value < BW_FIXED_MIN_I32); + res.value = value << BW_FIXED_BITS_PER_FRACTIONAL_PART; + return res; + } else + return bw_int_to_fixed_nonconst(value); +} -int32_t bw_fixed_to_int(struct bw_fixed value); +static inline int32_t bw_fixed_to_int(struct bw_fixed value) +{ + return BW_FIXED_GET_INTEGER_PART(value.value); +} struct bw_fixed bw_frc_to_fixed(int64_t num, int64_t denum); -- cgit From c233e91b0f3f7c9abc80eae491fa6507a24a8a32 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 17:13:26 +1000 Subject: amdgpu/dc: use the builtin constant p trick on the 31/32 fixed point. This only gets us 100 bytes, but may as well be consistent. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c | 22 ++++++++++------------ drivers/gpu/drm/amd/display/include/fixed31_32.h | 15 +++++++++++++-- 2 files changed, 23 insertions(+), 14 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c b/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c index 578691cf8725..1764a33c8350 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c +++ b/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c @@ -54,14 +54,12 @@ static inline uint64_t complete_integer_division_u64( return result; } -#define BITS_PER_FRACTIONAL_PART \ - 32 #define FRACTIONAL_PART_MASK \ - ((1ULL << BITS_PER_FRACTIONAL_PART) - 1) + ((1ULL << FIXED31_32_BITS_PER_FRACTIONAL_PART) - 1) #define GET_INTEGER_PART(x) \ - ((x) >> BITS_PER_FRACTIONAL_PART) + ((x) >> FIXED31_32_BITS_PER_FRACTIONAL_PART) #define GET_FRACTIONAL_PART(x) \ (FRACTIONAL_PART_MASK & (x)) @@ -89,7 +87,7 @@ struct fixed31_32 dal_fixed31_32_from_fraction( /* determine fractional part */ { - uint32_t i = BITS_PER_FRACTIONAL_PART; + uint32_t i = FIXED31_32_BITS_PER_FRACTIONAL_PART; do { remainder <<= 1; @@ -120,14 +118,14 @@ struct fixed31_32 dal_fixed31_32_from_fraction( return res; } -struct fixed31_32 dal_fixed31_32_from_int( +struct fixed31_32 dal_fixed31_32_from_int_nonconst( int64_t arg) { struct fixed31_32 res; ASSERT((LONG_MIN <= arg) && (arg <= LONG_MAX)); - res.value = arg << BITS_PER_FRACTIONAL_PART; + res.value = arg << FIXED31_32_BITS_PER_FRACTIONAL_PART; return res; } @@ -198,7 +196,7 @@ struct fixed31_32 dal_fixed31_32_mul( ASSERT(res.value <= LONG_MAX); - res.value <<= BITS_PER_FRACTIONAL_PART; + res.value <<= FIXED31_32_BITS_PER_FRACTIONAL_PART; tmp = arg1_int * arg2_fra; @@ -214,7 +212,7 @@ struct fixed31_32 dal_fixed31_32_mul( tmp = arg1_fra * arg2_fra; - tmp = (tmp >> BITS_PER_FRACTIONAL_PART) + + tmp = (tmp >> FIXED31_32_BITS_PER_FRACTIONAL_PART) + (tmp >= (uint64_t)dal_fixed31_32_half.value); ASSERT(tmp <= (uint64_t)(LLONG_MAX - res.value)); @@ -244,7 +242,7 @@ struct fixed31_32 dal_fixed31_32_sqr( ASSERT(res.value <= LONG_MAX); - res.value <<= BITS_PER_FRACTIONAL_PART; + res.value <<= FIXED31_32_BITS_PER_FRACTIONAL_PART; tmp = arg_int * arg_fra; @@ -258,7 +256,7 @@ struct fixed31_32 dal_fixed31_32_sqr( tmp = arg_fra * arg_fra; - tmp = (tmp >> BITS_PER_FRACTIONAL_PART) + + tmp = (tmp >> FIXED31_32_BITS_PER_FRACTIONAL_PART) + (tmp >= (uint64_t)dal_fixed31_32_half.value); ASSERT(tmp <= (uint64_t)(LLONG_MAX - res.value)); @@ -560,7 +558,7 @@ static inline uint32_t ux_dy( /* 4. make space for fractional part to be filled in after integer */ result <<= fractional_bits; /* 5. shrink fixed point fractional part to of fractional_bits width*/ - fractional_part >>= BITS_PER_FRACTIONAL_PART - fractional_bits; + fractional_part >>= FIXED31_32_BITS_PER_FRACTIONAL_PART - fractional_bits; /* 6. merge the result */ return result | fractional_part; } diff --git a/drivers/gpu/drm/amd/display/include/fixed31_32.h b/drivers/gpu/drm/amd/display/include/fixed31_32.h index f0bc3c4afe02..2c9e2231ef06 100644 --- a/drivers/gpu/drm/amd/display/include/fixed31_32.h +++ b/drivers/gpu/drm/amd/display/include/fixed31_32.h @@ -28,6 +28,8 @@ #include "os_types.h" +#define FIXED31_32_BITS_PER_FRACTIONAL_PART 32 + /* * @brief * Arithmetic operations on real numbers @@ -78,8 +80,17 @@ struct fixed31_32 dal_fixed31_32_from_fraction( * @brief * result = arg */ -struct fixed31_32 dal_fixed31_32_from_int( - int64_t arg); +struct fixed31_32 dal_fixed31_32_from_int_nonconst(int64_t arg); +static inline struct fixed31_32 dal_fixed31_32_from_int(int64_t arg) +{ + if (__builtin_constant_p(arg)) { + struct fixed31_32 res; + BUILD_BUG_ON((LONG_MIN > arg) || (arg > LONG_MAX)); + res.value = arg << FIXED31_32_BITS_PER_FRACTIONAL_PART; + return res; + } else + return dal_fixed31_32_from_int_nonconst(arg); +} /* * @brief -- cgit From bd6d15769e6dcd22c57224b67376e1c6fb44b04f Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 17:13:27 +1000 Subject: amdgpu/dc: inline fixed31_32 div_int Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c | 9 --------- drivers/gpu/drm/amd/display/include/fixed31_32.h | 9 ++++++--- 2 files changed, 6 insertions(+), 12 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c b/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c index 1764a33c8350..26936892c6f5 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c +++ b/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c @@ -266,15 +266,6 @@ struct fixed31_32 dal_fixed31_32_sqr( return res; } -struct fixed31_32 dal_fixed31_32_div_int( - struct fixed31_32 arg1, - int64_t arg2) -{ - return dal_fixed31_32_from_fraction( - arg1.value, - dal_fixed31_32_from_int(arg2).value); -} - struct fixed31_32 dal_fixed31_32_recip( struct fixed31_32 arg) { diff --git a/drivers/gpu/drm/amd/display/include/fixed31_32.h b/drivers/gpu/drm/amd/display/include/fixed31_32.h index 2c9e2231ef06..3248f699daf2 100644 --- a/drivers/gpu/drm/amd/display/include/fixed31_32.h +++ b/drivers/gpu/drm/amd/display/include/fixed31_32.h @@ -308,9 +308,12 @@ struct fixed31_32 dal_fixed31_32_sqr( * @brief * result = arg1 / arg2 */ -struct fixed31_32 dal_fixed31_32_div_int( - struct fixed31_32 arg1, - int64_t arg2); +static inline struct fixed31_32 dal_fixed31_32_div_int(struct fixed31_32 arg1, + int64_t arg2) +{ + return dal_fixed31_32_from_fraction(arg1.value, + dal_fixed31_32_from_int(arg2).value); +} /* * @brief -- cgit From 69e3fdaabe185ecbf7413eb53cd43ca407d6fbba Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 17:13:28 +1000 Subject: amdgpu/dc: inline all the signal_types code. This is worth 300 bytes, and one less source file. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/basics/Makefile | 2 +- .../gpu/drm/amd/display/dc/basics/signal_types.c | 80 ---------------------- drivers/gpu/drm/amd/display/include/signal_types.h | 59 +++++++++++++--- 3 files changed, 52 insertions(+), 89 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/dc/basics/signal_types.c (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/basics/Makefile b/drivers/gpu/drm/amd/display/dc/basics/Makefile index 065816209da1..43c5ccdeeb72 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/Makefile +++ b/drivers/gpu/drm/amd/display/dc/basics/Makefile @@ -4,7 +4,7 @@ # subcomponents. BASICS = conversion.o fixpt31_32.o fixpt32_32.o grph_object_id.o \ - logger.o log_helpers.o signal_types.o vector.o + logger.o log_helpers.o vector.o AMD_DAL_BASICS = $(addprefix $(AMDDALPATH)/dc/basics/,$(BASICS)) diff --git a/drivers/gpu/drm/amd/display/dc/basics/signal_types.c b/drivers/gpu/drm/amd/display/dc/basics/signal_types.c deleted file mode 100644 index 534c803e7091..000000000000 --- a/drivers/gpu/drm/amd/display/dc/basics/signal_types.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" -#include "include/signal_types.h" - -bool dc_is_hdmi_signal(enum signal_type signal) -{ - return (signal == SIGNAL_TYPE_HDMI_TYPE_A); -} - -bool dc_is_dp_sst_signal(enum signal_type signal) -{ - return (signal == SIGNAL_TYPE_DISPLAY_PORT || - signal == SIGNAL_TYPE_EDP); -} - -bool dc_is_dp_signal(enum signal_type signal) -{ - return (signal == SIGNAL_TYPE_DISPLAY_PORT || - signal == SIGNAL_TYPE_EDP || - signal == SIGNAL_TYPE_DISPLAY_PORT_MST); -} - -bool dc_is_embedded_signal(enum signal_type signal) -{ - return (signal == SIGNAL_TYPE_EDP || signal == SIGNAL_TYPE_LVDS); -} - -bool dc_is_dvi_signal(enum signal_type signal) -{ - switch (signal) { - case SIGNAL_TYPE_DVI_SINGLE_LINK: - case SIGNAL_TYPE_DVI_DUAL_LINK: - return true; - break; - default: - return false; - } -} - -bool dc_is_dvi_single_link_signal(enum signal_type signal) -{ - return (signal == SIGNAL_TYPE_DVI_SINGLE_LINK); -} - -bool dc_is_dual_link_signal(enum signal_type signal) -{ - return (signal == SIGNAL_TYPE_DVI_DUAL_LINK); -} - -bool dc_is_audio_capable_signal(enum signal_type signal) -{ - return (signal == SIGNAL_TYPE_DISPLAY_PORT || - signal == SIGNAL_TYPE_DISPLAY_PORT_MST || - dc_is_hdmi_signal(signal)); -} - diff --git a/drivers/gpu/drm/amd/display/include/signal_types.h b/drivers/gpu/drm/amd/display/include/signal_types.h index 1a2ca53c68cd..b5ebde642207 100644 --- a/drivers/gpu/drm/amd/display/include/signal_types.h +++ b/drivers/gpu/drm/amd/display/include/signal_types.h @@ -40,13 +40,56 @@ enum signal_type { }; /* help functions for signal types manipulation */ -bool dc_is_hdmi_signal(enum signal_type signal); -bool dc_is_dp_sst_signal(enum signal_type signal); -bool dc_is_dp_signal(enum signal_type signal); -bool dc_is_embedded_signal(enum signal_type signal); -bool dc_is_dvi_signal(enum signal_type signal); -bool dc_is_dvi_single_link_signal(enum signal_type signal); -bool dc_is_dual_link_signal(enum signal_type signal); -bool dc_is_audio_capable_signal(enum signal_type signal); +static inline bool dc_is_hdmi_signal(enum signal_type signal) +{ + return (signal == SIGNAL_TYPE_HDMI_TYPE_A); +} + +static inline bool dc_is_dp_sst_signal(enum signal_type signal) +{ + return (signal == SIGNAL_TYPE_DISPLAY_PORT || + signal == SIGNAL_TYPE_EDP); +} + +static inline bool dc_is_dp_signal(enum signal_type signal) +{ + return (signal == SIGNAL_TYPE_DISPLAY_PORT || + signal == SIGNAL_TYPE_EDP || + signal == SIGNAL_TYPE_DISPLAY_PORT_MST); +} + +static inline bool dc_is_embedded_signal(enum signal_type signal) +{ + return (signal == SIGNAL_TYPE_EDP || signal == SIGNAL_TYPE_LVDS); +} + +static inline bool dc_is_dvi_signal(enum signal_type signal) +{ + switch (signal) { + case SIGNAL_TYPE_DVI_SINGLE_LINK: + case SIGNAL_TYPE_DVI_DUAL_LINK: + return true; + break; + default: + return false; + } +} + +static inline bool dc_is_dvi_single_link_signal(enum signal_type signal) +{ + return (signal == SIGNAL_TYPE_DVI_SINGLE_LINK); +} + +static inline bool dc_is_dual_link_signal(enum signal_type signal) +{ + return (signal == SIGNAL_TYPE_DVI_DUAL_LINK); +} + +static inline bool dc_is_audio_capable_signal(enum signal_type signal) +{ + return (signal == SIGNAL_TYPE_DISPLAY_PORT || + signal == SIGNAL_TYPE_DISPLAY_PORT_MST || + dc_is_hdmi_signal(signal)); +} #endif -- cgit From 04e212926f0d1213bc1ff1f8ab4050878699977d Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 17:13:29 +1000 Subject: amdgpu/dc: set some of the link dp code to static. These aren't currently used outside this file. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 18 +++++++++++++----- drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h | 8 -------- 2 files changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers/gpu') 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 305ca0decfaa..888d268e9622 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 @@ -32,6 +32,14 @@ enum { LINK_TRAINING_MAX_CR_RETRY = 100 }; +static bool decide_fallback_link_setting( + struct dc_link_settings initial_link_settings, + struct dc_link_settings *current_link_setting, + enum link_training_result training_result); +static struct dc_link_settings get_common_supported_link_settings ( + struct dc_link_settings link_setting_a, + struct dc_link_settings link_setting_b); + static void wait_for_training_aux_rd_interval( struct dc_link *link, uint32_t default_wait_in_micro_secs) @@ -1150,7 +1158,7 @@ bool dp_hbr_verify_link_cap( return success; } -struct dc_link_settings get_common_supported_link_settings ( +static struct dc_link_settings get_common_supported_link_settings ( struct dc_link_settings link_setting_a, struct dc_link_settings link_setting_b) { @@ -1215,7 +1223,7 @@ enum dc_lane_count reduce_lane_count(enum dc_lane_count lane_count) } } -enum dc_link_rate reduce_link_rate(enum dc_link_rate link_rate) +static enum dc_link_rate reduce_link_rate(enum dc_link_rate link_rate) { switch (link_rate) { case LINK_RATE_HIGH3: @@ -1231,7 +1239,7 @@ enum dc_link_rate reduce_link_rate(enum dc_link_rate link_rate) } } -enum dc_lane_count increase_lane_count(enum dc_lane_count lane_count) +static enum dc_lane_count increase_lane_count(enum dc_lane_count lane_count) { switch (lane_count) { case LANE_COUNT_ONE: @@ -1243,7 +1251,7 @@ enum dc_lane_count increase_lane_count(enum dc_lane_count lane_count) } } -enum dc_link_rate increase_link_rate(enum dc_link_rate link_rate) +static enum dc_link_rate increase_link_rate(enum dc_link_rate link_rate) { switch (link_rate) { case LINK_RATE_LOW: @@ -1265,7 +1273,7 @@ enum dc_link_rate increase_link_rate(enum dc_link_rate link_rate) * false - has reached minimum setting * and no further fallback could be done */ -bool decide_fallback_link_setting( +static bool decide_fallback_link_setting( struct dc_link_settings initial_link_settings, struct dc_link_settings *current_link_setting, enum link_training_result training_result) diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h index 7168dcc70ae7..616c73e2b0bd 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h @@ -37,14 +37,6 @@ bool dp_hbr_verify_link_cap( struct dc_link *link, struct dc_link_settings *known_limit_link_setting); -bool decide_fallback_link_setting(struct dc_link_settings link_setting_init, - struct dc_link_settings *link_setting_current, - enum link_training_result training_result); - -struct dc_link_settings get_common_supported_link_settings ( - struct dc_link_settings link_setting_a, - struct dc_link_settings link_setting_b); - bool dp_validate_mode_timing( struct dc_link *link, const struct dc_crtc_timing *timing); -- cgit From 2a206cc20a37b0a7a31179b32d1281ead9c56038 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 17:13:30 +1000 Subject: amdgpu/dc: rename bios get_image symbol to something more searchable. This just makes it easier to find. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/bios/bios_parser.c | 6 +++--- drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c | 2 +- drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.c | 2 +- drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.h | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c index f6828f43eac6..2e003b5c8d08 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c @@ -412,7 +412,7 @@ static enum bp_result bios_parser_get_voltage_ddc_info(struct dc_bios *dcb, if (!DATA_TABLES(VoltageObjectInfo)) return result; - voltage_info_address = get_image(&bp->base, DATA_TABLES(VoltageObjectInfo), sizeof(ATOM_COMMON_TABLE_HEADER)); + voltage_info_address = bios_get_image(&bp->base, DATA_TABLES(VoltageObjectInfo), sizeof(ATOM_COMMON_TABLE_HEADER)); header = (ATOM_COMMON_TABLE_HEADER *) voltage_info_address; @@ -2328,7 +2328,7 @@ static uint32_t get_dest_obj_list(struct bios_parser *bp, return 0; offset += sizeof(uint8_t); - *id_list = (uint16_t *)get_image(&bp->base, offset, *number * sizeof(uint16_t)); + *id_list = (uint16_t *)bios_get_image(&bp->base, offset, *number * sizeof(uint16_t)); if (!*id_list) return 0; @@ -2355,7 +2355,7 @@ static uint32_t get_src_obj_list(struct bios_parser *bp, ATOM_OBJECT *object, return 0; offset += sizeof(uint8_t); - *id_list = (uint16_t *)get_image(&bp->base, offset, *number * sizeof(uint16_t)); + *id_list = (uint16_t *)bios_get_image(&bp->base, offset, *number * sizeof(uint16_t)); if (!*id_list) return 0; diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c index 852bb0d2eb8d..0c623b314577 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -535,7 +535,7 @@ static enum bp_result bios_parser_get_voltage_ddc_info(struct dc_bios *dcb, if (!DATA_TABLES(voltageobject_info)) return result; - voltage_info_address = get_image(&bp->base, + voltage_info_address = bios_get_image(&bp->base, DATA_TABLES(voltageobject_info), sizeof(struct atom_common_table_header)); diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.c index 8e56d2f25dea..5c9e5108c32c 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.c @@ -33,7 +33,7 @@ #include "command_table.h" #include "bios_parser_types_internal.h" -uint8_t *get_image(struct dc_bios *bp, +uint8_t *bios_get_image(struct dc_bios *bp, uint32_t offset, uint32_t size) { diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.h b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.h index a8fbb82b8c8e..c0047efeb006 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.h +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.h @@ -28,13 +28,13 @@ struct bios_parser; -uint8_t *get_image(struct dc_bios *bp, uint32_t offset, +uint8_t *bios_get_image(struct dc_bios *bp, uint32_t offset, uint32_t size); bool bios_is_accelerated_mode(struct dc_bios *bios); void bios_set_scratch_acc_mode_change(struct dc_bios *bios); void bios_set_scratch_critical_state(struct dc_bios *bios, bool state); -#define GET_IMAGE(type, offset) ((type *) get_image(&bp->base, offset, sizeof(type))) +#define GET_IMAGE(type, offset) ((type *) bios_get_image(&bp->base, offset, sizeof(type))) #endif -- cgit From d8c893b44b2199f5935fe8667708253c38353782 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 17:13:31 +1000 Subject: amdgpu/dc: inline dml_round_to_multiple turns out to be a win to inline this. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c | 19 ------------------- drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h | 2 -- drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h | 19 +++++++++++++++++++ 3 files changed, 19 insertions(+), 21 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c index 7c0eb52b91b8..df2d5099b90e 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c @@ -39,23 +39,4 @@ double dml_round(double a) return floor; } -unsigned int dml_round_to_multiple( - unsigned int num, - unsigned int multiple, - bool up) -{ - unsigned int remainder; - - if (multiple == 0) - return num; - - remainder = num % multiple; - if (remainder == 0) - return num; - - if (up) - return (num + multiple - remainder); - else - return (num - remainder); -} diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h index a2da3da5ef8f..81c53d879a16 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h @@ -33,7 +33,5 @@ #define DTRACE(str, ...) dm_logger_write(mode_lib->logger, LOG_DML, str, ##__VA_ARGS__); double dml_round(double a); -unsigned int dml_round_to_multiple( - unsigned int num, unsigned int multiple, bool up); #endif /* __DC_COMMON_DEFS_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h b/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h index 1c6c631daad4..a91b4a6c6154 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h @@ -58,4 +58,23 @@ static inline double dml_log(double x, double base) return (double) dcn_bw_log(x, base); } +static inline unsigned int dml_round_to_multiple(unsigned int num, + unsigned int multiple, + bool up) +{ + unsigned int remainder; + + if (multiple == 0) + return num; + + remainder = num % multiple; + + if (remainder == 0) + return num; + + if (up) + return (num + multiple - remainder); + else + return (num - remainder); +} #endif -- cgit From 48aa3ddfd535a8e80b1b46da8a13920d9de8e5c5 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 3 Oct 2017 12:36:54 +1000 Subject: amdgpu/dc: inline dal grph object id functions. This is worth 400 bytes. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/basics/grph_object_id.c | 61 +----------------- .../gpu/drm/amd/display/include/grph_object_id.h | 72 +++++++++++++++++----- 2 files changed, 56 insertions(+), 77 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/basics/grph_object_id.c b/drivers/gpu/drm/amd/display/dc/basics/grph_object_id.c index 9c80847d03a9..147822545252 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/grph_object_id.c +++ b/drivers/gpu/drm/amd/display/dc/basics/grph_object_id.c @@ -26,7 +26,7 @@ #include "dm_services.h" #include "include/grph_object_id.h" -bool dal_graphics_object_id_is_valid(struct graphics_object_id id) +static bool dal_graphics_object_id_is_valid(struct graphics_object_id id) { bool rc = true; @@ -72,63 +72,4 @@ bool dal_graphics_object_id_is_equal( return false; } -/* Based on internal data members memory layout */ -uint32_t dal_graphics_object_id_to_uint(struct graphics_object_id id) -{ - uint32_t object_id = 0; - - object_id = id.id + (id.enum_id << 0x8) + (id.type << 0xc); - return object_id; -} - -/* - * ******* get specific ID - internal safe cast into specific type ******* - */ - -enum controller_id dal_graphics_object_id_get_controller_id( - struct graphics_object_id id) -{ - if (id.type == OBJECT_TYPE_CONTROLLER) - return id.id; - return CONTROLLER_ID_UNDEFINED; -} - -enum clock_source_id dal_graphics_object_id_get_clock_source_id( - struct graphics_object_id id) -{ - if (id.type == OBJECT_TYPE_CLOCK_SOURCE) - return id.id; - return CLOCK_SOURCE_ID_UNDEFINED; -} - -enum encoder_id dal_graphics_object_id_get_encoder_id( - struct graphics_object_id id) -{ - if (id.type == OBJECT_TYPE_ENCODER) - return id.id; - return ENCODER_ID_UNKNOWN; -} - -enum connector_id dal_graphics_object_id_get_connector_id( - struct graphics_object_id id) -{ - if (id.type == OBJECT_TYPE_CONNECTOR) - return id.id; - return CONNECTOR_ID_UNKNOWN; -} - -enum audio_id dal_graphics_object_id_get_audio_id(struct graphics_object_id id) -{ - if (id.type == OBJECT_TYPE_AUDIO) - return id.id; - return AUDIO_ID_UNKNOWN; -} - -enum engine_id dal_graphics_object_id_get_engine_id( - struct graphics_object_id id) -{ - if (id.type == OBJECT_TYPE_ENGINE) - return id.id; - return ENGINE_ID_UNKNOWN; -} diff --git a/drivers/gpu/drm/amd/display/include/grph_object_id.h b/drivers/gpu/drm/amd/display/include/grph_object_id.h index e4aa4ddf9d2a..5eb2b4dc7b9c 100644 --- a/drivers/gpu/drm/amd/display/include/grph_object_id.h +++ b/drivers/gpu/drm/amd/display/include/grph_object_id.h @@ -233,24 +233,62 @@ static inline struct graphics_object_id dal_graphics_object_id_init( return result; } -bool dal_graphics_object_id_is_valid( - struct graphics_object_id id); bool dal_graphics_object_id_is_equal( struct graphics_object_id id1, struct graphics_object_id id2); -uint32_t dal_graphics_object_id_to_uint( - struct graphics_object_id id); - -enum controller_id dal_graphics_object_id_get_controller_id( - struct graphics_object_id id); -enum clock_source_id dal_graphics_object_id_get_clock_source_id( - struct graphics_object_id id); -enum encoder_id dal_graphics_object_id_get_encoder_id( - struct graphics_object_id id); -enum connector_id dal_graphics_object_id_get_connector_id( - struct graphics_object_id id); -enum audio_id dal_graphics_object_id_get_audio_id( - struct graphics_object_id id); -enum engine_id dal_graphics_object_id_get_engine_id( - struct graphics_object_id id); + +/* Based on internal data members memory layout */ +static inline uint32_t dal_graphics_object_id_to_uint( + struct graphics_object_id id) +{ + return id.id + (id.enum_id << 0x8) + (id.type << 0xc); +} + +static inline enum controller_id dal_graphics_object_id_get_controller_id( + struct graphics_object_id id) +{ + if (id.type == OBJECT_TYPE_CONTROLLER) + return id.id; + return CONTROLLER_ID_UNDEFINED; +} + +static inline enum clock_source_id dal_graphics_object_id_get_clock_source_id( + struct graphics_object_id id) +{ + if (id.type == OBJECT_TYPE_CLOCK_SOURCE) + return id.id; + return CLOCK_SOURCE_ID_UNDEFINED; +} + +static inline enum encoder_id dal_graphics_object_id_get_encoder_id( + struct graphics_object_id id) +{ + if (id.type == OBJECT_TYPE_ENCODER) + return id.id; + return ENCODER_ID_UNKNOWN; +} + +static inline enum connector_id dal_graphics_object_id_get_connector_id( + struct graphics_object_id id) +{ + if (id.type == OBJECT_TYPE_CONNECTOR) + return id.id; + return CONNECTOR_ID_UNKNOWN; +} + +static inline enum audio_id dal_graphics_object_id_get_audio_id( + struct graphics_object_id id) +{ + if (id.type == OBJECT_TYPE_AUDIO) + return id.id; + return AUDIO_ID_UNKNOWN; +} + +static inline enum engine_id dal_graphics_object_id_get_engine_id( + struct graphics_object_id id) +{ + if (id.type == OBJECT_TYPE_ENGINE) + return id.id; + return ENGINE_ID_UNKNOWN; +} #endif -- cgit From 4ee67c71b89948289eb5c55f1a19281be61178e5 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 3 Oct 2017 12:37:33 +1000 Subject: amdgpu/dc: don't memset after kzalloc. We allocate this struct zeroed, so don't need to memset in the constructor. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_surface.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index f170ae95529c..ff07105bfd99 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -37,8 +37,6 @@ static void construct(struct dc_context *ctx, struct dc_plane_state *plane_state) { plane_state->ctx = ctx; - memset(&plane_state->hdr_static_ctx, - 0, sizeof(struct dc_hdr_static_metadata)); } static void destruct(struct dc_plane_state *plane_state) -- cgit From 23d433fabef852e82053186b60710d138f727284 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 3 Oct 2017 13:49:42 +1000 Subject: amdgpu/dc: use kernel ilog2 for log_2. This should produce the same result. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/basics/conversion.c | 10 ---------- drivers/gpu/drm/amd/display/dc/basics/conversion.h | 5 ++++- 2 files changed, 4 insertions(+), 11 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/basics/conversion.c b/drivers/gpu/drm/amd/display/dc/basics/conversion.c index a2e22ae12adb..23c9a0ec0181 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/conversion.c +++ b/drivers/gpu/drm/amd/display/dc/basics/conversion.c @@ -102,13 +102,3 @@ void convert_float_matrix( matrix[i] = (uint16_t)reg_value; } } - -unsigned int log_2(unsigned int num) -{ - unsigned int result = 0; - - while ((num >>= 1) != 0) - result++; - - return result; -} diff --git a/drivers/gpu/drm/amd/display/dc/basics/conversion.h b/drivers/gpu/drm/amd/display/dc/basics/conversion.h index 189325f68cfd..ade785c4fdc7 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/conversion.h +++ b/drivers/gpu/drm/amd/display/dc/basics/conversion.h @@ -38,6 +38,9 @@ void convert_float_matrix( struct fixed31_32 *flt, uint32_t buffer_size); -unsigned int log_2(unsigned int num); +static inline unsigned int log_2(unsigned int num) +{ + return ilog2(num); +} #endif -- cgit From bd42a6f45180b3bd2bfe260959f53344f2636e71 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 3 Oct 2017 13:49:43 +1000 Subject: amdgpu/dc: drop dce110_types.h Doesn't appear to be used. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dce110/dce110_types.h | 30 ---------------------- 1 file changed, 30 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_types.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_types.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_types.h deleted file mode 100644 index 55f52382ddfb..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_types.h +++ /dev/null @@ -1,30 +0,0 @@ -/* Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef _DCE110_TYPES_H_ -#define __DCE110_TYPES_H_ - -#define GAMMA_SEGMENTS_NUM 16 - -#endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_DCE110_DCE110_TYPES_H_ */ -- cgit From 2016b641f421ecb28c21e34063ac8bd43ca6cfdc Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 3 Oct 2017 13:49:44 +1000 Subject: amdgpu/dc: drop hw_sequencer_types.h This isn't used or required. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../display/dc/dce110/dce110_timing_generator.h | 1 - .../display/dc/dce120/dce120_timing_generator.h | 1 - drivers/gpu/drm/amd/display/dc/inc/core_types.h | 1 - .../gpu/drm/amd/display/dc/inc/hw/stream_encoder.h | 1 - .../drm/amd/display/include/hw_sequencer_types.h | 33 ---------------------- 5 files changed, 37 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/include/hw_sequencer_types.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h index bd8d0ab668b7..82737dea6984 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h @@ -28,7 +28,6 @@ #include "timing_generator.h" #include "../include/grph_object_id.h" -#include "../include/hw_sequencer_types.h" /* GSL Sync related values */ diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.h index d69871ec0dde..549d70b23e82 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.h @@ -28,7 +28,6 @@ #include "timing_generator.h" #include "../include/grph_object_id.h" -#include "../include/hw_sequencer_types.h" #include "dce110/dce110_timing_generator.h" diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 1a1d322da8cc..c47ce6b9fc6b 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -46,7 +46,6 @@ void enable_surface_flip_reporting(struct dc_plane_state *plane_state, #include "stream_encoder.h" #include "clock_source.h" #include "audio.h" -#include "hw_sequencer_types.h" #include "dm_pp_smu.h" diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h index 6ff90a0fef24..3050afe8e8a9 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h @@ -6,7 +6,6 @@ #ifndef STREAM_ENCODER_H_ #define STREAM_ENCODER_H_ -#include "include/hw_sequencer_types.h" #include "audio_types.h" struct dc_bios; diff --git a/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h b/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h deleted file mode 100644 index 8ba9f65276f5..000000000000 --- a/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DAL_HW_SEQUENCER_TYPES_H__ -#define __DAL_HW_SEQUENCER_TYPES_H__ - -#include "signal_types.h" -#include "grph_object_defs.h" -#include "link_service_types.h" - -#endif -- cgit From 5667ff5c117f2d8735f27a267bc68a0811c55075 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 3 Oct 2017 14:27:13 +1000 Subject: amdgpu/dc: fix a bunch of misc whitespace. This just aligns a few things with kernel style. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 8 ++-- drivers/gpu/drm/amd/display/dc/dc_types.h | 16 ++++---- .../display/dc/dce110/dce110_timing_generator.c | 4 +- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 16 ++++---- .../gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c | 46 +++++++++++----------- .../amd/display/include/grph_object_ctrl_defs.h | 20 +++++----- 6 files changed, 55 insertions(+), 55 deletions(-) (limited to 'drivers/gpu') 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 888d268e9622..3c323c1ea366 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 @@ -1473,10 +1473,10 @@ void decide_link_settings(struct dc_stream_state *stream, return; } - /* search for the minimum link setting that: - * 1. is supported according to the link training result - * 2. could support the b/w requested by the timing - */ + /* search for the minimum link setting that: + * 1. is supported according to the link training result + * 2. could support the b/w requested by the timing + */ while (current_link_setting.link_rate <= link->verified_link_cap.link_rate) { link_bw = bandwidth_in_kbps_from_link_settings( diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index a47f7472ea92..6b891fde400c 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -429,14 +429,14 @@ union audio_sample_rates { }; struct audio_speaker_flags { - uint32_t FL_FR:1; - uint32_t LFE:1; - uint32_t FC:1; - uint32_t RL_RR:1; - uint32_t RC:1; - uint32_t FLC_FRC:1; - uint32_t RLC_RRC:1; - uint32_t SUPPORT_AI:1; + uint32_t FL_FR:1; + uint32_t LFE:1; + uint32_t FC:1; + uint32_t RL_RR:1; + uint32_t RC:1; + uint32_t FLC_FRC:1; + uint32_t RLC_RRC:1; + uint32_t SUPPORT_AI:1; }; struct audio_speaker_info { diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c index bcd544d85621..67ac737eaa7e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c @@ -1238,8 +1238,8 @@ void dce110_timing_generator_setup_global_swap_lock( DCP_GSL_CONTROL, DCP_GSL_HSYNC_FLIP_FORCE_DELAY); - /* Keep signal low (pending high) during 6 lines. - * Also defines minimum interval before re-checking signal. */ + /* Keep signal low (pending high) during 6 lines. + * Also defines minimum interval before re-checking signal. */ set_reg_field_value(value, HFLIP_CHECK_DELAY, DCP_GSL_CONTROL, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index c4875c3a0d93..d3fee15aeb79 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2396,14 +2396,14 @@ static void program_all_pipe_in_tree( dcn10_power_on_fe(dc, pipe_ctx, context); /* temporary dcn1 wa: - * watermark update requires toggle after a/b/c/d sets are programmed - * if hubp is pg then wm value doesn't get properaged to hubp - * need to toggle after ungate to ensure wm gets to hubp. - * - * final solution: we need to get SMU to do the toggle as - * DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST is owned by SMU we should have - * both driver and fw accessing same register - */ + * watermark update requires toggle after a/b/c/d sets are programmed + * if hubp is pg then wm value doesn't get properaged to hubp + * need to toggle after ungate to ensure wm gets to hubp. + * + * final solution: we need to get SMU to do the toggle as + * DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST is owned by SMU we should have + * both driver and fw accessing same register + */ toggle_watermark_change_req(dc->hwseq); update_dchubp_dpp(dc, pipe_ctx, context); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index c8088489c6a2..a28495d95a15 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -697,37 +697,37 @@ static void min10_set_vm_context0_settings(struct mem_input *mem_input, } static void min_set_viewport( - struct mem_input *mem_input, - const struct rect *viewport, - const struct rect *viewport_c) + struct mem_input *mem_input, + const struct rect *viewport, + const struct rect *viewport_c) { struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); - REG_SET_2(DCSURF_PRI_VIEWPORT_DIMENSION, 0, - PRI_VIEWPORT_WIDTH, viewport->width, - PRI_VIEWPORT_HEIGHT, viewport->height); + REG_SET_2(DCSURF_PRI_VIEWPORT_DIMENSION, 0, + PRI_VIEWPORT_WIDTH, viewport->width, + PRI_VIEWPORT_HEIGHT, viewport->height); - REG_SET_2(DCSURF_PRI_VIEWPORT_START, 0, - PRI_VIEWPORT_X_START, viewport->x, - PRI_VIEWPORT_Y_START, viewport->y); + REG_SET_2(DCSURF_PRI_VIEWPORT_START, 0, + PRI_VIEWPORT_X_START, viewport->x, + PRI_VIEWPORT_Y_START, viewport->y); - /*for stereo*/ - REG_SET_2(DCSURF_SEC_VIEWPORT_DIMENSION, 0, - SEC_VIEWPORT_WIDTH, viewport->width, - SEC_VIEWPORT_HEIGHT, viewport->height); + /*for stereo*/ + REG_SET_2(DCSURF_SEC_VIEWPORT_DIMENSION, 0, + SEC_VIEWPORT_WIDTH, viewport->width, + SEC_VIEWPORT_HEIGHT, viewport->height); - REG_SET_2(DCSURF_SEC_VIEWPORT_START, 0, - SEC_VIEWPORT_X_START, viewport->x, - SEC_VIEWPORT_Y_START, viewport->y); + REG_SET_2(DCSURF_SEC_VIEWPORT_START, 0, + SEC_VIEWPORT_X_START, viewport->x, + SEC_VIEWPORT_Y_START, viewport->y); - /* DC supports NV12 only at the moment */ - REG_SET_2(DCSURF_PRI_VIEWPORT_DIMENSION_C, 0, - PRI_VIEWPORT_WIDTH_C, viewport_c->width, - PRI_VIEWPORT_HEIGHT_C, viewport_c->height); + /* DC supports NV12 only at the moment */ + REG_SET_2(DCSURF_PRI_VIEWPORT_DIMENSION_C, 0, + PRI_VIEWPORT_WIDTH_C, viewport_c->width, + PRI_VIEWPORT_HEIGHT_C, viewport_c->height); - REG_SET_2(DCSURF_PRI_VIEWPORT_START_C, 0, - PRI_VIEWPORT_X_START_C, viewport_c->x, - PRI_VIEWPORT_Y_START_C, viewport_c->y); + REG_SET_2(DCSURF_PRI_VIEWPORT_START_C, 0, + PRI_VIEWPORT_X_START_C, viewport_c->x, + PRI_VIEWPORT_Y_START_C, viewport_c->y); } void dcn10_mem_input_read_state(struct dcn10_mem_input *mi, diff --git a/drivers/gpu/drm/amd/display/include/grph_object_ctrl_defs.h b/drivers/gpu/drm/amd/display/include/grph_object_ctrl_defs.h index 92fe00fab87c..7a9b43f84a31 100644 --- a/drivers/gpu/drm/amd/display/include/grph_object_ctrl_defs.h +++ b/drivers/gpu/drm/amd/display/include/grph_object_ctrl_defs.h @@ -183,9 +183,9 @@ struct dc_firmware_info { }; struct step_and_delay_info { - uint32_t step; - uint32_t delay; - uint32_t recommended_ref_div; + uint32_t step; + uint32_t delay; + uint32_t recommended_ref_div; }; struct spread_spectrum_info { @@ -266,16 +266,16 @@ struct transmitter_configuration { #define NUMBER_OF_AVAILABLE_SCLK 5 struct i2c_reg_info { - unsigned char i2c_reg_index; - unsigned char i2c_reg_val; + unsigned char i2c_reg_index; + unsigned char i2c_reg_val; }; struct ext_hdmi_settings { - unsigned char slv_addr; - unsigned char reg_num; - struct i2c_reg_info reg_settings[9]; - unsigned char reg_num_6g; - struct i2c_reg_info reg_settings_6g[3]; + unsigned char slv_addr; + unsigned char reg_num; + struct i2c_reg_info reg_settings[9]; + unsigned char reg_num_6g; + struct i2c_reg_info reg_settings_6g[3]; }; -- cgit From d029810caafa4e6b146274560154e3f0f0381fb5 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 3 Oct 2017 14:27:14 +1000 Subject: amdgpu/dc: kfree already checks for NULL. Don't bother checking for it. Found with the cocci ifnullfree.cocci script. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/basics/vector.c | 3 +-- drivers/gpu/drm/amd/display/dc/bios/bios_parser.c | 7 ++----- drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c | 7 ++----- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 3 +-- drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c | 11 +++-------- 5 files changed, 9 insertions(+), 22 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/basics/vector.c b/drivers/gpu/drm/amd/display/dc/basics/vector.c index e00fc4db3ac4..217b8f1f7bf6 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/vector.c +++ b/drivers/gpu/drm/amd/display/dc/basics/vector.c @@ -130,8 +130,7 @@ struct vector *dal_vector_create( void dal_vector_destruct( struct vector *vector) { - if (vector->container != NULL) - kfree(vector->container); + kfree(vector->container); vector->count = 0; vector->capacity = 0; } diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c index 2e003b5c8d08..6d2f886f7ff4 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c @@ -119,11 +119,8 @@ struct dc_bios *bios_parser_create( static void destruct(struct bios_parser *bp) { - if (bp->base.bios_local_image) - kfree(bp->base.bios_local_image); - - if (bp->base.integrated_info) - kfree(bp->base.integrated_info); + kfree(bp->base.bios_local_image); + kfree(bp->base.integrated_info); } static void bios_parser_destroy(struct dc_bios **dcb) diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c index 0c623b314577..3d65e2ab9bf1 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -85,11 +85,8 @@ static struct atom_encoder_caps_record *get_encoder_cap_record( static void destruct(struct bios_parser *bp) { - if (bp->base.bios_local_image) - kfree(bp->base.bios_local_image); - - if (bp->base.integrated_info) - kfree(bp->base.integrated_info); + kfree(bp->base.bios_local_image); + kfree(bp->base.integrated_info); } static void firmware_parser_destroy(struct dc_bios **dcb) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 1832f252edab..99a4d19f582d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -159,8 +159,7 @@ void dc_destroy_resource_pool(struct dc *dc) if (dc->res_pool) dc->res_pool->funcs->destroy(&dc->res_pool); - if (dc->hwseq) - kfree(dc->hwseq); + kfree(dc->hwseq); } } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 89036aff9021..28e768de744c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -619,14 +619,9 @@ void dce110_clock_source_destroy(struct clock_source **clk_src) dce110_clk_src = TO_DCE110_CLK_SRC(*clk_src); - if (dce110_clk_src->dp_ss_params) - kfree(dce110_clk_src->dp_ss_params); - - if (dce110_clk_src->hdmi_ss_params) - kfree(dce110_clk_src->hdmi_ss_params); - - if (dce110_clk_src->dvi_ss_params) - kfree(dce110_clk_src->dvi_ss_params); + kfree(dce110_clk_src->dp_ss_params); + kfree(dce110_clk_src->hdmi_ss_params); + kfree(dce110_clk_src->dvi_ss_params); kfree(dce110_clk_src); *clk_src = NULL; -- cgit From ae3a27d19b59e431aea9f9d5917c1aec710ae4c3 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 3 Oct 2017 14:27:15 +1000 Subject: amdgpu/dm: don't use after free. This dereference acrtc after freeing it. Found by the kfree cocci script. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/gpu') 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 61ccddd19718..4f8973182f8a 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3174,7 +3174,6 @@ int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, fail: kfree(acrtc); kfree(cursor_plane); - acrtc->crtc_id = -1; return res; } -- cgit From c1199962f58528d6530db055b576cfaf5340b427 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 3 Oct 2017 15:10:59 +1000 Subject: amdgpu/dc: fix indentation on a couple of returns. These were misaligned. found by the cocci ifcol script. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c index 3d65e2ab9bf1..cb94e18cc455 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -1472,7 +1472,7 @@ static enum bp_result get_integrated_info_v11( DATA_TABLES(integratedsysteminfo)); if (info_v11 == NULL) - return BP_RESULT_BADBIOSTABLE; + return BP_RESULT_BADBIOSTABLE; info->gpu_cap_info = le32_to_cpu(info_v11->gpucapinfo); @@ -1753,7 +1753,7 @@ static struct integrated_info *bios_parser_create_integrated_info( } if (construct_integrated_info(bp, info) == BP_RESULT_OK) - return info; + return info; kfree(info); -- cgit From c6fa531809f08af52406347e5351920cc2d55e42 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 3 Oct 2017 15:11:00 +1000 Subject: amdgpu/dc: kill some deadcode in dc core. Moves one function to an inline, but kills a bunch of deadcode. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 91 -------------------------------- drivers/gpu/drm/amd/display/dc/dc.h | 9 ++-- 2 files changed, 4 insertions(+), 96 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index c8235b041b5b..1ec8248546c5 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -575,30 +575,6 @@ fail: return false; } -/* -void ProgramPixelDurationV(unsigned int pixelClockInKHz ) -{ - fixed31_32 pixel_duration = Fixed31_32(100000000, pixelClockInKHz) * 10; - unsigned int pixDurationInPico = round(pixel_duration); - - DPG_PIPE_ARBITRATION_CONTROL1 arb_control; - - arb_control.u32All = ReadReg (mmDPGV0_PIPE_ARBITRATION_CONTROL1); - arb_control.bits.PIXEL_DURATION = pixDurationInPico; - WriteReg (mmDPGV0_PIPE_ARBITRATION_CONTROL1, arb_control.u32All); - - arb_control.u32All = ReadReg (mmDPGV1_PIPE_ARBITRATION_CONTROL1); - arb_control.bits.PIXEL_DURATION = pixDurationInPico; - WriteReg (mmDPGV1_PIPE_ARBITRATION_CONTROL1, arb_control.u32All); - - WriteReg (mmDPGV0_PIPE_ARBITRATION_CONTROL2, 0x4000800); - WriteReg (mmDPGV0_REPEATER_PROGRAM, 0x11); - - WriteReg (mmDPGV1_PIPE_ARBITRATION_CONTROL2, 0x4000800); - WriteReg (mmDPGV1_REPEATER_PROGRAM, 0x11); -} -*/ - /******************************************************************************* * Public functions ******************************************************************************/ @@ -1518,28 +1494,6 @@ struct dc_stream_state *dc_get_stream_at_index(struct dc *dc, uint8_t i) return NULL; } -struct dc_link *dc_get_link_at_index(struct dc *dc, uint32_t link_index) -{ - return dc->links[link_index]; -} - -const struct graphics_object_id dc_get_link_id_at_index( - struct dc *dc, uint32_t link_index) -{ - return dc->links[link_index]->link_id; -} - -enum dc_irq_source dc_get_hpd_irq_source_at_index( - struct dc *dc, uint32_t link_index) -{ - return dc->links[link_index]->irq_source_hpd; -} - -const struct audio **dc_get_audios(struct dc *dc) -{ - return (const struct audio **)dc->res_pool->audios; -} - enum dc_irq_source dc_interrupt_to_irq_source( struct dc *dc, uint32_t src_id, @@ -1789,17 +1743,6 @@ fail_add_sink: return NULL; } -void dc_link_set_sink(struct dc_link *link, struct dc_sink *sink) -{ - link->local_sink = sink; - - if (sink == NULL) { - link->type = dc_connection_none; - } else { - link->type = dc_connection_single; - } -} - void dc_link_remove_remote_sink(struct dc_link *link, struct dc_sink *sink) { int i; @@ -1825,37 +1768,3 @@ void dc_link_remove_remote_sink(struct dc_link *link, struct dc_sink *sink) } } } - -bool dc_init_dchub(struct dc *dc, struct dchub_init_data *dh_data) -{ - int i; - struct mem_input *mi = NULL; - - for (i = 0; i < dc->res_pool->pipe_count; i++) { - if (dc->res_pool->mis[i] != NULL) { - mi = dc->res_pool->mis[i]; - break; - } - } - if (mi == NULL) { - dm_error("no mem_input!\n"); - return false; - } - - if (dc->hwss.update_dchub) - dc->hwss.update_dchub(dc->hwseq, dh_data); - else - ASSERT(dc->hwss.update_dchub); - - - return true; - -} - -void dc_log_hw_state(struct dc *dc) -{ - - if (dc->hwss.log_hw_state) - dc->hwss.log_hw_state(dc); -} - diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 9c0e00050753..259ac6918564 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -277,10 +277,6 @@ struct dc *dc_create(const struct dc_init_data *init_params); void dc_destroy(struct dc **dc); -bool dc_init_dchub(struct dc *dc, struct dchub_init_data *dh_data); - -void dc_log_hw_state(struct dc *dc); - /******************************************************************************* * Surface Interfaces ******************************************************************************/ @@ -866,7 +862,10 @@ const struct dc_link_status *dc_link_get_status(const struct dc_link *dc_link); * boot time. They cannot be created or destroyed. * Use dc_get_caps() to get number of links. */ -struct dc_link *dc_get_link_at_index(struct dc *dc, uint32_t link_index); +static inline struct dc_link *dc_get_link_at_index(struct dc *dc, uint32_t link_index) +{ + return dc->links[link_index]; +} /* Set backlight level of an embedded panel (eDP, LVDS). */ bool dc_link_set_backlight_level(const struct dc_link *dc_link, uint32_t level, -- cgit From 44858055bb28b1ba45dc05acecf9087bc4786701 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 3 Oct 2017 15:11:01 +1000 Subject: amdgpu/dc: set a bunch of functions to static. All of these are unused outside the file they are in. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/bios/bios_parser.c | 2 +- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 2 +- drivers/gpu/drm/amd/display/dc/dce/dce_audio.c | 3 +-- drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c | 6 +++--- 8 files changed, 10 insertions(+), 11 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c index 6d2f886f7ff4..aaaebd06d7ee 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c @@ -531,7 +531,7 @@ static enum bp_result bios_parser_get_hpd_info(struct dc_bios *dcb, return BP_RESULT_NORECORD; } -enum bp_result bios_parser_get_device_tag_record( +static enum bp_result bios_parser_get_device_tag_record( struct bios_parser *bp, ATOM_OBJECT *object, ATOM_CONNECTOR_DEVICE_TAG_RECORD **record) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 91f43a1b88ee..8ca6c3e4e65a 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -1135,7 +1135,7 @@ bool dcn_validate_bandwidth( return false; } -unsigned int dcn_find_normalized_clock_vdd_Level( +static unsigned int dcn_find_normalized_clock_vdd_Level( const struct dc *dc, enum dm_pp_clock_type clocks_type, int clocks_in_khz) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 1ec8248546c5..2dcff41c9b38 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -327,7 +327,7 @@ static void set_test_pattern( cust_pattern_size); } -void set_dither_option(struct dc_stream_state *stream, +static void set_dither_option(struct dc_stream_state *stream, enum dc_dither_option option) { struct bit_depth_reduction_params params; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 43ebd8941b77..d02dd9f2ef09 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -208,7 +208,7 @@ hpd_gpio_failure: return false; } -enum ddc_transaction_type get_ddc_transaction_type( +static enum ddc_transaction_type get_ddc_transaction_type( enum signal_type sink_signal) { enum ddc_transaction_type transaction_type = DDC_TRANSACTION_TYPE_NONE; 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 3c323c1ea366..b735782b8fe0 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 @@ -1209,7 +1209,7 @@ static inline bool reached_minimum_link_rate(enum dc_link_rate link_rate) return link_rate <= LINK_RATE_LOW; } -enum dc_lane_count reduce_lane_count(enum dc_lane_count lane_count) +static enum dc_lane_count reduce_lane_count(enum dc_lane_count lane_count) { switch (lane_count) { case LANE_COUNT_FOUR: diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 3427fb5b7e30..616431e25b79 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -110,7 +110,7 @@ void dp_enable_link_phy( dp_receiver_power_ctrl(link, true); } -bool edp_receiver_ready_T9(struct dc_link *link) +static bool edp_receiver_ready_T9(struct dc_link *link) { unsigned int tries = 0; unsigned char sinkstatus = 0; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c index 6e940286c98d..526ec5c8eafd 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c @@ -833,8 +833,7 @@ void dce_aud_wall_dto_setup( } } -bool dce_aud_endpoint_valid( - struct audio *audio) +static bool dce_aud_endpoint_valid(struct audio *audio) { uint32_t value; uint32_t port_connectivity; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c index a09727fb405f..4fd49a16c3b6 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c @@ -1183,7 +1183,7 @@ static const struct audio_clock_info audio_clock_info_table_48bpc[14] = { }; -union audio_cea_channels speakers_to_channels( +static union audio_cea_channels speakers_to_channels( struct audio_speaker_flags speaker_flags) { union audio_cea_channels cea_channels = {0}; @@ -1217,7 +1217,7 @@ union audio_cea_channels speakers_to_channels( return cea_channels; } -uint32_t calc_max_audio_packets_per_line( +static uint32_t calc_max_audio_packets_per_line( const struct audio_crtc_info *crtc_info) { uint32_t max_packets_per_line; @@ -1238,7 +1238,7 @@ uint32_t calc_max_audio_packets_per_line( return max_packets_per_line; } -void get_audio_clock_info( +static void get_audio_clock_info( enum dc_color_depth color_depth, uint32_t crtc_pixel_clock_in_khz, uint32_t actual_pixel_clock_in_khz, -- cgit From 5d15ae23f8a42ce6728294808b6bd96c6b251a5f Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 3 Oct 2017 15:11:02 +1000 Subject: amdgpu/dc: kill a bunch of dead code. None of this code is used currently. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 101 -------------------------- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 15 ---- drivers/gpu/drm/amd/display/dc/core/dc_sink.c | 34 --------- 3 files changed, 150 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 2dcff41c9b38..d8820d6f79c6 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1559,107 +1559,6 @@ void dc_resume(struct dc *dc) core_link_resume(dc->links[i]); } -bool dc_read_aux_dpcd( - struct dc *dc, - uint32_t link_index, - uint32_t address, - uint8_t *data, - uint32_t size) -{ - - struct dc_link *link = dc->links[link_index]; - enum ddc_result r = dal_ddc_service_read_dpcd_data( - link->ddc, - false, - I2C_MOT_UNDEF, - address, - data, - size); - return r == DDC_RESULT_SUCESSFULL; -} - -bool dc_write_aux_dpcd( - struct dc *dc, - uint32_t link_index, - uint32_t address, - const uint8_t *data, - uint32_t size) -{ - struct dc_link *link = dc->links[link_index]; - - enum ddc_result r = dal_ddc_service_write_dpcd_data( - link->ddc, - false, - I2C_MOT_UNDEF, - address, - data, - size); - return r == DDC_RESULT_SUCESSFULL; -} - -bool dc_read_aux_i2c( - struct dc *dc, - uint32_t link_index, - enum i2c_mot_mode mot, - uint32_t address, - uint8_t *data, - uint32_t size) -{ - - struct dc_link *link = dc->links[link_index]; - enum ddc_result r = dal_ddc_service_read_dpcd_data( - link->ddc, - true, - mot, - address, - data, - size); - return r == DDC_RESULT_SUCESSFULL; -} - -bool dc_write_aux_i2c( - struct dc *dc, - uint32_t link_index, - enum i2c_mot_mode mot, - uint32_t address, - const uint8_t *data, - uint32_t size) -{ - struct dc_link *link = dc->links[link_index]; - - enum ddc_result r = dal_ddc_service_write_dpcd_data( - link->ddc, - true, - mot, - address, - data, - size); - return r == DDC_RESULT_SUCESSFULL; -} - -bool dc_query_ddc_data( - struct dc *dc, - uint32_t link_index, - uint32_t address, - uint8_t *write_buf, - uint32_t write_size, - uint8_t *read_buf, - uint32_t read_size) { - - - struct dc_link *link = dc->links[link_index]; - - bool result = dal_ddc_service_query_ddc_data( - link->ddc, - address, - write_buf, - write_size, - read_buf, - read_size); - - return result; -} - bool dc_submit_i2c( struct dc *dc, uint32_t link_index, diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index d02dd9f2ef09..4a70948c91b1 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1857,21 +1857,6 @@ bool dc_link_set_backlight_level(const struct dc_link *link, uint32_t level, return true; } - -bool dc_link_set_abm_disable(const struct dc_link *link) -{ - struct dc *core_dc = link->ctx->dc; - struct abm *abm = core_dc->res_pool->abm; - - if ((abm == NULL) || (abm->funcs->set_backlight_level == NULL)) - return false; - - abm->funcs->set_abm_immediate_disable(abm); - - return true; -} - - bool dc_link_set_psr_enable(const struct dc_link *link, bool enable, bool wait) { struct dc *core_dc = link->ctx->dc; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_sink.c b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c index b3bbafc8fd6a..3d620d3d0672 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_sink.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c @@ -99,40 +99,6 @@ alloc_fail: return NULL; } -bool dc_sink_get_container_id(struct dc_sink *dc_sink, struct dc_container_id *container_id) -{ - if (dc_sink && container_id && dc_sink->dc_container_id) { - memmove(&container_id->guid, &dc_sink->dc_container_id->guid, - sizeof(container_id->guid)); - memmove(&container_id->portId, &dc_sink->dc_container_id->portId, - sizeof(container_id->portId)); - container_id->manufacturerName = dc_sink->dc_container_id->manufacturerName; - container_id->productCode = dc_sink->dc_container_id->productCode; - return true; - } - return false; -} - -bool dc_sink_set_container_id(struct dc_sink *dc_sink, const struct dc_container_id *container_id) -{ - if (dc_sink && container_id) { - if (!dc_sink->dc_container_id) - dc_sink->dc_container_id = kzalloc(sizeof(*dc_sink->dc_container_id), - GFP_KERNEL); - - if (dc_sink->dc_container_id) { - memmove(&dc_sink->dc_container_id->guid, &container_id->guid, - sizeof(container_id->guid)); - memmove(&dc_sink->dc_container_id->portId, &container_id->portId, - sizeof(container_id->portId)); - dc_sink->dc_container_id->manufacturerName = container_id->manufacturerName; - dc_sink->dc_container_id->productCode = container_id->productCode; - return true; - } - } - return false; -} - /******************************************************************************* * Protected functions - visible only inside of DC (not visible in DM) ******************************************************************************/ -- cgit From 93052132568aedb5eda04deae51d6034738a4800 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 3 Oct 2017 12:38:57 +1000 Subject: amdgpu/dc: convert dc_transfer to use a kref. Rolling your own atomic ref counts is frowned upon. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_surface.c | 17 +++++++++-------- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- drivers/gpu/drm/amd/display/dc/os_types.h | 2 ++ 3 files changed, 12 insertions(+), 9 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index ff07105bfd99..c2168dfacc8d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -161,17 +161,18 @@ alloc_fail: void dc_transfer_func_retain(struct dc_transfer_func *tf) { - ASSERT(atomic_read(&tf->ref_count) > 0); - atomic_inc(&tf->ref_count); + kref_get(&tf->refcount); } -void dc_transfer_func_release(struct dc_transfer_func *tf) +static void dc_transfer_func_free(struct kref *kref) { - ASSERT(atomic_read(&tf->ref_count) > 0); - atomic_dec(&tf->ref_count); + struct dc_transfer_func *tf = container_of(kref, struct dc_transfer_func, refcount); + kfree(tf); +} - if (atomic_read(&tf->ref_count) == 0) - kfree(tf); +void dc_transfer_func_release(struct dc_transfer_func *tf) +{ + kref_put(&tf->refcount, dc_transfer_func_free); } struct dc_transfer_func *dc_create_transfer_func() @@ -181,7 +182,7 @@ struct dc_transfer_func *dc_create_transfer_func() if (tf == NULL) goto alloc_fail; - atomic_inc(&tf->ref_count); + kref_init(&tf->refcount); return tf; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 259ac6918564..f16c545a87ed 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -330,11 +330,11 @@ enum dc_transfer_func_predefined { }; struct dc_transfer_func { + struct kref refcount; struct dc_transfer_func_distributed_points tf_pts; enum dc_transfer_func_type type; enum dc_transfer_func_predefined tf; struct dc_context *ctx; - atomic_t ref_count; }; /* diff --git a/drivers/gpu/drm/amd/display/dc/os_types.h b/drivers/gpu/drm/amd/display/dc/os_types.h index 27ed2a61c3c8..e0cd5278aae8 100644 --- a/drivers/gpu/drm/amd/display/dc/os_types.h +++ b/drivers/gpu/drm/amd/display/dc/os_types.h @@ -32,6 +32,8 @@ #include #include +#include + #include "cgs_linux.h" #if defined(__BIG_ENDIAN) && !defined(BIGENDIAN_CPU) -- cgit From 5c58ab0bd61b5c8538721f4200475c0af0e33efe Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 3 Oct 2017 12:38:58 +1000 Subject: amdgpu/dc: convert dc_gamma to kref reference counting. Rolling your own reference counting is frowned upon. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_surface.c | 19 +++++++++---------- drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 4 +--- 2 files changed, 10 insertions(+), 13 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index c2168dfacc8d..0950075b6c54 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -129,18 +129,18 @@ void dc_plane_state_release(struct dc_plane_state *plane_state) void dc_gamma_retain(struct dc_gamma *gamma) { - ASSERT(atomic_read(&gamma->ref_count) > 0); - atomic_inc(&gamma->ref_count); + kref_get(&gamma->refcount); } -void dc_gamma_release(struct dc_gamma **gamma) +static void dc_gamma_free(struct kref *kref) { - ASSERT(atomic_read(&(*gamma)->ref_count) > 0); - atomic_dec(&(*gamma)->ref_count); - - if (atomic_read(&(*gamma)->ref_count) == 0) - kfree((*gamma)); + struct dc_gamma *gamma = container_of(kref, struct dc_gamma, refcount); + kfree(gamma); +} +void dc_gamma_release(struct dc_gamma **gamma) +{ + kref_put(&(*gamma)->refcount, dc_gamma_free); *gamma = NULL; } @@ -151,8 +151,7 @@ struct dc_gamma *dc_create_gamma() if (gamma == NULL) goto alloc_fail; - atomic_inc(&gamma->ref_count); - + kref_init(&gamma->refcount); return gamma; alloc_fail: diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index 94f83cd9ab32..4ab109314e4b 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -420,6 +420,7 @@ enum dc_gamma_type { }; struct dc_gamma { + struct kref refcount; enum dc_gamma_type type; unsigned int num_entries; @@ -431,9 +432,6 @@ struct dc_gamma { /* private to DC core */ struct dc_context *ctx; - - /* private to dc_surface.c */ - atomic_t ref_count; }; /* Used by both ipp amd opp functions*/ -- cgit From 4d090f0fae08ddaccf8caaf707f386d52b7f7a08 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 3 Oct 2017 12:38:59 +1000 Subject: amdgpu/dc: use kref for dc_plane_state. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_surface.c | 20 ++++++++++---------- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index 0950075b6c54..d43783a45ab6 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -71,8 +71,8 @@ struct dc_plane_state *dc_create_plane_state(struct dc *dc) if (NULL == plane_state) return NULL; + kref_init(&plane_state->refcount); construct(core_dc->ctx, plane_state); - atomic_inc(&plane_state->ref_count); return plane_state; } @@ -112,19 +112,19 @@ const struct dc_plane_status *dc_plane_get_status( void dc_plane_state_retain(struct dc_plane_state *plane_state) { - ASSERT(atomic_read(&plane_state->ref_count) > 0); - atomic_inc(&plane_state->ref_count); + kref_get(&plane_state->refcount); } -void dc_plane_state_release(struct dc_plane_state *plane_state) +static void dc_plane_state_free(struct kref *kref) { - ASSERT(atomic_read(&plane_state->ref_count) > 0); - atomic_dec(&plane_state->ref_count); + struct dc_plane_state *plane_state = container_of(kref, struct dc_plane_state, refcount); + destruct(plane_state); + kfree(plane_state); +} - if (atomic_read(&plane_state->ref_count) == 0) { - destruct(plane_state); - kfree(plane_state); - } +void dc_plane_state_release(struct dc_plane_state *plane_state) +{ + kref_put(&plane_state->refcount, dc_plane_state_free); } void dc_gamma_retain(struct dc_gamma *gamma) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index f16c545a87ed..1adfa97bf3fd 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -381,7 +381,7 @@ struct dc_plane_state { /* private to dc_surface.c */ enum dc_irq_source irq_source; - atomic_t ref_count; + struct kref refcount; }; struct dc_plane_info { -- cgit From bfe0feb143151cce76411bb211c3eec0f6cff7ba Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 3 Oct 2017 12:39:00 +1000 Subject: amdgpu/dc: convert dc_stream_state to kref. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 22 +++++++++++----------- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index a99196414255..23df7bc020d2 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -118,20 +118,21 @@ static void destruct(struct dc_stream_state *stream) void dc_stream_retain(struct dc_stream_state *stream) { - ASSERT(atomic_read(&stream->ref_count) > 0); - atomic_inc(&stream->ref_count); + kref_get(&stream->refcount); +} + +static void dc_stream_free(struct kref *kref) +{ + struct dc_stream_state *stream = container_of(kref, struct dc_stream_state, refcount); + + destruct(stream); + kfree(stream); } void dc_stream_release(struct dc_stream_state *stream) { if (stream != NULL) { - ASSERT(atomic_read(&stream->ref_count) > 0); - atomic_dec(&stream->ref_count); - - if (atomic_read(&stream->ref_count) == 0) { - destruct(stream); - kfree(stream); - } + kref_put(&stream->refcount, dc_stream_free); } } @@ -149,10 +150,9 @@ struct dc_stream_state *dc_create_stream_for_sink( construct(stream, sink); - atomic_inc(&stream->ref_count); + kref_init(&stream->refcount); return stream; - } struct dc_stream_status *dc_stream_get_status( diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 1adfa97bf3fd..97f6f34f3d22 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -558,7 +558,7 @@ struct dc_stream_state { struct dc_stream_status status; /* from stream struct */ - atomic_t ref_count; + struct kref refcount; }; struct dc_stream_update { -- cgit From cb56aceabd36ef42bc7e081c43dc55ef57efba7a Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 3 Oct 2017 12:39:01 +1000 Subject: amdgpu/dc: convert dc_sink to kref. Refcounts use krefs. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_sink.c | 20 ++++++++++---------- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_sink.c b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c index 3d620d3d0672..25fae38409ab 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_sink.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c @@ -63,19 +63,19 @@ static bool construct(struct dc_sink *sink, const struct dc_sink_init_data *init void dc_sink_retain(struct dc_sink *sink) { - ASSERT(atomic_read(&sink->ref_count) > 0); - atomic_inc(&sink->ref_count); + kref_get(&sink->refcount); } -void dc_sink_release(struct dc_sink *sink) +static void dc_sink_free(struct kref *kref) { - ASSERT(atomic_read(&sink->ref_count) > 0); - atomic_dec(&sink->ref_count); + struct dc_sink *sink = container_of(kref, struct dc_sink, refcount); + destruct(sink); + kfree(sink); +} - if (atomic_read(&sink->ref_count) == 0) { - destruct(sink); - kfree(sink); - } +void dc_sink_release(struct dc_sink *sink) +{ + kref_put(&sink->refcount, dc_sink_free); } struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params) @@ -88,7 +88,7 @@ struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params) if (false == construct(sink, init_params)) goto construct_fail; - atomic_inc(&sink->ref_count); + kref_init(&sink->refcount); return sink; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 97f6f34f3d22..4ff543826476 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -971,7 +971,7 @@ struct dc_sink { struct dc_context *ctx; /* private to dc_sink.c */ - atomic_t ref_count; + struct kref refcount; }; void dc_sink_retain(struct dc_sink *sink); -- cgit From 8ee5702afdd48b5864c46418ad310d6a23c8e9ab Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 3 Oct 2017 12:39:02 +1000 Subject: amdgpu/dc: use kref for dc_state. I'm not a huge fan of those copying around refcounts bits, might want to consider alternates, but this should work for now. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 26 +++++++++++------------ drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 4 ++-- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 2 +- 3 files changed, 16 insertions(+), 16 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index d8820d6f79c6..f41f15faf019 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -940,25 +940,25 @@ struct dc_state *dc_create_state(void) if (!context) return NULL; - atomic_inc(&context->ref_count); + kref_init(&context->refcount); return context; } void dc_retain_state(struct dc_state *context) { - ASSERT(atomic_read(&context->ref_count) > 0); - atomic_inc(&context->ref_count); + kref_get(&context->refcount); } -void dc_release_state(struct dc_state *context) +static void dc_state_free(struct kref *kref) { - ASSERT(atomic_read(&context->ref_count) > 0); - atomic_dec(&context->ref_count); + struct dc_state *context = container_of(kref, struct dc_state, refcount); + dc_resource_state_destruct(context); + kfree(context); +} - if (atomic_read(&context->ref_count) == 0) { - dc_resource_state_destruct(context); - kfree(context); - } +void dc_release_state(struct dc_state *context) +{ + kref_put(&context->refcount, dc_state_free); } static bool is_surface_in_context( @@ -1520,7 +1520,7 @@ void dc_set_power_state( struct dc *dc, enum dc_acpi_cm_power_state power_state) { - atomic_t ref_count; + struct kref refcount; switch (power_state) { case DC_ACPI_CM_POWER_STATE_D0: @@ -1538,12 +1538,12 @@ void dc_set_power_state( */ /* Preserve refcount */ - ref_count = dc->current_state->ref_count; + refcount = dc->current_state->refcount; dc_resource_state_destruct(dc->current_state); memset(dc->current_state, 0, sizeof(*dc->current_state)); - dc->current_state->ref_count = ref_count; + dc->current_state->refcount = refcount; break; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 99a4d19f582d..77b3474a7c9e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -2432,7 +2432,7 @@ void dc_resource_state_copy_construct( struct dc_state *dst_ctx) { int i, j; - atomic_t ref_count = dst_ctx->ref_count; + struct kref refcount = dst_ctx->refcount; *dst_ctx = *src_ctx; @@ -2455,7 +2455,7 @@ void dc_resource_state_copy_construct( } /* context refcount should not be overridden */ - dst_ctx->ref_count = ref_count; + dst_ctx->refcount = refcount; } diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index c47ce6b9fc6b..ff23f268fe02 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -267,7 +267,7 @@ struct dc_state { struct display_clock *dis_clk; - atomic_t ref_count; + struct kref refcount; }; #endif /* _CORE_TYPES_H_ */ -- cgit From 9ba29fcb76a559078491adffc74f66bf92b9dbea Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 9 Oct 2017 10:33:04 +1000 Subject: drm/amd/display: Use DRM new-style object iterators. Use the correct for_each_new/old_* iterators instead of for_each_* The following functions were considered: amdgpu_dm_find_first_crtc_matching_connector: use for_each_new - Old from_state_var flag was always choosing the new state amdgpu_dm_display_resume: use for_each_new - drm_atomic_helper_duplicate_state is called during suspend to cache the state - It sets 'state' within the state triplet to 'new_state' amdgpu_dm_commit_planes: use for_each_old - Called after the state was swapped (via atomic commit tail) amdgpu_dm_atomic_commit: use for_each_new - Called before the state is swapped amdgpu_dm_atomic_commit_tail: use for_each_old - Called after the state was swapped dm_update_crtcs_state: use for_each_new - Called before the state is swapped (via atomic check) amdgpu_dm_atomic_check: use for_each_new - Called before the state is swapped v2: Split out typo fixes to a new patch. v3: Say "functions considered" instead of "affected functions". The latter implies that changes are made to each. [airlied: squashed with my hacks] Reviewed-by: Harry Wentland Reviewed-by: Maarten Lankhorst Signed-off-by: Leo (Sunpeng) Li Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 42 +++++++++-------------- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 3 +- 2 files changed, 17 insertions(+), 28 deletions(-) (limited to 'drivers/gpu') 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 4f8973182f8a..cc024abb14d5 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -570,23 +570,15 @@ static int dm_suspend(void *handle) struct amdgpu_dm_connector *amdgpu_dm_find_first_crct_matching_connector( struct drm_atomic_state *state, - struct drm_crtc *crtc, - bool from_state_var) + struct drm_crtc *crtc) { uint32_t i; struct drm_connector_state *conn_state; struct drm_connector *connector; struct drm_crtc *crtc_from_state; - for_each_connector_in_state( - state, - connector, - conn_state, - i) { - crtc_from_state = - from_state_var ? - conn_state->crtc : - connector->state->crtc; + for_each_new_connector_in_state(state, connector, conn_state, i) { + crtc_from_state = conn_state->crtc; if (crtc_from_state == crtc) return to_amdgpu_dm_connector(connector); @@ -652,7 +644,7 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev) } /* Force mode set in atomic comit */ - for_each_crtc_in_state(adev->dm.cached_state, crtc, crtc_state, i) + for_each_new_crtc_in_state(adev->dm.cached_state, crtc, crtc_state, i) crtc_state->active_changed = true; ret = drm_atomic_helper_resume(ddev, adev->dm.cached_state); @@ -3890,7 +3882,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, unsigned long flags; /* update planes when needed */ - for_each_plane_in_state(state, plane, old_plane_state, i) { + for_each_old_plane_in_state(state, plane, old_plane_state, i) { struct drm_plane_state *plane_state = plane->state; struct drm_crtc *crtc = plane_state->crtc; struct drm_framebuffer *fb = plane_state->fb; @@ -3987,7 +3979,7 @@ int amdgpu_dm_atomic_commit( * it will update crtc->dm_crtc_state->stream pointer which is used in * the ISRs. */ - for_each_crtc_in_state(state, crtc, new_state, i) { + for_each_new_crtc_in_state(state, crtc, new_state, i) { struct dm_crtc_state *old_acrtc_state = to_dm_crtc_state(crtc->state); struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); @@ -4024,7 +4016,7 @@ void amdgpu_dm_atomic_commit_tail( dm_state = to_dm_atomic_state(state); /* update changed items */ - for_each_crtc_in_state(state, crtc, old_crtc_state, i) { + for_each_old_crtc_in_state(state, crtc, old_crtc_state, i) { struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); struct drm_crtc_state *new_state = crtc->state; @@ -4113,11 +4105,9 @@ void amdgpu_dm_atomic_commit_tail( new_acrtc_state = to_dm_crtc_state(new_crtcs[i]->base.state); new_stream = new_acrtc_state->stream; - aconnector = - amdgpu_dm_find_first_crct_matching_connector( + aconnector = amdgpu_dm_find_first_crct_matching_connector( state, - &new_crtcs[i]->base, - false); + &new_crtcs[i]->base); if (!aconnector) { DRM_DEBUG_DRIVER("Atomic commit: Failed to find connector for acrtc id:%d " "skipping freesync init\n", @@ -4151,7 +4141,7 @@ void amdgpu_dm_atomic_commit_tail( } /* Handle scaling and undersacn changes*/ - for_each_connector_in_state(state, connector, old_conn_state, i) { + for_each_old_connector_in_state(state, connector, old_conn_state, i) { struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); struct dm_connector_state *con_new_state = to_dm_connector_state(aconnector->base.state); @@ -4205,7 +4195,7 @@ void amdgpu_dm_atomic_commit_tail( } /* update planes when needed per crtc*/ - for_each_crtc_in_state(state, pcrtc, old_crtc_state, j) { + for_each_old_crtc_in_state(state, pcrtc, old_crtc_state, j) { new_acrtc_state = to_dm_crtc_state(pcrtc->state); if (new_acrtc_state->stream) @@ -4218,7 +4208,7 @@ void amdgpu_dm_atomic_commit_tail( * mark consumed event for drm_atomic_helper_commit_hw_done */ spin_lock_irqsave(&adev->ddev->event_lock, flags); - for_each_crtc_in_state(state, crtc, old_crtc_state, i) { + for_each_old_crtc_in_state(state, crtc, old_crtc_state, i) { struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); if (acrtc->base.state->event) @@ -4390,7 +4380,7 @@ static int dm_update_crtcs_state( /*TODO Move this code into dm_crtc_atomic_check once we get rid of dc_validation_set */ /* update changed items */ - for_each_crtc_in_state(state, crtc, crtc_state, i) { + for_each_new_crtc_in_state(state, crtc, crtc_state, i) { struct amdgpu_crtc *acrtc = NULL; struct amdgpu_dm_connector *aconnector = NULL; struct drm_connector_state *conn_state = NULL; @@ -4402,7 +4392,7 @@ static int dm_update_crtcs_state( new_acrtc_state = to_dm_crtc_state(crtc_state); acrtc = to_amdgpu_crtc(crtc); - aconnector = amdgpu_dm_find_first_crct_matching_connector(state, crtc, true); + aconnector = amdgpu_dm_find_first_crct_matching_connector(state, crtc); /* TODO This hack should go away */ if (aconnector) { @@ -4674,7 +4664,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, * Hack: Commit needs planes right now, specifically for gamma * TODO rework commit to check CRTC for gamma change */ - for_each_crtc_in_state(state, crtc, crtc_state, i) { + for_each_new_crtc_in_state(state, crtc, crtc_state, i) { if (crtc_state->color_mgmt_changed) { ret = drm_atomic_add_affected_planes(state, crtc); if (ret) @@ -4720,7 +4710,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, * new stream into context w\o causing full reset. Need to * decide how to handle. */ - for_each_connector_in_state(state, connector, conn_state, i) { + for_each_new_connector_in_state(state, connector, conn_state, i) { struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); struct dm_connector_state *con_old_state = to_dm_connector_state(aconnector->base.state); 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 630e6cdf84f6..1c55a0b5cd15 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -228,8 +228,7 @@ void amdgpu_dm_update_connector_after_detect( struct amdgpu_dm_connector *amdgpu_dm_find_first_crct_matching_connector( struct drm_atomic_state *state, - struct drm_crtc *crtc, - bool from_state_var); + struct drm_crtc *crtc); struct amdgpu_framebuffer; -- cgit From 0bc9706db3a35b6d674d0642f425d768560736b2 Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Thu, 12 Oct 2017 17:15:07 -0400 Subject: drm/amd/display: Use new DRM API where possible To conform to DRM's new API, we should not be accessing a DRM object's internal state directly. Rather, the DRM for_each_old/new_* iterators, and drm_atomic_get_old/new_* interface should be used. This is an ongoing process. For now, update the DRM-facing atomic functions, where the atomic state object is given. Reviewed-by: Harry Wentland Reviewed-by: Maarten Lankhorst Signed-off-by: Leo (Sunpeng) Li Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 131 +++++++++++----------- 1 file changed, 66 insertions(+), 65 deletions(-) (limited to 'drivers/gpu') 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 cc024abb14d5..d4426b326918 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3873,28 +3873,31 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, { uint32_t i; struct drm_plane *plane; - struct drm_plane_state *old_plane_state; + struct drm_plane_state *old_plane_state, *new_plane_state; struct dc_stream_state *dc_stream_attach; struct dc_plane_state *plane_states_constructed[MAX_SURFACES]; struct amdgpu_crtc *acrtc_attach = to_amdgpu_crtc(pcrtc); - struct dm_crtc_state *acrtc_state = to_dm_crtc_state(pcrtc->state); + struct drm_crtc_state *new_pcrtc_state = + drm_atomic_get_new_crtc_state(state, pcrtc); + struct dm_crtc_state *acrtc_state = to_dm_crtc_state(new_pcrtc_state); int planes_count = 0; unsigned long flags; /* update planes when needed */ - for_each_old_plane_in_state(state, plane, old_plane_state, i) { - struct drm_plane_state *plane_state = plane->state; - struct drm_crtc *crtc = plane_state->crtc; - struct drm_framebuffer *fb = plane_state->fb; + for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) { + struct drm_crtc *crtc = new_plane_state->crtc; + struct drm_crtc_state *new_crtc_state = + drm_atomic_get_new_crtc_state(state, crtc); + struct drm_framebuffer *fb = new_plane_state->fb; bool pflip_needed; - struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state); + struct dm_plane_state *dm_plane_state = to_dm_plane_state(new_plane_state); if (plane->type == DRM_PLANE_TYPE_CURSOR) { handle_cursor_update(plane, old_plane_state); continue; } - if (!fb || !crtc || pcrtc != crtc || !crtc->state->active) + if (!fb || !crtc || pcrtc != crtc || !new_crtc_state->active) continue; pflip_needed = !state->allow_modeset; @@ -3918,13 +3921,13 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, dc_stream_attach = acrtc_state->stream; planes_count++; - } else if (crtc->state->planes_changed) { + } else if (new_crtc_state->planes_changed) { /* Assume even ONE crtc with immediate flip means * entire can't wait for VBLANK * TODO Check if it's correct */ *wait_for_vblank = - pcrtc->state->pageflip_flags & DRM_MODE_PAGE_FLIP_ASYNC ? + new_pcrtc_state->pageflip_flags & DRM_MODE_PAGE_FLIP_ASYNC ? false : true; /* TODO: Needs rework for multiplane flip */ @@ -3942,7 +3945,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, if (planes_count) { unsigned long flags; - if (pcrtc->state->event) { + if (new_pcrtc_state->event) { drm_crtc_vblank_get(pcrtc); @@ -3968,7 +3971,7 @@ int amdgpu_dm_atomic_commit( bool nonblock) { struct drm_crtc *crtc; - struct drm_crtc_state *new_state; + struct drm_crtc_state *old_crtc_state, *new_state; struct amdgpu_device *adev = dev->dev_private; int i; @@ -3979,8 +3982,8 @@ int amdgpu_dm_atomic_commit( * it will update crtc->dm_crtc_state->stream pointer which is used in * the ISRs. */ - for_each_new_crtc_in_state(state, crtc, new_state, i) { - struct dm_crtc_state *old_acrtc_state = to_dm_crtc_state(crtc->state); + for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_state, i) { + struct dm_crtc_state *old_acrtc_state = to_dm_crtc_state(old_crtc_state); struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); if (drm_atomic_crtc_needs_modeset(new_state) && old_acrtc_state->stream) @@ -4002,13 +4005,13 @@ void amdgpu_dm_atomic_commit_tail( uint32_t i, j; uint32_t new_crtcs_count = 0; struct drm_crtc *crtc, *pcrtc; - struct drm_crtc_state *old_crtc_state; + struct drm_crtc_state *old_crtc_state, *new_crtc_state; struct amdgpu_crtc *new_crtcs[MAX_STREAMS]; struct dc_stream_state *new_stream = NULL; unsigned long flags; bool wait_for_vblank = true; struct drm_connector *connector; - struct drm_connector_state *old_conn_state; + struct drm_connector_state *old_conn_state, *new_con_state; struct dm_crtc_state *old_acrtc_state, *new_acrtc_state; drm_atomic_helper_update_legacy_modeset_state(dev, state); @@ -4016,11 +4019,10 @@ void amdgpu_dm_atomic_commit_tail( dm_state = to_dm_atomic_state(state); /* update changed items */ - for_each_old_crtc_in_state(state, crtc, old_crtc_state, i) { + for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - struct drm_crtc_state *new_state = crtc->state; - new_acrtc_state = to_dm_crtc_state(new_state); + new_acrtc_state = to_dm_crtc_state(new_crtc_state); old_acrtc_state = to_dm_crtc_state(old_crtc_state); DRM_DEBUG_DRIVER( @@ -4028,18 +4030,18 @@ void amdgpu_dm_atomic_commit_tail( "planes_changed:%d, mode_changed:%d,active_changed:%d," "connectors_changed:%d\n", acrtc->crtc_id, - new_state->enable, - new_state->active, - new_state->planes_changed, - new_state->mode_changed, - new_state->active_changed, - new_state->connectors_changed); + new_crtc_state->enable, + new_crtc_state->active, + new_crtc_state->planes_changed, + new_crtc_state->mode_changed, + new_crtc_state->active_changed, + new_crtc_state->connectors_changed); /* handles headless hotplug case, updating new_state and * aconnector as needed */ - if (modeset_required(new_state, new_acrtc_state->stream, old_acrtc_state->stream)) { + if (modeset_required(new_crtc_state, new_acrtc_state->stream, old_acrtc_state->stream)) { DRM_DEBUG_DRIVER("Atomic commit: SET crtc id %d: [%p]\n", acrtc->crtc_id, acrtc); @@ -4082,10 +4084,11 @@ void amdgpu_dm_atomic_commit_tail( new_crtcs[new_crtcs_count] = acrtc; new_crtcs_count++; + new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc); acrtc->enabled = true; - acrtc->hw_mode = crtc->state->mode; - crtc->hwmode = crtc->state->mode; - } else if (modereset_required(new_state)) { + acrtc->hw_mode = new_crtc_state->mode; + crtc->hwmode = new_crtc_state->mode; + } else if (modereset_required(new_crtc_state)) { DRM_DEBUG_DRIVER("Atomic commit: RESET. crtc id %d:[%p]\n", acrtc->crtc_id, acrtc); /* i.e. reset mode */ @@ -4102,7 +4105,9 @@ void amdgpu_dm_atomic_commit_tail( for (i = 0; i < new_crtcs_count; i++) { struct amdgpu_dm_connector *aconnector = NULL; - new_acrtc_state = to_dm_crtc_state(new_crtcs[i]->base.state); + new_crtc_state = drm_atomic_get_new_crtc_state(state, + &new_crtcs[i]->base); + new_acrtc_state = to_dm_crtc_state(new_crtc_state); new_stream = new_acrtc_state->stream; aconnector = amdgpu_dm_find_first_crct_matching_connector( @@ -4123,11 +4128,10 @@ void amdgpu_dm_atomic_commit_tail( if (dm_state->context) WARN_ON(!dc_commit_state(dm->dc, dm_state->context)); - - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - new_acrtc_state = to_dm_crtc_state(crtc->state); + new_acrtc_state = to_dm_crtc_state(new_crtc_state); if (new_acrtc_state->stream != NULL) { const struct dc_stream_status *status = @@ -4141,24 +4145,24 @@ void amdgpu_dm_atomic_commit_tail( } /* Handle scaling and undersacn changes*/ - for_each_old_connector_in_state(state, connector, old_conn_state, i) { - struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); - struct dm_connector_state *con_new_state = - to_dm_connector_state(aconnector->base.state); - struct dm_connector_state *con_old_state = - to_dm_connector_state(old_conn_state); + for_each_oldnew_connector_in_state(state, connector, old_conn_state, new_con_state, i) { + struct dm_connector_state *con_new_state = to_dm_connector_state(new_con_state); + struct dm_connector_state *con_old_state = to_dm_connector_state(old_conn_state); struct amdgpu_crtc *acrtc = to_amdgpu_crtc(con_new_state->base.crtc); struct dc_stream_status *status = NULL; + if (acrtc) + new_crtc_state = drm_atomic_get_new_crtc_state(state, &acrtc->base); + /* Skip any modesets/resets */ - if (!acrtc || drm_atomic_crtc_needs_modeset(acrtc->base.state)) + if (!acrtc || drm_atomic_crtc_needs_modeset(new_crtc_state)) continue; /* Skip any thing not scale or underscan changes */ if (!is_scaling_state_different(con_new_state, con_old_state)) continue; - new_acrtc_state = to_dm_crtc_state(acrtc->base.state); + new_acrtc_state = to_dm_crtc_state(new_crtc_state); update_stream_scaling_settings(&con_new_state->base.crtc->mode, con_new_state, (struct dc_stream_state *)new_acrtc_state->stream); @@ -4185,7 +4189,8 @@ void amdgpu_dm_atomic_commit_tail( */ struct amdgpu_crtc *acrtc = new_crtcs[i]; - new_acrtc_state = to_dm_crtc_state(acrtc->base.state); + new_crtc_state = drm_atomic_get_new_crtc_state(state, &acrtc->base); + new_acrtc_state = to_dm_crtc_state(new_crtc_state); if (adev->dm.freesync_module) mod_freesync_notify_mode_change( @@ -4195,8 +4200,8 @@ void amdgpu_dm_atomic_commit_tail( } /* update planes when needed per crtc*/ - for_each_old_crtc_in_state(state, pcrtc, old_crtc_state, j) { - new_acrtc_state = to_dm_crtc_state(pcrtc->state); + for_each_new_crtc_in_state(state, pcrtc, new_crtc_state, j) { + new_acrtc_state = to_dm_crtc_state(new_crtc_state); if (new_acrtc_state->stream) amdgpu_dm_commit_planes(state, dev, dm, pcrtc, &wait_for_vblank); @@ -4208,13 +4213,12 @@ void amdgpu_dm_atomic_commit_tail( * mark consumed event for drm_atomic_helper_commit_hw_done */ spin_lock_irqsave(&adev->ddev->event_lock, flags); - for_each_old_crtc_in_state(state, crtc, old_crtc_state, i) { - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { - if (acrtc->base.state->event) - drm_send_event_locked(dev, &crtc->state->event->base); + if (new_crtc_state->event) + drm_send_event_locked(dev, &new_crtc_state->event->base); - acrtc->base.state->event = NULL; + new_crtc_state->event = NULL; } spin_unlock_irqrestore(&adev->ddev->event_lock, flags); @@ -4371,7 +4375,7 @@ static int dm_update_crtcs_state( bool *lock_and_validation_needed) { struct drm_crtc *crtc; - struct drm_crtc_state *crtc_state; + struct drm_crtc_state *old_crtc_state, *crtc_state; int i; struct dm_crtc_state *old_acrtc_state, *new_acrtc_state; struct dm_atomic_state *dm_state = to_dm_atomic_state(state); @@ -4380,7 +4384,7 @@ static int dm_update_crtcs_state( /*TODO Move this code into dm_crtc_atomic_check once we get rid of dc_validation_set */ /* update changed items */ - for_each_new_crtc_in_state(state, crtc, crtc_state, i) { + for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, crtc_state, i) { struct amdgpu_crtc *acrtc = NULL; struct amdgpu_dm_connector *aconnector = NULL; struct drm_connector_state *conn_state = NULL; @@ -4388,7 +4392,7 @@ static int dm_update_crtcs_state( new_stream = NULL; - old_acrtc_state = to_dm_crtc_state(crtc->state); + old_acrtc_state = to_dm_crtc_state(old_crtc_state); new_acrtc_state = to_dm_crtc_state(crtc_state); acrtc = to_amdgpu_crtc(crtc); @@ -4521,7 +4525,7 @@ static int dm_update_planes_state( bool *lock_and_validation_needed) { struct drm_crtc *new_plane_crtc, *old_plane_crtc; - struct drm_crtc_state *new_crtc_state; + struct drm_crtc_state *old_crtc_state, *new_crtc_state; struct drm_plane *plane; struct drm_plane_state *old_plane_state, *new_plane_state; struct dm_crtc_state *new_acrtc_state, *old_acrtc_state; @@ -4552,10 +4556,9 @@ static int dm_update_planes_state( if (!old_plane_crtc) continue; - old_acrtc_state = to_dm_crtc_state( - drm_atomic_get_old_crtc_state( - state, - old_plane_crtc)); + old_crtc_state = drm_atomic_get_old_crtc_state( + state, old_plane_crtc); + old_acrtc_state = to_dm_crtc_state(old_crtc_state); if (!old_acrtc_state->stream) continue; @@ -4643,7 +4646,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, struct dc *dc = adev->dm.dc; struct dm_atomic_state *dm_state = to_dm_atomic_state(state); struct drm_connector *connector; - struct drm_connector_state *conn_state; + struct drm_connector_state *old_con_state, *conn_state; struct drm_crtc *crtc; struct drm_crtc_state *crtc_state; @@ -4710,16 +4713,14 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, * new stream into context w\o causing full reset. Need to * decide how to handle. */ - for_each_new_connector_in_state(state, connector, conn_state, i) { - struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); - struct dm_connector_state *con_old_state = - to_dm_connector_state(aconnector->base.state); - struct dm_connector_state *con_new_state = - to_dm_connector_state(conn_state); + for_each_oldnew_connector_in_state(state, connector, old_con_state, conn_state, i) { + struct dm_connector_state *con_old_state = to_dm_connector_state(old_con_state); + struct dm_connector_state *con_new_state = to_dm_connector_state(conn_state); struct amdgpu_crtc *acrtc = to_amdgpu_crtc(con_new_state->base.crtc); /* Skip any modesets/resets */ - if (!acrtc || drm_atomic_crtc_needs_modeset(acrtc->base.state)) + if (!acrtc || drm_atomic_crtc_needs_modeset( + drm_atomic_get_new_crtc_state(state, &acrtc->base))) continue; /* Skip any thing not scale or underscan changes */ -- cgit From c2cea7063b85fc2bcec92997a808f1d3a16f8052 Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Thu, 12 Oct 2017 17:15:08 -0400 Subject: drm/amd/display: Unify DRM state variable namings. Use new_*_state and old_*_state for their respective new/old DRM object states. Reviewed-by: Maarten Lankhorst Reviewed-by: Harry Wentland Signed-off-by: Leo (Sunpeng) Li Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 80 +++++++++++------------ 1 file changed, 40 insertions(+), 40 deletions(-) (limited to 'drivers/gpu') 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 d4426b326918..fe0b658cf3a6 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -573,12 +573,12 @@ struct amdgpu_dm_connector *amdgpu_dm_find_first_crct_matching_connector( struct drm_crtc *crtc) { uint32_t i; - struct drm_connector_state *conn_state; + struct drm_connector_state *new_con_state; struct drm_connector *connector; struct drm_crtc *crtc_from_state; - for_each_new_connector_in_state(state, connector, conn_state, i) { - crtc_from_state = conn_state->crtc; + for_each_new_connector_in_state(state, connector, new_con_state, i) { + crtc_from_state = new_con_state->crtc; if (crtc_from_state == crtc) return to_amdgpu_dm_connector(connector); @@ -608,7 +608,7 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev) struct amdgpu_dm_connector *aconnector; struct drm_connector *connector; struct drm_crtc *crtc; - struct drm_crtc_state *crtc_state; + struct drm_crtc_state *new_crtc_state; int ret = 0; int i; @@ -644,8 +644,8 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev) } /* Force mode set in atomic comit */ - for_each_new_crtc_in_state(adev->dm.cached_state, crtc, crtc_state, i) - crtc_state->active_changed = true; + for_each_new_crtc_in_state(adev->dm.cached_state, crtc, new_crtc_state, i) + new_crtc_state->active_changed = true; ret = drm_atomic_helper_resume(ddev, adev->dm.cached_state); @@ -3971,7 +3971,7 @@ int amdgpu_dm_atomic_commit( bool nonblock) { struct drm_crtc *crtc; - struct drm_crtc_state *old_crtc_state, *new_state; + struct drm_crtc_state *old_crtc_state, *new_crtc_state; struct amdgpu_device *adev = dev->dev_private; int i; @@ -3982,11 +3982,11 @@ int amdgpu_dm_atomic_commit( * it will update crtc->dm_crtc_state->stream pointer which is used in * the ISRs. */ - for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_state, i) { + for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { struct dm_crtc_state *old_acrtc_state = to_dm_crtc_state(old_crtc_state); struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - if (drm_atomic_crtc_needs_modeset(new_state) && old_acrtc_state->stream) + if (drm_atomic_crtc_needs_modeset(new_crtc_state) && old_acrtc_state->stream) manage_dm_interrupts(adev, acrtc, false); } @@ -4011,7 +4011,7 @@ void amdgpu_dm_atomic_commit_tail( unsigned long flags; bool wait_for_vblank = true; struct drm_connector *connector; - struct drm_connector_state *old_conn_state, *new_con_state; + struct drm_connector_state *old_con_state, *new_con_state; struct dm_crtc_state *old_acrtc_state, *new_acrtc_state; drm_atomic_helper_update_legacy_modeset_state(dev, state); @@ -4145,9 +4145,9 @@ void amdgpu_dm_atomic_commit_tail( } /* Handle scaling and undersacn changes*/ - for_each_oldnew_connector_in_state(state, connector, old_conn_state, new_con_state, i) { + for_each_oldnew_connector_in_state(state, connector, old_con_state, new_con_state, i) { struct dm_connector_state *con_new_state = to_dm_connector_state(new_con_state); - struct dm_connector_state *con_old_state = to_dm_connector_state(old_conn_state); + struct dm_connector_state *con_old_state = to_dm_connector_state(old_con_state); struct amdgpu_crtc *acrtc = to_amdgpu_crtc(con_new_state->base.crtc); struct dc_stream_status *status = NULL; @@ -4375,7 +4375,7 @@ static int dm_update_crtcs_state( bool *lock_and_validation_needed) { struct drm_crtc *crtc; - struct drm_crtc_state *old_crtc_state, *crtc_state; + struct drm_crtc_state *old_crtc_state, *new_crtc_state; int i; struct dm_crtc_state *old_acrtc_state, *new_acrtc_state; struct dm_atomic_state *dm_state = to_dm_atomic_state(state); @@ -4384,34 +4384,34 @@ static int dm_update_crtcs_state( /*TODO Move this code into dm_crtc_atomic_check once we get rid of dc_validation_set */ /* update changed items */ - for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, crtc_state, i) { + for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { struct amdgpu_crtc *acrtc = NULL; struct amdgpu_dm_connector *aconnector = NULL; - struct drm_connector_state *conn_state = NULL; + struct drm_connector_state *new_con_state = NULL; struct dm_connector_state *dm_conn_state = NULL; new_stream = NULL; old_acrtc_state = to_dm_crtc_state(old_crtc_state); - new_acrtc_state = to_dm_crtc_state(crtc_state); + new_acrtc_state = to_dm_crtc_state(new_crtc_state); acrtc = to_amdgpu_crtc(crtc); aconnector = amdgpu_dm_find_first_crct_matching_connector(state, crtc); /* TODO This hack should go away */ if (aconnector) { - conn_state = drm_atomic_get_connector_state(state, - &aconnector->base); + new_con_state = drm_atomic_get_connector_state(state, + &aconnector->base); - if (IS_ERR(conn_state)) { - ret = PTR_ERR_OR_ZERO(conn_state); + if (IS_ERR(new_con_state)) { + ret = PTR_ERR_OR_ZERO(new_con_state); break; } - dm_conn_state = to_dm_connector_state(conn_state); + dm_conn_state = to_dm_connector_state(new_con_state); new_stream = create_stream_for_sink(aconnector, - &crtc_state->mode, + &new_crtc_state->mode, dm_conn_state); /* @@ -4431,14 +4431,14 @@ static int dm_update_crtcs_state( if (dc_is_stream_unchanged(new_stream, old_acrtc_state->stream)) { - crtc_state->mode_changed = false; + new_crtc_state->mode_changed = false; - DRM_DEBUG_DRIVER("Mode change not required, setting mode_changed to %d", - crtc_state->mode_changed); + DRM_DEBUG_DRIVER("Mode change not required, setting mode_changed to %d", + new_crtc_state->mode_changed); } - if (!drm_atomic_crtc_needs_modeset(crtc_state)) + if (!drm_atomic_crtc_needs_modeset(new_crtc_state)) goto next_crtc; DRM_DEBUG_DRIVER( @@ -4446,12 +4446,12 @@ static int dm_update_crtcs_state( "planes_changed:%d, mode_changed:%d,active_changed:%d," "connectors_changed:%d\n", acrtc->crtc_id, - crtc_state->enable, - crtc_state->active, - crtc_state->planes_changed, - crtc_state->mode_changed, - crtc_state->active_changed, - crtc_state->connectors_changed); + new_crtc_state->enable, + new_crtc_state->active, + new_crtc_state->planes_changed, + new_crtc_state->mode_changed, + new_crtc_state->active_changed, + new_crtc_state->connectors_changed); /* Remove stream for any changed/disabled CRTC */ if (!enable) { @@ -4478,10 +4478,10 @@ static int dm_update_crtcs_state( } else {/* Add stream for any updated/enabled CRTC */ - if (modereset_required(crtc_state)) + if (modereset_required(new_crtc_state)) goto next_crtc; - if (modeset_required(crtc_state, new_stream, + if (modeset_required(new_crtc_state, new_stream, old_acrtc_state->stream)) { WARN_ON(new_acrtc_state->stream); @@ -4646,9 +4646,9 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, struct dc *dc = adev->dm.dc; struct dm_atomic_state *dm_state = to_dm_atomic_state(state); struct drm_connector *connector; - struct drm_connector_state *old_con_state, *conn_state; + struct drm_connector_state *old_con_state, *new_con_state; struct drm_crtc *crtc; - struct drm_crtc_state *crtc_state; + struct drm_crtc_state *new_crtc_state; /* * This bool will be set for true for any modeset/reset @@ -4667,8 +4667,8 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, * Hack: Commit needs planes right now, specifically for gamma * TODO rework commit to check CRTC for gamma change */ - for_each_new_crtc_in_state(state, crtc, crtc_state, i) { - if (crtc_state->color_mgmt_changed) { + for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { + if (new_crtc_state->color_mgmt_changed) { ret = drm_atomic_add_affected_planes(state, crtc); if (ret) goto fail; @@ -4713,9 +4713,9 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, * new stream into context w\o causing full reset. Need to * decide how to handle. */ - for_each_oldnew_connector_in_state(state, connector, old_con_state, conn_state, i) { + for_each_oldnew_connector_in_state(state, connector, old_con_state, new_con_state, i) { struct dm_connector_state *con_old_state = to_dm_connector_state(old_con_state); - struct dm_connector_state *con_new_state = to_dm_connector_state(conn_state); + struct dm_connector_state *con_new_state = to_dm_connector_state(new_con_state); struct amdgpu_crtc *acrtc = to_amdgpu_crtc(con_new_state->base.crtc); /* Skip any modesets/resets */ -- cgit From 54d76575246798f5f42ca56fe5d54d1f195198b2 Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Thu, 12 Oct 2017 17:15:09 -0400 Subject: drm/amd/display: Unify amdgpu_dm state variable namings. Use dm_new_*_state and dm_old_*_state for their respective amdgpu_dm new and old object states. Helps with readability, and enforces use of new DRM api (choose either new, or old). Reviewed-by: Maarten Lankhorst Reviewed-by: Harry Wentland Signed-off-by: Leo (Sunpeng) Li Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 137 +++++++++++----------- 1 file changed, 68 insertions(+), 69 deletions(-) (limited to 'drivers/gpu') 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 fe0b658cf3a6..de88ee1af438 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3890,7 +3890,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, drm_atomic_get_new_crtc_state(state, crtc); struct drm_framebuffer *fb = new_plane_state->fb; bool pflip_needed; - struct dm_plane_state *dm_plane_state = to_dm_plane_state(new_plane_state); + struct dm_plane_state *dm_new_plane_state = to_dm_plane_state(new_plane_state); if (plane->type == DRM_PLANE_TYPE_CURSOR) { handle_cursor_update(plane, old_plane_state); @@ -3914,9 +3914,9 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, spin_unlock_irqrestore(&crtc->dev->event_lock, flags); if (!pflip_needed) { - WARN_ON(!dm_plane_state->dc_state); + WARN_ON(!dm_new_plane_state->dc_state); - plane_states_constructed[planes_count] = dm_plane_state->dc_state; + plane_states_constructed[planes_count] = dm_new_plane_state->dc_state; dc_stream_attach = acrtc_state->stream; planes_count++; @@ -3983,10 +3983,10 @@ int amdgpu_dm_atomic_commit( * the ISRs. */ for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { - struct dm_crtc_state *old_acrtc_state = to_dm_crtc_state(old_crtc_state); + struct dm_crtc_state *dm_old_crtc_state = to_dm_crtc_state(old_crtc_state); struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - if (drm_atomic_crtc_needs_modeset(new_crtc_state) && old_acrtc_state->stream) + if (drm_atomic_crtc_needs_modeset(new_crtc_state) && dm_old_crtc_state->stream) manage_dm_interrupts(adev, acrtc, false); } @@ -4012,7 +4012,7 @@ void amdgpu_dm_atomic_commit_tail( bool wait_for_vblank = true; struct drm_connector *connector; struct drm_connector_state *old_con_state, *new_con_state; - struct dm_crtc_state *old_acrtc_state, *new_acrtc_state; + struct dm_crtc_state *dm_old_crtc_state, *dm_new_crtc_state; drm_atomic_helper_update_legacy_modeset_state(dev, state); @@ -4022,8 +4022,8 @@ void amdgpu_dm_atomic_commit_tail( for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - new_acrtc_state = to_dm_crtc_state(new_crtc_state); - old_acrtc_state = to_dm_crtc_state(old_crtc_state); + dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); + dm_old_crtc_state = to_dm_crtc_state(old_crtc_state); DRM_DEBUG_DRIVER( "amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, " @@ -4041,11 +4041,11 @@ void amdgpu_dm_atomic_commit_tail( * aconnector as needed */ - if (modeset_required(new_crtc_state, new_acrtc_state->stream, old_acrtc_state->stream)) { + if (modeset_required(new_crtc_state, dm_new_crtc_state->stream, dm_old_crtc_state->stream)) { DRM_DEBUG_DRIVER("Atomic commit: SET crtc id %d: [%p]\n", acrtc->crtc_id, acrtc); - if (!new_acrtc_state->stream) { + if (!dm_new_crtc_state->stream) { /* * this could happen because of issues with * userspace notifications delivery. @@ -4067,8 +4067,8 @@ void amdgpu_dm_atomic_commit_tail( } - if (old_acrtc_state->stream) - remove_stream(adev, acrtc, old_acrtc_state->stream); + if (dm_old_crtc_state->stream) + remove_stream(adev, acrtc, dm_old_crtc_state->stream); /* @@ -4092,8 +4092,8 @@ void amdgpu_dm_atomic_commit_tail( DRM_DEBUG_DRIVER("Atomic commit: RESET. crtc id %d:[%p]\n", acrtc->crtc_id, acrtc); /* i.e. reset mode */ - if (old_acrtc_state->stream) - remove_stream(adev, acrtc, old_acrtc_state->stream); + if (dm_old_crtc_state->stream) + remove_stream(adev, acrtc, dm_old_crtc_state->stream); } } /* for_each_crtc_in_state() */ @@ -4107,9 +4107,9 @@ void amdgpu_dm_atomic_commit_tail( new_crtc_state = drm_atomic_get_new_crtc_state(state, &new_crtcs[i]->base); - new_acrtc_state = to_dm_crtc_state(new_crtc_state); + dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); - new_stream = new_acrtc_state->stream; + new_stream = dm_new_crtc_state->stream; aconnector = amdgpu_dm_find_first_crct_matching_connector( state, &new_crtcs[i]->base); @@ -4131,14 +4131,14 @@ void amdgpu_dm_atomic_commit_tail( for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - new_acrtc_state = to_dm_crtc_state(new_crtc_state); + dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); - if (new_acrtc_state->stream != NULL) { + if (dm_new_crtc_state->stream != NULL) { const struct dc_stream_status *status = - dc_stream_get_status(new_acrtc_state->stream); + dc_stream_get_status(dm_new_crtc_state->stream); if (!status) - DC_ERR("got no status for stream %p on acrtc%p\n", new_acrtc_state->stream, acrtc); + DC_ERR("got no status for stream %p on acrtc%p\n", dm_new_crtc_state->stream, acrtc); else acrtc->otg_inst = status->primary_otg_inst; } @@ -4146,9 +4146,9 @@ void amdgpu_dm_atomic_commit_tail( /* Handle scaling and undersacn changes*/ for_each_oldnew_connector_in_state(state, connector, old_con_state, new_con_state, i) { - struct dm_connector_state *con_new_state = to_dm_connector_state(new_con_state); - struct dm_connector_state *con_old_state = to_dm_connector_state(old_con_state); - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(con_new_state->base.crtc); + struct dm_connector_state *dm_new_con_state = to_dm_connector_state(new_con_state); + struct dm_connector_state *dm_old_con_state = to_dm_connector_state(old_con_state); + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(dm_new_con_state->base.crtc); struct dc_stream_status *status = NULL; if (acrtc) @@ -4159,19 +4159,19 @@ void amdgpu_dm_atomic_commit_tail( continue; /* Skip any thing not scale or underscan changes */ - if (!is_scaling_state_different(con_new_state, con_old_state)) + if (!is_scaling_state_different(dm_new_con_state, dm_old_con_state)) continue; - new_acrtc_state = to_dm_crtc_state(new_crtc_state); + dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); - update_stream_scaling_settings(&con_new_state->base.crtc->mode, - con_new_state, (struct dc_stream_state *)new_acrtc_state->stream); + update_stream_scaling_settings(&dm_new_con_state->base.crtc->mode, + dm_new_con_state, (struct dc_stream_state *)dm_new_crtc_state->stream); - status = dc_stream_get_status(new_acrtc_state->stream); + status = dc_stream_get_status(dm_new_crtc_state->stream); WARN_ON(!status); WARN_ON(!status->plane_count); - if (!new_acrtc_state->stream) + if (!dm_new_crtc_state->stream) continue; /*TODO How it works with MPO ?*/ @@ -4179,7 +4179,7 @@ void amdgpu_dm_atomic_commit_tail( dm->dc, status->plane_states, status->plane_count, - new_acrtc_state->stream)) + dm_new_crtc_state->stream)) dm_error("%s: Failed to update stream scaling!\n", __func__); } @@ -4190,20 +4190,20 @@ void amdgpu_dm_atomic_commit_tail( struct amdgpu_crtc *acrtc = new_crtcs[i]; new_crtc_state = drm_atomic_get_new_crtc_state(state, &acrtc->base); - new_acrtc_state = to_dm_crtc_state(new_crtc_state); + dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); if (adev->dm.freesync_module) mod_freesync_notify_mode_change( - adev->dm.freesync_module, &new_acrtc_state->stream, 1); + adev->dm.freesync_module, &dm_new_crtc_state->stream, 1); manage_dm_interrupts(adev, acrtc, true); } /* update planes when needed per crtc*/ for_each_new_crtc_in_state(state, pcrtc, new_crtc_state, j) { - new_acrtc_state = to_dm_crtc_state(new_crtc_state); + dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); - if (new_acrtc_state->stream) + if (dm_new_crtc_state->stream) amdgpu_dm_commit_planes(state, dev, dm, pcrtc, &wait_for_vblank); } @@ -4377,7 +4377,7 @@ static int dm_update_crtcs_state( struct drm_crtc *crtc; struct drm_crtc_state *old_crtc_state, *new_crtc_state; int i; - struct dm_crtc_state *old_acrtc_state, *new_acrtc_state; + struct dm_crtc_state *dm_old_crtc_state, *dm_new_crtc_state; struct dm_atomic_state *dm_state = to_dm_atomic_state(state); struct dc_stream_state *new_stream; int ret = 0; @@ -4392,8 +4392,8 @@ static int dm_update_crtcs_state( new_stream = NULL; - old_acrtc_state = to_dm_crtc_state(old_crtc_state); - new_acrtc_state = to_dm_crtc_state(new_crtc_state); + dm_old_crtc_state = to_dm_crtc_state(old_crtc_state); + dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); acrtc = to_amdgpu_crtc(crtc); aconnector = amdgpu_dm_find_first_crct_matching_connector(state, crtc); @@ -4428,8 +4428,7 @@ static int dm_update_crtcs_state( } } - if (dc_is_stream_unchanged(new_stream, - old_acrtc_state->stream)) { + if (dc_is_stream_unchanged(new_stream, dm_old_crtc_state->stream)) { new_crtc_state->mode_changed = false; @@ -4456,7 +4455,7 @@ static int dm_update_crtcs_state( /* Remove stream for any changed/disabled CRTC */ if (!enable) { - if (!old_acrtc_state->stream) + if (!dm_old_crtc_state->stream) goto next_crtc; DRM_DEBUG_DRIVER("Disabling DRM crtc: %d\n", @@ -4466,13 +4465,13 @@ static int dm_update_crtcs_state( if (!dc_remove_stream_from_ctx( dc, dm_state->context, - old_acrtc_state->stream)) { + dm_old_crtc_state->stream)) { ret = -EINVAL; goto fail; } - dc_stream_release(old_acrtc_state->stream); - new_acrtc_state->stream = NULL; + dc_stream_release(dm_old_crtc_state->stream); + dm_new_crtc_state->stream = NULL; *lock_and_validation_needed = true; @@ -4482,11 +4481,11 @@ static int dm_update_crtcs_state( goto next_crtc; if (modeset_required(new_crtc_state, new_stream, - old_acrtc_state->stream)) { + dm_old_crtc_state->stream)) { - WARN_ON(new_acrtc_state->stream); + WARN_ON(dm_new_crtc_state->stream); - new_acrtc_state->stream = new_stream; + dm_new_crtc_state->stream = new_stream; dc_stream_retain(new_stream); DRM_DEBUG_DRIVER("Enabling DRM crtc: %d\n", @@ -4495,7 +4494,7 @@ static int dm_update_crtcs_state( if (!dc_add_stream_to_ctx( dc, dm_state->context, - new_acrtc_state->stream)) { + dm_new_crtc_state->stream)) { ret = -EINVAL; goto fail; } @@ -4528,9 +4527,9 @@ static int dm_update_planes_state( struct drm_crtc_state *old_crtc_state, *new_crtc_state; struct drm_plane *plane; struct drm_plane_state *old_plane_state, *new_plane_state; - struct dm_crtc_state *new_acrtc_state, *old_acrtc_state; + struct dm_crtc_state *dm_new_crtc_state, *dm_old_crtc_state; struct dm_atomic_state *dm_state = to_dm_atomic_state(state); - struct dm_plane_state *new_dm_plane_state, *old_dm_plane_state; + struct dm_plane_state *dm_new_plane_state, *dm_old_plane_state; int i ; /* TODO return page_flip_needed() function */ bool pflip_needed = !state->allow_modeset; @@ -4543,8 +4542,8 @@ static int dm_update_planes_state( for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) { new_plane_crtc = new_plane_state->crtc; old_plane_crtc = old_plane_state->crtc; - new_dm_plane_state = to_dm_plane_state(new_plane_state); - old_dm_plane_state = to_dm_plane_state(old_plane_state); + dm_new_plane_state = to_dm_plane_state(new_plane_state); + dm_old_plane_state = to_dm_plane_state(old_plane_state); /*TODO Implement atomic check for cursor plane */ if (plane->type == DRM_PLANE_TYPE_CURSOR) @@ -4558,9 +4557,9 @@ static int dm_update_planes_state( old_crtc_state = drm_atomic_get_old_crtc_state( state, old_plane_crtc); - old_acrtc_state = to_dm_crtc_state(old_crtc_state); + dm_old_crtc_state = to_dm_crtc_state(old_crtc_state); - if (!old_acrtc_state->stream) + if (!dm_old_crtc_state->stream) continue; DRM_DEBUG_DRIVER("Disabling DRM plane: %d on DRM crtc %d\n", @@ -4568,8 +4567,8 @@ static int dm_update_planes_state( if (!dc_remove_plane_from_context( dc, - old_acrtc_state->stream, - old_dm_plane_state->dc_state, + dm_old_crtc_state->stream, + dm_old_plane_state->dc_state, dm_state->context)) { ret = EINVAL; @@ -4577,8 +4576,8 @@ static int dm_update_planes_state( } - dc_plane_state_release(old_dm_plane_state->dc_state); - new_dm_plane_state->dc_state = NULL; + dc_plane_state_release(dm_old_plane_state->dc_state); + dm_new_plane_state->dc_state = NULL; *lock_and_validation_needed = true; @@ -4591,27 +4590,27 @@ static int dm_update_planes_state( continue; new_crtc_state = drm_atomic_get_new_crtc_state(state, new_plane_crtc); - new_acrtc_state = to_dm_crtc_state(new_crtc_state); + dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); - if (!new_acrtc_state->stream) + if (!dm_new_crtc_state->stream) continue; - WARN_ON(new_dm_plane_state->dc_state); + WARN_ON(dm_new_plane_state->dc_state); - new_dm_plane_state->dc_state = dc_create_plane_state(dc); + dm_new_plane_state->dc_state = dc_create_plane_state(dc); DRM_DEBUG_DRIVER("Enabling DRM plane: %d on DRM crtc %d\n", plane->base.id, new_plane_crtc->base.id); - if (!new_dm_plane_state->dc_state) { + if (!dm_new_plane_state->dc_state) { ret = -EINVAL; return ret; } ret = fill_plane_attributes( new_plane_crtc->dev->dev_private, - new_dm_plane_state->dc_state, + dm_new_plane_state->dc_state, new_plane_state, new_crtc_state, false); @@ -4621,8 +4620,8 @@ static int dm_update_planes_state( if (!dc_add_plane_to_context( dc, - new_acrtc_state->stream, - new_dm_plane_state->dc_state, + dm_new_crtc_state->stream, + dm_new_plane_state->dc_state, dm_state->context)) { ret = -EINVAL; @@ -4714,9 +4713,9 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, * decide how to handle. */ for_each_oldnew_connector_in_state(state, connector, old_con_state, new_con_state, i) { - struct dm_connector_state *con_old_state = to_dm_connector_state(old_con_state); - struct dm_connector_state *con_new_state = to_dm_connector_state(new_con_state); - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(con_new_state->base.crtc); + struct dm_connector_state *dm_old_con_state = to_dm_connector_state(old_con_state); + struct dm_connector_state *dm_new_con_state = to_dm_connector_state(new_con_state); + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(dm_new_con_state->base.crtc); /* Skip any modesets/resets */ if (!acrtc || drm_atomic_crtc_needs_modeset( @@ -4724,7 +4723,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, continue; /* Skip any thing not scale or underscan changes */ - if (!is_scaling_state_different(con_new_state, con_old_state)) + if (!is_scaling_state_different(dm_new_con_state, dm_old_con_state)) continue; lock_and_validation_needed = true; -- cgit From ebdd27e1a5440cb3f30952d105eb08cadafc431d Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Thu, 12 Oct 2017 17:15:10 -0400 Subject: drm/amd/display: Fix typo undersacn -> underscan Reviewed-by: Maarten Lankhorst Reviewed-by: Harry Wentland Reviewed-by: Alex Deucher Signed-off-by: Leo (Sunpeng) Li Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') 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 de88ee1af438..67222ffac96a 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4144,7 +4144,7 @@ void amdgpu_dm_atomic_commit_tail( } } - /* Handle scaling and undersacn changes*/ + /* Handle scaling and underscan changes*/ for_each_oldnew_connector_in_state(state, connector, old_con_state, new_con_state, i) { struct dm_connector_state *dm_new_con_state = to_dm_connector_state(new_con_state); struct dm_connector_state *dm_old_con_state = to_dm_connector_state(old_con_state); @@ -4707,7 +4707,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, if (ret) goto fail; - /* Check scaling and undersacn changes*/ + /* Check scaling and underscan changes*/ /*TODO Removed scaling changes validation due to inability to commit * new stream into context w\o causing full reset. Need to * decide how to handle. -- cgit From 5cc6dcbd45a60be4800cd5cc9a30bcc2e158e6a1 Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Thu, 12 Oct 2017 17:15:11 -0400 Subject: drm/amd/display: Remove useless pcrtc pointer in amdgpu_dm_atomic_commit_tail. Just use crtc instead. Reviewed-by: Maarten Lankhorst Reviewed-by: Harry Wentland Reviewed-by: Alex Deucher Signed-off-by: Leo (Sunpeng) Li Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') 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 67222ffac96a..f9b57697be70 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4004,7 +4004,7 @@ void amdgpu_dm_atomic_commit_tail( struct dm_atomic_state *dm_state; uint32_t i, j; uint32_t new_crtcs_count = 0; - struct drm_crtc *crtc, *pcrtc; + struct drm_crtc *crtc; struct drm_crtc_state *old_crtc_state, *new_crtc_state; struct amdgpu_crtc *new_crtcs[MAX_STREAMS]; struct dc_stream_state *new_stream = NULL; @@ -4200,11 +4200,11 @@ void amdgpu_dm_atomic_commit_tail( } /* update planes when needed per crtc*/ - for_each_new_crtc_in_state(state, pcrtc, new_crtc_state, j) { + for_each_new_crtc_in_state(state, crtc, new_crtc_state, j) { dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); if (dm_new_crtc_state->stream) - amdgpu_dm_commit_planes(state, dev, dm, pcrtc, &wait_for_vblank); + amdgpu_dm_commit_planes(state, dev, dm, crtc, &wait_for_vblank); } -- cgit From 1daf8c63480b35b967a63a40457c1b0ad866ee81 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 13 Oct 2017 14:04:26 -0400 Subject: drm/amd/display: fix typo in function name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit s/amdgpu_dm_find_first_crct_matching_connector/ amdgpu_dm_find_first_crtc_matching_connector/ And while here, make it static. Reviewed-by: Harry Wentland Acked-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 10 +++++----- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 5 ----- 2 files changed, 5 insertions(+), 10 deletions(-) (limited to 'drivers/gpu') 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 f9b57697be70..c2031eb5833f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -568,9 +568,9 @@ static int dm_suspend(void *handle) return ret; } -struct amdgpu_dm_connector *amdgpu_dm_find_first_crct_matching_connector( - struct drm_atomic_state *state, - struct drm_crtc *crtc) +static struct amdgpu_dm_connector * +amdgpu_dm_find_first_crtc_matching_connector(struct drm_atomic_state *state, + struct drm_crtc *crtc) { uint32_t i; struct drm_connector_state *new_con_state; @@ -4110,7 +4110,7 @@ void amdgpu_dm_atomic_commit_tail( dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); new_stream = dm_new_crtc_state->stream; - aconnector = amdgpu_dm_find_first_crct_matching_connector( + aconnector = amdgpu_dm_find_first_crtc_matching_connector( state, &new_crtcs[i]->base); if (!aconnector) { @@ -4396,7 +4396,7 @@ static int dm_update_crtcs_state( dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); acrtc = to_amdgpu_crtc(crtc); - aconnector = amdgpu_dm_find_first_crct_matching_connector(state, crtc); + aconnector = amdgpu_dm_find_first_crtc_matching_connector(state, crtc); /* TODO This hack should go away */ if (aconnector) { 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 1c55a0b5cd15..aca061aa4643 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -226,11 +226,6 @@ extern const struct amdgpu_ip_block_version dm_ip_block; void amdgpu_dm_update_connector_after_detect( struct amdgpu_dm_connector *aconnector); -struct amdgpu_dm_connector *amdgpu_dm_find_first_crct_matching_connector( - struct drm_atomic_state *state, - struct drm_crtc *crtc); - - struct amdgpu_framebuffer; struct amdgpu_display_manager; struct dc_validation_set; -- cgit From 3ee6b26b78e47825032726f807beb70be86ea20a Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 10 Oct 2017 17:44:52 -0400 Subject: drm/amd/display: whitespace cleanup in amdgpu_dm.c/h To match kernel standards. No intended functional change. Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 330 ++++++++++------------ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 91 +++--- 2 files changed, 192 insertions(+), 229 deletions(-) (limited to 'drivers/gpu') 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 c2031eb5833f..f282fe8d5089 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -127,7 +127,7 @@ static u32 dm_vblank_get_counter(struct amdgpu_device *adev, int crtc) } static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc, - u32 *vbl, u32 *position) + u32 *vbl, u32 *position) { uint32_t v_blank_start, v_blank_end, h_position, v_position; @@ -184,9 +184,9 @@ static int dm_soft_reset(void *handle) return 0; } -static struct amdgpu_crtc *get_crtc_by_otg_inst( - struct amdgpu_device *adev, - int otg_inst) +static struct amdgpu_crtc * +get_crtc_by_otg_inst(struct amdgpu_device *adev, + int otg_inst) { struct drm_device *dev = adev->ddev; struct drm_crtc *crtc; @@ -738,8 +738,8 @@ static struct drm_mode_config_helper_funcs amdgpu_dm_mode_config_helperfuncs = { .atomic_commit_tail = amdgpu_dm_atomic_commit_tail }; -void amdgpu_dm_update_connector_after_detect( - struct amdgpu_dm_connector *aconnector) +void +amdgpu_dm_update_connector_after_detect(struct amdgpu_dm_connector *aconnector) { struct drm_connector *connector = &aconnector->base; struct drm_device *dev = connector->dev; @@ -1490,11 +1490,10 @@ static const struct amdgpu_display_funcs dm_display_funcs = { #if defined(CONFIG_DEBUG_KERNEL_DC) -static ssize_t s3_debug_store( - struct device *device, - struct device_attribute *attr, - const char *buf, - size_t count) +static ssize_t s3_debug_store(struct device *device, + struct device_attribute *attr, + const char *buf, + size_t count) { int ret; int s3_state; @@ -1670,9 +1669,8 @@ static const struct drm_encoder_funcs amdgpu_dm_encoder_funcs = { .destroy = amdgpu_dm_encoder_destroy, }; -static bool fill_rects_from_plane_state( - const struct drm_plane_state *state, - struct dc_plane_state *plane_state) +static bool fill_rects_from_plane_state(const struct drm_plane_state *state, + struct dc_plane_state *plane_state) { plane_state->src_rect.x = state->src_x >> 16; plane_state->src_rect.y = state->src_y >> 16; @@ -1721,10 +1719,9 @@ static bool fill_rects_from_plane_state( return true; } -static int get_fb_info( - const struct amdgpu_framebuffer *amdgpu_fb, - uint64_t *tiling_flags, - uint64_t *fb_location) +static int get_fb_info(const struct amdgpu_framebuffer *amdgpu_fb, + uint64_t *tiling_flags, + uint64_t *fb_location) { struct amdgpu_bo *rbo = gem_to_amdgpu_bo(amdgpu_fb->obj); int r = amdgpu_bo_reserve(rbo, false); @@ -1745,10 +1742,10 @@ static int get_fb_info( return r; } -static int fill_plane_attributes_from_fb( - struct amdgpu_device *adev, - struct dc_plane_state *plane_state, - const struct amdgpu_framebuffer *amdgpu_fb, bool addReq) +static int fill_plane_attributes_from_fb(struct amdgpu_device *adev, + struct dc_plane_state *plane_state, + const struct amdgpu_framebuffer *amdgpu_fb, + bool addReq) { uint64_t tiling_flags; uint64_t fb_location = 0; @@ -1897,9 +1894,8 @@ static int fill_plane_attributes_from_fb( } -static void fill_gamma_from_crtc_state( - const struct drm_crtc_state *crtc_state, - struct dc_plane_state *plane_state) +static void fill_gamma_from_crtc_state(const struct drm_crtc_state *crtc_state, + struct dc_plane_state *plane_state) { int i; struct dc_gamma *gamma; @@ -1924,12 +1920,11 @@ static void fill_gamma_from_crtc_state( plane_state->gamma_correction = gamma; } -static int fill_plane_attributes( - struct amdgpu_device *adev, - struct dc_plane_state *dc_plane_state, - struct drm_plane_state *plane_state, - struct drm_crtc_state *crtc_state, - bool addrReq) +static int fill_plane_attributes(struct amdgpu_device *adev, + struct dc_plane_state *dc_plane_state, + struct drm_plane_state *plane_state, + struct drm_crtc_state *crtc_state, + bool addrReq) { const struct amdgpu_framebuffer *amdgpu_fb = to_amdgpu_framebuffer(plane_state->fb); @@ -1968,8 +1963,8 @@ static int fill_plane_attributes( /*****************************************************************************/ -struct amdgpu_dm_connector *aconnector_from_drm_crtc_id( - const struct drm_crtc *crtc) +struct amdgpu_dm_connector * +aconnector_from_drm_crtc_id(const struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; struct drm_connector *connector; @@ -1992,10 +1987,9 @@ struct amdgpu_dm_connector *aconnector_from_drm_crtc_id( return NULL; } -static void update_stream_scaling_settings( - const struct drm_display_mode *mode, - const struct dm_connector_state *dm_state, - struct dc_stream_state *stream) +static void update_stream_scaling_settings(const struct drm_display_mode *mode, + const struct dm_connector_state *dm_state, + struct dc_stream_state *stream) { enum amdgpu_rmx_type rmx_type; @@ -2046,8 +2040,8 @@ static void update_stream_scaling_settings( } -static enum dc_color_depth convert_color_depth_from_display_info( - const struct drm_connector *connector) +static enum dc_color_depth +convert_color_depth_from_display_info(const struct drm_connector *connector) { uint32_t bpc = connector->display_info.bpc; @@ -2081,8 +2075,8 @@ static enum dc_color_depth convert_color_depth_from_display_info( } } -static enum dc_aspect_ratio get_aspect_ratio( - const struct drm_display_mode *mode_in) +static enum dc_aspect_ratio +get_aspect_ratio(const struct drm_display_mode *mode_in) { int32_t width = mode_in->crtc_hdisplay * 9; int32_t height = mode_in->crtc_vdisplay * 16; @@ -2093,8 +2087,8 @@ static enum dc_aspect_ratio get_aspect_ratio( return ASPECT_RATIO_4_3; } -static enum dc_color_space get_output_color_space( - const struct dc_crtc_timing *dc_crtc_timing) +static enum dc_color_space +get_output_color_space(const struct dc_crtc_timing *dc_crtc_timing) { enum dc_color_space color_space = COLOR_SPACE_SRGB; @@ -2138,10 +2132,10 @@ static enum dc_color_space get_output_color_space( /*****************************************************************************/ -static void fill_stream_properties_from_drm_display_mode( - struct dc_stream_state *stream, - const struct drm_display_mode *mode_in, - const struct drm_connector *connector) +static void +fill_stream_properties_from_drm_display_mode(struct dc_stream_state *stream, + const struct drm_display_mode *mode_in, + const struct drm_connector *connector) { struct dc_crtc_timing *timing_out = &stream->timing; @@ -2196,10 +2190,9 @@ static void fill_stream_properties_from_drm_display_mode( } } -static void fill_audio_info( - struct audio_info *audio_info, - const struct drm_connector *drm_connector, - const struct dc_sink *dc_sink) +static void fill_audio_info(struct audio_info *audio_info, + const struct drm_connector *drm_connector, + const struct dc_sink *dc_sink) { int i = 0; int cea_revision = 0; @@ -2244,9 +2237,9 @@ static void fill_audio_info( } -static void copy_crtc_timing_for_drm_display_mode( - const struct drm_display_mode *src_mode, - struct drm_display_mode *dst_mode) +static void +copy_crtc_timing_for_drm_display_mode(const struct drm_display_mode *src_mode, + struct drm_display_mode *dst_mode) { dst_mode->crtc_hdisplay = src_mode->crtc_hdisplay; dst_mode->crtc_vdisplay = src_mode->crtc_vdisplay; @@ -2264,10 +2257,10 @@ static void copy_crtc_timing_for_drm_display_mode( dst_mode->crtc_vtotal = src_mode->crtc_vtotal; } -static void decide_crtc_timing_for_drm_display_mode( - struct drm_display_mode *drm_mode, - const struct drm_display_mode *native_mode, - bool scale_enabled) +static void +decide_crtc_timing_for_drm_display_mode(struct drm_display_mode *drm_mode, + const struct drm_display_mode *native_mode, + bool scale_enabled) { if (scale_enabled) { copy_crtc_timing_for_drm_display_mode(native_mode, drm_mode); @@ -2299,10 +2292,10 @@ static void create_fake_sink(struct amdgpu_dm_connector *aconnector) aconnector->dc_link->local_sink = sink; } -static struct dc_stream_state *create_stream_for_sink( - struct amdgpu_dm_connector *aconnector, - const struct drm_display_mode *drm_mode, - const struct dm_connector_state *dm_state) +static struct dc_stream_state * +create_stream_for_sink(struct amdgpu_dm_connector *aconnector, + const struct drm_display_mode *drm_mode, + const struct dm_connector_state *dm_state) { struct drm_display_mode *preferred_mode = NULL; const struct drm_connector *drm_connector; @@ -2380,7 +2373,7 @@ void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc) } static void dm_crtc_destroy_state(struct drm_crtc *crtc, - struct drm_crtc_state *state) + struct drm_crtc_state *state) { struct dm_crtc_state *cur = to_dm_crtc_state(state); @@ -2466,11 +2459,10 @@ amdgpu_dm_connector_detect(struct drm_connector *connector, bool force) connector_status_disconnected); } -int amdgpu_dm_connector_atomic_set_property( - struct drm_connector *connector, - struct drm_connector_state *connector_state, - struct drm_property *property, - uint64_t val) +int amdgpu_dm_connector_atomic_set_property(struct drm_connector *connector, + struct drm_connector_state *connector_state, + struct drm_property *property, + uint64_t val) { struct drm_device *dev = connector->dev; struct amdgpu_device *adev = dev->dev_private; @@ -2519,11 +2511,10 @@ int amdgpu_dm_connector_atomic_set_property( return ret; } -int amdgpu_dm_connector_atomic_get_property( - struct drm_connector *connector, - const struct drm_connector_state *state, - struct drm_property *property, - uint64_t *val) +int amdgpu_dm_connector_atomic_get_property(struct drm_connector *connector, + const struct drm_connector_state *state, + struct drm_property *property, + uint64_t *val) { struct drm_device *dev = connector->dev; struct amdgpu_device *adev = dev->dev_private; @@ -2605,8 +2596,8 @@ void amdgpu_dm_connector_funcs_reset(struct drm_connector *connector) } } -struct drm_connector_state *amdgpu_dm_connector_atomic_duplicate_state( - struct drm_connector *connector) +struct drm_connector_state * +amdgpu_dm_connector_atomic_duplicate_state(struct drm_connector *connector) { struct dm_connector_state *state = to_dm_connector_state(connector->state); @@ -2711,9 +2702,8 @@ static void handle_edid_mgmt(struct amdgpu_dm_connector *aconnector) create_eml_sink(aconnector); } -int amdgpu_dm_connector_mode_valid( - struct drm_connector *connector, - struct drm_display_mode *mode) +int amdgpu_dm_connector_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) { int result = MODE_ERROR; struct dc_sink *dc_sink; @@ -2780,9 +2770,8 @@ static void dm_crtc_helper_disable(struct drm_crtc *crtc) { } -static int dm_crtc_helper_atomic_check( - struct drm_crtc *crtc, - struct drm_crtc_state *state) +static int dm_crtc_helper_atomic_check(struct drm_crtc *crtc, + struct drm_crtc_state *state) { struct amdgpu_device *adev = crtc->dev->dev_private; struct dc *dc = adev->dm.dc; @@ -2805,10 +2794,9 @@ static int dm_crtc_helper_atomic_check( return ret; } -static bool dm_crtc_helper_mode_fixup( - struct drm_crtc *crtc, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) +static bool dm_crtc_helper_mode_fixup(struct drm_crtc *crtc, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) { return true; } @@ -2824,10 +2812,9 @@ static void dm_encoder_helper_disable(struct drm_encoder *encoder) } -static int dm_encoder_helper_atomic_check( - struct drm_encoder *encoder, - struct drm_crtc_state *crtc_state, - struct drm_connector_state *conn_state) +static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) { return 0; } @@ -2875,7 +2862,7 @@ dm_drm_plane_duplicate_state(struct drm_plane *plane) } void dm_drm_plane_destroy_state(struct drm_plane *plane, - struct drm_plane_state *state) + struct drm_plane_state *state) { struct dm_plane_state *dm_plane_state = to_dm_plane_state(state); @@ -2894,9 +2881,8 @@ static const struct drm_plane_funcs dm_plane_funcs = { .atomic_destroy_state = dm_drm_plane_destroy_state, }; -static int dm_plane_helper_prepare_fb( - struct drm_plane *plane, - struct drm_plane_state *new_state) +static int dm_plane_helper_prepare_fb(struct drm_plane *plane, + struct drm_plane_state *new_state) { struct amdgpu_framebuffer *afb; struct drm_gem_object *obj; @@ -2964,9 +2950,8 @@ static int dm_plane_helper_prepare_fb( return 0; } -static void dm_plane_helper_cleanup_fb( - struct drm_plane *plane, - struct drm_plane_state *old_state) +static void dm_plane_helper_cleanup_fb(struct drm_plane *plane, + struct drm_plane_state *old_state) { struct amdgpu_bo *rbo; struct amdgpu_framebuffer *afb; @@ -2989,7 +2974,8 @@ static void dm_plane_helper_cleanup_fb( } int dm_create_validation_set_for_connector(struct drm_connector *connector, - struct drm_display_mode *mode, struct dc_validation_set *val_set) + struct drm_display_mode *mode, + struct dc_validation_set *val_set) { int result = MODE_ERROR; struct dc_sink *dc_sink = @@ -3027,7 +3013,7 @@ int dm_create_validation_set_for_connector(struct drm_connector *connector, } int dm_plane_atomic_check(struct drm_plane *plane, - struct drm_plane_state *state) + struct drm_plane_state *state) { struct amdgpu_device *adev = plane->dev->dev_private; struct dc *dc = adev->dm.dc; @@ -3075,8 +3061,8 @@ static const u32 cursor_formats[] = { }; int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, - struct amdgpu_plane *aplane, - unsigned long possible_crtcs) + struct amdgpu_plane *aplane, + unsigned long possible_crtcs) { int res = -EPERM; @@ -3224,9 +3210,10 @@ static void amdgpu_dm_get_native_mode(struct drm_connector *connector) } } -static struct drm_display_mode *amdgpu_dm_create_common_mode( - struct drm_encoder *encoder, char *name, - int hdisplay, int vdisplay) +static struct drm_display_mode * +amdgpu_dm_create_common_mode(struct drm_encoder *encoder, + char *name, + int hdisplay, int vdisplay) { struct drm_device *dev = encoder->dev; struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); @@ -3248,7 +3235,7 @@ static struct drm_display_mode *amdgpu_dm_create_common_mode( } static void amdgpu_dm_connector_add_common_modes(struct drm_encoder *encoder, - struct drm_connector *connector) + struct drm_connector *connector) { struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct drm_display_mode *mode = NULL; @@ -3306,9 +3293,8 @@ static void amdgpu_dm_connector_add_common_modes(struct drm_encoder *encoder, } } -static void amdgpu_dm_connector_ddc_get_modes( - struct drm_connector *connector, - struct edid *edid) +static void amdgpu_dm_connector_ddc_get_modes(struct drm_connector *connector, + struct edid *edid) { struct amdgpu_dm_connector *amdgpu_dm_connector = to_amdgpu_dm_connector(connector); @@ -3342,12 +3328,11 @@ int amdgpu_dm_connector_get_modes(struct drm_connector *connector) return amdgpu_dm_connector->num_modes; } -void amdgpu_dm_connector_init_helper( - struct amdgpu_display_manager *dm, - struct amdgpu_dm_connector *aconnector, - int connector_type, - struct dc_link *link, - int link_index) +void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm, + struct amdgpu_dm_connector *aconnector, + int connector_type, + struct dc_link *link, + int link_index) { struct amdgpu_device *adev = dm->ddev->dev_private; @@ -3395,7 +3380,7 @@ void amdgpu_dm_connector_init_helper( } int amdgpu_dm_i2c_xfer(struct i2c_adapter *i2c_adap, - struct i2c_msg *msgs, int num) + struct i2c_msg *msgs, int num) { struct amdgpu_i2c_adapter *i2c = i2c_get_adapdata(i2c_adap); struct ddc_service *ddc_service = i2c->ddc_service; @@ -3439,10 +3424,10 @@ static const struct i2c_algorithm amdgpu_dm_i2c_algo = { .functionality = amdgpu_dm_i2c_func, }; -static struct amdgpu_i2c_adapter *create_i2c( - struct ddc_service *ddc_service, - int link_index, - int *res) +static struct amdgpu_i2c_adapter * +create_i2c(struct ddc_service *ddc_service, + int link_index, + int *res) { struct amdgpu_device *adev = ddc_service->ctx->driver_context; struct amdgpu_i2c_adapter *i2c; @@ -3462,11 +3447,10 @@ static struct amdgpu_i2c_adapter *create_i2c( /* Note: this function assumes that dc_link_detect() was called for the * dc_link which will be represented by this aconnector. */ -int amdgpu_dm_connector_init( - struct amdgpu_display_manager *dm, - struct amdgpu_dm_connector *aconnector, - uint32_t link_index, - struct amdgpu_encoder *aencoder) +int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm, + struct amdgpu_dm_connector *aconnector, + uint32_t link_index, + struct amdgpu_encoder *aencoder) { int res = 0; int connector_type; @@ -3569,10 +3553,9 @@ int amdgpu_dm_get_encoder_crtc_mask(struct amdgpu_device *adev) } } -int amdgpu_dm_encoder_init( - struct drm_device *dev, - struct amdgpu_encoder *aencoder, - uint32_t link_index) +int amdgpu_dm_encoder_init(struct drm_device *dev, + struct amdgpu_encoder *aencoder, + uint32_t link_index) { struct amdgpu_device *adev = dev->dev_private; @@ -3594,10 +3577,9 @@ int amdgpu_dm_encoder_init( return res; } -static void manage_dm_interrupts( - struct amdgpu_device *adev, - struct amdgpu_crtc *acrtc, - bool enable) +static void manage_dm_interrupts(struct amdgpu_device *adev, + struct amdgpu_crtc *acrtc, + bool enable) { /* * this is not correct translation but will work as soon as VBLANK @@ -3624,9 +3606,9 @@ static void manage_dm_interrupts( } } -static bool is_scaling_state_different( - const struct dm_connector_state *dm_state, - const struct dm_connector_state *old_dm_state) +static bool +is_scaling_state_different(const struct dm_connector_state *dm_state, + const struct dm_connector_state *old_dm_state) { if (dm_state->scaling != old_dm_state->scaling) return true; @@ -3642,10 +3624,9 @@ static bool is_scaling_state_different( return false; } -static void remove_stream( - struct amdgpu_device *adev, - struct amdgpu_crtc *acrtc, - struct dc_stream_state *stream) +static void remove_stream(struct amdgpu_device *adev, + struct amdgpu_crtc *acrtc, + struct dc_stream_state *stream) { /* this is the update mode case */ if (adev->dm.freesync_module) @@ -3656,7 +3637,7 @@ static void remove_stream( } int get_cursor_position(struct drm_plane *plane, struct drm_crtc *crtc, - struct dc_cursor_position *position) + struct dc_cursor_position *position) { struct amdgpu_crtc *amdgpu_crtc = amdgpu_crtc = to_amdgpu_crtc(crtc); int x, y; @@ -3700,9 +3681,8 @@ int get_cursor_position(struct drm_plane *plane, struct drm_crtc *crtc, return 0; } -static void handle_cursor_update( - struct drm_plane *plane, - struct drm_plane_state *old_plane_state) +static void handle_cursor_update(struct drm_plane *plane, + struct drm_plane_state *old_plane_state) { struct amdgpu_framebuffer *afb = to_amdgpu_framebuffer(plane->state->fb); struct drm_crtc *crtc = afb ? plane->state->crtc : old_plane_state->crtc; @@ -3780,10 +3760,9 @@ static void prepare_flip_isr(struct amdgpu_crtc *acrtc) * * Waits on all BO's fences and for proper vblank count */ -static void amdgpu_dm_do_flip( - struct drm_crtc *crtc, - struct drm_framebuffer *fb, - uint32_t target) +static void amdgpu_dm_do_flip(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + uint32_t target) { unsigned long flags; uint32_t target_vblank; @@ -3866,10 +3845,10 @@ static void amdgpu_dm_do_flip( } static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, - struct drm_device *dev, - struct amdgpu_display_manager *dm, - struct drm_crtc *pcrtc, - bool *wait_for_vblank) + struct drm_device *dev, + struct amdgpu_display_manager *dm, + struct drm_crtc *pcrtc, + bool *wait_for_vblank) { uint32_t i; struct drm_plane *plane; @@ -3965,10 +3944,9 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, } -int amdgpu_dm_atomic_commit( - struct drm_device *dev, - struct drm_atomic_state *state, - bool nonblock) +int amdgpu_dm_atomic_commit(struct drm_device *dev, + struct drm_atomic_state *state, + bool nonblock) { struct drm_crtc *crtc; struct drm_crtc_state *old_crtc_state, *new_crtc_state; @@ -3995,8 +3973,7 @@ int amdgpu_dm_atomic_commit( /*TODO Handle EINTR, reenable IRQ*/ } -void amdgpu_dm_atomic_commit_tail( - struct drm_atomic_state *state) +void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) { struct drm_device *dev = state->dev; struct amdgpu_device *adev = dev->dev_private; @@ -4294,7 +4271,8 @@ err: * This include when the same display is unplugged then plugged back into the * same port and when we are running without usermode desktop manager supprot */ -void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector *connector) +void dm_restore_drm_connector_state(struct drm_device *dev, + struct drm_connector *connector) { struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); struct amdgpu_crtc *disconnected_acrtc; @@ -4322,9 +4300,8 @@ void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector * Grabs all modesetting locks to serialize against any blocking commits, * Waits for completion of all non blocking commits. */ -static int do_aquire_global_lock( - struct drm_device *dev, - struct drm_atomic_state *state) +static int do_aquire_global_lock(struct drm_device *dev, + struct drm_atomic_state *state) { struct drm_crtc *crtc; struct drm_crtc_commit *commit; @@ -4368,11 +4345,10 @@ static int do_aquire_global_lock( return ret < 0 ? ret : 0; } -static int dm_update_crtcs_state( - struct dc *dc, - struct drm_atomic_state *state, - bool enable, - bool *lock_and_validation_needed) +static int dm_update_crtcs_state(struct dc *dc, + struct drm_atomic_state *state, + bool enable, + bool *lock_and_validation_needed) { struct drm_crtc *crtc; struct drm_crtc_state *old_crtc_state, *new_crtc_state; @@ -4517,11 +4493,10 @@ fail: return ret; } -static int dm_update_planes_state( - struct dc *dc, - struct drm_atomic_state *state, - bool enable, - bool *lock_and_validation_needed) +static int dm_update_planes_state(struct dc *dc, + struct drm_atomic_state *state, + bool enable, + bool *lock_and_validation_needed) { struct drm_crtc *new_plane_crtc, *old_plane_crtc; struct drm_crtc_state *old_crtc_state, *new_crtc_state; @@ -4637,7 +4612,7 @@ static int dm_update_planes_state( } int amdgpu_dm_atomic_check(struct drm_device *dev, - struct drm_atomic_state *state) + struct drm_atomic_state *state) { int i; int ret; @@ -4766,9 +4741,8 @@ fail: return ret; } -static bool is_dp_capable_without_timing_msa( - struct dc *dc, - struct amdgpu_dm_connector *amdgpu_dm_connector) +static bool is_dp_capable_without_timing_msa(struct dc *dc, + struct amdgpu_dm_connector *amdgpu_dm_connector) { uint8_t dpcd_data; bool capable = false; @@ -4785,9 +4759,8 @@ static bool is_dp_capable_without_timing_msa( return capable; } -void amdgpu_dm_add_sink_to_freesync_module( - struct drm_connector *connector, - struct edid *edid) +void amdgpu_dm_add_sink_to_freesync_module(struct drm_connector *connector, + struct edid *edid) { int i; uint64_t val_capable; @@ -4867,8 +4840,7 @@ void amdgpu_dm_add_sink_to_freesync_module( } -void amdgpu_dm_remove_sink_from_freesync_module( - struct drm_connector *connector) +void amdgpu_dm_remove_sink_from_freesync_module(struct drm_connector *connector) { /* * TODO fill in once we figure out how to deal with freesync in 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 aca061aa4643..eb20642403ae 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -206,12 +206,10 @@ void amdgpu_dm_destroy(void); * * Returns 0 on success */ -int amdgpu_dm_initialize_drm_device( - struct amdgpu_device *adev); +int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev); /* removes and deallocates the drm structures, created by the above function */ -void amdgpu_dm_destroy_drm_device( - struct amdgpu_display_manager *dm); +void amdgpu_dm_destroy_drm_device(struct amdgpu_display_manager *dm); /* Locking/Mutex */ bool amdgpu_dm_acquire_dal_lock(struct amdgpu_display_manager *dm); @@ -223,8 +221,8 @@ void amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm); extern const struct amdgpu_ip_block_version dm_ip_block; -void amdgpu_dm_update_connector_after_detect( - struct amdgpu_dm_connector *aconnector); +void +amdgpu_dm_update_connector_after_detect(struct amdgpu_dm_connector *aconnector); struct amdgpu_framebuffer; struct amdgpu_display_manager; @@ -256,19 +254,18 @@ struct dm_atomic_state { /*TODO Jodan Hersen use the one in amdgpu_dm*/ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, - struct amdgpu_plane *aplane, - unsigned long possible_crtcs); + struct amdgpu_plane *aplane, + unsigned long possible_crtcs); int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, struct drm_plane *plane, uint32_t link_index); int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm, - struct amdgpu_dm_connector *amdgpu_dm_connector, - uint32_t link_index, - struct amdgpu_encoder *amdgpu_encoder); -int amdgpu_dm_encoder_init( - struct drm_device *dev, - struct amdgpu_encoder *aencoder, - uint32_t link_index); + struct amdgpu_dm_connector *amdgpu_dm_connector, + uint32_t link_index, + struct amdgpu_encoder *amdgpu_encoder); +int amdgpu_dm_encoder_init(struct drm_device *dev, + struct amdgpu_encoder *aencoder, + uint32_t link_index); void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc); void amdgpu_dm_connector_destroy(struct drm_connector *connector); @@ -276,53 +273,47 @@ void amdgpu_dm_encoder_destroy(struct drm_encoder *encoder); int amdgpu_dm_connector_get_modes(struct drm_connector *connector); -int amdgpu_dm_atomic_commit( - struct drm_device *dev, - struct drm_atomic_state *state, - bool nonblock); +int amdgpu_dm_atomic_commit(struct drm_device *dev, + struct drm_atomic_state *state, + bool nonblock); -void amdgpu_dm_atomic_commit_tail( - struct drm_atomic_state *state); +void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state); int amdgpu_dm_atomic_check(struct drm_device *dev, - struct drm_atomic_state *state); + struct drm_atomic_state *state); void amdgpu_dm_connector_funcs_reset(struct drm_connector *connector); -struct drm_connector_state *amdgpu_dm_connector_atomic_duplicate_state( - struct drm_connector *connector); -int amdgpu_dm_connector_atomic_set_property( - struct drm_connector *connector, - struct drm_connector_state *state, - struct drm_property *property, - uint64_t val); - -int amdgpu_dm_connector_atomic_get_property( - struct drm_connector *connector, - const struct drm_connector_state *state, - struct drm_property *property, - uint64_t *val); +struct drm_connector_state * +amdgpu_dm_connector_atomic_duplicate_state(struct drm_connector *connector); +int amdgpu_dm_connector_atomic_set_property(struct drm_connector *connector, + struct drm_connector_state *state, + struct drm_property *property, + uint64_t val); + +int amdgpu_dm_connector_atomic_get_property(struct drm_connector *connector, + const struct drm_connector_state *state, + struct drm_property *property, + uint64_t *val); int amdgpu_dm_get_encoder_crtc_mask(struct amdgpu_device *adev); -void amdgpu_dm_connector_init_helper( - struct amdgpu_display_manager *dm, - struct amdgpu_dm_connector *aconnector, - int connector_type, - struct dc_link *link, - int link_index); +void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm, + struct amdgpu_dm_connector *aconnector, + int connector_type, + struct dc_link *link, + int link_index); -int amdgpu_dm_connector_mode_valid( - struct drm_connector *connector, - struct drm_display_mode *mode); +int amdgpu_dm_connector_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode); -void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector *connector); +void dm_restore_drm_connector_state(struct drm_device *dev, + struct drm_connector *connector); -void amdgpu_dm_add_sink_to_freesync_module( - struct drm_connector *connector, - struct edid *edid); +void amdgpu_dm_add_sink_to_freesync_module(struct drm_connector *connector, + struct edid *edid); -void amdgpu_dm_remove_sink_from_freesync_module( - struct drm_connector *connector); +void +amdgpu_dm_remove_sink_from_freesync_module(struct drm_connector *connector); extern const struct drm_encoder_helper_funcs amdgpu_dm_encoder_helper_funcs; -- cgit From 7578ecda14d521f39e74166103270c62b15af96d Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 10 Oct 2017 17:51:02 -0400 Subject: drm/amd/display: make a bunch of stuff in amdgpu_dm.c static Not used outside of that file. Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 136 +++++++++++++++------- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 59 ---------- 2 files changed, 91 insertions(+), 104 deletions(-) (limited to 'drivers/gpu') 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 f282fe8d5089..051cb371e88b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -70,6 +70,50 @@ #include "i2caux_interface.h" +/* basic init/fini API */ +static int amdgpu_dm_init(struct amdgpu_device *adev); +static void amdgpu_dm_fini(struct amdgpu_device *adev); + +/* initializes drm_device display related structures, based on the information + * provided by DAL. The drm strcutures are: drm_crtc, drm_connector, + * drm_encoder, drm_mode_config + * + * Returns 0 on success + */ +static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev); +/* removes and deallocates the drm structures, created by the above function */ +static void amdgpu_dm_destroy_drm_device(struct amdgpu_display_manager *dm); + +static void +amdgpu_dm_update_connector_after_detect(struct amdgpu_dm_connector *aconnector); + +static int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, + struct amdgpu_plane *aplane, + unsigned long possible_crtcs); +static int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, + struct drm_plane *plane, + uint32_t link_index); +static int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm, + struct amdgpu_dm_connector *amdgpu_dm_connector, + uint32_t link_index, + struct amdgpu_encoder *amdgpu_encoder); +static int amdgpu_dm_encoder_init(struct drm_device *dev, + struct amdgpu_encoder *aencoder, + uint32_t link_index); + +static int amdgpu_dm_connector_get_modes(struct drm_connector *connector); + +static int amdgpu_dm_atomic_commit(struct drm_device *dev, + struct drm_atomic_state *state, + bool nonblock); + +static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state); + +static int amdgpu_dm_atomic_check(struct drm_device *dev, + struct drm_atomic_state *state); + + + static const enum drm_plane_type dm_plane_type_default[AMDGPU_MAX_PLANES] = { DRM_PLANE_TYPE_PRIMARY, @@ -306,7 +350,7 @@ static void hotplug_notify_work_func(struct work_struct *work) /* TODO: Dynamic allocation */ #define AMDGPU_FBC_SIZE (3840 * 2160 * 4) -void amdgpu_dm_initialize_fbc(struct amdgpu_device *adev) +static void amdgpu_dm_initialize_fbc(struct amdgpu_device *adev) { int r; struct dm_comressor_info *compressor = &adev->dm.compressor; @@ -328,7 +372,7 @@ void amdgpu_dm_initialize_fbc(struct amdgpu_device *adev) * * Returns 0 on success */ -int amdgpu_dm_init(struct amdgpu_device *adev) +static int amdgpu_dm_init(struct amdgpu_device *adev) { struct dc_init_data init_data; adev->dm.ddev = adev->ddev; @@ -431,7 +475,7 @@ error: return -1; } -void amdgpu_dm_fini(struct amdgpu_device *adev) +static void amdgpu_dm_fini(struct amdgpu_device *adev) { amdgpu_dm_destroy_drm_device(&adev->dm); /* @@ -455,7 +499,7 @@ void amdgpu_dm_fini(struct amdgpu_device *adev) } /* moved from amdgpu_dm_kms.c */ -void amdgpu_dm_destroy() +static void amdgpu_dm_destroy(void) { } @@ -685,7 +729,7 @@ const struct amdgpu_ip_block_version dm_ip_block = }; -struct drm_atomic_state * +static struct drm_atomic_state * dm_atomic_state_alloc(struct drm_device *dev) { struct dm_atomic_state *state = kzalloc(sizeof(*state), GFP_KERNEL); @@ -738,7 +782,7 @@ static struct drm_mode_config_helper_funcs amdgpu_dm_mode_config_helperfuncs = { .atomic_commit_tail = amdgpu_dm_atomic_commit_tail }; -void +static void amdgpu_dm_update_connector_after_detect(struct amdgpu_dm_connector *aconnector) { struct drm_connector *connector = &aconnector->base; @@ -1245,7 +1289,8 @@ static const struct backlight_ops amdgpu_dm_backlight_ops = { .update_status = amdgpu_dm_backlight_update_status, }; -void amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm) +static void +amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm) { char bl_name[16]; struct backlight_properties props = { 0 }; @@ -1277,7 +1322,7 @@ void amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm) * * Returns 0 on success */ -int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) +static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) { struct amdgpu_display_manager *dm = &adev->dm; uint32_t i; @@ -1410,7 +1455,7 @@ fail_free_planes: return -1; } -void amdgpu_dm_destroy_drm_device(struct amdgpu_display_manager *dm) +static void amdgpu_dm_destroy_drm_device(struct amdgpu_display_manager *dm) { drm_mode_config_cleanup(dm->ddev); return; @@ -1613,13 +1658,13 @@ static int dm_early_init(void *handle) return 0; } -bool amdgpu_dm_acquire_dal_lock(struct amdgpu_display_manager *dm) +static bool amdgpu_dm_acquire_dal_lock(struct amdgpu_display_manager *dm) { /* TODO */ return true; } -bool amdgpu_dm_release_dal_lock(struct amdgpu_display_manager *dm) +static bool amdgpu_dm_release_dal_lock(struct amdgpu_display_manager *dm) { /* TODO */ return true; @@ -1659,7 +1704,7 @@ static bool modereset_required(struct drm_crtc_state *crtc_state) return !crtc_state->enable || !crtc_state->active; } -void amdgpu_dm_encoder_destroy(struct drm_encoder *encoder) +static void amdgpu_dm_encoder_destroy(struct drm_encoder *encoder) { drm_encoder_cleanup(encoder); kfree(encoder); @@ -1963,7 +2008,7 @@ static int fill_plane_attributes(struct amdgpu_device *adev, /*****************************************************************************/ -struct amdgpu_dm_connector * +static struct amdgpu_dm_connector * aconnector_from_drm_crtc_id(const struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; @@ -2366,7 +2411,7 @@ drm_connector_null: return stream; } -void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc) +static void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc) { drm_crtc_cleanup(crtc); kfree(crtc); @@ -2552,7 +2597,7 @@ int amdgpu_dm_connector_atomic_get_property(struct drm_connector *connector, return ret; } -void amdgpu_dm_connector_destroy(struct drm_connector *connector) +static void amdgpu_dm_connector_destroy(struct drm_connector *connector) { struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); const struct dc_link *link = aconnector->dc_link; @@ -2973,9 +3018,10 @@ static void dm_plane_helper_cleanup_fb(struct drm_plane *plane, amdgpu_bo_unref(&rbo); } -int dm_create_validation_set_for_connector(struct drm_connector *connector, - struct drm_display_mode *mode, - struct dc_validation_set *val_set) +static int +dm_create_validation_set_for_connector(struct drm_connector *connector, + struct drm_display_mode *mode, + struct dc_validation_set *val_set) { int result = MODE_ERROR; struct dc_sink *dc_sink = @@ -3012,8 +3058,8 @@ int dm_create_validation_set_for_connector(struct drm_connector *connector, return MODE_OK; } -int dm_plane_atomic_check(struct drm_plane *plane, - struct drm_plane_state *state) +static int dm_plane_atomic_check(struct drm_plane *plane, + struct drm_plane_state *state) { struct amdgpu_device *adev = plane->dev->dev_private; struct dc *dc = adev->dm.dc; @@ -3060,9 +3106,9 @@ static const u32 cursor_formats[] = { DRM_FORMAT_ARGB8888 }; -int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, - struct amdgpu_plane *aplane, - unsigned long possible_crtcs) +static int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, + struct amdgpu_plane *aplane, + unsigned long possible_crtcs) { int res = -EPERM; @@ -3106,9 +3152,9 @@ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, return res; } -int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, - struct drm_plane *plane, - uint32_t crtc_index) +static int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, + struct drm_plane *plane, + uint32_t crtc_index) { struct amdgpu_crtc *acrtc = NULL; struct amdgpu_plane *cursor_plane; @@ -3312,7 +3358,7 @@ static void amdgpu_dm_connector_ddc_get_modes(struct drm_connector *connector, amdgpu_dm_connector->num_modes = 0; } -int amdgpu_dm_connector_get_modes(struct drm_connector *connector) +static int amdgpu_dm_connector_get_modes(struct drm_connector *connector) { const struct drm_connector_helper_funcs *helper = connector->helper_private; @@ -3379,8 +3425,8 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm, } -int amdgpu_dm_i2c_xfer(struct i2c_adapter *i2c_adap, - struct i2c_msg *msgs, int num) +static int amdgpu_dm_i2c_xfer(struct i2c_adapter *i2c_adap, + struct i2c_msg *msgs, int num) { struct amdgpu_i2c_adapter *i2c = i2c_get_adapdata(i2c_adap); struct ddc_service *ddc_service = i2c->ddc_service; @@ -3414,7 +3460,7 @@ int amdgpu_dm_i2c_xfer(struct i2c_adapter *i2c_adap, return result; } -u32 amdgpu_dm_i2c_func(struct i2c_adapter *adap) +static u32 amdgpu_dm_i2c_func(struct i2c_adapter *adap) { return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; } @@ -3447,10 +3493,10 @@ create_i2c(struct ddc_service *ddc_service, /* Note: this function assumes that dc_link_detect() was called for the * dc_link which will be represented by this aconnector. */ -int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm, - struct amdgpu_dm_connector *aconnector, - uint32_t link_index, - struct amdgpu_encoder *aencoder) +static int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm, + struct amdgpu_dm_connector *aconnector, + uint32_t link_index, + struct amdgpu_encoder *aencoder) { int res = 0; int connector_type; @@ -3553,9 +3599,9 @@ int amdgpu_dm_get_encoder_crtc_mask(struct amdgpu_device *adev) } } -int amdgpu_dm_encoder_init(struct drm_device *dev, - struct amdgpu_encoder *aencoder, - uint32_t link_index) +static int amdgpu_dm_encoder_init(struct drm_device *dev, + struct amdgpu_encoder *aencoder, + uint32_t link_index) { struct amdgpu_device *adev = dev->dev_private; @@ -3636,8 +3682,8 @@ static void remove_stream(struct amdgpu_device *adev, acrtc->enabled = false; } -int get_cursor_position(struct drm_plane *plane, struct drm_crtc *crtc, - struct dc_cursor_position *position) +static int get_cursor_position(struct drm_plane *plane, struct drm_crtc *crtc, + struct dc_cursor_position *position) { struct amdgpu_crtc *amdgpu_crtc = amdgpu_crtc = to_amdgpu_crtc(crtc); int x, y; @@ -3944,9 +3990,9 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, } -int amdgpu_dm_atomic_commit(struct drm_device *dev, - struct drm_atomic_state *state, - bool nonblock) +static int amdgpu_dm_atomic_commit(struct drm_device *dev, + struct drm_atomic_state *state, + bool nonblock) { struct drm_crtc *crtc; struct drm_crtc_state *old_crtc_state, *new_crtc_state; @@ -3973,7 +4019,7 @@ int amdgpu_dm_atomic_commit(struct drm_device *dev, /*TODO Handle EINTR, reenable IRQ*/ } -void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) +static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) { struct drm_device *dev = state->dev; struct amdgpu_device *adev = dev->dev_private; @@ -4611,8 +4657,8 @@ static int dm_update_planes_state(struct dc *dc, return ret; } -int amdgpu_dm_atomic_check(struct drm_device *dev, - struct drm_atomic_state *state) +static int amdgpu_dm_atomic_check(struct drm_device *dev, + struct drm_atomic_state *state) { int i; int ret; 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 eb20642403ae..be3b70d683e7 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -193,37 +193,8 @@ struct amdgpu_dm_connector { #define to_amdgpu_dm_connector(x) container_of(x, struct amdgpu_dm_connector, base) -/* basic init/fini API */ -int amdgpu_dm_init(struct amdgpu_device *adev); - -void amdgpu_dm_fini(struct amdgpu_device *adev); - -void amdgpu_dm_destroy(void); - -/* initializes drm_device display related structures, based on the information - * provided by DAL. The drm strcutures are: drm_crtc, drm_connector, - * drm_encoder, drm_mode_config - * - * Returns 0 on success - */ -int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev); - -/* removes and deallocates the drm structures, created by the above function */ -void amdgpu_dm_destroy_drm_device(struct amdgpu_display_manager *dm); - -/* Locking/Mutex */ -bool amdgpu_dm_acquire_dal_lock(struct amdgpu_display_manager *dm); - -bool amdgpu_dm_release_dal_lock(struct amdgpu_display_manager *dm); - -/* Register "Backlight device" accessible by user-mode. */ -void amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm); - extern const struct amdgpu_ip_block_version dm_ip_block; -void -amdgpu_dm_update_connector_after_detect(struct amdgpu_dm_connector *aconnector); - struct amdgpu_framebuffer; struct amdgpu_display_manager; struct dc_validation_set; @@ -252,36 +223,6 @@ struct dm_atomic_state { #define to_dm_atomic_state(x) container_of(x, struct dm_atomic_state, base) -/*TODO Jodan Hersen use the one in amdgpu_dm*/ -int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, - struct amdgpu_plane *aplane, - unsigned long possible_crtcs); -int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, - struct drm_plane *plane, - uint32_t link_index); -int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm, - struct amdgpu_dm_connector *amdgpu_dm_connector, - uint32_t link_index, - struct amdgpu_encoder *amdgpu_encoder); -int amdgpu_dm_encoder_init(struct drm_device *dev, - struct amdgpu_encoder *aencoder, - uint32_t link_index); - -void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc); -void amdgpu_dm_connector_destroy(struct drm_connector *connector); -void amdgpu_dm_encoder_destroy(struct drm_encoder *encoder); - -int amdgpu_dm_connector_get_modes(struct drm_connector *connector); - -int amdgpu_dm_atomic_commit(struct drm_device *dev, - struct drm_atomic_state *state, - bool nonblock); - -void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state); - -int amdgpu_dm_atomic_check(struct drm_device *dev, - struct drm_atomic_state *state); - void amdgpu_dm_connector_funcs_reset(struct drm_connector *connector); struct drm_connector_state * amdgpu_dm_connector_atomic_duplicate_state(struct drm_connector *connector); -- cgit From b4133c09e47afe4c2a5485eb33c7cf456ce0241f Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 10 Oct 2017 17:53:24 -0400 Subject: drm/amd/display: drop unused functions in amdgpu_dm.c Not used anywhere. Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 82 ----------------------- 1 file changed, 82 deletions(-) (limited to 'drivers/gpu') 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 051cb371e88b..e98bb639268d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -498,11 +498,6 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev) return; } -/* moved from amdgpu_dm_kms.c */ -static void amdgpu_dm_destroy(void) -{ -} - static int dm_sw_init(void *handle) { return 0; @@ -1658,19 +1653,6 @@ static int dm_early_init(void *handle) return 0; } -static bool amdgpu_dm_acquire_dal_lock(struct amdgpu_display_manager *dm) -{ - /* TODO */ - return true; -} - -static bool amdgpu_dm_release_dal_lock(struct amdgpu_display_manager *dm) -{ - /* TODO */ - return true; -} - - struct dm_connector_state { struct drm_connector_state base; @@ -2008,30 +1990,6 @@ static int fill_plane_attributes(struct amdgpu_device *adev, /*****************************************************************************/ -static struct amdgpu_dm_connector * -aconnector_from_drm_crtc_id(const struct drm_crtc *crtc) -{ - struct drm_device *dev = crtc->dev; - struct drm_connector *connector; - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - struct amdgpu_dm_connector *aconnector; - - list_for_each_entry(connector, - &dev->mode_config.connector_list, head) { - - aconnector = to_amdgpu_dm_connector(connector); - - if (aconnector->base.state->crtc != &acrtc->base) - continue; - - /* Found the connector */ - return aconnector; - } - - /* If we get here, not found. */ - return NULL; -} - static void update_stream_scaling_settings(const struct drm_display_mode *mode, const struct dm_connector_state *dm_state, struct dc_stream_state *stream) @@ -3018,46 +2976,6 @@ static void dm_plane_helper_cleanup_fb(struct drm_plane *plane, amdgpu_bo_unref(&rbo); } -static int -dm_create_validation_set_for_connector(struct drm_connector *connector, - struct drm_display_mode *mode, - struct dc_validation_set *val_set) -{ - int result = MODE_ERROR; - struct dc_sink *dc_sink = - to_amdgpu_dm_connector(connector)->dc_sink; - /* TODO: Unhardcode stream count */ - struct dc_stream_state *stream; - - if ((mode->flags & DRM_MODE_FLAG_INTERLACE) || - (mode->flags & DRM_MODE_FLAG_DBLSCAN)) - return result; - - if (dc_sink == NULL) { - DRM_ERROR("dc_sink is NULL!\n"); - return result; - } - - stream = dc_create_stream_for_sink(dc_sink); - - if (stream == NULL) { - DRM_ERROR("Failed to create stream for sink!\n"); - return result; - } - - drm_mode_set_crtcinfo(mode, 0); - - fill_stream_properties_from_drm_display_mode(stream, mode, connector); - - val_set->stream = stream; - - stream->src.width = mode->hdisplay; - stream->src.height = mode->vdisplay; - stream->dst = stream->src; - - return MODE_OK; -} - static int dm_plane_atomic_check(struct drm_plane *plane, struct drm_plane_state *state) { -- cgit From 8ceb1cab8ec4d0beeac42714e27eb681f0afdd1d Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 10 Oct 2017 18:33:14 -0400 Subject: drm/amd/display: drop unused functions in amdgpu_dm_services.c not used. Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_services.c | 53 ---------------------- 1 file changed, 53 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c index aefd9ebc7bce..fc0668b2300c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c @@ -35,47 +35,6 @@ #include "amdgpu_dm_irq.h" #include "amdgpu_pm.h" -/****************************************************************************** - * IRQ Interfaces. - *****************************************************************************/ - -void dal_register_timer_interrupt( - struct dc_context *ctx, - struct dc_timer_interrupt_params *int_params, - interrupt_handler ih, - void *args) -{ - struct amdgpu_device *adev = ctx->driver_context; - - if (!adev || !int_params) { - DRM_ERROR("DM_IRQ: invalid input!\n"); - return; - } - - if (int_params->int_context != INTERRUPT_LOW_IRQ_CONTEXT) { - /* only low irq ctx is supported. */ - DRM_ERROR("DM_IRQ: invalid context: %d!\n", - int_params->int_context); - return; - } - - amdgpu_dm_irq_register_timer(adev, int_params, ih, args); -} - -void dal_isr_acquire_lock(struct dc_context *ctx) -{ - /*TODO*/ -} - -void dal_isr_release_lock(struct dc_context *ctx) -{ - /*TODO*/ -} - -/****************************************************************************** - * End-of-IRQ Interfaces. - *****************************************************************************/ - bool dm_write_persistent_data(struct dc_context *ctx, const struct dc_sink *sink, const char *module_name, @@ -118,18 +77,6 @@ bool dm_pp_pre_dce_clock_change( return false; } -bool dm_pp_apply_safe_state( - const struct dc_context *ctx) -{ - struct amdgpu_device *adev = ctx->driver_context; - - if (adev->pm.dpm_enabled) { - /* TODO: Does this require PreModeChange event to PPLIB? */ - } - - return true; -} - bool dm_pp_apply_display_requirements( const struct dc_context *ctx, const struct dm_pp_display_configuration *pp_display_cfg) -- cgit From aaa6346d75e2eaee715f36dd3b88a2a865663235 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 11 Oct 2017 09:44:50 -0400 Subject: drm/amd/display: whitespace cleanup in amdgpu_dm_mst_types.c/h To match kernel standards. No intended functional change. Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 39 +++++++++++----------- .../amd/display/amdgpu_dm/amdgpu_dm_mst_types.h | 5 ++- 2 files changed, 22 insertions(+), 22 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 343645e4070b..eed316a8b096 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -57,10 +57,10 @@ static inline char *side_band_msg_type_to_str(uint32_t address) } void log_dpcd(uint8_t type, - uint32_t address, - uint8_t *data, - uint32_t size, - bool res) + uint32_t address, + uint8_t *data, + uint32_t size, + bool res) { DRM_DEBUG_KMS("Op: %s, addr: %04x, SideBand Msg: %s, Op res: %s\n", (type == DP_AUX_NATIVE_READ) || @@ -77,9 +77,11 @@ void log_dpcd(uint8_t type, } #endif -static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) +static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux, + struct drm_dp_aux_msg *msg) { - enum i2c_mot_mode mot = (msg->request & DP_AUX_I2C_MOT) ? I2C_MOT_TRUE : I2C_MOT_FALSE; + enum i2c_mot_mode mot = (msg->request & DP_AUX_I2C_MOT) ? + I2C_MOT_TRUE : I2C_MOT_FALSE; enum ddc_result res; switch (msg->request & ~DP_AUX_I2C_MOT) { @@ -125,10 +127,10 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg #ifdef TRACE_DPCD log_dpcd(msg->request, - msg->address, - msg->buffer, - msg->size, - r == DDC_RESULT_SUCESSFULL); + msg->address, + msg->buffer, + msg->size, + r == DDC_RESULT_SUCESSFULL); #endif return msg->size; @@ -229,9 +231,10 @@ dm_dp_create_fake_mst_encoder(struct amdgpu_dm_connector *connector) return amdgpu_encoder; } -static struct drm_connector *dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr, - struct drm_dp_mst_port *port, - const char *pathprop) +static struct drm_connector * +dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr, + struct drm_dp_mst_port *port, + const char *pathprop) { struct amdgpu_dm_connector *master = container_of(mgr, struct amdgpu_dm_connector, mst_mgr); struct drm_device *dev = master->base.dev; @@ -311,9 +314,8 @@ static struct drm_connector *dm_dp_add_mst_connector(struct drm_dp_mst_topology_ return connector; } -static void dm_dp_destroy_mst_connector( - struct drm_dp_mst_topology_mgr *mgr, - struct drm_connector *connector) +static void dm_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr, + struct drm_connector *connector) { struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); @@ -438,9 +440,8 @@ static const struct drm_dp_mst_topology_cbs dm_mst_cbs = { .register_connector = dm_dp_mst_register_connector }; -void amdgpu_dm_initialize_dp_connector( - struct amdgpu_display_manager *dm, - struct amdgpu_dm_connector *aconnector) +void amdgpu_dm_initialize_dp_connector(struct amdgpu_display_manager *dm, + struct amdgpu_dm_connector *aconnector) { aconnector->dm_dp_aux.aux.name = "dmdc"; aconnector->dm_dp_aux.aux.dev = dm->adev->dev; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h index ba64a408d79c..2da851b40042 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h @@ -29,8 +29,7 @@ struct amdgpu_display_manager; struct amdgpu_dm_connector; -void amdgpu_dm_initialize_dp_connector( - struct amdgpu_display_manager *dm, - struct amdgpu_dm_connector *aconnector); +void amdgpu_dm_initialize_dp_connector(struct amdgpu_display_manager *dm, + struct amdgpu_dm_connector *aconnector); #endif -- cgit From 6563617fbbbe273be4ce99f15000a63eca789d6a Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 11 Oct 2017 09:47:04 -0400 Subject: drm/amd/display: make log_dpcd static It's only used in this file. Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index eed316a8b096..dfcfb5a722e0 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -56,11 +56,11 @@ static inline char *side_band_msg_type_to_str(uint32_t address) return str; } -void log_dpcd(uint8_t type, - uint32_t address, - uint8_t *data, - uint32_t size, - bool res) +static void log_dpcd(uint8_t type, + uint32_t address, + uint8_t *data, + uint32_t size, + bool res) { DRM_DEBUG_KMS("Op: %s, addr: %04x, SideBand Msg: %s, Op res: %s\n", (type == DP_AUX_NATIVE_READ) || -- cgit From e637525659ed04be89a7f79ccf6e94e1e5e40225 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 11 Oct 2017 09:53:16 -0400 Subject: drm/amd/display: whitespace cleanup in amdgpu_dm_irq.c/h To match kernel standards. No intended functional change. Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c | 111 +++++++++------------ .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h | 38 +++---- 2 files changed, 64 insertions(+), 85 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c index 22d41d35249e..743a9a361fc6 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c @@ -66,11 +66,10 @@ struct amdgpu_dm_timer_handler_data { * Private functions. *****************************************************************************/ -static void init_handler_common_data( - struct handler_common_data *hcd, - void (*ih)(void *), - void *args, - struct amdgpu_display_manager *dm) +static void init_handler_common_data(struct handler_common_data *hcd, + void (*ih)(void *), + void *args, + struct amdgpu_display_manager *dm) { hcd->handler = ih; hcd->handler_arg = args; @@ -115,10 +114,9 @@ static void dm_irq_work_func(struct work_struct *work) * Remove a handler and return a pointer to hander list from which the * handler was removed. */ -static struct list_head *remove_irq_handler( - struct amdgpu_device *adev, - void *ih, - const struct dc_interrupt_params *int_params) +static struct list_head *remove_irq_handler(struct amdgpu_device *adev, + void *ih, + const struct dc_interrupt_params *int_params) { struct list_head *hnd_list; struct list_head *entry, *tmp; @@ -172,9 +170,8 @@ static struct list_head *remove_irq_handler( } /* If 'handler_in == NULL' then remove ALL handlers. */ -static void remove_timer_handler( - struct amdgpu_device *adev, - struct amdgpu_dm_timer_handler_data *handler_in) +static void remove_timer_handler(struct amdgpu_device *adev, + struct amdgpu_dm_timer_handler_data *handler_in) { struct amdgpu_dm_timer_handler_data *handler_temp; struct list_head *handler_list; @@ -236,8 +233,7 @@ static void remove_timer_handler( * * @work: work struct */ -static void dm_timer_work_func( - struct work_struct *work) +static void dm_timer_work_func(struct work_struct *work) { struct amdgpu_dm_timer_handler_data *handler_data = container_of(work, struct amdgpu_dm_timer_handler_data, @@ -253,9 +249,9 @@ static void dm_timer_work_func( remove_timer_handler(handler_data->hcd.dm->adev, handler_data); } -static bool validate_irq_registration_params( - struct dc_interrupt_params *int_params, - void (*ih)(void *)) +static bool +validate_irq_registration_params(struct dc_interrupt_params *int_params, + void (*ih)(void *)) { if (NULL == int_params || NULL == ih) { DRM_ERROR("DM_IRQ: invalid input!\n"); @@ -277,9 +273,8 @@ static bool validate_irq_registration_params( return true; } -static bool validate_irq_unregistration_params( - enum dc_irq_source irq_source, - irq_handler_idx handler_idx) +static bool validate_irq_unregistration_params(enum dc_irq_source irq_source, + irq_handler_idx handler_idx) { if (DAL_INVALID_IRQ_HANDLER_IDX == handler_idx) { DRM_ERROR("DM_IRQ: invalid handler_idx==NULL!\n"); @@ -299,11 +294,10 @@ static bool validate_irq_unregistration_params( * Note: caller is responsible for input validation. *****************************************************************************/ -void *amdgpu_dm_irq_register_interrupt( - struct amdgpu_device *adev, - struct dc_interrupt_params *int_params, - void (*ih)(void *), - void *handler_args) +void *amdgpu_dm_irq_register_interrupt(struct amdgpu_device *adev, + struct dc_interrupt_params *int_params, + void (*ih)(void *), + void *handler_args) { struct list_head *hnd_list; struct amdgpu_dm_irq_handler_data *handler_data; @@ -359,10 +353,9 @@ void *amdgpu_dm_irq_register_interrupt( return handler_data; } -void amdgpu_dm_irq_unregister_interrupt( - struct amdgpu_device *adev, - enum dc_irq_source irq_source, - void *ih) +void amdgpu_dm_irq_unregister_interrupt(struct amdgpu_device *adev, + enum dc_irq_source irq_source, + void *ih) { struct list_head *handler_list; struct dc_interrupt_params int_params; @@ -394,8 +387,7 @@ void amdgpu_dm_irq_unregister_interrupt( } } -int amdgpu_dm_irq_init( - struct amdgpu_device *adev) +int amdgpu_dm_irq_init(struct amdgpu_device *adev) { int src; struct irq_list_head *lh; @@ -427,11 +419,10 @@ int amdgpu_dm_irq_init( return 0; } -void amdgpu_dm_irq_register_timer( - struct amdgpu_device *adev, - struct dc_timer_interrupt_params *int_params, - interrupt_handler ih, - void *args) +void amdgpu_dm_irq_register_timer(struct amdgpu_device *adev, + struct dc_timer_interrupt_params *int_params, + interrupt_handler ih, + void *args) { unsigned long jf_delay; struct list_head *handler_list; @@ -470,8 +461,7 @@ void amdgpu_dm_irq_register_timer( } /* DM IRQ and timer resource release */ -void amdgpu_dm_irq_fini( - struct amdgpu_device *adev) +void amdgpu_dm_irq_fini(struct amdgpu_device *adev) { int src; struct irq_list_head *lh; @@ -492,8 +482,7 @@ void amdgpu_dm_irq_fini( destroy_workqueue(adev->dm.timer_workqueue); } -int amdgpu_dm_irq_suspend( - struct amdgpu_device *adev) +int amdgpu_dm_irq_suspend(struct amdgpu_device *adev) { int src; struct list_head *hnd_list_h; @@ -576,9 +565,8 @@ int amdgpu_dm_irq_resume_late(struct amdgpu_device *adev) * amdgpu_dm_irq_schedule_work - schedule all work items registered for the * "irq_source". */ -static void amdgpu_dm_irq_schedule_work( - struct amdgpu_device *adev, - enum dc_irq_source irq_source) +static void amdgpu_dm_irq_schedule_work(struct amdgpu_device *adev, + enum dc_irq_source irq_source) { unsigned long irq_table_flags; struct work_struct *work = NULL; @@ -601,9 +589,8 @@ static void amdgpu_dm_irq_schedule_work( /** amdgpu_dm_irq_immediate_work * Callback high irq work immediately, don't send to work queue */ -static void amdgpu_dm_irq_immediate_work( - struct amdgpu_device *adev, - enum dc_irq_source irq_source) +static void amdgpu_dm_irq_immediate_work(struct amdgpu_device *adev, + enum dc_irq_source irq_source) { struct amdgpu_dm_irq_handler_data *handler_data; struct list_head *entry; @@ -635,10 +622,9 @@ static void amdgpu_dm_irq_immediate_work( * Generic IRQ handler, calls all registered high irq work immediately, and * schedules work for low irq */ -int amdgpu_dm_irq_handler( - struct amdgpu_device *adev, - struct amdgpu_irq_src *source, - struct amdgpu_iv_entry *entry) +int amdgpu_dm_irq_handler(struct amdgpu_device *adev, + struct amdgpu_irq_src *source, + struct amdgpu_iv_entry *entry) { enum dc_irq_source src = @@ -678,9 +664,9 @@ static enum dc_irq_source amdgpu_dm_hpd_to_dal_irq_source(unsigned type) } static int amdgpu_dm_set_hpd_irq_state(struct amdgpu_device *adev, - struct amdgpu_irq_src *source, - unsigned type, - enum amdgpu_interrupt_state state) + struct amdgpu_irq_src *source, + unsigned type, + enum amdgpu_interrupt_state state) { enum dc_irq_source src = amdgpu_dm_hpd_to_dal_irq_source(type); bool st = (state == AMDGPU_IRQ_STATE_ENABLE); @@ -689,13 +675,12 @@ static int amdgpu_dm_set_hpd_irq_state(struct amdgpu_device *adev, return 0; } -static inline int dm_irq_state( - struct amdgpu_device *adev, - struct amdgpu_irq_src *source, - unsigned crtc_id, - enum amdgpu_interrupt_state state, - const enum irq_type dal_irq_type, - const char *func) +static inline int dm_irq_state(struct amdgpu_device *adev, + struct amdgpu_irq_src *source, + unsigned crtc_id, + enum amdgpu_interrupt_state state, + const enum irq_type dal_irq_type, + const char *func) { bool st; enum dc_irq_source irq_source; @@ -719,9 +704,9 @@ static inline int dm_irq_state( } static int amdgpu_dm_set_pflip_irq_state(struct amdgpu_device *adev, - struct amdgpu_irq_src *source, - unsigned crtc_id, - enum amdgpu_interrupt_state state) + struct amdgpu_irq_src *source, + unsigned crtc_id, + enum amdgpu_interrupt_state state) { return dm_irq_state( adev, diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h index 9d3007634266..0927ed4ab758 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h @@ -39,8 +39,7 @@ * 0 - success * non-zero - error */ -int amdgpu_dm_irq_init( - struct amdgpu_device *adev); +int amdgpu_dm_irq_init(struct amdgpu_device *adev); /** * amdgpu_dm_irq_fini - deallocate internal structures of 'amdgpu_dm_irq'. @@ -48,8 +47,7 @@ int amdgpu_dm_irq_init( * This function should be called exactly once - during DM destruction. * */ -void amdgpu_dm_irq_fini( - struct amdgpu_device *adev); +void amdgpu_dm_irq_fini(struct amdgpu_device *adev); /** * amdgpu_dm_irq_register_interrupt - register irq handler for Display block. @@ -65,11 +63,10 @@ void amdgpu_dm_irq_fini( * * Cannot be called from an interrupt handler. */ -void *amdgpu_dm_irq_register_interrupt( - struct amdgpu_device *adev, - struct dc_interrupt_params *int_params, - void (*ih)(void *), - void *handler_args); +void *amdgpu_dm_irq_register_interrupt(struct amdgpu_device *adev, + struct dc_interrupt_params *int_params, + void (*ih)(void *), + void *handler_args); /** * amdgpu_dm_irq_unregister_interrupt - unregister handler which was registered @@ -79,26 +76,23 @@ void *amdgpu_dm_irq_register_interrupt( * @ih_index: irq handler index which was returned by * amdgpu_dm_irq_register_interrupt */ -void amdgpu_dm_irq_unregister_interrupt( - struct amdgpu_device *adev, - enum dc_irq_source irq_source, - void *ih_index); +void amdgpu_dm_irq_unregister_interrupt(struct amdgpu_device *adev, + enum dc_irq_source irq_source, + void *ih_index); -void amdgpu_dm_irq_register_timer( - struct amdgpu_device *adev, - struct dc_timer_interrupt_params *int_params, - interrupt_handler ih, - void *args); +void amdgpu_dm_irq_register_timer(struct amdgpu_device *adev, + struct dc_timer_interrupt_params *int_params, + interrupt_handler ih, + void *args); /** * amdgpu_dm_irq_handler * Generic IRQ handler, calls all registered high irq work immediately, and * schedules work for low irq */ -int amdgpu_dm_irq_handler( - struct amdgpu_device *adev, - struct amdgpu_irq_src *source, - struct amdgpu_iv_entry *entry); +int amdgpu_dm_irq_handler(struct amdgpu_device *adev, + struct amdgpu_irq_src *source, + struct amdgpu_iv_entry *entry); void amdgpu_dm_set_irq_funcs(struct amdgpu_device *adev); -- cgit From f1548455ce89cbb7708428f6a7989a3fe180ed55 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 11 Oct 2017 09:59:50 -0400 Subject: drm/amd/display: remove unused functions in amdgpu_dm_irq.c Not used. Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c | 62 ---------------------- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h | 5 -- 2 files changed, 67 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c index 743a9a361fc6..1b7df0b6c6d3 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c @@ -228,27 +228,6 @@ static void remove_timer_handler(struct amdgpu_device *adev, } } -/** - * dm_timer_work_func - Handle a timer. - * - * @work: work struct - */ -static void dm_timer_work_func(struct work_struct *work) -{ - struct amdgpu_dm_timer_handler_data *handler_data = - container_of(work, struct amdgpu_dm_timer_handler_data, - d_work.work); - - DRM_DEBUG_KMS("DM_IRQ: work_func: handler_data=%p\n", handler_data); - - /* Call a DAL subcomponent which registered for timer notification. */ - handler_data->hcd.handler(handler_data->hcd.handler_arg); - - /* We support only "single shot" timers. That means we must delete - * the handler after it was called. */ - remove_timer_handler(handler_data->hcd.dm->adev, handler_data); -} - static bool validate_irq_registration_params(struct dc_interrupt_params *int_params, void (*ih)(void *)) @@ -419,47 +398,6 @@ int amdgpu_dm_irq_init(struct amdgpu_device *adev) return 0; } -void amdgpu_dm_irq_register_timer(struct amdgpu_device *adev, - struct dc_timer_interrupt_params *int_params, - interrupt_handler ih, - void *args) -{ - unsigned long jf_delay; - struct list_head *handler_list; - struct amdgpu_dm_timer_handler_data *handler_data; - unsigned long irq_table_flags; - - handler_data = kzalloc(sizeof(*handler_data), GFP_KERNEL); - if (!handler_data) { - DRM_ERROR("DM_IRQ: failed to allocate timer handler!\n"); - return; - } - - memset(handler_data, 0, sizeof(*handler_data)); - - init_handler_common_data(&handler_data->hcd, ih, args, &adev->dm); - - INIT_DELAYED_WORK(&handler_data->d_work, dm_timer_work_func); - - /* Lock the list, add the handler. */ - DM_IRQ_TABLE_LOCK(adev, irq_table_flags); - - handler_list = &adev->dm.timer_handler_list; - - list_add_tail(&handler_data->hcd.list, handler_list); - - DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags); - - jf_delay = usecs_to_jiffies(int_params->micro_sec_interval); - - queue_delayed_work(adev->dm.timer_workqueue, &handler_data->d_work, - jf_delay); - - DRM_DEBUG_KMS("DM_IRQ: added handler:%p with micro_sec_interval=%u\n", - handler_data, int_params->micro_sec_interval); - return; -} - /* DM IRQ and timer resource release */ void amdgpu_dm_irq_fini(struct amdgpu_device *adev) { diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h index 0927ed4ab758..393fcf7bbcb4 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h @@ -80,11 +80,6 @@ void amdgpu_dm_irq_unregister_interrupt(struct amdgpu_device *adev, enum dc_irq_source irq_source, void *ih_index); -void amdgpu_dm_irq_register_timer(struct amdgpu_device *adev, - struct dc_timer_interrupt_params *int_params, - interrupt_handler ih, - void *args); - /** * amdgpu_dm_irq_handler * Generic IRQ handler, calls all registered high irq work immediately, and -- cgit From 8db02ca3410b0668d520c0c5d7ba0e7e3eaa811a Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 11 Oct 2017 10:03:10 -0400 Subject: drm/amd/display: make amdgpu_dm_irq_handler static It's not used outside the file. Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c | 6 +++--- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h | 9 --------- 2 files changed, 3 insertions(+), 12 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c index 1b7df0b6c6d3..52b6e4a91d8b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c @@ -560,9 +560,9 @@ static void amdgpu_dm_irq_immediate_work(struct amdgpu_device *adev, * Generic IRQ handler, calls all registered high irq work immediately, and * schedules work for low irq */ -int amdgpu_dm_irq_handler(struct amdgpu_device *adev, - struct amdgpu_irq_src *source, - struct amdgpu_iv_entry *entry) +static int amdgpu_dm_irq_handler(struct amdgpu_device *adev, + struct amdgpu_irq_src *source, + struct amdgpu_iv_entry *entry) { enum dc_irq_source src = diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h index 393fcf7bbcb4..82f8e761beca 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h @@ -80,15 +80,6 @@ void amdgpu_dm_irq_unregister_interrupt(struct amdgpu_device *adev, enum dc_irq_source irq_source, void *ih_index); -/** - * amdgpu_dm_irq_handler - * Generic IRQ handler, calls all registered high irq work immediately, and - * schedules work for low irq - */ -int amdgpu_dm_irq_handler(struct amdgpu_device *adev, - struct amdgpu_irq_src *source, - struct amdgpu_iv_entry *entry); - void amdgpu_dm_set_irq_funcs(struct amdgpu_device *adev); void amdgpu_dm_hpd_init(struct amdgpu_device *adev); -- cgit From 4770b18493b3d9fe1f8913e69ec5134b103d5788 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 11 Oct 2017 12:42:30 -0400 Subject: drm/amd/display/dc: drop dm_delay_in_microseconds Use udelay directly. Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 4 ++-- drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c | 4 ++-- drivers/gpu/drm/amd/display/dc/dm_services.h | 3 --- 3 files changed, 4 insertions(+), 7 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 616431e25b79..5f815cab94b5 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -127,7 +127,7 @@ static bool edp_receiver_ready_T9(struct dc_link *link) break; if (result != DC_OK) break; - dm_delay_in_microseconds(link->ctx, 100); //MAx T9 + udelay(100); //MAx T9 } while (++tries < 50); return result; } @@ -271,7 +271,7 @@ void dp_retrain_link_dp_test(struct dc_link *link, pipes[i].stream->sink->link != NULL && pipes[i].stream_res.stream_enc != NULL && pipes[i].stream->sink->link == link) { - dm_delay_in_microseconds(link->ctx, 100); + udelay(100); pipes[i].stream_res.stream_enc->funcs->dp_blank( pipes[i].stream_res.stream_enc); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c index f9873cad40e0..3691c7498d08 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c @@ -137,7 +137,7 @@ static void dce_dmcu_set_psr_enable(struct dmcu *dmcu, bool enable, bool wait) if (psr_state == 0) break; } - dm_delay_in_microseconds(dmcu->ctx, 10); + udelay(10); } } } @@ -378,7 +378,7 @@ static void dcn10_dmcu_set_psr_enable(struct dmcu *dmcu, bool enable, bool wait) if (psr_state == 0) break; } - dm_delay_in_microseconds(dmcu->ctx, 500); + udelay(500); } /* assert if max retry hit */ diff --git a/drivers/gpu/drm/amd/display/dc/dm_services.h b/drivers/gpu/drm/amd/display/dc/dm_services.h index 8166027d2d83..a11991c382de 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services.h @@ -404,9 +404,6 @@ bool dm_read_persistent_data(struct dc_context *ctx, unsigned int size, struct persistent_data_flag *flag); -void dm_delay_in_microseconds - (struct dc_context *ctx, unsigned int microSeconds); - bool dm_query_extended_brightness_caps (struct dc_context *ctx, enum dm_acpi_display_type display, struct dm_acpi_atif_backlight_caps *pCaps); -- cgit From d7205d5c0f2b09d900231de9026b97105c37d343 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 11 Oct 2017 12:44:13 -0400 Subject: drm/amd/display: drop unused dm_delay_in_microseconds No longer used. Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c index fc0668b2300c..26bf9918fcb7 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c @@ -59,13 +59,6 @@ bool dm_read_persistent_data(struct dc_context *ctx, return false; } -void dm_delay_in_microseconds(struct dc_context *ctx, - unsigned int microSeconds) -{ - /*TODO implement*/ - return; -} - /**** power component interfaces ****/ bool dm_pp_pre_dce_clock_change( -- cgit From 2a0b4d858f7bb3d36d0ca610d9ef02062589edeb Mon Sep 17 00:00:00 2001 From: Martin Tsai Date: Thu, 7 Sep 2017 13:02:05 +0800 Subject: drm/amd/display: To prevent detecting new sink from spurious HPD Signed-off-by: Martin Tsai Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 48 +++++++++++++++++++-------- 1 file changed, 34 insertions(+), 14 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 4a70948c91b1..ee23b609d7dd 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -565,8 +565,6 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) link->local_sink) return true; - link_disconnect_sink(link); - if (new_connection_type != dc_connection_none) { link->type = new_connection_type; @@ -638,8 +636,8 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) if (link->dpcd_caps.sink_count.bits.SINK_COUNT) link->dpcd_sink_count = link->dpcd_caps.sink_count. bits.SINK_COUNT; - else - link->dpcd_sink_count = 1; + else + link->dpcd_sink_count = 1; dal_ddc_service_set_transaction_type( link->ddc, @@ -651,16 +649,24 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) sink_init_data.link = link; sink_init_data.sink_signal = sink_caps.signal; - sink = dc_sink_create(&sink_init_data); - if (!sink) { - DC_ERROR("Failed to create sink!\n"); - return false; - } + if (link->local_sink) { + sink = link->local_sink; + } else { + link_disconnect_sink(link); + + sink_init_data.link = link; + sink_init_data.sink_signal = sink_caps.signal; - sink->dongle_max_pix_clk = sink_caps.max_hdmi_pixel_clock; - sink->converter_disable_audio = converter_disable_audio; + sink = dc_sink_create(&sink_init_data); + if (!sink) { + DC_ERROR("Failed to create sink!\n"); + return false; + } + sink->dongle_max_pix_clk = sink_caps.max_hdmi_pixel_clock; + sink->converter_disable_audio = converter_disable_audio; - link->local_sink = sink; + link->local_sink = sink; + } edid_status = dm_helpers_read_local_edid( link->ctx, @@ -752,8 +758,22 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) memset(link->mst_stream_alloc_table.stream_allocations, 0, sizeof(link->mst_stream_alloc_table.stream_allocations)); } - link->type = dc_connection_none; - sink_caps.signal = SIGNAL_TYPE_NONE; + if (link->local_sink) { + sink = link->local_sink; + edid_status = dm_helpers_read_local_edid( + link->ctx, + link, + sink); + if (edid_status != EDID_OK) { + link_disconnect_sink(link); + link->type = dc_connection_none; + sink_caps.signal = SIGNAL_TYPE_NONE; + } + } else { + link_disconnect_sink(link); + link->type = dc_connection_none; + sink_caps.signal = SIGNAL_TYPE_NONE; + } } LINK_INFO("link=%d, dc_sink_in=%p is now %s\n", -- cgit From 6bf520280f3621d458e2ef3bd3c48acb89a39af7 Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Tue, 5 Sep 2017 12:20:39 -0400 Subject: drm/amd/display: Driver message to SMU to indicate display off Signed-off-by: Hersen Wu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 2 +- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 3 +- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 38 ++++++++++++++-------- drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 2 +- 4 files changed, 28 insertions(+), 17 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index f41f15faf019..47f16a4b9f27 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -763,7 +763,7 @@ static bool dc_commit_state_no_check(struct dc *dc, struct dc_state *context) if (!dcb->funcs->is_accelerated_mode(dcb)) dc->hwss.enable_accelerated_mode(dc); - dc->hwss.ready_shared_resources(dc); + dc->hwss.ready_shared_resources(dc, context); for (i = 0; i < dc->res_pool->pipe_count; i++) { pipe = &context->res_ctx.pipe_ctx[i]; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index de154329b049..b3448a41718e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1889,6 +1889,7 @@ enum dc_status dce110_apply_ctx_to_hw( return status; } + /* pplib is notified if disp_num changed */ dc->hwss.set_bandwidth(dc, context, true); /* to save power */ @@ -2683,7 +2684,7 @@ static void program_csc_matrix(struct pipe_ctx *pipe_ctx, } } -static void ready_shared_resources(struct dc *dc) {} +static void ready_shared_resources(struct dc *dc, struct dc_state *context) {} static void optimize_shared_resources(struct dc *dc) {} diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index d3fee15aeb79..e60be00abcf2 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -802,18 +802,14 @@ static void undo_DEGVIDCN10_253_wa(struct dc *dc) IP_REQUEST_EN, 0); } -static void ready_shared_resources(struct dc *dc) -{ - if (dc->current_state->stream_count == 0 && - !dc->debug.disable_stutter) - undo_DEGVIDCN10_253_wa(dc); -} - static void apply_DEGVIDCN10_253_wa(struct dc *dc) { struct dce_hwseq *hws = dc->hwseq; struct mem_input *mi = dc->res_pool->mis[0]; + if (dc->debug.disable_stutter) + return; + REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1); @@ -824,13 +820,6 @@ static void apply_DEGVIDCN10_253_wa(struct dc *dc) mi->funcs->set_hubp_blank_en(mi, false); } -static void optimize_shared_resources(struct dc *dc) -{ - if (dc->current_state->stream_count == 0 && - !dc->debug.disable_stutter) - apply_DEGVIDCN10_253_wa(dc); -} - static void bios_golden_init(struct dc *dc) { struct dc_bios *bp = dc->ctx->dc_bios; @@ -2445,6 +2434,27 @@ static void dcn10_pplib_apply_display_requirements( dc->prev_display_config = *pp_display_cfg; } +static void optimize_shared_resources(struct dc *dc) +{ + if (dc->current_state->stream_count == 0) { + apply_DEGVIDCN10_253_wa(dc); + /* S0i2 message */ + dcn10_pplib_apply_display_requirements(dc, dc->current_state); + } +} + +static void ready_shared_resources(struct dc *dc, struct dc_state *context) +{ + if (dc->current_state->stream_count == 0 && + !dc->debug.disable_stutter) + undo_DEGVIDCN10_253_wa(dc); + + /* S0i2 message */ + if (dc->current_state->stream_count == 0 && + context->stream_count != 0) + dcn10_pplib_apply_display_requirements(dc, context); +} + static void dcn10_apply_ctx_for_surface( struct dc *dc, const struct dc_stream_state *stream, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index aae7629b1c08..1fa2edc6cfb1 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -174,7 +174,7 @@ struct hw_sequencer_funcs { struct resource_pool *res_pool, struct pipe_ctx *pipe_ctx); - void (*ready_shared_resources)(struct dc *dc); + void (*ready_shared_resources)(struct dc *dc, struct dc_state *context); void (*optimize_shared_resources)(struct dc *dc); }; -- cgit From 5088cc98f59b922a609078c048a25e30f94b9216 Mon Sep 17 00:00:00 2001 From: Andrew Jiang Date: Wed, 6 Sep 2017 18:56:46 -0400 Subject: drm/amd/display: Force always scale chroma, set always_scaled to false This allows us to not always have scaling on, which causes issues with validation and causes the text to blur slightly. Signed-off-by: Andrew Jiang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c | 9 +++++---- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 4 ---- 2 files changed, 5 insertions(+), 8 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c index 9d9604f05095..f9e43e68fc0c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c @@ -159,10 +159,11 @@ bool dpp_get_optimal_number_of_taps( scl_data->taps.h_taps = 1; if (IDENTITY_RATIO(scl_data->ratios.vert)) scl_data->taps.v_taps = 1; - if (IDENTITY_RATIO(scl_data->ratios.horz_c)) - scl_data->taps.h_taps_c = 1; - if (IDENTITY_RATIO(scl_data->ratios.vert_c)) - scl_data->taps.v_taps_c = 1; + /* + * Spreadsheet doesn't handle taps_c is one properly, + * need to force Chroma to always be scaled to pass + * bandwidth validation. + */ } return true; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index dc878f77837b..4f124dc303dc 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -420,10 +420,6 @@ static const struct dc_debug debug_defaults_drv = { .force_abm_enable = false, .timing_trace = false, .clock_trace = true, - /* spread sheet doesn't handle taps_c is one properly, - * need to enable scaler for video surface to pass - * bandwidth validation.*/ - .always_scale = true, .disable_pplib_clock_request = true, .disable_pplib_wm_range = false, #if defined(CONFIG_DRM_AMD_DC_DCN1_0) -- cgit From 1049e39fa62f443aae64a2fb6057b96abf20e8de Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Thu, 7 Sep 2017 14:53:23 -0400 Subject: drm/amd/display: fix usb-c dongle regression A previous change moved link_disconnect_sink after dpcd read, this causes the sink count to be overwritten which in turn causes another detection to be triggered in the short pulse handler, which brings down the display. Signed-off-by: Eric Yang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index ee23b609d7dd..d5eaebeaeb89 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -652,8 +652,6 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) if (link->local_sink) { sink = link->local_sink; } else { - link_disconnect_sink(link); - sink_init_data.link = link; sink_init_data.sink_signal = sink_caps.signal; -- cgit From e008b0bcc63793d3e42fd88f412a90f329a05865 Mon Sep 17 00:00:00 2001 From: Roman Li Date: Thu, 7 Sep 2017 17:02:47 -0400 Subject: drm/amd/display: Add FBC on/off to front-end programming - Fixing text mode for cases when VT-switch doesn't result in timing change Signed-off-by: Roman Li Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index b3448a41718e..590b2ad37105 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -2554,6 +2554,15 @@ static void dce110_program_front_end_for_pipe( program_scaler(dc, pipe_ctx); +#ifdef ENABLE_FBC + if (dc->fbc_compressor && old_pipe->stream) { + if (plane_state->tiling_info.gfx8.array_mode == DC_ARRAY_LINEAR_GENERAL) + dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); + else + enable_fbc(dc, dc->current_state); + } +#endif + mi->funcs->mem_input_program_surface_config( mi, plane_state->format, -- cgit From 7d58e72149fa73504fa13e7044d68e79a39996fb Mon Sep 17 00:00:00 2001 From: Martin Tsai Date: Fri, 8 Sep 2017 19:25:35 +0800 Subject: drm/amd/display: To prevent detecting new sink from spurious HPD Signed-off-by: Martin Tsai Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 33 ++++++++++++++++----------- drivers/gpu/drm/amd/display/dc/dc_types.h | 1 + 2 files changed, 21 insertions(+), 13 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index d5eaebeaeb89..c7751a31081a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -649,27 +649,34 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) sink_init_data.link = link; sink_init_data.sink_signal = sink_caps.signal; - if (link->local_sink) { - sink = link->local_sink; - } else { - sink_init_data.link = link; - sink_init_data.sink_signal = sink_caps.signal; + sink = dc_sink_create(&sink_init_data); + if (!sink) { + DC_ERROR("Failed to create sink!\n"); + return false; + } - sink = dc_sink_create(&sink_init_data); - if (!sink) { - DC_ERROR("Failed to create sink!\n"); - return false; + if (link->local_sink) { + edid_status = dm_helpers_read_local_edid( + link->ctx, + link, + sink); + + if (edid_status == EDID_OK) { + // Edid is not the same, to update the local sink with new sink. + sink->dongle_max_pix_clk = sink_caps.max_hdmi_pixel_clock; + sink->converter_disable_audio = converter_disable_audio; + link->local_sink = sink; } + } else { sink->dongle_max_pix_clk = sink_caps.max_hdmi_pixel_clock; sink->converter_disable_audio = converter_disable_audio; - link->local_sink = sink; - } - edid_status = dm_helpers_read_local_edid( + edid_status = dm_helpers_read_local_edid( link->ctx, link, sink); + } switch (edid_status) { case EDID_BAD_CHECKSUM: @@ -762,7 +769,7 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) link->ctx, link, sink); - if (edid_status != EDID_OK) { + if (edid_status != EDID_OK && edid_status != EDID_THE_SAME) { link_disconnect_sink(link); link->type = dc_connection_none; sink_caps.signal = SIGNAL_TYPE_NONE; diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 6b891fde400c..4bd74fc6c782 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -151,6 +151,7 @@ enum dc_edid_status { EDID_BAD_INPUT, EDID_NO_RESPONSE, EDID_BAD_CHECKSUM, + EDID_THE_SAME, }; /* audio capability from EDID*/ -- cgit From 8580d60baed5c8c9f08a5c3b239e563c8966a9dc Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 17 Aug 2017 14:58:07 -0400 Subject: drm/amd/display: Don't report fake sink as connected This was missed in the previous fake sink change. The fake sink allows us to enable a pipe with a disconnected display. We shouldn't report it as connected. Signed-off-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') 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 8cc228ebdc9a..75212f74f027 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2453,7 +2453,8 @@ amdgpu_dm_connector_detect(struct drm_connector *connector, bool force) * 2. This interface *is called* in context of user-mode ioctl. Which * makes it a bad place for *any* MST-related activit. */ - if (aconnector->base.force == DRM_FORCE_UNSPECIFIED) + if (aconnector->base.force == DRM_FORCE_UNSPECIFIED && + !aconnector->fake_enable) connected = (aconnector->dc_sink != NULL); else connected = (aconnector->base.force == DRM_FORCE_ON); -- cgit From 024f0607cfed19a9f6082e4b94267544de4fc584 Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Mon, 11 Sep 2017 14:30:02 -0400 Subject: drm/amd/display: Refactor dcn10_dpp_cm_helper to dcn10_cm_common Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/Makefile | 2 +- .../gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c | 123 +++++++++++++++++++++ .../gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.h | 99 +++++++++++++++++ .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c | 2 +- .../drm/amd/display/dc/dcn10/dcn10_dpp_cm_helper.c | 123 --------------------- .../drm/amd/display/dc/dcn10/dcn10_dpp_cm_helper.h | 99 ----------------- 6 files changed, 224 insertions(+), 224 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm_helper.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm_helper.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile index 2d6d3a371858..6b19106f4679 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile @@ -4,7 +4,7 @@ DCN10 = dcn10_resource.o dcn10_ipp.o dcn10_hw_sequencer.o \ dcn10_dpp.o dcn10_opp.o dcn10_timing_generator.o \ dcn10_mem_input.o dcn10_mpc.o \ - dcn10_dpp_dscl.o dcn10_dpp_cm.o dcn10_dpp_cm_helper.o + dcn10_dpp_dscl.o dcn10_dpp_cm.o dcn10_cm_common.o AMD_DAL_DCN10 = $(addprefix $(AMDDALPATH)/dc/dcn10/,$(DCN10)) 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 new file mode 100644 index 000000000000..7f579cb19f4b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c @@ -0,0 +1,123 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "reg_helper.h" +#include "dcn10_dpp.h" + +#include "dcn10_cm_common.h" + +#define REG(reg) reg + +#define CTX \ + ctx + +#undef FN +#define FN(reg_name, field_name) \ + reg->shifts.field_name, reg->masks.field_name + +void cm_helper_program_color_matrices( + struct dc_context *ctx, + const uint16_t *regval, + const struct color_matrices_reg *reg) +{ + uint32_t cur_csc_reg; + unsigned int i = 0; + + for (cur_csc_reg = reg->csc_c11_c12; + cur_csc_reg <= reg->csc_c33_c34; + cur_csc_reg++) { + + const uint16_t *regval0 = &(regval[2 * i]); + const uint16_t *regval1 = &(regval[(2 * i) + 1]); + + REG_SET_2(cur_csc_reg, 0, + csc_c11, *regval0, + csc_c12, *regval1); + + i++; + } + +} + +void cm_helper_program_xfer_func( + struct dc_context *ctx, + const struct pwl_params *params, + const struct xfer_func_reg *reg) +{ + uint32_t reg_region_cur; + unsigned int i = 0; + + REG_SET_2(reg->start_cntl_b, 0, + exp_region_start, params->arr_points[0].custom_float_x, + exp_resion_start_segment, 0); + REG_SET_2(reg->start_cntl_g, 0, + exp_region_start, params->arr_points[0].custom_float_x, + exp_resion_start_segment, 0); + REG_SET_2(reg->start_cntl_r, 0, + exp_region_start, params->arr_points[0].custom_float_x, + exp_resion_start_segment, 0); + + REG_SET(reg->start_slope_cntl_b, 0, + field_region_linear_slope, params->arr_points[0].custom_float_slope); + REG_SET(reg->start_slope_cntl_g, 0, + field_region_linear_slope, params->arr_points[0].custom_float_slope); + REG_SET(reg->start_slope_cntl_r, 0, + field_region_linear_slope, params->arr_points[0].custom_float_slope); + + REG_SET(reg->start_end_cntl1_b, 0, + field_region_end, params->arr_points[1].custom_float_x); + REG_SET_2(reg->start_end_cntl2_b, 0, + field_region_end_slope, params->arr_points[1].custom_float_slope, + field_region_end_base, params->arr_points[1].custom_float_y); + + REG_SET(reg->start_end_cntl1_g, 0, + field_region_end, params->arr_points[1].custom_float_x); + REG_SET_2(reg->start_end_cntl2_g, 0, + field_region_end_slope, params->arr_points[1].custom_float_slope, + field_region_end_base, params->arr_points[1].custom_float_y); + + REG_SET(reg->start_end_cntl1_r, 0, + field_region_end, params->arr_points[1].custom_float_x); + REG_SET_2(reg->start_end_cntl2_r, 0, + field_region_end_slope, params->arr_points[1].custom_float_slope, + field_region_end_base, params->arr_points[1].custom_float_y); + + for (reg_region_cur = reg->region_start; + reg_region_cur <= reg->region_end; + reg_region_cur++) { + + const struct gamma_curve *curve0 = &(params->arr_curve_points[2 * i]); + const struct gamma_curve *curve1 = &(params->arr_curve_points[(2 * i) + 1]); + + REG_SET_4(reg_region_cur, 0, + exp_region0_lut_offset, curve0->offset, + exp_region0_num_segments, curve0->segments_num, + exp_region1_lut_offset, curve1->offset, + exp_region1_num_segments, curve1->segments_num); + + i++; + } + +} diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.h new file mode 100644 index 000000000000..64836dcf21f2 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.h @@ -0,0 +1,99 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_DCN10_CM_COMMON_H__ +#define __DAL_DCN10_CM_COMMON_H__ + +#define TF_HELPER_REG_FIELD_LIST(type) \ + type exp_region0_lut_offset; \ + type exp_region0_num_segments; \ + type exp_region1_lut_offset; \ + type exp_region1_num_segments;\ + type field_region_end;\ + type field_region_end_slope;\ + type field_region_end_base;\ + type exp_region_start;\ + type exp_resion_start_segment;\ + type field_region_linear_slope + +#define TF_CM_REG_FIELD_LIST(type) \ + type csc_c11; \ + type csc_c12 + +struct xfer_func_shift { + TF_HELPER_REG_FIELD_LIST(uint8_t); +}; + +struct xfer_func_mask { + TF_HELPER_REG_FIELD_LIST(uint32_t); +}; + +struct xfer_func_reg { + struct xfer_func_shift shifts; + struct xfer_func_mask masks; + + uint32_t start_cntl_b; + uint32_t start_cntl_g; + uint32_t start_cntl_r; + uint32_t start_slope_cntl_b; + uint32_t start_slope_cntl_g; + uint32_t start_slope_cntl_r; + uint32_t start_end_cntl1_b; + uint32_t start_end_cntl2_b; + uint32_t start_end_cntl1_g; + uint32_t start_end_cntl2_g; + uint32_t start_end_cntl1_r; + uint32_t start_end_cntl2_r; + uint32_t region_start; + uint32_t region_end; +}; + +struct cm_color_matrix_shift { + TF_CM_REG_FIELD_LIST(uint8_t); +}; + +struct cm_color_matrix_mask { + TF_CM_REG_FIELD_LIST(uint32_t); +}; + +struct color_matrices_reg{ + struct cm_color_matrix_shift shifts; + struct cm_color_matrix_mask masks; + + uint32_t csc_c11_c12; + uint32_t csc_c33_c34; +}; + +void cm_helper_program_color_matrices( + struct dc_context *ctx, + const uint16_t *regval, + const struct color_matrices_reg *reg); + +void cm_helper_program_xfer_func( + struct dc_context *ctx, + const struct pwl_params *params, + const struct xfer_func_reg *reg); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c index d0e72acfc1d5..61e2a8919e9c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c @@ -29,8 +29,8 @@ #include "reg_helper.h" #include "dcn10_dpp.h" -#include "dcn10_dpp_cm_helper.h" #include "basics/conversion.h" +#include "dcn10_cm_common.h" #define NUM_PHASES 64 #define HORZ_MAX_TAPS 8 diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm_helper.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm_helper.c deleted file mode 100644 index f616e08759de..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm_helper.c +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright 2016 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "reg_helper.h" -#include "dcn10_dpp.h" - -#include "dcn10_dpp_cm_helper.h" - -#define REG(reg) reg - -#define CTX \ - ctx - -#undef FN -#define FN(reg_name, field_name) \ - reg->shifts.field_name, reg->masks.field_name - -void cm_helper_program_color_matrices( - struct dc_context *ctx, - const uint16_t *regval, - const struct color_matrices_reg *reg) -{ - uint32_t cur_csc_reg; - unsigned int i = 0; - - for (cur_csc_reg = reg->csc_c11_c12; - cur_csc_reg <= reg->csc_c33_c34; - cur_csc_reg++) { - - const uint16_t *regval0 = &(regval[2 * i]); - const uint16_t *regval1 = &(regval[(2 * i) + 1]); - - REG_SET_2(cur_csc_reg, 0, - csc_c11, *regval0, - csc_c12, *regval1); - - i++; - } - -} - -void cm_helper_program_xfer_func( - struct dc_context *ctx, - const struct pwl_params *params, - const struct xfer_func_reg *reg) -{ - uint32_t reg_region_cur; - unsigned int i = 0; - - REG_SET_2(reg->start_cntl_b, 0, - exp_region_start, params->arr_points[0].custom_float_x, - exp_resion_start_segment, 0); - REG_SET_2(reg->start_cntl_g, 0, - exp_region_start, params->arr_points[0].custom_float_x, - exp_resion_start_segment, 0); - REG_SET_2(reg->start_cntl_r, 0, - exp_region_start, params->arr_points[0].custom_float_x, - exp_resion_start_segment, 0); - - REG_SET(reg->start_slope_cntl_b, 0, - field_region_linear_slope, params->arr_points[0].custom_float_slope); - REG_SET(reg->start_slope_cntl_g, 0, - field_region_linear_slope, params->arr_points[0].custom_float_slope); - REG_SET(reg->start_slope_cntl_r, 0, - field_region_linear_slope, params->arr_points[0].custom_float_slope); - - REG_SET(reg->start_end_cntl1_b, 0, - field_region_end, params->arr_points[1].custom_float_x); - REG_SET_2(reg->start_end_cntl2_b, 0, - field_region_end_slope, params->arr_points[1].custom_float_slope, - field_region_end_base, params->arr_points[1].custom_float_y); - - REG_SET(reg->start_end_cntl1_g, 0, - field_region_end, params->arr_points[1].custom_float_x); - REG_SET_2(reg->start_end_cntl2_g, 0, - field_region_end_slope, params->arr_points[1].custom_float_slope, - field_region_end_base, params->arr_points[1].custom_float_y); - - REG_SET(reg->start_end_cntl1_r, 0, - field_region_end, params->arr_points[1].custom_float_x); - REG_SET_2(reg->start_end_cntl2_r, 0, - field_region_end_slope, params->arr_points[1].custom_float_slope, - field_region_end_base, params->arr_points[1].custom_float_y); - - for (reg_region_cur = reg->region_start; - reg_region_cur <= reg->region_end; - reg_region_cur++) { - - const struct gamma_curve *curve0 = &(params->arr_curve_points[2 * i]); - const struct gamma_curve *curve1 = &(params->arr_curve_points[(2 * i) + 1]); - - REG_SET_4(reg_region_cur, 0, - exp_region0_lut_offset, curve0->offset, - exp_region0_num_segments, curve0->segments_num, - exp_region1_lut_offset, curve1->offset, - exp_region1_num_segments, curve1->segments_num); - - i++; - } - -} diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm_helper.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm_helper.h deleted file mode 100644 index 1155ee522898..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm_helper.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2016 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DAL_DPP_DCN10_CM_HELPER_H__ -#define __DAL_DPP_DCN10_CM_HELPER_H__ - -#define TF_HELPER_REG_FIELD_LIST(type) \ - type exp_region0_lut_offset; \ - type exp_region0_num_segments; \ - type exp_region1_lut_offset; \ - type exp_region1_num_segments;\ - type field_region_end;\ - type field_region_end_slope;\ - type field_region_end_base;\ - type exp_region_start;\ - type exp_resion_start_segment;\ - type field_region_linear_slope - -#define TF_CM_REG_FIELD_LIST(type) \ - type csc_c11; \ - type csc_c12 - -struct xfer_func_shift { - TF_HELPER_REG_FIELD_LIST(uint8_t); -}; - -struct xfer_func_mask { - TF_HELPER_REG_FIELD_LIST(uint32_t); -}; - -struct xfer_func_reg { - struct xfer_func_shift shifts; - struct xfer_func_mask masks; - - uint32_t start_cntl_b; - uint32_t start_cntl_g; - uint32_t start_cntl_r; - uint32_t start_slope_cntl_b; - uint32_t start_slope_cntl_g; - uint32_t start_slope_cntl_r; - uint32_t start_end_cntl1_b; - uint32_t start_end_cntl2_b; - uint32_t start_end_cntl1_g; - uint32_t start_end_cntl2_g; - uint32_t start_end_cntl1_r; - uint32_t start_end_cntl2_r; - uint32_t region_start; - uint32_t region_end; -}; - -struct cm_color_matrix_shift { - TF_CM_REG_FIELD_LIST(uint8_t); -}; - -struct cm_color_matrix_mask { - TF_CM_REG_FIELD_LIST(uint32_t); -}; - -struct color_matrices_reg{ - struct cm_color_matrix_shift shifts; - struct cm_color_matrix_mask masks; - - uint32_t csc_c11_c12; - uint32_t csc_c33_c34; -}; - -void cm_helper_program_color_matrices( - struct dc_context *ctx, - const uint16_t *regval, - const struct color_matrices_reg *reg); - -void cm_helper_program_xfer_func( - struct dc_context *ctx, - const struct pwl_params *params, - const struct xfer_func_reg *reg); - -#endif -- cgit From 98b49c2f9c66cf42b6d762498e2d9f327e439416 Mon Sep 17 00:00:00 2001 From: Roman Li Date: Mon, 11 Sep 2017 16:28:21 -0400 Subject: drm/amd/display: fix multi-display on CZ - fixed wrong index in dce110_validate_surface_sets() - formatted for better readability Signed-off-by: Roman Li Reviewed-by: Harry Wentland igned-off-by: Alex Deucher --- .../drm/amd/display/dc/dce110/dce110_resource.c | 29 ++++++++++++++++------ 1 file changed, 21 insertions(+), 8 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 28e768de744c..8e4ec61d59a4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -849,7 +849,7 @@ static bool dce110_validate_bandwidth( static bool dce110_validate_surface_sets( struct dc_state *context) { - int i; + int i, j; for (i = 0; i < context->stream_count; i++) { if (context->stream_status[i].plane_count == 0) @@ -858,14 +858,27 @@ static bool dce110_validate_surface_sets( if (context->stream_status[i].plane_count > 2) return false; - if ((context->stream_status[i].plane_states[i]->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) && - (context->stream_status[i].plane_states[i]->src_rect.width > 1920 || - context->stream_status[i].plane_states[i]->src_rect.height > 1080)) - return false; + for (j = 0; j < context->stream_status[i].plane_count; j++) { + struct dc_plane_state *plane = + context->stream_status[i].plane_states[j]; - /* irrespective of plane format, stream should be RGB encoded */ - if (context->streams[i]->timing.pixel_encoding != PIXEL_ENCODING_RGB) - return false; + /* underlay validation */ + if (plane->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) { + + if ((plane->src_rect.width > 1920 || + plane->src_rect.height > 1080)) + return false; + + /* irrespective of plane format, + * stream should be RGB encoded + */ + if (context->streams[i]->timing.pixel_encoding + != PIXEL_ENCODING_RGB) + return false; + + } + + } } return true; -- cgit From 7f4a7253b112c9ed21022e25c7a740d824c56619 Mon Sep 17 00:00:00 2001 From: Eric Bernstein Date: Mon, 11 Sep 2017 16:56:51 -0400 Subject: drm/amd/display: update mpc add/remove functions Signed-off-by: Eric Bernstein Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 17 +- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c | 173 ++++++++++++++------- drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h | 10 +- 3 files changed, 130 insertions(+), 70 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index e60be00abcf2..82a985a981be 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -881,7 +881,8 @@ static void dcn10_init_hw(struct dc *dc) xfm->funcs->transform_reset(xfm); dc->res_pool->mpc->funcs->remove( - dc->res_pool->mpc, dc->res_pool->opps[i], i); + dc->res_pool->mpc, &(dc->res_pool->opps[i]->mpc_tree), + dc->res_pool->opps[i]->inst, i); /* Blank controller using driver code instead of * command table. @@ -1079,7 +1080,8 @@ static void plane_atomic_disconnect(struct dc *dc, if (dc->debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); - mpc->funcs->remove(mpc, dc->res_pool->opps[opp_id], fe_idx); + mpc->funcs->remove(mpc, &(dc->res_pool->opps[opp_id]->mpc_tree), + dc->res_pool->opps[opp_id]->inst, fe_idx); } /* disable HW used by plane. @@ -2299,8 +2301,9 @@ static void update_dchubp_dpp( plane_state->format, EXPANSION_MODE_ZERO); - mpcc_cfg.mi = mi; - mpcc_cfg.opp = pipe_ctx->stream_res.opp; + mpcc_cfg.dpp_id = mi->inst; + mpcc_cfg.opp_id = pipe_ctx->stream_res.opp->inst; + mpcc_cfg.tree_cfg = &(pipe_ctx->stream_res.opp->mpc_tree); for (top_pipe = pipe_ctx->top_pipe; top_pipe; top_pipe = top_pipe->top_pipe) mpcc_cfg.z_index++; if (dc->debug.surface_visual_confirm) @@ -2317,7 +2320,8 @@ static void update_dchubp_dpp( mpcc_cfg.pre_multiplied_alpha = is_rgb_cspace( pipe_ctx->stream->output_color_space) && per_pixel_alpha; - dc->res_pool->mpc->funcs->add(dc->res_pool->mpc, &mpcc_cfg); + mi->mpcc_id = dc->res_pool->mpc->funcs->add(dc->res_pool->mpc, &mpcc_cfg); + mi->opp_id = mpcc_cfg.opp_id; pipe_ctx->plane_res.scl_data.lb_params.alpha_en = per_pixel_alpha; pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; @@ -2528,7 +2532,8 @@ static void dcn10_apply_ctx_for_surface( /* reset mpc */ dc->res_pool->mpc->funcs->remove( dc->res_pool->mpc, - old_pipe_ctx->stream_res.opp, + &(old_pipe_ctx->stream_res.opp->mpc_tree), + old_pipe_ctx->stream_res.opp->inst, old_pipe_ctx->pipe_idx); old_pipe_ctx->stream_res.opp->mpcc_disconnect_pending[old_pipe_ctx->plane_res.mi->mpcc_id] = true; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c index 082b39a65e6a..8e767c84359c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c @@ -118,17 +118,19 @@ static void mpc10_assert_mpcc_idle_before_connect(struct dcn10_mpc *mpc10, int i static void mpc10_mpcc_remove( struct mpc *mpc, - struct output_pixel_processor *opp, + struct mpc_tree_cfg *tree_cfg, + int opp_id, int dpp_id) { struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); int mpcc_id, z_idx; - for (z_idx = 0; z_idx < opp->mpc_tree.num_pipes; z_idx++) - if (opp->mpc_tree.dpp[z_idx] == dpp_id) + /* find z_idx for the dpp to be removed */ + for (z_idx = 0; z_idx < tree_cfg->num_pipes; z_idx++) + if (tree_cfg->dpp[z_idx] == dpp_id) break; - if (z_idx == opp->mpc_tree.num_pipes) { + if (z_idx == tree_cfg->num_pipes) { /* In case of resume from S3/S4, remove mpcc from bios left over */ REG_SET(MPCC_OPP_ID[dpp_id], 0, MPCC_OPP_ID, 0xf); @@ -139,7 +141,7 @@ static void mpc10_mpcc_remove( return; } - mpcc_id = opp->mpc_tree.mpcc[z_idx]; + mpcc_id = tree_cfg->mpcc[z_idx]; REG_SET(MPCC_OPP_ID[mpcc_id], 0, MPCC_OPP_ID, 0xf); @@ -149,82 +151,101 @@ static void mpc10_mpcc_remove( MPCC_BOT_SEL, 0xf); if (z_idx > 0) { - int top_mpcc_id = opp->mpc_tree.mpcc[z_idx - 1]; + int top_mpcc_id = tree_cfg->mpcc[z_idx - 1]; - if (z_idx + 1 < opp->mpc_tree.num_pipes) + if (z_idx + 1 < tree_cfg->num_pipes) + /* mpcc to be removed is in the middle of the tree */ REG_SET(MPCC_BOT_SEL[top_mpcc_id], 0, - MPCC_BOT_SEL, opp->mpc_tree.mpcc[z_idx + 1]); + MPCC_BOT_SEL, tree_cfg->mpcc[z_idx + 1]); else { + /* mpcc to be removed is at the bottom of the tree */ REG_SET(MPCC_BOT_SEL[top_mpcc_id], 0, MPCC_BOT_SEL, 0xf); REG_UPDATE(MPCC_CONTROL[top_mpcc_id], MPCC_MODE, MODE_TOP_ONLY); } - } else if (opp->mpc_tree.num_pipes > 1) - REG_SET(MUX[opp->inst], 0, - MPC_OUT_MUX, opp->mpc_tree.mpcc[z_idx + 1]); + } else if (tree_cfg->num_pipes > 1) + /* mpcc to be removed is at the top of the tree */ + REG_SET(MUX[opp_id], 0, + MPC_OUT_MUX, tree_cfg->mpcc[z_idx + 1]); else - REG_SET(MUX[opp->inst], 0, MPC_OUT_MUX, 0xf); + /* mpcc to be removed is the only one in the tree */ + REG_SET(MUX[opp_id], 0, MPC_OUT_MUX, 0xf); + /* mark this mpcc as not in use */ mpc10->mpcc_in_use_mask &= ~(1 << mpcc_id); - opp->mpc_tree.num_pipes--; - for (; z_idx < opp->mpc_tree.num_pipes; z_idx++) { - opp->mpc_tree.dpp[z_idx] = opp->mpc_tree.dpp[z_idx + 1]; - opp->mpc_tree.mpcc[z_idx] = opp->mpc_tree.mpcc[z_idx + 1]; + tree_cfg->num_pipes--; + for (; z_idx < tree_cfg->num_pipes; z_idx++) { + tree_cfg->dpp[z_idx] = tree_cfg->dpp[z_idx + 1]; + tree_cfg->mpcc[z_idx] = tree_cfg->mpcc[z_idx + 1]; } - opp->mpc_tree.dpp[opp->mpc_tree.num_pipes] = 0xdeadbeef; - opp->mpc_tree.mpcc[opp->mpc_tree.num_pipes] = 0xdeadbeef; + tree_cfg->dpp[tree_cfg->num_pipes] = 0xdeadbeef; + tree_cfg->mpcc[tree_cfg->num_pipes] = 0xdeadbeef; } -static void mpc10_mpcc_add(struct mpc *mpc, struct mpcc_cfg *cfg) +static void mpc10_add_to_tree_cfg( + struct mpc *mpc, + struct mpcc_cfg *cfg, + int mpcc_id) { struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); + int mpcc_mode = MODE_TOP_ONLY; + int position = cfg->z_index; + struct mpc_tree_cfg *tree_cfg = cfg->tree_cfg; int alpha_blnd_mode = cfg->per_pixel_alpha ? BLND_PP_ALPHA : BLND_GLOBAL_ALPHA; - int mpcc_mode = MODE_TOP_ONLY; - int mpcc_id, z_idx; + int z_idx; - ASSERT(cfg->z_index < mpc10->num_mpcc); + REG_SET(MPCC_OPP_ID[mpcc_id], 0, + MPCC_OPP_ID, cfg->opp_id); - for (z_idx = 0; z_idx < cfg->opp->mpc_tree.num_pipes; z_idx++) - if (cfg->opp->mpc_tree.dpp[z_idx] == cfg->mi->inst) - break; - if (z_idx == cfg->opp->mpc_tree.num_pipes) { - ASSERT(cfg->z_index <= cfg->opp->mpc_tree.num_pipes); - mpcc_id = mpc10_get_idle_mpcc_id(mpc10); - /*todo: remove hack*/ - mpcc_id = cfg->mi->inst; - ASSERT(!(mpc10->mpcc_in_use_mask & 1 << mpcc_id)); + REG_SET(MPCC_TOP_SEL[mpcc_id], 0, + MPCC_TOP_SEL, cfg->dpp_id); - if (mpc->ctx->dc->debug.sanity_checks) - mpc10_assert_mpcc_idle_before_connect(mpc10, mpcc_id); - } else { - ASSERT(cfg->z_index < cfg->opp->mpc_tree.num_pipes); - mpcc_id = cfg->opp->mpc_tree.mpcc[z_idx]; - mpc10_mpcc_remove(mpc, cfg->opp, cfg->mi->inst); - } + if (position == 0) { + /* idle dpp/mpcc is added to the top layer of tree */ - REG_SET(MPCC_OPP_ID[mpcc_id], 0, - MPCC_OPP_ID, cfg->opp->inst); + if (tree_cfg->num_pipes > 0) { + /* get instance of previous top mpcc */ + int prev_top_mpcc_id = tree_cfg->mpcc[0]; - REG_SET(MPCC_TOP_SEL[mpcc_id], 0, - MPCC_TOP_SEL, cfg->mi->inst); + REG_SET(MPCC_BOT_SEL[mpcc_id], 0, + MPCC_BOT_SEL, prev_top_mpcc_id); + mpcc_mode = MODE_BLEND; + } + + /* opp will get new output. from new added mpcc */ + REG_SET(MUX[cfg->opp_id], 0, MPC_OUT_MUX, mpcc_id); + + } else if (position == tree_cfg->num_pipes) { + /* idle dpp/mpcc is added to the bottom layer of tree */ - if (cfg->z_index > 0) { - int top_mpcc_id = cfg->opp->mpc_tree.mpcc[cfg->z_index - 1]; + /* get instance of previous bottom mpcc, set to middle layer */ + int prev_bot_mpcc_id = tree_cfg->mpcc[tree_cfg->num_pipes - 1]; - REG_SET(MPCC_BOT_SEL[top_mpcc_id], 0, + REG_SET(MPCC_BOT_SEL[prev_bot_mpcc_id], 0, MPCC_BOT_SEL, mpcc_id); - REG_UPDATE(MPCC_CONTROL[top_mpcc_id], + REG_UPDATE(MPCC_CONTROL[prev_bot_mpcc_id], MPCC_MODE, MODE_BLEND); - } else - REG_SET(MUX[cfg->opp->inst], 0, MPC_OUT_MUX, mpcc_id); - if (cfg->z_index < cfg->opp->mpc_tree.num_pipes) { - int bot_mpcc_id = cfg->opp->mpc_tree.mpcc[cfg->z_index]; + /* mpcc_id become new bottom mpcc*/ + REG_SET(MPCC_BOT_SEL[mpcc_id], 0, + MPCC_BOT_SEL, 0xf); + + } else { + /* idle dpp/mpcc is added to middle of tree */ + int above_mpcc_id = tree_cfg->mpcc[position - 1]; + int below_mpcc_id = tree_cfg->mpcc[position]; + + /* mpcc above new mpcc_id has new bottom mux*/ + REG_SET(MPCC_BOT_SEL[above_mpcc_id], 0, + MPCC_BOT_SEL, mpcc_id); + REG_UPDATE(MPCC_CONTROL[above_mpcc_id], + MPCC_MODE, MODE_BLEND); + /* mpcc_id bottom mux is from below mpcc*/ REG_SET(MPCC_BOT_SEL[mpcc_id], 0, - MPCC_BOT_SEL, bot_mpcc_id); + MPCC_BOT_SEL, below_mpcc_id); mpcc_mode = MODE_BLEND; } @@ -234,18 +255,50 @@ static void mpc10_mpcc_add(struct mpc *mpc, struct mpcc_cfg *cfg) MPCC_ALPHA_MULTIPLIED_MODE, cfg->pre_multiplied_alpha, MPCC_BLND_ACTIVE_OVERLAP_ONLY, false); + /* update mpc_tree_cfg with new mpcc */ + for (z_idx = tree_cfg->num_pipes; z_idx > position; z_idx--) { + tree_cfg->dpp[z_idx] = tree_cfg->dpp[z_idx - 1]; + tree_cfg->mpcc[z_idx] = tree_cfg->mpcc[z_idx - 1]; + } + tree_cfg->dpp[position] = cfg->dpp_id; + tree_cfg->mpcc[position] = mpcc_id; + tree_cfg->num_pipes++; +} + +static int mpc10_mpcc_add(struct mpc *mpc, struct mpcc_cfg *cfg) +{ + struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); + int mpcc_id, z_idx; + + ASSERT(cfg->z_index < mpc10->num_mpcc); + + /* check in dpp already exists in mpc tree */ + for (z_idx = 0; z_idx < cfg->tree_cfg->num_pipes; z_idx++) + if (cfg->tree_cfg->dpp[z_idx] == cfg->dpp_id) + break; + if (z_idx == cfg->tree_cfg->num_pipes) { + ASSERT(cfg->z_index <= cfg->tree_cfg->num_pipes); + mpcc_id = mpc10_get_idle_mpcc_id(mpc10); + ASSERT(!(mpc10->mpcc_in_use_mask & 1 << mpcc_id)); + + if (mpc->ctx->dc->debug.sanity_checks) + mpc10_assert_mpcc_idle_before_connect(mpc10, mpcc_id); + } else { + ASSERT(cfg->z_index < cfg->tree_cfg->num_pipes); + mpcc_id = cfg->tree_cfg->mpcc[z_idx]; + mpc10_mpcc_remove(mpc, cfg->tree_cfg, cfg->opp_id, cfg->dpp_id); + } + + /* add dpp/mpcc pair to mpc_tree_cfg and update mpcc registers */ + mpc10_add_to_tree_cfg(mpc, cfg, mpcc_id); + + /* set background color */ mpc10_set_bg_color(mpc10, &cfg->black_color, mpcc_id); + /* mark this mpcc as in use */ mpc10->mpcc_in_use_mask |= 1 << mpcc_id; - for (z_idx = cfg->opp->mpc_tree.num_pipes; z_idx > cfg->z_index; z_idx--) { - cfg->opp->mpc_tree.dpp[z_idx] = cfg->opp->mpc_tree.dpp[z_idx - 1]; - cfg->opp->mpc_tree.mpcc[z_idx] = cfg->opp->mpc_tree.mpcc[z_idx - 1]; - } - cfg->opp->mpc_tree.dpp[cfg->z_index] = cfg->mi->inst; - cfg->opp->mpc_tree.mpcc[cfg->z_index] = mpcc_id; - cfg->opp->mpc_tree.num_pipes++; - cfg->mi->opp_id = cfg->opp->inst; - cfg->mi->mpcc_id = mpcc_id; + + return mpcc_id; } const struct mpc_funcs dcn10_mpc_funcs = { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h index 4bbcff48acc8..2d3de5b68e34 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h @@ -29,8 +29,9 @@ #include "opp.h" struct mpcc_cfg { - struct mem_input *mi; - struct output_pixel_processor *opp; + int dpp_id; + int opp_id; + struct mpc_tree_cfg *tree_cfg; unsigned int z_index; struct tg_color black_color; @@ -44,9 +45,10 @@ struct mpc { }; struct mpc_funcs { - void (*add)(struct mpc *mpc, struct mpcc_cfg *cfg); + int (*add)(struct mpc *mpc, struct mpcc_cfg *cfg); void (*remove)(struct mpc *mpc, - struct output_pixel_processor *opp, + struct mpc_tree_cfg *tree_cfg, + int opp_id, int mpcc_inst); void (*wait_for_idle)(struct mpc *mpc, int id); }; -- cgit From 4f346e655d24140fb40b46f814506ba17ac34ea1 Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Thu, 7 Sep 2017 17:05:38 -0400 Subject: drm/amd/display: Match actual state during S3 resume. During system suspend, we: 1. Cache a duplicate of the current DRM atomic state, which calls hooks to duplicate our internal states. 2. Call hooks to disable all functionalities. 3. System suspended. During resume, we attempt to restore the cached state. However, our interal states are now stale, since step 1 was done before step 2. i.e. our cached state does not reflect the disabled nature of things. This change resolves that by destroying all relevant states to reflect the actual state during resume. Signed-off-by: Leo (Sunpeng) Li Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 36 +++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'drivers/gpu') 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 75212f74f027..ecca2862407f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -648,6 +648,11 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev) struct drm_connector *connector; struct drm_crtc *crtc; struct drm_crtc_state *new_crtc_state; + struct dm_crtc_state *dm_crtc_state; + struct drm_plane *plane; + struct drm_plane_state *plane_state; + struct dm_plane_state *dm_plane_state; + struct dm_atomic_state *cached_state; int ret = 0; int i; @@ -686,6 +691,37 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev) for_each_new_crtc_in_state(adev->dm.cached_state, crtc, new_crtc_state, i) new_crtc_state->active_changed = true; + cached_state = to_dm_atomic_state(adev->dm.cached_state); + + /* + * During suspend, the cached state is saved before all streams are + * disabled. Refresh cached state to match actual current state before + * restoring it. + */ + WARN_ON(kref_read(&cached_state->context->refcount) > 1); + dc_release_state(cached_state->context); + + cached_state->context = dc_create_state(); + dc_resource_state_copy_construct_current(adev->dm.dc, cached_state->context); + + for_each_new_crtc_in_state(adev->dm.cached_state, crtc, new_crtc_state, i) { + dm_crtc_state = to_dm_crtc_state(new_crtc_state); + if (dm_crtc_state->stream) { + WARN_ON(kref_read(&dm_crtc_state->stream->refcount) > 1); + dc_stream_release(dm_crtc_state->stream); + dm_crtc_state->stream = NULL; + } + } + + for_each_new_plane_in_state(adev->dm.cached_state, plane, plane_state, i) { + dm_plane_state = to_dm_plane_state(plane_state); + if (dm_plane_state->dc_state) { + WARN_ON(kref_read(&dm_plane_state->dc_state->refcount) > 1); + dc_plane_state_release(dm_plane_state->dc_state); + dm_plane_state->dc_state = NULL; + } + } + ret = drm_atomic_helper_resume(ddev, adev->dm.cached_state); drm_atomic_state_put(adev->dm.cached_state); -- cgit From eade83503a5381ab0292f9653786bec6a638c523 Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Tue, 12 Sep 2017 12:08:14 -0400 Subject: drm/amd/display: fixing register includes Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h | 89 +++++++++++----------- .../gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h | 2 + 2 files changed, 46 insertions(+), 45 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index 2d3a41f744af..589332019a83 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -131,8 +131,6 @@ HWSEQ_PHYPLL_REG_LIST(CRTC) #define HWSEQ_DCN_REG_LIST()\ - HWSEQ_PIXEL_RATE_REG_LIST(OTG), \ - HWSEQ_PHYPLL_REG_LIST(OTG), \ SRII(OTG_GLOBAL_SYNC_STATUS, OTG, 0), \ SRII(OTG_GLOBAL_SYNC_STATUS, OTG, 1), \ SRII(OTG_GLOBAL_SYNC_STATUS, OTG, 2), \ @@ -182,22 +180,6 @@ SR(DCHUBBUB_TEST_DEBUG_INDEX), \ SR(DCHUBBUB_TEST_DEBUG_DATA), \ SR(DC_IP_REQUEST_CNTL), \ - SR(DOMAIN0_PG_CONFIG), \ - SR(DOMAIN1_PG_CONFIG), \ - SR(DOMAIN2_PG_CONFIG), \ - SR(DOMAIN3_PG_CONFIG), \ - SR(DOMAIN4_PG_CONFIG), \ - SR(DOMAIN5_PG_CONFIG), \ - SR(DOMAIN6_PG_CONFIG), \ - SR(DOMAIN7_PG_CONFIG), \ - SR(DOMAIN0_PG_STATUS), \ - SR(DOMAIN1_PG_STATUS), \ - SR(DOMAIN2_PG_STATUS), \ - SR(DOMAIN3_PG_STATUS), \ - SR(DOMAIN4_PG_STATUS), \ - SR(DOMAIN5_PG_STATUS), \ - SR(DOMAIN6_PG_STATUS), \ - SR(DOMAIN7_PG_STATUS), \ SR(DIO_MEM_PWR_CTRL), \ SR(DCCG_GATE_DISABLE_CNTL), \ SR(DCCG_GATE_DISABLE_CNTL2), \ @@ -223,13 +205,30 @@ #define HWSEQ_DCN1_REG_LIST()\ HWSEQ_DCN_REG_LIST(), \ + HWSEQ_PIXEL_RATE_REG_LIST(OTG), \ + HWSEQ_PHYPLL_REG_LIST(OTG), \ SR(DCHUBBUB_SDPIF_FB_TOP),\ SR(DCHUBBUB_SDPIF_FB_BASE),\ SR(DCHUBBUB_SDPIF_FB_OFFSET),\ SR(DCHUBBUB_SDPIF_AGP_BASE),\ SR(DCHUBBUB_SDPIF_AGP_BOT),\ - SR(DCHUBBUB_SDPIF_AGP_TOP) - + SR(DCHUBBUB_SDPIF_AGP_TOP),\ + SR(DOMAIN0_PG_CONFIG), \ + SR(DOMAIN1_PG_CONFIG), \ + SR(DOMAIN2_PG_CONFIG), \ + SR(DOMAIN3_PG_CONFIG), \ + SR(DOMAIN4_PG_CONFIG), \ + SR(DOMAIN5_PG_CONFIG), \ + SR(DOMAIN6_PG_CONFIG), \ + SR(DOMAIN7_PG_CONFIG), \ + SR(DOMAIN0_PG_STATUS), \ + SR(DOMAIN1_PG_STATUS), \ + SR(DOMAIN2_PG_STATUS), \ + SR(DOMAIN3_PG_STATUS), \ + SR(DOMAIN4_PG_STATUS), \ + SR(DOMAIN5_PG_STATUS), \ + SR(DOMAIN6_PG_STATUS), \ + SR(DOMAIN7_PG_STATUS) struct dce_hwseq_registers { uint32_t DCFE_CLOCK_CONTROL[6]; @@ -417,30 +416,6 @@ struct dce_hwseq_registers { HWS_SF(OPP_PIPE0_, OPP_PIPE_CONTROL, OPP_PIPE_CLOCK_EN, mask_sh),\ HWS_SF(, DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, mask_sh), \ HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh), \ - HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN0_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN0_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN1_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN1_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN2_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN2_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN3_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN3_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN4_PG_CONFIG, DOMAIN4_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN4_PG_CONFIG, DOMAIN4_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN5_PG_CONFIG, DOMAIN5_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN5_PG_CONFIG, DOMAIN5_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN6_PG_CONFIG, DOMAIN6_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN6_PG_CONFIG, DOMAIN6_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN7_PG_CONFIG, DOMAIN7_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN7_PG_CONFIG, DOMAIN7_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN0_PG_STATUS, DOMAIN0_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN1_PG_STATUS, DOMAIN1_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN2_PG_STATUS, DOMAIN2_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN3_PG_STATUS, DOMAIN3_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN4_PG_STATUS, DOMAIN4_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN5_PG_STATUS, DOMAIN5_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN6_PG_STATUS, DOMAIN6_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN7_PG_STATUS, DOMAIN7_PGFSM_PWR_STATUS, mask_sh), \ HWS_SF(, DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, mask_sh), \ HWS_SF(, DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE, mask_sh), \ HWS_SF(, DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE, mask_sh), \ @@ -468,7 +443,31 @@ struct dce_hwseq_registers { HWS_SF(, VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32, PHYSICAL_PAGE_ADDR_LO32, mask_sh),\ HWS_SF(, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, PHYSICAL_PAGE_NUMBER_MSB, mask_sh),\ HWS_SF(, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, PHYSICAL_PAGE_NUMBER_LSB, mask_sh),\ - HWS_SF(, MC_VM_SYSTEM_APERTURE_LOW_ADDR, LOGICAL_ADDR, mask_sh) + HWS_SF(, MC_VM_SYSTEM_APERTURE_LOW_ADDR, LOGICAL_ADDR, mask_sh),\ + HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN0_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN0_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN1_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN1_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN2_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN2_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN3_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN3_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN4_PG_CONFIG, DOMAIN4_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN4_PG_CONFIG, DOMAIN4_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN5_PG_CONFIG, DOMAIN5_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN5_PG_CONFIG, DOMAIN5_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN6_PG_CONFIG, DOMAIN6_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN6_PG_CONFIG, DOMAIN6_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN7_PG_CONFIG, DOMAIN7_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN7_PG_CONFIG, DOMAIN7_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN0_PG_STATUS, DOMAIN0_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN1_PG_STATUS, DOMAIN1_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN2_PG_STATUS, DOMAIN2_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN3_PG_STATUS, DOMAIN3_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN4_PG_STATUS, DOMAIN4_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN5_PG_STATUS, DOMAIN5_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN6_PG_STATUS, DOMAIN6_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN7_PG_STATUS, DOMAIN7_PGFSM_PWR_STATUS, mask_sh) #define HWSEQ_REG_FIELD_LIST(type) \ type DCFE_CLOCK_ENABLE; \ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h index aefd3e7bd7eb..0b7d4faff82f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h @@ -120,6 +120,8 @@ SR(DCHUBBUB_SDPIF_FB_BASE),\ SR(DCHUBBUB_SDPIF_FB_OFFSET) + + struct dcn_mi_registers { uint32_t DCHUBP_CNTL; uint32_t HUBPREQ_DEBUG_DB; -- cgit From f4ac176e62fdc74e52ee58461fb7c8912322fc1c Mon Sep 17 00:00:00 2001 From: Jerry Zuo Date: Fri, 8 Sep 2017 11:52:45 -0400 Subject: drm/amd/display: Exclude MST from fake sink Needs effort to take care of the fake sink scenario in downstream daisy chain device. Exclude MST from fake sink feature for now. Signed-off-by: Jerry Zuo Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') 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 ecca2862407f..dfea04fed695 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2354,8 +2354,16 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, drm_connector = &aconnector->base; - if (!aconnector->dc_sink) + if (!aconnector->dc_sink) { + /* + * Exclude MST from creating fake_sink + * TODO: need to enable MST into fake_sink feature + */ + if (aconnector->mst_port) + goto stream_create_fail; + create_fake_sink(aconnector); + } stream = dc_create_stream_for_sink(aconnector->dc_sink); @@ -4376,7 +4384,8 @@ static int dm_update_crtcs_state(struct dc *dc, aconnector = amdgpu_dm_find_first_crtc_matching_connector(state, crtc); /* TODO This hack should go away */ - if (aconnector) { + if (aconnector && enable) { + // Make sure fake sink is created in plug-in scenario new_con_state = drm_atomic_get_connector_state(state, &aconnector->base); -- cgit From fc17235fe65b0179969e0793a086cba93afcc078 Mon Sep 17 00:00:00 2001 From: Jerry Zuo Date: Fri, 8 Sep 2017 16:40:34 -0400 Subject: drm/amd/display: Fix NULL pointer on MST chained mode Prevent NULL pointer on new_stream being added to ctx when added MST connectors cannot be found in existing crtc_state in the chained mode Signed-off-by: Jerry Zuo Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/gpu') 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 dfea04fed695..f2724713ddd0 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4462,6 +4462,13 @@ static int dm_update_crtcs_state(struct dc *dc, *lock_and_validation_needed = true; } else {/* Add stream for any updated/enabled CRTC */ + /* + * Quick fix to prevent NULL pointer on new_stream when + * added MST connectors not found in existing crtc_state in the chained mode + * TODO: need to dig out the root cause of that + */ + if (!aconnector || (!aconnector->dc_sink && aconnector->mst_port)) + continue; if (modereset_required(new_crtc_state)) goto next_crtc; -- cgit From bc6828e0e6b6c5bcafbb093f9fe475f63dbe47e5 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Tue, 12 Sep 2017 13:56:57 -0400 Subject: drm/amd/display: Refactor dc_update_planes_and_stream. Split update_planes_and_stream_state (split Software and Hardware programming) as the state is already build, so we only need to program the hardware Signed-off-by: Andrey Grodzovsky Signed-off-by: Bhawanpreet Lakha Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 21 +- drivers/gpu/drm/amd/display/dc/core/dc.c | 256 +++++----------------- drivers/gpu/drm/amd/display/dc/dc.h | 36 +-- 3 files changed, 87 insertions(+), 226 deletions(-) (limited to 'drivers/gpu') 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 f2724713ddd0..6c04ad1b5859 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3771,7 +3771,8 @@ static void prepare_flip_isr(struct amdgpu_crtc *acrtc) */ static void amdgpu_dm_do_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, - uint32_t target) + uint32_t target, + struct dc_state *state) { unsigned long flags; uint32_t target_vblank; @@ -3842,7 +3843,13 @@ static void amdgpu_dm_do_flip(struct drm_crtc *crtc, surface_updates->flip_addr = &addr; - dc_update_planes_and_stream(adev->dm.dc, surface_updates, 1, acrtc_state->stream, NULL); + dc_commit_updates_for_stream(adev->dm.dc, + surface_updates, + 1, + acrtc_state->stream, + NULL, + &surface_updates->surface, + state); DRM_DEBUG_DRIVER("%s Flipping to hi: 0x%x, low: 0x%x \n", __func__, @@ -3868,6 +3875,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, struct drm_crtc_state *new_pcrtc_state = drm_atomic_get_new_crtc_state(state, pcrtc); struct dm_crtc_state *acrtc_state = to_dm_crtc_state(new_pcrtc_state); + struct dm_atomic_state *dm_state = to_dm_atomic_state(state); int planes_count = 0; unsigned long flags; @@ -3925,7 +3933,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, amdgpu_dm_do_flip( crtc, fb, - drm_crtc_vblank_count(crtc) + *wait_for_vblank); + drm_crtc_vblank_count(crtc) + *wait_for_vblank, + dm_state->context); } } @@ -3945,7 +3954,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, if (false == dc_commit_planes_to_stream(dm->dc, plane_states_constructed, planes_count, - dc_stream_attach)) + dc_stream_attach, + dm_state->context)) dm_error("%s: Failed to attach plane!\n", __func__); } else { /*TODO BUG Here should go disable planes on CRTC. */ @@ -4165,7 +4175,8 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) dm->dc, status->plane_states, status->plane_count, - dm_new_crtc_state->stream)) + dm_new_crtc_state->stream, + dm_state->context)) dm_error("%s: Failed to update stream scaling!\n", __func__); } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 47f16a4b9f27..1ec6df9870da 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -869,7 +869,8 @@ bool dc_commit_planes_to_stream( struct dc *dc, struct dc_plane_state **plane_states, uint8_t new_plane_count, - struct dc_stream_state *dc_stream) + struct dc_stream_state *dc_stream, + struct dc_state *state) { struct dc_surface_update updates[MAX_SURFACES]; struct dc_flip_addrs flip_addr[MAX_SURFACES]; @@ -920,11 +921,11 @@ bool dc_commit_planes_to_stream( updates[i].scaling_info = &scaling_info[i]; } - dc_update_planes_and_stream( + dc_commit_updates_for_stream( dc, updates, new_plane_count, - dc_stream, stream_update); + dc_stream, stream_update, plane_states, state); dc_post_update_surfaces_to_stream(dc); @@ -1150,192 +1151,20 @@ static struct dc_stream_status *stream_get_status( static const enum surface_update_type update_surface_trace_level = UPDATE_TYPE_FULL; -void dc_update_planes_and_stream(struct dc *dc, - struct dc_surface_update *srf_updates, int surface_count, + +static void commit_planes_for_stream(struct dc *dc, + struct dc_surface_update *srf_updates, + int surface_count, struct dc_stream_state *stream, - struct dc_stream_update *stream_update) + struct dc_stream_update *stream_update, + enum surface_update_type update_type, + struct dc_state *context) { - struct dc_state *context; int i, j; - enum surface_update_type update_type; - const struct dc_stream_status *stream_status; - struct dc_context *dc_ctx = dc->ctx; - - stream_status = dc_stream_get_status(stream); - - ASSERT(stream_status); - if (!stream_status) - return; /* Cannot commit surface to stream that is not committed */ - -#ifdef ENABLE_FBC - if (srf_updates->flip_addr) { - if (srf_updates->flip_addr->address.grph.addr.low_part == 0) - ASSERT(0); - } -#endif - context = dc->current_state; - - /* update current stream with the new updates */ - if (stream_update) { - if ((stream_update->src.height != 0) && - (stream_update->src.width != 0)) - stream->src = stream_update->src; - - if ((stream_update->dst.height != 0) && - (stream_update->dst.width != 0)) - stream->dst = stream_update->dst; - - if (stream_update->out_transfer_func && - stream_update->out_transfer_func != - stream->out_transfer_func) { - if (stream->out_transfer_func != NULL) - dc_transfer_func_release(stream->out_transfer_func); - dc_transfer_func_retain(stream_update->out_transfer_func); - stream->out_transfer_func = - stream_update->out_transfer_func; - } - } - - /* do not perform surface update if surface has invalid dimensions - * (all zero) and no scaling_info is provided - */ - if (surface_count > 0 && - srf_updates->surface->src_rect.width == 0 && - srf_updates->surface->src_rect.height == 0 && - srf_updates->surface->dst_rect.width == 0 && - srf_updates->surface->dst_rect.height == 0 && - !srf_updates->scaling_info) { - ASSERT(false); - return; - } - - update_type = dc_check_update_surfaces_for_stream( - dc, srf_updates, surface_count, stream_update, stream_status); - - if (update_type >= update_surface_trace_level) - update_surface_trace(dc, srf_updates, surface_count); - - if (update_type >= UPDATE_TYPE_FULL) { - struct dc_plane_state *new_planes[MAX_SURFACES] = {0}; - - for (i = 0; i < surface_count; i++) - new_planes[i] = srf_updates[i].surface; - - /* initialize scratch memory for building context */ - context = dc_create_state(); - if (context == NULL) { - DC_ERROR("Failed to allocate new validate context!\n"); - return; - } - - dc_resource_state_copy_construct( - dc->current_state, context); - - /*remove old surfaces from context */ - if (!dc_rem_all_planes_for_stream(dc, stream, context)) { - - BREAK_TO_DEBUGGER(); - goto fail; - } - - /* add surface to context */ - if (!dc_add_all_planes_for_stream(dc, stream, new_planes, surface_count, context)) { - - BREAK_TO_DEBUGGER(); - goto fail; - } - } - - /* save update parameters into surface */ - for (i = 0; i < surface_count; i++) { - struct dc_plane_state *surface = srf_updates[i].surface; - - if (srf_updates[i].flip_addr) { - surface->address = srf_updates[i].flip_addr->address; - surface->flip_immediate = - srf_updates[i].flip_addr->flip_immediate; - } - - if (srf_updates[i].scaling_info) { - surface->scaling_quality = - srf_updates[i].scaling_info->scaling_quality; - surface->dst_rect = - srf_updates[i].scaling_info->dst_rect; - surface->src_rect = - srf_updates[i].scaling_info->src_rect; - surface->clip_rect = - srf_updates[i].scaling_info->clip_rect; - } - - if (srf_updates[i].plane_info) { - surface->color_space = - srf_updates[i].plane_info->color_space; - surface->format = - srf_updates[i].plane_info->format; - surface->plane_size = - srf_updates[i].plane_info->plane_size; - surface->rotation = - srf_updates[i].plane_info->rotation; - surface->horizontal_mirror = - srf_updates[i].plane_info->horizontal_mirror; - surface->stereo_format = - srf_updates[i].plane_info->stereo_format; - surface->tiling_info = - srf_updates[i].plane_info->tiling_info; - surface->visible = - srf_updates[i].plane_info->visible; - surface->per_pixel_alpha = - srf_updates[i].plane_info->per_pixel_alpha; - surface->dcc = - srf_updates[i].plane_info->dcc; - } - - if (update_type >= UPDATE_TYPE_MED) { - for (j = 0; j < dc->res_pool->pipe_count; j++) { - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - - if (pipe_ctx->plane_state != surface) - continue; - - resource_build_scaling_params(pipe_ctx); - } - } - - if (srf_updates[i].gamma && - srf_updates[i].gamma != surface->gamma_correction) { - if (surface->gamma_correction != NULL) - dc_gamma_release(&surface->gamma_correction); - - dc_gamma_retain(srf_updates[i].gamma); - surface->gamma_correction = srf_updates[i].gamma; - } - - if (srf_updates[i].in_transfer_func && - srf_updates[i].in_transfer_func != surface->in_transfer_func) { - if (surface->in_transfer_func != NULL) - dc_transfer_func_release( - surface-> - in_transfer_func); - - dc_transfer_func_retain( - srf_updates[i].in_transfer_func); - surface->in_transfer_func = - srf_updates[i].in_transfer_func; - } - - if (srf_updates[i].hdr_static_metadata) - surface->hdr_static_ctx = - *(srf_updates[i].hdr_static_metadata); - } if (update_type == UPDATE_TYPE_FULL) { - if (!dc->res_pool->funcs->validate_bandwidth(dc, context)) { - BREAK_TO_DEBUGGER(); - goto fail; - } else { - dc->hwss.set_bandwidth(dc, context, false); - context_clock_trace(dc, context); - } + dc->hwss.set_bandwidth(dc, context, false); + context_clock_trace(dc, context); } if (update_type > UPDATE_TYPE_FAST) { @@ -1459,27 +1288,60 @@ void dc_update_planes_and_stream(struct dc *dc, break; } } +} + +void dc_commit_updates_for_stream(struct dc *dc, + struct dc_surface_update *srf_updates, + int surface_count, + struct dc_stream_state *stream, + struct dc_stream_update *stream_update, + struct dc_plane_state **plane_states, + struct dc_state *state) +{ + const struct dc_stream_status *stream_status; + enum surface_update_type update_type; + struct dc_state *context; + int i; - if (dc->current_state != context) { + stream_status = dc_stream_get_status(stream); + context = dc->current_state; + + update_type = dc_check_update_surfaces_for_stream( + dc, srf_updates, surface_count, stream_update, stream_status); + + if (update_type >= update_surface_trace_level) + update_surface_trace(dc, srf_updates, surface_count); - /* Since memory free requires elevated IRQL, an interrupt - * request is generated by mem free. If this happens - * between freeing and reassigning the context, our vsync - * interrupt will call into dc and cause a memory - * corruption BSOD. Hence, we first reassign the context, - * then free the old context. - */ - struct dc_state *old = dc->current_state; + if (update_type >= UPDATE_TYPE_FULL) + dc_resource_state_copy_construct(state, context); - dc->current_state = context; - dc_release_state(old); + + for (i = 0; i < surface_count; i++) { + struct dc_plane_state *surface = srf_updates[i].surface; + + /* TODO: On flip we don't build the state, so it still has the + * old address. Which is why we are updating the address here + */ + if (srf_updates[i].flip_addr) + surface->address = srf_updates[i].flip_addr->address; } + + + commit_planes_for_stream( + dc, + srf_updates, + surface_count, + stream, + stream_update, + update_type, + context); + + dc_post_update_surfaces_to_stream(dc); + return; -fail: - dc_release_state(context); } uint8_t dc_get_current_stream_count(struct dc *dc) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 4ff543826476..50440731f83c 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -449,23 +449,6 @@ struct dc_flip_addrs { /* TODO: add flip duration for FreeSync */ }; -/* - * Set up surface attributes and associate to a stream - * The surfaces parameter is an absolute set of all surface active for the stream. - * If no surfaces are provided, the stream will be blanked; no memory read. - * Any flip related attribute changes must be done through this interface. - * - * After this call: - * Surfaces attributes are programmed and configured to be composed into stream. - * This does not trigger a flip. No surface address is programmed. - */ - -bool dc_commit_planes_to_stream( - struct dc *dc, - struct dc_plane_state **plane_states, - uint8_t new_plane_count, - struct dc_stream_state *stream); - bool dc_post_update_surfaces_to_stream( struct dc *dc); @@ -571,9 +554,6 @@ bool dc_is_stream_unchanged( struct dc_stream_state *old_stream, struct dc_stream_state *stream); /* - * Setup stream attributes if no stream updates are provided - * there will be no impact on the stream parameters - * * Set up surface attributes and associate to a stream * The surfaces parameter is an absolute set of all surface active for the stream. * If no surfaces are provided, the stream will be blanked; no memory read. @@ -582,14 +562,22 @@ bool dc_is_stream_unchanged( * After this call: * Surfaces attributes are programmed and configured to be composed into stream. * This does not trigger a flip. No surface address is programmed. - * */ -void dc_update_planes_and_stream(struct dc *dc, - struct dc_surface_update *surface_updates, int surface_count, +bool dc_commit_planes_to_stream( + struct dc *dc, + struct dc_plane_state **plane_states, + uint8_t new_plane_count, struct dc_stream_state *dc_stream, - struct dc_stream_update *stream_update); + struct dc_state *state); +void dc_commit_updates_for_stream(struct dc *dc, + struct dc_surface_update *srf_updates, + int surface_count, + struct dc_stream_state *stream, + struct dc_stream_update *stream_update, + struct dc_plane_state **plane_states, + struct dc_state *state); /* * Log the current stream state. */ -- cgit From 4b7e7e2b1bb2c7308ee3ccbef3f67cb9ce52e954 Mon Sep 17 00:00:00 2001 From: ShihChen Chen Date: Tue, 12 Sep 2017 11:10:12 +0800 Subject: drm/amd/display: make tile changing run at ISR Signed-off-by: ShihChen Chen Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 1ec6df9870da..2cea8de9c9be 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1031,7 +1031,6 @@ static enum surface_update_type get_plane_info_update_type( temp_plane_info.plane_size = u->surface->plane_size; temp_plane_info.rotation = u->surface->rotation; temp_plane_info.stereo_format = u->surface->stereo_format; - temp_plane_info.tiling_info = u->surface->tiling_info; if (surface_index == 0) temp_plane_info.visible = u->plane_info->visible; @@ -1044,10 +1043,26 @@ static enum surface_update_type get_plane_info_update_type( if (pixel_format_to_bpp(u->plane_info->format) != pixel_format_to_bpp(u->surface->format)) { + /* different bytes per element will require full bandwidth + * and DML calculation + */ return UPDATE_TYPE_FULL; - } else { - return UPDATE_TYPE_MED; } + + if (memcmp(&u->plane_info->tiling_info, &u->surface->tiling_info, + sizeof(union dc_tiling_info)) != 0) { + /* todo: below are HW dependent, we should add a hook to + * DCE/N resource and validated there. + */ + if (u->plane_info->tiling_info.gfx9.swizzle != DC_SW_LINEAR) { + /* swizzled mode requires RQ to be setup properly, + * thus need to run DML to calculate RQ settings + */ + return UPDATE_TYPE_FULL; + } + } + + return UPDATE_TYPE_MED; } static enum surface_update_type get_scaling_info_update_type( -- cgit From 68d77dd8214e5186d535ec7af29722aaad621824 Mon Sep 17 00:00:00 2001 From: Andrew Jiang Date: Wed, 13 Sep 2017 11:36:34 -0400 Subject: drm/amd/display: power_down_Hw need signal type to turnoff backlight Signed-off-by: Charlene Liu Reviewed-by: Anthony Koo Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 590b2ad37105..d83a330712f7 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1171,6 +1171,7 @@ static void power_down_encoders(struct dc *dc) { int i; enum connector_id connector_id; + enum signal_type signal = SIGNAL_TYPE_NONE; for (i = 0; i < dc->link_count; i++) { connector_id = dal_graphics_object_id_get_connector_id(dc->links[i]->link_id); if ((connector_id == CONNECTOR_ID_DISPLAY_PORT) || @@ -1178,10 +1179,12 @@ static void power_down_encoders(struct dc *dc) if (!dc->links[i]->wa_flags.dp_keep_receiver_powered) dp_receiver_power_ctrl(dc->links[i], false); + if (connector_id == CONNECTOR_ID_EDP) + signal = SIGNAL_TYPE_EDP; } dc->links[i]->link_enc->funcs->disable_output( - dc->links[i]->link_enc, SIGNAL_TYPE_NONE); + dc->links[i]->link_enc, signal); } } -- cgit From d53d7866a795410f7b6a16b1ef0b37825edc794e Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Thu, 14 Sep 2017 11:27:34 -0400 Subject: drm/amd/display: removing remaining register definitions work around Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h | 16 ++++++++-------- .../gpu/drm/amd/display/dc/dce/dce_link_encoder.h | 21 ++++++++++++++------- .../amd/display/dc/dcn10/dcn10_timing_generator.h | 11 +---------- 3 files changed, 23 insertions(+), 25 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index 589332019a83..5798001da770 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -179,16 +179,11 @@ SR(DCHUBBUB_GLOBAL_TIMER_CNTL), \ SR(DCHUBBUB_TEST_DEBUG_INDEX), \ SR(DCHUBBUB_TEST_DEBUG_DATA), \ - SR(DC_IP_REQUEST_CNTL), \ SR(DIO_MEM_PWR_CTRL), \ SR(DCCG_GATE_DISABLE_CNTL), \ SR(DCCG_GATE_DISABLE_CNTL2), \ SR(DCFCLK_CNTL),\ SR(DCFCLK_CNTL), \ - SR(D1VGA_CONTROL), \ - SR(D2VGA_CONTROL), \ - SR(D3VGA_CONTROL), \ - SR(D4VGA_CONTROL), \ /* todo: get these from GVM instead of reading registers ourselves */\ MMHUB_SR(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32),\ MMHUB_SR(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32),\ @@ -228,7 +223,12 @@ SR(DOMAIN4_PG_STATUS), \ SR(DOMAIN5_PG_STATUS), \ SR(DOMAIN6_PG_STATUS), \ - SR(DOMAIN7_PG_STATUS) + SR(DOMAIN7_PG_STATUS), \ + SR(D1VGA_CONTROL), \ + SR(D2VGA_CONTROL), \ + SR(D3VGA_CONTROL), \ + SR(D4VGA_CONTROL), \ + SR(DC_IP_REQUEST_CNTL) struct dce_hwseq_registers { uint32_t DCFE_CLOCK_CONTROL[6]; @@ -415,7 +415,6 @@ struct dce_hwseq_registers { HWS_SF(DPP_TOP0_, DPP_CONTROL, DPP_CLOCK_ENABLE, mask_sh), \ HWS_SF(OPP_PIPE0_, OPP_PIPE_CONTROL, OPP_PIPE_CLOCK_EN, mask_sh),\ HWS_SF(, DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, mask_sh), \ - HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh), \ HWS_SF(, DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, mask_sh), \ HWS_SF(, DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE, mask_sh), \ HWS_SF(, DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE, mask_sh), \ @@ -467,7 +466,8 @@ struct dce_hwseq_registers { HWS_SF(, DOMAIN4_PG_STATUS, DOMAIN4_PGFSM_PWR_STATUS, mask_sh), \ HWS_SF(, DOMAIN5_PG_STATUS, DOMAIN5_PGFSM_PWR_STATUS, mask_sh), \ HWS_SF(, DOMAIN6_PG_STATUS, DOMAIN6_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN7_PG_STATUS, DOMAIN7_PGFSM_PWR_STATUS, mask_sh) + HWS_SF(, DOMAIN7_PG_STATUS, DOMAIN7_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh) #define HWSEQ_REG_FIELD_LIST(type) \ type DCFE_CLOCK_ENABLE; \ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h index be0a45bdc5e2..05463df7e636 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h @@ -44,8 +44,6 @@ SRI(DC_HPD_CONTROL, HPD, id) #define LE_COMMON_REG_LIST_BASE(id) \ - SR(LVTMA_PWRSEQ_CNTL), \ - SR(LVTMA_PWRSEQ_STATE), \ SR(DMCU_RAM_ACCESS_CTRL), \ SR(DMCU_IRAM_RD_CTRL), \ SR(DMCU_IRAM_RD_DATA), \ @@ -71,6 +69,10 @@ SRI(DP_DPHY_FAST_TRAINING, DP, id), \ SRI(DP_SEC_CNTL1, DP, id) +#define LE_EDP_REG_LIST(id)\ + SR(LVTMA_PWRSEQ_CNTL), \ + SR(LVTMA_PWRSEQ_STATE) + #define LE_COMMON_REG_LIST(id)\ LE_COMMON_REG_LIST_BASE(id), \ SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ @@ -79,33 +81,38 @@ #define LE_DCE80_REG_LIST(id)\ SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ - LE_COMMON_REG_LIST_BASE(id) + LE_COMMON_REG_LIST_BASE(id), \ + LE_EDP_REG_LIST(id) #define LE_DCE100_REG_LIST(id)\ LE_COMMON_REG_LIST_BASE(id), \ SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ - SR(DCI_MEM_PWR_STATUS) + SR(DCI_MEM_PWR_STATUS), \ + LE_EDP_REG_LIST(id) #define LE_DCE110_REG_LIST(id)\ LE_COMMON_REG_LIST_BASE(id), \ SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ SRI(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id), \ - SR(DCI_MEM_PWR_STATUS) + SR(DCI_MEM_PWR_STATUS), \ + LE_EDP_REG_LIST(id) #define LE_DCE120_REG_LIST(id)\ LE_COMMON_REG_LIST_BASE(id), \ SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ SRI(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id), \ - SR(DCI_MEM_PWR_STATUS) + SR(DCI_MEM_PWR_STATUS), \ + LE_EDP_REG_LIST(id) #define LE_DCN10_REG_LIST(id)\ LE_COMMON_REG_LIST_BASE(id), \ SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ SRI(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id), \ - SR(DMU_MEM_PWR_CNTL) + SR(DMU_MEM_PWR_CNTL), \ + LE_EDP_REG_LIST(id) struct dce110_link_enc_aux_registers { uint32_t AUX_CONTROL; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h index 69da293e9b4a..0826d73b9809 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h @@ -71,11 +71,7 @@ SRI(OPTC_INPUT_GLOBAL_CONTROL, ODM, inst),\ SRI(OPPBUF_CONTROL, OPPBUF, inst),\ SRI(OPPBUF_3D_PARAMETERS_0, OPPBUF, inst),\ - SRI(CONTROL, VTG, inst),\ - SR(D1VGA_CONTROL),\ - SR(D2VGA_CONTROL),\ - SR(D3VGA_CONTROL),\ - SR(D4VGA_CONTROL) + SRI(CONTROL, VTG, inst) #define TG_COMMON_REG_LIST_DCN1_0(inst) \ TG_COMMON_REG_LIST_DCN(inst),\ @@ -128,11 +124,6 @@ struct dcn_tg_registers { uint32_t OPPBUF_CONTROL; uint32_t OPPBUF_3D_PARAMETERS_0; uint32_t CONTROL; - /*todo: move VGA to HWSS */ - uint32_t D1VGA_CONTROL; - uint32_t D2VGA_CONTROL; - uint32_t D3VGA_CONTROL; - uint32_t D4VGA_CONTROL; }; #define TG_COMMON_MASK_SH_LIST_DCN(mask_sh)\ -- cgit From 25bab0da8f61e7d8f717e4f9be34e97a1aaa0ccc Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Thu, 14 Sep 2017 18:50:32 -0400 Subject: drm/amd/display: set cp25201 to use TPS4 [Description] hbr2 compliance eye output is unstable (toggling on and off) with debugger break. This caueses intermittent PHY automation failure. Need to look into the root cause later Signed-off-by: Wenjing Liu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') 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 b735782b8fe0..ced42484dcfc 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 @@ -1700,6 +1700,12 @@ static void dp_test_send_link_training(struct dc_link *link) dp_retrain_link_dp_test(link, &link_settings, false); } +/* TODO hbr2 compliance eye output is unstable + * (toggling on and off) with debugger break + * This caueses intermittent PHY automation failure + * Need to look into the root cause */ +static uint8_t force_tps4_for_cp2520 = 1; + static void dp_test_send_phy_test_pattern(struct dc_link *link) { union phy_test_pattern dpcd_test_pattern; @@ -1758,10 +1764,16 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link) test_pattern = DP_TEST_PATTERN_80BIT_CUSTOM; break; case PHY_TEST_PATTERN_CP2520_1: - test_pattern = DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE; + /* CP2520 pattern is unstable, temporarily use TPS4 instead */ + test_pattern = (force_tps4_for_cp2520 == 1) ? + DP_TEST_PATTERN_TRAINING_PATTERN4 : + DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE; break; case PHY_TEST_PATTERN_CP2520_2: - test_pattern = DP_TEST_PATTERN_CP2520_2; + /* CP2520 pattern is unstable, temporarily use TPS4 instead */ + test_pattern = (force_tps4_for_cp2520 == 1) ? + DP_TEST_PATTERN_TRAINING_PATTERN4 : + DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE; break; case PHY_TEST_PATTERN_CP2520_3: test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN4; -- cgit From 904aa42e77aa7fb5f95408b4d1ffb4b2c3a805d7 Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Thu, 14 Sep 2017 19:03:04 -0400 Subject: drm/amd/display: add back removed hack for mpcc add A previous changed removed the hack to match mpcc_idd with mi instance. This causes pstate hang on resume from hibernate for yet unknown reason. Add the hack back for now to work around the issue. More debugging required in init_hw to root cause the hang. Signed-off-by: Eric Yang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c index 8e767c84359c..6e56fa3a135b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c @@ -279,6 +279,18 @@ static int mpc10_mpcc_add(struct mpc *mpc, struct mpcc_cfg *cfg) if (z_idx == cfg->tree_cfg->num_pipes) { ASSERT(cfg->z_index <= cfg->tree_cfg->num_pipes); mpcc_id = mpc10_get_idle_mpcc_id(mpc10); + + /* + * TODO: remove hack + * Note: currently there is a bug in init_hw such that + * on resume from hibernate, BIOS sets up MPCC0, and + * we do mpcc_remove but the mpcc cannot go to idle + * after remove. This cause us to pick mpcc1 here, + * which causes a pstate hang for yet unknown reason. + */ + mpcc_id = cfg->dpp_id; + /* end hack*/ + ASSERT(!(mpc10->mpcc_in_use_mask & 1 << mpcc_id)); if (mpc->ctx->dc->debug.sanity_checks) -- cgit From 62bf6e9b292212b9a821bd3c24adff57ff4b4bd7 Mon Sep 17 00:00:00 2001 From: Eric Bernstein Date: Thu, 14 Sep 2017 18:01:40 -0400 Subject: drm/amd/display: update blending mode and set output denorm Signed-off-by: Eric Bernstein Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c | 27 +++++++++++++++++++++++- drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h | 4 ++++ 2 files changed, 30 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c index 6e56fa3a135b..334f072cea1d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c @@ -313,10 +313,34 @@ static int mpc10_mpcc_add(struct mpc *mpc, struct mpcc_cfg *cfg) return mpcc_id; } +static void mpc10_update_blend_mode( + struct mpc *mpc, + struct mpcc_cfg *cfg) +{ + struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); + int mpcc_id, z_idx; + int alpha_blnd_mode = cfg->per_pixel_alpha ? + BLND_PP_ALPHA : BLND_GLOBAL_ALPHA; + + /* find z_idx for the dpp that requires blending mode update*/ + for (z_idx = 0; z_idx < cfg->tree_cfg->num_pipes; z_idx++) + if (cfg->tree_cfg->dpp[z_idx] == cfg->dpp_id) + break; + + ASSERT(z_idx < cfg->tree_cfg->num_pipes); + mpcc_id = cfg->tree_cfg->mpcc[z_idx]; + + REG_UPDATE_2(MPCC_CONTROL[mpcc_id], + MPCC_ALPHA_BLND_MODE, alpha_blnd_mode, + MPCC_ALPHA_MULTIPLIED_MODE, cfg->pre_multiplied_alpha); +} + const struct mpc_funcs dcn10_mpc_funcs = { .add = mpc10_mpcc_add, .remove = mpc10_mpcc_remove, - .wait_for_idle = mpc10_assert_idle_mpcc + .wait_for_idle = mpc10_assert_idle_mpcc, + .set_denorm = NULL, + .update_blend_mode = mpc10_update_blend_mode }; void dcn10_mpc_construct(struct dcn10_mpc *mpc10, @@ -337,3 +361,4 @@ void dcn10_mpc_construct(struct dcn10_mpc *mpc10, mpc10->mpcc_in_use_mask = 0; mpc10->num_mpcc = num_mpcc; } + diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h index 2d3de5b68e34..fb590f5353a0 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h @@ -51,6 +51,10 @@ struct mpc_funcs { int opp_id, int mpcc_inst); void (*wait_for_idle)(struct mpc *mpc, int id); + void (*set_denorm)(struct mpc *mpc, + int opp_id, + enum dc_color_depth output_depth); + void (*update_blend_mode)(struct mpc *mpc, struct mpcc_cfg *cfg); }; #endif -- cgit From 5eefbc40173644b5f74d7e074ba6cd8de5563e05 Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Fri, 15 Sep 2017 17:42:20 -0400 Subject: drm/amd/display: moving backlight registers to hwsequencer Signed-off-by: Yue Hin Lau Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 11 ++- drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h | 47 +++++++--- .../gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 79 +--------------- .../gpu/drm/amd/display/dc/dce/dce_link_encoder.h | 27 ++---- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 103 ++++++++++++++++++++- .../gpu/drm/amd/display/dc/inc/hw/link_encoder.h | 4 +- drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 4 + .../amd/display/dc/virtual/virtual_link_encoder.c | 8 +- 9 files changed, 158 insertions(+), 127 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index c7751a31081a..976f0f136f29 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1807,7 +1807,7 @@ static void disable_link(struct dc_link *link, enum signal_type signal) else dp_disable_link_phy_mst(link, signal); } else - link->link_enc->funcs->disable_output(link->link_enc, signal); + link->link_enc->funcs->disable_output(link->link_enc, signal, link); } enum dc_status dc_link_validate_mode_timing( diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 5f815cab94b5..fa2250554be5 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -94,7 +94,7 @@ void dp_enable_link_phy( link_enc, link_settings, clock_source); - link_enc->funcs->backlight_control(link_enc, true); + link->dc->hwss.backlight_control(link, true); } else link_enc->funcs->enable_dp_output( link_enc, @@ -138,12 +138,12 @@ void dp_disable_link_phy(struct dc_link *link, enum signal_type signal) dp_receiver_power_ctrl(link, false); if (signal == SIGNAL_TYPE_EDP) { - link->link_enc->funcs->backlight_control(link->link_enc, false); + link->dc->hwss.backlight_control(link, false); edp_receiver_ready_T9(link); - link->link_enc->funcs->disable_output(link->link_enc, signal); + link->link_enc->funcs->disable_output(link->link_enc, signal, link); link->link_enc->funcs->power_control(link->link_enc, false); } else - link->link_enc->funcs->disable_output(link->link_enc, signal); + link->link_enc->funcs->disable_output(link->link_enc, signal, link); /* Clear current link setting.*/ memset(&link->cur_link_settings, 0, @@ -286,7 +286,8 @@ void dp_retrain_link_dp_test(struct dc_link *link, link->link_enc->funcs->disable_output( link->link_enc, - SIGNAL_TYPE_DISPLAY_PORT); + SIGNAL_TYPE_DISPLAY_PORT, + link); /* Clear current link setting. */ memset(&link->cur_link_settings, 0, diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index 5798001da770..227c9b655b65 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -27,6 +27,10 @@ #include "hw_sequencer.h" +#define BL_REG_LIST()\ + SR(LVTMA_PWRSEQ_CNTL), \ + SR(LVTMA_PWRSEQ_STATE) + #define HWSEQ_DCEF_REG_LIST_DCE8() \ .DCFE_CLOCK_CONTROL[0] = mmCRTC0_CRTC_DCFE_CLOCK_CONTROL, \ .DCFE_CLOCK_CONTROL[1] = mmCRTC1_CRTC_DCFE_CLOCK_CONTROL, \ @@ -86,24 +90,27 @@ SRII(BLND_CONTROL, BLND, 0),\ SRII(BLND_CONTROL, BLND, 1),\ SR(BLNDV_CONTROL),\ - HWSEQ_PIXEL_RATE_REG_LIST(CRTC) + HWSEQ_PIXEL_RATE_REG_LIST(CRTC),\ + BL_REG_LIST() #define HWSEQ_DCE8_REG_LIST() \ HWSEQ_DCEF_REG_LIST_DCE8(), \ HWSEQ_BLND_REG_LIST(), \ - HWSEQ_PIXEL_RATE_REG_LIST(CRTC) + HWSEQ_PIXEL_RATE_REG_LIST(CRTC),\ + BL_REG_LIST() #define HWSEQ_DCE10_REG_LIST() \ HWSEQ_DCEF_REG_LIST(), \ HWSEQ_BLND_REG_LIST(), \ - HWSEQ_PIXEL_RATE_REG_LIST(CRTC) + HWSEQ_PIXEL_RATE_REG_LIST(CRTC), \ + BL_REG_LIST() #define HWSEQ_ST_REG_LIST() \ HWSEQ_DCE11_REG_LIST_BASE(), \ .DCFE_CLOCK_CONTROL[2] = mmDCFEV_CLOCK_CONTROL, \ .CRTC_H_BLANK_START_END[2] = mmCRTCV_H_BLANK_START_END, \ .BLND_V_UPDATE_LOCK[2] = mmBLNDV_V_UPDATE_LOCK, \ - .BLND_CONTROL[2] = mmBLNDV_CONTROL, + .BLND_CONTROL[2] = mmBLNDV_CONTROL #define HWSEQ_CZ_REG_LIST() \ HWSEQ_DCE11_REG_LIST_BASE(), \ @@ -123,12 +130,14 @@ SR(DCHUB_FB_LOCATION),\ SR(DCHUB_AGP_BASE),\ SR(DCHUB_AGP_BOT),\ - SR(DCHUB_AGP_TOP) + SR(DCHUB_AGP_TOP), \ + BL_REG_LIST() #define HWSEQ_DCE112_REG_LIST() \ HWSEQ_DCE10_REG_LIST(), \ HWSEQ_PIXEL_RATE_REG_LIST(CRTC), \ - HWSEQ_PHYPLL_REG_LIST(CRTC) + HWSEQ_PHYPLL_REG_LIST(CRTC), \ + BL_REG_LIST() #define HWSEQ_DCN_REG_LIST()\ SRII(OTG_GLOBAL_SYNC_STATUS, OTG, 0), \ @@ -228,9 +237,15 @@ SR(D2VGA_CONTROL), \ SR(D3VGA_CONTROL), \ SR(D4VGA_CONTROL), \ - SR(DC_IP_REQUEST_CNTL) + SR(DC_IP_REQUEST_CNTL), \ + BL_REG_LIST() struct dce_hwseq_registers { + + /* Backlight registers */ + uint32_t LVTMA_PWRSEQ_CNTL; + uint32_t LVTMA_PWRSEQ_STATE; + uint32_t DCFE_CLOCK_CONTROL[6]; uint32_t DCFEV_CLOCK_CONTROL; uint32_t DC_MEM_GLOBAL_PWR_REQ_CNTL; @@ -375,20 +390,24 @@ struct dce_hwseq_registers { HWS_SF(BLND_, V_UPDATE_LOCK, BLND_SCL_V_UPDATE_LOCK, mask_sh),\ HWS_SF(BLND_, V_UPDATE_LOCK, BLND_DCP_GRPH_SURF_V_UPDATE_LOCK, mask_sh),\ HWS_SF(BLND_, CONTROL, BLND_MODE, mask_sh),\ + HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh),\ HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_) #define HWSEQ_DCE10_MASK_SH_LIST(mask_sh)\ HWSEQ_DCEF_MASK_SH_LIST(mask_sh, DCFE_),\ HWSEQ_BLND_MASK_SH_LIST(mask_sh, BLND_),\ - HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_) + HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_), \ + HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh) #define HWSEQ_DCE11_MASK_SH_LIST(mask_sh)\ HWSEQ_DCE10_MASK_SH_LIST(mask_sh),\ SF(DCFEV_CLOCK_CONTROL, DCFEV_CLOCK_ENABLE, mask_sh),\ + HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh),\ HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_) #define HWSEQ_DCE112_MASK_SH_LIST(mask_sh)\ HWSEQ_DCE10_MASK_SH_LIST(mask_sh),\ + HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh),\ HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, CRTC0_) #define HWSEQ_GFX9_DCHUB_MASK_SH_LIST(mask_sh)\ @@ -396,14 +415,16 @@ struct dce_hwseq_registers { SF(DCHUB_FB_LOCATION, FB_BASE, mask_sh),\ SF(DCHUB_AGP_BASE, AGP_BASE, mask_sh),\ SF(DCHUB_AGP_BOT, AGP_BOT, mask_sh),\ - SF(DCHUB_AGP_TOP, AGP_TOP, mask_sh) + SF(DCHUB_AGP_TOP, AGP_TOP, mask_sh), \ + HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh) #define HWSEQ_DCE12_MASK_SH_LIST(mask_sh)\ HWSEQ_DCEF_MASK_SH_LIST(mask_sh, DCFE0_DCFE_),\ HWSEQ_BLND_MASK_SH_LIST(mask_sh, BLND0_BLND_),\ HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_),\ HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, CRTC0_),\ - HWSEQ_GFX9_DCHUB_MASK_SH_LIST(mask_sh) + HWSEQ_GFX9_DCHUB_MASK_SH_LIST(mask_sh), \ + HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh) #define HWSEQ_DCN_MASK_SH_LIST(mask_sh)\ HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, OTG0_),\ @@ -467,7 +488,8 @@ struct dce_hwseq_registers { HWS_SF(, DOMAIN5_PG_STATUS, DOMAIN5_PGFSM_PWR_STATUS, mask_sh), \ HWS_SF(, DOMAIN6_PG_STATUS, DOMAIN6_PGFSM_PWR_STATUS, mask_sh), \ HWS_SF(, DOMAIN7_PG_STATUS, DOMAIN7_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh) + HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh), \ + HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh) #define HWSEQ_REG_FIELD_LIST(type) \ type DCFE_CLOCK_ENABLE; \ @@ -497,7 +519,8 @@ struct dce_hwseq_registers { type PHYSICAL_PAGE_NUMBER_LSB;\ type LOGICAL_ADDR; \ type ENABLE_L1_TLB;\ - type SYSTEM_ACCESS_MODE; + type SYSTEM_ACCESS_MODE;\ + type LVTMA_BLON; #define HWSEQ_DCN_REG_FIELD_LIST(type) \ type VUPDATE_NO_LOCK_EVENT_CLEAR; \ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 37aeddfb7431..1cb727bdaa56 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -122,7 +122,6 @@ static const struct link_encoder_funcs dce110_lnk_enc_funcs = { .psr_program_dp_dphy_fast_training = dce110_psr_program_dp_dphy_fast_training, .psr_program_secondary_packet = dce110_psr_program_secondary_packet, - .backlight_control = dce110_link_encoder_edp_backlight_control, .power_control = dce110_link_encoder_edp_power_control, .connect_dig_be_to_fe = dce110_link_encoder_connect_dig_be_to_fe, .enable_hpd = dce110_link_encoder_enable_hpd, @@ -674,16 +673,6 @@ static void aux_initialize( } -/*todo: cloned in stream enc, fix*/ -static bool is_panel_backlight_on(struct dce110_link_encoder *enc110) -{ - uint32_t value; - - REG_GET(LVTMA_PWRSEQ_CNTL, LVTMA_BLON, &value); - - return value; -} - void dce110_psr_program_dp_dphy_fast_training(struct link_encoder *enc, bool exit_link_training_required) { @@ -718,69 +707,6 @@ void dce110_psr_program_secondary_packet(struct link_encoder *enc, DP_SEC_GSP0_PRIORITY, 1); } -/*todo: cloned in stream enc, fix*/ -/* - * @brief - * eDP only. Control the backlight of the eDP panel - */ -void dce110_link_encoder_edp_backlight_control( - struct link_encoder *enc, - bool enable) -{ - struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); - struct dc_context *ctx = enc110->base.ctx; - struct bp_transmitter_control cntl = { 0 }; - - if (dal_graphics_object_id_get_connector_id(enc110->base.connector) - != CONNECTOR_ID_EDP) { - BREAK_TO_DEBUGGER(); - return; - } - - if (enable && is_panel_backlight_on(enc110)) { - dm_logger_write(ctx->logger, LOG_HW_RESUME_S3, - "%s: panel already powered up. Do nothing.\n", - __func__); - return; - } - - if (!enable && !is_panel_backlight_on(enc110)) { - dm_logger_write(ctx->logger, LOG_HW_RESUME_S3, - "%s: panel already powered down. Do nothing.\n", - __func__); - return; - } - - /* Send VBIOS command to control eDP panel backlight */ - - dm_logger_write(ctx->logger, LOG_HW_RESUME_S3, - "%s: backlight action: %s\n", - __func__, (enable ? "On":"Off")); - - cntl.action = enable ? - TRANSMITTER_CONTROL_BACKLIGHT_ON : - TRANSMITTER_CONTROL_BACKLIGHT_OFF; - /*cntl.engine_id = ctx->engine;*/ - cntl.transmitter = enc110->base.transmitter; - cntl.connector_obj_id = enc110->base.connector; - /*todo: unhardcode*/ - cntl.lanes_number = LANE_COUNT_FOUR; - cntl.hpd_sel = enc110->base.hpd_source; - - /* For eDP, the following delays might need to be considered - * after link training completed: - * idle period - min. accounts for required BS-Idle pattern, - * max. allows for source frame synchronization); - * 50 msec max. delay from valid video data from source - * to video on dislpay or backlight enable. - * - * Disable the delay for now. - * Enable it in the future if necessary. - */ - /* dc_service_sleep_in_milliseconds(50); */ - link_transmitter_control(enc110, &cntl); -} - static bool is_dig_enabled(const struct dce110_link_encoder *enc110) { uint32_t value; @@ -1279,7 +1205,8 @@ void dce110_link_encoder_enable_dp_mst_output( */ void dce110_link_encoder_disable_output( struct link_encoder *enc, - enum signal_type signal) + enum signal_type signal, + struct dc_link *link) { struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); struct dc_context *ctx = enc110->base.ctx; @@ -1291,7 +1218,7 @@ void dce110_link_encoder_disable_output( return; } if (enc110->base.connector.id == CONNECTOR_ID_EDP) - dce110_link_encoder_edp_backlight_control(enc, false); + ctx->dc->hwss.backlight_control(link, false); /* Power-down RX and disable GPU PHY should be paired. * Disabling PHY without powering down RX may cause * symbol lock loss, on which we will get DP Sink interrupt. */ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h index 05463df7e636..c65def5f6a44 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h @@ -69,10 +69,6 @@ SRI(DP_DPHY_FAST_TRAINING, DP, id), \ SRI(DP_SEC_CNTL1, DP, id) -#define LE_EDP_REG_LIST(id)\ - SR(LVTMA_PWRSEQ_CNTL), \ - SR(LVTMA_PWRSEQ_STATE) - #define LE_COMMON_REG_LIST(id)\ LE_COMMON_REG_LIST_BASE(id), \ SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ @@ -81,38 +77,32 @@ #define LE_DCE80_REG_LIST(id)\ SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ - LE_COMMON_REG_LIST_BASE(id), \ - LE_EDP_REG_LIST(id) + LE_COMMON_REG_LIST_BASE(id) #define LE_DCE100_REG_LIST(id)\ LE_COMMON_REG_LIST_BASE(id), \ SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ - SR(DCI_MEM_PWR_STATUS), \ - LE_EDP_REG_LIST(id) + SR(DCI_MEM_PWR_STATUS) #define LE_DCE110_REG_LIST(id)\ LE_COMMON_REG_LIST_BASE(id), \ SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ SRI(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id), \ - SR(DCI_MEM_PWR_STATUS), \ - LE_EDP_REG_LIST(id) + SR(DCI_MEM_PWR_STATUS) #define LE_DCE120_REG_LIST(id)\ LE_COMMON_REG_LIST_BASE(id), \ SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ SRI(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id), \ - SR(DCI_MEM_PWR_STATUS), \ - LE_EDP_REG_LIST(id) + SR(DCI_MEM_PWR_STATUS) #define LE_DCN10_REG_LIST(id)\ LE_COMMON_REG_LIST_BASE(id), \ SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ - SRI(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id), \ - SR(DMU_MEM_PWR_CNTL), \ - LE_EDP_REG_LIST(id) + SRI(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id) struct dce110_link_enc_aux_registers { uint32_t AUX_CONTROL; @@ -243,7 +233,8 @@ void dce110_link_encoder_enable_dp_mst_output( /* disable PHY output */ void dce110_link_encoder_disable_output( struct link_encoder *link_enc, - enum signal_type signal); + enum signal_type signal, + struct dc_link *link); /* set DP lane settings */ void dce110_link_encoder_dp_set_lane_settings( @@ -259,10 +250,6 @@ void dce110_link_encoder_update_mst_stream_allocation_table( struct link_encoder *enc, const struct link_mst_stream_allocation_table *table); -void dce110_link_encoder_edp_backlight_control( - struct link_encoder *enc, - bool enable); - void dce110_link_encoder_edp_power_control( struct link_encoder *enc, bool power_up); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index d83a330712f7..9fc43bcac5bc 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -56,6 +56,15 @@ #include "dce/dce_11_0_sh_mask.h" #include "custom_float.h" +#define CTX \ + hws->ctx +#define REG(reg)\ + hws->regs->reg + +#undef FN +#define FN(reg_name, field_name) \ + hws->shifts->field_name, hws->masks->field_name + struct dce110_hw_seq_reg_offsets { uint32_t crtc; }; @@ -761,6 +770,92 @@ void dce110_enable_stream(struct pipe_ctx *pipe_ctx) } +/*todo: cloned in stream enc, fix*/ +static bool is_panel_backlight_on(struct dce_hwseq *hws) +{ + uint32_t value; + + REG_GET(LVTMA_PWRSEQ_CNTL, LVTMA_BLON, &value); + + return value; +} + +static enum bp_result link_transmitter_control( + struct dc_link *link, + struct bp_transmitter_control *cntl) +{ + enum bp_result result; + struct dc_bios *bp = link->dc->ctx->dc_bios; + + result = bp->funcs->transmitter_control(bp, cntl); + + return result; +} + + +/*todo: cloned in stream enc, fix*/ +/* + * @brief + * eDP only. Control the backlight of the eDP panel + */ +void hwss_blacklight_control( + struct dc_link *link, + bool enable) +{ + struct dce_hwseq *hws = link->dc->hwseq; + struct dc_context *ctx = link->dc->ctx; + struct bp_transmitter_control cntl = { 0 }; + + if (dal_graphics_object_id_get_connector_id(link->link_id) + != CONNECTOR_ID_EDP) { + BREAK_TO_DEBUGGER(); + return; + } + + if (enable && is_panel_backlight_on(hws)) { + dm_logger_write(ctx->logger, LOG_HW_RESUME_S3, + "%s: panel already powered up. Do nothing.\n", + __func__); + return; + } + + if (!enable && !is_panel_backlight_on(hws)) { + dm_logger_write(ctx->logger, LOG_HW_RESUME_S3, + "%s: panel already powered down. Do nothing.\n", + __func__); + return; + } + + /* Send VBIOS command to control eDP panel backlight */ + + dm_logger_write(ctx->logger, LOG_HW_RESUME_S3, + "%s: backlight action: %s\n", + __func__, (enable ? "On":"Off")); + + cntl.action = enable ? + TRANSMITTER_CONTROL_BACKLIGHT_ON : + TRANSMITTER_CONTROL_BACKLIGHT_OFF; + /*cntl.engine_id = ctx->engine;*/ + cntl.transmitter = link->link_enc->transmitter; + cntl.connector_obj_id = link->link_enc->connector; + /*todo: unhardcode*/ + cntl.lanes_number = LANE_COUNT_FOUR; + cntl.hpd_sel = link->link_enc->hpd_source; + + /* For eDP, the following delays might need to be considered + * after link training completed: + * idle period - min. accounts for required BS-Idle pattern, + * max. allows for source frame synchronization); + * 50 msec max. delay from valid video data from source + * to video on dislpay or backlight enable. + * + * Disable the delay for now. + * Enable it in the future if necessary. + */ + /* dc_service_sleep_in_milliseconds(50); */ + link_transmitter_control(link, &cntl); +} + void dce110_disable_stream(struct pipe_ctx *pipe_ctx) { struct dc_stream_state *stream = pipe_ctx->stream; @@ -798,7 +893,7 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) /* blank at encoder level */ if (dc_is_dp_signal(pipe_ctx->stream->signal)) { if (pipe_ctx->stream->sink->link->connector_signal == SIGNAL_TYPE_EDP) - link->link_enc->funcs->backlight_control(link->link_enc, false); + hwss_blacklight_control(link, false); pipe_ctx->stream_res.stream_enc->funcs->dp_blank(pipe_ctx->stream_res.stream_enc); } link->link_enc->funcs->connect_dig_be_to_fe( @@ -820,7 +915,7 @@ void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, params.link_settings.link_rate = link_settings->link_rate; pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(pipe_ctx->stream_res.stream_enc, ¶ms); if (link->connector_signal == SIGNAL_TYPE_EDP) - link->link_enc->funcs->backlight_control(link->link_enc, true); + hwss_blacklight_control(link, true); } @@ -1184,7 +1279,7 @@ static void power_down_encoders(struct dc *dc) } dc->links[i]->link_enc->funcs->disable_output( - dc->links[i]->link_enc, signal); + dc->links[i]->link_enc, signal, dc->links[i]); } } @@ -2733,7 +2828,7 @@ static const struct hw_sequencer_funcs dce110_funcs = { .wait_for_mpcc_disconnect = dce110_wait_for_mpcc_disconnect, .ready_shared_resources = ready_shared_resources, .optimize_shared_resources = optimize_shared_resources, - + .backlight_control = hwss_blacklight_control }; void dce110_hw_sequencer_construct(struct dc *dc) diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h index 961bbcc9202c..6cd6bc7d15fb 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h @@ -111,7 +111,7 @@ struct link_encoder_funcs { const struct dc_link_settings *link_settings, enum clock_source_id clock_source); void (*disable_output)(struct link_encoder *link_enc, - enum signal_type signal); + enum signal_type signal, struct dc_link *link); void (*dp_set_lane_settings)(struct link_encoder *enc, const struct link_training_settings *link_settings); void (*dp_set_phy_pattern)(struct link_encoder *enc, @@ -123,8 +123,6 @@ struct link_encoder_funcs { bool exit_link_training_required); void (*psr_program_secondary_packet)(struct link_encoder *enc, unsigned int sdp_transmit_line_num_deadline); - void (*backlight_control) (struct link_encoder *enc, - bool enable); void (*power_control) (struct link_encoder *enc, bool power_up); void (*connect_dig_be_to_fe)(struct link_encoder *enc, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 1fa2edc6cfb1..210874f37722 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -176,6 +176,10 @@ struct hw_sequencer_funcs { void (*ready_shared_resources)(struct dc *dc, struct dc_state *context); void (*optimize_shared_resources)(struct dc *dc); + + void (*backlight_control)( + struct dc_link *link, + bool enable); }; void color_space_to_black_color( diff --git a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c index db513abd735a..4f405348130f 100644 --- a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c @@ -58,7 +58,8 @@ static void virtual_link_encoder_enable_dp_mst_output( static void virtual_link_encoder_disable_output( struct link_encoder *link_enc, - enum signal_type signal) {} + enum signal_type signal, + struct dc_link *link) {} static void virtual_link_encoder_dp_set_lane_settings( struct link_encoder *enc, @@ -72,10 +73,6 @@ static void virtual_link_encoder_update_mst_stream_allocation_table( struct link_encoder *enc, const struct link_mst_stream_allocation_table *table) {} -static void virtual_link_encoder_edp_backlight_control( - struct link_encoder *enc, - bool enable) {} - static void virtual_link_encoder_edp_power_control( struct link_encoder *enc, bool power_up) {} @@ -105,7 +102,6 @@ static const struct link_encoder_funcs virtual_lnk_enc_funcs = { .dp_set_phy_pattern = virtual_link_encoder_dp_set_phy_pattern, .update_mst_stream_allocation_table = virtual_link_encoder_update_mst_stream_allocation_table, - .backlight_control = virtual_link_encoder_edp_backlight_control, .power_control = virtual_link_encoder_edp_power_control, .connect_dig_be_to_fe = virtual_link_encoder_connect_dig_be_to_fe, .destroy = virtual_link_encoder_destroy -- cgit From dbaed8037c6c606456c182f5fc327f9d405a7ffe Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Tue, 19 Sep 2017 11:35:23 -0400 Subject: drm/amd/display: edp backlight regression fix Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h | 5 +++++ drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 1 + 2 files changed, 6 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h index db6c19cd15eb..3e95f7f92c73 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h @@ -68,5 +68,10 @@ void dce110_fill_display_configs( uint32_t dce110_get_min_vblank_time_us(const struct dc_state *context); void dp_receiver_power_ctrl(struct dc_link *link, bool on); + +void hwss_blacklight_control( + struct dc_link *link, + bool enable); + #endif /* __DC_HWSS_DCE110_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 82a985a981be..bf5c9243ba7a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2897,6 +2897,7 @@ static const struct hw_sequencer_funcs dcn10_funcs = { .wait_for_mpcc_disconnect = dcn10_wait_for_mpcc_disconnect, .ready_shared_resources = ready_shared_resources, .optimize_shared_resources = optimize_shared_resources, + .backlight_control = hwss_blacklight_control }; -- cgit From 5df921d4c0e3e2065b961ac8d4269be68f80801d Mon Sep 17 00:00:00 2001 From: Ken Chalmers Date: Wed, 20 Sep 2017 11:48:47 -0400 Subject: drm/amd/display: fix ASSERT() caused by missing registers. Signed-off-by: Ken Chalmers Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 42 ++++++++++++---------- 1 file changed, 23 insertions(+), 19 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index bf5c9243ba7a..cdaed0c0a70c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -771,14 +771,16 @@ static void power_on_plane( struct dce_hwseq *hws, int plane_id) { - REG_SET(DC_IP_REQUEST_CNTL, 0, - IP_REQUEST_EN, 1); - dpp_pg_control(hws, plane_id, true); - hubp_pg_control(hws, plane_id, true); - REG_SET(DC_IP_REQUEST_CNTL, 0, - IP_REQUEST_EN, 0); - dm_logger_write(hws->ctx->logger, LOG_DEBUG, - "Un-gated front end for pipe %d\n", plane_id); + if (REG(DC_IP_REQUEST_CNTL)) { + REG_SET(DC_IP_REQUEST_CNTL, 0, + IP_REQUEST_EN, 1); + dpp_pg_control(hws, plane_id, true); + hubp_pg_control(hws, plane_id, true); + REG_SET(DC_IP_REQUEST_CNTL, 0, + IP_REQUEST_EN, 0); + dm_logger_write(hws->ctx->logger, LOG_DEBUG, + "Un-gated front end for pipe %d\n", plane_id); + } } static void undo_DEGVIDCN10_253_wa(struct dc *dc) @@ -1130,18 +1132,20 @@ static void plane_atomic_power_down(struct dc *dc, int fe_idx) struct dce_hwseq *hws = dc->hwseq; struct transform *xfm = dc->res_pool->transforms[fe_idx]; - REG_SET(DC_IP_REQUEST_CNTL, 0, - IP_REQUEST_EN, 1); - dpp_pg_control(hws, fe_idx, false); - hubp_pg_control(hws, fe_idx, false); - xfm->funcs->transform_reset(xfm); - REG_SET(DC_IP_REQUEST_CNTL, 0, - IP_REQUEST_EN, 0); - dm_logger_write(dc->ctx->logger, LOG_DEBUG, - "Power gated front end %d\n", fe_idx); + if (REG(DC_IP_REQUEST_CNTL)) { + REG_SET(DC_IP_REQUEST_CNTL, 0, + IP_REQUEST_EN, 1); + dpp_pg_control(hws, fe_idx, false); + hubp_pg_control(hws, fe_idx, false); + xfm->funcs->transform_reset(xfm); + REG_SET(DC_IP_REQUEST_CNTL, 0, + IP_REQUEST_EN, 0); + dm_logger_write(dc->ctx->logger, LOG_DEBUG, + "Power gated front end %d\n", fe_idx); - if (dc->debug.sanity_checks) - verify_allow_pstate_change_high(dc->hwseq); + if (dc->debug.sanity_checks) + verify_allow_pstate_change_high(dc->hwseq); + } } -- cgit From 19af33aca4384f840838a781f105726bb24c604f Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Wed, 20 Sep 2017 14:06:24 -0400 Subject: drm/amd/display: make sure BL off to mainlink off has enough time Signed-off-by: Charlene Liu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 9fc43bcac5bc..f28fce6e6ba4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -819,13 +819,6 @@ void hwss_blacklight_control( return; } - if (!enable && !is_panel_backlight_on(hws)) { - dm_logger_write(ctx->logger, LOG_HW_RESUME_S3, - "%s: panel already powered down. Do nothing.\n", - __func__); - return; - } - /* Send VBIOS command to control eDP panel backlight */ dm_logger_write(ctx->logger, LOG_HW_RESUME_S3, -- cgit From 6d732e7917064195b65303cab9591f311b621034 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Wed, 20 Sep 2017 16:15:18 -0400 Subject: drm/amd/display: add hubp/dpp pg debug key Signed-off-by: Charlene Liu Reviewed-by: Anthony Koo Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 50440731f83c..2e77885fc1ea 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -191,6 +191,8 @@ struct dc_debug { bool disable_dmcu; bool disable_psr; bool force_abm_enable; + bool disable_hbup_pg; + bool disable_dpp_pg; }; struct dc_state; struct resource_pool; -- cgit From e750d56d2c62875c81f52344afab44220300388d Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Wed, 20 Sep 2017 17:06:18 -0400 Subject: drm/amd/display: Fixed validation return wrong result. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') 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 6c04ad1b5859..0707bec111a5 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4748,7 +4748,7 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, if (ret) goto fail; - if (!dc_validate_global_state(dc, dm_state->context)) { + if (dc_validate_global_state(dc, dm_state->context) != DC_OK) { ret = -EINVAL; goto fail; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 77b3474a7c9e..d9a2d09a1f4f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1716,7 +1716,7 @@ void dc_resource_state_construct( dst_ctx->dis_clk = dc->res_pool->display_clock; } -bool dc_validate_global_state( +enum dc_status dc_validate_global_state( struct dc *dc, struct dc_state *new_ctx) { diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 2e77885fc1ea..1e49b8f9c66e 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -654,7 +654,7 @@ bool dc_validate_stream(struct dc *dc, struct dc_stream_state *stream); bool dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state); -bool dc_validate_global_state( +enum dc_status dc_validate_global_state( struct dc *dc, struct dc_state *new_ctx); -- cgit From 4d1a562659e1414ccb010bea56286ba4302e84e5 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Tue, 5 Sep 2017 21:13:55 -0400 Subject: drm/amd/display: version 3.1.02 Signed-off-by: Tony Cheng Reviewed-by: Tony Cheng Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 1e49b8f9c66e..12601ffc0fe4 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -38,7 +38,7 @@ #include "inc/compressor.h" #include "dml/display_mode_lib.h" -#define DC_VER "3.1.01" +#define DC_VER "3.1.02" #define MAX_SURFACES 3 #define MAX_STREAMS 6 -- cgit From 4f4ee68686c74bf1dfde6fa9fb7124104ff6f283 Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Wed, 20 Sep 2017 16:30:44 -0400 Subject: drm/amd/display: screen flickers when connected to ext monitor in clone Signed-off-by: Hersen Wu Signed-off-by: Tony Cheng Reviewed-by: Hersen Wu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 8 ++++++++ drivers/gpu/drm/amd/display/dc/dc.h | 1 + drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 3 +++ 3 files changed, 12 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 8ca6c3e4e65a..cc99073b7a54 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -1018,9 +1018,17 @@ bool dcn_validate_bandwidth( context->bw.dcn.calc_clk.min_active_dram_ccm_us = (int)(v->min_active_dram_clock_change_margin); context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz = (int)(v->dcf_clk_deep_sleep * 1000); context->bw.dcn.calc_clk.dcfclk_khz = (int)(v->dcfclk * 1000); + context->bw.dcn.calc_clk.dispclk_khz = (int)(v->dispclk * 1000); if (dc->debug.max_disp_clk == true) context->bw.dcn.calc_clk.dispclk_khz = (int)(dc->dcn_soc->max_dispclk_vmax0p9 * 1000); + + if (context->bw.dcn.calc_clk.dispclk_khz < + dc->debug.min_disp_clk_khz) { + context->bw.dcn.calc_clk.dispclk_khz = + dc->debug.min_disp_clk_khz; + } + context->bw.dcn.calc_clk.dppclk_div = (int)(v->dispclk_dppclk_ratio) == 2; for (i = 0, input_idx = 0; i < pool->pipe_count; i++) { diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 12601ffc0fe4..7a3a48179452 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -178,6 +178,7 @@ struct dc_debug { bool disable_pplib_wm_range; bool use_dml_wm; bool disable_pipe_split; + unsigned int min_disp_clk_khz; int sr_exit_time_dpm0_ns; int sr_enter_plus_exit_time_dpm0_ns; int sr_exit_time_ns; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 4f124dc303dc..82c82b6310ca 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -420,6 +420,9 @@ static const struct dc_debug debug_defaults_drv = { .force_abm_enable = false, .timing_trace = false, .clock_trace = true, + + .min_disp_clk_khz = 300000, + .disable_pplib_clock_request = true, .disable_pplib_wm_range = false, #if defined(CONFIG_DRM_AMD_DC_DCN1_0) -- cgit From d596e5d08da0a25be789432ed821e63db9ef72ac Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Thu, 21 Sep 2017 10:46:33 -0400 Subject: drm/amd/display: Fixed incorrect return value for validaton Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index d9a2d09a1f4f..bbfec7cb2ad1 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1723,10 +1723,11 @@ enum dc_status dc_validate_global_state( enum dc_status result = DC_ERROR_UNEXPECTED; int i, j; - if (dc->res_pool->funcs->validate_global && - dc->res_pool->funcs->validate_global( - dc, new_ctx) != DC_OK) - return false; + if (dc->res_pool->funcs->validate_global) { + result = dc->res_pool->funcs->validate_global(dc, new_ctx); + if (result != DC_OK) + return result; + } for (i = 0; new_ctx && i < new_ctx->stream_count; i++) { struct dc_stream_state *stream = new_ctx->streams[i]; -- cgit From fcbbe3da0ab65dc114937857fce81902e3fa2a97 Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Thu, 21 Sep 2017 18:16:01 -0400 Subject: drm/amd/display: Use active + border for bw validation When doing SLS, KMD gives us clipped v_addressable with border. This results in bw validation failure. Signed-off-by: Eric Yang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index cc99073b7a54..319450d9cfc1 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -364,7 +364,8 @@ static void pipe_ctx_to_e2e_pipe_params ( } - input->dest.vactive = pipe->stream->timing.v_addressable; + input->dest.vactive = pipe->stream->timing.v_addressable + pipe->stream->timing.v_border_top + + pipe->stream->timing.v_border_bottom; input->dest.recout_width = pipe->plane_res.scl_data.recout.width; input->dest.recout_height = pipe->plane_res.scl_data.recout.height; @@ -882,10 +883,11 @@ bool dcn_validate_bandwidth( v->htotal[input_idx] = pipe->stream->timing.h_total; v->vtotal[input_idx] = pipe->stream->timing.v_total; + v->vactive[input_idx] = pipe->stream->timing.v_addressable + + pipe->stream->timing.v_border_top + pipe->stream->timing.v_border_bottom; v->v_sync_plus_back_porch[input_idx] = pipe->stream->timing.v_total - - pipe->stream->timing.v_addressable + - v->vactive[input_idx] - pipe->stream->timing.v_front_porch; - v->vactive[input_idx] = pipe->stream->timing.v_addressable; v->pixel_clock[input_idx] = pipe->stream->timing.pix_clk_khz / 1000.0f; if (!pipe->plane_state) { -- cgit From e4ba6335cd91367f31978db1fc62d6bac0489672 Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Thu, 21 Sep 2017 18:53:40 -0400 Subject: drm/amd/display: update link type to mst before topology discovery [Description] link type is not updated before mst topology discovery. This causes issue when branch device response to link address after before the start topology discovery event finishes. [Solution] update link type to mst before topology discovery Signed-off-by: Wenjing Liu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 976f0f136f29..a58e61b6e9f9 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -496,6 +496,7 @@ static void detect_dp( } if (is_mst_supported(link)) { sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT_MST; + link->type = dc_connection_mst_branch; /* * This call will initiate MST topology discovery. Which @@ -524,12 +525,11 @@ static void detect_dp( if (reason == DETECT_REASON_BOOT) boot = true; - if (dm_helpers_dp_mst_start_top_mgr( + if (!dm_helpers_dp_mst_start_top_mgr( link->ctx, link, boot)) { - link->type = dc_connection_mst_branch; - } else { /* MST not supported */ + link->type = dc_connection_single; sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT; } } -- cgit From 69b516c91cbf459e5fd4b8b6e97cfdfa7ea25126 Mon Sep 17 00:00:00 2001 From: SivapiriyanKumarasamy Date: Fri, 22 Sep 2017 12:48:54 -0400 Subject: drm/amd/display: Program stream's csc matrix instead of using default Signed-off-by: SivapiriyanKumarasamy Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index cdaed0c0a70c..4e4f20ba5643 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2259,7 +2259,6 @@ static void update_dchubp_dpp( struct transform *xfm = pipe_ctx->plane_res.xfm; struct dc_plane_state *plane_state = pipe_ctx->plane_state; union plane_size size = plane_state->plane_size; - struct default_adjustment ocsc = {0}; struct mpcc_cfg mpcc_cfg = {0}; struct pipe_ctx *top_pipe; bool per_pixel_alpha = plane_state->per_pixel_alpha && pipe_ctx->bottom_pipe; @@ -2338,9 +2337,9 @@ static void update_dchubp_dpp( /*gamut remap*/ program_gamut_remap(pipe_ctx); - /*TODO add adjustments parameters*/ - ocsc.out_color_space = pipe_ctx->stream->output_color_space; - pipe_ctx->plane_res.xfm->funcs->opp_set_csc_default(pipe_ctx->plane_res.xfm, &ocsc); + program_csc_matrix(pipe_ctx, + pipe_ctx->stream->output_color_space, + pipe_ctx->stream->csc_color_matrix.matrix); mi->funcs->mem_input_program_surface_config( mi, -- cgit From 671a6246e0d3652c024f99d5641c7cf427b0b5a5 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Fri, 22 Sep 2017 13:41:13 -0400 Subject: drm/amd/display: Early return when turn off a plane. In case of two monitor connected and turn off one of the monitors, OTG0 is locked after graphic plane off due to redundant programming front end regs. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 2cea8de9c9be..ffc36f5ac50c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1190,8 +1190,14 @@ static void commit_planes_for_stream(struct dc *dc, } } - if (surface_count == 0) + if (surface_count == 0) { + /* + * In case of turning off screen, no need to program front end a second time. + * just return after program front end. + */ dc->hwss.apply_ctx_for_surface(dc, stream, surface_count, context); + return; + } /* Lock pipes for provided surfaces, or all active if full update*/ for (i = 0; i < surface_count; i++) { -- cgit From 56e6ed4561f2962d1220c16bbd2709ced7a84be8 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Fri, 22 Sep 2017 16:06:04 -0400 Subject: drm/amd/display: Only reset top pipe back end. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 4e4f20ba5643..014911ebdbd6 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1270,6 +1270,9 @@ static void reset_hw_ctx_wrap( if (!pipe_ctx_old->stream) continue; + if (pipe_ctx_old->top_pipe) + continue; + if (!pipe_ctx->stream || pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) { struct clock_source *old_clk = pipe_ctx_old->clock_source; -- cgit From 544276514760f293eadb68461f1b45b6ccec073e Mon Sep 17 00:00:00 2001 From: Jerry Zuo Date: Wed, 20 Sep 2017 15:04:52 -0400 Subject: drm/amd/display: Fix MST daisy chain SST not light up In SST daisy chain scenario, edid is getting read in mst hotplug routine. It is getting conflict with drm send_enum_path_resources kernel thread in terms of i2c bus which is getting locked up in such case. Have edid being read in get_mode hook, instead of in hotplug routine. Signed-off-by: Jerry Zuo Reviewed-by: Roman Li Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 110 +++++++++------------ 1 file changed, 49 insertions(+), 61 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index dfcfb5a722e0..610375b2a04b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -174,14 +174,60 @@ static const struct drm_connector_funcs dm_dp_mst_connector_funcs = { .atomic_get_property = amdgpu_dm_connector_atomic_get_property }; +static int dm_connector_update_modes(struct drm_connector *connector, + struct edid *edid) +{ + int ret; + + ret = drm_add_edid_modes(connector, edid); + drm_edid_to_eld(connector, edid); + + return ret; +} + static int dm_dp_mst_get_modes(struct drm_connector *connector) { struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); int ret = 0; - ret = drm_add_edid_modes(&aconnector->base, aconnector->edid); + if (!aconnector) + return dm_connector_update_modes(connector, NULL); + + if (!aconnector->edid) { + struct edid *edid; + struct dc_sink *dc_sink; + struct dc_sink_init_data init_params = { + .link = aconnector->dc_link, + .sink_signal = SIGNAL_TYPE_DISPLAY_PORT_MST }; + edid = drm_dp_mst_get_edid(connector, &aconnector->mst_port->mst_mgr, aconnector->port); - drm_edid_to_eld(&aconnector->base, aconnector->edid); + if (!edid) { + drm_mode_connector_update_edid_property( + &aconnector->base, + NULL); + return ret; + } + + aconnector->edid = edid; + + dc_sink = dc_link_add_remote_sink( + aconnector->dc_link, + (uint8_t *)edid, + (edid->extensions + 1) * EDID_LENGTH, + &init_params); + + dc_sink->priv = aconnector; + aconnector->dc_sink = dc_sink; + + if (aconnector->dc_sink) + amdgpu_dm_add_sink_to_freesync_module( + connector, edid); + + drm_mode_connector_update_edid_property( + &aconnector->base, edid); + } + + ret = dm_connector_update_modes(connector, aconnector->edid); return ret; } @@ -343,66 +389,8 @@ static void dm_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr) { struct amdgpu_dm_connector *master = container_of(mgr, struct amdgpu_dm_connector, mst_mgr); struct drm_device *dev = master->base.dev; - struct amdgpu_device *adev = dev->dev_private; - struct drm_connector *connector; - struct amdgpu_dm_connector *aconnector; - struct edid *edid; - struct dc_sink *dc_sink; - - drm_modeset_lock_all(dev); - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - aconnector = to_amdgpu_dm_connector(connector); - if (aconnector->port && - aconnector->port->pdt != DP_PEER_DEVICE_NONE && - aconnector->port->pdt != DP_PEER_DEVICE_MST_BRANCHING && - !aconnector->dc_sink) { - /* - * This is plug in case, where port has been created but - * sink hasn't been created yet - */ - if (!aconnector->edid) { - struct dc_sink_init_data init_params = { - .link = aconnector->dc_link, - .sink_signal = SIGNAL_TYPE_DISPLAY_PORT_MST}; - edid = drm_dp_mst_get_edid(connector, &aconnector->mst_port->mst_mgr, aconnector->port); - - if (!edid) { - drm_mode_connector_update_edid_property( - &aconnector->base, - NULL); - continue; - } - - aconnector->edid = edid; - - dc_sink = dc_link_add_remote_sink( - aconnector->dc_link, - (uint8_t *)edid, - (edid->extensions + 1) * EDID_LENGTH, - &init_params); - - dc_sink->priv = aconnector; - aconnector->dc_sink = dc_sink; - - if (aconnector->dc_sink) - amdgpu_dm_add_sink_to_freesync_module( - connector, - edid); - - dm_restore_drm_connector_state(connector->dev, connector); - } else - edid = aconnector->edid; - - DRM_DEBUG_KMS("edid retrieved %p\n", edid); - - drm_mode_connector_update_edid_property( - &aconnector->base, - aconnector->edid); - } - } - drm_modeset_unlock_all(dev); - schedule_work(&adev->dm.mst_hotplug_work); + drm_kms_helper_hotplug_event(dev); } static void dm_dp_mst_register_connector(struct drm_connector *connector) -- cgit From e778915c916229475ba76267534b70834ba8de8d Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Mon, 25 Sep 2017 15:52:49 -0400 Subject: drm/amd/display: temp disable DCC on high res. Signed-off-by: Charlene Liu Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 82c82b6310ca..dd3ff5114d42 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -1133,20 +1133,27 @@ static bool get_dcc_compression_cap(const struct dc *dc, output->grph.rgb.max_uncompressed_blk_size = 256; output->grph.rgb.max_compressed_blk_size = 256; output->grph.rgb.independent_64b_blks = false; + output->capable = true; + output->const_color_support = false; break; case dcc_control__128_128_xxx: output->grph.rgb.max_uncompressed_blk_size = 128; output->grph.rgb.max_compressed_blk_size = 128; output->grph.rgb.independent_64b_blks = false; + /*temp: not allow dcc on high res*/ + output->capable = false; + output->const_color_support = false; break; case dcc_control__256_64_64: output->grph.rgb.max_uncompressed_blk_size = 256; output->grph.rgb.max_compressed_blk_size = 64; output->grph.rgb.independent_64b_blks = true; + /*temp: not allow dcc on high res*/ + output->capable = false; + output->const_color_support = false; break; } - output->capable = true; - output->const_color_support = false; + return true; } -- cgit From db64fbe73288f0b5f2a36ecdd48c9bae978406e0 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Mon, 25 Sep 2017 10:52:07 -0400 Subject: drm/amd/display: enable optional pipe split for single display also refactor debug option. now pipe_split_policy are dynamic = no hack around dcn_calcs. will split based on HW recommendation avoid = avoid split if we can support the config with higher voltage avoid_multi_display = allow split with single display output. force_single_disp_pipe_split force single display to pipe split to improve stutter efficiency by using DET buffers using 2 HUBP. Signed-off-by: Tony Cheng Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 44 ++++++++++++++++++++-- drivers/gpu/drm/amd/display/dc/dc.h | 9 ++++- .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 8 +--- 3 files changed, 51 insertions(+), 10 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 319450d9cfc1..aa56243f2522 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -720,6 +720,46 @@ static bool dcn_bw_apply_registry_override(struct dc *dc) return updated; } +void hack_disable_optional_pipe_split(struct dcn_bw_internal_vars *v) +{ + /* + * disable optional pipe split by lower dispclk bounding box + * at DPM0 + */ + v->max_dispclk[0] = v->max_dppclk_vmin0p65; +} + +void hack_force_pipe_split(struct dcn_bw_internal_vars *v, + unsigned int pixel_rate_khz) +{ + /* + * force enabling pipe split by lower dpp clock for DPM0 to just + * below the specify pixel_rate, so bw calc would split pipe. + */ + v->max_dppclk[0] = pixel_rate_khz / 1000; +} + +void hack_bounding_box(struct dcn_bw_internal_vars *v, + struct dc_debug *dbg, + struct dc_state *context) +{ + if (dbg->pipe_split_policy == MPC_SPLIT_AVOID) { + hack_disable_optional_pipe_split(v); + } + + if (dbg->pipe_split_policy == MPC_SPLIT_AVOID_MULT_DISP && + context->stream_count >= 2) { + hack_disable_optional_pipe_split(v); + } + + if (context->stream_count == 1 && + dbg->force_single_disp_pipe_split) { + struct dc_stream_state *stream0 = context->streams[0]; + + hack_force_pipe_split(v, stream0->timing.pix_clk_khz); + } +} + bool dcn_validate_bandwidth( struct dc *dc, struct dc_state *context) @@ -851,9 +891,7 @@ bool dcn_validate_bandwidth( v->phyclk_per_state[1] = v->phyclkv_mid0p72; v->phyclk_per_state[0] = v->phyclkv_min0p65; - if (dc->debug.disable_pipe_split) { - v->max_dispclk[0] = v->max_dppclk_vmin0p65; - } + hack_bounding_box(v, &dc->debug, context); if (v->voltage_override == dcn_bw_v_max0p9) { v->voltage_override_level = number_of_states - 1; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 7a3a48179452..622488efa9e6 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -162,6 +162,12 @@ struct dc_config { bool disable_disp_pll_sharing; }; +enum pipe_split_policy { + MPC_SPLIT_DYNAMIC = 0, + MPC_SPLIT_AVOID = 1, + MPC_SPLIT_AVOID_MULT_DISP = 2, +}; + struct dc_debug { bool surface_visual_confirm; bool sanity_checks; @@ -177,7 +183,8 @@ struct dc_debug { bool disable_hubp_power_gate; bool disable_pplib_wm_range; bool use_dml_wm; - bool disable_pipe_split; + enum pipe_split_policy pipe_split_policy; + bool force_single_disp_pipe_split; unsigned int min_disp_clk_khz; int sr_exit_time_dpm0_ns; int sr_enter_plus_exit_time_dpm0_ns; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index dd3ff5114d42..bd7c86e5800e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -425,10 +425,9 @@ static const struct dc_debug debug_defaults_drv = { .disable_pplib_clock_request = true, .disable_pplib_wm_range = false, -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) .use_dml_wm = false, - .disable_pipe_split = true -#endif + + .pipe_split_policy = MPC_SPLIT_AVOID_MULT_DISP, }; static const struct dc_debug debug_defaults_diags = { @@ -437,12 +436,9 @@ static const struct dc_debug debug_defaults_diags = { .timing_trace = true, .clock_trace = true, .disable_stutter = true, -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) .disable_pplib_clock_request = true, .disable_pplib_wm_range = true, .use_dml_wm = false, - .disable_pipe_split = false -#endif }; static void dcn10_dpp_destroy(struct transform **xfm) -- cgit From a32a7708ae8b01c191768d503c1af33b85b369d0 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Mon, 25 Sep 2017 18:06:11 -0400 Subject: drm/amd/display: add option to disable DCC for DCC 128b request 1. reverts commit e67f51012740 ("dc: temp disable DCC on high res.") - default still DCC enabled 2. add debug options to decide how DCC is disabled - disable DCC - disable DCC if DCC requires 128b (aka. half) request -- observed compressed data corruption result in screen corruption in full (256b) request while half (128b) would cause DCN to hang, result in DF hang Signed-off-by: Tony Cheng Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 11 ++++++++--- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 18 ++++++++---------- 2 files changed, 16 insertions(+), 13 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 622488efa9e6..d7afbcfb33ce 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -56,11 +56,10 @@ struct dc_caps { uint32_t max_planes; uint32_t max_downscale_ratio; uint32_t i2c_speed_in_khz; - unsigned int max_cursor_size; + bool dcc_const_color; }; - struct dc_dcc_surface_param { struct dc_size surface_size; enum surface_pixel_format format; @@ -162,6 +161,12 @@ struct dc_config { bool disable_disp_pll_sharing; }; +enum dcc_option { + DCC_ENABLE = 0, + DCC_DISABLE = 1, + DCC_HALF_REQ_DISALBE = 2, +}; + enum pipe_split_policy { MPC_SPLIT_DYNAMIC = 0, MPC_SPLIT_AVOID = 1, @@ -177,7 +182,7 @@ struct dc_debug { bool clock_trace; bool validation_trace; bool disable_stutter; - bool disable_dcc; + enum dcc_option disable_dcc; bool disable_dfs_bypass; bool disable_dpp_power_gate; bool disable_hubp_power_gate; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index bd7c86e5800e..30c275e05796 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -414,7 +414,6 @@ static const struct resource_caps res_cap = { }; static const struct dc_debug debug_defaults_drv = { - .disable_dcc = false, .sanity_checks = true, .disable_dmcu = true, .force_abm_enable = false, @@ -428,6 +427,7 @@ static const struct dc_debug debug_defaults_drv = { .use_dml_wm = false, .pipe_split_policy = MPC_SPLIT_AVOID_MULT_DISP, + .disable_dcc = DCC_ENABLE, }; static const struct dc_debug debug_defaults_diags = { @@ -1080,7 +1080,7 @@ static bool get_dcc_compression_cap(const struct dc *dc, memset(output, 0, sizeof(*output)); - if (dc->debug.disable_dcc) + if (dc->debug.disable_dcc == DCC_DISABLE) return false; if (!dcc_support_pixel_format(input->format, @@ -1124,32 +1124,30 @@ static bool get_dcc_compression_cap(const struct dc *dc, dcc_control = dcc_control__128_128_xxx; } + if (dc->debug.disable_dcc == DCC_HALF_REQ_DISALBE && + dcc_control != dcc_control__256_256_xxx) + return false; + switch (dcc_control) { case dcc_control__256_256_xxx: output->grph.rgb.max_uncompressed_blk_size = 256; output->grph.rgb.max_compressed_blk_size = 256; output->grph.rgb.independent_64b_blks = false; - output->capable = true; - output->const_color_support = false; break; case dcc_control__128_128_xxx: output->grph.rgb.max_uncompressed_blk_size = 128; output->grph.rgb.max_compressed_blk_size = 128; output->grph.rgb.independent_64b_blks = false; - /*temp: not allow dcc on high res*/ - output->capable = false; - output->const_color_support = false; break; case dcc_control__256_64_64: output->grph.rgb.max_uncompressed_blk_size = 256; output->grph.rgb.max_compressed_blk_size = 64; output->grph.rgb.independent_64b_blks = true; - /*temp: not allow dcc on high res*/ - output->capable = false; - output->const_color_support = false; break; } + output->capable = true; + output->const_color_support = false; return true; } -- cgit From 966869d07aae2d1becfcb16b55cafd4aae3c6627 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Tue, 26 Sep 2017 01:56:00 -0400 Subject: drm/amd/display: option to maximize lb usage experimental change for testing if max line buffer result in better stutter efficiency for 1080p, LB can hold up to 9 line at 10bpcc, potentially add 10 line time of latency hiding. Signed-off-by: Tony Cheng Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 8 ++++++-- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c | 3 +++ 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index d7afbcfb33ce..427ccbc28f51 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -181,15 +181,19 @@ struct dc_debug { bool timing_trace; bool clock_trace; bool validation_trace; + + /* stutter efficiency related */ bool disable_stutter; + bool use_max_lb; enum dcc_option disable_dcc; + enum pipe_split_policy pipe_split_policy; + bool force_single_disp_pipe_split; + bool disable_dfs_bypass; bool disable_dpp_power_gate; bool disable_hubp_power_gate; bool disable_pplib_wm_range; bool use_dml_wm; - enum pipe_split_policy pipe_split_policy; - bool force_single_disp_pipe_split; unsigned int min_disp_clk_khz; int sr_exit_time_dpm0_ns; int sr_enter_plus_exit_time_dpm0_ns; 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 82b8887d4973..fa2ab9952388 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 @@ -507,6 +507,9 @@ static enum lb_memory_config find_lb_memory_config(struct dcn10_dpp *xfm, { enum lb_memory_config mem_cfg = LB_MEMORY_CONFIG_0; + if (xfm->base.ctx->dc->debug.use_max_lb) + return mem_cfg; + if (xfm->tf_mask->PIXEL_DEPTH) { mem_cfg = dpp10_find_lb_memory_config(scl_data); } -- cgit From 9f945eab797b042930553388d37c12fed38f3396 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Tue, 26 Sep 2017 10:16:34 -0400 Subject: drm/amd/display: fix bug in force_single_disp_pipe_split should only lower dpp clock. Signed-off-by: Tony Cheng Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index aa56243f2522..cf474eb1cde8 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -732,11 +732,14 @@ void hack_disable_optional_pipe_split(struct dcn_bw_internal_vars *v) void hack_force_pipe_split(struct dcn_bw_internal_vars *v, unsigned int pixel_rate_khz) { + float pixel_rate_mhz = pixel_rate_khz / 1000; + /* * force enabling pipe split by lower dpp clock for DPM0 to just * below the specify pixel_rate, so bw calc would split pipe. */ - v->max_dppclk[0] = pixel_rate_khz / 1000; + if (pixel_rate_mhz < v->max_dppclk[0]) + v->max_dppclk[0] = pixel_rate_mhz; } void hack_bounding_box(struct dcn_bw_internal_vars *v, -- cgit From 2e1cc334631849b035b24897d6be59d2a57b6f1c Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Tue, 26 Sep 2017 17:06:26 -0400 Subject: drm/amd/display: dal 3.1.03 Signed-off-by: Tony Cheng Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 427ccbc28f51..cf9cd108539f 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -38,7 +38,7 @@ #include "inc/compressor.h" #include "dml/display_mode_lib.h" -#define DC_VER "3.1.02" +#define DC_VER "3.1.03" #define MAX_SURFACES 3 #define MAX_STREAMS 6 -- cgit From 60d671db1c0c02f31bcff3ea5dee244d26b8ed77 Mon Sep 17 00:00:00 2001 From: Jerry Zuo Date: Mon, 25 Sep 2017 16:39:45 -0400 Subject: drm/amd/display: Fix ref_count messed up issue In the full update type, need to add ref_count to the newly created dc_state->stream. It made mistake to add ref_count to dc->current_state->stream which keeps adding up without release. Signed-off-by: Jerry Zuo Reviewed-by: Roman Li Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index ffc36f5ac50c..3439bc46a4a2 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1322,6 +1322,7 @@ void dc_commit_updates_for_stream(struct dc *dc, const struct dc_stream_status *stream_status; enum surface_update_type update_type; struct dc_state *context; + struct dc_context *dc_ctx = dc->ctx; int i; stream_status = dc_stream_get_status(stream); @@ -1334,8 +1335,17 @@ void dc_commit_updates_for_stream(struct dc *dc, update_surface_trace(dc, srf_updates, surface_count); - if (update_type >= UPDATE_TYPE_FULL) + if (update_type >= UPDATE_TYPE_FULL) { + + /* initialize scratch memory for building context */ + context = dc_create_state(); + if (context == NULL) { + DC_ERROR("Failed to allocate new validate context!\n"); + return; + } + dc_resource_state_copy_construct(state, context); + } for (i = 0; i < surface_count; i++) { @@ -1361,6 +1371,15 @@ void dc_commit_updates_for_stream(struct dc *dc, dc_post_update_surfaces_to_stream(dc); + if (dc->current_state != context) { + + struct dc_state *old = dc->current_state; + + dc->current_state = context; + dc_release_state(old); + + } + return; } -- cgit From b87d78d6aa104b207ff588d2cfd13633c2385994 Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Tue, 19 Sep 2017 17:29:28 -0400 Subject: drm/amd/display: moving cursor functions from ipp to mem_input Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 32 +++- drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c | 2 + drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c | 51 ++++++ drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h | 15 +- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c | 189 --------------------- .../gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c | 163 ++++++++++++++++++ .../gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h | 57 ++++++- drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h | 10 ++ drivers/gpu/drm/amd/display/dc/inc/hw/transform.h | 11 ++ 9 files changed, 329 insertions(+), 201 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 23df7bc020d2..c19b478bcdc7 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -195,13 +195,23 @@ bool dc_stream_set_cursor_attributes( for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; - if (pipe_ctx->stream != stream || !pipe_ctx->plane_res.ipp) + if (pipe_ctx->stream != stream || !pipe_ctx->plane_res.mi || !pipe_ctx->plane_res.xfm) continue; if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state) continue; - pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes( - pipe_ctx->plane_res.ipp, attributes); + + if (pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes != NULL) + pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes( + pipe_ctx->plane_res.ipp, attributes); + + if (pipe_ctx->plane_res.mi->funcs->set_cursor_attributes != NULL) + pipe_ctx->plane_res.mi->funcs->set_cursor_attributes( + pipe_ctx->plane_res.mi, attributes); + + if (pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes != NULL) + pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes( + pipe_ctx->plane_res.xfm, attributes); } return true; @@ -231,6 +241,8 @@ bool dc_stream_set_cursor_position( for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp; + struct mem_input *mi = pipe_ctx->plane_res.mi; + struct transform *xfm = pipe_ctx->plane_res.xfm; struct dc_cursor_position pos_cpy = *position; struct dc_cursor_mi_param param = { .pixel_clk_khz = stream->timing.pix_clk_khz, @@ -241,7 +253,9 @@ bool dc_stream_set_cursor_position( }; if (pipe_ctx->stream != stream || - !pipe_ctx->plane_res.ipp || !pipe_ctx->plane_state) + !pipe_ctx->plane_res.mi || + !pipe_ctx->plane_state || + !pipe_ctx->plane_res.xfm) continue; if (pipe_ctx->plane_state->address.type @@ -251,7 +265,15 @@ bool dc_stream_set_cursor_position( if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state) pos_cpy.enable = false; - ipp->funcs->ipp_cursor_set_position(ipp, &pos_cpy, ¶m); + + if (ipp->funcs->ipp_cursor_set_position != NULL) + ipp->funcs->ipp_cursor_set_position(ipp, &pos_cpy, ¶m); + + if (mi->funcs->set_cursor_attributes != NULL) + mi->funcs->set_cursor_position(mi, &pos_cpy, ¶m); + + if (xfm->funcs->set_cursor_attributes != NULL) + xfm->funcs->set_cursor_position(xfm, &pos_cpy, ¶m, mi->curs_attr.width); } return true; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c index fa481d481132..d618fdd0cc82 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c @@ -37,6 +37,7 @@ #define CTX \ ipp_dce->base.ctx + static void dce_ipp_cursor_set_position( struct input_pixel_processor *ipp, const struct dc_cursor_position *position, @@ -133,6 +134,7 @@ static void dce_ipp_cursor_set_attributes( REG_UPDATE(CUR_UPDATE, CURSOR_UPDATE_LOCK, false); } + static void dce_ipp_program_prescale( struct input_pixel_processor *ipp, struct ipp_prescale_params *params) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c index f9e43e68fc0c..05df3b222945 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c @@ -372,6 +372,55 @@ void ippn10_cnv_setup ( } } +void dcn10_set_cursor_attributes( + struct transform *xfm_base, + const struct dc_cursor_attributes *attr) +{ + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + enum dc_cursor_color_format color_format = attr->color_format; + + REG_UPDATE_2(CURSOR0_CONTROL, + CUR0_MODE, color_format, + CUR0_EXPANSION_MODE, 0); + + if (color_format == CURSOR_MODE_MONO) { + /* todo: clarify what to program these to */ + REG_UPDATE(CURSOR0_COLOR0, + CUR0_COLOR0, 0x00000000); + REG_UPDATE(CURSOR0_COLOR1, + CUR0_COLOR1, 0xFFFFFFFF); + } + + /* TODO: Fixed vs float */ + + REG_UPDATE_3(FORMAT_CONTROL, + CNVC_BYPASS, 0, + FORMAT_CONTROL__ALPHA_EN, 1, + FORMAT_EXPANSION_MODE, 0); +} + + +void dcn10_set_cursor_position( + struct transform *xfm_base, + const struct dc_cursor_position *pos, + const struct dc_cursor_mi_param *param, + uint32_t width) +{ + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + int src_x_offset = pos->x - pos->x_hotspot - param->viewport_x_start; + uint32_t cur_en = pos->enable ? 1 : 0; + + if (src_x_offset >= (int)param->viewport_width) + cur_en = 0; /* not visible beyond right edge*/ + + if (src_x_offset + (int)width < 0) + cur_en = 0; /* not visible beyond left edge*/ + + REG_UPDATE(CURSOR0_CONTROL, + CUR0_ENABLE, cur_en); + +} + static const struct transform_funcs dcn10_dpp_funcs = { .transform_reset = dpp_reset, .transform_set_scaler = dcn10_dpp_dscl_set_scaler_manual_scale, @@ -391,6 +440,8 @@ static const struct transform_funcs dcn10_dpp_funcs = { .ipp_program_degamma_pwl = ippn10_set_degamma_pwl, .ipp_setup = ippn10_cnv_setup, .ipp_full_bypass = ippn10_full_bypass, + .set_cursor_attributes = dcn10_set_cursor_attributes, + .set_cursor_position = dcn10_set_cursor_position, }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h index a1f6b01a2eb4..7fecdb19761d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h @@ -112,7 +112,10 @@ SRI(CM_DGAM_CONTROL, CM, id), \ SRI(FORMAT_CONTROL, CNVC_CFG, id), \ SRI(CNVC_SURFACE_PIXEL_FORMAT, CNVC_CFG, id), \ - SRI(CURSOR0_CONTROL, CNVC_CUR, id) + SRI(CURSOR0_CONTROL, CNVC_CUR, id), \ + SRI(CURSOR0_CONTROL, CNVC_CUR, id), \ + SRI(CURSOR0_COLOR0, CNVC_CUR, id), \ + SRI(CURSOR0_COLOR1, CNVC_CUR, id) @@ -302,7 +305,9 @@ TF_SF(CNVC_CFG0_CNVC_SURFACE_PIXEL_FORMAT, CNVC_SURFACE_PIXEL_FORMAT, mask_sh), \ TF_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_MODE, mask_sh), \ TF_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_EXPANSION_MODE, mask_sh), \ - TF_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_ENABLE, mask_sh) + TF_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_ENABLE, mask_sh), \ + TF_SF(CNVC_CUR0_CURSOR0_COLOR0, CUR0_COLOR0, mask_sh), \ + TF_SF(CNVC_CUR0_CURSOR0_COLOR1, CUR0_COLOR1, mask_sh) #define TF_REG_LIST_SH_MASK_DCN10(mask_sh)\ TF_REG_LIST_SH_MASK_DCN(mask_sh),\ @@ -989,7 +994,9 @@ type CUR0_EXPANSION_MODE; \ type CUR0_ENABLE; \ type CM_BYPASS; \ - type FORMAT_CONTROL__ALPHA_EN + type FORMAT_CONTROL__ALPHA_EN; \ + type CUR0_COLOR0; \ + type CUR0_COLOR1 @@ -1237,6 +1244,8 @@ struct dcn_dpp_registers { uint32_t CNVC_SURFACE_PIXEL_FORMAT; uint32_t CURSOR_CONTROL; uint32_t CURSOR0_CONTROL; + uint32_t CURSOR0_COLOR0; + uint32_t CURSOR0_COLOR1; }; struct dcn10_dpp { diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c index 67bd6a738fe9..08db1e6b5166 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c @@ -37,188 +37,6 @@ #define CTX \ ippn10->base.ctx -static bool ippn10_cursor_program_control( - struct dcn10_ipp *ippn10, - bool pixel_data_invert, - enum dc_cursor_color_format color_format) -{ - if (REG(CURSOR_SETTINS)) - REG_SET_2(CURSOR_SETTINS, 0, - /* no shift of the cursor HDL schedule */ - CURSOR0_DST_Y_OFFSET, 0, - /* used to shift the cursor chunk request deadline */ - CURSOR0_CHUNK_HDL_ADJUST, 3); - else - REG_SET_2(CURSOR_SETTINGS, 0, - /* no shift of the cursor HDL schedule */ - CURSOR0_DST_Y_OFFSET, 0, - /* used to shift the cursor chunk request deadline */ - CURSOR0_CHUNK_HDL_ADJUST, 3); - - REG_UPDATE_2(CURSOR0_CONTROL, - CUR0_MODE, color_format, - CUR0_EXPANSION_MODE, 0); - - if (color_format == CURSOR_MODE_MONO) { - /* todo: clarify what to program these to */ - REG_UPDATE(CURSOR0_COLOR0, - CUR0_COLOR0, 0x00000000); - REG_UPDATE(CURSOR0_COLOR1, - CUR0_COLOR1, 0xFFFFFFFF); - } - - /* TODO: Fixed vs float */ - - REG_UPDATE_3(FORMAT_CONTROL, - CNVC_BYPASS, 0, - ALPHA_EN, 1, - FORMAT_EXPANSION_MODE, 0); - - return true; -} - -enum cursor_pitch { - CURSOR_PITCH_64_PIXELS = 0, - CURSOR_PITCH_128_PIXELS, - CURSOR_PITCH_256_PIXELS -}; - -enum cursor_lines_per_chunk { - CURSOR_LINE_PER_CHUNK_2 = 1, - CURSOR_LINE_PER_CHUNK_4, - CURSOR_LINE_PER_CHUNK_8, - CURSOR_LINE_PER_CHUNK_16 -}; - -static enum cursor_pitch ippn10_get_cursor_pitch( - unsigned int pitch) -{ - enum cursor_pitch hw_pitch; - - switch (pitch) { - case 64: - hw_pitch = CURSOR_PITCH_64_PIXELS; - break; - case 128: - hw_pitch = CURSOR_PITCH_128_PIXELS; - break; - case 256: - hw_pitch = CURSOR_PITCH_256_PIXELS; - break; - default: - DC_ERR("Invalid cursor pitch of %d. " - "Only 64/128/256 is supported on DCN.\n", pitch); - hw_pitch = CURSOR_PITCH_64_PIXELS; - break; - } - return hw_pitch; -} - -static enum cursor_lines_per_chunk ippn10_get_lines_per_chunk( - unsigned int cur_width, - enum dc_cursor_color_format format) -{ - enum cursor_lines_per_chunk line_per_chunk; - - if (format == CURSOR_MODE_MONO) - /* impl B. expansion in CUR Buffer reader */ - line_per_chunk = CURSOR_LINE_PER_CHUNK_16; - else if (cur_width <= 32) - line_per_chunk = CURSOR_LINE_PER_CHUNK_16; - else if (cur_width <= 64) - line_per_chunk = CURSOR_LINE_PER_CHUNK_8; - else if (cur_width <= 128) - line_per_chunk = CURSOR_LINE_PER_CHUNK_4; - else - line_per_chunk = CURSOR_LINE_PER_CHUNK_2; - - return line_per_chunk; -} - -static void ippn10_cursor_set_attributes( - struct input_pixel_processor *ipp, - const struct dc_cursor_attributes *attr) -{ - struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); - enum cursor_pitch hw_pitch = ippn10_get_cursor_pitch(attr->pitch); - enum cursor_lines_per_chunk lpc = ippn10_get_lines_per_chunk( - attr->width, attr->color_format); - - ippn10->curs_attr = *attr; - - REG_UPDATE(CURSOR_SURFACE_ADDRESS_HIGH, - CURSOR_SURFACE_ADDRESS_HIGH, attr->address.high_part); - REG_UPDATE(CURSOR_SURFACE_ADDRESS, - CURSOR_SURFACE_ADDRESS, attr->address.low_part); - - REG_UPDATE_2(CURSOR_SIZE, - CURSOR_WIDTH, attr->width, - CURSOR_HEIGHT, attr->height); - REG_UPDATE_3(CURSOR_CONTROL, - CURSOR_MODE, attr->color_format, - CURSOR_PITCH, hw_pitch, - CURSOR_LINES_PER_CHUNK, lpc); - ippn10_cursor_program_control(ippn10, - attr->attribute_flags.bits.INVERT_PIXEL_DATA, - attr->color_format); -} - -static void ippn10_cursor_set_position( - struct input_pixel_processor *ipp, - const struct dc_cursor_position *pos, - const struct dc_cursor_mi_param *param) -{ - struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); - int src_x_offset = pos->x - pos->x_hotspot - param->viewport_x_start; - uint32_t cur_en = pos->enable ? 1 : 0; - uint32_t dst_x_offset = (src_x_offset >= 0) ? src_x_offset : 0; - - /* - * Guard aganst cursor_set_position() from being called with invalid - * attributes - * - * TODO: Look at combining cursor_set_position() and - * cursor_set_attributes() into cursor_update() - */ - if (ippn10->curs_attr.address.quad_part == 0) - return; - - dst_x_offset *= param->ref_clk_khz; - dst_x_offset /= param->pixel_clk_khz; - - ASSERT(param->h_scale_ratio.value); - - if (param->h_scale_ratio.value) - dst_x_offset = dal_fixed31_32_floor(dal_fixed31_32_div( - dal_fixed31_32_from_int(dst_x_offset), - param->h_scale_ratio)); - - if (src_x_offset >= (int)param->viewport_width) - cur_en = 0; /* not visible beyond right edge*/ - - if (src_x_offset + (int)ippn10->curs_attr.width < 0) - cur_en = 0; /* not visible beyond left edge*/ - - if (cur_en && REG_READ(CURSOR_SURFACE_ADDRESS) == 0) - ippn10_cursor_set_attributes(ipp, &ippn10->curs_attr); - REG_UPDATE(CURSOR_CONTROL, - CURSOR_ENABLE, cur_en); - REG_UPDATE(CURSOR0_CONTROL, - CUR0_ENABLE, cur_en); - - REG_SET_2(CURSOR_POSITION, 0, - CURSOR_X_POSITION, pos->x, - CURSOR_Y_POSITION, pos->y); - - REG_SET_2(CURSOR_HOT_SPOT, 0, - CURSOR_HOT_SPOT_X, pos->x_hotspot, - CURSOR_HOT_SPOT_Y, pos->y_hotspot); - - REG_SET(CURSOR_DST_OFFSET, 0, - CURSOR_DST_X_OFFSET, dst_x_offset); - /* TODO Handle surface pixel formats other than 4:4:4 */ -} - /*****************************************/ /* Constructor, Destructor */ /*****************************************/ @@ -230,13 +48,6 @@ static void dcn10_ipp_destroy(struct input_pixel_processor **ipp) } static const struct ipp_funcs dcn10_ipp_funcs = { - .ipp_cursor_set_attributes = ippn10_cursor_set_attributes, - .ipp_cursor_set_position = ippn10_cursor_set_position, - .ipp_set_degamma = NULL, - .ipp_program_input_lut = NULL, - .ipp_full_bypass = NULL, - .ipp_setup = NULL, - .ipp_program_degamma_pwl = NULL, .ipp_destroy = dcn10_ipp_destroy }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index a28495d95a15..efa1aca187ad 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -766,6 +766,167 @@ void dcn10_mem_input_read_state(struct dcn10_mem_input *mi, QoS_LEVEL_HIGH_WM, &s->qos_level_high_wm); } +enum cursor_pitch { + CURSOR_PITCH_64_PIXELS = 0, + CURSOR_PITCH_128_PIXELS, + CURSOR_PITCH_256_PIXELS +}; + +enum cursor_lines_per_chunk { + CURSOR_LINE_PER_CHUNK_2 = 1, + CURSOR_LINE_PER_CHUNK_4, + CURSOR_LINE_PER_CHUNK_8, + CURSOR_LINE_PER_CHUNK_16 +}; + +static bool ippn10_cursor_program_control( + struct dcn10_mem_input *mi, + bool pixel_data_invert, + enum dc_cursor_color_format color_format) +{ + if (REG(CURSOR_SETTINS)) + REG_SET_2(CURSOR_SETTINS, 0, + /* no shift of the cursor HDL schedule */ + CURSOR0_DST_Y_OFFSET, 0, + /* used to shift the cursor chunk request deadline */ + CURSOR0_CHUNK_HDL_ADJUST, 3); + else + REG_SET_2(CURSOR_SETTINGS, 0, + /* no shift of the cursor HDL schedule */ + CURSOR0_DST_Y_OFFSET, 0, + /* used to shift the cursor chunk request deadline */ + CURSOR0_CHUNK_HDL_ADJUST, 3); + + return true; +} + +static enum cursor_pitch ippn10_get_cursor_pitch( + unsigned int pitch) +{ + enum cursor_pitch hw_pitch; + + switch (pitch) { + case 64: + hw_pitch = CURSOR_PITCH_64_PIXELS; + break; + case 128: + hw_pitch = CURSOR_PITCH_128_PIXELS; + break; + case 256: + hw_pitch = CURSOR_PITCH_256_PIXELS; + break; + default: + DC_ERR("Invalid cursor pitch of %d. " + "Only 64/128/256 is supported on DCN.\n", pitch); + hw_pitch = CURSOR_PITCH_64_PIXELS; + break; + } + return hw_pitch; +} + +static enum cursor_lines_per_chunk ippn10_get_lines_per_chunk( + unsigned int cur_width, + enum dc_cursor_color_format format) +{ + enum cursor_lines_per_chunk line_per_chunk; + + if (format == CURSOR_MODE_MONO) + /* impl B. expansion in CUR Buffer reader */ + line_per_chunk = CURSOR_LINE_PER_CHUNK_16; + else if (cur_width <= 32) + line_per_chunk = CURSOR_LINE_PER_CHUNK_16; + else if (cur_width <= 64) + line_per_chunk = CURSOR_LINE_PER_CHUNK_8; + else if (cur_width <= 128) + line_per_chunk = CURSOR_LINE_PER_CHUNK_4; + else + line_per_chunk = CURSOR_LINE_PER_CHUNK_2; + + return line_per_chunk; +} + +static void ippn10_cursor_set_attributes( + struct mem_input *mem_input, + const struct dc_cursor_attributes *attr) +{ + struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + enum cursor_pitch hw_pitch = ippn10_get_cursor_pitch(attr->pitch); + enum cursor_lines_per_chunk lpc = ippn10_get_lines_per_chunk( + attr->width, attr->color_format); + + mem_input->curs_attr = *attr; + + REG_UPDATE(CURSOR_SURFACE_ADDRESS_HIGH, + CURSOR_SURFACE_ADDRESS_HIGH, attr->address.high_part); + REG_UPDATE(CURSOR_SURFACE_ADDRESS, + CURSOR_SURFACE_ADDRESS, attr->address.low_part); + + REG_UPDATE_2(CURSOR_SIZE, + CURSOR_WIDTH, attr->width, + CURSOR_HEIGHT, attr->height); + REG_UPDATE_3(CURSOR_CONTROL, + CURSOR_MODE, attr->color_format, + CURSOR_PITCH, hw_pitch, + CURSOR_LINES_PER_CHUNK, lpc); + ippn10_cursor_program_control(mi, + attr->attribute_flags.bits.INVERT_PIXEL_DATA, + attr->color_format); +} + +static void ippn10_cursor_set_position( + struct mem_input *mem_input, + const struct dc_cursor_position *pos, + const struct dc_cursor_mi_param *param) +{ + struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + int src_x_offset = pos->x - pos->x_hotspot - param->viewport_x_start; + uint32_t cur_en = pos->enable ? 1 : 0; + uint32_t dst_x_offset = (src_x_offset >= 0) ? src_x_offset : 0; + + /* + * Guard aganst cursor_set_position() from being called with invalid + * attributes + * + * TODO: Look at combining cursor_set_position() and + * cursor_set_attributes() into cursor_update() + */ + if (mem_input->curs_attr.address.quad_part == 0) + return; + + dst_x_offset *= param->ref_clk_khz; + dst_x_offset /= param->pixel_clk_khz; + + ASSERT(param->h_scale_ratio.value); + + if (param->h_scale_ratio.value) + dst_x_offset = dal_fixed31_32_floor(dal_fixed31_32_div( + dal_fixed31_32_from_int(dst_x_offset), + param->h_scale_ratio)); + + if (src_x_offset >= (int)param->viewport_width) + cur_en = 0; /* not visible beyond right edge*/ + + if (src_x_offset + (int)mem_input->curs_attr.width < 0) + cur_en = 0; /* not visible beyond left edge*/ + + if (cur_en && REG_READ(CURSOR_SURFACE_ADDRESS) == 0) + ippn10_cursor_set_attributes(mem_input, &mem_input->curs_attr); + REG_UPDATE(CURSOR_CONTROL, + CURSOR_ENABLE, cur_en); + + REG_SET_2(CURSOR_POSITION, 0, + CURSOR_X_POSITION, pos->x, + CURSOR_Y_POSITION, pos->y); + + REG_SET_2(CURSOR_HOT_SPOT, 0, + CURSOR_HOT_SPOT_X, pos->x_hotspot, + CURSOR_HOT_SPOT_Y, pos->y_hotspot); + + REG_SET(CURSOR_DST_OFFSET, 0, + CURSOR_DST_X_OFFSET, dst_x_offset); + /* TODO Handle surface pixel formats other than 4:4:4 */ +} + static struct mem_input_funcs dcn10_mem_input_funcs = { .mem_input_program_display_marks = min10_program_display_marks, .mem_input_program_surface_flip_and_addr = @@ -780,6 +941,8 @@ static struct mem_input_funcs dcn10_mem_input_funcs = { .dcc_control = min10_dcc_control, .mem_program_viewport = min_set_viewport, .set_hubp_blank_en = min10_set_hubp_blank_en, + .set_cursor_attributes = ippn10_cursor_set_attributes, + .set_cursor_position = ippn10_cursor_set_position, }; /*****************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h index 0b7d4faff82f..2c79d7aa3f91 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h @@ -30,7 +30,6 @@ #define TO_DCN10_MEM_INPUT(mi)\ container_of(mi, struct dcn10_mem_input, base) - #define MI_REG_LIST_DCN(id)\ SRI(DCHUBP_CNTL, HUBP, id),\ SRI(HUBPREQ_DEBUG_DB, HUBP, id),\ @@ -118,7 +117,15 @@ SRI(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, HUBPREQ, id),\ SRI(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, HUBPREQ, id),\ SR(DCHUBBUB_SDPIF_FB_BASE),\ - SR(DCHUBBUB_SDPIF_FB_OFFSET) + SR(DCHUBBUB_SDPIF_FB_OFFSET),\ + SRI(CURSOR_SETTINS, HUBPREQ, id), \ + SRI(CURSOR_SURFACE_ADDRESS_HIGH, CURSOR, id), \ + SRI(CURSOR_SURFACE_ADDRESS, CURSOR, id), \ + SRI(CURSOR_SIZE, CURSOR, id), \ + SRI(CURSOR_CONTROL, CURSOR, id), \ + SRI(CURSOR_POSITION, CURSOR, id), \ + SRI(CURSOR_HOT_SPOT, CURSOR, id), \ + SRI(CURSOR_DST_OFFSET, CURSOR, id) @@ -217,6 +224,15 @@ struct dcn_mi_registers { uint32_t DCN_VM_AGP_BASE; uint32_t DCN_VM_AGP_BOT; uint32_t DCN_VM_AGP_TOP; + uint32_t CURSOR_SETTINS; + uint32_t CURSOR_SETTINGS; + uint32_t CURSOR_SURFACE_ADDRESS_HIGH; + uint32_t CURSOR_SURFACE_ADDRESS; + uint32_t CURSOR_SIZE; + uint32_t CURSOR_CONTROL; + uint32_t CURSOR_POSITION; + uint32_t CURSOR_HOT_SPOT; + uint32_t CURSOR_DST_OFFSET; }; #define MI_SF(reg_name, field_name, post_fix)\ @@ -362,7 +378,23 @@ struct dcn_mi_registers { MI_SF(DCHUBBUB_SDPIF_FB_OFFSET, SDPIF_FB_OFFSET, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, MC_VM_SYSTEM_APERTURE_DEFAULT_SYSTEM, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, mask_sh) + MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, mask_sh),\ + MI_SF(HUBPREQ0_CURSOR_SETTINS, CURSOR0_DST_Y_OFFSET, mask_sh), \ + MI_SF(HUBPREQ0_CURSOR_SETTINS, CURSOR0_CHUNK_HDL_ADJUST, mask_sh), \ + MI_SF(CURSOR0_CURSOR_SURFACE_ADDRESS_HIGH, CURSOR_SURFACE_ADDRESS_HIGH, mask_sh), \ + MI_SF(CURSOR0_CURSOR_SURFACE_ADDRESS, CURSOR_SURFACE_ADDRESS, mask_sh), \ + MI_SF(CURSOR0_CURSOR_SIZE, CURSOR_WIDTH, mask_sh), \ + MI_SF(CURSOR0_CURSOR_SIZE, CURSOR_HEIGHT, mask_sh), \ + MI_SF(CURSOR0_CURSOR_CONTROL, CURSOR_MODE, mask_sh), \ + MI_SF(CURSOR0_CURSOR_CONTROL, CURSOR_2X_MAGNIFY, mask_sh), \ + MI_SF(CURSOR0_CURSOR_CONTROL, CURSOR_PITCH, mask_sh), \ + MI_SF(CURSOR0_CURSOR_CONTROL, CURSOR_LINES_PER_CHUNK, mask_sh), \ + MI_SF(CURSOR0_CURSOR_CONTROL, CURSOR_ENABLE, mask_sh), \ + MI_SF(CURSOR0_CURSOR_POSITION, CURSOR_X_POSITION, mask_sh), \ + MI_SF(CURSOR0_CURSOR_POSITION, CURSOR_Y_POSITION, mask_sh), \ + MI_SF(CURSOR0_CURSOR_HOT_SPOT, CURSOR_HOT_SPOT_X, mask_sh), \ + MI_SF(CURSOR0_CURSOR_HOT_SPOT, CURSOR_HOT_SPOT_Y, mask_sh), \ + MI_SF(CURSOR0_CURSOR_DST_OFFSET, CURSOR_DST_X_OFFSET, mask_sh) #define DCN_MI_REG_FIELD_LIST(type) \ type HUBP_BLANK_EN;\ @@ -523,7 +555,24 @@ struct dcn_mi_registers { type PHYSICAL_PAGE_ADDR_LO32;\ type PHYSICAL_PAGE_NUMBER_MSB;\ type PHYSICAL_PAGE_NUMBER_LSB;\ - type LOGICAL_ADDR + type LOGICAL_ADDR;\ + type CURSOR0_DST_Y_OFFSET; \ + type CURSOR0_CHUNK_HDL_ADJUST; \ + type CURSOR_SURFACE_ADDRESS_HIGH; \ + type CURSOR_SURFACE_ADDRESS; \ + type CURSOR_WIDTH; \ + type CURSOR_HEIGHT; \ + type CURSOR_MODE; \ + type CURSOR_2X_MAGNIFY; \ + type CURSOR_PITCH; \ + type CURSOR_LINES_PER_CHUNK; \ + type CURSOR_ENABLE; \ + type CURSOR_X_POSITION; \ + type CURSOR_Y_POSITION; \ + type CURSOR_HOT_SPOT_X; \ + type CURSOR_HOT_SPOT_Y; \ + type CURSOR_DST_X_OFFSET; \ + type OUTPUT_FP struct dcn_mi_shift { DCN_MI_REG_FIELD_LIST(uint8_t); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h index 6cef9ad0af91..5c8e45ba8f45 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h @@ -72,6 +72,7 @@ struct mem_input { int opp_id; int mpcc_id; struct stutter_modes stutter_mode; + struct dc_cursor_attributes curs_attr; }; struct vm_system_aperture_param { @@ -163,6 +164,15 @@ struct mem_input_funcs { void (*set_blank)(struct mem_input *mi, bool blank); void (*set_hubp_blank_en)(struct mem_input *mi, bool blank); + void (*set_cursor_attributes)( + struct mem_input *mem_input, + const struct dc_cursor_attributes *attr); + + void (*set_cursor_position)( + struct mem_input *mem_input, + const struct dc_cursor_position *pos, + const struct dc_cursor_mi_param *param); + }; #endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h index 785d39706832..f95621dfd4d4 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h @@ -238,6 +238,17 @@ struct transform_funcs { void (*ipp_full_bypass)(struct transform *xfm_base); + void (*set_cursor_attributes)( + struct transform *xfm_base, + const struct dc_cursor_attributes *attr); + + void (*set_cursor_position)( + struct transform *xfm_base, + const struct dc_cursor_position *pos, + const struct dc_cursor_mi_param *param, + uint32_t width + ); + }; const uint16_t *get_filter_2tap_16p(void); -- cgit From 8740196935625dfb171ab115120315060e4a8a41 Mon Sep 17 00:00:00 2001 From: Andrew Jiang Date: Mon, 25 Sep 2017 18:03:14 -0400 Subject: drm/amd/display: Move power control from link encoder to hwsequencer A recent commit moved the backlight control code along with the register defines, but did not move the power control code. This along with remnant fields in the dce110_link_enc_registers struct made it so that the code still compiled, but any attempts to access the LVTMA_PWRSEQ_STATE register led to reading from an address of 0. This patch corrects that. Also, rename blacklight_control to edp_backlight_control (Typo fix). Signed-off-by: Andrew Jiang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 17 +- drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 8 +- drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h | 18 ++- .../gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 171 +-------------------- .../gpu/drm/amd/display/dc/dce/dce_link_encoder.h | 8 - .../amd/display/dc/dce110/dce110_hw_sequencer.c | 155 +++++++++++++++++-- .../amd/display/dc/dce110/dce110_hw_sequencer.h | 6 +- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 3 +- .../gpu/drm/amd/display/dc/inc/hw/link_encoder.h | 2 - drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 7 +- drivers/gpu/drm/amd/display/dc/inc/link_hwss.h | 4 + .../amd/display/dc/virtual/virtual_link_encoder.c | 5 - 12 files changed, 190 insertions(+), 214 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index a58e61b6e9f9..feb10be0ce4c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -78,14 +78,15 @@ static void destruct(struct dc_link *link) dc_sink_release(link->remote_sinks[i]); } -static struct gpio *get_hpd_gpio(const struct dc_link *link) +struct gpio *get_hpd_gpio(struct dc_bios *dcb, + struct graphics_object_id link_id, + struct gpio_service *gpio_service) { enum bp_result bp_result; - struct dc_bios *dcb = link->ctx->dc_bios; struct graphics_object_hpd_info hpd_info; struct gpio_pin_info pin_info; - if (dcb->funcs->get_hpd_info(dcb, link->link_id, &hpd_info) != BP_RESULT_OK) + if (dcb->funcs->get_hpd_info(dcb, link_id, &hpd_info) != BP_RESULT_OK) return NULL; bp_result = dcb->funcs->get_gpio_pin_info(dcb, @@ -97,7 +98,7 @@ static struct gpio *get_hpd_gpio(const struct dc_link *link) } return dal_gpio_service_create_irq( - link->ctx->gpio_service, + gpio_service, pin_info.offset, pin_info.mask); } @@ -153,7 +154,7 @@ static bool program_hpd_filter( } /* Obtain HPD handle */ - hpd = get_hpd_gpio(link); + hpd = get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service); if (!hpd) return result; @@ -186,7 +187,7 @@ static bool detect_sink(struct dc_link *link, enum dc_connection_type *type) struct gpio *hpd_pin; /* todo: may need to lock gpio access */ - hpd_pin = get_hpd_gpio(link); + hpd_pin = get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service); if (hpd_pin == NULL) goto hpd_gpio_failure; @@ -795,7 +796,7 @@ static enum hpd_source_id get_hpd_line( struct gpio *hpd; enum hpd_source_id hpd_id = HPD_SOURCEID_UNKNOWN; - hpd = get_hpd_gpio(link); + hpd = get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service); if (hpd) { switch (dal_irq_get_source(hpd)) { @@ -965,7 +966,7 @@ static bool construct( goto create_fail; } - hpd_gpio = get_hpd_gpio(link); + hpd_gpio = get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service); if (hpd_gpio != NULL) link->irq_source_hpd = dal_irq_get_source(hpd_gpio); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index fa2250554be5..34b6d1cb151e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -89,12 +89,12 @@ void dp_enable_link_phy( if (dc_is_dp_sst_signal(signal)) { if (signal == SIGNAL_TYPE_EDP) { - link_enc->funcs->power_control(link_enc, true); + link->dc->hwss.edp_power_control(link->link_enc, true); link_enc->funcs->enable_dp_output( link_enc, link_settings, clock_source); - link->dc->hwss.backlight_control(link, true); + link->dc->hwss.edp_backlight_control(link, true); } else link_enc->funcs->enable_dp_output( link_enc, @@ -138,10 +138,10 @@ void dp_disable_link_phy(struct dc_link *link, enum signal_type signal) dp_receiver_power_ctrl(link, false); if (signal == SIGNAL_TYPE_EDP) { - link->dc->hwss.backlight_control(link, false); + link->dc->hwss.edp_backlight_control(link, false); edp_receiver_ready_T9(link); link->link_enc->funcs->disable_output(link->link_enc, signal, link); - link->link_enc->funcs->power_control(link->link_enc, false); + link->dc->hwss.edp_power_control(link->link_enc, false); } else link->link_enc->funcs->disable_output(link->link_enc, signal, link); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index 227c9b655b65..0a058e0c3fec 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -391,23 +391,27 @@ struct dce_hwseq_registers { HWS_SF(BLND_, V_UPDATE_LOCK, BLND_DCP_GRPH_SURF_V_UPDATE_LOCK, mask_sh),\ HWS_SF(BLND_, CONTROL, BLND_MODE, mask_sh),\ HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh),\ + HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh),\ HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_) #define HWSEQ_DCE10_MASK_SH_LIST(mask_sh)\ HWSEQ_DCEF_MASK_SH_LIST(mask_sh, DCFE_),\ HWSEQ_BLND_MASK_SH_LIST(mask_sh, BLND_),\ HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_), \ - HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh) + HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh), \ + HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh) #define HWSEQ_DCE11_MASK_SH_LIST(mask_sh)\ HWSEQ_DCE10_MASK_SH_LIST(mask_sh),\ SF(DCFEV_CLOCK_CONTROL, DCFEV_CLOCK_ENABLE, mask_sh),\ HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh),\ + HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh),\ HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_) #define HWSEQ_DCE112_MASK_SH_LIST(mask_sh)\ HWSEQ_DCE10_MASK_SH_LIST(mask_sh),\ HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh),\ + HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh),\ HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, CRTC0_) #define HWSEQ_GFX9_DCHUB_MASK_SH_LIST(mask_sh)\ @@ -416,7 +420,8 @@ struct dce_hwseq_registers { SF(DCHUB_AGP_BASE, AGP_BASE, mask_sh),\ SF(DCHUB_AGP_BOT, AGP_BOT, mask_sh),\ SF(DCHUB_AGP_TOP, AGP_TOP, mask_sh), \ - HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh) + HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh), \ + HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh) #define HWSEQ_DCE12_MASK_SH_LIST(mask_sh)\ HWSEQ_DCEF_MASK_SH_LIST(mask_sh, DCFE0_DCFE_),\ @@ -424,7 +429,8 @@ struct dce_hwseq_registers { HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_),\ HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, CRTC0_),\ HWSEQ_GFX9_DCHUB_MASK_SH_LIST(mask_sh), \ - HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh) + HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh), \ + HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh) #define HWSEQ_DCN_MASK_SH_LIST(mask_sh)\ HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, OTG0_),\ @@ -489,7 +495,8 @@ struct dce_hwseq_registers { HWS_SF(, DOMAIN6_PG_STATUS, DOMAIN6_PGFSM_PWR_STATUS, mask_sh), \ HWS_SF(, DOMAIN7_PG_STATUS, DOMAIN7_PGFSM_PWR_STATUS, mask_sh), \ HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh), \ - HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh) + HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh), \ + HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh) #define HWSEQ_REG_FIELD_LIST(type) \ type DCFE_CLOCK_ENABLE; \ @@ -520,7 +527,8 @@ struct dce_hwseq_registers { type LOGICAL_ADDR; \ type ENABLE_L1_TLB;\ type SYSTEM_ACCESS_MODE;\ - type LVTMA_BLON; + type LVTMA_BLON;\ + type LVTMA_PWRSEQ_TARGET_STATE_R; #define HWSEQ_DCN_REG_FIELD_LIST(type) \ type VUPDATE_NO_LOCK_EVENT_CLEAR; \ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 1cb727bdaa56..0cf0fff74d44 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -82,13 +82,6 @@ #define DCE110_DIG_FE_SOURCE_SELECT_DIGF 0x20 #define DCE110_DIG_FE_SOURCE_SELECT_DIGG 0x40 -/* all values are in milliseconds */ -/* For eDP, after power-up/power/down, - * 300/500 msec max. delay from LCDVCC to black video generation */ -#define PANEL_POWER_UP_TIMEOUT 300 -#define PANEL_POWER_DOWN_TIMEOUT 500 -#define HPD_CHECK_INTERVAL 10 - /* Minimum pixel clock, in KHz. For TMDS signal is 25.00 MHz */ #define TMDS_MIN_PIXEL_CLOCK 25000 /* Maximum pixel clock, in KHz. For TMDS signal is 165.00 MHz */ @@ -122,7 +115,6 @@ static const struct link_encoder_funcs dce110_lnk_enc_funcs = { .psr_program_dp_dphy_fast_training = dce110_psr_program_dp_dphy_fast_training, .psr_program_secondary_packet = dce110_psr_program_secondary_packet, - .power_control = dce110_link_encoder_edp_power_control, .connect_dig_be_to_fe = dce110_link_encoder_connect_dig_be_to_fe, .enable_hpd = dce110_link_encoder_enable_hpd, .disable_hpd = dce110_link_encoder_disable_hpd, @@ -492,165 +484,6 @@ static void configure_encoder( REG_UPDATE(DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_ADVANCE, 1); } -static bool is_panel_powered_on(struct dce110_link_encoder *enc110) -{ - bool ret; - uint32_t value; - - REG_GET(LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, &value); - ret = value; - - return ret == 1; -} - - -/* TODO duplicate of dc_link.c version */ -static struct gpio *get_hpd_gpio(const struct link_encoder *enc) -{ - enum bp_result bp_result; - struct dc_bios *dcb = enc->ctx->dc_bios; - struct graphics_object_hpd_info hpd_info; - struct gpio_pin_info pin_info; - - if (dcb->funcs->get_hpd_info(dcb, enc->connector, &hpd_info) != BP_RESULT_OK) - return NULL; - - bp_result = dcb->funcs->get_gpio_pin_info(dcb, - hpd_info.hpd_int_gpio_uid, &pin_info); - - if (bp_result != BP_RESULT_OK) { - ASSERT(bp_result == BP_RESULT_NORECORD); - return NULL; - } - - return dal_gpio_service_create_irq( - enc->ctx->gpio_service, - pin_info.offset, - pin_info.mask); -} - -/* - * @brief - * eDP only. - */ -static void link_encoder_edp_wait_for_hpd_ready( - struct dce110_link_encoder *enc110, - bool power_up) -{ - struct dc_context *ctx = enc110->base.ctx; - struct graphics_object_id connector = enc110->base.connector; - struct gpio *hpd; - bool edp_hpd_high = false; - uint32_t time_elapsed = 0; - uint32_t timeout = power_up ? - PANEL_POWER_UP_TIMEOUT : PANEL_POWER_DOWN_TIMEOUT; - - if (dal_graphics_object_id_get_connector_id(connector) != - CONNECTOR_ID_EDP) { - BREAK_TO_DEBUGGER(); - return; - } - - if (!power_up) - /* from KV, we will not HPD low after turning off VCC - - * instead, we will check the SW timer in power_up(). */ - return; - - /* when we power on/off the eDP panel, - * we need to wait until SENSE bit is high/low */ - - /* obtain HPD */ - /* TODO what to do with this? */ - hpd = get_hpd_gpio(&enc110->base); - - if (!hpd) { - BREAK_TO_DEBUGGER(); - return; - } - - dal_gpio_open(hpd, GPIO_MODE_INTERRUPT); - - /* wait until timeout or panel detected */ - - do { - uint32_t detected = 0; - - dal_gpio_get_value(hpd, &detected); - - if (!(detected ^ power_up)) { - edp_hpd_high = true; - break; - } - - msleep(HPD_CHECK_INTERVAL); - - time_elapsed += HPD_CHECK_INTERVAL; - } while (time_elapsed < timeout); - - dal_gpio_close(hpd); - - dal_gpio_destroy_irq(&hpd); - - if (false == edp_hpd_high) { - dm_logger_write(ctx->logger, LOG_ERROR, - "%s: wait timed out!\n", __func__); - } -} - -/* - * @brief - * eDP only. Control the power of the eDP panel. - */ -void dce110_link_encoder_edp_power_control( - struct link_encoder *enc, - bool power_up) -{ - struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); - struct dc_context *ctx = enc110->base.ctx; - struct bp_transmitter_control cntl = { 0 }; - enum bp_result bp_result; - - if (dal_graphics_object_id_get_connector_id(enc110->base.connector) != - CONNECTOR_ID_EDP) { - BREAK_TO_DEBUGGER(); - return; - } - - if ((power_up && !is_panel_powered_on(enc110)) || - (!power_up && is_panel_powered_on(enc110))) { - - /* Send VBIOS command to prompt eDP panel power */ - - dm_logger_write(ctx->logger, LOG_HW_RESUME_S3, - "%s: Panel Power action: %s\n", - __func__, (power_up ? "On":"Off")); - - cntl.action = power_up ? - TRANSMITTER_CONTROL_POWER_ON : - TRANSMITTER_CONTROL_POWER_OFF; - cntl.transmitter = enc110->base.transmitter; - cntl.connector_obj_id = enc110->base.connector; - cntl.coherent = false; - cntl.lanes_number = LANE_COUNT_FOUR; - cntl.hpd_sel = enc110->base.hpd_source; - - bp_result = link_transmitter_control(enc110, &cntl); - - if (BP_RESULT_OK != bp_result) { - - dm_logger_write(ctx->logger, LOG_ERROR, - "%s: Panel Power bp_result: %d\n", - __func__, bp_result); - } - } else { - dm_logger_write(ctx->logger, LOG_HW_RESUME_S3, - "%s: Skipping Panel Power action: %s\n", - __func__, (power_up ? "On":"Off")); - } - - link_encoder_edp_wait_for_hpd_ready(enc110, true); -} - static void aux_initialize( struct dce110_link_encoder *enc110) { @@ -1018,7 +851,7 @@ void dce110_link_encoder_hw_init( ASSERT(result == BP_RESULT_OK); } else if (enc110->base.connector.id == CONNECTOR_ID_EDP) { - enc->funcs->power_control(&enc110->base, true); + ctx->dc->hwss.edp_power_control(enc, true); } aux_initialize(enc110); @@ -1218,7 +1051,7 @@ void dce110_link_encoder_disable_output( return; } if (enc110->base.connector.id == CONNECTOR_ID_EDP) - ctx->dc->hwss.backlight_control(link, false); + ctx->dc->hwss.edp_backlight_control(link, false); /* Power-down RX and disable GPU PHY should be paired. * Disabling PHY without powering down RX may cause * symbol lock loss, on which we will get DP Sink interrupt. */ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h index c65def5f6a44..494067dedd03 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h @@ -114,10 +114,6 @@ struct dce110_link_enc_hpd_registers { }; struct dce110_link_enc_registers { - /* Backlight registers */ - uint32_t LVTMA_PWRSEQ_CNTL; - uint32_t LVTMA_PWRSEQ_STATE; - /* DMCU registers */ uint32_t MASTER_COMM_DATA_REG1; uint32_t MASTER_COMM_DATA_REG2; @@ -250,10 +246,6 @@ void dce110_link_encoder_update_mst_stream_allocation_table( struct link_encoder *enc, const struct link_mst_stream_allocation_table *table); -void dce110_link_encoder_edp_power_control( - struct link_encoder *enc, - bool power_up); - void dce110_link_encoder_connect_dig_be_to_fe( struct link_encoder *enc, enum engine_id engine, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index f28fce6e6ba4..a891e387ed7b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -32,6 +32,7 @@ #include "dce110_hw_sequencer.h" #include "dce110_timing_generator.h" #include "dce/dce_hwseq.h" +#include "gpio_service_interface.h" #ifdef ENABLE_FBC #include "dce110_compressor.h" @@ -45,10 +46,10 @@ #include "transform.h" #include "stream_encoder.h" #include "link_encoder.h" +#include "link_hwss.h" #include "clock_source.h" #include "abm.h" #include "audio.h" -#include "dce/dce_hwseq.h" #include "reg_helper.h" /* include DCE11 register header files */ @@ -56,6 +57,15 @@ #include "dce/dce_11_0_sh_mask.h" #include "custom_float.h" +/* + * All values are in milliseconds; + * For eDP, after power-up/power/down, + * 300/500 msec max. delay from LCDVCC to black video generation + */ +#define PANEL_POWER_UP_TIMEOUT 300 +#define PANEL_POWER_DOWN_TIMEOUT 500 +#define HPD_CHECK_INTERVAL 10 + #define CTX \ hws->ctx #define REG(reg)\ @@ -780,25 +790,150 @@ static bool is_panel_backlight_on(struct dce_hwseq *hws) return value; } +static bool is_panel_powered_on(struct dce_hwseq *hws) +{ + uint32_t value; + + REG_GET(LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, &value); + return value == 1; +} + static enum bp_result link_transmitter_control( - struct dc_link *link, + struct dc_bios *bios, struct bp_transmitter_control *cntl) { enum bp_result result; - struct dc_bios *bp = link->dc->ctx->dc_bios; - result = bp->funcs->transmitter_control(bp, cntl); + result = bios->funcs->transmitter_control(bios, cntl); return result; } +/* + * @brief + * eDP only. + */ +void hwss_edp_wait_for_hpd_ready( + struct link_encoder *enc, + bool power_up) +{ + struct dc_context *ctx = enc->ctx; + struct graphics_object_id connector = enc->connector; + struct gpio *hpd; + bool edp_hpd_high = false; + uint32_t time_elapsed = 0; + uint32_t timeout = power_up ? + PANEL_POWER_UP_TIMEOUT : PANEL_POWER_DOWN_TIMEOUT; + + if (dal_graphics_object_id_get_connector_id(connector) + != CONNECTOR_ID_EDP) { + BREAK_TO_DEBUGGER(); + return; + } + + if (!power_up) + /* + * From KV, we will not HPD low after turning off VCC - + * instead, we will check the SW timer in power_up(). + */ + return; + + /* + * When we power on/off the eDP panel, + * we need to wait until SENSE bit is high/low. + */ + + /* obtain HPD */ + /* TODO what to do with this? */ + hpd = get_hpd_gpio(ctx->dc_bios, connector, ctx->gpio_service); + + if (!hpd) { + BREAK_TO_DEBUGGER(); + return; + } + + dal_gpio_open(hpd, GPIO_MODE_INTERRUPT); + + /* wait until timeout or panel detected */ + + do { + uint32_t detected = 0; + + dal_gpio_get_value(hpd, &detected); + + if (!(detected ^ power_up)) { + edp_hpd_high = true; + break; + } + + msleep(HPD_CHECK_INTERVAL); + + time_elapsed += HPD_CHECK_INTERVAL; + } while (time_elapsed < timeout); + + dal_gpio_close(hpd); + + dal_gpio_destroy_irq(&hpd); + + if (false == edp_hpd_high) { + dm_logger_write(ctx->logger, LOG_ERROR, + "%s: wait timed out!\n", __func__); + } +} + +void hwss_edp_power_control( + struct link_encoder *enc, + bool power_up) +{ + struct dc_context *ctx = enc->ctx; + struct dce_hwseq *hwseq = ctx->dc->hwseq; + struct bp_transmitter_control cntl = { 0 }; + enum bp_result bp_result; + + + if (dal_graphics_object_id_get_connector_id(enc->connector) + != CONNECTOR_ID_EDP) { + BREAK_TO_DEBUGGER(); + return; + } + + if (power_up != is_panel_powered_on(hwseq)) { + /* Send VBIOS command to prompt eDP panel power */ + + dm_logger_write(ctx->logger, LOG_HW_RESUME_S3, + "%s: Panel Power action: %s\n", + __func__, (power_up ? "On":"Off")); + + cntl.action = power_up ? + TRANSMITTER_CONTROL_POWER_ON : + TRANSMITTER_CONTROL_POWER_OFF; + cntl.transmitter = enc->transmitter; + cntl.connector_obj_id = enc->connector; + cntl.coherent = false; + cntl.lanes_number = LANE_COUNT_FOUR; + cntl.hpd_sel = enc->hpd_source; + + bp_result = link_transmitter_control(ctx->dc_bios, &cntl); + + if (bp_result != BP_RESULT_OK) + dm_logger_write(ctx->logger, LOG_ERROR, + "%s: Panel Power bp_result: %d\n", + __func__, bp_result); + } else { + dm_logger_write(ctx->logger, LOG_HW_RESUME_S3, + "%s: Skipping Panel Power action: %s\n", + __func__, (power_up ? "On":"Off")); + } + + hwss_edp_wait_for_hpd_ready(enc, true); +} /*todo: cloned in stream enc, fix*/ /* * @brief * eDP only. Control the backlight of the eDP panel */ -void hwss_blacklight_control( +void hwss_edp_backlight_control( struct dc_link *link, bool enable) { @@ -828,6 +963,7 @@ void hwss_blacklight_control( cntl.action = enable ? TRANSMITTER_CONTROL_BACKLIGHT_ON : TRANSMITTER_CONTROL_BACKLIGHT_OFF; + /*cntl.engine_id = ctx->engine;*/ cntl.transmitter = link->link_enc->transmitter; cntl.connector_obj_id = link->link_enc->connector; @@ -846,7 +982,7 @@ void hwss_blacklight_control( * Enable it in the future if necessary. */ /* dc_service_sleep_in_milliseconds(50); */ - link_transmitter_control(link, &cntl); + link_transmitter_control(link->dc->ctx->dc_bios, &cntl); } void dce110_disable_stream(struct pipe_ctx *pipe_ctx) @@ -886,7 +1022,7 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) /* blank at encoder level */ if (dc_is_dp_signal(pipe_ctx->stream->signal)) { if (pipe_ctx->stream->sink->link->connector_signal == SIGNAL_TYPE_EDP) - hwss_blacklight_control(link, false); + hwss_edp_backlight_control(link, false); pipe_ctx->stream_res.stream_enc->funcs->dp_blank(pipe_ctx->stream_res.stream_enc); } link->link_enc->funcs->connect_dig_be_to_fe( @@ -908,7 +1044,7 @@ void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, params.link_settings.link_rate = link_settings->link_rate; pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(pipe_ctx->stream_res.stream_enc, ¶ms); if (link->connector_signal == SIGNAL_TYPE_EDP) - hwss_blacklight_control(link, true); + hwss_edp_backlight_control(link, true); } @@ -2821,7 +2957,8 @@ static const struct hw_sequencer_funcs dce110_funcs = { .wait_for_mpcc_disconnect = dce110_wait_for_mpcc_disconnect, .ready_shared_resources = ready_shared_resources, .optimize_shared_resources = optimize_shared_resources, - .backlight_control = hwss_blacklight_control + .edp_backlight_control = hwss_edp_backlight_control, + .edp_power_control = hwss_edp_power_control, }; void dce110_hw_sequencer_construct(struct dc *dc) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h index 3e95f7f92c73..a1e964af60ac 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h @@ -69,7 +69,11 @@ uint32_t dce110_get_min_vblank_time_us(const struct dc_state *context); void dp_receiver_power_ctrl(struct dc_link *link, bool on); -void hwss_blacklight_control( +void hwss_edp_power_control( + struct link_encoder *enc, + bool power_up); + +void hwss_edp_backlight_control( struct dc_link *link, bool enable); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 014911ebdbd6..efa3f6f97baf 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2903,7 +2903,8 @@ static const struct hw_sequencer_funcs dcn10_funcs = { .wait_for_mpcc_disconnect = dcn10_wait_for_mpcc_disconnect, .ready_shared_resources = ready_shared_resources, .optimize_shared_resources = optimize_shared_resources, - .backlight_control = hwss_blacklight_control + .edp_backlight_control = hwss_edp_backlight_control, + .edp_power_control = hwss_edp_power_control }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h index 6cd6bc7d15fb..3d33bcda7059 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h @@ -123,8 +123,6 @@ struct link_encoder_funcs { bool exit_link_training_required); void (*psr_program_secondary_packet)(struct link_encoder *enc, unsigned int sdp_transmit_line_num_deadline); - void (*power_control) (struct link_encoder *enc, - bool power_up); void (*connect_dig_be_to_fe)(struct link_encoder *enc, enum engine_id engine, bool connect); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 210874f37722..bf3ab5d7398e 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -28,6 +28,7 @@ #include "dc_types.h" #include "clock_source.h" #include "inc/hw/timing_generator.h" +#include "inc/hw/link_encoder.h" #include "core_status.h" enum pipe_gating_control { @@ -176,8 +177,10 @@ struct hw_sequencer_funcs { void (*ready_shared_resources)(struct dc *dc, struct dc_state *context); void (*optimize_shared_resources)(struct dc *dc); - - void (*backlight_control)( + void (*edp_power_control)( + struct link_encoder *enc, + bool enable); + void (*edp_backlight_control)( struct dc_link *link, bool enable); }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h index f7994cfc850d..f2b8c9a376d5 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h +++ b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h @@ -40,6 +40,10 @@ enum dc_status core_link_write_dpcd( const uint8_t *data, uint32_t size); +struct gpio *get_hpd_gpio(struct dc_bios *dcb, + struct graphics_object_id link_id, + struct gpio_service *gpio_service); + void dp_enable_link_phy( struct dc_link *link, enum signal_type signal, diff --git a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c index 4f405348130f..88c2bde3f039 100644 --- a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c @@ -73,10 +73,6 @@ static void virtual_link_encoder_update_mst_stream_allocation_table( struct link_encoder *enc, const struct link_mst_stream_allocation_table *table) {} -static void virtual_link_encoder_edp_power_control( - struct link_encoder *enc, - bool power_up) {} - static void virtual_link_encoder_connect_dig_be_to_fe( struct link_encoder *enc, enum engine_id engine, @@ -102,7 +98,6 @@ static const struct link_encoder_funcs virtual_lnk_enc_funcs = { .dp_set_phy_pattern = virtual_link_encoder_dp_set_phy_pattern, .update_mst_stream_allocation_table = virtual_link_encoder_update_mst_stream_allocation_table, - .power_control = virtual_link_encoder_edp_power_control, .connect_dig_be_to_fe = virtual_link_encoder_connect_dig_be_to_fe, .destroy = virtual_link_encoder_destroy }; -- cgit From 6512387a54357c5d3fbea8995d8879ea817a5ec6 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Wed, 27 Sep 2017 09:20:51 -0400 Subject: drm/amd/display: align DCLK to voltage level in past program SMU will use all voltage headroom. RV does not if DAL need higher voltage for DCFCLK or DISPCLK, also increase FCLK to improve stutter as voltage is already Signed-off-by: Tony Cheng Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 4 ++++ drivers/gpu/drm/amd/display/dc/dc.h | 1 + drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 1 + 3 files changed, 6 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index cf474eb1cde8..9337ccadc321 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -1049,6 +1049,10 @@ bool dcn_validate_bandwidth( else bw_consumed = v->fabric_and_dram_bandwidth_vmax0p9; + if (bw_consumed < v->fabric_and_dram_bandwidth) + if (dc->debug.voltage_align_fclk) + bw_consumed = v->fabric_and_dram_bandwidth; + display_pipe_configuration(v); calc_wm_sets_and_perf_params(context, v); context->bw.dcn.calc_clk.fclk_khz = (int)(bw_consumed * 1000000 / diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index cf9cd108539f..dbbe1d621bee 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -188,6 +188,7 @@ struct dc_debug { enum dcc_option disable_dcc; enum pipe_split_policy pipe_split_policy; bool force_single_disp_pipe_split; + bool voltage_align_fclk; bool disable_dfs_bypass; bool disable_dpp_power_gate; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 30c275e05796..4018e831eb4b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -428,6 +428,7 @@ static const struct dc_debug debug_defaults_drv = { .pipe_split_policy = MPC_SPLIT_AVOID_MULT_DISP, .disable_dcc = DCC_ENABLE, + .voltage_align_fclk = true, }; static const struct dc_debug debug_defaults_diags = { -- cgit From dcf298c3137ace22b92c584781e6092e4eb273fb Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Mon, 25 Sep 2017 14:53:14 -0400 Subject: drm/amd/display: disconnect on HPD low even if edid is the same [Description] There are many occasions we need to retrieve sink capability and notify connectivity change to os even if edid is not changed on a HPD toggle. (HDMI2.0 display needs re-enable link on every hpd, display changes other capability outside from edid need to be queried again and possibly reset the mode, etc.) In these cases we cannot keep the same sink without letting DM know. Signed-off-by: Wenjing Liu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 42 ++++++--------------------- 1 file changed, 9 insertions(+), 33 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index feb10be0ce4c..e414e4770789 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -566,6 +566,8 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) link->local_sink) return true; + link_disconnect_sink(link); + if (new_connection_type != dc_connection_none) { link->type = new_connection_type; @@ -656,28 +658,15 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) return false; } - if (link->local_sink) { - edid_status = dm_helpers_read_local_edid( - link->ctx, - link, - sink); + sink->dongle_max_pix_clk = sink_caps.max_hdmi_pixel_clock; + sink->converter_disable_audio = converter_disable_audio; - if (edid_status == EDID_OK) { - // Edid is not the same, to update the local sink with new sink. - sink->dongle_max_pix_clk = sink_caps.max_hdmi_pixel_clock; - sink->converter_disable_audio = converter_disable_audio; - link->local_sink = sink; - } - } else { - sink->dongle_max_pix_clk = sink_caps.max_hdmi_pixel_clock; - sink->converter_disable_audio = converter_disable_audio; - link->local_sink = sink; + link->local_sink = sink; - edid_status = dm_helpers_read_local_edid( + edid_status = dm_helpers_read_local_edid( link->ctx, link, sink); - } switch (edid_status) { case EDID_BAD_CHECKSUM: @@ -758,28 +747,15 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) if (link->type == dc_connection_mst_branch) { LINK_INFO("link=%d, mst branch is now Disconnected\n", link->link_index); + dm_helpers_dp_mst_stop_top_mgr(link->ctx, link); link->mst_stream_alloc_table.stream_count = 0; memset(link->mst_stream_alloc_table.stream_allocations, 0, sizeof(link->mst_stream_alloc_table.stream_allocations)); } - if (link->local_sink) { - sink = link->local_sink; - edid_status = dm_helpers_read_local_edid( - link->ctx, - link, - sink); - if (edid_status != EDID_OK && edid_status != EDID_THE_SAME) { - link_disconnect_sink(link); - link->type = dc_connection_none; - sink_caps.signal = SIGNAL_TYPE_NONE; - } - } else { - link_disconnect_sink(link); - link->type = dc_connection_none; - sink_caps.signal = SIGNAL_TYPE_NONE; - } + link->type = dc_connection_none; + sink_caps.signal = SIGNAL_TYPE_NONE; } LINK_INFO("link=%d, dc_sink_in=%p is now %s\n", -- cgit From 441ad741739e9092f6af231a539781118e23d6df Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Wed, 27 Sep 2017 11:44:43 -0400 Subject: drm/amd/display: Add override for reporting wm ranges For verification of watermark select with SMU team, proper implementation will follow Signed-off-by: Eric Yang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 47 ++++++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dc.h | 6 +++ .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 3 ++ .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 1 + 4 files changed, 57 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 9337ccadc321..6318f9f69c92 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -1441,6 +1441,53 @@ void dcn_bw_notify_pplib_of_wm_ranges(struct dc *dc) ranges.writer_wm_sets[3].min_drain_clk_khz = max_fclk_khz; ranges.writer_wm_sets[3].max_drain_clk_khz = max_fclk_khz; + if (dc->debug.pplib_wm_report_mode == WM_REPORT_OVERRIDE) { + ranges.reader_wm_sets[0].wm_inst = WM_A; + ranges.reader_wm_sets[0].min_drain_clk_khz = 300000; + ranges.reader_wm_sets[0].max_drain_clk_khz = 654000; + ranges.reader_wm_sets[0].min_fill_clk_khz = 800000; + ranges.reader_wm_sets[0].max_fill_clk_khz = 800000; + ranges.writer_wm_sets[0].wm_inst = WM_A; + ranges.writer_wm_sets[0].min_fill_clk_khz = 200000; + ranges.writer_wm_sets[0].max_fill_clk_khz = 757000; + ranges.writer_wm_sets[0].min_drain_clk_khz = 800000; + ranges.writer_wm_sets[0].max_drain_clk_khz = 800000; + + ranges.reader_wm_sets[1].wm_inst = WM_B; + ranges.reader_wm_sets[1].min_drain_clk_khz = 300000; + ranges.reader_wm_sets[1].max_drain_clk_khz = 654000; + ranges.reader_wm_sets[1].min_fill_clk_khz = 933000; + ranges.reader_wm_sets[1].max_fill_clk_khz = 933000; + ranges.writer_wm_sets[1].wm_inst = WM_B; + ranges.writer_wm_sets[1].min_fill_clk_khz = 200000; + ranges.writer_wm_sets[1].max_fill_clk_khz = 757000; + ranges.writer_wm_sets[1].min_drain_clk_khz = 933000; + ranges.writer_wm_sets[1].max_drain_clk_khz = 933000; + + + ranges.reader_wm_sets[2].wm_inst = WM_C; + ranges.reader_wm_sets[2].min_drain_clk_khz = 300000; + ranges.reader_wm_sets[2].max_drain_clk_khz = 654000; + ranges.reader_wm_sets[2].min_fill_clk_khz = 1067000; + ranges.reader_wm_sets[2].max_fill_clk_khz = 1067000; + ranges.writer_wm_sets[2].wm_inst = WM_C; + ranges.writer_wm_sets[2].min_fill_clk_khz = 200000; + ranges.writer_wm_sets[2].max_fill_clk_khz = 757000; + ranges.writer_wm_sets[2].min_drain_clk_khz = 1067000; + ranges.writer_wm_sets[2].max_drain_clk_khz = 1067000; + + ranges.reader_wm_sets[3].wm_inst = WM_D; + ranges.reader_wm_sets[3].min_drain_clk_khz = 300000; + ranges.reader_wm_sets[3].max_drain_clk_khz = 654000; + ranges.reader_wm_sets[3].min_fill_clk_khz = 1200000; + ranges.reader_wm_sets[3].max_fill_clk_khz = 1200000; + ranges.writer_wm_sets[3].wm_inst = WM_D; + ranges.writer_wm_sets[3].min_fill_clk_khz = 200000; + ranges.writer_wm_sets[3].max_fill_clk_khz = 757000; + ranges.writer_wm_sets[3].min_drain_clk_khz = 1200000; + ranges.writer_wm_sets[3].max_drain_clk_khz = 1200000; + } + /* Notify PP Lib/SMU which Watermarks to use for which clock ranges */ pp->set_wm_ranges(&pp->pp_smu, &ranges); } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index dbbe1d621bee..d624554efbc7 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -173,6 +173,11 @@ enum pipe_split_policy { MPC_SPLIT_AVOID_MULT_DISP = 2, }; +enum wm_report_mode { + WM_REPORT_DEFAULT = 0, + WM_REPORT_OVERRIDE = 1, +}; + struct dc_debug { bool surface_visual_confirm; bool sanity_checks; @@ -194,6 +199,7 @@ struct dc_debug { bool disable_dpp_power_gate; bool disable_hubp_power_gate; bool disable_pplib_wm_range; + enum wm_report_mode pplib_wm_report_mode; bool use_dml_wm; unsigned int min_disp_clk_khz; int sr_exit_time_dpm0_ns; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index efa3f6f97baf..86cfab33feea 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2451,6 +2451,9 @@ static void optimize_shared_resources(struct dc *dc) /* S0i2 message */ dcn10_pplib_apply_display_requirements(dc, dc->current_state); } + + if (dc->debug.pplib_wm_report_mode == WM_REPORT_OVERRIDE) + dcn_bw_notify_pplib_of_wm_ranges(dc); } static void ready_shared_resources(struct dc *dc, struct dc_state *context) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 4018e831eb4b..5d618e68a744 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -424,6 +424,7 @@ static const struct dc_debug debug_defaults_drv = { .disable_pplib_clock_request = true, .disable_pplib_wm_range = false, + .pplib_wm_report_mode = WM_REPORT_DEFAULT, .use_dml_wm = false, .pipe_split_policy = MPC_SPLIT_AVOID_MULT_DISP, -- cgit From ed23cba20d011e1867dea69a45bda88a088585b6 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Wed, 27 Sep 2017 16:08:47 -0400 Subject: drm/amd/display: soc_bound_box -update DML based on HW. Signed-off-by: Charlene Liu Reviewed-by: Anthony Koo Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c b/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c index 0745366d80bc..d40f6ae9622c 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c +++ b/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c @@ -68,7 +68,6 @@ double dml_socbb_return_bw_mhz(struct _vcs_dpi_soc_bounding_box_st *box, enum vo return_bw = dml_min( ((double) box->return_bus_width_bytes) * state.dcfclk_mhz, - state.dram_bw_per_chan_gbps * 1000.0 * (double) box->num_chans - * box->ideal_dram_bw_after_urgent_percent / 100.0); + state.dram_bw_per_chan_gbps * 1000.0 * box->ideal_dram_bw_after_urgent_percent / 100.0); return return_bw; } -- cgit From c73b046f86d0ceac52bfa0a035796c8c017a2de5 Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Wed, 27 Sep 2017 15:34:35 -0400 Subject: drm/amd/display: Expose some mem_input functions for reuse Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h | 1 - .../gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c | 26 +++++----- .../gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h | 60 ++++++++++++++++++++++ 3 files changed, 73 insertions(+), 14 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h index 7fecdb19761d..889f91cf47cf 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h @@ -113,7 +113,6 @@ SRI(FORMAT_CONTROL, CNVC_CFG, id), \ SRI(CNVC_SURFACE_PIXEL_FORMAT, CNVC_CFG, id), \ SRI(CURSOR0_CONTROL, CNVC_CUR, id), \ - SRI(CURSOR0_CONTROL, CNVC_CUR, id), \ SRI(CURSOR0_COLOR0, CNVC_CUR, id), \ SRI(CURSOR0_COLOR1, CNVC_CUR, id) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index efa1aca187ad..b61f41c61358 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -38,7 +38,7 @@ #define FN(reg_name, field_name) \ mi->mi_shift->field_name, mi->mi_mask->field_name -static void min10_set_blank(struct mem_input *mem_input, bool blank) +void min10_set_blank(struct mem_input *mem_input, bool blank) { struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); uint32_t blank_en = blank ? 1 : 0; @@ -87,7 +87,7 @@ static void min10_vready_workaround(struct mem_input *mem_input, REG_WRITE(HUBPREQ_DEBUG_DB, value); } -static void min10_program_tiling( +void min10_program_tiling( struct dcn10_mem_input *mi, const union dc_tiling_info *info, const enum surface_pixel_format pixel_format) @@ -107,7 +107,7 @@ static void min10_program_tiling( PIPE_ALIGNED, info->gfx9.pipe_aligned); } -static void min10_program_size_and_rotation( +void min10_program_size_and_rotation( struct dcn10_mem_input *mi, enum dc_rotation_angle rotation, enum surface_pixel_format format, @@ -169,7 +169,7 @@ static void min10_program_size_and_rotation( H_MIRROR_EN, mirror); } -static void min10_program_pixel_format( +void min10_program_pixel_format( struct dcn10_mem_input *mi, enum surface_pixel_format format) { @@ -245,7 +245,7 @@ static void min10_program_pixel_format( /* don't see the need of program the xbar in DCN 1.0 */ } -static bool min10_program_surface_flip_and_addr( +bool min10_program_surface_flip_and_addr( struct mem_input *mem_input, const struct dc_plane_address *address, bool flip_immediate) @@ -395,7 +395,7 @@ static bool min10_program_surface_flip_and_addr( return true; } -static void min10_dcc_control(struct mem_input *mem_input, bool enable, +void min10_dcc_control(struct mem_input *mem_input, bool enable, bool independent_64b_blks) { uint32_t dcc_en = enable ? 1 : 0; @@ -425,7 +425,7 @@ static void min10_program_surface_config( min10_program_pixel_format(mi, format); } -static void min10_program_requestor( +void min10_program_requestor( struct mem_input *mem_input, struct _vcs_dpi_display_rq_regs_st *rq_regs) { @@ -459,7 +459,7 @@ static void min10_program_requestor( } -static void min10_program_deadline( +void min10_program_deadline( struct mem_input *mem_input, struct _vcs_dpi_display_dlg_regs_st *dlg_attr, struct _vcs_dpi_display_ttu_regs_st *ttu_attr) @@ -595,7 +595,7 @@ static void min10_setup( min10_vready_workaround(mem_input, pipe_dest); } -static void min10_program_display_marks( +void min10_program_display_marks( struct mem_input *mem_input, struct dce_watermarks nbp, struct dce_watermarks stutter, @@ -607,7 +607,7 @@ static void min10_program_display_marks( */ } -static bool min10_is_flip_pending(struct mem_input *mem_input) +bool min10_is_flip_pending(struct mem_input *mem_input) { uint32_t flip_pending = 0; struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); @@ -696,7 +696,7 @@ static void min10_set_vm_context0_settings(struct mem_input *mem_input, SYSTEM_ACCESS_MODE, 3); } -static void min_set_viewport( +void min_set_viewport( struct mem_input *mem_input, const struct rect *viewport, const struct rect *viewport_c) @@ -845,7 +845,7 @@ static enum cursor_lines_per_chunk ippn10_get_lines_per_chunk( return line_per_chunk; } -static void ippn10_cursor_set_attributes( +void ippn10_cursor_set_attributes( struct mem_input *mem_input, const struct dc_cursor_attributes *attr) { @@ -873,7 +873,7 @@ static void ippn10_cursor_set_attributes( attr->color_format); } -static void ippn10_cursor_set_position( +void ippn10_cursor_set_position( struct mem_input *mem_input, const struct dc_cursor_position *pos, const struct dc_cursor_mi_param *param) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h index 2c79d7aa3f91..fdeb0e87463e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h @@ -589,6 +589,65 @@ struct dcn10_mem_input { const struct dcn_mi_mask *mi_mask; }; +void min10_program_deadline( + struct mem_input *mem_input, + struct _vcs_dpi_display_dlg_regs_st *dlg_attr, + struct _vcs_dpi_display_ttu_regs_st *ttu_attr); + +void min10_program_requestor( + struct mem_input *mem_input, + struct _vcs_dpi_display_rq_regs_st *rq_regs); + +void min10_program_pixel_format( + struct dcn10_mem_input *mi, + enum surface_pixel_format format); + +void min10_program_size_and_rotation( + struct dcn10_mem_input *mi, + enum dc_rotation_angle rotation, + enum surface_pixel_format format, + const union plane_size *plane_size, + struct dc_plane_dcc_param *dcc, + bool horizontal_mirror); + +void min10_program_tiling( + struct dcn10_mem_input *mi, + const union dc_tiling_info *info, + const enum surface_pixel_format pixel_format); + +void min10_dcc_control(struct mem_input *mem_input, + bool enable, + bool independent_64b_blks); + +void min10_program_display_marks( + struct mem_input *mem_input, + struct dce_watermarks nbp, + struct dce_watermarks stutter, + struct dce_watermarks urgent, + uint32_t total_dest_line_time_ns); + +bool min10_program_surface_flip_and_addr( + struct mem_input *mem_input, + const struct dc_plane_address *address, + bool flip_immediate); + +bool min10_is_flip_pending(struct mem_input *mem_input); + +void ippn10_cursor_set_attributes( + struct mem_input *mem_input, + const struct dc_cursor_attributes *attr); + +void ippn10_cursor_set_position( + struct mem_input *mem_input, + const struct dc_cursor_position *pos, + const struct dc_cursor_mi_param *param); + +void min10_set_blank(struct mem_input *mem_input, bool blank); + +void min_set_viewport(struct mem_input *mem_input, + const struct rect *viewport, + const struct rect *viewport_c); + void dcn10_mem_input_construct( struct dcn10_mem_input *mi, struct dc_context *ctx, @@ -597,6 +656,7 @@ void dcn10_mem_input_construct( const struct dcn_mi_shift *mi_shift, const struct dcn_mi_mask *mi_mask); + struct dcn_hubp_state { uint32_t pixel_format; uint32_t inuse_addr_hi; -- cgit From 07e9266593e64f6897996c37dcfb28cb21a612c6 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 16 Oct 2017 22:10:19 -0400 Subject: Revert "amdgpu/dc: inline dml_round_to_multiple" This reverts commit d8c893b44b2199f5935fe8667708253c38353782. Unfortunately these clash with our DML update from the HW guys. Will attempt to reroll them after. Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c | 19 +++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h | 2 ++ drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h | 19 ------------------- 3 files changed, 21 insertions(+), 19 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c index df2d5099b90e..7c0eb52b91b8 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c @@ -39,4 +39,23 @@ double dml_round(double a) return floor; } +unsigned int dml_round_to_multiple( + unsigned int num, + unsigned int multiple, + bool up) +{ + unsigned int remainder; + + if (multiple == 0) + return num; + + remainder = num % multiple; + if (remainder == 0) + return num; + + if (up) + return (num + multiple - remainder); + else + return (num - remainder); +} diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h index 81c53d879a16..a2da3da5ef8f 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h @@ -33,5 +33,7 @@ #define DTRACE(str, ...) dm_logger_write(mode_lib->logger, LOG_DML, str, ##__VA_ARGS__); double dml_round(double a); +unsigned int dml_round_to_multiple( + unsigned int num, unsigned int multiple, bool up); #endif /* __DC_COMMON_DEFS_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h b/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h index a91b4a6c6154..1c6c631daad4 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h @@ -58,23 +58,4 @@ static inline double dml_log(double x, double base) return (double) dcn_bw_log(x, base); } -static inline unsigned int dml_round_to_multiple(unsigned int num, - unsigned int multiple, - bool up) -{ - unsigned int remainder; - - if (multiple == 0) - return num; - - remainder = num % multiple; - - if (remainder == 0) - return num; - - if (up) - return (num + multiple - remainder); - else - return (num - remainder); -} #endif -- cgit From 78109d230b797077d58600694ca427b9830eb600 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 16 Oct 2017 22:10:31 -0400 Subject: Revert "amdgpu/dc: drop dml display_mode_support.c (v2)" This reverts commit 5e0adbff084f33202db36be798c583a115990392. Unfortunately these clash with our DML update from the HW guys. Will attempt to reroll them after. Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/Makefile | 4 +- .../drm/amd/display/dc/dml/display_mode_support.c | 2327 ++++++++++++++++++++ .../drm/amd/display/dc/dml/display_mode_support.h | 5 + 3 files changed, 2335 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dml/Makefile b/drivers/gpu/drm/amd/display/dc/dml/Makefile index ec712d727665..a6bf36466497 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dml/Makefile @@ -10,10 +10,12 @@ CFLAGS_display_rq_dlg_helpers.o := -mhard-float -msse -mpreferred-stack-boundary CFLAGS_display_watermark.o := -mhard-float -msse -mpreferred-stack-boundary=4 CFLAGS_soc_bounding_box.o := -mhard-float -msse -mpreferred-stack-boundary=4 CFLAGS_dml_common_defs.o := -mhard-float -msse -mpreferred-stack-boundary=4 +CFLAGS_display_mode_support.o := -mhard-float -msse -mpreferred-stack-boundary=4 + DML = display_mode_lib.o display_rq_dlg_calc.o \ display_rq_dlg_helpers.o display_watermark.o \ - soc_bounding_box.o dml_common_defs.o + soc_bounding_box.o dml_common_defs.o display_mode_support.o AMD_DAL_DML = $(addprefix $(AMDDALPATH)/dc/dml/,$(DML)) diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c new file mode 100644 index 000000000000..ac573568c10a --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c @@ -0,0 +1,2327 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "display_mode_support.h" +#include "display_mode_lib.h" + +#include "dml_inline_defs.h" +int dml_ms_check( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + int num_pipes) +{ + struct _vcs_dpi_ip_params_st *ip; + struct _vcs_dpi_soc_bounding_box_st *soc; + struct _vcs_dpi_mode_evaluation_st *me; + struct dml_ms_internal_vars *v; + int num_planes, i, j, ij, k, ijk; + + ip = &(mode_lib->ip); + soc = &(mode_lib->soc); + me = &(mode_lib->me); + v = &(mode_lib->vars); + num_planes = dml_wm_e2e_to_wm(mode_lib, e2e, num_pipes, v->planes); + + //instantiating variables to zero + v->MacroTileBlockWidthC = 0; + v->SwathWidthGranularityC = 0; + + v->DCFCLKPerState[5] = 0; + v->DCFCLKPerState[4] = 0; + v->DCFCLKPerState[3] = 0; + v->DCFCLKPerState[2] = 0; + v->DCFCLKPerState[1] = 0; + v->DCFCLKPerState[0] = 0; + + if (soc->vmin.dcfclk_mhz > 0) { + v->DCFCLKPerState[5] = soc->vmin.dcfclk_mhz; + v->DCFCLKPerState[4] = soc->vmin.dcfclk_mhz; + v->DCFCLKPerState[3] = soc->vmin.dcfclk_mhz; + v->DCFCLKPerState[2] = soc->vmin.dcfclk_mhz; + v->DCFCLKPerState[1] = soc->vmin.dcfclk_mhz; + v->DCFCLKPerState[0] = soc->vmin.dcfclk_mhz; + } + + if (soc->vmid.dcfclk_mhz > 0) { + v->DCFCLKPerState[5] = soc->vmid.dcfclk_mhz; + v->DCFCLKPerState[4] = soc->vmid.dcfclk_mhz; + v->DCFCLKPerState[3] = soc->vmid.dcfclk_mhz; + v->DCFCLKPerState[2] = soc->vmid.dcfclk_mhz; + v->DCFCLKPerState[1] = soc->vmid.dcfclk_mhz; + } + + if (soc->vnom.dcfclk_mhz > 0) { + v->DCFCLKPerState[5] = soc->vnom.dcfclk_mhz; + v->DCFCLKPerState[4] = soc->vnom.dcfclk_mhz; + v->DCFCLKPerState[3] = soc->vnom.dcfclk_mhz; + v->DCFCLKPerState[2] = soc->vnom.dcfclk_mhz; + } + + if (soc->vmax.dcfclk_mhz > 0) { + v->DCFCLKPerState[5] = soc->vmax.dcfclk_mhz; + v->DCFCLKPerState[4] = soc->vmax.dcfclk_mhz; + v->DCFCLKPerState[3] = soc->vmax.dcfclk_mhz; + } + + v->FabricAndDRAMBandwidthPerState[5] = 0; + v->FabricAndDRAMBandwidthPerState[4] = 0; + v->FabricAndDRAMBandwidthPerState[3] = 0; + v->FabricAndDRAMBandwidthPerState[2] = 0; + v->FabricAndDRAMBandwidthPerState[1] = 0; + v->FabricAndDRAMBandwidthPerState[0] = 0; + + if (soc->vmin.dram_bw_per_chan_gbps > 0) { + v->FabricAndDRAMBandwidthPerState[5] = soc->vmin.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[4] = soc->vmin.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[3] = soc->vmin.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[2] = soc->vmin.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[1] = soc->vmin.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[0] = soc->vmin.dram_bw_per_chan_gbps; + } + + if (soc->vmid.dram_bw_per_chan_gbps > 0) { + v->FabricAndDRAMBandwidthPerState[5] = soc->vmid.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[4] = soc->vmid.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[3] = soc->vmid.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[2] = soc->vmid.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[1] = soc->vmid.dram_bw_per_chan_gbps; + } + + if (soc->vnom.dram_bw_per_chan_gbps > 0) { + v->FabricAndDRAMBandwidthPerState[5] = soc->vnom.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[4] = soc->vnom.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[3] = soc->vnom.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[2] = soc->vnom.dram_bw_per_chan_gbps; + } + + if (soc->vmax.dram_bw_per_chan_gbps > 0) { + v->FabricAndDRAMBandwidthPerState[5] = soc->vmax.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[4] = soc->vmax.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[3] = soc->vmax.dram_bw_per_chan_gbps; + } + + v->PHYCLKPerState[5] = 0; + v->PHYCLKPerState[4] = 0; + v->PHYCLKPerState[3] = 0; + v->PHYCLKPerState[2] = 0; + v->PHYCLKPerState[1] = 0; + v->PHYCLKPerState[0] = 0; + + if (soc->vmin.phyclk_mhz > 0) { + v->PHYCLKPerState[5] = soc->vmin.phyclk_mhz; + v->PHYCLKPerState[4] = soc->vmin.phyclk_mhz; + v->PHYCLKPerState[3] = soc->vmin.phyclk_mhz; + v->PHYCLKPerState[2] = soc->vmin.phyclk_mhz; + v->PHYCLKPerState[1] = soc->vmin.phyclk_mhz; + v->PHYCLKPerState[0] = soc->vmin.phyclk_mhz; + } + + if (soc->vmid.phyclk_mhz > 0) { + v->PHYCLKPerState[5] = soc->vmid.phyclk_mhz; + v->PHYCLKPerState[4] = soc->vmid.phyclk_mhz; + v->PHYCLKPerState[3] = soc->vmid.phyclk_mhz; + v->PHYCLKPerState[2] = soc->vmid.phyclk_mhz; + v->PHYCLKPerState[1] = soc->vmid.phyclk_mhz; + } + + if (soc->vnom.phyclk_mhz > 0) { + v->PHYCLKPerState[5] = soc->vnom.phyclk_mhz; + v->PHYCLKPerState[4] = soc->vnom.phyclk_mhz; + v->PHYCLKPerState[3] = soc->vnom.phyclk_mhz; + v->PHYCLKPerState[2] = soc->vnom.phyclk_mhz; + } + + if (soc->vmax.phyclk_mhz > 0) { + v->PHYCLKPerState[5] = soc->vmax.phyclk_mhz; + v->PHYCLKPerState[4] = soc->vmax.phyclk_mhz; + v->PHYCLKPerState[3] = soc->vmax.phyclk_mhz; + } + + v->MaxDispclk[5] = 0; + v->MaxDispclk[4] = 0; + v->MaxDispclk[3] = 0; + v->MaxDispclk[2] = 0; + v->MaxDispclk[1] = 0; + v->MaxDispclk[0] = 0; + + if (soc->vmin.dispclk_mhz > 0) { + v->MaxDispclk[5] = soc->vmin.dispclk_mhz; + v->MaxDispclk[4] = soc->vmin.dispclk_mhz; + v->MaxDispclk[3] = soc->vmin.dispclk_mhz; + v->MaxDispclk[2] = soc->vmin.dispclk_mhz; + v->MaxDispclk[1] = soc->vmin.dispclk_mhz; + v->MaxDispclk[0] = soc->vmin.dispclk_mhz; + } + + if (soc->vmid.dispclk_mhz > 0) { + v->MaxDispclk[5] = soc->vmid.dispclk_mhz; + v->MaxDispclk[4] = soc->vmid.dispclk_mhz; + v->MaxDispclk[3] = soc->vmid.dispclk_mhz; + v->MaxDispclk[2] = soc->vmid.dispclk_mhz; + v->MaxDispclk[1] = soc->vmid.dispclk_mhz; + } + + if (soc->vnom.dispclk_mhz > 0) { + v->MaxDispclk[5] = soc->vnom.dispclk_mhz; + v->MaxDispclk[4] = soc->vnom.dispclk_mhz; + v->MaxDispclk[3] = soc->vnom.dispclk_mhz; + v->MaxDispclk[2] = soc->vnom.dispclk_mhz; + } + + if (soc->vmax.dispclk_mhz > 0) { + v->MaxDispclk[5] = soc->vmax.dispclk_mhz; + v->MaxDispclk[4] = soc->vmax.dispclk_mhz; + v->MaxDispclk[3] = soc->vmax.dispclk_mhz; + } + + v->MaxDppclk[5] = 0; + v->MaxDppclk[4] = 0; + v->MaxDppclk[3] = 0; + v->MaxDppclk[2] = 0; + v->MaxDppclk[1] = 0; + v->MaxDppclk[0] = 0; + + if (soc->vmin.dppclk_mhz > 0) { + v->MaxDppclk[5] = soc->vmin.dppclk_mhz; + v->MaxDppclk[4] = soc->vmin.dppclk_mhz; + v->MaxDppclk[3] = soc->vmin.dppclk_mhz; + v->MaxDppclk[2] = soc->vmin.dppclk_mhz; + v->MaxDppclk[1] = soc->vmin.dppclk_mhz; + v->MaxDppclk[0] = soc->vmin.dppclk_mhz; + } + + if (soc->vmid.dppclk_mhz > 0) { + v->MaxDppclk[5] = soc->vmid.dppclk_mhz; + v->MaxDppclk[4] = soc->vmid.dppclk_mhz; + v->MaxDppclk[3] = soc->vmid.dppclk_mhz; + v->MaxDppclk[2] = soc->vmid.dppclk_mhz; + v->MaxDppclk[1] = soc->vmid.dppclk_mhz; + } + + if (soc->vnom.dppclk_mhz > 0) { + v->MaxDppclk[5] = soc->vnom.dppclk_mhz; + v->MaxDppclk[4] = soc->vnom.dppclk_mhz; + v->MaxDppclk[3] = soc->vnom.dppclk_mhz; + v->MaxDppclk[2] = soc->vnom.dppclk_mhz; + } + + if (soc->vmax.dppclk_mhz > 0) { + v->MaxDppclk[5] = soc->vmax.dppclk_mhz; + v->MaxDppclk[4] = soc->vmax.dppclk_mhz; + v->MaxDppclk[3] = soc->vmax.dppclk_mhz; + } + + if (me->voltage_override == dm_vmax) { + v->VoltageOverrideLevel = NumberOfStates - 1; + } else if (me->voltage_override == dm_vnom) { + v->VoltageOverrideLevel = NumberOfStates - 2; + } else if (me->voltage_override == dm_vmid) { + v->VoltageOverrideLevel = NumberOfStates - 3; + } else { + v->VoltageOverrideLevel = 0; + } + + // Scale Ratio Support Check + + v->ScaleRatioSupport = 1; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = + e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; + struct _vcs_dpi_scaler_taps_st scale_taps = + e2e[v->planes[k].e2e_index].pipe.scale_taps; + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + + if (scale_ratio_depth.hscl_ratio > ip->max_hscl_ratio + || scale_ratio_depth.vscl_ratio > ip->max_vscl_ratio + || scale_ratio_depth.hscl_ratio > scale_taps.htaps + || scale_ratio_depth.vscl_ratio > scale_taps.vtaps + || (src.source_format != dm_444_64 && src.source_format != dm_444_32 + && src.source_format != dm_444_16 + && ((scale_ratio_depth.hscl_ratio / 2 + > scale_taps.htaps_c) + || (scale_ratio_depth.vscl_ratio / 2 + > scale_taps.vtaps_c)))) + + { + v->ScaleRatioSupport = 0; + } + } + + // Source Format, Pixel Format and Scan Support Check + + v->SourceFormatPixelAndScanSupport = 1; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + + if ((src.sw_mode == dm_sw_linear && src.source_scan != dm_horz) + || ((src.sw_mode == dm_sw_4kb_d || src.sw_mode == dm_sw_4kb_d_x + || src.sw_mode == dm_sw_64kb_d + || src.sw_mode == dm_sw_64kb_d_t + || src.sw_mode == dm_sw_64kb_d_x + || src.sw_mode == dm_sw_var_d + || src.sw_mode == dm_sw_var_d_x) + && (src.source_format != dm_444_64))) { + v->SourceFormatPixelAndScanSupport = 0; + } + } + + // Bandwidth Support Check + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + + if (src.source_scan == dm_horz) { + v->SwathWidthYSingleDPP[k] = src.viewport_width; + } else { + v->SwathWidthYSingleDPP[k] = src.viewport_height; + } + + if (src.source_format == dm_444_64) { + v->BytePerPixelInDETY[k] = 8; + v->BytePerPixelInDETC[k] = 0; + } else if (src.source_format == dm_444_32) { + v->BytePerPixelInDETY[k] = 4; + v->BytePerPixelInDETC[k] = 0; + } else if (src.source_format == dm_444_16) { + v->BytePerPixelInDETY[k] = 2; + v->BytePerPixelInDETC[k] = 0; + } else if (src.source_format == dm_420_8) { + v->BytePerPixelInDETY[k] = 1; + v->BytePerPixelInDETC[k] = 2; + } else { + v->BytePerPixelInDETY[k] = 4.00 / 3.00; + v->BytePerPixelInDETC[k] = 8.00 / 3.00; + } + } + + v->TotalReadBandwidthConsumedGBytePerSecond = 0; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = + e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; + + v->ReadBandwidth[k] = + v->SwathWidthYSingleDPP[k] + * (dml_ceil_ex(v->BytePerPixelInDETY[k], 1) + * scale_ratio_depth.vscl_ratio + + (dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) / 2) + * (scale_ratio_depth.vscl_ratio + / 2)) + / (dest.htotal / dest.pixel_rate_mhz); + + if (src.dcc == 1) { + v->ReadBandwidth[k] = v->ReadBandwidth[k] * (1 + 1 / 256); + } + + if (ip->pte_enable == 1 && src.source_scan != dm_horz + && (src.sw_mode == dm_sw_4kb_s || src.sw_mode == dm_sw_4kb_s_x + || src.sw_mode == dm_sw_4kb_d + || src.sw_mode == dm_sw_4kb_d_x)) { + v->ReadBandwidth[k] = v->ReadBandwidth[k] * (1 + 1 / 64); + } else if (ip->pte_enable == 1 && src.source_scan == dm_horz + && (src.source_format == dm_444_64 || src.source_format == dm_444_32) + && (src.sw_mode == dm_sw_64kb_s || src.sw_mode == dm_sw_64kb_s_t + || src.sw_mode == dm_sw_64kb_s_x + || src.sw_mode == dm_sw_64kb_d + || src.sw_mode == dm_sw_64kb_d_t + || src.sw_mode == dm_sw_64kb_d_x)) { + v->ReadBandwidth[k] = v->ReadBandwidth[k] * (1 + 1 / 256); + } else if (ip->pte_enable == 1) { + v->ReadBandwidth[k] = v->ReadBandwidth[k] * (1 + 1 / 512); + } + + v->TotalReadBandwidthConsumedGBytePerSecond = + v->TotalReadBandwidthConsumedGBytePerSecond + + v->ReadBandwidth[k] / 1000; + } + + v->TotalWriteBandwidthConsumedGBytePerSecond = 0; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + struct _vcs_dpi_display_output_params_st dout = e2e[v->planes[k].e2e_index].dout; + + if (dout.output_type == dm_wb && dout.output_format == dm_444) { + v->WriteBandwidth[k] = dest.recout_width + / (dest.htotal / dest.pixel_rate_mhz) * 4; + } else if (dout.output_type == dm_wb) { + v->WriteBandwidth[k] = dest.recout_width + / (dest.htotal / dest.pixel_rate_mhz) * 1.5; + } else { + v->WriteBandwidth[k] = 0; + } + + v->TotalWriteBandwidthConsumedGBytePerSecond = + v->TotalWriteBandwidthConsumedGBytePerSecond + + v->WriteBandwidth[k] / 1000; + } + + v->TotalBandwidthConsumedGBytePerSecond = v->TotalReadBandwidthConsumedGBytePerSecond + + v->TotalWriteBandwidthConsumedGBytePerSecond; + + v->DCCEnabledInAnyPlane = 0; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + + if (src.dcc == 1) { + v->DCCEnabledInAnyPlane = 1; + } + } + + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + v->ReturnBWToDCNPerState = dml_min( + soc->return_bus_width_bytes * v->DCFCLKPerState[i], + v->FabricAndDRAMBandwidthPerState[i] * 1000 + * soc->ideal_dram_bw_after_urgent_percent / 100); + + v->ReturnBWPerState[i] = v->ReturnBWToDCNPerState; + + if (v->DCCEnabledInAnyPlane == 1 + && v->ReturnBWToDCNPerState + > (v->DCFCLKPerState[i] + * soc->return_bus_width_bytes / 4)) { + v->ReturnBWPerState[i] = + dml_min( + v->ReturnBWPerState[i], + v->ReturnBWToDCNPerState * 4 + * (1 + - soc->urgent_latency_us + / ((ip->rob_buffer_size_kbytes + - ip->pixel_chunk_size_kbytes) + * 1024 + / (v->ReturnBWToDCNPerState + - v->DCFCLKPerState[i] + * soc->return_bus_width_bytes + / 4) + + soc->urgent_latency_us))); + } + + v->CriticalPoint = 2 * soc->return_bus_width_bytes * v->DCFCLKPerState[i] + * soc->urgent_latency_us + / (v->ReturnBWToDCNPerState * soc->urgent_latency_us + + (ip->rob_buffer_size_kbytes + - ip->pixel_chunk_size_kbytes) + * 1024); + + if (v->DCCEnabledInAnyPlane == 1 && v->CriticalPoint > 1 && v->CriticalPoint < 4) { + v->ReturnBWPerState[i] = + dml_min( + v->ReturnBWPerState[i], + 4 * v->ReturnBWToDCNPerState + * (ip->rob_buffer_size_kbytes + - ip->pixel_chunk_size_kbytes) + * 1024 + * soc->return_bus_width_bytes + * v->DCFCLKPerState[i] + * soc->urgent_latency_us + / dml_pow( + (v->ReturnBWToDCNPerState + * soc->urgent_latency_us + + (ip->rob_buffer_size_kbytes + - ip->pixel_chunk_size_kbytes) + * 1024), + 2)); + } + + v->ReturnBWToDCNPerState = dml_min( + soc->return_bus_width_bytes * v->DCFCLKPerState[i], + v->FabricAndDRAMBandwidthPerState[i] * 1000); + + if (v->DCCEnabledInAnyPlane == 1 + && v->ReturnBWToDCNPerState + > (v->DCFCLKPerState[i] + * soc->return_bus_width_bytes / 4)) { + v->ReturnBWPerState[i] = + dml_min( + v->ReturnBWPerState[i], + v->ReturnBWToDCNPerState * 4 + * (1 + - soc->urgent_latency_us + / ((ip->rob_buffer_size_kbytes + - ip->pixel_chunk_size_kbytes) + * 1024 + / (v->ReturnBWToDCNPerState + - v->DCFCLKPerState[i] + * soc->return_bus_width_bytes + / 4) + + soc->urgent_latency_us))); + } + + v->CriticalPoint = 2 * soc->return_bus_width_bytes * v->DCFCLKPerState[i] + * soc->urgent_latency_us + / (v->ReturnBWToDCNPerState * soc->urgent_latency_us + + (ip->rob_buffer_size_kbytes + - ip->pixel_chunk_size_kbytes) + * 1024); + + if (v->DCCEnabledInAnyPlane == 1 && v->CriticalPoint > 1 && v->CriticalPoint < 4) { + v->ReturnBWPerState[i] = + dml_min( + v->ReturnBWPerState[i], + 4 * v->ReturnBWToDCNPerState + * (ip->rob_buffer_size_kbytes + - ip->pixel_chunk_size_kbytes) + * 1024 + * soc->return_bus_width_bytes + * v->DCFCLKPerState[i] + * soc->urgent_latency_us + / dml_pow( + (v->ReturnBWToDCNPerState + * soc->urgent_latency_us + + (ip->rob_buffer_size_kbytes + - ip->pixel_chunk_size_kbytes) + * 1024), + 2)); + } + } + + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + if ((v->TotalReadBandwidthConsumedGBytePerSecond * 1000 <= v->ReturnBWPerState[i]) + && (v->TotalBandwidthConsumedGBytePerSecond * 1000 + <= v->FabricAndDRAMBandwidthPerState[i] * 1000 + * soc->ideal_dram_bw_after_urgent_percent + / 100)) { + v->BandwidthSupport[i] = 1; + } else { + v->BandwidthSupport[i] = 0; + } + } + + // Writeback Latency support check + + v->WritebackLatencySupport = 1; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + struct _vcs_dpi_display_output_params_st dout = e2e[v->planes[k].e2e_index].dout; + + if (dout.output_type == dm_wb && dout.output_format == dm_444 + && (dest.recout_width / (dest.htotal / dest.pixel_rate_mhz) * 4) + > ((ip->writeback_luma_buffer_size_kbytes + + ip->writeback_chroma_buffer_size_kbytes) + * 1024 / soc->writeback_latency_us)) { + v->WritebackLatencySupport = 0; + } else if (dout.output_type == dm_wb + && (dest.recout_width / (dest.htotal / dest.pixel_rate_mhz)) + > (dml_min( + ip->writeback_luma_buffer_size_kbytes, + 2 + * ip->writeback_chroma_buffer_size_kbytes) + * 1024 / soc->writeback_latency_us)) { + v->WritebackLatencySupport = 0; + } + } + + // Re-ordering Buffer Support Check + + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + v->UrgentRoundTripAndOutOfOrderLatencyPerState[i] = + (soc->round_trip_ping_latency_dcfclk_cycles + 32) + / v->DCFCLKPerState[i] + + soc->urgent_out_of_order_return_per_channel_bytes + * soc->num_chans + / v->ReturnBWPerState[i]; + + if ((ip->rob_buffer_size_kbytes - ip->pixel_chunk_size_kbytes) * 1024 + / v->ReturnBWPerState[i] + > v->UrgentRoundTripAndOutOfOrderLatencyPerState[i]) { + v->ROBSupport[i] = 1; + } else { + v->ROBSupport[i] = 0; + } + } + + // Display IO Support Check + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + struct _vcs_dpi_display_output_params_st dout = e2e[v->planes[k].e2e_index].dout; + + if (dout.output_format == dm_420) { + v->RequiredOutputBW = dest.pixel_rate_mhz * 3 / 2; + } else { + v->RequiredOutputBW = dest.pixel_rate_mhz * 3; + } + + if (dout.output_type == dm_hdmi) { + v->RequiredPHYCLK[k] = v->RequiredOutputBW / 3; + } else if (dout.output_type == dm_dp) { + v->RequiredPHYCLK[k] = v->RequiredOutputBW / 4; + } else { + v->RequiredPHYCLK[k] = 0; + } + } + + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + v->DIOSupport[i] = 1; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_output_params_st dout = + e2e[v->planes[k].e2e_index].dout; + + if ((v->RequiredPHYCLK[k] > v->PHYCLKPerState[i]) + || (dout.output_type == dm_hdmi + && v->RequiredPHYCLK[k] > 600)) { + v->DIOSupport[i] = 0; + } + } + } + + // Total Available Writeback Support Check + + v->TotalNumberOfActiveWriteback = 0; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_output_params_st dout = e2e[v->planes[k].e2e_index].dout; + + if (dout.output_type == dm_wb) { + v->TotalNumberOfActiveWriteback = v->TotalNumberOfActiveWriteback + 1; + } + } + + if (v->TotalNumberOfActiveWriteback <= ip->max_num_wb) { + v->TotalAvailableWritebackSupport = 1; + } else { + v->TotalAvailableWritebackSupport = 0; + } + + // Maximum DISPCLK/DPPCLK Support check + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = + e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; + struct _vcs_dpi_scaler_taps_st scale_taps = + e2e[v->planes[k].e2e_index].pipe.scale_taps; + + if (scale_ratio_depth.hscl_ratio > 1) { + v->PSCL_FACTOR[k] = dml_min( + ip->max_dchub_pscl_bw_pix_per_clk, + ip->max_pscl_lb_bw_pix_per_clk + * scale_ratio_depth.hscl_ratio + / dml_ceil_ex(scale_taps.htaps / 6, 1)); + } else { + v->PSCL_FACTOR[k] = dml_min( + ip->max_dchub_pscl_bw_pix_per_clk, + ip->max_pscl_lb_bw_pix_per_clk); + } + + if (v->BytePerPixelInDETC[k] == 0) { + v->PSCL_FACTOR_CHROMA[k] = 0; + v->MinDPPCLKUsingSingleDPP[k] = + dest.pixel_rate_mhz + * dml_max( + scale_taps.vtaps / 6 + * dml_min( + 1, + scale_ratio_depth.hscl_ratio), + dml_max( + scale_ratio_depth.hscl_ratio + * scale_ratio_depth.vscl_ratio + / v->PSCL_FACTOR[k], + 1)); + + } else { + if (scale_ratio_depth.hscl_ratio / 2 > 1) { + v->PSCL_FACTOR_CHROMA[k] = dml_min( + ip->max_dchub_pscl_bw_pix_per_clk, + ip->max_pscl_lb_bw_pix_per_clk + * scale_ratio_depth.hscl_ratio / 2 + / dml_ceil_ex( + scale_taps.htaps_c + / 6, + 1)); + } else { + v->PSCL_FACTOR_CHROMA[k] = dml_min( + ip->max_dchub_pscl_bw_pix_per_clk, + ip->max_pscl_lb_bw_pix_per_clk); + } + v->MinDPPCLKUsingSingleDPP[k] = + dest.pixel_rate_mhz + * dml_max( + dml_max( + scale_taps.vtaps + / 6 + * dml_min( + 1, + scale_ratio_depth.hscl_ratio), + scale_ratio_depth.hscl_ratio + * scale_ratio_depth.vscl_ratio + / v->PSCL_FACTOR[k]), + dml_max( + dml_max( + scale_taps.vtaps_c + / 6 + * dml_min( + 1, + scale_ratio_depth.hscl_ratio + / 2), + scale_ratio_depth.hscl_ratio + * scale_ratio_depth.vscl_ratio + / 4 + / v->PSCL_FACTOR_CHROMA[k]), + 1)); + + } + } + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = + e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; + struct _vcs_dpi_scaler_taps_st scale_taps = + e2e[v->planes[k].e2e_index].pipe.scale_taps; + + if (src.source_format == dm_444_64 || src.source_format == dm_444_32 + || src.source_format == dm_444_16) { + if (src.sw_mode == dm_sw_linear) { + v->Read256BlockHeightY[k] = 1; + } else if (src.source_format == dm_444_64) { + v->Read256BlockHeightY[k] = 4; + } else { + v->Read256BlockHeightY[k] = 8; + } + + v->Read256BlockWidthY[k] = 256 / dml_ceil_ex(v->BytePerPixelInDETY[k], 1) + / v->Read256BlockHeightY[k]; + v->Read256BlockHeightC[k] = 0; + v->Read256BlockWidthC[k] = 0; + } else { + if (src.sw_mode == dm_sw_linear) { + v->Read256BlockHeightY[k] = 1; + v->Read256BlockHeightC[k] = 1; + } else if (src.source_format == dm_420_8) { + v->Read256BlockHeightY[k] = 16; + v->Read256BlockHeightC[k] = 8; + } else { + v->Read256BlockHeightY[k] = 8; + v->Read256BlockHeightC[k] = 8; + } + + v->Read256BlockWidthY[k] = 256 / dml_ceil_ex(v->BytePerPixelInDETY[k], 1) + / v->Read256BlockHeightY[k]; + v->Read256BlockWidthC[k] = 256 / dml_ceil_ex(v->BytePerPixelInDETC[k], 2) + / v->Read256BlockHeightC[k]; + } + + if (src.source_scan == dm_horz) { + v->MaxSwathHeightY[k] = v->Read256BlockHeightY[k]; + v->MaxSwathHeightC[k] = v->Read256BlockHeightC[k]; + } else { + v->MaxSwathHeightY[k] = v->Read256BlockWidthY[k]; + v->MaxSwathHeightC[k] = v->Read256BlockWidthC[k]; + } + + if (src.source_format == dm_444_64 || src.source_format == dm_444_32 + || src.source_format == dm_444_16) { + if (src.sw_mode == dm_sw_linear + || (src.source_format == dm_444_64 + && (src.sw_mode == dm_sw_4kb_s + || src.sw_mode + == dm_sw_4kb_s_x + || src.sw_mode + == dm_sw_64kb_s + || src.sw_mode + == dm_sw_64kb_s_t + || src.sw_mode + == dm_sw_64kb_s_x + || src.sw_mode + == dm_sw_var_s + || src.sw_mode + == dm_sw_var_s_x) + && src.source_scan == dm_horz)) { + v->MinSwathHeightY[k] = v->MaxSwathHeightY[k]; + } else { + v->MinSwathHeightY[k] = v->MaxSwathHeightY[k] / 2; + } + v->MinSwathHeightC[k] = v->MaxSwathHeightC[k]; + } else { + if (src.sw_mode == dm_sw_linear) { + v->MinSwathHeightY[k] = v->MaxSwathHeightY[k]; + v->MinSwathHeightC[k] = v->MaxSwathHeightC[k]; + } else if (src.source_format == dm_420_8 && src.source_scan == dm_horz) { + v->MinSwathHeightY[k] = v->MaxSwathHeightY[k] / 2; + if (ip->bug_forcing_LC_req_same_size_fixed == 1) { + v->MinSwathHeightC[k] = v->MaxSwathHeightC[k]; + } else { + v->MinSwathHeightC[k] = v->MaxSwathHeightC[k] / 2; + } + } else if (src.source_format == dm_420_10 && src.source_scan == dm_horz) { + v->MinSwathHeightC[k] = v->MaxSwathHeightC[k] / 2; + if (ip->bug_forcing_LC_req_same_size_fixed == 1) { + v->MinSwathHeightY[k] = v->MaxSwathHeightY[k]; + } else { + v->MinSwathHeightY[k] = v->MaxSwathHeightY[k] / 2; + } + } else { + v->MinSwathHeightY[k] = v->MaxSwathHeightY[k]; + v->MinSwathHeightC[k] = v->MaxSwathHeightC[k]; + } + } + + if (src.sw_mode == dm_sw_linear) { + v->MaximumSwathWidth = 8192; + } else { + v->MaximumSwathWidth = 5120; + } + + v->NumberOfDPPRequiredForDETSize = + dml_ceil_ex( + v->SwathWidthYSingleDPP[k] + / dml_min( + v->MaximumSwathWidth, + ip->det_buffer_size_kbytes + * 1024 + / 2 + / (v->BytePerPixelInDETY[k] + * v->MinSwathHeightY[k] + + v->BytePerPixelInDETC[k] + / 2 + * v->MinSwathHeightC[k])), + 1); + + if (v->BytePerPixelInDETC[k] == 0) { + v->NumberOfDPPRequiredForLBSize = + dml_ceil_ex( + (scale_taps.vtaps + + dml_max( + dml_ceil_ex( + scale_ratio_depth.vscl_ratio, + 1) + - 2, + 0)) + * v->SwathWidthYSingleDPP[k] + / dml_max( + scale_ratio_depth.hscl_ratio, + 1) + * scale_ratio_depth.lb_depth + / ip->line_buffer_size_bits, + 1); + } else { + v->NumberOfDPPRequiredForLBSize = + dml_max( + dml_ceil_ex( + (scale_taps.vtaps + + dml_max( + dml_ceil_ex( + scale_ratio_depth.vscl_ratio, + 1) + - 2, + 0)) + * v->SwathWidthYSingleDPP[k] + / dml_max( + scale_ratio_depth.hscl_ratio, + 1) + * scale_ratio_depth.lb_depth + / ip->line_buffer_size_bits, + 1), + dml_ceil_ex( + (scale_taps.vtaps_c + + dml_max( + dml_ceil_ex( + scale_ratio_depth.vscl_ratio + / 2, + 1) + - 2, + 0)) + * v->SwathWidthYSingleDPP[k] + / 2 + / dml_max( + scale_ratio_depth.hscl_ratio + / 2, + 1) + * scale_ratio_depth.lb_depth + / ip->line_buffer_size_bits, + 1)); + } + + v->NumberOfDPPRequiredForDETAndLBSize[k] = dml_max( + v->NumberOfDPPRequiredForDETSize, + v->NumberOfDPPRequiredForLBSize); + + } + + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + for (j = 0; j < 2; j++) { + v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] = 0; + v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = 0; + v->DISPCLK_DPPCLK_Support[j * NumberOfStatesPlusTwo + i] = 1; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + v->MinDispclkUsingSingleDPP = dml_max( + dest.pixel_rate_mhz, + v->MinDPPCLKUsingSingleDPP[k] * (j + 1)) + * (1 + soc->downspread_percent / 100); + v->MinDispclkUsingDualDPP = dml_max( + dest.pixel_rate_mhz, + v->MinDPPCLKUsingSingleDPP[k] / 2 * (j + 1)) + * (1 + soc->downspread_percent / 100); + + if (i < NumberOfStates) { + v->MinDispclkUsingSingleDPP = + v->MinDispclkUsingSingleDPP + * (1 + + ip->dispclk_ramp_margin_percent + / 100); + v->MinDispclkUsingDualDPP = + v->MinDispclkUsingDualDPP + * (1 + + ip->dispclk_ramp_margin_percent + / 100); + } + + if (v->MinDispclkUsingSingleDPP + <= dml_min( + v->MaxDispclk[i], + (j + 1) * v->MaxDppclk[i]) + && v->NumberOfDPPRequiredForDETAndLBSize[k] <= 1) { + v->NoOfDPP[ijk] = 1; + v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = dml_max( + v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + + i], + v->MinDispclkUsingSingleDPP); + } else if (v->MinDispclkUsingDualDPP + <= dml_min( + v->MaxDispclk[i], + (j + 1) * v->MaxDppclk[i])) { + v->NoOfDPP[ijk] = 2; + v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = dml_max( + v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + + i], + v->MinDispclkUsingDualDPP); + } else { + v->NoOfDPP[ijk] = 2; + v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = dml_max( + v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + + i], + v->MinDispclkUsingDualDPP); + v->DISPCLK_DPPCLK_Support[j * NumberOfStatesPlusTwo + i] = + 0; + } + + v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] = + v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + + i] + v->NoOfDPP[ijk]; + } + + if (v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] + > ip->max_num_dpp) { + v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] = 0; + v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = 0; + v->DISPCLK_DPPCLK_Support[j * NumberOfStatesPlusTwo + i] = 1; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + ijk = k * 2 * NumberOfStatesPlusTwo + + j * NumberOfStatesPlusTwo + i; + + v->MinDispclkUsingSingleDPP = dml_max( + dest.pixel_rate_mhz, + v->MinDPPCLKUsingSingleDPP[k] * (j + 1)) + * (1 + soc->downspread_percent / 100); + v->MinDispclkUsingDualDPP = dml_max( + dest.pixel_rate_mhz, + v->MinDPPCLKUsingSingleDPP[k] / 2 * (j + 1)) + * (1 + soc->downspread_percent / 100); + + if (i < NumberOfStates) { + v->MinDispclkUsingSingleDPP = + v->MinDispclkUsingSingleDPP + * (1 + + ip->dispclk_ramp_margin_percent + / 100); + v->MinDispclkUsingDualDPP = + v->MinDispclkUsingDualDPP + * (1 + + ip->dispclk_ramp_margin_percent + / 100); + } + + if (v->NumberOfDPPRequiredForDETAndLBSize[k] <= 1) { + v->NoOfDPP[ijk] = 1; + v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = + dml_max( + v->RequiredDISPCLK[j + * NumberOfStatesPlusTwo + + i], + v->MinDispclkUsingSingleDPP); + if (v->MinDispclkUsingSingleDPP + > dml_min( + v->MaxDispclk[i], + (j + 1) + * v->MaxDppclk[i])) { + v->DISPCLK_DPPCLK_Support[j + * NumberOfStatesPlusTwo + i] = + 0; + } + } else { + v->NoOfDPP[ijk] = 2; + v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = + dml_max( + v->RequiredDISPCLK[j + * NumberOfStatesPlusTwo + + i], + v->MinDispclkUsingDualDPP); + if (v->MinDispclkUsingDualDPP + > dml_min( + v->MaxDispclk[i], + (j + 1) + * v->MaxDppclk[i])) { + v->DISPCLK_DPPCLK_Support[j + * NumberOfStatesPlusTwo + i] = + 0; + } + } + v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] = + v->TotalNumberOfActiveDPP[j + * NumberOfStatesPlusTwo + i] + + v->NoOfDPP[ijk]; + } + } + } + } + + // Viewport Size Check + + v->ViewportSizeSupport = 1; + + for (k = 0; k < num_planes; k++) { + if (v->NumberOfDPPRequiredForDETAndLBSize[k] > 2) { + v->ViewportSizeSupport = 0; + } + } + + // Total Available Pipes Support Check + + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + for (j = 0; j < 2; j++) { + if (v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] + <= ip->max_num_dpp) { + v->TotalAvailablePipesSupport[j * NumberOfStatesPlusTwo + i] = 1; + } else { + v->TotalAvailablePipesSupport[j * NumberOfStatesPlusTwo + i] = 0; + } + } + } + + // Urgent Latency Support Check + + for (j = 0; j < 2; j++) { + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + ij = j * NumberOfStatesPlusTwo + i; + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = + e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; + struct _vcs_dpi_scaler_taps_st scale_taps = + e2e[v->planes[k].e2e_index].pipe.scale_taps; + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + v->SwathWidthYPerState[ijk] = v->SwathWidthYSingleDPP[k] + / v->NoOfDPP[ijk]; + + v->SwathWidthGranularityY = 256 + / dml_ceil_ex(v->BytePerPixelInDETY[k], 1) + / v->MaxSwathHeightY[k]; + v->RoundedUpMaxSwathSizeBytesY = (dml_ceil_ex( + v->SwathWidthYPerState[ijk] - 1, + v->SwathWidthGranularityY) + + v->SwathWidthGranularityY) + * v->BytePerPixelInDETY[k] * v->MaxSwathHeightY[k]; + if (src.source_format == dm_420_10) { + v->RoundedUpMaxSwathSizeBytesY = dml_ceil_ex( + v->RoundedUpMaxSwathSizeBytesY, + 256) + 256; + } + if (v->MaxSwathHeightC[k] > 0) { + v->SwathWidthGranularityC = 256 + / dml_ceil_ex(v->BytePerPixelInDETC[k], 2) + / v->MaxSwathHeightC[k]; + } + v->RoundedUpMaxSwathSizeBytesC = (dml_ceil_ex( + v->SwathWidthYPerState[ijk] / 2 - 1, + v->SwathWidthGranularityC) + + v->SwathWidthGranularityC) + * v->BytePerPixelInDETC[k] * v->MaxSwathHeightC[k]; + if (src.source_format == dm_420_10) { + v->RoundedUpMaxSwathSizeBytesC = dml_ceil_ex( + v->RoundedUpMaxSwathSizeBytesC, + 256) + 256; + } + + if (v->RoundedUpMaxSwathSizeBytesY + v->RoundedUpMaxSwathSizeBytesC + <= ip->det_buffer_size_kbytes * 1024 / 2) { + v->SwathHeightYPerState[ijk] = v->MaxSwathHeightY[k]; + v->SwathHeightCPerState[ijk] = v->MaxSwathHeightC[k]; + } else { + v->SwathHeightYPerState[ijk] = v->MinSwathHeightY[k]; + v->SwathHeightCPerState[ijk] = v->MinSwathHeightC[k]; + } + + if (v->BytePerPixelInDETC[k] == 0) { + v->LinesInDETLuma = ip->det_buffer_size_kbytes * 1024 + / v->BytePerPixelInDETY[k] + / v->SwathWidthYPerState[ijk]; + + v->LinesInDETChroma = 0; + } else if (v->SwathHeightYPerState[ijk] + <= v->SwathHeightCPerState[ijk]) { + v->LinesInDETLuma = ip->det_buffer_size_kbytes * 1024 / 2 + / v->BytePerPixelInDETY[k] + / v->SwathWidthYPerState[ijk]; + v->LinesInDETChroma = ip->det_buffer_size_kbytes * 1024 / 2 + / v->BytePerPixelInDETC[k] + / (v->SwathWidthYPerState[ijk] / 2); + } else { + v->LinesInDETLuma = ip->det_buffer_size_kbytes * 1024 * 2 + / 3 / v->BytePerPixelInDETY[k] + / v->SwathWidthYPerState[ijk]; + v->LinesInDETChroma = ip->det_buffer_size_kbytes * 1024 / 3 + / v->BytePerPixelInDETY[k] + / (v->SwathWidthYPerState[ijk] / 2); + } + + v->EffectiveLBLatencyHidingSourceLinesLuma = + dml_min( + ip->max_line_buffer_lines, + dml_floor_ex( + ip->line_buffer_size_bits + / scale_ratio_depth.lb_depth + / (v->SwathWidthYPerState[ijk] + / dml_max( + scale_ratio_depth.hscl_ratio, + 1)), + 1)) + - (scale_taps.vtaps - 1); + + v->EffectiveLBLatencyHidingSourceLinesChroma = + dml_min( + ip->max_line_buffer_lines, + dml_floor_ex( + ip->line_buffer_size_bits + / scale_ratio_depth.lb_depth + / (v->SwathWidthYPerState[ijk] + / 2 + / dml_max( + scale_ratio_depth.hscl_ratio + / 2, + 1)), + 1)) + - (scale_taps.vtaps_c - 1); + + v->EffectiveDETLBLinesLuma = + dml_floor_ex( + v->LinesInDETLuma + + dml_min( + v->LinesInDETLuma + * v->RequiredDISPCLK[ij] + * v->BytePerPixelInDETY[k] + * v->PSCL_FACTOR[k] + / v->ReturnBWPerState[i], + v->EffectiveLBLatencyHidingSourceLinesLuma), + v->SwathHeightYPerState[ijk]); + + v->EffectiveDETLBLinesChroma = + dml_floor_ex( + v->LinesInDETChroma + + dml_min( + v->LinesInDETChroma + * v->RequiredDISPCLK[ij] + * v->BytePerPixelInDETC[k] + * v->PSCL_FACTOR_CHROMA[k] + / v->ReturnBWPerState[i], + v->EffectiveLBLatencyHidingSourceLinesChroma), + v->SwathHeightCPerState[ijk]); + + if (v->BytePerPixelInDETC[k] == 0) { + v->UrgentLatencySupportUsPerState[ijk] = + v->EffectiveDETLBLinesLuma + * (dest.htotal + / dest.pixel_rate_mhz) + / scale_ratio_depth.vscl_ratio + - v->EffectiveDETLBLinesLuma + * v->SwathWidthYPerState[ijk] + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + / (v->ReturnBWPerState[i] + / v->NoOfDPP[ijk]); + } else { + v->UrgentLatencySupportUsPerState[ijk] = + dml_min( + v->EffectiveDETLBLinesLuma + * (dest.htotal + / dest.pixel_rate_mhz) + / scale_ratio_depth.vscl_ratio + - v->EffectiveDETLBLinesLuma + * v->SwathWidthYPerState[ijk] + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + / (v->ReturnBWPerState[i] + / v->NoOfDPP[ijk]), + v->EffectiveDETLBLinesChroma + * (dest.htotal + / dest.pixel_rate_mhz) + / (scale_ratio_depth.vscl_ratio + / 2) + - v->EffectiveDETLBLinesChroma + * v->SwathWidthYPerState[ijk] + / 2 + * dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / (v->ReturnBWPerState[i] + / v->NoOfDPP[ijk])); + } + + } + } + } + + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + for (j = 0; j < 2; j++) { + ij = j * NumberOfStatesPlusTwo + i; + + v->UrgentLatencySupport[ij] = 1; + for (k = 0; k < num_planes; k++) { + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + if (v->UrgentLatencySupportUsPerState[ijk] + < soc->urgent_latency_us / 1) { + v->UrgentLatencySupport[ij] = 0; + } + } + } + } + + // Prefetch Check + + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + for (j = 0; j < 2; j++) { + ij = j * NumberOfStatesPlusTwo + i; + + v->TotalNumberOfDCCActiveDPP[ij] = 0; + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + if (src.dcc == 1) { + v->TotalNumberOfDCCActiveDPP[ij] = + v->TotalNumberOfDCCActiveDPP[ij] + + v->NoOfDPP[ijk]; + } + } + } + } + + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + for (j = 0; j < 2; j++) { + ij = j * NumberOfStatesPlusTwo + i; + + v->ProjectedDCFCLKDeepSleep = 8; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = + e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + v->ProjectedDCFCLKDeepSleep = dml_max( + v->ProjectedDCFCLKDeepSleep, + dest.pixel_rate_mhz / 16); + if (v->BytePerPixelInDETC[k] == 0) { + if (scale_ratio_depth.vscl_ratio <= 1) { + v->ProjectedDCFCLKDeepSleep = + dml_max( + v->ProjectedDCFCLKDeepSleep, + 1.1 + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + / 64 + * scale_ratio_depth.hscl_ratio + * dest.pixel_rate_mhz + / v->NoOfDPP[ijk]); + } else { + v->ProjectedDCFCLKDeepSleep = + dml_max( + v->ProjectedDCFCLKDeepSleep, + 1.1 + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + / 64 + * v->PSCL_FACTOR[k] + * v->RequiredDISPCLK[ij] + / (1 + + j)); + } + + } else { + if (scale_ratio_depth.vscl_ratio <= 1) { + v->ProjectedDCFCLKDeepSleep = + dml_max( + v->ProjectedDCFCLKDeepSleep, + 1.1 + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + / 32 + * scale_ratio_depth.hscl_ratio + * dest.pixel_rate_mhz + / v->NoOfDPP[ijk]); + } else { + v->ProjectedDCFCLKDeepSleep = + dml_max( + v->ProjectedDCFCLKDeepSleep, + 1.1 + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + / 32 + * v->PSCL_FACTOR[k] + * v->RequiredDISPCLK[ij] + / (1 + + j)); + } + if ((scale_ratio_depth.vscl_ratio / 2) <= 1) { + v->ProjectedDCFCLKDeepSleep = + dml_max( + v->ProjectedDCFCLKDeepSleep, + 1.1 + * dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / 32 + * scale_ratio_depth.hscl_ratio + / 2 + * dest.pixel_rate_mhz + / v->NoOfDPP[ijk]); + } else { + v->ProjectedDCFCLKDeepSleep = + dml_max( + v->ProjectedDCFCLKDeepSleep, + 1.1 + * dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / 32 + * v->PSCL_FACTOR_CHROMA[k] + * v->RequiredDISPCLK[ij] + / (1 + + j)); + } + + } + } + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = + e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; + struct _vcs_dpi_scaler_taps_st scale_taps = + e2e[v->planes[k].e2e_index].pipe.scale_taps; + struct _vcs_dpi_display_output_params_st dout = + e2e[v->planes[k].e2e_index].dout; + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + if (src.dcc == 1) { + v->MetaReqHeightY = 8 * v->Read256BlockHeightY[k]; + v->MetaReqWidthY = 64 * 256 + / dml_ceil_ex(v->BytePerPixelInDETY[k], 1) + / v->MetaReqHeightY; + v->MetaSurfaceWidthY = dml_ceil_ex( + src.viewport_width / v->NoOfDPP[ijk] - 1, + v->MetaReqWidthY) + v->MetaReqWidthY; + v->MetaSurfaceHeightY = dml_ceil_ex( + src.viewport_height - 1, + v->MetaReqHeightY) + v->MetaReqHeightY; + if (ip->pte_enable == 1) { + v->MetaPteBytesPerFrameY = + (dml_ceil_ex( + (v->MetaSurfaceWidthY + * v->MetaSurfaceHeightY + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + / 256.0 + - 4096) + / 8 + / 4096, + 1) + 1) * 64; + } else { + v->MetaPteBytesPerFrameY = 0; + } + if (src.source_scan == dm_horz) { + v->MetaRowBytesY = + v->MetaSurfaceWidthY + * v->MetaReqHeightY + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + / 256; + } else { + v->MetaRowBytesY = + v->MetaSurfaceHeightY + * v->MetaReqWidthY + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + / 256; + } + } else { + v->MetaPteBytesPerFrameY = 0; + v->MetaRowBytesY = 0; + } + + if (ip->pte_enable == 1) { + if (src.sw_mode == dm_sw_linear) { + v->MacroTileBlockSizeBytesY = 256; + v->MacroTileBlockHeightY = 1; + } else if (src.sw_mode == dm_sw_4kb_s + || src.sw_mode == dm_sw_4kb_s_x + || src.sw_mode == dm_sw_4kb_d + || src.sw_mode == dm_sw_4kb_d_x) { + v->MacroTileBlockSizeBytesY = 4096; + v->MacroTileBlockHeightY = 4 + * v->Read256BlockHeightY[k]; + } else if (src.sw_mode == dm_sw_64kb_s + || src.sw_mode == dm_sw_64kb_s_t + || src.sw_mode == dm_sw_64kb_s_x + || src.sw_mode == dm_sw_64kb_d + || src.sw_mode == dm_sw_64kb_d_t + || src.sw_mode == dm_sw_64kb_d_x) { + v->MacroTileBlockSizeBytesY = 64 * 1024; + v->MacroTileBlockHeightY = 16 + * v->Read256BlockHeightY[k]; + } else { + v->MacroTileBlockSizeBytesY = 256 * 1024; + v->MacroTileBlockHeightY = 32 + * v->Read256BlockHeightY[k]; + } + if (v->MacroTileBlockSizeBytesY <= 65536) { + v->DataPTEReqHeightY = v->MacroTileBlockHeightY; + } else { + v->DataPTEReqHeightY = 16 + * v->Read256BlockHeightY[k]; + } + v->DataPTEReqWidthY = 4096 + / dml_ceil_ex(v->BytePerPixelInDETY[k], 1) + / v->DataPTEReqHeightY * 8; + if (src.sw_mode == dm_sw_linear) { + v->DPTEBytesPerRowY = + 64 + * (dml_ceil_ex( + (src.viewport_width + / v->NoOfDPP[ijk] + * dml_min( + 128, + dml_pow( + 2, + dml_floor_ex( + dml_log( + ip->dpte_buffer_size_in_pte_reqs + * v->DataPTEReqWidthY + / (src.viewport_width + / v->NoOfDPP[ijk]), + 2), + 1))) + - 1) + / v->DataPTEReqWidthY, + 1) + + 1); + } else if (src.source_scan == dm_horz) { + v->DPTEBytesPerRowY = + 64 + * (dml_ceil_ex( + (src.viewport_width + / v->NoOfDPP[ijk] + - 1) + / v->DataPTEReqWidthY, + 1) + + 1); + } else { + v->DPTEBytesPerRowY = + 64 + * (dml_ceil_ex( + (src.viewport_height + - 1) + / v->DataPTEReqHeightY, + 1) + + 1); + } + } else { + v->DPTEBytesPerRowY = 0; + } + + if (src.source_format != dm_444_64 && src.source_format != dm_444_32 + && src.source_format != dm_444_16) { + if (src.dcc == 1) { + v->MetaReqHeightC = 8 * v->Read256BlockHeightC[k]; + v->MetaReqWidthC = + 64 * 256 + / dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / v->MetaReqHeightC; + v->MetaSurfaceWidthC = dml_ceil_ex( + src.viewport_width / v->NoOfDPP[ijk] + / 2 - 1, + v->MetaReqWidthC) + + v->MetaReqWidthC; + v->MetaSurfaceHeightC = dml_ceil_ex( + src.viewport_height / 2 - 1, + v->MetaReqHeightC) + + v->MetaReqHeightC; + if (ip->pte_enable == 1) { + v->MetaPteBytesPerFrameC = + (dml_ceil_ex( + (v->MetaSurfaceWidthC + * v->MetaSurfaceHeightC + * dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / 256.0 + - 4096) + / 8 + / 4096, + 1) + 1) + * 64; + } else { + v->MetaPteBytesPerFrameC = 0; + } + if (src.source_scan == dm_horz) { + v->MetaRowBytesC = + v->MetaSurfaceWidthC + * v->MetaReqHeightC + * dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / 256; + } else { + v->MetaRowBytesC = + v->MetaSurfaceHeightC + * v->MetaReqWidthC + * dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / 256; + } + } else { + v->MetaPteBytesPerFrameC = 0; + v->MetaRowBytesC = 0; + } + + if (ip->pte_enable == 1) { + if (src.sw_mode == dm_sw_linear) { + v->MacroTileBlockSizeBytesC = 256; + v->MacroTileBlockHeightC = 1; + } else if (src.sw_mode == dm_sw_4kb_s + || src.sw_mode == dm_sw_4kb_s_x + || src.sw_mode == dm_sw_4kb_d + || src.sw_mode == dm_sw_4kb_d_x) { + v->MacroTileBlockSizeBytesC = 4096; + v->MacroTileBlockHeightC = 4 + * v->Read256BlockHeightC[k]; + } else if (src.sw_mode == dm_sw_64kb_s + || src.sw_mode == dm_sw_64kb_s_t + || src.sw_mode == dm_sw_64kb_s_x + || src.sw_mode == dm_sw_64kb_d + || src.sw_mode == dm_sw_64kb_d_t + || src.sw_mode == dm_sw_64kb_d_x) { + v->MacroTileBlockSizeBytesC = 64 * 1024; + v->MacroTileBlockHeightC = 16 + * v->Read256BlockHeightC[k]; + } else { + v->MacroTileBlockSizeBytesC = 256 * 1024; + v->MacroTileBlockHeightC = 32 + * v->Read256BlockHeightC[k]; + } + v->MacroTileBlockWidthC = + v->MacroTileBlockSizeBytesC + / dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / v->MacroTileBlockHeightC; + if (v->MacroTileBlockSizeBytesC <= 65536) { + v->DataPTEReqHeightC = + v->MacroTileBlockHeightC; + } else { + v->DataPTEReqHeightC = 16 + * v->Read256BlockHeightC[k]; + } + v->DataPTEReqWidthC = + 4096 + / dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / v->DataPTEReqHeightC + * 8; + if (src.sw_mode == dm_sw_linear) { + v->DPTEBytesPerRowC = + 64 + * (dml_ceil_ex( + (src.viewport_width + / v->NoOfDPP[ijk] + / 2 + * dml_min( + 128, + dml_pow( + 2, + dml_floor_ex( + dml_log( + ip->dpte_buffer_size_in_pte_reqs + * v->DataPTEReqWidthC + / (src.viewport_width + / v->NoOfDPP[ijk] + / 2), + 2), + 1))) + - 1) + / v->DataPTEReqWidthC, + 1) + + 1); + } else if (src.source_scan == dm_horz) { + v->DPTEBytesPerRowC = + 64 + * (dml_ceil_ex( + (src.viewport_width + / v->NoOfDPP[ijk] + / 2 + - 1) + / v->DataPTEReqWidthC, + 1) + + 1); + } else { + v->DPTEBytesPerRowC = + 64 + * (dml_ceil_ex( + (src.viewport_height + / 2 + - 1) + / v->DataPTEReqHeightC, + 1) + + 1); + } + } else { + v->DPTEBytesPerRowC = 0; + } + } else { + v->DPTEBytesPerRowC = 0; + v->MetaPteBytesPerFrameC = 0; + v->MetaRowBytesC = 0; + } + + v->DPTEBytesPerRow[k] = v->DPTEBytesPerRowY + v->DPTEBytesPerRowC; + v->MetaPTEBytesPerFrame[k] = v->MetaPteBytesPerFrameY + + v->MetaPteBytesPerFrameC; + v->MetaRowBytes[k] = v->MetaRowBytesY + v->MetaRowBytesC; + + v->VInitY = (scale_ratio_depth.vscl_ratio + scale_taps.vtaps + 1 + + dest.interlaced * 0.5 + * scale_ratio_depth.vscl_ratio) + / 2.0; + v->PrefillY[k] = dml_floor_ex(v->VInitY, 1); + v->MaxNumSwY[k] = dml_ceil_ex( + (v->PrefillY[k] - 1.0) + / v->SwathHeightYPerState[ijk], + 1) + 1.0; + + if (v->PrefillY[k] > 1) { + v->MaxPartialSwY = ((int) (v->PrefillY[k] - 2)) + % ((int) v->SwathHeightYPerState[ijk]); + } else { + v->MaxPartialSwY = ((int) (v->PrefillY[k] + + v->SwathHeightYPerState[ijk] - 2)) + % ((int) v->SwathHeightYPerState[ijk]); + } + v->MaxPartialSwY = dml_max(1, v->MaxPartialSwY); + + v->PrefetchLinesY[k] = v->MaxNumSwY[k] + * v->SwathHeightYPerState[ijk] + v->MaxPartialSwY; + + if (src.source_format != dm_444_64 && src.source_format != dm_444_32 + && src.source_format != dm_444_16) { + v->VInitC = + (scale_ratio_depth.vscl_ratio / 2 + + scale_taps.vtaps + 1 + + dest.interlaced * 0.5 + * scale_ratio_depth.vscl_ratio + / 2) / 2.0; + v->PrefillC[k] = dml_floor_ex(v->VInitC, 1); + v->MaxNumSwC[k] = + dml_ceil_ex( + (v->PrefillC[k] - 1.0) + / v->SwathHeightCPerState[ijk], + 1) + 1.0; + if (v->PrefillC[k] > 1) { + v->MaxPartialSwC = + ((int) (v->PrefillC[k] - 2)) + % ((int) v->SwathHeightCPerState[ijk]); + } else { + v->MaxPartialSwC = + ((int) (v->PrefillC[k] + + v->SwathHeightCPerState[ijk] + - 2)) + % ((int) v->SwathHeightCPerState[ijk]); + } + v->MaxPartialSwC = dml_max(1, v->MaxPartialSwC); + + v->PrefetchLinesC[k] = v->MaxNumSwC[k] + * v->SwathHeightCPerState[ijk] + + v->MaxPartialSwC; + } else { + v->PrefetchLinesC[k] = 0; + } + + v->dst_x_after_scaler = 90 * dest.pixel_rate_mhz + / (v->RequiredDISPCLK[ij] / (j + 1)) + + 42 * dest.pixel_rate_mhz / v->RequiredDISPCLK[ij]; + if (v->NoOfDPP[ijk] > 1) { + v->dst_x_after_scaler = v->dst_x_after_scaler + + dest.recout_width / 2.0; + } + + if (dout.output_format == dm_420) { + v->dst_y_after_scaler = 1; + } else { + v->dst_y_after_scaler = 0; + } + + v->TimeCalc = 24 / v->ProjectedDCFCLKDeepSleep; + + v->VUpdateOffset = dml_ceil_ex(dest.htotal / 4, 1); + v->TotalRepeaterDelay = ip->max_inter_dcn_tile_repeaters + * (2 / (v->RequiredDISPCLK[ij] / (j + 1)) + + 3 / v->RequiredDISPCLK[ij]); + v->VUpdateWidth = (14 / v->ProjectedDCFCLKDeepSleep + + 12 / (v->RequiredDISPCLK[ij] / (j + 1)) + + v->TotalRepeaterDelay) * dest.pixel_rate_mhz; + v->VReadyOffset = + dml_max( + 150 + / (v->RequiredDISPCLK[ij] + / (j + + 1)), + v->TotalRepeaterDelay + + 20 + / v->ProjectedDCFCLKDeepSleep + + 10 + / (v->RequiredDISPCLK[ij] + / (j + + 1))) + * dest.pixel_rate_mhz; + + v->TimeSetup = + (v->VUpdateOffset + v->VUpdateWidth + + v->VReadyOffset) + / dest.pixel_rate_mhz; + + v->ExtraLatency = + v->UrgentRoundTripAndOutOfOrderLatencyPerState[i] + + (v->TotalNumberOfActiveDPP[ij] + * ip->pixel_chunk_size_kbytes + + v->TotalNumberOfDCCActiveDPP[ij] + * ip->meta_chunk_size_kbytes) + * 1024 + / v->ReturnBWPerState[i]; + + if (ip->pte_enable == 1) { + v->ExtraLatency = v->ExtraLatency + + v->TotalNumberOfActiveDPP[ij] + * ip->pte_chunk_size_kbytes + * 1024 + / v->ReturnBWPerState[i]; + } + + if (ip->can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one + == 1) { + v->MaximumVStartup = dest.vtotal - dest.vactive - 1; + } else { + v->MaximumVStartup = dest.vsync_plus_back_porch - 1; + } + + v->LineTimesForPrefetch[k] = + v->MaximumVStartup + - soc->urgent_latency_us + / (dest.htotal + / dest.pixel_rate_mhz) + - (v->TimeCalc + v->TimeSetup) + / (dest.htotal + / dest.pixel_rate_mhz) + - (v->dst_y_after_scaler + + v->dst_x_after_scaler + / dest.htotal); + + v->LineTimesForPrefetch[k] = dml_floor_ex( + 4.0 * (v->LineTimesForPrefetch[k] + 0.125), + 1) / 4; + + v->PrefetchBW[k] = + (v->MetaPTEBytesPerFrame[k] + 2 * v->MetaRowBytes[k] + + 2 * v->DPTEBytesPerRow[k] + + v->PrefetchLinesY[k] + * v->SwathWidthYPerState[ijk] + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + + v->PrefetchLinesC[k] + * v->SwathWidthYPerState[ijk] + / 2 + * dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2)) + / (v->LineTimesForPrefetch[k] + * dest.htotal + / dest.pixel_rate_mhz); + } + + v->BWAvailableForImmediateFlip = v->ReturnBWPerState[i]; + + for (k = 0; k < num_planes; k++) { + v->BWAvailableForImmediateFlip = v->BWAvailableForImmediateFlip + - dml_max(v->ReadBandwidth[k], v->PrefetchBW[k]); + } + + v->TotalImmediateFlipBytes = 0; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + + if (src.source_format != dm_420_8 + && src.source_format != dm_420_10) { + v->TotalImmediateFlipBytes = v->TotalImmediateFlipBytes + + v->MetaPTEBytesPerFrame[k] + + v->MetaRowBytes[k] + + v->DPTEBytesPerRow[k]; + } + } + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + if (ip->pte_enable == 1 && src.dcc == 1) { + v->TimeForMetaPTEWithImmediateFlip = + dml_max( + v->MetaPTEBytesPerFrame[k] + / v->PrefetchBW[k], + dml_max( + v->MetaPTEBytesPerFrame[k] + * v->TotalImmediateFlipBytes + / (v->BWAvailableForImmediateFlip + * (v->MetaPTEBytesPerFrame[k] + + v->MetaRowBytes[k] + + v->DPTEBytesPerRow[k])), + dml_max( + v->ExtraLatency, + dml_max( + soc->urgent_latency_us, + dest.htotal + / dest.pixel_rate_mhz + / 4)))); + + v->TimeForMetaPTEWithoutImmediateFlip = + dml_max( + v->MetaPTEBytesPerFrame[k] + / v->PrefetchBW[k], + dml_max( + v->ExtraLatency, + dest.htotal + / dest.pixel_rate_mhz + / 4)); + } else { + v->TimeForMetaPTEWithImmediateFlip = dest.htotal + / dest.pixel_rate_mhz / 4; + v->TimeForMetaPTEWithoutImmediateFlip = dest.htotal + / dest.pixel_rate_mhz / 4; + } + + if (ip->pte_enable == 1 || src.dcc == 1) { + v->TimeForMetaAndDPTERowWithImmediateFlip = + dml_max( + (v->MetaRowBytes[k] + + v->DPTEBytesPerRow[k]) + / v->PrefetchBW[k], + dml_max( + (v->MetaRowBytes[k] + + v->DPTEBytesPerRow[k]) + * v->TotalImmediateFlipBytes + / (v->BWAvailableForImmediateFlip + * (v->MetaPTEBytesPerFrame[k] + + v->MetaRowBytes[k] + + v->DPTEBytesPerRow[k])), + dml_max( + dest.htotal + / dest.pixel_rate_mhz + - v->TimeForMetaPTEWithImmediateFlip, + dml_max( + v->ExtraLatency, + 2 + * soc->urgent_latency_us)))); + + v->TimeForMetaAndDPTERowWithoutImmediateFlip = + dml_max( + (v->MetaRowBytes[k] + + v->DPTEBytesPerRow[k]) + / v->PrefetchBW[k], + dml_max( + dest.htotal + / dest.pixel_rate_mhz + - v->TimeForMetaPTEWithoutImmediateFlip, + v->ExtraLatency)); + } else { + v->TimeForMetaAndDPTERowWithImmediateFlip = + dml_max( + dest.htotal + / dest.pixel_rate_mhz + - v->TimeForMetaPTEWithImmediateFlip, + v->ExtraLatency + - v->TimeForMetaPTEWithImmediateFlip); + v->TimeForMetaAndDPTERowWithoutImmediateFlip = + dml_max( + dest.htotal + / dest.pixel_rate_mhz + - v->TimeForMetaPTEWithoutImmediateFlip, + v->ExtraLatency + - v->TimeForMetaPTEWithoutImmediateFlip); + } + + v->LinesForMetaPTEWithImmediateFlip[k] = + dml_floor_ex( + 4.0 + * (v->TimeForMetaPTEWithImmediateFlip + / (dest.htotal + / dest.pixel_rate_mhz) + + 0.125), + 1) / 4.0; + + v->LinesForMetaPTEWithoutImmediateFlip[k] = + dml_floor_ex( + 4.0 + * (v->TimeForMetaPTEWithoutImmediateFlip + / (dest.htotal + / dest.pixel_rate_mhz) + + 0.125), + 1) / 4.0; + + v->LinesForMetaAndDPTERowWithImmediateFlip[k] = + dml_floor_ex( + 4.0 + * (v->TimeForMetaAndDPTERowWithImmediateFlip + / (dest.htotal + / dest.pixel_rate_mhz) + + 0.125), + 1) / 4.0; + + v->LinesForMetaAndDPTERowWithoutImmediateFlip[k] = + dml_floor_ex( + 4.0 + * (v->TimeForMetaAndDPTERowWithoutImmediateFlip + / (dest.htotal + / dest.pixel_rate_mhz) + + 0.125), + 1) / 4.0; + + v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip = + v->LineTimesForPrefetch[k] + - v->LinesForMetaPTEWithImmediateFlip[k] + - v->LinesForMetaAndDPTERowWithImmediateFlip[k]; + + v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip = + v->LineTimesForPrefetch[k] + - v->LinesForMetaPTEWithoutImmediateFlip[k] + - v->LinesForMetaAndDPTERowWithoutImmediateFlip[k]; + + if (v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip > 0) { + v->VRatioPreYWithImmediateFlip[ijk] = + v->PrefetchLinesY[k] + / v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip; + if (v->SwathHeightYPerState[ijk] > 4) { + if (v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip + - (v->PrefillY[k] - 3.0) / 2.0 + > 0) { + v->VRatioPreYWithImmediateFlip[ijk] = + dml_max( + v->VRatioPreYWithImmediateFlip[ijk], + (v->MaxNumSwY[k] + * v->SwathHeightYPerState[ijk]) + / (v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip + - (v->PrefillY[k] + - 3.0) + / 2.0)); + } else { + v->VRatioPreYWithImmediateFlip[ijk] = + 999999; + } + } + v->VRatioPreCWithImmediateFlip[ijk] = + v->PrefetchLinesC[k] + / v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip; + if (v->SwathHeightCPerState[ijk] > 4) { + if (v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip + - (v->PrefillC[k] - 3.0) / 2.0 + > 0) { + v->VRatioPreCWithImmediateFlip[ijk] = + dml_max( + v->VRatioPreCWithImmediateFlip[ijk], + (v->MaxNumSwC[k] + * v->SwathHeightCPerState[ijk]) + / (v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip + - (v->PrefillC[k] + - 3.0) + / 2.0)); + } else { + v->VRatioPreCWithImmediateFlip[ijk] = + 999999; + } + } + + v->RequiredPrefetchPixelDataBWWithImmediateFlip[ijk] = + v->NoOfDPP[ijk] + * (v->PrefetchLinesY[k] + / v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + + v->PrefetchLinesC[k] + / v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip + * dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / 2) + * v->SwathWidthYPerState[ijk] + / (dest.htotal + / dest.pixel_rate_mhz); + } else { + v->VRatioPreYWithImmediateFlip[ijk] = 999999; + v->VRatioPreCWithImmediateFlip[ijk] = 999999; + v->RequiredPrefetchPixelDataBWWithImmediateFlip[ijk] = + 999999; + } + + if (v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip + > 0) { + v->VRatioPreYWithoutImmediateFlip[ijk] = + v->PrefetchLinesY[k] + / v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip; + if (v->SwathHeightYPerState[ijk] > 4) { + if (v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip + - (v->PrefillY[k] - 3.0) / 2.0 + > 0) { + v->VRatioPreYWithoutImmediateFlip[ijk] = + dml_max( + v->VRatioPreYWithoutImmediateFlip[ijk], + (v->MaxNumSwY[k] + * v->SwathHeightYPerState[ijk]) + / (v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip + - (v->PrefillY[k] + - 3.0) + / 2.0)); + } else { + v->VRatioPreYWithoutImmediateFlip[ijk] = + 999999; + } + } + v->VRatioPreCWithoutImmediateFlip[ijk] = + v->PrefetchLinesC[k] + / v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip; + if (v->SwathHeightCPerState[ijk] > 4) { + if (v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip + - (v->PrefillC[k] - 3.0) / 2.0 + > 0) { + v->VRatioPreCWithoutImmediateFlip[ijk] = + dml_max( + v->VRatioPreCWithoutImmediateFlip[ijk], + (v->MaxNumSwC[k] + * v->SwathHeightCPerState[ijk]) + / (v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip + - (v->PrefillC[k] + - 3.0) + / 2.0)); + } else { + v->VRatioPreCWithoutImmediateFlip[ijk] = + 999999; + } + } + + v->RequiredPrefetchPixelDataBWWithoutImmediateFlip[ijk] = + v->NoOfDPP[ijk] + * (v->PrefetchLinesY[k] + / v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + + v->PrefetchLinesC[k] + / v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip + * dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / 2) + * v->SwathWidthYPerState[ijk] + / (dest.htotal + / dest.pixel_rate_mhz); + } else { + v->VRatioPreYWithoutImmediateFlip[ijk] = 999999; + v->VRatioPreCWithoutImmediateFlip[ijk] = 999999; + v->RequiredPrefetchPixelDataBWWithoutImmediateFlip[ijk] = + 999999; + } + } + + v->MaximumReadBandwidthWithPrefetchWithImmediateFlip = 0; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + if (src.source_format != dm_420_8 + && src.source_format != dm_420_10) { + v->MaximumReadBandwidthWithPrefetchWithImmediateFlip = + v->MaximumReadBandwidthWithPrefetchWithImmediateFlip + + dml_max( + v->ReadBandwidth[k], + v->RequiredPrefetchPixelDataBWWithImmediateFlip[ijk]) + + dml_max( + v->MetaPTEBytesPerFrame[k] + / (v->LinesForMetaPTEWithImmediateFlip[k] + * dest.htotal + / dest.pixel_rate_mhz), + (v->MetaRowBytes[k] + + v->DPTEBytesPerRow[k]) + / (v->LinesForMetaAndDPTERowWithImmediateFlip[k] + * dest.htotal + / dest.pixel_rate_mhz)); + } else { + v->MaximumReadBandwidthWithPrefetchWithImmediateFlip = + v->MaximumReadBandwidthWithPrefetchWithImmediateFlip + + dml_max( + v->ReadBandwidth[k], + v->RequiredPrefetchPixelDataBWWithoutImmediateFlip[ijk]); + } + } + + v->MaximumReadBandwidthWithPrefetchWithoutImmediateFlip = 0; + + for (k = 0; k < num_planes; k++) { + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + v->MaximumReadBandwidthWithPrefetchWithoutImmediateFlip = + v->MaximumReadBandwidthWithPrefetchWithoutImmediateFlip + + dml_max( + v->ReadBandwidth[k], + v->RequiredPrefetchPixelDataBWWithoutImmediateFlip[ijk]); + } + + v->PrefetchSupportedWithImmediateFlip[ij] = 1; + if (v->MaximumReadBandwidthWithPrefetchWithImmediateFlip + > v->ReturnBWPerState[i]) { + v->PrefetchSupportedWithImmediateFlip[ij] = 0; + } + for (k = 0; k < num_planes; k++) { + if (v->LineTimesForPrefetch[k] < 2 + || v->LinesForMetaPTEWithImmediateFlip[k] >= 8 + || v->LinesForMetaAndDPTERowWithImmediateFlip[k] + >= 16) { + v->PrefetchSupportedWithImmediateFlip[ij] = 0; + } + } + + v->PrefetchSupportedWithoutImmediateFlip[ij] = 1; + if (v->MaximumReadBandwidthWithPrefetchWithoutImmediateFlip + > v->ReturnBWPerState[i]) { + v->PrefetchSupportedWithoutImmediateFlip[ij] = 0; + } + for (k = 0; k < num_planes; k++) { + if (v->LineTimesForPrefetch[k] < 2 + || v->LinesForMetaPTEWithoutImmediateFlip[k] >= 8 + || v->LinesForMetaAndDPTERowWithoutImmediateFlip[k] + >= 16) { + v->PrefetchSupportedWithoutImmediateFlip[ij] = 0; + } + } + } + } + + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + for (j = 0; j < 2; j++) { + ij = j * NumberOfStatesPlusTwo + i; + + v->VRatioInPrefetchSupportedWithImmediateFlip[ij] = 1; + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + if (((src.source_format != dm_420_8 + && src.source_format != dm_420_10) + && (v->VRatioPreYWithImmediateFlip[ijk] > 4 + || v->VRatioPreCWithImmediateFlip[ijk] + > 4)) + || ((src.source_format == dm_420_8 + || src.source_format == dm_420_10) + && (v->VRatioPreYWithoutImmediateFlip[ijk] + > 4 + || v->VRatioPreCWithoutImmediateFlip[ijk] + > 4))) { + v->VRatioInPrefetchSupportedWithImmediateFlip[ij] = 0; + } + } + v->VRatioInPrefetchSupportedWithoutImmediateFlip[ij] = 1; + for (k = 0; k < num_planes; k++) { + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + if (v->VRatioPreYWithoutImmediateFlip[ijk] > 4 + || v->VRatioPreCWithoutImmediateFlip[ijk] > 4) { + v->VRatioInPrefetchSupportedWithoutImmediateFlip[ij] = 0; + } + } + } + } + + // Mode Support, Voltage State and SOC Configuration + + for (i = (NumberOfStatesPlusTwo - 1); i >= 0; i--) // use int type here + { + for (j = 0; j < 2; j++) { + ij = j * NumberOfStatesPlusTwo + i; + + if (v->ScaleRatioSupport == 1 && v->SourceFormatPixelAndScanSupport == 1 + && v->ViewportSizeSupport == 1 + && v->BandwidthSupport[i] == 1 && v->DIOSupport[i] == 1 + && v->UrgentLatencySupport[ij] == 1 && v->ROBSupport[i] == 1 + && v->DISPCLK_DPPCLK_Support[ij] == 1 + && v->TotalAvailablePipesSupport[ij] == 1 + && v->TotalAvailableWritebackSupport == 1 + && v->WritebackLatencySupport == 1) { + if (v->PrefetchSupportedWithImmediateFlip[ij] == 1 + && v->VRatioInPrefetchSupportedWithImmediateFlip[ij] + == 1) { + v->ModeSupportWithImmediateFlip[ij] = 1; + } else { + v->ModeSupportWithImmediateFlip[ij] = 0; + } + if (v->PrefetchSupportedWithoutImmediateFlip[ij] == 1 + && v->VRatioInPrefetchSupportedWithoutImmediateFlip[ij] + == 1) { + v->ModeSupportWithoutImmediateFlip[ij] = 1; + } else { + v->ModeSupportWithoutImmediateFlip[ij] = 0; + } + } else { + v->ModeSupportWithImmediateFlip[ij] = 0; + v->ModeSupportWithoutImmediateFlip[ij] = 0; + } + } + } + + for (i = (NumberOfStatesPlusTwo - 1); i >= 0; i--) // use int type here + { + if ((i == (NumberOfStatesPlusTwo - 1) + || v->ModeSupportWithImmediateFlip[1 * NumberOfStatesPlusTwo + i] + == 1 + || v->ModeSupportWithImmediateFlip[0 * NumberOfStatesPlusTwo + i] + == 1) && i >= v->VoltageOverrideLevel) { + v->VoltageLevelWithImmediateFlip = i; + } + } + + for (i = (NumberOfStatesPlusTwo - 1); i >= 0; i--) // use int type here + { + if ((i == (NumberOfStatesPlusTwo - 1) + || v->ModeSupportWithoutImmediateFlip[1 * NumberOfStatesPlusTwo + i] + == 1 + || v->ModeSupportWithoutImmediateFlip[0 * NumberOfStatesPlusTwo + i] + == 1) && i >= v->VoltageOverrideLevel) { + v->VoltageLevelWithoutImmediateFlip = i; + } + } + + if (v->VoltageLevelWithImmediateFlip == (NumberOfStatesPlusTwo - 1)) { + v->ImmediateFlipSupported = 0; + v->VoltageLevel = v->VoltageLevelWithoutImmediateFlip; + } else { + v->ImmediateFlipSupported = 1; + v->VoltageLevel = v->VoltageLevelWithImmediateFlip; + } + + v->DCFCLK = v->DCFCLKPerState[(int) v->VoltageLevel]; + v->FabricAndDRAMBandwidth = v->FabricAndDRAMBandwidthPerState[(int) v->VoltageLevel]; + + for (j = 0; j < 2; j++) { + v->RequiredDISPCLKPerRatio[j] = v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + + (int) v->VoltageLevel]; + for (k = 0; k < num_planes; k++) { + v->DPPPerPlanePerRatio[k * 2 + j] = v->NoOfDPP[k * 2 * NumberOfStatesPlusTwo + + j * NumberOfStatesPlusTwo + (int) v->VoltageLevel]; + } + v->DISPCLK_DPPCLK_SupportPerRatio[j] = v->DISPCLK_DPPCLK_Support[j + * NumberOfStatesPlusTwo + (int) v->VoltageLevel]; + } + + ASSERT(v->ImmediateFlipSupported || v->MacroTileBlockWidthC || v->DCFCLK || v->FabricAndDRAMBandwidth); + + return (v->VoltageLevel); +} + diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.h index d4ea0371cde2..ead4942f998c 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.h @@ -191,4 +191,9 @@ struct dml_ms_internal_vars { struct _vcs_dpi_wm_calc_pipe_params_st planes[DC__NUM_PIPES__MAX]; }; +int dml_ms_check( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + int num_pipes); + #endif -- cgit From e168df36a807dff8e5cc78c1daeb9dec89e4118c Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 16 Oct 2017 22:10:54 -0400 Subject: Revert "amdgpu/dc: drop dml_util_is_420" This reverts commit e5bcf3d83e40cc7acc9d111519b7bacaf4a01070. Unfortunately these clash with our DML update from the HW guys. Will attempt to reroll them after. Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dml/dml_common_defs.c | 33 ++++++++++++++++++++++ .../gpu/drm/amd/display/dc/dml/dml_common_defs.h | 1 + 2 files changed, 34 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c index 7c0eb52b91b8..c242b8d41b8a 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c @@ -59,3 +59,36 @@ unsigned int dml_round_to_multiple( else return (num - remainder); } + +bool dml_util_is_420(enum source_format_class sorce_format) +{ + bool val = false; + + switch (sorce_format) { + case dm_444_16: + val = false; + break; + case dm_444_32: + val = false; + break; + case dm_444_64: + val = false; + break; + case dm_420_8: + val = true; + break; + case dm_420_10: + val = true; + break; + case dm_422_8: + val = false; + break; + case dm_422_10: + val = false; + break; + default: + BREAK_TO_DEBUGGER(); + } + + return val; +} diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h index a2da3da5ef8f..c621f8321b03 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h @@ -32,6 +32,7 @@ #define DTRACE(str, ...) dm_logger_write(mode_lib->logger, LOG_DML, str, ##__VA_ARGS__); +bool dml_util_is_420(enum source_format_class sorce_format); double dml_round(double a); unsigned int dml_round_to_multiple( unsigned int num, unsigned int multiple, bool up); -- cgit From 711b55f3fca418de8c6484a1aa38bcc241acc536 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 16 Oct 2017 22:11:04 -0400 Subject: Revert "amdgpu/dc: inline a bunch of the dml wrappers." This reverts commit 3e8c3108dab197858e74dbb740c5312ae636ea9b. Unfortunately these clash with our DML update from the HW guys. Will attempt to reroll them after. Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dml/display_mode_support.c | 1 - .../drm/amd/display/dc/dml/display_rq_dlg_calc.c | 2 - .../gpu/drm/amd/display/dc/dml/display_watermark.c | 1 - .../gpu/drm/amd/display/dc/dml/dml_common_defs.c | 56 +++++++++++++++++++- .../gpu/drm/amd/display/dc/dml/dml_common_defs.h | 11 ++++ .../gpu/drm/amd/display/dc/dml/dml_inline_defs.h | 61 ---------------------- .../gpu/drm/amd/display/dc/dml/soc_bounding_box.c | 1 - 7 files changed, 66 insertions(+), 67 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c index ac573568c10a..3b4ee74527f5 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c @@ -26,7 +26,6 @@ #include "display_mode_support.h" #include "display_mode_lib.h" -#include "dml_inline_defs.h" int dml_ms_check( struct display_mode_lib *mode_lib, struct _vcs_dpi_display_e2e_pipe_params_st *e2e, diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c index 7a5fb1cef303..9fccbbffe129 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c @@ -25,8 +25,6 @@ #include "display_rq_dlg_calc.h" #include "display_mode_lib.h" -#include "dml_inline_defs.h" - static unsigned int get_bytes_per_element(enum source_format_class source_format, bool is_chroma) { unsigned int ret_val = 0; diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_watermark.c b/drivers/gpu/drm/amd/display/dc/dml/display_watermark.c index 142a3284ac44..390f09391433 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_watermark.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_watermark.c @@ -24,7 +24,6 @@ */ #include "display_watermark.h" #include "display_mode_lib.h" -#include "dml_inline_defs.h" static void get_bytes_per_pixel( enum source_format_class format, diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c index c242b8d41b8a..21349a022de3 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c @@ -26,7 +26,26 @@ #include "dml_common_defs.h" #include "../calcs/dcn_calc_math.h" -#include "dml_inline_defs.h" +double dml_min(double a, double b) +{ + return (double) dcn_bw_min2(a, b); +} + +double dml_max(double a, double b) +{ + return (double) dcn_bw_max2(a, b); +} + +double dml_ceil(double a) +{ + return (double) dcn_bw_ceil2(a, 1); +} + +double dml_floor(double a) +{ + return (double) dcn_bw_floor2(a, 1); +} + double dml_round(double a) { double round_pt = 0.5; @@ -39,6 +58,16 @@ double dml_round(double a) return floor; } +int dml_log2(double x) +{ + return dml_round((double)dcn_bw_log(x, 2)); +} + +double dml_pow(double a, int exp) +{ + return (double) dcn_bw_pow(a, exp); +} + unsigned int dml_round_to_multiple( unsigned int num, unsigned int multiple, @@ -60,6 +89,16 @@ unsigned int dml_round_to_multiple( return (num - remainder); } +double dml_fmod(double f, int val) +{ + return (double) dcn_bw_mod(f, val); +} + +double dml_ceil_2(double f) +{ + return (double) dcn_bw_ceil2(f, 2); +} + bool dml_util_is_420(enum source_format_class sorce_format) { bool val = false; @@ -92,3 +131,18 @@ bool dml_util_is_420(enum source_format_class sorce_format) return val; } + +double dml_ceil_ex(double x, double granularity) +{ + return (double) dcn_bw_ceil2(x, granularity); +} + +double dml_floor_ex(double x, double granularity) +{ + return (double) dcn_bw_floor2(x, granularity); +} + +double dml_log(double x, double base) +{ + return (double) dcn_bw_log(x, base); +} diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h index c621f8321b03..c5340d41eedb 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h @@ -32,9 +32,20 @@ #define DTRACE(str, ...) dm_logger_write(mode_lib->logger, LOG_DML, str, ##__VA_ARGS__); +double dml_min(double a, double b); +double dml_max(double a, double b); bool dml_util_is_420(enum source_format_class sorce_format); +double dml_ceil_ex(double x, double granularity); +double dml_floor_ex(double x, double granularity); +double dml_log(double x, double base); +double dml_ceil(double a); +double dml_floor(double a); double dml_round(double a); +int dml_log2(double x); +double dml_pow(double a, int exp); unsigned int dml_round_to_multiple( unsigned int num, unsigned int multiple, bool up); +double dml_fmod(double f, int val); +double dml_ceil_2(double f); #endif /* __DC_COMMON_DEFS_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h b/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h deleted file mode 100644 index 1c6c631daad4..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef __DML_INLINE_DEFS_H__ -#define __DML_INLINE_DEFS_H__ -#include "dml_common_defs.h" -#include "../calcs/dcn_calc_math.h" - -static inline double dml_min(double a, double b) -{ - return (double) dcn_bw_min2(a, b); -} - -static inline double dml_max(double a, double b) -{ - return (double) dcn_bw_max2(a, b); -} - -static inline double dml_ceil(double a) -{ - return (double) dcn_bw_ceil2(a, 1); -} - -static inline double dml_floor(double a) -{ - return (double) dcn_bw_floor2(a, 1); -} - -static inline int dml_log2(double x) -{ - return dml_round((double)dcn_bw_log(x, 2)); -} - -static inline double dml_pow(double a, int exp) -{ - return (double) dcn_bw_pow(a, exp); -} - -static inline double dml_fmod(double f, int val) -{ - return (double) dcn_bw_mod(f, val); -} - -static inline double dml_ceil_2(double f) -{ - return (double) dcn_bw_ceil2(f, 2); -} - -static inline double dml_ceil_ex(double x, double granularity) -{ - return (double) dcn_bw_ceil2(x, granularity); -} - -static inline double dml_floor_ex(double x, double granularity) -{ - return (double) dcn_bw_floor2(x, granularity); -} - -static inline double dml_log(double x, double base) -{ - return (double) dcn_bw_log(x, base); -} - -#endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c b/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c index d40f6ae9622c..112b0b728b4d 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c +++ b/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c @@ -25,7 +25,6 @@ #include "soc_bounding_box.h" #include "display_mode_lib.h" -#include "dml_inline_defs.h" void dml_socbb_set_latencies( struct display_mode_lib *mode_lib, struct _vcs_dpi_soc_bounding_box_st *from_box) -- cgit From 378c4a2d609dfc048c4416a387ddec06994cc307 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 16 Oct 2017 22:11:18 -0400 Subject: Revert "amdgpu/dc: drop display_pipe_clocks.c." This reverts commit b3fbdcec5e6c16c93867289ae0960a64c423eb34. Unfortunately these clash with our DML update from the HW guys as it's starting to get used now. Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/Makefile | 2 +- .../gpu/drm/amd/display/dc/dml/display_mode_lib.h | 1 + .../drm/amd/display/dc/dml/display_pipe_clocks.c | 367 +++++++++++++++++++++ .../drm/amd/display/dc/dml/display_pipe_clocks.h | 41 +++ 4 files changed, 410 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.c create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dml/Makefile b/drivers/gpu/drm/amd/display/dc/dml/Makefile index a6bf36466497..9d7791d00e97 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dml/Makefile @@ -13,7 +13,7 @@ CFLAGS_dml_common_defs.o := -mhard-float -msse -mpreferred-stack-boundary=4 CFLAGS_display_mode_support.o := -mhard-float -msse -mpreferred-stack-boundary=4 -DML = display_mode_lib.o display_rq_dlg_calc.o \ +DML = display_mode_lib.o display_pipe_clocks.o display_rq_dlg_calc.o \ display_rq_dlg_helpers.o display_watermark.o \ soc_bounding_box.o dml_common_defs.o display_mode_support.o diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h index eb1c8e6e7f23..e2e311138358 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h @@ -28,6 +28,7 @@ #include "dml_common_defs.h" #include "soc_bounding_box.h" #include "display_watermark.h" +#include "display_pipe_clocks.h" #include "display_rq_dlg_calc.h" #include "display_mode_support.h" diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.c b/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.c new file mode 100644 index 000000000000..2e4dc57cafa0 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.c @@ -0,0 +1,367 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "display_pipe_clocks.h" +#include "display_mode_lib.h" +#include "soc_bounding_box.h" + +static enum voltage_state power_state( + struct display_mode_lib *mode_lib, + double dispclk, + double dppclk) +{ + enum voltage_state state1; + enum voltage_state state2; + + if (dispclk <= mode_lib->soc.vmin.dispclk_mhz) + state1 = dm_vmin; + else if (dispclk <= mode_lib->soc.vnom.dispclk_mhz) + state1 = dm_vnom; + else if (dispclk <= mode_lib->soc.vmax.dispclk_mhz) + state1 = dm_vmax; + else + state1 = dm_vmax_exceeded; + + if (dppclk <= mode_lib->soc.vmin.dppclk_mhz) + state2 = dm_vmin; + else if (dppclk <= mode_lib->soc.vnom.dppclk_mhz) + state2 = dm_vnom; + else if (dppclk <= mode_lib->soc.vmax.dppclk_mhz) + state2 = dm_vmax; + else + state2 = dm_vmax_exceeded; + + if (state1 > state2) + return state1; + else + return state2; +} + +static unsigned int dpp_in_grp( + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_pipes, + unsigned int hsplit_grp) +{ + unsigned int num_dpp = 0; + unsigned int i; + + for (i = 0; i < num_pipes; i++) { + if (e2e[i].pipe.src.is_hsplit) { + if (e2e[i].pipe.src.hsplit_grp == hsplit_grp) { + num_dpp++; + } + } + } + + if (0 == num_dpp) + num_dpp = 1; + + return num_dpp; +} + +static void calculate_pipe_clk_requirement( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_dpp_in_grp, + double *dppclk, + double *dispclk, + bool *dppdiv) +{ + double pscl_throughput = 0.0; + double max_hratio = e2e->pipe.scale_ratio_depth.hscl_ratio; + double max_vratio = e2e->pipe.scale_ratio_depth.vscl_ratio; + double max_htaps = e2e->pipe.scale_taps.htaps; + double max_vtaps = e2e->pipe.scale_taps.vtaps; + double dpp_clock_divider = (double) num_dpp_in_grp; + double dispclk_dppclk_ratio; + double dispclk_ramp_margin_percent; + + if (max_hratio > 1.0) { + double pscl_to_lb = ((double) mode_lib->ip.max_pscl_lb_bw_pix_per_clk * max_hratio) + / dml_ceil(max_htaps / 6.0); + pscl_throughput = dml_min( + pscl_to_lb, + (double) mode_lib->ip.max_dchub_pscl_bw_pix_per_clk); + } else { + pscl_throughput = dml_min( + (double) mode_lib->ip.max_pscl_lb_bw_pix_per_clk, + (double) mode_lib->ip.max_dchub_pscl_bw_pix_per_clk); + } + + DTRACE("pscl_throughput: %f pix per clk", pscl_throughput); + DTRACE("vtaps: %f hratio: %f vratio: %f", max_vtaps, max_hratio, max_vratio); + *dppclk = dml_max( + max_vtaps / 6.0 * dml_min(1.0, max_hratio), + max_hratio * max_vratio / pscl_throughput); + DTRACE("pixel rate multiplier: %f", *dppclk); + *dppclk = dml_max(*dppclk, 1.0); + DTRACE("pixel rate multiplier clamped: %f", *dppclk); + *dppclk = *dppclk * e2e->pipe.dest.pixel_rate_mhz; + + *dppclk = *dppclk / dpp_clock_divider; + DTRACE("dppclk after split: %f", *dppclk); + + if (dpp_clock_divider > 1.0 && (*dppclk < e2e->pipe.dest.pixel_rate_mhz)) { + dispclk_dppclk_ratio = 2.0; + *dppdiv = true; + } else { + dispclk_dppclk_ratio = 1.0; + *dppdiv = false; + } + + dispclk_ramp_margin_percent = mode_lib->ip.dispclk_ramp_margin_percent; + + /* Comment this out because of Gabes possible bug in spreadsheet, + * just to make other cases evident during debug + * + *if(e2e->clks_cfg.voltage == dm_vmax) + * dispclk_ramp_margin_percent = 0.0; + */ + + /* account for ramping margin and downspread */ + *dispclk = dml_max(*dppclk * dispclk_dppclk_ratio, e2e->pipe.dest.pixel_rate_mhz) + * (1.0 + (double) mode_lib->soc.downspread_percent / 100.0) + * (1.0 + (double) dispclk_ramp_margin_percent / 100.0); + + return; +} + +bool dml_clks_pipe_clock_requirement_fit_power_constraint( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_dpp_in_grp) +{ + double dppclk = 0; + double dispclk = 0; + bool dppdiv = 0; + + calculate_pipe_clk_requirement(mode_lib, e2e, num_dpp_in_grp, &dppclk, &dispclk, &dppdiv); + + if (power_state(mode_lib, dispclk, dppclk) > e2e->clks_cfg.voltage) { + return false; + } + + return true; +} + +static void get_plane_clks( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_pipes, + double *dppclks, + double *dispclks, + bool *dppdiv) +{ + /* it is assumed that the scale ratios passed into the e2e pipe params have already been calculated + * for any split pipe configurations, where extra pixels inthe overlap region do not contribute to + * the scale ratio. This means that we can simply calculate the dppclk for each dpp independently + * and we would expect the same result on any split pipes, which would be handled + */ + unsigned int i; + + for (i = 0; i < num_pipes; i++) { + double num_dpp_in_grp; + double dispclk_ramp_margin_percent; + double dispclk_margined; + + if (e2e[i].pipe.src.is_hsplit) + num_dpp_in_grp = (double) dpp_in_grp( + e2e, + num_pipes, + e2e[i].pipe.src.hsplit_grp); + else + num_dpp_in_grp = 1; + + calculate_pipe_clk_requirement( + mode_lib, + &e2e[i], + num_dpp_in_grp, + &dppclks[i], + &dispclks[i], + &dppdiv[i]); + + dispclk_ramp_margin_percent = mode_lib->ip.dispclk_ramp_margin_percent; + + dispclk_margined = e2e[i].pipe.dest.pixel_rate_mhz + * (1.0 + (double) mode_lib->soc.downspread_percent / 100.0) + * (1.0 + (double) dispclk_ramp_margin_percent / 100.0); + + DTRACE("p%d: requested power state: %d", i, (int) e2e[0].clks_cfg.voltage); + + if (power_state(mode_lib, dispclks[i], dppclks[i]) + > power_state(mode_lib, dispclk_margined, dispclk_margined) + && dispclk_margined > dppclks[i]) { + if (power_state(mode_lib, dispclks[i], dppclks[i]) + > e2e[0].clks_cfg.voltage) { + dispclks[i] = dispclk_margined; + dppclks[i] = dispclk_margined; + dppdiv[i] = false; + } + } + + DTRACE("p%d: dispclk: %f", i, dispclks[i]); + } +} + +static void get_dcfclk( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_pipes, + double *dcfclk_mhz) +{ + double bytes_per_pixel_det_y[DC__NUM_PIPES__MAX]; + double bytes_per_pixel_det_c[DC__NUM_PIPES__MAX]; + double swath_width_y[DC__NUM_PIPES__MAX]; + unsigned int i; + double total_read_bandwidth_gbps = 0.0; + + for (i = 0; i < num_pipes; i++) { + if (e2e[i].pipe.src.source_scan == dm_horz) { + swath_width_y[i] = e2e[i].pipe.src.viewport_width * 1.0; + } else { + swath_width_y[i] = e2e[i].pipe.src.viewport_height * 1.0; + } + + switch (e2e[i].pipe.src.source_format) { + case dm_444_64: + bytes_per_pixel_det_y[i] = 8.0; + bytes_per_pixel_det_c[i] = 0.0; + break; + case dm_444_32: + bytes_per_pixel_det_y[i] = 4.0; + bytes_per_pixel_det_c[i] = 0.0; + break; + case dm_444_16: + bytes_per_pixel_det_y[i] = 2.0; + bytes_per_pixel_det_c[i] = 0.0; + break; + case dm_422_8: + bytes_per_pixel_det_y[i] = 2.0; + bytes_per_pixel_det_c[i] = 0.0; + break; + case dm_422_10: + bytes_per_pixel_det_y[i] = 4.0; + bytes_per_pixel_det_c[i] = 0.0; + break; + case dm_420_8: + bytes_per_pixel_det_y[i] = 1.0; + bytes_per_pixel_det_c[i] = 2.0; + break; + case dm_420_10: + bytes_per_pixel_det_y[i] = 4.0 / 3.0; + bytes_per_pixel_det_c[i] = 8.0 / 3.0; + break; + default: + BREAK_TO_DEBUGGER(); /* invalid src_format in get_dcfclk */ + } + } + + for (i = 0; i < num_pipes; i++) { + double read_bandwidth_plane_mbps = 0.0; + read_bandwidth_plane_mbps = (double) swath_width_y[i] + * ((double) bytes_per_pixel_det_y[i] + + (double) bytes_per_pixel_det_c[i] / 2.0) + / ((double) e2e[i].pipe.dest.htotal + / (double) e2e[i].pipe.dest.pixel_rate_mhz) + * e2e[i].pipe.scale_ratio_depth.vscl_ratio; + + if (e2e[i].pipe.src.dcc) { + read_bandwidth_plane_mbps += (read_bandwidth_plane_mbps / 1000.0 / 256.0); + } + + if (e2e[i].pipe.src.vm) { + read_bandwidth_plane_mbps += (read_bandwidth_plane_mbps / 1000.0 / 512.0); + } + + total_read_bandwidth_gbps = total_read_bandwidth_gbps + + read_bandwidth_plane_mbps / 1000.0; + } + + DTRACE("total bandwidth = %f gbps", total_read_bandwidth_gbps); + + (*dcfclk_mhz) = (total_read_bandwidth_gbps * 1000.0) / mode_lib->soc.return_bus_width_bytes; + + DTRACE( + "minimum theoretical dcfclk without stutter and full utilization = %f MHz", + (*dcfclk_mhz)); + +} + +struct _vcs_dpi_display_pipe_clock_st dml_clks_get_pipe_clocks( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_pipes) +{ + struct _vcs_dpi_display_pipe_clock_st clocks; + double max_dispclk = 0.0; + double dcfclk; + double dispclks[DC__NUM_PIPES__MAX]; + double dppclks[DC__NUM_PIPES__MAX]; + bool dppdiv[DC__NUM_PIPES__MAX]; + unsigned int i; + + DTRACE("Calculating pipe clocks..."); + + /* this is the theoretical minimum, have to adjust based on valid values for soc */ + get_dcfclk(mode_lib, e2e, num_pipes, &dcfclk); + + /* if(dcfclk > soc.vnom.dcfclk_mhz) + * dcfclk = soc.vmax.dcfclk_mhz; + * else if(dcfclk > soc.vmin.dcfclk_mhz) + * dcfclk = soc.vnom.dcfclk_mhz; + * else + * dcfclk = soc.vmin.dcfclk_mhz; + */ + + dcfclk = dml_socbb_voltage_scaling( + &mode_lib->soc, + (enum voltage_state) e2e[0].clks_cfg.voltage).dcfclk_mhz; + clocks.dcfclk_mhz = dcfclk; + + get_plane_clks(mode_lib, e2e, num_pipes, dppclks, dispclks, dppdiv); + + for (i = 0; i < num_pipes; i++) { + max_dispclk = dml_max(max_dispclk, dispclks[i]); + } + + clocks.dispclk_mhz = max_dispclk; + DTRACE("dispclk: %f Mhz", clocks.dispclk_mhz); + DTRACE("dcfclk: %f Mhz", clocks.dcfclk_mhz); + + for (i = 0; i < num_pipes; i++) { + if (dppclks[i] * 2 < max_dispclk) + dppdiv[i] = 1; + + if (dppdiv[i]) + clocks.dppclk_div[i] = 1; + else + clocks.dppclk_div[i] = 0; + + clocks.dppclk_mhz[i] = max_dispclk / ((dppdiv[i]) ? 2.0 : 1.0); + DTRACE("dppclk%d: %f Mhz", i, clocks.dppclk_mhz[i]); + } + + return clocks; +} diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.h b/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.h new file mode 100644 index 000000000000..aed5f33bb04f --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.h @@ -0,0 +1,41 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef __DISPLAY_PIPE_CLOCKS_H__ +#define __DISPLAY_PIPE_CLOCKS_H__ + +#include "dml_common_defs.h" + +struct display_mode_lib; + +struct _vcs_dpi_display_pipe_clock_st dml_clks_get_pipe_clocks( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_pipes); + +bool dml_clks_pipe_clock_requirement_fit_power_constraint( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_dpp_in_grp); +#endif -- cgit From 19b7fe4a48efbe0f7e8c496b040c4eb16ff02313 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 16 Oct 2017 22:15:57 -0400 Subject: Revert "amdgpu/dc: inline a bunch of float operations." This reverts commit d1209512e028a917e6e70b13297ff185234ba24d. Unfortunately these clash with our DML update from the HW guys. Rerolling this after the fact won't save us anything anymore, unfortunately so we're back to non-inline for this. Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/calcs/dcn_calc_math.c | 29 +++++++++++++++++ .../gpu/drm/amd/display/dc/calcs/dcn_calc_math.h | 36 ++++------------------ 2 files changed, 35 insertions(+), 30 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.c index 05cf5f77ec60..a18474437990 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.c @@ -25,6 +25,25 @@ #include "dcn_calc_math.h" +float dcn_bw_mod(const float arg1, const float arg2) +{ + return arg1 - arg1 * ((int) (arg1 / arg2)); +} + +float dcn_bw_min2(const float arg1, const float arg2) +{ + return arg1 < arg2 ? arg1 : arg2; +} + +unsigned int dcn_bw_max(const unsigned int arg1, const unsigned int arg2) +{ + return arg1 > arg2 ? arg1 : arg2; +} +float dcn_bw_max2(const float arg1, const float arg2) +{ + return arg1 > arg2 ? arg1 : arg2; +} + float dcn_bw_floor2(const float arg, const float significance) { if (significance == 0) @@ -40,6 +59,16 @@ float dcn_bw_ceil2(const float arg, const float significance) return flr + 0.00001 >= arg ? arg : flr + significance; } +float dcn_bw_max3(float v1, float v2, float v3) +{ + return v3 > dcn_bw_max2(v1, v2) ? v3 : dcn_bw_max2(v1, v2); +} + +float dcn_bw_max5(float v1, float v2, float v3, float v4, float v5) +{ + return dcn_bw_max3(v1, v2, v3) > dcn_bw_max2(v4, v5) ? dcn_bw_max3(v1, v2, v3) : dcn_bw_max2(v4, v5); +} + float dcn_bw_pow(float a, float exp) { float temp; diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.h b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.h index 6f66d9d164d1..f46ab0e24ca1 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.h +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.h @@ -26,38 +26,14 @@ #ifndef _DCN_CALC_MATH_H_ #define _DCN_CALC_MATH_H_ -static inline float dcn_bw_mod(const float arg1, const float arg2) -{ - return arg1 - arg1 * ((int) (arg1 / arg2)); -} - -static inline float dcn_bw_min2(const float arg1, const float arg2) -{ - return arg1 < arg2 ? arg1 : arg2; -} - -static inline unsigned int dcn_bw_max(const unsigned int arg1, const unsigned int arg2) -{ - return arg1 > arg2 ? arg1 : arg2; -} - -static inline float dcn_bw_max2(const float arg1, const float arg2) -{ - return arg1 > arg2 ? arg1 : arg2; -} - -static inline float dcn_bw_max3(float v1, float v2, float v3) -{ - return v3 > dcn_bw_max2(v1, v2) ? v3 : dcn_bw_max2(v1, v2); -} - -static inline float dcn_bw_max5(float v1, float v2, float v3, float v4, float v5) -{ - return dcn_bw_max3(v1, v2, v3) > dcn_bw_max2(v4, v5) ? dcn_bw_max3(v1, v2, v3) : dcn_bw_max2(v4, v5); -} - +float dcn_bw_mod(const float arg1, const float arg2); +float dcn_bw_min2(const float arg1, const float arg2); +unsigned int dcn_bw_max(const unsigned int arg1, const unsigned int arg2); +float dcn_bw_max2(const float arg1, const float arg2); float dcn_bw_floor2(const float arg, const float significance); float dcn_bw_ceil2(const float arg, const float significance); +float dcn_bw_max3(float v1, float v2, float v3); +float dcn_bw_max5(float v1, float v2, float v3, float v4, float v5); float dcn_bw_pow(float a, float exp); float dcn_bw_log(float a, float b); -- cgit From 6d04ee9dc10149db842d41de66eca201c9d91b60 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 23 Aug 2017 16:43:17 -0400 Subject: drm/amd/display: Restructuring and cleaning up DML Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/calcs/dcn_calc_math.c | 16 + drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 103 +- drivers/gpu/drm/amd/display/dc/dc.h | 1 - .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 5 +- drivers/gpu/drm/amd/display/dc/dml/Makefile | 8 +- drivers/gpu/drm/amd/display/dc/dml/dc_features.h | 2 + .../drm/amd/display/dc/dml/display_mode_enums.h | 52 +- .../gpu/drm/amd/display/dc/dml/display_mode_lib.c | 7 +- .../gpu/drm/amd/display/dc/dml/display_mode_lib.h | 8 +- .../drm/amd/display/dc/dml/display_mode_structs.h | 898 +++--- .../drm/amd/display/dc/dml/display_mode_support.c | 2326 -------------- .../drm/amd/display/dc/dml/display_mode_support.h | 199 -- .../gpu/drm/amd/display/dc/dml/display_mode_vba.c | 3263 ++++++++++++++++++++ .../gpu/drm/amd/display/dc/dml/display_mode_vba.h | 410 +++ .../drm/amd/display/dc/dml/display_pipe_clocks.c | 377 +-- .../drm/amd/display/dc/dml/display_pipe_clocks.h | 8 +- .../drm/amd/display/dc/dml/display_rq_dlg_calc.c | 2457 ++++++--------- .../drm/amd/display/dc/dml/display_rq_dlg_calc.h | 151 +- .../amd/display/dc/dml/display_rq_dlg_helpers.c | 482 +-- .../amd/display/dc/dml/display_rq_dlg_helpers.h | 41 +- .../gpu/drm/amd/display/dc/dml/display_watermark.c | 1281 -------- .../gpu/drm/amd/display/dc/dml/display_watermark.h | 98 - .../amd/display/dc/dml/dml1_display_rq_dlg_calc.c | 1903 ++++++++++++ .../amd/display/dc/dml/dml1_display_rq_dlg_calc.h | 67 + .../gpu/drm/amd/display/dc/dml/dml_common_defs.c | 12 +- .../gpu/drm/amd/display/dc/dml/dml_common_defs.h | 8 +- .../gpu/drm/amd/display/dc/dml/soc_bounding_box.c | 48 +- .../gpu/drm/amd/display/dc/dml/soc_bounding_box.h | 9 +- 28 files changed, 7658 insertions(+), 6582 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_mode_support.h create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_watermark.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_watermark.h create mode 100644 drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c create mode 100644 drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.c index a18474437990..b6abe0f3bb15 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.c @@ -27,20 +27,36 @@ float dcn_bw_mod(const float arg1, const float arg2) { + if (arg1 != arg1) + return arg2; + if (arg2 != arg2) + return arg1; return arg1 - arg1 * ((int) (arg1 / arg2)); } float dcn_bw_min2(const float arg1, const float arg2) { + if (arg1 != arg1) + return arg2; + if (arg2 != arg2) + return arg1; return arg1 < arg2 ? arg1 : arg2; } unsigned int dcn_bw_max(const unsigned int arg1, const unsigned int arg2) { + if (arg1 != arg1) + return arg2; + if (arg2 != arg2) + return arg1; return arg1 > arg2 ? arg1 : arg2; } float dcn_bw_max2(const float arg1, const float arg2) { + if (arg1 != arg1) + return arg2; + if (arg2 != arg2) + return arg1; return arg1 > arg2 ? arg1 : arg2; } diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 6318f9f69c92..fd1db8dc2f35 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -386,10 +386,6 @@ static void pipe_ctx_to_e2e_pipe_params ( - pipe->stream->timing.v_addressable - pipe->stream->timing.v_border_bottom - pipe->stream->timing.v_border_top; - - input->dest.vsync_plus_back_porch = pipe->stream->timing.v_total - - pipe->stream->timing.v_addressable - - pipe->stream->timing.v_front_porch; input->dest.pixel_rate_mhz = pipe->stream->timing.pix_clk_khz/1000.0; input->dest.vstartup_start = pipe->pipe_dlg_param.vstartup_start; input->dest.vupdate_offset = pipe->pipe_dlg_param.vupdate_offset; @@ -459,9 +455,9 @@ static void dcn_bw_calc_rq_dlg_ttu( /*todo: soc->sr_enter_plus_exit_time??*/ dlg_sys_param.t_srx_delay_us = dc->dcn_ip->dcfclk_cstate_latency / v->dcf_clk_deep_sleep; - dml_rq_dlg_get_rq_params(dml, &rq_param, input.pipe.src); - extract_rq_regs(dml, rq_regs, rq_param); - dml_rq_dlg_get_dlg_params( + dml1_rq_dlg_get_rq_params(dml, &rq_param, input.pipe.src); + dml1_extract_rq_regs(dml, rq_regs, rq_param); + dml1_rq_dlg_get_dlg_params( dml, dlg_regs, ttu_regs, @@ -474,96 +470,6 @@ static void dcn_bw_calc_rq_dlg_ttu( pipe->plane_state->flip_immediate); } -static void dcn_dml_wm_override( - const struct dcn_bw_internal_vars *v, - struct display_mode_lib *dml, - struct dc_state *context, - const struct resource_pool *pool) -{ - int i, in_idx, active_count; - - struct _vcs_dpi_display_e2e_pipe_params_st *input = kzalloc(pool->pipe_count * sizeof(struct _vcs_dpi_display_e2e_pipe_params_st), - GFP_KERNEL); - struct wm { - double urgent; - struct _vcs_dpi_cstate_pstate_watermarks_st cpstate; - double pte_meta_urgent; - } a; - - - for (i = 0, in_idx = 0; i < pool->pipe_count; i++) { - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; - - if (!pipe->stream || !pipe->plane_state) - continue; - - input[in_idx].clks_cfg.dcfclk_mhz = v->dcfclk; - input[in_idx].clks_cfg.dispclk_mhz = v->dispclk; - input[in_idx].clks_cfg.dppclk_mhz = v->dppclk; - input[in_idx].clks_cfg.refclk_mhz = pool->ref_clock_inKhz / 1000; - input[in_idx].clks_cfg.socclk_mhz = v->socclk; - input[in_idx].clks_cfg.voltage = v->voltage_level; - input[in_idx].dout.output_format = (v->output_format[in_idx] == dcn_bw_420) ? dm_420 : dm_444; - input[in_idx].dout.output_type = (v->output[in_idx] == dcn_bw_hdmi) ? dm_hdmi : dm_dp; - //input[in_idx].dout.output_standard; - switch (v->output_deep_color[in_idx]) { - case dcn_bw_encoder_12bpc: - input[in_idx].dout.output_bpc = dm_out_12; - break; - case dcn_bw_encoder_10bpc: - input[in_idx].dout.output_bpc = dm_out_10; - break; - case dcn_bw_encoder_8bpc: - default: - input[in_idx].dout.output_bpc = dm_out_8; - break; - } - pipe_ctx_to_e2e_pipe_params(pipe, &input[in_idx].pipe); - dml_rq_dlg_get_rq_reg( - dml, - &pipe->rq_regs, - input[in_idx].pipe.src); - in_idx++; - } - active_count = in_idx; - - a.urgent = dml_wm_urgent_e2e(dml, input, active_count); - a.cpstate = dml_wm_cstate_pstate_e2e(dml, input, active_count); - a.pte_meta_urgent = dml_wm_pte_meta_urgent(dml, a.urgent); - - context->bw.dcn.watermarks.a.cstate_pstate.cstate_exit_ns = - a.cpstate.cstate_exit_us * 1000; - context->bw.dcn.watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns = - a.cpstate.cstate_enter_plus_exit_us * 1000; - context->bw.dcn.watermarks.a.cstate_pstate.pstate_change_ns = - a.cpstate.pstate_change_us * 1000; - context->bw.dcn.watermarks.a.pte_meta_urgent_ns = a.pte_meta_urgent * 1000; - context->bw.dcn.watermarks.a.urgent_ns = a.urgent * 1000; - context->bw.dcn.watermarks.b = context->bw.dcn.watermarks.a; - context->bw.dcn.watermarks.c = context->bw.dcn.watermarks.a; - context->bw.dcn.watermarks.d = context->bw.dcn.watermarks.a; - - - for (i = 0, in_idx = 0; i < pool->pipe_count; i++) { - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; - - if (!pipe->stream || !pipe->plane_state) - continue; - - dml_rq_dlg_get_dlg_reg(dml, - &pipe->dlg_regs, - &pipe->ttu_regs, - input, active_count, - in_idx, - true, - true, - v->pte_enable == dcn_bw_yes, - pipe->plane_state->flip_immediate); - in_idx++; - } - kfree(input); -} - static void split_stream_across_pipes( struct resource_context *res_ctx, const struct resource_pool *pool, @@ -1163,9 +1069,6 @@ bool dcn_validate_bandwidth( input_idx++; } - if (dc->debug.use_dml_wm) - dcn_dml_wm_override(v, (struct display_mode_lib *) - &dc->dml, context, pool); } if (v->voltage_level == 0) { diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index d624554efbc7..bf83459456a8 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -200,7 +200,6 @@ struct dc_debug { bool disable_hubp_power_gate; bool disable_pplib_wm_range; enum wm_report_mode pplib_wm_report_mode; - bool use_dml_wm; unsigned int min_disp_clk_khz; int sr_exit_time_dpm0_ns; int sr_enter_plus_exit_time_dpm0_ns; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 5d618e68a744..3000ddab2357 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -425,8 +425,6 @@ static const struct dc_debug debug_defaults_drv = { .disable_pplib_clock_request = true, .disable_pplib_wm_range = false, .pplib_wm_report_mode = WM_REPORT_DEFAULT, - .use_dml_wm = false, - .pipe_split_policy = MPC_SPLIT_AVOID_MULT_DISP, .disable_dcc = DCC_ENABLE, .voltage_align_fclk = true, @@ -439,8 +437,7 @@ static const struct dc_debug debug_defaults_diags = { .clock_trace = true, .disable_stutter = true, .disable_pplib_clock_request = true, - .disable_pplib_wm_range = true, - .use_dml_wm = false, + .disable_pplib_wm_range = true }; static void dcn10_dpp_destroy(struct transform **xfm) diff --git a/drivers/gpu/drm/amd/display/dc/dml/Makefile b/drivers/gpu/drm/amd/display/dc/dml/Makefile index 9d7791d00e97..c6d9d9530d75 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dml/Makefile @@ -3,19 +3,19 @@ # It provides the general basic services required by other DAL # subcomponents. +CFLAGS_display_mode_vba.o := -mhard-float -msse -mpreferred-stack-boundary=4 CFLAGS_display_mode_lib.o := -mhard-float -msse -mpreferred-stack-boundary=4 CFLAGS_display_pipe_clocks.o := -mhard-float -msse -mpreferred-stack-boundary=4 CFLAGS_display_rq_dlg_calc.o := -mhard-float -msse -mpreferred-stack-boundary=4 +CFLAGS_dml1_display_rq_dlg_calc.o := -mhard-float -msse -mpreferred-stack-boundary=4 CFLAGS_display_rq_dlg_helpers.o := -mhard-float -msse -mpreferred-stack-boundary=4 -CFLAGS_display_watermark.o := -mhard-float -msse -mpreferred-stack-boundary=4 CFLAGS_soc_bounding_box.o := -mhard-float -msse -mpreferred-stack-boundary=4 CFLAGS_dml_common_defs.o := -mhard-float -msse -mpreferred-stack-boundary=4 -CFLAGS_display_mode_support.o := -mhard-float -msse -mpreferred-stack-boundary=4 DML = display_mode_lib.o display_pipe_clocks.o display_rq_dlg_calc.o \ - display_rq_dlg_helpers.o display_watermark.o \ - soc_bounding_box.o dml_common_defs.o display_mode_support.o + display_rq_dlg_helpers.o dml1_display_rq_dlg_calc.o \ + soc_bounding_box.o dml_common_defs.o display_mode_vba.o AMD_DAL_DML = $(addprefix $(AMDDALPATH)/dc/dml/,$(DML)) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dc_features.h b/drivers/gpu/drm/amd/display/dc/dml/dc_features.h index 745c04cb764a..ea4cde952f4f 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dc_features.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dc_features.h @@ -25,9 +25,11 @@ #ifndef __DC_FEATURES_H__ #define __DC_FEATURES_H__ +// local features #define DC__PRESENT 1 #define DC__PRESENT__1 1 #define DC__NUM_DPP 4 +#define DC__VOLTAGE_STATES 7 #define DC__NUM_DPP__4 1 #define DC__NUM_DPP__0_PRESENT 1 #define DC__NUM_DPP__1_PRESENT 1 diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h index 143a3d418de0..eebaeb1fb61c 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h @@ -24,14 +24,12 @@ */ #ifndef __DISPLAY_MODE_ENUMS_H__ #define __DISPLAY_MODE_ENUMS_H__ + enum output_encoder_class { - dm_dp = 0, - dm_hdmi = 1, - dm_wb = 2 + dm_dp = 0, dm_hdmi = 1, dm_wb = 2 }; enum output_format_class { - dm_444 = 0, - dm_420 = 1 + dm_444 = 0, dm_420 = 1, dm_n422, dm_s422 }; enum source_format_class { dm_444_16 = 0, @@ -40,18 +38,14 @@ enum source_format_class { dm_420_8 = 3, dm_420_10 = 4, dm_422_8 = 5, - dm_422_10 = 6 + dm_422_10 = 6, + dm_444_8 = 7 }; enum output_bpc_class { - dm_out_6 = 0, - dm_out_8 = 1, - dm_out_10 = 2, - dm_out_12 = 3, - dm_out_16 = 4 + dm_out_6 = 0, dm_out_8 = 1, dm_out_10 = 2, dm_out_12 = 3, dm_out_16 = 4 }; enum scan_direction_class { - dm_horz = 0, - dm_vert = 1 + dm_horz = 0, dm_vert = 1 }; enum dm_swizzle_mode { dm_sw_linear = 0, @@ -84,28 +78,30 @@ enum dm_swizzle_mode { dm_sw_SPARE_14 = 27, dm_sw_SPARE_15 = 28, dm_sw_var_s_x = 29, - dm_sw_var_d_x = 30 + dm_sw_var_d_x = 30, + dm_sw_64kb_r_x }; enum lb_depth { - dm_lb_10 = 30, - dm_lb_8 = 24, - dm_lb_6 = 18, - dm_lb_12 = 36 + dm_lb_10 = 0, dm_lb_8 = 1, dm_lb_6 = 2, dm_lb_12 = 3, dm_lb_16 }; enum voltage_state { - dm_vmin = 0, - dm_vmid = 1, - dm_vnom = 2, - dm_vmax = 3, - dm_vmax_exceeded = 4 + dm_vmin = 0, dm_vmid = 1, dm_vnom = 2, dm_vmax = 3 }; enum source_macro_tile_size { - dm_4k_tile = 0, - dm_64k_tile = 1, - dm_256k_tile = 2 + dm_4k_tile = 0, dm_64k_tile = 1, dm_256k_tile = 2 }; enum cursor_bpp { - dm_cur_2bit = 0, - dm_cur_32bit = 1 + dm_cur_2bit = 0, dm_cur_32bit = 1, dm_cur_64bit = 2 }; +enum clock_change_support { + dm_dram_clock_change_uninitialized = 0, + dm_dram_clock_change_vactive, + dm_dram_clock_change_vblank, + dm_dram_clock_change_unsupported +}; + +enum output_standard { + dm_std_uninitialized = 0, dm_std_cvtr2, dm_std_cvt +}; + #endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c index c02c5522613b..09d232806de7 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c @@ -24,6 +24,7 @@ */ #include "display_mode_lib.h" +#include "dc_features.h" static void set_soc_bounding_box(struct _vcs_dpi_soc_bounding_box_st *soc, enum dml_project project) { @@ -128,11 +129,7 @@ static void set_ip_params(struct _vcs_dpi_ip_params_st *ip, enum dml_project pro static void set_mode_evaluation(struct _vcs_dpi_mode_evaluation_st *me, enum dml_project project) { - if (project == DML_PROJECT_RAVEN1) { - me->voltage_override = dm_vmin; - } else { - BREAK_TO_DEBUGGER(); /* Invalid Project Specified */ - } + me->voltage_override = dm_vmin; } void dml_init_instance(struct display_mode_lib *lib, enum dml_project project) diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h index e2e311138358..57f49d29c6b9 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h @@ -25,12 +25,13 @@ #ifndef __DISPLAY_MODE_LIB_H__ #define __DISPLAY_MODE_LIB_H__ + #include "dml_common_defs.h" #include "soc_bounding_box.h" -#include "display_watermark.h" +#include "display_mode_vba.h" #include "display_pipe_clocks.h" #include "display_rq_dlg_calc.h" -#include "display_mode_support.h" +#include "dml1_display_rq_dlg_calc.h" enum dml_project { DML_PROJECT_UNDEFINED, @@ -42,8 +43,7 @@ struct display_mode_lib { struct _vcs_dpi_soc_bounding_box_st soc; struct _vcs_dpi_mode_evaluation_st me; enum dml_project project; - struct dml_ms_internal_vars vars; - struct _vcs_dpi_wm_calc_pipe_params_st wm_param[DC__NUM_PIPES__MAX]; + struct vba_vars_st vba; struct dal_logger *logger; }; diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h index e589a5eadb6a..e5b7f7042e0b 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h @@ -25,405 +25,531 @@ #ifndef __DISPLAY_MODE_STRUCTS_H__ #define __DISPLAY_MODE_STRUCTS_H__ +typedef struct _vcs_dpi_voltage_scaling_st voltage_scaling_st; +typedef struct _vcs_dpi_soc_bounding_box_st soc_bounding_box_st; +typedef struct _vcs_dpi_mode_evaluation_st mode_evaluation_st; +typedef struct _vcs_dpi_ip_params_st ip_params_st; +typedef struct _vcs_dpi_display_pipe_source_params_st display_pipe_source_params_st; +typedef struct _vcs_dpi_display_output_params_st display_output_params_st; +typedef struct _vcs_dpi_display_bandwidth_st display_bandwidth_st; +typedef struct _vcs_dpi_scaler_ratio_depth_st scaler_ratio_depth_st; +typedef struct _vcs_dpi_scaler_taps_st scaler_taps_st; +typedef struct _vcs_dpi_display_pipe_dest_params_st display_pipe_dest_params_st; +typedef struct _vcs_dpi_display_pipe_params_st display_pipe_params_st; +typedef struct _vcs_dpi_display_clocks_and_cfg_st display_clocks_and_cfg_st; +typedef struct _vcs_dpi_display_e2e_pipe_params_st display_e2e_pipe_params_st; +typedef struct _vcs_dpi_dchub_buffer_sizing_st dchub_buffer_sizing_st; +typedef struct _vcs_dpi_watermarks_perf_st watermarks_perf_st; +typedef struct _vcs_dpi_cstate_pstate_watermarks_st cstate_pstate_watermarks_st; +typedef struct _vcs_dpi_wm_calc_pipe_params_st wm_calc_pipe_params_st; +typedef struct _vcs_dpi_vratio_pre_st vratio_pre_st; +typedef struct _vcs_dpi_display_data_rq_misc_params_st display_data_rq_misc_params_st; +typedef struct _vcs_dpi_display_data_rq_sizing_params_st display_data_rq_sizing_params_st; +typedef struct _vcs_dpi_display_data_rq_dlg_params_st display_data_rq_dlg_params_st; +typedef struct _vcs_dpi_display_cur_rq_dlg_params_st display_cur_rq_dlg_params_st; +typedef struct _vcs_dpi_display_rq_dlg_params_st display_rq_dlg_params_st; +typedef struct _vcs_dpi_display_rq_sizing_params_st display_rq_sizing_params_st; +typedef struct _vcs_dpi_display_rq_misc_params_st display_rq_misc_params_st; +typedef struct _vcs_dpi_display_rq_params_st display_rq_params_st; +typedef struct _vcs_dpi_display_dlg_regs_st display_dlg_regs_st; +typedef struct _vcs_dpi_display_ttu_regs_st display_ttu_regs_st; +typedef struct _vcs_dpi_display_data_rq_regs_st display_data_rq_regs_st; +typedef struct _vcs_dpi_display_rq_regs_st display_rq_regs_st; +typedef struct _vcs_dpi_display_dlg_sys_params_st display_dlg_sys_params_st; +typedef struct _vcs_dpi_display_dlg_prefetch_param_st display_dlg_prefetch_param_st; +typedef struct _vcs_dpi_display_pipe_clock_st display_pipe_clock_st; +typedef struct _vcs_dpi_display_arb_params_st display_arb_params_st; + +struct _vcs_dpi_mode_evaluation_st { + int voltage_override; +}; + struct _vcs_dpi_voltage_scaling_st { + int state; double dcfclk_mhz; + double socclk_mhz; + double dram_speed_mhz; + double fabricclk_mhz; double dispclk_mhz; - double dppclk_mhz; double dram_bw_per_chan_gbps; double phyclk_mhz; - double socclk_mhz; + double dppclk_mhz; }; -struct _vcs_dpi_soc_bounding_box_st { - double sr_exit_time_us; - double sr_enter_plus_exit_time_us; - double urgent_latency_us; - double writeback_latency_us; - double ideal_dram_bw_after_urgent_percent; - unsigned int max_request_size_bytes; - struct _vcs_dpi_voltage_scaling_st vmin; - struct _vcs_dpi_voltage_scaling_st vmid; - struct _vcs_dpi_voltage_scaling_st vnom; - struct _vcs_dpi_voltage_scaling_st vmax; - double downspread_percent; - double dram_page_open_time_ns; - double dram_rw_turnaround_time_ns; - double dram_return_buffer_per_channel_bytes; - unsigned int round_trip_ping_latency_dcfclk_cycles; - unsigned int urgent_out_of_order_return_per_channel_bytes; - unsigned int channel_interleave_bytes; - unsigned int num_banks; - unsigned int num_chans; - unsigned int vmm_page_size_bytes; - double dram_clock_change_latency_us; - double writeback_dram_clock_change_latency_us; - unsigned int return_bus_width_bytes; -}; - -struct _vcs_dpi_ip_params_st { - unsigned int rob_buffer_size_kbytes; - unsigned int det_buffer_size_kbytes; - unsigned int dpte_buffer_size_in_pte_reqs; - unsigned int dpp_output_buffer_pixels; - unsigned int opp_output_buffer_lines; - unsigned int pixel_chunk_size_kbytes; - unsigned char pte_enable; - unsigned int pte_chunk_size_kbytes; - unsigned int meta_chunk_size_kbytes; - unsigned int writeback_chunk_size_kbytes; - unsigned int line_buffer_size_bits; - unsigned int max_line_buffer_lines; +struct _vcs_dpi_soc_bounding_box_st { + double sr_exit_time_us; + double sr_enter_plus_exit_time_us; + double urgent_latency_us; + double writeback_latency_us; + double ideal_dram_bw_after_urgent_percent; + unsigned int max_request_size_bytes; + struct _vcs_dpi_voltage_scaling_st vmin; + struct _vcs_dpi_voltage_scaling_st vmid; + struct _vcs_dpi_voltage_scaling_st vnom; + struct _vcs_dpi_voltage_scaling_st vmax; + double downspread_percent; + double dram_page_open_time_ns; + double dram_rw_turnaround_time_ns; + double dram_return_buffer_per_channel_bytes; + double dram_channel_width_bytes; + double fabric_datapath_to_dcn_data_return_bytes; + double dcn_downspread_percent; + double dispclk_dppclk_vco_speed_mhz; + unsigned int round_trip_ping_latency_dcfclk_cycles; + unsigned int urgent_out_of_order_return_per_channel_bytes; + unsigned int channel_interleave_bytes; + unsigned int num_banks; + unsigned int num_chans; + unsigned int vmm_page_size_bytes; + double dram_clock_change_latency_us; + double writeback_dram_clock_change_latency_us; + unsigned int return_bus_width_bytes; + double xfc_bus_transport_time_us; + double xfc_xbuf_latency_tolerance_us; + struct _vcs_dpi_voltage_scaling_st clock_limits[7]; +}; + +struct _vcs_dpi_ip_params_st { + unsigned int max_inter_dcn_tile_repeaters; + unsigned int num_dsc; + unsigned int odm_capable; + unsigned int rob_buffer_size_kbytes; + unsigned int det_buffer_size_kbytes; + unsigned int dpte_buffer_size_in_pte_reqs; + unsigned int pde_proc_buffer_size_64k_reqs; + unsigned int dpp_output_buffer_pixels; + unsigned int opp_output_buffer_lines; + unsigned int pixel_chunk_size_kbytes; + unsigned char pte_enable; + unsigned int pte_chunk_size_kbytes; + unsigned int meta_chunk_size_kbytes; + unsigned int writeback_chunk_size_kbytes; + unsigned int line_buffer_size_bits; + unsigned int max_line_buffer_lines; + unsigned int writeback_luma_buffer_size_kbytes; + unsigned int writeback_chroma_buffer_size_kbytes; + unsigned int writeback_chroma_line_buffer_width_pixels; + unsigned int max_page_table_levels; + unsigned int max_num_dpp; + unsigned int max_num_wb; + unsigned int max_dchub_pscl_bw_pix_per_clk; + unsigned int max_pscl_lb_bw_pix_per_clk; + unsigned int max_lb_vscl_bw_pix_per_clk; + unsigned int max_vscl_hscl_bw_pix_per_clk; + double max_hscl_ratio; + double max_vscl_ratio; + unsigned int hscl_mults; + unsigned int vscl_mults; + unsigned int max_hscl_taps; + unsigned int max_vscl_taps; + unsigned int xfc_supported; + unsigned int ptoi_supported; + unsigned int xfc_fill_constant_bytes; + double dispclk_ramp_margin_percent; + double xfc_fill_bw_overhead_percent; + double underscan_factor; + unsigned int min_vblank_lines; + unsigned int dppclk_delay_subtotal; + unsigned int dispclk_delay_subtotal; + unsigned int dcfclk_cstate_latency; + unsigned int dppclk_delay_scl; + unsigned int dppclk_delay_scl_lb_only; + unsigned int dppclk_delay_cnvc_formatter; + unsigned int dppclk_delay_cnvc_cursor; + unsigned int is_line_buffer_bpp_fixed; + unsigned int line_buffer_fixed_bpp; + unsigned int dcc_supported; + unsigned int IsLineBufferBppFixed; unsigned int LineBufferFixedBpp; - unsigned int writeback_luma_buffer_size_kbytes; - unsigned int writeback_chroma_buffer_size_kbytes; - unsigned int max_num_dpp; - unsigned int max_num_wb; - unsigned int max_dchub_pscl_bw_pix_per_clk; - unsigned int max_pscl_lb_bw_pix_per_clk; - unsigned int max_lb_vscl_bw_pix_per_clk; - unsigned int max_vscl_hscl_bw_pix_per_clk; - double max_hscl_ratio; - double max_vscl_ratio; - unsigned int hscl_mults; - unsigned int vscl_mults; - unsigned int max_hscl_taps; - unsigned int max_vscl_taps; - double dispclk_ramp_margin_percent; - double underscan_factor; - unsigned int min_vblank_lines; - unsigned int dppclk_delay_subtotal; - unsigned int dispclk_delay_subtotal; - unsigned int dcfclk_cstate_latency; - unsigned int max_inter_dcn_tile_repeaters; unsigned int can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one; unsigned int bug_forcing_LC_req_same_size_fixed; }; -struct _vcs_dpi_display_pipe_source_params_st { - int source_format; - unsigned char dcc; - unsigned int dcc_rate; - unsigned char vm; - int source_scan; - int sw_mode; - int macro_tile_size; - unsigned char is_display_sw; - unsigned int viewport_width; - unsigned int viewport_height; - unsigned int viewport_width_c; - unsigned int viewport_height_c; - unsigned int data_pitch; - unsigned int data_pitch_c; - unsigned int meta_pitch; - unsigned int meta_pitch_c; - unsigned int cur0_src_width; - int cur0_bpp; - unsigned char is_hsplit; - unsigned int hsplit_grp; -}; - -struct _vcs_dpi_display_output_params_st { - int output_bpc; - int output_type; - int output_format; - int output_standard; -}; - -struct _vcs_dpi_display_bandwidth_st { - double total_bw_consumed_gbps; - double guaranteed_urgent_return_bw_gbps; -}; - -struct _vcs_dpi_scaler_ratio_depth_st { - double hscl_ratio; - double vscl_ratio; - double hscl_ratio_c; - double vscl_ratio_c; - double vinit; - double vinit_c; - double vinit_bot; - double vinit_bot_c; - int lb_depth; -}; - -struct _vcs_dpi_scaler_taps_st { - unsigned int htaps; - unsigned int vtaps; - unsigned int htaps_c; - unsigned int vtaps_c; -}; - -struct _vcs_dpi_display_pipe_dest_params_st { - unsigned int recout_width; - unsigned int recout_height; - unsigned int full_recout_width; - unsigned int full_recout_height; - unsigned int hblank_start; - unsigned int hblank_end; - unsigned int vblank_start; - unsigned int vblank_end; - unsigned int htotal; - unsigned int vtotal; - unsigned int vactive; - unsigned int vstartup_start; - unsigned int vupdate_offset; - unsigned int vupdate_width; - unsigned int vready_offset; - unsigned int vsync_plus_back_porch; - unsigned char interlaced; - unsigned char underscan; - double pixel_rate_mhz; - unsigned char syncronized_vblank_all_planes; -}; - -struct _vcs_dpi_display_pipe_params_st { - struct _vcs_dpi_display_pipe_source_params_st src; - struct _vcs_dpi_display_pipe_dest_params_st dest; - struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth; - struct _vcs_dpi_scaler_taps_st scale_taps; -}; - -struct _vcs_dpi_display_clocks_and_cfg_st { - int voltage; - double dppclk_mhz; - double refclk_mhz; - double dispclk_mhz; - double dcfclk_mhz; - double socclk_mhz; -}; - -struct _vcs_dpi_display_e2e_pipe_params_st { - struct _vcs_dpi_display_pipe_params_st pipe; - struct _vcs_dpi_display_output_params_st dout; - struct _vcs_dpi_display_clocks_and_cfg_st clks_cfg; -}; - -struct _vcs_dpi_dchub_buffer_sizing_st { - unsigned int swath_width_y; - unsigned int swath_height_y; - unsigned int swath_height_c; - unsigned int detail_buffer_size_y; -}; - -struct _vcs_dpi_watermarks_perf_st { - double stutter_eff_in_active_region_percent; - double urgent_latency_supported_us; - double non_urgent_latency_supported_us; - double dram_clock_change_margin_us; - double dram_access_eff_percent; -}; - -struct _vcs_dpi_cstate_pstate_watermarks_st { - double cstate_exit_us; - double cstate_enter_plus_exit_us; - double pstate_change_us; -}; - -struct _vcs_dpi_wm_calc_pipe_params_st { - unsigned int num_dpp; - int voltage; - int output_type; - double dcfclk_mhz; - double socclk_mhz; - double dppclk_mhz; - double pixclk_mhz; - unsigned char interlace_en; - unsigned char pte_enable; - unsigned char dcc_enable; - double dcc_rate; - double bytes_per_pixel_c; - double bytes_per_pixel_y; - unsigned int swath_width_y; - unsigned int swath_height_y; - unsigned int swath_height_c; - unsigned int det_buffer_size_y; - double h_ratio; - double v_ratio; - unsigned int h_taps; - unsigned int h_total; - unsigned int v_total; - unsigned int v_active; - unsigned int e2e_index; - double display_pipe_line_delivery_time; - double read_bw; - unsigned int lines_in_det_y; - unsigned int lines_in_det_y_rounded_down_to_swath; - double full_det_buffering_time; - double dcfclk_deepsleep_mhz_per_plane; -}; - -struct _vcs_dpi_vratio_pre_st { - double vratio_pre_l; - double vratio_pre_c; -}; - -struct _vcs_dpi_display_data_rq_misc_params_st { - unsigned int full_swath_bytes; - unsigned int stored_swath_bytes; - unsigned int blk256_height; - unsigned int blk256_width; - unsigned int req_height; - unsigned int req_width; -}; - -struct _vcs_dpi_display_data_rq_sizing_params_st { - unsigned int chunk_bytes; - unsigned int min_chunk_bytes; - unsigned int meta_chunk_bytes; - unsigned int min_meta_chunk_bytes; - unsigned int mpte_group_bytes; - unsigned int dpte_group_bytes; -}; - -struct _vcs_dpi_display_data_rq_dlg_params_st { - unsigned int swath_width_ub; - unsigned int swath_height; - unsigned int req_per_swath_ub; - unsigned int meta_pte_bytes_per_frame_ub; - unsigned int dpte_req_per_row_ub; - unsigned int dpte_groups_per_row_ub; - unsigned int dpte_row_height; - unsigned int dpte_bytes_per_row_ub; - unsigned int meta_chunks_per_row_ub; - unsigned int meta_req_per_row_ub; - unsigned int meta_row_height; - unsigned int meta_bytes_per_row_ub; -}; - -struct _vcs_dpi_display_cur_rq_dlg_params_st { - unsigned char enable; - unsigned int swath_height; - unsigned int req_per_line; -}; - -struct _vcs_dpi_display_rq_dlg_params_st { - struct _vcs_dpi_display_data_rq_dlg_params_st rq_l; - struct _vcs_dpi_display_data_rq_dlg_params_st rq_c; - struct _vcs_dpi_display_cur_rq_dlg_params_st rq_cur0; -}; - -struct _vcs_dpi_display_rq_sizing_params_st { - struct _vcs_dpi_display_data_rq_sizing_params_st rq_l; - struct _vcs_dpi_display_data_rq_sizing_params_st rq_c; -}; - -struct _vcs_dpi_display_rq_misc_params_st { - struct _vcs_dpi_display_data_rq_misc_params_st rq_l; - struct _vcs_dpi_display_data_rq_misc_params_st rq_c; -}; - -struct _vcs_dpi_display_rq_params_st { - unsigned char yuv420; - unsigned char yuv420_10bpc; - struct _vcs_dpi_display_rq_misc_params_st misc; - struct _vcs_dpi_display_rq_sizing_params_st sizing; - struct _vcs_dpi_display_rq_dlg_params_st dlg; -}; - -struct _vcs_dpi_display_dlg_regs_st { - unsigned int refcyc_h_blank_end; - unsigned int dlg_vblank_end; - unsigned int min_dst_y_next_start; - unsigned int refcyc_per_htotal; - unsigned int refcyc_x_after_scaler; - unsigned int dst_y_after_scaler; - unsigned int dst_y_prefetch; - unsigned int dst_y_per_vm_vblank; - unsigned int dst_y_per_row_vblank; - unsigned int ref_freq_to_pix_freq; - unsigned int vratio_prefetch; - unsigned int vratio_prefetch_c; - unsigned int refcyc_per_pte_group_vblank_l; - unsigned int refcyc_per_pte_group_vblank_c; - unsigned int refcyc_per_meta_chunk_vblank_l; - unsigned int refcyc_per_meta_chunk_vblank_c; - unsigned int dst_y_per_pte_row_nom_l; - unsigned int dst_y_per_pte_row_nom_c; - unsigned int refcyc_per_pte_group_nom_l; - unsigned int refcyc_per_pte_group_nom_c; - unsigned int dst_y_per_meta_row_nom_l; - unsigned int dst_y_per_meta_row_nom_c; - unsigned int refcyc_per_meta_chunk_nom_l; - unsigned int refcyc_per_meta_chunk_nom_c; - unsigned int refcyc_per_line_delivery_pre_l; - unsigned int refcyc_per_line_delivery_pre_c; - unsigned int refcyc_per_line_delivery_l; - unsigned int refcyc_per_line_delivery_c; - unsigned int chunk_hdl_adjust_cur0; -}; - -struct _vcs_dpi_display_ttu_regs_st { - unsigned int qos_level_low_wm; - unsigned int qos_level_high_wm; - unsigned int min_ttu_vblank; - unsigned int qos_level_flip; - unsigned int refcyc_per_req_delivery_l; - unsigned int refcyc_per_req_delivery_c; - unsigned int refcyc_per_req_delivery_cur0; - unsigned int refcyc_per_req_delivery_pre_l; - unsigned int refcyc_per_req_delivery_pre_c; - unsigned int refcyc_per_req_delivery_pre_cur0; - unsigned int qos_level_fixed_l; - unsigned int qos_level_fixed_c; - unsigned int qos_level_fixed_cur0; - unsigned int qos_ramp_disable_l; - unsigned int qos_ramp_disable_c; - unsigned int qos_ramp_disable_cur0; -}; - -struct _vcs_dpi_display_data_rq_regs_st { - unsigned int chunk_size; - unsigned int min_chunk_size; - unsigned int meta_chunk_size; - unsigned int min_meta_chunk_size; - unsigned int dpte_group_size; - unsigned int mpte_group_size; - unsigned int swath_height; - unsigned int pte_row_height_linear; -}; - -struct _vcs_dpi_display_rq_regs_st { - struct _vcs_dpi_display_data_rq_regs_st rq_regs_l; - struct _vcs_dpi_display_data_rq_regs_st rq_regs_c; - unsigned int drq_expansion_mode; - unsigned int prq_expansion_mode; - unsigned int mrq_expansion_mode; - unsigned int crq_expansion_mode; - unsigned int plane1_base_address; -}; - -struct _vcs_dpi_display_dlg_sys_params_st { - double t_mclk_wm_us; - double t_urg_wm_us; - double t_sr_wm_us; - double t_extra_us; - double t_srx_delay_us; - double deepsleep_dcfclk_mhz; - double total_flip_bw; - unsigned int total_flip_bytes; -}; - -struct _vcs_dpi_display_dlg_prefetch_param_st { - double prefetch_bw; - unsigned int flip_bytes; -}; - -struct _vcs_dpi_display_pipe_clock_st { - double dcfclk_mhz; - double dispclk_mhz; - double dppclk_mhz[4]; - unsigned char dppclk_div[4]; -}; - -struct _vcs_dpi_display_arb_params_st { - int max_req_outstanding; - int min_req_outstanding; - int sat_level_us; -}; - -struct _vcs_dpi_mode_evaluation_st { - int voltage_override; +struct _vcs_dpi_display_xfc_params_st { + double xfc_tslv_vready_offset_us; + double xfc_tslv_vupdate_width_us; + double xfc_tslv_vupdate_offset_us; + int xfc_slv_chunk_size_bytes; +}; + +struct _vcs_dpi_display_pipe_source_params_st { + int source_format; + unsigned char dcc; + unsigned int dcc_override; + unsigned int dcc_rate; + unsigned char dcc_use_global; + unsigned char vm; + unsigned char vm_levels_force_en; + unsigned int vm_levels_force; + int source_scan; + int sw_mode; + int macro_tile_size; + unsigned char is_display_sw; + unsigned int viewport_width; + unsigned int viewport_height; + unsigned int viewport_y_y; + unsigned int viewport_y_c; + unsigned int viewport_width_c; + unsigned int viewport_height_c; + unsigned int data_pitch; + unsigned int data_pitch_c; + unsigned int meta_pitch; + unsigned int meta_pitch_c; + unsigned int cur0_src_width; + int cur0_bpp; + unsigned int cur1_src_width; + int cur1_bpp; + int num_cursors; + unsigned char is_hsplit; + unsigned char dynamic_metadata_enable; + unsigned int dynamic_metadata_lines_before_active; + unsigned int dynamic_metadata_xmit_bytes; + unsigned int hsplit_grp; + unsigned char xfc_enable; + unsigned char xfc_slave; + struct _vcs_dpi_display_xfc_params_st xfc_params; +}; +struct writeback_st { + int wb_src_height; + int wb_dst_width; + int wb_dst_height; + int wb_pixel_format; + int wb_htaps_luma; + int wb_vtaps_luma; + int wb_htaps_chroma; + int wb_vtaps_chroma; + int wb_hratio; + int wb_vratio; +}; + +struct _vcs_dpi_display_output_params_st { + int output_bpp; + int dsc_enable; + int wb_enable; + int output_bpc; + int output_type; + int output_format; + int output_standard; + int dsc_slices; + struct writeback_st wb; +}; + +struct _vcs_dpi_display_bandwidth_st { + double total_bw_consumed_gbps; + double guaranteed_urgent_return_bw_gbps; +}; + +struct _vcs_dpi_scaler_ratio_depth_st { + double hscl_ratio; + double vscl_ratio; + double hscl_ratio_c; + double vscl_ratio_c; + double vinit; + double vinit_c; + double vinit_bot; + double vinit_bot_c; + int lb_depth; + int scl_enable; +}; + +struct _vcs_dpi_scaler_taps_st { + unsigned int htaps; + unsigned int vtaps; + unsigned int htaps_c; + unsigned int vtaps_c; +}; + +struct _vcs_dpi_display_pipe_dest_params_st { + unsigned int recout_width; + unsigned int recout_height; + unsigned int full_recout_width; + unsigned int full_recout_height; + unsigned int hblank_start; + unsigned int hblank_end; + unsigned int vblank_start; + unsigned int vblank_end; + unsigned int htotal; + unsigned int vtotal; + unsigned int vactive; + unsigned int hactive; + unsigned int vstartup_start; + unsigned int vupdate_offset; + unsigned int vupdate_width; + unsigned int vready_offset; + unsigned char interlaced; + unsigned char underscan; + double pixel_rate_mhz; + unsigned char synchronized_vblank_all_planes; + unsigned char otg_inst; + unsigned char odm_split_cnt; + unsigned char odm_combine; +}; + +struct _vcs_dpi_display_pipe_params_st { + display_pipe_source_params_st src; + display_pipe_dest_params_st dest; + scaler_ratio_depth_st scale_ratio_depth; + scaler_taps_st scale_taps; +}; + +struct _vcs_dpi_display_clocks_and_cfg_st { + int voltage; + double dppclk_mhz; + double refclk_mhz; + double dispclk_mhz; + double dcfclk_mhz; + double socclk_mhz; +}; + +struct _vcs_dpi_display_e2e_pipe_params_st { + display_pipe_params_st pipe; + display_output_params_st dout; + display_clocks_and_cfg_st clks_cfg; +}; + +struct _vcs_dpi_dchub_buffer_sizing_st { + unsigned int swath_width_y; + unsigned int swath_height_y; + unsigned int swath_height_c; + unsigned int detail_buffer_size_y; +}; + +struct _vcs_dpi_watermarks_perf_st { + double stutter_eff_in_active_region_percent; + double urgent_latency_supported_us; + double non_urgent_latency_supported_us; + double dram_clock_change_margin_us; + double dram_access_eff_percent; +}; + +struct _vcs_dpi_cstate_pstate_watermarks_st { + double cstate_exit_us; + double cstate_enter_plus_exit_us; + double pstate_change_us; +}; + +struct _vcs_dpi_wm_calc_pipe_params_st { + unsigned int num_dpp; + int voltage; + int output_type; + double dcfclk_mhz; + double socclk_mhz; + double dppclk_mhz; + double pixclk_mhz; + unsigned char interlace_en; + unsigned char pte_enable; + unsigned char dcc_enable; + double dcc_rate; + double bytes_per_pixel_c; + double bytes_per_pixel_y; + unsigned int swath_width_y; + unsigned int swath_height_y; + unsigned int swath_height_c; + unsigned int det_buffer_size_y; + double h_ratio; + double v_ratio; + unsigned int h_taps; + unsigned int h_total; + unsigned int v_total; + unsigned int v_active; + unsigned int e2e_index; + double display_pipe_line_delivery_time; + double read_bw; + unsigned int lines_in_det_y; + unsigned int lines_in_det_y_rounded_down_to_swath; + double full_det_buffering_time; + double dcfclk_deepsleep_mhz_per_plane; +}; + +struct _vcs_dpi_vratio_pre_st { + double vratio_pre_l; + double vratio_pre_c; +}; + +struct _vcs_dpi_display_data_rq_misc_params_st { + unsigned int full_swath_bytes; + unsigned int stored_swath_bytes; + unsigned int blk256_height; + unsigned int blk256_width; + unsigned int req_height; + unsigned int req_width; +}; + +struct _vcs_dpi_display_data_rq_sizing_params_st { + unsigned int chunk_bytes; + unsigned int min_chunk_bytes; + unsigned int meta_chunk_bytes; + unsigned int min_meta_chunk_bytes; + unsigned int mpte_group_bytes; + unsigned int dpte_group_bytes; +}; + +struct _vcs_dpi_display_data_rq_dlg_params_st { + unsigned int swath_width_ub; + unsigned int swath_height; + unsigned int req_per_swath_ub; + unsigned int meta_pte_bytes_per_frame_ub; + unsigned int dpte_req_per_row_ub; + unsigned int dpte_groups_per_row_ub; + unsigned int dpte_row_height; + unsigned int dpte_bytes_per_row_ub; + unsigned int meta_chunks_per_row_ub; + unsigned int meta_req_per_row_ub; + unsigned int meta_row_height; + unsigned int meta_bytes_per_row_ub; +}; + +struct _vcs_dpi_display_cur_rq_dlg_params_st { + unsigned char enable; + unsigned int swath_height; + unsigned int req_per_line; +}; + +struct _vcs_dpi_display_rq_dlg_params_st { + display_data_rq_dlg_params_st rq_l; + display_data_rq_dlg_params_st rq_c; + display_cur_rq_dlg_params_st rq_cur0; +}; + +struct _vcs_dpi_display_rq_sizing_params_st { + display_data_rq_sizing_params_st rq_l; + display_data_rq_sizing_params_st rq_c; +}; + +struct _vcs_dpi_display_rq_misc_params_st { + display_data_rq_misc_params_st rq_l; + display_data_rq_misc_params_st rq_c; +}; + +struct _vcs_dpi_display_rq_params_st { + unsigned char yuv420; + unsigned char yuv420_10bpc; + display_rq_misc_params_st misc; + display_rq_sizing_params_st sizing; + display_rq_dlg_params_st dlg; +}; + +struct _vcs_dpi_display_dlg_regs_st { + unsigned int refcyc_h_blank_end; + unsigned int dlg_vblank_end; + unsigned int min_dst_y_next_start; + unsigned int refcyc_per_htotal; + unsigned int refcyc_x_after_scaler; + unsigned int dst_y_after_scaler; + unsigned int dst_y_prefetch; + unsigned int dst_y_per_vm_vblank; + unsigned int dst_y_per_row_vblank; + unsigned int dst_y_per_vm_flip; + unsigned int dst_y_per_row_flip; + unsigned int ref_freq_to_pix_freq; + unsigned int vratio_prefetch; + unsigned int vratio_prefetch_c; + unsigned int refcyc_per_pte_group_vblank_l; + unsigned int refcyc_per_pte_group_vblank_c; + unsigned int refcyc_per_meta_chunk_vblank_l; + unsigned int refcyc_per_meta_chunk_vblank_c; + unsigned int refcyc_per_pte_group_flip_l; + unsigned int refcyc_per_pte_group_flip_c; + unsigned int refcyc_per_meta_chunk_flip_l; + unsigned int refcyc_per_meta_chunk_flip_c; + unsigned int dst_y_per_pte_row_nom_l; + unsigned int dst_y_per_pte_row_nom_c; + unsigned int refcyc_per_pte_group_nom_l; + unsigned int refcyc_per_pte_group_nom_c; + unsigned int dst_y_per_meta_row_nom_l; + unsigned int dst_y_per_meta_row_nom_c; + unsigned int refcyc_per_meta_chunk_nom_l; + unsigned int refcyc_per_meta_chunk_nom_c; + unsigned int refcyc_per_line_delivery_pre_l; + unsigned int refcyc_per_line_delivery_pre_c; + unsigned int refcyc_per_line_delivery_l; + unsigned int refcyc_per_line_delivery_c; + unsigned int chunk_hdl_adjust_cur0; + unsigned int chunk_hdl_adjust_cur1; + unsigned int vready_after_vcount0; + unsigned int dst_y_offset_cur0; + unsigned int dst_y_offset_cur1; + unsigned int xfc_reg_transfer_delay; + unsigned int xfc_reg_precharge_delay; + unsigned int xfc_reg_remote_surface_flip_latency; + unsigned int xfc_reg_prefetch_margin; + unsigned int dst_y_delta_drq_limit; +}; + +struct _vcs_dpi_display_ttu_regs_st { + unsigned int qos_level_low_wm; + unsigned int qos_level_high_wm; + unsigned int min_ttu_vblank; + unsigned int qos_level_flip; + unsigned int refcyc_per_req_delivery_l; + unsigned int refcyc_per_req_delivery_c; + unsigned int refcyc_per_req_delivery_cur0; + unsigned int refcyc_per_req_delivery_cur1; + unsigned int refcyc_per_req_delivery_pre_l; + unsigned int refcyc_per_req_delivery_pre_c; + unsigned int refcyc_per_req_delivery_pre_cur0; + unsigned int refcyc_per_req_delivery_pre_cur1; + unsigned int qos_level_fixed_l; + unsigned int qos_level_fixed_c; + unsigned int qos_level_fixed_cur0; + unsigned int qos_level_fixed_cur1; + unsigned int qos_ramp_disable_l; + unsigned int qos_ramp_disable_c; + unsigned int qos_ramp_disable_cur0; + unsigned int qos_ramp_disable_cur1; +}; + +struct _vcs_dpi_display_data_rq_regs_st { + unsigned int chunk_size; + unsigned int min_chunk_size; + unsigned int meta_chunk_size; + unsigned int min_meta_chunk_size; + unsigned int dpte_group_size; + unsigned int mpte_group_size; + unsigned int swath_height; + unsigned int pte_row_height_linear; +}; + +struct _vcs_dpi_display_rq_regs_st { + display_data_rq_regs_st rq_regs_l; + display_data_rq_regs_st rq_regs_c; + unsigned int drq_expansion_mode; + unsigned int prq_expansion_mode; + unsigned int mrq_expansion_mode; + unsigned int crq_expansion_mode; + unsigned int plane1_base_address; +}; + +struct _vcs_dpi_display_dlg_sys_params_st { + double t_mclk_wm_us; + double t_urg_wm_us; + double t_sr_wm_us; + double t_extra_us; + double mem_trip_us; + double t_srx_delay_us; + double deepsleep_dcfclk_mhz; + double total_flip_bw; + unsigned int total_flip_bytes; +}; + +struct _vcs_dpi_display_dlg_prefetch_param_st { + double prefetch_bw; + unsigned int flip_bytes; +}; + +struct _vcs_dpi_display_pipe_clock_st { + double dcfclk_mhz; + double dispclk_mhz; + double socclk_mhz; + double dscclk_mhz[6]; + double dppclk_mhz[6]; +}; + +struct _vcs_dpi_display_arb_params_st { + int max_req_outstanding; + int min_req_outstanding; + int sat_level_us; }; #endif /*__DISPLAY_MODE_STRUCTS_H__*/ diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c deleted file mode 100644 index 3b4ee74527f5..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c +++ /dev/null @@ -1,2326 +0,0 @@ -/* - * Copyright 2017 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "display_mode_support.h" -#include "display_mode_lib.h" - -int dml_ms_check( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - int num_pipes) -{ - struct _vcs_dpi_ip_params_st *ip; - struct _vcs_dpi_soc_bounding_box_st *soc; - struct _vcs_dpi_mode_evaluation_st *me; - struct dml_ms_internal_vars *v; - int num_planes, i, j, ij, k, ijk; - - ip = &(mode_lib->ip); - soc = &(mode_lib->soc); - me = &(mode_lib->me); - v = &(mode_lib->vars); - num_planes = dml_wm_e2e_to_wm(mode_lib, e2e, num_pipes, v->planes); - - //instantiating variables to zero - v->MacroTileBlockWidthC = 0; - v->SwathWidthGranularityC = 0; - - v->DCFCLKPerState[5] = 0; - v->DCFCLKPerState[4] = 0; - v->DCFCLKPerState[3] = 0; - v->DCFCLKPerState[2] = 0; - v->DCFCLKPerState[1] = 0; - v->DCFCLKPerState[0] = 0; - - if (soc->vmin.dcfclk_mhz > 0) { - v->DCFCLKPerState[5] = soc->vmin.dcfclk_mhz; - v->DCFCLKPerState[4] = soc->vmin.dcfclk_mhz; - v->DCFCLKPerState[3] = soc->vmin.dcfclk_mhz; - v->DCFCLKPerState[2] = soc->vmin.dcfclk_mhz; - v->DCFCLKPerState[1] = soc->vmin.dcfclk_mhz; - v->DCFCLKPerState[0] = soc->vmin.dcfclk_mhz; - } - - if (soc->vmid.dcfclk_mhz > 0) { - v->DCFCLKPerState[5] = soc->vmid.dcfclk_mhz; - v->DCFCLKPerState[4] = soc->vmid.dcfclk_mhz; - v->DCFCLKPerState[3] = soc->vmid.dcfclk_mhz; - v->DCFCLKPerState[2] = soc->vmid.dcfclk_mhz; - v->DCFCLKPerState[1] = soc->vmid.dcfclk_mhz; - } - - if (soc->vnom.dcfclk_mhz > 0) { - v->DCFCLKPerState[5] = soc->vnom.dcfclk_mhz; - v->DCFCLKPerState[4] = soc->vnom.dcfclk_mhz; - v->DCFCLKPerState[3] = soc->vnom.dcfclk_mhz; - v->DCFCLKPerState[2] = soc->vnom.dcfclk_mhz; - } - - if (soc->vmax.dcfclk_mhz > 0) { - v->DCFCLKPerState[5] = soc->vmax.dcfclk_mhz; - v->DCFCLKPerState[4] = soc->vmax.dcfclk_mhz; - v->DCFCLKPerState[3] = soc->vmax.dcfclk_mhz; - } - - v->FabricAndDRAMBandwidthPerState[5] = 0; - v->FabricAndDRAMBandwidthPerState[4] = 0; - v->FabricAndDRAMBandwidthPerState[3] = 0; - v->FabricAndDRAMBandwidthPerState[2] = 0; - v->FabricAndDRAMBandwidthPerState[1] = 0; - v->FabricAndDRAMBandwidthPerState[0] = 0; - - if (soc->vmin.dram_bw_per_chan_gbps > 0) { - v->FabricAndDRAMBandwidthPerState[5] = soc->vmin.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[4] = soc->vmin.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[3] = soc->vmin.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[2] = soc->vmin.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[1] = soc->vmin.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[0] = soc->vmin.dram_bw_per_chan_gbps; - } - - if (soc->vmid.dram_bw_per_chan_gbps > 0) { - v->FabricAndDRAMBandwidthPerState[5] = soc->vmid.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[4] = soc->vmid.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[3] = soc->vmid.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[2] = soc->vmid.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[1] = soc->vmid.dram_bw_per_chan_gbps; - } - - if (soc->vnom.dram_bw_per_chan_gbps > 0) { - v->FabricAndDRAMBandwidthPerState[5] = soc->vnom.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[4] = soc->vnom.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[3] = soc->vnom.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[2] = soc->vnom.dram_bw_per_chan_gbps; - } - - if (soc->vmax.dram_bw_per_chan_gbps > 0) { - v->FabricAndDRAMBandwidthPerState[5] = soc->vmax.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[4] = soc->vmax.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[3] = soc->vmax.dram_bw_per_chan_gbps; - } - - v->PHYCLKPerState[5] = 0; - v->PHYCLKPerState[4] = 0; - v->PHYCLKPerState[3] = 0; - v->PHYCLKPerState[2] = 0; - v->PHYCLKPerState[1] = 0; - v->PHYCLKPerState[0] = 0; - - if (soc->vmin.phyclk_mhz > 0) { - v->PHYCLKPerState[5] = soc->vmin.phyclk_mhz; - v->PHYCLKPerState[4] = soc->vmin.phyclk_mhz; - v->PHYCLKPerState[3] = soc->vmin.phyclk_mhz; - v->PHYCLKPerState[2] = soc->vmin.phyclk_mhz; - v->PHYCLKPerState[1] = soc->vmin.phyclk_mhz; - v->PHYCLKPerState[0] = soc->vmin.phyclk_mhz; - } - - if (soc->vmid.phyclk_mhz > 0) { - v->PHYCLKPerState[5] = soc->vmid.phyclk_mhz; - v->PHYCLKPerState[4] = soc->vmid.phyclk_mhz; - v->PHYCLKPerState[3] = soc->vmid.phyclk_mhz; - v->PHYCLKPerState[2] = soc->vmid.phyclk_mhz; - v->PHYCLKPerState[1] = soc->vmid.phyclk_mhz; - } - - if (soc->vnom.phyclk_mhz > 0) { - v->PHYCLKPerState[5] = soc->vnom.phyclk_mhz; - v->PHYCLKPerState[4] = soc->vnom.phyclk_mhz; - v->PHYCLKPerState[3] = soc->vnom.phyclk_mhz; - v->PHYCLKPerState[2] = soc->vnom.phyclk_mhz; - } - - if (soc->vmax.phyclk_mhz > 0) { - v->PHYCLKPerState[5] = soc->vmax.phyclk_mhz; - v->PHYCLKPerState[4] = soc->vmax.phyclk_mhz; - v->PHYCLKPerState[3] = soc->vmax.phyclk_mhz; - } - - v->MaxDispclk[5] = 0; - v->MaxDispclk[4] = 0; - v->MaxDispclk[3] = 0; - v->MaxDispclk[2] = 0; - v->MaxDispclk[1] = 0; - v->MaxDispclk[0] = 0; - - if (soc->vmin.dispclk_mhz > 0) { - v->MaxDispclk[5] = soc->vmin.dispclk_mhz; - v->MaxDispclk[4] = soc->vmin.dispclk_mhz; - v->MaxDispclk[3] = soc->vmin.dispclk_mhz; - v->MaxDispclk[2] = soc->vmin.dispclk_mhz; - v->MaxDispclk[1] = soc->vmin.dispclk_mhz; - v->MaxDispclk[0] = soc->vmin.dispclk_mhz; - } - - if (soc->vmid.dispclk_mhz > 0) { - v->MaxDispclk[5] = soc->vmid.dispclk_mhz; - v->MaxDispclk[4] = soc->vmid.dispclk_mhz; - v->MaxDispclk[3] = soc->vmid.dispclk_mhz; - v->MaxDispclk[2] = soc->vmid.dispclk_mhz; - v->MaxDispclk[1] = soc->vmid.dispclk_mhz; - } - - if (soc->vnom.dispclk_mhz > 0) { - v->MaxDispclk[5] = soc->vnom.dispclk_mhz; - v->MaxDispclk[4] = soc->vnom.dispclk_mhz; - v->MaxDispclk[3] = soc->vnom.dispclk_mhz; - v->MaxDispclk[2] = soc->vnom.dispclk_mhz; - } - - if (soc->vmax.dispclk_mhz > 0) { - v->MaxDispclk[5] = soc->vmax.dispclk_mhz; - v->MaxDispclk[4] = soc->vmax.dispclk_mhz; - v->MaxDispclk[3] = soc->vmax.dispclk_mhz; - } - - v->MaxDppclk[5] = 0; - v->MaxDppclk[4] = 0; - v->MaxDppclk[3] = 0; - v->MaxDppclk[2] = 0; - v->MaxDppclk[1] = 0; - v->MaxDppclk[0] = 0; - - if (soc->vmin.dppclk_mhz > 0) { - v->MaxDppclk[5] = soc->vmin.dppclk_mhz; - v->MaxDppclk[4] = soc->vmin.dppclk_mhz; - v->MaxDppclk[3] = soc->vmin.dppclk_mhz; - v->MaxDppclk[2] = soc->vmin.dppclk_mhz; - v->MaxDppclk[1] = soc->vmin.dppclk_mhz; - v->MaxDppclk[0] = soc->vmin.dppclk_mhz; - } - - if (soc->vmid.dppclk_mhz > 0) { - v->MaxDppclk[5] = soc->vmid.dppclk_mhz; - v->MaxDppclk[4] = soc->vmid.dppclk_mhz; - v->MaxDppclk[3] = soc->vmid.dppclk_mhz; - v->MaxDppclk[2] = soc->vmid.dppclk_mhz; - v->MaxDppclk[1] = soc->vmid.dppclk_mhz; - } - - if (soc->vnom.dppclk_mhz > 0) { - v->MaxDppclk[5] = soc->vnom.dppclk_mhz; - v->MaxDppclk[4] = soc->vnom.dppclk_mhz; - v->MaxDppclk[3] = soc->vnom.dppclk_mhz; - v->MaxDppclk[2] = soc->vnom.dppclk_mhz; - } - - if (soc->vmax.dppclk_mhz > 0) { - v->MaxDppclk[5] = soc->vmax.dppclk_mhz; - v->MaxDppclk[4] = soc->vmax.dppclk_mhz; - v->MaxDppclk[3] = soc->vmax.dppclk_mhz; - } - - if (me->voltage_override == dm_vmax) { - v->VoltageOverrideLevel = NumberOfStates - 1; - } else if (me->voltage_override == dm_vnom) { - v->VoltageOverrideLevel = NumberOfStates - 2; - } else if (me->voltage_override == dm_vmid) { - v->VoltageOverrideLevel = NumberOfStates - 3; - } else { - v->VoltageOverrideLevel = 0; - } - - // Scale Ratio Support Check - - v->ScaleRatioSupport = 1; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = - e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; - struct _vcs_dpi_scaler_taps_st scale_taps = - e2e[v->planes[k].e2e_index].pipe.scale_taps; - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - - if (scale_ratio_depth.hscl_ratio > ip->max_hscl_ratio - || scale_ratio_depth.vscl_ratio > ip->max_vscl_ratio - || scale_ratio_depth.hscl_ratio > scale_taps.htaps - || scale_ratio_depth.vscl_ratio > scale_taps.vtaps - || (src.source_format != dm_444_64 && src.source_format != dm_444_32 - && src.source_format != dm_444_16 - && ((scale_ratio_depth.hscl_ratio / 2 - > scale_taps.htaps_c) - || (scale_ratio_depth.vscl_ratio / 2 - > scale_taps.vtaps_c)))) - - { - v->ScaleRatioSupport = 0; - } - } - - // Source Format, Pixel Format and Scan Support Check - - v->SourceFormatPixelAndScanSupport = 1; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - - if ((src.sw_mode == dm_sw_linear && src.source_scan != dm_horz) - || ((src.sw_mode == dm_sw_4kb_d || src.sw_mode == dm_sw_4kb_d_x - || src.sw_mode == dm_sw_64kb_d - || src.sw_mode == dm_sw_64kb_d_t - || src.sw_mode == dm_sw_64kb_d_x - || src.sw_mode == dm_sw_var_d - || src.sw_mode == dm_sw_var_d_x) - && (src.source_format != dm_444_64))) { - v->SourceFormatPixelAndScanSupport = 0; - } - } - - // Bandwidth Support Check - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - - if (src.source_scan == dm_horz) { - v->SwathWidthYSingleDPP[k] = src.viewport_width; - } else { - v->SwathWidthYSingleDPP[k] = src.viewport_height; - } - - if (src.source_format == dm_444_64) { - v->BytePerPixelInDETY[k] = 8; - v->BytePerPixelInDETC[k] = 0; - } else if (src.source_format == dm_444_32) { - v->BytePerPixelInDETY[k] = 4; - v->BytePerPixelInDETC[k] = 0; - } else if (src.source_format == dm_444_16) { - v->BytePerPixelInDETY[k] = 2; - v->BytePerPixelInDETC[k] = 0; - } else if (src.source_format == dm_420_8) { - v->BytePerPixelInDETY[k] = 1; - v->BytePerPixelInDETC[k] = 2; - } else { - v->BytePerPixelInDETY[k] = 4.00 / 3.00; - v->BytePerPixelInDETC[k] = 8.00 / 3.00; - } - } - - v->TotalReadBandwidthConsumedGBytePerSecond = 0; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - struct _vcs_dpi_display_pipe_dest_params_st dest = - e2e[v->planes[k].e2e_index].pipe.dest; - struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = - e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; - - v->ReadBandwidth[k] = - v->SwathWidthYSingleDPP[k] - * (dml_ceil_ex(v->BytePerPixelInDETY[k], 1) - * scale_ratio_depth.vscl_ratio - + (dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2) / 2) - * (scale_ratio_depth.vscl_ratio - / 2)) - / (dest.htotal / dest.pixel_rate_mhz); - - if (src.dcc == 1) { - v->ReadBandwidth[k] = v->ReadBandwidth[k] * (1 + 1 / 256); - } - - if (ip->pte_enable == 1 && src.source_scan != dm_horz - && (src.sw_mode == dm_sw_4kb_s || src.sw_mode == dm_sw_4kb_s_x - || src.sw_mode == dm_sw_4kb_d - || src.sw_mode == dm_sw_4kb_d_x)) { - v->ReadBandwidth[k] = v->ReadBandwidth[k] * (1 + 1 / 64); - } else if (ip->pte_enable == 1 && src.source_scan == dm_horz - && (src.source_format == dm_444_64 || src.source_format == dm_444_32) - && (src.sw_mode == dm_sw_64kb_s || src.sw_mode == dm_sw_64kb_s_t - || src.sw_mode == dm_sw_64kb_s_x - || src.sw_mode == dm_sw_64kb_d - || src.sw_mode == dm_sw_64kb_d_t - || src.sw_mode == dm_sw_64kb_d_x)) { - v->ReadBandwidth[k] = v->ReadBandwidth[k] * (1 + 1 / 256); - } else if (ip->pte_enable == 1) { - v->ReadBandwidth[k] = v->ReadBandwidth[k] * (1 + 1 / 512); - } - - v->TotalReadBandwidthConsumedGBytePerSecond = - v->TotalReadBandwidthConsumedGBytePerSecond - + v->ReadBandwidth[k] / 1000; - } - - v->TotalWriteBandwidthConsumedGBytePerSecond = 0; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_dest_params_st dest = - e2e[v->planes[k].e2e_index].pipe.dest; - struct _vcs_dpi_display_output_params_st dout = e2e[v->planes[k].e2e_index].dout; - - if (dout.output_type == dm_wb && dout.output_format == dm_444) { - v->WriteBandwidth[k] = dest.recout_width - / (dest.htotal / dest.pixel_rate_mhz) * 4; - } else if (dout.output_type == dm_wb) { - v->WriteBandwidth[k] = dest.recout_width - / (dest.htotal / dest.pixel_rate_mhz) * 1.5; - } else { - v->WriteBandwidth[k] = 0; - } - - v->TotalWriteBandwidthConsumedGBytePerSecond = - v->TotalWriteBandwidthConsumedGBytePerSecond - + v->WriteBandwidth[k] / 1000; - } - - v->TotalBandwidthConsumedGBytePerSecond = v->TotalReadBandwidthConsumedGBytePerSecond - + v->TotalWriteBandwidthConsumedGBytePerSecond; - - v->DCCEnabledInAnyPlane = 0; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - - if (src.dcc == 1) { - v->DCCEnabledInAnyPlane = 1; - } - } - - for (i = 0; i < NumberOfStatesPlusTwo; i++) { - v->ReturnBWToDCNPerState = dml_min( - soc->return_bus_width_bytes * v->DCFCLKPerState[i], - v->FabricAndDRAMBandwidthPerState[i] * 1000 - * soc->ideal_dram_bw_after_urgent_percent / 100); - - v->ReturnBWPerState[i] = v->ReturnBWToDCNPerState; - - if (v->DCCEnabledInAnyPlane == 1 - && v->ReturnBWToDCNPerState - > (v->DCFCLKPerState[i] - * soc->return_bus_width_bytes / 4)) { - v->ReturnBWPerState[i] = - dml_min( - v->ReturnBWPerState[i], - v->ReturnBWToDCNPerState * 4 - * (1 - - soc->urgent_latency_us - / ((ip->rob_buffer_size_kbytes - - ip->pixel_chunk_size_kbytes) - * 1024 - / (v->ReturnBWToDCNPerState - - v->DCFCLKPerState[i] - * soc->return_bus_width_bytes - / 4) - + soc->urgent_latency_us))); - } - - v->CriticalPoint = 2 * soc->return_bus_width_bytes * v->DCFCLKPerState[i] - * soc->urgent_latency_us - / (v->ReturnBWToDCNPerState * soc->urgent_latency_us - + (ip->rob_buffer_size_kbytes - - ip->pixel_chunk_size_kbytes) - * 1024); - - if (v->DCCEnabledInAnyPlane == 1 && v->CriticalPoint > 1 && v->CriticalPoint < 4) { - v->ReturnBWPerState[i] = - dml_min( - v->ReturnBWPerState[i], - 4 * v->ReturnBWToDCNPerState - * (ip->rob_buffer_size_kbytes - - ip->pixel_chunk_size_kbytes) - * 1024 - * soc->return_bus_width_bytes - * v->DCFCLKPerState[i] - * soc->urgent_latency_us - / dml_pow( - (v->ReturnBWToDCNPerState - * soc->urgent_latency_us - + (ip->rob_buffer_size_kbytes - - ip->pixel_chunk_size_kbytes) - * 1024), - 2)); - } - - v->ReturnBWToDCNPerState = dml_min( - soc->return_bus_width_bytes * v->DCFCLKPerState[i], - v->FabricAndDRAMBandwidthPerState[i] * 1000); - - if (v->DCCEnabledInAnyPlane == 1 - && v->ReturnBWToDCNPerState - > (v->DCFCLKPerState[i] - * soc->return_bus_width_bytes / 4)) { - v->ReturnBWPerState[i] = - dml_min( - v->ReturnBWPerState[i], - v->ReturnBWToDCNPerState * 4 - * (1 - - soc->urgent_latency_us - / ((ip->rob_buffer_size_kbytes - - ip->pixel_chunk_size_kbytes) - * 1024 - / (v->ReturnBWToDCNPerState - - v->DCFCLKPerState[i] - * soc->return_bus_width_bytes - / 4) - + soc->urgent_latency_us))); - } - - v->CriticalPoint = 2 * soc->return_bus_width_bytes * v->DCFCLKPerState[i] - * soc->urgent_latency_us - / (v->ReturnBWToDCNPerState * soc->urgent_latency_us - + (ip->rob_buffer_size_kbytes - - ip->pixel_chunk_size_kbytes) - * 1024); - - if (v->DCCEnabledInAnyPlane == 1 && v->CriticalPoint > 1 && v->CriticalPoint < 4) { - v->ReturnBWPerState[i] = - dml_min( - v->ReturnBWPerState[i], - 4 * v->ReturnBWToDCNPerState - * (ip->rob_buffer_size_kbytes - - ip->pixel_chunk_size_kbytes) - * 1024 - * soc->return_bus_width_bytes - * v->DCFCLKPerState[i] - * soc->urgent_latency_us - / dml_pow( - (v->ReturnBWToDCNPerState - * soc->urgent_latency_us - + (ip->rob_buffer_size_kbytes - - ip->pixel_chunk_size_kbytes) - * 1024), - 2)); - } - } - - for (i = 0; i < NumberOfStatesPlusTwo; i++) { - if ((v->TotalReadBandwidthConsumedGBytePerSecond * 1000 <= v->ReturnBWPerState[i]) - && (v->TotalBandwidthConsumedGBytePerSecond * 1000 - <= v->FabricAndDRAMBandwidthPerState[i] * 1000 - * soc->ideal_dram_bw_after_urgent_percent - / 100)) { - v->BandwidthSupport[i] = 1; - } else { - v->BandwidthSupport[i] = 0; - } - } - - // Writeback Latency support check - - v->WritebackLatencySupport = 1; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_dest_params_st dest = - e2e[v->planes[k].e2e_index].pipe.dest; - struct _vcs_dpi_display_output_params_st dout = e2e[v->planes[k].e2e_index].dout; - - if (dout.output_type == dm_wb && dout.output_format == dm_444 - && (dest.recout_width / (dest.htotal / dest.pixel_rate_mhz) * 4) - > ((ip->writeback_luma_buffer_size_kbytes - + ip->writeback_chroma_buffer_size_kbytes) - * 1024 / soc->writeback_latency_us)) { - v->WritebackLatencySupport = 0; - } else if (dout.output_type == dm_wb - && (dest.recout_width / (dest.htotal / dest.pixel_rate_mhz)) - > (dml_min( - ip->writeback_luma_buffer_size_kbytes, - 2 - * ip->writeback_chroma_buffer_size_kbytes) - * 1024 / soc->writeback_latency_us)) { - v->WritebackLatencySupport = 0; - } - } - - // Re-ordering Buffer Support Check - - for (i = 0; i < NumberOfStatesPlusTwo; i++) { - v->UrgentRoundTripAndOutOfOrderLatencyPerState[i] = - (soc->round_trip_ping_latency_dcfclk_cycles + 32) - / v->DCFCLKPerState[i] - + soc->urgent_out_of_order_return_per_channel_bytes - * soc->num_chans - / v->ReturnBWPerState[i]; - - if ((ip->rob_buffer_size_kbytes - ip->pixel_chunk_size_kbytes) * 1024 - / v->ReturnBWPerState[i] - > v->UrgentRoundTripAndOutOfOrderLatencyPerState[i]) { - v->ROBSupport[i] = 1; - } else { - v->ROBSupport[i] = 0; - } - } - - // Display IO Support Check - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_dest_params_st dest = - e2e[v->planes[k].e2e_index].pipe.dest; - struct _vcs_dpi_display_output_params_st dout = e2e[v->planes[k].e2e_index].dout; - - if (dout.output_format == dm_420) { - v->RequiredOutputBW = dest.pixel_rate_mhz * 3 / 2; - } else { - v->RequiredOutputBW = dest.pixel_rate_mhz * 3; - } - - if (dout.output_type == dm_hdmi) { - v->RequiredPHYCLK[k] = v->RequiredOutputBW / 3; - } else if (dout.output_type == dm_dp) { - v->RequiredPHYCLK[k] = v->RequiredOutputBW / 4; - } else { - v->RequiredPHYCLK[k] = 0; - } - } - - for (i = 0; i < NumberOfStatesPlusTwo; i++) { - v->DIOSupport[i] = 1; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_output_params_st dout = - e2e[v->planes[k].e2e_index].dout; - - if ((v->RequiredPHYCLK[k] > v->PHYCLKPerState[i]) - || (dout.output_type == dm_hdmi - && v->RequiredPHYCLK[k] > 600)) { - v->DIOSupport[i] = 0; - } - } - } - - // Total Available Writeback Support Check - - v->TotalNumberOfActiveWriteback = 0; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_output_params_st dout = e2e[v->planes[k].e2e_index].dout; - - if (dout.output_type == dm_wb) { - v->TotalNumberOfActiveWriteback = v->TotalNumberOfActiveWriteback + 1; - } - } - - if (v->TotalNumberOfActiveWriteback <= ip->max_num_wb) { - v->TotalAvailableWritebackSupport = 1; - } else { - v->TotalAvailableWritebackSupport = 0; - } - - // Maximum DISPCLK/DPPCLK Support check - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_dest_params_st dest = - e2e[v->planes[k].e2e_index].pipe.dest; - struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = - e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; - struct _vcs_dpi_scaler_taps_st scale_taps = - e2e[v->planes[k].e2e_index].pipe.scale_taps; - - if (scale_ratio_depth.hscl_ratio > 1) { - v->PSCL_FACTOR[k] = dml_min( - ip->max_dchub_pscl_bw_pix_per_clk, - ip->max_pscl_lb_bw_pix_per_clk - * scale_ratio_depth.hscl_ratio - / dml_ceil_ex(scale_taps.htaps / 6, 1)); - } else { - v->PSCL_FACTOR[k] = dml_min( - ip->max_dchub_pscl_bw_pix_per_clk, - ip->max_pscl_lb_bw_pix_per_clk); - } - - if (v->BytePerPixelInDETC[k] == 0) { - v->PSCL_FACTOR_CHROMA[k] = 0; - v->MinDPPCLKUsingSingleDPP[k] = - dest.pixel_rate_mhz - * dml_max( - scale_taps.vtaps / 6 - * dml_min( - 1, - scale_ratio_depth.hscl_ratio), - dml_max( - scale_ratio_depth.hscl_ratio - * scale_ratio_depth.vscl_ratio - / v->PSCL_FACTOR[k], - 1)); - - } else { - if (scale_ratio_depth.hscl_ratio / 2 > 1) { - v->PSCL_FACTOR_CHROMA[k] = dml_min( - ip->max_dchub_pscl_bw_pix_per_clk, - ip->max_pscl_lb_bw_pix_per_clk - * scale_ratio_depth.hscl_ratio / 2 - / dml_ceil_ex( - scale_taps.htaps_c - / 6, - 1)); - } else { - v->PSCL_FACTOR_CHROMA[k] = dml_min( - ip->max_dchub_pscl_bw_pix_per_clk, - ip->max_pscl_lb_bw_pix_per_clk); - } - v->MinDPPCLKUsingSingleDPP[k] = - dest.pixel_rate_mhz - * dml_max( - dml_max( - scale_taps.vtaps - / 6 - * dml_min( - 1, - scale_ratio_depth.hscl_ratio), - scale_ratio_depth.hscl_ratio - * scale_ratio_depth.vscl_ratio - / v->PSCL_FACTOR[k]), - dml_max( - dml_max( - scale_taps.vtaps_c - / 6 - * dml_min( - 1, - scale_ratio_depth.hscl_ratio - / 2), - scale_ratio_depth.hscl_ratio - * scale_ratio_depth.vscl_ratio - / 4 - / v->PSCL_FACTOR_CHROMA[k]), - 1)); - - } - } - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = - e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; - struct _vcs_dpi_scaler_taps_st scale_taps = - e2e[v->planes[k].e2e_index].pipe.scale_taps; - - if (src.source_format == dm_444_64 || src.source_format == dm_444_32 - || src.source_format == dm_444_16) { - if (src.sw_mode == dm_sw_linear) { - v->Read256BlockHeightY[k] = 1; - } else if (src.source_format == dm_444_64) { - v->Read256BlockHeightY[k] = 4; - } else { - v->Read256BlockHeightY[k] = 8; - } - - v->Read256BlockWidthY[k] = 256 / dml_ceil_ex(v->BytePerPixelInDETY[k], 1) - / v->Read256BlockHeightY[k]; - v->Read256BlockHeightC[k] = 0; - v->Read256BlockWidthC[k] = 0; - } else { - if (src.sw_mode == dm_sw_linear) { - v->Read256BlockHeightY[k] = 1; - v->Read256BlockHeightC[k] = 1; - } else if (src.source_format == dm_420_8) { - v->Read256BlockHeightY[k] = 16; - v->Read256BlockHeightC[k] = 8; - } else { - v->Read256BlockHeightY[k] = 8; - v->Read256BlockHeightC[k] = 8; - } - - v->Read256BlockWidthY[k] = 256 / dml_ceil_ex(v->BytePerPixelInDETY[k], 1) - / v->Read256BlockHeightY[k]; - v->Read256BlockWidthC[k] = 256 / dml_ceil_ex(v->BytePerPixelInDETC[k], 2) - / v->Read256BlockHeightC[k]; - } - - if (src.source_scan == dm_horz) { - v->MaxSwathHeightY[k] = v->Read256BlockHeightY[k]; - v->MaxSwathHeightC[k] = v->Read256BlockHeightC[k]; - } else { - v->MaxSwathHeightY[k] = v->Read256BlockWidthY[k]; - v->MaxSwathHeightC[k] = v->Read256BlockWidthC[k]; - } - - if (src.source_format == dm_444_64 || src.source_format == dm_444_32 - || src.source_format == dm_444_16) { - if (src.sw_mode == dm_sw_linear - || (src.source_format == dm_444_64 - && (src.sw_mode == dm_sw_4kb_s - || src.sw_mode - == dm_sw_4kb_s_x - || src.sw_mode - == dm_sw_64kb_s - || src.sw_mode - == dm_sw_64kb_s_t - || src.sw_mode - == dm_sw_64kb_s_x - || src.sw_mode - == dm_sw_var_s - || src.sw_mode - == dm_sw_var_s_x) - && src.source_scan == dm_horz)) { - v->MinSwathHeightY[k] = v->MaxSwathHeightY[k]; - } else { - v->MinSwathHeightY[k] = v->MaxSwathHeightY[k] / 2; - } - v->MinSwathHeightC[k] = v->MaxSwathHeightC[k]; - } else { - if (src.sw_mode == dm_sw_linear) { - v->MinSwathHeightY[k] = v->MaxSwathHeightY[k]; - v->MinSwathHeightC[k] = v->MaxSwathHeightC[k]; - } else if (src.source_format == dm_420_8 && src.source_scan == dm_horz) { - v->MinSwathHeightY[k] = v->MaxSwathHeightY[k] / 2; - if (ip->bug_forcing_LC_req_same_size_fixed == 1) { - v->MinSwathHeightC[k] = v->MaxSwathHeightC[k]; - } else { - v->MinSwathHeightC[k] = v->MaxSwathHeightC[k] / 2; - } - } else if (src.source_format == dm_420_10 && src.source_scan == dm_horz) { - v->MinSwathHeightC[k] = v->MaxSwathHeightC[k] / 2; - if (ip->bug_forcing_LC_req_same_size_fixed == 1) { - v->MinSwathHeightY[k] = v->MaxSwathHeightY[k]; - } else { - v->MinSwathHeightY[k] = v->MaxSwathHeightY[k] / 2; - } - } else { - v->MinSwathHeightY[k] = v->MaxSwathHeightY[k]; - v->MinSwathHeightC[k] = v->MaxSwathHeightC[k]; - } - } - - if (src.sw_mode == dm_sw_linear) { - v->MaximumSwathWidth = 8192; - } else { - v->MaximumSwathWidth = 5120; - } - - v->NumberOfDPPRequiredForDETSize = - dml_ceil_ex( - v->SwathWidthYSingleDPP[k] - / dml_min( - v->MaximumSwathWidth, - ip->det_buffer_size_kbytes - * 1024 - / 2 - / (v->BytePerPixelInDETY[k] - * v->MinSwathHeightY[k] - + v->BytePerPixelInDETC[k] - / 2 - * v->MinSwathHeightC[k])), - 1); - - if (v->BytePerPixelInDETC[k] == 0) { - v->NumberOfDPPRequiredForLBSize = - dml_ceil_ex( - (scale_taps.vtaps - + dml_max( - dml_ceil_ex( - scale_ratio_depth.vscl_ratio, - 1) - - 2, - 0)) - * v->SwathWidthYSingleDPP[k] - / dml_max( - scale_ratio_depth.hscl_ratio, - 1) - * scale_ratio_depth.lb_depth - / ip->line_buffer_size_bits, - 1); - } else { - v->NumberOfDPPRequiredForLBSize = - dml_max( - dml_ceil_ex( - (scale_taps.vtaps - + dml_max( - dml_ceil_ex( - scale_ratio_depth.vscl_ratio, - 1) - - 2, - 0)) - * v->SwathWidthYSingleDPP[k] - / dml_max( - scale_ratio_depth.hscl_ratio, - 1) - * scale_ratio_depth.lb_depth - / ip->line_buffer_size_bits, - 1), - dml_ceil_ex( - (scale_taps.vtaps_c - + dml_max( - dml_ceil_ex( - scale_ratio_depth.vscl_ratio - / 2, - 1) - - 2, - 0)) - * v->SwathWidthYSingleDPP[k] - / 2 - / dml_max( - scale_ratio_depth.hscl_ratio - / 2, - 1) - * scale_ratio_depth.lb_depth - / ip->line_buffer_size_bits, - 1)); - } - - v->NumberOfDPPRequiredForDETAndLBSize[k] = dml_max( - v->NumberOfDPPRequiredForDETSize, - v->NumberOfDPPRequiredForLBSize); - - } - - for (i = 0; i < NumberOfStatesPlusTwo; i++) { - for (j = 0; j < 2; j++) { - v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] = 0; - v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = 0; - v->DISPCLK_DPPCLK_Support[j * NumberOfStatesPlusTwo + i] = 1; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_dest_params_st dest = - e2e[v->planes[k].e2e_index].pipe.dest; - ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; - - v->MinDispclkUsingSingleDPP = dml_max( - dest.pixel_rate_mhz, - v->MinDPPCLKUsingSingleDPP[k] * (j + 1)) - * (1 + soc->downspread_percent / 100); - v->MinDispclkUsingDualDPP = dml_max( - dest.pixel_rate_mhz, - v->MinDPPCLKUsingSingleDPP[k] / 2 * (j + 1)) - * (1 + soc->downspread_percent / 100); - - if (i < NumberOfStates) { - v->MinDispclkUsingSingleDPP = - v->MinDispclkUsingSingleDPP - * (1 - + ip->dispclk_ramp_margin_percent - / 100); - v->MinDispclkUsingDualDPP = - v->MinDispclkUsingDualDPP - * (1 - + ip->dispclk_ramp_margin_percent - / 100); - } - - if (v->MinDispclkUsingSingleDPP - <= dml_min( - v->MaxDispclk[i], - (j + 1) * v->MaxDppclk[i]) - && v->NumberOfDPPRequiredForDETAndLBSize[k] <= 1) { - v->NoOfDPP[ijk] = 1; - v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = dml_max( - v->RequiredDISPCLK[j * NumberOfStatesPlusTwo - + i], - v->MinDispclkUsingSingleDPP); - } else if (v->MinDispclkUsingDualDPP - <= dml_min( - v->MaxDispclk[i], - (j + 1) * v->MaxDppclk[i])) { - v->NoOfDPP[ijk] = 2; - v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = dml_max( - v->RequiredDISPCLK[j * NumberOfStatesPlusTwo - + i], - v->MinDispclkUsingDualDPP); - } else { - v->NoOfDPP[ijk] = 2; - v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = dml_max( - v->RequiredDISPCLK[j * NumberOfStatesPlusTwo - + i], - v->MinDispclkUsingDualDPP); - v->DISPCLK_DPPCLK_Support[j * NumberOfStatesPlusTwo + i] = - 0; - } - - v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] = - v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo - + i] + v->NoOfDPP[ijk]; - } - - if (v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] - > ip->max_num_dpp) { - v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] = 0; - v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = 0; - v->DISPCLK_DPPCLK_Support[j * NumberOfStatesPlusTwo + i] = 1; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_dest_params_st dest = - e2e[v->planes[k].e2e_index].pipe.dest; - ijk = k * 2 * NumberOfStatesPlusTwo - + j * NumberOfStatesPlusTwo + i; - - v->MinDispclkUsingSingleDPP = dml_max( - dest.pixel_rate_mhz, - v->MinDPPCLKUsingSingleDPP[k] * (j + 1)) - * (1 + soc->downspread_percent / 100); - v->MinDispclkUsingDualDPP = dml_max( - dest.pixel_rate_mhz, - v->MinDPPCLKUsingSingleDPP[k] / 2 * (j + 1)) - * (1 + soc->downspread_percent / 100); - - if (i < NumberOfStates) { - v->MinDispclkUsingSingleDPP = - v->MinDispclkUsingSingleDPP - * (1 - + ip->dispclk_ramp_margin_percent - / 100); - v->MinDispclkUsingDualDPP = - v->MinDispclkUsingDualDPP - * (1 - + ip->dispclk_ramp_margin_percent - / 100); - } - - if (v->NumberOfDPPRequiredForDETAndLBSize[k] <= 1) { - v->NoOfDPP[ijk] = 1; - v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = - dml_max( - v->RequiredDISPCLK[j - * NumberOfStatesPlusTwo - + i], - v->MinDispclkUsingSingleDPP); - if (v->MinDispclkUsingSingleDPP - > dml_min( - v->MaxDispclk[i], - (j + 1) - * v->MaxDppclk[i])) { - v->DISPCLK_DPPCLK_Support[j - * NumberOfStatesPlusTwo + i] = - 0; - } - } else { - v->NoOfDPP[ijk] = 2; - v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = - dml_max( - v->RequiredDISPCLK[j - * NumberOfStatesPlusTwo - + i], - v->MinDispclkUsingDualDPP); - if (v->MinDispclkUsingDualDPP - > dml_min( - v->MaxDispclk[i], - (j + 1) - * v->MaxDppclk[i])) { - v->DISPCLK_DPPCLK_Support[j - * NumberOfStatesPlusTwo + i] = - 0; - } - } - v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] = - v->TotalNumberOfActiveDPP[j - * NumberOfStatesPlusTwo + i] - + v->NoOfDPP[ijk]; - } - } - } - } - - // Viewport Size Check - - v->ViewportSizeSupport = 1; - - for (k = 0; k < num_planes; k++) { - if (v->NumberOfDPPRequiredForDETAndLBSize[k] > 2) { - v->ViewportSizeSupport = 0; - } - } - - // Total Available Pipes Support Check - - for (i = 0; i < NumberOfStatesPlusTwo; i++) { - for (j = 0; j < 2; j++) { - if (v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] - <= ip->max_num_dpp) { - v->TotalAvailablePipesSupport[j * NumberOfStatesPlusTwo + i] = 1; - } else { - v->TotalAvailablePipesSupport[j * NumberOfStatesPlusTwo + i] = 0; - } - } - } - - // Urgent Latency Support Check - - for (j = 0; j < 2; j++) { - for (i = 0; i < NumberOfStatesPlusTwo; i++) { - ij = j * NumberOfStatesPlusTwo + i; - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - struct _vcs_dpi_display_pipe_dest_params_st dest = - e2e[v->planes[k].e2e_index].pipe.dest; - struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = - e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; - struct _vcs_dpi_scaler_taps_st scale_taps = - e2e[v->planes[k].e2e_index].pipe.scale_taps; - ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; - - v->SwathWidthYPerState[ijk] = v->SwathWidthYSingleDPP[k] - / v->NoOfDPP[ijk]; - - v->SwathWidthGranularityY = 256 - / dml_ceil_ex(v->BytePerPixelInDETY[k], 1) - / v->MaxSwathHeightY[k]; - v->RoundedUpMaxSwathSizeBytesY = (dml_ceil_ex( - v->SwathWidthYPerState[ijk] - 1, - v->SwathWidthGranularityY) - + v->SwathWidthGranularityY) - * v->BytePerPixelInDETY[k] * v->MaxSwathHeightY[k]; - if (src.source_format == dm_420_10) { - v->RoundedUpMaxSwathSizeBytesY = dml_ceil_ex( - v->RoundedUpMaxSwathSizeBytesY, - 256) + 256; - } - if (v->MaxSwathHeightC[k] > 0) { - v->SwathWidthGranularityC = 256 - / dml_ceil_ex(v->BytePerPixelInDETC[k], 2) - / v->MaxSwathHeightC[k]; - } - v->RoundedUpMaxSwathSizeBytesC = (dml_ceil_ex( - v->SwathWidthYPerState[ijk] / 2 - 1, - v->SwathWidthGranularityC) - + v->SwathWidthGranularityC) - * v->BytePerPixelInDETC[k] * v->MaxSwathHeightC[k]; - if (src.source_format == dm_420_10) { - v->RoundedUpMaxSwathSizeBytesC = dml_ceil_ex( - v->RoundedUpMaxSwathSizeBytesC, - 256) + 256; - } - - if (v->RoundedUpMaxSwathSizeBytesY + v->RoundedUpMaxSwathSizeBytesC - <= ip->det_buffer_size_kbytes * 1024 / 2) { - v->SwathHeightYPerState[ijk] = v->MaxSwathHeightY[k]; - v->SwathHeightCPerState[ijk] = v->MaxSwathHeightC[k]; - } else { - v->SwathHeightYPerState[ijk] = v->MinSwathHeightY[k]; - v->SwathHeightCPerState[ijk] = v->MinSwathHeightC[k]; - } - - if (v->BytePerPixelInDETC[k] == 0) { - v->LinesInDETLuma = ip->det_buffer_size_kbytes * 1024 - / v->BytePerPixelInDETY[k] - / v->SwathWidthYPerState[ijk]; - - v->LinesInDETChroma = 0; - } else if (v->SwathHeightYPerState[ijk] - <= v->SwathHeightCPerState[ijk]) { - v->LinesInDETLuma = ip->det_buffer_size_kbytes * 1024 / 2 - / v->BytePerPixelInDETY[k] - / v->SwathWidthYPerState[ijk]; - v->LinesInDETChroma = ip->det_buffer_size_kbytes * 1024 / 2 - / v->BytePerPixelInDETC[k] - / (v->SwathWidthYPerState[ijk] / 2); - } else { - v->LinesInDETLuma = ip->det_buffer_size_kbytes * 1024 * 2 - / 3 / v->BytePerPixelInDETY[k] - / v->SwathWidthYPerState[ijk]; - v->LinesInDETChroma = ip->det_buffer_size_kbytes * 1024 / 3 - / v->BytePerPixelInDETY[k] - / (v->SwathWidthYPerState[ijk] / 2); - } - - v->EffectiveLBLatencyHidingSourceLinesLuma = - dml_min( - ip->max_line_buffer_lines, - dml_floor_ex( - ip->line_buffer_size_bits - / scale_ratio_depth.lb_depth - / (v->SwathWidthYPerState[ijk] - / dml_max( - scale_ratio_depth.hscl_ratio, - 1)), - 1)) - - (scale_taps.vtaps - 1); - - v->EffectiveLBLatencyHidingSourceLinesChroma = - dml_min( - ip->max_line_buffer_lines, - dml_floor_ex( - ip->line_buffer_size_bits - / scale_ratio_depth.lb_depth - / (v->SwathWidthYPerState[ijk] - / 2 - / dml_max( - scale_ratio_depth.hscl_ratio - / 2, - 1)), - 1)) - - (scale_taps.vtaps_c - 1); - - v->EffectiveDETLBLinesLuma = - dml_floor_ex( - v->LinesInDETLuma - + dml_min( - v->LinesInDETLuma - * v->RequiredDISPCLK[ij] - * v->BytePerPixelInDETY[k] - * v->PSCL_FACTOR[k] - / v->ReturnBWPerState[i], - v->EffectiveLBLatencyHidingSourceLinesLuma), - v->SwathHeightYPerState[ijk]); - - v->EffectiveDETLBLinesChroma = - dml_floor_ex( - v->LinesInDETChroma - + dml_min( - v->LinesInDETChroma - * v->RequiredDISPCLK[ij] - * v->BytePerPixelInDETC[k] - * v->PSCL_FACTOR_CHROMA[k] - / v->ReturnBWPerState[i], - v->EffectiveLBLatencyHidingSourceLinesChroma), - v->SwathHeightCPerState[ijk]); - - if (v->BytePerPixelInDETC[k] == 0) { - v->UrgentLatencySupportUsPerState[ijk] = - v->EffectiveDETLBLinesLuma - * (dest.htotal - / dest.pixel_rate_mhz) - / scale_ratio_depth.vscl_ratio - - v->EffectiveDETLBLinesLuma - * v->SwathWidthYPerState[ijk] - * dml_ceil_ex( - v->BytePerPixelInDETY[k], - 1) - / (v->ReturnBWPerState[i] - / v->NoOfDPP[ijk]); - } else { - v->UrgentLatencySupportUsPerState[ijk] = - dml_min( - v->EffectiveDETLBLinesLuma - * (dest.htotal - / dest.pixel_rate_mhz) - / scale_ratio_depth.vscl_ratio - - v->EffectiveDETLBLinesLuma - * v->SwathWidthYPerState[ijk] - * dml_ceil_ex( - v->BytePerPixelInDETY[k], - 1) - / (v->ReturnBWPerState[i] - / v->NoOfDPP[ijk]), - v->EffectiveDETLBLinesChroma - * (dest.htotal - / dest.pixel_rate_mhz) - / (scale_ratio_depth.vscl_ratio - / 2) - - v->EffectiveDETLBLinesChroma - * v->SwathWidthYPerState[ijk] - / 2 - * dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2) - / (v->ReturnBWPerState[i] - / v->NoOfDPP[ijk])); - } - - } - } - } - - for (i = 0; i < NumberOfStatesPlusTwo; i++) { - for (j = 0; j < 2; j++) { - ij = j * NumberOfStatesPlusTwo + i; - - v->UrgentLatencySupport[ij] = 1; - for (k = 0; k < num_planes; k++) { - ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; - - if (v->UrgentLatencySupportUsPerState[ijk] - < soc->urgent_latency_us / 1) { - v->UrgentLatencySupport[ij] = 0; - } - } - } - } - - // Prefetch Check - - for (i = 0; i < NumberOfStatesPlusTwo; i++) { - for (j = 0; j < 2; j++) { - ij = j * NumberOfStatesPlusTwo + i; - - v->TotalNumberOfDCCActiveDPP[ij] = 0; - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; - - if (src.dcc == 1) { - v->TotalNumberOfDCCActiveDPP[ij] = - v->TotalNumberOfDCCActiveDPP[ij] - + v->NoOfDPP[ijk]; - } - } - } - } - - for (i = 0; i < NumberOfStatesPlusTwo; i++) { - for (j = 0; j < 2; j++) { - ij = j * NumberOfStatesPlusTwo + i; - - v->ProjectedDCFCLKDeepSleep = 8; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_dest_params_st dest = - e2e[v->planes[k].e2e_index].pipe.dest; - struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = - e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; - ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; - - v->ProjectedDCFCLKDeepSleep = dml_max( - v->ProjectedDCFCLKDeepSleep, - dest.pixel_rate_mhz / 16); - if (v->BytePerPixelInDETC[k] == 0) { - if (scale_ratio_depth.vscl_ratio <= 1) { - v->ProjectedDCFCLKDeepSleep = - dml_max( - v->ProjectedDCFCLKDeepSleep, - 1.1 - * dml_ceil_ex( - v->BytePerPixelInDETY[k], - 1) - / 64 - * scale_ratio_depth.hscl_ratio - * dest.pixel_rate_mhz - / v->NoOfDPP[ijk]); - } else { - v->ProjectedDCFCLKDeepSleep = - dml_max( - v->ProjectedDCFCLKDeepSleep, - 1.1 - * dml_ceil_ex( - v->BytePerPixelInDETY[k], - 1) - / 64 - * v->PSCL_FACTOR[k] - * v->RequiredDISPCLK[ij] - / (1 - + j)); - } - - } else { - if (scale_ratio_depth.vscl_ratio <= 1) { - v->ProjectedDCFCLKDeepSleep = - dml_max( - v->ProjectedDCFCLKDeepSleep, - 1.1 - * dml_ceil_ex( - v->BytePerPixelInDETY[k], - 1) - / 32 - * scale_ratio_depth.hscl_ratio - * dest.pixel_rate_mhz - / v->NoOfDPP[ijk]); - } else { - v->ProjectedDCFCLKDeepSleep = - dml_max( - v->ProjectedDCFCLKDeepSleep, - 1.1 - * dml_ceil_ex( - v->BytePerPixelInDETY[k], - 1) - / 32 - * v->PSCL_FACTOR[k] - * v->RequiredDISPCLK[ij] - / (1 - + j)); - } - if ((scale_ratio_depth.vscl_ratio / 2) <= 1) { - v->ProjectedDCFCLKDeepSleep = - dml_max( - v->ProjectedDCFCLKDeepSleep, - 1.1 - * dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2) - / 32 - * scale_ratio_depth.hscl_ratio - / 2 - * dest.pixel_rate_mhz - / v->NoOfDPP[ijk]); - } else { - v->ProjectedDCFCLKDeepSleep = - dml_max( - v->ProjectedDCFCLKDeepSleep, - 1.1 - * dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2) - / 32 - * v->PSCL_FACTOR_CHROMA[k] - * v->RequiredDISPCLK[ij] - / (1 - + j)); - } - - } - } - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - struct _vcs_dpi_display_pipe_dest_params_st dest = - e2e[v->planes[k].e2e_index].pipe.dest; - struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = - e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; - struct _vcs_dpi_scaler_taps_st scale_taps = - e2e[v->planes[k].e2e_index].pipe.scale_taps; - struct _vcs_dpi_display_output_params_st dout = - e2e[v->planes[k].e2e_index].dout; - ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; - - if (src.dcc == 1) { - v->MetaReqHeightY = 8 * v->Read256BlockHeightY[k]; - v->MetaReqWidthY = 64 * 256 - / dml_ceil_ex(v->BytePerPixelInDETY[k], 1) - / v->MetaReqHeightY; - v->MetaSurfaceWidthY = dml_ceil_ex( - src.viewport_width / v->NoOfDPP[ijk] - 1, - v->MetaReqWidthY) + v->MetaReqWidthY; - v->MetaSurfaceHeightY = dml_ceil_ex( - src.viewport_height - 1, - v->MetaReqHeightY) + v->MetaReqHeightY; - if (ip->pte_enable == 1) { - v->MetaPteBytesPerFrameY = - (dml_ceil_ex( - (v->MetaSurfaceWidthY - * v->MetaSurfaceHeightY - * dml_ceil_ex( - v->BytePerPixelInDETY[k], - 1) - / 256.0 - - 4096) - / 8 - / 4096, - 1) + 1) * 64; - } else { - v->MetaPteBytesPerFrameY = 0; - } - if (src.source_scan == dm_horz) { - v->MetaRowBytesY = - v->MetaSurfaceWidthY - * v->MetaReqHeightY - * dml_ceil_ex( - v->BytePerPixelInDETY[k], - 1) - / 256; - } else { - v->MetaRowBytesY = - v->MetaSurfaceHeightY - * v->MetaReqWidthY - * dml_ceil_ex( - v->BytePerPixelInDETY[k], - 1) - / 256; - } - } else { - v->MetaPteBytesPerFrameY = 0; - v->MetaRowBytesY = 0; - } - - if (ip->pte_enable == 1) { - if (src.sw_mode == dm_sw_linear) { - v->MacroTileBlockSizeBytesY = 256; - v->MacroTileBlockHeightY = 1; - } else if (src.sw_mode == dm_sw_4kb_s - || src.sw_mode == dm_sw_4kb_s_x - || src.sw_mode == dm_sw_4kb_d - || src.sw_mode == dm_sw_4kb_d_x) { - v->MacroTileBlockSizeBytesY = 4096; - v->MacroTileBlockHeightY = 4 - * v->Read256BlockHeightY[k]; - } else if (src.sw_mode == dm_sw_64kb_s - || src.sw_mode == dm_sw_64kb_s_t - || src.sw_mode == dm_sw_64kb_s_x - || src.sw_mode == dm_sw_64kb_d - || src.sw_mode == dm_sw_64kb_d_t - || src.sw_mode == dm_sw_64kb_d_x) { - v->MacroTileBlockSizeBytesY = 64 * 1024; - v->MacroTileBlockHeightY = 16 - * v->Read256BlockHeightY[k]; - } else { - v->MacroTileBlockSizeBytesY = 256 * 1024; - v->MacroTileBlockHeightY = 32 - * v->Read256BlockHeightY[k]; - } - if (v->MacroTileBlockSizeBytesY <= 65536) { - v->DataPTEReqHeightY = v->MacroTileBlockHeightY; - } else { - v->DataPTEReqHeightY = 16 - * v->Read256BlockHeightY[k]; - } - v->DataPTEReqWidthY = 4096 - / dml_ceil_ex(v->BytePerPixelInDETY[k], 1) - / v->DataPTEReqHeightY * 8; - if (src.sw_mode == dm_sw_linear) { - v->DPTEBytesPerRowY = - 64 - * (dml_ceil_ex( - (src.viewport_width - / v->NoOfDPP[ijk] - * dml_min( - 128, - dml_pow( - 2, - dml_floor_ex( - dml_log( - ip->dpte_buffer_size_in_pte_reqs - * v->DataPTEReqWidthY - / (src.viewport_width - / v->NoOfDPP[ijk]), - 2), - 1))) - - 1) - / v->DataPTEReqWidthY, - 1) - + 1); - } else if (src.source_scan == dm_horz) { - v->DPTEBytesPerRowY = - 64 - * (dml_ceil_ex( - (src.viewport_width - / v->NoOfDPP[ijk] - - 1) - / v->DataPTEReqWidthY, - 1) - + 1); - } else { - v->DPTEBytesPerRowY = - 64 - * (dml_ceil_ex( - (src.viewport_height - - 1) - / v->DataPTEReqHeightY, - 1) - + 1); - } - } else { - v->DPTEBytesPerRowY = 0; - } - - if (src.source_format != dm_444_64 && src.source_format != dm_444_32 - && src.source_format != dm_444_16) { - if (src.dcc == 1) { - v->MetaReqHeightC = 8 * v->Read256BlockHeightC[k]; - v->MetaReqWidthC = - 64 * 256 - / dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2) - / v->MetaReqHeightC; - v->MetaSurfaceWidthC = dml_ceil_ex( - src.viewport_width / v->NoOfDPP[ijk] - / 2 - 1, - v->MetaReqWidthC) - + v->MetaReqWidthC; - v->MetaSurfaceHeightC = dml_ceil_ex( - src.viewport_height / 2 - 1, - v->MetaReqHeightC) - + v->MetaReqHeightC; - if (ip->pte_enable == 1) { - v->MetaPteBytesPerFrameC = - (dml_ceil_ex( - (v->MetaSurfaceWidthC - * v->MetaSurfaceHeightC - * dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2) - / 256.0 - - 4096) - / 8 - / 4096, - 1) + 1) - * 64; - } else { - v->MetaPteBytesPerFrameC = 0; - } - if (src.source_scan == dm_horz) { - v->MetaRowBytesC = - v->MetaSurfaceWidthC - * v->MetaReqHeightC - * dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2) - / 256; - } else { - v->MetaRowBytesC = - v->MetaSurfaceHeightC - * v->MetaReqWidthC - * dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2) - / 256; - } - } else { - v->MetaPteBytesPerFrameC = 0; - v->MetaRowBytesC = 0; - } - - if (ip->pte_enable == 1) { - if (src.sw_mode == dm_sw_linear) { - v->MacroTileBlockSizeBytesC = 256; - v->MacroTileBlockHeightC = 1; - } else if (src.sw_mode == dm_sw_4kb_s - || src.sw_mode == dm_sw_4kb_s_x - || src.sw_mode == dm_sw_4kb_d - || src.sw_mode == dm_sw_4kb_d_x) { - v->MacroTileBlockSizeBytesC = 4096; - v->MacroTileBlockHeightC = 4 - * v->Read256BlockHeightC[k]; - } else if (src.sw_mode == dm_sw_64kb_s - || src.sw_mode == dm_sw_64kb_s_t - || src.sw_mode == dm_sw_64kb_s_x - || src.sw_mode == dm_sw_64kb_d - || src.sw_mode == dm_sw_64kb_d_t - || src.sw_mode == dm_sw_64kb_d_x) { - v->MacroTileBlockSizeBytesC = 64 * 1024; - v->MacroTileBlockHeightC = 16 - * v->Read256BlockHeightC[k]; - } else { - v->MacroTileBlockSizeBytesC = 256 * 1024; - v->MacroTileBlockHeightC = 32 - * v->Read256BlockHeightC[k]; - } - v->MacroTileBlockWidthC = - v->MacroTileBlockSizeBytesC - / dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2) - / v->MacroTileBlockHeightC; - if (v->MacroTileBlockSizeBytesC <= 65536) { - v->DataPTEReqHeightC = - v->MacroTileBlockHeightC; - } else { - v->DataPTEReqHeightC = 16 - * v->Read256BlockHeightC[k]; - } - v->DataPTEReqWidthC = - 4096 - / dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2) - / v->DataPTEReqHeightC - * 8; - if (src.sw_mode == dm_sw_linear) { - v->DPTEBytesPerRowC = - 64 - * (dml_ceil_ex( - (src.viewport_width - / v->NoOfDPP[ijk] - / 2 - * dml_min( - 128, - dml_pow( - 2, - dml_floor_ex( - dml_log( - ip->dpte_buffer_size_in_pte_reqs - * v->DataPTEReqWidthC - / (src.viewport_width - / v->NoOfDPP[ijk] - / 2), - 2), - 1))) - - 1) - / v->DataPTEReqWidthC, - 1) - + 1); - } else if (src.source_scan == dm_horz) { - v->DPTEBytesPerRowC = - 64 - * (dml_ceil_ex( - (src.viewport_width - / v->NoOfDPP[ijk] - / 2 - - 1) - / v->DataPTEReqWidthC, - 1) - + 1); - } else { - v->DPTEBytesPerRowC = - 64 - * (dml_ceil_ex( - (src.viewport_height - / 2 - - 1) - / v->DataPTEReqHeightC, - 1) - + 1); - } - } else { - v->DPTEBytesPerRowC = 0; - } - } else { - v->DPTEBytesPerRowC = 0; - v->MetaPteBytesPerFrameC = 0; - v->MetaRowBytesC = 0; - } - - v->DPTEBytesPerRow[k] = v->DPTEBytesPerRowY + v->DPTEBytesPerRowC; - v->MetaPTEBytesPerFrame[k] = v->MetaPteBytesPerFrameY - + v->MetaPteBytesPerFrameC; - v->MetaRowBytes[k] = v->MetaRowBytesY + v->MetaRowBytesC; - - v->VInitY = (scale_ratio_depth.vscl_ratio + scale_taps.vtaps + 1 - + dest.interlaced * 0.5 - * scale_ratio_depth.vscl_ratio) - / 2.0; - v->PrefillY[k] = dml_floor_ex(v->VInitY, 1); - v->MaxNumSwY[k] = dml_ceil_ex( - (v->PrefillY[k] - 1.0) - / v->SwathHeightYPerState[ijk], - 1) + 1.0; - - if (v->PrefillY[k] > 1) { - v->MaxPartialSwY = ((int) (v->PrefillY[k] - 2)) - % ((int) v->SwathHeightYPerState[ijk]); - } else { - v->MaxPartialSwY = ((int) (v->PrefillY[k] - + v->SwathHeightYPerState[ijk] - 2)) - % ((int) v->SwathHeightYPerState[ijk]); - } - v->MaxPartialSwY = dml_max(1, v->MaxPartialSwY); - - v->PrefetchLinesY[k] = v->MaxNumSwY[k] - * v->SwathHeightYPerState[ijk] + v->MaxPartialSwY; - - if (src.source_format != dm_444_64 && src.source_format != dm_444_32 - && src.source_format != dm_444_16) { - v->VInitC = - (scale_ratio_depth.vscl_ratio / 2 - + scale_taps.vtaps + 1 - + dest.interlaced * 0.5 - * scale_ratio_depth.vscl_ratio - / 2) / 2.0; - v->PrefillC[k] = dml_floor_ex(v->VInitC, 1); - v->MaxNumSwC[k] = - dml_ceil_ex( - (v->PrefillC[k] - 1.0) - / v->SwathHeightCPerState[ijk], - 1) + 1.0; - if (v->PrefillC[k] > 1) { - v->MaxPartialSwC = - ((int) (v->PrefillC[k] - 2)) - % ((int) v->SwathHeightCPerState[ijk]); - } else { - v->MaxPartialSwC = - ((int) (v->PrefillC[k] - + v->SwathHeightCPerState[ijk] - - 2)) - % ((int) v->SwathHeightCPerState[ijk]); - } - v->MaxPartialSwC = dml_max(1, v->MaxPartialSwC); - - v->PrefetchLinesC[k] = v->MaxNumSwC[k] - * v->SwathHeightCPerState[ijk] - + v->MaxPartialSwC; - } else { - v->PrefetchLinesC[k] = 0; - } - - v->dst_x_after_scaler = 90 * dest.pixel_rate_mhz - / (v->RequiredDISPCLK[ij] / (j + 1)) - + 42 * dest.pixel_rate_mhz / v->RequiredDISPCLK[ij]; - if (v->NoOfDPP[ijk] > 1) { - v->dst_x_after_scaler = v->dst_x_after_scaler - + dest.recout_width / 2.0; - } - - if (dout.output_format == dm_420) { - v->dst_y_after_scaler = 1; - } else { - v->dst_y_after_scaler = 0; - } - - v->TimeCalc = 24 / v->ProjectedDCFCLKDeepSleep; - - v->VUpdateOffset = dml_ceil_ex(dest.htotal / 4, 1); - v->TotalRepeaterDelay = ip->max_inter_dcn_tile_repeaters - * (2 / (v->RequiredDISPCLK[ij] / (j + 1)) - + 3 / v->RequiredDISPCLK[ij]); - v->VUpdateWidth = (14 / v->ProjectedDCFCLKDeepSleep - + 12 / (v->RequiredDISPCLK[ij] / (j + 1)) - + v->TotalRepeaterDelay) * dest.pixel_rate_mhz; - v->VReadyOffset = - dml_max( - 150 - / (v->RequiredDISPCLK[ij] - / (j - + 1)), - v->TotalRepeaterDelay - + 20 - / v->ProjectedDCFCLKDeepSleep - + 10 - / (v->RequiredDISPCLK[ij] - / (j - + 1))) - * dest.pixel_rate_mhz; - - v->TimeSetup = - (v->VUpdateOffset + v->VUpdateWidth - + v->VReadyOffset) - / dest.pixel_rate_mhz; - - v->ExtraLatency = - v->UrgentRoundTripAndOutOfOrderLatencyPerState[i] - + (v->TotalNumberOfActiveDPP[ij] - * ip->pixel_chunk_size_kbytes - + v->TotalNumberOfDCCActiveDPP[ij] - * ip->meta_chunk_size_kbytes) - * 1024 - / v->ReturnBWPerState[i]; - - if (ip->pte_enable == 1) { - v->ExtraLatency = v->ExtraLatency - + v->TotalNumberOfActiveDPP[ij] - * ip->pte_chunk_size_kbytes - * 1024 - / v->ReturnBWPerState[i]; - } - - if (ip->can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one - == 1) { - v->MaximumVStartup = dest.vtotal - dest.vactive - 1; - } else { - v->MaximumVStartup = dest.vsync_plus_back_porch - 1; - } - - v->LineTimesForPrefetch[k] = - v->MaximumVStartup - - soc->urgent_latency_us - / (dest.htotal - / dest.pixel_rate_mhz) - - (v->TimeCalc + v->TimeSetup) - / (dest.htotal - / dest.pixel_rate_mhz) - - (v->dst_y_after_scaler - + v->dst_x_after_scaler - / dest.htotal); - - v->LineTimesForPrefetch[k] = dml_floor_ex( - 4.0 * (v->LineTimesForPrefetch[k] + 0.125), - 1) / 4; - - v->PrefetchBW[k] = - (v->MetaPTEBytesPerFrame[k] + 2 * v->MetaRowBytes[k] - + 2 * v->DPTEBytesPerRow[k] - + v->PrefetchLinesY[k] - * v->SwathWidthYPerState[ijk] - * dml_ceil_ex( - v->BytePerPixelInDETY[k], - 1) - + v->PrefetchLinesC[k] - * v->SwathWidthYPerState[ijk] - / 2 - * dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2)) - / (v->LineTimesForPrefetch[k] - * dest.htotal - / dest.pixel_rate_mhz); - } - - v->BWAvailableForImmediateFlip = v->ReturnBWPerState[i]; - - for (k = 0; k < num_planes; k++) { - v->BWAvailableForImmediateFlip = v->BWAvailableForImmediateFlip - - dml_max(v->ReadBandwidth[k], v->PrefetchBW[k]); - } - - v->TotalImmediateFlipBytes = 0; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - - if (src.source_format != dm_420_8 - && src.source_format != dm_420_10) { - v->TotalImmediateFlipBytes = v->TotalImmediateFlipBytes - + v->MetaPTEBytesPerFrame[k] - + v->MetaRowBytes[k] - + v->DPTEBytesPerRow[k]; - } - } - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - struct _vcs_dpi_display_pipe_dest_params_st dest = - e2e[v->planes[k].e2e_index].pipe.dest; - ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; - - if (ip->pte_enable == 1 && src.dcc == 1) { - v->TimeForMetaPTEWithImmediateFlip = - dml_max( - v->MetaPTEBytesPerFrame[k] - / v->PrefetchBW[k], - dml_max( - v->MetaPTEBytesPerFrame[k] - * v->TotalImmediateFlipBytes - / (v->BWAvailableForImmediateFlip - * (v->MetaPTEBytesPerFrame[k] - + v->MetaRowBytes[k] - + v->DPTEBytesPerRow[k])), - dml_max( - v->ExtraLatency, - dml_max( - soc->urgent_latency_us, - dest.htotal - / dest.pixel_rate_mhz - / 4)))); - - v->TimeForMetaPTEWithoutImmediateFlip = - dml_max( - v->MetaPTEBytesPerFrame[k] - / v->PrefetchBW[k], - dml_max( - v->ExtraLatency, - dest.htotal - / dest.pixel_rate_mhz - / 4)); - } else { - v->TimeForMetaPTEWithImmediateFlip = dest.htotal - / dest.pixel_rate_mhz / 4; - v->TimeForMetaPTEWithoutImmediateFlip = dest.htotal - / dest.pixel_rate_mhz / 4; - } - - if (ip->pte_enable == 1 || src.dcc == 1) { - v->TimeForMetaAndDPTERowWithImmediateFlip = - dml_max( - (v->MetaRowBytes[k] - + v->DPTEBytesPerRow[k]) - / v->PrefetchBW[k], - dml_max( - (v->MetaRowBytes[k] - + v->DPTEBytesPerRow[k]) - * v->TotalImmediateFlipBytes - / (v->BWAvailableForImmediateFlip - * (v->MetaPTEBytesPerFrame[k] - + v->MetaRowBytes[k] - + v->DPTEBytesPerRow[k])), - dml_max( - dest.htotal - / dest.pixel_rate_mhz - - v->TimeForMetaPTEWithImmediateFlip, - dml_max( - v->ExtraLatency, - 2 - * soc->urgent_latency_us)))); - - v->TimeForMetaAndDPTERowWithoutImmediateFlip = - dml_max( - (v->MetaRowBytes[k] - + v->DPTEBytesPerRow[k]) - / v->PrefetchBW[k], - dml_max( - dest.htotal - / dest.pixel_rate_mhz - - v->TimeForMetaPTEWithoutImmediateFlip, - v->ExtraLatency)); - } else { - v->TimeForMetaAndDPTERowWithImmediateFlip = - dml_max( - dest.htotal - / dest.pixel_rate_mhz - - v->TimeForMetaPTEWithImmediateFlip, - v->ExtraLatency - - v->TimeForMetaPTEWithImmediateFlip); - v->TimeForMetaAndDPTERowWithoutImmediateFlip = - dml_max( - dest.htotal - / dest.pixel_rate_mhz - - v->TimeForMetaPTEWithoutImmediateFlip, - v->ExtraLatency - - v->TimeForMetaPTEWithoutImmediateFlip); - } - - v->LinesForMetaPTEWithImmediateFlip[k] = - dml_floor_ex( - 4.0 - * (v->TimeForMetaPTEWithImmediateFlip - / (dest.htotal - / dest.pixel_rate_mhz) - + 0.125), - 1) / 4.0; - - v->LinesForMetaPTEWithoutImmediateFlip[k] = - dml_floor_ex( - 4.0 - * (v->TimeForMetaPTEWithoutImmediateFlip - / (dest.htotal - / dest.pixel_rate_mhz) - + 0.125), - 1) / 4.0; - - v->LinesForMetaAndDPTERowWithImmediateFlip[k] = - dml_floor_ex( - 4.0 - * (v->TimeForMetaAndDPTERowWithImmediateFlip - / (dest.htotal - / dest.pixel_rate_mhz) - + 0.125), - 1) / 4.0; - - v->LinesForMetaAndDPTERowWithoutImmediateFlip[k] = - dml_floor_ex( - 4.0 - * (v->TimeForMetaAndDPTERowWithoutImmediateFlip - / (dest.htotal - / dest.pixel_rate_mhz) - + 0.125), - 1) / 4.0; - - v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip = - v->LineTimesForPrefetch[k] - - v->LinesForMetaPTEWithImmediateFlip[k] - - v->LinesForMetaAndDPTERowWithImmediateFlip[k]; - - v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip = - v->LineTimesForPrefetch[k] - - v->LinesForMetaPTEWithoutImmediateFlip[k] - - v->LinesForMetaAndDPTERowWithoutImmediateFlip[k]; - - if (v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip > 0) { - v->VRatioPreYWithImmediateFlip[ijk] = - v->PrefetchLinesY[k] - / v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip; - if (v->SwathHeightYPerState[ijk] > 4) { - if (v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip - - (v->PrefillY[k] - 3.0) / 2.0 - > 0) { - v->VRatioPreYWithImmediateFlip[ijk] = - dml_max( - v->VRatioPreYWithImmediateFlip[ijk], - (v->MaxNumSwY[k] - * v->SwathHeightYPerState[ijk]) - / (v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip - - (v->PrefillY[k] - - 3.0) - / 2.0)); - } else { - v->VRatioPreYWithImmediateFlip[ijk] = - 999999; - } - } - v->VRatioPreCWithImmediateFlip[ijk] = - v->PrefetchLinesC[k] - / v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip; - if (v->SwathHeightCPerState[ijk] > 4) { - if (v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip - - (v->PrefillC[k] - 3.0) / 2.0 - > 0) { - v->VRatioPreCWithImmediateFlip[ijk] = - dml_max( - v->VRatioPreCWithImmediateFlip[ijk], - (v->MaxNumSwC[k] - * v->SwathHeightCPerState[ijk]) - / (v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip - - (v->PrefillC[k] - - 3.0) - / 2.0)); - } else { - v->VRatioPreCWithImmediateFlip[ijk] = - 999999; - } - } - - v->RequiredPrefetchPixelDataBWWithImmediateFlip[ijk] = - v->NoOfDPP[ijk] - * (v->PrefetchLinesY[k] - / v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip - * dml_ceil_ex( - v->BytePerPixelInDETY[k], - 1) - + v->PrefetchLinesC[k] - / v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip - * dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2) - / 2) - * v->SwathWidthYPerState[ijk] - / (dest.htotal - / dest.pixel_rate_mhz); - } else { - v->VRatioPreYWithImmediateFlip[ijk] = 999999; - v->VRatioPreCWithImmediateFlip[ijk] = 999999; - v->RequiredPrefetchPixelDataBWWithImmediateFlip[ijk] = - 999999; - } - - if (v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip - > 0) { - v->VRatioPreYWithoutImmediateFlip[ijk] = - v->PrefetchLinesY[k] - / v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip; - if (v->SwathHeightYPerState[ijk] > 4) { - if (v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip - - (v->PrefillY[k] - 3.0) / 2.0 - > 0) { - v->VRatioPreYWithoutImmediateFlip[ijk] = - dml_max( - v->VRatioPreYWithoutImmediateFlip[ijk], - (v->MaxNumSwY[k] - * v->SwathHeightYPerState[ijk]) - / (v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip - - (v->PrefillY[k] - - 3.0) - / 2.0)); - } else { - v->VRatioPreYWithoutImmediateFlip[ijk] = - 999999; - } - } - v->VRatioPreCWithoutImmediateFlip[ijk] = - v->PrefetchLinesC[k] - / v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip; - if (v->SwathHeightCPerState[ijk] > 4) { - if (v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip - - (v->PrefillC[k] - 3.0) / 2.0 - > 0) { - v->VRatioPreCWithoutImmediateFlip[ijk] = - dml_max( - v->VRatioPreCWithoutImmediateFlip[ijk], - (v->MaxNumSwC[k] - * v->SwathHeightCPerState[ijk]) - / (v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip - - (v->PrefillC[k] - - 3.0) - / 2.0)); - } else { - v->VRatioPreCWithoutImmediateFlip[ijk] = - 999999; - } - } - - v->RequiredPrefetchPixelDataBWWithoutImmediateFlip[ijk] = - v->NoOfDPP[ijk] - * (v->PrefetchLinesY[k] - / v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip - * dml_ceil_ex( - v->BytePerPixelInDETY[k], - 1) - + v->PrefetchLinesC[k] - / v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip - * dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2) - / 2) - * v->SwathWidthYPerState[ijk] - / (dest.htotal - / dest.pixel_rate_mhz); - } else { - v->VRatioPreYWithoutImmediateFlip[ijk] = 999999; - v->VRatioPreCWithoutImmediateFlip[ijk] = 999999; - v->RequiredPrefetchPixelDataBWWithoutImmediateFlip[ijk] = - 999999; - } - } - - v->MaximumReadBandwidthWithPrefetchWithImmediateFlip = 0; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - struct _vcs_dpi_display_pipe_dest_params_st dest = - e2e[v->planes[k].e2e_index].pipe.dest; - ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; - - if (src.source_format != dm_420_8 - && src.source_format != dm_420_10) { - v->MaximumReadBandwidthWithPrefetchWithImmediateFlip = - v->MaximumReadBandwidthWithPrefetchWithImmediateFlip - + dml_max( - v->ReadBandwidth[k], - v->RequiredPrefetchPixelDataBWWithImmediateFlip[ijk]) - + dml_max( - v->MetaPTEBytesPerFrame[k] - / (v->LinesForMetaPTEWithImmediateFlip[k] - * dest.htotal - / dest.pixel_rate_mhz), - (v->MetaRowBytes[k] - + v->DPTEBytesPerRow[k]) - / (v->LinesForMetaAndDPTERowWithImmediateFlip[k] - * dest.htotal - / dest.pixel_rate_mhz)); - } else { - v->MaximumReadBandwidthWithPrefetchWithImmediateFlip = - v->MaximumReadBandwidthWithPrefetchWithImmediateFlip - + dml_max( - v->ReadBandwidth[k], - v->RequiredPrefetchPixelDataBWWithoutImmediateFlip[ijk]); - } - } - - v->MaximumReadBandwidthWithPrefetchWithoutImmediateFlip = 0; - - for (k = 0; k < num_planes; k++) { - ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; - - v->MaximumReadBandwidthWithPrefetchWithoutImmediateFlip = - v->MaximumReadBandwidthWithPrefetchWithoutImmediateFlip - + dml_max( - v->ReadBandwidth[k], - v->RequiredPrefetchPixelDataBWWithoutImmediateFlip[ijk]); - } - - v->PrefetchSupportedWithImmediateFlip[ij] = 1; - if (v->MaximumReadBandwidthWithPrefetchWithImmediateFlip - > v->ReturnBWPerState[i]) { - v->PrefetchSupportedWithImmediateFlip[ij] = 0; - } - for (k = 0; k < num_planes; k++) { - if (v->LineTimesForPrefetch[k] < 2 - || v->LinesForMetaPTEWithImmediateFlip[k] >= 8 - || v->LinesForMetaAndDPTERowWithImmediateFlip[k] - >= 16) { - v->PrefetchSupportedWithImmediateFlip[ij] = 0; - } - } - - v->PrefetchSupportedWithoutImmediateFlip[ij] = 1; - if (v->MaximumReadBandwidthWithPrefetchWithoutImmediateFlip - > v->ReturnBWPerState[i]) { - v->PrefetchSupportedWithoutImmediateFlip[ij] = 0; - } - for (k = 0; k < num_planes; k++) { - if (v->LineTimesForPrefetch[k] < 2 - || v->LinesForMetaPTEWithoutImmediateFlip[k] >= 8 - || v->LinesForMetaAndDPTERowWithoutImmediateFlip[k] - >= 16) { - v->PrefetchSupportedWithoutImmediateFlip[ij] = 0; - } - } - } - } - - for (i = 0; i < NumberOfStatesPlusTwo; i++) { - for (j = 0; j < 2; j++) { - ij = j * NumberOfStatesPlusTwo + i; - - v->VRatioInPrefetchSupportedWithImmediateFlip[ij] = 1; - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; - - if (((src.source_format != dm_420_8 - && src.source_format != dm_420_10) - && (v->VRatioPreYWithImmediateFlip[ijk] > 4 - || v->VRatioPreCWithImmediateFlip[ijk] - > 4)) - || ((src.source_format == dm_420_8 - || src.source_format == dm_420_10) - && (v->VRatioPreYWithoutImmediateFlip[ijk] - > 4 - || v->VRatioPreCWithoutImmediateFlip[ijk] - > 4))) { - v->VRatioInPrefetchSupportedWithImmediateFlip[ij] = 0; - } - } - v->VRatioInPrefetchSupportedWithoutImmediateFlip[ij] = 1; - for (k = 0; k < num_planes; k++) { - ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; - - if (v->VRatioPreYWithoutImmediateFlip[ijk] > 4 - || v->VRatioPreCWithoutImmediateFlip[ijk] > 4) { - v->VRatioInPrefetchSupportedWithoutImmediateFlip[ij] = 0; - } - } - } - } - - // Mode Support, Voltage State and SOC Configuration - - for (i = (NumberOfStatesPlusTwo - 1); i >= 0; i--) // use int type here - { - for (j = 0; j < 2; j++) { - ij = j * NumberOfStatesPlusTwo + i; - - if (v->ScaleRatioSupport == 1 && v->SourceFormatPixelAndScanSupport == 1 - && v->ViewportSizeSupport == 1 - && v->BandwidthSupport[i] == 1 && v->DIOSupport[i] == 1 - && v->UrgentLatencySupport[ij] == 1 && v->ROBSupport[i] == 1 - && v->DISPCLK_DPPCLK_Support[ij] == 1 - && v->TotalAvailablePipesSupport[ij] == 1 - && v->TotalAvailableWritebackSupport == 1 - && v->WritebackLatencySupport == 1) { - if (v->PrefetchSupportedWithImmediateFlip[ij] == 1 - && v->VRatioInPrefetchSupportedWithImmediateFlip[ij] - == 1) { - v->ModeSupportWithImmediateFlip[ij] = 1; - } else { - v->ModeSupportWithImmediateFlip[ij] = 0; - } - if (v->PrefetchSupportedWithoutImmediateFlip[ij] == 1 - && v->VRatioInPrefetchSupportedWithoutImmediateFlip[ij] - == 1) { - v->ModeSupportWithoutImmediateFlip[ij] = 1; - } else { - v->ModeSupportWithoutImmediateFlip[ij] = 0; - } - } else { - v->ModeSupportWithImmediateFlip[ij] = 0; - v->ModeSupportWithoutImmediateFlip[ij] = 0; - } - } - } - - for (i = (NumberOfStatesPlusTwo - 1); i >= 0; i--) // use int type here - { - if ((i == (NumberOfStatesPlusTwo - 1) - || v->ModeSupportWithImmediateFlip[1 * NumberOfStatesPlusTwo + i] - == 1 - || v->ModeSupportWithImmediateFlip[0 * NumberOfStatesPlusTwo + i] - == 1) && i >= v->VoltageOverrideLevel) { - v->VoltageLevelWithImmediateFlip = i; - } - } - - for (i = (NumberOfStatesPlusTwo - 1); i >= 0; i--) // use int type here - { - if ((i == (NumberOfStatesPlusTwo - 1) - || v->ModeSupportWithoutImmediateFlip[1 * NumberOfStatesPlusTwo + i] - == 1 - || v->ModeSupportWithoutImmediateFlip[0 * NumberOfStatesPlusTwo + i] - == 1) && i >= v->VoltageOverrideLevel) { - v->VoltageLevelWithoutImmediateFlip = i; - } - } - - if (v->VoltageLevelWithImmediateFlip == (NumberOfStatesPlusTwo - 1)) { - v->ImmediateFlipSupported = 0; - v->VoltageLevel = v->VoltageLevelWithoutImmediateFlip; - } else { - v->ImmediateFlipSupported = 1; - v->VoltageLevel = v->VoltageLevelWithImmediateFlip; - } - - v->DCFCLK = v->DCFCLKPerState[(int) v->VoltageLevel]; - v->FabricAndDRAMBandwidth = v->FabricAndDRAMBandwidthPerState[(int) v->VoltageLevel]; - - for (j = 0; j < 2; j++) { - v->RequiredDISPCLKPerRatio[j] = v->RequiredDISPCLK[j * NumberOfStatesPlusTwo - + (int) v->VoltageLevel]; - for (k = 0; k < num_planes; k++) { - v->DPPPerPlanePerRatio[k * 2 + j] = v->NoOfDPP[k * 2 * NumberOfStatesPlusTwo - + j * NumberOfStatesPlusTwo + (int) v->VoltageLevel]; - } - v->DISPCLK_DPPCLK_SupportPerRatio[j] = v->DISPCLK_DPPCLK_Support[j - * NumberOfStatesPlusTwo + (int) v->VoltageLevel]; - } - - ASSERT(v->ImmediateFlipSupported || v->MacroTileBlockWidthC || v->DCFCLK || v->FabricAndDRAMBandwidth); - - return (v->VoltageLevel); -} - diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.h deleted file mode 100644 index ead4942f998c..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.h +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright 2017 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ -#ifndef __DISPLAY_MODE_SUPPORT_H__ -#define __DISPLAY_MODE_SUPPORT_H__ - -#include "dml_common_defs.h" - -struct display_mode_lib; - -#define NumberOfStates 4 -#define NumberOfStatesPlusTwo (NumberOfStates+2) - -struct dml_ms_internal_vars { - double ScaleRatioSupport; - double SourceFormatPixelAndScanSupport; - double TotalReadBandwidthConsumedGBytePerSecond; - double TotalWriteBandwidthConsumedGBytePerSecond; - double TotalBandwidthConsumedGBytePerSecond; - double DCCEnabledInAnyPlane; - double ReturnBWToDCNPerState; - double CriticalPoint; - double WritebackLatencySupport; - double RequiredOutputBW; - double TotalNumberOfActiveWriteback; - double TotalAvailableWritebackSupport; - double MaximumSwathWidth; - double NumberOfDPPRequiredForDETSize; - double NumberOfDPPRequiredForLBSize; - double MinDispclkUsingSingleDPP; - double MinDispclkUsingDualDPP; - double ViewportSizeSupport; - double SwathWidthGranularityY; - double RoundedUpMaxSwathSizeBytesY; - double SwathWidthGranularityC; - double RoundedUpMaxSwathSizeBytesC; - double LinesInDETLuma; - double LinesInDETChroma; - double EffectiveLBLatencyHidingSourceLinesLuma; - double EffectiveLBLatencyHidingSourceLinesChroma; - double EffectiveDETLBLinesLuma; - double EffectiveDETLBLinesChroma; - double ProjectedDCFCLKDeepSleep; - double MetaReqHeightY; - double MetaReqWidthY; - double MetaSurfaceWidthY; - double MetaSurfaceHeightY; - double MetaPteBytesPerFrameY; - double MetaRowBytesY; - double MacroTileBlockSizeBytesY; - double MacroTileBlockHeightY; - double DataPTEReqHeightY; - double DataPTEReqWidthY; - double DPTEBytesPerRowY; - double MetaReqHeightC; - double MetaReqWidthC; - double MetaSurfaceWidthC; - double MetaSurfaceHeightC; - double MetaPteBytesPerFrameC; - double MetaRowBytesC; - double MacroTileBlockSizeBytesC; - double MacroTileBlockHeightC; - double MacroTileBlockWidthC; - double DataPTEReqHeightC; - double DataPTEReqWidthC; - double DPTEBytesPerRowC; - double VInitY; - double MaxPartialSwY; - double VInitC; - double MaxPartialSwC; - double dst_x_after_scaler; - double dst_y_after_scaler; - double TimeCalc; - double VUpdateOffset; - double TotalRepeaterDelay; - double VUpdateWidth; - double VReadyOffset; - double TimeSetup; - double ExtraLatency; - double MaximumVStartup; - double BWAvailableForImmediateFlip; - double TotalImmediateFlipBytes; - double TimeForMetaPTEWithImmediateFlip; - double TimeForMetaPTEWithoutImmediateFlip; - double TimeForMetaAndDPTERowWithImmediateFlip; - double TimeForMetaAndDPTERowWithoutImmediateFlip; - double LineTimesToRequestPrefetchPixelDataWithImmediateFlip; - double LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip; - double MaximumReadBandwidthWithPrefetchWithImmediateFlip; - double MaximumReadBandwidthWithPrefetchWithoutImmediateFlip; - double VoltageOverrideLevel; - double VoltageLevelWithImmediateFlip; - double VoltageLevelWithoutImmediateFlip; - double ImmediateFlipSupported; - double VoltageLevel; - double DCFCLK; - double FabricAndDRAMBandwidth; - double SwathWidthYSingleDPP[DC__NUM_PIPES__MAX]; - double BytePerPixelInDETY[DC__NUM_PIPES__MAX]; - double BytePerPixelInDETC[DC__NUM_PIPES__MAX]; - double ReadBandwidth[DC__NUM_PIPES__MAX]; - double WriteBandwidth[DC__NUM_PIPES__MAX]; - double DCFCLKPerState[NumberOfStatesPlusTwo]; - double FabricAndDRAMBandwidthPerState[NumberOfStatesPlusTwo]; - double ReturnBWPerState[NumberOfStatesPlusTwo]; - double BandwidthSupport[NumberOfStatesPlusTwo]; - double UrgentRoundTripAndOutOfOrderLatencyPerState[NumberOfStatesPlusTwo]; - double ROBSupport[NumberOfStatesPlusTwo]; - double RequiredPHYCLK[DC__NUM_PIPES__MAX]; - double DIOSupport[NumberOfStatesPlusTwo]; - double PHYCLKPerState[NumberOfStatesPlusTwo]; - double PSCL_FACTOR[DC__NUM_PIPES__MAX]; - double PSCL_FACTOR_CHROMA[DC__NUM_PIPES__MAX]; - double MinDPPCLKUsingSingleDPP[DC__NUM_PIPES__MAX]; - double Read256BlockHeightY[DC__NUM_PIPES__MAX]; - double Read256BlockWidthY[DC__NUM_PIPES__MAX]; - double Read256BlockHeightC[DC__NUM_PIPES__MAX]; - double Read256BlockWidthC[DC__NUM_PIPES__MAX]; - double MaxSwathHeightY[DC__NUM_PIPES__MAX]; - double MaxSwathHeightC[DC__NUM_PIPES__MAX]; - double MinSwathHeightY[DC__NUM_PIPES__MAX]; - double MinSwathHeightC[DC__NUM_PIPES__MAX]; - double NumberOfDPPRequiredForDETAndLBSize[DC__NUM_PIPES__MAX]; - double TotalNumberOfActiveDPP[NumberOfStatesPlusTwo * 2]; - double RequiredDISPCLK[NumberOfStatesPlusTwo * 2]; - double DISPCLK_DPPCLK_Support[NumberOfStatesPlusTwo * 2]; - double MaxDispclk[NumberOfStatesPlusTwo]; - double MaxDppclk[NumberOfStatesPlusTwo]; - double NoOfDPP[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; - double TotalAvailablePipesSupport[NumberOfStatesPlusTwo * 2]; - double SwathWidthYPerState[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; - double SwathHeightYPerState[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; - double SwathHeightCPerState[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; - double DETBufferSizeYPerState[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; - double UrgentLatencySupportUsPerState[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; - double UrgentLatencySupport[NumberOfStatesPlusTwo * 2]; - double TotalNumberOfDCCActiveDPP[NumberOfStatesPlusTwo * 2]; - double DPTEBytesPerRow[DC__NUM_PIPES__MAX]; - double MetaPTEBytesPerFrame[DC__NUM_PIPES__MAX]; - double MetaRowBytes[DC__NUM_PIPES__MAX]; - double PrefillY[DC__NUM_PIPES__MAX]; - double MaxNumSwY[DC__NUM_PIPES__MAX]; - double PrefetchLinesY[DC__NUM_PIPES__MAX]; - double PrefillC[DC__NUM_PIPES__MAX]; - double MaxNumSwC[DC__NUM_PIPES__MAX]; - double PrefetchLinesC[DC__NUM_PIPES__MAX]; - double LineTimesForPrefetch[DC__NUM_PIPES__MAX]; - double PrefetchBW[DC__NUM_PIPES__MAX]; - double LinesForMetaPTEWithImmediateFlip[DC__NUM_PIPES__MAX]; - double LinesForMetaPTEWithoutImmediateFlip[DC__NUM_PIPES__MAX]; - double LinesForMetaAndDPTERowWithImmediateFlip[DC__NUM_PIPES__MAX]; - double LinesForMetaAndDPTERowWithoutImmediateFlip[DC__NUM_PIPES__MAX]; - double VRatioPreYWithImmediateFlip[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; - double VRatioPreCWithImmediateFlip[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; - double RequiredPrefetchPixelDataBWWithImmediateFlip[NumberOfStatesPlusTwo * 2 - * DC__NUM_PIPES__MAX]; - double VRatioPreYWithoutImmediateFlip[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; - double VRatioPreCWithoutImmediateFlip[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; - double RequiredPrefetchPixelDataBWWithoutImmediateFlip[NumberOfStatesPlusTwo * 2 - * DC__NUM_PIPES__MAX]; - double PrefetchSupportedWithImmediateFlip[NumberOfStatesPlusTwo * 2]; - double PrefetchSupportedWithoutImmediateFlip[NumberOfStatesPlusTwo * 2]; - double VRatioInPrefetchSupportedWithImmediateFlip[NumberOfStatesPlusTwo * 2]; - double VRatioInPrefetchSupportedWithoutImmediateFlip[NumberOfStatesPlusTwo * 2]; - double ModeSupportWithImmediateFlip[NumberOfStatesPlusTwo * 2]; - double ModeSupportWithoutImmediateFlip[NumberOfStatesPlusTwo * 2]; - double RequiredDISPCLKPerRatio[2]; - double DPPPerPlanePerRatio[2 * DC__NUM_PIPES__MAX]; - double DISPCLK_DPPCLK_SupportPerRatio[2]; - struct _vcs_dpi_wm_calc_pipe_params_st planes[DC__NUM_PIPES__MAX]; -}; - -int dml_ms_check( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - int num_pipes); - -#endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c new file mode 100644 index 000000000000..ada0eeed3301 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c @@ -0,0 +1,3263 @@ +#include "display_mode_lib.h" +#include "display_mode_vba.h" + +static const unsigned int NumberOfStates = DC__VOLTAGE_STATES; + +static void fetch_socbb_params(struct display_mode_lib *mode_lib); +static void fetch_ip_params(struct display_mode_lib *mode_lib); +static void fetch_pipe_params(struct display_mode_lib *mode_lib); +static void recalculate_params(struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *pipes, + unsigned int num_pipes); +static void recalculate(struct display_mode_lib *mode_lib); +static double adjust_ReturnBW(struct display_mode_lib *mode_lib, double ReturnBW, bool DCCEnabledAnyPlane, double ReturnBandwidthToDCN); +static void ModeSupportAndSystemConfiguration(struct display_mode_lib *mode_lib); +static void DisplayPipeConfiguration(struct display_mode_lib *mode_lib); +static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation(struct display_mode_lib *mode_lib); +static unsigned int dscceComputeDelay(unsigned int bpc, + double bpp, + unsigned int sliceWidth, + unsigned int numSlices, + enum output_format_class pixelFormat); +static unsigned int dscComputeDelay(enum output_format_class pixelFormat); +// Super monster function with some 45 argument +static bool CalculatePrefetchSchedule(struct display_mode_lib *mode_lib, + double DPPCLK, + double DISPCLK, + double PixelClock, + double DCFClkDeepSleep, + unsigned int DSCDelay, + unsigned int DPPPerPlane, + bool ScalerEnabled, + unsigned int NumberOfCursors, + double DPPCLKDelaySubtotal, + double DPPCLKDelaySCL, + double DPPCLKDelaySCLLBOnly, + double DPPCLKDelayCNVCFormater, + double DPPCLKDelayCNVCCursor, + double DISPCLKDelaySubtotal, + unsigned int ScalerRecoutWidth, + enum output_format_class OutputFormat, + unsigned int VBlank, + unsigned int HTotal, + unsigned int MaxInterDCNTileRepeaters, + unsigned int VStartup, + unsigned int PageTableLevels, + bool VirtualMemoryEnable, + bool DynamicMetadataEnable, + unsigned int DynamicMetadataLinesBeforeActiveRequired, + unsigned int DynamicMetadataTransmittedBytes, + bool DCCEnable, + double UrgentLatency, + double UrgentExtraLatency, + double TCalc, + unsigned int PDEAndMetaPTEBytesFrame, + unsigned int MetaRowByte, + unsigned int PixelPTEBytesPerRow, + double PrefetchSourceLinesY, + unsigned int SwathWidthY, + double BytePerPixelDETY, + double VInitPreFillY, + unsigned int MaxNumSwathY, + double PrefetchSourceLinesC, + double BytePerPixelDETC, + double VInitPreFillC, + unsigned int MaxNumSwathC, + unsigned int SwathHeightY, + unsigned int SwathHeightC, + double TWait, + bool XFCEnabled, + double XFCRemoteSurfaceFlipDelay, + bool InterlaceEnable, + bool ProgressiveToInterlaceUnitInOPP, + double *DSTXAfterScaler, + double *DSTYAfterScaler, + double *DestinationLinesForPrefetch, + double *PrefetchBandwidth, + double *DestinationLinesToRequestVMInVBlank, + double *DestinationLinesToRequestRowInVBlank, + double *VRatioPrefetchY, + double *VRatioPrefetchC, + double *RequiredPrefetchPixDataBW, + unsigned int *VStartupRequiredWhenNotEnoughTimeForDynamicMetadata, + double *Tno_bw); +static double CeilToDFSGranularity(double Clock, double VCOSpeed); +static double FloorToDFSGranularity(double Clock, double VCOSpeed); +static double CalculatePrefetchSourceLines(struct display_mode_lib *mode_lib, + double VRatio, + double vtaps, + bool Interlace, + bool ProgressiveToInterlaceUnitInOPP, + unsigned int SwathHeight, + unsigned int ViewportYStart, + double *VInitPreFill, + unsigned int *MaxNumSwath); +static unsigned int CalculateVMAndRowBytes(struct display_mode_lib *mode_lib, + bool DCCEnable, + unsigned int BlockHeight256Bytes, + unsigned int BlockWidth256Bytes, + enum source_format_class SourcePixelFormat, + unsigned int SurfaceTiling, + unsigned int BytePerPixel, + enum scan_direction_class ScanDirection, + unsigned int ViewportWidth, + unsigned int ViewportHeight, + unsigned int SwathWidthY, + bool VirtualMemoryEnable, + unsigned int VMMPageSize, + unsigned int PTEBufferSizeInRequests, + unsigned int PDEProcessingBufIn64KBReqs, + unsigned int Pitch, + unsigned int DCCMetaPitch, + unsigned int *MacroTileWidth, + unsigned int *MetaRowByte, + unsigned int *PixelPTEBytesPerRow, + bool *PTEBufferSizeNotExceeded, + unsigned int *dpte_row_height, + unsigned int *meta_row_height); +static double CalculateTWait(unsigned int PrefetchMode, + double DRAMClockChangeLatency, + double UrgentLatency, + double SREnterPlusExitTime); +static double CalculateRemoteSurfaceFlipDelay(struct display_mode_lib *mode_lib, + double VRatio, + double SwathWidth, + double Bpp, + double LineTime, + double XFCTSlvVupdateOffset, + double XFCTSlvVupdateWidth, + double XFCTSlvVreadyOffset, + double XFCXBUFLatencyTolerance, + double XFCFillBWOverhead, + double XFCSlvChunkSize, + double XFCBusTransportTime, + double TCalc, + double TWait, + double *SrcActiveDrainRate, + double *TInitXFill, + double *TslvChk); +static double CalculateWriteBackDISPCLK(enum source_format_class WritebackPixelFormat, + double PixelClock, + double WritebackHRatio, + double WritebackVRatio, + unsigned int WritebackLumaHTaps, + unsigned int WritebackLumaVTaps, + unsigned int WritebackChromaHTaps, + unsigned int WritebackChromaVTaps, + double WritebackDestinationWidth, + unsigned int HTotal, + unsigned int WritebackChromaLineBufferWidth); +static void CalculateActiveRowBandwidth(bool VirtualMemoryEnable, + enum source_format_class SourcePixelFormat, + double VRatio, + bool DCCEnable, + double LineTime, + unsigned int MetaRowByteLuma, + unsigned int MetaRowByteChroma, + unsigned int meta_row_height_luma, + unsigned int meta_row_height_chroma, + unsigned int PixelPTEBytesPerRowLuma, + unsigned int PixelPTEBytesPerRowChroma, + unsigned int dpte_row_height_luma, + unsigned int dpte_row_height_chroma, + double *meta_row_bw, + double *dpte_row_bw, + double *qual_row_bw); +static void CalculateFlipSchedule(struct display_mode_lib *mode_lib, + double UrgentExtraLatency, + double UrgentLatency, + unsigned int MaxPageTableLevels, + bool VirtualMemoryEnable, + double BandwidthAvailableForImmediateFlip, + unsigned int TotImmediateFlipBytes, + enum source_format_class SourcePixelFormat, + unsigned int ImmediateFlipBytes, + double LineTime, + double Tno_bw, + double VRatio, + double PDEAndMetaPTEBytesFrame, + unsigned int MetaRowByte, + unsigned int PixelPTEBytesPerRow, + bool DCCEnable, + unsigned int dpte_row_height, + unsigned int meta_row_height, + double qual_row_bw, + double *DestinationLinesToRequestVMInImmediateFlip, + double *DestinationLinesToRequestRowInImmediateFlip, + double *final_flip_bw, + bool *ImmediateFlipSupportedForPipe); +static double CalculateWriteBackDelay(enum source_format_class WritebackPixelFormat, + double WritebackHRatio, + double WritebackVRatio, + unsigned int WritebackLumaHTaps, + unsigned int WritebackLumaVTaps, + unsigned int WritebackChromaHTaps, + unsigned int WritebackChromaVTaps, + unsigned int WritebackDestinationWidth); +static void PixelClockAdjustmentForProgressiveToInterlaceUnit(struct display_mode_lib *mode_lib); +static unsigned int CursorBppEnumToBits(enum cursor_bpp ebpp); + +void set_prefetch_mode(struct display_mode_lib *mode_lib, + bool cstate_en, + bool pstate_en, + bool ignore_viewport_pos, + bool immediate_flip_support) +{ + unsigned int prefetch_mode; + + if (cstate_en && pstate_en) + prefetch_mode = 0; + else if (cstate_en) + prefetch_mode = 1; + else + prefetch_mode = 2; + if (prefetch_mode != mode_lib->vba.PrefetchMode || ignore_viewport_pos != mode_lib->vba.IgnoreViewportPositioning + || immediate_flip_support != mode_lib->vba.ImmediateFlipSupport) { + DTRACE(" Prefetch mode has changed from %i to %i. Recalculating.", + prefetch_mode, + mode_lib->vba.PrefetchMode); + mode_lib->vba.PrefetchMode = prefetch_mode; + mode_lib->vba.IgnoreViewportPositioning = ignore_viewport_pos; + mode_lib->vba.ImmediateFlipSupport = immediate_flip_support; + recalculate(mode_lib); + } +} + +#define dml_get_attr_func(attr, var) double get_##attr(struct display_mode_lib *mode_lib, const display_e2e_pipe_params_st *pipes, unsigned int num_pipes) \ +{ \ + recalculate_params(mode_lib, pipes, num_pipes); \ + return var; \ +} + +dml_get_attr_func(clk_dcf_deepsleep, mode_lib->vba.DCFClkDeepSleep); +dml_get_attr_func(wm_urgent, mode_lib->vba.UrgentWatermark); +dml_get_attr_func(wm_memory_trip, mode_lib->vba.MemoryTripWatermark); +dml_get_attr_func(wm_writeback_urgent, mode_lib->vba.WritebackUrgentWatermark); +dml_get_attr_func(wm_stutter_exit, mode_lib->vba.StutterExitWatermark); +dml_get_attr_func(wm_stutter_enter_exit, mode_lib->vba.StutterEnterPlusExitWatermark); +dml_get_attr_func(wm_dram_clock_change, mode_lib->vba.DRAMClockChangeWatermark); +dml_get_attr_func(wm_writeback_dram_clock_change, mode_lib->vba.WritebackDRAMClockChangeWatermark); +dml_get_attr_func(wm_xfc_underflow, mode_lib->vba.UrgentWatermark); // xfc_underflow maps to urgent +dml_get_attr_func(stutter_efficiency, mode_lib->vba.StutterEfficiency); +dml_get_attr_func(stutter_efficiency_no_vblank, mode_lib->vba.StutterEfficiencyNotIncludingVBlank); +dml_get_attr_func(urgent_latency, mode_lib->vba.MinUrgentLatencySupportUs); +dml_get_attr_func(urgent_extra_latency, mode_lib->vba.UrgentExtraLatency); +dml_get_attr_func(nonurgent_latency, mode_lib->vba.NonUrgentLatencyTolerance); +dml_get_attr_func(dram_clock_change_latency, mode_lib->vba.MinActiveDRAMClockChangeLatencySupported); +dml_get_attr_func(dispclk_calculated, mode_lib->vba.DISPCLK_calculated); +dml_get_attr_func(total_data_read_bw, mode_lib->vba.TotalDataReadBandwidth); +dml_get_attr_func(return_bw, mode_lib->vba.ReturnBW); +dml_get_attr_func(tcalc, mode_lib->vba.TCalc); + +#define dml_get_pipe_attr_func(attr, var) double get_##attr(struct display_mode_lib *mode_lib, const display_e2e_pipe_params_st *pipes, unsigned int num_pipes, unsigned int which_pipe) \ +{\ + unsigned int which_plane; \ + recalculate_params(mode_lib, pipes, num_pipes); \ + which_plane = mode_lib->vba.pipe_plane[which_pipe]; \ + return var[which_plane]; \ +} + +dml_get_pipe_attr_func(dsc_delay, mode_lib->vba.DSCDelay); +dml_get_pipe_attr_func(dppclk_calculated, mode_lib->vba.DPPCLK_calculated); +dml_get_pipe_attr_func(dscclk_calculated, mode_lib->vba.DSCCLK_calculated); +dml_get_pipe_attr_func(min_ttu_vblank, mode_lib->vba.MinTTUVBlank); +dml_get_pipe_attr_func(vratio_prefetch_l, mode_lib->vba.VRatioPrefetchY); +dml_get_pipe_attr_func(vratio_prefetch_c, mode_lib->vba.VRatioPrefetchC); +dml_get_pipe_attr_func(dst_x_after_scaler, mode_lib->vba.DSTXAfterScaler); +dml_get_pipe_attr_func(dst_y_after_scaler, mode_lib->vba.DSTYAfterScaler); +dml_get_pipe_attr_func(dst_y_per_vm_vblank, mode_lib->vba.DestinationLinesToRequestVMInVBlank); +dml_get_pipe_attr_func(dst_y_per_row_vblank, mode_lib->vba.DestinationLinesToRequestRowInVBlank); +dml_get_pipe_attr_func(dst_y_prefetch, mode_lib->vba.DestinationLinesForPrefetch); +dml_get_pipe_attr_func(dst_y_per_vm_flip, mode_lib->vba.DestinationLinesToRequestVMInImmediateFlip); +dml_get_pipe_attr_func(dst_y_per_row_flip, mode_lib->vba.DestinationLinesToRequestRowInImmediateFlip); + +dml_get_pipe_attr_func(xfc_transfer_delay, mode_lib->vba.XFCTransferDelay); +dml_get_pipe_attr_func(xfc_precharge_delay, mode_lib->vba.XFCPrechargeDelay); +dml_get_pipe_attr_func(xfc_remote_surface_flip_latency, mode_lib->vba.XFCRemoteSurfaceFlipLatency); +dml_get_pipe_attr_func(xfc_prefetch_margin, mode_lib->vba.XFCPrefetchMargin); + +unsigned int get_vstartup_calculated(struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *pipes, + unsigned int num_pipes, + unsigned int which_pipe) +{ + unsigned int which_plane; + + recalculate_params(mode_lib, pipes, num_pipes); + which_plane = mode_lib->vba.pipe_plane[which_pipe]; + return mode_lib->vba.VStartup[which_plane]; +} + +double get_total_immediate_flip_bytes(struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *pipes, + unsigned int num_pipes) +{ + recalculate_params(mode_lib, pipes, num_pipes); + return mode_lib->vba.TotImmediateFlipBytes; +} + +double get_total_immediate_flip_bw(struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *pipes, + unsigned int num_pipes) +{ + recalculate_params(mode_lib, pipes, num_pipes); + return mode_lib->vba.ImmediateFlipBW; +} + +double get_total_prefetch_bw(struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *pipes, + unsigned int num_pipes) +{ + unsigned int k; + double total_prefetch_bw = 0.0; + + recalculate_params(mode_lib, pipes, num_pipes); + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) + total_prefetch_bw += mode_lib->vba.PrefetchBandwidth[k]; + return total_prefetch_bw; +} + +static void fetch_socbb_params(struct display_mode_lib *mode_lib) +{ + soc_bounding_box_st *soc = &mode_lib->vba.soc; + unsigned int i; + + // SOC Bounding Box Parameters + mode_lib->vba.ReturnBusWidth = soc->return_bus_width_bytes; + mode_lib->vba.NumberOfChannels = soc->num_chans; + mode_lib->vba.PercentOfIdealDRAMAndFabricBWReceivedAfterUrgLatency = + soc->ideal_dram_bw_after_urgent_percent; // there's always that one bastard variable that's so long it throws everything out of alignment! + mode_lib->vba.UrgentLatency = soc->urgent_latency_us; + mode_lib->vba.RoundTripPingLatencyCycles = soc->round_trip_ping_latency_dcfclk_cycles; + mode_lib->vba.UrgentOutOfOrderReturnPerChannel = soc->urgent_out_of_order_return_per_channel_bytes; + mode_lib->vba.WritebackLatency = soc->writeback_latency_us; + mode_lib->vba.SRExitTime = soc->sr_exit_time_us; + mode_lib->vba.SREnterPlusExitTime = soc->sr_enter_plus_exit_time_us; + mode_lib->vba.DRAMClockChangeLatency = soc->dram_clock_change_latency_us; + mode_lib->vba.Downspreading = soc->downspread_percent; + mode_lib->vba.DRAMChannelWidth = soc->dram_channel_width_bytes; // new! + mode_lib->vba.FabricDatapathToDCNDataReturn = soc->fabric_datapath_to_dcn_data_return_bytes; // new! + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading = soc->dcn_downspread_percent; // new + mode_lib->vba.DISPCLKDPPCLKVCOSpeed = soc->dispclk_dppclk_vco_speed_mhz; // new + mode_lib->vba.VMMPageSize = soc->vmm_page_size_bytes; + // Set the voltage scaling clocks as the defaults. Most of these will + // be set to different values by the test + for (i = 0; i < DC__VOLTAGE_STATES; ++i) + if (soc->clock_limits[i].state == mode_lib->vba.VoltageLevel) + break; + + mode_lib->vba.DCFCLK = soc->clock_limits[i].dcfclk_mhz; + mode_lib->vba.SOCCLK = soc->clock_limits[i].socclk_mhz; + mode_lib->vba.DRAMSpeed = soc->clock_limits[i].dram_speed_mhz; + mode_lib->vba.FabricClock = soc->clock_limits[i].fabricclk_mhz; + + mode_lib->vba.XFCBusTransportTime = soc->xfc_bus_transport_time_us; + mode_lib->vba.XFCXBUFLatencyTolerance = soc->xfc_xbuf_latency_tolerance_us; +} + +static void fetch_ip_params(struct display_mode_lib *mode_lib) +{ + ip_params_st *ip = &mode_lib->vba.ip; + + // IP Parameters + mode_lib->vba.MaxDCHUBToPSCLThroughput = ip->max_dchub_pscl_bw_pix_per_clk; + mode_lib->vba.MaxPSCLToLBThroughput = ip->max_pscl_lb_bw_pix_per_clk; + mode_lib->vba.ROBBufferSizeInKByte = ip->rob_buffer_size_kbytes; + mode_lib->vba.DETBufferSizeInKByte = ip->det_buffer_size_kbytes; + mode_lib->vba.PixelChunkSizeInKByte = ip->pixel_chunk_size_kbytes; + mode_lib->vba.MetaChunkSize = ip->meta_chunk_size_kbytes; + mode_lib->vba.PTEChunkSize = ip->pte_chunk_size_kbytes; + mode_lib->vba.WritebackChunkSize = ip->writeback_chunk_size_kbytes; + mode_lib->vba.LineBufferSize = ip->line_buffer_size_bits; + mode_lib->vba.MaxLineBufferLines = ip->max_line_buffer_lines; + mode_lib->vba.PTEBufferSizeInRequests = ip->dpte_buffer_size_in_pte_reqs; + mode_lib->vba.DPPOutputBufferPixels = ip->dpp_output_buffer_pixels; + mode_lib->vba.OPPOutputBufferLines = ip->opp_output_buffer_lines; + mode_lib->vba.WritebackInterfaceLumaBufferSize = ip->writeback_luma_buffer_size_kbytes; + mode_lib->vba.WritebackInterfaceChromaBufferSize = ip->writeback_chroma_buffer_size_kbytes; + mode_lib->vba.WritebackChromaLineBufferWidth = ip->writeback_chroma_line_buffer_width_pixels; + mode_lib->vba.MaxPageTableLevels = ip->max_page_table_levels; + mode_lib->vba.MaxInterDCNTileRepeaters = ip->max_inter_dcn_tile_repeaters; + mode_lib->vba.NumberOfDSC = ip->num_dsc; + mode_lib->vba.ODMCapability = ip->odm_capable; + mode_lib->vba.DISPCLKRampingMargin = ip->dispclk_ramp_margin_percent; + + mode_lib->vba.XFCSupported = ip->xfc_supported; + mode_lib->vba.XFCFillBWOverhead = ip->xfc_fill_bw_overhead_percent; + mode_lib->vba.XFCFillConstant = ip->xfc_fill_constant_bytes; + mode_lib->vba.DPPCLKDelaySubtotal = ip->dppclk_delay_subtotal; + mode_lib->vba.DPPCLKDelaySCL = ip->dppclk_delay_scl; + mode_lib->vba.DPPCLKDelaySCLLBOnly = ip->dppclk_delay_scl_lb_only; + mode_lib->vba.DPPCLKDelayCNVCFormater = ip->dppclk_delay_cnvc_formatter; + mode_lib->vba.DPPCLKDelayCNVCCursor = ip->dppclk_delay_cnvc_cursor; + mode_lib->vba.DISPCLKDelaySubtotal = ip->dispclk_delay_subtotal; + + mode_lib->vba.ProgressiveToInterlaceUnitInOPP = ip->ptoi_supported; + + mode_lib->vba.PDEProcessingBufIn64KBReqs = ip->pde_proc_buffer_size_64k_reqs; +} + +static void fetch_pipe_params(struct display_mode_lib *mode_lib) +{ + display_e2e_pipe_params_st *pipes = mode_lib->vba.cache_pipes; + ip_params_st *ip = &mode_lib->vba.ip; + + unsigned int OTGInstPlane[DC__NUM_DPP]; + unsigned int j, k; + bool PlaneVisited[DC__NUM_DPP]; + bool visited[DC__NUM_PIPES__MAX]; + + // Convert Pipes to Planes + for (k = 0; k < mode_lib->vba.cache_num_pipes; ++k) + visited[k] = false; + + mode_lib->vba.NumberOfActivePlanes = 0; + for (j = 0; j < mode_lib->vba.cache_num_pipes; ++j) { + display_pipe_source_params_st *src = &pipes[j].pipe.src; + display_pipe_dest_params_st *dst = &pipes[j].pipe.dest; + scaler_ratio_depth_st *scl = &pipes[j].pipe.scale_ratio_depth; + scaler_taps_st *taps = &pipes[j].pipe.scale_taps; + display_output_params_st *dout = &pipes[j].dout; + display_clocks_and_cfg_st *clks = &pipes[j].clks_cfg; + + if (visited[j]) + continue; + visited[j] = true; + + mode_lib->vba.pipe_plane[j] = mode_lib->vba.NumberOfActivePlanes; + + mode_lib->vba.DPPPerPlane[mode_lib->vba.NumberOfActivePlanes] = 1; + mode_lib->vba.SourceScan[mode_lib->vba.NumberOfActivePlanes] = (enum scan_direction_class)(src->source_scan); + mode_lib->vba.ViewportWidth[mode_lib->vba.NumberOfActivePlanes] = src->viewport_width; + mode_lib->vba.ViewportHeight[mode_lib->vba.NumberOfActivePlanes] = src->viewport_height; + mode_lib->vba.ViewportYStartY[mode_lib->vba.NumberOfActivePlanes] = src->viewport_y_y; + mode_lib->vba.ViewportYStartC[mode_lib->vba.NumberOfActivePlanes] = src->viewport_y_c; + mode_lib->vba.PitchY[mode_lib->vba.NumberOfActivePlanes] = src->data_pitch; + mode_lib->vba.PitchC[mode_lib->vba.NumberOfActivePlanes] = src->data_pitch_c; + mode_lib->vba.DCCMetaPitchY[mode_lib->vba.NumberOfActivePlanes] = src->meta_pitch; + mode_lib->vba.HRatio[mode_lib->vba.NumberOfActivePlanes] = scl->hscl_ratio; + mode_lib->vba.VRatio[mode_lib->vba.NumberOfActivePlanes] = scl->vscl_ratio; + mode_lib->vba.ScalerEnabled[mode_lib->vba.NumberOfActivePlanes] = scl->scl_enable; + mode_lib->vba.Interlace[mode_lib->vba.NumberOfActivePlanes] = dst->interlaced; + if (mode_lib->vba.Interlace[mode_lib->vba.NumberOfActivePlanes]) + mode_lib->vba.VRatio[mode_lib->vba.NumberOfActivePlanes] *= 2.0; + mode_lib->vba.htaps[mode_lib->vba.NumberOfActivePlanes] = taps->htaps; + mode_lib->vba.vtaps[mode_lib->vba.NumberOfActivePlanes] = taps->vtaps; + mode_lib->vba.HTAPsChroma[mode_lib->vba.NumberOfActivePlanes] = taps->htaps_c; + mode_lib->vba.VTAPsChroma[mode_lib->vba.NumberOfActivePlanes] = taps->vtaps_c; + mode_lib->vba.HTotal[mode_lib->vba.NumberOfActivePlanes] = dst->htotal; + mode_lib->vba.VTotal[mode_lib->vba.NumberOfActivePlanes] = dst->vtotal; + mode_lib->vba.DCCEnable[mode_lib->vba.NumberOfActivePlanes] = + src->dcc_use_global ? ip->dcc_supported : src->dcc & ip->dcc_supported; + mode_lib->vba.DCCRate[mode_lib->vba.NumberOfActivePlanes] = src->dcc_rate; + mode_lib->vba.SourcePixelFormat[mode_lib->vba.NumberOfActivePlanes] = (enum source_format_class)(src->source_format); + mode_lib->vba.HActive[mode_lib->vba.NumberOfActivePlanes] = dst->hactive; + mode_lib->vba.VActive[mode_lib->vba.NumberOfActivePlanes] = dst->vactive; + mode_lib->vba.SurfaceTiling[mode_lib->vba.NumberOfActivePlanes] = (enum dm_swizzle_mode)(src->sw_mode); + mode_lib->vba.ScalerRecoutWidth[mode_lib->vba.NumberOfActivePlanes] = dst->recout_width; // TODO: or should this be full_recout_width???...maybe only when in hsplit mode? + mode_lib->vba.ODMCombineEnabled[mode_lib->vba.NumberOfActivePlanes] = dst->odm_combine; + mode_lib->vba.OutputFormat[mode_lib->vba.NumberOfActivePlanes] = (enum output_format_class)(dout->output_format); + mode_lib->vba.Output[mode_lib->vba.NumberOfActivePlanes] = (enum output_encoder_class)(dout->output_type); + mode_lib->vba.OutputBpp[mode_lib->vba.NumberOfActivePlanes] = dout->output_bpp; + mode_lib->vba.DSCEnabled[mode_lib->vba.NumberOfActivePlanes] = dout->dsc_enable; + mode_lib->vba.NumberOfDSCSlices[mode_lib->vba.NumberOfActivePlanes] = dout->dsc_slices; + mode_lib->vba.DSCInputBitPerComponent[mode_lib->vba.NumberOfActivePlanes] = + dout->output_bpc == 0 ? 12 : dout->output_bpc; + mode_lib->vba.WritebackEnable[mode_lib->vba.NumberOfActivePlanes] = dout->wb_enable; + mode_lib->vba.WritebackSourceHeight[mode_lib->vba.NumberOfActivePlanes] = dout->wb.wb_src_height; + mode_lib->vba.WritebackDestinationWidth[mode_lib->vba.NumberOfActivePlanes] = dout->wb.wb_dst_width; + mode_lib->vba.WritebackDestinationHeight[mode_lib->vba.NumberOfActivePlanes] = dout->wb.wb_dst_height; + mode_lib->vba.WritebackPixelFormat[mode_lib->vba.NumberOfActivePlanes] = (enum source_format_class)(dout->wb.wb_pixel_format); + mode_lib->vba.WritebackLumaHTaps[mode_lib->vba.NumberOfActivePlanes] = dout->wb.wb_htaps_luma; + mode_lib->vba.WritebackLumaVTaps[mode_lib->vba.NumberOfActivePlanes] = dout->wb.wb_vtaps_luma; + mode_lib->vba.WritebackChromaHTaps[mode_lib->vba.NumberOfActivePlanes] = dout->wb.wb_htaps_chroma; + mode_lib->vba.WritebackChromaVTaps[mode_lib->vba.NumberOfActivePlanes] = dout->wb.wb_vtaps_chroma; + mode_lib->vba.WritebackHRatio[mode_lib->vba.NumberOfActivePlanes] = dout->wb.wb_hratio; + mode_lib->vba.WritebackVRatio[mode_lib->vba.NumberOfActivePlanes] = dout->wb.wb_vratio; + + mode_lib->vba.DynamicMetadataEnable[mode_lib->vba.NumberOfActivePlanes] = src->dynamic_metadata_enable; + mode_lib->vba.DynamicMetadataLinesBeforeActiveRequired[mode_lib->vba.NumberOfActivePlanes] = + src->dynamic_metadata_lines_before_active; + mode_lib->vba.DynamicMetadataTransmittedBytes[mode_lib->vba.NumberOfActivePlanes] = + src->dynamic_metadata_xmit_bytes; + + mode_lib->vba.XFCEnabled[mode_lib->vba.NumberOfActivePlanes] = src->xfc_enable && ip->xfc_supported; + mode_lib->vba.XFCSlvChunkSize = src->xfc_params.xfc_slv_chunk_size_bytes; + mode_lib->vba.XFCTSlvVupdateOffset = src->xfc_params.xfc_tslv_vupdate_offset_us; + mode_lib->vba.XFCTSlvVupdateWidth = src->xfc_params.xfc_tslv_vupdate_width_us; + mode_lib->vba.XFCTSlvVreadyOffset = src->xfc_params.xfc_tslv_vready_offset_us; + mode_lib->vba.PixelClock[mode_lib->vba.NumberOfActivePlanes] = dst->pixel_rate_mhz; + mode_lib->vba.DPPCLK[mode_lib->vba.NumberOfActivePlanes] = clks->dppclk_mhz; + if (ip->is_line_buffer_bpp_fixed) + mode_lib->vba.LBBitPerPixel[mode_lib->vba.NumberOfActivePlanes] = ip->line_buffer_fixed_bpp; + else { + unsigned int lb_depth; + + switch (scl->lb_depth) { + case dm_lb_6: + lb_depth = 18; + break; + case dm_lb_8: + lb_depth = 24; + break; + case dm_lb_10: + lb_depth = 30; + break; + case dm_lb_12: + lb_depth = 36; + break; + case dm_lb_16: + lb_depth = 48; + break; + default: + lb_depth = 36; + } + mode_lib->vba.LBBitPerPixel[mode_lib->vba.NumberOfActivePlanes] = lb_depth; + } + mode_lib->vba.NumberOfCursors[mode_lib->vba.NumberOfActivePlanes] = 0; + // The DML spreadsheet assumes that the two cursors utilize the same amount of bandwidth. We'll + // calculate things a little more accurately + for (k = 0; k < DC__NUM_CURSOR; ++k) { + switch (k) { + case 0: + mode_lib->vba.CursorBPP[mode_lib->vba.NumberOfActivePlanes][0] = CursorBppEnumToBits((enum cursor_bpp)(src->cur0_bpp)); + mode_lib->vba.CursorWidth[mode_lib->vba.NumberOfActivePlanes][0] = src->cur0_src_width; + if (src->cur0_src_width > 0) + mode_lib->vba.NumberOfCursors[mode_lib->vba.NumberOfActivePlanes]++; + break; + case 1: + mode_lib->vba.CursorBPP[mode_lib->vba.NumberOfActivePlanes][1] = CursorBppEnumToBits((enum cursor_bpp)(src->cur1_bpp)); + mode_lib->vba.CursorWidth[mode_lib->vba.NumberOfActivePlanes][1] = src->cur1_src_width; + if (src->cur1_src_width > 0) + mode_lib->vba.NumberOfCursors[mode_lib->vba.NumberOfActivePlanes]++; + break; + default: + dml_print("ERROR: Number of cursors specified exceeds supported maximum\n"); + } + } + + OTGInstPlane[mode_lib->vba.NumberOfActivePlanes] = dst->otg_inst; + + if (dst->odm_combine && !src->is_hsplit) + dml_print("ERROR: ODM Combine is specified but is_hsplit has not be specified for pipe %i\n", + j); + + if (src->is_hsplit) { + for (k = j + 1; k < mode_lib->vba.cache_num_pipes; ++k) { + display_pipe_source_params_st *src_k = &pipes[k].pipe.src; + display_output_params_st *dout_k = &pipes[k].dout; + + if (src_k->is_hsplit && !visited[k] + && src->hsplit_grp == src_k->hsplit_grp) { + mode_lib->vba.pipe_plane[k] = mode_lib->vba.NumberOfActivePlanes; + mode_lib->vba.DPPPerPlane[mode_lib->vba.NumberOfActivePlanes]++; + if (mode_lib->vba.SourceScan[mode_lib->vba.NumberOfActivePlanes] == dm_horz) + mode_lib->vba.ViewportWidth[mode_lib->vba.NumberOfActivePlanes] += + src_k->viewport_width; + else + mode_lib->vba.ViewportHeight[mode_lib->vba.NumberOfActivePlanes] += + src_k->viewport_height; + + mode_lib->vba.NumberOfDSCSlices[mode_lib->vba.NumberOfActivePlanes] += + dout_k->dsc_slices; + visited[k] = true; + } + } + } + + mode_lib->vba.NumberOfActivePlanes++; + } + + // handle overlays through dml_ml->vba.BlendingAndTiming + // dml_ml->vba.BlendingAndTiming tells you which instance to look at to get timing, the so called 'master' + + for (j = 0; j < mode_lib->vba.NumberOfActivePlanes; ++j) + PlaneVisited[j] = false; + + for (j = 0; j < mode_lib->vba.NumberOfActivePlanes; ++j) { + for (k = j + 1; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (!PlaneVisited[k] && OTGInstPlane[j] == OTGInstPlane[k]) { + // doesn't matter, so choose the smaller one + mode_lib->vba.BlendingAndTiming[j] = j; + PlaneVisited[j] = true; + mode_lib->vba.BlendingAndTiming[k] = j; + PlaneVisited[k] = true; + } + } + + if (!PlaneVisited[j]) { + mode_lib->vba.BlendingAndTiming[j] = j; + PlaneVisited[j] = true; + } + } + + // TODO: dml_ml->vba.ODMCombineEnabled => 2 * dml_ml->vba.DPPPerPlane...actually maybe not since all pipes are specified + // Do we want the dscclk to automatically be halved? Guess not since the value is specified + + mode_lib->vba.SynchronizedVBlank = pipes[0].pipe.dest.synchronized_vblank_all_planes; + for (k = 1; k < mode_lib->vba.cache_num_pipes; ++k) + ASSERT(mode_lib->vba.SynchronizedVBlank == pipes[k].pipe.dest.synchronized_vblank_all_planes); + + mode_lib->vba.VirtualMemoryEnable = 0; + mode_lib->vba.OverridePageTableLevels = 0; + + for (k = 0; k < mode_lib->vba.cache_num_pipes; ++k) { + mode_lib->vba.VirtualMemoryEnable |= pipes[k].pipe.src.vm; + mode_lib->vba.OverridePageTableLevels = + (pipes[k].pipe.src.vm_levels_force_en + && mode_lib->vba.OverridePageTableLevels + < pipes[k].pipe.src.vm_levels_force) ? + pipes[k].pipe.src.vm_levels_force : + mode_lib->vba.OverridePageTableLevels; + } + + if (mode_lib->vba.OverridePageTableLevels) + mode_lib->vba.MaxPageTableLevels = mode_lib->vba.OverridePageTableLevels; + + mode_lib->vba.VirtualMemoryEnable &= ip->pte_enable; + + mode_lib->vba.FabricAndDRAMBandwidth = dml_min(mode_lib->vba.DRAMSpeed * mode_lib->vba.NumberOfChannels * mode_lib->vba.DRAMChannelWidth, + mode_lib->vba.FabricClock * mode_lib->vba.FabricDatapathToDCNDataReturn) / 1000.0; + + // TODO: Must be consistent across all pipes + // DCCProgrammingAssumesScanDirectionUnknown = src.dcc_scan_dir_unknown; +} + +static void recalculate(struct display_mode_lib *mode_lib) +{ + ModeSupportAndSystemConfiguration(mode_lib); + PixelClockAdjustmentForProgressiveToInterlaceUnit(mode_lib); + DisplayPipeConfiguration(mode_lib); + DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation(mode_lib); +} + +// in wm mode we pull the parameters needed from the display_e2e_pipe_params_st structs +// rather than working them out as in recalculate_ms +static void recalculate_params(struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *pipes, + unsigned int num_pipes) +{ + // This is only safe to use memcmp because there are non-POD types in struct display_mode_lib + if (memcmp(&mode_lib->soc, &mode_lib->vba.soc, sizeof(mode_lib->vba.soc)) != 0 + || memcmp(&mode_lib->ip, &mode_lib->vba.ip, sizeof(mode_lib->vba.ip)) != 0 + || memcmp(&mode_lib->me, &mode_lib->vba.me, sizeof(mode_lib->vba.me)) != 0 + || num_pipes != mode_lib->vba.cache_num_pipes + || memcmp(pipes, mode_lib->vba.cache_pipes, sizeof(display_e2e_pipe_params_st) * num_pipes) != 0) { + mode_lib->vba.soc = mode_lib->soc; + mode_lib->vba.ip = mode_lib->ip; + mode_lib->vba.me = mode_lib->me; + memcpy(mode_lib->vba.cache_pipes, pipes, sizeof(*pipes) * num_pipes); + mode_lib->vba.cache_num_pipes = num_pipes; + recalculate(mode_lib); + } +} + +static void ModeSupportAndSystemConfiguration(struct display_mode_lib *mode_lib) +{ + soc_bounding_box_st *soc = &mode_lib->vba.soc; + unsigned int i, k; + unsigned int total_pipes = 0; + + mode_lib->vba.VoltageLevel = mode_lib->vba.cache_pipes[0].clks_cfg.voltage; + for (i = 1; i < mode_lib->vba.cache_num_pipes; ++i) + ASSERT(mode_lib->vba.VoltageLevel == -1 || mode_lib->vba.VoltageLevel == mode_lib->vba.cache_pipes[i].clks_cfg.voltage); + + mode_lib->vba.DCFCLK = mode_lib->vba.cache_pipes[0].clks_cfg.dcfclk_mhz; + mode_lib->vba.SOCCLK = mode_lib->vba.cache_pipes[0].clks_cfg.socclk_mhz; + + if (mode_lib->vba.cache_pipes[0].clks_cfg.dispclk_mhz > 0.0) + mode_lib->vba.DISPCLK = mode_lib->vba.cache_pipes[0].clks_cfg.dispclk_mhz; + else + mode_lib->vba.DISPCLK = soc->clock_limits[mode_lib->vba.VoltageLevel].dispclk_mhz; + + fetch_socbb_params(mode_lib); + fetch_ip_params(mode_lib); + fetch_pipe_params(mode_lib); + + // Total Available Pipes Support Check + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) + total_pipes += mode_lib->vba.DPPPerPlane[k]; + ASSERT(total_pipes <= DC__NUM_DPP); +} + +static double adjust_ReturnBW(struct display_mode_lib *mode_lib, double ReturnBW, bool DCCEnabledAnyPlane, double ReturnBandwidthToDCN) +{ + double CriticalCompression; + + if (DCCEnabledAnyPlane && ReturnBandwidthToDCN > mode_lib->vba.DCFCLK * mode_lib->vba.ReturnBusWidth / 4.0) + ReturnBW = + dml_min(ReturnBW, + ReturnBandwidthToDCN * 4 + * (1.0 + - mode_lib->vba.UrgentLatency + / ((mode_lib->vba.ROBBufferSizeInKByte + - mode_lib->vba.PixelChunkSizeInKByte) + * 1024 + / ReturnBandwidthToDCN + - mode_lib->vba.DCFCLK + * mode_lib->vba.ReturnBusWidth + / 4) + + mode_lib->vba.UrgentLatency)); + + CriticalCompression = 2.0 * mode_lib->vba.ReturnBusWidth * mode_lib->vba.DCFCLK * mode_lib->vba.UrgentLatency + / (ReturnBandwidthToDCN * mode_lib->vba.UrgentLatency + + (mode_lib->vba.ROBBufferSizeInKByte - mode_lib->vba.PixelChunkSizeInKByte) * 1024); + + if (DCCEnabledAnyPlane && CriticalCompression > 1.0 && CriticalCompression < 4.0) + ReturnBW = + dml_min(ReturnBW, + 4.0 * ReturnBandwidthToDCN + * (mode_lib->vba.ROBBufferSizeInKByte + - mode_lib->vba.PixelChunkSizeInKByte) + * 1024 * mode_lib->vba.ReturnBusWidth * mode_lib->vba.DCFCLK + * mode_lib->vba.UrgentLatency + / dml_pow((ReturnBandwidthToDCN + * mode_lib->vba.UrgentLatency + + (mode_lib->vba.ROBBufferSizeInKByte + - mode_lib->vba.PixelChunkSizeInKByte) + * 1024), + 2)); + + return ReturnBW; +} + +static unsigned int dscceComputeDelay(unsigned int bpc, + double bpp, + unsigned int sliceWidth, + unsigned int numSlices, + enum output_format_class pixelFormat) +{ + // valid bpc = source bits per component in the set of {8, 10, 12} + // valid bpp = increments of 1/16 of a bit + // min = 6/7/8 in N420/N422/444, respectively + // max = such that compression is 1:1 + //valid sliceWidth = number of pixels per slice line, must be less than or equal to 5184/numSlices (or 4096/numSlices in 420 mode) + //valid numSlices = number of slices in the horiziontal direction per DSC engine in the set of {1, 2, 3, 4} + //valid pixelFormat = pixel/color format in the set of {:N444_RGB, :S422, :N422, :N420} + + // fixed value + unsigned int rcModelSize = 8192; + + // N422/N420 operate at 2 pixels per clock + unsigned int pixelsPerClock, lstall, D, initalXmitDelay, w, s, ix, wx, p, l0, a, ax, l, Delay, + pixels; + + if (pixelFormat == dm_n422 || pixelFormat == dm_420) + pixelsPerClock = 2; + // #all other modes operate at 1 pixel per clock + else + pixelsPerClock = 1; + + //initial transmit delay as per PPS + initalXmitDelay = dml_round(rcModelSize / 2.0 / bpp / pixelsPerClock); + + //compute ssm delay + if (bpc == 8) + D = 81; + else if (bpc == 10) + D = 89; + else + D = 113; + + //divide by pixel per cycle to compute slice width as seen by DSC + w = sliceWidth / pixelsPerClock; + + //422 mode has an additional cycle of delay + if (pixelFormat == dm_s422) + s = 1; + else + s = 0; + + //main calculation for the dscce + ix = initalXmitDelay + 45; + wx = (w + 2) / 3; + p = 3 * wx - w; + l0 = ix / w; + a = ix + p * l0; + ax = (a + 2) / 3 + D + 6 + 1; + l = (ax + wx - 1) / wx; + if ((ix % w) == 0 && p != 0) + lstall = 1; + else + lstall = 0; + Delay = l * wx * (numSlices - 1) + ax + s + lstall + 22; + + //dsc processes 3 pixel containers per cycle and a container can contain 1 or 2 pixels + pixels = Delay * 3 * pixelsPerClock; + return pixels; +} + +static unsigned int dscComputeDelay(enum output_format_class pixelFormat) +{ + unsigned int Delay = 0; + + if (pixelFormat == dm_420) { + // sfr + Delay = Delay + 2; + // dsccif + Delay = Delay + 0; + // dscc - input deserializer + Delay = Delay + 3; + // dscc gets pixels every other cycle + Delay = Delay + 2; + // dscc - input cdc fifo + Delay = Delay + 12; + // dscc gets pixels every other cycle + Delay = Delay + 13; + // dscc - cdc uncertainty + Delay = Delay + 2; + // dscc - output cdc fifo + Delay = Delay + 7; + // dscc gets pixels every other cycle + Delay = Delay + 3; + // dscc - cdc uncertainty + Delay = Delay + 2; + // dscc - output serializer + Delay = Delay + 1; + // sft + Delay = Delay + 1; + } else if (pixelFormat == dm_n422) { + // sfr + Delay = Delay + 2; + // dsccif + Delay = Delay + 1; + // dscc - input deserializer + Delay = Delay + 5; + // dscc - input cdc fifo + Delay = Delay + 25; + // dscc - cdc uncertainty + Delay = Delay + 2; + // dscc - output cdc fifo + Delay = Delay + 10; + // dscc - cdc uncertainty + Delay = Delay + 2; + // dscc - output serializer + Delay = Delay + 1; + // sft + Delay = Delay + 1; + } else { + // sfr + Delay = Delay + 2; + // dsccif + Delay = Delay + 0; + // dscc - input deserializer + Delay = Delay + 3; + // dscc - input cdc fifo + Delay = Delay + 12; + // dscc - cdc uncertainty + Delay = Delay + 2; + // dscc - output cdc fifo + Delay = Delay + 7; + // dscc - output serializer + Delay = Delay + 1; + // dscc - cdc uncertainty + Delay = Delay + 2; + // sft + Delay = Delay + 1; + } + + return Delay; +} + +static bool CalculatePrefetchSchedule(struct display_mode_lib *mode_lib, + double DPPCLK, + double DISPCLK, + double PixelClock, + double DCFClkDeepSleep, + unsigned int DSCDelay, + unsigned int DPPPerPlane, + bool ScalerEnabled, + unsigned int NumberOfCursors, + double DPPCLKDelaySubtotal, + double DPPCLKDelaySCL, + double DPPCLKDelaySCLLBOnly, + double DPPCLKDelayCNVCFormater, + double DPPCLKDelayCNVCCursor, + double DISPCLKDelaySubtotal, + unsigned int ScalerRecoutWidth, + enum output_format_class OutputFormat, + unsigned int VBlank, + unsigned int HTotal, + unsigned int MaxInterDCNTileRepeaters, + unsigned int VStartup, + unsigned int PageTableLevels, + bool VirtualMemoryEnable, + bool DynamicMetadataEnable, + unsigned int DynamicMetadataLinesBeforeActiveRequired, + unsigned int DynamicMetadataTransmittedBytes, + bool DCCEnable, + double UrgentLatency, + double UrgentExtraLatency, + double TCalc, + unsigned int PDEAndMetaPTEBytesFrame, + unsigned int MetaRowByte, + unsigned int PixelPTEBytesPerRow, + double PrefetchSourceLinesY, + unsigned int SwathWidthY, + double BytePerPixelDETY, + double VInitPreFillY, + unsigned int MaxNumSwathY, + double PrefetchSourceLinesC, + double BytePerPixelDETC, + double VInitPreFillC, + unsigned int MaxNumSwathC, + unsigned int SwathHeightY, + unsigned int SwathHeightC, + double TWait, + bool XFCEnabled, + double XFCRemoteSurfaceFlipDelay, + bool InterlaceEnable, + bool ProgressiveToInterlaceUnitInOPP, + double *DSTXAfterScaler, + double *DSTYAfterScaler, + double *DestinationLinesForPrefetch, + double *PrefetchBandwidth, + double *DestinationLinesToRequestVMInVBlank, + double *DestinationLinesToRequestRowInVBlank, + double *VRatioPrefetchY, + double *VRatioPrefetchC, + double *RequiredPrefetchPixDataBW, + unsigned int *VStartupRequiredWhenNotEnoughTimeForDynamicMetadata, + double *Tno_bw) +{ + bool MyError = false; + unsigned int DPPCycles, DISPCLKCycles, VUpdateOffsetPix, VUpdateWidthPix, VReadyOffsetPix; + double DSTTotalPixelsAfterScaler, TotalRepeaterDelayTime; + double Tdm, LineTime, Tsetup; + double dst_y_prefetch_equ; + double Tsw_oto; + double prefetch_bw_oto; + double Tvm_oto; + double Tr0_oto; + double Tpre_oto; + double dst_y_prefetch_oto; + double TimeForFetchingMetaPTE = 0; + double TimeForFetchingRowInVBlank = 0; + double LinesToRequestPrefetchPixelData = 0; + + if (ScalerEnabled) + DPPCycles = DPPCLKDelaySubtotal + DPPCLKDelaySCL; + else + DPPCycles = DPPCLKDelaySubtotal + DPPCLKDelaySCLLBOnly; + + DPPCycles = DPPCycles + DPPCLKDelayCNVCFormater + NumberOfCursors * DPPCLKDelayCNVCCursor; + + DISPCLKCycles = DISPCLKDelaySubtotal; + + if (DPPCLK == 0.0 || DISPCLK == 0.0) + return true; + + *DSTXAfterScaler = DPPCycles * PixelClock / DPPCLK + DISPCLKCycles * PixelClock / DISPCLK + + DSCDelay; + + if (DPPPerPlane > 1) + *DSTXAfterScaler = *DSTXAfterScaler + ScalerRecoutWidth; + + if (OutputFormat == dm_420 || (InterlaceEnable && ProgressiveToInterlaceUnitInOPP)) + *DSTYAfterScaler = 1; + else + *DSTYAfterScaler = 0; + + DSTTotalPixelsAfterScaler = ((double)(*DSTYAfterScaler * HTotal)) + *DSTXAfterScaler; + *DSTYAfterScaler = dml_floor(DSTTotalPixelsAfterScaler / HTotal, 1); + *DSTXAfterScaler = DSTTotalPixelsAfterScaler - ((double)(*DSTYAfterScaler * HTotal)); + + VUpdateOffsetPix = dml_ceil(HTotal / 4.0, 1); + TotalRepeaterDelayTime = MaxInterDCNTileRepeaters * (2.0 / DPPCLK + 3.0 / DISPCLK); + VUpdateWidthPix = (14.0 / DCFClkDeepSleep + 12.0 / DPPCLK + TotalRepeaterDelayTime) + * PixelClock; + + VReadyOffsetPix = dml_max(150.0 / DPPCLK, + TotalRepeaterDelayTime + 20.0 / DCFClkDeepSleep + 10.0 / DPPCLK) + * PixelClock; + + Tsetup = (double)(VUpdateOffsetPix + VUpdateWidthPix + VReadyOffsetPix) / PixelClock; + + LineTime = (double)HTotal / PixelClock; + + if (DynamicMetadataEnable) { + double Tdmbf, Tdmec, Tdmsks; + + Tdm = dml_max(0.0, UrgentExtraLatency - TCalc); + Tdmbf = DynamicMetadataTransmittedBytes / 4.0 / DISPCLK; + Tdmec = LineTime; + if (DynamicMetadataLinesBeforeActiveRequired == 0) + Tdmsks = VBlank * LineTime / 2.0; + else + Tdmsks = DynamicMetadataLinesBeforeActiveRequired * LineTime; + if (InterlaceEnable && !ProgressiveToInterlaceUnitInOPP) + Tdmsks = Tdmsks / 2; + if (VStartup * LineTime + < Tsetup + TWait + UrgentExtraLatency + Tdmbf + Tdmec + Tdmsks) { + MyError = true; + *VStartupRequiredWhenNotEnoughTimeForDynamicMetadata = (Tsetup + TWait + + UrgentExtraLatency + Tdmbf + Tdmec + Tdmsks) / LineTime; + } else + *VStartupRequiredWhenNotEnoughTimeForDynamicMetadata = 0.0; + } else + Tdm = 0; + + if (VirtualMemoryEnable) { + if (PageTableLevels == 4) + *Tno_bw = UrgentExtraLatency + UrgentLatency; + else if (PageTableLevels == 3) + *Tno_bw = UrgentExtraLatency; + else + Tno_bw = 0; + } else if (DCCEnable) + *Tno_bw = LineTime; + else + *Tno_bw = LineTime / 4; + + dst_y_prefetch_equ = VStartup - dml_max(TCalc + TWait, XFCRemoteSurfaceFlipDelay) / LineTime + - (Tsetup + Tdm) / LineTime + - (*DSTYAfterScaler + *DSTXAfterScaler / HTotal); + + Tsw_oto = dml_max(PrefetchSourceLinesY, PrefetchSourceLinesC) * LineTime; + + prefetch_bw_oto = (MetaRowByte + PixelPTEBytesPerRow + + PrefetchSourceLinesY * SwathWidthY * dml_ceil(BytePerPixelDETY, 1) + + PrefetchSourceLinesC * SwathWidthY / 2 * dml_ceil(BytePerPixelDETC, 2)) + / Tsw_oto; + + if (VirtualMemoryEnable == true) { + Tvm_oto = + dml_max(*Tno_bw + PDEAndMetaPTEBytesFrame / prefetch_bw_oto, + dml_max(UrgentExtraLatency + + UrgentLatency + * (PageTableLevels + - 1), + LineTime / 4.0)); + } else + Tvm_oto = LineTime / 4.0; + + if ((VirtualMemoryEnable == true || DCCEnable == true)) { + Tr0_oto = dml_max((MetaRowByte + PixelPTEBytesPerRow) / prefetch_bw_oto, + dml_max(UrgentLatency, dml_max(LineTime - Tvm_oto, LineTime / 4))); + } else + Tr0_oto = LineTime - Tvm_oto; + + Tpre_oto = Tvm_oto + Tr0_oto + Tsw_oto; + + dst_y_prefetch_oto = Tpre_oto / LineTime; + + if (dst_y_prefetch_oto < dst_y_prefetch_equ) + *DestinationLinesForPrefetch = dst_y_prefetch_oto; + else + *DestinationLinesForPrefetch = dst_y_prefetch_equ; + + *DestinationLinesForPrefetch = dml_floor(4.0 * (*DestinationLinesForPrefetch + 0.125), 1) / 4; + + dml_print("DML: VStartup: %d\n", VStartup); + dml_print("DML: TCalc: %f\n", TCalc); + dml_print("DML: TWait: %f\n", TWait); + dml_print("DML: XFCRemoteSurfaceFlipDelay: %f\n", XFCRemoteSurfaceFlipDelay); + dml_print("DML: LineTime: %f\n", LineTime); + dml_print("DML: Tsetup: %f\n", Tsetup); + dml_print("DML: Tdm: %f\n", Tdm); + dml_print("DML: DSTYAfterScaler: %f\n", *DSTYAfterScaler); + dml_print("DML: DSTXAfterScaler: %f\n", *DSTXAfterScaler); + dml_print("DML: HTotal: %d\n", HTotal); + + *PrefetchBandwidth = 0; + *DestinationLinesToRequestVMInVBlank = 0; + *DestinationLinesToRequestRowInVBlank = 0; + *VRatioPrefetchY = 0; + *VRatioPrefetchC = 0; + *RequiredPrefetchPixDataBW = 0; + if (*DestinationLinesForPrefetch > 1) { + *PrefetchBandwidth = (PDEAndMetaPTEBytesFrame + 2 * MetaRowByte + + 2 * PixelPTEBytesPerRow + + PrefetchSourceLinesY * SwathWidthY * dml_ceil(BytePerPixelDETY, 1) + + PrefetchSourceLinesC * SwathWidthY / 2 + * dml_ceil(BytePerPixelDETC, 2)) + / (*DestinationLinesForPrefetch * LineTime - *Tno_bw); + if (VirtualMemoryEnable) { + TimeForFetchingMetaPTE = + dml_max(*Tno_bw + + (double)PDEAndMetaPTEBytesFrame + / *PrefetchBandwidth, + dml_max(UrgentExtraLatency + + UrgentLatency + * (PageTableLevels + - 1), + LineTime / 4)); + } else { + if (NumberOfCursors > 0 || XFCEnabled) + TimeForFetchingMetaPTE = LineTime / 4; + else + TimeForFetchingMetaPTE = 0.0; + } + + if ((VirtualMemoryEnable == true || DCCEnable == true)) { + TimeForFetchingRowInVBlank = + dml_max((MetaRowByte + PixelPTEBytesPerRow) + / *PrefetchBandwidth, + dml_max(UrgentLatency, + dml_max(LineTime + - TimeForFetchingMetaPTE, + LineTime + / 4.0))); + } else { + if (NumberOfCursors > 0 || XFCEnabled) + TimeForFetchingRowInVBlank = LineTime - TimeForFetchingMetaPTE; + else + TimeForFetchingRowInVBlank = 0.0; + } + + *DestinationLinesToRequestVMInVBlank = dml_floor(4.0 * (TimeForFetchingMetaPTE / LineTime + 0.125), + 1) / 4.0; + + *DestinationLinesToRequestRowInVBlank = dml_floor(4.0 * (TimeForFetchingRowInVBlank / LineTime + 0.125), + 1) / 4.0; + + LinesToRequestPrefetchPixelData = + *DestinationLinesForPrefetch + - ((NumberOfCursors > 0 || VirtualMemoryEnable + || DCCEnable) ? + (*DestinationLinesToRequestVMInVBlank + + *DestinationLinesToRequestRowInVBlank) : + 0.0); + + if (LinesToRequestPrefetchPixelData > 0) { + + *VRatioPrefetchY = (double)PrefetchSourceLinesY + / LinesToRequestPrefetchPixelData; + *VRatioPrefetchY = dml_max(*VRatioPrefetchY, 1.0); + if ((SwathHeightY > 4) && (VInitPreFillY > 3)) { + if (LinesToRequestPrefetchPixelData > (VInitPreFillY - 3.0) / 2.0) { + *VRatioPrefetchY = + dml_max((double)PrefetchSourceLinesY + / LinesToRequestPrefetchPixelData, + (double)MaxNumSwathY + * SwathHeightY + / (LinesToRequestPrefetchPixelData + - (VInitPreFillY + - 3.0) + / 2.0)); + *VRatioPrefetchY = dml_max(*VRatioPrefetchY, 1.0); + } else { + MyError = true; + *VRatioPrefetchY = 0; + } + } + + *VRatioPrefetchC = (double)PrefetchSourceLinesC + / LinesToRequestPrefetchPixelData; + *VRatioPrefetchC = dml_max(*VRatioPrefetchC, 1.0); + + if ((SwathHeightC > 4)) { + if (LinesToRequestPrefetchPixelData > (VInitPreFillC - 3.0) / 2.0) { + *VRatioPrefetchC = + dml_max(*VRatioPrefetchC, + (double)MaxNumSwathC + * SwathHeightC + / (LinesToRequestPrefetchPixelData + - (VInitPreFillC + - 3.0) + / 2.0)); + *VRatioPrefetchC = dml_max(*VRatioPrefetchC, 1.0); + } else { + MyError = true; + *VRatioPrefetchC = 0; + } + } + + *RequiredPrefetchPixDataBW = + DPPPerPlane + * ((double)PrefetchSourceLinesY + / LinesToRequestPrefetchPixelData + * dml_ceil(BytePerPixelDETY, + 1) + + (double)PrefetchSourceLinesC + / LinesToRequestPrefetchPixelData + * dml_ceil(BytePerPixelDETC, + 2) + / 2) + * SwathWidthY / LineTime; + } else { + MyError = true; + *VRatioPrefetchY = 0; + *VRatioPrefetchC = 0; + *RequiredPrefetchPixDataBW = 0; + } + + } else { + MyError = true; + } + + if (MyError) { + *PrefetchBandwidth = 0; + TimeForFetchingMetaPTE = 0; + TimeForFetchingRowInVBlank = 0; + *DestinationLinesToRequestVMInVBlank = 0; + *DestinationLinesToRequestRowInVBlank = 0; + *DestinationLinesForPrefetch = 0; + LinesToRequestPrefetchPixelData = 0; + *VRatioPrefetchY = 0; + *VRatioPrefetchC = 0; + *RequiredPrefetchPixDataBW = 0; + } + + return MyError; +} + +static double CeilToDFSGranularity(double Clock, double VCOSpeed) +{ + return VCOSpeed * 4 / dml_floor(VCOSpeed * 4 / Clock, 1); +} + +static double FloorToDFSGranularity(double Clock, double VCOSpeed) +{ + return VCOSpeed * 4 / dml_ceil(VCOSpeed * 4 / Clock, 1); +} + +static double CalculatePrefetchSourceLines(struct display_mode_lib *mode_lib, + double VRatio, + double vtaps, + bool Interlace, + bool ProgressiveToInterlaceUnitInOPP, + unsigned int SwathHeight, + unsigned int ViewportYStart, + double *VInitPreFill, + unsigned int *MaxNumSwath) +{ + unsigned int MaxPartialSwath; + + if (ProgressiveToInterlaceUnitInOPP) + *VInitPreFill = dml_floor((VRatio + vtaps + 1) / 2.0, 1); + else + *VInitPreFill = dml_floor((VRatio + vtaps + 1 + Interlace * 0.5 * VRatio) / 2.0, 1); + + if (!mode_lib->vba.IgnoreViewportPositioning) { + + *MaxNumSwath = dml_ceil((*VInitPreFill - 1.0) / SwathHeight, 1) + 1.0; + + if (*VInitPreFill > 1.0) + MaxPartialSwath = (unsigned int)(*VInitPreFill - 2) % SwathHeight; + else + MaxPartialSwath = (unsigned int)(*VInitPreFill + SwathHeight - 2) % SwathHeight; + MaxPartialSwath = dml_max(1U, MaxPartialSwath); + + } else { + + if (ViewportYStart != 0) + dml_print("WARNING DML: using viewport y position of 0 even though actual viewport y position is non-zero in prefetch source lines calculation\n"); + + *MaxNumSwath = dml_ceil(*VInitPreFill / SwathHeight, 1); + + if (*VInitPreFill > 1.0) + MaxPartialSwath = (unsigned int)(*VInitPreFill - 1) % SwathHeight; + else + MaxPartialSwath = (unsigned int)(*VInitPreFill + SwathHeight - 1) % SwathHeight; + } + + return *MaxNumSwath * SwathHeight + MaxPartialSwath; +} + +static unsigned int CalculateVMAndRowBytes(struct display_mode_lib *mode_lib, + bool DCCEnable, + unsigned int BlockHeight256Bytes, + unsigned int BlockWidth256Bytes, + enum source_format_class SourcePixelFormat, + unsigned int SurfaceTiling, + unsigned int BytePerPixel, + enum scan_direction_class ScanDirection, + unsigned int ViewportWidth, + unsigned int ViewportHeight, + unsigned int SwathWidth, + bool VirtualMemoryEnable, + unsigned int VMMPageSize, + unsigned int PTEBufferSizeInRequests, + unsigned int PDEProcessingBufIn64KBReqs, + unsigned int Pitch, + unsigned int DCCMetaPitch, + unsigned int *MacroTileWidth, + unsigned int *MetaRowByte, + unsigned int *PixelPTEBytesPerRow, + bool *PTEBufferSizeNotExceeded, + unsigned int *dpte_row_height, + unsigned int *meta_row_height) +{ + unsigned int MetaRequestHeight; + unsigned int MetaRequestWidth; + unsigned int MetaSurfWidth; + unsigned int MetaSurfHeight; + unsigned int MPDEBytesFrame; + unsigned int MetaPTEBytesFrame; + unsigned int DCCMetaSurfaceBytes; + + unsigned int MacroTileSizeBytes; + unsigned int MacroTileHeight; + unsigned int DPDE0BytesFrame; + unsigned int ExtraDPDEBytesFrame; + unsigned int PDEAndMetaPTEBytesFrame; + + if (DCCEnable == true) { + MetaRequestHeight = 8 * BlockHeight256Bytes; + MetaRequestWidth = 8 * BlockWidth256Bytes; + if (ScanDirection == dm_horz) { + *meta_row_height = MetaRequestHeight; + MetaSurfWidth = dml_ceil((double)SwathWidth - 1, MetaRequestWidth) + + MetaRequestWidth; + *MetaRowByte = MetaSurfWidth * MetaRequestHeight * BytePerPixel / 256.0; + } else { + *meta_row_height = MetaRequestWidth; + MetaSurfHeight = dml_ceil((double)SwathWidth - 1, MetaRequestHeight) + + MetaRequestHeight; + *MetaRowByte = MetaSurfHeight * MetaRequestWidth * BytePerPixel / 256.0; + } + if (ScanDirection == dm_horz) { + DCCMetaSurfaceBytes = DCCMetaPitch + * (dml_ceil(ViewportHeight - 1, 64 * BlockHeight256Bytes) + + 64 * BlockHeight256Bytes) * BytePerPixel + / 256; + } else { + DCCMetaSurfaceBytes = DCCMetaPitch + * (dml_ceil((double)ViewportHeight - 1, + 64 * BlockHeight256Bytes) + + 64 * BlockHeight256Bytes) * BytePerPixel + / 256; + } + if (VirtualMemoryEnable == true) { + MetaPTEBytesFrame = (dml_ceil((double)(DCCMetaSurfaceBytes - VMMPageSize) + / (8 * VMMPageSize), + 1) + 1) * 64; + MPDEBytesFrame = 128 * (mode_lib->vba.MaxPageTableLevels - 1); + } else { + MetaPTEBytesFrame = 0; + MPDEBytesFrame = 0; + } + } else { + MetaPTEBytesFrame = 0; + MPDEBytesFrame = 0; + *MetaRowByte = 0; + } + + if (SurfaceTiling == dm_sw_linear) { + MacroTileSizeBytes = 256; + MacroTileHeight = 1; + } else if (SurfaceTiling == dm_sw_4kb_s || SurfaceTiling == dm_sw_4kb_s_x + || SurfaceTiling == dm_sw_4kb_d || SurfaceTiling == dm_sw_4kb_d_x) { + MacroTileSizeBytes = 4096; + MacroTileHeight = 4 * BlockHeight256Bytes; + } else if (SurfaceTiling == dm_sw_64kb_s || SurfaceTiling == dm_sw_64kb_s_t + || SurfaceTiling == dm_sw_64kb_s_x || SurfaceTiling == dm_sw_64kb_d + || SurfaceTiling == dm_sw_64kb_d_t || SurfaceTiling == dm_sw_64kb_d_x + || SurfaceTiling == dm_sw_64kb_r_x) { + MacroTileSizeBytes = 65536; + MacroTileHeight = 16 * BlockHeight256Bytes; + } else { + MacroTileSizeBytes = 262144; + MacroTileHeight = 32 * BlockHeight256Bytes; + } + *MacroTileWidth = MacroTileSizeBytes / BytePerPixel / MacroTileHeight; + + if (VirtualMemoryEnable == true && mode_lib->vba.MaxPageTableLevels > 1) { + if (ScanDirection == dm_horz) { + DPDE0BytesFrame = + 64 + * (dml_ceil(((Pitch + * (dml_ceil(ViewportHeight + - 1, + MacroTileHeight) + + MacroTileHeight) + * BytePerPixel) + - MacroTileSizeBytes) + / (8 + * 2097152), + 1) + 1); + } else { + DPDE0BytesFrame = + 64 + * (dml_ceil(((Pitch + * (dml_ceil((double)SwathWidth + - 1, + MacroTileHeight) + + MacroTileHeight) + * BytePerPixel) + - MacroTileSizeBytes) + / (8 + * 2097152), + 1) + 1); + } + ExtraDPDEBytesFrame = 128 * (mode_lib->vba.MaxPageTableLevels - 2); + } else { + DPDE0BytesFrame = 0; + ExtraDPDEBytesFrame = 0; + } + + PDEAndMetaPTEBytesFrame = MetaPTEBytesFrame + MPDEBytesFrame + DPDE0BytesFrame + + ExtraDPDEBytesFrame; + + if (VirtualMemoryEnable == true) { + unsigned int PTERequestSize; + unsigned int PixelPTEReqHeight; + unsigned int PixelPTEReqWidth; + double FractionOfPTEReturnDrop; + unsigned int EffectivePDEProcessingBufIn64KBReqs; + + if (SurfaceTiling == dm_sw_linear) { + PixelPTEReqHeight = 1; + PixelPTEReqWidth = 8.0 * VMMPageSize / BytePerPixel; + PTERequestSize = 64; + FractionOfPTEReturnDrop = 0; + } else if (MacroTileSizeBytes == 4096) { + PixelPTEReqHeight = MacroTileHeight; + PixelPTEReqWidth = 8 * *MacroTileWidth; + PTERequestSize = 64; + if (ScanDirection == dm_horz) + FractionOfPTEReturnDrop = 0; + else + FractionOfPTEReturnDrop = 7 / 8; + } else if (VMMPageSize == 4096 && MacroTileSizeBytes > 4096) { + PixelPTEReqHeight = 16 * BlockHeight256Bytes; + PixelPTEReqWidth = 16 * BlockWidth256Bytes; + PTERequestSize = 128; + FractionOfPTEReturnDrop = 0; + } else { + PixelPTEReqHeight = MacroTileHeight; + PixelPTEReqWidth = 8 * *MacroTileWidth; + PTERequestSize = 64; + FractionOfPTEReturnDrop = 0; + } + + if (SourcePixelFormat == dm_420_8 || SourcePixelFormat == dm_420_10) + EffectivePDEProcessingBufIn64KBReqs = PDEProcessingBufIn64KBReqs / 2; + else + EffectivePDEProcessingBufIn64KBReqs = PDEProcessingBufIn64KBReqs; + + if (SurfaceTiling == dm_sw_linear) { + *dpte_row_height = + dml_min(128, + 1 + << (unsigned int)dml_floor(dml_log2(dml_min((double)PTEBufferSizeInRequests + * PixelPTEReqWidth, + EffectivePDEProcessingBufIn64KBReqs + * 65536.0 + / BytePerPixel) + / Pitch), + 1)); + *PixelPTEBytesPerRow = PTERequestSize + * (dml_ceil((double)(Pitch * *dpte_row_height - 1) + / PixelPTEReqWidth, + 1) + 1); + } else if (ScanDirection == dm_horz) { + *dpte_row_height = PixelPTEReqHeight; + *PixelPTEBytesPerRow = PTERequestSize + * (dml_ceil(((double)SwathWidth - 1) / PixelPTEReqWidth, 1) + + 1); + } else { + *dpte_row_height = dml_min(PixelPTEReqWidth, *MacroTileWidth); + *PixelPTEBytesPerRow = PTERequestSize + * (dml_ceil(((double)SwathWidth - 1) + / PixelPTEReqHeight, + 1) + 1); + } + if (*PixelPTEBytesPerRow * (1 - FractionOfPTEReturnDrop) + <= 64 * PTEBufferSizeInRequests) { + *PTEBufferSizeNotExceeded = true; + } else { + *PTEBufferSizeNotExceeded = false; + } + } else { + *PixelPTEBytesPerRow = 0; + *PTEBufferSizeNotExceeded = true; + } + + return PDEAndMetaPTEBytesFrame; +} + +static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation(struct display_mode_lib *mode_lib) +{ + unsigned int j, k; + + mode_lib->vba.WritebackDISPCLK = 0.0; + mode_lib->vba.DISPCLKWithRamping = 0; + mode_lib->vba.DISPCLKWithoutRamping = 0; + mode_lib->vba.GlobalDPPCLK = 0.0; + + // dml_ml->vba.DISPCLK and dml_ml->vba.DPPCLK Calculation + // + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (mode_lib->vba.WritebackEnable[k]) { + mode_lib->vba.WritebackDISPCLK = dml_max(mode_lib->vba.WritebackDISPCLK, + CalculateWriteBackDISPCLK(mode_lib->vba.WritebackPixelFormat[k], + mode_lib->vba.PixelClock[k], + mode_lib->vba.WritebackHRatio[k], + mode_lib->vba.WritebackVRatio[k], + mode_lib->vba.WritebackLumaHTaps[k], + mode_lib->vba.WritebackLumaVTaps[k], + mode_lib->vba.WritebackChromaHTaps[k], + mode_lib->vba.WritebackChromaVTaps[k], + mode_lib->vba.WritebackDestinationWidth[k], + mode_lib->vba.HTotal[k], + mode_lib->vba.WritebackChromaLineBufferWidth)); + } + } + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (mode_lib->vba.HRatio[k] > 1) { + mode_lib->vba.PSCL_THROUGHPUT_LUMA[k] = dml_min(mode_lib->vba.MaxDCHUBToPSCLThroughput, + mode_lib->vba.MaxPSCLToLBThroughput * mode_lib->vba.HRatio[k] + / dml_ceil(mode_lib->vba.htaps[k] / 6.0, 1)); + } else { + mode_lib->vba.PSCL_THROUGHPUT_LUMA[k] = dml_min(mode_lib->vba.MaxDCHUBToPSCLThroughput, + mode_lib->vba.MaxPSCLToLBThroughput); + } + + mode_lib->vba.DPPCLKUsingSingleDPPLuma = + mode_lib->vba.PixelClock[k] + * dml_max(mode_lib->vba.vtaps[k] / 6.0 + * dml_min(1.0, + mode_lib->vba.HRatio[k]), + dml_max(mode_lib->vba.HRatio[k] + * mode_lib->vba.VRatio[k] + / mode_lib->vba.PSCL_THROUGHPUT_LUMA[k], + 1.0)); + + if ((mode_lib->vba.htaps[k] > 6 || mode_lib->vba.vtaps[k] > 6) + && mode_lib->vba.DPPCLKUsingSingleDPPLuma < 2 * mode_lib->vba.PixelClock[k]) { + mode_lib->vba.DPPCLKUsingSingleDPPLuma = 2 * mode_lib->vba.PixelClock[k]; + } + + if ((mode_lib->vba.SourcePixelFormat[k] != dm_420_8 && mode_lib->vba.SourcePixelFormat[k] != dm_420_10)) { + mode_lib->vba.PSCL_THROUGHPUT_CHROMA[k] = 0.0; + mode_lib->vba.DPPCLKUsingSingleDPP[k] = mode_lib->vba.DPPCLKUsingSingleDPPLuma; + } else { + if (mode_lib->vba.HRatio[k] > 1) { + mode_lib->vba.PSCL_THROUGHPUT_CHROMA[k] = + dml_min(mode_lib->vba.MaxDCHUBToPSCLThroughput, + mode_lib->vba.MaxPSCLToLBThroughput * mode_lib->vba.HRatio[k] + / 2 + / dml_ceil(mode_lib->vba.HTAPsChroma[k] + / 6.0, + 1.0)); + } else { + mode_lib->vba.PSCL_THROUGHPUT_CHROMA[k] = dml_min(mode_lib->vba.MaxDCHUBToPSCLThroughput, + mode_lib->vba.MaxPSCLToLBThroughput); + } + mode_lib->vba.DPPCLKUsingSingleDPPChroma = + mode_lib->vba.PixelClock[k] + * dml_max(mode_lib->vba.VTAPsChroma[k] / 6.0 + * dml_min(1.0, + mode_lib->vba.HRatio[k] + / 2), + dml_max(mode_lib->vba.HRatio[k] + * mode_lib->vba.VRatio[k] + / 4 + / mode_lib->vba.PSCL_THROUGHPUT_CHROMA[k], + 1.0)); + + if ((mode_lib->vba.HTAPsChroma[k] > 6 || mode_lib->vba.VTAPsChroma[k] > 6) + && mode_lib->vba.DPPCLKUsingSingleDPPChroma < 2 * mode_lib->vba.PixelClock[k]) { + mode_lib->vba.DPPCLKUsingSingleDPPChroma = 2 * mode_lib->vba.PixelClock[k]; + } + + mode_lib->vba.DPPCLKUsingSingleDPP[k] = dml_max(mode_lib->vba.DPPCLKUsingSingleDPPLuma, + mode_lib->vba.DPPCLKUsingSingleDPPChroma); + } + } + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (mode_lib->vba.BlendingAndTiming[k] != k) + continue; + if (mode_lib->vba.ODMCombineEnabled[k]) { + mode_lib->vba.DISPCLKWithRamping = + dml_max(mode_lib->vba.DISPCLKWithRamping, + mode_lib->vba.PixelClock[k] / 2 + * (1 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100) + * (1 + + mode_lib->vba.DISPCLKRampingMargin + / 100)); + mode_lib->vba.DISPCLKWithoutRamping = + dml_max(mode_lib->vba.DISPCLKWithoutRamping, + mode_lib->vba.PixelClock[k] / 2 + * (1 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100)); + } else if (!mode_lib->vba.ODMCombineEnabled[k]) { + mode_lib->vba.DISPCLKWithRamping = dml_max(mode_lib->vba.DISPCLKWithRamping, + mode_lib->vba.PixelClock[k] * (1 + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading / 100) + * (1 + mode_lib->vba.DISPCLKRampingMargin / 100)); + mode_lib->vba.DISPCLKWithoutRamping = + dml_max(mode_lib->vba.DISPCLKWithoutRamping, + mode_lib->vba.PixelClock[k] + * (1 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100)); + } + } + + mode_lib->vba.DISPCLKWithRamping = dml_max(mode_lib->vba.DISPCLKWithRamping, mode_lib->vba.WritebackDISPCLK); + mode_lib->vba.DISPCLKWithoutRamping = dml_max(mode_lib->vba.DISPCLKWithoutRamping, mode_lib->vba.WritebackDISPCLK); + + mode_lib->vba.MaxDispclk = mode_lib->vba.soc.clock_limits[NumberOfStates - 1].dispclk_mhz; + ASSERT(mode_lib->vba.DISPCLKDPPCLKVCOSpeed != 0); + mode_lib->vba.DISPCLKWithRampingRoundedToDFSGranularity = CeilToDFSGranularity( + mode_lib->vba.DISPCLKWithRamping, + mode_lib->vba.DISPCLKDPPCLKVCOSpeed); + mode_lib->vba.DISPCLKWithoutRampingRoundedToDFSGranularity = CeilToDFSGranularity( + mode_lib->vba.DISPCLKWithoutRamping, + mode_lib->vba.DISPCLKDPPCLKVCOSpeed); + mode_lib->vba.MaxDispclkRoundedToDFSGranularity = FloorToDFSGranularity( + mode_lib->vba.MaxDispclk, + mode_lib->vba.DISPCLKDPPCLKVCOSpeed); + if (mode_lib->vba.DISPCLKWithoutRampingRoundedToDFSGranularity + > mode_lib->vba.MaxDispclkRoundedToDFSGranularity) { + mode_lib->vba.DISPCLK_calculated = mode_lib->vba.DISPCLKWithoutRampingRoundedToDFSGranularity; + } else if (mode_lib->vba.DISPCLKWithRampingRoundedToDFSGranularity + > mode_lib->vba.MaxDispclkRoundedToDFSGranularity) { + mode_lib->vba.DISPCLK_calculated = mode_lib->vba.MaxDispclkRoundedToDFSGranularity; + } else { + mode_lib->vba.DISPCLK_calculated = mode_lib->vba.DISPCLKWithRampingRoundedToDFSGranularity; + } + DTRACE(" dispclk_mhz (calculated) = %f", mode_lib->vba.DISPCLK_calculated); + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + mode_lib->vba.DPPCLK_calculated[k] = mode_lib->vba.DPPCLKUsingSingleDPP[k] / mode_lib->vba.DPPPerPlane[k] + * (1 + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading / 100); + mode_lib->vba.GlobalDPPCLK = dml_max(mode_lib->vba.GlobalDPPCLK, mode_lib->vba.DPPCLK_calculated[k]); + } + mode_lib->vba.GlobalDPPCLK = CeilToDFSGranularity(mode_lib->vba.GlobalDPPCLK, mode_lib->vba.DISPCLKDPPCLKVCOSpeed); + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + mode_lib->vba.DPPCLK_calculated[k] = mode_lib->vba.GlobalDPPCLK / 255 + * dml_ceil(mode_lib->vba.DPPCLK_calculated[k] * 255 / mode_lib->vba.GlobalDPPCLK, 1); + DTRACE(" dppclk_mhz[%i] (calculated) = %f", k, mode_lib->vba.DPPCLK_calculated[k]); + } + + // Urgent Watermark + mode_lib->vba.DCCEnabledAnyPlane = false; + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) + if (mode_lib->vba.DCCEnable[k]) + mode_lib->vba.DCCEnabledAnyPlane = true; + + mode_lib->vba.ReturnBandwidthToDCN = dml_min(mode_lib->vba.ReturnBusWidth * mode_lib->vba.DCFCLK, mode_lib->vba.FabricAndDRAMBandwidth * 1000) + * mode_lib->vba.PercentOfIdealDRAMAndFabricBWReceivedAfterUrgLatency / 100; + + mode_lib->vba.ReturnBW = mode_lib->vba.ReturnBandwidthToDCN; + mode_lib->vba.ReturnBW = adjust_ReturnBW(mode_lib, mode_lib->vba.ReturnBW, mode_lib->vba.DCCEnabledAnyPlane, mode_lib->vba.ReturnBandwidthToDCN); + + // Let's do this calculation again?? + mode_lib->vba.ReturnBandwidthToDCN = dml_min(mode_lib->vba.ReturnBusWidth * mode_lib->vba.DCFCLK, mode_lib->vba.FabricAndDRAMBandwidth * 1000); + mode_lib->vba.ReturnBW = adjust_ReturnBW(mode_lib, mode_lib->vba.ReturnBW, mode_lib->vba.DCCEnabledAnyPlane, mode_lib->vba.ReturnBandwidthToDCN); + + DTRACE(" dcfclk_mhz = %f", mode_lib->vba.DCFCLK); + DTRACE(" return_bw_to_dcn = %f", mode_lib->vba.ReturnBandwidthToDCN); + DTRACE(" return_bus_bw = %f", mode_lib->vba.ReturnBW); + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + bool MainPlaneDoesODMCombine = false; + + if (mode_lib->vba.SourceScan[k] == dm_horz) + mode_lib->vba.SwathWidthSingleDPPY[k] = mode_lib->vba.ViewportWidth[k]; + else + mode_lib->vba.SwathWidthSingleDPPY[k] = mode_lib->vba.ViewportHeight[k]; + + if (mode_lib->vba.ODMCombineEnabled[k] == true) + MainPlaneDoesODMCombine = true; + for (j = 0; j < mode_lib->vba.NumberOfActivePlanes; ++j) + if (mode_lib->vba.BlendingAndTiming[k] == j && mode_lib->vba.ODMCombineEnabled[j] == true) + MainPlaneDoesODMCombine = true; + + if (MainPlaneDoesODMCombine == true) + mode_lib->vba.SwathWidthY[k] = dml_min((double)mode_lib->vba.SwathWidthSingleDPPY[k], + dml_round(mode_lib->vba.HActive[k] / 2.0 * mode_lib->vba.HRatio[k])); + else + mode_lib->vba.SwathWidthY[k] = mode_lib->vba.SwathWidthSingleDPPY[k] / mode_lib->vba.DPPPerPlane[k]; + } + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (mode_lib->vba.SourcePixelFormat[k] == dm_444_64) { + mode_lib->vba.BytePerPixelDETY[k] = 8; + mode_lib->vba.BytePerPixelDETC[k] = 0; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_32) { + mode_lib->vba.BytePerPixelDETY[k] = 4; + mode_lib->vba.BytePerPixelDETC[k] = 0; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_16) { + mode_lib->vba.BytePerPixelDETY[k] = 2; + mode_lib->vba.BytePerPixelDETC[k] = 0; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_8) { + mode_lib->vba.BytePerPixelDETY[k] = 1; + mode_lib->vba.BytePerPixelDETC[k] = 0; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_420_8) { + mode_lib->vba.BytePerPixelDETY[k] = 1; + mode_lib->vba.BytePerPixelDETC[k] = 2; + } else { // dm_420_10 + mode_lib->vba.BytePerPixelDETY[k] = 4.0 / 3.0; + mode_lib->vba.BytePerPixelDETC[k] = 8.0 / 3.0; + } + } + + mode_lib->vba.TotalDataReadBandwidth = 0.0; + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + mode_lib->vba.ReadBandwidthPlaneLuma[k] = mode_lib->vba.SwathWidthSingleDPPY[k] + * dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1) / (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) + * mode_lib->vba.VRatio[k]; + mode_lib->vba.ReadBandwidthPlaneChroma[k] = mode_lib->vba.SwathWidthSingleDPPY[k] / 2 + * dml_ceil(mode_lib->vba.BytePerPixelDETC[k], 2) / (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) + * mode_lib->vba.VRatio[k] / 2; + DTRACE(" read_bw[%i] = %fBps", + k, + mode_lib->vba.ReadBandwidthPlaneLuma[k] + mode_lib->vba.ReadBandwidthPlaneChroma[k]); + mode_lib->vba.TotalDataReadBandwidth += mode_lib->vba.ReadBandwidthPlaneLuma[k] + + mode_lib->vba.ReadBandwidthPlaneChroma[k]; + } + + mode_lib->vba.TotalDCCActiveDPP = 0; + mode_lib->vba.TotalActiveDPP = 0; + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + mode_lib->vba.TotalActiveDPP = mode_lib->vba.TotalActiveDPP + mode_lib->vba.DPPPerPlane[k]; + if (mode_lib->vba.DCCEnable[k]) + mode_lib->vba.TotalDCCActiveDPP = mode_lib->vba.TotalDCCActiveDPP + mode_lib->vba.DPPPerPlane[k]; + } + + mode_lib->vba.UrgentRoundTripAndOutOfOrderLatency = (mode_lib->vba.RoundTripPingLatencyCycles + 32) / mode_lib->vba.DCFCLK + + mode_lib->vba.UrgentOutOfOrderReturnPerChannel * mode_lib->vba.NumberOfChannels / mode_lib->vba.ReturnBW; + + mode_lib->vba.LastPixelOfLineExtraWatermark = 0; + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + double DataFabricLineDeliveryTimeLuma, DataFabricLineDeliveryTimeChroma; + + if (mode_lib->vba.VRatio[k] <= 1.0) + mode_lib->vba.DisplayPipeLineDeliveryTimeLuma[k] = (double)mode_lib->vba.SwathWidthY[k] + * mode_lib->vba.DPPPerPlane[k] / mode_lib->vba.HRatio[k] / mode_lib->vba.PixelClock[k]; + else + mode_lib->vba.DisplayPipeLineDeliveryTimeLuma[k] = (double)mode_lib->vba.SwathWidthY[k] + / mode_lib->vba.PSCL_THROUGHPUT_LUMA[k] / mode_lib->vba.DPPCLK[k]; + + DataFabricLineDeliveryTimeLuma = + mode_lib->vba.SwathWidthSingleDPPY[k] * mode_lib->vba.SwathHeightY[k] + * dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1) + / (mode_lib->vba.ReturnBW * mode_lib->vba.ReadBandwidthPlaneLuma[k] + / mode_lib->vba.TotalDataReadBandwidth); + mode_lib->vba.LastPixelOfLineExtraWatermark = dml_max(mode_lib->vba.LastPixelOfLineExtraWatermark, + DataFabricLineDeliveryTimeLuma + - mode_lib->vba.DisplayPipeLineDeliveryTimeLuma[k]); + + if (mode_lib->vba.BytePerPixelDETC[k] == 0) + mode_lib->vba.DisplayPipeLineDeliveryTimeChroma[k] = 0.0; + else if (mode_lib->vba.VRatio[k] / 2.0 <= 1.0) + mode_lib->vba.DisplayPipeLineDeliveryTimeChroma[k] = mode_lib->vba.SwathWidthY[k] / 2.0 + * mode_lib->vba.DPPPerPlane[k] / (mode_lib->vba.HRatio[k] / 2.0) / mode_lib->vba.PixelClock[k]; + else + mode_lib->vba.DisplayPipeLineDeliveryTimeChroma[k] = mode_lib->vba.SwathWidthY[k] / 2.0 + / mode_lib->vba.PSCL_THROUGHPUT_CHROMA[k] / mode_lib->vba.DPPCLK[k]; + + DataFabricLineDeliveryTimeChroma = mode_lib->vba.SwathWidthSingleDPPY[k] / 2.0 + * mode_lib->vba.SwathHeightC[k] * dml_ceil(mode_lib->vba.BytePerPixelDETC[k], 2) + / (mode_lib->vba.ReturnBW * mode_lib->vba.ReadBandwidthPlaneChroma[k] + / mode_lib->vba.TotalDataReadBandwidth); + mode_lib->vba.LastPixelOfLineExtraWatermark = dml_max(mode_lib->vba.LastPixelOfLineExtraWatermark, + DataFabricLineDeliveryTimeChroma + - mode_lib->vba.DisplayPipeLineDeliveryTimeChroma[k]); + } + + mode_lib->vba.UrgentExtraLatency = mode_lib->vba.UrgentRoundTripAndOutOfOrderLatency + + (mode_lib->vba.TotalActiveDPP * mode_lib->vba.PixelChunkSizeInKByte + + mode_lib->vba.TotalDCCActiveDPP * mode_lib->vba.MetaChunkSize) * 1024.0 + / mode_lib->vba.ReturnBW; + + if (mode_lib->vba.VirtualMemoryEnable) + mode_lib->vba.UrgentExtraLatency += mode_lib->vba.TotalActiveDPP * mode_lib->vba.PTEChunkSize * 1024.0 / mode_lib->vba.ReturnBW; + + mode_lib->vba.UrgentWatermark = mode_lib->vba.UrgentLatency + mode_lib->vba.LastPixelOfLineExtraWatermark + mode_lib->vba.UrgentExtraLatency; + + DTRACE(" urgent_extra_latency = %fus", mode_lib->vba.UrgentExtraLatency); + DTRACE(" wm_urgent = %fus", mode_lib->vba.UrgentWatermark); + + mode_lib->vba.MemoryTripWatermark = mode_lib->vba.UrgentLatency; + + mode_lib->vba.TotalActiveWriteback = 0; + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (mode_lib->vba.WritebackEnable[k]) + mode_lib->vba.TotalActiveWriteback = mode_lib->vba.TotalActiveWriteback + 1; + } + + if (mode_lib->vba.TotalActiveWriteback <= 1) + mode_lib->vba.WritebackUrgentWatermark = mode_lib->vba.WritebackLatency; + else + mode_lib->vba.WritebackUrgentWatermark = mode_lib->vba.WritebackLatency + + mode_lib->vba.WritebackChunkSize * 1024.0 / 32 / mode_lib->vba.SOCCLK; + + DTRACE(" wm_wb_urgent = %fus", mode_lib->vba.WritebackUrgentWatermark); + + // NB P-State/DRAM Clock Change Watermark + mode_lib->vba.DRAMClockChangeWatermark = mode_lib->vba.DRAMClockChangeLatency + mode_lib->vba.UrgentWatermark; + + DTRACE(" wm_pstate_change = %fus", mode_lib->vba.DRAMClockChangeWatermark); + + DTRACE(" calculating wb pstate watermark"); + DTRACE(" total wb outputs %d", mode_lib->vba.TotalActiveWriteback); + DTRACE(" socclk frequency %f Mhz", mode_lib->vba.SOCCLK); + + if (mode_lib->vba.TotalActiveWriteback <= 1) + mode_lib->vba.WritebackDRAMClockChangeWatermark = mode_lib->vba.DRAMClockChangeLatency + mode_lib->vba.WritebackLatency; + else + mode_lib->vba.WritebackDRAMClockChangeWatermark = mode_lib->vba.DRAMClockChangeLatency + mode_lib->vba.WritebackLatency + + mode_lib->vba.WritebackChunkSize * 1024.0 / 32 / mode_lib->vba.SOCCLK; + + DTRACE(" wm_wb_pstate %fus", mode_lib->vba.WritebackDRAMClockChangeWatermark); + + // Stutter Efficiency + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + mode_lib->vba.LinesInDETY[k] = mode_lib->vba.DETBufferSizeY[k] / mode_lib->vba.BytePerPixelDETY[k] + / mode_lib->vba.SwathWidthY[k]; + mode_lib->vba.LinesInDETYRoundedDownToSwath[k] = dml_floor(mode_lib->vba.LinesInDETY[k], + mode_lib->vba.SwathHeightY[k]); + mode_lib->vba.FullDETBufferingTimeY[k] = mode_lib->vba.LinesInDETYRoundedDownToSwath[k] + * (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) / mode_lib->vba.VRatio[k]; + if (mode_lib->vba.BytePerPixelDETC[k] > 0) { + mode_lib->vba.LinesInDETC[k] = mode_lib->vba.DETBufferSizeC[k] / mode_lib->vba.BytePerPixelDETC[k] + / (mode_lib->vba.SwathWidthY[k] / 2); + mode_lib->vba.LinesInDETCRoundedDownToSwath[k] = dml_floor(mode_lib->vba.LinesInDETC[k], + mode_lib->vba.SwathHeightC[k]); + mode_lib->vba.FullDETBufferingTimeC[k] = mode_lib->vba.LinesInDETCRoundedDownToSwath[k] + * (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) / (mode_lib->vba.VRatio[k] / 2); + } else { + mode_lib->vba.LinesInDETC[k] = 0; + mode_lib->vba.LinesInDETCRoundedDownToSwath[k] = 0; + mode_lib->vba.FullDETBufferingTimeC[k] = 999999; + } + } + + mode_lib->vba.MinFullDETBufferingTime = 999999.0; + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (mode_lib->vba.FullDETBufferingTimeY[k] < mode_lib->vba.MinFullDETBufferingTime) { + mode_lib->vba.MinFullDETBufferingTime = mode_lib->vba.FullDETBufferingTimeY[k]; + mode_lib->vba.FrameTimeForMinFullDETBufferingTime = (double)mode_lib->vba.VTotal[k] * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]; + } + if (mode_lib->vba.FullDETBufferingTimeC[k] < mode_lib->vba.MinFullDETBufferingTime) { + mode_lib->vba.MinFullDETBufferingTime = mode_lib->vba.FullDETBufferingTimeC[k]; + mode_lib->vba.FrameTimeForMinFullDETBufferingTime = (double)mode_lib->vba.VTotal[k] * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]; + } + } + + mode_lib->vba.AverageReadBandwidthGBytePerSecond = 0.0; + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (mode_lib->vba.DCCEnable[k]) { + mode_lib->vba.AverageReadBandwidthGBytePerSecond = + mode_lib->vba.AverageReadBandwidthGBytePerSecond + + mode_lib->vba.ReadBandwidthPlaneLuma[k] / mode_lib->vba.DCCRate[k] + / 1000 + + mode_lib->vba.ReadBandwidthPlaneChroma[k] + / mode_lib->vba.DCCRate[k] / 1000; + } else { + mode_lib->vba.AverageReadBandwidthGBytePerSecond = + mode_lib->vba.AverageReadBandwidthGBytePerSecond + + mode_lib->vba.ReadBandwidthPlaneLuma[k] / 1000 + + mode_lib->vba.ReadBandwidthPlaneChroma[k] / 1000; + } + if (mode_lib->vba.DCCEnable[k]) { + mode_lib->vba.AverageReadBandwidthGBytePerSecond = + mode_lib->vba.AverageReadBandwidthGBytePerSecond + + mode_lib->vba.ReadBandwidthPlaneLuma[k] / 1000 / 256 + + mode_lib->vba.ReadBandwidthPlaneChroma[k] / 1000 + / 256; + } + if (mode_lib->vba.VirtualMemoryEnable) { + mode_lib->vba.AverageReadBandwidthGBytePerSecond = + mode_lib->vba.AverageReadBandwidthGBytePerSecond + + mode_lib->vba.ReadBandwidthPlaneLuma[k] / 1000 / 512 + + mode_lib->vba.ReadBandwidthPlaneChroma[k] / 1000 + / 512; + } + } + + mode_lib->vba.PartOfBurstThatFitsInROB = dml_min(mode_lib->vba.MinFullDETBufferingTime * mode_lib->vba.TotalDataReadBandwidth, + mode_lib->vba.ROBBufferSizeInKByte * 1024 * mode_lib->vba.TotalDataReadBandwidth + / (mode_lib->vba.AverageReadBandwidthGBytePerSecond * 1000)); + mode_lib->vba.StutterBurstTime = mode_lib->vba.PartOfBurstThatFitsInROB + * (mode_lib->vba.AverageReadBandwidthGBytePerSecond * 1000) / mode_lib->vba.TotalDataReadBandwidth + / mode_lib->vba.ReturnBW + + (mode_lib->vba.MinFullDETBufferingTime * mode_lib->vba.TotalDataReadBandwidth + - mode_lib->vba.PartOfBurstThatFitsInROB) / (mode_lib->vba.DCFCLK * 64); + if (mode_lib->vba.TotalActiveWriteback == 0) { + mode_lib->vba.StutterEfficiencyNotIncludingVBlank = (1 + - (mode_lib->vba.SRExitTime + mode_lib->vba.StutterBurstTime) / mode_lib->vba.MinFullDETBufferingTime) + * 100; + } else { + mode_lib->vba.StutterEfficiencyNotIncludingVBlank = 0; + } + + mode_lib->vba.SmallestVBlank = 999999; + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (mode_lib->vba.SynchronizedVBlank || mode_lib->vba.NumberOfActivePlanes == 1) { + mode_lib->vba.VBlankTime = (double)(mode_lib->vba.VTotal[k] - mode_lib->vba.VActive[k]) * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]; + } else { + mode_lib->vba.VBlankTime = 0; + } + mode_lib->vba.SmallestVBlank = dml_min(mode_lib->vba.SmallestVBlank, mode_lib->vba.VBlankTime); + } + + mode_lib->vba.StutterEfficiency = (mode_lib->vba.StutterEfficiencyNotIncludingVBlank / 100 + * (mode_lib->vba.FrameTimeForMinFullDETBufferingTime - mode_lib->vba.SmallestVBlank) + + mode_lib->vba.SmallestVBlank) / mode_lib->vba.FrameTimeForMinFullDETBufferingTime * 100; + + // dml_ml->vba.DCFCLK Deep Sleep + mode_lib->vba.DCFClkDeepSleep = 8.0; + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; k++) { + if (mode_lib->vba.BytePerPixelDETC[k] > 0) { + mode_lib->vba.DCFCLKDeepSleepPerPlane = dml_max(1.1 * mode_lib->vba.SwathWidthY[k] + * dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1) / 32 + / mode_lib->vba.DisplayPipeLineDeliveryTimeLuma[k], + 1.1 * mode_lib->vba.SwathWidthY[k] / 2.0 + * dml_ceil(mode_lib->vba.BytePerPixelDETC[k], 2) / 32 + / mode_lib->vba.DisplayPipeLineDeliveryTimeChroma[k]); + } else + mode_lib->vba.DCFCLKDeepSleepPerPlane = 1.1 * mode_lib->vba.SwathWidthY[k] + * dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1) / 64.0 + / mode_lib->vba.DisplayPipeLineDeliveryTimeLuma[k]; + mode_lib->vba.DCFCLKDeepSleepPerPlane = dml_max(mode_lib->vba.DCFCLKDeepSleepPerPlane, + mode_lib->vba.PixelClock[k] / 16.0); + mode_lib->vba.DCFClkDeepSleep = dml_max(mode_lib->vba.DCFClkDeepSleep, mode_lib->vba.DCFCLKDeepSleepPerPlane); + + DTRACE(" dcfclk_deepsleep_per_plane[%i] = %fMHz", k, mode_lib->vba.DCFCLKDeepSleepPerPlane); + } + + DTRACE(" dcfclk_deepsleep_mhz = %fMHz", mode_lib->vba.DCFClkDeepSleep); + + // Stutter Watermark + mode_lib->vba.StutterExitWatermark = mode_lib->vba.SRExitTime + mode_lib->vba.LastPixelOfLineExtraWatermark + mode_lib->vba.UrgentExtraLatency + + 10 / mode_lib->vba.DCFClkDeepSleep; + mode_lib->vba.StutterEnterPlusExitWatermark = mode_lib->vba.SREnterPlusExitTime + mode_lib->vba.LastPixelOfLineExtraWatermark + + mode_lib->vba.UrgentExtraLatency; + + DTRACE(" wm_cstate_exit = %fus", mode_lib->vba.StutterExitWatermark); + DTRACE(" wm_cstate_enter_exit = %fus", mode_lib->vba.StutterEnterPlusExitWatermark); + + // Urgent Latency Supported + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + mode_lib->vba.EffectiveDETPlusLBLinesLuma = + dml_floor(mode_lib->vba.LinesInDETY[k] + + dml_min(mode_lib->vba.LinesInDETY[k] + * mode_lib->vba.DPPCLK[k] + * mode_lib->vba.BytePerPixelDETY[k] + * mode_lib->vba.PSCL_THROUGHPUT_LUMA[k] + / (mode_lib->vba.ReturnBW + / mode_lib->vba.DPPPerPlane[k]), + (double)mode_lib->vba.EffectiveLBLatencyHidingSourceLinesLuma), + mode_lib->vba.SwathHeightY[k]); + + mode_lib->vba.UrgentLatencySupportUsLuma = mode_lib->vba.EffectiveDETPlusLBLinesLuma + * (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) / mode_lib->vba.VRatio[k] + - mode_lib->vba.EffectiveDETPlusLBLinesLuma * mode_lib->vba.SwathWidthY[k] + * mode_lib->vba.BytePerPixelDETY[k] + / (mode_lib->vba.ReturnBW / mode_lib->vba.DPPPerPlane[k]); + + if (mode_lib->vba.BytePerPixelDETC[k] > 0) { + mode_lib->vba.EffectiveDETPlusLBLinesChroma = + dml_floor(mode_lib->vba.LinesInDETC[k] + + dml_min(mode_lib->vba.LinesInDETC[k] + * mode_lib->vba.DPPCLK[k] + * mode_lib->vba.BytePerPixelDETC[k] + * mode_lib->vba.PSCL_THROUGHPUT_CHROMA[k] + / (mode_lib->vba.ReturnBW + / mode_lib->vba.DPPPerPlane[k]), + (double)mode_lib->vba.EffectiveLBLatencyHidingSourceLinesChroma), + mode_lib->vba.SwathHeightC[k]); + mode_lib->vba.UrgentLatencySupportUsChroma = mode_lib->vba.EffectiveDETPlusLBLinesChroma + * (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) / (mode_lib->vba.VRatio[k] / 2) + - mode_lib->vba.EffectiveDETPlusLBLinesChroma + * (mode_lib->vba.SwathWidthY[k] / 2) + * mode_lib->vba.BytePerPixelDETC[k] + / (mode_lib->vba.ReturnBW / mode_lib->vba.DPPPerPlane[k]); + mode_lib->vba.UrgentLatencySupportUs[k] = dml_min(mode_lib->vba.UrgentLatencySupportUsLuma, + mode_lib->vba.UrgentLatencySupportUsChroma); + } else { + mode_lib->vba.UrgentLatencySupportUs[k] = mode_lib->vba.UrgentLatencySupportUsLuma; + } + } + + mode_lib->vba.MinUrgentLatencySupportUs = 999999; + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + mode_lib->vba.MinUrgentLatencySupportUs = dml_min(mode_lib->vba.MinUrgentLatencySupportUs, + mode_lib->vba.UrgentLatencySupportUs[k]); + } + + // Non-Urgent Latency Tolerance + mode_lib->vba.NonUrgentLatencyTolerance = mode_lib->vba.MinUrgentLatencySupportUs - mode_lib->vba.UrgentWatermark; + + // DSCCLK + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if ((mode_lib->vba.BlendingAndTiming[k] != k) || !mode_lib->vba.DSCEnabled[k]) { + mode_lib->vba.DSCCLK_calculated[k] = 0.0; + } else { + if (mode_lib->vba.OutputFormat[k] == dm_420 || mode_lib->vba.OutputFormat[k] == dm_n422) + mode_lib->vba.DSCFormatFactor = 2; + else + mode_lib->vba.DSCFormatFactor = 1; + if (mode_lib->vba.ODMCombineEnabled[k]) + mode_lib->vba.DSCCLK_calculated[k] = mode_lib->vba.PixelClockBackEnd[k] / 6 + / mode_lib->vba.DSCFormatFactor + / (1 - mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading / 100); + else + mode_lib->vba.DSCCLK_calculated[k] = mode_lib->vba.PixelClockBackEnd[k] / 3 + / mode_lib->vba.DSCFormatFactor + / (1 - mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading / 100); + } + } + + // DSC Delay + // TODO + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + double bpp = mode_lib->vba.OutputBpp[k]; + unsigned int slices = mode_lib->vba.NumberOfDSCSlices[k]; + + if (mode_lib->vba.DSCEnabled[k] && bpp != 0) { + if (!mode_lib->vba.ODMCombineEnabled[k]) { + mode_lib->vba.DSCDelay[k] = + dscceComputeDelay(mode_lib->vba.DSCInputBitPerComponent[k], + bpp, + dml_ceil((double)mode_lib->vba.HActive[k] + / mode_lib->vba.NumberOfDSCSlices[k], + 1), + slices, + mode_lib->vba.OutputFormat[k]) + + dscComputeDelay(mode_lib->vba.OutputFormat[k]); + } else { + mode_lib->vba.DSCDelay[k] = + 2 + * (dscceComputeDelay(mode_lib->vba.DSCInputBitPerComponent[k], + bpp, + dml_ceil((double)mode_lib->vba.HActive[k] + / mode_lib->vba.NumberOfDSCSlices[k], + 1), + slices / 2.0, + mode_lib->vba.OutputFormat[k]) + + dscComputeDelay(mode_lib->vba.OutputFormat[k])); + } + mode_lib->vba.DSCDelay[k] = mode_lib->vba.DSCDelay[k] * mode_lib->vba.PixelClock[k] / mode_lib->vba.PixelClockBackEnd[k]; + } else { + mode_lib->vba.DSCDelay[k] = 0; + } + } + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) + for (j = 0; j < mode_lib->vba.NumberOfActivePlanes; ++j) // NumberOfPlanes + if (j != k && mode_lib->vba.BlendingAndTiming[k] == j && mode_lib->vba.DSCEnabled[j]) + mode_lib->vba.DSCDelay[k] = mode_lib->vba.DSCDelay[j]; + + // Prefetch + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + unsigned int PDEAndMetaPTEBytesFrameY; + unsigned int PixelPTEBytesPerRowY; + unsigned int MetaRowByteY; + unsigned int MetaRowByteC; + unsigned int PDEAndMetaPTEBytesFrameC; + unsigned int PixelPTEBytesPerRowC; + + Calculate256BBlockSizes(mode_lib->vba.SourcePixelFormat[k], + mode_lib->vba.SurfaceTiling[k], + dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1), + dml_ceil(mode_lib->vba.BytePerPixelDETC[k], 2), + &mode_lib->vba.BlockHeight256BytesY[k], + &mode_lib->vba.BlockHeight256BytesC[k], + &mode_lib->vba.BlockWidth256BytesY[k], + &mode_lib->vba.BlockWidth256BytesC[k]); + PDEAndMetaPTEBytesFrameY = CalculateVMAndRowBytes(mode_lib, + mode_lib->vba.DCCEnable[k], + mode_lib->vba.BlockHeight256BytesY[k], + mode_lib->vba.BlockWidth256BytesY[k], + mode_lib->vba.SourcePixelFormat[k], + mode_lib->vba.SurfaceTiling[k], + dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1), + mode_lib->vba.SourceScan[k], + mode_lib->vba.ViewportWidth[k], + mode_lib->vba.ViewportHeight[k], + mode_lib->vba.SwathWidthY[k], + mode_lib->vba.VirtualMemoryEnable, + mode_lib->vba.VMMPageSize, + mode_lib->vba.PTEBufferSizeInRequests, + mode_lib->vba.PDEProcessingBufIn64KBReqs, + mode_lib->vba.PitchY[k], + mode_lib->vba.DCCMetaPitchY[k], + &mode_lib->vba.MacroTileWidthY, + &MetaRowByteY, + &PixelPTEBytesPerRowY, + &mode_lib->vba.PTEBufferSizeNotExceeded, + &mode_lib->vba.dpte_row_height[k], + &mode_lib->vba.meta_row_height[k]); + mode_lib->vba.PrefetchSourceLinesY[k] = CalculatePrefetchSourceLines(mode_lib, + mode_lib->vba.VRatio[k], + mode_lib->vba.vtaps[k], + mode_lib->vba.Interlace[k], + mode_lib->vba.ProgressiveToInterlaceUnitInOPP, + mode_lib->vba.SwathHeightY[k], + mode_lib->vba.ViewportYStartY[k], + &mode_lib->vba.VInitPreFillY[k], + &mode_lib->vba.MaxNumSwathY[k]); + + if ((mode_lib->vba.SourcePixelFormat[k] != dm_444_64 && mode_lib->vba.SourcePixelFormat[k] != dm_444_32 + && mode_lib->vba.SourcePixelFormat[k] != dm_444_16 + && mode_lib->vba.SourcePixelFormat[k] != dm_444_8)) { + PDEAndMetaPTEBytesFrameC = CalculateVMAndRowBytes(mode_lib, + mode_lib->vba.DCCEnable[k], + mode_lib->vba.BlockHeight256BytesC[k], + mode_lib->vba.BlockWidth256BytesC[k], + mode_lib->vba.SourcePixelFormat[k], + mode_lib->vba.SurfaceTiling[k], + dml_ceil(mode_lib->vba.BytePerPixelDETC[k], 2), + mode_lib->vba.SourceScan[k], + mode_lib->vba.ViewportWidth[k] / 2, + mode_lib->vba.ViewportHeight[k] / 2, + mode_lib->vba.SwathWidthY[k] / 2, + mode_lib->vba.VirtualMemoryEnable, + mode_lib->vba.VMMPageSize, + mode_lib->vba.PTEBufferSizeInRequests, + mode_lib->vba.PDEProcessingBufIn64KBReqs, + mode_lib->vba.PitchC[k], + 0, + &mode_lib->vba.MacroTileWidthC, + &MetaRowByteC, + &PixelPTEBytesPerRowC, + &mode_lib->vba.PTEBufferSizeNotExceeded, + &mode_lib->vba.dpte_row_height_chroma[k], + &mode_lib->vba.meta_row_height_chroma[k]); + mode_lib->vba.PrefetchSourceLinesC[k] = CalculatePrefetchSourceLines(mode_lib, + mode_lib->vba.VRatio[k] / 2, + mode_lib->vba.VTAPsChroma[k], + mode_lib->vba.Interlace[k], + mode_lib->vba.ProgressiveToInterlaceUnitInOPP, + mode_lib->vba.SwathHeightC[k], + mode_lib->vba.ViewportYStartC[k], + &mode_lib->vba.VInitPreFillC[k], + &mode_lib->vba.MaxNumSwathC[k]); + } else { + PixelPTEBytesPerRowC = 0; + PDEAndMetaPTEBytesFrameC = 0; + MetaRowByteC = 0; + mode_lib->vba.MaxNumSwathC[k] = 0; + mode_lib->vba.PrefetchSourceLinesC[k] = 0; + } + + mode_lib->vba.PixelPTEBytesPerRow[k] = PixelPTEBytesPerRowY + PixelPTEBytesPerRowC; + mode_lib->vba.PDEAndMetaPTEBytesFrame[k] = PDEAndMetaPTEBytesFrameY + PDEAndMetaPTEBytesFrameC; + mode_lib->vba.MetaRowByte[k] = MetaRowByteY + MetaRowByteC; + + CalculateActiveRowBandwidth(mode_lib->vba.VirtualMemoryEnable, + mode_lib->vba.SourcePixelFormat[k], + mode_lib->vba.VRatio[k], + mode_lib->vba.DCCEnable[k], + mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k], + MetaRowByteY, + MetaRowByteC, + mode_lib->vba.meta_row_height[k], + mode_lib->vba.meta_row_height_chroma[k], + PixelPTEBytesPerRowY, + PixelPTEBytesPerRowC, + mode_lib->vba.dpte_row_height[k], + mode_lib->vba.dpte_row_height_chroma[k], + &mode_lib->vba.meta_row_bw[k], + &mode_lib->vba.dpte_row_bw[k], + &mode_lib->vba.qual_row_bw[k]); + } + + mode_lib->vba.TCalc = 24.0 / mode_lib->vba.DCFClkDeepSleep; + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (mode_lib->vba.BlendingAndTiming[k] == k) { + if (mode_lib->vba.WritebackEnable[k] == true) { + mode_lib->vba.WritebackDelay[k] = mode_lib->vba.WritebackLatency + + CalculateWriteBackDelay(mode_lib->vba.WritebackPixelFormat[k], + mode_lib->vba.WritebackHRatio[k], + mode_lib->vba.WritebackVRatio[k], + mode_lib->vba.WritebackLumaHTaps[k], + mode_lib->vba.WritebackLumaVTaps[k], + mode_lib->vba.WritebackChromaHTaps[k], + mode_lib->vba.WritebackChromaVTaps[k], + mode_lib->vba.WritebackDestinationWidth[k]) + / mode_lib->vba.DISPCLK; + } else + mode_lib->vba.WritebackDelay[k] = 0; + for (j = 0; j < mode_lib->vba.NumberOfActivePlanes; ++j) { + if (mode_lib->vba.BlendingAndTiming[j] == k && mode_lib->vba.WritebackEnable[j] == true) { + mode_lib->vba.WritebackDelay[k] = + dml_max(mode_lib->vba.WritebackDelay[k], + mode_lib->vba.WritebackLatency + + CalculateWriteBackDelay(mode_lib->vba.WritebackPixelFormat[j], + mode_lib->vba.WritebackHRatio[j], + mode_lib->vba.WritebackVRatio[j], + mode_lib->vba.WritebackLumaHTaps[j], + mode_lib->vba.WritebackLumaVTaps[j], + mode_lib->vba.WritebackChromaHTaps[j], + mode_lib->vba.WritebackChromaVTaps[j], + mode_lib->vba.WritebackDestinationWidth[j]) + / mode_lib->vba.DISPCLK); + } + } + } + } + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) + for (j = 0; j < mode_lib->vba.NumberOfActivePlanes; ++j) + if (mode_lib->vba.BlendingAndTiming[k] == j) + mode_lib->vba.WritebackDelay[k] = mode_lib->vba.WritebackDelay[j]; + + mode_lib->vba.VStartupLines = 13; + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + mode_lib->vba.MaxVStartupLines[k] = + mode_lib->vba.VTotal[k] - mode_lib->vba.VActive[k] + - dml_max(1.0, + dml_ceil(mode_lib->vba.WritebackDelay[k] + / (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]), + 1)); + } + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) + mode_lib->vba.MaximumMaxVStartupLines = dml_max(mode_lib->vba.MaximumMaxVStartupLines, mode_lib->vba.MaxVStartupLines[k]); + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + mode_lib->vba.cursor_bw[k] = 0.0; + for (j = 0; j < mode_lib->vba.NumberOfCursors[k]; ++j) + mode_lib->vba.cursor_bw[k] += mode_lib->vba.CursorWidth[k][j] * mode_lib->vba.CursorBPP[k][j] / 8.0 + / (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) * mode_lib->vba.VRatio[k]; + } + + do { + double MaxTotalRDBandwidth = 0; + bool DestinationLineTimesForPrefetchLessThan2 = false; + bool VRatioPrefetchMoreThan4 = false; + bool prefetch_vm_bw_valid = true; + bool prefetch_row_bw_valid = true; + double TWait = CalculateTWait(mode_lib->vba.PrefetchMode, + mode_lib->vba.DRAMClockChangeLatency, + mode_lib->vba.UrgentLatency, + mode_lib->vba.SREnterPlusExitTime); + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (mode_lib->vba.XFCEnabled[k] == true) { + mode_lib->vba.XFCRemoteSurfaceFlipDelay = CalculateRemoteSurfaceFlipDelay(mode_lib, + mode_lib->vba.VRatio[k], + mode_lib->vba.SwathWidthY[k], + dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1), + mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k], + mode_lib->vba.XFCTSlvVupdateOffset, + mode_lib->vba.XFCTSlvVupdateWidth, + mode_lib->vba.XFCTSlvVreadyOffset, + mode_lib->vba.XFCXBUFLatencyTolerance, + mode_lib->vba.XFCFillBWOverhead, + mode_lib->vba.XFCSlvChunkSize, + mode_lib->vba.XFCBusTransportTime, + mode_lib->vba.TCalc, + TWait, + &mode_lib->vba.SrcActiveDrainRate, + &mode_lib->vba.TInitXFill, + &mode_lib->vba.TslvChk); + } else { + mode_lib->vba.XFCRemoteSurfaceFlipDelay = 0; + } + mode_lib->vba.ErrorResult[k] = CalculatePrefetchSchedule(mode_lib, + mode_lib->vba.DPPCLK[k], + mode_lib->vba.DISPCLK, + mode_lib->vba.PixelClock[k], + mode_lib->vba.DCFClkDeepSleep, + mode_lib->vba.DSCDelay[k], + mode_lib->vba.DPPPerPlane[k], + mode_lib->vba.ScalerEnabled[k], + mode_lib->vba.NumberOfCursors[k], + mode_lib->vba.DPPCLKDelaySubtotal, + mode_lib->vba.DPPCLKDelaySCL, + mode_lib->vba.DPPCLKDelaySCLLBOnly, + mode_lib->vba.DPPCLKDelayCNVCFormater, + mode_lib->vba.DPPCLKDelayCNVCCursor, + mode_lib->vba.DISPCLKDelaySubtotal, + (unsigned int)(mode_lib->vba.SwathWidthY[k] / mode_lib->vba.HRatio[k]), + mode_lib->vba.OutputFormat[k], + mode_lib->vba.VTotal[k] - mode_lib->vba.VActive[k], + mode_lib->vba.HTotal[k], + mode_lib->vba.MaxInterDCNTileRepeaters, + dml_min(mode_lib->vba.VStartupLines, mode_lib->vba.MaxVStartupLines[k]), + mode_lib->vba.MaxPageTableLevels, + mode_lib->vba.VirtualMemoryEnable, + mode_lib->vba.DynamicMetadataEnable[k], + mode_lib->vba.DynamicMetadataLinesBeforeActiveRequired[k], + mode_lib->vba.DynamicMetadataTransmittedBytes[k], + mode_lib->vba.DCCEnable[k], + mode_lib->vba.UrgentLatency, + mode_lib->vba.UrgentExtraLatency, + mode_lib->vba.TCalc, + mode_lib->vba.PDEAndMetaPTEBytesFrame[k], + mode_lib->vba.MetaRowByte[k], + mode_lib->vba.PixelPTEBytesPerRow[k], + mode_lib->vba.PrefetchSourceLinesY[k], + mode_lib->vba.SwathWidthY[k], + mode_lib->vba.BytePerPixelDETY[k], + mode_lib->vba.VInitPreFillY[k], + mode_lib->vba.MaxNumSwathY[k], + mode_lib->vba.PrefetchSourceLinesC[k], + mode_lib->vba.BytePerPixelDETC[k], + mode_lib->vba.VInitPreFillC[k], + mode_lib->vba.MaxNumSwathC[k], + mode_lib->vba.SwathHeightY[k], + mode_lib->vba.SwathHeightC[k], + TWait, + mode_lib->vba.XFCEnabled[k], + mode_lib->vba.XFCRemoteSurfaceFlipDelay, + mode_lib->vba.Interlace[k], + mode_lib->vba.ProgressiveToInterlaceUnitInOPP, + &mode_lib->vba.DSTXAfterScaler[k], + &mode_lib->vba.DSTYAfterScaler[k], + &mode_lib->vba.DestinationLinesForPrefetch[k], + &mode_lib->vba.PrefetchBandwidth[k], + &mode_lib->vba.DestinationLinesToRequestVMInVBlank[k], + &mode_lib->vba.DestinationLinesToRequestRowInVBlank[k], + &mode_lib->vba.VRatioPrefetchY[k], + &mode_lib->vba.VRatioPrefetchC[k], + &mode_lib->vba.RequiredPrefetchPixDataBW[k], + &mode_lib->vba.VStartupRequiredWhenNotEnoughTimeForDynamicMetadata, + &mode_lib->vba.Tno_bw[k]); + if (mode_lib->vba.BlendingAndTiming[k] == k) { + mode_lib->vba.VStartup[k] = dml_min(mode_lib->vba.VStartupLines, mode_lib->vba.MaxVStartupLines[k]); + if (mode_lib->vba.VStartupRequiredWhenNotEnoughTimeForDynamicMetadata != 0) { + mode_lib->vba.VStartup[k] = + mode_lib->vba.VStartupRequiredWhenNotEnoughTimeForDynamicMetadata; + } + } else { + mode_lib->vba.VStartup[k] = dml_min(mode_lib->vba.VStartupLines, + mode_lib->vba.MaxVStartupLines[mode_lib->vba.BlendingAndTiming[k]]); + } + } + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + + if (mode_lib->vba.PDEAndMetaPTEBytesFrame[k] == 0) + mode_lib->vba.prefetch_vm_bw[k] = 0; + else if (mode_lib->vba.DestinationLinesToRequestVMInVBlank[k] > 0) { + mode_lib->vba.prefetch_vm_bw[k] = (double)mode_lib->vba.PDEAndMetaPTEBytesFrame[k] + / (mode_lib->vba.DestinationLinesToRequestVMInVBlank[k] + * mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]); + } else { + mode_lib->vba.prefetch_vm_bw[k] = 0; + prefetch_vm_bw_valid = false; + } + if (mode_lib->vba.MetaRowByte[k] + mode_lib->vba.PixelPTEBytesPerRow[k] == 0) + mode_lib->vba.prefetch_row_bw[k] = 0; + else if (mode_lib->vba.DestinationLinesToRequestRowInVBlank[k] > 0) { + mode_lib->vba.prefetch_row_bw[k] = (double)(mode_lib->vba.MetaRowByte[k] + + mode_lib->vba.PixelPTEBytesPerRow[k]) + / (mode_lib->vba.DestinationLinesToRequestRowInVBlank[k] + * mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]); + } else { + mode_lib->vba.prefetch_row_bw[k] = 0; + prefetch_row_bw_valid = false; + } + + MaxTotalRDBandwidth = + MaxTotalRDBandwidth + mode_lib->vba.cursor_bw[k] + + dml_max(mode_lib->vba.prefetch_vm_bw[k], + dml_max(mode_lib->vba.prefetch_row_bw[k], + dml_max(mode_lib->vba.ReadBandwidthPlaneLuma[k] + + mode_lib->vba.ReadBandwidthPlaneChroma[k], + mode_lib->vba.RequiredPrefetchPixDataBW[k]) + + mode_lib->vba.meta_row_bw[k] + + mode_lib->vba.dpte_row_bw[k])); + + if (mode_lib->vba.DestinationLinesForPrefetch[k] < 2) + DestinationLineTimesForPrefetchLessThan2 = true; + if (mode_lib->vba.VRatioPrefetchY[k] > 4 || mode_lib->vba.VRatioPrefetchC[k] > 4) + VRatioPrefetchMoreThan4 = true; + } + + if (MaxTotalRDBandwidth <= mode_lib->vba.ReturnBW && prefetch_vm_bw_valid && prefetch_row_bw_valid + && !VRatioPrefetchMoreThan4 + && !DestinationLineTimesForPrefetchLessThan2) + mode_lib->vba.PrefetchModeSupported = true; + else { + mode_lib->vba.PrefetchModeSupported = false; + dml_print("DML: CalculatePrefetchSchedule ***failed***. Bandwidth violation. Results are NOT valid\n"); + } + + if (mode_lib->vba.PrefetchModeSupported == true) { + double final_flip_bw[DC__NUM_PIPES__MAX]; + unsigned int ImmediateFlipBytes[DC__NUM_PIPES__MAX]; + double total_dcn_read_bw_with_flip = 0; + + mode_lib->vba.BandwidthAvailableForImmediateFlip = mode_lib->vba.ReturnBW; + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + mode_lib->vba.BandwidthAvailableForImmediateFlip = + mode_lib->vba.BandwidthAvailableForImmediateFlip - mode_lib->vba.cursor_bw[k] + - dml_max(mode_lib->vba.ReadBandwidthPlaneLuma[k] + + mode_lib->vba.ReadBandwidthPlaneChroma[k] + + mode_lib->vba.qual_row_bw[k], + mode_lib->vba.PrefetchBandwidth[k]); + } + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + ImmediateFlipBytes[k] = 0; + if ((mode_lib->vba.SourcePixelFormat[k] != dm_420_8 + && mode_lib->vba.SourcePixelFormat[k] != dm_420_10)) { + ImmediateFlipBytes[k] = mode_lib->vba.PDEAndMetaPTEBytesFrame[k] + + mode_lib->vba.MetaRowByte[k] + + mode_lib->vba.PixelPTEBytesPerRow[k]; + } + } + mode_lib->vba.TotImmediateFlipBytes = 0; + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if ((mode_lib->vba.SourcePixelFormat[k] != dm_420_8 + && mode_lib->vba.SourcePixelFormat[k] != dm_420_10)) { + mode_lib->vba.TotImmediateFlipBytes = mode_lib->vba.TotImmediateFlipBytes + + ImmediateFlipBytes[k]; + } + } + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + CalculateFlipSchedule(mode_lib, + mode_lib->vba.UrgentExtraLatency, + mode_lib->vba.UrgentLatency, + mode_lib->vba.MaxPageTableLevels, + mode_lib->vba.VirtualMemoryEnable, + mode_lib->vba.BandwidthAvailableForImmediateFlip, + mode_lib->vba.TotImmediateFlipBytes, + mode_lib->vba.SourcePixelFormat[k], + ImmediateFlipBytes[k], + mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k], + mode_lib->vba.VRatio[k], + mode_lib->vba.Tno_bw[k], + mode_lib->vba.PDEAndMetaPTEBytesFrame[k], + mode_lib->vba.MetaRowByte[k], + mode_lib->vba.PixelPTEBytesPerRow[k], + mode_lib->vba.DCCEnable[k], + mode_lib->vba.dpte_row_height[k], + mode_lib->vba.meta_row_height[k], + mode_lib->vba.qual_row_bw[k], + &mode_lib->vba.DestinationLinesToRequestVMInImmediateFlip[k], + &mode_lib->vba.DestinationLinesToRequestRowInImmediateFlip[k], + &final_flip_bw[k], + &mode_lib->vba.ImmediateFlipSupportedForPipe[k]); + } + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + total_dcn_read_bw_with_flip = + total_dcn_read_bw_with_flip + mode_lib->vba.cursor_bw[k] + + dml_max(mode_lib->vba.prefetch_vm_bw[k], + dml_max(mode_lib->vba.prefetch_row_bw[k], + final_flip_bw[k] + + dml_max(mode_lib->vba.ReadBandwidthPlaneLuma[k] + + mode_lib->vba.ReadBandwidthPlaneChroma[k], + mode_lib->vba.RequiredPrefetchPixDataBW[k]))); + } + mode_lib->vba.ImmediateFlipSupported = true; + if (total_dcn_read_bw_with_flip > mode_lib->vba.ReturnBW) { + mode_lib->vba.ImmediateFlipSupported = false; + } + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (mode_lib->vba.ImmediateFlipSupportedForPipe[k] == false) { + mode_lib->vba.ImmediateFlipSupported = false; + } + } + } else { + mode_lib->vba.ImmediateFlipSupported = false; + } + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (mode_lib->vba.ErrorResult[k]) { + mode_lib->vba.PrefetchModeSupported = false; + dml_print("DML: CalculatePrefetchSchedule ***failed***. Prefetch schedule violation. Results are NOT valid\n"); + } + } + + mode_lib->vba.VStartupLines = mode_lib->vba.VStartupLines + 1; + } while (!((mode_lib->vba.PrefetchModeSupported + && (!mode_lib->vba.ImmediateFlipSupport || mode_lib->vba.ImmediateFlipSupported)) + || mode_lib->vba.MaximumMaxVStartupLines < mode_lib->vba.VStartupLines)); + + //Display Pipeline Delivery Time in Prefetch + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (mode_lib->vba.VRatioPrefetchY[k] <= 1) { + mode_lib->vba.DisplayPipeLineDeliveryTimeLumaPrefetch[k] = mode_lib->vba.SwathWidthY[k] + * mode_lib->vba.DPPPerPlane[k] / mode_lib->vba.HRatio[k] / mode_lib->vba.PixelClock[k]; + } else { + mode_lib->vba.DisplayPipeLineDeliveryTimeLumaPrefetch[k] = mode_lib->vba.SwathWidthY[k] + / mode_lib->vba.PSCL_THROUGHPUT_LUMA[k] / mode_lib->vba.DPPCLK[k]; + } + if (mode_lib->vba.BytePerPixelDETC[k] == 0) { + mode_lib->vba.DisplayPipeLineDeliveryTimeChromaPrefetch[k] = 0; + } else { + if (mode_lib->vba.VRatioPrefetchC[k] <= 1) { + mode_lib->vba.DisplayPipeLineDeliveryTimeChromaPrefetch[k] = + mode_lib->vba.SwathWidthY[k] * mode_lib->vba.DPPPerPlane[k] / mode_lib->vba.HRatio[k] + / mode_lib->vba.PixelClock[k]; + } else { + mode_lib->vba.DisplayPipeLineDeliveryTimeChromaPrefetch[k] = + mode_lib->vba.SwathWidthY[k] / mode_lib->vba.PSCL_THROUGHPUT_LUMA[k] + / mode_lib->vba.DPPCLK[k]; + } + } + } + + // Min TTUVBlank + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (mode_lib->vba.PrefetchMode == 0) { + mode_lib->vba.AllowDRAMClockChangeDuringVBlank[k] = true; + mode_lib->vba.AllowDRAMSelfRefreshDuringVBlank[k] = true; + mode_lib->vba.MinTTUVBlank[k] = dml_max(mode_lib->vba.DRAMClockChangeWatermark, + dml_max(mode_lib->vba.StutterEnterPlusExitWatermark, mode_lib->vba.UrgentWatermark)); + } else if (mode_lib->vba.PrefetchMode == 1) { + mode_lib->vba.AllowDRAMClockChangeDuringVBlank[k] = false; + mode_lib->vba.AllowDRAMSelfRefreshDuringVBlank[k] = true; + mode_lib->vba.MinTTUVBlank[k] = dml_max(mode_lib->vba.StutterEnterPlusExitWatermark, mode_lib->vba.UrgentWatermark); + } else { + mode_lib->vba.AllowDRAMClockChangeDuringVBlank[k] = false; + mode_lib->vba.AllowDRAMSelfRefreshDuringVBlank[k] = false; + mode_lib->vba.MinTTUVBlank[k] = mode_lib->vba.UrgentWatermark; + } + if (!mode_lib->vba.DynamicMetadataEnable[k]) + mode_lib->vba.MinTTUVBlank[k] = mode_lib->vba.TCalc + mode_lib->vba.MinTTUVBlank[k]; + } + + // DCC Configuration + mode_lib->vba.ActiveDPPs = 0; + // NB P-State/DRAM Clock Change Support + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + mode_lib->vba.ActiveDPPs = mode_lib->vba.ActiveDPPs + mode_lib->vba.DPPPerPlane[k]; + } + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + double EffectiveLBLatencyHidingY; + double EffectiveLBLatencyHidingC; + double DPPOutputBufferLinesY; + double DPPOutputBufferLinesC; + double DPPOPPBufferingY; + double MaxDETBufferingTimeY; + double ActiveDRAMClockChangeLatencyMarginY; + + mode_lib->vba.LBLatencyHidingSourceLinesY = + dml_min(mode_lib->vba.MaxLineBufferLines, + (unsigned int)dml_floor((double)mode_lib->vba.LineBufferSize + / mode_lib->vba.LBBitPerPixel[k] + / (mode_lib->vba.SwathWidthY[k] + / dml_max(mode_lib->vba.HRatio[k], + 1.0)), + 1)) - (mode_lib->vba.vtaps[k] - 1); + + mode_lib->vba.LBLatencyHidingSourceLinesC = + dml_min(mode_lib->vba.MaxLineBufferLines, + (unsigned int)dml_floor((double)mode_lib->vba.LineBufferSize + / mode_lib->vba.LBBitPerPixel[k] + / (mode_lib->vba.SwathWidthY[k] + / 2.0 + / dml_max(mode_lib->vba.HRatio[k] + / 2, + 1.0)), + 1)) - (mode_lib->vba.VTAPsChroma[k] - 1); + + EffectiveLBLatencyHidingY = mode_lib->vba.LBLatencyHidingSourceLinesY / mode_lib->vba.VRatio[k] + * (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]); + + EffectiveLBLatencyHidingC = mode_lib->vba.LBLatencyHidingSourceLinesC / (mode_lib->vba.VRatio[k] / 2) + * (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]); + + if (mode_lib->vba.SwathWidthY[k] > 2 * mode_lib->vba.DPPOutputBufferPixels) { + DPPOutputBufferLinesY = mode_lib->vba.DPPOutputBufferPixels / mode_lib->vba.SwathWidthY[k]; + } else if (mode_lib->vba.SwathWidthY[k] > mode_lib->vba.DPPOutputBufferPixels) { + DPPOutputBufferLinesY = 0.5; + } else { + DPPOutputBufferLinesY = 1; + } + + if (mode_lib->vba.SwathWidthY[k] / 2 > 2 * mode_lib->vba.DPPOutputBufferPixels) { + DPPOutputBufferLinesC = mode_lib->vba.DPPOutputBufferPixels / (mode_lib->vba.SwathWidthY[k] / 2); + } else if (mode_lib->vba.SwathWidthY[k] / 2 > mode_lib->vba.DPPOutputBufferPixels) { + DPPOutputBufferLinesC = 0.5; + } else { + DPPOutputBufferLinesC = 1; + } + + DPPOPPBufferingY = (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) + * (DPPOutputBufferLinesY + mode_lib->vba.OPPOutputBufferLines); + MaxDETBufferingTimeY = mode_lib->vba.FullDETBufferingTimeY[k] + + (mode_lib->vba.LinesInDETY[k] - mode_lib->vba.LinesInDETYRoundedDownToSwath[k]) + / mode_lib->vba.SwathHeightY[k] * (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]); + + ActiveDRAMClockChangeLatencyMarginY = DPPOPPBufferingY + EffectiveLBLatencyHidingY + + MaxDETBufferingTimeY - mode_lib->vba.DRAMClockChangeWatermark; + + if (mode_lib->vba.ActiveDPPs > 1) { + ActiveDRAMClockChangeLatencyMarginY = ActiveDRAMClockChangeLatencyMarginY + - (1 - 1 / (mode_lib->vba.ActiveDPPs - 1)) * mode_lib->vba.SwathHeightY[k] + * (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]); + } + + if (mode_lib->vba.BytePerPixelDETC[k] > 0) { + double DPPOPPBufferingC = (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) + * (DPPOutputBufferLinesC + mode_lib->vba.OPPOutputBufferLines); + double MaxDETBufferingTimeC = + mode_lib->vba.FullDETBufferingTimeC[k] + + (mode_lib->vba.LinesInDETC[k] + - mode_lib->vba.LinesInDETCRoundedDownToSwath[k]) + / mode_lib->vba.SwathHeightC[k] + * (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]); + double ActiveDRAMClockChangeLatencyMarginC = DPPOPPBufferingC + + EffectiveLBLatencyHidingC + MaxDETBufferingTimeC + - mode_lib->vba.DRAMClockChangeWatermark; + + if (mode_lib->vba.ActiveDPPs > 1) { + ActiveDRAMClockChangeLatencyMarginC = + ActiveDRAMClockChangeLatencyMarginC + - (1 - 1 / (mode_lib->vba.ActiveDPPs - 1)) + * mode_lib->vba.SwathHeightC[k] + * (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]); + } + mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k] = dml_min(ActiveDRAMClockChangeLatencyMarginY, + ActiveDRAMClockChangeLatencyMarginC); + } else { + mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k] = + ActiveDRAMClockChangeLatencyMarginY; + } + + if (mode_lib->vba.WritebackEnable[k]) { + double WritebackDRAMClockChangeLatencyMargin; + + if (mode_lib->vba.WritebackPixelFormat[k] == dm_444_32) { + WritebackDRAMClockChangeLatencyMargin = + (double)(mode_lib->vba.WritebackInterfaceLumaBufferSize + + mode_lib->vba.WritebackInterfaceChromaBufferSize) + / (mode_lib->vba.WritebackDestinationWidth[k] + * mode_lib->vba.WritebackDestinationHeight[k] + / (mode_lib->vba.WritebackSourceHeight[k] + * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]) + * 4) + - mode_lib->vba.WritebackDRAMClockChangeWatermark; + } else if (mode_lib->vba.WritebackPixelFormat[k] == dm_420_10) { + WritebackDRAMClockChangeLatencyMargin = dml_min((double)mode_lib->vba.WritebackInterfaceLumaBufferSize * 8.0 + / 10, + 2.0 * mode_lib->vba.WritebackInterfaceChromaBufferSize * 8 / 10) + / (mode_lib->vba.WritebackDestinationWidth[k] + * mode_lib->vba.WritebackDestinationHeight[k] + / (mode_lib->vba.WritebackSourceHeight[k] + * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k])) + - mode_lib->vba.WritebackDRAMClockChangeWatermark; + } else { + WritebackDRAMClockChangeLatencyMargin = dml_min((double)mode_lib->vba.WritebackInterfaceLumaBufferSize, + 2.0 * mode_lib->vba.WritebackInterfaceChromaBufferSize) + / (mode_lib->vba.WritebackDestinationWidth[k] + * mode_lib->vba.WritebackDestinationHeight[k] + / (mode_lib->vba.WritebackSourceHeight[k] + * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k])) + - mode_lib->vba.WritebackDRAMClockChangeWatermark; + } + mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k] = dml_min(mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k], + WritebackDRAMClockChangeLatencyMargin); + } + } + + mode_lib->vba.MinActiveDRAMClockChangeMargin = 999999; + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k] + < mode_lib->vba.MinActiveDRAMClockChangeMargin) { + mode_lib->vba.MinActiveDRAMClockChangeMargin = + mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k]; + } + } + + mode_lib->vba.MinActiveDRAMClockChangeLatencySupported = mode_lib->vba.MinActiveDRAMClockChangeMargin + + mode_lib->vba.DRAMClockChangeLatency; + + if (mode_lib->vba.MinActiveDRAMClockChangeMargin > 0) { + mode_lib->vba.DRAMClockChangeSupport = dm_dram_clock_change_vactive; + } else { + if (mode_lib->vba.SynchronizedVBlank || mode_lib->vba.NumberOfActivePlanes == 1) { + mode_lib->vba.DRAMClockChangeSupport = dm_dram_clock_change_vblank; + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (!mode_lib->vba.AllowDRAMClockChangeDuringVBlank[k]) { + mode_lib->vba.DRAMClockChangeSupport = dm_dram_clock_change_unsupported; + } + } + } else { + mode_lib->vba.DRAMClockChangeSupport = dm_dram_clock_change_unsupported; + } + } + + //XFC Parameters: + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (mode_lib->vba.XFCEnabled[k] == true) { + double TWait; + + mode_lib->vba.XFCSlaveVUpdateOffset[k] = mode_lib->vba.XFCTSlvVupdateOffset; + mode_lib->vba.XFCSlaveVupdateWidth[k] = mode_lib->vba.XFCTSlvVupdateWidth; + mode_lib->vba.XFCSlaveVReadyOffset[k] = mode_lib->vba.XFCTSlvVreadyOffset; + TWait = CalculateTWait(mode_lib->vba.PrefetchMode, + mode_lib->vba.DRAMClockChangeLatency, + mode_lib->vba.UrgentLatency, + mode_lib->vba.SREnterPlusExitTime); + mode_lib->vba.XFCRemoteSurfaceFlipDelay = CalculateRemoteSurfaceFlipDelay(mode_lib, + mode_lib->vba.VRatio[k], + mode_lib->vba.SwathWidthY[k], + dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1), + mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k], + mode_lib->vba.XFCTSlvVupdateOffset, + mode_lib->vba.XFCTSlvVupdateWidth, + mode_lib->vba.XFCTSlvVreadyOffset, + mode_lib->vba.XFCXBUFLatencyTolerance, + mode_lib->vba.XFCFillBWOverhead, + mode_lib->vba.XFCSlvChunkSize, + mode_lib->vba.XFCBusTransportTime, + mode_lib->vba.TCalc, + TWait, + &mode_lib->vba.SrcActiveDrainRate, + &mode_lib->vba.TInitXFill, + &mode_lib->vba.TslvChk); + mode_lib->vba.XFCRemoteSurfaceFlipLatency[k] = dml_floor(mode_lib->vba.XFCRemoteSurfaceFlipDelay / (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]), + 1); + mode_lib->vba.XFCTransferDelay[k] = dml_ceil(mode_lib->vba.XFCBusTransportTime / (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]), + 1); + mode_lib->vba.XFCPrechargeDelay[k] = dml_ceil((mode_lib->vba.XFCBusTransportTime + mode_lib->vba.TInitXFill + mode_lib->vba.TslvChk) + / (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]), + 1); + mode_lib->vba.InitFillLevel = mode_lib->vba.XFCXBUFLatencyTolerance * mode_lib->vba.SrcActiveDrainRate; + mode_lib->vba.FinalFillMargin = (mode_lib->vba.DestinationLinesToRequestVMInVBlank[k] + + mode_lib->vba.DestinationLinesToRequestRowInVBlank[k]) * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k] * mode_lib->vba.SrcActiveDrainRate + mode_lib->vba.XFCFillConstant; + mode_lib->vba.FinalFillLevel = mode_lib->vba.XFCRemoteSurfaceFlipDelay * mode_lib->vba.SrcActiveDrainRate + + mode_lib->vba.FinalFillMargin; + mode_lib->vba.RemainingFillLevel = dml_max(0.0, + mode_lib->vba.FinalFillLevel - mode_lib->vba.InitFillLevel); + mode_lib->vba.TFinalxFill = mode_lib->vba.RemainingFillLevel + / (mode_lib->vba.SrcActiveDrainRate * mode_lib->vba.XFCFillBWOverhead / 100); + mode_lib->vba.XFCPrefetchMargin[k] = mode_lib->vba.XFCRemoteSurfaceFlipDelay + mode_lib->vba.TFinalxFill + + (mode_lib->vba.DestinationLinesToRequestVMInVBlank[k] + + mode_lib->vba.DestinationLinesToRequestRowInVBlank[k]) + * mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]; + } else { + mode_lib->vba.XFCSlaveVUpdateOffset[k] = 0; + mode_lib->vba.XFCSlaveVupdateWidth[k] = 0; + mode_lib->vba.XFCSlaveVReadyOffset[k] = 0; + mode_lib->vba.XFCRemoteSurfaceFlipLatency[k] = 0; + mode_lib->vba.XFCPrechargeDelay[k] = 0; + mode_lib->vba.XFCTransferDelay[k] = 0; + mode_lib->vba.XFCPrefetchMargin[k] = 0; + } + } +} + +static void DisplayPipeConfiguration(struct display_mode_lib *mode_lib) +{ + double BytePerPixDETY; + double BytePerPixDETC; + double Read256BytesBlockHeightY; + double Read256BytesBlockHeightC; + double Read256BytesBlockWidthY; + double Read256BytesBlockWidthC; + double MaximumSwathHeightY; + double MaximumSwathHeightC; + double MinimumSwathHeightY; + double MinimumSwathHeightC; + double SwathWidth; + double SwathWidthGranularityY; + double SwathWidthGranularityC; + double RoundedUpMaxSwathSizeBytesY; + double RoundedUpMaxSwathSizeBytesC; + unsigned int j, k; + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + bool MainPlaneDoesODMCombine = false; + + if (mode_lib->vba.SourcePixelFormat[k] == dm_444_64) { + BytePerPixDETY = 8; + BytePerPixDETC = 0; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_32) { + BytePerPixDETY = 4; + BytePerPixDETC = 0; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_16) { + BytePerPixDETY = 2; + BytePerPixDETC = 0; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_8) { + BytePerPixDETY = 1; + BytePerPixDETC = 0; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_420_8) { + BytePerPixDETY = 1; + BytePerPixDETC = 2; + } else { + BytePerPixDETY = 4.0 / 3.0; + BytePerPixDETC = 8.0 / 3.0; + } + + if ((mode_lib->vba.SourcePixelFormat[k] == dm_444_64 || mode_lib->vba.SourcePixelFormat[k] == dm_444_32 + || mode_lib->vba.SourcePixelFormat[k] == dm_444_16 + || mode_lib->vba.SourcePixelFormat[k] == dm_444_8)) { + if (mode_lib->vba.SurfaceTiling[k] == dm_sw_linear) { + Read256BytesBlockHeightY = 1; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_64) { + Read256BytesBlockHeightY = 4; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_32 + || mode_lib->vba.SourcePixelFormat[k] == dm_444_16) { + Read256BytesBlockHeightY = 8; + } else { + Read256BytesBlockHeightY = 16; + } + Read256BytesBlockWidthY = 256 / dml_ceil(BytePerPixDETY, 1) + / Read256BytesBlockHeightY; + Read256BytesBlockHeightC = 0; + Read256BytesBlockWidthC = 0; + } else { + if (mode_lib->vba.SurfaceTiling[k] == dm_sw_linear) { + Read256BytesBlockHeightY = 1; + Read256BytesBlockHeightC = 1; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_420_8) { + Read256BytesBlockHeightY = 16; + Read256BytesBlockHeightC = 8; + } else { + Read256BytesBlockHeightY = 8; + Read256BytesBlockHeightC = 8; + } + Read256BytesBlockWidthY = 256 / dml_ceil(BytePerPixDETY, 1) + / Read256BytesBlockHeightY; + Read256BytesBlockWidthC = 256 / dml_ceil(BytePerPixDETC, 2) + / Read256BytesBlockHeightC; + } + + if (mode_lib->vba.SourceScan[k] == dm_horz) { + MaximumSwathHeightY = Read256BytesBlockHeightY; + MaximumSwathHeightC = Read256BytesBlockHeightC; + } else { + MaximumSwathHeightY = Read256BytesBlockWidthY; + MaximumSwathHeightC = Read256BytesBlockWidthC; + } + + if ((mode_lib->vba.SourcePixelFormat[k] == dm_444_64 || mode_lib->vba.SourcePixelFormat[k] == dm_444_32 + || mode_lib->vba.SourcePixelFormat[k] == dm_444_16 + || mode_lib->vba.SourcePixelFormat[k] == dm_444_8)) { + if (mode_lib->vba.SurfaceTiling[k] == dm_sw_linear + || (mode_lib->vba.SourcePixelFormat[k] == dm_444_64 + && (mode_lib->vba.SurfaceTiling[k] == dm_sw_4kb_s + || mode_lib->vba.SurfaceTiling[k] + == dm_sw_4kb_s_x + || mode_lib->vba.SurfaceTiling[k] + == dm_sw_64kb_s + || mode_lib->vba.SurfaceTiling[k] + == dm_sw_64kb_s_t + || mode_lib->vba.SurfaceTiling[k] + == dm_sw_64kb_s_x + || mode_lib->vba.SurfaceTiling[k] + == dm_sw_var_s + || mode_lib->vba.SurfaceTiling[k] + == dm_sw_var_s_x) + && mode_lib->vba.SourceScan[k] == dm_horz)) { + MinimumSwathHeightY = MaximumSwathHeightY; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_8 && mode_lib->vba.SourceScan[k] != dm_horz) { + MinimumSwathHeightY = MaximumSwathHeightY; + } else { + MinimumSwathHeightY = MaximumSwathHeightY / 2.0; + } + MinimumSwathHeightC = MaximumSwathHeightC; + } else { + if (mode_lib->vba.SurfaceTiling[k] == dm_sw_linear) { + MinimumSwathHeightY = MaximumSwathHeightY; + MinimumSwathHeightC = MaximumSwathHeightC; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_420_8 && mode_lib->vba.SourceScan[k] == dm_horz) { + MinimumSwathHeightY = MaximumSwathHeightY / 2.0; + MinimumSwathHeightC = MaximumSwathHeightC; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_420_10 && mode_lib->vba.SourceScan[k] == dm_horz) { + MinimumSwathHeightC = MaximumSwathHeightC / 2.0; + MinimumSwathHeightY = MaximumSwathHeightY; + } else { + MinimumSwathHeightY = MaximumSwathHeightY; + MinimumSwathHeightC = MaximumSwathHeightC; + } + } + + if (mode_lib->vba.SourceScan[k] == dm_horz) { + SwathWidth = mode_lib->vba.ViewportWidth[k]; + } else { + SwathWidth = mode_lib->vba.ViewportHeight[k]; + } + + if (mode_lib->vba.ODMCombineEnabled[k] == true) { + MainPlaneDoesODMCombine = true; + } + for (j = 0; j < mode_lib->vba.NumberOfActivePlanes; ++j) { + if (mode_lib->vba.BlendingAndTiming[k] == j && mode_lib->vba.ODMCombineEnabled[j] == true) { + MainPlaneDoesODMCombine = true; + } + } + + if (MainPlaneDoesODMCombine == true) { + SwathWidth = dml_min(SwathWidth, mode_lib->vba.HActive[k] / 2.0 * mode_lib->vba.HRatio[k]); + } else { + SwathWidth = SwathWidth / mode_lib->vba.DPPPerPlane[k]; + } + + SwathWidthGranularityY = 256 / dml_ceil(BytePerPixDETY, 1) / MaximumSwathHeightY; + RoundedUpMaxSwathSizeBytesY = (dml_ceil((double)(SwathWidth - 1), + SwathWidthGranularityY) + SwathWidthGranularityY) * BytePerPixDETY + * MaximumSwathHeightY; + if (mode_lib->vba.SourcePixelFormat[k] == dm_420_10) { + RoundedUpMaxSwathSizeBytesY = dml_ceil(RoundedUpMaxSwathSizeBytesY, 256) + + 256; + } + if (MaximumSwathHeightC > 0) { + SwathWidthGranularityC = 256.0 / dml_ceil(BytePerPixDETC, 2) + / MaximumSwathHeightC; + RoundedUpMaxSwathSizeBytesC = (dml_ceil((double)(SwathWidth / 2.0 - 1), + SwathWidthGranularityC) + SwathWidthGranularityC) + * BytePerPixDETC * MaximumSwathHeightC; + if (mode_lib->vba.SourcePixelFormat[k] == dm_420_10) { + RoundedUpMaxSwathSizeBytesC = dml_ceil(RoundedUpMaxSwathSizeBytesC, + 256) + 256; + } + } else + RoundedUpMaxSwathSizeBytesC = 0.0; + + if (RoundedUpMaxSwathSizeBytesY + RoundedUpMaxSwathSizeBytesC + <= mode_lib->vba.DETBufferSizeInKByte * 1024.0 / 2.0) { + mode_lib->vba.SwathHeightY[k] = MaximumSwathHeightY; + mode_lib->vba.SwathHeightC[k] = MaximumSwathHeightC; + } else { + mode_lib->vba.SwathHeightY[k] = MinimumSwathHeightY; + mode_lib->vba.SwathHeightC[k] = MinimumSwathHeightC; + } + + if (mode_lib->vba.SwathHeightC[k] == 0) { + mode_lib->vba.DETBufferSizeY[k] = mode_lib->vba.DETBufferSizeInKByte * 1024; + mode_lib->vba.DETBufferSizeC[k] = 0; + } else if (mode_lib->vba.SwathHeightY[k] <= mode_lib->vba.SwathHeightC[k]) { + mode_lib->vba.DETBufferSizeY[k] = mode_lib->vba.DETBufferSizeInKByte * 1024.0 / 2; + mode_lib->vba.DETBufferSizeC[k] = mode_lib->vba.DETBufferSizeInKByte * 1024.0 / 2; + } else { + mode_lib->vba.DETBufferSizeY[k] = mode_lib->vba.DETBufferSizeInKByte * 1024.0 * 2 / 3; + mode_lib->vba.DETBufferSizeC[k] = mode_lib->vba.DETBufferSizeInKByte * 1024.0 / 3; + } + } +} + +bool Calculate256BBlockSizes(enum source_format_class SourcePixelFormat, + enum dm_swizzle_mode SurfaceTiling, + unsigned int BytePerPixelY, + unsigned int BytePerPixelC, + unsigned int *BlockHeight256BytesY, + unsigned int *BlockHeight256BytesC, + unsigned int *BlockWidth256BytesY, + unsigned int *BlockWidth256BytesC) +{ + if ((SourcePixelFormat == dm_444_64 || SourcePixelFormat == dm_444_32 + || SourcePixelFormat == dm_444_16 || SourcePixelFormat == dm_444_16 + || SourcePixelFormat == dm_444_8)) { + if (SurfaceTiling == dm_sw_linear) { + *BlockHeight256BytesY = 1; + } else if (SourcePixelFormat == dm_444_64) { + *BlockHeight256BytesY = 4; + } else if (SourcePixelFormat == dm_444_8) { + *BlockHeight256BytesY = 16; + } else { + *BlockHeight256BytesY = 8; + } + *BlockWidth256BytesY = 256 / BytePerPixelY / *BlockHeight256BytesY; + *BlockHeight256BytesC = 0; + *BlockWidth256BytesC = 0; + } else { + if (SurfaceTiling == dm_sw_linear) { + *BlockHeight256BytesY = 1; + *BlockHeight256BytesC = 1; + } else if (SourcePixelFormat == dm_420_8) { + *BlockHeight256BytesY = 16; + *BlockHeight256BytesC = 8; + } else { + *BlockHeight256BytesY = 8; + *BlockHeight256BytesC = 8; + } + *BlockWidth256BytesY = 256 / BytePerPixelY / *BlockHeight256BytesY; + *BlockWidth256BytesC = 256 / BytePerPixelC / *BlockHeight256BytesC; + } + return true; +} + +static double CalculateTWait(unsigned int PrefetchMode, + double DRAMClockChangeLatency, + double UrgentLatency, + double SREnterPlusExitTime) +{ + if (PrefetchMode == 0) { + return dml_max(DRAMClockChangeLatency + UrgentLatency, + dml_max(SREnterPlusExitTime, UrgentLatency)); + } else if (PrefetchMode == 1) { + return dml_max(SREnterPlusExitTime, UrgentLatency); + } else { + return UrgentLatency; + } +} + +static double CalculateRemoteSurfaceFlipDelay(struct display_mode_lib *mode_lib, + double VRatio, + double SwathWidth, + double Bpp, + double LineTime, + double XFCTSlvVupdateOffset, + double XFCTSlvVupdateWidth, + double XFCTSlvVreadyOffset, + double XFCXBUFLatencyTolerance, + double XFCFillBWOverhead, + double XFCSlvChunkSize, + double XFCBusTransportTime, + double TCalc, + double TWait, + double *SrcActiveDrainRate, + double *TInitXFill, + double *TslvChk) +{ + double TSlvSetup, AvgfillRate, result; + + *SrcActiveDrainRate = VRatio * SwathWidth * Bpp / LineTime; + TSlvSetup = XFCTSlvVupdateOffset + XFCTSlvVupdateWidth + XFCTSlvVreadyOffset; + *TInitXFill = XFCXBUFLatencyTolerance / (1 + XFCFillBWOverhead / 100); + AvgfillRate = *SrcActiveDrainRate * (1 + XFCFillBWOverhead / 100); + *TslvChk = XFCSlvChunkSize / AvgfillRate; + dml_print("DML::CalculateRemoteSurfaceFlipDelay: SrcActiveDrainRate: %f\n", + *SrcActiveDrainRate); + dml_print("DML::CalculateRemoteSurfaceFlipDelay: TSlvSetup: %f\n", TSlvSetup); + dml_print("DML::CalculateRemoteSurfaceFlipDelay: TInitXFill: %f\n", *TInitXFill); + dml_print("DML::CalculateRemoteSurfaceFlipDelay: AvgfillRate: %f\n", AvgfillRate); + dml_print("DML::CalculateRemoteSurfaceFlipDelay: TslvChk: %f\n", *TslvChk); + result = 2 * XFCBusTransportTime + TSlvSetup + TCalc + TWait + *TslvChk + *TInitXFill; // TODO: This doesn't seem to match programming guide + dml_print("DML::CalculateRemoteSurfaceFlipDelay: RemoteSurfaceFlipDelay: %f\n", result); + return result; +} + +static double CalculateWriteBackDISPCLK(enum source_format_class WritebackPixelFormat, + double PixelClock, + double WritebackHRatio, + double WritebackVRatio, + unsigned int WritebackLumaHTaps, + unsigned int WritebackLumaVTaps, + unsigned int WritebackChromaHTaps, + unsigned int WritebackChromaVTaps, + double WritebackDestinationWidth, + unsigned int HTotal, + unsigned int WritebackChromaLineBufferWidth) +{ + double CalculateWriteBackDISPCLK = 1.01 * PixelClock + * dml_max( + dml_ceil(WritebackLumaHTaps / 4.0, 1) / WritebackHRatio, + dml_max( + (WritebackLumaVTaps * dml_ceil(1.0 / WritebackVRatio, 1) + * dml_ceil(WritebackDestinationWidth / 4.0, 1) + + dml_ceil(WritebackDestinationWidth / 4.0, 1)) / (double)HTotal + + dml_ceil(1.0 / WritebackVRatio, 1) * (dml_ceil(WritebackLumaVTaps / 4.0, 1) + 4.0) + / (double)HTotal, + dml_ceil(1.0 / WritebackVRatio, 1) * WritebackDestinationWidth / (double)HTotal)); + if (WritebackPixelFormat != dm_444_32) { + CalculateWriteBackDISPCLK = dml_max( + CalculateWriteBackDISPCLK, + 1.01 * PixelClock + * dml_max( + dml_ceil(WritebackChromaHTaps / 2.0, 1) / (2 * WritebackHRatio), + dml_max( + (WritebackChromaVTaps * dml_ceil(1 / (2 * WritebackVRatio), 1) + * dml_ceil(WritebackDestinationWidth / 2.0 / 2.0, 1) + + dml_ceil(WritebackDestinationWidth / 2.0 / WritebackChromaLineBufferWidth, 1)) + / HTotal + + dml_ceil(1 / (2 * WritebackVRatio), 1) + * (dml_ceil(WritebackChromaVTaps / 4.0, 1) + 4) / HTotal, + dml_ceil(1.0 / (2 * WritebackVRatio), 1) * WritebackDestinationWidth / 2.0 + / HTotal))); + } + return CalculateWriteBackDISPCLK; +} + +static double CalculateWriteBackDelay( +enum source_format_class WritebackPixelFormat, + double WritebackHRatio, + double WritebackVRatio, + unsigned int WritebackLumaHTaps, + unsigned int WritebackLumaVTaps, + unsigned int WritebackChromaHTaps, + unsigned int WritebackChromaVTaps, + unsigned int WritebackDestinationWidth) +{ + double CalculateWriteBackDelay = dml_max( + dml_ceil(WritebackLumaHTaps / 4.0, 1) / WritebackHRatio, + WritebackLumaVTaps * dml_ceil(1.0 / WritebackVRatio, 1) + * dml_ceil(WritebackDestinationWidth / 4.0, 1) + + dml_ceil(1.0 / WritebackVRatio, 1) * (dml_ceil(WritebackLumaVTaps / 4.0, 1) + 4)); + + if (WritebackPixelFormat != dm_444_32) { + CalculateWriteBackDelay = dml_max( + CalculateWriteBackDelay, + dml_max( + dml_ceil(WritebackChromaHTaps / 2.0, 1) / (2 * WritebackHRatio), + WritebackChromaVTaps * dml_ceil(1 / (2 * WritebackVRatio), 1) + * dml_ceil(WritebackDestinationWidth / 2.0 / 2.0, 1) + + dml_ceil(1 / (2 * WritebackVRatio), 1) + * (dml_ceil(WritebackChromaVTaps / 4.0, 1) + 4))); + } + return CalculateWriteBackDelay; +} + +static void CalculateActiveRowBandwidth(bool VirtualMemoryEnable, + enum source_format_class SourcePixelFormat, + double VRatio, + bool DCCEnable, + double LineTime, + unsigned int MetaRowByteLuma, + unsigned int MetaRowByteChroma, + unsigned int meta_row_height_luma, + unsigned int meta_row_height_chroma, + unsigned int PixelPTEBytesPerRowLuma, + unsigned int PixelPTEBytesPerRowChroma, + unsigned int dpte_row_height_luma, + unsigned int dpte_row_height_chroma, + double *meta_row_bw, + double *dpte_row_bw, + double *qual_row_bw) +{ + if (DCCEnable != true) { + *meta_row_bw = 0; + } else if (SourcePixelFormat == dm_420_8 || SourcePixelFormat == dm_420_10) { + *meta_row_bw = VRatio * MetaRowByteLuma / (meta_row_height_luma * LineTime) + + VRatio / 2 * MetaRowByteChroma + / (meta_row_height_chroma * LineTime); + } else { + *meta_row_bw = VRatio * MetaRowByteLuma / (meta_row_height_luma * LineTime); + } + + if (VirtualMemoryEnable != true) { + *dpte_row_bw = 0; + } else if (SourcePixelFormat == dm_420_8 || SourcePixelFormat == dm_420_10) { + *dpte_row_bw = VRatio * PixelPTEBytesPerRowLuma / (dpte_row_height_luma * LineTime) + + VRatio / 2 * PixelPTEBytesPerRowChroma + / (dpte_row_height_chroma * LineTime); + } else { + *dpte_row_bw = VRatio * PixelPTEBytesPerRowLuma / (dpte_row_height_luma * LineTime); + } + + if ((SourcePixelFormat == dm_420_8 || SourcePixelFormat == dm_420_10)) { + *qual_row_bw = *meta_row_bw + *dpte_row_bw; + } else { + *qual_row_bw = 0; + } +} + +static void CalculateFlipSchedule(struct display_mode_lib *mode_lib, + double UrgentExtraLatency, + double UrgentLatency, + unsigned int MaxPageTableLevels, + bool VirtualMemoryEnable, + double BandwidthAvailableForImmediateFlip, + unsigned int TotImmediateFlipBytes, + enum source_format_class SourcePixelFormat, + unsigned int ImmediateFlipBytes, + double LineTime, + double Tno_bw, + double VRatio, + double PDEAndMetaPTEBytesFrame, + unsigned int MetaRowByte, + unsigned int PixelPTEBytesPerRow, + bool DCCEnable, + unsigned int dpte_row_height, + unsigned int meta_row_height, + double qual_row_bw, + double *DestinationLinesToRequestVMInImmediateFlip, + double *DestinationLinesToRequestRowInImmediateFlip, + double *final_flip_bw, + bool *ImmediateFlipSupportedForPipe) +{ + double min_row_time = 0.0; + + if (SourcePixelFormat == dm_420_8 || SourcePixelFormat == dm_420_10) { + *DestinationLinesToRequestVMInImmediateFlip = 0.0; + *DestinationLinesToRequestRowInImmediateFlip = 0.0; + *final_flip_bw = qual_row_bw; + *ImmediateFlipSupportedForPipe = true; + } else { + double TimeForFetchingMetaPTEImmediateFlip; + double TimeForFetchingRowInVBlankImmediateFlip; + + if (VirtualMemoryEnable == true) { + mode_lib->vba.ImmediateFlipBW = BandwidthAvailableForImmediateFlip * ImmediateFlipBytes + / TotImmediateFlipBytes; + TimeForFetchingMetaPTEImmediateFlip = + dml_max(Tno_bw + + PDEAndMetaPTEBytesFrame + / mode_lib->vba.ImmediateFlipBW, + dml_max(UrgentExtraLatency + + UrgentLatency + * (MaxPageTableLevels + - 1), + LineTime / 4.0)); + } else { + TimeForFetchingMetaPTEImmediateFlip = 0; + } + + *DestinationLinesToRequestVMInImmediateFlip = dml_floor(4.0 * (TimeForFetchingMetaPTEImmediateFlip / LineTime + 0.125), + 1) / 4.0; + + if ((VirtualMemoryEnable == true || DCCEnable == true)) { + mode_lib->vba.ImmediateFlipBW = BandwidthAvailableForImmediateFlip * ImmediateFlipBytes + / TotImmediateFlipBytes; + TimeForFetchingRowInVBlankImmediateFlip = dml_max((MetaRowByte + PixelPTEBytesPerRow) / mode_lib->vba.ImmediateFlipBW, + dml_max(UrgentLatency, LineTime / 4.0)); + } else { + TimeForFetchingRowInVBlankImmediateFlip = 0; + } + + *DestinationLinesToRequestRowInImmediateFlip = dml_floor(4.0 * (TimeForFetchingRowInVBlankImmediateFlip / LineTime + 0.125), + 1) / 4.0; + + if (VirtualMemoryEnable == true) { + *final_flip_bw = + dml_max(PDEAndMetaPTEBytesFrame + / (*DestinationLinesToRequestVMInImmediateFlip + * LineTime), + (MetaRowByte + PixelPTEBytesPerRow) + / (TimeForFetchingRowInVBlankImmediateFlip + * LineTime)); + } else if (MetaRowByte + PixelPTEBytesPerRow > 0) { + *final_flip_bw = (MetaRowByte + PixelPTEBytesPerRow) + / (TimeForFetchingRowInVBlankImmediateFlip * LineTime); + } else { + *final_flip_bw = 0; + } + + if (VirtualMemoryEnable && !DCCEnable) + min_row_time = dpte_row_height * LineTime / VRatio; + else if (!VirtualMemoryEnable && DCCEnable) + min_row_time = meta_row_height * LineTime / VRatio; + else + min_row_time = dml_min(dpte_row_height, meta_row_height) * LineTime + / VRatio; + + if (*DestinationLinesToRequestVMInImmediateFlip >= 8 + || *DestinationLinesToRequestRowInImmediateFlip >= 16 + || TimeForFetchingMetaPTEImmediateFlip + + 2 * TimeForFetchingRowInVBlankImmediateFlip > min_row_time) + *ImmediateFlipSupportedForPipe = false; + else + *ImmediateFlipSupportedForPipe = true; + } +} + +static void PixelClockAdjustmentForProgressiveToInterlaceUnit(struct display_mode_lib *mode_lib) +{ + unsigned int k; + + //Progressive To dml_ml->vba.Interlace Unit Effect + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + mode_lib->vba.PixelClockBackEnd[k] = mode_lib->vba.PixelClock[k]; + if (mode_lib->vba.Interlace[k] == 1 && mode_lib->vba.ProgressiveToInterlaceUnitInOPP == true) { + mode_lib->vba.PixelClock[k] = 2 * mode_lib->vba.PixelClock[k]; + } + } +} + +static unsigned int CursorBppEnumToBits(enum cursor_bpp ebpp) +{ + switch (ebpp) { + case dm_cur_2bit: + return 2; + case dm_cur_32bit: + return 32; + case dm_cur_64bit: + return 64; + default: + return 0; + } +} diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h new file mode 100644 index 000000000000..a24fe9a0383d --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h @@ -0,0 +1,410 @@ +/* + * display_mode_vba.h + * + * Created on: Aug 18, 2017 + * Author: dlaktyus + */ + +#ifndef __DML2_DISPLAY_MODE_VBA_H__ +#define __DML2_DISPLAY_MODE_VBA_H__ + +#include "dml_common_defs.h" + +struct display_mode_lib; + +void set_prefetch_mode(struct display_mode_lib *mode_lib, + bool cstate_en, + bool pstate_en, + bool ignore_viewport_pos, + bool immediate_flip_support); + +#define dml_get_attr_decl(attr) double get_##attr(struct display_mode_lib *mode_lib, const display_e2e_pipe_params_st *pipes, unsigned int num_pipes) + +dml_get_attr_decl(clk_dcf_deepsleep); +dml_get_attr_decl(wm_urgent); +dml_get_attr_decl(wm_memory_trip); +dml_get_attr_decl(wm_writeback_urgent); +dml_get_attr_decl(wm_stutter_exit); +dml_get_attr_decl(wm_stutter_enter_exit); +dml_get_attr_decl(wm_dram_clock_change); +dml_get_attr_decl(wm_writeback_dram_clock_change); +dml_get_attr_decl(wm_xfc_underflow); +dml_get_attr_decl(stutter_efficiency_no_vblank); +dml_get_attr_decl(stutter_efficiency); +dml_get_attr_decl(urgent_latency); +dml_get_attr_decl(urgent_extra_latency); +dml_get_attr_decl(nonurgent_latency); +dml_get_attr_decl(dram_clock_change_latency); +dml_get_attr_decl(dispclk_calculated); +dml_get_attr_decl(total_data_read_bw); +dml_get_attr_decl(return_bw); +dml_get_attr_decl(tcalc); + +#define dml_get_pipe_attr_decl(attr) double get_##attr(struct display_mode_lib *mode_lib, const display_e2e_pipe_params_st *pipes, unsigned int num_pipes, unsigned int which_pipe) + +dml_get_pipe_attr_decl(dsc_delay); +dml_get_pipe_attr_decl(dppclk_calculated); +dml_get_pipe_attr_decl(dscclk_calculated); +dml_get_pipe_attr_decl(min_ttu_vblank); +dml_get_pipe_attr_decl(vratio_prefetch_l); +dml_get_pipe_attr_decl(vratio_prefetch_c); +dml_get_pipe_attr_decl(dst_x_after_scaler); +dml_get_pipe_attr_decl(dst_y_after_scaler); +dml_get_pipe_attr_decl(dst_y_per_vm_vblank); +dml_get_pipe_attr_decl(dst_y_per_row_vblank); +dml_get_pipe_attr_decl(dst_y_prefetch); +dml_get_pipe_attr_decl(dst_y_per_vm_flip); +dml_get_pipe_attr_decl(dst_y_per_row_flip); +dml_get_pipe_attr_decl(xfc_transfer_delay); +dml_get_pipe_attr_decl(xfc_precharge_delay); +dml_get_pipe_attr_decl(xfc_remote_surface_flip_latency); +dml_get_pipe_attr_decl(xfc_prefetch_margin); + +unsigned int get_vstartup_calculated( + struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *pipes, + unsigned int num_pipes, + unsigned int which_pipe); + +double get_total_immediate_flip_bytes( + struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *pipes, + unsigned int num_pipes); +double get_total_immediate_flip_bw( + struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *pipes, + unsigned int num_pipes); +double get_total_prefetch_bw( + struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *pipes, + unsigned int num_pipes); + +bool Calculate256BBlockSizes( + enum source_format_class SourcePixelFormat, + enum dm_swizzle_mode SurfaceTiling, + unsigned int BytePerPixelY, + unsigned int BytePerPixelC, + unsigned int *BlockHeight256BytesY, + unsigned int *BlockHeight256BytesC, + unsigned int *BlockWidth256BytesY, + unsigned int *BlockWidth256BytesC); + + +struct vba_vars_st { + ip_params_st ip; + soc_bounding_box_st soc; + mode_evaluation_st me; + + unsigned int MaximumMaxVStartupLines; + double cursor_bw[DC__NUM_PIPES__MAX]; + double meta_row_bw[DC__NUM_PIPES__MAX]; + double dpte_row_bw[DC__NUM_PIPES__MAX]; + double qual_row_bw[DC__NUM_PIPES__MAX]; + double WritebackDISPCLK; + double PSCL_THROUGHPUT_LUMA[DC__NUM_PIPES__MAX]; + double PSCL_THROUGHPUT_CHROMA[DC__NUM_PIPES__MAX]; + double DPPCLKUsingSingleDPPLuma; + double DPPCLKUsingSingleDPPChroma; + double DPPCLKUsingSingleDPP[DC__NUM_PIPES__MAX]; + double DISPCLKWithRamping; + double DISPCLKWithoutRamping; + double GlobalDPPCLK; + double MaxDispclk; + double DISPCLKWithRampingRoundedToDFSGranularity; + double DISPCLKWithoutRampingRoundedToDFSGranularity; + double MaxDispclkRoundedToDFSGranularity; + bool DCCEnabledAnyPlane; + double ReturnBandwidthToDCN; + unsigned int SwathWidthY[DC__NUM_PIPES__MAX]; + unsigned int SwathWidthSingleDPPY[DC__NUM_PIPES__MAX]; + double BytePerPixelDETY[DC__NUM_PIPES__MAX]; + double BytePerPixelDETC[DC__NUM_PIPES__MAX]; + double ReadBandwidthPlaneLuma[DC__NUM_PIPES__MAX]; + double ReadBandwidthPlaneChroma[DC__NUM_PIPES__MAX]; + unsigned int TotalActiveDPP; + unsigned int TotalDCCActiveDPP; + double UrgentRoundTripAndOutOfOrderLatency; + double DisplayPipeLineDeliveryTimeLuma[DC__NUM_PIPES__MAX]; // WM + double DisplayPipeLineDeliveryTimeChroma[DC__NUM_PIPES__MAX]; // WM + double LinesInDETY[DC__NUM_PIPES__MAX]; // WM + double LinesInDETC[DC__NUM_PIPES__MAX]; // WM + unsigned int LinesInDETYRoundedDownToSwath[DC__NUM_PIPES__MAX]; // WM + unsigned int LinesInDETCRoundedDownToSwath[DC__NUM_PIPES__MAX]; // WM + double FullDETBufferingTimeY[DC__NUM_PIPES__MAX]; // WM + double FullDETBufferingTimeC[DC__NUM_PIPES__MAX]; // WM + double MinFullDETBufferingTime; + double FrameTimeForMinFullDETBufferingTime; + double AverageReadBandwidthGBytePerSecond; + double PartOfBurstThatFitsInROB; + double StutterBurstTime; + //unsigned int NextPrefetchMode; + double VBlankTime; + double SmallestVBlank; + double DCFCLKDeepSleepPerPlane; + double EffectiveDETPlusLBLinesLuma; + double EffectiveDETPlusLBLinesChroma; + double UrgentLatencySupportUsLuma; + double UrgentLatencySupportUsChroma; + double UrgentLatencySupportUs[DC__NUM_PIPES__MAX]; + unsigned int DSCFormatFactor; + unsigned int BlockHeight256BytesY[DC__NUM_PIPES__MAX]; + unsigned int BlockHeight256BytesC[DC__NUM_PIPES__MAX]; + unsigned int BlockWidth256BytesY[DC__NUM_PIPES__MAX]; + unsigned int BlockWidth256BytesC[DC__NUM_PIPES__MAX]; + double VInitPreFillY[DC__NUM_PIPES__MAX]; + double VInitPreFillC[DC__NUM_PIPES__MAX]; + unsigned int MaxNumSwathY[DC__NUM_PIPES__MAX]; + unsigned int MaxNumSwathC[DC__NUM_PIPES__MAX]; + double PrefetchSourceLinesY[DC__NUM_PIPES__MAX]; + double PrefetchSourceLinesC[DC__NUM_PIPES__MAX]; + double PixelPTEBytesPerRow[DC__NUM_PIPES__MAX]; + double MetaRowByte[DC__NUM_PIPES__MAX]; + bool PTEBufferSizeNotExceeded; // not used + unsigned int dpte_row_height[DC__NUM_PIPES__MAX]; + unsigned int dpte_row_height_chroma[DC__NUM_PIPES__MAX]; + unsigned int meta_row_height[DC__NUM_PIPES__MAX]; + unsigned int meta_row_height_chroma[DC__NUM_PIPES__MAX]; + + unsigned int MacroTileWidthY; + unsigned int MacroTileWidthC; + unsigned int MaxVStartupLines[DC__NUM_PIPES__MAX]; + double WritebackDelay[DC__NUM_PIPES__MAX]; + bool PrefetchModeSupported; + bool AllowDRAMClockChangeDuringVBlank[DC__NUM_PIPES__MAX]; + bool AllowDRAMSelfRefreshDuringVBlank[DC__NUM_PIPES__MAX]; + double RequiredPrefetchPixDataBW[DC__NUM_PIPES__MAX]; + double XFCRemoteSurfaceFlipDelay; + double TInitXFill; + double TslvChk; + double SrcActiveDrainRate; + double Tno_bw[DC__NUM_PIPES__MAX]; + bool ImmediateFlipSupported; + + double prefetch_vm_bw[DC__NUM_PIPES__MAX]; + double prefetch_row_bw[DC__NUM_PIPES__MAX]; + bool ImmediateFlipSupportedForPipe[DC__NUM_PIPES__MAX]; + unsigned int VStartupLines; + double DisplayPipeLineDeliveryTimeLumaPrefetch[DC__NUM_PIPES__MAX]; + double DisplayPipeLineDeliveryTimeChromaPrefetch[DC__NUM_PIPES__MAX]; + unsigned int ActiveDPPs; + unsigned int LBLatencyHidingSourceLinesY; + unsigned int LBLatencyHidingSourceLinesC; + double ActiveDRAMClockChangeLatencyMargin[DC__NUM_PIPES__MAX]; + double MinActiveDRAMClockChangeMargin; + double XFCSlaveVUpdateOffset[DC__NUM_PIPES__MAX]; + double XFCSlaveVupdateWidth[DC__NUM_PIPES__MAX]; + double XFCSlaveVReadyOffset[DC__NUM_PIPES__MAX]; + double InitFillLevel; + double FinalFillMargin; + double FinalFillLevel; + double RemainingFillLevel; + double TFinalxFill; + + + // + // SOC Bounding Box Parameters + // + double SRExitTime; + double SREnterPlusExitTime; + double UrgentLatency; + double WritebackLatency; + double PercentOfIdealDRAMAndFabricBWReceivedAfterUrgLatency; + double NumberOfChannels; + double DRAMChannelWidth; + double FabricDatapathToDCNDataReturn; + double ReturnBusWidth; + double Downspreading; + double DISPCLKDPPCLKDSCCLKDownSpreading; + double DISPCLKDPPCLKVCOSpeed; + double RoundTripPingLatencyCycles; + double UrgentOutOfOrderReturnPerChannel; + unsigned int VMMPageSize; + double DRAMClockChangeLatency; + double XFCBusTransportTime; + double XFCXBUFLatencyTolerance; + + // + // IP Parameters + // + unsigned int ROBBufferSizeInKByte; + double DETBufferSizeInKByte; + unsigned int DPPOutputBufferPixels; + unsigned int OPPOutputBufferLines; + unsigned int PixelChunkSizeInKByte; + double ReturnBW; + bool VirtualMemoryEnable; + unsigned int MaxPageTableLevels; + unsigned int OverridePageTableLevels; + unsigned int PTEChunkSize; + unsigned int MetaChunkSize; + unsigned int WritebackChunkSize; + bool ODMCapability; + unsigned int NumberOfDSC; + unsigned int LineBufferSize; + unsigned int MaxLineBufferLines; + unsigned int WritebackInterfaceLumaBufferSize; + unsigned int WritebackInterfaceChromaBufferSize; + unsigned int WritebackChromaLineBufferWidth; + double MaxDCHUBToPSCLThroughput; + double MaxPSCLToLBThroughput; + unsigned int PTEBufferSizeInRequests; + double DISPCLKRampingMargin; + unsigned int MaxInterDCNTileRepeaters; + bool XFCSupported; + double XFCSlvChunkSize; + double XFCFillBWOverhead; + double XFCFillConstant; + double XFCTSlvVupdateOffset; + double XFCTSlvVupdateWidth; + double XFCTSlvVreadyOffset; + double DPPCLKDelaySubtotal; + double DPPCLKDelaySCL; + double DPPCLKDelaySCLLBOnly; + double DPPCLKDelayCNVCFormater; + double DPPCLKDelayCNVCCursor; + double DISPCLKDelaySubtotal; + bool ProgressiveToInterlaceUnitInOPP; + unsigned int PDEProcessingBufIn64KBReqs; + + // Pipe/Plane Parameters + int VoltageLevel; + double FabricAndDRAMBandwidth; + double FabricClock; + double DRAMSpeed; + double DISPCLK; + double SOCCLK; + double DCFCLK; + + unsigned int NumberOfActivePlanes; + unsigned int ViewportWidth[DC__NUM_DPP]; + unsigned int ViewportHeight[DC__NUM_DPP]; + unsigned int ViewportYStartY[DC__NUM_DPP]; + unsigned int ViewportYStartC[DC__NUM_DPP]; + unsigned int PitchY[DC__NUM_DPP]; + unsigned int PitchC[DC__NUM_DPP]; + double HRatio[DC__NUM_DPP]; + double VRatio[DC__NUM_DPP]; + unsigned int htaps[DC__NUM_DPP]; + unsigned int vtaps[DC__NUM_DPP]; + unsigned int HTAPsChroma[DC__NUM_DPP]; + unsigned int VTAPsChroma[DC__NUM_DPP]; + unsigned int HTotal[DC__NUM_DPP]; + unsigned int VTotal[DC__NUM_DPP]; + unsigned int DPPPerPlane[DC__NUM_DPP]; + double PixelClock[DC__NUM_DPP]; + double PixelClockBackEnd[DC__NUM_DPP]; + double DPPCLK[DC__NUM_DPP]; + bool DCCEnable[DC__NUM_DPP]; + unsigned int DCCMetaPitchY[DC__NUM_DPP]; + enum scan_direction_class SourceScan[DC__NUM_DPP]; + enum source_format_class SourcePixelFormat[DC__NUM_DPP]; + bool WritebackEnable[DC__NUM_DPP]; + double WritebackDestinationWidth[DC__NUM_DPP]; + double WritebackDestinationHeight[DC__NUM_DPP]; + double WritebackSourceHeight[DC__NUM_DPP]; + enum source_format_class WritebackPixelFormat[DC__NUM_DPP]; + unsigned int WritebackLumaHTaps[DC__NUM_DPP]; + unsigned int WritebackLumaVTaps[DC__NUM_DPP]; + unsigned int WritebackChromaHTaps[DC__NUM_DPP]; + unsigned int WritebackChromaVTaps[DC__NUM_DPP]; + double WritebackHRatio[DC__NUM_DPP]; + double WritebackVRatio[DC__NUM_DPP]; + unsigned int HActive[DC__NUM_DPP]; + unsigned int VActive[DC__NUM_DPP]; + bool Interlace[DC__NUM_DPP]; + enum dm_swizzle_mode SurfaceTiling[DC__NUM_DPP]; + unsigned int ScalerRecoutWidth[DC__NUM_DPP]; + bool DynamicMetadataEnable[DC__NUM_DPP]; + unsigned int DynamicMetadataLinesBeforeActiveRequired[DC__NUM_DPP]; + unsigned int DynamicMetadataTransmittedBytes[DC__NUM_DPP]; + double DCCRate[DC__NUM_DPP]; + bool ODMCombineEnabled[DC__NUM_DPP]; + double OutputBpp[DC__NUM_DPP]; + unsigned int NumberOfDSCSlices[DC__NUM_DPP]; + bool DSCEnabled[DC__NUM_DPP]; + unsigned int DSCDelay[DC__NUM_DPP]; + unsigned int DSCInputBitPerComponent[DC__NUM_DPP]; + enum output_format_class OutputFormat[DC__NUM_DPP]; + enum output_encoder_class Output[DC__NUM_DPP]; + unsigned int BlendingAndTiming[DC__NUM_DPP]; + bool SynchronizedVBlank; + unsigned int NumberOfCursors[DC__NUM_DPP]; + unsigned int CursorWidth[DC__NUM_DPP][DC__NUM_CURSOR]; + unsigned int CursorBPP[DC__NUM_DPP][DC__NUM_CURSOR]; + bool XFCEnabled[DC__NUM_DPP]; + bool ScalerEnabled[DC__NUM_DPP]; + + // Intermediates/Informational + bool ImmediateFlipSupport; + unsigned int SwathHeightY[DC__NUM_DPP]; + unsigned int SwathHeightC[DC__NUM_DPP]; + unsigned int DETBufferSizeY[DC__NUM_DPP]; + unsigned int DETBufferSizeC[DC__NUM_DPP]; + unsigned int LBBitPerPixel[DC__NUM_DPP]; + double LastPixelOfLineExtraWatermark; + double TotalDataReadBandwidth; + unsigned int TotalActiveWriteback; + unsigned int EffectiveLBLatencyHidingSourceLinesLuma; + unsigned int EffectiveLBLatencyHidingSourceLinesChroma; + double BandwidthAvailableForImmediateFlip; + unsigned int PrefetchMode; + bool IgnoreViewportPositioning; + double PrefetchBandwidth[DC__NUM_DPP]; + bool ErrorResult[DC__NUM_DPP]; + double PDEAndMetaPTEBytesFrame[DC__NUM_DPP]; + + // + // Calculated dml_ml->vba.Outputs + // + double DCFClkDeepSleep; + double UrgentWatermark; + double UrgentExtraLatency; + double MemoryTripWatermark; + double WritebackUrgentWatermark; + double StutterExitWatermark; + double StutterEnterPlusExitWatermark; + double DRAMClockChangeWatermark; + double WritebackDRAMClockChangeWatermark; + double StutterEfficiency; + double StutterEfficiencyNotIncludingVBlank; + double MinUrgentLatencySupportUs; + double NonUrgentLatencyTolerance; + double MinActiveDRAMClockChangeLatencySupported; + enum clock_change_support DRAMClockChangeSupport; + + // These are the clocks calcuated by the library but they are not actually + // used explicitly. They are fetched by tests and then possibly used. The + // ultimate values to use are the ones specified by the parameters to DML + double DISPCLK_calculated; + double DSCCLK_calculated[DC__NUM_DPP]; + double DPPCLK_calculated[DC__NUM_DPP]; + + unsigned int VStartup[DC__NUM_DPP]; + unsigned int VStartupRequiredWhenNotEnoughTimeForDynamicMetadata; + + double ImmediateFlipBW; + unsigned int TotImmediateFlipBytes; + double TCalc; + double MinTTUVBlank[DC__NUM_DPP]; + double VRatioPrefetchY[DC__NUM_DPP]; + double VRatioPrefetchC[DC__NUM_DPP]; + double DSTXAfterScaler[DC__NUM_DPP]; + double DSTYAfterScaler[DC__NUM_DPP]; + + double DestinationLinesToRequestVMInVBlank[DC__NUM_DPP]; + double DestinationLinesToRequestRowInVBlank[DC__NUM_DPP]; + double DestinationLinesForPrefetch[DC__NUM_DPP]; + double DestinationLinesToRequestRowInImmediateFlip[DC__NUM_DPP]; + double DestinationLinesToRequestVMInImmediateFlip[DC__NUM_DPP]; + + double XFCTransferDelay[DC__NUM_DPP]; + double XFCPrechargeDelay[DC__NUM_DPP]; + double XFCRemoteSurfaceFlipLatency[DC__NUM_DPP]; + double XFCPrefetchMargin[DC__NUM_DPP]; + + display_e2e_pipe_params_st cache_pipes[DC__NUM_DPP]; + unsigned int cache_num_pipes; + unsigned int pipe_plane[DC__NUM_PIPES__MAX]; +}; + +#endif /* _DML2_DISPLAY_MODE_VBA_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.c b/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.c index 2e4dc57cafa0..30c379d95156 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.c @@ -27,340 +27,79 @@ #include "display_mode_lib.h" #include "soc_bounding_box.h" -static enum voltage_state power_state( +display_pipe_clock_st dml_clks_get_pipe_clocks( struct display_mode_lib *mode_lib, - double dispclk, - double dppclk) -{ - enum voltage_state state1; - enum voltage_state state2; - - if (dispclk <= mode_lib->soc.vmin.dispclk_mhz) - state1 = dm_vmin; - else if (dispclk <= mode_lib->soc.vnom.dispclk_mhz) - state1 = dm_vnom; - else if (dispclk <= mode_lib->soc.vmax.dispclk_mhz) - state1 = dm_vmax; - else - state1 = dm_vmax_exceeded; - - if (dppclk <= mode_lib->soc.vmin.dppclk_mhz) - state2 = dm_vmin; - else if (dppclk <= mode_lib->soc.vnom.dppclk_mhz) - state2 = dm_vnom; - else if (dppclk <= mode_lib->soc.vmax.dppclk_mhz) - state2 = dm_vmax; - else - state2 = dm_vmax_exceeded; - - if (state1 > state2) - return state1; - else - return state2; -} - -static unsigned int dpp_in_grp( - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - unsigned int num_pipes, - unsigned int hsplit_grp) -{ - unsigned int num_dpp = 0; - unsigned int i; - - for (i = 0; i < num_pipes; i++) { - if (e2e[i].pipe.src.is_hsplit) { - if (e2e[i].pipe.src.hsplit_grp == hsplit_grp) { - num_dpp++; - } - } - } - - if (0 == num_dpp) - num_dpp = 1; - - return num_dpp; -} - -static void calculate_pipe_clk_requirement( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - unsigned int num_dpp_in_grp, - double *dppclk, - double *dispclk, - bool *dppdiv) -{ - double pscl_throughput = 0.0; - double max_hratio = e2e->pipe.scale_ratio_depth.hscl_ratio; - double max_vratio = e2e->pipe.scale_ratio_depth.vscl_ratio; - double max_htaps = e2e->pipe.scale_taps.htaps; - double max_vtaps = e2e->pipe.scale_taps.vtaps; - double dpp_clock_divider = (double) num_dpp_in_grp; - double dispclk_dppclk_ratio; - double dispclk_ramp_margin_percent; - - if (max_hratio > 1.0) { - double pscl_to_lb = ((double) mode_lib->ip.max_pscl_lb_bw_pix_per_clk * max_hratio) - / dml_ceil(max_htaps / 6.0); - pscl_throughput = dml_min( - pscl_to_lb, - (double) mode_lib->ip.max_dchub_pscl_bw_pix_per_clk); - } else { - pscl_throughput = dml_min( - (double) mode_lib->ip.max_pscl_lb_bw_pix_per_clk, - (double) mode_lib->ip.max_dchub_pscl_bw_pix_per_clk); - } - - DTRACE("pscl_throughput: %f pix per clk", pscl_throughput); - DTRACE("vtaps: %f hratio: %f vratio: %f", max_vtaps, max_hratio, max_vratio); - *dppclk = dml_max( - max_vtaps / 6.0 * dml_min(1.0, max_hratio), - max_hratio * max_vratio / pscl_throughput); - DTRACE("pixel rate multiplier: %f", *dppclk); - *dppclk = dml_max(*dppclk, 1.0); - DTRACE("pixel rate multiplier clamped: %f", *dppclk); - *dppclk = *dppclk * e2e->pipe.dest.pixel_rate_mhz; - - *dppclk = *dppclk / dpp_clock_divider; - DTRACE("dppclk after split: %f", *dppclk); - - if (dpp_clock_divider > 1.0 && (*dppclk < e2e->pipe.dest.pixel_rate_mhz)) { - dispclk_dppclk_ratio = 2.0; - *dppdiv = true; - } else { - dispclk_dppclk_ratio = 1.0; - *dppdiv = false; - } - - dispclk_ramp_margin_percent = mode_lib->ip.dispclk_ramp_margin_percent; - - /* Comment this out because of Gabes possible bug in spreadsheet, - * just to make other cases evident during debug - * - *if(e2e->clks_cfg.voltage == dm_vmax) - * dispclk_ramp_margin_percent = 0.0; - */ - - /* account for ramping margin and downspread */ - *dispclk = dml_max(*dppclk * dispclk_dppclk_ratio, e2e->pipe.dest.pixel_rate_mhz) - * (1.0 + (double) mode_lib->soc.downspread_percent / 100.0) - * (1.0 + (double) dispclk_ramp_margin_percent / 100.0); - - return; -} - -bool dml_clks_pipe_clock_requirement_fit_power_constraint( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - unsigned int num_dpp_in_grp) -{ - double dppclk = 0; - double dispclk = 0; - bool dppdiv = 0; - - calculate_pipe_clk_requirement(mode_lib, e2e, num_dpp_in_grp, &dppclk, &dispclk, &dppdiv); - - if (power_state(mode_lib, dispclk, dppclk) > e2e->clks_cfg.voltage) { - return false; - } - - return true; -} - -static void get_plane_clks( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - unsigned int num_pipes, - double *dppclks, - double *dispclks, - bool *dppdiv) -{ - /* it is assumed that the scale ratios passed into the e2e pipe params have already been calculated - * for any split pipe configurations, where extra pixels inthe overlap region do not contribute to - * the scale ratio. This means that we can simply calculate the dppclk for each dpp independently - * and we would expect the same result on any split pipes, which would be handled - */ - unsigned int i; - - for (i = 0; i < num_pipes; i++) { - double num_dpp_in_grp; - double dispclk_ramp_margin_percent; - double dispclk_margined; - - if (e2e[i].pipe.src.is_hsplit) - num_dpp_in_grp = (double) dpp_in_grp( - e2e, - num_pipes, - e2e[i].pipe.src.hsplit_grp); - else - num_dpp_in_grp = 1; - - calculate_pipe_clk_requirement( - mode_lib, - &e2e[i], - num_dpp_in_grp, - &dppclks[i], - &dispclks[i], - &dppdiv[i]); - - dispclk_ramp_margin_percent = mode_lib->ip.dispclk_ramp_margin_percent; - - dispclk_margined = e2e[i].pipe.dest.pixel_rate_mhz - * (1.0 + (double) mode_lib->soc.downspread_percent / 100.0) - * (1.0 + (double) dispclk_ramp_margin_percent / 100.0); - - DTRACE("p%d: requested power state: %d", i, (int) e2e[0].clks_cfg.voltage); - - if (power_state(mode_lib, dispclks[i], dppclks[i]) - > power_state(mode_lib, dispclk_margined, dispclk_margined) - && dispclk_margined > dppclks[i]) { - if (power_state(mode_lib, dispclks[i], dppclks[i]) - > e2e[0].clks_cfg.voltage) { - dispclks[i] = dispclk_margined; - dppclks[i] = dispclk_margined; - dppdiv[i] = false; - } - } - - DTRACE("p%d: dispclk: %f", i, dispclks[i]); - } -} - -static void get_dcfclk( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - unsigned int num_pipes, - double *dcfclk_mhz) -{ - double bytes_per_pixel_det_y[DC__NUM_PIPES__MAX]; - double bytes_per_pixel_det_c[DC__NUM_PIPES__MAX]; - double swath_width_y[DC__NUM_PIPES__MAX]; - unsigned int i; - double total_read_bandwidth_gbps = 0.0; - - for (i = 0; i < num_pipes; i++) { - if (e2e[i].pipe.src.source_scan == dm_horz) { - swath_width_y[i] = e2e[i].pipe.src.viewport_width * 1.0; - } else { - swath_width_y[i] = e2e[i].pipe.src.viewport_height * 1.0; - } - - switch (e2e[i].pipe.src.source_format) { - case dm_444_64: - bytes_per_pixel_det_y[i] = 8.0; - bytes_per_pixel_det_c[i] = 0.0; - break; - case dm_444_32: - bytes_per_pixel_det_y[i] = 4.0; - bytes_per_pixel_det_c[i] = 0.0; - break; - case dm_444_16: - bytes_per_pixel_det_y[i] = 2.0; - bytes_per_pixel_det_c[i] = 0.0; - break; - case dm_422_8: - bytes_per_pixel_det_y[i] = 2.0; - bytes_per_pixel_det_c[i] = 0.0; - break; - case dm_422_10: - bytes_per_pixel_det_y[i] = 4.0; - bytes_per_pixel_det_c[i] = 0.0; - break; - case dm_420_8: - bytes_per_pixel_det_y[i] = 1.0; - bytes_per_pixel_det_c[i] = 2.0; - break; - case dm_420_10: - bytes_per_pixel_det_y[i] = 4.0 / 3.0; - bytes_per_pixel_det_c[i] = 8.0 / 3.0; - break; - default: - BREAK_TO_DEBUGGER(); /* invalid src_format in get_dcfclk */ - } - } - - for (i = 0; i < num_pipes; i++) { - double read_bandwidth_plane_mbps = 0.0; - read_bandwidth_plane_mbps = (double) swath_width_y[i] - * ((double) bytes_per_pixel_det_y[i] - + (double) bytes_per_pixel_det_c[i] / 2.0) - / ((double) e2e[i].pipe.dest.htotal - / (double) e2e[i].pipe.dest.pixel_rate_mhz) - * e2e[i].pipe.scale_ratio_depth.vscl_ratio; - - if (e2e[i].pipe.src.dcc) { - read_bandwidth_plane_mbps += (read_bandwidth_plane_mbps / 1000.0 / 256.0); - } - - if (e2e[i].pipe.src.vm) { - read_bandwidth_plane_mbps += (read_bandwidth_plane_mbps / 1000.0 / 512.0); - } - - total_read_bandwidth_gbps = total_read_bandwidth_gbps - + read_bandwidth_plane_mbps / 1000.0; - } - - DTRACE("total bandwidth = %f gbps", total_read_bandwidth_gbps); - - (*dcfclk_mhz) = (total_read_bandwidth_gbps * 1000.0) / mode_lib->soc.return_bus_width_bytes; - - DTRACE( - "minimum theoretical dcfclk without stutter and full utilization = %f MHz", - (*dcfclk_mhz)); - -} - -struct _vcs_dpi_display_pipe_clock_st dml_clks_get_pipe_clocks( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + display_e2e_pipe_params_st *e2e, unsigned int num_pipes) { - struct _vcs_dpi_display_pipe_clock_st clocks; - double max_dispclk = 0.0; - double dcfclk; - double dispclks[DC__NUM_PIPES__MAX]; - double dppclks[DC__NUM_PIPES__MAX]; - bool dppdiv[DC__NUM_PIPES__MAX]; - unsigned int i; + display_pipe_clock_st clocks; + bool visited[DC__NUM_PIPES__MAX]; + double max_dispclk = 25.0; //the min dispclk is 25MHz, so keep the min dispclk caculated larger thant 25MHz + double dcfclk, socclk; + unsigned int i, j, k; + unsigned int dsc_inst = 0; DTRACE("Calculating pipe clocks..."); - /* this is the theoretical minimum, have to adjust based on valid values for soc */ - get_dcfclk(mode_lib, e2e, num_pipes, &dcfclk); - - /* if(dcfclk > soc.vnom.dcfclk_mhz) - * dcfclk = soc.vmax.dcfclk_mhz; - * else if(dcfclk > soc.vmin.dcfclk_mhz) - * dcfclk = soc.vnom.dcfclk_mhz; - * else - * dcfclk = soc.vmin.dcfclk_mhz; - */ - dcfclk = dml_socbb_voltage_scaling( &mode_lib->soc, (enum voltage_state) e2e[0].clks_cfg.voltage).dcfclk_mhz; + socclk = dml_socbb_voltage_scaling( + &mode_lib->soc, + (enum voltage_state) e2e[0].clks_cfg.voltage).socclk_mhz; clocks.dcfclk_mhz = dcfclk; + clocks.socclk_mhz = socclk; - get_plane_clks(mode_lib, e2e, num_pipes, dppclks, dispclks, dppdiv); - - for (i = 0; i < num_pipes; i++) { - max_dispclk = dml_max(max_dispclk, dispclks[i]); - } - + max_dispclk = dml_max(max_dispclk, get_dispclk_calculated(mode_lib, e2e, num_pipes)); clocks.dispclk_mhz = max_dispclk; - DTRACE("dispclk: %f Mhz", clocks.dispclk_mhz); - DTRACE("dcfclk: %f Mhz", clocks.dcfclk_mhz); + DTRACE(" dispclk: %f Mhz", clocks.dispclk_mhz); + DTRACE(" dcfclk: %f Mhz", clocks.dcfclk_mhz); + DTRACE(" socclk: %f Mhz", clocks.socclk_mhz); - for (i = 0; i < num_pipes; i++) { - if (dppclks[i] * 2 < max_dispclk) - dppdiv[i] = 1; + for (k = 0; k < num_pipes; ++k) + visited[k] = false; - if (dppdiv[i]) - clocks.dppclk_div[i] = 1; - else - clocks.dppclk_div[i] = 0; + for (i = 0; i < num_pipes; i++) { + clocks.dppclk_mhz[i] = get_dppclk_calculated(mode_lib, e2e, num_pipes, i); + DTRACE(" dppclk%d: %f Mhz", i, clocks.dppclk_mhz[i]); + + if (e2e[i].pipe.src.is_hsplit && !visited[i]) { + unsigned int grp = e2e[i].pipe.src.hsplit_grp; + + for (j = i; j < num_pipes; j++) { + if (e2e[j].pipe.src.hsplit_grp == grp && e2e[j].pipe.src.is_hsplit + && !visited[j]) { + clocks.dscclk_mhz[j] = get_dscclk_calculated( + mode_lib, + e2e, + num_pipes, + dsc_inst); + DTRACE(" dscclk%d: %f Mhz", j, clocks.dscclk_mhz[j]); + visited[j] = true; + } + } + dsc_inst++; + } - clocks.dppclk_mhz[i] = max_dispclk / ((dppdiv[i]) ? 2.0 : 1.0); - DTRACE("dppclk%d: %f Mhz", i, clocks.dppclk_mhz[i]); + if (!visited[i]) { + unsigned int otg_inst = e2e[i].pipe.dest.otg_inst; + + for (j = i; j < num_pipes; j++) { + // assign dscclk to all planes with this otg, except if they're doing odm combine, or mpc combine + // which is handled by the conditions above, the odm_combine is not required, but it helps make sense of this code + if (e2e[j].pipe.dest.otg_inst == otg_inst + && !e2e[j].pipe.dest.odm_combine && !visited[j]) { + clocks.dscclk_mhz[j] = get_dscclk_calculated( + mode_lib, + e2e, + num_pipes, + dsc_inst); + DTRACE(" dscclk%d: %f Mhz", j, clocks.dscclk_mhz[j]); + visited[j] = true; + } + } + dsc_inst++; + } } return clocks; diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.h b/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.h index aed5f33bb04f..a712dc3ecf4b 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.h @@ -29,13 +29,9 @@ struct display_mode_lib; -struct _vcs_dpi_display_pipe_clock_st dml_clks_get_pipe_clocks( +display_pipe_clock_st dml_clks_get_pipe_clocks( struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + display_e2e_pipe_params_st *e2e, unsigned int num_pipes); -bool dml_clks_pipe_clock_requirement_fit_power_constraint( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - unsigned int num_dpp_in_grp); #endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c index 9fccbbffe129..657b7386021d 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c @@ -22,8 +22,22 @@ * Authors: AMD * */ -#include "display_rq_dlg_calc.h" + #include "display_mode_lib.h" +#include "display_mode_vba.h" +#include "display_rq_dlg_calc.h" + +static void calculate_ttu_cursor(struct display_mode_lib *mode_lib, + double *refcyc_per_req_delivery_pre_cur, + double *refcyc_per_req_delivery_cur, + double refclk_freq_in_mhz, + double ref_freq_to_pix_freq, + double hscale_pixel_rate_l, + double hscl_ratio, + double vratio_pre_l, + double vratio_l, + unsigned int cur_width, + enum cursor_bpp cur_bpp); static unsigned int get_bytes_per_element(enum source_format_class source_format, bool is_chroma) { @@ -48,6 +62,8 @@ static unsigned int get_bytes_per_element(enum source_format_class source_format ret_val = 4; else ret_val = 2; + } else if (source_format == dm_444_8) { + ret_val = 1; } return ret_val; } @@ -62,123 +78,43 @@ static bool is_dual_plane(enum source_format_class source_format) return ret_val; } -static void get_blk256_size( - unsigned int *blk256_width, - unsigned int *blk256_height, - unsigned int bytes_per_element) -{ - if (bytes_per_element == 1) { - *blk256_width = 16; - *blk256_height = 16; - } else if (bytes_per_element == 2) { - *blk256_width = 16; - *blk256_height = 8; - } else if (bytes_per_element == 4) { - *blk256_width = 8; - *blk256_height = 8; - } else if (bytes_per_element == 8) { - *blk256_width = 8; - *blk256_height = 4; - } -} - -static double get_refcyc_per_delivery( - struct display_mode_lib *mode_lib, +static double get_refcyc_per_delivery(struct display_mode_lib *mode_lib, double refclk_freq_in_mhz, double pclk_freq_in_mhz, - int unsigned recout_width, + bool odm_combine, + unsigned int recout_width, + unsigned int hactive, double vratio, double hscale_pixel_rate, - int unsigned delivery_width, - int unsigned req_per_swath_ub) + unsigned int delivery_width, + unsigned int req_per_swath_ub) { double refcyc_per_delivery = 0.0; + if (vratio <= 1.0) { - refcyc_per_delivery = (double) refclk_freq_in_mhz * (double) recout_width - / pclk_freq_in_mhz / (double) req_per_swath_ub; + if (odm_combine) + refcyc_per_delivery = (double) refclk_freq_in_mhz + * dml_min((double) recout_width, (double) hactive / 2.0) + / pclk_freq_in_mhz / (double) req_per_swath_ub; + else + refcyc_per_delivery = (double) refclk_freq_in_mhz * (double) recout_width + / pclk_freq_in_mhz / (double) req_per_swath_ub; } else { refcyc_per_delivery = (double) refclk_freq_in_mhz * (double) delivery_width / (double) hscale_pixel_rate / (double) req_per_swath_ub; } - DTRACE("DLG: %s: refclk_freq_in_mhz = %3.2f", __func__, refclk_freq_in_mhz); - DTRACE("DLG: %s: pclk_freq_in_mhz = %3.2f", __func__, pclk_freq_in_mhz); - DTRACE("DLG: %s: recout_width = %d", __func__, recout_width); - DTRACE("DLG: %s: vratio = %3.2f", __func__, vratio); - DTRACE("DLG: %s: req_per_swath_ub = %d", __func__, req_per_swath_ub); - DTRACE("DLG: %s: refcyc_per_delivery= %3.2f", __func__, refcyc_per_delivery); + dml_print("DML_DLG: %s: refclk_freq_in_mhz = %3.2f\n", __func__, refclk_freq_in_mhz); + dml_print("DML_DLG: %s: pclk_freq_in_mhz = %3.2f\n", __func__, pclk_freq_in_mhz); + dml_print("DML_DLG: %s: recout_width = %d\n", __func__, recout_width); + dml_print("DML_DLG: %s: vratio = %3.2f\n", __func__, vratio); + dml_print("DML_DLG: %s: req_per_swath_ub = %d\n", __func__, req_per_swath_ub); + dml_print("DML_DLG: %s: refcyc_per_delivery= %3.2f\n", __func__, refcyc_per_delivery); return refcyc_per_delivery; } -static double get_vratio_pre( - struct display_mode_lib *mode_lib, - unsigned int max_num_sw, - unsigned int max_partial_sw, - unsigned int swath_height, - double vinit, - double l_sw) -{ - double prefill = dml_floor(vinit); - double vratio_pre = 1.0; - - vratio_pre = (max_num_sw * swath_height + max_partial_sw) / l_sw; - - if (swath_height > 4) { - double tmp0 = (max_num_sw * swath_height) / (l_sw - (prefill - 3.0) / 2.0); - if (tmp0 > vratio_pre) - vratio_pre = tmp0; - } - - DTRACE("DLG: %s: max_num_sw = %0d", __func__, max_num_sw); - DTRACE("DLG: %s: max_partial_sw = %0d", __func__, max_partial_sw); - DTRACE("DLG: %s: swath_height = %0d", __func__, swath_height); - DTRACE("DLG: %s: vinit = %3.2f", __func__, vinit); - DTRACE("DLG: %s: vratio_pre = %3.2f", __func__, vratio_pre); - - if (vratio_pre < 1.0) { - DTRACE("WARNING_DLG: %s: vratio_pre=%3.2f < 1.0, set to 1.0", __func__, vratio_pre); - vratio_pre = 1.0; - } - - if (vratio_pre > 4.0) { - DTRACE( - "WARNING_DLG: %s: vratio_pre=%3.2f > 4.0 (max scaling ratio). set to 4.0", - __func__, - vratio_pre); - vratio_pre = 4.0; - } - - return vratio_pre; -} - -static void get_swath_need( - struct display_mode_lib *mode_lib, - unsigned int *max_num_sw, - unsigned int *max_partial_sw, - unsigned int swath_height, - double vinit) -{ - double prefill = dml_floor(vinit); - unsigned int max_partial_sw_int; - - DTRACE("DLG: %s: swath_height = %0d", __func__, swath_height); - DTRACE("DLG: %s: vinit = %3.2f", __func__, vinit); - - ASSERT(prefill > 0.0 && prefill <= 8.0); - - *max_num_sw = (int unsigned) (dml_ceil((prefill - 1.0) / (double) swath_height) + 1.0); /* prefill has to be >= 1 */ - max_partial_sw_int = - (prefill == 1) ? - (swath_height - 1) : - ((int unsigned) (prefill - 2.0) % swath_height); - *max_partial_sw = (max_partial_sw_int < 1) ? 1 : max_partial_sw_int; /* ensure minimum of 1 is used */ - - DTRACE("DLG: %s: max_num_sw = %0d", __func__, *max_num_sw); - DTRACE("DLG: %s: max_partial_sw = %0d", __func__, *max_partial_sw); -} - static unsigned int get_blk_size_bytes(const enum source_macro_tile_size tile_size) { if (tile_size == dm_256k_tile) @@ -189,12 +125,11 @@ static unsigned int get_blk_size_bytes(const enum source_macro_tile_size tile_si return (4 * 1024); } -static void extract_rq_sizing_regs( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_data_rq_regs_st *rq_regs, - const struct _vcs_dpi_display_data_rq_sizing_params_st rq_sizing) +static void extract_rq_sizing_regs(struct display_mode_lib *mode_lib, + display_data_rq_regs_st *rq_regs, + const display_data_rq_sizing_params_st rq_sizing) { - DTRACE("DLG: %s: rq_sizing param", __func__); + dml_print("DML_DLG: %s: rq_sizing param\n", __func__); print__data_rq_sizing_params_st(mode_lib, rq_sizing); rq_regs->chunk_size = dml_log2(rq_sizing.chunk_bytes) - 10; @@ -214,25 +149,30 @@ static void extract_rq_sizing_regs( rq_regs->mpte_group_size = dml_log2(rq_sizing.mpte_group_bytes) - 6; } -void extract_rq_regs( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_rq_regs_st *rq_regs, - const struct _vcs_dpi_display_rq_params_st rq_param) +static void extract_rq_regs(struct display_mode_lib *mode_lib, + display_rq_regs_st *rq_regs, + const display_rq_params_st rq_param) { unsigned int detile_buf_size_in_bytes = mode_lib->ip.det_buffer_size_kbytes * 1024; unsigned int detile_buf_plane1_addr = 0; extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_l), rq_param.sizing.rq_l); - if (rq_param.yuv420) + + rq_regs->rq_regs_l.pte_row_height_linear = dml_floor(dml_log2(rq_param.dlg.rq_l.dpte_row_height), + 1) - 3; + + if (rq_param.yuv420) { extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_c), rq_param.sizing.rq_c); + rq_regs->rq_regs_c.pte_row_height_linear = dml_floor(dml_log2(rq_param.dlg.rq_c.dpte_row_height), + 1) - 3; + } rq_regs->rq_regs_l.swath_height = dml_log2(rq_param.dlg.rq_l.swath_height); rq_regs->rq_regs_c.swath_height = dml_log2(rq_param.dlg.rq_c.swath_height); - /* FIXME: take the max between luma, chroma chunk size? - * okay for now, as we are setting chunk_bytes to 8kb anyways - */ - if (rq_param.sizing.rq_l.chunk_bytes >= 32 * 1024) { /*32kb */ + // FIXME: take the max between luma, chroma chunk size? + // okay for now, as we are setting chunk_bytes to 8kb anyways + if (rq_param.sizing.rq_l.chunk_bytes >= 32 * 1024) { //32kb rq_regs->drq_expansion_mode = 0; } else { rq_regs->drq_expansion_mode = 2; @@ -244,21 +184,19 @@ void extract_rq_regs( if (rq_param.yuv420) { if ((double) rq_param.misc.rq_l.stored_swath_bytes / (double) rq_param.misc.rq_c.stored_swath_bytes <= 1.5) { - detile_buf_plane1_addr = (detile_buf_size_in_bytes / 2.0 / 64.0); /* half to chroma */ + detile_buf_plane1_addr = (detile_buf_size_in_bytes / 2.0 / 64.0); // half to chroma } else { - detile_buf_plane1_addr = dml_round_to_multiple( - (unsigned int) ((2.0 * detile_buf_size_in_bytes) / 3.0), + detile_buf_plane1_addr = dml_round_to_multiple((unsigned int) ((2.0 * detile_buf_size_in_bytes) / 3.0), 256, - 0) / 64.0; /* 2/3 to chroma */ + 0) / 64.0; // 2/3 to chroma } } rq_regs->plane1_base_address = detile_buf_plane1_addr; } -static void handle_det_buf_split( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_rq_params_st *rq_param, - const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param) +static void handle_det_buf_split(struct display_mode_lib *mode_lib, + display_rq_params_st *rq_param, + const display_pipe_source_params_st pipe_src_param) { unsigned int total_swath_bytes = 0; unsigned int swath_bytes_l = 0; @@ -277,12 +215,10 @@ static void handle_det_buf_split( full_swath_bytes_packed_c = rq_param->misc.rq_c.full_swath_bytes; if (rq_param->yuv420_10bpc) { - full_swath_bytes_packed_l = dml_round_to_multiple( - rq_param->misc.rq_l.full_swath_bytes * 2 / 3, + full_swath_bytes_packed_l = dml_round_to_multiple(rq_param->misc.rq_l.full_swath_bytes * 2 / 3, 256, 1) + 256; - full_swath_bytes_packed_c = dml_round_to_multiple( - rq_param->misc.rq_c.full_swath_bytes * 2 / 3, + full_swath_bytes_packed_c = dml_round_to_multiple(rq_param->misc.rq_c.full_swath_bytes * 2 / 3, 256, 1) + 256; } @@ -290,29 +226,19 @@ static void handle_det_buf_split( if (rq_param->yuv420) { total_swath_bytes = 2 * full_swath_bytes_packed_l + 2 * full_swath_bytes_packed_c; - if (total_swath_bytes <= detile_buf_size_in_bytes) { /*full 256b request */ + if (total_swath_bytes <= detile_buf_size_in_bytes) { //full 256b request req128_l = 0; req128_c = 0; swath_bytes_l = full_swath_bytes_packed_l; swath_bytes_c = full_swath_bytes_packed_c; - } else { /*128b request (for luma only for yuv420 8bpc) */ + } else { //128b request (for luma only for yuv420 8bpc) req128_l = 1; req128_c = 0; swath_bytes_l = full_swath_bytes_packed_l / 2; swath_bytes_c = full_swath_bytes_packed_c; } - - /* Bug workaround, luma and chroma req size needs to be the same. (see: DEGVIDCN10-137) - * TODO: Remove after rtl fix - */ - if (req128_l == 1) { - req128_c = 1; - DTRACE("DLG: %s: bug workaround DEGVIDCN10-137", __func__); - } - - /* Note: assumption, the config that pass in will fit into - * the detiled buffer. - */ + // Note: assumption, the config that pass in will fit into + // the detiled buffer. } else { total_swath_bytes = 2 * full_swath_bytes_packed_l; @@ -340,207 +266,47 @@ static void handle_det_buf_split( rq_param->dlg.rq_l.swath_height = 1 << log2_swath_height_l; rq_param->dlg.rq_c.swath_height = 1 << log2_swath_height_c; - DTRACE("DLG: %s: req128_l = %0d", __func__, req128_l); - DTRACE("DLG: %s: req128_c = %0d", __func__, req128_c); - DTRACE("DLG: %s: full_swath_bytes_packed_l = %0d", __func__, full_swath_bytes_packed_l); - DTRACE("DLG: %s: full_swath_bytes_packed_c = %0d", __func__, full_swath_bytes_packed_c); + dml_print("DML_DLG: %s: req128_l = %0d\n", __func__, req128_l); + dml_print("DML_DLG: %s: req128_c = %0d\n", __func__, req128_c); + dml_print("DML_DLG: %s: full_swath_bytes_packed_l = %0d\n", + __func__, + full_swath_bytes_packed_l); + dml_print("DML_DLG: %s: full_swath_bytes_packed_c = %0d\n", + __func__, + full_swath_bytes_packed_c); } -/* Need refactor. */ -void dml_rq_dlg_get_row_heights( - struct display_mode_lib *mode_lib, - unsigned int *o_dpte_row_height, - unsigned int *o_meta_row_height, +static void get_meta_and_pte_attr(struct display_mode_lib *mode_lib, + display_data_rq_dlg_params_st *rq_dlg_param, + display_data_rq_misc_params_st *rq_misc_param, + display_data_rq_sizing_params_st *rq_sizing_param, unsigned int vp_width, + unsigned int vp_height, unsigned int data_pitch, - int source_format, - int tiling, - int macro_tile_size, - int source_scan, - int is_chroma) + unsigned int meta_pitch, + unsigned int source_format, + unsigned int tiling, + unsigned int macro_tile_size, + unsigned int source_scan, + unsigned int is_chroma) { bool surf_linear = (tiling == dm_sw_linear); bool surf_vert = (source_scan == dm_vert); - unsigned int bytes_per_element = get_bytes_per_element( - (enum source_format_class) source_format, - is_chroma); - unsigned int log2_bytes_per_element = dml_log2(bytes_per_element); + unsigned int bytes_per_element; + unsigned int bytes_per_element_y = get_bytes_per_element((enum source_format_class)(source_format), + false); + unsigned int bytes_per_element_c = get_bytes_per_element((enum source_format_class)(source_format), + true); + unsigned int blk256_width = 0; unsigned int blk256_height = 0; - unsigned int log2_blk256_height; - unsigned int blk_bytes; - unsigned int log2_blk_bytes; - unsigned int log2_blk_height; - unsigned int log2_blk_width; - unsigned int log2_meta_req_bytes; - unsigned int log2_meta_req_height; - unsigned int log2_meta_req_width; - unsigned int log2_meta_row_height; - unsigned int log2_vmpg_bytes; - unsigned int dpte_buf_in_pte_reqs; - unsigned int log2_vmpg_height; - unsigned int log2_vmpg_width; - unsigned int log2_dpte_req_height_ptes; - unsigned int log2_dpte_req_width_ptes; - unsigned int log2_dpte_req_height; - unsigned int log2_dpte_req_width; - unsigned int log2_dpte_row_height_linear; - unsigned int log2_dpte_row_height; - unsigned int dpte_req_width; - - if (surf_linear) { - blk256_width = 256; - blk256_height = 1; - } else { - get_blk256_size(&blk256_width, &blk256_height, bytes_per_element); - } - - log2_blk256_height = dml_log2((double) blk256_height); - blk_bytes = surf_linear ? - 256 : get_blk_size_bytes((enum source_macro_tile_size) macro_tile_size); - log2_blk_bytes = dml_log2((double) blk_bytes); - log2_blk_height = 0; - log2_blk_width = 0; - - /* remember log rule - * "+" in log is multiply - * "-" in log is divide - * "/2" is like square root - * blk is vertical biased - */ - if (tiling != dm_sw_linear) - log2_blk_height = log2_blk256_height - + dml_ceil((double) (log2_blk_bytes - 8) / 2.0); - else - log2_blk_height = 0; /* blk height of 1 */ - - log2_blk_width = log2_blk_bytes - log2_bytes_per_element - log2_blk_height; - - /* ------- */ - /* meta */ - /* ------- */ - log2_meta_req_bytes = 6; /* meta request is 64b and is 8x8byte meta element */ - - /* each 64b meta request for dcn is 8x8 meta elements and - * a meta element covers one 256b block of the the data surface. - */ - log2_meta_req_height = log2_blk256_height + 3; /* meta req is 8x8 */ - log2_meta_req_width = log2_meta_req_bytes + 8 - log2_bytes_per_element - - log2_meta_req_height; - log2_meta_row_height = 0; - - /* the dimensions of a meta row are meta_row_width x meta_row_height in elements. - * calculate upper bound of the meta_row_width - */ - if (!surf_vert) - log2_meta_row_height = log2_meta_req_height; - else - log2_meta_row_height = log2_meta_req_width; - - *o_meta_row_height = 1 << log2_meta_row_height; - - /* ------ */ - /* dpte */ - /* ------ */ - log2_vmpg_bytes = dml_log2(mode_lib->soc.vmm_page_size_bytes); - dpte_buf_in_pte_reqs = mode_lib->ip.dpte_buffer_size_in_pte_reqs; - - log2_vmpg_height = 0; - log2_vmpg_width = 0; - log2_dpte_req_height_ptes = 0; - log2_dpte_req_width_ptes = 0; - log2_dpte_req_height = 0; - log2_dpte_req_width = 0; - log2_dpte_row_height_linear = 0; - log2_dpte_row_height = 0; - dpte_req_width = 0; /* 64b dpte req width in data element */ - - if (surf_linear) { - log2_vmpg_height = 0; /* one line high */ - } else { - log2_vmpg_height = (log2_vmpg_bytes - 8) / 2 + log2_blk256_height; - } - log2_vmpg_width = log2_vmpg_bytes - log2_bytes_per_element - log2_vmpg_height; - - /* only 3 possible shapes for dpte request in dimensions of ptes: 8x1, 4x2, 2x4. */ - if (log2_blk_bytes <= log2_vmpg_bytes) - log2_dpte_req_height_ptes = 0; - else if (log2_blk_height - log2_vmpg_height >= 2) - log2_dpte_req_height_ptes = 2; - else - log2_dpte_req_height_ptes = log2_blk_height - log2_vmpg_height; - log2_dpte_req_width_ptes = 3 - log2_dpte_req_height_ptes; - - ASSERT((log2_dpte_req_width_ptes == 3 && log2_dpte_req_height_ptes == 0) || /* 8x1 */ - (log2_dpte_req_width_ptes == 2 && log2_dpte_req_height_ptes == 1) || /* 4x2 */ - (log2_dpte_req_width_ptes == 1 && log2_dpte_req_height_ptes == 2)); /* 2x4 */ - - /* the dpte request dimensions in data elements is dpte_req_width x dpte_req_height - * log2_wmpg_width is how much 1 pte represent, now trying to calculate how much 64b pte req represent - */ - log2_dpte_req_height = log2_vmpg_height + log2_dpte_req_height_ptes; - log2_dpte_req_width = log2_vmpg_width + log2_dpte_req_width_ptes; - dpte_req_width = 1 << log2_dpte_req_width; - - /* calculate pitch dpte row buffer can hold - * round the result down to a power of two. - */ - if (surf_linear) { - log2_dpte_row_height_linear = dml_floor( - dml_log2(dpte_buf_in_pte_reqs * dpte_req_width / data_pitch)); - - ASSERT(log2_dpte_row_height_linear >= 3); - - if (log2_dpte_row_height_linear > 7) - log2_dpte_row_height_linear = 7; - - log2_dpte_row_height = log2_dpte_row_height_linear; - } else { - /* the upper bound of the dpte_row_width without dependency on viewport position follows. */ - if (!surf_vert) { - log2_dpte_row_height = log2_dpte_req_height; - } else { - log2_dpte_row_height = - (log2_blk_width < log2_dpte_req_width) ? - log2_blk_width : log2_dpte_req_width; - } - } - - /* From programming guide: - * There is a special case of saving only half of ptes returned due to buffer space limits. - * this case applies to 4 and 8bpe in horizontal access of a vp_width greater than 2560+16 - * when the pte request is 2x4 ptes (which happens when vmpg_bytes =4kb and tile blk_bytes >=64kb). - */ - if (!surf_vert && vp_width > (2560 + 16) && bytes_per_element >= 4 && log2_vmpg_bytes == 12 - && log2_blk_bytes >= 16) { - log2_dpte_row_height = log2_dpte_row_height - 1; /*half of the full height */ - } - - *o_dpte_row_height = 1 << log2_dpte_row_height; -} - -static void get_surf_rq_param( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_data_rq_sizing_params_st *rq_sizing_param, - struct _vcs_dpi_display_data_rq_dlg_params_st *rq_dlg_param, - struct _vcs_dpi_display_data_rq_misc_params_st *rq_misc_param, - const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param, - bool is_chroma) -{ - bool mode_422 = 0; - unsigned int vp_width = 0; - unsigned int vp_height = 0; - unsigned int data_pitch = 0; - unsigned int meta_pitch = 0; - unsigned int ppe = mode_422 ? 2 : 1; - bool surf_linear; - bool surf_vert; - unsigned int bytes_per_element; + unsigned int blk256_width_y = 0; + unsigned int blk256_height_y = 0; + unsigned int blk256_width_c = 0; + unsigned int blk256_height_c = 0; unsigned int log2_bytes_per_element; - unsigned int blk256_width; - unsigned int blk256_height; unsigned int log2_blk256_width; unsigned int log2_blk256_height; unsigned int blk_bytes; @@ -556,6 +322,8 @@ static void get_surf_rq_param( unsigned int meta_row_width_ub; unsigned int log2_meta_chunk_bytes; unsigned int log2_meta_chunk_height; + + //full sized meta chunk width in unit of data elements unsigned int log2_meta_chunk_width; unsigned int log2_min_meta_chunk_bytes; unsigned int min_meta_chunk_width; @@ -570,93 +338,72 @@ static void get_surf_rq_param( unsigned int vmpg_bytes; unsigned int meta_pte_req_per_frame_ub; unsigned int meta_pte_bytes_per_frame_ub; - unsigned int log2_vmpg_bytes; - unsigned int dpte_buf_in_pte_reqs; - unsigned int log2_vmpg_height; - unsigned int log2_vmpg_width; - unsigned int log2_dpte_req_height_ptes; - unsigned int log2_dpte_req_width_ptes; - unsigned int log2_dpte_req_height; - unsigned int log2_dpte_req_width; - unsigned int log2_dpte_row_height_linear; - unsigned int log2_dpte_row_height; - unsigned int log2_dpte_group_width; - unsigned int dpte_row_width_ub; - unsigned int dpte_row_height; - unsigned int dpte_req_height; - unsigned int dpte_req_width; - unsigned int dpte_group_width; - unsigned int log2_dpte_group_bytes; - unsigned int log2_dpte_group_length; - unsigned int func_meta_row_height, func_dpte_row_height; - - /* FIXME check if ppe apply for both luma and chroma in 422 case */ - if (is_chroma) { - vp_width = pipe_src_param.viewport_width_c / ppe; - vp_height = pipe_src_param.viewport_height_c; - data_pitch = pipe_src_param.data_pitch_c; - meta_pitch = pipe_src_param.meta_pitch_c; + const unsigned int log2_vmpg_bytes = dml_log2(mode_lib->soc.vmm_page_size_bytes); + const unsigned int dpte_buf_in_pte_reqs = mode_lib->ip.dpte_buffer_size_in_pte_reqs; + const unsigned int pde_proc_buffer_size_64k_reqs = + mode_lib->ip.pde_proc_buffer_size_64k_reqs; + + unsigned int log2_vmpg_height = 0; + unsigned int log2_vmpg_width = 0; + unsigned int log2_dpte_req_height_ptes = 0; + unsigned int log2_dpte_req_height = 0; + unsigned int log2_dpte_req_width = 0; + unsigned int log2_dpte_row_height_linear = 0; + unsigned int log2_dpte_row_height = 0; + unsigned int log2_dpte_group_width = 0; + unsigned int dpte_row_width_ub = 0; + unsigned int dpte_req_height = 0; + unsigned int dpte_req_width = 0; + unsigned int dpte_group_width = 0; + unsigned int log2_dpte_group_bytes = 0; + unsigned int log2_dpte_group_length = 0; + unsigned int pde_buf_entries; + bool yuv420 = (source_format == dm_420_8 || source_format == dm_420_10); + + Calculate256BBlockSizes((enum source_format_class)(source_format), + (enum dm_swizzle_mode)(tiling), + bytes_per_element_y, + bytes_per_element_c, + &blk256_height_y, + &blk256_height_c, + &blk256_width_y, + &blk256_width_c); + + if (!is_chroma) { + blk256_width = blk256_width_y; + blk256_height = blk256_height_y; + bytes_per_element = bytes_per_element_y; } else { - vp_width = pipe_src_param.viewport_width / ppe; - vp_height = pipe_src_param.viewport_height; - data_pitch = pipe_src_param.data_pitch; - meta_pitch = pipe_src_param.meta_pitch; + blk256_width = blk256_width_c; + blk256_height = blk256_height_c; + bytes_per_element = bytes_per_element_c; } - rq_sizing_param->chunk_bytes = 8192; - - if (rq_sizing_param->chunk_bytes == 64 * 1024) - rq_sizing_param->min_chunk_bytes = 0; - else - rq_sizing_param->min_chunk_bytes = 1024; - - rq_sizing_param->meta_chunk_bytes = 2048; - rq_sizing_param->min_meta_chunk_bytes = 256; - - rq_sizing_param->mpte_group_bytes = 2048; - - surf_linear = (pipe_src_param.sw_mode == dm_sw_linear); - surf_vert = (pipe_src_param.source_scan == dm_vert); - - bytes_per_element = get_bytes_per_element( - (enum source_format_class) pipe_src_param.source_format, - is_chroma); log2_bytes_per_element = dml_log2(bytes_per_element); - blk256_width = 0; - blk256_height = 0; - - if (surf_linear) { - blk256_width = 256 / bytes_per_element; - blk256_height = 1; - } else { - get_blk256_size(&blk256_width, &blk256_height, bytes_per_element); - } - DTRACE("DLG: %s: surf_linear = %d", __func__, surf_linear); - DTRACE("DLG: %s: surf_vert = %d", __func__, surf_vert); - DTRACE("DLG: %s: blk256_width = %d", __func__, blk256_width); - DTRACE("DLG: %s: blk256_height = %d", __func__, blk256_height); + dml_print("DML_DLG: %s: surf_linear = %d\n", __func__, surf_linear); + dml_print("DML_DLG: %s: surf_vert = %d\n", __func__, surf_vert); + dml_print("DML_DLG: %s: blk256_width = %d\n", __func__, blk256_width); + dml_print("DML_DLG: %s: blk256_height = %d\n", __func__, blk256_height); log2_blk256_width = dml_log2((double) blk256_width); log2_blk256_height = dml_log2((double) blk256_height); - blk_bytes = - surf_linear ? 256 : get_blk_size_bytes( - (enum source_macro_tile_size) pipe_src_param.macro_tile_size); + blk_bytes = surf_linear ? + 256 : get_blk_size_bytes((enum source_macro_tile_size) macro_tile_size); log2_blk_bytes = dml_log2((double) blk_bytes); log2_blk_height = 0; log2_blk_width = 0; - /* remember log rule - * "+" in log is multiply - * "-" in log is divide - * "/2" is like square root - * blk is vertical biased - */ - if (pipe_src_param.sw_mode != dm_sw_linear) + // remember log rule + // "+" in log is multiply + // "-" in log is divide + // "/2" is like square root + // blk is vertical biased + if (tiling != dm_sw_linear) log2_blk_height = log2_blk256_height - + dml_ceil((double) (log2_blk_bytes - 8) / 2.0); + + dml_ceil((double) (log2_blk_bytes - 8) / 2.0, 1); else - log2_blk_height = 0; /* blk height of 1 */ + log2_blk_height = 0; // blk height of 1 log2_blk_width = log2_blk_bytes - log2_bytes_per_element - log2_blk_height; @@ -665,10 +412,8 @@ static void get_surf_rq_param( + blk256_width; rq_dlg_param->req_per_swath_ub = rq_dlg_param->swath_width_ub >> log2_blk256_width; } else { - rq_dlg_param->swath_width_ub = dml_round_to_multiple( - vp_height - 1, - blk256_height, - 1) + blk256_height; + rq_dlg_param->swath_width_ub = dml_round_to_multiple(vp_height - 1, blk256_height, 1) + + blk256_height; rq_dlg_param->req_per_swath_ub = rq_dlg_param->swath_width_ub >> log2_blk256_height; } @@ -682,15 +427,14 @@ static void get_surf_rq_param( rq_misc_param->blk256_height = blk256_height; rq_misc_param->blk256_width = blk256_width; - /* ------- */ - /* meta */ - /* ------- */ - log2_meta_req_bytes = 6; /* meta request is 64b and is 8x8byte meta element */ + // ------- + // meta + // ------- + log2_meta_req_bytes = 6; // meta request is 64b and is 8x8byte meta element - /* each 64b meta request for dcn is 8x8 meta elements and - * a meta element covers one 256b block of the the data surface. - */ - log2_meta_req_height = log2_blk256_height + 3; /* meta req is 8x8 byte, each byte represent 1 blk256 */ + // each 64b meta request for dcn is 8x8 meta elements and + // a meta element covers one 256b block of the the data surface. + log2_meta_req_height = log2_blk256_height + 3; // meta req is 8x8 byte, each byte represent 1 blk256 log2_meta_req_width = log2_meta_req_bytes + 8 - log2_bytes_per_element - log2_meta_req_height; meta_req_width = 1 << log2_meta_req_width; @@ -698,9 +442,8 @@ static void get_surf_rq_param( log2_meta_row_height = 0; meta_row_width_ub = 0; - /* the dimensions of a meta row are meta_row_width x meta_row_height in elements. - * calculate upper bound of the meta_row_width - */ + // the dimensions of a meta row are meta_row_width x meta_row_height in elements. + // calculate upper bound of the meta_row_width if (!surf_vert) { log2_meta_row_height = log2_meta_req_height; meta_row_width_ub = dml_round_to_multiple(vp_width - 1, meta_req_width, 1) @@ -714,10 +457,12 @@ static void get_surf_rq_param( } rq_dlg_param->meta_bytes_per_row_ub = rq_dlg_param->meta_req_per_row_ub * 64; + rq_dlg_param->meta_row_height = 1 << log2_meta_row_height; + log2_meta_chunk_bytes = dml_log2(rq_sizing_param->meta_chunk_bytes); log2_meta_chunk_height = log2_meta_row_height; - /*full sized meta chunk width in unit of data elements */ + //full sized meta chunk width in unit of data elements log2_meta_chunk_width = log2_meta_chunk_bytes + 8 - log2_bytes_per_element - log2_meta_chunk_height; log2_min_meta_chunk_bytes = dml_log2(rq_sizing_param->min_meta_chunk_bytes); @@ -732,21 +477,24 @@ static void get_surf_rq_param( meta_blk_height = blk256_height * 64; meta_blk_width = meta_blk_bytes * 256 / bytes_per_element / meta_blk_height; meta_surface_bytes = meta_pitch - * (dml_round_to_multiple(vp_height - 1, meta_blk_height, 1) - + meta_blk_height) * bytes_per_element / 256; + * (dml_round_to_multiple(vp_height - 1, meta_blk_height, 1) + meta_blk_height) + * bytes_per_element / 256; vmpg_bytes = mode_lib->soc.vmm_page_size_bytes; - meta_pte_req_per_frame_ub = (dml_round_to_multiple( - meta_surface_bytes - vmpg_bytes, + meta_pte_req_per_frame_ub = (dml_round_to_multiple(meta_surface_bytes - vmpg_bytes, 8 * vmpg_bytes, 1) + 8 * vmpg_bytes) / (8 * vmpg_bytes); - meta_pte_bytes_per_frame_ub = meta_pte_req_per_frame_ub * 64; /*64B mpte request */ + meta_pte_bytes_per_frame_ub = meta_pte_req_per_frame_ub * 64; //64B mpte request rq_dlg_param->meta_pte_bytes_per_frame_ub = meta_pte_bytes_per_frame_ub; - DTRACE("DLG: %s: meta_blk_height = %d", __func__, meta_blk_height); - DTRACE("DLG: %s: meta_blk_width = %d", __func__, meta_blk_width); - DTRACE("DLG: %s: meta_surface_bytes = %d", __func__, meta_surface_bytes); - DTRACE("DLG: %s: meta_pte_req_per_frame_ub = %d", __func__, meta_pte_req_per_frame_ub); - DTRACE("DLG: %s: meta_pte_bytes_per_frame_ub = %d", __func__, meta_pte_bytes_per_frame_ub); + dml_print("DML_DLG: %s: meta_blk_height = %d\n", __func__, meta_blk_height); + dml_print("DML_DLG: %s: meta_blk_width = %d\n", __func__, meta_blk_width); + dml_print("DML_DLG: %s: meta_surface_bytes = %d\n", __func__, meta_surface_bytes); + dml_print("DML_DLG: %s: meta_pte_req_per_frame_ub = %d\n", + __func__, + meta_pte_req_per_frame_ub); + dml_print("DML_DLG: %s: meta_pte_bytes_per_frame_ub = %d\n", + __func__, + meta_pte_bytes_per_frame_ub); if (!surf_vert) meta_chunk_threshold = 2 * min_meta_chunk_width - meta_req_width; @@ -758,67 +506,58 @@ static void get_surf_rq_param( else rq_dlg_param->meta_chunks_per_row_ub = meta_chunk_per_row_int + 2; - rq_dlg_param->meta_row_height = 1 << log2_meta_row_height; - - /* ------ */ - /* dpte */ - /* ------ */ - log2_vmpg_bytes = dml_log2(mode_lib->soc.vmm_page_size_bytes); - dpte_buf_in_pte_reqs = mode_lib->ip.dpte_buffer_size_in_pte_reqs; - - log2_vmpg_height = 0; - log2_vmpg_width = 0; - log2_dpte_req_height_ptes = 0; - log2_dpte_req_width_ptes = 0; - log2_dpte_req_height = 0; - log2_dpte_req_width = 0; - log2_dpte_row_height_linear = 0; - log2_dpte_row_height = 0; - log2_dpte_group_width = 0; - dpte_row_width_ub = 0; - dpte_row_height = 0; - dpte_req_height = 0; /* 64b dpte req height in data element */ - dpte_req_width = 0; /* 64b dpte req width in data element */ - dpte_group_width = 0; - log2_dpte_group_bytes = 0; - log2_dpte_group_length = 0; - + // ------ + // dpte + // ------ if (surf_linear) { - log2_vmpg_height = 0; /* one line high */ + log2_vmpg_height = 0; // one line high } else { log2_vmpg_height = (log2_vmpg_bytes - 8) / 2 + log2_blk256_height; } log2_vmpg_width = log2_vmpg_bytes - log2_bytes_per_element - log2_vmpg_height; - /* only 3 possible shapes for dpte request in dimensions of ptes: 8x1, 4x2, 2x4. */ - if (log2_blk_bytes <= log2_vmpg_bytes) + // only 3 possible shapes for dpte request in dimensions of ptes: 8x1, 4x2, 2x4. + if (surf_linear) { //one 64B PTE request returns 8 PTEs log2_dpte_req_height_ptes = 0; - else if (log2_blk_height - log2_vmpg_height >= 2) - log2_dpte_req_height_ptes = 2; - else - log2_dpte_req_height_ptes = log2_blk_height - log2_vmpg_height; - log2_dpte_req_width_ptes = 3 - log2_dpte_req_height_ptes; - - /* Ensure we only have the 3 shapes */ - ASSERT((log2_dpte_req_width_ptes == 3 && log2_dpte_req_height_ptes == 0) || /* 8x1 */ - (log2_dpte_req_width_ptes == 2 && log2_dpte_req_height_ptes == 1) || /* 4x2 */ - (log2_dpte_req_width_ptes == 1 && log2_dpte_req_height_ptes == 2)); /* 2x4 */ - - /* The dpte request dimensions in data elements is dpte_req_width x dpte_req_height - * log2_vmpg_width is how much 1 pte represent, now calculating how much a 64b pte req represent - * That depends on the pte shape (i.e. 8x1, 4x2, 2x4) - */ - log2_dpte_req_height = log2_vmpg_height + log2_dpte_req_height_ptes; - log2_dpte_req_width = log2_vmpg_width + log2_dpte_req_width_ptes; + log2_dpte_req_width = log2_vmpg_width + 3; + log2_dpte_req_height = 0; + } else if (log2_blk_bytes == 12) { //4KB tile means 4kB page size + //one 64B req gives 8x1 PTEs for 4KB tile + log2_dpte_req_height_ptes = 0; + log2_dpte_req_width = log2_blk_width + 3; + log2_dpte_req_height = log2_blk_height + 0; + } else if ((log2_blk_bytes >= 16) && (log2_vmpg_bytes == 12)) { // tile block >= 64KB + //two 64B reqs of 2x4 PTEs give 16 PTEs to cover 64KB + log2_dpte_req_height_ptes = 4; + log2_dpte_req_width = log2_blk256_width + 4; // log2_64KB_width + log2_dpte_req_height = log2_blk256_height + 4; // log2_64KB_height + } else { //64KB page size and must 64KB tile block + //one 64B req gives 8x1 PTEs for 64KB tile + log2_dpte_req_height_ptes = 0; + log2_dpte_req_width = log2_blk_width + 3; + log2_dpte_req_height = log2_blk_height + 0; + } + + // The dpte request dimensions in data elements is dpte_req_width x dpte_req_height + // log2_vmpg_width is how much 1 pte represent, now calculating how much a 64b pte req represent + // That depends on the pte shape (i.e. 8x1, 4x2, 2x4) + //log2_dpte_req_height = log2_vmpg_height + log2_dpte_req_height_ptes; + //log2_dpte_req_width = log2_vmpg_width + log2_dpte_req_width_ptes; dpte_req_height = 1 << log2_dpte_req_height; dpte_req_width = 1 << log2_dpte_req_width; - /* calculate pitch dpte row buffer can hold - * round the result down to a power of two. - */ + // calculate pitch dpte row buffer can hold + // round the result down to a power of two. + pde_buf_entries = yuv420 ? (pde_proc_buffer_size_64k_reqs >> 1) : pde_proc_buffer_size_64k_reqs; if (surf_linear) { - log2_dpte_row_height_linear = dml_floor( - dml_log2(dpte_buf_in_pte_reqs * dpte_req_width / data_pitch)); + unsigned int dpte_row_height; + + log2_dpte_row_height_linear = dml_floor(dml_log2(dml_min(64 * 1024 * pde_buf_entries + / bytes_per_element, + dpte_buf_in_pte_reqs + * dpte_req_width) + / data_pitch), + 1); ASSERT(log2_dpte_row_height_linear >= 3); @@ -826,18 +565,16 @@ static void get_surf_rq_param( log2_dpte_row_height_linear = 7; log2_dpte_row_height = log2_dpte_row_height_linear; - rq_dlg_param->dpte_row_height = 1 << log2_dpte_row_height; - - /* For linear, the dpte row is pitch dependent and the pte requests wrap at the pitch boundary. - * the dpte_row_width_ub is the upper bound of data_pitch*dpte_row_height in elements with this unique buffering. - */ - dpte_row_width_ub = dml_round_to_multiple( - data_pitch * dpte_row_height - 1, + // For linear, the dpte row is pitch dependent and the pte requests wrap at the pitch boundary. + // the dpte_row_width_ub is the upper bound of data_pitch*dpte_row_height in elements with this unique buffering. + dpte_row_height = 1 << log2_dpte_row_height; + dpte_row_width_ub = dml_round_to_multiple(data_pitch * dpte_row_height - 1, dpte_req_width, 1) + dpte_req_width; rq_dlg_param->dpte_req_per_row_ub = dpte_row_width_ub / dpte_req_width; } else { - /* for tiled mode, row height is the same as req height and row store up to vp size upper bound */ + // the upper bound of the dpte_row_width without dependency on viewport position follows. + // for tiled mode, row height is the same as req height and row store up to vp size upper bound if (!surf_vert) { log2_dpte_row_height = log2_dpte_req_height; dpte_row_width_ub = dml_round_to_multiple(vp_width - 1, dpte_req_width, 1) @@ -851,103 +588,117 @@ static void get_surf_rq_param( + dpte_req_height; rq_dlg_param->dpte_req_per_row_ub = dpte_row_width_ub / dpte_req_height; } - rq_dlg_param->dpte_row_height = 1 << log2_dpte_row_height; - } - rq_dlg_param->dpte_bytes_per_row_ub = rq_dlg_param->dpte_req_per_row_ub * 64; - - /* From programming guide: - * There is a special case of saving only half of ptes returned due to buffer space limits. - * this case applies to 4 and 8bpe in horizontal access of a vp_width greater than 2560+16 - * when the pte request is 2x4 ptes (which happens when vmpg_bytes =4kb and tile blk_bytes >=64kb). - */ - if (!surf_vert && vp_width > (2560 + 16) && bytes_per_element >= 4 && log2_vmpg_bytes == 12 - && log2_blk_bytes >= 16) { - log2_dpte_row_height = log2_dpte_row_height - 1; /*half of the full height */ - rq_dlg_param->dpte_row_height = 1 << log2_dpte_row_height; } + if (log2_blk_bytes >= 16 && log2_vmpg_bytes == 12) // tile block >= 64KB + rq_dlg_param->dpte_bytes_per_row_ub = rq_dlg_param->dpte_req_per_row_ub * 128; //2*64B dpte request + else + rq_dlg_param->dpte_bytes_per_row_ub = rq_dlg_param->dpte_req_per_row_ub * 64; //64B dpte request - /* the dpte_group_bytes is reduced for the specific case of vertical - * access of a tile surface that has dpte request of 8x1 ptes. - */ - if (!surf_linear & (log2_dpte_req_height_ptes == 0) & surf_vert) /*reduced, in this case, will have page fault within a group */ + rq_dlg_param->dpte_row_height = 1 << log2_dpte_row_height; + + // the dpte_group_bytes is reduced for the specific case of vertical + // access of a tile surface that has dpte request of 8x1 ptes. + if (!surf_linear & (log2_dpte_req_height_ptes == 0) & surf_vert) //reduced, in this case, will have page fault within a group rq_sizing_param->dpte_group_bytes = 512; else - /*full size */ + //full size rq_sizing_param->dpte_group_bytes = 2048; - /*since pte request size is 64byte, the number of data pte requests per full sized group is as follows. */ + //since pte request size is 64byte, the number of data pte requests per full sized group is as follows. log2_dpte_group_bytes = dml_log2(rq_sizing_param->dpte_group_bytes); - log2_dpte_group_length = log2_dpte_group_bytes - 6; /*length in 64b requests */ + log2_dpte_group_length = log2_dpte_group_bytes - 6; //length in 64b requests - /* full sized data pte group width in elements */ + // full sized data pte group width in elements if (!surf_vert) log2_dpte_group_width = log2_dpte_group_length + log2_dpte_req_width; else log2_dpte_group_width = log2_dpte_group_length + log2_dpte_req_height; + //But if the tile block >=64KB and the page size is 4KB, then each dPTE request is 2*64B + if ((log2_blk_bytes >= 16) && (log2_vmpg_bytes == 12)) // tile block >= 64KB + log2_dpte_group_width = log2_dpte_group_width - 1; + dpte_group_width = 1 << log2_dpte_group_width; - /* since dpte groups are only aligned to dpte_req_width and not dpte_group_width, - * the upper bound for the dpte groups per row is as follows. - */ - rq_dlg_param->dpte_groups_per_row_ub = dml_ceil( - (double) dpte_row_width_ub / dpte_group_width); + // since dpte groups are only aligned to dpte_req_width and not dpte_group_width, + // the upper bound for the dpte groups per row is as follows. + rq_dlg_param->dpte_groups_per_row_ub = dml_ceil((double) dpte_row_width_ub / dpte_group_width, + 1); +} + +static void get_surf_rq_param(struct display_mode_lib *mode_lib, + display_data_rq_sizing_params_st *rq_sizing_param, + display_data_rq_dlg_params_st *rq_dlg_param, + display_data_rq_misc_params_st *rq_misc_param, + const display_pipe_source_params_st pipe_src_param, + bool is_chroma) +{ + bool mode_422 = 0; + unsigned int vp_width = 0; + unsigned int vp_height = 0; + unsigned int data_pitch = 0; + unsigned int meta_pitch = 0; + unsigned int ppe = mode_422 ? 2 : 1; + + // FIXME check if ppe apply for both luma and chroma in 422 case + if (is_chroma) { + vp_width = pipe_src_param.viewport_width_c / ppe; + vp_height = pipe_src_param.viewport_height_c; + data_pitch = pipe_src_param.data_pitch_c; + meta_pitch = pipe_src_param.meta_pitch_c; + } else { + vp_width = pipe_src_param.viewport_width / ppe; + vp_height = pipe_src_param.viewport_height; + data_pitch = pipe_src_param.data_pitch; + meta_pitch = pipe_src_param.meta_pitch; + } + + rq_sizing_param->chunk_bytes = 8192; + + if (rq_sizing_param->chunk_bytes == 64 * 1024) + rq_sizing_param->min_chunk_bytes = 0; + else + rq_sizing_param->min_chunk_bytes = 1024; + + rq_sizing_param->meta_chunk_bytes = 2048; + rq_sizing_param->min_meta_chunk_bytes = 256; + + rq_sizing_param->mpte_group_bytes = 2048; - dml_rq_dlg_get_row_heights( - mode_lib, - &func_dpte_row_height, - &func_meta_row_height, + get_meta_and_pte_attr(mode_lib, + rq_dlg_param, + rq_misc_param, + rq_sizing_param, vp_width, + vp_height, data_pitch, + meta_pitch, pipe_src_param.source_format, pipe_src_param.sw_mode, pipe_src_param.macro_tile_size, pipe_src_param.source_scan, is_chroma); - - /* Just a check to make sure this function and the new one give the same - * result. The standalone get_row_heights() function is based off of the - * code in this function so the same changes need to be made to both. - */ - if (rq_dlg_param->meta_row_height != func_meta_row_height) { - DTRACE( - "MISMATCH: rq_dlg_param->meta_row_height = %d", - rq_dlg_param->meta_row_height); - DTRACE("MISMATCH: func_meta_row_height = %d", func_meta_row_height); - ASSERT(0); - } - - if (rq_dlg_param->dpte_row_height != func_dpte_row_height) { - DTRACE( - "MISMATCH: rq_dlg_param->dpte_row_height = %d", - rq_dlg_param->dpte_row_height); - DTRACE("MISMATCH: func_dpte_row_height = %d", func_dpte_row_height); - ASSERT(0); - } } -void dml_rq_dlg_get_rq_params( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_rq_params_st *rq_param, - const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param) +void dml_rq_dlg_get_rq_params(struct display_mode_lib *mode_lib, + display_rq_params_st *rq_param, + const display_pipe_source_params_st pipe_src_param) { - /* get param for luma surface */ + // get param for luma surface rq_param->yuv420 = pipe_src_param.source_format == dm_420_8 || pipe_src_param.source_format == dm_420_10; rq_param->yuv420_10bpc = pipe_src_param.source_format == dm_420_10; - get_surf_rq_param( - mode_lib, + get_surf_rq_param(mode_lib, &(rq_param->sizing.rq_l), &(rq_param->dlg.rq_l), &(rq_param->misc.rq_l), pipe_src_param, 0); - if (is_dual_plane((enum source_format_class) pipe_src_param.source_format)) { - /* get param for chroma surface */ - get_surf_rq_param( - mode_lib, + if (is_dual_plane((enum source_format_class)(pipe_src_param.source_format))) { + // get param for chroma surface + get_surf_rq_param(mode_lib, &(rq_param->sizing.rq_c), &(rq_param->dlg.rq_c), &(rq_param->misc.rq_c), @@ -955,355 +706,126 @@ void dml_rq_dlg_get_rq_params( 1); } - /* calculate how to split the det buffer space between luma and chroma */ + // calculate how to split the det buffer space between luma and chroma handle_det_buf_split(mode_lib, rq_param, pipe_src_param); print__rq_params_st(mode_lib, *rq_param); } -void dml_rq_dlg_get_rq_reg( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_rq_regs_st *rq_regs, - const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param) +void dml_rq_dlg_get_rq_reg(struct display_mode_lib *mode_lib, + display_rq_regs_st *rq_regs, + const display_pipe_source_params_st pipe_src_param) { - struct _vcs_dpi_display_rq_params_st rq_param = {0}; + display_rq_params_st rq_param = {0}; memset(rq_regs, 0, sizeof(*rq_regs)); - dml_rq_dlg_get_rq_params(mode_lib, &rq_param, pipe_src_param); extract_rq_regs(mode_lib, rq_regs, rq_param); print__rq_regs_st(mode_lib, *rq_regs); } -/* TODO: Need refactor, so this is used by dml_rq_dlg_get_dlg_params as well - * The problem is that there are some intermediate terms that would need by - * some dlg calculation (i.e. rest of prefetch and active prog guide calculation) - */ -void dml_rq_dlg_get_dlg_params_prefetch( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_dlg_prefetch_param_st *prefetch_param, - struct _vcs_dpi_display_rq_dlg_params_st rq_dlg_param, - struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param, - struct _vcs_dpi_display_e2e_pipe_params_st e2e_pipe_param, +// Note: currently taken in as is. +// Nice to decouple code from hw register implement and extract code that are repeated for luma and chroma. +void dml_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *e2e_pipe_param, + const unsigned int num_pipes, + const unsigned int pipe_idx, + display_dlg_regs_st *disp_dlg_regs, + display_ttu_regs_st *disp_ttu_regs, + const display_rq_dlg_params_st rq_dlg_param, + const display_dlg_sys_params_st dlg_sys_param, const bool cstate_en, const bool pstate_en, - const bool vm_en) + const bool vm_en, + const bool ignore_viewport_pos, + const bool immediate_flip_support) { - /* Prefetch */ - unsigned int htotal = e2e_pipe_param.pipe.dest.htotal; - bool interlaced = e2e_pipe_param.pipe.dest.interlaced; + const display_pipe_source_params_st *src = &e2e_pipe_param[pipe_idx].pipe.src; + const display_pipe_dest_params_st *dst = &e2e_pipe_param[pipe_idx].pipe.dest; + const display_output_params_st *dout = &e2e_pipe_param[pipe_idx].dout; + const display_clocks_and_cfg_st *clks = &e2e_pipe_param[pipe_idx].clks_cfg; + const scaler_ratio_depth_st *scl = &e2e_pipe_param[pipe_idx].pipe.scale_ratio_depth; + const scaler_taps_st *taps = &e2e_pipe_param[pipe_idx].pipe.scale_taps; + + // ------------------------- + // Section 1.15.2.1: OTG dependent Params + // ------------------------- + // Timing + unsigned int htotal = dst->htotal; +// unsigned int hblank_start = dst.hblank_start; // TODO: Remove + unsigned int hblank_end = dst->hblank_end; + unsigned int vblank_start = dst->vblank_start; + unsigned int vblank_end = dst->vblank_end; unsigned int min_vblank = mode_lib->ip.min_vblank_lines; - const double prefetch_xy_calc_in_dcfclk = 24.0; /* FIXME: ip_param */ - double min_dcfclk_mhz = dlg_sys_param.deepsleep_dcfclk_mhz; - double t_calc_us = prefetch_xy_calc_in_dcfclk / min_dcfclk_mhz; - - bool dcc_en = e2e_pipe_param.pipe.src.dcc; - bool dual_plane = is_dual_plane( - (enum source_format_class) e2e_pipe_param.pipe.src.source_format); - unsigned int bytes_per_element_l = get_bytes_per_element( - (enum source_format_class) e2e_pipe_param.pipe.src.source_format, - 0); - unsigned int bytes_per_element_c = get_bytes_per_element( - (enum source_format_class) e2e_pipe_param.pipe.src.source_format, - 1); - - double pclk_freq_in_mhz = e2e_pipe_param.pipe.dest.pixel_rate_mhz; - double dppclk_freq_in_mhz = e2e_pipe_param.clks_cfg.dppclk_mhz; - double dispclk_freq_in_mhz = e2e_pipe_param.clks_cfg.dispclk_mhz; - - double line_time_in_us = (htotal / pclk_freq_in_mhz); - double vinit_l = e2e_pipe_param.pipe.scale_ratio_depth.vinit; - double vinit_c = e2e_pipe_param.pipe.scale_ratio_depth.vinit_c; - double vinit_bot_l = e2e_pipe_param.pipe.scale_ratio_depth.vinit_bot; - double vinit_bot_c = e2e_pipe_param.pipe.scale_ratio_depth.vinit_bot_c; - - unsigned int swath_height_l = rq_dlg_param.rq_l.swath_height; - unsigned int swath_width_ub_l = rq_dlg_param.rq_l.swath_width_ub; - unsigned int dpte_bytes_per_row_ub_l = rq_dlg_param.rq_l.dpte_bytes_per_row_ub; - unsigned int meta_pte_bytes_per_frame_ub_l = rq_dlg_param.rq_l.meta_pte_bytes_per_frame_ub; - unsigned int meta_bytes_per_row_ub_l = rq_dlg_param.rq_l.meta_bytes_per_row_ub; - - unsigned int swath_height_c = rq_dlg_param.rq_c.swath_height; - unsigned int swath_width_ub_c = rq_dlg_param.rq_c.swath_width_ub; - unsigned int dpte_bytes_per_row_ub_c = rq_dlg_param.rq_c.dpte_bytes_per_row_ub; - unsigned int vupdate_offset = e2e_pipe_param.pipe.dest.vupdate_offset; - unsigned int vupdate_width = e2e_pipe_param.pipe.dest.vupdate_width; - unsigned int vready_offset = e2e_pipe_param.pipe.dest.vready_offset; - - const unsigned int dppclk_delay_subtotal = mode_lib->ip.dppclk_delay_subtotal; - const unsigned int dispclk_delay_subtotal = mode_lib->ip.dispclk_delay_subtotal; - unsigned int pixel_rate_delay_subtotal = dppclk_delay_subtotal * pclk_freq_in_mhz - / dppclk_freq_in_mhz - + dispclk_delay_subtotal * pclk_freq_in_mhz / dispclk_freq_in_mhz; - unsigned int dst_y_after_scaler = 0; - unsigned int dst_x_after_scaler = 0; - unsigned int vstartup_start = e2e_pipe_param.pipe.dest.vstartup_start; + double dppclk_freq_in_mhz = clks->dppclk_mhz; + double dispclk_freq_in_mhz = clks->dispclk_mhz; + double refclk_freq_in_mhz = clks->refclk_mhz; + double pclk_freq_in_mhz = dst->pixel_rate_mhz; + bool interlaced = dst->interlaced; - double line_wait; - double line_o; - double line_setup; - double line_calc; - double dst_y_prefetch; - double t_pre_us; - int unsigned vm_bytes; - int unsigned meta_row_bytes; - int unsigned max_num_sw_l; - int unsigned max_num_sw_c; - int unsigned max_partial_sw_l; - int unsigned max_partial_sw_c; - - double max_vinit_l; - double max_vinit_c; - int unsigned lsw_l; - int unsigned lsw_c; - int unsigned sw_bytes_ub_l; - int unsigned sw_bytes_ub_c; - int unsigned sw_bytes; - int unsigned dpte_row_bytes; + double ref_freq_to_pix_freq = refclk_freq_in_mhz / pclk_freq_in_mhz; - if (interlaced) - vstartup_start = vstartup_start / 2; + double min_dcfclk_mhz; + double t_calc_us; + double min_ttu_vblank; - if (vstartup_start >= min_vblank) { - min_vblank = vstartup_start + 1; - DTRACE( - "WARNING_DLG: %s: vstartup_start=%d should be less than min_vblank=%d", - __func__, - vstartup_start, - min_vblank); - } + double min_dst_y_ttu_vblank; + unsigned int dlg_vblank_start; + bool dual_plane; + bool mode_422; + unsigned int access_dir; + unsigned int vp_height_l; + unsigned int vp_width_l; + unsigned int vp_height_c; + unsigned int vp_width_c; - if (e2e_pipe_param.pipe.src.is_hsplit) - dst_x_after_scaler = pixel_rate_delay_subtotal - + e2e_pipe_param.pipe.dest.recout_width; - else - dst_x_after_scaler = pixel_rate_delay_subtotal; + // Scaling + unsigned int htaps_l; + unsigned int htaps_c; + double hratio_l; + double hratio_c; + double vratio_l; + double vratio_c; + bool scl_enable; - if (e2e_pipe_param.dout.output_format == dm_420) - dst_y_after_scaler = 1; - else - dst_y_after_scaler = 0; + double line_time_in_us; + // double vinit_l; + // double vinit_c; + // double vinit_bot_l; + // double vinit_bot_c; - if (dst_x_after_scaler >= htotal) { - dst_x_after_scaler = dst_x_after_scaler - htotal; - dst_y_after_scaler = dst_y_after_scaler + 1; - } - - DTRACE("DLG: %s: htotal = %d", __func__, htotal); - DTRACE( - "DLG: %s: pixel_rate_delay_subtotal = %d", - __func__, - pixel_rate_delay_subtotal); - DTRACE("DLG: %s: dst_x_after_scaler = %d", __func__, dst_x_after_scaler); - DTRACE("DLG: %s: dst_y_after_scaler = %d", __func__, dst_y_after_scaler); - - line_wait = mode_lib->soc.urgent_latency_us; - if (cstate_en) - line_wait = dml_max(mode_lib->soc.sr_enter_plus_exit_time_us, line_wait); - if (pstate_en) - line_wait = dml_max( - mode_lib->soc.dram_clock_change_latency_us - + mode_lib->soc.urgent_latency_us, - line_wait); - line_wait = line_wait / line_time_in_us; - - line_o = (double) dst_y_after_scaler + dst_x_after_scaler / (double) htotal; - line_setup = (double) (vupdate_offset + vupdate_width + vready_offset) / (double) htotal; - line_calc = t_calc_us / line_time_in_us; - - DTRACE( - "DLG: %s: soc.sr_enter_plus_exit_time_us = %3.2f", - __func__, - (double) mode_lib->soc.sr_enter_plus_exit_time_us); - DTRACE( - "DLG: %s: soc.dram_clock_change_latency_us = %3.2f", - __func__, - (double) mode_lib->soc.dram_clock_change_latency_us); - - DTRACE("DLG: %s: urgent_latency_us = %3.2f", __func__, mode_lib->soc.urgent_latency_us); - DTRACE( - "DLG: %s: t_srx_delay_us = %3.2f", - __func__, - (double) dlg_sys_param.t_srx_delay_us); - DTRACE("DLG: %s: line_time_in_us = %3.2f", __func__, (double) line_time_in_us); - DTRACE("DLG: %s: vupdate_offset = %d", __func__, vupdate_offset); - DTRACE("DLG: %s: vupdate_width = %d", __func__, vupdate_width); - DTRACE("DLG: %s: vready_offset = %d", __func__, vready_offset); - DTRACE("DLG: %s: line_wait = %3.2f", __func__, line_wait); - DTRACE("DLG: %s: line_o = %3.2f", __func__, line_o); - DTRACE("DLG: %s: line_setup = %3.2f", __func__, line_setup); - DTRACE("DLG: %s: line_calc = %3.2f", __func__, line_calc); - - dst_y_prefetch = ((double) min_vblank - 1.0) - - (line_setup + line_calc + line_wait + line_o); - DTRACE("DLG: %s: dst_y_prefetch (before rnd) = %3.2f", __func__, dst_y_prefetch); - ASSERT(dst_y_prefetch >= 2.0); - - dst_y_prefetch = dml_floor(4.0 * (dst_y_prefetch + 0.125)) / 4; - DTRACE("DLG: %s: dst_y_prefetch (after rnd) = %3.2f", __func__, dst_y_prefetch); - - t_pre_us = dst_y_prefetch * line_time_in_us; - vm_bytes = 0; - meta_row_bytes = 0; - - if (dcc_en && vm_en) - vm_bytes = meta_pte_bytes_per_frame_ub_l; - if (dcc_en) - meta_row_bytes = meta_bytes_per_row_ub_l; - - max_num_sw_l = 0; - max_num_sw_c = 0; - max_partial_sw_l = 0; - max_partial_sw_c = 0; - - max_vinit_l = interlaced ? dml_max(vinit_l, vinit_bot_l) : vinit_l; - max_vinit_c = interlaced ? dml_max(vinit_c, vinit_bot_c) : vinit_c; - - get_swath_need(mode_lib, &max_num_sw_l, &max_partial_sw_l, swath_height_l, max_vinit_l); - if (dual_plane) - get_swath_need( - mode_lib, - &max_num_sw_c, - &max_partial_sw_c, - swath_height_c, - max_vinit_c); - - lsw_l = max_num_sw_l * swath_height_l + max_partial_sw_l; - lsw_c = max_num_sw_c * swath_height_c + max_partial_sw_c; - sw_bytes_ub_l = lsw_l * swath_width_ub_l * bytes_per_element_l; - sw_bytes_ub_c = lsw_c * swath_width_ub_c * bytes_per_element_c; - sw_bytes = 0; - dpte_row_bytes = 0; - - if (vm_en) { - if (dual_plane) - dpte_row_bytes = dpte_bytes_per_row_ub_l + dpte_bytes_per_row_ub_c; - else - dpte_row_bytes = dpte_bytes_per_row_ub_l; - } else { - dpte_row_bytes = 0; - } - - if (dual_plane) - sw_bytes = sw_bytes_ub_l + sw_bytes_ub_c; - else - sw_bytes = sw_bytes_ub_l; - - DTRACE("DLG: %s: sw_bytes_ub_l = %d", __func__, sw_bytes_ub_l); - DTRACE("DLG: %s: sw_bytes_ub_c = %d", __func__, sw_bytes_ub_c); - DTRACE("DLG: %s: sw_bytes = %d", __func__, sw_bytes); - DTRACE("DLG: %s: vm_bytes = %d", __func__, vm_bytes); - DTRACE("DLG: %s: meta_row_bytes = %d", __func__, meta_row_bytes); - DTRACE("DLG: %s: dpte_row_bytes = %d", __func__, dpte_row_bytes); - - prefetch_param->prefetch_bw = - (vm_bytes + 2 * dpte_row_bytes + 2 * meta_row_bytes + sw_bytes) / t_pre_us; - prefetch_param->flip_bytes = (vm_bytes + dpte_row_bytes + meta_row_bytes); -} - -/* Note: currently taken in as is. - * Nice to decouple code from hw register implement and extract code that are repeated for luma and chroma. - */ -void dml_rq_dlg_get_dlg_params( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_dlg_regs_st *disp_dlg_regs, - struct _vcs_dpi_display_ttu_regs_st *disp_ttu_regs, - const struct _vcs_dpi_display_rq_dlg_params_st rq_dlg_param, - const struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param, - const struct _vcs_dpi_display_e2e_pipe_params_st e2e_pipe_param, - const bool cstate_en, - const bool pstate_en, - const bool vm_en, - const bool iflip_en) -{ - /* Timing */ - unsigned int htotal = e2e_pipe_param.pipe.dest.htotal; - unsigned int hblank_end = e2e_pipe_param.pipe.dest.hblank_end; - unsigned int vblank_start = e2e_pipe_param.pipe.dest.vblank_start; - unsigned int vblank_end = e2e_pipe_param.pipe.dest.vblank_end; - bool interlaced = e2e_pipe_param.pipe.dest.interlaced; - unsigned int min_vblank = mode_lib->ip.min_vblank_lines; - - double pclk_freq_in_mhz = e2e_pipe_param.pipe.dest.pixel_rate_mhz; - double refclk_freq_in_mhz = e2e_pipe_param.clks_cfg.refclk_mhz; - double dppclk_freq_in_mhz = e2e_pipe_param.clks_cfg.dppclk_mhz; - double dispclk_freq_in_mhz = e2e_pipe_param.clks_cfg.dispclk_mhz; - - double ref_freq_to_pix_freq; - double prefetch_xy_calc_in_dcfclk; - double min_dcfclk_mhz; - double t_calc_us; - double min_ttu_vblank; - double min_dst_y_ttu_vblank; - int unsigned dlg_vblank_start; - bool dcc_en; - bool dual_plane; - bool mode_422; - unsigned int access_dir; - unsigned int bytes_per_element_l; - unsigned int bytes_per_element_c; - unsigned int vp_height_l; - unsigned int vp_width_l; - unsigned int vp_height_c; - unsigned int vp_width_c; - unsigned int htaps_l; - unsigned int htaps_c; - double hratios_l; - double hratios_c; - double vratio_l; - double vratio_c; - double line_time_in_us; - double vinit_l; - double vinit_c; - double vinit_bot_l; - double vinit_bot_c; - unsigned int swath_height_l; + // unsigned int swath_height_l; unsigned int swath_width_ub_l; - unsigned int dpte_bytes_per_row_ub_l; + // unsigned int dpte_bytes_per_row_ub_l; unsigned int dpte_groups_per_row_ub_l; - unsigned int meta_pte_bytes_per_frame_ub_l; - unsigned int meta_bytes_per_row_ub_l; - unsigned int swath_height_c; + // unsigned int meta_pte_bytes_per_frame_ub_l; + // unsigned int meta_bytes_per_row_ub_l; + + // unsigned int swath_height_c; unsigned int swath_width_ub_c; - unsigned int dpte_bytes_per_row_ub_c; + // unsigned int dpte_bytes_per_row_ub_c; unsigned int dpte_groups_per_row_ub_c; + unsigned int meta_chunks_per_row_ub_l; + unsigned int meta_chunks_per_row_ub_c; unsigned int vupdate_offset; unsigned int vupdate_width; unsigned int vready_offset; + unsigned int dppclk_delay_subtotal; unsigned int dispclk_delay_subtotal; unsigned int pixel_rate_delay_subtotal; + unsigned int vstartup_start; unsigned int dst_x_after_scaler; unsigned int dst_y_after_scaler; double line_wait; - double line_o; - double line_setup; - double line_calc; double dst_y_prefetch; - double t_pre_us; - int unsigned vm_bytes; - int unsigned meta_row_bytes; - int unsigned max_num_sw_l; - int unsigned max_num_sw_c; - int unsigned max_partial_sw_l; - int unsigned max_partial_sw_c; - double max_vinit_l; - double max_vinit_c; - int unsigned lsw_l; - int unsigned lsw_c; - int unsigned sw_bytes_ub_l; - int unsigned sw_bytes_ub_c; - int unsigned sw_bytes; - int unsigned dpte_row_bytes; - double prefetch_bw; - double flip_bw; - double t_vm_us; - double t_r0_us; double dst_y_per_vm_vblank; double dst_y_per_row_vblank; + double dst_y_per_vm_flip; + double dst_y_per_row_flip; double min_dst_y_per_vm_vblank; double min_dst_y_per_row_vblank; double lsw; @@ -1312,6 +834,7 @@ void dml_rq_dlg_get_dlg_params( unsigned int req_per_swath_ub_l; unsigned int req_per_swath_ub_c; unsigned int meta_row_height_l; + unsigned int meta_row_height_c; unsigned int swath_width_pixels_ub_l; unsigned int swath_width_pixels_ub_c; unsigned int scaler_rec_in_width_l; @@ -1326,59 +849,52 @@ void dml_rq_dlg_get_dlg_params( double refcyc_per_line_delivery_pre_c; double refcyc_per_line_delivery_l; double refcyc_per_line_delivery_c; + double refcyc_per_req_delivery_pre_l; double refcyc_per_req_delivery_pre_c; double refcyc_per_req_delivery_l; double refcyc_per_req_delivery_c; + + unsigned int full_recout_width; + double xfc_transfer_delay; + double xfc_precharge_delay; + double xfc_remote_surface_flip_latency; + double xfc_dst_y_delta_drq_limit; + double xfc_prefetch_margin; double refcyc_per_req_delivery_pre_cur0; double refcyc_per_req_delivery_cur0; - int unsigned full_recout_width; - double hratios_cur0; - unsigned int cur0_src_width; - enum cursor_bpp cur0_bpp; - unsigned int cur0_req_size; - unsigned int cur0_req_width; - double cur0_width_ub; - double cur0_req_per_width; - double hactive_cur0; + double refcyc_per_req_delivery_pre_cur1; + double refcyc_per_req_delivery_cur1; memset(disp_dlg_regs, 0, sizeof(*disp_dlg_regs)); memset(disp_ttu_regs, 0, sizeof(*disp_ttu_regs)); - DTRACE("DLG: %s: cstate_en = %d", __func__, cstate_en); - DTRACE("DLG: %s: pstate_en = %d", __func__, pstate_en); - DTRACE("DLG: %s: vm_en = %d", __func__, vm_en); - DTRACE("DLG: %s: iflip_en = %d", __func__, iflip_en); - - /* ------------------------- */ - /* Section 1.5.2.1: OTG dependent Params */ - /* ------------------------- */ - DTRACE("DLG: %s: dppclk_freq_in_mhz = %3.2f", __func__, dppclk_freq_in_mhz); - DTRACE("DLG: %s: dispclk_freq_in_mhz = %3.2f", __func__, dispclk_freq_in_mhz); - DTRACE("DLG: %s: refclk_freq_in_mhz = %3.2f", __func__, refclk_freq_in_mhz); - DTRACE("DLG: %s: pclk_freq_in_mhz = %3.2f", __func__, pclk_freq_in_mhz); - DTRACE("DLG: %s: interlaced = %d", __func__, interlaced); - - ref_freq_to_pix_freq = refclk_freq_in_mhz / pclk_freq_in_mhz; + dml_print("DML_DLG: %s: cstate_en = %d\n", __func__, cstate_en); + dml_print("DML_DLG: %s: pstate_en = %d\n", __func__, pstate_en); + dml_print("DML_DLG: %s: vm_en = %d\n", __func__, vm_en); + dml_print("DML_DLG: %s: ignore_viewport_pos = %d\n", __func__, ignore_viewport_pos); + dml_print("DML_DLG: %s: immediate_flip_support = %d\n", __func__, immediate_flip_support); + + dml_print("DML_DLG: %s: dppclk_freq_in_mhz = %3.2f\n", __func__, dppclk_freq_in_mhz); + dml_print("DML_DLG: %s: dispclk_freq_in_mhz = %3.2f\n", __func__, dispclk_freq_in_mhz); + dml_print("DML_DLG: %s: refclk_freq_in_mhz = %3.2f\n", __func__, refclk_freq_in_mhz); + dml_print("DML_DLG: %s: pclk_freq_in_mhz = %3.2f\n", __func__, pclk_freq_in_mhz); + dml_print("DML_DLG: %s: interlaced = %d\n", __func__, interlaced); ASSERT(ref_freq_to_pix_freq < 4.0); + disp_dlg_regs->ref_freq_to_pix_freq = (unsigned int) (ref_freq_to_pix_freq * dml_pow(2, 19)); disp_dlg_regs->refcyc_per_htotal = (unsigned int) (ref_freq_to_pix_freq * (double) htotal * dml_pow(2, 8)); + disp_dlg_regs->dlg_vblank_end = interlaced ? (vblank_end / 2) : vblank_end; // 15 bits disp_dlg_regs->refcyc_h_blank_end = (unsigned int) ((double) hblank_end * (double) ref_freq_to_pix_freq); ASSERT(disp_dlg_regs->refcyc_h_blank_end < (unsigned int) dml_pow(2, 13)); - disp_dlg_regs->dlg_vblank_end = interlaced ? (vblank_end / 2) : vblank_end; /* 15 bits */ - prefetch_xy_calc_in_dcfclk = 24.0; /* FIXME: ip_param */ min_dcfclk_mhz = dlg_sys_param.deepsleep_dcfclk_mhz; - t_calc_us = prefetch_xy_calc_in_dcfclk / min_dcfclk_mhz; - min_ttu_vblank = dlg_sys_param.t_urg_wm_us; - if (cstate_en) - min_ttu_vblank = dml_max(dlg_sys_param.t_sr_wm_us, min_ttu_vblank); - if (pstate_en) - min_ttu_vblank = dml_max(dlg_sys_param.t_mclk_wm_us, min_ttu_vblank); - min_ttu_vblank = min_ttu_vblank + t_calc_us; + set_prefetch_mode(mode_lib, cstate_en, pstate_en, ignore_viewport_pos, immediate_flip_support); + t_calc_us = get_tcalc(mode_lib, e2e_pipe_param, num_pipes); + min_ttu_vblank = get_min_ttu_vblank(mode_lib, e2e_pipe_param, num_pipes, pipe_idx); min_dst_y_ttu_vblank = min_ttu_vblank * pclk_freq_in_mhz / (double) htotal; dlg_vblank_start = interlaced ? (vblank_start / 2) : vblank_start; @@ -1387,383 +903,202 @@ void dml_rq_dlg_get_dlg_params( + min_dst_y_ttu_vblank) * dml_pow(2, 2)); ASSERT(disp_dlg_regs->min_dst_y_next_start < (unsigned int) dml_pow(2, 18)); - DTRACE("DLG: %s: min_dcfclk_mhz = %3.2f", __func__, min_dcfclk_mhz); - DTRACE("DLG: %s: min_ttu_vblank = %3.2f", __func__, min_ttu_vblank); - DTRACE( - "DLG: %s: min_dst_y_ttu_vblank = %3.2f", + dml_print("DML_DLG: %s: min_dcfclk_mhz = %3.2f\n", + __func__, + min_dcfclk_mhz); + dml_print("DML_DLG: %s: min_ttu_vblank = %3.2f\n", + __func__, + min_ttu_vblank); + dml_print("DML_DLG: %s: min_dst_y_ttu_vblank = %3.2f\n", __func__, min_dst_y_ttu_vblank); - DTRACE("DLG: %s: t_calc_us = %3.2f", __func__, t_calc_us); - DTRACE( - "DLG: %s: disp_dlg_regs->min_dst_y_next_start = 0x%0x", + dml_print("DML_DLG: %s: t_calc_us = %3.2f\n", + __func__, + t_calc_us); + dml_print("DML_DLG: %s: disp_dlg_regs->min_dst_y_next_start = 0x%0x\n", __func__, disp_dlg_regs->min_dst_y_next_start); - DTRACE( - "DLG: %s: ref_freq_to_pix_freq = %3.2f", + dml_print("DML_DLG: %s: ref_freq_to_pix_freq = %3.2f\n", __func__, ref_freq_to_pix_freq); - /* ------------------------- */ - /* Section 1.5.2.2: Prefetch, Active and TTU */ - /* ------------------------- */ - /* Prefetch Calc */ - /* Source */ - dcc_en = e2e_pipe_param.pipe.src.dcc; - dual_plane = is_dual_plane( - (enum source_format_class) e2e_pipe_param.pipe.src.source_format); - mode_422 = 0; /* FIXME */ - access_dir = (e2e_pipe_param.pipe.src.source_scan == dm_vert); /* vp access direction: horizontal or vertical accessed */ - bytes_per_element_l = get_bytes_per_element( - (enum source_format_class) e2e_pipe_param.pipe.src.source_format, - 0); - bytes_per_element_c = get_bytes_per_element( - (enum source_format_class) e2e_pipe_param.pipe.src.source_format, - 1); - vp_height_l = e2e_pipe_param.pipe.src.viewport_height; - vp_width_l = e2e_pipe_param.pipe.src.viewport_width; - vp_height_c = e2e_pipe_param.pipe.src.viewport_height_c; - vp_width_c = e2e_pipe_param.pipe.src.viewport_width_c; - - /* Scaling */ - htaps_l = e2e_pipe_param.pipe.scale_taps.htaps; - htaps_c = e2e_pipe_param.pipe.scale_taps.htaps_c; - hratios_l = e2e_pipe_param.pipe.scale_ratio_depth.hscl_ratio; - hratios_c = e2e_pipe_param.pipe.scale_ratio_depth.hscl_ratio_c; - vratio_l = e2e_pipe_param.pipe.scale_ratio_depth.vscl_ratio; - vratio_c = e2e_pipe_param.pipe.scale_ratio_depth.vscl_ratio_c; + // ------------------------- + // Section 1.15.2.2: Prefetch, Active and TTU + // ------------------------- + // Prefetch Calc + // Source +// dcc_en = src.dcc; + dual_plane = is_dual_plane((enum source_format_class)(src->source_format)); + mode_422 = 0; // FIXME + access_dir = (src->source_scan == dm_vert); // vp access direction: horizontal or vertical accessed +// bytes_per_element_l = get_bytes_per_element(source_format_class(src.source_format), 0); +// bytes_per_element_c = get_bytes_per_element(source_format_class(src.source_format), 1); + vp_height_l = src->viewport_height; + vp_width_l = src->viewport_width; + vp_height_c = src->viewport_height_c; + vp_width_c = src->viewport_width_c; + + // Scaling + htaps_l = taps->htaps; + htaps_c = taps->htaps_c; + hratio_l = scl->hscl_ratio; + hratio_c = scl->hscl_ratio_c; + vratio_l = scl->vscl_ratio; + vratio_c = scl->vscl_ratio_c; + scl_enable = scl->scl_enable; line_time_in_us = (htotal / pclk_freq_in_mhz); - vinit_l = e2e_pipe_param.pipe.scale_ratio_depth.vinit; - vinit_c = e2e_pipe_param.pipe.scale_ratio_depth.vinit_c; - vinit_bot_l = e2e_pipe_param.pipe.scale_ratio_depth.vinit_bot; - vinit_bot_c = e2e_pipe_param.pipe.scale_ratio_depth.vinit_bot_c; +// vinit_l = scl.vinit; +// vinit_c = scl.vinit_c; +// vinit_bot_l = scl.vinit_bot; +// vinit_bot_c = scl.vinit_bot_c; - swath_height_l = rq_dlg_param.rq_l.swath_height; +// unsigned int swath_height_l = rq_dlg_param.rq_l.swath_height; swath_width_ub_l = rq_dlg_param.rq_l.swath_width_ub; - dpte_bytes_per_row_ub_l = rq_dlg_param.rq_l.dpte_bytes_per_row_ub; +// unsigned int dpte_bytes_per_row_ub_l = rq_dlg_param.rq_l.dpte_bytes_per_row_ub; dpte_groups_per_row_ub_l = rq_dlg_param.rq_l.dpte_groups_per_row_ub; - meta_pte_bytes_per_frame_ub_l = rq_dlg_param.rq_l.meta_pte_bytes_per_frame_ub; - meta_bytes_per_row_ub_l = rq_dlg_param.rq_l.meta_bytes_per_row_ub; +// unsigned int meta_pte_bytes_per_frame_ub_l = rq_dlg_param.rq_l.meta_pte_bytes_per_frame_ub; +// unsigned int meta_bytes_per_row_ub_l = rq_dlg_param.rq_l.meta_bytes_per_row_ub; - swath_height_c = rq_dlg_param.rq_c.swath_height; +// unsigned int swath_height_c = rq_dlg_param.rq_c.swath_height; swath_width_ub_c = rq_dlg_param.rq_c.swath_width_ub; - dpte_bytes_per_row_ub_c = rq_dlg_param.rq_c.dpte_bytes_per_row_ub; + // dpte_bytes_per_row_ub_c = rq_dlg_param.rq_c.dpte_bytes_per_row_ub; dpte_groups_per_row_ub_c = rq_dlg_param.rq_c.dpte_groups_per_row_ub; meta_chunks_per_row_ub_l = rq_dlg_param.rq_l.meta_chunks_per_row_ub; - vupdate_offset = e2e_pipe_param.pipe.dest.vupdate_offset; - vupdate_width = e2e_pipe_param.pipe.dest.vupdate_width; - vready_offset = e2e_pipe_param.pipe.dest.vready_offset; + meta_chunks_per_row_ub_c = rq_dlg_param.rq_c.meta_chunks_per_row_ub; + vupdate_offset = dst->vupdate_offset; + vupdate_width = dst->vupdate_width; + vready_offset = dst->vready_offset; dppclk_delay_subtotal = mode_lib->ip.dppclk_delay_subtotal; dispclk_delay_subtotal = mode_lib->ip.dispclk_delay_subtotal; + + if (scl_enable) + dppclk_delay_subtotal += mode_lib->ip.dppclk_delay_scl; + else + dppclk_delay_subtotal += mode_lib->ip.dppclk_delay_scl_lb_only; + + dppclk_delay_subtotal += mode_lib->ip.dppclk_delay_cnvc_formatter + + src->num_cursors * mode_lib->ip.dppclk_delay_cnvc_cursor; + + if (dout->dsc_enable) { + double dsc_delay = get_dsc_delay(mode_lib, e2e_pipe_param, num_pipes, pipe_idx); + + dispclk_delay_subtotal += dsc_delay; + } + pixel_rate_delay_subtotal = dppclk_delay_subtotal * pclk_freq_in_mhz / dppclk_freq_in_mhz + dispclk_delay_subtotal * pclk_freq_in_mhz / dispclk_freq_in_mhz; - vstartup_start = e2e_pipe_param.pipe.dest.vstartup_start; + vstartup_start = dst->vstartup_start; + if (interlaced) { + if (vstartup_start / 2.0 + - (double) (vready_offset + vupdate_width + vupdate_offset) / htotal + <= vblank_end / 2.0) + disp_dlg_regs->vready_after_vcount0 = 1; + else + disp_dlg_regs->vready_after_vcount0 = 0; + } else { + if (vstartup_start + - (double) (vready_offset + vupdate_width + vupdate_offset) / htotal + <= vblank_end) + disp_dlg_regs->vready_after_vcount0 = 1; + else + disp_dlg_regs->vready_after_vcount0 = 0; + } + // TODO: Where is this coming from? if (interlaced) vstartup_start = vstartup_start / 2; + // TODO: What if this min_vblank doesn't match the value in the dml_config_settings.cpp? if (vstartup_start >= min_vblank) { - DTRACE( - "WARNING_DLG: %s: vblank_start=%d vblank_end=%d", + dml_print("WARNING: DML_DLG: %s: vblank_start=%d vblank_end=%d\n", __func__, vblank_start, vblank_end); - DTRACE( - "WARNING_DLG: %s: vstartup_start=%d should be less than min_vblank=%d", + dml_print("WARNING: DML_DLG: %s: vstartup_start=%d should be less than min_vblank=%d\n", __func__, vstartup_start, min_vblank); min_vblank = vstartup_start + 1; - DTRACE( - "WARNING_DLG: %s: vstartup_start=%d should be less than min_vblank=%d", + dml_print("WARNING: DML_DLG: %s: vstartup_start=%d should be less than min_vblank=%d\n", __func__, vstartup_start, min_vblank); } - dst_x_after_scaler = 0; - dst_y_after_scaler = 0; - - if (e2e_pipe_param.pipe.src.is_hsplit) - dst_x_after_scaler = pixel_rate_delay_subtotal - + e2e_pipe_param.pipe.dest.recout_width; - else - dst_x_after_scaler = pixel_rate_delay_subtotal; - - if (e2e_pipe_param.dout.output_format == dm_420) - dst_y_after_scaler = 1; - else - dst_y_after_scaler = 0; - - if (dst_x_after_scaler >= htotal) { - dst_x_after_scaler = dst_x_after_scaler - htotal; - dst_y_after_scaler = dst_y_after_scaler + 1; - } + dst_x_after_scaler = get_dst_x_after_scaler(mode_lib, e2e_pipe_param, num_pipes, pipe_idx); + dst_y_after_scaler = get_dst_y_after_scaler(mode_lib, e2e_pipe_param, num_pipes, pipe_idx); - DTRACE("DLG: %s: htotal = %d", __func__, htotal); - DTRACE( - "DLG: %s: pixel_rate_delay_subtotal = %d", + dml_print("DML_DLG: %s: htotal = %d\n", __func__, htotal); + dml_print("DML_DLG: %s: pixel_rate_delay_subtotal = %d\n", __func__, pixel_rate_delay_subtotal); - DTRACE("DLG: %s: dst_x_after_scaler = %d", __func__, dst_x_after_scaler); - DTRACE("DLG: %s: dst_y_after_scaler = %d", __func__, dst_y_after_scaler); + dml_print("DML_DLG: %s: dst_x_after_scaler = %d\n", + __func__, + dst_x_after_scaler); + dml_print("DML_DLG: %s: dst_y_after_scaler = %d\n", + __func__, + dst_y_after_scaler); + // Lwait line_wait = mode_lib->soc.urgent_latency_us; if (cstate_en) line_wait = dml_max(mode_lib->soc.sr_enter_plus_exit_time_us, line_wait); if (pstate_en) - line_wait = dml_max( - mode_lib->soc.dram_clock_change_latency_us + line_wait = dml_max(mode_lib->soc.dram_clock_change_latency_us + mode_lib->soc.urgent_latency_us, line_wait); line_wait = line_wait / line_time_in_us; - line_o = (double) dst_y_after_scaler + dst_x_after_scaler / (double) htotal; - line_setup = (double) (vupdate_offset + vupdate_width + vready_offset) / (double) htotal; - line_calc = t_calc_us / line_time_in_us; + dst_y_prefetch = get_dst_y_prefetch(mode_lib, e2e_pipe_param, num_pipes, pipe_idx); + dml_print("DML_DLG: %s: dst_y_prefetch (after rnd) = %3.2f\n", __func__, dst_y_prefetch); - DTRACE( - "DLG: %s: soc.sr_enter_plus_exit_time_us = %3.2f", - __func__, - (double) mode_lib->soc.sr_enter_plus_exit_time_us); - DTRACE( - "DLG: %s: soc.dram_clock_change_latency_us = %3.2f", - __func__, - (double) mode_lib->soc.dram_clock_change_latency_us); - DTRACE( - "DLG: %s: soc.urgent_latency_us = %3.2f", - __func__, - mode_lib->soc.urgent_latency_us); - - DTRACE("DLG: %s: swath_height_l = %d", __func__, swath_height_l); - if (dual_plane) - DTRACE("DLG: %s: swath_height_c = %d", __func__, swath_height_c); - - DTRACE( - "DLG: %s: t_srx_delay_us = %3.2f", - __func__, - (double) dlg_sys_param.t_srx_delay_us); - DTRACE("DLG: %s: line_time_in_us = %3.2f", __func__, (double) line_time_in_us); - DTRACE("DLG: %s: vupdate_offset = %d", __func__, vupdate_offset); - DTRACE("DLG: %s: vupdate_width = %d", __func__, vupdate_width); - DTRACE("DLG: %s: vready_offset = %d", __func__, vready_offset); - DTRACE("DLG: %s: line_time_in_us = %3.2f", __func__, line_time_in_us); - DTRACE("DLG: %s: line_wait = %3.2f", __func__, line_wait); - DTRACE("DLG: %s: line_o = %3.2f", __func__, line_o); - DTRACE("DLG: %s: line_setup = %3.2f", __func__, line_setup); - DTRACE("DLG: %s: line_calc = %3.2f", __func__, line_calc); - - dst_y_prefetch = ((double) min_vblank - 1.0) - - (line_setup + line_calc + line_wait + line_o); - DTRACE("DLG: %s: dst_y_prefetch (before rnd) = %3.2f", __func__, dst_y_prefetch); - ASSERT(dst_y_prefetch >= 2.0); - - dst_y_prefetch = dml_floor(4.0 * (dst_y_prefetch + 0.125)) / 4; - DTRACE("DLG: %s: dst_y_prefetch (after rnd) = %3.2f", __func__, dst_y_prefetch); - - t_pre_us = dst_y_prefetch * line_time_in_us; - vm_bytes = 0; - meta_row_bytes = 0; - - if (dcc_en && vm_en) - vm_bytes = meta_pte_bytes_per_frame_ub_l; - if (dcc_en) - meta_row_bytes = meta_bytes_per_row_ub_l; - - max_num_sw_l = 0; - max_num_sw_c = 0; - max_partial_sw_l = 0; - max_partial_sw_c = 0; - - max_vinit_l = interlaced ? dml_max(vinit_l, vinit_bot_l) : vinit_l; - max_vinit_c = interlaced ? dml_max(vinit_c, vinit_bot_c) : vinit_c; - - get_swath_need(mode_lib, &max_num_sw_l, &max_partial_sw_l, swath_height_l, max_vinit_l); - if (dual_plane) - get_swath_need( - mode_lib, - &max_num_sw_c, - &max_partial_sw_c, - swath_height_c, - max_vinit_c); - - lsw_l = max_num_sw_l * swath_height_l + max_partial_sw_l; - lsw_c = max_num_sw_c * swath_height_c + max_partial_sw_c; - sw_bytes_ub_l = lsw_l * swath_width_ub_l * bytes_per_element_l; - sw_bytes_ub_c = lsw_c * swath_width_ub_c * bytes_per_element_c; - sw_bytes = 0; - dpte_row_bytes = 0; - - if (vm_en) { - if (dual_plane) - dpte_row_bytes = dpte_bytes_per_row_ub_l + dpte_bytes_per_row_ub_c; - else - dpte_row_bytes = dpte_bytes_per_row_ub_l; - } else { - dpte_row_bytes = 0; - } - - if (dual_plane) - sw_bytes = sw_bytes_ub_l + sw_bytes_ub_c; - else - sw_bytes = sw_bytes_ub_l; - - DTRACE("DLG: %s: sw_bytes_ub_l = %d", __func__, sw_bytes_ub_l); - DTRACE("DLG: %s: sw_bytes_ub_c = %d", __func__, sw_bytes_ub_c); - DTRACE("DLG: %s: sw_bytes = %d", __func__, sw_bytes); - DTRACE("DLG: %s: vm_bytes = %d", __func__, vm_bytes); - DTRACE("DLG: %s: meta_row_bytes = %d", __func__, meta_row_bytes); - DTRACE("DLG: %s: dpte_row_bytes = %d", __func__, dpte_row_bytes); - - prefetch_bw = (vm_bytes + 2 * dpte_row_bytes + 2 * meta_row_bytes + sw_bytes) / t_pre_us; - flip_bw = ((vm_bytes + dpte_row_bytes + meta_row_bytes) * dlg_sys_param.total_flip_bw) - / (double) dlg_sys_param.total_flip_bytes; - t_vm_us = line_time_in_us / 4.0; - if (vm_en && dcc_en) { - t_vm_us = dml_max( - dlg_sys_param.t_extra_us, - dml_max((double) vm_bytes / prefetch_bw, t_vm_us)); - - if (iflip_en && !dual_plane) { - t_vm_us = dml_max(mode_lib->soc.urgent_latency_us, t_vm_us); - if (flip_bw > 0.) - t_vm_us = dml_max(vm_bytes / flip_bw, t_vm_us); - } - } - - t_r0_us = dml_max(dlg_sys_param.t_extra_us - t_vm_us, line_time_in_us - t_vm_us); - - if (vm_en || dcc_en) { - t_r0_us = dml_max( - (double) (dpte_row_bytes + meta_row_bytes) / prefetch_bw, - dlg_sys_param.t_extra_us); - t_r0_us = dml_max((double) (line_time_in_us - t_vm_us), t_r0_us); - - if (iflip_en && !dual_plane) { - t_r0_us = dml_max(mode_lib->soc.urgent_latency_us * 2.0, t_r0_us); - if (flip_bw > 0.) - t_r0_us = dml_max( - (dpte_row_bytes + meta_row_bytes) / flip_bw, - t_r0_us); - } - } - - disp_dlg_regs->dst_y_after_scaler = dst_y_after_scaler; /* in terms of line */ - disp_dlg_regs->refcyc_x_after_scaler = dst_x_after_scaler * ref_freq_to_pix_freq; /* in terms of refclk */ - ASSERT(disp_dlg_regs->refcyc_x_after_scaler < (unsigned int) dml_pow(2, 13)); - DTRACE( - "DLG: %s: disp_dlg_regs->dst_y_after_scaler = 0x%0x", - __func__, - disp_dlg_regs->dst_y_after_scaler); - DTRACE( - "DLG: %s: disp_dlg_regs->refcyc_x_after_scaler = 0x%0x", - __func__, - disp_dlg_regs->refcyc_x_after_scaler); - - disp_dlg_regs->dst_y_prefetch = (unsigned int) (dst_y_prefetch * dml_pow(2, 2)); - DTRACE( - "DLG: %s: disp_dlg_regs->dst_y_prefetch = %d", - __func__, - disp_dlg_regs->dst_y_prefetch); - - dst_y_per_vm_vblank = 0.0; - dst_y_per_row_vblank = 0.0; - - dst_y_per_vm_vblank = t_vm_us / line_time_in_us; - dst_y_per_vm_vblank = dml_floor(4.0 * (dst_y_per_vm_vblank + 0.125)) / 4.0; - disp_dlg_regs->dst_y_per_vm_vblank = (unsigned int) (dst_y_per_vm_vblank * dml_pow(2, 2)); - - dst_y_per_row_vblank = t_r0_us / line_time_in_us; - dst_y_per_row_vblank = dml_floor(4.0 * (dst_y_per_row_vblank + 0.125)) / 4.0; - disp_dlg_regs->dst_y_per_row_vblank = (unsigned int) (dst_y_per_row_vblank * dml_pow(2, 2)); - - DTRACE("DLG: %s: lsw_l = %d", __func__, lsw_l); - DTRACE("DLG: %s: lsw_c = %d", __func__, lsw_c); - DTRACE("DLG: %s: dpte_bytes_per_row_ub_l = %d", __func__, dpte_bytes_per_row_ub_l); - DTRACE("DLG: %s: dpte_bytes_per_row_ub_c = %d", __func__, dpte_bytes_per_row_ub_c); - - DTRACE("DLG: %s: prefetch_bw = %3.2f", __func__, prefetch_bw); - DTRACE("DLG: %s: flip_bw = %3.2f", __func__, flip_bw); - DTRACE("DLG: %s: t_pre_us = %3.2f", __func__, t_pre_us); - DTRACE("DLG: %s: t_vm_us = %3.2f", __func__, t_vm_us); - DTRACE("DLG: %s: t_r0_us = %3.2f", __func__, t_r0_us); - DTRACE("DLG: %s: dst_y_per_vm_vblank = %3.2f", __func__, dst_y_per_vm_vblank); - DTRACE("DLG: %s: dst_y_per_row_vblank = %3.2f", __func__, dst_y_per_row_vblank); - DTRACE("DLG: %s: dst_y_prefetch = %3.2f", __func__, dst_y_prefetch); + dst_y_per_vm_vblank = get_dst_y_per_vm_vblank(mode_lib, + e2e_pipe_param, + num_pipes, + pipe_idx); + dst_y_per_row_vblank = get_dst_y_per_row_vblank(mode_lib, + e2e_pipe_param, + num_pipes, + pipe_idx); + dst_y_per_vm_flip = get_dst_y_per_vm_flip(mode_lib, e2e_pipe_param, num_pipes, pipe_idx); + dst_y_per_row_flip = get_dst_y_per_row_flip(mode_lib, e2e_pipe_param, num_pipes, pipe_idx); min_dst_y_per_vm_vblank = 8.0; min_dst_y_per_row_vblank = 16.0; + + // magic! if (htotal <= 75) { min_vblank = 300; min_dst_y_per_vm_vblank = 100.0; min_dst_y_per_row_vblank = 100.0; } + dml_print("DML_DLG: %s: dst_y_per_vm_vblank = %3.2f\n", __func__, dst_y_per_vm_vblank); + dml_print("DML_DLG: %s: dst_y_per_row_vblank = %3.2f\n", __func__, dst_y_per_row_vblank); + ASSERT(dst_y_per_vm_vblank < min_dst_y_per_vm_vblank); ASSERT(dst_y_per_row_vblank < min_dst_y_per_row_vblank); ASSERT(dst_y_prefetch > (dst_y_per_vm_vblank + dst_y_per_row_vblank)); lsw = dst_y_prefetch - (dst_y_per_vm_vblank + dst_y_per_row_vblank); - DTRACE("DLG: %s: lsw = %3.2f", __func__, lsw); - - vratio_pre_l = get_vratio_pre( - mode_lib, - max_num_sw_l, - max_partial_sw_l, - swath_height_l, - max_vinit_l, - lsw); - vratio_pre_c = 1.0; - if (dual_plane) - vratio_pre_c = get_vratio_pre( - mode_lib, - max_num_sw_c, - max_partial_sw_c, - swath_height_c, - max_vinit_c, - lsw); - - DTRACE("DLG: %s: vratio_pre_l=%3.2f", __func__, vratio_pre_l); - DTRACE("DLG: %s: vratio_pre_c=%3.2f", __func__, vratio_pre_c); - - ASSERT(vratio_pre_l <= 4.0); - if (vratio_pre_l >= 4.0) - disp_dlg_regs->vratio_prefetch = (unsigned int) dml_pow(2, 21) - 1; - else - disp_dlg_regs->vratio_prefetch = (unsigned int) (vratio_pre_l * dml_pow(2, 19)); - - ASSERT(vratio_pre_c <= 4.0); - if (vratio_pre_c >= 4.0) - disp_dlg_regs->vratio_prefetch_c = (unsigned int) dml_pow(2, 21) - 1; - else - disp_dlg_regs->vratio_prefetch_c = (unsigned int) (vratio_pre_c * dml_pow(2, 19)); - - disp_dlg_regs->refcyc_per_pte_group_vblank_l = - (unsigned int) (dst_y_per_row_vblank * (double) htotal - * ref_freq_to_pix_freq / (double) dpte_groups_per_row_ub_l); - ASSERT(disp_dlg_regs->refcyc_per_pte_group_vblank_l < (unsigned int) dml_pow(2, 13)); - - disp_dlg_regs->refcyc_per_pte_group_vblank_c = - (unsigned int) (dst_y_per_row_vblank * (double) htotal - * ref_freq_to_pix_freq / (double) dpte_groups_per_row_ub_c); - ASSERT(disp_dlg_regs->refcyc_per_pte_group_vblank_c < (unsigned int) dml_pow(2, 13)); + dml_print("DML_DLG: %s: lsw = %3.2f\n", __func__, lsw); - disp_dlg_regs->refcyc_per_meta_chunk_vblank_l = - (unsigned int) (dst_y_per_row_vblank * (double) htotal - * ref_freq_to_pix_freq / (double) meta_chunks_per_row_ub_l); - ASSERT(disp_dlg_regs->refcyc_per_meta_chunk_vblank_l < (unsigned int) dml_pow(2, 13)); + vratio_pre_l = get_vratio_prefetch_l(mode_lib, e2e_pipe_param, num_pipes, pipe_idx); + vratio_pre_c = get_vratio_prefetch_c(mode_lib, e2e_pipe_param, num_pipes, pipe_idx); - disp_dlg_regs->refcyc_per_meta_chunk_vblank_c = - disp_dlg_regs->refcyc_per_meta_chunk_vblank_l;/* dcc for 4:2:0 is not supported in dcn1.0. assigned to be the same as _l for now */ + dml_print("DML_DLG: %s: vratio_pre_l=%3.2f\n", __func__, vratio_pre_l); + dml_print("DML_DLG: %s: vratio_pre_c=%3.2f\n", __func__, vratio_pre_c); - /* Active */ + // Active req_per_swath_ub_l = rq_dlg_param.rq_l.req_per_swath_ub; req_per_swath_ub_c = rq_dlg_param.rq_c.req_per_swath_ub; meta_row_height_l = rq_dlg_param.rq_l.meta_row_height; + meta_row_height_c = rq_dlg_param.rq_c.meta_row_height; swath_width_pixels_ub_l = 0; swath_width_pixels_ub_c = 0; scaler_rec_in_width_l = 0; @@ -1771,40 +1106,8 @@ void dml_rq_dlg_get_dlg_params( dpte_row_height_l = rq_dlg_param.rq_l.dpte_row_height; dpte_row_height_c = rq_dlg_param.rq_c.dpte_row_height; - disp_dlg_regs->dst_y_per_pte_row_nom_l = (unsigned int) ((double) dpte_row_height_l - / (double) vratio_l * dml_pow(2, 2)); - ASSERT(disp_dlg_regs->dst_y_per_pte_row_nom_l < (unsigned int) dml_pow(2, 17)); - - disp_dlg_regs->dst_y_per_pte_row_nom_c = (unsigned int) ((double) dpte_row_height_c - / (double) vratio_c * dml_pow(2, 2)); - ASSERT(disp_dlg_regs->dst_y_per_pte_row_nom_c < (unsigned int) dml_pow(2, 17)); - - disp_dlg_regs->dst_y_per_meta_row_nom_l = (unsigned int) ((double) meta_row_height_l - / (double) vratio_l * dml_pow(2, 2)); - ASSERT(disp_dlg_regs->dst_y_per_meta_row_nom_l < (unsigned int) dml_pow(2, 17)); - - disp_dlg_regs->dst_y_per_meta_row_nom_c = disp_dlg_regs->dst_y_per_meta_row_nom_l; /* dcc for 4:2:0 is not supported in dcn1.0. assigned to be the same as _l for now */ - - disp_dlg_regs->refcyc_per_pte_group_nom_l = (unsigned int) ((double) dpte_row_height_l - / (double) vratio_l * (double) htotal * ref_freq_to_pix_freq - / (double) dpte_groups_per_row_ub_l); - if (disp_dlg_regs->refcyc_per_pte_group_nom_l >= (unsigned int) dml_pow(2, 23)) - disp_dlg_regs->refcyc_per_pte_group_nom_l = dml_pow(2, 23) - 1; - - disp_dlg_regs->refcyc_per_pte_group_nom_c = (unsigned int) ((double) dpte_row_height_c - / (double) vratio_c * (double) htotal * ref_freq_to_pix_freq - / (double) dpte_groups_per_row_ub_c); - if (disp_dlg_regs->refcyc_per_pte_group_nom_c >= (unsigned int) dml_pow(2, 23)) - disp_dlg_regs->refcyc_per_pte_group_nom_c = dml_pow(2, 23) - 1; - - disp_dlg_regs->refcyc_per_meta_chunk_nom_l = (unsigned int) ((double) meta_row_height_l - / (double) vratio_l * (double) htotal * ref_freq_to_pix_freq - / (double) meta_chunks_per_row_ub_l); - if (disp_dlg_regs->refcyc_per_meta_chunk_nom_l >= (unsigned int) dml_pow(2, 23)) - disp_dlg_regs->refcyc_per_meta_chunk_nom_l = dml_pow(2, 23) - 1; - if (mode_422) { - swath_width_pixels_ub_l = swath_width_ub_l * 2; /* *2 for 2 pixel per element */ + swath_width_pixels_ub_l = swath_width_ub_l * 2; // *2 for 2 pixel per element swath_width_pixels_ub_c = swath_width_ub_c * 2; } else { swath_width_pixels_ub_l = swath_width_ub_l * 1; @@ -1819,15 +1122,15 @@ void dml_rq_dlg_get_dlg_params( if (htaps_l <= 1) min_hratio_fact_l = 2.0; else if (htaps_l <= 6) { - if ((hratios_l * 2.0) > 4.0) + if ((hratio_l * 2.0) > 4.0) min_hratio_fact_l = 4.0; else - min_hratio_fact_l = hratios_l * 2.0; + min_hratio_fact_l = hratio_l * 2.0; } else { - if (hratios_l > 4.0) + if (hratio_l > 4.0) min_hratio_fact_l = 4.0; else - min_hratio_fact_l = hratios_l; + min_hratio_fact_l = hratio_l; } hscale_pixel_rate_l = min_hratio_fact_l * dppclk_freq_in_mhz; @@ -1835,15 +1138,15 @@ void dml_rq_dlg_get_dlg_params( if (htaps_c <= 1) min_hratio_fact_c = 2.0; else if (htaps_c <= 6) { - if ((hratios_c * 2.0) > 4.0) + if ((hratio_c * 2.0) > 4.0) min_hratio_fact_c = 4.0; else - min_hratio_fact_c = hratios_c * 2.0; + min_hratio_fact_c = hratio_c * 2.0; } else { - if (hratios_c > 4.0) + if (hratio_c > 4.0) min_hratio_fact_c = 4.0; else - min_hratio_fact_c = hratios_c; + min_hratio_fact_c = hratio_c; } hscale_pixel_rate_c = min_hratio_fact_c * dppclk_freq_in_mhz; @@ -1857,97 +1160,90 @@ void dml_rq_dlg_get_dlg_params( refcyc_per_req_delivery_pre_c = 0.; refcyc_per_req_delivery_l = 0.; refcyc_per_req_delivery_c = 0.; - refcyc_per_req_delivery_pre_cur0 = 0.; - refcyc_per_req_delivery_cur0 = 0.; full_recout_width = 0; - if (e2e_pipe_param.pipe.src.is_hsplit) { - if (e2e_pipe_param.pipe.dest.full_recout_width == 0) { - DTRACE("DLG: %s: Warningfull_recout_width not set in hsplit mode", __func__); - full_recout_width = e2e_pipe_param.pipe.dest.recout_width * 2; /* assume half split for dcn1 */ + // In ODM + if (src->is_hsplit) { + // This "hack" is only allowed (and valid) for MPC combine. In ODM + // combine, you MUST specify the full_recout_width...according to Oswin + if (dst->full_recout_width == 0 && !dst->odm_combine) { + dml_print("DML_DLG: %s: Warning: full_recout_width not set in hsplit mode\n", + __func__); + full_recout_width = dst->recout_width * 2; // assume half split for dcn1 } else - full_recout_width = e2e_pipe_param.pipe.dest.full_recout_width; + full_recout_width = dst->full_recout_width; } else - full_recout_width = e2e_pipe_param.pipe.dest.recout_width; + full_recout_width = dst->recout_width; - refcyc_per_line_delivery_pre_l = get_refcyc_per_delivery( - mode_lib, + // mpc_combine and odm_combine are mutually exclusive + refcyc_per_line_delivery_pre_l = get_refcyc_per_delivery(mode_lib, refclk_freq_in_mhz, pclk_freq_in_mhz, + dst->odm_combine, full_recout_width, + dst->hactive, vratio_pre_l, hscale_pixel_rate_l, swath_width_pixels_ub_l, - 1); /* per line */ + 1); // per line - refcyc_per_line_delivery_l = get_refcyc_per_delivery( - mode_lib, + refcyc_per_line_delivery_l = get_refcyc_per_delivery(mode_lib, refclk_freq_in_mhz, pclk_freq_in_mhz, + dst->odm_combine, full_recout_width, + dst->hactive, vratio_l, hscale_pixel_rate_l, swath_width_pixels_ub_l, - 1); /* per line */ + 1); // per line - DTRACE("DLG: %s: full_recout_width = %d", __func__, full_recout_width); - DTRACE("DLG: %s: hscale_pixel_rate_l = %3.2f", __func__, hscale_pixel_rate_l); - DTRACE( - "DLG: %s: refcyc_per_line_delivery_pre_l = %3.2f", + dml_print("DML_DLG: %s: full_recout_width = %d\n", __func__, - refcyc_per_line_delivery_pre_l); - DTRACE( - "DLG: %s: refcyc_per_line_delivery_l = %3.2f", + full_recout_width); + dml_print("DML_DLG: %s: hscale_pixel_rate_l = %3.2f\n", + __func__, + hscale_pixel_rate_l); + dml_print("DML_DLG: %s: refcyc_per_line_delivery_pre_l = %3.2f\n", __func__, - refcyc_per_line_delivery_l); - - disp_dlg_regs->refcyc_per_line_delivery_pre_l = (unsigned int) dml_floor( refcyc_per_line_delivery_pre_l); - disp_dlg_regs->refcyc_per_line_delivery_l = (unsigned int) dml_floor( + dml_print("DML_DLG: %s: refcyc_per_line_delivery_l = %3.2f\n", + __func__, refcyc_per_line_delivery_l); - ASSERT(disp_dlg_regs->refcyc_per_line_delivery_pre_l < (unsigned int) dml_pow(2, 13)); - ASSERT(disp_dlg_regs->refcyc_per_line_delivery_l < (unsigned int) dml_pow(2, 13)); if (dual_plane) { - refcyc_per_line_delivery_pre_c = get_refcyc_per_delivery( - mode_lib, + refcyc_per_line_delivery_pre_c = get_refcyc_per_delivery(mode_lib, refclk_freq_in_mhz, pclk_freq_in_mhz, + dst->odm_combine, full_recout_width, + dst->hactive, vratio_pre_c, hscale_pixel_rate_c, swath_width_pixels_ub_c, - 1); /* per line */ + 1); // per line - refcyc_per_line_delivery_c = get_refcyc_per_delivery( - mode_lib, + refcyc_per_line_delivery_c = get_refcyc_per_delivery(mode_lib, refclk_freq_in_mhz, pclk_freq_in_mhz, + dst->odm_combine, full_recout_width, + dst->hactive, vratio_c, hscale_pixel_rate_c, swath_width_pixels_ub_c, - 1); /* per line */ + 1); // per line - DTRACE( - "DLG: %s: refcyc_per_line_delivery_pre_c = %3.2f", + dml_print("DML_DLG: %s: refcyc_per_line_delivery_pre_c = %3.2f\n", __func__, refcyc_per_line_delivery_pre_c); - DTRACE( - "DLG: %s: refcyc_per_line_delivery_c = %3.2f", + dml_print("DML_DLG: %s: refcyc_per_line_delivery_c = %3.2f\n", __func__, refcyc_per_line_delivery_c); - - disp_dlg_regs->refcyc_per_line_delivery_pre_c = (unsigned int) dml_floor( - refcyc_per_line_delivery_pre_c); - disp_dlg_regs->refcyc_per_line_delivery_c = (unsigned int) dml_floor( - refcyc_per_line_delivery_c); - ASSERT(disp_dlg_regs->refcyc_per_line_delivery_pre_c < (unsigned int) dml_pow(2, 13)); ASSERT(disp_dlg_regs->refcyc_per_line_delivery_c < (unsigned int) dml_pow(2, 13)); } - disp_dlg_regs->chunk_hdl_adjust_cur0 = 3; - /* TTU - Luma / Chroma */ - if (access_dir) { /* vertical access */ + // TTU - Luma / Chroma + if (access_dir) { // vertical access scaler_rec_in_width_l = vp_height_l; scaler_rec_in_width_c = vp_height_c; } else { @@ -1955,167 +1251,264 @@ void dml_rq_dlg_get_dlg_params( scaler_rec_in_width_c = vp_width_c; } - refcyc_per_req_delivery_pre_l = get_refcyc_per_delivery( - mode_lib, + refcyc_per_req_delivery_pre_l = get_refcyc_per_delivery(mode_lib, refclk_freq_in_mhz, pclk_freq_in_mhz, + dst->odm_combine, full_recout_width, + dst->hactive, vratio_pre_l, hscale_pixel_rate_l, scaler_rec_in_width_l, - req_per_swath_ub_l); /* per req */ - refcyc_per_req_delivery_l = get_refcyc_per_delivery( - mode_lib, + req_per_swath_ub_l); // per req + refcyc_per_req_delivery_l = get_refcyc_per_delivery(mode_lib, refclk_freq_in_mhz, pclk_freq_in_mhz, + dst->odm_combine, full_recout_width, + dst->hactive, vratio_l, hscale_pixel_rate_l, scaler_rec_in_width_l, - req_per_swath_ub_l); /* per req */ + req_per_swath_ub_l); // per req - DTRACE( - "DLG: %s: refcyc_per_req_delivery_pre_l = %3.2f", + dml_print("DML_DLG: %s: refcyc_per_req_delivery_pre_l = %3.2f\n", __func__, refcyc_per_req_delivery_pre_l); - DTRACE( - "DLG: %s: refcyc_per_req_delivery_l = %3.2f", + dml_print("DML_DLG: %s: refcyc_per_req_delivery_l = %3.2f\n", __func__, refcyc_per_req_delivery_l); - disp_ttu_regs->refcyc_per_req_delivery_pre_l = (unsigned int) (refcyc_per_req_delivery_pre_l - * dml_pow(2, 10)); - disp_ttu_regs->refcyc_per_req_delivery_l = (unsigned int) (refcyc_per_req_delivery_l - * dml_pow(2, 10)); - ASSERT(refcyc_per_req_delivery_pre_l < dml_pow(2, 13)); ASSERT(refcyc_per_req_delivery_l < dml_pow(2, 13)); if (dual_plane) { - refcyc_per_req_delivery_pre_c = get_refcyc_per_delivery( - mode_lib, + refcyc_per_req_delivery_pre_c = get_refcyc_per_delivery(mode_lib, refclk_freq_in_mhz, pclk_freq_in_mhz, + dst->odm_combine, full_recout_width, + dst->hactive, vratio_pre_c, hscale_pixel_rate_c, scaler_rec_in_width_c, - req_per_swath_ub_c); /* per req */ - refcyc_per_req_delivery_c = get_refcyc_per_delivery( - mode_lib, + req_per_swath_ub_c); // per req + refcyc_per_req_delivery_c = get_refcyc_per_delivery(mode_lib, refclk_freq_in_mhz, pclk_freq_in_mhz, + dst->odm_combine, full_recout_width, + dst->hactive, vratio_c, hscale_pixel_rate_c, scaler_rec_in_width_c, - req_per_swath_ub_c); /* per req */ + req_per_swath_ub_c); // per req - DTRACE( - "DLG: %s: refcyc_per_req_delivery_pre_c = %3.2f", + dml_print("DML_DLG: %s: refcyc_per_req_delivery_pre_c = %3.2f\n", __func__, refcyc_per_req_delivery_pre_c); - DTRACE( - "DLG: %s: refcyc_per_req_delivery_c = %3.2f", + dml_print("DML_DLG: %s: refcyc_per_req_delivery_c = %3.2f\n", __func__, refcyc_per_req_delivery_c); - disp_ttu_regs->refcyc_per_req_delivery_pre_c = - (unsigned int) (refcyc_per_req_delivery_pre_c * dml_pow(2, 10)); - disp_ttu_regs->refcyc_per_req_delivery_c = (unsigned int) (refcyc_per_req_delivery_c - * dml_pow(2, 10)); - ASSERT(refcyc_per_req_delivery_pre_c < dml_pow(2, 13)); ASSERT(refcyc_per_req_delivery_c < dml_pow(2, 13)); } - /* TTU - Cursor */ - hratios_cur0 = e2e_pipe_param.pipe.scale_ratio_depth.hscl_ratio; - cur0_src_width = e2e_pipe_param.pipe.src.cur0_src_width; /* cursor source width */ - cur0_bpp = (enum cursor_bpp) e2e_pipe_param.pipe.src.cur0_bpp; - cur0_req_size = 0; - cur0_req_width = 0; - cur0_width_ub = 0.0; - cur0_req_per_width = 0.0; - hactive_cur0 = 0.0; - - ASSERT(cur0_src_width <= 256); - - if (cur0_src_width > 0) { - unsigned int cur0_bit_per_pixel = 0; - - if (cur0_bpp == dm_cur_2bit) { - cur0_req_size = 64; /* byte */ - cur0_bit_per_pixel = 2; - } else { /* 32bit */ - cur0_bit_per_pixel = 32; - if (cur0_src_width >= 1 && cur0_src_width <= 16) - cur0_req_size = 64; - else if (cur0_src_width >= 17 && cur0_src_width <= 31) - cur0_req_size = 128; - else - cur0_req_size = 256; - } + // XFC + xfc_transfer_delay = get_xfc_transfer_delay(mode_lib, e2e_pipe_param, num_pipes, pipe_idx); + xfc_precharge_delay = get_xfc_precharge_delay(mode_lib, + e2e_pipe_param, + num_pipes, + pipe_idx); + xfc_remote_surface_flip_latency = get_xfc_remote_surface_flip_latency(mode_lib, + e2e_pipe_param, + num_pipes, + pipe_idx); + xfc_dst_y_delta_drq_limit = xfc_remote_surface_flip_latency; + xfc_prefetch_margin = get_xfc_prefetch_margin(mode_lib, + e2e_pipe_param, + num_pipes, + pipe_idx); + + // TTU - Cursor + refcyc_per_req_delivery_pre_cur0 = 0.0; + refcyc_per_req_delivery_cur0 = 0.0; + if (src->num_cursors > 0) { + calculate_ttu_cursor(mode_lib, + &refcyc_per_req_delivery_pre_cur0, + &refcyc_per_req_delivery_cur0, + refclk_freq_in_mhz, + ref_freq_to_pix_freq, + hscale_pixel_rate_l, + scl->hscl_ratio, + vratio_pre_l, + vratio_l, + src->cur0_src_width, + (enum cursor_bpp)(src->cur0_bpp)); + } + + refcyc_per_req_delivery_pre_cur1 = 0.0; + refcyc_per_req_delivery_cur1 = 0.0; + if (src->num_cursors > 1) { + calculate_ttu_cursor(mode_lib, + &refcyc_per_req_delivery_pre_cur1, + &refcyc_per_req_delivery_cur1, + refclk_freq_in_mhz, + ref_freq_to_pix_freq, + hscale_pixel_rate_l, + scl->hscl_ratio, + vratio_pre_l, + vratio_l, + src->cur1_src_width, + (enum cursor_bpp)(src->cur1_bpp)); + } - cur0_req_width = (double) cur0_req_size / ((double) cur0_bit_per_pixel / 8.0); - cur0_width_ub = dml_ceil((double) cur0_src_width / (double) cur0_req_width) - * (double) cur0_req_width; - cur0_req_per_width = cur0_width_ub / (double) cur0_req_width; - hactive_cur0 = (double) cur0_src_width / hratios_cur0; /* FIXME: oswin to think about what to do for cursor */ + // TTU - Misc + // all hard-coded - if (vratio_pre_l <= 1.0) { - refcyc_per_req_delivery_pre_cur0 = hactive_cur0 * ref_freq_to_pix_freq - / (double) cur0_req_per_width; - } else { - refcyc_per_req_delivery_pre_cur0 = (double) refclk_freq_in_mhz - * (double) cur0_src_width / hscale_pixel_rate_l - / (double) cur0_req_per_width; - } + // Assignment to register structures + disp_dlg_regs->dst_y_after_scaler = dst_y_after_scaler; // in terms of line + disp_dlg_regs->refcyc_x_after_scaler = dst_x_after_scaler * ref_freq_to_pix_freq; // in terms of refclk + ASSERT(disp_dlg_regs->refcyc_x_after_scaler < (unsigned int) dml_pow(2, 13)); + disp_dlg_regs->dst_y_prefetch = (unsigned int) (dst_y_prefetch * dml_pow(2, 2)); + disp_dlg_regs->dst_y_per_vm_vblank = (unsigned int) (dst_y_per_vm_vblank * dml_pow(2, 2)); + disp_dlg_regs->dst_y_per_row_vblank = (unsigned int) (dst_y_per_row_vblank * dml_pow(2, 2)); + disp_dlg_regs->dst_y_per_vm_flip = (unsigned int) (dst_y_per_vm_flip * dml_pow(2, 2)); + disp_dlg_regs->dst_y_per_row_flip = (unsigned int) (dst_y_per_row_flip * dml_pow(2, 2)); - disp_ttu_regs->refcyc_per_req_delivery_pre_cur0 = - (unsigned int) (refcyc_per_req_delivery_pre_cur0 * dml_pow(2, 10)); - ASSERT(refcyc_per_req_delivery_pre_cur0 < dml_pow(2, 13)); + disp_dlg_regs->vratio_prefetch = (unsigned int) (vratio_pre_l * dml_pow(2, 19)); + disp_dlg_regs->vratio_prefetch_c = (unsigned int) (vratio_pre_c * dml_pow(2, 19)); - if (vratio_l <= 1.0) { - refcyc_per_req_delivery_cur0 = hactive_cur0 * ref_freq_to_pix_freq - / (double) cur0_req_per_width; - } else { - refcyc_per_req_delivery_cur0 = (double) refclk_freq_in_mhz - * (double) cur0_src_width / hscale_pixel_rate_l - / (double) cur0_req_per_width; + disp_dlg_regs->refcyc_per_pte_group_vblank_l = + (unsigned int) (dst_y_per_row_vblank * (double) htotal + * ref_freq_to_pix_freq / (double) dpte_groups_per_row_ub_l); + ASSERT(disp_dlg_regs->refcyc_per_pte_group_vblank_l < (unsigned int) dml_pow(2, 13)); + + if (dual_plane) { + disp_dlg_regs->refcyc_per_pte_group_vblank_c = (unsigned int) (dst_y_per_row_vblank + * (double) htotal * ref_freq_to_pix_freq + / (double) dpte_groups_per_row_ub_c); + ASSERT(disp_dlg_regs->refcyc_per_pte_group_vblank_c + < (unsigned int) dml_pow(2, 13)); + } + + disp_dlg_regs->refcyc_per_meta_chunk_vblank_l = + (unsigned int) (dst_y_per_row_vblank * (double) htotal + * ref_freq_to_pix_freq / (double) meta_chunks_per_row_ub_l); + ASSERT(disp_dlg_regs->refcyc_per_meta_chunk_vblank_l < (unsigned int) dml_pow(2, 13)); + + disp_dlg_regs->refcyc_per_meta_chunk_vblank_c = + disp_dlg_regs->refcyc_per_meta_chunk_vblank_l; // dcc for 4:2:0 is not supported in dcn1.0. assigned to be the same as _l for now + + disp_dlg_regs->refcyc_per_pte_group_flip_l = (unsigned int) (dst_y_per_row_flip * htotal + * ref_freq_to_pix_freq) / dpte_groups_per_row_ub_l; + disp_dlg_regs->refcyc_per_meta_chunk_flip_l = (unsigned int) (dst_y_per_row_flip * htotal + * ref_freq_to_pix_freq) / meta_chunks_per_row_ub_l; + + if (dual_plane) { + disp_dlg_regs->refcyc_per_pte_group_flip_c = (unsigned int) (dst_y_per_row_flip + * htotal * ref_freq_to_pix_freq) / dpte_groups_per_row_ub_c; + disp_dlg_regs->refcyc_per_meta_chunk_flip_c = (unsigned int) (dst_y_per_row_flip + * htotal * ref_freq_to_pix_freq) / meta_chunks_per_row_ub_c; + } + + disp_dlg_regs->dst_y_per_pte_row_nom_l = (unsigned int) ((double) dpte_row_height_l + / (double) vratio_l * dml_pow(2, 2)); + ASSERT(disp_dlg_regs->dst_y_per_pte_row_nom_l < (unsigned int) dml_pow(2, 17)); + + if (dual_plane) { + disp_dlg_regs->dst_y_per_pte_row_nom_c = (unsigned int) ((double) dpte_row_height_c + / (double) vratio_c * dml_pow(2, 2)); + if (disp_dlg_regs->dst_y_per_pte_row_nom_c >= (unsigned int) dml_pow(2, 17)) { + dml_print("DML_DLG: %s: Warning dst_y_per_pte_row_nom_c %u larger than supported by register format U15.2 %u\n", + __func__, + disp_dlg_regs->dst_y_per_pte_row_nom_c, + (unsigned int) dml_pow(2, 17) - 1); } + } - DTRACE("DLG: %s: cur0_req_width = %d", __func__, cur0_req_width); - DTRACE( - "DLG: %s: cur0_width_ub = %3.2f", - __func__, - cur0_width_ub); - DTRACE( - "DLG: %s: cur0_req_per_width = %3.2f", - __func__, - cur0_req_per_width); - DTRACE( - "DLG: %s: hactive_cur0 = %3.2f", - __func__, - hactive_cur0); - DTRACE( - "DLG: %s: refcyc_per_req_delivery_pre_cur0 = %3.2f", - __func__, - refcyc_per_req_delivery_pre_cur0); - DTRACE( - "DLG: %s: refcyc_per_req_delivery_cur0 = %3.2f", - __func__, - refcyc_per_req_delivery_cur0); + disp_dlg_regs->dst_y_per_meta_row_nom_l = (unsigned int) ((double) meta_row_height_l + / (double) vratio_l * dml_pow(2, 2)); + ASSERT(disp_dlg_regs->dst_y_per_meta_row_nom_l < (unsigned int) dml_pow(2, 17)); - disp_ttu_regs->refcyc_per_req_delivery_cur0 = - (unsigned int) (refcyc_per_req_delivery_cur0 * dml_pow(2, 10)); - ASSERT(refcyc_per_req_delivery_cur0 < dml_pow(2, 13)); - } else { - disp_ttu_regs->refcyc_per_req_delivery_pre_cur0 = 0; - disp_ttu_regs->refcyc_per_req_delivery_cur0 = 0; + disp_dlg_regs->dst_y_per_meta_row_nom_c = disp_dlg_regs->dst_y_per_meta_row_nom_l; // TODO: dcc for 4:2:0 is not supported in dcn1.0. assigned to be the same as _l for now + + disp_dlg_regs->refcyc_per_pte_group_nom_l = (unsigned int) ((double) dpte_row_height_l + / (double) vratio_l * (double) htotal * ref_freq_to_pix_freq + / (double) dpte_groups_per_row_ub_l); + if (disp_dlg_regs->refcyc_per_pte_group_nom_l >= (unsigned int) dml_pow(2, 23)) + disp_dlg_regs->refcyc_per_pte_group_nom_l = dml_pow(2, 23) - 1; + disp_dlg_regs->refcyc_per_meta_chunk_nom_l = (unsigned int) ((double) meta_row_height_l + / (double) vratio_l * (double) htotal * ref_freq_to_pix_freq + / (double) meta_chunks_per_row_ub_l); + if (disp_dlg_regs->refcyc_per_meta_chunk_nom_l >= (unsigned int) dml_pow(2, 23)) + disp_dlg_regs->refcyc_per_meta_chunk_nom_l = dml_pow(2, 23) - 1; + + if (dual_plane) { + disp_dlg_regs->refcyc_per_pte_group_nom_c = + (unsigned int) ((double) dpte_row_height_c / (double) vratio_c + * (double) htotal * ref_freq_to_pix_freq + / (double) dpte_groups_per_row_ub_c); + if (disp_dlg_regs->refcyc_per_pte_group_nom_c >= (unsigned int) dml_pow(2, 23)) + disp_dlg_regs->refcyc_per_pte_group_nom_c = dml_pow(2, 23) - 1; + + // TODO: Is this the right calculation? Does htotal need to be halved? + disp_dlg_regs->refcyc_per_meta_chunk_nom_c = + (unsigned int) ((double) meta_row_height_c / (double) vratio_c + * (double) htotal * ref_freq_to_pix_freq + / (double) meta_chunks_per_row_ub_c); + if (disp_dlg_regs->refcyc_per_meta_chunk_nom_c >= (unsigned int) dml_pow(2, 23)) + disp_dlg_regs->refcyc_per_meta_chunk_nom_c = dml_pow(2, 23) - 1; } - /* TTU - Misc */ + disp_dlg_regs->refcyc_per_line_delivery_pre_l = (unsigned int) dml_floor(refcyc_per_line_delivery_pre_l, + 1); + disp_dlg_regs->refcyc_per_line_delivery_l = (unsigned int) dml_floor(refcyc_per_line_delivery_l, + 1); + ASSERT(disp_dlg_regs->refcyc_per_line_delivery_pre_l < (unsigned int) dml_pow(2, 13)); + ASSERT(disp_dlg_regs->refcyc_per_line_delivery_l < (unsigned int) dml_pow(2, 13)); + + disp_dlg_regs->refcyc_per_line_delivery_pre_c = (unsigned int) dml_floor(refcyc_per_line_delivery_pre_c, + 1); + disp_dlg_regs->refcyc_per_line_delivery_c = (unsigned int) dml_floor(refcyc_per_line_delivery_c, + 1); + ASSERT(disp_dlg_regs->refcyc_per_line_delivery_pre_c < (unsigned int) dml_pow(2, 13)); + ASSERT(disp_dlg_regs->refcyc_per_line_delivery_c < (unsigned int) dml_pow(2, 13)); + + disp_dlg_regs->chunk_hdl_adjust_cur0 = 3; + disp_dlg_regs->dst_y_offset_cur0 = 0; + disp_dlg_regs->chunk_hdl_adjust_cur1 = 3; + disp_dlg_regs->dst_y_offset_cur1 = 0; + + disp_dlg_regs->xfc_reg_transfer_delay = xfc_transfer_delay; + disp_dlg_regs->xfc_reg_precharge_delay = xfc_precharge_delay; + disp_dlg_regs->xfc_reg_remote_surface_flip_latency = xfc_remote_surface_flip_latency; + disp_dlg_regs->xfc_reg_prefetch_margin = dml_ceil(xfc_prefetch_margin * refclk_freq_in_mhz, + 1); + + // slave has to have this value also set to off + if (src->xfc_enable && !src->xfc_slave) + disp_dlg_regs->dst_y_delta_drq_limit = dml_ceil(xfc_dst_y_delta_drq_limit, 1); + else + disp_dlg_regs->dst_y_delta_drq_limit = 0x7fff; // off + + disp_ttu_regs->refcyc_per_req_delivery_pre_l = (unsigned int) (refcyc_per_req_delivery_pre_l + * dml_pow(2, 10)); + disp_ttu_regs->refcyc_per_req_delivery_l = (unsigned int) (refcyc_per_req_delivery_l + * dml_pow(2, 10)); + disp_ttu_regs->refcyc_per_req_delivery_pre_c = (unsigned int) (refcyc_per_req_delivery_pre_c + * dml_pow(2, 10)); + disp_ttu_regs->refcyc_per_req_delivery_c = (unsigned int) (refcyc_per_req_delivery_c + * dml_pow(2, 10)); + disp_ttu_regs->refcyc_per_req_delivery_pre_cur0 = + (unsigned int) (refcyc_per_req_delivery_pre_cur0 * dml_pow(2, 10)); + disp_ttu_regs->refcyc_per_req_delivery_cur0 = (unsigned int) (refcyc_per_req_delivery_cur0 + * dml_pow(2, 10)); + disp_ttu_regs->refcyc_per_req_delivery_pre_cur1 = + (unsigned int) (refcyc_per_req_delivery_pre_cur1 * dml_pow(2, 10)); + disp_ttu_regs->refcyc_per_req_delivery_cur1 = (unsigned int) (refcyc_per_req_delivery_cur1 + * dml_pow(2, 10)); disp_ttu_regs->qos_level_low_wm = 0; ASSERT(disp_ttu_regs->qos_level_low_wm < dml_pow(2, 14)); disp_ttu_regs->qos_level_high_wm = (unsigned int) (4.0 * (double) htotal @@ -2137,118 +1530,232 @@ void dml_rq_dlg_get_dlg_params( print__dlg_regs_st(mode_lib, *disp_dlg_regs); } -void dml_rq_dlg_get_dlg_reg( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_dlg_regs_st *dlg_regs, - struct _vcs_dpi_display_ttu_regs_st *ttu_regs, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e_pipe_param, - const int unsigned num_pipes, - const int unsigned pipe_idx, +void dml_rq_dlg_get_dlg_reg(struct display_mode_lib *mode_lib, + display_dlg_regs_st *dlg_regs, + display_ttu_regs_st *ttu_regs, + display_e2e_pipe_params_st *e2e_pipe_param, + const unsigned int num_pipes, + const unsigned int pipe_idx, const bool cstate_en, const bool pstate_en, const bool vm_en, - const bool iflip_en) + const bool ignore_viewport_pos, + const bool immediate_flip_support) { - struct _vcs_dpi_display_rq_params_st rq_param = {0}; - struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param = {0}; - struct _vcs_dpi_wm_calc_pipe_params_st *wm_param = mode_lib->wm_param; - struct _vcs_dpi_cstate_pstate_watermarks_st cstate_pstate_wm; - struct _vcs_dpi_display_dlg_prefetch_param_st prefetch_param; - double total_ret_bw; - double total_active_bw; - double total_prefetch_bw; - int unsigned total_flip_bytes; - int unsigned num_planes; - int i; - - memset(wm_param, 0, sizeof(mode_lib->wm_param)); - - /* Get watermark and Tex. */ - DTRACE("DLG: Start calculating system setting related parameters. num_pipes=%d", num_pipes); - num_planes = dml_wm_e2e_to_wm(mode_lib, e2e_pipe_param, num_pipes, wm_param); - - cstate_pstate_wm = dml_wm_cstate_pstate_e2e(mode_lib, e2e_pipe_param, num_pipes); - dlg_sys_param.t_mclk_wm_us = cstate_pstate_wm.pstate_change_us; - dlg_sys_param.t_sr_wm_us = cstate_pstate_wm.cstate_enter_plus_exit_us; - dlg_sys_param.t_urg_wm_us = dml_wm_urgent_e2e(mode_lib, e2e_pipe_param, num_pipes); - dlg_sys_param.t_srx_delay_us = mode_lib->ip.dcfclk_cstate_latency - / dml_wm_dcfclk_deepsleep_mhz_e2e(mode_lib, e2e_pipe_param, num_pipes); - dlg_sys_param.t_extra_us = dml_wm_urgent_extra(mode_lib, wm_param, num_planes); - dlg_sys_param.deepsleep_dcfclk_mhz = dml_wm_dcfclk_deepsleep_mhz_e2e( - mode_lib, + display_rq_params_st rq_param = {0}; + display_dlg_sys_params_st dlg_sys_param = {0}; + + // Get watermark and Tex. + dlg_sys_param.t_urg_wm_us = get_wm_urgent(mode_lib, e2e_pipe_param, num_pipes); + dlg_sys_param.deepsleep_dcfclk_mhz = get_clk_dcf_deepsleep(mode_lib, + e2e_pipe_param, + num_pipes); + dlg_sys_param.t_extra_us = get_urgent_extra_latency(mode_lib, e2e_pipe_param, num_pipes); + dlg_sys_param.mem_trip_us = get_wm_memory_trip(mode_lib, e2e_pipe_param, num_pipes); + dlg_sys_param.t_mclk_wm_us = get_wm_dram_clock_change(mode_lib, e2e_pipe_param, num_pipes); + dlg_sys_param.t_sr_wm_us = get_wm_stutter_enter_exit(mode_lib, e2e_pipe_param, num_pipes); + dlg_sys_param.total_flip_bw = get_total_immediate_flip_bw(mode_lib, e2e_pipe_param, num_pipes); + dlg_sys_param.total_flip_bytes = get_total_immediate_flip_bytes(mode_lib, + e2e_pipe_param, + num_pipes); + dlg_sys_param.t_srx_delay_us = mode_lib->ip.dcfclk_cstate_latency + / dlg_sys_param.deepsleep_dcfclk_mhz; // TODO: Deprecated print__dlg_sys_params_st(mode_lib, dlg_sys_param); - DTRACE("DLG: Start calculating total prefetch bw. num_planes=%d", num_planes); - total_ret_bw = dml_wm_calc_return_bw(mode_lib, wm_param, num_planes); - total_active_bw = dml_wm_calc_total_data_read_bw(mode_lib, wm_param, num_planes); - total_prefetch_bw = 0.0; - total_flip_bytes = 0; + // system parameter calculation done - for (i = 0; i < num_pipes; i++) { - dml_rq_dlg_get_rq_params(mode_lib, &rq_param, e2e_pipe_param[i].pipe.src); - dml_rq_dlg_get_dlg_params_prefetch( - mode_lib, - &prefetch_param, - rq_param.dlg, - dlg_sys_param, - e2e_pipe_param[i], - cstate_en, - pstate_en, - vm_en); - total_prefetch_bw += prefetch_param.prefetch_bw; - total_flip_bytes += prefetch_param.flip_bytes; - DTRACE( - "DLG: pipe=%d, total_prefetch_bw=%3.2f total_flip_bytes=%d", - i, - total_prefetch_bw, - total_flip_bytes); - } - - dlg_sys_param.total_flip_bw = total_ret_bw - dml_max(total_active_bw, total_prefetch_bw); - - DTRACE("DLG: Done calculating total prefetch bw"); - DTRACE("DLG: num_pipes = %d", num_pipes); - DTRACE("DLG: total_ret_bw = %3.2f", total_ret_bw); - DTRACE("DLG: total_active_bw = %3.2f", total_active_bw); - DTRACE("DLG: total_prefetch_bw = %3.2f", total_prefetch_bw); - DTRACE("DLG: total_flip_bw = %3.2f", dlg_sys_param.total_flip_bw); - - if (dlg_sys_param.total_flip_bw < 0.0 && iflip_en) { - DTRACE("WARNING_DLG Insufficient bw for immediate flip!"); - dlg_sys_param.total_flip_bw = 0; - } - - dlg_sys_param.total_flip_bytes = total_flip_bytes; - DTRACE("DLG: total_flip_bytes = %d", dlg_sys_param.total_flip_bytes); - DTRACE("DLG: Done calculating system setting related parameters."); - - /* system parameter calculation done */ - - DTRACE("DLG: Calculation for pipe[%d] start", pipe_idx); + dml_print("DML_DLG: Calculation for pipe[%d] start\n\n", pipe_idx); dml_rq_dlg_get_rq_params(mode_lib, &rq_param, e2e_pipe_param[pipe_idx].pipe.src); - dml_rq_dlg_get_dlg_params( - mode_lib, + dml_rq_dlg_get_dlg_params(mode_lib, + e2e_pipe_param, + num_pipes, + pipe_idx, dlg_regs, ttu_regs, rq_param.dlg, dlg_sys_param, - e2e_pipe_param[pipe_idx], cstate_en, pstate_en, vm_en, - iflip_en); - DTRACE("DLG: Calculation for pipe[%d] end", pipe_idx); + ignore_viewport_pos, + immediate_flip_support); + dml_print("DML_DLG: Calculation for pipe[%d] end\n", pipe_idx); } -void dml_rq_dlg_get_arb_params( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_arb_params_st *arb_param) +void dml_rq_dlg_get_arb_params(struct display_mode_lib *mode_lib, display_arb_params_st *arb_param) { memset(arb_param, 0, sizeof(*arb_param)); arb_param->max_req_outstanding = 256; arb_param->min_req_outstanding = 68; arb_param->sat_level_us = 60; } + +void calculate_ttu_cursor(struct display_mode_lib *mode_lib, + double *refcyc_per_req_delivery_pre_cur, + double *refcyc_per_req_delivery_cur, + double refclk_freq_in_mhz, + double ref_freq_to_pix_freq, + double hscale_pixel_rate_l, + double hscl_ratio, + double vratio_pre_l, + double vratio_l, + unsigned int cur_width, + enum cursor_bpp cur_bpp) +{ + unsigned int cur_src_width = cur_width; + unsigned int cur_req_size = 0; + unsigned int cur_req_width = 0; + double cur_width_ub = 0.0; + double cur_req_per_width = 0.0; + double hactive_cur = 0.0; + + ASSERT(cur_src_width <= 256); + + *refcyc_per_req_delivery_pre_cur = 0.0; + *refcyc_per_req_delivery_cur = 0.0; + if (cur_src_width > 0) { + unsigned int cur_bit_per_pixel = 0; + + if (cur_bpp == dm_cur_2bit) { + cur_req_size = 64; // byte + cur_bit_per_pixel = 2; + } else { // 32bit + cur_bit_per_pixel = 32; + if (cur_src_width >= 1 && cur_src_width <= 16) + cur_req_size = 64; + else if (cur_src_width >= 17 && cur_src_width <= 31) + cur_req_size = 128; + else + cur_req_size = 256; + } + + cur_req_width = (double) cur_req_size / ((double) cur_bit_per_pixel / 8.0); + cur_width_ub = dml_ceil((double) cur_src_width / (double) cur_req_width, 1) + * (double) cur_req_width; + cur_req_per_width = cur_width_ub / (double) cur_req_width; + hactive_cur = (double) cur_src_width / hscl_ratio; // FIXME: oswin to think about what to do for cursor + + if (vratio_pre_l <= 1.0) { + *refcyc_per_req_delivery_pre_cur = hactive_cur * ref_freq_to_pix_freq + / (double) cur_req_per_width; + } else { + *refcyc_per_req_delivery_pre_cur = (double) refclk_freq_in_mhz + * (double) cur_src_width / hscale_pixel_rate_l + / (double) cur_req_per_width; + } + + ASSERT(*refcyc_per_req_delivery_pre_cur < dml_pow(2, 13)); + + if (vratio_l <= 1.0) { + *refcyc_per_req_delivery_cur = hactive_cur * ref_freq_to_pix_freq + / (double) cur_req_per_width; + } else { + *refcyc_per_req_delivery_cur = (double) refclk_freq_in_mhz + * (double) cur_src_width / hscale_pixel_rate_l + / (double) cur_req_per_width; + } + + dml_print("DML_DLG: %s: cur_req_width = %d\n", + __func__, + cur_req_width); + dml_print("DML_DLG: %s: cur_width_ub = %3.2f\n", + __func__, + cur_width_ub); + dml_print("DML_DLG: %s: cur_req_per_width = %3.2f\n", + __func__, + cur_req_per_width); + dml_print("DML_DLG: %s: hactive_cur = %3.2f\n", + __func__, + hactive_cur); + dml_print("DML_DLG: %s: refcyc_per_req_delivery_pre_cur = %3.2f\n", + __func__, + *refcyc_per_req_delivery_pre_cur); + dml_print("DML_DLG: %s: refcyc_per_req_delivery_cur = %3.2f\n", + __func__, + *refcyc_per_req_delivery_cur); + + ASSERT(*refcyc_per_req_delivery_cur < dml_pow(2, 13)); + } +} + +unsigned int dml_rq_dlg_get_calculated_vstartup(struct display_mode_lib *mode_lib, + display_e2e_pipe_params_st *e2e_pipe_param, + const unsigned int num_pipes, + const unsigned int pipe_idx) +{ + unsigned int vstartup_pipe[DC__NUM_PIPES__MAX]; + bool visited[DC__NUM_PIPES__MAX]; + unsigned int pipe_inst = 0; + unsigned int i, j, k; + + for (k = 0; k < num_pipes; ++k) + visited[k] = false; + + for (i = 0; i < num_pipes; i++) { + if (e2e_pipe_param[i].pipe.src.is_hsplit && !visited[i]) { + unsigned int grp = e2e_pipe_param[i].pipe.src.hsplit_grp; + + for (j = i; j < num_pipes; j++) { + if (e2e_pipe_param[j].pipe.src.hsplit_grp == grp + && e2e_pipe_param[j].pipe.src.is_hsplit + && !visited[j]) { + vstartup_pipe[j] = get_vstartup_calculated(mode_lib, + e2e_pipe_param, + num_pipes, + pipe_inst); + visited[j] = true; + } + } + + pipe_inst++; + } + + if (!visited[i]) { + vstartup_pipe[i] = get_vstartup_calculated(mode_lib, + e2e_pipe_param, + num_pipes, + pipe_inst); + visited[i] = true; + pipe_inst++; + } + } + + return vstartup_pipe[pipe_idx]; + +} + +void dml_rq_dlg_get_row_heights(struct display_mode_lib *mode_lib, + unsigned int *o_dpte_row_height, + unsigned int *o_meta_row_height, + unsigned int vp_width, + unsigned int data_pitch, + int source_format, + int tiling, + int macro_tile_size, + int source_scan, + int is_chroma) +{ + display_data_rq_dlg_params_st rq_dlg_param; + display_data_rq_misc_params_st rq_misc_param; + display_data_rq_sizing_params_st rq_sizing_param; + + get_meta_and_pte_attr(mode_lib, + &rq_dlg_param, + &rq_misc_param, + &rq_sizing_param, + vp_width, + 0, // dummy + data_pitch, + 0, // dummy + source_format, + tiling, + macro_tile_size, + source_scan, + is_chroma); + + *o_dpte_row_height = rq_dlg_param.dpte_row_height; + *o_meta_row_height = rq_dlg_param.meta_row_height; +} diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.h b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.h index e63b13fb2887..efdd4c73d8f3 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.h @@ -22,103 +22,114 @@ * Authors: AMD * */ -#ifndef __DISPLAY_RQ_DLG_CALC_H__ -#define __DISPLAY_RQ_DLG_CALC_H__ + +#ifndef __DML2_DISPLAY_RQ_DLG_CALC_H__ +#define __DML2_DISPLAY_RQ_DLG_CALC_H__ #include "dml_common_defs.h" #include "display_rq_dlg_helpers.h" struct display_mode_lib; -void extract_rq_regs( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_rq_regs_st *rq_regs, - const struct _vcs_dpi_display_rq_params_st rq_param); -/* Function: dml_rq_dlg_get_rq_params - * Calculate requestor related parameters that register definition agnostic - * (i.e. this layer does try to separate real values from register defintion) - * Input: - * pipe_src_param - pipe source configuration (e.g. vp, pitch, etc.) - * Output: - * rq_param - values that can be used to setup RQ (e.g. swath_height, plane1_addr, etc.) - */ +// Function: dml_rq_dlg_get_rq_params +// Calculate requestor related parameters that register definition agnostic +// (i.e. this layer does try to separate real values from register definition) +// Input: +// pipe_src_param - pipe source configuration (e.g. vp, pitch, etc.) +// Output: +// rq_param - values that can be used to setup RQ (e.g. swath_height, plane1_addr, etc.) +// void dml_rq_dlg_get_rq_params( struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_rq_params_st *rq_param, - const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param); + display_rq_params_st *rq_param, + const display_pipe_source_params_st pipe_src_param); -/* Function: dml_rq_dlg_get_rq_reg - * Main entry point for test to get the register values out of this DML class. - * This function calls and fucntions to calculate - * and then populate the rq_regs struct - * Input: - * pipe_src_param - pipe source configuration (e.g. vp, pitch, etc.) - * Output: - * rq_regs - struct that holds all the RQ registers field value. - * See also: - */ +// Function: dml_rq_dlg_get_rq_reg +// Main entry point for test to get the register values out of this DML class. +// This function calls and fucntions to calculate +// and then populate the rq_regs struct +// Input: +// pipe_src_param - pipe source configuration (e.g. vp, pitch, etc.) +// Output: +// rq_regs - struct that holds all the RQ registers field value. +// See also: void dml_rq_dlg_get_rq_reg( struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_rq_regs_st *rq_regs, - const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param); + display_rq_regs_st *rq_regs, + const display_pipe_source_params_st pipe_src_param); -/* Function: dml_rq_dlg_get_dlg_params - * Calculate deadline related parameters - */ -void dml_rq_dlg_get_dlg_params( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_dlg_regs_st *dlg_regs, - struct _vcs_dpi_display_ttu_regs_st *ttu_regs, - const struct _vcs_dpi_display_rq_dlg_params_st rq_dlg_param, - const struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param, - const struct _vcs_dpi_display_e2e_pipe_params_st e2e_pipe_param, +// Function: dml_rq_dlg_get_dlg_params +// Calculate deadline related parameters +// +void dml_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *e2e_pipe_param, + const unsigned int num_pipes, + const unsigned int pipe_idx, + display_dlg_regs_st *disp_dlg_regs, + display_ttu_regs_st *disp_ttu_regs, + const display_rq_dlg_params_st rq_dlg_param, + const display_dlg_sys_params_st dlg_sys_param, const bool cstate_en, const bool pstate_en, const bool vm_en, - const bool iflip_en); + const bool ignore_viewport_pos, + const bool immediate_flip_support); -/* Function: dml_rq_dlg_get_dlg_param_prefetch - * For flip_bw programming guide change, now dml needs to calculate the flip_bytes and prefetch_bw - * for ALL pipes and use this info to calculate the prefetch programming. - * Output: prefetch_param.prefetch_bw and flip_bytes - */ +// Function: dml_rq_dlg_get_dlg_param_prefetch +// For flip_bw programming guide change, now dml needs to calculate the flip_bytes and prefetch_bw +// for ALL pipes and use this info to calculate the prefetch programming. +// Output: prefetch_param.prefetch_bw and flip_bytes void dml_rq_dlg_get_dlg_params_prefetch( struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_dlg_prefetch_param_st *prefetch_param, - struct _vcs_dpi_display_rq_dlg_params_st rq_dlg_param, - struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param, - struct _vcs_dpi_display_e2e_pipe_params_st e2e_pipe_param, + display_dlg_prefetch_param_st *prefetch_param, + display_rq_dlg_params_st rq_dlg_param, + display_dlg_sys_params_st dlg_sys_param, + display_e2e_pipe_params_st e2e_pipe_param, const bool cstate_en, const bool pstate_en, const bool vm_en); -/* Function: dml_rq_dlg_get_dlg_reg - * Calculate and return DLG and TTU register struct given the system setting - * Output: - * dlg_regs - output DLG register struct - * ttu_regs - output DLG TTU register struct - * Input: - * e2e_pipe_param - "compacted" array of e2e pipe param struct - * num_pipes - num of active "pipe" or "route" - * pipe_idx - index that identifies the e2e_pipe_param that corresponding to this dlg - * cstate - 0: when calculate min_ttu_vblank it is assumed cstate is not required. 1: Normal mode, cstate is considered. - * Added for legacy or unrealistic timing tests. - */ +// Function: dml_rq_dlg_get_dlg_reg +// Calculate and return DLG and TTU register struct given the system setting +// Output: +// dlg_regs - output DLG register struct +// ttu_regs - output DLG TTU register struct +// Input: +// e2e_pipe_param - "compacted" array of e2e pipe param struct +// num_pipes - num of active "pipe" or "route" +// pipe_idx - index that identifies the e2e_pipe_param that corresponding to this dlg +// cstate - 0: when calculate min_ttu_vblank it is assumed cstate is not required. 1: Normal mode, cstate is considered. +// Added for legacy or unrealistic timing tests. void dml_rq_dlg_get_dlg_reg( struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_dlg_regs_st *dlg_regs, - struct _vcs_dpi_display_ttu_regs_st *ttu_regs, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e_pipe_param, + display_dlg_regs_st *dlg_regs, + display_ttu_regs_st *ttu_regs, + display_e2e_pipe_params_st *e2e_pipe_param, const unsigned int num_pipes, const unsigned int pipe_idx, const bool cstate_en, const bool pstate_en, const bool vm_en, - const bool iflip_en); + const bool ignore_viewport_pos, + const bool immediate_flip_support); -/* Function: dml_rq_dlg_get_row_heights - * Calculate dpte and meta row heights - */ +// Function: dml_rq_dlg_get_calculated_vstartup +// Calculate and return vstartup +// Output: +// unsigned int vstartup +// Input: +// e2e_pipe_param - "compacted" array of e2e pipe param struct +// num_pipes - num of active "pipe" or "route" +// pipe_idx - index that identifies the e2e_pipe_param that corresponding to this dlg +// NOTE: this MUST be called after setting the prefetch mode! +unsigned int dml_rq_dlg_get_calculated_vstartup( + struct display_mode_lib *mode_lib, + display_e2e_pipe_params_st *e2e_pipe_param, + const unsigned int num_pipes, + const unsigned int pipe_idx); + +// Function: dml_rq_dlg_get_row_heights +// Calculate dpte and meta row heights void dml_rq_dlg_get_row_heights( struct display_mode_lib *mode_lib, unsigned int *o_dpte_row_height, @@ -131,9 +142,7 @@ void dml_rq_dlg_get_row_heights( int source_scan, int is_chroma); -/* Function: dml_rq_dlg_get_arb_params */ -void dml_rq_dlg_get_arb_params( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_arb_params_st *arb_param); +// Function: dml_rq_dlg_get_arb_params +void dml_rq_dlg_get_arb_params(struct display_mode_lib *mode_lib, display_arb_params_st *arb_param); #endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c index 3dc11366cd36..189052e911fc 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c @@ -25,296 +25,368 @@ #include "display_rq_dlg_helpers.h" -void print__rq_params_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_rq_params_st rq_param) +void print__rq_params_st(struct display_mode_lib *mode_lib, display_rq_params_st rq_param) { - DTRACE("RQ_DLG_CALC: *************************** "); - DTRACE("RQ_DLG_CALC: DISPLAY_RQ_PARAM_ST"); - DTRACE("RQ_DLG_CALC: "); + dml_print("DML_RQ_DLG_CALC: ***************************\n"); + dml_print("DML_RQ_DLG_CALC: DISPLAY_RQ_PARAM_ST\n"); + dml_print("DML_RQ_DLG_CALC: \n"); print__data_rq_sizing_params_st(mode_lib, rq_param.sizing.rq_l); - DTRACE("RQ_DLG_CALC: === "); + dml_print("DML_RQ_DLG_CALC: ===\n"); print__data_rq_sizing_params_st(mode_lib, rq_param.sizing.rq_c); - DTRACE("RQ_DLG_CALC: "); + dml_print("DML_RQ_DLG_CALC: \n"); print__data_rq_dlg_params_st(mode_lib, rq_param.dlg.rq_l); - DTRACE("RQ_DLG_CALC: "); + dml_print("DML_RQ_DLG_CALC: \n"); print__data_rq_dlg_params_st(mode_lib, rq_param.dlg.rq_c); - DTRACE("RQ_DLG_CALC: "); + dml_print("DML_RQ_DLG_CALC: \n"); print__data_rq_misc_params_st(mode_lib, rq_param.misc.rq_l); - DTRACE("RQ_DLG_CALC: "); + dml_print("DML_RQ_DLG_CALC: \n"); print__data_rq_misc_params_st(mode_lib, rq_param.misc.rq_c); - DTRACE("RQ_DLG_CALC: *************************** "); + dml_print("DML_RQ_DLG_CALC: ***************************\n"); } -void print__data_rq_sizing_params_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_data_rq_sizing_params_st rq_sizing) +void print__data_rq_sizing_params_st(struct display_mode_lib *mode_lib, display_data_rq_sizing_params_st rq_sizing) { - DTRACE("RQ_DLG_CALC: ===================================== "); - DTRACE("RQ_DLG_CALC: DISPLAY_DATA_RQ_SIZING_PARAM_ST"); - DTRACE("RQ_DLG_CALC: chunk_bytes = %0d", rq_sizing.chunk_bytes); - DTRACE("RQ_DLG_CALC: min_chunk_bytes = %0d", rq_sizing.min_chunk_bytes); - DTRACE("RQ_DLG_CALC: meta_chunk_bytes = %0d", rq_sizing.meta_chunk_bytes); - DTRACE("RQ_DLG_CALC: min_meta_chunk_bytes = %0d", rq_sizing.min_meta_chunk_bytes); - DTRACE("RQ_DLG_CALC: mpte_group_bytes = %0d", rq_sizing.mpte_group_bytes); - DTRACE("RQ_DLG_CALC: dpte_group_bytes = %0d", rq_sizing.dpte_group_bytes); - DTRACE("RQ_DLG_CALC: ===================================== "); + dml_print("DML_RQ_DLG_CALC: =====================================\n"); + dml_print("DML_RQ_DLG_CALC: DISPLAY_DATA_RQ_SIZING_PARAM_ST\n"); + dml_print("DML_RQ_DLG_CALC: chunk_bytes = %0d\n", rq_sizing.chunk_bytes); + dml_print("DML_RQ_DLG_CALC: min_chunk_bytes = %0d\n", rq_sizing.min_chunk_bytes); + dml_print("DML_RQ_DLG_CALC: meta_chunk_bytes = %0d\n", rq_sizing.meta_chunk_bytes); + dml_print( + "DML_RQ_DLG_CALC: min_meta_chunk_bytes = %0d\n", + rq_sizing.min_meta_chunk_bytes); + dml_print("DML_RQ_DLG_CALC: mpte_group_bytes = %0d\n", rq_sizing.mpte_group_bytes); + dml_print("DML_RQ_DLG_CALC: dpte_group_bytes = %0d\n", rq_sizing.dpte_group_bytes); + dml_print("DML_RQ_DLG_CALC: =====================================\n"); } -void print__data_rq_dlg_params_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_data_rq_dlg_params_st rq_dlg_param) +void print__data_rq_dlg_params_st(struct display_mode_lib *mode_lib, display_data_rq_dlg_params_st rq_dlg_param) { - DTRACE("RQ_DLG_CALC: ===================================== "); - DTRACE("RQ_DLG_CALC: DISPLAY_DATA_RQ_DLG_PARAM_ST"); - DTRACE("RQ_DLG_CALC: swath_width_ub = %0d", rq_dlg_param.swath_width_ub); - DTRACE("RQ_DLG_CALC: swath_height = %0d", rq_dlg_param.swath_height); - DTRACE("RQ_DLG_CALC: req_per_swath_ub = %0d", rq_dlg_param.req_per_swath_ub); - DTRACE( - "RQ_DLG_CALC: meta_pte_bytes_per_frame_ub = %0d", + dml_print("DML_RQ_DLG_CALC: =====================================\n"); + dml_print("DML_RQ_DLG_CALC: DISPLAY_DATA_RQ_DLG_PARAM_ST\n"); + dml_print( + "DML_RQ_DLG_CALC: swath_width_ub = %0d\n", + rq_dlg_param.swath_width_ub); + dml_print( + "DML_RQ_DLG_CALC: swath_height = %0d\n", + rq_dlg_param.swath_height); + dml_print( + "DML_RQ_DLG_CALC: req_per_swath_ub = %0d\n", + rq_dlg_param.req_per_swath_ub); + dml_print( + "DML_RQ_DLG_CALC: meta_pte_bytes_per_frame_ub = %0d\n", rq_dlg_param.meta_pte_bytes_per_frame_ub); - DTRACE( - "RQ_DLG_CALC: dpte_req_per_row_ub = %0d", + dml_print( + "DML_RQ_DLG_CALC: dpte_req_per_row_ub = %0d\n", rq_dlg_param.dpte_req_per_row_ub); - DTRACE( - "RQ_DLG_CALC: dpte_groups_per_row_ub = %0d", + dml_print( + "DML_RQ_DLG_CALC: dpte_groups_per_row_ub = %0d\n", rq_dlg_param.dpte_groups_per_row_ub); - DTRACE("RQ_DLG_CALC: dpte_row_height = %0d", rq_dlg_param.dpte_row_height); - DTRACE( - "RQ_DLG_CALC: dpte_bytes_per_row_ub = %0d", + dml_print( + "DML_RQ_DLG_CALC: dpte_row_height = %0d\n", + rq_dlg_param.dpte_row_height); + dml_print( + "DML_RQ_DLG_CALC: dpte_bytes_per_row_ub = %0d\n", rq_dlg_param.dpte_bytes_per_row_ub); - DTRACE( - "RQ_DLG_CALC: meta_chunks_per_row_ub = %0d", + dml_print( + "DML_RQ_DLG_CALC: meta_chunks_per_row_ub = %0d\n", rq_dlg_param.meta_chunks_per_row_ub); - DTRACE( - "RQ_DLG_CALC: meta_req_per_row_ub = %0d", + dml_print( + "DML_RQ_DLG_CALC: meta_req_per_row_ub = %0d\n", rq_dlg_param.meta_req_per_row_ub); - DTRACE("RQ_DLG_CALC: meta_row_height = %0d", rq_dlg_param.meta_row_height); - DTRACE( - "RQ_DLG_CALC: meta_bytes_per_row_ub = %0d", + dml_print( + "DML_RQ_DLG_CALC: meta_row_height = %0d\n", + rq_dlg_param.meta_row_height); + dml_print( + "DML_RQ_DLG_CALC: meta_bytes_per_row_ub = %0d\n", rq_dlg_param.meta_bytes_per_row_ub); - DTRACE("RQ_DLG_CALC: ===================================== "); + dml_print("DML_RQ_DLG_CALC: =====================================\n"); } -void print__data_rq_misc_params_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_data_rq_misc_params_st rq_misc_param) +void print__data_rq_misc_params_st(struct display_mode_lib *mode_lib, display_data_rq_misc_params_st rq_misc_param) { - DTRACE("RQ_DLG_CALC: ===================================== "); - DTRACE("RQ_DLG_CALC: DISPLAY_DATA_RQ_MISC_PARAM_ST"); - DTRACE("RQ_DLG_CALC: full_swath_bytes = %0d", rq_misc_param.full_swath_bytes); - DTRACE("RQ_DLG_CALC: stored_swath_bytes = %0d", rq_misc_param.stored_swath_bytes); - DTRACE("RQ_DLG_CALC: blk256_width = %0d", rq_misc_param.blk256_width); - DTRACE("RQ_DLG_CALC: blk256_height = %0d", rq_misc_param.blk256_height); - DTRACE("RQ_DLG_CALC: req_width = %0d", rq_misc_param.req_width); - DTRACE("RQ_DLG_CALC: req_height = %0d", rq_misc_param.req_height); - DTRACE("RQ_DLG_CALC: ===================================== "); + dml_print("DML_RQ_DLG_CALC: =====================================\n"); + dml_print("DML_RQ_DLG_CALC: DISPLAY_DATA_RQ_MISC_PARAM_ST\n"); + dml_print( + "DML_RQ_DLG_CALC: full_swath_bytes = %0d\n", + rq_misc_param.full_swath_bytes); + dml_print( + "DML_RQ_DLG_CALC: stored_swath_bytes = %0d\n", + rq_misc_param.stored_swath_bytes); + dml_print("DML_RQ_DLG_CALC: blk256_width = %0d\n", rq_misc_param.blk256_width); + dml_print("DML_RQ_DLG_CALC: blk256_height = %0d\n", rq_misc_param.blk256_height); + dml_print("DML_RQ_DLG_CALC: req_width = %0d\n", rq_misc_param.req_width); + dml_print("DML_RQ_DLG_CALC: req_height = %0d\n", rq_misc_param.req_height); + dml_print("DML_RQ_DLG_CALC: =====================================\n"); } -void print__rq_dlg_params_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_rq_dlg_params_st rq_dlg_param) +void print__rq_dlg_params_st(struct display_mode_lib *mode_lib, display_rq_dlg_params_st rq_dlg_param) { - DTRACE("RQ_DLG_CALC: ===================================== "); - DTRACE("RQ_DLG_CALC: DISPLAY_RQ_DLG_PARAM_ST"); - DTRACE("RQ_DLG_CALC: "); + dml_print("DML_RQ_DLG_CALC: =====================================\n"); + dml_print("DML_RQ_DLG_CALC: DISPLAY_RQ_DLG_PARAM_ST\n"); + dml_print("DML_RQ_DLG_CALC: \n"); print__data_rq_dlg_params_st(mode_lib, rq_dlg_param.rq_l); - DTRACE("RQ_DLG_CALC: "); + dml_print("DML_RQ_DLG_CALC: \n"); print__data_rq_dlg_params_st(mode_lib, rq_dlg_param.rq_c); - DTRACE("RQ_DLG_CALC: ===================================== "); + dml_print("DML_RQ_DLG_CALC: =====================================\n"); } -void print__dlg_sys_params_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param) +void print__dlg_sys_params_st(struct display_mode_lib *mode_lib, display_dlg_sys_params_st dlg_sys_param) { - DTRACE("RQ_DLG_CALC: ===================================== "); - DTRACE("RQ_DLG_CALC: DISPLAY_RQ_DLG_PARAM_ST"); - DTRACE("RQ_DLG_CALC: t_mclk_wm_us = %3.2f", dlg_sys_param.t_mclk_wm_us); - DTRACE("RQ_DLG_CALC: t_urg_wm_us = %3.2f", dlg_sys_param.t_urg_wm_us); - DTRACE("RQ_DLG_CALC: t_sr_wm_us = %3.2f", dlg_sys_param.t_sr_wm_us); - DTRACE("RQ_DLG_CALC: t_extra_us = %3.2f", dlg_sys_param.t_extra_us); - DTRACE("RQ_DLG_CALC: t_srx_delay_us = %3.2f", dlg_sys_param.t_srx_delay_us); - DTRACE("RQ_DLG_CALC: deepsleep_dcfclk_mhz = %3.2f", dlg_sys_param.deepsleep_dcfclk_mhz); - DTRACE("RQ_DLG_CALC: ===================================== "); + dml_print("DML_RQ_DLG_CALC: =====================================\n"); + dml_print("DML_RQ_DLG_CALC: DISPLAY_RQ_DLG_PARAM_ST\n"); + dml_print("DML_RQ_DLG_CALC: t_mclk_wm_us = %3.2f\n", dlg_sys_param.t_mclk_wm_us); + dml_print("DML_RQ_DLG_CALC: t_urg_wm_us = %3.2f\n", dlg_sys_param.t_urg_wm_us); + dml_print("DML_RQ_DLG_CALC: t_sr_wm_us = %3.2f\n", dlg_sys_param.t_sr_wm_us); + dml_print("DML_RQ_DLG_CALC: t_extra_us = %3.2f\n", dlg_sys_param.t_extra_us); + dml_print( + "DML_RQ_DLG_CALC: t_srx_delay_us = %3.2f\n", + dlg_sys_param.t_srx_delay_us); + dml_print( + "DML_RQ_DLG_CALC: deepsleep_dcfclk_mhz = %3.2f\n", + dlg_sys_param.deepsleep_dcfclk_mhz); + dml_print( + "DML_RQ_DLG_CALC: total_flip_bw = %3.2f\n", + dlg_sys_param.total_flip_bw); + dml_print( + "DML_RQ_DLG_CALC: total_flip_bytes = %i\n", + dlg_sys_param.total_flip_bytes); + dml_print("DML_RQ_DLG_CALC: =====================================\n"); } -void print__data_rq_regs_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_data_rq_regs_st rq_regs) +void print__data_rq_regs_st(struct display_mode_lib *mode_lib, display_data_rq_regs_st rq_regs) { - DTRACE("RQ_DLG_CALC: ===================================== "); - DTRACE("RQ_DLG_CALC: DISPLAY_DATA_RQ_REGS_ST"); - DTRACE("RQ_DLG_CALC: chunk_size = 0x%0x", rq_regs.chunk_size); - DTRACE("RQ_DLG_CALC: min_chunk_size = 0x%0x", rq_regs.min_chunk_size); - DTRACE("RQ_DLG_CALC: meta_chunk_size = 0x%0x", rq_regs.meta_chunk_size); - DTRACE("RQ_DLG_CALC: min_meta_chunk_size = 0x%0x", rq_regs.min_meta_chunk_size); - DTRACE("RQ_DLG_CALC: dpte_group_size = 0x%0x", rq_regs.dpte_group_size); - DTRACE("RQ_DLG_CALC: mpte_group_size = 0x%0x", rq_regs.mpte_group_size); - DTRACE("RQ_DLG_CALC: swath_height = 0x%0x", rq_regs.swath_height); - DTRACE("RQ_DLG_CALC: pte_row_height_linear = 0x%0x", rq_regs.pte_row_height_linear); - DTRACE("RQ_DLG_CALC: ===================================== "); + dml_print("DML_RQ_DLG_CALC: =====================================\n"); + dml_print("DML_RQ_DLG_CALC: DISPLAY_DATA_RQ_REGS_ST\n"); + dml_print("DML_RQ_DLG_CALC: chunk_size = 0x%0x\n", rq_regs.chunk_size); + dml_print("DML_RQ_DLG_CALC: min_chunk_size = 0x%0x\n", rq_regs.min_chunk_size); + dml_print("DML_RQ_DLG_CALC: meta_chunk_size = 0x%0x\n", rq_regs.meta_chunk_size); + dml_print( + "DML_RQ_DLG_CALC: min_meta_chunk_size = 0x%0x\n", + rq_regs.min_meta_chunk_size); + dml_print("DML_RQ_DLG_CALC: dpte_group_size = 0x%0x\n", rq_regs.dpte_group_size); + dml_print("DML_RQ_DLG_CALC: mpte_group_size = 0x%0x\n", rq_regs.mpte_group_size); + dml_print("DML_RQ_DLG_CALC: swath_height = 0x%0x\n", rq_regs.swath_height); + dml_print( + "DML_RQ_DLG_CALC: pte_row_height_linear = 0x%0x\n", + rq_regs.pte_row_height_linear); + dml_print("DML_RQ_DLG_CALC: =====================================\n"); } -void print__rq_regs_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_rq_regs_st rq_regs) +void print__rq_regs_st(struct display_mode_lib *mode_lib, display_rq_regs_st rq_regs) { - DTRACE("RQ_DLG_CALC: ===================================== "); - DTRACE("RQ_DLG_CALC: DISPLAY_RQ_REGS_ST"); - DTRACE("RQ_DLG_CALC: "); + dml_print("DML_RQ_DLG_CALC: =====================================\n"); + dml_print("DML_RQ_DLG_CALC: DISPLAY_RQ_REGS_ST\n"); + dml_print("DML_RQ_DLG_CALC: \n"); print__data_rq_regs_st(mode_lib, rq_regs.rq_regs_l); - DTRACE("RQ_DLG_CALC: "); + dml_print("DML_RQ_DLG_CALC: \n"); print__data_rq_regs_st(mode_lib, rq_regs.rq_regs_c); - DTRACE("RQ_DLG_CALC: drq_expansion_mode = 0x%0x", rq_regs.drq_expansion_mode); - DTRACE("RQ_DLG_CALC: prq_expansion_mode = 0x%0x", rq_regs.prq_expansion_mode); - DTRACE("RQ_DLG_CALC: mrq_expansion_mode = 0x%0x", rq_regs.mrq_expansion_mode); - DTRACE("RQ_DLG_CALC: crq_expansion_mode = 0x%0x", rq_regs.crq_expansion_mode); - DTRACE("RQ_DLG_CALC: plane1_base_address = 0x%0x", rq_regs.plane1_base_address); - DTRACE("RQ_DLG_CALC: ===================================== "); + dml_print("DML_RQ_DLG_CALC: drq_expansion_mode = 0x%0x\n", rq_regs.drq_expansion_mode); + dml_print("DML_RQ_DLG_CALC: prq_expansion_mode = 0x%0x\n", rq_regs.prq_expansion_mode); + dml_print("DML_RQ_DLG_CALC: mrq_expansion_mode = 0x%0x\n", rq_regs.mrq_expansion_mode); + dml_print("DML_RQ_DLG_CALC: crq_expansion_mode = 0x%0x\n", rq_regs.crq_expansion_mode); + dml_print("DML_RQ_DLG_CALC: plane1_base_address = 0x%0x\n", rq_regs.plane1_base_address); + dml_print("DML_RQ_DLG_CALC: =====================================\n"); } -void print__dlg_regs_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_dlg_regs_st dlg_regs) +void print__dlg_regs_st(struct display_mode_lib *mode_lib, display_dlg_regs_st dlg_regs) { - DTRACE("RQ_DLG_CALC: ===================================== "); - DTRACE("RQ_DLG_CALC: DISPLAY_DLG_REGS_ST "); - DTRACE( - "RQ_DLG_CALC: refcyc_h_blank_end = 0x%0x", + dml_print("DML_RQ_DLG_CALC: =====================================\n"); + dml_print("DML_RQ_DLG_CALC: DISPLAY_DLG_REGS_ST\n"); + dml_print( + "DML_RQ_DLG_CALC: refcyc_h_blank_end = 0x%0x\n", dlg_regs.refcyc_h_blank_end); - DTRACE("RQ_DLG_CALC: dlg_vblank_end = 0x%0x", dlg_regs.dlg_vblank_end); - DTRACE( - "RQ_DLG_CALC: min_dst_y_next_start = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: dlg_vblank_end = 0x%0x\n", + dlg_regs.dlg_vblank_end); + dml_print( + "DML_RQ_DLG_CALC: min_dst_y_next_start = 0x%0x\n", dlg_regs.min_dst_y_next_start); - DTRACE( - "RQ_DLG_CALC: refcyc_per_htotal = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_htotal = 0x%0x\n", dlg_regs.refcyc_per_htotal); - DTRACE( - "RQ_DLG_CALC: refcyc_x_after_scaler = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_x_after_scaler = 0x%0x\n", dlg_regs.refcyc_x_after_scaler); - DTRACE( - "RQ_DLG_CALC: dst_y_after_scaler = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: dst_y_after_scaler = 0x%0x\n", dlg_regs.dst_y_after_scaler); - DTRACE("RQ_DLG_CALC: dst_y_prefetch = 0x%0x", dlg_regs.dst_y_prefetch); - DTRACE( - "RQ_DLG_CALC: dst_y_per_vm_vblank = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: dst_y_prefetch = 0x%0x\n", + dlg_regs.dst_y_prefetch); + dml_print( + "DML_RQ_DLG_CALC: dst_y_per_vm_vblank = 0x%0x\n", dlg_regs.dst_y_per_vm_vblank); - DTRACE( - "RQ_DLG_CALC: dst_y_per_row_vblank = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: dst_y_per_row_vblank = 0x%0x\n", dlg_regs.dst_y_per_row_vblank); - DTRACE( - "RQ_DLG_CALC: ref_freq_to_pix_freq = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: dst_y_per_vm_flip = 0x%0x\n", + dlg_regs.dst_y_per_vm_flip); + dml_print( + "DML_RQ_DLG_CALC: dst_y_per_row_flip = 0x%0x\n", + dlg_regs.dst_y_per_row_flip); + dml_print( + "DML_RQ_DLG_CALC: ref_freq_to_pix_freq = 0x%0x\n", dlg_regs.ref_freq_to_pix_freq); - DTRACE("RQ_DLG_CALC: vratio_prefetch = 0x%0x", dlg_regs.vratio_prefetch); - DTRACE( - "RQ_DLG_CALC: vratio_prefetch_c = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: vratio_prefetch = 0x%0x\n", + dlg_regs.vratio_prefetch); + dml_print( + "DML_RQ_DLG_CALC: vratio_prefetch_c = 0x%0x\n", dlg_regs.vratio_prefetch_c); - DTRACE( - "RQ_DLG_CALC: refcyc_per_pte_group_vblank_l = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_pte_group_vblank_l = 0x%0x\n", dlg_regs.refcyc_per_pte_group_vblank_l); - DTRACE( - "RQ_DLG_CALC: refcyc_per_pte_group_vblank_c = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_pte_group_vblank_c = 0x%0x\n", dlg_regs.refcyc_per_pte_group_vblank_c); - DTRACE( - "RQ_DLG_CALC: refcyc_per_meta_chunk_vblank_l = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_meta_chunk_vblank_l = 0x%0x\n", dlg_regs.refcyc_per_meta_chunk_vblank_l); - DTRACE( - "RQ_DLG_CALC: refcyc_per_meta_chunk_vblank_c = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_meta_chunk_vblank_c = 0x%0x\n", dlg_regs.refcyc_per_meta_chunk_vblank_c); - DTRACE( - "RQ_DLG_CALC: dst_y_per_pte_row_nom_l = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_pte_group_flip_l = 0x%0x\n", + dlg_regs.refcyc_per_pte_group_flip_l); + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_pte_group_flip_c = 0x%0x\n", + dlg_regs.refcyc_per_pte_group_flip_c); + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_meta_chunk_flip_l = 0x%0x\n", + dlg_regs.refcyc_per_meta_chunk_flip_l); + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_meta_chunk_flip_c = 0x%0x\n", + dlg_regs.refcyc_per_meta_chunk_flip_c); + dml_print( + "DML_RQ_DLG_CALC: dst_y_per_pte_row_nom_l = 0x%0x\n", dlg_regs.dst_y_per_pte_row_nom_l); - DTRACE( - "RQ_DLG_CALC: dst_y_per_pte_row_nom_c = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: dst_y_per_pte_row_nom_c = 0x%0x\n", dlg_regs.dst_y_per_pte_row_nom_c); - DTRACE( - "RQ_DLG_CALC: refcyc_per_pte_group_nom_l = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_pte_group_nom_l = 0x%0x\n", dlg_regs.refcyc_per_pte_group_nom_l); - DTRACE( - "RQ_DLG_CALC: refcyc_per_pte_group_nom_c = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_pte_group_nom_c = 0x%0x\n", dlg_regs.refcyc_per_pte_group_nom_c); - DTRACE( - "RQ_DLG_CALC: dst_y_per_meta_row_nom_l = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: dst_y_per_meta_row_nom_l = 0x%0x\n", dlg_regs.dst_y_per_meta_row_nom_l); - DTRACE( - "RQ_DLG_CALC: dst_y_per_meta_row_nom_c = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: dst_y_per_meta_row_nom_c = 0x%0x\n", dlg_regs.dst_y_per_meta_row_nom_c); - DTRACE( - "RQ_DLG_CALC: refcyc_per_meta_chunk_nom_l = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_meta_chunk_nom_l = 0x%0x\n", dlg_regs.refcyc_per_meta_chunk_nom_l); - DTRACE( - "RQ_DLG_CALC: refcyc_per_meta_chunk_nom_c = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_meta_chunk_nom_c = 0x%0x\n", dlg_regs.refcyc_per_meta_chunk_nom_c); - DTRACE( - "RQ_DLG_CALC: refcyc_per_line_delivery_pre_l = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_line_delivery_pre_l = 0x%0x\n", dlg_regs.refcyc_per_line_delivery_pre_l); - DTRACE( - "RQ_DLG_CALC: refcyc_per_line_delivery_pre_c = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_line_delivery_pre_c = 0x%0x\n", dlg_regs.refcyc_per_line_delivery_pre_c); - DTRACE( - "RQ_DLG_CALC: refcyc_per_line_delivery_l = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_line_delivery_l = 0x%0x\n", dlg_regs.refcyc_per_line_delivery_l); - DTRACE( - "RQ_DLG_CALC: refcyc_per_line_delivery_c = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_line_delivery_c = 0x%0x\n", dlg_regs.refcyc_per_line_delivery_c); - DTRACE( - "RQ_DLG_CALC: chunk_hdl_adjust_cur0 = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: chunk_hdl_adjust_cur0 = 0x%0x\n", dlg_regs.chunk_hdl_adjust_cur0); - DTRACE("RQ_DLG_CALC: ===================================== "); + dml_print( + "DML_RQ_DLG_CALC: dst_y_offset_cur1 = 0x%0x\n", + dlg_regs.dst_y_offset_cur1); + dml_print( + "DML_RQ_DLG_CALC: chunk_hdl_adjust_cur1 = 0x%0x\n", + dlg_regs.chunk_hdl_adjust_cur1); + dml_print( + "DML_RQ_DLG_CALC: vready_after_vcount0 = 0x%0x\n", + dlg_regs.vready_after_vcount0); + dml_print( + "DML_RQ_DLG_CALC: dst_y_delta_drq_limit = 0x%0x\n", + dlg_regs.dst_y_delta_drq_limit); + dml_print( + "DML_RQ_DLG_CALC: xfc_reg_transfer_delay = 0x%0x\n", + dlg_regs.xfc_reg_transfer_delay); + dml_print( + "DML_RQ_DLG_CALC: xfc_reg_precharge_delay = 0x%0x\n", + dlg_regs.xfc_reg_precharge_delay); + dml_print( + "DML_RQ_DLG_CALC: xfc_reg_remote_surface_flip_latency = 0x%0x\n", + dlg_regs.xfc_reg_remote_surface_flip_latency); + + dml_print("DML_RQ_DLG_CALC: =====================================\n"); } -void print__ttu_regs_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_ttu_regs_st ttu_regs) +void print__ttu_regs_st(struct display_mode_lib *mode_lib, display_ttu_regs_st ttu_regs) { - DTRACE("RQ_DLG_CALC: ===================================== "); - DTRACE("RQ_DLG_CALC: DISPLAY_TTU_REGS_ST "); - DTRACE( - "RQ_DLG_CALC: qos_level_low_wm = 0x%0x", + dml_print("DML_RQ_DLG_CALC: =====================================\n"); + dml_print("DML_RQ_DLG_CALC: DISPLAY_TTU_REGS_ST\n"); + dml_print( + "DML_RQ_DLG_CALC: qos_level_low_wm = 0x%0x\n", ttu_regs.qos_level_low_wm); - DTRACE( - "RQ_DLG_CALC: qos_level_high_wm = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: qos_level_high_wm = 0x%0x\n", ttu_regs.qos_level_high_wm); - DTRACE("RQ_DLG_CALC: min_ttu_vblank = 0x%0x", ttu_regs.min_ttu_vblank); - DTRACE("RQ_DLG_CALC: qos_level_flip = 0x%0x", ttu_regs.qos_level_flip); - DTRACE( - "RQ_DLG_CALC: refcyc_per_req_delivery_pre_l = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: min_ttu_vblank = 0x%0x\n", + ttu_regs.min_ttu_vblank); + dml_print( + "DML_RQ_DLG_CALC: qos_level_flip = 0x%0x\n", + ttu_regs.qos_level_flip); + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_req_delivery_pre_l = 0x%0x\n", ttu_regs.refcyc_per_req_delivery_pre_l); - DTRACE( - "RQ_DLG_CALC: refcyc_per_req_delivery_l = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_req_delivery_l = 0x%0x\n", ttu_regs.refcyc_per_req_delivery_l); - DTRACE( - "RQ_DLG_CALC: refcyc_per_req_delivery_pre_c = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_req_delivery_pre_c = 0x%0x\n", ttu_regs.refcyc_per_req_delivery_pre_c); - DTRACE( - "RQ_DLG_CALC: refcyc_per_req_delivery_c = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_req_delivery_c = 0x%0x\n", ttu_regs.refcyc_per_req_delivery_c); - DTRACE( - "RQ_DLG_CALC: refcyc_per_req_delivery_cur0 = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_req_delivery_cur0 = 0x%0x\n", ttu_regs.refcyc_per_req_delivery_cur0); - DTRACE( - "RQ_DLG_CALC: refcyc_per_req_delivery_pre_cur0 = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_req_delivery_pre_cur0 = 0x%0x\n", ttu_regs.refcyc_per_req_delivery_pre_cur0); - DTRACE( - "RQ_DLG_CALC: qos_level_fixed_l = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_req_delivery_cur1 = 0x%0x\n", + ttu_regs.refcyc_per_req_delivery_cur1); + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_req_delivery_pre_cur1 = 0x%0x\n", + ttu_regs.refcyc_per_req_delivery_pre_cur1); + dml_print( + "DML_RQ_DLG_CALC: qos_level_fixed_l = 0x%0x\n", ttu_regs.qos_level_fixed_l); - DTRACE( - "RQ_DLG_CALC: qos_ramp_disable_l = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: qos_ramp_disable_l = 0x%0x\n", ttu_regs.qos_ramp_disable_l); - DTRACE( - "RQ_DLG_CALC: qos_level_fixed_c = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: qos_level_fixed_c = 0x%0x\n", ttu_regs.qos_level_fixed_c); - DTRACE( - "RQ_DLG_CALC: qos_ramp_disable_c = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: qos_ramp_disable_c = 0x%0x\n", ttu_regs.qos_ramp_disable_c); - DTRACE( - "RQ_DLG_CALC: qos_level_fixed_cur0 = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: qos_level_fixed_cur0 = 0x%0x\n", ttu_regs.qos_level_fixed_cur0); - DTRACE( - "RQ_DLG_CALC: qos_ramp_disable_cur0 = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: qos_ramp_disable_cur0 = 0x%0x\n", ttu_regs.qos_ramp_disable_cur0); - DTRACE("RQ_DLG_CALC: ===================================== "); + dml_print( + "DML_RQ_DLG_CALC: qos_level_fixed_cur1 = 0x%0x\n", + ttu_regs.qos_level_fixed_cur1); + dml_print( + "DML_RQ_DLG_CALC: qos_ramp_disable_cur1 = 0x%0x\n", + ttu_regs.qos_ramp_disable_cur1); + dml_print("DML_RQ_DLG_CALC: =====================================\n"); } diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.h b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.h index 7403ccaf637b..1f24db830737 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.h @@ -22,6 +22,7 @@ * Authors: AMD * */ + #ifndef __DISPLAY_RQ_DLG_HELPERS_H__ #define __DISPLAY_RQ_DLG_HELPERS_H__ @@ -31,36 +32,16 @@ /* Function: Printer functions * Print various struct */ -void print__rq_params_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_rq_params_st rq_param); -void print__data_rq_sizing_params_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_data_rq_sizing_params_st rq_sizing); -void print__data_rq_dlg_params_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_data_rq_dlg_params_st rq_dlg_param); -void print__data_rq_misc_params_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_data_rq_misc_params_st rq_misc_param); -void print__rq_dlg_params_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_rq_dlg_params_st rq_dlg_param); -void print__dlg_sys_params_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param); +void print__rq_params_st(struct display_mode_lib *mode_lib, display_rq_params_st rq_param); +void print__data_rq_sizing_params_st(struct display_mode_lib *mode_lib, display_data_rq_sizing_params_st rq_sizing); +void print__data_rq_dlg_params_st(struct display_mode_lib *mode_lib, display_data_rq_dlg_params_st rq_dlg_param); +void print__data_rq_misc_params_st(struct display_mode_lib *mode_lib, display_data_rq_misc_params_st rq_misc_param); +void print__rq_dlg_params_st(struct display_mode_lib *mode_lib, display_rq_dlg_params_st rq_dlg_param); +void print__dlg_sys_params_st(struct display_mode_lib *mode_lib, display_dlg_sys_params_st dlg_sys_param); -void print__data_rq_regs_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_data_rq_regs_st data_rq_regs); -void print__rq_regs_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_rq_regs_st rq_regs); -void print__dlg_regs_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_dlg_regs_st dlg_regs); -void print__ttu_regs_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_ttu_regs_st ttu_regs); +void print__data_rq_regs_st(struct display_mode_lib *mode_lib, display_data_rq_regs_st data_rq_regs); +void print__rq_regs_st(struct display_mode_lib *mode_lib, display_rq_regs_st rq_regs); +void print__dlg_regs_st(struct display_mode_lib *mode_lib, display_dlg_regs_st dlg_regs); +void print__ttu_regs_st(struct display_mode_lib *mode_lib, display_ttu_regs_st ttu_regs); #endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_watermark.c b/drivers/gpu/drm/amd/display/dc/dml/display_watermark.c deleted file mode 100644 index 390f09391433..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dml/display_watermark.c +++ /dev/null @@ -1,1281 +0,0 @@ -/* - * Copyright 2017 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ -#include "display_watermark.h" -#include "display_mode_lib.h" - -static void get_bytes_per_pixel( - enum source_format_class format, - struct _vcs_dpi_wm_calc_pipe_params_st *plane) -{ - switch (format) { - case dm_444_64: - plane->bytes_per_pixel_y = 8.0; - plane->bytes_per_pixel_c = 0.0; - break; - case dm_444_32: - plane->bytes_per_pixel_y = 4.0; - plane->bytes_per_pixel_c = 0.0; - break; - case dm_444_16: - plane->bytes_per_pixel_y = 2.0; - plane->bytes_per_pixel_c = 0.0; - break; - case dm_422_10: - plane->bytes_per_pixel_y = 4.0; - plane->bytes_per_pixel_c = 0.0; - break; - case dm_422_8: - plane->bytes_per_pixel_y = 2.0; - plane->bytes_per_pixel_c = 0.0; - break; - case dm_420_8: - plane->bytes_per_pixel_y = 1.0; - plane->bytes_per_pixel_c = 2.0; - break; - case dm_420_10: - plane->bytes_per_pixel_y = 4.0 / 3; - plane->bytes_per_pixel_c = 8.0 / 3; - break; - default: - BREAK_TO_DEBUGGER(); /* invalid format in get_bytes_per_pixel */ - } -} - -static unsigned int get_swath_width_y( - struct _vcs_dpi_display_pipe_source_params_st *src_param, - unsigned int num_dpp) -{ - unsigned int val; - - /* note that we don't divide by num_dpp here because we have an interface which has already split - * any viewports - */ - if (src_param->source_scan == dm_horz) { - val = src_param->viewport_width; - } else { - val = src_param->viewport_height; - } - - return val; -} - -static void get_swath_height( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_pipe_source_params_st *src_param, - struct _vcs_dpi_wm_calc_pipe_params_st *plane, - unsigned int swath_width_y) -{ - double buffer_width; - - if (src_param->source_format == dm_444_64 || src_param->source_format == dm_444_32 - || src_param->source_format == dm_444_16) { - if (src_param->sw_mode == dm_sw_linear) { - plane->swath_height_y = 1; - } else if (src_param->source_format == dm_444_64) { - plane->swath_height_y = 4; - } else { - plane->swath_height_y = 8; - } - - if (src_param->source_scan != dm_horz) { - plane->swath_height_y = 256 / (unsigned int) plane->bytes_per_pixel_y - / plane->swath_height_y; - } - - plane->swath_height_c = 0; - - } else { - if (src_param->sw_mode == dm_sw_linear) { - plane->swath_height_y = 1; - plane->swath_height_c = 1; - } else if (src_param->source_format == dm_420_8) { - plane->swath_height_y = 16; - plane->swath_height_c = 8; - } else { - plane->swath_height_y = 8; - plane->swath_height_c = 8; - } - - if (src_param->source_scan != dm_horz) { - double bytes_per_pixel_c_ceil; - - plane->swath_height_y = 256 / dml_ceil(plane->bytes_per_pixel_y) - / plane->swath_height_y; - - bytes_per_pixel_c_ceil = dml_ceil_2(plane->bytes_per_pixel_c); - - plane->swath_height_c = 256 / bytes_per_pixel_c_ceil - / plane->swath_height_c; - } - } - - /* use swath height min if buffer isn't big enough */ - - buffer_width = ((double) mode_lib->ip.det_buffer_size_kbytes * 1024.0 / 2.0) - / (plane->bytes_per_pixel_y * (double) plane->swath_height_y - + (plane->bytes_per_pixel_c / 2.0 - * (double) plane->swath_height_c)); - - if ((double) swath_width_y <= buffer_width) { - /* do nothing, just keep code structure from Gabes vba */ - } else { - /* substitute swath height with swath height min */ - if (src_param->source_format == dm_444_64 || src_param->source_format == dm_444_32 - || src_param->source_format == dm_444_16) { - if ((src_param->sw_mode == dm_sw_linear) - || (src_param->source_format == dm_444_64 - && (src_param->sw_mode == dm_sw_4kb_s - || src_param->sw_mode - == dm_sw_4kb_s_x - || src_param->sw_mode - == dm_sw_64kb_s - || src_param->sw_mode - == dm_sw_64kb_s_t - || src_param->sw_mode - == dm_sw_64kb_s_x - || src_param->sw_mode - == dm_sw_var_s - || src_param->sw_mode - == dm_sw_var_s_x) - && src_param->source_scan == dm_horz)) { - /* do nothing, just keep code structure from Gabes vba */ - } else { - plane->swath_height_y = plane->swath_height_y / 2; - } - } else { - if (src_param->sw_mode == dm_sw_linear) { - /* do nothing, just keep code structure from Gabes vba */ - } else if (src_param->source_format == dm_420_8 - && src_param->source_scan == dm_horz) { - plane->swath_height_y = plane->swath_height_y / 2; - } else if (src_param->source_format == dm_420_10 - && src_param->source_scan == dm_horz) { - plane->swath_height_c = plane->swath_height_c / 2; - } - } - } - - if (plane->swath_height_c == 0) { - plane->det_buffer_size_y = mode_lib->ip.det_buffer_size_kbytes * 1024.0; - } else if (plane->swath_height_c <= plane->swath_height_y) { - plane->det_buffer_size_y = mode_lib->ip.det_buffer_size_kbytes * 1024.0 / 2.0; - } else { - plane->det_buffer_size_y = mode_lib->ip.det_buffer_size_kbytes * 1024.0 * 2.0 / 3.0; - } -} - -static void calc_display_pipe_line_delivery_time( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *planes, - unsigned int num_planes) -{ - unsigned int i; - - for (i = 0; i < num_planes; i++) { - if (planes[i].v_ratio <= 1.0) { - planes[i].display_pipe_line_delivery_time = planes[i].swath_width_y - * planes[i].num_dpp / planes[i].h_ratio - / planes[i].pixclk_mhz; - } else { - double dchub_pscl_bw_per_clk; - - if (planes[i].h_ratio > 1) { - double num_hscl_kernels; - - num_hscl_kernels = dml_ceil((double) planes[i].h_taps / 6); - dchub_pscl_bw_per_clk = - dml_min( - (double) mode_lib->ip.max_dchub_pscl_bw_pix_per_clk, - mode_lib->ip.max_pscl_lb_bw_pix_per_clk - * planes[i].h_ratio - / num_hscl_kernels); - } else { - dchub_pscl_bw_per_clk = - dml_min( - (double) mode_lib->ip.max_dchub_pscl_bw_pix_per_clk, - (double) mode_lib->ip.max_pscl_lb_bw_pix_per_clk); - } - - planes[i].display_pipe_line_delivery_time = planes[i].swath_width_y - / dchub_pscl_bw_per_clk / planes[i].dppclk_mhz; - } - } -} - -static double calc_total_data_read_bw( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *planes, - unsigned int num_planes) -{ - double val = 0.0; - unsigned int i; - - for (i = 0; i < num_planes; i++) { - double swath_width_y_plane = planes[i].swath_width_y * planes[i].num_dpp; - - planes[i].read_bw = swath_width_y_plane - * (dml_ceil(planes[i].bytes_per_pixel_y) - + dml_ceil_2(planes[i].bytes_per_pixel_c) / 2) - / (planes[i].h_total / planes[i].pixclk_mhz) * planes[i].v_ratio; - - val += planes[i].read_bw; - - DTRACE("plane[%d] start", i); - DTRACE("read_bw = %f", planes[i].read_bw); - DTRACE("plane[%d] end", i); - } - - return val; -} - -double dml_wm_calc_total_data_read_bw( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *planes, - unsigned int num_planes) -{ - return calc_total_data_read_bw(mode_lib, planes, num_planes); -} - -static double calc_dcfclk_mhz( - struct _vcs_dpi_wm_calc_pipe_params_st *planes, - unsigned int num_planes) -{ - double dcfclk_mhz = -1.0; - unsigned int i; - - for (i = 0; i < num_planes; i++) { - /* voltage and dcfclk must be the same for all pipes */ - ASSERT(dcfclk_mhz == -1.0 || dcfclk_mhz == planes[i].dcfclk_mhz); - dcfclk_mhz = planes[i].dcfclk_mhz; - } - - return dcfclk_mhz; -} - -static enum voltage_state find_voltage( - struct _vcs_dpi_wm_calc_pipe_params_st *planes, - unsigned int num_planes) -{ - int voltage = -1; - unsigned int i; - - for (i = 0; i < num_planes; i++) { - ASSERT(voltage == -1 || voltage == planes[i].voltage); - voltage = planes[i].voltage; - } - - return (enum voltage_state) voltage; -} - -static bool find_dcc_enable(struct _vcs_dpi_wm_calc_pipe_params_st *planes, unsigned int num_planes) -{ - unsigned int i; - - for (i = 0; i < num_planes; i++) { - if (planes[i].dcc_enable) { - return true; - } - } - - return false; -} - -static double calc_return_bw( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *planes, - unsigned int num_planes) -{ - struct _vcs_dpi_soc_bounding_box_st *soc; - double return_bw_mbps; - double dcfclk_mhz; - double return_bus_bw; - enum voltage_state voltage; - double return_bw_to_dcn; - bool dcc_enable; - double rob_chunk_diff; - double urgent_latency_traffic; - double critical_compression; - struct _vcs_dpi_voltage_scaling_st state; - - soc = &mode_lib->soc; - - dcfclk_mhz = calc_dcfclk_mhz(planes, num_planes); - return_bus_bw = dcfclk_mhz * soc->return_bus_width_bytes; - - DTRACE("INTERMEDIATE dcfclk_mhz = %f", dcfclk_mhz); - DTRACE("INTERMEDIATE return_bus_bw = %f", return_bus_bw); - - voltage = find_voltage(planes, num_planes); - return_bw_to_dcn = dml_socbb_return_bw_mhz(soc, voltage); - - dcc_enable = find_dcc_enable(planes, num_planes); - - return_bw_mbps = return_bw_to_dcn; - DTRACE("INTERMEDIATE return_bw_mbps = %f", return_bw_mbps); - - rob_chunk_diff = - (mode_lib->ip.rob_buffer_size_kbytes - mode_lib->ip.pixel_chunk_size_kbytes) - * 1024.0; - DTRACE("INTERMEDIATE rob_chunk_diff = %f", rob_chunk_diff); - - if (dcc_enable && return_bw_to_dcn > return_bus_bw / 4) { - double dcc_return_bw = - return_bw_to_dcn * 4.0 - * (1.0 - - soc->urgent_latency_us - / (rob_chunk_diff - / (return_bw_to_dcn - - return_bus_bw - / 4.0) - + soc->urgent_latency_us)); - return_bw_mbps = dml_min(return_bw_mbps, dcc_return_bw); - DTRACE("INTERMEDIATE dcc_return_bw = %f", dcc_return_bw); - } - - urgent_latency_traffic = return_bus_bw * soc->urgent_latency_us; - DTRACE("INTERMEDIATE urgent_latency_traffic = %f", urgent_latency_traffic); - critical_compression = 2.0 * urgent_latency_traffic - / (return_bw_to_dcn * soc->urgent_latency_us + rob_chunk_diff); - DTRACE("INTERMEDIATE critical_compression = %f", critical_compression); - - if (dcc_enable && critical_compression > 1.0 && critical_compression < 4.0) { - double crit_return_bw = (4 * return_bw_to_dcn * rob_chunk_diff - * urgent_latency_traffic); - crit_return_bw = crit_return_bw - / dml_pow( - return_bw_to_dcn * soc->urgent_latency_us - + rob_chunk_diff, - 2); - DTRACE("INTERMEDIATE critical_return_bw = %f", crit_return_bw); - return_bw_mbps = dml_min(return_bw_mbps, crit_return_bw); - } - - /* Gabe does this again for some reason using the value of return_bw_mpbs from the previous calculation - * and a lightly different return_bw_to_dcn - */ - - state = dml_socbb_voltage_scaling(soc, voltage); - return_bw_to_dcn = dml_min( - soc->return_bus_width_bytes * dcfclk_mhz, - state.dram_bw_per_chan_gbps * 1000.0 * (double) soc->num_chans); - - DTRACE("INTERMEDIATE rob_chunk_diff = %f", rob_chunk_diff); - - if (dcc_enable && return_bw_to_dcn > return_bus_bw / 4) { - double dcc_return_bw = - return_bw_to_dcn * 4.0 - * (1.0 - - soc->urgent_latency_us - / (rob_chunk_diff - / (return_bw_to_dcn - - return_bus_bw - / 4.0) - + soc->urgent_latency_us)); - return_bw_mbps = dml_min(return_bw_mbps, dcc_return_bw); - DTRACE("INTERMEDIATE dcc_return_bw = %f", dcc_return_bw); - } - - urgent_latency_traffic = return_bus_bw * soc->urgent_latency_us; - DTRACE("INTERMEDIATE urgent_latency_traffic = %f", urgent_latency_traffic); - critical_compression = 2.0 * urgent_latency_traffic - / (return_bw_to_dcn * soc->urgent_latency_us + rob_chunk_diff); - DTRACE("INTERMEDIATE critical_compression = %f", critical_compression); - - /* problem here? */ - if (dcc_enable && critical_compression > 1.0 && critical_compression < 4.0) { - double crit_return_bw = (4 * return_bw_to_dcn * rob_chunk_diff - * urgent_latency_traffic); - crit_return_bw = crit_return_bw - / dml_pow( - return_bw_to_dcn * soc->urgent_latency_us - + rob_chunk_diff, - 2); - DTRACE("INTERMEDIATE critical_return_bw = %f", crit_return_bw); - DTRACE("INTERMEDIATE return_bw_to_dcn = %f", return_bw_to_dcn); - DTRACE("INTERMEDIATE rob_chunk_diff = %f", rob_chunk_diff); - DTRACE("INTERMEDIATE urgent_latency_traffic = %f", urgent_latency_traffic); - - return_bw_mbps = dml_min(return_bw_mbps, crit_return_bw); - } - - DTRACE("INTERMEDIATE final return_bw_mbps = %f", return_bw_mbps); - return return_bw_mbps; -} - -double dml_wm_calc_return_bw( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *planes, - unsigned int num_planes) -{ - return calc_return_bw(mode_lib, planes, num_planes); -} - -static double calc_last_pixel_of_line_extra_wm_us( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *planes, - unsigned int num_planes) -{ - double val = 0.0; - double total_data_read_bw = calc_total_data_read_bw(mode_lib, planes, num_planes); - int voltage = -1; - unsigned int i; - double return_bw_mbps; - - for (i = 0; i < num_planes; i++) { - /* voltage mode must be the same for all pipes */ - ASSERT(voltage == -1 || voltage == planes[i].voltage); - voltage = planes[i].voltage; - } - return_bw_mbps = calc_return_bw(mode_lib, planes, num_planes); - - for (i = 0; i < num_planes; i++) { - double bytes_pp_y = dml_ceil(planes[i].bytes_per_pixel_y); - double bytes_pp_c = dml_ceil_2(planes[i].bytes_per_pixel_c); - double swath_bytes_y = (double) planes[i].swath_width_y - * (double) planes[i].swath_height_y * (double) bytes_pp_y; - double swath_bytes_c = ((double) planes[i].swath_width_y / 2.0) - * (double) planes[i].swath_height_c * (double) bytes_pp_c; - double data_fabric_line_delivery_time = (swath_bytes_y + swath_bytes_c) - / (return_bw_mbps * planes[i].read_bw / (double) planes[i].num_dpp - / total_data_read_bw); - - DTRACE( - "bytes_pp_y = %f, swath_width_y = %f, swath_height_y = %f, swath_bytes_y = %f", - bytes_pp_y, - (double) planes[i].swath_width_y, - (double) planes[i].swath_height_y, - swath_bytes_y); - DTRACE( - "bytes_pp_c = %f, swath_width_c = %f, swath_height_c = %f, swath_bytes_c = %f", - bytes_pp_c, - ((double) planes[i].swath_width_y / 2.0), - (double) planes[i].swath_height_c, - swath_bytes_c); - DTRACE( - "return_bw_mbps = %f, read_bw = %f, num_dpp = %d, total_data_read_bw = %f", - return_bw_mbps, - planes[i].read_bw, - planes[i].num_dpp, - total_data_read_bw); - DTRACE("data_fabric_line_delivery_time = %f", data_fabric_line_delivery_time); - DTRACE( - "display_pipe_line_delivery_time = %f", - planes[i].display_pipe_line_delivery_time); - - val = dml_max( - val, - data_fabric_line_delivery_time - - planes[i].display_pipe_line_delivery_time); - } - - DTRACE("last_pixel_of_line_extra_wm is %f us", val); - return val; -} - -static bool calc_pte_enable(struct _vcs_dpi_wm_calc_pipe_params_st *planes, unsigned int num_planes) -{ - unsigned int i; - - for (i = 0; i < num_planes; i++) { - if (planes[i].pte_enable) { - return true; - } - } - - return false; -} - -static void calc_lines_in_det_y(struct _vcs_dpi_wm_calc_pipe_params_st *plane) -{ - plane->lines_in_det_y = plane->det_buffer_size_y / plane->bytes_per_pixel_y - / plane->swath_width_y; - plane->lines_in_det_y_rounded_down_to_swath = dml_floor( - (double) plane->lines_in_det_y / plane->swath_height_y) - * plane->swath_height_y; - plane->full_det_buffering_time = plane->lines_in_det_y_rounded_down_to_swath - * (plane->h_total / plane->pixclk_mhz); -} - -/* CHECKME: not obviously 1:1 with calculation described in architectural - * document or spreadsheet */ -static void calc_dcfclk_deepsleep_mhz_per_plane( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *plane) -{ - double bus_width_per_pixel; - - if (plane->swath_height_c == 0) { - bus_width_per_pixel = dml_ceil(plane->bytes_per_pixel_y) / 64; - } else { - double bus_width_per_pixel_c; - - bus_width_per_pixel = dml_ceil(plane->bytes_per_pixel_y) / 32; - bus_width_per_pixel_c = dml_ceil(plane->bytes_per_pixel_c) / 32; - if (bus_width_per_pixel < bus_width_per_pixel_c) - bus_width_per_pixel = bus_width_per_pixel_c; - } - - if (plane->v_ratio <= 1) { - plane->dcfclk_deepsleep_mhz_per_plane = 1.1 * plane->pixclk_mhz / plane->num_dpp - * plane->h_ratio * bus_width_per_pixel; - } else if (plane->h_ratio > 1) { - double num_hscl_kernels = dml_ceil((double) plane->h_taps / 6); - double dchub_pscl_bw_per_clk = dml_min( - (double) mode_lib->ip.max_dchub_pscl_bw_pix_per_clk, - mode_lib->ip.max_pscl_lb_bw_pix_per_clk * plane->h_ratio - / num_hscl_kernels); - - plane->dcfclk_deepsleep_mhz_per_plane = 1.1 * plane->dppclk_mhz - * dchub_pscl_bw_per_clk * bus_width_per_pixel; - } else { - double dchub_pscl_bw_per_clk = dml_min( - (double) mode_lib->ip.max_dchub_pscl_bw_pix_per_clk, - (double) mode_lib->ip.max_pscl_lb_bw_pix_per_clk); - - plane->dcfclk_deepsleep_mhz_per_plane = 1.1 * plane->dppclk_mhz - * dchub_pscl_bw_per_clk * bus_width_per_pixel; - } - - plane->dcfclk_deepsleep_mhz_per_plane = dml_max( - plane->dcfclk_deepsleep_mhz_per_plane, - plane->pixclk_mhz / 16); -} - -/* Implementation of expected stutter efficiency from DCN1_Display_Mode.docx */ -double dml_wm_expected_stutter_eff_e2e( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - unsigned int num_pipes) -{ - double min_full_det_buffering_time_us; - double frame_time_for_min_full_det_buffering_time_us = 0.0; - struct _vcs_dpi_wm_calc_pipe_params_st *planes = mode_lib->wm_param; - unsigned int num_planes; - unsigned int i; - double total_data_read_bw_mbps; - double average_read_bw_gbps; - double min_full_det_buffer_size_bytes; - double rob_fill_size_bytes; - double part_of_burst_that_fits_in_rob; - int voltage; - double dcfclk_mhz; - unsigned int total_writeback; - double return_bw_mbps; - double stutter_burst_time_us; - double stutter_eff_not_including_vblank; - double smallest_vblank_us; - double stutter_eff; - - memset(mode_lib->wm_param, 0, sizeof(mode_lib->wm_param)); - DTRACE("calculating expected stutter efficiency"); - - num_planes = dml_wm_e2e_to_wm(mode_lib, e2e, num_pipes, planes); - - for (i = 0; i < num_planes; i++) { - calc_lines_in_det_y(&planes[i]); - - DTRACE("swath width y plane %d = %d", i, planes[i].swath_width_y); - DTRACE("swath height y plane %d = %d", i, planes[i].swath_height_y); - DTRACE( - "bytes per pixel det y plane %d = %f", - i, - planes[i].bytes_per_pixel_y); - DTRACE( - "bytes per pixel det c plane %d = %f", - i, - planes[i].bytes_per_pixel_c); - DTRACE( - "det buffer size plane %d = %d", - i, - planes[i].det_buffer_size_y); - DTRACE("lines in det plane %d = %d", i, planes[i].lines_in_det_y); - DTRACE( - "lines in det rounded to swaths plane %d = %d", - i, - planes[i].lines_in_det_y_rounded_down_to_swath); - } - - min_full_det_buffering_time_us = 9999.0; - for (i = 0; i < num_planes; i++) { - if (planes[i].full_det_buffering_time < min_full_det_buffering_time_us) { - min_full_det_buffering_time_us = planes[i].full_det_buffering_time; - frame_time_for_min_full_det_buffering_time_us = (double) planes[i].v_total - * planes[i].h_total / planes[i].pixclk_mhz; - } - } - - DTRACE("INTERMEDIATE: min_full_det_buffering_time_us = %f", min_full_det_buffering_time_us); - - total_data_read_bw_mbps = calc_total_data_read_bw(mode_lib, planes, num_planes); - - average_read_bw_gbps = 0.0; - - for (i = 0; i < num_planes; i++) { - if (planes[i].dcc_enable) { - average_read_bw_gbps += planes[i].read_bw / planes[i].dcc_rate / 1000; - } else { - average_read_bw_gbps += planes[i].read_bw / 1000; - } - - if (planes[i].dcc_enable) { - average_read_bw_gbps += planes[i].read_bw / 1000 / 256; - } - - if (planes[i].pte_enable) { - average_read_bw_gbps += planes[i].read_bw / 1000 / 512; - } - } - - min_full_det_buffer_size_bytes = min_full_det_buffering_time_us * total_data_read_bw_mbps; - rob_fill_size_bytes = mode_lib->ip.rob_buffer_size_kbytes * 1024 * total_data_read_bw_mbps - / (average_read_bw_gbps * 1000); - part_of_burst_that_fits_in_rob = dml_min( - min_full_det_buffer_size_bytes, - rob_fill_size_bytes); - - voltage = -1; - dcfclk_mhz = -1.0; - total_writeback = 0; - - for (i = 0; i < num_pipes; i++) { - /* voltage and dcfclk must be the same for all pipes */ - ASSERT(voltage == -1 || voltage == e2e[i].clks_cfg.voltage); - voltage = e2e[i].clks_cfg.voltage; - ASSERT(dcfclk_mhz == -1.0 || dcfclk_mhz == e2e[i].clks_cfg.dcfclk_mhz); - dcfclk_mhz = e2e[i].clks_cfg.dcfclk_mhz; - - if (e2e[i].dout.output_type == dm_wb) - total_writeback++; - } - - return_bw_mbps = calc_return_bw(mode_lib, planes, num_planes); - - DTRACE("INTERMEDIATE: part_of_burst_that_fits_in_rob = %f", part_of_burst_that_fits_in_rob); - DTRACE("INTERMEDIATE: average_read_bw_gbps = %f", average_read_bw_gbps); - DTRACE("INTERMEDIATE: total_data_read_bw_mbps = %f", total_data_read_bw_mbps); - DTRACE("INTERMEDIATE: return_bw_mbps = %f", return_bw_mbps); - - stutter_burst_time_us = part_of_burst_that_fits_in_rob * (average_read_bw_gbps * 1000) - / total_data_read_bw_mbps / return_bw_mbps - + (min_full_det_buffering_time_us * total_data_read_bw_mbps - - part_of_burst_that_fits_in_rob) / (dcfclk_mhz * 64); - DTRACE("INTERMEDIATE: stutter_burst_time_us = %f", stutter_burst_time_us); - - if (total_writeback == 0) { - stutter_eff_not_including_vblank = (1.0 - - ((mode_lib->soc.sr_exit_time_us + stutter_burst_time_us) - / min_full_det_buffering_time_us)) * 100.0; - } else { - stutter_eff_not_including_vblank = 0.0; - } - - DTRACE("stutter_efficiency_not_including_vblank = %f", stutter_eff_not_including_vblank); - - smallest_vblank_us = 9999.0; - - for (i = 0; i < num_pipes; i++) { - double vblank_us; - if (e2e[i].pipe.dest.syncronized_vblank_all_planes != 0 || num_pipes == 1) { - vblank_us = (double) (e2e[i].pipe.dest.vtotal + 1 - - e2e[i].pipe.dest.vblank_start - + e2e[i].pipe.dest.vblank_end * e2e[i].pipe.dest.htotal) - / e2e[i].pipe.dest.pixel_rate_mhz; - } else { - vblank_us = 0.0; - } - - smallest_vblank_us = dml_min(smallest_vblank_us, vblank_us); - } - - DTRACE("smallest vblank = %f us", smallest_vblank_us); - - stutter_eff = 100.0 - * (((stutter_eff_not_including_vblank / 100.0) - * (frame_time_for_min_full_det_buffering_time_us - - smallest_vblank_us) + smallest_vblank_us) - / frame_time_for_min_full_det_buffering_time_us); - - DTRACE("stutter_efficiency = %f", stutter_eff); - - return stutter_eff_not_including_vblank; -} - -double dml_wm_expected_stutter_eff_e2e_with_vblank( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - unsigned int num_pipes) -{ - double min_full_det_buffering_time_us; - double frame_time_for_min_full_det_buffering_time_us = 0.0; - struct _vcs_dpi_wm_calc_pipe_params_st *planes = mode_lib->wm_param; - unsigned int num_planes; - unsigned int i; - double total_data_read_bw_mbps; - double average_read_bw_gbps; - double min_full_det_buffer_size_bytes; - double rob_fill_size_bytes; - double part_of_burst_that_fits_in_rob; - int voltage; - double dcfclk_mhz; - unsigned int total_writeback; - double return_bw_mbps; - double stutter_burst_time_us; - double stutter_eff_not_including_vblank; - double smallest_vblank_us; - double stutter_eff; - - memset(mode_lib->wm_param, 0, sizeof(mode_lib->wm_param)); - num_planes = dml_wm_e2e_to_wm(mode_lib, e2e, num_pipes, planes); - - for (i = 0; i < num_planes; i++) { - calc_lines_in_det_y(&planes[i]); - } - - min_full_det_buffering_time_us = 9999.0; - for (i = 0; i < num_planes; i++) { - if (planes[i].full_det_buffering_time < min_full_det_buffering_time_us) { - min_full_det_buffering_time_us = planes[i].full_det_buffering_time; - frame_time_for_min_full_det_buffering_time_us = (double) planes[i].v_total - * planes[i].h_total / planes[i].pixclk_mhz; - } - } - - total_data_read_bw_mbps = calc_total_data_read_bw(mode_lib, planes, num_planes); - average_read_bw_gbps = 0.0; - - for (i = 0; i < num_planes; i++) { - if (planes[i].dcc_enable) { - average_read_bw_gbps += planes[i].read_bw / planes[i].dcc_rate / 1000; - } else { - average_read_bw_gbps += planes[i].read_bw / 1000; - } - - if (planes[i].dcc_enable) { - average_read_bw_gbps += planes[i].read_bw / 1000 / 256; - } - - if (planes[i].pte_enable) { - average_read_bw_gbps += planes[i].read_bw / 1000 / 512; - } - } - - min_full_det_buffer_size_bytes = min_full_det_buffering_time_us * total_data_read_bw_mbps; - rob_fill_size_bytes = mode_lib->ip.rob_buffer_size_kbytes * 1024 * total_data_read_bw_mbps - / (average_read_bw_gbps * 1000); - part_of_burst_that_fits_in_rob = dml_min( - min_full_det_buffer_size_bytes, - rob_fill_size_bytes); - - voltage = -1; - dcfclk_mhz = -1.0; - total_writeback = 0; - - for (i = 0; i < num_pipes; i++) { - /* voltage and dcfclk must be the same for all pipes */ - ASSERT(voltage == -1 || voltage == e2e[i].clks_cfg.voltage); - voltage = e2e[i].clks_cfg.voltage; - ASSERT(dcfclk_mhz == -1.0 || dcfclk_mhz == e2e[i].clks_cfg.dcfclk_mhz); - dcfclk_mhz = e2e[i].clks_cfg.dcfclk_mhz; - - if (e2e[i].dout.output_type == dm_wb) - total_writeback++; - } - - return_bw_mbps = calc_return_bw(mode_lib, planes, num_planes); - - stutter_burst_time_us = part_of_burst_that_fits_in_rob * (average_read_bw_gbps * 1000) - / total_data_read_bw_mbps / return_bw_mbps - + (min_full_det_buffering_time_us * total_data_read_bw_mbps - - part_of_burst_that_fits_in_rob) / (dcfclk_mhz * 64); - - if (total_writeback == 0) { - stutter_eff_not_including_vblank = (1.0 - - ((mode_lib->soc.sr_exit_time_us + stutter_burst_time_us) - / min_full_det_buffering_time_us)) * 100.0; - } else { - stutter_eff_not_including_vblank = 0.0; - } - - smallest_vblank_us = 9999.0; - - for (i = 0; i < num_pipes; i++) { - double vblank_us; - if (e2e[i].pipe.dest.syncronized_vblank_all_planes != 0 || num_pipes == 1) { - vblank_us = (double) (e2e[i].pipe.dest.vtotal + 1 - - e2e[i].pipe.dest.vblank_start - + e2e[i].pipe.dest.vblank_end * e2e[i].pipe.dest.htotal) - / e2e[i].pipe.dest.pixel_rate_mhz; - } else { - vblank_us = 0.0; - } - - smallest_vblank_us = dml_min(smallest_vblank_us, vblank_us); - } - - stutter_eff = 100.0 - * (((stutter_eff_not_including_vblank / 100.0) - * (frame_time_for_min_full_det_buffering_time_us - - smallest_vblank_us) + smallest_vblank_us) - / frame_time_for_min_full_det_buffering_time_us); - - - return stutter_eff; -} - -double urgent_extra_calc( - struct display_mode_lib *mode_lib, - double dcfclk_mhz, - double return_bw_mbps, - unsigned int total_active_dpp, - unsigned int total_dcc_active_dpp) -{ - double urgent_extra_latency_us = 0.0; - double urgent_round_trip_ooo_latency_us; - - urgent_round_trip_ooo_latency_us = - (((double) mode_lib->soc.round_trip_ping_latency_dcfclk_cycles + 32) - / dcfclk_mhz) - + (((double) (mode_lib->soc.urgent_out_of_order_return_per_channel_bytes - * mode_lib->soc.num_chans)) / return_bw_mbps); - - DTRACE( - "INTERMEDIATE round_trip_ping_latency_dcfclk_cycles = %d", - mode_lib->soc.round_trip_ping_latency_dcfclk_cycles); - DTRACE("INTERMEDIATE dcfclk_mhz = %f", dcfclk_mhz); - DTRACE( - "INTERMEDIATE urgent_out_of_order_return_per_channel_bytes = %d", - mode_lib->soc.urgent_out_of_order_return_per_channel_bytes); - - urgent_extra_latency_us = urgent_round_trip_ooo_latency_us - + ((double) total_active_dpp * mode_lib->ip.pixel_chunk_size_kbytes - + (double) total_dcc_active_dpp - * mode_lib->ip.meta_chunk_size_kbytes) - * 1024.0 / return_bw_mbps; /* to us */ - - DTRACE( - "INTERMEDIATE urgent_round_trip_ooo_latency_us = %f", - urgent_round_trip_ooo_latency_us); - DTRACE("INTERMEDIATE total_active_dpp = %d", total_active_dpp); - DTRACE( - "INTERMEDIATE pixel_chunk_size_kbytes = %d", - mode_lib->ip.pixel_chunk_size_kbytes); - DTRACE("INTERMEDIATE total_dcc_active_dpp = %d", total_dcc_active_dpp); - DTRACE( - "INTERMEDIATE meta_chunk_size_kbyte = %d", - mode_lib->ip.meta_chunk_size_kbytes); - DTRACE("INTERMEDIATE return_bw_mbps = %f", return_bw_mbps); - - return urgent_extra_latency_us; -} - -double dml_wm_urgent_extra_max(struct display_mode_lib *mode_lib) -{ - unsigned int total_active_dpp = DC__NUM_DPP; - unsigned int total_dcc_active_dpp = total_active_dpp; - double urgent_extra_latency_us = 0.0; - double dcfclk_mhz = 0.0; - double return_bw_mbps = 0.0; - int voltage = dm_vmin; - - /* use minimum voltage */ - return_bw_mbps = dml_socbb_return_bw_mhz(&mode_lib->soc, (enum voltage_state) voltage); - /* use minimum dcfclk */ - dcfclk_mhz = mode_lib->soc.vmin.dcfclk_mhz; - /* use max dpps and dpps with dcc */ - - urgent_extra_latency_us = urgent_extra_calc( - mode_lib, - dcfclk_mhz, - return_bw_mbps, - total_active_dpp, - total_dcc_active_dpp); - - DTRACE("urgent extra max = %f", urgent_extra_latency_us); - return urgent_extra_latency_us; -} - -double dml_wm_urgent_extra( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *pipes, - unsigned int num_pipes) -{ - unsigned int total_active_dpp = 0; - unsigned int total_dcc_active_dpp = 0; - double urgent_extra_latency_us = 0.0; - double dcfclk_mhz = 0.0; - double return_bw_mbps = 0.0; - int voltage = -1; - bool pte_enable = false; - unsigned int i; - - for (i = 0; i < num_pipes; i++) { - /* num_dpp must be greater than 0 */ - ASSERT(pipes[i].num_dpp > 0); - - /* voltage mode must be the same for all pipes */ - ASSERT(voltage == -1 || voltage == pipes[i].voltage); - voltage = pipes[i].voltage; - - /* dcfclk for all pipes must be the same */ - ASSERT(dcfclk_mhz == 0.0 || dcfclk_mhz == pipes[i].dcfclk_mhz); - dcfclk_mhz = pipes[i].dcfclk_mhz; - - total_active_dpp += pipes[i].num_dpp; - - if (pipes[i].dcc_enable) { - total_dcc_active_dpp += pipes[i].num_dpp; - } - } - - DTRACE("total active dpps %d", total_active_dpp); - DTRACE("total active dpps with dcc %d", total_dcc_active_dpp); - DTRACE("voltage state is %d", voltage); - - return_bw_mbps = calc_return_bw(mode_lib, pipes, num_pipes); - - DTRACE("return_bandwidth is %f MBps", return_bw_mbps); - - pte_enable = calc_pte_enable(pipes, num_pipes); - - /* calculate the maximum extra latency just for comparison purposes */ - /* dml_wm_urgent_extra_max(); */ - urgent_extra_latency_us = urgent_extra_calc( - mode_lib, - dcfclk_mhz, - return_bw_mbps, - total_active_dpp, - total_dcc_active_dpp); - - DTRACE("INTERMEDIATE urgent_extra_latency_us_before_pte = %f", urgent_extra_latency_us); - - if (pte_enable) { - urgent_extra_latency_us += total_active_dpp * mode_lib->ip.pte_chunk_size_kbytes - * 1024.0 / return_bw_mbps; - - DTRACE("INTERMEDIATE pte_enable = true"); - DTRACE("INTERMEDIATE total_active_dpp = %d", total_active_dpp); - DTRACE( - "INTERMEDIATE pte_chunk_size_kbytes = %d", - mode_lib->ip.pte_chunk_size_kbytes); - DTRACE("INTERMEDIATE return_bw_mbps = %f", return_bw_mbps); - } - - return urgent_extra_latency_us; -} - -double dml_wm_urgent_e2e( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *pipes, - unsigned int num_pipes) -{ - struct _vcs_dpi_wm_calc_pipe_params_st *wm = mode_lib->wm_param; - unsigned int combined_pipes; - double urgent_wm; - - memset(mode_lib->wm_param, 0, sizeof(mode_lib->wm_param)); - combined_pipes = dml_wm_e2e_to_wm(mode_lib, pipes, num_pipes, wm); - - urgent_wm = dml_wm_urgent(mode_lib, wm, combined_pipes); - - return urgent_wm; -} - -double dml_wm_urgent( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *planes, - unsigned int num_planes) -{ - double urgent_watermark; - double urgent_extra_latency_us; - double last_pixel_of_line_extra_wm_us = 0.0; - - DTRACE("calculating urgent watermark"); - calc_display_pipe_line_delivery_time(mode_lib, planes, num_planes); - urgent_extra_latency_us = dml_wm_urgent_extra(mode_lib, planes, num_planes); - - last_pixel_of_line_extra_wm_us = calc_last_pixel_of_line_extra_wm_us( - mode_lib, - planes, - num_planes); - - urgent_watermark = mode_lib->soc.urgent_latency_us + last_pixel_of_line_extra_wm_us - + urgent_extra_latency_us; - - DTRACE("INTERMEDIATE urgent_latency_us = %f", mode_lib->soc.urgent_latency_us); - DTRACE("INTERMEDIATE last_pixel_of_line_extra_wm_us = %f", last_pixel_of_line_extra_wm_us); - DTRACE("INTERMEDIATE urgent_extra_latency_us = %f", urgent_extra_latency_us); - - DTRACE("urgent_watermark_us = %f", urgent_watermark); - return urgent_watermark; -} - -double dml_wm_pte_meta_urgent(struct display_mode_lib *mode_lib, double urgent_wm_us) -{ - double val; - - val = urgent_wm_us + 2.0 * mode_lib->soc.urgent_latency_us; - DTRACE("pte_meta_urgent_watermark_us = %f", val); - - return val; -} - -double dml_wm_dcfclk_deepsleep_mhz_e2e( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *pipes, - unsigned int num_pipes) -{ - struct _vcs_dpi_wm_calc_pipe_params_st *planes = mode_lib->wm_param; - unsigned int num_planes; - double val; - - memset(mode_lib->wm_param, 0, sizeof(mode_lib->wm_param)); - num_planes = dml_wm_e2e_to_wm(mode_lib, pipes, num_pipes, planes); - - val = dml_wm_dcfclk_deepsleep_mhz(mode_lib, planes, num_planes); - - return val; -} - -double dml_wm_dcfclk_deepsleep_mhz( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *planes, - unsigned int num_planes) -{ - double val = 8.0; - unsigned int i; - - for (i = 0; i < num_planes; i++) { - calc_dcfclk_deepsleep_mhz_per_plane(mode_lib, &planes[i]); - - if (val < planes[i].dcfclk_deepsleep_mhz_per_plane) { - val = planes[i].dcfclk_deepsleep_mhz_per_plane; - } - - DTRACE("plane[%d] start", i); - DTRACE("dcfclk_deepsleep_per_plane = %f", planes[i].dcfclk_deepsleep_mhz_per_plane); - DTRACE("plane[%d] end", i); - } - - DTRACE("dcfclk_deepsleep_mhz = %f", val); - - return val; -} - -struct _vcs_dpi_cstate_pstate_watermarks_st dml_wm_cstate_pstate_e2e( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *pipes, - unsigned int num_pipes) -{ - struct _vcs_dpi_wm_calc_pipe_params_st *wm = mode_lib->wm_param; - unsigned int combined_pipes; - struct _vcs_dpi_cstate_pstate_watermarks_st cstate_pstate_wm; - - memset(mode_lib->wm_param, 0, sizeof(mode_lib->wm_param)); - combined_pipes = dml_wm_e2e_to_wm(mode_lib, pipes, num_pipes, wm); - cstate_pstate_wm = dml_wm_cstate_pstate(mode_lib, wm, combined_pipes); - - - return cstate_pstate_wm; -} - -struct _vcs_dpi_cstate_pstate_watermarks_st dml_wm_cstate_pstate( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *pipes, - unsigned int num_pipes) -{ - struct _vcs_dpi_cstate_pstate_watermarks_st wm; - double urgent_extra_latency_us; - double urgent_watermark_us; - double last_pixel_of_line_extra_wm_us; - double dcfclk_deepsleep_freq; - - DTRACE("calculating cstate and pstate watermarks"); - urgent_extra_latency_us = dml_wm_urgent_extra(mode_lib, pipes, num_pipes); - urgent_watermark_us = dml_wm_urgent(mode_lib, pipes, num_pipes); - - last_pixel_of_line_extra_wm_us = calc_last_pixel_of_line_extra_wm_us( - mode_lib, - pipes, - num_pipes); - dcfclk_deepsleep_freq = dml_wm_dcfclk_deepsleep_mhz(mode_lib, pipes, num_pipes); - - wm.cstate_exit_us = mode_lib->soc.sr_exit_time_us + last_pixel_of_line_extra_wm_us - + urgent_extra_latency_us - + mode_lib->ip.dcfclk_cstate_latency / dcfclk_deepsleep_freq; - wm.cstate_enter_plus_exit_us = mode_lib->soc.sr_enter_plus_exit_time_us - + last_pixel_of_line_extra_wm_us + urgent_extra_latency_us; - wm.pstate_change_us = mode_lib->soc.dram_clock_change_latency_us + urgent_watermark_us; - - DTRACE("stutter_exit_watermark_us = %f", wm.cstate_exit_us); - DTRACE("stutter_enter_plus_exit_watermark_us = %f", wm.cstate_enter_plus_exit_us); - DTRACE("dram_clock_change_watermark_us = %f", wm.pstate_change_us); - - return wm; -} - -double dml_wm_writeback_pstate_e2e( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *pipes, - unsigned int num_pipes) -{ - struct _vcs_dpi_wm_calc_pipe_params_st *wm = mode_lib->wm_param; - unsigned int combined_pipes; - - memset(mode_lib->wm_param, 0, sizeof(mode_lib->wm_param)); - combined_pipes = dml_wm_e2e_to_wm(mode_lib, pipes, num_pipes, wm); - - - return dml_wm_writeback_pstate(mode_lib, wm, combined_pipes); -} - -double dml_wm_writeback_pstate( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *pipes, - unsigned int num_pipes) -{ - unsigned int total_active_wb = 0; - double wm = 0.0; - double socclk_mhz = 0.0; - unsigned int i; - - DTRACE("calculating wb pstate watermark"); - for (i = 0; i < num_pipes; i++) { - if (pipes[i].output_type == dm_wb) - total_active_wb++; - ASSERT(socclk_mhz == 0.0 || socclk_mhz == pipes[i].socclk_mhz); - socclk_mhz = pipes[i].socclk_mhz; - } - - DTRACE("total wb outputs %d", total_active_wb); - DTRACE("socclk frequency %f Mhz", socclk_mhz); - - if (total_active_wb <= 1) { - wm = mode_lib->soc.writeback_dram_clock_change_latency_us; - } else { - wm = mode_lib->soc.writeback_dram_clock_change_latency_us - + (mode_lib->ip.writeback_chunk_size_kbytes * 1024.0) / 32.0 - / socclk_mhz; - } - - DTRACE("wb pstate watermark %f us", wm); - return wm; -} - -unsigned int dml_wm_e2e_to_wm( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - unsigned int num_pipes, - struct _vcs_dpi_wm_calc_pipe_params_st *wm) -{ - unsigned int num_planes = 0; - bool visited[DC__NUM_PIPES]; - unsigned int i, j; - - for (i = 0; i < num_pipes; i++) { - visited[i] = false; - } - - for (i = 0; i < num_pipes; i++) { - unsigned int num_dpp = 1; - - if (visited[i]) { - continue; - } - - visited[i] = true; - - if (e2e[i].pipe.src.is_hsplit) { - for (j = i + 1; j < num_pipes; j++) { - if (e2e[j].pipe.src.is_hsplit && !visited[j] - && (e2e[i].pipe.src.hsplit_grp - == e2e[j].pipe.src.hsplit_grp)) { - num_dpp++; - visited[j] = true; - } - } - } - - wm[num_planes].num_dpp = num_dpp; - wm[num_planes].voltage = e2e[i].clks_cfg.voltage; - wm[num_planes].output_type = e2e[i].dout.output_type; - wm[num_planes].dcfclk_mhz = e2e[i].clks_cfg.dcfclk_mhz; - wm[num_planes].socclk_mhz = e2e[i].clks_cfg.socclk_mhz; - wm[num_planes].dppclk_mhz = e2e[i].clks_cfg.dppclk_mhz; - wm[num_planes].pixclk_mhz = e2e[i].pipe.dest.pixel_rate_mhz; - - wm[num_planes].pte_enable = e2e[i].pipe.src.vm; - wm[num_planes].dcc_enable = e2e[i].pipe.src.dcc; - wm[num_planes].dcc_rate = e2e[i].pipe.src.dcc_rate; - - get_bytes_per_pixel( - (enum source_format_class) e2e[i].pipe.src.source_format, - &wm[num_planes]); - wm[num_planes].swath_width_y = get_swath_width_y(&e2e[i].pipe.src, num_dpp); - get_swath_height( - mode_lib, - &e2e[i].pipe.src, - &wm[num_planes], - wm[num_planes].swath_width_y); - - wm[num_planes].interlace_en = e2e[i].pipe.dest.interlaced; - wm[num_planes].h_ratio = e2e[i].pipe.scale_ratio_depth.hscl_ratio; - wm[num_planes].v_ratio = e2e[i].pipe.scale_ratio_depth.vscl_ratio; - if (wm[num_planes].interlace_en) { - wm[num_planes].v_ratio = 2 * wm[num_planes].v_ratio; - } - wm[num_planes].h_taps = e2e[i].pipe.scale_taps.htaps; - wm[num_planes].h_total = e2e[i].pipe.dest.htotal; - wm[num_planes].v_total = e2e[i].pipe.dest.vtotal; - wm[num_planes].v_active = e2e[i].pipe.dest.vactive; - wm[num_planes].e2e_index = i; - num_planes++; - } - - for (i = 0; i < num_planes; i++) { - DTRACE("plane[%d] start", i); - DTRACE("voltage = %d", wm[i].voltage); - DTRACE("v_active = %d", wm[i].v_active); - DTRACE("h_total = %d", wm[i].h_total); - DTRACE("v_total = %d", wm[i].v_total); - DTRACE("pixclk_mhz = %f", wm[i].pixclk_mhz); - DTRACE("dcfclk_mhz = %f", wm[i].dcfclk_mhz); - DTRACE("dppclk_mhz = %f", wm[i].dppclk_mhz); - DTRACE("h_ratio = %f", wm[i].h_ratio); - DTRACE("v_ratio = %f", wm[i].v_ratio); - DTRACE("interlaced = %d", wm[i].interlace_en); - DTRACE("h_taps = %d", wm[i].h_taps); - DTRACE("num_dpp = %d", wm[i].num_dpp); - DTRACE("swath_width_y = %d", wm[i].swath_width_y); - DTRACE("swath_height_y = %d", wm[i].swath_height_y); - DTRACE("swath_height_c = %d", wm[i].swath_height_c); - DTRACE("det_buffer_size_y = %d", wm[i].det_buffer_size_y); - DTRACE("dcc_rate = %f", wm[i].dcc_rate); - DTRACE("dcc_enable = %s", wm[i].dcc_enable ? "true" : "false"); - DTRACE("pte_enable = %s", wm[i].pte_enable ? "true" : "false"); - DTRACE("plane[%d] end", i); - } - - return num_planes; -} diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_watermark.h b/drivers/gpu/drm/amd/display/dc/dml/display_watermark.h deleted file mode 100644 index 94cde8b55e08..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dml/display_watermark.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright 2017 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ -#ifndef __DISPLAY_WATERMARK_H__ -#define __DISPLAY_WATERMARK_H__ - -#include "dml_common_defs.h" - -struct display_mode_lib; - -double dml_wm_urgent_extra( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *pipes, - unsigned int num_pipes); -double dml_wm_urgent_extra_max(struct display_mode_lib *mode_lib); - -double dml_wm_urgent_e2e( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *pipes, - unsigned int num_pipes); -double dml_wm_urgent( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *planes, - unsigned int num_planes); -double dml_wm_pte_meta_urgent(struct display_mode_lib *mode_lib, double urgent_wm_us); -double dml_wm_dcfclk_deepsleep_mhz_e2e( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *pipes, - unsigned int num_pipes); -double dml_wm_dcfclk_deepsleep_mhz( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *planes, - unsigned int num_planes); - -struct _vcs_dpi_cstate_pstate_watermarks_st dml_wm_cstate_pstate_e2e( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *pipes, - unsigned int num_pipes); -struct _vcs_dpi_cstate_pstate_watermarks_st dml_wm_cstate_pstate( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *pipes, - unsigned int num_pipes); - -double dml_wm_writeback_pstate_e2e( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *pipes, - unsigned int num_pipes); -double dml_wm_writeback_pstate( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *pipes, - unsigned int num_pipes); - -double dml_wm_expected_stutter_eff_e2e( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - unsigned int num_pipes); -double dml_wm_expected_stutter_eff_e2e_with_vblank( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - unsigned int num_pipes); - -unsigned int dml_wm_e2e_to_wm( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - unsigned int num_pipes, - struct _vcs_dpi_wm_calc_pipe_params_st *wm); - -double dml_wm_calc_total_data_read_bw( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *planes, - unsigned int num_planes); -double dml_wm_calc_return_bw( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *planes, - unsigned int num_planes); - -#endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c b/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c new file mode 100644 index 000000000000..8229f782260b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c @@ -0,0 +1,1903 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dml1_display_rq_dlg_calc.h" +#include "display_mode_lib.h" + +static unsigned int get_bytes_per_element(enum source_format_class source_format, bool is_chroma) +{ + unsigned int ret_val = 0; + + if (source_format == dm_444_16) { + if (!is_chroma) + ret_val = 2; + } else if (source_format == dm_444_32) { + if (!is_chroma) + ret_val = 4; + } else if (source_format == dm_444_64) { + if (!is_chroma) + ret_val = 8; + } else if (source_format == dm_420_8) { + if (is_chroma) + ret_val = 2; + else + ret_val = 1; + } else if (source_format == dm_420_10) { + if (is_chroma) + ret_val = 4; + else + ret_val = 2; + } + return ret_val; +} + +static bool is_dual_plane(enum source_format_class source_format) +{ + bool ret_val = 0; + + if ((source_format == dm_420_8) || (source_format == dm_420_10)) + ret_val = 1; + + return ret_val; +} + +static void get_blk256_size( + unsigned int *blk256_width, + unsigned int *blk256_height, + unsigned int bytes_per_element) +{ + if (bytes_per_element == 1) { + *blk256_width = 16; + *blk256_height = 16; + } else if (bytes_per_element == 2) { + *blk256_width = 16; + *blk256_height = 8; + } else if (bytes_per_element == 4) { + *blk256_width = 8; + *blk256_height = 8; + } else if (bytes_per_element == 8) { + *blk256_width = 8; + *blk256_height = 4; + } +} + +static double get_refcyc_per_delivery( + struct display_mode_lib *mode_lib, + double refclk_freq_in_mhz, + double pclk_freq_in_mhz, + unsigned int recout_width, + double vratio, + double hscale_pixel_rate, + unsigned int delivery_width, + unsigned int req_per_swath_ub) +{ + double refcyc_per_delivery = 0.0; + + if (vratio <= 1.0) { + refcyc_per_delivery = (double) refclk_freq_in_mhz * (double) recout_width + / pclk_freq_in_mhz / (double) req_per_swath_ub; + } else { + refcyc_per_delivery = (double) refclk_freq_in_mhz * (double) delivery_width + / (double) hscale_pixel_rate / (double) req_per_swath_ub; + } + + DTRACE("DLG: %s: refclk_freq_in_mhz = %3.2f", __func__, refclk_freq_in_mhz); + DTRACE("DLG: %s: pclk_freq_in_mhz = %3.2f", __func__, pclk_freq_in_mhz); + DTRACE("DLG: %s: recout_width = %d", __func__, recout_width); + DTRACE("DLG: %s: vratio = %3.2f", __func__, vratio); + DTRACE("DLG: %s: req_per_swath_ub = %d", __func__, req_per_swath_ub); + DTRACE("DLG: %s: refcyc_per_delivery= %3.2f", __func__, refcyc_per_delivery); + + return refcyc_per_delivery; + +} + +static double get_vratio_pre( + struct display_mode_lib *mode_lib, + unsigned int max_num_sw, + unsigned int max_partial_sw, + unsigned int swath_height, + double vinit, + double l_sw) +{ + double prefill = dml_floor(vinit, 1); + double vratio_pre = 1.0; + + vratio_pre = (max_num_sw * swath_height + max_partial_sw) / l_sw; + + if (swath_height > 4) { + double tmp0 = (max_num_sw * swath_height) / (l_sw - (prefill - 3.0) / 2.0); + + if (tmp0 > vratio_pre) + vratio_pre = tmp0; + } + + DTRACE("DLG: %s: max_num_sw = %0d", __func__, max_num_sw); + DTRACE("DLG: %s: max_partial_sw = %0d", __func__, max_partial_sw); + DTRACE("DLG: %s: swath_height = %0d", __func__, swath_height); + DTRACE("DLG: %s: vinit = %3.2f", __func__, vinit); + DTRACE("DLG: %s: vratio_pre = %3.2f", __func__, vratio_pre); + + if (vratio_pre < 1.0) { + DTRACE("WARNING_DLG: %s: vratio_pre=%3.2f < 1.0, set to 1.0", __func__, vratio_pre); + vratio_pre = 1.0; + } + + if (vratio_pre > 4.0) { + DTRACE( + "WARNING_DLG: %s: vratio_pre=%3.2f > 4.0 (max scaling ratio). set to 4.0", + __func__, + vratio_pre); + vratio_pre = 4.0; + } + + return vratio_pre; +} + +static void get_swath_need( + struct display_mode_lib *mode_lib, + unsigned int *max_num_sw, + unsigned int *max_partial_sw, + unsigned int swath_height, + double vinit) +{ + double prefill = dml_floor(vinit, 1); + unsigned int max_partial_sw_int; + + DTRACE("DLG: %s: swath_height = %0d", __func__, swath_height); + DTRACE("DLG: %s: vinit = %3.2f", __func__, vinit); + + ASSERT(prefill > 0.0 && prefill <= 8.0); + + *max_num_sw = (unsigned int) (dml_ceil((prefill - 1.0) / (double) swath_height, 1) + 1.0); /* prefill has to be >= 1 */ + max_partial_sw_int = + (prefill == 1) ? + (swath_height - 1) : + ((unsigned int) (prefill - 2.0) % swath_height); + *max_partial_sw = (max_partial_sw_int < 1) ? 1 : max_partial_sw_int; /* ensure minimum of 1 is used */ + + DTRACE("DLG: %s: max_num_sw = %0d", __func__, *max_num_sw); + DTRACE("DLG: %s: max_partial_sw = %0d", __func__, *max_partial_sw); +} + +static unsigned int get_blk_size_bytes(const enum source_macro_tile_size tile_size) +{ + if (tile_size == dm_256k_tile) + return (256 * 1024); + else if (tile_size == dm_64k_tile) + return (64 * 1024); + else + return (4 * 1024); +} + +static void extract_rq_sizing_regs( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_data_rq_regs_st *rq_regs, + const struct _vcs_dpi_display_data_rq_sizing_params_st rq_sizing) +{ + DTRACE("DLG: %s: rq_sizing param", __func__); + print__data_rq_sizing_params_st(mode_lib, rq_sizing); + + rq_regs->chunk_size = dml_log2(rq_sizing.chunk_bytes) - 10; + + if (rq_sizing.min_chunk_bytes == 0) + rq_regs->min_chunk_size = 0; + else + rq_regs->min_chunk_size = dml_log2(rq_sizing.min_chunk_bytes) - 8 + 1; + + rq_regs->meta_chunk_size = dml_log2(rq_sizing.meta_chunk_bytes) - 10; + if (rq_sizing.min_meta_chunk_bytes == 0) + rq_regs->min_meta_chunk_size = 0; + else + rq_regs->min_meta_chunk_size = dml_log2(rq_sizing.min_meta_chunk_bytes) - 6 + 1; + + rq_regs->dpte_group_size = dml_log2(rq_sizing.dpte_group_bytes) - 6; + rq_regs->mpte_group_size = dml_log2(rq_sizing.mpte_group_bytes) - 6; +} + +void dml1_extract_rq_regs( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_regs_st *rq_regs, + const struct _vcs_dpi_display_rq_params_st rq_param) +{ + unsigned int detile_buf_size_in_bytes = mode_lib->ip.det_buffer_size_kbytes * 1024; + unsigned int detile_buf_plane1_addr = 0; + + extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_l), rq_param.sizing.rq_l); + if (rq_param.yuv420) + extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_c), rq_param.sizing.rq_c); + + rq_regs->rq_regs_l.swath_height = dml_log2(rq_param.dlg.rq_l.swath_height); + rq_regs->rq_regs_c.swath_height = dml_log2(rq_param.dlg.rq_c.swath_height); + + /* FIXME: take the max between luma, chroma chunk size? + * okay for now, as we are setting chunk_bytes to 8kb anyways + */ + if (rq_param.sizing.rq_l.chunk_bytes >= 32 * 1024) { /*32kb */ + rq_regs->drq_expansion_mode = 0; + } else { + rq_regs->drq_expansion_mode = 2; + } + rq_regs->prq_expansion_mode = 1; + rq_regs->mrq_expansion_mode = 1; + rq_regs->crq_expansion_mode = 1; + + if (rq_param.yuv420) { + if ((double) rq_param.misc.rq_l.stored_swath_bytes + / (double) rq_param.misc.rq_c.stored_swath_bytes <= 1.5) { + detile_buf_plane1_addr = (detile_buf_size_in_bytes / 2.0 / 64.0); /* half to chroma */ + } else { + detile_buf_plane1_addr = dml_round_to_multiple( + (unsigned int) ((2.0 * detile_buf_size_in_bytes) / 3.0), + 256, + 0) / 64.0; /* 2/3 to chroma */ + } + } + rq_regs->plane1_base_address = detile_buf_plane1_addr; +} + +static void handle_det_buf_split( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_params_st *rq_param, + const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param) +{ + unsigned int total_swath_bytes = 0; + unsigned int swath_bytes_l = 0; + unsigned int swath_bytes_c = 0; + unsigned int full_swath_bytes_packed_l = 0; + unsigned int full_swath_bytes_packed_c = 0; + bool req128_l = 0; + bool req128_c = 0; + bool surf_linear = (pipe_src_param.sw_mode == dm_sw_linear); + bool surf_vert = (pipe_src_param.source_scan == dm_vert); + unsigned int log2_swath_height_l = 0; + unsigned int log2_swath_height_c = 0; + unsigned int detile_buf_size_in_bytes = mode_lib->ip.det_buffer_size_kbytes * 1024; + + full_swath_bytes_packed_l = rq_param->misc.rq_l.full_swath_bytes; + full_swath_bytes_packed_c = rq_param->misc.rq_c.full_swath_bytes; + + if (rq_param->yuv420_10bpc) { + full_swath_bytes_packed_l = dml_round_to_multiple( + rq_param->misc.rq_l.full_swath_bytes * 2 / 3, + 256, + 1) + 256; + full_swath_bytes_packed_c = dml_round_to_multiple( + rq_param->misc.rq_c.full_swath_bytes * 2 / 3, + 256, + 1) + 256; + } + + if (rq_param->yuv420) { + total_swath_bytes = 2 * full_swath_bytes_packed_l + 2 * full_swath_bytes_packed_c; + + if (total_swath_bytes <= detile_buf_size_in_bytes) { /*full 256b request */ + req128_l = 0; + req128_c = 0; + swath_bytes_l = full_swath_bytes_packed_l; + swath_bytes_c = full_swath_bytes_packed_c; + } else { /*128b request (for luma only for yuv420 8bpc) */ + req128_l = 1; + req128_c = 0; + swath_bytes_l = full_swath_bytes_packed_l / 2; + swath_bytes_c = full_swath_bytes_packed_c; + } + + /* Bug workaround, luma and chroma req size needs to be the same. (see: DEGVIDCN10-137) + * TODO: Remove after rtl fix + */ + if (req128_l == 1) { + req128_c = 1; + DTRACE("DLG: %s: bug workaround DEGVIDCN10-137", __func__); + } + + /* Note: assumption, the config that pass in will fit into + * the detiled buffer. + */ + } else { + total_swath_bytes = 2 * full_swath_bytes_packed_l; + + if (total_swath_bytes <= detile_buf_size_in_bytes) + req128_l = 0; + else + req128_l = 1; + + swath_bytes_l = total_swath_bytes; + swath_bytes_c = 0; + } + rq_param->misc.rq_l.stored_swath_bytes = swath_bytes_l; + rq_param->misc.rq_c.stored_swath_bytes = swath_bytes_c; + + if (surf_linear) { + log2_swath_height_l = 0; + log2_swath_height_c = 0; + } else if (!surf_vert) { + log2_swath_height_l = dml_log2(rq_param->misc.rq_l.blk256_height) - req128_l; + log2_swath_height_c = dml_log2(rq_param->misc.rq_c.blk256_height) - req128_c; + } else { + log2_swath_height_l = dml_log2(rq_param->misc.rq_l.blk256_width) - req128_l; + log2_swath_height_c = dml_log2(rq_param->misc.rq_c.blk256_width) - req128_c; + } + rq_param->dlg.rq_l.swath_height = 1 << log2_swath_height_l; + rq_param->dlg.rq_c.swath_height = 1 << log2_swath_height_c; + + DTRACE("DLG: %s: req128_l = %0d", __func__, req128_l); + DTRACE("DLG: %s: req128_c = %0d", __func__, req128_c); + DTRACE("DLG: %s: full_swath_bytes_packed_l = %0d", __func__, full_swath_bytes_packed_l); + DTRACE("DLG: %s: full_swath_bytes_packed_c = %0d", __func__, full_swath_bytes_packed_c); +} + +/* Need refactor. */ +static void dml1_rq_dlg_get_row_heights( + struct display_mode_lib *mode_lib, + unsigned int *o_dpte_row_height, + unsigned int *o_meta_row_height, + unsigned int vp_width, + unsigned int data_pitch, + int source_format, + int tiling, + int macro_tile_size, + int source_scan, + int is_chroma) +{ + bool surf_linear = (tiling == dm_sw_linear); + bool surf_vert = (source_scan == dm_vert); + + unsigned int bytes_per_element = get_bytes_per_element( + (enum source_format_class) source_format, + is_chroma); + unsigned int log2_bytes_per_element = dml_log2(bytes_per_element); + unsigned int blk256_width = 0; + unsigned int blk256_height = 0; + + unsigned int log2_blk256_height; + unsigned int blk_bytes; + unsigned int log2_blk_bytes; + unsigned int log2_blk_height; + unsigned int log2_blk_width; + unsigned int log2_meta_req_bytes; + unsigned int log2_meta_req_height; + unsigned int log2_meta_req_width; + unsigned int log2_meta_row_height; + unsigned int log2_vmpg_bytes; + unsigned int dpte_buf_in_pte_reqs; + unsigned int log2_vmpg_height; + unsigned int log2_vmpg_width; + unsigned int log2_dpte_req_height_ptes; + unsigned int log2_dpte_req_width_ptes; + unsigned int log2_dpte_req_height; + unsigned int log2_dpte_req_width; + unsigned int log2_dpte_row_height_linear; + unsigned int log2_dpte_row_height; + unsigned int dpte_req_width; + + if (surf_linear) { + blk256_width = 256; + blk256_height = 1; + } else { + get_blk256_size(&blk256_width, &blk256_height, bytes_per_element); + } + + log2_blk256_height = dml_log2((double) blk256_height); + blk_bytes = surf_linear ? + 256 : get_blk_size_bytes((enum source_macro_tile_size) macro_tile_size); + log2_blk_bytes = dml_log2((double) blk_bytes); + log2_blk_height = 0; + log2_blk_width = 0; + + /* remember log rule + * "+" in log is multiply + * "-" in log is divide + * "/2" is like square root + * blk is vertical biased + */ + if (tiling != dm_sw_linear) + log2_blk_height = log2_blk256_height + + dml_ceil((double) (log2_blk_bytes - 8) / 2.0, 1); + else + log2_blk_height = 0; /* blk height of 1 */ + + log2_blk_width = log2_blk_bytes - log2_bytes_per_element - log2_blk_height; + + /* ------- */ + /* meta */ + /* ------- */ + log2_meta_req_bytes = 6; /* meta request is 64b and is 8x8byte meta element */ + + /* each 64b meta request for dcn is 8x8 meta elements and + * a meta element covers one 256b block of the the data surface. + */ + log2_meta_req_height = log2_blk256_height + 3; /* meta req is 8x8 */ + log2_meta_req_width = log2_meta_req_bytes + 8 - log2_bytes_per_element + - log2_meta_req_height; + log2_meta_row_height = 0; + + /* the dimensions of a meta row are meta_row_width x meta_row_height in elements. + * calculate upper bound of the meta_row_width + */ + if (!surf_vert) + log2_meta_row_height = log2_meta_req_height; + else + log2_meta_row_height = log2_meta_req_width; + + *o_meta_row_height = 1 << log2_meta_row_height; + + /* ------ */ + /* dpte */ + /* ------ */ + log2_vmpg_bytes = dml_log2(mode_lib->soc.vmm_page_size_bytes); + dpte_buf_in_pte_reqs = mode_lib->ip.dpte_buffer_size_in_pte_reqs; + + log2_vmpg_height = 0; + log2_vmpg_width = 0; + log2_dpte_req_height_ptes = 0; + log2_dpte_req_width_ptes = 0; + log2_dpte_req_height = 0; + log2_dpte_req_width = 0; + log2_dpte_row_height_linear = 0; + log2_dpte_row_height = 0; + dpte_req_width = 0; /* 64b dpte req width in data element */ + + if (surf_linear) + log2_vmpg_height = 0; /* one line high */ + else + log2_vmpg_height = (log2_vmpg_bytes - 8) / 2 + log2_blk256_height; + log2_vmpg_width = log2_vmpg_bytes - log2_bytes_per_element - log2_vmpg_height; + + /* only 3 possible shapes for dpte request in dimensions of ptes: 8x1, 4x2, 2x4. */ + if (log2_blk_bytes <= log2_vmpg_bytes) + log2_dpte_req_height_ptes = 0; + else if (log2_blk_height - log2_vmpg_height >= 2) + log2_dpte_req_height_ptes = 2; + else + log2_dpte_req_height_ptes = log2_blk_height - log2_vmpg_height; + log2_dpte_req_width_ptes = 3 - log2_dpte_req_height_ptes; + + ASSERT((log2_dpte_req_width_ptes == 3 && log2_dpte_req_height_ptes == 0) || /* 8x1 */ + (log2_dpte_req_width_ptes == 2 && log2_dpte_req_height_ptes == 1) || /* 4x2 */ + (log2_dpte_req_width_ptes == 1 && log2_dpte_req_height_ptes == 2)); /* 2x4 */ + + /* the dpte request dimensions in data elements is dpte_req_width x dpte_req_height + * log2_wmpg_width is how much 1 pte represent, now trying to calculate how much 64b pte req represent + */ + log2_dpte_req_height = log2_vmpg_height + log2_dpte_req_height_ptes; + log2_dpte_req_width = log2_vmpg_width + log2_dpte_req_width_ptes; + dpte_req_width = 1 << log2_dpte_req_width; + + /* calculate pitch dpte row buffer can hold + * round the result down to a power of two. + */ + if (surf_linear) { + log2_dpte_row_height_linear = dml_floor( + dml_log2(dpte_buf_in_pte_reqs * dpte_req_width / data_pitch), + 1); + + ASSERT(log2_dpte_row_height_linear >= 3); + + if (log2_dpte_row_height_linear > 7) + log2_dpte_row_height_linear = 7; + + log2_dpte_row_height = log2_dpte_row_height_linear; + } else { + /* the upper bound of the dpte_row_width without dependency on viewport position follows. */ + if (!surf_vert) + log2_dpte_row_height = log2_dpte_req_height; + else + log2_dpte_row_height = + (log2_blk_width < log2_dpte_req_width) ? + log2_blk_width : log2_dpte_req_width; + } + + /* From programming guide: + * There is a special case of saving only half of ptes returned due to buffer space limits. + * this case applies to 4 and 8bpe in horizontal access of a vp_width greater than 2560+16 + * when the pte request is 2x4 ptes (which happens when vmpg_bytes =4kb and tile blk_bytes >=64kb). + */ + if (!surf_vert && vp_width > (2560 + 16) && bytes_per_element >= 4 && log2_vmpg_bytes == 12 + && log2_blk_bytes >= 16) + log2_dpte_row_height = log2_dpte_row_height - 1; /*half of the full height */ + + *o_dpte_row_height = 1 << log2_dpte_row_height; +} + +static void get_surf_rq_param( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_data_rq_sizing_params_st *rq_sizing_param, + struct _vcs_dpi_display_data_rq_dlg_params_st *rq_dlg_param, + struct _vcs_dpi_display_data_rq_misc_params_st *rq_misc_param, + const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param, + bool is_chroma) +{ + bool mode_422 = 0; + unsigned int vp_width = 0; + unsigned int vp_height = 0; + unsigned int data_pitch = 0; + unsigned int meta_pitch = 0; + unsigned int ppe = mode_422 ? 2 : 1; + bool surf_linear; + bool surf_vert; + unsigned int bytes_per_element; + unsigned int log2_bytes_per_element; + unsigned int blk256_width; + unsigned int blk256_height; + unsigned int log2_blk256_width; + unsigned int log2_blk256_height; + unsigned int blk_bytes; + unsigned int log2_blk_bytes; + unsigned int log2_blk_height; + unsigned int log2_blk_width; + unsigned int log2_meta_req_bytes; + unsigned int log2_meta_req_height; + unsigned int log2_meta_req_width; + unsigned int meta_req_width; + unsigned int meta_req_height; + unsigned int log2_meta_row_height; + unsigned int meta_row_width_ub; + unsigned int log2_meta_chunk_bytes; + unsigned int log2_meta_chunk_height; + unsigned int log2_meta_chunk_width; + unsigned int log2_min_meta_chunk_bytes; + unsigned int min_meta_chunk_width; + unsigned int meta_chunk_width; + unsigned int meta_chunk_per_row_int; + unsigned int meta_row_remainder; + unsigned int meta_chunk_threshold; + unsigned int meta_blk_bytes; + unsigned int meta_blk_height; + unsigned int meta_blk_width; + unsigned int meta_surface_bytes; + unsigned int vmpg_bytes; + unsigned int meta_pte_req_per_frame_ub; + unsigned int meta_pte_bytes_per_frame_ub; + unsigned int log2_vmpg_bytes; + unsigned int dpte_buf_in_pte_reqs; + unsigned int log2_vmpg_height; + unsigned int log2_vmpg_width; + unsigned int log2_dpte_req_height_ptes; + unsigned int log2_dpte_req_width_ptes; + unsigned int log2_dpte_req_height; + unsigned int log2_dpte_req_width; + unsigned int log2_dpte_row_height_linear; + unsigned int log2_dpte_row_height; + unsigned int log2_dpte_group_width; + unsigned int dpte_row_width_ub; + unsigned int dpte_row_height; + unsigned int dpte_req_height; + unsigned int dpte_req_width; + unsigned int dpte_group_width; + unsigned int log2_dpte_group_bytes; + unsigned int log2_dpte_group_length; + unsigned int func_meta_row_height, func_dpte_row_height; + + /* FIXME check if ppe apply for both luma and chroma in 422 case */ + if (is_chroma) { + vp_width = pipe_src_param.viewport_width_c / ppe; + vp_height = pipe_src_param.viewport_height_c; + data_pitch = pipe_src_param.data_pitch_c; + meta_pitch = pipe_src_param.meta_pitch_c; + } else { + vp_width = pipe_src_param.viewport_width / ppe; + vp_height = pipe_src_param.viewport_height; + data_pitch = pipe_src_param.data_pitch; + meta_pitch = pipe_src_param.meta_pitch; + } + + rq_sizing_param->chunk_bytes = 8192; + + if (rq_sizing_param->chunk_bytes == 64 * 1024) + rq_sizing_param->min_chunk_bytes = 0; + else + rq_sizing_param->min_chunk_bytes = 1024; + + rq_sizing_param->meta_chunk_bytes = 2048; + rq_sizing_param->min_meta_chunk_bytes = 256; + + rq_sizing_param->mpte_group_bytes = 2048; + + surf_linear = (pipe_src_param.sw_mode == dm_sw_linear); + surf_vert = (pipe_src_param.source_scan == dm_vert); + + bytes_per_element = get_bytes_per_element( + (enum source_format_class) pipe_src_param.source_format, + is_chroma); + log2_bytes_per_element = dml_log2(bytes_per_element); + blk256_width = 0; + blk256_height = 0; + + if (surf_linear) { + blk256_width = 256 / bytes_per_element; + blk256_height = 1; + } else { + get_blk256_size(&blk256_width, &blk256_height, bytes_per_element); + } + + DTRACE("DLG: %s: surf_linear = %d", __func__, surf_linear); + DTRACE("DLG: %s: surf_vert = %d", __func__, surf_vert); + DTRACE("DLG: %s: blk256_width = %d", __func__, blk256_width); + DTRACE("DLG: %s: blk256_height = %d", __func__, blk256_height); + + log2_blk256_width = dml_log2((double) blk256_width); + log2_blk256_height = dml_log2((double) blk256_height); + blk_bytes = + surf_linear ? 256 : get_blk_size_bytes( + (enum source_macro_tile_size) pipe_src_param.macro_tile_size); + log2_blk_bytes = dml_log2((double) blk_bytes); + log2_blk_height = 0; + log2_blk_width = 0; + + /* remember log rule + * "+" in log is multiply + * "-" in log is divide + * "/2" is like square root + * blk is vertical biased + */ + if (pipe_src_param.sw_mode != dm_sw_linear) + log2_blk_height = log2_blk256_height + + dml_ceil((double) (log2_blk_bytes - 8) / 2.0, 1); + else + log2_blk_height = 0; /* blk height of 1 */ + + log2_blk_width = log2_blk_bytes - log2_bytes_per_element - log2_blk_height; + + if (!surf_vert) { + rq_dlg_param->swath_width_ub = dml_round_to_multiple(vp_width - 1, blk256_width, 1) + + blk256_width; + rq_dlg_param->req_per_swath_ub = rq_dlg_param->swath_width_ub >> log2_blk256_width; + } else { + rq_dlg_param->swath_width_ub = dml_round_to_multiple( + vp_height - 1, + blk256_height, + 1) + blk256_height; + rq_dlg_param->req_per_swath_ub = rq_dlg_param->swath_width_ub >> log2_blk256_height; + } + + if (!surf_vert) + rq_misc_param->full_swath_bytes = rq_dlg_param->swath_width_ub * blk256_height + * bytes_per_element; + else + rq_misc_param->full_swath_bytes = rq_dlg_param->swath_width_ub * blk256_width + * bytes_per_element; + + rq_misc_param->blk256_height = blk256_height; + rq_misc_param->blk256_width = blk256_width; + + /* ------- */ + /* meta */ + /* ------- */ + log2_meta_req_bytes = 6; /* meta request is 64b and is 8x8byte meta element */ + + /* each 64b meta request for dcn is 8x8 meta elements and + * a meta element covers one 256b block of the the data surface. + */ + log2_meta_req_height = log2_blk256_height + 3; /* meta req is 8x8 byte, each byte represent 1 blk256 */ + log2_meta_req_width = log2_meta_req_bytes + 8 - log2_bytes_per_element + - log2_meta_req_height; + meta_req_width = 1 << log2_meta_req_width; + meta_req_height = 1 << log2_meta_req_height; + log2_meta_row_height = 0; + meta_row_width_ub = 0; + + /* the dimensions of a meta row are meta_row_width x meta_row_height in elements. + * calculate upper bound of the meta_row_width + */ + if (!surf_vert) { + log2_meta_row_height = log2_meta_req_height; + meta_row_width_ub = dml_round_to_multiple(vp_width - 1, meta_req_width, 1) + + meta_req_width; + rq_dlg_param->meta_req_per_row_ub = meta_row_width_ub / meta_req_width; + } else { + log2_meta_row_height = log2_meta_req_width; + meta_row_width_ub = dml_round_to_multiple(vp_height - 1, meta_req_height, 1) + + meta_req_height; + rq_dlg_param->meta_req_per_row_ub = meta_row_width_ub / meta_req_height; + } + rq_dlg_param->meta_bytes_per_row_ub = rq_dlg_param->meta_req_per_row_ub * 64; + + log2_meta_chunk_bytes = dml_log2(rq_sizing_param->meta_chunk_bytes); + log2_meta_chunk_height = log2_meta_row_height; + + /*full sized meta chunk width in unit of data elements */ + log2_meta_chunk_width = log2_meta_chunk_bytes + 8 - log2_bytes_per_element + - log2_meta_chunk_height; + log2_min_meta_chunk_bytes = dml_log2(rq_sizing_param->min_meta_chunk_bytes); + min_meta_chunk_width = 1 + << (log2_min_meta_chunk_bytes + 8 - log2_bytes_per_element + - log2_meta_chunk_height); + meta_chunk_width = 1 << log2_meta_chunk_width; + meta_chunk_per_row_int = (unsigned int) (meta_row_width_ub / meta_chunk_width); + meta_row_remainder = meta_row_width_ub % meta_chunk_width; + meta_chunk_threshold = 0; + meta_blk_bytes = 4096; + meta_blk_height = blk256_height * 64; + meta_blk_width = meta_blk_bytes * 256 / bytes_per_element / meta_blk_height; + meta_surface_bytes = meta_pitch + * (dml_round_to_multiple(vp_height - 1, meta_blk_height, 1) + + meta_blk_height) * bytes_per_element / 256; + vmpg_bytes = mode_lib->soc.vmm_page_size_bytes; + meta_pte_req_per_frame_ub = (dml_round_to_multiple( + meta_surface_bytes - vmpg_bytes, + 8 * vmpg_bytes, + 1) + 8 * vmpg_bytes) / (8 * vmpg_bytes); + meta_pte_bytes_per_frame_ub = meta_pte_req_per_frame_ub * 64; /*64B mpte request */ + rq_dlg_param->meta_pte_bytes_per_frame_ub = meta_pte_bytes_per_frame_ub; + + DTRACE("DLG: %s: meta_blk_height = %d", __func__, meta_blk_height); + DTRACE("DLG: %s: meta_blk_width = %d", __func__, meta_blk_width); + DTRACE("DLG: %s: meta_surface_bytes = %d", __func__, meta_surface_bytes); + DTRACE("DLG: %s: meta_pte_req_per_frame_ub = %d", __func__, meta_pte_req_per_frame_ub); + DTRACE("DLG: %s: meta_pte_bytes_per_frame_ub = %d", __func__, meta_pte_bytes_per_frame_ub); + + if (!surf_vert) + meta_chunk_threshold = 2 * min_meta_chunk_width - meta_req_width; + else + meta_chunk_threshold = 2 * min_meta_chunk_width - meta_req_height; + + if (meta_row_remainder <= meta_chunk_threshold) + rq_dlg_param->meta_chunks_per_row_ub = meta_chunk_per_row_int + 1; + else + rq_dlg_param->meta_chunks_per_row_ub = meta_chunk_per_row_int + 2; + + rq_dlg_param->meta_row_height = 1 << log2_meta_row_height; + + /* ------ */ + /* dpte */ + /* ------ */ + log2_vmpg_bytes = dml_log2(mode_lib->soc.vmm_page_size_bytes); + dpte_buf_in_pte_reqs = mode_lib->ip.dpte_buffer_size_in_pte_reqs; + + log2_vmpg_height = 0; + log2_vmpg_width = 0; + log2_dpte_req_height_ptes = 0; + log2_dpte_req_width_ptes = 0; + log2_dpte_req_height = 0; + log2_dpte_req_width = 0; + log2_dpte_row_height_linear = 0; + log2_dpte_row_height = 0; + log2_dpte_group_width = 0; + dpte_row_width_ub = 0; + dpte_row_height = 0; + dpte_req_height = 0; /* 64b dpte req height in data element */ + dpte_req_width = 0; /* 64b dpte req width in data element */ + dpte_group_width = 0; + log2_dpte_group_bytes = 0; + log2_dpte_group_length = 0; + + if (surf_linear) + log2_vmpg_height = 0; /* one line high */ + else + log2_vmpg_height = (log2_vmpg_bytes - 8) / 2 + log2_blk256_height; + log2_vmpg_width = log2_vmpg_bytes - log2_bytes_per_element - log2_vmpg_height; + + /* only 3 possible shapes for dpte request in dimensions of ptes: 8x1, 4x2, 2x4. */ + if (log2_blk_bytes <= log2_vmpg_bytes) + log2_dpte_req_height_ptes = 0; + else if (log2_blk_height - log2_vmpg_height >= 2) + log2_dpte_req_height_ptes = 2; + else + log2_dpte_req_height_ptes = log2_blk_height - log2_vmpg_height; + log2_dpte_req_width_ptes = 3 - log2_dpte_req_height_ptes; + + /* Ensure we only have the 3 shapes */ + ASSERT((log2_dpte_req_width_ptes == 3 && log2_dpte_req_height_ptes == 0) || /* 8x1 */ + (log2_dpte_req_width_ptes == 2 && log2_dpte_req_height_ptes == 1) || /* 4x2 */ + (log2_dpte_req_width_ptes == 1 && log2_dpte_req_height_ptes == 2)); /* 2x4 */ + + /* The dpte request dimensions in data elements is dpte_req_width x dpte_req_height + * log2_vmpg_width is how much 1 pte represent, now calculating how much a 64b pte req represent + * That depends on the pte shape (i.e. 8x1, 4x2, 2x4) + */ + log2_dpte_req_height = log2_vmpg_height + log2_dpte_req_height_ptes; + log2_dpte_req_width = log2_vmpg_width + log2_dpte_req_width_ptes; + dpte_req_height = 1 << log2_dpte_req_height; + dpte_req_width = 1 << log2_dpte_req_width; + + /* calculate pitch dpte row buffer can hold + * round the result down to a power of two. + */ + if (surf_linear) { + log2_dpte_row_height_linear = dml_floor( + dml_log2(dpte_buf_in_pte_reqs * dpte_req_width / data_pitch), + 1); + + ASSERT(log2_dpte_row_height_linear >= 3); + + if (log2_dpte_row_height_linear > 7) + log2_dpte_row_height_linear = 7; + + log2_dpte_row_height = log2_dpte_row_height_linear; + rq_dlg_param->dpte_row_height = 1 << log2_dpte_row_height; + + /* For linear, the dpte row is pitch dependent and the pte requests wrap at the pitch boundary. + * the dpte_row_width_ub is the upper bound of data_pitch*dpte_row_height in elements with this unique buffering. + */ + dpte_row_width_ub = dml_round_to_multiple( + data_pitch * dpte_row_height - 1, + dpte_req_width, + 1) + dpte_req_width; + rq_dlg_param->dpte_req_per_row_ub = dpte_row_width_ub / dpte_req_width; + } else { + /* for tiled mode, row height is the same as req height and row store up to vp size upper bound */ + if (!surf_vert) { + log2_dpte_row_height = log2_dpte_req_height; + dpte_row_width_ub = dml_round_to_multiple(vp_width - 1, dpte_req_width, 1) + + dpte_req_width; + rq_dlg_param->dpte_req_per_row_ub = dpte_row_width_ub / dpte_req_width; + } else { + log2_dpte_row_height = + (log2_blk_width < log2_dpte_req_width) ? + log2_blk_width : log2_dpte_req_width; + dpte_row_width_ub = dml_round_to_multiple(vp_height - 1, dpte_req_height, 1) + + dpte_req_height; + rq_dlg_param->dpte_req_per_row_ub = dpte_row_width_ub / dpte_req_height; + } + rq_dlg_param->dpte_row_height = 1 << log2_dpte_row_height; + } + rq_dlg_param->dpte_bytes_per_row_ub = rq_dlg_param->dpte_req_per_row_ub * 64; + + /* From programming guide: + * There is a special case of saving only half of ptes returned due to buffer space limits. + * this case applies to 4 and 8bpe in horizontal access of a vp_width greater than 2560+16 + * when the pte request is 2x4 ptes (which happens when vmpg_bytes =4kb and tile blk_bytes >=64kb). + */ + if (!surf_vert && vp_width > (2560 + 16) && bytes_per_element >= 4 && log2_vmpg_bytes == 12 + && log2_blk_bytes >= 16) { + log2_dpte_row_height = log2_dpte_row_height - 1; /*half of the full height */ + rq_dlg_param->dpte_row_height = 1 << log2_dpte_row_height; + } + + /* the dpte_group_bytes is reduced for the specific case of vertical + * access of a tile surface that has dpte request of 8x1 ptes. + */ + if (!surf_linear & (log2_dpte_req_height_ptes == 0) & surf_vert) /*reduced, in this case, will have page fault within a group */ + rq_sizing_param->dpte_group_bytes = 512; + else + /*full size */ + rq_sizing_param->dpte_group_bytes = 2048; + + /*since pte request size is 64byte, the number of data pte requests per full sized group is as follows. */ + log2_dpte_group_bytes = dml_log2(rq_sizing_param->dpte_group_bytes); + log2_dpte_group_length = log2_dpte_group_bytes - 6; /*length in 64b requests */ + + /* full sized data pte group width in elements */ + if (!surf_vert) + log2_dpte_group_width = log2_dpte_group_length + log2_dpte_req_width; + else + log2_dpte_group_width = log2_dpte_group_length + log2_dpte_req_height; + + dpte_group_width = 1 << log2_dpte_group_width; + + /* since dpte groups are only aligned to dpte_req_width and not dpte_group_width, + * the upper bound for the dpte groups per row is as follows. + */ + rq_dlg_param->dpte_groups_per_row_ub = dml_ceil( + (double) dpte_row_width_ub / dpte_group_width, + 1); + + dml1_rq_dlg_get_row_heights( + mode_lib, + &func_dpte_row_height, + &func_meta_row_height, + vp_width, + data_pitch, + pipe_src_param.source_format, + pipe_src_param.sw_mode, + pipe_src_param.macro_tile_size, + pipe_src_param.source_scan, + is_chroma); + + /* Just a check to make sure this function and the new one give the same + * result. The standalone get_row_heights() function is based off of the + * code in this function so the same changes need to be made to both. + */ + if (rq_dlg_param->meta_row_height != func_meta_row_height) { + DTRACE( + "MISMATCH: rq_dlg_param->meta_row_height = %d", + rq_dlg_param->meta_row_height); + DTRACE("MISMATCH: func_meta_row_height = %d", func_meta_row_height); + ASSERT(0); + } + + if (rq_dlg_param->dpte_row_height != func_dpte_row_height) { + DTRACE( + "MISMATCH: rq_dlg_param->dpte_row_height = %d", + rq_dlg_param->dpte_row_height); + DTRACE("MISMATCH: func_dpte_row_height = %d", func_dpte_row_height); + ASSERT(0); + } +} + +void dml1_rq_dlg_get_rq_params( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_params_st *rq_param, + const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param) +{ + /* get param for luma surface */ + rq_param->yuv420 = pipe_src_param.source_format == dm_420_8 + || pipe_src_param.source_format == dm_420_10; + rq_param->yuv420_10bpc = pipe_src_param.source_format == dm_420_10; + + get_surf_rq_param( + mode_lib, + &(rq_param->sizing.rq_l), + &(rq_param->dlg.rq_l), + &(rq_param->misc.rq_l), + pipe_src_param, + 0); + + if (is_dual_plane((enum source_format_class) pipe_src_param.source_format)) { + /* get param for chroma surface */ + get_surf_rq_param( + mode_lib, + &(rq_param->sizing.rq_c), + &(rq_param->dlg.rq_c), + &(rq_param->misc.rq_c), + pipe_src_param, + 1); + } + + /* calculate how to split the det buffer space between luma and chroma */ + handle_det_buf_split(mode_lib, rq_param, pipe_src_param); + print__rq_params_st(mode_lib, *rq_param); +} + +/* Note: currently taken in as is. + * Nice to decouple code from hw register implement and extract code that are repeated for luma and chroma. + */ +void dml1_rq_dlg_get_dlg_params( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_dlg_regs_st *disp_dlg_regs, + struct _vcs_dpi_display_ttu_regs_st *disp_ttu_regs, + const struct _vcs_dpi_display_rq_dlg_params_st rq_dlg_param, + const struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param, + const struct _vcs_dpi_display_e2e_pipe_params_st e2e_pipe_param, + const bool cstate_en, + const bool pstate_en, + const bool vm_en, + const bool iflip_en) +{ + /* Timing */ + unsigned int htotal = e2e_pipe_param.pipe.dest.htotal; + unsigned int hblank_end = e2e_pipe_param.pipe.dest.hblank_end; + unsigned int vblank_start = e2e_pipe_param.pipe.dest.vblank_start; + unsigned int vblank_end = e2e_pipe_param.pipe.dest.vblank_end; + bool interlaced = e2e_pipe_param.pipe.dest.interlaced; + unsigned int min_vblank = mode_lib->ip.min_vblank_lines; + + double pclk_freq_in_mhz = e2e_pipe_param.pipe.dest.pixel_rate_mhz; + double refclk_freq_in_mhz = e2e_pipe_param.clks_cfg.refclk_mhz; + double dppclk_freq_in_mhz = e2e_pipe_param.clks_cfg.dppclk_mhz; + double dispclk_freq_in_mhz = e2e_pipe_param.clks_cfg.dispclk_mhz; + + double ref_freq_to_pix_freq; + double prefetch_xy_calc_in_dcfclk; + double min_dcfclk_mhz; + double t_calc_us; + double min_ttu_vblank; + double min_dst_y_ttu_vblank; + unsigned int dlg_vblank_start; + bool dcc_en; + bool dual_plane; + bool mode_422; + unsigned int access_dir; + unsigned int bytes_per_element_l; + unsigned int bytes_per_element_c; + unsigned int vp_height_l; + unsigned int vp_width_l; + unsigned int vp_height_c; + unsigned int vp_width_c; + unsigned int htaps_l; + unsigned int htaps_c; + double hratios_l; + double hratios_c; + double vratio_l; + double vratio_c; + double line_time_in_us; + double vinit_l; + double vinit_c; + double vinit_bot_l; + double vinit_bot_c; + unsigned int swath_height_l; + unsigned int swath_width_ub_l; + unsigned int dpte_bytes_per_row_ub_l; + unsigned int dpte_groups_per_row_ub_l; + unsigned int meta_pte_bytes_per_frame_ub_l; + unsigned int meta_bytes_per_row_ub_l; + unsigned int swath_height_c; + unsigned int swath_width_ub_c; + unsigned int dpte_bytes_per_row_ub_c; + unsigned int dpte_groups_per_row_ub_c; + unsigned int meta_chunks_per_row_ub_l; + unsigned int vupdate_offset; + unsigned int vupdate_width; + unsigned int vready_offset; + unsigned int dppclk_delay_subtotal; + unsigned int dispclk_delay_subtotal; + unsigned int pixel_rate_delay_subtotal; + unsigned int vstartup_start; + unsigned int dst_x_after_scaler; + unsigned int dst_y_after_scaler; + double line_wait; + double line_o; + double line_setup; + double line_calc; + double dst_y_prefetch; + double t_pre_us; + unsigned int vm_bytes; + unsigned int meta_row_bytes; + unsigned int max_num_sw_l; + unsigned int max_num_sw_c; + unsigned int max_partial_sw_l; + unsigned int max_partial_sw_c; + double max_vinit_l; + double max_vinit_c; + unsigned int lsw_l; + unsigned int lsw_c; + unsigned int sw_bytes_ub_l; + unsigned int sw_bytes_ub_c; + unsigned int sw_bytes; + unsigned int dpte_row_bytes; + double prefetch_bw; + double flip_bw; + double t_vm_us; + double t_r0_us; + double dst_y_per_vm_vblank; + double dst_y_per_row_vblank; + double min_dst_y_per_vm_vblank; + double min_dst_y_per_row_vblank; + double lsw; + double vratio_pre_l; + double vratio_pre_c; + unsigned int req_per_swath_ub_l; + unsigned int req_per_swath_ub_c; + unsigned int meta_row_height_l; + unsigned int swath_width_pixels_ub_l; + unsigned int swath_width_pixels_ub_c; + unsigned int scaler_rec_in_width_l; + unsigned int scaler_rec_in_width_c; + unsigned int dpte_row_height_l; + unsigned int dpte_row_height_c; + double hscale_pixel_rate_l; + double hscale_pixel_rate_c; + double min_hratio_fact_l; + double min_hratio_fact_c; + double refcyc_per_line_delivery_pre_l; + double refcyc_per_line_delivery_pre_c; + double refcyc_per_line_delivery_l; + double refcyc_per_line_delivery_c; + double refcyc_per_req_delivery_pre_l; + double refcyc_per_req_delivery_pre_c; + double refcyc_per_req_delivery_l; + double refcyc_per_req_delivery_c; + double refcyc_per_req_delivery_pre_cur0; + double refcyc_per_req_delivery_cur0; + unsigned int full_recout_width; + double hratios_cur0; + unsigned int cur0_src_width; + enum cursor_bpp cur0_bpp; + unsigned int cur0_req_size; + unsigned int cur0_req_width; + double cur0_width_ub; + double cur0_req_per_width; + double hactive_cur0; + + memset(disp_dlg_regs, 0, sizeof(*disp_dlg_regs)); + memset(disp_ttu_regs, 0, sizeof(*disp_ttu_regs)); + + DTRACE("DLG: %s: cstate_en = %d", __func__, cstate_en); + DTRACE("DLG: %s: pstate_en = %d", __func__, pstate_en); + DTRACE("DLG: %s: vm_en = %d", __func__, vm_en); + DTRACE("DLG: %s: iflip_en = %d", __func__, iflip_en); + + /* ------------------------- */ + /* Section 1.5.2.1: OTG dependent Params */ + /* ------------------------- */ + DTRACE("DLG: %s: dppclk_freq_in_mhz = %3.2f", __func__, dppclk_freq_in_mhz); + DTRACE("DLG: %s: dispclk_freq_in_mhz = %3.2f", __func__, dispclk_freq_in_mhz); + DTRACE("DLG: %s: refclk_freq_in_mhz = %3.2f", __func__, refclk_freq_in_mhz); + DTRACE("DLG: %s: pclk_freq_in_mhz = %3.2f", __func__, pclk_freq_in_mhz); + DTRACE("DLG: %s: interlaced = %d", __func__, interlaced); + + ref_freq_to_pix_freq = refclk_freq_in_mhz / pclk_freq_in_mhz; + ASSERT(ref_freq_to_pix_freq < 4.0); + disp_dlg_regs->ref_freq_to_pix_freq = + (unsigned int) (ref_freq_to_pix_freq * dml_pow(2, 19)); + disp_dlg_regs->refcyc_per_htotal = (unsigned int) (ref_freq_to_pix_freq * (double) htotal + * dml_pow(2, 8)); + disp_dlg_regs->refcyc_h_blank_end = (unsigned int) ((double) hblank_end + * (double) ref_freq_to_pix_freq); + ASSERT(disp_dlg_regs->refcyc_h_blank_end < (unsigned int) dml_pow(2, 13)); + disp_dlg_regs->dlg_vblank_end = interlaced ? (vblank_end / 2) : vblank_end; /* 15 bits */ + + prefetch_xy_calc_in_dcfclk = 24.0; /* FIXME: ip_param */ + min_dcfclk_mhz = dlg_sys_param.deepsleep_dcfclk_mhz; + t_calc_us = prefetch_xy_calc_in_dcfclk / min_dcfclk_mhz; + min_ttu_vblank = dlg_sys_param.t_urg_wm_us; + if (cstate_en) + min_ttu_vblank = dml_max(dlg_sys_param.t_sr_wm_us, min_ttu_vblank); + if (pstate_en) + min_ttu_vblank = dml_max(dlg_sys_param.t_mclk_wm_us, min_ttu_vblank); + min_ttu_vblank = min_ttu_vblank + t_calc_us; + + min_dst_y_ttu_vblank = min_ttu_vblank * pclk_freq_in_mhz / (double) htotal; + dlg_vblank_start = interlaced ? (vblank_start / 2) : vblank_start; + + disp_dlg_regs->min_dst_y_next_start = (unsigned int) (((double) dlg_vblank_start + + min_dst_y_ttu_vblank) * dml_pow(2, 2)); + ASSERT(disp_dlg_regs->min_dst_y_next_start < (unsigned int) dml_pow(2, 18)); + + DTRACE("DLG: %s: min_dcfclk_mhz = %3.2f", __func__, min_dcfclk_mhz); + DTRACE("DLG: %s: min_ttu_vblank = %3.2f", __func__, min_ttu_vblank); + DTRACE( + "DLG: %s: min_dst_y_ttu_vblank = %3.2f", + __func__, + min_dst_y_ttu_vblank); + DTRACE("DLG: %s: t_calc_us = %3.2f", __func__, t_calc_us); + DTRACE( + "DLG: %s: disp_dlg_regs->min_dst_y_next_start = 0x%0x", + __func__, + disp_dlg_regs->min_dst_y_next_start); + DTRACE( + "DLG: %s: ref_freq_to_pix_freq = %3.2f", + __func__, + ref_freq_to_pix_freq); + + /* ------------------------- */ + /* Section 1.5.2.2: Prefetch, Active and TTU */ + /* ------------------------- */ + /* Prefetch Calc */ + /* Source */ + dcc_en = e2e_pipe_param.pipe.src.dcc; + dual_plane = is_dual_plane( + (enum source_format_class) e2e_pipe_param.pipe.src.source_format); + mode_422 = 0; /* FIXME */ + access_dir = (e2e_pipe_param.pipe.src.source_scan == dm_vert); /* vp access direction: horizontal or vertical accessed */ + bytes_per_element_l = get_bytes_per_element( + (enum source_format_class) e2e_pipe_param.pipe.src.source_format, + 0); + bytes_per_element_c = get_bytes_per_element( + (enum source_format_class) e2e_pipe_param.pipe.src.source_format, + 1); + vp_height_l = e2e_pipe_param.pipe.src.viewport_height; + vp_width_l = e2e_pipe_param.pipe.src.viewport_width; + vp_height_c = e2e_pipe_param.pipe.src.viewport_height_c; + vp_width_c = e2e_pipe_param.pipe.src.viewport_width_c; + + /* Scaling */ + htaps_l = e2e_pipe_param.pipe.scale_taps.htaps; + htaps_c = e2e_pipe_param.pipe.scale_taps.htaps_c; + hratios_l = e2e_pipe_param.pipe.scale_ratio_depth.hscl_ratio; + hratios_c = e2e_pipe_param.pipe.scale_ratio_depth.hscl_ratio_c; + vratio_l = e2e_pipe_param.pipe.scale_ratio_depth.vscl_ratio; + vratio_c = e2e_pipe_param.pipe.scale_ratio_depth.vscl_ratio_c; + + line_time_in_us = (htotal / pclk_freq_in_mhz); + vinit_l = e2e_pipe_param.pipe.scale_ratio_depth.vinit; + vinit_c = e2e_pipe_param.pipe.scale_ratio_depth.vinit_c; + vinit_bot_l = e2e_pipe_param.pipe.scale_ratio_depth.vinit_bot; + vinit_bot_c = e2e_pipe_param.pipe.scale_ratio_depth.vinit_bot_c; + + swath_height_l = rq_dlg_param.rq_l.swath_height; + swath_width_ub_l = rq_dlg_param.rq_l.swath_width_ub; + dpte_bytes_per_row_ub_l = rq_dlg_param.rq_l.dpte_bytes_per_row_ub; + dpte_groups_per_row_ub_l = rq_dlg_param.rq_l.dpte_groups_per_row_ub; + meta_pte_bytes_per_frame_ub_l = rq_dlg_param.rq_l.meta_pte_bytes_per_frame_ub; + meta_bytes_per_row_ub_l = rq_dlg_param.rq_l.meta_bytes_per_row_ub; + + swath_height_c = rq_dlg_param.rq_c.swath_height; + swath_width_ub_c = rq_dlg_param.rq_c.swath_width_ub; + dpte_bytes_per_row_ub_c = rq_dlg_param.rq_c.dpte_bytes_per_row_ub; + dpte_groups_per_row_ub_c = rq_dlg_param.rq_c.dpte_groups_per_row_ub; + + meta_chunks_per_row_ub_l = rq_dlg_param.rq_l.meta_chunks_per_row_ub; + vupdate_offset = e2e_pipe_param.pipe.dest.vupdate_offset; + vupdate_width = e2e_pipe_param.pipe.dest.vupdate_width; + vready_offset = e2e_pipe_param.pipe.dest.vready_offset; + + dppclk_delay_subtotal = mode_lib->ip.dppclk_delay_subtotal; + dispclk_delay_subtotal = mode_lib->ip.dispclk_delay_subtotal; + pixel_rate_delay_subtotal = dppclk_delay_subtotal * pclk_freq_in_mhz / dppclk_freq_in_mhz + + dispclk_delay_subtotal * pclk_freq_in_mhz / dispclk_freq_in_mhz; + + vstartup_start = e2e_pipe_param.pipe.dest.vstartup_start; + + if (interlaced) + vstartup_start = vstartup_start / 2; + + if (vstartup_start >= min_vblank) { + DTRACE( + "WARNING_DLG: %s: vblank_start=%d vblank_end=%d", + __func__, + vblank_start, + vblank_end); + DTRACE( + "WARNING_DLG: %s: vstartup_start=%d should be less than min_vblank=%d", + __func__, + vstartup_start, + min_vblank); + min_vblank = vstartup_start + 1; + DTRACE( + "WARNING_DLG: %s: vstartup_start=%d should be less than min_vblank=%d", + __func__, + vstartup_start, + min_vblank); + } + + dst_x_after_scaler = 0; + dst_y_after_scaler = 0; + + if (e2e_pipe_param.pipe.src.is_hsplit) + dst_x_after_scaler = pixel_rate_delay_subtotal + + e2e_pipe_param.pipe.dest.recout_width; + else + dst_x_after_scaler = pixel_rate_delay_subtotal; + + if (e2e_pipe_param.dout.output_format == dm_420) + dst_y_after_scaler = 1; + else + dst_y_after_scaler = 0; + + if (dst_x_after_scaler >= htotal) { + dst_x_after_scaler = dst_x_after_scaler - htotal; + dst_y_after_scaler = dst_y_after_scaler + 1; + } + + DTRACE("DLG: %s: htotal = %d", __func__, htotal); + DTRACE( + "DLG: %s: pixel_rate_delay_subtotal = %d", + __func__, + pixel_rate_delay_subtotal); + DTRACE("DLG: %s: dst_x_after_scaler = %d", __func__, dst_x_after_scaler); + DTRACE("DLG: %s: dst_y_after_scaler = %d", __func__, dst_y_after_scaler); + + line_wait = mode_lib->soc.urgent_latency_us; + if (cstate_en) + line_wait = dml_max(mode_lib->soc.sr_enter_plus_exit_time_us, line_wait); + if (pstate_en) + line_wait = dml_max( + mode_lib->soc.dram_clock_change_latency_us + + mode_lib->soc.urgent_latency_us, + line_wait); + line_wait = line_wait / line_time_in_us; + + line_o = (double) dst_y_after_scaler + dst_x_after_scaler / (double) htotal; + line_setup = (double) (vupdate_offset + vupdate_width + vready_offset) / (double) htotal; + line_calc = t_calc_us / line_time_in_us; + + DTRACE( + "DLG: %s: soc.sr_enter_plus_exit_time_us = %3.2f", + __func__, + (double) mode_lib->soc.sr_enter_plus_exit_time_us); + DTRACE( + "DLG: %s: soc.dram_clock_change_latency_us = %3.2f", + __func__, + (double) mode_lib->soc.dram_clock_change_latency_us); + DTRACE( + "DLG: %s: soc.urgent_latency_us = %3.2f", + __func__, + mode_lib->soc.urgent_latency_us); + + DTRACE("DLG: %s: swath_height_l = %d", __func__, swath_height_l); + if (dual_plane) + DTRACE("DLG: %s: swath_height_c = %d", __func__, swath_height_c); + + DTRACE( + "DLG: %s: t_srx_delay_us = %3.2f", + __func__, + (double) dlg_sys_param.t_srx_delay_us); + DTRACE("DLG: %s: line_time_in_us = %3.2f", __func__, (double) line_time_in_us); + DTRACE("DLG: %s: vupdate_offset = %d", __func__, vupdate_offset); + DTRACE("DLG: %s: vupdate_width = %d", __func__, vupdate_width); + DTRACE("DLG: %s: vready_offset = %d", __func__, vready_offset); + DTRACE("DLG: %s: line_time_in_us = %3.2f", __func__, line_time_in_us); + DTRACE("DLG: %s: line_wait = %3.2f", __func__, line_wait); + DTRACE("DLG: %s: line_o = %3.2f", __func__, line_o); + DTRACE("DLG: %s: line_setup = %3.2f", __func__, line_setup); + DTRACE("DLG: %s: line_calc = %3.2f", __func__, line_calc); + + dst_y_prefetch = ((double) min_vblank - 1.0) + - (line_setup + line_calc + line_wait + line_o); + DTRACE("DLG: %s: dst_y_prefetch (before rnd) = %3.2f", __func__, dst_y_prefetch); + ASSERT(dst_y_prefetch >= 2.0); + + dst_y_prefetch = dml_floor(4.0 * (dst_y_prefetch + 0.125), 1) / 4; + DTRACE("DLG: %s: dst_y_prefetch (after rnd) = %3.2f", __func__, dst_y_prefetch); + + t_pre_us = dst_y_prefetch * line_time_in_us; + vm_bytes = 0; + meta_row_bytes = 0; + + if (dcc_en && vm_en) + vm_bytes = meta_pte_bytes_per_frame_ub_l; + if (dcc_en) + meta_row_bytes = meta_bytes_per_row_ub_l; + + max_num_sw_l = 0; + max_num_sw_c = 0; + max_partial_sw_l = 0; + max_partial_sw_c = 0; + + max_vinit_l = interlaced ? dml_max(vinit_l, vinit_bot_l) : vinit_l; + max_vinit_c = interlaced ? dml_max(vinit_c, vinit_bot_c) : vinit_c; + + get_swath_need(mode_lib, &max_num_sw_l, &max_partial_sw_l, swath_height_l, max_vinit_l); + if (dual_plane) + get_swath_need( + mode_lib, + &max_num_sw_c, + &max_partial_sw_c, + swath_height_c, + max_vinit_c); + + lsw_l = max_num_sw_l * swath_height_l + max_partial_sw_l; + lsw_c = max_num_sw_c * swath_height_c + max_partial_sw_c; + sw_bytes_ub_l = lsw_l * swath_width_ub_l * bytes_per_element_l; + sw_bytes_ub_c = lsw_c * swath_width_ub_c * bytes_per_element_c; + sw_bytes = 0; + dpte_row_bytes = 0; + + if (vm_en) { + if (dual_plane) + dpte_row_bytes = dpte_bytes_per_row_ub_l + dpte_bytes_per_row_ub_c; + else + dpte_row_bytes = dpte_bytes_per_row_ub_l; + } else { + dpte_row_bytes = 0; + } + + if (dual_plane) + sw_bytes = sw_bytes_ub_l + sw_bytes_ub_c; + else + sw_bytes = sw_bytes_ub_l; + + DTRACE("DLG: %s: sw_bytes_ub_l = %d", __func__, sw_bytes_ub_l); + DTRACE("DLG: %s: sw_bytes_ub_c = %d", __func__, sw_bytes_ub_c); + DTRACE("DLG: %s: sw_bytes = %d", __func__, sw_bytes); + DTRACE("DLG: %s: vm_bytes = %d", __func__, vm_bytes); + DTRACE("DLG: %s: meta_row_bytes = %d", __func__, meta_row_bytes); + DTRACE("DLG: %s: dpte_row_bytes = %d", __func__, dpte_row_bytes); + + prefetch_bw = (vm_bytes + 2 * dpte_row_bytes + 2 * meta_row_bytes + sw_bytes) / t_pre_us; + flip_bw = ((vm_bytes + dpte_row_bytes + meta_row_bytes) * dlg_sys_param.total_flip_bw) + / (double) dlg_sys_param.total_flip_bytes; + t_vm_us = line_time_in_us / 4.0; + if (vm_en && dcc_en) { + t_vm_us = dml_max( + dlg_sys_param.t_extra_us, + dml_max((double) vm_bytes / prefetch_bw, t_vm_us)); + + if (iflip_en && !dual_plane) { + t_vm_us = dml_max(mode_lib->soc.urgent_latency_us, t_vm_us); + if (flip_bw > 0.) + t_vm_us = dml_max(vm_bytes / flip_bw, t_vm_us); + } + } + + t_r0_us = dml_max(dlg_sys_param.t_extra_us - t_vm_us, line_time_in_us - t_vm_us); + + if (vm_en || dcc_en) { + t_r0_us = dml_max( + (double) (dpte_row_bytes + meta_row_bytes) / prefetch_bw, + dlg_sys_param.t_extra_us); + t_r0_us = dml_max((double) (line_time_in_us - t_vm_us), t_r0_us); + + if (iflip_en && !dual_plane) { + t_r0_us = dml_max(mode_lib->soc.urgent_latency_us * 2.0, t_r0_us); + if (flip_bw > 0.) + t_r0_us = dml_max( + (dpte_row_bytes + meta_row_bytes) / flip_bw, + t_r0_us); + } + } + + disp_dlg_regs->dst_y_after_scaler = dst_y_after_scaler; /* in terms of line */ + disp_dlg_regs->refcyc_x_after_scaler = dst_x_after_scaler * ref_freq_to_pix_freq; /* in terms of refclk */ + ASSERT(disp_dlg_regs->refcyc_x_after_scaler < (unsigned int) dml_pow(2, 13)); + DTRACE( + "DLG: %s: disp_dlg_regs->dst_y_after_scaler = 0x%0x", + __func__, + disp_dlg_regs->dst_y_after_scaler); + DTRACE( + "DLG: %s: disp_dlg_regs->refcyc_x_after_scaler = 0x%0x", + __func__, + disp_dlg_regs->refcyc_x_after_scaler); + + disp_dlg_regs->dst_y_prefetch = (unsigned int) (dst_y_prefetch * dml_pow(2, 2)); + DTRACE( + "DLG: %s: disp_dlg_regs->dst_y_prefetch = %d", + __func__, + disp_dlg_regs->dst_y_prefetch); + + dst_y_per_vm_vblank = 0.0; + dst_y_per_row_vblank = 0.0; + + dst_y_per_vm_vblank = t_vm_us / line_time_in_us; + dst_y_per_vm_vblank = dml_floor(4.0 * (dst_y_per_vm_vblank + 0.125), 1) / 4.0; + disp_dlg_regs->dst_y_per_vm_vblank = (unsigned int) (dst_y_per_vm_vblank * dml_pow(2, 2)); + + dst_y_per_row_vblank = t_r0_us / line_time_in_us; + dst_y_per_row_vblank = dml_floor(4.0 * (dst_y_per_row_vblank + 0.125), 1) / 4.0; + disp_dlg_regs->dst_y_per_row_vblank = (unsigned int) (dst_y_per_row_vblank * dml_pow(2, 2)); + + DTRACE("DLG: %s: lsw_l = %d", __func__, lsw_l); + DTRACE("DLG: %s: lsw_c = %d", __func__, lsw_c); + DTRACE("DLG: %s: dpte_bytes_per_row_ub_l = %d", __func__, dpte_bytes_per_row_ub_l); + DTRACE("DLG: %s: dpte_bytes_per_row_ub_c = %d", __func__, dpte_bytes_per_row_ub_c); + + DTRACE("DLG: %s: prefetch_bw = %3.2f", __func__, prefetch_bw); + DTRACE("DLG: %s: flip_bw = %3.2f", __func__, flip_bw); + DTRACE("DLG: %s: t_pre_us = %3.2f", __func__, t_pre_us); + DTRACE("DLG: %s: t_vm_us = %3.2f", __func__, t_vm_us); + DTRACE("DLG: %s: t_r0_us = %3.2f", __func__, t_r0_us); + DTRACE("DLG: %s: dst_y_per_vm_vblank = %3.2f", __func__, dst_y_per_vm_vblank); + DTRACE("DLG: %s: dst_y_per_row_vblank = %3.2f", __func__, dst_y_per_row_vblank); + DTRACE("DLG: %s: dst_y_prefetch = %3.2f", __func__, dst_y_prefetch); + + min_dst_y_per_vm_vblank = 8.0; + min_dst_y_per_row_vblank = 16.0; + if (htotal <= 75) { + min_vblank = 300; + min_dst_y_per_vm_vblank = 100.0; + min_dst_y_per_row_vblank = 100.0; + } + + ASSERT(dst_y_per_vm_vblank < min_dst_y_per_vm_vblank); + ASSERT(dst_y_per_row_vblank < min_dst_y_per_row_vblank); + + ASSERT(dst_y_prefetch > (dst_y_per_vm_vblank + dst_y_per_row_vblank)); + lsw = dst_y_prefetch - (dst_y_per_vm_vblank + dst_y_per_row_vblank); + + DTRACE("DLG: %s: lsw = %3.2f", __func__, lsw); + + vratio_pre_l = get_vratio_pre( + mode_lib, + max_num_sw_l, + max_partial_sw_l, + swath_height_l, + max_vinit_l, + lsw); + vratio_pre_c = 1.0; + if (dual_plane) + vratio_pre_c = get_vratio_pre( + mode_lib, + max_num_sw_c, + max_partial_sw_c, + swath_height_c, + max_vinit_c, + lsw); + + DTRACE("DLG: %s: vratio_pre_l=%3.2f", __func__, vratio_pre_l); + DTRACE("DLG: %s: vratio_pre_c=%3.2f", __func__, vratio_pre_c); + + ASSERT(vratio_pre_l <= 4.0); + if (vratio_pre_l >= 4.0) + disp_dlg_regs->vratio_prefetch = (unsigned int) dml_pow(2, 21) - 1; + else + disp_dlg_regs->vratio_prefetch = (unsigned int) (vratio_pre_l * dml_pow(2, 19)); + + ASSERT(vratio_pre_c <= 4.0); + if (vratio_pre_c >= 4.0) + disp_dlg_regs->vratio_prefetch_c = (unsigned int) dml_pow(2, 21) - 1; + else + disp_dlg_regs->vratio_prefetch_c = (unsigned int) (vratio_pre_c * dml_pow(2, 19)); + + disp_dlg_regs->refcyc_per_pte_group_vblank_l = + (unsigned int) (dst_y_per_row_vblank * (double) htotal + * ref_freq_to_pix_freq / (double) dpte_groups_per_row_ub_l); + ASSERT(disp_dlg_regs->refcyc_per_pte_group_vblank_l < (unsigned int) dml_pow(2, 13)); + + disp_dlg_regs->refcyc_per_pte_group_vblank_c = + (unsigned int) (dst_y_per_row_vblank * (double) htotal + * ref_freq_to_pix_freq / (double) dpte_groups_per_row_ub_c); + ASSERT(disp_dlg_regs->refcyc_per_pte_group_vblank_c < (unsigned int) dml_pow(2, 13)); + + disp_dlg_regs->refcyc_per_meta_chunk_vblank_l = + (unsigned int) (dst_y_per_row_vblank * (double) htotal + * ref_freq_to_pix_freq / (double) meta_chunks_per_row_ub_l); + ASSERT(disp_dlg_regs->refcyc_per_meta_chunk_vblank_l < (unsigned int) dml_pow(2, 13)); + + disp_dlg_regs->refcyc_per_meta_chunk_vblank_c = + disp_dlg_regs->refcyc_per_meta_chunk_vblank_l;/* dcc for 4:2:0 is not supported in dcn1.0. assigned to be the same as _l for now */ + + /* Active */ + req_per_swath_ub_l = rq_dlg_param.rq_l.req_per_swath_ub; + req_per_swath_ub_c = rq_dlg_param.rq_c.req_per_swath_ub; + meta_row_height_l = rq_dlg_param.rq_l.meta_row_height; + swath_width_pixels_ub_l = 0; + swath_width_pixels_ub_c = 0; + scaler_rec_in_width_l = 0; + scaler_rec_in_width_c = 0; + dpte_row_height_l = rq_dlg_param.rq_l.dpte_row_height; + dpte_row_height_c = rq_dlg_param.rq_c.dpte_row_height; + + disp_dlg_regs->dst_y_per_pte_row_nom_l = (unsigned int) ((double) dpte_row_height_l + / (double) vratio_l * dml_pow(2, 2)); + ASSERT(disp_dlg_regs->dst_y_per_pte_row_nom_l < (unsigned int) dml_pow(2, 17)); + + disp_dlg_regs->dst_y_per_pte_row_nom_c = (unsigned int) ((double) dpte_row_height_c + / (double) vratio_c * dml_pow(2, 2)); + ASSERT(disp_dlg_regs->dst_y_per_pte_row_nom_c < (unsigned int) dml_pow(2, 17)); + + disp_dlg_regs->dst_y_per_meta_row_nom_l = (unsigned int) ((double) meta_row_height_l + / (double) vratio_l * dml_pow(2, 2)); + ASSERT(disp_dlg_regs->dst_y_per_meta_row_nom_l < (unsigned int) dml_pow(2, 17)); + + disp_dlg_regs->dst_y_per_meta_row_nom_c = disp_dlg_regs->dst_y_per_meta_row_nom_l; /* dcc for 4:2:0 is not supported in dcn1.0. assigned to be the same as _l for now */ + + disp_dlg_regs->refcyc_per_pte_group_nom_l = (unsigned int) ((double) dpte_row_height_l + / (double) vratio_l * (double) htotal * ref_freq_to_pix_freq + / (double) dpte_groups_per_row_ub_l); + if (disp_dlg_regs->refcyc_per_pte_group_nom_l >= (unsigned int) dml_pow(2, 23)) + disp_dlg_regs->refcyc_per_pte_group_nom_l = dml_pow(2, 23) - 1; + + disp_dlg_regs->refcyc_per_pte_group_nom_c = (unsigned int) ((double) dpte_row_height_c + / (double) vratio_c * (double) htotal * ref_freq_to_pix_freq + / (double) dpte_groups_per_row_ub_c); + if (disp_dlg_regs->refcyc_per_pte_group_nom_c >= (unsigned int) dml_pow(2, 23)) + disp_dlg_regs->refcyc_per_pte_group_nom_c = dml_pow(2, 23) - 1; + + disp_dlg_regs->refcyc_per_meta_chunk_nom_l = (unsigned int) ((double) meta_row_height_l + / (double) vratio_l * (double) htotal * ref_freq_to_pix_freq + / (double) meta_chunks_per_row_ub_l); + if (disp_dlg_regs->refcyc_per_meta_chunk_nom_l >= (unsigned int) dml_pow(2, 23)) + disp_dlg_regs->refcyc_per_meta_chunk_nom_l = dml_pow(2, 23) - 1; + + if (mode_422) { + swath_width_pixels_ub_l = swath_width_ub_l * 2; /* *2 for 2 pixel per element */ + swath_width_pixels_ub_c = swath_width_ub_c * 2; + } else { + swath_width_pixels_ub_l = swath_width_ub_l * 1; + swath_width_pixels_ub_c = swath_width_ub_c * 1; + } + + hscale_pixel_rate_l = 0.; + hscale_pixel_rate_c = 0.; + min_hratio_fact_l = 1.0; + min_hratio_fact_c = 1.0; + + if (htaps_l <= 1) + min_hratio_fact_l = 2.0; + else if (htaps_l <= 6) { + if ((hratios_l * 2.0) > 4.0) + min_hratio_fact_l = 4.0; + else + min_hratio_fact_l = hratios_l * 2.0; + } else { + if (hratios_l > 4.0) + min_hratio_fact_l = 4.0; + else + min_hratio_fact_l = hratios_l; + } + + hscale_pixel_rate_l = min_hratio_fact_l * dppclk_freq_in_mhz; + + if (htaps_c <= 1) + min_hratio_fact_c = 2.0; + else if (htaps_c <= 6) { + if ((hratios_c * 2.0) > 4.0) + min_hratio_fact_c = 4.0; + else + min_hratio_fact_c = hratios_c * 2.0; + } else { + if (hratios_c > 4.0) + min_hratio_fact_c = 4.0; + else + min_hratio_fact_c = hratios_c; + } + + hscale_pixel_rate_c = min_hratio_fact_c * dppclk_freq_in_mhz; + + refcyc_per_line_delivery_pre_l = 0.; + refcyc_per_line_delivery_pre_c = 0.; + refcyc_per_line_delivery_l = 0.; + refcyc_per_line_delivery_c = 0.; + + refcyc_per_req_delivery_pre_l = 0.; + refcyc_per_req_delivery_pre_c = 0.; + refcyc_per_req_delivery_l = 0.; + refcyc_per_req_delivery_c = 0.; + refcyc_per_req_delivery_pre_cur0 = 0.; + refcyc_per_req_delivery_cur0 = 0.; + + full_recout_width = 0; + if (e2e_pipe_param.pipe.src.is_hsplit) { + if (e2e_pipe_param.pipe.dest.full_recout_width == 0) { + DTRACE("DLG: %s: Warningfull_recout_width not set in hsplit mode", __func__); + full_recout_width = e2e_pipe_param.pipe.dest.recout_width * 2; /* assume half split for dcn1 */ + } else + full_recout_width = e2e_pipe_param.pipe.dest.full_recout_width; + } else + full_recout_width = e2e_pipe_param.pipe.dest.recout_width; + + refcyc_per_line_delivery_pre_l = get_refcyc_per_delivery( + mode_lib, + refclk_freq_in_mhz, + pclk_freq_in_mhz, + full_recout_width, + vratio_pre_l, + hscale_pixel_rate_l, + swath_width_pixels_ub_l, + 1); /* per line */ + + refcyc_per_line_delivery_l = get_refcyc_per_delivery( + mode_lib, + refclk_freq_in_mhz, + pclk_freq_in_mhz, + full_recout_width, + vratio_l, + hscale_pixel_rate_l, + swath_width_pixels_ub_l, + 1); /* per line */ + + DTRACE("DLG: %s: full_recout_width = %d", __func__, full_recout_width); + DTRACE("DLG: %s: hscale_pixel_rate_l = %3.2f", __func__, hscale_pixel_rate_l); + DTRACE( + "DLG: %s: refcyc_per_line_delivery_pre_l = %3.2f", + __func__, + refcyc_per_line_delivery_pre_l); + DTRACE( + "DLG: %s: refcyc_per_line_delivery_l = %3.2f", + __func__, + refcyc_per_line_delivery_l); + + disp_dlg_regs->refcyc_per_line_delivery_pre_l = (unsigned int) dml_floor( + refcyc_per_line_delivery_pre_l, + 1); + disp_dlg_regs->refcyc_per_line_delivery_l = (unsigned int) dml_floor( + refcyc_per_line_delivery_l, + 1); + ASSERT(disp_dlg_regs->refcyc_per_line_delivery_pre_l < (unsigned int) dml_pow(2, 13)); + ASSERT(disp_dlg_regs->refcyc_per_line_delivery_l < (unsigned int) dml_pow(2, 13)); + + if (dual_plane) { + refcyc_per_line_delivery_pre_c = get_refcyc_per_delivery( + mode_lib, + refclk_freq_in_mhz, + pclk_freq_in_mhz, + full_recout_width, + vratio_pre_c, + hscale_pixel_rate_c, + swath_width_pixels_ub_c, + 1); /* per line */ + + refcyc_per_line_delivery_c = get_refcyc_per_delivery( + mode_lib, + refclk_freq_in_mhz, + pclk_freq_in_mhz, + full_recout_width, + vratio_c, + hscale_pixel_rate_c, + swath_width_pixels_ub_c, + 1); /* per line */ + + DTRACE( + "DLG: %s: refcyc_per_line_delivery_pre_c = %3.2f", + __func__, + refcyc_per_line_delivery_pre_c); + DTRACE( + "DLG: %s: refcyc_per_line_delivery_c = %3.2f", + __func__, + refcyc_per_line_delivery_c); + + disp_dlg_regs->refcyc_per_line_delivery_pre_c = (unsigned int) dml_floor( + refcyc_per_line_delivery_pre_c, + 1); + disp_dlg_regs->refcyc_per_line_delivery_c = (unsigned int) dml_floor( + refcyc_per_line_delivery_c, + 1); + ASSERT(disp_dlg_regs->refcyc_per_line_delivery_pre_c < (unsigned int) dml_pow(2, 13)); + ASSERT(disp_dlg_regs->refcyc_per_line_delivery_c < (unsigned int) dml_pow(2, 13)); + } + disp_dlg_regs->chunk_hdl_adjust_cur0 = 3; + + /* TTU - Luma / Chroma */ + if (access_dir) { /* vertical access */ + scaler_rec_in_width_l = vp_height_l; + scaler_rec_in_width_c = vp_height_c; + } else { + scaler_rec_in_width_l = vp_width_l; + scaler_rec_in_width_c = vp_width_c; + } + + refcyc_per_req_delivery_pre_l = get_refcyc_per_delivery( + mode_lib, + refclk_freq_in_mhz, + pclk_freq_in_mhz, + full_recout_width, + vratio_pre_l, + hscale_pixel_rate_l, + scaler_rec_in_width_l, + req_per_swath_ub_l); /* per req */ + refcyc_per_req_delivery_l = get_refcyc_per_delivery( + mode_lib, + refclk_freq_in_mhz, + pclk_freq_in_mhz, + full_recout_width, + vratio_l, + hscale_pixel_rate_l, + scaler_rec_in_width_l, + req_per_swath_ub_l); /* per req */ + + DTRACE( + "DLG: %s: refcyc_per_req_delivery_pre_l = %3.2f", + __func__, + refcyc_per_req_delivery_pre_l); + DTRACE( + "DLG: %s: refcyc_per_req_delivery_l = %3.2f", + __func__, + refcyc_per_req_delivery_l); + + disp_ttu_regs->refcyc_per_req_delivery_pre_l = (unsigned int) (refcyc_per_req_delivery_pre_l + * dml_pow(2, 10)); + disp_ttu_regs->refcyc_per_req_delivery_l = (unsigned int) (refcyc_per_req_delivery_l + * dml_pow(2, 10)); + + ASSERT(refcyc_per_req_delivery_pre_l < dml_pow(2, 13)); + ASSERT(refcyc_per_req_delivery_l < dml_pow(2, 13)); + + if (dual_plane) { + refcyc_per_req_delivery_pre_c = get_refcyc_per_delivery( + mode_lib, + refclk_freq_in_mhz, + pclk_freq_in_mhz, + full_recout_width, + vratio_pre_c, + hscale_pixel_rate_c, + scaler_rec_in_width_c, + req_per_swath_ub_c); /* per req */ + refcyc_per_req_delivery_c = get_refcyc_per_delivery( + mode_lib, + refclk_freq_in_mhz, + pclk_freq_in_mhz, + full_recout_width, + vratio_c, + hscale_pixel_rate_c, + scaler_rec_in_width_c, + req_per_swath_ub_c); /* per req */ + + DTRACE( + "DLG: %s: refcyc_per_req_delivery_pre_c = %3.2f", + __func__, + refcyc_per_req_delivery_pre_c); + DTRACE( + "DLG: %s: refcyc_per_req_delivery_c = %3.2f", + __func__, + refcyc_per_req_delivery_c); + + disp_ttu_regs->refcyc_per_req_delivery_pre_c = + (unsigned int) (refcyc_per_req_delivery_pre_c * dml_pow(2, 10)); + disp_ttu_regs->refcyc_per_req_delivery_c = (unsigned int) (refcyc_per_req_delivery_c + * dml_pow(2, 10)); + + ASSERT(refcyc_per_req_delivery_pre_c < dml_pow(2, 13)); + ASSERT(refcyc_per_req_delivery_c < dml_pow(2, 13)); + } + + /* TTU - Cursor */ + hratios_cur0 = e2e_pipe_param.pipe.scale_ratio_depth.hscl_ratio; + cur0_src_width = e2e_pipe_param.pipe.src.cur0_src_width; /* cursor source width */ + cur0_bpp = (enum cursor_bpp) e2e_pipe_param.pipe.src.cur0_bpp; + cur0_req_size = 0; + cur0_req_width = 0; + cur0_width_ub = 0.0; + cur0_req_per_width = 0.0; + hactive_cur0 = 0.0; + + ASSERT(cur0_src_width <= 256); + + if (cur0_src_width > 0) { + unsigned int cur0_bit_per_pixel = 0; + + if (cur0_bpp == dm_cur_2bit) { + cur0_req_size = 64; /* byte */ + cur0_bit_per_pixel = 2; + } else { /* 32bit */ + cur0_bit_per_pixel = 32; + if (cur0_src_width >= 1 && cur0_src_width <= 16) + cur0_req_size = 64; + else if (cur0_src_width >= 17 && cur0_src_width <= 31) + cur0_req_size = 128; + else + cur0_req_size = 256; + } + + cur0_req_width = (double) cur0_req_size / ((double) cur0_bit_per_pixel / 8.0); + cur0_width_ub = dml_ceil((double) cur0_src_width / (double) cur0_req_width, 1) + * (double) cur0_req_width; + cur0_req_per_width = cur0_width_ub / (double) cur0_req_width; + hactive_cur0 = (double) cur0_src_width / hratios_cur0; /* FIXME: oswin to think about what to do for cursor */ + + if (vratio_pre_l <= 1.0) { + refcyc_per_req_delivery_pre_cur0 = hactive_cur0 * ref_freq_to_pix_freq + / (double) cur0_req_per_width; + } else { + refcyc_per_req_delivery_pre_cur0 = (double) refclk_freq_in_mhz + * (double) cur0_src_width / hscale_pixel_rate_l + / (double) cur0_req_per_width; + } + + disp_ttu_regs->refcyc_per_req_delivery_pre_cur0 = + (unsigned int) (refcyc_per_req_delivery_pre_cur0 * dml_pow(2, 10)); + ASSERT(refcyc_per_req_delivery_pre_cur0 < dml_pow(2, 13)); + + if (vratio_l <= 1.0) { + refcyc_per_req_delivery_cur0 = hactive_cur0 * ref_freq_to_pix_freq + / (double) cur0_req_per_width; + } else { + refcyc_per_req_delivery_cur0 = (double) refclk_freq_in_mhz + * (double) cur0_src_width / hscale_pixel_rate_l + / (double) cur0_req_per_width; + } + + DTRACE("DLG: %s: cur0_req_width = %d", __func__, cur0_req_width); + DTRACE( + "DLG: %s: cur0_width_ub = %3.2f", + __func__, + cur0_width_ub); + DTRACE( + "DLG: %s: cur0_req_per_width = %3.2f", + __func__, + cur0_req_per_width); + DTRACE( + "DLG: %s: hactive_cur0 = %3.2f", + __func__, + hactive_cur0); + DTRACE( + "DLG: %s: refcyc_per_req_delivery_pre_cur0 = %3.2f", + __func__, + refcyc_per_req_delivery_pre_cur0); + DTRACE( + "DLG: %s: refcyc_per_req_delivery_cur0 = %3.2f", + __func__, + refcyc_per_req_delivery_cur0); + + disp_ttu_regs->refcyc_per_req_delivery_cur0 = + (unsigned int) (refcyc_per_req_delivery_cur0 * dml_pow(2, 10)); + ASSERT(refcyc_per_req_delivery_cur0 < dml_pow(2, 13)); + } else { + disp_ttu_regs->refcyc_per_req_delivery_pre_cur0 = 0; + disp_ttu_regs->refcyc_per_req_delivery_cur0 = 0; + } + + /* TTU - Misc */ + disp_ttu_regs->qos_level_low_wm = 0; + ASSERT(disp_ttu_regs->qos_level_low_wm < dml_pow(2, 14)); + disp_ttu_regs->qos_level_high_wm = (unsigned int) (4.0 * (double) htotal + * ref_freq_to_pix_freq); + ASSERT(disp_ttu_regs->qos_level_high_wm < dml_pow(2, 14)); + + disp_ttu_regs->qos_level_flip = 14; + disp_ttu_regs->qos_level_fixed_l = 8; + disp_ttu_regs->qos_level_fixed_c = 8; + disp_ttu_regs->qos_level_fixed_cur0 = 8; + disp_ttu_regs->qos_ramp_disable_l = 0; + disp_ttu_regs->qos_ramp_disable_c = 0; + disp_ttu_regs->qos_ramp_disable_cur0 = 0; + + disp_ttu_regs->min_ttu_vblank = min_ttu_vblank * refclk_freq_in_mhz; + ASSERT(disp_ttu_regs->min_ttu_vblank < dml_pow(2, 24)); + + print__ttu_regs_st(mode_lib, *disp_ttu_regs); + print__dlg_regs_st(mode_lib, *disp_dlg_regs); +} diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.h b/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.h new file mode 100644 index 000000000000..987d7671cd0f --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.h @@ -0,0 +1,67 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DISPLAY_RQ_DLG_CALC_H__ +#define __DISPLAY_RQ_DLG_CALC_H__ + +#include "dml_common_defs.h" +#include "display_rq_dlg_helpers.h" + +struct display_mode_lib; + +void dml1_extract_rq_regs( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_regs_st *rq_regs, + const struct _vcs_dpi_display_rq_params_st rq_param); +/* Function: dml_rq_dlg_get_rq_params + * Calculate requestor related parameters that register definition agnostic + * (i.e. this layer does try to separate real values from register definition) + * Input: + * pipe_src_param - pipe source configuration (e.g. vp, pitch, etc.) + * Output: + * rq_param - values that can be used to setup RQ (e.g. swath_height, plane1_addr, etc.) + */ +void dml1_rq_dlg_get_rq_params( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_params_st *rq_param, + const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param); + + +/* Function: dml_rq_dlg_get_dlg_params + * Calculate deadline related parameters + */ +void dml1_rq_dlg_get_dlg_params( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_dlg_regs_st *dlg_regs, + struct _vcs_dpi_display_ttu_regs_st *ttu_regs, + const struct _vcs_dpi_display_rq_dlg_params_st rq_dlg_param, + const struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param, + const struct _vcs_dpi_display_e2e_pipe_params_st e2e_pipe_param, + const bool cstate_en, + const bool pstate_en, + const bool vm_en, + const bool iflip_en); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c index 21349a022de3..9cbd415e508d 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c @@ -36,21 +36,21 @@ double dml_max(double a, double b) return (double) dcn_bw_max2(a, b); } -double dml_ceil(double a) +double dml_ceil(double a, double granularity) { - return (double) dcn_bw_ceil2(a, 1); + return (double) dcn_bw_ceil2(a, granularity); } -double dml_floor(double a) +double dml_floor(double a, double granularity) { - return (double) dcn_bw_floor2(a, 1); + return (double) dcn_bw_floor2(a, granularity); } double dml_round(double a) { double round_pt = 0.5; - double ceil = dml_ceil(a); - double floor = dml_floor(a); + double ceil = dml_ceil(a, 1); + double floor = dml_floor(a, 1); if (a - floor >= round_pt) return ceil; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h index c5340d41eedb..19271e79abcc 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h @@ -22,6 +22,7 @@ * Authors: AMD * */ + #ifndef __DC_COMMON_DEFS_H__ #define __DC_COMMON_DEFS_H__ @@ -30,7 +31,8 @@ #include "display_mode_structs.h" #include "display_mode_enums.h" -#define DTRACE(str, ...) dm_logger_write(mode_lib->logger, LOG_DML, str, ##__VA_ARGS__); +#define dml_print(str, ...) {dm_logger_write(mode_lib->logger, LOG_DML, str, ##__VA_ARGS__); } +#define DTRACE(str, ...) {dm_logger_write(mode_lib->logger, LOG_DML, str, ##__VA_ARGS__); } double dml_min(double a, double b); double dml_max(double a, double b); @@ -38,8 +40,8 @@ bool dml_util_is_420(enum source_format_class sorce_format); double dml_ceil_ex(double x, double granularity); double dml_floor_ex(double x, double granularity); double dml_log(double x, double base); -double dml_ceil(double a); -double dml_floor(double a); +double dml_ceil(double a, double granularity); +double dml_floor(double a, double granularity); double dml_round(double a); int dml_log2(double x); double dml_pow(double a, int exp); diff --git a/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c b/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c index 112b0b728b4d..8b8512528af5 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c +++ b/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c @@ -24,49 +24,45 @@ */ #include "soc_bounding_box.h" #include "display_mode_lib.h" +#include "dc_features.h" -void dml_socbb_set_latencies( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_soc_bounding_box_st *from_box) +void dml_socbb_set_latencies(soc_bounding_box_st *to_box, soc_bounding_box_st *from_box) { - struct _vcs_dpi_soc_bounding_box_st *to_box = &mode_lib->soc; - to_box->dram_clock_change_latency_us = from_box->dram_clock_change_latency_us; to_box->sr_exit_time_us = from_box->sr_exit_time_us; to_box->sr_enter_plus_exit_time_us = from_box->sr_enter_plus_exit_time_us; to_box->urgent_latency_us = from_box->urgent_latency_us; to_box->writeback_latency_us = from_box->writeback_latency_us; - DTRACE("box.dram_clock_change_latency_us: %f", from_box->dram_clock_change_latency_us); - DTRACE("box.sr_exit_time_us: %f", from_box->sr_exit_time_us); - DTRACE("box.sr_enter_plus_exit_time_us: %f", from_box->sr_enter_plus_exit_time_us); - DTRACE("box.urgent_latency_us: %f", from_box->urgent_latency_us); - DTRACE("box.writeback_latency_us: %f", from_box->writeback_latency_us); - } -struct _vcs_dpi_voltage_scaling_st dml_socbb_voltage_scaling( - struct _vcs_dpi_soc_bounding_box_st *box, +voltage_scaling_st dml_socbb_voltage_scaling( + const soc_bounding_box_st *soc, enum voltage_state voltage) { - switch (voltage) { - case dm_vmin: - return box->vmin; - case dm_vnom: - return box->vnom; - case dm_vmax: - default: - return box->vmax; + const voltage_scaling_st *voltage_state; + const voltage_scaling_st * const voltage_end = soc->clock_limits + DC__VOLTAGE_STATES; + + for (voltage_state = soc->clock_limits; + voltage_state < voltage_end && voltage_state->state != voltage; + voltage_state++) { } + + if (voltage_state < voltage_end) + return *voltage_state; + return soc->clock_limits[DC__VOLTAGE_STATES - 1]; } -double dml_socbb_return_bw_mhz(struct _vcs_dpi_soc_bounding_box_st *box, enum voltage_state voltage) +double dml_socbb_return_bw_mhz(soc_bounding_box_st *box, enum voltage_state voltage) { double return_bw; - struct _vcs_dpi_voltage_scaling_st state = dml_socbb_voltage_scaling(box, voltage); + voltage_scaling_st state = dml_socbb_voltage_scaling(box, voltage); + + return_bw = dml_min((double) box->return_bus_width_bytes * state.dcfclk_mhz, + state.dram_bw_per_chan_gbps * 1000.0 * (double) box->num_chans + * box->ideal_dram_bw_after_urgent_percent / 100.0); + + return_bw = dml_min((double) box->return_bus_width_bytes * state.fabricclk_mhz, return_bw); - return_bw = dml_min( - ((double) box->return_bus_width_bytes) * state.dcfclk_mhz, - state.dram_bw_per_chan_gbps * 1000.0 * box->ideal_dram_bw_after_urgent_percent / 100.0); return return_bw; } diff --git a/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.h b/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.h index 7bbae33f163e..7a65206a6d21 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.h +++ b/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.h @@ -22,15 +22,14 @@ * Authors: AMD * */ + #ifndef __SOC_BOUNDING_BOX_H__ #define __SOC_BOUNDING_BOX_H__ #include "dml_common_defs.h" -struct display_mode_lib; - -void dml_socbb_set_latencies(struct display_mode_lib *mode_lib, struct _vcs_dpi_soc_bounding_box_st *from_box); -struct _vcs_dpi_voltage_scaling_st dml_socbb_voltage_scaling(struct _vcs_dpi_soc_bounding_box_st *box, enum voltage_state voltage); -double dml_socbb_return_bw_mhz(struct _vcs_dpi_soc_bounding_box_st *box, enum voltage_state voltage); +void dml_socbb_set_latencies(soc_bounding_box_st *to_box, soc_bounding_box_st *from_box); +voltage_scaling_st dml_socbb_voltage_scaling(const soc_bounding_box_st *box, enum voltage_state voltage); +double dml_socbb_return_bw_mhz(soc_bounding_box_st *box, enum voltage_state voltage); #endif -- cgit From cb94f78e3665ef23aabfe547962748d49471cf45 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 15 Sep 2017 16:03:09 -0400 Subject: drm/amd/display: add mode support check to dml vba code Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dml/display_mode_enums.h | 10 +- .../drm/amd/display/dc/dml/display_mode_structs.h | 5 + .../gpu/drm/amd/display/dc/dml/display_mode_vba.c | 5701 +++++++++++++++----- .../gpu/drm/amd/display/dc/dml/display_mode_vba.h | 456 +- .../gpu/drm/amd/display/dc/dml/dml_common_defs.c | 12 + .../gpu/drm/amd/display/dc/dml/dml_common_defs.h | 3 + 6 files changed, 4604 insertions(+), 1583 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h index eebaeb1fb61c..b1ad3553f900 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h @@ -26,7 +26,7 @@ #define __DISPLAY_MODE_ENUMS_H__ enum output_encoder_class { - dm_dp = 0, dm_hdmi = 1, dm_wb = 2 + dm_dp = 0, dm_hdmi = 1, dm_wb = 2, dm_edp }; enum output_format_class { dm_444 = 0, dm_420 = 1, dm_n422, dm_s422 @@ -39,7 +39,9 @@ enum source_format_class { dm_420_10 = 4, dm_422_8 = 5, dm_422_10 = 6, - dm_444_8 = 7 + dm_444_8 = 7, + dm_mono_8, + dm_mono_16 }; enum output_bpc_class { dm_out_6 = 0, dm_out_8 = 1, dm_out_10 = 2, dm_out_12 = 3, dm_out_16 = 4 @@ -79,7 +81,9 @@ enum dm_swizzle_mode { dm_sw_SPARE_15 = 28, dm_sw_var_s_x = 29, dm_sw_var_d_x = 30, - dm_sw_64kb_r_x + dm_sw_64kb_r_x, + dm_sw_gfx7_2d_thin_lvp, + dm_sw_gfx7_2d_thin_gl }; enum lb_depth { dm_lb_10 = 0, dm_lb_8 = 1, dm_lb_6 = 2, dm_lb_12 = 3, dm_lb_16 diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h index e5b7f7042e0b..27e20460c71b 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h @@ -66,6 +66,7 @@ struct _vcs_dpi_mode_evaluation_st { struct _vcs_dpi_voltage_scaling_st { int state; + double dscclk_mhz; double dcfclk_mhz; double socclk_mhz; double dram_speed_mhz; @@ -131,6 +132,9 @@ struct _vcs_dpi_ip_params_st { unsigned int writeback_chroma_line_buffer_width_pixels; unsigned int max_page_table_levels; unsigned int max_num_dpp; + unsigned int max_num_otg; + unsigned int cursor_chunk_size; + unsigned int cursor_buffer_size; unsigned int max_num_wb; unsigned int max_dchub_pscl_bw_pix_per_clk; unsigned int max_pscl_lb_bw_pix_per_clk; @@ -224,6 +228,7 @@ struct writeback_st { }; struct _vcs_dpi_display_output_params_st { + int dp_lanes; int output_bpp; int dsc_enable; int wb_enable; diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c index ada0eeed3301..e1a3182d58b3 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c @@ -6,202 +6,220 @@ static const unsigned int NumberOfStates = DC__VOLTAGE_STATES; static void fetch_socbb_params(struct display_mode_lib *mode_lib); static void fetch_ip_params(struct display_mode_lib *mode_lib); static void fetch_pipe_params(struct display_mode_lib *mode_lib); -static void recalculate_params(struct display_mode_lib *mode_lib, - const display_e2e_pipe_params_st *pipes, - unsigned int num_pipes); +static void recalculate_params( + struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *pipes, + unsigned int num_pipes); static void recalculate(struct display_mode_lib *mode_lib); -static double adjust_ReturnBW(struct display_mode_lib *mode_lib, double ReturnBW, bool DCCEnabledAnyPlane, double ReturnBandwidthToDCN); +static double adjust_ReturnBW( + struct display_mode_lib *mode_lib, + double ReturnBW, + bool DCCEnabledAnyPlane, + double ReturnBandwidthToDCN); static void ModeSupportAndSystemConfiguration(struct display_mode_lib *mode_lib); static void DisplayPipeConfiguration(struct display_mode_lib *mode_lib); -static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation(struct display_mode_lib *mode_lib); -static unsigned int dscceComputeDelay(unsigned int bpc, - double bpp, - unsigned int sliceWidth, - unsigned int numSlices, - enum output_format_class pixelFormat); +static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation( + struct display_mode_lib *mode_lib); +static unsigned int dscceComputeDelay( + unsigned int bpc, + double bpp, + unsigned int sliceWidth, + unsigned int numSlices, + enum output_format_class pixelFormat); static unsigned int dscComputeDelay(enum output_format_class pixelFormat); // Super monster function with some 45 argument -static bool CalculatePrefetchSchedule(struct display_mode_lib *mode_lib, - double DPPCLK, - double DISPCLK, - double PixelClock, - double DCFClkDeepSleep, - unsigned int DSCDelay, - unsigned int DPPPerPlane, - bool ScalerEnabled, - unsigned int NumberOfCursors, - double DPPCLKDelaySubtotal, - double DPPCLKDelaySCL, - double DPPCLKDelaySCLLBOnly, - double DPPCLKDelayCNVCFormater, - double DPPCLKDelayCNVCCursor, - double DISPCLKDelaySubtotal, - unsigned int ScalerRecoutWidth, - enum output_format_class OutputFormat, - unsigned int VBlank, - unsigned int HTotal, - unsigned int MaxInterDCNTileRepeaters, - unsigned int VStartup, - unsigned int PageTableLevels, - bool VirtualMemoryEnable, - bool DynamicMetadataEnable, - unsigned int DynamicMetadataLinesBeforeActiveRequired, - unsigned int DynamicMetadataTransmittedBytes, - bool DCCEnable, - double UrgentLatency, - double UrgentExtraLatency, - double TCalc, - unsigned int PDEAndMetaPTEBytesFrame, - unsigned int MetaRowByte, - unsigned int PixelPTEBytesPerRow, - double PrefetchSourceLinesY, - unsigned int SwathWidthY, - double BytePerPixelDETY, - double VInitPreFillY, - unsigned int MaxNumSwathY, - double PrefetchSourceLinesC, - double BytePerPixelDETC, - double VInitPreFillC, - unsigned int MaxNumSwathC, - unsigned int SwathHeightY, - unsigned int SwathHeightC, - double TWait, - bool XFCEnabled, - double XFCRemoteSurfaceFlipDelay, - bool InterlaceEnable, - bool ProgressiveToInterlaceUnitInOPP, - double *DSTXAfterScaler, - double *DSTYAfterScaler, - double *DestinationLinesForPrefetch, - double *PrefetchBandwidth, - double *DestinationLinesToRequestVMInVBlank, - double *DestinationLinesToRequestRowInVBlank, - double *VRatioPrefetchY, - double *VRatioPrefetchC, - double *RequiredPrefetchPixDataBW, - unsigned int *VStartupRequiredWhenNotEnoughTimeForDynamicMetadata, - double *Tno_bw); -static double CeilToDFSGranularity(double Clock, double VCOSpeed); -static double FloorToDFSGranularity(double Clock, double VCOSpeed); -static double CalculatePrefetchSourceLines(struct display_mode_lib *mode_lib, - double VRatio, - double vtaps, - bool Interlace, - bool ProgressiveToInterlaceUnitInOPP, - unsigned int SwathHeight, - unsigned int ViewportYStart, - double *VInitPreFill, - unsigned int *MaxNumSwath); -static unsigned int CalculateVMAndRowBytes(struct display_mode_lib *mode_lib, - bool DCCEnable, - unsigned int BlockHeight256Bytes, - unsigned int BlockWidth256Bytes, - enum source_format_class SourcePixelFormat, - unsigned int SurfaceTiling, - unsigned int BytePerPixel, - enum scan_direction_class ScanDirection, - unsigned int ViewportWidth, - unsigned int ViewportHeight, - unsigned int SwathWidthY, - bool VirtualMemoryEnable, - unsigned int VMMPageSize, - unsigned int PTEBufferSizeInRequests, - unsigned int PDEProcessingBufIn64KBReqs, - unsigned int Pitch, - unsigned int DCCMetaPitch, - unsigned int *MacroTileWidth, - unsigned int *MetaRowByte, - unsigned int *PixelPTEBytesPerRow, - bool *PTEBufferSizeNotExceeded, - unsigned int *dpte_row_height, - unsigned int *meta_row_height); -static double CalculateTWait(unsigned int PrefetchMode, - double DRAMClockChangeLatency, - double UrgentLatency, - double SREnterPlusExitTime); -static double CalculateRemoteSurfaceFlipDelay(struct display_mode_lib *mode_lib, - double VRatio, - double SwathWidth, - double Bpp, - double LineTime, - double XFCTSlvVupdateOffset, - double XFCTSlvVupdateWidth, - double XFCTSlvVreadyOffset, - double XFCXBUFLatencyTolerance, - double XFCFillBWOverhead, - double XFCSlvChunkSize, - double XFCBusTransportTime, - double TCalc, - double TWait, - double *SrcActiveDrainRate, - double *TInitXFill, - double *TslvChk); -static double CalculateWriteBackDISPCLK(enum source_format_class WritebackPixelFormat, - double PixelClock, - double WritebackHRatio, - double WritebackVRatio, - unsigned int WritebackLumaHTaps, - unsigned int WritebackLumaVTaps, - unsigned int WritebackChromaHTaps, - unsigned int WritebackChromaVTaps, - double WritebackDestinationWidth, - unsigned int HTotal, - unsigned int WritebackChromaLineBufferWidth); -static void CalculateActiveRowBandwidth(bool VirtualMemoryEnable, - enum source_format_class SourcePixelFormat, - double VRatio, - bool DCCEnable, - double LineTime, - unsigned int MetaRowByteLuma, - unsigned int MetaRowByteChroma, - unsigned int meta_row_height_luma, - unsigned int meta_row_height_chroma, - unsigned int PixelPTEBytesPerRowLuma, - unsigned int PixelPTEBytesPerRowChroma, - unsigned int dpte_row_height_luma, - unsigned int dpte_row_height_chroma, - double *meta_row_bw, - double *dpte_row_bw, - double *qual_row_bw); -static void CalculateFlipSchedule(struct display_mode_lib *mode_lib, - double UrgentExtraLatency, - double UrgentLatency, - unsigned int MaxPageTableLevels, - bool VirtualMemoryEnable, - double BandwidthAvailableForImmediateFlip, - unsigned int TotImmediateFlipBytes, - enum source_format_class SourcePixelFormat, - unsigned int ImmediateFlipBytes, - double LineTime, - double Tno_bw, - double VRatio, - double PDEAndMetaPTEBytesFrame, - unsigned int MetaRowByte, - unsigned int PixelPTEBytesPerRow, - bool DCCEnable, - unsigned int dpte_row_height, - unsigned int meta_row_height, - double qual_row_bw, - double *DestinationLinesToRequestVMInImmediateFlip, - double *DestinationLinesToRequestRowInImmediateFlip, - double *final_flip_bw, - bool *ImmediateFlipSupportedForPipe); -static double CalculateWriteBackDelay(enum source_format_class WritebackPixelFormat, - double WritebackHRatio, - double WritebackVRatio, - unsigned int WritebackLumaHTaps, - unsigned int WritebackLumaVTaps, - unsigned int WritebackChromaHTaps, - unsigned int WritebackChromaVTaps, - unsigned int WritebackDestinationWidth); +static bool CalculatePrefetchSchedule( + struct display_mode_lib *mode_lib, + double DPPCLK, + double DISPCLK, + double PixelClock, + double DCFClkDeepSleep, + unsigned int DSCDelay, + unsigned int DPPPerPlane, + bool ScalerEnabled, + unsigned int NumberOfCursors, + double DPPCLKDelaySubtotal, + double DPPCLKDelaySCL, + double DPPCLKDelaySCLLBOnly, + double DPPCLKDelayCNVCFormater, + double DPPCLKDelayCNVCCursor, + double DISPCLKDelaySubtotal, + unsigned int ScalerRecoutWidth, + enum output_format_class OutputFormat, + unsigned int VBlank, + unsigned int HTotal, + unsigned int MaxInterDCNTileRepeaters, + unsigned int VStartup, + unsigned int PageTableLevels, + bool VirtualMemoryEnable, + bool DynamicMetadataEnable, + unsigned int DynamicMetadataLinesBeforeActiveRequired, + unsigned int DynamicMetadataTransmittedBytes, + bool DCCEnable, + double UrgentLatency, + double UrgentExtraLatency, + double TCalc, + unsigned int PDEAndMetaPTEBytesFrame, + unsigned int MetaRowByte, + unsigned int PixelPTEBytesPerRow, + double PrefetchSourceLinesY, + unsigned int SwathWidthY, + double BytePerPixelDETY, + double VInitPreFillY, + unsigned int MaxNumSwathY, + double PrefetchSourceLinesC, + double BytePerPixelDETC, + double VInitPreFillC, + unsigned int MaxNumSwathC, + unsigned int SwathHeightY, + unsigned int SwathHeightC, + double TWait, + bool XFCEnabled, + double XFCRemoteSurfaceFlipDelay, + bool InterlaceEnable, + bool ProgressiveToInterlaceUnitInOPP, + double *DSTXAfterScaler, + double *DSTYAfterScaler, + double *DestinationLinesForPrefetch, + double *PrefetchBandwidth, + double *DestinationLinesToRequestVMInVBlank, + double *DestinationLinesToRequestRowInVBlank, + double *VRatioPrefetchY, + double *VRatioPrefetchC, + double *RequiredPrefetchPixDataBW, + unsigned int *VStartupRequiredWhenNotEnoughTimeForDynamicMetadata, + double *Tno_bw); +static double RoundToDFSGranularityUp(double Clock, double VCOSpeed); +static double RoundToDFSGranularityDown(double Clock, double VCOSpeed); +static double CalculatePrefetchSourceLines( + struct display_mode_lib *mode_lib, + double VRatio, + double vtaps, + bool Interlace, + bool ProgressiveToInterlaceUnitInOPP, + unsigned int SwathHeight, + unsigned int ViewportYStart, + double *VInitPreFill, + unsigned int *MaxNumSwath); +static unsigned int CalculateVMAndRowBytes( + struct display_mode_lib *mode_lib, + bool DCCEnable, + unsigned int BlockHeight256Bytes, + unsigned int BlockWidth256Bytes, + enum source_format_class SourcePixelFormat, + unsigned int SurfaceTiling, + unsigned int BytePerPixel, + enum scan_direction_class ScanDirection, + unsigned int ViewportWidth, + unsigned int ViewportHeight, + unsigned int SwathWidthY, + bool VirtualMemoryEnable, + unsigned int VMMPageSize, + unsigned int PTEBufferSizeInRequests, + unsigned int PDEProcessingBufIn64KBReqs, + unsigned int Pitch, + unsigned int DCCMetaPitch, + unsigned int *MacroTileWidth, + unsigned int *MetaRowByte, + unsigned int *PixelPTEBytesPerRow, + bool *PTEBufferSizeNotExceeded, + unsigned int *dpte_row_height, + unsigned int *meta_row_height); +static double CalculateTWait( + unsigned int PrefetchMode, + double DRAMClockChangeLatency, + double UrgentLatency, + double SREnterPlusExitTime); +static double CalculateRemoteSurfaceFlipDelay( + struct display_mode_lib *mode_lib, + double VRatio, + double SwathWidth, + double Bpp, + double LineTime, + double XFCTSlvVupdateOffset, + double XFCTSlvVupdateWidth, + double XFCTSlvVreadyOffset, + double XFCXBUFLatencyTolerance, + double XFCFillBWOverhead, + double XFCSlvChunkSize, + double XFCBusTransportTime, + double TCalc, + double TWait, + double *SrcActiveDrainRate, + double *TInitXFill, + double *TslvChk); +static double CalculateWriteBackDISPCLK( + enum source_format_class WritebackPixelFormat, + double PixelClock, + double WritebackHRatio, + double WritebackVRatio, + unsigned int WritebackLumaHTaps, + unsigned int WritebackLumaVTaps, + unsigned int WritebackChromaHTaps, + unsigned int WritebackChromaVTaps, + double WritebackDestinationWidth, + unsigned int HTotal, + unsigned int WritebackChromaLineBufferWidth); +static void CalculateActiveRowBandwidth( + bool VirtualMemoryEnable, + enum source_format_class SourcePixelFormat, + double VRatio, + bool DCCEnable, + double LineTime, + unsigned int MetaRowByteLuma, + unsigned int MetaRowByteChroma, + unsigned int meta_row_height_luma, + unsigned int meta_row_height_chroma, + unsigned int PixelPTEBytesPerRowLuma, + unsigned int PixelPTEBytesPerRowChroma, + unsigned int dpte_row_height_luma, + unsigned int dpte_row_height_chroma, + double *meta_row_bw, + double *dpte_row_bw, + double *qual_row_bw); +static void CalculateFlipSchedule( + struct display_mode_lib *mode_lib, + double UrgentExtraLatency, + double UrgentLatency, + unsigned int MaxPageTableLevels, + bool VirtualMemoryEnable, + double BandwidthAvailableForImmediateFlip, + unsigned int TotImmediateFlipBytes, + enum source_format_class SourcePixelFormat, + unsigned int ImmediateFlipBytes, + double LineTime, + double Tno_bw, + double VRatio, + double PDEAndMetaPTEBytesFrame, + unsigned int MetaRowByte, + unsigned int PixelPTEBytesPerRow, + bool DCCEnable, + unsigned int dpte_row_height, + unsigned int meta_row_height, + double qual_row_bw, + double *DestinationLinesToRequestVMInImmediateFlip, + double *DestinationLinesToRequestRowInImmediateFlip, + double *final_flip_bw, + bool *ImmediateFlipSupportedForPipe); +static double CalculateWriteBackDelay( + enum source_format_class WritebackPixelFormat, + double WritebackHRatio, + double WritebackVRatio, + unsigned int WritebackLumaHTaps, + unsigned int WritebackLumaVTaps, + unsigned int WritebackChromaHTaps, + unsigned int WritebackChromaVTaps, + unsigned int WritebackDestinationWidth); static void PixelClockAdjustmentForProgressiveToInterlaceUnit(struct display_mode_lib *mode_lib); static unsigned int CursorBppEnumToBits(enum cursor_bpp ebpp); - -void set_prefetch_mode(struct display_mode_lib *mode_lib, - bool cstate_en, - bool pstate_en, - bool ignore_viewport_pos, - bool immediate_flip_support) +static void ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_lib); + +void set_prefetch_mode( + struct display_mode_lib *mode_lib, + bool cstate_en, + bool pstate_en, + bool ignore_viewport_pos, + bool immediate_flip_support) { unsigned int prefetch_mode; @@ -211,11 +229,13 @@ void set_prefetch_mode(struct display_mode_lib *mode_lib, prefetch_mode = 1; else prefetch_mode = 2; - if (prefetch_mode != mode_lib->vba.PrefetchMode || ignore_viewport_pos != mode_lib->vba.IgnoreViewportPositioning - || immediate_flip_support != mode_lib->vba.ImmediateFlipSupport) { - DTRACE(" Prefetch mode has changed from %i to %i. Recalculating.", - prefetch_mode, - mode_lib->vba.PrefetchMode); + if (prefetch_mode != mode_lib->vba.PrefetchMode + || ignore_viewport_pos != mode_lib->vba.IgnoreViewportPositioning + || immediate_flip_support != mode_lib->vba.ImmediateFlipSupport) { + DTRACE( + " Prefetch mode has changed from %i to %i. Recalculating.", + prefetch_mode, + mode_lib->vba.PrefetchMode); mode_lib->vba.PrefetchMode = prefetch_mode; mode_lib->vba.IgnoreViewportPositioning = ignore_viewport_pos; mode_lib->vba.ImmediateFlipSupport = immediate_flip_support; @@ -223,6 +243,39 @@ void set_prefetch_mode(struct display_mode_lib *mode_lib, } } +unsigned int dml_get_voltage_level( + struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *pipes, + unsigned int num_pipes) +{ + bool need_recalculate = memcmp( + &mode_lib->soc, + &mode_lib->vba.soc, + sizeof(mode_lib->vba.soc)) != 0 + || memcmp(&mode_lib->ip, &mode_lib->vba.ip, sizeof(mode_lib->vba.ip)) != 0 + || memcmp(&mode_lib->me, &mode_lib->vba.me, sizeof(mode_lib->vba.me)) != 0 + || num_pipes != mode_lib->vba.cache_num_pipes + || memcmp(pipes, mode_lib->vba.cache_pipes, + sizeof(display_e2e_pipe_params_st) * num_pipes) != 0; + + mode_lib->vba.soc = mode_lib->soc; + mode_lib->vba.ip = mode_lib->ip; + mode_lib->vba.me = mode_lib->me; + memcpy(mode_lib->vba.cache_pipes, pipes, sizeof(*pipes) * num_pipes); + mode_lib->vba.cache_num_pipes = num_pipes; + + if (need_recalculate) + recalculate(mode_lib); + else { + fetch_socbb_params(mode_lib); + fetch_ip_params(mode_lib); + fetch_pipe_params(mode_lib); + } + ModeSupportAndSystemConfigurationFull(mode_lib); + + return mode_lib->vba.VoltageLevel; +} + #define dml_get_attr_func(attr, var) double get_##attr(struct display_mode_lib *mode_lib, const display_e2e_pipe_params_st *pipes, unsigned int num_pipes) \ { \ recalculate_params(mode_lib, pipes, num_pipes); \ @@ -243,7 +296,9 @@ dml_get_attr_func(stutter_efficiency_no_vblank, mode_lib->vba.StutterEfficiencyN dml_get_attr_func(urgent_latency, mode_lib->vba.MinUrgentLatencySupportUs); dml_get_attr_func(urgent_extra_latency, mode_lib->vba.UrgentExtraLatency); dml_get_attr_func(nonurgent_latency, mode_lib->vba.NonUrgentLatencyTolerance); -dml_get_attr_func(dram_clock_change_latency, mode_lib->vba.MinActiveDRAMClockChangeLatencySupported); +dml_get_attr_func( + dram_clock_change_latency, + mode_lib->vba.MinActiveDRAMClockChangeLatencySupported); dml_get_attr_func(dispclk_calculated, mode_lib->vba.DISPCLK_calculated); dml_get_attr_func(total_data_read_bw, mode_lib->vba.TotalDataReadBandwidth); dml_get_attr_func(return_bw, mode_lib->vba.ReturnBW); @@ -269,17 +324,20 @@ dml_get_pipe_attr_func(dst_y_per_vm_vblank, mode_lib->vba.DestinationLinesToRequ dml_get_pipe_attr_func(dst_y_per_row_vblank, mode_lib->vba.DestinationLinesToRequestRowInVBlank); dml_get_pipe_attr_func(dst_y_prefetch, mode_lib->vba.DestinationLinesForPrefetch); dml_get_pipe_attr_func(dst_y_per_vm_flip, mode_lib->vba.DestinationLinesToRequestVMInImmediateFlip); -dml_get_pipe_attr_func(dst_y_per_row_flip, mode_lib->vba.DestinationLinesToRequestRowInImmediateFlip); +dml_get_pipe_attr_func( + dst_y_per_row_flip, + mode_lib->vba.DestinationLinesToRequestRowInImmediateFlip); dml_get_pipe_attr_func(xfc_transfer_delay, mode_lib->vba.XFCTransferDelay); dml_get_pipe_attr_func(xfc_precharge_delay, mode_lib->vba.XFCPrechargeDelay); dml_get_pipe_attr_func(xfc_remote_surface_flip_latency, mode_lib->vba.XFCRemoteSurfaceFlipLatency); dml_get_pipe_attr_func(xfc_prefetch_margin, mode_lib->vba.XFCPrefetchMargin); -unsigned int get_vstartup_calculated(struct display_mode_lib *mode_lib, - const display_e2e_pipe_params_st *pipes, - unsigned int num_pipes, - unsigned int which_pipe) +unsigned int get_vstartup_calculated( + struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *pipes, + unsigned int num_pipes, + unsigned int which_pipe) { unsigned int which_plane; @@ -288,25 +346,28 @@ unsigned int get_vstartup_calculated(struct display_mode_lib *mode_lib, return mode_lib->vba.VStartup[which_plane]; } -double get_total_immediate_flip_bytes(struct display_mode_lib *mode_lib, - const display_e2e_pipe_params_st *pipes, - unsigned int num_pipes) +double get_total_immediate_flip_bytes( + struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *pipes, + unsigned int num_pipes) { recalculate_params(mode_lib, pipes, num_pipes); return mode_lib->vba.TotImmediateFlipBytes; } -double get_total_immediate_flip_bw(struct display_mode_lib *mode_lib, - const display_e2e_pipe_params_st *pipes, - unsigned int num_pipes) +double get_total_immediate_flip_bw( + struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *pipes, + unsigned int num_pipes) { recalculate_params(mode_lib, pipes, num_pipes); return mode_lib->vba.ImmediateFlipBW; } -double get_total_prefetch_bw(struct display_mode_lib *mode_lib, - const display_e2e_pipe_params_st *pipes, - unsigned int num_pipes) +double get_total_prefetch_bw( + struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *pipes, + unsigned int num_pipes) { unsigned int k; double total_prefetch_bw = 0.0; @@ -326,10 +387,11 @@ static void fetch_socbb_params(struct display_mode_lib *mode_lib) mode_lib->vba.ReturnBusWidth = soc->return_bus_width_bytes; mode_lib->vba.NumberOfChannels = soc->num_chans; mode_lib->vba.PercentOfIdealDRAMAndFabricBWReceivedAfterUrgLatency = - soc->ideal_dram_bw_after_urgent_percent; // there's always that one bastard variable that's so long it throws everything out of alignment! + soc->ideal_dram_bw_after_urgent_percent; // there's always that one bastard variable that's so long it throws everything out of alignment! mode_lib->vba.UrgentLatency = soc->urgent_latency_us; mode_lib->vba.RoundTripPingLatencyCycles = soc->round_trip_ping_latency_dcfclk_cycles; - mode_lib->vba.UrgentOutOfOrderReturnPerChannel = soc->urgent_out_of_order_return_per_channel_bytes; + mode_lib->vba.UrgentOutOfOrderReturnPerChannel = + soc->urgent_out_of_order_return_per_channel_bytes; mode_lib->vba.WritebackLatency = soc->writeback_latency_us; mode_lib->vba.SRExitTime = soc->sr_exit_time_us; mode_lib->vba.SREnterPlusExitTime = soc->sr_enter_plus_exit_time_us; @@ -342,7 +404,7 @@ static void fetch_socbb_params(struct display_mode_lib *mode_lib) mode_lib->vba.VMMPageSize = soc->vmm_page_size_bytes; // Set the voltage scaling clocks as the defaults. Most of these will // be set to different values by the test - for (i = 0; i < DC__VOLTAGE_STATES; ++i) + for (i = 0; i < DC__VOLTAGE_STATES; i++) if (soc->clock_limits[i].state == mode_lib->vba.VoltageLevel) break; @@ -353,6 +415,23 @@ static void fetch_socbb_params(struct display_mode_lib *mode_lib) mode_lib->vba.XFCBusTransportTime = soc->xfc_bus_transport_time_us; mode_lib->vba.XFCXBUFLatencyTolerance = soc->xfc_xbuf_latency_tolerance_us; + + mode_lib->vba.SupportGFX7CompatibleTilingIn32bppAnd64bpp = false; + mode_lib->vba.MaxHSCLRatio = 4; + mode_lib->vba.MaxVSCLRatio = 4; + mode_lib->vba.MaxNumWriteback = 0; /*TODO*/ + mode_lib->vba.WritebackLumaAndChromaScalingSupported = true; + mode_lib->vba.Cursor64BppSupport = true; + for (i = 0; i <= DC__VOLTAGE_STATES; i++) { + mode_lib->vba.DCFCLKPerState[i] = soc->clock_limits[i].dcfclk_mhz; + mode_lib->vba.FabricClockPerState[i] = soc->clock_limits[i].fabricclk_mhz; + mode_lib->vba.SOCCLKPerState[i] = soc->clock_limits[i].socclk_mhz; + mode_lib->vba.PHYCLKPerState[i] = soc->clock_limits[i].phyclk_mhz; + mode_lib->vba.MaxDppclk[i] = soc->clock_limits[i].dppclk_mhz; + mode_lib->vba.MaxDSCCLK[i] = soc->clock_limits[i].dscclk_mhz; + mode_lib->vba.DRAMSpeedPerState[i] = soc->clock_limits[i].dram_speed_mhz; + mode_lib->vba.MaxDispclk[i] = soc->clock_limits[i].dispclk_mhz; + } } static void fetch_ip_params(struct display_mode_lib *mode_lib) @@ -360,6 +439,11 @@ static void fetch_ip_params(struct display_mode_lib *mode_lib) ip_params_st *ip = &mode_lib->vba.ip; // IP Parameters + mode_lib->vba.MaxNumDPP = ip->max_num_dpp; + mode_lib->vba.MaxNumOTG = ip->max_num_otg; + mode_lib->vba.CursorChunkSize = ip->cursor_chunk_size; + mode_lib->vba.CursorBufferSize = ip->cursor_buffer_size; + mode_lib->vba.MaxDCHUBToPSCLThroughput = ip->max_dchub_pscl_bw_pix_per_clk; mode_lib->vba.MaxPSCLToLBThroughput = ip->max_pscl_lb_bw_pix_per_clk; mode_lib->vba.ROBBufferSizeInKByte = ip->rob_buffer_size_kbytes; @@ -375,7 +459,8 @@ static void fetch_ip_params(struct display_mode_lib *mode_lib) mode_lib->vba.OPPOutputBufferLines = ip->opp_output_buffer_lines; mode_lib->vba.WritebackInterfaceLumaBufferSize = ip->writeback_luma_buffer_size_kbytes; mode_lib->vba.WritebackInterfaceChromaBufferSize = ip->writeback_chroma_buffer_size_kbytes; - mode_lib->vba.WritebackChromaLineBufferWidth = ip->writeback_chroma_line_buffer_width_pixels; + mode_lib->vba.WritebackChromaLineBufferWidth = + ip->writeback_chroma_line_buffer_width_pixels; mode_lib->vba.MaxPageTableLevels = ip->max_page_table_levels; mode_lib->vba.MaxInterDCNTileRepeaters = ip->max_inter_dcn_tile_repeaters; mode_lib->vba.NumberOfDSC = ip->num_dsc; @@ -402,10 +487,10 @@ static void fetch_pipe_params(struct display_mode_lib *mode_lib) display_e2e_pipe_params_st *pipes = mode_lib->vba.cache_pipes; ip_params_st *ip = &mode_lib->vba.ip; - unsigned int OTGInstPlane[DC__NUM_DPP]; + unsigned int OTGInstPlane[DC__NUM_DPP__MAX]; unsigned int j, k; - bool PlaneVisited[DC__NUM_DPP]; - bool visited[DC__NUM_PIPES__MAX]; + bool PlaneVisited[DC__NUM_DPP__MAX]; + bool visited[DC__NUM_DPP__MAX]; // Convert Pipes to Planes for (k = 0; k < mode_lib->vba.cache_num_pipes; ++k) @@ -427,11 +512,16 @@ static void fetch_pipe_params(struct display_mode_lib *mode_lib) mode_lib->vba.pipe_plane[j] = mode_lib->vba.NumberOfActivePlanes; mode_lib->vba.DPPPerPlane[mode_lib->vba.NumberOfActivePlanes] = 1; - mode_lib->vba.SourceScan[mode_lib->vba.NumberOfActivePlanes] = (enum scan_direction_class)(src->source_scan); - mode_lib->vba.ViewportWidth[mode_lib->vba.NumberOfActivePlanes] = src->viewport_width; - mode_lib->vba.ViewportHeight[mode_lib->vba.NumberOfActivePlanes] = src->viewport_height; - mode_lib->vba.ViewportYStartY[mode_lib->vba.NumberOfActivePlanes] = src->viewport_y_y; - mode_lib->vba.ViewportYStartC[mode_lib->vba.NumberOfActivePlanes] = src->viewport_y_c; + mode_lib->vba.SourceScan[mode_lib->vba.NumberOfActivePlanes] = + (enum scan_direction_class) (src->source_scan); + mode_lib->vba.ViewportWidth[mode_lib->vba.NumberOfActivePlanes] = + src->viewport_width; + mode_lib->vba.ViewportHeight[mode_lib->vba.NumberOfActivePlanes] = + src->viewport_height; + mode_lib->vba.ViewportYStartY[mode_lib->vba.NumberOfActivePlanes] = + src->viewport_y_y; + mode_lib->vba.ViewportYStartC[mode_lib->vba.NumberOfActivePlanes] = + src->viewport_y_c; mode_lib->vba.PitchY[mode_lib->vba.NumberOfActivePlanes] = src->data_pitch; mode_lib->vba.PitchC[mode_lib->vba.NumberOfActivePlanes] = src->data_pitch_c; mode_lib->vba.DCCMetaPitchY[mode_lib->vba.NumberOfActivePlanes] = src->meta_pitch; @@ -448,40 +538,62 @@ static void fetch_pipe_params(struct display_mode_lib *mode_lib) mode_lib->vba.HTotal[mode_lib->vba.NumberOfActivePlanes] = dst->htotal; mode_lib->vba.VTotal[mode_lib->vba.NumberOfActivePlanes] = dst->vtotal; mode_lib->vba.DCCEnable[mode_lib->vba.NumberOfActivePlanes] = - src->dcc_use_global ? ip->dcc_supported : src->dcc & ip->dcc_supported; + src->dcc_use_global ? + ip->dcc_supported : src->dcc && ip->dcc_supported; mode_lib->vba.DCCRate[mode_lib->vba.NumberOfActivePlanes] = src->dcc_rate; - mode_lib->vba.SourcePixelFormat[mode_lib->vba.NumberOfActivePlanes] = (enum source_format_class)(src->source_format); + mode_lib->vba.SourcePixelFormat[mode_lib->vba.NumberOfActivePlanes] = + (enum source_format_class) (src->source_format); mode_lib->vba.HActive[mode_lib->vba.NumberOfActivePlanes] = dst->hactive; mode_lib->vba.VActive[mode_lib->vba.NumberOfActivePlanes] = dst->vactive; - mode_lib->vba.SurfaceTiling[mode_lib->vba.NumberOfActivePlanes] = (enum dm_swizzle_mode)(src->sw_mode); - mode_lib->vba.ScalerRecoutWidth[mode_lib->vba.NumberOfActivePlanes] = dst->recout_width; // TODO: or should this be full_recout_width???...maybe only when in hsplit mode? - mode_lib->vba.ODMCombineEnabled[mode_lib->vba.NumberOfActivePlanes] = dst->odm_combine; - mode_lib->vba.OutputFormat[mode_lib->vba.NumberOfActivePlanes] = (enum output_format_class)(dout->output_format); - mode_lib->vba.Output[mode_lib->vba.NumberOfActivePlanes] = (enum output_encoder_class)(dout->output_type); + mode_lib->vba.SurfaceTiling[mode_lib->vba.NumberOfActivePlanes] = + (enum dm_swizzle_mode) (src->sw_mode); + mode_lib->vba.ScalerRecoutWidth[mode_lib->vba.NumberOfActivePlanes] = + dst->recout_width; // TODO: or should this be full_recout_width???...maybe only when in hsplit mode? + mode_lib->vba.ODMCombineEnabled[mode_lib->vba.NumberOfActivePlanes] = + dst->odm_combine; + mode_lib->vba.OutputFormat[mode_lib->vba.NumberOfActivePlanes] = + (enum output_format_class) (dout->output_format); + mode_lib->vba.Output[mode_lib->vba.NumberOfActivePlanes] = + (enum output_encoder_class) (dout->output_type); mode_lib->vba.OutputBpp[mode_lib->vba.NumberOfActivePlanes] = dout->output_bpp; + mode_lib->vba.OutputLinkDPLanes[mode_lib->vba.NumberOfActivePlanes] = + dout->dp_lanes; mode_lib->vba.DSCEnabled[mode_lib->vba.NumberOfActivePlanes] = dout->dsc_enable; - mode_lib->vba.NumberOfDSCSlices[mode_lib->vba.NumberOfActivePlanes] = dout->dsc_slices; + mode_lib->vba.NumberOfDSCSlices[mode_lib->vba.NumberOfActivePlanes] = + dout->dsc_slices; mode_lib->vba.DSCInputBitPerComponent[mode_lib->vba.NumberOfActivePlanes] = - dout->output_bpc == 0 ? 12 : dout->output_bpc; + dout->output_bpc == 0 ? 12 : dout->output_bpc; mode_lib->vba.WritebackEnable[mode_lib->vba.NumberOfActivePlanes] = dout->wb_enable; - mode_lib->vba.WritebackSourceHeight[mode_lib->vba.NumberOfActivePlanes] = dout->wb.wb_src_height; - mode_lib->vba.WritebackDestinationWidth[mode_lib->vba.NumberOfActivePlanes] = dout->wb.wb_dst_width; - mode_lib->vba.WritebackDestinationHeight[mode_lib->vba.NumberOfActivePlanes] = dout->wb.wb_dst_height; - mode_lib->vba.WritebackPixelFormat[mode_lib->vba.NumberOfActivePlanes] = (enum source_format_class)(dout->wb.wb_pixel_format); - mode_lib->vba.WritebackLumaHTaps[mode_lib->vba.NumberOfActivePlanes] = dout->wb.wb_htaps_luma; - mode_lib->vba.WritebackLumaVTaps[mode_lib->vba.NumberOfActivePlanes] = dout->wb.wb_vtaps_luma; - mode_lib->vba.WritebackChromaHTaps[mode_lib->vba.NumberOfActivePlanes] = dout->wb.wb_htaps_chroma; - mode_lib->vba.WritebackChromaVTaps[mode_lib->vba.NumberOfActivePlanes] = dout->wb.wb_vtaps_chroma; - mode_lib->vba.WritebackHRatio[mode_lib->vba.NumberOfActivePlanes] = dout->wb.wb_hratio; - mode_lib->vba.WritebackVRatio[mode_lib->vba.NumberOfActivePlanes] = dout->wb.wb_vratio; - - mode_lib->vba.DynamicMetadataEnable[mode_lib->vba.NumberOfActivePlanes] = src->dynamic_metadata_enable; + mode_lib->vba.WritebackSourceHeight[mode_lib->vba.NumberOfActivePlanes] = + dout->wb.wb_src_height; + mode_lib->vba.WritebackDestinationWidth[mode_lib->vba.NumberOfActivePlanes] = + dout->wb.wb_dst_width; + mode_lib->vba.WritebackDestinationHeight[mode_lib->vba.NumberOfActivePlanes] = + dout->wb.wb_dst_height; + mode_lib->vba.WritebackPixelFormat[mode_lib->vba.NumberOfActivePlanes] = + (enum source_format_class) (dout->wb.wb_pixel_format); + mode_lib->vba.WritebackLumaHTaps[mode_lib->vba.NumberOfActivePlanes] = + dout->wb.wb_htaps_luma; + mode_lib->vba.WritebackLumaVTaps[mode_lib->vba.NumberOfActivePlanes] = + dout->wb.wb_vtaps_luma; + mode_lib->vba.WritebackChromaHTaps[mode_lib->vba.NumberOfActivePlanes] = + dout->wb.wb_htaps_chroma; + mode_lib->vba.WritebackChromaVTaps[mode_lib->vba.NumberOfActivePlanes] = + dout->wb.wb_vtaps_chroma; + mode_lib->vba.WritebackHRatio[mode_lib->vba.NumberOfActivePlanes] = + dout->wb.wb_hratio; + mode_lib->vba.WritebackVRatio[mode_lib->vba.NumberOfActivePlanes] = + dout->wb.wb_vratio; + + mode_lib->vba.DynamicMetadataEnable[mode_lib->vba.NumberOfActivePlanes] = + src->dynamic_metadata_enable; mode_lib->vba.DynamicMetadataLinesBeforeActiveRequired[mode_lib->vba.NumberOfActivePlanes] = - src->dynamic_metadata_lines_before_active; + src->dynamic_metadata_lines_before_active; mode_lib->vba.DynamicMetadataTransmittedBytes[mode_lib->vba.NumberOfActivePlanes] = - src->dynamic_metadata_xmit_bytes; + src->dynamic_metadata_xmit_bytes; - mode_lib->vba.XFCEnabled[mode_lib->vba.NumberOfActivePlanes] = src->xfc_enable && ip->xfc_supported; + mode_lib->vba.XFCEnabled[mode_lib->vba.NumberOfActivePlanes] = src->xfc_enable + && ip->xfc_supported; mode_lib->vba.XFCSlvChunkSize = src->xfc_params.xfc_slv_chunk_size_bytes; mode_lib->vba.XFCTSlvVupdateOffset = src->xfc_params.xfc_tslv_vupdate_offset_us; mode_lib->vba.XFCTSlvVupdateWidth = src->xfc_params.xfc_tslv_vupdate_width_us; @@ -489,7 +601,8 @@ static void fetch_pipe_params(struct display_mode_lib *mode_lib) mode_lib->vba.PixelClock[mode_lib->vba.NumberOfActivePlanes] = dst->pixel_rate_mhz; mode_lib->vba.DPPCLK[mode_lib->vba.NumberOfActivePlanes] = clks->dppclk_mhz; if (ip->is_line_buffer_bpp_fixed) - mode_lib->vba.LBBitPerPixel[mode_lib->vba.NumberOfActivePlanes] = ip->line_buffer_fixed_bpp; + mode_lib->vba.LBBitPerPixel[mode_lib->vba.NumberOfActivePlanes] = + ip->line_buffer_fixed_bpp; else { unsigned int lb_depth; @@ -520,27 +633,36 @@ static void fetch_pipe_params(struct display_mode_lib *mode_lib) for (k = 0; k < DC__NUM_CURSOR; ++k) { switch (k) { case 0: - mode_lib->vba.CursorBPP[mode_lib->vba.NumberOfActivePlanes][0] = CursorBppEnumToBits((enum cursor_bpp)(src->cur0_bpp)); - mode_lib->vba.CursorWidth[mode_lib->vba.NumberOfActivePlanes][0] = src->cur0_src_width; + mode_lib->vba.CursorBPP[mode_lib->vba.NumberOfActivePlanes][0] = + CursorBppEnumToBits( + (enum cursor_bpp) (src->cur0_bpp)); + mode_lib->vba.CursorWidth[mode_lib->vba.NumberOfActivePlanes][0] = + src->cur0_src_width; if (src->cur0_src_width > 0) mode_lib->vba.NumberOfCursors[mode_lib->vba.NumberOfActivePlanes]++; break; case 1: - mode_lib->vba.CursorBPP[mode_lib->vba.NumberOfActivePlanes][1] = CursorBppEnumToBits((enum cursor_bpp)(src->cur1_bpp)); - mode_lib->vba.CursorWidth[mode_lib->vba.NumberOfActivePlanes][1] = src->cur1_src_width; + mode_lib->vba.CursorBPP[mode_lib->vba.NumberOfActivePlanes][1] = + CursorBppEnumToBits( + (enum cursor_bpp) (src->cur1_bpp)); + mode_lib->vba.CursorWidth[mode_lib->vba.NumberOfActivePlanes][1] = + src->cur1_src_width; if (src->cur1_src_width > 0) mode_lib->vba.NumberOfCursors[mode_lib->vba.NumberOfActivePlanes]++; break; default: - dml_print("ERROR: Number of cursors specified exceeds supported maximum\n"); + dml_print( + "ERROR: Number of cursors specified exceeds supported maximum\n") + ; } } OTGInstPlane[mode_lib->vba.NumberOfActivePlanes] = dst->otg_inst; if (dst->odm_combine && !src->is_hsplit) - dml_print("ERROR: ODM Combine is specified but is_hsplit has not be specified for pipe %i\n", - j); + dml_print( + "ERROR: ODM Combine is specified but is_hsplit has not be specified for pipe %i\n", + j); if (src->is_hsplit) { for (k = j + 1; k < mode_lib->vba.cache_num_pipes; ++k) { @@ -548,18 +670,20 @@ static void fetch_pipe_params(struct display_mode_lib *mode_lib) display_output_params_st *dout_k = &pipes[k].dout; if (src_k->is_hsplit && !visited[k] - && src->hsplit_grp == src_k->hsplit_grp) { - mode_lib->vba.pipe_plane[k] = mode_lib->vba.NumberOfActivePlanes; + && src->hsplit_grp == src_k->hsplit_grp) { + mode_lib->vba.pipe_plane[k] = + mode_lib->vba.NumberOfActivePlanes; mode_lib->vba.DPPPerPlane[mode_lib->vba.NumberOfActivePlanes]++; - if (mode_lib->vba.SourceScan[mode_lib->vba.NumberOfActivePlanes] == dm_horz) + if (mode_lib->vba.SourceScan[mode_lib->vba.NumberOfActivePlanes] + == dm_horz) mode_lib->vba.ViewportWidth[mode_lib->vba.NumberOfActivePlanes] += - src_k->viewport_width; + src_k->viewport_width; else mode_lib->vba.ViewportHeight[mode_lib->vba.NumberOfActivePlanes] += - src_k->viewport_height; + src_k->viewport_height; mode_lib->vba.NumberOfDSCSlices[mode_lib->vba.NumberOfActivePlanes] += - dout_k->dsc_slices; + dout_k->dsc_slices; visited[k] = true; } } @@ -598,26 +722,30 @@ static void fetch_pipe_params(struct display_mode_lib *mode_lib) for (k = 1; k < mode_lib->vba.cache_num_pipes; ++k) ASSERT(mode_lib->vba.SynchronizedVBlank == pipes[k].pipe.dest.synchronized_vblank_all_planes); - mode_lib->vba.VirtualMemoryEnable = 0; + mode_lib->vba.VirtualMemoryEnable = false; mode_lib->vba.OverridePageTableLevels = 0; for (k = 0; k < mode_lib->vba.cache_num_pipes; ++k) { - mode_lib->vba.VirtualMemoryEnable |= pipes[k].pipe.src.vm; + mode_lib->vba.VirtualMemoryEnable = mode_lib->vba.VirtualMemoryEnable + || !!pipes[k].pipe.src.vm; mode_lib->vba.OverridePageTableLevels = - (pipes[k].pipe.src.vm_levels_force_en - && mode_lib->vba.OverridePageTableLevels - < pipes[k].pipe.src.vm_levels_force) ? - pipes[k].pipe.src.vm_levels_force : - mode_lib->vba.OverridePageTableLevels; + (pipes[k].pipe.src.vm_levels_force_en + && mode_lib->vba.OverridePageTableLevels + < pipes[k].pipe.src.vm_levels_force) ? + pipes[k].pipe.src.vm_levels_force : + mode_lib->vba.OverridePageTableLevels; } if (mode_lib->vba.OverridePageTableLevels) mode_lib->vba.MaxPageTableLevels = mode_lib->vba.OverridePageTableLevels; - mode_lib->vba.VirtualMemoryEnable &= ip->pte_enable; + mode_lib->vba.VirtualMemoryEnable = mode_lib->vba.VirtualMemoryEnable && !!ip->pte_enable; - mode_lib->vba.FabricAndDRAMBandwidth = dml_min(mode_lib->vba.DRAMSpeed * mode_lib->vba.NumberOfChannels * mode_lib->vba.DRAMChannelWidth, - mode_lib->vba.FabricClock * mode_lib->vba.FabricDatapathToDCNDataReturn) / 1000.0; + mode_lib->vba.FabricAndDRAMBandwidth = dml_min( + mode_lib->vba.DRAMSpeed * mode_lib->vba.NumberOfChannels + * mode_lib->vba.DRAMChannelWidth, + mode_lib->vba.FabricClock * mode_lib->vba.FabricDatapathToDCNDataReturn) + / 1000.0; // TODO: Must be consistent across all pipes // DCCProgrammingAssumesScanDirectionUnknown = src.dcc_scan_dir_unknown; @@ -633,16 +761,20 @@ static void recalculate(struct display_mode_lib *mode_lib) // in wm mode we pull the parameters needed from the display_e2e_pipe_params_st structs // rather than working them out as in recalculate_ms -static void recalculate_params(struct display_mode_lib *mode_lib, - const display_e2e_pipe_params_st *pipes, - unsigned int num_pipes) +static void recalculate_params( + struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *pipes, + unsigned int num_pipes) { // This is only safe to use memcmp because there are non-POD types in struct display_mode_lib if (memcmp(&mode_lib->soc, &mode_lib->vba.soc, sizeof(mode_lib->vba.soc)) != 0 || memcmp(&mode_lib->ip, &mode_lib->vba.ip, sizeof(mode_lib->vba.ip)) != 0 || memcmp(&mode_lib->me, &mode_lib->vba.me, sizeof(mode_lib->vba.me)) != 0 || num_pipes != mode_lib->vba.cache_num_pipes - || memcmp(pipes, mode_lib->vba.cache_pipes, sizeof(display_e2e_pipe_params_st) * num_pipes) != 0) { + || memcmp( + pipes, + mode_lib->vba.cache_pipes, + sizeof(display_e2e_pipe_params_st) * num_pipes) != 0) { mode_lib->vba.soc = mode_lib->soc; mode_lib->vba.ip = mode_lib->ip; mode_lib->vba.me = mode_lib->me; @@ -677,55 +809,70 @@ static void ModeSupportAndSystemConfiguration(struct display_mode_lib *mode_lib) // Total Available Pipes Support Check for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) total_pipes += mode_lib->vba.DPPPerPlane[k]; - ASSERT(total_pipes <= DC__NUM_DPP); + ASSERT(total_pipes <= DC__NUM_DPP__MAX); } -static double adjust_ReturnBW(struct display_mode_lib *mode_lib, double ReturnBW, bool DCCEnabledAnyPlane, double ReturnBandwidthToDCN) +static double adjust_ReturnBW( + struct display_mode_lib *mode_lib, + double ReturnBW, + bool DCCEnabledAnyPlane, + double ReturnBandwidthToDCN) { double CriticalCompression; - if (DCCEnabledAnyPlane && ReturnBandwidthToDCN > mode_lib->vba.DCFCLK * mode_lib->vba.ReturnBusWidth / 4.0) + if (DCCEnabledAnyPlane + && ReturnBandwidthToDCN + > mode_lib->vba.DCFCLK * mode_lib->vba.ReturnBusWidth / 4.0) ReturnBW = - dml_min(ReturnBW, - ReturnBandwidthToDCN * 4 - * (1.0 - - mode_lib->vba.UrgentLatency - / ((mode_lib->vba.ROBBufferSizeInKByte - - mode_lib->vba.PixelChunkSizeInKByte) - * 1024 - / ReturnBandwidthToDCN - - mode_lib->vba.DCFCLK - * mode_lib->vba.ReturnBusWidth - / 4) - + mode_lib->vba.UrgentLatency)); - - CriticalCompression = 2.0 * mode_lib->vba.ReturnBusWidth * mode_lib->vba.DCFCLK * mode_lib->vba.UrgentLatency - / (ReturnBandwidthToDCN * mode_lib->vba.UrgentLatency - + (mode_lib->vba.ROBBufferSizeInKByte - mode_lib->vba.PixelChunkSizeInKByte) * 1024); + dml_min( + ReturnBW, + ReturnBandwidthToDCN * 4 + * (1.0 + - mode_lib->vba.UrgentLatency + / ((mode_lib->vba.ROBBufferSizeInKByte + - mode_lib->vba.PixelChunkSizeInKByte) + * 1024 + / ReturnBandwidthToDCN + - mode_lib->vba.DCFCLK + * mode_lib->vba.ReturnBusWidth + / 4) + + mode_lib->vba.UrgentLatency)); + + CriticalCompression = 2.0 * mode_lib->vba.ReturnBusWidth * mode_lib->vba.DCFCLK + * mode_lib->vba.UrgentLatency + / (ReturnBandwidthToDCN * mode_lib->vba.UrgentLatency + + (mode_lib->vba.ROBBufferSizeInKByte + - mode_lib->vba.PixelChunkSizeInKByte) + * 1024); if (DCCEnabledAnyPlane && CriticalCompression > 1.0 && CriticalCompression < 4.0) ReturnBW = - dml_min(ReturnBW, - 4.0 * ReturnBandwidthToDCN - * (mode_lib->vba.ROBBufferSizeInKByte - - mode_lib->vba.PixelChunkSizeInKByte) - * 1024 * mode_lib->vba.ReturnBusWidth * mode_lib->vba.DCFCLK - * mode_lib->vba.UrgentLatency - / dml_pow((ReturnBandwidthToDCN - * mode_lib->vba.UrgentLatency - + (mode_lib->vba.ROBBufferSizeInKByte - - mode_lib->vba.PixelChunkSizeInKByte) - * 1024), - 2)); + dml_min( + ReturnBW, + 4.0 * ReturnBandwidthToDCN + * (mode_lib->vba.ROBBufferSizeInKByte + - mode_lib->vba.PixelChunkSizeInKByte) + * 1024 + * mode_lib->vba.ReturnBusWidth + * mode_lib->vba.DCFCLK + * mode_lib->vba.UrgentLatency + / dml_pow( + (ReturnBandwidthToDCN + * mode_lib->vba.UrgentLatency + + (mode_lib->vba.ROBBufferSizeInKByte + - mode_lib->vba.PixelChunkSizeInKByte) + * 1024), + 2)); return ReturnBW; } -static unsigned int dscceComputeDelay(unsigned int bpc, - double bpp, - unsigned int sliceWidth, - unsigned int numSlices, - enum output_format_class pixelFormat) +static unsigned int dscceComputeDelay( + unsigned int bpc, + double bpp, + unsigned int sliceWidth, + unsigned int numSlices, + enum output_format_class pixelFormat) { // valid bpc = source bits per component in the set of {8, 10, 12} // valid bpp = increments of 1/16 of a bit @@ -739,12 +886,12 @@ static unsigned int dscceComputeDelay(unsigned int bpc, unsigned int rcModelSize = 8192; // N422/N420 operate at 2 pixels per clock - unsigned int pixelsPerClock, lstall, D, initalXmitDelay, w, s, ix, wx, p, l0, a, ax, l, Delay, - pixels; + unsigned int pixelsPerClock, lstall, D, initalXmitDelay, w, s, ix, wx, p, l0, a, ax, l, + Delay, pixels; if (pixelFormat == dm_n422 || pixelFormat == dm_420) pixelsPerClock = 2; - // #all other modes operate at 1 pixel per clock + // #all other modes operate at 1 pixel per clock else pixelsPerClock = 1; @@ -859,66 +1006,67 @@ static unsigned int dscComputeDelay(enum output_format_class pixelFormat) return Delay; } -static bool CalculatePrefetchSchedule(struct display_mode_lib *mode_lib, - double DPPCLK, - double DISPCLK, - double PixelClock, - double DCFClkDeepSleep, - unsigned int DSCDelay, - unsigned int DPPPerPlane, - bool ScalerEnabled, - unsigned int NumberOfCursors, - double DPPCLKDelaySubtotal, - double DPPCLKDelaySCL, - double DPPCLKDelaySCLLBOnly, - double DPPCLKDelayCNVCFormater, - double DPPCLKDelayCNVCCursor, - double DISPCLKDelaySubtotal, - unsigned int ScalerRecoutWidth, - enum output_format_class OutputFormat, - unsigned int VBlank, - unsigned int HTotal, - unsigned int MaxInterDCNTileRepeaters, - unsigned int VStartup, - unsigned int PageTableLevels, - bool VirtualMemoryEnable, - bool DynamicMetadataEnable, - unsigned int DynamicMetadataLinesBeforeActiveRequired, - unsigned int DynamicMetadataTransmittedBytes, - bool DCCEnable, - double UrgentLatency, - double UrgentExtraLatency, - double TCalc, - unsigned int PDEAndMetaPTEBytesFrame, - unsigned int MetaRowByte, - unsigned int PixelPTEBytesPerRow, - double PrefetchSourceLinesY, - unsigned int SwathWidthY, - double BytePerPixelDETY, - double VInitPreFillY, - unsigned int MaxNumSwathY, - double PrefetchSourceLinesC, - double BytePerPixelDETC, - double VInitPreFillC, - unsigned int MaxNumSwathC, - unsigned int SwathHeightY, - unsigned int SwathHeightC, - double TWait, - bool XFCEnabled, - double XFCRemoteSurfaceFlipDelay, - bool InterlaceEnable, - bool ProgressiveToInterlaceUnitInOPP, - double *DSTXAfterScaler, - double *DSTYAfterScaler, - double *DestinationLinesForPrefetch, - double *PrefetchBandwidth, - double *DestinationLinesToRequestVMInVBlank, - double *DestinationLinesToRequestRowInVBlank, - double *VRatioPrefetchY, - double *VRatioPrefetchC, - double *RequiredPrefetchPixDataBW, - unsigned int *VStartupRequiredWhenNotEnoughTimeForDynamicMetadata, - double *Tno_bw) +static bool CalculatePrefetchSchedule( + struct display_mode_lib *mode_lib, + double DPPCLK, + double DISPCLK, + double PixelClock, + double DCFClkDeepSleep, + unsigned int DSCDelay, + unsigned int DPPPerPlane, + bool ScalerEnabled, + unsigned int NumberOfCursors, + double DPPCLKDelaySubtotal, + double DPPCLKDelaySCL, + double DPPCLKDelaySCLLBOnly, + double DPPCLKDelayCNVCFormater, + double DPPCLKDelayCNVCCursor, + double DISPCLKDelaySubtotal, + unsigned int ScalerRecoutWidth, + enum output_format_class OutputFormat, + unsigned int VBlank, + unsigned int HTotal, + unsigned int MaxInterDCNTileRepeaters, + unsigned int VStartup, + unsigned int PageTableLevels, + bool VirtualMemoryEnable, + bool DynamicMetadataEnable, + unsigned int DynamicMetadataLinesBeforeActiveRequired, + unsigned int DynamicMetadataTransmittedBytes, + bool DCCEnable, + double UrgentLatency, + double UrgentExtraLatency, + double TCalc, + unsigned int PDEAndMetaPTEBytesFrame, + unsigned int MetaRowByte, + unsigned int PixelPTEBytesPerRow, + double PrefetchSourceLinesY, + unsigned int SwathWidthY, + double BytePerPixelDETY, + double VInitPreFillY, + unsigned int MaxNumSwathY, + double PrefetchSourceLinesC, + double BytePerPixelDETC, + double VInitPreFillC, + unsigned int MaxNumSwathC, + unsigned int SwathHeightY, + unsigned int SwathHeightC, + double TWait, + bool XFCEnabled, + double XFCRemoteSurfaceFlipDelay, + bool InterlaceEnable, + bool ProgressiveToInterlaceUnitInOPP, + double *DSTXAfterScaler, + double *DSTYAfterScaler, + double *DestinationLinesForPrefetch, + double *PrefetchBandwidth, + double *DestinationLinesToRequestVMInVBlank, + double *DestinationLinesToRequestRowInVBlank, + double *VRatioPrefetchY, + double *VRatioPrefetchC, + double *RequiredPrefetchPixDataBW, + unsigned int *VStartupRequiredWhenNotEnoughTimeForDynamicMetadata, + double *Tno_bw) { bool MyError = false; unsigned int DPPCycles, DISPCLKCycles, VUpdateOffsetPix, VUpdateWidthPix, VReadyOffsetPix; @@ -948,7 +1096,7 @@ static bool CalculatePrefetchSchedule(struct display_mode_lib *mode_lib, return true; *DSTXAfterScaler = DPPCycles * PixelClock / DPPCLK + DISPCLKCycles * PixelClock / DISPCLK - + DSCDelay; + + DSCDelay; if (DPPPerPlane > 1) *DSTXAfterScaler = *DSTXAfterScaler + ScalerRecoutWidth; @@ -958,22 +1106,23 @@ static bool CalculatePrefetchSchedule(struct display_mode_lib *mode_lib, else *DSTYAfterScaler = 0; - DSTTotalPixelsAfterScaler = ((double)(*DSTYAfterScaler * HTotal)) + *DSTXAfterScaler; + DSTTotalPixelsAfterScaler = ((double) (*DSTYAfterScaler * HTotal)) + *DSTXAfterScaler; *DSTYAfterScaler = dml_floor(DSTTotalPixelsAfterScaler / HTotal, 1); - *DSTXAfterScaler = DSTTotalPixelsAfterScaler - ((double)(*DSTYAfterScaler * HTotal)); + *DSTXAfterScaler = DSTTotalPixelsAfterScaler - ((double) (*DSTYAfterScaler * HTotal)); VUpdateOffsetPix = dml_ceil(HTotal / 4.0, 1); TotalRepeaterDelayTime = MaxInterDCNTileRepeaters * (2.0 / DPPCLK + 3.0 / DISPCLK); VUpdateWidthPix = (14.0 / DCFClkDeepSleep + 12.0 / DPPCLK + TotalRepeaterDelayTime) - * PixelClock; + * PixelClock; - VReadyOffsetPix = dml_max(150.0 / DPPCLK, - TotalRepeaterDelayTime + 20.0 / DCFClkDeepSleep + 10.0 / DPPCLK) - * PixelClock; + VReadyOffsetPix = dml_max( + 150.0 / DPPCLK, + TotalRepeaterDelayTime + 20.0 / DCFClkDeepSleep + 10.0 / DPPCLK) + * PixelClock; - Tsetup = (double)(VUpdateOffsetPix + VUpdateWidthPix + VReadyOffsetPix) / PixelClock; + Tsetup = (double) (VUpdateOffsetPix + VUpdateWidthPix + VReadyOffsetPix) / PixelClock; - LineTime = (double)HTotal / PixelClock; + LineTime = (double) HTotal / PixelClock; if (DynamicMetadataEnable) { double Tdmbf, Tdmec, Tdmsks; @@ -988,10 +1137,10 @@ static bool CalculatePrefetchSchedule(struct display_mode_lib *mode_lib, if (InterlaceEnable && !ProgressiveToInterlaceUnitInOPP) Tdmsks = Tdmsks / 2; if (VStartup * LineTime - < Tsetup + TWait + UrgentExtraLatency + Tdmbf + Tdmec + Tdmsks) { + < Tsetup + TWait + UrgentExtraLatency + Tdmbf + Tdmec + Tdmsks) { MyError = true; *VStartupRequiredWhenNotEnoughTimeForDynamicMetadata = (Tsetup + TWait - + UrgentExtraLatency + Tdmbf + Tdmec + Tdmsks) / LineTime; + + UrgentExtraLatency + Tdmbf + Tdmec + Tdmsks) / LineTime; } else *VStartupRequiredWhenNotEnoughTimeForDynamicMetadata = 0.0; } else @@ -1010,30 +1159,33 @@ static bool CalculatePrefetchSchedule(struct display_mode_lib *mode_lib, *Tno_bw = LineTime / 4; dst_y_prefetch_equ = VStartup - dml_max(TCalc + TWait, XFCRemoteSurfaceFlipDelay) / LineTime - - (Tsetup + Tdm) / LineTime - - (*DSTYAfterScaler + *DSTXAfterScaler / HTotal); + - (Tsetup + Tdm) / LineTime + - (*DSTYAfterScaler + *DSTXAfterScaler / HTotal); Tsw_oto = dml_max(PrefetchSourceLinesY, PrefetchSourceLinesC) * LineTime; prefetch_bw_oto = (MetaRowByte + PixelPTEBytesPerRow - + PrefetchSourceLinesY * SwathWidthY * dml_ceil(BytePerPixelDETY, 1) - + PrefetchSourceLinesC * SwathWidthY / 2 * dml_ceil(BytePerPixelDETC, 2)) - / Tsw_oto; + + PrefetchSourceLinesY * SwathWidthY * dml_ceil(BytePerPixelDETY, 1) + + PrefetchSourceLinesC * SwathWidthY / 2 * dml_ceil(BytePerPixelDETC, 2)) + / Tsw_oto; if (VirtualMemoryEnable == true) { Tvm_oto = - dml_max(*Tno_bw + PDEAndMetaPTEBytesFrame / prefetch_bw_oto, - dml_max(UrgentExtraLatency - + UrgentLatency - * (PageTableLevels - - 1), - LineTime / 4.0)); + dml_max( + *Tno_bw + PDEAndMetaPTEBytesFrame / prefetch_bw_oto, + dml_max( + UrgentExtraLatency + + UrgentLatency + * (PageTableLevels + - 1), + LineTime / 4.0)); } else Tvm_oto = LineTime / 4.0; if ((VirtualMemoryEnable == true || DCCEnable == true)) { - Tr0_oto = dml_max((MetaRowByte + PixelPTEBytesPerRow) / prefetch_bw_oto, - dml_max(UrgentLatency, dml_max(LineTime - Tvm_oto, LineTime / 4))); + Tr0_oto = dml_max( + (MetaRowByte + PixelPTEBytesPerRow) / prefetch_bw_oto, + dml_max(UrgentLatency, dml_max(LineTime - Tvm_oto, LineTime / 4))); } else Tr0_oto = LineTime - Tvm_oto; @@ -1046,7 +1198,8 @@ static bool CalculatePrefetchSchedule(struct display_mode_lib *mode_lib, else *DestinationLinesForPrefetch = dst_y_prefetch_equ; - *DestinationLinesForPrefetch = dml_floor(4.0 * (*DestinationLinesForPrefetch + 0.125), 1) / 4; + *DestinationLinesForPrefetch = dml_floor(4.0 * (*DestinationLinesForPrefetch + 0.125), 1) + / 4; dml_print("DML: VStartup: %d\n", VStartup); dml_print("DML: TCalc: %f\n", TCalc); @@ -1067,21 +1220,23 @@ static bool CalculatePrefetchSchedule(struct display_mode_lib *mode_lib, *RequiredPrefetchPixDataBW = 0; if (*DestinationLinesForPrefetch > 1) { *PrefetchBandwidth = (PDEAndMetaPTEBytesFrame + 2 * MetaRowByte - + 2 * PixelPTEBytesPerRow - + PrefetchSourceLinesY * SwathWidthY * dml_ceil(BytePerPixelDETY, 1) - + PrefetchSourceLinesC * SwathWidthY / 2 - * dml_ceil(BytePerPixelDETC, 2)) - / (*DestinationLinesForPrefetch * LineTime - *Tno_bw); + + 2 * PixelPTEBytesPerRow + + PrefetchSourceLinesY * SwathWidthY * dml_ceil(BytePerPixelDETY, 1) + + PrefetchSourceLinesC * SwathWidthY / 2 + * dml_ceil(BytePerPixelDETC, 2)) + / (*DestinationLinesForPrefetch * LineTime - *Tno_bw); if (VirtualMemoryEnable) { TimeForFetchingMetaPTE = - dml_max(*Tno_bw - + (double)PDEAndMetaPTEBytesFrame - / *PrefetchBandwidth, - dml_max(UrgentExtraLatency - + UrgentLatency - * (PageTableLevels - - 1), - LineTime / 4)); + dml_max( + *Tno_bw + + (double) PDEAndMetaPTEBytesFrame + / *PrefetchBandwidth, + dml_max( + UrgentExtraLatency + + UrgentLatency + * (PageTableLevels + - 1), + LineTime / 4)); } else { if (NumberOfCursors > 0 || XFCEnabled) TimeForFetchingMetaPTE = LineTime / 4; @@ -1091,13 +1246,16 @@ static bool CalculatePrefetchSchedule(struct display_mode_lib *mode_lib, if ((VirtualMemoryEnable == true || DCCEnable == true)) { TimeForFetchingRowInVBlank = - dml_max((MetaRowByte + PixelPTEBytesPerRow) - / *PrefetchBandwidth, - dml_max(UrgentLatency, - dml_max(LineTime - - TimeForFetchingMetaPTE, - LineTime - / 4.0))); + dml_max( + (MetaRowByte + PixelPTEBytesPerRow) + / *PrefetchBandwidth, + dml_max( + UrgentLatency, + dml_max( + LineTime + - TimeForFetchingMetaPTE, + LineTime + / 4.0))); } else { if (NumberOfCursors > 0 || XFCEnabled) TimeForFetchingRowInVBlank = LineTime - TimeForFetchingMetaPTE; @@ -1105,36 +1263,39 @@ static bool CalculatePrefetchSchedule(struct display_mode_lib *mode_lib, TimeForFetchingRowInVBlank = 0.0; } - *DestinationLinesToRequestVMInVBlank = dml_floor(4.0 * (TimeForFetchingMetaPTE / LineTime + 0.125), - 1) / 4.0; + *DestinationLinesToRequestVMInVBlank = dml_floor( + 4.0 * (TimeForFetchingMetaPTE / LineTime + 0.125), + 1) / 4.0; - *DestinationLinesToRequestRowInVBlank = dml_floor(4.0 * (TimeForFetchingRowInVBlank / LineTime + 0.125), - 1) / 4.0; + *DestinationLinesToRequestRowInVBlank = dml_floor( + 4.0 * (TimeForFetchingRowInVBlank / LineTime + 0.125), + 1) / 4.0; LinesToRequestPrefetchPixelData = - *DestinationLinesForPrefetch - - ((NumberOfCursors > 0 || VirtualMemoryEnable - || DCCEnable) ? - (*DestinationLinesToRequestVMInVBlank - + *DestinationLinesToRequestRowInVBlank) : - 0.0); + *DestinationLinesForPrefetch + - ((NumberOfCursors > 0 || VirtualMemoryEnable + || DCCEnable) ? + (*DestinationLinesToRequestVMInVBlank + + *DestinationLinesToRequestRowInVBlank) : + 0.0); if (LinesToRequestPrefetchPixelData > 0) { - *VRatioPrefetchY = (double)PrefetchSourceLinesY - / LinesToRequestPrefetchPixelData; + *VRatioPrefetchY = (double) PrefetchSourceLinesY + / LinesToRequestPrefetchPixelData; *VRatioPrefetchY = dml_max(*VRatioPrefetchY, 1.0); if ((SwathHeightY > 4) && (VInitPreFillY > 3)) { if (LinesToRequestPrefetchPixelData > (VInitPreFillY - 3.0) / 2.0) { *VRatioPrefetchY = - dml_max((double)PrefetchSourceLinesY - / LinesToRequestPrefetchPixelData, - (double)MaxNumSwathY - * SwathHeightY - / (LinesToRequestPrefetchPixelData - - (VInitPreFillY - - 3.0) - / 2.0)); + dml_max( + (double) PrefetchSourceLinesY + / LinesToRequestPrefetchPixelData, + (double) MaxNumSwathY + * SwathHeightY + / (LinesToRequestPrefetchPixelData + - (VInitPreFillY + - 3.0) + / 2.0)); *VRatioPrefetchY = dml_max(*VRatioPrefetchY, 1.0); } else { MyError = true; @@ -1142,20 +1303,21 @@ static bool CalculatePrefetchSchedule(struct display_mode_lib *mode_lib, } } - *VRatioPrefetchC = (double)PrefetchSourceLinesC - / LinesToRequestPrefetchPixelData; + *VRatioPrefetchC = (double) PrefetchSourceLinesC + / LinesToRequestPrefetchPixelData; *VRatioPrefetchC = dml_max(*VRatioPrefetchC, 1.0); if ((SwathHeightC > 4)) { if (LinesToRequestPrefetchPixelData > (VInitPreFillC - 3.0) / 2.0) { *VRatioPrefetchC = - dml_max(*VRatioPrefetchC, - (double)MaxNumSwathC - * SwathHeightC - / (LinesToRequestPrefetchPixelData - - (VInitPreFillC - - 3.0) - / 2.0)); + dml_max( + *VRatioPrefetchC, + (double) MaxNumSwathC + * SwathHeightC + / (LinesToRequestPrefetchPixelData + - (VInitPreFillC + - 3.0) + / 2.0)); *VRatioPrefetchC = dml_max(*VRatioPrefetchC, 1.0); } else { MyError = true; @@ -1164,17 +1326,19 @@ static bool CalculatePrefetchSchedule(struct display_mode_lib *mode_lib, } *RequiredPrefetchPixDataBW = - DPPPerPlane - * ((double)PrefetchSourceLinesY - / LinesToRequestPrefetchPixelData - * dml_ceil(BytePerPixelDETY, - 1) - + (double)PrefetchSourceLinesC - / LinesToRequestPrefetchPixelData - * dml_ceil(BytePerPixelDETC, - 2) - / 2) - * SwathWidthY / LineTime; + DPPPerPlane + * ((double) PrefetchSourceLinesY + / LinesToRequestPrefetchPixelData + * dml_ceil( + BytePerPixelDETY, + 1) + + (double) PrefetchSourceLinesC + / LinesToRequestPrefetchPixelData + * dml_ceil( + BytePerPixelDETC, + 2) + / 2) + * SwathWidthY / LineTime; } else { MyError = true; *VRatioPrefetchY = 0; @@ -1202,25 +1366,26 @@ static bool CalculatePrefetchSchedule(struct display_mode_lib *mode_lib, return MyError; } -static double CeilToDFSGranularity(double Clock, double VCOSpeed) +static double RoundToDFSGranularityUp(double Clock, double VCOSpeed) { return VCOSpeed * 4 / dml_floor(VCOSpeed * 4 / Clock, 1); } -static double FloorToDFSGranularity(double Clock, double VCOSpeed) +static double RoundToDFSGranularityDown(double Clock, double VCOSpeed) { return VCOSpeed * 4 / dml_ceil(VCOSpeed * 4 / Clock, 1); } -static double CalculatePrefetchSourceLines(struct display_mode_lib *mode_lib, - double VRatio, - double vtaps, - bool Interlace, - bool ProgressiveToInterlaceUnitInOPP, - unsigned int SwathHeight, - unsigned int ViewportYStart, - double *VInitPreFill, - unsigned int *MaxNumSwath) +static double CalculatePrefetchSourceLines( + struct display_mode_lib *mode_lib, + double VRatio, + double vtaps, + bool Interlace, + bool ProgressiveToInterlaceUnitInOPP, + unsigned int SwathHeight, + unsigned int ViewportYStart, + double *VInitPreFill, + unsigned int *MaxNumSwath) { unsigned int MaxPartialSwath; @@ -1234,50 +1399,54 @@ static double CalculatePrefetchSourceLines(struct display_mode_lib *mode_lib, *MaxNumSwath = dml_ceil((*VInitPreFill - 1.0) / SwathHeight, 1) + 1.0; if (*VInitPreFill > 1.0) - MaxPartialSwath = (unsigned int)(*VInitPreFill - 2) % SwathHeight; + MaxPartialSwath = (unsigned int) (*VInitPreFill - 2) % SwathHeight; else - MaxPartialSwath = (unsigned int)(*VInitPreFill + SwathHeight - 2) % SwathHeight; + MaxPartialSwath = (unsigned int) (*VInitPreFill + SwathHeight - 2) + % SwathHeight; MaxPartialSwath = dml_max(1U, MaxPartialSwath); } else { if (ViewportYStart != 0) - dml_print("WARNING DML: using viewport y position of 0 even though actual viewport y position is non-zero in prefetch source lines calculation\n"); + dml_print( + "WARNING DML: using viewport y position of 0 even though actual viewport y position is non-zero in prefetch source lines calculation\n"); *MaxNumSwath = dml_ceil(*VInitPreFill / SwathHeight, 1); if (*VInitPreFill > 1.0) - MaxPartialSwath = (unsigned int)(*VInitPreFill - 1) % SwathHeight; + MaxPartialSwath = (unsigned int) (*VInitPreFill - 1) % SwathHeight; else - MaxPartialSwath = (unsigned int)(*VInitPreFill + SwathHeight - 1) % SwathHeight; + MaxPartialSwath = (unsigned int) (*VInitPreFill + SwathHeight - 1) + % SwathHeight; } return *MaxNumSwath * SwathHeight + MaxPartialSwath; } -static unsigned int CalculateVMAndRowBytes(struct display_mode_lib *mode_lib, - bool DCCEnable, - unsigned int BlockHeight256Bytes, - unsigned int BlockWidth256Bytes, - enum source_format_class SourcePixelFormat, - unsigned int SurfaceTiling, - unsigned int BytePerPixel, - enum scan_direction_class ScanDirection, - unsigned int ViewportWidth, - unsigned int ViewportHeight, - unsigned int SwathWidth, - bool VirtualMemoryEnable, - unsigned int VMMPageSize, - unsigned int PTEBufferSizeInRequests, - unsigned int PDEProcessingBufIn64KBReqs, - unsigned int Pitch, - unsigned int DCCMetaPitch, - unsigned int *MacroTileWidth, - unsigned int *MetaRowByte, - unsigned int *PixelPTEBytesPerRow, - bool *PTEBufferSizeNotExceeded, - unsigned int *dpte_row_height, - unsigned int *meta_row_height) +static unsigned int CalculateVMAndRowBytes( + struct display_mode_lib *mode_lib, + bool DCCEnable, + unsigned int BlockHeight256Bytes, + unsigned int BlockWidth256Bytes, + enum source_format_class SourcePixelFormat, + unsigned int SurfaceTiling, + unsigned int BytePerPixel, + enum scan_direction_class ScanDirection, + unsigned int ViewportWidth, + unsigned int ViewportHeight, + unsigned int SwathWidth, + bool VirtualMemoryEnable, + unsigned int VMMPageSize, + unsigned int PTEBufferSizeInRequests, + unsigned int PDEProcessingBufIn64KBReqs, + unsigned int Pitch, + unsigned int DCCMetaPitch, + unsigned int *MacroTileWidth, + unsigned int *MetaRowByte, + unsigned int *PixelPTEBytesPerRow, + bool *PTEBufferSizeNotExceeded, + unsigned int *dpte_row_height, + unsigned int *meta_row_height) { unsigned int MetaRequestHeight; unsigned int MetaRequestWidth; @@ -1298,31 +1467,33 @@ static unsigned int CalculateVMAndRowBytes(struct display_mode_lib *mode_lib, MetaRequestWidth = 8 * BlockWidth256Bytes; if (ScanDirection == dm_horz) { *meta_row_height = MetaRequestHeight; - MetaSurfWidth = dml_ceil((double)SwathWidth - 1, MetaRequestWidth) - + MetaRequestWidth; + MetaSurfWidth = dml_ceil((double) SwathWidth - 1, MetaRequestWidth) + + MetaRequestWidth; *MetaRowByte = MetaSurfWidth * MetaRequestHeight * BytePerPixel / 256.0; } else { *meta_row_height = MetaRequestWidth; - MetaSurfHeight = dml_ceil((double)SwathWidth - 1, MetaRequestHeight) - + MetaRequestHeight; + MetaSurfHeight = dml_ceil((double) SwathWidth - 1, MetaRequestHeight) + + MetaRequestHeight; *MetaRowByte = MetaSurfHeight * MetaRequestWidth * BytePerPixel / 256.0; } if (ScanDirection == dm_horz) { DCCMetaSurfaceBytes = DCCMetaPitch - * (dml_ceil(ViewportHeight - 1, 64 * BlockHeight256Bytes) - + 64 * BlockHeight256Bytes) * BytePerPixel - / 256; + * (dml_ceil(ViewportHeight - 1, 64 * BlockHeight256Bytes) + + 64 * BlockHeight256Bytes) * BytePerPixel + / 256; } else { DCCMetaSurfaceBytes = DCCMetaPitch - * (dml_ceil((double)ViewportHeight - 1, - 64 * BlockHeight256Bytes) - + 64 * BlockHeight256Bytes) * BytePerPixel - / 256; + * (dml_ceil( + (double) ViewportHeight - 1, + 64 * BlockHeight256Bytes) + + 64 * BlockHeight256Bytes) * BytePerPixel + / 256; } if (VirtualMemoryEnable == true) { - MetaPTEBytesFrame = (dml_ceil((double)(DCCMetaSurfaceBytes - VMMPageSize) - / (8 * VMMPageSize), - 1) + 1) * 64; + MetaPTEBytesFrame = (dml_ceil( + (double) (DCCMetaSurfaceBytes - VMMPageSize) + / (8 * VMMPageSize), + 1) + 1) * 64; MPDEBytesFrame = 128 * (mode_lib->vba.MaxPageTableLevels - 1); } else { MetaPTEBytesFrame = 0; @@ -1338,13 +1509,13 @@ static unsigned int CalculateVMAndRowBytes(struct display_mode_lib *mode_lib, MacroTileSizeBytes = 256; MacroTileHeight = 1; } else if (SurfaceTiling == dm_sw_4kb_s || SurfaceTiling == dm_sw_4kb_s_x - || SurfaceTiling == dm_sw_4kb_d || SurfaceTiling == dm_sw_4kb_d_x) { + || SurfaceTiling == dm_sw_4kb_d || SurfaceTiling == dm_sw_4kb_d_x) { MacroTileSizeBytes = 4096; MacroTileHeight = 4 * BlockHeight256Bytes; } else if (SurfaceTiling == dm_sw_64kb_s || SurfaceTiling == dm_sw_64kb_s_t - || SurfaceTiling == dm_sw_64kb_s_x || SurfaceTiling == dm_sw_64kb_d - || SurfaceTiling == dm_sw_64kb_d_t || SurfaceTiling == dm_sw_64kb_d_x - || SurfaceTiling == dm_sw_64kb_r_x) { + || SurfaceTiling == dm_sw_64kb_s_x || SurfaceTiling == dm_sw_64kb_d + || SurfaceTiling == dm_sw_64kb_d_t || SurfaceTiling == dm_sw_64kb_d_x + || SurfaceTiling == dm_sw_64kb_r_x) { MacroTileSizeBytes = 65536; MacroTileHeight = 16 * BlockHeight256Bytes; } else { @@ -1356,30 +1527,34 @@ static unsigned int CalculateVMAndRowBytes(struct display_mode_lib *mode_lib, if (VirtualMemoryEnable == true && mode_lib->vba.MaxPageTableLevels > 1) { if (ScanDirection == dm_horz) { DPDE0BytesFrame = - 64 - * (dml_ceil(((Pitch - * (dml_ceil(ViewportHeight - - 1, - MacroTileHeight) - + MacroTileHeight) - * BytePerPixel) - - MacroTileSizeBytes) - / (8 - * 2097152), - 1) + 1); + 64 + * (dml_ceil( + ((Pitch + * (dml_ceil( + ViewportHeight + - 1, + MacroTileHeight) + + MacroTileHeight) + * BytePerPixel) + - MacroTileSizeBytes) + / (8 + * 2097152), + 1) + 1); } else { DPDE0BytesFrame = - 64 - * (dml_ceil(((Pitch - * (dml_ceil((double)SwathWidth - - 1, - MacroTileHeight) - + MacroTileHeight) - * BytePerPixel) - - MacroTileSizeBytes) - / (8 - * 2097152), - 1) + 1); + 64 + * (dml_ceil( + ((Pitch + * (dml_ceil( + (double) SwathWidth + - 1, + MacroTileHeight) + + MacroTileHeight) + * BytePerPixel) + - MacroTileSizeBytes) + / (8 + * 2097152), + 1) + 1); } ExtraDPDEBytesFrame = 128 * (mode_lib->vba.MaxPageTableLevels - 2); } else { @@ -1388,7 +1563,7 @@ static unsigned int CalculateVMAndRowBytes(struct display_mode_lib *mode_lib, } PDEAndMetaPTEBytesFrame = MetaPTEBytesFrame + MPDEBytesFrame + DPDE0BytesFrame - + ExtraDPDEBytesFrame; + + ExtraDPDEBytesFrame; if (VirtualMemoryEnable == true) { unsigned int PTERequestSize; @@ -1429,33 +1604,39 @@ static unsigned int CalculateVMAndRowBytes(struct display_mode_lib *mode_lib, if (SurfaceTiling == dm_sw_linear) { *dpte_row_height = - dml_min(128, - 1 - << (unsigned int)dml_floor(dml_log2(dml_min((double)PTEBufferSizeInRequests - * PixelPTEReqWidth, - EffectivePDEProcessingBufIn64KBReqs - * 65536.0 - / BytePerPixel) - / Pitch), - 1)); + dml_min( + 128, + 1 + << (unsigned int) dml_floor( + dml_log2( + dml_min( + (double) PTEBufferSizeInRequests + * PixelPTEReqWidth, + EffectivePDEProcessingBufIn64KBReqs + * 65536.0 + / BytePerPixel) + / Pitch), + 1)); *PixelPTEBytesPerRow = PTERequestSize - * (dml_ceil((double)(Pitch * *dpte_row_height - 1) - / PixelPTEReqWidth, - 1) + 1); + * (dml_ceil( + (double) (Pitch * *dpte_row_height - 1) + / PixelPTEReqWidth, + 1) + 1); } else if (ScanDirection == dm_horz) { *dpte_row_height = PixelPTEReqHeight; *PixelPTEBytesPerRow = PTERequestSize - * (dml_ceil(((double)SwathWidth - 1) / PixelPTEReqWidth, 1) - + 1); + * (dml_ceil(((double) SwathWidth - 1) / PixelPTEReqWidth, 1) + + 1); } else { *dpte_row_height = dml_min(PixelPTEReqWidth, *MacroTileWidth); *PixelPTEBytesPerRow = PTERequestSize - * (dml_ceil(((double)SwathWidth - 1) - / PixelPTEReqHeight, - 1) + 1); + * (dml_ceil( + ((double) SwathWidth - 1) + / PixelPTEReqHeight, + 1) + 1); } if (*PixelPTEBytesPerRow * (1 - FractionOfPTEReturnDrop) - <= 64 * PTEBufferSizeInRequests) { + <= 64 * PTEBufferSizeInRequests) { *PTEBufferSizeNotExceeded = true; } else { *PTEBufferSizeNotExceeded = false; @@ -1468,7 +1649,8 @@ static unsigned int CalculateVMAndRowBytes(struct display_mode_lib *mode_lib, return PDEAndMetaPTEBytesFrame; } -static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation(struct display_mode_lib *mode_lib) +static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation( + struct display_mode_lib *mode_lib) { unsigned int j, k; @@ -1481,81 +1663,107 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman // for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { if (mode_lib->vba.WritebackEnable[k]) { - mode_lib->vba.WritebackDISPCLK = dml_max(mode_lib->vba.WritebackDISPCLK, - CalculateWriteBackDISPCLK(mode_lib->vba.WritebackPixelFormat[k], - mode_lib->vba.PixelClock[k], - mode_lib->vba.WritebackHRatio[k], - mode_lib->vba.WritebackVRatio[k], - mode_lib->vba.WritebackLumaHTaps[k], - mode_lib->vba.WritebackLumaVTaps[k], - mode_lib->vba.WritebackChromaHTaps[k], - mode_lib->vba.WritebackChromaVTaps[k], - mode_lib->vba.WritebackDestinationWidth[k], - mode_lib->vba.HTotal[k], - mode_lib->vba.WritebackChromaLineBufferWidth)); + mode_lib->vba.WritebackDISPCLK = + dml_max( + mode_lib->vba.WritebackDISPCLK, + CalculateWriteBackDISPCLK( + mode_lib->vba.WritebackPixelFormat[k], + mode_lib->vba.PixelClock[k], + mode_lib->vba.WritebackHRatio[k], + mode_lib->vba.WritebackVRatio[k], + mode_lib->vba.WritebackLumaHTaps[k], + mode_lib->vba.WritebackLumaVTaps[k], + mode_lib->vba.WritebackChromaHTaps[k], + mode_lib->vba.WritebackChromaVTaps[k], + mode_lib->vba.WritebackDestinationWidth[k], + mode_lib->vba.HTotal[k], + mode_lib->vba.WritebackChromaLineBufferWidth)); } } for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { if (mode_lib->vba.HRatio[k] > 1) { - mode_lib->vba.PSCL_THROUGHPUT_LUMA[k] = dml_min(mode_lib->vba.MaxDCHUBToPSCLThroughput, - mode_lib->vba.MaxPSCLToLBThroughput * mode_lib->vba.HRatio[k] - / dml_ceil(mode_lib->vba.htaps[k] / 6.0, 1)); + mode_lib->vba.PSCL_THROUGHPUT_LUMA[k] = dml_min( + mode_lib->vba.MaxDCHUBToPSCLThroughput, + mode_lib->vba.MaxPSCLToLBThroughput + * mode_lib->vba.HRatio[k] + / dml_ceil( + mode_lib->vba.htaps[k] + / 6.0, + 1)); } else { - mode_lib->vba.PSCL_THROUGHPUT_LUMA[k] = dml_min(mode_lib->vba.MaxDCHUBToPSCLThroughput, - mode_lib->vba.MaxPSCLToLBThroughput); + mode_lib->vba.PSCL_THROUGHPUT_LUMA[k] = dml_min( + mode_lib->vba.MaxDCHUBToPSCLThroughput, + mode_lib->vba.MaxPSCLToLBThroughput); } mode_lib->vba.DPPCLKUsingSingleDPPLuma = - mode_lib->vba.PixelClock[k] - * dml_max(mode_lib->vba.vtaps[k] / 6.0 - * dml_min(1.0, - mode_lib->vba.HRatio[k]), - dml_max(mode_lib->vba.HRatio[k] - * mode_lib->vba.VRatio[k] - / mode_lib->vba.PSCL_THROUGHPUT_LUMA[k], - 1.0)); + mode_lib->vba.PixelClock[k] + * dml_max( + mode_lib->vba.vtaps[k] / 6.0 + * dml_min( + 1.0, + mode_lib->vba.HRatio[k]), + dml_max( + mode_lib->vba.HRatio[k] + * mode_lib->vba.VRatio[k] + / mode_lib->vba.PSCL_THROUGHPUT_LUMA[k], + 1.0)); if ((mode_lib->vba.htaps[k] > 6 || mode_lib->vba.vtaps[k] > 6) - && mode_lib->vba.DPPCLKUsingSingleDPPLuma < 2 * mode_lib->vba.PixelClock[k]) { + && mode_lib->vba.DPPCLKUsingSingleDPPLuma + < 2 * mode_lib->vba.PixelClock[k]) { mode_lib->vba.DPPCLKUsingSingleDPPLuma = 2 * mode_lib->vba.PixelClock[k]; } - if ((mode_lib->vba.SourcePixelFormat[k] != dm_420_8 && mode_lib->vba.SourcePixelFormat[k] != dm_420_10)) { + if ((mode_lib->vba.SourcePixelFormat[k] != dm_420_8 + && mode_lib->vba.SourcePixelFormat[k] != dm_420_10)) { mode_lib->vba.PSCL_THROUGHPUT_CHROMA[k] = 0.0; - mode_lib->vba.DPPCLKUsingSingleDPP[k] = mode_lib->vba.DPPCLKUsingSingleDPPLuma; + mode_lib->vba.DPPCLKUsingSingleDPP[k] = + mode_lib->vba.DPPCLKUsingSingleDPPLuma; } else { if (mode_lib->vba.HRatio[k] > 1) { mode_lib->vba.PSCL_THROUGHPUT_CHROMA[k] = - dml_min(mode_lib->vba.MaxDCHUBToPSCLThroughput, - mode_lib->vba.MaxPSCLToLBThroughput * mode_lib->vba.HRatio[k] - / 2 - / dml_ceil(mode_lib->vba.HTAPsChroma[k] - / 6.0, - 1.0)); + dml_min( + mode_lib->vba.MaxDCHUBToPSCLThroughput, + mode_lib->vba.MaxPSCLToLBThroughput + * mode_lib->vba.HRatio[k] + / 2 + / dml_ceil( + mode_lib->vba.HTAPsChroma[k] + / 6.0, + 1.0)); } else { - mode_lib->vba.PSCL_THROUGHPUT_CHROMA[k] = dml_min(mode_lib->vba.MaxDCHUBToPSCLThroughput, - mode_lib->vba.MaxPSCLToLBThroughput); + mode_lib->vba.PSCL_THROUGHPUT_CHROMA[k] = dml_min( + mode_lib->vba.MaxDCHUBToPSCLThroughput, + mode_lib->vba.MaxPSCLToLBThroughput); } mode_lib->vba.DPPCLKUsingSingleDPPChroma = - mode_lib->vba.PixelClock[k] - * dml_max(mode_lib->vba.VTAPsChroma[k] / 6.0 - * dml_min(1.0, - mode_lib->vba.HRatio[k] - / 2), - dml_max(mode_lib->vba.HRatio[k] - * mode_lib->vba.VRatio[k] - / 4 - / mode_lib->vba.PSCL_THROUGHPUT_CHROMA[k], - 1.0)); + mode_lib->vba.PixelClock[k] + * dml_max( + mode_lib->vba.VTAPsChroma[k] + / 6.0 + * dml_min( + 1.0, + mode_lib->vba.HRatio[k] + / 2), + dml_max( + mode_lib->vba.HRatio[k] + * mode_lib->vba.VRatio[k] + / 4 + / mode_lib->vba.PSCL_THROUGHPUT_CHROMA[k], + 1.0)); if ((mode_lib->vba.HTAPsChroma[k] > 6 || mode_lib->vba.VTAPsChroma[k] > 6) - && mode_lib->vba.DPPCLKUsingSingleDPPChroma < 2 * mode_lib->vba.PixelClock[k]) { - mode_lib->vba.DPPCLKUsingSingleDPPChroma = 2 * mode_lib->vba.PixelClock[k]; + && mode_lib->vba.DPPCLKUsingSingleDPPChroma + < 2 * mode_lib->vba.PixelClock[k]) { + mode_lib->vba.DPPCLKUsingSingleDPPChroma = 2 + * mode_lib->vba.PixelClock[k]; } - mode_lib->vba.DPPCLKUsingSingleDPP[k] = dml_max(mode_lib->vba.DPPCLKUsingSingleDPPLuma, - mode_lib->vba.DPPCLKUsingSingleDPPChroma); + mode_lib->vba.DPPCLKUsingSingleDPP[k] = dml_max( + mode_lib->vba.DPPCLKUsingSingleDPPLuma, + mode_lib->vba.DPPCLKUsingSingleDPPChroma); } } @@ -1564,67 +1772,90 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman continue; if (mode_lib->vba.ODMCombineEnabled[k]) { mode_lib->vba.DISPCLKWithRamping = - dml_max(mode_lib->vba.DISPCLKWithRamping, - mode_lib->vba.PixelClock[k] / 2 - * (1 - + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading - / 100) - * (1 - + mode_lib->vba.DISPCLKRampingMargin - / 100)); + dml_max( + mode_lib->vba.DISPCLKWithRamping, + mode_lib->vba.PixelClock[k] / 2 + * (1 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100) + * (1 + + mode_lib->vba.DISPCLKRampingMargin + / 100)); mode_lib->vba.DISPCLKWithoutRamping = - dml_max(mode_lib->vba.DISPCLKWithoutRamping, - mode_lib->vba.PixelClock[k] / 2 - * (1 - + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading - / 100)); + dml_max( + mode_lib->vba.DISPCLKWithoutRamping, + mode_lib->vba.PixelClock[k] / 2 + * (1 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100)); } else if (!mode_lib->vba.ODMCombineEnabled[k]) { - mode_lib->vba.DISPCLKWithRamping = dml_max(mode_lib->vba.DISPCLKWithRamping, - mode_lib->vba.PixelClock[k] * (1 + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading / 100) - * (1 + mode_lib->vba.DISPCLKRampingMargin / 100)); + mode_lib->vba.DISPCLKWithRamping = + dml_max( + mode_lib->vba.DISPCLKWithRamping, + mode_lib->vba.PixelClock[k] + * (1 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100) + * (1 + + mode_lib->vba.DISPCLKRampingMargin + / 100)); mode_lib->vba.DISPCLKWithoutRamping = - dml_max(mode_lib->vba.DISPCLKWithoutRamping, - mode_lib->vba.PixelClock[k] - * (1 - + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading - / 100)); + dml_max( + mode_lib->vba.DISPCLKWithoutRamping, + mode_lib->vba.PixelClock[k] + * (1 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100)); } } - mode_lib->vba.DISPCLKWithRamping = dml_max(mode_lib->vba.DISPCLKWithRamping, mode_lib->vba.WritebackDISPCLK); - mode_lib->vba.DISPCLKWithoutRamping = dml_max(mode_lib->vba.DISPCLKWithoutRamping, mode_lib->vba.WritebackDISPCLK); + mode_lib->vba.DISPCLKWithRamping = dml_max( + mode_lib->vba.DISPCLKWithRamping, + mode_lib->vba.WritebackDISPCLK); + mode_lib->vba.DISPCLKWithoutRamping = dml_max( + mode_lib->vba.DISPCLKWithoutRamping, + mode_lib->vba.WritebackDISPCLK); - mode_lib->vba.MaxDispclk = mode_lib->vba.soc.clock_limits[NumberOfStates - 1].dispclk_mhz; ASSERT(mode_lib->vba.DISPCLKDPPCLKVCOSpeed != 0); - mode_lib->vba.DISPCLKWithRampingRoundedToDFSGranularity = CeilToDFSGranularity( + mode_lib->vba.DISPCLKWithRampingRoundedToDFSGranularity = RoundToDFSGranularityUp( mode_lib->vba.DISPCLKWithRamping, mode_lib->vba.DISPCLKDPPCLKVCOSpeed); - mode_lib->vba.DISPCLKWithoutRampingRoundedToDFSGranularity = CeilToDFSGranularity( + mode_lib->vba.DISPCLKWithoutRampingRoundedToDFSGranularity = RoundToDFSGranularityUp( mode_lib->vba.DISPCLKWithoutRamping, mode_lib->vba.DISPCLKDPPCLKVCOSpeed); - mode_lib->vba.MaxDispclkRoundedToDFSGranularity = FloorToDFSGranularity( - mode_lib->vba.MaxDispclk, + mode_lib->vba.MaxDispclkRoundedToDFSGranularity = RoundToDFSGranularityDown( + mode_lib->vba.soc.clock_limits[NumberOfStates - 1].dispclk_mhz, mode_lib->vba.DISPCLKDPPCLKVCOSpeed); if (mode_lib->vba.DISPCLKWithoutRampingRoundedToDFSGranularity - > mode_lib->vba.MaxDispclkRoundedToDFSGranularity) { - mode_lib->vba.DISPCLK_calculated = mode_lib->vba.DISPCLKWithoutRampingRoundedToDFSGranularity; + > mode_lib->vba.MaxDispclkRoundedToDFSGranularity) { + mode_lib->vba.DISPCLK_calculated = + mode_lib->vba.DISPCLKWithoutRampingRoundedToDFSGranularity; } else if (mode_lib->vba.DISPCLKWithRampingRoundedToDFSGranularity - > mode_lib->vba.MaxDispclkRoundedToDFSGranularity) { + > mode_lib->vba.MaxDispclkRoundedToDFSGranularity) { mode_lib->vba.DISPCLK_calculated = mode_lib->vba.MaxDispclkRoundedToDFSGranularity; } else { - mode_lib->vba.DISPCLK_calculated = mode_lib->vba.DISPCLKWithRampingRoundedToDFSGranularity; + mode_lib->vba.DISPCLK_calculated = + mode_lib->vba.DISPCLKWithRampingRoundedToDFSGranularity; } DTRACE(" dispclk_mhz (calculated) = %f", mode_lib->vba.DISPCLK_calculated); for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { - mode_lib->vba.DPPCLK_calculated[k] = mode_lib->vba.DPPCLKUsingSingleDPP[k] / mode_lib->vba.DPPPerPlane[k] - * (1 + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading / 100); - mode_lib->vba.GlobalDPPCLK = dml_max(mode_lib->vba.GlobalDPPCLK, mode_lib->vba.DPPCLK_calculated[k]); + mode_lib->vba.DPPCLK_calculated[k] = mode_lib->vba.DPPCLKUsingSingleDPP[k] + / mode_lib->vba.DPPPerPlane[k] + * (1 + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading / 100); + mode_lib->vba.GlobalDPPCLK = dml_max( + mode_lib->vba.GlobalDPPCLK, + mode_lib->vba.DPPCLK_calculated[k]); } - mode_lib->vba.GlobalDPPCLK = CeilToDFSGranularity(mode_lib->vba.GlobalDPPCLK, mode_lib->vba.DISPCLKDPPCLKVCOSpeed); + mode_lib->vba.GlobalDPPCLK = RoundToDFSGranularityUp( + mode_lib->vba.GlobalDPPCLK, + mode_lib->vba.DISPCLKDPPCLKVCOSpeed); for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { mode_lib->vba.DPPCLK_calculated[k] = mode_lib->vba.GlobalDPPCLK / 255 - * dml_ceil(mode_lib->vba.DPPCLK_calculated[k] * 255 / mode_lib->vba.GlobalDPPCLK, 1); + * dml_ceil( + mode_lib->vba.DPPCLK_calculated[k] * 255 + / mode_lib->vba.GlobalDPPCLK, + 1); DTRACE(" dppclk_mhz[%i] (calculated) = %f", k, mode_lib->vba.DPPCLK_calculated[k]); } @@ -1634,15 +1865,27 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman if (mode_lib->vba.DCCEnable[k]) mode_lib->vba.DCCEnabledAnyPlane = true; - mode_lib->vba.ReturnBandwidthToDCN = dml_min(mode_lib->vba.ReturnBusWidth * mode_lib->vba.DCFCLK, mode_lib->vba.FabricAndDRAMBandwidth * 1000) - * mode_lib->vba.PercentOfIdealDRAMAndFabricBWReceivedAfterUrgLatency / 100; + mode_lib->vba.ReturnBandwidthToDCN = dml_min( + mode_lib->vba.ReturnBusWidth * mode_lib->vba.DCFCLK, + mode_lib->vba.FabricAndDRAMBandwidth * 1000) + * mode_lib->vba.PercentOfIdealDRAMAndFabricBWReceivedAfterUrgLatency / 100; mode_lib->vba.ReturnBW = mode_lib->vba.ReturnBandwidthToDCN; - mode_lib->vba.ReturnBW = adjust_ReturnBW(mode_lib, mode_lib->vba.ReturnBW, mode_lib->vba.DCCEnabledAnyPlane, mode_lib->vba.ReturnBandwidthToDCN); + mode_lib->vba.ReturnBW = adjust_ReturnBW( + mode_lib, + mode_lib->vba.ReturnBW, + mode_lib->vba.DCCEnabledAnyPlane, + mode_lib->vba.ReturnBandwidthToDCN); // Let's do this calculation again?? - mode_lib->vba.ReturnBandwidthToDCN = dml_min(mode_lib->vba.ReturnBusWidth * mode_lib->vba.DCFCLK, mode_lib->vba.FabricAndDRAMBandwidth * 1000); - mode_lib->vba.ReturnBW = adjust_ReturnBW(mode_lib, mode_lib->vba.ReturnBW, mode_lib->vba.DCCEnabledAnyPlane, mode_lib->vba.ReturnBandwidthToDCN); + mode_lib->vba.ReturnBandwidthToDCN = dml_min( + mode_lib->vba.ReturnBusWidth * mode_lib->vba.DCFCLK, + mode_lib->vba.FabricAndDRAMBandwidth * 1000); + mode_lib->vba.ReturnBW = adjust_ReturnBW( + mode_lib, + mode_lib->vba.ReturnBW, + mode_lib->vba.DCCEnabledAnyPlane, + mode_lib->vba.ReturnBandwidthToDCN); DTRACE(" dcfclk_mhz = %f", mode_lib->vba.DCFCLK); DTRACE(" return_bw_to_dcn = %f", mode_lib->vba.ReturnBandwidthToDCN); @@ -1659,14 +1902,19 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman if (mode_lib->vba.ODMCombineEnabled[k] == true) MainPlaneDoesODMCombine = true; for (j = 0; j < mode_lib->vba.NumberOfActivePlanes; ++j) - if (mode_lib->vba.BlendingAndTiming[k] == j && mode_lib->vba.ODMCombineEnabled[j] == true) + if (mode_lib->vba.BlendingAndTiming[k] == j + && mode_lib->vba.ODMCombineEnabled[j] == true) MainPlaneDoesODMCombine = true; if (MainPlaneDoesODMCombine == true) - mode_lib->vba.SwathWidthY[k] = dml_min((double)mode_lib->vba.SwathWidthSingleDPPY[k], - dml_round(mode_lib->vba.HActive[k] / 2.0 * mode_lib->vba.HRatio[k])); + mode_lib->vba.SwathWidthY[k] = dml_min( + (double) mode_lib->vba.SwathWidthSingleDPPY[k], + dml_round( + mode_lib->vba.HActive[k] / 2.0 + * mode_lib->vba.HRatio[k])); else - mode_lib->vba.SwathWidthY[k] = mode_lib->vba.SwathWidthSingleDPPY[k] / mode_lib->vba.DPPPerPlane[k]; + mode_lib->vba.SwathWidthY[k] = mode_lib->vba.SwathWidthSingleDPPY[k] + / mode_lib->vba.DPPPerPlane[k]; } for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { @@ -1694,76 +1942,104 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman mode_lib->vba.TotalDataReadBandwidth = 0.0; for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { mode_lib->vba.ReadBandwidthPlaneLuma[k] = mode_lib->vba.SwathWidthSingleDPPY[k] - * dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1) / (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) - * mode_lib->vba.VRatio[k]; - mode_lib->vba.ReadBandwidthPlaneChroma[k] = mode_lib->vba.SwathWidthSingleDPPY[k] / 2 - * dml_ceil(mode_lib->vba.BytePerPixelDETC[k], 2) / (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) - * mode_lib->vba.VRatio[k] / 2; - DTRACE(" read_bw[%i] = %fBps", - k, - mode_lib->vba.ReadBandwidthPlaneLuma[k] + mode_lib->vba.ReadBandwidthPlaneChroma[k]); + * dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1) + / (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) + * mode_lib->vba.VRatio[k]; + mode_lib->vba.ReadBandwidthPlaneChroma[k] = mode_lib->vba.SwathWidthSingleDPPY[k] + / 2 * dml_ceil(mode_lib->vba.BytePerPixelDETC[k], 2) + / (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) + * mode_lib->vba.VRatio[k] / 2; + DTRACE( + " read_bw[%i] = %fBps", + k, + mode_lib->vba.ReadBandwidthPlaneLuma[k] + + mode_lib->vba.ReadBandwidthPlaneChroma[k]); mode_lib->vba.TotalDataReadBandwidth += mode_lib->vba.ReadBandwidthPlaneLuma[k] - + mode_lib->vba.ReadBandwidthPlaneChroma[k]; + + mode_lib->vba.ReadBandwidthPlaneChroma[k]; } mode_lib->vba.TotalDCCActiveDPP = 0; mode_lib->vba.TotalActiveDPP = 0; for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { - mode_lib->vba.TotalActiveDPP = mode_lib->vba.TotalActiveDPP + mode_lib->vba.DPPPerPlane[k]; + mode_lib->vba.TotalActiveDPP = mode_lib->vba.TotalActiveDPP + + mode_lib->vba.DPPPerPlane[k]; if (mode_lib->vba.DCCEnable[k]) - mode_lib->vba.TotalDCCActiveDPP = mode_lib->vba.TotalDCCActiveDPP + mode_lib->vba.DPPPerPlane[k]; + mode_lib->vba.TotalDCCActiveDPP = mode_lib->vba.TotalDCCActiveDPP + + mode_lib->vba.DPPPerPlane[k]; } - mode_lib->vba.UrgentRoundTripAndOutOfOrderLatency = (mode_lib->vba.RoundTripPingLatencyCycles + 32) / mode_lib->vba.DCFCLK - + mode_lib->vba.UrgentOutOfOrderReturnPerChannel * mode_lib->vba.NumberOfChannels / mode_lib->vba.ReturnBW; + mode_lib->vba.UrgentRoundTripAndOutOfOrderLatency = + (mode_lib->vba.RoundTripPingLatencyCycles + 32) / mode_lib->vba.DCFCLK + + mode_lib->vba.UrgentOutOfOrderReturnPerChannel + * mode_lib->vba.NumberOfChannels + / mode_lib->vba.ReturnBW; mode_lib->vba.LastPixelOfLineExtraWatermark = 0; for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { double DataFabricLineDeliveryTimeLuma, DataFabricLineDeliveryTimeChroma; if (mode_lib->vba.VRatio[k] <= 1.0) - mode_lib->vba.DisplayPipeLineDeliveryTimeLuma[k] = (double)mode_lib->vba.SwathWidthY[k] - * mode_lib->vba.DPPPerPlane[k] / mode_lib->vba.HRatio[k] / mode_lib->vba.PixelClock[k]; + mode_lib->vba.DisplayPipeLineDeliveryTimeLuma[k] = + (double) mode_lib->vba.SwathWidthY[k] + * mode_lib->vba.DPPPerPlane[k] + / mode_lib->vba.HRatio[k] + / mode_lib->vba.PixelClock[k]; else - mode_lib->vba.DisplayPipeLineDeliveryTimeLuma[k] = (double)mode_lib->vba.SwathWidthY[k] - / mode_lib->vba.PSCL_THROUGHPUT_LUMA[k] / mode_lib->vba.DPPCLK[k]; - - DataFabricLineDeliveryTimeLuma = - mode_lib->vba.SwathWidthSingleDPPY[k] * mode_lib->vba.SwathHeightY[k] - * dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1) - / (mode_lib->vba.ReturnBW * mode_lib->vba.ReadBandwidthPlaneLuma[k] - / mode_lib->vba.TotalDataReadBandwidth); - mode_lib->vba.LastPixelOfLineExtraWatermark = dml_max(mode_lib->vba.LastPixelOfLineExtraWatermark, - DataFabricLineDeliveryTimeLuma - - mode_lib->vba.DisplayPipeLineDeliveryTimeLuma[k]); + mode_lib->vba.DisplayPipeLineDeliveryTimeLuma[k] = + (double) mode_lib->vba.SwathWidthY[k] + / mode_lib->vba.PSCL_THROUGHPUT_LUMA[k] + / mode_lib->vba.DPPCLK[k]; + + DataFabricLineDeliveryTimeLuma = mode_lib->vba.SwathWidthSingleDPPY[k] + * mode_lib->vba.SwathHeightY[k] + * dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1) + / (mode_lib->vba.ReturnBW * mode_lib->vba.ReadBandwidthPlaneLuma[k] + / mode_lib->vba.TotalDataReadBandwidth); + mode_lib->vba.LastPixelOfLineExtraWatermark = dml_max( + mode_lib->vba.LastPixelOfLineExtraWatermark, + DataFabricLineDeliveryTimeLuma + - mode_lib->vba.DisplayPipeLineDeliveryTimeLuma[k]); if (mode_lib->vba.BytePerPixelDETC[k] == 0) mode_lib->vba.DisplayPipeLineDeliveryTimeChroma[k] = 0.0; else if (mode_lib->vba.VRatio[k] / 2.0 <= 1.0) - mode_lib->vba.DisplayPipeLineDeliveryTimeChroma[k] = mode_lib->vba.SwathWidthY[k] / 2.0 - * mode_lib->vba.DPPPerPlane[k] / (mode_lib->vba.HRatio[k] / 2.0) / mode_lib->vba.PixelClock[k]; + mode_lib->vba.DisplayPipeLineDeliveryTimeChroma[k] = + mode_lib->vba.SwathWidthY[k] / 2.0 + * mode_lib->vba.DPPPerPlane[k] + / (mode_lib->vba.HRatio[k] / 2.0) + / mode_lib->vba.PixelClock[k]; else - mode_lib->vba.DisplayPipeLineDeliveryTimeChroma[k] = mode_lib->vba.SwathWidthY[k] / 2.0 - / mode_lib->vba.PSCL_THROUGHPUT_CHROMA[k] / mode_lib->vba.DPPCLK[k]; + mode_lib->vba.DisplayPipeLineDeliveryTimeChroma[k] = + mode_lib->vba.SwathWidthY[k] / 2.0 + / mode_lib->vba.PSCL_THROUGHPUT_CHROMA[k] + / mode_lib->vba.DPPCLK[k]; DataFabricLineDeliveryTimeChroma = mode_lib->vba.SwathWidthSingleDPPY[k] / 2.0 - * mode_lib->vba.SwathHeightC[k] * dml_ceil(mode_lib->vba.BytePerPixelDETC[k], 2) - / (mode_lib->vba.ReturnBW * mode_lib->vba.ReadBandwidthPlaneChroma[k] - / mode_lib->vba.TotalDataReadBandwidth); - mode_lib->vba.LastPixelOfLineExtraWatermark = dml_max(mode_lib->vba.LastPixelOfLineExtraWatermark, - DataFabricLineDeliveryTimeChroma - - mode_lib->vba.DisplayPipeLineDeliveryTimeChroma[k]); + * mode_lib->vba.SwathHeightC[k] + * dml_ceil(mode_lib->vba.BytePerPixelDETC[k], 2) + / (mode_lib->vba.ReturnBW + * mode_lib->vba.ReadBandwidthPlaneChroma[k] + / mode_lib->vba.TotalDataReadBandwidth); + mode_lib->vba.LastPixelOfLineExtraWatermark = + dml_max( + mode_lib->vba.LastPixelOfLineExtraWatermark, + DataFabricLineDeliveryTimeChroma + - mode_lib->vba.DisplayPipeLineDeliveryTimeChroma[k]); } mode_lib->vba.UrgentExtraLatency = mode_lib->vba.UrgentRoundTripAndOutOfOrderLatency - + (mode_lib->vba.TotalActiveDPP * mode_lib->vba.PixelChunkSizeInKByte - + mode_lib->vba.TotalDCCActiveDPP * mode_lib->vba.MetaChunkSize) * 1024.0 - / mode_lib->vba.ReturnBW; + + (mode_lib->vba.TotalActiveDPP * mode_lib->vba.PixelChunkSizeInKByte + + mode_lib->vba.TotalDCCActiveDPP + * mode_lib->vba.MetaChunkSize) * 1024.0 + / mode_lib->vba.ReturnBW; if (mode_lib->vba.VirtualMemoryEnable) - mode_lib->vba.UrgentExtraLatency += mode_lib->vba.TotalActiveDPP * mode_lib->vba.PTEChunkSize * 1024.0 / mode_lib->vba.ReturnBW; + mode_lib->vba.UrgentExtraLatency += mode_lib->vba.TotalActiveDPP + * mode_lib->vba.PTEChunkSize * 1024.0 / mode_lib->vba.ReturnBW; - mode_lib->vba.UrgentWatermark = mode_lib->vba.UrgentLatency + mode_lib->vba.LastPixelOfLineExtraWatermark + mode_lib->vba.UrgentExtraLatency; + mode_lib->vba.UrgentWatermark = mode_lib->vba.UrgentLatency + + mode_lib->vba.LastPixelOfLineExtraWatermark + + mode_lib->vba.UrgentExtraLatency; DTRACE(" urgent_extra_latency = %fus", mode_lib->vba.UrgentExtraLatency); DTRACE(" wm_urgent = %fus", mode_lib->vba.UrgentWatermark); @@ -1780,12 +2056,14 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman mode_lib->vba.WritebackUrgentWatermark = mode_lib->vba.WritebackLatency; else mode_lib->vba.WritebackUrgentWatermark = mode_lib->vba.WritebackLatency - + mode_lib->vba.WritebackChunkSize * 1024.0 / 32 / mode_lib->vba.SOCCLK; + + mode_lib->vba.WritebackChunkSize * 1024.0 / 32 + / mode_lib->vba.SOCCLK; DTRACE(" wm_wb_urgent = %fus", mode_lib->vba.WritebackUrgentWatermark); // NB P-State/DRAM Clock Change Watermark - mode_lib->vba.DRAMClockChangeWatermark = mode_lib->vba.DRAMClockChangeLatency + mode_lib->vba.UrgentWatermark; + mode_lib->vba.DRAMClockChangeWatermark = mode_lib->vba.DRAMClockChangeLatency + + mode_lib->vba.UrgentWatermark; DTRACE(" wm_pstate_change = %fus", mode_lib->vba.DRAMClockChangeWatermark); @@ -1794,28 +2072,42 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman DTRACE(" socclk frequency %f Mhz", mode_lib->vba.SOCCLK); if (mode_lib->vba.TotalActiveWriteback <= 1) - mode_lib->vba.WritebackDRAMClockChangeWatermark = mode_lib->vba.DRAMClockChangeLatency + mode_lib->vba.WritebackLatency; + mode_lib->vba.WritebackDRAMClockChangeWatermark = + mode_lib->vba.DRAMClockChangeLatency + + mode_lib->vba.WritebackLatency; else - mode_lib->vba.WritebackDRAMClockChangeWatermark = mode_lib->vba.DRAMClockChangeLatency + mode_lib->vba.WritebackLatency - + mode_lib->vba.WritebackChunkSize * 1024.0 / 32 / mode_lib->vba.SOCCLK; + mode_lib->vba.WritebackDRAMClockChangeWatermark = + mode_lib->vba.DRAMClockChangeLatency + + mode_lib->vba.WritebackLatency + + mode_lib->vba.WritebackChunkSize * 1024.0 / 32 + / mode_lib->vba.SOCCLK; DTRACE(" wm_wb_pstate %fus", mode_lib->vba.WritebackDRAMClockChangeWatermark); // Stutter Efficiency for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { - mode_lib->vba.LinesInDETY[k] = mode_lib->vba.DETBufferSizeY[k] / mode_lib->vba.BytePerPixelDETY[k] - / mode_lib->vba.SwathWidthY[k]; - mode_lib->vba.LinesInDETYRoundedDownToSwath[k] = dml_floor(mode_lib->vba.LinesInDETY[k], - mode_lib->vba.SwathHeightY[k]); - mode_lib->vba.FullDETBufferingTimeY[k] = mode_lib->vba.LinesInDETYRoundedDownToSwath[k] - * (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) / mode_lib->vba.VRatio[k]; + mode_lib->vba.LinesInDETY[k] = mode_lib->vba.DETBufferSizeY[k] + / mode_lib->vba.BytePerPixelDETY[k] / mode_lib->vba.SwathWidthY[k]; + mode_lib->vba.LinesInDETYRoundedDownToSwath[k] = dml_floor( + mode_lib->vba.LinesInDETY[k], + mode_lib->vba.SwathHeightY[k]); + mode_lib->vba.FullDETBufferingTimeY[k] = + mode_lib->vba.LinesInDETYRoundedDownToSwath[k] + * (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]) + / mode_lib->vba.VRatio[k]; if (mode_lib->vba.BytePerPixelDETC[k] > 0) { - mode_lib->vba.LinesInDETC[k] = mode_lib->vba.DETBufferSizeC[k] / mode_lib->vba.BytePerPixelDETC[k] - / (mode_lib->vba.SwathWidthY[k] / 2); - mode_lib->vba.LinesInDETCRoundedDownToSwath[k] = dml_floor(mode_lib->vba.LinesInDETC[k], - mode_lib->vba.SwathHeightC[k]); - mode_lib->vba.FullDETBufferingTimeC[k] = mode_lib->vba.LinesInDETCRoundedDownToSwath[k] - * (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) / (mode_lib->vba.VRatio[k] / 2); + mode_lib->vba.LinesInDETC[k] = mode_lib->vba.DETBufferSizeC[k] + / mode_lib->vba.BytePerPixelDETC[k] + / (mode_lib->vba.SwathWidthY[k] / 2); + mode_lib->vba.LinesInDETCRoundedDownToSwath[k] = dml_floor( + mode_lib->vba.LinesInDETC[k], + mode_lib->vba.SwathHeightC[k]); + mode_lib->vba.FullDETBufferingTimeC[k] = + mode_lib->vba.LinesInDETCRoundedDownToSwath[k] + * (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]) + / (mode_lib->vba.VRatio[k] / 2); } else { mode_lib->vba.LinesInDETC[k] = 0; mode_lib->vba.LinesInDETCRoundedDownToSwath[k] = 0; @@ -1825,15 +2117,21 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman mode_lib->vba.MinFullDETBufferingTime = 999999.0; for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { - if (mode_lib->vba.FullDETBufferingTimeY[k] < mode_lib->vba.MinFullDETBufferingTime) { - mode_lib->vba.MinFullDETBufferingTime = mode_lib->vba.FullDETBufferingTimeY[k]; - mode_lib->vba.FrameTimeForMinFullDETBufferingTime = (double)mode_lib->vba.VTotal[k] * mode_lib->vba.HTotal[k] - / mode_lib->vba.PixelClock[k]; + if (mode_lib->vba.FullDETBufferingTimeY[k] + < mode_lib->vba.MinFullDETBufferingTime) { + mode_lib->vba.MinFullDETBufferingTime = + mode_lib->vba.FullDETBufferingTimeY[k]; + mode_lib->vba.FrameTimeForMinFullDETBufferingTime = + (double) mode_lib->vba.VTotal[k] * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]; } - if (mode_lib->vba.FullDETBufferingTimeC[k] < mode_lib->vba.MinFullDETBufferingTime) { - mode_lib->vba.MinFullDETBufferingTime = mode_lib->vba.FullDETBufferingTimeC[k]; - mode_lib->vba.FrameTimeForMinFullDETBufferingTime = (double)mode_lib->vba.VTotal[k] * mode_lib->vba.HTotal[k] - / mode_lib->vba.PixelClock[k]; + if (mode_lib->vba.FullDETBufferingTimeC[k] + < mode_lib->vba.MinFullDETBufferingTime) { + mode_lib->vba.MinFullDETBufferingTime = + mode_lib->vba.FullDETBufferingTimeC[k]; + mode_lib->vba.FrameTimeForMinFullDETBufferingTime = + (double) mode_lib->vba.VTotal[k] * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]; } } @@ -1841,45 +2139,58 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { if (mode_lib->vba.DCCEnable[k]) { mode_lib->vba.AverageReadBandwidthGBytePerSecond = - mode_lib->vba.AverageReadBandwidthGBytePerSecond - + mode_lib->vba.ReadBandwidthPlaneLuma[k] / mode_lib->vba.DCCRate[k] - / 1000 - + mode_lib->vba.ReadBandwidthPlaneChroma[k] - / mode_lib->vba.DCCRate[k] / 1000; + mode_lib->vba.AverageReadBandwidthGBytePerSecond + + mode_lib->vba.ReadBandwidthPlaneLuma[k] + / mode_lib->vba.DCCRate[k] + / 1000 + + mode_lib->vba.ReadBandwidthPlaneChroma[k] + / mode_lib->vba.DCCRate[k] + / 1000; } else { mode_lib->vba.AverageReadBandwidthGBytePerSecond = - mode_lib->vba.AverageReadBandwidthGBytePerSecond - + mode_lib->vba.ReadBandwidthPlaneLuma[k] / 1000 - + mode_lib->vba.ReadBandwidthPlaneChroma[k] / 1000; + mode_lib->vba.AverageReadBandwidthGBytePerSecond + + mode_lib->vba.ReadBandwidthPlaneLuma[k] + / 1000 + + mode_lib->vba.ReadBandwidthPlaneChroma[k] + / 1000; } if (mode_lib->vba.DCCEnable[k]) { mode_lib->vba.AverageReadBandwidthGBytePerSecond = - mode_lib->vba.AverageReadBandwidthGBytePerSecond - + mode_lib->vba.ReadBandwidthPlaneLuma[k] / 1000 / 256 - + mode_lib->vba.ReadBandwidthPlaneChroma[k] / 1000 - / 256; + mode_lib->vba.AverageReadBandwidthGBytePerSecond + + mode_lib->vba.ReadBandwidthPlaneLuma[k] + / 1000 / 256 + + mode_lib->vba.ReadBandwidthPlaneChroma[k] + / 1000 / 256; } if (mode_lib->vba.VirtualMemoryEnable) { mode_lib->vba.AverageReadBandwidthGBytePerSecond = - mode_lib->vba.AverageReadBandwidthGBytePerSecond - + mode_lib->vba.ReadBandwidthPlaneLuma[k] / 1000 / 512 - + mode_lib->vba.ReadBandwidthPlaneChroma[k] / 1000 - / 512; + mode_lib->vba.AverageReadBandwidthGBytePerSecond + + mode_lib->vba.ReadBandwidthPlaneLuma[k] + / 1000 / 512 + + mode_lib->vba.ReadBandwidthPlaneChroma[k] + / 1000 / 512; } } - mode_lib->vba.PartOfBurstThatFitsInROB = dml_min(mode_lib->vba.MinFullDETBufferingTime * mode_lib->vba.TotalDataReadBandwidth, - mode_lib->vba.ROBBufferSizeInKByte * 1024 * mode_lib->vba.TotalDataReadBandwidth - / (mode_lib->vba.AverageReadBandwidthGBytePerSecond * 1000)); + mode_lib->vba.PartOfBurstThatFitsInROB = + dml_min( + mode_lib->vba.MinFullDETBufferingTime + * mode_lib->vba.TotalDataReadBandwidth, + mode_lib->vba.ROBBufferSizeInKByte * 1024 + * mode_lib->vba.TotalDataReadBandwidth + / (mode_lib->vba.AverageReadBandwidthGBytePerSecond + * 1000)); mode_lib->vba.StutterBurstTime = mode_lib->vba.PartOfBurstThatFitsInROB - * (mode_lib->vba.AverageReadBandwidthGBytePerSecond * 1000) / mode_lib->vba.TotalDataReadBandwidth - / mode_lib->vba.ReturnBW - + (mode_lib->vba.MinFullDETBufferingTime * mode_lib->vba.TotalDataReadBandwidth - - mode_lib->vba.PartOfBurstThatFitsInROB) / (mode_lib->vba.DCFCLK * 64); + * (mode_lib->vba.AverageReadBandwidthGBytePerSecond * 1000) + / mode_lib->vba.TotalDataReadBandwidth / mode_lib->vba.ReturnBW + + (mode_lib->vba.MinFullDETBufferingTime + * mode_lib->vba.TotalDataReadBandwidth + - mode_lib->vba.PartOfBurstThatFitsInROB) + / (mode_lib->vba.DCFCLK * 64); if (mode_lib->vba.TotalActiveWriteback == 0) { mode_lib->vba.StutterEfficiencyNotIncludingVBlank = (1 - - (mode_lib->vba.SRExitTime + mode_lib->vba.StutterBurstTime) / mode_lib->vba.MinFullDETBufferingTime) - * 100; + - (mode_lib->vba.SRExitTime + mode_lib->vba.StutterBurstTime) + / mode_lib->vba.MinFullDETBufferingTime) * 100; } else { mode_lib->vba.StutterEfficiencyNotIncludingVBlank = 0; } @@ -1887,47 +2198,66 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman mode_lib->vba.SmallestVBlank = 999999; for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { if (mode_lib->vba.SynchronizedVBlank || mode_lib->vba.NumberOfActivePlanes == 1) { - mode_lib->vba.VBlankTime = (double)(mode_lib->vba.VTotal[k] - mode_lib->vba.VActive[k]) * mode_lib->vba.HTotal[k] - / mode_lib->vba.PixelClock[k]; + mode_lib->vba.VBlankTime = (double) (mode_lib->vba.VTotal[k] + - mode_lib->vba.VActive[k]) * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]; } else { mode_lib->vba.VBlankTime = 0; } - mode_lib->vba.SmallestVBlank = dml_min(mode_lib->vba.SmallestVBlank, mode_lib->vba.VBlankTime); + mode_lib->vba.SmallestVBlank = dml_min( + mode_lib->vba.SmallestVBlank, + mode_lib->vba.VBlankTime); } mode_lib->vba.StutterEfficiency = (mode_lib->vba.StutterEfficiencyNotIncludingVBlank / 100 - * (mode_lib->vba.FrameTimeForMinFullDETBufferingTime - mode_lib->vba.SmallestVBlank) - + mode_lib->vba.SmallestVBlank) / mode_lib->vba.FrameTimeForMinFullDETBufferingTime * 100; + * (mode_lib->vba.FrameTimeForMinFullDETBufferingTime + - mode_lib->vba.SmallestVBlank) + + mode_lib->vba.SmallestVBlank) + / mode_lib->vba.FrameTimeForMinFullDETBufferingTime * 100; // dml_ml->vba.DCFCLK Deep Sleep mode_lib->vba.DCFClkDeepSleep = 8.0; for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; k++) { if (mode_lib->vba.BytePerPixelDETC[k] > 0) { - mode_lib->vba.DCFCLKDeepSleepPerPlane = dml_max(1.1 * mode_lib->vba.SwathWidthY[k] - * dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1) / 32 - / mode_lib->vba.DisplayPipeLineDeliveryTimeLuma[k], - 1.1 * mode_lib->vba.SwathWidthY[k] / 2.0 - * dml_ceil(mode_lib->vba.BytePerPixelDETC[k], 2) / 32 - / mode_lib->vba.DisplayPipeLineDeliveryTimeChroma[k]); + mode_lib->vba.DCFCLKDeepSleepPerPlane = + dml_max( + 1.1 * mode_lib->vba.SwathWidthY[k] + * dml_ceil( + mode_lib->vba.BytePerPixelDETY[k], + 1) / 32 + / mode_lib->vba.DisplayPipeLineDeliveryTimeLuma[k], + 1.1 * mode_lib->vba.SwathWidthY[k] / 2.0 + * dml_ceil( + mode_lib->vba.BytePerPixelDETC[k], + 2) / 32 + / mode_lib->vba.DisplayPipeLineDeliveryTimeChroma[k]); } else mode_lib->vba.DCFCLKDeepSleepPerPlane = 1.1 * mode_lib->vba.SwathWidthY[k] - * dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1) / 64.0 - / mode_lib->vba.DisplayPipeLineDeliveryTimeLuma[k]; - mode_lib->vba.DCFCLKDeepSleepPerPlane = dml_max(mode_lib->vba.DCFCLKDeepSleepPerPlane, - mode_lib->vba.PixelClock[k] / 16.0); - mode_lib->vba.DCFClkDeepSleep = dml_max(mode_lib->vba.DCFClkDeepSleep, mode_lib->vba.DCFCLKDeepSleepPerPlane); + * dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1) / 64.0 + / mode_lib->vba.DisplayPipeLineDeliveryTimeLuma[k]; + mode_lib->vba.DCFCLKDeepSleepPerPlane = dml_max( + mode_lib->vba.DCFCLKDeepSleepPerPlane, + mode_lib->vba.PixelClock[k] / 16.0); + mode_lib->vba.DCFClkDeepSleep = dml_max( + mode_lib->vba.DCFClkDeepSleep, + mode_lib->vba.DCFCLKDeepSleepPerPlane); - DTRACE(" dcfclk_deepsleep_per_plane[%i] = %fMHz", k, mode_lib->vba.DCFCLKDeepSleepPerPlane); + DTRACE( + " dcfclk_deepsleep_per_plane[%i] = %fMHz", + k, + mode_lib->vba.DCFCLKDeepSleepPerPlane); } DTRACE(" dcfclk_deepsleep_mhz = %fMHz", mode_lib->vba.DCFClkDeepSleep); // Stutter Watermark - mode_lib->vba.StutterExitWatermark = mode_lib->vba.SRExitTime + mode_lib->vba.LastPixelOfLineExtraWatermark + mode_lib->vba.UrgentExtraLatency - + 10 / mode_lib->vba.DCFClkDeepSleep; - mode_lib->vba.StutterEnterPlusExitWatermark = mode_lib->vba.SREnterPlusExitTime + mode_lib->vba.LastPixelOfLineExtraWatermark - + mode_lib->vba.UrgentExtraLatency; + mode_lib->vba.StutterExitWatermark = mode_lib->vba.SRExitTime + + mode_lib->vba.LastPixelOfLineExtraWatermark + + mode_lib->vba.UrgentExtraLatency + 10 / mode_lib->vba.DCFClkDeepSleep; + mode_lib->vba.StutterEnterPlusExitWatermark = mode_lib->vba.SREnterPlusExitTime + + mode_lib->vba.LastPixelOfLineExtraWatermark + + mode_lib->vba.UrgentExtraLatency; DTRACE(" wm_cstate_exit = %fus", mode_lib->vba.StutterExitWatermark); DTRACE(" wm_cstate_enter_exit = %fus", mode_lib->vba.StutterEnterPlusExitWatermark); @@ -1935,72 +2265,95 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman // Urgent Latency Supported for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { mode_lib->vba.EffectiveDETPlusLBLinesLuma = - dml_floor(mode_lib->vba.LinesInDETY[k] - + dml_min(mode_lib->vba.LinesInDETY[k] - * mode_lib->vba.DPPCLK[k] - * mode_lib->vba.BytePerPixelDETY[k] - * mode_lib->vba.PSCL_THROUGHPUT_LUMA[k] - / (mode_lib->vba.ReturnBW - / mode_lib->vba.DPPPerPlane[k]), - (double)mode_lib->vba.EffectiveLBLatencyHidingSourceLinesLuma), - mode_lib->vba.SwathHeightY[k]); + dml_floor( + mode_lib->vba.LinesInDETY[k] + + dml_min( + mode_lib->vba.LinesInDETY[k] + * mode_lib->vba.DPPCLK[k] + * mode_lib->vba.BytePerPixelDETY[k] + * mode_lib->vba.PSCL_THROUGHPUT_LUMA[k] + / (mode_lib->vba.ReturnBW + / mode_lib->vba.DPPPerPlane[k]), + (double) mode_lib->vba.EffectiveLBLatencyHidingSourceLinesLuma), + mode_lib->vba.SwathHeightY[k]); mode_lib->vba.UrgentLatencySupportUsLuma = mode_lib->vba.EffectiveDETPlusLBLinesLuma - * (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) / mode_lib->vba.VRatio[k] - - mode_lib->vba.EffectiveDETPlusLBLinesLuma * mode_lib->vba.SwathWidthY[k] - * mode_lib->vba.BytePerPixelDETY[k] - / (mode_lib->vba.ReturnBW / mode_lib->vba.DPPPerPlane[k]); + * (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) + / mode_lib->vba.VRatio[k] + - mode_lib->vba.EffectiveDETPlusLBLinesLuma + * mode_lib->vba.SwathWidthY[k] + * mode_lib->vba.BytePerPixelDETY[k] + / (mode_lib->vba.ReturnBW + / mode_lib->vba.DPPPerPlane[k]); if (mode_lib->vba.BytePerPixelDETC[k] > 0) { mode_lib->vba.EffectiveDETPlusLBLinesChroma = - dml_floor(mode_lib->vba.LinesInDETC[k] - + dml_min(mode_lib->vba.LinesInDETC[k] - * mode_lib->vba.DPPCLK[k] - * mode_lib->vba.BytePerPixelDETC[k] - * mode_lib->vba.PSCL_THROUGHPUT_CHROMA[k] - / (mode_lib->vba.ReturnBW - / mode_lib->vba.DPPPerPlane[k]), - (double)mode_lib->vba.EffectiveLBLatencyHidingSourceLinesChroma), - mode_lib->vba.SwathHeightC[k]); - mode_lib->vba.UrgentLatencySupportUsChroma = mode_lib->vba.EffectiveDETPlusLBLinesChroma - * (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) / (mode_lib->vba.VRatio[k] / 2) - - mode_lib->vba.EffectiveDETPlusLBLinesChroma - * (mode_lib->vba.SwathWidthY[k] / 2) - * mode_lib->vba.BytePerPixelDETC[k] - / (mode_lib->vba.ReturnBW / mode_lib->vba.DPPPerPlane[k]); - mode_lib->vba.UrgentLatencySupportUs[k] = dml_min(mode_lib->vba.UrgentLatencySupportUsLuma, - mode_lib->vba.UrgentLatencySupportUsChroma); + dml_floor( + mode_lib->vba.LinesInDETC[k] + + dml_min( + mode_lib->vba.LinesInDETC[k] + * mode_lib->vba.DPPCLK[k] + * mode_lib->vba.BytePerPixelDETC[k] + * mode_lib->vba.PSCL_THROUGHPUT_CHROMA[k] + / (mode_lib->vba.ReturnBW + / mode_lib->vba.DPPPerPlane[k]), + (double) mode_lib->vba.EffectiveLBLatencyHidingSourceLinesChroma), + mode_lib->vba.SwathHeightC[k]); + mode_lib->vba.UrgentLatencySupportUsChroma = + mode_lib->vba.EffectiveDETPlusLBLinesChroma + * (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]) + / (mode_lib->vba.VRatio[k] / 2) + - mode_lib->vba.EffectiveDETPlusLBLinesChroma + * (mode_lib->vba.SwathWidthY[k] + / 2) + * mode_lib->vba.BytePerPixelDETC[k] + / (mode_lib->vba.ReturnBW + / mode_lib->vba.DPPPerPlane[k]); + mode_lib->vba.UrgentLatencySupportUs[k] = dml_min( + mode_lib->vba.UrgentLatencySupportUsLuma, + mode_lib->vba.UrgentLatencySupportUsChroma); } else { - mode_lib->vba.UrgentLatencySupportUs[k] = mode_lib->vba.UrgentLatencySupportUsLuma; + mode_lib->vba.UrgentLatencySupportUs[k] = + mode_lib->vba.UrgentLatencySupportUsLuma; } } mode_lib->vba.MinUrgentLatencySupportUs = 999999; for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { - mode_lib->vba.MinUrgentLatencySupportUs = dml_min(mode_lib->vba.MinUrgentLatencySupportUs, - mode_lib->vba.UrgentLatencySupportUs[k]); + mode_lib->vba.MinUrgentLatencySupportUs = dml_min( + mode_lib->vba.MinUrgentLatencySupportUs, + mode_lib->vba.UrgentLatencySupportUs[k]); } // Non-Urgent Latency Tolerance - mode_lib->vba.NonUrgentLatencyTolerance = mode_lib->vba.MinUrgentLatencySupportUs - mode_lib->vba.UrgentWatermark; + mode_lib->vba.NonUrgentLatencyTolerance = mode_lib->vba.MinUrgentLatencySupportUs + - mode_lib->vba.UrgentWatermark; // DSCCLK for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { if ((mode_lib->vba.BlendingAndTiming[k] != k) || !mode_lib->vba.DSCEnabled[k]) { mode_lib->vba.DSCCLK_calculated[k] = 0.0; } else { - if (mode_lib->vba.OutputFormat[k] == dm_420 || mode_lib->vba.OutputFormat[k] == dm_n422) + if (mode_lib->vba.OutputFormat[k] == dm_420 + || mode_lib->vba.OutputFormat[k] == dm_n422) mode_lib->vba.DSCFormatFactor = 2; else mode_lib->vba.DSCFormatFactor = 1; if (mode_lib->vba.ODMCombineEnabled[k]) - mode_lib->vba.DSCCLK_calculated[k] = mode_lib->vba.PixelClockBackEnd[k] / 6 - / mode_lib->vba.DSCFormatFactor - / (1 - mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading / 100); + mode_lib->vba.DSCCLK_calculated[k] = + mode_lib->vba.PixelClockBackEnd[k] / 6 + / mode_lib->vba.DSCFormatFactor + / (1 + - mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100); else - mode_lib->vba.DSCCLK_calculated[k] = mode_lib->vba.PixelClockBackEnd[k] / 3 - / mode_lib->vba.DSCFormatFactor - / (1 - mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading / 100); + mode_lib->vba.DSCCLK_calculated[k] = + mode_lib->vba.PixelClockBackEnd[k] / 3 + / mode_lib->vba.DSCFormatFactor + / (1 + - mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100); } } @@ -2013,27 +2366,35 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman if (mode_lib->vba.DSCEnabled[k] && bpp != 0) { if (!mode_lib->vba.ODMCombineEnabled[k]) { mode_lib->vba.DSCDelay[k] = - dscceComputeDelay(mode_lib->vba.DSCInputBitPerComponent[k], - bpp, - dml_ceil((double)mode_lib->vba.HActive[k] - / mode_lib->vba.NumberOfDSCSlices[k], - 1), - slices, - mode_lib->vba.OutputFormat[k]) - + dscComputeDelay(mode_lib->vba.OutputFormat[k]); + dscceComputeDelay( + mode_lib->vba.DSCInputBitPerComponent[k], + bpp, + dml_ceil( + (double) mode_lib->vba.HActive[k] + / mode_lib->vba.NumberOfDSCSlices[k], + 1), + slices, + mode_lib->vba.OutputFormat[k]) + + dscComputeDelay( + mode_lib->vba.OutputFormat[k]); } else { mode_lib->vba.DSCDelay[k] = - 2 - * (dscceComputeDelay(mode_lib->vba.DSCInputBitPerComponent[k], - bpp, - dml_ceil((double)mode_lib->vba.HActive[k] - / mode_lib->vba.NumberOfDSCSlices[k], - 1), - slices / 2.0, - mode_lib->vba.OutputFormat[k]) - + dscComputeDelay(mode_lib->vba.OutputFormat[k])); - } - mode_lib->vba.DSCDelay[k] = mode_lib->vba.DSCDelay[k] * mode_lib->vba.PixelClock[k] / mode_lib->vba.PixelClockBackEnd[k]; + 2 + * (dscceComputeDelay( + mode_lib->vba.DSCInputBitPerComponent[k], + bpp, + dml_ceil( + (double) mode_lib->vba.HActive[k] + / mode_lib->vba.NumberOfDSCSlices[k], + 1), + slices / 2.0, + mode_lib->vba.OutputFormat[k]) + + dscComputeDelay( + mode_lib->vba.OutputFormat[k])); + } + mode_lib->vba.DSCDelay[k] = mode_lib->vba.DSCDelay[k] + * mode_lib->vba.PixelClock[k] + / mode_lib->vba.PixelClockBackEnd[k]; } else { mode_lib->vba.DSCDelay[k] = 0; } @@ -2041,7 +2402,8 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) for (j = 0; j < mode_lib->vba.NumberOfActivePlanes; ++j) // NumberOfPlanes - if (j != k && mode_lib->vba.BlendingAndTiming[k] == j && mode_lib->vba.DSCEnabled[j]) + if (j != k && mode_lib->vba.BlendingAndTiming[k] == j + && mode_lib->vba.DSCEnabled[j]) mode_lib->vba.DSCDelay[k] = mode_lib->vba.DSCDelay[j]; // Prefetch @@ -2053,82 +2415,91 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman unsigned int PDEAndMetaPTEBytesFrameC; unsigned int PixelPTEBytesPerRowC; - Calculate256BBlockSizes(mode_lib->vba.SourcePixelFormat[k], - mode_lib->vba.SurfaceTiling[k], - dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1), - dml_ceil(mode_lib->vba.BytePerPixelDETC[k], 2), - &mode_lib->vba.BlockHeight256BytesY[k], - &mode_lib->vba.BlockHeight256BytesC[k], - &mode_lib->vba.BlockWidth256BytesY[k], - &mode_lib->vba.BlockWidth256BytesC[k]); - PDEAndMetaPTEBytesFrameY = CalculateVMAndRowBytes(mode_lib, - mode_lib->vba.DCCEnable[k], - mode_lib->vba.BlockHeight256BytesY[k], - mode_lib->vba.BlockWidth256BytesY[k], - mode_lib->vba.SourcePixelFormat[k], - mode_lib->vba.SurfaceTiling[k], - dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1), - mode_lib->vba.SourceScan[k], - mode_lib->vba.ViewportWidth[k], - mode_lib->vba.ViewportHeight[k], - mode_lib->vba.SwathWidthY[k], - mode_lib->vba.VirtualMemoryEnable, - mode_lib->vba.VMMPageSize, - mode_lib->vba.PTEBufferSizeInRequests, - mode_lib->vba.PDEProcessingBufIn64KBReqs, - mode_lib->vba.PitchY[k], - mode_lib->vba.DCCMetaPitchY[k], - &mode_lib->vba.MacroTileWidthY, - &MetaRowByteY, - &PixelPTEBytesPerRowY, - &mode_lib->vba.PTEBufferSizeNotExceeded, - &mode_lib->vba.dpte_row_height[k], - &mode_lib->vba.meta_row_height[k]); - mode_lib->vba.PrefetchSourceLinesY[k] = CalculatePrefetchSourceLines(mode_lib, - mode_lib->vba.VRatio[k], - mode_lib->vba.vtaps[k], - mode_lib->vba.Interlace[k], - mode_lib->vba.ProgressiveToInterlaceUnitInOPP, - mode_lib->vba.SwathHeightY[k], - mode_lib->vba.ViewportYStartY[k], - &mode_lib->vba.VInitPreFillY[k], - &mode_lib->vba.MaxNumSwathY[k]); - - if ((mode_lib->vba.SourcePixelFormat[k] != dm_444_64 && mode_lib->vba.SourcePixelFormat[k] != dm_444_32 - && mode_lib->vba.SourcePixelFormat[k] != dm_444_16 - && mode_lib->vba.SourcePixelFormat[k] != dm_444_8)) { - PDEAndMetaPTEBytesFrameC = CalculateVMAndRowBytes(mode_lib, - mode_lib->vba.DCCEnable[k], - mode_lib->vba.BlockHeight256BytesC[k], - mode_lib->vba.BlockWidth256BytesC[k], + Calculate256BBlockSizes( mode_lib->vba.SourcePixelFormat[k], mode_lib->vba.SurfaceTiling[k], + dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1), dml_ceil(mode_lib->vba.BytePerPixelDETC[k], 2), + &mode_lib->vba.BlockHeight256BytesY[k], + &mode_lib->vba.BlockHeight256BytesC[k], + &mode_lib->vba.BlockWidth256BytesY[k], + &mode_lib->vba.BlockWidth256BytesC[k]); + PDEAndMetaPTEBytesFrameY = CalculateVMAndRowBytes( + mode_lib, + mode_lib->vba.DCCEnable[k], + mode_lib->vba.BlockHeight256BytesY[k], + mode_lib->vba.BlockWidth256BytesY[k], + mode_lib->vba.SourcePixelFormat[k], + mode_lib->vba.SurfaceTiling[k], + dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1), mode_lib->vba.SourceScan[k], - mode_lib->vba.ViewportWidth[k] / 2, - mode_lib->vba.ViewportHeight[k] / 2, - mode_lib->vba.SwathWidthY[k] / 2, + mode_lib->vba.ViewportWidth[k], + mode_lib->vba.ViewportHeight[k], + mode_lib->vba.SwathWidthY[k], mode_lib->vba.VirtualMemoryEnable, mode_lib->vba.VMMPageSize, mode_lib->vba.PTEBufferSizeInRequests, mode_lib->vba.PDEProcessingBufIn64KBReqs, - mode_lib->vba.PitchC[k], - 0, - &mode_lib->vba.MacroTileWidthC, - &MetaRowByteC, - &PixelPTEBytesPerRowC, - &mode_lib->vba.PTEBufferSizeNotExceeded, - &mode_lib->vba.dpte_row_height_chroma[k], - &mode_lib->vba.meta_row_height_chroma[k]); - mode_lib->vba.PrefetchSourceLinesC[k] = CalculatePrefetchSourceLines(mode_lib, - mode_lib->vba.VRatio[k] / 2, - mode_lib->vba.VTAPsChroma[k], + mode_lib->vba.PitchY[k], + mode_lib->vba.DCCMetaPitchY[k], + &mode_lib->vba.MacroTileWidthY[k], + &MetaRowByteY, + &PixelPTEBytesPerRowY, + &mode_lib->vba.PTEBufferSizeNotExceeded[mode_lib->vba.VoltageLevel], + &mode_lib->vba.dpte_row_height[k], + &mode_lib->vba.meta_row_height[k]); + mode_lib->vba.PrefetchSourceLinesY[k] = CalculatePrefetchSourceLines( + mode_lib, + mode_lib->vba.VRatio[k], + mode_lib->vba.vtaps[k], mode_lib->vba.Interlace[k], mode_lib->vba.ProgressiveToInterlaceUnitInOPP, - mode_lib->vba.SwathHeightC[k], - mode_lib->vba.ViewportYStartC[k], - &mode_lib->vba.VInitPreFillC[k], - &mode_lib->vba.MaxNumSwathC[k]); + mode_lib->vba.SwathHeightY[k], + mode_lib->vba.ViewportYStartY[k], + &mode_lib->vba.VInitPreFillY[k], + &mode_lib->vba.MaxNumSwathY[k]); + + if ((mode_lib->vba.SourcePixelFormat[k] != dm_444_64 + && mode_lib->vba.SourcePixelFormat[k] != dm_444_32 + && mode_lib->vba.SourcePixelFormat[k] != dm_444_16 + && mode_lib->vba.SourcePixelFormat[k] != dm_444_8)) { + PDEAndMetaPTEBytesFrameC = + CalculateVMAndRowBytes( + mode_lib, + mode_lib->vba.DCCEnable[k], + mode_lib->vba.BlockHeight256BytesC[k], + mode_lib->vba.BlockWidth256BytesC[k], + mode_lib->vba.SourcePixelFormat[k], + mode_lib->vba.SurfaceTiling[k], + dml_ceil( + mode_lib->vba.BytePerPixelDETC[k], + 2), + mode_lib->vba.SourceScan[k], + mode_lib->vba.ViewportWidth[k] / 2, + mode_lib->vba.ViewportHeight[k] / 2, + mode_lib->vba.SwathWidthY[k] / 2, + mode_lib->vba.VirtualMemoryEnable, + mode_lib->vba.VMMPageSize, + mode_lib->vba.PTEBufferSizeInRequests, + mode_lib->vba.PDEProcessingBufIn64KBReqs, + mode_lib->vba.PitchC[k], + 0, + &mode_lib->vba.MacroTileWidthC[k], + &MetaRowByteC, + &PixelPTEBytesPerRowC, + &mode_lib->vba.PTEBufferSizeNotExceeded[mode_lib->vba.VoltageLevel], + &mode_lib->vba.dpte_row_height_chroma[k], + &mode_lib->vba.meta_row_height_chroma[k]); + mode_lib->vba.PrefetchSourceLinesC[k] = CalculatePrefetchSourceLines( + mode_lib, + mode_lib->vba.VRatio[k] / 2, + mode_lib->vba.VTAPsChroma[k], + mode_lib->vba.Interlace[k], + mode_lib->vba.ProgressiveToInterlaceUnitInOPP, + mode_lib->vba.SwathHeightC[k], + mode_lib->vba.ViewportYStartC[k], + &mode_lib->vba.VInitPreFillC[k], + &mode_lib->vba.MaxNumSwathC[k]); } else { PixelPTEBytesPerRowC = 0; PDEAndMetaPTEBytesFrameC = 0; @@ -2138,25 +2509,27 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman } mode_lib->vba.PixelPTEBytesPerRow[k] = PixelPTEBytesPerRowY + PixelPTEBytesPerRowC; - mode_lib->vba.PDEAndMetaPTEBytesFrame[k] = PDEAndMetaPTEBytesFrameY + PDEAndMetaPTEBytesFrameC; + mode_lib->vba.PDEAndMetaPTEBytesFrame[k] = PDEAndMetaPTEBytesFrameY + + PDEAndMetaPTEBytesFrameC; mode_lib->vba.MetaRowByte[k] = MetaRowByteY + MetaRowByteC; - CalculateActiveRowBandwidth(mode_lib->vba.VirtualMemoryEnable, - mode_lib->vba.SourcePixelFormat[k], - mode_lib->vba.VRatio[k], - mode_lib->vba.DCCEnable[k], - mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k], - MetaRowByteY, - MetaRowByteC, - mode_lib->vba.meta_row_height[k], - mode_lib->vba.meta_row_height_chroma[k], - PixelPTEBytesPerRowY, - PixelPTEBytesPerRowC, - mode_lib->vba.dpte_row_height[k], - mode_lib->vba.dpte_row_height_chroma[k], - &mode_lib->vba.meta_row_bw[k], - &mode_lib->vba.dpte_row_bw[k], - &mode_lib->vba.qual_row_bw[k]); + CalculateActiveRowBandwidth( + mode_lib->vba.VirtualMemoryEnable, + mode_lib->vba.SourcePixelFormat[k], + mode_lib->vba.VRatio[k], + mode_lib->vba.DCCEnable[k], + mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k], + MetaRowByteY, + MetaRowByteC, + mode_lib->vba.meta_row_height[k], + mode_lib->vba.meta_row_height_chroma[k], + PixelPTEBytesPerRowY, + PixelPTEBytesPerRowC, + mode_lib->vba.dpte_row_height[k], + mode_lib->vba.dpte_row_height_chroma[k], + &mode_lib->vba.meta_row_bw[k], + &mode_lib->vba.dpte_row_bw[k], + &mode_lib->vba.qual_row_bw[k]); } mode_lib->vba.TCalc = 24.0 / mode_lib->vba.DCFClkDeepSleep; @@ -2164,32 +2537,37 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { if (mode_lib->vba.BlendingAndTiming[k] == k) { if (mode_lib->vba.WritebackEnable[k] == true) { - mode_lib->vba.WritebackDelay[k] = mode_lib->vba.WritebackLatency - + CalculateWriteBackDelay(mode_lib->vba.WritebackPixelFormat[k], - mode_lib->vba.WritebackHRatio[k], - mode_lib->vba.WritebackVRatio[k], - mode_lib->vba.WritebackLumaHTaps[k], - mode_lib->vba.WritebackLumaVTaps[k], - mode_lib->vba.WritebackChromaHTaps[k], - mode_lib->vba.WritebackChromaVTaps[k], - mode_lib->vba.WritebackDestinationWidth[k]) - / mode_lib->vba.DISPCLK; + mode_lib->vba.WritebackDelay[mode_lib->vba.VoltageLevel][k] = + mode_lib->vba.WritebackLatency + + CalculateWriteBackDelay( + mode_lib->vba.WritebackPixelFormat[k], + mode_lib->vba.WritebackHRatio[k], + mode_lib->vba.WritebackVRatio[k], + mode_lib->vba.WritebackLumaHTaps[k], + mode_lib->vba.WritebackLumaVTaps[k], + mode_lib->vba.WritebackChromaHTaps[k], + mode_lib->vba.WritebackChromaVTaps[k], + mode_lib->vba.WritebackDestinationWidth[k]) + / mode_lib->vba.DISPCLK; } else - mode_lib->vba.WritebackDelay[k] = 0; + mode_lib->vba.WritebackDelay[mode_lib->vba.VoltageLevel][k] = 0; for (j = 0; j < mode_lib->vba.NumberOfActivePlanes; ++j) { - if (mode_lib->vba.BlendingAndTiming[j] == k && mode_lib->vba.WritebackEnable[j] == true) { - mode_lib->vba.WritebackDelay[k] = - dml_max(mode_lib->vba.WritebackDelay[k], - mode_lib->vba.WritebackLatency - + CalculateWriteBackDelay(mode_lib->vba.WritebackPixelFormat[j], - mode_lib->vba.WritebackHRatio[j], - mode_lib->vba.WritebackVRatio[j], - mode_lib->vba.WritebackLumaHTaps[j], - mode_lib->vba.WritebackLumaVTaps[j], - mode_lib->vba.WritebackChromaHTaps[j], - mode_lib->vba.WritebackChromaVTaps[j], - mode_lib->vba.WritebackDestinationWidth[j]) - / mode_lib->vba.DISPCLK); + if (mode_lib->vba.BlendingAndTiming[j] == k + && mode_lib->vba.WritebackEnable[j] == true) { + mode_lib->vba.WritebackDelay[mode_lib->vba.VoltageLevel][k] = + dml_max( + mode_lib->vba.WritebackDelay[mode_lib->vba.VoltageLevel][k], + mode_lib->vba.WritebackLatency + + CalculateWriteBackDelay( + mode_lib->vba.WritebackPixelFormat[j], + mode_lib->vba.WritebackHRatio[j], + mode_lib->vba.WritebackVRatio[j], + mode_lib->vba.WritebackLumaHTaps[j], + mode_lib->vba.WritebackLumaVTaps[j], + mode_lib->vba.WritebackChromaHTaps[j], + mode_lib->vba.WritebackChromaVTaps[j], + mode_lib->vba.WritebackDestinationWidth[j]) + / mode_lib->vba.DISPCLK); } } } @@ -2198,27 +2576,34 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) for (j = 0; j < mode_lib->vba.NumberOfActivePlanes; ++j) if (mode_lib->vba.BlendingAndTiming[k] == j) - mode_lib->vba.WritebackDelay[k] = mode_lib->vba.WritebackDelay[j]; + mode_lib->vba.WritebackDelay[mode_lib->vba.VoltageLevel][k] = + mode_lib->vba.WritebackDelay[mode_lib->vba.VoltageLevel][j]; mode_lib->vba.VStartupLines = 13; for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { mode_lib->vba.MaxVStartupLines[k] = - mode_lib->vba.VTotal[k] - mode_lib->vba.VActive[k] - - dml_max(1.0, - dml_ceil(mode_lib->vba.WritebackDelay[k] - / (mode_lib->vba.HTotal[k] - / mode_lib->vba.PixelClock[k]), - 1)); + mode_lib->vba.VTotal[k] - mode_lib->vba.VActive[k] + - dml_max( + 1.0, + dml_ceil( + mode_lib->vba.WritebackDelay[mode_lib->vba.VoltageLevel][k] + / (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]), + 1)); } for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) - mode_lib->vba.MaximumMaxVStartupLines = dml_max(mode_lib->vba.MaximumMaxVStartupLines, mode_lib->vba.MaxVStartupLines[k]); + mode_lib->vba.MaximumMaxVStartupLines = dml_max( + mode_lib->vba.MaximumMaxVStartupLines, + mode_lib->vba.MaxVStartupLines[k]); for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { mode_lib->vba.cursor_bw[k] = 0.0; for (j = 0; j < mode_lib->vba.NumberOfCursors[k]; ++j) - mode_lib->vba.cursor_bw[k] += mode_lib->vba.CursorWidth[k][j] * mode_lib->vba.CursorBPP[k][j] / 8.0 - / (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) * mode_lib->vba.VRatio[k]; + mode_lib->vba.cursor_bw[k] += mode_lib->vba.CursorWidth[k][j] + * mode_lib->vba.CursorBPP[k][j] / 8.0 + / (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) + * mode_lib->vba.VRatio[k]; } do { @@ -2227,102 +2612,119 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman bool VRatioPrefetchMoreThan4 = false; bool prefetch_vm_bw_valid = true; bool prefetch_row_bw_valid = true; - double TWait = CalculateTWait(mode_lib->vba.PrefetchMode, - mode_lib->vba.DRAMClockChangeLatency, - mode_lib->vba.UrgentLatency, - mode_lib->vba.SREnterPlusExitTime); + double TWait = CalculateTWait( + mode_lib->vba.PrefetchMode, + mode_lib->vba.DRAMClockChangeLatency, + mode_lib->vba.UrgentLatency, + mode_lib->vba.SREnterPlusExitTime); for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { if (mode_lib->vba.XFCEnabled[k] == true) { - mode_lib->vba.XFCRemoteSurfaceFlipDelay = CalculateRemoteSurfaceFlipDelay(mode_lib, - mode_lib->vba.VRatio[k], - mode_lib->vba.SwathWidthY[k], - dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1), - mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k], - mode_lib->vba.XFCTSlvVupdateOffset, - mode_lib->vba.XFCTSlvVupdateWidth, - mode_lib->vba.XFCTSlvVreadyOffset, - mode_lib->vba.XFCXBUFLatencyTolerance, - mode_lib->vba.XFCFillBWOverhead, - mode_lib->vba.XFCSlvChunkSize, - mode_lib->vba.XFCBusTransportTime, - mode_lib->vba.TCalc, - TWait, - &mode_lib->vba.SrcActiveDrainRate, - &mode_lib->vba.TInitXFill, - &mode_lib->vba.TslvChk); + mode_lib->vba.XFCRemoteSurfaceFlipDelay = + CalculateRemoteSurfaceFlipDelay( + mode_lib, + mode_lib->vba.VRatio[k], + mode_lib->vba.SwathWidthY[k], + dml_ceil( + mode_lib->vba.BytePerPixelDETY[k], + 1), + mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k], + mode_lib->vba.XFCTSlvVupdateOffset, + mode_lib->vba.XFCTSlvVupdateWidth, + mode_lib->vba.XFCTSlvVreadyOffset, + mode_lib->vba.XFCXBUFLatencyTolerance, + mode_lib->vba.XFCFillBWOverhead, + mode_lib->vba.XFCSlvChunkSize, + mode_lib->vba.XFCBusTransportTime, + mode_lib->vba.TCalc, + TWait, + &mode_lib->vba.SrcActiveDrainRate, + &mode_lib->vba.TInitXFill, + &mode_lib->vba.TslvChk); } else { mode_lib->vba.XFCRemoteSurfaceFlipDelay = 0; } - mode_lib->vba.ErrorResult[k] = CalculatePrefetchSchedule(mode_lib, - mode_lib->vba.DPPCLK[k], - mode_lib->vba.DISPCLK, - mode_lib->vba.PixelClock[k], - mode_lib->vba.DCFClkDeepSleep, - mode_lib->vba.DSCDelay[k], - mode_lib->vba.DPPPerPlane[k], - mode_lib->vba.ScalerEnabled[k], - mode_lib->vba.NumberOfCursors[k], - mode_lib->vba.DPPCLKDelaySubtotal, - mode_lib->vba.DPPCLKDelaySCL, - mode_lib->vba.DPPCLKDelaySCLLBOnly, - mode_lib->vba.DPPCLKDelayCNVCFormater, - mode_lib->vba.DPPCLKDelayCNVCCursor, - mode_lib->vba.DISPCLKDelaySubtotal, - (unsigned int)(mode_lib->vba.SwathWidthY[k] / mode_lib->vba.HRatio[k]), - mode_lib->vba.OutputFormat[k], - mode_lib->vba.VTotal[k] - mode_lib->vba.VActive[k], - mode_lib->vba.HTotal[k], - mode_lib->vba.MaxInterDCNTileRepeaters, - dml_min(mode_lib->vba.VStartupLines, mode_lib->vba.MaxVStartupLines[k]), - mode_lib->vba.MaxPageTableLevels, - mode_lib->vba.VirtualMemoryEnable, - mode_lib->vba.DynamicMetadataEnable[k], - mode_lib->vba.DynamicMetadataLinesBeforeActiveRequired[k], - mode_lib->vba.DynamicMetadataTransmittedBytes[k], - mode_lib->vba.DCCEnable[k], - mode_lib->vba.UrgentLatency, - mode_lib->vba.UrgentExtraLatency, - mode_lib->vba.TCalc, - mode_lib->vba.PDEAndMetaPTEBytesFrame[k], - mode_lib->vba.MetaRowByte[k], - mode_lib->vba.PixelPTEBytesPerRow[k], - mode_lib->vba.PrefetchSourceLinesY[k], - mode_lib->vba.SwathWidthY[k], - mode_lib->vba.BytePerPixelDETY[k], - mode_lib->vba.VInitPreFillY[k], - mode_lib->vba.MaxNumSwathY[k], - mode_lib->vba.PrefetchSourceLinesC[k], - mode_lib->vba.BytePerPixelDETC[k], - mode_lib->vba.VInitPreFillC[k], - mode_lib->vba.MaxNumSwathC[k], - mode_lib->vba.SwathHeightY[k], - mode_lib->vba.SwathHeightC[k], - TWait, - mode_lib->vba.XFCEnabled[k], - mode_lib->vba.XFCRemoteSurfaceFlipDelay, - mode_lib->vba.Interlace[k], - mode_lib->vba.ProgressiveToInterlaceUnitInOPP, - &mode_lib->vba.DSTXAfterScaler[k], - &mode_lib->vba.DSTYAfterScaler[k], - &mode_lib->vba.DestinationLinesForPrefetch[k], - &mode_lib->vba.PrefetchBandwidth[k], - &mode_lib->vba.DestinationLinesToRequestVMInVBlank[k], - &mode_lib->vba.DestinationLinesToRequestRowInVBlank[k], - &mode_lib->vba.VRatioPrefetchY[k], - &mode_lib->vba.VRatioPrefetchC[k], - &mode_lib->vba.RequiredPrefetchPixDataBW[k], - &mode_lib->vba.VStartupRequiredWhenNotEnoughTimeForDynamicMetadata, - &mode_lib->vba.Tno_bw[k]); + mode_lib->vba.ErrorResult[k] = + CalculatePrefetchSchedule( + mode_lib, + mode_lib->vba.DPPCLK[k], + mode_lib->vba.DISPCLK, + mode_lib->vba.PixelClock[k], + mode_lib->vba.DCFClkDeepSleep, + mode_lib->vba.DSCDelay[k], + mode_lib->vba.DPPPerPlane[k], + mode_lib->vba.ScalerEnabled[k], + mode_lib->vba.NumberOfCursors[k], + mode_lib->vba.DPPCLKDelaySubtotal, + mode_lib->vba.DPPCLKDelaySCL, + mode_lib->vba.DPPCLKDelaySCLLBOnly, + mode_lib->vba.DPPCLKDelayCNVCFormater, + mode_lib->vba.DPPCLKDelayCNVCCursor, + mode_lib->vba.DISPCLKDelaySubtotal, + (unsigned int) (mode_lib->vba.SwathWidthY[k] + / mode_lib->vba.HRatio[k]), + mode_lib->vba.OutputFormat[k], + mode_lib->vba.VTotal[k] + - mode_lib->vba.VActive[k], + mode_lib->vba.HTotal[k], + mode_lib->vba.MaxInterDCNTileRepeaters, + dml_min( + mode_lib->vba.VStartupLines, + mode_lib->vba.MaxVStartupLines[k]), + mode_lib->vba.MaxPageTableLevels, + mode_lib->vba.VirtualMemoryEnable, + mode_lib->vba.DynamicMetadataEnable[k], + mode_lib->vba.DynamicMetadataLinesBeforeActiveRequired[k], + mode_lib->vba.DynamicMetadataTransmittedBytes[k], + mode_lib->vba.DCCEnable[k], + mode_lib->vba.UrgentLatency, + mode_lib->vba.UrgentExtraLatency, + mode_lib->vba.TCalc, + mode_lib->vba.PDEAndMetaPTEBytesFrame[k], + mode_lib->vba.MetaRowByte[k], + mode_lib->vba.PixelPTEBytesPerRow[k], + mode_lib->vba.PrefetchSourceLinesY[k], + mode_lib->vba.SwathWidthY[k], + mode_lib->vba.BytePerPixelDETY[k], + mode_lib->vba.VInitPreFillY[k], + mode_lib->vba.MaxNumSwathY[k], + mode_lib->vba.PrefetchSourceLinesC[k], + mode_lib->vba.BytePerPixelDETC[k], + mode_lib->vba.VInitPreFillC[k], + mode_lib->vba.MaxNumSwathC[k], + mode_lib->vba.SwathHeightY[k], + mode_lib->vba.SwathHeightC[k], + TWait, + mode_lib->vba.XFCEnabled[k], + mode_lib->vba.XFCRemoteSurfaceFlipDelay, + mode_lib->vba.Interlace[k], + mode_lib->vba.ProgressiveToInterlaceUnitInOPP, + &mode_lib->vba.DSTXAfterScaler[k], + &mode_lib->vba.DSTYAfterScaler[k], + &mode_lib->vba.DestinationLinesForPrefetch[k], + &mode_lib->vba.PrefetchBandwidth[k], + &mode_lib->vba.DestinationLinesToRequestVMInVBlank[k], + &mode_lib->vba.DestinationLinesToRequestRowInVBlank[k], + &mode_lib->vba.VRatioPrefetchY[k], + &mode_lib->vba.VRatioPrefetchC[k], + &mode_lib->vba.RequiredPrefetchPixDataBW[k], + &mode_lib->vba.VStartupRequiredWhenNotEnoughTimeForDynamicMetadata, + &mode_lib->vba.Tno_bw[k]); if (mode_lib->vba.BlendingAndTiming[k] == k) { - mode_lib->vba.VStartup[k] = dml_min(mode_lib->vba.VStartupLines, mode_lib->vba.MaxVStartupLines[k]); - if (mode_lib->vba.VStartupRequiredWhenNotEnoughTimeForDynamicMetadata != 0) { + mode_lib->vba.VStartup[k] = dml_min( + mode_lib->vba.VStartupLines, + mode_lib->vba.MaxVStartupLines[k]); + if (mode_lib->vba.VStartupRequiredWhenNotEnoughTimeForDynamicMetadata + != 0) { mode_lib->vba.VStartup[k] = - mode_lib->vba.VStartupRequiredWhenNotEnoughTimeForDynamicMetadata; + mode_lib->vba.VStartupRequiredWhenNotEnoughTimeForDynamicMetadata; } } else { - mode_lib->vba.VStartup[k] = dml_min(mode_lib->vba.VStartupLines, - mode_lib->vba.MaxVStartupLines[mode_lib->vba.BlendingAndTiming[k]]); + mode_lib->vba.VStartup[k] = + dml_min( + mode_lib->vba.VStartupLines, + mode_lib->vba.MaxVStartupLines[mode_lib->vba.BlendingAndTiming[k]]); } } @@ -2331,116 +2733,136 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman if (mode_lib->vba.PDEAndMetaPTEBytesFrame[k] == 0) mode_lib->vba.prefetch_vm_bw[k] = 0; else if (mode_lib->vba.DestinationLinesToRequestVMInVBlank[k] > 0) { - mode_lib->vba.prefetch_vm_bw[k] = (double)mode_lib->vba.PDEAndMetaPTEBytesFrame[k] - / (mode_lib->vba.DestinationLinesToRequestVMInVBlank[k] - * mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]); + mode_lib->vba.prefetch_vm_bw[k] = + (double) mode_lib->vba.PDEAndMetaPTEBytesFrame[k] + / (mode_lib->vba.DestinationLinesToRequestVMInVBlank[k] + * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]); } else { mode_lib->vba.prefetch_vm_bw[k] = 0; prefetch_vm_bw_valid = false; } - if (mode_lib->vba.MetaRowByte[k] + mode_lib->vba.PixelPTEBytesPerRow[k] == 0) + if (mode_lib->vba.MetaRowByte[k] + mode_lib->vba.PixelPTEBytesPerRow[k] + == 0) mode_lib->vba.prefetch_row_bw[k] = 0; else if (mode_lib->vba.DestinationLinesToRequestRowInVBlank[k] > 0) { - mode_lib->vba.prefetch_row_bw[k] = (double)(mode_lib->vba.MetaRowByte[k] - + mode_lib->vba.PixelPTEBytesPerRow[k]) - / (mode_lib->vba.DestinationLinesToRequestRowInVBlank[k] - * mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]); + mode_lib->vba.prefetch_row_bw[k] = + (double) (mode_lib->vba.MetaRowByte[k] + + mode_lib->vba.PixelPTEBytesPerRow[k]) + / (mode_lib->vba.DestinationLinesToRequestRowInVBlank[k] + * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]); } else { mode_lib->vba.prefetch_row_bw[k] = 0; prefetch_row_bw_valid = false; } MaxTotalRDBandwidth = - MaxTotalRDBandwidth + mode_lib->vba.cursor_bw[k] - + dml_max(mode_lib->vba.prefetch_vm_bw[k], - dml_max(mode_lib->vba.prefetch_row_bw[k], - dml_max(mode_lib->vba.ReadBandwidthPlaneLuma[k] - + mode_lib->vba.ReadBandwidthPlaneChroma[k], - mode_lib->vba.RequiredPrefetchPixDataBW[k]) - + mode_lib->vba.meta_row_bw[k] - + mode_lib->vba.dpte_row_bw[k])); + MaxTotalRDBandwidth + mode_lib->vba.cursor_bw[k] + + dml_max( + mode_lib->vba.prefetch_vm_bw[k], + dml_max( + mode_lib->vba.prefetch_row_bw[k], + dml_max( + mode_lib->vba.ReadBandwidthPlaneLuma[k] + + mode_lib->vba.ReadBandwidthPlaneChroma[k], + mode_lib->vba.RequiredPrefetchPixDataBW[k]) + + mode_lib->vba.meta_row_bw[k] + + mode_lib->vba.dpte_row_bw[k])); if (mode_lib->vba.DestinationLinesForPrefetch[k] < 2) DestinationLineTimesForPrefetchLessThan2 = true; - if (mode_lib->vba.VRatioPrefetchY[k] > 4 || mode_lib->vba.VRatioPrefetchC[k] > 4) + if (mode_lib->vba.VRatioPrefetchY[k] > 4 + || mode_lib->vba.VRatioPrefetchC[k] > 4) VRatioPrefetchMoreThan4 = true; } - if (MaxTotalRDBandwidth <= mode_lib->vba.ReturnBW && prefetch_vm_bw_valid && prefetch_row_bw_valid - && !VRatioPrefetchMoreThan4 + if (MaxTotalRDBandwidth <= mode_lib->vba.ReturnBW && prefetch_vm_bw_valid + && prefetch_row_bw_valid && !VRatioPrefetchMoreThan4 && !DestinationLineTimesForPrefetchLessThan2) mode_lib->vba.PrefetchModeSupported = true; else { mode_lib->vba.PrefetchModeSupported = false; - dml_print("DML: CalculatePrefetchSchedule ***failed***. Bandwidth violation. Results are NOT valid\n"); + dml_print( + "DML: CalculatePrefetchSchedule ***failed***. Bandwidth violation. Results are NOT valid\n"); } if (mode_lib->vba.PrefetchModeSupported == true) { - double final_flip_bw[DC__NUM_PIPES__MAX]; - unsigned int ImmediateFlipBytes[DC__NUM_PIPES__MAX]; + double final_flip_bw[DC__NUM_DPP__MAX]; + unsigned int ImmediateFlipBytes[DC__NUM_DPP__MAX]; double total_dcn_read_bw_with_flip = 0; mode_lib->vba.BandwidthAvailableForImmediateFlip = mode_lib->vba.ReturnBW; for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { mode_lib->vba.BandwidthAvailableForImmediateFlip = - mode_lib->vba.BandwidthAvailableForImmediateFlip - mode_lib->vba.cursor_bw[k] - - dml_max(mode_lib->vba.ReadBandwidthPlaneLuma[k] - + mode_lib->vba.ReadBandwidthPlaneChroma[k] - + mode_lib->vba.qual_row_bw[k], - mode_lib->vba.PrefetchBandwidth[k]); + mode_lib->vba.BandwidthAvailableForImmediateFlip + - mode_lib->vba.cursor_bw[k] + - dml_max( + mode_lib->vba.ReadBandwidthPlaneLuma[k] + + mode_lib->vba.ReadBandwidthPlaneChroma[k] + + mode_lib->vba.qual_row_bw[k], + mode_lib->vba.PrefetchBandwidth[k]); } for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { ImmediateFlipBytes[k] = 0; if ((mode_lib->vba.SourcePixelFormat[k] != dm_420_8 - && mode_lib->vba.SourcePixelFormat[k] != dm_420_10)) { - ImmediateFlipBytes[k] = mode_lib->vba.PDEAndMetaPTEBytesFrame[k] - + mode_lib->vba.MetaRowByte[k] - + mode_lib->vba.PixelPTEBytesPerRow[k]; + && mode_lib->vba.SourcePixelFormat[k] != dm_420_10)) { + ImmediateFlipBytes[k] = + mode_lib->vba.PDEAndMetaPTEBytesFrame[k] + + mode_lib->vba.MetaRowByte[k] + + mode_lib->vba.PixelPTEBytesPerRow[k]; } } mode_lib->vba.TotImmediateFlipBytes = 0; for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { if ((mode_lib->vba.SourcePixelFormat[k] != dm_420_8 - && mode_lib->vba.SourcePixelFormat[k] != dm_420_10)) { - mode_lib->vba.TotImmediateFlipBytes = mode_lib->vba.TotImmediateFlipBytes - + ImmediateFlipBytes[k]; + && mode_lib->vba.SourcePixelFormat[k] != dm_420_10)) { + mode_lib->vba.TotImmediateFlipBytes = + mode_lib->vba.TotImmediateFlipBytes + + ImmediateFlipBytes[k]; } } for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { - CalculateFlipSchedule(mode_lib, - mode_lib->vba.UrgentExtraLatency, - mode_lib->vba.UrgentLatency, - mode_lib->vba.MaxPageTableLevels, - mode_lib->vba.VirtualMemoryEnable, - mode_lib->vba.BandwidthAvailableForImmediateFlip, - mode_lib->vba.TotImmediateFlipBytes, - mode_lib->vba.SourcePixelFormat[k], - ImmediateFlipBytes[k], - mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k], - mode_lib->vba.VRatio[k], - mode_lib->vba.Tno_bw[k], - mode_lib->vba.PDEAndMetaPTEBytesFrame[k], - mode_lib->vba.MetaRowByte[k], - mode_lib->vba.PixelPTEBytesPerRow[k], - mode_lib->vba.DCCEnable[k], - mode_lib->vba.dpte_row_height[k], - mode_lib->vba.meta_row_height[k], - mode_lib->vba.qual_row_bw[k], - &mode_lib->vba.DestinationLinesToRequestVMInImmediateFlip[k], - &mode_lib->vba.DestinationLinesToRequestRowInImmediateFlip[k], - &final_flip_bw[k], - &mode_lib->vba.ImmediateFlipSupportedForPipe[k]); + CalculateFlipSchedule( + mode_lib, + mode_lib->vba.UrgentExtraLatency, + mode_lib->vba.UrgentLatency, + mode_lib->vba.MaxPageTableLevels, + mode_lib->vba.VirtualMemoryEnable, + mode_lib->vba.BandwidthAvailableForImmediateFlip, + mode_lib->vba.TotImmediateFlipBytes, + mode_lib->vba.SourcePixelFormat[k], + ImmediateFlipBytes[k], + mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k], + mode_lib->vba.VRatio[k], + mode_lib->vba.Tno_bw[k], + mode_lib->vba.PDEAndMetaPTEBytesFrame[k], + mode_lib->vba.MetaRowByte[k], + mode_lib->vba.PixelPTEBytesPerRow[k], + mode_lib->vba.DCCEnable[k], + mode_lib->vba.dpte_row_height[k], + mode_lib->vba.meta_row_height[k], + mode_lib->vba.qual_row_bw[k], + &mode_lib->vba.DestinationLinesToRequestVMInImmediateFlip[k], + &mode_lib->vba.DestinationLinesToRequestRowInImmediateFlip[k], + &final_flip_bw[k], + &mode_lib->vba.ImmediateFlipSupportedForPipe[k]); } for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { total_dcn_read_bw_with_flip = - total_dcn_read_bw_with_flip + mode_lib->vba.cursor_bw[k] - + dml_max(mode_lib->vba.prefetch_vm_bw[k], - dml_max(mode_lib->vba.prefetch_row_bw[k], - final_flip_bw[k] - + dml_max(mode_lib->vba.ReadBandwidthPlaneLuma[k] - + mode_lib->vba.ReadBandwidthPlaneChroma[k], - mode_lib->vba.RequiredPrefetchPixDataBW[k]))); + total_dcn_read_bw_with_flip + + mode_lib->vba.cursor_bw[k] + + dml_max( + mode_lib->vba.prefetch_vm_bw[k], + dml_max( + mode_lib->vba.prefetch_row_bw[k], + final_flip_bw[k] + + dml_max( + mode_lib->vba.ReadBandwidthPlaneLuma[k] + + mode_lib->vba.ReadBandwidthPlaneChroma[k], + mode_lib->vba.RequiredPrefetchPixDataBW[k]))); } mode_lib->vba.ImmediateFlipSupported = true; if (total_dcn_read_bw_with_flip > mode_lib->vba.ReturnBW) { @@ -2458,35 +2880,44 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { if (mode_lib->vba.ErrorResult[k]) { mode_lib->vba.PrefetchModeSupported = false; - dml_print("DML: CalculatePrefetchSchedule ***failed***. Prefetch schedule violation. Results are NOT valid\n"); + dml_print( + "DML: CalculatePrefetchSchedule ***failed***. Prefetch schedule violation. Results are NOT valid\n"); } } mode_lib->vba.VStartupLines = mode_lib->vba.VStartupLines + 1; } while (!((mode_lib->vba.PrefetchModeSupported - && (!mode_lib->vba.ImmediateFlipSupport || mode_lib->vba.ImmediateFlipSupported)) - || mode_lib->vba.MaximumMaxVStartupLines < mode_lib->vba.VStartupLines)); + && (!mode_lib->vba.ImmediateFlipSupport + || mode_lib->vba.ImmediateFlipSupported)) + || mode_lib->vba.MaximumMaxVStartupLines < mode_lib->vba.VStartupLines)); //Display Pipeline Delivery Time in Prefetch for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { if (mode_lib->vba.VRatioPrefetchY[k] <= 1) { - mode_lib->vba.DisplayPipeLineDeliveryTimeLumaPrefetch[k] = mode_lib->vba.SwathWidthY[k] - * mode_lib->vba.DPPPerPlane[k] / mode_lib->vba.HRatio[k] / mode_lib->vba.PixelClock[k]; + mode_lib->vba.DisplayPipeLineDeliveryTimeLumaPrefetch[k] = + mode_lib->vba.SwathWidthY[k] * mode_lib->vba.DPPPerPlane[k] + / mode_lib->vba.HRatio[k] + / mode_lib->vba.PixelClock[k]; } else { - mode_lib->vba.DisplayPipeLineDeliveryTimeLumaPrefetch[k] = mode_lib->vba.SwathWidthY[k] - / mode_lib->vba.PSCL_THROUGHPUT_LUMA[k] / mode_lib->vba.DPPCLK[k]; + mode_lib->vba.DisplayPipeLineDeliveryTimeLumaPrefetch[k] = + mode_lib->vba.SwathWidthY[k] + / mode_lib->vba.PSCL_THROUGHPUT_LUMA[k] + / mode_lib->vba.DPPCLK[k]; } if (mode_lib->vba.BytePerPixelDETC[k] == 0) { mode_lib->vba.DisplayPipeLineDeliveryTimeChromaPrefetch[k] = 0; } else { if (mode_lib->vba.VRatioPrefetchC[k] <= 1) { mode_lib->vba.DisplayPipeLineDeliveryTimeChromaPrefetch[k] = - mode_lib->vba.SwathWidthY[k] * mode_lib->vba.DPPPerPlane[k] / mode_lib->vba.HRatio[k] - / mode_lib->vba.PixelClock[k]; + mode_lib->vba.SwathWidthY[k] + * mode_lib->vba.DPPPerPlane[k] + / mode_lib->vba.HRatio[k] + / mode_lib->vba.PixelClock[k]; } else { mode_lib->vba.DisplayPipeLineDeliveryTimeChromaPrefetch[k] = - mode_lib->vba.SwathWidthY[k] / mode_lib->vba.PSCL_THROUGHPUT_LUMA[k] - / mode_lib->vba.DPPCLK[k]; + mode_lib->vba.SwathWidthY[k] + / mode_lib->vba.PSCL_THROUGHPUT_LUMA[k] + / mode_lib->vba.DPPCLK[k]; } } } @@ -2496,19 +2927,25 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman if (mode_lib->vba.PrefetchMode == 0) { mode_lib->vba.AllowDRAMClockChangeDuringVBlank[k] = true; mode_lib->vba.AllowDRAMSelfRefreshDuringVBlank[k] = true; - mode_lib->vba.MinTTUVBlank[k] = dml_max(mode_lib->vba.DRAMClockChangeWatermark, - dml_max(mode_lib->vba.StutterEnterPlusExitWatermark, mode_lib->vba.UrgentWatermark)); + mode_lib->vba.MinTTUVBlank[k] = dml_max( + mode_lib->vba.DRAMClockChangeWatermark, + dml_max( + mode_lib->vba.StutterEnterPlusExitWatermark, + mode_lib->vba.UrgentWatermark)); } else if (mode_lib->vba.PrefetchMode == 1) { mode_lib->vba.AllowDRAMClockChangeDuringVBlank[k] = false; mode_lib->vba.AllowDRAMSelfRefreshDuringVBlank[k] = true; - mode_lib->vba.MinTTUVBlank[k] = dml_max(mode_lib->vba.StutterEnterPlusExitWatermark, mode_lib->vba.UrgentWatermark); + mode_lib->vba.MinTTUVBlank[k] = dml_max( + mode_lib->vba.StutterEnterPlusExitWatermark, + mode_lib->vba.UrgentWatermark); } else { mode_lib->vba.AllowDRAMClockChangeDuringVBlank[k] = false; mode_lib->vba.AllowDRAMSelfRefreshDuringVBlank[k] = false; mode_lib->vba.MinTTUVBlank[k] = mode_lib->vba.UrgentWatermark; } if (!mode_lib->vba.DynamicMetadataEnable[k]) - mode_lib->vba.MinTTUVBlank[k] = mode_lib->vba.TCalc + mode_lib->vba.MinTTUVBlank[k]; + mode_lib->vba.MinTTUVBlank[k] = mode_lib->vba.TCalc + + mode_lib->vba.MinTTUVBlank[k]; } // DCC Configuration @@ -2528,33 +2965,43 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman double ActiveDRAMClockChangeLatencyMarginY; mode_lib->vba.LBLatencyHidingSourceLinesY = - dml_min(mode_lib->vba.MaxLineBufferLines, - (unsigned int)dml_floor((double)mode_lib->vba.LineBufferSize - / mode_lib->vba.LBBitPerPixel[k] - / (mode_lib->vba.SwathWidthY[k] - / dml_max(mode_lib->vba.HRatio[k], - 1.0)), - 1)) - (mode_lib->vba.vtaps[k] - 1); + dml_min( + mode_lib->vba.MaxLineBufferLines, + (unsigned int) dml_floor( + (double) mode_lib->vba.LineBufferSize + / mode_lib->vba.LBBitPerPixel[k] + / (mode_lib->vba.SwathWidthY[k] + / dml_max( + mode_lib->vba.HRatio[k], + 1.0)), + 1)) - (mode_lib->vba.vtaps[k] - 1); mode_lib->vba.LBLatencyHidingSourceLinesC = - dml_min(mode_lib->vba.MaxLineBufferLines, - (unsigned int)dml_floor((double)mode_lib->vba.LineBufferSize - / mode_lib->vba.LBBitPerPixel[k] - / (mode_lib->vba.SwathWidthY[k] - / 2.0 - / dml_max(mode_lib->vba.HRatio[k] - / 2, - 1.0)), - 1)) - (mode_lib->vba.VTAPsChroma[k] - 1); - - EffectiveLBLatencyHidingY = mode_lib->vba.LBLatencyHidingSourceLinesY / mode_lib->vba.VRatio[k] - * (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]); - - EffectiveLBLatencyHidingC = mode_lib->vba.LBLatencyHidingSourceLinesC / (mode_lib->vba.VRatio[k] / 2) - * (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]); + dml_min( + mode_lib->vba.MaxLineBufferLines, + (unsigned int) dml_floor( + (double) mode_lib->vba.LineBufferSize + / mode_lib->vba.LBBitPerPixel[k] + / (mode_lib->vba.SwathWidthY[k] + / 2.0 + / dml_max( + mode_lib->vba.HRatio[k] + / 2, + 1.0)), + 1)) + - (mode_lib->vba.VTAPsChroma[k] - 1); + + EffectiveLBLatencyHidingY = mode_lib->vba.LBLatencyHidingSourceLinesY + / mode_lib->vba.VRatio[k] + * (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]); + + EffectiveLBLatencyHidingC = mode_lib->vba.LBLatencyHidingSourceLinesC + / (mode_lib->vba.VRatio[k] / 2) + * (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]); if (mode_lib->vba.SwathWidthY[k] > 2 * mode_lib->vba.DPPOutputBufferPixels) { - DPPOutputBufferLinesY = mode_lib->vba.DPPOutputBufferPixels / mode_lib->vba.SwathWidthY[k]; + DPPOutputBufferLinesY = mode_lib->vba.DPPOutputBufferPixels + / mode_lib->vba.SwathWidthY[k]; } else if (mode_lib->vba.SwathWidthY[k] > mode_lib->vba.DPPOutputBufferPixels) { DPPOutputBufferLinesY = 0.5; } else { @@ -2562,7 +3009,8 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman } if (mode_lib->vba.SwathWidthY[k] / 2 > 2 * mode_lib->vba.DPPOutputBufferPixels) { - DPPOutputBufferLinesC = mode_lib->vba.DPPOutputBufferPixels / (mode_lib->vba.SwathWidthY[k] / 2); + DPPOutputBufferLinesC = mode_lib->vba.DPPOutputBufferPixels + / (mode_lib->vba.SwathWidthY[k] / 2); } else if (mode_lib->vba.SwathWidthY[k] / 2 > mode_lib->vba.DPPOutputBufferPixels) { DPPOutputBufferLinesC = 0.5; } else { @@ -2570,46 +3018,59 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman } DPPOPPBufferingY = (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) - * (DPPOutputBufferLinesY + mode_lib->vba.OPPOutputBufferLines); + * (DPPOutputBufferLinesY + mode_lib->vba.OPPOutputBufferLines); MaxDETBufferingTimeY = mode_lib->vba.FullDETBufferingTimeY[k] - + (mode_lib->vba.LinesInDETY[k] - mode_lib->vba.LinesInDETYRoundedDownToSwath[k]) - / mode_lib->vba.SwathHeightY[k] * (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]); + + (mode_lib->vba.LinesInDETY[k] + - mode_lib->vba.LinesInDETYRoundedDownToSwath[k]) + / mode_lib->vba.SwathHeightY[k] + * (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]); ActiveDRAMClockChangeLatencyMarginY = DPPOPPBufferingY + EffectiveLBLatencyHidingY - + MaxDETBufferingTimeY - mode_lib->vba.DRAMClockChangeWatermark; + + MaxDETBufferingTimeY - mode_lib->vba.DRAMClockChangeWatermark; if (mode_lib->vba.ActiveDPPs > 1) { - ActiveDRAMClockChangeLatencyMarginY = ActiveDRAMClockChangeLatencyMarginY - - (1 - 1 / (mode_lib->vba.ActiveDPPs - 1)) * mode_lib->vba.SwathHeightY[k] - * (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]); + ActiveDRAMClockChangeLatencyMarginY = + ActiveDRAMClockChangeLatencyMarginY + - (1 - 1 / (mode_lib->vba.ActiveDPPs - 1)) + * mode_lib->vba.SwathHeightY[k] + * (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]); } if (mode_lib->vba.BytePerPixelDETC[k] > 0) { - double DPPOPPBufferingC = (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) - * (DPPOutputBufferLinesC + mode_lib->vba.OPPOutputBufferLines); + double DPPOPPBufferingC = (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]) + * (DPPOutputBufferLinesC + + mode_lib->vba.OPPOutputBufferLines); double MaxDETBufferingTimeC = - mode_lib->vba.FullDETBufferingTimeC[k] - + (mode_lib->vba.LinesInDETC[k] - - mode_lib->vba.LinesInDETCRoundedDownToSwath[k]) - / mode_lib->vba.SwathHeightC[k] - * (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]); + mode_lib->vba.FullDETBufferingTimeC[k] + + (mode_lib->vba.LinesInDETC[k] + - mode_lib->vba.LinesInDETCRoundedDownToSwath[k]) + / mode_lib->vba.SwathHeightC[k] + * (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]); double ActiveDRAMClockChangeLatencyMarginC = DPPOPPBufferingC - + EffectiveLBLatencyHidingC + MaxDETBufferingTimeC - - mode_lib->vba.DRAMClockChangeWatermark; + + EffectiveLBLatencyHidingC + MaxDETBufferingTimeC + - mode_lib->vba.DRAMClockChangeWatermark; if (mode_lib->vba.ActiveDPPs > 1) { ActiveDRAMClockChangeLatencyMarginC = - ActiveDRAMClockChangeLatencyMarginC - - (1 - 1 / (mode_lib->vba.ActiveDPPs - 1)) - * mode_lib->vba.SwathHeightC[k] - * (mode_lib->vba.HTotal[k] - / mode_lib->vba.PixelClock[k]); - } - mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k] = dml_min(ActiveDRAMClockChangeLatencyMarginY, - ActiveDRAMClockChangeLatencyMarginC); + ActiveDRAMClockChangeLatencyMarginC + - (1 + - 1 + / (mode_lib->vba.ActiveDPPs + - 1)) + * mode_lib->vba.SwathHeightC[k] + * (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]); + } + mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k] = dml_min( + ActiveDRAMClockChangeLatencyMarginY, + ActiveDRAMClockChangeLatencyMarginC); } else { mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k] = - ActiveDRAMClockChangeLatencyMarginY; + ActiveDRAMClockChangeLatencyMarginY; } if (mode_lib->vba.WritebackEnable[k]) { @@ -2617,51 +3078,60 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman if (mode_lib->vba.WritebackPixelFormat[k] == dm_444_32) { WritebackDRAMClockChangeLatencyMargin = - (double)(mode_lib->vba.WritebackInterfaceLumaBufferSize - + mode_lib->vba.WritebackInterfaceChromaBufferSize) - / (mode_lib->vba.WritebackDestinationWidth[k] - * mode_lib->vba.WritebackDestinationHeight[k] - / (mode_lib->vba.WritebackSourceHeight[k] - * mode_lib->vba.HTotal[k] - / mode_lib->vba.PixelClock[k]) - * 4) - - mode_lib->vba.WritebackDRAMClockChangeWatermark; + (double) (mode_lib->vba.WritebackInterfaceLumaBufferSize + + mode_lib->vba.WritebackInterfaceChromaBufferSize) + / (mode_lib->vba.WritebackDestinationWidth[k] + * mode_lib->vba.WritebackDestinationHeight[k] + / (mode_lib->vba.WritebackSourceHeight[k] + * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]) + * 4) + - mode_lib->vba.WritebackDRAMClockChangeWatermark; } else if (mode_lib->vba.WritebackPixelFormat[k] == dm_420_10) { - WritebackDRAMClockChangeLatencyMargin = dml_min((double)mode_lib->vba.WritebackInterfaceLumaBufferSize * 8.0 - / 10, - 2.0 * mode_lib->vba.WritebackInterfaceChromaBufferSize * 8 / 10) - / (mode_lib->vba.WritebackDestinationWidth[k] - * mode_lib->vba.WritebackDestinationHeight[k] - / (mode_lib->vba.WritebackSourceHeight[k] - * mode_lib->vba.HTotal[k] - / mode_lib->vba.PixelClock[k])) - - mode_lib->vba.WritebackDRAMClockChangeWatermark; + WritebackDRAMClockChangeLatencyMargin = + dml_min( + (double) mode_lib->vba.WritebackInterfaceLumaBufferSize + * 8.0 / 10, + 2.0 + * mode_lib->vba.WritebackInterfaceChromaBufferSize + * 8 / 10) + / (mode_lib->vba.WritebackDestinationWidth[k] + * mode_lib->vba.WritebackDestinationHeight[k] + / (mode_lib->vba.WritebackSourceHeight[k] + * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k])) + - mode_lib->vba.WritebackDRAMClockChangeWatermark; } else { - WritebackDRAMClockChangeLatencyMargin = dml_min((double)mode_lib->vba.WritebackInterfaceLumaBufferSize, - 2.0 * mode_lib->vba.WritebackInterfaceChromaBufferSize) - / (mode_lib->vba.WritebackDestinationWidth[k] - * mode_lib->vba.WritebackDestinationHeight[k] - / (mode_lib->vba.WritebackSourceHeight[k] - * mode_lib->vba.HTotal[k] - / mode_lib->vba.PixelClock[k])) - - mode_lib->vba.WritebackDRAMClockChangeWatermark; + WritebackDRAMClockChangeLatencyMargin = + dml_min( + (double) mode_lib->vba.WritebackInterfaceLumaBufferSize, + 2.0 + * mode_lib->vba.WritebackInterfaceChromaBufferSize) + / (mode_lib->vba.WritebackDestinationWidth[k] + * mode_lib->vba.WritebackDestinationHeight[k] + / (mode_lib->vba.WritebackSourceHeight[k] + * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k])) + - mode_lib->vba.WritebackDRAMClockChangeWatermark; } - mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k] = dml_min(mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k], - WritebackDRAMClockChangeLatencyMargin); + mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k] = dml_min( + mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k], + WritebackDRAMClockChangeLatencyMargin); } } mode_lib->vba.MinActiveDRAMClockChangeMargin = 999999; for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { if (mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k] - < mode_lib->vba.MinActiveDRAMClockChangeMargin) { + < mode_lib->vba.MinActiveDRAMClockChangeMargin) { mode_lib->vba.MinActiveDRAMClockChangeMargin = - mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k]; + mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k]; } } - mode_lib->vba.MinActiveDRAMClockChangeLatencySupported = mode_lib->vba.MinActiveDRAMClockChangeMargin - + mode_lib->vba.DRAMClockChangeLatency; + mode_lib->vba.MinActiveDRAMClockChangeLatencySupported = + mode_lib->vba.MinActiveDRAMClockChangeMargin + + mode_lib->vba.DRAMClockChangeLatency; if (mode_lib->vba.MinActiveDRAMClockChangeMargin > 0) { mode_lib->vba.DRAMClockChangeSupport = dm_dram_clock_change_vactive; @@ -2670,7 +3140,8 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman mode_lib->vba.DRAMClockChangeSupport = dm_dram_clock_change_vblank; for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { if (!mode_lib->vba.AllowDRAMClockChangeDuringVBlank[k]) { - mode_lib->vba.DRAMClockChangeSupport = dm_dram_clock_change_unsupported; + mode_lib->vba.DRAMClockChangeSupport = + dm_dram_clock_change_unsupported; } } } else { @@ -2686,48 +3157,74 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman mode_lib->vba.XFCSlaveVUpdateOffset[k] = mode_lib->vba.XFCTSlvVupdateOffset; mode_lib->vba.XFCSlaveVupdateWidth[k] = mode_lib->vba.XFCTSlvVupdateWidth; mode_lib->vba.XFCSlaveVReadyOffset[k] = mode_lib->vba.XFCTSlvVreadyOffset; - TWait = CalculateTWait(mode_lib->vba.PrefetchMode, - mode_lib->vba.DRAMClockChangeLatency, - mode_lib->vba.UrgentLatency, - mode_lib->vba.SREnterPlusExitTime); - mode_lib->vba.XFCRemoteSurfaceFlipDelay = CalculateRemoteSurfaceFlipDelay(mode_lib, - mode_lib->vba.VRatio[k], - mode_lib->vba.SwathWidthY[k], - dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1), - mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k], - mode_lib->vba.XFCTSlvVupdateOffset, - mode_lib->vba.XFCTSlvVupdateWidth, - mode_lib->vba.XFCTSlvVreadyOffset, - mode_lib->vba.XFCXBUFLatencyTolerance, - mode_lib->vba.XFCFillBWOverhead, - mode_lib->vba.XFCSlvChunkSize, - mode_lib->vba.XFCBusTransportTime, - mode_lib->vba.TCalc, - TWait, - &mode_lib->vba.SrcActiveDrainRate, - &mode_lib->vba.TInitXFill, - &mode_lib->vba.TslvChk); - mode_lib->vba.XFCRemoteSurfaceFlipLatency[k] = dml_floor(mode_lib->vba.XFCRemoteSurfaceFlipDelay / (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]), - 1); - mode_lib->vba.XFCTransferDelay[k] = dml_ceil(mode_lib->vba.XFCBusTransportTime / (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]), - 1); - mode_lib->vba.XFCPrechargeDelay[k] = dml_ceil((mode_lib->vba.XFCBusTransportTime + mode_lib->vba.TInitXFill + mode_lib->vba.TslvChk) - / (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]), - 1); - mode_lib->vba.InitFillLevel = mode_lib->vba.XFCXBUFLatencyTolerance * mode_lib->vba.SrcActiveDrainRate; - mode_lib->vba.FinalFillMargin = (mode_lib->vba.DestinationLinesToRequestVMInVBlank[k] - + mode_lib->vba.DestinationLinesToRequestRowInVBlank[k]) * mode_lib->vba.HTotal[k] - / mode_lib->vba.PixelClock[k] * mode_lib->vba.SrcActiveDrainRate + mode_lib->vba.XFCFillConstant; - mode_lib->vba.FinalFillLevel = mode_lib->vba.XFCRemoteSurfaceFlipDelay * mode_lib->vba.SrcActiveDrainRate - + mode_lib->vba.FinalFillMargin; - mode_lib->vba.RemainingFillLevel = dml_max(0.0, - mode_lib->vba.FinalFillLevel - mode_lib->vba.InitFillLevel); + TWait = CalculateTWait( + mode_lib->vba.PrefetchMode, + mode_lib->vba.DRAMClockChangeLatency, + mode_lib->vba.UrgentLatency, + mode_lib->vba.SREnterPlusExitTime); + mode_lib->vba.XFCRemoteSurfaceFlipDelay = CalculateRemoteSurfaceFlipDelay( + mode_lib, + mode_lib->vba.VRatio[k], + mode_lib->vba.SwathWidthY[k], + dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1), + mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k], + mode_lib->vba.XFCTSlvVupdateOffset, + mode_lib->vba.XFCTSlvVupdateWidth, + mode_lib->vba.XFCTSlvVreadyOffset, + mode_lib->vba.XFCXBUFLatencyTolerance, + mode_lib->vba.XFCFillBWOverhead, + mode_lib->vba.XFCSlvChunkSize, + mode_lib->vba.XFCBusTransportTime, + mode_lib->vba.TCalc, + TWait, + &mode_lib->vba.SrcActiveDrainRate, + &mode_lib->vba.TInitXFill, + &mode_lib->vba.TslvChk); + mode_lib->vba.XFCRemoteSurfaceFlipLatency[k] = + dml_floor( + mode_lib->vba.XFCRemoteSurfaceFlipDelay + / (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]), + 1); + mode_lib->vba.XFCTransferDelay[k] = + dml_ceil( + mode_lib->vba.XFCBusTransportTime + / (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]), + 1); + mode_lib->vba.XFCPrechargeDelay[k] = + dml_ceil( + (mode_lib->vba.XFCBusTransportTime + + mode_lib->vba.TInitXFill + + mode_lib->vba.TslvChk) + / (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]), + 1); + mode_lib->vba.InitFillLevel = mode_lib->vba.XFCXBUFLatencyTolerance + * mode_lib->vba.SrcActiveDrainRate; + mode_lib->vba.FinalFillMargin = + (mode_lib->vba.DestinationLinesToRequestVMInVBlank[k] + + mode_lib->vba.DestinationLinesToRequestRowInVBlank[k]) + * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k] + * mode_lib->vba.SrcActiveDrainRate + + mode_lib->vba.XFCFillConstant; + mode_lib->vba.FinalFillLevel = mode_lib->vba.XFCRemoteSurfaceFlipDelay + * mode_lib->vba.SrcActiveDrainRate + + mode_lib->vba.FinalFillMargin; + mode_lib->vba.RemainingFillLevel = dml_max( + 0.0, + mode_lib->vba.FinalFillLevel - mode_lib->vba.InitFillLevel); mode_lib->vba.TFinalxFill = mode_lib->vba.RemainingFillLevel - / (mode_lib->vba.SrcActiveDrainRate * mode_lib->vba.XFCFillBWOverhead / 100); - mode_lib->vba.XFCPrefetchMargin[k] = mode_lib->vba.XFCRemoteSurfaceFlipDelay + mode_lib->vba.TFinalxFill - + (mode_lib->vba.DestinationLinesToRequestVMInVBlank[k] - + mode_lib->vba.DestinationLinesToRequestRowInVBlank[k]) - * mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]; + / (mode_lib->vba.SrcActiveDrainRate + * mode_lib->vba.XFCFillBWOverhead / 100); + mode_lib->vba.XFCPrefetchMargin[k] = + mode_lib->vba.XFCRemoteSurfaceFlipDelay + + mode_lib->vba.TFinalxFill + + (mode_lib->vba.DestinationLinesToRequestVMInVBlank[k] + + mode_lib->vba.DestinationLinesToRequestRowInVBlank[k]) + * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]; } else { mode_lib->vba.XFCSlaveVUpdateOffset[k] = 0; mode_lib->vba.XFCSlaveVupdateWidth[k] = 0; @@ -2782,21 +3279,22 @@ static void DisplayPipeConfiguration(struct display_mode_lib *mode_lib) BytePerPixDETC = 8.0 / 3.0; } - if ((mode_lib->vba.SourcePixelFormat[k] == dm_444_64 || mode_lib->vba.SourcePixelFormat[k] == dm_444_32 - || mode_lib->vba.SourcePixelFormat[k] == dm_444_16 - || mode_lib->vba.SourcePixelFormat[k] == dm_444_8)) { + if ((mode_lib->vba.SourcePixelFormat[k] == dm_444_64 + || mode_lib->vba.SourcePixelFormat[k] == dm_444_32 + || mode_lib->vba.SourcePixelFormat[k] == dm_444_16 + || mode_lib->vba.SourcePixelFormat[k] == dm_444_8)) { if (mode_lib->vba.SurfaceTiling[k] == dm_sw_linear) { Read256BytesBlockHeightY = 1; } else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_64) { Read256BytesBlockHeightY = 4; } else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_32 - || mode_lib->vba.SourcePixelFormat[k] == dm_444_16) { + || mode_lib->vba.SourcePixelFormat[k] == dm_444_16) { Read256BytesBlockHeightY = 8; } else { Read256BytesBlockHeightY = 16; } Read256BytesBlockWidthY = 256 / dml_ceil(BytePerPixDETY, 1) - / Read256BytesBlockHeightY; + / Read256BytesBlockHeightY; Read256BytesBlockHeightC = 0; Read256BytesBlockWidthC = 0; } else { @@ -2811,9 +3309,9 @@ static void DisplayPipeConfiguration(struct display_mode_lib *mode_lib) Read256BytesBlockHeightC = 8; } Read256BytesBlockWidthY = 256 / dml_ceil(BytePerPixDETY, 1) - / Read256BytesBlockHeightY; + / Read256BytesBlockHeightY; Read256BytesBlockWidthC = 256 / dml_ceil(BytePerPixDETC, 2) - / Read256BytesBlockHeightC; + / Read256BytesBlockHeightC; } if (mode_lib->vba.SourceScan[k] == dm_horz) { @@ -2824,27 +3322,30 @@ static void DisplayPipeConfiguration(struct display_mode_lib *mode_lib) MaximumSwathHeightC = Read256BytesBlockWidthC; } - if ((mode_lib->vba.SourcePixelFormat[k] == dm_444_64 || mode_lib->vba.SourcePixelFormat[k] == dm_444_32 - || mode_lib->vba.SourcePixelFormat[k] == dm_444_16 - || mode_lib->vba.SourcePixelFormat[k] == dm_444_8)) { + if ((mode_lib->vba.SourcePixelFormat[k] == dm_444_64 + || mode_lib->vba.SourcePixelFormat[k] == dm_444_32 + || mode_lib->vba.SourcePixelFormat[k] == dm_444_16 + || mode_lib->vba.SourcePixelFormat[k] == dm_444_8)) { if (mode_lib->vba.SurfaceTiling[k] == dm_sw_linear - || (mode_lib->vba.SourcePixelFormat[k] == dm_444_64 - && (mode_lib->vba.SurfaceTiling[k] == dm_sw_4kb_s - || mode_lib->vba.SurfaceTiling[k] - == dm_sw_4kb_s_x - || mode_lib->vba.SurfaceTiling[k] - == dm_sw_64kb_s - || mode_lib->vba.SurfaceTiling[k] - == dm_sw_64kb_s_t - || mode_lib->vba.SurfaceTiling[k] - == dm_sw_64kb_s_x - || mode_lib->vba.SurfaceTiling[k] - == dm_sw_var_s - || mode_lib->vba.SurfaceTiling[k] - == dm_sw_var_s_x) - && mode_lib->vba.SourceScan[k] == dm_horz)) { + || (mode_lib->vba.SourcePixelFormat[k] == dm_444_64 + && (mode_lib->vba.SurfaceTiling[k] + == dm_sw_4kb_s + || mode_lib->vba.SurfaceTiling[k] + == dm_sw_4kb_s_x + || mode_lib->vba.SurfaceTiling[k] + == dm_sw_64kb_s + || mode_lib->vba.SurfaceTiling[k] + == dm_sw_64kb_s_t + || mode_lib->vba.SurfaceTiling[k] + == dm_sw_64kb_s_x + || mode_lib->vba.SurfaceTiling[k] + == dm_sw_var_s + || mode_lib->vba.SurfaceTiling[k] + == dm_sw_var_s_x) + && mode_lib->vba.SourceScan[k] == dm_horz)) { MinimumSwathHeightY = MaximumSwathHeightY; - } else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_8 && mode_lib->vba.SourceScan[k] != dm_horz) { + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_8 + && mode_lib->vba.SourceScan[k] != dm_horz) { MinimumSwathHeightY = MaximumSwathHeightY; } else { MinimumSwathHeightY = MaximumSwathHeightY / 2.0; @@ -2854,10 +3355,12 @@ static void DisplayPipeConfiguration(struct display_mode_lib *mode_lib) if (mode_lib->vba.SurfaceTiling[k] == dm_sw_linear) { MinimumSwathHeightY = MaximumSwathHeightY; MinimumSwathHeightC = MaximumSwathHeightC; - } else if (mode_lib->vba.SourcePixelFormat[k] == dm_420_8 && mode_lib->vba.SourceScan[k] == dm_horz) { + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_420_8 + && mode_lib->vba.SourceScan[k] == dm_horz) { MinimumSwathHeightY = MaximumSwathHeightY / 2.0; MinimumSwathHeightC = MaximumSwathHeightC; - } else if (mode_lib->vba.SourcePixelFormat[k] == dm_420_10 && mode_lib->vba.SourceScan[k] == dm_horz) { + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_420_10 + && mode_lib->vba.SourceScan[k] == dm_horz) { MinimumSwathHeightC = MaximumSwathHeightC / 2.0; MinimumSwathHeightY = MaximumSwathHeightY; } else { @@ -2876,40 +3379,46 @@ static void DisplayPipeConfiguration(struct display_mode_lib *mode_lib) MainPlaneDoesODMCombine = true; } for (j = 0; j < mode_lib->vba.NumberOfActivePlanes; ++j) { - if (mode_lib->vba.BlendingAndTiming[k] == j && mode_lib->vba.ODMCombineEnabled[j] == true) { + if (mode_lib->vba.BlendingAndTiming[k] == j + && mode_lib->vba.ODMCombineEnabled[j] == true) { MainPlaneDoesODMCombine = true; } } if (MainPlaneDoesODMCombine == true) { - SwathWidth = dml_min(SwathWidth, mode_lib->vba.HActive[k] / 2.0 * mode_lib->vba.HRatio[k]); + SwathWidth = dml_min( + SwathWidth, + mode_lib->vba.HActive[k] / 2.0 * mode_lib->vba.HRatio[k]); } else { SwathWidth = SwathWidth / mode_lib->vba.DPPPerPlane[k]; } SwathWidthGranularityY = 256 / dml_ceil(BytePerPixDETY, 1) / MaximumSwathHeightY; - RoundedUpMaxSwathSizeBytesY = (dml_ceil((double)(SwathWidth - 1), - SwathWidthGranularityY) + SwathWidthGranularityY) * BytePerPixDETY - * MaximumSwathHeightY; + RoundedUpMaxSwathSizeBytesY = (dml_ceil( + (double) (SwathWidth - 1), + SwathWidthGranularityY) + SwathWidthGranularityY) * BytePerPixDETY + * MaximumSwathHeightY; if (mode_lib->vba.SourcePixelFormat[k] == dm_420_10) { RoundedUpMaxSwathSizeBytesY = dml_ceil(RoundedUpMaxSwathSizeBytesY, 256) - + 256; + + 256; } if (MaximumSwathHeightC > 0) { SwathWidthGranularityC = 256.0 / dml_ceil(BytePerPixDETC, 2) - / MaximumSwathHeightC; - RoundedUpMaxSwathSizeBytesC = (dml_ceil((double)(SwathWidth / 2.0 - 1), - SwathWidthGranularityC) + SwathWidthGranularityC) - * BytePerPixDETC * MaximumSwathHeightC; + / MaximumSwathHeightC; + RoundedUpMaxSwathSizeBytesC = (dml_ceil( + (double) (SwathWidth / 2.0 - 1), + SwathWidthGranularityC) + SwathWidthGranularityC) + * BytePerPixDETC * MaximumSwathHeightC; if (mode_lib->vba.SourcePixelFormat[k] == dm_420_10) { - RoundedUpMaxSwathSizeBytesC = dml_ceil(RoundedUpMaxSwathSizeBytesC, - 256) + 256; + RoundedUpMaxSwathSizeBytesC = dml_ceil( + RoundedUpMaxSwathSizeBytesC, + 256) + 256; } } else RoundedUpMaxSwathSizeBytesC = 0.0; if (RoundedUpMaxSwathSizeBytesY + RoundedUpMaxSwathSizeBytesC - <= mode_lib->vba.DETBufferSizeInKByte * 1024.0 / 2.0) { + <= mode_lib->vba.DETBufferSizeInKByte * 1024.0 / 2.0) { mode_lib->vba.SwathHeightY[k] = MaximumSwathHeightY; mode_lib->vba.SwathHeightC[k] = MaximumSwathHeightC; } else { @@ -2921,27 +3430,32 @@ static void DisplayPipeConfiguration(struct display_mode_lib *mode_lib) mode_lib->vba.DETBufferSizeY[k] = mode_lib->vba.DETBufferSizeInKByte * 1024; mode_lib->vba.DETBufferSizeC[k] = 0; } else if (mode_lib->vba.SwathHeightY[k] <= mode_lib->vba.SwathHeightC[k]) { - mode_lib->vba.DETBufferSizeY[k] = mode_lib->vba.DETBufferSizeInKByte * 1024.0 / 2; - mode_lib->vba.DETBufferSizeC[k] = mode_lib->vba.DETBufferSizeInKByte * 1024.0 / 2; + mode_lib->vba.DETBufferSizeY[k] = mode_lib->vba.DETBufferSizeInKByte + * 1024.0 / 2; + mode_lib->vba.DETBufferSizeC[k] = mode_lib->vba.DETBufferSizeInKByte + * 1024.0 / 2; } else { - mode_lib->vba.DETBufferSizeY[k] = mode_lib->vba.DETBufferSizeInKByte * 1024.0 * 2 / 3; - mode_lib->vba.DETBufferSizeC[k] = mode_lib->vba.DETBufferSizeInKByte * 1024.0 / 3; + mode_lib->vba.DETBufferSizeY[k] = mode_lib->vba.DETBufferSizeInKByte + * 1024.0 * 2 / 3; + mode_lib->vba.DETBufferSizeC[k] = mode_lib->vba.DETBufferSizeInKByte + * 1024.0 / 3; } } } -bool Calculate256BBlockSizes(enum source_format_class SourcePixelFormat, - enum dm_swizzle_mode SurfaceTiling, - unsigned int BytePerPixelY, - unsigned int BytePerPixelC, - unsigned int *BlockHeight256BytesY, - unsigned int *BlockHeight256BytesC, - unsigned int *BlockWidth256BytesY, - unsigned int *BlockWidth256BytesC) +bool Calculate256BBlockSizes( + enum source_format_class SourcePixelFormat, + enum dm_swizzle_mode SurfaceTiling, + unsigned int BytePerPixelY, + unsigned int BytePerPixelC, + unsigned int *BlockHeight256BytesY, + unsigned int *BlockHeight256BytesC, + unsigned int *BlockWidth256BytesY, + unsigned int *BlockWidth256BytesC) { if ((SourcePixelFormat == dm_444_64 || SourcePixelFormat == dm_444_32 - || SourcePixelFormat == dm_444_16 || SourcePixelFormat == dm_444_16 - || SourcePixelFormat == dm_444_8)) { + || SourcePixelFormat == dm_444_16 || SourcePixelFormat == dm_444_16 + || SourcePixelFormat == dm_444_8)) { if (SurfaceTiling == dm_sw_linear) { *BlockHeight256BytesY = 1; } else if (SourcePixelFormat == dm_444_64) { @@ -2971,14 +3485,16 @@ bool Calculate256BBlockSizes(enum source_format_class SourcePixelFormat, return true; } -static double CalculateTWait(unsigned int PrefetchMode, - double DRAMClockChangeLatency, - double UrgentLatency, - double SREnterPlusExitTime) +static double CalculateTWait( + unsigned int PrefetchMode, + double DRAMClockChangeLatency, + double UrgentLatency, + double SREnterPlusExitTime) { if (PrefetchMode == 0) { - return dml_max(DRAMClockChangeLatency + UrgentLatency, - dml_max(SREnterPlusExitTime, UrgentLatency)); + return dml_max( + DRAMClockChangeLatency + UrgentLatency, + dml_max(SREnterPlusExitTime, UrgentLatency)); } else if (PrefetchMode == 1) { return dml_max(SREnterPlusExitTime, UrgentLatency); } else { @@ -2986,23 +3502,24 @@ static double CalculateTWait(unsigned int PrefetchMode, } } -static double CalculateRemoteSurfaceFlipDelay(struct display_mode_lib *mode_lib, - double VRatio, - double SwathWidth, - double Bpp, - double LineTime, - double XFCTSlvVupdateOffset, - double XFCTSlvVupdateWidth, - double XFCTSlvVreadyOffset, - double XFCXBUFLatencyTolerance, - double XFCFillBWOverhead, - double XFCSlvChunkSize, - double XFCBusTransportTime, - double TCalc, - double TWait, - double *SrcActiveDrainRate, - double *TInitXFill, - double *TslvChk) +static double CalculateRemoteSurfaceFlipDelay( + struct display_mode_lib *mode_lib, + double VRatio, + double SwathWidth, + double Bpp, + double LineTime, + double XFCTSlvVupdateOffset, + double XFCTSlvVupdateWidth, + double XFCTSlvVreadyOffset, + double XFCXBUFLatencyTolerance, + double XFCFillBWOverhead, + double XFCSlvChunkSize, + double XFCBusTransportTime, + double TCalc, + double TWait, + double *SrcActiveDrainRate, + double *TInitXFill, + double *TslvChk) { double TSlvSetup, AvgfillRate, result; @@ -3011,8 +3528,9 @@ static double CalculateRemoteSurfaceFlipDelay(struct display_mode_lib *mode_lib, *TInitXFill = XFCXBUFLatencyTolerance / (1 + XFCFillBWOverhead / 100); AvgfillRate = *SrcActiveDrainRate * (1 + XFCFillBWOverhead / 100); *TslvChk = XFCSlvChunkSize / AvgfillRate; - dml_print("DML::CalculateRemoteSurfaceFlipDelay: SrcActiveDrainRate: %f\n", - *SrcActiveDrainRate); + dml_print( + "DML::CalculateRemoteSurfaceFlipDelay: SrcActiveDrainRate: %f\n", + *SrcActiveDrainRate); dml_print("DML::CalculateRemoteSurfaceFlipDelay: TSlvSetup: %f\n", TSlvSetup); dml_print("DML::CalculateRemoteSurfaceFlipDelay: TInitXFill: %f\n", *TInitXFill); dml_print("DML::CalculateRemoteSurfaceFlipDelay: AvgfillRate: %f\n", AvgfillRate); @@ -3022,99 +3540,192 @@ static double CalculateRemoteSurfaceFlipDelay(struct display_mode_lib *mode_lib, return result; } -static double CalculateWriteBackDISPCLK(enum source_format_class WritebackPixelFormat, - double PixelClock, - double WritebackHRatio, - double WritebackVRatio, - unsigned int WritebackLumaHTaps, - unsigned int WritebackLumaVTaps, - unsigned int WritebackChromaHTaps, - unsigned int WritebackChromaVTaps, - double WritebackDestinationWidth, - unsigned int HTotal, - unsigned int WritebackChromaLineBufferWidth) +static double CalculateWriteBackDISPCLK( + enum source_format_class WritebackPixelFormat, + double PixelClock, + double WritebackHRatio, + double WritebackVRatio, + unsigned int WritebackLumaHTaps, + unsigned int WritebackLumaVTaps, + unsigned int WritebackChromaHTaps, + unsigned int WritebackChromaVTaps, + double WritebackDestinationWidth, + unsigned int HTotal, + unsigned int WritebackChromaLineBufferWidth) { - double CalculateWriteBackDISPCLK = 1.01 * PixelClock - * dml_max( - dml_ceil(WritebackLumaHTaps / 4.0, 1) / WritebackHRatio, - dml_max( - (WritebackLumaVTaps * dml_ceil(1.0 / WritebackVRatio, 1) - * dml_ceil(WritebackDestinationWidth / 4.0, 1) - + dml_ceil(WritebackDestinationWidth / 4.0, 1)) / (double)HTotal - + dml_ceil(1.0 / WritebackVRatio, 1) * (dml_ceil(WritebackLumaVTaps / 4.0, 1) + 4.0) - / (double)HTotal, - dml_ceil(1.0 / WritebackVRatio, 1) * WritebackDestinationWidth / (double)HTotal)); - if (WritebackPixelFormat != dm_444_32) { - CalculateWriteBackDISPCLK = dml_max( - CalculateWriteBackDISPCLK, + double CalculateWriteBackDISPCLK = 1.01 * PixelClock - * dml_max( - dml_ceil(WritebackChromaHTaps / 2.0, 1) / (2 * WritebackHRatio), + * dml_max( + dml_ceil(WritebackLumaHTaps / 4.0, 1) + / WritebackHRatio, + dml_max( + (WritebackLumaVTaps + * dml_ceil( + 1.0 + / WritebackVRatio, + 1) + * dml_ceil( + WritebackDestinationWidth + / 4.0, + 1) + + dml_ceil( + WritebackDestinationWidth + / 4.0, + 1)) + / (double) HTotal + + dml_ceil( + 1.0 + / WritebackVRatio, + 1) + * (dml_ceil( + WritebackLumaVTaps + / 4.0, + 1) + + 4.0) + / (double) HTotal, + dml_ceil( + 1.0 + / WritebackVRatio, + 1) + * WritebackDestinationWidth + / (double) HTotal)); + if (WritebackPixelFormat != dm_444_32) { + CalculateWriteBackDISPCLK = dml_max( - (WritebackChromaVTaps * dml_ceil(1 / (2 * WritebackVRatio), 1) - * dml_ceil(WritebackDestinationWidth / 2.0 / 2.0, 1) - + dml_ceil(WritebackDestinationWidth / 2.0 / WritebackChromaLineBufferWidth, 1)) - / HTotal - + dml_ceil(1 / (2 * WritebackVRatio), 1) - * (dml_ceil(WritebackChromaVTaps / 4.0, 1) + 4) / HTotal, - dml_ceil(1.0 / (2 * WritebackVRatio), 1) * WritebackDestinationWidth / 2.0 - / HTotal))); + CalculateWriteBackDISPCLK, + 1.01 * PixelClock + * dml_max( + dml_ceil( + WritebackChromaHTaps + / 2.0, + 1) + / (2 + * WritebackHRatio), + dml_max( + (WritebackChromaVTaps + * dml_ceil( + 1 + / (2 + * WritebackVRatio), + 1) + * dml_ceil( + WritebackDestinationWidth + / 2.0 + / 2.0, + 1) + + dml_ceil( + WritebackDestinationWidth + / 2.0 + / WritebackChromaLineBufferWidth, + 1)) + / HTotal + + dml_ceil( + 1 + / (2 + * WritebackVRatio), + 1) + * (dml_ceil( + WritebackChromaVTaps + / 4.0, + 1) + + 4) + / HTotal, + dml_ceil( + 1.0 + / (2 + * WritebackVRatio), + 1) + * WritebackDestinationWidth + / 2.0 + / HTotal))); } return CalculateWriteBackDISPCLK; } static double CalculateWriteBackDelay( -enum source_format_class WritebackPixelFormat, - double WritebackHRatio, - double WritebackVRatio, - unsigned int WritebackLumaHTaps, - unsigned int WritebackLumaVTaps, - unsigned int WritebackChromaHTaps, - unsigned int WritebackChromaVTaps, - unsigned int WritebackDestinationWidth) + enum source_format_class WritebackPixelFormat, + double WritebackHRatio, + double WritebackVRatio, + unsigned int WritebackLumaHTaps, + unsigned int WritebackLumaVTaps, + unsigned int WritebackChromaHTaps, + unsigned int WritebackChromaVTaps, + unsigned int WritebackDestinationWidth) { - double CalculateWriteBackDelay = dml_max( - dml_ceil(WritebackLumaHTaps / 4.0, 1) / WritebackHRatio, - WritebackLumaVTaps * dml_ceil(1.0 / WritebackVRatio, 1) - * dml_ceil(WritebackDestinationWidth / 4.0, 1) - + dml_ceil(1.0 / WritebackVRatio, 1) * (dml_ceil(WritebackLumaVTaps / 4.0, 1) + 4)); + double CalculateWriteBackDelay = + dml_max( + dml_ceil(WritebackLumaHTaps / 4.0, 1) / WritebackHRatio, + WritebackLumaVTaps * dml_ceil(1.0 / WritebackVRatio, 1) + * dml_ceil( + WritebackDestinationWidth + / 4.0, + 1) + + dml_ceil(1.0 / WritebackVRatio, 1) + * (dml_ceil( + WritebackLumaVTaps + / 4.0, + 1) + 4)); if (WritebackPixelFormat != dm_444_32) { - CalculateWriteBackDelay = dml_max( - CalculateWriteBackDelay, - dml_max( - dml_ceil(WritebackChromaHTaps / 2.0, 1) / (2 * WritebackHRatio), - WritebackChromaVTaps * dml_ceil(1 / (2 * WritebackVRatio), 1) - * dml_ceil(WritebackDestinationWidth / 2.0 / 2.0, 1) - + dml_ceil(1 / (2 * WritebackVRatio), 1) - * (dml_ceil(WritebackChromaVTaps / 4.0, 1) + 4))); + CalculateWriteBackDelay = + dml_max( + CalculateWriteBackDelay, + dml_max( + dml_ceil( + WritebackChromaHTaps + / 2.0, + 1) + / (2 + * WritebackHRatio), + WritebackChromaVTaps + * dml_ceil( + 1 + / (2 + * WritebackVRatio), + 1) + * dml_ceil( + WritebackDestinationWidth + / 2.0 + / 2.0, + 1) + + dml_ceil( + 1 + / (2 + * WritebackVRatio), + 1) + * (dml_ceil( + WritebackChromaVTaps + / 4.0, + 1) + + 4))); } return CalculateWriteBackDelay; } -static void CalculateActiveRowBandwidth(bool VirtualMemoryEnable, - enum source_format_class SourcePixelFormat, - double VRatio, - bool DCCEnable, - double LineTime, - unsigned int MetaRowByteLuma, - unsigned int MetaRowByteChroma, - unsigned int meta_row_height_luma, - unsigned int meta_row_height_chroma, - unsigned int PixelPTEBytesPerRowLuma, - unsigned int PixelPTEBytesPerRowChroma, - unsigned int dpte_row_height_luma, - unsigned int dpte_row_height_chroma, - double *meta_row_bw, - double *dpte_row_bw, - double *qual_row_bw) +static void CalculateActiveRowBandwidth( + bool VirtualMemoryEnable, + enum source_format_class SourcePixelFormat, + double VRatio, + bool DCCEnable, + double LineTime, + unsigned int MetaRowByteLuma, + unsigned int MetaRowByteChroma, + unsigned int meta_row_height_luma, + unsigned int meta_row_height_chroma, + unsigned int PixelPTEBytesPerRowLuma, + unsigned int PixelPTEBytesPerRowChroma, + unsigned int dpte_row_height_luma, + unsigned int dpte_row_height_chroma, + double *meta_row_bw, + double *dpte_row_bw, + double *qual_row_bw) { if (DCCEnable != true) { *meta_row_bw = 0; } else if (SourcePixelFormat == dm_420_8 || SourcePixelFormat == dm_420_10) { *meta_row_bw = VRatio * MetaRowByteLuma / (meta_row_height_luma * LineTime) - + VRatio / 2 * MetaRowByteChroma - / (meta_row_height_chroma * LineTime); + + VRatio / 2 * MetaRowByteChroma + / (meta_row_height_chroma * LineTime); } else { *meta_row_bw = VRatio * MetaRowByteLuma / (meta_row_height_luma * LineTime); } @@ -3123,8 +3734,8 @@ static void CalculateActiveRowBandwidth(bool VirtualMemoryEnable, *dpte_row_bw = 0; } else if (SourcePixelFormat == dm_420_8 || SourcePixelFormat == dm_420_10) { *dpte_row_bw = VRatio * PixelPTEBytesPerRowLuma / (dpte_row_height_luma * LineTime) - + VRatio / 2 * PixelPTEBytesPerRowChroma - / (dpte_row_height_chroma * LineTime); + + VRatio / 2 * PixelPTEBytesPerRowChroma + / (dpte_row_height_chroma * LineTime); } else { *dpte_row_bw = VRatio * PixelPTEBytesPerRowLuma / (dpte_row_height_luma * LineTime); } @@ -3136,29 +3747,30 @@ static void CalculateActiveRowBandwidth(bool VirtualMemoryEnable, } } -static void CalculateFlipSchedule(struct display_mode_lib *mode_lib, - double UrgentExtraLatency, - double UrgentLatency, - unsigned int MaxPageTableLevels, - bool VirtualMemoryEnable, - double BandwidthAvailableForImmediateFlip, - unsigned int TotImmediateFlipBytes, - enum source_format_class SourcePixelFormat, - unsigned int ImmediateFlipBytes, - double LineTime, - double Tno_bw, - double VRatio, - double PDEAndMetaPTEBytesFrame, - unsigned int MetaRowByte, - unsigned int PixelPTEBytesPerRow, - bool DCCEnable, - unsigned int dpte_row_height, - unsigned int meta_row_height, - double qual_row_bw, - double *DestinationLinesToRequestVMInImmediateFlip, - double *DestinationLinesToRequestRowInImmediateFlip, - double *final_flip_bw, - bool *ImmediateFlipSupportedForPipe) +static void CalculateFlipSchedule( + struct display_mode_lib *mode_lib, + double UrgentExtraLatency, + double UrgentLatency, + unsigned int MaxPageTableLevels, + bool VirtualMemoryEnable, + double BandwidthAvailableForImmediateFlip, + unsigned int TotImmediateFlipBytes, + enum source_format_class SourcePixelFormat, + unsigned int ImmediateFlipBytes, + double LineTime, + double Tno_bw, + double VRatio, + double PDEAndMetaPTEBytesFrame, + unsigned int MetaRowByte, + unsigned int PixelPTEBytesPerRow, + bool DCCEnable, + unsigned int dpte_row_height, + unsigned int meta_row_height, + double qual_row_bw, + double *DestinationLinesToRequestVMInImmediateFlip, + double *DestinationLinesToRequestRowInImmediateFlip, + double *final_flip_bw, + bool *ImmediateFlipSupportedForPipe) { double min_row_time = 0.0; @@ -3172,47 +3784,54 @@ static void CalculateFlipSchedule(struct display_mode_lib *mode_lib, double TimeForFetchingRowInVBlankImmediateFlip; if (VirtualMemoryEnable == true) { - mode_lib->vba.ImmediateFlipBW = BandwidthAvailableForImmediateFlip * ImmediateFlipBytes - / TotImmediateFlipBytes; + mode_lib->vba.ImmediateFlipBW = BandwidthAvailableForImmediateFlip + * ImmediateFlipBytes / TotImmediateFlipBytes; TimeForFetchingMetaPTEImmediateFlip = - dml_max(Tno_bw - + PDEAndMetaPTEBytesFrame - / mode_lib->vba.ImmediateFlipBW, - dml_max(UrgentExtraLatency - + UrgentLatency - * (MaxPageTableLevels - - 1), - LineTime / 4.0)); + dml_max( + Tno_bw + + PDEAndMetaPTEBytesFrame + / mode_lib->vba.ImmediateFlipBW, + dml_max( + UrgentExtraLatency + + UrgentLatency + * (MaxPageTableLevels + - 1), + LineTime / 4.0)); } else { TimeForFetchingMetaPTEImmediateFlip = 0; } - *DestinationLinesToRequestVMInImmediateFlip = dml_floor(4.0 * (TimeForFetchingMetaPTEImmediateFlip / LineTime + 0.125), - 1) / 4.0; + *DestinationLinesToRequestVMInImmediateFlip = dml_floor( + 4.0 * (TimeForFetchingMetaPTEImmediateFlip / LineTime + 0.125), + 1) / 4.0; if ((VirtualMemoryEnable == true || DCCEnable == true)) { - mode_lib->vba.ImmediateFlipBW = BandwidthAvailableForImmediateFlip * ImmediateFlipBytes - / TotImmediateFlipBytes; - TimeForFetchingRowInVBlankImmediateFlip = dml_max((MetaRowByte + PixelPTEBytesPerRow) / mode_lib->vba.ImmediateFlipBW, - dml_max(UrgentLatency, LineTime / 4.0)); + mode_lib->vba.ImmediateFlipBW = BandwidthAvailableForImmediateFlip + * ImmediateFlipBytes / TotImmediateFlipBytes; + TimeForFetchingRowInVBlankImmediateFlip = dml_max( + (MetaRowByte + PixelPTEBytesPerRow) + / mode_lib->vba.ImmediateFlipBW, + dml_max(UrgentLatency, LineTime / 4.0)); } else { TimeForFetchingRowInVBlankImmediateFlip = 0; } - *DestinationLinesToRequestRowInImmediateFlip = dml_floor(4.0 * (TimeForFetchingRowInVBlankImmediateFlip / LineTime + 0.125), - 1) / 4.0; + *DestinationLinesToRequestRowInImmediateFlip = dml_floor( + 4.0 * (TimeForFetchingRowInVBlankImmediateFlip / LineTime + 0.125), + 1) / 4.0; if (VirtualMemoryEnable == true) { *final_flip_bw = - dml_max(PDEAndMetaPTEBytesFrame - / (*DestinationLinesToRequestVMInImmediateFlip - * LineTime), - (MetaRowByte + PixelPTEBytesPerRow) - / (TimeForFetchingRowInVBlankImmediateFlip - * LineTime)); + dml_max( + PDEAndMetaPTEBytesFrame + / (*DestinationLinesToRequestVMInImmediateFlip + * LineTime), + (MetaRowByte + PixelPTEBytesPerRow) + / (TimeForFetchingRowInVBlankImmediateFlip + * LineTime)); } else if (MetaRowByte + PixelPTEBytesPerRow > 0) { *final_flip_bw = (MetaRowByte + PixelPTEBytesPerRow) - / (TimeForFetchingRowInVBlankImmediateFlip * LineTime); + / (TimeForFetchingRowInVBlankImmediateFlip * LineTime); } else { *final_flip_bw = 0; } @@ -3223,12 +3842,13 @@ static void CalculateFlipSchedule(struct display_mode_lib *mode_lib, min_row_time = meta_row_height * LineTime / VRatio; else min_row_time = dml_min(dpte_row_height, meta_row_height) * LineTime - / VRatio; + / VRatio; if (*DestinationLinesToRequestVMInImmediateFlip >= 8 || *DestinationLinesToRequestRowInImmediateFlip >= 16 || TimeForFetchingMetaPTEImmediateFlip - + 2 * TimeForFetchingRowInVBlankImmediateFlip > min_row_time) + + 2 * TimeForFetchingRowInVBlankImmediateFlip + > min_row_time) *ImmediateFlipSupportedForPipe = false; else *ImmediateFlipSupportedForPipe = true; @@ -3242,7 +3862,8 @@ static void PixelClockAdjustmentForProgressiveToInterlaceUnit(struct display_mod //Progressive To dml_ml->vba.Interlace Unit Effect for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { mode_lib->vba.PixelClockBackEnd[k] = mode_lib->vba.PixelClock[k]; - if (mode_lib->vba.Interlace[k] == 1 && mode_lib->vba.ProgressiveToInterlaceUnitInOPP == true) { + if (mode_lib->vba.Interlace[k] == 1 + && mode_lib->vba.ProgressiveToInterlaceUnitInOPP == true) { mode_lib->vba.PixelClock[k] = 2 * mode_lib->vba.PixelClock[k]; } } @@ -3261,3 +3882,2211 @@ static unsigned int CursorBppEnumToBits(enum cursor_bpp ebpp) return 0; } } + +static unsigned int TruncToValidBPP( + double DecimalBPP, + bool DSCEnabled, + enum output_encoder_class Output, + enum output_format_class Format, + unsigned int DSCInputBitPerComponent) +{ + if (Output == dm_hdmi) { + if (Format == dm_420) { + if (DecimalBPP >= 18) + return 18; + else if (DecimalBPP >= 15) + return 15; + else if (DecimalBPP >= 12) + return 12; + else + return 0; + } else if (Format == dm_444) { + if (DecimalBPP >= 36) + return 36; + else if (DecimalBPP >= 30) + return 30; + else if (DecimalBPP >= 24) + return 24; + else + return 0; + } else { + if (DecimalBPP / 1.5 >= 24) + return 24; + else if (DecimalBPP / 1.5 >= 20) + return 20; + else if (DecimalBPP / 1.5 >= 16) + return 16; + else + return 0; + } + } else { + if (DSCEnabled) { + if (Format == dm_420) { + if (DecimalBPP < 6) + return 0; + else if (DecimalBPP >= 1.5 * DSCInputBitPerComponent - 1 / 16) + return 1.5 * DSCInputBitPerComponent - 1 / 16; + else + return dml_floor(16 * DecimalBPP, 1) / 16; + } else if (Format == dm_n422) { + if (DecimalBPP < 7) + return 0; + else if (DecimalBPP >= 2 * DSCInputBitPerComponent - 1 / 16) + return 2 * DSCInputBitPerComponent - 1 / 16; + else + return dml_floor(16 * DecimalBPP, 1) / 16; + } else { + if (DecimalBPP < 8) + return 0; + else if (DecimalBPP >= 3 * DSCInputBitPerComponent - 1 / 16) + return 3 * DSCInputBitPerComponent - 1 / 16; + else + return dml_floor(16 * DecimalBPP, 1) / 16; + } + } else if (Format == dm_420) { + if (DecimalBPP >= 18) + return 18; + else if (DecimalBPP >= 15) + return 15; + else if (DecimalBPP >= 12) + return 12; + else + return 0; + } else if (Format == dm_s422 || Format == dm_n422) { + if (DecimalBPP >= 24) + return 24; + else if (DecimalBPP >= 20) + return 20; + else if (DecimalBPP >= 16) + return 16; + else + return 0; + } else { + if (DecimalBPP >= 36) + return 36; + else if (DecimalBPP >= 30) + return 30; + else if (DecimalBPP >= 24) + return 24; + else + return 0; + } + } +} + +static void ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_lib) +{ + int i; + unsigned int j, k; + /*MODE SUPPORT, VOLTAGE STATE AND SOC CONFIGURATION*/ + + /*Scale Ratio, taps Support Check*/ + + mode_lib->vba.ScaleRatioAndTapsSupport = true; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.ScalerEnabled[k] == false + && ((mode_lib->vba.SourcePixelFormat[k] != dm_444_64 + && mode_lib->vba.SourcePixelFormat[k] != dm_444_32 + && mode_lib->vba.SourcePixelFormat[k] != dm_444_16 + && mode_lib->vba.SourcePixelFormat[k] != dm_mono_16 + && mode_lib->vba.SourcePixelFormat[k] != dm_mono_8) + || mode_lib->vba.HRatio[k] != 1.0 + || mode_lib->vba.htaps[k] != 1.0 + || mode_lib->vba.VRatio[k] != 1.0 + || mode_lib->vba.vtaps[k] != 1.0)) { + mode_lib->vba.ScaleRatioAndTapsSupport = false; + } else if (mode_lib->vba.vtaps[k] < 1.0 || mode_lib->vba.vtaps[k] > 8.0 + || mode_lib->vba.htaps[k] < 1.0 || mode_lib->vba.htaps[k] > 8.0 + || (mode_lib->vba.htaps[k] > 1.0 + && (mode_lib->vba.htaps[k] % 2) == 1) + || mode_lib->vba.HRatio[k] > mode_lib->vba.MaxHSCLRatio + || mode_lib->vba.VRatio[k] > mode_lib->vba.MaxVSCLRatio + || mode_lib->vba.HRatio[k] > mode_lib->vba.htaps[k] + || mode_lib->vba.VRatio[k] > mode_lib->vba.vtaps[k] + || (mode_lib->vba.SourcePixelFormat[k] != dm_444_64 + && mode_lib->vba.SourcePixelFormat[k] != dm_444_32 + && mode_lib->vba.SourcePixelFormat[k] != dm_444_16 + && mode_lib->vba.SourcePixelFormat[k] != dm_mono_16 + && mode_lib->vba.SourcePixelFormat[k] != dm_mono_8 + && (mode_lib->vba.HRatio[k] / 2.0 + > mode_lib->vba.HTAPsChroma[k] + || mode_lib->vba.VRatio[k] / 2.0 + > mode_lib->vba.VTAPsChroma[k]))) { + mode_lib->vba.ScaleRatioAndTapsSupport = false; + } + } + /*Source Format, Pixel Format and Scan Support Check*/ + + mode_lib->vba.SourceFormatPixelAndScanSupport = true; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if ((mode_lib->vba.SurfaceTiling[k] == dm_sw_linear + && mode_lib->vba.SourceScan[k] != dm_horz) + || ((mode_lib->vba.SurfaceTiling[k] == dm_sw_4kb_d + || mode_lib->vba.SurfaceTiling[k] == dm_sw_4kb_d_x + || mode_lib->vba.SurfaceTiling[k] == dm_sw_64kb_d + || mode_lib->vba.SurfaceTiling[k] == dm_sw_64kb_d_t + || mode_lib->vba.SurfaceTiling[k] == dm_sw_64kb_d_x + || mode_lib->vba.SurfaceTiling[k] == dm_sw_var_d + || mode_lib->vba.SurfaceTiling[k] == dm_sw_var_d_x) + && mode_lib->vba.SourcePixelFormat[k] != dm_444_64) + || (mode_lib->vba.SurfaceTiling[k] == dm_sw_64kb_r_x + && (mode_lib->vba.SourcePixelFormat[k] == dm_mono_8 + || mode_lib->vba.SourcePixelFormat[k] + == dm_420_8 + || mode_lib->vba.SourcePixelFormat[k] + == dm_420_10)) + || (((mode_lib->vba.SurfaceTiling[k] + == dm_sw_gfx7_2d_thin_gl + || mode_lib->vba.SurfaceTiling[k] + == dm_sw_gfx7_2d_thin_lvp) + && !((mode_lib->vba.SourcePixelFormat[k] + == dm_444_64 + || mode_lib->vba.SourcePixelFormat[k] + == dm_444_32) + && mode_lib->vba.SourceScan[k] + == dm_horz + && mode_lib->vba.SupportGFX7CompatibleTilingIn32bppAnd64bpp + == true + && mode_lib->vba.DCCEnable[k] + == false)) + || (mode_lib->vba.DCCEnable[k] == true + && (mode_lib->vba.SurfaceTiling[k] + == dm_sw_linear + || mode_lib->vba.SourcePixelFormat[k] + == dm_420_8 + || mode_lib->vba.SourcePixelFormat[k] + == dm_420_10)))) { + mode_lib->vba.SourceFormatPixelAndScanSupport = false; + } + } + /*Bandwidth Support Check*/ + + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.SourceScan[k] == dm_horz) { + mode_lib->vba.SwathWidthYSingleDPP[k] = mode_lib->vba.ViewportWidth[k]; + } else { + mode_lib->vba.SwathWidthYSingleDPP[k] = mode_lib->vba.ViewportHeight[k]; + } + if (mode_lib->vba.SourcePixelFormat[k] == dm_444_64) { + mode_lib->vba.BytePerPixelInDETY[k] = 8.0; + mode_lib->vba.BytePerPixelInDETC[k] = 0.0; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_32) { + mode_lib->vba.BytePerPixelInDETY[k] = 4.0; + mode_lib->vba.BytePerPixelInDETC[k] = 0.0; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_16 + || mode_lib->vba.SourcePixelFormat[k] == dm_mono_16) { + mode_lib->vba.BytePerPixelInDETY[k] = 2.0; + mode_lib->vba.BytePerPixelInDETC[k] = 0.0; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_mono_8) { + mode_lib->vba.BytePerPixelInDETY[k] = 1.0; + mode_lib->vba.BytePerPixelInDETC[k] = 0.0; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_420_8) { + mode_lib->vba.BytePerPixelInDETY[k] = 1.0; + mode_lib->vba.BytePerPixelInDETC[k] = 2.0; + } else { + mode_lib->vba.BytePerPixelInDETY[k] = 4.0 / 3; + mode_lib->vba.BytePerPixelInDETC[k] = 8.0 / 3; + } + } + mode_lib->vba.TotalReadBandwidthConsumedGBytePerSecond = 0.0; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.ReadBandwidth[k] = mode_lib->vba.SwathWidthYSingleDPP[k] + * (dml_ceil(mode_lib->vba.BytePerPixelInDETY[k], 1.0) + * mode_lib->vba.VRatio[k] + + dml_ceil(mode_lib->vba.BytePerPixelInDETC[k], 2.0) + / 2.0 * mode_lib->vba.VRatio[k] / 2) + / (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]); + if (mode_lib->vba.DCCEnable[k] == true) { + mode_lib->vba.ReadBandwidth[k] = mode_lib->vba.ReadBandwidth[k] + * (1 + 1 / 256); + } + if (mode_lib->vba.VirtualMemoryEnable == true + && mode_lib->vba.SourceScan[k] != dm_horz + && (mode_lib->vba.SurfaceTiling[k] == dm_sw_4kb_s + || mode_lib->vba.SurfaceTiling[k] == dm_sw_4kb_s_x + || mode_lib->vba.SurfaceTiling[k] == dm_sw_4kb_d + || mode_lib->vba.SurfaceTiling[k] == dm_sw_4kb_d_x)) { + mode_lib->vba.ReadBandwidth[k] = mode_lib->vba.ReadBandwidth[k] + * (1 + 1 / 64); + } else if (mode_lib->vba.VirtualMemoryEnable == true + && mode_lib->vba.SourceScan[k] == dm_horz + && (mode_lib->vba.SourcePixelFormat[k] == dm_444_64 + || mode_lib->vba.SourcePixelFormat[k] == dm_444_32) + && (mode_lib->vba.SurfaceTiling[k] == dm_sw_64kb_s + || mode_lib->vba.SurfaceTiling[k] == dm_sw_64kb_s_t + || mode_lib->vba.SurfaceTiling[k] == dm_sw_64kb_s_x + || mode_lib->vba.SurfaceTiling[k] == dm_sw_64kb_d + || mode_lib->vba.SurfaceTiling[k] == dm_sw_64kb_d_t + || mode_lib->vba.SurfaceTiling[k] == dm_sw_64kb_d_x + || mode_lib->vba.SurfaceTiling[k] == dm_sw_64kb_r_x)) { + mode_lib->vba.ReadBandwidth[k] = mode_lib->vba.ReadBandwidth[k] + * (1 + 1 / 256); + } else if (mode_lib->vba.VirtualMemoryEnable == true) { + mode_lib->vba.ReadBandwidth[k] = mode_lib->vba.ReadBandwidth[k] + * (1 + 1 / 512); + } + mode_lib->vba.TotalReadBandwidthConsumedGBytePerSecond = + mode_lib->vba.TotalReadBandwidthConsumedGBytePerSecond + + mode_lib->vba.ReadBandwidth[k] / 1000.0; + } + mode_lib->vba.TotalWriteBandwidthConsumedGBytePerSecond = 0.0; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.WritebackEnable[k] == true + && mode_lib->vba.WritebackPixelFormat[k] == dm_444_32) { + mode_lib->vba.WriteBandwidth[k] = mode_lib->vba.WritebackDestinationWidth[k] + * mode_lib->vba.WritebackDestinationHeight[k] + / (mode_lib->vba.WritebackSourceHeight[k] + * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]) * 4.0; + } else if (mode_lib->vba.WritebackEnable[k] == true + && mode_lib->vba.WritebackPixelFormat[k] == dm_420_10) { + mode_lib->vba.WriteBandwidth[k] = mode_lib->vba.WritebackDestinationWidth[k] + * mode_lib->vba.WritebackDestinationHeight[k] + / (mode_lib->vba.WritebackSourceHeight[k] + * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]) * 3.0; + } else if (mode_lib->vba.WritebackEnable[k] == true) { + mode_lib->vba.WriteBandwidth[k] = mode_lib->vba.WritebackDestinationWidth[k] + * mode_lib->vba.WritebackDestinationHeight[k] + / (mode_lib->vba.WritebackSourceHeight[k] + * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]) * 1.5; + } else { + mode_lib->vba.WriteBandwidth[k] = 0.0; + } + mode_lib->vba.TotalWriteBandwidthConsumedGBytePerSecond = + mode_lib->vba.TotalWriteBandwidthConsumedGBytePerSecond + + mode_lib->vba.WriteBandwidth[k] / 1000.0; + } + mode_lib->vba.TotalBandwidthConsumedGBytePerSecond = + mode_lib->vba.TotalReadBandwidthConsumedGBytePerSecond + + mode_lib->vba.TotalWriteBandwidthConsumedGBytePerSecond; + mode_lib->vba.DCCEnabledInAnyPlane = false; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.DCCEnable[k] == true) { + mode_lib->vba.DCCEnabledInAnyPlane = true; + } + } + for (i = 0; i <= DC__VOLTAGE_STATES; i++) { + mode_lib->vba.FabricAndDRAMBandwidthPerState[i] = dml_min( + mode_lib->vba.DRAMSpeedPerState[i] * mode_lib->vba.NumberOfChannels + * mode_lib->vba.DRAMChannelWidth, + mode_lib->vba.FabricClockPerState[i] + * mode_lib->vba.FabricDatapathToDCNDataReturn) + / 1000; + mode_lib->vba.ReturnBWToDCNPerState = dml_min( + mode_lib->vba.ReturnBusWidth * mode_lib->vba.DCFCLKPerState[i], + mode_lib->vba.FabricAndDRAMBandwidthPerState[i] * 1000.0) + * mode_lib->vba.PercentOfIdealDRAMAndFabricBWReceivedAfterUrgLatency + / 100; + mode_lib->vba.ReturnBWPerState[i] = mode_lib->vba.ReturnBWToDCNPerState; + if (mode_lib->vba.DCCEnabledInAnyPlane == true + && mode_lib->vba.ReturnBWToDCNPerState + > mode_lib->vba.DCFCLKPerState[i] + * mode_lib->vba.ReturnBusWidth + / 4.0) { + mode_lib->vba.ReturnBWPerState[i] = + dml_min( + mode_lib->vba.ReturnBWPerState[i], + mode_lib->vba.ReturnBWToDCNPerState * 4.0 + * (1.0 + - mode_lib->vba.UrgentLatency + / ((mode_lib->vba.ROBBufferSizeInKByte + - mode_lib->vba.PixelChunkSizeInKByte) + * 1024.0 + / (mode_lib->vba.ReturnBWToDCNPerState + - mode_lib->vba.DCFCLKPerState[i] + * mode_lib->vba.ReturnBusWidth + / 4.0) + + mode_lib->vba.UrgentLatency))); + } + mode_lib->vba.CriticalPoint = + 2.0 * mode_lib->vba.ReturnBusWidth * mode_lib->vba.DCFCLKPerState[i] + * mode_lib->vba.UrgentLatency + / (mode_lib->vba.ReturnBWToDCNPerState + * mode_lib->vba.UrgentLatency + + (mode_lib->vba.ROBBufferSizeInKByte + - mode_lib->vba.PixelChunkSizeInKByte) + * 1024.0); + if (mode_lib->vba.DCCEnabledInAnyPlane == true && mode_lib->vba.CriticalPoint > 1.0 + && mode_lib->vba.CriticalPoint < 4.0) { + mode_lib->vba.ReturnBWPerState[i] = + dml_min( + mode_lib->vba.ReturnBWPerState[i], + dml_pow( + 4.0 + * mode_lib->vba.ReturnBWToDCNPerState + * (mode_lib->vba.ROBBufferSizeInKByte + - mode_lib->vba.PixelChunkSizeInKByte) + * 1024.0 + * mode_lib->vba.ReturnBusWidth + * mode_lib->vba.DCFCLKPerState[i] + * mode_lib->vba.UrgentLatency + / (mode_lib->vba.ReturnBWToDCNPerState + * mode_lib->vba.UrgentLatency + + (mode_lib->vba.ROBBufferSizeInKByte + - mode_lib->vba.PixelChunkSizeInKByte) + * 1024.0), + 2)); + } + mode_lib->vba.ReturnBWToDCNPerState = dml_min( + mode_lib->vba.ReturnBusWidth * mode_lib->vba.DCFCLKPerState[i], + mode_lib->vba.FabricAndDRAMBandwidthPerState[i] * 1000.0); + if (mode_lib->vba.DCCEnabledInAnyPlane == true + && mode_lib->vba.ReturnBWToDCNPerState + > mode_lib->vba.DCFCLKPerState[i] + * mode_lib->vba.ReturnBusWidth + / 4.0) { + mode_lib->vba.ReturnBWPerState[i] = + dml_min( + mode_lib->vba.ReturnBWPerState[i], + mode_lib->vba.ReturnBWToDCNPerState * 4.0 + * (1.0 + - mode_lib->vba.UrgentLatency + / ((mode_lib->vba.ROBBufferSizeInKByte + - mode_lib->vba.PixelChunkSizeInKByte) + * 1024.0 + / (mode_lib->vba.ReturnBWToDCNPerState + - mode_lib->vba.DCFCLKPerState[i] + * mode_lib->vba.ReturnBusWidth + / 4.0) + + mode_lib->vba.UrgentLatency))); + } + mode_lib->vba.CriticalPoint = + 2.0 * mode_lib->vba.ReturnBusWidth * mode_lib->vba.DCFCLKPerState[i] + * mode_lib->vba.UrgentLatency + / (mode_lib->vba.ReturnBWToDCNPerState + * mode_lib->vba.UrgentLatency + + (mode_lib->vba.ROBBufferSizeInKByte + - mode_lib->vba.PixelChunkSizeInKByte) + * 1024.0); + if (mode_lib->vba.DCCEnabledInAnyPlane == true && mode_lib->vba.CriticalPoint > 1.0 + && mode_lib->vba.CriticalPoint < 4.0) { + mode_lib->vba.ReturnBWPerState[i] = + dml_min( + mode_lib->vba.ReturnBWPerState[i], + dml_pow( + 4.0 + * mode_lib->vba.ReturnBWToDCNPerState + * (mode_lib->vba.ROBBufferSizeInKByte + - mode_lib->vba.PixelChunkSizeInKByte) + * 1024.0 + * mode_lib->vba.ReturnBusWidth + * mode_lib->vba.DCFCLKPerState[i] + * mode_lib->vba.UrgentLatency + / (mode_lib->vba.ReturnBWToDCNPerState + * mode_lib->vba.UrgentLatency + + (mode_lib->vba.ROBBufferSizeInKByte + - mode_lib->vba.PixelChunkSizeInKByte) + * 1024.0), + 2)); + } + } + for (i = 0; i <= DC__VOLTAGE_STATES; i++) { + if ((mode_lib->vba.TotalReadBandwidthConsumedGBytePerSecond * 1000.0 + <= mode_lib->vba.ReturnBWPerState[i]) + && (mode_lib->vba.TotalBandwidthConsumedGBytePerSecond * 1000.0 + <= mode_lib->vba.FabricAndDRAMBandwidthPerState[i] + * 1000.0 + * mode_lib->vba.PercentOfIdealDRAMAndFabricBWReceivedAfterUrgLatency + / 100.0)) { + mode_lib->vba.BandwidthSupport[i] = true; + } else { + mode_lib->vba.BandwidthSupport[i] = false; + } + } + /*Writeback Latency support check*/ + + mode_lib->vba.WritebackLatencySupport = true; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.WritebackEnable[k] == true) { + if (mode_lib->vba.WritebackPixelFormat[k] == dm_444_32) { + if (mode_lib->vba.WriteBandwidth[k] + > (mode_lib->vba.WritebackInterfaceLumaBufferSize + + mode_lib->vba.WritebackInterfaceChromaBufferSize) + / mode_lib->vba.WritebackLatency) { + mode_lib->vba.WritebackLatencySupport = false; + } + } else { + if (mode_lib->vba.WriteBandwidth[k] + > 1.5 + * dml_min( + mode_lib->vba.WritebackInterfaceLumaBufferSize, + 2.0 + * mode_lib->vba.WritebackInterfaceChromaBufferSize) + / mode_lib->vba.WritebackLatency) { + mode_lib->vba.WritebackLatencySupport = false; + } + } + } + } + /*Re-ordering Buffer Support Check*/ + + for (i = 0; i <= DC__VOLTAGE_STATES; i++) { + mode_lib->vba.UrgentRoundTripAndOutOfOrderLatencyPerState[i] = + (mode_lib->vba.RoundTripPingLatencyCycles + 32.0) + / mode_lib->vba.DCFCLKPerState[i] + + mode_lib->vba.UrgentOutOfOrderReturnPerChannel + * mode_lib->vba.NumberOfChannels + / mode_lib->vba.ReturnBWPerState[i]; + if ((mode_lib->vba.ROBBufferSizeInKByte - mode_lib->vba.PixelChunkSizeInKByte) + * 1024.0 / mode_lib->vba.ReturnBWPerState[i] + > mode_lib->vba.UrgentRoundTripAndOutOfOrderLatencyPerState[i]) { + mode_lib->vba.ROBSupport[i] = true; + } else { + mode_lib->vba.ROBSupport[i] = false; + } + } + /*Writeback Mode Support Check*/ + + mode_lib->vba.TotalNumberOfActiveWriteback = 0; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.WritebackEnable[k] == true) { + mode_lib->vba.TotalNumberOfActiveWriteback = + mode_lib->vba.TotalNumberOfActiveWriteback + 1; + } + } + mode_lib->vba.WritebackModeSupport = true; + if (mode_lib->vba.TotalNumberOfActiveWriteback > mode_lib->vba.MaxNumWriteback) { + mode_lib->vba.WritebackModeSupport = false; + } + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.WritebackEnable[k] == true + && mode_lib->vba.Writeback10bpc420Supported != true + && mode_lib->vba.WritebackPixelFormat[k] == dm_420_10) { + mode_lib->vba.WritebackModeSupport = false; + } + } + /*Writeback Scale Ratio and Taps Support Check*/ + + mode_lib->vba.WritebackScaleRatioAndTapsSupport = true; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.WritebackEnable[k] == true) { + if (mode_lib->vba.WritebackLumaAndChromaScalingSupported == false + && (mode_lib->vba.WritebackHRatio[k] != 1.0 + || mode_lib->vba.WritebackVRatio[k] != 1.0)) { + mode_lib->vba.WritebackScaleRatioAndTapsSupport = false; + } + if (mode_lib->vba.WritebackHRatio[k] > mode_lib->vba.WritebackMaxHSCLRatio + || mode_lib->vba.WritebackVRatio[k] + > mode_lib->vba.WritebackMaxVSCLRatio + || mode_lib->vba.WritebackHRatio[k] + < mode_lib->vba.WritebackMinHSCLRatio + || mode_lib->vba.WritebackVRatio[k] + < mode_lib->vba.WritebackMinVSCLRatio + || mode_lib->vba.WritebackLumaHTaps[k] + > mode_lib->vba.WritebackMaxHSCLTaps + || mode_lib->vba.WritebackLumaVTaps[k] + > mode_lib->vba.WritebackMaxVSCLTaps + || mode_lib->vba.WritebackHRatio[k] + > mode_lib->vba.WritebackLumaHTaps[k] + || mode_lib->vba.WritebackVRatio[k] + > mode_lib->vba.WritebackLumaVTaps[k] + || (mode_lib->vba.WritebackLumaHTaps[k] > 2.0 + && ((mode_lib->vba.WritebackLumaHTaps[k] % 2) + == 1)) + || (mode_lib->vba.WritebackPixelFormat[k] != dm_444_32 + && (mode_lib->vba.WritebackChromaHTaps[k] + > mode_lib->vba.WritebackMaxHSCLTaps + || mode_lib->vba.WritebackChromaVTaps[k] + > mode_lib->vba.WritebackMaxVSCLTaps + || 2.0 + * mode_lib->vba.WritebackHRatio[k] + > mode_lib->vba.WritebackChromaHTaps[k] + || 2.0 + * mode_lib->vba.WritebackVRatio[k] + > mode_lib->vba.WritebackChromaVTaps[k] + || (mode_lib->vba.WritebackChromaHTaps[k] > 2.0 + && ((mode_lib->vba.WritebackChromaHTaps[k] % 2) == 1))))) { + mode_lib->vba.WritebackScaleRatioAndTapsSupport = false; + } + if (mode_lib->vba.WritebackVRatio[k] < 1.0) { + mode_lib->vba.WritebackLumaVExtra = + dml_max(1.0 - 2.0 / dml_ceil(1.0 / mode_lib->vba.WritebackVRatio[k], 1.0), 0.0); + } else { + mode_lib->vba.WritebackLumaVExtra = -1; + } + if ((mode_lib->vba.WritebackPixelFormat[k] == dm_444_32 + && mode_lib->vba.WritebackLumaVTaps[k] + > (mode_lib->vba.WritebackLineBufferLumaBufferSize + + mode_lib->vba.WritebackLineBufferChromaBufferSize) + / 3.0 + / mode_lib->vba.WritebackDestinationWidth[k] + - mode_lib->vba.WritebackLumaVExtra) + || (mode_lib->vba.WritebackPixelFormat[k] == dm_420_8 + && mode_lib->vba.WritebackLumaVTaps[k] + > mode_lib->vba.WritebackLineBufferLumaBufferSize + / mode_lib->vba.WritebackDestinationWidth[k] + - mode_lib->vba.WritebackLumaVExtra) + || (mode_lib->vba.WritebackPixelFormat[k] == dm_420_10 + && mode_lib->vba.WritebackLumaVTaps[k] + > mode_lib->vba.WritebackLineBufferLumaBufferSize + * 8.0 / 10.0 + / mode_lib->vba.WritebackDestinationWidth[k] + - mode_lib->vba.WritebackLumaVExtra)) { + mode_lib->vba.WritebackScaleRatioAndTapsSupport = false; + } + if (2.0 * mode_lib->vba.WritebackVRatio[k] < 1) { + mode_lib->vba.WritebackChromaVExtra = 0.0; + } else { + mode_lib->vba.WritebackChromaVExtra = -1; + } + if ((mode_lib->vba.WritebackPixelFormat[k] == dm_420_8 + && mode_lib->vba.WritebackChromaVTaps[k] + > mode_lib->vba.WritebackLineBufferChromaBufferSize + / mode_lib->vba.WritebackDestinationWidth[k] + - mode_lib->vba.WritebackChromaVExtra) + || (mode_lib->vba.WritebackPixelFormat[k] == dm_420_10 + && mode_lib->vba.WritebackChromaVTaps[k] + > mode_lib->vba.WritebackLineBufferChromaBufferSize + * 8.0 / 10.0 + / mode_lib->vba.WritebackDestinationWidth[k] + - mode_lib->vba.WritebackChromaVExtra)) { + mode_lib->vba.WritebackScaleRatioAndTapsSupport = false; + } + } + } + /*Maximum DISPCLK/DPPCLK Support check*/ + + mode_lib->vba.WritebackRequiredDISPCLK = 0.0; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.WritebackEnable[k] == true) { + mode_lib->vba.WritebackRequiredDISPCLK = + dml_max( + mode_lib->vba.WritebackRequiredDISPCLK, + CalculateWriteBackDISPCLK( + mode_lib->vba.WritebackPixelFormat[k], + mode_lib->vba.PixelClock[k], + mode_lib->vba.WritebackHRatio[k], + mode_lib->vba.WritebackVRatio[k], + mode_lib->vba.WritebackLumaHTaps[k], + mode_lib->vba.WritebackLumaVTaps[k], + mode_lib->vba.WritebackChromaHTaps[k], + mode_lib->vba.WritebackChromaVTaps[k], + mode_lib->vba.WritebackDestinationWidth[k], + mode_lib->vba.HTotal[k], + mode_lib->vba.WritebackChromaLineBufferWidth)); + } + } + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.HRatio[k] > 1.0) { + mode_lib->vba.PSCL_FACTOR[k] = dml_min( + mode_lib->vba.MaxDCHUBToPSCLThroughput, + mode_lib->vba.MaxPSCLToLBThroughput + * mode_lib->vba.HRatio[k] + / dml_ceil( + mode_lib->vba.htaps[k] + / 6.0, + 1.0)); + } else { + mode_lib->vba.PSCL_FACTOR[k] = dml_min( + mode_lib->vba.MaxDCHUBToPSCLThroughput, + mode_lib->vba.MaxPSCLToLBThroughput); + } + if (mode_lib->vba.BytePerPixelInDETC[k] == 0.0) { + mode_lib->vba.PSCL_FACTOR_CHROMA[k] = 0.0; + mode_lib->vba.MinDPPCLKUsingSingleDPP[k] = + mode_lib->vba.PixelClock[k] + * dml_max3( + mode_lib->vba.vtaps[k] / 6.0 + * dml_min( + 1.0, + mode_lib->vba.HRatio[k]), + mode_lib->vba.HRatio[k] + * mode_lib->vba.VRatio[k] + / mode_lib->vba.PSCL_FACTOR[k], + 1.0); + if ((mode_lib->vba.htaps[k] > 6.0 || mode_lib->vba.vtaps[k] > 6.0) + && mode_lib->vba.MinDPPCLKUsingSingleDPP[k] + < 2.0 * mode_lib->vba.PixelClock[k]) { + mode_lib->vba.MinDPPCLKUsingSingleDPP[k] = 2.0 + * mode_lib->vba.PixelClock[k]; + } + } else { + if (mode_lib->vba.HRatio[k] / 2.0 > 1.0) { + mode_lib->vba.PSCL_FACTOR_CHROMA[k] = + dml_min( + mode_lib->vba.MaxDCHUBToPSCLThroughput, + mode_lib->vba.MaxPSCLToLBThroughput + * mode_lib->vba.HRatio[k] + / 2.0 + / dml_ceil( + mode_lib->vba.HTAPsChroma[k] + / 6.0, + 1.0)); + } else { + mode_lib->vba.PSCL_FACTOR_CHROMA[k] = dml_min( + mode_lib->vba.MaxDCHUBToPSCLThroughput, + mode_lib->vba.MaxPSCLToLBThroughput); + } + mode_lib->vba.MinDPPCLKUsingSingleDPP[k] = + mode_lib->vba.PixelClock[k] + * dml_max5( + mode_lib->vba.vtaps[k] / 6.0 + * dml_min( + 1.0, + mode_lib->vba.HRatio[k]), + mode_lib->vba.HRatio[k] + * mode_lib->vba.VRatio[k] + / mode_lib->vba.PSCL_FACTOR[k], + mode_lib->vba.VTAPsChroma[k] + / 6.0 + * dml_min( + 1.0, + mode_lib->vba.HRatio[k] + / 2.0), + mode_lib->vba.HRatio[k] + * mode_lib->vba.VRatio[k] + / 4.0 + / mode_lib->vba.PSCL_FACTOR_CHROMA[k], + 1.0); + if ((mode_lib->vba.htaps[k] > 6.0 || mode_lib->vba.vtaps[k] > 6.0 + || mode_lib->vba.HTAPsChroma[k] > 6.0 + || mode_lib->vba.VTAPsChroma[k] > 6.0) + && mode_lib->vba.MinDPPCLKUsingSingleDPP[k] + < 2.0 * mode_lib->vba.PixelClock[k]) { + mode_lib->vba.MinDPPCLKUsingSingleDPP[k] = 2.0 + * mode_lib->vba.PixelClock[k]; + } + } + } + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + Calculate256BBlockSizes( + mode_lib->vba.SourcePixelFormat[k], + mode_lib->vba.SurfaceTiling[k], + dml_ceil(mode_lib->vba.BytePerPixelInDETY[k], 1.0), + dml_ceil(mode_lib->vba.BytePerPixelInDETC[k], 2.0), + &mode_lib->vba.Read256BlockHeightY[k], + &mode_lib->vba.Read256BlockHeightC[k], + &mode_lib->vba.Read256BlockWidthY[k], + &mode_lib->vba.Read256BlockWidthC[k]); + if (mode_lib->vba.SourceScan[k] == dm_horz) { + mode_lib->vba.MaxSwathHeightY[k] = mode_lib->vba.Read256BlockHeightY[k]; + mode_lib->vba.MaxSwathHeightC[k] = mode_lib->vba.Read256BlockHeightC[k]; + } else { + mode_lib->vba.MaxSwathHeightY[k] = mode_lib->vba.Read256BlockWidthY[k]; + mode_lib->vba.MaxSwathHeightC[k] = mode_lib->vba.Read256BlockWidthC[k]; + } + if ((mode_lib->vba.SourcePixelFormat[k] == dm_444_64 + || mode_lib->vba.SourcePixelFormat[k] == dm_444_32 + || mode_lib->vba.SourcePixelFormat[k] == dm_444_16 + || mode_lib->vba.SourcePixelFormat[k] == dm_mono_16 + || mode_lib->vba.SourcePixelFormat[k] == dm_mono_8)) { + if (mode_lib->vba.SurfaceTiling[k] == dm_sw_linear + || (mode_lib->vba.SourcePixelFormat[k] == dm_444_64 + && (mode_lib->vba.SurfaceTiling[k] + == dm_sw_4kb_s + || mode_lib->vba.SurfaceTiling[k] + == dm_sw_4kb_s_x + || mode_lib->vba.SurfaceTiling[k] + == dm_sw_64kb_s + || mode_lib->vba.SurfaceTiling[k] + == dm_sw_64kb_s_t + || mode_lib->vba.SurfaceTiling[k] + == dm_sw_64kb_s_x + || mode_lib->vba.SurfaceTiling[k] + == dm_sw_var_s + || mode_lib->vba.SurfaceTiling[k] + == dm_sw_var_s_x) + && mode_lib->vba.SourceScan[k] == dm_horz)) { + mode_lib->vba.MinSwathHeightY[k] = mode_lib->vba.MaxSwathHeightY[k]; + } else { + mode_lib->vba.MinSwathHeightY[k] = mode_lib->vba.MaxSwathHeightY[k] + / 2.0; + } + mode_lib->vba.MinSwathHeightC[k] = mode_lib->vba.MaxSwathHeightC[k]; + } else { + if (mode_lib->vba.SurfaceTiling[k] == dm_sw_linear) { + mode_lib->vba.MinSwathHeightY[k] = mode_lib->vba.MaxSwathHeightY[k]; + mode_lib->vba.MinSwathHeightC[k] = mode_lib->vba.MaxSwathHeightC[k]; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_420_8 + && mode_lib->vba.SourceScan[k] == dm_horz) { + mode_lib->vba.MinSwathHeightY[k] = mode_lib->vba.MaxSwathHeightY[k] + / 2.0; + mode_lib->vba.MinSwathHeightC[k] = mode_lib->vba.MaxSwathHeightC[k]; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_420_10 + && mode_lib->vba.SourceScan[k] == dm_horz) { + mode_lib->vba.MinSwathHeightC[k] = mode_lib->vba.MaxSwathHeightC[k] + / 2.0; + mode_lib->vba.MinSwathHeightY[k] = mode_lib->vba.MaxSwathHeightY[k]; + } else { + mode_lib->vba.MinSwathHeightY[k] = mode_lib->vba.MaxSwathHeightY[k]; + mode_lib->vba.MinSwathHeightC[k] = mode_lib->vba.MaxSwathHeightC[k]; + } + } + if (mode_lib->vba.SurfaceTiling[k] == dm_sw_linear) { + mode_lib->vba.MaximumSwathWidthSupport = 8192.0; + } else { + mode_lib->vba.MaximumSwathWidthSupport = 5120.0; + } + mode_lib->vba.MaximumSwathWidthInDETBuffer = + dml_min( + mode_lib->vba.MaximumSwathWidthSupport, + mode_lib->vba.DETBufferSizeInKByte * 1024.0 / 2.0 + / (mode_lib->vba.BytePerPixelInDETY[k] + * mode_lib->vba.MinSwathHeightY[k] + + mode_lib->vba.BytePerPixelInDETC[k] + / 2.0 + * mode_lib->vba.MinSwathHeightC[k])); + if (mode_lib->vba.BytePerPixelInDETC[k] == 0.0) { + mode_lib->vba.MaximumSwathWidthInLineBuffer = + mode_lib->vba.LineBufferSize + * dml_max(mode_lib->vba.HRatio[k], 1.0) + / mode_lib->vba.LBBitPerPixel[k] + / (mode_lib->vba.vtaps[k] + + dml_max( + dml_ceil( + mode_lib->vba.VRatio[k], + 1.0) + - 2, + 0.0)); + } else { + mode_lib->vba.MaximumSwathWidthInLineBuffer = + dml_min( + mode_lib->vba.LineBufferSize + * dml_max( + mode_lib->vba.HRatio[k], + 1.0) + / mode_lib->vba.LBBitPerPixel[k] + / (mode_lib->vba.vtaps[k] + + dml_max( + dml_ceil( + mode_lib->vba.VRatio[k], + 1.0) + - 2, + 0.0)), + 2.0 * mode_lib->vba.LineBufferSize + * dml_max( + mode_lib->vba.HRatio[k] + / 2.0, + 1.0) + / mode_lib->vba.LBBitPerPixel[k] + / (mode_lib->vba.VTAPsChroma[k] + + dml_max( + dml_ceil( + mode_lib->vba.VRatio[k] + / 2.0, + 1.0) + - 2, + 0.0))); + } + mode_lib->vba.MaximumSwathWidth[k] = dml_min( + mode_lib->vba.MaximumSwathWidthInDETBuffer, + mode_lib->vba.MaximumSwathWidthInLineBuffer); + } + for (i = 0; i <= DC__VOLTAGE_STATES; i++) { + mode_lib->vba.MaxDispclkRoundedDownToDFSGranularity = RoundToDFSGranularityDown( + mode_lib->vba.MaxDispclk[i], + mode_lib->vba.DISPCLKDPPCLKVCOSpeed); + mode_lib->vba.MaxDppclkRoundedDownToDFSGranularity = RoundToDFSGranularityDown( + mode_lib->vba.MaxDppclk[i], + mode_lib->vba.DISPCLKDPPCLKVCOSpeed); + mode_lib->vba.RequiredDISPCLK[i] = 0.0; + mode_lib->vba.DISPCLK_DPPCLK_Support[i] = true; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.PlaneRequiredDISPCLKWithoutODMCombine = + mode_lib->vba.PixelClock[k] + * (1.0 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100.0) + * (1.0 + + mode_lib->vba.DISPCLKRampingMargin + / 100.0); + if (mode_lib->vba.ODMCapability == true + && mode_lib->vba.PlaneRequiredDISPCLKWithoutODMCombine + > mode_lib->vba.MaxDispclkRoundedDownToDFSGranularity) { + mode_lib->vba.ODMCombineEnablePerState[i][k] = true; + mode_lib->vba.PlaneRequiredDISPCLK = + mode_lib->vba.PlaneRequiredDISPCLKWithoutODMCombine + / 2.0; + } else { + mode_lib->vba.ODMCombineEnablePerState[i][k] = false; + mode_lib->vba.PlaneRequiredDISPCLK = + mode_lib->vba.PlaneRequiredDISPCLKWithoutODMCombine; + } + if (mode_lib->vba.MinDPPCLKUsingSingleDPP[k] + * (1.0 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100.0) + <= mode_lib->vba.MaxDppclkRoundedDownToDFSGranularity + && mode_lib->vba.SwathWidthYSingleDPP[k] + <= mode_lib->vba.MaximumSwathWidth[k] + && mode_lib->vba.ODMCombineEnablePerState[i][k] == false) { + mode_lib->vba.NoOfDPP[i][k] = 1.0; + mode_lib->vba.RequiredDPPCLK[i][k] = + mode_lib->vba.MinDPPCLKUsingSingleDPP[k] + * (1.0 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100.0); + } else { + mode_lib->vba.NoOfDPP[i][k] = 2.0; + mode_lib->vba.RequiredDPPCLK[i][k] = + mode_lib->vba.MinDPPCLKUsingSingleDPP[k] + * (1.0 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100.0) + / 2.0; + } + mode_lib->vba.RequiredDISPCLK[i] = dml_max( + mode_lib->vba.RequiredDISPCLK[i], + mode_lib->vba.PlaneRequiredDISPCLK); + if ((mode_lib->vba.MinDPPCLKUsingSingleDPP[k] / mode_lib->vba.NoOfDPP[i][k] + * (1.0 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100.0) + > mode_lib->vba.MaxDppclkRoundedDownToDFSGranularity) + || (mode_lib->vba.PlaneRequiredDISPCLK + > mode_lib->vba.MaxDispclkRoundedDownToDFSGranularity)) { + mode_lib->vba.DISPCLK_DPPCLK_Support[i] = false; + } + } + mode_lib->vba.TotalNumberOfActiveDPP[i] = 0.0; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.TotalNumberOfActiveDPP[i] = + mode_lib->vba.TotalNumberOfActiveDPP[i] + + mode_lib->vba.NoOfDPP[i][k]; + } + if ((mode_lib->vba.MaxDispclk[i] == mode_lib->vba.MaxDispclk[DC__VOLTAGE_STATES] + && mode_lib->vba.MaxDppclk[i] + == mode_lib->vba.MaxDppclk[DC__VOLTAGE_STATES]) + && (mode_lib->vba.TotalNumberOfActiveDPP[i] + > mode_lib->vba.MaxNumDPP + || mode_lib->vba.DISPCLK_DPPCLK_Support[i] == false)) { + mode_lib->vba.RequiredDISPCLK[i] = 0.0; + mode_lib->vba.DISPCLK_DPPCLK_Support[i] = true; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.PlaneRequiredDISPCLKWithoutODMCombine = + mode_lib->vba.PixelClock[k] + * (1.0 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100.0); + if (mode_lib->vba.ODMCapability == true + && mode_lib->vba.PlaneRequiredDISPCLKWithoutODMCombine + > mode_lib->vba.MaxDispclkRoundedDownToDFSGranularity) { + mode_lib->vba.ODMCombineEnablePerState[i][k] = true; + mode_lib->vba.PlaneRequiredDISPCLK = + mode_lib->vba.PlaneRequiredDISPCLKWithoutODMCombine + / 2.0; + } else { + mode_lib->vba.ODMCombineEnablePerState[i][k] = false; + mode_lib->vba.PlaneRequiredDISPCLK = + mode_lib->vba.PlaneRequiredDISPCLKWithoutODMCombine; + } + if (mode_lib->vba.MinDPPCLKUsingSingleDPP[k] + * (1.0 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100.0) + <= mode_lib->vba.MaxDppclkRoundedDownToDFSGranularity + && mode_lib->vba.SwathWidthYSingleDPP[k] + <= mode_lib->vba.MaximumSwathWidth[k] + && mode_lib->vba.ODMCombineEnablePerState[i][k] + == false) { + mode_lib->vba.NoOfDPP[i][k] = 1.0; + mode_lib->vba.RequiredDPPCLK[i][k] = + mode_lib->vba.MinDPPCLKUsingSingleDPP[k] + * (1.0 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100.0); + } else { + mode_lib->vba.NoOfDPP[i][k] = 2.0; + mode_lib->vba.RequiredDPPCLK[i][k] = + mode_lib->vba.MinDPPCLKUsingSingleDPP[k] + * (1.0 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100.0) + / 2.0; + } + mode_lib->vba.RequiredDISPCLK[i] = dml_max( + mode_lib->vba.RequiredDISPCLK[i], + mode_lib->vba.PlaneRequiredDISPCLK); + if ((mode_lib->vba.MinDPPCLKUsingSingleDPP[k] + / mode_lib->vba.NoOfDPP[i][k] + * (1.0 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100.0) + > mode_lib->vba.MaxDppclkRoundedDownToDFSGranularity) + || (mode_lib->vba.PlaneRequiredDISPCLK + > mode_lib->vba.MaxDispclkRoundedDownToDFSGranularity)) { + mode_lib->vba.DISPCLK_DPPCLK_Support[i] = false; + } + } + mode_lib->vba.TotalNumberOfActiveDPP[i] = 0.0; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.TotalNumberOfActiveDPP[i] = + mode_lib->vba.TotalNumberOfActiveDPP[i] + + mode_lib->vba.NoOfDPP[i][k]; + } + } + if (mode_lib->vba.TotalNumberOfActiveDPP[i] > mode_lib->vba.MaxNumDPP) { + mode_lib->vba.RequiredDISPCLK[i] = 0.0; + mode_lib->vba.DISPCLK_DPPCLK_Support[i] = true; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.ODMCombineEnablePerState[i][k] = false; + if (mode_lib->vba.SwathWidthYSingleDPP[k] + <= mode_lib->vba.MaximumSwathWidth[k]) { + mode_lib->vba.NoOfDPP[i][k] = 1.0; + mode_lib->vba.RequiredDPPCLK[i][k] = + mode_lib->vba.MinDPPCLKUsingSingleDPP[k] + * (1.0 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100.0); + } else { + mode_lib->vba.NoOfDPP[i][k] = 2.0; + mode_lib->vba.RequiredDPPCLK[i][k] = + mode_lib->vba.MinDPPCLKUsingSingleDPP[k] + * (1.0 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100.0) + / 2.0; + } + if (!(mode_lib->vba.MaxDispclk[i] + == mode_lib->vba.MaxDispclk[DC__VOLTAGE_STATES] + && mode_lib->vba.MaxDppclk[i] + == mode_lib->vba.MaxDppclk[DC__VOLTAGE_STATES])) { + mode_lib->vba.PlaneRequiredDISPCLK = + mode_lib->vba.PixelClock[k] + * (1.0 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100.0) + * (1.0 + + mode_lib->vba.DISPCLKRampingMargin + / 100.0); + } else { + mode_lib->vba.PlaneRequiredDISPCLK = + mode_lib->vba.PixelClock[k] + * (1.0 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100.0); + } + mode_lib->vba.RequiredDISPCLK[i] = dml_max( + mode_lib->vba.RequiredDISPCLK[i], + mode_lib->vba.PlaneRequiredDISPCLK); + if ((mode_lib->vba.MinDPPCLKUsingSingleDPP[k] + / mode_lib->vba.NoOfDPP[i][k] + * (1.0 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100.0) + > mode_lib->vba.MaxDppclkRoundedDownToDFSGranularity) + || (mode_lib->vba.PlaneRequiredDISPCLK + > mode_lib->vba.MaxDispclkRoundedDownToDFSGranularity)) { + mode_lib->vba.DISPCLK_DPPCLK_Support[i] = false; + } + } + mode_lib->vba.TotalNumberOfActiveDPP[i] = 0.0; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.TotalNumberOfActiveDPP[i] = + mode_lib->vba.TotalNumberOfActiveDPP[i] + + mode_lib->vba.NoOfDPP[i][k]; + } + } + mode_lib->vba.RequiredDISPCLK[i] = dml_max( + mode_lib->vba.RequiredDISPCLK[i], + mode_lib->vba.WritebackRequiredDISPCLK); + if (mode_lib->vba.MaxDispclkRoundedDownToDFSGranularity + < mode_lib->vba.WritebackRequiredDISPCLK) { + mode_lib->vba.DISPCLK_DPPCLK_Support[i] = false; + } + } + /*Viewport Size Check*/ + + for (i = 0; i <= DC__VOLTAGE_STATES; i++) { + mode_lib->vba.ViewportSizeSupport[i] = true; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.ODMCombineEnablePerState[i][k] == true) { + if (dml_min( + mode_lib->vba.SwathWidthYSingleDPP[k], + dml_round( + mode_lib->vba.HActive[k] / 2.0 + * mode_lib->vba.HRatio[k])) + > mode_lib->vba.MaximumSwathWidth[k]) { + mode_lib->vba.ViewportSizeSupport[i] = false; + } + } else { + if (mode_lib->vba.SwathWidthYSingleDPP[k] / 2.0 + > mode_lib->vba.MaximumSwathWidth[k]) { + mode_lib->vba.ViewportSizeSupport[i] = false; + } + } + } + } + /*Total Available Pipes Support Check*/ + + for (i = 0; i <= DC__VOLTAGE_STATES; i++) { + if (mode_lib->vba.TotalNumberOfActiveDPP[i] <= mode_lib->vba.MaxNumDPP) { + mode_lib->vba.TotalAvailablePipesSupport[i] = true; + } else { + mode_lib->vba.TotalAvailablePipesSupport[i] = false; + } + } + /*Total Available OTG Support Check*/ + + mode_lib->vba.TotalNumberOfActiveOTG = 0.0; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.BlendingAndTiming[k] == k) { + mode_lib->vba.TotalNumberOfActiveOTG = mode_lib->vba.TotalNumberOfActiveOTG + + 1.0; + } + } + if (mode_lib->vba.TotalNumberOfActiveOTG <= mode_lib->vba.MaxNumOTG) { + mode_lib->vba.NumberOfOTGSupport = true; + } else { + mode_lib->vba.NumberOfOTGSupport = false; + } + /*Display IO and DSC Support Check*/ + + mode_lib->vba.NonsupportedDSCInputBPC = false; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (!(mode_lib->vba.DSCInputBitPerComponent[k] == 12.0 + || mode_lib->vba.DSCInputBitPerComponent[k] == 10.0 + || mode_lib->vba.DSCInputBitPerComponent[k] == 8.0)) { + mode_lib->vba.NonsupportedDSCInputBPC = true; + } + } + for (i = 0; i <= DC__VOLTAGE_STATES; i++) { + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.RequiresDSC[i][k] = 0; + mode_lib->vba.RequiresFEC[i][k] = 0; + if (mode_lib->vba.BlendingAndTiming[k] == k) { + if (mode_lib->vba.Output[k] == dm_hdmi) { + mode_lib->vba.RequiresDSC[i][k] = 0; + mode_lib->vba.RequiresFEC[i][k] = 0; + mode_lib->vba.OutputBppPerState[i][k] = + TruncToValidBPP( + dml_min( + 600.0, + mode_lib->vba.PHYCLKPerState[i]) + / mode_lib->vba.PixelClockBackEnd[k] + * 24, + false, + mode_lib->vba.Output[k], + mode_lib->vba.OutputFormat[k], + mode_lib->vba.DSCInputBitPerComponent[k]); + } else if (mode_lib->vba.Output[k] == dm_dp + || mode_lib->vba.Output[k] == dm_edp) { + if (mode_lib->vba.Output[k] == dm_edp) { + mode_lib->vba.EffectiveFECOverhead = 0.0; + } else { + mode_lib->vba.EffectiveFECOverhead = + mode_lib->vba.FECOverhead; + } + if (mode_lib->vba.PHYCLKPerState[i] >= 270.0) { + mode_lib->vba.Outbpp = + TruncToValidBPP( + (1.0 + - mode_lib->vba.Downspreading + / 100.0) + * 270.0 + * mode_lib->vba.OutputLinkDPLanes[k] + / mode_lib->vba.PixelClockBackEnd[k] + * 8.0, + false, + mode_lib->vba.Output[k], + mode_lib->vba.OutputFormat[k], + mode_lib->vba.DSCInputBitPerComponent[k]); + mode_lib->vba.OutbppDSC = + TruncToValidBPP( + (1.0 + - mode_lib->vba.Downspreading + / 100.0) + * (1.0 + - mode_lib->vba.EffectiveFECOverhead + / 100.0) + * 270.0 + * mode_lib->vba.OutputLinkDPLanes[k] + / mode_lib->vba.PixelClockBackEnd[k] + * 8.0, + true, + mode_lib->vba.Output[k], + mode_lib->vba.OutputFormat[k], + mode_lib->vba.DSCInputBitPerComponent[k]); + if (mode_lib->vba.DSCEnabled[k] == true) { + mode_lib->vba.RequiresDSC[i][k] = true; + if (mode_lib->vba.Output[k] == dm_dp) { + mode_lib->vba.RequiresFEC[i][k] = + true; + } else { + mode_lib->vba.RequiresFEC[i][k] = + false; + } + mode_lib->vba.Outbpp = + mode_lib->vba.OutbppDSC; + } else { + mode_lib->vba.RequiresDSC[i][k] = false; + mode_lib->vba.RequiresFEC[i][k] = false; + } + mode_lib->vba.OutputBppPerState[i][k] = + mode_lib->vba.Outbpp; + } + if (mode_lib->vba.Outbpp == 0) { + mode_lib->vba.Outbpp = + TruncToValidBPP( + (1.0 + - mode_lib->vba.Downspreading + / 100.0) + * 540.0 + * mode_lib->vba.OutputLinkDPLanes[k] + / mode_lib->vba.PixelClockBackEnd[k] + * 8.0, + false, + mode_lib->vba.Output[k], + mode_lib->vba.OutputFormat[k], + mode_lib->vba.DSCInputBitPerComponent[k]); + mode_lib->vba.OutbppDSC = + TruncToValidBPP( + (1.0 + - mode_lib->vba.Downspreading + / 100.0) + * (1.0 + - mode_lib->vba.EffectiveFECOverhead + / 100.0) + * 540.0 + * mode_lib->vba.OutputLinkDPLanes[k] + / mode_lib->vba.PixelClockBackEnd[k] + * 8.0, + true, + mode_lib->vba.Output[k], + mode_lib->vba.OutputFormat[k], + mode_lib->vba.DSCInputBitPerComponent[k]); + if (mode_lib->vba.DSCEnabled[k] == true) { + mode_lib->vba.RequiresDSC[i][k] = true; + if (mode_lib->vba.Output[k] == dm_dp) { + mode_lib->vba.RequiresFEC[i][k] = + true; + } else { + mode_lib->vba.RequiresFEC[i][k] = + false; + } + mode_lib->vba.Outbpp = + mode_lib->vba.OutbppDSC; + } else { + mode_lib->vba.RequiresDSC[i][k] = false; + mode_lib->vba.RequiresFEC[i][k] = false; + } + mode_lib->vba.OutputBppPerState[i][k] = + mode_lib->vba.Outbpp; + } + if (mode_lib->vba.Outbpp == 0 + && mode_lib->vba.PHYCLKPerState[i] + >= 810.0) { + mode_lib->vba.Outbpp = + TruncToValidBPP( + (1.0 + - mode_lib->vba.Downspreading + / 100.0) + * 810.0 + * mode_lib->vba.OutputLinkDPLanes[k] + / mode_lib->vba.PixelClockBackEnd[k] + * 8.0, + false, + mode_lib->vba.Output[k], + mode_lib->vba.OutputFormat[k], + mode_lib->vba.DSCInputBitPerComponent[k]); + mode_lib->vba.OutbppDSC = + TruncToValidBPP( + (1.0 + - mode_lib->vba.Downspreading + / 100.0) + * (1.0 + - mode_lib->vba.EffectiveFECOverhead + / 100.0) + * 810.0 + * mode_lib->vba.OutputLinkDPLanes[k] + / mode_lib->vba.PixelClockBackEnd[k] + * 8.0, + true, + mode_lib->vba.Output[k], + mode_lib->vba.OutputFormat[k], + mode_lib->vba.DSCInputBitPerComponent[k]); + if (mode_lib->vba.DSCEnabled[k] == true + || mode_lib->vba.Outbpp == 0) { + mode_lib->vba.RequiresDSC[i][k] = true; + if (mode_lib->vba.Output[k] == dm_dp) { + mode_lib->vba.RequiresFEC[i][k] = + true; + } else { + mode_lib->vba.RequiresFEC[i][k] = + false; + } + mode_lib->vba.Outbpp = + mode_lib->vba.OutbppDSC; + } else { + mode_lib->vba.RequiresDSC[i][k] = false; + mode_lib->vba.RequiresFEC[i][k] = false; + } + mode_lib->vba.OutputBppPerState[i][k] = + mode_lib->vba.Outbpp; + } + } + } else { + mode_lib->vba.OutputBppPerState[i][k] = 0; + } + } + } + for (i = 0; i <= DC__VOLTAGE_STATES; i++) { + mode_lib->vba.DIOSupport[i] = true; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.OutputBppPerState[i][k] == 0 + || (mode_lib->vba.OutputFormat[k] == dm_420 + && mode_lib->vba.ProgressiveToInterlaceUnitInOPP + == true)) { + mode_lib->vba.DIOSupport[i] = false; + } + } + } + for (i = 0; i <= DC__VOLTAGE_STATES; i++) { + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.DSCCLKRequiredMoreThanSupported[i] = false; + if (mode_lib->vba.BlendingAndTiming[k] == k) { + if ((mode_lib->vba.Output[k] == dm_dp + || mode_lib->vba.Output[k] == dm_edp)) { + if (mode_lib->vba.OutputFormat[k] == dm_420 + || mode_lib->vba.OutputFormat[k] + == dm_n422) { + mode_lib->vba.DSCFormatFactor = 2; + } else { + mode_lib->vba.DSCFormatFactor = 1; + } + if (mode_lib->vba.RequiresDSC[i][k] == true) { + if (mode_lib->vba.ODMCombineEnablePerState[i][k] + == true) { + if (mode_lib->vba.PixelClockBackEnd[k] / 6.0 + / mode_lib->vba.DSCFormatFactor + > (1.0 + - mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100.0) + * mode_lib->vba.MaxDSCCLK[i]) { + mode_lib->vba.DSCCLKRequiredMoreThanSupported[i] = + true; + } + } else { + if (mode_lib->vba.PixelClockBackEnd[k] / 3.0 + / mode_lib->vba.DSCFormatFactor + > (1.0 + - mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100.0) + * mode_lib->vba.MaxDSCCLK[i]) { + mode_lib->vba.DSCCLKRequiredMoreThanSupported[i] = + true; + } + } + } + } + } + } + } + for (i = 0; i <= DC__VOLTAGE_STATES; i++) { + mode_lib->vba.NotEnoughDSCUnits[i] = false; + mode_lib->vba.TotalDSCUnitsRequired = 0.0; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.RequiresDSC[i][k] == true) { + if (mode_lib->vba.ODMCombineEnablePerState[i][k] == true) { + mode_lib->vba.TotalDSCUnitsRequired = + mode_lib->vba.TotalDSCUnitsRequired + 2.0; + } else { + mode_lib->vba.TotalDSCUnitsRequired = + mode_lib->vba.TotalDSCUnitsRequired + 1.0; + } + } + } + if (mode_lib->vba.TotalDSCUnitsRequired > mode_lib->vba.NumberOfDSC) { + mode_lib->vba.NotEnoughDSCUnits[i] = true; + } + } + /*DSC Delay per state*/ + + for (i = 0; i <= DC__VOLTAGE_STATES; i++) { + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.BlendingAndTiming[k] != k) { + mode_lib->vba.slices = 0; + } else if (mode_lib->vba.RequiresDSC[i][k] == 0 + || mode_lib->vba.RequiresDSC[i][k] == false) { + mode_lib->vba.slices = 0; + } else if (mode_lib->vba.PixelClockBackEnd[k] > 3200.0) { + mode_lib->vba.slices = dml_ceil( + mode_lib->vba.PixelClockBackEnd[k] / 400.0, + 4.0); + } else if (mode_lib->vba.PixelClockBackEnd[k] > 1360.0) { + mode_lib->vba.slices = 8.0; + } else if (mode_lib->vba.PixelClockBackEnd[k] > 680.0) { + mode_lib->vba.slices = 4.0; + } else if (mode_lib->vba.PixelClockBackEnd[k] > 340.0) { + mode_lib->vba.slices = 2.0; + } else { + mode_lib->vba.slices = 1.0; + } + if (mode_lib->vba.OutputBppPerState[i][k] == 0 + || mode_lib->vba.OutputBppPerState[i][k] == 0) { + mode_lib->vba.bpp = 0.0; + } else { + mode_lib->vba.bpp = mode_lib->vba.OutputBppPerState[i][k]; + } + if (mode_lib->vba.RequiresDSC[i][k] == true && mode_lib->vba.bpp != 0.0) { + if (mode_lib->vba.ODMCombineEnablePerState[i][k] == false) { + mode_lib->vba.DSCDelayPerState[i][k] = + dscceComputeDelay( + mode_lib->vba.DSCInputBitPerComponent[k], + mode_lib->vba.bpp, + dml_ceil( + mode_lib->vba.HActive[k] + / mode_lib->vba.slices, + 1.0), + mode_lib->vba.slices, + mode_lib->vba.OutputFormat[k]) + + dscComputeDelay( + mode_lib->vba.OutputFormat[k]); + } else { + mode_lib->vba.DSCDelayPerState[i][k] = + 2.0 + * (dscceComputeDelay( + mode_lib->vba.DSCInputBitPerComponent[k], + mode_lib->vba.bpp, + dml_ceil( + mode_lib->vba.HActive[k] + / mode_lib->vba.slices, + 1.0), + mode_lib->vba.slices + / 2, + mode_lib->vba.OutputFormat[k]) + + dscComputeDelay( + mode_lib->vba.OutputFormat[k])); + } + mode_lib->vba.DSCDelayPerState[i][k] = + mode_lib->vba.DSCDelayPerState[i][k] + * mode_lib->vba.PixelClock[k] + / mode_lib->vba.PixelClockBackEnd[k]; + } else { + mode_lib->vba.DSCDelayPerState[i][k] = 0.0; + } + } + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + for (j = 0; j <= mode_lib->vba.NumberOfActivePlanes - 1; j++) { + if (mode_lib->vba.BlendingAndTiming[k] == j + && mode_lib->vba.RequiresDSC[i][j] == true) { + mode_lib->vba.DSCDelayPerState[i][k] = + mode_lib->vba.DSCDelayPerState[i][j]; + } + } + } + } + /*Urgent Latency Support Check*/ + + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + for (i = 0; i <= DC__VOLTAGE_STATES; i++) { + if (mode_lib->vba.ODMCombineEnablePerState[i][k] == true) { + mode_lib->vba.SwathWidthYPerState[i][k] = + dml_min( + mode_lib->vba.SwathWidthYSingleDPP[k], + dml_round( + mode_lib->vba.HActive[k] + / 2.0 + * mode_lib->vba.HRatio[k])); + } else { + mode_lib->vba.SwathWidthYPerState[i][k] = + mode_lib->vba.SwathWidthYSingleDPP[k] + / mode_lib->vba.NoOfDPP[i][k]; + } + mode_lib->vba.SwathWidthGranularityY = 256.0 + / dml_ceil(mode_lib->vba.BytePerPixelInDETY[k], 1.0) + / mode_lib->vba.MaxSwathHeightY[k]; + mode_lib->vba.RoundedUpMaxSwathSizeBytesY = (dml_ceil( + mode_lib->vba.SwathWidthYPerState[i][k] - 1.0, + mode_lib->vba.SwathWidthGranularityY) + + mode_lib->vba.SwathWidthGranularityY) + * mode_lib->vba.BytePerPixelInDETY[k] + * mode_lib->vba.MaxSwathHeightY[k]; + if (mode_lib->vba.SourcePixelFormat[k] == dm_420_10) { + mode_lib->vba.RoundedUpMaxSwathSizeBytesY = dml_ceil( + mode_lib->vba.RoundedUpMaxSwathSizeBytesY, + 256.0) + 256; + } + if (mode_lib->vba.MaxSwathHeightC[k] > 0.0) { + mode_lib->vba.SwathWidthGranularityC = 256.0 + / dml_ceil(mode_lib->vba.BytePerPixelInDETC[k], 2.0) + / mode_lib->vba.MaxSwathHeightC[k]; + mode_lib->vba.RoundedUpMaxSwathSizeBytesC = (dml_ceil( + mode_lib->vba.SwathWidthYPerState[i][k] / 2.0 - 1.0, + mode_lib->vba.SwathWidthGranularityC) + + mode_lib->vba.SwathWidthGranularityC) + * mode_lib->vba.BytePerPixelInDETC[k] + * mode_lib->vba.MaxSwathHeightC[k]; + if (mode_lib->vba.SourcePixelFormat[k] == dm_420_10) { + mode_lib->vba.RoundedUpMaxSwathSizeBytesC = dml_ceil( + mode_lib->vba.RoundedUpMaxSwathSizeBytesC, + 256.0) + 256; + } + } else { + mode_lib->vba.RoundedUpMaxSwathSizeBytesC = 0.0; + } + if (mode_lib->vba.RoundedUpMaxSwathSizeBytesY + + mode_lib->vba.RoundedUpMaxSwathSizeBytesC + <= mode_lib->vba.DETBufferSizeInKByte * 1024.0 / 2.0) { + mode_lib->vba.SwathHeightYPerState[i][k] = + mode_lib->vba.MaxSwathHeightY[k]; + mode_lib->vba.SwathHeightCPerState[i][k] = + mode_lib->vba.MaxSwathHeightC[k]; + } else { + mode_lib->vba.SwathHeightYPerState[i][k] = + mode_lib->vba.MinSwathHeightY[k]; + mode_lib->vba.SwathHeightCPerState[i][k] = + mode_lib->vba.MinSwathHeightC[k]; + } + if (mode_lib->vba.BytePerPixelInDETC[k] == 0.0) { + mode_lib->vba.LinesInDETLuma = mode_lib->vba.DETBufferSizeInKByte + * 1024.0 / mode_lib->vba.BytePerPixelInDETY[k] + / mode_lib->vba.SwathWidthYPerState[i][k]; + mode_lib->vba.LinesInDETChroma = 0.0; + } else if (mode_lib->vba.SwathHeightYPerState[i][k] + <= mode_lib->vba.SwathHeightCPerState[i][k]) { + mode_lib->vba.LinesInDETLuma = mode_lib->vba.DETBufferSizeInKByte + * 1024.0 / 2.0 / mode_lib->vba.BytePerPixelInDETY[k] + / mode_lib->vba.SwathWidthYPerState[i][k]; + mode_lib->vba.LinesInDETChroma = mode_lib->vba.DETBufferSizeInKByte + * 1024.0 / 2.0 / mode_lib->vba.BytePerPixelInDETC[k] + / (mode_lib->vba.SwathWidthYPerState[i][k] / 2.0); + } else { + mode_lib->vba.LinesInDETLuma = mode_lib->vba.DETBufferSizeInKByte + * 1024.0 * 2.0 / 3.0 + / mode_lib->vba.BytePerPixelInDETY[k] + / mode_lib->vba.SwathWidthYPerState[i][k]; + mode_lib->vba.LinesInDETChroma = mode_lib->vba.DETBufferSizeInKByte + * 1024.0 / 3.0 / mode_lib->vba.BytePerPixelInDETY[k] + / (mode_lib->vba.SwathWidthYPerState[i][k] / 2.0); + } + mode_lib->vba.EffectiveLBLatencyHidingSourceLinesLuma = + dml_min( + mode_lib->vba.MaxLineBufferLines, + dml_floor( + mode_lib->vba.LineBufferSize + / mode_lib->vba.LBBitPerPixel[k] + / (mode_lib->vba.SwathWidthYPerState[i][k] + / dml_max( + mode_lib->vba.HRatio[k], + 1.0)), + 1.0)) + - (mode_lib->vba.vtaps[k] - 1.0); + mode_lib->vba.EffectiveLBLatencyHidingSourceLinesChroma = + dml_min( + mode_lib->vba.MaxLineBufferLines, + dml_floor( + mode_lib->vba.LineBufferSize + / mode_lib->vba.LBBitPerPixel[k] + / (mode_lib->vba.SwathWidthYPerState[i][k] + / 2.0 + / dml_max( + mode_lib->vba.HRatio[k] + / 2.0, + 1.0)), + 1.0)) + - (mode_lib->vba.VTAPsChroma[k] - 1.0); + mode_lib->vba.EffectiveDETLBLinesLuma = + dml_floor( + mode_lib->vba.LinesInDETLuma + + dml_min( + mode_lib->vba.LinesInDETLuma + * mode_lib->vba.RequiredDISPCLK[i] + * mode_lib->vba.BytePerPixelInDETY[k] + * mode_lib->vba.PSCL_FACTOR[k] + / mode_lib->vba.ReturnBWPerState[i], + mode_lib->vba.EffectiveLBLatencyHidingSourceLinesLuma), + mode_lib->vba.SwathHeightYPerState[i][k]); + mode_lib->vba.EffectiveDETLBLinesChroma = + dml_floor( + mode_lib->vba.LinesInDETChroma + + dml_min( + mode_lib->vba.LinesInDETChroma + * mode_lib->vba.RequiredDISPCLK[i] + * mode_lib->vba.BytePerPixelInDETC[k] + * mode_lib->vba.PSCL_FACTOR_CHROMA[k] + / mode_lib->vba.ReturnBWPerState[i], + mode_lib->vba.EffectiveLBLatencyHidingSourceLinesChroma), + mode_lib->vba.SwathHeightCPerState[i][k]); + if (mode_lib->vba.BytePerPixelInDETC[k] == 0.0) { + mode_lib->vba.UrgentLatencySupportUsPerState[i][k] = + mode_lib->vba.EffectiveDETLBLinesLuma + * (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]) + / mode_lib->vba.VRatio[k] + - mode_lib->vba.EffectiveDETLBLinesLuma + * mode_lib->vba.SwathWidthYPerState[i][k] + * dml_ceil( + mode_lib->vba.BytePerPixelInDETY[k], + 1.0) + / (mode_lib->vba.ReturnBWPerState[i] + / mode_lib->vba.NoOfDPP[i][k]); + } else { + mode_lib->vba.UrgentLatencySupportUsPerState[i][k] = + dml_min( + mode_lib->vba.EffectiveDETLBLinesLuma + * (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]) + / mode_lib->vba.VRatio[k] + - mode_lib->vba.EffectiveDETLBLinesLuma + * mode_lib->vba.SwathWidthYPerState[i][k] + * dml_ceil( + mode_lib->vba.BytePerPixelInDETY[k], + 1.0) + / (mode_lib->vba.ReturnBWPerState[i] + / mode_lib->vba.NoOfDPP[i][k]), + mode_lib->vba.EffectiveDETLBLinesChroma + * (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]) + / (mode_lib->vba.VRatio[k] + / 2.0) + - mode_lib->vba.EffectiveDETLBLinesChroma + * mode_lib->vba.SwathWidthYPerState[i][k] + / 2.0 + * dml_ceil( + mode_lib->vba.BytePerPixelInDETC[k], + 2.0) + / (mode_lib->vba.ReturnBWPerState[i] + / mode_lib->vba.NoOfDPP[i][k])); + } + } + } + for (i = 0; i <= DC__VOLTAGE_STATES; i++) { + mode_lib->vba.UrgentLatencySupport[i] = true; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.UrgentLatencySupportUsPerState[i][k] + < mode_lib->vba.UrgentLatency / 1.0) { + mode_lib->vba.UrgentLatencySupport[i] = false; + } + } + } + /*Prefetch Check*/ + + for (i = 0; i <= DC__VOLTAGE_STATES; i++) { + mode_lib->vba.TotalNumberOfDCCActiveDPP[i] = 0.0; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.DCCEnable[k] == true) { + mode_lib->vba.TotalNumberOfDCCActiveDPP[i] = + mode_lib->vba.TotalNumberOfDCCActiveDPP[i] + + mode_lib->vba.NoOfDPP[i][k]; + } + } + } + for (i = 0; i <= DC__VOLTAGE_STATES; i++) { + mode_lib->vba.ProjectedDCFCLKDeepSleep = 8.0; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.ProjectedDCFCLKDeepSleep = dml_max( + mode_lib->vba.ProjectedDCFCLKDeepSleep, + mode_lib->vba.PixelClock[k] / 16.0); + if (mode_lib->vba.BytePerPixelInDETC[k] == 0.0) { + if (mode_lib->vba.VRatio[k] <= 1.0) { + mode_lib->vba.ProjectedDCFCLKDeepSleep = + dml_max( + mode_lib->vba.ProjectedDCFCLKDeepSleep, + 1.1 + * dml_ceil( + mode_lib->vba.BytePerPixelInDETY[k], + 1.0) + / 64.0 + * mode_lib->vba.HRatio[k] + * mode_lib->vba.PixelClock[k] + / mode_lib->vba.NoOfDPP[i][k]); + } else { + mode_lib->vba.ProjectedDCFCLKDeepSleep = + dml_max( + mode_lib->vba.ProjectedDCFCLKDeepSleep, + 1.1 + * dml_ceil( + mode_lib->vba.BytePerPixelInDETY[k], + 1.0) + / 64.0 + * mode_lib->vba.PSCL_FACTOR[k] + * mode_lib->vba.RequiredDPPCLK[i][k]); + } + } else { + if (mode_lib->vba.VRatio[k] <= 1.0) { + mode_lib->vba.ProjectedDCFCLKDeepSleep = + dml_max( + mode_lib->vba.ProjectedDCFCLKDeepSleep, + 1.1 + * dml_ceil( + mode_lib->vba.BytePerPixelInDETY[k], + 1.0) + / 32.0 + * mode_lib->vba.HRatio[k] + * mode_lib->vba.PixelClock[k] + / mode_lib->vba.NoOfDPP[i][k]); + } else { + mode_lib->vba.ProjectedDCFCLKDeepSleep = + dml_max( + mode_lib->vba.ProjectedDCFCLKDeepSleep, + 1.1 + * dml_ceil( + mode_lib->vba.BytePerPixelInDETY[k], + 1.0) + / 32.0 + * mode_lib->vba.PSCL_FACTOR[k] + * mode_lib->vba.RequiredDPPCLK[i][k]); + } + if (mode_lib->vba.VRatio[k] / 2.0 <= 1.0) { + mode_lib->vba.ProjectedDCFCLKDeepSleep = + dml_max( + mode_lib->vba.ProjectedDCFCLKDeepSleep, + 1.1 + * dml_ceil( + mode_lib->vba.BytePerPixelInDETC[k], + 2.0) + / 32.0 + * mode_lib->vba.HRatio[k] + / 2.0 + * mode_lib->vba.PixelClock[k] + / mode_lib->vba.NoOfDPP[i][k]); + } else { + mode_lib->vba.ProjectedDCFCLKDeepSleep = + dml_max( + mode_lib->vba.ProjectedDCFCLKDeepSleep, + 1.1 + * dml_ceil( + mode_lib->vba.BytePerPixelInDETC[k], + 2.0) + / 32.0 + * mode_lib->vba.PSCL_FACTOR_CHROMA[k] + * mode_lib->vba.RequiredDPPCLK[i][k]); + } + } + } + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.PDEAndMetaPTEBytesPerFrameY = CalculateVMAndRowBytes( + mode_lib, + mode_lib->vba.DCCEnable[k], + mode_lib->vba.Read256BlockHeightY[k], + mode_lib->vba.Read256BlockWidthY[k], + mode_lib->vba.SourcePixelFormat[k], + mode_lib->vba.SurfaceTiling[k], + dml_ceil(mode_lib->vba.BytePerPixelInDETY[k], 1.0), + mode_lib->vba.SourceScan[k], + mode_lib->vba.ViewportWidth[k], + mode_lib->vba.ViewportHeight[k], + mode_lib->vba.SwathWidthYPerState[i][k], + mode_lib->vba.VirtualMemoryEnable, + mode_lib->vba.VMMPageSize, + mode_lib->vba.PTEBufferSizeInRequests, + mode_lib->vba.PDEProcessingBufIn64KBReqs, + mode_lib->vba.PitchY[k], + mode_lib->vba.DCCMetaPitchY[k], + &mode_lib->vba.MacroTileWidthY[k], + &mode_lib->vba.MetaRowBytesY, + &mode_lib->vba.DPTEBytesPerRowY, + &mode_lib->vba.PTEBufferSizeNotExceededY[i][k], + &mode_lib->vba.dpte_row_height[k], + &mode_lib->vba.meta_row_height[k]); + mode_lib->vba.PrefetchLinesY[k] = CalculatePrefetchSourceLines( + mode_lib, + mode_lib->vba.VRatio[k], + mode_lib->vba.vtaps[k], + mode_lib->vba.Interlace[k], + mode_lib->vba.ProgressiveToInterlaceUnitInOPP, + mode_lib->vba.SwathHeightYPerState[i][k], + mode_lib->vba.ViewportYStartY[k], + &mode_lib->vba.PrefillY[k], + &mode_lib->vba.MaxNumSwY[k]); + if ((mode_lib->vba.SourcePixelFormat[k] != dm_444_64 + && mode_lib->vba.SourcePixelFormat[k] != dm_444_32 + && mode_lib->vba.SourcePixelFormat[k] != dm_444_16 + && mode_lib->vba.SourcePixelFormat[k] != dm_mono_16 + && mode_lib->vba.SourcePixelFormat[k] != dm_mono_8)) { + mode_lib->vba.PDEAndMetaPTEBytesPerFrameC = CalculateVMAndRowBytes( + mode_lib, + mode_lib->vba.DCCEnable[k], + mode_lib->vba.Read256BlockHeightY[k], + mode_lib->vba.Read256BlockWidthY[k], + mode_lib->vba.SourcePixelFormat[k], + mode_lib->vba.SurfaceTiling[k], + dml_ceil(mode_lib->vba.BytePerPixelInDETC[k], 2.0), + mode_lib->vba.SourceScan[k], + mode_lib->vba.ViewportWidth[k] / 2.0, + mode_lib->vba.ViewportHeight[k] / 2.0, + mode_lib->vba.SwathWidthYPerState[i][k] / 2.0, + mode_lib->vba.VirtualMemoryEnable, + mode_lib->vba.VMMPageSize, + mode_lib->vba.PTEBufferSizeInRequests, + mode_lib->vba.PDEProcessingBufIn64KBReqs, + mode_lib->vba.PitchC[k], + 0.0, + &mode_lib->vba.MacroTileWidthC[k], + &mode_lib->vba.MetaRowBytesC, + &mode_lib->vba.DPTEBytesPerRowC, + &mode_lib->vba.PTEBufferSizeNotExceededC[i][k], + &mode_lib->vba.dpte_row_height_chroma[k], + &mode_lib->vba.meta_row_height_chroma[k]); + mode_lib->vba.PrefetchLinesC[k] = CalculatePrefetchSourceLines( + mode_lib, + mode_lib->vba.VRatio[k] / 2.0, + mode_lib->vba.VTAPsChroma[k], + mode_lib->vba.Interlace[k], + mode_lib->vba.ProgressiveToInterlaceUnitInOPP, + mode_lib->vba.SwathHeightCPerState[i][k], + mode_lib->vba.ViewportYStartC[k], + &mode_lib->vba.PrefillC[k], + &mode_lib->vba.MaxNumSwC[k]); + } else { + mode_lib->vba.PDEAndMetaPTEBytesPerFrameC = 0.0; + mode_lib->vba.MetaRowBytesC = 0.0; + mode_lib->vba.DPTEBytesPerRowC = 0.0; + mode_lib->vba.PrefetchLinesC[k] = 0.0; + mode_lib->vba.PTEBufferSizeNotExceededC[i][k] = true; + } + mode_lib->vba.PDEAndMetaPTEBytesPerFrame[k] = + mode_lib->vba.PDEAndMetaPTEBytesPerFrameY + + mode_lib->vba.PDEAndMetaPTEBytesPerFrameC; + mode_lib->vba.MetaRowBytes[k] = mode_lib->vba.MetaRowBytesY + + mode_lib->vba.MetaRowBytesC; + mode_lib->vba.DPTEBytesPerRow[k] = mode_lib->vba.DPTEBytesPerRowY + + mode_lib->vba.DPTEBytesPerRowC; + } + mode_lib->vba.ExtraLatency = + mode_lib->vba.UrgentRoundTripAndOutOfOrderLatencyPerState[i] + + (mode_lib->vba.TotalNumberOfActiveDPP[i] + * mode_lib->vba.PixelChunkSizeInKByte + + mode_lib->vba.TotalNumberOfDCCActiveDPP[i] + * mode_lib->vba.MetaChunkSize) + * 1024.0 + / mode_lib->vba.ReturnBWPerState[i]; + if (mode_lib->vba.VirtualMemoryEnable == true) { + mode_lib->vba.ExtraLatency = mode_lib->vba.ExtraLatency + + mode_lib->vba.TotalNumberOfActiveDPP[i] + * mode_lib->vba.PTEChunkSize * 1024.0 + / mode_lib->vba.ReturnBWPerState[i]; + } + mode_lib->vba.TimeCalc = 24.0 / mode_lib->vba.ProjectedDCFCLKDeepSleep; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.BlendingAndTiming[k] == k) { + if (mode_lib->vba.WritebackEnable[k] == true) { + mode_lib->vba.WritebackDelay[i][k] = + mode_lib->vba.WritebackLatency + + CalculateWriteBackDelay( + mode_lib->vba.WritebackPixelFormat[k], + mode_lib->vba.WritebackHRatio[k], + mode_lib->vba.WritebackVRatio[k], + mode_lib->vba.WritebackLumaHTaps[k], + mode_lib->vba.WritebackLumaVTaps[k], + mode_lib->vba.WritebackChromaHTaps[k], + mode_lib->vba.WritebackChromaVTaps[k], + mode_lib->vba.WritebackDestinationWidth[k]) + / mode_lib->vba.RequiredDISPCLK[i]; + } else { + mode_lib->vba.WritebackDelay[i][k] = 0.0; + } + for (j = 0; j <= mode_lib->vba.NumberOfActivePlanes - 1; j++) { + if (mode_lib->vba.BlendingAndTiming[j] == k + && mode_lib->vba.WritebackEnable[j] + == true) { + mode_lib->vba.WritebackDelay[i][k] = + dml_max( + mode_lib->vba.WritebackDelay[i][k], + mode_lib->vba.WritebackLatency + + CalculateWriteBackDelay( + mode_lib->vba.WritebackPixelFormat[j], + mode_lib->vba.WritebackHRatio[j], + mode_lib->vba.WritebackVRatio[j], + mode_lib->vba.WritebackLumaHTaps[j], + mode_lib->vba.WritebackLumaVTaps[j], + mode_lib->vba.WritebackChromaHTaps[j], + mode_lib->vba.WritebackChromaVTaps[j], + mode_lib->vba.WritebackDestinationWidth[j]) + / mode_lib->vba.RequiredDISPCLK[i]); + } + } + } + } + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + for (j = 0; j <= mode_lib->vba.NumberOfActivePlanes - 1; j++) { + if (mode_lib->vba.BlendingAndTiming[k] == j) { + mode_lib->vba.WritebackDelay[i][k] = + mode_lib->vba.WritebackDelay[i][j]; + } + } + } + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.MaximumVStartup[k] = + mode_lib->vba.VTotal[k] - mode_lib->vba.VActive[k] + - dml_max( + 1.0, + dml_ceil( + mode_lib->vba.WritebackDelay[i][k] + / (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]), + 1.0)); + } + mode_lib->vba.TWait = CalculateTWait( + mode_lib->vba.PrefetchMode, + mode_lib->vba.DRAMClockChangeLatency, + mode_lib->vba.UrgentLatency, + mode_lib->vba.SREnterPlusExitTime); + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.XFCEnabled[k] == true) { + mode_lib->vba.XFCRemoteSurfaceFlipDelay = + CalculateRemoteSurfaceFlipDelay( + mode_lib, + mode_lib->vba.VRatio[k], + mode_lib->vba.SwathWidthYPerState[i][k], + dml_ceil( + mode_lib->vba.BytePerPixelInDETY[k], + 1.0), + mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k], + mode_lib->vba.XFCTSlvVupdateOffset, + mode_lib->vba.XFCTSlvVupdateWidth, + mode_lib->vba.XFCTSlvVreadyOffset, + mode_lib->vba.XFCXBUFLatencyTolerance, + mode_lib->vba.XFCFillBWOverhead, + mode_lib->vba.XFCSlvChunkSize, + mode_lib->vba.XFCBusTransportTime, + mode_lib->vba.TimeCalc, + mode_lib->vba.TWait, + &mode_lib->vba.SrcActiveDrainRate, + &mode_lib->vba.TInitXFill, + &mode_lib->vba.TslvChk); + } else { + mode_lib->vba.XFCRemoteSurfaceFlipDelay = 0.0; + } + mode_lib->vba.IsErrorResult[i][k] = + CalculatePrefetchSchedule( + mode_lib, + mode_lib->vba.RequiredDPPCLK[i][k], + mode_lib->vba.RequiredDISPCLK[i], + mode_lib->vba.PixelClock[k], + mode_lib->vba.ProjectedDCFCLKDeepSleep, + mode_lib->vba.DSCDelayPerState[i][k], + mode_lib->vba.NoOfDPP[i][k], + mode_lib->vba.ScalerEnabled[k], + mode_lib->vba.NumberOfCursors[k], + mode_lib->vba.DPPCLKDelaySubtotal, + mode_lib->vba.DPPCLKDelaySCL, + mode_lib->vba.DPPCLKDelaySCLLBOnly, + mode_lib->vba.DPPCLKDelayCNVCFormater, + mode_lib->vba.DPPCLKDelayCNVCCursor, + mode_lib->vba.DISPCLKDelaySubtotal, + mode_lib->vba.SwathWidthYPerState[i][k] + / mode_lib->vba.HRatio[k], + mode_lib->vba.OutputFormat[k], + mode_lib->vba.VTotal[k] + - mode_lib->vba.VActive[k], + mode_lib->vba.HTotal[k], + mode_lib->vba.MaxInterDCNTileRepeaters, + mode_lib->vba.MaximumVStartup[k], + mode_lib->vba.MaxPageTableLevels, + mode_lib->vba.VirtualMemoryEnable, + mode_lib->vba.DynamicMetadataEnable[k], + mode_lib->vba.DynamicMetadataLinesBeforeActiveRequired[k], + mode_lib->vba.DynamicMetadataTransmittedBytes[k], + mode_lib->vba.DCCEnable[k], + mode_lib->vba.UrgentLatency, + mode_lib->vba.ExtraLatency, + mode_lib->vba.TimeCalc, + mode_lib->vba.PDEAndMetaPTEBytesPerFrame[k], + mode_lib->vba.MetaRowBytes[k], + mode_lib->vba.DPTEBytesPerRow[k], + mode_lib->vba.PrefetchLinesY[k], + mode_lib->vba.SwathWidthYPerState[i][k], + mode_lib->vba.BytePerPixelInDETY[k], + mode_lib->vba.PrefillY[k], + mode_lib->vba.MaxNumSwY[k], + mode_lib->vba.PrefetchLinesC[k], + mode_lib->vba.BytePerPixelInDETC[k], + mode_lib->vba.PrefillC[k], + mode_lib->vba.MaxNumSwC[k], + mode_lib->vba.SwathHeightYPerState[i][k], + mode_lib->vba.SwathHeightCPerState[i][k], + mode_lib->vba.TWait, + mode_lib->vba.XFCEnabled[k], + mode_lib->vba.XFCRemoteSurfaceFlipDelay, + mode_lib->vba.Interlace[k], + mode_lib->vba.ProgressiveToInterlaceUnitInOPP, + mode_lib->vba.DSTXAfterScaler, + mode_lib->vba.DSTYAfterScaler, + &mode_lib->vba.LineTimesForPrefetch[k], + &mode_lib->vba.PrefetchBW[k], + &mode_lib->vba.LinesForMetaPTE[k], + &mode_lib->vba.LinesForMetaAndDPTERow[k], + &mode_lib->vba.VRatioPreY[i][k], + &mode_lib->vba.VRatioPreC[i][k], + &mode_lib->vba.RequiredPrefetchPixelDataBW[i][k], + &mode_lib->vba.VStartupRequiredWhenNotEnoughTimeForDynamicMetadata, + &mode_lib->vba.Tno_bw[k]); + } + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.cursor_bw[k] = mode_lib->vba.NumberOfCursors[k] + * mode_lib->vba.CursorWidth[k][0] + * mode_lib->vba.CursorBPP[k][0] / 8.0 + / (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) + * mode_lib->vba.VRatio[k]; + } + mode_lib->vba.MaximumReadBandwidthWithPrefetch = 0.0; + mode_lib->vba.prefetch_vm_bw_valid = true; + mode_lib->vba.prefetch_row_bw_valid = true; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.PDEAndMetaPTEBytesPerFrame[k] == 0.0) { + mode_lib->vba.prefetch_vm_bw[k] = 0.0; + } else if (mode_lib->vba.LinesForMetaPTE[k] > 0.0) { + mode_lib->vba.prefetch_vm_bw[k] = + mode_lib->vba.PDEAndMetaPTEBytesPerFrame[k] + / (mode_lib->vba.LinesForMetaPTE[k] + * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]); + } else { + mode_lib->vba.prefetch_vm_bw[k] = 0.0; + mode_lib->vba.prefetch_vm_bw_valid = false; + } + if (mode_lib->vba.MetaRowBytes[k] + mode_lib->vba.DPTEBytesPerRow[k] + == 0.0) { + mode_lib->vba.prefetch_row_bw[k] = 0.0; + } else if (mode_lib->vba.LinesForMetaAndDPTERow[k] > 0.0) { + mode_lib->vba.prefetch_row_bw[k] = (mode_lib->vba.MetaRowBytes[k] + + mode_lib->vba.DPTEBytesPerRow[k]) + / (mode_lib->vba.LinesForMetaAndDPTERow[k] + * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]); + } else { + mode_lib->vba.prefetch_row_bw[k] = 0.0; + mode_lib->vba.prefetch_row_bw_valid = false; + } + mode_lib->vba.MaximumReadBandwidthWithPrefetch = + mode_lib->vba.MaximumReadBandwidthWithPrefetch + + mode_lib->vba.cursor_bw[k] + + dml_max4( + mode_lib->vba.prefetch_vm_bw[k], + mode_lib->vba.prefetch_row_bw[k], + mode_lib->vba.ReadBandwidth[k], + mode_lib->vba.RequiredPrefetchPixelDataBW[i][k]); + } + mode_lib->vba.PrefetchSupported[i] = true; + if (mode_lib->vba.MaximumReadBandwidthWithPrefetch + > mode_lib->vba.ReturnBWPerState[i] + || mode_lib->vba.prefetch_vm_bw_valid == false + || mode_lib->vba.prefetch_row_bw_valid == false) { + mode_lib->vba.PrefetchSupported[i] = false; + } + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.LineTimesForPrefetch[k] < 2.0 + || mode_lib->vba.LinesForMetaPTE[k] >= 8.0 + || mode_lib->vba.LinesForMetaAndDPTERow[k] >= 16.0 + || mode_lib->vba.IsErrorResult[i][k] == true) { + mode_lib->vba.PrefetchSupported[i] = false; + } + } + mode_lib->vba.VRatioInPrefetchSupported[i] = true; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.VRatioPreY[i][k] > 4.0 + || mode_lib->vba.VRatioPreC[i][k] > 4.0 + || mode_lib->vba.IsErrorResult[i][k] == true) { + mode_lib->vba.VRatioInPrefetchSupported[i] = false; + } + } + if (mode_lib->vba.PrefetchSupported[i] == true + && mode_lib->vba.VRatioInPrefetchSupported[i] == true) { + mode_lib->vba.BandwidthAvailableForImmediateFlip = + mode_lib->vba.ReturnBWPerState[i]; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.BandwidthAvailableForImmediateFlip = + mode_lib->vba.BandwidthAvailableForImmediateFlip + - mode_lib->vba.cursor_bw[k] + - dml_max( + mode_lib->vba.ReadBandwidth[k], + mode_lib->vba.PrefetchBW[k]); + } + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.ImmediateFlipBytes[k] = 0.0; + if ((mode_lib->vba.SourcePixelFormat[k] != dm_420_8 + && mode_lib->vba.SourcePixelFormat[k] != dm_420_10)) { + mode_lib->vba.ImmediateFlipBytes[k] = + mode_lib->vba.PDEAndMetaPTEBytesPerFrame[k] + + mode_lib->vba.MetaRowBytes[k] + + mode_lib->vba.DPTEBytesPerRow[k]; + } + } + mode_lib->vba.TotImmediateFlipBytes = 0.0; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if ((mode_lib->vba.SourcePixelFormat[k] != dm_420_8 + && mode_lib->vba.SourcePixelFormat[k] != dm_420_10)) { + mode_lib->vba.TotImmediateFlipBytes = + mode_lib->vba.TotImmediateFlipBytes + + mode_lib->vba.ImmediateFlipBytes[k]; + } + } + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + CalculateFlipSchedule( + mode_lib, + mode_lib->vba.ExtraLatency, + mode_lib->vba.UrgentLatency, + mode_lib->vba.MaxPageTableLevels, + mode_lib->vba.VirtualMemoryEnable, + mode_lib->vba.BandwidthAvailableForImmediateFlip, + mode_lib->vba.TotImmediateFlipBytes, + mode_lib->vba.SourcePixelFormat[k], + mode_lib->vba.ImmediateFlipBytes[k], + mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k], + mode_lib->vba.VRatio[k], + mode_lib->vba.Tno_bw[k], + mode_lib->vba.PDEAndMetaPTEBytesPerFrame[k], + mode_lib->vba.MetaRowBytes[k], + mode_lib->vba.DPTEBytesPerRow[k], + mode_lib->vba.DCCEnable[k], + mode_lib->vba.dpte_row_height[k], + mode_lib->vba.meta_row_height[k], + mode_lib->vba.qual_row_bw[k], + &mode_lib->vba.DestinationLinesToRequestVMInImmediateFlip[k], + &mode_lib->vba.DestinationLinesToRequestRowInImmediateFlip[k], + &mode_lib->vba.final_flip_bw[k], + &mode_lib->vba.ImmediateFlipSupportedForPipe[k]); + } + mode_lib->vba.total_dcn_read_bw_with_flip = 0.0; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.total_dcn_read_bw_with_flip = + mode_lib->vba.total_dcn_read_bw_with_flip + + mode_lib->vba.cursor_bw[k] + + dml_max3( + mode_lib->vba.prefetch_vm_bw[k], + mode_lib->vba.prefetch_row_bw[k], + mode_lib->vba.final_flip_bw[k] + + dml_max( + mode_lib->vba.ReadBandwidth[k], + mode_lib->vba.RequiredPrefetchPixelDataBW[i][k])); + } + mode_lib->vba.ImmediateFlipSupportedForState[i] = true; + if (mode_lib->vba.total_dcn_read_bw_with_flip + > mode_lib->vba.ReturnBWPerState[i]) { + mode_lib->vba.ImmediateFlipSupportedForState[i] = false; + } + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.ImmediateFlipSupportedForPipe[k] == false) { + mode_lib->vba.ImmediateFlipSupportedForState[i] = false; + } + } + } else { + mode_lib->vba.ImmediateFlipSupportedForState[i] = false; + } + } + /*PTE Buffer Size Check*/ + + for (i = 0; i <= DC__VOLTAGE_STATES; i++) { + mode_lib->vba.PTEBufferSizeNotExceeded[i] = true; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.PTEBufferSizeNotExceededY[i][k] == false + || mode_lib->vba.PTEBufferSizeNotExceededC[i][k] == false) { + mode_lib->vba.PTEBufferSizeNotExceeded[i] = false; + } + } + } + /*Cursor Support Check*/ + + mode_lib->vba.CursorSupport = true; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.CursorWidth[k][0] > 0.0) { + if (dml_floor( + dml_floor( + mode_lib->vba.CursorBufferSize + - mode_lib->vba.CursorChunkSize, + mode_lib->vba.CursorChunkSize) * 1024.0 + / (mode_lib->vba.CursorWidth[k][0] + * mode_lib->vba.CursorBPP[k][0] + / 8.0), + 1.0) + * (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) + / mode_lib->vba.VRatio[k] < mode_lib->vba.UrgentLatency + || (mode_lib->vba.CursorBPP[k][0] == 64.0 + && mode_lib->vba.Cursor64BppSupport == false)) { + mode_lib->vba.CursorSupport = false; + } + } + } + /*Valid Pitch Check*/ + + mode_lib->vba.PitchSupport = true; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.AlignedYPitch[k] = dml_ceil( + dml_max(mode_lib->vba.PitchY[k], mode_lib->vba.ViewportWidth[k]), + mode_lib->vba.MacroTileWidthY[k]); + if (mode_lib->vba.AlignedYPitch[k] > mode_lib->vba.PitchY[k]) { + mode_lib->vba.PitchSupport = false; + } + if (mode_lib->vba.DCCEnable[k] == true) { + mode_lib->vba.AlignedDCCMetaPitch[k] = dml_ceil( + dml_max( + mode_lib->vba.DCCMetaPitchY[k], + mode_lib->vba.ViewportWidth[k]), + 64.0 * mode_lib->vba.Read256BlockWidthY[k]); + } else { + mode_lib->vba.AlignedDCCMetaPitch[k] = mode_lib->vba.DCCMetaPitchY[k]; + } + if (mode_lib->vba.AlignedDCCMetaPitch[k] > mode_lib->vba.DCCMetaPitchY[k]) { + mode_lib->vba.PitchSupport = false; + } + if (mode_lib->vba.SourcePixelFormat[k] != dm_444_64 + && mode_lib->vba.SourcePixelFormat[k] != dm_444_32 + && mode_lib->vba.SourcePixelFormat[k] != dm_444_16 + && mode_lib->vba.SourcePixelFormat[k] != dm_mono_16 + && mode_lib->vba.SourcePixelFormat[k] != dm_mono_8) { + mode_lib->vba.AlignedCPitch[k] = dml_ceil( + dml_max( + mode_lib->vba.PitchC[k], + mode_lib->vba.ViewportWidth[k] / 2.0), + mode_lib->vba.MacroTileWidthC[k]); + } else { + mode_lib->vba.AlignedCPitch[k] = mode_lib->vba.PitchC[k]; + } + if (mode_lib->vba.AlignedCPitch[k] > mode_lib->vba.PitchC[k]) { + mode_lib->vba.PitchSupport = false; + } + } + /*Mode Support, Voltage State and SOC Configuration*/ + + for (i = DC__VOLTAGE_STATES; i >= 0; i--) { + if (mode_lib->vba.ScaleRatioAndTapsSupport == true + && mode_lib->vba.SourceFormatPixelAndScanSupport == true + && mode_lib->vba.ViewportSizeSupport[i] == true + && mode_lib->vba.BandwidthSupport[i] == true + && mode_lib->vba.DIOSupport[i] == true + && mode_lib->vba.NotEnoughDSCUnits[i] == false + && mode_lib->vba.DSCCLKRequiredMoreThanSupported[i] == false + && mode_lib->vba.UrgentLatencySupport[i] == true + && mode_lib->vba.ROBSupport[i] == true + && mode_lib->vba.DISPCLK_DPPCLK_Support[i] == true + && mode_lib->vba.TotalAvailablePipesSupport[i] == true + && mode_lib->vba.NumberOfOTGSupport == true + && mode_lib->vba.WritebackModeSupport == true + && mode_lib->vba.WritebackLatencySupport == true + && mode_lib->vba.WritebackScaleRatioAndTapsSupport == true + && mode_lib->vba.CursorSupport == true + && mode_lib->vba.PitchSupport == true + && mode_lib->vba.PrefetchSupported[i] == true + && mode_lib->vba.VRatioInPrefetchSupported[i] == true + && mode_lib->vba.PTEBufferSizeNotExceeded[i] == true + && mode_lib->vba.NonsupportedDSCInputBPC == false) { + mode_lib->vba.ModeSupport[i] = true; + } else { + mode_lib->vba.ModeSupport[i] = false; + } + } + for (i = DC__VOLTAGE_STATES; i >= 0; i--) { + if (i == DC__VOLTAGE_STATES || mode_lib->vba.ModeSupport[i] == true) { + mode_lib->vba.VoltageLevel = i; + } + } + mode_lib->vba.DCFCLK = mode_lib->vba.DCFCLKPerState[mode_lib->vba.VoltageLevel]; + mode_lib->vba.DRAMSpeed = mode_lib->vba.DRAMSpeedPerState[mode_lib->vba.VoltageLevel]; + mode_lib->vba.FabricClock = mode_lib->vba.FabricClockPerState[mode_lib->vba.VoltageLevel]; + mode_lib->vba.SOCCLK = mode_lib->vba.SOCCLKPerState[mode_lib->vba.VoltageLevel]; + mode_lib->vba.FabricAndDRAMBandwidth = + mode_lib->vba.FabricAndDRAMBandwidthPerState[mode_lib->vba.VoltageLevel]; + mode_lib->vba.ImmediateFlipSupport = + mode_lib->vba.ImmediateFlipSupportedForState[mode_lib->vba.VoltageLevel]; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.DPPPerPlane[k] = mode_lib->vba.NoOfDPP[mode_lib->vba.VoltageLevel][k]; + } + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.BlendingAndTiming[k] == k) { + mode_lib->vba.ODMCombineEnabled[k] = + mode_lib->vba.ODMCombineEnablePerState[mode_lib->vba.VoltageLevel][k]; + } else { + mode_lib->vba.ODMCombineEnabled[k] = 0; + } + mode_lib->vba.DSCEnabled[k] = + mode_lib->vba.RequiresDSC[mode_lib->vba.VoltageLevel][k]; + mode_lib->vba.OutputBpp[k] = + mode_lib->vba.OutputBppPerState[mode_lib->vba.VoltageLevel][k]; + } +} diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h index a24fe9a0383d..346ffea843c9 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h @@ -79,6 +79,11 @@ double get_total_prefetch_bw( const display_e2e_pipe_params_st *pipes, unsigned int num_pipes); +unsigned int dml_get_voltage_level( + struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *pipes, + unsigned int num_pipes); + bool Calculate256BBlockSizes( enum source_format_class SourcePixelFormat, enum dm_swizzle_mode SurfaceTiling, @@ -96,42 +101,41 @@ struct vba_vars_st { mode_evaluation_st me; unsigned int MaximumMaxVStartupLines; - double cursor_bw[DC__NUM_PIPES__MAX]; - double meta_row_bw[DC__NUM_PIPES__MAX]; - double dpte_row_bw[DC__NUM_PIPES__MAX]; - double qual_row_bw[DC__NUM_PIPES__MAX]; + double cursor_bw[DC__NUM_DPP__MAX]; + double meta_row_bw[DC__NUM_DPP__MAX]; + double dpte_row_bw[DC__NUM_DPP__MAX]; + double qual_row_bw[DC__NUM_DPP__MAX]; double WritebackDISPCLK; - double PSCL_THROUGHPUT_LUMA[DC__NUM_PIPES__MAX]; - double PSCL_THROUGHPUT_CHROMA[DC__NUM_PIPES__MAX]; + double PSCL_THROUGHPUT_LUMA[DC__NUM_DPP__MAX]; + double PSCL_THROUGHPUT_CHROMA[DC__NUM_DPP__MAX]; double DPPCLKUsingSingleDPPLuma; double DPPCLKUsingSingleDPPChroma; - double DPPCLKUsingSingleDPP[DC__NUM_PIPES__MAX]; + double DPPCLKUsingSingleDPP[DC__NUM_DPP__MAX]; double DISPCLKWithRamping; double DISPCLKWithoutRamping; double GlobalDPPCLK; - double MaxDispclk; double DISPCLKWithRampingRoundedToDFSGranularity; double DISPCLKWithoutRampingRoundedToDFSGranularity; double MaxDispclkRoundedToDFSGranularity; bool DCCEnabledAnyPlane; double ReturnBandwidthToDCN; - unsigned int SwathWidthY[DC__NUM_PIPES__MAX]; - unsigned int SwathWidthSingleDPPY[DC__NUM_PIPES__MAX]; - double BytePerPixelDETY[DC__NUM_PIPES__MAX]; - double BytePerPixelDETC[DC__NUM_PIPES__MAX]; - double ReadBandwidthPlaneLuma[DC__NUM_PIPES__MAX]; - double ReadBandwidthPlaneChroma[DC__NUM_PIPES__MAX]; + unsigned int SwathWidthY[DC__NUM_DPP__MAX]; + unsigned int SwathWidthSingleDPPY[DC__NUM_DPP__MAX]; + double BytePerPixelDETY[DC__NUM_DPP__MAX]; + double BytePerPixelDETC[DC__NUM_DPP__MAX]; + double ReadBandwidthPlaneLuma[DC__NUM_DPP__MAX]; + double ReadBandwidthPlaneChroma[DC__NUM_DPP__MAX]; unsigned int TotalActiveDPP; unsigned int TotalDCCActiveDPP; double UrgentRoundTripAndOutOfOrderLatency; - double DisplayPipeLineDeliveryTimeLuma[DC__NUM_PIPES__MAX]; // WM - double DisplayPipeLineDeliveryTimeChroma[DC__NUM_PIPES__MAX]; // WM - double LinesInDETY[DC__NUM_PIPES__MAX]; // WM - double LinesInDETC[DC__NUM_PIPES__MAX]; // WM - unsigned int LinesInDETYRoundedDownToSwath[DC__NUM_PIPES__MAX]; // WM - unsigned int LinesInDETCRoundedDownToSwath[DC__NUM_PIPES__MAX]; // WM - double FullDETBufferingTimeY[DC__NUM_PIPES__MAX]; // WM - double FullDETBufferingTimeC[DC__NUM_PIPES__MAX]; // WM + double DisplayPipeLineDeliveryTimeLuma[DC__NUM_DPP__MAX]; // WM + double DisplayPipeLineDeliveryTimeChroma[DC__NUM_DPP__MAX]; // WM + double LinesInDETY[DC__NUM_DPP__MAX]; // WM + double LinesInDETC[DC__NUM_DPP__MAX]; // WM + unsigned int LinesInDETYRoundedDownToSwath[DC__NUM_DPP__MAX]; // WM + unsigned int LinesInDETCRoundedDownToSwath[DC__NUM_DPP__MAX]; // WM + double FullDETBufferingTimeY[DC__NUM_DPP__MAX]; // WM + double FullDETBufferingTimeC[DC__NUM_DPP__MAX]; // WM double MinFullDETBufferingTime; double FrameTimeForMinFullDETBufferingTime; double AverageReadBandwidthGBytePerSecond; @@ -145,55 +149,54 @@ struct vba_vars_st { double EffectiveDETPlusLBLinesChroma; double UrgentLatencySupportUsLuma; double UrgentLatencySupportUsChroma; - double UrgentLatencySupportUs[DC__NUM_PIPES__MAX]; + double UrgentLatencySupportUs[DC__NUM_DPP__MAX]; unsigned int DSCFormatFactor; - unsigned int BlockHeight256BytesY[DC__NUM_PIPES__MAX]; - unsigned int BlockHeight256BytesC[DC__NUM_PIPES__MAX]; - unsigned int BlockWidth256BytesY[DC__NUM_PIPES__MAX]; - unsigned int BlockWidth256BytesC[DC__NUM_PIPES__MAX]; - double VInitPreFillY[DC__NUM_PIPES__MAX]; - double VInitPreFillC[DC__NUM_PIPES__MAX]; - unsigned int MaxNumSwathY[DC__NUM_PIPES__MAX]; - unsigned int MaxNumSwathC[DC__NUM_PIPES__MAX]; - double PrefetchSourceLinesY[DC__NUM_PIPES__MAX]; - double PrefetchSourceLinesC[DC__NUM_PIPES__MAX]; - double PixelPTEBytesPerRow[DC__NUM_PIPES__MAX]; - double MetaRowByte[DC__NUM_PIPES__MAX]; - bool PTEBufferSizeNotExceeded; // not used - unsigned int dpte_row_height[DC__NUM_PIPES__MAX]; - unsigned int dpte_row_height_chroma[DC__NUM_PIPES__MAX]; - unsigned int meta_row_height[DC__NUM_PIPES__MAX]; - unsigned int meta_row_height_chroma[DC__NUM_PIPES__MAX]; - - unsigned int MacroTileWidthY; - unsigned int MacroTileWidthC; - unsigned int MaxVStartupLines[DC__NUM_PIPES__MAX]; - double WritebackDelay[DC__NUM_PIPES__MAX]; + unsigned int BlockHeight256BytesY[DC__NUM_DPP__MAX]; + unsigned int BlockHeight256BytesC[DC__NUM_DPP__MAX]; + unsigned int BlockWidth256BytesY[DC__NUM_DPP__MAX]; + unsigned int BlockWidth256BytesC[DC__NUM_DPP__MAX]; + double VInitPreFillY[DC__NUM_DPP__MAX]; + double VInitPreFillC[DC__NUM_DPP__MAX]; + unsigned int MaxNumSwathY[DC__NUM_DPP__MAX]; + unsigned int MaxNumSwathC[DC__NUM_DPP__MAX]; + double PrefetchSourceLinesY[DC__NUM_DPP__MAX]; + double PrefetchSourceLinesC[DC__NUM_DPP__MAX]; + double PixelPTEBytesPerRow[DC__NUM_DPP__MAX]; + double MetaRowByte[DC__NUM_DPP__MAX]; + unsigned int dpte_row_height[DC__NUM_DPP__MAX]; + unsigned int dpte_row_height_chroma[DC__NUM_DPP__MAX]; + unsigned int meta_row_height[DC__NUM_DPP__MAX]; + unsigned int meta_row_height_chroma[DC__NUM_DPP__MAX]; + + unsigned int MacroTileWidthY[DC__NUM_DPP__MAX]; + unsigned int MacroTileWidthC[DC__NUM_DPP__MAX]; + unsigned int MaxVStartupLines[DC__NUM_DPP__MAX]; + double WritebackDelay[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; bool PrefetchModeSupported; - bool AllowDRAMClockChangeDuringVBlank[DC__NUM_PIPES__MAX]; - bool AllowDRAMSelfRefreshDuringVBlank[DC__NUM_PIPES__MAX]; - double RequiredPrefetchPixDataBW[DC__NUM_PIPES__MAX]; + bool AllowDRAMClockChangeDuringVBlank[DC__NUM_DPP__MAX]; + bool AllowDRAMSelfRefreshDuringVBlank[DC__NUM_DPP__MAX]; + double RequiredPrefetchPixDataBW[DC__NUM_DPP__MAX]; double XFCRemoteSurfaceFlipDelay; double TInitXFill; double TslvChk; double SrcActiveDrainRate; - double Tno_bw[DC__NUM_PIPES__MAX]; + double Tno_bw[DC__NUM_DPP__MAX]; bool ImmediateFlipSupported; - double prefetch_vm_bw[DC__NUM_PIPES__MAX]; - double prefetch_row_bw[DC__NUM_PIPES__MAX]; - bool ImmediateFlipSupportedForPipe[DC__NUM_PIPES__MAX]; + double prefetch_vm_bw[DC__NUM_DPP__MAX]; + double prefetch_row_bw[DC__NUM_DPP__MAX]; + bool ImmediateFlipSupportedForPipe[DC__NUM_DPP__MAX]; unsigned int VStartupLines; - double DisplayPipeLineDeliveryTimeLumaPrefetch[DC__NUM_PIPES__MAX]; - double DisplayPipeLineDeliveryTimeChromaPrefetch[DC__NUM_PIPES__MAX]; + double DisplayPipeLineDeliveryTimeLumaPrefetch[DC__NUM_DPP__MAX]; + double DisplayPipeLineDeliveryTimeChromaPrefetch[DC__NUM_DPP__MAX]; unsigned int ActiveDPPs; unsigned int LBLatencyHidingSourceLinesY; unsigned int LBLatencyHidingSourceLinesC; - double ActiveDRAMClockChangeLatencyMargin[DC__NUM_PIPES__MAX]; + double ActiveDRAMClockChangeLatencyMargin[DC__NUM_DPP__MAX]; double MinActiveDRAMClockChangeMargin; - double XFCSlaveVUpdateOffset[DC__NUM_PIPES__MAX]; - double XFCSlaveVupdateWidth[DC__NUM_PIPES__MAX]; - double XFCSlaveVReadyOffset[DC__NUM_PIPES__MAX]; + double XFCSlaveVUpdateOffset[DC__NUM_DPP__MAX]; + double XFCSlaveVupdateWidth[DC__NUM_DPP__MAX]; + double XFCSlaveVReadyOffset[DC__NUM_DPP__MAX]; double InitFillLevel; double FinalFillMargin; double FinalFillLevel; @@ -276,71 +279,71 @@ struct vba_vars_st { double DCFCLK; unsigned int NumberOfActivePlanes; - unsigned int ViewportWidth[DC__NUM_DPP]; - unsigned int ViewportHeight[DC__NUM_DPP]; - unsigned int ViewportYStartY[DC__NUM_DPP]; - unsigned int ViewportYStartC[DC__NUM_DPP]; - unsigned int PitchY[DC__NUM_DPP]; - unsigned int PitchC[DC__NUM_DPP]; - double HRatio[DC__NUM_DPP]; - double VRatio[DC__NUM_DPP]; - unsigned int htaps[DC__NUM_DPP]; - unsigned int vtaps[DC__NUM_DPP]; - unsigned int HTAPsChroma[DC__NUM_DPP]; - unsigned int VTAPsChroma[DC__NUM_DPP]; - unsigned int HTotal[DC__NUM_DPP]; - unsigned int VTotal[DC__NUM_DPP]; - unsigned int DPPPerPlane[DC__NUM_DPP]; - double PixelClock[DC__NUM_DPP]; - double PixelClockBackEnd[DC__NUM_DPP]; - double DPPCLK[DC__NUM_DPP]; - bool DCCEnable[DC__NUM_DPP]; - unsigned int DCCMetaPitchY[DC__NUM_DPP]; - enum scan_direction_class SourceScan[DC__NUM_DPP]; - enum source_format_class SourcePixelFormat[DC__NUM_DPP]; - bool WritebackEnable[DC__NUM_DPP]; - double WritebackDestinationWidth[DC__NUM_DPP]; - double WritebackDestinationHeight[DC__NUM_DPP]; - double WritebackSourceHeight[DC__NUM_DPP]; - enum source_format_class WritebackPixelFormat[DC__NUM_DPP]; - unsigned int WritebackLumaHTaps[DC__NUM_DPP]; - unsigned int WritebackLumaVTaps[DC__NUM_DPP]; - unsigned int WritebackChromaHTaps[DC__NUM_DPP]; - unsigned int WritebackChromaVTaps[DC__NUM_DPP]; - double WritebackHRatio[DC__NUM_DPP]; - double WritebackVRatio[DC__NUM_DPP]; - unsigned int HActive[DC__NUM_DPP]; - unsigned int VActive[DC__NUM_DPP]; - bool Interlace[DC__NUM_DPP]; - enum dm_swizzle_mode SurfaceTiling[DC__NUM_DPP]; - unsigned int ScalerRecoutWidth[DC__NUM_DPP]; - bool DynamicMetadataEnable[DC__NUM_DPP]; - unsigned int DynamicMetadataLinesBeforeActiveRequired[DC__NUM_DPP]; - unsigned int DynamicMetadataTransmittedBytes[DC__NUM_DPP]; - double DCCRate[DC__NUM_DPP]; - bool ODMCombineEnabled[DC__NUM_DPP]; - double OutputBpp[DC__NUM_DPP]; - unsigned int NumberOfDSCSlices[DC__NUM_DPP]; - bool DSCEnabled[DC__NUM_DPP]; - unsigned int DSCDelay[DC__NUM_DPP]; - unsigned int DSCInputBitPerComponent[DC__NUM_DPP]; - enum output_format_class OutputFormat[DC__NUM_DPP]; - enum output_encoder_class Output[DC__NUM_DPP]; - unsigned int BlendingAndTiming[DC__NUM_DPP]; + unsigned int ViewportWidth[DC__NUM_DPP__MAX]; + unsigned int ViewportHeight[DC__NUM_DPP__MAX]; + unsigned int ViewportYStartY[DC__NUM_DPP__MAX]; + unsigned int ViewportYStartC[DC__NUM_DPP__MAX]; + unsigned int PitchY[DC__NUM_DPP__MAX]; + unsigned int PitchC[DC__NUM_DPP__MAX]; + double HRatio[DC__NUM_DPP__MAX]; + double VRatio[DC__NUM_DPP__MAX]; + unsigned int htaps[DC__NUM_DPP__MAX]; + unsigned int vtaps[DC__NUM_DPP__MAX]; + unsigned int HTAPsChroma[DC__NUM_DPP__MAX]; + unsigned int VTAPsChroma[DC__NUM_DPP__MAX]; + unsigned int HTotal[DC__NUM_DPP__MAX]; + unsigned int VTotal[DC__NUM_DPP__MAX]; + unsigned int DPPPerPlane[DC__NUM_DPP__MAX]; + double PixelClock[DC__NUM_DPP__MAX]; + double PixelClockBackEnd[DC__NUM_DPP__MAX]; + double DPPCLK[DC__NUM_DPP__MAX]; + bool DCCEnable[DC__NUM_DPP__MAX]; + unsigned int DCCMetaPitchY[DC__NUM_DPP__MAX]; + enum scan_direction_class SourceScan[DC__NUM_DPP__MAX]; + enum source_format_class SourcePixelFormat[DC__NUM_DPP__MAX]; + bool WritebackEnable[DC__NUM_DPP__MAX]; + double WritebackDestinationWidth[DC__NUM_DPP__MAX]; + double WritebackDestinationHeight[DC__NUM_DPP__MAX]; + double WritebackSourceHeight[DC__NUM_DPP__MAX]; + enum source_format_class WritebackPixelFormat[DC__NUM_DPP__MAX]; + unsigned int WritebackLumaHTaps[DC__NUM_DPP__MAX]; + unsigned int WritebackLumaVTaps[DC__NUM_DPP__MAX]; + unsigned int WritebackChromaHTaps[DC__NUM_DPP__MAX]; + unsigned int WritebackChromaVTaps[DC__NUM_DPP__MAX]; + double WritebackHRatio[DC__NUM_DPP__MAX]; + double WritebackVRatio[DC__NUM_DPP__MAX]; + unsigned int HActive[DC__NUM_DPP__MAX]; + unsigned int VActive[DC__NUM_DPP__MAX]; + bool Interlace[DC__NUM_DPP__MAX]; + enum dm_swizzle_mode SurfaceTiling[DC__NUM_DPP__MAX]; + unsigned int ScalerRecoutWidth[DC__NUM_DPP__MAX]; + bool DynamicMetadataEnable[DC__NUM_DPP__MAX]; + unsigned int DynamicMetadataLinesBeforeActiveRequired[DC__NUM_DPP__MAX]; + unsigned int DynamicMetadataTransmittedBytes[DC__NUM_DPP__MAX]; + double DCCRate[DC__NUM_DPP__MAX]; + bool ODMCombineEnabled[DC__NUM_DPP__MAX]; + double OutputBpp[DC__NUM_DPP__MAX]; + unsigned int NumberOfDSCSlices[DC__NUM_DPP__MAX]; + bool DSCEnabled[DC__NUM_DPP__MAX]; + unsigned int DSCDelay[DC__NUM_DPP__MAX]; + unsigned int DSCInputBitPerComponent[DC__NUM_DPP__MAX]; + enum output_format_class OutputFormat[DC__NUM_DPP__MAX]; + enum output_encoder_class Output[DC__NUM_DPP__MAX]; + unsigned int BlendingAndTiming[DC__NUM_DPP__MAX]; bool SynchronizedVBlank; - unsigned int NumberOfCursors[DC__NUM_DPP]; - unsigned int CursorWidth[DC__NUM_DPP][DC__NUM_CURSOR]; - unsigned int CursorBPP[DC__NUM_DPP][DC__NUM_CURSOR]; - bool XFCEnabled[DC__NUM_DPP]; - bool ScalerEnabled[DC__NUM_DPP]; + unsigned int NumberOfCursors[DC__NUM_DPP__MAX]; + unsigned int CursorWidth[DC__NUM_DPP__MAX][DC__NUM_CURSOR]; + unsigned int CursorBPP[DC__NUM_DPP__MAX][DC__NUM_CURSOR]; + bool XFCEnabled[DC__NUM_DPP__MAX]; + bool ScalerEnabled[DC__NUM_DPP__MAX]; // Intermediates/Informational bool ImmediateFlipSupport; - unsigned int SwathHeightY[DC__NUM_DPP]; - unsigned int SwathHeightC[DC__NUM_DPP]; - unsigned int DETBufferSizeY[DC__NUM_DPP]; - unsigned int DETBufferSizeC[DC__NUM_DPP]; - unsigned int LBBitPerPixel[DC__NUM_DPP]; + unsigned int SwathHeightY[DC__NUM_DPP__MAX]; + unsigned int SwathHeightC[DC__NUM_DPP__MAX]; + unsigned int DETBufferSizeY[DC__NUM_DPP__MAX]; + unsigned int DETBufferSizeC[DC__NUM_DPP__MAX]; + unsigned int LBBitPerPixel[DC__NUM_DPP__MAX]; double LastPixelOfLineExtraWatermark; double TotalDataReadBandwidth; unsigned int TotalActiveWriteback; @@ -349,9 +352,9 @@ struct vba_vars_st { double BandwidthAvailableForImmediateFlip; unsigned int PrefetchMode; bool IgnoreViewportPositioning; - double PrefetchBandwidth[DC__NUM_DPP]; - bool ErrorResult[DC__NUM_DPP]; - double PDEAndMetaPTEBytesFrame[DC__NUM_DPP]; + double PrefetchBandwidth[DC__NUM_DPP__MAX]; + bool ErrorResult[DC__NUM_DPP__MAX]; + double PDEAndMetaPTEBytesFrame[DC__NUM_DPP__MAX]; // // Calculated dml_ml->vba.Outputs @@ -376,35 +379,200 @@ struct vba_vars_st { // used explicitly. They are fetched by tests and then possibly used. The // ultimate values to use are the ones specified by the parameters to DML double DISPCLK_calculated; - double DSCCLK_calculated[DC__NUM_DPP]; - double DPPCLK_calculated[DC__NUM_DPP]; + double DSCCLK_calculated[DC__NUM_DPP__MAX]; + double DPPCLK_calculated[DC__NUM_DPP__MAX]; - unsigned int VStartup[DC__NUM_DPP]; + unsigned int VStartup[DC__NUM_DPP__MAX]; unsigned int VStartupRequiredWhenNotEnoughTimeForDynamicMetadata; double ImmediateFlipBW; unsigned int TotImmediateFlipBytes; double TCalc; - double MinTTUVBlank[DC__NUM_DPP]; - double VRatioPrefetchY[DC__NUM_DPP]; - double VRatioPrefetchC[DC__NUM_DPP]; - double DSTXAfterScaler[DC__NUM_DPP]; - double DSTYAfterScaler[DC__NUM_DPP]; - - double DestinationLinesToRequestVMInVBlank[DC__NUM_DPP]; - double DestinationLinesToRequestRowInVBlank[DC__NUM_DPP]; - double DestinationLinesForPrefetch[DC__NUM_DPP]; - double DestinationLinesToRequestRowInImmediateFlip[DC__NUM_DPP]; - double DestinationLinesToRequestVMInImmediateFlip[DC__NUM_DPP]; - - double XFCTransferDelay[DC__NUM_DPP]; - double XFCPrechargeDelay[DC__NUM_DPP]; - double XFCRemoteSurfaceFlipLatency[DC__NUM_DPP]; - double XFCPrefetchMargin[DC__NUM_DPP]; - - display_e2e_pipe_params_st cache_pipes[DC__NUM_DPP]; + double MinTTUVBlank[DC__NUM_DPP__MAX]; + double VRatioPrefetchY[DC__NUM_DPP__MAX]; + double VRatioPrefetchC[DC__NUM_DPP__MAX]; + double DSTXAfterScaler[DC__NUM_DPP__MAX]; + double DSTYAfterScaler[DC__NUM_DPP__MAX]; + + double DestinationLinesToRequestVMInVBlank[DC__NUM_DPP__MAX]; + double DestinationLinesToRequestRowInVBlank[DC__NUM_DPP__MAX]; + double DestinationLinesForPrefetch[DC__NUM_DPP__MAX]; + double DestinationLinesToRequestRowInImmediateFlip[DC__NUM_DPP__MAX]; + double DestinationLinesToRequestVMInImmediateFlip[DC__NUM_DPP__MAX]; + + double XFCTransferDelay[DC__NUM_DPP__MAX]; + double XFCPrechargeDelay[DC__NUM_DPP__MAX]; + double XFCRemoteSurfaceFlipLatency[DC__NUM_DPP__MAX]; + double XFCPrefetchMargin[DC__NUM_DPP__MAX]; + + display_e2e_pipe_params_st cache_pipes[DC__NUM_DPP__MAX]; unsigned int cache_num_pipes; - unsigned int pipe_plane[DC__NUM_PIPES__MAX]; + unsigned int pipe_plane[DC__NUM_DPP__MAX]; + + /* vba mode support */ + /*inputs*/ + bool SupportGFX7CompatibleTilingIn32bppAnd64bpp; + double MaxHSCLRatio; + double MaxVSCLRatio; + unsigned int MaxNumWriteback; + bool WritebackLumaAndChromaScalingSupported; + bool Cursor64BppSupport; + double DCFCLKPerState[DC__VOLTAGE_STATES + 1]; + double FabricClockPerState[DC__VOLTAGE_STATES + 1]; + double SOCCLKPerState[DC__VOLTAGE_STATES + 1]; + double PHYCLKPerState[DC__VOLTAGE_STATES + 1]; + double MaxDppclk[DC__VOLTAGE_STATES + 1]; + double MaxDSCCLK[DC__VOLTAGE_STATES + 1]; + double DRAMSpeedPerState[DC__VOLTAGE_STATES + 1]; + double MaxDispclk[DC__VOLTAGE_STATES + 1]; + + /*outputs*/ + bool ScaleRatioAndTapsSupport; + bool SourceFormatPixelAndScanSupport; + unsigned int SwathWidthYSingleDPP[DC__NUM_DPP__MAX]; + double BytePerPixelInDETY[DC__NUM_DPP__MAX]; + double BytePerPixelInDETC[DC__NUM_DPP__MAX]; + double TotalReadBandwidthConsumedGBytePerSecond; + double ReadBandwidth[DC__NUM_DPP__MAX]; + double TotalWriteBandwidthConsumedGBytePerSecond; + double WriteBandwidth[DC__NUM_DPP__MAX]; + double TotalBandwidthConsumedGBytePerSecond; + bool DCCEnabledInAnyPlane; + bool WritebackLatencySupport; + bool WritebackModeSupport; + bool Writeback10bpc420Supported; + bool BandwidthSupport[DC__VOLTAGE_STATES + 1]; + unsigned int TotalNumberOfActiveWriteback; + double CriticalPoint; + double ReturnBWToDCNPerState; + double FabricAndDRAMBandwidthPerState[DC__VOLTAGE_STATES + 1]; + double ReturnBWPerState[DC__VOLTAGE_STATES + 1]; + double UrgentRoundTripAndOutOfOrderLatencyPerState[DC__VOLTAGE_STATES + 1]; + bool ODMCombineEnablePerState[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + bool PTEBufferSizeNotExceededY[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + bool PTEBufferSizeNotExceededC[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + bool PrefetchSupported[DC__VOLTAGE_STATES + 1]; + bool VRatioInPrefetchSupported[DC__VOLTAGE_STATES + 1]; + bool DISPCLK_DPPCLK_Support[DC__VOLTAGE_STATES + 1]; + bool TotalAvailablePipesSupport[DC__VOLTAGE_STATES + 1]; + bool UrgentLatencySupport[DC__VOLTAGE_STATES + 1]; + bool ModeSupport[DC__VOLTAGE_STATES + 1]; + bool DIOSupport[DC__VOLTAGE_STATES + 1]; + bool NotEnoughDSCUnits[DC__VOLTAGE_STATES + 1]; + bool DSCCLKRequiredMoreThanSupported[DC__VOLTAGE_STATES + 1]; + bool ROBSupport[DC__VOLTAGE_STATES + 1]; + bool PTEBufferSizeNotExceeded[DC__VOLTAGE_STATES + 1]; + bool RequiresDSC[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + bool IsErrorResult[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + bool ViewportSizeSupport[DC__VOLTAGE_STATES + 1]; + bool prefetch_vm_bw_valid; + bool prefetch_row_bw_valid; + bool NumberOfOTGSupport; + bool NonsupportedDSCInputBPC; + bool WritebackScaleRatioAndTapsSupport; + bool CursorSupport; + bool PitchSupport; + + double WritebackLineBufferLumaBufferSize; + double WritebackLineBufferChromaBufferSize; + double WritebackMinHSCLRatio; + double WritebackMinVSCLRatio; + double WritebackMaxHSCLRatio; + double WritebackMaxVSCLRatio; + double WritebackMaxHSCLTaps; + double WritebackMaxVSCLTaps; + unsigned int MaxNumDPP; + unsigned int MaxNumOTG; + double CursorBufferSize; + double CursorChunkSize; + unsigned int Mode; + double NoOfDPP[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + double OutputLinkDPLanes[DC__NUM_DPP__MAX]; + double SwathWidthYPerState[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + double SwathHeightYPerState[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + double SwathHeightCPerState[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + double UrgentLatencySupportUsPerState[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + double VRatioPreY[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + double VRatioPreC[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + double RequiredPrefetchPixelDataBW[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + double RequiredDPPCLK[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + double RequiredDISPCLK[DC__VOLTAGE_STATES + 1]; + double TotalNumberOfActiveDPP[DC__VOLTAGE_STATES + 1]; + double TotalNumberOfDCCActiveDPP[DC__VOLTAGE_STATES + 1]; + double PrefetchBW[DC__NUM_DPP__MAX]; + double PDEAndMetaPTEBytesPerFrame[DC__NUM_DPP__MAX]; + double MetaRowBytes[DC__NUM_DPP__MAX]; + double DPTEBytesPerRow[DC__NUM_DPP__MAX]; + double PrefetchLinesY[DC__NUM_DPP__MAX]; + double PrefetchLinesC[DC__NUM_DPP__MAX]; + unsigned int MaxNumSwY[DC__NUM_DPP__MAX]; + unsigned int MaxNumSwC[DC__NUM_DPP__MAX]; + double PrefillY[DC__NUM_DPP__MAX]; + double PrefillC[DC__NUM_DPP__MAX]; + double LineTimesForPrefetch[DC__NUM_DPP__MAX]; + double LinesForMetaPTE[DC__NUM_DPP__MAX]; + double LinesForMetaAndDPTERow[DC__NUM_DPP__MAX]; + double MinDPPCLKUsingSingleDPP[DC__NUM_DPP__MAX]; + double RequiresFEC[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + unsigned int OutputBppPerState[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + double DSCDelayPerState[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + unsigned int Read256BlockHeightY[DC__NUM_DPP__MAX]; + unsigned int Read256BlockWidthY[DC__NUM_DPP__MAX]; + unsigned int Read256BlockHeightC[DC__NUM_DPP__MAX]; + unsigned int Read256BlockWidthC[DC__NUM_DPP__MAX]; + unsigned int ImmediateFlipBytes[DC__NUM_DPP__MAX]; + double MaxSwathHeightY[DC__NUM_DPP__MAX]; + double MaxSwathHeightC[DC__NUM_DPP__MAX]; + double MinSwathHeightY[DC__NUM_DPP__MAX]; + double MinSwathHeightC[DC__NUM_DPP__MAX]; + double PSCL_FACTOR[DC__NUM_DPP__MAX]; + double PSCL_FACTOR_CHROMA[DC__NUM_DPP__MAX]; + double MaximumVStartup[DC__NUM_DPP__MAX]; + double AlignedDCCMetaPitch[DC__NUM_DPP__MAX]; + double AlignedYPitch[DC__NUM_DPP__MAX]; + double AlignedCPitch[DC__NUM_DPP__MAX]; + double MaximumSwathWidth[DC__NUM_DPP__MAX]; + double final_flip_bw[DC__NUM_DPP__MAX]; + double ImmediateFlipSupportedForState[DC__VOLTAGE_STATES + 1]; + + double WritebackLumaVExtra; + double WritebackChromaVExtra; + double WritebackRequiredDISPCLK; + double MaximumSwathWidthSupport; + double MaximumSwathWidthInDETBuffer; + double MaximumSwathWidthInLineBuffer; + double MaxDispclkRoundedDownToDFSGranularity; + double MaxDppclkRoundedDownToDFSGranularity; + double PlaneRequiredDISPCLKWithoutODMCombine; + double PlaneRequiredDISPCLK; + double TotalNumberOfActiveOTG; + double FECOverhead; + double EffectiveFECOverhead; + unsigned int Outbpp; + unsigned int OutbppDSC; + double TotalDSCUnitsRequired; + double bpp; + unsigned int slices; + double SwathWidthGranularityY; + double RoundedUpMaxSwathSizeBytesY; + double SwathWidthGranularityC; + double RoundedUpMaxSwathSizeBytesC; + double LinesInDETLuma; + double LinesInDETChroma; + double EffectiveDETLBLinesLuma; + double EffectiveDETLBLinesChroma; + double ProjectedDCFCLKDeepSleep; + double PDEAndMetaPTEBytesPerFrameY; + double PDEAndMetaPTEBytesPerFrameC; + unsigned int MetaRowBytesY; + unsigned int MetaRowBytesC; + unsigned int DPTEBytesPerRowC; + unsigned int DPTEBytesPerRowY; + double ExtraLatency; + double TimeCalc; + double TWait; + double MaximumReadBandwidthWithPrefetch; + double total_dcn_read_bw_with_flip; }; #endif /* _DML2_DISPLAY_MODE_VBA_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c index 9cbd415e508d..2af6d150cc46 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c @@ -35,6 +35,18 @@ double dml_max(double a, double b) { return (double) dcn_bw_max2(a, b); } +double dml_max3(double a, double b, double c) +{ + return dml_max(dml_max(a, b), c); +} +double dml_max4(double a, double b, double c, double d) +{ + return dml_max(dml_max(a, b), dml_max(c, d)); +} +double dml_max5(double a, double b, double c, double d, double e) +{ + return dml_max(dml_max4(a, b, c, d), e); +} double dml_ceil(double a, double granularity) { diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h index 19271e79abcc..ba01bbb007fc 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h @@ -36,6 +36,9 @@ double dml_min(double a, double b); double dml_max(double a, double b); +double dml_max3(double a, double b, double c); +double dml_max4(double a, double b, double c, double d); +double dml_max5(double a, double b, double c, double d, double e); bool dml_util_is_420(enum source_format_class sorce_format); double dml_ceil_ex(double x, double granularity); double dml_floor_ex(double x, double granularity); -- cgit From c81a351ab9c054e28544f31f715ad50cfe54089d Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 20 Sep 2017 17:50:02 -0400 Subject: drm/amd/display: extract global sync params from vba Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dml/display_mode_vba.c | 32 +++++++++++++++------- .../gpu/drm/amd/display/dc/dml/display_mode_vba.h | 3 ++ 2 files changed, 25 insertions(+), 10 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c index e1a3182d58b3..054b5067fc17 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c @@ -88,7 +88,10 @@ static bool CalculatePrefetchSchedule( double *VRatioPrefetchC, double *RequiredPrefetchPixDataBW, unsigned int *VStartupRequiredWhenNotEnoughTimeForDynamicMetadata, - double *Tno_bw); + double *Tno_bw, + unsigned int *VUpdateOffsetPix, + unsigned int *VUpdateWidthPix, + unsigned int *VReadyOffsetPix); static double RoundToDFSGranularityUp(double Clock, double VCOSpeed); static double RoundToDFSGranularityDown(double Clock, double VCOSpeed); static double CalculatePrefetchSourceLines( @@ -264,7 +267,7 @@ unsigned int dml_get_voltage_level( memcpy(mode_lib->vba.cache_pipes, pipes, sizeof(*pipes) * num_pipes); mode_lib->vba.cache_num_pipes = num_pipes; - if (need_recalculate) + if (need_recalculate && pipes[0].clks_cfg.dppclk_mhz != 0) recalculate(mode_lib); else { fetch_socbb_params(mode_lib); @@ -1066,10 +1069,13 @@ static bool CalculatePrefetchSchedule( double *VRatioPrefetchC, double *RequiredPrefetchPixDataBW, unsigned int *VStartupRequiredWhenNotEnoughTimeForDynamicMetadata, - double *Tno_bw) + double *Tno_bw, + unsigned int *VUpdateOffsetPix, + unsigned int *VUpdateWidthPix, + unsigned int *VReadyOffsetPix) { bool MyError = false; - unsigned int DPPCycles, DISPCLKCycles, VUpdateOffsetPix, VUpdateWidthPix, VReadyOffsetPix; + unsigned int DPPCycles, DISPCLKCycles; double DSTTotalPixelsAfterScaler, TotalRepeaterDelayTime; double Tdm, LineTime, Tsetup; double dst_y_prefetch_equ; @@ -1110,17 +1116,17 @@ static bool CalculatePrefetchSchedule( *DSTYAfterScaler = dml_floor(DSTTotalPixelsAfterScaler / HTotal, 1); *DSTXAfterScaler = DSTTotalPixelsAfterScaler - ((double) (*DSTYAfterScaler * HTotal)); - VUpdateOffsetPix = dml_ceil(HTotal / 4.0, 1); + *VUpdateOffsetPix = dml_ceil(HTotal / 4.0, 1); TotalRepeaterDelayTime = MaxInterDCNTileRepeaters * (2.0 / DPPCLK + 3.0 / DISPCLK); - VUpdateWidthPix = (14.0 / DCFClkDeepSleep + 12.0 / DPPCLK + TotalRepeaterDelayTime) + *VUpdateWidthPix = (14.0 / DCFClkDeepSleep + 12.0 / DPPCLK + TotalRepeaterDelayTime) * PixelClock; - VReadyOffsetPix = dml_max( + *VReadyOffsetPix = dml_max( 150.0 / DPPCLK, TotalRepeaterDelayTime + 20.0 / DCFClkDeepSleep + 10.0 / DPPCLK) * PixelClock; - Tsetup = (double) (VUpdateOffsetPix + VUpdateWidthPix + VReadyOffsetPix) / PixelClock; + Tsetup = (double) (*VUpdateOffsetPix + *VUpdateWidthPix + *VReadyOffsetPix) / PixelClock; LineTime = (double) HTotal / PixelClock; @@ -2710,7 +2716,10 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman &mode_lib->vba.VRatioPrefetchC[k], &mode_lib->vba.RequiredPrefetchPixDataBW[k], &mode_lib->vba.VStartupRequiredWhenNotEnoughTimeForDynamicMetadata, - &mode_lib->vba.Tno_bw[k]); + &mode_lib->vba.Tno_bw[k], + &mode_lib->vba.VUpdateOffsetPix[k], + &mode_lib->vba.VUpdateWidthPix[k], + &mode_lib->vba.VReadyOffsetPix[k]); if (mode_lib->vba.BlendingAndTiming[k] == k) { mode_lib->vba.VStartup[k] = dml_min( mode_lib->vba.VStartupLines, @@ -5805,7 +5814,10 @@ static void ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_ &mode_lib->vba.VRatioPreC[i][k], &mode_lib->vba.RequiredPrefetchPixelDataBW[i][k], &mode_lib->vba.VStartupRequiredWhenNotEnoughTimeForDynamicMetadata, - &mode_lib->vba.Tno_bw[k]); + &mode_lib->vba.Tno_bw[k], + &mode_lib->vba.VUpdateOffsetPix[k], + &mode_lib->vba.VUpdateWidthPix[k], + &mode_lib->vba.VReadyOffsetPix[k]); } for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { mode_lib->vba.cursor_bw[k] = mode_lib->vba.NumberOfCursors[k] diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h index 346ffea843c9..5758c3fd39ba 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h @@ -383,6 +383,9 @@ struct vba_vars_st { double DPPCLK_calculated[DC__NUM_DPP__MAX]; unsigned int VStartup[DC__NUM_DPP__MAX]; + unsigned int VUpdateOffsetPix[DC__NUM_DPP__MAX]; + unsigned int VUpdateWidthPix[DC__NUM_DPP__MAX]; + unsigned int VReadyOffsetPix[DC__NUM_DPP__MAX]; unsigned int VStartupRequiredWhenNotEnoughTimeForDynamicMetadata; double ImmediateFlipBW; -- cgit From 09f2317be4e86a60b481ce14da84c0752f848235 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 20 Sep 2017 18:32:51 -0400 Subject: drm/amd/display: change dml vba cursor count define to correct one Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c | 2 +- drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c index 054b5067fc17..a11b37c50d96 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c @@ -633,7 +633,7 @@ static void fetch_pipe_params(struct display_mode_lib *mode_lib) mode_lib->vba.NumberOfCursors[mode_lib->vba.NumberOfActivePlanes] = 0; // The DML spreadsheet assumes that the two cursors utilize the same amount of bandwidth. We'll // calculate things a little more accurately - for (k = 0; k < DC__NUM_CURSOR; ++k) { + for (k = 0; k < DC__NUM_CURSOR__MAX; ++k) { switch (k) { case 0: mode_lib->vba.CursorBPP[mode_lib->vba.NumberOfActivePlanes][0] = diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h index 5758c3fd39ba..63ad4a7bfeb5 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h @@ -332,8 +332,8 @@ struct vba_vars_st { unsigned int BlendingAndTiming[DC__NUM_DPP__MAX]; bool SynchronizedVBlank; unsigned int NumberOfCursors[DC__NUM_DPP__MAX]; - unsigned int CursorWidth[DC__NUM_DPP__MAX][DC__NUM_CURSOR]; - unsigned int CursorBPP[DC__NUM_DPP__MAX][DC__NUM_CURSOR]; + unsigned int CursorWidth[DC__NUM_DPP__MAX][DC__NUM_CURSOR__MAX]; + unsigned int CursorBPP[DC__NUM_DPP__MAX][DC__NUM_CURSOR__MAX]; bool XFCEnabled[DC__NUM_DPP__MAX]; bool ScalerEnabled[DC__NUM_DPP__MAX]; -- cgit From 0fc899b0f1d522efc171c09cb36ce1d27cd75de2 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Wed, 27 Sep 2017 17:28:11 -0400 Subject: drm/amd/display: Enable double buffer as per vertical interrupt enabled. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c | 11 +++++++++++ drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h | 4 ++++ 2 files changed, 15 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c index 7cd10cbc5497..8dbc82ff9b3a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c @@ -299,6 +299,17 @@ static void tgn10_program_timing( static void tgn10_unblank_crtc(struct timing_generator *tg) { struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + uint32_t vertical_interrupt_enable = 0; + + REG_GET(OTG_VERTICAL_INTERRUPT2_CONTROL, + OTG_VERTICAL_INTERRUPT2_INT_ENABLE, &vertical_interrupt_enable); + + /* temporary work around for vertical interrupt, once vertical interrupt enabled, + * this check will be removed. + */ + if (vertical_interrupt_enable) + REG_UPDATE(OTG_DOUBLE_BUFFER_CONTROL, + OTG_BLANK_DATA_DOUBLE_BUFFER_EN, 1); REG_UPDATE_2(OTG_BLANK_CONTROL, OTG_BLANK_DATA_EN, 0, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h index 0826d73b9809..7d4818d7aa31 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h @@ -65,6 +65,7 @@ SRI(OTG_NOM_VERT_POSITION, OTG, inst),\ SRI(OTG_BLACK_COLOR, OTG, inst),\ SRI(OTG_CLOCK_CONTROL, OTG, inst),\ + SRI(OTG_VERTICAL_INTERRUPT2_CONTROL, OTG, inst),\ SRI(OTG_VERTICAL_INTERRUPT2_POSITION, OTG, inst),\ SRI(OPTC_INPUT_CLOCK_CONTROL, ODM, inst),\ SRI(OPTC_DATA_SOURCE_SELECT, ODM, inst),\ @@ -117,6 +118,7 @@ struct dcn_tg_registers { uint32_t OTG_TEST_PATTERN_CONTROL; uint32_t OTG_TEST_PATTERN_COLOR; uint32_t OTG_CLOCK_CONTROL; + uint32_t OTG_VERTICAL_INTERRUPT2_CONTROL; uint32_t OTG_VERTICAL_INTERRUPT2_POSITION; uint32_t OPTC_INPUT_CLOCK_CONTROL; uint32_t OPTC_DATA_SOURCE_SELECT; @@ -196,6 +198,7 @@ struct dcn_tg_registers { SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_EN, mask_sh),\ SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_ON, mask_sh),\ SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_GATE_DIS, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT2_CONTROL, OTG_VERTICAL_INTERRUPT2_INT_ENABLE, mask_sh),\ SF(OTG0_OTG_VERTICAL_INTERRUPT2_POSITION, OTG_VERTICAL_INTERRUPT2_LINE_START, mask_sh),\ SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_EN, mask_sh),\ SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_ON, mask_sh),\ @@ -302,6 +305,7 @@ struct dcn_tg_registers { type OTG_CLOCK_EN;\ type OTG_CLOCK_ON;\ type OTG_CLOCK_GATE_DIS;\ + type OTG_VERTICAL_INTERRUPT2_INT_ENABLE;\ type OTG_VERTICAL_INTERRUPT2_LINE_START;\ type OPTC_INPUT_CLK_EN;\ type OPTC_INPUT_CLK_ON;\ -- cgit From 6a2b691f0985d16c16b70dbc4b5727afabde6ba9 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Tue, 26 Sep 2017 22:16:11 -0400 Subject: drm/amd/display: wrong VM setting cause invalid DF request from DCN fix typo in register field. we are lucky the shift/mask is the same, no behavior change add globals to experiment with using different VM settings Signed-off-by: Tony Cheng Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c | 11 +++++++---- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h | 2 ++ 2 files changed, 9 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index b61f41c61358..c09e65a0031a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -632,6 +632,9 @@ bool min10_is_flip_pending(struct mem_input *mem_input) return false; } +uint32_t aperture_default_system = 1; +uint32_t context0_default_system; /* = 0;*/ + static void min10_set_vm_system_aperture_settings(struct mem_input *mem_input, struct vm_system_aperture_param *apt) { @@ -645,7 +648,7 @@ static void min10_set_vm_system_aperture_settings(struct mem_input *mem_input, mc_vm_apt_high.quad_part = apt->sys_high.quad_part >> 12; REG_SET_2(DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, 0, - MC_VM_SYSTEM_APERTURE_DEFAULT_SYSTEM, 1, /* 1 = system physical memory */ + MC_VM_SYSTEM_APERTURE_DEFAULT_SYSTEM, aperture_default_system, /* 1 = system physical memory */ MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, mc_vm_apt_default.high_part); REG_SET(DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, 0, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, mc_vm_apt_default.low_part); @@ -684,9 +687,9 @@ static void min10_set_vm_context0_settings(struct mem_input *mem_input, VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB, vm0->pte_end.low_part); /* fault handling */ - REG_SET(DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, 0, - VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB, vm0->fault_default.high_part); - /* VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_SYSTEM, 0 */ + REG_SET_2(DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, 0, + VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, vm0->fault_default.high_part, + VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_SYSTEM, context0_default_system); REG_SET(DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, 0, VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, vm0->fault_default.low_part); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h index fdeb0e87463e..15231e86e6c6 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h @@ -369,6 +369,7 @@ struct dcn_mi_registers { MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB, VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB, VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_SYSTEM, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, MC_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, MC_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, mask_sh),\ @@ -522,6 +523,7 @@ struct dcn_mi_registers { type VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB;\ type VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB;\ type VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB;\ + type VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_SYSTEM;\ type VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB;\ type ENABLE_L1_TLB;\ type SYSTEM_ACCESS_MODE;\ -- cgit From 96687275555a166951d77d845a924ee07b854822 Mon Sep 17 00:00:00 2001 From: Roman Li Date: Wed, 27 Sep 2017 17:57:37 -0400 Subject: drm/amd/display: Fix hotplug after s3 resume. On S3 resume the HPD6 irq source was not reenabled due to loop boundary bug. Signed-off-by: Roman Li Reviewed-by: Mikita Lipski Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c index 52b6e4a91d8b..8de19ba5b2e3 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c @@ -462,7 +462,7 @@ int amdgpu_dm_irq_resume_early(struct amdgpu_device *adev) DRM_DEBUG_KMS("DM_IRQ: early resume\n"); /* re-enable short pulse interrupts HW interrupt */ - for (src = DC_IRQ_SOURCE_HPD1RX; src < DC_IRQ_SOURCE_HPD6RX + 1; src++) { + for (src = DC_IRQ_SOURCE_HPD1RX; src <= DC_IRQ_SOURCE_HPD6RX + 1; src++) { hnd_list_l = &adev->dm.irq_handler_list_low_tab[src].head; hnd_list_h = &adev->dm.irq_handler_list_high_tab[src]; if (!list_empty(hnd_list_l) || !list_empty(hnd_list_h)) @@ -488,7 +488,7 @@ int amdgpu_dm_irq_resume_late(struct amdgpu_device *adev) * Renable HW interrupt for HPD and only since FLIP and VBLANK * will be enabled from manage_dm_interrupts on enable CRTC. */ - for (src = DC_IRQ_SOURCE_HPD1; src < DC_IRQ_SOURCE_HPD6; src++) { + for (src = DC_IRQ_SOURCE_HPD1; src <= DC_IRQ_SOURCE_HPD6; src++) { hnd_list_l = &adev->dm.irq_handler_list_low_tab[src].head; hnd_list_h = &adev->dm.irq_handler_list_high_tab[src]; if (!list_empty(hnd_list_l) || !list_empty(hnd_list_h)) -- cgit From 3eab79163fcb0f7777440dfe360d2eedbbcc47b9 Mon Sep 17 00:00:00 2001 From: Shirish S Date: Tue, 26 Sep 2017 15:35:42 +0530 Subject: drm/amd/display: make FBC configurable option Currently FBC is guarded with ENABLE_FBC macro, which needs to be manually enabled in Makefile. This patch moves it to Kconfig so that there wont be any need to additional patch to be carried for enabling or disabling on every SoC. Signed-off-by: Shirish S Reviewed-by: Roman Li Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/Kconfig | 10 ++++++++++ drivers/gpu/drm/amd/display/dc/core/dc.c | 2 +- drivers/gpu/drm/amd/display/dc/dc.h | 4 ++-- drivers/gpu/drm/amd/display/dc/dc_types.h | 2 +- .../gpu/drm/amd/display/dc/dce110/dce110_compressor.c | 2 +- .../gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 16 ++++++++-------- drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c | 4 ++-- 7 files changed, 25 insertions(+), 15 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/Kconfig b/drivers/gpu/drm/amd/display/Kconfig index 6d1086d0a277..ec3285f65517 100644 --- a/drivers/gpu/drm/amd/display/Kconfig +++ b/drivers/gpu/drm/amd/display/Kconfig @@ -17,6 +17,16 @@ config DRM_AMD_DC_PRE_VEGA by default. This includes Polaris, Carrizo, Tonga, Bonaire, and Hawaii. +config DRM_AMD_DC_FBC + bool "AMD FBC - Enable Frame Buffer Compression" + depends on DRM_AMD_DC + help + Choose this option if you want to use frame buffer compression + support. + This is a power optimisation feature, check its availability + on your hardware before enabling this option. + + config DRM_AMD_DC_DCN1_0 bool "DCN 1.0 Raven family" depends on DRM_AMD_DC && X86 diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 3439bc46a4a2..a5c72dbc2dcc 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -507,7 +507,7 @@ static bool construct(struct dc *dc, dc_version = resource_parse_asic_id(init_params->asic_id); dc->ctx->dce_version = dc_version; -#ifdef ENABLE_FBC +#if defined(CONFIG_DRM_AMD_DC_FBC) dc->ctx->fbc_gpu_addr = init_params->fbc_gpu_addr; #endif /* Resource should construct all asic specific resources. diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index bf83459456a8..adadfad2bd51 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -258,7 +258,7 @@ struct dc { struct dm_pp_display_configuration prev_display_config; /* FBC compressor */ -#ifdef ENABLE_FBC +#if defined(CONFIG_DRM_AMD_DC_FBC) struct compressor *fbc_compressor; #endif }; @@ -293,7 +293,7 @@ struct dc_init_data { struct dc_config flags; uint32_t log_mask; -#ifdef ENABLE_FBC +#if defined(CONFIG_DRM_AMD_DC_FBC) uint64_t fbc_gpu_addr; #endif }; diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 4bd74fc6c782..a8698e399111 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -92,7 +92,7 @@ struct dc_context { bool created_bios; struct gpio_service *gpio_service; struct i2caux *i2caux; -#ifdef ENABLE_FBC +#if defined(CONFIG_DRM_AMD_DC_FBC) uint64_t fbc_gpu_addr; #endif }; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c index 3872febb4f6b..6923662413cd 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c @@ -514,7 +514,7 @@ void dce110_compressor_construct(struct dce110_compressor *compressor, compressor->base.lpt_channels_num = 0; compressor->base.attached_inst = 0; compressor->base.is_enabled = false; -#ifdef ENABLE_FBC +#if defined(CONFIG_DRM_AMD_DC_FBC) compressor->base.funcs = &dce110_compressor_funcs; #endif diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index a891e387ed7b..247e81806c4a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -34,7 +34,7 @@ #include "dce/dce_hwseq.h" #include "gpio_service_interface.h" -#ifdef ENABLE_FBC +#if defined(CONFIG_DRM_AMD_DC_FBC) #include "dce110_compressor.h" #endif @@ -1445,7 +1445,7 @@ static void power_down_all_hw_blocks(struct dc *dc) power_down_clock_sources(dc); -#ifdef ENABLE_FBC +#if defined(CONFIG_DRM_AMD_DC_FBC) if (dc->fbc_compressor) dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); #endif @@ -1618,7 +1618,7 @@ static void set_static_screen_control(struct pipe_ctx **pipe_ctx, if (events->cursor_update) value |= 0x2; -#ifdef ENABLE_FBC +#if defined(CONFIG_DRM_AMD_DC_FBC) value |= 0x84; #endif @@ -1748,7 +1748,7 @@ static void apply_min_clocks( } } -#ifdef ENABLE_FBC +#if defined(CONFIG_DRM_AMD_DC_FBC) /* * Check if FBC can be enabled @@ -1940,7 +1940,7 @@ enum dc_status dce110_apply_ctx_to_hw( set_safe_displaymarks(&context->res_ctx, dc->res_pool); -#ifdef ENABLE_FBC +#if defined(CONFIG_DRM_AMD_DC_FBC) if (dc->fbc_compressor) dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); #endif @@ -2124,7 +2124,7 @@ enum dc_status dce110_apply_ctx_to_hw( dcb->funcs->set_scratch_critical_state(dcb, false); -#ifdef ENABLE_FBC +#if defined(CONFIG_DRM_AMD_DC_FBC) if (dc->fbc_compressor) enable_fbc(dc, context); @@ -2533,7 +2533,7 @@ static void init_hw(struct dc *dc) abm->funcs->init_backlight(abm); abm->funcs->abm_init(abm); } -#ifdef ENABLE_FBC +#if defined(CONFIG_DRM_AMD_DC_FBC) if (dc->fbc_compressor) dc->fbc_compressor->funcs->power_up_fbc(dc->fbc_compressor); #endif @@ -2781,7 +2781,7 @@ static void dce110_program_front_end_for_pipe( program_scaler(dc, pipe_ctx); -#ifdef ENABLE_FBC +#if defined(CONFIG_DRM_AMD_DC_FBC) if (dc->fbc_compressor && old_pipe->stream) { if (plane_state->tiling_info.gfx8.array_mode == DC_ARRAY_LINEAR_GENERAL) dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 8e4ec61d59a4..db96d2b47ff1 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -52,7 +52,7 @@ #include "dce/dce_abm.h" #include "dce/dce_dmcu.h" -#ifdef ENABLE_FBC +#if defined(CONFIG_DRM_AMD_DC_FBC) #include "dce110/dce110_compressor.h" #endif @@ -1279,7 +1279,7 @@ static bool construct( } } -#ifdef ENABLE_FBC +#if defined(CONFIG_DRM_AMD_DC_FBC) dc->fbc_compressor = dce110_compressor_create(ctx); -- cgit From 50d4cfdc118122f58ffdb09607a57c621e24d777 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Thu, 28 Sep 2017 10:40:10 -0400 Subject: drm/amd/display: Program front end first when set mode. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 27 ++++++++++++++-------- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 5 ++-- 2 files changed, 20 insertions(+), 12 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index a5c72dbc2dcc..f9bac11d3950 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -763,16 +763,6 @@ static bool dc_commit_state_no_check(struct dc *dc, struct dc_state *context) if (!dcb->funcs->is_accelerated_mode(dcb)) dc->hwss.enable_accelerated_mode(dc); - dc->hwss.ready_shared_resources(dc, context); - - for (i = 0; i < dc->res_pool->pipe_count; i++) { - pipe = &context->res_ctx.pipe_ctx[i]; - dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, pipe); - } - result = dc->hwss.apply_ctx_to_hw(dc, context); - - program_timing_sync(dc, context); - for (i = 0; i < context->stream_count; i++) { const struct dc_sink *sink = context->streams[i]->sink; @@ -798,6 +788,13 @@ static bool dc_commit_state_no_check(struct dc *dc, struct dc_state *context) } } + for (j = 0; j < MAX_PIPES; j++) { + pipe = &context->res_ctx.pipe_ctx[j]; + + if (!pipe->top_pipe && pipe->stream == context->streams[i]) + dc->hwss.pipe_control_lock(dc, pipe, false); + } + CONN_MSG_MODE(sink->link, "{%dx%d, %dx%d@%dKhz}", context->streams[i]->timing.h_addressable, context->streams[i]->timing.v_addressable, @@ -806,6 +803,16 @@ static bool dc_commit_state_no_check(struct dc *dc, struct dc_state *context) context->streams[i]->timing.pix_clk_khz); } + dc->hwss.ready_shared_resources(dc, context); + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + pipe = &context->res_ctx.pipe_ctx[i]; + dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, pipe); + } + result = dc->hwss.apply_ctx_to_hw(dc, context); + + program_timing_sync(dc, context); + dc_enable_stereo(dc, context, dc_streams, context->stream_count); dc_release_state(dc->current_state); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 86cfab33feea..84d9d202d3b5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2283,8 +2283,6 @@ static void update_dchubp_dpp( */ REG_UPDATE(DCHUBP_CNTL[pipe_ctx->pipe_idx], HUBP_VTG_SEL, pipe_ctx->stream_res.tg->inst); - dc->hwss.update_plane_addr(dc, pipe_ctx); - mi->funcs->mem_input_setup( mi, &pipe_ctx->dlg_regs, @@ -2353,6 +2351,8 @@ static void update_dchubp_dpp( &plane_state->dcc, plane_state->horizontal_mirror); + dc->hwss.update_plane_addr(dc, pipe_ctx); + if (is_pipe_tree_visible(pipe_ctx)) mi->funcs->set_blank(mi, false); } @@ -2556,6 +2556,7 @@ static void dcn10_apply_ctx_for_surface( old_pipe_ctx->top_pipe = NULL; old_pipe_ctx->bottom_pipe = NULL; old_pipe_ctx->plane_state = NULL; + old_pipe_ctx->stream = NULL; dm_logger_write(dc->ctx->logger, LOG_DC, "Reset mpcc for pipe %d\n", -- cgit From 4176664b1fc8aa052f886037590cac4fb0dd8afb Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Wed, 27 Sep 2017 23:23:16 -0400 Subject: drm/amd/display: audio dynamic resource acquired related Signed-off-by: Charlene Liu Reviewed-by: Anthony Koo Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 4 ++-- drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 24 ++++++++++++++++------ drivers/gpu/drm/amd/display/dc/dc.h | 1 + .../amd/display/dc/dce110/dce110_hw_sequencer.c | 12 +++++++++-- .../amd/display/dc/dce110/dce110_hw_sequencer.h | 2 +- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 2 +- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 7 ++++++- drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 3 ++- drivers/gpu/drm/amd/display/dc/inc/resource.h | 5 +++++ 10 files changed, 47 insertions(+), 15 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index e414e4770789..2d59f77fa9a2 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -2323,14 +2323,14 @@ void core_link_enable_stream( allocate_mst_payload(pipe_ctx); } -void core_link_disable_stream(struct pipe_ctx *pipe_ctx) +void core_link_disable_stream(struct pipe_ctx *pipe_ctx, int option) { struct dc *core_dc = pipe_ctx->stream->ctx->dc; if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) deallocate_mst_payload(pipe_ctx); - core_dc->hwss.disable_stream(pipe_ctx); + core_dc->hwss.disable_stream(pipe_ctx, option); disable_link(pipe_ctx->stream->sink->link, pipe_ctx->stream->signal); } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 34b6d1cb151e..9a33b471270a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -282,7 +282,7 @@ void dp_retrain_link_dp_test(struct dc_link *link, dp_receiver_power_ctrl(link, false); - link->dc->hwss.disable_stream(&pipes[i]); + link->dc->hwss.disable_stream(&pipes[i], KEEP_ACQUIRED_RESOURCE); link->link_enc->funcs->disable_output( link->link_enc, diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index bbfec7cb2ad1..68c613229a10 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -242,7 +242,10 @@ bool resource_construct( pool->stream_enc_count++; } } - + dc->caps.dynamic_audio = false; + if (pool->audio_count < pool->stream_enc_count) { + dc->caps.dynamic_audio = true; + } for (i = 0; i < num_virtual_links; i++) { pool->stream_enc[pool->stream_enc_count] = virtual_stream_encoder_create( @@ -1330,7 +1333,7 @@ static void update_stream_engine_usage( } /* TODO: release audio object */ -static void update_audio_usage( +void update_audio_usage( struct resource_context *res_ctx, const struct resource_pool *pool, struct audio *audio, @@ -1414,12 +1417,21 @@ static struct audio *find_first_free_audio( const struct resource_pool *pool) { int i; - for (i = 0; i < pool->audio_count; i++) { - if (res_ctx->is_audio_acquired[i] == false) { - return pool->audios[i]; + if (pool->audio_count >= pool->stream_enc_count) { + for (i = 0; i < pool->audio_count; i++) { + if ((res_ctx->is_audio_acquired[i] == false) && (res_ctx->is_stream_enc_acquired[i] == true)) { + /*we have enough audio endpoint, no need to do dynamic distribution*/ + return pool->audios[i]; + } } - } + } else { /*first come first serve*/ + for (i = 0; i < pool->audio_count; i++) { + if (res_ctx->is_audio_acquired[i] == false) { + return pool->audios[i]; + } + } + } return 0; } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index adadfad2bd51..2517fb821fff 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -58,6 +58,7 @@ struct dc_caps { uint32_t i2c_speed_in_khz; unsigned int max_cursor_size; bool dcc_const_color; + bool dynamic_audio; }; struct dc_dcc_surface_param { diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 247e81806c4a..453d2ffd5c4a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -985,10 +985,11 @@ void hwss_edp_backlight_control( link_transmitter_control(link->dc->ctx->dc_bios, &cntl); } -void dce110_disable_stream(struct pipe_ctx *pipe_ctx) +void dce110_disable_stream(struct pipe_ctx *pipe_ctx, int option) { struct dc_stream_state *stream = pipe_ctx->stream; struct dc_link *link = stream->sink->link; + struct dc *dc = pipe_ctx->stream->ctx->dc; if (pipe_ctx->stream_res.audio) { pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio); @@ -999,6 +1000,13 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) else pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_disable( pipe_ctx->stream_res.stream_enc); + /*don't free audio if it is from retrain or internal disable stream*/ + if (option == FREE_ACQUIRED_RESOURCE && dc->caps.dynamic_audio == true) { + /*we have to dynamic arbitrate the audio endpoints*/ + pipe_ctx->stream_res.audio = NULL; + /*we free the resource, need reset is_audio_acquired*/ + update_audio_usage(&dc->current_state->res_ctx, dc->res_pool, pipe_ctx->stream_res.audio, false); + } /* TODO: notify audio driver for if audio modes list changed * add audio mode list change flag */ @@ -1871,7 +1879,7 @@ static void dce110_reset_hw_ctx_wrap( pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) { struct clock_source *old_clk = pipe_ctx_old->clock_source; - core_link_disable_stream(pipe_ctx_old); + core_link_disable_stream(pipe_ctx_old, FREE_ACQUIRED_RESOURCE); pipe_ctx_old->stream_res.tg->funcs->set_blank(pipe_ctx_old->stream_res.tg, true); if (!hwss_wait_for_blank_complete(pipe_ctx_old->stream_res.tg)) { dm_error("DC: failed to blank crtc!\n"); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h index a1e964af60ac..4d72bb99be93 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h @@ -47,7 +47,7 @@ void dce110_set_displaymarks( void dce110_enable_stream(struct pipe_ctx *pipe_ctx); -void dce110_disable_stream(struct pipe_ctx *pipe_ctx); +void dce110_disable_stream(struct pipe_ctx *pipe_ctx, int option); void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, struct dc_link_settings *link_settings); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 84d9d202d3b5..072c48188b79 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1025,7 +1025,7 @@ static void reset_back_end_for_pipe( * which is used by otg. Move disable_link after disable_crtc */ if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) - core_link_disable_stream(pipe_ctx); + core_link_disable_stream(pipe_ctx, FREE_ACQUIRED_RESOURCE); /* by upper caller loop, parent pipe: pipe0, will be reset last. * back end share by all pipes and will be disable only when disable diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index ff23f268fe02..5230dddc8617 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -58,6 +58,11 @@ struct link_init_data { TODO: remove it when DC is complete. */ }; +enum { + FREE_ACQUIRED_RESOURCE = 0, + KEEP_ACQUIRED_RESOURCE = 1, +}; + struct dc_link *link_create(const struct link_init_data *init_params); void link_destroy(struct dc_link **link); @@ -72,7 +77,7 @@ void core_link_enable_stream( struct dc_state *state, struct pipe_ctx *pipe_ctx); -void core_link_disable_stream(struct pipe_ctx *pipe_ctx); +void core_link_disable_stream(struct pipe_ctx *pipe_ctx, int option); void core_link_set_avmute(struct pipe_ctx *pipe_ctx, bool enable); /********** DAL Core*********************/ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index bf3ab5d7398e..8734689a9245 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -134,7 +134,8 @@ struct hw_sequencer_funcs { void (*enable_stream)(struct pipe_ctx *pipe_ctx); - void (*disable_stream)(struct pipe_ctx *pipe_ctx); + void (*disable_stream)(struct pipe_ctx *pipe_ctx, + int option); void (*unblank_stream)(struct pipe_ctx *pipe_ctx, struct dc_link_settings *link_settings); diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index 614bb691ab59..5467332faf7b 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -164,4 +164,9 @@ bool pipe_need_reprogram( void resource_build_bit_depth_reduction_params(struct dc_stream_state *stream, struct bit_depth_reduction_params *fmt_bit_depth); +void update_audio_usage( + struct resource_context *res_ctx, + const struct resource_pool *pool, + struct audio *audio, + bool acquired); #endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_RESOURCE_H_ */ -- cgit From b7901be0ed5d43525ac2c3fc2a3f9a0cdc5d069c Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Thu, 28 Sep 2017 14:54:58 -0400 Subject: drm/amd/display: renaming mem input to hubp Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c | 76 +++++++++++----------- .../gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h | 24 +++---- 2 files changed, 50 insertions(+), 50 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index c09e65a0031a..46086bec9982 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -38,7 +38,7 @@ #define FN(reg_name, field_name) \ mi->mi_shift->field_name, mi->mi_mask->field_name -void min10_set_blank(struct mem_input *mem_input, bool blank) +void hubp1_set_blank(struct mem_input *mem_input, bool blank) { struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); uint32_t blank_en = blank ? 1 : 0; @@ -56,7 +56,7 @@ void min10_set_blank(struct mem_input *mem_input, bool blank) } } -static void min10_set_hubp_blank_en(struct mem_input *mem_input, bool blank) +static void hubp1_set_hubp_blank_en(struct mem_input *mem_input, bool blank) { struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); uint32_t blank_en = blank ? 1 : 0; @@ -64,7 +64,7 @@ static void min10_set_hubp_blank_en(struct mem_input *mem_input, bool blank) REG_UPDATE(DCHUBP_CNTL, HUBP_BLANK_EN, blank_en); } -static void min10_vready_workaround(struct mem_input *mem_input, +static void hubp1_vready_workaround(struct mem_input *mem_input, struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest) { uint32_t value = 0; @@ -87,7 +87,7 @@ static void min10_vready_workaround(struct mem_input *mem_input, REG_WRITE(HUBPREQ_DEBUG_DB, value); } -void min10_program_tiling( +void hubp1_program_tiling( struct dcn10_mem_input *mi, const union dc_tiling_info *info, const enum surface_pixel_format pixel_format) @@ -107,7 +107,7 @@ void min10_program_tiling( PIPE_ALIGNED, info->gfx9.pipe_aligned); } -void min10_program_size_and_rotation( +void hubp1_program_size_and_rotation( struct dcn10_mem_input *mi, enum dc_rotation_angle rotation, enum surface_pixel_format format, @@ -169,7 +169,7 @@ void min10_program_size_and_rotation( H_MIRROR_EN, mirror); } -void min10_program_pixel_format( +void hubp1_program_pixel_format( struct dcn10_mem_input *mi, enum surface_pixel_format format) { @@ -245,7 +245,7 @@ void min10_program_pixel_format( /* don't see the need of program the xbar in DCN 1.0 */ } -bool min10_program_surface_flip_and_addr( +bool hubp1_program_surface_flip_and_addr( struct mem_input *mem_input, const struct dc_plane_address *address, bool flip_immediate) @@ -395,7 +395,7 @@ bool min10_program_surface_flip_and_addr( return true; } -void min10_dcc_control(struct mem_input *mem_input, bool enable, +void hubp1_dcc_control(struct mem_input *mem_input, bool enable, bool independent_64b_blks) { uint32_t dcc_en = enable ? 1 : 0; @@ -407,7 +407,7 @@ void min10_dcc_control(struct mem_input *mem_input, bool enable, PRIMARY_SURFACE_DCC_IND_64B_BLK, dcc_ind_64b_blk); } -static void min10_program_surface_config( +static void hubp1_program_surface_config( struct mem_input *mem_input, enum surface_pixel_format format, union dc_tiling_info *tiling_info, @@ -418,14 +418,14 @@ static void min10_program_surface_config( { struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); - min10_dcc_control(mem_input, dcc->enable, dcc->grph.independent_64b_blks); - min10_program_tiling(mi, tiling_info, format); - min10_program_size_and_rotation( + hubp1_dcc_control(mem_input, dcc->enable, dcc->grph.independent_64b_blks); + hubp1_program_tiling(mi, tiling_info, format); + hubp1_program_size_and_rotation( mi, rotation, format, plane_size, dcc, horizontal_mirror); - min10_program_pixel_format(mi, format); + hubp1_program_pixel_format(mi, format); } -void min10_program_requestor( +void hubp1_program_requestor( struct mem_input *mem_input, struct _vcs_dpi_display_rq_regs_st *rq_regs) { @@ -459,7 +459,7 @@ void min10_program_requestor( } -void min10_program_deadline( +void hubp1_program_deadline( struct mem_input *mem_input, struct _vcs_dpi_display_dlg_regs_st *dlg_attr, struct _vcs_dpi_display_ttu_regs_st *ttu_attr) @@ -580,7 +580,7 @@ void min10_program_deadline( ttu_attr->refcyc_per_req_delivery_pre_c); } -static void min10_setup( +static void hubp1_setup( struct mem_input *mem_input, struct _vcs_dpi_display_dlg_regs_st *dlg_attr, struct _vcs_dpi_display_ttu_regs_st *ttu_attr, @@ -590,12 +590,12 @@ static void min10_setup( /* otg is locked when this func is called. Register are double buffered. * disable the requestors is not needed */ - min10_program_requestor(mem_input, rq_regs); - min10_program_deadline(mem_input, dlg_attr, ttu_attr); - min10_vready_workaround(mem_input, pipe_dest); + hubp1_program_requestor(mem_input, rq_regs); + hubp1_program_deadline(mem_input, dlg_attr, ttu_attr); + hubp1_vready_workaround(mem_input, pipe_dest); } -void min10_program_display_marks( +void hubp1_program_display_marks( struct mem_input *mem_input, struct dce_watermarks nbp, struct dce_watermarks stutter, @@ -607,7 +607,7 @@ void min10_program_display_marks( */ } -bool min10_is_flip_pending(struct mem_input *mem_input) +bool hubp1_is_flip_pending(struct mem_input *mem_input) { uint32_t flip_pending = 0; struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); @@ -635,7 +635,7 @@ bool min10_is_flip_pending(struct mem_input *mem_input) uint32_t aperture_default_system = 1; uint32_t context0_default_system; /* = 0;*/ -static void min10_set_vm_system_aperture_settings(struct mem_input *mem_input, +static void hubp1_set_vm_system_aperture_settings(struct mem_input *mem_input, struct vm_system_aperture_param *apt) { struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); @@ -664,7 +664,7 @@ static void min10_set_vm_system_aperture_settings(struct mem_input *mem_input, MC_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, mc_vm_apt_high.low_part); } -static void min10_set_vm_context0_settings(struct mem_input *mem_input, +static void hubp1_set_vm_context0_settings(struct mem_input *mem_input, const struct vm_context0_param *vm0) { struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); @@ -848,7 +848,7 @@ static enum cursor_lines_per_chunk ippn10_get_lines_per_chunk( return line_per_chunk; } -void ippn10_cursor_set_attributes( +void hubp1_cursor_set_attributes( struct mem_input *mem_input, const struct dc_cursor_attributes *attr) { @@ -876,7 +876,7 @@ void ippn10_cursor_set_attributes( attr->color_format); } -void ippn10_cursor_set_position( +void hubp1_cursor_set_position( struct mem_input *mem_input, const struct dc_cursor_position *pos, const struct dc_cursor_mi_param *param) @@ -913,7 +913,7 @@ void ippn10_cursor_set_position( cur_en = 0; /* not visible beyond left edge*/ if (cur_en && REG_READ(CURSOR_SURFACE_ADDRESS) == 0) - ippn10_cursor_set_attributes(mem_input, &mem_input->curs_attr); + hubp1_cursor_set_attributes(mem_input, &mem_input->curs_attr); REG_UPDATE(CURSOR_CONTROL, CURSOR_ENABLE, cur_en); @@ -931,21 +931,21 @@ void ippn10_cursor_set_position( } static struct mem_input_funcs dcn10_mem_input_funcs = { - .mem_input_program_display_marks = min10_program_display_marks, + .mem_input_program_display_marks = hubp1_program_display_marks, .mem_input_program_surface_flip_and_addr = - min10_program_surface_flip_and_addr, + hubp1_program_surface_flip_and_addr, .mem_input_program_surface_config = - min10_program_surface_config, - .mem_input_is_flip_pending = min10_is_flip_pending, - .mem_input_setup = min10_setup, - .mem_input_set_vm_system_aperture_settings = min10_set_vm_system_aperture_settings, - .mem_input_set_vm_context0_settings = min10_set_vm_context0_settings, - .set_blank = min10_set_blank, - .dcc_control = min10_dcc_control, + hubp1_program_surface_config, + .mem_input_is_flip_pending = hubp1_is_flip_pending, + .mem_input_setup = hubp1_setup, + .mem_input_set_vm_system_aperture_settings = hubp1_set_vm_system_aperture_settings, + .mem_input_set_vm_context0_settings = hubp1_set_vm_context0_settings, + .set_blank = hubp1_set_blank, + .dcc_control = hubp1_dcc_control, .mem_program_viewport = min_set_viewport, - .set_hubp_blank_en = min10_set_hubp_blank_en, - .set_cursor_attributes = ippn10_cursor_set_attributes, - .set_cursor_position = ippn10_cursor_set_position, + .set_hubp_blank_en = hubp1_set_hubp_blank_en, + .set_cursor_attributes = hubp1_cursor_set_attributes, + .set_cursor_position = hubp1_cursor_set_position, }; /*****************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h index 15231e86e6c6..653875285b70 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h @@ -591,20 +591,20 @@ struct dcn10_mem_input { const struct dcn_mi_mask *mi_mask; }; -void min10_program_deadline( +void hubp1_program_deadline( struct mem_input *mem_input, struct _vcs_dpi_display_dlg_regs_st *dlg_attr, struct _vcs_dpi_display_ttu_regs_st *ttu_attr); -void min10_program_requestor( +void hubp1_program_requestor( struct mem_input *mem_input, struct _vcs_dpi_display_rq_regs_st *rq_regs); -void min10_program_pixel_format( +void hubp1_program_pixel_format( struct dcn10_mem_input *mi, enum surface_pixel_format format); -void min10_program_size_and_rotation( +void hubp1_program_size_and_rotation( struct dcn10_mem_input *mi, enum dc_rotation_angle rotation, enum surface_pixel_format format, @@ -612,39 +612,39 @@ void min10_program_size_and_rotation( struct dc_plane_dcc_param *dcc, bool horizontal_mirror); -void min10_program_tiling( +void hubp1_program_tiling( struct dcn10_mem_input *mi, const union dc_tiling_info *info, const enum surface_pixel_format pixel_format); -void min10_dcc_control(struct mem_input *mem_input, +void hubp1_dcc_control(struct mem_input *mem_input, bool enable, bool independent_64b_blks); -void min10_program_display_marks( +void hubp1_program_display_marks( struct mem_input *mem_input, struct dce_watermarks nbp, struct dce_watermarks stutter, struct dce_watermarks urgent, uint32_t total_dest_line_time_ns); -bool min10_program_surface_flip_and_addr( +bool hubp1_program_surface_flip_and_addr( struct mem_input *mem_input, const struct dc_plane_address *address, bool flip_immediate); -bool min10_is_flip_pending(struct mem_input *mem_input); +bool hubp1_is_flip_pending(struct mem_input *mem_input); -void ippn10_cursor_set_attributes( +void hubp1_cursor_set_attributes( struct mem_input *mem_input, const struct dc_cursor_attributes *attr); -void ippn10_cursor_set_position( +void hubp1_cursor_set_position( struct mem_input *mem_input, const struct dc_cursor_position *pos, const struct dc_cursor_mi_param *param); -void min10_set_blank(struct mem_input *mem_input, bool blank); +void hubp1_set_blank(struct mem_input *mem_input, bool blank); void min_set_viewport(struct mem_input *mem_input, const struct rect *viewport, -- cgit From 66bfd4fd17737d0a644fa74e0cb309c0daf8fb22 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Thu, 28 Sep 2017 15:38:01 -0400 Subject: drm/amd/display: arbitration find the matching dig-az first. [Description] this change is in branch already. without this change, after resume, az_inst might swapped. Signed-off-by: Charlene Liu Reviewed-by: Anthony Koo Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 68c613229a10..c31dccdc3d2e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1417,19 +1417,15 @@ static struct audio *find_first_free_audio( const struct resource_pool *pool) { int i; - if (pool->audio_count >= pool->stream_enc_count) { - for (i = 0; i < pool->audio_count; i++) { - if ((res_ctx->is_audio_acquired[i] == false) && (res_ctx->is_stream_enc_acquired[i] == true)) { - /*we have enough audio endpoint, no need to do dynamic distribution*/ - return pool->audios[i]; - } + for (i = 0; i < pool->audio_count; i++) { + if ((res_ctx->is_audio_acquired[i] == false) && (res_ctx->is_stream_enc_acquired[i] == true)) { + return pool->audios[i]; } - } else { /*first come first serve*/ - for (i = 0; i < pool->audio_count; i++) { - if (res_ctx->is_audio_acquired[i] == false) { - - return pool->audios[i]; - } + } + /*not found the matching one, first come first serve*/ + for (i = 0; i < pool->audio_count; i++) { + if (res_ctx->is_audio_acquired[i] == false) { + return pool->audios[i]; } } return 0; -- cgit From e4b3b5ccd9835bafab67851a7cc759c9250a8a9d Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Thu, 28 Sep 2017 16:09:56 -0400 Subject: drm/amd/display: Making hubp1_program_surface_config public Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c | 3 ++- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h | 9 +++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index 46086bec9982..2336da54000c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -407,7 +407,7 @@ void hubp1_dcc_control(struct mem_input *mem_input, bool enable, PRIMARY_SURFACE_DCC_IND_64B_BLK, dcc_ind_64b_blk); } -static void hubp1_program_surface_config( +void hubp1_program_surface_config( struct mem_input *mem_input, enum surface_pixel_format format, union dc_tiling_info *tiling_info, @@ -970,3 +970,4 @@ void dcn10_mem_input_construct( mi->base.mpcc_id = 0xf; } + diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h index 653875285b70..5c5eed5c95d5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h @@ -591,6 +591,15 @@ struct dcn10_mem_input { const struct dcn_mi_mask *mi_mask; }; +void hubp1_program_surface_config( + struct mem_input *mem_input, + enum surface_pixel_format format, + union dc_tiling_info *tiling_info, + union plane_size *plane_size, + enum dc_rotation_angle rotation, + struct dc_plane_dcc_param *dcc, + bool horizontal_mirror); + void hubp1_program_deadline( struct mem_input *mem_input, struct _vcs_dpi_display_dlg_regs_st *dlg_attr, -- cgit From c018b04b7c17e0814bc75b09d782204d73c64b1b Mon Sep 17 00:00:00 2001 From: Roman Li Date: Thu, 28 Sep 2017 12:57:21 -0400 Subject: drm/amd/display: Fix irq enable/disable on resume. Fixing loop boundaries in irq enable/disable on resume. Signed-off-by: Roman Li Reviewed-by: Mikita Lipski Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c index 8de19ba5b2e3..b9e4d3831001 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c @@ -435,7 +435,7 @@ int amdgpu_dm_irq_suspend(struct amdgpu_device *adev) * Disable HW interrupt for HPD and HPDRX only since FLIP and VBLANK * will be disabled from manage_dm_interrupts on disable CRTC. */ - for (src = DC_IRQ_SOURCE_HPD1; src < DC_IRQ_SOURCE_HPD6RX; src++) { + for (src = DC_IRQ_SOURCE_HPD1; src <= DC_IRQ_SOURCE_HPD6RX; src++) { hnd_list_l = &adev->dm.irq_handler_list_low_tab[src].head; hnd_list_h = &adev->dm.irq_handler_list_high_tab[src]; if (!list_empty(hnd_list_l) || !list_empty(hnd_list_h)) @@ -462,7 +462,7 @@ int amdgpu_dm_irq_resume_early(struct amdgpu_device *adev) DRM_DEBUG_KMS("DM_IRQ: early resume\n"); /* re-enable short pulse interrupts HW interrupt */ - for (src = DC_IRQ_SOURCE_HPD1RX; src <= DC_IRQ_SOURCE_HPD6RX + 1; src++) { + for (src = DC_IRQ_SOURCE_HPD1RX; src <= DC_IRQ_SOURCE_HPD6RX; src++) { hnd_list_l = &adev->dm.irq_handler_list_low_tab[src].head; hnd_list_h = &adev->dm.irq_handler_list_high_tab[src]; if (!list_empty(hnd_list_l) || !list_empty(hnd_list_h)) -- cgit From 4bd29c34988be0c24759d5d58df424f861a8bf24 Mon Sep 17 00:00:00 2001 From: Jerry Zuo Date: Thu, 28 Sep 2017 16:20:30 -0400 Subject: drm/amd/display: Do not access fbdev helper members Original code is no longer needed and tested without loop. Signed-off-by: Harry Wentland Signed-off-by: Jerry Zuo Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 610375b2a04b..382f499cb60d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -397,21 +397,10 @@ static void dm_dp_mst_register_connector(struct drm_connector *connector) { struct drm_device *dev = connector->dev; struct amdgpu_device *adev = dev->dev_private; - int i; drm_modeset_lock_all(dev); - if (adev->mode_info.rfbdev) { - /*Do not add if already registered in past*/ - for (i = 0; i < adev->mode_info.rfbdev->helper.connector_count; i++) { - if (adev->mode_info.rfbdev->helper.connector_info[i]->connector - == connector) { - drm_modeset_unlock_all(dev); - return; - } - } - + if (adev->mode_info.rfbdev) drm_fb_helper_add_one_connector(&adev->mode_info.rfbdev->helper, connector); - } else DRM_ERROR("adev->mode_info.rfbdev is NULL\n"); -- cgit From 365c7c975dcd1a2158ed33dab76c1d308f9f9906 Mon Sep 17 00:00:00 2001 From: Jerry Zuo Date: Thu, 28 Sep 2017 16:58:32 -0400 Subject: drm/amd/display: Remove drm_modeset_lock in MST code Locks are no longer needed since the drm framework takes care of correct locking. Signed-off-by: Harry Wentland Signed-off-by: Jerry Zuo Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 382f499cb60d..3b05da7a90e8 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -287,9 +287,10 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr, struct amdgpu_device *adev = dev->dev_private; struct amdgpu_dm_connector *aconnector; struct drm_connector *connector; + struct drm_connector_list_iter conn_iter; - drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + drm_connector_list_iter_begin(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { aconnector = to_amdgpu_dm_connector(connector); if (aconnector->mst_port == master && !aconnector->port) { @@ -299,11 +300,11 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr, aconnector->port = port; drm_mode_connector_set_path_property(connector, pathprop); - drm_modeset_unlock(&dev->mode_config.connection_mutex); + drm_connector_list_iter_end(&conn_iter); return &aconnector->base; } } - drm_modeset_unlock(&dev->mode_config.connection_mutex); + drm_connector_list_iter_end(&conn_iter); aconnector = kzalloc(sizeof(*aconnector), GFP_KERNEL); if (!aconnector) @@ -398,14 +399,11 @@ static void dm_dp_mst_register_connector(struct drm_connector *connector) struct drm_device *dev = connector->dev; struct amdgpu_device *adev = dev->dev_private; - drm_modeset_lock_all(dev); if (adev->mode_info.rfbdev) drm_fb_helper_add_one_connector(&adev->mode_info.rfbdev->helper, connector); else DRM_ERROR("adev->mode_info.rfbdev is NULL\n"); - drm_modeset_unlock_all(dev); - drm_connector_register(connector); } -- cgit From 734a092b1fe407319c8a4f38f9b4a647ddb54c2c Mon Sep 17 00:00:00 2001 From: Eric Bernstein Date: Fri, 29 Sep 2017 15:30:17 -0400 Subject: drm/amd/display: clean up dcn10 dpp after HW review Signed-off-by: Eric Bernstein Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 2 + drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h | 20 +++++ .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c | 85 +++++++++++----------- 3 files changed, 65 insertions(+), 42 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index 4ab109314e4b..1a9f57fb0838 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -204,6 +204,8 @@ enum surface_pixel_format { /*grow 444 video here if necessary */ }; + + /* Pixel format */ enum pixel_format { /*graph*/ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h index 889f91cf47cf..153aa3c32762 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h @@ -1265,6 +1265,21 @@ struct dcn10_dpp { }; +enum lb_memory_config { + /* Enable all 3 pieces of memory */ + LB_MEMORY_CONFIG_0 = 0, + + /* Enable only the first piece of memory */ + LB_MEMORY_CONFIG_1 = 1, + + /* Enable only the second piece of memory */ + LB_MEMORY_CONFIG_2 = 2, + + /* Only applicable in 4:2:0 mode, enable all 3 pieces of memory and the + * last piece of chroma memory used for the luma storage + */ + LB_MEMORY_CONFIG_3 = 3 +}; enum dcn10_input_csc_select { INPUT_CSC_SELECT_BYPASS = 0, @@ -1272,6 +1287,11 @@ enum dcn10_input_csc_select { INPUT_CSC_SELECT_COMA }; +bool is_lb_conf_valid( + int ceil_vratio, + int num_partitions, + int vtaps); + void ippn10_degamma_ram_select( struct transform *xfm_base, bool use_ram_a); 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 fa2ab9952388..c5267e42a2f2 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 @@ -57,22 +57,6 @@ enum dcn10_coef_filter_type_sel { SCL_COEF_ALPHA_HORZ_FILTER = 5 }; -enum lb_memory_config { - /* Enable all 3 pieces of memory */ - LB_MEMORY_CONFIG_0 = 0, - - /* Enable only the first piece of memory */ - LB_MEMORY_CONFIG_1 = 1, - - /* Enable only the second piece of memory */ - LB_MEMORY_CONFIG_2 = 2, - - /* Only applicable in 4:2:0 mode, enable all 3 pieces of memory and the - * last piece of chroma memory used for the luma storage - */ - LB_MEMORY_CONFIG_3 = 3 -}; - enum dscl_autocal_mode { AUTOCAL_MODE_OFF = 0, @@ -161,23 +145,37 @@ static int get_pixel_depth_val(enum lb_pixel_depth depth) } } -static enum dscl_mode_sel get_dscl_mode( - const struct scaler_data *data, bool dbg_always_scale) +static bool is_video_format(enum pixel_format format) { - const long long one = dal_fixed31_32_one.value; - bool ycbcr = false; - bool format420 = false; + if (format >= PIXEL_FORMAT_VIDEO_BEGIN + && format <= PIXEL_FORMAT_VIDEO_END) + return true; + else + return false; +} - if (data->format == PIXEL_FORMAT_FP16) - return DSCL_MODE_DSCL_BYPASS; +static bool is_420_format(enum pixel_format format) +{ + if (format == PIXEL_FORMAT_420BPP8 || + format == PIXEL_FORMAT_420BPP10) + return true; + else + return false; +} - if (data->format >= PIXEL_FORMAT_VIDEO_BEGIN - && data->format <= PIXEL_FORMAT_VIDEO_END) - ycbcr = true; +static enum dscl_mode_sel get_dscl_mode( + struct transform *xfm_base, + const struct scaler_data *data, + bool dbg_always_scale) +{ + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + const long long one = dal_fixed31_32_one.value; - if (data->format == PIXEL_FORMAT_420BPP8 || - data->format == PIXEL_FORMAT_420BPP10) - format420 = true; + if (xfm->tf_mask->PIXEL_DEPTH) { + /* DSCL caps: LB data is fixed format */ + if (data->format == PIXEL_FORMAT_FP16) + return DSCL_MODE_DSCL_BYPASS; + } if (data->ratios.horz.value == one && data->ratios.vert.value == one @@ -186,8 +184,8 @@ static enum dscl_mode_sel get_dscl_mode( && !dbg_always_scale) return DSCL_MODE_SCALING_444_BYPASS; - if (!format420) { - if (ycbcr) + if (!is_420_format(data->format)) { + if (is_video_format(data->format)) return DSCL_MODE_SCALING_444_YCBCR_ENABLE; else return DSCL_MODE_SCALING_444_RGB_ENABLE; @@ -205,11 +203,12 @@ static void dpp_set_lb( const struct line_buffer_params *lb_params, enum lb_memory_config mem_size_config) { - uint32_t pixel_depth = get_pixel_depth_val(lb_params->depth); - uint32_t dyn_pix_depth = lb_params->dynamic_pixel_depth; - /* LB */ if (xfm->tf_mask->PIXEL_DEPTH) { + /* DSCL caps: LB data is fixed format */ + uint32_t pixel_depth = get_pixel_depth_val(lb_params->depth); + uint32_t dyn_pix_depth = lb_params->dynamic_pixel_depth; + REG_SET_7(LB_DATA_FORMAT, 0, PIXEL_DEPTH, pixel_depth, /* Pixel depth stored in LB */ PIXEL_EXPAN_MODE, lb_params->pixel_expan_mode, /* Pixel expansion mode */ @@ -401,7 +400,7 @@ static int get_lb_depth_bpc(enum lb_pixel_depth depth) } } -static void calc_lb_num_partitions( +static void dscl1_calc_lb_num_partitions( const struct scaler_data *scl_data, enum lb_memory_config lb_config, int *num_part_y, @@ -426,6 +425,7 @@ static void calc_lb_num_partitions( lb_memory_size_c = 1088; lb_memory_size_a = 1312; } else if (lb_config == LB_MEMORY_CONFIG_3) { + /* 420 mode: using 3rd mem from Y, Cr and Cb */ lb_memory_size = 816 + 1088 + 848 + 848 + 848; lb_memory_size_c = 816 + 1088; lb_memory_size_a = 984 + 1312 + 456; @@ -449,7 +449,7 @@ static void calc_lb_num_partitions( } -static bool is_lb_conf_valid(int ceil_vratio, int num_partitions, int vtaps) +bool is_lb_conf_valid(int ceil_vratio, int num_partitions, int vtaps) { if (ceil_vratio > 2) return vtaps <= (num_partitions - ceil_vratio + 2); @@ -467,14 +467,14 @@ static enum lb_memory_config dpp10_find_lb_memory_config( int ceil_vratio = dal_fixed31_32_ceil(scl_data->ratios.vert); int ceil_vratio_c = dal_fixed31_32_ceil(scl_data->ratios.vert_c); - calc_lb_num_partitions( + dscl1_calc_lb_num_partitions( scl_data, LB_MEMORY_CONFIG_1, &num_part_y, &num_part_c); if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)) return LB_MEMORY_CONFIG_1; - calc_lb_num_partitions( + dscl1_calc_lb_num_partitions( scl_data, LB_MEMORY_CONFIG_2, &num_part_y, &num_part_c); if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) @@ -483,7 +483,7 @@ static enum lb_memory_config dpp10_find_lb_memory_config( if (scl_data->format == PIXEL_FORMAT_420BPP8 || scl_data->format == PIXEL_FORMAT_420BPP10) { - calc_lb_num_partitions( + dscl1_calc_lb_num_partitions( scl_data, LB_MEMORY_CONFIG_3, &num_part_y, &num_part_c); if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) @@ -491,7 +491,7 @@ static enum lb_memory_config dpp10_find_lb_memory_config( return LB_MEMORY_CONFIG_3; } - calc_lb_num_partitions( + dscl1_calc_lb_num_partitions( scl_data, LB_MEMORY_CONFIG_0, &num_part_y, &num_part_c); /*Ensure we can support the requested number of vtaps*/ @@ -511,6 +511,7 @@ static enum lb_memory_config find_lb_memory_config(struct dcn10_dpp *xfm, return mem_cfg; if (xfm->tf_mask->PIXEL_DEPTH) { + /* DSCL caps: LB data is fixed format */ mem_cfg = dpp10_find_lb_memory_config(scl_data); } return mem_cfg; @@ -523,7 +524,7 @@ void dpp_set_scaler_auto_scale( enum lb_memory_config lb_config; struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); enum dscl_mode_sel dscl_mode = get_dscl_mode( - scl_data, xfm_base->ctx->dc->debug.always_scale); + xfm_base, scl_data, xfm_base->ctx->dc->debug.always_scale); bool ycbcr = scl_data->format >= PIXEL_FORMAT_VIDEO_BEGIN && scl_data->format <= PIXEL_FORMAT_VIDEO_END; @@ -655,7 +656,7 @@ void dcn10_dpp_dscl_set_scaler_manual_scale( enum lb_memory_config lb_config; struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); enum dscl_mode_sel dscl_mode = get_dscl_mode( - scl_data, xfm_base->ctx->dc->debug.always_scale); + xfm_base, scl_data, xfm_base->ctx->dc->debug.always_scale); bool ycbcr = scl_data->format >= PIXEL_FORMAT_VIDEO_BEGIN && scl_data->format <= PIXEL_FORMAT_VIDEO_END; -- cgit From 3af89b96b2f22119556b8e89edde72951f6bd410 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Sat, 30 Sep 2017 21:03:40 -0400 Subject: drm/amd/display: Add stereo_support debug flag Signed-off-by: Charlene Liu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 2517fb821fff..172050ad845d 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -217,6 +217,7 @@ struct dc_debug { bool force_abm_enable; bool disable_hbup_pg; bool disable_dpp_pg; + bool stereo_support; }; struct dc_state; struct resource_pool; -- cgit From 13ab1b44151195823fa0e2ceace1cf4687266dba Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Thu, 28 Sep 2017 17:18:27 -0400 Subject: drm/amd/display: Fixed extend to second screen mode hang 1. Fixed acquire free split pipe bug. 2. Change return value for dc_add_stream_to_ctx from bool to enum. 4. Remove redundant apply_ctx_for_surface calling 5. Unlock pipe after back end programming. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 +- drivers/gpu/drm/amd/display/dc/core/dc.c | 48 ++++++++++++----------- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 9 ++--- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 4 files changed, 32 insertions(+), 31 deletions(-) (limited to 'drivers/gpu') 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 0707bec111a5..8653453566b8 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4495,10 +4495,10 @@ static int dm_update_crtcs_state(struct dc *dc, DRM_DEBUG_DRIVER("Enabling DRM crtc: %d\n", crtc->base.id); - if (!dc_add_stream_to_ctx( + if (dc_add_stream_to_ctx( dc, dm_state->context, - dm_new_crtc_state->stream)) { + dm_new_crtc_state->stream) != DC_OK) { ret = -EINVAL; goto fail; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index f9bac11d3950..33a63c7d7a8e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -766,34 +766,27 @@ static bool dc_commit_state_no_check(struct dc *dc, struct dc_state *context) for (i = 0; i < context->stream_count; i++) { const struct dc_sink *sink = context->streams[i]->sink; - for (j = 0; j < context->stream_status[i].plane_count; j++) { - dc->hwss.apply_ctx_for_surface( - dc, context->streams[i], - context->stream_status[i].plane_count, - context); + dc->hwss.apply_ctx_for_surface( + dc, context->streams[i], + context->stream_status[i].plane_count, + context); - /* - * enable stereo - * TODO rework dc_enable_stereo call to work with validation sets? - */ - for (k = 0; k < MAX_PIPES; k++) { - pipe = &context->res_ctx.pipe_ctx[k]; - - for (l = 0 ; pipe && l < context->stream_count; l++) { - if (context->streams[l] && - context->streams[l] == pipe->stream && - dc->hwss.setup_stereo) - dc->hwss.setup_stereo(pipe, dc); - } + /* + * enable stereo + * TODO rework dc_enable_stereo call to work with validation sets? + */ + for (k = 0; k < MAX_PIPES; k++) { + pipe = &context->res_ctx.pipe_ctx[k]; + + for (l = 0 ; pipe && l < context->stream_count; l++) { + if (context->streams[l] && + context->streams[l] == pipe->stream && + dc->hwss.setup_stereo) + dc->hwss.setup_stereo(pipe, dc); } } - for (j = 0; j < MAX_PIPES; j++) { - pipe = &context->res_ctx.pipe_ctx[j]; - if (!pipe->top_pipe && pipe->stream == context->streams[i]) - dc->hwss.pipe_control_lock(dc, pipe, false); - } CONN_MSG_MODE(sink->link, "{%dx%d, %dx%d@%dKhz}", context->streams[i]->timing.h_addressable, @@ -815,6 +808,15 @@ static bool dc_commit_state_no_check(struct dc *dc, struct dc_state *context) dc_enable_stereo(dc, context, dc_streams, context->stream_count); + for (i = 0; i < context->stream_count; i++) { + for (j = 0; j < MAX_PIPES; j++) { + pipe = &context->res_ctx.pipe_ctx[j]; + + if (!pipe->top_pipe && pipe->stream == context->streams[i]) + dc->hwss.pipe_control_lock(dc, pipe, false); + } + } + dc_release_state(dc->current_state); dc->current_state = context; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index c31dccdc3d2e..c60f53069708 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1446,7 +1446,7 @@ bool resource_is_stream_unchanged( return false; } -bool dc_add_stream_to_ctx( +enum dc_status dc_add_stream_to_ctx( struct dc *dc, struct dc_state *new_ctx, struct dc_stream_state *stream) @@ -1467,7 +1467,7 @@ bool dc_add_stream_to_ctx( if (res != DC_OK) DC_ERROR("Adding stream %p to context failed with err %d!\n", stream, res); - return res == DC_OK; + return res; } bool dc_remove_stream_from_ctx( @@ -1640,10 +1640,9 @@ enum dc_status resource_map_pool_resources( /* acquire new resources */ pipe_idx = acquire_first_free_pipe(&context->res_ctx, pool, stream); -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) if (pipe_idx < 0) - acquire_first_split_pipe(&context->res_ctx, pool, stream); -#endif + pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream); + if (pipe_idx < 0) return DC_NO_CONTROLLER_RESOURCE; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 172050ad845d..eeb8ee5acdc1 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -631,7 +631,7 @@ bool dc_stream_get_scanoutpos(const struct dc_stream_state *stream, uint32_t *h_position, uint32_t *v_position); -bool dc_add_stream_to_ctx( +enum dc_status dc_add_stream_to_ctx( struct dc *dc, struct dc_state *new_ctx, struct dc_stream_state *stream); -- cgit From 309c42efdab945071c693a51334fbaeb0a700b0d Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Mon, 2 Oct 2017 17:08:24 -0400 Subject: drm/amd/display: wa to program split pipedegamma regs after mode set. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 33a63c7d7a8e..09bab93815a3 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1282,7 +1282,9 @@ static void commit_planes_for_stream(struct dc *dc, if (update_type == UPDATE_TYPE_FAST) continue; - if (srf_updates[i].in_transfer_func) + /* work around to program degamma regs for split pipe after set mode. */ + if (srf_updates[i].in_transfer_func || (pipe_ctx->top_pipe && + pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state)) dc->hwss.set_input_transfer_func( pipe_ctx, pipe_ctx->plane_state); -- cgit From f6cb588a42a7812e65eff368d3d1134ee1a88489 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Mon, 2 Oct 2017 16:25:58 -0400 Subject: drm/amd/display: Add debug flag for VSR support Signed-off-by: Charlene Liu Reviewed-by: Krunoslav Kovac Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 1 + drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 1 + drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c | 1 + 3 files changed, 3 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index eeb8ee5acdc1..defc44393b38 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -218,6 +218,7 @@ struct dc_debug { bool disable_hbup_pg; bool disable_dpp_pg; bool stereo_support; + bool vsr_support; }; struct dc_state; struct resource_pool; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 3000ddab2357..1b108ae2e656 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -428,6 +428,7 @@ static const struct dc_debug debug_defaults_drv = { .pipe_split_policy = MPC_SPLIT_AVOID_MULT_DISP, .disable_dcc = DCC_ENABLE, .voltage_align_fclk = true, + .vsr_support = true, }; static const struct dc_debug debug_defaults_diags = { diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c index 8dbc82ff9b3a..178dadda74f9 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c @@ -25,6 +25,7 @@ #include "reg_helper.h" #include "dcn10_timing_generator.h" +#include "dc.h" #define REG(reg)\ tgn10->tg_regs->reg -- cgit From 458e9d03875ec6cb2ee37b64cf201bc80401bf92 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Mon, 2 Oct 2017 12:00:24 -0400 Subject: drm/amd/display: fix re-enabling stutter for raven We were overwriting the whole register which was re-enabling stutter for raven. Now we are reading the register then setting the values only for pstate. Signed-off-by: Bhawanpreet Lakha Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h | 4 ++++ drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 9 ++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index 0a058e0c3fec..9a04b8758888 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -446,6 +446,8 @@ struct dce_hwseq_registers { HWS_SF(, DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE, mask_sh), \ HWS_SF(, DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE, mask_sh), \ HWS_SF(, DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, mask_sh), \ + HWS_SF(, DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_VALUE, mask_sh), \ + HWS_SF(, DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_ENABLE, mask_sh), \ HWS_SF(, DCHUBBUB_ARB_SAT_LEVEL, DCHUBBUB_ARB_SAT_LEVEL, mask_sh), \ HWS_SF(, DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MIN_REQ_OUTSTAND, mask_sh), \ HWS_SF(, DCFCLK_CNTL, DCFCLK_GATE_DIS, mask_sh) @@ -554,6 +556,8 @@ struct dce_hwseq_registers { type DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE;\ type DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE;\ type DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE;\ + type DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_VALUE;\ + type DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_ENABLE;\ type DCHUBBUB_ARB_SAT_LEVEL;\ type DCHUBBUB_ARB_MIN_REQ_OUTSTAND;\ type OPP_PIPE_CLOCK_EN;\ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 072c48188b79..db774b3c3721 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -253,7 +253,6 @@ static void verify_allow_pstate_change_high( unsigned int debug_index = 0x7; unsigned int debug_data; - unsigned int force_allow_pstate = 0x30; unsigned int i; if (forced_pstate_allow) { @@ -261,7 +260,9 @@ static void verify_allow_pstate_change_high( * we verify_allow_pstate_change_high. so disable force * here so we can check status */ - REG_WRITE(DCHUBBUB_ARB_DRAM_STATE_CNTL, 0); + REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL, + DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_VALUE, 0, + DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_ENABLE, 0); forced_pstate_allow = false; } @@ -304,7 +305,9 @@ static void verify_allow_pstate_change_high( /* force pstate allow to prevent system hang * and break to debugger to investigate */ - REG_WRITE(DCHUBBUB_ARB_DRAM_STATE_CNTL, force_allow_pstate); + REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL, + DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_VALUE, 1, + DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_ENABLE, 1); forced_pstate_allow = true; if (should_log_hw_state) { -- cgit From 73fb63e74fb26c12bc847fd28596cc4e088e870b Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Mon, 2 Oct 2017 18:01:36 -0400 Subject: drm/amd/display: reject 3D mode based on static debug flag. Signed-off-by: Charlene Liu Reviewed-by: Krunoslav Kovac Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 1 + drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c | 3 +++ 3 files changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index defc44393b38..4c47a489c87a 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -217,7 +217,7 @@ struct dc_debug { bool force_abm_enable; bool disable_hbup_pg; bool disable_dpp_pg; - bool stereo_support; + bool disable_stereo_support; bool vsr_support; }; struct dc_state; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 1b108ae2e656..f168335e95bf 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -428,6 +428,7 @@ static const struct dc_debug debug_defaults_drv = { .pipe_split_policy = MPC_SPLIT_AVOID_MULT_DISP, .disable_dcc = DCC_ENABLE, .voltage_align_fclk = true, + .disable_stereo_support = true, .vsr_support = true, }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c index 178dadda74f9..1994865d4351 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c @@ -499,6 +499,9 @@ static bool tgn10_validate_timing( timing->timing_3d_format != TIMING_3D_FORMAT_INBAND_FA) return false; + if (timing->timing_3d_format != TIMING_3D_FORMAT_NONE && + tg->ctx->dc->debug.disable_stereo_support) + return false; /* Temporarily blocking interlacing mode until it's supported */ if (timing->flags.INTERLACE == 1) return false; -- cgit From ff79cbdccea94935ff9d2111458e439e28c86e74 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Mon, 2 Oct 2017 13:40:02 -0400 Subject: drm/amd/display: increase pstate wait timeout For linux it takes longer than 40us so increasing it to 200us. Also added debug prints regarding the change Signed-off-by: Bhawanpreet Lakha Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index db774b3c3721..012ba7c9ca8d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -245,8 +245,13 @@ static void verify_allow_pstate_change_high( { /* pstate latency is ~20us so if we wait over 40us and pstate allow * still not asserted, we are probably stuck and going to hang + * + * TODO: Figure out why it takes ~100us on linux + * pstate takes around ~100us on linux. Unknown currently as to + * why it takes that long on linux */ - static unsigned int pstate_wait_timeout_us = 40; + static unsigned int pstate_wait_timeout_us = 200; + static unsigned int pstate_wait_expected_timeout_us = 40; static unsigned int max_sampled_pstate_wait_us; /* data collection */ static bool forced_pstate_allow; /* help with revert wa */ static bool should_log_hw_state; /* prevent hw state log by default */ @@ -293,9 +298,15 @@ static void verify_allow_pstate_change_high( for (i = 0; i < pstate_wait_timeout_us; i++) { debug_data = REG_READ(DCHUBBUB_TEST_DEBUG_DATA); - if (debug_data & (1 << 30)) - return; + if (debug_data & (1 << 30)) { + + if (i > pstate_wait_expected_timeout_us) + dm_logger_write(hws->ctx->logger, LOG_WARNING, + "pstate took longer than expected ~%dus", + i); + return; + } if (max_sampled_pstate_wait_us < i) max_sampled_pstate_wait_us = i; @@ -314,6 +325,9 @@ static void verify_allow_pstate_change_high( dcn10_log_hw_state(hws->ctx->dc); } + dm_logger_write(hws->ctx->logger, LOG_WARNING, + "pstate TEST_DEBUG_DATA: 0x%X", + debug_data); BREAK_TO_DEBUGGER(); } -- cgit From bac4c5592774fef2503c3204e8f947ce595bfcdf Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Tue, 3 Oct 2017 11:11:28 -0400 Subject: drm/amd/display: block video planes >4k on dcn10 Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index f168335e95bf..4dd7c3af51e6 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -1163,6 +1163,14 @@ static void dcn10_destroy_resource_pool(struct resource_pool **pool) *pool = NULL; } +enum dc_status dcn10_validate_plane(const struct dc_plane_state *plane_state) +{ + if (plane_state->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN + && plane_state->src_rect.width > 3840) + return DC_FAIL_SURFACE_VALIDATE; + + return DC_OK; +} static struct dc_cap_funcs cap_funcs = { .get_dcc_compression_cap = get_dcc_compression_cap @@ -1174,6 +1182,7 @@ static struct resource_funcs dcn10_res_pool_funcs = { .validate_guaranteed = dcn10_validate_guaranteed, .validate_bandwidth = dcn_validate_bandwidth, .acquire_idle_pipe_for_layer = dcn10_acquire_idle_pipe_for_layer, + .validate_plane = dcn10_validate_plane, .add_stream_to_ctx = dcn10_add_stream_to_ctx }; -- cgit From 8e7095b909dd5451c92dc04420891a578e2f3152 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Tue, 3 Oct 2017 12:54:18 -0400 Subject: drm/amd/display: add max_video_width cap to dc Signed-off-by: Dmytro Laktyushkin Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 6 ++---- drivers/gpu/drm/amd/display/dc/dc.h | 1 + drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h | 2 +- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 6 ++++-- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 2 +- 6 files changed, 10 insertions(+), 9 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index c60f53069708..7d750369b78b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -2750,11 +2750,9 @@ bool dc_validate_stream(struct dc *dc, struct dc_stream_state *stream) bool dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state) { - struct dc *core_dc = dc; - /* TODO For now validates pixel format only */ - if (core_dc->res_pool->funcs->validate_plane) - return core_dc->res_pool->funcs->validate_plane(plane_state) == DC_OK; + if (dc->res_pool->funcs->validate_plane) + return dc->res_pool->funcs->validate_plane(plane_state, &dc->caps) == DC_OK; return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 4c47a489c87a..5a378cc5daaf 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -57,6 +57,7 @@ struct dc_caps { uint32_t max_downscale_ratio; uint32_t i2c_speed_in_khz; unsigned int max_cursor_size; + unsigned int max_video_width; bool dcc_const_color; bool dynamic_audio; }; diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index b1cf591b3408..90911258bdb3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -743,7 +743,7 @@ static void dce100_destroy_resource_pool(struct resource_pool **pool) *pool = NULL; } -enum dc_status dce100_validate_plane(const struct dc_plane_state *plane_state) +enum dc_status dce100_validate_plane(const struct dc_plane_state *plane_state, struct dc_caps *caps) { if (plane_state->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h index f52cae24ee23..de8fdf438f9b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h @@ -16,7 +16,7 @@ struct resource_pool *dce100_create_resource_pool( uint8_t num_virtual_links, struct dc *dc); -enum dc_status dce100_validate_plane(const struct dc_plane_state *plane_state); +enum dc_status dce100_validate_plane(const struct dc_plane_state *plane_state, struct dc_caps *caps); enum dc_status dce100_add_stream_to_ctx( struct dc *dc, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 4dd7c3af51e6..2caad73257e0 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -1163,10 +1163,11 @@ static void dcn10_destroy_resource_pool(struct resource_pool **pool) *pool = NULL; } -enum dc_status dcn10_validate_plane(const struct dc_plane_state *plane_state) +static enum dc_status dcn10_validate_plane(const struct dc_plane_state *plane_state, struct dc_caps *caps) { if (plane_state->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN - && plane_state->src_rect.width > 3840) + && caps->max_video_width != 0 + && plane_state->src_rect.width > caps->max_video_width) return DC_FAIL_SURFACE_VALIDATE; return DC_OK; @@ -1222,6 +1223,7 @@ static bool construct( /* max pipe num for ASIC before check pipe fuses */ pool->base.pipe_count = pool->base.res_cap->num_timing_generator; + dc->caps.max_video_width = 3840; dc->caps.max_downscale_ratio = 200; dc->caps.i2c_speed_in_khz = 100; dc->caps.max_cursor_size = 256; diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 5230dddc8617..118122d12e2b 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -111,7 +111,7 @@ struct resource_funcs { const struct resource_pool *pool, struct dc_stream_state *stream); - enum dc_status (*validate_plane)(const struct dc_plane_state *plane_state); + enum dc_status (*validate_plane)(const struct dc_plane_state *plane_state, struct dc_caps *caps); enum dc_status (*add_stream_to_ctx)( struct dc *dc, -- cgit From d050f8ed14494ea23c6e10b5893010946ef0f78b Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Fri, 29 Sep 2017 16:36:34 -0400 Subject: drm/amd/display: add dpms state to DC - avoid eDP screen flash 4 times when resume from s3 - improve s3 and boot time Signed-off-by: Hersen Wu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 39 +++++++++++++++++++++- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 4 +++ drivers/gpu/drm/amd/display/dc/dc.h | 5 +++ .../amd/display/dc/dce110/dce110_hw_sequencer.c | 13 ++++---- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 11 +++--- 5 files changed, 58 insertions(+), 14 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 09bab93815a3..d963de753e63 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -332,7 +332,16 @@ static void set_dither_option(struct dc_stream_state *stream, { struct bit_depth_reduction_params params; struct dc_link *link = stream->status.link; - struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx; + struct pipe_ctx *pipes; + int i; + + for (i = 0; i < MAX_PIPES; i++) { + if (link->dc->current_state->res_ctx.pipe_ctx[i].stream == + stream) { + pipes = &link->dc->current_state->res_ctx.pipe_ctx[i]; + break; + } + } memset(¶ms, 0, sizeof(params)); if (!stream) @@ -349,6 +358,31 @@ static void set_dither_option(struct dc_stream_state *stream, opp_program_bit_depth_reduction(pipes->stream_res.opp, ¶ms); } +void set_dpms( + struct dc *dc, + struct dc_stream_state *stream, + bool dpms_off) +{ + struct pipe_ctx *pipe_ctx; + int i; + + for (i = 0; i < MAX_PIPES; i++) { + if (dc->current_state->res_ctx.pipe_ctx[i].stream == stream) { + pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; + break; + } + } + + if (stream->dpms_off != dpms_off) { + stream->dpms_off = dpms_off; + if (dpms_off) + core_link_disable_stream(pipe_ctx, + KEEP_ACQUIRED_RESOURCE); + else + core_link_enable_stream(dc->current_state, pipe_ctx); + } +} + static void allocate_dc_stream_funcs(struct dc *dc) { if (dc->hwss.set_drr != NULL) { @@ -371,6 +405,9 @@ static void allocate_dc_stream_funcs(struct dc *dc) dc->stream_funcs.set_dither_option = set_dither_option; + dc->stream_funcs.set_dpms = + set_dpms; + dc->link_funcs.set_drive_settings = set_drive_settings; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 2d59f77fa9a2..72e56fbe4a42 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -2321,6 +2321,10 @@ void core_link_enable_stream( if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) allocate_mst_payload(pipe_ctx); + + if (dc_is_dp_signal(pipe_ctx->stream->signal)) + core_dc->hwss.unblank_stream(pipe_ctx, + &pipe_ctx->stream->sink->link->cur_link_settings); } void core_link_disable_stream(struct pipe_ctx *pipe_ctx, int option) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 5a378cc5daaf..7a5e53ffac2e 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -133,6 +133,10 @@ struct dc_stream_state_funcs { void (*set_dither_option)(struct dc_stream_state *stream, enum dc_dither_option option); + + void (*set_dpms)(struct dc *dc, + struct dc_stream_state *stream, + bool dpms_off); }; struct link_training_settings; @@ -566,6 +570,7 @@ struct dc_stream_state { int phy_pix_clk; enum signal_type signal; + bool dpms_off; struct dc_stream_status status; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 453d2ffd5c4a..81ebf2b9c71d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1364,12 +1364,8 @@ static enum dc_status apply_single_controller_ctx_to_hw( resource_build_info_frame(pipe_ctx); dce110_update_info_frame(pipe_ctx); if (!pipe_ctx_old->stream) { - core_link_enable_stream(context, pipe_ctx); - - - if (dc_is_dp_signal(pipe_ctx->stream->signal)) - dce110_unblank_stream(pipe_ctx, - &stream->sink->link->cur_link_settings); + if (!pipe_ctx->stream->dpms_off) + core_link_enable_stream(context, pipe_ctx); } pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; @@ -1879,7 +1875,10 @@ static void dce110_reset_hw_ctx_wrap( pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) { struct clock_source *old_clk = pipe_ctx_old->clock_source; - core_link_disable_stream(pipe_ctx_old, FREE_ACQUIRED_RESOURCE); + /* disable already, no need to disable again */ + if (!pipe_ctx->stream->dpms_off) + core_link_disable_stream(pipe_ctx_old, FREE_ACQUIRED_RESOURCE); + pipe_ctx_old->stream_res.tg->funcs->set_blank(pipe_ctx_old->stream_res.tg, true); if (!hwss_wait_for_blank_complete(pipe_ctx_old->stream_res.tg)) { dm_error("DC: failed to blank crtc!\n"); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 012ba7c9ca8d..494f833208f9 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1037,12 +1037,11 @@ static void reset_back_end_for_pipe( return; } - /* TODOFPGA break core_link_disable_stream into 2 functions: - * disable_stream and disable_link. disable_link will disable PHYPLL - * which is used by otg. Move disable_link after disable_crtc - */ - if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) - core_link_disable_stream(pipe_ctx, FREE_ACQUIRED_RESOURCE); + if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { + /* DPMS may already disable */ + if (!pipe_ctx->stream->dpms_off) + core_link_disable_stream(pipe_ctx, FREE_ACQUIRED_RESOURCE); + } /* by upper caller loop, parent pipe: pipe0, will be reset last. * back end share by all pipes and will be disable only when disable -- cgit From 067c878a220cbe6198b3cfdc7f372adab4762ad8 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Tue, 3 Oct 2017 15:03:49 -0400 Subject: drm/amd/display: Fixed switching mode half screen gamma incorrect. Half screen gamma setting and cursor are incorrect when switching mode through win+p due to wrong programming gamma sequence (In case of bottom pipe, gamma and cursor are programmed before front end programmed, pipe is power gated). change: 1. Cache curor attributes to stream 2. Move set gamma and cursor inside front end programming. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 15 --------------- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 9 ++++++++- drivers/gpu/drm/amd/display/dc/dc.h | 4 +++- .../gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 10 ++++++++++ .../gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 17 +++++++++++++++++ 5 files changed, 38 insertions(+), 17 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index d963de753e63..92fab09843e4 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1269,10 +1269,6 @@ static void commit_planes_for_stream(struct dc *dc, /* Full fe update*/ for (j = 0; j < dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - struct pipe_ctx *cur_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[j]; - bool is_new_pipe_surface = cur_pipe_ctx->plane_state != pipe_ctx->plane_state; - struct dc_cursor_position position = { 0 }; - if (update_type != UPDATE_TYPE_FULL || !pipe_ctx->plane_state) continue; @@ -1283,17 +1279,6 @@ static void commit_planes_for_stream(struct dc *dc, dc->hwss.apply_ctx_for_surface( dc, pipe_ctx->stream, stream_status->plane_count, context); } - - /* TODO: this is a hack w/a for switching from mpo to pipe split */ - dc_stream_set_cursor_position(pipe_ctx->stream, &position); - - if (is_new_pipe_surface) { - dc->hwss.update_plane_addr(dc, pipe_ctx); - dc->hwss.set_input_transfer_func( - pipe_ctx, pipe_ctx->plane_state); - dc->hwss.set_output_transfer_func( - pipe_ctx, pipe_ctx->stream); - } } if (update_type > UPDATE_TYPE_FAST) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index c19b478bcdc7..3dd44bef56eb 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -173,7 +173,7 @@ struct dc_stream_status *dc_stream_get_status( * Update the cursor attributes and set cursor surface address */ bool dc_stream_set_cursor_attributes( - const struct dc_stream_state *stream, + struct dc_stream_state *stream, const struct dc_cursor_attributes *attributes) { int i; @@ -189,6 +189,11 @@ bool dc_stream_set_cursor_attributes( return false; } + if (attributes->address.quad_part == 0) { + dm_error("DC: Cursor address is 0!\n"); + return false; + } + core_dc = stream->ctx->dc; res_ctx = &core_dc->current_state->res_ctx; @@ -214,6 +219,8 @@ bool dc_stream_set_cursor_attributes( pipe_ctx->plane_res.xfm, attributes); } + stream->cursor_attributes = *attributes; + return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 7a5e53ffac2e..c832d5abbbdf 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -574,6 +574,8 @@ struct dc_stream_state { struct dc_stream_status status; + struct dc_cursor_attributes cursor_attributes; + /* from stream struct */ struct kref refcount; }; @@ -1013,7 +1015,7 @@ struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params); ******************************************************************************/ /* TODO: Deprecated once we switch to dc_set_cursor_position */ bool dc_stream_set_cursor_attributes( - const struct dc_stream_state *stream, + struct dc_stream_state *stream, const struct dc_cursor_attributes *attributes); bool dc_stream_set_cursor_position( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 81ebf2b9c71d..bf7318246401 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -2725,6 +2725,8 @@ static void dce110_program_front_end_for_pipe( struct dc_plane_state *plane_state = pipe_ctx->plane_state; struct xfm_grph_csc_adjustment adjust; struct out_csc_color_matrix tbl_entry; + struct pipe_ctx *cur_pipe_ctx = + &dc->current_state->res_ctx.pipe_ctx[pipe_ctx->pipe_idx]; unsigned int i; memset(&tbl_entry, 0, sizeof(tbl_entry)); @@ -2815,6 +2817,14 @@ static void dce110_program_front_end_for_pipe( &plane_state->tiling_info, plane_state->rotation); + /* Moved programming gamma from dc to hwss */ + if (cur_pipe_ctx->plane_state != pipe_ctx->plane_state) { + dc->hwss.set_input_transfer_func( + pipe_ctx, pipe_ctx->plane_state); + dc->hwss.set_output_transfer_func( + pipe_ctx, pipe_ctx->stream); + } + dm_logger_write(dc->ctx->logger, LOG_SURFACE, "Pipe:%d 0x%x: addr hi:0x%x, " "addr low:0x%x, " diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 494f833208f9..ee63155c1895 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2408,6 +2408,10 @@ static void program_all_pipe_in_tree( } if (pipe_ctx->plane_state != NULL) { + struct dc_cursor_position position = { 0 }; + struct pipe_ctx *cur_pipe_ctx = + &dc->current_state->res_ctx.pipe_ctx[pipe_ctx->pipe_idx]; + dcn10_power_on_fe(dc, pipe_ctx, context); /* temporary dcn1 wa: @@ -2422,6 +2426,19 @@ static void program_all_pipe_in_tree( toggle_watermark_change_req(dc->hwseq); update_dchubp_dpp(dc, pipe_ctx, context); + + /* TODO: this is a hack w/a for switching from mpo to pipe split */ + dc_stream_set_cursor_position(pipe_ctx->stream, &position); + + dc_stream_set_cursor_attributes(pipe_ctx->stream, + &pipe_ctx->stream->cursor_attributes); + + if (cur_pipe_ctx->plane_state != pipe_ctx->plane_state) { + dc->hwss.set_input_transfer_func( + pipe_ctx, pipe_ctx->plane_state); + dc->hwss.set_output_transfer_func( + pipe_ctx, pipe_ctx->stream); + } } if (dc->debug.sanity_checks) { -- cgit From c196cbe065da1c9b5f7683af9cdd0889760151c1 Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Tue, 3 Oct 2017 16:47:02 -0400 Subject: drm/amd/display: add dpms state to DC follow up Signed-off-by: Hersen Wu Reviewed-by: Tony Cheng Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 92fab09843e4..4cdb855ef855 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -332,7 +332,7 @@ static void set_dither_option(struct dc_stream_state *stream, { struct bit_depth_reduction_params params; struct dc_link *link = stream->status.link; - struct pipe_ctx *pipes; + struct pipe_ctx *pipes = NULL; int i; for (i = 0; i < MAX_PIPES; i++) { @@ -344,7 +344,7 @@ static void set_dither_option(struct dc_stream_state *stream, } memset(¶ms, 0, sizeof(params)); - if (!stream) + if (!pipes) return; if (option > DITHER_OPTION_MAX) return; -- cgit From 8459f633b65a81979b9b233ed0a91a9fdc98b7bd Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Tue, 3 Oct 2017 18:15:51 -0400 Subject: drm/amd/display: Handle case when stream not found in set_dpms When validate with context fail to add stream to the context, we have a case where set_dpms won't be able to find the stream that need to be disabled. Signed-off-by: Eric Yang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 4cdb855ef855..fe66c6a21bc3 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -363,7 +363,7 @@ void set_dpms( struct dc_stream_state *stream, bool dpms_off) { - struct pipe_ctx *pipe_ctx; + struct pipe_ctx *pipe_ctx = NULL; int i; for (i = 0; i < MAX_PIPES; i++) { @@ -373,6 +373,11 @@ void set_dpms( } } + if (!pipe_ctx) { + ASSERT(0); + return; + } + if (stream->dpms_off != dpms_off) { stream->dpms_off = dpms_off; if (dpms_off) -- cgit From 410d0b39e2247778db5ead9d40330837fecb7a43 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 2 Oct 2017 15:27:26 -0400 Subject: drm/amd/display: Ignore wrong tautological warning Some of our HW calcs functions compares a var against itself to check for NaN. Gcc isn't fond of it and wrongfully warns about a tautological comparison. Disable this check for dcn_calcs_math.c. Signed-off-by: Harry Wentland Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/Makefile b/drivers/gpu/drm/amd/display/dc/calcs/Makefile index a095472bf4b5..41ef35995b02 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/Makefile +++ b/drivers/gpu/drm/amd/display/dc/calcs/Makefile @@ -5,7 +5,7 @@ CFLAGS_dcn_calcs.o := -mhard-float -msse -mpreferred-stack-boundary=4 CFLAGS_dcn_calc_auto.o := -mhard-float -msse -mpreferred-stack-boundary=4 -CFLAGS_dcn_calc_math.o := -mhard-float -msse -mpreferred-stack-boundary=4 +CFLAGS_dcn_calc_math.o := -mhard-float -msse -mpreferred-stack-boundary=4 -Wno-tautological-compare BW_CALCS = dce_calcs.o bw_fixed.o custom_float.o -- cgit From 4e9ba34f7bd54bcf4bf97ecfdd18fa60c152978c Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Tue, 3 Oct 2017 18:19:01 -0400 Subject: drm/amd/display: dal 3.1.04 Signed-off-by: Tony Cheng Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index c832d5abbbdf..8fa9ef1167fa 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -38,7 +38,7 @@ #include "inc/compressor.h" #include "dml/display_mode_lib.h" -#define DC_VER "3.1.03" +#define DC_VER "3.1.04" #define MAX_SURFACES 3 #define MAX_STREAMS 6 -- cgit From 0c63c115f254c1024d0679de859283ae48d2cf1b Mon Sep 17 00:00:00 2001 From: Eric Bernstein Date: Wed, 4 Oct 2017 16:56:27 -0400 Subject: drm/amd/display: group DCN watermark registers Signed-off-by: Eric Bernstein Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index 9a04b8758888..52506155e361 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -163,23 +163,15 @@ SR(REFCLK_CNTL), \ SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A),\ SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A),\ - SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A),\ - SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A),\ SR(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A),\ SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B),\ SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B),\ - SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B),\ - SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B),\ SR(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B),\ SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C),\ SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C),\ - SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C),\ - SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C),\ SR(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C),\ SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D),\ SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D),\ - SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D),\ - SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D),\ SR(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D),\ SR(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL),\ SR(DCHUBBUB_ARB_DRAM_STATE_CNTL),\ @@ -207,8 +199,19 @@ MMHUB_SR(MC_VM_SYSTEM_APERTURE_LOW_ADDR),\ MMHUB_SR(MC_VM_SYSTEM_APERTURE_HIGH_ADDR) +#define HWSEQ_SR_WATERMARK_REG_LIST()\ + SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A),\ + SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A),\ + SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B),\ + SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B),\ + SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C),\ + SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C),\ + SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D),\ + SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D) + #define HWSEQ_DCN1_REG_LIST()\ HWSEQ_DCN_REG_LIST(), \ + HWSEQ_SR_WATERMARK_REG_LIST(), \ HWSEQ_PIXEL_RATE_REG_LIST(OTG), \ HWSEQ_PHYPLL_REG_LIST(OTG), \ SR(DCHUBBUB_SDPIF_FB_TOP),\ -- cgit From 8feabd03d34e4555c119e69269dae28f52e0d86c Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Mon, 2 Oct 2017 14:39:42 -0400 Subject: drm/amd/display: rename struct mem_input to hubp for dcn Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 1 + drivers/gpu/drm/amd/display/dc/core/dc.c | 1 + drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 3 +- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 22 +-- drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c | 3 - .../amd/display/dc/dce110/dce110_hw_sequencer.c | 19 +-- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 88 ++++++------ .../gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c | 157 ++++++++++----------- .../gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h | 49 +++---- .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 26 ++-- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 4 +- drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h | 105 ++++++++++++++ drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h | 3 - 13 files changed, 286 insertions(+), 195 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index fd1db8dc2f35..c37f130b0170 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -485,6 +485,7 @@ static void split_stream_across_pipes( secondary_pipe->pipe_idx = pipe_idx; secondary_pipe->plane_res.mi = pool->mis[secondary_pipe->pipe_idx]; + secondary_pipe->plane_res.hubp = pool->hubps[secondary_pipe->pipe_idx]; secondary_pipe->plane_res.ipp = pool->ipps[secondary_pipe->pipe_idx]; secondary_pipe->plane_res.xfm = pool->transforms[secondary_pipe->pipe_idx]; if (primary_pipe->bottom_pipe) { diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index fe66c6a21bc3..4df5bf750257 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -47,6 +47,7 @@ #include "dc_link_ddc.h" #include "dm_helpers.h" #include "mem_input.h" +#include "hubp.h" /******************************************************************************* diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 7d750369b78b..4fb4f0068f1b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1024,7 +1024,7 @@ static int acquire_first_split_pipe( memset(pipe_ctx, 0, sizeof(*pipe_ctx)); pipe_ctx->stream_res.tg = pool->timing_generators[i]; - pipe_ctx->plane_res.mi = pool->mis[i]; + pipe_ctx->plane_res.hubp = pool->hubps[i]; pipe_ctx->plane_res.ipp = pool->ipps[i]; pipe_ctx->plane_res.xfm = pool->transforms[i]; pipe_ctx->stream_res.opp = pool->opps[i]; @@ -1359,6 +1359,7 @@ static int acquire_first_free_pipe( pipe_ctx->stream_res.tg = pool->timing_generators[i]; pipe_ctx->plane_res.mi = pool->mis[i]; + pipe_ctx->plane_res.hubp = pool->hubps[i]; pipe_ctx->plane_res.ipp = pool->ipps[i]; pipe_ctx->plane_res.xfm = pool->transforms[i]; pipe_ctx->stream_res.opp = pool->opps[i]; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 3dd44bef56eb..411678736ed4 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -200,7 +200,7 @@ bool dc_stream_set_cursor_attributes( for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; - if (pipe_ctx->stream != stream || !pipe_ctx->plane_res.mi || !pipe_ctx->plane_res.xfm) + if (pipe_ctx->stream != stream || !pipe_ctx->plane_res.xfm) continue; if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state) continue; @@ -210,10 +210,15 @@ bool dc_stream_set_cursor_attributes( pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes( pipe_ctx->plane_res.ipp, attributes); - if (pipe_ctx->plane_res.mi->funcs->set_cursor_attributes != NULL) + if (pipe_ctx->plane_res.hubp != NULL) + pipe_ctx->plane_res.hubp->funcs->set_cursor_attributes( + pipe_ctx->plane_res.hubp, attributes); + + if (pipe_ctx->plane_res.mi != NULL) pipe_ctx->plane_res.mi->funcs->set_cursor_attributes( pipe_ctx->plane_res.mi, attributes); + if (pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes != NULL) pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes( pipe_ctx->plane_res.xfm, attributes); @@ -248,7 +253,7 @@ bool dc_stream_set_cursor_position( for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp; - struct mem_input *mi = pipe_ctx->plane_res.mi; + struct hubp *hubp = pipe_ctx->plane_res.hubp; struct transform *xfm = pipe_ctx->plane_res.xfm; struct dc_cursor_position pos_cpy = *position; struct dc_cursor_mi_param param = { @@ -260,7 +265,7 @@ bool dc_stream_set_cursor_position( }; if (pipe_ctx->stream != stream || - !pipe_ctx->plane_res.mi || + (!pipe_ctx->plane_res.mi && !pipe_ctx->plane_res.hubp) || !pipe_ctx->plane_state || !pipe_ctx->plane_res.xfm) continue; @@ -276,11 +281,12 @@ bool dc_stream_set_cursor_position( if (ipp->funcs->ipp_cursor_set_position != NULL) ipp->funcs->ipp_cursor_set_position(ipp, &pos_cpy, ¶m); - if (mi->funcs->set_cursor_attributes != NULL) - mi->funcs->set_cursor_position(mi, &pos_cpy, ¶m); + if (hubp != NULL) + hubp->funcs->set_cursor_position(hubp, &pos_cpy, ¶m); + + if (xfm != NULL) + xfm->funcs->set_cursor_position(xfm, &pos_cpy, ¶m, hubp->curs_attr.width); - if (xfm->funcs->set_cursor_attributes != NULL) - xfm->funcs->set_cursor_position(xfm, &pos_cpy, ¶m, mi->curs_attr.width); } return true; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c index 83d9caa4f438..ed301c3b2736 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c @@ -685,9 +685,6 @@ void dce_mem_input_construct( dce_mi->regs = regs; dce_mi->shifts = mi_shift; dce_mi->masks = mi_mask; - - dce_mi->base.mpcc_id = 0xf; - dce_mi->base.opp_id = 0xf; } void dce112_mem_input_construct( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index bf7318246401..867a0eb9f2e0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1378,15 +1378,14 @@ static enum dc_status apply_single_controller_ctx_to_hw( } /* mst support - use total stream count */ -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) - if (pipe_ctx->plane_res.mi->funcs->allocate_mem_input != NULL) -#endif + if (pipe_ctx->plane_res.mi != NULL) { pipe_ctx->plane_res.mi->funcs->allocate_mem_input( - pipe_ctx->plane_res.mi, - stream->timing.h_total, - stream->timing.v_total, - stream->timing.pix_clk_khz, - context->stream_count); + pipe_ctx->plane_res.mi, + stream->timing.h_total, + stream->timing.v_total, + stream->timing.pix_clk_khz, + context->stream_count); + } pipe_ctx->stream->sink->link->psr_enabled = false; @@ -1556,7 +1555,7 @@ static void set_safe_displaymarks( SAFE_NBP_MARK, SAFE_NBP_MARK, SAFE_NBP_MARK, SAFE_NBP_MARK }; for (i = 0; i < MAX_PIPES; i++) { - if (res_ctx->pipe_ctx[i].stream == NULL) + if (res_ctx->pipe_ctx[i].stream == NULL || res_ctx->pipe_ctx[i].plane_res.mi == NULL) continue; res_ctx->pipe_ctx[i].plane_res.mi->funcs->mem_input_program_display_marks( @@ -1565,6 +1564,7 @@ static void set_safe_displaymarks( max_marks, max_marks, MAX_WATERMARK); + if (i == underlay_idx) res_ctx->pipe_ctx[i].plane_res.mi->funcs->mem_input_program_chroma_display_marks( res_ctx->pipe_ctx[i].plane_res.mi, @@ -1572,6 +1572,7 @@ static void set_safe_displaymarks( max_marks, max_marks, MAX_WATERMARK); + } } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index ee63155c1895..c34dbcd1fba4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -172,10 +172,10 @@ static void dcn10_log_hw_state(struct dc *dc) "min_ttu_vblank \t qos_low_wm \t qos_high_wm \n"); for (i = 0; i < pool->pipe_count; i++) { - struct mem_input *mi = pool->mis[i]; + struct hubp *hubp = pool->hubps[i]; struct dcn_hubp_state s; - dcn10_mem_input_read_state(TO_DCN10_MEM_INPUT(mi), &s); + hubp1_read_state(TO_DCN10_HUBP(hubp), &s); DTN_INFO("[%d]:\t %xh \t %xh \t %d \t %d \t " "%xh \t %xh \t %xh \t " @@ -803,7 +803,7 @@ static void power_on_plane( static void undo_DEGVIDCN10_253_wa(struct dc *dc) { struct dce_hwseq *hws = dc->hwseq; - struct mem_input *mi = dc->res_pool->mis[0]; + struct hubp *hubp = dc->res_pool->hubps[0]; int pwr_status = 0; REG_GET(DOMAIN0_PG_STATUS, DOMAIN0_PGFSM_PWR_STATUS, &pwr_status); @@ -811,7 +811,7 @@ static void undo_DEGVIDCN10_253_wa(struct dc *dc) if (pwr_status == 2) return; - mi->funcs->set_blank(mi, true); + hubp->funcs->set_blank(hubp, true); REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1); @@ -824,7 +824,7 @@ static void undo_DEGVIDCN10_253_wa(struct dc *dc) static void apply_DEGVIDCN10_253_wa(struct dc *dc) { struct dce_hwseq *hws = dc->hwseq; - struct mem_input *mi = dc->res_pool->mis[0]; + struct hubp *hubp = dc->res_pool->hubps[0]; if (dc->debug.disable_stutter) return; @@ -836,7 +836,7 @@ static void apply_DEGVIDCN10_253_wa(struct dc *dc) REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0); - mi->funcs->set_hubp_blank_en(mi, false); + hubp->funcs->set_hubp_blank_en(hubp, false); } static void bios_golden_init(struct dc *dc) @@ -1070,7 +1070,7 @@ static void reset_back_end_for_pipe( static void plane_atomic_disconnect(struct dc *dc, int fe_idx) { - struct mem_input *mi = dc->res_pool->mis[fe_idx]; + struct hubp *hubp = dc->res_pool->hubps[fe_idx]; struct mpc *mpc = dc->res_pool->mpc; int opp_id, z_idx; int mpcc_id = -1; @@ -1094,7 +1094,7 @@ static void plane_atomic_disconnect(struct dc *dc, if (dc->debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); - mi->funcs->dcc_control(mi, false, false); + hubp->funcs->dcc_control(hubp, false, false); if (dc->debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); @@ -1108,20 +1108,20 @@ static void plane_atomic_disable(struct dc *dc, int fe_idx) { struct dce_hwseq *hws = dc->hwseq; - struct mem_input *mi = dc->res_pool->mis[fe_idx]; + struct hubp *hubp = dc->res_pool->hubps[fe_idx]; struct mpc *mpc = dc->res_pool->mpc; - int opp_id = mi->opp_id; + int opp_id = hubp->opp_id; if (opp_id == 0xf) return; - mpc->funcs->wait_for_idle(mpc, mi->mpcc_id); - dc->res_pool->opps[mi->opp_id]->mpcc_disconnect_pending[mi->mpcc_id] = false; + mpc->funcs->wait_for_idle(mpc, hubp->mpcc_id); + dc->res_pool->opps[hubp->opp_id]->mpcc_disconnect_pending[hubp->mpcc_id] = false; /*dm_logger_write(dc->ctx->logger, LOG_ERROR, "[debug_mpo: atomic disable finished on mpcc %d]\n", fe_idx);*/ - mi->funcs->set_blank(mi, true); + hubp->funcs->set_blank(hubp, true); if (dc->debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); @@ -1171,7 +1171,7 @@ static void reset_front_end( { struct dce_hwseq *hws = dc->hwseq; struct timing_generator *tg; - int opp_id = dc->res_pool->mis[fe_idx]->opp_id; + int opp_id = dc->res_pool->hubps[fe_idx]->opp_id; /*Already reset*/ if (opp_id == 0xf) @@ -1353,8 +1353,8 @@ static void dcn10_update_plane_addr(const struct dc *dc, struct pipe_ctx *pipe_c if (plane_state == NULL) return; addr_patched = patch_address_for_sbs_tb_stereo(pipe_ctx, &addr); - pipe_ctx->plane_res.mi->funcs->mem_input_program_surface_flip_and_addr( - pipe_ctx->plane_res.mi, + pipe_ctx->plane_res.hubp->funcs->hubp_program_surface_flip_and_addr( + pipe_ctx->plane_res.hubp, &plane_state->address, plane_state->flip_immediate); plane_state->status.requested_address = plane_state->address; @@ -1759,8 +1759,8 @@ static void dcn10_pipe_control_lock( struct pipe_ctx *pipe, bool lock) { - struct mem_input *mi = NULL; - mi = dc->res_pool->mis[pipe->pipe_idx]; + struct hubp *hubp = NULL; + hubp = dc->res_pool->hubps[pipe->pipe_idx]; /* use TG master update lock to lock everything on the TG * therefore only top pipe need to lock */ @@ -2181,7 +2181,7 @@ static void dcn10_get_surface_visual_confirm_color( } } -static void mmhub_read_vm_system_aperture_settings(struct dcn10_mem_input *mi, +static void mmhub_read_vm_system_aperture_settings(struct dcn10_hubp *hubp1, struct vm_system_aperture_param *apt, struct dce_hwseq *hws) { @@ -2206,7 +2206,7 @@ static void mmhub_read_vm_system_aperture_settings(struct dcn10_mem_input *mi, } /* Temporary read settings, future will get values from kmd directly */ -static void mmhub_read_vm_context0_settings(struct dcn10_mem_input *mi, +static void mmhub_read_vm_context0_settings(struct dcn10_hubp *hubp1, struct vm_context0_param *vm0, struct dce_hwseq *hws) { @@ -2250,22 +2250,22 @@ static void mmhub_read_vm_context0_settings(struct dcn10_mem_input *mi, vm0->pte_base.quad_part -= fb_offset.quad_part; } -static void dcn10_program_pte_vm(struct mem_input *mem_input, +static void dcn10_program_pte_vm(struct hubp *hubp, enum surface_pixel_format format, union dc_tiling_info *tiling_info, enum dc_rotation_angle rotation, struct dce_hwseq *hws) { - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); struct vm_system_aperture_param apt = { {{ 0 } } }; struct vm_context0_param vm0 = { { { 0 } } }; - mmhub_read_vm_system_aperture_settings(mi, &apt, hws); - mmhub_read_vm_context0_settings(mi, &vm0, hws); + mmhub_read_vm_system_aperture_settings(hubp1, &apt, hws); + mmhub_read_vm_context0_settings(hubp1, &vm0, hws); - mem_input->funcs->mem_input_set_vm_system_aperture_settings(mem_input, &apt); - mem_input->funcs->mem_input_set_vm_context0_settings(mem_input, &vm0); + hubp->funcs->hubp_set_vm_system_aperture_settings(hubp, &apt); + hubp->funcs->hubp_set_vm_context0_settings(hubp, &vm0); } static void update_dchubp_dpp( @@ -2274,7 +2274,7 @@ static void update_dchubp_dpp( struct dc_state *context) { struct dce_hwseq *hws = dc->hwseq; - struct mem_input *mi = pipe_ctx->plane_res.mi; + struct hubp *hubp = pipe_ctx->plane_res.hubp; struct transform *xfm = pipe_ctx->plane_res.xfm; struct dc_plane_state *plane_state = pipe_ctx->plane_state; union plane_size size = plane_state->plane_size; @@ -2299,8 +2299,8 @@ static void update_dchubp_dpp( */ REG_UPDATE(DCHUBP_CNTL[pipe_ctx->pipe_idx], HUBP_VTG_SEL, pipe_ctx->stream_res.tg->inst); - mi->funcs->mem_input_setup( - mi, + hubp->funcs->hubp_setup( + hubp, &pipe_ctx->dlg_regs, &pipe_ctx->ttu_regs, &pipe_ctx->rq_regs, @@ -2310,7 +2310,7 @@ static void update_dchubp_dpp( if (dc->config.gpu_vm_support) dcn10_program_pte_vm( - pipe_ctx->plane_res.mi, + pipe_ctx->plane_res.hubp, plane_state->format, &plane_state->tiling_info, plane_state->rotation, @@ -2321,7 +2321,7 @@ static void update_dchubp_dpp( plane_state->format, EXPANSION_MODE_ZERO); - mpcc_cfg.dpp_id = mi->inst; + mpcc_cfg.dpp_id = hubp->inst; mpcc_cfg.opp_id = pipe_ctx->stream_res.opp->inst; mpcc_cfg.tree_cfg = &(pipe_ctx->stream_res.opp->mpc_tree); for (top_pipe = pipe_ctx->top_pipe; top_pipe; top_pipe = top_pipe->top_pipe) @@ -2340,15 +2340,15 @@ static void update_dchubp_dpp( mpcc_cfg.pre_multiplied_alpha = is_rgb_cspace( pipe_ctx->stream->output_color_space) && per_pixel_alpha; - mi->mpcc_id = dc->res_pool->mpc->funcs->add(dc->res_pool->mpc, &mpcc_cfg); - mi->opp_id = mpcc_cfg.opp_id; + hubp->mpcc_id = dc->res_pool->mpc->funcs->add(dc->res_pool->mpc, &mpcc_cfg); + hubp->opp_id = mpcc_cfg.opp_id; pipe_ctx->plane_res.scl_data.lb_params.alpha_en = per_pixel_alpha; pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; /* scaler configuration */ pipe_ctx->plane_res.xfm->funcs->transform_set_scaler( pipe_ctx->plane_res.xfm, &pipe_ctx->plane_res.scl_data); - mi->funcs->mem_program_viewport(mi, + hubp->funcs->mem_program_viewport(hubp, &pipe_ctx->plane_res.scl_data.viewport, &pipe_ctx->plane_res.scl_data.viewport_c); /*gamut remap*/ @@ -2358,8 +2358,8 @@ static void update_dchubp_dpp( pipe_ctx->stream->output_color_space, pipe_ctx->stream->csc_color_matrix.matrix); - mi->funcs->mem_input_program_surface_config( - mi, + hubp->funcs->hubp_program_surface_config( + hubp, plane_state->format, &plane_state->tiling_info, &size, @@ -2370,7 +2370,7 @@ static void update_dchubp_dpp( dc->hwss.update_plane_addr(dc, pipe_ctx); if (is_pipe_tree_visible(pipe_ctx)) - mi->funcs->set_blank(mi, false); + hubp->funcs->set_blank(hubp, false); } @@ -2550,7 +2550,7 @@ static void dcn10_apply_ctx_for_surface( */ if (pipe_ctx->plane_state && !old_pipe_ctx->plane_state) { - if (pipe_ctx->plane_res.mi->opp_id != 0xf && pipe_ctx->stream_res.tg->inst == be_idx) { + if (pipe_ctx->plane_res.hubp->opp_id != 0xf && pipe_ctx->stream_res.tg->inst == be_idx) { dcn10_power_down_fe(dc, pipe_ctx->pipe_idx); /* * power down fe will unlock when calling reset, need @@ -2577,7 +2577,7 @@ static void dcn10_apply_ctx_for_surface( &(old_pipe_ctx->stream_res.opp->mpc_tree), old_pipe_ctx->stream_res.opp->inst, old_pipe_ctx->pipe_idx); - old_pipe_ctx->stream_res.opp->mpcc_disconnect_pending[old_pipe_ctx->plane_res.mi->mpcc_id] = true; + old_pipe_ctx->stream_res.opp->mpcc_disconnect_pending[old_pipe_ctx->plane_res.hubp->mpcc_id] = true; /*dm_logger_write(dc->ctx->logger, LOG_ERROR, "[debug_mpo: apply_ctx disconnect pending on mpcc %d]\n", @@ -2861,7 +2861,7 @@ static void dcn10_wait_for_mpcc_disconnect( if (pipe_ctx->stream_res.opp->mpcc_disconnect_pending[i]) { res_pool->mpc->funcs->wait_for_idle(res_pool->mpc, i); pipe_ctx->stream_res.opp->mpcc_disconnect_pending[i] = false; - res_pool->mis[i]->funcs->set_blank(res_pool->mis[i], true); + res_pool->hubps[i]->funcs->set_blank(res_pool->hubps[i], true); /*dm_logger_write(dc->ctx->logger, LOG_ERROR, "[debug_mpo: wait_for_mpcc finished waiting on mpcc %d]\n", i);*/ @@ -2892,11 +2892,11 @@ void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx) return; plane_state->status.is_flip_pending = - pipe_ctx->plane_res.mi->funcs->mem_input_is_flip_pending( - pipe_ctx->plane_res.mi); + pipe_ctx->plane_res.hubp->funcs->hubp_is_flip_pending( + pipe_ctx->plane_res.hubp); - plane_state->status.current_address = pipe_ctx->plane_res.mi->current_address; - if (pipe_ctx->plane_res.mi->current_address.type == PLN_ADDR_TYPE_GRPH_STEREO && + plane_state->status.current_address = pipe_ctx->plane_res.hubp->current_address; + if (pipe_ctx->plane_res.hubp->current_address.type == PLN_ADDR_TYPE_GRPH_STEREO && tg->funcs->is_stereo_left_eye) { plane_state->status.is_right_eye = !tg->funcs->is_stereo_left_eye(pipe_ctx->stream_res.tg); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index 2336da54000c..9ee42d9840fb 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -29,18 +29,18 @@ #include "basics/conversion.h" #define REG(reg)\ - mi->mi_regs->reg + hubp1->mi_regs->reg #define CTX \ - mi->base.ctx + hubp1->base.ctx #undef FN #define FN(reg_name, field_name) \ - mi->mi_shift->field_name, mi->mi_mask->field_name + hubp1->mi_shift->field_name, hubp1->mi_mask->field_name -void hubp1_set_blank(struct mem_input *mem_input, bool blank) +void hubp1_set_blank(struct hubp *hubp, bool blank) { - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); uint32_t blank_en = blank ? 1 : 0; REG_UPDATE_2(DCHUBP_CNTL, @@ -51,24 +51,24 @@ void hubp1_set_blank(struct mem_input *mem_input, bool blank) REG_WAIT(DCHUBP_CNTL, HUBP_NO_OUTSTANDING_REQ, 1, 1, 200); - mem_input->mpcc_id = 0xf; - mem_input->opp_id = 0xf; + hubp->mpcc_id = 0xf; + hubp->opp_id = 0xf; } } -static void hubp1_set_hubp_blank_en(struct mem_input *mem_input, bool blank) +static void hubp1_set_hubp_blank_en(struct hubp *hubp, bool blank) { - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); uint32_t blank_en = blank ? 1 : 0; REG_UPDATE(DCHUBP_CNTL, HUBP_BLANK_EN, blank_en); } -static void hubp1_vready_workaround(struct mem_input *mem_input, +static void hubp1_vready_workaround(struct hubp *hubp, struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest) { uint32_t value = 0; - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); /* set HBUBREQ_DEBUG_DB[12] = 1 */ value = REG_READ(HUBPREQ_DEBUG_DB); @@ -88,7 +88,7 @@ static void hubp1_vready_workaround(struct mem_input *mem_input, } void hubp1_program_tiling( - struct dcn10_mem_input *mi, + struct dcn10_hubp *hubp1, const union dc_tiling_info *info, const enum surface_pixel_format pixel_format) { @@ -108,7 +108,7 @@ void hubp1_program_tiling( } void hubp1_program_size_and_rotation( - struct dcn10_mem_input *mi, + struct dcn10_hubp *hubp1, enum dc_rotation_angle rotation, enum surface_pixel_format format, const union plane_size *plane_size, @@ -170,7 +170,7 @@ void hubp1_program_size_and_rotation( } void hubp1_program_pixel_format( - struct dcn10_mem_input *mi, + struct dcn10_hubp *hubp1, enum surface_pixel_format format) { uint32_t red_bar = 3; @@ -246,11 +246,11 @@ void hubp1_program_pixel_format( } bool hubp1_program_surface_flip_and_addr( - struct mem_input *mem_input, + struct hubp *hubp, const struct dc_plane_address *address, bool flip_immediate) { - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); /* program flip type */ REG_SET(DCSURF_FLIP_CONTROL, 0, @@ -387,20 +387,20 @@ bool hubp1_program_surface_flip_and_addr( break; } - mem_input->request_address = *address; + hubp->request_address = *address; if (flip_immediate) - mem_input->current_address = *address; + hubp->current_address = *address; return true; } -void hubp1_dcc_control(struct mem_input *mem_input, bool enable, +void hubp1_dcc_control(struct hubp *hubp, bool enable, bool independent_64b_blks) { uint32_t dcc_en = enable ? 1 : 0; uint32_t dcc_ind_64b_blk = independent_64b_blks ? 1 : 0; - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); REG_UPDATE_2(DCSURF_SURFACE_CONTROL, PRIMARY_SURFACE_DCC_EN, dcc_en, @@ -408,7 +408,7 @@ void hubp1_dcc_control(struct mem_input *mem_input, bool enable, } void hubp1_program_surface_config( - struct mem_input *mem_input, + struct hubp *hubp, enum surface_pixel_format format, union dc_tiling_info *tiling_info, union plane_size *plane_size, @@ -416,20 +416,20 @@ void hubp1_program_surface_config( struct dc_plane_dcc_param *dcc, bool horizontal_mirror) { - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); - hubp1_dcc_control(mem_input, dcc->enable, dcc->grph.independent_64b_blks); - hubp1_program_tiling(mi, tiling_info, format); + hubp1_dcc_control(hubp, dcc->enable, dcc->grph.independent_64b_blks); + hubp1_program_tiling(hubp1, tiling_info, format); hubp1_program_size_and_rotation( - mi, rotation, format, plane_size, dcc, horizontal_mirror); - hubp1_program_pixel_format(mi, format); + hubp1, rotation, format, plane_size, dcc, horizontal_mirror); + hubp1_program_pixel_format(hubp1, format); } void hubp1_program_requestor( - struct mem_input *mem_input, + struct hubp *hubp, struct _vcs_dpi_display_rq_regs_st *rq_regs) { - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); REG_UPDATE(HUBPRET_CONTROL, DET_BUF_PLANE1_BASE_ADDRESS, rq_regs->plane1_base_address); @@ -460,11 +460,11 @@ void hubp1_program_requestor( void hubp1_program_deadline( - struct mem_input *mem_input, + struct hubp *hubp, struct _vcs_dpi_display_dlg_regs_st *dlg_attr, struct _vcs_dpi_display_ttu_regs_st *ttu_attr) { - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); /* DLG - Per hubp */ REG_SET_2(BLANK_OFFSET_0, 0, @@ -581,7 +581,7 @@ void hubp1_program_deadline( } static void hubp1_setup( - struct mem_input *mem_input, + struct hubp *hubp, struct _vcs_dpi_display_dlg_regs_st *dlg_attr, struct _vcs_dpi_display_ttu_regs_st *ttu_attr, struct _vcs_dpi_display_rq_regs_st *rq_regs, @@ -590,27 +590,15 @@ static void hubp1_setup( /* otg is locked when this func is called. Register are double buffered. * disable the requestors is not needed */ - hubp1_program_requestor(mem_input, rq_regs); - hubp1_program_deadline(mem_input, dlg_attr, ttu_attr); - hubp1_vready_workaround(mem_input, pipe_dest); + hubp1_program_requestor(hubp, rq_regs); + hubp1_program_deadline(hubp, dlg_attr, ttu_attr); + hubp1_vready_workaround(hubp, pipe_dest); } -void hubp1_program_display_marks( - struct mem_input *mem_input, - struct dce_watermarks nbp, - struct dce_watermarks stutter, - struct dce_watermarks urgent, - uint32_t total_dest_line_time_ns) -{ - /* only for dce - * dcn use only program_watermarks - */ -} - -bool hubp1_is_flip_pending(struct mem_input *mem_input) +bool hubp1_is_flip_pending(struct hubp *hubp) { uint32_t flip_pending = 0; - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); struct dc_plane_address earliest_inuse_address; REG_GET(DCSURF_FLIP_CONTROL, @@ -625,20 +613,20 @@ bool hubp1_is_flip_pending(struct mem_input *mem_input) if (flip_pending) return true; - if (earliest_inuse_address.grph.addr.quad_part != mem_input->request_address.grph.addr.quad_part) + if (earliest_inuse_address.grph.addr.quad_part != hubp->request_address.grph.addr.quad_part) return true; - mem_input->current_address = mem_input->request_address; + hubp->current_address = hubp->request_address; return false; } uint32_t aperture_default_system = 1; uint32_t context0_default_system; /* = 0;*/ -static void hubp1_set_vm_system_aperture_settings(struct mem_input *mem_input, +static void hubp1_set_vm_system_aperture_settings(struct hubp *hubp, struct vm_system_aperture_param *apt) { - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); PHYSICAL_ADDRESS_LOC mc_vm_apt_default; PHYSICAL_ADDRESS_LOC mc_vm_apt_low; PHYSICAL_ADDRESS_LOC mc_vm_apt_high; @@ -664,10 +652,10 @@ static void hubp1_set_vm_system_aperture_settings(struct mem_input *mem_input, MC_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, mc_vm_apt_high.low_part); } -static void hubp1_set_vm_context0_settings(struct mem_input *mem_input, +static void hubp1_set_vm_context0_settings(struct hubp *hubp, const struct vm_context0_param *vm0) { - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); /* pte base */ REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, 0, VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, vm0->pte_base.high_part); @@ -700,11 +688,11 @@ static void hubp1_set_vm_context0_settings(struct mem_input *mem_input, } void min_set_viewport( - struct mem_input *mem_input, + struct hubp *hubp, const struct rect *viewport, const struct rect *viewport_c) { - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); REG_SET_2(DCSURF_PRI_VIEWPORT_DIMENSION, 0, PRI_VIEWPORT_WIDTH, viewport->width, @@ -733,7 +721,7 @@ void min_set_viewport( PRI_VIEWPORT_Y_START_C, viewport_c->y); } -void dcn10_mem_input_read_state(struct dcn10_mem_input *mi, +void hubp1_read_state(struct dcn10_hubp *hubp1, struct dcn_hubp_state *s) { REG_GET(DCSURF_SURFACE_CONFIG, @@ -783,7 +771,7 @@ enum cursor_lines_per_chunk { }; static bool ippn10_cursor_program_control( - struct dcn10_mem_input *mi, + struct dcn10_hubp *hubp1, bool pixel_data_invert, enum dc_cursor_color_format color_format) { @@ -849,15 +837,15 @@ static enum cursor_lines_per_chunk ippn10_get_lines_per_chunk( } void hubp1_cursor_set_attributes( - struct mem_input *mem_input, + struct hubp *hubp, const struct dc_cursor_attributes *attr) { - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); enum cursor_pitch hw_pitch = ippn10_get_cursor_pitch(attr->pitch); enum cursor_lines_per_chunk lpc = ippn10_get_lines_per_chunk( attr->width, attr->color_format); - mem_input->curs_attr = *attr; + hubp->curs_attr = *attr; REG_UPDATE(CURSOR_SURFACE_ADDRESS_HIGH, CURSOR_SURFACE_ADDRESS_HIGH, attr->address.high_part); @@ -871,17 +859,17 @@ void hubp1_cursor_set_attributes( CURSOR_MODE, attr->color_format, CURSOR_PITCH, hw_pitch, CURSOR_LINES_PER_CHUNK, lpc); - ippn10_cursor_program_control(mi, + ippn10_cursor_program_control(hubp1, attr->attribute_flags.bits.INVERT_PIXEL_DATA, attr->color_format); } void hubp1_cursor_set_position( - struct mem_input *mem_input, + struct hubp *hubp, const struct dc_cursor_position *pos, const struct dc_cursor_mi_param *param) { - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); int src_x_offset = pos->x - pos->x_hotspot - param->viewport_x_start; uint32_t cur_en = pos->enable ? 1 : 0; uint32_t dst_x_offset = (src_x_offset >= 0) ? src_x_offset : 0; @@ -893,7 +881,7 @@ void hubp1_cursor_set_position( * TODO: Look at combining cursor_set_position() and * cursor_set_attributes() into cursor_update() */ - if (mem_input->curs_attr.address.quad_part == 0) + if (hubp->curs_attr.address.quad_part == 0) return; dst_x_offset *= param->ref_clk_khz; @@ -909,11 +897,11 @@ void hubp1_cursor_set_position( if (src_x_offset >= (int)param->viewport_width) cur_en = 0; /* not visible beyond right edge*/ - if (src_x_offset + (int)mem_input->curs_attr.width < 0) + if (src_x_offset + (int)hubp->curs_attr.width < 0) cur_en = 0; /* not visible beyond left edge*/ if (cur_en && REG_READ(CURSOR_SURFACE_ADDRESS) == 0) - hubp1_cursor_set_attributes(mem_input, &mem_input->curs_attr); + hubp1_cursor_set_attributes(hubp, &hubp->curs_attr); REG_UPDATE(CURSOR_CONTROL, CURSOR_ENABLE, cur_en); @@ -930,16 +918,15 @@ void hubp1_cursor_set_position( /* TODO Handle surface pixel formats other than 4:4:4 */ } -static struct mem_input_funcs dcn10_mem_input_funcs = { - .mem_input_program_display_marks = hubp1_program_display_marks, - .mem_input_program_surface_flip_and_addr = +static struct hubp_funcs dcn10_hubp_funcs = { + .hubp_program_surface_flip_and_addr = hubp1_program_surface_flip_and_addr, - .mem_input_program_surface_config = + .hubp_program_surface_config = hubp1_program_surface_config, - .mem_input_is_flip_pending = hubp1_is_flip_pending, - .mem_input_setup = hubp1_setup, - .mem_input_set_vm_system_aperture_settings = hubp1_set_vm_system_aperture_settings, - .mem_input_set_vm_context0_settings = hubp1_set_vm_context0_settings, + .hubp_is_flip_pending = hubp1_is_flip_pending, + .hubp_setup = hubp1_setup, + .hubp_set_vm_system_aperture_settings = hubp1_set_vm_system_aperture_settings, + .hubp_set_vm_context0_settings = hubp1_set_vm_context0_settings, .set_blank = hubp1_set_blank, .dcc_control = hubp1_dcc_control, .mem_program_viewport = min_set_viewport, @@ -952,22 +939,22 @@ static struct mem_input_funcs dcn10_mem_input_funcs = { /* Constructor, Destructor */ /*****************************************/ -void dcn10_mem_input_construct( - struct dcn10_mem_input *mi, +void dcn10_hubp_construct( + struct dcn10_hubp *hubp1, struct dc_context *ctx, uint32_t inst, const struct dcn_mi_registers *mi_regs, const struct dcn_mi_shift *mi_shift, const struct dcn_mi_mask *mi_mask) { - mi->base.funcs = &dcn10_mem_input_funcs; - mi->base.ctx = ctx; - mi->mi_regs = mi_regs; - mi->mi_shift = mi_shift; - mi->mi_mask = mi_mask; - mi->base.inst = inst; - mi->base.opp_id = 0xf; - mi->base.mpcc_id = 0xf; + hubp1->base.funcs = &dcn10_hubp_funcs; + hubp1->base.ctx = ctx; + hubp1->mi_regs = mi_regs; + hubp1->mi_shift = mi_shift; + hubp1->mi_mask = mi_mask; + hubp1->base.inst = inst; + hubp1->base.opp_id = 0xf; + hubp1->base.mpcc_id = 0xf; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h index 5c5eed5c95d5..66db453c801b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h @@ -25,10 +25,10 @@ #ifndef __DC_MEM_INPUT_DCN10_H__ #define __DC_MEM_INPUT_DCN10_H__ -#include "mem_input.h" +#include "hubp.h" -#define TO_DCN10_MEM_INPUT(mi)\ - container_of(mi, struct dcn10_mem_input, base) +#define TO_DCN10_HUBP(hubp)\ + container_of(hubp, struct dcn10_hubp, base) #define MI_REG_LIST_DCN(id)\ SRI(DCHUBP_CNTL, HUBP, id),\ @@ -584,15 +584,15 @@ struct dcn_mi_mask { DCN_MI_REG_FIELD_LIST(uint32_t); }; -struct dcn10_mem_input { - struct mem_input base; +struct dcn10_hubp { + struct hubp base; const struct dcn_mi_registers *mi_regs; const struct dcn_mi_shift *mi_shift; const struct dcn_mi_mask *mi_mask; }; void hubp1_program_surface_config( - struct mem_input *mem_input, + struct hubp *hubp, enum surface_pixel_format format, union dc_tiling_info *tiling_info, union plane_size *plane_size, @@ -601,20 +601,20 @@ void hubp1_program_surface_config( bool horizontal_mirror); void hubp1_program_deadline( - struct mem_input *mem_input, + struct hubp *hubp, struct _vcs_dpi_display_dlg_regs_st *dlg_attr, struct _vcs_dpi_display_ttu_regs_st *ttu_attr); void hubp1_program_requestor( - struct mem_input *mem_input, + struct hubp *hubp, struct _vcs_dpi_display_rq_regs_st *rq_regs); void hubp1_program_pixel_format( - struct dcn10_mem_input *mi, + struct dcn10_hubp *hubp, enum surface_pixel_format format); void hubp1_program_size_and_rotation( - struct dcn10_mem_input *mi, + struct dcn10_hubp *hubp, enum dc_rotation_angle rotation, enum surface_pixel_format format, const union plane_size *plane_size, @@ -622,45 +622,38 @@ void hubp1_program_size_and_rotation( bool horizontal_mirror); void hubp1_program_tiling( - struct dcn10_mem_input *mi, + struct dcn10_hubp *hubp, const union dc_tiling_info *info, const enum surface_pixel_format pixel_format); -void hubp1_dcc_control(struct mem_input *mem_input, +void hubp1_dcc_control(struct hubp *hubp, bool enable, bool independent_64b_blks); -void hubp1_program_display_marks( - struct mem_input *mem_input, - struct dce_watermarks nbp, - struct dce_watermarks stutter, - struct dce_watermarks urgent, - uint32_t total_dest_line_time_ns); - bool hubp1_program_surface_flip_and_addr( - struct mem_input *mem_input, + struct hubp *hubp, const struct dc_plane_address *address, bool flip_immediate); -bool hubp1_is_flip_pending(struct mem_input *mem_input); +bool hubp1_is_flip_pending(struct hubp *hubp); void hubp1_cursor_set_attributes( - struct mem_input *mem_input, + struct hubp *hubp, const struct dc_cursor_attributes *attr); void hubp1_cursor_set_position( - struct mem_input *mem_input, + struct hubp *hubp, const struct dc_cursor_position *pos, const struct dc_cursor_mi_param *param); -void hubp1_set_blank(struct mem_input *mem_input, bool blank); +void hubp1_set_blank(struct hubp *hubp, bool blank); -void min_set_viewport(struct mem_input *mem_input, +void min_set_viewport(struct hubp *hubp, const struct rect *viewport, const struct rect *viewport_c); -void dcn10_mem_input_construct( - struct dcn10_mem_input *mi, +void dcn10_hubp_construct( + struct dcn10_hubp *hubp1, struct dc_context *ctx, uint32_t inst, const struct dcn_mi_registers *mi_regs, @@ -684,7 +677,7 @@ struct dcn_hubp_state { uint32_t qos_level_low_wm; uint32_t qos_level_high_wm; }; -void dcn10_mem_input_read_state(struct dcn10_mem_input *mi, +void hubp1_read_state(struct dcn10_hubp *hubp1, struct dcn_hubp_state *s); #endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 2caad73257e0..93edbba762e8 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -704,9 +704,9 @@ static void destruct(struct dcn10_resource_pool *pool) if (pool->base.ipps[i] != NULL) pool->base.ipps[i]->funcs->ipp_destroy(&pool->base.ipps[i]); - if (pool->base.mis[i] != NULL) { - kfree(TO_DCN10_MEM_INPUT(pool->base.mis[i])); - pool->base.mis[i] = NULL; + if (pool->base.hubps[i] != NULL) { + kfree(TO_DCN10_HUBP(pool->base.hubps[i])); + pool->base.hubps[i] = NULL; } if (pool->base.irqs != NULL) { @@ -753,19 +753,19 @@ static void destruct(struct dcn10_resource_pool *pool) kfree(pool->base.pp_smu); } -static struct mem_input *dcn10_mem_input_create( +static struct hubp *dcn10_hubp_create( struct dc_context *ctx, uint32_t inst) { - struct dcn10_mem_input *mem_inputn10 = - kzalloc(sizeof(struct dcn10_mem_input), GFP_KERNEL); + struct dcn10_hubp *hubp1 = + kzalloc(sizeof(struct dcn10_hubp), GFP_KERNEL); - if (!mem_inputn10) + if (!hubp1) return NULL; - dcn10_mem_input_construct(mem_inputn10, ctx, inst, - &mi_regs[inst], &mi_shift, &mi_mask); - return &mem_inputn10->base; + dcn10_hubp_construct(hubp1, ctx, inst, + &mi_regs[inst], &mi_shift, &mi_mask); + return &hubp1->base; } static void get_pixel_clock_parameters( @@ -918,7 +918,7 @@ static struct pipe_ctx *dcn10_acquire_idle_pipe_for_layer( idle_pipe->stream_res.tg = head_pipe->stream_res.tg; idle_pipe->stream_res.opp = head_pipe->stream_res.opp; - idle_pipe->plane_res.mi = pool->mis[idle_pipe->pipe_idx]; + idle_pipe->plane_res.hubp = pool->hubps[idle_pipe->pipe_idx]; idle_pipe->plane_res.ipp = pool->ipps[idle_pipe->pipe_idx]; idle_pipe->plane_res.xfm = pool->transforms[idle_pipe->pipe_idx]; @@ -1357,8 +1357,8 @@ static bool construct( if ((pipe_fuses & (1 << i)) != 0) continue; - pool->base.mis[j] = dcn10_mem_input_create(ctx, i); - if (pool->base.mis[j] == NULL) { + pool->base.hubps[j] = dcn10_hubp_create(ctx, i); + if (pool->base.hubps[j] == NULL) { BREAK_TO_DEBUGGER(); dm_error( "DC: failed to create memory input!\n"); diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 118122d12e2b..45518c05e846 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -32,6 +32,7 @@ #include "ddc_service_types.h" #include "dc_bios_types.h" #include "mem_input.h" +#include "hubp.h" #if defined(CONFIG_DRM_AMD_DC_DCN1_0) #include "mpc.h" #endif @@ -129,6 +130,7 @@ struct audio_support{ struct resource_pool { struct mem_input *mis[MAX_PIPES]; + struct hubp *hubps[MAX_PIPES]; struct input_pixel_processor *ipps[MAX_PIPES]; struct transform *transforms[MAX_PIPES]; struct output_pixel_processor *opps[MAX_PIPES]; @@ -178,7 +180,7 @@ struct stream_resource { struct plane_resource { struct scaler_data scl_data; - + struct hubp *hubp; struct mem_input *mi; struct input_pixel_processor *ipp; struct transform *xfm; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h new file mode 100644 index 000000000000..0d186be24cf4 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h @@ -0,0 +1,105 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_HUBP_H__ +#define __DAL_HUBP_H__ + +#include "mem_input.h" + +struct hubp { + struct hubp_funcs *funcs; + struct dc_context *ctx; + struct dc_plane_address request_address; + struct dc_plane_address current_address; + int inst; + int opp_id; + int mpcc_id; + struct dc_cursor_attributes curs_attr; +}; + + +struct hubp_funcs { + void (*hubp_setup)( + struct hubp *hubp, + struct _vcs_dpi_display_dlg_regs_st *dlg_regs, + struct _vcs_dpi_display_ttu_regs_st *ttu_regs, + struct _vcs_dpi_display_rq_regs_st *rq_regs, + struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest); + + void (*dcc_control)(struct hubp *hubp, bool enable, + bool independent_64b_blks); + void (*mem_program_viewport)( + struct hubp *hubp, + const struct rect *viewport, + const struct rect *viewport_c); + + bool (*hubp_program_surface_flip_and_addr)( + struct hubp *hubp, + const struct dc_plane_address *address, + bool flip_immediate); + + void (*hubp_program_pte_vm)( + struct hubp *hubp, + enum surface_pixel_format format, + union dc_tiling_info *tiling_info, + enum dc_rotation_angle rotation); + + void (*hubp_set_vm_system_aperture_settings)( + struct hubp *hubp, + struct vm_system_aperture_param *apt); + + void (*hubp_set_vm_context0_settings)( + struct hubp *hubp, + const struct vm_context0_param *vm0); + + void (*hubp_program_surface_config)( + struct hubp *hubp, + enum surface_pixel_format format, + union dc_tiling_info *tiling_info, + union plane_size *plane_size, + enum dc_rotation_angle rotation, + struct dc_plane_dcc_param *dcc, + bool horizontal_mirror); + + bool (*hubp_is_flip_pending)(struct hubp *hubp); + + void (*hubp_update_dchub)(struct hubp *hubp, + struct dchub_init_data *dh_data); + + void (*set_blank)(struct hubp *hubp, bool blank); + void (*set_hubp_blank_en)(struct hubp *hubp, bool blank); + + void (*set_cursor_attributes)( + struct hubp *hubp, + const struct dc_cursor_attributes *attr); + + void (*set_cursor_position)( + struct hubp *hubp, + const struct dc_cursor_position *pos, + const struct dc_cursor_mi_param *param); + +}; + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h index 5c8e45ba8f45..3e1e7e6a8792 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h @@ -69,10 +69,7 @@ struct mem_input { struct dc_plane_address request_address; struct dc_plane_address current_address; int inst; - int opp_id; - int mpcc_id; struct stutter_modes stutter_mode; - struct dc_cursor_attributes curs_attr; }; struct vm_system_aperture_param { -- cgit From 81739b7f49bfded3bbd0b29c5213e9bcbea3c58d Mon Sep 17 00:00:00 2001 From: Eric Bernstein Date: Mon, 2 Oct 2017 15:03:50 -0400 Subject: drm/amd/display: Add DPP capabilities Signed-off-by: Eric Bernstein Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c | 5 +++ drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h | 23 +++-------- .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c | 42 +++++++------------- drivers/gpu/drm/amd/display/dc/inc/hw/transform.h | 46 ++++++++++++++++++++++ 4 files changed, 72 insertions(+), 44 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c index 05df3b222945..fb3c78858ebe 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c @@ -444,6 +444,10 @@ static const struct transform_funcs dcn10_dpp_funcs = { .set_cursor_position = dcn10_set_cursor_position, }; +static struct dpp_caps dcn10_dpp_cap = { + .dscl_data_proc_format = DSCL_DATA_PRCESSING_FIXED_FORMAT, + .dscl_calc_lb_num_partitions = dscl1_calc_lb_num_partitions, +}; /*****************************************/ /* Constructor, Destructor */ @@ -461,6 +465,7 @@ void dcn10_dpp_construct( xfm->base.inst = inst; xfm->base.funcs = &dcn10_dpp_funcs; + xfm->base.caps = &dcn10_dpp_cap; xfm->tf_regs = tf_regs; xfm->tf_shift = tf_shift; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h index 153aa3c32762..4cf18a500dcd 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h @@ -1264,23 +1264,6 @@ struct dcn10_dpp { bool is_write_to_ram_a_safe; }; - -enum lb_memory_config { - /* Enable all 3 pieces of memory */ - LB_MEMORY_CONFIG_0 = 0, - - /* Enable only the first piece of memory */ - LB_MEMORY_CONFIG_1 = 1, - - /* Enable only the second piece of memory */ - LB_MEMORY_CONFIG_2 = 2, - - /* Only applicable in 4:2:0 mode, enable all 3 pieces of memory and the - * last piece of chroma memory used for the luma storage - */ - LB_MEMORY_CONFIG_3 = 3 -}; - enum dcn10_input_csc_select { INPUT_CSC_SELECT_BYPASS = 0, INPUT_CSC_SELECT_ICSC, @@ -1292,6 +1275,12 @@ bool is_lb_conf_valid( int num_partitions, int vtaps); +void dscl1_calc_lb_num_partitions( + const struct scaler_data *scl_data, + enum lb_memory_config lb_config, + int *num_part_y, + int *num_part_c); + void ippn10_degamma_ram_select( struct transform *xfm_base, bool use_ram_a); 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 c5267e42a2f2..830dbd5d4144 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 @@ -31,6 +31,7 @@ #include "dcn10_dpp.h" #include "basics/conversion.h" + #define NUM_PHASES 64 #define HORZ_MAX_TAPS 8 #define VERT_MAX_TAPS 8 @@ -168,11 +169,10 @@ static enum dscl_mode_sel get_dscl_mode( const struct scaler_data *data, bool dbg_always_scale) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); const long long one = dal_fixed31_32_one.value; - if (xfm->tf_mask->PIXEL_DEPTH) { - /* DSCL caps: LB data is fixed format */ + if (xfm_base->caps->dscl_data_proc_format == DSCL_DATA_PRCESSING_FIXED_FORMAT) { + /* DSCL is processing data in fixed format */ if (data->format == PIXEL_FORMAT_FP16) return DSCL_MODE_DSCL_BYPASS; } @@ -204,8 +204,8 @@ static void dpp_set_lb( enum lb_memory_config mem_size_config) { /* LB */ - if (xfm->tf_mask->PIXEL_DEPTH) { - /* DSCL caps: LB data is fixed format */ + if (xfm->base.caps->dscl_data_proc_format == DSCL_DATA_PRCESSING_FIXED_FORMAT) { + /* DSCL caps: pixel data processed in fixed format */ uint32_t pixel_depth = get_pixel_depth_val(lb_params->depth); uint32_t dyn_pix_depth = lb_params->dynamic_pixel_depth; @@ -400,7 +400,7 @@ static int get_lb_depth_bpc(enum lb_pixel_depth depth) } } -static void dscl1_calc_lb_num_partitions( +void dscl1_calc_lb_num_partitions( const struct scaler_data *scl_data, enum lb_memory_config lb_config, int *num_part_y, @@ -458,7 +458,7 @@ bool is_lb_conf_valid(int ceil_vratio, int num_partitions, int vtaps) } /*find first match configuration which meets the min required lb size*/ -static enum lb_memory_config dpp10_find_lb_memory_config( +static enum lb_memory_config find_lb_memory_config(struct dcn10_dpp *xfm, const struct scaler_data *scl_data) { int num_part_y, num_part_c; @@ -466,15 +466,19 @@ static enum lb_memory_config dpp10_find_lb_memory_config( int vtaps_c = scl_data->taps.v_taps_c; int ceil_vratio = dal_fixed31_32_ceil(scl_data->ratios.vert); int ceil_vratio_c = dal_fixed31_32_ceil(scl_data->ratios.vert_c); + enum lb_memory_config mem_cfg = LB_MEMORY_CONFIG_0; + + if (xfm->base.ctx->dc->debug.use_max_lb) + return mem_cfg; - dscl1_calc_lb_num_partitions( + xfm->base.caps->dscl_calc_lb_num_partitions( scl_data, LB_MEMORY_CONFIG_1, &num_part_y, &num_part_c); if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)) return LB_MEMORY_CONFIG_1; - dscl1_calc_lb_num_partitions( + xfm->base.caps->dscl_calc_lb_num_partitions( scl_data, LB_MEMORY_CONFIG_2, &num_part_y, &num_part_c); if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) @@ -483,7 +487,7 @@ static enum lb_memory_config dpp10_find_lb_memory_config( if (scl_data->format == PIXEL_FORMAT_420BPP8 || scl_data->format == PIXEL_FORMAT_420BPP10) { - dscl1_calc_lb_num_partitions( + xfm->base.caps->dscl_calc_lb_num_partitions( scl_data, LB_MEMORY_CONFIG_3, &num_part_y, &num_part_c); if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) @@ -491,7 +495,7 @@ static enum lb_memory_config dpp10_find_lb_memory_config( return LB_MEMORY_CONFIG_3; } - dscl1_calc_lb_num_partitions( + xfm->base.caps->dscl_calc_lb_num_partitions( scl_data, LB_MEMORY_CONFIG_0, &num_part_y, &num_part_c); /*Ensure we can support the requested number of vtaps*/ @@ -501,22 +505,6 @@ static enum lb_memory_config dpp10_find_lb_memory_config( return LB_MEMORY_CONFIG_0; } -/*find first match configuration which meets the min required lb size*/ -static enum lb_memory_config find_lb_memory_config(struct dcn10_dpp *xfm, - const struct scaler_data *scl_data) -{ - enum lb_memory_config mem_cfg = LB_MEMORY_CONFIG_0; - - if (xfm->base.ctx->dc->debug.use_max_lb) - return mem_cfg; - - if (xfm->tf_mask->PIXEL_DEPTH) { - /* DSCL caps: LB data is fixed format */ - mem_cfg = dpp10_find_lb_memory_config(scl_data); - } - return mem_cfg; -} - void dpp_set_scaler_auto_scale( struct transform *xfm_base, const struct scaler_data *scl_data) diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h index f95621dfd4d4..7c08bc62c1f5 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h @@ -38,6 +38,7 @@ struct transform { const struct transform_funcs *funcs; struct dc_context *ctx; int inst; + struct dpp_caps *caps; struct pwl_params regamma_params; }; @@ -109,6 +110,22 @@ enum graphics_gamut_adjust_type { GRAPHICS_GAMUT_ADJUST_TYPE_SW /* use adjustments */ }; +enum lb_memory_config { + /* Enable all 3 pieces of memory */ + LB_MEMORY_CONFIG_0 = 0, + + /* Enable only the first piece of memory */ + LB_MEMORY_CONFIG_1 = 1, + + /* Enable only the second piece of memory */ + LB_MEMORY_CONFIG_2 = 2, + + /* Only applicable in 4:2:0 mode, enable all 3 pieces of memory and the + * last piece of chroma memory used for the luma storage + */ + LB_MEMORY_CONFIG_3 = 3 +}; + struct xfm_grph_csc_adjustment { struct fixed31_32 temperature_matrix[CSC_TEMPERATURE_MATRIX_SIZE]; enum graphics_gamut_adjust_type gamut_adjust_type; @@ -262,4 +279,33 @@ const uint16_t *get_filter_6tap_64p(struct fixed31_32 ratio); const uint16_t *get_filter_7tap_64p(struct fixed31_32 ratio); const uint16_t *get_filter_8tap_64p(struct fixed31_32 ratio); + +/* Defines the pixel processing capability of the DSCL */ +enum dscl_data_processing_format { + DSCL_DATA_PRCESSING_FIXED_FORMAT, /* The DSCL processes pixel data in fixed format */ + DSCL_DATA_PRCESSING_FLOAT_FORMAT, /* The DSCL processes pixel data in float format */ +}; + +/* + * The DPP capabilities structure contains enumerations to specify the + * HW processing features and an associated function pointers to + * provide the function interface that can be overloaded for implementations + * based on different capabilities + */ +struct dpp_caps { + /* DSCL processing pixel data in fixed or float format */ + enum dscl_data_processing_format dscl_data_proc_format; + + /* Calculates the number of partitions in the line buffer. + * The implementation of this function is overloaded for + * different versions of DSCL LB. + */ + void (*dscl_calc_lb_num_partitions)( + const struct scaler_data *scl_data, + enum lb_memory_config lb_config, + int *num_part_y, + int *num_part_c); +}; + + #endif -- cgit From e66a575508b5a11df7a670265c91981e4d735749 Mon Sep 17 00:00:00 2001 From: Andrew Jiang Date: Wed, 4 Oct 2017 14:10:16 -0400 Subject: drm/amd/display: Add missing newlines in pstate wait debug messages These were spamming the debugger logs. Signed-off-by: Andrew Jiang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index c34dbcd1fba4..059da7882a68 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -302,7 +302,7 @@ static void verify_allow_pstate_change_high( if (i > pstate_wait_expected_timeout_us) dm_logger_write(hws->ctx->logger, LOG_WARNING, - "pstate took longer than expected ~%dus", + "pstate took longer than expected ~%dus\n", i); return; @@ -326,7 +326,7 @@ static void verify_allow_pstate_change_high( } dm_logger_write(hws->ctx->logger, LOG_WARNING, - "pstate TEST_DEBUG_DATA: 0x%X", + "pstate TEST_DEBUG_DATA: 0x%X\n", debug_data); BREAK_TO_DEBUGGER(); } -- cgit From abb4986eea1670922a0b89ef62688b4b649bd3c6 Mon Sep 17 00:00:00 2001 From: Andrew Jiang Date: Wed, 4 Oct 2017 15:55:45 -0400 Subject: drm/amd/display: Fix up plane_states add/remove logic Our plane_states array trimming logic was faulty, we should be starting to shuffle from the plane that was just released, not from the very beginning of the array. Also get rid of a leftover line that was setting the plane state at the stream index to null, leading to issues. Also move the dc_plane_state_retain call to where we reference plane_state, in case we do hit the error case where we can't get a free pipe. Signed-off-by: Andrew Jiang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 4fb4f0068f1b..c80bde94472f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1073,9 +1073,6 @@ bool dc_add_plane_to_context( return false; } - /* retain new surfaces */ - dc_plane_state_retain(plane_state); - free_pipe = acquire_free_pipe_for_stream(context, pool, stream); #if defined(CONFIG_DRM_AMD_DC_DCN1_0) @@ -1085,11 +1082,11 @@ bool dc_add_plane_to_context( free_pipe = &context->res_ctx.pipe_ctx[pipe_idx]; } #endif - if (!free_pipe) { - stream_status->plane_states[i] = NULL; + if (!free_pipe) return false; - } + /* retain new surfaces */ + dc_plane_state_retain(plane_state); free_pipe->plane_state = plane_state; if (head_pipe != free_pipe) { @@ -1181,8 +1178,8 @@ bool dc_remove_plane_from_context( stream_status->plane_count--; - /* Trim back arrays */ - for (i = 0; i < stream_status->plane_count; i++) + /* Start at the plane we've just released, and move all the planes one index forward to "trim" the array */ + for (; i < stream_status->plane_count; i++) stream_status->plane_states[i] = stream_status->plane_states[i + 1]; stream_status->plane_states[stream_status->plane_count] = NULL; -- cgit From 179584ef6d9d763f9f17d2fe627c2d801e9a0973 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Thu, 5 Oct 2017 14:15:44 -0400 Subject: drm/amd/display: dal 3.1.05 Signed-off-by: Tony Cheng Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 8fa9ef1167fa..6e9b21928d4f 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -38,7 +38,7 @@ #include "inc/compressor.h" #include "dml/display_mode_lib.h" -#define DC_VER "3.1.04" +#define DC_VER "3.1.05" #define MAX_SURFACES 3 #define MAX_STREAMS 6 -- cgit From 86be9a0495c6b4ca8ec37b652152df947c155848 Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Thu, 5 Oct 2017 12:30:14 -0400 Subject: drm/amd/display: renaming filename for hubp Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/Makefile | 2 +- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c | 960 +++++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h | 683 +++++++++++++++ .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 2 +- .../gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c | 960 --------------------- .../gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h | 683 --------------- .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 2 +- 7 files changed, 1646 insertions(+), 1646 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile index 6b19106f4679..ebeb88283a14 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile @@ -3,7 +3,7 @@ DCN10 = dcn10_resource.o dcn10_ipp.o dcn10_hw_sequencer.o \ dcn10_dpp.o dcn10_opp.o dcn10_timing_generator.o \ - dcn10_mem_input.o dcn10_mpc.o \ + dcn10_hubp.o dcn10_mpc.o \ dcn10_dpp_dscl.o dcn10_dpp_cm.o dcn10_cm_common.o AMD_DAL_DCN10 = $(addprefix $(AMDDALPATH)/dc/dcn10/,$(DCN10)) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c new file mode 100644 index 000000000000..b13dee64e0ce --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c @@ -0,0 +1,960 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#include "dm_services.h" +#include "dce_calcs.h" +#include "reg_helper.h" +#include "basics/conversion.h" +#include "dcn10_hubp.h" + +#define REG(reg)\ + hubp1->mi_regs->reg + +#define CTX \ + hubp1->base.ctx + +#undef FN +#define FN(reg_name, field_name) \ + hubp1->mi_shift->field_name, hubp1->mi_mask->field_name + +void hubp1_set_blank(struct hubp *hubp, bool blank) +{ + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); + uint32_t blank_en = blank ? 1 : 0; + + REG_UPDATE_2(DCHUBP_CNTL, + HUBP_BLANK_EN, blank_en, + HUBP_TTU_DISABLE, blank_en); + + if (blank) { + REG_WAIT(DCHUBP_CNTL, + HUBP_NO_OUTSTANDING_REQ, 1, + 1, 200); + hubp->mpcc_id = 0xf; + hubp->opp_id = 0xf; + } +} + +static void hubp1_set_hubp_blank_en(struct hubp *hubp, bool blank) +{ + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); + uint32_t blank_en = blank ? 1 : 0; + + REG_UPDATE(DCHUBP_CNTL, HUBP_BLANK_EN, blank_en); +} + +static void hubp1_vready_workaround(struct hubp *hubp, + struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest) +{ + uint32_t value = 0; + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); + + /* set HBUBREQ_DEBUG_DB[12] = 1 */ + value = REG_READ(HUBPREQ_DEBUG_DB); + + /* hack mode disable */ + value |= 0x100; + value &= ~0x1000; + + if ((pipe_dest->vstartup_start - 2*(pipe_dest->vready_offset+pipe_dest->vupdate_width + + pipe_dest->vupdate_offset) / pipe_dest->htotal) <= pipe_dest->vblank_end) { + /* if (eco_fix_needed(otg_global_sync_timing) + * set HBUBREQ_DEBUG_DB[12] = 1 */ + value |= 0x1000; + } + + REG_WRITE(HUBPREQ_DEBUG_DB, value); +} + +void hubp1_program_tiling( + struct dcn10_hubp *hubp1, + const union dc_tiling_info *info, + const enum surface_pixel_format pixel_format) +{ + REG_UPDATE_6(DCSURF_ADDR_CONFIG, + NUM_PIPES, log_2(info->gfx9.num_pipes), + NUM_BANKS, log_2(info->gfx9.num_banks), + PIPE_INTERLEAVE, info->gfx9.pipe_interleave, + NUM_SE, log_2(info->gfx9.num_shader_engines), + NUM_RB_PER_SE, log_2(info->gfx9.num_rb_per_se), + MAX_COMPRESSED_FRAGS, log_2(info->gfx9.max_compressed_frags)); + + REG_UPDATE_4(DCSURF_TILING_CONFIG, + SW_MODE, info->gfx9.swizzle, + META_LINEAR, info->gfx9.meta_linear, + RB_ALIGNED, info->gfx9.rb_aligned, + PIPE_ALIGNED, info->gfx9.pipe_aligned); +} + +void hubp1_program_size_and_rotation( + struct dcn10_hubp *hubp1, + enum dc_rotation_angle rotation, + enum surface_pixel_format format, + const union plane_size *plane_size, + struct dc_plane_dcc_param *dcc, + bool horizontal_mirror) +{ + uint32_t pitch, meta_pitch, pitch_c, meta_pitch_c, mirror; + + /* Program data and meta surface pitch (calculation from addrlib) + * 444 or 420 luma + */ + if (format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) { + pitch = plane_size->video.luma_pitch - 1; + meta_pitch = dcc->video.meta_pitch_l - 1; + pitch_c = plane_size->video.chroma_pitch - 1; + meta_pitch_c = dcc->video.meta_pitch_c - 1; + } else { + pitch = plane_size->grph.surface_pitch - 1; + meta_pitch = dcc->grph.meta_pitch - 1; + pitch_c = 0; + meta_pitch_c = 0; + } + + if (!dcc->enable) { + meta_pitch = 0; + meta_pitch_c = 0; + } + + REG_UPDATE_2(DCSURF_SURFACE_PITCH, + PITCH, pitch, META_PITCH, meta_pitch); + + if (format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) + REG_UPDATE_2(DCSURF_SURFACE_PITCH_C, + PITCH_C, pitch_c, META_PITCH_C, meta_pitch_c); + + if (horizontal_mirror) + mirror = 1; + else + mirror = 0; + + + /* Program rotation angle and horz mirror - no mirror */ + if (rotation == ROTATION_ANGLE_0) + REG_UPDATE_2(DCSURF_SURFACE_CONFIG, + ROTATION_ANGLE, 0, + H_MIRROR_EN, mirror); + else if (rotation == ROTATION_ANGLE_90) + REG_UPDATE_2(DCSURF_SURFACE_CONFIG, + ROTATION_ANGLE, 1, + H_MIRROR_EN, mirror); + else if (rotation == ROTATION_ANGLE_180) + REG_UPDATE_2(DCSURF_SURFACE_CONFIG, + ROTATION_ANGLE, 2, + H_MIRROR_EN, mirror); + else if (rotation == ROTATION_ANGLE_270) + REG_UPDATE_2(DCSURF_SURFACE_CONFIG, + ROTATION_ANGLE, 3, + H_MIRROR_EN, mirror); +} + +void hubp1_program_pixel_format( + struct dcn10_hubp *hubp1, + enum surface_pixel_format format) +{ + uint32_t red_bar = 3; + uint32_t blue_bar = 2; + + /* swap for ABGR format */ + if (format == SURFACE_PIXEL_FORMAT_GRPH_ABGR8888 + || format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010 + || format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS + || format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F) { + red_bar = 2; + blue_bar = 3; + } + + REG_UPDATE_2(HUBPRET_CONTROL, + CROSSBAR_SRC_CB_B, blue_bar, + CROSSBAR_SRC_CR_R, red_bar); + + /* Mapping is same as ipp programming (cnvc) */ + + switch (format) { + case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: + REG_UPDATE(DCSURF_SURFACE_CONFIG, + SURFACE_PIXEL_FORMAT, 1); + break; + case SURFACE_PIXEL_FORMAT_GRPH_RGB565: + REG_UPDATE(DCSURF_SURFACE_CONFIG, + SURFACE_PIXEL_FORMAT, 3); + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: + REG_UPDATE(DCSURF_SURFACE_CONFIG, + SURFACE_PIXEL_FORMAT, 8); + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: + REG_UPDATE(DCSURF_SURFACE_CONFIG, + SURFACE_PIXEL_FORMAT, 10); + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: + REG_UPDATE(DCSURF_SURFACE_CONFIG, + SURFACE_PIXEL_FORMAT, 22); + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:/*we use crossbar already*/ + REG_UPDATE(DCSURF_SURFACE_CONFIG, + SURFACE_PIXEL_FORMAT, 24); + break; + + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: + REG_UPDATE(DCSURF_SURFACE_CONFIG, + SURFACE_PIXEL_FORMAT, 65); + break; + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: + REG_UPDATE(DCSURF_SURFACE_CONFIG, + SURFACE_PIXEL_FORMAT, 64); + break; + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: + REG_UPDATE(DCSURF_SURFACE_CONFIG, + SURFACE_PIXEL_FORMAT, 67); + break; + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: + REG_UPDATE(DCSURF_SURFACE_CONFIG, + SURFACE_PIXEL_FORMAT, 66); + break; + default: + BREAK_TO_DEBUGGER(); + break; + } + + /* don't see the need of program the xbar in DCN 1.0 */ +} + +bool hubp1_program_surface_flip_and_addr( + struct hubp *hubp, + const struct dc_plane_address *address, + bool flip_immediate) +{ + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); + + /* program flip type */ + REG_SET(DCSURF_FLIP_CONTROL, 0, + SURFACE_FLIP_TYPE, flip_immediate); + + /* HW automatically latch rest of address register on write to + * DCSURF_PRIMARY_SURFACE_ADDRESS if SURFACE_UPDATE_LOCK is not used + * + * program high first and then the low addr, order matters! + */ + switch (address->type) { + case PLN_ADDR_TYPE_GRAPHICS: + /* DCN1.0 does not support const color + * TODO: program DCHUBBUB_RET_PATH_DCC_CFGx_0/1 + * base on address->grph.dcc_const_color + * x = 0, 2, 4, 6 for pipe 0, 1, 2, 3 for rgb and luma + * x = 1, 3, 5, 7 for pipe 0, 1, 2, 3 for chroma + */ + + if (address->grph.addr.quad_part == 0) + break; + + REG_UPDATE(DCSURF_SURFACE_CONTROL, + PRIMARY_SURFACE_TMZ, address->tmz_surface); + + if (address->grph.meta_addr.quad_part != 0) { + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, 0, + PRIMARY_META_SURFACE_ADDRESS_HIGH, + address->grph.meta_addr.high_part); + + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS, 0, + PRIMARY_META_SURFACE_ADDRESS, + address->grph.meta_addr.low_part); + } + + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, 0, + PRIMARY_SURFACE_ADDRESS_HIGH, + address->grph.addr.high_part); + + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS, 0, + PRIMARY_SURFACE_ADDRESS, + address->grph.addr.low_part); + break; + case PLN_ADDR_TYPE_VIDEO_PROGRESSIVE: + if (address->video_progressive.luma_addr.quad_part == 0 + || address->video_progressive.chroma_addr.quad_part == 0) + break; + + REG_UPDATE(DCSURF_SURFACE_CONTROL, + PRIMARY_SURFACE_TMZ, address->tmz_surface); + + if (address->video_progressive.luma_meta_addr.quad_part != 0) { + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C, 0, + PRIMARY_META_SURFACE_ADDRESS_HIGH_C, + address->video_progressive.chroma_meta_addr.high_part); + + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_C, 0, + PRIMARY_META_SURFACE_ADDRESS_C, + address->video_progressive.chroma_meta_addr.low_part); + + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, 0, + PRIMARY_META_SURFACE_ADDRESS_HIGH, + address->video_progressive.luma_meta_addr.high_part); + + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS, 0, + PRIMARY_META_SURFACE_ADDRESS, + address->video_progressive.luma_meta_addr.low_part); + } + + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C, 0, + PRIMARY_SURFACE_ADDRESS_HIGH_C, + address->video_progressive.chroma_addr.high_part); + + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_C, 0, + PRIMARY_SURFACE_ADDRESS_C, + address->video_progressive.chroma_addr.low_part); + + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, 0, + PRIMARY_SURFACE_ADDRESS_HIGH, + address->video_progressive.luma_addr.high_part); + + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS, 0, + PRIMARY_SURFACE_ADDRESS, + address->video_progressive.luma_addr.low_part); + break; + case PLN_ADDR_TYPE_GRPH_STEREO: + if (address->grph_stereo.left_addr.quad_part == 0) + break; + if (address->grph_stereo.right_addr.quad_part == 0) + break; + + REG_UPDATE(DCSURF_SURFACE_CONTROL, + PRIMARY_SURFACE_TMZ, address->tmz_surface); + + if (address->grph_stereo.right_meta_addr.quad_part != 0) { + + REG_SET(DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH, 0, + SECONDARY_META_SURFACE_ADDRESS_HIGH, + address->grph_stereo.right_meta_addr.high_part); + + REG_SET(DCSURF_SECONDARY_META_SURFACE_ADDRESS, 0, + SECONDARY_META_SURFACE_ADDRESS, + address->grph_stereo.right_meta_addr.low_part); + } + if (address->grph_stereo.left_meta_addr.quad_part != 0) { + + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, 0, + PRIMARY_META_SURFACE_ADDRESS_HIGH, + address->grph_stereo.left_meta_addr.high_part); + + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS, 0, + PRIMARY_META_SURFACE_ADDRESS, + address->grph_stereo.left_meta_addr.low_part); + } + + REG_SET(DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH, 0, + SECONDARY_SURFACE_ADDRESS_HIGH, + address->grph_stereo.right_addr.high_part); + + REG_SET(DCSURF_SECONDARY_SURFACE_ADDRESS, 0, + SECONDARY_SURFACE_ADDRESS, + address->grph_stereo.right_addr.low_part); + + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, 0, + PRIMARY_SURFACE_ADDRESS_HIGH, + address->grph_stereo.left_addr.high_part); + + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS, 0, + PRIMARY_SURFACE_ADDRESS, + address->grph_stereo.left_addr.low_part); + break; + default: + BREAK_TO_DEBUGGER(); + break; + } + + hubp->request_address = *address; + + if (flip_immediate) + hubp->current_address = *address; + + return true; +} + +void hubp1_dcc_control(struct hubp *hubp, bool enable, + bool independent_64b_blks) +{ + uint32_t dcc_en = enable ? 1 : 0; + uint32_t dcc_ind_64b_blk = independent_64b_blks ? 1 : 0; + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); + + REG_UPDATE_2(DCSURF_SURFACE_CONTROL, + PRIMARY_SURFACE_DCC_EN, dcc_en, + PRIMARY_SURFACE_DCC_IND_64B_BLK, dcc_ind_64b_blk); +} + +void hubp1_program_surface_config( + struct hubp *hubp, + enum surface_pixel_format format, + union dc_tiling_info *tiling_info, + union plane_size *plane_size, + enum dc_rotation_angle rotation, + struct dc_plane_dcc_param *dcc, + bool horizontal_mirror) +{ + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); + + hubp1_dcc_control(hubp, dcc->enable, dcc->grph.independent_64b_blks); + hubp1_program_tiling(hubp1, tiling_info, format); + hubp1_program_size_and_rotation( + hubp1, rotation, format, plane_size, dcc, horizontal_mirror); + hubp1_program_pixel_format(hubp1, format); +} + +void hubp1_program_requestor( + struct hubp *hubp, + struct _vcs_dpi_display_rq_regs_st *rq_regs) +{ + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); + + REG_UPDATE(HUBPRET_CONTROL, + DET_BUF_PLANE1_BASE_ADDRESS, rq_regs->plane1_base_address); + REG_SET_4(DCN_EXPANSION_MODE, 0, + DRQ_EXPANSION_MODE, rq_regs->drq_expansion_mode, + PRQ_EXPANSION_MODE, rq_regs->prq_expansion_mode, + MRQ_EXPANSION_MODE, rq_regs->mrq_expansion_mode, + CRQ_EXPANSION_MODE, rq_regs->crq_expansion_mode); + REG_SET_8(DCHUBP_REQ_SIZE_CONFIG, 0, + CHUNK_SIZE, rq_regs->rq_regs_l.chunk_size, + MIN_CHUNK_SIZE, rq_regs->rq_regs_l.min_chunk_size, + META_CHUNK_SIZE, rq_regs->rq_regs_l.meta_chunk_size, + MIN_META_CHUNK_SIZE, rq_regs->rq_regs_l.min_meta_chunk_size, + DPTE_GROUP_SIZE, rq_regs->rq_regs_l.dpte_group_size, + MPTE_GROUP_SIZE, rq_regs->rq_regs_l.mpte_group_size, + SWATH_HEIGHT, rq_regs->rq_regs_l.swath_height, + PTE_ROW_HEIGHT_LINEAR, rq_regs->rq_regs_l.pte_row_height_linear); + REG_SET_8(DCHUBP_REQ_SIZE_CONFIG_C, 0, + CHUNK_SIZE_C, rq_regs->rq_regs_c.chunk_size, + MIN_CHUNK_SIZE_C, rq_regs->rq_regs_c.min_chunk_size, + META_CHUNK_SIZE_C, rq_regs->rq_regs_c.meta_chunk_size, + MIN_META_CHUNK_SIZE_C, rq_regs->rq_regs_c.min_meta_chunk_size, + DPTE_GROUP_SIZE_C, rq_regs->rq_regs_c.dpte_group_size, + MPTE_GROUP_SIZE_C, rq_regs->rq_regs_c.mpte_group_size, + SWATH_HEIGHT_C, rq_regs->rq_regs_c.swath_height, + PTE_ROW_HEIGHT_LINEAR_C, rq_regs->rq_regs_c.pte_row_height_linear); +} + + +void hubp1_program_deadline( + struct hubp *hubp, + struct _vcs_dpi_display_dlg_regs_st *dlg_attr, + struct _vcs_dpi_display_ttu_regs_st *ttu_attr) +{ + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); + + /* DLG - Per hubp */ + REG_SET_2(BLANK_OFFSET_0, 0, + REFCYC_H_BLANK_END, dlg_attr->refcyc_h_blank_end, + DLG_V_BLANK_END, dlg_attr->dlg_vblank_end); + + REG_SET(BLANK_OFFSET_1, 0, + MIN_DST_Y_NEXT_START, dlg_attr->min_dst_y_next_start); + + REG_SET(DST_DIMENSIONS, 0, + REFCYC_PER_HTOTAL, dlg_attr->refcyc_per_htotal); + + REG_SET_2(DST_AFTER_SCALER, 0, + REFCYC_X_AFTER_SCALER, dlg_attr->refcyc_x_after_scaler, + DST_Y_AFTER_SCALER, dlg_attr->dst_y_after_scaler); + + if (REG(PREFETCH_SETTINS)) + REG_SET_2(PREFETCH_SETTINS, 0, + DST_Y_PREFETCH, dlg_attr->dst_y_prefetch, + VRATIO_PREFETCH, dlg_attr->vratio_prefetch); + else + REG_SET_2(PREFETCH_SETTINGS, 0, + DST_Y_PREFETCH, dlg_attr->dst_y_prefetch, + VRATIO_PREFETCH, dlg_attr->vratio_prefetch); + + REG_SET_2(VBLANK_PARAMETERS_0, 0, + DST_Y_PER_VM_VBLANK, dlg_attr->dst_y_per_vm_vblank, + DST_Y_PER_ROW_VBLANK, dlg_attr->dst_y_per_row_vblank); + + REG_SET(REF_FREQ_TO_PIX_FREQ, 0, + REF_FREQ_TO_PIX_FREQ, dlg_attr->ref_freq_to_pix_freq); + + /* DLG - Per luma/chroma */ + REG_SET(VBLANK_PARAMETERS_1, 0, + REFCYC_PER_PTE_GROUP_VBLANK_L, dlg_attr->refcyc_per_pte_group_vblank_l); + + REG_SET(VBLANK_PARAMETERS_3, 0, + REFCYC_PER_META_CHUNK_VBLANK_L, dlg_attr->refcyc_per_meta_chunk_vblank_l); + + REG_SET(NOM_PARAMETERS_0, 0, + DST_Y_PER_PTE_ROW_NOM_L, dlg_attr->dst_y_per_pte_row_nom_l); + + REG_SET(NOM_PARAMETERS_1, 0, + REFCYC_PER_PTE_GROUP_NOM_L, dlg_attr->refcyc_per_pte_group_nom_l); + + REG_SET(NOM_PARAMETERS_4, 0, + DST_Y_PER_META_ROW_NOM_L, dlg_attr->dst_y_per_meta_row_nom_l); + + REG_SET(NOM_PARAMETERS_5, 0, + REFCYC_PER_META_CHUNK_NOM_L, dlg_attr->refcyc_per_meta_chunk_nom_l); + + REG_SET_2(PER_LINE_DELIVERY_PRE, 0, + REFCYC_PER_LINE_DELIVERY_PRE_L, dlg_attr->refcyc_per_line_delivery_pre_l, + REFCYC_PER_LINE_DELIVERY_PRE_C, dlg_attr->refcyc_per_line_delivery_pre_c); + + REG_SET_2(PER_LINE_DELIVERY, 0, + REFCYC_PER_LINE_DELIVERY_L, dlg_attr->refcyc_per_line_delivery_l, + REFCYC_PER_LINE_DELIVERY_C, dlg_attr->refcyc_per_line_delivery_c); + + if (REG(PREFETCH_SETTINS_C)) + REG_SET(PREFETCH_SETTINS_C, 0, + VRATIO_PREFETCH_C, dlg_attr->vratio_prefetch_c); + else + REG_SET(PREFETCH_SETTINGS_C, 0, + VRATIO_PREFETCH_C, dlg_attr->vratio_prefetch_c); + + REG_SET(VBLANK_PARAMETERS_2, 0, + REFCYC_PER_PTE_GROUP_VBLANK_C, dlg_attr->refcyc_per_pte_group_vblank_c); + + REG_SET(VBLANK_PARAMETERS_4, 0, + REFCYC_PER_META_CHUNK_VBLANK_C, dlg_attr->refcyc_per_meta_chunk_vblank_c); + + REG_SET(NOM_PARAMETERS_2, 0, + DST_Y_PER_PTE_ROW_NOM_C, dlg_attr->dst_y_per_pte_row_nom_c); + + REG_SET(NOM_PARAMETERS_3, 0, + REFCYC_PER_PTE_GROUP_NOM_C, dlg_attr->refcyc_per_pte_group_nom_c); + + REG_SET(NOM_PARAMETERS_6, 0, + DST_Y_PER_META_ROW_NOM_C, dlg_attr->dst_y_per_meta_row_nom_c); + + REG_SET(NOM_PARAMETERS_7, 0, + REFCYC_PER_META_CHUNK_NOM_C, dlg_attr->refcyc_per_meta_chunk_nom_c); + + /* TTU - per hubp */ + REG_SET_2(DCN_TTU_QOS_WM, 0, + QoS_LEVEL_LOW_WM, ttu_attr->qos_level_low_wm, + QoS_LEVEL_HIGH_WM, ttu_attr->qos_level_high_wm); + + REG_SET_2(DCN_GLOBAL_TTU_CNTL, 0, + MIN_TTU_VBLANK, ttu_attr->min_ttu_vblank, + QoS_LEVEL_FLIP, ttu_attr->qos_level_flip); + + /* TTU - per luma/chroma */ + /* Assumed surf0 is luma and 1 is chroma */ + + REG_SET_3(DCN_SURF0_TTU_CNTL0, 0, + REFCYC_PER_REQ_DELIVERY, ttu_attr->refcyc_per_req_delivery_l, + QoS_LEVEL_FIXED, ttu_attr->qos_level_fixed_l, + QoS_RAMP_DISABLE, ttu_attr->qos_ramp_disable_l); + + REG_SET(DCN_SURF0_TTU_CNTL1, 0, + REFCYC_PER_REQ_DELIVERY_PRE, + ttu_attr->refcyc_per_req_delivery_pre_l); + + REG_SET_3(DCN_SURF1_TTU_CNTL0, 0, + REFCYC_PER_REQ_DELIVERY, ttu_attr->refcyc_per_req_delivery_c, + QoS_LEVEL_FIXED, ttu_attr->qos_level_fixed_c, + QoS_RAMP_DISABLE, ttu_attr->qos_ramp_disable_c); + + REG_SET(DCN_SURF1_TTU_CNTL1, 0, + REFCYC_PER_REQ_DELIVERY_PRE, + ttu_attr->refcyc_per_req_delivery_pre_c); +} + +static void hubp1_setup( + struct hubp *hubp, + struct _vcs_dpi_display_dlg_regs_st *dlg_attr, + struct _vcs_dpi_display_ttu_regs_st *ttu_attr, + struct _vcs_dpi_display_rq_regs_st *rq_regs, + struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest) +{ + /* otg is locked when this func is called. Register are double buffered. + * disable the requestors is not needed + */ + hubp1_program_requestor(hubp, rq_regs); + hubp1_program_deadline(hubp, dlg_attr, ttu_attr); + hubp1_vready_workaround(hubp, pipe_dest); +} + +bool hubp1_is_flip_pending(struct hubp *hubp) +{ + uint32_t flip_pending = 0; + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); + struct dc_plane_address earliest_inuse_address; + + REG_GET(DCSURF_FLIP_CONTROL, + SURFACE_FLIP_PENDING, &flip_pending); + + REG_GET(DCSURF_SURFACE_EARLIEST_INUSE, + SURFACE_EARLIEST_INUSE_ADDRESS, &earliest_inuse_address.grph.addr.low_part); + + REG_GET(DCSURF_SURFACE_EARLIEST_INUSE_HIGH, + SURFACE_EARLIEST_INUSE_ADDRESS_HIGH, &earliest_inuse_address.grph.addr.high_part); + + if (flip_pending) + return true; + + if (earliest_inuse_address.grph.addr.quad_part != hubp->request_address.grph.addr.quad_part) + return true; + + hubp->current_address = hubp->request_address; + return false; +} + +uint32_t aperture_default_system = 1; +uint32_t context0_default_system; /* = 0;*/ + +static void hubp1_set_vm_system_aperture_settings(struct hubp *hubp, + struct vm_system_aperture_param *apt) +{ + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); + PHYSICAL_ADDRESS_LOC mc_vm_apt_default; + PHYSICAL_ADDRESS_LOC mc_vm_apt_low; + PHYSICAL_ADDRESS_LOC mc_vm_apt_high; + + mc_vm_apt_default.quad_part = apt->sys_default.quad_part >> 12; + mc_vm_apt_low.quad_part = apt->sys_low.quad_part >> 12; + mc_vm_apt_high.quad_part = apt->sys_high.quad_part >> 12; + + REG_SET_2(DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, 0, + MC_VM_SYSTEM_APERTURE_DEFAULT_SYSTEM, aperture_default_system, /* 1 = system physical memory */ + MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, mc_vm_apt_default.high_part); + REG_SET(DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, 0, + MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, mc_vm_apt_default.low_part); + + REG_SET(DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, 0, + MC_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, mc_vm_apt_low.high_part); + REG_SET(DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, 0, + MC_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, mc_vm_apt_low.low_part); + + REG_SET(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, 0, + MC_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, mc_vm_apt_high.high_part); + REG_SET(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, 0, + MC_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, mc_vm_apt_high.low_part); +} + +static void hubp1_set_vm_context0_settings(struct hubp *hubp, + const struct vm_context0_param *vm0) +{ + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); + /* pte base */ + REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, 0, + VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, vm0->pte_base.high_part); + REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB, 0, + VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB, vm0->pte_base.low_part); + + /* pte start */ + REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB, 0, + VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB, vm0->pte_start.high_part); + REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_LSB, 0, + VM_CONTEXT0_PAGE_TABLE_START_ADDR_LSB, vm0->pte_start.low_part); + + /* pte end */ + REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB, 0, + VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB, vm0->pte_end.high_part); + REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB, 0, + VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB, vm0->pte_end.low_part); + + /* fault handling */ + REG_SET_2(DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, 0, + VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, vm0->fault_default.high_part, + VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_SYSTEM, context0_default_system); + REG_SET(DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, 0, + VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, vm0->fault_default.low_part); + + /* control: enable VM PTE*/ + REG_SET_2(DCN_VM_MX_L1_TLB_CNTL, 0, + ENABLE_L1_TLB, 1, + SYSTEM_ACCESS_MODE, 3); +} + +void min_set_viewport( + struct hubp *hubp, + const struct rect *viewport, + const struct rect *viewport_c) +{ + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); + + REG_SET_2(DCSURF_PRI_VIEWPORT_DIMENSION, 0, + PRI_VIEWPORT_WIDTH, viewport->width, + PRI_VIEWPORT_HEIGHT, viewport->height); + + REG_SET_2(DCSURF_PRI_VIEWPORT_START, 0, + PRI_VIEWPORT_X_START, viewport->x, + PRI_VIEWPORT_Y_START, viewport->y); + + /*for stereo*/ + REG_SET_2(DCSURF_SEC_VIEWPORT_DIMENSION, 0, + SEC_VIEWPORT_WIDTH, viewport->width, + SEC_VIEWPORT_HEIGHT, viewport->height); + + REG_SET_2(DCSURF_SEC_VIEWPORT_START, 0, + SEC_VIEWPORT_X_START, viewport->x, + SEC_VIEWPORT_Y_START, viewport->y); + + /* DC supports NV12 only at the moment */ + REG_SET_2(DCSURF_PRI_VIEWPORT_DIMENSION_C, 0, + PRI_VIEWPORT_WIDTH_C, viewport_c->width, + PRI_VIEWPORT_HEIGHT_C, viewport_c->height); + + REG_SET_2(DCSURF_PRI_VIEWPORT_START_C, 0, + PRI_VIEWPORT_X_START_C, viewport_c->x, + PRI_VIEWPORT_Y_START_C, viewport_c->y); +} + +void hubp1_read_state(struct dcn10_hubp *hubp1, + struct dcn_hubp_state *s) +{ + REG_GET(DCSURF_SURFACE_CONFIG, + SURFACE_PIXEL_FORMAT, &s->pixel_format); + + REG_GET(DCSURF_SURFACE_EARLIEST_INUSE_HIGH, + SURFACE_EARLIEST_INUSE_ADDRESS_HIGH, &s->inuse_addr_hi); + + REG_GET_2(DCSURF_PRI_VIEWPORT_DIMENSION, + PRI_VIEWPORT_WIDTH, &s->viewport_width, + PRI_VIEWPORT_HEIGHT, &s->viewport_height); + + REG_GET_2(DCSURF_SURFACE_CONFIG, + ROTATION_ANGLE, &s->rotation_angle, + H_MIRROR_EN, &s->h_mirror_en); + + REG_GET(DCSURF_TILING_CONFIG, + SW_MODE, &s->sw_mode); + + REG_GET(DCSURF_SURFACE_CONTROL, + PRIMARY_SURFACE_DCC_EN, &s->dcc_en); + + REG_GET_3(DCHUBP_CNTL, + HUBP_BLANK_EN, &s->blank_en, + HUBP_TTU_DISABLE, &s->ttu_disable, + HUBP_UNDERFLOW_STATUS, &s->underflow_status); + + REG_GET(DCN_GLOBAL_TTU_CNTL, + MIN_TTU_VBLANK, &s->min_ttu_vblank); + + REG_GET_2(DCN_TTU_QOS_WM, + QoS_LEVEL_LOW_WM, &s->qos_level_low_wm, + QoS_LEVEL_HIGH_WM, &s->qos_level_high_wm); +} + +enum cursor_pitch { + CURSOR_PITCH_64_PIXELS = 0, + CURSOR_PITCH_128_PIXELS, + CURSOR_PITCH_256_PIXELS +}; + +enum cursor_lines_per_chunk { + CURSOR_LINE_PER_CHUNK_2 = 1, + CURSOR_LINE_PER_CHUNK_4, + CURSOR_LINE_PER_CHUNK_8, + CURSOR_LINE_PER_CHUNK_16 +}; + +static bool ippn10_cursor_program_control( + struct dcn10_hubp *hubp1, + bool pixel_data_invert, + enum dc_cursor_color_format color_format) +{ + if (REG(CURSOR_SETTINS)) + REG_SET_2(CURSOR_SETTINS, 0, + /* no shift of the cursor HDL schedule */ + CURSOR0_DST_Y_OFFSET, 0, + /* used to shift the cursor chunk request deadline */ + CURSOR0_CHUNK_HDL_ADJUST, 3); + else + REG_SET_2(CURSOR_SETTINGS, 0, + /* no shift of the cursor HDL schedule */ + CURSOR0_DST_Y_OFFSET, 0, + /* used to shift the cursor chunk request deadline */ + CURSOR0_CHUNK_HDL_ADJUST, 3); + + return true; +} + +static enum cursor_pitch ippn10_get_cursor_pitch( + unsigned int pitch) +{ + enum cursor_pitch hw_pitch; + + switch (pitch) { + case 64: + hw_pitch = CURSOR_PITCH_64_PIXELS; + break; + case 128: + hw_pitch = CURSOR_PITCH_128_PIXELS; + break; + case 256: + hw_pitch = CURSOR_PITCH_256_PIXELS; + break; + default: + DC_ERR("Invalid cursor pitch of %d. " + "Only 64/128/256 is supported on DCN.\n", pitch); + hw_pitch = CURSOR_PITCH_64_PIXELS; + break; + } + return hw_pitch; +} + +static enum cursor_lines_per_chunk ippn10_get_lines_per_chunk( + unsigned int cur_width, + enum dc_cursor_color_format format) +{ + enum cursor_lines_per_chunk line_per_chunk; + + if (format == CURSOR_MODE_MONO) + /* impl B. expansion in CUR Buffer reader */ + line_per_chunk = CURSOR_LINE_PER_CHUNK_16; + else if (cur_width <= 32) + line_per_chunk = CURSOR_LINE_PER_CHUNK_16; + else if (cur_width <= 64) + line_per_chunk = CURSOR_LINE_PER_CHUNK_8; + else if (cur_width <= 128) + line_per_chunk = CURSOR_LINE_PER_CHUNK_4; + else + line_per_chunk = CURSOR_LINE_PER_CHUNK_2; + + return line_per_chunk; +} + +void hubp1_cursor_set_attributes( + struct hubp *hubp, + const struct dc_cursor_attributes *attr) +{ + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); + enum cursor_pitch hw_pitch = ippn10_get_cursor_pitch(attr->pitch); + enum cursor_lines_per_chunk lpc = ippn10_get_lines_per_chunk( + attr->width, attr->color_format); + + hubp->curs_attr = *attr; + + REG_UPDATE(CURSOR_SURFACE_ADDRESS_HIGH, + CURSOR_SURFACE_ADDRESS_HIGH, attr->address.high_part); + REG_UPDATE(CURSOR_SURFACE_ADDRESS, + CURSOR_SURFACE_ADDRESS, attr->address.low_part); + + REG_UPDATE_2(CURSOR_SIZE, + CURSOR_WIDTH, attr->width, + CURSOR_HEIGHT, attr->height); + REG_UPDATE_3(CURSOR_CONTROL, + CURSOR_MODE, attr->color_format, + CURSOR_PITCH, hw_pitch, + CURSOR_LINES_PER_CHUNK, lpc); + ippn10_cursor_program_control(hubp1, + attr->attribute_flags.bits.INVERT_PIXEL_DATA, + attr->color_format); +} + +void hubp1_cursor_set_position( + struct hubp *hubp, + const struct dc_cursor_position *pos, + const struct dc_cursor_mi_param *param) +{ + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); + int src_x_offset = pos->x - pos->x_hotspot - param->viewport_x_start; + uint32_t cur_en = pos->enable ? 1 : 0; + uint32_t dst_x_offset = (src_x_offset >= 0) ? src_x_offset : 0; + + /* + * Guard aganst cursor_set_position() from being called with invalid + * attributes + * + * TODO: Look at combining cursor_set_position() and + * cursor_set_attributes() into cursor_update() + */ + if (hubp->curs_attr.address.quad_part == 0) + return; + + dst_x_offset *= param->ref_clk_khz; + dst_x_offset /= param->pixel_clk_khz; + + ASSERT(param->h_scale_ratio.value); + + if (param->h_scale_ratio.value) + dst_x_offset = dal_fixed31_32_floor(dal_fixed31_32_div( + dal_fixed31_32_from_int(dst_x_offset), + param->h_scale_ratio)); + + if (src_x_offset >= (int)param->viewport_width) + cur_en = 0; /* not visible beyond right edge*/ + + if (src_x_offset + (int)hubp->curs_attr.width < 0) + cur_en = 0; /* not visible beyond left edge*/ + + if (cur_en && REG_READ(CURSOR_SURFACE_ADDRESS) == 0) + hubp1_cursor_set_attributes(hubp, &hubp->curs_attr); + REG_UPDATE(CURSOR_CONTROL, + CURSOR_ENABLE, cur_en); + + REG_SET_2(CURSOR_POSITION, 0, + CURSOR_X_POSITION, pos->x, + CURSOR_Y_POSITION, pos->y); + + REG_SET_2(CURSOR_HOT_SPOT, 0, + CURSOR_HOT_SPOT_X, pos->x_hotspot, + CURSOR_HOT_SPOT_Y, pos->y_hotspot); + + REG_SET(CURSOR_DST_OFFSET, 0, + CURSOR_DST_X_OFFSET, dst_x_offset); + /* TODO Handle surface pixel formats other than 4:4:4 */ +} + +static struct hubp_funcs dcn10_hubp_funcs = { + .hubp_program_surface_flip_and_addr = + hubp1_program_surface_flip_and_addr, + .hubp_program_surface_config = + hubp1_program_surface_config, + .hubp_is_flip_pending = hubp1_is_flip_pending, + .hubp_setup = hubp1_setup, + .hubp_set_vm_system_aperture_settings = hubp1_set_vm_system_aperture_settings, + .hubp_set_vm_context0_settings = hubp1_set_vm_context0_settings, + .set_blank = hubp1_set_blank, + .dcc_control = hubp1_dcc_control, + .mem_program_viewport = min_set_viewport, + .set_hubp_blank_en = hubp1_set_hubp_blank_en, + .set_cursor_attributes = hubp1_cursor_set_attributes, + .set_cursor_position = hubp1_cursor_set_position, +}; + +/*****************************************/ +/* Constructor, Destructor */ +/*****************************************/ + +void dcn10_hubp_construct( + struct dcn10_hubp *hubp1, + struct dc_context *ctx, + uint32_t inst, + const struct dcn_mi_registers *mi_regs, + const struct dcn_mi_shift *mi_shift, + const struct dcn_mi_mask *mi_mask) +{ + hubp1->base.funcs = &dcn10_hubp_funcs; + hubp1->base.ctx = ctx; + hubp1->mi_regs = mi_regs; + hubp1->mi_shift = mi_shift; + hubp1->mi_mask = mi_mask; + hubp1->base.inst = inst; + hubp1->base.opp_id = 0xf; + hubp1->base.mpcc_id = 0xf; +} + + diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h new file mode 100644 index 000000000000..66db453c801b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h @@ -0,0 +1,683 @@ +/* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_MEM_INPUT_DCN10_H__ +#define __DC_MEM_INPUT_DCN10_H__ + +#include "hubp.h" + +#define TO_DCN10_HUBP(hubp)\ + container_of(hubp, struct dcn10_hubp, base) + +#define MI_REG_LIST_DCN(id)\ + SRI(DCHUBP_CNTL, HUBP, id),\ + SRI(HUBPREQ_DEBUG_DB, HUBP, id),\ + SRI(DCSURF_ADDR_CONFIG, HUBP, id),\ + SRI(DCSURF_TILING_CONFIG, HUBP, id),\ + SRI(DCSURF_SURFACE_PITCH, HUBPREQ, id),\ + SRI(DCSURF_SURFACE_PITCH_C, HUBPREQ, id),\ + SRI(DCSURF_SURFACE_CONFIG, HUBP, id),\ + SRI(DCSURF_FLIP_CONTROL, HUBPREQ, id),\ + SRI(DCSURF_PRI_VIEWPORT_DIMENSION, HUBP, id), \ + SRI(DCSURF_PRI_VIEWPORT_START, HUBP, id), \ + SRI(DCSURF_SEC_VIEWPORT_DIMENSION, HUBP, id), \ + SRI(DCSURF_SEC_VIEWPORT_START, HUBP, id), \ + SRI(DCSURF_PRI_VIEWPORT_DIMENSION_C, HUBP, id), \ + SRI(DCSURF_PRI_VIEWPORT_START_C, HUBP, id), \ + SRI(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, HUBPREQ, id),\ + SRI(DCSURF_PRIMARY_SURFACE_ADDRESS, HUBPREQ, id),\ + SRI(DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH, HUBPREQ, id),\ + SRI(DCSURF_SECONDARY_SURFACE_ADDRESS, HUBPREQ, id),\ + SRI(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, HUBPREQ, id),\ + SRI(DCSURF_PRIMARY_META_SURFACE_ADDRESS, HUBPREQ, id),\ + SRI(DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH, HUBPREQ, id),\ + SRI(DCSURF_SECONDARY_META_SURFACE_ADDRESS, HUBPREQ, id),\ + SRI(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C, HUBPREQ, id),\ + SRI(DCSURF_PRIMARY_SURFACE_ADDRESS_C, HUBPREQ, id),\ + SRI(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C, HUBPREQ, id),\ + SRI(DCSURF_PRIMARY_META_SURFACE_ADDRESS_C, HUBPREQ, id),\ + SRI(DCSURF_SURFACE_INUSE, HUBPREQ, id),\ + SRI(DCSURF_SURFACE_INUSE_HIGH, HUBPREQ, id),\ + SRI(DCSURF_SURFACE_INUSE_C, HUBPREQ, id),\ + SRI(DCSURF_SURFACE_INUSE_HIGH_C, HUBPREQ, id),\ + SRI(DCSURF_SURFACE_EARLIEST_INUSE, HUBPREQ, id),\ + SRI(DCSURF_SURFACE_EARLIEST_INUSE_HIGH, HUBPREQ, id),\ + SRI(DCSURF_SURFACE_EARLIEST_INUSE_C, HUBPREQ, id),\ + SRI(DCSURF_SURFACE_EARLIEST_INUSE_HIGH_C, HUBPREQ, id),\ + SRI(DCSURF_SURFACE_CONTROL, HUBPREQ, id),\ + SRI(HUBPRET_CONTROL, HUBPRET, id),\ + SRI(DCN_EXPANSION_MODE, HUBPREQ, id),\ + SRI(DCHUBP_REQ_SIZE_CONFIG, HUBP, id),\ + SRI(DCHUBP_REQ_SIZE_CONFIG_C, HUBP, id),\ + SRI(BLANK_OFFSET_0, HUBPREQ, id),\ + SRI(BLANK_OFFSET_1, HUBPREQ, id),\ + SRI(DST_DIMENSIONS, HUBPREQ, id),\ + SRI(DST_AFTER_SCALER, HUBPREQ, id),\ + SRI(VBLANK_PARAMETERS_0, HUBPREQ, id),\ + SRI(REF_FREQ_TO_PIX_FREQ, HUBPREQ, id),\ + SRI(VBLANK_PARAMETERS_1, HUBPREQ, id),\ + SRI(VBLANK_PARAMETERS_3, HUBPREQ, id),\ + SRI(NOM_PARAMETERS_0, HUBPREQ, id),\ + SRI(NOM_PARAMETERS_1, HUBPREQ, id),\ + SRI(NOM_PARAMETERS_4, HUBPREQ, id),\ + SRI(NOM_PARAMETERS_5, HUBPREQ, id),\ + SRI(PER_LINE_DELIVERY_PRE, HUBPREQ, id),\ + SRI(PER_LINE_DELIVERY, HUBPREQ, id),\ + SRI(VBLANK_PARAMETERS_2, HUBPREQ, id),\ + SRI(VBLANK_PARAMETERS_4, HUBPREQ, id),\ + SRI(NOM_PARAMETERS_2, HUBPREQ, id),\ + SRI(NOM_PARAMETERS_3, HUBPREQ, id),\ + SRI(NOM_PARAMETERS_6, HUBPREQ, id),\ + SRI(NOM_PARAMETERS_7, HUBPREQ, id),\ + SRI(DCN_TTU_QOS_WM, HUBPREQ, id),\ + SRI(DCN_GLOBAL_TTU_CNTL, HUBPREQ, id),\ + SRI(DCN_SURF0_TTU_CNTL0, HUBPREQ, id),\ + SRI(DCN_SURF0_TTU_CNTL1, HUBPREQ, id),\ + SRI(DCN_SURF1_TTU_CNTL0, HUBPREQ, id),\ + SRI(DCN_SURF1_TTU_CNTL1, HUBPREQ, id),\ + SRI(DCN_VM_MX_L1_TLB_CNTL, HUBPREQ, id) + +#define MI_REG_LIST_DCN10(id)\ + MI_REG_LIST_DCN(id),\ + SRI(PREFETCH_SETTINS, HUBPREQ, id),\ + SRI(PREFETCH_SETTINS_C, HUBPREQ, id),\ + SRI(DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, HUBPREQ, id),\ + SRI(DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB, HUBPREQ, id),\ + SRI(DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB, HUBPREQ, id),\ + SRI(DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_LSB, HUBPREQ, id),\ + SRI(DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB, HUBPREQ, id),\ + SRI(DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB, HUBPREQ, id),\ + SRI(DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, HUBPREQ, id),\ + SRI(DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, HUBPREQ, id),\ + SRI(DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, HUBPREQ, id),\ + SRI(DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, HUBPREQ, id),\ + SRI(DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, HUBPREQ, id),\ + SRI(DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, HUBPREQ, id),\ + SRI(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, HUBPREQ, id),\ + SRI(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, HUBPREQ, id),\ + SR(DCHUBBUB_SDPIF_FB_BASE),\ + SR(DCHUBBUB_SDPIF_FB_OFFSET),\ + SRI(CURSOR_SETTINS, HUBPREQ, id), \ + SRI(CURSOR_SURFACE_ADDRESS_HIGH, CURSOR, id), \ + SRI(CURSOR_SURFACE_ADDRESS, CURSOR, id), \ + SRI(CURSOR_SIZE, CURSOR, id), \ + SRI(CURSOR_CONTROL, CURSOR, id), \ + SRI(CURSOR_POSITION, CURSOR, id), \ + SRI(CURSOR_HOT_SPOT, CURSOR, id), \ + SRI(CURSOR_DST_OFFSET, CURSOR, id) + + + +struct dcn_mi_registers { + uint32_t DCHUBP_CNTL; + uint32_t HUBPREQ_DEBUG_DB; + uint32_t DCSURF_ADDR_CONFIG; + uint32_t DCSURF_TILING_CONFIG; + uint32_t DCSURF_SURFACE_PITCH; + uint32_t DCSURF_SURFACE_PITCH_C; + uint32_t DCSURF_SURFACE_CONFIG; + uint32_t DCSURF_FLIP_CONTROL; + uint32_t DCSURF_PRI_VIEWPORT_DIMENSION; + uint32_t DCSURF_PRI_VIEWPORT_START; + uint32_t DCSURF_SEC_VIEWPORT_DIMENSION; + uint32_t DCSURF_SEC_VIEWPORT_START; + uint32_t DCSURF_PRI_VIEWPORT_DIMENSION_C; + uint32_t DCSURF_PRI_VIEWPORT_START_C; + uint32_t DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH; + uint32_t DCSURF_PRIMARY_SURFACE_ADDRESS; + uint32_t DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH; + uint32_t DCSURF_SECONDARY_SURFACE_ADDRESS; + uint32_t DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH; + uint32_t DCSURF_PRIMARY_META_SURFACE_ADDRESS; + uint32_t DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH; + uint32_t DCSURF_SECONDARY_META_SURFACE_ADDRESS; + uint32_t DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C; + uint32_t DCSURF_PRIMARY_SURFACE_ADDRESS_C; + uint32_t DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C; + uint32_t DCSURF_PRIMARY_META_SURFACE_ADDRESS_C; + uint32_t DCSURF_SURFACE_INUSE; + uint32_t DCSURF_SURFACE_INUSE_HIGH; + uint32_t DCSURF_SURFACE_INUSE_C; + uint32_t DCSURF_SURFACE_INUSE_HIGH_C; + uint32_t DCSURF_SURFACE_EARLIEST_INUSE; + uint32_t DCSURF_SURFACE_EARLIEST_INUSE_HIGH; + uint32_t DCSURF_SURFACE_EARLIEST_INUSE_C; + uint32_t DCSURF_SURFACE_EARLIEST_INUSE_HIGH_C; + uint32_t DCSURF_SURFACE_CONTROL; + uint32_t HUBPRET_CONTROL; + uint32_t DCN_EXPANSION_MODE; + uint32_t DCHUBP_REQ_SIZE_CONFIG; + uint32_t DCHUBP_REQ_SIZE_CONFIG_C; + uint32_t BLANK_OFFSET_0; + uint32_t BLANK_OFFSET_1; + uint32_t DST_DIMENSIONS; + uint32_t DST_AFTER_SCALER; + uint32_t PREFETCH_SETTINS; + uint32_t PREFETCH_SETTINGS; + uint32_t VBLANK_PARAMETERS_0; + uint32_t REF_FREQ_TO_PIX_FREQ; + uint32_t VBLANK_PARAMETERS_1; + uint32_t VBLANK_PARAMETERS_3; + uint32_t NOM_PARAMETERS_0; + uint32_t NOM_PARAMETERS_1; + uint32_t NOM_PARAMETERS_4; + uint32_t NOM_PARAMETERS_5; + uint32_t PER_LINE_DELIVERY_PRE; + uint32_t PER_LINE_DELIVERY; + uint32_t PREFETCH_SETTINS_C; + uint32_t PREFETCH_SETTINGS_C; + uint32_t VBLANK_PARAMETERS_2; + uint32_t VBLANK_PARAMETERS_4; + uint32_t NOM_PARAMETERS_2; + uint32_t NOM_PARAMETERS_3; + uint32_t NOM_PARAMETERS_6; + uint32_t NOM_PARAMETERS_7; + uint32_t DCN_TTU_QOS_WM; + uint32_t DCN_GLOBAL_TTU_CNTL; + uint32_t DCN_SURF0_TTU_CNTL0; + uint32_t DCN_SURF0_TTU_CNTL1; + uint32_t DCN_SURF1_TTU_CNTL0; + uint32_t DCN_SURF1_TTU_CNTL1; + uint32_t DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB; + uint32_t DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB; + uint32_t DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB; + uint32_t DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_LSB; + uint32_t DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB; + uint32_t DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB; + uint32_t DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB; + uint32_t DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB; + uint32_t DCN_VM_MX_L1_TLB_CNTL; + uint32_t DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB; + uint32_t DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB; + uint32_t DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB; + uint32_t DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB; + uint32_t DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB; + uint32_t DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB; + uint32_t DCN_VM_SYSTEM_APERTURE_LOW_ADDR; + uint32_t DCN_VM_SYSTEM_APERTURE_HIGH_ADDR; + uint32_t DCHUBBUB_SDPIF_FB_BASE; + uint32_t DCHUBBUB_SDPIF_FB_OFFSET; + uint32_t DCN_VM_FB_LOCATION_TOP; + uint32_t DCN_VM_FB_LOCATION_BASE; + uint32_t DCN_VM_FB_OFFSET; + uint32_t DCN_VM_AGP_BASE; + uint32_t DCN_VM_AGP_BOT; + uint32_t DCN_VM_AGP_TOP; + uint32_t CURSOR_SETTINS; + uint32_t CURSOR_SETTINGS; + uint32_t CURSOR_SURFACE_ADDRESS_HIGH; + uint32_t CURSOR_SURFACE_ADDRESS; + uint32_t CURSOR_SIZE; + uint32_t CURSOR_CONTROL; + uint32_t CURSOR_POSITION; + uint32_t CURSOR_HOT_SPOT; + uint32_t CURSOR_DST_OFFSET; +}; + +#define MI_SF(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define MI_MASK_SH_LIST_DCN(mask_sh)\ + MI_SF(HUBP0_DCHUBP_CNTL, HUBP_BLANK_EN, mask_sh),\ + MI_SF(HUBP0_DCHUBP_CNTL, HUBP_TTU_DISABLE, mask_sh),\ + MI_SF(HUBP0_DCHUBP_CNTL, HUBP_UNDERFLOW_STATUS, mask_sh),\ + MI_SF(HUBP0_DCHUBP_CNTL, HUBP_NO_OUTSTANDING_REQ, mask_sh),\ + MI_SF(HUBP0_DCSURF_ADDR_CONFIG, NUM_PIPES, mask_sh),\ + MI_SF(HUBP0_DCSURF_ADDR_CONFIG, NUM_BANKS, mask_sh),\ + MI_SF(HUBP0_DCSURF_ADDR_CONFIG, PIPE_INTERLEAVE, mask_sh),\ + MI_SF(HUBP0_DCSURF_ADDR_CONFIG, NUM_SE, mask_sh),\ + MI_SF(HUBP0_DCSURF_ADDR_CONFIG, NUM_RB_PER_SE, mask_sh),\ + MI_SF(HUBP0_DCSURF_ADDR_CONFIG, MAX_COMPRESSED_FRAGS, mask_sh),\ + MI_SF(HUBP0_DCSURF_TILING_CONFIG, SW_MODE, mask_sh),\ + MI_SF(HUBP0_DCSURF_TILING_CONFIG, META_LINEAR, mask_sh),\ + MI_SF(HUBP0_DCSURF_TILING_CONFIG, RB_ALIGNED, mask_sh),\ + MI_SF(HUBP0_DCSURF_TILING_CONFIG, PIPE_ALIGNED, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SURFACE_PITCH, PITCH, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SURFACE_PITCH, META_PITCH, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SURFACE_PITCH_C, PITCH_C, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SURFACE_PITCH_C, META_PITCH_C, mask_sh),\ + MI_SF(HUBP0_DCSURF_SURFACE_CONFIG, ROTATION_ANGLE, mask_sh),\ + MI_SF(HUBP0_DCSURF_SURFACE_CONFIG, H_MIRROR_EN, mask_sh),\ + MI_SF(HUBP0_DCSURF_SURFACE_CONFIG, SURFACE_PIXEL_FORMAT, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_FLIP_CONTROL, SURFACE_FLIP_TYPE, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_FLIP_CONTROL, SURFACE_FLIP_PENDING, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_FLIP_CONTROL, SURFACE_UPDATE_LOCK, mask_sh),\ + MI_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION, PRI_VIEWPORT_WIDTH, mask_sh),\ + MI_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION, PRI_VIEWPORT_HEIGHT, mask_sh),\ + MI_SF(HUBP0_DCSURF_PRI_VIEWPORT_START, PRI_VIEWPORT_X_START, mask_sh),\ + MI_SF(HUBP0_DCSURF_PRI_VIEWPORT_START, PRI_VIEWPORT_Y_START, mask_sh),\ + MI_SF(HUBP0_DCSURF_SEC_VIEWPORT_DIMENSION, SEC_VIEWPORT_WIDTH, mask_sh),\ + MI_SF(HUBP0_DCSURF_SEC_VIEWPORT_DIMENSION, SEC_VIEWPORT_HEIGHT, mask_sh),\ + MI_SF(HUBP0_DCSURF_SEC_VIEWPORT_START, SEC_VIEWPORT_X_START, mask_sh),\ + MI_SF(HUBP0_DCSURF_SEC_VIEWPORT_START, SEC_VIEWPORT_Y_START, mask_sh),\ + MI_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION_C, PRI_VIEWPORT_WIDTH_C, mask_sh),\ + MI_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION_C, PRI_VIEWPORT_HEIGHT_C, mask_sh),\ + MI_SF(HUBP0_DCSURF_PRI_VIEWPORT_START_C, PRI_VIEWPORT_X_START_C, mask_sh),\ + MI_SF(HUBP0_DCSURF_PRI_VIEWPORT_START_C, PRI_VIEWPORT_Y_START_C, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, PRIMARY_SURFACE_ADDRESS_HIGH, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_PRIMARY_SURFACE_ADDRESS, PRIMARY_SURFACE_ADDRESS, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH, SECONDARY_SURFACE_ADDRESS_HIGH, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SECONDARY_SURFACE_ADDRESS, SECONDARY_SURFACE_ADDRESS, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, PRIMARY_META_SURFACE_ADDRESS_HIGH, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_PRIMARY_META_SURFACE_ADDRESS, PRIMARY_META_SURFACE_ADDRESS, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH, SECONDARY_META_SURFACE_ADDRESS_HIGH, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SECONDARY_META_SURFACE_ADDRESS, SECONDARY_META_SURFACE_ADDRESS, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C, PRIMARY_SURFACE_ADDRESS_HIGH_C, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_PRIMARY_SURFACE_ADDRESS_C, PRIMARY_SURFACE_ADDRESS_C, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C, PRIMARY_META_SURFACE_ADDRESS_HIGH_C, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_PRIMARY_META_SURFACE_ADDRESS_C, PRIMARY_META_SURFACE_ADDRESS_C, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SURFACE_INUSE, SURFACE_INUSE_ADDRESS, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SURFACE_INUSE_HIGH, SURFACE_INUSE_ADDRESS_HIGH, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SURFACE_INUSE_C, SURFACE_INUSE_ADDRESS_C, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SURFACE_INUSE_HIGH_C, SURFACE_INUSE_ADDRESS_HIGH_C, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SURFACE_EARLIEST_INUSE, SURFACE_EARLIEST_INUSE_ADDRESS, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SURFACE_EARLIEST_INUSE_HIGH, SURFACE_EARLIEST_INUSE_ADDRESS_HIGH, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SURFACE_EARLIEST_INUSE_C, SURFACE_EARLIEST_INUSE_ADDRESS_C, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SURFACE_EARLIEST_INUSE_HIGH_C, SURFACE_EARLIEST_INUSE_ADDRESS_HIGH_C, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, PRIMARY_SURFACE_TMZ, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, PRIMARY_SURFACE_DCC_EN, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, PRIMARY_SURFACE_DCC_IND_64B_BLK, mask_sh),\ + MI_SF(HUBPRET0_HUBPRET_CONTROL, DET_BUF_PLANE1_BASE_ADDRESS, mask_sh),\ + MI_SF(HUBPRET0_HUBPRET_CONTROL, CROSSBAR_SRC_CB_B, mask_sh),\ + MI_SF(HUBPRET0_HUBPRET_CONTROL, CROSSBAR_SRC_CR_R, mask_sh),\ + MI_SF(HUBPREQ0_DCN_EXPANSION_MODE, DRQ_EXPANSION_MODE, mask_sh),\ + MI_SF(HUBPREQ0_DCN_EXPANSION_MODE, PRQ_EXPANSION_MODE, mask_sh),\ + MI_SF(HUBPREQ0_DCN_EXPANSION_MODE, MRQ_EXPANSION_MODE, mask_sh),\ + MI_SF(HUBPREQ0_DCN_EXPANSION_MODE, CRQ_EXPANSION_MODE, mask_sh),\ + MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, CHUNK_SIZE, mask_sh),\ + MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, MIN_CHUNK_SIZE, mask_sh),\ + MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, META_CHUNK_SIZE, mask_sh),\ + MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, MIN_META_CHUNK_SIZE, mask_sh),\ + MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, DPTE_GROUP_SIZE, mask_sh),\ + MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, MPTE_GROUP_SIZE, mask_sh),\ + MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, SWATH_HEIGHT, mask_sh),\ + MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, PTE_ROW_HEIGHT_LINEAR, mask_sh),\ + MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, CHUNK_SIZE_C, mask_sh),\ + MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, MIN_CHUNK_SIZE_C, mask_sh),\ + MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, META_CHUNK_SIZE_C, mask_sh),\ + MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, MIN_META_CHUNK_SIZE_C, mask_sh),\ + MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, DPTE_GROUP_SIZE_C, mask_sh),\ + MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, MPTE_GROUP_SIZE_C, mask_sh),\ + MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, SWATH_HEIGHT_C, mask_sh),\ + MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, PTE_ROW_HEIGHT_LINEAR_C, mask_sh),\ + MI_SF(HUBPREQ0_BLANK_OFFSET_0, REFCYC_H_BLANK_END, mask_sh),\ + MI_SF(HUBPREQ0_BLANK_OFFSET_0, DLG_V_BLANK_END, mask_sh),\ + MI_SF(HUBPREQ0_BLANK_OFFSET_1, MIN_DST_Y_NEXT_START, mask_sh),\ + MI_SF(HUBPREQ0_DST_DIMENSIONS, REFCYC_PER_HTOTAL, mask_sh),\ + MI_SF(HUBPREQ0_DST_AFTER_SCALER, REFCYC_X_AFTER_SCALER, mask_sh),\ + MI_SF(HUBPREQ0_DST_AFTER_SCALER, DST_Y_AFTER_SCALER, mask_sh),\ + MI_SF(HUBPREQ0_VBLANK_PARAMETERS_0, DST_Y_PER_VM_VBLANK, mask_sh),\ + MI_SF(HUBPREQ0_VBLANK_PARAMETERS_0, DST_Y_PER_ROW_VBLANK, mask_sh),\ + MI_SF(HUBPREQ0_REF_FREQ_TO_PIX_FREQ, REF_FREQ_TO_PIX_FREQ, mask_sh),\ + MI_SF(HUBPREQ0_VBLANK_PARAMETERS_1, REFCYC_PER_PTE_GROUP_VBLANK_L, mask_sh),\ + MI_SF(HUBPREQ0_VBLANK_PARAMETERS_3, REFCYC_PER_META_CHUNK_VBLANK_L, mask_sh),\ + MI_SF(HUBPREQ0_NOM_PARAMETERS_0, DST_Y_PER_PTE_ROW_NOM_L, mask_sh),\ + MI_SF(HUBPREQ0_NOM_PARAMETERS_1, REFCYC_PER_PTE_GROUP_NOM_L, mask_sh),\ + MI_SF(HUBPREQ0_NOM_PARAMETERS_4, DST_Y_PER_META_ROW_NOM_L, mask_sh),\ + MI_SF(HUBPREQ0_NOM_PARAMETERS_5, REFCYC_PER_META_CHUNK_NOM_L, mask_sh),\ + MI_SF(HUBPREQ0_PER_LINE_DELIVERY_PRE, REFCYC_PER_LINE_DELIVERY_PRE_L, mask_sh),\ + MI_SF(HUBPREQ0_PER_LINE_DELIVERY_PRE, REFCYC_PER_LINE_DELIVERY_PRE_C, mask_sh),\ + MI_SF(HUBPREQ0_PER_LINE_DELIVERY, REFCYC_PER_LINE_DELIVERY_L, mask_sh),\ + MI_SF(HUBPREQ0_PER_LINE_DELIVERY, REFCYC_PER_LINE_DELIVERY_C, mask_sh),\ + MI_SF(HUBPREQ0_VBLANK_PARAMETERS_2, REFCYC_PER_PTE_GROUP_VBLANK_C, mask_sh),\ + MI_SF(HUBPREQ0_VBLANK_PARAMETERS_4, REFCYC_PER_META_CHUNK_VBLANK_C, mask_sh),\ + MI_SF(HUBPREQ0_NOM_PARAMETERS_2, DST_Y_PER_PTE_ROW_NOM_C, mask_sh),\ + MI_SF(HUBPREQ0_NOM_PARAMETERS_3, REFCYC_PER_PTE_GROUP_NOM_C, mask_sh),\ + MI_SF(HUBPREQ0_NOM_PARAMETERS_6, DST_Y_PER_META_ROW_NOM_C, mask_sh),\ + MI_SF(HUBPREQ0_NOM_PARAMETERS_7, REFCYC_PER_META_CHUNK_NOM_C, mask_sh),\ + MI_SF(HUBPREQ0_DCN_TTU_QOS_WM, QoS_LEVEL_LOW_WM, mask_sh),\ + MI_SF(HUBPREQ0_DCN_TTU_QOS_WM, QoS_LEVEL_HIGH_WM, mask_sh),\ + MI_SF(HUBPREQ0_DCN_GLOBAL_TTU_CNTL, MIN_TTU_VBLANK, mask_sh),\ + MI_SF(HUBPREQ0_DCN_GLOBAL_TTU_CNTL, QoS_LEVEL_FLIP, mask_sh),\ + MI_SF(HUBPREQ0_DCN_SURF0_TTU_CNTL0, REFCYC_PER_REQ_DELIVERY, mask_sh),\ + MI_SF(HUBPREQ0_DCN_SURF0_TTU_CNTL0, QoS_LEVEL_FIXED, mask_sh),\ + MI_SF(HUBPREQ0_DCN_SURF0_TTU_CNTL0, QoS_RAMP_DISABLE, mask_sh),\ + MI_SF(HUBPREQ0_DCN_SURF0_TTU_CNTL1, REFCYC_PER_REQ_DELIVERY_PRE, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_MX_L1_TLB_CNTL, ENABLE_L1_TLB, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_MX_L1_TLB_CNTL, SYSTEM_ACCESS_MODE, mask_sh) + +#define MI_MASK_SH_LIST_DCN10(mask_sh)\ + MI_MASK_SH_LIST_DCN(mask_sh),\ + MI_SF(HUBPREQ0_PREFETCH_SETTINS, DST_Y_PREFETCH, mask_sh),\ + MI_SF(HUBPREQ0_PREFETCH_SETTINS, VRATIO_PREFETCH, mask_sh),\ + MI_SF(HUBPREQ0_PREFETCH_SETTINS_C, VRATIO_PREFETCH_C, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB, VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB, VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_LSB, VM_CONTEXT0_PAGE_TABLE_START_ADDR_LSB, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB, VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB, VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_SYSTEM, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, MC_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, MC_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, MC_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, MC_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, mask_sh),\ + MI_SF(DCHUBBUB_SDPIF_FB_BASE, SDPIF_FB_BASE, mask_sh),\ + MI_SF(DCHUBBUB_SDPIF_FB_OFFSET, SDPIF_FB_OFFSET, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, MC_VM_SYSTEM_APERTURE_DEFAULT_SYSTEM, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, mask_sh),\ + MI_SF(HUBPREQ0_CURSOR_SETTINS, CURSOR0_DST_Y_OFFSET, mask_sh), \ + MI_SF(HUBPREQ0_CURSOR_SETTINS, CURSOR0_CHUNK_HDL_ADJUST, mask_sh), \ + MI_SF(CURSOR0_CURSOR_SURFACE_ADDRESS_HIGH, CURSOR_SURFACE_ADDRESS_HIGH, mask_sh), \ + MI_SF(CURSOR0_CURSOR_SURFACE_ADDRESS, CURSOR_SURFACE_ADDRESS, mask_sh), \ + MI_SF(CURSOR0_CURSOR_SIZE, CURSOR_WIDTH, mask_sh), \ + MI_SF(CURSOR0_CURSOR_SIZE, CURSOR_HEIGHT, mask_sh), \ + MI_SF(CURSOR0_CURSOR_CONTROL, CURSOR_MODE, mask_sh), \ + MI_SF(CURSOR0_CURSOR_CONTROL, CURSOR_2X_MAGNIFY, mask_sh), \ + MI_SF(CURSOR0_CURSOR_CONTROL, CURSOR_PITCH, mask_sh), \ + MI_SF(CURSOR0_CURSOR_CONTROL, CURSOR_LINES_PER_CHUNK, mask_sh), \ + MI_SF(CURSOR0_CURSOR_CONTROL, CURSOR_ENABLE, mask_sh), \ + MI_SF(CURSOR0_CURSOR_POSITION, CURSOR_X_POSITION, mask_sh), \ + MI_SF(CURSOR0_CURSOR_POSITION, CURSOR_Y_POSITION, mask_sh), \ + MI_SF(CURSOR0_CURSOR_HOT_SPOT, CURSOR_HOT_SPOT_X, mask_sh), \ + MI_SF(CURSOR0_CURSOR_HOT_SPOT, CURSOR_HOT_SPOT_Y, mask_sh), \ + MI_SF(CURSOR0_CURSOR_DST_OFFSET, CURSOR_DST_X_OFFSET, mask_sh) + +#define DCN_MI_REG_FIELD_LIST(type) \ + type HUBP_BLANK_EN;\ + type HUBP_TTU_DISABLE;\ + type HUBP_NO_OUTSTANDING_REQ;\ + type HUBP_UNDERFLOW_STATUS;\ + type NUM_PIPES;\ + type NUM_BANKS;\ + type PIPE_INTERLEAVE;\ + type NUM_SE;\ + type NUM_RB_PER_SE;\ + type MAX_COMPRESSED_FRAGS;\ + type SW_MODE;\ + type META_LINEAR;\ + type RB_ALIGNED;\ + type PIPE_ALIGNED;\ + type PITCH;\ + type META_PITCH;\ + type PITCH_C;\ + type META_PITCH_C;\ + type ROTATION_ANGLE;\ + type H_MIRROR_EN;\ + type SURFACE_PIXEL_FORMAT;\ + type SURFACE_FLIP_TYPE;\ + type SURFACE_UPDATE_LOCK;\ + type SURFACE_FLIP_PENDING;\ + type PRI_VIEWPORT_WIDTH; \ + type PRI_VIEWPORT_HEIGHT; \ + type PRI_VIEWPORT_X_START; \ + type PRI_VIEWPORT_Y_START; \ + type SEC_VIEWPORT_WIDTH; \ + type SEC_VIEWPORT_HEIGHT; \ + type SEC_VIEWPORT_X_START; \ + type SEC_VIEWPORT_Y_START; \ + type PRI_VIEWPORT_WIDTH_C; \ + type PRI_VIEWPORT_HEIGHT_C; \ + type PRI_VIEWPORT_X_START_C; \ + type PRI_VIEWPORT_Y_START_C; \ + type PRIMARY_SURFACE_ADDRESS_HIGH;\ + type PRIMARY_SURFACE_ADDRESS;\ + type SECONDARY_SURFACE_ADDRESS_HIGH;\ + type SECONDARY_SURFACE_ADDRESS;\ + type PRIMARY_META_SURFACE_ADDRESS_HIGH;\ + type PRIMARY_META_SURFACE_ADDRESS;\ + type SECONDARY_META_SURFACE_ADDRESS_HIGH;\ + type SECONDARY_META_SURFACE_ADDRESS;\ + type PRIMARY_SURFACE_ADDRESS_HIGH_C;\ + type PRIMARY_SURFACE_ADDRESS_C;\ + type PRIMARY_META_SURFACE_ADDRESS_HIGH_C;\ + type PRIMARY_META_SURFACE_ADDRESS_C;\ + type SURFACE_INUSE_ADDRESS;\ + type SURFACE_INUSE_ADDRESS_HIGH;\ + type SURFACE_INUSE_ADDRESS_C;\ + type SURFACE_INUSE_ADDRESS_HIGH_C;\ + type SURFACE_EARLIEST_INUSE_ADDRESS;\ + type SURFACE_EARLIEST_INUSE_ADDRESS_HIGH;\ + type SURFACE_EARLIEST_INUSE_ADDRESS_C;\ + type SURFACE_EARLIEST_INUSE_ADDRESS_HIGH_C;\ + type PRIMARY_SURFACE_TMZ;\ + type PRIMARY_SURFACE_DCC_EN;\ + type PRIMARY_SURFACE_DCC_IND_64B_BLK;\ + type DET_BUF_PLANE1_BASE_ADDRESS;\ + type CROSSBAR_SRC_CB_B;\ + type CROSSBAR_SRC_CR_R;\ + type DRQ_EXPANSION_MODE;\ + type PRQ_EXPANSION_MODE;\ + type MRQ_EXPANSION_MODE;\ + type CRQ_EXPANSION_MODE;\ + type CHUNK_SIZE;\ + type MIN_CHUNK_SIZE;\ + type META_CHUNK_SIZE;\ + type MIN_META_CHUNK_SIZE;\ + type DPTE_GROUP_SIZE;\ + type MPTE_GROUP_SIZE;\ + type SWATH_HEIGHT;\ + type PTE_ROW_HEIGHT_LINEAR;\ + type CHUNK_SIZE_C;\ + type MIN_CHUNK_SIZE_C;\ + type META_CHUNK_SIZE_C;\ + type MIN_META_CHUNK_SIZE_C;\ + type DPTE_GROUP_SIZE_C;\ + type MPTE_GROUP_SIZE_C;\ + type SWATH_HEIGHT_C;\ + type PTE_ROW_HEIGHT_LINEAR_C;\ + type REFCYC_H_BLANK_END;\ + type DLG_V_BLANK_END;\ + type MIN_DST_Y_NEXT_START;\ + type REFCYC_PER_HTOTAL;\ + type REFCYC_X_AFTER_SCALER;\ + type DST_Y_AFTER_SCALER;\ + type DST_Y_PREFETCH;\ + type VRATIO_PREFETCH;\ + type DST_Y_PER_VM_VBLANK;\ + type DST_Y_PER_ROW_VBLANK;\ + type REF_FREQ_TO_PIX_FREQ;\ + type REFCYC_PER_PTE_GROUP_VBLANK_L;\ + type REFCYC_PER_META_CHUNK_VBLANK_L;\ + type DST_Y_PER_PTE_ROW_NOM_L;\ + type REFCYC_PER_PTE_GROUP_NOM_L;\ + type DST_Y_PER_META_ROW_NOM_L;\ + type REFCYC_PER_META_CHUNK_NOM_L;\ + type REFCYC_PER_LINE_DELIVERY_PRE_L;\ + type REFCYC_PER_LINE_DELIVERY_PRE_C;\ + type REFCYC_PER_LINE_DELIVERY_L;\ + type REFCYC_PER_LINE_DELIVERY_C;\ + type VRATIO_PREFETCH_C;\ + type REFCYC_PER_PTE_GROUP_VBLANK_C;\ + type REFCYC_PER_META_CHUNK_VBLANK_C;\ + type DST_Y_PER_PTE_ROW_NOM_C;\ + type REFCYC_PER_PTE_GROUP_NOM_C;\ + type DST_Y_PER_META_ROW_NOM_C;\ + type REFCYC_PER_META_CHUNK_NOM_C;\ + type QoS_LEVEL_LOW_WM;\ + type QoS_LEVEL_HIGH_WM;\ + type MIN_TTU_VBLANK;\ + type QoS_LEVEL_FLIP;\ + type REFCYC_PER_REQ_DELIVERY;\ + type QoS_LEVEL_FIXED;\ + type QoS_RAMP_DISABLE;\ + type REFCYC_PER_REQ_DELIVERY_PRE;\ + type VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB;\ + type VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB;\ + type VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB;\ + type VM_CONTEXT0_PAGE_TABLE_START_ADDR_LSB;\ + type VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB;\ + type VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB;\ + type VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB;\ + type VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_SYSTEM;\ + type VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB;\ + type ENABLE_L1_TLB;\ + type SYSTEM_ACCESS_MODE;\ + type MC_VM_SYSTEM_APERTURE_DEFAULT_SYSTEM;\ + type MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB;\ + type MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB;\ + type MC_VM_SYSTEM_APERTURE_LOW_ADDR_MSB;\ + type MC_VM_SYSTEM_APERTURE_LOW_ADDR_LSB;\ + type MC_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB;\ + type MC_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB;\ + type MC_VM_SYSTEM_APERTURE_LOW_ADDR;\ + type MC_VM_SYSTEM_APERTURE_HIGH_ADDR;\ + type SDPIF_FB_TOP;\ + type SDPIF_FB_BASE;\ + type SDPIF_FB_OFFSET;\ + type SDPIF_AGP_BASE;\ + type SDPIF_AGP_BOT;\ + type SDPIF_AGP_TOP;\ + type FB_TOP;\ + type FB_BASE;\ + type FB_OFFSET;\ + type AGP_BASE;\ + type AGP_BOT;\ + type AGP_TOP;\ + /* todo: get these from GVM instead of reading registers ourselves */\ + type PAGE_DIRECTORY_ENTRY_HI32;\ + type PAGE_DIRECTORY_ENTRY_LO32;\ + type LOGICAL_PAGE_NUMBER_HI4;\ + type LOGICAL_PAGE_NUMBER_LO32;\ + type PHYSICAL_PAGE_ADDR_HI4;\ + type PHYSICAL_PAGE_ADDR_LO32;\ + type PHYSICAL_PAGE_NUMBER_MSB;\ + type PHYSICAL_PAGE_NUMBER_LSB;\ + type LOGICAL_ADDR;\ + type CURSOR0_DST_Y_OFFSET; \ + type CURSOR0_CHUNK_HDL_ADJUST; \ + type CURSOR_SURFACE_ADDRESS_HIGH; \ + type CURSOR_SURFACE_ADDRESS; \ + type CURSOR_WIDTH; \ + type CURSOR_HEIGHT; \ + type CURSOR_MODE; \ + type CURSOR_2X_MAGNIFY; \ + type CURSOR_PITCH; \ + type CURSOR_LINES_PER_CHUNK; \ + type CURSOR_ENABLE; \ + type CURSOR_X_POSITION; \ + type CURSOR_Y_POSITION; \ + type CURSOR_HOT_SPOT_X; \ + type CURSOR_HOT_SPOT_Y; \ + type CURSOR_DST_X_OFFSET; \ + type OUTPUT_FP + +struct dcn_mi_shift { + DCN_MI_REG_FIELD_LIST(uint8_t); +}; + +struct dcn_mi_mask { + DCN_MI_REG_FIELD_LIST(uint32_t); +}; + +struct dcn10_hubp { + struct hubp base; + const struct dcn_mi_registers *mi_regs; + const struct dcn_mi_shift *mi_shift; + const struct dcn_mi_mask *mi_mask; +}; + +void hubp1_program_surface_config( + struct hubp *hubp, + enum surface_pixel_format format, + union dc_tiling_info *tiling_info, + union plane_size *plane_size, + enum dc_rotation_angle rotation, + struct dc_plane_dcc_param *dcc, + bool horizontal_mirror); + +void hubp1_program_deadline( + struct hubp *hubp, + struct _vcs_dpi_display_dlg_regs_st *dlg_attr, + struct _vcs_dpi_display_ttu_regs_st *ttu_attr); + +void hubp1_program_requestor( + struct hubp *hubp, + struct _vcs_dpi_display_rq_regs_st *rq_regs); + +void hubp1_program_pixel_format( + struct dcn10_hubp *hubp, + enum surface_pixel_format format); + +void hubp1_program_size_and_rotation( + struct dcn10_hubp *hubp, + enum dc_rotation_angle rotation, + enum surface_pixel_format format, + const union plane_size *plane_size, + struct dc_plane_dcc_param *dcc, + bool horizontal_mirror); + +void hubp1_program_tiling( + struct dcn10_hubp *hubp, + const union dc_tiling_info *info, + const enum surface_pixel_format pixel_format); + +void hubp1_dcc_control(struct hubp *hubp, + bool enable, + bool independent_64b_blks); + +bool hubp1_program_surface_flip_and_addr( + struct hubp *hubp, + const struct dc_plane_address *address, + bool flip_immediate); + +bool hubp1_is_flip_pending(struct hubp *hubp); + +void hubp1_cursor_set_attributes( + struct hubp *hubp, + const struct dc_cursor_attributes *attr); + +void hubp1_cursor_set_position( + struct hubp *hubp, + const struct dc_cursor_position *pos, + const struct dc_cursor_mi_param *param); + +void hubp1_set_blank(struct hubp *hubp, bool blank); + +void min_set_viewport(struct hubp *hubp, + const struct rect *viewport, + const struct rect *viewport_c); + +void dcn10_hubp_construct( + struct dcn10_hubp *hubp1, + struct dc_context *ctx, + uint32_t inst, + const struct dcn_mi_registers *mi_regs, + const struct dcn_mi_shift *mi_shift, + const struct dcn_mi_mask *mi_mask); + + +struct dcn_hubp_state { + uint32_t pixel_format; + uint32_t inuse_addr_hi; + uint32_t viewport_width; + uint32_t viewport_height; + uint32_t rotation_angle; + uint32_t h_mirror_en; + uint32_t sw_mode; + uint32_t dcc_en; + uint32_t blank_en; + uint32_t underflow_status; + uint32_t ttu_disable; + uint32_t min_ttu_vblank; + uint32_t qos_level_low_wm; + uint32_t qos_level_high_wm; +}; +void hubp1_read_state(struct dcn10_hubp *hubp1, + struct dcn_hubp_state *s); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 059da7882a68..6b866b169985 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -31,7 +31,6 @@ #include "dce110/dce110_hw_sequencer.h" #include "dce/dce_hwseq.h" #include "abm.h" -#include "dcn10/dcn10_mem_input.h" #include "dcn10/dcn10_timing_generator.h" #include "dcn10/dcn10_dpp.h" #include "dcn10/dcn10_mpc.h" @@ -41,6 +40,7 @@ #include "mpc.h" #include "reg_helper.h" #include "custom_float.h" +#include "dcn10_hubp.h" #define CTX \ hws->ctx diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c deleted file mode 100644 index 9ee42d9840fb..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ /dev/null @@ -1,960 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ -#include "dm_services.h" -#include "dce_calcs.h" -#include "dcn10_mem_input.h" -#include "reg_helper.h" -#include "basics/conversion.h" - -#define REG(reg)\ - hubp1->mi_regs->reg - -#define CTX \ - hubp1->base.ctx - -#undef FN -#define FN(reg_name, field_name) \ - hubp1->mi_shift->field_name, hubp1->mi_mask->field_name - -void hubp1_set_blank(struct hubp *hubp, bool blank) -{ - struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); - uint32_t blank_en = blank ? 1 : 0; - - REG_UPDATE_2(DCHUBP_CNTL, - HUBP_BLANK_EN, blank_en, - HUBP_TTU_DISABLE, blank_en); - - if (blank) { - REG_WAIT(DCHUBP_CNTL, - HUBP_NO_OUTSTANDING_REQ, 1, - 1, 200); - hubp->mpcc_id = 0xf; - hubp->opp_id = 0xf; - } -} - -static void hubp1_set_hubp_blank_en(struct hubp *hubp, bool blank) -{ - struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); - uint32_t blank_en = blank ? 1 : 0; - - REG_UPDATE(DCHUBP_CNTL, HUBP_BLANK_EN, blank_en); -} - -static void hubp1_vready_workaround(struct hubp *hubp, - struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest) -{ - uint32_t value = 0; - struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); - - /* set HBUBREQ_DEBUG_DB[12] = 1 */ - value = REG_READ(HUBPREQ_DEBUG_DB); - - /* hack mode disable */ - value |= 0x100; - value &= ~0x1000; - - if ((pipe_dest->vstartup_start - 2*(pipe_dest->vready_offset+pipe_dest->vupdate_width - + pipe_dest->vupdate_offset) / pipe_dest->htotal) <= pipe_dest->vblank_end) { - /* if (eco_fix_needed(otg_global_sync_timing) - * set HBUBREQ_DEBUG_DB[12] = 1 */ - value |= 0x1000; - } - - REG_WRITE(HUBPREQ_DEBUG_DB, value); -} - -void hubp1_program_tiling( - struct dcn10_hubp *hubp1, - const union dc_tiling_info *info, - const enum surface_pixel_format pixel_format) -{ - REG_UPDATE_6(DCSURF_ADDR_CONFIG, - NUM_PIPES, log_2(info->gfx9.num_pipes), - NUM_BANKS, log_2(info->gfx9.num_banks), - PIPE_INTERLEAVE, info->gfx9.pipe_interleave, - NUM_SE, log_2(info->gfx9.num_shader_engines), - NUM_RB_PER_SE, log_2(info->gfx9.num_rb_per_se), - MAX_COMPRESSED_FRAGS, log_2(info->gfx9.max_compressed_frags)); - - REG_UPDATE_4(DCSURF_TILING_CONFIG, - SW_MODE, info->gfx9.swizzle, - META_LINEAR, info->gfx9.meta_linear, - RB_ALIGNED, info->gfx9.rb_aligned, - PIPE_ALIGNED, info->gfx9.pipe_aligned); -} - -void hubp1_program_size_and_rotation( - struct dcn10_hubp *hubp1, - enum dc_rotation_angle rotation, - enum surface_pixel_format format, - const union plane_size *plane_size, - struct dc_plane_dcc_param *dcc, - bool horizontal_mirror) -{ - uint32_t pitch, meta_pitch, pitch_c, meta_pitch_c, mirror; - - /* Program data and meta surface pitch (calculation from addrlib) - * 444 or 420 luma - */ - if (format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) { - pitch = plane_size->video.luma_pitch - 1; - meta_pitch = dcc->video.meta_pitch_l - 1; - pitch_c = plane_size->video.chroma_pitch - 1; - meta_pitch_c = dcc->video.meta_pitch_c - 1; - } else { - pitch = plane_size->grph.surface_pitch - 1; - meta_pitch = dcc->grph.meta_pitch - 1; - pitch_c = 0; - meta_pitch_c = 0; - } - - if (!dcc->enable) { - meta_pitch = 0; - meta_pitch_c = 0; - } - - REG_UPDATE_2(DCSURF_SURFACE_PITCH, - PITCH, pitch, META_PITCH, meta_pitch); - - if (format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) - REG_UPDATE_2(DCSURF_SURFACE_PITCH_C, - PITCH_C, pitch_c, META_PITCH_C, meta_pitch_c); - - if (horizontal_mirror) - mirror = 1; - else - mirror = 0; - - - /* Program rotation angle and horz mirror - no mirror */ - if (rotation == ROTATION_ANGLE_0) - REG_UPDATE_2(DCSURF_SURFACE_CONFIG, - ROTATION_ANGLE, 0, - H_MIRROR_EN, mirror); - else if (rotation == ROTATION_ANGLE_90) - REG_UPDATE_2(DCSURF_SURFACE_CONFIG, - ROTATION_ANGLE, 1, - H_MIRROR_EN, mirror); - else if (rotation == ROTATION_ANGLE_180) - REG_UPDATE_2(DCSURF_SURFACE_CONFIG, - ROTATION_ANGLE, 2, - H_MIRROR_EN, mirror); - else if (rotation == ROTATION_ANGLE_270) - REG_UPDATE_2(DCSURF_SURFACE_CONFIG, - ROTATION_ANGLE, 3, - H_MIRROR_EN, mirror); -} - -void hubp1_program_pixel_format( - struct dcn10_hubp *hubp1, - enum surface_pixel_format format) -{ - uint32_t red_bar = 3; - uint32_t blue_bar = 2; - - /* swap for ABGR format */ - if (format == SURFACE_PIXEL_FORMAT_GRPH_ABGR8888 - || format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010 - || format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS - || format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F) { - red_bar = 2; - blue_bar = 3; - } - - REG_UPDATE_2(HUBPRET_CONTROL, - CROSSBAR_SRC_CB_B, blue_bar, - CROSSBAR_SRC_CR_R, red_bar); - - /* Mapping is same as ipp programming (cnvc) */ - - switch (format) { - case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: - REG_UPDATE(DCSURF_SURFACE_CONFIG, - SURFACE_PIXEL_FORMAT, 1); - break; - case SURFACE_PIXEL_FORMAT_GRPH_RGB565: - REG_UPDATE(DCSURF_SURFACE_CONFIG, - SURFACE_PIXEL_FORMAT, 3); - break; - case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: - case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: - REG_UPDATE(DCSURF_SURFACE_CONFIG, - SURFACE_PIXEL_FORMAT, 8); - break; - case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: - case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: - case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: - REG_UPDATE(DCSURF_SURFACE_CONFIG, - SURFACE_PIXEL_FORMAT, 10); - break; - case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: - REG_UPDATE(DCSURF_SURFACE_CONFIG, - SURFACE_PIXEL_FORMAT, 22); - break; - case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: - case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:/*we use crossbar already*/ - REG_UPDATE(DCSURF_SURFACE_CONFIG, - SURFACE_PIXEL_FORMAT, 24); - break; - - case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: - REG_UPDATE(DCSURF_SURFACE_CONFIG, - SURFACE_PIXEL_FORMAT, 65); - break; - case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: - REG_UPDATE(DCSURF_SURFACE_CONFIG, - SURFACE_PIXEL_FORMAT, 64); - break; - case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: - REG_UPDATE(DCSURF_SURFACE_CONFIG, - SURFACE_PIXEL_FORMAT, 67); - break; - case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: - REG_UPDATE(DCSURF_SURFACE_CONFIG, - SURFACE_PIXEL_FORMAT, 66); - break; - default: - BREAK_TO_DEBUGGER(); - break; - } - - /* don't see the need of program the xbar in DCN 1.0 */ -} - -bool hubp1_program_surface_flip_and_addr( - struct hubp *hubp, - const struct dc_plane_address *address, - bool flip_immediate) -{ - struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); - - /* program flip type */ - REG_SET(DCSURF_FLIP_CONTROL, 0, - SURFACE_FLIP_TYPE, flip_immediate); - - /* HW automatically latch rest of address register on write to - * DCSURF_PRIMARY_SURFACE_ADDRESS if SURFACE_UPDATE_LOCK is not used - * - * program high first and then the low addr, order matters! - */ - switch (address->type) { - case PLN_ADDR_TYPE_GRAPHICS: - /* DCN1.0 does not support const color - * TODO: program DCHUBBUB_RET_PATH_DCC_CFGx_0/1 - * base on address->grph.dcc_const_color - * x = 0, 2, 4, 6 for pipe 0, 1, 2, 3 for rgb and luma - * x = 1, 3, 5, 7 for pipe 0, 1, 2, 3 for chroma - */ - - if (address->grph.addr.quad_part == 0) - break; - - REG_UPDATE(DCSURF_SURFACE_CONTROL, - PRIMARY_SURFACE_TMZ, address->tmz_surface); - - if (address->grph.meta_addr.quad_part != 0) { - REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, 0, - PRIMARY_META_SURFACE_ADDRESS_HIGH, - address->grph.meta_addr.high_part); - - REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS, 0, - PRIMARY_META_SURFACE_ADDRESS, - address->grph.meta_addr.low_part); - } - - REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, 0, - PRIMARY_SURFACE_ADDRESS_HIGH, - address->grph.addr.high_part); - - REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS, 0, - PRIMARY_SURFACE_ADDRESS, - address->grph.addr.low_part); - break; - case PLN_ADDR_TYPE_VIDEO_PROGRESSIVE: - if (address->video_progressive.luma_addr.quad_part == 0 - || address->video_progressive.chroma_addr.quad_part == 0) - break; - - REG_UPDATE(DCSURF_SURFACE_CONTROL, - PRIMARY_SURFACE_TMZ, address->tmz_surface); - - if (address->video_progressive.luma_meta_addr.quad_part != 0) { - REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C, 0, - PRIMARY_META_SURFACE_ADDRESS_HIGH_C, - address->video_progressive.chroma_meta_addr.high_part); - - REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_C, 0, - PRIMARY_META_SURFACE_ADDRESS_C, - address->video_progressive.chroma_meta_addr.low_part); - - REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, 0, - PRIMARY_META_SURFACE_ADDRESS_HIGH, - address->video_progressive.luma_meta_addr.high_part); - - REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS, 0, - PRIMARY_META_SURFACE_ADDRESS, - address->video_progressive.luma_meta_addr.low_part); - } - - REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C, 0, - PRIMARY_SURFACE_ADDRESS_HIGH_C, - address->video_progressive.chroma_addr.high_part); - - REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_C, 0, - PRIMARY_SURFACE_ADDRESS_C, - address->video_progressive.chroma_addr.low_part); - - REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, 0, - PRIMARY_SURFACE_ADDRESS_HIGH, - address->video_progressive.luma_addr.high_part); - - REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS, 0, - PRIMARY_SURFACE_ADDRESS, - address->video_progressive.luma_addr.low_part); - break; - case PLN_ADDR_TYPE_GRPH_STEREO: - if (address->grph_stereo.left_addr.quad_part == 0) - break; - if (address->grph_stereo.right_addr.quad_part == 0) - break; - - REG_UPDATE(DCSURF_SURFACE_CONTROL, - PRIMARY_SURFACE_TMZ, address->tmz_surface); - - if (address->grph_stereo.right_meta_addr.quad_part != 0) { - - REG_SET(DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH, 0, - SECONDARY_META_SURFACE_ADDRESS_HIGH, - address->grph_stereo.right_meta_addr.high_part); - - REG_SET(DCSURF_SECONDARY_META_SURFACE_ADDRESS, 0, - SECONDARY_META_SURFACE_ADDRESS, - address->grph_stereo.right_meta_addr.low_part); - } - if (address->grph_stereo.left_meta_addr.quad_part != 0) { - - REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, 0, - PRIMARY_META_SURFACE_ADDRESS_HIGH, - address->grph_stereo.left_meta_addr.high_part); - - REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS, 0, - PRIMARY_META_SURFACE_ADDRESS, - address->grph_stereo.left_meta_addr.low_part); - } - - REG_SET(DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH, 0, - SECONDARY_SURFACE_ADDRESS_HIGH, - address->grph_stereo.right_addr.high_part); - - REG_SET(DCSURF_SECONDARY_SURFACE_ADDRESS, 0, - SECONDARY_SURFACE_ADDRESS, - address->grph_stereo.right_addr.low_part); - - REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, 0, - PRIMARY_SURFACE_ADDRESS_HIGH, - address->grph_stereo.left_addr.high_part); - - REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS, 0, - PRIMARY_SURFACE_ADDRESS, - address->grph_stereo.left_addr.low_part); - break; - default: - BREAK_TO_DEBUGGER(); - break; - } - - hubp->request_address = *address; - - if (flip_immediate) - hubp->current_address = *address; - - return true; -} - -void hubp1_dcc_control(struct hubp *hubp, bool enable, - bool independent_64b_blks) -{ - uint32_t dcc_en = enable ? 1 : 0; - uint32_t dcc_ind_64b_blk = independent_64b_blks ? 1 : 0; - struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); - - REG_UPDATE_2(DCSURF_SURFACE_CONTROL, - PRIMARY_SURFACE_DCC_EN, dcc_en, - PRIMARY_SURFACE_DCC_IND_64B_BLK, dcc_ind_64b_blk); -} - -void hubp1_program_surface_config( - struct hubp *hubp, - enum surface_pixel_format format, - union dc_tiling_info *tiling_info, - union plane_size *plane_size, - enum dc_rotation_angle rotation, - struct dc_plane_dcc_param *dcc, - bool horizontal_mirror) -{ - struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); - - hubp1_dcc_control(hubp, dcc->enable, dcc->grph.independent_64b_blks); - hubp1_program_tiling(hubp1, tiling_info, format); - hubp1_program_size_and_rotation( - hubp1, rotation, format, plane_size, dcc, horizontal_mirror); - hubp1_program_pixel_format(hubp1, format); -} - -void hubp1_program_requestor( - struct hubp *hubp, - struct _vcs_dpi_display_rq_regs_st *rq_regs) -{ - struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); - - REG_UPDATE(HUBPRET_CONTROL, - DET_BUF_PLANE1_BASE_ADDRESS, rq_regs->plane1_base_address); - REG_SET_4(DCN_EXPANSION_MODE, 0, - DRQ_EXPANSION_MODE, rq_regs->drq_expansion_mode, - PRQ_EXPANSION_MODE, rq_regs->prq_expansion_mode, - MRQ_EXPANSION_MODE, rq_regs->mrq_expansion_mode, - CRQ_EXPANSION_MODE, rq_regs->crq_expansion_mode); - REG_SET_8(DCHUBP_REQ_SIZE_CONFIG, 0, - CHUNK_SIZE, rq_regs->rq_regs_l.chunk_size, - MIN_CHUNK_SIZE, rq_regs->rq_regs_l.min_chunk_size, - META_CHUNK_SIZE, rq_regs->rq_regs_l.meta_chunk_size, - MIN_META_CHUNK_SIZE, rq_regs->rq_regs_l.min_meta_chunk_size, - DPTE_GROUP_SIZE, rq_regs->rq_regs_l.dpte_group_size, - MPTE_GROUP_SIZE, rq_regs->rq_regs_l.mpte_group_size, - SWATH_HEIGHT, rq_regs->rq_regs_l.swath_height, - PTE_ROW_HEIGHT_LINEAR, rq_regs->rq_regs_l.pte_row_height_linear); - REG_SET_8(DCHUBP_REQ_SIZE_CONFIG_C, 0, - CHUNK_SIZE_C, rq_regs->rq_regs_c.chunk_size, - MIN_CHUNK_SIZE_C, rq_regs->rq_regs_c.min_chunk_size, - META_CHUNK_SIZE_C, rq_regs->rq_regs_c.meta_chunk_size, - MIN_META_CHUNK_SIZE_C, rq_regs->rq_regs_c.min_meta_chunk_size, - DPTE_GROUP_SIZE_C, rq_regs->rq_regs_c.dpte_group_size, - MPTE_GROUP_SIZE_C, rq_regs->rq_regs_c.mpte_group_size, - SWATH_HEIGHT_C, rq_regs->rq_regs_c.swath_height, - PTE_ROW_HEIGHT_LINEAR_C, rq_regs->rq_regs_c.pte_row_height_linear); -} - - -void hubp1_program_deadline( - struct hubp *hubp, - struct _vcs_dpi_display_dlg_regs_st *dlg_attr, - struct _vcs_dpi_display_ttu_regs_st *ttu_attr) -{ - struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); - - /* DLG - Per hubp */ - REG_SET_2(BLANK_OFFSET_0, 0, - REFCYC_H_BLANK_END, dlg_attr->refcyc_h_blank_end, - DLG_V_BLANK_END, dlg_attr->dlg_vblank_end); - - REG_SET(BLANK_OFFSET_1, 0, - MIN_DST_Y_NEXT_START, dlg_attr->min_dst_y_next_start); - - REG_SET(DST_DIMENSIONS, 0, - REFCYC_PER_HTOTAL, dlg_attr->refcyc_per_htotal); - - REG_SET_2(DST_AFTER_SCALER, 0, - REFCYC_X_AFTER_SCALER, dlg_attr->refcyc_x_after_scaler, - DST_Y_AFTER_SCALER, dlg_attr->dst_y_after_scaler); - - if (REG(PREFETCH_SETTINS)) - REG_SET_2(PREFETCH_SETTINS, 0, - DST_Y_PREFETCH, dlg_attr->dst_y_prefetch, - VRATIO_PREFETCH, dlg_attr->vratio_prefetch); - else - REG_SET_2(PREFETCH_SETTINGS, 0, - DST_Y_PREFETCH, dlg_attr->dst_y_prefetch, - VRATIO_PREFETCH, dlg_attr->vratio_prefetch); - - REG_SET_2(VBLANK_PARAMETERS_0, 0, - DST_Y_PER_VM_VBLANK, dlg_attr->dst_y_per_vm_vblank, - DST_Y_PER_ROW_VBLANK, dlg_attr->dst_y_per_row_vblank); - - REG_SET(REF_FREQ_TO_PIX_FREQ, 0, - REF_FREQ_TO_PIX_FREQ, dlg_attr->ref_freq_to_pix_freq); - - /* DLG - Per luma/chroma */ - REG_SET(VBLANK_PARAMETERS_1, 0, - REFCYC_PER_PTE_GROUP_VBLANK_L, dlg_attr->refcyc_per_pte_group_vblank_l); - - REG_SET(VBLANK_PARAMETERS_3, 0, - REFCYC_PER_META_CHUNK_VBLANK_L, dlg_attr->refcyc_per_meta_chunk_vblank_l); - - REG_SET(NOM_PARAMETERS_0, 0, - DST_Y_PER_PTE_ROW_NOM_L, dlg_attr->dst_y_per_pte_row_nom_l); - - REG_SET(NOM_PARAMETERS_1, 0, - REFCYC_PER_PTE_GROUP_NOM_L, dlg_attr->refcyc_per_pte_group_nom_l); - - REG_SET(NOM_PARAMETERS_4, 0, - DST_Y_PER_META_ROW_NOM_L, dlg_attr->dst_y_per_meta_row_nom_l); - - REG_SET(NOM_PARAMETERS_5, 0, - REFCYC_PER_META_CHUNK_NOM_L, dlg_attr->refcyc_per_meta_chunk_nom_l); - - REG_SET_2(PER_LINE_DELIVERY_PRE, 0, - REFCYC_PER_LINE_DELIVERY_PRE_L, dlg_attr->refcyc_per_line_delivery_pre_l, - REFCYC_PER_LINE_DELIVERY_PRE_C, dlg_attr->refcyc_per_line_delivery_pre_c); - - REG_SET_2(PER_LINE_DELIVERY, 0, - REFCYC_PER_LINE_DELIVERY_L, dlg_attr->refcyc_per_line_delivery_l, - REFCYC_PER_LINE_DELIVERY_C, dlg_attr->refcyc_per_line_delivery_c); - - if (REG(PREFETCH_SETTINS_C)) - REG_SET(PREFETCH_SETTINS_C, 0, - VRATIO_PREFETCH_C, dlg_attr->vratio_prefetch_c); - else - REG_SET(PREFETCH_SETTINGS_C, 0, - VRATIO_PREFETCH_C, dlg_attr->vratio_prefetch_c); - - REG_SET(VBLANK_PARAMETERS_2, 0, - REFCYC_PER_PTE_GROUP_VBLANK_C, dlg_attr->refcyc_per_pte_group_vblank_c); - - REG_SET(VBLANK_PARAMETERS_4, 0, - REFCYC_PER_META_CHUNK_VBLANK_C, dlg_attr->refcyc_per_meta_chunk_vblank_c); - - REG_SET(NOM_PARAMETERS_2, 0, - DST_Y_PER_PTE_ROW_NOM_C, dlg_attr->dst_y_per_pte_row_nom_c); - - REG_SET(NOM_PARAMETERS_3, 0, - REFCYC_PER_PTE_GROUP_NOM_C, dlg_attr->refcyc_per_pte_group_nom_c); - - REG_SET(NOM_PARAMETERS_6, 0, - DST_Y_PER_META_ROW_NOM_C, dlg_attr->dst_y_per_meta_row_nom_c); - - REG_SET(NOM_PARAMETERS_7, 0, - REFCYC_PER_META_CHUNK_NOM_C, dlg_attr->refcyc_per_meta_chunk_nom_c); - - /* TTU - per hubp */ - REG_SET_2(DCN_TTU_QOS_WM, 0, - QoS_LEVEL_LOW_WM, ttu_attr->qos_level_low_wm, - QoS_LEVEL_HIGH_WM, ttu_attr->qos_level_high_wm); - - REG_SET_2(DCN_GLOBAL_TTU_CNTL, 0, - MIN_TTU_VBLANK, ttu_attr->min_ttu_vblank, - QoS_LEVEL_FLIP, ttu_attr->qos_level_flip); - - /* TTU - per luma/chroma */ - /* Assumed surf0 is luma and 1 is chroma */ - - REG_SET_3(DCN_SURF0_TTU_CNTL0, 0, - REFCYC_PER_REQ_DELIVERY, ttu_attr->refcyc_per_req_delivery_l, - QoS_LEVEL_FIXED, ttu_attr->qos_level_fixed_l, - QoS_RAMP_DISABLE, ttu_attr->qos_ramp_disable_l); - - REG_SET(DCN_SURF0_TTU_CNTL1, 0, - REFCYC_PER_REQ_DELIVERY_PRE, - ttu_attr->refcyc_per_req_delivery_pre_l); - - REG_SET_3(DCN_SURF1_TTU_CNTL0, 0, - REFCYC_PER_REQ_DELIVERY, ttu_attr->refcyc_per_req_delivery_c, - QoS_LEVEL_FIXED, ttu_attr->qos_level_fixed_c, - QoS_RAMP_DISABLE, ttu_attr->qos_ramp_disable_c); - - REG_SET(DCN_SURF1_TTU_CNTL1, 0, - REFCYC_PER_REQ_DELIVERY_PRE, - ttu_attr->refcyc_per_req_delivery_pre_c); -} - -static void hubp1_setup( - struct hubp *hubp, - struct _vcs_dpi_display_dlg_regs_st *dlg_attr, - struct _vcs_dpi_display_ttu_regs_st *ttu_attr, - struct _vcs_dpi_display_rq_regs_st *rq_regs, - struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest) -{ - /* otg is locked when this func is called. Register are double buffered. - * disable the requestors is not needed - */ - hubp1_program_requestor(hubp, rq_regs); - hubp1_program_deadline(hubp, dlg_attr, ttu_attr); - hubp1_vready_workaround(hubp, pipe_dest); -} - -bool hubp1_is_flip_pending(struct hubp *hubp) -{ - uint32_t flip_pending = 0; - struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); - struct dc_plane_address earliest_inuse_address; - - REG_GET(DCSURF_FLIP_CONTROL, - SURFACE_FLIP_PENDING, &flip_pending); - - REG_GET(DCSURF_SURFACE_EARLIEST_INUSE, - SURFACE_EARLIEST_INUSE_ADDRESS, &earliest_inuse_address.grph.addr.low_part); - - REG_GET(DCSURF_SURFACE_EARLIEST_INUSE_HIGH, - SURFACE_EARLIEST_INUSE_ADDRESS_HIGH, &earliest_inuse_address.grph.addr.high_part); - - if (flip_pending) - return true; - - if (earliest_inuse_address.grph.addr.quad_part != hubp->request_address.grph.addr.quad_part) - return true; - - hubp->current_address = hubp->request_address; - return false; -} - -uint32_t aperture_default_system = 1; -uint32_t context0_default_system; /* = 0;*/ - -static void hubp1_set_vm_system_aperture_settings(struct hubp *hubp, - struct vm_system_aperture_param *apt) -{ - struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); - PHYSICAL_ADDRESS_LOC mc_vm_apt_default; - PHYSICAL_ADDRESS_LOC mc_vm_apt_low; - PHYSICAL_ADDRESS_LOC mc_vm_apt_high; - - mc_vm_apt_default.quad_part = apt->sys_default.quad_part >> 12; - mc_vm_apt_low.quad_part = apt->sys_low.quad_part >> 12; - mc_vm_apt_high.quad_part = apt->sys_high.quad_part >> 12; - - REG_SET_2(DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, 0, - MC_VM_SYSTEM_APERTURE_DEFAULT_SYSTEM, aperture_default_system, /* 1 = system physical memory */ - MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, mc_vm_apt_default.high_part); - REG_SET(DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, 0, - MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, mc_vm_apt_default.low_part); - - REG_SET(DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, 0, - MC_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, mc_vm_apt_low.high_part); - REG_SET(DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, 0, - MC_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, mc_vm_apt_low.low_part); - - REG_SET(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, 0, - MC_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, mc_vm_apt_high.high_part); - REG_SET(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, 0, - MC_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, mc_vm_apt_high.low_part); -} - -static void hubp1_set_vm_context0_settings(struct hubp *hubp, - const struct vm_context0_param *vm0) -{ - struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); - /* pte base */ - REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, 0, - VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, vm0->pte_base.high_part); - REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB, 0, - VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB, vm0->pte_base.low_part); - - /* pte start */ - REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB, 0, - VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB, vm0->pte_start.high_part); - REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_LSB, 0, - VM_CONTEXT0_PAGE_TABLE_START_ADDR_LSB, vm0->pte_start.low_part); - - /* pte end */ - REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB, 0, - VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB, vm0->pte_end.high_part); - REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB, 0, - VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB, vm0->pte_end.low_part); - - /* fault handling */ - REG_SET_2(DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, 0, - VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, vm0->fault_default.high_part, - VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_SYSTEM, context0_default_system); - REG_SET(DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, 0, - VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, vm0->fault_default.low_part); - - /* control: enable VM PTE*/ - REG_SET_2(DCN_VM_MX_L1_TLB_CNTL, 0, - ENABLE_L1_TLB, 1, - SYSTEM_ACCESS_MODE, 3); -} - -void min_set_viewport( - struct hubp *hubp, - const struct rect *viewport, - const struct rect *viewport_c) -{ - struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); - - REG_SET_2(DCSURF_PRI_VIEWPORT_DIMENSION, 0, - PRI_VIEWPORT_WIDTH, viewport->width, - PRI_VIEWPORT_HEIGHT, viewport->height); - - REG_SET_2(DCSURF_PRI_VIEWPORT_START, 0, - PRI_VIEWPORT_X_START, viewport->x, - PRI_VIEWPORT_Y_START, viewport->y); - - /*for stereo*/ - REG_SET_2(DCSURF_SEC_VIEWPORT_DIMENSION, 0, - SEC_VIEWPORT_WIDTH, viewport->width, - SEC_VIEWPORT_HEIGHT, viewport->height); - - REG_SET_2(DCSURF_SEC_VIEWPORT_START, 0, - SEC_VIEWPORT_X_START, viewport->x, - SEC_VIEWPORT_Y_START, viewport->y); - - /* DC supports NV12 only at the moment */ - REG_SET_2(DCSURF_PRI_VIEWPORT_DIMENSION_C, 0, - PRI_VIEWPORT_WIDTH_C, viewport_c->width, - PRI_VIEWPORT_HEIGHT_C, viewport_c->height); - - REG_SET_2(DCSURF_PRI_VIEWPORT_START_C, 0, - PRI_VIEWPORT_X_START_C, viewport_c->x, - PRI_VIEWPORT_Y_START_C, viewport_c->y); -} - -void hubp1_read_state(struct dcn10_hubp *hubp1, - struct dcn_hubp_state *s) -{ - REG_GET(DCSURF_SURFACE_CONFIG, - SURFACE_PIXEL_FORMAT, &s->pixel_format); - - REG_GET(DCSURF_SURFACE_EARLIEST_INUSE_HIGH, - SURFACE_EARLIEST_INUSE_ADDRESS_HIGH, &s->inuse_addr_hi); - - REG_GET_2(DCSURF_PRI_VIEWPORT_DIMENSION, - PRI_VIEWPORT_WIDTH, &s->viewport_width, - PRI_VIEWPORT_HEIGHT, &s->viewport_height); - - REG_GET_2(DCSURF_SURFACE_CONFIG, - ROTATION_ANGLE, &s->rotation_angle, - H_MIRROR_EN, &s->h_mirror_en); - - REG_GET(DCSURF_TILING_CONFIG, - SW_MODE, &s->sw_mode); - - REG_GET(DCSURF_SURFACE_CONTROL, - PRIMARY_SURFACE_DCC_EN, &s->dcc_en); - - REG_GET_3(DCHUBP_CNTL, - HUBP_BLANK_EN, &s->blank_en, - HUBP_TTU_DISABLE, &s->ttu_disable, - HUBP_UNDERFLOW_STATUS, &s->underflow_status); - - REG_GET(DCN_GLOBAL_TTU_CNTL, - MIN_TTU_VBLANK, &s->min_ttu_vblank); - - REG_GET_2(DCN_TTU_QOS_WM, - QoS_LEVEL_LOW_WM, &s->qos_level_low_wm, - QoS_LEVEL_HIGH_WM, &s->qos_level_high_wm); -} - -enum cursor_pitch { - CURSOR_PITCH_64_PIXELS = 0, - CURSOR_PITCH_128_PIXELS, - CURSOR_PITCH_256_PIXELS -}; - -enum cursor_lines_per_chunk { - CURSOR_LINE_PER_CHUNK_2 = 1, - CURSOR_LINE_PER_CHUNK_4, - CURSOR_LINE_PER_CHUNK_8, - CURSOR_LINE_PER_CHUNK_16 -}; - -static bool ippn10_cursor_program_control( - struct dcn10_hubp *hubp1, - bool pixel_data_invert, - enum dc_cursor_color_format color_format) -{ - if (REG(CURSOR_SETTINS)) - REG_SET_2(CURSOR_SETTINS, 0, - /* no shift of the cursor HDL schedule */ - CURSOR0_DST_Y_OFFSET, 0, - /* used to shift the cursor chunk request deadline */ - CURSOR0_CHUNK_HDL_ADJUST, 3); - else - REG_SET_2(CURSOR_SETTINGS, 0, - /* no shift of the cursor HDL schedule */ - CURSOR0_DST_Y_OFFSET, 0, - /* used to shift the cursor chunk request deadline */ - CURSOR0_CHUNK_HDL_ADJUST, 3); - - return true; -} - -static enum cursor_pitch ippn10_get_cursor_pitch( - unsigned int pitch) -{ - enum cursor_pitch hw_pitch; - - switch (pitch) { - case 64: - hw_pitch = CURSOR_PITCH_64_PIXELS; - break; - case 128: - hw_pitch = CURSOR_PITCH_128_PIXELS; - break; - case 256: - hw_pitch = CURSOR_PITCH_256_PIXELS; - break; - default: - DC_ERR("Invalid cursor pitch of %d. " - "Only 64/128/256 is supported on DCN.\n", pitch); - hw_pitch = CURSOR_PITCH_64_PIXELS; - break; - } - return hw_pitch; -} - -static enum cursor_lines_per_chunk ippn10_get_lines_per_chunk( - unsigned int cur_width, - enum dc_cursor_color_format format) -{ - enum cursor_lines_per_chunk line_per_chunk; - - if (format == CURSOR_MODE_MONO) - /* impl B. expansion in CUR Buffer reader */ - line_per_chunk = CURSOR_LINE_PER_CHUNK_16; - else if (cur_width <= 32) - line_per_chunk = CURSOR_LINE_PER_CHUNK_16; - else if (cur_width <= 64) - line_per_chunk = CURSOR_LINE_PER_CHUNK_8; - else if (cur_width <= 128) - line_per_chunk = CURSOR_LINE_PER_CHUNK_4; - else - line_per_chunk = CURSOR_LINE_PER_CHUNK_2; - - return line_per_chunk; -} - -void hubp1_cursor_set_attributes( - struct hubp *hubp, - const struct dc_cursor_attributes *attr) -{ - struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); - enum cursor_pitch hw_pitch = ippn10_get_cursor_pitch(attr->pitch); - enum cursor_lines_per_chunk lpc = ippn10_get_lines_per_chunk( - attr->width, attr->color_format); - - hubp->curs_attr = *attr; - - REG_UPDATE(CURSOR_SURFACE_ADDRESS_HIGH, - CURSOR_SURFACE_ADDRESS_HIGH, attr->address.high_part); - REG_UPDATE(CURSOR_SURFACE_ADDRESS, - CURSOR_SURFACE_ADDRESS, attr->address.low_part); - - REG_UPDATE_2(CURSOR_SIZE, - CURSOR_WIDTH, attr->width, - CURSOR_HEIGHT, attr->height); - REG_UPDATE_3(CURSOR_CONTROL, - CURSOR_MODE, attr->color_format, - CURSOR_PITCH, hw_pitch, - CURSOR_LINES_PER_CHUNK, lpc); - ippn10_cursor_program_control(hubp1, - attr->attribute_flags.bits.INVERT_PIXEL_DATA, - attr->color_format); -} - -void hubp1_cursor_set_position( - struct hubp *hubp, - const struct dc_cursor_position *pos, - const struct dc_cursor_mi_param *param) -{ - struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); - int src_x_offset = pos->x - pos->x_hotspot - param->viewport_x_start; - uint32_t cur_en = pos->enable ? 1 : 0; - uint32_t dst_x_offset = (src_x_offset >= 0) ? src_x_offset : 0; - - /* - * Guard aganst cursor_set_position() from being called with invalid - * attributes - * - * TODO: Look at combining cursor_set_position() and - * cursor_set_attributes() into cursor_update() - */ - if (hubp->curs_attr.address.quad_part == 0) - return; - - dst_x_offset *= param->ref_clk_khz; - dst_x_offset /= param->pixel_clk_khz; - - ASSERT(param->h_scale_ratio.value); - - if (param->h_scale_ratio.value) - dst_x_offset = dal_fixed31_32_floor(dal_fixed31_32_div( - dal_fixed31_32_from_int(dst_x_offset), - param->h_scale_ratio)); - - if (src_x_offset >= (int)param->viewport_width) - cur_en = 0; /* not visible beyond right edge*/ - - if (src_x_offset + (int)hubp->curs_attr.width < 0) - cur_en = 0; /* not visible beyond left edge*/ - - if (cur_en && REG_READ(CURSOR_SURFACE_ADDRESS) == 0) - hubp1_cursor_set_attributes(hubp, &hubp->curs_attr); - REG_UPDATE(CURSOR_CONTROL, - CURSOR_ENABLE, cur_en); - - REG_SET_2(CURSOR_POSITION, 0, - CURSOR_X_POSITION, pos->x, - CURSOR_Y_POSITION, pos->y); - - REG_SET_2(CURSOR_HOT_SPOT, 0, - CURSOR_HOT_SPOT_X, pos->x_hotspot, - CURSOR_HOT_SPOT_Y, pos->y_hotspot); - - REG_SET(CURSOR_DST_OFFSET, 0, - CURSOR_DST_X_OFFSET, dst_x_offset); - /* TODO Handle surface pixel formats other than 4:4:4 */ -} - -static struct hubp_funcs dcn10_hubp_funcs = { - .hubp_program_surface_flip_and_addr = - hubp1_program_surface_flip_and_addr, - .hubp_program_surface_config = - hubp1_program_surface_config, - .hubp_is_flip_pending = hubp1_is_flip_pending, - .hubp_setup = hubp1_setup, - .hubp_set_vm_system_aperture_settings = hubp1_set_vm_system_aperture_settings, - .hubp_set_vm_context0_settings = hubp1_set_vm_context0_settings, - .set_blank = hubp1_set_blank, - .dcc_control = hubp1_dcc_control, - .mem_program_viewport = min_set_viewport, - .set_hubp_blank_en = hubp1_set_hubp_blank_en, - .set_cursor_attributes = hubp1_cursor_set_attributes, - .set_cursor_position = hubp1_cursor_set_position, -}; - -/*****************************************/ -/* Constructor, Destructor */ -/*****************************************/ - -void dcn10_hubp_construct( - struct dcn10_hubp *hubp1, - struct dc_context *ctx, - uint32_t inst, - const struct dcn_mi_registers *mi_regs, - const struct dcn_mi_shift *mi_shift, - const struct dcn_mi_mask *mi_mask) -{ - hubp1->base.funcs = &dcn10_hubp_funcs; - hubp1->base.ctx = ctx; - hubp1->mi_regs = mi_regs; - hubp1->mi_shift = mi_shift; - hubp1->mi_mask = mi_mask; - hubp1->base.inst = inst; - hubp1->base.opp_id = 0xf; - hubp1->base.mpcc_id = 0xf; -} - - diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h deleted file mode 100644 index 66db453c801b..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h +++ /dev/null @@ -1,683 +0,0 @@ -/* Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DC_MEM_INPUT_DCN10_H__ -#define __DC_MEM_INPUT_DCN10_H__ - -#include "hubp.h" - -#define TO_DCN10_HUBP(hubp)\ - container_of(hubp, struct dcn10_hubp, base) - -#define MI_REG_LIST_DCN(id)\ - SRI(DCHUBP_CNTL, HUBP, id),\ - SRI(HUBPREQ_DEBUG_DB, HUBP, id),\ - SRI(DCSURF_ADDR_CONFIG, HUBP, id),\ - SRI(DCSURF_TILING_CONFIG, HUBP, id),\ - SRI(DCSURF_SURFACE_PITCH, HUBPREQ, id),\ - SRI(DCSURF_SURFACE_PITCH_C, HUBPREQ, id),\ - SRI(DCSURF_SURFACE_CONFIG, HUBP, id),\ - SRI(DCSURF_FLIP_CONTROL, HUBPREQ, id),\ - SRI(DCSURF_PRI_VIEWPORT_DIMENSION, HUBP, id), \ - SRI(DCSURF_PRI_VIEWPORT_START, HUBP, id), \ - SRI(DCSURF_SEC_VIEWPORT_DIMENSION, HUBP, id), \ - SRI(DCSURF_SEC_VIEWPORT_START, HUBP, id), \ - SRI(DCSURF_PRI_VIEWPORT_DIMENSION_C, HUBP, id), \ - SRI(DCSURF_PRI_VIEWPORT_START_C, HUBP, id), \ - SRI(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, HUBPREQ, id),\ - SRI(DCSURF_PRIMARY_SURFACE_ADDRESS, HUBPREQ, id),\ - SRI(DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH, HUBPREQ, id),\ - SRI(DCSURF_SECONDARY_SURFACE_ADDRESS, HUBPREQ, id),\ - SRI(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, HUBPREQ, id),\ - SRI(DCSURF_PRIMARY_META_SURFACE_ADDRESS, HUBPREQ, id),\ - SRI(DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH, HUBPREQ, id),\ - SRI(DCSURF_SECONDARY_META_SURFACE_ADDRESS, HUBPREQ, id),\ - SRI(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C, HUBPREQ, id),\ - SRI(DCSURF_PRIMARY_SURFACE_ADDRESS_C, HUBPREQ, id),\ - SRI(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C, HUBPREQ, id),\ - SRI(DCSURF_PRIMARY_META_SURFACE_ADDRESS_C, HUBPREQ, id),\ - SRI(DCSURF_SURFACE_INUSE, HUBPREQ, id),\ - SRI(DCSURF_SURFACE_INUSE_HIGH, HUBPREQ, id),\ - SRI(DCSURF_SURFACE_INUSE_C, HUBPREQ, id),\ - SRI(DCSURF_SURFACE_INUSE_HIGH_C, HUBPREQ, id),\ - SRI(DCSURF_SURFACE_EARLIEST_INUSE, HUBPREQ, id),\ - SRI(DCSURF_SURFACE_EARLIEST_INUSE_HIGH, HUBPREQ, id),\ - SRI(DCSURF_SURFACE_EARLIEST_INUSE_C, HUBPREQ, id),\ - SRI(DCSURF_SURFACE_EARLIEST_INUSE_HIGH_C, HUBPREQ, id),\ - SRI(DCSURF_SURFACE_CONTROL, HUBPREQ, id),\ - SRI(HUBPRET_CONTROL, HUBPRET, id),\ - SRI(DCN_EXPANSION_MODE, HUBPREQ, id),\ - SRI(DCHUBP_REQ_SIZE_CONFIG, HUBP, id),\ - SRI(DCHUBP_REQ_SIZE_CONFIG_C, HUBP, id),\ - SRI(BLANK_OFFSET_0, HUBPREQ, id),\ - SRI(BLANK_OFFSET_1, HUBPREQ, id),\ - SRI(DST_DIMENSIONS, HUBPREQ, id),\ - SRI(DST_AFTER_SCALER, HUBPREQ, id),\ - SRI(VBLANK_PARAMETERS_0, HUBPREQ, id),\ - SRI(REF_FREQ_TO_PIX_FREQ, HUBPREQ, id),\ - SRI(VBLANK_PARAMETERS_1, HUBPREQ, id),\ - SRI(VBLANK_PARAMETERS_3, HUBPREQ, id),\ - SRI(NOM_PARAMETERS_0, HUBPREQ, id),\ - SRI(NOM_PARAMETERS_1, HUBPREQ, id),\ - SRI(NOM_PARAMETERS_4, HUBPREQ, id),\ - SRI(NOM_PARAMETERS_5, HUBPREQ, id),\ - SRI(PER_LINE_DELIVERY_PRE, HUBPREQ, id),\ - SRI(PER_LINE_DELIVERY, HUBPREQ, id),\ - SRI(VBLANK_PARAMETERS_2, HUBPREQ, id),\ - SRI(VBLANK_PARAMETERS_4, HUBPREQ, id),\ - SRI(NOM_PARAMETERS_2, HUBPREQ, id),\ - SRI(NOM_PARAMETERS_3, HUBPREQ, id),\ - SRI(NOM_PARAMETERS_6, HUBPREQ, id),\ - SRI(NOM_PARAMETERS_7, HUBPREQ, id),\ - SRI(DCN_TTU_QOS_WM, HUBPREQ, id),\ - SRI(DCN_GLOBAL_TTU_CNTL, HUBPREQ, id),\ - SRI(DCN_SURF0_TTU_CNTL0, HUBPREQ, id),\ - SRI(DCN_SURF0_TTU_CNTL1, HUBPREQ, id),\ - SRI(DCN_SURF1_TTU_CNTL0, HUBPREQ, id),\ - SRI(DCN_SURF1_TTU_CNTL1, HUBPREQ, id),\ - SRI(DCN_VM_MX_L1_TLB_CNTL, HUBPREQ, id) - -#define MI_REG_LIST_DCN10(id)\ - MI_REG_LIST_DCN(id),\ - SRI(PREFETCH_SETTINS, HUBPREQ, id),\ - SRI(PREFETCH_SETTINS_C, HUBPREQ, id),\ - SRI(DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, HUBPREQ, id),\ - SRI(DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB, HUBPREQ, id),\ - SRI(DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB, HUBPREQ, id),\ - SRI(DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_LSB, HUBPREQ, id),\ - SRI(DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB, HUBPREQ, id),\ - SRI(DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB, HUBPREQ, id),\ - SRI(DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, HUBPREQ, id),\ - SRI(DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, HUBPREQ, id),\ - SRI(DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, HUBPREQ, id),\ - SRI(DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, HUBPREQ, id),\ - SRI(DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, HUBPREQ, id),\ - SRI(DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, HUBPREQ, id),\ - SRI(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, HUBPREQ, id),\ - SRI(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, HUBPREQ, id),\ - SR(DCHUBBUB_SDPIF_FB_BASE),\ - SR(DCHUBBUB_SDPIF_FB_OFFSET),\ - SRI(CURSOR_SETTINS, HUBPREQ, id), \ - SRI(CURSOR_SURFACE_ADDRESS_HIGH, CURSOR, id), \ - SRI(CURSOR_SURFACE_ADDRESS, CURSOR, id), \ - SRI(CURSOR_SIZE, CURSOR, id), \ - SRI(CURSOR_CONTROL, CURSOR, id), \ - SRI(CURSOR_POSITION, CURSOR, id), \ - SRI(CURSOR_HOT_SPOT, CURSOR, id), \ - SRI(CURSOR_DST_OFFSET, CURSOR, id) - - - -struct dcn_mi_registers { - uint32_t DCHUBP_CNTL; - uint32_t HUBPREQ_DEBUG_DB; - uint32_t DCSURF_ADDR_CONFIG; - uint32_t DCSURF_TILING_CONFIG; - uint32_t DCSURF_SURFACE_PITCH; - uint32_t DCSURF_SURFACE_PITCH_C; - uint32_t DCSURF_SURFACE_CONFIG; - uint32_t DCSURF_FLIP_CONTROL; - uint32_t DCSURF_PRI_VIEWPORT_DIMENSION; - uint32_t DCSURF_PRI_VIEWPORT_START; - uint32_t DCSURF_SEC_VIEWPORT_DIMENSION; - uint32_t DCSURF_SEC_VIEWPORT_START; - uint32_t DCSURF_PRI_VIEWPORT_DIMENSION_C; - uint32_t DCSURF_PRI_VIEWPORT_START_C; - uint32_t DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH; - uint32_t DCSURF_PRIMARY_SURFACE_ADDRESS; - uint32_t DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH; - uint32_t DCSURF_SECONDARY_SURFACE_ADDRESS; - uint32_t DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH; - uint32_t DCSURF_PRIMARY_META_SURFACE_ADDRESS; - uint32_t DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH; - uint32_t DCSURF_SECONDARY_META_SURFACE_ADDRESS; - uint32_t DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C; - uint32_t DCSURF_PRIMARY_SURFACE_ADDRESS_C; - uint32_t DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C; - uint32_t DCSURF_PRIMARY_META_SURFACE_ADDRESS_C; - uint32_t DCSURF_SURFACE_INUSE; - uint32_t DCSURF_SURFACE_INUSE_HIGH; - uint32_t DCSURF_SURFACE_INUSE_C; - uint32_t DCSURF_SURFACE_INUSE_HIGH_C; - uint32_t DCSURF_SURFACE_EARLIEST_INUSE; - uint32_t DCSURF_SURFACE_EARLIEST_INUSE_HIGH; - uint32_t DCSURF_SURFACE_EARLIEST_INUSE_C; - uint32_t DCSURF_SURFACE_EARLIEST_INUSE_HIGH_C; - uint32_t DCSURF_SURFACE_CONTROL; - uint32_t HUBPRET_CONTROL; - uint32_t DCN_EXPANSION_MODE; - uint32_t DCHUBP_REQ_SIZE_CONFIG; - uint32_t DCHUBP_REQ_SIZE_CONFIG_C; - uint32_t BLANK_OFFSET_0; - uint32_t BLANK_OFFSET_1; - uint32_t DST_DIMENSIONS; - uint32_t DST_AFTER_SCALER; - uint32_t PREFETCH_SETTINS; - uint32_t PREFETCH_SETTINGS; - uint32_t VBLANK_PARAMETERS_0; - uint32_t REF_FREQ_TO_PIX_FREQ; - uint32_t VBLANK_PARAMETERS_1; - uint32_t VBLANK_PARAMETERS_3; - uint32_t NOM_PARAMETERS_0; - uint32_t NOM_PARAMETERS_1; - uint32_t NOM_PARAMETERS_4; - uint32_t NOM_PARAMETERS_5; - uint32_t PER_LINE_DELIVERY_PRE; - uint32_t PER_LINE_DELIVERY; - uint32_t PREFETCH_SETTINS_C; - uint32_t PREFETCH_SETTINGS_C; - uint32_t VBLANK_PARAMETERS_2; - uint32_t VBLANK_PARAMETERS_4; - uint32_t NOM_PARAMETERS_2; - uint32_t NOM_PARAMETERS_3; - uint32_t NOM_PARAMETERS_6; - uint32_t NOM_PARAMETERS_7; - uint32_t DCN_TTU_QOS_WM; - uint32_t DCN_GLOBAL_TTU_CNTL; - uint32_t DCN_SURF0_TTU_CNTL0; - uint32_t DCN_SURF0_TTU_CNTL1; - uint32_t DCN_SURF1_TTU_CNTL0; - uint32_t DCN_SURF1_TTU_CNTL1; - uint32_t DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB; - uint32_t DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB; - uint32_t DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB; - uint32_t DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_LSB; - uint32_t DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB; - uint32_t DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB; - uint32_t DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB; - uint32_t DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB; - uint32_t DCN_VM_MX_L1_TLB_CNTL; - uint32_t DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB; - uint32_t DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB; - uint32_t DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB; - uint32_t DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB; - uint32_t DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB; - uint32_t DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB; - uint32_t DCN_VM_SYSTEM_APERTURE_LOW_ADDR; - uint32_t DCN_VM_SYSTEM_APERTURE_HIGH_ADDR; - uint32_t DCHUBBUB_SDPIF_FB_BASE; - uint32_t DCHUBBUB_SDPIF_FB_OFFSET; - uint32_t DCN_VM_FB_LOCATION_TOP; - uint32_t DCN_VM_FB_LOCATION_BASE; - uint32_t DCN_VM_FB_OFFSET; - uint32_t DCN_VM_AGP_BASE; - uint32_t DCN_VM_AGP_BOT; - uint32_t DCN_VM_AGP_TOP; - uint32_t CURSOR_SETTINS; - uint32_t CURSOR_SETTINGS; - uint32_t CURSOR_SURFACE_ADDRESS_HIGH; - uint32_t CURSOR_SURFACE_ADDRESS; - uint32_t CURSOR_SIZE; - uint32_t CURSOR_CONTROL; - uint32_t CURSOR_POSITION; - uint32_t CURSOR_HOT_SPOT; - uint32_t CURSOR_DST_OFFSET; -}; - -#define MI_SF(reg_name, field_name, post_fix)\ - .field_name = reg_name ## __ ## field_name ## post_fix - -#define MI_MASK_SH_LIST_DCN(mask_sh)\ - MI_SF(HUBP0_DCHUBP_CNTL, HUBP_BLANK_EN, mask_sh),\ - MI_SF(HUBP0_DCHUBP_CNTL, HUBP_TTU_DISABLE, mask_sh),\ - MI_SF(HUBP0_DCHUBP_CNTL, HUBP_UNDERFLOW_STATUS, mask_sh),\ - MI_SF(HUBP0_DCHUBP_CNTL, HUBP_NO_OUTSTANDING_REQ, mask_sh),\ - MI_SF(HUBP0_DCSURF_ADDR_CONFIG, NUM_PIPES, mask_sh),\ - MI_SF(HUBP0_DCSURF_ADDR_CONFIG, NUM_BANKS, mask_sh),\ - MI_SF(HUBP0_DCSURF_ADDR_CONFIG, PIPE_INTERLEAVE, mask_sh),\ - MI_SF(HUBP0_DCSURF_ADDR_CONFIG, NUM_SE, mask_sh),\ - MI_SF(HUBP0_DCSURF_ADDR_CONFIG, NUM_RB_PER_SE, mask_sh),\ - MI_SF(HUBP0_DCSURF_ADDR_CONFIG, MAX_COMPRESSED_FRAGS, mask_sh),\ - MI_SF(HUBP0_DCSURF_TILING_CONFIG, SW_MODE, mask_sh),\ - MI_SF(HUBP0_DCSURF_TILING_CONFIG, META_LINEAR, mask_sh),\ - MI_SF(HUBP0_DCSURF_TILING_CONFIG, RB_ALIGNED, mask_sh),\ - MI_SF(HUBP0_DCSURF_TILING_CONFIG, PIPE_ALIGNED, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_SURFACE_PITCH, PITCH, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_SURFACE_PITCH, META_PITCH, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_SURFACE_PITCH_C, PITCH_C, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_SURFACE_PITCH_C, META_PITCH_C, mask_sh),\ - MI_SF(HUBP0_DCSURF_SURFACE_CONFIG, ROTATION_ANGLE, mask_sh),\ - MI_SF(HUBP0_DCSURF_SURFACE_CONFIG, H_MIRROR_EN, mask_sh),\ - MI_SF(HUBP0_DCSURF_SURFACE_CONFIG, SURFACE_PIXEL_FORMAT, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_FLIP_CONTROL, SURFACE_FLIP_TYPE, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_FLIP_CONTROL, SURFACE_FLIP_PENDING, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_FLIP_CONTROL, SURFACE_UPDATE_LOCK, mask_sh),\ - MI_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION, PRI_VIEWPORT_WIDTH, mask_sh),\ - MI_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION, PRI_VIEWPORT_HEIGHT, mask_sh),\ - MI_SF(HUBP0_DCSURF_PRI_VIEWPORT_START, PRI_VIEWPORT_X_START, mask_sh),\ - MI_SF(HUBP0_DCSURF_PRI_VIEWPORT_START, PRI_VIEWPORT_Y_START, mask_sh),\ - MI_SF(HUBP0_DCSURF_SEC_VIEWPORT_DIMENSION, SEC_VIEWPORT_WIDTH, mask_sh),\ - MI_SF(HUBP0_DCSURF_SEC_VIEWPORT_DIMENSION, SEC_VIEWPORT_HEIGHT, mask_sh),\ - MI_SF(HUBP0_DCSURF_SEC_VIEWPORT_START, SEC_VIEWPORT_X_START, mask_sh),\ - MI_SF(HUBP0_DCSURF_SEC_VIEWPORT_START, SEC_VIEWPORT_Y_START, mask_sh),\ - MI_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION_C, PRI_VIEWPORT_WIDTH_C, mask_sh),\ - MI_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION_C, PRI_VIEWPORT_HEIGHT_C, mask_sh),\ - MI_SF(HUBP0_DCSURF_PRI_VIEWPORT_START_C, PRI_VIEWPORT_X_START_C, mask_sh),\ - MI_SF(HUBP0_DCSURF_PRI_VIEWPORT_START_C, PRI_VIEWPORT_Y_START_C, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, PRIMARY_SURFACE_ADDRESS_HIGH, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_PRIMARY_SURFACE_ADDRESS, PRIMARY_SURFACE_ADDRESS, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH, SECONDARY_SURFACE_ADDRESS_HIGH, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_SECONDARY_SURFACE_ADDRESS, SECONDARY_SURFACE_ADDRESS, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, PRIMARY_META_SURFACE_ADDRESS_HIGH, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_PRIMARY_META_SURFACE_ADDRESS, PRIMARY_META_SURFACE_ADDRESS, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH, SECONDARY_META_SURFACE_ADDRESS_HIGH, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_SECONDARY_META_SURFACE_ADDRESS, SECONDARY_META_SURFACE_ADDRESS, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C, PRIMARY_SURFACE_ADDRESS_HIGH_C, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_PRIMARY_SURFACE_ADDRESS_C, PRIMARY_SURFACE_ADDRESS_C, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C, PRIMARY_META_SURFACE_ADDRESS_HIGH_C, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_PRIMARY_META_SURFACE_ADDRESS_C, PRIMARY_META_SURFACE_ADDRESS_C, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_SURFACE_INUSE, SURFACE_INUSE_ADDRESS, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_SURFACE_INUSE_HIGH, SURFACE_INUSE_ADDRESS_HIGH, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_SURFACE_INUSE_C, SURFACE_INUSE_ADDRESS_C, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_SURFACE_INUSE_HIGH_C, SURFACE_INUSE_ADDRESS_HIGH_C, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_SURFACE_EARLIEST_INUSE, SURFACE_EARLIEST_INUSE_ADDRESS, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_SURFACE_EARLIEST_INUSE_HIGH, SURFACE_EARLIEST_INUSE_ADDRESS_HIGH, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_SURFACE_EARLIEST_INUSE_C, SURFACE_EARLIEST_INUSE_ADDRESS_C, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_SURFACE_EARLIEST_INUSE_HIGH_C, SURFACE_EARLIEST_INUSE_ADDRESS_HIGH_C, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, PRIMARY_SURFACE_TMZ, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, PRIMARY_SURFACE_DCC_EN, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, PRIMARY_SURFACE_DCC_IND_64B_BLK, mask_sh),\ - MI_SF(HUBPRET0_HUBPRET_CONTROL, DET_BUF_PLANE1_BASE_ADDRESS, mask_sh),\ - MI_SF(HUBPRET0_HUBPRET_CONTROL, CROSSBAR_SRC_CB_B, mask_sh),\ - MI_SF(HUBPRET0_HUBPRET_CONTROL, CROSSBAR_SRC_CR_R, mask_sh),\ - MI_SF(HUBPREQ0_DCN_EXPANSION_MODE, DRQ_EXPANSION_MODE, mask_sh),\ - MI_SF(HUBPREQ0_DCN_EXPANSION_MODE, PRQ_EXPANSION_MODE, mask_sh),\ - MI_SF(HUBPREQ0_DCN_EXPANSION_MODE, MRQ_EXPANSION_MODE, mask_sh),\ - MI_SF(HUBPREQ0_DCN_EXPANSION_MODE, CRQ_EXPANSION_MODE, mask_sh),\ - MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, CHUNK_SIZE, mask_sh),\ - MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, MIN_CHUNK_SIZE, mask_sh),\ - MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, META_CHUNK_SIZE, mask_sh),\ - MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, MIN_META_CHUNK_SIZE, mask_sh),\ - MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, DPTE_GROUP_SIZE, mask_sh),\ - MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, MPTE_GROUP_SIZE, mask_sh),\ - MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, SWATH_HEIGHT, mask_sh),\ - MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, PTE_ROW_HEIGHT_LINEAR, mask_sh),\ - MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, CHUNK_SIZE_C, mask_sh),\ - MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, MIN_CHUNK_SIZE_C, mask_sh),\ - MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, META_CHUNK_SIZE_C, mask_sh),\ - MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, MIN_META_CHUNK_SIZE_C, mask_sh),\ - MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, DPTE_GROUP_SIZE_C, mask_sh),\ - MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, MPTE_GROUP_SIZE_C, mask_sh),\ - MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, SWATH_HEIGHT_C, mask_sh),\ - MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, PTE_ROW_HEIGHT_LINEAR_C, mask_sh),\ - MI_SF(HUBPREQ0_BLANK_OFFSET_0, REFCYC_H_BLANK_END, mask_sh),\ - MI_SF(HUBPREQ0_BLANK_OFFSET_0, DLG_V_BLANK_END, mask_sh),\ - MI_SF(HUBPREQ0_BLANK_OFFSET_1, MIN_DST_Y_NEXT_START, mask_sh),\ - MI_SF(HUBPREQ0_DST_DIMENSIONS, REFCYC_PER_HTOTAL, mask_sh),\ - MI_SF(HUBPREQ0_DST_AFTER_SCALER, REFCYC_X_AFTER_SCALER, mask_sh),\ - MI_SF(HUBPREQ0_DST_AFTER_SCALER, DST_Y_AFTER_SCALER, mask_sh),\ - MI_SF(HUBPREQ0_VBLANK_PARAMETERS_0, DST_Y_PER_VM_VBLANK, mask_sh),\ - MI_SF(HUBPREQ0_VBLANK_PARAMETERS_0, DST_Y_PER_ROW_VBLANK, mask_sh),\ - MI_SF(HUBPREQ0_REF_FREQ_TO_PIX_FREQ, REF_FREQ_TO_PIX_FREQ, mask_sh),\ - MI_SF(HUBPREQ0_VBLANK_PARAMETERS_1, REFCYC_PER_PTE_GROUP_VBLANK_L, mask_sh),\ - MI_SF(HUBPREQ0_VBLANK_PARAMETERS_3, REFCYC_PER_META_CHUNK_VBLANK_L, mask_sh),\ - MI_SF(HUBPREQ0_NOM_PARAMETERS_0, DST_Y_PER_PTE_ROW_NOM_L, mask_sh),\ - MI_SF(HUBPREQ0_NOM_PARAMETERS_1, REFCYC_PER_PTE_GROUP_NOM_L, mask_sh),\ - MI_SF(HUBPREQ0_NOM_PARAMETERS_4, DST_Y_PER_META_ROW_NOM_L, mask_sh),\ - MI_SF(HUBPREQ0_NOM_PARAMETERS_5, REFCYC_PER_META_CHUNK_NOM_L, mask_sh),\ - MI_SF(HUBPREQ0_PER_LINE_DELIVERY_PRE, REFCYC_PER_LINE_DELIVERY_PRE_L, mask_sh),\ - MI_SF(HUBPREQ0_PER_LINE_DELIVERY_PRE, REFCYC_PER_LINE_DELIVERY_PRE_C, mask_sh),\ - MI_SF(HUBPREQ0_PER_LINE_DELIVERY, REFCYC_PER_LINE_DELIVERY_L, mask_sh),\ - MI_SF(HUBPREQ0_PER_LINE_DELIVERY, REFCYC_PER_LINE_DELIVERY_C, mask_sh),\ - MI_SF(HUBPREQ0_VBLANK_PARAMETERS_2, REFCYC_PER_PTE_GROUP_VBLANK_C, mask_sh),\ - MI_SF(HUBPREQ0_VBLANK_PARAMETERS_4, REFCYC_PER_META_CHUNK_VBLANK_C, mask_sh),\ - MI_SF(HUBPREQ0_NOM_PARAMETERS_2, DST_Y_PER_PTE_ROW_NOM_C, mask_sh),\ - MI_SF(HUBPREQ0_NOM_PARAMETERS_3, REFCYC_PER_PTE_GROUP_NOM_C, mask_sh),\ - MI_SF(HUBPREQ0_NOM_PARAMETERS_6, DST_Y_PER_META_ROW_NOM_C, mask_sh),\ - MI_SF(HUBPREQ0_NOM_PARAMETERS_7, REFCYC_PER_META_CHUNK_NOM_C, mask_sh),\ - MI_SF(HUBPREQ0_DCN_TTU_QOS_WM, QoS_LEVEL_LOW_WM, mask_sh),\ - MI_SF(HUBPREQ0_DCN_TTU_QOS_WM, QoS_LEVEL_HIGH_WM, mask_sh),\ - MI_SF(HUBPREQ0_DCN_GLOBAL_TTU_CNTL, MIN_TTU_VBLANK, mask_sh),\ - MI_SF(HUBPREQ0_DCN_GLOBAL_TTU_CNTL, QoS_LEVEL_FLIP, mask_sh),\ - MI_SF(HUBPREQ0_DCN_SURF0_TTU_CNTL0, REFCYC_PER_REQ_DELIVERY, mask_sh),\ - MI_SF(HUBPREQ0_DCN_SURF0_TTU_CNTL0, QoS_LEVEL_FIXED, mask_sh),\ - MI_SF(HUBPREQ0_DCN_SURF0_TTU_CNTL0, QoS_RAMP_DISABLE, mask_sh),\ - MI_SF(HUBPREQ0_DCN_SURF0_TTU_CNTL1, REFCYC_PER_REQ_DELIVERY_PRE, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_MX_L1_TLB_CNTL, ENABLE_L1_TLB, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_MX_L1_TLB_CNTL, SYSTEM_ACCESS_MODE, mask_sh) - -#define MI_MASK_SH_LIST_DCN10(mask_sh)\ - MI_MASK_SH_LIST_DCN(mask_sh),\ - MI_SF(HUBPREQ0_PREFETCH_SETTINS, DST_Y_PREFETCH, mask_sh),\ - MI_SF(HUBPREQ0_PREFETCH_SETTINS, VRATIO_PREFETCH, mask_sh),\ - MI_SF(HUBPREQ0_PREFETCH_SETTINS_C, VRATIO_PREFETCH_C, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB, VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB, VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_LSB, VM_CONTEXT0_PAGE_TABLE_START_ADDR_LSB, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB, VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB, VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_SYSTEM, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, MC_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, MC_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, MC_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, MC_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, mask_sh),\ - MI_SF(DCHUBBUB_SDPIF_FB_BASE, SDPIF_FB_BASE, mask_sh),\ - MI_SF(DCHUBBUB_SDPIF_FB_OFFSET, SDPIF_FB_OFFSET, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, MC_VM_SYSTEM_APERTURE_DEFAULT_SYSTEM, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, mask_sh),\ - MI_SF(HUBPREQ0_CURSOR_SETTINS, CURSOR0_DST_Y_OFFSET, mask_sh), \ - MI_SF(HUBPREQ0_CURSOR_SETTINS, CURSOR0_CHUNK_HDL_ADJUST, mask_sh), \ - MI_SF(CURSOR0_CURSOR_SURFACE_ADDRESS_HIGH, CURSOR_SURFACE_ADDRESS_HIGH, mask_sh), \ - MI_SF(CURSOR0_CURSOR_SURFACE_ADDRESS, CURSOR_SURFACE_ADDRESS, mask_sh), \ - MI_SF(CURSOR0_CURSOR_SIZE, CURSOR_WIDTH, mask_sh), \ - MI_SF(CURSOR0_CURSOR_SIZE, CURSOR_HEIGHT, mask_sh), \ - MI_SF(CURSOR0_CURSOR_CONTROL, CURSOR_MODE, mask_sh), \ - MI_SF(CURSOR0_CURSOR_CONTROL, CURSOR_2X_MAGNIFY, mask_sh), \ - MI_SF(CURSOR0_CURSOR_CONTROL, CURSOR_PITCH, mask_sh), \ - MI_SF(CURSOR0_CURSOR_CONTROL, CURSOR_LINES_PER_CHUNK, mask_sh), \ - MI_SF(CURSOR0_CURSOR_CONTROL, CURSOR_ENABLE, mask_sh), \ - MI_SF(CURSOR0_CURSOR_POSITION, CURSOR_X_POSITION, mask_sh), \ - MI_SF(CURSOR0_CURSOR_POSITION, CURSOR_Y_POSITION, mask_sh), \ - MI_SF(CURSOR0_CURSOR_HOT_SPOT, CURSOR_HOT_SPOT_X, mask_sh), \ - MI_SF(CURSOR0_CURSOR_HOT_SPOT, CURSOR_HOT_SPOT_Y, mask_sh), \ - MI_SF(CURSOR0_CURSOR_DST_OFFSET, CURSOR_DST_X_OFFSET, mask_sh) - -#define DCN_MI_REG_FIELD_LIST(type) \ - type HUBP_BLANK_EN;\ - type HUBP_TTU_DISABLE;\ - type HUBP_NO_OUTSTANDING_REQ;\ - type HUBP_UNDERFLOW_STATUS;\ - type NUM_PIPES;\ - type NUM_BANKS;\ - type PIPE_INTERLEAVE;\ - type NUM_SE;\ - type NUM_RB_PER_SE;\ - type MAX_COMPRESSED_FRAGS;\ - type SW_MODE;\ - type META_LINEAR;\ - type RB_ALIGNED;\ - type PIPE_ALIGNED;\ - type PITCH;\ - type META_PITCH;\ - type PITCH_C;\ - type META_PITCH_C;\ - type ROTATION_ANGLE;\ - type H_MIRROR_EN;\ - type SURFACE_PIXEL_FORMAT;\ - type SURFACE_FLIP_TYPE;\ - type SURFACE_UPDATE_LOCK;\ - type SURFACE_FLIP_PENDING;\ - type PRI_VIEWPORT_WIDTH; \ - type PRI_VIEWPORT_HEIGHT; \ - type PRI_VIEWPORT_X_START; \ - type PRI_VIEWPORT_Y_START; \ - type SEC_VIEWPORT_WIDTH; \ - type SEC_VIEWPORT_HEIGHT; \ - type SEC_VIEWPORT_X_START; \ - type SEC_VIEWPORT_Y_START; \ - type PRI_VIEWPORT_WIDTH_C; \ - type PRI_VIEWPORT_HEIGHT_C; \ - type PRI_VIEWPORT_X_START_C; \ - type PRI_VIEWPORT_Y_START_C; \ - type PRIMARY_SURFACE_ADDRESS_HIGH;\ - type PRIMARY_SURFACE_ADDRESS;\ - type SECONDARY_SURFACE_ADDRESS_HIGH;\ - type SECONDARY_SURFACE_ADDRESS;\ - type PRIMARY_META_SURFACE_ADDRESS_HIGH;\ - type PRIMARY_META_SURFACE_ADDRESS;\ - type SECONDARY_META_SURFACE_ADDRESS_HIGH;\ - type SECONDARY_META_SURFACE_ADDRESS;\ - type PRIMARY_SURFACE_ADDRESS_HIGH_C;\ - type PRIMARY_SURFACE_ADDRESS_C;\ - type PRIMARY_META_SURFACE_ADDRESS_HIGH_C;\ - type PRIMARY_META_SURFACE_ADDRESS_C;\ - type SURFACE_INUSE_ADDRESS;\ - type SURFACE_INUSE_ADDRESS_HIGH;\ - type SURFACE_INUSE_ADDRESS_C;\ - type SURFACE_INUSE_ADDRESS_HIGH_C;\ - type SURFACE_EARLIEST_INUSE_ADDRESS;\ - type SURFACE_EARLIEST_INUSE_ADDRESS_HIGH;\ - type SURFACE_EARLIEST_INUSE_ADDRESS_C;\ - type SURFACE_EARLIEST_INUSE_ADDRESS_HIGH_C;\ - type PRIMARY_SURFACE_TMZ;\ - type PRIMARY_SURFACE_DCC_EN;\ - type PRIMARY_SURFACE_DCC_IND_64B_BLK;\ - type DET_BUF_PLANE1_BASE_ADDRESS;\ - type CROSSBAR_SRC_CB_B;\ - type CROSSBAR_SRC_CR_R;\ - type DRQ_EXPANSION_MODE;\ - type PRQ_EXPANSION_MODE;\ - type MRQ_EXPANSION_MODE;\ - type CRQ_EXPANSION_MODE;\ - type CHUNK_SIZE;\ - type MIN_CHUNK_SIZE;\ - type META_CHUNK_SIZE;\ - type MIN_META_CHUNK_SIZE;\ - type DPTE_GROUP_SIZE;\ - type MPTE_GROUP_SIZE;\ - type SWATH_HEIGHT;\ - type PTE_ROW_HEIGHT_LINEAR;\ - type CHUNK_SIZE_C;\ - type MIN_CHUNK_SIZE_C;\ - type META_CHUNK_SIZE_C;\ - type MIN_META_CHUNK_SIZE_C;\ - type DPTE_GROUP_SIZE_C;\ - type MPTE_GROUP_SIZE_C;\ - type SWATH_HEIGHT_C;\ - type PTE_ROW_HEIGHT_LINEAR_C;\ - type REFCYC_H_BLANK_END;\ - type DLG_V_BLANK_END;\ - type MIN_DST_Y_NEXT_START;\ - type REFCYC_PER_HTOTAL;\ - type REFCYC_X_AFTER_SCALER;\ - type DST_Y_AFTER_SCALER;\ - type DST_Y_PREFETCH;\ - type VRATIO_PREFETCH;\ - type DST_Y_PER_VM_VBLANK;\ - type DST_Y_PER_ROW_VBLANK;\ - type REF_FREQ_TO_PIX_FREQ;\ - type REFCYC_PER_PTE_GROUP_VBLANK_L;\ - type REFCYC_PER_META_CHUNK_VBLANK_L;\ - type DST_Y_PER_PTE_ROW_NOM_L;\ - type REFCYC_PER_PTE_GROUP_NOM_L;\ - type DST_Y_PER_META_ROW_NOM_L;\ - type REFCYC_PER_META_CHUNK_NOM_L;\ - type REFCYC_PER_LINE_DELIVERY_PRE_L;\ - type REFCYC_PER_LINE_DELIVERY_PRE_C;\ - type REFCYC_PER_LINE_DELIVERY_L;\ - type REFCYC_PER_LINE_DELIVERY_C;\ - type VRATIO_PREFETCH_C;\ - type REFCYC_PER_PTE_GROUP_VBLANK_C;\ - type REFCYC_PER_META_CHUNK_VBLANK_C;\ - type DST_Y_PER_PTE_ROW_NOM_C;\ - type REFCYC_PER_PTE_GROUP_NOM_C;\ - type DST_Y_PER_META_ROW_NOM_C;\ - type REFCYC_PER_META_CHUNK_NOM_C;\ - type QoS_LEVEL_LOW_WM;\ - type QoS_LEVEL_HIGH_WM;\ - type MIN_TTU_VBLANK;\ - type QoS_LEVEL_FLIP;\ - type REFCYC_PER_REQ_DELIVERY;\ - type QoS_LEVEL_FIXED;\ - type QoS_RAMP_DISABLE;\ - type REFCYC_PER_REQ_DELIVERY_PRE;\ - type VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB;\ - type VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB;\ - type VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB;\ - type VM_CONTEXT0_PAGE_TABLE_START_ADDR_LSB;\ - type VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB;\ - type VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB;\ - type VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB;\ - type VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_SYSTEM;\ - type VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB;\ - type ENABLE_L1_TLB;\ - type SYSTEM_ACCESS_MODE;\ - type MC_VM_SYSTEM_APERTURE_DEFAULT_SYSTEM;\ - type MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB;\ - type MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB;\ - type MC_VM_SYSTEM_APERTURE_LOW_ADDR_MSB;\ - type MC_VM_SYSTEM_APERTURE_LOW_ADDR_LSB;\ - type MC_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB;\ - type MC_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB;\ - type MC_VM_SYSTEM_APERTURE_LOW_ADDR;\ - type MC_VM_SYSTEM_APERTURE_HIGH_ADDR;\ - type SDPIF_FB_TOP;\ - type SDPIF_FB_BASE;\ - type SDPIF_FB_OFFSET;\ - type SDPIF_AGP_BASE;\ - type SDPIF_AGP_BOT;\ - type SDPIF_AGP_TOP;\ - type FB_TOP;\ - type FB_BASE;\ - type FB_OFFSET;\ - type AGP_BASE;\ - type AGP_BOT;\ - type AGP_TOP;\ - /* todo: get these from GVM instead of reading registers ourselves */\ - type PAGE_DIRECTORY_ENTRY_HI32;\ - type PAGE_DIRECTORY_ENTRY_LO32;\ - type LOGICAL_PAGE_NUMBER_HI4;\ - type LOGICAL_PAGE_NUMBER_LO32;\ - type PHYSICAL_PAGE_ADDR_HI4;\ - type PHYSICAL_PAGE_ADDR_LO32;\ - type PHYSICAL_PAGE_NUMBER_MSB;\ - type PHYSICAL_PAGE_NUMBER_LSB;\ - type LOGICAL_ADDR;\ - type CURSOR0_DST_Y_OFFSET; \ - type CURSOR0_CHUNK_HDL_ADJUST; \ - type CURSOR_SURFACE_ADDRESS_HIGH; \ - type CURSOR_SURFACE_ADDRESS; \ - type CURSOR_WIDTH; \ - type CURSOR_HEIGHT; \ - type CURSOR_MODE; \ - type CURSOR_2X_MAGNIFY; \ - type CURSOR_PITCH; \ - type CURSOR_LINES_PER_CHUNK; \ - type CURSOR_ENABLE; \ - type CURSOR_X_POSITION; \ - type CURSOR_Y_POSITION; \ - type CURSOR_HOT_SPOT_X; \ - type CURSOR_HOT_SPOT_Y; \ - type CURSOR_DST_X_OFFSET; \ - type OUTPUT_FP - -struct dcn_mi_shift { - DCN_MI_REG_FIELD_LIST(uint8_t); -}; - -struct dcn_mi_mask { - DCN_MI_REG_FIELD_LIST(uint32_t); -}; - -struct dcn10_hubp { - struct hubp base; - const struct dcn_mi_registers *mi_regs; - const struct dcn_mi_shift *mi_shift; - const struct dcn_mi_mask *mi_mask; -}; - -void hubp1_program_surface_config( - struct hubp *hubp, - enum surface_pixel_format format, - union dc_tiling_info *tiling_info, - union plane_size *plane_size, - enum dc_rotation_angle rotation, - struct dc_plane_dcc_param *dcc, - bool horizontal_mirror); - -void hubp1_program_deadline( - struct hubp *hubp, - struct _vcs_dpi_display_dlg_regs_st *dlg_attr, - struct _vcs_dpi_display_ttu_regs_st *ttu_attr); - -void hubp1_program_requestor( - struct hubp *hubp, - struct _vcs_dpi_display_rq_regs_st *rq_regs); - -void hubp1_program_pixel_format( - struct dcn10_hubp *hubp, - enum surface_pixel_format format); - -void hubp1_program_size_and_rotation( - struct dcn10_hubp *hubp, - enum dc_rotation_angle rotation, - enum surface_pixel_format format, - const union plane_size *plane_size, - struct dc_plane_dcc_param *dcc, - bool horizontal_mirror); - -void hubp1_program_tiling( - struct dcn10_hubp *hubp, - const union dc_tiling_info *info, - const enum surface_pixel_format pixel_format); - -void hubp1_dcc_control(struct hubp *hubp, - bool enable, - bool independent_64b_blks); - -bool hubp1_program_surface_flip_and_addr( - struct hubp *hubp, - const struct dc_plane_address *address, - bool flip_immediate); - -bool hubp1_is_flip_pending(struct hubp *hubp); - -void hubp1_cursor_set_attributes( - struct hubp *hubp, - const struct dc_cursor_attributes *attr); - -void hubp1_cursor_set_position( - struct hubp *hubp, - const struct dc_cursor_position *pos, - const struct dc_cursor_mi_param *param); - -void hubp1_set_blank(struct hubp *hubp, bool blank); - -void min_set_viewport(struct hubp *hubp, - const struct rect *viewport, - const struct rect *viewport_c); - -void dcn10_hubp_construct( - struct dcn10_hubp *hubp1, - struct dc_context *ctx, - uint32_t inst, - const struct dcn_mi_registers *mi_regs, - const struct dcn_mi_shift *mi_shift, - const struct dcn_mi_mask *mi_mask); - - -struct dcn_hubp_state { - uint32_t pixel_format; - uint32_t inuse_addr_hi; - uint32_t viewport_width; - uint32_t viewport_height; - uint32_t rotation_angle; - uint32_t h_mirror_en; - uint32_t sw_mode; - uint32_t dcc_en; - uint32_t blank_en; - uint32_t underflow_status; - uint32_t ttu_disable; - uint32_t min_ttu_vblank; - uint32_t qos_level_low_wm; - uint32_t qos_level_high_wm; -}; -void hubp1_read_state(struct dcn10_hubp *hubp1, - struct dcn_hubp_state *s); - -#endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 93edbba762e8..1da5105ed30a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -42,12 +42,12 @@ #include "dce/dce_stream_encoder.h" #include "dce/dce_clocks.h" #include "dce/dce_clock_source.h" -#include "dcn10/dcn10_mem_input.h" #include "dce/dce_audio.h" #include "dce/dce_hwseq.h" #include "../virtual/virtual_stream_encoder.h" #include "dce110/dce110_resource.h" #include "dce112/dce112_resource.h" +#include "dcn10_hubp.h" #include "vega10/soc15ip.h" -- cgit From 2938bbb646107d4e39bf850a5bc09385abd012e8 Mon Sep 17 00:00:00 2001 From: SivapiriyanKumarasamy Date: Wed, 4 Oct 2017 14:24:53 -0400 Subject: drm/amd/display: Pull transfer func defines into DC Signed-off-by: SivapiriyanKumarasamy Reviewed-by: Anthony Koo Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 38 +++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 6e9b21928d4f..c7b31adc736e 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -318,6 +318,38 @@ enum { TRANSFER_FUNC_POINTS = 1025 }; +// Moved here from color module for linux +enum color_transfer_func { + transfer_func_unknown, + transfer_func_srgb, + transfer_func_bt709, + transfer_func_pq2084, + transfer_func_pq2084_interim, + transfer_func_linear_0_1, + transfer_func_linear_0_125, + transfer_func_dolbyvision, + transfer_func_gamma_22, + transfer_func_gamma_26 +}; + +enum color_color_space { + color_space_unsupported, + color_space_srgb, + color_space_bt601, + color_space_bt709, + color_space_xv_ycc_bt601, + color_space_xv_ycc_bt709, + color_space_xr_rgb, + color_space_bt2020, + color_space_adobe, + color_space_dci_p3, + color_space_sc_rgb_ms_ref, + color_space_display_native, + color_space_app_ctrl, + color_space_dolby_vision, + color_space_custom_coordinates +}; + struct dc_hdr_static_metadata { /* display chromaticities and white point in units of 0.00001 */ unsigned int chromaticity_green_x; @@ -398,6 +430,12 @@ struct dc_plane_state { struct dc_gamma *gamma_correction; struct dc_transfer_func *in_transfer_func; + // sourceContentAttribute cache + bool is_source_input_valid; + struct dc_hdr_static_metadata source_input_mastering_info; + enum color_color_space source_input_color_space; + enum color_transfer_func source_input_tf; + enum dc_color_space color_space; enum surface_pixel_format format; enum dc_rotation_angle rotation; -- cgit From 80e80ec817f161560b4159608fb41bd289abede3 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Tue, 3 Oct 2017 13:53:51 -0400 Subject: drm/amd/display: Fix underscan not using proper scaling fix underscan not being set correctly Signed-off-by: Bhawanpreet Lakha Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 4df5bf750257..12aeb6d83f42 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1362,7 +1362,7 @@ void dc_commit_updates_for_stream(struct dc *dc, enum surface_update_type update_type; struct dc_state *context; struct dc_context *dc_ctx = dc->ctx; - int i; + int i, j; stream_status = dc_stream_get_status(stream); context = dc->current_state; @@ -1396,8 +1396,17 @@ void dc_commit_updates_for_stream(struct dc *dc, if (srf_updates[i].flip_addr) surface->address = srf_updates[i].flip_addr->address; - } + if (update_type >= UPDATE_TYPE_MED) { + for (j = 0; j < dc->res_pool->pipe_count; j++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; + + if (pipe_ctx->plane_state != surface) + continue; + resource_build_scaling_params(pipe_ctx); + } + } + } commit_planes_for_stream( dc, -- cgit From 8534575fed085a78a847f88fbc929d9c4a8c3255 Mon Sep 17 00:00:00 2001 From: Eric Bernstein Date: Thu, 5 Oct 2017 14:27:27 -0400 Subject: drm/amd/display: Expose some MPC functions for reuse Signed-off-by: Eric Bernstein Reviewed-by: Eric Bernstein Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c | 11 +++--- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h | 45 ++++++++++++++++------ .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 6 ++- drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h | 7 ++-- 4 files changed, 48 insertions(+), 21 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c index 334f072cea1d..76573e1f5b01 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c @@ -65,7 +65,7 @@ static void mpc10_set_bg_color( MPCC_BG_B_CB, bg_b_cb); } -static void mpc10_assert_idle_mpcc(struct mpc *mpc, int id) +void mpc10_assert_idle_mpcc(struct mpc *mpc, int id) { struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); @@ -116,7 +116,7 @@ static void mpc10_assert_mpcc_idle_before_connect(struct dcn10_mpc *mpc10, int i } } -static void mpc10_mpcc_remove( +void mpc10_mpcc_remove( struct mpc *mpc, struct mpc_tree_cfg *tree_cfg, int opp_id, @@ -265,7 +265,7 @@ static void mpc10_add_to_tree_cfg( tree_cfg->num_pipes++; } -static int mpc10_mpcc_add(struct mpc *mpc, struct mpcc_cfg *cfg) +int mpc10_mpcc_add(struct mpc *mpc, struct mpcc_cfg *cfg) { struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); int mpcc_id, z_idx; @@ -313,7 +313,7 @@ static int mpc10_mpcc_add(struct mpc *mpc, struct mpcc_cfg *cfg) return mpcc_id; } -static void mpc10_update_blend_mode( +void mpc10_update_blend_mode( struct mpc *mpc, struct mpcc_cfg *cfg) { @@ -339,8 +339,7 @@ const struct mpc_funcs dcn10_mpc_funcs = { .add = mpc10_mpcc_add, .remove = mpc10_mpcc_remove, .wait_for_idle = mpc10_assert_idle_mpcc, - .set_denorm = NULL, - .update_blend_mode = mpc10_update_blend_mode + .update_blend_mode = mpc10_update_blend_mode, }; void dcn10_mpc_construct(struct dcn10_mpc *mpc10, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h index 94f890a0ad40..683ce4aaa76e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h @@ -34,7 +34,6 @@ #define MAX_OPP 6 #define MPC_COMMON_REG_LIST_DCN1_0(inst) \ - SRII(MUX, MPC_OUT, inst),\ SRII(MPCC_TOP_SEL, MPCC, inst),\ SRII(MPCC_BOT_SEL, MPCC, inst),\ SRII(MPCC_CONTROL, MPCC, inst),\ @@ -45,17 +44,19 @@ SRII(MPCC_BG_B_CB, MPCC, inst),\ SRII(MPCC_BG_B_CB, MPCC, inst) -struct dcn_mpc_registers { - uint32_t MPCC_TOP_SEL[MAX_MPCC]; - uint32_t MPCC_BOT_SEL[MAX_MPCC]; - uint32_t MPCC_CONTROL[MAX_MPCC]; - uint32_t MPCC_STATUS[MAX_MPCC]; - uint32_t MPCC_OPP_ID[MAX_MPCC]; - uint32_t MPCC_BG_G_Y[MAX_MPCC]; - uint32_t MPCC_BG_R_CR[MAX_MPCC]; - uint32_t MPCC_BG_B_CB[MAX_MPCC]; +#define MPC_OUT_MUX_COMMON_REG_LIST_DCN1_0(inst) \ + SRII(MUX, MPC_OUT, inst) + +#define MPC_COMMON_REG_VARIABLE_LIST \ + uint32_t MPCC_TOP_SEL[MAX_MPCC]; \ + uint32_t MPCC_BOT_SEL[MAX_MPCC]; \ + uint32_t MPCC_CONTROL[MAX_MPCC]; \ + uint32_t MPCC_STATUS[MAX_MPCC]; \ + uint32_t MPCC_OPP_ID[MAX_MPCC]; \ + uint32_t MPCC_BG_G_Y[MAX_MPCC]; \ + uint32_t MPCC_BG_R_CR[MAX_MPCC]; \ + uint32_t MPCC_BG_B_CB[MAX_MPCC]; \ uint32_t MUX[MAX_OPP]; -}; #define MPC_COMMON_MASK_SH_LIST_DCN1_0(mask_sh)\ SF(MPCC0_MPCC_TOP_SEL, MPCC_TOP_SEL, mask_sh),\ @@ -87,6 +88,10 @@ struct dcn_mpc_registers { type MPCC_BG_B_CB;\ type MPC_OUT_MUX; +struct dcn_mpc_registers { + MPC_COMMON_REG_VARIABLE_LIST +}; + struct dcn_mpc_shift { MPC_REG_FIELD_LIST(uint8_t) }; @@ -112,4 +117,22 @@ void dcn10_mpc_construct(struct dcn10_mpc *mpcc10, const struct dcn_mpc_mask *mpc_mask, int num_mpcc); +int mpc10_mpcc_add( + struct mpc *mpc, + struct mpcc_cfg *cfg); + +void mpc10_mpcc_remove( + struct mpc *mpc, + struct mpc_tree_cfg *tree_cfg, + int opp_id, + int dpp_id); + +void mpc10_assert_idle_mpcc( + struct mpc *mpc, + int id); + +void mpc10_update_blend_mode( + struct mpc *mpc, + struct mpcc_cfg *cfg); + #endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 1da5105ed30a..4764590f9097 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -329,7 +329,11 @@ static const struct dcn_mpc_registers mpc_regs = { MPC_COMMON_REG_LIST_DCN1_0(0), MPC_COMMON_REG_LIST_DCN1_0(1), MPC_COMMON_REG_LIST_DCN1_0(2), - MPC_COMMON_REG_LIST_DCN1_0(3) + MPC_COMMON_REG_LIST_DCN1_0(3), + MPC_OUT_MUX_COMMON_REG_LIST_DCN1_0(0), + MPC_OUT_MUX_COMMON_REG_LIST_DCN1_0(1), + MPC_OUT_MUX_COMMON_REG_LIST_DCN1_0(2), + MPC_OUT_MUX_COMMON_REG_LIST_DCN1_0(3) }; static const struct dcn_mpc_shift mpc_shift = { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h index fb590f5353a0..d4188b2c0626 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h @@ -46,15 +46,16 @@ struct mpc { struct mpc_funcs { int (*add)(struct mpc *mpc, struct mpcc_cfg *cfg); + void (*remove)(struct mpc *mpc, struct mpc_tree_cfg *tree_cfg, int opp_id, int mpcc_inst); + void (*wait_for_idle)(struct mpc *mpc, int id); - void (*set_denorm)(struct mpc *mpc, - int opp_id, - enum dc_color_depth output_depth); + void (*update_blend_mode)(struct mpc *mpc, struct mpcc_cfg *cfg); + }; #endif -- cgit From be5a55dc3de9bc5764b3eb4ba6f743783584aa58 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Thu, 5 Oct 2017 13:32:29 -0400 Subject: drm/amd/display: change when to set tap_hardcode_coeff Set hardcode_coeff only when BOTH chroma and luma taps are more than 1 without this underscan with h or v set to 0 darkens the screen (either h or v set to 0, not both) Signed-off-by: Bhawanpreet Lakha Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') 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 830dbd5d4144..eda6c8010fb8 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 @@ -306,10 +306,10 @@ static void dpp_set_scl_filter( h_2tap_hardcode_coef_en = scl_data->taps.h_taps < 3 && scl_data->taps.h_taps_c < 3 - && (scl_data->taps.h_taps > 1 || scl_data->taps.h_taps_c > 1); + && (scl_data->taps.h_taps > 1 && scl_data->taps.h_taps_c > 1); v_2tap_hardcode_coef_en = scl_data->taps.v_taps < 3 && scl_data->taps.v_taps_c < 3 - && (scl_data->taps.v_taps > 1 || scl_data->taps.v_taps_c > 1); + && (scl_data->taps.v_taps > 1 && scl_data->taps.v_taps_c > 1); h_2tap_sharp_en = h_2tap_hardcode_coef_en && h_2tap_sharp_factor != 0; v_2tap_sharp_en = v_2tap_hardcode_coef_en && v_2tap_sharp_factor != 0; -- cgit From 3411eac1a144ac5ad5a7ab994645724130bb2996 Mon Sep 17 00:00:00 2001 From: Vitaly Prosyak Date: Thu, 5 Oct 2017 10:45:50 -0500 Subject: drm/amd/display: [RV] bug in cm programming When surface bigger then 10 bpc the output pixel does not match to the required value.Update CRC's. Signed-off-by: Vitaly Prosyak Reviewed-by: Jordan Lazare Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h | 6 +++++- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h index 4cf18a500dcd..c2e3ff883537 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h @@ -164,7 +164,8 @@ SRI(CM_IGAM_LUT_RW_CONTROL, CM, id), \ SRI(CM_IGAM_LUT_RW_INDEX, CM, id), \ SRI(CM_IGAM_LUT_SEQ_COLOR, CM, id), \ - SRI(CURSOR_CONTROL, CURSOR, id) + SRI(CURSOR_CONTROL, CURSOR, id), \ + SRI(CM_CMOUT_CONTROL, CM, id) #define TF_REG_LIST_SH_MASK_DCN(mask_sh)\ @@ -401,6 +402,7 @@ TF_SF(CM0_CM_CONTROL, CM_BYPASS_EN, mask_sh), \ TF_SF(CM0_CM_IGAM_LUT_SEQ_COLOR, CM_IGAM_LUT_SEQ_COLOR, mask_sh), \ TF_SF(CNVC_CFG0_FORMAT_CONTROL, OUTPUT_FP, mask_sh), \ + TF_SF(CM0_CM_CMOUT_CONTROL, CM_CMOUT_ROUND_TRUNC_MODE, mask_sh), \ TF_SF(CURSOR0_CURSOR_CONTROL, CURSOR_MODE, mask_sh), \ TF_SF(CURSOR0_CURSOR_CONTROL, CURSOR_PITCH, mask_sh), \ TF_SF(CURSOR0_CURSOR_CONTROL, CURSOR_LINES_PER_CHUNK, mask_sh), \ @@ -549,6 +551,7 @@ type CM_RGAM_RAMA_EXP_REGION33_LUT_OFFSET; \ type CM_RGAM_RAMA_EXP_REGION33_NUM_SEGMENTS; \ type CM_RGAM_LUT_MODE; \ + type CM_CMOUT_ROUND_TRUNC_MODE; \ type OBUF_BYPASS; \ type OBUF_H_2X_UPSCALE_EN; \ type CM_BLNDGAM_LUT_MODE; \ @@ -1081,6 +1084,7 @@ struct dcn_dpp_registers { uint32_t CM_RGAM_RAMA_REGION_0_1; uint32_t CM_RGAM_RAMA_REGION_32_33; uint32_t CM_RGAM_CONTROL; + uint32_t CM_CMOUT_CONTROL; uint32_t OBUF_CONTROL; uint32_t CM_BLNDGAM_LUT_WRITE_EN_MASK; uint32_t CM_BLNDGAM_CONTROL; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c index 61e2a8919e9c..f88fd2e2e0aa 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c @@ -602,7 +602,7 @@ static void ippn10_enable_cm_block( struct transform *xfm_base) { struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); - + REG_UPDATE(CM_CMOUT_CONTROL, CM_CMOUT_ROUND_TRUNC_MODE, 8); REG_UPDATE(CM_CONTROL, CM_BYPASS_EN, 0); } -- cgit From 886daac91d4c794fa76a0e5cf1101bdb329f3fe3 Mon Sep 17 00:00:00 2001 From: Jerry Zuo Date: Thu, 5 Oct 2017 15:37:46 -0400 Subject: drm/amd/display: Fix a logic defect in cursor move Regression caused by: Ib98354194d7 Need to check crtc->stream before updating cursor attributes and position. Signed-off-by: Jerry Zuo Reviewed-by: Roman Li Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') 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 8653453566b8..17fb636648f4 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3736,14 +3736,15 @@ static void handle_cursor_update(struct drm_plane *plane, attributes.pitch = attributes.width; - if (!dc_stream_set_cursor_attributes(crtc_state->stream, - &attributes)) - DRM_ERROR("DC failed to set cursor attributes\n"); + if (crtc_state->stream) { + if (!dc_stream_set_cursor_attributes(crtc_state->stream, + &attributes)) + DRM_ERROR("DC failed to set cursor attributes\n"); - if (crtc_state->stream) if (!dc_stream_set_cursor_position(crtc_state->stream, &position)) DRM_ERROR("DC failed to set cursor position\n"); + } } static void prepare_flip_isr(struct amdgpu_crtc *acrtc) -- cgit From e6f4f9cfde0f586c276190f541ecfc80d9b688bc Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Thu, 5 Oct 2017 16:00:29 -0400 Subject: drm/amd/display: fix null dereference in reset hw ctx Signed-off-by: Eric Yang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 867a0eb9f2e0..5e5763c0ee94 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1877,7 +1877,7 @@ static void dce110_reset_hw_ctx_wrap( struct clock_source *old_clk = pipe_ctx_old->clock_source; /* disable already, no need to disable again */ - if (!pipe_ctx->stream->dpms_off) + if (pipe_ctx->stream && !pipe_ctx->stream->dpms_off) core_link_disable_stream(pipe_ctx_old, FREE_ACQUIRED_RESOURCE); pipe_ctx_old->stream_res.tg->funcs->set_blank(pipe_ctx_old->stream_res.tg, true); -- cgit From 39a4e6608f28586dee77daf8dc3af53e7829d2a8 Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Thu, 5 Oct 2017 17:57:35 -0400 Subject: drm/amd/display: add null check for cursor functions Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 411678736ed4..10421ea31373 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -210,11 +210,13 @@ bool dc_stream_set_cursor_attributes( pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes( pipe_ctx->plane_res.ipp, attributes); - if (pipe_ctx->plane_res.hubp != NULL) + if (pipe_ctx->plane_res.hubp != NULL && + pipe_ctx->plane_res.hubp->funcs->set_cursor_attributes != NULL) pipe_ctx->plane_res.hubp->funcs->set_cursor_attributes( pipe_ctx->plane_res.hubp, attributes); - if (pipe_ctx->plane_res.mi != NULL) + if (pipe_ctx->plane_res.mi != NULL && + pipe_ctx->plane_res.mi->funcs->set_cursor_attributes != NULL) pipe_ctx->plane_res.mi->funcs->set_cursor_attributes( pipe_ctx->plane_res.mi, attributes); @@ -253,6 +255,7 @@ bool dc_stream_set_cursor_position( for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp; + struct mem_input *mi = pipe_ctx->plane_res.mi; struct hubp *hubp = pipe_ctx->plane_res.hubp; struct transform *xfm = pipe_ctx->plane_res.xfm; struct dc_cursor_position pos_cpy = *position; @@ -281,10 +284,13 @@ bool dc_stream_set_cursor_position( if (ipp->funcs->ipp_cursor_set_position != NULL) ipp->funcs->ipp_cursor_set_position(ipp, &pos_cpy, ¶m); - if (hubp != NULL) + if (mi != NULL && mi->funcs->set_cursor_position != NULL) + mi->funcs->set_cursor_position(mi, &pos_cpy, ¶m); + + if (hubp != NULL && hubp->funcs->set_cursor_position != NULL) hubp->funcs->set_cursor_position(hubp, &pos_cpy, ¶m); - if (xfm != NULL) + if (xfm != NULL && xfm->funcs->set_cursor_position != NULL) xfm->funcs->set_cursor_position(xfm, &pos_cpy, ¶m, hubp->curs_attr.width); } -- cgit From d94585a06b8197a723787c6c5502872abcff0e8e Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Thu, 5 Oct 2017 16:47:49 -0400 Subject: drm/amd/display: rename transform to dpp for dcn Signed-off-by: Yue Hin Lau Reviewed-by: Eric Bernstein Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 1 + drivers/gpu/drm/amd/display/dc/core/dc.c | 1 + drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 16 +- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 16 +- drivers/gpu/drm/amd/display/dc/core/dc_surface.c | 1 + drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c | 144 ++++++------ drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h | 94 ++++---- .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c | 261 +++++++++++---------- .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c | 104 ++++---- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 59 ++--- .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 22 +- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 3 + drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h | 134 +++++++++++ 13 files changed, 509 insertions(+), 347 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index c37f130b0170..cf0c1459f546 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -488,6 +488,7 @@ static void split_stream_across_pipes( secondary_pipe->plane_res.hubp = pool->hubps[secondary_pipe->pipe_idx]; secondary_pipe->plane_res.ipp = pool->ipps[secondary_pipe->pipe_idx]; secondary_pipe->plane_res.xfm = pool->transforms[secondary_pipe->pipe_idx]; + secondary_pipe->plane_res.dpp = pool->dpps[secondary_pipe->pipe_idx]; if (primary_pipe->bottom_pipe) { ASSERT(primary_pipe->bottom_pipe != secondary_pipe); secondary_pipe->bottom_pipe = primary_pipe->bottom_pipe; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 12aeb6d83f42..80ddccc2570a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -38,6 +38,7 @@ #include "bios_parser_interface.h" #include "include/irq_service_interface.h" #include "transform.h" +#include "dpp.h" #include "timing_generator.h" #include "virtual/virtual_link_encoder.h" diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index c80bde94472f..303d7ec684d9 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -31,6 +31,7 @@ #include "opp.h" #include "timing_generator.h" #include "transform.h" +#include "dpp.h" #include "core_types.h" #include "set_mode_types.h" #include "virtual/virtual_stream_encoder.h" @@ -853,8 +854,13 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) pipe_ctx->plane_res.scl_data.v_active = timing->v_addressable; /* Taps calculations */ - res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps( - pipe_ctx->plane_res.xfm, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); + if (pipe_ctx->plane_res.xfm != NULL) + res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps( + pipe_ctx->plane_res.xfm, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); + + if (pipe_ctx->plane_res.dpp != NULL) + res = pipe_ctx->plane_res.dpp->funcs->dpp_get_optimal_number_of_taps( + pipe_ctx->plane_res.dpp, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); if (!res) { /* Try 24 bpp linebuffer */ @@ -862,6 +868,9 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps( pipe_ctx->plane_res.xfm, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); + + res = pipe_ctx->plane_res.dpp->funcs->dpp_get_optimal_number_of_taps( + pipe_ctx->plane_res.dpp, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); } if (res) @@ -1026,7 +1035,7 @@ static int acquire_first_split_pipe( pipe_ctx->stream_res.tg = pool->timing_generators[i]; pipe_ctx->plane_res.hubp = pool->hubps[i]; pipe_ctx->plane_res.ipp = pool->ipps[i]; - pipe_ctx->plane_res.xfm = pool->transforms[i]; + pipe_ctx->plane_res.dpp = pool->dpps[i]; pipe_ctx->stream_res.opp = pool->opps[i]; pipe_ctx->pipe_idx = i; @@ -1359,6 +1368,7 @@ static int acquire_first_free_pipe( pipe_ctx->plane_res.hubp = pool->hubps[i]; pipe_ctx->plane_res.ipp = pool->ipps[i]; pipe_ctx->plane_res.xfm = pool->transforms[i]; + pipe_ctx->plane_res.dpp = pool->dpps[i]; pipe_ctx->stream_res.opp = pool->opps[i]; pipe_ctx->pipe_idx = i; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 10421ea31373..97f040a25820 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -200,7 +200,7 @@ bool dc_stream_set_cursor_attributes( for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; - if (pipe_ctx->stream != stream || !pipe_ctx->plane_res.xfm) + if (pipe_ctx->stream != stream || (!pipe_ctx->plane_res.xfm && !pipe_ctx->plane_res.dpp)) continue; if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state) continue; @@ -221,9 +221,15 @@ bool dc_stream_set_cursor_attributes( pipe_ctx->plane_res.mi, attributes); - if (pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes != NULL) + if (pipe_ctx->plane_res.xfm != NULL && + pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes != NULL) pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes( pipe_ctx->plane_res.xfm, attributes); + + if (pipe_ctx->plane_res.dpp != NULL && + pipe_ctx->plane_res.dpp->funcs->set_cursor_attributes != NULL) + pipe_ctx->plane_res.dpp->funcs->set_cursor_attributes( + pipe_ctx->plane_res.dpp, attributes); } stream->cursor_attributes = *attributes; @@ -258,6 +264,7 @@ bool dc_stream_set_cursor_position( struct mem_input *mi = pipe_ctx->plane_res.mi; struct hubp *hubp = pipe_ctx->plane_res.hubp; struct transform *xfm = pipe_ctx->plane_res.xfm; + struct dpp *dpp = pipe_ctx->plane_res.dpp; struct dc_cursor_position pos_cpy = *position; struct dc_cursor_mi_param param = { .pixel_clk_khz = stream->timing.pix_clk_khz, @@ -270,7 +277,7 @@ bool dc_stream_set_cursor_position( if (pipe_ctx->stream != stream || (!pipe_ctx->plane_res.mi && !pipe_ctx->plane_res.hubp) || !pipe_ctx->plane_state || - !pipe_ctx->plane_res.xfm) + (!pipe_ctx->plane_res.xfm && !pipe_ctx->plane_res.dpp)) continue; if (pipe_ctx->plane_state->address.type @@ -293,6 +300,9 @@ bool dc_stream_set_cursor_position( if (xfm != NULL && xfm->funcs->set_cursor_position != NULL) xfm->funcs->set_cursor_position(xfm, &pos_cpy, ¶m, hubp->curs_attr.width); + if (dpp != NULL && dpp->funcs->set_cursor_position != NULL) + dpp->funcs->set_cursor_position(dpp, &pos_cpy, ¶m, hubp->curs_attr.width); + } return true; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index d43783a45ab6..5aa2270f36fd 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -30,6 +30,7 @@ /* DC core (private) */ #include "core_types.h" #include "transform.h" +#include "dpp.h" /******************************************************************************* * Private functions diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c index fb3c78858ebe..5960e491159d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c @@ -39,14 +39,14 @@ #define BLACK_OFFSET_CBCR 0x8000 #define REG(reg)\ - xfm->tf_regs->reg + dpp->tf_regs->reg #define CTX \ - xfm->base.ctx + dpp->base.ctx #undef FN #define FN(reg_name, field_name) \ - xfm->tf_shift->field_name, xfm->tf_mask->field_name + dpp->tf_shift->field_name, dpp->tf_mask->field_name enum pixel_format_description { PIXEL_FORMAT_FIXED = 0, @@ -99,7 +99,7 @@ enum gamut_remap_select { }; /* Program gamut remap in bypass mode */ -void dpp_set_gamut_remap_bypass(struct dcn10_dpp *xfm) +void dpp_set_gamut_remap_bypass(struct dcn10_dpp *dpp) { REG_SET(CM_GAMUT_REMAP_CONTROL, 0, CM_GAMUT_REMAP_MODE, 0); @@ -110,7 +110,7 @@ void dpp_set_gamut_remap_bypass(struct dcn10_dpp *xfm) bool dpp_get_optimal_number_of_taps( - struct transform *xfm, + struct dpp *dpp, struct scaler_data *scl_data, const struct scaling_taps *in_taps) { @@ -154,7 +154,7 @@ bool dpp_get_optimal_number_of_taps( else scl_data->taps.h_taps_c = in_taps->h_taps_c; - if (!xfm->ctx->dc->debug.always_scale) { + if (!dpp->ctx->dc->debug.always_scale) { if (IDENTITY_RATIO(scl_data->ratios.horz)) scl_data->taps.h_taps = 1; if (IDENTITY_RATIO(scl_data->ratios.vert)) @@ -169,14 +169,14 @@ bool dpp_get_optimal_number_of_taps( return true; } -void dpp_reset(struct transform *xfm_base) +void dpp_reset(struct dpp *dpp_base) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); - xfm->filter_h_c = NULL; - xfm->filter_v_c = NULL; - xfm->filter_h = NULL; - xfm->filter_v = NULL; + dpp->filter_h_c = NULL; + dpp->filter_v_c = NULL; + dpp->filter_h = NULL; + dpp->filter_v = NULL; /* set boundary mode to 0 */ REG_SET(DSCL_CONTROL, 0, SCL_BOUNDARY_MODE, 0); @@ -184,28 +184,28 @@ void dpp_reset(struct transform *xfm_base) -static void dcn10_dpp_cm_set_regamma_pwl( - struct transform *xfm_base, const struct pwl_params *params) +static void dpp1_cm_set_regamma_pwl( + struct dpp *dpp_base, const struct pwl_params *params) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); - dcn10_dpp_cm_power_on_regamma_lut(xfm_base, true); - dcn10_dpp_cm_configure_regamma_lut(xfm_base, xfm->is_write_to_ram_a_safe); + dpp1_cm_power_on_regamma_lut(dpp_base, true); + dpp1_cm_configure_regamma_lut(dpp_base, dpp->is_write_to_ram_a_safe); - if (xfm->is_write_to_ram_a_safe) - dcn10_dpp_cm_program_regamma_luta_settings(xfm_base, params); + if (dpp->is_write_to_ram_a_safe) + dpp1_cm_program_regamma_luta_settings(dpp_base, params); else - dcn10_dpp_cm_program_regamma_lutb_settings(xfm_base, params); + dpp1_cm_program_regamma_lutb_settings(dpp_base, params); - dcn10_dpp_cm_program_regamma_lut( - xfm_base, params->rgb_resulted, params->hw_points_num); + dpp1_cm_program_regamma_lut( + dpp_base, params->rgb_resulted, params->hw_points_num); } -static void dcn10_dpp_cm_set_regamma_mode( - struct transform *xfm_base, +static void dpp1_cm_set_regamma_mode( + struct dpp *dpp_base, enum opp_regamma mode) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); uint32_t re_mode = 0; uint32_t obuf_bypass = 0; /* need for pipe split */ uint32_t obuf_hupscale = 0; @@ -221,8 +221,8 @@ static void dcn10_dpp_cm_set_regamma_mode( re_mode = 2; break; case OPP_REGAMMA_USER: - re_mode = xfm->is_write_to_ram_a_safe ? 3 : 4; - xfm->is_write_to_ram_a_safe = !xfm->is_write_to_ram_a_safe; + re_mode = dpp->is_write_to_ram_a_safe ? 3 : 4; + dpp->is_write_to_ram_a_safe = !dpp->is_write_to_ram_a_safe; break; default: break; @@ -234,7 +234,7 @@ static void dcn10_dpp_cm_set_regamma_mode( OBUF_H_2X_UPSCALE_EN, obuf_hupscale); } -static void ippn10_setup_format_flags(enum surface_pixel_format input_format,\ +static void dpp1_setup_format_flags(enum surface_pixel_format input_format,\ enum pixel_format_description *fmt) { @@ -247,11 +247,11 @@ static void ippn10_setup_format_flags(enum surface_pixel_format input_format,\ *fmt = PIXEL_FORMAT_FIXED; } -static void ippn10_set_degamma_format_float( - struct transform *xfm_base, +static void dpp1_set_degamma_format_float( + struct dpp *dpp_base, bool is_float) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); if (is_float) { REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_INPUT_FORMAT, 3); @@ -262,8 +262,8 @@ static void ippn10_set_degamma_format_float( } } -void ippn10_cnv_setup ( - struct transform *xfm_base, +void dpp1_cnv_setup ( + struct dpp *dpp_base, enum surface_pixel_format input_format, enum expansion_mode mode) { @@ -273,10 +273,10 @@ void ippn10_cnv_setup ( enum dc_color_space color_space; enum dcn10_input_csc_select select; bool is_float; - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); bool force_disable_cursor = false; - ippn10_setup_format_flags(input_format, &fmt); + dpp1_setup_format_flags(input_format, &fmt); alpha_en = 1; pixel_format = 0; color_space = COLOR_SPACE_SRGB; @@ -304,7 +304,7 @@ void ippn10_cnv_setup ( break; } - ippn10_set_degamma_format_float(xfm_base, is_float); + dpp1_set_degamma_format_float(dpp_base, is_float); switch (input_format) { case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: @@ -362,7 +362,7 @@ void ippn10_cnv_setup ( CNVC_SURFACE_PIXEL_FORMAT, pixel_format); REG_UPDATE(FORMAT_CONTROL, FORMAT_CONTROL__ALPHA_EN, alpha_en); - ippn10_program_input_csc(xfm_base, color_space, select); + dpp1_program_input_csc(dpp_base, color_space, select); if (force_disable_cursor) { REG_UPDATE(CURSOR_CONTROL, @@ -373,10 +373,10 @@ void ippn10_cnv_setup ( } void dcn10_set_cursor_attributes( - struct transform *xfm_base, + struct dpp *dpp_base, const struct dc_cursor_attributes *attr) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); enum dc_cursor_color_format color_format = attr->color_format; REG_UPDATE_2(CURSOR0_CONTROL, @@ -401,12 +401,12 @@ void dcn10_set_cursor_attributes( void dcn10_set_cursor_position( - struct transform *xfm_base, + struct dpp *dpp_base, const struct dc_cursor_position *pos, const struct dc_cursor_mi_param *param, uint32_t width) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); int src_x_offset = pos->x - pos->x_hotspot - param->viewport_x_start; uint32_t cur_en = pos->enable ? 1 : 0; @@ -421,25 +421,25 @@ void dcn10_set_cursor_position( } -static const struct transform_funcs dcn10_dpp_funcs = { - .transform_reset = dpp_reset, - .transform_set_scaler = dcn10_dpp_dscl_set_scaler_manual_scale, - .transform_get_optimal_number_of_taps = dpp_get_optimal_number_of_taps, - .transform_set_gamut_remap = dcn10_dpp_cm_set_gamut_remap, - .opp_set_csc_adjustment = dcn10_dpp_cm_set_output_csc_adjustment, - .opp_set_csc_default = dcn10_dpp_cm_set_output_csc_default, - .opp_power_on_regamma_lut = dcn10_dpp_cm_power_on_regamma_lut, - .opp_program_regamma_lut = dcn10_dpp_cm_program_regamma_lut, - .opp_configure_regamma_lut = dcn10_dpp_cm_configure_regamma_lut, - .opp_program_regamma_lutb_settings = dcn10_dpp_cm_program_regamma_lutb_settings, - .opp_program_regamma_luta_settings = dcn10_dpp_cm_program_regamma_luta_settings, - .opp_program_regamma_pwl = dcn10_dpp_cm_set_regamma_pwl, - .opp_set_regamma_mode = dcn10_dpp_cm_set_regamma_mode, - .ipp_set_degamma = ippn10_set_degamma, - .ipp_program_input_lut = ippn10_program_input_lut, - .ipp_program_degamma_pwl = ippn10_set_degamma_pwl, - .ipp_setup = ippn10_cnv_setup, - .ipp_full_bypass = ippn10_full_bypass, +static const struct dpp_funcs dcn10_dpp_funcs = { + .dpp_reset = dpp_reset, + .dpp_set_scaler = dpp1_dscl_set_scaler_manual_scale, + .dpp_get_optimal_number_of_taps = dpp_get_optimal_number_of_taps, + .dpp_set_gamut_remap = dpp1_cm_set_gamut_remap, + .opp_set_csc_adjustment = dpp1_cm_set_output_csc_adjustment, + .opp_set_csc_default = dpp1_cm_set_output_csc_default, + .opp_power_on_regamma_lut = dpp1_cm_power_on_regamma_lut, + .opp_program_regamma_lut = dpp1_cm_program_regamma_lut, + .opp_configure_regamma_lut = dpp1_cm_configure_regamma_lut, + .opp_program_regamma_lutb_settings = dpp1_cm_program_regamma_lutb_settings, + .opp_program_regamma_luta_settings = dpp1_cm_program_regamma_luta_settings, + .opp_program_regamma_pwl = dpp1_cm_set_regamma_pwl, + .opp_set_regamma_mode = dpp1_cm_set_regamma_mode, + .ipp_set_degamma = dpp1_set_degamma, + .ipp_program_input_lut = dpp1_program_input_lut, + .ipp_program_degamma_pwl = dpp1_set_degamma_pwl, + .ipp_setup = dpp1_cnv_setup, + .ipp_full_bypass = dpp1_full_bypass, .set_cursor_attributes = dcn10_set_cursor_attributes, .set_cursor_position = dcn10_set_cursor_position, }; @@ -453,29 +453,29 @@ static struct dpp_caps dcn10_dpp_cap = { /* Constructor, Destructor */ /*****************************************/ -void dcn10_dpp_construct( - struct dcn10_dpp *xfm, +void dpp1_construct( + struct dcn10_dpp *dpp, struct dc_context *ctx, uint32_t inst, const struct dcn_dpp_registers *tf_regs, const struct dcn_dpp_shift *tf_shift, const struct dcn_dpp_mask *tf_mask) { - xfm->base.ctx = ctx; + dpp->base.ctx = ctx; - xfm->base.inst = inst; - xfm->base.funcs = &dcn10_dpp_funcs; - xfm->base.caps = &dcn10_dpp_cap; + dpp->base.inst = inst; + dpp->base.funcs = &dcn10_dpp_funcs; + dpp->base.caps = &dcn10_dpp_cap; - xfm->tf_regs = tf_regs; - xfm->tf_shift = tf_shift; - xfm->tf_mask = tf_mask; + dpp->tf_regs = tf_regs; + dpp->tf_shift = tf_shift; + dpp->tf_mask = tf_mask; - xfm->lb_pixel_depth_supported = + dpp->lb_pixel_depth_supported = LB_PIXEL_DEPTH_18BPP | LB_PIXEL_DEPTH_24BPP | LB_PIXEL_DEPTH_30BPP; - xfm->lb_bits_per_entry = LB_BITS_PER_ENTRY; - xfm->lb_memory_size = LB_TOTAL_NUMBER_OF_ENTRIES; /*0x1404*/ + dpp->lb_bits_per_entry = LB_BITS_PER_ENTRY; + dpp->lb_memory_size = LB_TOTAL_NUMBER_OF_ENTRIES; /*0x1404*/ } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h index c2e3ff883537..fe6c0aa13da4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h @@ -25,10 +25,10 @@ #ifndef __DAL_DPP_DCN10_H__ #define __DAL_DPP_DCN10_H__ -#include "transform.h" +#include "dpp.h" -#define TO_DCN10_DPP(transform)\ - container_of(transform, struct dcn10_dpp, base) +#define TO_DCN10_DPP(dpp)\ + container_of(dpp, struct dcn10_dpp, base) /* TODO: Use correct number of taps. Using polaris values for now */ #define LB_TOTAL_NUMBER_OF_ENTRIES 5124 @@ -1252,7 +1252,7 @@ struct dcn_dpp_registers { }; struct dcn10_dpp { - struct transform base; + struct dpp base; const struct dcn_dpp_registers *tf_regs; const struct dcn_dpp_shift *tf_shift; @@ -1285,99 +1285,99 @@ void dscl1_calc_lb_num_partitions( int *num_part_y, int *num_part_c); -void ippn10_degamma_ram_select( - struct transform *xfm_base, +void dpp1_degamma_ram_select( + struct dpp *dpp_base, bool use_ram_a); -void ippn10_program_degamma_luta_settings( - struct transform *xfm_base, +void dpp1_program_degamma_luta_settings( + struct dpp *dpp_base, const struct pwl_params *params); -void ippn10_program_degamma_lutb_settings( - struct transform *xfm_base, +void dpp1_program_degamma_lutb_settings( + struct dpp *dpp_base, const struct pwl_params *params); -void ippn10_program_degamma_lut( - struct transform *xfm_base, +void dpp1_program_degamma_lut( + struct dpp *dpp_base, const struct pwl_result_data *rgb, uint32_t num, bool is_ram_a); -void ippn10_power_on_degamma_lut( - struct transform *xfm_base, +void dpp1_power_on_degamma_lut( + struct dpp *dpp_base, bool power_on); -void ippn10_program_input_csc( - struct transform *xfm_base, +void dpp1_program_input_csc( + struct dpp *dpp_base, enum dc_color_space color_space, enum dcn10_input_csc_select select); -void ippn10_program_input_lut( - struct transform *xfm_base, +void dpp1_program_input_lut( + struct dpp *dpp_base, const struct dc_gamma *gamma); -void ippn10_full_bypass(struct transform *xfm_base); +void dpp1_full_bypass(struct dpp *dpp_base); -void ippn10_set_degamma( - struct transform *xfm_base, +void dpp1_set_degamma( + struct dpp *dpp_base, enum ipp_degamma_mode mode); -void ippn10_set_degamma_pwl(struct transform *xfm_base, +void dpp1_set_degamma_pwl(struct dpp *dpp_base, const struct pwl_params *params); bool dpp_get_optimal_number_of_taps( - struct transform *xfm, + struct dpp *dpp, struct scaler_data *scl_data, const struct scaling_taps *in_taps); -void dpp_reset(struct transform *xfm_base); +void dpp_reset(struct dpp *dpp_base); -void dcn10_dpp_cm_program_regamma_lut( - struct transform *xfm_base, +void dpp1_cm_program_regamma_lut( + struct dpp *dpp_base, const struct pwl_result_data *rgb, uint32_t num); -void dcn10_dpp_cm_power_on_regamma_lut( - struct transform *xfm_base, +void dpp1_cm_power_on_regamma_lut( + struct dpp *dpp_base, bool power_on); -void dcn10_dpp_cm_configure_regamma_lut( - struct transform *xfm_base, +void dpp1_cm_configure_regamma_lut( + struct dpp *dpp_base, bool is_ram_a); /*program re gamma RAM A*/ -void dcn10_dpp_cm_program_regamma_luta_settings( - struct transform *xfm_base, +void dpp1_cm_program_regamma_luta_settings( + struct dpp *dpp_base, const struct pwl_params *params); /*program re gamma RAM B*/ -void dcn10_dpp_cm_program_regamma_lutb_settings( - struct transform *xfm_base, +void dpp1_cm_program_regamma_lutb_settings( + struct dpp *dpp_base, const struct pwl_params *params); -void dcn10_dpp_cm_set_output_csc_adjustment( - struct transform *xfm_base, +void dpp1_cm_set_output_csc_adjustment( + struct dpp *dpp_base, const struct out_csc_color_matrix *tbl_entry); -void dcn10_dpp_cm_set_output_csc_default( - struct transform *xfm_base, +void dpp1_cm_set_output_csc_default( + struct dpp *dpp_base, const struct default_adjustment *default_adjust); -void dcn10_dpp_cm_set_gamut_remap( - struct transform *xfm, - const struct xfm_grph_csc_adjustment *adjust); +void dpp1_cm_set_gamut_remap( + struct dpp *dpp, + const struct dpp_grph_csc_adjustment *adjust); -void dcn10_dpp_dscl_set_scaler_manual_scale( - struct transform *xfm_base, +void dpp1_dscl_set_scaler_manual_scale( + struct dpp *dpp_base, const struct scaler_data *scl_data); -void ippn10_cnv_setup ( - struct transform *xfm_base, +void dpp1_cnv_setup ( + struct dpp *dpp_base, enum surface_pixel_format input_format, enum expansion_mode mode); -void ippn10_full_bypass(struct transform *xfm_base); +void dpp1_full_bypass(struct dpp *dpp_base); -void dcn10_dpp_construct(struct dcn10_dpp *xfm110, +void dpp1_construct(struct dcn10_dpp *dpp1, struct dc_context *ctx, uint32_t inst, const struct dcn_dpp_registers *tf_regs, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c index f88fd2e2e0aa..7784001c3a17 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c @@ -40,14 +40,14 @@ #define BLACK_OFFSET_CBCR 0x8000 #define REG(reg)\ - xfm->tf_regs->reg + dpp->tf_regs->reg #define CTX \ - xfm->base.ctx + dpp->base.ctx #undef FN #define FN(reg_name, field_name) \ - xfm->tf_shift->field_name, xfm->tf_mask->field_name + dpp->tf_shift->field_name, dpp->tf_mask->field_name struct dcn10_input_csc_matrix { enum dc_color_space color_space; @@ -120,7 +120,7 @@ static const struct dcn10_input_csc_matrix dcn10_input_csc_matrix[] = { static void program_gamut_remap( - struct dcn10_dpp *xfm, + struct dcn10_dpp *dpp, const uint16_t *regval, enum gamut_remap_select select) { @@ -146,10 +146,10 @@ static void program_gamut_remap( break; } - gam_regs.shifts.csc_c11 = xfm->tf_shift->CM_GAMUT_REMAP_C11; - gam_regs.masks.csc_c11 = xfm->tf_mask->CM_GAMUT_REMAP_C11; - gam_regs.shifts.csc_c12 = xfm->tf_shift->CM_GAMUT_REMAP_C12; - gam_regs.masks.csc_c12 = xfm->tf_mask->CM_GAMUT_REMAP_C12; + gam_regs.shifts.csc_c11 = dpp->tf_shift->CM_GAMUT_REMAP_C11; + gam_regs.masks.csc_c11 = dpp->tf_mask->CM_GAMUT_REMAP_C11; + gam_regs.shifts.csc_c12 = dpp->tf_shift->CM_GAMUT_REMAP_C12; + gam_regs.masks.csc_c12 = dpp->tf_mask->CM_GAMUT_REMAP_C12; if (select == GAMUT_REMAP_COEFF) { @@ -157,7 +157,7 @@ static void program_gamut_remap( gam_regs.csc_c33_c34 = REG(CM_GAMUT_REMAP_C33_C34); cm_helper_program_color_matrices( - xfm->base.ctx, + dpp->base.ctx, regval, &gam_regs); @@ -167,7 +167,7 @@ static void program_gamut_remap( gam_regs.csc_c33_c34 = REG(CM_COMA_C33_C34); cm_helper_program_color_matrices( - xfm->base.ctx, + dpp->base.ctx, regval, &gam_regs); @@ -177,7 +177,7 @@ static void program_gamut_remap( gam_regs.csc_c33_c34 = REG(CM_COMB_C33_C34); cm_helper_program_color_matrices( - xfm->base.ctx, + dpp->base.ctx, regval, &gam_regs); } @@ -188,15 +188,15 @@ static void program_gamut_remap( } -void dcn10_dpp_cm_set_gamut_remap( - struct transform *xfm, - const struct xfm_grph_csc_adjustment *adjust) +void dpp1_cm_set_gamut_remap( + struct dpp *dpp_base, + const struct dpp_grph_csc_adjustment *adjust) { - struct dcn10_dpp *dcn_xfm = TO_DCN10_DPP(xfm); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); if (adjust->gamut_adjust_type != GRAPHICS_GAMUT_ADJUST_TYPE_SW) /* Bypass if type is bypass or hw */ - program_gamut_remap(dcn_xfm, NULL, GAMUT_REMAP_BYPASS); + program_gamut_remap(dpp, NULL, GAMUT_REMAP_BYPASS); else { struct fixed31_32 arr_matrix[12]; uint16_t arr_reg_val[12]; @@ -219,16 +219,16 @@ void dcn10_dpp_cm_set_gamut_remap( convert_float_matrix( arr_reg_val, arr_matrix, 12); - program_gamut_remap(dcn_xfm, arr_reg_val, GAMUT_REMAP_COEFF); + program_gamut_remap(dpp, arr_reg_val, GAMUT_REMAP_COEFF); } } -void dcn10_dpp_cm_set_output_csc_default( - struct transform *xfm_base, +void dpp1_cm_set_output_csc_default( + struct dpp *dpp_base, const struct default_adjustment *default_adjust) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); uint32_t ocsc_mode = 0; if (default_adjust != NULL) { @@ -260,35 +260,35 @@ void dcn10_dpp_cm_set_output_csc_default( } -static void dcn10_dpp_cm_get_reg_field( - struct dcn10_dpp *xfm, +static void dpp1_cm_get_reg_field( + struct dcn10_dpp *dpp, struct xfer_func_reg *reg) { - reg->shifts.exp_region0_lut_offset = xfm->tf_shift->CM_RGAM_RAMA_EXP_REGION0_LUT_OFFSET; - reg->masks.exp_region0_lut_offset = xfm->tf_mask->CM_RGAM_RAMA_EXP_REGION0_LUT_OFFSET; - reg->shifts.exp_region0_num_segments = xfm->tf_shift->CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS; - reg->masks.exp_region0_num_segments = xfm->tf_mask->CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS; - reg->shifts.exp_region1_lut_offset = xfm->tf_shift->CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET; - reg->masks.exp_region1_lut_offset = xfm->tf_mask->CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET; - reg->shifts.exp_region1_num_segments = xfm->tf_shift->CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS; - reg->masks.exp_region1_num_segments = xfm->tf_mask->CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS; - - reg->shifts.field_region_end = xfm->tf_shift->CM_RGAM_RAMB_EXP_REGION_END_B; - reg->masks.field_region_end = xfm->tf_mask->CM_RGAM_RAMB_EXP_REGION_END_B; - reg->shifts.field_region_end_slope = xfm->tf_shift->CM_RGAM_RAMB_EXP_REGION_END_SLOPE_B; - reg->masks.field_region_end_slope = xfm->tf_mask->CM_RGAM_RAMB_EXP_REGION_END_SLOPE_B; - reg->shifts.field_region_end_base = xfm->tf_shift->CM_RGAM_RAMB_EXP_REGION_END_BASE_B; - reg->masks.field_region_end_base = xfm->tf_mask->CM_RGAM_RAMB_EXP_REGION_END_BASE_B; - reg->shifts.field_region_linear_slope = xfm->tf_shift->CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B; - reg->masks.field_region_linear_slope = xfm->tf_mask->CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B; - reg->shifts.exp_region_start = xfm->tf_shift->CM_RGAM_RAMB_EXP_REGION_START_B; - reg->masks.exp_region_start = xfm->tf_mask->CM_RGAM_RAMB_EXP_REGION_START_B; - reg->shifts.exp_resion_start_segment = xfm->tf_shift->CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B; - reg->masks.exp_resion_start_segment = xfm->tf_mask->CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B; + reg->shifts.exp_region0_lut_offset = dpp->tf_shift->CM_RGAM_RAMA_EXP_REGION0_LUT_OFFSET; + reg->masks.exp_region0_lut_offset = dpp->tf_mask->CM_RGAM_RAMA_EXP_REGION0_LUT_OFFSET; + reg->shifts.exp_region0_num_segments = dpp->tf_shift->CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS; + reg->masks.exp_region0_num_segments = dpp->tf_mask->CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS; + reg->shifts.exp_region1_lut_offset = dpp->tf_shift->CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET; + reg->masks.exp_region1_lut_offset = dpp->tf_mask->CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET; + reg->shifts.exp_region1_num_segments = dpp->tf_shift->CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS; + reg->masks.exp_region1_num_segments = dpp->tf_mask->CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS; + + reg->shifts.field_region_end = dpp->tf_shift->CM_RGAM_RAMB_EXP_REGION_END_B; + reg->masks.field_region_end = dpp->tf_mask->CM_RGAM_RAMB_EXP_REGION_END_B; + reg->shifts.field_region_end_slope = dpp->tf_shift->CM_RGAM_RAMB_EXP_REGION_END_SLOPE_B; + reg->masks.field_region_end_slope = dpp->tf_mask->CM_RGAM_RAMB_EXP_REGION_END_SLOPE_B; + reg->shifts.field_region_end_base = dpp->tf_shift->CM_RGAM_RAMB_EXP_REGION_END_BASE_B; + reg->masks.field_region_end_base = dpp->tf_mask->CM_RGAM_RAMB_EXP_REGION_END_BASE_B; + reg->shifts.field_region_linear_slope = dpp->tf_shift->CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B; + reg->masks.field_region_linear_slope = dpp->tf_mask->CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B; + reg->shifts.exp_region_start = dpp->tf_shift->CM_RGAM_RAMB_EXP_REGION_START_B; + reg->masks.exp_region_start = dpp->tf_mask->CM_RGAM_RAMB_EXP_REGION_START_B; + reg->shifts.exp_resion_start_segment = dpp->tf_shift->CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B; + reg->masks.exp_resion_start_segment = dpp->tf_mask->CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B; } -static void dcn10_dpp_cm_program_color_matrix( - struct dcn10_dpp *xfm, +static void dpp1_cm_program_color_matrix( + struct dcn10_dpp *dpp, const struct out_csc_color_matrix *tbl_entry) { uint32_t mode; @@ -301,10 +301,10 @@ static void dcn10_dpp_cm_program_color_matrix( return; } - gam_regs.shifts.csc_c11 = xfm->tf_shift->CM_OCSC_C11; - gam_regs.masks.csc_c11 = xfm->tf_mask->CM_OCSC_C11; - gam_regs.shifts.csc_c12 = xfm->tf_shift->CM_OCSC_C12; - gam_regs.masks.csc_c12 = xfm->tf_mask->CM_OCSC_C12; + gam_regs.shifts.csc_c11 = dpp->tf_shift->CM_OCSC_C11; + gam_regs.masks.csc_c11 = dpp->tf_mask->CM_OCSC_C11; + gam_regs.shifts.csc_c12 = dpp->tf_shift->CM_OCSC_C12; + gam_regs.masks.csc_c12 = dpp->tf_mask->CM_OCSC_C12; if (mode == 4) { @@ -312,7 +312,7 @@ static void dcn10_dpp_cm_program_color_matrix( gam_regs.csc_c33_c34 = REG(CM_OCSC_C33_C34); cm_helper_program_color_matrices( - xfm->base.ctx, + dpp->base.ctx, tbl_entry->regval, &gam_regs); @@ -322,17 +322,17 @@ static void dcn10_dpp_cm_program_color_matrix( gam_regs.csc_c33_c34 = REG(CM_COMB_C33_C34); cm_helper_program_color_matrices( - xfm->base.ctx, + dpp->base.ctx, tbl_entry->regval, &gam_regs); } } -void dcn10_dpp_cm_set_output_csc_adjustment( - struct transform *xfm_base, +void dpp1_cm_set_output_csc_adjustment( + struct dpp *dpp_base, const struct out_csc_color_matrix *tbl_entry) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); //enum csc_color_mode config = CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; uint32_t ocsc_mode = 4; @@ -364,26 +364,26 @@ void dcn10_dpp_cm_set_output_csc_adjustment( */ REG_SET(CM_OCSC_CONTROL, 0, CM_OCSC_MODE, ocsc_mode); - dcn10_dpp_cm_program_color_matrix(xfm, tbl_entry); + dpp1_cm_program_color_matrix(dpp, tbl_entry); } -void dcn10_dpp_cm_power_on_regamma_lut( - struct transform *xfm_base, +void dpp1_cm_power_on_regamma_lut( + struct dpp *dpp_base, bool power_on) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); REG_SET(CM_MEM_PWR_CTRL, 0, RGAM_MEM_PWR_FORCE, power_on == true ? 0:1); } -void dcn10_dpp_cm_program_regamma_lut( - struct transform *xfm_base, +void dpp1_cm_program_regamma_lut( + struct dpp *dpp_base, const struct pwl_result_data *rgb, uint32_t num) { uint32_t i; - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); for (i = 0 ; i < num; i++) { REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].red_reg); REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].green_reg); @@ -400,11 +400,11 @@ void dcn10_dpp_cm_program_regamma_lut( } -void dcn10_dpp_cm_configure_regamma_lut( - struct transform *xfm_base, +void dpp1_cm_configure_regamma_lut( + struct dpp *dpp_base, bool is_ram_a) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); REG_UPDATE(CM_RGAM_LUT_WRITE_EN_MASK, CM_RGAM_LUT_WRITE_EN_MASK, 7); @@ -414,14 +414,14 @@ void dcn10_dpp_cm_configure_regamma_lut( } /*program re gamma RAM A*/ -void dcn10_dpp_cm_program_regamma_luta_settings( - struct transform *xfm_base, +void dpp1_cm_program_regamma_luta_settings( + struct dpp *dpp_base, const struct pwl_params *params) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); struct xfer_func_reg gam_regs; - dcn10_dpp_cm_get_reg_field(xfm, &gam_regs); + dpp1_cm_get_reg_field(dpp, &gam_regs); gam_regs.start_cntl_b = REG(CM_RGAM_RAMA_START_CNTL_B); gam_regs.start_cntl_g = REG(CM_RGAM_RAMA_START_CNTL_G); @@ -438,19 +438,19 @@ void dcn10_dpp_cm_program_regamma_luta_settings( gam_regs.region_start = REG(CM_RGAM_RAMA_REGION_0_1); gam_regs.region_end = REG(CM_RGAM_RAMA_REGION_32_33); - cm_helper_program_xfer_func(xfm->base.ctx, params, &gam_regs); + cm_helper_program_xfer_func(dpp->base.ctx, params, &gam_regs); } /*program re gamma RAM B*/ -void dcn10_dpp_cm_program_regamma_lutb_settings( - struct transform *xfm_base, +void dpp1_cm_program_regamma_lutb_settings( + struct dpp *dpp_base, const struct pwl_params *params) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); struct xfer_func_reg gam_regs; - dcn10_dpp_cm_get_reg_field(xfm, &gam_regs); + dpp1_cm_get_reg_field(dpp, &gam_regs); gam_regs.start_cntl_b = REG(CM_RGAM_RAMB_START_CNTL_B); gam_regs.start_cntl_g = REG(CM_RGAM_RAMB_START_CNTL_G); @@ -467,15 +467,15 @@ void dcn10_dpp_cm_program_regamma_lutb_settings( gam_regs.region_start = REG(CM_RGAM_RAMB_REGION_0_1); gam_regs.region_end = REG(CM_RGAM_RAMB_REGION_32_33); - cm_helper_program_xfer_func(xfm->base.ctx, params, &gam_regs); + cm_helper_program_xfer_func(dpp->base.ctx, params, &gam_regs); } -void ippn10_program_input_csc( - struct transform *xfm_base, +void dpp1_program_input_csc( + struct dpp *dpp_base, enum dc_color_space color_space, enum dcn10_input_csc_select select) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); int i; int arr_size = sizeof(dcn10_input_csc_matrix)/sizeof(struct dcn10_input_csc_matrix); const uint16_t *regval = NULL; @@ -503,10 +503,10 @@ void ippn10_program_input_csc( REG_SET(CM_ICSC_CONTROL, 0, CM_ICSC_MODE, selection); - gam_regs.shifts.csc_c11 = xfm->tf_shift->CM_ICSC_C11; - gam_regs.masks.csc_c11 = xfm->tf_mask->CM_ICSC_C11; - gam_regs.shifts.csc_c12 = xfm->tf_shift->CM_ICSC_C12; - gam_regs.masks.csc_c12 = xfm->tf_mask->CM_ICSC_C12; + gam_regs.shifts.csc_c11 = dpp->tf_shift->CM_ICSC_C11; + gam_regs.masks.csc_c11 = dpp->tf_mask->CM_ICSC_C11; + gam_regs.shifts.csc_c12 = dpp->tf_shift->CM_ICSC_C12; + gam_regs.masks.csc_c12 = dpp->tf_mask->CM_ICSC_C12; if (select == INPUT_CSC_SELECT_ICSC) { @@ -515,7 +515,7 @@ void ippn10_program_input_csc( gam_regs.csc_c33_c34 = REG(CM_ICSC_C33_C34); cm_helper_program_color_matrices( - xfm->base.ctx, + dpp->base.ctx, regval, &gam_regs); } else { @@ -524,21 +524,21 @@ void ippn10_program_input_csc( gam_regs.csc_c33_c34 = REG(CM_COMA_C33_C34); cm_helper_program_color_matrices( - xfm->base.ctx, + dpp->base.ctx, regval, &gam_regs); } } /*program de gamma RAM B*/ -void ippn10_program_degamma_lutb_settings( - struct transform *xfm_base, +void dpp1_program_degamma_lutb_settings( + struct dpp *dpp_base, const struct pwl_params *params) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); struct xfer_func_reg gam_regs; - dcn10_dpp_cm_get_reg_field(xfm, &gam_regs); + dpp1_cm_get_reg_field(dpp, &gam_regs); gam_regs.start_cntl_b = REG(CM_DGAM_RAMB_START_CNTL_B); gam_regs.start_cntl_g = REG(CM_DGAM_RAMB_START_CNTL_G); @@ -556,18 +556,18 @@ void ippn10_program_degamma_lutb_settings( gam_regs.region_end = REG(CM_DGAM_RAMB_REGION_14_15); - cm_helper_program_xfer_func(xfm->base.ctx, params, &gam_regs); + cm_helper_program_xfer_func(dpp->base.ctx, params, &gam_regs); } /*program de gamma RAM A*/ -void ippn10_program_degamma_luta_settings( - struct transform *xfm_base, +void dpp1_program_degamma_luta_settings( + struct dpp *dpp_base, const struct pwl_params *params) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); struct xfer_func_reg gam_regs; - dcn10_dpp_cm_get_reg_field(xfm, &gam_regs); + dpp1_cm_get_reg_field(dpp, &gam_regs); gam_regs.start_cntl_b = REG(CM_DGAM_RAMA_START_CNTL_B); gam_regs.start_cntl_g = REG(CM_DGAM_RAMA_START_CNTL_G); @@ -584,34 +584,35 @@ void ippn10_program_degamma_luta_settings( gam_regs.region_start = REG(CM_DGAM_RAMA_REGION_0_1); gam_regs.region_end = REG(CM_DGAM_RAMA_REGION_14_15); - cm_helper_program_xfer_func(xfm->base.ctx, params, &gam_regs); + cm_helper_program_xfer_func(dpp->base.ctx, params, &gam_regs); } -void ippn10_power_on_degamma_lut( - struct transform *xfm_base, +void dpp1_power_on_degamma_lut( + struct dpp *dpp_base, bool power_on) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); REG_SET(CM_MEM_PWR_CTRL, 0, SHARED_MEM_PWR_DIS, power_on == true ? 0:1); } -static void ippn10_enable_cm_block( - struct transform *xfm_base) +static void dpp1_enable_cm_block( + struct dpp *dpp_base) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); + REG_UPDATE(CM_CMOUT_CONTROL, CM_CMOUT_ROUND_TRUNC_MODE, 8); REG_UPDATE(CM_CONTROL, CM_BYPASS_EN, 0); } -void ippn10_set_degamma( - struct transform *xfm_base, +void dpp1_set_degamma( + struct dpp *dpp_base, enum ipp_degamma_mode mode) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); - ippn10_enable_cm_block(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); + dpp1_enable_cm_block(dpp_base); switch (mode) { case IPP_DEGAMMA_MODE_BYPASS: @@ -630,11 +631,11 @@ void ippn10_set_degamma( } } -void ippn10_degamma_ram_select( - struct transform *xfm_base, +void dpp1_degamma_ram_select( + struct dpp *dpp_base, bool use_ram_a) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); if (use_ram_a) REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 3); @@ -643,13 +644,13 @@ void ippn10_degamma_ram_select( } -static bool ippn10_degamma_ram_inuse( - struct transform *xfm_base, +static bool dpp1_degamma_ram_inuse( + struct dpp *dpp_base, bool *ram_a_inuse) { bool ret = false; uint32_t status_reg = 0; - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); REG_GET(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_DGAM_CONFIG_STATUS, &status_reg); @@ -664,15 +665,15 @@ static bool ippn10_degamma_ram_inuse( return ret; } -void ippn10_program_degamma_lut( - struct transform *xfm_base, +void dpp1_program_degamma_lut( + struct dpp *dpp_base, const struct pwl_result_data *rgb, uint32_t num, bool is_ram_a) { uint32_t i; - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_HOST_EN, 0); REG_UPDATE(CM_DGAM_LUT_WRITE_EN_MASK, CM_DGAM_LUT_WRITE_EN_MASK, 7); @@ -694,27 +695,27 @@ void ippn10_program_degamma_lut( } } -void ippn10_set_degamma_pwl(struct transform *xfm_base, +void dpp1_set_degamma_pwl(struct dpp *dpp_base, const struct pwl_params *params) { bool is_ram_a = true; - ippn10_power_on_degamma_lut(xfm_base, true); - ippn10_enable_cm_block(xfm_base); - ippn10_degamma_ram_inuse(xfm_base, &is_ram_a); + dpp1_power_on_degamma_lut(dpp_base, true); + dpp1_enable_cm_block(dpp_base); + dpp1_degamma_ram_inuse(dpp_base, &is_ram_a); if (is_ram_a == true) - ippn10_program_degamma_lutb_settings(xfm_base, params); + dpp1_program_degamma_lutb_settings(dpp_base, params); else - ippn10_program_degamma_luta_settings(xfm_base, params); + dpp1_program_degamma_luta_settings(dpp_base, params); - ippn10_program_degamma_lut(xfm_base, params->rgb_resulted, + dpp1_program_degamma_lut(dpp_base, params->rgb_resulted, params->hw_points_num, !is_ram_a); - ippn10_degamma_ram_select(xfm_base, !is_ram_a); + dpp1_degamma_ram_select(dpp_base, !is_ram_a); } -void ippn10_full_bypass(struct transform *xfm_base) +void dpp1_full_bypass(struct dpp *dpp_base) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); /* Input pixel format: ARGB8888 */ REG_SET(CNVC_SURFACE_PIXEL_FORMAT, 0, @@ -727,19 +728,19 @@ void ippn10_full_bypass(struct transform *xfm_base) FORMAT_EXPANSION_MODE, 0); /* COLOR_KEYER_CONTROL.COLOR_KEYER_EN = 0 this should be default */ - if (xfm->tf_mask->CM_BYPASS_EN) + if (dpp->tf_mask->CM_BYPASS_EN) REG_SET(CM_CONTROL, 0, CM_BYPASS_EN, 1); /* Setting degamma bypass for now */ REG_SET(CM_DGAM_CONTROL, 0, CM_DGAM_LUT_MODE, 0); } -static bool ippn10_ingamma_ram_inuse(struct transform *xfm_base, +static bool dpp1_ingamma_ram_inuse(struct dpp *dpp_base, bool *ram_a_inuse) { bool in_use = false; uint32_t status_reg = 0; - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); REG_GET(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_DGAM_CONFIG_STATUS, &status_reg); @@ -765,19 +766,19 @@ static bool ippn10_ingamma_ram_inuse(struct transform *xfm_base, * In the future, this function should support additional input gamma methods, * such as piecewise linear mapping, and input gamma bypass. */ -void ippn10_program_input_lut( - struct transform *xfm_base, +void dpp1_program_input_lut( + struct dpp *dpp_base, const struct dc_gamma *gamma) { int i; - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); bool rama_occupied = false; uint32_t ram_num; // Power on LUT memory. REG_SET(CM_MEM_PWR_CTRL, 0, SHARED_MEM_PWR_DIS, 1); - ippn10_enable_cm_block(xfm_base); + dpp1_enable_cm_block(dpp_base); // Determine whether to use RAM A or RAM B - ippn10_ingamma_ram_inuse(xfm_base, &rama_occupied); + dpp1_ingamma_ram_inuse(dpp_base, &rama_occupied); if (!rama_occupied) REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_SEL, 0); else 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 eda6c8010fb8..b443a90974b9 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 @@ -40,14 +40,14 @@ #define BLACK_OFFSET_CBCR 0x8000 #define REG(reg)\ - xfm->tf_regs->reg + dpp->tf_regs->reg #define CTX \ - xfm->base.ctx + dpp->base.ctx #undef FN #define FN(reg_name, field_name) \ - xfm->tf_shift->field_name, xfm->tf_mask->field_name + dpp->tf_shift->field_name, dpp->tf_mask->field_name enum dcn10_coef_filter_type_sel { SCL_COEF_LUMA_VERT_FILTER = 0, @@ -86,7 +86,7 @@ enum dscl_mode_sel { }; static void dpp_set_overscan( - struct dcn10_dpp *xfm, + struct dcn10_dpp *dpp, const struct scaler_data *data) { uint32_t left = data->recout.x; @@ -114,7 +114,7 @@ static void dpp_set_overscan( } static void dpp_set_otg_blank( - struct dcn10_dpp *xfm, const struct scaler_data *data) + struct dcn10_dpp *dpp, const struct scaler_data *data) { uint32_t h_blank_start = data->h_active; uint32_t h_blank_end = 0; @@ -165,13 +165,13 @@ static bool is_420_format(enum pixel_format format) } static enum dscl_mode_sel get_dscl_mode( - struct transform *xfm_base, + struct dpp *dpp_base, const struct scaler_data *data, bool dbg_always_scale) { const long long one = dal_fixed31_32_one.value; - if (xfm_base->caps->dscl_data_proc_format == DSCL_DATA_PRCESSING_FIXED_FORMAT) { + if (dpp_base->caps->dscl_data_proc_format == DSCL_DATA_PRCESSING_FIXED_FORMAT) { /* DSCL is processing data in fixed format */ if (data->format == PIXEL_FORMAT_FP16) return DSCL_MODE_DSCL_BYPASS; @@ -199,12 +199,12 @@ static enum dscl_mode_sel get_dscl_mode( } static void dpp_set_lb( - struct dcn10_dpp *xfm, + struct dcn10_dpp *dpp, const struct line_buffer_params *lb_params, enum lb_memory_config mem_size_config) { /* LB */ - if (xfm->base.caps->dscl_data_proc_format == DSCL_DATA_PRCESSING_FIXED_FORMAT) { + if (dpp->base.caps->dscl_data_proc_format == DSCL_DATA_PRCESSING_FIXED_FORMAT) { /* DSCL caps: pixel data processed in fixed format */ uint32_t pixel_depth = get_pixel_depth_val(lb_params->depth); uint32_t dyn_pix_depth = lb_params->dynamic_pixel_depth; @@ -250,7 +250,7 @@ static const uint16_t *get_filter_coeffs_64p(int taps, struct fixed31_32 ratio) } static void dpp_set_scaler_filter( - struct dcn10_dpp *xfm, + struct dcn10_dpp *dpp, uint32_t taps, enum dcn10_coef_filter_type_sel filter_type, const uint16_t *filter) @@ -288,7 +288,7 @@ static void dpp_set_scaler_filter( } static void dpp_set_scl_filter( - struct dcn10_dpp *xfm, + struct dcn10_dpp *dpp, const struct scaler_data *scl_data, bool chroma_coef_mode) { @@ -330,16 +330,16 @@ static void dpp_set_scl_filter( filter_v = get_filter_coeffs_64p( scl_data->taps.v_taps, scl_data->ratios.vert); - filter_updated = (filter_h && (filter_h != xfm->filter_h)) - || (filter_v && (filter_v != xfm->filter_v)); + filter_updated = (filter_h && (filter_h != dpp->filter_h)) + || (filter_v && (filter_v != dpp->filter_v)); if (chroma_coef_mode) { filter_h_c = get_filter_coeffs_64p( scl_data->taps.h_taps_c, scl_data->ratios.horz_c); filter_v_c = get_filter_coeffs_64p( scl_data->taps.v_taps_c, scl_data->ratios.vert_c); - filter_updated = filter_updated || (filter_h_c && (filter_h_c != xfm->filter_h_c)) - || (filter_v_c && (filter_v_c != xfm->filter_v_c)); + filter_updated = filter_updated || (filter_h_c && (filter_h_c != dpp->filter_h_c)) + || (filter_v_c && (filter_v_c != dpp->filter_v_c)); } if (filter_updated) { @@ -347,34 +347,34 @@ static void dpp_set_scl_filter( if (!h_2tap_hardcode_coef_en && filter_h) { dpp_set_scaler_filter( - xfm, scl_data->taps.h_taps, + dpp, scl_data->taps.h_taps, SCL_COEF_LUMA_HORZ_FILTER, filter_h); } - xfm->filter_h = filter_h; + dpp->filter_h = filter_h; if (!v_2tap_hardcode_coef_en && filter_v) { dpp_set_scaler_filter( - xfm, scl_data->taps.v_taps, + dpp, scl_data->taps.v_taps, SCL_COEF_LUMA_VERT_FILTER, filter_v); } - xfm->filter_v = filter_v; + dpp->filter_v = filter_v; if (chroma_coef_mode) { if (!h_2tap_hardcode_coef_en && filter_h_c) { dpp_set_scaler_filter( - xfm, scl_data->taps.h_taps_c, + dpp, scl_data->taps.h_taps_c, SCL_COEF_CHROMA_HORZ_FILTER, filter_h_c); } if (!v_2tap_hardcode_coef_en && filter_v_c) { dpp_set_scaler_filter( - xfm, scl_data->taps.v_taps_c, + dpp, scl_data->taps.v_taps_c, SCL_COEF_CHROMA_VERT_FILTER, filter_v_c); } } - xfm->filter_h_c = filter_h_c; - xfm->filter_v_c = filter_v_c; + dpp->filter_h_c = filter_h_c; + dpp->filter_v_c = filter_v_c; coef_ram_current = get_reg_field_value_ex( - scl_mode, xfm->tf_mask->SCL_COEF_RAM_SELECT_CURRENT, - xfm->tf_shift->SCL_COEF_RAM_SELECT_CURRENT); + scl_mode, dpp->tf_mask->SCL_COEF_RAM_SELECT_CURRENT, + dpp->tf_shift->SCL_COEF_RAM_SELECT_CURRENT); /* Swap coefficient RAM and set chroma coefficient mode */ REG_SET_2(SCL_MODE, scl_mode, @@ -458,7 +458,7 @@ bool is_lb_conf_valid(int ceil_vratio, int num_partitions, int vtaps) } /*find first match configuration which meets the min required lb size*/ -static enum lb_memory_config find_lb_memory_config(struct dcn10_dpp *xfm, +static enum lb_memory_config find_lb_memory_config(struct dcn10_dpp *dpp, const struct scaler_data *scl_data) { int num_part_y, num_part_c; @@ -468,17 +468,17 @@ static enum lb_memory_config find_lb_memory_config(struct dcn10_dpp *xfm, int ceil_vratio_c = dal_fixed31_32_ceil(scl_data->ratios.vert_c); enum lb_memory_config mem_cfg = LB_MEMORY_CONFIG_0; - if (xfm->base.ctx->dc->debug.use_max_lb) + if (dpp->base.ctx->dc->debug.use_max_lb) return mem_cfg; - xfm->base.caps->dscl_calc_lb_num_partitions( + dpp->base.caps->dscl_calc_lb_num_partitions( scl_data, LB_MEMORY_CONFIG_1, &num_part_y, &num_part_c); if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)) return LB_MEMORY_CONFIG_1; - xfm->base.caps->dscl_calc_lb_num_partitions( + dpp->base.caps->dscl_calc_lb_num_partitions( scl_data, LB_MEMORY_CONFIG_2, &num_part_y, &num_part_c); if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) @@ -487,7 +487,7 @@ static enum lb_memory_config find_lb_memory_config(struct dcn10_dpp *xfm, if (scl_data->format == PIXEL_FORMAT_420BPP8 || scl_data->format == PIXEL_FORMAT_420BPP10) { - xfm->base.caps->dscl_calc_lb_num_partitions( + dpp->base.caps->dscl_calc_lb_num_partitions( scl_data, LB_MEMORY_CONFIG_3, &num_part_y, &num_part_c); if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) @@ -495,7 +495,7 @@ static enum lb_memory_config find_lb_memory_config(struct dcn10_dpp *xfm, return LB_MEMORY_CONFIG_3; } - xfm->base.caps->dscl_calc_lb_num_partitions( + dpp->base.caps->dscl_calc_lb_num_partitions( scl_data, LB_MEMORY_CONFIG_0, &num_part_y, &num_part_c); /*Ensure we can support the requested number of vtaps*/ @@ -506,27 +506,27 @@ static enum lb_memory_config find_lb_memory_config(struct dcn10_dpp *xfm, } void dpp_set_scaler_auto_scale( - struct transform *xfm_base, + struct dpp *dpp_base, const struct scaler_data *scl_data) { enum lb_memory_config lb_config; - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); enum dscl_mode_sel dscl_mode = get_dscl_mode( - xfm_base, scl_data, xfm_base->ctx->dc->debug.always_scale); + dpp_base, scl_data, dpp_base->ctx->dc->debug.always_scale); bool ycbcr = scl_data->format >= PIXEL_FORMAT_VIDEO_BEGIN && scl_data->format <= PIXEL_FORMAT_VIDEO_END; - dpp_set_overscan(xfm, scl_data); + dpp_set_overscan(dpp, scl_data); - dpp_set_otg_blank(xfm, scl_data); + dpp_set_otg_blank(dpp, scl_data); REG_UPDATE(SCL_MODE, DSCL_MODE, dscl_mode); if (dscl_mode == DSCL_MODE_DSCL_BYPASS) return; - lb_config = find_lb_memory_config(xfm, scl_data); - dpp_set_lb(xfm, &scl_data->lb_params, lb_config); + lb_config = find_lb_memory_config(dpp, scl_data); + dpp_set_lb(dpp, &scl_data->lb_params, lb_config); if (dscl_mode == DSCL_MODE_SCALING_444_BYPASS) return; @@ -554,12 +554,12 @@ void dpp_set_scaler_auto_scale( SCL_V_NUM_TAPS_C, scl_data->taps.v_taps_c - 1, SCL_H_NUM_TAPS_C, scl_data->taps.h_taps_c - 1); - dpp_set_scl_filter(xfm, scl_data, ycbcr); + dpp_set_scl_filter(dpp, scl_data, ycbcr); } static void dpp_set_manual_ratio_init( - struct dcn10_dpp *xfm, const struct scaler_data *data) + struct dcn10_dpp *dpp, const struct scaler_data *data) { uint32_t init_frac = 0; uint32_t init_int = 0; @@ -619,7 +619,7 @@ static void dpp_set_manual_ratio_init( static void dpp_set_recout( - struct dcn10_dpp *xfm, const struct rect *recout) + struct dcn10_dpp *dpp, const struct rect *recout) { REG_SET_2(RECOUT_START, 0, /* First pixel of RECOUT */ @@ -632,24 +632,24 @@ static void dpp_set_recout( RECOUT_WIDTH, recout->width, /* Number of RECOUT vertical lines */ RECOUT_HEIGHT, recout->height - - xfm->base.ctx->dc->debug.surface_visual_confirm * 4 * - (xfm->base.inst + 1)); + - dpp->base.ctx->dc->debug.surface_visual_confirm * 4 * + (dpp->base.inst + 1)); } /* Main function to program scaler and line buffer in manual scaling mode */ -void dcn10_dpp_dscl_set_scaler_manual_scale( - struct transform *xfm_base, +void dpp1_dscl_set_scaler_manual_scale( + struct dpp *dpp_base, const struct scaler_data *scl_data) { enum lb_memory_config lb_config; - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); enum dscl_mode_sel dscl_mode = get_dscl_mode( - xfm_base, scl_data, xfm_base->ctx->dc->debug.always_scale); + dpp_base, scl_data, dpp_base->ctx->dc->debug.always_scale); bool ycbcr = scl_data->format >= PIXEL_FORMAT_VIDEO_BEGIN && scl_data->format <= PIXEL_FORMAT_VIDEO_END; /* Recout */ - dpp_set_recout(xfm, &scl_data->recout); + dpp_set_recout(dpp, &scl_data->recout); /* MPC Size */ REG_SET_2(MPC_SIZE, 0, @@ -665,8 +665,8 @@ void dcn10_dpp_dscl_set_scaler_manual_scale( return; /* LB */ - lb_config = find_lb_memory_config(xfm, scl_data); - dpp_set_lb(xfm, &scl_data->lb_params, lb_config); + lb_config = find_lb_memory_config(dpp, scl_data); + dpp_set_lb(dpp, &scl_data->lb_params, lb_config); if (dscl_mode == DSCL_MODE_SCALING_444_BYPASS) return; @@ -689,7 +689,7 @@ void dcn10_dpp_dscl_set_scaler_manual_scale( SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_RGB_Y); /* Manually calculate scale ratio and init values */ - dpp_set_manual_ratio_init(xfm, scl_data); + dpp_set_manual_ratio_init(dpp, scl_data); /* HTaps/VTaps */ REG_SET_4(SCL_TAP_CONTROL, 0, @@ -698,5 +698,5 @@ void dcn10_dpp_dscl_set_scaler_manual_scale( SCL_V_NUM_TAPS_C, scl_data->taps.v_taps_c - 1, SCL_H_NUM_TAPS_C, scl_data->taps.h_taps_c - 1); - dpp_set_scl_filter(xfm, scl_data, ycbcr); + dpp_set_scl_filter(dpp, scl_data, ycbcr); } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 6b866b169985..b69884549fc5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -895,10 +895,10 @@ static void dcn10_init_hw(struct dc *dc) } for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct transform *xfm = dc->res_pool->transforms[i]; + struct dpp *dpp = dc->res_pool->dpps[i]; struct timing_generator *tg = dc->res_pool->timing_generators[i]; - xfm->funcs->transform_reset(xfm); + dpp->funcs->dpp_reset(dpp); dc->res_pool->mpc->funcs->remove( dc->res_pool->mpc, &(dc->res_pool->opps[i]->mpc_tree), dc->res_pool->opps[i]->inst, i); @@ -1146,14 +1146,14 @@ static void plane_atomic_disable(struct dc *dc, static void plane_atomic_power_down(struct dc *dc, int fe_idx) { struct dce_hwseq *hws = dc->hwseq; - struct transform *xfm = dc->res_pool->transforms[fe_idx]; + struct dpp *dpp = dc->res_pool->dpps[fe_idx]; if (REG(DC_IP_REQUEST_CNTL)) { REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1); dpp_pg_control(hws, fe_idx, false); hubp_pg_control(hws, fe_idx, false); - xfm->funcs->transform_reset(xfm); + dpp->funcs->dpp_reset(dpp); REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0); dm_logger_write(dc->ctx->logger, LOG_DEBUG, @@ -1203,7 +1203,7 @@ static void reset_front_end( static void dcn10_power_down_fe(struct dc *dc, int fe_idx) { struct dce_hwseq *hws = dc->hwseq; - struct transform *xfm = dc->res_pool->transforms[fe_idx]; + struct dpp *dpp = dc->res_pool->dpps[fe_idx]; reset_front_end(dc, fe_idx); @@ -1211,7 +1211,7 @@ static void dcn10_power_down_fe(struct dc *dc, int fe_idx) IP_REQUEST_EN, 1); dpp_pg_control(hws, fe_idx, false); hubp_pg_control(hws, fe_idx, false); - xfm->funcs->transform_reset(xfm); + dpp->funcs->dpp_reset(dpp); REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0); dm_logger_write(dc->ctx->logger, LOG_DEBUG, @@ -1365,34 +1365,34 @@ static void dcn10_update_plane_addr(const struct dc *dc, struct pipe_ctx *pipe_c static bool dcn10_set_input_transfer_func( struct pipe_ctx *pipe_ctx, const struct dc_plane_state *plane_state) { - struct transform *xfm_base = pipe_ctx->plane_res.xfm; + struct dpp *dpp_base = pipe_ctx->plane_res.dpp; const struct dc_transfer_func *tf = NULL; bool result = true; - if (xfm_base == NULL) + if (dpp_base == NULL) return false; if (plane_state->in_transfer_func) tf = plane_state->in_transfer_func; if (plane_state->gamma_correction && dce_use_lut(plane_state)) - xfm_base->funcs->ipp_program_input_lut(xfm_base, + dpp_base->funcs->ipp_program_input_lut(dpp_base, plane_state->gamma_correction); if (tf == NULL) - xfm_base->funcs->ipp_set_degamma(xfm_base, IPP_DEGAMMA_MODE_BYPASS); + dpp_base->funcs->ipp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_BYPASS); else if (tf->type == TF_TYPE_PREDEFINED) { switch (tf->tf) { case TRANSFER_FUNCTION_SRGB: - xfm_base->funcs->ipp_set_degamma(xfm_base, + dpp_base->funcs->ipp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_HW_sRGB); break; case TRANSFER_FUNCTION_BT709: - xfm_base->funcs->ipp_set_degamma(xfm_base, + dpp_base->funcs->ipp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_HW_xvYCC); break; case TRANSFER_FUNCTION_LINEAR: - xfm_base->funcs->ipp_set_degamma(xfm_base, + dpp_base->funcs->ipp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_BYPASS); break; case TRANSFER_FUNCTION_PQ: @@ -1403,7 +1403,7 @@ static bool dcn10_set_input_transfer_func( break; } } else if (tf->type == TF_TYPE_BYPASS) { - xfm_base->funcs->ipp_set_degamma(xfm_base, IPP_DEGAMMA_MODE_BYPASS); + dpp_base->funcs->ipp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_BYPASS); } else { /*TF_TYPE_DISTRIBUTED_POINTS*/ result = false; @@ -1730,25 +1730,25 @@ static bool dcn10_set_output_transfer_func( struct pipe_ctx *pipe_ctx, const struct dc_stream_state *stream) { - struct transform *xfm = pipe_ctx->plane_res.xfm; + struct dpp *dpp = pipe_ctx->plane_res.dpp; - if (xfm == NULL) + if (dpp == NULL) return false; - xfm->regamma_params.hw_points_num = GAMMA_HW_POINTS_NUM; + dpp->regamma_params.hw_points_num = GAMMA_HW_POINTS_NUM; if (stream->out_transfer_func && stream->out_transfer_func->type == TF_TYPE_PREDEFINED && stream->out_transfer_func->tf == TRANSFER_FUNCTION_SRGB) { - xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_SRGB); + dpp->funcs->opp_set_regamma_mode(dpp, OPP_REGAMMA_SRGB); } else if (dcn10_translate_regamma_to_hw_format( - stream->out_transfer_func, &xfm->regamma_params)) { - xfm->funcs->opp_program_regamma_pwl(xfm, &xfm->regamma_params); - xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_USER); + stream->out_transfer_func, &dpp->regamma_params)) { + dpp->funcs->opp_program_regamma_pwl(dpp, &dpp->regamma_params); + dpp->funcs->opp_set_regamma_mode(dpp, OPP_REGAMMA_USER); } else { - xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_BYPASS); + dpp->funcs->opp_set_regamma_mode(dpp, OPP_REGAMMA_BYPASS); } return true; @@ -2033,7 +2033,7 @@ static void dcn10_power_on_fe( static void program_gamut_remap(struct pipe_ctx *pipe_ctx) { - struct xfm_grph_csc_adjustment adjust; + struct dpp_grph_csc_adjustment adjust; memset(&adjust, 0, sizeof(adjust)); adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS; @@ -2069,7 +2069,7 @@ static void program_gamut_remap(struct pipe_ctx *pipe_ctx) gamut_remap_matrix.matrix[10]; } - pipe_ctx->plane_res.xfm->funcs->transform_set_gamut_remap(pipe_ctx->plane_res.xfm, &adjust); + pipe_ctx->plane_res.dpp->funcs->dpp_set_gamut_remap(pipe_ctx->plane_res.dpp, &adjust); } @@ -2091,7 +2091,7 @@ static void program_csc_matrix(struct pipe_ctx *pipe_ctx, tbl_entry.color_space = color_space; //tbl_entry.regval = matrix; - pipe_ctx->plane_res.xfm->funcs->opp_set_csc_adjustment(pipe_ctx->plane_res.xfm, &tbl_entry); + pipe_ctx->plane_res.dpp->funcs->opp_set_csc_adjustment(pipe_ctx->plane_res.dpp, &tbl_entry); } } static bool is_lower_pipe_tree_visible(struct pipe_ctx *pipe_ctx) @@ -2275,7 +2275,7 @@ static void update_dchubp_dpp( { struct dce_hwseq *hws = dc->hwseq; struct hubp *hubp = pipe_ctx->plane_res.hubp; - struct transform *xfm = pipe_ctx->plane_res.xfm; + struct dpp *dpp = pipe_ctx->plane_res.dpp; struct dc_plane_state *plane_state = pipe_ctx->plane_state; union plane_size size = plane_state->plane_size; struct mpcc_cfg mpcc_cfg = {0}; @@ -2317,7 +2317,7 @@ static void update_dchubp_dpp( hws ); - xfm->funcs->ipp_setup(xfm, + dpp->funcs->ipp_setup(dpp, plane_state->format, EXPANSION_MODE_ZERO); @@ -2346,8 +2346,9 @@ static void update_dchubp_dpp( pipe_ctx->plane_res.scl_data.lb_params.alpha_en = per_pixel_alpha; pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; /* scaler configuration */ - pipe_ctx->plane_res.xfm->funcs->transform_set_scaler( - pipe_ctx->plane_res.xfm, &pipe_ctx->plane_res.scl_data); + pipe_ctx->plane_res.dpp->funcs->dpp_set_scaler( + pipe_ctx->plane_res.dpp, &pipe_ctx->plane_res.scl_data); + hubp->funcs->mem_program_viewport(hubp, &pipe_ctx->plane_res.scl_data.viewport, &pipe_ctx->plane_res.scl_data.viewport_c); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 4764590f9097..4dbaf9a2f275 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -446,13 +446,13 @@ static const struct dc_debug debug_defaults_diags = { .disable_pplib_wm_range = true }; -static void dcn10_dpp_destroy(struct transform **xfm) +static void dcn10_dpp_destroy(struct dpp **dpp) { - kfree(TO_DCN10_DPP(*xfm)); - *xfm = NULL; + kfree(TO_DCN10_DPP(*dpp)); + *dpp = NULL; } -static struct transform *dcn10_dpp_create( +static struct dpp *dcn10_dpp_create( struct dc_context *ctx, uint32_t inst) { @@ -462,8 +462,8 @@ static struct transform *dcn10_dpp_create( if (!dpp) return NULL; - dcn10_dpp_construct(dpp, ctx, inst, - &tf_regs[inst], &tf_shift, &tf_mask); + dpp1_construct(dpp, ctx, inst, + &tf_regs[inst], &tf_shift, &tf_mask); return &dpp->base; } @@ -702,8 +702,8 @@ static void destruct(struct dcn10_resource_pool *pool) if (pool->base.opps[i] != NULL) pool->base.opps[i]->funcs->opp_destroy(&pool->base.opps[i]); - if (pool->base.transforms[i] != NULL) - dcn10_dpp_destroy(&pool->base.transforms[i]); + if (pool->base.dpps[i] != NULL) + dcn10_dpp_destroy(&pool->base.dpps[i]); if (pool->base.ipps[i] != NULL) pool->base.ipps[i]->funcs->ipp_destroy(&pool->base.ipps[i]); @@ -924,7 +924,7 @@ static struct pipe_ctx *dcn10_acquire_idle_pipe_for_layer( idle_pipe->plane_res.hubp = pool->hubps[idle_pipe->pipe_idx]; idle_pipe->plane_res.ipp = pool->ipps[idle_pipe->pipe_idx]; - idle_pipe->plane_res.xfm = pool->transforms[idle_pipe->pipe_idx]; + idle_pipe->plane_res.dpp = pool->dpps[idle_pipe->pipe_idx]; return idle_pipe; } @@ -1377,8 +1377,8 @@ static bool construct( goto ipp_create_fail; } - pool->base.transforms[j] = dcn10_dpp_create(ctx, i); - if (pool->base.transforms[j] == NULL) { + pool->base.dpps[j] = dcn10_dpp_create(ctx, i); + if (pool->base.dpps[j] == NULL) { BREAK_TO_DEBUGGER(); dm_error( "DC: failed to create dpp!\n"); diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 45518c05e846..b69f321e2ab6 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -84,6 +84,7 @@ void core_link_set_avmute(struct pipe_ctx *pipe_ctx, bool enable); /********** DAL Core*********************/ #include "display_clock.h" #include "transform.h" +#include "dpp.h" struct resource_pool; struct dc_state; @@ -133,6 +134,7 @@ struct resource_pool { struct hubp *hubps[MAX_PIPES]; struct input_pixel_processor *ipps[MAX_PIPES]; struct transform *transforms[MAX_PIPES]; + struct dpp *dpps[MAX_PIPES]; struct output_pixel_processor *opps[MAX_PIPES]; struct timing_generator *timing_generators[MAX_PIPES]; struct stream_encoder *stream_enc[MAX_PIPES * 2]; @@ -184,6 +186,7 @@ struct plane_resource { struct mem_input *mi; struct input_pixel_processor *ipp; struct transform *xfm; + struct dpp *dpp; }; struct pipe_ctx { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h new file mode 100644 index 000000000000..83a68460edcd --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h @@ -0,0 +1,134 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + + +#ifndef __DAL_DPP_H__ +#define __DAL_DPP_H__ + +#include "transform.h" + +struct dpp { + const struct dpp_funcs *funcs; + struct dc_context *ctx; + int inst; + struct dpp_caps *caps; + struct pwl_params regamma_params; +}; + +struct dpp_grph_csc_adjustment { + struct fixed31_32 temperature_matrix[CSC_TEMPERATURE_MATRIX_SIZE]; + enum graphics_gamut_adjust_type gamut_adjust_type; +}; + +struct dpp_funcs { + void (*dpp_reset)(struct dpp *dpp); + + void (*dpp_set_scaler)(struct dpp *dpp, + const struct scaler_data *scl_data); + + void (*dpp_set_pixel_storage_depth)( + struct dpp *dpp, + enum lb_pixel_depth depth, + const struct bit_depth_reduction_params *bit_depth_params); + + bool (*dpp_get_optimal_number_of_taps)( + struct dpp *dpp, + struct scaler_data *scl_data, + const struct scaling_taps *in_taps); + + void (*dpp_set_gamut_remap)( + struct dpp *dpp, + const struct dpp_grph_csc_adjustment *adjust); + + void (*opp_set_csc_default)( + struct dpp *dpp, + const struct default_adjustment *default_adjust); + + void (*opp_set_csc_adjustment)( + struct dpp *dpp, + const struct out_csc_color_matrix *tbl_entry); + + void (*opp_power_on_regamma_lut)( + struct dpp *dpp, + bool power_on); + + void (*opp_program_regamma_lut)( + struct dpp *dpp, + const struct pwl_result_data *rgb, + uint32_t num); + + void (*opp_configure_regamma_lut)( + struct dpp *dpp, + bool is_ram_a); + + void (*opp_program_regamma_lutb_settings)( + struct dpp *dpp, + const struct pwl_params *params); + + void (*opp_program_regamma_luta_settings)( + struct dpp *dpp, + const struct pwl_params *params); + + void (*opp_program_regamma_pwl)( + struct dpp *dpp, const struct pwl_params *params); + + void (*opp_set_regamma_mode)( + struct dpp *dpp_base, + enum opp_regamma mode); + + void (*ipp_set_degamma)( + struct dpp *dpp_base, + enum ipp_degamma_mode mode); + + void (*ipp_program_input_lut)( + struct dpp *dpp_base, + const struct dc_gamma *gamma); + + void (*ipp_program_degamma_pwl)(struct dpp *dpp_base, + const struct pwl_params *params); + + void (*ipp_setup)( + struct dpp *dpp_base, + enum surface_pixel_format input_format, + enum expansion_mode mode); + + void (*ipp_full_bypass)(struct dpp *dpp_base); + + void (*set_cursor_attributes)( + struct dpp *dpp_base, + const struct dc_cursor_attributes *attr); + + void (*set_cursor_position)( + struct dpp *dpp_base, + const struct dc_cursor_position *pos, + const struct dc_cursor_mi_param *param, + uint32_t width + ); + +}; + + + +#endif -- cgit From 3df8fcafb7edab79d76c4c76c93446b91eb4916f Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Wed, 4 Oct 2017 12:47:13 -0400 Subject: drm/amd/display: Do not set bandwidth on page flips. Which removes a lockdep warning for a possible deadlock situation: While holding the drm event mutex (hard irq safe), dc_post_update_surfaces_to_stream eventually acquires the atom context lock, which is hard irq unsafe. We should only be calling it on full updates anyways. Also remove a redundant call to dc_post_update_surfaces_to_stream, dc_commit_updates_for_stream already calls it. Signed-off-by: Leo (Sunpeng) Li Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 80ddccc2570a..9d750fa29a87 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -980,8 +980,6 @@ bool dc_commit_planes_to_stream( new_plane_count, dc_stream, stream_update, plane_states, state); - dc_post_update_surfaces_to_stream(dc); - kfree(stream_update); return true; } @@ -1418,7 +1416,8 @@ void dc_commit_updates_for_stream(struct dc *dc, update_type, context); - dc_post_update_surfaces_to_stream(dc); + if (update_type >= UPDATE_TYPE_FULL) + dc_post_update_surfaces_to_stream(dc); if (dc->current_state != context) { -- cgit From 9bbc30310f240c9400e31c7ab7b7edd2b76b3589 Mon Sep 17 00:00:00 2001 From: Jerry Zuo Date: Fri, 6 Oct 2017 15:08:07 -0400 Subject: drm/amd/display: Remove a false-positive error message To avoid confusion, need to suppress the error message when get -ERESTARTSYS error code. It is normal when getting interrupted by signals in the process of a wait for the buffer to become unreserved. Only propagate to user-mode for further action, no need to pop up error message. Signed-off-by: Jerry Zuo Reviewed-by: Sun peng Li Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') 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 17fb636648f4..09163d8d9332 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1790,7 +1790,9 @@ static int get_fb_info(const struct amdgpu_framebuffer *amdgpu_fb, int r = amdgpu_bo_reserve(rbo, false); if (unlikely(r)) { - DRM_ERROR("Unable to reserve buffer\n"); + // Don't show error msg. when return -ERESTARTSYS + if (r != -ERESTARTSYS) + DRM_ERROR("Unable to reserve buffer: %d\n", r); return r; } -- cgit From 215a6f05bcc18ffcd953a8527639ea1f571f4d81 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 6 Oct 2017 15:40:07 -0400 Subject: drm/amd/display: add performance trace macro to dc Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_services.c | 6 ++ drivers/gpu/drm/amd/display/dc/basics/logger.c | 78 ++++++---------------- drivers/gpu/drm/amd/display/dc/basics/logger.h | 37 ---------- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 5 +- drivers/gpu/drm/amd/display/dc/dc.h | 1 + .../gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 5 -- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 40 +++++------ .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 1 + drivers/gpu/drm/amd/display/dc/dm_services.h | 2 + .../gpu/drm/amd/display/include/logger_interface.h | 28 ++++++++ drivers/gpu/drm/amd/display/include/logger_types.h | 36 +++++++++- 11 files changed, 118 insertions(+), 121 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c index 26bf9918fcb7..5df8fd5b537c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c @@ -35,6 +35,12 @@ #include "amdgpu_dm_irq.h" #include "amdgpu_pm.h" +unsigned long long dm_get_timestamp(struct dc_context *ctx) +{ + /* TODO: return actual timestamp */ + return 0; +} + bool dm_write_persistent_data(struct dc_context *ctx, const struct dc_sink *sink, const char *module_name, diff --git a/drivers/gpu/drm/amd/display/dc/basics/logger.c b/drivers/gpu/drm/amd/display/dc/basics/logger.c index afb6d2d80e0c..e04e8ecd4874 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/logger.c +++ b/drivers/gpu/drm/amd/display/dc/basics/logger.c @@ -80,8 +80,6 @@ static bool construct(struct dc_context *ctx, struct dal_logger *logger, logger->buffer_read_offset = 0; logger->buffer_write_offset = 0; - logger->write_wrap_count = 0; - logger->read_wrap_count = 0; logger->open_count = 0; logger->flags.bits.ENABLE_CONSOLE = 1; @@ -162,23 +160,24 @@ static void log_to_debug_console(struct log_entry *entry) } /* Print everything unread existing in log_buffer to debug console*/ -static void flush_to_debug_console(struct dal_logger *logger) +void dm_logger_flush_buffer(struct dal_logger *logger, bool should_warn) { - int i = logger->buffer_read_offset; - char *string_start = &logger->log_buffer[i]; + char *string_start = &logger->log_buffer[logger->buffer_read_offset]; - dm_output_to_console( - "---------------- FLUSHING LOG BUFFER ----------------\n"); - while (i < logger->buffer_write_offset) { + if (should_warn) + dm_output_to_console( + "---------------- FLUSHING LOG BUFFER ----------------\n"); + while (logger->buffer_read_offset < logger->buffer_write_offset) { - if (logger->log_buffer[i] == '\0') { + if (logger->log_buffer[logger->buffer_read_offset] == '\0') { dm_output_to_console("%s", string_start); - string_start = (char *)logger->log_buffer + i + 1; + string_start = logger->log_buffer + logger->buffer_read_offset + 1; } - i++; + logger->buffer_read_offset++; } - dm_output_to_console( - "-------------- END FLUSHING LOG BUFFER --------------\n\n"); + if (should_warn) + dm_output_to_console( + "-------------- END FLUSHING LOG BUFFER --------------\n\n"); } static void log_to_internal_buffer(struct log_entry *entry) @@ -195,35 +194,17 @@ static void log_to_internal_buffer(struct log_entry *entry) if (size > 0 && size < logger->log_buffer_size) { - int total_free_space = 0; - int space_before_wrap = 0; - - if (logger->buffer_write_offset > logger->buffer_read_offset) { - total_free_space = logger->log_buffer_size - - logger->buffer_write_offset + - logger->buffer_read_offset; - space_before_wrap = logger->log_buffer_size - - logger->buffer_write_offset; - } else if (logger->buffer_write_offset < - logger->buffer_read_offset) { - total_free_space = logger->log_buffer_size - - logger->buffer_read_offset + - logger->buffer_write_offset; - space_before_wrap = total_free_space; - } else if (logger->write_wrap_count != - logger->read_wrap_count) { - /* Buffer is completely full already */ - total_free_space = 0; - space_before_wrap = 0; - } else { + int buffer_space = logger->log_buffer_size - + logger->buffer_write_offset; + + if (logger->buffer_write_offset == logger->buffer_read_offset) { /* Buffer is empty, start writing at beginning */ - total_free_space = logger->log_buffer_size; - space_before_wrap = logger->log_buffer_size; + buffer_space = logger->log_buffer_size; logger->buffer_write_offset = 0; logger->buffer_read_offset = 0; } - if (space_before_wrap > size) { + if (buffer_space > size) { /* No wrap around, copy 'size' bytes * from 'entry->buf' to 'log_buffer' */ @@ -232,28 +213,12 @@ static void log_to_internal_buffer(struct log_entry *entry) entry->buf, size); logger->buffer_write_offset += size; - } else if (total_free_space > size) { - /* We have enough room without flushing, - * but need to wrap around */ - - int space_after_wrap = total_free_space - - space_before_wrap; - - memmove(logger->log_buffer + - logger->buffer_write_offset, - entry->buf, space_before_wrap); - memmove(logger->log_buffer, entry->buf + - space_before_wrap, space_after_wrap); - - logger->buffer_write_offset = space_after_wrap; - logger->write_wrap_count++; - } else { /* Not enough room remaining, we should flush * existing logs */ /* Flush existing unread logs to console */ - flush_to_debug_console(logger); + dm_logger_flush_buffer(logger, true); /* Start writing to beginning of buffer */ memmove(logger->log_buffer, entry->buf, size); @@ -325,9 +290,10 @@ void dm_logger_write( log_heading(&entry); size = dm_log_to_buffer( - buffer, LOG_MAX_LINE_SIZE, msg, args); + buffer, LOG_MAX_LINE_SIZE - 1, msg, args); - entry.buf_offset += size; + buffer[entry.buf_offset + size] = '\0'; + entry.buf_offset += size + 1; /* --Flush log_entry buffer-- */ /* print to kernel console */ diff --git a/drivers/gpu/drm/amd/display/dc/basics/logger.h b/drivers/gpu/drm/amd/display/dc/basics/logger.h index 2f7a5df4c811..09722f0f8aa3 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/logger.h +++ b/drivers/gpu/drm/amd/display/dc/basics/logger.h @@ -26,42 +26,5 @@ #ifndef __DAL_LOGGER_H__ #define __DAL_LOGGER_H__ -/* Structure for keeping track of offsets, buffer, etc */ - -#define DAL_LOGGER_BUFFER_MAX_SIZE 2048 - -/*Connectivity log needs to output EDID, which needs at lease 256x3 bytes, - * change log line size to 896 to meet the request. - */ -#define LOG_MAX_LINE_SIZE 896 - -#include "include/logger_types.h" - -struct dal_logger { - - /* How far into the circular buffer has been read by dsat - * Read offset should never cross write offset. Write \0's to - * read data just to be sure? - */ - uint32_t buffer_read_offset; - - /* How far into the circular buffer we have written - * Write offset should never cross read offset - */ - uint32_t buffer_write_offset; - - uint32_t write_wrap_count; - uint32_t read_wrap_count; - - uint32_t open_count; - - char *log_buffer; /* Pointer to malloc'ed buffer */ - uint32_t log_buffer_size; /* Size of circular buffer */ - - uint32_t mask; /*array of masks for major elements*/ - - union logger_flags flags; - struct dc_context *ctx; -}; #endif /* __DAL_LOGGER_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index cf0c1459f546..e1515230c661 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -682,6 +682,7 @@ bool dcn_validate_bandwidth( bool bw_limit_pass; float bw_limit; + PERFORMANCE_TRACE_START(); if (dcn_bw_apply_registry_override(dc)) dcn_bw_sync_calcs_and_dml(dc); @@ -1089,6 +1090,8 @@ bool dcn_validate_bandwidth( kernel_fpu_end(); + PERFORMANCE_TRACE_END(); + if (bw_limit_pass && v->voltage_level != 5) return true; else @@ -1223,7 +1226,7 @@ unsigned int dcn_find_dcfclk_suits_all( else dcf_clk = dc->dcn_soc->dcfclkv_min0p65*1000; - dm_logger_write(dc->ctx->logger, LOG_HW_MARKS, + dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_CALCS, "\tdcf_clk for voltage = %d\n", dcf_clk); return dcf_clk; } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index c7b31adc736e..ace17d13683a 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -224,6 +224,7 @@ struct dc_debug { bool disable_dpp_pg; bool disable_stereo_support; bool vsr_support; + bool performance_trace; }; struct dc_state; struct resource_pool; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 0cf0fff74d44..fe88852b4774 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -757,11 +757,6 @@ void dce110_link_encoder_construct( enc110->base.preferred_engine = ENGINE_ID_UNKNOWN; } - dm_logger_write(init_data->ctx->logger, LOG_I2C_AUX, - "Using channel: %s [%d]\n", - DECODE_CHANNEL_ID(init_data->channel), - init_data->channel); - /* Override features with DCE-specific values */ if (BP_RESULT_OK == bp_funcs->get_encoder_cap_info( enc110->base.ctx->dc_bios, enc110->base.id, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index b69884549fc5..6e2cec643f31 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -468,7 +468,7 @@ static void program_watermarks( refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "URGENCY_WATERMARK_A calculated =%d\n" "HW register value = 0x%x\n", watermarks->a.urgent_ns, prog_wm_value); @@ -476,7 +476,7 @@ static void program_watermarks( prog_wm_value = convert_and_clamp(watermarks->a.pte_meta_urgent_ns, refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "PTE_META_URGENCY_WATERMARK_A calculated =%d\n" "HW register value = 0x%x\n", watermarks->a.pte_meta_urgent_ns, prog_wm_value); @@ -487,7 +487,7 @@ static void program_watermarks( refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "SR_ENTER_EXIT_WATERMARK_A calculated =%d\n" "HW register value = 0x%x\n", watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); @@ -497,7 +497,7 @@ static void program_watermarks( watermarks->a.cstate_pstate.cstate_exit_ns, refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "SR_EXIT_WATERMARK_A calculated =%d\n" "HW register value = 0x%x\n", watermarks->a.cstate_pstate.cstate_exit_ns, prog_wm_value); @@ -507,7 +507,7 @@ static void program_watermarks( watermarks->a.cstate_pstate.pstate_change_ns, refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "DRAM_CLK_CHANGE_WATERMARK_A calculated =%d\n" "HW register value = 0x%x\n\n", watermarks->a.cstate_pstate.pstate_change_ns, prog_wm_value); @@ -517,7 +517,7 @@ static void program_watermarks( prog_wm_value = convert_and_clamp( watermarks->b.urgent_ns, refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "URGENCY_WATERMARK_B calculated =%d\n" "HW register value = 0x%x\n", watermarks->b.urgent_ns, prog_wm_value); @@ -527,7 +527,7 @@ static void program_watermarks( watermarks->b.pte_meta_urgent_ns, refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "PTE_META_URGENCY_WATERMARK_B calculated =%d\n" "HW register value = 0x%x\n", watermarks->b.pte_meta_urgent_ns, prog_wm_value); @@ -537,7 +537,7 @@ static void program_watermarks( watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "SR_ENTER_WATERMARK_B calculated =%d\n" "HW register value = 0x%x\n", watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); @@ -547,7 +547,7 @@ static void program_watermarks( watermarks->b.cstate_pstate.cstate_exit_ns, refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "SR_EXIT_WATERMARK_B calculated =%d\n" "HW register value = 0x%x\n", watermarks->b.cstate_pstate.cstate_exit_ns, prog_wm_value); @@ -556,7 +556,7 @@ static void program_watermarks( watermarks->b.cstate_pstate.pstate_change_ns, refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "DRAM_CLK_CHANGE_WATERMARK_B calculated =%d\n\n" "HW register value = 0x%x\n", watermarks->b.cstate_pstate.pstate_change_ns, prog_wm_value); @@ -565,7 +565,7 @@ static void program_watermarks( prog_wm_value = convert_and_clamp( watermarks->c.urgent_ns, refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "URGENCY_WATERMARK_C calculated =%d\n" "HW register value = 0x%x\n", watermarks->c.urgent_ns, prog_wm_value); @@ -575,7 +575,7 @@ static void program_watermarks( watermarks->c.pte_meta_urgent_ns, refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "PTE_META_URGENCY_WATERMARK_C calculated =%d\n" "HW register value = 0x%x\n", watermarks->c.pte_meta_urgent_ns, prog_wm_value); @@ -585,7 +585,7 @@ static void program_watermarks( watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "SR_ENTER_WATERMARK_C calculated =%d\n" "HW register value = 0x%x\n", watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); @@ -595,7 +595,7 @@ static void program_watermarks( watermarks->c.cstate_pstate.cstate_exit_ns, refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "SR_EXIT_WATERMARK_C calculated =%d\n" "HW register value = 0x%x\n", watermarks->c.cstate_pstate.cstate_exit_ns, prog_wm_value); @@ -605,7 +605,7 @@ static void program_watermarks( watermarks->c.cstate_pstate.pstate_change_ns, refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "DRAM_CLK_CHANGE_WATERMARK_C calculated =%d\n\n" "HW register value = 0x%x\n", watermarks->c.cstate_pstate.pstate_change_ns, prog_wm_value); @@ -614,7 +614,7 @@ static void program_watermarks( prog_wm_value = convert_and_clamp( watermarks->d.urgent_ns, refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "URGENCY_WATERMARK_D calculated =%d\n" "HW register value = 0x%x\n", watermarks->d.urgent_ns, prog_wm_value); @@ -623,7 +623,7 @@ static void program_watermarks( watermarks->d.pte_meta_urgent_ns, refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "PTE_META_URGENCY_WATERMARK_D calculated =%d\n" "HW register value = 0x%x\n", watermarks->d.pte_meta_urgent_ns, prog_wm_value); @@ -633,7 +633,7 @@ static void program_watermarks( watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "SR_ENTER_WATERMARK_D calculated =%d\n" "HW register value = 0x%x\n", watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); @@ -643,7 +643,7 @@ static void program_watermarks( watermarks->d.cstate_pstate.cstate_exit_ns, refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "SR_EXIT_WATERMARK_D calculated =%d\n" "HW register value = 0x%x\n", watermarks->d.cstate_pstate.cstate_exit_ns, prog_wm_value); @@ -653,7 +653,7 @@ static void program_watermarks( watermarks->d.cstate_pstate.pstate_change_ns, refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "DRAM_CLK_CHANGE_WATERMARK_D calculated =%d\n" "HW register value = 0x%x\n\n", watermarks->d.cstate_pstate.pstate_change_ns, prog_wm_value); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 4dbaf9a2f275..d47ff7e6a525 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -434,6 +434,7 @@ static const struct dc_debug debug_defaults_drv = { .voltage_align_fclk = true, .disable_stereo_support = true, .vsr_support = true, + .performance_trace = false, }; static const struct dc_debug debug_defaults_diags = { diff --git a/drivers/gpu/drm/amd/display/dc/dm_services.h b/drivers/gpu/drm/amd/display/dc/dm_services.h index a11991c382de..d6b3b832986b 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services.h @@ -418,6 +418,8 @@ bool dm_dmcu_set_pipe(struct dc_context *ctx, unsigned int controller_id); #define dm_log_to_buffer(buffer, size, fmt, args)\ vsnprintf(buffer, size, fmt, args) +unsigned long long dm_get_timestamp(struct dc_context *ctx); + /* * Debug and verification hooks */ diff --git a/drivers/gpu/drm/amd/display/include/logger_interface.h b/drivers/gpu/drm/amd/display/include/logger_interface.h index 5aaf2dacfe38..8e1fe70097be 100644 --- a/drivers/gpu/drm/amd/display/include/logger_interface.h +++ b/drivers/gpu/drm/amd/display/include/logger_interface.h @@ -44,6 +44,8 @@ struct dal_logger *dal_logger_create(struct dc_context *ctx, uint32_t log_mask); uint32_t dal_logger_destroy(struct dal_logger **logger); +void dm_logger_flush_buffer(struct dal_logger *logger, bool should_warn); + void dm_logger_write( struct dal_logger *logger, enum dc_log_type log_type, @@ -157,4 +159,30 @@ void context_clock_trace( #define DTN_INFO_END() \ dm_dtn_log_end(dc_ctx) +#define PERFORMANCE_TRACE_START() \ + unsigned long long perf_trc_start_stmp = dm_get_timestamp(dc->ctx); \ + unsigned long long perf_trc_start_log_msk = dc->ctx->logger->mask; \ + unsigned int perf_trc_start_log_flags = dc->ctx->logger->flags.value; \ + if (dc->debug.performance_trace) {\ + dm_logger_flush_buffer(dc->ctx->logger, false);\ + dc->ctx->logger->mask = 1<ctx->logger->flags.bits.ENABLE_CONSOLE = 0;\ + dc->ctx->logger->flags.bits.ENABLE_BUFFER = 1;\ + } + +#define PERFORMANCE_TRACE_END() do {\ + unsigned long long perf_trc_end_stmp = dm_get_timestamp(dc->ctx);\ + if (dc->debug.performance_trace) {\ + dm_logger_write(dc->ctx->logger, \ + LOG_PERF_TRACE, \ + "%s duration: %d ticks\n", __func__,\ + perf_trc_end_stmp - perf_trc_start_stmp); \ + if (perf_trc_start_log_msk != 1<ctx->logger->mask = perf_trc_start_log_msk;\ + dc->ctx->logger->flags.value = perf_trc_start_log_flags;\ + dm_logger_flush_buffer(dc->ctx->logger, false);\ + } \ + } \ +} while (0) + #endif /* __DAL_LOGGER_INTERFACE_H__ */ diff --git a/drivers/gpu/drm/amd/display/include/logger_types.h b/drivers/gpu/drm/amd/display/include/logger_types.h index 1f22e84cedb9..e2ff8cd423d6 100644 --- a/drivers/gpu/drm/amd/display/include/logger_types.h +++ b/drivers/gpu/drm/amd/display/include/logger_types.h @@ -64,8 +64,7 @@ enum dc_log_type { LOG_EVENT_LINK_LOSS, LOG_EVENT_UNDERFLOW, LOG_IF_TRACE, - LOG_HW_MARKS, - LOG_PPLIB, + LOG_PERF_TRACE, LOG_SECTION_TOTAL_COUNT }; @@ -131,4 +130,37 @@ struct dc_log_type_info { char name[MAX_NAME_LEN]; }; +/* Structure for keeping track of offsets, buffer, etc */ + +#define DAL_LOGGER_BUFFER_MAX_SIZE 2048 + +/*Connectivity log needs to output EDID, which needs at lease 256x3 bytes, + * change log line size to 896 to meet the request. + */ +#define LOG_MAX_LINE_SIZE 896 + +struct dal_logger { + + /* How far into the circular buffer has been read by dsat + * Read offset should never cross write offset. Write \0's to + * read data just to be sure? + */ + uint32_t buffer_read_offset; + + /* How far into the circular buffer we have written + * Write offset should never cross read offset + */ + uint32_t buffer_write_offset; + + uint32_t open_count; + + char *log_buffer; /* Pointer to malloc'ed buffer */ + uint32_t log_buffer_size; /* Size of circular buffer */ + + uint32_t mask; /*array of masks for major elements*/ + + union logger_flags flags; + struct dc_context *ctx; +}; + #endif /* __DAL_LOGGER_TYPES_H__ */ -- cgit From 199e458aafc241a2792b3f8a99d5a11aa7726a7d Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Thu, 5 Oct 2017 19:15:25 -0400 Subject: drm/amd/display: Set addressable region as active + border This ensures that we do not draw the blank region onscreen, and that we do underscan instead. Signed-off-by: Andrew Jiang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 303d7ec684d9..454a521a268d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -850,6 +850,20 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) */ pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; + /** + * KMD sends us h and v_addressable without the borders, which causes us sometimes to draw + * the blank region on-screen. Correct for this by adding the borders back to their + * respective addressable values, and by shifting recout. + */ + timing->h_addressable += timing->h_border_left + timing->h_border_right; + timing->v_addressable += timing->v_border_top + timing->v_border_bottom; + pipe_ctx->plane_res.scl_data.recout.y += timing->v_border_top; + pipe_ctx->plane_res.scl_data.recout.x += timing->h_border_left; + timing->v_border_top = 0; + timing->v_border_bottom = 0; + timing->h_border_left = 0; + timing->h_border_right = 0; + pipe_ctx->plane_res.scl_data.h_active = timing->h_addressable; pipe_ctx->plane_res.scl_data.v_active = timing->v_addressable; -- cgit From 9a5d9c48d883db4f7f3e5409062bef7d25165a95 Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Fri, 6 Oct 2017 11:57:40 -0400 Subject: drm/amd/display: Report stream as different on scaling change When scaling is enabled, our preference is to scale up to the prefered (native) mode. This means that hardware timings will be the same across a modeset. Therefore, also report mode as changed if source or destination rectangle is different. Signed-off-by: Leo (Sunpeng) Li Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 5 +++-- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 22 ++++++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dc.h | 2 ++ 3 files changed, 27 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') 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 09163d8d9332..fad40da8422e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4428,12 +4428,13 @@ static int dm_update_crtcs_state(struct dc *dc, } } - if (dc_is_stream_unchanged(new_stream, dm_old_crtc_state->stream)) { + if (dc_is_stream_unchanged(new_stream, dm_old_crtc_state->stream) && + dc_is_stream_scaling_unchanged(new_stream, dm_old_crtc_state->stream)) { new_crtc_state->mode_changed = false; DRM_DEBUG_DRIVER("Mode change not required, setting mode_changed to %d", - new_crtc_state->mode_changed); + new_crtc_state->mode_changed); } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 454a521a268d..2a5c91772473 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1335,6 +1335,28 @@ bool dc_is_stream_unchanged( return true; } +bool dc_is_stream_scaling_unchanged( + struct dc_stream_state *old_stream, struct dc_stream_state *stream) +{ + if (old_stream == stream) + return true; + + if (old_stream == NULL || stream == NULL) + return false; + + if (memcmp(&old_stream->src, + &stream->src, + sizeof(struct rect)) != 0) + return false; + + if (memcmp(&old_stream->dst, + &stream->dst, + sizeof(struct rect)) != 0) + return false; + + return true; +} + /* Maximum TMDS single link pixel clock 165MHz */ #define TMDS_MAX_PIXEL_CLOCK_IN_KHZ 165000 diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index ace17d13683a..f60191d9c7e5 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -627,6 +627,8 @@ struct dc_stream_update { bool dc_is_stream_unchanged( struct dc_stream_state *old_stream, struct dc_stream_state *stream); +bool dc_is_stream_scaling_unchanged( + struct dc_stream_state *old_stream, struct dc_stream_state *stream); /* * Set up surface attributes and associate to a stream -- cgit From 5771ec8fe8cb99c0db3115e81b4f69b1543c6982 Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Fri, 6 Oct 2017 15:11:41 -0400 Subject: drm/amd/display: ASSERT on dc_create_state failing. dc_create_state() returns NULL on allocation failure. Raise warning when that happens. Signed-off-by: Leo (Sunpeng) Li Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu') 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 fad40da8422e..e439363ed54b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -702,6 +702,7 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev) dc_release_state(cached_state->context); cached_state->context = dc_create_state(); + ASSERT(cached_state->context); dc_resource_state_copy_construct_current(adev->dm.dc, cached_state->context); for_each_new_crtc_in_state(adev->dm.cached_state, crtc, new_crtc_state, i) { -- cgit From 94c6d735e9ca13018da40f633fd602af6e272cc6 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Fri, 13 Oct 2017 12:42:01 -0400 Subject: drm/amd/display: Fix non-DCN build Acquire_first_split_pipe only makes sense for DCN. Signed-off-by: Harry Wentland Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 2a5c91772473..55feb16b1fd7 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1684,8 +1684,10 @@ enum dc_status resource_map_pool_resources( /* acquire new resources */ pipe_idx = acquire_first_free_pipe(&context->res_ctx, pool, stream); +#ifdef CONFIG_DRM_AMD_DC_DCN1_0 if (pipe_idx < 0) pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream); +#endif if (pipe_idx < 0) return DC_NO_CONTROLLER_RESOURCE; -- cgit From 085b017bf81ad5c76118b3e1a9165c743927556b Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 10 Oct 2017 11:23:50 -0400 Subject: drm/amd/display: Fix warning about overflow v2: convert value to bool using !! Signed-off-by: Harry Wentland Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c index cb94e18cc455..43e9a9959288 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -1042,13 +1042,13 @@ static enum bp_result get_embedded_panel_info_v2_1( info->lcd_timing.misc_info.VERTICAL_CUT_OFF = 0; info->lcd_timing.misc_info.H_REPLICATION_BY2 = - lvds->lcd_timing.miscinfo & ATOM_H_REPLICATIONBY2; + !!(lvds->lcd_timing.miscinfo & ATOM_H_REPLICATIONBY2); info->lcd_timing.misc_info.V_REPLICATION_BY2 = - lvds->lcd_timing.miscinfo & ATOM_V_REPLICATIONBY2; + !!(lvds->lcd_timing.miscinfo & ATOM_V_REPLICATIONBY2); info->lcd_timing.misc_info.COMPOSITE_SYNC = - lvds->lcd_timing.miscinfo & ATOM_COMPOSITESYNC; + !!(lvds->lcd_timing.miscinfo & ATOM_COMPOSITESYNC); info->lcd_timing.misc_info.INTERLACE = - lvds->lcd_timing.miscinfo & ATOM_INTERLACE; + !!(lvds->lcd_timing.miscinfo & ATOM_INTERLACE); /* not provided by VBIOS*/ info->lcd_timing.misc_info.DOUBLE_CLOCK = 0; @@ -1056,7 +1056,7 @@ static enum bp_result get_embedded_panel_info_v2_1( info->ss_id = 0; info->realtek_eDPToLVDS = - (lvds->dplvdsrxid == eDP_TO_LVDS_REALTEK_ID ? 1:0); + !!(lvds->dplvdsrxid == eDP_TO_LVDS_REALTEK_ID); return BP_RESULT_OK; } -- cgit From 1a7e4f7407e8869759be7e715bce18698aadbe98 Mon Sep 17 00:00:00 2001 From: kbuild test robot Date: Fri, 13 Oct 2017 07:35:54 +0800 Subject: drm/amd/dc: fix semicolon.cocci warnings drivers/gpu/drm/amd/amdgpu/../display/dc/gpio/gpio_service.c:134:2-3: Unneeded semicolon Remove unneeded semicolon. Generated by: scripts/coccinelle/misc/semicolon.cocci Fixes: 80be23c57868 ("drm/amd/dc: Add dc display driver (v2)") CC: Harry Wentland Signed-off-by: Fengguang Wu Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c b/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c index d4e5ef64e489..ff9d36b5866e 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c @@ -132,7 +132,7 @@ failure_2: if (slot) kfree(slot); - }; + } failure_1: kfree(service); -- cgit From 2979d7e973464c00154fa4fe029de128de3e51db Mon Sep 17 00:00:00 2001 From: kbuild test robot Date: Fri, 13 Oct 2017 07:17:48 +0800 Subject: drm/amd/display: fix ifnullfree.cocci warnings drivers/gpu/drm/amd/amdgpu/../display/dc/gpio/gpio_service.c:134:3-8: WARNING: NULL check before freeing functions like kfree, debugfs_remove, debugfs_remove_recursive or usb_free_urb is not needed. Maybe consider reorganizing relevant code to avoid passing NULL values. drivers/gpu/drm/amd/amdgpu/../display/dc/gpio/gpio_service.c:175:4-9: WARNING: NULL check before freeing functions like kfree, debugfs_remove, debugfs_remove_recursive or usb_free_urb is not needed. Maybe consider reorganizing relevant code to avoid passing NULL values. NULL check before some freeing functions is not needed. Based on checkpatch warning "kfree(NULL) is safe this check is probably not required" and kfreeaddr.cocci by Julia Lawall. Generated by: scripts/coccinelle/free/ifnullfree.cocci Fixes: f09cd1f46388 ("drm/amd/display: Use kernel alloc/free") Signed-off-by: Fengguang Wu Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c b/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c index ff9d36b5866e..80038e0e610f 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c @@ -130,8 +130,7 @@ failure_2: slot = service->busyness[index_of_id]; - if (slot) - kfree(slot); + kfree(slot); } failure_1: @@ -171,8 +170,7 @@ void dal_gpio_service_destroy( do { uint32_t *slot = (*ptr)->busyness[index_of_id]; - if (slot) - kfree(slot); + kfree(slot); ++index_of_id; } while (index_of_id < GPIO_ID_COUNT); -- cgit From b0f8d4e963de8cd77c237a8ea37799f6f5ce995a Mon Sep 17 00:00:00 2001 From: Andrew Jiang Date: Fri, 6 Oct 2017 18:02:23 -0400 Subject: drm/amd/display: Don't set cursor address is 0 logging as errors This actually happens quite a bit, and having it as an error causes false positive messages when running tests. Signed-off-by: Andrew Jiang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 97f040a25820..5cf69af9693d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -190,7 +190,7 @@ bool dc_stream_set_cursor_attributes( } if (attributes->address.quad_part == 0) { - dm_error("DC: Cursor address is 0!\n"); + dm_output_to_console("DC: Cursor address is 0!\n"); return false; } -- cgit From 4beb50ff5e96014787d8588a78d07e49df0d114a Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Wed, 4 Oct 2017 13:54:35 -0400 Subject: drm/amd/display: Fix warning about uninitialized variable Signed-off-by: Harry Wentland Reviewed-by: Bhawanpreet Lakha Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c index ed301c3b2736..0790f25c7b3b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c @@ -361,7 +361,7 @@ static void program_grph_pixel_format( enum surface_pixel_format format) { uint32_t red_xbar = 0, blue_xbar = 0; /* no swap */ - uint32_t grph_depth, grph_format; + uint32_t grph_depth = 0, grph_format = 0; uint32_t sign = 0, floating = 0; if (format == SURFACE_PIXEL_FORMAT_GRPH_ABGR8888 || -- cgit From c12a7ba543d16c1770fb44670e5eb42ae524c502 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 12 Sep 2017 20:04:48 -0400 Subject: drm/amd/display: Fix up some whitespace in handle_cursor_update Use combo of tabs and spaces Signed-off-by: Harry Wentland Acked-by: Alex Deucher Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') 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 e439363ed54b..60587d6f81d7 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3709,10 +3709,10 @@ static void handle_cursor_update(struct drm_plane *plane, return; DRM_DEBUG_DRIVER("%s: crtc_id=%d with size %d to %d\n", - __func__, - amdgpu_crtc->crtc_id, - plane->state->crtc_w, - plane->state->crtc_h); + __func__, + amdgpu_crtc->crtc_id, + plane->state->crtc_w, + plane->state->crtc_h); ret = get_cursor_position(plane, crtc, &position); if (ret) -- cgit From 2126732fdaaa4101b186a76b4df52f575b5df4e5 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 28 Sep 2017 10:10:22 +1000 Subject: drm/amd/display: drop display_pipe_clocks.c. This code isn't used at all in the kernel tree, perhaps it can wait to be imported when it is. It also does a lot of floating point calcs, so probably good to drop it until it's needed and we can ensure proper fpu accessors. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/Makefile | 2 +- .../gpu/drm/amd/display/dc/dml/display_mode_lib.h | 1 - .../drm/amd/display/dc/dml/display_pipe_clocks.c | 106 --------------------- .../drm/amd/display/dc/dml/display_pipe_clocks.h | 37 ------- 4 files changed, 1 insertion(+), 145 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dml/Makefile b/drivers/gpu/drm/amd/display/dc/dml/Makefile index c6d9d9530d75..87bab8e8139f 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dml/Makefile @@ -13,7 +13,7 @@ CFLAGS_soc_bounding_box.o := -mhard-float -msse -mpreferred-stack-boundary=4 CFLAGS_dml_common_defs.o := -mhard-float -msse -mpreferred-stack-boundary=4 -DML = display_mode_lib.o display_pipe_clocks.o display_rq_dlg_calc.o \ +DML = display_mode_lib.o display_rq_dlg_calc.o \ display_rq_dlg_helpers.o dml1_display_rq_dlg_calc.o \ soc_bounding_box.o dml_common_defs.o display_mode_vba.o diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h index 57f49d29c6b9..ed77f96016dd 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h @@ -29,7 +29,6 @@ #include "dml_common_defs.h" #include "soc_bounding_box.h" #include "display_mode_vba.h" -#include "display_pipe_clocks.h" #include "display_rq_dlg_calc.h" #include "dml1_display_rq_dlg_calc.h" diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.c b/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.c deleted file mode 100644 index 30c379d95156..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2017 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "display_pipe_clocks.h" -#include "display_mode_lib.h" -#include "soc_bounding_box.h" - -display_pipe_clock_st dml_clks_get_pipe_clocks( - struct display_mode_lib *mode_lib, - display_e2e_pipe_params_st *e2e, - unsigned int num_pipes) -{ - display_pipe_clock_st clocks; - bool visited[DC__NUM_PIPES__MAX]; - double max_dispclk = 25.0; //the min dispclk is 25MHz, so keep the min dispclk caculated larger thant 25MHz - double dcfclk, socclk; - unsigned int i, j, k; - unsigned int dsc_inst = 0; - - DTRACE("Calculating pipe clocks..."); - - dcfclk = dml_socbb_voltage_scaling( - &mode_lib->soc, - (enum voltage_state) e2e[0].clks_cfg.voltage).dcfclk_mhz; - socclk = dml_socbb_voltage_scaling( - &mode_lib->soc, - (enum voltage_state) e2e[0].clks_cfg.voltage).socclk_mhz; - clocks.dcfclk_mhz = dcfclk; - clocks.socclk_mhz = socclk; - - max_dispclk = dml_max(max_dispclk, get_dispclk_calculated(mode_lib, e2e, num_pipes)); - clocks.dispclk_mhz = max_dispclk; - DTRACE(" dispclk: %f Mhz", clocks.dispclk_mhz); - DTRACE(" dcfclk: %f Mhz", clocks.dcfclk_mhz); - DTRACE(" socclk: %f Mhz", clocks.socclk_mhz); - - for (k = 0; k < num_pipes; ++k) - visited[k] = false; - - for (i = 0; i < num_pipes; i++) { - clocks.dppclk_mhz[i] = get_dppclk_calculated(mode_lib, e2e, num_pipes, i); - DTRACE(" dppclk%d: %f Mhz", i, clocks.dppclk_mhz[i]); - - if (e2e[i].pipe.src.is_hsplit && !visited[i]) { - unsigned int grp = e2e[i].pipe.src.hsplit_grp; - - for (j = i; j < num_pipes; j++) { - if (e2e[j].pipe.src.hsplit_grp == grp && e2e[j].pipe.src.is_hsplit - && !visited[j]) { - clocks.dscclk_mhz[j] = get_dscclk_calculated( - mode_lib, - e2e, - num_pipes, - dsc_inst); - DTRACE(" dscclk%d: %f Mhz", j, clocks.dscclk_mhz[j]); - visited[j] = true; - } - } - dsc_inst++; - } - - if (!visited[i]) { - unsigned int otg_inst = e2e[i].pipe.dest.otg_inst; - - for (j = i; j < num_pipes; j++) { - // assign dscclk to all planes with this otg, except if they're doing odm combine, or mpc combine - // which is handled by the conditions above, the odm_combine is not required, but it helps make sense of this code - if (e2e[j].pipe.dest.otg_inst == otg_inst - && !e2e[j].pipe.dest.odm_combine && !visited[j]) { - clocks.dscclk_mhz[j] = get_dscclk_calculated( - mode_lib, - e2e, - num_pipes, - dsc_inst); - DTRACE(" dscclk%d: %f Mhz", j, clocks.dscclk_mhz[j]); - visited[j] = true; - } - } - dsc_inst++; - } - } - - return clocks; -} diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.h b/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.h deleted file mode 100644 index a712dc3ecf4b..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2017 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ -#ifndef __DISPLAY_PIPE_CLOCKS_H__ -#define __DISPLAY_PIPE_CLOCKS_H__ - -#include "dml_common_defs.h" - -struct display_mode_lib; - -display_pipe_clock_st dml_clks_get_pipe_clocks( - struct display_mode_lib *mode_lib, - display_e2e_pipe_params_st *e2e, - unsigned int num_pipes); - -#endif -- cgit From 9a5bcd47ea0eb40c8a9e00f6797453c90fbd74d1 Mon Sep 17 00:00:00 2001 From: Eric Bernstein Date: Wed, 11 Oct 2017 15:14:46 -0400 Subject: drm/amd/display: check SR_WATERMARK regs prior to write Signed-off-by: Eric Bernstein Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 144 +++++++++++---------- 1 file changed, 74 insertions(+), 70 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 6e2cec643f31..741b5e06d314 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -481,27 +481,26 @@ static void program_watermarks( "HW register value = 0x%x\n", watermarks->a.pte_meta_urgent_ns, prog_wm_value); - - prog_wm_value = convert_and_clamp( - watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, - refclk_mhz, 0x1fffff); - - REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, - "SR_ENTER_EXIT_WATERMARK_A calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); - - - prog_wm_value = convert_and_clamp( - watermarks->a.cstate_pstate.cstate_exit_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, - "SR_EXIT_WATERMARK_A calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->a.cstate_pstate.cstate_exit_ns, prog_wm_value); - + if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A)) { + prog_wm_value = convert_and_clamp( + watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, + "SR_ENTER_EXIT_WATERMARK_A calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->a.cstate_pstate.cstate_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, + "SR_EXIT_WATERMARK_A calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->a.cstate_pstate.cstate_exit_ns, prog_wm_value); + } prog_wm_value = convert_and_clamp( watermarks->a.cstate_pstate.pstate_change_ns, @@ -533,24 +532,26 @@ static void program_watermarks( watermarks->b.pte_meta_urgent_ns, prog_wm_value); - prog_wm_value = convert_and_clamp( - watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, - "SR_ENTER_WATERMARK_B calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); + if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B)) { + prog_wm_value = convert_and_clamp( + watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, + "SR_ENTER_WATERMARK_B calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); - prog_wm_value = convert_and_clamp( - watermarks->b.cstate_pstate.cstate_exit_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, - "SR_EXIT_WATERMARK_B calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->b.cstate_pstate.cstate_exit_ns, prog_wm_value); + prog_wm_value = convert_and_clamp( + watermarks->b.cstate_pstate.cstate_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, + "SR_EXIT_WATERMARK_B calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->b.cstate_pstate.cstate_exit_ns, prog_wm_value); + } prog_wm_value = convert_and_clamp( watermarks->b.cstate_pstate.pstate_change_ns, @@ -581,25 +582,26 @@ static void program_watermarks( watermarks->c.pte_meta_urgent_ns, prog_wm_value); - prog_wm_value = convert_and_clamp( - watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, - "SR_ENTER_WATERMARK_C calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); + if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C)) { + prog_wm_value = convert_and_clamp( + watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, + "SR_ENTER_WATERMARK_C calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); - prog_wm_value = convert_and_clamp( - watermarks->c.cstate_pstate.cstate_exit_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, - "SR_EXIT_WATERMARK_C calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->c.cstate_pstate.cstate_exit_ns, prog_wm_value); - + prog_wm_value = convert_and_clamp( + watermarks->c.cstate_pstate.cstate_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, + "SR_EXIT_WATERMARK_C calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->c.cstate_pstate.cstate_exit_ns, prog_wm_value); + } prog_wm_value = convert_and_clamp( watermarks->c.cstate_pstate.pstate_change_ns, @@ -629,24 +631,26 @@ static void program_watermarks( watermarks->d.pte_meta_urgent_ns, prog_wm_value); - prog_wm_value = convert_and_clamp( - watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, - "SR_ENTER_WATERMARK_D calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); + if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D)) { + prog_wm_value = convert_and_clamp( + watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, + "SR_ENTER_WATERMARK_D calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); - prog_wm_value = convert_and_clamp( - watermarks->d.cstate_pstate.cstate_exit_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, - "SR_EXIT_WATERMARK_D calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->d.cstate_pstate.cstate_exit_ns, prog_wm_value); + prog_wm_value = convert_and_clamp( + watermarks->d.cstate_pstate.cstate_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, + "SR_EXIT_WATERMARK_D calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->d.cstate_pstate.cstate_exit_ns, prog_wm_value); + } prog_wm_value = convert_and_clamp( -- cgit From 58bb0e63dd99c4bdb84e79a95311bb6899789681 Mon Sep 17 00:00:00 2001 From: Andrew Jiang Date: Tue, 10 Oct 2017 14:36:39 -0400 Subject: drm/amd/display: Correct timings in build scaling params A previous patch set the addressable timing as active + border, when in fact, the VESA standard specifies active as equal to addressable + border. This patch makes the fix more correct and in line with the standard. Signed-off-by: Andrew Jiang Reviewed-by: Andrew Jiang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 55feb16b1fd7..0aca7a3d3dd6 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -850,22 +850,11 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) */ pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; - /** - * KMD sends us h and v_addressable without the borders, which causes us sometimes to draw - * the blank region on-screen. Correct for this by adding the borders back to their - * respective addressable values, and by shifting recout. - */ - timing->h_addressable += timing->h_border_left + timing->h_border_right; - timing->v_addressable += timing->v_border_top + timing->v_border_bottom; - pipe_ctx->plane_res.scl_data.recout.y += timing->v_border_top; pipe_ctx->plane_res.scl_data.recout.x += timing->h_border_left; - timing->v_border_top = 0; - timing->v_border_bottom = 0; - timing->h_border_left = 0; - timing->h_border_right = 0; + pipe_ctx->plane_res.scl_data.recout.y += timing->v_border_top; - pipe_ctx->plane_res.scl_data.h_active = timing->h_addressable; - pipe_ctx->plane_res.scl_data.v_active = timing->v_addressable; + pipe_ctx->plane_res.scl_data.h_active = timing->h_addressable + timing->h_border_left + timing->h_border_right; + pipe_ctx->plane_res.scl_data.v_active = timing->v_addressable + timing->v_border_top + timing->v_border_bottom; /* Taps calculations */ if (pipe_ctx->plane_res.xfm != NULL) -- cgit From 3e5e22154acfd89810d37aa4b3fac14014eb7ca8 Mon Sep 17 00:00:00 2001 From: Andrew Jiang Date: Wed, 11 Oct 2017 14:59:51 -0400 Subject: drm/amd/display: Add chip mask to HDMI retimer/redriver check There were cases where the chip caps held additional bits that led to the retimer/redriver check failing; use the proper mask to ensure that we have only the bits that we care about for the check in question. Signed-off-by: Andrew Jiang Reviewed-by: Charlene Liu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 72e56fbe4a42..004e0b0aad8a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -45,6 +45,7 @@ #include "dce/dce_11_0_enum.h" #include "dce/dce_11_0_sh_mask.h" +#define EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK 0x007C /* Copied from atombios.h */ #define LINK_INFO(...) \ dm_logger_write(dc_ctx->logger, LOG_HW_HOTPLUG, \ __VA_ARGS__) @@ -1345,7 +1346,6 @@ static bool get_ext_hdmi_settings(struct pipe_ctx *pipe_ctx, sizeof(integrated_info->dp2_ext_hdmi_6g_reg_settings)); result = true; break; - default: break; } @@ -1682,7 +1682,9 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) is_over_340mhz = true; if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) { - if ((pipe_ctx->stream->sink->link->chip_caps >> 2) == 0x2) { + unsigned short masked_chip_caps = pipe_ctx->stream->sink->link->chip_caps & + EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK; + if (masked_chip_caps == (0x2 << 2)) { /* DP159, Retimer settings */ eng_id = pipe_ctx->stream_res.stream_enc->id; @@ -1693,7 +1695,7 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) write_i2c_default_retimer_setting(pipe_ctx, is_vga_mode, is_over_340mhz); } - } else if ((pipe_ctx->stream->sink->link->chip_caps >> 2) == 0x1) { + } else if (masked_chip_caps == (0x1 << 2)) { /* PI3EQX1204, Redriver settings */ write_i2c_redriver_setting(pipe_ctx, is_over_340mhz); } -- cgit From 4e527c01aa7a31b7aad98fa5493944891b69238d Mon Sep 17 00:00:00 2001 From: Andrew Jiang Date: Wed, 11 Oct 2017 15:12:58 -0400 Subject: drm/amd/display: Add DIGD case when getting retimer settings One of the HDMI ports map to DIGD, which we did not map to DP3 ext HDMI settings. Add the DIGD case so that we can get proper retimer settings from SBIOS for that port. Signed-off-by: Andrew Jiang Reviewed-by: Charlene Liu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 004e0b0aad8a..c47da645d3b8 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1346,6 +1346,18 @@ static bool get_ext_hdmi_settings(struct pipe_ctx *pipe_ctx, sizeof(integrated_info->dp2_ext_hdmi_6g_reg_settings)); result = true; break; + case ENGINE_ID_DIGD: + settings->slv_addr = integrated_info->dp3_ext_hdmi_slv_addr; + settings->reg_num = integrated_info->dp3_ext_hdmi_6g_reg_num; + settings->reg_num_6g = integrated_info->dp3_ext_hdmi_6g_reg_num; + memmove(settings->reg_settings, + integrated_info->dp3_ext_hdmi_reg_settings, + sizeof(integrated_info->dp3_ext_hdmi_reg_settings)); + memmove(settings->reg_settings_6g, + integrated_info->dp3_ext_hdmi_6g_reg_settings, + sizeof(integrated_info->dp3_ext_hdmi_6g_reg_settings)); + result = true; + break; default: break; } -- cgit From 62c933f9c6bf287b5b911a1eb838bc942eaa7202 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Tue, 10 Oct 2017 14:01:33 -0400 Subject: drm/amd/display: WA for 3 display play video hot plug. Three monitor connected and playing a video will occupy all 4 pipes, if hot plug forth display, commit streams will be failed due to no free pipe can be found. Work around: When forth monitor connected, mark video plane as a fake plane, remove it in dc, keep it in dm and report address to OS, until OS turn off MPO. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 10 +++++----- drivers/gpu/drm/amd/display/dc/core/dc.c | 4 ++-- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 14 ++++++++------ drivers/gpu/drm/amd/display/dc/dc.h | 6 +++--- drivers/gpu/drm/amd/display/dc/inc/core_status.h | 15 ++++++++------- 5 files changed, 26 insertions(+), 23 deletions(-) (limited to 'drivers/gpu') 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 60587d6f81d7..0d1b41298990 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2794,7 +2794,7 @@ int amdgpu_dm_connector_mode_valid(struct drm_connector *connector, stream->src.height = mode->vdisplay; stream->dst = stream->src; - if (dc_validate_stream(adev->dm.dc, stream)) + if (dc_validate_stream(adev->dm.dc, stream) == DC_OK) result = MODE_OK; dc_stream_release(stream); @@ -2839,7 +2839,7 @@ static int dm_crtc_helper_atomic_check(struct drm_crtc *crtc, if (!dm_crtc_state->stream) return 0; - if (dc_validate_stream(dc, dm_crtc_state->stream)) + if (dc_validate_stream(dc, dm_crtc_state->stream) == DC_OK) return 0; return ret; @@ -3034,7 +3034,7 @@ static int dm_plane_atomic_check(struct drm_plane *plane, if (!dm_plane_state->dc_state) return 0; - if (dc_validate_plane(dc, dm_plane_state->dc_state)) + if (dc_validate_plane(dc, dm_plane_state->dc_state) == DC_OK) return 0; return -EINVAL; @@ -4464,10 +4464,10 @@ static int dm_update_crtcs_state(struct dc *dc, crtc->base.id); /* i.e. reset mode */ - if (!dc_remove_stream_from_ctx( + if (dc_remove_stream_from_ctx( dc, dm_state->context, - dm_old_crtc_state->stream)) { + dm_old_crtc_state->stream) != DC_OK) { ret = -EINVAL; goto fail; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 9d750fa29a87..ff6bd384aece 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -793,7 +793,7 @@ bool dc_enable_stereo( * Applies given context to HW and copy it into current context. * It's up to the user to release the src context afterwards. */ -static bool dc_commit_state_no_check(struct dc *dc, struct dc_state *context) +static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *context) { struct dc_bios *dcb = dc->ctx->dc_bios; enum dc_status result = DC_ERROR_UNEXPECTED; @@ -869,7 +869,7 @@ static bool dc_commit_state_no_check(struct dc *dc, struct dc_state *context) dc->hwss.optimize_shared_resources(dc); - return (result == DC_OK); + return result; } bool dc_commit_state(struct dc *dc, struct dc_state *context) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 0aca7a3d3dd6..d1cdf9f8853d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1503,7 +1503,7 @@ enum dc_status dc_add_stream_to_ctx( return res; } -bool dc_remove_stream_from_ctx( +enum dc_status dc_remove_stream_from_ctx( struct dc *dc, struct dc_state *new_ctx, struct dc_stream_state *stream) @@ -2756,7 +2756,7 @@ void resource_build_bit_depth_reduction_params(struct dc_stream_state *stream, fmt_bit_depth->pixel_encoding = pixel_encoding; } -bool dc_validate_stream(struct dc *dc, struct dc_stream_state *stream) +enum dc_status dc_validate_stream(struct dc *dc, struct dc_stream_state *stream) { struct dc *core_dc = dc; struct dc_link *link = stream->sink->link; @@ -2780,14 +2780,16 @@ bool dc_validate_stream(struct dc *dc, struct dc_stream_state *stream) link, &stream->timing); - return res == DC_OK; + return res; } -bool dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state) +enum dc_status dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state) { + enum dc_status res = DC_OK; + /* TODO For now validates pixel format only */ if (dc->res_pool->funcs->validate_plane) - return dc->res_pool->funcs->validate_plane(plane_state, &dc->caps) == DC_OK; + return dc->res_pool->funcs->validate_plane(plane_state, &dc->caps); - return true; + return res; } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index f60191d9c7e5..6c0de093a59e 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -686,7 +686,7 @@ enum dc_status dc_add_stream_to_ctx( struct dc_state *new_ctx, struct dc_stream_state *stream); -bool dc_remove_stream_from_ctx( +enum dc_status dc_remove_stream_from_ctx( struct dc *dc, struct dc_state *new_ctx, struct dc_stream_state *stream); @@ -725,9 +725,9 @@ struct dc_validation_set { uint8_t plane_count; }; -bool dc_validate_stream(struct dc *dc, struct dc_stream_state *stream); +enum dc_status dc_validate_stream(struct dc *dc, struct dc_stream_state *stream); -bool dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state); +enum dc_status dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state); enum dc_status dc_validate_global_state( struct dc *dc, diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_status.h b/drivers/gpu/drm/amd/display/dc/inc/core_status.h index b5759c0e5a2f..01df85641684 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_status.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_status.h @@ -35,13 +35,14 @@ enum dc_status { DC_FAIL_CONTROLLER_VALIDATE = 5, DC_FAIL_ENC_VALIDATE = 6, DC_FAIL_ATTACH_SURFACES = 7, - DC_FAIL_SURFACE_VALIDATE = 8, - DC_NO_DP_LINK_BANDWIDTH = 9, - DC_EXCEED_DONGLE_MAX_CLK = 10, - DC_SURFACE_PIXEL_FORMAT_UNSUPPORTED = 11, - DC_FAIL_BANDWIDTH_VALIDATE = 12, /* BW and Watermark validation */ - DC_FAIL_SCALING = 13, - DC_FAIL_DP_LINK_TRAINING = 14, + DC_FAIL_DETACH_SURFACES = 8, + DC_FAIL_SURFACE_VALIDATE = 9, + DC_NO_DP_LINK_BANDWIDTH = 10, + DC_EXCEED_DONGLE_MAX_CLK = 11, + DC_SURFACE_PIXEL_FORMAT_UNSUPPORTED = 12, + DC_FAIL_BANDWIDTH_VALIDATE = 13, /* BW and Watermark validation */ + DC_FAIL_SCALING = 14, + DC_FAIL_DP_LINK_TRAINING = 15, DC_ERROR_UNEXPECTED = -1 }; -- cgit From dd93752b6483094ec879efbbdb854967355b91ac Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Tue, 10 Oct 2017 17:58:41 -0400 Subject: drm/amd/display: rename dscl functions Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c | 10 +-- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h | 4 +- .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c | 98 +++++++++++----------- 3 files changed, 56 insertions(+), 56 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c index 5960e491159d..74e7c82bdc76 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c @@ -372,7 +372,7 @@ void dpp1_cnv_setup ( } } -void dcn10_set_cursor_attributes( +void dpp1_set_cursor_attributes( struct dpp *dpp_base, const struct dc_cursor_attributes *attr) { @@ -400,7 +400,7 @@ void dcn10_set_cursor_attributes( } -void dcn10_set_cursor_position( +void dpp1_set_cursor_position( struct dpp *dpp_base, const struct dc_cursor_position *pos, const struct dc_cursor_mi_param *param, @@ -440,13 +440,13 @@ static const struct dpp_funcs dcn10_dpp_funcs = { .ipp_program_degamma_pwl = dpp1_set_degamma_pwl, .ipp_setup = dpp1_cnv_setup, .ipp_full_bypass = dpp1_full_bypass, - .set_cursor_attributes = dcn10_set_cursor_attributes, - .set_cursor_position = dcn10_set_cursor_position, + .set_cursor_attributes = dpp1_set_cursor_attributes, + .set_cursor_position = dpp1_set_cursor_position, }; static struct dpp_caps dcn10_dpp_cap = { .dscl_data_proc_format = DSCL_DATA_PRCESSING_FIXED_FORMAT, - .dscl_calc_lb_num_partitions = dscl1_calc_lb_num_partitions, + .dscl_calc_lb_num_partitions = dpp1_dscl_calc_lb_num_partitions, }; /*****************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h index fe6c0aa13da4..a9782b1aba47 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h @@ -1274,12 +1274,12 @@ enum dcn10_input_csc_select { INPUT_CSC_SELECT_COMA }; -bool is_lb_conf_valid( +bool dpp1_dscl_is_lb_conf_valid( int ceil_vratio, int num_partitions, int vtaps); -void dscl1_calc_lb_num_partitions( +void dpp1_dscl_calc_lb_num_partitions( const struct scaler_data *scl_data, enum lb_memory_config lb_config, int *num_part_y, 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 b443a90974b9..cbad36410b32 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 @@ -85,7 +85,7 @@ enum dscl_mode_sel { DSCL_MODE_DSCL_BYPASS = 6 }; -static void dpp_set_overscan( +static void dpp1_dscl_set_overscan( struct dcn10_dpp *dpp, const struct scaler_data *data) { @@ -113,7 +113,7 @@ static void dpp_set_overscan( EXT_OVERSCAN_TOP, top); } -static void dpp_set_otg_blank( +static void dpp1_dscl_set_otg_blank( struct dcn10_dpp *dpp, const struct scaler_data *data) { uint32_t h_blank_start = data->h_active; @@ -130,7 +130,7 @@ static void dpp_set_otg_blank( OTG_V_BLANK_END, v_blank_end); } -static int get_pixel_depth_val(enum lb_pixel_depth depth) +static int dpp1_dscl_get_pixel_depth_val(enum lb_pixel_depth depth) { if (depth == LB_PIXEL_DEPTH_30BPP) return 0; /* 10 bpc */ @@ -146,7 +146,7 @@ static int get_pixel_depth_val(enum lb_pixel_depth depth) } } -static bool is_video_format(enum pixel_format format) +static bool dpp1_dscl_is_video_format(enum pixel_format format) { if (format >= PIXEL_FORMAT_VIDEO_BEGIN && format <= PIXEL_FORMAT_VIDEO_END) @@ -155,7 +155,7 @@ static bool is_video_format(enum pixel_format format) return false; } -static bool is_420_format(enum pixel_format format) +static bool dpp1_dscl_is_420_format(enum pixel_format format) { if (format == PIXEL_FORMAT_420BPP8 || format == PIXEL_FORMAT_420BPP10) @@ -164,7 +164,7 @@ static bool is_420_format(enum pixel_format format) return false; } -static enum dscl_mode_sel get_dscl_mode( +static enum dscl_mode_sel dpp1_dscl_get_dscl_mode( struct dpp *dpp_base, const struct scaler_data *data, bool dbg_always_scale) @@ -184,8 +184,8 @@ static enum dscl_mode_sel get_dscl_mode( && !dbg_always_scale) return DSCL_MODE_SCALING_444_BYPASS; - if (!is_420_format(data->format)) { - if (is_video_format(data->format)) + if (!dpp1_dscl_is_420_format(data->format)) { + if (dpp1_dscl_is_video_format(data->format)) return DSCL_MODE_SCALING_444_YCBCR_ENABLE; else return DSCL_MODE_SCALING_444_RGB_ENABLE; @@ -198,7 +198,7 @@ static enum dscl_mode_sel get_dscl_mode( return DSCL_MODE_SCALING_420_YCBCR_ENABLE; } -static void dpp_set_lb( +static void dpp1_dscl_set_lb( struct dcn10_dpp *dpp, const struct line_buffer_params *lb_params, enum lb_memory_config mem_size_config) @@ -206,7 +206,7 @@ static void dpp_set_lb( /* LB */ if (dpp->base.caps->dscl_data_proc_format == DSCL_DATA_PRCESSING_FIXED_FORMAT) { /* DSCL caps: pixel data processed in fixed format */ - uint32_t pixel_depth = get_pixel_depth_val(lb_params->depth); + uint32_t pixel_depth = dpp1_dscl_get_pixel_depth_val(lb_params->depth); uint32_t dyn_pix_depth = lb_params->dynamic_pixel_depth; REG_SET_7(LB_DATA_FORMAT, 0, @@ -224,7 +224,7 @@ static void dpp_set_lb( LB_MAX_PARTITIONS, 63); } -static const uint16_t *get_filter_coeffs_64p(int taps, struct fixed31_32 ratio) +static const uint16_t *dpp1_dscl_get_filter_coeffs_64p(int taps, struct fixed31_32 ratio) { if (taps == 8) return get_filter_8tap_64p(ratio); @@ -249,7 +249,7 @@ static const uint16_t *get_filter_coeffs_64p(int taps, struct fixed31_32 ratio) } } -static void dpp_set_scaler_filter( +static void dpp1_dscl_set_scaler_filter( struct dcn10_dpp *dpp, uint32_t taps, enum dcn10_coef_filter_type_sel filter_type, @@ -287,7 +287,7 @@ static void dpp_set_scaler_filter( } -static void dpp_set_scl_filter( +static void dpp1_dscl_set_scl_filter( struct dcn10_dpp *dpp, const struct scaler_data *scl_data, bool chroma_coef_mode) @@ -325,18 +325,18 @@ static void dpp_set_scl_filter( if (!v_2tap_hardcode_coef_en || !h_2tap_hardcode_coef_en) { bool filter_updated = false; - filter_h = get_filter_coeffs_64p( + filter_h = dpp1_dscl_get_filter_coeffs_64p( scl_data->taps.h_taps, scl_data->ratios.horz); - filter_v = get_filter_coeffs_64p( + filter_v = dpp1_dscl_get_filter_coeffs_64p( scl_data->taps.v_taps, scl_data->ratios.vert); filter_updated = (filter_h && (filter_h != dpp->filter_h)) || (filter_v && (filter_v != dpp->filter_v)); if (chroma_coef_mode) { - filter_h_c = get_filter_coeffs_64p( + filter_h_c = dpp1_dscl_get_filter_coeffs_64p( scl_data->taps.h_taps_c, scl_data->ratios.horz_c); - filter_v_c = get_filter_coeffs_64p( + filter_v_c = dpp1_dscl_get_filter_coeffs_64p( scl_data->taps.v_taps_c, scl_data->ratios.vert_c); filter_updated = filter_updated || (filter_h_c && (filter_h_c != dpp->filter_h_c)) || (filter_v_c && (filter_v_c != dpp->filter_v_c)); @@ -346,25 +346,25 @@ static void dpp_set_scl_filter( uint32_t scl_mode = REG_READ(SCL_MODE); if (!h_2tap_hardcode_coef_en && filter_h) { - dpp_set_scaler_filter( + dpp1_dscl_set_scaler_filter( dpp, scl_data->taps.h_taps, SCL_COEF_LUMA_HORZ_FILTER, filter_h); } dpp->filter_h = filter_h; if (!v_2tap_hardcode_coef_en && filter_v) { - dpp_set_scaler_filter( + dpp1_dscl_set_scaler_filter( dpp, scl_data->taps.v_taps, SCL_COEF_LUMA_VERT_FILTER, filter_v); } dpp->filter_v = filter_v; if (chroma_coef_mode) { if (!h_2tap_hardcode_coef_en && filter_h_c) { - dpp_set_scaler_filter( + dpp1_dscl_set_scaler_filter( dpp, scl_data->taps.h_taps_c, SCL_COEF_CHROMA_HORZ_FILTER, filter_h_c); } if (!v_2tap_hardcode_coef_en && filter_v_c) { - dpp_set_scaler_filter( + dpp1_dscl_set_scaler_filter( dpp, scl_data->taps.v_taps_c, SCL_COEF_CHROMA_VERT_FILTER, filter_v_c); } @@ -384,7 +384,7 @@ static void dpp_set_scl_filter( } } -static int get_lb_depth_bpc(enum lb_pixel_depth depth) +static int dpp1_dscl_get_lb_depth_bpc(enum lb_pixel_depth depth) { if (depth == LB_PIXEL_DEPTH_30BPP) return 10; @@ -400,7 +400,7 @@ static int get_lb_depth_bpc(enum lb_pixel_depth depth) } } -void dscl1_calc_lb_num_partitions( +void dpp1_dscl_calc_lb_num_partitions( const struct scaler_data *scl_data, enum lb_memory_config lb_config, int *num_part_y, @@ -410,7 +410,7 @@ void dscl1_calc_lb_num_partitions( scl_data->viewport.width : scl_data->recout.width; int line_size_c = scl_data->viewport_c.width < scl_data->recout.width ? scl_data->viewport_c.width : scl_data->recout.width; - int lb_bpc = get_lb_depth_bpc(scl_data->lb_params.depth); + int lb_bpc = dpp1_dscl_get_lb_depth_bpc(scl_data->lb_params.depth); int memory_line_size_y = (line_size * lb_bpc + 71) / 72; /* +71 to ceil */ int memory_line_size_c = (line_size_c * lb_bpc + 71) / 72; /* +71 to ceil */ int memory_line_size_a = (line_size + 5) / 6; /* +5 to ceil */ @@ -449,7 +449,7 @@ void dscl1_calc_lb_num_partitions( } -bool is_lb_conf_valid(int ceil_vratio, int num_partitions, int vtaps) +bool dpp1_dscl_is_lb_conf_valid(int ceil_vratio, int num_partitions, int vtaps) { if (ceil_vratio > 2) return vtaps <= (num_partitions - ceil_vratio + 2); @@ -458,7 +458,7 @@ bool is_lb_conf_valid(int ceil_vratio, int num_partitions, int vtaps) } /*find first match configuration which meets the min required lb size*/ -static enum lb_memory_config find_lb_memory_config(struct dcn10_dpp *dpp, +static enum lb_memory_config dpp1_dscl_find_lb_memory_config(struct dcn10_dpp *dpp, const struct scaler_data *scl_data) { int num_part_y, num_part_c; @@ -474,15 +474,15 @@ static enum lb_memory_config find_lb_memory_config(struct dcn10_dpp *dpp, dpp->base.caps->dscl_calc_lb_num_partitions( scl_data, LB_MEMORY_CONFIG_1, &num_part_y, &num_part_c); - if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) - && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)) + if (dpp1_dscl_is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) + && dpp1_dscl_is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)) return LB_MEMORY_CONFIG_1; dpp->base.caps->dscl_calc_lb_num_partitions( scl_data, LB_MEMORY_CONFIG_2, &num_part_y, &num_part_c); - if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) - && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)) + if (dpp1_dscl_is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) + && dpp1_dscl_is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)) return LB_MEMORY_CONFIG_2; if (scl_data->format == PIXEL_FORMAT_420BPP8 @@ -490,8 +490,8 @@ static enum lb_memory_config find_lb_memory_config(struct dcn10_dpp *dpp, dpp->base.caps->dscl_calc_lb_num_partitions( scl_data, LB_MEMORY_CONFIG_3, &num_part_y, &num_part_c); - if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) - && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)) + if (dpp1_dscl_is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) + && dpp1_dscl_is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)) return LB_MEMORY_CONFIG_3; } @@ -499,34 +499,34 @@ static enum lb_memory_config find_lb_memory_config(struct dcn10_dpp *dpp, scl_data, LB_MEMORY_CONFIG_0, &num_part_y, &num_part_c); /*Ensure we can support the requested number of vtaps*/ - ASSERT(is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) - && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)); + ASSERT(dpp1_dscl_is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) + && dpp1_dscl_is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)); return LB_MEMORY_CONFIG_0; } -void dpp_set_scaler_auto_scale( +void dpp1_dscl_set_scaler_auto_scale( struct dpp *dpp_base, const struct scaler_data *scl_data) { enum lb_memory_config lb_config; struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); - enum dscl_mode_sel dscl_mode = get_dscl_mode( + enum dscl_mode_sel dscl_mode = dpp1_dscl_get_dscl_mode( dpp_base, scl_data, dpp_base->ctx->dc->debug.always_scale); bool ycbcr = scl_data->format >= PIXEL_FORMAT_VIDEO_BEGIN && scl_data->format <= PIXEL_FORMAT_VIDEO_END; - dpp_set_overscan(dpp, scl_data); + dpp1_dscl_set_overscan(dpp, scl_data); - dpp_set_otg_blank(dpp, scl_data); + dpp1_dscl_set_otg_blank(dpp, scl_data); REG_UPDATE(SCL_MODE, DSCL_MODE, dscl_mode); if (dscl_mode == DSCL_MODE_DSCL_BYPASS) return; - lb_config = find_lb_memory_config(dpp, scl_data); - dpp_set_lb(dpp, &scl_data->lb_params, lb_config); + lb_config = dpp1_dscl_find_lb_memory_config(dpp, scl_data); + dpp1_dscl_set_lb(dpp, &scl_data->lb_params, lb_config); if (dscl_mode == DSCL_MODE_SCALING_444_BYPASS) return; @@ -554,11 +554,11 @@ void dpp_set_scaler_auto_scale( SCL_V_NUM_TAPS_C, scl_data->taps.v_taps_c - 1, SCL_H_NUM_TAPS_C, scl_data->taps.h_taps_c - 1); - dpp_set_scl_filter(dpp, scl_data, ycbcr); + dpp1_dscl_set_scl_filter(dpp, scl_data, ycbcr); } -static void dpp_set_manual_ratio_init( +static void dpp1_dscl_set_manual_ratio_init( struct dcn10_dpp *dpp, const struct scaler_data *data) { uint32_t init_frac = 0; @@ -618,7 +618,7 @@ static void dpp_set_manual_ratio_init( -static void dpp_set_recout( +static void dpp1_dscl_set_recout( struct dcn10_dpp *dpp, const struct rect *recout) { REG_SET_2(RECOUT_START, 0, @@ -643,13 +643,13 @@ void dpp1_dscl_set_scaler_manual_scale( { enum lb_memory_config lb_config; struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); - enum dscl_mode_sel dscl_mode = get_dscl_mode( + enum dscl_mode_sel dscl_mode = dpp1_dscl_get_dscl_mode( dpp_base, scl_data, dpp_base->ctx->dc->debug.always_scale); bool ycbcr = scl_data->format >= PIXEL_FORMAT_VIDEO_BEGIN && scl_data->format <= PIXEL_FORMAT_VIDEO_END; /* Recout */ - dpp_set_recout(dpp, &scl_data->recout); + dpp1_dscl_set_recout(dpp, &scl_data->recout); /* MPC Size */ REG_SET_2(MPC_SIZE, 0, @@ -665,8 +665,8 @@ void dpp1_dscl_set_scaler_manual_scale( return; /* LB */ - lb_config = find_lb_memory_config(dpp, scl_data); - dpp_set_lb(dpp, &scl_data->lb_params, lb_config); + lb_config = dpp1_dscl_find_lb_memory_config(dpp, scl_data); + dpp1_dscl_set_lb(dpp, &scl_data->lb_params, lb_config); if (dscl_mode == DSCL_MODE_SCALING_444_BYPASS) return; @@ -689,7 +689,7 @@ void dpp1_dscl_set_scaler_manual_scale( SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_RGB_Y); /* Manually calculate scale ratio and init values */ - dpp_set_manual_ratio_init(dpp, scl_data); + dpp1_dscl_set_manual_ratio_init(dpp, scl_data); /* HTaps/VTaps */ REG_SET_4(SCL_TAP_CONTROL, 0, @@ -698,5 +698,5 @@ void dpp1_dscl_set_scaler_manual_scale( SCL_V_NUM_TAPS_C, scl_data->taps.v_taps_c - 1, SCL_H_NUM_TAPS_C, scl_data->taps.h_taps_c - 1); - dpp_set_scl_filter(dpp, scl_data, ycbcr); + dpp1_dscl_set_scl_filter(dpp, scl_data, ycbcr); } -- cgit From 6b29f4424e39d279fa1c7b465bc1b508ea6fc98e Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Thu, 12 Oct 2017 10:59:42 -0400 Subject: drm/amd/display: DAL 3.1.06 Raven bug fixes - RS3 MPO stability improvement - SLS fixes - AM4 fixes DAL 3.1 - merge in upstream patches from DRM maintainer Dave Arilie - hubp, dpp HW objects Signed-off-by: Tony Cheng Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 6c0de093a59e..37a779ead4fb 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -38,7 +38,8 @@ #include "inc/compressor.h" #include "dml/display_mode_lib.h" -#define DC_VER "3.1.05" +#define DC_VER "3.1.06" + #define MAX_SURFACES 3 #define MAX_STREAMS 6 -- cgit From b9b171fffc9358be9e98cbc2bc7ef3fbe029f170 Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Tue, 10 Oct 2017 16:28:02 -0400 Subject: drm/amd/display: LGD panel willl flash line under window Signed-off-by: Hersen Wu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 5e5763c0ee94..e8b8daeeed97 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1399,6 +1399,15 @@ static void power_down_encoders(struct dc *dc) int i; enum connector_id connector_id; enum signal_type signal = SIGNAL_TYPE_NONE; + + /* do not know BIOS back-front mapping, simply blank all. It will not + * hurt for non-DP + */ + for (i = 0; i < dc->res_pool->stream_enc_count; i++) { + dc->res_pool->stream_enc[i]->funcs->dp_blank( + dc->res_pool->stream_enc[i]); + } + for (i = 0; i < dc->link_count; i++) { connector_id = dal_graphics_object_id_get_connector_id(dc->links[i]->link_id); if ((connector_id == CONNECTOR_ID_DISPLAY_PORT) || -- cgit From 75e68891200e3404fb3283e47ed74184932a748a Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 12 Oct 2017 12:27:48 -0400 Subject: drm/amd/display: Move OS types to os_types.h Some of this stuff is not really dm_services Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dm_services.h | 45 ---------------------------- drivers/gpu/drm/amd/display/dc/os_types.h | 40 +++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 45 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dm_services.h b/drivers/gpu/drm/amd/display/dc/dm_services.h index d6b3b832986b..c8190c38a644 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services.h @@ -38,51 +38,6 @@ #undef DEPRECATED -/* - * - * general debug capabilities - * - */ -#if defined(CONFIG_DEBUG_KERNEL) || defined(CONFIG_DEBUG_DRIVER) - -#if defined(CONFIG_HAVE_KGDB) || defined(CONFIG_KGDB) -#define ASSERT_CRITICAL(expr) do { \ - if (WARN_ON(!(expr))) { \ - kgdb_breakpoint(); \ - } \ -} while (0) -#else -#define ASSERT_CRITICAL(expr) do { \ - if (WARN_ON(!(expr))) { \ - ; \ - } \ -} while (0) -#endif - -#if defined(CONFIG_DEBUG_KERNEL_DC) -#define ASSERT(expr) ASSERT_CRITICAL(expr) - -#else -#define ASSERT(expr) WARN_ON(!(expr)) -#endif - -#define BREAK_TO_DEBUGGER() ASSERT(0) - -#endif /* CONFIG_DEBUG_KERNEL || CONFIG_DEBUG_DRIVER */ - -#define DC_ERR(...) do { \ - dm_error(__VA_ARGS__); \ - BREAK_TO_DEBUGGER(); \ -} while (0) - -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) -#include -#endif - -#define dm_alloc(size) kzalloc(size, GFP_KERNEL) -#define dm_realloc(ptr, size) krealloc(ptr, size, GFP_KERNEL) -#define dm_free(ptr) kfree(ptr) - irq_handler_idx dm_register_interrupt( struct dc_context *ctx, struct dc_interrupt_params *int_params, diff --git a/drivers/gpu/drm/amd/display/dc/os_types.h b/drivers/gpu/drm/amd/display/dc/os_types.h index e0cd5278aae8..86170b40b5c5 100644 --- a/drivers/gpu/drm/amd/display/dc/os_types.h +++ b/drivers/gpu/drm/amd/display/dc/os_types.h @@ -56,5 +56,45 @@ #endif +/* + * + * general debug capabilities + * + */ +#if defined(CONFIG_DEBUG_KERNEL) || defined(CONFIG_DEBUG_DRIVER) + +#if defined(CONFIG_HAVE_KGDB) || defined(CONFIG_KGDB) +#define ASSERT_CRITICAL(expr) do { \ + if (WARN_ON(!(expr))) { \ + kgdb_breakpoint(); \ + } \ +} while (0) +#else +#define ASSERT_CRITICAL(expr) do { \ + if (WARN_ON(!(expr))) { \ + ; \ + } \ +} while (0) +#endif + +#if defined(CONFIG_DEBUG_KERNEL_DC) +#define ASSERT(expr) ASSERT_CRITICAL(expr) + +#else +#define ASSERT(expr) WARN_ON(!(expr)) +#endif + +#define BREAK_TO_DEBUGGER() ASSERT(0) + +#endif /* CONFIG_DEBUG_KERNEL || CONFIG_DEBUG_DRIVER */ + +#define DC_ERR(...) do { \ + dm_error(__VA_ARGS__); \ + BREAK_TO_DEBUGGER(); \ +} while (0) + +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +#include +#endif #endif /* _OS_TYPES_H_ */ -- cgit From 1bed4d09a4cc5a7d4449da86832d9bd816ae44ff Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 12 Sep 2017 17:10:25 +0100 Subject: drm/amd/display: Fix one more place for dc_stream_state leak One more thing that happened due to uneven applying of patches. This mirrors what Darren Salt fixed. Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') 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 0d1b41298990..58143fe49e4a 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4484,7 +4484,7 @@ static int dm_update_crtcs_state(struct dc *dc, * TODO: need to dig out the root cause of that */ if (!aconnector || (!aconnector->dc_sink && aconnector->mst_port)) - continue; + goto next_crtc; if (modereset_required(new_crtc_state)) goto next_crtc; -- cgit From bb16bee4b394bafd6168c7719b7b07e19d1f0ce1 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 12 Oct 2017 14:15:26 -0400 Subject: drm/amd/display: Reduce stack size of commit_planes_to_stream This function likes to blow 1024 stack size when something is added to the addr struct. For now just dynamically allocate. Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index ff6bd384aece..7a0593d4ca62 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -926,9 +926,9 @@ bool dc_commit_planes_to_stream( struct dc_state *state) { struct dc_surface_update updates[MAX_SURFACES]; - struct dc_flip_addrs flip_addr[MAX_SURFACES]; - struct dc_plane_info plane_info[MAX_SURFACES]; - struct dc_scaling_info scaling_info[MAX_SURFACES]; + struct dc_flip_addrs *flip_addr; + struct dc_plane_info *plane_info; + struct dc_scaling_info *scaling_info; int i; struct dc_stream_update *stream_update = kzalloc(sizeof(struct dc_stream_update), GFP_KERNEL); @@ -938,10 +938,14 @@ bool dc_commit_planes_to_stream( return false; } + flip_addr = kcalloc(MAX_SURFACES, sizeof(struct dc_flip_addrs), + GFP_KERNEL); + plane_info = kcalloc(MAX_SURFACES, sizeof(struct dc_plane_info), + GFP_KERNEL); + scaling_info = kcalloc(MAX_SURFACES, sizeof(struct dc_scaling_info), + GFP_KERNEL); + memset(updates, 0, sizeof(updates)); - memset(flip_addr, 0, sizeof(flip_addr)); - memset(plane_info, 0, sizeof(plane_info)); - memset(scaling_info, 0, sizeof(scaling_info)); stream_update->src = dc_stream->src; stream_update->dst = dc_stream->dst; @@ -980,6 +984,9 @@ bool dc_commit_planes_to_stream( new_plane_count, dc_stream, stream_update, plane_states, state); + kfree(flip_addr); + kfree(plane_info); + kfree(scaling_info); kfree(stream_update); return true; } -- cgit From 9e7da3268aedd21d559f0f27406874cf92ff582a Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Thu, 12 Oct 2017 22:18:12 -0400 Subject: drm/amd/display: dal 3.1.07 - regression fixes in dal 3.1.06 - more linux upstream backport Signed-off-by: Tony Cheng Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 37a779ead4fb..9d8f4a55c74e 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -38,8 +38,7 @@ #include "inc/compressor.h" #include "dml/display_mode_lib.h" -#define DC_VER "3.1.06" - +#define DC_VER "3.1.07" #define MAX_SURFACES 3 #define MAX_STREAMS 6 -- cgit From be11749177d74b2e2c8a4cf2526e88355c40ad00 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Fri, 13 Oct 2017 15:12:04 -0400 Subject: drm/amd/display: Remove redundant condition in dml vba Found by 0-day https://lists.freedesktop.org/archives/dri-devel/2017-October/154698.html Signed-off-by: Harry Wentland Reviewed-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c index a11b37c50d96..117ec11ef304 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c @@ -3463,7 +3463,7 @@ bool Calculate256BBlockSizes( unsigned int *BlockWidth256BytesC) { if ((SourcePixelFormat == dm_444_64 || SourcePixelFormat == dm_444_32 - || SourcePixelFormat == dm_444_16 || SourcePixelFormat == dm_444_16 + || SourcePixelFormat == dm_444_16 || SourcePixelFormat == dm_444_8)) { if (SurfaceTiling == dm_sw_linear) { *BlockHeight256BytesY = 1; -- cgit From e92b44fdee3ec0b679bacdb9c7e95e55699167f0 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Thu, 5 Oct 2017 14:38:46 -0400 Subject: drm/amd/display: default force_single_disp_pipe_split = 1 on RV 1080p idle, stutter efficiency goes up from 95.8% to 97.8% result in 5mW saving from APU and 8mW saving from DDR4 Signed-off-by: Tony Cheng Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index d47ff7e6a525..d911590d08bc 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -430,6 +430,7 @@ static const struct dc_debug debug_defaults_drv = { .disable_pplib_wm_range = false, .pplib_wm_report_mode = WM_REPORT_DEFAULT, .pipe_split_policy = MPC_SPLIT_AVOID_MULT_DISP, + .force_single_disp_pipe_split = true, .disable_dcc = DCC_ENABLE, .voltage_align_fclk = true, .disable_stereo_support = true, -- cgit From f63d89066fb29a47ad3e9530214de7ea87e82e57 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 13 Oct 2017 12:53:38 -0400 Subject: drm/amd/display: change dml numdpp var to uint Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c | 14 +++++++------- drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c index 117ec11ef304..ffd1d8d10bdf 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c @@ -1158,7 +1158,7 @@ static bool CalculatePrefetchSchedule( else if (PageTableLevels == 3) *Tno_bw = UrgentExtraLatency; else - Tno_bw = 0; + *Tno_bw = 0; } else if (DCCEnable) *Tno_bw = LineTime; else @@ -4721,14 +4721,14 @@ static void ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_ && mode_lib->vba.SwathWidthYSingleDPP[k] <= mode_lib->vba.MaximumSwathWidth[k] && mode_lib->vba.ODMCombineEnablePerState[i][k] == false) { - mode_lib->vba.NoOfDPP[i][k] = 1.0; + mode_lib->vba.NoOfDPP[i][k] = 1; mode_lib->vba.RequiredDPPCLK[i][k] = mode_lib->vba.MinDPPCLKUsingSingleDPP[k] * (1.0 + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading / 100.0); } else { - mode_lib->vba.NoOfDPP[i][k] = 2.0; + mode_lib->vba.NoOfDPP[i][k] = 2; mode_lib->vba.RequiredDPPCLK[i][k] = mode_lib->vba.MinDPPCLKUsingSingleDPP[k] * (1.0 @@ -4790,14 +4790,14 @@ static void ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_ <= mode_lib->vba.MaximumSwathWidth[k] && mode_lib->vba.ODMCombineEnablePerState[i][k] == false) { - mode_lib->vba.NoOfDPP[i][k] = 1.0; + mode_lib->vba.NoOfDPP[i][k] = 1; mode_lib->vba.RequiredDPPCLK[i][k] = mode_lib->vba.MinDPPCLKUsingSingleDPP[k] * (1.0 + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading / 100.0); } else { - mode_lib->vba.NoOfDPP[i][k] = 2.0; + mode_lib->vba.NoOfDPP[i][k] = 2; mode_lib->vba.RequiredDPPCLK[i][k] = mode_lib->vba.MinDPPCLKUsingSingleDPP[k] * (1.0 @@ -4833,14 +4833,14 @@ static void ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_ mode_lib->vba.ODMCombineEnablePerState[i][k] = false; if (mode_lib->vba.SwathWidthYSingleDPP[k] <= mode_lib->vba.MaximumSwathWidth[k]) { - mode_lib->vba.NoOfDPP[i][k] = 1.0; + mode_lib->vba.NoOfDPP[i][k] = 1; mode_lib->vba.RequiredDPPCLK[i][k] = mode_lib->vba.MinDPPCLKUsingSingleDPP[k] * (1.0 + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading / 100.0); } else { - mode_lib->vba.NoOfDPP[i][k] = 2.0; + mode_lib->vba.NoOfDPP[i][k] = 2; mode_lib->vba.RequiredDPPCLK[i][k] = mode_lib->vba.MinDPPCLKUsingSingleDPP[k] * (1.0 diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h index 63ad4a7bfeb5..4b8c1b911f17 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h @@ -489,7 +489,7 @@ struct vba_vars_st { double CursorBufferSize; double CursorChunkSize; unsigned int Mode; - double NoOfDPP[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + unsigned int NoOfDPP[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; double OutputLinkDPLanes[DC__NUM_DPP__MAX]; double SwathWidthYPerState[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; double SwathHeightYPerState[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; -- cgit From 3eea71e36fcd04d0a3e735ee3cf4dbbe9934e3c8 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Thu, 12 Oct 2017 22:45:25 -0400 Subject: drm/amd/display: Minor update to DML Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 3 ++- drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c | 6 ------ drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h | 1 - drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h | 7 ++----- drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c | 9 +-------- drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h | 1 - 6 files changed, 5 insertions(+), 22 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 741b5e06d314..63c2f5266142 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2015,10 +2015,11 @@ static void dcn10_power_on_fe( plane_state->dst_rect.height); dm_logger_write(dc->ctx->logger, LOG_DC, - "Pipe %d: width, height, x, y\n" + "Pipe %d: width, height, x, y format:%d\n" "viewport:%d, %d, %d, %d\n" "recout: %d, %d, %d, %d\n", pipe_ctx->pipe_idx, + plane_state->format, pipe_ctx->plane_res.scl_data.viewport.width, pipe_ctx->plane_res.scl_data.viewport.height, pipe_ctx->plane_res.scl_data.viewport.x, diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c index 09d232806de7..4c31fa54af39 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c @@ -127,17 +127,11 @@ static void set_ip_params(struct _vcs_dpi_ip_params_st *ip, enum dml_project pro } } -static void set_mode_evaluation(struct _vcs_dpi_mode_evaluation_st *me, enum dml_project project) -{ - me->voltage_override = dm_vmin; -} - void dml_init_instance(struct display_mode_lib *lib, enum dml_project project) { if (lib->project != project) { set_soc_bounding_box(&lib->soc, project); set_ip_params(&lib->ip, project); - set_mode_evaluation(&lib->me, project); lib->project = project; } } diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h index ed77f96016dd..26f4f2a3d90d 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h @@ -40,7 +40,6 @@ enum dml_project { struct display_mode_lib { struct _vcs_dpi_ip_params_st ip; struct _vcs_dpi_soc_bounding_box_st soc; - struct _vcs_dpi_mode_evaluation_st me; enum dml_project project; struct vba_vars_st vba; struct dal_logger *logger; diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h index 27e20460c71b..baf182177736 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h @@ -27,7 +27,6 @@ typedef struct _vcs_dpi_voltage_scaling_st voltage_scaling_st; typedef struct _vcs_dpi_soc_bounding_box_st soc_bounding_box_st; -typedef struct _vcs_dpi_mode_evaluation_st mode_evaluation_st; typedef struct _vcs_dpi_ip_params_st ip_params_st; typedef struct _vcs_dpi_display_pipe_source_params_st display_pipe_source_params_st; typedef struct _vcs_dpi_display_output_params_st display_output_params_st; @@ -60,10 +59,6 @@ typedef struct _vcs_dpi_display_dlg_prefetch_param_st display_dlg_prefetch_param typedef struct _vcs_dpi_display_pipe_clock_st display_pipe_clock_st; typedef struct _vcs_dpi_display_arb_params_st display_arb_params_st; -struct _vcs_dpi_mode_evaluation_st { - int voltage_override; -}; - struct _vcs_dpi_voltage_scaling_st { int state; double dscclk_mhz; @@ -96,6 +91,7 @@ struct _vcs_dpi_soc_bounding_box_st { double fabric_datapath_to_dcn_data_return_bytes; double dcn_downspread_percent; double dispclk_dppclk_vco_speed_mhz; + double dfs_vco_period_ps; unsigned int round_trip_ping_latency_dcfclk_cycles; unsigned int urgent_out_of_order_return_per_channel_bytes; unsigned int channel_interleave_bytes; @@ -105,6 +101,7 @@ struct _vcs_dpi_soc_bounding_box_st { double dram_clock_change_latency_us; double writeback_dram_clock_change_latency_us; unsigned int return_bus_width_bytes; + unsigned int voltage_override; double xfc_bus_transport_time_us; double xfc_xbuf_latency_tolerance_us; struct _vcs_dpi_voltage_scaling_st clock_limits[7]; diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c index ffd1d8d10bdf..e337c2cf2c09 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c @@ -251,19 +251,14 @@ unsigned int dml_get_voltage_level( const display_e2e_pipe_params_st *pipes, unsigned int num_pipes) { - bool need_recalculate = memcmp( - &mode_lib->soc, - &mode_lib->vba.soc, - sizeof(mode_lib->vba.soc)) != 0 + bool need_recalculate = memcmp(&mode_lib->soc, &mode_lib->vba.soc, sizeof(mode_lib->vba.soc)) != 0 || memcmp(&mode_lib->ip, &mode_lib->vba.ip, sizeof(mode_lib->vba.ip)) != 0 - || memcmp(&mode_lib->me, &mode_lib->vba.me, sizeof(mode_lib->vba.me)) != 0 || num_pipes != mode_lib->vba.cache_num_pipes || memcmp(pipes, mode_lib->vba.cache_pipes, sizeof(display_e2e_pipe_params_st) * num_pipes) != 0; mode_lib->vba.soc = mode_lib->soc; mode_lib->vba.ip = mode_lib->ip; - mode_lib->vba.me = mode_lib->me; memcpy(mode_lib->vba.cache_pipes, pipes, sizeof(*pipes) * num_pipes); mode_lib->vba.cache_num_pipes = num_pipes; @@ -772,7 +767,6 @@ static void recalculate_params( // This is only safe to use memcmp because there are non-POD types in struct display_mode_lib if (memcmp(&mode_lib->soc, &mode_lib->vba.soc, sizeof(mode_lib->vba.soc)) != 0 || memcmp(&mode_lib->ip, &mode_lib->vba.ip, sizeof(mode_lib->vba.ip)) != 0 - || memcmp(&mode_lib->me, &mode_lib->vba.me, sizeof(mode_lib->vba.me)) != 0 || num_pipes != mode_lib->vba.cache_num_pipes || memcmp( pipes, @@ -780,7 +774,6 @@ static void recalculate_params( sizeof(display_e2e_pipe_params_st) * num_pipes) != 0) { mode_lib->vba.soc = mode_lib->soc; mode_lib->vba.ip = mode_lib->ip; - mode_lib->vba.me = mode_lib->me; memcpy(mode_lib->vba.cache_pipes, pipes, sizeof(*pipes) * num_pipes); mode_lib->vba.cache_num_pipes = num_pipes; recalculate(mode_lib); diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h index 4b8c1b911f17..c8d1a0539541 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h @@ -98,7 +98,6 @@ bool Calculate256BBlockSizes( struct vba_vars_st { ip_params_st ip; soc_bounding_box_st soc; - mode_evaluation_st me; unsigned int MaximumMaxVStartupLines; double cursor_bw[DC__NUM_DPP__MAX]; -- cgit From 565f26a39d8e49745fda00d2303138aea831fd29 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 16 Oct 2017 20:10:00 -0400 Subject: drm/amd/display: Small comment on dc_commit_planes_to_stream Having one struct on the stack was somewhat confusing. Also mention that the whole function should eventually go. Signed-off-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 7a0593d4ca62..a71392ffc46d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -918,6 +918,12 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) return true; } +/* + * TODO this whole function needs to go + * + * dc_surface_update is needlessly complex. See if we can just replace this + * with a dc_plane_state and follow the atomic model a bit more closely here. + */ bool dc_commit_planes_to_stream( struct dc *dc, struct dc_plane_state **plane_states, @@ -925,6 +931,7 @@ bool dc_commit_planes_to_stream( struct dc_stream_state *dc_stream, struct dc_state *state) { + /* no need to dynamically allocate this. it's pretty small */ struct dc_surface_update updates[MAX_SURFACES]; struct dc_flip_addrs *flip_addr; struct dc_plane_info *plane_info; -- cgit From 16b2f2ed5f2ece5bf44d94883412048856ca2966 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 28 Sep 2017 10:45:26 +1000 Subject: amdgpu/dc: inline a bunch of the dml wrappers. This reduces the code size. This is basically a redo of Dave's change with the same name on top of the latest DML. Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dml/display_mode_vba.c | 2 + .../drm/amd/display/dc/dml/display_rq_dlg_calc.c | 2 + .../amd/display/dc/dml/dml1_display_rq_dlg_calc.c | 2 + .../gpu/drm/amd/display/dc/dml/dml_common_defs.c | 67 +------------- .../gpu/drm/amd/display/dc/dml/dml_common_defs.h | 14 --- .../gpu/drm/amd/display/dc/dml/dml_inline_defs.h | 102 +++++++++++++++++++++ .../gpu/drm/amd/display/dc/dml/soc_bounding_box.c | 1 + 7 files changed, 110 insertions(+), 80 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c index e337c2cf2c09..f51a36449410 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c @@ -1,6 +1,8 @@ #include "display_mode_lib.h" #include "display_mode_vba.h" +#include "dml_inline_defs.h" + static const unsigned int NumberOfStates = DC__VOLTAGE_STATES; static void fetch_socbb_params(struct display_mode_lib *mode_lib); diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c index 657b7386021d..8ba962df42e6 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c @@ -39,6 +39,8 @@ static void calculate_ttu_cursor(struct display_mode_lib *mode_lib, unsigned int cur_width, enum cursor_bpp cur_bpp); +#include "dml_inline_defs.h" + static unsigned int get_bytes_per_element(enum source_format_class source_format, bool is_chroma) { unsigned int ret_val = 0; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c b/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c index 8229f782260b..1e4b1e383401 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c @@ -26,6 +26,8 @@ #include "dml1_display_rq_dlg_calc.h" #include "display_mode_lib.h" +#include "dml_inline_defs.h" + static unsigned int get_bytes_per_element(enum source_format_class source_format, bool is_chroma) { unsigned int ret_val = 0; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c index 2af6d150cc46..101fb6f19c43 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c @@ -26,37 +26,7 @@ #include "dml_common_defs.h" #include "../calcs/dcn_calc_math.h" -double dml_min(double a, double b) -{ - return (double) dcn_bw_min2(a, b); -} - -double dml_max(double a, double b) -{ - return (double) dcn_bw_max2(a, b); -} -double dml_max3(double a, double b, double c) -{ - return dml_max(dml_max(a, b), c); -} -double dml_max4(double a, double b, double c, double d) -{ - return dml_max(dml_max(a, b), dml_max(c, d)); -} -double dml_max5(double a, double b, double c, double d, double e) -{ - return dml_max(dml_max4(a, b, c, d), e); -} - -double dml_ceil(double a, double granularity) -{ - return (double) dcn_bw_ceil2(a, granularity); -} - -double dml_floor(double a, double granularity) -{ - return (double) dcn_bw_floor2(a, granularity); -} +#include "dml_inline_defs.h" double dml_round(double a) { @@ -70,16 +40,6 @@ double dml_round(double a) return floor; } -int dml_log2(double x) -{ - return dml_round((double)dcn_bw_log(x, 2)); -} - -double dml_pow(double a, int exp) -{ - return (double) dcn_bw_pow(a, exp); -} - unsigned int dml_round_to_multiple( unsigned int num, unsigned int multiple, @@ -101,16 +61,6 @@ unsigned int dml_round_to_multiple( return (num - remainder); } -double dml_fmod(double f, int val) -{ - return (double) dcn_bw_mod(f, val); -} - -double dml_ceil_2(double f) -{ - return (double) dcn_bw_ceil2(f, 2); -} - bool dml_util_is_420(enum source_format_class sorce_format) { bool val = false; @@ -143,18 +93,3 @@ bool dml_util_is_420(enum source_format_class sorce_format) return val; } - -double dml_ceil_ex(double x, double granularity) -{ - return (double) dcn_bw_ceil2(x, granularity); -} - -double dml_floor_ex(double x, double granularity) -{ - return (double) dcn_bw_floor2(x, granularity); -} - -double dml_log(double x, double base) -{ - return (double) dcn_bw_log(x, base); -} diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h index ba01bbb007fc..a55f4d5af36c 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h @@ -34,23 +34,9 @@ #define dml_print(str, ...) {dm_logger_write(mode_lib->logger, LOG_DML, str, ##__VA_ARGS__); } #define DTRACE(str, ...) {dm_logger_write(mode_lib->logger, LOG_DML, str, ##__VA_ARGS__); } -double dml_min(double a, double b); -double dml_max(double a, double b); -double dml_max3(double a, double b, double c); -double dml_max4(double a, double b, double c, double d); -double dml_max5(double a, double b, double c, double d, double e); bool dml_util_is_420(enum source_format_class sorce_format); -double dml_ceil_ex(double x, double granularity); -double dml_floor_ex(double x, double granularity); -double dml_log(double x, double base); -double dml_ceil(double a, double granularity); -double dml_floor(double a, double granularity); double dml_round(double a); -int dml_log2(double x); -double dml_pow(double a, int exp); unsigned int dml_round_to_multiple( unsigned int num, unsigned int multiple, bool up); -double dml_fmod(double f, int val); -double dml_ceil_2(double f); #endif /* __DC_COMMON_DEFS_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h b/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h new file mode 100644 index 000000000000..105c6721f901 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h @@ -0,0 +1,102 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DML_INLINE_DEFS_H__ +#define __DML_INLINE_DEFS_H__ + +#include "dml_common_defs.h" +#include "../calcs/dcn_calc_math.h" + +static inline double dml_min(double a, double b) +{ + return (double) dcn_bw_min2(a, b); +} + +static inline double dml_max(double a, double b) +{ + return (double) dcn_bw_max2(a, b); +} + +static inline double dml_max3(double a, double b, double c) +{ + return dml_max(dml_max(a, b), c); +} + +static inline double dml_max4(double a, double b, double c, double d) +{ + return dml_max(dml_max(a, b), dml_max(c, d)); +} + +static inline double dml_max5(double a, double b, double c, double d, double e) +{ + return dml_max(dml_max4(a, b, c, d), e); +} + +static inline double dml_ceil(double a, double granularity) +{ + return (double) dcn_bw_ceil2(a, granularity); +} + +static inline double dml_floor(double a, double granularity) +{ + return (double) dcn_bw_floor2(a, granularity); +} + +static inline int dml_log2(double x) +{ + return dml_round((double)dcn_bw_log(x, 2)); +} + +static inline double dml_pow(double a, int exp) +{ + return (double) dcn_bw_pow(a, exp); +} + +static inline double dml_fmod(double f, int val) +{ + return (double) dcn_bw_mod(f, val); +} + +static inline double dml_ceil_2(double f) +{ + return (double) dcn_bw_ceil2(f, 2); +} + +static inline double dml_ceil_ex(double x, double granularity) +{ + return (double) dcn_bw_ceil2(x, granularity); +} + +static inline double dml_floor_ex(double x, double granularity) +{ + return (double) dcn_bw_floor2(x, granularity); +} + +static inline double dml_log(double x, double base) +{ + return (double) dcn_bw_log(x, base); +} + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c b/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c index 8b8512528af5..bc7d8c707221 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c +++ b/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c @@ -26,6 +26,7 @@ #include "display_mode_lib.h" #include "dc_features.h" +#include "dml_inline_defs.h" void dml_socbb_set_latencies(soc_bounding_box_st *to_box, soc_bounding_box_st *from_box) { to_box->dram_clock_change_latency_us = from_box->dram_clock_change_latency_us; -- cgit From c6ca4496177d89e3f6eef7d7b6200798b19250ee Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 16 Oct 2017 22:58:18 -0400 Subject: drm/amd/display: Add bunch of missing license headers in DML All files should have MIT headers. Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dml/display_mode_vba.c | 25 ++++++++++++++++++++++ .../gpu/drm/amd/display/dc/dml/display_mode_vba.h | 24 ++++++++++++++++++--- 2 files changed, 46 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c index f51a36449410..ea661ee44674 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c @@ -1,3 +1,28 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + #include "display_mode_lib.h" #include "display_mode_vba.h" diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h index c8d1a0539541..4112409cd974 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h @@ -1,8 +1,26 @@ /* - * display_mode_vba.h + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD * - * Created on: Aug 18, 2017 - * Author: dlaktyus */ #ifndef __DML2_DISPLAY_MODE_VBA_H__ -- cgit From b2484b6237ef3ed60af0400027c053ec973b60cc Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 28 Sep 2017 10:55:25 +1000 Subject: amdgpu/dc: drop dml_util_is_420 This is unused code. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dml/dml_common_defs.c | 33 ---------------------- .../gpu/drm/amd/display/dc/dml/dml_common_defs.h | 1 - 2 files changed, 34 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c index 101fb6f19c43..1683514ed0e3 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c @@ -60,36 +60,3 @@ unsigned int dml_round_to_multiple( else return (num - remainder); } - -bool dml_util_is_420(enum source_format_class sorce_format) -{ - bool val = false; - - switch (sorce_format) { - case dm_444_16: - val = false; - break; - case dm_444_32: - val = false; - break; - case dm_444_64: - val = false; - break; - case dm_420_8: - val = true; - break; - case dm_420_10: - val = true; - break; - case dm_422_8: - val = false; - break; - case dm_422_10: - val = false; - break; - default: - BREAK_TO_DEBUGGER(); - } - - return val; -} diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h index a55f4d5af36c..e11d123ab8d9 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h @@ -34,7 +34,6 @@ #define dml_print(str, ...) {dm_logger_write(mode_lib->logger, LOG_DML, str, ##__VA_ARGS__); } #define DTRACE(str, ...) {dm_logger_write(mode_lib->logger, LOG_DML, str, ##__VA_ARGS__); } -bool dml_util_is_420(enum source_format_class sorce_format); double dml_round(double a); unsigned int dml_round_to_multiple( unsigned int num, unsigned int multiple, bool up); -- cgit From 299f27fd370f34cb6e22e2ffb84b61e91dd6a4c1 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 17:13:31 +1000 Subject: amdgpu/dc: inline dml_round_to_multiple turns out to be a win to inline this. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c | 19 ------------------- drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h | 2 -- drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h | 19 +++++++++++++++++++ 3 files changed, 19 insertions(+), 21 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c index 1683514ed0e3..b953b02a1512 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c @@ -40,23 +40,4 @@ double dml_round(double a) return floor; } -unsigned int dml_round_to_multiple( - unsigned int num, - unsigned int multiple, - bool up) -{ - unsigned int remainder; - - if (multiple == 0) - return num; - - remainder = num % multiple; - if (remainder == 0) - return num; - - if (up) - return (num + multiple - remainder); - else - return (num - remainder); -} diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h index e11d123ab8d9..b2847bc469fe 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h @@ -35,7 +35,5 @@ #define DTRACE(str, ...) {dm_logger_write(mode_lib->logger, LOG_DML, str, ##__VA_ARGS__); } double dml_round(double a); -unsigned int dml_round_to_multiple( - unsigned int num, unsigned int multiple, bool up); #endif /* __DC_COMMON_DEFS_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h b/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h index 105c6721f901..e68086b8a22f 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h @@ -99,4 +99,23 @@ static inline double dml_log(double x, double base) return (double) dcn_bw_log(x, base); } +static inline unsigned int dml_round_to_multiple(unsigned int num, + unsigned int multiple, + bool up) +{ + unsigned int remainder; + + if (multiple == 0) + return num; + + remainder = num % multiple; + + if (remainder == 0) + return num; + + if (up) + return (num + multiple - remainder); + else + return (num - remainder); +} #endif -- cgit From 33be2785477e470087ea1c5b203881d644cdb0f3 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Tue, 17 Oct 2017 08:47:25 -0400 Subject: drm/amd/display: Simplify dm_late_init() Signed-off-by: Tom St Denis Acked-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/gpu') 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 58143fe49e4a..d8fcf24a041e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -538,9 +538,8 @@ static int detect_mst_link_for_all_connectors(struct drm_device *dev) static int dm_late_init(void *handle) { struct drm_device *dev = ((struct amdgpu_device *)handle)->ddev; - int r = detect_mst_link_for_all_connectors(dev); - return r; + return detect_mst_link_for_all_connectors(dev); } static void s3_handle_mst(struct drm_device *dev, bool suspend) -- cgit From 32f5062d1c7dc2a4d974bb10cf67a98043d9c901 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Tue, 17 Oct 2017 08:48:44 -0400 Subject: drm/amd/display: Fix indentation in dm_suspend() Signed-off-by: Tom St Denis Acked-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/gpu') 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 d8fcf24a041e..893213b9c11e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -598,10 +598,7 @@ static int dm_suspend(void *handle) WARN_ON(adev->dm.cached_state); adev->dm.cached_state = drm_atomic_helper_suspend(adev->ddev); - dc_set_power_state( - dm->dc, - DC_ACPI_CM_POWER_STATE_D3 - ); + dc_set_power_state(dm->dc, DC_ACPI_CM_POWER_STATE_D3); return ret; } -- cgit From 1fb0c9ccb311cdf16f6ec617fb30c249888c5f97 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Tue, 17 Oct 2017 08:49:13 -0400 Subject: drm/amd/display: Fix indentation in dm_resume() Signed-off-by: Tom St Denis Acked-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/gpu') 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 893213b9c11e..a7bbd22e8f12 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -628,10 +628,7 @@ static int dm_resume(void *handle) struct amdgpu_display_manager *dm = &adev->dm; /* power on hardware */ - dc_set_power_state( - dm->dc, - DC_ACPI_CM_POWER_STATE_D0 - ); + dc_set_power_state(dm->dc, DC_ACPI_CM_POWER_STATE_D0); return 0; } -- cgit From 900b3cb1833883de9be62e48ff748663c7b6ef96 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Tue, 17 Oct 2017 08:59:18 -0400 Subject: drm/amd/display: Fix brace style in amdgpu_dm_update_connector_after_detect() Signed-off-by: Tom St Denis Acked-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') 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 a7bbd22e8f12..7999eadddd75 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -890,9 +890,9 @@ amdgpu_dm_update_connector_after_detect(struct amdgpu_dm_connector *aconnector) connector); aconnector->dc_sink = sink; - if (sink->dc_edid.length == 0) + if (sink->dc_edid.length == 0) { aconnector->edid = NULL; - else { + } else { aconnector->edid = (struct edid *) sink->dc_edid.raw_edid; -- cgit From d4a6e8a90ffa281918d9ba75a08f1f917c7eb183 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Tue, 17 Oct 2017 09:00:33 -0400 Subject: drm/amd/display: Fix brace style in dm_handle_hpd_rx_irq() Signed-off-by: Tom St Denis Acked-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') 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 7999eadddd75..2b57bfc8ec40 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1010,8 +1010,9 @@ static void dm_handle_hpd_rx_irq(struct amdgpu_dm_connector *aconnector) dpcd_bytes_to_read); new_irq_handled = false; - } else + } else { break; + } } if (process_count == max_process_count) -- cgit From 53cbf65c145450e35fbca50a33c56f5a066e3fe8 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Tue, 17 Oct 2017 09:04:25 -0400 Subject: drm/amd/display: Simplify handle_hpd_rx_irq() There is a local reference to the dc_link that wasn't being used so we shorten references throughout the function. Signed-off-by: Tom St Denis Acked-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') 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 2b57bfc8ec40..bb83da6fd31b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1024,20 +1024,20 @@ static void handle_hpd_rx_irq(void *param) struct amdgpu_dm_connector *aconnector = (struct amdgpu_dm_connector *)param; struct drm_connector *connector = &aconnector->base; struct drm_device *dev = connector->dev; - const struct dc_link *dc_link = aconnector->dc_link; + struct dc_link *dc_link = aconnector->dc_link; bool is_mst_root_connector = aconnector->mst_mgr.mst_state; /* TODO:Temporary add mutex to protect hpd interrupt not have a gpio * conflict, after implement i2c helper, this mutex should be * retired. */ - if (aconnector->dc_link->type != dc_connection_mst_branch) + if (dc_link->type != dc_connection_mst_branch) mutex_lock(&aconnector->hpd_lock); - if (dc_link_handle_hpd_rx_irq(aconnector->dc_link, NULL) && + if (dc_link_handle_hpd_rx_irq(dc_link, NULL) && !is_mst_root_connector) { /* Downstream Port status changed. */ - if (dc_link_detect(aconnector->dc_link, DETECT_REASON_HPDRX)) { + if (dc_link_detect(dc_link, DETECT_REASON_HPDRX)) { amdgpu_dm_update_connector_after_detect(aconnector); @@ -1049,10 +1049,10 @@ static void handle_hpd_rx_irq(void *param) } } if ((dc_link->cur_link_settings.lane_count != LANE_COUNT_UNKNOWN) || - (dc_link->type == dc_connection_mst_branch)) + (dc_link->type == dc_connection_mst_branch)) dm_handle_hpd_rx_irq(aconnector); - if (aconnector->dc_link->type != dc_connection_mst_branch) + if (dc_link->type != dc_connection_mst_branch) mutex_unlock(&aconnector->hpd_lock); } -- cgit From 8440c30463f3c6d312a5a65be634e6c6c1b6a5b3 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Tue, 17 Oct 2017 09:09:42 -0400 Subject: drm/amd/display: Fix brace style in amdgpu_dm_initialize_drm_device() Signed-off-by: Tom St Denis Acked-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/gpu') 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 bb83da6fd31b..fb24ba69b2a6 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1412,9 +1412,8 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) goto fail_free_planes; aencoder = kzalloc(sizeof(*aencoder), GFP_KERNEL); - if (!aencoder) { + if (!aencoder) goto fail_free_connector; - } if (amdgpu_dm_encoder_init(dm->ddev, aencoder, i)) { DRM_ERROR("KMS: Failed to initialize encoder\n"); -- cgit From d2b2562c23e5e2a122a73627b0c658c5cfedb01a Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Tue, 17 Oct 2017 09:46:54 -0400 Subject: drm/amd/display: Replace block with strncpy() in fill_audio_info() Replace inlined strncpy with library call. Signed-off-by: Tom St Denis Acked-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') 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 fb24ba69b2a6..3f405976f882 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2238,11 +2238,9 @@ static void fill_audio_info(struct audio_info *audio_info, cea_revision = drm_connector->display_info.cea_rev; - while (i < AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS && - edid_caps->display_name[i]) { - audio_info->display_name[i] = edid_caps->display_name[i]; - i++; - } + strncpy(audio_info->display_name, + edid_caps->display_name, + AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS - 1); if (cea_revision >= 3) { audio_info->mode_count = edid_caps->audio_mode_count; -- cgit From a68d90e7aed55e274cb117bbca34913d5fb8afd2 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Tue, 17 Oct 2017 10:15:12 -0400 Subject: drm/amd/display: Fix indentation in create_eml_sink() Signed-off-by: Tom St Denis Acked-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/gpu') 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 3f405976f882..ce975aef27a7 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2720,8 +2720,7 @@ static void create_eml_sink(struct amdgpu_dm_connector *aconnector) (edid->extensions + 1) * EDID_LENGTH, &init_params); - if (aconnector->base.force - == DRM_FORCE_ON) + if (aconnector->base.force == DRM_FORCE_ON) aconnector->dc_sink = aconnector->dc_link->local_sink ? aconnector->dc_link->local_sink : aconnector->dc_em_sink; -- cgit From f922237daa7f2de4a8eae0ecdc99e944333fffc2 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Tue, 17 Oct 2017 10:16:39 -0400 Subject: drm/amd/display: Tidy up dm_drm_plane_reset() Move WARN_ON higher up and in doing so fix brace style. Signed-off-by: Tom St Denis Acked-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') 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 ce975aef27a7..46fac2bccc57 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2873,13 +2873,13 @@ static void dm_drm_plane_reset(struct drm_plane *plane) plane->funcs->atomic_destroy_state(plane, plane->state); amdgpu_state = kzalloc(sizeof(*amdgpu_state), GFP_KERNEL); - + WARN_ON(amdgpu_state == NULL); + if (amdgpu_state) { plane->state = &amdgpu_state->base; plane->state->plane = plane; plane->state->rotation = DRM_MODE_ROTATE_0; - } else - WARN_ON(1); + } } static struct drm_plane_state * -- cgit From a8d8d3dc9ad8dc4ba6155bdd88f01e23bfc7dfbc Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Tue, 17 Oct 2017 10:38:27 -0400 Subject: drm/amd/display: Fix brace style in amdgpu_dm_connector_ddc_get_modes() Signed-off-by: Tom St Denis Acked-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') 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 46fac2bccc57..d7fc237851c5 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3310,8 +3310,9 @@ static void amdgpu_dm_connector_ddc_get_modes(struct drm_connector *connector, drm_edid_to_eld(connector, edid); amdgpu_dm_get_native_mode(connector); - } else + } else { amdgpu_dm_connector->num_modes = 0; + } } static int amdgpu_dm_connector_get_modes(struct drm_connector *connector) -- cgit From 9a227d263d44572583be5dd9e9f215cceb4297a1 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Tue, 17 Oct 2017 10:40:08 -0400 Subject: drm/amd/display: Remove needless cast in amdgpu_dm_connector_init() The cast of dc_link is redundant. Signed-off-by: Tom St Denis Acked-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') 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 d7fc237851c5..6ef71e192845 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3460,7 +3460,8 @@ static int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm, struct dc *dc = dm->dc; struct dc_link *link = dc_get_link_at_index(dc, link_index); struct amdgpu_i2c_adapter *i2c; - ((struct dc_link *)link)->priv = aconnector; + + link->priv = aconnector; DRM_DEBUG_DRIVER("%s()\n", __func__); -- cgit From 634086b464ac92d215aeaa3653759b0fbcde1a02 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Tue, 17 Oct 2017 12:13:39 -0400 Subject: drm/amd/display: Fix brace style Signed-off-by: Tom St Denis Acked-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c index b9e4d3831001..ca5d0d1581dc 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c @@ -208,24 +208,21 @@ static void remove_timer_handler(struct amdgpu_device *adev, DM_IRQ_TABLE_LOCK(adev, irq_table_flags); } - if (handler_in == NULL) { - /* Remove ALL handlers. */ + /* Remove ALL handlers. */ + if (handler_in == NULL) continue; - } - if (handler_in == handler_temp) { - /* Remove a SPECIFIC handler. - * Found our handler - we can stop here. */ + /* Remove a SPECIFIC handler. + * Found our handler - we can stop here. */ + if (handler_in == handler_temp) break; - } } DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags); - if (handler_in != NULL && handler_removed == false) { + if (handler_in != NULL && handler_removed == false) DRM_ERROR("DM_IRQ: handler: %p is not in the list!\n", handler_in); - } } static bool -- cgit From fc9e9920b1d3a7a6af7eb993d531c36beb985570 Mon Sep 17 00:00:00 2001 From: Shirish S Date: Wed, 27 Sep 2017 15:15:38 +0530 Subject: drm/amd/display: add hardware_planes_only to list of affected planes For SoC's having software designed cursor plane, should be treated differently than hardware cursor planes. The DRM core initializes cursor plane by default with legacy_cursor_update set. Hence legacy_cursor_update can be use effectively to handle software cursor planes' update and atomicity functionalities. This patch uses this variable to decide in the atomic_check to whether add a requested plane to the list of affected planes or not, hence fixing the issue of co-existence of MPO, i.e, setting of available hardware planes like underlay and updation of cursor planes as well. Without this patch when underlay is set from user space, only blank screen with backlight is visible. Signed-off-by: Shirish S Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 30 ++++++++++++++++++----- 1 file changed, 24 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') 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 6ef71e192845..51258d045167 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3982,6 +3982,8 @@ static int amdgpu_dm_atomic_commit(struct drm_device *dev, if (drm_atomic_crtc_needs_modeset(new_crtc_state) && dm_old_crtc_state->stream) manage_dm_interrupts(adev, acrtc, false); } + /* Add check here for SoC's that support hardware cursor plane, to + * unset legacy_cursor_update */ return drm_atomic_helper_commit(dev, state, nonblock); @@ -4647,7 +4649,7 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, struct drm_connector *connector; struct drm_connector_state *old_con_state, *new_con_state; struct drm_crtc *crtc; - struct drm_crtc_state *new_crtc_state; + struct drm_crtc_state *old_crtc_state, *new_crtc_state; /* * This bool will be set for true for any modeset/reset @@ -4656,18 +4658,34 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, bool lock_and_validation_needed = false; ret = drm_atomic_helper_check_modeset(dev, state); - if (ret) { DRM_ERROR("Atomic state validation failed with error :%d !\n", ret); return ret; } /* - * Hack: Commit needs planes right now, specifically for gamma - * TODO rework commit to check CRTC for gamma change + * legacy_cursor_update should be made false for SoC's having + * a dedicated hardware plane for cursor in amdgpu_dm_atomic_commit(), + * otherwise for software cursor plane, + * we should not add it to list of affected planes. */ - for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { - if (new_crtc_state->color_mgmt_changed) { + if (state->legacy_cursor_update) { + for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { + if (new_crtc_state->color_mgmt_changed) { + ret = drm_atomic_add_affected_planes(state, crtc); + if (ret) + goto fail; + } + } + } else { + for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { + if (!new_crtc_state->enable) + continue; + + ret = drm_atomic_add_affected_connectors(state, crtc); + if (ret) + return ret; + ret = drm_atomic_add_affected_planes(state, crtc); if (ret) goto fail; -- cgit From af09e48aa52377eb807709e2a1cdc33e9fd1ac94 Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Fri, 20 Oct 2017 13:59:53 -0400 Subject: drm/amd/display: Fix memoryleak during S3 resume. Do not create dc_state within display_resume, since it's being constructed within atomic check. Reviewed-by: Harry Wentland Signed-off-by: Leo (Sunpeng) Li Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/gpu') 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 51258d045167..d0ee1b3b8b5c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -694,10 +694,6 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev) WARN_ON(kref_read(&cached_state->context->refcount) > 1); dc_release_state(cached_state->context); - cached_state->context = dc_create_state(); - ASSERT(cached_state->context); - dc_resource_state_copy_construct_current(adev->dm.dc, cached_state->context); - for_each_new_crtc_in_state(adev->dm.cached_state, crtc, new_crtc_state, i) { dm_crtc_state = to_dm_crtc_state(new_crtc_state); if (dm_crtc_state->stream) { -- cgit From 9b38bd1b8f5c874c3d1f330e0dcf4e7d84137477 Mon Sep 17 00:00:00 2001 From: "Jerry (Fangzhi) Zuo" Date: Fri, 20 Oct 2017 16:45:53 -0400 Subject: drm/amd/display:: Fix NULL pointer in Raven hotplug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Programming sequence to frontend and backend has been switched. In such case, program_scaler() is getting called when programming frontend, and should be removed from backend programming routine. Reviewed-by: Harry Wentland Signed-off-by: Jerry (Fangzhi) Zuo Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index e8b8daeeed97..2a6d3ca12954 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1369,13 +1369,6 @@ static enum dc_status apply_single_controller_ctx_to_hw( } pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; - /* program_scaler and allocate_mem_input are not new asic */ - if ((!pipe_ctx_old || - memcmp(&pipe_ctx_old->plane_res.scl_data, &pipe_ctx->plane_res.scl_data, - sizeof(struct scaler_data)) != 0) && - pipe_ctx->plane_state) { - program_scaler(dc, pipe_ctx); - } /* mst support - use total stream count */ if (pipe_ctx->plane_res.mi != NULL) { -- cgit From 9a68db7220d05fb28de139a7db93bd6866cc86fa Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Thu, 26 Oct 2017 00:03:27 -0400 Subject: Revert "drm/amd/display: Match actual state during S3 resume." This reverts commit 4f346e655d24140fb40b46f814506ba17ac34ea1. fix s3 hang issue. Acked-by: Alex Deucher Signed-off-by: Rex Zhu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 33 ----------------------- 1 file changed, 33 deletions(-) (limited to 'drivers/gpu') 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 d0ee1b3b8b5c..bb134a6320bf 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -641,11 +641,6 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev) struct drm_connector *connector; struct drm_crtc *crtc; struct drm_crtc_state *new_crtc_state; - struct dm_crtc_state *dm_crtc_state; - struct drm_plane *plane; - struct drm_plane_state *plane_state; - struct dm_plane_state *dm_plane_state; - struct dm_atomic_state *cached_state; int ret = 0; int i; @@ -684,34 +679,6 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev) for_each_new_crtc_in_state(adev->dm.cached_state, crtc, new_crtc_state, i) new_crtc_state->active_changed = true; - cached_state = to_dm_atomic_state(adev->dm.cached_state); - - /* - * During suspend, the cached state is saved before all streams are - * disabled. Refresh cached state to match actual current state before - * restoring it. - */ - WARN_ON(kref_read(&cached_state->context->refcount) > 1); - dc_release_state(cached_state->context); - - for_each_new_crtc_in_state(adev->dm.cached_state, crtc, new_crtc_state, i) { - dm_crtc_state = to_dm_crtc_state(new_crtc_state); - if (dm_crtc_state->stream) { - WARN_ON(kref_read(&dm_crtc_state->stream->refcount) > 1); - dc_stream_release(dm_crtc_state->stream); - dm_crtc_state->stream = NULL; - } - } - - for_each_new_plane_in_state(adev->dm.cached_state, plane, plane_state, i) { - dm_plane_state = to_dm_plane_state(plane_state); - if (dm_plane_state->dc_state) { - WARN_ON(kref_read(&dm_plane_state->dc_state->refcount) > 1); - dc_plane_state_release(dm_plane_state->dc_state); - dm_plane_state->dc_state = NULL; - } - } - ret = drm_atomic_helper_resume(ddev, adev->dm.cached_state); drm_atomic_state_put(adev->dm.cached_state); -- cgit From 3b21b6d239f43c0d797bf0deb8c0f8c846862eb1 Mon Sep 17 00:00:00 2001 From: Jerry Zuo Date: Tue, 17 Oct 2017 15:36:13 -0400 Subject: drm/amd/display: Fix no display on Fiji MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allocate memory for the second pipe allocate_mem_input() needs to be done prior to program pipe front end. It shows sensitive to Fiji. Failure to do so will cause error in allocate memory  allocate_mem_input() on the second connected display. Signed-off-by: Jerry Zuo Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 2a6d3ca12954..399a5984ada3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1370,16 +1370,6 @@ static enum dc_status apply_single_controller_ctx_to_hw( pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; - /* mst support - use total stream count */ - if (pipe_ctx->plane_res.mi != NULL) { - pipe_ctx->plane_res.mi->funcs->allocate_mem_input( - pipe_ctx->plane_res.mi, - stream->timing.h_total, - stream->timing.v_total, - stream->timing.pix_clk_khz, - context->stream_count); - } - pipe_ctx->stream->sink->link->psr_enabled = false; return DC_OK; @@ -2891,6 +2881,15 @@ static void dce110_apply_ctx_for_surface( if (pipe_ctx->stream != stream) continue; + /* Need to allocate mem before program front end for Fiji */ + if (pipe_ctx->plane_res.mi != NULL) + pipe_ctx->plane_res.mi->funcs->allocate_mem_input( + pipe_ctx->plane_res.mi, + pipe_ctx->stream->timing.h_total, + pipe_ctx->stream->timing.v_total, + pipe_ctx->stream->timing.pix_clk_khz, + context->stream_count); + dce110_program_front_end_for_pipe(dc, pipe_ctx); program_surface_visibility(dc, pipe_ctx); -- cgit From 4d3e00dad80a2c317d542358620facd8ca698428 Mon Sep 17 00:00:00 2001 From: Shirish S Date: Thu, 19 Oct 2017 22:34:15 +0530 Subject: drm/amd/display : add high part address calculation for underlay Currently the high part of the address structure is not populated in case of luma and chroma. This patch adds this calculation. Signed-off-by: Shirish S Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') 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 bb134a6320bf..635a8a3df369 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1771,6 +1771,7 @@ static int fill_plane_attributes_from_fb(struct amdgpu_device *adev, { uint64_t tiling_flags; uint64_t fb_location = 0; + uint64_t chroma_addr = 0; unsigned int awidth; const struct drm_framebuffer *fb = &amdgpu_fb->base; int ret = 0; @@ -1833,9 +1834,13 @@ static int fill_plane_attributes_from_fb(struct amdgpu_device *adev, plane_state->address.type = PLN_ADDR_TYPE_VIDEO_PROGRESSIVE; plane_state->address.video_progressive.luma_addr.low_part = lower_32_bits(fb_location); + plane_state->address.video_progressive.luma_addr.high_part + = upper_32_bits(fb_location); + chroma_addr = fb_location + (u64)(awidth * fb->height); plane_state->address.video_progressive.chroma_addr.low_part - = lower_32_bits(fb_location) + - (awidth * fb->height); + = lower_32_bits(chroma_addr); + plane_state->address.video_progressive.chroma_addr.high_part + = upper_32_bits(chroma_addr); plane_state->plane_size.video.luma_size.x = 0; plane_state->plane_size.video.luma_size.y = 0; plane_state->plane_size.video.luma_size.width = awidth; -- cgit From 56087b31f4b2861c773185ec45d313b55dbbb69d Mon Sep 17 00:00:00 2001 From: Shirish S Date: Thu, 26 Oct 2017 16:15:01 +0530 Subject: drm/amd/display: fix high part address in dm_plane_helper_prepare_fb() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The high part calculation of luma and chroma address' was missing in dm_plane_helper_prepare_fb(). This fix brings uniformity in the address' at atomic_check and atomic_commit for both RGB & YUV planes. Signed-off-by: Shirish S Reviewed-by: Michel Dänzer Reviewed-by: Alex Deucher Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') 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 635a8a3df369..c2fefd3e657e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2896,6 +2896,7 @@ static int dm_plane_helper_prepare_fb(struct drm_plane *plane, struct amdgpu_framebuffer *afb; struct drm_gem_object *obj; struct amdgpu_bo *rbo; + uint64_t chroma_addr = 0; int r; struct dm_plane_state *dm_plane_state_new, *dm_plane_state_old; unsigned int awidth; @@ -2937,11 +2938,16 @@ static int dm_plane_helper_prepare_fb(struct drm_plane *plane, plane_state->address.grph.addr.high_part = upper_32_bits(afb->address); } else { awidth = ALIGN(new_state->fb->width, 64); + plane_state->address.type = PLN_ADDR_TYPE_VIDEO_PROGRESSIVE; plane_state->address.video_progressive.luma_addr.low_part = lower_32_bits(afb->address); + plane_state->address.video_progressive.luma_addr.high_part + = upper_32_bits(afb->address); + chroma_addr = afb->address + (u64)(awidth * new_state->fb->height); plane_state->address.video_progressive.chroma_addr.low_part - = lower_32_bits(afb->address) + - (awidth * new_state->fb->height); + = lower_32_bits(chroma_addr); + plane_state->address.video_progressive.chroma_addr.high_part + = upper_32_bits(chroma_addr); } } -- cgit From 7bef1af3b9c2a5690a41298b5986dbde82fbedbc Mon Sep 17 00:00:00 2001 From: Shirish S Date: Fri, 27 Oct 2017 03:25:55 +0000 Subject: drm/amd/display: check if modeset is required before adding plane Adding affected planes without checking if modeset is requested from the user space causes performance regression in video p/b scenarios when full screen p/b is not composited. Hence add a check before adding a plane as affected. bug: https://bugs.freedesktop.org/show_bug.cgi?id=103408 Acked-by: Alex Deucher Reviewed-by: Harry Wentland Signed-off-by: Shirish S Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpu') 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 c2fefd3e657e..fd3e995fc426 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4653,6 +4653,9 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, } } else { for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { + if (!drm_atomic_crtc_needs_modeset(new_crtc_state)) + continue; + if (!new_crtc_state->enable) continue; -- cgit From cc57306f426e3953118f1fcf8a7254dbad46c5f6 Mon Sep 17 00:00:00 2001 From: Andrew Jiang Date: Fri, 20 Oct 2017 16:40:45 -0400 Subject: drm/amd/display: Use constants from atom.h for HDMI caps read Get rid of the constant we copied over before and just directly use the constants from the file. Signed-off-by: Andrew Jiang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index c47da645d3b8..e70612eaf257 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -24,6 +24,7 @@ */ #include "dm_services.h" +#include "atom.h" #include "dm_helpers.h" #include "dc.h" #include "grph_object_id.h" @@ -45,7 +46,6 @@ #include "dce/dce_11_0_enum.h" #include "dce/dce_11_0_sh_mask.h" -#define EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK 0x007C /* Copied from atombios.h */ #define LINK_INFO(...) \ dm_logger_write(dc_ctx->logger, LOG_HW_HOTPLUG, \ __VA_ARGS__) @@ -1696,7 +1696,7 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) { unsigned short masked_chip_caps = pipe_ctx->stream->sink->link->chip_caps & EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK; - if (masked_chip_caps == (0x2 << 2)) { + if (masked_chip_caps == EXT_DISPLAY_PATH_CAPS__HDMI20_TISN65DP159RSBT) { /* DP159, Retimer settings */ eng_id = pipe_ctx->stream_res.stream_enc->id; @@ -1707,7 +1707,7 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) write_i2c_default_retimer_setting(pipe_ctx, is_vga_mode, is_over_340mhz); } - } else if (masked_chip_caps == (0x1 << 2)) { + } else if (masked_chip_caps == EXT_DISPLAY_PATH_CAPS__HDMI20_PI3EQX1204) { /* PI3EQX1204, Redriver settings */ write_i2c_redriver_setting(pipe_ctx, is_over_340mhz); } -- cgit From 30b7c6147d18d77c6120a8f689d04d2518d3f5e4 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 26 Oct 2017 15:35:14 -0400 Subject: drm/amd/display: Don't print error when bo_pin is interrupted MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit v2: Also don't print for ERESTARTSYS or EAGAIN v3: Best practice is to only ignore ERESTARTSYS Signed-off-by: Harry Wentland Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') 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 fd3e995fc426..b94987bb6af9 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2923,7 +2923,8 @@ static int dm_plane_helper_prepare_fb(struct drm_plane *plane, amdgpu_bo_unreserve(rbo); if (unlikely(r != 0)) { - DRM_ERROR("Failed to pin framebuffer\n"); + if (r != -ERESTARTSYS) + DRM_ERROR("Failed to pin framebuffer with error %d\n", r); return r; } -- cgit From f5ba60fefa00ca789c4eb35df38b171d532b3155 Mon Sep 17 00:00:00 2001 From: Drew Davenport Date: Fri, 27 Oct 2017 12:34:46 -0600 Subject: amdgpu/dc: Avoid dereferencing NULL pointer crtc is dereferenced from within drm_atomic_get_new_crtc_state, so check for NULL before initializing new_crtc_state. Signed-off-by: Drew Davenport Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') 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 b94987bb6af9..84591781fca1 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3853,8 +3853,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, /* update planes when needed */ for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) { struct drm_crtc *crtc = new_plane_state->crtc; - struct drm_crtc_state *new_crtc_state = - drm_atomic_get_new_crtc_state(state, crtc); + struct drm_crtc_state *new_crtc_state; struct drm_framebuffer *fb = new_plane_state->fb; bool pflip_needed; struct dm_plane_state *dm_new_plane_state = to_dm_plane_state(new_plane_state); @@ -3864,7 +3863,11 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, continue; } - if (!fb || !crtc || pcrtc != crtc || !new_crtc_state->active) + if (!fb || !crtc || pcrtc != crtc) + continue; + + new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc); + if (!new_crtc_state->active) continue; pflip_needed = !state->allow_modeset; -- cgit From 55d9038b0c680ec90e3a7d2440e717ac6a2a8064 Mon Sep 17 00:00:00 2001 From: Shirish S Date: Thu, 26 Oct 2017 11:47:42 +0530 Subject: drm/amd/display: fix null pointer dereference While setting cursor position in case of mpo, input_pixel_processor is not available for underlay, hence add check of the same to avoid null pointer access issue. Signed-off-by: Shirish S Reviewed-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 5cf69af9693d..572b885195c7 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -288,7 +288,7 @@ bool dc_stream_set_cursor_position( pos_cpy.enable = false; - if (ipp->funcs->ipp_cursor_set_position != NULL) + if (ipp !=NULL && ipp->funcs->ipp_cursor_set_position != NULL) ipp->funcs->ipp_cursor_set_position(ipp, &pos_cpy, ¶m); if (mi != NULL && mi->funcs->set_cursor_position != NULL) -- cgit From efa6a8b7ca0f1c6073a2ac7f5a02f8ea333daf92 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Fri, 20 Oct 2017 08:42:41 -0400 Subject: drm/amd/display: Use plane pointer to avoid line breaks Signed-off-by: Harry Wentland Reviewed-by: Mikita Lipski Reviewed-by: Tony Cheng Acked-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') 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 84591781fca1..2df9f951b7e7 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1328,13 +1328,16 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) } for (i = 0; i < dm->dc->caps.max_planes; i++) { - mode_info->planes[i] = kzalloc(sizeof(struct amdgpu_plane), - GFP_KERNEL); - if (!mode_info->planes[i]) { + struct amdgpu_plane *plane; + + plane = kzalloc(sizeof(struct amdgpu_plane), GFP_KERNEL); + mode_info->planes[i] = plane; + + if (!plane) { DRM_ERROR("KMS: Failed to allocate plane\n"); goto fail_free_planes; } - mode_info->planes[i]->base.type = mode_info->plane_type[i]; + plane->base.type = mode_info->plane_type[i]; /* * HACK: IGT tests expect that each plane can only have one -- cgit From cd8a2ae8dc08a92d4804a7adda645f1f8d1f7586 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Fri, 20 Oct 2017 08:28:59 -0400 Subject: drm/amd/display: Use single fail label in init_drm_dev No need for multiple labels as kfree will always do a NULL check before freeing the memory. Signed-off-by: Harry Wentland Reviewed-by: Bhawanpreet Lakha Reviewed-by: Tony Cheng Acked-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 24 +++++++++++------------ 1 file changed, 11 insertions(+), 13 deletions(-) (limited to 'drivers/gpu') 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 2df9f951b7e7..6eb7b32fb763 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1335,7 +1335,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) if (!plane) { DRM_ERROR("KMS: Failed to allocate plane\n"); - goto fail_free_planes; + goto fail; } plane->base.type = mode_info->plane_type[i]; @@ -1351,14 +1351,14 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) if (amdgpu_dm_plane_init(dm, mode_info->planes[i], possible_crtcs)) { DRM_ERROR("KMS: Failed to initialize plane\n"); - goto fail_free_planes; + goto fail; } } for (i = 0; i < dm->dc->caps.max_streams; i++) if (amdgpu_dm_crtc_init(dm, &mode_info->planes[i]->base, i)) { DRM_ERROR("KMS: Failed to initialize crtc\n"); - goto fail_free_planes; + goto fail; } dm->display_indexes_num = dm->dc->caps.max_streams; @@ -1375,20 +1375,20 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) aconnector = kzalloc(sizeof(*aconnector), GFP_KERNEL); if (!aconnector) - goto fail_free_planes; + goto fail; aencoder = kzalloc(sizeof(*aencoder), GFP_KERNEL); if (!aencoder) - goto fail_free_connector; + goto fail; if (amdgpu_dm_encoder_init(dm->ddev, aencoder, i)) { DRM_ERROR("KMS: Failed to initialize encoder\n"); - goto fail_free_encoder; + goto fail; } if (amdgpu_dm_connector_init(dm, aconnector, i, aencoder)) { DRM_ERROR("KMS: Failed to initialize connector\n"); - goto fail_free_encoder; + goto fail; } if (dc_link_detect(dc_get_link_at_index(dm->dc, i), @@ -1413,14 +1413,14 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) case CHIP_VEGA10: if (dce110_register_irq_handlers(dm->adev)) { DRM_ERROR("DM: Failed to initialize IRQ\n"); - goto fail_free_encoder; + goto fail; } break; #if defined(CONFIG_DRM_AMD_DC_DCN1_0) case CHIP_RAVEN: if (dcn10_register_irq_handlers(dm->adev)) { DRM_ERROR("DM: Failed to initialize IRQ\n"); - goto fail_free_encoder; + goto fail; } /* * Temporary disable until pplib/smu interaction is implemented @@ -1430,17 +1430,15 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) #endif default: DRM_ERROR("Usupported ASIC type: 0x%X\n", adev->asic_type); - goto fail_free_encoder; + goto fail; } drm_mode_config_reset(dm->ddev); return 0; -fail_free_encoder: +fail: kfree(aencoder); -fail_free_connector: kfree(aconnector); -fail_free_planes: for (i = 0; i < dm->dc->caps.max_planes; i++) kfree(mode_info->planes[i]); return -1; -- cgit From 96719c5439b4d75bfd6b3c5cb24f1a8e537125bb Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Fri, 20 Oct 2017 08:43:40 -0400 Subject: drm/amd/display: Explicitly call ->reset for each object We need to avoid calling reset after detection because the next commit adds freesync properties on the atomic_state which are set during detection. Calling reset after this clears them. The easiest way to accomplish this right now is to call ->reset on the connector right after creation but before detection. To stay consistent call ->reset on every other object as well after creation. v2: Provide better reason for this change in commit msg. Signed-off-by: Harry Wentland Reviewed-by: Roman Li Acked-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') 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 6eb7b32fb763..33a15a1d818c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1433,8 +1433,6 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) goto fail; } - drm_mode_config_reset(dm->ddev); - return 0; fail: kfree(aencoder); @@ -3081,6 +3079,11 @@ static int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, drm_plane_helper_add(&aplane->base, &dm_plane_helper_funcs); + /* Create (reset) the plane state */ + if (aplane->base.funcs->reset) + aplane->base.funcs->reset(&aplane->base); + + return res; } @@ -3116,6 +3119,10 @@ static int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, drm_crtc_helper_add(&acrtc->base, &amdgpu_dm_crtc_helper_funcs); + /* Create (reset) the plane state */ + if (acrtc->base.funcs->reset) + acrtc->base.funcs->reset(&acrtc->base); + acrtc->max_cursor_width = dm->adev->dm.dc->caps.max_cursor_size; acrtc->max_cursor_height = dm->adev->dm.dc->caps.max_cursor_size; @@ -3468,6 +3475,9 @@ static int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm, &aconnector->base, &amdgpu_dm_connector_helper_funcs); + if (aconnector->base.funcs->reset) + aconnector->base.funcs->reset(&aconnector->base); + amdgpu_dm_connector_init_helper( dm, aconnector, -- cgit From b7fa8519057319aef8405923dc8fa6782fce969f Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Tue, 31 Oct 2017 16:28:57 -0400 Subject: drm/amd: Add DCE12 resource strap registers We need them for initializing audio properly. Signed-off-by: Leo (Sunpeng) Li Reviewed-by: Harry Wentland Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/include/asic_reg/vega10/DC/dce_12_0_offset.h | 4 ++++ drivers/gpu/drm/amd/include/asic_reg/vega10/DC/dce_12_0_sh_mask.h | 8 ++++++++ 2 files changed, 12 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/include/asic_reg/vega10/DC/dce_12_0_offset.h b/drivers/gpu/drm/amd/include/asic_reg/vega10/DC/dce_12_0_offset.h index 75b660d57bdf..f730d0629020 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/vega10/DC/dce_12_0_offset.h +++ b/drivers/gpu/drm/amd/include/asic_reg/vega10/DC/dce_12_0_offset.h @@ -1841,6 +1841,10 @@ #define mmUNIPHYG_CHANNEL_XBAR_CNTL_BASE_IDX 2 #define mmDCIO_WRCMD_DELAY 0x2094 #define mmDCIO_WRCMD_DELAY_BASE_IDX 2 +#define mmDC_PINSTRAPS 0x2096 +#define mmDC_PINSTRAPS_BASE_IDX 2 +#define mmCC_DC_MISC_STRAPS 0x2097 +#define mmCC_DC_MISC_STRAPS_BASE_IDX 2 #define mmDC_DVODATA_CONFIG 0x2098 #define mmDC_DVODATA_CONFIG_BASE_IDX 2 #define mmLVTMA_PWRSEQ_CNTL 0x2099 diff --git a/drivers/gpu/drm/amd/include/asic_reg/vega10/DC/dce_12_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/vega10/DC/dce_12_0_sh_mask.h index d8ad862b3a74..6d3162c42957 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/vega10/DC/dce_12_0_sh_mask.h +++ b/drivers/gpu/drm/amd/include/asic_reg/vega10/DC/dce_12_0_sh_mask.h @@ -2447,6 +2447,14 @@ //DCCG_CBUS_WRCMD_DELAY #define DCCG_CBUS_WRCMD_DELAY__CBUS_PLL_WRCMD_DELAY__SHIFT 0x0 #define DCCG_CBUS_WRCMD_DELAY__CBUS_PLL_WRCMD_DELAY_MASK 0x0000000FL +//DC_PINSTRAPS +#define DC_PINSTRAPS__DC_PINSTRAPS_AUDIO__SHIFT 0xe +#define DC_PINSTRAPS__DC_PINSTRAPS_AUDIO_MASK 0x0000C000L +//CC_DC_MISC_STRAPS +#define CC_DC_MISC_STRAPS__HDMI_DISABLE__SHIFT 0x6 +#define CC_DC_MISC_STRAPS__AUDIO_STREAM_NUMBER__SHIFT 0x8 +#define CC_DC_MISC_STRAPS__HDMI_DISABLE_MASK 0x00000040L +#define CC_DC_MISC_STRAPS__AUDIO_STREAM_NUMBER_MASK 0x00000700L //DCCG_DS_DTO_INCR #define DCCG_DS_DTO_INCR__DCCG_DS_DTO_INCR__SHIFT 0x0 #define DCCG_DS_DTO_INCR__DCCG_DS_DTO_INCR_MASK 0xFFFFFFFFL -- cgit From 4a74635ce23a4b8758047a733faf791e38032263 Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Wed, 1 Nov 2017 10:24:51 -0400 Subject: drm/amd/display: Read resource_straps from registers for DCE12 Now that the registers exist, assign them to the resource_straps struct. v2: Fix indentation v3: Fix trailing whitespace and checkpatch warnings. bug: https://bugs.freedesktop.org/show_bug.cgi?id=103404 Reviewed-by: Harry Wentland Signed-off-by: Leo (Sunpeng) Li Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dce120/dce120_resource.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index 3ed28a870e20..5c48c22d9d98 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -501,12 +501,19 @@ static void read_dce_straps( struct dc_context *ctx, struct resource_straps *straps) { - /* TODO: Registers are missing */ - /*REG_GET_2(CC_DC_HDMI_STRAPS, - HDMI_DISABLE, &straps->hdmi_disable, - AUDIO_STREAM_NUMBER, &straps->audio_stream_number); - - REG_GET(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO, &straps->dc_pinstraps_audio);*/ + uint32_t reg_val = dm_read_reg_soc15(ctx, mmCC_DC_MISC_STRAPS, 0); + + straps->audio_stream_number = get_reg_field_value(reg_val, + CC_DC_MISC_STRAPS, + AUDIO_STREAM_NUMBER); + straps->hdmi_disable = get_reg_field_value(reg_val, + CC_DC_MISC_STRAPS, + HDMI_DISABLE); + + reg_val = dm_read_reg_soc15(ctx, mmDC_PINSTRAPS, 0); + straps->dc_pinstraps_audio = get_reg_field_value(reg_val, + DC_PINSTRAPS, + DC_PINSTRAPS_AUDIO); } static struct audio *create_audio( -- cgit From d8eed8263aa09c0c92416d06321eae4ad3eda343 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 2 Nov 2017 15:24:40 +0100 Subject: drm/amdgpu/display: provide ASSERT macros unconditionally It seems impossible to build this driver without setting either CONFIG_DEBUG_KERNEL or CONFIG_DEBUG_DRIVER: drivers/gpu/drm/amd/amdgpu/../display/dc/dm_services.h: In function 'set_reg_field_value_ex': drivers/gpu/drm/amd/amdgpu/../display/dc/dm_services.h:132:2: error: implicit declaration of function 'ASSERT'; did you mean 'IS_ERR'? [-Werror=implicit-function-declaration] This moves the ASSERT() macro and related helpers outside of the #ifdef to get it to build again. Reviewed-by: Harry Wentland Signed-off-by: Arnd Bergmann Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/os_types.h | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/os_types.h b/drivers/gpu/drm/amd/display/dc/os_types.h index 86170b40b5c5..a87c0329541f 100644 --- a/drivers/gpu/drm/amd/display/dc/os_types.h +++ b/drivers/gpu/drm/amd/display/dc/os_types.h @@ -61,8 +61,6 @@ * general debug capabilities * */ -#if defined(CONFIG_DEBUG_KERNEL) || defined(CONFIG_DEBUG_DRIVER) - #if defined(CONFIG_HAVE_KGDB) || defined(CONFIG_KGDB) #define ASSERT_CRITICAL(expr) do { \ if (WARN_ON(!(expr))) { \ @@ -86,8 +84,6 @@ #define BREAK_TO_DEBUGGER() ASSERT(0) -#endif /* CONFIG_DEBUG_KERNEL || CONFIG_DEBUG_DRIVER */ - #define DC_ERR(...) do { \ dm_error(__VA_ARGS__); \ BREAK_TO_DEBUGGER(); \ -- cgit From d8d46ae97ffd4ace4b8a7f45c232ff4bb8b6c129 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 2 Nov 2017 12:26:42 +0100 Subject: drm/amdgpu/display: remove unused REG_OFFSET macro The name conflicts with another macro of the same name on the ARM ixp4xx platform, leading to build errors. Neither of the users actually should use a name that generic, but the other one was here first and the dc driver doesn't actually use it. Reviewed-by: Harry Wentland Signed-off-by: Arnd Bergmann Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dm_services.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dm_services.h b/drivers/gpu/drm/amd/display/dc/dm_services.h index c8190c38a644..d4917037ac42 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services.h @@ -160,9 +160,6 @@ unsigned int generic_reg_wait(const struct dc_context *ctx, /* These macros need to be used with soc15 registers in order to retrieve * the actual offset. */ -#define REG_OFFSET(reg) (reg + DCE_BASE.instance[0].segment[reg##_BASE_IDX]) -#define REG_BIF_OFFSET(reg) (reg + NBIF_BASE.instance[0].segment[reg##_BASE_IDX]) - #define dm_write_reg_soc15(ctx, reg, inst_offset, value) \ dm_write_reg_func(ctx, reg + DCE_BASE.instance[0].segment[reg##_BASE_IDX] + inst_offset, value, __func__) -- cgit From 1f3493faa8d73b0332d46ea79448b10b66fb1af0 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 2 Nov 2017 12:26:43 +0100 Subject: drm/amdgpu/display: fix integer arithmetic problem gcc warns about an ambiguous integer calculation: drivers/gpu/drm/amd/amdgpu/../display/dc/calcs/dce_calcs.c: In function 'calculate_bandwidth': drivers/gpu/drm/amd/amdgpu/../display/dc/calcs/dce_calcs.c:534:5: error: this decimal constant is unsigned only in ISO C90 [-Werror] data->lb_line_pitch = bw_ceil2(bw_mul(bw_div(bw_frc_to_fixed(2401171875, 100000000), bw_int_to_fixed(3)), bw_ceil2(data->source_width_in_lb, bw_int_to_fixed(8))), bw_int_to_fixed(48)); ^~~~ Marking the constant as explicitly unsigned makes it work fine everywhere without warnings. Reviewed-by: Harry Wentland Signed-off-by: Arnd Bergmann Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c index 15cbfc400633..4f8a95368ffc 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c @@ -531,7 +531,7 @@ static void calculate_bandwidth( } switch (data->lb_bpc[i]) { case 8: - data->lb_line_pitch = bw_ceil2(bw_mul(bw_div(bw_frc_to_fixed(2401171875, 100000000), bw_int_to_fixed(3)), bw_ceil2(data->source_width_in_lb, bw_int_to_fixed(8))), bw_int_to_fixed(48)); + data->lb_line_pitch = bw_ceil2(bw_mul(bw_div(bw_frc_to_fixed(2401171875ul, 100000000), bw_int_to_fixed(3)), bw_ceil2(data->source_width_in_lb, bw_int_to_fixed(8))), bw_int_to_fixed(48)); break; case 10: data->lb_line_pitch = bw_ceil2(bw_mul(bw_div(bw_frc_to_fixed(300234375, 10000000), bw_int_to_fixed(3)), bw_ceil2(data->source_width_in_lb, bw_int_to_fixed(8))), bw_int_to_fixed(48)); -- cgit From 620fd73edfd7297307e0e3ac581e65247c9dd8db Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 6 Nov 2017 10:07:33 +0300 Subject: drm/amd/display: small cleanup in destruct() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Static analysis tools get annoyed that we don't indent this if statement. Actually, the if statement isn't required because kfree() can handle NULL pointers just fine. The DCE110STRENC_FROM_STRENC() macro is a wrapper around container_of() but it's basically a no-op or a cast. Anyway, it's not really appropriate here so it should be removed as well. Acked-by: Christian König Signed-off-by: Dan Carpenter Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index d911590d08bc..4c4bd72d4e40 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -725,10 +725,8 @@ static void destruct(struct dcn10_resource_pool *pool) } } - for (i = 0; i < pool->base.stream_enc_count; i++) { - if (pool->base.stream_enc[i] != NULL) - kfree(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); - } + for (i = 0; i < pool->base.stream_enc_count; i++) + kfree(pool->base.stream_enc[i]); for (i = 0; i < pool->base.audio_count; i++) { if (pool->base.audios[i]) -- cgit From 74baea4275ee130c67400b33c532da8999b530af Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 6 Nov 2017 14:43:41 +0300 Subject: drm/amd/display: checking for NULL instead of IS_ERR() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit backlight_device_register() never returns NULL, it returns error pointers on error so the check here is wrong. Acked-by: Christian König Signed-off-by: Dan Carpenter Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') 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 33a15a1d818c..75f9383f5b9b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1296,7 +1296,7 @@ amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm) &amdgpu_dm_backlight_ops, &props); - if (NULL == dm->backlight_dev) + if (IS_ERR(dm->backlight_dev)) DRM_ERROR("DM: Backlight registration failed!\n"); else DRM_DEBUG_DRIVER("DM: Registered Backlight device: %s\n", bl_name); -- cgit From f05f1b3da5a531d1569194b24dd7eb33b4a067ca Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 6 Nov 2017 14:44:22 +0300 Subject: drm/amd/display: remove some unneeded code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We assign "v_init = asic_blank_start;" a few lines earlier so there is no need to do it again inside the if statements. Also "v_init" is unsigned so it can't be less than zero. Acked-by: Christian König Signed-off-by: Dan Carpenter Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c index 1994865d4351..c7333cdf1802 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c @@ -236,13 +236,10 @@ static void tgn10_program_timing( if (tg->dlg_otg_param.signal == SIGNAL_TYPE_DISPLAY_PORT || tg->dlg_otg_param.signal == SIGNAL_TYPE_DISPLAY_PORT_MST || tg->dlg_otg_param.signal == SIGNAL_TYPE_EDP) { - v_init = asic_blank_start; start_point = 1; if (patched_crtc_timing.flags.INTERLACE == 1) field_num = 1; } - if (v_init < 0) - v_init = 0; v_fp2 = 0; if (tg->dlg_otg_param.vstartup_start > asic_blank_end) v_fp2 = tg->dlg_otg_param.vstartup_start > asic_blank_end; -- cgit From a4718a5bca77954ffaa5f828158c45aae40a7ec8 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 7 Nov 2017 05:17:12 +1000 Subject: amdgpu/dc: fix non-ansi function decls. smatch reported: drivers/gpu/drm/amd/amdgpu/../display/dc/bios/dce80/command_table_helper_dce80.c:351:71: warning: non-ANSI function declaration of function 'dal_cmd_tbl_helper_dce80_get_table' drivers/gpu/drm/amd/amdgpu/../display/dc/bios/dce110/command_table_helper_dce110.c:361:72: warning: non-ANSI function declaration of function 'dal_cmd_tbl_helper_dce110_get_table' drivers/gpu/drm/amd/amdgpu/../display/dc/bios/dce112/command_table_helper_dce112.c:415:72: warning: non-ANSI function declaration of function 'dal_cmd_tbl_helper_dce112_get_table' drivers/gpu/drm/amd/amdgpu/../display/dc/bios/dce112/command_table_helper2_dce112.c:415:73: warning: non-ANSI function declaration of function 'dal_cmd_tbl_helper_dce112_get_table2' drivers/gpu/drm/amd/amdgpu/../display/dc/core/dc_surface.c:148:34: warning: non-ANSI function declaration of function 'dc_create_gamma' drivers/gpu/drm/amd/amdgpu/../display/dc/core/dc_surface.c:178:50: warning: non-ANSI function declaration of function 'dc_create_transfer_func' This fixes them. Reviewed-by: Harry Wentland Signed-off-by: Dave Airlie Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.c | 2 +- .../gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.c | 2 +- .../gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c | 2 +- .../gpu/drm/amd/display/dc/bios/dce80/command_table_helper_dce80.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_surface.c | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.c b/drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.c index 8049320e8b03..ca24154468c7 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.c @@ -358,7 +358,7 @@ static const struct command_table_helper command_table_helper_funcs = { * const struct command_table_helper **h - [out] struct of functions * */ -const struct command_table_helper *dal_cmd_tbl_helper_dce110_get_table() +const struct command_table_helper *dal_cmd_tbl_helper_dce110_get_table(void) { return &command_table_helper_funcs; } diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.c b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.c index d342cdecba11..0237ae575068 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.c +++ b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.c @@ -412,7 +412,7 @@ static const struct command_table_helper command_table_helper_funcs = { * const struct command_table_helper **h - [out] struct of functions * */ -const struct command_table_helper *dal_cmd_tbl_helper_dce112_get_table2() +const struct command_table_helper *dal_cmd_tbl_helper_dce112_get_table2(void) { return &command_table_helper_funcs; } diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c index 48e59963dad4..452034f83e4c 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c +++ b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c @@ -412,7 +412,7 @@ static const struct command_table_helper command_table_helper_funcs = { * const struct command_table_helper **h - [out] struct of functions * */ -const struct command_table_helper *dal_cmd_tbl_helper_dce112_get_table() +const struct command_table_helper *dal_cmd_tbl_helper_dce112_get_table(void) { return &command_table_helper_funcs; } diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce80/command_table_helper_dce80.c b/drivers/gpu/drm/amd/display/dc/bios/dce80/command_table_helper_dce80.c index 295e16ef3f73..8b30b558cf1f 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/dce80/command_table_helper_dce80.c +++ b/drivers/gpu/drm/amd/display/dc/bios/dce80/command_table_helper_dce80.c @@ -348,7 +348,7 @@ static const struct command_table_helper command_table_helper_funcs = { dal_cmd_table_helper_encoder_mode_bp_to_atom, }; -const struct command_table_helper *dal_cmd_tbl_helper_dce80_get_table() +const struct command_table_helper *dal_cmd_tbl_helper_dce80_get_table(void) { return &command_table_helper_funcs; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index 5aa2270f36fd..ade5b8ee9c3c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -145,7 +145,7 @@ void dc_gamma_release(struct dc_gamma **gamma) *gamma = NULL; } -struct dc_gamma *dc_create_gamma() +struct dc_gamma *dc_create_gamma(void) { struct dc_gamma *gamma = kzalloc(sizeof(*gamma), GFP_KERNEL); @@ -175,7 +175,7 @@ void dc_transfer_func_release(struct dc_transfer_func *tf) kref_put(&tf->refcount, dc_transfer_func_free); } -struct dc_transfer_func *dc_create_transfer_func() +struct dc_transfer_func *dc_create_transfer_func(void) { struct dc_transfer_func *tf = kzalloc(sizeof(*tf), GFP_KERNEL); -- cgit From bf5563ede9f254fba083c6b56e4ca8b836babb1d Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 7 Nov 2017 05:30:47 +1000 Subject: amdgpu/dc: fix indentation warning from smatch. This fixes all the current smatch: warn: inconsistent indenting Reviewed-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Dave Airlie Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c | 2 +- .../gpu/drm/amd/display/dc/bios/command_table2.c | 18 ++++++------- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 4 +-- drivers/gpu/drm/amd/display/dc/dce/dce_audio.c | 26 +++++++++---------- drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c | 16 ++++++------ .../amd/display/dc/dce110/dce110_hw_sequencer.c | 30 +++++++++++----------- .../display/dc/dce120/dce120_timing_generator.c | 7 +++-- .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c | 2 +- .../dc/i2caux/dce110/i2c_hw_engine_dce110.c | 30 +++++++++++----------- 10 files changed, 68 insertions(+), 69 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c index 43e9a9959288..1ee1717f2e6f 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -1373,7 +1373,7 @@ static enum bp_result get_firmware_info_v3_1( bp->cmd_tbl.get_smu_clock_info(bp) * 10; } - return BP_RESULT_OK; + return BP_RESULT_OK; } static enum bp_result bios_parser_get_encoder_cap_info( diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c index 64eab356d336..ba68693758a7 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c @@ -373,15 +373,15 @@ static void init_set_crtc_timing(struct bios_parser *bp) uint32_t dtd_version = BIOS_CMD_TABLE_PARA_REVISION(setcrtc_usingdtdtiming); - switch (dtd_version) { - case 3: - bp->cmd_tbl.set_crtc_timing = - set_crtc_using_dtd_timing_v3; - break; - default: - bp->cmd_tbl.set_crtc_timing = NULL; - break; - } + switch (dtd_version) { + case 3: + bp->cmd_tbl.set_crtc_timing = + set_crtc_using_dtd_timing_v3; + break; + default: + bp->cmd_tbl.set_crtc_timing = NULL; + break; + } } static enum bp_result set_crtc_using_dtd_timing_v3( diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index e1515230c661..3dce35e66b09 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -1155,7 +1155,7 @@ static unsigned int dcn_find_normalized_clock_vdd_Level( unsigned factor = (ddr4_dram_factor_single_Channel * dc->dcn_soc->number_of_channels); if (clocks_in_khz > dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9*1000000/factor) { - vdd_level = dcn_bw_v_max0p91; + vdd_level = dcn_bw_v_max0p91; BREAK_TO_DEBUGGER(); } else if (clocks_in_khz > dc->dcn_soc->fabric_and_dram_bandwidth_vnom0p8*1000000/factor) { vdd_level = dcn_bw_v_max0p9; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 572b885195c7..de04b95e103a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -182,11 +182,11 @@ bool dc_stream_set_cursor_attributes( if (NULL == stream) { dm_error("DC: dc_stream is NULL!\n"); - return false; + return false; } if (NULL == attributes) { dm_error("DC: attributes is NULL!\n"); - return false; + return false; } if (attributes->address.quad_part == 0) { diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c index 526ec5c8eafd..d882adf746a5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c @@ -179,19 +179,19 @@ static void check_audio_bandwidth_hdmi( /* Number of Audio Packets (multiplied by 10) per Line (for 8 ch number * of Audio samples per line multiplied by 10 - Layout 1) */ - samples /= 32; - samples *= crtc_info->v_active; - /*Number of samples multiplied by 10, per second */ - samples *= crtc_info->refresh_rate; - /*Number of Audio samples per second */ - samples /= 10; - - /* @todo do it after deep color is implemented - * 8xx - deep color bandwidth scaling - * Extra bandwidth is avaliable in deep color b/c link runs faster than - * pixel rate. This has the effect of allowing more tmds characters to - * be transmitted during blank - */ + samples /= 32; + samples *= crtc_info->v_active; + /*Number of samples multiplied by 10, per second */ + samples *= crtc_info->refresh_rate; + /*Number of Audio samples per second */ + samples /= 10; + + /* @todo do it after deep color is implemented + * 8xx - deep color bandwidth scaling + * Extra bandwidth is avaliable in deep color b/c link runs faster than + * pixel rate. This has the effect of allowing more tmds characters to + * be transmitted during blank + */ switch (crtc_info->color_depth) { case COLOR_DEPTH_888: diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c index 3691c7498d08..fd77df573b61 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c @@ -130,14 +130,14 @@ static void dce_dmcu_set_psr_enable(struct dmcu *dmcu, bool enable, bool wait) if (wait == true) { for (retryCount = 0; retryCount <= 100; retryCount++) { dce_get_dmcu_psr_state(dmcu, &psr_state); - if (enable) { - if (psr_state != 0) - break; - } else { - if (psr_state == 0) - break; - } - udelay(10); + if (enable) { + if (psr_state != 0) + break; + } else { + if (psr_state == 0) + break; + } + udelay(10); } } } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 399a5984ada3..1229a3315018 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -775,8 +775,8 @@ void dce110_enable_stream(struct pipe_ctx *pipe_ctx) * connect DIG back_end to front_end while enable_stream and * disconnect them during disable_stream * BY this, it is logic clean to separate stream and link */ - link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc, - pipe_ctx->stream_res.stream_enc->id, true); + link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc, + pipe_ctx->stream_res.stream_enc->id, true); } @@ -1306,7 +1306,7 @@ static enum dc_status apply_single_controller_ctx_to_hw( stream->timing.display_color_depth, pipe_ctx->stream->signal); - pipe_ctx->stream_res.opp->funcs->opp_program_fmt( + pipe_ctx->stream_res.opp->funcs->opp_program_fmt( pipe_ctx->stream_res.opp, &stream->bit_depth_params, &stream->clamping); @@ -2594,21 +2594,21 @@ uint32_t dce110_get_min_vblank_time_us(const struct dc_state *context) uint8_t j; uint32_t min_vertical_blank_time = -1; - for (j = 0; j < context->stream_count; j++) { - struct dc_stream_state *stream = context->streams[j]; - uint32_t vertical_blank_in_pixels = 0; - uint32_t vertical_blank_time = 0; + for (j = 0; j < context->stream_count; j++) { + struct dc_stream_state *stream = context->streams[j]; + uint32_t vertical_blank_in_pixels = 0; + uint32_t vertical_blank_time = 0; - vertical_blank_in_pixels = stream->timing.h_total * - (stream->timing.v_total - - stream->timing.v_addressable); + vertical_blank_in_pixels = stream->timing.h_total * + (stream->timing.v_total + - stream->timing.v_addressable); - vertical_blank_time = vertical_blank_in_pixels - * 1000 / stream->timing.pix_clk_khz; + vertical_blank_time = vertical_blank_in_pixels + * 1000 / stream->timing.pix_clk_khz; - if (min_vertical_blank_time > vertical_blank_time) - min_vertical_blank_time = vertical_blank_time; - } + if (min_vertical_blank_time > vertical_blank_time) + min_vertical_blank_time = vertical_blank_time; + } return min_vertical_blank_time; } diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c index 95d871be3a0b..2502182d5e82 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c @@ -293,10 +293,9 @@ void dce120_timing_generator_tear_down_global_swap_lock( FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_SYNC_SOURCE), 0, FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_DELAY_SURFACE_UPDATE_PENDING), 0); - CRTC_REG_SET_2( - CRTC0_CRTC_GSL_CONTROL, - CRTC_GSL_CHECK_LINE_NUM, 0, - CRTC_GSL_FORCE_DELAY, 0x2); /*TODO Why this value here ?*/ + CRTC_REG_SET_2(CRTC0_CRTC_GSL_CONTROL, + CRTC_GSL_CHECK_LINE_NUM, 0, + CRTC_GSL_FORCE_DELAY, 0x2); /*TODO Why this value here ?*/ } /* Reset slave controllers on master VSync */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c index 7784001c3a17..40627c244bf5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c @@ -124,7 +124,7 @@ static void program_gamut_remap( const uint16_t *regval, enum gamut_remap_select select) { - uint16_t selection = 0; + uint16_t selection = 0; struct color_matrices_reg gam_regs; if (regval == NULL || select == GAMUT_REMAP_BYPASS) { diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.c index 1a5b3f70ddc9..56e25b3d65fd 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.c @@ -133,13 +133,13 @@ static void release_engine( safe_to_reset = (i2c_sw_status == 1); } - if (safe_to_reset) - REG_UPDATE_2( - DC_I2C_CONTROL, - DC_I2C_SOFT_RESET, 1, - DC_I2C_SW_STATUS_RESET, 1); - else - REG_UPDATE(DC_I2C_CONTROL, DC_I2C_SW_STATUS_RESET, 1); + if (safe_to_reset) + REG_UPDATE_2( + DC_I2C_CONTROL, + DC_I2C_SOFT_RESET, 1, + DC_I2C_SW_STATUS_RESET, 1); + else + REG_UPDATE(DC_I2C_CONTROL, DC_I2C_SW_STATUS_RESET, 1); /* HW I2c engine - clock gating feature */ if (!hw_engine->engine_keep_power_up_count) @@ -301,16 +301,16 @@ static bool process_transaction( * For an I2C send operation, the LSB must be programmed to 0; * for I2C receive operation, the LSB must be programmed to 1. */ if (hw_engine->transaction_count == 0) { - value = REG_SET_4(DC_I2C_DATA, 0, - DC_I2C_DATA_RW, false, - DC_I2C_DATA, request->address, - DC_I2C_INDEX, 0, - DC_I2C_INDEX_WRITE, 1); + value = REG_SET_4(DC_I2C_DATA, 0, + DC_I2C_DATA_RW, false, + DC_I2C_DATA, request->address, + DC_I2C_INDEX, 0, + DC_I2C_INDEX_WRITE, 1); hw_engine->buffer_used_write = 0; } else - value = REG_SET_2(DC_I2C_DATA, 0, - DC_I2C_DATA_RW, false, - DC_I2C_DATA, request->address); + value = REG_SET_2(DC_I2C_DATA, 0, + DC_I2C_DATA_RW, false, + DC_I2C_DATA, request->address); hw_engine->buffer_used_write++; -- cgit From f7dbc385c15084d6e11192e8a5dd901eb96dbec2 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 7 Nov 2017 05:21:18 +1000 Subject: amdgpu/dc: handle allocation failures in dc_commit_planes_to_stream. Reported-by smatch: drivers/gpu/drm/amd/amdgpu/../display/dc/core/dc.c:966 dc_commit_planes_to_stream() error: potential null dereference 'flip_addr'. (kcalloc returns null) drivers/gpu/drm/amd/amdgpu/../display/dc/core/dc.c:968 dc_commit_planes_to_stream() error: potential null dereference 'plane_info'. (kcalloc returns null) drivers/gpu/drm/amd/amdgpu/../display/dc/core/dc.c:978 dc_commit_planes_to_stream() error: potential null dereference 'scaling_info'. (kcalloc returns null) Reviewed-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Dave Airlie Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index a71392ffc46d..ce3c57b38bc0 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -952,6 +952,14 @@ bool dc_commit_planes_to_stream( scaling_info = kcalloc(MAX_SURFACES, sizeof(struct dc_scaling_info), GFP_KERNEL); + if (!flip_addr || !plane_info || !scaling_info) { + kfree(flip_addr); + kfree(plane_info); + kfree(scaling_info); + kfree(stream_update); + return false; + } + memset(updates, 0, sizeof(updates)); stream_update->src = dc_stream->src; -- cgit From b349f76ece33be50943c1e6f78ccffd1b3e9627e Mon Sep 17 00:00:00 2001 From: Ernst Sjöstrand Date: Tue, 7 Nov 2017 21:06:57 +0100 Subject: amdgpu/dc: fix more indentation warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit More "warn: inconsistent indenting" fixes from smatch. Acked-by: Christian König Reviewed-by: Harry Wentland Signed-off-by: Ernst Sjöstrand Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 10 +++++----- .../gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') 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 75f9383f5b9b..ad98885222e6 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -517,7 +517,7 @@ static int detect_mst_link_for_all_connectors(struct drm_device *dev) drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - aconnector = to_amdgpu_dm_connector(connector); + aconnector = to_amdgpu_dm_connector(connector); if (aconnector->dc_link->type == dc_connection_mst_branch) { DRM_DEBUG_DRIVER("DM_MST: starting TM on aconnector: %p [id: %d]\n", aconnector, aconnector->base.base.id); @@ -4712,10 +4712,10 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, goto fail; } - /* Run this here since we want to validate the streams we created */ - ret = drm_atomic_helper_check_planes(dev, state); - if (ret) - goto fail; + /* Run this here since we want to validate the streams we created */ + ret = drm_atomic_helper_check_planes(dev, state); + if (ret) + goto fail; /* Check scaling and underscan changes*/ /*TODO Removed scaling changes validation due to inability to commit diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c index 0c4bbc10510d..81f9f3e34c10 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c @@ -318,7 +318,7 @@ static void process_channel_reply( REG_GET(AUX_SW_DATA, AUX_SW_DATA, &aux_sw_data_val); - reply->data[i] = aux_sw_data_val; + reply->data[i] = aux_sw_data_val; ++i; } -- cgit From 2a55f09643acf51ec0f1c72d92fdd4515e9a8aa7 Mon Sep 17 00:00:00 2001 From: Ernst Sjöstrand Date: Tue, 7 Nov 2017 21:06:58 +0100 Subject: amdgpu/dc: Fix potential null dereferences in amdgpu_dm.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Acked-by: Christian König Reviewed-by: Harry Wentland Signed-off-by: Ernst Sjöstrand Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/gpu') 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 ad98885222e6..8ee1bff09a6c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2423,6 +2423,8 @@ dm_crtc_duplicate_state(struct drm_crtc *crtc) return NULL; state = kzalloc(sizeof(*state), GFP_KERNEL); + if (!state) + return NULL; __drm_atomic_helper_crtc_duplicate_state(crtc, &state->base); @@ -3419,6 +3421,8 @@ create_i2c(struct ddc_service *ddc_service, struct amdgpu_i2c_adapter *i2c; i2c = kzalloc(sizeof(struct amdgpu_i2c_adapter), GFP_KERNEL); + if (!i2c) + return NULL; i2c->base.owner = THIS_MODULE; i2c->base.class = I2C_CLASS_DDC; i2c->base.dev.parent = &adev->pdev->dev; @@ -3449,6 +3453,11 @@ static int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm, DRM_DEBUG_DRIVER("%s()\n", __func__); i2c = create_i2c(link->ddc, link->link_index, &res); + if (!i2c) { + DRM_ERROR("Failed to create i2c adapter data\n"); + return -ENOMEM; + } + aconnector->i2c = i2c; res = i2c_add_adapter(&i2c->base); -- cgit From 423788c7a866cb7f5265af9b96952e8a4bf48fd5 Mon Sep 17 00:00:00 2001 From: Ernst Sjöstrand Date: Tue, 7 Nov 2017 21:06:59 +0100 Subject: amdgpu/dc: Fix missing null checks in amdgpu_dm.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From smatch: error: we previously assumed X could be null Acked-by: Christian König Reviewed-by: Harry Wentland Signed-off-by: Ernst Sjöstrand Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') 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 8ee1bff09a6c..cb45a3dc5a65 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -430,10 +430,12 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) /* Display Core create. */ adev->dm.dc = dc_create(&init_data); - if (adev->dm.dc) + if (adev->dm.dc) { DRM_INFO("Display Core initialized!\n"); - else + } else { DRM_INFO("Display Core failed to initialize!\n"); + goto error; + } INIT_WORK(&adev->dm.mst_hotplug_work, hotplug_notify_work_func); @@ -2273,7 +2275,7 @@ decide_crtc_timing_for_drm_display_mode(struct drm_display_mode *drm_mode, } } -static void create_fake_sink(struct amdgpu_dm_connector *aconnector) +static int create_fake_sink(struct amdgpu_dm_connector *aconnector) { struct dc_sink *sink = NULL; struct dc_sink_init_data sink_init_data = { 0 }; @@ -2282,14 +2284,18 @@ static void create_fake_sink(struct amdgpu_dm_connector *aconnector) sink_init_data.sink_signal = aconnector->dc_link->connector_signal; sink = dc_sink_create(&sink_init_data); - if (!sink) + if (!sink) { DRM_ERROR("Failed to create sink!\n"); + return -ENOMEM; + } sink->sink_signal = SIGNAL_TYPE_VIRTUAL; aconnector->fake_enable = true; aconnector->dc_sink = sink; aconnector->dc_link->local_sink = sink; + + return 0; } static struct dc_stream_state * @@ -2323,7 +2329,8 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, if (aconnector->mst_port) goto stream_create_fail; - create_fake_sink(aconnector); + if (create_fake_sink(aconnector)) + goto stream_create_fail; } stream = dc_create_stream_for_sink(aconnector->dc_sink); -- cgit From 53a23207f2a17fd990c85bd84c45d243463e21bb Mon Sep 17 00:00:00 2001 From: Ernst Sjöstrand Date: Tue, 7 Nov 2017 21:18:06 +0100 Subject: amdgpu/dc: Fix double unlock in amdgpu_dm_commit_planes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reported by smartch: amdgpu_dm_commit_planes() error: double unlock 'spin_lock:&crtc->dev->event_lock' amdgpu_dm_commit_planes() error: double unlock 'irqsave:flags' The error path doesn't return so we only need a single unlock. Reviewed-by: Harry Wentland Signed-off-by: Ernst Sjöstrand Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/gpu') 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 cb45a3dc5a65..8ed6767b4616 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3904,7 +3904,6 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, DRM_ERROR("%s: acrtc %d, already busy\n", __func__, acrtc_attach->crtc_id); - spin_unlock_irqrestore(&crtc->dev->event_lock, flags); /* In commit tail framework this cannot happen */ WARN_ON(1); } -- cgit From cd3f6ad8389a5065811a5fd3befab7999ac4e117 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 7 Nov 2017 19:33:55 -0500 Subject: drm/amdgpu: Remove unused dc_stream from amdgpu_crtc It's no longer used. In fact, there is no more dc_stream object. Signed-off-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index 59e2e5d59562..ffde1e9666e8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -436,8 +436,6 @@ struct amdgpu_crtc { enum amdgpu_interrupt_state vsync_timer_enabled; int otg_inst; - /* After Set Mode stream will be non-NULL */ - const struct dc_stream *stream; struct drm_pending_vblank_event *event; }; -- cgit From d83e87b239ec42eeda34850da342b3d8f104812b Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 7 Nov 2017 19:29:40 -0500 Subject: amdgpu/dm: Remove unused forward declaration dc_stream has long been renamed to dc_stream_state, so this forward declaration hasn't been used at all. Signed-off-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/gpu') 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 be3b70d683e7..f42f8357b676 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -199,8 +199,6 @@ struct amdgpu_framebuffer; struct amdgpu_display_manager; struct dc_validation_set; struct dc_plane_state; -/* TODO rename to dc_stream_state */ -struct dc_stream; struct dm_plane_state { struct drm_plane_state base; -- cgit From f368d3bfde225199eef2216b03e0ba4944a3434a Mon Sep 17 00:00:00 2001 From: Ernst Sjöstrand Date: Wed, 8 Nov 2017 22:47:06 +0100 Subject: amd/display: Fix potential null dereference in dce_calcs.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reported by smatch: bw_calcs() error: potential null dereference 'data' Reviewed-by: Alex Deucher Signed-off-by: Ernst Sjöstrand Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c index 4f8a95368ffc..6347712db834 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c @@ -2794,6 +2794,8 @@ bool bw_calcs(struct dc_context *ctx, { struct bw_calcs_data *data = kzalloc(sizeof(struct bw_calcs_data), GFP_KERNEL); + if (!data) + return false; populate_initial_data(pipe, pipe_count, data); -- cgit From 01e28f9c03aa88edfda313e6d309c816690d4b10 Mon Sep 17 00:00:00 2001 From: Michel Dänzer Date: Thu, 9 Nov 2017 18:38:09 +0100 Subject: amdgpu/dm: Don't use DRM_ERROR in amdgpu_dm_atomic_check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The atomic_check hook is expected to fail in some cases, e.g. if the modeset operation requested by userspace cannot be performed, so it must not spam dmesg on failure. Fixes spurious [drm:amdgpu_dm_atomic_check [amdgpu]] *ERROR* Atomic state validation failed with error :-35 ! error messages on DPMS off with CONFIG_DEBUG_WW_MUTEX_SLOWPATH enabled. While we're at it, fix up the existing DRM_DEBUG_DRIVER strings. Signed-off-by: Michel Dänzer Reviewed-by: Alex Deucher Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'drivers/gpu') 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 8ed6767b4616..6db8840c12a3 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4662,10 +4662,8 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, bool lock_and_validation_needed = false; ret = drm_atomic_helper_check_modeset(dev, state); - if (ret) { - DRM_ERROR("Atomic state validation failed with error :%d !\n", ret); - return ret; - } + if (ret) + goto fail; /* * legacy_cursor_update should be made false for SoC's having @@ -4782,11 +4780,11 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, fail: if (ret == -EDEADLK) - DRM_DEBUG_DRIVER("Atomic check stopped due to to deadlock.\n"); + DRM_DEBUG_DRIVER("Atomic check stopped to avoid deadlock.\n"); else if (ret == -EINTR || ret == -EAGAIN || ret == -ERESTARTSYS) - DRM_DEBUG_DRIVER("Atomic check stopped due to to signal.\n"); + DRM_DEBUG_DRIVER("Atomic check stopped due to signal.\n"); else - DRM_ERROR("Atomic check failed with err: %d \n", ret); + DRM_DEBUG_DRIVER("Atomic check failed with err: %d \n", ret); return ret; } -- cgit From 6a5a8ca9decab46423257e220475fa30e4e3333e Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Wed, 25 Oct 2017 14:12:51 -0400 Subject: drm/amd/display: fix AZ clock not enabled before program AZ endpoint Signed-off-by: Charlene Liu Reviewed-by: Anthony Koo Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_audio.c | 31 ++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c index d882adf746a5..81c40f8864db 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c @@ -348,29 +348,44 @@ static void set_audio_latency( void dce_aud_az_enable(struct audio *audio) { + struct dce_audio *aud = DCE_AUD(audio); uint32_t value = AZ_REG_READ(AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL); - if (get_reg_field_value(value, + set_reg_field_value(value, 1, AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL, - AUDIO_ENABLED) != 1) + CLOCK_GATING_DISABLE); set_reg_field_value(value, 1, AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL, AUDIO_ENABLED); AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL, value); + value = AZ_REG_READ(AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL); + + dm_logger_write(CTX->logger, LOG_HW_AUDIO, + "\n\t========= AUDIO:dce_aud_az_enable: index: %u data: 0x%x\n", + audio->inst, value); } void dce_aud_az_disable(struct audio *audio) { uint32_t value; + struct dce_audio *aud = DCE_AUD(audio); value = AZ_REG_READ(AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL); set_reg_field_value(value, 0, AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL, AUDIO_ENABLED); + AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL, value); + set_reg_field_value(value, 0, + AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL, + CLOCK_GATING_DISABLE); AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL, value); + value = AZ_REG_READ(AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL); + dm_logger_write(CTX->logger, LOG_HW_AUDIO, + "\n\t========= AUDIO:dce_aud_az_disable: index: %u data: 0x%x\n", + audio->inst, value); } void dce_aud_az_configure( @@ -390,6 +405,11 @@ void dce_aud_az_configure( bool is_ac3_supported = false; union audio_sample_rates sample_rate; uint32_t strlen = 0; + value = AZ_REG_READ(AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL); + set_reg_field_value(value, 1, + AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL, + CLOCK_GATING_DISABLE); + AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL, value); /* Speaker Allocation */ /* @@ -852,6 +872,7 @@ static bool dce_aud_endpoint_valid(struct audio *audio) void dce_aud_hw_init( struct audio *audio) { + uint32_t value; struct dce_audio *aud = DCE_AUD(audio); /* we only need to program the following registers once, so we only do @@ -863,6 +884,12 @@ void dce_aud_hw_init( * Suport R6 - 44.1khz * Suport R7 - 48khz */ + /*disable clock gating before write to endpoint register*/ + value = AZ_REG_READ(AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL); + set_reg_field_value(value, 1, + AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL, + CLOCK_GATING_DISABLE); + AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL, value); REG_UPDATE(AZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES, AUDIO_RATE_CAPABILITIES, 0x70); -- cgit From 6ef39a6224e0f18222a9b75f00d24cdd0c755612 Mon Sep 17 00:00:00 2001 From: Roman Li Date: Thu, 26 Oct 2017 18:43:58 -0400 Subject: drm/amd/display: use configurable FBC option in dm Replace ENABLE_FBC macro with config option CONFIG_DRM_AMD_DC_FBC in dm. DC code has been already updated the same way. Signed-off-by: Roman Li Reviewed-by: Shirish Shankarappa Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 ++-- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') 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 6db8840c12a3..cd19db28a845 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -344,7 +344,7 @@ static void hotplug_notify_work_func(struct work_struct *work) drm_kms_helper_hotplug_event(dev); } -#ifdef ENABLE_FBC +#if defined(CONFIG_DRM_AMD_DC_FBC) #include "dal_asic_id.h" /* Allocate memory for FBC compressed data */ /* TODO: Dynamic allocation */ @@ -422,7 +422,7 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) else init_data.log_mask = DC_MIN_LOG_MASK; -#ifdef ENABLE_FBC +#if defined(CONFIG_DRM_AMD_DC_FBC) if (adev->family == FAMILY_CZ) amdgpu_dm_initialize_fbc(adev); init_data.fbc_gpu_addr = adev->dm.compressor.gpu_addr; 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 f42f8357b676..117521c6a6ed 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -72,7 +72,7 @@ struct irq_list_head { struct work_struct work; }; -#ifdef ENABLE_FBC +#if defined(CONFIG_DRM_AMD_DC_FBC) struct dm_comressor_info { void *cpu_addr; struct amdgpu_bo *bo_ptr; @@ -142,7 +142,7 @@ struct amdgpu_display_manager { * Caches device atomic state for suspend/resume */ struct drm_atomic_state *cached_state; -#ifdef ENABLE_FBC +#if defined(CONFIG_DRM_AMD_DC_FBC) struct dm_comressor_info compressor; #endif }; -- cgit From e99a30de13822685110cfc843a07a035d4aa6253 Mon Sep 17 00:00:00 2001 From: Ken Chalmers Date: Thu, 2 Nov 2017 10:45:12 -0400 Subject: drm/amd/display: use num_timing_generator instead of pipe_count The two are not necessarily the same. Signed-off-by: Ken Chalmers Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 63c2f5266142..961ad5c3b454 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -202,7 +202,7 @@ static void dcn10_log_hw_state(struct dc *dc) DTN_INFO("OTG:\t v_bs \t v_be \t v_ss \t v_se \t vpol \t vmax \t vmin \t " "h_bs \t h_be \t h_ss \t h_se \t hpol \t htot \t vtot \t underflow\n"); - for (i = 0; i < pool->pipe_count; i++) { + for (i = 0; i < pool->res_cap->num_timing_generator; i++) { struct timing_generator *tg = pool->timing_generators[i]; struct dcn_otg_state s = {0}; -- cgit From fcb4019e090b959dbcbfc7bbbc1ebd99c924fa11 Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Wed, 1 Nov 2017 16:49:14 -0400 Subject: drm/amd/display: Fix warnings on S3 resume This is a followup to the following revert: Rex Zhu Revert "drm/amd/display: Match actual state during S3 resume." Three things needed to be addressed: 1. Potential memory leak on dc_state creation in atomic_check during s3 resume 2. Warnings are now seen in dmesg during S3 resume 3. Since dc_state is now created in atomic_check, what the reverted patch was addressing needs to be reevaluated. This change addresses the above: 1. Since the suspend procedure calls drm_atomic_state_clear, our hook for releasing the dc_state is called. This frees it before atomic_check creates it during resume. The leak does not occur. 2. The dc_crtc/plane_state references kept by the atomic states need to be released before calling atomic_check, which warns if they are non-null. This is because atomic_check is responsible for creating the dc_*_states. This is a special case for S3 resume, since the atomic state duplication that occurs during suspend also copies a reference to the dc_*_states. 3. See 2. comments are also updated to reflect this. Reviewed-by: Andrey Grodzovsky Signed-off-by: Leo (Sunpeng) Li Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 28 +++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'drivers/gpu') 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 cd19db28a845..889ed24084e8 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -643,6 +643,11 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev) struct drm_connector *connector; struct drm_crtc *crtc; struct drm_crtc_state *new_crtc_state; + struct dm_crtc_state *dm_new_crtc_state; + struct drm_plane *plane; + struct drm_plane_state *new_plane_state; + struct dm_plane_state *dm_new_plane_state; + int ret = 0; int i; @@ -681,6 +686,29 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev) for_each_new_crtc_in_state(adev->dm.cached_state, crtc, new_crtc_state, i) new_crtc_state->active_changed = true; + /* + * atomic_check is expected to create the dc states. We need to release + * them here, since they were duplicated as part of the suspend + * procedure. + */ + for_each_new_crtc_in_state(adev->dm.cached_state, crtc, new_crtc_state, i) { + dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); + if (dm_new_crtc_state->stream) { + WARN_ON(kref_read(&dm_new_crtc_state->stream->refcount) > 1); + dc_stream_release(dm_new_crtc_state->stream); + dm_new_crtc_state->stream = NULL; + } + } + + for_each_new_plane_in_state(adev->dm.cached_state, plane, new_plane_state, i) { + dm_new_plane_state = to_dm_plane_state(new_plane_state); + if (dm_new_plane_state->dc_state) { + WARN_ON(kref_read(&dm_new_plane_state->dc_state->refcount) > 1); + dc_plane_state_release(dm_new_plane_state->dc_state); + dm_new_plane_state->dc_state = NULL; + } + } + ret = drm_atomic_helper_resume(ddev, adev->dm.cached_state); drm_atomic_state_put(adev->dm.cached_state); -- cgit From 4fc6f65965481bd2cdb8827a6fd991ed076b1006 Mon Sep 17 00:00:00 2001 From: "Jerry (Fangzhi) Zuo" Date: Fri, 3 Nov 2017 14:19:06 -0400 Subject: drm/amd/display: Miss register MST encoder cbs It is to fix: MST display failed to resume from S3 Need to properly setup MST encoder cbs. Otherwise drm_device encoder doesn't register its own cbs, leading to NULL encoder->funcs in drm_atomic_helper_resume(). Signed-off-by: Jerry (Fangzhi) Zuo Reviewed-by: Roman Li Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 3b05da7a90e8..f8efb98b1fa7 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -245,6 +245,16 @@ static const struct drm_connector_helper_funcs dm_dp_mst_connector_helper_funcs .best_encoder = dm_mst_best_encoder, }; +static void amdgpu_dm_encoder_destroy(struct drm_encoder *encoder) +{ + drm_encoder_cleanup(encoder); + kfree(encoder); +} + +static const struct drm_encoder_funcs amdgpu_dm_encoder_funcs = { + .destroy = amdgpu_dm_encoder_destroy, +}; + static struct amdgpu_encoder * dm_dp_create_fake_mst_encoder(struct amdgpu_dm_connector *connector) { @@ -268,7 +278,7 @@ dm_dp_create_fake_mst_encoder(struct amdgpu_dm_connector *connector) drm_encoder_init( dev, &amdgpu_encoder->base, - NULL, + &amdgpu_dm_encoder_funcs, DRM_MODE_ENCODER_DPMST, NULL); -- cgit From 3f0260f6fb86cdb35bf8e6974d50453e7b7f8e40 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Tue, 31 Oct 2017 14:39:36 -0400 Subject: drm/amd/display: add flip_immediate to commit update for stream MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This struct is not updated on page flip and causes vblank_mode to not work as expected Signed-off-by: Bhawanpreet Lakha Reviewed-by: Tony Cheng Acked-by: Harry Wentland Tested-by: Michel Dänzer Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index ce3c57b38bc0..566ca82b5241 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1414,8 +1414,11 @@ void dc_commit_updates_for_stream(struct dc *dc, /* TODO: On flip we don't build the state, so it still has the * old address. Which is why we are updating the address here */ - if (srf_updates[i].flip_addr) + if (srf_updates[i].flip_addr) { surface->address = srf_updates[i].flip_addr->address; + surface->flip_immediate = srf_updates[i].flip_addr->flip_immediate; + + } if (update_type >= UPDATE_TYPE_MED) { for (j = 0; j < dc->res_pool->pipe_count; j++) { -- cgit From 524bed9a2b9f7d7f9aa5f62547b1faec2f9bab35 Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Tue, 7 Nov 2017 13:21:02 -0500 Subject: drm/amd/display: Remove dangling planes on dc commit state When disabling pipe splitting, we need to make sure we disable both planes used. This should be done for Linux as well. Signed-off-by: Leo (Sunpeng) Li Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 37 ++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 566ca82b5241..fe63f5894d43 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -619,6 +619,39 @@ fail: return false; } +static void disable_dangling_plane(struct dc *dc, struct dc_state *context) +{ + int i, j; + struct dc_state *dangling_context = dc_create_state(); + struct dc_state *current_ctx; + + if (dangling_context == NULL) + return; + + dc_resource_state_copy_construct(dc->current_state, dangling_context); + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct dc_stream_state *old_stream = + dc->current_state->res_ctx.pipe_ctx[i].stream; + bool should_disable = true; + + for (j = 0; j < context->stream_count; j++) { + if (old_stream == context->streams[j]) { + should_disable = false; + break; + } + } + if (should_disable && old_stream) { + dc_rem_all_planes_for_stream(dc, old_stream, dangling_context); + dc->hwss.apply_ctx_for_surface(dc, old_stream, 0, dangling_context); + } + } + + current_ctx = dc->current_state; + dc->current_state = dangling_context; + dc_release_state(current_ctx); +} + /******************************************************************************* * Public functions ******************************************************************************/ @@ -801,6 +834,8 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c int i, j, k, l; struct dc_stream_state *dc_streams[MAX_STREAMS] = {0}; + disable_dangling_plane(dc, context); + for (i = 0; i < context->stream_count; i++) dc_streams[i] = context->streams[i]; @@ -830,8 +865,6 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c } } - - CONN_MSG_MODE(sink->link, "{%dx%d, %dx%d@%dKhz}", context->streams[i]->timing.h_addressable, context->streams[i]->timing.v_addressable, -- cgit From 82e9781053c8a6aa3515aea3ade76546afb4c082 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 26 Oct 2017 11:47:42 +0530 Subject: drm/amd/display: Fix formatting for null pointer dereference fix Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index de04b95e103a..b00a6040a697 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -288,7 +288,7 @@ bool dc_stream_set_cursor_position( pos_cpy.enable = false; - if (ipp !=NULL && ipp->funcs->ipp_cursor_set_position != NULL) + if (ipp != NULL && ipp->funcs->ipp_cursor_set_position != NULL) ipp->funcs->ipp_cursor_set_position(ipp, &pos_cpy, ¶m); if (mi != NULL && mi->funcs->set_cursor_position != NULL) -- cgit From 00f713c6dc657397ba37b42d7f6887f526c730c6 Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Wed, 1 Nov 2017 15:43:47 -0400 Subject: drm/amd/display: fix MST link training fail division by 0 When link training fail in MST case, we will divide by 0 when calculating avg_time_slots_per_mtp, so we cannot proceed. Signed-off-by: Eric Yang Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index e70612eaf257..0602610489d7 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -2318,9 +2318,11 @@ void core_link_enable_stream( /* Abort stream enable *unless* the failure was due to * DP link training - some DP monitors will recover and - * show the stream anyway. + * show the stream anyway. But MST displays can't proceed + * without link training. */ - if (status != DC_FAIL_DP_LINK_TRAINING) { + if (status != DC_FAIL_DP_LINK_TRAINING || + pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { BREAK_TO_DEBUGGER(); return; } -- cgit